Well I have a basic script for this working now…it is not fully integrated, but provides basic sensor input from the Multicast broadcast messages from the Network OWL.
The script as-is only supports the heating and hot water devices, but could be easily extended to cover solar PV (which I don’t have so are unable to test).
First of all a python script which captures the multicast messages and outputs as json:
import socket
import struct
import json
from xml.etree import ElementTree as ET
OWL_PORT = 22600
OWL_GROUP = "224.192.32.19"
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind((OWL_GROUP, OWL_PORT))
mreq = struct.pack("=4sl", socket.inet_aton(OWL_GROUP), socket.INADDR_ANY)
sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)
while True:
# Collect the XML multicast message
xml, addr = sock.recvfrom(1024)
# Parse the XML string
root = ET.fromstring(xml)
# Only process those messages we are interested in
if root.tag == 'hot_water' or root.tag == 'heating':
timestamp_value = 0
timestamp = root.find('timestamp')
if timestamp is not None:
timestamp_value = int(timestamp.text)
# iterate over each zone (Owl supports up to 4), but we don't distinguish
for zone in root.iter('zone'):
battery_value = 0
battery = zone.find('battery')
if battery is not None:
battery_value = int(battery.attrib["level"])
current_value = 0.0
current = zone.find('temperature/current')
if current is not None:
current_value = float(current.text)
required_value = 0.0
required = zone.find('temperature/required')
if required is not None:
required_value = float(required.text)
ambient_value = 0.0
ambient = zone.find('temperature/ambient')
if ambient is not None:
ambient_value = float(ambient.text)
print json.dumps({'device': root.tag, \
'timestamp': timestamp_value, \
'battery_level': battery_value, \
'current_temperature': current_value, \
'required_temperature': required_value, \
'ambient_temperature': ambient_value })
Then there is a bash script which takes the output of the above and publishes as MQTT messages with topic home/mcast/heating or home/mcast/hot_water.
#!/bin/sh
#
# owl_mcast2mqtt.sh
#
# Publish json output of the owl_mcast2json script to MQTT
#
export LANG=C
PATH="/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin"
MQTT_HOST="192.168.1.10"
MQTT_USER="homeassistant"
MQTT_PASS="SETPASSWORDHERE"
echo "OWL Network Multicast 2 MQTT"
python -u owl_mcast2json.py | while read line
do
MQTT_TOPIC="home/mcast/$(echo $line | jq --raw-output '.device')"
# Publish the json to the appropriate topic
echo $line | mosquitto_pub -h $MQTT_HOST -u $MQTT_USER -P $MQTT_PASS -i OWL_MCast -r -l -t $MQTT_TOPIC
done
Finally a sensor in configuration.yaml to pickup the values, e.g.:
sensor:
- platform: mqtt
name: 'Owl Heating'
state_topic: "home/mcast/heating"
unit_of_measurement: '°C'
value_template: '{{ value_json.current_temperature }}'
The approach is based on the rtl4332mqqt addon by James Fry.