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

Merge branch 'develop/2.4-python' of https://github.com/thingsboard/thingsboard-gateway into feature/ODBC-connector

This commit is contained in:
zbeacon
2020-05-05 12:55:40 +03:00
13 changed files with 101 additions and 47 deletions

View File

@@ -52,17 +52,13 @@ setup(
'pip',
'jsonschema==3.1.1',
'lxml',
'opcua',
'paho-mqtt',
'pymodbus>=2.3.0',
'pyserial',
'pytz',
'PyYAML',
'simplejson',
'pyrsistent',
'requests',
'python-can',
'bacpypes>=0.18.0'
'requests'
],
download_url='https://github.com/thingsboard/thingsboard-gateway/archive/%s.tar.gz' % VERSION,
entry_points={

View File

@@ -136,14 +136,14 @@
"rpc": [
{
"tag": "setValue",
"type": "bit",
"type": "bits",
"functionCode": 5,
"objectsCount": 1,
"address": 31
},
{
"tag": "getValue",
"type": "bit",
"type": "bits",
"functionCode": 1,
"objectsCount": 1,
"address": 31

View File

@@ -12,16 +12,24 @@
# See the License for the specific language governing permissions and
# limitations under the License.
from copy import deepcopy
from random import choice
from threading import Thread
from time import time, sleep
from string import ascii_lowercase
from bacpypes.core import run, stop
from thingsboard_gateway.tb_utility.tb_utility import TBUtility
try:
from bacpypes.core import run, stop
except ImportError:
print("BACnet library not found - installing...")
TBUtility.install_package("bacpypes", ">=0.18.0")
from bacpypes.core import run, stop
from bacpypes.pdu import Address, GlobalBroadcast, LocalBroadcast, LocalStation, RemoteStation
from thingsboard_gateway.connectors.connector import Connector, log
from thingsboard_gateway.connectors.bacnet.bacnet_utilities.tb_gateway_bacnet_application import TBBACnetApplication
from thingsboard_gateway.tb_utility.tb_utility import TBUtility
class BACnetConnector(Thread, Connector):

View File

@@ -15,16 +15,22 @@
import re
import sched
import time
from threading import Thread
from copy import copy
from random import choice
from string import ascii_lowercase
from can import Notifier, BufferedReader, Message, CanError, ThreadSafeBus
from threading import Thread
from thingsboard_gateway.tb_utility.tb_utility import TBUtility
try:
from can import Notifier, BufferedReader, Message, CanError, ThreadSafeBus
except ImportError:
print("CAN library not found - installing...")
TBUtility.install_package("python-can")
from can import Notifier, BufferedReader, Message, CanError, ThreadSafeBus
from thingsboard_gateway.connectors.can.bytes_can_downlink_converter import BytesCanDownlinkConverter
from thingsboard_gateway.connectors.can.bytes_can_uplink_converter import BytesCanUplinkConverter
from thingsboard_gateway.connectors.connector import Connector, log
from thingsboard_gateway.tb_utility.tb_utility import TBUtility
class CanConnector(Connector, Thread):

View File

@@ -62,14 +62,15 @@ class BytesModbusDownlinkConverter(ModbusConverter):
lower_type = str(variable_size) + "float"
assert builder_functions.get(lower_type) is not None
builder_functions[lower_type](value)
elif lower_type in ["coil", "bits"]:
elif lower_type in ["coil", "bits", "coils", "bit"]:
assert builder_functions.get("bits") is not None
builder_functions["bits"](value)
if variable_size/8 > 1.0:
builder_functions["bits"](value)
else:
return bytes(bool(int(value)))
elif lower_type in ["string"]:
assert builder_functions.get("string") is not None
builder_functions[lower_type](value)
elif lower_type in ["bit"]:
return bytes(bool(int(value)))
elif lower_type in builder_functions:
builder_functions[lower_type](value)
else:

View File

@@ -36,8 +36,8 @@ class BytesModbusUplinkConverter(ModbusConverter):
try:
configuration = data[config_data][tag]["data_sent"]
response = data[config_data][tag]["input_data"]
if config.get("byteOrder"):
byte_order = config["byteOrder"]
if configuration.get("byteOrder") is not None:
byte_order = configuration["byteOrder"]
else:
byte_order = configuration.get("byteOrder", "LITTLE")
endian_order = Endian.Little if byte_order.upper() == "LITTLE" else Endian.Big
@@ -47,9 +47,9 @@ class BytesModbusUplinkConverter(ModbusConverter):
result = response.bits
result = result if byte_order.upper() == 'LITTLE' else result[::-1]
log.debug(result)
if configuration["type"].lower() == "bit":
if configuration["type"].lower() == "bits":
decoded_data = result[:configuration.get("objectsCount", configuration.get("registersCount", configuration.get("registerCount", 1)))]
if len(decoded_data) == 1:
if len(decoded_data) == 1 and isinstance(decoded_data, list):
decoded_data = decoded_data[0]
else:
decoded_data = result[0]
@@ -127,10 +127,6 @@ class BytesModbusUplinkConverter(ModbusConverter):
assert decoder_functions.get(type_) is not None
decoded = decoder_functions[type_]()
elif lower_type == 'bit':
bit_address = configuration["bit"]
decoded = decoder_functions[type_]()[bit_address]
else:
log.error("Unknown type: %s", type_)
@@ -141,7 +137,7 @@ class BytesModbusUplinkConverter(ModbusConverter):
elif isinstance(decoded, bytes) and lower_type == "bytes":
result_data = decoded
elif isinstance(decoded, list):
result_data = str(decoded)
result_data = decoded
elif isinstance(decoded, float):
result_data = decoded
elif decoded is not None:

View File

@@ -17,7 +17,15 @@ import threading
from random import choice
from string import ascii_lowercase
from pymodbus.constants import Defaults
from thingsboard_gateway.tb_utility.tb_utility import TBUtility
# Try import Pymodbus library or install it and import
try:
from pymodbus.constants import Defaults
except ImportError:
print("Modbus library not found - installing...")
TBUtility.install_package("pymodbus", ">=2.3.0")
from pymodbus.constants import Defaults
from pymodbus.client.sync import ModbusTcpClient, ModbusUdpClient, ModbusSerialClient, ModbusRtuFramer, ModbusSocketFramer
from pymodbus.bit_write_message import WriteSingleCoilResponse, WriteMultipleCoilsResponse
from pymodbus.register_write_message import WriteMultipleRegistersResponse, \
@@ -26,7 +34,6 @@ from pymodbus.register_read_message import ReadRegistersResponseBase
from pymodbus.bit_read_message import ReadBitsResponseBase
from pymodbus.exceptions import ConnectionException
from thingsboard_gateway.tb_utility.tb_utility import TBUtility
from thingsboard_gateway.connectors.connector import Connector, log
from thingsboard_gateway.connectors.modbus.bytes_modbus_uplink_converter import BytesModbusUplinkConverter
from thingsboard_gateway.connectors.modbus.bytes_modbus_downlink_converter import BytesModbusDownlinkConverter
@@ -185,7 +192,20 @@ class ModbusConnector(Connector, threading.Thread):
log.exception(e)
def on_attributes_update(self, content):
pass
try:
for attribute_updates_command_config in self.__devices[content["device"]]["config"]["attributeUpdates"]:
for attribute_updated in content["data"]:
if attribute_updates_command_config["tag"] == attribute_updated:
to_process = {
"device": content["device"],
"data": {
"method": attribute_updated,
"params": content["data"][attribute_updated]
}
}
self.__process_rpc_request(to_process, attribute_updates_command_config)
except Exception as e:
log.exception(e)
def __configure_master(self):
host = self.__config.get("host", "localhost")
@@ -246,6 +266,7 @@ class ModbusConnector(Connector, threading.Thread):
def server_side_rpc_handler(self, content):
try:
if content.get("device") is not None:
log.debug("Modbus connector received rpc request for %s with content: %s", content["device"], content)
if isinstance(self.__devices[content["device"]]["config"]["rpc"], dict):
rpc_command_config = self.__devices[content["device"]]["config"]["rpc"].get(content["data"]["method"])
@@ -255,6 +276,7 @@ class ModbusConnector(Connector, threading.Thread):
for rpc_command_config in self.__devices[content["device"]]["config"]["rpc"]:
if rpc_command_config["tag"] == content["data"]["method"]:
self.__process_rpc_request(content, rpc_command_config)
break
else:
log.error("Received rpc request, but method %s not found in config for %s.",
content["data"].get("method"),
@@ -293,12 +315,13 @@ class ModbusConnector(Connector, threading.Thread):
WriteSingleRegisterResponse)):
log.debug("Write %r", str(response))
response = {"success": True}
if isinstance(response, Exception):
self.__gateway.send_rpc_reply(content["device"],
content["data"]["id"],
{content["data"]["method"]: str(response)})
else:
self.__gateway.send_rpc_reply(content["device"],
content["data"]["id"],
response)
if content.get("id") or (content.get("data") is not None and content["data"].get("id")):
if isinstance(response, Exception):
self.__gateway.send_rpc_reply(content["device"],
content["data"]["id"],
{content["data"]["method"]: str(response)})
else:
self.__gateway.send_rpc_reply(content["device"],
content["data"]["id"],
response)
log.debug("%r", response)

View File

@@ -175,7 +175,7 @@ class MqttConnector(Connector, Thread):
self._client.loop_start()
if not self._connected:
time.sleep(1)
except Exception as e:
except ConnectionRefusedError as e:
self.__log.exception(e)
time.sleep(10)

View File

@@ -20,9 +20,14 @@ from random import choice
from threading import Thread
from string import ascii_lowercase
import regex
from opcua import Client, ua
from simplejson import dumps
from thingsboard_gateway.tb_utility.tb_utility import TBUtility
try:
from opcua import Client, ua
except ImportError:
print("OPC-UA library not found")
TBUtility.install_package("opcua")
from opcua import Client, ua
from thingsboard_gateway.connectors.connector import Connector, log
from thingsboard_gateway.connectors.opcua.opcua_uplink_converter import OpcUaUplinkConverter

View File

@@ -19,12 +19,18 @@ from string import ascii_lowercase
from time import sleep, time
from re import fullmatch
import requests
from requests import Timeout
# import requests
from thingsboard_gateway.tb_utility.tb_utility import TBUtility
try:
from requests import Timeout, request
except ImportError:
print("Requests library not found - installing...")
TBUtility.install_package("requests")
from requests import Timeout, request
from requests.auth import HTTPBasicAuth
from requests.exceptions import RequestException
from thingsboard_gateway.tb_utility.tb_utility import TBUtility
from thingsboard_gateway.connectors.connector import Connector, log
from thingsboard_gateway.connectors.request.json_request_uplink_converter import JsonRequestUplinkConverter
from thingsboard_gateway.connectors.request.json_request_downlink_converter import JsonRequestDownlinkConverter
@@ -80,7 +86,7 @@ class RequestConnector(Connector, Thread):
response_queue = Queue(1)
request_dict = {"config": {**attribute_request,
**converted_data},
"request": requests.request}
"request": request}
attribute_update_request_thread = Thread(target=self.__send_request,
args=(request_dict, response_queue, log),
daemon=True,
@@ -102,7 +108,7 @@ class RequestConnector(Connector, Thread):
response_queue = Queue(1)
request_dict = {"config": {**rpc_request,
**converted_data},
"request": requests.request}
"request": request}
request_dict["config"].get("uplink_converter")
rpc_request_thread = Thread(target=self.__send_request,
args=(request_dict, response_queue, log),
@@ -138,7 +144,7 @@ class RequestConnector(Connector, Thread):
self.__requests_in_progress.append({"config": endpoint,
"converter": converter,
"next_time": time(),
"request": requests.request})
"request": request})
except Exception as e:
log.exception(e)

