Changing report interval and deadband on 300 controllers in the field: attributes or commands?
Integrator here. A customer has about 300 pump controllers in the field, ESP32-S3 boards running our own firmware, all on MQTT to Hermetry. We need to change a few settings remotely, per site: the reporting interval, a deadband on the pressure reading, and the NTP server (some sites block the public pools).
Two approaches on the table internally:
- a command, say
cfg.set, with the settings as JSON params, answered with ok/error - shared attributes that the device applies
What I care about: knowing for certain that a given unit has applied a value, and not losing changes for units that are offline. Some rural sites drop off for two or three days at a time.
The firmware already reads a JSON config from flash at boot, so applying the values is not the hard part. The units report every 60 s and sit behind a mix of LTE routers and site Wi-Fi. Which way is Hermetry built for, and is there anything like a desired-vs-reported view?
Student here, curious: why would it matter? A command with the settings in it sounds simpler to me.
Commands to an offline unit only wait if you send them persistent, and that gives up after 7 days at most. Attributes are state, commands are actions. I’d go attributes.
We did it with commands on a smaller fleet and it was a mess every time a unit missed one. Nobody could tell which units had which interval.
Use cfg.* shared attributes, that’s exactly what they’re for, and you get the desired-vs-reported view for free.
Declare the keys on the profile’s Configuration keys tab (type, label, limits), then set them as shared attributes: cfg.telemetry.interval_s, cfg.pressure.deadband_bar, cfg.ntp.server. The device gets changes on v1/attributes/set, applies them, and reports the applied value back as a client attribute with the same key. Hermetry compares the two and shows In sync, Pending, Rejected or Drifted per key on the Attributes tab.
Device side, after every connect:
SUBSCRIBE v1/attributes/set
PUBLISH v1/attributes/req/1 {"sharedKeys": "cfg.*"}
# answer on v1/attributes/res/1 -> apply everything -> report back:
PUBLISH v1/attributes {"cfg.telemetry.interval_s": 300, "cfg.pressure.deadband_bar": 0.05}
The request after connect is what covers your rural sites: a unit that was offline for three days asks for all cfg.* keys when it comes back and catches up. If a unit can’t apply something, report it in cfg_rejected, e.g. {"cfg_rejected": {"cfg.ntp.server": "apply_failed"}}, and the row shows Rejected with the reason. Apply idempotently, a message can arrive twice.
For 300 units, write the values with the API (POST …/attributes/shared, up to 100 keys per call) in a loop over the device list. The baseline and bulk-job screens are for devices that publish a settings manifest (licensed devices), so with your own firmware cfg.* is the route. Attributes page has the status table.
- You must be logged in to reply to this topic.
Join the conversation
Sign in to ask and answer, like helpful posts and mark the reply that solved your problem. Every contribution earns points and levels.

