示例#1
0
    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()
示例#2
0
    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]))
示例#3
0
    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()
示例#4
0
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()
示例#5
0
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()
示例#6
0
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()