示例#1
0
 def __post_init__(self):
     if self.targets is None and self.targets_by_type is None:
         return
     elif self.targets_by_type is None:
         list_of_targets = [asdict(target) if is_dataclass(target) else target for target in self.targets]
         self.targets_by_type = group_targets_by_type(list_of_targets)
     elif self.targets is None:
         self.targets = [Target(**target) for target in ungroup_targets_by_type(self.targets_by_type)]
     elif self.targets is not None and self.targets_by_type is not None:
         list_of_targets = [asdict(target) if is_dataclass(target) else target for target in self.targets]
         if group_targets_by_type(list_of_targets) != self.targets_by_type:
             raise ValueError("You assigned both 'targets' and 'targets_by_type' in your event, "
                              "but the two were not consistent with each other. "
                              f"You supplied 'targets' = {self.targets} and "
                              f"'targets_by_type' = {self.targets_by_type}")
示例#2
0
 def __post_init__(self):
     if self.active_period is None:
         dtstart = min([
             i['dtstart'] if isinstance(i, dict) else i.dtstart
             for s in self.event_signals for i in s.intervals
         ])
         duration = max([
             i['dtstart'] + i['duration']
             if isinstance(i, dict) else i.dtstart + i.duration
             for s in self.event_signals for i in s.intervals
         ]) - dtstart
         self.active_period = ActivePeriod(dtstart=dtstart,
                                           duration=duration)
     if self.targets is None and self.targets_by_type is None:
         raise ValueError(
             "You must supply either 'targets' or 'targets_by_type'.")
     elif self.targets_by_type is None:
         list_of_targets = [
             asdict(target) if is_dataclass(target) else target
             for target in self.targets
         ]
         self.targets_by_type = utils.group_targets_by_type(list_of_targets)
     elif self.targets is None:
         self.targets = [
             Target(**target) for target in utils.ungroup_targets_by_type(
                 self.targets_by_type)
         ]
     elif self.targets is not None and self.targets_by_type is not None:
         list_of_targets = [
             asdict(target) if is_dataclass(target) else target
             for target in self.targets
         ]
         if utils.group_targets_by_type(
                 list_of_targets) != self.targets_by_type:
             raise ValueError(
                 "You assigned both 'targets' and 'targets_by_type' in your event, "
                 "but the two were not consistent with each other. "
                 f"You supplied 'targets' = {self.targets} and "
                 f"'targets_by_type' = {self.targets_by_type}")
     # Set the event status
     self.event_descriptor.event_status = utils.determine_event_status(
         self.active_period)
示例#3
0
 def __post_init__(self):
     if self.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: '{self.signal_type}'.""")
     if self.signal_name not in enums.SIGNAL_NAME.values and not self.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: '{self.signal_name}'"""
         )
     if self.targets is None and self.targets_by_type is None:
         return
     elif self.targets_by_type is None:
         list_of_targets = [
             asdict(target) if is_dataclass(target) else target
             for target in self.targets
         ]
         targets_by_type = utils.group_targets_by_type(list_of_targets)
         if len(targets_by_type) > 1:
             raise ValueError(
                 "In OpenADR, the EventSignal target may only be of type endDeviceAsset. "
                 f"You provided types: '{', '.join(targets_by_type)}'")
     elif self.targets is None:
         self.targets = [
             Target(**target) for target in utils.ungroup_targets_by_type(
                 self.targets_by_type)
         ]
     elif self.targets is not None and self.targets_by_type is not None:
         list_of_targets = [
             asdict(target) if is_dataclass(target) else target
             for target in self.targets
         ]
         if utils.group_targets_by_type(
                 list_of_targets) != self.targets_by_type:
             raise ValueError(
                 "You assigned both 'targets' and 'targets_by_type' in your event, "
                 "but the two were not consistent with each other. "
                 f"You supplied 'targets' = {self.targets} and "
                 f"'targets_by_type' = {self.targets_by_type}")
