@@ -57,6 +57,8 @@ constexpr const char* kDefaultMicrohardPassword = "qwertz1";
5757constexpr int kDefaultMicrohardVideoPort = 5910 ;
5858constexpr int kDefaultMicrohardTelemetryPort = 5920 ;
5959constexpr bool kRecordModeEnabled = false ;
60+ constexpr int kLegacyUsbCameraType = 1 ;
61+ constexpr int kUsbGenericCameraType = 10 ;
6062
6163bool file_exists (const char * path) {
6264 std::error_code ec;
@@ -123,6 +125,14 @@ std::optional<int> read_int_file(const char* path) {
123125 return value;
124126}
125127
128+ int normalize_camera_type (int value) {
129+ // ImageWriter historically emits "1" for USB. OpenHD expects USB generic as 10.
130+ if (value == kLegacyUsbCameraType ) {
131+ return kUsbGenericCameraType ;
132+ }
133+ return value;
134+ }
135+
126136} // namespace
127137
128138void sync_settings_from_files () {
@@ -149,21 +159,36 @@ void sync_settings_from_files() {
149159 buffer << file.rdbuf ();
150160 const std::string content = buffer.str ();
151161
152- // Parse camera (supports int or string)
153- auto cam_int = extract_int_field (content, " camera " );
154- if (cam_int) {
155- config. camera_type = *cam_int;
156- changed = true ;
157- } else {
158- auto cam_str = extract_string_field (content, " camera " );
159- if (cam_str) {
162+ // Parse camera fields (supports int or string)
163+ auto parse_camera_field = [&]( const char * key, std::optional< int >& out) {
164+ if (auto cam_int = extract_int_field (content, key); cam_int) {
165+ out = normalize_camera_type ( *cam_int) ;
166+ changed = true ;
167+ return ;
168+ }
169+ if (auto cam_str = extract_string_field (content, key); cam_str) {
160170 try {
161- config. camera_type = std::stoi (*cam_str);
171+ out = normalize_camera_type ( std::stoi (*cam_str) );
162172 changed = true ;
163173 } catch (...) {
164174 // Invalid integer string
165175 }
166176 }
177+ };
178+ parse_camera_field (" camera" , config.camera_type );
179+ parse_camera_field (" camera2" , config.camera2_type );
180+
181+ if (auto camera_resolution_fps =
182+ extract_string_field (content, " camera_resolution_fps" );
183+ camera_resolution_fps.has_value ()) {
184+ config.camera_resolution_fps = *camera_resolution_fps;
185+ changed = true ;
186+ }
187+ if (auto camera2_resolution_fps =
188+ extract_string_field (content, " camera2_resolution_fps" );
189+ camera2_resolution_fps.has_value ()) {
190+ config.camera2_resolution_fps = *camera2_resolution_fps;
191+ changed = true ;
167192 }
168193
169194 // Parse role
@@ -257,6 +282,11 @@ std::string build_settings_response() {
257282 }
258283 }
259284 const bool has_camera_type = config.camera_type .has_value ();
285+ const bool has_camera2_type = config.camera2_type .has_value ();
286+ const bool has_camera_resolution_fps =
287+ config.camera_resolution_fps .has_value ();
288+ const bool has_camera2_resolution_fps =
289+ config.camera2_resolution_fps .has_value ();
260290 const bool wifi_enable_autodetect =
261291 config.wifi_enable_autodetect .value_or (kDefaultWifiEnableAutodetect );
262292 const std::string wifi_wb_link_cards =
@@ -310,6 +340,22 @@ std::string build_settings_response() {
310340 << " ,\" reset_requested\" :" << (reset_requested ? " true" : " false" )
311341 << " ,\" has_camera_type\" :" << (has_camera_type ? " true" : " false" )
312342 << " ,\" camera_type\" :" << (has_camera_type ? *config.camera_type : 0 )
343+ << " ,\" has_camera2_type\" :" << (has_camera2_type ? " true" : " false" )
344+ << " ,\" camera2_type\" :" << (has_camera2_type ? *config.camera2_type : 0 )
345+ << " ,\" has_camera_resolution_fps\" :"
346+ << (has_camera_resolution_fps ? " true" : " false" )
347+ << " ,\" camera_resolution_fps\" :\" "
348+ << json_escape (has_camera_resolution_fps
349+ ? *config.camera_resolution_fps
350+ : " " )
351+ << " \" "
352+ << " ,\" has_camera2_resolution_fps\" :"
353+ << (has_camera2_resolution_fps ? " true" : " false" )
354+ << " ,\" camera2_resolution_fps\" :\" "
355+ << json_escape (has_camera2_resolution_fps
356+ ? *config.camera2_resolution_fps
357+ : " " )
358+ << " \" "
313359 << " ,\" has_run_mode\" :" << (has_run_mode ? " true" : " false" )
314360 << " ,\" run_mode\" :\" "
315361 << json_escape (has_run_mode ? run_mode : " ground" ) << " \" "
@@ -372,7 +418,27 @@ std::string handle_settings_update(const std::string& line) {
372418
373419 if (auto camera_type = extract_int_field (line, " camera_type" );
374420 camera_type.has_value ()) {
375- config.camera_type = *camera_type;
421+ config.camera_type = normalize_camera_type (*camera_type);
422+ changed = true ;
423+ }
424+
425+ if (auto camera2_type = extract_int_field (line, " camera2_type" );
426+ camera2_type.has_value ()) {
427+ config.camera2_type = normalize_camera_type (*camera2_type);
428+ changed = true ;
429+ }
430+
431+ if (auto camera_resolution_fps =
432+ extract_string_field (line, " camera_resolution_fps" );
433+ camera_resolution_fps.has_value ()) {
434+ config.camera_resolution_fps = *camera_resolution_fps;
435+ changed = true ;
436+ }
437+
438+ if (auto camera2_resolution_fps =
439+ extract_string_field (line, " camera2_resolution_fps" );
440+ camera2_resolution_fps.has_value ()) {
441+ config.camera2_resolution_fps = *camera2_resolution_fps;
376442 changed = true ;
377443 }
378444
@@ -585,7 +651,7 @@ std::string handle_camera_setup_request(const std::string& line) {
585651 return " {\" type\" :\" sysutil.camera.setup.response\" ,\" ok\" :false,\" message\" :\" missing camera_type\" }\n " ;
586652 }
587653
588- config.camera_type = *camera_type;
654+ config.camera_type = normalize_camera_type ( *camera_type) ;
589655 if (!write_sysutil_config (config)) {
590656 return " {\" type\" :\" sysutil.camera.setup.response\" ,\" ok\" :false,\" message\" :\" config write failed\" }\n " ;
591657 }
0 commit comments