Skip to content

Commit f6ca3f3

Browse files
committed
refactor API to use xml serializable
1 parent c91f639 commit f6ca3f3

29 files changed

+826
-420
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,4 @@ doc/api/
2323
# Generated files
2424
*.chopper.dart
2525
*.freezed.dart
26+
*.g.dart

.vscode/dart.code-snippets

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
{
2+
// Place your aha-dart workspace snippets here. Each snippet is defined under a snippet name and has a scope, prefix, body and
3+
// description. Add comma separated ids of the languages where the snippet is applicable in the scope field. If scope
4+
// is left empty or omitted, the snippet gets applied to all languages. The prefix is what is
5+
// used to trigger the snippet and the body will be expanded and inserted. Possible variables are:
6+
// $1, $2 for tab stops, $0 for the final cursor position, and ${1:label}, ${2:another} for placeholders.
7+
// Placeholders with the same ids are connected.
8+
// Example:
9+
// "Print to console": {
10+
// "scope": "javascript,typescript",
11+
// "prefix": "log",
12+
// "body": [
13+
// "console.log('$1');",
14+
// "$2"
15+
// ],
16+
// "description": "Log output to console"
17+
// }
18+
"Create XML serializable with root element": {
19+
"scope": "dart",
20+
"prefix": [
21+
"xml-root",
22+
"xml-serializable-root"
23+
],
24+
"body": [
25+
"import 'package:meta/meta.dart';",
26+
"import 'package:xml/xml.dart';",
27+
"import 'package:xml_annotation/xml_annotation.dart' as xml;",
28+
"",
29+
"part '$TM_FILENAME_BASE.g.dart';",
30+
"",
31+
"const ${1/(.)(.*)/${1:/downcase}$2/}ElementName = '$2';",
32+
"",
33+
"@xml.XmlSerializable(createMixin: true)",
34+
"@xml.XmlRootElement(name: ${1/(.)(.*)/${1:/downcase}$2/}ElementName)",
35+
"@immutable",
36+
"class ${1/(.)(.*)/${1:/upcase}$2/} extends XmlConvertible<${1/(.)(.*)/${1:/upcase}$2/}>",
37+
" with _$${1/(.)(.*)/${1:/upcase}$2/}XmlSerializableMixin, _${1/(.)(.*)/${1:/upcase}$2/}Equality {",
38+
"",
39+
"const ${1/(.)(.*)/${1:/upcase}$2/}();",
40+
"",
41+
"factory ${1/(.)(.*)/${1:/upcase}$2/}.fromXmlElement(XmlElement element) =>",
42+
" _$${1/(.)(.*)/${1:/upcase}$2/}FromXmlElement(element);",
43+
"}",
44+
"",
45+
"mixin _${1/(.)(.*)/${1:/upcase}$2/}Equality on XmlConvertible$0<${1/(.)(.*)/${1:/upcase}$2/}> {",
46+
" @override",
47+
" List<Object?> get props => [];",
48+
"}"
49+
],
50+
"description": "Creates a XML serializable and convertible class",
51+
},
52+
"Create XML serializable": {
53+
"scope": "dart",
54+
"prefix": [
55+
"xml",
56+
"xml-serializable"
57+
],
58+
"body": [
59+
"import 'package:meta/meta.dart';",
60+
"import 'package:xml/xml.dart';",
61+
"import 'package:xml_annotation/xml_annotation.dart' as xml;",
62+
"",
63+
"part '$TM_FILENAME_BASE.g.dart';",
64+
"",
65+
"@xml.XmlSerializable(createMixin: true)",
66+
"@immutable",
67+
"class ${1/(.)(.*)/${1:/upcase}$2/} extends XmlEquatable<${1/(.)(.*)/${1:/upcase}$2/}>",
68+
" with _$${1/(.)(.*)/${1:/upcase}$2/}XmlSerializableMixin, _${1/(.)(.*)/${1:/upcase}$2/}Equality {",
69+
"",
70+
"const ${1/(.)(.*)/${1:/upcase}$2/}();",
71+
"",
72+
"factory ${1/(.)(.*)/${1:/upcase}$2/}.fromXmlElement(XmlElement element) =>",
73+
" _$${1/(.)(.*)/${1:/upcase}$2/}FromXmlElement(element);",
74+
"}",
75+
"",
76+
"mixin _${1/(.)(.*)/${1:/upcase}$2/}Equality on XmlEquatable$0<${1/(.)(.*)/${1:/upcase}$2/}> {",
77+
" @override",
78+
" List<Object?> get props => [];",
79+
"}"
80+
],
81+
"description": "Creates a XML serializable and equatable class",
82+
}
83+
}

