Thanks @rog99, i will copy that code here (see below).
##################################################################
# v3 - electric + hw
# v4 - adds ground floor room sensor
from twisted.internet.protocol import DatagramProtocol
from lxml import objectify
from decimal import Decimal
import socket
import requests
import pdb
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # Internet, UDP
MCAST_ADDR = '224.192.32.19'
MCAST_PORT = 22600
class node(object):
# structure for storing data about channels
def __init__(self, channel_id, current_w, daily_wh):
self.channel_id = channel_id
self.current_w = Decimal(current_w)
self.daily_wh = Decimal(daily_wh)
def __str__(self):
return '%s' % (
self.channel_id, # self.channel_id
self.current_w, # self.current_w
self.daily_wh # self.daily_wh
)
class OwlMessage(object):
def __init__(self, datagram):
#print "datagram: %r" % (datagram,)
self.root = objectify.fromstring(datagram)
if self.root.tag == 'electricity':
# there are also weather events -- we don't care about these (yet)
assert (self.root.tag == 'electricity'), ('OwlMessage XML must have `electricity` root node (got %r).' % self.root.tag)
# note that the MAC address is given by the message, not the packet.
# this can be spoofed
self.mac = self.root.attrib['id']
# read signal information for the sensor's 433MHz link
self.rssi = Decimal(self.root.signal[0].attrib['rssi'])
self.lqi = Decimal(self.root.signal[0].attrib['lqi'])
# read timestamp from message
self.msgtime = self.root.timestamp
# read battery information from the sensor.
self.battery = Decimal(self.root.battery[0].attrib['level'][:-1])
import xml.etree.ElementTree as ET
tree = ET.ElementTree(ET.fromstring(datagram))
root = tree.getroot()
#self.otimestamp = root[0].text # messages timestamp
self.och1curr = root[3][0].text # chan1 current usage
self.och1day = root[3][1].text # chan1 daily usage
elif self.root.tag == 'hot_water':
assert (self.root.tag == 'hot_water'), ('OwlMessage XML must have `hot_water` root node (got %r).' % self.root.tag)
#gather relevant data from datagram
self.mac = self.root.attrib['id']
self.msgtime = self.root.timestamp
self.battery = Decimal(self.root.zones.zone.battery.attrib['level'][:-1])
self.tcurr = self.root.zones.zone.temperature.current.text # current HW temperature according to probe sensor
self.treq = self.root.zones.zone.temperature.required.text # required/target HW temperature according to time schedule
self.tambi = self.root.zones.zone.temperature.ambient.text # ambient temperature at wall control box
# HW heater state; 0=off,1=heat on,4=comfort(at temp),5=warmingup,6=comfort(cooling down), 7=standby (on, freeze protection)
self.hwstatus = self.root.zones.zone.temperature.attrib['state']
elif self.root.tag == 'heating':
assert (self.root.tag == 'heating'), ('OwlMessage XML must have `heating` root node (got %r).' % self.root.tag)
# gather heating data from datagram (1 room sensor)
# self.msgtime = self.root.timestamp
# self.battery = Decimal(self.root.zones.zone.battery.attrib['level'][:-1])
# self.tcurr = self.root.zones.zone.temperature.current.text
# self.treq = self.root.zones.zone.temperature.required.text
# self.chstatus = self.root.zones.zone.temperature.attrib['state']
# ground floor room sensor [zone 0]
self.gbattery = Decimal(self.root.zones.zone[0].battery.attrib['level'][:-1])
self.gtcurr = self.root.zones.zone[0].temperature.current.text
self.gtreq = self.root.zones.zone[0].temperature.required.text
self.gchstatus = self.root.zones.zone[0].temperature.attrib['state']
# upstairs room sensor [zone 1]
self.ubattery = Decimal(self.root.zones.zone[1].battery.attrib['level'][:-1])
self.utcurr = self.root.zones.zone[1].temperature.current.text
self.utreq = self.root.zones.zone[1].temperature.required.text
self.uchstatus = self.root.zones.zone[1].temperature.attrib['state']
def __str__(self):
if self.root.tag == 'electricity': #prepare electricity message
self.nodemsg = '1&' # we want to submit electricity messages as node 1
return (self.nodemsg + 'csv=%s' % (
','.join((str(x) for x in (self.mac,self.msgtime,self.battery,self.och1curr,self.och1day)))
))
elif self.root.tag == 'hot_water': #prepare hot water message
self.nodemsg = '2&' # we want to submit hot water messages as node 2
return (self.nodemsg + 'csv=%s' % (
','.join((str(x) for x in (self.mac,self.msgtime,self.battery,self.tcurr,self.treq,self.tambi,self.hwstatus)))
))
elif self.root.tag == 'heating': #prepare heating message
self.nodemsg = '3&' # we want to submit heating messages as node 3
return (self.nodemsg + 'csv=0,%s' % (
','.join((str(x) for x in (self.gbattery,self.gtcurr,self.gtreq,self.gchstatus,self.ubattery,self.utcurr,self.utreq,self.uchstatus)))
))
class OwlIntuitionProtocol(DatagramProtocol):
def __init__(self, iface=''):
"""
Protocol for Owl Intution (Network Owl) multicast UDP.
:param iface: Name of the interface to use to communicate with the Network Owl. If not specified, uses the default network connection on the cost.
:type iface: str
"""
self.iface = iface
def startProtocol(self):
self.transport.joinGroup(MCAST_ADDR, self.iface)
def datagramReceived(self, datagram, address):
msg = OwlMessage(datagram)
self.owlReceived(address, msg)
def owlReceived(self, address, msg):
print '%s' % (msg)
curlmessage = '%s' % (msg)
myurl = "http://localhost/emoncms/input/post.json?node="+curlmessage+"&apikey=46e787d42926d0caf0bd647747d3ac1c"
r = requests.post(myurl)
if __name__ == '__main__':
from twisted.internet import reactor
from argparse import ArgumentParser
parser = ArgumentParser()
parser.add_argument('-i', '--iface', dest='iface', default='', help='Network interface to use for getting data.')
options = parser.parse_args()
protocol = OwlIntuitionProtocol(iface=options.iface)
reactor.listenMulticast(MCAST_PORT, protocol, listenMultiple=True)
reactor.run()
#########################################################################
Do you intend to have the blog back up and running oneday?
Perhaps you content might be better place on GitHub or maybe it could be found a home here somewhere, subject to some peer review and a nod from the powers that be, or indeed just as a forum topic that we can close to comment?