Skip to content

Event Implementation Guide

This page provides context on how to implement OpenADR events with Plaid. It gives key information on how events are formatted in OpenADR, and how you can handle them via Plaid.

OpenADR events: background information & implementation strategies

Anatomy of an OpenADR event

Understanding what OpenADR events include is helpful for creating a strategy of how best to handle them. The OpenADR specification document includes the following useful diagram in section 8. There is a lot in this diagram, and we will cover the key parts (the red boxes are editorial oversight, not in the original image). For a complete description, please refer to the spec.

OpenADR Event Diagram

Event Content

The key descriptor of what the VTN is requesting in the event is through the intervals and signals. Most events will just have one signal and one interval, but can have many.


Signals are the event content: they describe the VTN's request to the VEN (for example, initiate control level of 2, please provide 10,000 Watts, etc.). Events may include one or many signals in parallel (the diagram describes an event with 2 signals).

For example, the VTN may simultaneously send a price signal and a simple control signal, so the VEN could decide to either use the price signal and determine a strategy based on that, or follow a predefined strategy defined by the VTN operator. The original intent behind sending two Signals is that one payload could be sent to A profile VENs and another to B profile VENs. In practice, this seems to be very rare and events only have one signal. We recommend implementing your VEN with the assumption that there will only be one signal, and in the unlikely event you need to update that in the future, you can extend your implementation via Plaid.

See the Signal Names and Types section (below) for a description of the types of signals you will encounter.


Each signal is broken up sequentially into intervals that make up the full event. Again, most of the time signals just have one interval.

Each interval within a signal provides a different payload. This allows VTNs to request varying levels of control over the course of the event. For example, partial capacity for the first 50% of the event and full capacity for the last 50% of the event. Or, a VTN may send a price event over the next hour with different intervals providing prices in 5 minute increments over the hour.

Event Timing

Most typically, events will be called a day in advance, so the Notification Time will be 12-24 hours. However, we have seen fast response programs where events may be called 5-10 minutes in advance, which would necessitate a faster polling window.

Events will always have a start time (coinciding with the first interval), but there are a couple of things that dictate when a VEN should actually start and stop responding to the event.

Randomization defines a randomized offset. If the randomization window is 5 minutes, the VEN may choose any value between 1 and 5 minutes, and start it's control that amount of time after the start time, and end the same amount of time after the end time (so the duration of the event is the same). This would be helpful in real world programs to prevent assets coming online and offline all at the same time and giving a shock to the grid.

Ramp up provides a time window over which the VEN may ramp up to the expected level of control.

Recovery provides a time window over which the VEN may return to a normal state.

While they are part of the spec, in practice we haven't seen these options used much in the field and when an event starts your VEN is expected to start providing capacity right then. Since randomization is included in the certification process, it is handled in the event callbacks (see later). Ramp up and Recovery are not, and are also not used in practice so do not have dedicated http callbacks, but are available in the plugin so in the unlikely event that they are required, they can be implemented without having to go into the core OpenADR functionality.

Signal Names And Types

OpenADR allows for a diverse set of signals, which describe load shifting events. Signals are defined by their name, type and units allowed.

There are a number of pre-defined signals that may be used. Specific deployments may also define their own custom signals in addition. New signals must be prefixed with a x- on the signal name. Existing signal types and units can be used to construct a new signal. Custom signal types can be defined if necessary and also prefixed with x-.

In practice, the Simple / Level signal is used in most implementations. This may change in the future as load shifting programs get more sophisticated.

The following table describes the pre-defined signal types. These are defined in section 8.3.3 of the OpenADR 2.0b profile specification, v1.1. Please refer to that for full descriptions.

Signal Category Signal Name Type Units Allowed Values
Simple levels SIMPLE level None 0,1,2,3
Price of electricity ELECTRICITY_PRICE price currency / kWh any
Price of electricity ELECTRICITY_PRICE priceRelative currency / kWh any
Price of electricity ELECTRICITY_PRICE priceMultiplier none any
Price of energy ENERGY_PRICE price currency / kWh any
Price of energy ENERGY_PRICE priceRelative currency / kWh any
Price of energy ENERGY_PRICE priceMultiplier none any
Demand Charge DEMAND_CHARGE price currency / kWh any
Demand Charge DEMAND_CHARGE priceRelative currency / kW any
Demand Charge DEMAND_CHARGE priceMultiplier none any
Customer bid levels BID_PRICE price currency / kWh any
Customer bid levels BID_LOAD setpoint power any
Customer bid levels BID_ENERGY setpoint energy any
Storage-specific resources CHARGE_STATE setpoint energy any
Storage-specific resources CHARGE_STATE delta energy any
Storage-specific resources CHARGE_STATE multiplier none 0.0 - 1.0
Set the load LOAD_DISPATCH setpoint power any
Set the load LOAD_DISPATCH delta power any
Set the load LOAD_DISPATCH multiplier none any
Set the load LOAD_DISPATCH level power Integer between -10 and +10
Relative value load control LOAD_CONTROL x-loadControlCapacity none 0.0 - 1.0
Relative value load control LOAD_CONTROL x-loadControlLevelOffset none non-zero integer
Relative value load control LOAD_CONTROL x-loadControlSetpoint none any
Relative value load control LOAD_CONTROL x-loadControlPercentOffset none -1.0 - 1.0

