Repository navigation
DeviceManagerSettings
{
"Buses": [
BusConfig#1,
BusConfig#2
],
"Devices": [
DeviceConfig#1,
DeviceConfig#2
],
"typeTable": {
"maxExtendedRecords": 32,
"maxExtendedBytes": 20480
}
}Notes:
- DeviceManager automatically scans the I2C bus to detect devices. For details on the scanning process, priority lists, and multiplexer handling, see I2C Device Scanning.
- DeviceManager automatically publishes device data through the
devjsonanddevbintopics. For details on the published message formats and how to subscribe to device data, see Device Data Publishing.
Limits for device type records added at runtime (extended records - e.g. the records of static devices). Base records are compiled into the firmware and stored in flash, so they need no limit. Each extended record is one allocation, in PSRAM when the board has it (a typical record is about 540 bytes).
| Setting | Description | Type | Default | Example |
|---|---|---|---|---|
maxExtendedRecords |
Most extended records | int | 256 with PSRAM, 32 without | 64 |
maxExtendedBytes |
Most bytes used by extended records | int | 262144 with PSRAM, 20480 without | 40000 |
runtimeDecoders |
When a record with no compiled decoder gets its runtime decoder: onIdentify (when a device of the type is first identified - checked when the record is added), atLoad (when the record is added) or off (never: only clients decode its data) |
string | onIdentify |
"off" |
maxDecoderBytes |
Most bytes runtime decoders may use; -1 for no limit (beyond RAFT_RUNTIME_DECODE_MAX_DECODERS decoders) |
int | no limit with PSRAM, 8192 without (about 8 typical decoders) | 4096 |
A runtime decoder takes about 1 KB (internal RAM without PSRAM). With onIdentify only the types of devices actually present have one, so a board with a large type file and a few devices pays for a few. A decoder that can't be made when it's needed (maxDecoderBytes used up, or no decoder slot free) is logged, and devman/typeinfo reports runtimeFailed with the reason: the device is still identified and polled, and clients still decode its data.
A record that would exceed either limit is not added: a static device whose record isn't added has no device type, and an error is logged. A static device whose record has the same key (type) as one already added but different content (for example a different data size) is also not added - give it a distinct type.
Settings for device types that are choices for the board or product rather than properties of the device: the poll bus speed and the multiplexer slots it applies to, the poll interval, the samples kept, the sample rate and the scan priority. The device type record stays the same for every board.
"typeSettings": {
"LSM6DS3": { "busHz": 400000, "busHzSlots": "1,2,3,4,7" },
"VL6180": { "intervalUs": 50000, "scanPriority": "low" }
}| Setting | Meaning |
|---|---|
intervalUs |
Poll interval in microseconds (the record's pollInfo.i is the default) |
numSamples |
Poll results kept (the record's pollInfo.s is the default) |
busHz |
I2C bus speed for the device's polls (0 for the bus default) |
busHzSlots |
The multiplexer slots busHz applies to, as "1,2,3" or [1, 2, 3] (empty for all) |
sampleRateHz |
Sample rate, through the record's _conf.rate action (see Device Type Record Format) |
scanPriority |
high, medium, low or none, in place of the record's scanPriority (the scanner's priority lists). low and none both put the address in the last list |
- The first five are the settings
devman/devconfigtakes. They are applied when a device of the type is identified (and again when it is re-identified or re-initialised). A device's own settings - saved or set withdevconfigwhile running - override them. - Each level overrides the one before: the record's defaults;
typeSettings; the device's saved settings;devconfigwhile running. - Settings apply just after identification, so the first polls may run with the record's defaults. Initialisation runs at the bus's default speed.
- Unknown setting names and invalid values are logged at startup and ignored. A key that isn't a device type in the build is logged at the information level. Names starting with
_(e.g."_notes") are ignored. - The poll bus speed is set only here (or with
devconfig). Records no longer takepollInfo.busHzorbusHzSlots, and the build warns if one does.
Sets whether device type records are used for identification, by device type key. Only identification is affected: typeinfo, decoding and subscriptions are the same whatever the policy.
| Policy | Meaning |
|---|---|
enabled |
Used for identification (the default) |
disabled |
Not used: the next record that can identify a device at that address gets the chance, then any identification hook |
disabledClaim |
Not used, but the address still counts as claimed: it stays reserved (re-addressable devices keep off it) and identification hooks aren't run there |
"typePolicy": { "VCNL4040": "disabled", "AS5600": "disabledClaim" }A protected type (see expectType) can't be disabled. A policy set here applies from startup. It can also be changed at runtime with devman/typepolicy (not saved), which identifies the devices it affects again. A compiled catalogue can also set a record's initial policy with "disable": true or "disable": "claim" - see Device Type Record Format - and DeviceTypeSources.json can set it for the build (builtin.policy). Use the build selection for "this product never has it", and typePolicy for a board that can be reconfigured.
A file of device type records that adds types the firmware doesn't have, overrides compiled ones and disables ones that must not be identified - without rebuilding the firmware. It is loaded at startup, before any device is identified: buses scan for devices meanwhile, and identify them as soon as the file has been loaded. To apply a changed file, upload it under another name, check it with devman/typefile/check?file=... and apply it with devman/typefile/apply?file=..., which makes it the device type file only if nothing in it is rejected and restarts the device. (Uploading it as the device type file and calling devman/typefile/apply also works, without the check.) A type file can be built from a project's DeviceTypeSources.json. A change to device type records is always applied by a restart: until then devman/typefile reports restartRequired, so a client making several changes restarts once. Loading takes roughly 10-15 ms per ordinary record and 60-110 ms per record with custom decode code on an ESP32-S3 (a 44-record file loaded in about 620 ms on an Axiom) - well within typeFileTimeoutMs for a typical file.
| Setting | Description | Type | Default | Example |
|---|---|---|---|---|
typeFile |
Path of the file; empty for none | string |
DeviceLibrary/devLibFile if set, otherwise /local/devlib.json
|
"/local/devtypes.json" |
typeFileRequired |
A missing file is an error (logged, and reported as state missing). Either way the compiled records are used |
bool | false |
true |
typeFileTimeoutMs |
If the file hasn't been loaded after this long, devices are identified without it (logged) | int | 10000 |
5000 |
typeFileLimits |
Limits for the file and its records: maxFileBytes (the file is read into one buffer, in PSRAM where there is any), maxReadBytes (one command), maxSamples (pollInfo.s), maxRecordRingBytes (poll result size with timestamp x samples) |
object |
262144 with PSRAM, 65536 without (RaftCore 1.62.0 and earlier: 65536); 1024, 256, 65536
|
{"maxSamples": 64} |
The file has the shape of DeviceTypeRecords.json, so a compiled record can be copied into it unchanged (Device Type Record Format):
{
"_notes": "other top-level keys, and _notes in a record, are ignored",
"devTypes": {
"MCP9808": { "addresses": "0x18-0x1f", "detectionValues": "...", "pollInfo": {...}, "devInfoJson": {...} },
"MyNewSensor": { "addresses": "0x4a", "detectionValues": "...", "pollInfo": {...}, "devInfoJson": {...} },
"LSM6DS3": { "disable": true }
}
}-
A new key adds a record (as an extended record, within the
typeTablelimits). - The key of a compiled record overrides it: the file's record replaces the compiled one, keeping its device type index. The compiled record is not tried as well - if the file's detection doesn't match, the device isn't identified by that type.
-
"disable": true(or"claim", asdisabledClaimintypePolicy) disables a type that is present; the rest of the entry is ignored, so a type can be disabled by copying its record and adding one field. With a full record and a new key, the record is added already disabled. Disabling a key that isn't present is reported as an error. -
deviceType, if present, must equal the key. A protected type (seeexpectType) can't be overridden or disabled. -
devTypes: {}is a valid file with no custom types.
Each record is checked before it is added - its addresses (0xHH or 0xHH-0xHH), identification fields, command strings (the grammar the firmware uses), the limits above, and that devInfoJson.resp.b equals the size the poll reads produce. A record that fails is rejected on its own; the rest of the file is applied, and the first error is reported by devman/typefile. A record with neither addresses nor hwTypeId is added with a warning, as it can't be identified. A record whose hwTypeId is already used by a record with another key is rejected, as is a record with deviceTypeId (the field's old name, from RaftCore 1.60.0). A record with pollInfo.ext (data supplied by firmware code rather than by polling) is added with a warning unless the firmware has code that supplies that type's data (registered with deviceTypeRecords.registerExtDataSource()).
Device names, roles, devconfig settings and stopped polling can be saved (save=1 on devman/setname, setrole, devconfig and devenable) and are applied again after a restart. They are kept in one file, keyed by device ID:
| Setting | Description | Type | Default | Example |
|---|---|---|---|---|
deviceSettingsFile |
Path of the file; empty to save nothing | string | /local/devsettings.json |
"/local/mydevs.json" |
{
"devices": {
"1_68": { "name": "Arm IMU", "role": "system", "type": "MPU6050", "devconfig": { "intervalUs": "100000" }, "poll": false }
}
}-
nameandroleare applied at startup (a name saved here takes the place of one in the SysType configuration). -
devconfigsettings are for the type intype: they are applied when the device is identified as that type, and not if it is identified as another. -
"poll": falsestops polling the device when it is identified (seedevman/devenable).
A device ID names a bus and an address (with the multiplexer slot), so the settings belong to whatever device is at that place. Static device IDs are 0_<position in the Devices list>, so reordering that list moves their settings to other devices.
Array of configurations for Buses which must contain at least the settings defined below. Any other information is passed to the bus constructor as part of the JSON configuration and is specific to the type of bus being defined.
| Setting | Description | Type | Default | Example |
|---|---|---|---|---|
name |
The name of the bus. | string | N/A | "I2CA" |
type |
The type of the bus which must match a registered bus type | string | N/A | "I2C" |
An array of configurations for Devices. Each entry is either a static-device entry (identified by the presence of a class field — DeviceManager instantiates the device via the DeviceFactory) or a bus-tagging entry (no class field — used purely to assign a friendly name and/or role to a bus-discovered device identified by its bus+addr).
A class field is required. Any other information is passed to the device constructor as part of the JSON configuration and is specific to the type of device being defined.
| Setting | Description | Type | Default | Example |
|---|---|---|---|---|
class |
The class name of the device which must match a registered device class. | string | N/A | "Buzzer" |
name |
Optional friendly name for the device. Recorded in DeviceManager's name map and returned by /devman/typeinfo and /devman/listdevs. |
string (optional) | — | "Buzzer1" |
role |
Optional role tag. The default role is normal; set to system to mark the device as system infrastructure (e.g. fuel gauge, RTC) so that consumers can distinguish it from standard measurement devices. |
string (optional) | "normal" |
"system" |
enable |
true (or non-zero) if the device is to be created. |
bool (optional) | true |
false |
Used to attach a friendly name and/or role to a device that is dynamically detected on a bus (i.e. not instantiated from the Devices list). No factory instantiation occurs — the entry exists purely to associate metadata with the bus address.
| Setting | Description | Type | Default | Example |
|---|---|---|---|---|
bus |
Bus name (e.g. "I2CA") on which the device lives. |
string | N/A | "I2CA" |
addr |
Device address on the bus (hex, with or without 0x). |
string | N/A | "0x36" |
name |
Friendly name to assign to the bus device. | string (optional) | — | "FuelGauge" |
role |
Role tag for the bus device (e.g. "system"). |
string (optional) | "normal" |
"system" |
expectType |
With role: "system": the device type key this device must be. That type is protected - it can't be disabled, overridden or replaced (by typePolicy, a type file or code). A device at this address identified as a different type is logged as an error, and code that uses the device can check the expected type (DeviceManager::getDeviceExpectedType()) so it doesn't misread its data. |
string (optional) | — | "MAX17048" |
enable |
Set to false to skip this entry. |
bool (optional) | true |
false |
"Devices": [
{ "class": "Buzzer", "name": "Buzzer1" },
{ "class": "MotorControl", "name": "MotorControl", "role": "system" },
{ "bus": "I2CA", "addr": "0x36", "name": "FuelGauge", "role": "system", "expectType": "MAX17048" },
{ "bus": "I2CA", "addr": "0x6a", "name": "IMU1" }
]The
roleandnamemappings configured here can also be changed at runtime through the/devman/setnameand/devman/setroleREST endpoints (in-memory only — runtime changes are not persisted).
Getting Started
- Quick Start
- Architecture at a Glance
- Writing Your First SysMod
- Adding a Comms Channel
- Adding an I2C Device Type
Scaffolding & Building
- Raft CLI
- Web Apps (Device Types, Flasher)
- SysTypes
- Top-Level SysType
- Build Process
- WebUI Build Pipeline
- File System
- Partitions & Flash
- Local Dev Libraries
- Library Developer Guide
Architecture
Built-in SysMods
- NetworkManager
- WiFi Troubleshooting
- BLEManager
- WebServer
- MQTTManager
- SerialConsole
- CommandSerial
- CommandSocket
- CommandFile
- FileManager
- LogManager
- ESPOTAUpdate
- StatePublisher
- Remote Logging
- Data Source Registration
Comms & Protocols
- Stack Overview
- Comms Channels
- ProtocolExchange
- RICREST Protocol
- Real-Time Streams
- Adding REST Endpoints
- Built-in REST Endpoints
- File Download (OKTO)
- OTA Update Flow
Devices & Buses
- DeviceManager
- Device Manager REST API
- Device Factory & Classes
- Device Type Records
- Adding an I2C Device Type
- Device Data Publishing
- Data Logger
- I2C Bus
- I2C Device Scanning
- I2C ID & Polling
- MotorControl Overview
- MotorControl Config
- MotorControl Commands
- Camera
ROS 2
Helpers
Reference