def __init__(self, name, core_services):
        self.__name = name
        self.__core = core_services
        
        self._logger = init_module_logger(name)        

        ## Local State Variables:
        self.__lora_manager = None
        
        self._extended_address_setting = None
        
        # Settings
        #
        # xbee_device_manager: must be set to the name of an XBeeDeviceManager
        #                      instance.
        # extended_address: the extended address of the XBee Sensor device you
        #                   would like to monitor.
        #
        # Advanced settings:
        #
        # None

        settings_list = [
                         
            Setting(
                name='lora_device_manager', type=str, required=True),
            Setting(
                name='extended_address', type=str, required=True),                         
                  
            Setting(
                name='log_level', type=str, required=False, default_value='DEBUG', verify_function=check_debug_level_setting),                  
          
            ]

        ## Channel Properties Definition:
        property_list = [
            # getable properties
            ChannelSourceDeviceProperty(name='software_version', type=str,
                initial=Sample(timestamp=digitime.time(), value=VERSION_NUMBER),
                perms_mask= DPROP_PERM_GET,
                options=DPROP_OPT_AUTOTIMESTAMP),
                         
            # setable properties
            ChannelSourceDeviceProperty(name='simulate_xbee_frame', type=str,
                initial=Sample(timestamp=0, value=''),
                perms_mask= DPROP_PERM_SET,
                options=DPROP_OPT_AUTOTIMESTAMP,
                set_cb=self._simulate_xbee_frame_cb),
            ChannelSourceDeviceProperty(name='command', type=str,
                initial=Sample(timestamp=0, value=''),
                perms_mask= DPROP_PERM_SET,
                options=DPROP_OPT_AUTOTIMESTAMP,
                set_cb=self._send_command_to_sensor_cb),                         
                         
         ]
        
        ## Initialize the DeviceBase interface:
        DeviceBase.__init__(self, self.__name, self.__core,
                                        settings_list, property_list)
    def __init__(self, name, core_services):
        ## Initialize and declare class variables
        self.__name = name
        self.__core = core_services

        self.__logger = init_module_logger(name)

        ## Settings Table Definition:
        settings_list = [
            Setting(name='baudrate',
                    type=int,
                    required=False,
                    default_value=38400,
                    verify_function=lambda x: x > 0),
            Setting(name='port', type=str, required=False, default_value='11'),
            Setting(name='mainloop_serial_read_timeout',
                    type=int,
                    required=False,
                    default_value=30),
            Setting(name='log_level',
                    type=str,
                    required=False,
                    default_value='DEBUG',
                    verify_function=check_debug_level_setting),
        ]

        ## Channel Properties Definition:
        property_list = [
            ChannelSourceDeviceProperty(name='software_version',
                                        type=str,
                                        initial=Sample(
                                            timestamp=digitime.time(),
                                            value=VERSION_NUMBER),
                                        perms_mask=DPROP_PERM_GET,
                                        options=DPROP_OPT_AUTOTIMESTAMP),
            ChannelSourceDeviceProperty(name="LoRaPlugAndSenseFrame",
                                        type=str,
                                        initial=Sample(timestamp=0, value=''),
                                        perms_mask=DPROP_PERM_GET,
                                        options=DPROP_OPT_AUTOTIMESTAMP),
        ]

        ## Initialize the DeviceBase interface:
        DeviceBase.__init__(self, self.__name, self.__core, settings_list,
                            property_list)

        ## Thread initialization:
        self.__stopevent = threading.Event()
        threading.Thread.__init__(self, name=name)
        threading.Thread.setDaemon(self, True)
    def __init__(self, name, core_services):
        self.__name = name
        self.__core = core_services

        self.__logger = init_module_logger(name)

        ## Settings Table Definition:
        settings_list = [
            Setting(name='log_level',
                    type=str,
                    required=False,
                    default_value='DEBUG',
                    verify_function=check_debug_level_setting),
        ]

        ## Channel Properties Definition:
        property_list = [
            # gettable properties
            ChannelSourceDeviceProperty(name="raw_out",
                                        type=str,
                                        initial=Sample(timestamp=0, value=""),
                                        perms_mask=DPROP_PERM_GET,
                                        options=DPROP_OPT_AUTOTIMESTAMP),

            # settable properties
            ChannelSourceDeviceProperty(name="raw_in",
                                        type=str,
                                        initial=Sample(
                                            timestamp=0,
                                            value='__INITIAL_SAMPLE__'),
                                        perms_mask=DPROP_PERM_SET,
                                        set_cb=self.__prop_set_raw_in),
            ChannelSourceDeviceProperty(name='software_version',
                                        type=str,
                                        initial=Sample(timestamp=0,
                                                       value=_VERSION_NUMBER),
                                        perms_mask=DPROP_PERM_GET,
                                        options=DPROP_OPT_AUTOTIMESTAMP),
        ]

        ## Initialize the DeviceBase interface:
        DeviceBase.__init__(self, self.__name, self.__core, settings_list,
                            property_list)

        ## Thread initialization:
        self.__stopevent = threading.Event()
        threading.Thread.__init__(self, name=name)
        threading.Thread.setDaemon(self, True)
 def __prop_set_raw_in(self, in_sample):
     injected_raw_data = in_sample.value
     self.__logger.debug(
         'Received a new raw input sample. String value=\"%s\". Hex value=\"%s\"'
         % (injected_raw_data, ''.join('0x%02X' % ord(x)
                                       for x in injected_raw_data)))
     self.property_set("raw_out", Sample(0, injected_raw_data))
    def _receive(self, channel):
        """\
            Called whenever there is a new sample on the channel
                that we are following/shadowing.

            Keyword arguments:

            channel -- the shadowed channel with the new sample
        """
        self._tracer.info("sample received in periodic alarm %s, %s, %s", channel.get(), channel.get().value, self._trigger_condition)
        if channel.get().value == self._trigger_condition:
            self._tracer.info("sample passed test in periodic alarm")
            self.property_set(Sample(value = self._trigger_condition))
            self._schedule_event()
        else:
            self._scheduler_lock.acquire()
            try:
                try:
                    if self._scheduled_event_handle:
                        self._scheduler.cancel(self._scheduled_event_handle)
                        self._scheduled_event_handle = None
                except ValueError:
                    pass #The event has already occured, nothing to remove
            finally:
                self._scheduler_lock.release()
