Table of Contents

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

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 }
  }
}

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:

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

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