Beispiel #1
0
 def datachange_notification(self, node, val, data):
     try:
         log.debug("Python: New data change event on node %s, with val: %s",
                   node, val)
         subscription = self.connector.subscribed[node]
         converted_data = subscription["converter"].convert(
             (subscription["config_path"], subscription["path"]), val)
         self.connector.statistics['MessagesReceived'] += 1
         self.connector.data_to_send.append(converted_data)
         self.connector.statistics['MessagesSent'] += 1
         log.debug("Data to ThingsBoard: %s", converted_data)
     except Exception as e:
         log.exception(e)
 def on_attributes_update(self, content):
     log.debug(content)
     try:
         for server_variables in self.__available_object_resources[content["device"]]['variables']:
             for attribute in content["data"]:
                 for variable in server_variables:
                     if attribute == variable:
                         try:
                             server_variables[variable].set_value(content["data"][variable])
                         except Exception:
                             server_variables[variable].set_attribute(ua.AttributeIds.Value, ua.DataValue(content["data"][variable]))
     except Exception as e:
         log.exception(e)
Beispiel #3
0
 def datachange_notification(self, node, val, data):
     try:
         log.debug("Python: New data change event on node %s, with val: %s and data %s", node, val, str(data))
         subscription = self.connector.subscribed[node]
         converted_data = subscription["converter"].convert((subscription["config_path"], subscription["path"]), val)
         self.connector.statistics['MessagesReceived'] = self.connector.statistics['MessagesReceived'] + 1
         self.connector.data_to_send.append(converted_data)
         self.connector.statistics['MessagesSent'] = self.connector.statistics['MessagesSent'] + 1
         log.debug("[SUBSCRIPTION] Data to ThingsBoard: %s", converted_data)
     except KeyError:
         self.connector.scan_nodes_from_config()
     except Exception as e:
         log.exception(e)
Beispiel #4
0
 def __initialize_client(self):
     self.__opcua_nodes["root"] = self.client.get_objects_node()
     self.__opcua_nodes["objects"] = self.client.get_objects_node()
     if not self.__server_conf.get("disableSubscriptions", False):
         self.__sub = self.client.create_subscription(
             self.__server_conf.get("subCheckPeriodInMillis", 500),
             self.__sub_handler)
     else:
         self.__sub = False
     self.__scan_nodes_from_config()
     self.__previous_scan_time = time.time() * 1000
     log.debug('Subscriptions: %s', self.subscribed)
     log.debug("Available methods: %s", self.__available_object_resources)
    def __process_slaves(self):
        # TODO: write documentation
        device = ModbusConnector.process_requests.get()

        device_responses = {'timeseries': {}, 'attributes': {}}
        current_device_config = {}
        try:
            for config_section in device_responses:
                if device.config.get(config_section) is not None:
                    current_device_config = device.config

                    self.__connect_to_current_master(device)

                    if not device.config['master'].is_socket_open() or not len(
                            current_device_config[config_section]):
                        continue

                    # Reading data from device
                    for interested_data in range(
                            len(current_device_config[config_section])):
                        current_data = current_device_config[config_section][
                            interested_data]
                        current_data[DEVICE_NAME_PARAMETER] = device
                        input_data = self.__function_to_device(
                            device, current_data)
                        device_responses[config_section][
                            current_data[TAG_PARAMETER]] = {
                                "data_sent": current_data,
                                "input_data": input_data
                            }

                    log.debug("Checking %s for device %s", config_section,
                              device)
                    log.debug('Device response: ', device_responses)

            if device_responses.get('timeseries') or device_responses.get(
                    'attributes'):
                self.__convert_and_save_data((device, current_device_config, {
                    **current_device_config, BYTE_ORDER_PARAMETER:
                    current_device_config.get(BYTE_ORDER_PARAMETER,
                                              device.byte_order),
                    WORD_ORDER_PARAMETER:
                    current_device_config.get(WORD_ORDER_PARAMETER,
                                              device.word_order)
                }, device_responses))

        except ConnectionException:
            sleep(5)
            log.error("Connection lost! Reconnecting...")
        except Exception as e:
            log.exception(e)
Beispiel #6
0
 def on_attributes_update(
     self, content
 ):  # Function used for processing attribute update requests from ThingsBoard
     log.debug(content)
     if self.devices.get(content["device"]) is not None:
         device_config = self.devices[content["device"]].get(
             "device_config")
         if device_config is not None:
             log.debug(device_config)
             if device_config.get("attributeUpdates") is not None:
                 requests = device_config["attributeUpdates"]
                 for request in requests:
                     attribute = request.get("attributeOnThingsBoard")
                     log.debug(attribute)
                     if attribute is not None and attribute in content[
                             "data"]:
                         try:
                             value = content["data"][attribute]
                             str_to_send = str(
                                 request["stringToDevice"].replace(
                                     "${" + attribute + "}",
                                     str(value))).encode("UTF-8")
                             self.devices[content["device"]][
                                 "serial"].write(str_to_send)
                             log.debug(
                                 "Attribute update request to device %s : %s",
                                 content["device"], str_to_send)
                             time.sleep(.01)
                         except Exception as e:
                             log.exception(e)