예제 #6
0
 def __handle_debug(self, value):
     '''
     handle a call from the channel
     '''
     value = Boolean(value.value)
     self.property_set('debug_mode', Sample(0, value=value, unit='bool'))
     self.set_debug_mode(value)
예제 #7
0
    def __init__(self, name, core_services):
        settings_list = [
            Setting(name='debug_sleep_time',
                    type=int,
                    required=False,
                    default_value=50,
                    verify_function=lambda x: 10 <= x <= 14400000),
            Setting(name='debug_wake_time',
                    type=int,
                    required=False,
                    default_value=20000,
                    verify_function=lambda x: 69 <= x <= 3600000),
        ]

        property_list = [
            ChannelSourceDeviceProperty(name='debug_mode',
                                        type=Boolean,
                                        initial=Sample(timestamp=0,
                                                       value=Boolean(False),
                                                       unit='bool'),
                                        perms_mask=DPROP_PERM_GET
                                        | DPROP_PERM_SET,
                                        options=DPROP_OPT_AUTOTIMESTAMP,
                                        set_cb=self.__handle_debug),
        ]

        # network debug mode flag
        self.__debug = False
        self.__debug_lock = threading.RLock()

        DigiMeshDeviceManager.__init__(self, name, core_services,
                                       settings_list, property_list)
    def _set_sleep_wake(self, sleep_time, wake_time):
        '''
        Set the network's sleep/wake cycle to the passed parameters.

        sleep_time and wake_time are both in milliseconds.
        '''
        self.property_set('sleep_time', Sample(0, value=sleep_time, unit='ms'))
        self.property_set('wake_time', Sample(0, value=wake_time, unit='ms'))

        # need to set SM/SP/ST here to enable switching between
        # sleep and non-sleep in gateway.
        if sleep_time == 0:
            # then no sleep
            self._tracer.debug("Disabling Sleep; set SM=0, run fully awake")
            self.__sleeping = False
            self._awakeEvent.set()
            # disable sleep support
            self.xbee_device_ddo_set_param(None, 'SM', 0x0, timeout=15)
            # note: these two at 'not available' when SM=0x0
            # ddo_set_param(None, 'SP', 0x0)
            # ddo_set_param(None, 'ST', 0x7D0)

            # define as non-sleep coordinator
            self.xbee_device_ddo_set_param(None, 'SO', 0x2, timeout=15)

            self.listener.stop()
            self.remove_all_properties()

        else:
            # SM=0x7 for non-sleeping gway only
            self.__sleeping = True
            self._awakeEvent.clear()
            self._tracer.debug("Enabling Sleeping, sleep=%d, wake=%d",
                               sleep_time, wake_time)
            # sleep support
            self.xbee_device_ddo_set_param(None, 'SM', 0x7, timeout=15)
            self.xbee_device_ddo_set_param(None, 'SP', sleep_time / 10)
            self.xbee_device_ddo_set_param(None, 'ST', wake_time)

            # preferred sleep coord with api msgs
            self.xbee_device_ddo_set_param(None, 'SO', 0x5, timeout=15)

        self.xbee_device_ddo_set_param(None, 'WR', '')
 def _receive_sensor_data_callback_synchronized(self, channel):
     
     try:
         # critical section start
         self._receive_sensor_data_callback_lock.acquire()
         
         try:
             sample = channel.get()
             # timestamp value
             ts = sample.timestamp
             self._logger.debug('sample timestamps : %s' %(ts))
             # channel name (temperature, light, ...)
             dia_module_name, dia_channel_name = channel.name().split ('.')
             self._logger.debug('DIA channel name: %s' % dia_channel_name)
              
             # Compute the EC sensor name
             # map dia channel name to ec sensor name
             if self._dia_channel_name_to_ec_sensor_name_setting_map.has_key(dia_channel_name):
                 ecn_sensor_name = self._dia_channel_name_to_ec_sensor_name_setting_map.get(dia_channel_name)
             else:
                 ecn_sensor_name = dia_channel_name
             self._logger.debug('EC corresponding sensor name: %s' % ecn_sensor_name)
             
             # Compute the EC device public key
             # map the dia module name to a key
             if self._dia_module_name_to_ec_device_public_key_setting_map.has_key(dia_module_name):
                 ecn_device_public_key = self._dia_module_name_to_ec_device_public_key_setting_map.get(dia_module_name)
             else:
                 # the key is the module mame          
                 ecn_device_public_key = dia_module_name
             self._logger.debug('EC device public key: %s' % ecn_device_public_key)
             
             # channel value
             cv = sample.value
             
             ec_accespoint_pub_key = self._get_gw_id_for_ecn()
             self._logger.info('EC access point public key: %s' %(ec_accespoint_pub_key))
             # domainId
             dId = 'SBI_ECN'
 
             json_data = self._build_json_data (ecn_device_public_key, dId, ts, ec_accespoint_pub_key, ecn_sensor_name, cv)
             self._logger.info('json_data is : %s' %(json_data))
             
             self.property_set("json_data", Sample(0, json_data))
             
         except :
             self._logger.error('Unexpected error !!!')
             self._logger.error(traceback.format_exc())
             return
         
     finally:
         # critical section end 
         self._receive_sensor_data_callback_lock.release()
    def _receive(self, channel):
        """\
            Called whenever there is a new sample on the channel
                that we are following/shadowing.

            Keyword arguments:

            channel -- the shadowed channel with the new sample
        """
        test_sample = channel.get()
        filter_channel_sample = self.property_get()

        if test_sample.value == self._threshold:
            self.__above_count += 1
            self.__below_count = 0
            self._tracer.info(
                "Above Threshold Set HIGH Alarm...  Threshold: %r  Readings: %d",
                self._threshold, self.__above_count)
            if self.__above_count >= self._readings:
                if self._continuous or filter_channel_sample.value != True:
                    self._tracer.info(
                        "Threshold Alarm and count reached, setting!")
                    self.property_set(
                        Sample(timestamp=test_sample.timestamp, value=True))
        else:
            self.__above_count = 0
            # Only check if we are currently in an alarm condition.
            if filter_channel_sample.value == True:
                self.__below_count += 1
                self._tracer.info(
                    "Below Threshold Set HIGH Alarm...  Threshold: %r  Readings: %d",
                    self._threshold, self.__below_count)
                if self.__below_count >= self._readings:
                    self._tracer.info(
                        "Threshold Alarm resolved, unsetting! Threshold: %r",
                        self._threshold)
                    self.property_set(
                        Sample(timestamp=test_sample.timestamp, value=False))
