1
0
mirror of https://github.com/thingsboard/thingsboard-gateway synced 2025-10-26 22:31:42 +08:00

Improvements for custom serial connector

This commit is contained in:
zbeacon
2019-12-25 01:47:43 +02:00
parent bcd6502668
commit 551514af01
3 changed files with 85 additions and 107 deletions

View File

@@ -1,81 +0,0 @@
# Copyright 2019. ThingsBoard
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import logging
from random import choice
from string import ascii_lowercase
from threading import Thread
from thingsboard_gateway.connectors.connector import Connector
from thingsboard_gateway.tb_utility.tb_utility import TBUtility
from abc import abstractmethod
log = logging.getLogger('extension')
class CustomConnector(Connector, Thread):
def __init__(self, gateway, config, connector_type):
super().__init__()
self.statistics = {'MessagesReceived': 0,
'MessagesSent': 0}
self.__connector_type = connector_type
self.__config = config
self.__gateway = gateway
self.setName(self.__config.get("name",
"Custom %s connector " % self.get_name() + ''.join(choice(ascii_lowercase) for _ in range(5))))
log.info("Starting Custom %s connector", self.get_name())
self.daemon = True
self.stopped = True
self.connected = False
self.devices = {}
self.load_converters()
log.info('Custom connector %s initialization success.', self.get_name())
log.info("Devices in configuration file found: %s ", '\n'.join(device for device in self.devices))
def open(self):
self.stopped = False
self.start()
def close(self):
self.stopped = True
def get_name(self):
return self.name
def is_connected(self):
return self.connected
def load_converters(self):
devices_config = self.__config.get('devices')
try:
if devices_config is not None:
for device_config in devices_config:
if device_config.get('converter') is not None:
converter = TBUtility.check_and_import(self.__connector_type, device_config['converter'])
self.devices[device_config['name']] = {'converter': converter(device_config),
'device_config': device_config}
else:
log.error('Converter configuration for the custom connector %s -- not found, please check your configuration file.', self.get_name())
else:
log.error('Section "devices" in the configuration not found. A custom connector %s has being stopped.', self.get_name())
self.close()
except Exception as e:
log.exception(e)
@abstractmethod
def on_attributes_update(self, content):
pass
@abstractmethod
def server_side_rpc_handler(self, content):
pass

View File

