no way to compare when less than two revisions
Differences
This shows you the differences between two versions of the page.
Next revision | |||
— | livebox:hah_xap_python [2010/04/25 16:18] – external edit 127.0.0.1 | ||
---|---|---|---|
Line 1: | Line 1: | ||
+ | ====== Using xAP and Python ====== | ||
+ | {{: | ||
+ | |||
+ | As Python run on Windows as well as Linux these programs will work on both platforms. | ||
+ | |||
+ | ===== Simplistic samples ===== | ||
+ | |||
+ | Remember as xAP is a Broadcast protocol none of these programs need to be executed on the Livebox to interact with its hardware. | ||
+ | |||
+ | ==== xAP message snooper ==== | ||
+ | |||
+ | Listening to xAP messages on the LAN | ||
+ | <code python> | ||
+ | # | ||
+ | # xAP message listener - simplistic | ||
+ | |||
+ | import socket, traceback | ||
+ | |||
+ | host = '' | ||
+ | s = socket.socket(socket.AF_INET, | ||
+ | s.bind((host, | ||
+ | |||
+ | while 1: | ||
+ | try: | ||
+ | message, address = s.recvfrom(8192) | ||
+ | print "%s: %s" % (address, message) | ||
+ | except (KeyboardInterrupt, | ||
+ | raise | ||
+ | except: | ||
+ | traceback.print_exc() | ||
+ | </ | ||
+ | |||
+ | ==== xAP relay toggle ==== | ||
+ | |||
+ | Toggling the relays on and off using python is very easy. Each will go TICK on/off in sequence. | ||
+ | |||
+ | <code python> | ||
+ | import socket | ||
+ | import time | ||
+ | |||
+ | s = socket.socket(socket.AF_INET, | ||
+ | s.setsockopt(socket.SOL_SOCKET, | ||
+ | |||
+ | for relay in range(1,5): | ||
+ | for state in [' | ||
+ | msg=""" | ||
+ | { | ||
+ | v=12 | ||
+ | hop=1 | ||
+ | uid=FF000F00 | ||
+ | class=xAPBSC.cmd | ||
+ | source=dbzoo.livebox.demo | ||
+ | target=dbzoo.livebox.controller: | ||
+ | } | ||
+ | output.state.1 | ||
+ | { | ||
+ | id=* | ||
+ | state=%s | ||
+ | } | ||
+ | """ | ||
+ | s.sendto(msg % (relay, state), ('< | ||
+ | time.sleep(1) | ||
+ | </ | ||
+ | |||
+ | ==== xAP LCD Clock ==== | ||
+ | |||
+ | A simplistic xAP CLOCK in python. | ||
+ | <code python> | ||
+ | # | ||
+ | # xAP - Simplistic LCD Clock | ||
+ | |||
+ | from socket import * | ||
+ | from time import localtime, strftime, sleep | ||
+ | |||
+ | s = socket(AF_INET, | ||
+ | s.setsockopt(SOL_SOCKET, | ||
+ | while 1: | ||
+ | msg=""" | ||
+ | { | ||
+ | v=12 | ||
+ | hop=1 | ||
+ | uid=FF000F00 | ||
+ | class=xAPBSC.cmd | ||
+ | source=dbzoo.livebox.demo | ||
+ | target=dbzoo.livebox.Controller: | ||
+ | } | ||
+ | output.state.1 | ||
+ | { | ||
+ | id=* | ||
+ | text=%s | ||
+ | } | ||
+ | """ | ||
+ | t = localtime() | ||
+ | s.sendto(msg % strftime(" | ||
+ | sleep(60 - t[5]) | ||
+ | </ | ||
+ | |||
+ | ===== Need an xAP HUB ===== | ||
+ | |||
+ | Without a HUB we are only able to run a single xAP program on a computer at a time, as port 3639, the default xAP port, can only be accessed by one program. | ||
+ | |||
+ | To get around this limitation we run an xAP hub, this performs the same function a the hardware variant of the same name. It allows multiple xAP applications to share the 3639 port which the HUB will manage for us. | ||
+ | |||
+ | Various hub implementations can be found on the [[http:// | ||
+ | |||
+ | Personally I'm a fan of http:// | ||
+ | |||
+ | ===== xAP support Library ===== | ||
+ | |||
+ | The support library {{xaplib.zip}} provides additional code to handle integration with a HUB. | ||
+ | |||
+ | <code python> | ||
+ | # | ||
+ | # | ||
+ | # XAP support library | ||
+ | |||
+ | import socket, traceback, time | ||
+ | |||
+ | class Xap: | ||
+ | def __init__(self, | ||
+ | self.heartbeat_tick = 0; | ||
+ | self.uid = uid | ||
+ | self.source = source | ||
+ | self.port = 0 | ||
+ | self.running = 1 | ||
+ | |||
+ | def run(self, func): | ||
+ | self.connect() | ||
+ | while self.running: | ||
+ | if self.port: | ||
+ | self.heartbeat(60) | ||
+ | try: | ||
+ | func(self) | ||
+ | except KeyboardInterrupt: | ||
+ | self.done() | ||
+ | pass | ||
+ | except socket.timeout: | ||
+ | pass | ||
+ | except: | ||
+ | traceback.print_exc() | ||
+ | self.done() | ||
+ | |||
+ | def done(self): | ||
+ | self.gout.close() | ||
+ | self.gin.close() | ||
+ | self.running = 0 | ||
+ | |||
+ | def connect(self): | ||
+ | host = '' | ||
+ | self.gin = socket.socket(socket.AF_INET, | ||
+ | self.gin.settimeout(60) | ||
+ | try: | ||
+ | self.gin.bind((host, | ||
+ | except socket.error, | ||
+ | print " | ||
+ | print " | ||
+ | host = ' | ||
+ | for self.port in range(3639, | ||
+ | try: | ||
+ | self.gin.bind((host, | ||
+ | except socket.error, | ||
+ | print " | ||
+ | continue | ||
+ | print " | ||
+ | break | ||
+ | |||
+ | self.gout = socket.socket(socket.AF_INET, | ||
+ | self.gout.setsockopt(socket.SOL_SOCKET, | ||
+ | |||
+ | def send(self ,msg): | ||
+ | self.gout.sendto(msg, | ||
+ | |||
+ | def sendMsg(self, | ||
+ | msg = """ | ||
+ | { | ||
+ | v=12 | ||
+ | hop=1 | ||
+ | uid=%s | ||
+ | class=%s | ||
+ | source=%s | ||
+ | target=%s | ||
+ | } | ||
+ | %s""" | ||
+ | self.send(msg) | ||
+ | |||
+ | def sendLCDMsg(self, | ||
+ | msg = " | ||
+ | self.sendMsg(" | ||
+ | |||
+ | def sendSMS(self, | ||
+ | msg = " | ||
+ | self.sendMsg(" | ||
+ | |||
+ | def receive(self): | ||
+ | try: | ||
+ | return self.gin.recvfrom(8192) | ||
+ | except KeyboardInterrupt: | ||
+ | self.done() | ||
+ | pass | ||
+ | |||
+ | # The HUB won't relay messages to us until it see's our heartbeat knows our listening port. | ||
+ | # This must be periodically sent to keep it active on the HUB. | ||
+ | def heartbeat(self, | ||
+ | now = time.time() | ||
+ | if now - self.heartbeat_tick > interval or self.heartbeat_tick == 0: | ||
+ | self.heartbeat_tick = now | ||
+ | msg=""" | ||
+ | { | ||
+ | nv=12 | ||
+ | hop=1 | ||
+ | uid=%s | ||
+ | class=xap-hbeat-alive | ||
+ | source=%s | ||
+ | interval=%s | ||
+ | port=%s | ||
+ | }""" | ||
+ | self.send(msg % (self.uid, self.source, | ||
+ | </ | ||
+ | |||
+ | ===== HUB aware samples ===== | ||
+ | |||
+ | The support library greatly simplifies the process of writing a small xaplet. | ||
+ | |||
+ | ==== xAP message snoop ==== | ||
+ | |||
+ | A message snooper is now trivially implemented | ||
+ | <code python> | ||
+ | # | ||
+ | # xAP message listener - HUB aware | ||
+ | |||
+ | from xaplib import Xap | ||
+ | |||
+ | def snoopTraffic(xap): | ||
+ | print "MSG: %s ADDR: %s" % xap.receive() | ||
+ | |||
+ | Xap(" | ||
+ | </ | ||
+ | |||
+ | ==== xAP LCD Clock ==== | ||
+ | |||
+ | Revisiting our simplistic clock we can rewrite the code using fewer lines and at the same time making it hub friendly. | ||
+ | |||
+ | <code python> | ||
+ | # | ||
+ | # LCD Clock | ||
+ | |||
+ | from xaplib import Xap | ||
+ | from time import localtime, strftime, sleep | ||
+ | |||
+ | def clock(xap): | ||
+ | t = localtime() | ||
+ | xap.sendLCDMsg( strftime(" | ||
+ | sleep(60 - t[5]) | ||
+ | |||
+ | Xap(" | ||
+ | </ | ||
+ | |||
+ | ====== Demo code ====== | ||
+ | Some other samples which might be useful | ||
+ | * {{xap-sms-event.zip}} - Watch out for an RF or RELAY event when one if detected send an SMS of the change | ||
+ | * {{xap-sms-lcd.zip}} - Watch out for inbound SMS messages when one if detected display the message on the livebox LCD | ||
+ | * {{xap-input-smtp.zip}} - Send an email on an input event | ||
+ | |||
+ | {{tag> |