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 = []
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 = []
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 = []
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'
def __init__(self): super(ROSLocationProcessor, self).__init__() self._lastSensors = {} self._lastLocations = {} self._sensors = Sensors() self._locations = Locations() self._ros = ROS()
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 }
def __init__(self, robot=None): super(PoseUpdater, self).__init__() if robot == None: robot = CareOBot() self._robot = robot self._ros = rosHelper.ROS() self._sensors = Sensors().findSensors() self._channels = {} self._warned = []
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'
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 = []
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 = []
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 __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 = []
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 = []
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 = []
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 __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 = []
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 }
def __init__(self): self._dao = Sensors() self._sr = StateResolver()
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 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 MapProcessor(object): """ Used to build the live image of the sensor network """ _mapCache = {} _iconCache = {} _mapLock = RLock() _iconLock = RLock() def __init__(self, _map): self._root = os.path.dirname(os.path.realpath(__file__)) self._baseFile = os.path.join(self._root, _map["base"]) self._map = _map self._sensorTypes = {} self._dao = Sensors() @property def mapBase(self): """ Returns a copy of the base svg map file """ """ Caches initial map for fast access in subsequent calls """ if self._baseFile not in MapProcessor._mapCache: MapProcessor._mapLock.acquire() try: MapProcessor._mapCache[self._baseFile] = et.parse(self._baseFile) finally: MapProcessor._mapLock.release() return copy.deepcopy(MapProcessor._mapCache[self._baseFile]) def getIcon(self, iconId, text=None, sensorOn=False): """ Returns the sensor icon (with option 'On' graphic') wrapped in a group node """ """ Caches icon for fast access in subsequent calls """ key = str(iconId) + str(sensorOn) if key not in MapProcessor._iconCache: MapProcessor._iconLock.acquire() try: if iconId not in self._sensorTypes: self._sensorTypes[iconId] = self._dao.getSensorIcon(iconId) sensorDef = self._sensorTypes[iconId] imgFile = None imgPath = None imgName = None if sensorDef is not None: imgName = sensorDef["name"] if sensorDef["icon"] is not None: if sensorOn: imgPath = sensorDef["icon"] + "_on" + ".svg" else: imgPath = sensorDef["icon"] + ".svg" try: imgFile = et.parse(os.path.join(self._root, imgPath)) except Exception as e: if sensorOn: print >> sys.stderr, "Error parsing sensor image (%(path)s): %(error)s" % { "error": e, "path": imgPath, } if imgFile is None: if imgPath is not None: print "Unable to load image from %(path)s, using default" % {"path": imgPath} else: print "Unable to load image for %(type)s, using default" % {"type": imgName} imgPath = "icons/default.svg" imgFile = et.parse(os.path.join(self._root, imgPath)) imgFile.find("{http://www.w3.org/2000/svg}text").text = text or imgName or imgPath if sys.version_info >= (2, 7): group = et.Element("g") else: group = et.Element("ns0:g") for child in imgFile.getroot().getchildren(): group.append(et.fromstring(et.tostring(child))) height = float(imgFile.getroot().get("height", 0)) width = float(imgFile.getroot().get("width", 0)) MapProcessor._iconCache[key] = (group, height, width) finally: MapProcessor._iconLock.release() return copy.deepcopy(MapProcessor._iconCache[key]) def buildMap(self, elements=[]): """elements=[{'state':'on', 'location':{'xCoord':2.3, 'yCoord':9.2', 'orientation':3.141}, 'id':12]""" """state must match from the sensor state=>sensor Icon mapping""" """state can be empty or missing to use a stateless icon""" """x and y are in meters""" """orientation is assumed in radians, use d or r suffix to use others (90d/6R)""" # TODO: when map is clicked, show RH coords if sys.version_info >= (2, 7): et.register_namespace("", "http://www.w3.org/2000/svg") root = self.mapBase.getroot() mapHeight = float(root.attrib["height"]) cc = CoordinateConvertor(self._map) for element in elements: try: if element["on"] is None: state = False else: state = element["on"] except: state = False (x, y, d) = cc.toScaled((element["xCoord"], element["yCoord"], element["orientation"])) (img, height, width) = self.getIcon(element["icon"], element["name"], state) # svg y is from bottom corner My = mapHeight - y # be sure to translate first, which changes the local coordinate space to the group object # which is important for the rotation about the center transform = "translate(%(x)s, %(y)s) rotate(%(rotate)s, %(xCenter)s, %(yCenter)s)" % { "x": x, "y": My, "rotate": d, "xCenter": 0, "yCenter": 0, } img.attrib["transform"] = transform img.attrib["id"] = str(element["id"]) img.attrib["name"] = str(element["name"]) root.append(img) # ElementTree.write() doesn't write the headers f = io.BytesIO() f.write('<?xml version="1.0" standalone="no"?>\n') f.write('<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">\n') if sys.version_info >= (2, 7): f.write(et.tostring(root)) else: f.write(et.tostring(root).replace("ns0:", "").replace(":ns0", "")) ret = f.getvalue() f.close() return ret
def __init__(self, _map): self._root = os.path.dirname(os.path.realpath(__file__)) self._baseFile = os.path.join(self._root, _map['base']) self._map = _map self._sensorTypes = {} self._dao = Sensors()
class MapProcessor(object): """ Used to build the live image of the sensor network """ _mapCache = {} _iconCache = {} _mapLock = RLock() _iconLock = RLock() def __init__(self, _map): self._root = os.path.dirname(os.path.realpath(__file__)) self._baseFile = os.path.join(self._root, _map['base']) self._map = _map self._sensorTypes = {} self._dao = Sensors() @property def mapBase(self): """ Returns a copy of the base svg map file """ """ Caches initial map for fast access in subsequent calls """ if not MapProcessor._mapCache.has_key(self._baseFile): MapProcessor._mapLock.acquire() try: MapProcessor._mapCache[self._baseFile] = et.parse( self._baseFile) finally: MapProcessor._mapLock.release() return copy.deepcopy(MapProcessor._mapCache[self._baseFile]) def getIcon(self, iconId, sensorOn=False): """ Returns the sensor icon (with option 'On' graphic') wrapped in a group node """ """ Caches icon for fast access in subsequent calls """ key = str(iconId) + str(sensorOn) if not MapProcessor._iconCache.has_key(key): MapProcessor._iconLock.acquire() try: if not self._sensorTypes.has_key(iconId): self._sensorTypes[iconId] = self._dao.getSensorIcon(iconId) sensorDef = self._sensorTypes[iconId] imgFile = None imgPath = None imgName = None if sensorDef != None: imgName = sensorDef['name'] if sensorDef['icon'] != None: if sensorOn: imgPath = sensorDef['icon'] + '_on' + ".svg" else: imgPath = sensorDef['icon'] + ".svg" try: imgFile = et.parse( os.path.join(self._root, imgPath)) except Exception as e: if sensorOn: print >> sys.stderr, "Error parsing sensor image (%(path)s): %(error)s" % { 'error': e, 'path': imgPath } if imgFile == None: if imgPath != None: print "Unable to load image from %(path)s, using default" % { 'path': imgPath } else: print "Unable to load image for %(type)s, using default" % { 'type': imgName } imgPath = 'icons/default.svg' imgFile = et.parse(os.path.join(self._root, imgPath)) imgFile.find( '{http://www.w3.org/2000/svg}text').text = imgName if sys.version_info >= (2, 7): group = et.Element('g') else: group = et.Element('ns0:g') for child in imgFile.getroot().getchildren(): group.append(et.fromstring(et.tostring(child))) height = float(imgFile.getroot().get('height', 0)) width = float(imgFile.getroot().get('width', 0)) MapProcessor._iconCache[key] = (group, height, width) finally: MapProcessor._iconLock.release() return copy.deepcopy(MapProcessor._iconCache[key]) def buildMap(self, elements=[]): """elements=[{'state':'on', 'location':{'xCoord':2.3, 'yCoord':9.2', 'orientation':3.141}, 'id':12]""" """state must match from the sensor state=>sensor Icon mapping""" """state can be empty or missing to use a stateless icon""" """x and y are in meters""" """orientation is assumed in radians, use d or r suffix to use others (90d/6R)""" # TODO: when map is clicked, show RH coords if sys.version_info >= (2, 7): et.register_namespace("", "http://www.w3.org/2000/svg") root = self.mapBase.getroot() mapHeight = float(root.attrib['height']) cc = CoordinateConvertor(self._map) for element in elements: try: if element['on'] == None: state = False else: state = element['on'] except: state = False (x, y, d) = cc.toSensorMap( (element['xCoord'], element['yCoord'], element['orientation'])) (img, height, width) = self.getIcon(element['icon'], state) # y is reversed for translation, seems that way at least My = mapHeight - y # be sure to translate first, which changes the local coordinate space to the group object # which is important for the rotation about the centre transform = "translate(%(x)s, %(y)s) rotate(%(rotate)s, %(xCenter)s, %(yCenter)s)" % { 'x': x, 'y': My, 'rotate': d, 'xCenter': (width / 2), 'yCenter': (height / 2) } img.attrib['transform'] = transform img.attrib['id'] = str(element['id']) root.append(img) # ElementTree.write() doesn't write the headers f = io.BytesIO() f.write('<?xml version=\"1.0\" standalone=\"no\"?>\n') f.write( '<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n' ) if sys.version_info >= (2, 7): f.write(et.tostring(root)) else: f.write(et.tostring(root).replace('ns0:', '').replace(':ns0', '')) ret = f.getvalue() f.close() return ret
class actuators(): def __init__ (self): self._env = Environment(self._setup_switch) self._sensors = Sensors() def _setup_switch(self,switch): print "Switch found!", switch.name def start(self): self._env.start() def _getName(self): sensorName=self._env.list_switches() return sensorName[0] def _getNameList(self): sensorNameList=self._env.list_switches() return sensorNameList def _getIdFromName(self, name): if name=='Lamp01': idSensor='91' elif name=='LivingRoomLamp': idSensor='92' elif name=='KitchenCoffeMachine': idSensor='93' elif name=='LivingRoomTV': idSensor='94' else: idSensor=null return idSensor def _getValue(self, name): if name=='Lamp01': idSensor='91' elif name=='LivingRoomLamp': idSensor='92' elif name=='KitchenCoffeMachine': idSensor='93' elif name=='LivingRoomTV': idSensor='94' else: idSensor=null return self._sensors.getSensor(idSensor) def _get_switch(self, name): return self._env.get_switch(name) def _on_switch(self, switch): switch.basicevent.SetBinaryState(BinaryState=1) def _off_switch(self, switch): switch.basicevent.SetBinaryState(BinaryState=0) def setOn(self, name): self._sensors.updateSensor(self._getIdFromName(name), 1.0, 'On') print " %s has been switched On" % name def setOff(self, name): self._sensors.updateSensor(self._getIdFromName(name), 0.0, 'Off') print " %s has been switched Off" % name
def __init__ (self): self._env = Environment(self._setup_switch) self._sensors = Sensors()
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 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 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 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 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 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 }
def __init__(self, robot): super(PoseUpdater, self).__init__() self._robot = robot self._sensors = Sensors().findSensors(None, False) self._channels = {} self._warned = []
class MapProcessor(object): """ Used to build the live image of the sensor network """ _mapCache = {} _iconCache = {} _mapLock = RLock() _iconLock = RLock() def __init__(self, _map): self._root = os.path.dirname(os.path.realpath(__file__)) self._baseFile = os.path.join(self._root, _map['base']) self._map = _map self._sensorTypes = {} self._dao = Sensors() @property def mapBase(self): """ Returns a copy of the base svg map file """ """ Caches initial map for fast access in subsequent calls """ if not MapProcessor._mapCache.has_key(self._baseFile): MapProcessor._mapLock.acquire() try: MapProcessor._mapCache[self._baseFile] = et.parse(self._baseFile) finally: MapProcessor._mapLock.release() return copy.deepcopy(MapProcessor._mapCache[self._baseFile]) def getIcon(self, iconId, sensorOn=False): """ Returns the sensor icon (with option 'On' graphic') wrapped in a group node """ """ Caches icon for fast access in subsequent calls """ key = str(iconId) + str(sensorOn) if not MapProcessor._iconCache.has_key(key): MapProcessor._iconLock.acquire() try: if not self._sensorTypes.has_key(iconId): self._sensorTypes[iconId] = self._dao.getSensorIcon(iconId) sensorDef = self._sensorTypes[iconId] imgFile = None imgPath = None imgName = None if sensorDef != None: imgName = sensorDef['name'] if sensorDef['icon'] != None: if sensorOn: imgPath = sensorDef['icon'] + '_on' + ".svg" else: imgPath = sensorDef['icon'] + ".svg" try: imgFile = et.parse(os.path.join(self._root, imgPath)) except Exception as e: if sensorOn: print >> sys.stderr, "Error parsing sensor image (%(path)s): %(error)s" % {'error' :e, 'path': imgPath } if imgFile == None: if imgPath != None: print "Unable to load image from %(path)s, using default" % {'path' : imgPath } else: print "Unable to load image for %(type)s, using default" % {'type': imgName } imgPath = 'icons/default.svg' imgFile = et.parse(os.path.join(self._root, imgPath)) imgFile.find('{http://www.w3.org/2000/svg}text').text = imgName if sys.version_info >= (2, 7): group = et.Element('g') else: group = et.Element('ns0:g') for child in imgFile.getroot().getchildren(): group.append(et.fromstring(et.tostring(child))) height = float(imgFile.getroot().get('height', 0)) width = float(imgFile.getroot().get('width', 0)) MapProcessor._iconCache[key] = (group, height, width) finally: MapProcessor._iconLock.release() return copy.deepcopy(MapProcessor._iconCache[key]) def buildMap(self, elements=[]): """elements=[{'state':'on', 'location':{'xCoord':2.3, 'yCoord':9.2', 'orientation':3.141}, 'id':12]""" """state must match from the sensor state=>sensor Icon mapping""" """state can be empty or missing to use a stateless icon""" """x and y are in meters""" """orientation is assumed in radians, use d or r suffix to use others (90d/6R)""" # TODO: when map is clicked, show RH coords if sys.version_info >= (2, 7): et.register_namespace("", "http://www.w3.org/2000/svg") root = self.mapBase.getroot() mapHeight = float(root.attrib['height']) cc = CoordinateConvertor(self._map) for element in elements: try: if element['on'] == None: state = False else: state = element['on'] except: state = False (x, y, d) = cc.toSensorMap((element['xCoord'], element['yCoord'], element['orientation'])) (img, height, width) = self.getIcon(element['icon'], state) # y is reversed for translation, seems that way at least My = mapHeight - y # be sure to translate first, which changes the local coordinate space to the group object # which is important for the rotation about the centre transform = "translate(%(x)s, %(y)s) rotate(%(rotate)s, %(xCenter)s, %(yCenter)s)" % { 'x': x, 'y': My, 'rotate': d, 'xCenter': (width / 2), 'yCenter': (height / 2) } img.attrib['transform'] = transform img.attrib['id'] = str(element['id']) root.append(img) # ElementTree.write() doesn't write the headers f = io.BytesIO() f.write('<?xml version=\"1.0\" standalone=\"no\"?>\n') f.write('<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n') if sys.version_info >= (2, 7): f.write(et.tostring(root)) else: f.write(et.tostring(root).replace('ns0:', '').replace(':ns0', '')) ret = f.getvalue() f.close() return ret
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 }