예제 #11
0
    def _receive(self, channel):
        """\
            Called whenever there is a new sample on the channel
                that we are following/shadowing.

            Keyword arguments:

            channel -- the shadowed channel with the new sample
        """
        self._sample_queue.append(channel.get())
        if len(self._sample_queue) >= self._number_of_samples:
            average = self._average(list(x.value for x in self._sample_queue))
            self.property_set(Sample(value = average, unit = self._sample_queue[0].unit))
            self._sample_queue = []
    def _send_data_to_dia_channel(self, frame, addr):
              
        self._last_timestamp = digitime.time()
        io_sample=parser(decode_waspmote_frame(frame))
        
        self._logger.debug ('Found following information: %s' % str(io_sample))
          
        # route each information to its corresponding channel
        for key in io_sample.keys():
            
            if libelium_to_dia_map.has_key(key):
                channel_name, type_name, channel_unit = libelium_to_dia_map[key]
            else:
                # add this key to existing map for next loop
                                # use default values =>
                # ... the new channel has the information name
                channel_name = libelium_key_to_dia_channel_name (key)
                # ... type will be default
                type_name = str
                # ... unit will be none
                channel_unit = ''

                # extend the map (initialized in utils) with this new key                
                libelium_to_dia_map[key] = (channel_name, type_name, channel_unit)
                

            #verify the type of the value
            if type_name=='float':
                    sample_value=Convert_Str_Float(io_sample[key])
            elif type_name=='int':
                    sample_value=Convert_Str_Integer(io_sample[key])
            else:
                    sample_value=io_sample[key]
                    
            sample = Sample(self._last_timestamp, sample_value, channel_unit)
            
            #verify if the channel already exists. I not, create it. 
            if not self.property_exists(channel_name):
                # create the new channel
                self.add_property(
                   ChannelSourceDeviceProperty(channel_name,
                                               type=type(sample_value),
                                               initial=sample,
                                               perms_mask=DPROP_PERM_GET,
                                               options=DPROP_OPT_AUTOTIMESTAMP))
                self._logger.info ("Created channel \"%s\" for key \"%s\"" % (channel_name, key))
                
            # send the new sample
            self._logger.debug ('Put %s data to dia channel: %s' % (key, channel_name))
            self.property_set(channel_name, sample)                
