Пример #1
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)
Пример #2
0
 async def _perform_request(self, service, message):
     await self._ensure_client_session()
     logger.debug(f"Client is sending {message}")
     url = f"{self.vtn_url}/{service}"
     try:
         async with self.client_session.post(url, data=message) as req:
             content = await req.read()
             if req.status != HTTPStatus.OK:
                 logger.warning(
                     f"Non-OK status {req.status} when performing a request to {url} "
                     f"with data {message}: {req.status} {content.decode('utf-8')}"
                 )
                 return None, {}
             logger.debug(content.decode('utf-8'))
     except aiohttp.client_exceptions.ClientConnectorError as err:
         # Could not connect to server
         logger.error(
             f"Could not connect to server with URL {self.vtn_url}:")
         logger.error(f"{err.__class__.__name__}: {str(err)}")
         return None, {}
     except Exception as err:
         logger.error(f"Request error {err.__class__.__name__}:{err}")
         return None, {}
     if len(content) == 0:
         return None
     try:
         tree = validate_xml_schema(content)
         if self.vtn_fingerprint:
             validate_xml_signature(tree)
         message_type, message_payload = parse_message(content)
     except XMLSyntaxError as err:
         logger.warning(
             f"Incoming message did not pass XML schema validation: {err}")
         return None, {}
     except errors.FingerprintMismatch as err:
         logger.warning(err)
         return None, {}
     except InvalidSignature:
         logger.warning("Incoming message had invalid signature, ignoring.")
         return None, {}
     except Exception as err:
         logger.error(
             f"The incoming message could not be parsed or validated: {err}"
         )
         return None, {}
     if 'response' in message_payload and 'response_code' in message_payload[
             'response']:
         if message_payload['response']['response_code'] != 200:
             logger.warning(
                 "We got a non-OK OpenADR response from the server: "
                 f"{message_payload['response']['response_code']}: "
                 f"{message_payload['response']['response_description']}")
     return message_type, message_payload
def test_message(message_type, data):
    # file = open('representations.rst', 'a')
    # print(f".. _{message_type}:", file=file)
    # print("", file=file)
    # print(message_type, file=file)
    # print("="*len(message_type), file=file)
    # print("", file=file)
    # print("OpenADR payload:", file=file)
    # print("", file=file)
    # print(".. code-block:: xml", file=file)
    # print("    ", file=file)
    message = create_message(message_type, **data)
    # message = re.sub(r"\s\s+","",message)
    # message = message.replace("\n","")
    # xml_lines = etree.tostring(etree.fromstring(message.replace('\n', '').encode('utf-8')), pretty_print=True).decode('utf-8').splitlines()
    # for line in xml_lines:
    #      print("    " + line, file=file)
    # print("", file=file)
    # print("OpenLEADR representation:", file=file)
    # print("    ", file=file)
    # print(".. code-block:: python3", file=file)
    # print("    ", file=file)
    validate_xml_schema(message)
    parsed = parse_message(message)[1]
    # dict_lines = pformat(parsed).splitlines()
    # for line in dict_lines:
    #     print("    " + line, file=file)
    # print("", file=file)
    # print("", file=file)
    if message_type == 'oadrRegisterReport':
        for report in data['reports']:
            for rd in report['report_descriptions']:
                if 'measurement' in rd:
                    rd['measurement'].pop('ns')
    if message_type == 'oadrDistributeEvent':
        for event in data['events']:
            for signal in event['event_signals']:
                if 'measurement' in signal:
                    signal['measurement'].pop('ns')
    assert parsed == data
