5.3 KiB
DVgo device emulator
Node.js ThingsBoard device emulator with a SQLite-backed web portal. Each virtual device can connect over MQTT, publish live *_s telemetry, react to shared-attribute commands from the apps, and be taken offline without deleting the ThingsBoard record.
Requires Node 22+ (uses the built-in node:sqlite module).
Python historical data generation is not included.
What it does
- Create / delete real ThingsBoard devices via the REST API (delete still removes the emulator row if the TB device is already gone)
- Persist credentials, telemetry, published-key selection, and plant settings in SQLite
- MQTT connect with the device access token as username (
v1/devices/me/telemetry, plus attributes and RPC) - Web portal (
http://localhost:3080) to:- add devices (or attach an existing MQTT access token)
- select devices (select all / deselect all) and enable, disable, or delete
- Connect / Disconnect MQTT (new devices stay idle until you connect)
- start / stop the telemetry loop (Start telemetry is disabled until connected)
- toggle which keys are included in each publish (per-card On, plus select all / deselect all under Publish now)
- edit every live
_skey from the device dashboard - run a virtual plant that follows boost and schedule commands from the apps
On startup, devices already in SQLite are restored. They reconnect only if they were left enabled (not disabled). New devices are created disconnected, with telemetry off.
Virtual plant
While MQTT is connected, the device polls ThingsBoard shared attributes every 5 seconds (and also receives live pushes). It understands:
| Source | Keys |
|---|---|
| One-shot boost | boostNowHw, boostNowAux (minutes; written by the apps via TB REST) |
| HW schedule | hwRlyMode 2 or 3, plus hwRlySchedMode0/1StartTime / StopTime (minutes since midnight) |
| Aux schedule | auxRlyMode 2 or 3, plus auxRlySchedMode0/1Start / Stop |
Schedule saves in the apps are SQL-only, so this emulator polls rather than waiting for a TB push.
Behaviour:
- Red / grey lamps for hot water boost and aux boost / divert
- While HW is on,
heatsink_srises at Heat rate (°C / min) (integer, default 1) - At Thermostat max (°C) (default 65) heating stops,
rlyInSel_sgoes to 0, andboostNowHwis written back to ThingsBoard as 0 - Live state is published as
heatsink_s,rlyInSel_s,auxOn_s,auxRelay_s
Telemetry keys
Each device can publish the following live *_s keys on v1/devices/me/telemetry. Dashboard cards are ordered Status, Power, Energy flows, Energy today, Validity. Only keys with On checked are sent.
Status
heatsink_s— hot water / tank temperature (°C)batterySoc_s— battery state of charge (%)soc_s— SoC fallback (%)batteryPercent_s— battery percent fallback (%)auxOn_s— aux on (0/1)auxRelay_s— aux relay (0/1)rlyInSel_s— control load heating (0/1)xCntlLoadState— control load state (integer; no_ssuffix)
Power (W)
solarPower_s— solar generationloadPower_s— home loadhotWaterInPower_s— hot water inhotWaterOutPower_s— hot water outbatteryPower_s— battery power (negative = charging, positive = discharging)gridPower_s— grid power (positive = importing, negative = exporting)
Energy flows (W)
solarToLoadPower_ssolarToHotWaterPower_ssolarToBatteryPower_ssolarToGridPower_sgridToLoadPower_sgridToHotWaterPower_sgridToBatteryPower_sbatteryToLoadPower_sbatteryToHotWaterPower_sbatteryToGridPower_s
Energy today (Wh)
solarToday_sloadToday_shotWaterInToday_shotWaterOutToday_ssolarToLoadToday_ssolarToHotWaterToday_ssolarToGridToday_ssolarToBatteryToday_sgridToLoadToday_sgridToHotWaterToday_sgridToBatteryToday_sbatteryToLoadToday_sbatteryToHotwaterToday_s— note the lowercasewinHotwaterbatteryToGridToday_sbatteryExportToday_sbatteryImportToday_sgridImport_sgridExport_s
Validity
vPwrReadings_s— bitmask of valid live power keys (65535= bits 0–15 all valid)
Setup
cp .env.example .env
# fill TB_USERNAME / TB_PASSWORD (tenant admin or a user who can create devices)
npm install
npm start
Open http://localhost:3080.
Optional env:
PORT— portal port (default3080)TB_HTTP_URL— ThingsBoard REST origin (defaulthttps://tb-dvgo.datavolt.au)TB_DEVICE_PROFILE_ID— defaults to the Diverter / DVgo profile (e6b53240-7fec-11f1-a69d-edbc0b9170ac). The add-device dropdown is preselected to a profile named Diverter or DVgo when ThingsBoard returns one.TB_DEVICE_TYPE— defaultDVgoTB_MQTT_URL— defaultmqtts://tb-dvgo.datavolt.au:8883(TLS). Port 1883 is not reachable from outside the TB host.TB_MQTT_INSECURE—trueto skip TLS certificate verificationPORTAL_USER/PORTAL_PASSWORD— basic auth for the control APIALLOWED_IPS— comma-separated allowlist for/apiTELEMETRY_INTERVAL_MS— default5000DB_PATH— default./data/emulator.db
If a device already exists in ThingsBoard, paste its MQTT access token in the add form and skip REST provisioning. If create times out, the portal can look the device up by name and adopt it.