OpenADR 3.0 VEN
Enrols GEM as a Virtual End Node on an OpenADR 3.0 demand-response program. 3.0 replaced the 2.0b XML ceremony with a REST/JSON API secured by OAuth2 client credentials, and it is the profile new utility programs are written against.
The driver owns the connection only. Event interpretation, load curtailment, restore and history are shared with the OpenADR 2.0b driver — see the OpenADR console for everything on that side.
Prerequisites
- Enrolment with the utility or Energy Services Provider, which supplies:
- the VTN base URL, including the version path (e.g.
https://vtn.example.com/openadr3/3.0.0) - an OAuth2
client_idandclient_secret - the
clientNameregistered for this site, and the program id(s) to follow
- the VTN base URL, including the version path (e.g.
- Some programs additionally require a client certificate. Both mTLS and OAuth2 can be used together.
- Outbound HTTPS from the controller to the VTN. Webhook push additionally needs the VTN to reach the controller, which most installs cannot offer — polling is the default and needs no inbound path.
Setup steps
- System → Devices → Add Device, choose OpenADR 3.0 VEN (key
openadr3). - Set
base_url,client_idandclient_secret. - Set
ven_nameto theclientNamethe program registered for this site. An event targeted at a name that does not match is skipped — the Monitor tab shows the targets so they can be compared directly. - Optionally set
program_idsto restrict which programs are followed. Empty follows every program the VTN offers. - Configure the response on the console's Response tab: curtailable resources for kW-targeted shedding, and/or level-mapped macros.
Or add it from Integrations → OpenADR, which walks the same steps and then opens the console against the new VEN.
Attribute reference
| Scope | Attribute | Direction | Notes |
|---|---|---|---|
| device | base_url | required | 3.0 API root including the version path. |
| device | client_id | optional | OAuth2 client id. Omit only if the VTN authenticates purely with mTLS. |
| device | client_secret | optional, secure | OAuth2 client secret. |
| device | token_url | optional | Defaults to <base_url>/auth/token. |
| device | oauth_scope | optional | Only if the program requires a scope. |
| device | ven_name | optional | VEN clientName. Defaults to the device name. |
| device | ven_id | read-only | Assigned by the VTN on registration. |
| device | program_ids | optional | Comma-separated. Empty follows every program. |
| device | poll_interval | optional | Milliseconds between polls. Default 60000, floored at 5000. |
| device | push_enabled | optional | Subscribe to VTN webhook push. Polling continues either way. |
| device | push_callback_url | optional | Externally reachable URL for push delivery. |
| device | client_cert / client_key | optional, secure | PEM material for VTNs requiring mTLS. |
| device | ca_cert | optional | PEM CA chain used to verify the VTN. |
| device | allow_insecure | optional | Disables TLS verification. Lab VTNs only. |
| device | response_mode | optional | auto (default), resources, macro, both. |
| device | price_thresholds | optional | Maps a PRICE payload onto shed levels. |
| device | restore_spread_ms | optional | Window over which curtailed load is returned. Default 120000. |
| device | telemetry_enabled | optional | Measure and report readings to the VTN. Off by default. |
| device | telemetry_sample_ms | optional | How often readings are taken. Default 30000, floored at 5000. |
| device | report_interval_ms | optional | Submit telemetry on this cadence even with no event running. Empty reports only when an event asks. |
| device | report_granularity_ms | optional | Interval length for standing reports. Default 900000. |
| device | shed_macro_id, restore_macro_id, event_level_1..3_macro_id | optional | Level-mapped macros. |
| device | event_status | read-only | idle or active. |
| device | last_event_id, last_signal_level | read-only | Most recent event and the level in force. |
| device | dr_directive | read-only | Normalized reading of what the site is being asked to do. |
| device | opted_out | read-only | Tracking events but not acting on them. |
| device | dr_active_events | read-only | Persisted event and curtailment state. Managed by the driver. |
| zone | dr_event_active | read-only | 1 while an event is active. |
| zone | dr_signal_level | read-only | Level in force. |
| zone | dr_event_id | read-only | Current event id. |
Zones do not need an address — assigning one to the VEN simply gives it the DR attributes above.
Commands
| Command | Description |
|---|---|
register | Create or refresh this VEN's record on the VTN. |
poll | Fetch events now. |
opt_in / opt_out | Resume or suspend automatic load control. |
get_programs | Programs the VTN offers. |
get_events | Events currently tracked. |
get_status | Connection, registration and event state. |
get_response_status | Curtailable capacity and the current shed plan. |
get_trace | Recent protocol exchanges. |
subscribe_push | Create a webhook subscription for event push. |
get_telemetry | Streams, report obligations and latest readings. |
send_reports | Send any due telemetry reports now. |
Telemetry (reports)
With telemetry_enabled on, the driver registers its measurable resources under /vens/{id}/resources (so a program can target one piece of equipment) and POSTs REPORT objects to /reports.
Values are converted to 3.0's settlement units — watts become KW, watt-hours become KWH. Site-level readings report under the reserved AGGREGATED_REPORT resource name; a metered curtailable resource reports under its own name.
A failed POST is retried rather than skipped past, so a transient VTN outage does not leave a settlement gap.
Payload types
The driver classifies the 3.0 event payload vocabulary and acts only on what it recognizes:
| Payload type | Read as |
|---|---|
SIMPLE, LEVEL | shed level |
PRICE, EXPORT_PRICE, IMPORT_PRICE | price — drives load only with price_thresholds configured |
LOAD_CONTROL | percentage reduction |
LOAD_DISPATCH, DISPATCH_SETPOINT, IMPORT_CAPACITY_LIMIT, IMPORT_CAPACITY_SUBSCRIPTION, IMPORT_CAPACITY_RESERVATION, EXPORT_CAPACITY_LIMIT, EXPORT_CAPACITY_SUBSCRIPTION | kW target |
CONTROL_SETPOINT, CHARGE_STATE_SETPOINT | setpoint |
ALERT_GRID_EMERGENCY, ALERT_BLACK_START, ALERT_POSSIBLE_OUTAGE | shed level |
| anything else | recorded and displayed, never acted on |
Known quirks
- Event versioning uses
modificationDateTime, since 3.0 has no modification number. A VTN that does not update that field when an event is edited will not have its edits applied. - Event targeting is strict. An event with no targets is program-wide and applies. An event carrying only target types GEM does not recognize is treated as not ours — shedding on another VEN's event is worse than missing one, and a skipped event is visible in the console while a wrong shed is a comfort complaint.
- Webhook push is best-effort. When a subscription cannot be created the driver logs it and stays on polling rather than failing the connection.
- Events far outside the window are dropped before decoding — more than 7 days ahead or 6 hours behind. A VTN carrying a season of history is not re-decoded on every poll.
- Reporting obligations come from events. 3.0 has no METADATA negotiation: an event's
reportDescriptorscreate the obligation, so it can change with every event received. For data between events, setreport_interval_ms. - Only report payload types GEM can actually produce are answered —
USAGE,DEMAND,READING,BASELINE,OPERATING_STATE. A descriptor asking for anything else is skipped rather than answered with a wrong quantity.
Troubleshooting
| Symptom | Check |
|---|---|
| Token request fails with HTTP 401 | client_id / client_secret are wrong, or the VTN expects a scope — set oauth_scope to whatever the program documents. |
| Connected but no events ever arrive | Confirm program_ids matches a real program id. The Monitor tab shows the raw /events response; an empty array with HTTP 200 means the VTN has nothing scheduled for this VEN. |
| Events listed but nothing happens | Open the event in the console — the audit trail records the reason. Common causes are a PRICE-only event with no price_thresholds, a level-0 event, the VEN being opted out, or every resource sitting below its min_level. |
| Shed falls short of the requested kW | The Response tab shows available capacity against the target, and the shortfall is written to the event audit trail. Add resources or correct their nominal_kw. |
| Telemetry enabled but nothing is sent | No event has asked for a report and no standing interval is set. Set report_interval_ms for a continuous feed; the Telemetry tab shows every active obligation. |
| Reports rejected by the VTN | The Monitor tab holds the exact POST body and the rejection. Check that the programID matches and that the resources were registered. |
| Duplicate VEN records on the VTN | The driver looks for its own clientName before creating one. If duplicates already exist from an earlier tool, remove them at the VTN — a duplicate silently stops receiving targeted events. |
Related
- OpenADR console — events, resources, monitoring and the simulator
- OpenADR 2.0b driver — the older profile, same response engine