When integrating my electric meter via the serial binding to openhab I recognized that the number of data bits, stop bits and parity are hard-coded in the source code. This was the starting point for me to start a refactoring on the binding and to improve it.
This is what I have done so far:
- Message boundary detection: Instead of using the absence of available serial data as indicator for message boundaries a regular expression is used now to extract messages from the received data stream.
- Separation of item and binding configuration: Individual parameters per port are now defined in openhab.cfg (data bits, stop bits, parity, baud rate and port name) and item individual ones (regular expression for extracting item value from received message) in the item file. Both are linked via a port id which is part of the item and the port definition.
- Reconnecting: In case an error occurs when accessing the serial device the port is closed. Periodic attempts are performed to open the port after read or write failure. That is, when the USB plug is pulled out and inserted again no openhab restart is necessary.
Currently my item definitions look like this making use of the port id electricmeter
Number Strom_Zaehlerstand "Zählerstand [%.0f kWh]" { serial="portId=electricmeter,regex=.*1-0:1\\.8\\.0\\*255\\(([0-9]{8}\\.[0-9]{7}).*" }
Number Stromverbrauch_Aktuell_Gesamt "Gesamt [%.0f W]" { serial="portId=electricmeter,regex=.*1-0:1\\.7\\.255\\*255\\(([0-9]{6}\\.[0-9]{2}).*" }
Number Stromverbrauch_Aktuell_Phase1 "Phase1 [%.0f W]" { serial="portId=electricmeter,regex=.*1-0:21\\.7\\.255\\*255\\(([0-9]{6}\\.[0-9]{2}).*" }
Number Stromverbrauch_Aktuell_Phase2 "Phase2 [%.0f W]" { serial="portId=electricmeter,regex=.*1-0:41\\.7\\.255\\*255\\(([0-9]{6}\\.[0-9]{2}).*" }
Number Stromverbrauch_Aktuell_Phase3 "Phase3 [%.0f W]" { serial="portId=electricmeter,regex=.*1-0:61\\.7\\.255\\*255\\(([0-9]{6}\\.[0-9]{2}).*" }
which is defined in openhab.cfg
serial:electricmeter.portName=/dev/smartmeter
serial:electricmeter.baudRate=9600
serial:electricmeter.databits=7
serial:electricmeter.stopbits=1
serial:electricmeter.parity=even
serial:electricmeter.messagePattern=/.*!\r\n
serial:electricmeter.base64Conversion=false
serial:electricmeter.pollInterval=50
Additional device and items are configured the same way.
I am not sure whether it is useful to keep the Base64 conversion. The old implemenation is a bit inconsistent between reading from and writing to the serial port. For writing a conversion from Base64 to bytes is done in case the string item value has the prefix BASE64 whereas for reading a Base64 conversion is configured in the item configuration. In my new code Base64 is now a serial port parameter. If switched on all messages read from or written to the serial port are converted.
What do you think about these changes?
Are you missing something?