Пример #1
0
 async def on_poll(ven_id, future=None):
     if future and not future.done():
         future.set_result(True)
         return objects.Event(
             event_descriptor=objects.EventDescriptor(
                 event_id='event001',
                 modification_number=0,
                 event_status='far',
                 market_context='http://marketcontext01'),
             event_signals=[
                 objects.EventSignal(
                     signal_id='signal001',
                     signal_type='level',
                     signal_name='simple',
                     intervals=[
                         objects.Interval(
                             dtstart=now,
                             duration=datetime.timedelta(minutes=10),
                             signal_payload=1)
                     ]),
                 objects.EventSignal(
                     signal_id='signal002',
                     signal_type='price',
                     signal_name='ELECTRICITY_PRICE',
                     intervals=[
                         objects.Interval(
                             dtstart=now,
                             duration=datetime.timedelta(minutes=10),
                             signal_payload=1)
                     ])
             ],
             targets=[objects.Target(ven_id=ven_id)])
     else:
         print("Returning None")
         return None
Пример #2
0
async def test_raw_event():
    now = datetime.datetime.now(datetime.timezone.utc)
    server = OpenADRServer(vtn_id='myvtn')
    server.add_handler('on_create_party_registration',
                       on_create_party_registration)
    event = objects.Event(
        event_descriptor=objects.EventDescriptor(
            event_id='event001',
            modification_number=0,
            event_status='far',
            market_context='http://marketcontext01'),
        event_signals=[
            objects.EventSignal(
                signal_id='signal001',
                signal_type='level',
                signal_name='simple',
                intervals=[
                    objects.Interval(dtstart=now,
                                     duration=datetime.timedelta(minutes=10),
                                     signal_payload=1)
                ]),
            objects.EventSignal(
                signal_id='signal002',
                signal_type='price',
                signal_name='ELECTRICITY_PRICE',
                intervals=[
                    objects.Interval(dtstart=now,
                                     duration=datetime.timedelta(minutes=10),
                                     signal_payload=1)
                ])
        ],
        targets=[objects.Target(ven_id='ven123')])
    loop = asyncio.get_event_loop()
    event_callback_future = loop.create_future()
    server.add_raw_event(ven_id='ven123',
                         event=event,
                         callback=partial(event_callback,
                                          future=event_callback_future))

    on_event_future = loop.create_future()
    client = OpenADRClient(
        ven_name='myven', vtn_url='http://localhost:8080/OpenADR2/Simple/2.0b')
    client.add_handler('on_event',
                       partial(on_event_opt_in, future=on_event_future))

    await server.run_async()
    await client.run()
    event = await on_event_future
    assert len(event['event_signals']) == 2

    result = await event_callback_future
    assert result == 'optIn'

    await client.stop()
    await server.stop()
Пример #3
0
def test_oadr_event():
    event = objects.Event(
        event_descriptor=objects.EventDescriptor(
            event_id=1,
            modification_number=0,
            market_context='MarketContext1',
            event_status=enums.EVENT_STATUS.NEAR),
        active_period=objects.ActivePeriod(dtstart=datetime.now(),
                                           duration=timedelta(minutes=10)),
        event_signals=[
            objects.EventSignal(intervals=[
                objects.Interval(dtstart=datetime.now(),
                                 duration=timedelta(minutes=5),
                                 uid=0,
                                 signal_payload=1),
                objects.Interval(dtstart=datetime.now(),
                                 duration=timedelta(minutes=5),
                                 uid=1,
                                 signal_payload=2)
            ],
                                targets=[objects.Target(ven_id='1234')],
                                signal_name=enums.SIGNAL_NAME.LOAD_CONTROL,
                                signal_type=enums.SIGNAL_TYPE.LEVEL,
                                signal_id=1,
                                current_value=0)
        ],
        targets=[objects.Target(ven_id='1234')])

    response = objects.Response(response_code=200,
                                response_description='OK',
                                request_id='1234')
    msg = create_message('oadrDistributeEvent',
                         response=response,
                         events=[event])
    message_type, message_payload = parse_message(msg)