Пример #4
0
    async def handler(self, request):
        """
        Handle all incoming POST requests.
        """
        try:
            # Check the Content-Type header
            content_type = request.headers.get('content-type', '')
            if not content_type.lower().startswith("application/xml"):
                raise errors.HTTPError(status=HTTPStatus.BAD_REQUEST,
                                       description="The Content-Type header must be application/xml; "
                                                            f"you provided {request.headers.get('content-type', '')}")
            content = await request.read()
            hooks.call('before_parse', content)

            # Validate the message to the XML Schema
            message_tree = validate_xml_schema(content)

            # Parse the message to a type and payload dict
            message_type, message_payload = parse_message(content)

            if message_type == 'oadrResponse':
                raise errors.SendEmptyHTTPResponse()

            if 'vtn_id' in message_payload \
                    and message_payload['vtn_id'] is not None \
                    and message_payload['vtn_id'] != self.vtn_id:
                raise errors.InvalidIdError(f"The supplied vtnID is invalid. It should be '{self.vtn_id}', "
                                            f"you supplied {message_payload['vtn_id']}.")

            # Check if we know this VEN, ask for reregistration otherwise
            if message_type not in ('oadrCreatePartyRegistration', 'oadrQueryRegistration') \
                    and 'ven_id' in message_payload and hasattr(self, 'ven_lookup'):
                result = await utils.await_if_required(self.ven_lookup(ven_id=message_payload['ven_id']))
                if result is None or result.get('registration_id', None) is None:
                    raise errors.RequestReregistration(message_payload['ven_id'])

            # Authenticate the message
            if request.secure and 'ven_id' in message_payload:
                if hasattr(self, 'fingerprint_lookup'):
                    await authenticate_message(request, message_tree, message_payload,
                                               fingerprint_lookup=self.fingerprint_lookup)
                elif hasattr(self, 'ven_lookup'):
                    await authenticate_message(request, message_tree, message_payload,
                                               ven_lookup=self.ven_lookup)
                else:
                    logger.error("Could not authenticate this VEN because "
                                 "you did not provide a 'ven_lookup' function. Please see "
                                 "https://openleadr.org/docs/server.html#signing-messages for info.")

            # Pass the message off to the handler and get the response type and payload
            try:
                # Add the request fingerprint to the message so that the handler can check for it.
                if request.secure and message_type == 'oadrCreatePartyRegistration':
                    message_payload['fingerprint'] = utils.get_cert_fingerprint_from_request(request)
                response_type, response_payload = await self.handle_message(message_type,
                                                                            message_payload)
            except Exception as err:
                logger.error("An exception occurred during the execution of your "
                             f"{self.__class__.__name__} handler: "
                             f"{err.__class__.__name__}: {err}")
                raise err

            if 'response' not in response_payload:
                response_payload['response'] = {'response_code': 200,
                                                'response_description': 'OK',
                                                'request_id': message_payload.get('request_id')}
            response_payload['vtn_id'] = self.vtn_id
            if 'ven_id' not in response_payload:
                response_payload['ven_id'] = message_payload.get('ven_id')
        except errors.RequestReregistration as err:
            response_type = 'oadrRequestReregistration'
            response_payload = {'ven_id': err.ven_id}
            msg = self._create_message(response_type, **response_payload)
            response = web.Response(text=msg,
                                    status=HTTPStatus.OK,
                                    content_type='application/xml')
        except errors.SendEmptyHTTPResponse:
            response = web.Response(text='',
                                    status=HTTPStatus.OK,
                                    content_type='application/xml')
        except errors.ProtocolError as err:
            # In case of an OpenADR error, return a valid OpenADR message
            response_type, response_payload = self.error_response(message_type,
                                                                  err.response_code,
                                                                  err.response_description)
            msg = self._create_message(response_type, **response_payload)
            response = web.Response(text=msg,
                                    status=HTTPStatus.OK,
                                    content_type='application/xml')
        except errors.HTTPError as err:
            # If we throw a http-related error, deal with it here
            response = web.Response(text=err.response_description,
                                    status=err.response_code)
        except XMLSyntaxError as err:
            logger.warning(f"XML schema validation of incoming message failed: {err}.")
            response = web.Response(text=f'XML failed validation: {err}',
                                    status=HTTPStatus.BAD_REQUEST)
        except errors.FingerprintMismatch as err:
            logger.warning(err)
            response = web.Response(text=str(err),
                                    status=HTTPStatus.FORBIDDEN)
        except InvalidSignature:
            logger.warning("Incoming message had invalid signature, ignoring.")
            response = web.Response(text='Invalid Signature',
                                    status=HTTPStatus.FORBIDDEN)
        except Exception as err:
            # In case of some other error, return a HTTP 500
            logger.error(f"The VTN server encountered an error: {err.__class__.__name__}: {err}")
            response = web.Response(status=HTTPStatus.INTERNAL_SERVER_ERROR)
        else:
            # We've successfully handled this message
            msg = self._create_message(response_type, **response_payload)
            response = web.Response(text=msg,
                                    status=HTTPStatus.OK,
                                    content_type='application/xml')
        hooks.call('before_respond', response.text)
        return response
Пример #5
0
def test_message(msg_type, payload):
    message = create_message(msg_type, **payload)
    print(message)
    tree = validate_xml_schema(ensure_bytes(message))