Which Event Types to Support

Though some event types might not make sense for your device, VENs must support all event types in order to be compliant. VENs aren't required to have special logic for each event type, but each event type must be supported.

We suggest all Plaid implementations to fully implement SIMPLE/level events, as they are by far the most common. SIMPLE/level events have a payload of 0, 1, 2, or 3, meaning there's only 4 control options when working with simple/level events. According to the OpenADR profiles, these payload values correspond to the following:

  • 0 normal: run normal, don't perform any control
  • 1 moderate: perform a moderate reduction in energy use
  • 2 high: perform a high reduction in energy use
  • 3 special: program defined / special

In addition to implementing SIMPLE/level events, select other event types that make sense for your device type and implement specific logic to handle those event types. For all other event types, use default logic for the event (i.e. no matter what the payload is: when the even starts, reduce demand, when the event ends, go back to normal).

Following these tips will get you through compliance testing but the implementation will likely need to be modified to meet utility requirements. Furthermore, each utility will likely have different requirements for control for a given event type. This means special control logic may need to be written for each utility. Therefore, it does not make sense to build out control logic in a vacuum - you should write what is necessary to gain certification and then update as necessary to participate in different utility load shifting programs.

Event Targeting

Events may be targeted to specific VENs, resources, groups or parties - it is the VTN operator's way of fine-tuning DR events for the benefit of the grid. If events are untargeted, they should be assumed to apply to all resources. If a VEN receives an event target it is not configured for, it will reject the message.

  • VenID - only up to one may be specified. If none are, every VEN should respond.
  • Resource ID(s) - usually specifies individual devices.
  • Group ID(s) - refers to a group of devices (e.g. by geography, grid topology, device type, etc).
  • Party ID(s) - not often used.

Resource, group and party IDs are not defined within OpenADR: it is expected that they are defined out of band and both the VEN and VTN know what they refer to.

Event targeting to specific resources and/or groups is becoming more common as OpenADR programs are becoming more sophisticated, and VENs are increasingly implemented as "cloud VENs" that represent many devices and loads in a single program. However, when using Plaid this does not need to be implemented to achieve OpenADR compliance, so it is advised to wait until there is a specific need in a utility program, unless it is necessary for your internal testing purposes.

Implementing events with Plaid

For an example of how events flow through Plaid, please reference the event flow page.

There are two main strategies for dealing with event execution in Plaid (assuming you are using the default plugin that ships with Plaid)

  1. Let Plaid handle the event scheduling, and react as start and end messages are send
  2. Get all event information as Plaid receives it from the VTN, and execute the event correctly based on your own logic

To implement #1, all you need to implement is the OnStartEventInterval callback and OnCompleteEvent callback. Your system should start control when receiving the OnStartEventInterval message, and end it when receiving the OnCompleteEvent message. In this scenario, Plaid will handle complexities around scheduling, randomization, interval parsing (and corner cases, described below).

To implement #2, you should implement the OnEvent callback to receive all the information up front and handle it accordingly. When Plaid receives an event from the VTN, it will send it through the OnEvent callback. This provides the information needed to schedule the event in your system: signal type & payload, start time, end time, targets and randomization.

In practice, we expect #2 to become necessary. Even if you would like to rely on Plaid's OnEventStartInterval to kick off events in your system you would still want to receive the OnEvent message to notify customers that an event is coming up and/or optimize your system accordingly. We suggest the default option be #1 for simplicity at first, and as your system requirements grow you can get information up front and act accordingly.

Event Handling Corner Cases

Two features of events which often cause implementation issues are:

  1. Zero length events
  2. Event randomization

Compliance testing tests these features and also tests canceling a randomized event. If the Plaid OnEventStart, OnEventEnd, OnEventCancel callbacks are used, the following corner cases are handled automatically. If these called backs aren't used, the following corner cases must be handled by the external system.

Regardless of whether or not your plugin uses the Plaid callbacks, EVERYONE should read these corner cases carefully and implement accordingly. Most notably, canceled randomized events.

  1. Zero length events: events with a duration of 0 stay active until modified with a real duration or canceled.
  2. Randomized events: Plaid has two modes for randomized events: one where Plaid picks the randomized start time and one where the external system picks the randomized time. If Plaid picks the start time, the external system is notified of the start and end times correctly, and the times in the callbacks are the randomized times. If Plaid randomization is disabled, the external system is responsible for parsing the randomization parameter and starting control at a randomized time. Plaid will call the start event callback at the unrandomized start time, but the external system should not start the event when the message is received, but should start the event after a randomized period.
  3. Canceled randomized events: if a randomized event is canceled while active, the event should not end immediately - it should wait the randomized minutes before ending. In this situation, Plaid will send a canceled event message, followed by an end event message when the event is complete. The end event message will arrive after a randomized amount of time.

If the event has a randomization windows and randomization is turned on for Plaid (which we suggest), the OnEvent message will include the randomization offset in seconds, which can be added to the start time to schedule the event in your system.