@@ -14,44 +14,99 @@
import serial
import time
from thingsboard_gateway.connectors.custom_connector import CustomConnector, log
from threading import Thread
from random import choice
from string import ascii_lowercase
from thingsboard_gateway.connectors.connector import Connector, log
from thingsboard_gateway.tb_utility.tb_utility import TBUtility
class CustomSerialConnector(CustomConnector):
class CustomSerialConnector(Thread, Connector):
def __init__(self, gateway, config, connector_type):
super().__init__(gateway, config, connector_type)
super().__init__()
self.statistics = {'MessagesReceived': 0,
'MessagesSent': 0}
self.__config = config
self.__gateway = gateway
self.__connector_type = connector_type
self.__config = config
self.__gateway = gateway
self.setName(self.__config.get("name",
"Custom %s connector " % self.get_name() + ''.join(choice(ascii_lowercase) for _ in range(5))))
log.info("Starting Custom %s connector", self.get_name())
self.daemon = True
self.stopped = True
self.connected = False
self.devices = {}
self.load_converters()
self.__connect_to_devices()
log.info('Custom connector %s initialization success.', self.get_name())
log.info("Devices in configuration file found: %s ", '\n'.join(device for device in self.devices))
def __connect_to_devices(self):
for device in self.devices:
try:
connection_start = time.time()
self.devices[device]["serial"] = None
while self.devices[device]["serial"] is None or not self.devices[device]["serial"].isOpen():
self.devices[device]["serial"] = serial.Serial(
port=self.__config.get('port', '/dev/ttyUSB0'),
baudrate=self.__config.get('baudrate', 9600),
bytesize=self.__config.get('bytesize', serial.EIGHTBITS),
parity=self.__config.get('parity', serial.PARITY_NONE),
stopbits=self.__config.get('stopbits', serial.STOPBITS_ONE),
timeout=self.__config.get('timeout', 1),
xonxoff=self.__config.get('xonxoff', False),
rtscts=self.__config.get('rtscts', False),
write_timeout=self.__config.get('write_timeout', None),
dsrdtr=self.__config.get('dsrdtr', False),
inter_byte_timeout=self.__config.get('inter_byte_timeout', None),
exclusive=self.__config.get('exclusive', None)
)
time.sleep(.1)
if time.time() - connection_start > 10:
log.error("Connection refused per timeout for device %s", self.devices[device]["device_config"].get("name"))
break
if self.devices[device].get("serial") is None \
or self.devices[device]["serial"] is None \
or not self.devices[device]["serial"].isOpen():
self.devices[device]["serial"] = None
while self.devices[device]["serial"] is None or not self.devices[device]["serial"].isOpen():
self.devices[device]["serial"] = serial.Serial(
port=self.__config.get('port', '/dev/ttyUSB0'),
baudrate=self.__config.get('baudrate', 9600),
bytesize=self.__config.get('bytesize', serial.EIGHTBITS),
parity=self.__config.get('parity', serial.PARITY_NONE),
stopbits=self.__config.get('stopbits', serial.STOPBITS_ONE),
timeout=self.__config.get('timeout', 1),
xonxoff=self.__config.get('xonxoff', False),
rtscts=self.__config.get('rtscts', False),
write_timeout=self.__config.get('write_timeout', None),
dsrdtr=self.__config.get('dsrdtr', False),
inter_byte_timeout=self.__config.get('inter_byte_timeout', None),
exclusive=self.__config.get('exclusive', None)
)
time.sleep(.1)
if time.time() - connection_start > 10:
log.error("Connection refused per timeout for device %s", self.devices[device]["device_config"].get("name"))
break
except serial.serialutil.SerialException:
log.error("Port %s for device %s - not found", self.__config.get('port', '/dev/ttyUSB0'), device)
time.sleep(10)
except Exception as e:
log.exception(e)
time.sleep(10)
else:
self.__gateway.add_device(self.devices[device]["device_config"]["name"], {"connector": self})
self.connected = True
def open(self):
self.stopped = False
self.start()
def get_name(self):
return self.name
def is_connected(self):
return self.connected
def load_converters(self):
devices_config = self.__config.get('devices')
try:
if devices_config is not None:
for device_config in devices_config:
if device_config.get('converter') is not None:
converter = TBUtility.check_and_import(self.__connector_type, device_config['converter'])
self.devices[device_config['name']] = {'converter': converter(device_config),
'device_config': device_config}
else:
log.error('Converter configuration for the custom connector %s -- not found, please check your configuration file.', self.get_name())
else:
log.error('Section "devices" in the configuration not found. A custom connector %s has being stopped.', self.get_name())
self.close()
except Exception as e:
log.exception(e)
def run(self):
try:
while True:
@@ -60,7 +115,11 @@ class CustomSerialConnector(CustomConnector):
ch = b''
data_from_device = b''
while ch != b'\n':
ch = serial.read(1)
try:
ch = serial.read(1)
except AttributeError:
if serial is None:
self.__connect_to_devices()
data_from_device = data_from_device + ch
try:
converted_data = self.devices[device]['converter'].convert(self.devices[device]['device_config'], data_from_device)
@@ -74,7 +133,7 @@ class CustomSerialConnector(CustomConnector):
log.exception(e)
def close(self):
super().close()
self.stopped = True
for device in self.devices:
self.__gateway.del_device(self.devices[device])
if self.devices[device]['serial'].isOpen():

View File

@@ -90,7 +90,7 @@ class TBUtility:
body = loads(body)
if not expression:
return ''
positions = match(r'\$\{(?:(.*))\}', expression)
positions = search(r'\$\{(?:(.*))\}', expression)
if positions is not None:
p1 = positions.regs[-1][0]
p2 = positions.regs[-1][1]