Пример #4
0
def test_oadr_event_no_targets():
    with pytest.raises(ValueError):
        event = objects.Event(
            event_descriptor=objects.EventDescriptor(
                event_id=1,
                modification_number=0,
                market_context='MarketContext1',
                event_status=enums.EVENT_STATUS.NEAR),
            active_period=objects.ActivePeriod(dtstart=datetime.now(),
                                               duration=timedelta(minutes=10)),
            event_signals=[
                objects.EventSignal(intervals=[
                    objects.Interval(dtstart=datetime.now(),
                                     duration=timedelta(minutes=5),
                                     uid=0,
                                     signal_payload=1),
                    objects.Interval(dtstart=datetime.now(),
                                     duration=timedelta(minutes=5),
                                     uid=1,
                                     signal_payload=2)
                ],
                                    targets=[objects.Target(ven_id='1234')],
                                    signal_name=enums.SIGNAL_NAME.LOAD_CONTROL,
                                    signal_type=enums.SIGNAL_TYPE.LEVEL,
                                    signal_id=1,
                                    current_value=0)
            ])
Пример #5
0
def test_increment_modification_number():
    now = datetime.now(timezone.utc)
    event = objects.Event(
        event_descriptor=objects.EventDescriptor(
            event_id='event001',
            modification_number=0,
            created_date_time=now,
            event_status='far',
            priority=1,
            market_context='http://context01'),
        active_period=objects.ActivePeriod(dtstart=now - timedelta(minutes=5),
                                           duration=timedelta(minutes=10)),
        event_signals=[
            objects.EventSignal(intervals=[
                objects.Interval(dtstart=now,
                                 duration=timedelta(minutes=10),
                                 signal_payload=1)
            ],
                                signal_name='simple',
                                signal_type='level',
                                signal_id='signal001')
        ],
        targets=[{
            'ven_id': 'ven001'
        }])

    utils.increment_event_modification_number(event)
    assert utils.getmember(event, 'event_descriptor.modification_number') == 1
    utils.increment_event_modification_number(event)
    assert utils.getmember(event, 'event_descriptor.modification_number') == 2
Пример #6
0
def test_oadr_event_targets_and_targets_by_type():
    event = objects.Event(
        event_descriptor=objects.EventDescriptor(
            event_id=1,
            modification_number=0,
            market_context='MarketContext1',
            event_status=enums.EVENT_STATUS.NEAR),
        active_period=objects.ActivePeriod(dtstart=datetime.now(),
                                           duration=timedelta(minutes=10)),
        event_signals=[
            objects.EventSignal(intervals=[
                objects.Interval(dtstart=datetime.now(),
                                 duration=timedelta(minutes=5),
                                 uid=0,
                                 signal_payload=1),
                objects.Interval(dtstart=datetime.now(),
                                 duration=timedelta(minutes=5),
                                 uid=1,
                                 signal_payload=2)
            ],
                                targets=[objects.Target(ven_id='1234')],
                                signal_name=enums.SIGNAL_NAME.LOAD_CONTROL,
                                signal_type=enums.SIGNAL_TYPE.LEVEL,
                                signal_id=1,
                                current_value=0)
        ],
        targets=[{
            'ven_id': 'ven123'
        }],
        targets_by_type={'ven_id': ['ven123']})

    msg = create_message('oadrDistributeEvent', events=[event])
    validate_xml_schema(ensure_bytes(msg))
    message_type, message_payload = parse_message(msg)
Пример #7
0
def test_event_signal_with_incongruent_targets():
    with pytest.raises(ValueError):
        event_signal = objects.EventSignal(
            intervals=[
                objects.Interval(dtstart=datetime.now(timezone.utc),
                                 duration=timedelta(minutes=10),
                                 signal_payload=1)
            ],
            signal_name='simple',
            signal_type='level',
            signal_id='signal123',
            targets=[objects.Target(ven_id='ven123')],
            targets_by_type={'ven_id': ['ven123', 'ven456']})
Пример #8
0
def test_event_signal_with_grouped_targets():
    event_signal = objects.EventSignal(
        intervals=[
            objects.Interval(dtstart=datetime.now(timezone.utc),
                             duration=timedelta(minutes=10),
                             signal_payload=1)
        ],
        signal_name='simple',
        signal_type='level',
        signal_id='signal123',
        targets_by_type={'ven_id': ['ven123', 'ven456']})
    assert event_signal.targets == [
        objects.Target(ven_id='ven123'),
        objects.Target(ven_id='ven456')
    ]
