1 /*--------------------------------------------------------------------------*/
4 // This file is part of ruwai.
6 // If you use ruwai_parser in any program or publication, please inform and
7 // acknowledge its author Stefan Mertl (stefan@mertl-research.at).
9 // ruwai is free software: you can redistribute it and/or modify
10 // it under the terms of the GNU General Public License as published by
11 // the Free Software Foundation, either version 3 of the License, or
12 // (at your option) any later version.
14 // This program is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 // GNU General Public License for more details.
19 // You should have received a copy of the GNU General Public License
20 // along with this program. If not, see <http://www.gnu.org/licenses/>.
21 /*--------------------------------------------------------------------------*/
24 #include "log_temperature.h"
26 Root::Root(std::string config_file
)
28 boost::property_tree::ptree pt
;
29 double c1_gain
, c2_gain
, c3_gain
, c4_gain
;
32 display
= new LCDDisplay(66, 67, 45, 23, 47, 27);
36 display
->print("Hello, Ruwai", "is speaking.");
39 boost::property_tree::ini_parser::read_ini(config_file
, pt
);
41 // ---------------------------------------------------------
42 // Parse the arduino stack section.
43 dev_name
= pt
.get
<std::string
>("arduino_stack.serial_port");
44 n_channels
= pt
.get
<unsigned int>("arduino_stack.n_channels");
46 channel1_active
= pt
.get
<bool>("arduino_stack.channel1_active");
47 channel2_active
= pt
.get
<bool>("arduino_stack.channel2_active");
48 channel3_active
= pt
.get
<bool>("arduino_stack.channel3_active");
49 channel4_active
= pt
.get
<bool>("arduino_stack.channel4_active");
53 record_channels
.push_back(1);
58 record_channels
.push_back(2);
63 record_channels
.push_back(3);
68 record_channels
.push_back(4);
71 c1_gain
= pt
.get
<double>("arduino_stack.channel1_pga");
72 channel1_gain
= translate_pga_gain(c1_gain
);
73 if (channel1_gain
== PGA_GAIN_UNKNOWN
)
75 syslog(LOG_ERR
, "[ERROR][root] Unknown gain setting for channel 1: %f.", c1_gain
);
76 std::exit(EXIT_FAILURE
);
79 c2_gain
= pt
.get
<double>("arduino_stack.channel2_pga");
80 channel2_gain
= translate_pga_gain(c2_gain
);
81 if (channel2_gain
== PGA_GAIN_UNKNOWN
)
83 syslog(LOG_ERR
, "[ERROR][root] Unknown gain setting for channel 4: %f.", c2_gain
);
84 std::exit(EXIT_FAILURE
);
87 c3_gain
= pt
.get
<double>("arduino_stack.channel3_pga");
88 channel3_gain
= translate_pga_gain(c3_gain
);
89 if (channel3_gain
== PGA_GAIN_UNKNOWN
)
91 syslog(LOG_ERR
, "[ERROR][root] Unknown gain setting for channel 4: %f.", c3_gain
);
92 std::exit(EXIT_FAILURE
);
95 c4_gain
= pt
.get
<double>("arduino_stack.channel4_pga");
96 channel4_gain
= translate_pga_gain(c4_gain
);
97 if (channel4_gain
== PGA_GAIN_UNKNOWN
)
99 syslog(LOG_ERR
, "[ERROR][root] Unknown gain setting for channel 4: %f.", c4_gain
);
100 std::exit(EXIT_FAILURE
);
103 sps_raw
= pt
.get
<uint16_t>("arduino_stack.sps");
104 sps
= translate_adc_sps(sps_raw
);
105 if (sps
== ADC_SPS_UNKNOWN
)
107 syslog(LOG_ERR
, "[ERROR][root] Not supported sps setting: %d.", sps_raw
);
108 std::exit(EXIT_FAILURE
);
112 // ------------------------------------------------------------------------
113 // Parse the record section.
114 storage_mode
= pt
.get
<std::string
>("record.storage_mode");
115 tmp_dir
= pt
.get
<std::string
>("record.tmp_dir");
116 ruwai_serial_file
= pt
.get
<std::string
>("record.ruwai_serial_file");
117 file_length
= pt
.get
<unsigned int>("record.file_length");
118 //record_channels = to_array<unsigned int>(pt.get<std::string>("record.record_channels"));
120 // ------------------------------------------------------------------------
121 // Depending on the selected storage mode, parse the sd or hdd section.
122 if (storage_mode
== "sd")
124 sd_dev_label
= pt
.get
<std::string
>("sd.dev_label");
125 sd_dev_1
= pt
.get
<std::string
>("sd.dev_1");
126 sd_dev_2
= pt
.get
<std::string
>("sd.dev_2");
127 sd_mnt_point
= pt
.get
<std::string
>("sd.mnt_point");
128 } else if (storage_mode
== "hdd")
130 hdd_mseed_dir
= pt
.get
<std::string
>("hdd.mseed_dir");
133 // ------------------------------------------------------------------------
134 rts_start_server
= pt
.get
<bool>("rt_server.start_server");
135 rts_port
= pt
.get
<unsigned int>("rt_server.port");
136 rts_max_clients
= pt
.get
<unsigned int>("rt_server.max_clients");
138 catch (const boost::property_tree::ptree_bad_path
& e
) {
139 syslog(LOG_ERR
, "[ERROR][root] Couldn't read the config file %s. Error message: %s.", config_file
.c_str(), e
.what());
145 //const std::string serial_filename = "/etc/ruwai_serial";
147 std::ifstream
myfile(ruwai_serial_file
);
148 if (myfile
.is_open())
150 std::getline(myfile
, line
);
151 boost::trim_left(line
);
152 boost::trim_right(line
);
153 serial_number
= line
;
154 syslog(LOG_NOTICE
, "[root] Ruwai serial number: %s.", serial_number
.c_str());
159 syslog(LOG_ERR
, "[ERROR][root] Unable to open the file %s to read the serial number.", ruwai_serial_file
.c_str());
160 std::exit(EXIT_FAILURE
);
164 syslog(LOG_ERR
, "[ERROR][root] Couldn't read the serial number from %s. Unknown error.", ruwai_serial_file
.c_str());
169 std::string rec_channels_string
= "";
170 for (unsigned int k
= 0; k
< record_channels
.size(); k
++)
172 rec_channels_string
+= std::to_string(record_channels
[k
]);
174 if (k
< record_channels
.size() - 1)
176 rec_channels_string
+= ",";
180 syslog(LOG_NOTICE
, "------- read configuration --------");
181 syslog(LOG_NOTICE
, "arduino_stack");
182 syslog(LOG_NOTICE
, "serial_port: %s", dev_name
.c_str());
183 syslog(LOG_NOTICE
, "n_channels: %d", n_channels
);
184 syslog(LOG_NOTICE
, "channel1_active: %d", channel1_active
);
185 syslog(LOG_NOTICE
, "channel2_active: %d", channel2_active
);
186 syslog(LOG_NOTICE
, "channel3_active: %d", channel3_active
);
187 syslog(LOG_NOTICE
, "channel4_active: %d", channel4_active
);
188 syslog(LOG_NOTICE
, "channel1_gain: %.3f (%d)", c1_gain
, channel1_gain
);
189 syslog(LOG_NOTICE
, "channel2_gain: %.3f (%d)", c2_gain
, channel2_gain
);
190 syslog(LOG_NOTICE
, "channel3_gain: %.3f (%d)", c3_gain
, channel3_gain
);
191 syslog(LOG_NOTICE
, "channel4_gain: %.3f (%d)", c4_gain
, channel4_gain
);
192 syslog(LOG_NOTICE
, "sps: %d (%d)", sps_raw
, sps
);
193 syslog(LOG_NOTICE
, "record");
194 syslog(LOG_NOTICE
, "storage_mode: %s", storage_mode
.c_str());
195 syslog(LOG_NOTICE
, "tmp_dir: %s", tmp_dir
.c_str());
196 syslog(LOG_NOTICE
, "record_channels: %s", rec_channels_string
.c_str());
197 syslog(LOG_NOTICE
, "file_length: %d", file_length
);
198 if (storage_mode
== "sd")
200 syslog(LOG_NOTICE
, "sd");
201 syslog(LOG_NOTICE
, "dev_label: %s", sd_dev_label
.c_str());
202 syslog(LOG_NOTICE
, "dev_1: %s", sd_dev_1
.c_str());
203 syslog(LOG_NOTICE
, "dev_2: %s", sd_dev_2
.c_str());
204 syslog(LOG_NOTICE
, "mnt_point: %s", sd_mnt_point
.c_str());
205 } else if (storage_mode
== "hdd")
207 syslog(LOG_NOTICE
, "hdd");
208 syslog(LOG_NOTICE
, "mseed_dir: %s", hdd_mseed_dir
.c_str());
210 syslog(LOG_NOTICE
, "rt_server");
211 syslog(LOG_NOTICE
, "start_server: %d", rts_start_server
);
212 syslog(LOG_NOTICE
, "port: %d", rts_port
);
213 syslog(LOG_NOTICE
, "max_clients: %d", rts_max_clients
);
214 syslog(LOG_NOTICE
, "-----------------------------------");
216 // Create the temporary data directory.
217 if (!boost::filesystem::exists(tmp_dir
))
219 if (!boost::filesystem::create_directory(tmp_dir
))
221 syslog(LOG_ERR
, "[ERROR][root] Can't create the tmp_dir: %s. This is mandatory. Exiting.", tmp_dir
.c_str());
222 std::exit(EXIT_FAILURE
);
226 std::string mseed_dir
;
227 if (storage_mode
== "sd")
228 mseed_dir
= sd_mnt_point
;
229 else if (storage_mode
== "hdd")
230 mseed_dir
= hdd_mseed_dir
;
231 recorder
= new Recorder(serial_number
, n_channels
, record_channels
, sps
, mseed_dir
, tmp_dir
, file_length
);
232 rt_server
= new RealTimeServer(rts_port
, rts_max_clients
);
239 bool is_ready
= true;
241 // Check the output directory structure. If it doesn't exist, it's created.
242 if(!recorder
->check_output_dir_structure())
244 syslog(LOG_ERR
, "[ERROR][root] The output directory structure couldn't be created. Can't start the recorder.");
248 if (storage_mode
== "sd" && !is_sd_mounted())
257 Root::is_sd_dev_available(void)
259 bool dev_available
= false;
262 if (stat(sd_dev_label
.c_str(), &sb
) != -1)
264 switch (sb
.st_mode
& S_IFMT
) {
266 syslog(LOG_NOTICE
, "[root] SD card block device found at %s.", sd_dev_label
.c_str());
267 dev_available
= true;
270 syslog(LOG_ERR
, "[ERROR][root] SD card device file %s is not a block device.", sd_dev_label
.c_str());
276 syslog(LOG_WARNING
, "[WARNING][root] SD card block device file %s not found.", sd_dev_label
.c_str());
279 return dev_available
;
283 Root::is_sd_mounted(void)
286 struct mntent
*part
= NULL
;
287 bool is_mounted
= false;
289 if ((mtab
= setmntent("/etc/mtab", "r")) != NULL
)
291 while ((part
= getmntent(mtab
)) != NULL
)
293 if((part
->mnt_fsname
!= NULL
) && ((strcmp(part
->mnt_fsname
, sd_dev_1
.c_str())) == 0 || (strcmp(part
->mnt_fsname
, sd_dev_2
.c_str())) == 0) && (strcmp(part
->mnt_dir
, sd_mnt_point
.c_str()) == 0) )
302 syslog(LOG_NOTICE
, "[root] The SD card is correctly mounted at %s.", sd_mnt_point
.c_str());
306 syslog(LOG_WARNING
, "[WARNING][root] The SD card is NOT mounted. Couldn't find an entry for %s or %s mounted at %s in /etc/mtab.", sd_dev_1
.c_str(), sd_dev_2
.c_str(), sd_mnt_point
.c_str());
315 bool mount_success
= false;
318 // TODO: Use the mount function instead of calling mount using the system
319 // command. Using the mount function didn't work because of missing
320 // permissions when running as a normal user. Also the mtab entry is not
321 // written automatically. I think I would have to add an entry to mtab.
322 //ret_val = mount(sd_dev_label.c_str(), sd_mnt_point.c_str(), "ext4", MS_NOSUID | MS_NOEXEC | MS_NODEV, NULL);
324 std::string cmd
= "mount " + sd_mnt_point
;
325 ret_val
= system(cmd
.c_str());
329 syslog(LOG_NOTICE
, "[root] Successfully mounted the sd card on %s.", sd_mnt_point
.c_str());
330 mount_success
= true;
334 syslog(LOG_ERR
, "[ERROR][root] Troubles when mounting the SD card: %s.", strerror(errno
));
336 return mount_success
;
343 bool port_open
= false;
344 bool config_confirmed
= false;
347 display
->print("Starting...", "");
349 // Start the temperature logging thread.
350 syslog(LOG_NOTICE
, "[root] Starting the temperature logging thread.");
351 std::thread
t_temp_log(log_temperature
);
354 // Check the output directory structure. If it doesn't exist, it's created.
355 if(!recorder
->check_output_dir_structure())
357 syslog(LOG_ERR
, "[ERROR][root] The output directory structure couldn't be created. Can't start the recorder.");
361 port_open
= open_port();
366 // Test the chrono measurement.
368 syslog(LOG_DEBUG, "Testing the chrono measurement with usleep(1000).");
369 auto start = std::chrono::high_resolution_clock::now();
371 auto end = std::chrono::high_resolution_clock::now();
372 auto diff = end - start;
373 syslog(LOG_DEBUG, "Measured time: %d nanoseconds", (int)std::chrono::duration_cast<std::chrono::nanoseconds>(diff).count());
376 // Start the real time server if activated.
377 if (rts_start_server
)
379 syslog(LOG_NOTICE
, "[root] Starting the realtime server thread.");
380 std::thread
t_rts([&] (RealTimeServer
* rt_server
) {rt_server
->start_listen();}, rt_server
);
385 parser
= new SerialParser(serial_port
, recorder
);
386 std::thread
t_read_and_parse([&] (SerialParser
* parser
) {parser
->read_and_parse();}, parser
);
388 // Wait for handshaking.
389 display
->print("Handshaking...", "");
390 syslog(LOG_NOTICE
, "[root] Handshaking with Arduino stack....");
392 for (int k
= 0; k
< max_try
; k
++)
394 syslog(LOG_NOTICE
, "[root] Waiting for handshake with Arduino stack...");
395 parser
->start_handshake();
397 if (parser
->is_synced())
402 if (!parser
->is_synced())
404 syslog(LOG_ERR
, "[ERROR][root] ...tried handshake for %d times. Got no answer. Giving up.", max_try
);
405 std::exit(EXIT_FAILURE
);
409 syslog(LOG_NOTICE
, "[root] ...handshake was successful.");
413 display
->print("Configuring...", "");
414 syslog(LOG_NOTICE
, "[root] Setting the Arduino stack to control mode.");
415 success
= parser
->set_control_mode();
418 syslog(LOG_NOTICE
, "[root] Confirmed control mode configuration by the Arduino stack.");
422 syslog(LOG_ERR
, "[ERROR][root] No confirmation of the control mode configuration.");
425 // Configure the Arduino stack.
426 // TODO: Restart the configuration if no confirmation was received.
427 syslog(LOG_NOTICE
, "[root] Configuring the Arduino stack....");
429 for (int k
= 0; k
< max_try
; k
++)
431 config_confirmed
= true;
432 syslog(LOG_NOTICE
, "[root] Setting the sps to %d.", sps
);
433 success
= parser
->set_sps((uint16_t)sps
);
436 syslog(LOG_NOTICE
, "[root] Confirmed sps configuration by the Arduino stack.");
440 syslog(LOG_ERR
, "[ERROR][root] No confirmation of the sps configuration. Start again.");
441 config_confirmed
= false;
445 success
= parser
->set_channels(channel1_active
, channel2_active
, channel3_active
, channel4_active
, channel1_gain
, channel2_gain
, channel3_gain
, channel4_gain
);
448 syslog(LOG_NOTICE
, "[root] Confirmed channel configuration by the Arduino stack.");
452 syslog(LOG_ERR
, "[ERROR][root] No confirmation of the channel configuration. Start again.");
453 config_confirmed
= false;
457 if (config_confirmed
)
463 if (!config_confirmed
)
465 syslog(LOG_ERR
, "[ERROR][root] Couldn't configure the Arduino Stack. Tried it %d times.", max_try
);
466 std::exit(EXIT_FAILURE
);
469 syslog(LOG_NOTICE
, "[root] Stack configured successfully.");
471 syslog(LOG_NOTICE
, "[root] Set to record mode.");
472 success
= parser
->set_record_mode();
475 syslog(LOG_NOTICE
, "[root] Confirmed record mode configuration by the Arduino stack.");
476 display
->print("Recording...", "");
480 syslog(LOG_ERR
, "[ERROR][root] No confirmation of the record mode configuration.");
483 //std::thread t_lcd_status([&] (Root* this) {this->lcd_status();}, this);
484 std::thread
t_lcd_status(&Root::lcd_status
, this);
486 t_read_and_parse
.join();
488 // Close the serial port.
496 Root::open_port(void)
498 serial_port
= open(dev_name
.c_str(), O_RDWR
| O_NOCTTY
);
499 if(serial_port
== -1)
501 // Couldn't open the serial port.
502 syslog(LOG_ERR
, "[ERROR][root] Unable to open the Arduino stack serial port %s", dev_name
.c_str());
507 //fcntl(serial_port, F_SETFL, 0);
508 syslog(LOG_NOTICE
, "[root] Serial port %s to Arduino stack opened.", dev_name
.c_str());
514 Root::close_port(void)
521 Root::configure_port(void)
523 struct termios port_options
; // struct to hold the port settings
525 // Fetch the current port settings
526 tcgetattr(serial_port
, &port_options
);
528 // Flush the port's buffers (in and out) before we start using it
529 tcflush(serial_port
, TCIOFLUSH
);
531 // Input flags - Turn off input processing
533 // convert break to null byte, no CR to NL translation,
534 // no NL to CR translation, don't mark parity errors or breaks
535 // no input parity check, don't strip high bit off,
536 // no XON/XOFF software flow control
538 // port_options.c_iflag &= ~(IGNBRK | BRKINT | ICRNL |
539 // INLCR | PARMRK | INPCK | ISTRIP | IXON);
540 port_options
.c_iflag
= 0;
542 // Output flags - Turn off output processing
544 // no CR to NL translation, no NL to CR-NL translation,
545 // no NL to CR translation, no column 0 CR suppression,
546 // no Ctrl-D suppression, no fill characters, no case mapping,
547 // no local output processing
549 // port_options.c_oflag &= ~(OCRNL | ONLCR | ONLRET |
550 // ONOCR | ONOEOT| OFILL | OLCUC | OPOST);
551 port_options
.c_oflag
= 0;
553 // Turn off line processing
555 // echo off, echo newline off, canonical mode on,
556 // extended input processing off, signal chars off
557 // port_options.c_lflag &= ~(ECHO | ECHONL | ICANON | IEXTEN | ISIG);
559 // In non-blocking mode, the infinite loop in the serial parser causes a
560 // large CPU load which significantly increases the power consumption of
562 port_options
.c_lflag
= 0;
563 port_options
.c_lflag
&= ~ICANON
; // Set to non-canonical (blocking) mode.
564 port_options
.c_cc
[VMIN
] = 0; // Minimum number of bytes read.
565 port_options
.c_cc
[VTIME
] = 10; // timeout in deci-seconds
567 // Set the input and output baud rates
568 cfsetispeed(&port_options
, B1000000
);
569 cfsetospeed(&port_options
, B1000000
);
570 //cfsetispeed(&port_options, B500000);
571 //cfsetospeed(&port_options, B500000);
572 //cfsetispeed(&port_options, B1152000);
573 //cfsetospeed(&port_options, B1152000);
575 // c_cflag contains a few important things- CLOCAL and CREAD, to prevent
576 // this program from "owning" the port and to enable receipt of data.
577 // Also, it holds the settings for number of data bits, parity, stop bits,
578 // and hardware flow control.
579 port_options
.c_cflag
|= CLOCAL
;
580 port_options
.c_cflag
|= CREAD
;
581 // Set up the frame information.
582 port_options
.c_cflag
&= ~CSIZE
; // clear frame size info
583 port_options
.c_cflag
|= CS8
; // 8 bit frames
584 port_options
.c_cflag
&= ~PARENB
;// no parity
585 port_options
.c_cflag
&= ~CSTOPB
;// one stop bit
587 // Now that we've populated our options structure, let's push it back to the
589 tcsetattr(serial_port
, TCSANOW
, &port_options
);
591 syslog(LOG_DEBUG
, "Configured the serial port:");
592 syslog(LOG_DEBUG
, "port_options.c_cflag: %d - %s", port_options
.c_cflag
, std::bitset
<16>(port_options
.c_cflag
).to_string().c_str());
593 syslog(LOG_DEBUG
, "port_options.c_iflag: %d - %s", port_options
.c_iflag
, std::bitset
<16>(port_options
.c_iflag
).to_string().c_str());
594 syslog(LOG_DEBUG
, "port_options.c_oflag: %d - %s", port_options
.c_oflag
, std::bitset
<16>(port_options
.c_oflag
).to_string().c_str());
595 syslog(LOG_DEBUG
, "port_options.c_lflag: %d - %s", port_options
.c_lflag
, std::bitset
<16>(port_options
.c_lflag
).to_string().c_str());
597 // Flush the buffer one more time.
598 tcflush(serial_port
, TCIOFLUSH
);
600 //fcntl(serial_port, F_SETFL, 0);
605 Root::clear_tmp_dir(void)
607 // Check for forgotten files in the tmp directory.
608 syslog(LOG_NOTICE
, "[root] Cleaning the tmp directory.");
610 std::vector
<std::string
> file_list
;
611 boost::filesystem::path
search_dir(tmp_dir
);
612 boost::filesystem::directory_iterator end_itr
;
614 if (boost::filesystem::exists(search_dir
) && boost::filesystem::is_directory(search_dir
))
616 for (boost::filesystem::directory_iterator
dir_itr(search_dir
); dir_itr
!= end_itr
; dir_itr
++)
618 //syslog(LOG_NOTICE, "Moving file %s from tmp directory to mseed_dir.", dir_itr->path().filename().string().c_str());
619 file_list
.push_back(dir_itr
->path().filename().string());
623 if (file_list
.size() == 0)
625 syslog(LOG_NOTICE
, "[root] No data files found in the tmp directory: %s.", search_dir
.c_str());
629 recorder
->copy_files(file_list
);
636 Root::translate_pga_gain(double gain)
638 pga_gain_t ret = PGA_GAIN_UNKNOWN;
639 if (gain == 0.125 || gain == 0.172 || gain == 0.25 || gain == 0.344 || \
640 gain == 0.5 || gain == 0.688 || gain == 1 || gain == 1.375 || \
641 gain == 2 || gain == 2.75 || gain == 4 || gain == 5.5 || gain == 8 || \
642 gain == 11 || gain == 16 || gain == 22 || gain == 32 || gain == 44 || \
643 gain == 64 || gain == 88 || gain == 128 || gain == 176)
645 ret = (pga_gain_t) gain;
653 Root::translate_pga_gain(double gain
)
655 pga_gain_t ret
= PGA_GAIN_UNKNOWN
;
657 ret
= PGA_GAIN_0_125
;
658 else if (gain
== 0.172)
659 ret
= PGA_GAIN_0_172
;
660 else if (gain
== 0.25)
662 else if (gain
== 0.344)
663 ret
= PGA_GAIN_0_344
;
664 else if (gain
== 0.5)
666 else if (gain
== 0.688)
667 ret
= PGA_GAIN_0_688
;
670 else if (gain
== 1.375)
671 ret
= PGA_GAIN_1_375
;
674 else if (gain
== 2.75)
678 else if (gain
== 5.5)
696 else if (gain
== 128)
698 else if (gain
== 176)
707 Root::translate_adc_sps(uint16_t sps
)
709 adc_sps_t ret
= ADC_SPS_UNKNOWN
;
710 if (sps
== 100 || sps
== 200 || sps
== 400 || sps
== 500 || \
713 ret
= (adc_sps_t
) sps
;
720 Root::lcd_status(void)
722 char c_time_string
[27];
723 std::string time_string
;
724 timestamp_t last_timestamp
;
728 std::stringstream stream
;
732 last_timestamp
= recorder
->get_last_timestamp();
733 ms_hptime2isotimestr(last_timestamp
.time
, c_time_string
, true);
734 time_string
= std::string(c_time_string
);
735 display
->print(time_string
.substr(0, 10), time_string
.substr(11));
736 std::this_thread::sleep_for(std::chrono::seconds(3));
739 stream
<< "GPS F:" << last_timestamp
.gps_fix
<< " OK:" << last_timestamp
.gps_fix_ok
;
742 stream
<< "SLTS:" << last_timestamp
.sec_slts
;
744 display
->print(msg1
, msg2
);
745 std::this_thread::sleep_for(std::chrono::seconds(3));
748 std::string tmp_dir
= recorder
->get_tmp_dir();
749 std::vector
<std::string
> rec_files
= get_file_list(tmp_dir
);
750 std::sort(rec_files
.begin(), rec_files
.end());
752 stream
<< rec_files
.size() << " files";
756 for (std::vector
<std::string
>::iterator it
= rec_files
.begin(); it
!= rec_files
.end(); it
++)
758 std::string file_path
= tmp_dir
+ "/" + *it
;
759 stream
<< boost::filesystem::file_size(file_path
) / 1024 << "; ";
764 std::this_thread::sleep_for(std::chrono::seconds(10));
768 std::vector
<std::string
>
769 Root::get_file_list(const std::string path
)
771 std::vector
<std::string
> m_file_list
;
774 boost::filesystem::path
apk_path(path
);
776 for (auto& entry
: boost::make_iterator_range(boost::filesystem::directory_iterator(apk_path
), {}))
778 m_file_list
.push_back(entry
.path().string());