diff --git a/python/fusion_engine_client/messages/configuration.py b/python/fusion_engine_client/messages/configuration.py index 83976a1f..3addfe44 100644 --- a/python/fusion_engine_client/messages/configuration.py +++ b/python/fusion_engine_client/messages/configuration.py @@ -5,10 +5,12 @@ from construct import (Struct, Padding, this, Flag, Bytes, Array, Float32l, Float64l, Int64ul, Int32ul, Int16ul, Int8ul, Int64sl, Int32sl, Int16sl, Int8sl, PaddedString) +from ..utils import trace as logging from ..utils.construct_utils import NamedTupleAdapter, AutoEnum, construct_message_to_string from ..utils.enum_utils import IntEnum from .defs import * +_logger = logging.getLogger('point_one.fusion_engine.messages.configuration') ################################################################################ # Device Configuration Support @@ -1390,17 +1392,35 @@ def unpack(self, buffer: bytes, offset: int = 0, message_version: int = MessageP header_data = config_data[:_InterfaceConfigSubmessageConstruct.sizeof()] config_data = config_data[_InterfaceConfigSubmessageConstruct.sizeof():] interface_header = _InterfaceConfigSubmessageConstruct.parse(header_data) - subtype = interface_header.subtype + interface_config_subtype = interface_header.subtype self.interface = interface_header.interface - construct_obj = _conf_gen.INTERFACE_CONFIG_MAP[subtype] + construct_obj = _conf_gen.INTERFACE_CONFIG_MAP.get(interface_config_subtype, None) + if construct_obj is None: + _logger.warning(f'Unsupported interface config subtype. [interface={repr(self.interface)}, ' + f'subtype={interface_config_subtype}]') else: self.interface = None - construct_obj = _conf_gen.CONFIG_MAP[parsed.config_type] + interface_config_subtype = None + construct_obj = _conf_gen.CONFIG_MAP.get(parsed.config_type, None) + if construct_obj is None: + _logger.warning(f'Unsupported interface config type. [type={parsed.config_type}]') - if parsed.config_length_bytes > 0: - self.config_object = construct_obj.parse(config_data) - else: + if construct_obj is None: self.config_object = None + elif len(config_data) < construct_obj.sizeof(): + if self.response != Response.OK and len(config_data) == 0: + # For a non-OK response, they device may omit the parameter altogether. This is normal. + pass + elif self.interface is None: + _logger.error(f'Config response payload too small for expected contents. [type={parsed.config_type}, ' + f'size={len(config_data)} B (expected={construct_obj.sizeof()} B)]') + else: + _logger.error(f'Config response payload too small for expected contents. ' + f'[interface={repr(self.interface)}, subtype={interface_config_subtype}, ' + f'size={len(config_data)} B (expected={construct_obj.sizeof()} B)]') + self.config_object = None + else: + self.config_object = construct_obj.parse(config_data) return parsed._io.tell() diff --git a/src/point_one/fusion_engine/messages/configuration.h b/src/point_one/fusion_engine/messages/configuration.h index 0dbb7715..a690ca8c 100644 --- a/src/point_one/fusion_engine/messages/configuration.h +++ b/src/point_one/fusion_engine/messages/configuration.h @@ -587,6 +587,10 @@ struct P1_ALIGNAS(4) SaveConfigMessage : public MessagePayload { * {MessageHeader, ConfigResponseMessage, uint32_t} * ``` * + * The @ref response field will indicate the status of the requested value. If + * the response is not @ref Response::OK, the parameter value may be omitted and + * @ref config_length_bytes will be set to 0. + * * In response to a @ref GetConfigMessage with an invalid or unsupported @ref * ConfigType, @ref config_type in the resulting @ref ConfigResponseMessage will * be set to @ref ConfigType::INVALID, and @ref response will indicate the @@ -1988,7 +1992,7 @@ struct P1_ALIGNAS(4) InterfaceID { * @brief @ref InterfaceID stream operator. * @ingroup io_interfaces */ -inline p1_ostream& operator<<(p1_ostream& stream, InterfaceID val) { +inline p1_ostream& operator<<(p1_ostream& stream, const InterfaceID& val) { stream << "[type=" << val.type << ", index=" << (int)val.index << "]"; return stream; }