MeTIOT 0.1.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- metiot-0.1.3/.gitignore +26 -0
- metiot-0.1.3/CMakeLists.txt +18 -0
- metiot-0.1.3/LICENSE +21 -0
- metiot-0.1.3/PKG-INFO +94 -0
- metiot-0.1.3/README.md +83 -0
- metiot-0.1.3/docs/API_REFERENCE.md +138 -0
- metiot-0.1.3/docs/DEVICE_PROTOCOL_DEV_GUIDE.md +23 -0
- metiot-0.1.3/docs/PYTHON_LIB_GUIDE.md +131 -0
- metiot-0.1.3/docs/TCP_PROTOCOL_SPEC.md +205 -0
- metiot-0.1.3/docs/images/DeviceData.jpg +0 -0
- metiot-0.1.3/docs/images/DeviceIdentifierResponse.jpg +0 -0
- metiot-0.1.3/docs/images/FishTankSensorAttributeResponse.jpg +0 -0
- metiot-0.1.3/docs/images/Packet.jpg +0 -0
- metiot-0.1.3/examples/.gitkeep +0 -0
- metiot-0.1.3/examples/simple_client/README.md +33 -0
- metiot-0.1.3/examples/simple_client/main.py +59 -0
- metiot-0.1.3/pyproject.toml +21 -0
- metiot-0.1.3/src/MeTIOTCommunication/CMakeLists.txt +25 -0
- metiot-0.1.3/src/MeTIOTCommunication/include/client.hpp +93 -0
- metiot-0.1.3/src/MeTIOTCommunication/include/core/exceptions.hpp +27 -0
- metiot-0.1.3/src/MeTIOTCommunication/include/core/socket_core.hpp +35 -0
- metiot-0.1.3/src/MeTIOTCommunication/include/interfaces/event_handler.hpp +29 -0
- metiot-0.1.3/src/MeTIOTCommunication/include/protocol/abstract_protocol.hpp +44 -0
- metiot-0.1.3/src/MeTIOTCommunication/include/protocol/device_agnostic_protocol.hpp +29 -0
- metiot-0.1.3/src/MeTIOTCommunication/include/protocol/filter_guardian_protocol.hpp +16 -0
- metiot-0.1.3/src/MeTIOTCommunication/include/protocol/fish_tank_protocol.hpp +16 -0
- metiot-0.1.3/src/MeTIOTCommunication/include/protocol/protocol_constants.hpp +52 -0
- metiot-0.1.3/src/MeTIOTCommunication/include/utils/byte_conversion.hpp +26 -0
- metiot-0.1.3/src/MeTIOTCommunication/include/utils/cobs.hpp +23 -0
- metiot-0.1.3/src/MeTIOTCommunication/include/utils/crc.hpp +26 -0
- metiot-0.1.3/src/MeTIOTCommunication/src/client.cpp +169 -0
- metiot-0.1.3/src/MeTIOTCommunication/src/core/socket_core.cpp +51 -0
- metiot-0.1.3/src/MeTIOTCommunication/src/protocol/abstract_protocol.cpp +64 -0
- metiot-0.1.3/src/MeTIOTCommunication/src/protocol/device_agnostic_protocol.cpp +22 -0
- metiot-0.1.3/src/MeTIOTCommunication/src/protocol/filter_guardian_protocol.cpp +60 -0
- metiot-0.1.3/src/MeTIOTCommunication/src/protocol/fish_tank_protocol.cpp +42 -0
- metiot-0.1.3/src/MeTIOTCommunication/src/utils/byte_conversion.cpp +88 -0
- metiot-0.1.3/src/MeTIOTCommunication/src/utils/cobs.cpp +82 -0
- metiot-0.1.3/src/MeTIOTCommunication/src/utils/crc.cpp +17 -0
- metiot-0.1.3/src/python_bindings/CMakeLists.txt +18 -0
- metiot-0.1.3/src/python_bindings/PythonEventHandler.hpp +50 -0
- metiot-0.1.3/src/python_bindings/bindings.cpp +145 -0
- metiot-0.1.3/tests/test_basic.py +5 -0
metiot-0.1.3/.gitignore
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
venv/
|
|
2
|
+
**/build*/
|
|
3
|
+
|
|
4
|
+
CMakeCache.txt
|
|
5
|
+
CMakeFiles/
|
|
6
|
+
cmake_install.cmake
|
|
7
|
+
install_manifest.txt
|
|
8
|
+
|
|
9
|
+
*.o
|
|
10
|
+
*.obj
|
|
11
|
+
*.lo
|
|
12
|
+
*.la
|
|
13
|
+
*.d
|
|
14
|
+
*.a
|
|
15
|
+
*.so
|
|
16
|
+
*.dylib
|
|
17
|
+
*.dll
|
|
18
|
+
*.pyd
|
|
19
|
+
|
|
20
|
+
*.pyc
|
|
21
|
+
*.pyo
|
|
22
|
+
dist/
|
|
23
|
+
*.egg-info/
|
|
24
|
+
|
|
25
|
+
*~
|
|
26
|
+
.vscode/
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
cmake_minimum_required(VERSION 3.10)
|
|
2
|
+
project(MeTIOTPythonLibrary LANGUAGES CXX)
|
|
3
|
+
|
|
4
|
+
set(CMAKE_CXX_STANDARD 23)
|
|
5
|
+
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|
6
|
+
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
|
7
|
+
|
|
8
|
+
include(FetchContent)
|
|
9
|
+
FetchContent_Declare(
|
|
10
|
+
pybind11
|
|
11
|
+
GIT_REPOSITORY https://github.com/pybind/pybind11.git
|
|
12
|
+
GIT_TAG v3.0.1
|
|
13
|
+
)
|
|
14
|
+
FetchContent_MakeAvailable(pybind11)
|
|
15
|
+
|
|
16
|
+
add_subdirectory(src/MeTIOTCommunication)
|
|
17
|
+
|
|
18
|
+
add_subdirectory(src/python_bindings)
|
metiot-0.1.3/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Microelectronic Technologies
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
metiot-0.1.3/PKG-INFO
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
|
+
Name: MeTIOT
|
|
3
|
+
Version: 0.1.3
|
|
4
|
+
Summary: Communication handling for all MeT IOT devices
|
|
5
|
+
Author-Email: Cody Jackson <cjackson@micr.com.au>
|
|
6
|
+
Project-URL: Homepage, https://github.com/Microelectronic-Technologies/MeTIOTCommunication
|
|
7
|
+
Project-URL: API Reference, https://github.com/Microelectronic-Technologies/MeTIOTCommunication/blob/main/docs/API_REFERENCE.md
|
|
8
|
+
Project-URL: Library Guide, https://github.com/Microelectronic-Technologies/MeTIOTCommunication/blob/main/docs/PYTHON_LIB_GUIDE.md
|
|
9
|
+
Requires-Python: >=3.8
|
|
10
|
+
Description-Content-Type: text/markdown
|
|
11
|
+
|
|
12
|
+
# MeT IOT Communication
|
|
13
|
+
|
|
14
|
+
## Useful Links
|
|
15
|
+
|
|
16
|
+
* [API Reference](https://github.com/Microelectronic-Technologies/MeTIOTCommunication/blob/main/docs/API_REFERENCE.md)
|
|
17
|
+
* [Python Library Guide](https://github.com/Microelectronic-Technologies/MeTIOTCommunication/blob/main/docs/PYTHON_LIB_GUIDE.md)
|
|
18
|
+
* [Example Projects](https://github.com/Microelectronic-Technologies/MeTIOTCommunication/tree/main/examples)
|
|
19
|
+
|
|
20
|
+
## Changelog `v0.1.3`
|
|
21
|
+
|
|
22
|
+
```plaintext
|
|
23
|
+
- Fix invalid pointer error on python program exit
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## How To Use
|
|
27
|
+
|
|
28
|
+
### Importing the Library
|
|
29
|
+
|
|
30
|
+
#### Use pip to install the library
|
|
31
|
+
|
|
32
|
+
```sh
|
|
33
|
+
pip install MeTIOT
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
> [!NOTE]
|
|
37
|
+
> This library is not pre-compiled.
|
|
38
|
+
> You must have installed on your system (Other version may work but are official unsupported):
|
|
39
|
+
> * GCC >= 15.2.1
|
|
40
|
+
> * CMake >= 3.10
|
|
41
|
+
|
|
42
|
+
### Programming with the Library
|
|
43
|
+
|
|
44
|
+
#### Testing the library imported successfully
|
|
45
|
+
|
|
46
|
+
You can use this code to test you can successfully import the library into your code.
|
|
47
|
+
|
|
48
|
+
```py
|
|
49
|
+
import MeTIOT
|
|
50
|
+
|
|
51
|
+
client = MeTIOT.DeviceClient("0.0.0.0", 12345)
|
|
52
|
+
|
|
53
|
+
print(type(client))
|
|
54
|
+
print("MeTIOT import successful!")
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
#### Using the library
|
|
58
|
+
|
|
59
|
+
For further information on how to use this library refer to the [PYTHON_LIB_GUIDE.md document](https://github.com/Microelectronic-Technologies/MeTIOTCommunication/blob/main/docs/PYTHON_LIB_GUIDE.md).
|
|
60
|
+
|
|
61
|
+
## How to compile and use from this repository
|
|
62
|
+
|
|
63
|
+
Linux based systems:
|
|
64
|
+
|
|
65
|
+
1. Clone the repository
|
|
66
|
+
```bash
|
|
67
|
+
git clone https://github.com/Microelectronic-Technologies/MeTIOTCommunication.git
|
|
68
|
+
```
|
|
69
|
+
2. Create and navigate into build directory
|
|
70
|
+
```bash
|
|
71
|
+
mkdir build
|
|
72
|
+
cd build
|
|
73
|
+
```
|
|
74
|
+
3. Compile library using CMake
|
|
75
|
+
```bash
|
|
76
|
+
cmake ..
|
|
77
|
+
cmake --build . --config Release
|
|
78
|
+
```
|
|
79
|
+
4. Export path to python
|
|
80
|
+
```bash
|
|
81
|
+
export PYTHONPATH=./src/python_bindings:$PYTHONPATH
|
|
82
|
+
```
|
|
83
|
+
5. Now you can use and import the library in your current directory
|
|
84
|
+
6. *(optional)* Test the library is python
|
|
85
|
+
```bash
|
|
86
|
+
python3
|
|
87
|
+
```
|
|
88
|
+
```py
|
|
89
|
+
import MeTIOT
|
|
90
|
+
client = MeTIOT.DeviceClient("0.0.0.0", 12345)
|
|
91
|
+
type(client)
|
|
92
|
+
client.connect()
|
|
93
|
+
```
|
|
94
|
+
|
metiot-0.1.3/README.md
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# MeT IOT Communication
|
|
2
|
+
|
|
3
|
+
## Useful Links
|
|
4
|
+
|
|
5
|
+
* [API Reference](https://github.com/Microelectronic-Technologies/MeTIOTCommunication/blob/main/docs/API_REFERENCE.md)
|
|
6
|
+
* [Python Library Guide](https://github.com/Microelectronic-Technologies/MeTIOTCommunication/blob/main/docs/PYTHON_LIB_GUIDE.md)
|
|
7
|
+
* [Example Projects](https://github.com/Microelectronic-Technologies/MeTIOTCommunication/tree/main/examples)
|
|
8
|
+
|
|
9
|
+
## Changelog `v0.1.3`
|
|
10
|
+
|
|
11
|
+
```plaintext
|
|
12
|
+
- Fix invalid pointer error on python program exit
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## How To Use
|
|
16
|
+
|
|
17
|
+
### Importing the Library
|
|
18
|
+
|
|
19
|
+
#### Use pip to install the library
|
|
20
|
+
|
|
21
|
+
```sh
|
|
22
|
+
pip install MeTIOT
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
> [!NOTE]
|
|
26
|
+
> This library is not pre-compiled.
|
|
27
|
+
> You must have installed on your system (Other version may work but are official unsupported):
|
|
28
|
+
> * GCC >= 15.2.1
|
|
29
|
+
> * CMake >= 3.10
|
|
30
|
+
|
|
31
|
+
### Programming with the Library
|
|
32
|
+
|
|
33
|
+
#### Testing the library imported successfully
|
|
34
|
+
|
|
35
|
+
You can use this code to test you can successfully import the library into your code.
|
|
36
|
+
|
|
37
|
+
```py
|
|
38
|
+
import MeTIOT
|
|
39
|
+
|
|
40
|
+
client = MeTIOT.DeviceClient("0.0.0.0", 12345)
|
|
41
|
+
|
|
42
|
+
print(type(client))
|
|
43
|
+
print("MeTIOT import successful!")
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
#### Using the library
|
|
47
|
+
|
|
48
|
+
For further information on how to use this library refer to the [PYTHON_LIB_GUIDE.md document](https://github.com/Microelectronic-Technologies/MeTIOTCommunication/blob/main/docs/PYTHON_LIB_GUIDE.md).
|
|
49
|
+
|
|
50
|
+
## How to compile and use from this repository
|
|
51
|
+
|
|
52
|
+
Linux based systems:
|
|
53
|
+
|
|
54
|
+
1. Clone the repository
|
|
55
|
+
```bash
|
|
56
|
+
git clone https://github.com/Microelectronic-Technologies/MeTIOTCommunication.git
|
|
57
|
+
```
|
|
58
|
+
2. Create and navigate into build directory
|
|
59
|
+
```bash
|
|
60
|
+
mkdir build
|
|
61
|
+
cd build
|
|
62
|
+
```
|
|
63
|
+
3. Compile library using CMake
|
|
64
|
+
```bash
|
|
65
|
+
cmake ..
|
|
66
|
+
cmake --build . --config Release
|
|
67
|
+
```
|
|
68
|
+
4. Export path to python
|
|
69
|
+
```bash
|
|
70
|
+
export PYTHONPATH=./src/python_bindings:$PYTHONPATH
|
|
71
|
+
```
|
|
72
|
+
5. Now you can use and import the library in your current directory
|
|
73
|
+
6. *(optional)* Test the library is python
|
|
74
|
+
```bash
|
|
75
|
+
python3
|
|
76
|
+
```
|
|
77
|
+
```py
|
|
78
|
+
import MeTIOT
|
|
79
|
+
client = MeTIOT.DeviceClient("0.0.0.0", 12345)
|
|
80
|
+
type(client)
|
|
81
|
+
client.connect()
|
|
82
|
+
```
|
|
83
|
+
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
# API Reference
|
|
2
|
+
|
|
3
|
+
The `MeTIOT` library provides a high-level interface for interacting with MeTIOT IoT devices via TCP. The core of the library is the `DeviceClient`, which manages the connection, event loops, and protocol handling.
|
|
4
|
+
|
|
5
|
+
## 1. Client Library Components (`MeTIOT`)
|
|
6
|
+
|
|
7
|
+
The `DeviceClient` class is the primary entry point for all device interactions.
|
|
8
|
+
|
|
9
|
+
### Lifecycle Management
|
|
10
|
+
|
|
11
|
+
#### `DeviceClient(ip: str, port: int)`
|
|
12
|
+
|
|
13
|
+
*Constructor* | **Module:** `MeTIOT`
|
|
14
|
+
|
|
15
|
+
Initializes the client object with the target device's network information.
|
|
16
|
+
|
|
17
|
+
* **Arguments**
|
|
18
|
+
* `ip` (str): IPv4 address of the device.
|
|
19
|
+
* `port` (int): Communication port.
|
|
20
|
+
* **Errors:** Raises `SocketError` if the IP address is invalid or unsupported.
|
|
21
|
+
|
|
22
|
+
#### `connect()`
|
|
23
|
+
|
|
24
|
+
*Method* | **Module:** `MeTIOT.DeviceClient`
|
|
25
|
+
|
|
26
|
+
Establishes the TCP connection and performs initial handshake/device discovery.
|
|
27
|
+
|
|
28
|
+
* **Errors:** Raises `SocketError` if the device is unreachable.
|
|
29
|
+
|
|
30
|
+
#### `disconnect()`
|
|
31
|
+
|
|
32
|
+
*Method* | **Module:** `MeTIOT.DeviceClient`
|
|
33
|
+
|
|
34
|
+
Safely closes the active TCP connection.
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
### Protocol & Identity
|
|
39
|
+
|
|
40
|
+
#### `get_protocol_handler()`
|
|
41
|
+
|
|
42
|
+
*Method* | **Module:** `MeTIOT.DeviceClient`
|
|
43
|
+
|
|
44
|
+
Returns the `ProtocolHandler` specific to the current device type. use this to encode/decode bytes.
|
|
45
|
+
|
|
46
|
+
* **Returns:** `ProtocolHandler`
|
|
47
|
+
|
|
48
|
+
> [!TIP]
|
|
49
|
+
> Use this instead of the deprecated `get_specific_protocol_handler()`
|
|
50
|
+
|
|
51
|
+
#### `get_unique_id()`
|
|
52
|
+
|
|
53
|
+
*Method* | **Module:** `MeTIOT.DeviceClient`
|
|
54
|
+
|
|
55
|
+
Retrieves the globally unique 64-bit ID assigned to the hardware.
|
|
56
|
+
|
|
57
|
+
* **Returns:** 8-byte Device ID.
|
|
58
|
+
|
|
59
|
+
#### `get_device_type()`
|
|
60
|
+
|
|
61
|
+
*Method* | **Module:** `MeTIOT.DeviceClient`
|
|
62
|
+
|
|
63
|
+
Identifies the model/type of the connected device.
|
|
64
|
+
|
|
65
|
+
* **Returns:** `MeTIOT.DeviceType`
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
### Asynchronous Operations
|
|
70
|
+
|
|
71
|
+
#### `assign_handlers(on_data, on_warning=None, on_fatal=None)`
|
|
72
|
+
|
|
73
|
+
*Method* | **Module:** `MeTIOT.DeviceClient`
|
|
74
|
+
|
|
75
|
+
Registers callback functions for the background listening thread.
|
|
76
|
+
|
|
77
|
+
| Argument | Signature | Description |
|
|
78
|
+
|-|-|-|
|
|
79
|
+
| `on_data` | `(device, header, data)` | Triggered on successful packet reception. |
|
|
80
|
+
| `on_warning` | `(device, msg)` | **Optional.** Triggered on non-fatal issues (e.g., CRC mismatch). |
|
|
81
|
+
| `on_fatal` | `(device, msg)` | **Optional.** Triggered when the loop crashes or 10 warnings occur |
|
|
82
|
+
|
|
83
|
+
#### `start_listening()`
|
|
84
|
+
|
|
85
|
+
*Method* | **Module:** `MeTIOT.DeviceClient`
|
|
86
|
+
|
|
87
|
+
Spawns a background thread to monitor the TCP socket. **Requires handlers to be assigned first.**
|
|
88
|
+
|
|
89
|
+
* **Errors:** `LibraryError` if `assign_handlers` has not been called.
|
|
90
|
+
|
|
91
|
+
#### `send_packet(packet: bytes)`
|
|
92
|
+
|
|
93
|
+
*Method* | **Module:** `MeTIOT.DeviceClient`
|
|
94
|
+
|
|
95
|
+
Sends a raw byte buffer to the device.
|
|
96
|
+
|
|
97
|
+
* **Arguments:** `packet` (bytes): The encoded payload.
|
|
98
|
+
* **Errors:** `SocketError` on transmission failure.
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
> [!IMPORTANT]
|
|
102
|
+
> **WIP** Document. Below text may not be correct.
|
|
103
|
+
|
|
104
|
+
## 2. Protocol Handler Methods (Accessed via `client.get_protocol_handler()`)
|
|
105
|
+
|
|
106
|
+
The methods available on the protocol handler instance depend entirely on the connected device type. The protocol handler also contains universal utility methods for packet handling.
|
|
107
|
+
|
|
108
|
+
### 2.1 Universal Protocol Utility Methods
|
|
109
|
+
|
|
110
|
+
| Method | Returns | Description |
|
|
111
|
+
|-|-|-|
|
|
112
|
+
| `deconstruct_packet(packet: bytes)` | `tuple[int, bytes]` | Decodes the packet buffer, validating CRC, performing COBS unstuffing, and returning the Data Header and raw Data Payload. |
|
|
113
|
+
| `interpret_data(data_payload: bytes)` | `dict` | Interprets the raw Data Payload into a key-value dictionary using known Sub-Headers and Data Types. Keys match the Data Field purpose (e.g., "Temperature_C"). |
|
|
114
|
+
| `fetch_last_packet()` | `bytes` | Returns the raw byte buffer of the last packet successfully created by this protocol handler instance. Useful for re-sending after a `MalformedPacketNotification`. |
|
|
115
|
+
|
|
116
|
+
### 2.2 Fish Tank Protocol Methods (`Device ID: 0xFF`)
|
|
117
|
+
|
|
118
|
+
These methods are available if the device type is "Fish Tank"
|
|
119
|
+
|
|
120
|
+
| Method | Returns | Purpose | Arguments |
|
|
121
|
+
|-|-|-|-|
|
|
122
|
+
|
|
123
|
+
## 3. Protocol Constants (`MeTIOT.ProtocolConstants`)
|
|
124
|
+
|
|
125
|
+
These constants are integers representing the 1-byte Header/Sub-Header codes used in the communication. All constants mentioned here are the exposed constants. In other documentation the codes here are referenced as *Device-to-Library Codes*.
|
|
126
|
+
|
|
127
|
+
### 3.1 Standard Data Header Codes
|
|
128
|
+
|
|
129
|
+
| Constant Name | Value | Description |
|
|
130
|
+
|:---|:---|:---|
|
|
131
|
+
| `MalformedPacketNotification` | `0xFF` | Notification for a corrupted/unparsable packet. |
|
|
132
|
+
| `DeviceIdentifier` | `0xFE` | Response from the device containing the Device ID and Unique ID. |
|
|
133
|
+
| `DataTransfer` | `0xFD` | Unsolicited data/status update from the device. |
|
|
134
|
+
|
|
135
|
+
### 3.2 Fish Tank Data Header Codes
|
|
136
|
+
|
|
137
|
+
| Constant Name | Value | Description |
|
|
138
|
+
|-|-|-|
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Device Protocol
|
|
2
|
+
|
|
3
|
+
## Current Device Protocol Implementation
|
|
4
|
+
|
|
5
|
+
**Challenge:** Our `DeviceClient` class's `protocolHandler` is of the type `std::unique_ptr<AbstractProtocol>` which stops us from calling device protocol specific functions (e.g., function to create a calibration packet with specific parameters.)
|
|
6
|
+
|
|
7
|
+
**Solution:** Ideally the python programmer using this library simply calls the same function to get all of their device specific commands regardless of the device type. The solution to this issue is during the python function call `get_specific_protocol_handler` we automatically resolve exactly what protocol data type we are using (stored in `deviceType` for simplicity) then we dynamically cast the `std::unique_ptr<AbstractProtocol>` type into what ever the device protocol actually is.
|
|
8
|
+
|
|
9
|
+
## Creating New Device Protocols
|
|
10
|
+
|
|
11
|
+
> [!NOTE]
|
|
12
|
+
> The above information in `Current Device Protocol Implementation` is important to read to understand *why* you are doing the following
|
|
13
|
+
|
|
14
|
+
When creating a new device protocol (to support device specific protocol commands) following these steps should lead to success:
|
|
15
|
+
|
|
16
|
+
1. Add protocol .hpp file to `include/protocol/` and .cpp file to `src/protocol/`.
|
|
17
|
+
2. Create a class inheriting `AbstractProtocol` (This gives access to required functions like `constructPacket`).
|
|
18
|
+
3. Copy a similar workflow to other reference protocols. Function called -> Create data field -> Call constructPacket() -> return packet.
|
|
19
|
+
4. Add your new device type to `enum class DeviceType` in `include/client.hpp`.
|
|
20
|
+
5. Modify the device identification function in `src/client.cpp` to support your new protocol.
|
|
21
|
+
6. Modify `/src/python_bindings/bindings.cpp` to support your new protocol. You need to add support for protocol specific functions as well as support for dynamically casting the `AbstractProtocol` pointer to your Protocol pointer.
|
|
22
|
+
|
|
23
|
+
> If you want to add more OUTGOING fields or any protocol related header/subheader names add them to `include/protocol/protocol_constants.hpp`.
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
# Guide - How To Use the Library
|
|
2
|
+
|
|
3
|
+
This guide provides practical steps for using the MeT IoT Python client library. For details on the underlying packet structure, see [TCP_PROTOCOL_SPEC.md](TCP_PROTOCOL_SPEC.md).
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
The MeT IoT library is *soon to be* available on PyPI.
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
pip install MeTIOT
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
> [!NOTE]
|
|
14
|
+
> This library is not pre-compiled.
|
|
15
|
+
> You must have installed on your system (Other version may work but are official unsupported):
|
|
16
|
+
> * GCC >= 15.2.1
|
|
17
|
+
> * CMake >= 3.10
|
|
18
|
+
|
|
19
|
+
## Device Discovery
|
|
20
|
+
|
|
21
|
+
MeT IoT devices broadcast their presence using Zeroconf (mDNS). The library includes a function to listen for and find available devices on your local network.
|
|
22
|
+
|
|
23
|
+
1. **WIP**
|
|
24
|
+
|
|
25
|
+
## Connecting to a Device
|
|
26
|
+
|
|
27
|
+
Establish a persistent TCP connection and perform the initial device identification handshake.
|
|
28
|
+
|
|
29
|
+
1. **Create Client:** Create a client with the device's IP & Port.
|
|
30
|
+
```py
|
|
31
|
+
import MeTIOT
|
|
32
|
+
|
|
33
|
+
client = MeTIOT.DeviceClient("192.168.1.100", 12345)
|
|
34
|
+
```
|
|
35
|
+
2. **Connect:** Use the `connect()` method to connect to the device.
|
|
36
|
+
```py
|
|
37
|
+
client.connect()
|
|
38
|
+
```
|
|
39
|
+
**Behind the Scenes:** After connecting to the TCP socket, the client sends a Device Identification Request and waits for the Device Identifier response. This identifies the device type and its unique ID.
|
|
40
|
+
|
|
41
|
+
3. **Device Protocol:** For sending and interpreting message you will need a protocol handler.
|
|
42
|
+
```py
|
|
43
|
+
protocol = client.get_protocol_handler()
|
|
44
|
+
```
|
|
45
|
+
**Behind the Scenes:** After the connection has happened and the device type is identified that devices unique protocol class will be assigned to the client. This protocol class comes with its own unique methods. You can find all unique device protocol methods in the [API Reference](API_REFERENCE.md).
|
|
46
|
+
|
|
47
|
+
## Receiving Data
|
|
48
|
+
|
|
49
|
+
This library uses a dedicated thread to listen for unsolicited data transfers from the device. You should register callback functions to handle incoming data updates.
|
|
50
|
+
|
|
51
|
+
> [!NOTE]
|
|
52
|
+
> **Prerequisite:** You must first follow [Connecting to a Device](#connecting-to-a-device) creating a client, connecting, **and** fetching the device protocol.
|
|
53
|
+
|
|
54
|
+
1. **Define Async Callbacks:** Create a function to process incoming data, warning messages, and fatal errors. You will likely have different data processing function for each device type you expect to handle.
|
|
55
|
+
```py
|
|
56
|
+
def my_update_handler(device, header, data):
|
|
57
|
+
print(f"Received message from {device.get_unique_id()} with header: {header}")
|
|
58
|
+
|
|
59
|
+
match header:
|
|
60
|
+
case MeTIOT.NodeHeader.General.Data:
|
|
61
|
+
# Use the protocol handler to interpret the raw bytes into a dictionary
|
|
62
|
+
deviceProtocol = device.get_protocol_handler()
|
|
63
|
+
telemetry = deviceProtocol.interpret_data(data)
|
|
64
|
+
print(f"Temperature: {telemetry['Temperature_C']} C")
|
|
65
|
+
|
|
66
|
+
case MeTIOT.NodeHeader.MalformedPacketNotification:
|
|
67
|
+
print("Device reported a communication error.")
|
|
68
|
+
# Since the library is stateless, you must track your last
|
|
69
|
+
# sent packet locally if you wish to re-send it (Recommended).
|
|
70
|
+
|
|
71
|
+
# Example of modular expansion for specific devices
|
|
72
|
+
# case MeTIOT.NodeHeader.FishTank.SpecificAlert:
|
|
73
|
+
# print("Fish tank alert!")
|
|
74
|
+
|
|
75
|
+
case _:
|
|
76
|
+
# Handle other commands defined in the API Reference
|
|
77
|
+
pass
|
|
78
|
+
|
|
79
|
+
def warning_handler(device, msg):
|
|
80
|
+
# This function is optional
|
|
81
|
+
#
|
|
82
|
+
# When this function is called the warning handling is already handled by the library. This function is just for debugging.
|
|
83
|
+
print(f"Device {device.get_unique_id()} has non-fatal warning: {msg}")
|
|
84
|
+
|
|
85
|
+
def error_handler(device, msg):
|
|
86
|
+
# This function is optional
|
|
87
|
+
#
|
|
88
|
+
# When this function is called a fatal error has occured and the listening loop has stopped. The device will no longer listen for messages.
|
|
89
|
+
print(f"Device {device.get_unique_id()} has fatal error: {msg}")
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
2. **Register the Handler/s:** Attach the handler/s to the client instance.
|
|
93
|
+
```py
|
|
94
|
+
# --- To assign all devices the same handler ---
|
|
95
|
+
client.assign_handlers(on_data=my_update_handler, on_warning=warning_handler, on_fatal=error_handler)
|
|
96
|
+
# If you do not want to specify an on_warning or on_fatal handler they can both be removed
|
|
97
|
+
# client.assign_handlers(on_data=my_update_handler)
|
|
98
|
+
|
|
99
|
+
# OR
|
|
100
|
+
# --- To assign different devices types unique handlers ---
|
|
101
|
+
#
|
|
102
|
+
# devType = client.get_device_type() # Fetch the current device type
|
|
103
|
+
#
|
|
104
|
+
# if (devType == MeTIOT.DeviceType.FISH_TANK):
|
|
105
|
+
# client.assign_handlers(on_data=fish_tank_update_handler, on_warning=warning_handler, on_fatal=error_handler)
|
|
106
|
+
# elif (devType == MeTIOT.DeviceType.UNKNOWN):
|
|
107
|
+
# print("Unknown device type. Assigning generic handler")
|
|
108
|
+
# client.assign_handlers(on_data=generic_update_handler, on_warning=warning_handler, on_fatal=error_handler)
|
|
109
|
+
```
|
|
110
|
+
**Behind the Scenes:** The client initiates a background listener thread to monitor the socket. When a message is detected, the library automatically handles the decoding and verification (CRC/COBS). It segregated the payload into its `header` and `data` components and dispatches them directly to your handler.
|
|
111
|
+
|
|
112
|
+
## Sending Commands
|
|
113
|
+
|
|
114
|
+
To send a command (like changing a setting), use the client objects protocol handler for high-level command methods.
|
|
115
|
+
|
|
116
|
+
> [!NOTE]
|
|
117
|
+
> **Prerequisite:** You must first follow [Connecting to a Device](#connecting-to-a-device) creating a client, connecting, **and** fetching the device protocol.
|
|
118
|
+
|
|
119
|
+
1. **Create Packet:** Use the device-specific methods on the `protocol` object to generate the complete, ready-to-send packet buffer.
|
|
120
|
+
```py
|
|
121
|
+
# Example for sending a calibration command to a Fish Tank device
|
|
122
|
+
# The protocol method generates the Data Payload + Header + CRC + COBS.
|
|
123
|
+
packet = protocol.create_fish_tank_calibration()
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
2. **Send Packet:** Supply that packet buffer to the client's send function.
|
|
127
|
+
```py
|
|
128
|
+
client.send_packet(packet)
|
|
129
|
+
print("Calibration request packet sent.")
|
|
130
|
+
```
|
|
131
|
+
**Behind the Scenes:** The protocol handler wraps your command with mandatory overhead (CRC and COBS encoding), ensuring the device can validate the integrity of the message upon receipt.
|