def __init__(self, settings=None, verbose=False, monitor=False): """ Class constructor @param settings: path to the main configuration file @param verbose: Print out SWAP frames or not @param monitor: Print out network events or not """ try: # Superclass call SwapInterface.__init__(self, settings, verbose) except: raise # Print SWAP activity self._printSWAP = monitor # Mote address in SYNC mode self._addrInSyncMode = None # Read plugin config self._readPluginConfig() # Declare HouseAgent callbacks callbacks = {'poweron': self.cb_poweron, 'poweroff': self.cb_poweroff, 'custom': self.cb_custom, 'thermostat_setpoint': self.cb_thermostat} # Start plugin self._pluginapi = PluginAPI(guid=self.pluginId, plugintype="SWAP", broker_host=self.broker_host, broker_port=self.broker_port, **callbacks) self._pluginapi.ready() reactor.run()
def __init__(self): ''' Load initial CM11 configuration from hacm11.conf ''' from utils.generic import get_configurationpath self.config_path = get_configurationpath() config = ConfigParser.RawConfigParser() config.read(os.path.join(self.config_path, 'hacm11.conf')) print "DEBUG: get_configurationpath: ", self.config_path print "DEBUG: os.getcwd: ", os.getcwd( ) print "DEBUG: sys.path:", sys.path # Get serial port information self.port = config.get("serial", "port") # Get broker information (RabbitMQ) self.broker_host = config.get("broker", "host") self.broker_port = config.getint("broker", "port") self.broker_user = config.get("broker", "username") self.broker_pass = config.get("broker", "password") self.broker_vhost = config.get("broker", "vhost") self.logging = config.getboolean('general', 'logging') self.id = config.get('general', 'id') self.pluginapi = PluginAPI(plugin_id=self.id, plugin_type='x10', logging=self.logging, broker_ip=self.broker_host, broker_port=self.broker_port, username=self.broker_user, password=self.broker_pass, vhost=self.broker_vhost) self.pluginapi.register_poweron(self) self.pluginapi.register_poweroff(self) self.pluginapi.register_dim(self) self.pluginapi.register_custom(self) self.protocol = CM11Protocol(self) self.reactor = None # Initialize in-memory device list from xml file xml_file = os.path.join(self.config_path, 'x10.xml') try: xmldoc = ET.parse(xml_file) devices = xmldoc.findall('device') for device in devices: newdevice = Device(device.get('hcdc')) newdevice.standarddim = (device.findtext('standarddim', 'False').lower() == "true") newdevice.presetdim = (device.findtext('presetdim', 'False').lower() == "true") newdevice.allunitsoff = (device.findtext('allunitsoff', 'False').lower() == "true") newdevice.alllightsoff = (device.findtext('alllightsoff', 'False').lower() == "true") newdevice.alllightson = (device.findtext('alllightson', 'False').lower() == "true") newdevice.statusrequest = (device.findtext('statusrequest','False').lower() == "true") newdevice.reportstatus = (device.findtext('reportstatus','False').lower() == "true") listDevices.append(newdevice) except: log.msg("Error opening or reading '%s' (%s)" % (xml_file, sys.exc_info()[1]))
def __init__(self, settings=None, verbose=False, monitor=False): """ Class constructor @param settings: path to the main configuration file @param verbose: Print out SWAP frames or not @param monitor: Print out network events or not """ try: # Superclass call SwapInterface.__init__(self, settings, verbose) except: raise # Print SWAP activity self._printSWAP = monitor # Mote address in SYNC mode self._addrInSyncMode = None # Read plugin config self._readPluginConfig() # Declare HouseAgent callbacks callbacks = { 'poweron': self.cb_poweron, 'poweroff': self.cb_poweroff, 'custom': self.cb_custom, 'thermostat_setpoint': self.cb_thermostat } # Start plugin self._pluginapi = PluginAPI(guid=self.pluginId, plugintype="SWAP", broker_host=self.broker_host, broker_port=self.broker_port, **callbacks) self._pluginapi.ready() reactor.run()
class CM11Wrapper(): def __init__(self): ''' Load initial CM11 configuration from hacm11.conf ''' from utils.generic import get_configurationpath self.config_path = get_configurationpath() config = ConfigParser.RawConfigParser() config.read(os.path.join(self.config_path, 'hacm11.conf')) print "DEBUG: get_configurationpath: ", self.config_path print "DEBUG: os.getcwd: ", os.getcwd( ) print "DEBUG: sys.path:", sys.path # Get serial port information self.port = config.get("serial", "port") # Get broker information (RabbitMQ) self.broker_host = config.get("broker", "host") self.broker_port = config.getint("broker", "port") self.broker_user = config.get("broker", "username") self.broker_pass = config.get("broker", "password") self.broker_vhost = config.get("broker", "vhost") self.logging = config.getboolean('general', 'logging') self.id = config.get('general', 'id') self.pluginapi = PluginAPI(plugin_id=self.id, plugin_type='x10', logging=self.logging, broker_ip=self.broker_host, broker_port=self.broker_port, username=self.broker_user, password=self.broker_pass, vhost=self.broker_vhost) self.pluginapi.register_poweron(self) self.pluginapi.register_poweroff(self) self.pluginapi.register_dim(self) self.pluginapi.register_custom(self) self.protocol = CM11Protocol(self) self.reactor = None # Initialize in-memory device list from xml file xml_file = os.path.join(self.config_path, 'x10.xml') try: xmldoc = ET.parse(xml_file) devices = xmldoc.findall('device') for device in devices: newdevice = Device(device.get('hcdc')) newdevice.standarddim = (device.findtext('standarddim', 'False').lower() == "true") newdevice.presetdim = (device.findtext('presetdim', 'False').lower() == "true") newdevice.allunitsoff = (device.findtext('allunitsoff', 'False').lower() == "true") newdevice.alllightsoff = (device.findtext('alllightsoff', 'False').lower() == "true") newdevice.alllightson = (device.findtext('alllightson', 'False').lower() == "true") newdevice.statusrequest = (device.findtext('statusrequest','False').lower() == "true") newdevice.reportstatus = (device.findtext('reportstatus','False').lower() == "true") listDevices.append(newdevice) except: log.msg("Error opening or reading '%s' (%s)" % (xml_file, sys.exc_info()[1])) #device = next((device for device in listDevices if device.hcdc == 'M5'), None) #index = next((i for i in xrange(len(listDevices)) if listDevices[i].hcdc == 'M5'), None) #if index is not None: # print listDevices[index].hcdc # device = listDevices.pop(index) # print "HCDC: ", device.hcdc # print "allunitsoff: ", device.allunitsoff def start(self): ''' Function that starts the CM11 plug-in. It handles the creation of the plugin connection and connects to the specified serial port. ''' #FIXME: Error when serial port does not exist or cannot be opened try: myserial = SerialPort (self.protocol, self.port, reactor) myserial.setBaudRate(4800) self.reactor = reactor reactor.run(installSignalHandlers=0) return(True) except: log.msg("Error opening serial port %s (%s)" % (self.port, sys.exc_info()[1])) return(False) def on_poweron(self, hcdc): log.msg("Turn %s on" % hcdc) self.protocol.poweron(hcdc) return {'processed': True} def on_poweroff(self, hcdc): log.msg("Turn %s off" % hcdc) self.protocol.poweroff(hcdc) return {'processed': True} def on_dim(self, hcdc, level): log.msg("Dim %s to %s%%" % (hcdc, level)) self.protocol.dim(hcdc, level) return {'processed': True} def on_custom(self, command, parameters): """ Handles several custom actions used througout the plugin. """ log.msg("on_custom event received") if command == 'add_characteristics': ''' This command sets the characteristics of a new X10 device and starts monitoring it. ''' newdevice = Device(parameters["hcdc"]) for value in parameters["values"]: if value == "alllightsoff": newdevice.alllightsoff = True elif value == "alllightson": newdevice.alllightson = True elif value == "allunitsoff": newdevice.allunitsoff = True elif value == "presetdim": newdevice.presetdim = True elif value == "standarddim": newdevice.standarddim = True elif value == "statusrequest": newdevice.statusrequest = True elif value == "reportstatus": newdevice.reportstatus = True else: log.msg("Unknown characteristic (%s)" % value) listDevices.append(newdevice) log.msg("Monitoring new device (%s)" % newdevice.hcdc) self.writeXML() elif command == 'set_characteristics': ''' This command sets the characteristics of the specified X10 device. ''' item = next((i for i in xrange(len(listDevices)) if listDevices[i].hcdc == parameters["hcdc"]), None) if item is not None: listDevices[item].alllightsoff = False listDevices[item].alllightson = False listDevices[item].allunitsoff = False listDevices[item].presetdim = False listDevices[item].standarddim = False listDevices[item].statusrequest = False listDevices[item].reportstatus = False for value in parameters["values"]: if value == "alllightsoff": listDevices[item].alllightsoff = True if value == "alllightson": listDevices[item].alllightson = True if value == "allunitsoff": listDevices[item].allunitsoff = True if value == "presetdim": listDevices[item].presetdim = True if value == "standarddim": listDevices[item].standarddim = True if value == "statusrequest": listDevices[item].statusrequest = True if value == "reportstatus": listDevices[item].reportstatus = True else: log.msg("Unknown device specified (%s)" % parameters["hcdc"]) log.msg("Characteristics of device (%s) are changed" % parameters["hcdc"]) self.writeXML() elif command == 'get_characteristics': ''' This command retrieves the characteristics of the specified X10 device. ''' item = next((i for i in xrange(len(listDevices)) if listDevices[i].hcdc == parameters["hcdc"]), None) if item is None: log.msg("Error: Retrieved device characteristics of a device not being monitored.") else: return({"alllightsoff": listDevices[item].alllightsoff, "allunitsoff": listDevices[item].allunitsoff, "alllightson": listDevices[item].alllightson, "standarddim": listDevices[item].standarddim, "presetdim": listDevices[item].presetdim, "statusrequest": listDevices[item].statusrequest, "reportstatus": listDevices[item].reportstatus}) elif command == 'del_characteristics': ''' This command stops monitoring of the specified X10 device. ''' item = next((i for i in xrange(len(listDevices)) if listDevices[i].hcdc == parameters["hcdc"]), None) if item is not None: log.msg("Stopped monitoring X10 device (%s)" % parameters["hcdc"]) del listDevices[item] # Write XML file containing details of monitored devices self.writeXML() else: log.msg("Unknown device specified (%s)" % parameters["hcdc"]) return(None) else: log.msg("unknown command (%s)" % command) return {'processed': True} def writeXML(self): # Write device characteristics to a file xml_file = os.path.join(self.config_path, 'x10.xml') file = open(xml_file, 'w') root = ET.Element("devices") for device in listDevices: dev = ET.SubElement(root, "device", {"hcdc": device.hcdc}) char = ET.SubElement(dev, "standarddim") char.text = str(device.standarddim) char = ET.SubElement(dev, "presetdim") char.text = str(device.presetdim) char = ET.SubElement(dev, "allunitsoff") char.text = str(device.allunitsoff) char = ET.SubElement(dev, "alllightsoff") char.text = str(device.alllightsoff) char = ET.SubElement(dev, "alllightson") char.text = str(device.alllightson) char = ET.SubElement(dev, "statusrequest") char.text = str(device.statusrequest) char = ET.SubElement(dev, "reportstatus") char.text = str(device.reportstatus) # Function to indent XML output # Source: http://infix.se/2007/02/06/gentlemen-indent-your-xml def indent(elem, level=0): i = "\n" + level*" " if len(elem): if not elem.text or not elem.text.strip(): elem.text = i + " " for e in elem: indent(e, level+1) if not e.tail or not e.tail.strip(): e.tail = i + " " if not e.tail or not e.tail.strip(): e.tail = i else: if level and (not elem.tail or not elem.tail.strip()): elem.tail = i tree = ET.ElementTree(root) indent(tree.getroot()) tree.write(xml_file) file.close()
class SwapManager(SwapInterface): """ SWAP Management Class """ def newMoteDetected(self, mote): """ New mote detected by SWAP server @param mote: Mote detected """ if self._printSWAP == True: print "New mote with address " + str(mote.address) + " : " + mote.definition.product + \ " (by " + mote.definition.manufacturer + ")" def newEndpointDetected(self, endpoint): """ New endpoint detected by SWAP server @param endpoint: Endpoint detected """ if self._printSWAP == True: print "New endpoint with Reg ID = " + str( endpoint.getRegId()) + " : " + endpoint.name # Set param units for this endpoint values = self.cfgdevices.getValues(endpoint.getRegAddress()) if endpoint.name in values: endpoint.display = True if values[endpoint.name] != "": endpoint.setUnit(values[endpoint.name]) def moteStateChanged(self, mote): """ Mote state changed @param mote: Mote having changed """ if self._printSWAP == True: print "Mote with address " + str(mote.address) + " switched to \"" + \ SwapState.toString(mote.state) + "\"" # SYNC mode entered? if mote.state == SwapState.SYNC: self._addrInSyncMode = mote.address def moteAddressChanged(self, mote): """ Mote address changed @param mote: Mote having changed """ if self._printSWAP == True: print "Mote changed address to " + str(mote.address) def registerValueChanged(self, register): """ Register value changed @param register: register object having changed """ if self._printSWAP == True: print "Register addr= " + str(register.getAddress( )) + " id=" + str( register.id) + " changed to " + register.value.toAsciiHex() # Empty dictionary values = {} # For every endpoint contained in this register for endp in register.lstItems: strVal = endp.getValueInAscii() if endp.valueChanged: if self._printSWAP: print endp.name + " in address " + str( endp.getRegAddress()) + " changed to " + strVal if endp.display == True: values[endp.name] = strVal if len(values) > 0: if self._pluginapi is not None: self._pluginapi.value_update(register.getAddress(), values) def cb_poweron(self, address): """ This function is called when a poweron request has been received from the network. @param address: Address of the mote to be powered-on """ addr = int(address) d = defer.Deferred() #self.manager.setNodeOn(self.home_id, node_id) d.callback('done!') return d def cb_poweroff(self, address): """ This function is called when a poweroff request has been received from the network. @param address: Address of the mote to be powered-off """ addr = int(address) d = defer.Deferred() #self.manager.setNodeOff(self.home_id, node_id) d.callback('done!') return d def cb_thermostat(self, address, setpoint): ''' This callback function handles setting of thermostat setpoints. @param address: Address of the mote @param setpoint: the setpoint to set (float) ''' d = defer.Deferred() """ node = self.get_node(self.home_id, int(node_id)) if not isinstance(node, ZwaveNode): d.callback('error1') # Specified node not available else: for val in node.values: if val.value_data['commandClass'] == 'COMMAND_CLASS_THERMOSTAT_SETPOINT': value_id = int(val.value_data['id']) self.manager.setValue(value_id, float(setpoint)) d.callback('ok') """ return d def cb_custom(self, action, parameters): """ Handles several custom actions used througout the plugin. @param command: Custom command @param parameters: Custom command parameters @return Object requested """ if action == 'get_networkinfo': motes = {} for index, mote in enumerate(self.server.lstMotes): moteInfo = { "address": mote.address, "manufacturer": mote.definition.manufacturer, "product": mote.definition.product, "sleeping": mote.definition.pwrdownmode, "lastupdate": datetime.datetime.fromtimestamp( mote.timestamp).strftime("%d-%m-%Y %H:%M:%S") } motes[index] = moteInfo d = defer.Deferred() d.callback(motes) return d elif action == "get_motevalues": values = {} devaddress = int(parameters["mote"]) mote = self.server.getMote(address=devaddress) i = 0 for reg in mote.lstregregs: for endp in reg.lstItems: valueinfo = { "type": endp.type + " " + SwapType.toString(endp.direction), "name": endp.name, "value": endp.getValueInAscii(), "units": [], "unit": endp.unit.name } if endp.lstunits is not None and len(endp.lstunits) > 0: for unit in endp.lstunits: valueinfo["units"].append(unit.name) values[i] = valueinfo i += 1 d = defer.Deferred() d.callback(values) return d elif action == "track_values": ''' With this command you can set certain SWAP values to be tracked, and send them to the master node. ''' address = parameters['mote'] values = parameters['values'] self.cfgdevices.setValues(address, values) # Save config file self.cfgdevices.save() # Set units mote = self.getMote(address=address) for name, unit in values.items(): if unit != "": param = mote.getParameter(name) if param is not None: param.display = True param.setUnit(unit) # Update specified values right now report_values = {} i = 0 mote = self.getMote(address=address) for reg in mote.lstregregs: for endp in reg.lstItems: if endp.name in values: report_values[endp.name] = endp.getValueInAscii() i += 1 self._pluginapi.value_update(address, report_values) # Return something anyway, even though we return nothing. d = defer.Deferred() d.callback('') return d def _readPluginConfig(self): """ Read configuration parameters of the SWAP plugin """ config = ConfigParser.RawConfigParser() config.read('plugin.conf') self.broker_host = config.get('broker', 'host') self.broker_port = config.getint('broker', 'port') self.pluginId = config.get('general', 'id') self.loglevel = config.get('general', 'loglevel') # Read devices config file self.cfgdevices = XmlDevices() def __init__(self, settings=None, verbose=False, monitor=False): """ Class constructor @param settings: path to the main configuration file @param verbose: Print out SWAP frames or not @param monitor: Print out network events or not """ try: # Superclass call SwapInterface.__init__(self, settings, verbose) except: raise # Print SWAP activity self._printSWAP = monitor # Mote address in SYNC mode self._addrInSyncMode = None # Read plugin config self._readPluginConfig() # Declare HouseAgent callbacks callbacks = { 'poweron': self.cb_poweron, 'poweroff': self.cb_poweroff, 'custom': self.cb_custom, 'thermostat_setpoint': self.cb_thermostat } # Start plugin self._pluginapi = PluginAPI(guid=self.pluginId, plugintype="SWAP", broker_host=self.broker_host, broker_port=self.broker_port, **callbacks) self._pluginapi.ready() reactor.run()
class SwapManager(SwapInterface): """ SWAP Management Class """ def newMoteDetected(self, mote): """ New mote detected by SWAP server @param mote: Mote detected """ if self._printSWAP == True: print "New mote with address " + str(mote.address) + " : " + mote.definition.product + \ " (by " + mote.definition.manufacturer + ")" def newEndpointDetected(self, endpoint): """ New endpoint detected by SWAP server @param endpoint: Endpoint detected """ if self._printSWAP == True: print "New endpoint with Reg ID = " + str(endpoint.getRegId()) + " : " + endpoint.name # Set param units for this endpoint values = self.cfgdevices.getValues(endpoint.getRegAddress()) if endpoint.name in values: endpoint.display = True if values[endpoint.name] != "": endpoint.setUnit(values[endpoint.name]) def moteStateChanged(self, mote): """ Mote state changed @param mote: Mote having changed """ if self._printSWAP == True: print "Mote with address " + str(mote.address) + " switched to \"" + \ SwapState.toString(mote.state) + "\"" # SYNC mode entered? if mote.state == SwapState.SYNC: self._addrInSyncMode = mote.address def moteAddressChanged(self, mote): """ Mote address changed @param mote: Mote having changed """ if self._printSWAP == True: print "Mote changed address to " + str(mote.address) def registerValueChanged(self, register): """ Register value changed @param register: register object having changed """ if self._printSWAP == True: print "Register addr= " + str(register.getAddress()) + " id=" + str(register.id) + " changed to " + register.value.toAsciiHex() # Empty dictionary values = {} # For every endpoint contained in this register for endp in register.lstItems: strVal = endp.getValueInAscii() if endp.valueChanged: if self._printSWAP: print endp.name + " in address " + str(endp.getRegAddress()) + " changed to " + strVal if endp.display == True: values[endp.name] = strVal if len(values) > 0: if self._pluginapi is not None: self._pluginapi.value_update(register.getAddress(), values) def cb_poweron(self, address): """ This function is called when a poweron request has been received from the network. @param address: Address of the mote to be powered-on """ addr = int(address) d = defer.Deferred() #self.manager.setNodeOn(self.home_id, node_id) d.callback('done!') return d def cb_poweroff(self, address): """ This function is called when a poweroff request has been received from the network. @param address: Address of the mote to be powered-off """ addr = int(address) d = defer.Deferred() #self.manager.setNodeOff(self.home_id, node_id) d.callback('done!') return d def cb_thermostat(self, address, setpoint): ''' This callback function handles setting of thermostat setpoints. @param address: Address of the mote @param setpoint: the setpoint to set (float) ''' d = defer.Deferred() """ node = self.get_node(self.home_id, int(node_id)) if not isinstance(node, ZwaveNode): d.callback('error1') # Specified node not available else: for val in node.values: if val.value_data['commandClass'] == 'COMMAND_CLASS_THERMOSTAT_SETPOINT': value_id = int(val.value_data['id']) self.manager.setValue(value_id, float(setpoint)) d.callback('ok') """ return d def cb_custom(self, action, parameters): """ Handles several custom actions used througout the plugin. @param command: Custom command @param parameters: Custom command parameters @return Object requested """ if action == 'get_networkinfo': motes = {} for index, mote in enumerate(self.server.lstMotes): moteInfo = {"address": mote.address, "manufacturer": mote.definition.manufacturer, "product": mote.definition.product, "sleeping": mote.definition.pwrdownmode, "lastupdate": datetime.datetime.fromtimestamp(mote.timestamp).strftime("%d-%m-%Y %H:%M:%S")} motes[index] = moteInfo d = defer.Deferred() d.callback(motes) return d elif action == "get_motevalues": values = {} devaddress = int(parameters["mote"]) mote = self.server.getMote(address=devaddress) i = 0 for reg in mote.lstregregs: for endp in reg.lstItems: valueinfo = {"type": endp.type + " " + SwapType.toString(endp.direction), "name": endp.name, "value": endp.getValueInAscii(), "units": [], "unit": endp.unit.name } if endp.lstunits is not None and len(endp.lstunits) > 0: for unit in endp.lstunits: valueinfo["units"].append(unit.name) values[i] = valueinfo i += 1 d = defer.Deferred() d.callback(values) return d elif action == "track_values": ''' With this command you can set certain SWAP values to be tracked, and send them to the master node. ''' address = parameters['mote'] values = parameters['values'] self.cfgdevices.setValues(address, values) # Save config file self.cfgdevices.save() # Set units mote = self.getMote(address=address) for name, unit in values.items(): if unit != "": param = mote.getParameter(name) if param is not None: param.display = True param.setUnit(unit) # Update specified values right now report_values = {} i = 0 mote = self.getMote(address=address) for reg in mote.lstregregs: for endp in reg.lstItems: if endp.name in values: report_values[endp.name] = endp.getValueInAscii() i += 1 self._pluginapi.value_update(address, report_values) # Return something anyway, even though we return nothing. d = defer.Deferred() d.callback('') return d def _readPluginConfig(self): """ Read configuration parameters of the SWAP plugin """ config = ConfigParser.RawConfigParser() config.read('plugin.conf') self.broker_host = config.get('broker', 'host') self.broker_port = config.getint('broker', 'port') self.pluginId = config.get('general', 'id') self.loglevel = config.get('general', 'loglevel') # Read devices config file self.cfgdevices = XmlDevices() def __init__(self, settings=None, verbose=False, monitor=False): """ Class constructor @param settings: path to the main configuration file @param verbose: Print out SWAP frames or not @param monitor: Print out network events or not """ try: # Superclass call SwapInterface.__init__(self, settings, verbose) except: raise # Print SWAP activity self._printSWAP = monitor # Mote address in SYNC mode self._addrInSyncMode = None # Read plugin config self._readPluginConfig() # Declare HouseAgent callbacks callbacks = {'poweron': self.cb_poweron, 'poweroff': self.cb_poweroff, 'custom': self.cb_custom, 'thermostat_setpoint': self.cb_thermostat} # Start plugin self._pluginapi = PluginAPI(guid=self.pluginId, plugintype="SWAP", broker_host=self.broker_host, broker_port=self.broker_port, **callbacks) self._pluginapi.ready() reactor.run()