View File

@@ -464,6 +464,7 @@ class TBGatewayService:
result = self.__gateway_rpc_methods[method_to_call]()
else:
result = self.__gateway_rpc_methods[method_to_call]()
log.debug(result)
return result
def __rpc_ping(self, *args):

View File

@@ -166,7 +166,7 @@ class EventStorageReader:
def delete_read_file(self, current_file: EventStorageReaderPointer):
try:
data_files = self.files.get_data_files()
if exists(self.settings.get_data_folder_path() + current_file.file):
if exists(self.settings.get_data_folder_path() + current_file.file) and len(data_files) > 1:
remove(self.settings.get_data_folder_path() + current_file.file)
data_files.remove(current_file.file)
log.info("FileStorage_reader -- Cleanup old data file: %s%s!", self.settings.get_data_folder_path(), current_file.file)

View File

@@ -47,7 +47,10 @@ class TBUtility:
error = 'No telemetry and attributes in data: '
if error is not None:
json_data = dumps(data)
log.error(error+json_data.decode("UTF-8"))
if isinstance(json_data, bytes):
log.error(error+json_data.decode("UTF-8"))
else:
log.error(error + json_data)
return False
return True
@@ -137,3 +140,12 @@ class TBUtility:
except Exception as e:
log.exception(e)
return full_value
@staticmethod
def install_package(package, version="upgrade"):
from sys import executable
from subprocess import check_call
if version.lower() == "upgrade":
check_call([executable, "-m", "pip", "install", package, "--upgrade", "--user"])
else:
check_call([executable, "-m", "pip", "install", package + version, "--user"])