// Generated by tools/generate_can_semantic_protocol.py; do not edit. #pragma once #include #include #include #include #include #include #include namespace cognitive_agent_can_protocol { inline constexpr std::string_view kProtocolVersion = "1.0.0"; inline constexpr std::string_view kProtocolSourceSha256 = "cfb7a7eb28d14a82da70d44efece7f045a7a87a4cd549d7537dc00438c297e6e"; struct FrameMetadata { std::string_view rule_id; std::string_view key; unsigned frame_id; std::string_view format; bool brs; unsigned dlc; std::string_view template_kind; std::string_view base_payload_hex; std::string_view template_json; std::string_view repeat_kind; unsigned repeat_count; unsigned period_ms; std::string_view feedback_ids_csv; std::string_view feedback_policy; }; struct RuleMetadata { std::string_view id; int channel; std::string_view domain; std::string_view capabilities_csv; std::string_view help; std::string_view special_handler; }; struct StaticPayload { std::string_view rule_id; std::string_view frame_key; std::string_view selector; std::string_view payload_hex; }; inline constexpr std::array kFrames{{ FrameMetadata{"can0.seat.position", "move", 768, "classic_can", false, 8, "can0_motion_fields", "00 10 00 00 00 00 00 00", "{\"base_payload_hex\":\"00 10 00 00 00 00 00 00\",\"fields\":{\"motor\":{\"bit_length\":2,\"start_bit\":8,\"values\":{\"backrest\":2,\"basin\":1,\"height\":1,\"horizontal\":0,\"legrest\":3,\"longitudinal\":0}},\"opcode\":{\"absolute\":1,\"bit_length\":8,\"home_zero\":11,\"start_bit\":0},\"param_a\":{\"bit_length\":16,\"home_key\":19282,\"scale\":100,\"start_bit\":32},\"param_b\":{\"absolute_timeout_ms\":30000,\"bit_length\":16,\"home_timeout_s\":120,\"start_bit\":48},\"protocol_version\":{\"bit_length\":2,\"constant\":1,\"start_bit\":12},\"sequence\":{\"bit_length\":16,\"runtime_allocated\":true,\"start_bit\":16}}}", "fixed", 1, 0, "0x301,0x302", "ack_then_motor_terminal"}, FrameMetadata{"can0.seat.relative", "move", 768, "classic_can", false, 8, "can0_relative_closed_loop_or_timed_fallback", "03 10 00 00 00 00 00 00", "{\"base_payload_hex\":\"03 10 00 00 00 00 00 00\",\"fields\":{\"closed_loop_opcode\":1,\"direction_values\":{\"decrease\":2,\"increase\":1},\"timed_fallback_max_delta_pct\":15,\"timed_fallback_opcode\":3}}", "fixed", 1, 0, "0x301,0x302", "fresh_position_then_ack_then_motor_terminal"}, FrameMetadata{"can0.seat.thermal", "thermal_mode", 974, "classic_can", false, 8, "can0_heating_mode_optional", "10 00 00 00 00 00 00 00", "{\"base_payload_hex\":\"10 00 00 00 00 00 00 00\",\"optional_when\":\"heating_on\"}", "fixed", 1, 0, "0x4FA", ""}, FrameMetadata{"can0.seat.thermal", "thermal_control", 670, "classic_can", false, 8, "can0_thermal_bit_fields", "00 00 00 00 00 00 00 00", "{\"base_payload_hex\":\"00 00 00 00 00 00 00 00\"}", "fixed", 1, 0, "0x4FA", "thermal_state_match"}, FrameMetadata{"can0.seat.dynamic", "dynamic", 768, "classic_can", false, 8, "can0_dynamic_fields", "0E 10 00 00 00 00 00 00", "{\"base_payload_hex\":\"0E 10 00 00 00 00 00 00\",\"fields\":{\"mode_values\":{\"cradle\":2,\"rocking-horse\":1,\"stop\":0},\"start_opcode\":14,\"stop_opcode\":15}}", "fixed", 1, 0, "0x301,0x306", "ack_then_dynamic_state"}, FrameMetadata{"can1.door.rear_lock", "command", 811, "classic_can", false, 8, "bit_fields", "0A 00 00 00 00 00 00 00", "{\"base_payload_hex\":\"0A 00 00 00 00 00 00 00\",\"fields\":{\"state\":{\"bit_length\":2,\"start_bit\":14,\"values\":{\"lock\":1,\"unlock\":2}}}}", "fixed", 1, 0, "0x407", "rear_lock_state_match"}, FrameMetadata{"can1.window.motion", "command", 1073, "can_fd", true, 8, "window_motion_bit_fields", "00 00 00 00 00 00 00 00", "{\"base_payload_hex\":\"00 00 00 00 00 00 00 00\",\"fields\":{\"motion_values\":{\"close\":2,\"open\":1,\"stop\":3},\"starts\":[48,56,51,59]}}", "fixed", 3, 100, "0x388", "window_state_match"}, FrameMetadata{"can1.window.position", "command", 1073, "can_fd", true, 8, "window_feedback_closed_loop", "00 00 00 00 00 00 00 00", "{\"base_payload_hex\":\"00 00 00 00 00 00 00 00\"}", "special", 1, 0, "0x388", "fresh_position_then_motion_then_stop"}, FrameMetadata{"can1.climate.power", "command", 478, "classic_can", false, 8, "bit_fields", "00 00 00 00 00 00 00 00", "{\"base_payload_hex\":\"00 00 00 00 00 00 00 00\",\"fields\":{\"state\":{\"bit_length\":2,\"start_bit\":28,\"values\":{\"off\":2,\"on\":1}}}}", "fixed", 3, 100, "0x404", "climate_power_match"}, FrameMetadata{"can1.climate.fan", "command", 478, "classic_can", false, 8, "bit_fields", "00 00 00 00 00 00 00 00", "{\"base_payload_hex\":\"00 00 00 00 00 00 00 00\",\"fields\":{\"level\":{\"bit_length\":4,\"start_bit\":4}}}", "fixed", 3, 100, "0x404", "climate_fan_match"}, FrameMetadata{"can1.climate.mode", "command", 478, "classic_can", false, 8, "bit_fields", "00 00 00 00 00 00 00 00", "{\"base_payload_hex\":\"00 00 00 00 00 00 00 00\",\"fields\":{\"mode\":{\"bit_length\":4,\"start_bit\":0,\"values\":{\"defrost\":5,\"face\":1,\"face-defrost\":7,\"face-feet\":2,\"face-feet-defrost\":6,\"feet\":3,\"feet-defrost\":4}}}}", "fixed", 3, 100, "0x404", "climate_mode_match"}, FrameMetadata{"can1.climate.temperature", "front", 478, "classic_can", false, 8, "climate_temperature", "00 00 00 00 00 00 00 00", "{\"base_payload_hex\":\"00 00 00 00 00 00 00 00\",\"fields\":{\"starts\":{\"driver\":32,\"passenger\":40}}}", "fixed", 3, 100, "0x404", "climate_temperature_match"}, FrameMetadata{"can1.climate.temperature", "rear", 478, "classic_can", false, 8, "climate_temperature", "00 00 00 00 00 00 00 00", "{\"base_payload_hex\":\"00 00 00 00 00 00 00 00\",\"fields\":{\"starts\":{\"rear\":48}}}", "fixed", 1, 100, "0x404", "climate_temperature_match"}, FrameMetadata{"can1.climate.control", "command", 478, "classic_can", false, 8, "bit_fields", "00 00 00 00 00 00 00 00", "{\"base_payload_hex\":\"00 00 00 00 00 00 00 00\",\"fields\":{\"mode\":{\"bit_length\":2,\"start_bit\":16,\"values\":{\"auto\":2,\"manual\":1}}}}", "fixed", 3, 100, "0x404", "climate_control_match"}, FrameMetadata{"can1.climate.cycle", "command", 478, "classic_can", false, 8, "bit_fields", "00 00 00 00 00 00 00 00", "{\"base_payload_hex\":\"00 00 00 00 00 00 00 00\",\"fields\":{\"mode\":{\"bit_length\":2,\"start_bit\":19,\"values\":{\"external\":2,\"internal\":1}}}}", "fixed", 3, 100, "0x404", "climate_cycle_match"}, FrameMetadata{"can1.outlet.switch", "command", 1263, "can_fd", true, 8, "static_variant", "00 00 00 00 00 00 00 00", "{\"base_payload_hex\":\"00 00 00 00 00 00 00 00\",\"payload_variants\":{\"driver-left:close\":\"02 FF FF FF FF 02 FF FF\",\"driver-left:open\":\"02 FF FF FF FF 01 FF FF\",\"driver-right:close\":\"02 FF FF FF FF 08 FF FF\",\"driver-right:open\":\"02 FF FF FF FF 04 FF FF\",\"passenger-left:close\":\"03 FF FF FF FF 02 00 00\",\"passenger-left:open\":\"03 FF FF FF FF 01 00 00\",\"passenger-right:close\":\"03 FF FF FF FF 08 00 00\",\"passenger-right:open\":\"03 FF FF FF FF 04 00 00\"}}", "fixed", 3, 100, "0x4BB,0x37B", "outlet_switch_state_match"}, FrameMetadata{"can1.outlet.percent", "command", 1263, "can_fd", true, 8, "outlet_calibrated_coordinates", "00 FF FF FF FF 00 00 00", "{\"base_payload_hex\":\"00 FF FF FF FF 00 00 00\"}", "fixed", 3, 100, "0x2F5,0x37B", "outlet_position_match"}, FrameMetadata{"can1.outlet.position", "command", 1263, "can_fd", true, 8, "outlet_calibrated_coordinates", "00 FF FF FF FF 00 00 00", "{\"base_payload_hex\":\"00 FF FF FF FF 00 00 00\"}", "fixed", 3, 100, "0x2F5,0x37B", "outlet_position_match"}, FrameMetadata{"can1.seat.driver_thermal", "command", 1073, "can_fd", true, 8, "driver_seat_thermal", "00 00 00 00 00 00 00 00", "{\"base_payload_hex\":\"00 00 00 00 00 00 00 00\"}", "fixed", 3, 100, "0x4FA", "driver_seat_thermal_match"}, FrameMetadata{"can1.seat.driver_massage", "command", 1217, "can_fd", true, 8, "driver_seat_massage", "12 00 00 00 00 00 00 00", "{\"base_payload_hex\":\"12 00 00 00 00 00 00 00\"}", "fixed", 3, 100, "0x4FA", "driver_seat_massage_match"}, FrameMetadata{"can1.seat.driver_axis", "motion", 1217, "can_fd", true, 8, "driver_seat_axis", "05 00 00 00 00 00 00 00", "{\"base_payload_hex\":\"05 00 00 00 00 00 00 00\"}", "duration_ceiling", 0, 100, "0x494", "activity_then_forced_stop"}, FrameMetadata{"can1.seat.driver_axis", "stop", 1217, "can_fd", true, 8, "static", "05 00 00 00 00 00 00 00", "{\"base_payload_hex\":\"05 00 00 00 00 00 00 00\"}", "fixed", 3, 100, "0x494", "submitted_stop"}, FrameMetadata{"can1.seat.driver_memory", "sequence", 1217, "can_fd", true, 8, "learned_driver_memory_pair", "16 00 00 00 00 00 00 00", "{\"base_payload_hex\":\"16 00 00 00 00 00 00 00\"}", "sequence", 20, 50, "0x494", "fresh_initialized_status_then_post_status"}, FrameMetadata{"can1.light.indoor", "command", 1269, "can_fd", true, 8, "reading_light_all", "00 00 03 FF FF 00 00 00", "{\"base_payload_hex\":\"00 00 03 FF FF 00 00 00\"}", "fixed", 3, 100, "0x42E", "indoor_light_match"}, FrameMetadata{"can1.light.reading_all", "command", 1269, "can_fd", true, 8, "reading_light_all", "00 00 03 FF FF 00 00 00", "{\"base_payload_hex\":\"00 00 03 FF FF 00 00 00\"}", "fixed", 3, 100, "0x42E", "indoor_light_match"}, FrameMetadata{"can1.light.ambient_power", "command", 1020, "can_fd", true, 8, "static_variant", "00 00 00 00 00 00 00 00", "{\"base_payload_hex\":\"00 00 00 00 00 00 00 00\",\"payload_variants\":{\"off\":\"00 31 00 75 00 80 00 00\",\"on\":\"00 36 00 75 00 80 00 00\"}}", "fixed", 3, 100, "0x42E", "ambient_power_match"}, FrameMetadata{"can1.light.ambient_color", "command", 1020, "can_fd", true, 8, "ambient_color", "00 30 00 75 00 00 00 00", "{\"base_payload_hex\":\"00 30 00 75 00 00 00 00\"}", "fixed", 3, 100, "0x42E", "ambient_color_match"}, FrameMetadata{"can1.light.ambient_brightness", "command", 1020, "can_fd", true, 8, "ambient_brightness", "00 30 00 75 00 00 00 00", "{\"base_payload_hex\":\"00 30 00 75 00 00 00 00\"}", "fixed", 3, 100, "0x42E", "ambient_brightness_match"}, FrameMetadata{"can1.shade.motion", "command", 1073, "classic_can", false, 8, "static_variant", "00 00 00 00 00 00 00 00", "{\"base_payload_hex\":\"00 00 00 00 00 00 00 00\",\"payload_variants\":{\"close\":\"20 00 00 00 00 00 00 00\",\"half\":\"30 00 00 00 00 00 00 00\",\"open\":\"10 00 00 00 00 00 00 00\",\"stop\":\"40 00 00 00 00 00 00 00\"}}", "fixed", 1, 0, "0x41A", "shade_position_or_stop_submission"}, FrameMetadata{"can1.shade.position", "command", 1073, "classic_can", false, 8, "shade_feedback_closed_loop", "40 00 00 00 00 00 00 00", "{\"base_payload_hex\":\"40 00 00 00 00 00 00 00\"}", "special", 1, 0, "0x41A", "fresh_position_then_motion_then_stop"} }}; inline constexpr std::array kRules{{ RuleMetadata{"can0.seat.position", 0, "seat", "seat.set_longitudinal_position,seat.set_cushion_tilt,seat.set_backrest_recline,seat.set_legrest_height", "seat passenger position <0-100>", "can0_absolute_position"}, RuleMetadata{"can0.seat.relative", 0, "seat", "seat.set_longitudinal_position,seat.set_cushion_tilt,seat.set_backrest_recline,seat.set_legrest_height", "seat passenger relative <1-100>", "can0_relative_position"}, RuleMetadata{"can0.seat.thermal", 0, "seat", "seat.set_ventilation,seat.set_heating", "seat passenger ", "can0_thermal_preserve_peer_feature"}, RuleMetadata{"can0.seat.dynamic", 0, "seat", "seat.start_dynamic_mode,seat.stop_dynamic_mode", "seat passenger dynamic ", "can0_dynamic_mode"}, RuleMetadata{"can1.door.rear_lock", 1, "door", "door.set_rear_lock", "door rear ", ""}, RuleMetadata{"can1.window.motion", 1, "window", "window.set_motion", "window ", ""}, RuleMetadata{"can1.window.position", 1, "window", "window.set_position", "window position <0-100>", "window_position"}, RuleMetadata{"can1.climate.power", 1, "climate", "climate.set_power,climate.set_ac", "ac ", ""}, RuleMetadata{"can1.climate.fan", 1, "climate", "climate.set_fan_level", "ac fan <1-7>", ""}, RuleMetadata{"can1.climate.mode", 1, "climate", "climate.set_outlet_mode", "ac mode ", ""}, RuleMetadata{"can1.climate.temperature", 1, "climate", "climate.set_temperature", "ac temp <18-32>", ""}, RuleMetadata{"can1.climate.control", 1, "climate", "climate.set_control_mode", "ac control ", ""}, RuleMetadata{"can1.climate.cycle", 1, "climate", "climate.set_cycle_mode", "ac cycle ", ""}, RuleMetadata{"can1.outlet.switch", 1, "outlet", "outlet.set_switch_state", "outlet ", ""}, RuleMetadata{"can1.outlet.percent", 1, "outlet", "outlet.set_position_percent", "outlet percent <0-100> <0-100>", "outlet_percent_to_calibrated_position"}, RuleMetadata{"can1.outlet.position", 1, "outlet", "outlet.set_calibrated_position", "outlet position <-128..126> <-128..126>", "outlet_calibrated_position"}, RuleMetadata{"can1.seat.driver_thermal", 1, "seat", "seat.set_driver_ventilation_native,seat.set_driver_heating_native", "seat driver ", ""}, RuleMetadata{"can1.seat.driver_massage", 1, "seat", "seat.set_driver_massage_native", "seat driver massage ", ""}, RuleMetadata{"can1.seat.driver_axis", 1, "seat", "seat.set_driver_axis_native", "seat driver [100-2000]", "driver_seat_axis"}, RuleMetadata{"can1.seat.driver_memory", 1, "seat", "seat.set_driver_position_native,seat.recall_driver_memory_native", "seat driver position <1-3> | seat driver memory recall <1-3>", "driver_seat_memory_recall"}, RuleMetadata{"can1.light.indoor", 1, "light", "interior_light.set_indoor_power", "light indoor ", ""}, RuleMetadata{"can1.light.reading_all", 1, "light", "interior_light.set_reading_power", "light reading all ", ""}, RuleMetadata{"can1.light.ambient_power", 1, "light", "ambient_light.set_power", "light ambient ", ""}, RuleMetadata{"can1.light.ambient_color", 1, "light", "ambient_light.set_color_index", "light ambient color <1-127>", ""}, RuleMetadata{"can1.light.ambient_brightness", 1, "light", "ambient_light.set_brightness_level", "light ambient brightness <1-5>", ""}, RuleMetadata{"can1.shade.motion", 1, "roof", "roof.set_shade_motion", "shade ", "shade_preset"}, RuleMetadata{"can1.shade.position", 1, "roof", "roof.set_shade_position", "shade position <0-100>", "shade_position"} }}; inline constexpr std::array kStaticPayloads{{ StaticPayload{"can1.outlet.switch", "command", "driver-left:open", "02 FF FF FF FF 01 FF FF"}, StaticPayload{"can1.outlet.switch", "command", "driver-left:close", "02 FF FF FF FF 02 FF FF"}, StaticPayload{"can1.outlet.switch", "command", "driver-right:open", "02 FF FF FF FF 04 FF FF"}, StaticPayload{"can1.outlet.switch", "command", "driver-right:close", "02 FF FF FF FF 08 FF FF"}, StaticPayload{"can1.outlet.switch", "command", "passenger-left:open", "03 FF FF FF FF 01 00 00"}, StaticPayload{"can1.outlet.switch", "command", "passenger-left:close", "03 FF FF FF FF 02 00 00"}, StaticPayload{"can1.outlet.switch", "command", "passenger-right:open", "03 FF FF FF FF 04 00 00"}, StaticPayload{"can1.outlet.switch", "command", "passenger-right:close", "03 FF FF FF FF 08 00 00"}, StaticPayload{"can1.light.ambient_power", "command", "on", "00 36 00 75 00 80 00 00"}, StaticPayload{"can1.light.ambient_power", "command", "off", "00 31 00 75 00 80 00 00"}, StaticPayload{"can1.shade.motion", "command", "open", "10 00 00 00 00 00 00 00"}, StaticPayload{"can1.shade.motion", "command", "close", "20 00 00 00 00 00 00 00"}, StaticPayload{"can1.shade.motion", "command", "half", "30 00 00 00 00 00 00 00"}, StaticPayload{"can1.shade.motion", "command", "stop", "40 00 00 00 00 00 00 00"} }}; inline const RuleMetadata* find_rule(std::string_view id) { for (const auto& item : kRules) if (item.id == id) return &item; return nullptr; } inline const FrameMetadata* find_frame(std::string_view rule_id, std::string_view key = "command") { for (const auto& item : kFrames) if (item.rule_id == rule_id && item.key == key) return &item; return nullptr; } inline const StaticPayload* find_static_payload(std::string_view rule_id, std::string_view selector, std::string_view key = "command") { for (const auto& item : kStaticPayloads) if (item.rule_id == rule_id && item.frame_key == key && item.selector == selector) return &item; return nullptr; } inline bool protocol_contains(std::string_view value, std::initializer_list allowed) { for (const auto candidate : allowed) if (value == candidate) return true; return false; } inline bool protocol_integer_in_range(std::string_view text, int minimum, int maximum) { int value = 0; const auto result = std::from_chars(text.data(), text.data() + text.size(), value); return result.ec == std::errc{} && result.ptr == text.data() + text.size() && std::to_string(value) == text && value >= minimum && value <= maximum; } inline const RuleMetadata* match_semantic_command( const std::vector& words, int channel = -1) { if ((channel < 0 || channel == 0) && ((words.size() == 5 && words[0] == "seat" && words[1] == "passenger" && protocol_contains(words[2], {"horizontal", "longitudinal", "basin", "height", "backrest", "legrest"}) && words[3] == "position" && protocol_integer_in_range(words[4], 0, 100)))) return find_rule("can0.seat.position"); if ((channel < 0 || channel == 0) && ((words.size() == 6 && words[0] == "seat" && words[1] == "passenger" && protocol_contains(words[2], {"horizontal", "longitudinal"}) && words[3] == "relative" && protocol_contains(words[4], {"forward", "backward"}) && protocol_integer_in_range(words[5], 1, 100)) || (words.size() == 6 && words[0] == "seat" && words[1] == "passenger" && protocol_contains(words[2], {"basin", "height"}) && words[3] == "relative" && protocol_contains(words[4], {"up", "down"}) && protocol_integer_in_range(words[5], 1, 100)) || (words.size() == 6 && words[0] == "seat" && words[1] == "passenger" && words[2] == "backrest" && words[3] == "relative" && protocol_contains(words[4], {"forward", "backward"}) && protocol_integer_in_range(words[5], 1, 100)) || (words.size() == 6 && words[0] == "seat" && words[1] == "passenger" && words[2] == "legrest" && words[3] == "relative" && protocol_contains(words[4], {"up", "down"}) && protocol_integer_in_range(words[5], 1, 100)))) return find_rule("can0.seat.relative"); if ((channel < 0 || channel == 0) && ((words.size() == 4 && words[0] == "seat" && words[1] == "passenger" && protocol_contains(words[2], {"vent", "heat"}) && protocol_contains(words[3], {"off", "low", "medium", "high"})))) return find_rule("can0.seat.thermal"); if ((channel < 0 || channel == 0) && ((words.size() == 4 && words[0] == "seat" && words[1] == "passenger" && words[2] == "dynamic" && protocol_contains(words[3], {"rocking-horse", "cradle", "stop"})) || (words.size() == 5 && words[0] == "seat" && words[1] == "passenger" && words[2] == "dynamic" && words[3] == "start" && protocol_contains(words[4], {"rocking-horse", "cradle"})))) return find_rule("can0.seat.dynamic"); if ((channel < 0 || channel == 1) && ((words.size() == 3 && words[0] == "door" && words[1] == "rear" && protocol_contains(words[2], {"lock", "unlock"})))) return find_rule("can1.door.rear_lock"); if ((channel < 0 || channel == 1) && ((words.size() == 3 && words[0] == "window" && protocol_contains(words[1], {"all", "front", "rear", "front-left", "front-right", "rear-left", "rear-right"}) && protocol_contains(words[2], {"open", "close", "stop"})))) return find_rule("can1.window.motion"); if ((channel < 0 || channel == 1) && ((words.size() == 4 && words[0] == "window" && protocol_contains(words[1], {"front-left", "front-right", "rear-left", "rear-right"}) && words[2] == "position" && protocol_integer_in_range(words[3], 0, 100)))) return find_rule("can1.window.position"); if ((channel < 0 || channel == 1) && ((words.size() == 2 && words[0] == "ac" && protocol_contains(words[1], {"on", "off"})))) return find_rule("can1.climate.power"); if ((channel < 0 || channel == 1) && ((words.size() == 3 && words[0] == "ac" && words[1] == "fan" && protocol_integer_in_range(words[2], 1, 7)))) return find_rule("can1.climate.fan"); if ((channel < 0 || channel == 1) && ((words.size() == 3 && words[0] == "ac" && words[1] == "mode" && protocol_contains(words[2], {"face", "face-feet", "feet", "feet-defrost", "defrost", "face-feet-defrost", "face-defrost"})))) return find_rule("can1.climate.mode"); if ((channel < 0 || channel == 1) && ((words.size() == 4 && words[0] == "ac" && words[1] == "temp" && protocol_contains(words[2], {"driver", "passenger", "rear"}) && protocol_integer_in_range(words[3], 18, 32)))) return find_rule("can1.climate.temperature"); if ((channel < 0 || channel == 1) && ((words.size() == 3 && words[0] == "ac" && words[1] == "control" && protocol_contains(words[2], {"manual", "auto"})))) return find_rule("can1.climate.control"); if ((channel < 0 || channel == 1) && ((words.size() == 3 && words[0] == "ac" && words[1] == "cycle" && protocol_contains(words[2], {"internal", "external"})))) return find_rule("can1.climate.cycle"); if ((channel < 0 || channel == 1) && ((words.size() == 3 && words[0] == "outlet" && protocol_contains(words[1], {"driver-left", "driver-right", "passenger-left", "passenger-right"}) && protocol_contains(words[2], {"open", "close"})))) return find_rule("can1.outlet.switch"); if ((channel < 0 || channel == 1) && ((words.size() == 5 && words[0] == "outlet" && protocol_contains(words[1], {"driver-left", "driver-right", "passenger-left", "passenger-right"}) && words[2] == "percent" && protocol_integer_in_range(words[3], 0, 100) && protocol_integer_in_range(words[4], 0, 100)))) return find_rule("can1.outlet.percent"); if ((channel < 0 || channel == 1) && ((words.size() == 5 && words[0] == "outlet" && protocol_contains(words[1], {"driver-left", "driver-right", "passenger-left", "passenger-right"}) && words[2] == "position" && protocol_integer_in_range(words[3], -128, 126) && protocol_integer_in_range(words[4], -128, 126)))) return find_rule("can1.outlet.position"); if ((channel < 0 || channel == 1) && ((words.size() == 4 && words[0] == "seat" && words[1] == "driver" && protocol_contains(words[2], {"vent", "heat"}) && protocol_contains(words[3], {"off", "low", "high"})))) return find_rule("can1.seat.driver_thermal"); if ((channel < 0 || channel == 1) && ((words.size() == 4 && words[0] == "seat" && words[1] == "driver" && words[2] == "massage" && words[3] == "off") || (words.size() == 5 && words[0] == "seat" && words[1] == "driver" && words[2] == "massage" && words[3] == "strength" && protocol_contains(words[4], {"weak", "medium", "strong"})) || (words.size() == 5 && words[0] == "seat" && words[1] == "driver" && words[2] == "massage" && words[3] == "mode" && protocol_contains(words[4], {"wave", "pulse", "stretch", "slack", "relax"})))) return find_rule("can1.seat.driver_massage"); if ((channel < 0 || channel == 1) && ((words.size() == 4 && words[0] == "seat" && words[1] == "driver" && protocol_contains(words[2], {"horizontal", "backrest"}) && protocol_contains(words[3], {"forward", "backward"})) || (words.size() == 5 && words[0] == "seat" && words[1] == "driver" && protocol_contains(words[2], {"horizontal", "backrest"}) && protocol_contains(words[3], {"forward", "backward"}) && protocol_integer_in_range(words[4], 100, 2000)) || (words.size() == 4 && words[0] == "seat" && words[1] == "driver" && protocol_contains(words[2], {"height", "basin"}) && protocol_contains(words[3], {"up", "down"})) || (words.size() == 5 && words[0] == "seat" && words[1] == "driver" && protocol_contains(words[2], {"height", "basin"}) && protocol_contains(words[3], {"up", "down"}) && protocol_integer_in_range(words[4], 100, 2000)) || (words.size() == 4 && words[0] == "seat" && words[1] == "driver" && protocol_contains(words[2], {"horizontal", "height", "backrest", "basin"}) && words[3] == "stop"))) return find_rule("can1.seat.driver_axis"); if ((channel < 0 || channel == 1) && ((words.size() == 4 && words[0] == "seat" && words[1] == "driver" && words[2] == "position" && protocol_integer_in_range(words[3], 1, 3)) || (words.size() == 5 && words[0] == "seat" && words[1] == "driver" && words[2] == "memory" && words[3] == "recall" && protocol_integer_in_range(words[4], 1, 3)))) return find_rule("can1.seat.driver_memory"); if ((channel < 0 || channel == 1) && ((words.size() == 3 && words[0] == "light" && words[1] == "indoor" && protocol_contains(words[2], {"on", "off"})))) return find_rule("can1.light.indoor"); if ((channel < 0 || channel == 1) && ((words.size() == 4 && words[0] == "light" && words[1] == "reading" && words[2] == "all" && protocol_contains(words[3], {"on", "off"})))) return find_rule("can1.light.reading_all"); if ((channel < 0 || channel == 1) && ((words.size() == 3 && words[0] == "light" && words[1] == "ambient" && protocol_contains(words[2], {"on", "off"})))) return find_rule("can1.light.ambient_power"); if ((channel < 0 || channel == 1) && ((words.size() == 4 && words[0] == "light" && words[1] == "ambient" && words[2] == "color" && protocol_integer_in_range(words[3], 1, 127)))) return find_rule("can1.light.ambient_color"); if ((channel < 0 || channel == 1) && ((words.size() == 4 && words[0] == "light" && words[1] == "ambient" && words[2] == "brightness" && protocol_integer_in_range(words[3], 1, 5)))) return find_rule("can1.light.ambient_brightness"); if ((channel < 0 || channel == 1) && ((words.size() == 2 && words[0] == "shade" && protocol_contains(words[1], {"open", "close", "half", "stop"})))) return find_rule("can1.shade.motion"); if ((channel < 0 || channel == 1) && ((words.size() == 3 && words[0] == "shade" && words[1] == "position" && protocol_integer_in_range(words[2], 0, 100)))) return find_rule("can1.shade.position"); return nullptr; } } // namespace cognitive_agent_can_protocol