Beispiel #7
0
 def __new_device_processing(self, device):
     default_services_on_device = [service for service in self.__devices_around[device]['services'].keys() if int(service.split('-')[0], 16) in self.__default_services]
     log.debug('Default services found on device %s :%s', device, default_services_on_device)
     converter = BytesBLEUplinkConverter(self.__devices_around[device]['device_config'])
     converted_data = None
     for service in default_services_on_device:
         characteristics = [char for char in self.__devices_around[device]['services'][service].keys() if self.__devices_around[device]['services'][service][char]['characteristic'].supportsRead()]
         for char in characteristics:
             read_config = {'characteristicUUID': char,
                            'method': 'READ',
                            }
             try:
                 self.__check_and_reconnect(device)
                 data = self.__service_processing(device, read_config)
                 attribute = capitaliseName(UUID(char).getCommonName())
                 read_config['key'] = attribute
                 read_config['byteFrom'] = 0
                 read_config['byteTo'] = -1
                 converter_config = [{"type": "attributes",
                                      "clean": False,
                                      "section_config": read_config}]
                 for interest_information in converter_config:
                     try:
                         converted_data = converter.convert(interest_information, data)
                         log.debug(converted_data)
                     except Exception as e:
                         log.debug(e)
             except Exception as e:
                 log.debug('Cannot process %s', e)
                 continue
     if converted_data is not None:
         # self.__gateway.add_device(converted_data["deviceName"], {"connector": self})
         self.__gateway.send_to_storage(self.get_name(), converted_data)
    def run(self):
        while True:
            if time.time() - self.__previous_scan_time >= self.__rescan_time != 0:
                self.__scan_ble()
                self.__previous_scan_time = time.time()

            if time.time() - self.__previous_read_time >= self.__check_interval_seconds:
                self.__get_services_and_chars()
                self.__previous_read_time = time.time()

            time.sleep(.1)
            if self.__stopped:
                log.debug('STOPPED')
                break
Beispiel #9
0
 def scan_nodes_from_config(self):
     try:
         if self.__interest_nodes:
             for device_object in self.__interest_nodes:
                 for current_device in device_object:
                     try:
                         device_configuration = device_object[current_device]
                         devices_info_array = self.__search_general_info(device_configuration)
                         for device_info in devices_info_array:
                             if device_info is not None and device_info.get("deviceNode") is not None:
                                 self.__search_nodes_and_subscribe(device_info)
                                 self.__save_methods(device_info)
                                 self.__search_attribute_update_variables(device_info)
                             else:
                                 log.error("Device node is None, please check your configuration.")
                                 log.debug("Current device node is: %s", str(device_configuration.get("deviceNodePattern")))
                                 break
                     except BrokenPipeError:
                         log.debug("Broken Pipe. Connection lost.")
                     except OSError:
                         log.debug("Stop on scanning.")
                     except FuturesTimeoutError:
                         self.__check_connection()
                     except Exception as e:
                         log.exception(e)
             log.debug(self.__interest_nodes)
     except Exception as e:
         log.exception(e)
