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 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 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