|
1 | 1 | #pragma once |
2 | 2 |
|
| 3 | +#include <string.h> |
3 | 4 | #include <ship_data_model.hpp> |
4 | 5 |
|
5 | 6 | #include "seatalk_decoder.hpp" |
6 | 7 |
|
7 | 8 | namespace seatalk { |
8 | 9 |
|
| 10 | +inline ship_data_model::AutopilotMode seatalk_model_autopilot_mode(SeaTalkAutopilotMode mode) { |
| 11 | + switch (mode) { |
| 12 | + case SeaTalkAutopilotMode::standby: return ship_data_model::AutopilotMode::compass; |
| 13 | + case SeaTalkAutopilotMode::auto_heading: return ship_data_model::AutopilotMode::compass; |
| 14 | + case SeaTalkAutopilotMode::vane: return ship_data_model::AutopilotMode::wind; |
| 15 | + case SeaTalkAutopilotMode::track: return ship_data_model::AutopilotMode::nav; |
| 16 | + } |
| 17 | + return ship_data_model::AutopilotMode::compass; |
| 18 | +} |
| 19 | + |
| 20 | +inline void seatalk_copy_text(char* dst, size_t dst_len, const char* src) { |
| 21 | + if (!dst || dst_len == 0) return; |
| 22 | + dst[0] = '\0'; |
| 23 | + if (!src) return; |
| 24 | + strncpy(dst, src, dst_len - 1); |
| 25 | + dst[dst_len - 1] = '\0'; |
| 26 | +} |
| 27 | + |
9 | 28 | template<typename Real> |
10 | 29 | bool apply_seatalk_decoded(const SeaTalkDecoded<Real>& decoded, |
11 | 30 | ship_data_model::DataModel<Real>& model, |
@@ -61,6 +80,66 @@ bool apply_seatalk_decoded(const SeaTalkDecoded<Real>& decoded, |
61 | 80 | } |
62 | 81 | return true; |
63 | 82 |
|
| 83 | + case SeaTalkDecodedKind::autopilot_state: { |
| 84 | + auto& ap = model.autopilot.controller; |
| 85 | + ap.mode.value = seatalk_model_autopilot_mode(decoded.autopilot_mode); |
| 86 | + ap.enabled.value = decoded.autopilot_mode != SeaTalkAutopilotMode::standby; |
| 87 | + ap.heading_deg.set(decoded.value, now_us); |
| 88 | + if (decoded.secondary_valid) ap.heading_command_deg.set(decoded.secondary_value, now_us); |
| 89 | + model.ins.imu.heading_deg.set(decoded.value, now_us); |
| 90 | + model.ins.imu.heading_magnetic_deg.set(decoded.value, now_us); |
| 91 | + if (decoded.third_valid) { |
| 92 | + model.steering.rudder.angle_deg.set(decoded.third_value, now_us); |
| 93 | + model.steering.rudder.source.value = source; |
| 94 | + model.steering.rudder.last_update_us = now_us; |
| 95 | + } |
| 96 | + if (decoded.alarm) { |
| 97 | + model.autopilot.status.warnings.set(decoded.code, now_us); |
| 98 | + seatalk_copy_text(model.notifications.messages.event.event_id, sizeof(model.notifications.messages.event.event_id), "seatalk_ap_alarm"); |
| 99 | + seatalk_copy_text(model.notifications.messages.event.event_source, sizeof(model.notifications.messages.event.event_source), "seatalk"); |
| 100 | + model.notifications.messages.event.event_state = 'A'; |
| 101 | + seatalk_copy_text(model.notifications.messages.event.event_text, sizeof(model.notifications.messages.event.event_text), decoded.label); |
| 102 | + model.notifications.messages.event.field_count.set(1, now_us); |
| 103 | + model.notifications.messages.event.source.value = source; |
| 104 | + model.notifications.messages.event.last_update_us = now_us; |
| 105 | + } |
| 106 | + return true; |
| 107 | + } |
| 108 | + |
| 109 | + case SeaTalkDecodedKind::autopilot_key: |
| 110 | + seatalk_copy_text(model.notifications.messages.event.event_id, sizeof(model.notifications.messages.event.event_id), "seatalk_ap_key"); |
| 111 | + seatalk_copy_text(model.notifications.messages.event.event_source, sizeof(model.notifications.messages.event.event_source), "seatalk"); |
| 112 | + model.notifications.messages.event.event_state = decoded.long_press ? 'L' : 'S'; |
| 113 | + seatalk_copy_text(model.notifications.messages.event.event_text, sizeof(model.notifications.messages.event.event_text), decoded.label); |
| 114 | + model.notifications.messages.event.field_count.set(1, now_us); |
| 115 | + model.notifications.messages.event.source.value = source; |
| 116 | + model.notifications.messages.event.last_update_us = now_us; |
| 117 | + return true; |
| 118 | + |
| 119 | + case SeaTalkDecodedKind::navigation_to_waypoint: |
| 120 | + model.route.apb.xte_nmi.set(decoded.value, now_us); |
| 121 | + if (decoded.secondary_valid) { |
| 122 | + model.route.apb.present_to_destination_bearing_deg.set(decoded.secondary_value, now_us); |
| 123 | + model.route.apb.heading_to_steer_deg.set(decoded.secondary_value, now_us); |
| 124 | + model.route.waypoint.bearing_magnetic_deg.set(decoded.secondary_value, now_us); |
| 125 | + } |
| 126 | + if (decoded.third_valid) { |
| 127 | + model.route.apb.origin_to_destination_bearing_deg.set(decoded.secondary_value, now_us); |
| 128 | + model.route.waypoint.distance_nmi.set(decoded.third_value, now_us); |
| 129 | + model.route.rmb.range_nmi.set(decoded.third_value, now_us); |
| 130 | + } |
| 131 | + model.route.apb.mode_hint.value = ship_data_model::AutopilotMode::nav; |
| 132 | + model.route.apb.source.value = source; |
| 133 | + model.route.apb.last_update_us = now_us; |
| 134 | + model.route.waypoint.source.value = source; |
| 135 | + model.route.waypoint.last_update_us = now_us; |
| 136 | + return true; |
| 137 | + |
| 138 | + case SeaTalkDecodedKind::compass_variation: |
| 139 | + model.ins.imu.magnetic_variation_deg.set(decoded.value, now_us); |
| 140 | + model.gnss.fix.declination_deg.set(decoded.value, now_us); |
| 141 | + return true; |
| 142 | + |
64 | 143 | case SeaTalkDecodedKind::trip_distance: |
65 | 144 | model.sea.trip_distance_nmi.set(decoded.value, now_us); |
66 | 145 | model.sea.source.value = source; |
|
0 commit comments