Owl Intuition pv & Home Assistant

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.

1 Like