summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--ethcan.py277
-rw-r--r--ethcansend.py56
-rw-r--r--hub_ctrl.py256
-rw-r--r--subbot.py57
-rw-r--r--subcan.py50
6 files changed, 698 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..26e3eaf
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+*.pyc
+settings.py
diff --git a/ethcan.py b/ethcan.py
new file mode 100644
index 0000000..2449933
--- /dev/null
+++ b/ethcan.py
@@ -0,0 +1,277 @@
+import socket, select
+from socket import AF_PACKET, SOCK_RAW, htons, ntohs
+from struct import pack, unpack
+from time import time, sleep, strftime
+import json
+import os, traceback
+import hub_ctrl, usb
+import contextlib
+
+def ts():
+ return strftime('%Y-%m-%d %H:%M:%S')
+
+class SubCANDevice(object):
+ def __init__(s, addr, name, dsize = 1):
+ s.addr = addr
+ s.name = name
+ s.dsize = dsize
+ s.lastval = None
+ s.lastupd = None
+ s.lastchg = None
+ s.actorval = None
+ s.actorupd = None
+ s.actorchg = None
+
+class SubCANBool(SubCANDevice):
+ def __init__(s, addr, name, falseval, trueval):
+ SubCANDevice.__init__(s, addr, name, 1)
+ s.vals = [falseval, trueval]
+ def __str__(s):
+ if s.lastval is None:
+ return 'None'
+ return s.vals[s.lastval & 1]
+ def dict(s):
+ rv = {}
+ if s.lastval is not None:
+ rv['raw'] = s.lastval
+ rv['value'] = bool(s.lastval & 1)
+ rv['text'] = s.vals[s.lastval & 1]
+ rv['ts'] = int(s.lastupd)
+ rv['tschg'] = int(s.lastchg)
+ return rv
+
+class SubCANDALI(SubCANDevice):
+ def __str__(s):
+ if s.lastval is None or s.actorval is None:
+ return ''
+ return 'set: %02x actual: %02x' % (s.actorval, s.lastval)
+ def dict(s):
+ rv = {}
+ if s.lastval is not None:
+ rv['actual'] = s.lastval
+ rv['actual_ts'] = int(s.lastupd)
+ rv['actual_tschg'] = int(s.lastchg)
+ if s.actorval is not None:
+ rv['set'] = s.actorval
+ rv['set_ts'] = int(s.actorupd)
+ rv['set_tschg'] = int(s.actorchg)
+ return rv
+
+devices = [
+ SubCANBool(0x100, 'door.right', 'open', 'closed'),
+ SubCANBool(0x101, 'door.left', 'open', 'closed'),
+ SubCANBool(0x102, 'door.light', 'triggered', 'normal'),
+ SubCANBool(0x103, 'door.lock', 'open', 'closed'),
+ SubCANDALI(0x441, 'dali.lounge_buehne'),
+ SubCANDALI(0x442, 'dali.lounge_buero'),
+ SubCANDALI(0x443, 'dali.lounge_bar'),
+ SubCANDALI(0x444, 'dali.lounge_durchreiche'),
+# SubCANDALI(0x47f, 'dali.lswitch'),
+]
+def find_dev(addr):
+ for dev in devices:
+ if addr in range(dev.addr, dev.addr + dev.dsize):
+ return dev
+ return None
+
+class SubCANFrame(object):
+ def __init__(s, frame):
+ s.frame = frame
+ s.dstaddr = frame.eid & 0xfff
+
+ def process(s):
+ data = s.frame.payload
+ addr = s.dstaddr
+ while len(data) > 0:
+ dev = find_dev(addr)
+ if dev is None:
+ addr += 1
+ data = data[1:]
+ else:
+ val = None
+ devdata = data[:dev.dsize]
+ if dev.dsize == 1:
+ (val, ) = unpack('>B', devdata)
+ elif dev.dsize == 2:
+ (val, ) = unpack('>H', devdata)
+
+ s.do_process(dev, devdata, val)
+ addr += dev.dsize
+ data = data[dev.dsize:]
+
+ @classmethod
+ def create(s, frame):
+ for fclass in s.frametypes:
+ if frame.sid == fclass.matchsid:
+ return fclass(frame)
+ return None
+
+class SensorFrame(SubCANFrame):
+ matchsid = 0xe60
+ def do_process(s, dev, data, val):
+ dev.lastupd = s.frame.ts
+ if val != dev.lastval:
+ dev.lastchg = s.frame.ts
+ dev.lastval = val
+
+class ActorFrame(SubCANFrame):
+ matchsid = 0xcc0
+ def do_process(s, dev, data, val):
+ dev.actorupd = s.frame.ts
+ if val != dev.actorval:
+ dev.actorchg = s.frame.ts
+ dev.actorval = val
+
+SubCANFrame.frametypes = [SensorFrame, ActorFrame]
+
+class MacAddr(object):
+ def __init__(s, mac):
+ s.mac = mac
+ def __str__(s):
+ return ':'.join(['%02x' % (ord(c),) for c in s.mac])
+
+class NotACANFrame(Exception):
+ pass
+class InvalidCANFrame(Exception):
+ pass
+
+from collections import namedtuple
+StatsTuple = namedtuple('StatsTuple', 'ethstat_tx_overrun, ethstat_tx_ok, ethstat_tx_error, ethstat_tx_fnord, ' +
+ 'ethstat_rx_overrun, ethstat_rx_ok, ethstat_rx_error, ethstat_lastrxerr, ' +
+ 'ethstat_again, ethstat_hasherr, ' +
+ 'mcp2515_errors, mcp2515_rx_ok, mcp2515_tx')
+
+class Frame(object):
+ def __init__(s, data):
+ (dst, src, proto, oui, subp, typ) = unpack('>6s6sH3sHB', data[:20])
+ (tsv, ) = unpack('<I', data[20:24])
+ s.data = data[24:]
+ s.dst = MacAddr(dst)
+ s.src = MacAddr(src)
+ s.proto = proto
+ s.ts = time()
+ s.tsr = tsv / 100.
+
+ if s.proto != 0x88b7 or oui != '\x00\x80\x41' or subp != 0xaaaa or len(data) < 5:
+ raise NotACANFrame('invalid protocol/OUI/subp or too short')
+ if typ == 0x01:
+ stats = []
+ data = data[24:]
+ while len(data) >= 4:
+ stats.append(unpack('<I', data[:4])[0])
+ data = data[4:]
+ spretty = StatsTuple._make(stats[:len(StatsTuple._fields)])
+ print '\033[33m%s stats: %s\033[m' % (ts(), repr(spretty))
+ raise NotACANFrame('stats frame')
+
+ if typ != 0x03:
+ raise NotACANFrame('invalid type %02x' % (typ))
+
+ (ts2, ) = unpack('<I', s.data[:4])
+ (addr, dlc) = unpack('>IB', s.data[4:9])
+ s.tsr2 = ts2 / 100.
+
+ s.dlc = dlc & 0x0f
+ s.is_eid = addr & 0x00080000
+ s.is_rtr = bool(dlc & 0x40 if s.is_eid else addr & 0x00100000)
+ s.addr = addr & 0xffe3ffff
+ s.sid = addr >> 20
+ s.eid = addr & 0x3ffff
+
+ if s.is_eid:
+ s.addrstr = '%03x-%05x' % (s.sid, s.eid)
+ else:
+ s.addrstr = '%03x-XXXXX' % (s.sid)
+
+ if len(data) < 9 + s.dlc:
+ raise InvalidCANFrame('truncated frame')
+ s.payload = s.data[9:9+s.dlc]
+
+ def __str__(s):
+ return '%s <- %s %8.2f d=%.2f %s %s: %s' % (
+ s.dst, s.src, s.tsr, s.tsr - s.tsr2,
+ s.addrstr, 'RTR:' if s.is_rtr else 'norm',
+ ' '.join(['%02x' % (ord(c), ) for c in s.payload]))
+
+@contextlib.contextmanager
+def USBHandle(dev):
+ uh = dev.open()
+ try:
+ yield uh
+ finally:
+ del uh
+
+def repower_r0ket():
+ hubs = hub_ctrl.find_hubs(False, False)
+ for h in hubs:
+ if h['dev'].idVendor == 0x050f and h['dev'].idProduct == 0x0003:
+ break
+ else:
+ print 'could not find USB hub!'
+ return
+
+ with USBHandle(h['dev']) as uh:
+ feat = hub_ctrl.USB_PORT_FEAT_POWER
+ index = 1 # port no
+
+ req = usb.REQ_CLEAR_FEATURE
+ uh.controlMsg(requestType = hub_ctrl.USB_RT_PORT, request = req, value = feat, index = index, buffer = None, timeout = 1000)
+ print '\033[31;1m%s: port powered off.\033[m' % (ts(), )
+ sleep(2)
+ req = usb.REQ_SET_FEATURE
+ uh.controlMsg(requestType = hub_ctrl.USB_RT_PORT, request = req, value = feat, index = index, buffer = None, timeout = 1000)
+ print '\033[31;1m%s: port powered on.\033[m' % (ts(), )
+
+ with open('/var/log/ethcan.log', 'a') as logf:
+ logf.write('%s: r0ket powercycled\n' % (ts(), ))
+
+def main():
+ poller = select.poll()
+ poller.register(s, select.POLLIN)
+ timeout = 10
+ while True:
+ ev = poller.poll(timeout * 1000)
+ if len(ev) == 0:
+ # no stats frame for 10s ... r0ket stuck.
+ try: repower_r0ket()
+ except: traceback.print_exc()
+ timeout = 20
+ continue
+ else:
+ timeout = 10
+
+ (data, addr) = s.recvfrom(65536)
+ if addr[0] != 'br0':
+ continue
+ try:
+ pkt = Frame(data)
+ except NotACANFrame, e:
+ if str(e) != 'stats frame':
+ print e
+ continue
+ except InvalidCANFrame, e:
+ print e
+ continue
+
+ scf = SubCANFrame.create(pkt)
+ if scf is not None:
+ scf.process()
+
+ print ts(), addr[0], pkt
+
+ rd = {}
+ for d in devices:
+ rd[d.name] = d.dict()
+ output_file = '/home/services/http/subcan.json'
+ with open(output_file + '.new', 'w') as output:
+ output.write(json.dumps(rd, sort_keys=True, indent=4))
+ os.rename(output_file + '.new', output_file)
+
+if __name__ == '__main__':
+ ifindex = 3
+
+ s = socket.socket(AF_PACKET, SOCK_RAW, htons(0x88b7))
+ mreq = pack('@iHH8s', ifindex, 0, 6, '\xff\x3a\xf6CAN\x00\x00')
+ s.setsockopt(263, 1, mreq)
+
+ main()
diff --git a/ethcansend.py b/ethcansend.py
new file mode 100644
index 0000000..9aaaebd
--- /dev/null
+++ b/ethcansend.py
@@ -0,0 +1,56 @@
+import socket
+from socket import AF_PACKET, SOCK_RAW, htons, ntohs
+from struct import pack, unpack
+from time import time, sleep
+import json
+import hashlib
+
+ifindex = 3
+
+s = socket.socket(AF_PACKET, SOCK_RAW, htons(0x88b7))
+# mreq = pack('@iHH8s', ifindex, 0, 6, '\xff\x3a\xf6CAN\x00\x00')
+# s.setsockopt(263, 1, mreq)
+
+# (addr, dlc) = unpack('>IB', s.data[:5])
+import sys
+
+addr = int(sys.argv[1])
+data = ''
+for d in sys.argv[2:]:
+ data += chr(int(d))
+dlc = len(data)
+addr = 0xcc080440 + addr
+
+data = pack('>IB', addr, dlc) + data + '\x00' * (3 + 8 - len(data))
+
+src = '\x00\x04\x23\xb6\xde\xe4'
+dst = '\xff\x3a\xf6CAN'
+# dst = '\xd2r0ket'
+proto = 0x88b7
+oui = '\x00\x80\x41'
+subp = 0xaaaa
+typ = 3
+
+data = pack('<BII', typ, 0, 0) + data
+
+key = ''.join([chr(i) for i in [
+ 0x2f, 0x5d, 0xb5, 0xe4, 0x59, 0x6d, 0xc5, 0xf1, 0xb0, 0xf4,
+ 0xc3, 0xee, 0x8a, 0xc8, 0xff, 0x06, 0xbc, 0x28, 0x54, 0x08,
+ 0xa6, 0xc2, 0x96, 0x72, 0xd9, 0x0d, 0x22, 0x76, 0xd1, 0x98,
+ 0x0a, 0xdb, 0xca, 0xfe, 0xba, 0xbe, 0xde, 0xad, 0xbe, 0xef,
+]])
+
+dgst = hashlib.sha256()
+# dgst.update(key)
+dgst.update(data)
+
+data += dgst.digest()
+
+data = pack('>6s6sH3sH', dst, src, proto, oui, subp) + data
+
+s.sendto(data, ('bond0.4', 0))
+#sleep(0.1)
+#s.sendto(data, ('bond0.4', 0))
+#sleep(0.1)
+#s.sendto(data, ('bond0.4', 0))
+
diff --git a/hub_ctrl.py b/hub_ctrl.py
new file mode 100644
index 0000000..684b3bd
--- /dev/null
+++ b/hub_ctrl.py
@@ -0,0 +1,256 @@
+#! /usr/bin/python
+
+"""
+hub_ctrl.py - a tool to control port power/led of USB hub
+
+Copyright (C) 2006, 2011 Free Software Initiative of Japan
+
+Author: NIIBE Yutaka <gniibe@fsij.org>
+
+This file is a part of Gnuk, a GnuPG USB Token implementation.
+
+Gnuk is free software: you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+Gnuk is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+"""
+
+import usb
+
+USB_RT_HUB = (usb.TYPE_CLASS | usb.RECIP_DEVICE)
+USB_RT_PORT = (usb.TYPE_CLASS | usb.RECIP_OTHER)
+USB_PORT_FEAT_RESET = 4
+USB_PORT_FEAT_POWER = 8
+USB_PORT_FEAT_INDICATOR = 22
+USB_DIR_IN = 0x80 # device to host
+
+COMMAND_SET_NONE = 0
+COMMAND_SET_LED = 1
+COMMAND_SET_POWER = 2
+
+HUB_LED_GREEN = 2
+
+def find_hubs(listing, verbose, busnum=None, devnum=None, hub=None):
+ number_of_hubs_with_feature = 0
+ hubs = []
+ busses = usb.busses()
+ if not busses:
+ raise ValueError, "can't access USB"
+
+ for bus in busses:
+ devices = bus.devices
+ for dev in devices:
+ if dev.deviceClass != usb.CLASS_HUB:
+ continue
+
+ printout_enable = 0
+ if (listing
+ or (verbose
+ and ((bus.dirname == busnum and dev.devnum == devnumd)
+ or hub == number_of_hubs_with_feature))):
+ printout_enable = 1
+
+ uh = dev.open()
+
+ desc = None
+ try:
+ # Get USB Hub descriptor
+ desc = uh.controlMsg(requestType = USB_DIR_IN | USB_RT_HUB,
+ request = usb.REQ_GET_DESCRIPTOR,
+ value = usb.DT_HUB << 8,
+ index = 0, buffer = 1024, timeout = 1000)
+ finally:
+ del uh
+
+ if not desc:
+ continue
+
+ # desc[3] is lower byte of wHubCharacteristics
+ if (desc[3] & 0x80) == 0 and (desc[3] & 0x03) >= 2:
+ # Hub doesn't have features of controling port power/indicator
+ continue
+
+ if printout_enable:
+ print "Hub #%d at %s:%03d" % (number_of_hubs_with_feature,
+ bus.dirname, dev.devnum)
+ if (desc[3] & 0x03) == 0:
+ print " INFO: ganged power switching."
+ elif (desc[3] & 0x03) == 1:
+ print " INFO: individual power switching."
+ elif (desc[3] & 0x03) == 2 or (desc[3] & 0x03) == 3:
+ print " WARN: no power switching."
+
+ if (desc[3] & 0x80) == 0:
+ print " WARN: Port indicators are NOT supported."
+
+ hubs.append({ 'busnum' : bus.dirname, 'devnum' : dev.devnum,
+ 'indicator_support' : (desc[3] & 0x80) == 0x80,
+ 'dev' : dev, 'num_ports' : desc[2] })
+ number_of_hubs_with_feature += 1
+
+ return hubs
+
+def hub_port_status(handle, num_ports):
+ print " Hub Port Status:"
+ for i in range(num_ports):
+ port = i + 1
+ status = handle.controlMsg(requestType = USB_RT_PORT | usb.ENDPOINT_IN,
+ request = usb.REQ_GET_STATUS,
+ value = 0,
+ index = port, buffer = 4,
+ timeout = 1000)
+
+ print " Port %d: %02x%02x.%02x%02x" % (port, status[3], status[2],
+ status[1], status[0]),
+ if status[1] & 0x10:
+ print " indicator",
+ if status[1] & 0x08:
+ print " test" ,
+ if status[1] & 0x04:
+ print " highspeed",
+ if status[1] & 0x02:
+ print " lowspeed",
+ if status[1] & 0x01:
+ print " power",
+
+ if status[0] & 0x10:
+ print " RESET",
+ if status[0] & 0x08:
+ print " oc",
+ if status[0] & 0x04:
+ print " suspend",
+ if status[0] & 0x02:
+ print " enable",
+ if status[0] & 0x01:
+ print " connect",
+
+ print
+
+import sys
+
+COMMAND_SET_NONE = 0
+COMMAND_SET_LED = 1
+COMMAND_SET_POWER = 2
+HUB_LED_GREEN = 2
+
+def usage(progname):
+ print >> sys.stderr, """Usage: %s [{-h HUBNUM | -b BUSNUM -d DEVNUM}]
+ [-P PORT] [{-p [VALUE]|-l [VALUE]}]
+""" % progname
+
+def exit_with_usage(progname):
+ usage(progname)
+ exit(1)
+
+if __name__ == '__main__':
+ busnum = None
+ devnum = None
+ listing = False
+ verbose = False
+ hub = None
+ port = 1
+ cmd = COMMAND_SET_NONE
+
+ if len(sys.argv) == 1:
+ listing = True
+ else:
+ try:
+ while len(sys.argv) >= 2:
+ option = sys.argv[1]
+ sys.argv.pop(1)
+ if option == '-h':
+ if busnum != None or devnum != None:
+ exit_with_usage(sys.argv[0])
+ hub = int(sys.argv[1])
+ sys.argv.pop(1)
+ elif option == '-b':
+ busnum = int(sys.argv[1])
+ sys.argv.pop(1)
+ elif option == '-d':
+ devnum = int(sys.argv[1])
+ sys.argv.pop(1)
+ elif option == '-P':
+ port = int(sys.argv[1])
+ sys.argv.pop(1)
+ elif option == '-l':
+ if cmd != COMMAND_SET_NONE:
+ exit_with_usage(sys.argv[0])
+ if len(sys.argv) > 1:
+ value = int(sys.argv[1])
+ sys.argv.pop(1)
+ else:
+ value = HUB_LED_GREEN
+ cmd = COMMAND_SET_LED
+ elif option == '-p':
+ if cmd != COMMAND_SET_NONE:
+ exit_with_usage(sys.argv[0])
+ if len(sys.argv) > 1:
+ value = int(sys.argv[1])
+ sys.argv.pop(1)
+ else:
+ value = 0
+ cmd = COMMAND_SET_POWER
+ elif option == '-v':
+ verbose = True
+ if len(sys.argv) == 1:
+ listing = True
+ else:
+ exit_with_usage(sys.argv[0])
+ except:
+ exit_with_usage(sys.argv[0])
+
+ if ((busnum != None and devnum == None)
+ or (busnum == None and devnum != None)):
+ exit_with_usage(sys.argv[0])
+
+ if hub == None and busnum == None:
+ hub = 0 # Default hub = 0
+
+ if cmd == COMMAND_SET_NONE:
+ cmd = COMMAND_SET_POWER
+
+ hubs = find_hubs(listing, verbose, busnum, devnum, hub)
+ if len(hubs) == 0:
+ print >> sys.stderr, "No hubs found."
+ exit(1)
+ if listing:
+ exit(0)
+
+ if hub == None:
+ for h in hubs:
+ if h['busnum'] == busnum and h['devnum'] == devnum:
+ dev_hub = h['dev']
+ nports = h['num_ports']
+ else:
+ dev_hub = hubs[hub]['dev']
+ nports = hubs[hub]['num_ports']
+
+ uh = dev_hub.open()
+ if cmd == COMMAND_SET_POWER:
+ feature = USB_PORT_FEAT_POWER
+ index = port
+ if value:
+ request = usb.REQ_SET_FEATURE
+ else:
+ request = usb.REQ_CLEAR_FEATURE
+ else:
+ request = usb.REQ_SET_FEATURE
+ feature = USB_PORT_FEAT_INDICATOR
+ index = (value << 8) | port
+ if verbose:
+ print "Send control message (REQUEST=%d, FEATURE=%d, INDEX=%d) " % (request, feature, index)
+
+ uh.controlMsg(requestType = USB_RT_PORT, request = request, value = feature,
+ index = index, buffer = None, timeout = 1000)
+ if verbose:
+ hub_port_status(uh,nports)
+
+ del uh
diff --git a/subbot.py b/subbot.py
new file mode 100644
index 0000000..7462bce
--- /dev/null
+++ b/subbot.py
@@ -0,0 +1,57 @@
+#!/usr/bin/env python
+
+import irc.bot
+import json, time
+import traceback
+
+import settings
+
+svcpw = settings.bot_svcpw
+
+class TestBot(irc.bot.SingleServerIRCBot):
+ def __init__(self, channel, nickname, server, port=6667):
+ irc.bot.SingleServerIRCBot.__init__(self, [(server, port)], nickname, nickname)
+ self.channel = channel
+
+ def on_nicknameinuse(self, c, e):
+ c.nick(c.get_nickname() + "_")
+
+ def on_welcome(self, c, e):
+ c.privmsg('NickServ', 'identify sublab|open %s' % (svcpw, ))
+ self.refresh()
+ c.join(self.channel)
+
+ def refresh(self):
+ c = self.connection
+ havenick = c.get_nickname()
+ curtime = time.time()
+
+ try:
+ sdata = json.load(file('/home/services/http/subcan.json', 'r'))
+ door = sdata[u'door.lock']
+
+ if door[u'ts'] < curtime - 120:
+ wantnick = 'sublab|error'
+ elif door[u'text'] == u'closed':
+ wantnick = 'sublab|closed'
+ elif door[u'text'] == u'open':
+ wantnick = 'sublab|open'
+ else:
+ wantnick = 'sublab|error'
+ except Exception, e:
+ traceback.print_exc()
+ wantnick = 'sublab|error'
+
+ if wantnick != havenick:
+ print int(curtime), 'nick:', havenick, '->', wantnick
+ c.privmsg('NickServ', 'ghost %s %s' % (wantnick, svcpw))
+ c.privmsg('NickServ', 'release %s %s' % (wantnick, svcpw))
+ c.nick(wantnick)
+ self.ircobj.execute_delayed(5, self.refresh)
+
+def main():
+ bot = TestBot('#sublab', 'sublab|closed', '172.22.24.1', 6667)
+ bot.start()
+
+if __name__ == "__main__":
+ main()
diff --git a/subcan.py b/subcan.py
new file mode 100644
index 0000000..40d476d
--- /dev/null
+++ b/subcan.py
@@ -0,0 +1,50 @@
+import json
+import sys
+from lxml import etree
+from time import time, sleep
+
+def run():
+ doc = etree.parse('subcan.svg')
+ data = json.loads(file('/home/services/http/subcan.json').read())
+
+ for i in ['door.left', 'door.right', 'door.lock']:
+ cond = '%s=%s' % (i, data[i]['text'])
+ print cond
+ elems = doc.xpath('//svg:g[@inkscape:label="%s"]' % (cond,),
+ namespaces = {
+ 'svg': 'http://www.w3.org/2000/svg',
+ 'inkscape': 'http://www.inkscape.org/namespaces/inkscape',
+ })
+ for e in elems:
+ e.set('style', 'display:inline')
+
+ for i in data.keys():
+ if not i.startswith('dali.'):
+ continue
+ for j in ['set', 'actual']:
+ #for i in [('dali.lounge', 'set'), ('dali.lounge', 'actual')]:
+ elems = doc.xpath('//svg:text[@id="%s_%s"]/svg:tspan' % (i, j),
+ namespaces = {
+ 'svg': 'http://www.w3.org/2000/svg',
+ })
+ print 'elems for %s_%s: %d' % (i, j, len(elems))
+ for e in elems:
+ try:
+ text = data[i][j]
+ if data[i][j + '_ts'] > time() - 300.:
+ text = u'%d%%' % (text / 254. * 100.)
+ else:
+ text = u'<?>'
+ e.text = text
+ except KeyError:
+ print 'error processing \'%s_%s\'' % (i, j)
+ e.text = u'<?>'
+
+ file('/home/services/http/subcan.svg', 'w').write(etree.tostring(doc))
+
+while True:
+ try:
+ run()
+ except Exception:
+ sys.excepthook(*sys.exc_info())
+ sleep(10.)