29 "High pressure PT capable of going up to 5k PSI reading",
36 "COPV PT Post Regulator",
37 "COPV PT post regulator (1000psi)",
41 "COPV post regulator"};
45 "Rocket",
"Fuel upstream"};
49 "Rocket",
"Fuel downstream"};
52 "Upstream Oxidizer PT",
53 "Upstream Oxidizer PT (1000 PSI)",
60 "Downstream Oxidizer PT",
61 "Downstream Oxidizer PT (1000 PSI)",
65 "Oxidizer downstream"};
70 "LOX Fill PT that goes up to 1000 psi",
78 "Fuel fill PT that goes up to 1000 psi",
82 "Fuel fill pressure"};
85 "High Pressure Fill PT",
86 "High pressure fill with PT rated to 5000 psi",
89 "GSE - Pressurant Fill",
90 "High pressure fill"};
93 "Medium Pressure Fill PT",
94 "Medium press fill with PT rated to 2000 PSI",
97 "GSE - Pressurant Fill",
98 "Medium pressure fill"};
101 "Low Pressure Fill PT",
102 "Low pressure line with PT rated to 1000 psi",
105 "GSE - Pressurant Fill",
106 "Low pressure fill"};
109 <<
" pressure sensor definitions" << std::endl;
120 std::cout <<
"[SensorAssignment] Forcing static IP for board " << (int)
board_id
121 <<
" from " << it->second.board_ip <<
" to " << ip << std::endl;
122 it->second.board_ip = ip;
123 for (
auto& sensor : it->second.sensors) {
124 sensor.board_ip = ip;
127 if (assignment.board_id ==
board_id) {
128 assignment.board_ip = ip;
136 const std::string& mac_address,
138 const std::string& source_ip) {
140 std::string assigned_ip;
143 assigned_ip = static_it->second;
149 if (!assigned_ip.empty() && it->second.board_ip != assigned_ip) {
150 std::cout <<
"[SensorAssignment] Updating IP for board " << (int)
board_id
151 <<
" to static config IP " << assigned_ip << std::endl;
152 it->second.board_ip = assigned_ip;
154 for (
auto& sensor : it->second.sensors) {
155 sensor.board_ip = assigned_ip;
159 if (assignment.board_id ==
board_id) {
160 assignment.board_ip = assigned_ip;
163 }
else if (assigned_ip.empty() && !source_ip.empty() && it->second.board_ip != source_ip) {
164 std::cout <<
"[SensorAssignment] Updating IP for unconfigured board " << (int)
board_id
165 <<
" from " << it->second.board_ip <<
" to heartbeat source " << source_ip
167 it->second.board_ip = source_ip;
169 for (
auto& sensor : it->second.sensors) {
170 sensor.board_ip = source_ip;
174 if (assignment.board_id ==
board_id) {
175 assignment.board_ip = source_ip;
179 return it->second.board_ip;
183 if (assigned_ip.empty()) {
186 std::cout <<
"[SensorAssignment] Board " << (int)
board_id
187 <<
" not found in config.toml! Using pseudo-random auto-discovery IP."
194 config.board_ip = assigned_ip;
196 config.mac_address = mac_address;
197 config.system_state = system_state;
198 config.is_configured =
false;
200 std::cout <<
"[SensorAssignment] Assigned IP " << assigned_ip <<
" to board " << (int)
board_id
201 <<
" (MAC: " << mac_address
202 <<
", State: " << (system_state ==
SystemState::GSE ?
"GSE" :
"FLIGHT") <<
")"
209 const std::vector<std::string>& sensor_ids,
210 uint8_t start_channel) {
214 std::cerr <<
"[SensorAssignment] Error: Board " << (int)
board_id <<
" not found"
222 uint8_t channel = start_channel;
223 for (
const auto& sensor_id : sensor_ids) {
227 std::cerr <<
"[SensorAssignment] Warning: Sensor " << sensor_id
228 <<
" not found, skipping" << std::endl;
232 const auto& spec = sensor_it->second;
247 board_config.
sensors.push_back(assignment);
250 if (board_config.
sensors.size() == 1) {
254 std::cout <<
"[SensorAssignment] Assigned sensor " << sensor_id <<
" to board "
266 const auto&
config = it->second;
273 std::vector<uint8_t> sensor_ids;
274 sensor_ids.reserve(
config.sensors.size());
275 for (
const auto& sensor :
config.sensors) {
277 sensor_ids.push_back(sensor.channel_id);
280 uint8_t reference_voltage = 0;
281 bool necessary_for_abort =
false;
282 uint32_t controller_ip = 0;
283 uint8_t enable_serial_printing = 0;
288 uint32_t ts_ms =
static_cast<uint32_t
>(std::chrono::duration_cast<std::chrono::milliseconds>(
289 std::chrono::steady_clock::now().time_since_epoch())
293 sensor_ids, reference_voltage, necessary_for_abort, controller_ip, enable_serial_printing,
294 ts_ms, buffer,
sizeof(buffer));
297 std::cerr <<
"[SensorAssignment] Failed to serialize SENSOR_CONFIG for board "
298 <<
static_cast<int>(
board_id) <<
" using DAQv2-Comms serializer" << std::endl;
302 return std::vector<uint8_t>(buffer, buffer + written);
306 const std::string& sensor_id)
const {
319 return it->second.sensors;
323 std::vector<SensorAssignment> sensors;
325 if (assignment.system_state ==
state) {
326 sensors.push_back(assignment);
347 it->second.is_configured =
true;
362 std::istringstream mac_stream(mac_address);
363 std::string byte_str;
364 uint32_t mac_hash = 0;
367 while (std::getline(mac_stream, byte_str,
':') && byte_count < 6) {
368 uint8_t byte_val =
static_cast<uint8_t
>(std::stoul(byte_str,
nullptr, 16));
369 mac_hash = (mac_hash << 8) | byte_val;
375 uint8_t range_start =
380 uint8_t ip_octet = range_start + (mac_hash % (range_end - range_start + 1));
383 size_t last_dot = base_ip.rfind(
'.');
384 std::string base = base_ip.substr(0, last_dot);
386 return base +
"." + std::to_string(ip_octet);
390 if (type_str ==
"PT")
392 if (type_str ==
"TC")
394 if (type_str ==
"RTD")
396 if (type_str ==
"LC")
398 if (type_str ==
"ACTUATOR")
std::string sensor_type_to_string(SensorType type) const
uint8_t flight_ip_range_start_
std::string assign_board_ip(uint8_t board_id, const std::string &mac_address, SystemState system_state, const std::string &source_ip="")
Assign IP address to board (called by FSW) If a static IP was set for this board_id,...
bool update_board_config_from_packet(uint8_t board_id, const uint8_t *data, size_t size)
Update board configuration from received packet.
std::vector< uint8_t > generate_board_config_packet(uint8_t board_id) const
Get board configuration for sending to board.
bool load_sensor_definitions(const std::string &config_path)
Load sensor definitions from config.
SensorType sensor_type_from_string(const std::string &type_str) const
void register_config_update_callback(std::function< void(uint8_t, const BoardConfiguration &)> callback)
Register callback for board configuration updates.
void set_static_board_ip(uint8_t board_id, const std::string &ip)
Set a static IP for a board from loaded configuration.
SensorAssignmentManager()
std::optional< BoardConfiguration > get_board_config(uint8_t board_id) const
Get board configuration.
std::vector< std::function< void(uint8_t, const BoardConfiguration &)> > config_callbacks_
uint8_t flight_ip_range_end_
std::map< uint8_t, std::string > static_board_ips_
uint8_t gse_ip_range_start_
std::string flight_base_ip_
std::map< std::string, PressureSensorSpec > pressure_sensor_specs_
std::map< std::string, SensorAssignment > sensor_assignments_
std::string calculate_ip_from_mac(const std::string &mac_address, SystemState state) const
std::map< uint8_t, BoardConfiguration > board_configs_
std::vector< SensorAssignment > get_board_sensors(uint8_t board_id) const
Get all sensors for a board.
bool assign_sensors_to_board(uint8_t board_id, const std::vector< std::string > &sensor_ids, uint8_t start_channel=0)
Assign sensors to board (called by FSW).
std::optional< SensorAssignment > get_sensor_assignment(const std::string &sensor_id) const
Get sensor assignment for a sensor ID.
uint8_t gse_ip_range_end_
std::vector< SensorAssignment > get_system_sensors(SystemState state) const
Get all sensors for a system state.
static ActuatorControllerState state
size_t create_sensor_config_packet(const std::vector< uint8_t > &sensor_ids, uint8_t reference_voltage, bool necessary_for_abort, uint32_t controller_ip, uint8_t enable_serial_printing, uint32_t timestamp_ms, uint8_t *buffer, size_t buffer_size)
Creates a complete Sensor Config packet in the provided buffer.
SystemState
System state (GSE or Flight).
Motorized ball valve position: raw ADC counts -> % open.
Board configuration (assigned by FSW).
std::vector< SensorAssignment > sensors
SensorType primary_sensor_type
Sensor assignment to board.