def create_dummy_event(ven_id):
    """
    Creates a dummy event
    """
    now = datetime.now(timezone.utc)
    event_id = generate_id()
    active_period = {"dtstart": (now + timedelta(minutes=1)),
                     "duration": timedelta(minutes=9)}
    event_descriptor = {"event_id": event_id,
                        "modification_number": 1,
                        "modification_date_time": now,
                        "priority": 1,
                        "market_context": "http://MarketContext1",
                        "created_date_time": now,
                        "event_status": "near",
                        "test_event": False,
                        "vtn_comment": "This is an event"}
    event_signals = [{"intervals": [{"duration": timedelta(minutes=1), "uid": 0, "signal_payload": 8.0},
                                    {"duration": timedelta(minutes=1), "uid": 1, "signal_payload": 10.0},
                                    {"duration": timedelta(minutes=1), "uid": 2, "signal_payload": 12.0},
                                    {"duration": timedelta(minutes=1), "uid": 3, "signal_payload": 14.0},
                                    {"duration": timedelta(minutes=1), "uid": 4, "signal_payload": 16.0},
                                    {"duration": timedelta(minutes=1), "uid": 5, "signal_payload": 18.0},
                                    {"duration": timedelta(minutes=1), "uid": 6, "signal_payload": 20.0},
                                    {"duration": timedelta(minutes=1), "uid": 7, "signal_payload": 10.0},
                                    {"duration": timedelta(minutes=1), "uid": 8, "signal_payload": 20.0}],
                    "signal_name": "LOAD_CONTROL",
                    "signal_type": "x-loadControlCapacity",
                    "signal_id": generate_id(),
                    "measurement": {"name": "voltage",
                                    "description": "Voltage",
                                    "unit": "V",
                                    "scale": "none"},
                    "current_value": 0.0}]
    event_targets = [{"ven_id": 'VEN001'}, {"ven_id": 'VEN002'}]
    event = {'active_period': active_period,
             'event_descriptor': event_descriptor,
             'event_signals': event_signals,
             'targets': event_targets,
             'targets_by_type': group_targets_by_type(event_targets),
             'response_required': 'always'}
    return event
示例#5
0
def _preflight_oadrDistributeEvent(message_payload):
    if 'parse_duration' not in globals():
        from .utils import parse_duration
    # Check that the total event_duration matches the sum of the interval durations (rule 8)
    for event in message_payload['events']:
        active_period_duration = event['active_period']['duration']
        signal_durations = []
        for signal in event['event_signals']:
            signal_durations.append(
                sum([
                    parse_duration(i['duration']) for i in signal['intervals']
                ], timedelta(seconds=0)))

        if not all([d == active_period_duration for d in signal_durations]):
            if not all([d == signal_durations[0] for d in signal_durations]):
                raise ValueError(
                    "The different EventSignals have different total durations. "
                    "Please correct this.")
            else:
                logger.warning(
                    f"The active_period duration for event "
                    f"{event['event_descriptor']['event_id']} ({active_period_duration})"
                    f" differs from the sum of the interval's durations "
                    f"({signal_durations[0]}). The active_period duration has been "
                    f"adjusted to ({signal_durations[0]}).")
                event['active_period']['duration'] = signal_durations[0]

    # Check that payload values with signal name SIMPLE are constricted (rule 9)
    for event in message_payload['events']:
        for event_signal in event['event_signals']:
            if event_signal['signal_name'] == "SIMPLE":
                for interval in event_signal['intervals']:
                    if interval['signal_payload'] not in (0, 1, 2, 3):
                        raise ValueError(
                            "Payload Values used with Signal Name SIMPLE "
                            "must be one of 0, 1, 2 or 3")

    # Check that the current_value is 0 for SIMPLE events that are not yet active (rule 14)
    for event in message_payload['events']:
        for event_signal in event['event_signals']:
            if 'current_value' in event_signal and event_signal[
                    'current_value'] != 0:
                if event_signal['signal_name'] == "SIMPLE" \
                        and event['event_descriptor']['event_status'] != "ACTIVE":
                    logger.warning("The current_value for a SIMPLE event "
                                   "that is not yet active must be 0. "
                                   "This will be corrected.")
                    event_signal['current_value'] = 0

    # Check that there is a valid oadrResponseRequired value for each Event
    for event in message_payload['events']:
        if 'response_required' not in event:
            event['response_required'] = 'always'
        elif event['response_required'] not in ('never', 'always'):
            logger.warning(
                f"The response_required property in an Event "
                f"should be 'never' or 'always', not "
                f"{event['response_required']}. Changing to 'always'.")
            event['response_required'] = 'always'

    # Check that there is a valid oadrResponseRequired value for each Event
    for event in message_payload['events']:
        if 'created_date_time' not in event['event_descriptor'] \
                or not event['event_descriptor']['created_date_time']:
            event['event_descriptor']['created_date_time'] = datetime.now(
                timezone.utc)

    # Check that the target designations are correct and consistent
    for event in message_payload['events']:
        if 'targets' in event and 'targets_by_type' in event:
            if utils.group_targets_by_type(
                    event['targets']) != event['targets_by_type']:
                raise ValueError(
                    "You assigned both 'targets' and 'targets_by_type' in your event, "
                    "but the two were not consistent with each other. "
                    f"You supplied 'targets' = {event['targets']} and "
                    f"'targets_by_type' = {event['targets_by_type']}")
        elif 'targets_by_type' in event and 'targets' not in event:
            event['targets'] = utils.ungroup_targets_by_type(
                event['targets_by_type'])
