Device Configuration
Use a protected device property to distribute configuration to a device, then run a local service that reads and applies it. A device property is a named JSON value attached to a device. Properties can hold desired configuration, reported state, or inventory such as serial numbers. A protected property is readable by the device but writable only through authorized management clients. An unprotected property also allows device writes, which makes it useful for reporting state.
This example configures a Linux sensor service from
com.example.sensor.config. It shows how to separate the configuration an
operator wants from the work needed to apply it on the device.
You need a device connected through Nexigon Agent, Nexigon CLI configured on
your workstation, and a sensor service that reads
/etc/sensor-service/config.json and supports systemctl reload. Run the
device-side setup as root on a Linux system with Bash, systemd, and jq
installed.
The sensor service is an example application. Adapt the property name,
configuration path, validation, and reload command to your own service.
Declarative Configuration
The property records the desired configuration. A device-side service periodically reconciles its local configuration with that value. After a reboot or a temporary connection failure, the next successful run applies the same desired state without requiring the operator to resend the change.
Writing the property does not mean the service has applied it. The device must read the value, validate it, update its local configuration, and tell the service to reload. Reporting the applied state separately lets operators distinguish a requested change from a completed one.
Set the Desired Configuration
Run this on your workstation, replacing <device-id> with the device’s ID:
nexigon-cli devices properties set --protected=true <device-id> com.example.sensor.config \
'{"sample_rate_hz": 10, "enabled_channels": ["temperature", "humidity"]}'
In this example, sample_rate_hz requests ten readings per second, and
enabled_channels selects which readings the sensor service should collect.
Your service defines what these fields mean. Use your own domain prefix for
custom properties; dev.nexigon is reserved for Nexigon-defined values.
Apply the Configuration on the Device
Create this executable script on the device:
#!/usr/bin/env bash
set -euo pipefail
response=$(nexigon-agent device properties get com.example.sensor.config)
config=$(printf '%s\n' "$response" | jq -e '
if .result == "Found" and (.value | type == "object")
then .value
else error("configuration property is missing or is not an object")
end
')
printf '%s\n' "$config" >/etc/sensor-service/config.json.tmp
mv /etc/sensor-service/config.json.tmp /etc/sensor-service/config.json
systemctl reload sensor-serviceThe script extracts the property’s JSON value and refuses to replace the file if the property is missing or is not an object. The rename replaces the configuration file in one filesystem operation. Add validation appropriate for your sensor service before replacing its configuration. Checking for a JSON object does not establish that its fields are valid for the service. A failed reload does not restore the previous file; implement recovery appropriate for your application.
Create a systemd service and timer:
[Unit]
Description=Apply Sensor Service Configuration
After=network.target
[Service]
Type=oneshot
ExecStart=/usr/local/bin/apply-sensor-config.sh[Unit]
Description=Apply Sensor Service Configuration Timer
[Timer]
OnBootSec=1min
OnUnitInactiveSec=5min
[Install]
WantedBy=timers.targetEnable the timer:
chmod +x /usr/local/bin/apply-sensor-config.sh
systemctl daemon-reload
systemctl enable --now apply-sensor-config.timer
Change the property from your workstation and check the sensor service after
the next timer run. Use journalctl -u apply-sensor-config.service to inspect
failures. The device needs a connection to Nexigon Hub to read the property;
a failed read leaves the existing file in place. A later timer run retries the
read, which is how this example recovers from a temporary outage.
The timer reapplies the configuration and reloads the service every five minutes, even if the value is unchanged. Your service must tolerate repeated application. If reloads are expensive or disruptive, compare the desired configuration with the applied configuration before replacing the file.
To confirm which configuration was applied, have the script write a separate
unprotected property, such as com.example.sensor.state, after a successful
reload. It can also emit an event when applying configuration
fails.
Add a Configuration Form
A property schema describes the JSON fields operators should supply. It gives the web interface enough information to render a form and check values, such as a positive sample rate or a known sensor channel. The property remains a JSON value that automation can read and write.
To let operators edit this property with a form, open Project Settings →
Property Schemas → Add Schema. Save the following schema under the exact
property name com.example.sensor.config:
{
"type": "object",
"properties": {
"sample_rate_hz": {
"type": "integer",
"title": "Sample Rate (Hz)",
"minimum": 1,
"maximum": 100
},
"enabled_channels": {
"type": "array",
"title": "Enabled Channels",
"items": { "type": "string", "enum": ["temperature", "humidity"] }
}
},
"required": ["sample_rate_hz", "enabled_channels"]
}
Open the device’s Properties page and edit the property. The editor shows fields from the schema. Source opens the complete JSON draft; Form returns to the fields without discarding additional values.
Saving checks the draft against the schema. Correct any mismatch, or select Set property despite validation errors and choose Force Set Property. Schemas are advisory and do not restrict agent or API writes. See Property Schemas for supported schema versions and API actions.
Distribute Configuration Files
For configuration that is not JSON, store files in a repository and put their asset path in a device property. Adapt the device-side script to download the selected asset and apply it with the service’s own tooling. The property then selects which file to apply, while the repository stores the file’s bytes and versions. This is useful for formats such as YAML or a service-specific configuration language.