Collector Development
The main goals of the collector code are as follows:
- Be flexible in supporting the addition of new types of sensors to the software.
- Provide enough configuration options to support all use cases without modifying the source code.
- Support Micropython.
Architecture
The architecture of the collector code is visualized below and contains the following modules:
- Main Control Loop - This is the entrypoint of the program and is responsible for orchestrating the modules and the endless loop.
ConfigManager- This class is responsible for parsing and validating the configuration contained withinconfig.json.UploadManager- This class is responsible for formatting the collected data and uploading it via HTTP to the configured QuestDB endpoint.- Sensor Polling:
SensorDriver- EachSensorDriverclass instance is responsible for collecting data from a single sensor.SensorManager- This class is responsible for initializing as manySensorDriverinstances as are called for in the configuration, polling them, and sending the data to the main control loop.

Main Control Loop
The main control loop has the following behavior:
- Initializes all required manager classes.
- Updates the metadata tables in the database with the currently collector and sensor configuration.
- On an endless loop:
- Collects sensor data.
- Uploads sensor data.
- If the data could not be uploaded, saves the data in-memory to re-try next loop.
- Waits a length of time determined by the
polling_intervalconfiguration parameter.
stateDiagram-v2
[*] --> Initialization
Initialization --> Metadata : Success
Metadata --> Poll: Success
Initialization --> Error : Failure
Metadata --> Error : Failure
Poll --> Upload
Upload --> Wait
Wait --> Poll : After Polling Interval
Metadata: Metadata Upload
Upload: Data Upload
Config
For documentation on what the configuration values do, see the User Guide.
See the Config Reference for documentation on the configuration-related source code.
Upload
For documentation on the structure of the database, see the Storage Database page.
See the Upload Reference for documentation on the upload-related source code.
Sensors
For documentation on which sensors are currently supported and how to configure them, see the User Guide sensors page.
For instructions on how to add support for new sensors, see the Sensor page.
See the Sensor Reference for documentation on the sensor-related source code.
Architecture & Approach
As the main goal of the sensor code design was to support adding more sensors in the future, the sensor code follows a manager-driver pattern, with the driver code fulfilling an abstract interface.
In software engineering, an interface is a piece of code that contains only specification. For example, a function may define the arguments it accepts, the type of value it returns, and have a documentation string explaining its behaviour, but the actual workings of the function are left blank. The advantage of using interfaces is that it allows seperate pieces of software to be agnostic to specific implementations of the code they depend on, by making them depend on a contract instead. This allows changing those pieces independently. If one piece of the software changes, the changes required to make the rest of the system interact with the new logic should be as limited as possible to the location of the relevant change.

In practice, this means that that the SensorManger class is not directly dependent on any specific implementation of a sensor but is instead dependent on an interface called AbstractSensorDriver. As long as the interface is properly designed, the changes to the codebase required to add new sensors to the software should be isolated to the creation of new implementations of the interface.
Abstract classes are be implemented with Python's Protocol type.
Development
TODO: information here on how to flash the software for development