trunet

Using XBee Protocol on Twisted

Sep 30th, 2011
129
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 5.79 KB | None | 0 0
  1. # -*- coding: utf-8 -*-
  2. from twisted.python import log, usage
  3. from twisted.internet import reactor, task
  4. from twisted.internet.serialport import SerialPort
  5. from twisted.web.client import getPage
  6.  
  7. import simplejson as json
  8. import rfc822
  9. import ntplib
  10. import datetime
  11. import time
  12.  
  13. import re
  14. from struct import unpack
  15.  
  16. import sys
  17.  
  18. from xbeeService.protocol import ZigBeeProtocol
  19.  
  20. def strip_accents(string):
  21.     import unicodedata
  22.     return unicodedata.normalize('NFKD', unicode(string, encoding="utf-8")).encode('ASCII', 'ignore')
  23.  
  24. class JamesOptions(usage.Options):
  25.     optParameters = [
  26.         ['outfile', 'o', None, 'Logfile [default: sys.stdout]'],
  27.         ['baudrate', 'b', 38400, 'Serial baudrate [default: 38400'],
  28.         ['port', 'p', '/dev/tty.usbserial-A600ezgH', 'Serial Port device'],
  29.     ]
  30.  
  31. devices = {
  32.     "pc": "\x00\x13\xA2\x00\x40\x66\x5D\xB3",
  33.     "energymonitor": "\x00\x13\xA2\x00\x40\x5D\x35\x04",
  34.     "trunetclock": "\x00\x13\xA2\x00\x40\x66\x5D\xEF",
  35.     "template": "\x00\x13\xA2\x00\x00\x00\x00\x00",
  36. }
  37.  
  38. class James(ZigBeeProtocol):
  39.     def __init__(self, *args, **kwds):
  40.         super(James, self).__init__(*args, **kwds)
  41.         self.msgNumber = 1
  42.  
  43.         self.lc_watt = task.LoopingCall(self.getWatts)
  44.         self.lc_watt.start(35.0)
  45.        
  46.         self.lc_get_sigasantos = task.LoopingCall(self.getSantos)
  47.         self.lc_get_sigasantos.start(60.0)
  48.        
  49.         self.lc_printOnClock = task.LoopingCall(self.printOnClock)
  50.         self.lc_printOnClock.start(35.0, now=False)
  51.    
  52.     def decodeFloat(self, var):
  53.         text = ""
  54.         for i in range(0, len(var)):
  55.             text += var[i]
  56.         return unpack('f', text)[0]
  57.  
  58.     def handle_packet(self, xbeePacketDictionary):
  59.         response = xbeePacketDictionary
  60.         if (response.get("rf_data", "default") != "default"):
  61.             if len(response.get("rf_data")) > 0:
  62.                 if response.get("rf_data")[0] == "\x01":
  63.                     c = ntplib.NTPClient()
  64.                     try:
  65.                         response = c.request('br.pool.ntp.org', version=3)
  66.                         timestamp = int(response.tx_time)
  67.                     except:
  68.                         timestamp = int(time.time())
  69.                     finally:
  70.                         t1 = timestamp & 0xff
  71.                         t2 = (timestamp >> 8) & 0xff
  72.                         t3 = (timestamp >> 16) & 0xff
  73.                         t4 = (timestamp >> 24) & 0xff
  74.                         reactor.callFromThread(self.send,
  75.                                   "tx",
  76.                                   frame_id="\x01",
  77.                                   dest_addr_long=response.get("source_addr_long"),
  78.                                   dest_addr="\xff\xfe",
  79.                                   data=chr(t1) + chr(t2) + chr(t3) + chr(t4))
  80.         elif response.get("source_addr_long", "default") == devices["energymonitor"]:
  81.             reactor.callFromThread(self.send,
  82.                       "tx",
  83.                       frame_id="\x01",
  84.                       dest_addr_long=devices["trunetclock"],
  85.                       dest_addr="\xff\xfe",
  86.                       data="\x51" +
  87.                            "\x00" +
  88.                            "Consumo: " + str(int(self.decodeFloat(response["rf_data"][0:4]))) +
  89.                            " Watts")
  90.  
  91.     def printOnClock(self):
  92.         if self.msgNumber == 8:
  93.             self.msgNumber = 1
  94.  
  95.         scrollingPacket = ord("\xe0") | (self.msgNumber << 1)
  96.         self.msgNumber += 1
  97.        
  98.         log.msg("Scrolling on clock message " + str(self.msgNumber-1))
  99.        
  100.         reactor.callFromThread(self.send,
  101.                  "tx",
  102.                  frame_id="\x01",
  103.                  dest_addr_long=devices["trunetclock"],
  104.                  dest_addr="\xff\xfe",
  105.                  data="\x52" + chr(scrollingPacket))
  106.  
  107.     def getWatts(self):
  108.         log.msg("Asking power consumption...")
  109.         reactor.callFromThread(self.send,
  110.                      "tx",
  111.                      frame_id="\x01",
  112.                      dest_addr_long=devices["energymonitor"],
  113.                      dest_addr="\xff\xfe",
  114.                      data="\x05")
  115.  
  116.     def getSantos(self):
  117.         def parseFeed(data):
  118.             return json.loads(data)
  119.            
  120.         def saveData(feed):
  121.             santos = []
  122.             for item in range(0, len(feed)):
  123.                 title = strip_accents(feed[item]['text'].encode('utf-8'))
  124.                
  125.                 # Regular Expression to get what I want
  126.                 reg_notice = re.compile('^(.*)(: http://.*)$').search(title)
  127.                 reg_jogo = re.compile('^(.*)( Siga AO VIVO por aqui!)$').search(title)
  128.                 if reg_jogo is not None:
  129.                     title = reg_jogo.groups()[0][:90]
  130.                 elif reg_notice is not None:
  131.                     title = reg_notice.groups()[0][:90]
  132.                 else:
  133.                     title = title[:90]
  134.                
  135.                 created_at = rfc822.parsedate(feed[item]['created_at'])
  136.                 if (time.mktime(created_at) >= (time.time() - (60*60*12))):
  137.                     santos.append({
  138.                                     'created_at': created_at,
  139.                                     'title': title
  140.                                   })
  141.             return santos
  142.        
  143.         def sendToClock(data):
  144.             msg = 1
  145.             for item in range(0, len(data)):
  146.                 item = data.pop(0)
  147.                 if msg == 8:
  148.                     break
  149.                 title = item['title']
  150.                 log.msg("Sending to Clock on Address " + str(msg) + " - " + title)
  151.                 reactor.callFromThread(self.send,
  152.                          "tx",
  153.                          frame_id="\x01",
  154.                          dest_addr_long=devices["trunetclock"],
  155.                          dest_addr="\xff\xfe",
  156.                          data="\x51" +
  157.                               chr(msg) +
  158.                               title)
  159.                 msg += 1
  160.        
  161.         def logError(error):
  162.             log.msg("Error downloading SigaSantos RSS from twitter" + str(error))
  163.        
  164.         page = getPage("http://api.twitter.com/1/statuses/user_timeline.json?screen_name=sigasantos")
  165.        
  166.         page.addCallback(parseFeed)
  167.         page.addErrback(logError)
  168.        
  169.         page.addCallback(saveData)
  170.         page.addErrback(logError)
  171.        
  172.         page.addCallback(sendToClock)
  173.         page.addErrback(logError)
  174.  
  175. if __name__ == '__main__':
  176.     o = JamesOptions()
  177.     try:
  178.         o.parseOptions()
  179.     except usage.UsageError, errortext:
  180.         print '%s: %s' % (sys.argv[0], errortext)
  181.         print '%s: Try --help for usage details.' % (sys.argv[0])
  182.         raise SystemExit, 1
  183.  
  184.     logFile = o.opts['outfile']
  185.     if logFile is None:
  186.         logFile = sys.stdout
  187.     log.startLogging(logFile)
  188.  
  189.     port = o.opts['port']
  190.     log.msg('Attempting to open %s at %dbps as a %s device' % (port, o.opts['baudrate'], ZigBeeProtocol.__name__))
  191.    
  192.     s = SerialPort(James(), o.opts['port'], reactor, baudrate=o.opts['baudrate'])
  193.    
  194.     reactor.run()
  195.  
  196.  
Advertisement
Add Comment
Please, Sign In to add comment