.vscode/settings.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"cSpell.words": [
3+
"absenk",
4+
"celsius",
5+
"komfort"
6+
]
7+
}

analysis_options.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ include: package:dart_test_tools/analysis_options_package.yaml
22

33
analyzer:
44
exclude:
5+
- "**/*.g.dart"
56
- "**/*.chopper.dart"
67
- "**/*.freezed.dart"
78

example/aha_client_example.dart

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,13 @@ Future<void> main() async {
6565
print(response.statusCode);
6666
// ignore: avoid_print
6767
print('');
68-
// ignore: avoid_print
69-
print(response.body);
68+
if (response.isSuccessful) {
69+
// ignore: avoid_print
70+
print(response.body);
71+
} else {
72+
// ignore: avoid_print
73+
print(response.error);
74+
}
7075

7176
await client.dispose();
7277
}

lib/src/api/aha/aha_service.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import 'package:chopper/chopper.dart';
2-
import 'package:xml/xml.dart';
32

3+
import 'models/device_list.dart';
44
import 'models/optional.dart';
55
import 'models/switch_status.dart';
66

@@ -15,7 +15,7 @@ abstract class AhaService extends ChopperService {
1515
// all devices
1616

1717
@Get(path: '$_baseUrl=getdevicelistinfos')
18-
Future<Response<XmlDocument>> getDeviceListInfos();
18+
Future<Response<DeviceList>> getDeviceListInfos();
1919

2020
// switches
2121

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import 'package:meta/meta.dart';
2+
import 'package:xml/xml.dart';
3+
import 'package:xml_annotation/xml_annotation.dart' as xml;
4+
5+
import '../../util/xml_convertible.dart';
6+
7+
part 'battery_percentage.g.dart';
8+
9+
@xml.XmlSerializable(createMixin: true)
10+
@immutable
11+
class BatteryPercentage extends XmlEquatable<BatteryPercentage>
12+
with _$BatteryPercentageXmlSerializableMixin, _BatteryPercentageEquality {
13+
@xml.XmlText()
14+
final int rawValue;
15+
16+
const BatteryPercentage({
17+
required this.rawValue,
18+
}) : assert(
19+
rawValue >= 0 && rawValue <= 100,
20+
'rawValue must be in range [0, 100]',
21+
);
22+
23+
factory BatteryPercentage.fromXmlElement(XmlElement element) =>
24+
_$BatteryPercentageFromXmlElement(element);
25+
26+
double getValue() => rawValue / 100;
27+
28+
@override
29+
String toString() => '$rawValue%';
30+
}
31+
32+
mixin _BatteryPercentageEquality on XmlEquatable<BatteryPercentage> {
33+
@override
34+
List<Object?> get props => [self.getValue()];
35+
}

lib/src/api/aha/models/device.dart

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
import 'package:freezed_annotation/freezed_annotation.dart';
2+
import 'package:xml/xml.dart';
3+
import 'package:xml_annotation/xml_annotation.dart' as xml;
4+
5+
import '../../util/xml_convertible.dart';
6+
import 'battery_percentage.dart';
7+
import 'hkr.dart';
8+
import 'temperature.dart';
9+
10+
part 'device.g.dart';
11+
12+
@xml.XmlSerializable(createMixin: true)
13+
@immutable
14+
class Device extends XmlEquatable<Device>
15+
with _$DeviceXmlSerializableMixin, _DeviceEquality {
16+
@xml.XmlAttribute()
17+
final int id;
18+
19+
@xml.XmlAttribute()
20+
final String identifier;
21+
22+
@xml.XmlAttribute(name: 'functionbitmask')
23+
final int functionBitMask;
24+
25+
@xml.XmlAttribute(name: 'fwversion')
26+
final String fwVersion;
27+
28+
@xml.XmlAttribute()
29+
final String manufacturer;
30+
31+
@xml.XmlAttribute(name: 'productname')
32+
final String productName;
33+
34+
@xml.XmlElement()
35+
final bool present;
36+
37+
@xml.XmlElement(name: 'txbusy')
38+
final bool txBusy;
39+
40+
@xml.XmlElement()
41+
final String name;
42+
43+
@xml.XmlElement()
44+
final BatteryPercentage battery;
45+
46+
@xml.XmlElement(name: 'batterylow')
47+
final bool batteryLow;
48+
49+
@xml.XmlElement(name: 'temperature')
50+
final Temperature temperature;
51+
52+
@xml.XmlElement(name: 'hkr')
53+
final Hkr hkr;
54+
55+
const Device({
56+
required this.id,
57+
required this.identifier,
58+
required this.functionBitMask,
59+
required this.fwVersion,
60+
required this.manufacturer,
61+
required this.productName,
62+
required this.present,
63+
required this.txBusy,
64+
required this.name,
65+
required this.battery,
66+
required this.batteryLow,
67+
required this.temperature,
68+
required this.hkr,
69+
});
70+
71+
factory Device.fromXmlElement(XmlElement element) =>
72+
_$DeviceFromXmlElement(element);
73+
}
74+
75+
mixin _DeviceEquality on XmlEquatable<Device> {
76+
@override
77+
List<Object?> get props => [
78+
self.id,
79+
self.identifier,
80+
self.functionBitMask,
81+
self.fwVersion,
82+
self.manufacturer,
83+
self.productName,
84+
self.present,
85+
self.txBusy,
86+
self.name,
87+
self.battery,
88+
self.batteryLow,
89+
self.temperature,
90+
self.hkr,
91+
];
92+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import 'package:meta/meta.dart';
2+
import 'package:xml/xml.dart';
3+
import 'package:xml_annotation/xml_annotation.dart' as xml;
4+
5+
import '../../util/xml_convertible.dart';
6+
import 'device.dart';
7+
8+
part 'device_list.g.dart';
9+
10+
const deviceListElementName = 'devicelist';
11+
12+
@xml.XmlSerializable(createMixin: true)
13+
@xml.XmlRootElement(name: deviceListElementName)
14+
@immutable
15+
class DeviceList extends XmlConvertible<DeviceList>
16+
with _$DeviceListXmlSerializableMixin, _DeviceListEquality {
17+
@xml.XmlAttribute()
18+
final int version;
19+
20+
@xml.XmlAttribute(name: 'fwversion')
21+
final String fwVersion;
22+
23+
@xml.XmlElement(name: 'device')
24+
final List<Device>? devices;
25+
26+
const DeviceList({
27+
required this.version,
28+
required this.fwVersion,
29+
required this.devices,
30+
}) : assert(
31+
version == 1,
32+
'Only the$deviceListElementName format version 1 is supported',
33+
);
34+
35+
factory DeviceList.fromXmlElement(XmlElement element) =>
36+
_$DeviceListFromXmlElement(element);
37+
}
38+
39+
mixin _DeviceListEquality on XmlConvertible<DeviceList> {
40+
@override
41+
List<Object?> get props => [self.version, self.fwVersion, self.devices];
42+
}

0 commit comments

Comments
 (0)