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.
Files changed (43) hide show
  1. metiot-0.1.3/.gitignore +26 -0
  2. metiot-0.1.3/CMakeLists.txt +18 -0
  3. metiot-0.1.3/LICENSE +21 -0
  4. metiot-0.1.3/PKG-INFO +94 -0
  5. metiot-0.1.3/README.md +83 -0
  6. metiot-0.1.3/docs/API_REFERENCE.md +138 -0
  7. metiot-0.1.3/docs/DEVICE_PROTOCOL_DEV_GUIDE.md +23 -0
  8. metiot-0.1.3/docs/PYTHON_LIB_GUIDE.md +131 -0
  9. metiot-0.1.3/docs/TCP_PROTOCOL_SPEC.md +205 -0
  10. metiot-0.1.3/docs/images/DeviceData.jpg +0 -0
  11. metiot-0.1.3/docs/images/DeviceIdentifierResponse.jpg +0 -0
  12. metiot-0.1.3/docs/images/FishTankSensorAttributeResponse.jpg +0 -0
  13. metiot-0.1.3/docs/images/Packet.jpg +0 -0
  14. metiot-0.1.3/examples/.gitkeep +0 -0
  15. metiot-0.1.3/examples/simple_client/README.md +33 -0
  16. metiot-0.1.3/examples/simple_client/main.py +59 -0
  17. metiot-0.1.3/pyproject.toml +21 -0
  18. metiot-0.1.3/src/MeTIOTCommunication/CMakeLists.txt +25 -0
  19. metiot-0.1.3/src/MeTIOTCommunication/include/client.hpp +93 -0
  20. metiot-0.1.3/src/MeTIOTCommunication/include/core/exceptions.hpp +27 -0
  21. metiot-0.1.3/src/MeTIOTCommunication/include/core/socket_core.hpp +35 -0
  22. metiot-0.1.3/src/MeTIOTCommunication/include/interfaces/event_handler.hpp +29 -0
  23. metiot-0.1.3/src/MeTIOTCommunication/include/protocol/abstract_protocol.hpp +44 -0
  24. metiot-0.1.3/src/MeTIOTCommunication/include/protocol/device_agnostic_protocol.hpp +29 -0
  25. metiot-0.1.3/src/MeTIOTCommunication/include/protocol/filter_guardian_protocol.hpp +16 -0
  26. metiot-0.1.3/src/MeTIOTCommunication/include/protocol/fish_tank_protocol.hpp +16 -0
  27. metiot-0.1.3/src/MeTIOTCommunication/include/protocol/protocol_constants.hpp +52 -0
  28. metiot-0.1.3/src/MeTIOTCommunication/include/utils/byte_conversion.hpp +26 -0
  29. metiot-0.1.3/src/MeTIOTCommunication/include/utils/cobs.hpp +23 -0
  30. metiot-0.1.3/src/MeTIOTCommunication/include/utils/crc.hpp +26 -0
  31. metiot-0.1.3/src/MeTIOTCommunication/src/client.cpp +169 -0
  32. metiot-0.1.3/src/MeTIOTCommunication/src/core/socket_core.cpp +51 -0
  33. metiot-0.1.3/src/MeTIOTCommunication/src/protocol/abstract_protocol.cpp +64 -0
  34. metiot-0.1.3/src/MeTIOTCommunication/src/protocol/device_agnostic_protocol.cpp +22 -0
  35. metiot-0.1.3/src/MeTIOTCommunication/src/protocol/filter_guardian_protocol.cpp +60 -0
  36. metiot-0.1.3/src/MeTIOTCommunication/src/protocol/fish_tank_protocol.cpp +42 -0
  37. metiot-0.1.3/src/MeTIOTCommunication/src/utils/byte_conversion.cpp +88 -0
  38. metiot-0.1.3/src/MeTIOTCommunication/src/utils/cobs.cpp +82 -0
  39. metiot-0.1.3/src/MeTIOTCommunication/src/utils/crc.cpp +17 -0
  40. metiot-0.1.3/src/python_bindings/CMakeLists.txt +18 -0
  41. metiot-0.1.3/src/python_bindings/PythonEventHandler.hpp +50 -0
  42. metiot-0.1.3/src/python_bindings/bindings.cpp +145 -0
  43. metiot-0.1.3/tests/test_basic.py +5 -0
@@ -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.