Beispiel #10
0
    def connectionMade(self):
        # 初始化Framer
        self.framer = self.factory.framer
        # 初始化TransactionT
        if isinstance(self.framer, ModbusSocketFramer):
            self.transaction = DictTransactionManager(self)
        else:
            self.transaction = FifoTransactionManager(self)

        self._addr = '%s:%d' % (self.transport.getPeer().host,
                                self.transport.getPeer().port)
        self.factory.addClient(self._addr, self, None)
        log.debug("Client Connected [%s]" % self._addr)
        self._connected = True
 def __init__(self, gateway, config, connector_type):
     super().__init__()
     self.statistics = {
         'MessagesReceived': 0,
         'MessagesSent': 0
     }  # Dictionary, will save information about count received and sent messages.
     log.debug(type(config))
     log.debug(config)
     self.__config = config  # Save configuration from the configuration file.
     log.debug(type(gateway))
     log.debug(gateway)
     self.__gateway = gateway  # Save gateway object, we will use some gateway methods for adding devices and saving data from them.
     self.daemon = True  # Set self thread as daemon
     self.stopped = True  # Service variable for check state
     #self.__connected = False    # Service variable for check connection to device
     self.__devices = {}
     self.setName(
         self.__config.get(
             "name", 'IGT GPIO Default ' +
             ''.join(choice(ascii_lowercase) for _ in range(5))))
     self.__load_converters()
     log.info('Custom connector %s initialization success.',
              self.get_name())  # Message to logger
     log.info("Devices in configuration file found: %s ",
              '\n'.join(device
                        for device in self.__devices))  # Message to logger
 def __fill_interest_devices(self):
     if self.__config.get('devices') is None:
         log.error('Devices not found in configuration file. BLE Connector stopped.')
         self._connected = False
         return None
     for interest_device in self.__config.get('devices'):
         keys_in_config = ['attributes', 'telemetry']
         if interest_device.get('MACAddress') is not None:
             default_converter = BytesBLEUplinkConverter(interest_device)
             interest_uuid = {}
             for key_type in keys_in_config:
                 for type_section in interest_device.get(key_type):
                     if type_section.get("characteristicUUID") is not None:
                         converter = None
                         if type_section.get('converter') is not None:
                             try:
                                 module = TBUtility.check_and_import(self.__connector_type,
                                                                     type_section['converter'])
                                 if module is not None:
                                     log.debug('Custom converter for device %s - found!',
                                               interest_device['MACAddress'])
                                     converter = module(interest_device)
                                 else:
                                     log.error(
                                         "\n\nCannot find extension module for device %s .\nPlease check your configuration.\n",
                                         interest_device['MACAddress'])
                             except Exception as e:
                                 log.exception(e)
                         else:
                             converter = default_converter
                         if converter is not None:
                             if interest_uuid.get(type_section["characteristicUUID"].upper()) is None:
                                 interest_uuid[type_section["characteristicUUID"].upper()] = [
                                     {'section_config': type_section,
                                      'type': key_type,
                                      'converter': converter}]
                             else:
                                 interest_uuid[type_section["characteristicUUID"].upper()].append(
                                     {'section_config': type_section,
                                      'type': key_type,
                                      'converter': converter})
                     else:
                         log.error("No characteristicUUID found in configuration section for %s:\n%s\n", key_type,
                                   pformat(type_section))
             if self.__devices_around.get(interest_device['MACAddress'].upper()) is None:
                 self.__devices_around[interest_device['MACAddress'].upper()] = {}
             self.__devices_around[interest_device['MACAddress'].upper()]['device_config'] = interest_device
             self.__devices_around[interest_device['MACAddress'].upper()]['interest_uuid'] = interest_uuid
         else:
             log.error("Device address not found, please check your settings.")
    def run(self):
        while not self.__connected:
            try:
                self.__connected = self.client.connect()
                self.client.load_type_definitions()
                log.debug(self.client.get_namespace_array()[-1])
                log.debug(
                    self.client.get_namespace_index(
                        self.client.get_namespace_array()[-1]))
            except ConnectionRefusedError:
                log.error(
                    "Connection refused on connection to OPC-UA server with url %s",
                    self.__server_conf.get("url"))
                time.sleep(10)
            except Exception as e:
                log.debug("error on connection to OPC-UA server.")
                log.error(e)
                time.sleep(10)
            else:
                self.__connected = True
                log.info("OPC-UA connector %s connected to server %s",
                         self.get_name(), self.__server_conf.get("url"))
        self.__opcua_nodes["root"] = self.client.get_root_node()
        self.__opcua_nodes["objects"] = self.client.get_objects_node()
        sub = self.client.create_subscription(
            self.__server_conf.get("scanPeriodInMillis", 500),
            self.__sub_handler)
        # self.__search_name(self.__opcua_nodes["objects"], 2)
        # self.__search_tags(self.__opcua_nodes["objects"], 2, sub)

        self.__search_name(self.__opcua_nodes["root"], 0)
        self.__search_tags(self.__opcua_nodes["root"], 0, sub)
        log.debug('Subscriptions: %s', self.subscribed)

        log.debug("Available methods: %s", self.__available_object_resources)
        while True:
            try:
                time.sleep(1)
                if self.data_to_send:
                    self.__gateway.send_to_storage(self.get_name(),
                                                   self.data_to_send.pop())
                if self.__stopped:
                    break
            except (KeyboardInterrupt, SystemExit):
                self.close()
                raise
            except Exception as e:
                self.close()
                log.exception(e)
