Skip to content

Introduce the device scheme#159

Open
Luni-4 wants to merge 26 commits intomasterfrom
scheme2
Open

Introduce the device scheme#159
Luni-4 wants to merge 26 commits intomasterfrom
scheme2

Conversation

@Luni-4
Copy link
Copy Markdown
Member

@Luni-4 Luni-4 commented Apr 22, 2026

After a long time, I was finally able to implement the device scheme concept. This introduces a breaking change, so the framework version has been bumped to 0.2.

I guess it should satisfy all your requests, @lonesometraveler, feel free to review this PR and share feedback, an extra pair of eyes is always welcome for catching any inconsistencies. 😃

This PR fixes #112

What is a device scheme?

Until now, devices were classified solely by their identifier, which provides no insight into their minimum structural requirements in terms of behavior or risk. The introduction of a device scheme addresses this limitation by defining these requirements at the firmware level and removes the need to hard-code device types for specific hardware architectures. A generic Device abstraction is sufficient on its own. By loading a device scheme at creation time, Device is effectively transformed from a generic entity into a specific, well-defined one. This approach preserves flexibility while ensuring that structural and behavioral constraints are consistently enforced.

A device scheme consists of:

  • Device kind
    This can be either predefined in the tosca library or custom-defined. Predefined kinds offer stronger guarantees to the controller about discovered devices, while custom kinds give developers flexibility to define new device types without contributing to tosca.

  • Mandatory routes
    A set of routes that must be implemented for a device to be considered part of a given kind. Without these, the device cannot be regarded as correctly defined according to shared conventions.

  • Allowed hazards
    Each device is restricted to a specific set of significant hazards. Any hazard outside this set is considered invalid, as it would be inconsistent with the device’s physical characteristics.

A device scheme serves as a guide for developers when defining firmware, helping reduce implementation errors. Before a device is exposed externally, the scheme is used to validate its properties.

On the controller, the device scheme is used to evaluate incoming devices. The controller compares the scheme data against its internal policies to determine whether a device should be accepted or rejected.

The tosca crate now includes APIs to define device schemes on the firmware side, along with methods to access their internal data via references. Additionally, a comprehensive set of tests has been introduced to validate both the integrity of device scheme data and the correctness of these methods.

tosca-os changes

The introduction of device schemes in tosca removes the need for the previously hard-coded Light device, replacing it with a more flexible and generic Device. This eliminates the burden of maintaining architecture-specific device implementations while increasing overall extensibility.

Device construction is now centered around the build function, which validates developer-provided data against the selected device scheme. This process ensures that only verified and compliant devices can be instantiated and passed to the server.

Mandatory routes have been removed from both the base response kind and all specialized response kinds, simplifying the route APIs and making them more intuitive to use.

Additionally, new error cases have been introduced in the build functions to handle non-compliant devices. These validations ensure that devices are rejected if they lack a valid identifier, missing Wi-Fi and Ethernet MAC addresses, or if required mandatory routes are missing or invalid.

All tests have been updated to reflect these changes and ensure consistency across the framework.

tosca-esp32c3 changes

As with tosca-os, the hard-coded Light device has been removed in favor of the generic Device, improving flexibility and eliminating the need to maintain fixed, architecture-specific implementations.

Device construction now relies on the build function, which validates input data against the device scheme to produce a verified device ready for server integration.

New error cases have also been introduced to handle devices with missing or invalid mandatory routes, ensuring stricter validation and more predictable behavior.

tosca-controller changes

The controller now leverages device schemes to determine whether discovered devices should be accepted or rejected, based on their compliance with defined structural and behavioral requirements.

The Description structure has been renamed to Metadata to reduce ambiguity and better reflect its role as a container for device-related information.

The previous Unknown device type has been replaced with Custom. This shifts the perspective from a potentially unsafe or undefined device to one that is explicitly developer-defined, even if it does not conform to tosca framework conventions.

A new discovery mode, strict mode, has been introduced. When enabled, the controller rejects all custom devices and only allows those that conform to well-defined schemes, providing stronger safety guarantees.

