eclipse-smarthome-bluetooth-binding
eclipse-smarthome-bluetooth-binding copied to clipboard
Add support for Smart Radiator Thermostat - comet-blue-eurotronic
I'm testing the binding of https://community.openhab.org/t/comet-blue-eurotronic/36590 Now I can bind.
How can I create the XML files? Where to put? How to add an extra coefficent to each radiator (to calculate the calories) How to elaborate data. (to calculate calories and for billing purpose)
Hi @matteopedani , it looks similar to eQ-3 radiator thermostat, is it the same device?
I don't think so. May be. I don't have eQ-3 They use the similar hardware but they program in a different way. They have different ID manufactor I can expose my raspberry and the 7 thermostat to internet if you like to play send me your ssh pubblic id
@matteopedani It can be same device https://translate.google.com/translate?sl=auto&tl=en&js=y&prev=_t&hl=en&ie=UTF-8&u=http%3A%2F%2Ftorsten-traenkner.de%2Fwissen%2Fsmarthome%2Fheizung.php&edit-text=
Looks like it is not the same device. Here is a python project with some good details about its characteristics: https://github.com/im-0/cometblue/blob/master/cometblue/device.py
What you will need to do is:
-
Create GATT xml files similar to this (please do not think it is easy to accomplish):
- https://github.com/sputnikdev/bluetooth-gatt-parser/blob/396bdee4c6ec4c0656a31b7f12b9952b7bb928de/src/main/resources/gatt/service/com.eq-3.service.radiator_thermostat.xml
- https://github.com/sputnikdev/bluetooth-gatt-parser/blob/396bdee4c6ec4c0656a31b7f12b9952b7bb928de/src/main/resources/gatt/characteristic/com.eq-3.characteristic.state_and_control.xml
-
Install a new build of the Bluetooth binding from here (you will need to uninstall the binding from MarketPlace first): https://oss.sonatype.org/content/repositories/snapshots/org/sputnikdev/org.eclipse.smarthome.binding.bluetooth/1.1-SNAPSHOT/org.eclipse.smarthome.binding.bluetooth-1.1-20180114.100602-6.jar
It will give you a new experimental feature that can discover all characteristics (including "unknown" characteristics). To enable this feature:
- Create a folder on your file system that is accessible by "openhab" user, something like that:
/home/pi/.bluetooth_smart
That folder should contain two subfolders:
- characteristic
- service
These two folders should contain your xml files from the point n1, e.g. "characteristic" folder contains XML file for characteristics and "service" contains XML files for your services. Make sure that file permissions are set correctly so that "openhab" user can read them.
Specify that folder here:
I just want to warn you that this process is not easy, you should have some background in bluetooth technology (GATT) and in software engineering. So please do not expect any magic.
@bademux
Yes, Is this device In this page I linked for reference https://community.openhab.org/t/comet-blue-eurotronic/36590
@vkolotov I will try to follow your instructions to create GATT xml files.
To find the right ID Can I use ? sudo bluetoothctl
############## follow the full output of bluetoothctl
[termosifone cucina piano terra]# devices
Device D0:B5:C2:FB:BE:B3 termosifone bagno blu primo piano
Device D0:B5:C2:FB:BE:C3 termosifone 5
Device D0:B5:C2:FB:B9:40 termosifone 1
Device D0:B5:C2:FB:AF:64 termosifone 2
Device D0:B5:C2:F1:73:2E termosifone 3 primo piano
Device D0:B5:C2:FB:B9:3A termosifone 4
Device D0:B5:C2:F1:72:4D termosifone cucina piano terra
[termosifone cucina piano terra]# connect D0:B5:C2:F1:72:4D
Attempting to connect to D0:B5:C2:F1:72:4D
Connection successful
[termosifone cucina piano terra]# info
Device D0:B5:C2:F1:72:4D
Name: Comet Blue
Alias: termosifone cucina piano terra
Paired: yes
Trusted: no
Blocked: no
Connected: yes
LegacyPairing: no
UUID: Generic Access Profile (00001800-0000-1000-8000-00805f9b34fb)
UUID: Generic Attribute Profile (00001801-0000-1000-8000-00805f9b34fb)
UUID: Device Information (0000180a-0000-1000-8000-00805f9b34fb)
UUID: Vendor specific (47e9ee00-47e9-11e4-8939-164230d1df67)
ManufacturerData Key: 0xffff
ManufacturerData Value:
ff 00 01 ff ff ff ......
ManufacturerData Key: 0x2229
ManufacturerData Value:
20 00 00 ff 69 88 ...i.
ManufacturerData Key: 0x2f26
ManufacturerData Value:
23 01 00 ff af 69 #....i
RSSI: -82
TxPower: 0
[termosifone cucina piano terra]# list-attributes
Primary Service
/org/bluez/hci0/dev_D0_B5_C2_F1_72_4D/service001b
47e9ee00-47e9-11e4-8939-164230d1df67
Vendor specific
Characteristic
/org/bluez/hci0/dev_D0_B5_C2_F1_72_4D/service001b/char0046
47e9ee30-47e9-11e4-8939-164230d1df67
Vendor specific
Characteristic
/org/bluez/hci0/dev_D0_B5_C2_F1_72_4D/service001b/char0044
47e9ee2e-47e9-11e4-8939-164230d1df67
Vendor specific
Characteristic
/org/bluez/hci0/dev_D0_B5_C2_F1_72_4D/service001b/char0042
47e9ee2d-47e9-11e4-8939-164230d1df67
Vendor specific
Characteristic
/org/bluez/hci0/dev_D0_B5_C2_F1_72_4D/service001b/char0040
47e9ee2c-47e9-11e4-8939-164230d1df67
Vendor specific
Characteristic
/org/bluez/hci0/dev_D0_B5_C2_F1_72_4D/service001b/char003e
47e9ee2b-47e9-11e4-8939-164230d1df67
Vendor specific
Characteristic
/org/bluez/hci0/dev_D0_B5_C2_F1_72_4D/service001b/char003c
47e9ee2a-47e9-11e4-8939-164230d1df67
Vendor specific
Characteristic
/org/bluez/hci0/dev_D0_B5_C2_F1_72_4D/service001b/char003a
47e9ee27-47e9-11e4-8939-164230d1df67
Vendor specific
Characteristic
/org/bluez/hci0/dev_D0_B5_C2_F1_72_4D/service001b/char0038
47e9ee26-47e9-11e4-8939-164230d1df67
Vendor specific
Characteristic
/org/bluez/hci0/dev_D0_B5_C2_F1_72_4D/service001b/char0036
47e9ee25-47e9-11e4-8939-164230d1df67
Vendor specific
Characteristic
/org/bluez/hci0/dev_D0_B5_C2_F1_72_4D/service001b/char0034
47e9ee24-47e9-11e4-8939-164230d1df67
Vendor specific
Characteristic
/org/bluez/hci0/dev_D0_B5_C2_F1_72_4D/service001b/char0032
47e9ee23-47e9-11e4-8939-164230d1df67
Vendor specific
Characteristic
/org/bluez/hci0/dev_D0_B5_C2_F1_72_4D/service001b/char0030
47e9ee22-47e9-11e4-8939-164230d1df67
Vendor specific
Characteristic
/org/bluez/hci0/dev_D0_B5_C2_F1_72_4D/service001b/char002e
47e9ee21-47e9-11e4-8939-164230d1df67
Vendor specific
Characteristic
/org/bluez/hci0/dev_D0_B5_C2_F1_72_4D/service001b/char002c
47e9ee20-47e9-11e4-8939-164230d1df67
Vendor specific
Characteristic
/org/bluez/hci0/dev_D0_B5_C2_F1_72_4D/service001b/char002a
47e9ee16-47e9-11e4-8939-164230d1df67
Vendor specific
Characteristic
/org/bluez/hci0/dev_D0_B5_C2_F1_72_4D/service001b/char0028
47e9ee15-47e9-11e4-8939-164230d1df67
Vendor specific
Characteristic
/org/bluez/hci0/dev_D0_B5_C2_F1_72_4D/service001b/char0026
47e9ee14-47e9-11e4-8939-164230d1df67
Vendor specific
Characteristic
/org/bluez/hci0/dev_D0_B5_C2_F1_72_4D/service001b/char0024
47e9ee13-47e9-11e4-8939-164230d1df67
Vendor specific
Characteristic
/org/bluez/hci0/dev_D0_B5_C2_F1_72_4D/service001b/char0022
47e9ee12-47e9-11e4-8939-164230d1df67
Vendor specific
Characteristic
/org/bluez/hci0/dev_D0_B5_C2_F1_72_4D/service001b/char0020
47e9ee11-47e9-11e4-8939-164230d1df67
Vendor specific
Characteristic
/org/bluez/hci0/dev_D0_B5_C2_F1_72_4D/service001b/char001e
47e9ee10-47e9-11e4-8939-164230d1df67
Vendor specific
Characteristic
/org/bluez/hci0/dev_D0_B5_C2_F1_72_4D/service001b/char001c
47e9ee01-47e9-11e4-8939-164230d1df67
Vendor specific
Primary Service
/org/bluez/hci0/dev_D0_B5_C2_F1_72_4D/service0010
0000180a-0000-1000-8000-00805f9b34fb
Device Information
Characteristic
/org/bluez/hci0/dev_D0_B5_C2_F1_72_4D/service0010/char0019
00002a29-0000-1000-8000-00805f9b34fb
Manufacturer Name String
Characteristic
/org/bluez/hci0/dev_D0_B5_C2_F1_72_4D/service0010/char0017
00002a28-0000-1000-8000-00805f9b34fb
Software Revision String
Characteristic
/org/bluez/hci0/dev_D0_B5_C2_F1_72_4D/service0010/char0015
00002a26-0000-1000-8000-00805f9b34fb
Firmware Revision String
Characteristic
/org/bluez/hci0/dev_D0_B5_C2_F1_72_4D/service0010/char0013
00002a24-0000-1000-8000-00805f9b34fb
Model Number String
Characteristic
/org/bluez/hci0/dev_D0_B5_C2_F1_72_4D/service0010/char0011
00002a23-0000-1000-8000-00805f9b34fb
System ID
Primary Service
/org/bluez/hci0/dev_D0_B5_C2_F1_72_4D/service000c
00001801-0000-1000-8000-00805f9b34fb
Generic Attribute Profile
Characteristic
/org/bluez/hci0/dev_D0_B5_C2_F1_72_4D/service000c/char000d
00002a05-0000-1000-8000-00805f9b34fb
Service Changed
Descriptor
/org/bluez/hci0/dev_D0_B5_C2_F1_72_4D/service000c/char000d/desc000f
00002902-0000-1000-8000-00805f9b34fb
Client Characteristic Configuration
hi @matteopedani, yes those "manufacturer specific" services and characteristics are those that you will need to create mapping for. Look at this project, if you can read python code, you will find what each characteristic can do: https://github.com/im-0/cometblue/blob/master/cometblue/device.py
@matteopedani, looks like these ones are the most interesting:
'datetime': {
'description': 'time and date',
'uuid': '47e9ee01-47e9-11e4-8939-164230d1df67',
'read_requires_pin': True,
'decode': _decode_datetime,
'encode': _encode_datetime,
},
'flags': {
'description': 'flags',
'uuid': '47e9ee2a-47e9-11e4-8939-164230d1df67',
'read_requires_pin': True,
'decode': _decode_flags,
},
'temperatures': {
'description': 'temperatures',
'uuid': '47e9ee2b-47e9-11e4-8939-164230d1df67',
'read_requires_pin': True,
'decode': _decode_temperatures,
'encode': _encode_temperatures,
},
'battery': {
'description': 'battery charge',
'uuid': '47e9ee2c-47e9-11e4-8939-164230d1df67',
'read_requires_pin': True,
'decode': _decode_battery,
},
'firmware_revision2': {
'description': 'firmware revision #2',
'uuid': '47e9ee2d-47e9-11e4-8939-164230d1df67',
'read_requires_pin': True,
'decode': str,
},
'lcd_timer': {
'description': 'LCD timer',
'uuid': '47e9ee2e-47e9-11e4-8939-164230d1df67',
'read_requires_pin': True,
'decode': _decode_lcd_timer,
'encode': _encode_lcd_timer,
},
'pin': {
'description': 'PIN',
'uuid': '47e9ee30-47e9-11e4-8939-164230d1df67',
'encode': _encode_pin,
},
Thank's I will work on these. Matteo
2018-01-16 11:42 GMT+01:00 Vlad Kolotov [email protected]:
@matteopedani https://github.com/matteopedani, looks like these ones are the most interesting:
'datetime': { 'description': 'time and date', 'uuid': '47e9ee01-47e9-11e4-8939-164230d1df67', 'read_requires_pin': True, 'decode': _decode_datetime, 'encode': _encode_datetime, },
'flags': { 'description': 'flags', 'uuid': '47e9ee2a-47e9-11e4-8939-164230d1df67', 'read_requires_pin': True, 'decode': _decode_flags, }, 'temperatures': { 'description': 'temperatures', 'uuid': '47e9ee2b-47e9-11e4-8939-164230d1df67', 'read_requires_pin': True, 'decode': _decode_temperatures, 'encode': _encode_temperatures, }, 'battery': { 'description': 'battery charge', 'uuid': '47e9ee2c-47e9-11e4-8939-164230d1df67', 'read_requires_pin': True, 'decode': _decode_battery, }, 'firmware_revision2': { 'description': 'firmware revision #2', 'uuid': '47e9ee2d-47e9-11e4-8939-164230d1df67', 'read_requires_pin': True, 'decode': str, }, 'lcd_timer': { 'description': 'LCD timer', 'uuid': '47e9ee2e-47e9-11e4-8939-164230d1df67', 'read_requires_pin': True, 'decode': _decode_lcd_timer, 'encode': _encode_lcd_timer, }, 'pin': { 'description': 'PIN', 'uuid': '47e9ee30-47e9-11e4-8939-164230d1df67', 'encode': _encode_pin, },
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/sputnikdev/eclipse-smarthome-bluetooth-binding/issues/14#issuecomment-357921554, or mute the thread https://github.com/notifications/unsubscribe-auth/ASiPBT7Z1oeB9jsVIDCt2L-Es3-O9Aztks5tLH0WgaJpZM4RfePM .
-- Matteo Pedani
www.pedani.it mobile +39 3343637690 phone +39 0699341466 phone +39 069415152
Hi, thanks @vkolotov for pointing me in this dirrection, I have only skimmed through the original discussion and completely missed the roadmap. I suggest using my fork of cometblue control utility, as I had further developed the encoding of status triplet. You can find my fork at https://github.com/xrucka/cometblue . @matteopedani - is there any way I can contribute on developing the specs?
Hi @xrucka, any contribution is greatly appreciated. Looks like you have some knowledge of GATT stuff, If so you could try to come up with GATT files as I mentioned above: https://github.com/sputnikdev/eclipse-smarthome-bluetooth-binding/issues/14#issuecomment-357909251
I'll be supporting you in this answering any questions you have.
Please note that this might not be possible to add support for this device through GATT XML files. Please see here: https://github.com/sputnikdev/eclipse-smarthome-bluetooth-binding/issues/13
In short, the eQ-3 device has API that does not follow GATT specification, to be more precise the data structures for its main characteristic are different for read, write and notify operations. That's why for the eQ-3 device we will have to develop a custom bluetooth binding.
Ok, thanks for the headsup; I should be able to look into it either on tomorrow or thursday evening. I'll get back to you guys once I manage to do something about it. As for odd data structures, I've not noticed anything special, except perhaps the status triplet, but I believe that it should be manageable with correct read/write order.
Hi @xrucka, thank you very much for your contribution for TinyB transport. Looking forward to merge it to the upstream.
In regards your thermostat, there is a good example of how to implement GATT spec files. Recently we have added support for a device that kind of follows GATT spec (however we are still having some issues with notifications, looks like Bluez is of old version or something). Here are those files and a unittest:
- https://github.com/sputnikdev/bluetooth-gatt-parser/blob/new-device-oregon-rar213hg/src/main/resources/gatt/characteristic/com.oregonscientific.characteristic.temperature_and_humidity.xml
- https://github.com/sputnikdev/bluetooth-gatt-parser/blob/new-device-oregon-rar213hg/src/main/resources/gatt/service/com.oregonscientific.service.temperature_and_humidity.xml
- https://github.com/sputnikdev/bluetooth-gatt-parser/blob/5aaa7a9b50d8cab671e5844d66764b23ac784b1a/src/test/java/org/sputnikdev/bluetooth/gattparser/GenericCharacteristicParserIntegrationTest.java#L133
It is not still merged to the upstream as I mentioned above we have some issues with notifications, but unittest shows that data structure can be easily parsed for the given characteristic.
I'm not sure If I have some time this weekend (it is a long weekend), but I'll try to help you to create specs for your device.
The most interesting part is here:
<Field name="Flags">
<Requirement>Mandatory</Requirement>
<Format>8bit</Format>
<BitField>
<Bit index="0" size="8" name="DataTypeFlag">
<Enumerations>
<Enumeration key="1" value="False" requires="C1"/> <!-- DATA_GENERAL_4_CH_TH_TYPE_0 -->
<Enumeration key="-126" value="True" requires="C2"/> <!-- DATA_GENERAL_4_CH_TH_TYPE_1 -->
</Enumerations>
</Bit>
</BitField>
</Field>
This field in the characteristic defines overall structure of the characteristic. Basically it says if the very first byte is equal to 1 or -126, then C1 and C2 flags set respectively. This controls inclusion/exclusion of the rest of the fields, for example:
<!-- DATA_GENERAL_4_CH_TH_TYPE_0 -->
<Field name="Base temp">
<Requirement>C1</Requirement>
<Format>uint16</Format>
<DecimalExponent>-1</DecimalExponent>
</Field>
and
<!-- DATA_GENERAL_4_CH_TH_TYPE_1 -->
<Field name="Sensor 2 humidity min">
<Requirement>C2</Requirement>
<Format>uint8</Format>
</Field>
Notice <Requirement>C1/C2</Requirement> tag.
BTW, it does not mean that we have to do this all the time. This is required only for some characteristics that have "dynamic" data structure. If it is flat/fixed, then just a list of fields solves the problem.
Huray, I've finally managed to figure what was preventing my specs from working. If anyone reads this - so far, the short form of service and characteristics uuid has to be in upper case, as the libraries use internally string matching, instead of comparing numeric value.
Anyway, the device - at least at some points - uses offseted values. For example, year is represented with uint8 value, offseted by 1999. I've been following the field descriptions (http://schemas.bluetooth.org/Documents/formats.xsd), yet they do not explicitly provide a way to offset the value. Can you please confirm (and perhaps suggest an alternative), @vkolotov ? The only idea I got so far is to enumerate all 256 years, yet this sounds too hacked, even for me...
Thanks for your update @xrucka.
so far, the short form of service and characteristics uuid has to be in upper case, as the libraries use internally string matching, instead of comparing numeric value.
Yeah, I think it can be improved in the gatt parser by comparing "ignore case".
I think I remember seeing this in the eq-3 thermostat device as well. As you have said, there is not any easy way to fix that by using standard GATT spec. But you could extend the gatt parser with a new tag, e.g. like "DecimalExponent" https://github.com/sputnikdev/bluetooth-gatt-parser/blob/d488bc07404cd5ddc61b1c84087138cc9435f432/src/main/resources/gatt/characteristic/com.xiaomi.bluetooth.characteristic.advertised_data.xml#L31 and add some basic logic like here: https://github.com/sputnikdev/bluetooth-gatt-parser/blob/d488bc07404cd5ddc61b1c84087138cc9435f432/src/main/java/org/sputnikdev/bluetooth/gattparser/FieldHolder.java#L373
It must be quite easy to implement, let me know what you think?
I guess that extending the specs might be the easiest way to do, especially if there are multiple devices holding the same issue. I'll do the patches and see what happens (I need to recall extending xsd's though).
Furthermore, is there a way to specify order of read/write operations in the bluetooth binding? The issue is, that before reading any other attribute, a "pin" has to be written to the device, otherwise all reads fail.
Furthermore, is there a way to specify order of read/write operations in the bluetooth binding? The issue is, that before reading any other attribute, a "pin" has to be written to the device, otherwise all reads fail.
Damn... too bad. There is not any authentication mechanism supported by binding yet...
Is it a just "magic" number that must be written to a specific characteristic?
I was thinking to tweak the binding to allow specifying a magic number in the device settings... Xiaomi devices have the same issue, however they advertise all necessary readings, e.g. temperature, humidity etc so no need to connect to them actually.
Another way is to create a new custom bluetooth binding (by using public bluetooth API from the core binding) and publish it in the Eclipse Marketplace.
Just to sum up options we have in my mind to resolve your issue with the "magic number":
- Implement a new bluetooth binding which uses BluetoothManager API. I've been working on making the BluetoothManager API to be usable by multiple clients, I believe it is more or less ready. The new binding can be published in the Eclipse Marketplace.
- Change the existing bluetooth binding to add support for setting "magic number" (device thing parameters) before making any communications with target device. This might not be a bad option, the new "thing" parameter may look like:
- A dropdownbox "Characteristic UUID" (that one can be automatically prepopulated)
- A free-text field "Characteristic value" There is an example of how that dropdownbox might be populated: https://github.com/sputnikdev/eclipse-smarthome-bluetooth-binding/blob/master/src/main/java/org/sputnikdev/esh/binding/bluetooth/internal/BluetoothAdaptersConfigOptionProvider.java
- Extend the existing binding with a new thing-type "bluetooth-cometblue..." and a corresponding ThingHandler and ThingHandlerFactory. Implement authentication logic in the new ThingHandler.
I guess, this problem is a generic one - authentication. Ideally the binding should provide some mechanisms (settings or something...) to allow users to perform authentication.
Let me know what you think @xrucka.
Hi, I'd rather go with # 2. I believe that both # 1 and # 3 would (eventualy) lead to fatware explosion or lack of support. The automated dropdown magick suggestion can parse characteristics names for magic words (i.e. PIN). I'm not familiar with the Xiaomi device you've mentioned, but cometblue uses the same characteristic for both unlocking & setting the pin (1st, resp. 2nd write). I'll try to come up with some code for it during the next week and get back to you.
Hi, I have finally managed to get some time into this again. I've tested the 1.3-SNAPSHOT of bluetooth-manager with authentication and explicit UUID setting and hex byte array - the device now connects and authenticates successfuly. I'll get back once I manage to complete the gatt files.
In the mean time, is there a way to create a "combined channel"? Usecase: the device uses custom characteristic format to provide time setting (year, month, day, hour, minute). Similar to this, there are timeslots for heating provided in other characteristics.
Hi @xrucka,
Hi, I have finally managed to get some time into this again. I've tested the 1.3-SNAPSHOT of bluetooth-manager with authentication and explicit UUID setting and hex byte array - the device now connects and authenticates successfuly.
Good to know that this works for you. I've spent some significant effort to make it working, it turned out not very easy to do, lots of nuances, especially multithreading etc.
In the mean time, is there a way to create a "combined channel"? Usecase: the device uses custom characteristic format to provide time setting (year, month, day, hour, minute). Similar to this, there are timeslots for heating provided in other characteristics.
Can you please elaborate this more? Are you saying that a single characteristics is used to represent several data points?
Hi, ok, I'll elaborate a bit more on this. The device is programmable radiator valve - you can configure up to 4 presets for each day of the week - either as primary heading phase (i.e. day temperature) or secondary heating phase (i.e. night temperature). This, as a result means, that the device needs to keep track on current time - and for this purpose, it uses internal clock. This internal clock is accessible through characteristic 47e9ee01, which provides 5 bytes of data, representing minute, hour, day, month, year (1st to 5th byte respectively )
The current characteristic description I wrote mirrors the structure of gatt date_time characteristic
And as a result, it appears as 5 distinct channels - Year, Month, Day, Hour, Minute.
Hmm... got yet another issue implementing the program settings. The program is given as 8 8-bit fields, described by: <start_time1><end_time1><start_time2><end_time2><start_time3><end_time3><start_time4><end_time4>.
Where time is represented as 8-bit value in minutes, with 10 minute step. However, as a result, the heating program from from 7:00 .. 22:00 would be than given as minutes 420 .. 1320. This is rather ugly.
As I see it, there are 3 possible ways to go:
- Further extend the GATT XML specs with capability for printf/strftime-like (bidirectional) formating of the value given. This might be somewhat ugly to implement, however can pay off in future, as it might allow for support for devices that do not exactly fit GATT standard.
- Enumerate all 144 values with time they represent.
- Find a way to represent this as hours, using (integer) multiplier and binary/decimal exponent.
@vkolotov what would you suggest?
Hi @xrucka,
Re the program issue: I believe this issue consists of two:
- Datatype representation in Java (Optional). I agree this might not be very elegant to represent start/end time as minutes (from the beginning of day?), therefore I would suggest to pick a proper java type to do so, e.g. something from Java8, like Duration
- Parsing into/from that datatype. We will probably need to extend FieldHolder to allow users to set Duration. We could possibly use existing GATT mechanisms to construct Duration from 8bit number, e.g. DecimalExponent (-1).
Re the "combined" fields: I'm actually working on it at the moment, the idea is to come up with "high level" data types composite field holders that consist of smaller types. In the GATT specification those fields are defined as references, e.g. <Reference>
org.bluetooth.characteristic.exact_time_256</Reference>
: here
Your example of the date is perfect. There is also a good example - colour picker.
Here is a test that demonstrates composite fields: https://github.com/sputnikdev/bluetooth-gatt-parser/blob/c58d3524170a5695771873877cc6008275406aa2/src/test/java/org/sputnikdev/bluetooth/gattparser/GenericCharacteristicParserIntegrationTest.java#L126
"Exact Time 256" is the composite field that is defined in GATT spec.
Effectively users will be able to set data by using both ways: low level fields (primitive) and high level field (composite field). I think it perfectly matches the standard GATT spec approach.
Let me know what you think.
We could possibly use existing GATT mechanisms to construct Duration from 8bit number, e.g. DecimalExponent (-1).
Not sure how do you intend to accomplish this. Do you mean using the start time as the integer part and end time as the decimal one?
I believe that Reference mechanism fits better - as long as the References are nested. I can imagine something like:
<Field name="Monday Primary Heating Program 1"> <Reference>org.eurotronic.cometblue.program_duration</Reference> </Field> <Field name="Monday Primary Heating Program 2"> <Reference>org.eurotronic.cometblue.program_duration</Reference> </Field> <Field name="Monday Primary Heating Program 3"> <Reference>org.eurotronic.cometblue.program_duration</Reference> </Field> <Field name="Monday Primary Heating Program 4"> <Reference>org.eurotronic.cometblue.program_duration</Reference> </Field>
with org.eurotronic.cometblue.program_duration.xml as: <Field name="Start"> <Format>uint8</Format> <Unit>org.bluetooth.unit.time.minute</Unit> </Field> <Field name="End"> <Format>uint8</Format> <Unit>org.bluetooth.unit.time.minute</Unit> </Field>
I'm not sure though that duration alone is enough - I was not able to find out whether it holds start time as well as the duration - I'm afraid that both the start time + duration would have to be maintained.
This, however, means there would have to be some kind of semantics parsed out from the characteristic specification, perhaps based on characteristic name?
Hi @xrucka,
I've been playing with it a bit. Here is what I think:
Composite fields are definitely nice to have to implement "program"-like fields (scheduling), e.g. like you've mentioned "program_duration". Otherwise we can end up with a loooong list of primitive fields, e.g. "Monday Primary Heating Program 1 start", Monday Primary Heating Program 1 end, Tuesday Primary Heating Program 2 start etc... which would not be very usable.
However... It might not be critical/required just for now. If you think about it in general, OpenHab is a platform that provides all sorts of scheduling, so we probably do not actually need to provide configurable "programs" at all... If we have a mechanism to star/stop heating and set temperature, then this should be sufficient. I would be focusing on providing basic controls for now rather than implementing something complex that potentially won't be usable/in use.
Furthermore, even of we had a mechanism to define "programs", how would we implement this on OpenHab UI? AFAIK OH does not provide this sort of UI controls.
Another question/issue is "transactioning". Does your thermostat provide a separate characteristic per program/ per day? If it is per day, then there is another layer of complexity. If user wants to edit only "Monday program 1 start" field, then we have to gather all other program values, combine them together and send it to the device. This raises more questions like "what if we don't have other values"? Likewise, if we had "characteristic per program" data structure, then it should not be too difficult.
If we wanted to implement this on OH UI, we could potentially just use a textual channel. We could come up with a format for this, e.g.
Monday: [8:10-12:40; 18:00-21.30; 23:00-23:30] Tuesday: [8.10-12.40; 18:00-21.30]
This could potentially resolve the "transactioning" issue if each of the channel (Monday, Tuesday etc) belongs to a specific characteristic.
Re java "Duration": as far as know, this class represents quantity or amount of time in terms of seconds and nanoseconds. We don't have to use it though, I thought it might be a bit more convenient for users to define the "start" and "stop" fields by using Duration rather than minutes (Integer).
What do you think?
Ok, I was able to get some time to work on this. It's still work in progress, however can already do some good. Comments wellcomed.
Requires pullrequests #54 and bluetooth-gatt-parser#7
@vkolotov - Following the discussion on #67 -- If I understand that correctly, do you expect to use control points instead of arbitrary characteristic writes? Or was it more of "best practices" idea?
I'm currently struggling with the need to update field in characteristic (sending the whole characteristic to device is OK), but the 1.9.5 version of bluetooth-gatt-parser refuses to validate the write request. I didn't have time to look into it deeper yet, but if this is such a case, it would explain the issues.
Example of such a characteristic; havinig similar problem with another, yet unpublished, characteristic holds a set of boolean values, some of them are contacts, some are switches.
EDIT: 1.9.2->1.9.5