Skip to content

Commit 320a5f2

Browse files
authored
Merge pull request #2 from iot-for-all/dtdlv2
Version 1.1.0
2 parents e6d8b8c + 31db272 commit 320a5f2

31 files changed

+2170
-1194
lines changed

.gitignore

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,13 @@ exp.py
1313
# publish
1414
*.egg-info
1515
build
16-
dist
16+
dist
17+
18+
# virtualenv
19+
.env2
20+
.env3
21+
Include/
22+
Lib/
23+
Scripts/
24+
bin/
25+
pyvenv.cfg

CHANGELOG

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
1.1.0 (2021-02-05)
2+
-----------------
3+
- added DTDLv2 Support (with components)
4+
- added graceful shutdown
5+
- added credentials cache
6+
- added device twin synchronization at boot
7+
- improved tests and coverage
8+
19
1.0.4 (2020-10-07)
210
------------------
311
- fix property report with value wrapped

README.md

Lines changed: 77 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -5,47 +5,48 @@
55
[![PyPI version](https://badge.fury.io/py/iotc.svg)](https://badge.fury.io/py/iotc)
66

77
### An Azure IoT Central device client library written in Python.
8+
89
This repository contains code for the Azure IoT Central SDK for Python. This enables python developers to easily create device solutions that semealessly connect to Azure IoT Central applications.
910
It hides some of the complexities of the official Azure IoT SDK and uses IoT Central naming conventions.
1011

1112
### Disclaimer
12-
> __This library is experimental and has the purpose of providing an easy to use solution for prototyping and small projects. Although stable and actively maintained, its use in production is discouraged.
13-
Please refer to official [Azure IoT Python SDK](https://github.com/Azure/azure-iot-sdk-python) when building production products.__
13+
14+
> **This library is experimental and has the purpose of providing an easy to use solution for prototyping and small projects. Although stable and actively maintained, its use in production is discouraged.
15+
> Please refer to official [Azure IoT Python SDK](https://github.com/Azure/azure-iot-sdk-python) when building production products.**
1416
1517
_If you're looking for the v0.x.x client library, it is now preserved [here](https://github.com/obastemur/iot_client/tree/master/python).
1618
Latest version on pypi is 0.3.9_
1719

1820
## Prerequisites
19-
+ Python 2.7+ or Python 3.7+ (recommended)
21+
22+
- Python 2.7+ or Python 3.7+ (recommended)
2023

2124
## Installing `iotc`
2225

2326
```
2427
pip install iotc
2528
```
29+
2630
These clients are available with an asynchronous API, as well as a blocking synchronous API for compatibility scenarios. **We recommend you use Python 3.7+ and the asynchronous API.**
2731

2832
| Python Version | Asynchronous API | Synchronous API |
2933
| -------------- | ---------------- | --------------- |
3034
| Python 3.5.3+ | **YES** | **YES** |
3135
| Python 2.7 | NO | **YES** |
3236

33-
3437
## Samples
35-
Check out the [sample repository](samples) for example code showing how the SDK can be used in the various scenarios:
3638

37-
* [py3](samples/py3.py) - Sending telemetry and receiving properties and commands with device connected through **symmetric key** (Python 3.7+)
38-
* [py3_x509](samples/py3_x509.py) - Sending telemetry and receiving properties and commands with device connected through **x509 certificates** (Python 3.7+)
39-
* [py3_file_logger](samples/py3_file_logger.py) - Print logs on file with rotation (Python 3.7+)
40-
* [py3_eventhub_logger](samples/py3_eventhub_logger.py) - Redirect logs to Azure Event Hub (Python 3.7+)
39+
Check out the [sample repository](samples) for example code showing how the SDK can be used in the various scenarios:
4140

41+
- [async_device_key](samples/async_device_key) - Sending telemetry and receiving properties and commands with device connected through **symmetric key** (Python 3.7+)
42+
- [async_x509](samples/async_x509.py) - Sending telemetry and receiving properties and commands with device connected through **x509 certificates** (Python 3.7+)
43+
- [async_file_logger](samples/async_file_logger.py) - Print logs on file with rotation (Python 3.7+)
44+
- [async_eventhub_logger](samples/async_eventhub_logger.py) - Redirect logs to Azure Event Hub (Python 3.7+)
4245

4346
**The following samples are legacy samples**, they work with the sycnhronous API intended for use with Python 2.7, or in compatibility scenarios with later versions. We recommend you use the asynchronous API and Python3 samples above instead.
4447

45-
46-
* [py2](samples/py2.py) - Sending telemetry and receiving properties and commands with device connected through **symmetric key** (Python 2.7+)
47-
* [py2_x509](samples/py2_x509.py) - Sending telemetry and receiving properties and commands with device connected through **x509 certificates** (Python 2.7+)
48-
48+
- [sync_device_key](samples/sync_device_key.py) - Sending telemetry and receiving properties and commands with device connected through **symmetric key** (Python 2.7+)
49+
- [sync_x509](samples/sync_x509.py) - Sending telemetry and receiving properties and commands with device connected through **x509 certificates** (Python 2.7+)
4950

5051
Samples by default parse a configuration file including required credentials. Just create a file called **samples.ini** inside the _samples_ folder with a content like this:
5152

@@ -61,22 +62,27 @@ CertFilePath = path_to_cert_file
6162
KeyFilePath = path_to_key_file
6263
CertPassphrase = optional password
6364
```
65+
6466
The configuration file can include one or more sections representing device connection details. Section names must match references in the sample file.
6567

6668
### Run samples with local changes
69+
6770
It is possible to run samples against the local copy of the device client. This is particularly useful when testing patches not yet published upstream.
6871
Just add an entry to **samples.ini** in the _DEFAULT_ section:
72+
6973
```ini
7074
[DEFAULT]
7175
Local = yes
7276
```
7377

7478
## Importing the module
79+
7580
Sync client (Python 2.7+ and 3.7+) can be imported in this way:
7681

7782
```py
7883
from iotc import IoTCClient
7984
```
85+
8086
Async client (with asyncio for Python 3.7+ only) can be imported like this:
8187

8288
```py
@@ -86,6 +92,7 @@ from iotc.aio import IoTCClient
8692
## Connecting
8793

8894
#### X509
95+
8996
```py
9097
scope_id = 'scope_id';
9198
device_id = 'device_id';
@@ -94,14 +101,15 @@ key = {'certFile':'<CERT_CHAIN_FILE_PATH>','keyFile':'<CERT_KEY_FILE_PATH>','cer
94101
iotc = IoTCClient(device_id, scope_id,
95102
IOTCConnectType.IOTC_CONNECT_X509_CERT, key)
96103
```
104+
97105
IOTCConnectType enum can be imported from the same module of IoTCClient
98106

99107
_'certPhrase'_ is optional and represents the password for the certificate if any
100108

101109
**_A handy tool to generate self-signed certificates in order to test x509 authentication can be found in the IoTCentral Node.JS SDK [here.](https://github.com/lucadruda/iotc-nodejs-device-client#generate-x509-certificates)_**
102110

103-
104111
#### SAS
112+
105113
```py
106114
scopeId = 'scopeID'
107115
device_id = 'device_id'
@@ -110,27 +118,35 @@ sasKey = 'masterKey' # or use device key directly
110118
iotc = IoTCClient(device_id, scopeId,
111119
IOTCConnectType.IOTC_CONNECT_SYMM_KEY, sas_key)
112120
```
121+
113122
IOTCConnectType enum can be imported from the same module of IoTCClient
114123

115124
### Connect
125+
116126
Sync
127+
117128
```
118129
iotc.connect()
119130
```
131+
120132
Async
133+
121134
```py
122135
await iotc.connect()
123136
```
137+
124138
After successfull connection, IOTC context is available for further commands.
125139

126140
### Reconnection
127-
The device client automatically handle reconnection in case of network failures or disconnections. However if process runs for long time (e.g. unmonitored devices) a reconnection might fail because of credentials expiration.
141+
142+
The device client automatically handle reconnection in case of network failures or disconnections. However if process runs for long time (e.g. unmonitored devices) a reconnection might fail because of credentials expiration.
128143

129144
To control reconnection and reset credentials the function _is_connected()_ is available and can be used to test connection status inside a loop or before running operations.
130145

131146
e.g.
147+
132148
```py
133-
retry = 0 # stop reconnection attempts
149+
retry = 0 # stop reconnection attempts
134150
while true:
135151
if iotc.is_connected():
136152
# do something
@@ -141,13 +157,37 @@ while true:
141157
iotc.connect()
142158
```
143159

160+
## Cache Credentials
144161

162+
The IoT Central device client accepts a storage manager to cache connection credentials. This allows to skip unnecessary device re-provisioning and requests to provisioning service.
163+
When valid credentials are present, device connects directly to IoT Central, otherwise it asks provisioning service for new credentials and eventually cache them.
164+
165+
Provided class must extend [_Storage_](src/iotc/models.py) abstract class.
166+
167+
```py
168+
class FileStorage(Storage):
169+
def __init__(self):
170+
# initialize file read
171+
...
172+
def retrieve(self):
173+
# read from file
174+
...
175+
return CredentialsCache(
176+
hub_name,
177+
device_id,
178+
key,
179+
)
180+
def persist(self, credentials):
181+
# write to file
182+
...
183+
```
145184

146185
## Operations
147186

148187
### Send telemetry
149188

150189
e.g. Send telemetry every 3 seconds
190+
151191
```py
152192
while iotc.is_connected():
153193
await iotc.send_telemetry({
@@ -157,22 +197,28 @@ while iotc.is_connected():
157197
})
158198
time.sleep(3)
159199
```
160-
An optional *properties* object can be included in the send methods, to specify additional properties for the message (e.g. timestamp,etc... ).
200+
201+
An optional _properties_ object can be included in the send methods, to specify additional properties for the message (e.g. timestamp,etc... ).
161202
Properties can be custom or part of the reserved ones (see list [here](https://github.com/Azure/azure-iot-sdk-csharp/blob/master/iothub/device/src/MessageSystemPropertyNames.cs#L36)).
162203

163204
> Payload content type and encoding are set by default to 'application/json' and 'utf-8'. Alternative values can be set using these functions:<br/>
164-
_iotc.set_content_type(content_type)_ # .e.g 'text/plain'
165-
_iotc.set_content_encoding(content_encoding)_ # .e.g 'ascii'
205+
> _iotc.set_content_type(content_type)_ # .e.g 'text/plain'
206+
> _iotc.set_content_encoding(content_encoding)_ # .e.g 'ascii'
166207
167208
### Send property update
209+
168210
```py
169211
iotc.send_property({'fieldName':'fieldValue'})
170212
```
213+
171214
### Listen to properties update
215+
172216
```py
173217
iotc.on(IOTCEvents.IOTC_PROPERTIES, callback)
174218
```
219+
175220
To provide setting sync aknowledgement, the callback must reply **True** if the new value has been applied or **False** otherwise
221+
176222
```py
177223
async def on_props(prop_name, prop_value):
178224
print(prop_value)
@@ -182,12 +228,15 @@ iotc.on(IOTCEvents.IOTC_PROPERTIES, on_props)
182228
```
183229

184230
### Listen to commands
231+
185232
```py
186233
iotc.on(IOTCEvents.IOTC_COMMAND, callback)
187234
```
235+
188236
To provide feedbacks for the command like execution result or progress, the client can call the **ack** function available in the callback.
189237

190238
The function accepts 3 arguments: command name, a custom response message and the request id for which the ack applies.
239+
191240
```py
192241
async def on_commands(command, ack):
193242
print(command.name)
@@ -198,11 +247,11 @@ async def on_commands(command, ack):
198247

199248
The default log prints to console operations status and errors.
200249
This is the _IOTC_LOGGING_API_ONLY_ logging level.
201-
The function __set_log_level()__ can be used to change options or disable logs. It accepts a _IOTCLogLevel_ value among the following:
250+
The function **set_log_level()** can be used to change options or disable logs. It accepts a _IOTCLogLevel_ value among the following:
202251

203-
- IOTC_LOGGING_DISABLED (log disabled)
204-
- IOTC_LOGGING_API_ONLY (information and errors, default)
205-
- IOTC_LOGGING_ALL (all messages, debug and underlying errors)
252+
- IOTC_LOGGING_DISABLED (log disabled)
253+
- IOTC_LOGGING_API_ONLY (information and errors, default)
254+
- IOTC_LOGGING_ALL (all messages, debug and underlying errors)
206255

207256
The device client also accepts an optional Logger instance to redirect logs to other targets than console.
208257
The custom class must implement three methods:
@@ -212,9 +261,11 @@ The custom class must implement three methods:
212261
- set_log_level(message);
213262

214263
## One-touch device provisioning and approval
264+
215265
A device can send custom data during provision process: if a device is aware of its IoT Central template Id, then it can be automatically provisioned.
216266

217267
### How to set IoTC template ID in your device
268+
218269
Template Id can be found in the device explorer page of IoTCentral
219270
![Img](https://github.com/iot-for-all/iotc-python-client/raw/master/assets/modelId.jpg)
220271

@@ -225,16 +276,18 @@ iotc.set_model_id('<modelId>')
225276
```
226277

227278
### Manual approval (default)
279+
228280
By default device auto-approval in IoT Central is disabled, which means that administrator needs to approve the device registration to complete the provisioning process.
229281
This can be done from explorer page after selecting the device
230282
![Img](https://github.com/iot-for-all/iotc-python-client/raw/master/assets/manual_approval.jpg)
231283

232-
233284
### Automatic approval
285+
234286
To change default behavior, administrator can enable device auto-approval from Device Connection page under the Administration section.
235287
With automatic approval a device can be provisioned without any manual action and can start sending/receiving data after status changes to "Provisioned"
236288

237289
![Img](https://github.com/iot-for-all/iotc-python-client/raw/master/assets/auto_approval.jpg)
238290

239291
## License
292+
240293
This samples is licensed with the MIT license. For more information, see [LICENSE](./LICENSE)

requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
azure-iot-device

0 commit comments

Comments
 (0)