-
Notifications
You must be signed in to change notification settings - Fork 65
Description
Hi,
While integrating OpenLEADR with a certified OpenADR 2.0b VEN , I found what appears to be a bug in server.py add_raw_event() that causes optional ActivePeriod fields (such as notification_period) to be silently dropped from the generated XML.
When creating an event using server.add_event() and specifying:
notification_period=timedelta(minutes=10)
the ActivePeriod object is correctly constructed in add_event():
active_period = utils.get_active_period_from_intervals(intervals, False)
active_period.notification_period = notification_period
However, inside add_raw_event(), the following logic recalculates the active_period:
active_period = utils.get_active_period_from_intervals(
[utils.get_active_period_from_intervals(utils.getmember(signal, 'intervals'), False)
for signal in utils.getmember(event, 'event_signals')]
)
Since get_active_period_from_intervals() (From utils.py) defaults to as_dict=True, this returns:
{
'dtstart': ...,
'duration': ...
}
This replaces the existing ActivePeriod dataclas and remove notification_period, ramp_up_period, recovery_period, tolerance. As result, the generated XML does not include:
<ei:x-eiNotification>
<duration>PT10M</duration>
</ei:x-eiNotification>
This caused strict OpenADR VEN implementations to reject the event with:
invalid activePeriod
Document missing event notification node
I also noticed that add_raw_event() checks:
utils.getmember(event, 'event_descriptor.active_period', None)
However, active_period is a direct attribute of the Event object, not part of event_descriptor.
Changing this to:
utils.getmember(event, 'active_period', None)
ensures the existing ActivePeriod object is respected and not unnecessarily recalculated.
Proposed Fix:
Force get_active_period_from_intervals() to return an ActivePeriod object instead of a dict:
if not utils.getmember(event, 'active_period', None):
active_period = utils.get_active_period_from_intervals(
[utils.get_active_period_from_intervals(
utils.getmember(signal, 'intervals'), False)
for signal in utils.getmember(event, 'event_signals')],
False # ← force dataclass instead of dict
)
utils.setmember(event, 'active_period', active_period)
This preserves the dataclass structure and allows:
- notification_period
- ramp_up_period
- recovery_period
to be serialized correctly in the XML template.
The OpenADR 2.0b specification states that:
-ei:x-eiNotification is OPTIONAL in profile B
-REQUIRED in profile A
However, some certified VEN implementations expect this node to be present. Currently, even when users explicitly define notification_period, it does not appear in the final XML due to the re-conversion to dict.
After the change, the generated XML correctly includes:
<ei:x-eiNotification>
<duration>PT10M</duration>
</ei:x-eiNotification>