README.md 9.42 KB
Newer Older
1
# ThingsBoard MQTT and HTTP client Python SDK
Serhii Likhouzov's avatar
Serhii Likhouzov committed
2
[![Join the chat at https://gitter.im/thingsboard/chat](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/thingsboard/chat?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
Serhii Likhouzov's avatar
Serhii Likhouzov committed
3

zbeacon's avatar
zbeacon committed
4
<a href="https://thingsboard.io"><img src="./logo.png?raw=true" width="100" height="100"></a>
Serhii Likhouzov's avatar
Serhii Likhouzov committed
5
6

ThingsBoard is an open-source IoT platform for data collection, processing, visualization, and device management.
7
This project ia a Python library that provides convenient client SDK for both Device and [Gateway](https://thingsboard.io/docs/reference/gateway-mqtt-api/) APIs.
Serhii Likhouzov's avatar
Serhii Likhouzov committed
8

Andrew Shvayka's avatar
Andrew Shvayka committed
9
SDK supports:
10
- Unencrypted and encrypted (TLS v1.2) connection
11
- QoS 0 and 1 (MQTT only)
12
13
14
- Automatic reconnect
- All [Device MQTT](https://thingsboard.io/docs/reference/mqtt-api/) APIs provided by ThingsBoard
- All [Gateway MQTT](https://thingsboard.io/docs/reference/gateway-mqtt-api/) APIs provided by ThingsBoard
15
16
- Most [Device HTTP](https://thingsboard.io/docs/reference/http-api/) APIs provided by ThingsBoard
  - Device Claiming and Firmware updates are not supported yet.
Andrew Shvayka's avatar
Andrew Shvayka committed
17

18
The [Device MQTT](https://thingsboard.io/docs/reference/mqtt-api/) API and the [Gateway MQTT](https://thingsboard.io/docs/reference/gateway-mqtt-api/) API are base on the Paho MQTT library. The [Device HTTP](https://thingsboard.io/docs/reference/http-api/) API is based on the Requests library.
Andrew Shvayka's avatar
Andrew Shvayka committed
19
20

## Installation
Serhii Likhouzov's avatar
Serhii Likhouzov committed
21

Serhii Likhouzov's avatar
Serhii Likhouzov committed
22
To install using pip:
Andrew Shvayka's avatar
Andrew Shvayka committed
23

Andrew Shvayka's avatar
Andrew Shvayka committed
24
```bash
Serhii Likhouzov's avatar
Serhii Likhouzov committed
25
pip3 install tb-mqtt-client
Serhii Likhouzov's avatar
Serhii Likhouzov committed
26
```
Serhii Likhouzov's avatar
Serhii Likhouzov committed
27

Andrew Shvayka's avatar
Andrew Shvayka committed
28
29
30
## Getting Started

Client initialization and telemetry publishing
31
### MQTT
Andrew Shvayka's avatar
Andrew Shvayka committed
32
33
```python
from tb_device_mqtt import TBDeviceMqttClient, TBPublishInfo
Serhii Likhouzov's avatar
Serhii Likhouzov committed
34
telemetry = {"temperature": 41.9, "enabled": False, "currentFirmwareVersion": "v1.2.2"}
Andrew Shvayka's avatar
Andrew Shvayka committed
35
36
client = TBDeviceMqttClient("127.0.0.1", "A1_TEST_TOKEN")
# Connect to ThingsBoard
Serhii Likhouzov's avatar
Serhii Likhouzov committed
37
client.connect()
Andrew Shvayka's avatar
Andrew Shvayka committed
38
39
40
41
42
43
44
# 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
Serhii Likhouzov's avatar
Serhii Likhouzov committed
45
client.disconnect()
Serhii Likhouzov's avatar
Serhii Likhouzov committed
46
```
Serhii Likhouzov's avatar
Serhii Likhouzov committed
47

48
### MQTT using TLS
Andrew Shvayka's avatar
Andrew Shvayka committed
49
50
51
52
53

TLS connection to localhost. See https://thingsboard.io/docs/user-guide/mqtt-over-ssl/ for more information about client and ThingsBoard configuration.

```python
from tb_device_mqtt import TBDeviceMqttClient
Serhii Likhouzov's avatar
Serhii Likhouzov committed
54
import socket
Andrew Shvayka's avatar
Andrew Shvayka committed
55
client = TBDeviceMqttClient(socket.gethostname())
Serhii Likhouzov's avatar
Serhii Likhouzov committed
56
57
58
59
60
client.connect(tls=True,
               ca_certs="mqttserver.pub.pem",
               cert_file="mqttclient.nopass.pem")
client.disconnect()
```
Andrew Shvayka's avatar
Andrew Shvayka committed
61

62
63
64
65
66
67
68
69
70
71
### HTTP

````python
from tb_device_http import TBHTTPDevice

client = TBHTTPDevice('https://thingsboard.example.com', 'secret-token')
client.connect()
client.send_telemetry({'temperature': 41.9})
````

Andrew Shvayka's avatar
Andrew Shvayka committed
72
73
## Using Device APIs

74
75
76
**TBDeviceMqttClient** provides access to Device MQTT APIs of ThingsBoard platform. It allows to publish telemetry and attribute updates, subscribe to attribute changes, send and receive RPC commands, etc. Use **TBHTTPClient** for the Device HTTP API.
#### Subscription to attributes
##### MQTT
Andrew Shvayka's avatar
Andrew Shvayka committed
77
```python
Serhii Likhouzov's avatar
Serhii Likhouzov committed
78
import time
Andrew Shvayka's avatar
Andrew Shvayka committed
79
from tb_device_mqtt import TBDeviceMqttClient
Serhii Likhouzov's avatar
Serhii Likhouzov committed
80
81
82
83

def callback(result):
    print(result)

Andrew Shvayka's avatar
Andrew Shvayka committed
84
client = TBDeviceMqttClient("127.0.0.1", "A1_TEST_TOKEN")
Serhii Likhouzov's avatar
Serhii Likhouzov committed
85
client.connect()
Andrew Shvayka's avatar
Andrew Shvayka committed
86
client.subscribe_to_attribute("uploadFrequency", callback)
87
client.subscribe_to_all_attributes(callback)
Serhii Likhouzov's avatar
Serhii Likhouzov committed
88
89
90
91
while True:
    time.sleep(1)
```

92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
##### HTTP
Note: The HTTP API only allows a subscription to updates for all attribute.
```python
from tb_device_http import TBHTTPClient
client = TBHTTPClient('https://thingsboard.example.com', 'secret-token')

def callback(data):
    print(data)
    # ...

# Subscribe
client.subscribe('attributes', callback)
# Unsubscribe
client.unsubscribe('attributes')
```

serhiilikl's avatar
serhiilikl committed
108
#### Telemetry pack sending
109
##### MQTT
serhiilikl's avatar
serhiilikl committed
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
```python
import logging
from tb_device_mqtt import TBDeviceMqttClient, TBPublishInfo
import time
telemetry_with_ts = {"ts": int(round(time.time() * 1000)), "values": {"temperature": 42.1, "humidity": 70}}
client = TBDeviceMqttClient("127.0.0.1", "A1_TEST_TOKEN")
# we set maximum amount of messages sent to send them at the same time. it may stress memory but increases performance
client.max_inflight_messages_set(100)
client.connect()
results = []
result = True
for i in range(0, 100):
    results.append(client.send_telemetry(telemetry_with_ts))
for tmp_result in results:
    result &= tmp_result.get() == TBPublishInfo.TB_ERR_SUCCESS
print("Result " + str(result))
client.disconnect()
```
128
129
##### HTTP
Unsupported, the HTTP API does not allow the packing of values.
serhiilikl's avatar
serhiilikl committed
130
131

#### Request attributes from server
132
##### MQTT
serhiilikl's avatar
serhiilikl committed
133
134
135
136
137
138
139
140
141
142
143
144
145
```python
import logging
import time
from tb_device_mqtt import TBDeviceMqttClient

def on_attributes_change(result, exception):
    if exception is not None:
        print("Exception: " + str(exception))
    else:
        print(result)

client = TBDeviceMqttClient("127.0.0.1", "A1_TEST_TOKEN")
client.connect()
146
client.request_attributes(["configuration","targetFirmwareVersion"], callback=on_attributes_change)
serhiilikl's avatar
serhiilikl committed
147
148
149
while True:
    time.sleep(1)
```
150
151
152
153
154
155
156
157
158
159
##### HTTP
```python
from tb_device_http import TBHTTPClient
client = TBHTTPClient('https://thingsboard.example.com', 'secret-token')

client_keys = ['attr1', 'attr2']
shared_keys = ['shared1', 'shared2']
data = client.request_attributes(client_keys=client_keys, shared_keys=shared_keys)
```

serhiilikl's avatar
serhiilikl committed
160
#### Respond to server RPC call
161
##### MQTT
serhiilikl's avatar
serhiilikl committed
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
```python
import psutil
import time
import logging
from tb_device_mqtt import TBDeviceMqttClient

# dependently of request method we send different data back
def on_server_side_rpc_request(request_id, request_body):
    print(request_id, request_body)
    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})

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)
```
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199

##### HTTP
```python
from tb_device_http import TBHTTPClient
client = TBHTTPClient('https://thingsboard.example.com', 'secret-token')

def callback(data):
    rpc_id = data['id']
    # ... do something with data['params'] and data['method']...
    response_params = {'result': 1}
    client.send_rpc(name='rpc_response', rpc_id=rpc_id, params=response_params)

# Subscribe
client.subscribe('rpc', callback)
# Unsubscribe
client.unsubscribe('rpc')
```

Andrew Shvayka's avatar
Andrew Shvayka committed
200
201
202
203
## Using Gateway APIs

**TBGatewayMqttClient** extends **TBDeviceMqttClient**, thus has access to all it's APIs as a regular device.
Besides, gateway is able to represent multiple devices connected to it. For example, sending telemetry or attributes on behalf of other, constrained, device. See more info about the gateway here: 
serhiilikl's avatar
serhiilikl committed
204
#### Telemetry and attributes sending 
Andrew Shvayka's avatar
Andrew Shvayka committed
205
206
```python
import time
207
208
from tb_gateway_mqtt import TBGatewayMqttClient
gateway = TBGatewayMqttClient("127.0.0.1", "GATEWAY_TEST_TOKEN")
Serhii Likhouzov's avatar
Serhii Likhouzov committed
209
gateway.connect()
serhiilikl's avatar
serhiilikl committed
210
gateway.gw_connect_device("Test Device A1")
Andrew Shvayka's avatar
Andrew Shvayka committed
211

serhiilikl's avatar
serhiilikl committed
212
213
gateway.gw_send_telemetry("Test Device A1", {"ts": int(round(time.time() * 1000)), "values": {"temperature": 42.2}})
gateway.gw_send_attributes("Test Device A1", {"firmwareVersion": "2.3.1"})
Andrew Shvayka's avatar
Andrew Shvayka committed
214

serhiilikl's avatar
serhiilikl committed
215
gateway.gw_disconnect_device("Test Device A1")
Serhii Likhouzov's avatar
Serhii Likhouzov committed
216
217
gateway.disconnect()
```
serhiilikl's avatar
serhiilikl committed
218
219
220
221
222
223
224
225
226
227
228
229
230
231
#### Request attributes
```python
import logging
import time
from tb_gateway_mqtt import TBGatewayMqttClient

def callback(result, exception):
    if exception is not None:
        print("Exception: " + str(exception))
    else:
        print(result)

gateway = TBGatewayMqttClient("127.0.0.1", "TEST_GATEWAY_TOKEN")
gateway.connect()
232
gateway.gw_request_shared_attributes("Test Device A1", ["temperature"], callback)
Andrew Shvayka's avatar
Andrew Shvayka committed
233

serhiilikl's avatar
serhiilikl committed
234
235
236
237
238
239
while True:
    time.sleep(1)
```
#### Respond to RPC
```python
import time
Andrew Shvayka's avatar
Andrew Shvayka committed
240

serhiilikl's avatar
serhiilikl committed
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
from tb_gateway_mqtt import TBGatewayMqttClient
import psutil

def rpc_request_response(request_body):
    # request body contains id, method and other parameters
    print(request_body)
    method = request_body["data"]["method"]
    device = request_body["device"]
    req_id = request_body["data"]["id"]
    # dependently of request method we send different data back
    if method == 'getCPULoad':
        gateway.gw_send_rpc_reply(device, req_id, {"CPU load": psutil.cpu_percent()})
    elif method == 'getMemoryLoad':
        gateway.gw_send_rpc_reply(device, req_id, {"Memory": psutil.virtual_memory().percent})
    else:
        print('Unknown method: ' + method)

gateway = TBGatewayMqttClient("127.0.0.1", "TEST_GATEWAY_TOKEN")
gateway.connect()
# now rpc_request_response will process rpc requests from servers
gateway.gw_set_server_side_rpc_request_handler(rpc_request_response)
# without device connection it is impossible to get any messages
263
gateway.gw_connect_device("Test Device A1")
serhiilikl's avatar
serhiilikl committed
264
265
266
while True:
    time.sleep(1)
```
Andrew Shvayka's avatar
Andrew Shvayka committed
267
268
## Other Examples

zbeacon's avatar
zbeacon committed
269
There are more examples for both [device](https://github.com/thingsboard/thingsboard-python-client-sdk/tree/master/examples/device) and [gateway](https://github.com/thingsboard/thingsboard-python-client-sdk/tree/master/examples/gateway) in corresponding [folders](https://github.com/thingsboard/thingsboard-python-client-sdk/tree/master/examples).
Andrew Shvayka's avatar
Andrew Shvayka committed
270

Serhii Likhouzov's avatar
Serhii Likhouzov committed
271
272
273
274
275
276
277
278
279
## Support

 - [Community chat](https://gitter.im/thingsboard/chat)
 - [Q&A forum](https://groups.google.com/forum/#!forum/thingsboard)
 - [Stackoverflow](http://stackoverflow.com/questions/tagged/thingsboard)

## Licenses

This project is released under [Apache 2.0 License](./LICENSE).