class States(object): def __init__(self): self._dao = Sensors() self._sr = StateResolver() exposed = True def GET(self, *args, **kwargs): sensors = self._dao.findSensors() sensors = sorted(sensors, key=itemgetter('locationName', 'ChannelDescriptor')) elements = [] for sensor in sensors: elements.append({ 'color': self.getBackgroundColor(sensor), 'room': '%(loc)s: %(sen)s' % { 'loc': sensor['locationName'], 'sen': sensor['name'] }, 'channel': sensor['ChannelDescriptor'], 'value': sensor['value'], 'status': self._sr.getDisplayState(sensor) }) cherrypy.response.headers['Content-Type'] = 'application/json' return json.dumps(elements) def getBackgroundColor(self, sensor): stype = sensor['sensorTypeName'] if stype == 'CONTACT_REED': if float(sensor['value']) == 1: return '#FF0000' else: return '#00FF00' # closed door == green colour elif stype == 'CONTACT_PRESSUREMAT': if float(sensor['value']) == 1: return '#00FF00' # vacant chair == green colour else: return '#FF0000' elif stype == 'TEMPERATURE_MCP9700_HOT' or stype == 'TEMPERATURE_MCP9700_COLD': #return str((float(sensor['value']) - 0.5) * 100.0) + 'C' temp = float(sensor['value']) if temp < 0.0: r = 0 elif temp > 50.0: r = 255 else: r = int(temp * 5.1) # -0C..+50C -> 0..255 g = 0 b = 255 - r return '#%02X%02X%02X' % (r, g, b) elif stype == 'POWER_CONSUMPTION_MONITOR': if self._sr.isSensorOn(sensor): return '#FFFF00' else: return '#00FF00' # closed door == green colour else: return 'None'
class GEOSystem(PollingProcessor): def __init__ (self, hostName, userName, password, database, query): super(GEOSystem, self).__init__() self._geoDao = SQLDao(hostName, userName, password, database) self._geoQuery = query self._sensorDao = Sensors() self._sensors = self._sensorDao.findSensors() self._sr = StateResolver() self._channels = {} self._warned = [] @property def channels(self): return self._channels def start(self): print "Started polling geo sensors" self._addPollingProcessor('geoSensors', self.pollGeoSystem, None, 0.1) def stop(self): print "Stopped polling geo sensors" self._removePollingProcessor('geoSensors') def pollGeoSystem(self): rows = self._geoDao.getData(self._geoQuery) # This appears to be needed or 'CALL exppower' doesn't update the power values, # oddly, it updates the timestamp field though... self._geoDao.close() for row in rows: try: sensor = next(s for s in self._sensors if s['ChannelDescriptor'] == str(row['ID'])) except StopIteration: # Only warn once, or we'll flood the console if row['ID'] not in self._warned: print >> sys.stderr, "Warning: Unable to locate sensor record for geo sensor %s. ID: %s" % (row['Description'], row['ID']) self._warned.append(row['ID']) continue _device = sensor['locationName'] _name = sensor['name'] _id = sensor['sensorId'] _type = sensor['sensorTypeName'] # Only warn once, or we'll flood the console if _name != row['Description'] and row['ID'] not in self._warned: print >> sys.stderr, 'Warning: Channel name differs from Geo-System description: %s / %s' % (_name, row['Description']) self._warned.append(row['ID']) _status = self._sr.getDisplayState({'sensorTypeName': _type, 'value': row['Power'], 'sensorId': _id }) self._channels[row['ID']] = { 'id': _id, 'room': _device, 'channel': _name, 'value': '%.1f' % row['Power'], 'status': _status }
class States(object): def __init__(self): self._dao = Sensors() self._sr = StateResolver() exposed = True def GET(self, *args, **kwargs): sensors = self._dao.findSensors() sensors = sorted(sensors, key = itemgetter('locationName', 'ChannelDescriptor')) elements = [] for sensor in sensors: elements.append( { 'color': self.getBackgroundColor(sensor), 'room': '%(loc)s: %(sen)s' % { 'loc': sensor['locationName'], 'sen': sensor['name'] }, 'channel': sensor['ChannelDescriptor'], 'value': sensor['value'], 'status': self._sr.getDisplayState(sensor) }) cherrypy.response.headers['Content-Type'] = 'application/json' return json.dumps(elements) def getBackgroundColor(self, sensor): stype = sensor['sensorTypeName'] if stype == 'CONTACT_REED': if float(sensor['value']) == 1: return '#FF0000' else: return '#00FF00' # closed door == green colour elif stype == 'CONTACT_PRESSUREMAT': if float(sensor['value']) == 1: return '#00FF00' # vacant chair == green colour else: return '#FF0000' elif stype == 'TEMPERATURE_MCP9700_HOT' or stype == 'TEMPERATURE_MCP9700_COLD': #return str((float(sensor['value']) - 0.5) * 100.0) + 'C' temp = float(sensor['value']) if temp < 0.0: r = 0 elif temp > 50.0: r = 255 else: r = int(temp * 5.1) # -0C..+50C -> 0..255 g = 0 b = 255 - r return '#%02X%02X%02X' % (r, g, b) elif stype == 'POWER_CONSUMPTION_MONITOR': if self._sr.isSensorOn(sensor): return '#FFFF00' else: return '#00FF00' # closed door == green colour else: return 'None'
class ZigBee(PollingProcessor): # Initialisation method # Opens the configured UDP socket for the receipt of broadcast messages. def __init__(self, udpPort): super(ZigBee, self).__init__() self.sock = socket(AF_INET, SOCK_DGRAM) self.sock.settimeout(1) self.sock.bind(('', udpPort)) # Place for the callback methods to store "static" values. # Currently only needed for the Moving Average Filter for the MCP9700 # temperature sensor temperature calculations. self._handler_memory = {} self._channels = {} self._sr = StateResolver() self._sensorDao = Sensors() self._sensors = self._sensorDao.findSensors() self._warned = [] @property def channels(self): if self._channels == None: self._channels = {} return self._channels def start(self): print "Started polling zigBee sensors" self._addPollingProcessor('zigBee', self.pollZigbeeSensors, None, 0.0001) def stop(self): print "Stopped polling zigBee sensors" self._removePollingProcessor('zigBee') # ZigBee thread main loop def pollZigbeeSensors(self): try: data, _ = self.sock.recvfrom(10240, 0) except Exception as e: if type(e) != timeout: print e return (_, mac, channel, val) = data.split(' ') mac = mac.lower() channel = channel.upper() try: sensor = next(s for s in self._sensors if s['ChannelDescriptor'] == str(mac) + str(channel)) except StopIteration: #Only warn once, or we'll flood the console if str(mac) + str(channel) not in self._warned: print >> sys.stderr, "Warning: Unable to locate sensor record for zigbee sensor ID: %s" % ( str(mac) + str(channel)) self._warned.append(str(mac) + str(channel)) return _device = sensor['locationName'] _pin = sensor['name'] _id = sensor['sensorId'] if val != '-' and val != '': _type = sensor['sensorTypeName'] _uuid = '%s_%s' % (mac, channel) if _type == 'TEMPERATURE_MCP9700_HOT' or _type == 'TEMPERATURE_MCP9700_COLD': _value = str((float(val) - 0.5) * 100.0) else: _value = val _status = self._sr.getDisplayState({ 'sensorTypeName': _type, 'value': _value, 'sensorId': _id }) self._channels[_uuid] = { 'id': _id, 'room': _device, 'channel': _pin, 'value': _value, 'status': _status }
class GEOSystem(PollingProcessor): def __init__(self, hostName, userName, password, database, query): super(GEOSystem, self).__init__() self._geoDao = SQLDao(hostName, userName, password, database) self._geoQuery = query self._sensorDao = Sensors() self._sensors = self._sensorDao.findSensors() self._sr = StateResolver() self._channels = {} self._warned = [] @property def channels(self): return self._channels def start(self): print "Started polling geo sensors" self._addPollingProcessor('geoSensors', self.pollGeoSystem, None, 0.1) def stop(self): print "Stopped polling geo sensors" self._removePollingProcessor('geoSensors') def pollGeoSystem(self): rows = self._geoDao.getData(self._geoQuery) #This appears to be needed or 'CALL exppower' doesn't update the power values, # oddly, it updates the timestamp field though... self._geoDao.close() for row in rows: try: sensor = next(s for s in self._sensors if s['ChannelDescriptor'] == str(row['ID'])) except StopIteration: #Only warn once, or we'll flood the console if row['ID'] not in self._warned: print >> sys.stderr, "Warning: Unable to locate sensor record for geo sensor %s. ID: %s" % ( row['Description'], row['ID']) self._warned.append(row['ID']) continue _device = sensor['locationName'] _name = sensor['name'] _id = sensor['sensorId'] #Only warn once, or we'll flood the console if _name != row['Description'] and row['ID'] not in self._warned: print >> sys.stderr, 'Warning: Channel name differs from Geo-System description: %s / %s' % ( _name, row['Description']) self._warned.append(row['ID']) _state = self._sr.evaluateRule(sensor['sensorRule'], row['Power']) if _state: _state = 'On' else: _state = 'Off' self._channels[row['ID']] = { 'id': _id, 'room': _device, 'channel': _name, 'value': '%.1f' % row['Power'], 'status': _state }
class ZigBee(PollingProcessor): # Initialisation method # Opens the configured UDP socket for the receipt of broadcast messages. def __init__ (self, udpPort): super(ZigBee, self).__init__() self.sock = socket(AF_INET, SOCK_DGRAM) self.sock.settimeout(1) self.sock.bind(('', udpPort)) # Place for the callback methods to store "static" values. # Currently only needed for the Moving Average Filter for the MCP9700 # temperature sensor temperature calculations. self._handler_memory = {} self._channels = {} self._sr = StateResolver() self._sensorDao = Sensors() self._sensors = self._sensorDao.findSensors() self._warned = [] @property def channels(self): if self._channels == None: self._channels = {} return self._channels def start(self): print "Started polling zigBee sensors" self._addPollingProcessor('zigBee', self.pollZigbeeSensors, None, 0.0001) def stop(self): print "Stopped polling zigBee sensors" self._removePollingProcessor('zigBee') # ZigBee thread main loop def pollZigbeeSensors(self): try: data, _ = self.sock.recvfrom(10240, 0) except Exception as e: if type(e) != timeout: print e return (_, mac, channel, val) = data.split(' ') mac = mac.lower() channel = channel.upper() try: sensor = next(s for s in self._sensors if s['ChannelDescriptor'] == str(mac) + str(channel)) except StopIteration: #Only warn once, or we'll flood the console if str(mac) + str(channel) not in self._warned: print >> sys.stderr, "Warning: Unable to locate sensor record for zigbee sensor ID: %s" % (str(mac) + str(channel)) self._warned.append(str(mac) + str(channel)) return _device = sensor['locationName'] _pin = sensor['name'] _id = sensor['sensorId'] if val != '-' and val != '': _type = sensor['sensorTypeName'] _uuid = '%s_%s' % (mac , channel) if _type == 'TEMPERATURE_MCP9700_HOT' or _type == 'TEMPERATURE_MCP9700_COLD': _value = str((float( val) - 0.5) * 100.0) else: _value = val _status = self._sr.getDisplayState({'sensorTypeName': _type, 'value': _value, 'sensorId': _id }) self._channels[_uuid] = { 'id': _id, 'room': _device, 'channel': _pin, 'value': _value, 'status': _status }
class ZWaveHomeController(PollingProcessor): # Initialisation method # Opens the configured UDP socket for the receipt of broadcast messages. def __init__(self, ipAddress): super(ZWaveHomeController, self).__init__() self._baseUrl = "http://%(ip)s:80/api/devices" % {'ip': ipAddress} # Place for the callback methods to store "static" values. # Currently only needed for the Moving Average Filter for the MCP9700 # temperature sensor temperature calculations. self._handler_memory = {} self._channels = {} self._sr = StateResolver() self._sensorDao = Sensors() self._sensors = self._sensorDao.findSensors() self._warned = [] @property def channels(self): if self._channels == None: self._channels = {} return self._channels def start(self): print "Started polling zwave sensors" self._addPollingProcessor('zwave', self.pollZWaveSensors, None, 0.1) def stop(self): print "Stopped polling zwave sensors" self._removePollingProcessor('zwave') def pollZWaveSensors(self): """ Check the http api for sensors & values and add them to the channels list in the standard format """ try: # http://192.168.1.109/devices url = self._baseUrl request = urllib2.Request(url) base64string = base64.encodestring( '%s:%s' % ('admin', 'admin')).replace('\n', '') request.add_header("Authorization", "Basic %s" % base64string) result = urllib2.urlopen(request) data = json.load(result) except Exception as e: if str(type(e)) not in self._warned: print >> sys.stderr, "Error while receiving data from ZWaveHomeController: %s" % e self._warned.append(str(type(e))) return for device in data: channelDescriptor = 'zwave:' + str(device['id']) try: sensor = next(s for s in self._sensors if s['ChannelDescriptor'] == channelDescriptor) except StopIteration: # Only warn once, or we'll flood the console if channelDescriptor not in self._warned: print "Warning: Unable to locate sensor record for ZWave sensor ID: %s (%s)" % ( str(channelDescriptor), str(device['name'])) self._warned.append(channelDescriptor) continue _device = sensor['locationName'] _pin = sensor['name'] _id = sensor['sensorId'] _rule = sensor['sensorRule'] # order determines priority valueKeys = ['valueSensor', 'value'] _value = None for valueKey in valueKeys: if device['properties'].has_key(valueKey): _value = device['properties'][valueKey] break _value = _valueHelper.filterValue(_value, sensor['sensorTypeName']) if _value != None: _type = sensor['sensorTypeName'] _uuid = channelDescriptor _status = self._sr.getDisplayState({ 'sensorTypeName': _type, 'value': _value, 'sensorId': _id, 'sensorRule': _rule }) self._channels[_uuid] = { 'id': _id, 'room': _device, 'channel': _pin, 'value': _value, 'status': _status }
class ZigBeeDirect(PollingProcessor): def __init__(self, usbPort, baudRate=9600): super(ZigBeeDirect, self).__init__() import serial from Lib.xbee import ZigBee try: self._port = serial.Serial(usbPort, baudRate) except Exception as e: print >> sys.stderr, "Unable to connect to zigbee port, check that the port name (%s) and permissions are correct (should be a+rw)" % ( usbPort) raise e self._zigbee = ZigBee(self._port) # Place for the callback methods to store "static" values. # Currently only needed for the Moving Average Filter for the MCP9700 # temperature sensor temperature calculations. self._handler_memory = {} self._channels = {} self._sr = StateResolver() self._sensorDao = Sensors() self._sensors = self._sensorDao.findSensors() self._warned = [] def __del__(self): self._port.close() super(ZigBeeDirect, self).__del__() @property def channels(self): if self._channels == None: self._channels = {} return self._channels def start(self): print "Started polling directly connected zigBee sensors" self._addPollingProcessor('zigBeeDirect', self.pollZigbeeSensors, None, 0.1) def stop(self): print "Stopped polling directly connected zigBee sensors" self._removePollingProcessor('zigBeeDirect') # ZigBee thread main loop def pollZigbeeSensors(self): """ Read the data from the Zigbee sensors directly connected to this machine """ try: #data, _ = self._xbee.wait_read_frame() data = self._zigbee.wait_read_frame() except Exception as e: if str(type(e)) not in self._warned: print >> sys.stderr, "Error while receiving data from ZigBeeDirect: %s" % e self._warned.append(str(type(e))) return if data["id"] == "rx_explicit": mac = repr(data['source_addr_long']).replace( '\\x', ':').strip(":'").lower() # If NI (Network Id)recognised include NI string in returned values try: channels = self._zigbee._parse_samples( data['rf_data'])[0] # Parse IO data except Exception as e: print >> sys.stderr, "Error reading zigbee data: %s" % e return for channel, _value in channels.items(): channel = "!" + channel.lower() try: sensor = next(s for s in self._sensors if s['ChannelDescriptor'] == str(mac) + str(channel)) except StopIteration: # Only warn once, or we'll flood the console if str(mac) + str(channel) not in self._warned: print "Warning: Unable to locate sensor record for ZigBee sensor ID: %s" % ( str(mac) + str(channel)) self._warned.append(str(mac) + str(channel)) continue _device = sensor['locationName'] _pin = sensor['name'] _id = sensor['sensorId'] _rule = sensor['sensorRule'] _value = _valueHelper.filterValue(_value, sensor['sensorTypeName']) if _value != None: _type = sensor['sensorTypeName'] _uuid = '%s_%s' % (mac, channel) _status = self._sr.getDisplayState({ 'sensorTypeName': _type, 'value': _value, 'sensorId': _id, 'sensorRule': _rule }) self._channels[_uuid] = { 'id': _id, 'room': _device, 'channel': _pin, 'value': _value, 'status': _status }
class ZWaveVeraLite(PollingProcessor): # Initialisation method # Opens the configured UDP socket for the receipt of broadcast messages. def __init__(self, ipAddress, port): super(ZWaveVeraLite, self).__init__() self._loadTime = None self._dataVersion = None self._baseUrl = "http://%(ip)s:%(port)s/data_request?id=lu_sdata&timeout=%(timeout)s" % { 'ip': ipAddress, 'port': port, 'timeout': 60 } # Place for the callback methods to store "static" values. # Currently only needed for the Moving Average Filter for the MCP9700 # temperature sensor temperature calculations. self._handler_memory = {} self._channels = {} self._sr = StateResolver() self._sensorDao = Sensors() self._sensors = self._sensorDao.findSensors() self._warned = [] @property def channels(self): if self._channels == None: self._channels = {} return self._channels def start(self): print "Started polling zwave sensors" self._addPollingProcessor('zwave', self.pollZWaveSensors, None, 0.1) def stop(self): print "Stopped polling zwave sensors" self._removePollingProcessor('zwave') # ZigBee thread main loop def pollZWaveSensors(self): """ Check the http api for sensors & values and add them to the channels list in the standard format """ """ first iteration pulls all data, subsequent loops pull only changed data since the last run """ try: # http://192.168.1.158:3480/data_request?id=lu_sdata # http://192.168.1.158:3480/data_request?id=lu_sdata&loadtime=1282441735&dataversion=441736333&timeout=60 url = self._baseUrl if self._loadTime != None and self._dataVersion != None: url += '&loadtime=%(load)s&dataversion=(dataversion)s' % { 'load': self._loadTime, 'dataversion': self._dataVersion } data = json.load(urllib2.urlopen(url)) except Exception as e: if str(type(e)) not in self._warned: print >> sys.stderr, "Error while receiving data from ZWaveVeraLite: %s" % e self._warned.append(str(type(e))) return self._loadTime = data['loadtime'] self._dataVersion = data['dataversion'] for device in data['devices']: channelDescriptor = 'zwave:' + str(device['id']) try: sensor = next(s for s in self._sensors if s['ChannelDescriptor'] == channelDescriptor) except StopIteration: # Only warn once, or we'll flood the console if channelDescriptor not in self._warned: print "Warning: Unable to locate sensor record for ZWave sensor ID: %s (%s)" % ( str(channelDescriptor), str(device['name'])) self._warned.append(channelDescriptor) continue _device = sensor['locationName'] _pin = sensor['name'] _id = sensor['sensorId'] _rule = sensor['sensorRule'] valueKeys = ['armed', 'status'] _value = None for valueKey in valueKeys: if device.has_key(valueKey): _value = device[valueKey] break _value = _valueHelper.filterValue(_value, sensor['sensorTypeName']) if _value != None: _type = sensor['sensorTypeName'] _uuid = channelDescriptor _status = self._sr.getDisplayState({ 'sensorTypeName': _type, 'value': _value, 'sensorId': _id, 'sensorRule': _rule }) self._channels[_uuid] = { 'id': _id, 'room': _device, 'channel': _pin, 'value': _value, 'status': _status }
class ZWaveHomeController(PollingProcessor): # Initialisation method # Opens the configured UDP socket for the receipt of broadcast messages. def __init__ (self, ipAddress): super(ZWaveHomeController, self).__init__() self._baseUrl = "http://%(ip)s:80/api/devices" % {'ip': ipAddress} # Place for the callback methods to store "static" values. # Currently only needed for the Moving Average Filter for the MCP9700 # temperature sensor temperature calculations. self._handler_memory = {} self._channels = {} self._sr = StateResolver() self._sensorDao = Sensors() self._sensors = self._sensorDao.findSensors() self._warned = [] @property def channels(self): if self._channels == None: self._channels = {} return self._channels def start(self): print "Started polling zwave sensors" self._addPollingProcessor('zwave', self.pollZWaveSensors, None, 0.1) def stop(self): print "Stopped polling zwave sensors" self._removePollingProcessor('zwave') def pollZWaveSensors(self): """ Check the http api for sensors & values and add them to the channels list in the standard format """ try: # http://192.168.1.109/devices url = self._baseUrl request = urllib2.Request(url) base64string = base64.encodestring('%s:%s' % ('admin', 'admin')).replace('\n', '') request.add_header("Authorization", "Basic %s" % base64string) result = urllib2.urlopen(request) data = json.load(result) except Exception as e: if id(self) + type(e) not in self._warned: print >> sys.stderr, "Error while receiving data from ZWaveHomeController: %s" % e self._warned.append(id(self) + type(e)) return for device in data: channelDescriptor = 'zwave:' + str(device['id']) try: sensor = next(s for s in self._sensors if s['ChannelDescriptor'] == channelDescriptor) except StopIteration: # Only warn once, or we'll flood the console if channelDescriptor not in self._warned: print "Warning: Unable to locate sensor record for ZWave sensor ID: %s (%s)" % (str(channelDescriptor), str(device['name'])) self._warned.append(channelDescriptor) continue _device = sensor['locationName'] _pin = sensor['name'] _id = sensor['sensorId'] _rule = sensor['sensorRule'] # order determines priority valueKeys = ['valueSensor', 'value'] _value = None for valueKey in valueKeys: if device['properties'].has_key(valueKey): _value = device['properties'][valueKey] break _value = _valueHelper.filterValue(_value, sensor['sensorTypeName']) if _value != None: _type = sensor['sensorTypeName'] _uuid = channelDescriptor _status = self._sr.getDisplayState({'sensorTypeName': _type, 'value': _value, 'sensorId': _id, 'sensorRule': _rule }) self._channels[_uuid] = { 'id': _id, 'room': _device, 'channel': _pin, 'value': _value, 'status': _status }
class ZigBeeDirect(PollingProcessor): def __init__(self, usbPort, baudRate=9600): super(ZigBeeDirect, self).__init__() import serial from Lib.xbee import ZigBee self._port = serial.Serial(usbPort, baudRate) self._zigbee = ZigBee(self._port) # Place for the callback methods to store "static" values. # Currently only needed for the Moving Average Filter for the MCP9700 # temperature sensor temperature calculations. self._handler_memory = {} self._channels = {} self._sr = StateResolver() self._sensorDao = Sensors() self._sensors = self._sensorDao.findSensors() self._warned = [] def __del__(self): self._port.close() super(ZigBeeDirect, self).__del__() @property def channels(self): if self._channels == None: self._channels = {} return self._channels def start(self): print "Started polling directly connected zigBee sensors" self._addPollingProcessor('zigBeeDirect', self.pollZigbeeSensors, None, 0.1) def stop(self): print "Stopped polling directly connected zigBee sensors" self._removePollingProcessor('zigBeeDirect') # ZigBee thread main loop def pollZigbeeSensors(self): """ Read the data from the Zigbee sensors directly connected to this machine """ try: #data, _ = self._xbee.wait_read_frame() data = self._zigbee.wait_read_frame() except Exception as e: if id(self) + type(e) not in self._warned: print >> sys.stderr, "Error while receiving data from ZigBeeDirect: %s" % e self._warned.append(id(self) + type(e)) return if data["id"] == "rx_explicit": mac = repr(data['source_addr_long']).replace('\\x', ':').strip(":'").lower() # If NI (Network Id)recognised include NI string in returned values try: channels = self._zigbee._parse_samples(data['rf_data'])[0] # Parse IO data except Exception as e: print >> sys.stderr, "Error reading zigbee data: %s" % e return for channel, _value in channels.items(): channel = "!" + channel.lower() try: sensor = next(s for s in self._sensors if s['ChannelDescriptor'] == str(mac) + str(channel)) except StopIteration: # Only warn once, or we'll flood the console if str(mac) + str(channel) not in self._warned: print "Warning: Unable to locate sensor record for ZigBee sensor ID: %s" % (str(mac) + str(channel)) self._warned.append(str(mac) + str(channel)) continue _device = sensor['locationName'] _pin = sensor['name'] _id = sensor['sensorId'] _rule = sensor['sensorRule'] _value = _valueHelper.filterValue(_value, sensor['sensorTypeName']) if _value != None: _type = sensor['sensorTypeName'] _uuid = '%s_%s' % (mac , channel) _status = self._sr.getDisplayState({'sensorTypeName': _type, 'value': _value, 'sensorId': _id, 'sensorRule': _rule }) self._channels[_uuid] = { 'id': _id, 'room': _device, 'channel': _pin, 'value': _value, 'status': _status }
class ZWaveVeraLite(PollingProcessor): # Initialisation method # Opens the configured UDP socket for the receipt of broadcast messages. def __init__ (self, ipAddress, port): super(ZWaveVeraLite, self).__init__() self._loadTime = None self._dataVersion = None self._baseUrl = "http://%(ip)s:%(port)s/data_request?id=lu_sdata&timeout=%(timeout)s" % {'ip': ipAddress, 'port': port, 'timeout': 60} # Place for the callback methods to store "static" values. # Currently only needed for the Moving Average Filter for the MCP9700 # temperature sensor temperature calculations. self._handler_memory = {} self._channels = {} self._sr = StateResolver() self._sensorDao = Sensors() self._sensors = self._sensorDao.findSensors() self._warned = [] @property def channels(self): if self._channels == None: self._channels = {} return self._channels def start(self): print "Started polling zwave sensors" self._addPollingProcessor('zwave', self.pollZWaveSensors, None, 0.1) def stop(self): print "Stopped polling zwave sensors" self._removePollingProcessor('zwave') # ZigBee thread main loop def pollZWaveSensors(self): """ Check the http api for sensors & values and add them to the channels list in the standard format """ """ first iteration pulls all data, subsequent loops pull only changed data since the last run """ try: # http://192.168.1.158:3480/data_request?id=lu_sdata # http://192.168.1.158:3480/data_request?id=lu_sdata&loadtime=1282441735&dataversion=441736333&timeout=60 url = self._baseUrl if self._loadTime != None and self._dataVersion != None: url += '&loadtime=%(load)s&dataversion=(dataversion)s' % {'load': self._loadTime, 'dataversion': self._dataVersion } data = json.load(urllib2.urlopen(url)) except Exception as e: if id(self) + type(e) not in self._warned: print >> sys.stderr, "Error while receiving data from ZWaveVeraLite: %s" % e self._warned.append(id(self) + type(e)) return self._loadTime = data['loadtime'] self._dataVersion = data['dataversion'] for device in data['devices']: channelDescriptor = 'zwave:' + str(device['id']) try: sensor = next(s for s in self._sensors if s['ChannelDescriptor'] == channelDescriptor) except StopIteration: # Only warn once, or we'll flood the console if channelDescriptor not in self._warned: print "Warning: Unable to locate sensor record for ZWave sensor ID: %s (%s)" % (str(channelDescriptor), str(device['name'])) self._warned.append(channelDescriptor) continue _device = sensor['locationName'] _pin = sensor['name'] _id = sensor['sensorId'] _rule = sensor['sensorRule'] valueKeys = ['armed', 'status'] _value = None for valueKey in valueKeys: if device.has_key(valueKey): _value = device[valueKey] break _value = _valueHelper.filterValue(_value, sensor['sensorTypeName']) if _value != None: _type = sensor['sensorTypeName'] _uuid = channelDescriptor _status = self._sr.getDisplayState({'sensorTypeName': _type, 'value': _value, 'sensorId': _id, 'sensorRule': _rule }) self._channels[_uuid] = { 'id': _id, 'room': _device, 'channel': _pin, 'value': _value, 'status': _status }
class ZWaveVeraLite(PollingProcessor): # Initialisation method # Opens the configured UDP socket for the receipt of broadcast messages. def __init__ (self, ipAddress, port): super(ZWaveVeraLite, self).__init__() self._loadTime = None self._dataVersion = None self._baseUrl = "http://%(ip)s:%(port)s/data_request?id=lu_sdata&timeout=%(timeout)s" % {'ip': ipAddress, 'port': port, 'timeout': 60} # Place for the callback methods to store "static" values. # Currently only needed for the Moving Average Filter for the MCP9700 # temperature sensor temperature calculations. self._handler_memory = {} self._channels = {} self._sr = StateResolver() self._sensorDao = Sensors() self._sensors = self._sensorDao.findSensors() self._warned = [] @property def channels(self): if self._channels == None: self._channels = {} return self._channels def start(self): print "Started polling zwave sensors" self._addPollingProcessor('zwave', self.pollZWaveSensors, None, 0.1) def stop(self): print "Stopped polling zwave sensors" self._removePollingProcessor('zwave') # ZigBee thread main loop def pollZWaveSensors(self): try: # http://192.168.1.158:3480/data_request?id=lu_sdata # http://192.168.1.158:3480/data_request?id=lu_sdata&loadtime=1282441735&dataversion=441736333&timeout=60 url = self._baseUrl if self._loadTime != None and self._dataVersion != None: url += '&loadtime=%(load)s&dataversion=(dataversion)s' % {'load': self._loadTime, 'dataversion': self._dataVersion } data = json.load(urllib2.urlopen(url)) except Exception as e: if type(e) != timeout: print e return self._loadTime = data['loadtime'] self._dataVersion = data['dataversion'] for device in data['devices']: channelDescriptor = 'zwave:' + str(device['id']) try: sensor = next(s for s in self._sensors if s['ChannelDescriptor'] == channelDescriptor) except StopIteration: # Only warn once, or we'll flood the console if channelDescriptor not in self._warned: print >> sys.stderr, "Warning: Unable to locate sensor record for zwave sensor ID: %s (%s)" % (str(channelDescriptor), str(device['name'])) self._warned.append(channelDescriptor) continue _device = sensor['locationName'] _pin = sensor['name'] _id = sensor['sensorId'] valueKeys = ['armed', 'status'] val = '' for valueKey in valueKeys: if device.has_key(valueKey): val = device[valueKey] break if val != '-' and val != '': _type = sensor['sensorTypeName'] _uuid = channelDescriptor if _type == 'TEMPERATURE_MCP9700_HOT' or _type == 'TEMPERATURE_MCP9700_COLD': _value = str((float(val) - 0.5) * 100.0) else: _value = val _status = self._sr.getDisplayState({'sensorTypeName': _type, 'value': _value, 'sensorId': _id }) self._channels[_uuid] = { 'id': _id, 'room': _device, 'channel': _pin, 'value': _value, 'status': _status }
class ROSLocationProcessor(PollingProcessor): """Abstract location processor, current concrete implementations are Human and Robot processors""" def __init__(self): super(ROSLocationProcessor, self).__init__() self._lastSensors = {} self._lastLocations = {} self._sensors = Sensors() self._locations = Locations() self._ros = ROS() def start(self): print "Started polling uh locations" self._addPollingProcessor('location_publish', self.checkUpdateLocations, (), 0.1) self._addPollingProcessor('sensor_publish', self.checkUpdateSensors, (), 0.1) def stop(self): print "Stopped polling uh locations" self._removePollingProcessor('location_publish') self._removePollingProcessor('sensor_publish') def checkUpdateLocations(self): locationData = self._locations.findLocations() locations = {} for location in locationData: locationParam = { 'id': location['locationId'], 'text': location['name'] or '', 'color': {'r': float(not location['ValidRobotLocation'] and not location['ValidUserLocation']), 'g': float(location['ValidRobotLocation'] or 0), 'b': float(location['ValidUserLocation'] or 0), 'a': 1.0} } if location.get('xCoord', None) is not None: locationParam.setdefault('position', {}) locationParam['position']['x'] = location.get('xCoord') if location.get('yCoord', None) is not None: locationParam.setdefault('position', {}) locationParam['position']['y'] = location.get('yCoord') if location.get('zCoord', None) is not None: locationParam.setdefault('position', {}) locationParam['position']['z'] = location.get('zCoord') if location.get('orientation', None) is not None: locationParam.setdefault('orientation', {}) locationParam['orientation']['theta'] = math.radians(location['orientation']) locations[locationParam['id']] = locationParam if self._lastLocations != locations: self._lastLocations = locations self._ros.setParam('location_data', locations.values()) def checkUpdateSensors(self): sensorData = self._sensors.findSensors() sensors = {} for sensor in sensorData: sensorParam = { 'id': sensor['sensorId'], 'text': sensor['name'] or '', 'model': sensor['iconName'] or '', 'color': {'r': 0, 'g': 0, 'b': 0, 'a': 0} } if sensor.get('xCoord', None) is not None: sensorParam.setdefault('position', {}) sensorParam['position']['x'] = sensor.get('xCoord') if sensor.get('yCoord', None) is not None: sensorParam.setdefault('position', {}) sensorParam['position']['y'] = sensor.get('yCoord') if sensor.get('zCoord', None) is not None: sensorParam.setdefault('position', {}) sensorParam['position']['z'] = sensor.get('zCoord') if sensor['orientation'] is not None: sensorParam.setdefault('orientation', {}) sensorParam['orientation']['theta'] = math.radians(sensor['orientation']) if sensor['isActive']: sensorParam['color']['r'] = 0 sensorParam['color']['g'] = 1.0 sensorParam['color']['b'] = 0 sensorParam['color']['a'] = 1.0 if sensor['xCoord'] is None and sensor['yCoord'] is None: sensorParam['position']['z'] = -1 sensors[sensorParam['id']] = sensorParam if self._lastSensors != sensors: self._lastSensors = sensors self._ros.setParam('sensor_data', sensors.values())
class ZigBee(PollingProcessor): # Initialisation method # Opens the configured UDP socket for the receipt of broadcast messages. def __init__(self, udpPort): super(ZigBee, self).__init__() self.sock = socket(AF_INET, SOCK_DGRAM) self.sock.settimeout(1) self.sock.bind(('', udpPort)) # Place for the callback methods to store "static" values. # Currently only needed for the Moving Average Filter for the MCP9700 # temperature sensor temperature calculations. self._handler_memory = {} self._channels = {} self._sr = StateResolver() self._sensorDao = Sensors() self._sensors = self._sensorDao.findSensors() self._warned = [] self._connected = [] @property def channels(self): if self._channels is None: self._channels = {} return self._channels def start(self): print "Started polling zigBee sensors" self._addPollingProcessor('zigBee', self.pollZigbeeSensors, None, 0.0001) def stop(self): print "Stopped polling zigBee sensors" self._removePollingProcessor('zigBee') # ZigBee thread main loop def pollZigbeeSensors(self): """ Check the read sensors & values from the zigbee UDP broadcast and add them to the channels list in the standard format """ try: data, _ = self.sock.recvfrom(10240, 0) except Exception as e: if type(e) != timeout: print e return (_, mac, channel, _value) = data.split(' ') mac = mac.lower() channel = channel.upper() try: sensor = next(s for s in self._sensors if s['ChannelDescriptor'] == str(mac) + str(channel)) except StopIteration: # Only warn once, or we'll flood the console if str(mac) + str(channel) not in self._warned: print "Warning: Unable to locate sensor record for ZigBee sensor ID: %s" % (str(mac) + str(channel)) self._warned.append(str(mac) + str(channel)) return if sensor['ChannelDescriptor'] not in self._connected: print "Connected to %s sensor %s on %s" % (self.__class__.__name__, sensor['name'], sensor['ChannelDescriptor']) self._connected.append(sensor['ChannelDescriptor']) _device = sensor['locationName'] _pin = sensor['name'] _id = sensor['sensorId'] _rule = sensor['sensorRule'] _value = _valueHelper.filterValue(_value, sensor['sensorTypeName']) if _value is not None: _type = sensor['sensorTypeName'] _uuid = '%s_%s' % (mac, channel) _status = self._sr.getDisplayState({'sensorTypeName': _type, 'value': _value, 'sensorId': _id, 'sensorRule': _rule}) self._channels[_uuid] = { 'id': _id, 'room': _device, 'channel': _pin, 'value': _value, 'status': _status }