Пример #9
0
 async def add_event(self, ven_id, signal_name, signal_type, intervals,
                     target, callback):
     """
     Convenience method to add an event with a single signal.
     :param str ven_id: The ven_id to whom this event must be delivered.
     :param str signal_name: The OpenADR name of the signal; one of openleadr.objects.SIGNAL_NAME
     :param str signal_type: The OpenADR type of the signal; one of openleadr.objects.SIGNAL_TYPE
     :param str intervals: A list of intervals with a dtstart, duration and payload member.
     :param str callback: A callback function for when your event has been accepted (optIn) or refused (optOut).
     """
     if self.services['event_service'].polling_method == 'external':
         logger.error(
             "You cannot use the add_event method after you assign your own on_poll "
             "handler. If you use your own on_poll handler, you are responsible for "
             "delivering events from that handler. If you want to use OpenLEADRs "
             "message queuing system, you should not assign an on_poll handler. "
             "Your Event will NOT be added.")
         return
     event_id = generate_id()
     if not isinstance(target, list):
         target = [target]
     event_descriptor = objects.EventDescriptor(
         event_id=event_id,
         modification_number=0,
         market_context="None",
         event_status="near",
         created_date_time=datetime.now(timezone.utc))
     event_signal = objects.EventSignal(intervals=intervals,
                                        signal_name=signal_name,
                                        signal_type=signal_type,
                                        signal_id=generate_id(),
                                        targets=target)
     event = objects.Event(event_descriptor=event_descriptor,
                           event_signals=[event_signal],
                           targets=target)
     if ven_id not in self.message_queues:
         self.message_queues[ven_id] = asyncio.Queue()
     await self.message_queues[ven_id].put(event)
     self.services['event_service'].pending_events[event_id] = callback
Пример #10
0
def poll_responder(ven_id, message_type, message_payload):
    return message_type, message_payload


event = objects.Event(event_descriptor=objects.EventDescriptor(
    event_id='event123',
    event_status='far',
    modification_number='1',
    market_context='http://marketcontext01'),
                      event_signals=[
                          objects.EventSignal(
                              signal_name='simple',
                              signal_type='level',
                              signal_id=utils.generate_id(),
                              intervals=[
                                  objects.Interval(
                                      dtstart=datetime.now(timezone.utc),
                                      duration=timedelta(minutes=10),
                                      signal_payload=1)
                              ])
                      ],
                      targets=[{
                          'ven_id': 'ven123'
                      }])