Beispiel #14
0
 def server_side_rpc_handler(self, content):
     if content.get("device") is not None:
         log.debug(
             "Modbus connector received rpc request for %s with content: %s",
             content["device"], content)
         rpc_command_config = self.__devices[
             content["device"]]["config"]["rpc"].get(
                 content["data"].get("method"))
         if rpc_command_config is not None:
             rpc_command_config["unitId"] = self.__devices[
                 content["device"]]["config"]["unitId"]
             if rpc_command_config.get('bit') is not None:
                 rpc_command_config["functionCode"] = 6
             if rpc_command_config.get("functionCode") in (5, 6, 15, 16):
                 rpc_command_config["payload"] = self.__devices[
                     content["device"]]["downlink_converter"].convert(
                         rpc_command_config, content)
             response = None
             try:
                 response = self.__function_to_device(
                     rpc_command_config, rpc_command_config["unitId"])
             except Exception as e:
                 log.exception(e)
             if isinstance(response, ReadRegistersResponseBase):
                 to_converter = {
                     "rpc": {
                         content["data"]["method"]: {
                             "data_sent": rpc_command_config,
                             "input_data": response
                         }
                     }
                 }
                 response = self.__devices[
                     content["device"]]["converter"].convert(
                         config=None, data=to_converter)
                 log.debug("Received RPC method: %s, result: %r",
                           content["data"]["method"], response)
             elif isinstance(
                     response,
                 (WriteMultipleRegistersResponse,
                  WriteMultipleCoilsResponse, WriteSingleCoilResponse,
                  WriteSingleRegisterResponse)):
                 response = str(response)
                 log.debug("Write %r", response)
             response = False if response is None else response
             response = str(response) if isinstance(response,
                                                    Exception) else response
             self.__gateway.send_rpc_reply(
                 content["device"], content["data"]["id"],
                 {content["data"]["method"]: response})
         else:
             log.error(
                 "Received rpc request, but method %s not found in config for %s.",
                 content["data"].get("method"), self.get_name())
             self.__gateway.send_rpc_reply(
                 content["device"], content["data"]["id"],
                 {content["data"]["method"]: "METHOD NOT FOUND!"})
     else:
         log.debug("Received RPC to connector: %r", content)
Beispiel #15
0
 def dataReceived(self, data):
     log.debug("Received data: " +
               " ".join([hex(byte2int(x)) for x in data]))
     self._timeoutDeffer.callback('dataReceived')
     if self._is_valid:
         # 验证成功
         unit = self.framer.decode_data(data).get("uid", 0)
         self.framer.processIncomingPacket(data,
                                           self._handleResponse,
                                           unit=unit)
     else:
         # 首次获取数据,验证注册码
         data_str = str(data, encoding='ascii')
         if data_str is not None and len(data_str) > 0:
             self._handlerToken(data_str)
 def __service_processing(self, device, characteristic_processing_conf):
     for service in self.__devices_around[device]['services']:
         characteristic_uuid_from_config = characteristic_processing_conf.get('characteristicUUID')
         if characteristic_uuid_from_config is None:
             log.error('Characteristic not found in config: %s', pformat(characteristic_processing_conf))
             return None
         if self.__devices_around[device]['services'][service].get(characteristic_uuid_from_config) is None:
             continue
         characteristic = self.__devices_around[device]['services'][service][characteristic_uuid_from_config][
             'characteristic']
         self.__check_and_reconnect(device)
         data = None
         if characteristic_processing_conf.get('method', '_').upper().split()[0] == "READ":
             if characteristic.supportsRead():
                 self.__check_and_reconnect(device)
                 data = characteristic.read()
                 log.debug(data)
             else:
                 log.error('This characteristic doesn\'t support "READ" method.')
         if characteristic_processing_conf.get('method', '_').upper().split()[0] == "NOTIFY":
             self.__check_and_reconnect(device)
             descriptor = characteristic.getDescriptors(forUUID=0x2902)[0]
             handle = descriptor.handle
             if self.__notify_delegators.get(device) is None:
                 self.__notify_delegators[device] = {}
             if self.__notify_delegators[device].get(handle) is None:
                 self.__notify_delegators[device][handle] = {'function': self.__notify_handler,
                                                             'args': (self.__devices_around[device],
                                                                      handle,
                                                                      self.__notify_delegators[device].get(handle)),
                                                             'delegate': None
                                                             }
                 self.__notify_delegators[device][handle]['delegate'] = self.__notify_delegators[device][handle][
                     'function'](*self.__notify_delegators[device][handle]['args'])
                 data = self.__notify_delegators[device][handle]['delegate'].data
             else:
                 self.__notify_delegators[device][handle]['args'] = (self.__devices_around[device],
                                                                     handle,
                                                                     self.__notify_delegators[device][handle]['delegate'])
                 self.__notify_delegators[device][handle]['delegate'] = self.__notify_delegators[device][handle][
                     'function'](*self.__notify_delegators[device][handle]['args'])
                 data = self.__notify_delegators[device][handle]['delegate'].data
         if data is None:
             log.error('Cannot process characteristic: %s with config:\n%s', str(characteristic.uuid).upper(),
                       pformat(characteristic_processing_conf))
         else:
             log.debug('data: %s', data)
         return data
