IoT Hub: ADU Workflow (Simulator)
iot powershell dotnetcore iothub azure iot-core adu
This workflow uses IoT Hub twins to signal Device Update intent for simulator devices.
Prerequisites
- IoT Hub Standard tier (S1 or higher)
- Azure CLI with
azure-iotextension IOTHUB_NAMEenvironment variable set, or pass-HubName- Simulator running from
csharp_simulator
1. Generate devices.json (if needed)
.\3_Simulator\generate_devices_json.ps1
2. Start simulator
.\3_Simulator\run_10_devices.ps1
3. Set ADU target version intent
All devices (device1..device10):
.\4_ADU\adu_set_target_version.ps1 -TargetVersion 1.1.0
Single device:
.\4_ADU\adu_set_target_version.ps1 -TargetVersion 1.1.0 -DeviceId device1
4. Check ADU status
.\4_ADU\adu_get_status.ps1
Expected behavior:
desiredTargetVersionset to target releaserestartRequestedbecomesTruefor affected devices- simulator reports state then exits to allow external update workflow
5. Clear/rollback ADU intent
All devices:
.\4_ADU\adu_clear_target_version.ps1
Single device:
.\4_ADU\adu_clear_target_version.ps1 -DeviceId device1
6. Restart simulator after external update workflow
.\3_Simulator\run_10_devices.ps1
Notes
- This simulator does not install packages by itself.
- It only signals update intent and restart handoff through twin properties.
Addendum: Practical Update Sequence
Question:
- To do a device update do you update code, set new version, and run the simulator again?
- Do devices need stopping first?
Answer:
- Update the simulator code.
- Bump app version in
csharp_simulator/Program.cs(AppInfo.Version) to your new version. - Set the new desired target version:
.\4_ADU\adu_set_target_version.ps1 -TargetVersion 1.1.1
- Restart simulator processes so they pick up the new build.
Recommended restart flow:
.\3_Simulator\stop_10_devices.ps1
.\3_Simulator\run_10_devices.ps1
Notes:
- In this simulator pattern, ADU twin intent does not install binaries.
- New code is only picked up when simulator processes are started again.
- If devices already exited after
restartRequested=True, stop may find nothing, which is fine.
Quick Copy/Paste Checklist
# 1) Build/publish new simulator code and bump AppInfo.Version in csharp_simulator/Program.cs
# 2) Set desired ADU target version (match AppInfo.Version)
.\4_ADU\adu_set_target_version.ps1 -TargetVersion 1.1.1
# 3) Optional: confirm restart requested/status
.\4_ADU\adu_get_status.ps1
# 4) Restart simulator processes
.\3_Simulator\stop_10_devices.ps1
.\3_Simulator\run_10_devices.ps1
# 5) Verify running state after restart
.\4_ADU\adu_get_status.ps1
Addendum 2: What Is Preserved Between ADU Restarts?
Preserved across restart
- IoT Hub twin desired properties in cloud, including
desired.simsettings. - IoT Hub twin desired ADU intent, including
desired.du.targetVersion. - Device identities in IoT Hub.
Reset on restart
- In-memory simulator runtime state such as:
sendCountstoredTextstoredNumbertelemetryEnabled
What happens on next startup
- Simulator starts with default in-memory state.
- It reconnects and loads twin desired properties.
- It reapplies desired simulator config from twin.
- It compares
desired.du.targetVersionwithAppInfo.Version.
If target version still differs from app version, the simulator sets restart requested again and exits (expected behavior). If target version matches app version, it continues running normally.
Addendum 3: How Desired vs Reported Twin Properties Are Set
In this workflow:
- Desired properties are set from the cloud/service side (Azure CLI/scripts).
- Reported properties (actual runtime state) are set by the simulator app.
Desired (set from scripts)
ADU desired target version is written with:
.\4_ADU\adu_set_target_version.ps1 -TargetVersion 1.1.1
which runs az iot hub device-twin update against:
properties.desired.du.targetVersion
Desired values represent what you want the device to do/configure.
Reported (set by simulator)
When the simulator runs, it reports current state back to IoT Hub under:
properties.reported.sim.*properties.reported.app.*properties.reported.du.*
This includes values like current simulator settings, app version, restart requested flag, and last state timestamps.
Practical model
- Cloud writes desired.
- Device applies/observes desired.
- Device publishes reported actual state.
adu_get_status.ps1 shows both desired and reported values side-by-side so you can confirm whether device state has converged to the requested state.
Example Twin Shape (One Device)
{
"deviceId": "device1",
"properties": {
"desired": {
"sim": {
"intervalSeconds": 3,
"randomEvery": 10,
"tempMin": 15,
"tempMax": 40,
"baseTemp": 23
},
"du": {
"targetVersion": "1.1.1"
}
},
"reported": {
"app": {
"name": "csharp-simulator",
"version": "1.1.1"
},
"sim": {
"intervalSeconds": 3,
"randomEvery": 10,
"telemetryEnabled": true,
"sendCount": 42,
"lastState": "connected",
"lastUpdateUtc": "2026-07-11T06:00:00.0000000Z"
},
"du": {
"targetVersion": "1.1.1",
"restartRequested": false,
"note": "Device Update package installation is external to this app."
}
}
}
}
| Topic | Subtopic | |
| Next: > | IoT Hub | Start a RPI Pico W once set up |
| < Prev: | IoT Hub | C# Device Simulator Deployment |
| This Category Links | ||
| Category: | IoT Index: | IoT |