MeTIOT 0.1.0__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 (39) hide show
  1. metiot-0.1.0/.gitignore +26 -0
  2. metiot-0.1.0/CMakeLists.txt +18 -0
  3. metiot-0.1.0/LICENSE +21 -0
  4. metiot-0.1.0/PKG-INFO +53 -0
  5. metiot-0.1.0/README.md +45 -0
  6. metiot-0.1.0/docs/API_REFERENCE.md +138 -0
  7. metiot-0.1.0/docs/DEVICE_PROTOCOL_DEV_GUIDE.md +23 -0
  8. metiot-0.1.0/docs/PYTHON_LIB_GUIDE.md +125 -0
  9. metiot-0.1.0/docs/TCP_PROTOCOL_SPEC.md +182 -0
  10. metiot-0.1.0/docs/images/DeviceData.jpg +0 -0
  11. metiot-0.1.0/docs/images/DeviceIdentifierResponse.jpg +0 -0
  12. metiot-0.1.0/docs/images/FishTankSensorAttributeResponse.jpg +0 -0
  13. metiot-0.1.0/docs/images/Packet.jpg +0 -0
  14. metiot-0.1.0/examples/.gitkeep +0 -0
  15. metiot-0.1.0/pyproject.toml +16 -0
  16. metiot-0.1.0/src/MeTIOTCommunication/CMakeLists.txt +25 -0
  17. metiot-0.1.0/src/MeTIOTCommunication/include/client.hpp +94 -0
  18. metiot-0.1.0/src/MeTIOTCommunication/include/core/exceptions.hpp +30 -0
  19. metiot-0.1.0/src/MeTIOTCommunication/include/core/socket_core.hpp +38 -0
  20. metiot-0.1.0/src/MeTIOTCommunication/include/interfaces/event_handler.hpp +32 -0
  21. metiot-0.1.0/src/MeTIOTCommunication/include/protocol/abstract_protocol.hpp +47 -0
  22. metiot-0.1.0/src/MeTIOTCommunication/include/protocol/device_agnostic_protocol.hpp +32 -0
  23. metiot-0.1.0/src/MeTIOTCommunication/include/protocol/fish_tank_protocol.hpp +19 -0
  24. metiot-0.1.0/src/MeTIOTCommunication/include/protocol/protocol_constants.hpp +42 -0
  25. metiot-0.1.0/src/MeTIOTCommunication/include/utils/byte_conversion.hpp +29 -0
  26. metiot-0.1.0/src/MeTIOTCommunication/include/utils/cobs.hpp +26 -0
  27. metiot-0.1.0/src/MeTIOTCommunication/include/utils/crc.hpp +29 -0
  28. metiot-0.1.0/src/MeTIOTCommunication/src/client.cpp +163 -0
  29. metiot-0.1.0/src/MeTIOTCommunication/src/core/socket_core.cpp +51 -0
  30. metiot-0.1.0/src/MeTIOTCommunication/src/protocol/abstract_protocol.cpp +64 -0
  31. metiot-0.1.0/src/MeTIOTCommunication/src/protocol/device_agnostic_protocol.cpp +22 -0
  32. metiot-0.1.0/src/MeTIOTCommunication/src/protocol/fish_tank_protocol.cpp +47 -0
  33. metiot-0.1.0/src/MeTIOTCommunication/src/utils/byte_conversion.cpp +88 -0
  34. metiot-0.1.0/src/MeTIOTCommunication/src/utils/cobs.cpp +82 -0
  35. metiot-0.1.0/src/MeTIOTCommunication/src/utils/crc.cpp +17 -0
  36. metiot-0.1.0/src/python_bindings/CMakeLists.txt +18 -0
  37. metiot-0.1.0/src/python_bindings/PythonEventHandler.hpp +50 -0
  38. metiot-0.1.0/src/python_bindings/bindings.cpp +140 -0
  39. metiot-0.1.0/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.0/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.0/PKG-INFO ADDED