예제 #13
0
    def physically_create_filter_channel(self, original_channel,
                                         filter_channel_name):
        #create the filter property we are going to add

        # perm_mask draws the refresh setting from the channel we are following.
        # If it is refreshable, then our channel will be refreshable as well.
        is_refreshable = bool(original_channel.perm_mask()
                              & DPROP_PERM_REFRESH)
        if is_refreshable:
            perms_mask = DPROP_PERM_GET | DPROP_PERM_SET | DPROP_PERM_REFRESH
        else:
            perms_mask = DPROP_PERM_GET | DPROP_PERM_SET
        filter_channel = ChannelSourceDeviceProperty(
            name=filter_channel_name,
            type=original_channel.type(),
            initial=Sample(timestamp=0, value=original_channel.type()()),
            perms_mask=perms_mask,
            refresh_cb=self._refresh,
            options=DPROP_OPT_AUTOTIMESTAMP)
        return filter_channel
    def physically_create_filter_channel(self, original_channel,
                                         filter_channel_name):
        """\
            Optional override of the base channel's call of the same name.

            This allows us to create a new channel, and define its type,
               based on whatever type we desire it to be.

            Keyword arguments:

            original_channel -- the shadowed channel

            filter_channel_name -- the name of the channel we should create
        """
        filter_channel = ChannelSourceDeviceProperty(
            name=filter_channel_name,
            type=bool,
            initial=Sample(timestamp=0, value=bool()),
            perms_mask=DPROP_PERM_GET | DPROP_PERM_SET,
            options=DPROP_OPT_AUTOTIMESTAMP)
        return filter_channel
    def __init__(self,
                 name,
                 core_services,
                 settings_list=None,
                 property_list=None):
        if settings_list == None:
            settings_list = []
        if property_list == None:
            property_list = []

        # over-ride base-class defaults - YML still over-rides these over-rides

        # digimesh requires DH/DL to match the coordinator
        self.DH_DL_FORCE_DEFAULT = 'coordinator'
        # this is in minutes - default to once every 3 hours/180 minutes
        self.DH_DL_REFRESH_DEFAULT = 180

        # existing default of 00:00:00:00:00:00:FF:FF! is okay for DigiMesh
        # self.MESH_BROADCAST

        settings_list.extend([
            Setting(name='sleep_time',
                    type=int,
                    required=False,
                    default_value=self.DMMAN_DEF_SLEEP_TIME,
                    verify_function=lambda x:
                    (x == 0) or (10 <= x <= 14400000)),
            Setting(name='wake_time',
                    type=int,
                    required=False,
                    default_value=self.DMMAN_DEF_WAKE_TIME,
                    verify_function=lambda x: 69 <= x <= 3600000),

            # if True try setting IR/IF as required otherwise leave alone
            # and assume the user has managed all of this
            Setting(name='set_if',
                    type=bool,
                    required=False,
                    default_value=self.DMMAN_DEF_SET_IF),
        ])

        property_list.extend([
            ChannelSourceDeviceProperty(name='wake_time',
                                        type=int,
                                        initial=Sample(timestamp=0,
                                                       value=-1,
                                                       unit='ms'),
                                        perms_mask=DPROP_PERM_GET,
                                        options=DPROP_OPT_AUTOTIMESTAMP),
            ChannelSourceDeviceProperty(name='sleep_time',
                                        type=int,
                                        initial=Sample(timestamp=0,
                                                       value=-1,
                                                       unit='ms'),
                                        perms_mask=DPROP_PERM_GET,
                                        options=DPROP_OPT_AUTOTIMESTAMP),
        ])

        XBeeDeviceManager.__init__(self, name, core_services, settings_list,
                                   property_list)

        # will be initialized during run() startup
        self.__dh_dl_refresh_sec = self.DH_DL_REFRESH_NOT_SET
        self.listener = SleepChecker(self)
 def _interval_check(self):
     self.property_set(Sample(value = self._trigger_condition))
     self._schedule_event()
    def _receive(self, channel):
        """\
            Called whenever there is a new sample on the channel
                that we are following/shadowing.

            Keyword arguments:

            channel -- the shadowed channel with the new sample
        """
        test_sample = channel.get()
        filter_channel_sample = self.property_get()

        # High type alarm...
        if self._alarm_type == ThresholdAlarmWithHysteresisFactory.HIGH:
            if test_sample.value >= self._threshold:
                self.__above_count += 1
                self.__below_count = 0
                self._tracer.info(
                    "Above Threshold Set HIGH Alarm...  Threshold: %f Readings: %d Hysteresis %f",
                    self._threshold, self.__above_count, self._hysteresis)
                if self.__above_count >= self._readings:
                    if self._continuous == True or filter_channel_sample.value != True:
                        self._tracer.info(
                            "Threshold Alarm and count reached, setting!")
                        self.property_set(
                            Sample(timestamp=test_sample.timestamp,
                                   value=True))
            else:
                self.__above_count = 0
                # Only check if we are currently in an alarm condition.
                if filter_channel_sample.value == True:
                    # If previous value of the alarm is true, apply the hysteresis
                    # to determine whether we should unset to alarm.
                    if test_sample.value <= self._threshold - self._hysteresis:
                        self.__below_count += 1
                        self._tracer.info(
                            "Below Threshold Set HIGH Alarm...  Threshold: %f Readings: %d Hysteresis %f",
                            self._threshold, self.__below_count,
                            self._hysteresis)
                        if self.__below_count >= self._readings:
                            self._tracer.info(
                                "Threshold Alarm resolved, unsetting! Threshold: %f Hysteresis %f",
                                self._threshold, self._hysteresis)
                            self.property_set(
                                Sample(timestamp=test_sample.timestamp,
                                       value=False))
                    else:
                        self._tracer.info(
                            "In DeadZone...  Threshold: %f Hysteresis %f",
                            self._threshold, self._hysteresis)
                        self.__below_count = 0
                        if self._continuous == True:
                            self.property_set(
                                Sample(timestamp=test_sample.timestamp,
                                       value=True))

        # Low type alarm...
        else:

            if test_sample.value <= self._threshold:
                self.__above_count += 1
                self.__below_count = 0
                self._tracer.info(
                    "Above Threshold Set LOW Alarm...  Threshold: %f Readings: %d Hysteresis %f",
                    self._threshold, self.__above_count, self._hysteresis)
                if self.__above_count >= self._readings:
                    if self._continuous == True or filter_channel_sample.value != True:
                        self._tracer.info(
                            "Threshold Alarm and count reached, setting!")
                        self.property_set(
                            Sample(timestamp=test_sample.timestamp,
                                   value=True))
            else:
                self.__above_count = 0
                # Only check if we are currently in an alarm condition.
                if filter_channel_sample.value == True:
                    # If previous value of the alarm is true, apply the hysteresis
                    # to determine whether we should unset to alarm.
                    if test_sample.value >= self._threshold + self._hysteresis:
                        self.__below_count += 1
                        self._tracer.info(
                            "Below Threshold Set LOW Alarm...  Threshold: %f Readings: %d Hysteresis %f",
                            self._threshold, self.__below_count,
                            self._hysteresis)
                        if self.__below_count >= self._readings:
                            self._tracer.info(
                                "Threshold Alarm resolved, unsetting! Threshold: %f Hysteresis %f",
                                self._threshold, self._hysteresis)
                            self.property_set(
                                Sample(timestamp=test_sample.timestamp,
                                       value=False))
                    else:
                        self._tracer.info(
                            "In DeadZone...  Threshold: %f Hysteresis %f",
                            self._threshold, self._hysteresis)
                        self.__below_count = 0
                        if self._continuous == True:
                            self.property_set(
                                Sample(timestamp=test_sample.timestamp,
                                       value=True))
    def run(self):

        # Try to open virtual serial port on USB.
        try:
            self.__lora = serial.Serial(
                port=SettingsBase.get_setting(self, 'port'),
                baudrate=SettingsBase.get_setting(self, 'baudrate'))
            self.__logger.info('Serial port opened')
        except:
            self.__logger.fatal(
                'Unable to open serial port %s at baudrate %d, aborting...' %
                (SettingsBase.get_setting(
                    self, 'port'), SettingsBase.get_setting(self, 'baudrate')))
            return

        # Flush remaining serial input
        self.__logger.debug("Start flushing serial buffer...")
        self.__lora.setTimeout(10)
        self.__lora.read(1024)
        self.__lora.setTimeout(
            SettingsBase.get_setting(self, 'mainloop_serial_read_timeout'))
        self.__logger.debug("...serial buffer flushed")

        # Initialize our internal state.
        # Receive buffer.
        self.__recBuffer = []
        # CRC buffer.
        self.__crcHex = []
        # Current automaton state.
        self.__currentAssemblyState = STATE_WAIT_SOH_OR_LT
        # Number of fields or number of bytes.
        self.__nbData = 0
        # Number of hash characters already received.
        self.__nbHash = 0

        # read current configuration
        lora_get_info_frame = '\x01READ\x0D\x0A2A31\x04'
        self.__lora.write(lora_get_info_frame)

        # At this stage, we have been able to open the virtual serial port.
        while True:

            if self.__stopevent.isSet():
                # Stop request received.
                self.__stopevent.clear()
                # Close virtual serial link.
                self.__lora.close()
                self.__logger.info('serial port closed')
                # And exit.
                break

            recByte = self.__lora.read(size=1)
            if recByte and len(recByte) > 0:
                recFrame = self.frameAssembler(recByte)
                if (recFrame != None):
                    # Convert to string after having removed first five characters.
                    recStr = ''.join(recFrame)
                    cleanedStr = recStr[5:]
                    self.__logger.debug('Received a frame: ' + cleanedStr)
                    self.property_set("LoRaPlugAndSenseFrame",
                                      Sample(digitime.time(), cleanedStr))
            else:
                self.__logger.debug('no data')
    def __init__(self, name, core_services):
        
        
        ## Initialize and declare class variables
        self.__name = name
        self.__core = core_services
        self.__cm = self.__core.get_service("channel_manager")
        self.__cp = self.__cm.channel_publisher_get()
        self.__cdb = self.__cm.channel_database_get()
        self._ec_key_to_dia_command_channel_name_cache = {}
        
        self._logger = init_module_logger(name)
        self._subscribed_channels = []
        
        self._ec_access_point_pub_key_setting = None
        self._dia_module_name_to_ec_device_public_key_setting_map = None
        self._sensor_channel_list_to_subscribe_to_setting = None
        self._incoming_command_channel_setting = None
        
        # semaphores and synchronization variables
        self._receive_sensor_data_callback_lock = threading.Lock()
        
        # will be appended to a DIA module name to get the name of the
        # channel to be used to send received commands
        self._sensor_channel_name_where_to_forward_commands = "command"
        
        settings_list = [
            Setting(name='ec_access_point_pub_key', type=str, required=False),
            Setting(name='channels', type=list, required=True, default_value=[]),
            Setting(name='exclude', type=list, required=False, default_value=[]),
            Setting(name='dia_channel_to_ec_sensor', type=dict, required=False, default_value={}),
            Setting(name='dia_module_to_ec_pub_key', type=dict, required=False, default_value={}),
            Setting(name='incoming_command_channel', type=str, required=False, default_value=''),

            Setting(name='log_level', type=str, required=False, default_value='DEBUG', verify_function=check_debug_level_setting),

        ]
        
        # Channel Properties Definition:
        
        property_list = [
                         
            #  properties
            
            ChannelSourceDeviceProperty(name='json_data', type=str,
                initial=Sample(timestamp=digitime.time(), value=""),
                perms_mask= DPROP_PERM_GET,
                options=DPROP_OPT_AUTOTIMESTAMP), 
                         
            ChannelSourceDeviceProperty(name='software_version', type=str,
                initial=Sample(timestamp=digitime.time(), value=VERSION_NUMBER),
                perms_mask= DPROP_PERM_GET,
                options=DPROP_OPT_AUTOTIMESTAMP),                         

        ]        
        
        
        ## Initialize the DeviceBase interface:
        DeviceBase.__init__(self, self.__name, self.__core,
                                        settings_list, property_list)
        
        self.__stopevent = threading.Event()        
        
        threading.Thread.__init__(self, name=name)
        threading.Thread.setDaemon(self, True)       
    def _route_forward_command (self, command_destination_public_key, command_name, command_parameters):
        
        # Recognize the command
        case_not_matched = True
        
        if case_not_matched and 'FORWARD' == command_name:
            case_not_matched = False
            
            #
            # decode parameters
            #
            
            frame_b64 = command_parameters.get('frame_b64')
            if not frame_b64:
                self._logger.error ('Missing argument to FORWARD command received by the gateway: %s' % command_name)
                return False
            
            decoded_frame = base64.b64decode(frame_b64)
                

            #
            # Search for DIA channel to write to
            # ----------------------------------
            #
            
            # If we previously received a command for this public key and get the corresponding DIA channel,
            # the DIA channel is already in the cache
            dia_command_channel = None
            
            if (self._ec_key_to_dia_command_channel_name_cache.has_key(command_destination_public_key)):
                dia_command_channel = self._ec_key_to_dia_command_channel_name_cache.get(command_destination_public_key)
                self._logger.debug ("Retrieved from cash the channel where we have to write the command for ecocity key \"%s\": %s" % (command_destination_public_key, dia_command_channel.name()))
                
            else:
                # We have to find that channel which will be used to forward the commands
            
                # Check if public key is know and identify the DIA module having that key
                command_destination_dia_module_name = None
                for dia_module_name, known_ec_public_key in self._dia_module_name_to_ec_device_public_key_setting_map.items():
                    if command_destination_public_key == known_ec_public_key:
                        command_destination_dia_module_name = dia_module_name
                        break
                
                if (not command_destination_dia_module_name):
                    self._logger.error ('No destination DIA channel for public key \"%s\" found.' % command_destination_public_key)
                    return False
                    # NOT REACHED
                
                # The Ecocity public key could be matched to a known DIA module
                # The variable command_destination_dia_module_name contains the name of the
                # DIA module with have to send the command
                
                
                command_destination_dia_channel_name = command_destination_dia_module_name + '.' + self._sensor_channel_name_where_to_forward_commands
                
                # check if channel exists in channel database
                if (self.__cdb.channel_exists(command_destination_dia_channel_name)):
                    # get that channel
                    dia_command_channel = self.__cdb.channel_get(command_destination_dia_channel_name)
                    # and store found channel into cache
                    self._ec_key_to_dia_command_channel_name_cache[command_destination_public_key] = dia_command_channel
                    self._logger.debug ("Got the channel where we have to write the command for ecocity key \"%s\": %s" % (command_destination_public_key, dia_command_channel.name()))
                else:
                    self._logger.error('Could not retrieve DIA channel named: %s' % command_destination_dia_channel_name)
                    return False
                    # NOT REACHED
                    
                    
            # Variable dia_command_channel contains now the channel to write to
    
            #
            # Send the command to that channel
            #
            command_sample = Sample(timestamp=0, value=decoded_frame)
            try:
                dia_command_channel.set(command_sample)
            except Exception, msg:
                self._logger.error('Could not send message to channel: %s' % command_destination_dia_channel_name)
                self._logger.error('Error was: %s' % msg)
                return False
                    
            return True