Writing device profiles (Advanced JSON)

Writing device profiles (Advanced JSON)

A device profile is a short piece of JSON that tells Axiom how to find, identify, set up and read a device. This page explains the format and the Advanced JSON editor, so you can write a profile for a device that isn't in the catalogue.

Devlib Advanced Json

Start from a working profile

The easiest way to write a profile is to copy one for a similar device. Open a built-in profile from the Devices tab (Definition, then Customise this profile), or add one from the Catalogue. Then edit it in Advanced JSON.

The Advanced JSON tab

  • Profiles (left) lists every profile in your draft, with its address, origin (new, replaces built-in, …), polling interval and name. Search by name or address.
  • The editor (right) shows the selected profile as JSON. The label above it tells you whether you are editing your local draft or looking at a read-only built-in definition.
  • The Descriptor guide (below) is a quick reference to the fields and command syntax.
Button What it does
New profile Starts a new, empty profile in your draft. You'll be asked for a type name.
Edit package Opens the whole library (every profile) as one JSON document.
Save to draft Saves the editor's JSON to your draft. Unsaved edits are not written or exported.
Discard edits Throws away unsaved changes in the editor.
Remove custom Removes the selected profile from your draft.
Import JSON Loads a library or single-profile .json file from your computer. A whole library replaces your draft (you'll be asked first). A single profile is added to it.
Import from URL Loads a shared profile or library from an https:// address. The server must allow browser access (CORS).
Export draft / Export selected profile Saves your draft, or one profile, as a .json file.
Clear custom draft Empties your draft.

Below the editor, the page shows the draft's size and any Check messages. Checks are advice: they point out likely mistakes but don't stop you writing. The only verdict that counts is what Axiom reports after you install and restart: the rejected count and first error on the Install tab.

The library file

A library is one JSON object. Its devTypes object holds one entry per device type, keyed by the type's name:

{
  "devTypes": {
    "AHT20": { ... },
    "VL53L1X": { "disable": true }
  }
}
  • A key that doesn't match a built-in profile adds a new type.
  • A key that matches a built-in profile customises it: your version is tried first, with the built-in as a fallback.
  • “disable”: true disables that type. If the entry also contains a full profile, it is kept but ignored until you enable it again.

Type names can use 1–48 letters, digits, underscores and hyphens (e.g. LTR-390).

A complete example: AHT20

This is the catalogue profile for the AHT20 temperature and humidity sensor:

{
  "_notes": "Temperature and humidity sensor. Data format: Status(8bit) + Humidity(20bit) + Temperature(20bit).",
  "addresses": "0x38",
  "deviceType": "AHT20",
  "detectionValues": "",
  "initValues": "0xbe0800=",
  "pollInfo": {
    "c": "=r6&0xac3300=",
    "i": 500,
    "s": 1
  },
  "devInfoJson": {
    "name": "Temperature & Humidity Sensor",
    "desc": "",
    "manu": "Asair",
    "type": "AHT20",
    "clas": ["TEMP", "RH"],
    "resp": {
      "b": 6,
      "a": [
        { "n": "status", "t": "B", "u": "", "f": "02x", "o": "uint8", "vs": false },
        { "n": "humidity", "t": ">I", "u": "%", "r": [0, 100],
          "m": "0xfffff000", "s": 12, "d": 10485.76, "f": "3.1f", "o": "float" },
        { "n": "temperature", "at": 2, "t": ">I", "u": "°C", "r": [-40, 80],
          "m": "0x000fffff", "d": 5242.88, "a": -50, "f": "3.2f", "o": "float" }
      ]
    }
  }
}

In words:

  • Look for it at address 0x38. There is no identification check (detectionValues is empty), so anything at 0x38 is treated as an AHT20.
  • When it's found, write 0xbe 0x08 0x00 to initialise it.
  • Every 500 ms, read the 6-byte result of the previous measurement, then write 0xac 0x33 0x00 to start the next one. Keep 1 sample.
  • Decode the 6 bytes as a status byte, a 20-bit humidity value and a 20-bit temperature value.

Profile fields

Field Required Meaning
deviceType No The type name. If present, it must equal the key.
addresses Yes, for an I²C device Where to look: one address, a list or an inclusive range, e.g. “0x38”, “0x29,0x30”, “0x10-0x18”.
deviceTypeId Robotical modules only The ID that Robotical's own add-on modules report, instead of an address, e.g. “0x0084”.
detectionValues No How to recognise the device (see below). Empty means “anything at this address”.
initValues No Commands sent once when the device is found.
pollInfo No What to read and how often. Leave it out for an actuator that isn't read.
pollInfo.c The poll command.
pollInfo.i Polling interval in milliseconds (e.g. 500 = twice a second).
pollInfo.s Number of samples Axiom keeps between deliveries.
devInfoJson Yes Name, maker, classes and how to decode the data (see below).
disable No true disables this device type.

scanPriority and fields starting with _ (such as _notes) are accepted but not used. Profiles in a library are always scanned at the highest priority.

Command syntax

detectionValues, initValues and pollInfo.c use the same syntax. A command is a list of steps separated by & or ;. Each step is bytes to write=what happens next. The bytes before the = are written to the device as hex (the 0x is optional). What comes after the = depends on the field:

After = In initValues and pollInfo.c In detectionValues
rN Read N bytes
pN Pause N milliseconds Pause N milliseconds
0x… or hex Ignored The value expected back. Separate alternatives with commas.
0b… A byte count (don't use) A bit pattern to compare. x marks a bit to ignore.
nothing Write only Write only

Examples:

Command Meaning
0x01=r2 Write 0x01 (select a register), then read 2 bytes.
0xbe0800= Write the three bytes 0xbe 0x08 0x00.
0x0001=p25 Write 0x00 0x01, then wait 25 ms.
0x0f=0x69,0x6a,0x6c (detection) Write 0x0f and expect 0x69, 0x6a or 0x6c back.
0x00=0b000000xx (detection) Write 0x00 and expect six zero bits followed by two bits that are ignored.
Three common mistakes
  • Pauses need an =. Write =p20. A bare p20 is sent to the device as bytes.
  • To write data, put it before the =. In initValues, 0x10=0x60 writes only 0x10 and ignores 0x60. To write both bytes, use 0x1060.
  • An empty detectionValues claims anything at the address. Your profile is tried before the built-in ones, so it can take over a device a built-in profile would have recognised. If the datasheet has an ID or “who am I” register, check it.

You can test a detection command on a connected device before installing it. See Try a detection command in Testing and tuning devices.

Describing the data (devInfoJson)

Field Meaning
name, desc, manu Friendly name, description and maker, shown in apps.
type Type label (normally the same as the key).
clas Classes used for searching and grouping, e.g. [“TEMP”, “RH”].
resp.b The number of bytes one poll reads. Axiom sizes its buffer from this, so it must match the reads in pollInfo.c.
resp.a The list of values (attributes) to decode from those bytes.

Each attribute in resp.a describes one value:

Key Meaning Example
n Name “temperature”
t How the bytes are read, in Python struct style: B is an unsigned byte, h a signed 16-bit value, H an unsigned 16-bit value, I an unsigned 32-bit value, and so on. Put < in front for little-endian byte order, or > for big-endian. “>I”
at Byte position to start from. Otherwise each value follows the previous one. 2
m Bit mask applied to the raw value “0x000fffff”
s Shift right by this many bits (left if negative) 12
sb, ss Sign bit position, and the value to subtract when it is set 11, 4096
d Divide by this 5242.88
a Then add this -50
u Units “%”, “&deg;C”
r Expected range [min, max] [-40, 80]
f Display format, printf-style “3.2f”
o Output type “float”, “uint8”
vs false hides the value from graphs false

For the AHT20 temperature, the steps are: read 4 bytes starting at byte 2, keep the low 20 bits, divide by 5242.88, then subtract 50.

Custom decoding code

Some built-in profiles include a small decoding program for data that can't be described with the keys above. For safety, live readings in the Device Library ignore decoding code supplied in a profile. Only reviewed decoders for a few built-in devices are used. Describe your device's data with the attribute keys wherever you can.

Limits

  • The connected Axiom reports how many custom profiles it can hold and how big the library can be. The Install tab shows both, e.g. 1 of 19 profiles · 1.6 KiB of 64 KiB.
  • Addresses Axiom uses for its own hardware (including 0x25, 0x36 and 0x700x77) are reserved. The battery fuel gauge profile (MAX17048) can't be replaced or disabled.
  • A profile you add needs an address (or a Robotical deviceTypeId). A library can't create devices that are wired directly to Axiom.
Task Runner