('oadrCreatedPartyRegistration', dict(response={'response_code': 200, 'response_description': 'OK', 'request_id': generate_id()},
                                             registration_id=generate_id(),
                                             ven_id='123ABC',
                                             profiles=[{'profile_name': '2.0b',
                                                        'transports': [{'transport_name': 'simpleHttp'}]}],
                                             vtn_id='VTN123')),
('oadrCreatedReport', dict(response={'response_code': 200, 'response_description': 'OK', 'request_id': generate_id()}, pending_reports=[{'request_id': generate_id()}, {'request_id': generate_id()}])),
('oadrCreateOpt', dict(opt_id=generate_id(),
                              opt_type='optIn',
                              opt_reason='participating',
                              created_date_time=datetime.now(timezone.utc),
                              request_id=generate_id(),
                              event_id=generate_id(),
                              modification_number=1,
                              targets=[{'ven_id': '123ABC'}],
                              targets_by_type=group_targets_by_type([{'ven_id': '123ABC'}]),
                              ven_id='VEN123')),
('oadrCreatePartyRegistration', dict(request_id=generate_id(), ven_id='123ABC', profile_name='2.0b', transport_name='simpleHttp', transport_address='http://localhost', report_only=False, xml_signature=False, ven_name='test', http_pull_model=True)),
('oadrCreateReport', dict(request_id=generate_id(),
                                 ven_id='123ABC',
                                 report_requests=[{'report_request_id': 'd2b7bade5f',
                                                  'report_specifier': {'granularity': timedelta(seconds=900),
                                                                       'report_back_duration': timedelta(seconds=900),
                                                                       'report_interval': {'dtstart': datetime(2019, 11, 19, 11, 0, 18, 672768, tzinfo=timezone.utc),
                                                                                           'duration': timedelta(seconds=7200)},
                                                                       'report_specifier_id': '9c8bdc00e7',
                                                                       'specifier_payloads': [{'r_id': 'd6e2e07485',
                                                                                             'reading_type': 'Direct Read'}]}}])),
('oadrDistributeEvent', dict(request_id=generate_id(), response={'request_id': 123, 'response_code': 200, 'response_description': 'OK'}, events=[create_dummy_event(ven_id='123ABC')], vtn_id='VTN123')),
('oadrDistributeEvent', dict(request_id=generate_id(), response={'request_id': 123, 'response_code': 200, 'response_description': 'OK'}, events=[create_dummy_event(ven_id='123ABC'), create_dummy_event(ven_id='123ABC')], vtn_id='VTN123')),
('oadrPoll', dict(ven_id='123ABC')),