mirror of
				https://github.com/thingsboard/thingsboard-gateway
				synced 2025-10-26 22:31:42 +08:00 
			
		
		
		
	Fixed sqlite storage
This commit is contained in:
		
							parent
							
								
									daa865d644
								
							
						
					
					
						commit
						5b021029a2
					
				
							
								
								
									
										8
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										8
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							|  | @ -5,9 +5,6 @@ thingsboard_gateway/develop_tests/ | |||
| thingsboard_gateway/logs/* | ||||
| thingsboard_gateway/config/connected_devices.json | ||||
| thingsboard_gateway/storage/data/ | ||||
| thingsboard_gateway.egg-info/ | ||||
| .vscode/ | ||||
| /debug_utils/ | ||||
| .idea/ | ||||
| /build/ | ||||
| /deb_dist/ | ||||
|  | @ -15,14 +12,13 @@ thingsboard_gateway.egg-info/ | |||
| /.mypy_cache/ | ||||
| /thingsboard_gateway/storage/data_out/ | ||||
| *.gz | ||||
| *.orig | ||||
| /logs/ | ||||
| /python3-thingsboard-gateway.deb | ||||
| /python3-thingsboard-gateway.rpm | ||||
| /thingsboard_gateway.egg-info/ | ||||
| /docker/python3-thingsboard-gateway.deb | ||||
| /data/ | ||||
| /tests/storage/data/ | ||||
| /logs/ | ||||
| __pycache__ | ||||
| /thingsboard_gateway/config/ | ||||
| /venv/ | ||||
| *.db | ||||
|  |  | |||
|  | @ -1,4 +1,3 @@ | |||
| 
 | ||||
| #!/bin/sh | ||||
| #      Copyright 2021. ThingsBoard | ||||
| # | ||||
|  | @ -46,4 +45,4 @@ echo "Enabling daemon..." | |||
| sudo pidof systemd && sudo systemctl enable thingsboard-gateway || echo "Systemctl not found" | ||||
| #echo "Daemon starting..." | ||||
| sudo pidof systemd && sudo systemctl start thingsboard-gateway || echo | ||||
| echo -e "\e[96mThingsboard Gateway \e[92mhas been installed. Have a nice day \e[93m\e[5m:)\e[25m\e[39m" | ||||
| echo -e "\e[96mThingsboard Gateway \e[92mhas been installed. Have a nice day \e[93m\e[5m:)\e[25m\e[39m" | ||||
|  |  | |||
|  | @ -18,4 +18,4 @@ set -e | |||
| echo "Installing directory for configs..." | ||||
| sudo mkdir /etc/thingsboard-gateway || echo | ||||
| sudo adduser --system --gecos "ThingsBoard-Gateway Service" --disabled-password --group --home /var/lib/thingsboard_gateway thingsboard_gateway || echo "User exists" | ||||
| sudo mkdir /var/lib/thingsboard_gateway/extensions || echo | ||||
| sudo mkdir /var/lib/thingsboard_gateway/extensions || echo | ||||
|  |  | |||
|  | @ -1,53 +1,53 @@ | |||
| { | ||||
|   "name": "BLE Connector", | ||||
|   "rescanIntervalSeconds": 100, | ||||
|   "checkIntervalSeconds": 100, | ||||
|   "scanTimeSeconds": 5, | ||||
|   "passiveScanMode": true, | ||||
|   "devices": [ | ||||
|     { | ||||
|       "name": "Temperature and humidity sensor", | ||||
|       "MACAddress": "4C:65:A8:DF:85:C0", | ||||
|       "addrType": "public", | ||||
|       "telemetry": [ | ||||
|     "name": "BLE Connector", | ||||
|     "rescanIntervalSeconds": 100, | ||||
|     "checkIntervalSeconds": 100, | ||||
|     "scanTimeSeconds": 5, | ||||
|     "passiveScanMode": true, | ||||
|     "devices": [ | ||||
|         { | ||||
|           "key": "temperature", | ||||
|           "method": "notify", | ||||
|           "characteristicUUID": "226CAA55-6476-4566-7562-66734470666D", | ||||
|           "byteFrom": 2, | ||||
|           "byteTo": 6 | ||||
|         }, | ||||
|         { | ||||
|           "key": "humidity", | ||||
|           "method": "notify", | ||||
|           "characteristicUUID": "226CAA55-6476-4566-7562-66734470666D", | ||||
|           "byteFrom": 9, | ||||
|           "byteTo": 13 | ||||
|             "name": "Temperature and humidity sensor", | ||||
|             "MACAddress": "4C:65:A8:DF:85:C0", | ||||
|             "addrType": "public", | ||||
|             "telemetry": [ | ||||
|                 { | ||||
|                     "key": "temperature", | ||||
|                     "method": "notify", | ||||
|                     "characteristicUUID": "226CAA55-6476-4566-7562-66734470666D", | ||||
|                     "byteFrom": 2, | ||||
|                     "byteTo": 6 | ||||
|                 }, | ||||
|                 { | ||||
|                     "key": "humidity", | ||||
|                     "method": "notify", | ||||
|                     "characteristicUUID": "226CAA55-6476-4566-7562-66734470666D", | ||||
|                     "byteFrom": 9, | ||||
|                     "byteTo": 13 | ||||
|                 } | ||||
|             ], | ||||
|             "attributes": [ | ||||
|                 { | ||||
|                     "key": "name", | ||||
|                     "characteristicUUID": "00002A00-0000-1000-8000-00805F9B34FB", | ||||
|                     "method": "read", | ||||
|                     "byteFrom": 0, | ||||
|                     "byteTo": -1 | ||||
|                 } | ||||
|             ], | ||||
|             "attributeUpdates": [ | ||||
|                 { | ||||
|                     "attributeOnThingsBoard": "sharedName", | ||||
|                     "characteristicUUID": "00002A00-0000-1000-8000-00805F9B34FB" | ||||
|                 } | ||||
|             ], | ||||
|             "serverSideRpc": [ | ||||
|                 { | ||||
|                     "methodRPC": "rpcMethod1", | ||||
|                     "withResponse": true, | ||||
|                     "characteristicUUID": "00002A00-0000-1000-8000-00805F9B34FB", | ||||
|                     "methodProcessing": "read" | ||||
|                 } | ||||
|             ] | ||||
|         } | ||||
|       ], | ||||
|       "attributes": [ | ||||
|         { | ||||
|           "key": "name", | ||||
|           "characteristicUUID": "00002A00-0000-1000-8000-00805F9B34FB", | ||||
|           "method": "read", | ||||
|           "byteFrom": 0, | ||||
|           "byteTo": -1 | ||||
|         } | ||||
|       ], | ||||
|       "attributeUpdates": [ | ||||
|         { | ||||
|           "attributeOnThingsBoard": "sharedName", | ||||
|           "characteristicUUID": "00002A00-0000-1000-8000-00805F9B34FB" | ||||
|         } | ||||
|       ], | ||||
|       "serverSideRpc": [ | ||||
|         { | ||||
|           "methodRPC": "rpcMethod1", | ||||
|           "withResponse": true, | ||||
|           "characteristicUUID": "00002A00-0000-1000-8000-00805F9B34FB", | ||||
|           "methodProcessing": "read" | ||||
|         } | ||||
|       ] | ||||
|     } | ||||
|   ] | ||||
| } | ||||
|     ] | ||||
| } | ||||
|  |  | |||
|  | @ -14,7 +14,7 @@ | |||
|           "untilDelimiter": "\r" | ||||
|         } | ||||
|       ], | ||||
|       "attributes": [ | ||||
|       "attributes":[ | ||||
|         { | ||||
|           "key": "SerialNumber", | ||||
|           "type": "string", | ||||
|  | @ -30,4 +30,4 @@ | |||
|       ] | ||||
|     } | ||||
|   ] | ||||
| } | ||||
| } | ||||
|  |  | |||
|  | @ -5,83 +5,83 @@ keys=consoleHandler, serviceHandler, connectorHandler, converterHandler, tb_conn | |||
| [formatters] | ||||
| keys=LogFormatter | ||||
| [logger_root] | ||||
| level=INFO | ||||
| level=ERROR | ||||
| handlers=consoleHandler | ||||
| [logger_connector] | ||||
| level=DEBUG | ||||
| level=INFO | ||||
| handlers=connectorHandler | ||||
| formatter=LogFormatter | ||||
| qualname=connector | ||||
| [logger_storage] | ||||
| level=DEBUG | ||||
| level=INFO | ||||
| handlers=storageHandler | ||||
| formatter=LogFormatter | ||||
| qualname=storage | ||||
| [logger_database] | ||||
| level=DEBUG | ||||
| level=INFO | ||||
| handlers=databaseHandler | ||||
| formatter=LogFormatter | ||||
| qualname=database | ||||
| [logger_tb_connection] | ||||
| level=DEBUG | ||||
| level=INFO | ||||
| handlers=tb_connectionHandler | ||||
| formatter=LogFormatter | ||||
| qualname=tb_connection | ||||
| [logger_service] | ||||
| level=DEBUG | ||||
| level=INFO | ||||
| handlers=serviceHandler | ||||
| formatter=LogFormatter | ||||
| qualname=service | ||||
| [logger_converter] | ||||
| level=DEBUG | ||||
| level=INFO | ||||
| handlers=converterHandler | ||||
| formatter=LogFormatter | ||||
| qualname=converter | ||||
| [logger_extension] | ||||
| level=DEBUG | ||||
| level=INFO | ||||
| handlers=connectorHandler | ||||
| formatter=LogFormatter | ||||
| qualname=extension | ||||
| [handler_consoleHandler] | ||||
| class=StreamHandler | ||||
| level=DEBUG | ||||
| level=INFO | ||||
| formatter=LogFormatter | ||||
| args=(sys.stdout,) | ||||
| [handler_connectorHandler] | ||||
| level=DEBUG | ||||
| level=INFO | ||||
| class=logging.handlers.TimedRotatingFileHandler | ||||
| formatter=LogFormatter | ||||
| args=("./logs/connector.log", "d", 1, 7,) | ||||
| [handler_storageHandler] | ||||
| level=DEBUG | ||||
| level=INFO | ||||
| class=logging.handlers.TimedRotatingFileHandler | ||||
| formatter=LogFormatter | ||||
| args=("./logs/storage.log", "d", 1, 7,) | ||||
| [handler_databaseHandler] | ||||
| level=DEBUG | ||||
| level=INFO | ||||
| class=logging.handlers.TimedRotatingFileHandler | ||||
| formatter=LogFormatter | ||||
| args=("./logs/database.log", "d", 1, 7,) | ||||
| [handler_serviceHandler] | ||||
| level=DEBUG | ||||
| level=INFO | ||||
| class=logging.handlers.TimedRotatingFileHandler | ||||
| formatter=LogFormatter | ||||
| args=("./logs/service.log", "d", 1, 7,) | ||||
| [handler_converterHandler] | ||||
| level=DEBUG | ||||
| level=INFO | ||||
| class=logging.handlers.TimedRotatingFileHandler | ||||
| formatter=LogFormatter | ||||
| args=("./logs/converter.log", "d", 1, 3,) | ||||
| [handler_extensionHandler] | ||||
| level=DEBUG | ||||
| level=INFO | ||||
| class=logging.handlers.TimedRotatingFileHandler | ||||
| formatter=LogFormatter | ||||
| args=("./logs/extension.log", "d", 1, 3,) | ||||
| [handler_tb_connectionHandler] | ||||
| level=DEBUG | ||||
| level=INFO | ||||
| class=logging.handlers.TimedRotatingFileHandler | ||||
| formatter=LogFormatter | ||||
| args=("./logs/tb_connection.log", "d", 1, 3,) | ||||
| [formatter_LogFormatter] | ||||
| format="%(asctime)s - |%(levelname)s| - [%(filename)s] - %(module)s - %(funcName)s - %(lineno)d - %(message)s"  | ||||
| format="%(asctime)s - |%(levelname)s| - [%(filename)s] - %(module)s - %(funcName)s - %(lineno)d - %(message)s" | ||||
| datefmt="%Y-%m-%d %H:%M:%S" | ||||
|  |  | |||
|  | @ -75,8 +75,8 @@ | |||
|             "objectsCount": 4, | ||||
|             "address": 13 | ||||
|           } | ||||
|         ], | ||||
|         "timeseries": [ | ||||
|       ], | ||||
|       "timeseries": [ | ||||
|           { | ||||
|             "tag": "8uint_read", | ||||
|             "type": "8uint", | ||||
|  | @ -159,7 +159,7 @@ | |||
|             "address": 33 | ||||
|           }, | ||||
|           { | ||||
|             "tag": "getCPULoad", | ||||
|             "tag":"getCPULoad", | ||||
|             "type": "32int", | ||||
|             "functionCode": 4, | ||||
|             "objectsCount": 2, | ||||
|  |  | |||
|  | @ -1,8 +1,9 @@ | |||
| { | ||||
|   "broker": { | ||||
|     "name":"Default Local Broker", | ||||
|     "host":"192.168.1.100", | ||||
|     "host":"127.0.0.1", | ||||
|     "port":1883, | ||||
|     "clientId": "ThingsBoard_gateway", | ||||
|     "security": { | ||||
|       "type": "basic", | ||||
|       "username": "user", | ||||
|  | @ -22,6 +23,11 @@ | |||
|             "type": "string", | ||||
|             "key": "model", | ||||
|             "value": "${sensorModel}" | ||||
|           }, | ||||
|           { | ||||
|             "type": "string", | ||||
|             "key": "${sensorModel}", | ||||
|             "value": "on" | ||||
|           } | ||||
|         ], | ||||
|         "timeseries": [ | ||||
|  | @ -123,4 +129,4 @@ | |||
|       "valueExpression": "${params}" | ||||
|     } | ||||
|   ] | ||||
| } | ||||
| } | ||||
|  |  | |||
|  | @ -47,12 +47,8 @@ | |||
|       "procedureOne", | ||||
|       { | ||||
|         "name": "procedureTwo", | ||||
|         "args": [ | ||||
|           "One", | ||||
|           2, | ||||
|           3.0 | ||||
|         ] | ||||
|         "args": [ "One", 2, 3.0 ] | ||||
|       } | ||||
|     ] | ||||
|   } | ||||
| } | ||||
| } | ||||
|  |  | |||
|  | @ -4,7 +4,7 @@ | |||
|     "url": "localhost:4840/freeopcua/server/", | ||||
|     "timeoutInMillis": 5000, | ||||
|     "scanPeriodInMillis": 5000, | ||||
|     "disableSubscriptions": false, | ||||
|     "disableSubscriptions":false, | ||||
|     "subCheckPeriodInMillis": 100, | ||||
|     "showMap": false, | ||||
|     "security": "Basic128Rsa15", | ||||
|  | @ -34,10 +34,7 @@ | |||
|         "rpc_methods": [ | ||||
|           { | ||||
|             "method": "multiply", | ||||
|             "arguments": [ | ||||
|               2, | ||||
|               4 | ||||
|             ] | ||||
|             "arguments": [2, 4] | ||||
|           } | ||||
|         ], | ||||
|         "attributes_updates": [ | ||||
|  | @ -49,4 +46,4 @@ | |||
|       } | ||||
|     ] | ||||
|   } | ||||
| } | ||||
| } | ||||
|  |  | |||
|  | @ -121,19 +121,19 @@ | |||
|     } | ||||
|   ], | ||||
|   "attributeUpdates": [ | ||||
|     { | ||||
|       "httpMethod": "POST", | ||||
|       "httpHeaders": { | ||||
|         "CONTENT-TYPE": "application/json" | ||||
|       }, | ||||
|       "timeout": 0.5, | ||||
|       "tries": 3, | ||||
|       "allowRedirects": true, | ||||
|       "deviceNameFilter": "SD.*", | ||||
|       "attributeFilter": "send_data", | ||||
|       "requestUrlExpression": "sensor/${deviceName}/${attributeKey}", | ||||
|       "valueExpression": "{\"${attributeKey}\":\"${attributeValue}\"}" | ||||
|     } | ||||
|       { | ||||
|         "httpMethod": "POST", | ||||
|         "httpHeaders": { | ||||
|           "CONTENT-TYPE": "application/json" | ||||
|         }, | ||||
|         "timeout": 0.5, | ||||
|         "tries": 3, | ||||
|         "allowRedirects": true, | ||||
|         "deviceNameFilter": "SD.*", | ||||
|         "attributeFilter": "send_data", | ||||
|         "requestUrlExpression": "sensor/${deviceName}/${attributeKey}", | ||||
|         "valueExpression": "{\"${attributeKey}\":\"${attributeValue}\"}" | ||||
|       } | ||||
|   ], | ||||
|   "serverSideRpc": [ | ||||
|     { | ||||
|  | @ -160,4 +160,4 @@ | |||
|       } | ||||
|     } | ||||
|   ] | ||||
| } | ||||
| } | ||||
|  |  | |||
|  | @ -1,13 +1,14 @@ | |||
| { | ||||
|   "host": "127.0.0.1", | ||||
|   "port": "5000", | ||||
|   "mapping": [ | ||||
|   "mapping":[ | ||||
|     { | ||||
|       "endpoint": "/device1", | ||||
|       "HTTPMethods": [ | ||||
|         "POST" | ||||
|       ], | ||||
|       "security": { | ||||
|       "security": | ||||
|       { | ||||
|         "type": "basic", | ||||
|         "username": "user", | ||||
|         "password": "passwd" | ||||
|  | @ -43,7 +44,8 @@ | |||
|         "GET", | ||||
|         "POST" | ||||
|       ], | ||||
|       "security": { | ||||
|       "security": | ||||
|       { | ||||
|         "type": "anonymous" | ||||
|       }, | ||||
|       "converter": { | ||||
|  | @ -76,7 +78,8 @@ | |||
|       "HTTPMethods": [ | ||||
|         "POST" | ||||
|       ], | ||||
|       "security": { | ||||
|       "security": | ||||
|       { | ||||
|         "type": "anonymous" | ||||
|       }, | ||||
|       "converter": { | ||||
|  | @ -86,38 +89,37 @@ | |||
|         "extension": "CustomRestUplinkConverter", | ||||
|         "extension-config": [ | ||||
|           { | ||||
|             "key": "Totaliser", | ||||
|             "datatype": "float", | ||||
|             "fromByte": 0, | ||||
|             "toByte": 4, | ||||
|             "byteorder": "big", | ||||
|             "signed": true, | ||||
|             "multiplier": 1 | ||||
|           } | ||||
|         ] | ||||
|           "key": "Totaliser", | ||||
|           "datatype": "float", | ||||
|           "fromByte": 0, | ||||
|           "toByte": 4, | ||||
|           "byteorder": "big", | ||||
|           "signed": true, | ||||
|           "multiplier": 1 | ||||
|           }] | ||||
|       } | ||||
|     } | ||||
|   ], | ||||
|   "attributeUpdates": [ | ||||
|     { | ||||
|       "HTTPMethod": "POST", | ||||
|       "SSLVerify": false, | ||||
|       "httpHeaders": { | ||||
|         "CONTENT-TYPE": "application/json" | ||||
|       }, | ||||
|       "security": { | ||||
|         "type": "basic", | ||||
|         "username": "user", | ||||
|         "password": "passwd" | ||||
|       }, | ||||
|       "timeout": 0.5, | ||||
|       "tries": 3, | ||||
|       "allowRedirects": true, | ||||
|       "deviceNameFilter": ".*REST$", | ||||
|       "attributeFilter": "data", | ||||
|       "requestUrlExpression": "sensor/${deviceName}/${attributeKey}", | ||||
|       "valueExpression": "{\"${attributeKey}\":\"${attributeValue}\"}" | ||||
|     } | ||||
|       { | ||||
|         "HTTPMethod": "POST", | ||||
|         "SSLVerify": false, | ||||
|         "httpHeaders": { | ||||
|           "CONTENT-TYPE": "application/json" | ||||
|         }, | ||||
|         "security": { | ||||
|           "type": "basic", | ||||
|           "username": "user", | ||||
|           "password": "passwd" | ||||
|         }, | ||||
|         "timeout": 0.5, | ||||
|         "tries": 3, | ||||
|         "allowRedirects": true, | ||||
|         "deviceNameFilter": ".*REST$", | ||||
|         "attributeFilter": "data", | ||||
|         "requestUrlExpression": "sensor/${deviceName}/${attributeKey}", | ||||
|         "valueExpression": "{\"${attributeKey}\":\"${attributeValue}\"}" | ||||
|       } | ||||
|   ], | ||||
|   "serverSideRpc": [ | ||||
|     { | ||||
|  | @ -147,4 +149,4 @@ | |||
|       } | ||||
|     } | ||||
|   ] | ||||
| } | ||||
| } | ||||
|  |  | |||
|  | @ -11,3 +11,4 @@ | |||
| #     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. | ||||
| 
 | ||||
|  |  | |||
|  | @ -11,3 +11,4 @@ | |||
| #     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. | ||||
| 
 | ||||
|  |  | |||
|  | @ -11,3 +11,4 @@ | |||
| #     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. | ||||
| 
 | ||||
|  |  | |||
|  | @ -11,3 +11,4 @@ | |||
| #     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. | ||||
| 
 | ||||
|  |  | |||
|  | @ -13,7 +13,6 @@ | |||
| #     limitations under the License. | ||||
| 
 | ||||
| from simplejson import dumps | ||||
| 
 | ||||
| from thingsboard_gateway.connectors.mqtt.mqtt_uplink_converter import MqttUplinkConverter, log | ||||
| 
 | ||||
| 
 | ||||
|  | @ -24,8 +23,7 @@ class CustomMqttUplinkConverter(MqttUplinkConverter): | |||
| 
 | ||||
|     def convert(self, topic, body): | ||||
|         try: | ||||
|             self.dict_result["deviceName"] = topic.split("/")[ | ||||
|                 -1]  # getting all data after last '/' symbol in this case: if topic = 'devices/temperature/sensor1' device name will be 'sensor1'. | ||||
|             self.dict_result["deviceName"] = topic.split("/")[-1] # getting all data after last '/' symbol in this case: if topic = 'devices/temperature/sensor1' device name will be 'sensor1'. | ||||
|             self.dict_result["deviceType"] = "Thermostat"  # just hardcode this | ||||
|             self.dict_result["telemetry"] = []  # template for telemetry array | ||||
|             bytes_to_read = body.replace("0x", "")  # Replacing the 0x (if '0x' in body), needs for converting to bytearray | ||||
|  | @ -34,7 +32,7 @@ class CustomMqttUplinkConverter(MqttUplinkConverter): | |||
|                 for telemetry_key in self.__config["extension-config"]:  # Processing every telemetry key in config for extension | ||||
|                     value = 0 | ||||
|                     for _ in range(self.__config["extension-config"][telemetry_key]):  # reading every value with value length from config | ||||
|                         value = value * 256 + converted_bytes.pop(0)  # process and remove byte from processing | ||||
|                         value = value*256 + converted_bytes.pop(0)  # process and remove byte from processing | ||||
|                     telemetry_to_send = {telemetry_key.replace("Bytes", ""): value}  # creating telemetry data for sending into Thingsboard | ||||
|                     self.dict_result["telemetry"].append(telemetry_to_send)  # adding data to telemetry array | ||||
|             else: | ||||
|  |  | |||
|  | @ -11,3 +11,4 @@ | |||
| #     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. | ||||
| 
 | ||||
|  |  | |||
|  | @ -16,8 +16,8 @@ import struct | |||
| 
 | ||||
| from simplejson import dumps | ||||
| 
 | ||||
| from thingsboard_gateway.connectors.request.request_converter import RequestConverter, log | ||||
| from thingsboard_gateway.tb_utility.tb_utility import TBUtility | ||||
| from thingsboard_gateway.connectors.request.request_converter import RequestConverter, log | ||||
| 
 | ||||
| 
 | ||||
| class CustomRequestUplinkConverter(RequestConverter): | ||||
|  |  | |||
|  | @ -23,7 +23,7 @@ class CustomSerialUplinkConverter(Converter): | |||
|             'deviceType': config.get('deviceType', 'default'), | ||||
|             'attributes': [], | ||||
|             'telemetry': [] | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|     def convert(self, config, data: bytes): | ||||
|         keys = ['attributes', 'telemetry'] | ||||
|  |  | |||
							
								
								
									
										2
									
								
								setup.py
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								setup.py
									
									
									
									
									
								
							|  | @ -34,7 +34,7 @@ setup( | |||
|     long_description=long_description, | ||||
|     long_description_content_type="text/markdown", | ||||
|     include_package_data=True, | ||||
|     python_requires=">=3.5", | ||||
|     python_requires=">=3.7", | ||||
|     packages=['thingsboard_gateway', 'thingsboard_gateway.gateway', 'thingsboard_gateway.storage','thingsboard_gateway.storage.memory', | ||||
|               'thingsboard_gateway.storage.file','thingsboard_gateway.storage.sqlite','thingsboard_gateway.tb_client', | ||||
|               'thingsboard_gateway.connectors', 'thingsboard_gateway.connectors.ble', | ||||
|  |  | |||
|  | @ -24,7 +24,8 @@ from thingsboard_gateway.connectors.modbus.bytes_modbus_uplink_converter import | |||
| from thingsboard_gateway.connectors.opcua.opcua_uplink_converter import OpcUaUplinkConverter | ||||
| from thingsboard_gateway.connectors.ble.bytes_ble_uplink_converter import BytesBLEUplinkConverter | ||||
| from thingsboard_gateway.connectors.request.json_request_uplink_converter import JsonRequestUplinkConverter | ||||
| 
 | ||||
| from thingsboard_gateway.storage.memory_event_storage import MemoryEventStorage | ||||
| from thingsboard_gateway.storage.file_event_storage import FileEventStorage | ||||
| 
 | ||||
| logging.basicConfig(level=logging.ERROR, | ||||
|                     format='%(asctime)s - %(levelname)s - %(module)s - %(lineno)d - %(message)s', | ||||
|  | @ -384,5 +385,61 @@ class ConvertersTests(unittest.TestCase): | |||
|         self.assertDictEqual(result, test_request_result) | ||||
| 
 | ||||
| 
 | ||||
| class TestStorage(unittest.TestCase): | ||||
|     def test_memory_storage(self): | ||||
| 
 | ||||
|         test_size = randint(0, 100) | ||||
| 
 | ||||
|         storage_test_config = { | ||||
|             "type": "memory", | ||||
|             "read_records_count": 10, | ||||
|             "max_records_count": test_size * 10 | ||||
|         } | ||||
|         storage = MemoryEventStorage(storage_test_config) | ||||
| 
 | ||||
|         for test_value in range(test_size * 10): | ||||
|             storage.put(test_value) | ||||
| 
 | ||||
|         result = [] | ||||
|         for _ in range(test_size): | ||||
|             result.append(storage.get_event_pack()) | ||||
|             storage.event_pack_processing_done() | ||||
|         correct_result = [[item for item in range(pack * 10, (pack + 1) * 10)] for pack in range(test_size)] | ||||
| 
 | ||||
|         self.assertListEqual(result, correct_result) | ||||
| 
 | ||||
|     def test_file_storage(self): | ||||
| 
 | ||||
|         storage_test_config = {"data_folder_path": "storage/data/", | ||||
|                                "max_file_count": 1000, | ||||
|                                "max_records_per_file": 10, | ||||
|                                "max_read_records_count": 10, | ||||
|                                "no_records_sleep_interval": 5000 | ||||
|                                } | ||||
| 
 | ||||
|         test_size = randint(0, storage_test_config["max_file_count"]-1) | ||||
| 
 | ||||
|         storage = FileEventStorage(storage_test_config) | ||||
| 
 | ||||
|         for test_value in range(test_size * 10): | ||||
|             storage.put(str(test_value)) | ||||
|             sleep(.01) | ||||
| 
 | ||||
|         result = [] | ||||
|         for _ in range(test_size): | ||||
|             batch = storage.get_event_pack() | ||||
|             result.append(batch) | ||||
|             storage.event_pack_processing_done() | ||||
| 
 | ||||
|         correct_result = [[str(x) for x in range(y * 10, (y + 1) * 10)] for y in range(test_size)] | ||||
| 
 | ||||
|         print(result) | ||||
|         print(correct_result) | ||||
|         for file in listdir(storage_test_config["data_folder_path"]): | ||||
|             remove(storage_test_config["data_folder_path"]+"/"+file) | ||||
|         removedirs(storage_test_config["data_folder_path"]) | ||||
|         self.assertListEqual(result, correct_result) | ||||
| 
 | ||||
| 
 | ||||
| if __name__ == '__main__': | ||||
|     unittest.main() | ||||
|  |  | |||
|  | @ -37,8 +37,6 @@ from thingsboard_gateway.tb_utility.tb_updater import TBUpdater | |||
| from thingsboard_gateway.tb_utility.tb_utility import TBUtility | ||||
| 
 | ||||
| from thingsboard_gateway.storage.sqlite.storage_handler import StorageHandler | ||||
| from thingsboard_gateway.storage.sqlite.database_action_type import DatabaseActionType | ||||
| from thingsboard_gateway.storage.sqlite.database_request import DatabaseRequest | ||||
| 
 | ||||
| log = logging.getLogger('service') | ||||
| main_handler = logging.handlers.MemoryHandler(-1) | ||||
|  | @ -55,7 +53,7 @@ DEFAULT_CONNECTORS = { | |||
|     "rest": "RESTConnector", | ||||
|     "snmp": "SNMPConnector", | ||||
|     "ftp": "FTPConnector" | ||||
| } | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
| class TBGatewayService: | ||||
|  | @ -136,13 +134,8 @@ class TBGatewayService: | |||
|         self.connectors_configs = {} | ||||
|         self.__remote_configurator = None | ||||
|         self.__request_config_after_connect = False | ||||
| 
 | ||||
|         # if self.__config['storage']['type'] == 'sqlite': | ||||
|         #     self.__connected_devices = self._event_storage.connected_devices | ||||
|         # else: | ||||
|         self.__connected_devices = {} | ||||
|         # self.__load_persistent_devices() | ||||
| 
 | ||||
|         self.__load_persistent_devices() | ||||
|         self.__init_remote_configuration() | ||||
|         self._load_connectors() | ||||
|         self._connect_with_connectors() | ||||
|  | @ -244,10 +237,7 @@ class TBGatewayService: | |||
|         self.__updater.stop() | ||||
|         log.info("Stopping...") | ||||
|         self.__close_connectors() | ||||
| 
 | ||||
|         if self.__config['storage']['type'] == 'sqlite': | ||||
|             self._event_storage.close_db() | ||||
| 
 | ||||
|         self._event_storage.stop() | ||||
|         log.info("The gateway has been stopped.") | ||||
|         self.tb_client.disconnect() | ||||
|         self.tb_client.stop() | ||||
|  | @ -415,6 +405,7 @@ class TBGatewayService: | |||
|                         data["telemetry"] = telemetry_with_ts | ||||
|                     else: | ||||
|                         data["telemetry"] = {"ts": int(time() * 1000), "values": telemetry} | ||||
| 
 | ||||
|                     json_data = dumps(data) | ||||
|                     save_result = self._event_storage.put(json_data) | ||||
|                     if not save_result: | ||||
|  | @ -434,9 +425,6 @@ class TBGatewayService: | |||
|         devices_data_in_event_pack = {} | ||||
|         log.debug("Send data Thread has been started successfully.") | ||||
| 
 | ||||
|         # disconnected = False | ||||
|         # last_disconnect = None | ||||
| 
 | ||||
|         while not self.stopped: | ||||
|             try: | ||||
|                 if self.tb_client.is_connected(): | ||||
|  | @ -630,17 +618,6 @@ class TBGatewayService: | |||
|     def __rpc_ping(*args): | ||||
|         return {"code": 200, "resp": "pong"} | ||||
| 
 | ||||
|     # Request data from gateway storage | ||||
|     # you have to specify timestamp to specify from when to start reading | ||||
|     # args: JSON{"deviceName": "<deviceName>", "ts": <timestamp>} | ||||
|     def __rpc_data(self, args): | ||||
|         arguments = loads(args) | ||||
|         log.debug(str(arguments)) | ||||
|         _type = DatabaseActionType.READ_DEVICE | ||||
|         request = DatabaseRequest(_type, arguments) | ||||
|         self._event_storage.processQueue.put(request) | ||||
|         return {"code": 200, "resp": "Data from %s scheduled for upload" % arguments.get("deviceName")} | ||||
| 
 | ||||
|     def __rpc_devices(self, *args): | ||||
|         data_to_send = {} | ||||
|         for device in self.__connected_devices: | ||||
|  | @ -747,6 +724,11 @@ class TBGatewayService: | |||
|             self.__save_persistent_devices() | ||||
|             self.tb_client.client.gw_connect_device(device_name, device_type) | ||||
| 
 | ||||
|     def update_device(self, device_name, event, content): | ||||
|         if event == 'connector' and self.__connected_devices[device_name].get(event) != content: | ||||
|             self.__save_persistent_devices() | ||||
|         self.__connected_devices[device_name][event] = content | ||||
| 
 | ||||
|     def del_device(self, device_name): | ||||
|         del self.__connected_devices[device_name] | ||||
|         del self.__saved_devices[device_name] | ||||
|  |  | |||
|  | @ -106,13 +106,6 @@ class EventStorageReader: | |||
|         try: | ||||
|             if self.buffered_reader is None or self.buffered_reader.closed: | ||||
|                 new_file_to_read_path = self.settings.get_data_folder_path() + pointer.get_file() | ||||
|                 # if not exists(new_file_to_read_path): | ||||
|                 #     next_file = self.get_next_file(self.files, self.new_pos) | ||||
|                 #     if next_file is not None: | ||||
|                 #         new_file_to_read_path = self.settings.get_data_folder_path() + next_file | ||||
|                 #     else: | ||||
|                 #         self.buffered_reader = None | ||||
|                 #         return None | ||||
|                 self.buffered_reader = BufferedReader(FileIO(new_file_to_read_path, 'r')) | ||||
|                 lines_to_skip = pointer.get_line() | ||||
|                 if lines_to_skip > 0: | ||||
|  |  | |||
|  | @ -11,7 +11,7 @@ | |||
| #     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 sqlite3 | ||||
| 
 | ||||
| from time import time | ||||
| 
 | ||||
| from thingsboard_gateway.storage.event_storage import EventStorage | ||||
|  | @ -47,17 +47,21 @@ class StorageHandler(EventStorage): | |||
|         log.info("Sqlite storage initialized!") | ||||
|         self.delete_time_point = None | ||||
|         self.last_read = time() | ||||
|         self.closed = False | ||||
|         self.stopped = False | ||||
| 
 | ||||
|     def get_event_pack(self): | ||||
|         self.delete_time_point = self.last_read | ||||
|         data_from_storage = self.read_data(self.last_read) | ||||
|         self.last_read = time() | ||||
|         if not self.stopped: | ||||
|             self.delete_time_point = self.last_read | ||||
|             data_from_storage = self.read_data(self.last_read) | ||||
|             self.last_read = time() | ||||
| 
 | ||||
|         return [item[0] for item in data_from_storage or []] | ||||
|             return [item[0] for item in data_from_storage or []] | ||||
|         else: | ||||
|             return [] | ||||
| 
 | ||||
|     def event_pack_processing_done(self): | ||||
|         self.delete_data(self.delete_time_point) | ||||
|         if not self.stopped: | ||||
|             self.delete_data(self.delete_time_point) | ||||
| 
 | ||||
|     def read_data(self, ts): | ||||
|         return self.db.read_data(ts) | ||||
|  | @ -67,16 +71,19 @@ class StorageHandler(EventStorage): | |||
| 
 | ||||
|     def put(self, message): | ||||
|         try: | ||||
|             _type = DatabaseActionType.WRITE_DATA_STORAGE | ||||
|             request = DatabaseRequest(_type, message) | ||||
|             if not self.stopped: | ||||
|                 _type = DatabaseActionType.WRITE_DATA_STORAGE | ||||
|                 request = DatabaseRequest(_type, message) | ||||
| 
 | ||||
|             log.info("Sending data to storage") | ||||
|             self.processQueue.put(request) | ||||
|             self.db.process() | ||||
|             return True | ||||
|                 log.info("Sending data to storage") | ||||
|                 self.processQueue.put(request) | ||||
|                 self.db.process() | ||||
|                 return True | ||||
|             else: | ||||
|                 return False | ||||
|         except Exception as e: | ||||
|             log.exception(e) | ||||
| 
 | ||||
|     def close_db(self): | ||||
|     def stop(self): | ||||
|         self.db.closeDB() | ||||
|         self.closed = True | ||||
|         self.stopped = True | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 samson0v
						samson0v