@@ -0,0 +1,53 @@
1
+ Metadata-Version: 2.2
2
+ Name: MeTIOT
3
+ Version: 0.1.0
4
+ Summary: Communication handling for all MeT IOT devices
5
+ Author-Email: Cody Jackson <cjackson@micr.com.au>
6
+ Requires-Python: >=3.8
7
+ Description-Content-Type: text/markdown
8
+
9
+ # MeT IOT Communication
10
+
11
+ ## Protocol Information
12
+
13
+ Communication between MeT IOT devices and this library are conducted over TCP sockets. To see more in-depth details about this protocol including encryption standard see [Protocol Docs](docs/Protocol.md)
14
+
15
+ ## How To Use
16
+
17
+ For all information on **how** to use go to [HowToUse Docs](docs/HowToUse.md). Also see examples of use in the [Examples folder](examples/)
18
+
19
+ ## How to Compile
20
+
21
+ Linux based systems:
22
+
23
+ 1. Create and navigate into build directory
24
+ ```bash
25
+ mkdir build
26
+ cd build
27
+ ```
28
+ 2. Compile library using CMake
29
+ ```bash
30
+ cmake ..
31
+ cmake --build . --config Release
32
+ ```
33
+ 3. Export path to python
34
+ ```bash
35
+ export PYTHONPATH=./src/python_bindings:$PYTHONPATH
36
+ ```
37
+ 4. Now you can use the library. If you first want to test it you can try
38
+ ```bash
39
+ python3
40
+ ```
41
+ ```py
42
+ import MeTIOT
43
+ client = MeTIOT.DeviceClient("0.0.0.0", 12345)
44
+ type(client)
45
+ client.connect()
46
+ ```
47
+
48
+ ## How to Add More Features
49
+
50
+ **WIP** docs
51
+
52
+
53
+
metiot-0.1.0/README.md ADDED
@@ -0,0 +1,45 @@
1
+ # MeT IOT Communication
2
+
3
+ ## Protocol Information
4
+
5
+ Communication between MeT IOT devices and this library are conducted over TCP sockets. To see more in-depth details about this protocol including encryption standard see [Protocol Docs](docs/Protocol.md)
6
+
7
+ ## How To Use
8
+
9
+ For all information on **how** to use go to [HowToUse Docs](docs/HowToUse.md). Also see examples of use in the [Examples folder](examples/)
10
+
11
+ ## How to Compile
12
+
13
+ Linux based systems:
14
+
15
+ 1. Create and navigate into build directory
16
+ ```bash
17
+ mkdir build
18
+ cd build
19
+ ```
20
+ 2. Compile library using CMake
21
+ ```bash
22
+ cmake ..
23
+ cmake --build . --config Release
24
+ ```
25
+ 3. Export path to python
26
+ ```bash
27
+ export PYTHONPATH=./src/python_bindings:$PYTHONPATH
28
+ ```
29
+ 4. Now you can use the library. If you first want to test it you can try
30
+ ```bash
31
+ python3
32
+ ```
33
+ ```py
34
+ import MeTIOT
35
+ client = MeTIOT.DeviceClient("0.0.0.0", 12345)
36
+ type(client)
37
+ client.connect()
38
+ ```
39
+
40
+ ## How to Add More Features
41
+
42
+ **WIP** docs
43
+
44
+
45
+
@@ -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,125 @@
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
+ ```bash
10
+ pip install x
11
+ ```
12
+
13
+ ## Device Discovery
14
+
15
+ 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.
16
+
17
+ 1. **WIP**
18
+
19
+ ## Connecting to a Device
20
+
21
+ Establish a persistent TCP connection and perform the initial device identification handshake.
22
+
23
+ 1. **Create Client:** Create a client with the device's IP & Port.
24
+ ```py
25
+ import MeTIOT
26
+
27
+ client = MeTIOT.DeviceClient("192.168.1.100", 12345)
28
+ ```
29
+ 2. **Connect:** Use the `connect()` method to connect to the device.
30
+ ```py
31
+ client.connect()
32
+ ```
33
+ **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.
34
+
35
+ 3. **Device Protocol:** For sending and interpreting message you will need a protocol handler.
36
+ ```py
37
+ protocol = client.get_protocol_handler()
38
+ ```
39
+ **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).
40
+
41
+ ## Receiving Data
42
+
43
+ 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.
44
+
45
+ > [!NOTE]
46
+ > **Prerequisite:** You must first follow [Connecting to a Device](#connecting-to-a-device) creating a client, connecting, **and** fetching the device protocol.
47
+
48
+ 1. **Define Async Callbacks:** Create function to process incoming data object, warning messages, and fatal errors. You will likely have different data processing function for each device type you expect to handle.
49
+ ```py
50
+ def my_update_handler(device, header, data):
51
+ print(f"Received message from {device.get_unique_id()} with header: {header}")
52
+
53
+ match header:
54
+ case MeTIOT.Incoming.General.Data:
55
+ # Use the protocol handler to interpret the raw bytes into a dictionary
56
+ deviceProtocol = device.get_protocol_handler()
57
+ telemetry = deviceProtocol.interpret_data(data)
58
+ print(f"Temperature: {telemetry['Temperature_C']} C")
59
+
60
+ case MeTIOT.Incoming.MalformedPacketNotification:
61
+ print("Device reported a communication error.")
62
+ # Since the library is stateless, you must track your last
63
+ # sent packet locally if you wish to re-send it (Recommended).
64
+
65
+ # Example of modular expansion for specific devices
66
+ # case MeTIOT.Incoming.FishTank.SpecificAlert:
67
+ # print("Fish tank alert!")
68
+
69
+ case _:
70
+ # Handle other commands defined in the API Reference
71
+ pass
72
+
73
+ def warning_handler(device, msg):
74
+ # This function is optional
75
+ #
76
+ # When this function is called the warning handling is already handled by the library. This function is just for debugging.
77
+ print(f"Device {device.get_unique_id()} has non-fatal warning: {msg}")
78
+
79
+ def error_handler(device, msg):
80
+ # This function is optional
81
+ #
82
+ # When this function is called a fatal error has occured and the listening loop has stopped. The device will no longer listen for messages.
83
+ print(f"Device {device.get_unique_id()} has fatal error: {msg}")
84
+ ```
85
+
86
+ 2. **Register the Handler/s:** Attach the handler/s to the client instance.
87
+ ```py
88
+ # --- To assign all devices the same handler ---
89
+ client.assign_handlers(on_data=my_update_handler, on_warning=warning_handler, on_fatal=error_handler)
90
+ # If you do not want to specify an on_warning or on_fatal handler they can both be removed
91
+ # client.assign_handlers(on_data=my_update_handler)
92
+
93
+ # OR
94
+ # --- To assign different devices types unique handlers ---
95
+ #
96
+ # devType = client.get_device_type() # Fetch the current device type
97
+ #
98
+ # if (devType == MeTIOT.DeviceType.FISH_TANK):
99
+ # client.assign_handlers(on_data=fish_tank_update_handler, on_warning=warning_handler, on_fatal=error_handler)
100
+ # elif (devType == MeTIOT.DeviceType.UNKNOWN):
101
+ # print("Unknown device type. Assigning generic handler")
102
+ # client.assign_handlers(on_data=generic_update_handler, on_warning=warning_handler, on_fatal=error_handler)
103
+ ```
104
+ **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.
105
+
106
+ ## Sending Commands
107
+
108
+ To send a command (like changing a setting), use the client objects protocol handler for high-level command methods.
109
+
110
+ > [!NOTE]
111
+ > **Prerequisite:** You must first follow [Connecting to a Device](#connecting-to-a-device) creating a client, connecting, **and** fetching the device protocol.
112
+
113
+ 1. **Create Packet:** Use the device-specific methods on the `protocol` object to generate the complete, ready-to-send packet buffer.
114
+ ```py
115
+ # Example for sending a calibration command to a Fish Tank device
116
+ # The protocol method generates the Data Payload + Header + CRC + COBS.
117
+ packet = protocol.create_fish_tank_calibration()
118
+ ```
119
+
120
+ 2. **Send Packet:** Supply that packet buffer to the client's send function.
121
+ ```py
122
+ client.send_packet(packet)
123
+ print("Calibration request packet sent.")
124
+ ```
125
+ **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.
@@ -0,0 +1,182 @@
1
+ # TCP Communication Protocol Specification
2
+
3
+ > [!NOTE]
4
+ > This documentation details the technical specifications of the protocol used for all TCP communication. **It is not required** to be read or understood for general use of the associated Python library. For usage instructions, please refer to the [How To Use](HowToUse.md) documentation.
5
+
6
+ ## Protocol Scope and Usage
7
+
8
+ This protocol governs all TCP communication between MeT IoT devices and external clients (e.g., standalone library, Home Assistant integration).
9
+
10
+ ## Connection Initilization Sequence
11
+
12
+ This sequence desribes the steps a MeT IoT device and the client library take to establish and identify a connection.
13
+
14
+ ### Initialization Sequence
15
+
16
+ 1. **Discovery:** The device broadcasts a Zeroconf (mDNS) packet for initial discovery.
17
+ 2. **Connection:** The client library connects to the device's TCP socket.
18
+ 3. **Request:** The client library sends a **Device Identification Request** command.
19
+ 4. **Response:** The device responds with a **Device Identifier** response packet.
20
+ 5. **Operation:** Regular data exchange begins.
21
+
22
+ ### Device Identifier Response Packet
23
+
24
+ This specific packet is sent by the IoT device to the library during connection initialization.
25
+
26
+ ![Device Identifier Response](images/DeviceIdentifierResponse.jpg)
27
+
28
+ The Data Payload (within a Data Header `0xFE` packet) contains the following information:
29
+
30
+ * **8-Bit Device ID:** Specifies the type of device (e.g., Fish Tank).
31
+ * **64-Bit Unique Device ID:** A unique identifier for the specific device instance.
32
+
33
+ ## General Packet Format
34
+
35
+ All data over the TCP connection adheres to a common structure.
36
+
37
+ ![Packet Diagram](images/Packet.jpg)
38
+
39
+ ### Packet Structure Breakdown
40
+
41
+ | Field | Bytes | Description |
42
+ |-|-|-|
43
+ | COBS Header | 1 | Marks the start of the packet and contains information for COBS decoding. |
44
+ | CRC | 2 | 16-bit Cyclic Redundancy Check for error detection across the entire data payload. |
45
+ | Data Header | 1 | Identifies the overall purpose or type of the packet (e.g., data transfer, identification). |
46
+ | Data Payload | 0-n | The main data content. Its exact structure depends on the Data Header. |
47
+ | COBS Trailer | 1 | Marks the end of the packet, always the value `0x00`. |
48
+
49
+ ### Purpose of Protocol Components
50
+
51
+ * **Consistent Overhead Byte Stuffing (COBS):** Ensures reliable packet delimitation by guaranteeing the packet trailer byte (`0x00`) never appears in the body of the packet. The header contains essential information for the receiver on how to decode the data.
52
+ * **Cyclic Redundancy Check (CRC):** A 16-bit code used for robust error detection. If the received CRC does not match the CRC recalculated from the Data Header and Payload, the packet is discarded as corrupted. The CRC algorithm is based on: G.D. Nguyen, “Fast CRCs,” IEEE Transactions on Computers, vol. 58, no. 10, pp. 1321-1331, Oct. 2009.
53
+
54
+ ## Data Header Commands and Flow
55
+
56
+ > [!NOTE]
57
+ > All relevant **Bytes** columns in tables **do not include protocol overhead** and only include the length of the header + data. The protocol overhead specifically refers to COBS trailer, COBS deliminator, and 16-Bit CRC which make up for a total of **4 bytes not included in those values**.
58
+
59
+ The Data Header (1 byte) is the first piece of information after the CRC and determines the primary function of the packet.
60
+
61
+ ### Standard Library-to-Device Commands
62
+
63
+ These are requests or notifications sent from the client library to the MeT IoT device.
64
+
65
+ | Purpose | Data Header | Data Payload | Bytes |
66
+ |-|-|-|-|
67
+ | Malformed Packet Notification | `0xFF` | (None) | 1 |
68
+ | Device Identification Request | `0xFE` | (None) | 1 |
69
+
70
+ ### Standard Device-to-Library Commands
71
+
72
+ These are responses or unsolicited notifications sent from the MeT IoT device to the client library.
73
+
74
+ | Purpose | Data Header | Data Payload | Bytes |
75
+ |-|-|-|-|
76
+ | Malformed Packet Notification | `0xFF` | (None) | 1 |
77
+ | Device Identifier | `0xFE` | [1 byte Device ID + 8 byte Unique Device ID](#device-identifier-response-packet). | 10 |
78
+ | Data Transfer | `0xFD` | [Variable-length structure.](#data-field-format) | n |
79
+
80
+ ### Device Identification Codes
81
+
82
+ This 1-byte code is carried in the **Device Identifier** packet (`0xFE`).
83
+
84
+ | Code (1 Byte) | Device Type |
85
+ |-|-|
86
+ | `0xFF` | Fish Tank |
87
+ | ... | *(Future devices)* |
88
+
89
+ ## Data Payload Structure (Header 0xFD)
90
+
91
+ When the **Data Header** is `0xFD` (Data Transfer), the **Data Payload** is structured as a series of repeating **Sub-Header** and **Data** fields.
92
+
93
+ ### Data Field Format
94
+
95
+ ![Device Data Field Diagram](images/DeviceData.jpg)
96
+
97
+ The Data Payload consists of one or more data points, each preceded by its own Sub-Header. This pattern repeats until the payload ends: `Sub-Header`, `Data`, `Sub-Header`, `Data`, ...
98
+
99
+ | Field | Purpose |
100
+ |-|-|
101
+ | Data Sub-Header | Identifies the specific data point (e.g., "Current Temp"). |
102
+ | Data | The actual data value, interpreted based on the Sub-Header. |
103
+
104
+ ### Supported Data Types
105
+
106
+ > [!IMPORTANT]
107
+ > The following standard C/C++ data types are supported for transmission within the **Data** field:
108
+ >
109
+ > * `int8_t`
110
+ > * `int16_t`
111
+ > * `int32_t`
112
+ > * `int64_t`
113
+ >
114
+ > *All unsigned variants of the above data types are allowed*
115
+ >
116
+ > The following data types *can* be used but research must first be conducted to ensure each devices architecture support the same byte length.
117
+ >
118
+ > * `float`
119
+ > * `double`
120
+
121
+ ## Device-Specific Protocol: Fish Tank
122
+
123
+ This section details the custom commands and data formats specific to the Fish Tank device (`Device ID: 0xFF`). The Fish Tank protocol still inherits all commands defined in [Data Header Commands and Flow](#data-header-commands-and-flow).
124
+
125
+ ### Fish Tank: Library-to-Device Commands
126
+
127
+ | Purpose | Data Header | Data Payload | Bytes |
128
+ |-|-|-|-|
129
+ | Sensor Attribute Request | `0xFC` | None | 1 |
130
+ | Calibration Values | `0xFB` | *To be decided* | |
131
+
132
+ ### Fish Tank: Device-to-Library Commands
133
+
134
+ | Purpose | Data Header | Data Payload | Bytes |
135
+ |-|-|-|-|
136
+ | Sensor Attribute Response | `0xFC` | *To be decided* | |
137
+ | Calibration Finished | `0xFB` | 1-Byte Sensor Address | 2 |
138
+
139
+ ### Fish Tank: Data Sub-Header
140
+
141
+ > [!NOTE]
142
+ > Values marked with *(decimal value)* are multiplied by 100 before transmission then divided by 100 when being interpreted. This only gives an accuracy of up to 2 decimal places.
143
+
144
+ | Sub-Header | Data Field | Data Type |
145
+ |-|-|-|
146
+ | `0xFF` | Temperature *(decimal value)* | `int16_t` |
147
+ | `0xFE` | Humidity *(decimal value)* | `uint16_t` |
148
+ | `0xFD` | pH *(decimal value)* | `uint16_t` |
149
+ | `0xFC` | Oxidation-Reduction Potential | `int16_t` |
150
+ | `0xFB` | Dissolved Oxygen | `int16_t` |
151
+ | `0xFA` | Conductivity | `int16_t` |
152
+ | `0x00` | Data End | (None/Blank) |
153
+
154
+ ### Fish Tank: Sensor Attribute Aquisition
155
+
156
+ During the devices startup it allocates a unique I2C address and stores the device type for all devices on the I2C bus. For later use (like calibration) we will need to store this information so we know what types of devices are currently associated with the device.
157
+
158
+ #### Sensor Attribute Response Command
159
+
160
+ I2C Address:Device Type pair can repeat as many times as required.
161
+
162
+ ![Fish Tank Sensor Attribute Response](images/FishTankSensorAttributeResponse.jpg)
163
+
164
+ #### Sensor Device Types
165
+
166
+ > [!NOTE]
167
+ > A Fish Tank device can have multiple of the same type of device so its important to sort by their I2C address not.
168
+
169
+ | Code | Device Type |
170
+ |-|-|
171
+ | `0xFF` | Temeprature Sensor |
172
+ | `0xFE` | Humidity Sensor |
173
+ | `0xFD` | pH Sensor |
174
+ | `0xFC` | Oxidation-Reduction Potential Sensor |
175
+ | `0xFB` | Dissolved Oxygen Sensor |
176
+ | `0xFA` | Conductivity Sensor |
177
+
178
+ ### Fish Tank: Calibration
179
+
180
+ #### Calibration Values Command
181
+
182
+ #### Calibration Finished Command
Binary file
Binary file
File without changes
@@ -0,0 +1,16 @@
1
+ [build-system]
2
+ requires = ["scikit-build-core", "pybind11"]
3
+ build-backend = "scikit_build_core.build"
4
+
5
+ [project]
6
+ name = "MeTIOT"
7
+ version = "0.1.0"
8
+ authors = [
9
+ { name="Cody Jackson", email="cjackson@micr.com.au" }
10
+ ]
11
+ description = "Communication handling for all MeT IOT devices"
12
+ readme = "README.md"
13
+ requires-python = ">=3.8"
14
+
15
+ [tool.scikit-build]
16
+ cmake.version = ">=3.15"