thingsboard / thingsboard-python-client-sdk Goto Github PK
View Code? Open in Web Editor NEWThingsBoard client Python SDK
Home Page: https://thingsboard.io
License: Other
ThingsBoard client Python SDK
Home Page: https://thingsboard.io
License: Other
Indecisive between this one and the Thingsboard gateway.
I am new two both of this.
Currently, I have a control software(Raspberry PI) which read data from all sensors and stored in InfluxDB and also manage all the output relays. I want to push all these info to my Thingsboard cloud. I am not sure which is a good options.
Thanks;
Cound anyone tell me What is the difference between subscribe attributes and request attributes ?
I'm using this library in order to reply from the remote shell RPC but I'm not sure what is the payload the shell is expecting since I just can see undefined
in the terminal.
As an example, the gateway replies to the server the following payload:
result = {
"data":
[
{
"stdout": "Command not found",
"stderr": ""
}
],
"done": True,
"qos": 0
}
gateway.gw_send_rpc_reply(device, req_id, result)
Is this a valid reply? Could you add some examples in the documentation, please?
Thank you
In the MQTT API documentation, it is mentioned that: "Key is always a string, while value can be either string, boolean, double, long or JSON."
ref: https://thingsboard.io/docs/reference/mqtt-api/
Regarding this point, I don't see that the Python library supports a JSON "type" value.
reference:
KV_SCHEMA = {
"type": "object",
"patternProperties":
{
".": {"type": ["integer",
"string",
"boolean",
"number"]}
},
"minProperties": 1,
}
Additionally, I did some tests to validate this, and when I try to send a payload directly:
payload = {'someNumber':42,'someArray':[1,2,3],'someNestedObject':{'key':'value'}}
telemetry = {'newall': payload}
client.send_telemetry(telemetry,quality_of_service=1)
I get the following error message:
Failed validating 'anyOf' in schema['items']:
{'anyOf': [{'additionalProperties': False,
'properties': {'ts': {'type': 'integer'},
'values': {'minProperties': 1,
'patternProperties': {'.': {'type': ['integer',
'string',
'boolean',
'number']}},
'type': 'object'}},
'type': 'object'},
{'minProperties': 1,
'patternProperties': {'.': {'type': ['integer',
'string',
'boolean',
'number']}},
'type': 'object'}]}
On instance[0]:
{'newall': {'someArray': [1, 2, 3],
'someNestedObject': {'key': 'value'},
'someNumber': 42}}
Also, when I send my JSON payload as a string:
payload = {'someNumber':42,'someArray':[1,2,3],'someNestedObject':{'key':'value'}}
MQTT_MSG=json.dumps(payload)
telemetry = {'newall': payload}
client.send_telemetry(telemetry,quality_of_service=1)
The message is saved in Thingsboard as a string.
Additionally, validate the posting of a JSON payload as follows:
mosquitto_pub -d -h "ip" -t "v1/devices/me/telemetry" -u "token" -f "telemetry-data-as-object2.json"
My goal is to be able to publish my payload as JSON to be able to visualize it in the same way when I check the key through the REST AP (see images to visualize the difference)
I
from tb_device_mqtt import TBDeviceMqttClient, TBPublishInfo
import config
if __name__ == '__main__':
telemetry = {
"someArray": [1, 2, 3],
}
client = TBDeviceMqttClient(host=config.server_host,
token=config.device_test_token)
client.connect()
result = client.send_telemetry(telemetry)
success = (result.get() == TBPublishInfo.TB_ERR_SUCCESS)
if success:
print("Success")
else:
print("Failure")
client.disconnect()
the outputs of above code are
{'someArray': [1, 2, 3]} is not valid under any of the given schemas
Failed validating 'anyOf' in schema['items']:
{'anyOf': [{'additionalProperties': False,
'properties': {'ts': {'type': 'integer'},
'values': {'minProperties': 1,
'patternProperties': {'.': {'type': ['integer',
'string',
'boolean',
'number']}},
'type': 'object'}},
'type': 'object'},
{'minProperties': 1,
'patternProperties': {'.': {'type': ['integer',
'string',
'boolean',
'number']}},
'type': 'object'}]}
On instance[0]:
{'someArray': [1, 2, 3]}
Traceback (most recent call last):
File "/Users/zj/PycharmProjects/ThingsBoard/telemetry_upload.py", line 14, in <module>
result = client.send_telemetry(telemetry)
File "/usr/local/anaconda3/lib/python3.9/site-packages/tb_device_mqtt.py", line 394, in send_telemetry
self.validate(DEVICE_TS_OR_KV_VALIDATOR, telemetry)
File "/usr/local/anaconda3/lib/python3.9/site-packages/tb_device_mqtt.py", line 302, in validate
raise e
File "/usr/local/anaconda3/lib/python3.9/site-packages/tb_device_mqtt.py", line 299, in validate
validator.validate(data)
File "/usr/local/anaconda3/lib/python3.9/site-packages/jsonschema/validators.py", line 254, in validate
raise error
jsonschema.exceptions.ValidationError: {'someArray': [1, 2, 3]} is not valid under any of the given schemas
Failed validating 'anyOf' in schema['items']:
{'anyOf': [{'additionalProperties': False,
'properties': {'ts': {'type': 'integer'},
'values': {'minProperties': 1,
'patternProperties': {'.': {'type': ['integer',
'string',
'boolean',
'number']}},
'type': 'object'}},
'type': 'object'},
{'minProperties': 1,
'patternProperties': {'.': {'type': ['integer',
'string',
'boolean',
'number']}},
'type': 'object'}]}
On instance[0]:
{'someArray': [1, 2, 3]}
how should I do
For a while my code to post to thingsboard will work normally and then suddenly, the code will enter a loop where it repeatedly says connection SUCCESS every few ms until I terminate the script:
2020-05-15 23:51:31,012 - INFO - connection SUCCESS
2020-05-15 23:51:31,016 - INFO - connection SUCCESS
2020-05-15 23:51:31,877 - INFO - connection SUCCESS
2020-05-15 23:51:31,897 - INFO - connection SUCCESS
2020-05-15 23:51:31,939 - INFO - connection SUCCESS
2020-05-15 23:51:31,945 - INFO - connection SUCCESS
2020-05-15 23:51:31,953 - INFO - connection SUCCESS
2020-05-15 23:51:31,973 - INFO - connection SUCCESS
2020-05-15 23:51:32,010 - INFO - connection SUCCESS
2020-05-15 23:51:32,016 - INFO - connection SUCCESS
2020-05-15 23:51:32,022 - INFO - connection SUCCESS
^CException ignored in: <module 'threading' from '/usr/lib/python3.7/threading.py'>
Traceback (most recent call last):
File "/usr/lib/python3.7/threading.py", line 1281, in _shutdown
t.join()
File "/usr/lib/python3.7/threading.py", line 1032, in join
self._wait_for_tstate_lock()
File "/usr/lib/python3.7/threading.py", line 1048, in _wait_for_tstate_lock
elif lock.acquire(block, timeout):
KeyboardInterrupt
Here is how I'm using it:
from pyvesync_v2 import VeSync
import time
from time import localtime, strftime
#import os, sys, platform, datetime
import requests
from tb_device_mqtt import TBDeviceMqttClient, TBPublishInfo
TB_Token = "xxx"
manager = VeSync("email", "password", time_zone="America/New York")
manager.login()
# Get/Update Devices from server - populate device lists
manager.update()
my_switch = manager.outlets[0]
# Get energy usage data
manager.energy_update_interval = 3 * 60
manager.update()
# Display outlet device information
for device in manager.outlets:
device.display()
while True:
manager.update()
print(strftime("%a, %d %b %Y %H:%M:%S",localtime()))
print("%5.2fW - active for %d" %(manager.outlets[1].power,manager.outlets[1].active_time))
if manager.outlets[1].power > 0.0:
telemetry = {"power": manager.outlets[1].power}
client = TBDeviceMqttClient("192.168.1.100", TB_Token)
# Connect to ThingsBoard
client.connect()
# Sending telemetry without checking the delivery status
client.send_telemetry(telemetry)
# Sending telemetry and checking the delivery status (QoS = 1 by default)
result = client.send_telemetry(telemetry)
# get is a blocking call that awaits delivery status
success = result.get() == TBPublishInfo.TB_ERR_SUCCESS
# Disconnect from ThingsBoard
client.disconnect()
else:
print("0.0W returned, possible API error.")
time.sleep(manager.energy_update_interval)
Any thoughts on what I'm doing wrong?
TB MQTT client incorrectly handles reconnection using Paho client:
Thingsboard calls the paho reconnect_delay_set but looking at the actual paho client thats only used in the loop_forever() method while the tb client just uses loop_start
is_connected is never set to False on disconnect
Paho already handles an is_connected flag, rather than creating a new flag for the TB SDK
import psutil
import time
import logging
from tb_device_mqtt import TBDeviceMqttClient
def on_server_side_rpc_request(request_id, request_body):
print(request_id, request_body)
try:
if request_body["method"] == "getCPULoad":
client.send_rpc_reply(request_id, {"CPU percent": psutil.cpu_percent()})
elif request_body["method"] == "getMemoryUsage":
client.send_rpc_reply(request_id, {"Memory": psutil.virtual_memory().percent})
except Exception as e:
print(e)
client = TBDeviceMqttClient("127.0.0.1", "A1_TEST_TOKEN")
client.set_server_side_rpc_request_handler(on_server_side_rpc_request)
client.connect()
while True:
time.sleep(1)
-> Throw exception Payload must be a string, byte array, int, float or None -> I have to convert like client.send_rpc_reply(request_id, str({"Memory": psutil.virtual_memory().percent})) but no reply thingsboard receives ?
Any suggestion ?
Hello,
I was trying to install this library on an Inhand Networks IG502 IOT gateway. The device provides capability for users to run and execute python and python libraries, and no more. It does not seem possible to run packages with C dependencies. Is it possible the code could be updated to switch to PYMMH3 if MMH3 install fails? Obviously this would impact performance if GCC is not available. I am using this gateway more like a sensor node, and expect it to send a telemetry update at most once a minute. High performance is not applicable in my use case.
Thank you for your consideration.
The example in the readme says to use the callback as:
def on_attributes_change(client, result, exception):
But the callback doesn't bring the client information.
I solved this by using:
def on_attributes_change(result, exception):
After the last commit (7b1ffcc), import of sdk_utils
or anything which depends on it (tb_device_mqtt
& tb_gateway_mqtt
) will result in attempted installation of mmh3
/pymmh3
via pip. This is counter-intuitive and surprising - importing a Python module should not have side effect which modify the system state.
Furthermore, this makes the tb-mqtt-client package unusable on embedded systems which either lack pip
(to save space), have a read-only rootfs or lack internet access. Automated installation of packages at runtime also breaks installation reproducibility (as there's no way to control which version of the dependency is installed) and defeats attempts to achieve license compliance.
Dependencies should be expessed in setup.py
so that they can be installed in the usual way.
Installing tb-mqtt-client results in the following files in python's site-packages
directory:
__init__.py
sdk_utils.py
tb_device_http.py
tb_device_mqtt.py
tb_gateway_mqtt.py
utils.py
This gives me a few concerns:
__init__.py
file at the top-level of site-packages may be imported automatically when anything else from that directory is imported. This could lead to issues if any content is added to this file.__init__.py
, sdk_utils.py
and utils.py
are not very unique and may easily clash with modules from other Python packages.I recommend moving these files into a single top-level module or prefixing the file names with something unique to prevent issues.
I've tested Thingsboard API (HTTP using JMeter) with very good results. Now I've been asked to do the same using MQTT. I’m using the docker image described in https://thingsboard.io/docs/user-guide/install/docker/
For starters, the examples in https://thingsboard.io/docs/reference/python-client-sdk/ do not work with tb-mqtt-client latest versions. By trial and error, I managed to make it work with version 1.1, the only one that worked for sending attributes and telemetry (python -m pip install tb-mqtt-client==1.1).
Using the MQTT python client to create devices never succeeds in provision more than 10.000. It hangs before that without any error.
Since what I was asked to test was sending data (attributes and telemetry) I resorted to pycurl to provision the devices and get their tokens so I could send data to each device.
Following the example in https://github.com/thingsboard/thingsboard-python-client-sdk/blob/master/examples/device/send_telemetry_and_attr.py I created these two functions to send data on custom MQTT class of my own where properties like server address and device token are populated when the device is provisioned using http.
def write_device_attribute(self) -> bool:
attribute = {"withoutHistory": random.randint(-1000000, 1000000)}
client = TBDeviceMqttClient(host=self.server_address, token=self.device_token)
client.connect()
result = client.send_attributes(attribute)
success = result.get() == TBPublishInfo.TB_ERR_SUCCESS
client.disconnect()
del client
return success
def write_device_telemetry(self) -> bool:
telemetry = {"withHistory": random.randint(-1000000, 1000000)}
client = TBDeviceMqttClient(host=self.server_address, token=self.device_token)
client.connect()
result = client.send_telemetry(telemetry,0)
success = result.get() == TBPublishInfo.TB_ERR_SUCCESS
client.disconnect()
del client
return success
These functions are called by several threads but each thread only writes to it’s own devices:
#################################################################
def write_attributes(user_n):
"""Write to the user devices attribute
Args:
user_n (int): integer identifying the user 1..N_USERS
"""
try:
for _ in range(N_DATA_POINTS):
for n in range(N_DEVICES):
success = MQTT_CLIENTS[user_n][n].write_device_attribute()
Q_Request_log.put_nowait(f"{now_string()};attr;{success}")
time.sleep(SLEEP_TIME)
except TB_EXCEPTION as err:
print(err)
#################################################################
def write_telemetry(user_n):
"""Write telemetry to the user devices
Args:
user_n (int): integer identifying the user 1..N_USERS
"""
try:
for _ in range(N_DATA_POINTS):
for n in range(N_DEVICES):
success = MQTT_CLIENTS[user_n][n].write_device_telemetry()
Q_Request_log.put_nowait(f"{now_string()};ts;{success}")
time.sleep(SLEEP_TIME)
except TB_EXCEPTION as err:
print(err)
#################################################################
And the main function:
…
# Send telemetry (attribute, no history). Launch a thread for each user.
start_time = datetime.now()
for i in range(N_USERS):
thread_a = threading.Thread(target = write_attributes, args=(i,))
thread_a.start()
threads_At.append(thread_a)
# wait for all threads to finish
for thread in threads_At:
thread.join()
end_time = datetime.now()
print(f"Write attribute;{elapsed_time(start_time, end_time)}")
# Send telemetry (attribute, time series). Launch a thread for each user.
start_time = datetime.now()
for i in range(N_USERS):
thread_a = threading.Thread(target = write_telemetry, args=(i,))
thread_a.start()
threads_TS.append(thread_a)
# wait for all threads to finish
for thread in threads_TS:
thread.join()
end_time = datetime.now()
print(f"Send telemetry;{elapsed_time(start_time, end_time)}")
…
This code starts by running as expected but after a few hundred attribute writes it gets stuck. Checking the process with ps -u I see that it is waiting in a interruptible sleep (waiting for an event to complete), specifically state “Sl+”.
Any clue as why this works fine for low numbers but gets stuck on a long run? The server is almost idle at 2% CPU usage, lots of free memory and disk.
Compared to the Client object from paho.mqtt.client , the TBDeviceMqttClient object does not support the function proxy_set to set a proxy server.
Workaround is:
tb_client = TBDeviceMqttClient(...)
tb_client._client.proxy_set(proxy_type=socks.HTTP, proxy_addr="...", proxy_port=...)
Could you please provide this feature in the right way.
Thanks
I try to request an array of shared keys with gw_request_shared_attributes.
import config
import time
from tb_gateway_mqtt import TBGatewayMqttClient
def callback(client, result, exception):
print('on change:::')
print(result)
gateway = TBGatewayMqttClient(config.TB_HOST, config.TB_ACCESS_KEY)
keys = ['keyA', 'keyB']
gateway.connect()
gateway.gw_connect_device('myDevice')
gateway.gw_request_shared_attributes('myDevice', keys, callback)
while True:
time.sleep(1)
response is without any value: {'id': 1, 'device': 'myDevice'}
It works if I do it key by key. But I have around 10keys to request so I must find an efficient solution.
gateway.gw_request_shared_attributes('myDevice', ["keyA"] , callback)
# {'id': 1, 'device': 'myDevice'. value: True}
gateway.gw_request_shared_attributes('myDevice',["keyB"], callback)
# {'id': 2, 'device': 'myDevice'. value: True}
Hi guys!
I have been playing with the library (many thanks for your work!) and I have discovered that the provided examples do not work well because the library send messages too fast.
This is the code I'm using:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import time
from tb_device_mqtt import TBDeviceMqttClient, TBPublishInfo
client = TBDeviceMqttClient("10.15.181.58", "xxxxxxxxxxxxxxxxxxxxxxxx")
client.connect()
# while not client._TBDeviceMqttClient__is_connected:
# time.sleep(0.1)
result = client.send_telemetry({"temperature": 42.2})
client.disconnect()
And here you have what the Thingboard server reports:
2019-07-05 10:37:07,321 [nioEventLoopGroup-13-12] INFO o.t.s.t.mqtt.MqttTransportHandler - [74b542dd-1890-4ab7-acae-99503d5b3847] Processing connect msg for client: !
2019-07-05 10:37:07,322 [nioEventLoopGroup-13-12] INFO o.t.s.t.mqtt.MqttTransportHandler - [74b542dd-1890-4ab7-acae-99503d5b3847] Processing connect msg for client with user name: xxxxxxxxxxxxxxxxxxxxxxx!
2019-07-05 10:37:07,323 [nioEventLoopGroup-13-12] INFO o.t.s.t.mqtt.MqttTransportHandler - [74b542dd-1890-4ab7-acae-99503d5b3847] Closing current session due to invalid msg order: MqttPublishMessage[fixedHeader=MqttFixedHeader[messageType=PUBLISH, isDup=false, qosLevel=AT_LEAST_ONCE, isRetain=false, remainingLength=50], variableHeader=MqttPublishVariableHeader[topicName=v1/devices/me/telemetry, packetId=1], payload=PooledSlicedByteBuf(ridx: 0, widx: 23, cap: 23/23, unwrapped: PooledUnsafeDirectByteBuf(ridx: 88, widx: 90, cap: 1024))]
2019-07-05 10:37:07,324 [nioEventLoopGroup-13-12] INFO o.t.s.t.mqtt.MqttTransportHandler - [74b542dd-1890-4ab7-acae-99503d5b3847] Closing current session due to invalid msg order: MqttMessage[fixedHeader=MqttFixedHeader[messageType=DISCONNECT, isDup=false, qosLevel=AT_MOST_ONCE, isRetain=false, remainingLength=0], variableHeader=, payload=]
2019-07-05 10:37:07,327 [ForkJoinPool-9-worker-4] INFO o.t.s.t.mqtt.MqttTransportHandler - [74b542dd-1890-4ab7-acae-99503d5b3847] Client connected!
As you can see, the session is closed before the client is connected, so the telemetry messages are not processed by the server.
Everything works fine after adding the while not client._TBDeviceMqttClient__is_connected: time.sleep(0.1)
, but that is just a hack and not a permanent solution. The first option is to expose the connection status with a getter function (client.is_connected()), but, otherwise, I am not sure if making the "connect()" function a blocking function is the right approach. How about buffering the messages until connection is established?
Thank you for your attention and for developing this project and best regards,
Aitor
I try to use the tb_device_mqtt library together with the asyncronous opc-ua library asyncua and asyncio.Queue().
With the standard paho-mqtt library the sending of the data works fine. With tb_device_mqtt library it is not working.
The relevant part of the code looks like this:
p_plc is the asyncua client
q_queue is an async.Queue
async with g_plc:
await subscribe()
while g_running:
if(not g_queue.empty()):
g_logger.info("Queue size start: %d" % g_queue.qsize())
while(not g_queue.empty()):
send_data(await g_queue.get())
await g_plc.check_connection()
await asyncio.sleep(0.001)
await asyncio.sleep(2)
The send_data function sends the data to the thingsboard server.
With paho-mqtt I send the data with:
ret = g_rcc_mqtt.publish('v1/devices/me/telemetry', data, 1)
g_logger.info(ret)
With tb_device_mqtt I send the data with:
result = g_rcc_mqtt.send_telemetry(data)
success = result.get() == TBPublishInfo.TB_ERR_SUCCESS
g_logger.info(success)
With tb_device_mqtt I get after some seconds the exception: Message publish failed: The client is not currently connected.
Is there an example that shows how to use tb_device_mqtt library inside asyncio code.
Hello,
I'm trying to run the below example listed, which it should subscribe to all device shared attributes & updates. However, when I run the python file and make some change in some of the device shared attributes in my Thingsboard instance, there's no message received.
from time import sleep
from tb_device_mqtt import TBDeviceMqttClient
def callback(result):
print(result)
client = TBDeviceMqttClient("127.0.0.1", "A1_TEST_TOKEN")
client.connect()
client.subscribe_to_attribute("uploadFrequency", callback)
client.subscribe_to_all_attributes(callback)
while True:
sleep(1)
Diggin into tb_device_mqtt.py, I could check that the necessary device subscription for this (topic 'v1/devices/me/attributes') is made on _on_connect method.
I understand that when I make a change on any shared attribute, I should receive the new value into console, right? As I receive with a simple mosquitto_sub example.
However, with the example listed, I don't receive any response 🤷
Hi there !
I'm currently using the python client sdk and i found a missing item. So maybe i'm not using correctly the SDK but when my gateway device TBGatewayMqttClient suscribe for attribute with gw_subscribe_to_attribute, the device name is not shared to the callback.
This is a problem for me because when i modify an attribute on TB dashboard i get the new attribute name : value but i do not get the device corresponding.
In tb_gateway_mqtt.py i had to make a modification in method called "_on_decoded_message" to make this happened :
`elif message.topic == GATEWAY_ATTRIBUTES_TOPIC:
with self._lock:
# callbacks for everything
if self.__sub_dict.get("*|*"):
for callback in self.__sub_dict["*|*"]:
self.__sub_dict["*|*"][callback](self, content["data"])
# callbacks for device. in this case callback executes for all attributes in message
target = content["device"] + "|*"
if self.__sub_dict.get(target):
for callback in self.__sub_dict[target]:
self.__sub_dict[target][callback](self, content["data"])
# callback for atr. in this case callback executes for all attributes in message
targets = [content["device"] + "|" + callback for callback in content["data"]]
for target in targets:
if self.__sub_dict.get(target):
for sub_id in self.__sub_dict[target]:
self.__sub_dict[target][sub_id](self, content["data"])`
to
`elif message.topic == GATEWAY_ATTRIBUTES_TOPIC:
with self._lock:
# callbacks for everything
if self.__sub_dict.get("*|*"):
for callback in self.__sub_dict["*|*"]:
self.__sub_dict["*|*"][callback](self, content["device"], content["data"])
# callbacks for device. in this case callback executes for all attributes in message
target = content["device"] + "|*"
if self.__sub_dict.get(target):
for callback in self.__sub_dict[target]:
self.__sub_dict[target][callback](self, content["device"], content["data"])
# callback for atr. in this case callback executes for all attributes in message
targets = [content["device"] + "|" + callback for callback in content["data"]]
for target in targets:
if self.__sub_dict.get(target):
for sub_id in self.__sub_dict[target]:
self.__sub_dict[target][sub_id](self, content["device"], content["data"])`
adding content["device"] allows me to get the device name in the callback and execute correspond process for this particular device. Is there another way to get the same result or do you think this modification has to be implemented ?
With the new version 1.8.7 we encounter the following error:
024-03-19 16:42:42.709 ERROR [Sending thread ] [tb_device_mqtt ] __sending_thread_main - Error during data sending:
Traceback (most recent call last):
File "/root/.local/lib/python3.10/site-packages/tb_device_mqtt.py", line 634, in __sending_thread_main
self.__responses[item['id']] = {"info": info, "timeout_ts": int(time.time()) + DEFAULT_TIMEOUT}
Probably related to d7fd7b8
I've just installed today this library but when trying to run I was getting an error:
File "/home/alr/.local/lib/python3.8/site-packages/paho/mqtt/client.py", line 979, in connect_async
if port <= 0:
TypeError: '<=' not supported between instances of 'str' and 'int'
I solved adding the port information to the connection:
client = TBDeviceMqttClient("127.0.0.1", 1883, "token")
Everything works fine if the timestamp is not included, but when I try to use the function from https://thingsboard.io/docs/reference/python-client-sdk/#using-gateway-apis it gives me an error in ThingsBoard platform logs (using sudo journalctl -u thingsboard.service
)
Example that works:
from time import time from tb_gateway_mqtt import TBGatewayMqttClient gateway = TBGatewayMqttClient("THINGSBOARD_PLATFORM_IP", 1883, "GATEWAY_ACCESS_TOKEN") gateway.connect() gateway.gw_send_telemetry("DEVICE_ID", {"telemetryKey": "telemetryValue"})
Example that doesn't work:
from time import time from tb_gateway_mqtt import TBGatewayMqttClient gateway = TBGatewayMqttClient("THINGSBOARD_PLATFORM_IP", 1883, "GATEWAY_ACCESS_TOKEN")<br /> gateway.connect() gateway.gw_send_telemetry("DEVICE_ID", {"ts": int(round(time()*1000)), "values": {"telemetryKey": "telemetryValue"}})
When gw_send_telemetry is called in the second example, it gives me this in logs:
Mar 01 20:06:01 ip-172-31-34-70 thingsboard.jar[1750750]: Exception in thread "MqttTransportContext-50-2" com.google.gson.JsonSyntaxException: Can't parse value: {"040100":{"ts":1677701139953,"testTelemetry":3}} Mar 01 20:06:01 ip-172-31-34-70 thingsboard.jar[1750750]: at org.thingsboard.server.transport.mqtt.session.GatewaySessionHandler$3.onSuccess(GatewaySessionHandler.java:353) Mar 01 20:06:01 ip-172-31-34-70 thingsboard.jar[1750750]: at org.thingsboard.server.transport.mqtt.session.GatewaySessionHandler$3.onSuccess(GatewaySessionHandler.java:349) Mar 01 20:06:01 ip-172-31-34-70 thingsboard.jar[1750750]: at com.google.common.util.concurrent.Futures$CallbackListener.run(Futures.java:1080) Mar 01 20:06:01 ip-172-31-34-70 thingsboard.jar[1750750]: at java.base/java.util.concurrent.ForkJoinTask$RunnableExecuteAction.exec(ForkJoinTask.java:1426) Mar 01 20:06:01 ip-172-31-34-70 thingsboard.jar[1750750]: at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:290) Mar 01 20:06:01 ip-172-31-34-70 thingsboard.jar[1750750]: at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1020) Mar 01 20:06:01 ip-172-31-34-70 thingsboard.jar[1750750]: at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1656) Mar 01 20:06:01 ip-172-31-34-70 thingsboard.jar[1750750]: at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1594) Mar 01 20:06:01 ip-172-31-34-70 thingsboard.jar[1750750]: at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:183)
In my opinion, the problem is the format of the message, because it doesn't add the "telemetry":
needed for this kind of input value, but maybe it's another issue that I'm not seeing. Any help would be appreciated
Hi,
I am using your ThingsBoard library on a Raspberry Pi Zero.
It is a valuable piece of software that allows me to track my current location on a map and display my planned driving route on the dashboard.
https://github.com/hishizuka/pizero_bikecomputer
Now, I report the problem.
This program runs the mmh install every time it starts up, according to the code after line 23 of sdk_utils.py.
With the Raspberry Pi Zero's processing power, it takes almost a minute to run the pip command, which is a pain.
Is it possible to use requirements.txt during installation and make it a one-time install check?
I follow example. It not good.
When it will be up to date ?
""2022-07-09 11:08:23" - |INFO| - [tb_gateway_service.py] - tb_gateway_service - init - 112 - Gateway starting..."
""2022-07-09 11:08:23" - |INFO| - [tb_gateway_service.py] - tb_gateway_service - init - 117 - ThingsBoard IoT gateway version: 3.1"
""2022-07-09 11:08:23" - |INFO| - [tb_gateway_mqtt.py] - tb_gateway_mqtt - gw_subscribe_to_attribute - 175 - Subscribed to | with id 1 for device *"
""2022-07-09 11:08:23" - |INFO| - [tb_loader.py] - tb_loader - import_module - 68 - Import ModbusConnector from /usr/local/lib/python3.9/site-packages/thingsboard_gateway-3.1-py3.9.egg/thingsboard_gateway/connectors/modbus."
""2022-07-09 11:08:23" - |WARNING| - [tb_gateway_service.py] - tb_gateway_service - _load_connectors - 502 - Cannot parse connector configuration as a JSON, it will be passed as a string."
""2022-07-09 11:08:23" - |ERROR| - [tb_gateway_service.py] - tb_gateway_service - _connect_with_connectors - 547 - 'str' object has no attribute 'get'"
Traceback (most recent call last):
File "/usr/local/lib/python3.9/site-packages/thingsboard_gateway-3.1-py3.9.egg/thingsboard_gateway/gateway/tb_gateway_service.py", line 535, in _connect_with_connectors
connector = self._implemented_connectors[connector_type](self,
File "/usr/local/lib/python3.9/site-packages/thingsboard_gateway-3.1-py3.9.egg/thingsboard_gateway/connectors/modbus/modbus_connector.py", line 98, in init
self.__config = self.__backward_compatibility_adapter.convert()
File "/usr/local/lib/python3.9/site-packages/thingsboard_gateway-3.1-py3.9.egg/thingsboard_gateway/connectors/modbus/backward_compability_adapter.py", line 40, in convert
if not self.__config.get('server'):
AttributeError: 'str' object has no attribute 'get'
""2022-07-09 11:08:23" - |INFO| - [tb_gateway_service.py] - tb_gateway_service - init - 214 - Gateway started."
""2022-07-09 11:08:23" - |INFO| - [tb_device_mqtt.py] - tb_device_mqtt - _on_connect - 139 - connection SUCCESS"
""2022-07-09 11:08:23" - |INFO| - [tb_gateway_mqtt.py] - tb_gateway_mqtt - gw_subscribe_to_attribute - 175 - Subscribed to | with id 2 for device *"
I am registering MQTT in two devices with same Topic and device Token. When trying to do so Mqtt server has been closed in first device.
Hello,
I am using the TBDeviceMqttClient class from the "tb_device_mqtt.py".
I am getting this error when launching a firmware update:
File "/home/ubuntu/.local/lib/python3.8/site-packages/tb_device_mqtt.py", line 324, in _on_decoded_message callback = self._attr_request_dict.pop(req_id) KeyError: 1
My question concerns the messages received by the client:
"v1/devices/me/attributes"
topic"v2/fw/request/${requestId}/chunk/${chunk}"
topic"v1/devices/me/attributes/response/+"
topic which includes all the changed shared attributes related to the updateWhen the client receives a message on the "v1/devices/me/attributes/response/+"
topic, it has to get the callback function: callback = self._attr_request_dict.pop(req_id)
However, the self._attr_request_dict
is updated (and thus the callback is added to the dict) when the user calls the request_attributes
function which calls the _add_attr_request_callback
.
In the case of a firmware update, no callback function was added or defined to be called when a message is received on the "v1/devices/me/attributes/response/+"
topic, and as a consequence, the error is raised.
Is there any problem in the client script or am I missing something?
with python 3.7 and client 1.6 not possible connect to server using Token (examples) .
TBDeviceMqttClient init does not have this option, require PORT and username + password
if you want connect with TOKEN connection string
client = TBDeviceMqttClient("xxx.xxx.xxx.xxx",1883,None, "TOKEN")
i have used these commands to generate server.pem ( self signed certificate ) and server_key.pem (privarte key)
openssl ecparam -out server_key.pem -name secp256r1 -genkey
openssl req -new -key server_key.pem -x509 -nodes -days 365 -out server.pem
and the server running fine
In client side used below cmds to get client certificate and private key
openssl ecparam -out key.pem -name secp256r1 -genkey
openssl req -new -key key.pem -x509 -nodes -days 365 -out cert.pem
In python
client.tls_set(ca_certs="server.pem", certfile="cert.pem ", keyfile="key.pem", \ cert_reqs=ssl.CERT_NONE,tls_version=ssl.PROTOCOL_TLSv1_2, ciphers=None);
client.tls_insecure_set(False)
client.connect("XXXXXXXX", 8883, 60)
Error:
ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] self signed certificate (_ssl.c:1131)
Configuration
In thingsboard.conf
export MQTT_SSL_ENABLED=true
export MQTT_SSL_BIND_ADDRESS=0.0.0.0
export MQTT_SSL_BIND_PORT=8883
export MQTT_SSL_CREDENTIALS_TYPE=PEM
export MQTT_SSL_PEM_CERT=/etc/thingsboard/conf/server.pem
export MQTT_SSL_PEM_KEY=/etc/thingsboard/conf/server_key.pem
export MQTT_SSL_PEM_KEY_PASSWORD=password **
Versions (please complete the following information):
If you do not have sleep time, there are some lost in TB. NO ERRORS.
for (device, data) in dataset:
gateway.gw_connect_device(device)
gateway.gw_send_attributes(device, data)
gateway.gw_disconnect_device(device)
time.sleep(0.01)
Hi,
I have installed the tb_device_mqtt package on my ubuntu 22.04 running in VMware. It seem to have installed properly. However, when running the following code on jupyter notebook:
'from tb_device_mqtt import TBDeviceMqttClient, TBPublishInfo'
I get the following error:
'ImportError Traceback (most recent call last)
Cell In[9], line 1
----> 1 from tb_device_mqtt import TBPublishInfo
File ~/programs/anaconda3/lib/python3.11/site-packages/tb_device_mqtt.py:27
23 from threading import Thread
25 from simplejson import JSONDecodeError
---> 27 from sdk_utils import verify_checksum
30 FW_TITLE_ATTR = "fw_title"
31 FW_VERSION_ATTR = "fw_version"
File ~/programs/anaconda3/lib/python3.11/site-packages/sdk_utils.py:21
18 import logging
19 from subprocess import CalledProcessError
---> 21 from utils import install_package
23 try:
24 install_package('mmh3')
ImportError: cannot import name 'install_package' from 'utils' (/home/bard/programs/anaconda3/lib/python3.11/site-packages/utils/init.py)'
Am I doing anything wrong here? Any help is much appreciated. Thanks.
Is there a roadmap for the SDK releases?
Hi again!
The provided examples do not exit even after calling the disconnect function of the client/gateway. Two reasons:
Best regards,
Aitor
the official example as below:
from psutil import cpu_percent, virtual_memory
from time import sleep
from tb_device_mqtt import TBDeviceMqttClient
# dependently of request method we send different data back
def on_server_side_rpc_request(client, request_id, request_body):
print(request_id, request_body)
if request_body["method"] == "getCPULoad":
client.send_rpc_reply(request_id, {"CPU percent": cpu_percent()})
elif request_body["method"] == "getMemoryUsage":
client.send_rpc_reply(request_id, {"Memory": virtual_memory().percent})
client = TBDeviceMqttClient("127.0.0.1", "A1_TEST_TOKEN")
client.set_server_side_rpc_request_handler(on_server_side_rpc_request)
client.connect()
while True:
sleep(1)
but the SDK does not include client parameters. so I modified the local SDK to fit your official example and use client seems likes to be better for using global variables.
can you add this parameter back?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.