Beispiel #17
0
 def __send_request(self, request, converter_queue, log):
     url = ""
     try:
         request["next_time"] = time() + request["config"].get(
             "scanPeriod", 10)
         request_url_from_config = request["config"]["url"]
         request_url_from_config = str(
             '/' + request_url_from_config
         ) if request_url_from_config[0] != '/' else request_url_from_config
         log.debug(request_url_from_config)
         url = self.__host + request_url_from_config
         log.debug(url)
         request_timeout = request["config"].get("timeout", 1)
         params = {
             "method": request["config"].get("httpMethod", "GET"),
             "url": url,
             "timeout": request_timeout,
             "allow_redirects":
             request["config"].get("allowRedirects", False),
             "verify": self.__ssl_verify,
             "auth": self.__security
         }
         log.debug(url)
         if request["config"].get("httpHeaders") is not None:
             params["headers"] = request["config"]["httpHeaders"]
         log.debug("Request to %s will be sent", url)
         response = request["request"](**params)
         if response and response.ok:
             if not converter_queue.full():
                 data_to_storage = [url, request["converter"]]
                 try:
                     data_to_storage.append(response.json())
                 except UnicodeDecodeError:
                     data_to_storage.append(response.content())
                 if len(data_to_storage) == 3:
                     converter_queue.put(data_to_storage)
         else:
             log.error("Request to URL: %s finished with code: %i", url,
                       response.status_code)
     except Timeout:
         log.error("Timeout error on request %s.", url)
     except RequestException as e:
         log.error("Cannot connect to %s. Connection error.", url)
         log.debug(e)
     except ConnectionError:
         log.error("Cannot connect to %s. Connection error.", url)
     except Exception as e:
         log.exception(e)
    def server_side_rpc_handler(self, server_rpc_request):
        try:
            if server_rpc_request.get(DEVICE_SECTION_PARAMETER) is not None:

                log.debug(
                    "Modbus connector received rpc request for %s with server_rpc_request: %s",
                    server_rpc_request[DEVICE_SECTION_PARAMETER],
                    server_rpc_request)
                if isinstance(
                        self.__devices[
                            server_rpc_request[DEVICE_SECTION_PARAMETER]]
                    [CONFIG_SECTION_PARAMETER][RPC_SECTION], dict):
                    rpc_command_config = self.__devices[
                        server_rpc_request[DEVICE_SECTION_PARAMETER]][
                            CONFIG_SECTION_PARAMETER][RPC_SECTION].get(
                                server_rpc_request[DATA_PARAMETER]
                                [RPC_METHOD_PARAMETER])
                    if rpc_command_config is not None:
                        self.__process_rpc_request(server_rpc_request,
                                                   rpc_command_config)
                elif isinstance(
                        self.__devices[
                            server_rpc_request[DEVICE_SECTION_PARAMETER]]
                    [CONFIG_SECTION_PARAMETER][RPC_SECTION], list):
                    for rpc_command_config in self.__devices[
                            server_rpc_request[DEVICE_SECTION_PARAMETER]][
                                CONFIG_SECTION_PARAMETER][RPC_SECTION]:
                        if rpc_command_config[
                                TAG_PARAMETER] == server_rpc_request[
                                    DATA_PARAMETER][RPC_METHOD_PARAMETER]:
                            self.__process_rpc_request(server_rpc_request,
                                                       rpc_command_config)
                            break
                else:
                    log.error(
                        "Received rpc request, but method %s not found in config for %s.",
                        server_rpc_request[DATA_PARAMETER].get(
                            RPC_METHOD_PARAMETER), self.get_name())
                    self.__gateway.send_rpc_reply(
                        server_rpc_request[DEVICE_SECTION_PARAMETER],
                        server_rpc_request[DATA_PARAMETER][RPC_ID_PARAMETER], {
                            server_rpc_request[DATA_PARAMETER][RPC_METHOD_PARAMETER]:
                            "METHOD NOT FOUND!"
                        })
            else:
                log.debug("Received RPC to connector: %r", server_rpc_request)
        except Exception as e:
            log.exception(e)
 def form_iocb(device, config=None, request_type="readProperty"):
     config = config if config is not None else device
     address = device["address"] if isinstance(device["address"], Address) else Address(device["address"])
     object_id = ObjectIdentifier(config["objectId"])
     property_id = config.get("propertyId")
     value = config.get("propertyValue")
     property_index = config.get("propertyIndex")
     priority = config.get("priority")
     vendor = device.get("vendor", config.get("vendorId", 0))
     request = None
     iocb = None
     if request_type == "readProperty":
         try:
             request = ReadPropertyRequest(
                 objectIdentifier=object_id,
                 propertyIdentifier=property_id
             )
             request.pduDestination = address
             if property_index is not None:
                 request.propertyArrayIndex = int(property_index)
             iocb = IOCB(request)
         except Exception as e:
             log.exception(e)
     elif request_type == "writeProperty":
         datatype = get_datatype(object_id.value[0], property_id, vendor)
         if (isinstance(value, str) and value.lower() == 'null') or value is None:
             value = Null()
         request = WritePropertyRequest(
             objectIdentifier=object_id,
             propertyIdentifier=property_id
         )
         request.pduDestination = address
         request.propertyValue = Any()
         try:
             value = datatype(value)
             request.propertyValue = Any(value)
         except AttributeError as e:
             log.debug(e)
         except Exception as error:
             log.exception("WriteProperty cast error: %r", error)
         if property_index is not None:
             request.propertyArrayIndex = property_index
         if priority is not None:
             request.priority = priority
         iocb = IOCB(request)
     else:
         log.error("Request type is not found or not implemented")
     return iocb