All tests have been updated accordingly to ensure consistency with these changes.

Next steps

  • The build function currently propagates errors in a way that can cause the firmware to panic if they are not explicitly handled. This is problematic, as firmware should remain operational even if there are tosca-related issues. Instead of failing hard, these errors should be converted into structured notes or diagnostics that the controller can interpret to decide whether to accept or discard the device. This is tracked in issue Add a notes field to a device description to report device errors to the controller #88.

  • The controller does not yet fully leverage the capabilities of the device scheme. Additional controller modes should be introduced to better accommodate different levels of strictness and developer customization, allowing more flexible validation and acceptance policies.

Luni-4 added 23 commits April 21, 2026 11:53
`Clone` and `Copy` traits have a greater priority than the others
A hazard category should not be deserialized by default.
- Minimize ownership by preferring borrowing where possible
- Simplify min/max handling in `ParameterKind`
- Adjust some tests
Until now, a device has been classified solely by its identifier, which
does not provide any information about its minimum structural
requirements in terms of behavior or risk.
A device scheme has been designed to define these requirements.

It consists of:
- A device kind. It can be predefined in the `tosca` library or
custom. A predefined kind provides greater assurance
to the controller about discovered devices, while a custom kind
allows developers to define their own devices without contributing
to `tosca`, offering greater flexibility.
- Mandatory routes. All routes required to declare that a device
belongs to a specific kind. Without them, a device cannot be considered
correctly defined according to common conventions.
- Allowed hazards. Each device contain only a specific set of
significant hazards, while all others are prohibited as they are
inconsistent with its physical structure.

A device scheme guides developers in defining device firmware and helps
reduce errors during the process. Before a device is made externally
accessible, the scheme is used to perform validation checks.

On a controller, a device scheme is used to evaluate, based on
its information, whether to accept or reject incoming devices.

The code also introduces methods to define device schemes on the
firmware side, as well as methods to access their internal data
through references.

A series of tests have been created to validate both device scheme data
and its methods.
Since the mandatory routes for a device are contained in its scheme,
it is no longer necessary to define them for specific devices.
A parameter was missing
The implementation of the `tosca` device scheme removes the hard-coded
light device in favor of a more general device.
This increases flexibility in the framework, as there is no longer a
need to maintain or implement specific hard-coded devices.

Device construction is now centered around the `build` function, which
validates developer-provided data against the device scheme.
The result of this process is a verified device that can be passed
to the server.

Mandatory routes have been removed from the base response kind and all
specific response kinds, making the route APIs more straightforward and
intuitive.

New errors have been added for devices with missing identifiers, when
no Wi-Fi or Ethernet MAC addresses are found, or with missing or
invalid mandatory routes.

All tests have been updated accordingly to reflect these changes.
Convert error info from a static reference to a `Cow` to support
both borrowed and owned data.
Apply the new `tosca` ownership rules to server and parameters to
clearly distinguish when a type must be allocated and when it must not.
The implementation of the `tosca` device scheme removes the hard-coded
light device in favor of a more general device.
This increases flexibility in the framework, as there is no longer a
need to maintain or implement specific hard-coded devices.

Device construction is now centered around the `build` function, which
validates developer-provided data against the device scheme.
The result of this process is a verified device that can be passed
to the server.

New errors have been added for devices with missing or invalid mandatory
routes.
The controller now uses the device scheme to accept or reject
discovered devices.

The `Description` structure has been renamed to `Metadata` to
avoid confusion with device description and to more accurately represent
its role as device metadata.

The previous `Unknown` device type has been replaced with `Custom`.
This shifts the perspective from a potentially unsafe or undefined
device to one that is explicitly developer-defined, even if it does not
conform to `tosca` framework conventions.

A new discovery mode, strict mode, has been introduced.
When enabled, it discards all custom devices, allowing only those with
a well-defined scheme, providing stronger safety guarantees.

All tests have been updated accordingly to reflect these changes.
@Luni-4 Luni-4 requested a review from alexle0nte April 22, 2026 08:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

DeviceKind extensibility without forking or contributing

1 participant