Exemple #1
0
 def deserialize(cls, data):
     message = openxc_pb2.VehicleMessage()
     try:
         message.ParseFromString(data)
     except google.protobuf.message.DecodeError as e:
         pass
     except UnicodeDecodeError as e:
         LOG.warn("Unable to parse protobuf: %s", e)
     else:
         return cls._protobuf_to_dict(message)
Exemple #2
0
 def _dict_to_protobuf(cls, data):
     message = openxc_pb2.VehicleMessage()
     if 'command' in data:
         cls._build_control_command_message(data, message)
     elif 'command_response' in data:
         cls._build_command_response_message(data, message)
     elif 'id' in data and 'data' in data:
         cls._build_can_message(data, message)
     elif 'id' in data and 'bus' in data and 'mode' in data:
         cls._build_diagnostic_message(data, message)
     elif 'name' in data and 'value' in data:
         cls._build_simple_message(data, message)
     return message
Exemple #3
0
    def _parse_protobuf_message(self, message_buffer):
        parsed_message = None
        remainder = message_buffer
        message_data = ""

        # 1. decode a varint from the top of the stream
        # 2. using that as the length, if there's enough in the buffer, try and
        #       decode try and decode a VehicleMessage after the varint
        # 3. if it worked, great, we're oriented in the stream - continue
        # 4. if either couldn't be parsed, skip to the next byte and repeat
        while parsed_message is None and len(message_buffer) > 1:
            message_length, message_start = _DecodeVarint(message_buffer, 0)
            # sanity check to make sure we didn't parse some huge number that's
            # clearly not the length prefix
            if message_length > self.MAX_PROTOBUF_MESSAGE_LENGTH:
                message_buffer = message_buffer[1:]
                continue

            if message_start + message_length >= len(message_buffer):
                break

            message_data = message_buffer[message_start:message_start +
                    message_length]
            remainder = message_buffer[message_start + message_length:]

            message = openxc_pb2.VehicleMessage()
            try:
                message.ParseFromString(message_data)
            except google.protobuf.message.DecodeError as e:
                message_buffer = message_buffer[1:]
            except UnicodeDecodeError as e:
                LOG.warn("Unable to parse protobuf: %s", e)
            else:
                parsed_message = self._protobuf_to_dict(message)
                if parsed_message is None:
                    message_buffer = message_buffer[1:]

        bytes_received = 0
        if parsed_message is not None:
            bytes_received = len(message_data)
        return parsed_message, remainder, bytes_received
Exemple #4
0
    def _dict_to_protobuf(cls, data):
        message = openxc_pb2.VehicleMessage()
        if 'command' in data:
            command_name = data['command']
            message.type = openxc_pb2.VehicleMessage.CONTROL_COMMAND
            message.control_command.type = cls._command_string_to_protobuf(command_name)
            if message.control_command.type == openxc_pb2.ControlCommand.PASSTHROUGH:
                message.control_command.passthrough_mode_request.bus = data['bus']
                message.control_command.passthrough_mode_request.enabled = data['enabled']
            elif message.control_command.type == openxc_pb2.ControlCommand.ACCEPTANCE_FILTER_BYPASS:
                message.control_command.acceptance_filter_bypass_command.bus = data['bus']
                message.control_command.acceptance_filter_bypass_command.bypass = data['bypass']
            elif message.control_command.type == openxc_pb2.ControlCommand.PREDEFINED_OBD2_REQUESTS:
                message.control_command.predefined_obd2_requests_command.enabled = data['enabled']
            elif message.control_command.type == openxc_pb2.ControlCommand.PAYLOAD_FORMAT:
                if data['format'] == "json":
                    message.control_command.payload_format_command.format = openxc_pb2.PayloadFormatCommand.JSON
                elif data['format'] == "protobuf":
                    message.control_command.payload_format_command.format = openxc_pb2.PayloadFormatCommand.PROTOBUF
            elif message.control_command.type == openxc_pb2.ControlCommand.DIAGNOSTIC:
                request_command = message.control_command.diagnostic_request
                action = data['action']
                if action == "add":
                    request_command.action = openxc_pb2.DiagnosticControlCommand.ADD
                elif action == "cancel":
                    request_command.action = openxc_pb2.DiagnosticControlCommand.CANCEL
                request = request_command.request
                request_data = data['request']
                request.bus = request_data['bus']
                request.message_id = request_data['id']
                request.mode = request_data['mode']
                if 'frequency' in request_data:
                    request.frequency = request_data['frequency']
                if 'name' in request_data:
                    request.name = request_data['name']
                if 'multiple_responses' in request_data:
                    request.multiple_responses = request_data['multiple_responses']
                if 'pid' in request_data:
                    request.pid = request_data['pid']
                if 'payload' in request_data:
                    request.payload = binascii.unhexlify(request_data['payload'].split('0x')[1])
        elif 'command_response' in data:
            message.type = openxc_pb2.VehicleMessage.COMMAND_RESPONSE
            message.command_response.type = cls._command_string_to_protobuf(data['command_response'])
            if 'message' in data:
                message.command_response.message = data['message']
            message.command_response.status = data['status']
        elif 'id' in data and 'data' in data:
            message.type = openxc_pb2.VehicleMessage.CAN
            if 'bus' in data:
                message.can_message.bus = data['bus']
            if 'frame_format' in data:
                if data['frame_format'] == "standard":
                    message.can_message.frame_format = openxc_pb2.RawMessage.STANDARD
                elif data['frame_format'] == "extended":
                    message.can_message.frame_format = openxc_pb2.RawMessage.EXTENDED
            message.can_message.id = data['id']
            message.can_message.data = binascii.unhexlify(data['data'].split('0x')[1])
        elif 'id' in data and 'bus' in data and 'mode' in data:
            message.type = openxc_pb2.VehicleMessage.DIAGNOSTIC
            response = message.diagnostic_response
            response.bus = data['bus']
            response.message_id = data['id']
            response.mode = data['mode']
            if 'pid' in data:
                response.pid = data['pid']
            if 'success' in data:
                response.success = data['success']
            if 'negative_response_code' in data:
                response.negative_response_code = data['negative_response_code']
            if 'value' in data:
                response.value = data['value']
            if 'payload' in data:
                response.payload = binascii.unhexlify(data['payload'].split('0x')[1])
        elif 'name' in data and 'value' in data:
            message.type = openxc_pb2.VehicleMessage.SIMPLE
            message.simple_message.name = data['name']
            value = data['value']
            if isinstance(value, bool):
                message.simple_message.value.type = openxc_pb2.DynamicField.BOOL
                message.simple_message.value.boolean_value = value
            elif isinstance(value, str):
                message.simple_message.value.type = openxc_pb2.DynamicField.STRING
                message.simple_message.value.string_value = value
            elif isinstance(value, numbers.Number):
                message.simple_message.value.type = openxc_pb2.DynamicField.NUM
                message.simple_message.value.numeric_value = value

            if 'event' in data:
                event = data['event']
                # TODO holy repeated code, batman. this will be easier to DRY
                # when https://github.com/openxc/openxc-message-format/issues/19
                # is resolved
                if isinstance(event, bool):
                    message.simple_message.event.type = openxc_pb2.DynamicField.BOOL
                    message.simple_message.event.boolean_value = event
                elif isinstance(event, str):
                    message.simple_message.event.type = openxc_pb2.DynamicField.STRING
                    message.simple_message.event.string_value = event
                elif isinstance(event, numbers.Number):
                    message.simple_message.event.type = openxc_pb2.DynamicField.NUM
                    message.simple_message.event.numeric_value = event
        return message