Beispiel #20
0
 def __scan_ble(self):
     log.debug("Scanning for devices...")
     try:
         self.__scanner.scan(self.__config.get('scanTimeSeconds', 5), passive=self.__config.get('passiveScanMode', False))
     except BTLEManagementError as e:
         log.error('BLE working only with root user.')
         log.error('Or you can try this command:\nsudo setcap '
                   '\'cap_net_raw,cap_net_admin+eip\' %s'
                   '\n====== Attention! ====== '
                   '\nCommand above - provided access to ble devices to any user.'
                   '\n========================', str(bluepy_path[0] + '/bluepy-helper'))
         self._connected = False
         raise e
     except Exception as e:
         log.exception(e)
         time.sleep(10)
    def __resolve_iterator_file(self):
        file_name = ""
        try:
            # The algorithm of resolving iterator file name is described in
            # https://thingsboard.io/docs/iot-gateway/config/odbc/#subsection-iterator
            # Edit that description whether algorithm is changed.
            file_name += self.__connection.getinfo(pyodbc.SQL_DRIVER_NAME)
            file_name += self.__connection.getinfo(pyodbc.SQL_SERVER_NAME)
            file_name += self.__connection.getinfo(pyodbc.SQL_DATABASE_NAME)
            file_name += self.__config["polling"]["iterator"]["column"]

            self.__iterator_file_name = sha1(file_name.encode()).hexdigest() + ".json"
            log.debug("[%s] Iterator file name resolved to %s", self.get_name(), self.__iterator_file_name)
        except Exception as e:
            log.warn("[%s] Failed to resolve iterator file name: %s", self.get_name(), str(e))
        return bool(self.__iterator_file_name)
Beispiel #22
0
 def __search_general_info(self, device):
     result = {"deviceName": None, "deviceType": None, "deviceNode": None}
     result["deviceNode"] = self.__search_node(
         self.__opcua_nodes["root"],
         TBUtility.get_value(device["deviceNodePattern"], get_tag=True))
     if result["deviceNode"] is not None:
         name_pattern_config = device["deviceNamePattern"]
         name_expression = TBUtility.get_value(name_pattern_config,
                                               get_tag=True)
         device_name_node = self.__search_node(self.__opcua_nodes["root"],
                                               name_expression)
         if device_name_node is not None:
             device_name_from_node = device_name_node.get_value()
             full_device_name = name_pattern_config.replace(
                 "${" + name_expression + "}",
                 device_name_from_node).replace(name_expression,
                                                device_name_from_node)
             result["deviceName"] = full_device_name
             log.debug("Device name: %s", full_device_name)
             if device.get("deviceTypePattern"):
                 device_type_expression = TBUtility.get_value(
                     device["deviceTypePattern"], get_tag=True)
                 device_type_node = self.__search_node(
                     self.__opcua_nodes["root"], device_type_expression)
                 if device_type_node is not None:
                     device_type = device_type_node.get_value()
                     full_device_type = device_type_expression.replace(
                         "${" + device_type_expression + "}",
                         device_type).replace(device_type_expression,
                                              device_type)
                     result["deviceType"] = full_device_type
                     log.debug("Device type: %s", full_device_type)
                 else:
                     log.error(
                         "Device type node not found with expression: %s",
                         device_type_expression)
             else:
                 result["deviceType"] = "default"
             return result
         else:
             log.error("Device name node not found with expression: %s",
                       name_expression)
             return
     else:
         log.error(
             "Device node not found with expression: %s",
             TBUtility.get_value(device["deviceNodePattern"], get_tag=True))
 def indication(self, apdu: APDU):
     if isinstance(apdu, IAmRequest):
         log.debug("Received IAmRequest from device with ID: %i and address %s:%i",
                   apdu.iAmDeviceIdentifier[1],
                   apdu.pduSource.addrTuple[0],
                   apdu.pduSource.addrTuple[1]
                   )
         log.debug(apdu.pduSource)
         request = ReadPropertyRequest(
             destination=apdu.pduSource,
             objectIdentifier=apdu.iAmDeviceIdentifier,
             propertyIdentifier='objectName',
         )
         iocb = IOCB(request)
         deferred(self.request_io, iocb)
         iocb.add_callback(self.__iam_cb, vendor_id=apdu.vendorID)
         self.requests_in_progress.update({iocb: {"callback": self.__iam_cb}})
