56 #include <imgui_internal.h>
60 #ifndef V4L2_CTRL_CLASS_DETECT
61 #define V4L2_CTRL_CLASS_DETECT 0x00a30000
67 struct shortcontrol {
int id;
char const *
const shortname; };
72 static shortcontrol camcontrols[] = {
74 { V4L2_CID_BRIGHTNESS,
"brightness" },
75 { V4L2_CID_CONTRAST,
"contrast" },
76 { V4L2_CID_SATURATION,
"saturation" },
77 { V4L2_CID_HUE,
"hue" },
78 { V4L2_CID_AUDIO_VOLUME,
"audiovol" },
79 { V4L2_CID_AUDIO_BALANCE,
"audiobal" },
80 { V4L2_CID_AUDIO_BASS,
"audiobass" },
81 { V4L2_CID_AUDIO_TREBLE,
"audiotreble" },
82 { V4L2_CID_AUDIO_MUTE,
"audiomute" },
83 { V4L2_CID_AUDIO_LOUDNESS,
"audioloudness" },
84 { V4L2_CID_BLACK_LEVEL,
"blacklevel" },
85 { V4L2_CID_AUTO_WHITE_BALANCE,
"autowb" },
86 { V4L2_CID_DO_WHITE_BALANCE,
"dowb" },
87 { V4L2_CID_RED_BALANCE,
"redbal" },
88 { V4L2_CID_BLUE_BALANCE,
"bluebal" },
89 { V4L2_CID_GAMMA,
"gamma" },
90 { V4L2_CID_WHITENESS,
"whiteness" },
91 { V4L2_CID_EXPOSURE,
"exposure" },
92 { V4L2_CID_AUTOGAIN,
"autogain" },
93 { V4L2_CID_GAIN,
"gain" },
94 { V4L2_CID_HFLIP,
"hflip" },
95 { V4L2_CID_VFLIP,
"vflip" },
96 { V4L2_CID_POWER_LINE_FREQUENCY,
"powerfreq" },
97 { V4L2_CID_HUE_AUTO,
"autohue" },
98 { V4L2_CID_WHITE_BALANCE_TEMPERATURE,
"wbtemp" },
99 { V4L2_CID_SHARPNESS,
"sharpness" },
100 { V4L2_CID_BACKLIGHT_COMPENSATION,
"backlight" },
101 { V4L2_CID_CHROMA_AGC,
"chromaagc" },
102 { V4L2_CID_COLOR_KILLER,
"colorkiller" },
103 { V4L2_CID_COLORFX,
"colorfx" },
104 { V4L2_CID_AUTOBRIGHTNESS,
"autobrightness" },
105 { V4L2_CID_BAND_STOP_FILTER,
"bandfilter" },
106 { V4L2_CID_ROTATE,
"rotate" },
107 { V4L2_CID_BG_COLOR,
"bgcolor" },
108 { V4L2_CID_CHROMA_GAIN,
"chromagain" },
109 { V4L2_CID_ILLUMINATORS_1,
"illum1" },
110 { V4L2_CID_ILLUMINATORS_2,
"illum2" },
111 { V4L2_CID_MIN_BUFFERS_FOR_CAPTURE,
"mincapbuf" },
112 { V4L2_CID_MIN_BUFFERS_FOR_OUTPUT,
"minoutbuf" },
113 { V4L2_CID_ALPHA_COMPONENT,
"alphacompo" },
118 { V4L2_CID_EXPOSURE_AUTO,
"autoexp" },
119 { V4L2_CID_EXPOSURE_ABSOLUTE,
"absexp" },
120 { V4L2_CID_EXPOSURE_AUTO_PRIORITY,
"exppri" },
121 { V4L2_CID_PAN_RELATIVE,
"panrel" },
122 { V4L2_CID_TILT_RELATIVE,
"tiltrel" },
123 { V4L2_CID_PAN_RESET,
"panreset" },
124 { V4L2_CID_TILT_RESET,
"tiltreset" },
125 { V4L2_CID_PAN_ABSOLUTE,
"panabs" },
126 { V4L2_CID_TILT_ABSOLUTE,
"tiltabs" },
127 { V4L2_CID_FOCUS_ABSOLUTE,
"focusabs" },
128 { V4L2_CID_FOCUS_RELATIVE,
"focusrel" },
129 { V4L2_CID_FOCUS_AUTO,
"focusauto" },
130 { V4L2_CID_ZOOM_ABSOLUTE,
"zoomabs" },
131 { V4L2_CID_ZOOM_RELATIVE,
"zoomrel" },
132 { V4L2_CID_ZOOM_CONTINUOUS,
"zoomcontinuous" },
133 { V4L2_CID_PRIVACY,
"privacy" },
134 { V4L2_CID_IRIS_ABSOLUTE,
"irisabs" },
135 { V4L2_CID_IRIS_RELATIVE,
"irisrel" },
138 #ifndef V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE
139 #define V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE (V4L2_CID_CAMERA_CLASS_BASE+20)
160 { V4L2_CID_FLASH_LED_MODE,
"flashled" },
161 { V4L2_CID_FLASH_STROBE_SOURCE,
"flashstrobesrc" },
162 { V4L2_CID_FLASH_STROBE,
"flashstrobe" },
163 { V4L2_CID_FLASH_STROBE_STOP,
"flashstrobestop" },
164 { V4L2_CID_FLASH_STROBE_STATUS,
"flashstrovestat" },
165 { V4L2_CID_FLASH_TIMEOUT,
"flashtimeout" },
166 { V4L2_CID_FLASH_INTENSITY,
"flashintens" },
167 { V4L2_CID_FLASH_TORCH_INTENSITY,
"flashtorch" },
168 { V4L2_CID_FLASH_INDICATOR_INTENSITY,
"flashindintens" },
169 { V4L2_CID_FLASH_FAULT,
"flashfault" },
170 { V4L2_CID_FLASH_CHARGE,
"flashcharge" },
171 { V4L2_CID_FLASH_READY,
"flashready" },
174 { V4L2_CID_JPEG_CHROMA_SUBSAMPLING,
"jpegchroma" },
175 { V4L2_CID_JPEG_RESTART_INTERVAL,
"jpegrestartint" },
176 { V4L2_CID_JPEG_COMPRESSION_QUALITY,
"jpegcompression" },
177 { V4L2_CID_JPEG_ACTIVE_MARKER,
"jpegmarker" },
202 std::string abbreviate(std::string
const & longname)
204 std::string name(longname);
205 std::transform(name.begin(), name.end(), name.begin(), ::tolower);
206 name.erase(std::remove_if(name.begin(), name.end(), [](
int c) { return !std::isalnum(c); }), name.end());
214 jevois::
Manager(instance), itsMappings(), itsRunning(false), itsStreaming(false), itsStopMainLoop(false),
215 itsShellMode(false), itsTurbo(false), itsManualStreamon(false), itsVideoErrors(false), itsFrame(0),
216 itsNumSerialSent(0), itsRequestedFormat(-2)
220 #ifdef JEVOIS_PLATFORM_A33
222 itsCheckingMassStorage.store(
false); itsMassStorageMode.store(
false);
224 while (itsCheckingMassStorage.load() ==
false) std::this_thread::sleep_for(std::chrono::milliseconds(5));
230 jevois::
Manager(argc, argv, instance), itsMappings(), itsRunning(false), itsStreaming(false),
231 itsStopMainLoop(false), itsShellMode(false), itsTurbo(false), itsManualStreamon(false), itsVideoErrors(false),
232 itsFrame(0), itsNumSerialSent(0), itsRequestedFormat(-2)
236 #ifdef JEVOIS_PLATFORM_A33
238 itsCheckingMassStorage.store(
false); itsMassStorageMode.store(
false);
240 while (itsCheckingMassStorage.load() ==
false) std::this_thread::sleep_for(std::chrono::milliseconds(5));
246 std::string
const & newval)
251 for (std::list<std::shared_ptr<UserInterface> >::iterator itr = itsSerials.begin(); itr != itsSerials.end(); ++itr)
252 if ((*itr)->instanceName() ==
"serial") itr = itsSerials.erase(itr);
253 removeComponent(
"serial",
false);
256 if (newval.empty() ==
false)
259 std::shared_ptr<jevois::UserInterface> s;
260 if (newval ==
"stdio")
261 s = addComponent<jevois::StdioInterface>(
"serial");
268 itsSerials.push_back(s);
269 LINFO(
"Using [" << newval <<
"] hardware (4-pin connector) serial port");
272 else LINFO(
"No hardware (4-pin connector) serial port used");
277 std::string
const & newval)
282 for (std::list<std::shared_ptr<UserInterface> >::iterator itr = itsSerials.begin(); itr != itsSerials.end(); ++itr)
283 if ((*itr)->instanceName() ==
"usbserial") itr = itsSerials.erase(itr);
284 removeComponent(
"usbserial",
false);
287 if (newval.empty() ==
false)
290 std::shared_ptr<jevois::UserInterface> s =
293 itsSerials.push_back(s);
294 LINFO(
"Using [" << newval <<
"] USB serial port");
297 else LINFO(
"No USB serial port used");
302 jevois::engine::CPUmode
const & newval)
305 std::ofstream ofs(
"/sys/devices/system/cpu/cpu2/cpufreq/scaling_governor");
307 std::ofstream ofs(
"/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor");
309 if (ofs.is_open() ==
false)
311 #ifdef JEVOIS_PLATFORM
312 LERROR(
"Cannot set cpu frequency governor mode -- IGNORED");
319 case engine::CPUmode::PowerSave: ofs <<
"powersave" << std::endl;
break;
320 case engine::CPUmode::Conservative: ofs <<
"conservative" << std::endl;
break;
321 case engine::CPUmode::OnDemand: ofs <<
"ondemand" << std::endl;
break;
322 case engine::CPUmode::Interactive: ofs <<
"interactive" << std::endl;
break;
323 case engine::CPUmode::Performance: ofs <<
"performance" << std::endl;
break;
330 jevois::engine::CPUmode
const & newval)
332 std::ofstream ofs(
"/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor");
333 if (ofs.is_open() ==
false)
335 #ifdef JEVOIS_PLATFORM
336 LERROR(
"Cannot set cpu frequency governor mode -- IGNORED");
343 case engine::CPUmode::PowerSave: ofs <<
"powersave" << std::endl;
break;
344 case engine::CPUmode::Conservative: ofs <<
"conservative" << std::endl;
break;
345 case engine::CPUmode::OnDemand: ofs <<
"ondemand" << std::endl;
break;
346 case engine::CPUmode::Interactive: ofs <<
"interactive" << std::endl;
break;
347 case engine::CPUmode::Performance: ofs <<
"performance" << std::endl;
break;
354 unsigned int const & newval)
357 std::ofstream ofs(
"/sys/devices/system/cpu/cpu2/cpufreq/scaling_max_freq");
359 std::ofstream ofs(
"/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq");
362 if (ofs.is_open() ==
false)
364 #ifdef JEVOIS_PLATFORM
365 LERROR(
"Cannot set cpu max frequency -- IGNORED");
370 ofs << newval * 1000U << std::endl;
377 itsVideoErrors.store(newval);
390 itsGUIhelper = addComponent<jevois::GUIhelper>(
"gui",
conslock::get());
391 auto s = addComponent<jevois::GUIconsole>(
"guiconsole");
392 itsSerials.push_back(s);
393 LINFO(
"GUI enabled.");
396 else if (itsGUIhelper)
398 for (
auto itr = itsSerials.begin(); itr != itsSerials.end(); ++itr)
399 if ((*itr)->instanceName() ==
"guiconsole") { itsSerials.erase(itr);
break; }
400 removeComponent(
"guiconsole",
false);
401 removeComponent(itsGUIhelper);
402 itsGUIhelper.reset();
403 LINFO(
"GUI disabled.");
409 unsigned int const & newval)
411 std::ofstream ofs(
"/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq");
413 if (ofs.is_open() ==
false)
415 #ifdef JEVOIS_PLATFORM
416 LERROR(
"Cannot set cpu max frequency -- IGNORED");
421 ofs << newval * 1000U << std::endl;
429 std::string
const paramcfg = std::string(JEVOIS_CONFIG_PATH) +
'/' + JEVOIS_MODULE_PARAMS_FILENAME;
430 std::ifstream ifs(paramcfg);
if (ifs.is_open()) setParamsFromStream(ifs, paramcfg);
445 itsMappings = jevois::loadVideoMappings(
camerasens::get(), itsDefaultMappingIdx,
true, usegui);
446 LINFO(
"Loaded " << itsMappings.size() <<
" vision processing modes.");
461 usbserialdev::freeze();
465 camerasens::freeze();
467 cameranbuf::freeze();
470 gadgetnbuf::freeze();
489 reloadVideoMappings();
497 LINFO(
"Initalizing Python...");
498 jevois::pythonModuleSetEngine(
this);
505 LINFO(
"Starting camera device " << camdev);
507 #ifdef JEVOIS_PLATFORM_A33
509 std::ofstream ofs(
"/sys/module/vfe_v4l2/parameters/turbo");
512 if (itsTurbo) ofs <<
"1" << std::endl;
else ofs <<
"0" << std::endl;
515 else LERROR(
"Could not access VFE turbo parameter -- IGNORED");
521 #ifndef JEVOIS_PLATFORM
523 camreg::set(
false); camreg::freeze();
524 imureg::set(
false); imureg::freeze();
530 #ifdef JEVOIS_PLATFORM_A33
532 itsIMU.reset(
new jevois::IMUi2c(std::dynamic_pointer_cast<jevois::Camera>(itsCamera)));
536 #ifdef JEVOIS_PLATFORM_PRO
540 }
catch (...) {
LERROR(
"Sensor should have an IMU but we failed to initialize it."); }
544 LINFO(
"Using movie input " << camdev <<
" -- issue a 'streamon' to start processing.");
557 videomapping::freeze();
559 if (midx >=
int(itsMappings.size()))
560 {
LERROR(
"Mapping index " << midx <<
" out of range -- USING DEFAULT"); midx = -1; }
562 if (midx < 0) midx = itsDefaultMappingIdx;
568 LINFO(
"Using no USB video output.");
571 itsManualStreamon =
true;
575 LINFO(
"Loading USB video driver " << gd);
579 else if (gd.empty() ==
false)
581 LINFO(
"Saving output video to file " << gd);
584 itsManualStreamon =
true;
593 LINFO(
"Using OpenGL + ImGui display for video output");
598 LINFO(
"Using OpenGL display for video output");
603 LINFO(
"Using OpenCV display for video output");
607 itsManualStreamon =
true;
611 itsRunning.store(
true);
617 runScriptFromFile(JEVOIS_ENGINE_INIT_SCRIPT,
nullptr,
false);
629 itsRunning.store(
false);
631 #ifdef JEVOIS_PLATFORM_A33
633 itsCheckingMassStorage.store(
false);
639 if (itsModule) removeComponent(itsModule);
650 #ifdef JEVOIS_PLATFORM_A33
652 if (itsCheckMassStorageFut.valid())
661 #ifdef JEVOIS_PLATFORM_A33
662 void jevois::Engine::checkMassStorage()
664 itsCheckingMassStorage.store(
true);
666 while (itsCheckingMassStorage.load())
672 std::ifstream ifs(
"/sys/devices/platform/sunxi_usb_udc/gadget/lun0/mass_storage_in_use");
675 int inuse; ifs >> inuse;
676 if (itsMassStorageMode.load())
678 if (inuse == 0) stopMassStorageMode();
685 std::this_thread::sleep_for(std::chrono::milliseconds(500));
696 if (itsCamera) itsCamera->streamOn();
697 if (itsGadget) itsGadget->streamOn();
698 itsStreaming.store(
true);
707 if (itsGadget) itsGadget->abortStream();
708 if (itsCamera) itsCamera->abortStream();
711 LDEBUG(
"Stopping main loop...");
712 itsStopMainLoop.store(
true);
713 while (itsStopMainLoop.load() && itsRunning.load()) std::this_thread::sleep_for(std::chrono::milliseconds(10));
714 LDEBUG(
"Main loop stopped.");
718 if (itsGadget) itsGadget->streamOff();
719 if (itsCamera) itsCamera->streamOff();
726 itsRequestedFormat.store(idx);
734 LDEBUG(
"Set format number " << idx <<
" start...");
736 if (idx >= itsMappings.size())
737 LFATAL(
"Requested mapping index " << idx <<
" out of range [0 .. " << itsMappings.size()-1 <<
']');
740 setFormatInternal(idx);
741 LDEBUG(
"Set format number " << idx <<
" done");
745 void jevois::Engine::setFormatInternal(
size_t idx)
750 jevois::VideoMapping
const & m = itsMappings[idx];
751 setFormatInternal(m);
755 void jevois::Engine::setFormatInternal(jevois::VideoMapping
const & m,
bool reload)
761 itsModuleConstructionError =
"Unknown error while starting module " + m.modulename +
" ...";
763 #ifdef JEVOIS_PLATFORM_A33
764 if (itsMassStorageMode.load())
765 LFATAL(
"Cannot setup video streaming while in mass-storage mode. Eject the USB drive on your host computer first.");
773 LDEBUG(
"Removing current module " << itsModule->className() <<
": " << itsModule->descriptor());
774 try { removeComponent(itsModule); itsModule.reset();
LDEBUG(
"Current module removed."); }
781 LDEBUG(
"Setting camera format: " << m.cstrall());
782 try { itsCamera->setFormat(m); }
786 itsModuleConstructionError =
"Camera did not accept format:\n\n" + m.cstrall() +
787 "\n\nCheck videomappings.cfg and camera sensor specifications.";
791 LDEBUG(
"Setting gadget format: " << m.ostr());
792 try { itsGadget->setFormat(m); }
795 itsModuleConstructionError =
"Gadget did not accept format:\n\n" + m.ostr() +
796 "\n\nCheck videomappings.cfg for any unsupported output formats.";
803 itsCurrentMapping = m;
814 std::string
const sopath = m.sopath();
817 if (
python::get() ==
false)
LFATAL(
"Python disabled, delete BOOT:nopython and restart to enable python");
826 if (itsLoader.get() ==
nullptr || itsLoader->sopath() != sopath)
829 LINFO(
"Instantiating dynamic loader for " << sopath);
834 auto version_major = itsLoader->load<int()>(m.modulename +
"_version_major");
835 auto version_minor = itsLoader->load<int()>(m.modulename +
"_version_minor");
836 if (version_major() != JEVOIS_VERSION_MAJOR || version_minor() != JEVOIS_VERSION_MINOR)
837 LERROR(
"Module " << m.modulename <<
" in file " << sopath <<
" was build for JeVois v" << version_major() <<
'.'
838 << version_minor() <<
", but running framework is v" << JEVOIS_VERSION_STRING <<
" -- TRYING ANYWAY");
841 auto create = itsLoader->load<std::shared_ptr<jevois::Module>(std::string
const &)>(m.modulename +
"_create");
842 itsModule = create(m.modulename);
848 boost::unique_lock<boost::shared_mutex> ulck(itsSubMtx);
851 itsSubComponents.push_back(itsModule);
852 itsModule->itsParent =
this;
853 itsModule->setPath(sopath.substr(0, sopath.rfind(
'/')));
857 if (itsInitialized) itsModule->runPreInit();
859 std::string
const paramcfg = itsModule->absolutePath(JEVOIS_MODULE_PARAMS_FILENAME);
860 std::ifstream ifs(paramcfg);
if (ifs.is_open()) itsModule->setParamsFromStream(ifs, paramcfg);
862 if (itsInitialized) { itsModule->setInitialized(); itsModule->runPostInit(); }
865 std::shared_ptr<jevois::UserInterface> ser;
866 for (
auto & s : itsSerials)
870 runScriptFromFile(itsModule->absolutePath(JEVOIS_MODULE_SCRIPT_FILENAME), ser,
false);
872 LINFO(
"Module [" << m.modulename <<
"] loaded, initialized, and ready.");
873 itsModuleConstructionError.clear();
879 LERROR(
"Module [" << m.modulename <<
"] startup error and not operational.");
898 for (
auto & s : itsSerials)
900 try { s->
writeString(
"INF READY JEVOIS " JEVOIS_VERSION_STRING); }
903 while (itsRunning.load())
909 itsWatchdog->reset();
914 int rf = itsRequestedFormat.load();
918 itsRequestedFormat.store(-2);
923 if (rf != -1 && itsStreaming.load())
926 if (itsGadget) itsGadget->abortStream();
927 if (itsCamera) itsCamera->abortStream();
929 if (itsGadget) itsGadget->streamOff();
930 if (itsCamera) itsCamera->streamOff();
931 itsStreaming.store(
false);
936 if (itsGUIhelper) itsGUIhelper->reset( (rf != -1) );
943 setFormatInternal(itsCurrentMapping,
true);
948 if (rf != -1 && itsCurrentMapping.ofmt != 0)
952 if (itsCamera) itsCamera->streamOn();
953 if (itsGadget) itsGadget->streamOn();
954 itsStreaming.store(
true);
960 if (itsGUIhelper && itsStreaming.load() ==
false)
964 if (itsCamera) itsCamera->streamOn();
965 if (itsGadget) itsGadget->streamOn();
966 itsStreaming.store(
true);
977 if (itsGadget) itsGadget->abortStream();
978 if (itsCamera) itsCamera->abortStream();
980 if (itsGadget) itsGadget->streamOff();
981 if (itsCamera) itsCamera->streamOff();
982 itsStreaming.store(
false);
988 if (itsStreaming.load())
993 if (itsModuleConstructionError.empty() ==
false)
996 reportError(itsModuleConstructionError);
1011 switch (itsCurrentMapping.ofmt)
1020 if (itsGUIhelper) itsGUIhelper->headlessDisplay();
1044 catch (...) { reportError(); }
1051 itsNumSerialSent.store(0);
1055 if (itsStopMainLoop.load())
1057 itsStreaming.store(
false);
1058 LDEBUG(
"-- Main loop stopped --");
1059 itsStopMainLoop.store(
false);
1064 LDEBUG(
"No processing module loaded or not streaming... Sleeping...");
1065 std::this_thread::sleep_for(std::chrono::milliseconds(25));
1070 for (
auto & s : itsSerials)
1074 std::string str;
bool parsed =
false;
bool success =
false;
1083 pfx = JEVOIS_JVINV_PREFIX;
1084 str = str.substr(pfx.length());
1091 try { parsed = parseCommand(str, s, pfx);
success = parsed; }
1092 catch (std::exception
const & e)
1093 { s->
writeString(pfx, std::string(
"ERR ") + e.what()); parsed =
true; }
1095 { s->
writeString(pfx,
"ERR Unknown error"); parsed =
true; }
1097 if (parsed ==
false)
1102 try { itsModule->parseSerial(str, s);
success =
true; }
1103 catch (std::exception
const & me) { s->
writeString(pfx, std::string(
"ERR ") + me.what()); }
1104 catch (...) { s->
writeString(pfx,
"ERR Command [" + str +
"] not recognized by Engine or Module"); }
1106 else s->
writeString(pfx,
"ERR Unsupported command [" + str +
"] and no module");
1124 if (islog ==
false && slim)
1126 if (itsNumSerialSent.load() >= slim)
return;
1134 case jevois::engine::SerPort::None:
1137 case jevois::engine::SerPort::All:
1138 for (
auto & s : itsSerials)
1142 case jevois::engine::SerPort::Hard:
1143 for (
auto & s : itsSerials)
1148 case jevois::engine::SerPort::USB:
1149 for (
auto & s : itsSerials)
1157 if (itsGUIhelper && ((islog && itsGUIhelper->serlogEnabled()) || (!islog && itsGUIhelper->seroutEnabled())))
1158 for (
auto & s : itsSerials)
1165 void jevois::Engine::reportError(std::string
const & err)
1171 if (itsGUIhelper->frameStarted() ==
false) {
unsigned short w,
h; itsGUIhelper->startFrame(w,
h); }
1173 else itsGUIhelper->reportError(err);
1174 itsGUIhelper->endFrame();
1181 if (itsCurrentMapping.ofmt != 0 && itsCurrentMapping.ofmt !=
JEVOISPRO_FMT_GUI && itsVideoErrors.load())
1186 if (itsVideoErrorImage.valid() ==
false) itsGadget->get(itsVideoErrorImage);
1197 if (itsVideoErrorImage.valid()) itsGadget->send(itsVideoErrorImage);
1202 itsVideoErrorImage.invalidate();
1214 {
return itsFrame; }
1218 {
return itsModule; }
1226 {
return std::dynamic_pointer_cast<jevois::Camera>(itsCamera); }
1230 {
return itsCurrentMapping; }
1234 {
return itsMappings.size(); }
1239 if (idx >= itsMappings.size())
1240 LFATAL(
"Index " << idx <<
" out of range [0 .. " << itsMappings.size()-1 <<
']');
1242 return itsMappings[idx];
1249 if (iformat == 0 || iframe == 0)
return itsDefaultMappingIdx;
1255 float const fps = jevois::VideoMapping::uvcToFps(interval);
1258 for (jevois::VideoMapping
const & m : itsMappings)
1259 if (m.uvcformat == iformat && m.uvcframe == iframe && std::fabs(m.ofps - fps) < 0.1F)
return idx;
1262 LFATAL(
"No video mapping for iformat=" << iformat <<
", iframe=" << iframe <<
", interval=" << interval);
1268 for (jevois::VideoMapping
const & m : itsMappings)
1269 if (m.uvcformat == iformat && m.uvcframe == iframe)
return idx;
1272 LFATAL(
"No video mapping for iformat=" << iformat <<
", iframe=" << iframe <<
", interval=" << interval);
1278 {
return itsMappings[itsDefaultMappingIdx]; }
1282 {
return itsDefaultMappingIdx; }
1287 for (jevois::VideoMapping
const & m : itsMappings)
1292 jevois::VideoMapping
const &
1294 float oframespersec)
const
1296 for (jevois::VideoMapping
const & m : itsMappings)
1297 if (m.match(oformat, owidth, oheight, oframespersec))
return m;
1300 owidth <<
'x' << oheight <<
" @ " << oframespersec <<
" fps");
1304 void jevois::Engine::foreachCamCtrl(std::function<
void(
struct v4l2_queryctrl & qc, std::set<int> & doneids)> && func)
1306 struct v4l2_queryctrl qc = { }; std::set<int> doneids;
1312 qc.id = cls | 0x900;
unsigned int old_id;
1315 qc.id |= V4L2_CTRL_FLAG_NEXT_CTRL; old_id = qc.id;
bool failed =
false;
1316 try { func(qc, doneids); }
catch (...) { failed =
true; }
1320 qc.id |= V4L2_CTRL_FLAG_NEXT_CTRL;
1321 if (qc.id == old_id) { ++qc.id;
if (qc.id > 100 + (cls | 0x900 | V4L2_CTRL_FLAG_NEXT_CTRL))
break; }
1322 else if (failed)
break;
1328 std::string jevois::Engine::camctrlname(
int id,
char const * longname)
const
1330 for (
size_t i = 0; i <
sizeof camcontrols /
sizeof camcontrols[0]; ++i)
1331 if (camcontrols[i].
id ==
id)
return camcontrols[i].shortname;
1334 return abbreviate(longname);
1338 int jevois::Engine::camctrlid(std::string
const & shortname)
1340 for (
size_t i = 0; i <
sizeof camcontrols /
sizeof camcontrols[0]; ++i)
1341 if (shortname.compare(camcontrols[i].shortname) == 0)
return camcontrols[i].id;
1344 struct v4l2_queryctrl qc = { };
1350 qc.id = cls | 0x900;
1353 qc.id |= V4L2_CTRL_FLAG_NEXT_CTRL;
unsigned int old_id = qc.id;
bool failed =
false;
1356 itsCamera->queryControl(qc);
1357 if (abbreviate(
reinterpret_cast<char const *
>(qc.name)) == shortname)
return qc.id;
1359 catch (...) { failed =
true; }
1364 qc.id |= V4L2_CTRL_FLAG_NEXT_CTRL;
1365 if (qc.id == old_id) { ++qc.id;
if (qc.id > 100 + (cls | 0x900 | V4L2_CTRL_FLAG_NEXT_CTRL))
break; }
1366 else if (failed)
break;
1370 LFATAL(
"Could not find control [" << shortname <<
"] in the camera");
1374 std::string jevois::Engine::camCtrlHelp(
struct v4l2_queryctrl & qc, std::set<int> & doneids)
1377 itsCamera->queryControl(qc);
1378 qc.id &= ~V4L2_CTRL_FLAG_NEXT_CTRL;
1381 if (doneids.find(qc.id) != doneids.end())
return std::string();
else doneids.insert(qc.id);
1384 struct v4l2_control ctrl = { }; ctrl.id = qc.id;
1385 itsCamera->getControl(ctrl);
1388 std::ostringstream ss;
1389 ss <<
"- " << camctrlname(qc.id,
reinterpret_cast<char const *
>(qc.name));
1393 case V4L2_CTRL_TYPE_INTEGER:
1394 ss <<
" [int] min=" << qc.minimum <<
" max=" << qc.maximum <<
" step=" << qc.step
1395 <<
" def=" << qc.default_value <<
" curr=" << ctrl.value;
1407 case V4L2_CTRL_TYPE_BOOLEAN:
1408 ss <<
" [bool] default=" << qc.default_value <<
" curr=" << ctrl.value;
1417 case V4L2_CTRL_TYPE_BUTTON:
1421 case V4L2_CTRL_TYPE_BITMASK:
1422 ss <<
" [bitmask] max=" << qc.maximum <<
" def=" << qc.default_value <<
" curr=" << ctrl.value;
1425 case V4L2_CTRL_TYPE_MENU:
1427 struct v4l2_querymenu querymenu = { };
1428 querymenu.id = qc.id;
1429 ss <<
" [menu] values ";
1430 for (querymenu.index = qc.minimum; querymenu.index <= (
unsigned int)qc.maximum; ++querymenu.index)
1432 try { itsCamera->queryMenu(querymenu); }
catch (...) { strcpy((
char *)(querymenu.name),
"fixme"); }
1433 ss << querymenu.index <<
':' << querymenu.name <<
' ';
1435 ss <<
"curr=" << ctrl.value;
1440 ss <<
"[unknown type]";
1443 if (qc.flags & V4L2_CTRL_FLAG_DISABLED) ss <<
" [DISABLED]";
1449 std::string jevois::Engine::camCtrlInfo(
struct v4l2_queryctrl & qc, std::set<int> & doneids)
1452 itsCamera->queryControl(qc);
1453 qc.id &= ~V4L2_CTRL_FLAG_NEXT_CTRL;
1456 if (doneids.find(qc.id) != doneids.end())
return std::string();
else doneids.insert(qc.id);
1459 struct v4l2_control ctrl = { }; ctrl.id = qc.id;
1460 itsCamera->getControl(ctrl);
1463 std::ostringstream ss;
1464 ss << camctrlname(qc.id,
reinterpret_cast<char const *
>(qc.name));
1466 if (qc.flags & V4L2_CTRL_FLAG_DISABLED) ss <<
" D ";
1470 case V4L2_CTRL_TYPE_INTEGER:
1471 ss <<
" I " << qc.minimum <<
' ' << qc.maximum <<
' ' << qc.step
1472 <<
' ' << qc.default_value <<
' ' << ctrl.value;
1483 case V4L2_CTRL_TYPE_BOOLEAN:
1484 ss <<
" B " << qc.default_value <<
' ' << ctrl.value;
1492 case V4L2_CTRL_TYPE_BUTTON:
1496 case V4L2_CTRL_TYPE_BITMASK:
1497 ss <<
" K " << qc.maximum <<
' ' << qc.default_value <<
' ' << ctrl.value;
1500 case V4L2_CTRL_TYPE_MENU:
1502 struct v4l2_querymenu querymenu = { };
1503 querymenu.id = qc.id;
1504 ss <<
" M " << qc.default_value <<
' ' << ctrl.value;
1505 for (querymenu.index = qc.minimum; querymenu.index <= (
unsigned int)qc.maximum; ++querymenu.index)
1507 try { itsCamera->queryMenu(querymenu); }
catch (...) { strcpy((
char *)(querymenu.name),
"fixme"); }
1508 ss <<
' ' << querymenu.index <<
':' << querymenu.name <<
' ';
1520 #ifdef JEVOIS_PLATFORM_A33
1522 void jevois::Engine::startMassStorageMode()
1526 if (itsMassStorageMode.load()) {
LERROR(
"Already in mass-storage mode -- IGNORED");
return; }
1529 if (itsModule) { removeComponent(itsModule); itsModule.reset(); }
1530 if (itsLoader) itsLoader.reset();
1534 if (
std::system(
"mount -o remount,ro /jevois"))
LERROR(
"Failed to remount /jevois read-only -- IGNORED");
1537 std::ofstream ofs(JEVOIS_USBSD_SYS);
1538 if (ofs.is_open() ==
false)
LFATAL(
"Cannot setup mass-storage backing file to " << JEVOIS_USBSD_SYS);
1539 ofs << JEVOIS_USBSD_FILE << std::endl;
1541 LINFO(
"Exported JEVOIS partition of microSD to host computer as virtual flash drive.");
1542 itsMassStorageMode.store(
true);
1546 void jevois::Engine::stopMassStorageMode()
1549 LINFO(
"JeVois virtual USB drive ejected by host -- REBOOTING");
1559 #ifdef JEVOIS_PLATFORM_A33
1560 itsCheckingMassStorage.store(
false);
1562 itsRunning.store(
false);
1564 #ifdef JEVOIS_PLATFORM_A33
1566 if ( ! std::ofstream(
"/proc/sys/kernel/sysrq").put(
'1'))
LERROR(
"Cannot trigger hard reset -- please unplug me!");
1567 if ( ! std::ofstream(
"/proc/sysrq-trigger").put(
's'))
LERROR(
"Cannot trigger hard reset -- please unplug me!");
1568 if ( ! std::ofstream(
"/proc/sysrq-trigger").put(
'b'))
LERROR(
"Cannot trigger hard reset -- please unplug me!");
1579 itsGadget->abortStream();
1580 itsCamera->abortStream();
1581 itsStreaming.store(
false);
1582 itsGadget->streamOff();
1583 itsCamera->streamOff();
1584 itsRunning.store(
false);
1590 void jevois::Engine::cmdInfo(std::shared_ptr<UserInterface> s,
bool showAll, std::string
const & pfx)
1592 s->
writeString(pfx,
"help - print this help message");
1593 s->
writeString(pfx,
"help2 - print compact help message about current vision module only");
1594 s->
writeString(pfx,
"info - show system information including CPU speed, load and temperature");
1595 s->
writeString(pfx,
"setpar <name> <value> - set a parameter value");
1596 s->
writeString(pfx,
"getpar <name> - get a parameter value(s)");
1597 s->
writeString(pfx,
"runscript <filename> - run script commands in specified file");
1598 s->
writeString(pfx,
"setcam <ctrl> <val> - set camera control <ctrl> to value <val>");
1599 s->
writeString(pfx,
"getcam <ctrl> - get value of camera control <ctrl>");
1603 s->
writeString(pfx,
"setcamreg <reg> <val> - set raw camera register <reg> to value <val>");
1604 s->
writeString(pfx,
"getcamreg <reg> - get value of raw camera register <reg>");
1605 s->
writeString(pfx,
"setimureg <reg> <val> - set raw IMU register <reg> to value <val>");
1606 s->
writeString(pfx,
"getimureg <reg> - get value of raw IMU register <reg>");
1607 s->
writeString(pfx,
"setimuregs <reg> <num> <val1> ... <valn> - set array of raw IMU register values");
1608 s->
writeString(pfx,
"getimuregs <reg> <num> - get array of raw IMU register values");
1609 s->
writeString(pfx,
"setdmpreg <reg> <val> - set raw DMP register <reg> to value <val>");
1610 s->
writeString(pfx,
"getdmpreg <reg> - get value of raw DMP register <reg>");
1611 s->
writeString(pfx,
"setdmpregs <reg> <num> <val1> ... <valn> - set array of raw DMP register values");
1612 s->
writeString(pfx,
"getdmpregs <reg> <num> - get array of raw DMP register values");
1615 s->
writeString(pfx,
"listmappings - list all available video mappings");
1616 s->
writeString(pfx,
"setmapping <num> - select video mapping <num>, only possible while not streaming");
1617 s->
writeString(pfx,
"setmapping2 <CAMmode> <CAMwidth> <CAMheight> <CAMfps> <Vendor> <Module> - set no-USB-out "
1618 "video mapping defined on the fly, while not streaming");
1619 s->
writeString(pfx,
"reload - reload and reset the current module");
1621 if (showAll || itsCurrentMapping.ofmt == 0 || itsManualStreamon)
1623 s->
writeString(pfx,
"streamon - start camera video streaming");
1624 s->
writeString(pfx,
"streamoff - stop camera video streaming");
1628 s->
writeString(pfx,
"serlog <string> - forward string to the serial port(s) specified by the serlog parameter");
1629 s->
writeString(pfx,
"serout <string> - forward string to the serial port(s) specified by the serout parameter");
1634 s->
writeString(pfx,
"caminfo - returns machine-readable info about camera parameters");
1635 s->
writeString(pfx,
"cmdinfo [all] - returns machine-readable info about Engine commands");
1636 s->
writeString(pfx,
"modcmdinfo - returns machine-readable info about Module commands");
1637 s->
writeString(pfx,
"paraminfo [hot|mod|modhot] - returns machine-readable info about parameters");
1638 s->
writeString(pfx,
"serinfo - returns machine-readable info about serial settings (serout serlog serstyle serprec serstamp)");
1639 s->
writeString(pfx,
"fileget <filepath> - get a file from JeVois to the host. Use with caution!");
1640 s->
writeString(pfx,
"fileput <filepath> - put a file from the host to JeVois. Use with caution!");
1643 #ifdef JEVOIS_PLATFORM_A33
1644 s->
writeString(pfx,
"usbsd - export the JEVOIS partition of the microSD card as a virtual USB drive");
1646 s->
writeString(pfx,
"sync - commit any pending data write to microSD");
1647 s->
writeString(pfx,
"date [date and time] - get or set the system date and time");
1649 s->
writeString(pfx,
"shell <string> - execute <string> as a Linux shell command. Use with caution!");
1650 s->
writeString(pfx,
"shellstart - execute all subsequent commands as Linux shell commands. Use with caution!");
1651 s->
writeString(pfx,
"shellstop - stop executing all subsequent commands as Linux shell commands.");
1654 s->
writeString(pfx,
"dnnget <key> - download and install a DNN from JeVois Model Converter");
1657 #ifdef JEVOIS_PLATFORM
1658 s->
writeString(pfx,
"restart - restart the JeVois smart camera");
1661 #ifndef JEVOIS_PLATFORM_A33
1667 void jevois::Engine::modCmdInfo(std::shared_ptr<UserInterface> s, std::string
const & pfx)
1671 std::stringstream css; itsModule->supportedCommands(css);
1672 for (std::string line; std::getline(css, line); ) s->
writeString(pfx, line);
1686 if (str ==
"shellstop") { itsShellMode =
false;
return true; }
1690 for (std::string
const & r : rvec) s->
writeString(pfx, r);
1706 switch (str.length())
1709 LDEBUG(
"Ignoring empty string");
return true;
1713 if (str[0] ==
'~') {
LDEBUG(
"Ignoring modem config command [~]");
return true; }
1717 if (str[0] ==
'#') { sendSerial(str,
true);
return true; }
1723 if (str[0] ==
'~') {
LDEBUG(
"Ignoring modem config command [" << str <<
']');
return true; }
1726 if (str[0] ==
'A' && str[1] ==
'T') {
LDEBUG(
"Ignoring AT command [" << str <<
']');
return true; }
1730 if (str[0] ==
'#') { sendSerial(str,
true);
return true; }
1733 size_t const idx = str.find(
' '); std::string cmd, rem;
1734 if (idx == str.npos) cmd = str;
else { cmd = str.substr(0, idx);
if (idx < str.length()) rem = str.substr(idx+1); }
1742 cmdInfo(s,
false, pfx);
1755 std::stringstream pss; constructHelpMessage(pss);
1756 for (std::string line; std::getline(pss, line); ) s->
writeString(pfx, line);
1759 s->
writeString(pfx,
"AVAILABLE CAMERA CONTROLS:");
1762 foreachCamCtrl([
this,&pfx,&s](
struct v4l2_queryctrl & qc, std::set<int> & doneids)
1766 std::string hlp = camCtrlHelp(qc, doneids);
1767 if (hlp.empty() ==
false) s->
writeString(pfx, hlp);
1774 if (cmd ==
"caminfo")
1777 foreachCamCtrl([
this,&pfx,&s](
struct v4l2_queryctrl & qc, std::set<int> & doneids)
1781 std::string hlp = camCtrlInfo(qc, doneids);
1782 if (hlp.empty() ==
false) s->
writeString(pfx, hlp);
1789 if (cmd ==
"cmdinfo")
1791 bool showAll = (rem ==
"all") ?
true :
false;
1792 cmdInfo(s, showAll, pfx);
1797 if (cmd ==
"modcmdinfo")
1804 if (cmd ==
"paraminfo")
1806 std::map<std::string, std::string> categs;
1807 bool skipFrozen = (rem ==
"hot" || rem ==
"modhot") ?
true :
false;
1809 if (rem ==
"mod" || rem ==
"modhot")
1812 if (itsModule) itsModule->paramInfo(s, categs, skipFrozen, instanceName(), pfx);
1817 paramInfo(s, categs, skipFrozen,
"", pfx);
1824 if (cmd ==
"serinfo")
1826 std::string info = getParamStringUnique(
"serout") +
' ' + getParamStringUnique(
"serlog");
1828 info +=
' ' + mod->getParamStringUnique(
"serstyle") +
' ' + mod->getParamStringUnique(
"serprec") +
1829 ' ' + mod->getParamStringUnique(
"serstamp");
1830 else info +=
" - - -";
1843 std::stringstream css; itsModule->supportedCommands(css);
1846 for (std::string line; std::getline(css, line); ) s->
writeString(pfx, line);
1854 std::unordered_map<std::string,
1855 std::unordered_map<std::string,
1856 std::vector<std::pair<std::string,
1859 itsModule->populateHelpMessage(
"", helplist);
1861 if (helplist.empty())
1865 for (
auto const & c : helplist)
1871 for (
auto const & n : c.second)
1873 std::vector<std::string> tok =
jevois::split(n.first,
"[\\r\\n]+");
1875 for (
auto const & t : tok)
1880 auto const & v = n.second;
1883 if (v[0].second.empty())
1886 s->
writeString(pfx, t +
" current=[" + v[0].second +
']');
1888 else if (v.size() > 1)
1890 std::string sss = t +
" current=";
1891 for (
auto const & pp : v)
1892 if (pp.second.empty() ==
false) sss +=
'[' + pp.first +
':' + pp.second +
"] ";
1917 s->
writeString(pfx,
"INFO: JeVois " JEVOIS_VERSION_STRING);
1921 if (itsModule) s->
writeString(pfx,
"INFO: " + itsCurrentMapping.str());
1922 else s->
writeString(pfx,
"INFO: " + jevois::VideoMapping().str());
1927 if (cmd ==
"setpar")
1929 size_t const remidx = rem.find(
' ');
1930 if (remidx != rem.npos)
1932 std::string
const desc = rem.substr(0, remidx);
1933 if (remidx < rem.length())
1935 std::string
const val = rem.substr(remidx+1);
1936 setParamString(desc, val);
1940 errmsg =
"Need to provide a parameter name and a parameter value in setpar";
1944 if (cmd ==
"getpar")
1946 auto vec = getParamString(rem);
1947 for (
auto const & p : vec) s->
writeString(pfx, p.first +
' ' + p.second);
1952 if (cmd ==
"setcam")
1954 std::istringstream ss(rem); std::string ctrl;
int val; ss >> ctrl >> val;
1955 struct v4l2_control c = { }; c.id = camctrlid(ctrl); c.value = val;
1956 itsCamera->setControl(c);
1961 if (cmd ==
"getcam")
1963 struct v4l2_control c = { }; c.id = camctrlid(rem);
1964 itsCamera->getControl(c);
1970 if (cmd ==
"setcamreg")
1974 auto cam = std::dynamic_pointer_cast<jevois::Camera>(itsCamera);
1978 std::istringstream ss(rem); std::string reg, val; ss >> reg >> val;
1979 cam->writeRegister(std::stoi(reg,
nullptr, 0), std::stoi(val,
nullptr, 0));
1982 else errmsg =
"Not using a camera for video input";
1984 else errmsg =
"Access to camera registers is disabled, enable with: setpar camreg true";
1988 if (cmd ==
"getcamreg")
1992 auto cam = std::dynamic_pointer_cast<jevois::Camera>(itsCamera);
1995 unsigned int val = cam->readRegister(std::stoi(rem,
nullptr, 0));
1996 std::ostringstream os; os << std::hex << val;
2000 else errmsg =
"Not using a camera for video input";
2002 else errmsg =
"Access to camera registers is disabled, enable with: setpar camreg true";
2006 if (cmd ==
"setimureg")
2013 std::istringstream ss(rem); std::string reg, val; ss >> reg >> val;
2014 itsIMU->writeRegister(std::stoi(reg,
nullptr, 0), std::stoi(val,
nullptr, 0));
2017 else errmsg =
"No IMU driver loaded";
2019 else errmsg =
"Access to IMU registers is disabled, enable with: setpar imureg true";
2023 if (cmd ==
"getimureg")
2029 unsigned int val = itsIMU->readRegister(std::stoi(rem,
nullptr, 0));
2030 std::ostringstream os; os << std::hex << val;
2034 else errmsg =
"No IMU driver loaded";
2036 else errmsg =
"Access to IMU registers is disabled, enable with: setpar imureg true";
2040 if (cmd ==
"setimuregs")
2048 if (v.size() < 3) errmsg =
"Malformed arguments, need at least 3";
2051 unsigned short reg = std::stoi(v[0],
nullptr, 0);
2052 size_t num = std::stoi(v[1],
nullptr, 0);
2053 if (num > 32) errmsg =
"Maximum transfer size is 32 bytes";
2054 else if (num != v.size() - 2) errmsg =
"Incorrect number of data bytes, should pass " + v[1] +
" values.";
2057 unsigned char data[32];
2058 for (
size_t i = 2; i < v.size(); ++i) data[i-2] = std::stoi(v[i],
nullptr, 0) & 0xff;
2060 itsIMU->writeRegisterArray(reg, data, num);
2065 else errmsg =
"No IMU driver loaded";
2067 else errmsg =
"Access to IMU registers is disabled, enable with: setpar imureg true";
2071 if (cmd ==
"getimuregs")
2077 std::istringstream ss(rem); std::string reg, num; ss >> reg >> num;
2078 int n = std::stoi(num,
nullptr, 0);
2080 if (n > 32) errmsg =
"Maximum transfer size is 32 bytes";
2083 unsigned char data[32];
2084 itsIMU->readRegisterArray(std::stoi(reg,
nullptr, 0), data, n);
2086 std::ostringstream os; os << std::hex;
2087 for (
int i = 0; i < n; ++i) os << (
unsigned int)(data[i]) <<
' ';
2092 else errmsg =
"No IMU driver loaded";
2094 else errmsg =
"Access to IMU registers is disabled, enable with: setpar imureg true";
2098 if (cmd ==
"setdmpreg")
2105 std::istringstream ss(rem); std::string reg, val; ss >> reg >> val;
2106 itsIMU->writeDMPregister(std::stoi(reg,
nullptr, 0), std::stoi(val,
nullptr, 0));
2109 else errmsg =
"No IMU driver loaded";
2111 else errmsg =
"Access to IMU registers is disabled, enable with: setpar imureg true";
2115 if (cmd ==
"getdmpreg")
2121 unsigned int val = itsIMU->readDMPregister(std::stoi(rem,
nullptr, 0));
2122 std::ostringstream os; os << std::hex << val;
2126 else errmsg =
"No IMU driver loaded";
2128 else errmsg =
"Access to IMU registers is disabled, enable with: setpar imureg true";
2132 if (cmd ==
"setdmpregs")
2140 if (v.size() < 3) errmsg =
"Malformed arguments, need at least 3";
2143 unsigned short reg = std::stoi(v[0],
nullptr, 0);
2144 size_t num = std::stoi(v[1],
nullptr, 0);
2145 if (num > 32) errmsg =
"Maximum transfer size is 32 bytes";
2146 else if (num != v.size() - 2) errmsg =
"Incorrect number of data bytes, should pass " + v[1] +
" values.";
2149 unsigned char data[32];
2150 for (
size_t i = 2; i < v.size(); ++i) data[i-2] = std::stoi(v[i],
nullptr, 0) & 0xff;
2152 itsIMU->writeDMPregisterArray(reg, data, num);
2157 else errmsg =
"No IMU driver loaded";
2159 else errmsg =
"Access to IMU registers is disabled, enable with: setpar imureg true";
2163 if (cmd ==
"getdmpregs")
2169 std::istringstream ss(rem); std::string reg, num; ss >> reg >> num;
2170 int n = std::stoi(num,
nullptr, 0);
2172 if (n > 32) errmsg =
"Maximum transfer size is 32 bytes";
2175 unsigned char data[32];
2176 itsIMU->readDMPregisterArray(std::stoi(reg,
nullptr, 0), data, n);
2178 std::ostringstream os; os << std::hex;
2179 for (
int i = 0; i < n; ++i) os << (
unsigned int)(data[i]) <<
' ';
2184 else errmsg =
"No IMU driver loaded";
2186 else errmsg =
"Access to IMU registers is disabled, enable with: setpar imureg true";
2190 if (cmd ==
"listmappings")
2194 for (
size_t idx = 0; idx < itsMappings.size(); ++idx)
2197 if (idxstr.length() < 5) idxstr = std::string(5 - idxstr.length(),
' ') + idxstr;
2198 s->
writeString(pfx, idxstr +
" - " + itsMappings[idx].str());
2204 if (cmd ==
"setmapping")
2206 size_t const idx = std::stoi(rem);
2208 if (itsStreaming.load() && itsCurrentMapping.ofmt)
2209 errmsg =
"Cannot set mapping while streaming: Stop your webcam program on the host computer first.";
2210 else if (idx >= itsMappings.size())
2211 errmsg =
"Requested mapping index " +
std::to_string(idx) +
" out of range [0 .. " +
2217 setFormatInternal(idx);
2220 catch (std::exception
const & e) { errmsg =
"Error parsing or setting mapping [" + rem +
"]: " + e.what(); }
2221 catch (...) { errmsg =
"Error parsing or setting mapping [" + rem +
']'; }
2226 if (cmd ==
"setmapping2")
2228 if (itsStreaming.load() && itsCurrentMapping.ofmt)
2229 errmsg =
"Cannot set mapping while streaming: Stop your webcam program on the host computer first.";
2234 jevois::VideoMapping m; std::istringstream full(
"NONE 0 0 0.0 " + rem); full >> m;
2235 setFormatInternal(m);
2238 catch (std::exception
const & e) { errmsg =
"Error parsing or setting mapping [" + rem +
"]: " + e.what(); }
2239 catch (...) { errmsg =
"Error parsing or setting mapping [" + rem +
']'; }
2244 if (cmd ==
"reload")
2246 setFormatInternal(itsCurrentMapping,
true);
2251 if (itsCurrentMapping.ofmt == 0 || itsCurrentMapping.ofmt ==
JEVOISPRO_FMT_GUI || itsManualStreamon)
2253 if (cmd ==
"streamon")
2256 itsCamera->streamOn();
2257 itsGadget->streamOn();
2258 itsStreaming.store(
true);
2262 if (cmd ==
"streamoff")
2265 itsGadget->abortStream();
2266 itsCamera->abortStream();
2268 itsStreaming.store(
false);
2270 itsGadget->streamOff();
2271 itsCamera->streamOff();
2284 if (cmd ==
"serlog")
2286 sendSerial(rem,
true);
2291 if (cmd ==
"serout")
2293 sendSerial(rem,
false);
2298 #ifdef JEVOIS_PLATFORM_A33
2301 if (itsStreaming.load())
2303 errmsg =
"Cannot export microSD over USB while streaming: ";
2304 if (itsCurrentMapping.ofmt) errmsg +=
"Stop your webcam program on the host computer first.";
2305 else errmsg +=
"Issue a 'streamoff' command first.";
2309 startMassStorageMode();
2318 if (
std::system(
"sync")) errmsg =
"Disk sync failed";
2326 s->
writeString(pfx,
"date now " + dat.substr(0, dat.size()-1));
2331 if (cmd ==
"runscript")
2333 std::string
const fname = itsModule ? itsModule->absolutePath(rem) : rem;
2335 try { runScriptFromFile(fname, s,
true);
return true; }
2336 catch (...) { errmsg =
"Script " + fname +
" execution failed"; }
2344 for (std::string
const & r : rvec) s->
writeString(pfx, r);
2349 if (cmd ==
"shellstart")
2351 itsShellMode =
true;
2358 if (cmd ==
"dnnget")
2360 if (rem.length() != 4 || std::regex_match(rem, std::regex(
"^[a-zA-Z0-9]+$")) ==
false)
2361 errmsg =
"Key must be a 4-character alphanumeric string, as emailed to you by the model converter.";
2365 s->
writeString(pfx,
"Downloading custom DNN model " + rem +
" ...");
2366 std::string
const zip = rem +
".zip";
2367 std::string ret =
jevois::system(
"/usr/bin/curl " JEVOIS_CUSTOM_DNN_URL
"/" + zip +
" -o "
2368 JEVOIS_CUSTOM_DNN_PATH
"/" + zip,
true);
2370 for (std::string
const & r : rvec) s->
writeString(pfx, r);
2373 std::ifstream ifs(JEVOIS_CUSTOM_DNN_PATH
"/" + zip);
2374 if (ifs.is_open() ==
false)
2375 errmsg =
"Failed to download. Check network connectivity and available disk space.";
2379 s->
writeString(pfx,
"Unpacking custom DNN model " + rem +
" ...");
2380 ret =
jevois::system(
"/usr/bin/unzip -o " JEVOIS_CUSTOM_DNN_PATH
"/" + zip +
2381 " -d " JEVOIS_CUSTOM_DNN_PATH,
true);
2384 ret =
jevois::system(
"/bin/rm " JEVOIS_CUSTOM_DNN_PATH
"/" + zip,
true);
2387 s->
writeString(pfx,
"Reload your model zoo for changes to take effect.");
2396 if (cmd ==
"fileget")
2398 std::shared_ptr<jevois::Serial> ser = std::dynamic_pointer_cast<jevois::Serial>(s);
2400 errmsg =
"File transfer only supported over USB or Hard serial ports";
2403 std::string
const abspath = itsModule ? itsModule->absolutePath(rem) : rem;
2410 if (cmd ==
"fileput")
2412 std::shared_ptr<jevois::Serial> ser = std::dynamic_pointer_cast<jevois::Serial>(s);
2414 errmsg =
"File transfer only supported over USB or Hard serial ports";
2417 std::string
const abspath = itsModule ? itsModule->absolutePath(rem) : rem;
2424 #ifdef JEVOIS_PLATFORM
2426 if (cmd ==
"restart")
2428 s->
writeString(pfx,
"Restart command received - bye-bye!");
2430 if (itsStreaming.load())
2431 s->
writeString(pfx,
"ERR Video streaming is on - you should quit your video viewer before rebooting");
2435 #ifdef JEVOIS_PLATFORM_A33
2437 std::ofstream(JEVOIS_USBSD_SYS).put(
'\n');
2449 #ifndef JEVOIS_PLATFORM_A33
2453 s->
writeString(pfx,
"Quit command received - bye-bye!");
2464 if (errmsg.size())
throw std::runtime_error(
"Command error [" + str +
"]: " + errmsg);
2475 std::ifstream ifs(filename);
2476 if (!ifs) {
if (throw_no_file)
LFATAL(
"Could not open file " << filename);
else return; }
2482 if (itsSerials.empty())
LFATAL(
"Need at least one active serial to run script");
2486 case jevois::engine::SerPort::Hard:
2490 case jevois::engine::SerPort::USB:
2502 if (!ser) ser = itsSerials.front();
2507 for (std::string line; std::getline(ifs, line); )
2515 if (line.length() == 0 || line[0] ==
'#')
continue;
2520 bool parsed =
false;
2521 try { parsed = parseCommand(line, ser); }
2522 catch (std::exception
const & e)
2527 if (parsed ==
false)
2531 try { itsModule->parseSerial(line, ser); }
2532 catch (std::exception
const & me)
2537 else ser->
writeString(
"ERR Unsupported command [" + line +
"] and no module");
2549 ImGui::Columns(2,
"camctrl");
2551 foreachCamCtrl([
this](
struct v4l2_queryctrl & qc, std::set<int> & doneids)
2553 try { camCtrlGUI(qc, doneids); }
catch (...) { }
2560 void jevois::Engine::camCtrlGUI(
struct v4l2_queryctrl & qc, std::set<int> & doneids)
2563 itsCamera->queryControl(qc);
2564 qc.id &= ~V4L2_CTRL_FLAG_NEXT_CTRL;
2567 if (doneids.find(qc.id) != doneids.end())
return;
else doneids.insert(qc.id);
2570 struct v4l2_control ctrl = { }; ctrl.id = qc.id;
2571 itsCamera->getControl(ctrl);
2574 ImGui::AlignTextToFramePadding();
2575 ImGui::TextUnformatted(
reinterpret_cast<char const *
>(qc.name));
2576 ImGui::NextColumn();
2579 if (qc.flags & V4L2_CTRL_FLAG_DISABLED)
2581 ImGui::PushItemFlag(ImGuiItemFlags_Disabled,
true);
2582 ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.5f);
2586 static char wname[16]; snprintf(wname, 16,
"##c%d", ctrl.id);
2591 case V4L2_CTRL_TYPE_INTEGER:
2592 case V4L2_CTRL_TYPE_INTEGER_MENU:
2595 long range = long(qc.maximum) - long(qc.minimum);
2596 if (range > 1 && range < 5000)
2598 if (ImGui::SliderInt(wname, &ctrl.value, qc.minimum, qc.maximum)) itsCamera->setControl(ctrl);
2603 if (ImGui::InputInt(wname, &ctrl.value, qc.step, qc.step * 2)) itsCamera->setControl(ctrl);
2620 case V4L2_CTRL_TYPE_BOOLEAN:
2622 bool checked = (ctrl.value != 0);
2623 if (ImGui::Checkbox(wname, &checked)) { ctrl.value = checked ? 1 : 0; itsCamera->setControl(ctrl); }
2628 case V4L2_CTRL_TYPE_BUTTON:
2629 static char bname[16]; snprintf(bname, 16,
"Go##%d", ctrl.id);
2630 if (ImGui::Button(bname)) { ctrl.value = 1; itsCamera->setControl(ctrl); }
2633 case V4L2_CTRL_TYPE_BITMASK:
2637 case V4L2_CTRL_TYPE_MENU:
2639 struct v4l2_querymenu querymenu = { };
2640 querymenu.id = qc.id;
2641 char * items[qc.maximum - qc.minimum + 1];
2643 for (querymenu.index = qc.minimum; querymenu.index <= (
unsigned int)qc.maximum; ++querymenu.index)
2645 try { itsCamera->queryMenu(querymenu); }
catch (...) { strncpy((
char *)querymenu.name,
"fixme", 32); }
2646 items[querymenu.index] =
new char[32];
2647 strncpy(items[querymenu.index], (
char const *)querymenu.name, 32);
2650 int idx = ctrl.value - qc.minimum;
2651 if (ImGui::Combo(wname, &idx, items, qc.maximum - qc.minimum + 1))
2652 { ctrl.value = qc.minimum + idx; itsCamera->setControl(ctrl); }
2654 for (
int i = qc.minimum; i <= qc.maximum; ++i)
delete [] items[i];
2664 static char rname[16]; snprintf(rname, 16,
"Reset##%d", ctrl.id);
2666 if (ImGui::Button(rname)) { ctrl.value = qc.default_value; itsCamera->setControl(ctrl); }
2670 if (qc.flags & V4L2_CTRL_FLAG_DISABLED)
2672 ImGui::PopItemFlag();
2673 ImGui::PopStyleVar();
2677 ImGui::NextColumn();
2681 #endif // JEVOIS_PRO