poll_responses = [('oadrResponse', {}),
                  ('oadrDistributeEvent', {
                      'events': [asdict(event)]
                  }),
                  ('oadrCreateReport', {
                      'report_requests': [{
Пример #11
0
def test_order_events():
    now = datetime.now(timezone.utc)
    event_1_active_high_prio = objects.Event(
        event_descriptor=objects.EventDescriptor(
            event_id='event001',
            modification_number=0,
            created_date_time=now,
            event_status='far',
            priority=1,
            market_context='http://context01'),
        active_period=objects.ActivePeriod(dtstart=now - timedelta(minutes=5),
                                           duration=timedelta(minutes=10)),
        event_signals=[
            objects.EventSignal(intervals=[
                objects.Interval(dtstart=now,
                                 duration=timedelta(minutes=10),
                                 signal_payload=1)
            ],
                                signal_name='simple',
                                signal_type='level',
                                signal_id='signal001')
        ],
        targets=[{
            'ven_id': 'ven001'
        }])

    event_2_active_low_prio = objects.Event(
        event_descriptor=objects.EventDescriptor(
            event_id='event001',
            modification_number=0,
            created_date_time=now,
            event_status='far',
            priority=2,
            market_context='http://context01'),
        active_period=objects.ActivePeriod(dtstart=now - timedelta(minutes=5),
                                           duration=timedelta(minutes=10)),
        event_signals=[
            objects.EventSignal(intervals=[
                objects.Interval(dtstart=now,
                                 duration=timedelta(minutes=10),
                                 signal_payload=1)
            ],
                                signal_name='simple',
                                signal_type='level',
                                signal_id='signal001')
        ],
        targets=[{
            'ven_id': 'ven001'
        }])

    event_3_active_no_prio = objects.Event(
        event_descriptor=objects.EventDescriptor(
            event_id='event001',
            modification_number=0,
            created_date_time=now,
            event_status='far',
            market_context='http://context01'),
        active_period=objects.ActivePeriod(dtstart=now - timedelta(minutes=5),
                                           duration=timedelta(minutes=10)),
        event_signals=[
            objects.EventSignal(intervals=[
                objects.Interval(dtstart=now,
                                 duration=timedelta(minutes=10),
                                 signal_payload=1)
            ],
                                signal_name='simple',
                                signal_type='level',
                                signal_id='signal001')
        ],
        targets=[{
            'ven_id': 'ven001'
        }])

    event_4_far_early = objects.Event(
        event_descriptor=objects.EventDescriptor(
            event_id='event001',
            modification_number=0,
            created_date_time=now,
            event_status='far',
            market_context='http://context01'),
        active_period=objects.ActivePeriod(dtstart=now + timedelta(minutes=5),
                                           duration=timedelta(minutes=10)),
        event_signals=[
            objects.EventSignal(intervals=[
                objects.Interval(dtstart=now,
                                 duration=timedelta(minutes=10),
                                 signal_payload=1)
            ],
                                signal_name='simple',
                                signal_type='level',
                                signal_id='signal001')
        ],
        targets=[{
            'ven_id': 'ven001'
        }])

    event_5_far_later = objects.Event(
        event_descriptor=objects.EventDescriptor(
            event_id='event001',
            modification_number=0,
            created_date_time=now,
            event_status='far',
            market_context='http://context01'),
        active_period=objects.ActivePeriod(dtstart=now + timedelta(minutes=10),
                                           duration=timedelta(minutes=10)),
        event_signals=[
            objects.EventSignal(intervals=[
                objects.Interval(dtstart=now,
                                 duration=timedelta(minutes=10),
                                 signal_payload=1)
            ],
                                signal_name='simple',
                                signal_type='level',
                                signal_id='signal001')
        ],
        targets=[{
            'ven_id': 'ven001'
        }])

    events = [
        event_5_far_later, event_4_far_early, event_3_active_no_prio,
        event_2_active_low_prio, event_1_active_high_prio
    ]
    ordered_events = utils.order_events(events)
    assert ordered_events == [
        event_1_active_high_prio, event_2_active_low_prio,
        event_3_active_no_prio, event_4_far_early, event_5_far_later
    ]

    ordered_events = utils.order_events(event_1_active_high_prio)
    assert ordered_events == [event_1_active_high_prio]

    event_1_as_dict = asdict(event_1_active_high_prio)
    ordered_events = utils.order_events(event_1_as_dict)
    assert ordered_events == [event_1_as_dict]
Пример #12
0
    def add_event(self,
                  ven_id,
                  signal_name,
                  signal_type,
                  intervals,
                  callback,
                  targets=None,
                  targets_by_type=None,
                  target=None,
                  market_context="oadr://unknown.context"):
        """
        Convenience method to add an event with a single signal.
        :param str ven_id: The ven_id to whom this event must be delivered.
        :param str signal_name: The OpenADR name of the signal; one of openleadr.objects.SIGNAL_NAME
        :param str signal_type: The OpenADR type of the signal; one of openleadr.objects.SIGNAL_TYPE
        :param str intervals: A list of intervals with a dtstart, duration and payload member.
        :param str callback: A callback function for when your event has been accepted (optIn) or refused (optOut).
        :param list targets: A list of Targets that this Event applies to.
        :param target: A single target for this event.
        :param dict targets_by_type: A dict of targets, grouped by type.
        :param str market_context: A URI for the DR program that this event belongs to.

        If you don't provide a target using any of the three arguments, the target will be set to the given ven_id.
        """
        if self.services['event_service'].polling_method == 'external':
            logger.error(
                "You cannot use the add_event method after you assign your own on_poll "
                "handler. If you use your own on_poll handler, you are responsible for "
                "delivering events from that handler. If you want to use OpenLEADRs "
                "message queuing system, you should not assign an on_poll handler. "
                "Your Event will NOT be added.")
            return
        if not re.match(
                r"^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?",
                market_context):
            raise ValueError("The Market Context must be a valid URI.")
        event_id = utils.generate_id()

        # Figure out the target for this Event
        if target is None and targets is None and targets_by_type is None:
            targets = [{'ven_id': ven_id}]
        elif target is not None:
            targets = [target]
        elif targets_by_type is not None:
            targets = utils.ungroup_targets_by_type(targets_by_type)
        if not isinstance(targets, list):
            targets = [targets]

        event_descriptor = objects.EventDescriptor(
            event_id=event_id,
            modification_number=0,
            market_context=market_context,
            event_status="near",
            created_date_time=datetime.now(timezone.utc))
        event_signal = objects.EventSignal(intervals=intervals,
                                           signal_name=signal_name,
                                           signal_type=signal_type,
                                           signal_id=utils.generate_id(),
                                           targets=targets)
        event = objects.Event(event_descriptor=event_descriptor,
                              event_signals=[event_signal],
                              targets=targets)
        if ven_id not in self.message_queues:
            self.message_queues[ven_id] = asyncio.Queue()
        self.message_queues[ven_id].put_nowait(event)
        self.services['event_service'].pending_events[event_id] = callback
Пример #13
0
    def add_event(self, ven_id, signal_name, signal_type, intervals, callback=None, event_id=None,
                  targets=None, targets_by_type=None, target=None, response_required='always',
                  market_context="oadr://unknown.context", notification_period=None,
                  ramp_up_period=None, recovery_period=None, signal_target_mrid=None):
        """
        Convenience method to add an event with a single signal.

        :param str ven_id: The ven_id to whom this event must be delivered.
        :param str signal_name: The OpenADR name of the signal; one of openleadr.objects.SIGNAL_NAME
        :param str signal_type: The OpenADR type of the signal; one of openleadr.objects.SIGNAL_TYPE
        :param str intervals: A list of intervals with a dtstart, duration and payload member.
        :param str callback: A callback function for when your event has been accepted (optIn) or refused (optOut).
        :param list targets: A list of Targets that this Event applies to.
        :param target: A single target for this event.
        :param dict targets_by_type: A dict of targets, grouped by type.
        :param str market_context: A URI for the DR program that this event belongs to.
        :param timedelta notification_period: The Notification period for the Event's Active Period.
        :param timedelta ramp_up_period: The Ramp Up period for the Event's Active Period.
        :param timedelta recovery_period: The Recovery period for the Event's Active Period.

        If you don't provide a target using any of the three arguments, the target will be set to the given ven_id.
        """
        if self.services['event_service'].polling_method == 'external':
            logger.error("You cannot use the add_event method after you assign your own on_poll "
                         "handler. If you use your own on_poll handler, you are responsible for "
                         "delivering events from that handler. If you want to use OpenLEADRs "
                         "message queuing system, you should not assign an on_poll handler. "
                         "Your Event will NOT be added.")
            return
        if not re.match(r"^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?", market_context):
            raise ValueError("The Market Context must be a valid URI.")
        event_id = event_id or utils.generate_id()

        if response_required not in ('always', 'never'):
            raise ValueError("'response_required' should be either 'always' or 'never'; "
                             f"you provided '{response_required}'.")

        # Figure out the target for this Event
        if target is None and targets is None and targets_by_type is None:
            targets = [{'ven_id': ven_id}]
        elif target is not None:
            targets = [target]
        elif targets_by_type is not None:
            targets = utils.ungroup_targets_by_type(targets_by_type)
        if not isinstance(targets, list):
            targets = [targets]
        if signal_type not in enums.SIGNAL_TYPE.values:
            raise ValueError(f"""The signal_type must be one of '{"', '".join(enums.SIGNAL_TYPE.values)}', """
                             f"""you specified: '{signal_type}'.""")
        if signal_name not in enums.SIGNAL_NAME.values and not signal_name.startswith('x-'):
            raise ValueError(f"""The signal_name must be one of '{"', '".join(enums.SIGNAL_TYPE.values)}', """
                             f"""or it must begin with 'x-'. You specified: '{signal_name}'""")
        if not intervals or not isinstance(intervals, (list, tuple)) or len(intervals) == 0:
            raise ValueError(f"The intervals must be a list of intervals, you specified: {intervals}")

        event_descriptor = objects.EventDescriptor(event_id=event_id,
                                                   modification_number=0,
                                                   market_context=market_context,
                                                   event_status="far",
                                                   created_date_time=datetime.now(timezone.utc))
        event_signal = objects.EventSignal(intervals=intervals,
                                           signal_name=signal_name,
                                           signal_type=signal_type,
                                           signal_id=utils.generate_id())

        # Make sure the intervals carry timezone-aware timestamps
        for interval in intervals:
            if utils.getmember(interval, 'dtstart').tzinfo is None:
                utils.setmember(interval, 'dtstart',
                                utils.getmember(interval, 'dtstart').astimezone(timezone.utc))
                logger.warning("You supplied a naive datetime object to your interval's dtstart. "
                               "This will be interpreted as a timestamp in your local timezone "
                               "and then converted to UTC before sending. Please supply timezone-"
                               "aware timestamps like datetime.datetime.new(timezone.utc) or "
                               "datetime.datetime(..., tzinfo=datetime.timezone.utc)")
        active_period = utils.get_active_period_from_intervals(intervals, False)
        active_period.ramp_up_period = ramp_up_period
        active_period.notification_period = notification_period
        active_period.recovery_period = recovery_period
        event = objects.Event(active_period=active_period,
                              event_descriptor=event_descriptor,
                              event_signals=[event_signal],
                              targets=targets,
                              response_required=response_required)
        self.add_raw_event(ven_id=ven_id, event=event, callback=callback)
        return event_id