Beispiel #24
0
    def run(self):
        while not self.__stopped:
            # Initialization phase
            if not self.is_connected():
                while not self.__stopped and \
                        not self.__init_connection() and \
                        self.__config["connection"].get("reconnect", self.DEFAULT_RECONNECT_STATE):
                    reconnect_period = self.__config["connection"].get(
                        "reconnectPeriod", self.DEFAULT_RECONNECT_PERIOD)
                    log.info("[%s] Will reconnect to database in %d second(s)",
                             self.get_name(), reconnect_period)
                    sleep(reconnect_period)

                if not self.is_connected():
                    log.error(
                        "[%s] Cannot connect to database so exit from main loop",
                        self.get_name())
                    break

                if not self.__init_iterator():
                    log.error(
                        "[%s] Cannot init database iterator so exit from main loop",
                        self.get_name())
                    break

            # Polling phase
            try:
                self.__poll()
                if not self.__stopped:
                    polling_period = self.__config["polling"].get(
                        "period", self.DEFAULT_POLL_PERIOD)
                    log.debug(
                        "[%s] Next polling iteration will be in %d second(s)",
                        self.get_name(), polling_period)
                    sleep(polling_period)
            except pyodbc.Warning as w:
                log.warning("[%s] Warning while polling database: %s",
                            self.get_name(), str(w))
            except pyodbc.Error as e:
                log.error("[%s] Error while polling database: %s",
                          self.get_name(), str(e))
                self.__close()

        self.__close()
        self.__stopped = False
        log.info("[%s] Stopped", self.get_name())
Beispiel #25
0
    def server_side_rpc_handler(self, content):
        try:
            for method in self.__available_object_resources[
                    content["device"]]['methods']:
                rpc_method = content["data"].get("method")
                if rpc_method is not None and method.get(
                        rpc_method) is not None:
                    arguments_from_config = method["arguments"]
                    arguments = content["data"].get(
                        "params") if content["data"].get(
                            "params") is not None else arguments_from_config
                    try:
                        if type(arguments) is list:
                            result = method["node"].call_method(
                                method[rpc_method], *arguments)
                        elif arguments is not None:
                            result = method["node"].call_method(
                                method[rpc_method], arguments)
                        else:
                            result = method["node"].call_method(
                                method[rpc_method])

                        self.__gateway.send_rpc_reply(
                            content["device"], content["data"]["id"], {
                                content["data"]["method"]: result,
                                "code": 200
                            })
                        log.debug("method %s result is: %s",
                                  method[rpc_method], result)
                    except Exception as e:
                        log.exception(e)
                        self.__gateway.send_rpc_reply(content["device"],
                                                      content["data"]["id"], {
                                                          "error": str(e),
                                                          "code": 500
                                                      })
                else:
                    log.error("Method %s not found for device %s", rpc_method,
                              content["device"])
                    self.__gateway.send_rpc_reply(
                        content["device"], content["data"]["id"], {
                            "error": "%s - Method not found" % (rpc_method),
                            "code": 404
                        })
        except Exception as e:
            log.exception(e)
Beispiel #26
0
    def __function_to_device(self, config, unit_id):
        function_code = config.get('functionCode')
        result = None
        if function_code in (1, 2, 3, 4):
            result = self.__available_functions[function_code](
                config["address"],
                config.get("registerCount", 1),
                unit=unit_id)
        elif function_code in (5, 6, 15, 16):
            result = self.__available_functions[function_code](
                config["address"], config["payload"], unit=unit_id)
        else:
            log.error("Unknown Modbus function with code: %i", function_code)
        log.debug("To modbus device %s, \n%s", config["deviceName"], config)
        log.debug("With result %s", result)

        return result
Beispiel #27
0
    def __connect_to_current_master(self, device=None):
        # TODO: write documentation
        connect_attempt_count = 5
        connect_attempt_time_ms = 100
        wait_after_failed_attempts_ms = 300000

        if device.config.get('master') is None:
            device.config['master'], device.config['available_functions'] = self.__configure_master(device.config)

        if connect_attempt_count < 1:
            connect_attempt_count = 1

        connect_attempt_time_ms = device.config.get('connectAttemptTimeMs', connect_attempt_time_ms)

        if connect_attempt_time_ms < 500:
            connect_attempt_time_ms = 500

        wait_after_failed_attempts_ms = device.config.get('waitAfterFailedAttemptsMs', wait_after_failed_attempts_ms)

        if wait_after_failed_attempts_ms < 1000:
            wait_after_failed_attempts_ms = 1000

        current_time = time() * 1000

        if not device.config['master'].is_socket_open():
            if device.config['connection_attempt'] >= connect_attempt_count and current_time - device.config[
                    'last_connection_attempt_time'] >= wait_after_failed_attempts_ms:
                device.config['connection_attempt'] = 0

            while not device.config['master'].is_socket_open() \
                    and device.config['connection_attempt'] < connect_attempt_count \
                    and current_time - device.config.get('last_connection_attempt_time',
                                                         0) >= connect_attempt_time_ms:
                device.config['connection_attempt'] = device.config[
                                                          'connection_attempt'] + 1
                device.config['last_connection_attempt_time'] = current_time
                log.debug("Modbus trying connect to %s", device)
                device.config['master'].connect()

                if device.config['connection_attempt'] == connect_attempt_count:
                    log.warn("Maximum attempt count (%i) for device \"%s\" - encountered.", connect_attempt_count,
                             device)

        if device.config['connection_attempt'] >= 0 and device.config['master'].is_socket_open():
            device.config['connection_attempt'] = 0
            device.config['last_connection_attempt_time'] = current_time
 def __on_mapping_response_cb(self, iocb: IOCB):
     try:
         if self.requests_in_progress.get(iocb) is not None:
             log.debug(iocb)
             log.debug(self.requests_in_progress[iocb])
             if iocb.ioResponse:
                 apdu = iocb.ioResponse
                 value = self.__property_value_from_apdu(apdu)
                 callback_params = self.requests_in_progress[iocb]
                 if callback_params.get("callback") is not None:
                     self.__general_cb(iocb, callback_params, value)
             elif iocb.ioError:
                 log.exception(iocb.ioError)
     except Exception as e:
         log.exception(e)
     if self.requests_in_progress.get(iocb) is not None:
         del self.requests_in_progress[iocb]
Beispiel #29
0
 def server_side_rpc_handler(self, content):
     try:
         log.debug('Recieved RPC Request: %r', str(content))
         for device in self.__devices:
             if device["deviceName"] == content["device"]:
                 method_found = False
                 for request in device["server_side_rpc"]:
                     if request["config"].get("requestType") is not None:
                         if content["data"]["method"] == request["method"]:
                             method_found = True
                             kwargs = request["iocb"][1]
                             timeout = time() * 1000 + request[
                                 "config"].get("requestTimeout", 200)
                             if content["data"].get("params") is not None:
                                 kwargs["config"].update({
                                     "propertyValue":
                                     content["data"]["params"]
                                 })
                             iocb = request["iocb"][0](device, **kwargs)
                             self.__request_functions[
                                 request["config"]["requestType"]](
                                     device=iocb,
                                     callback=self.__rpc_response_cb)
                             self.rpc_requests_in_progress[iocb] = {
                                 "content": content,
                                 "uplink_converter":
                                 request["uplink_converter"]
                             }
                             # self.__gateway.register_rpc_request_timeout(content,
                             #                                             timeout,
                             #                                             iocb,
                             #                                             self.__rpc_cancel_processing)
                     else:
                         log.error(
                             "\"requestType\" not found in request configuration for key %s device: %s",
                             request.get("key", "[KEY IS EMPTY]"),
                             device["deviceName"])
                 if not method_found:
                     log.error("RPC method %s not found in configuration",
                               content["data"]["method"])
                     self.__gateway.send_rpc_reply(content["device"],
                                                   content["data"]["id"],
                                                   success_sent=False)
     except Exception as e:
         log.exception(e)
Beispiel #30
0
    def run(self):
        self.__connected = True
        self.scan_network()
        self._application.do_whois()
        log.debug("WhoIsRequest has been sent.")
        self.scan_network()
        while not self.__stopped:
            sleep(.1)
            for device in self.__devices:
                try:
                    if device.get("previous_check") is None or time(
                    ) * 1000 - device["previous_check"] >= device[
                            "poll_period"]:
                        for mapping_type in ["attributes", "telemetry"]:
                            for config in device[mapping_type]:
                                if config.get(
                                        "uplink_converter"
                                ) is None or config.get(
                                        "downlink_converter") is None:
                                    self.__load_converters(device)
                                data_to_application = {
                                    "device":
                                    device,
                                    "mapping_type":
                                    mapping_type,
                                    "config":
                                    config,
                                    "callback":
                                    self.__bacnet_device_mapping_response_cb
                                }
                                self._application.do_read_property(
                                    **data_to_application)
                        device["previous_check"] = time() * 1000
                    else:
                        sleep(.1)
                except Exception as e:
                    log.exception(e)

            if not self.__convert_and_save_data_queue.empty():
                for _ in range(self.__convert_and_save_data_queue.qsize()):
                    thread = Thread(
                        target=self.__convert_and_save_data,
                        args=(self.__convert_and_save_data_queue, ),
                        daemon=True)
                    thread.start()