From fe4c2d918436fe5e4dcca19a495c716716293a69 Mon Sep 17 00:00:00 2001 From: waltjohnson Date: Fri, 24 Aug 2018 18:11:11 -0600 Subject: [PATCH] Update for release 1.6.4. See release notese for details. --- CLTool/README.md | 39 +- .../LOG_SN30235_20180801_225711_0001.dat | Bin 0 -> 114136 bytes .../20180801_225711/diagnostic_30235.txt | 19 + .../IS_logs/20180801_225711/errors.txt | 0 .../IS_logs/20180801_225711/stats.txt | 122 ++ .../IS_logs/20180801_225711/stats_SN30235.txt | 122 ++ .../LOG_SN30235_20180801_225926_0001.dat | Bin 0 -> 287040 bytes .../20180801_225926/diagnostic_30235.txt | 42 + .../IS_logs/20180801_225926/errors.txt | 0 .../IS_logs/20180801_225926/stats.txt | 143 ++ .../IS_logs/20180801_225926/stats_SN30235.txt | 143 ++ CMakeLists.txt | 2 + .../Communications/ISCommunicationsExample.c | 8 +- ExampleProjects/LogReader/CMakeLists.txt | 42 + .../LogReader/ISLogReaderExample.cpp | 61 + ExampleProjects/LogReader/README.md | 97 + .../VS_Project/ISLogReader.vcxproj.filters | 205 ++ .../VS_Project/ISLogReaderExample.sln | 31 + .../VS_Project/ISLogReaderExample.vcxproj | 218 +++ .../Logger/VS_Project/ISLoggerExample.vcxproj | 4 + .../ISLoggerExample.vcxproj.filters | 12 + README.md | 3 +- VS_project/InertialSenseLib.vcxproj | 4 + VS_project/InertialSenseLib.vcxproj.filters | 12 + docs/html/_data_c_s_v_8cpp.html | 2 +- docs/html/_data_c_s_v_8cpp_source.html | 14 +- docs/html/_data_c_s_v_8h.html | 2 +- docs/html/_data_c_s_v_8h_source.html | 2 +- docs/html/_data_chunk_8cpp.html | 2 +- docs/html/_data_chunk_8cpp_source.html | 2 +- docs/html/_data_chunk_8h.html | 2 +- docs/html/_data_chunk_8h_source.html | 6 +- docs/html/_data_chunk_sorted_8cpp.html | 2 +- docs/html/_data_chunk_sorted_8cpp_source.html | 2 +- docs/html/_data_chunk_sorted_8h.html | 2 +- docs/html/_data_chunk_sorted_8h_source.html | 8 +- docs/html/_data_j_s_o_n_8cpp.html | 105 + docs/html/_data_j_s_o_n_8cpp_source.html | 104 + docs/html/_data_j_s_o_n_8h.html | 97 + docs/html/_data_j_s_o_n_8h_source.html | 87 + docs/html/_data_k_m_l_8cpp.html | 2 +- docs/html/_data_k_m_l_8cpp_source.html | 35 +- docs/html/_data_k_m_l_8h.html | 2 +- docs/html/_data_k_m_l_8h_source.html | 12 +- docs/html/_device_log_8cpp.html | 2 +- docs/html/_device_log_8cpp_source.html | 10 +- docs/html/_device_log_8h.html | 2 +- docs/html/_device_log_8h_source.html | 4 +- docs/html/_device_log_c_s_v_8cpp.html | 2 +- docs/html/_device_log_c_s_v_8cpp_source.html | 12 +- docs/html/_device_log_c_s_v_8h.html | 2 +- docs/html/_device_log_c_s_v_8h_source.html | 4 +- docs/html/_device_log_j_s_o_n_8cpp.html | 101 + .../html/_device_log_j_s_o_n_8cpp_source.html | 102 + docs/html/_device_log_j_s_o_n_8h.html | 100 + docs/html/_device_log_j_s_o_n_8h_source.html | 97 + docs/html/_device_log_k_m_l_8cpp.html | 2 +- docs/html/_device_log_k_m_l_8cpp_source.html | 38 +- docs/html/_device_log_k_m_l_8h.html | 2 +- docs/html/_device_log_k_m_l_8h_source.html | 4 +- docs/html/_device_log_serial_8cpp.html | 2 +- docs/html/_device_log_serial_8cpp_source.html | 2 +- docs/html/_device_log_serial_8h.html | 2 +- docs/html/_device_log_serial_8h_source.html | 4 +- docs/html/_device_log_sorted_8cpp.html | 2 +- docs/html/_device_log_sorted_8cpp_source.html | 4 +- docs/html/_device_log_sorted_8h.html | 2 +- docs/html/_device_log_sorted_8h_source.html | 4 +- docs/html/_gps_parser_8cpp.html | 2 +- docs/html/_gps_parser_8cpp_source.html | 20 +- docs/html/_gps_parser_8h.html | 2 +- docs/html/_gps_parser_8h_source.html | 16 +- docs/html/_i_s_comm_8c.html | 2 +- docs/html/_i_s_comm_8c_source.html | 12 +- docs/html/_i_s_comm_8h.html | 12 +- docs/html/_i_s_comm_8h_source.html | 8 +- docs/html/_i_s_comm_data_buffer_8cpp.html | 2 +- .../_i_s_comm_data_buffer_8cpp_source.html | 10 +- docs/html/_i_s_comm_data_buffer_8h.html | 2 +- .../html/_i_s_comm_data_buffer_8h_source.html | 2 +- docs/html/_i_s_constants_8h.html | 669 +++---- docs/html/_i_s_constants_8h_source.html | 34 +- docs/html/_i_s_data_mappings_8cpp.html | 13 +- docs/html/_i_s_data_mappings_8cpp_source.html | 63 +- docs/html/_i_s_data_mappings_8h.html | 4 +- docs/html/_i_s_data_mappings_8h_source.html | 8 +- docs/html/_i_s_display_8cpp.html | 10 +- docs/html/_i_s_display_8cpp_source.html | 318 +-- docs/html/_i_s_display_8h.html | 10 +- docs/html/_i_s_display_8h_source.html | 28 +- docs/html/_i_s_earth_8c.html | 2 +- docs/html/_i_s_earth_8c_source.html | 28 +- docs/html/_i_s_earth_8h.html | 2 +- docs/html/_i_s_earth_8h_source.html | 16 +- docs/html/_i_s_logger_8cpp.html | 2 +- docs/html/_i_s_logger_8cpp_source.html | 151 +- docs/html/_i_s_logger_8h.html | 5 +- docs/html/_i_s_logger_8h_source.html | 74 +- docs/html/_i_s_matrix_8c.html | 2 +- docs/html/_i_s_matrix_8c_source.html | 32 +- docs/html/_i_s_matrix_8h.html | 2 +- docs/html/_i_s_matrix_8h_source.html | 32 +- docs/html/_i_s_pose_8c.html | 2 +- docs/html/_i_s_pose_8c_source.html | 28 +- docs/html/_i_s_pose_8h.html | 2 +- docs/html/_i_s_pose_8h_source.html | 20 +- docs/html/_i_s_serial_port_8cpp.html | 2 +- docs/html/_i_s_serial_port_8cpp_source.html | 8 +- docs/html/_i_s_serial_port_8h.html | 2 +- docs/html/_i_s_serial_port_8h_source.html | 4 +- docs/html/_i_s_stream_8cpp.html | 2 +- docs/html/_i_s_stream_8cpp_source.html | 4 +- docs/html/_i_s_stream_8h.html | 2 +- docs/html/_i_s_stream_8h_source.html | 4 +- docs/html/_i_s_tcp_client_8cpp.html | 52 +- docs/html/_i_s_tcp_client_8cpp_source.html | 31 +- docs/html/_i_s_tcp_client_8h.html | 52 +- docs/html/_i_s_tcp_client_8h_source.html | 15 +- docs/html/_i_s_tcp_server_8cpp.html | 2 +- docs/html/_i_s_tcp_server_8cpp_source.html | 33 +- docs/html/_i_s_tcp_server_8h.html | 2 +- docs/html/_i_s_tcp_server_8h_source.html | 15 +- docs/html/_i_s_utilities_8cpp.html | 2 +- docs/html/_i_s_utilities_8cpp_source.html | 52 +- docs/html/_i_s_utilities_8h.html | 8 +- docs/html/_i_s_utilities_8h_source.html | 6 +- docs/html/_inertial_sense_8cpp.html | 2 +- docs/html/_inertial_sense_8cpp_source.html | 187 +- docs/html/_inertial_sense_8h.html | 6 +- docs/html/_inertial_sense_8h_source.html | 68 +- docs/html/_inertial_sense_s_d_k_8h.html | 2 +- .../html/_inertial_sense_s_d_k_8h_source.html | 2 +- docs/html/_r_e_a_d_m_e_8md.html | 2 +- docs/html/_r_e_a_d_m_e_8md_source.html | 4 +- docs/html/annotated.html | 184 +- docs/html/class_inertial_sense-members.html | 47 +- docs/html/class_inertial_sense.html | 271 ++- docs/html/class_inertial_sense.png | Bin 561 -> 905 bytes docs/html/class_ti_xml_attribute-members.html | 2 +- docs/html/class_ti_xml_attribute.html | 2 +- .../class_ti_xml_attribute_set-members.html | 2 +- docs/html/class_ti_xml_attribute_set.html | 2 +- docs/html/class_ti_xml_base-members.html | 2 +- docs/html/class_ti_xml_base.html | 2 +- docs/html/class_ti_xml_comment-members.html | 2 +- docs/html/class_ti_xml_comment.html | 2 +- .../class_ti_xml_declaration-members.html | 2 +- docs/html/class_ti_xml_declaration.html | 2 +- docs/html/class_ti_xml_document-members.html | 2 +- docs/html/class_ti_xml_document.html | 2 +- docs/html/class_ti_xml_element-members.html | 2 +- docs/html/class_ti_xml_element.html | 2 +- docs/html/class_ti_xml_handle-members.html | 2 +- docs/html/class_ti_xml_handle.html | 2 +- docs/html/class_ti_xml_node-members.html | 2 +- docs/html/class_ti_xml_node.html | 2 +- .../html/class_ti_xml_out_stream-members.html | 2 +- docs/html/class_ti_xml_out_stream.html | 2 +- .../class_ti_xml_parsing_data-members.html | 2 +- docs/html/class_ti_xml_parsing_data.html | 2 +- docs/html/class_ti_xml_printer-members.html | 2 +- docs/html/class_ti_xml_printer.html | 2 +- docs/html/class_ti_xml_string-members.html | 2 +- docs/html/class_ti_xml_string.html | 2 +- docs/html/class_ti_xml_text-members.html | 2 +- docs/html/class_ti_xml_text.html | 2 +- docs/html/class_ti_xml_unknown-members.html | 2 +- docs/html/class_ti_xml_unknown.html | 2 +- docs/html/class_ti_xml_visitor-members.html | 2 +- docs/html/class_ti_xml_visitor.html | 2 +- docs/html/classc_com_data_buffer-members.html | 2 +- docs/html/classc_com_data_buffer.html | 2 +- docs/html/classc_csv_log-members.html | 2 +- docs/html/classc_csv_log.html | 2 +- docs/html/classc_data_c_s_v-members.html | 2 +- docs/html/classc_data_c_s_v.html | 2 +- docs/html/classc_data_chunk-members.html | 2 +- docs/html/classc_data_chunk.html | 2 +- docs/html/classc_data_j_s_o_n-members.html | 85 + docs/html/classc_data_j_s_o_n.html | 224 +++ docs/html/classc_data_k_m_l-members.html | 2 +- docs/html/classc_data_k_m_l.html | 2 +- docs/html/classc_device_log-members.html | 2 +- docs/html/classc_device_log.html | 19 +- docs/html/classc_device_log.png | Bin 1061 -> 1267 bytes .../html/classc_device_log_c_s_v-members.html | 2 +- docs/html/classc_device_log_c_s_v.html | 2 +- .../classc_device_log_j_s_o_n-members.html | 122 ++ docs/html/classc_device_log_j_s_o_n.html | 348 ++++ docs/html/classc_device_log_j_s_o_n.png | Bin 0 -> 520 bytes .../html/classc_device_log_k_m_l-members.html | 2 +- docs/html/classc_device_log_k_m_l.html | 2 +- .../classc_device_log_serial-members.html | 2 +- docs/html/classc_device_log_serial.html | 2 +- .../classc_device_log_sorted-members.html | 2 +- docs/html/classc_device_log_sorted.html | 2 +- docs/html/classc_gps_parser-members.html | 2 +- docs/html/classc_gps_parser.html | 2 +- .../classc_i_s_data_mappings-members.html | 6 +- docs/html/classc_i_s_data_mappings.html | 50 +- docs/html/classc_i_s_file_stream-members.html | 2 +- docs/html/classc_i_s_file_stream.html | 2 +- docs/html/classc_i_s_logger-members.html | 29 +- docs/html/classc_i_s_logger.html | 87 +- docs/html/classc_i_s_serial_port-members.html | 2 +- docs/html/classc_i_s_serial_port.html | 2 +- docs/html/classc_i_s_stream-members.html | 2 +- docs/html/classc_i_s_stream.html | 2 +- docs/html/classc_i_s_tcp_client-members.html | 2 +- docs/html/classc_i_s_tcp_client.html | 18 +- docs/html/classc_i_s_tcp_server-members.html | 2 +- docs/html/classc_i_s_tcp_server.html | 16 +- ...classc_inertial_sense_display-members.html | 51 +- docs/html/classc_inertial_sense_display.html | 116 +- .../classc_inertial_sense_parser-members.html | 2 +- docs/html/classc_inertial_sense_parser.html | 2 +- .../html/classc_log_stat_data_id-members.html | 2 +- docs/html/classc_log_stat_data_id.html | 28 +- docs/html/classc_log_stats-members.html | 2 +- docs/html/classc_log_stats.html | 24 +- docs/html/classc_rtcm_parser-members.html | 2 +- docs/html/classc_rtcm_parser.html | 2 +- .../classc_sorted_data_chunk-members.html | 2 +- docs/html/classc_sorted_data_chunk.html | 2 +- docs/html/classc_ublox_parser-members.html | 2 +- docs/html/classc_ublox_parser.html | 2 +- docs/html/classes.html | 77 +- .../classi_gps_parser_delegate-members.html | 2 +- docs/html/classi_gps_parser_delegate.html | 2 +- ...lassi_i_s_tcp_server_delegate-members.html | 9 +- docs/html/classi_i_s_tcp_server_delegate.html | 189 +- docs/html/classi_i_s_tcp_server_delegate.png | Bin 0 -> 606 bytes docs/html/cltool_8cpp.html | 10 +- docs/html/cltool_8cpp_source.html | 74 +- docs/html/cltool_8h.html | 12 +- docs/html/cltool_8h_source.html | 24 +- docs/html/cltool__main_8cpp.html | 4 +- docs/html/cltool__main_8cpp_source.html | 95 +- docs/html/com__manager_8c.html | 2 +- docs/html/com__manager_8c_source.html | 24 +- docs/html/com__manager_8h.html | 2 +- docs/html/com__manager_8h_source.html | 2 +- docs/html/data__sets_8c.html | 44 +- docs/html/data__sets_8c_source.html | 104 +- docs/html/data__sets_8h.html | 800 +++++--- docs/html/data__sets_8h_source.html | 1354 ++++++------- docs/html/deprecated.html | 2 +- .../dir_68267d1309a1af8e8297ef4c3efbcdba.html | 10 +- docs/html/files.html | 130 +- docs/html/functions.html | 2 +- docs/html/functions_0x7e.html | 2 +- docs/html/functions_b.html | 4 +- docs/html/functions_c.html | 15 +- docs/html/functions_d.html | 14 +- docs/html/functions_e.html | 2 +- docs/html/functions_enum.html | 2 +- docs/html/functions_eval.html | 5 +- docs/html/functions_f.html | 2 +- docs/html/functions_func.html | 2 +- docs/html/functions_func_0x7e.html | 2 +- docs/html/functions_func_b.html | 4 +- docs/html/functions_func_c.html | 3 +- docs/html/functions_func_d.html | 14 +- docs/html/functions_func_e.html | 2 +- docs/html/functions_func_f.html | 2 +- docs/html/functions_func_g.html | 2 +- docs/html/functions_func_h.html | 2 +- docs/html/functions_func_i.html | 2 +- docs/html/functions_func_l.html | 3 +- docs/html/functions_func_n.html | 2 +- docs/html/functions_func_o.html | 25 +- docs/html/functions_func_p.html | 2 +- docs/html/functions_func_q.html | 2 +- docs/html/functions_func_r.html | 5 +- docs/html/functions_func_s.html | 17 +- docs/html/functions_func_t.html | 2 +- docs/html/functions_func_u.html | 2 +- docs/html/functions_func_v.html | 2 +- docs/html/functions_func_w.html | 3 +- docs/html/functions_g.html | 13 +- docs/html/functions_h.html | 5 +- docs/html/functions_i.html | 8 +- docs/html/functions_k.html | 2 +- docs/html/functions_l.html | 6 +- docs/html/functions_m.html | 2 +- docs/html/functions_n.html | 2 +- docs/html/functions_o.html | 23 +- docs/html/functions_p.html | 8 +- docs/html/functions_q.html | 2 +- docs/html/functions_r.html | 12 +- docs/html/functions_rela.html | 2 +- docs/html/functions_s.html | 21 +- docs/html/functions_t.html | 8 +- docs/html/functions_type.html | 2 +- docs/html/functions_u.html | 2 +- docs/html/functions_v.html | 17 +- docs/html/functions_vars.html | 2 +- docs/html/functions_vars_b.html | 2 +- docs/html/functions_vars_c.html | 14 +- docs/html/functions_vars_d.html | 2 +- docs/html/functions_vars_e.html | 2 +- docs/html/functions_vars_f.html | 2 +- docs/html/functions_vars_g.html | 13 +- docs/html/functions_vars_h.html | 5 +- docs/html/functions_vars_i.html | 8 +- docs/html/functions_vars_k.html | 2 +- docs/html/functions_vars_l.html | 2 +- docs/html/functions_vars_m.html | 2 +- docs/html/functions_vars_n.html | 2 +- docs/html/functions_vars_o.html | 2 +- docs/html/functions_vars_p.html | 8 +- docs/html/functions_vars_q.html | 2 +- docs/html/functions_vars_r.html | 9 +- docs/html/functions_vars_s.html | 6 +- docs/html/functions_vars_t.html | 2 +- docs/html/functions_vars_u.html | 2 +- docs/html/functions_vars_v.html | 5 +- docs/html/functions_vars_w.html | 2 +- docs/html/functions_vars_z.html | 2 +- docs/html/functions_w.html | 3 +- docs/html/functions_z.html | 2 +- docs/html/globals.html | 6 +- docs/html/globals_a.html | 2 +- docs/html/globals_b.html | 2 +- docs/html/globals_c.html | 2 +- docs/html/globals_d.html | 46 +- docs/html/globals_defs.html | 6 +- docs/html/globals_defs_a.html | 2 +- docs/html/globals_defs_b.html | 2 +- docs/html/globals_defs_c.html | 2 +- docs/html/globals_defs_d.html | 46 +- docs/html/globals_defs_e.html | 2 +- docs/html/globals_defs_f.html | 2 +- docs/html/globals_defs_g.html | 2 +- docs/html/globals_defs_h.html | 2 +- docs/html/globals_defs_i.html | 2 +- docs/html/globals_defs_l.html | 2 +- docs/html/globals_defs_m.html | 2 +- docs/html/globals_defs_n.html | 2 +- docs/html/globals_defs_o.html | 2 +- docs/html/globals_defs_p.html | 2 +- docs/html/globals_defs_r.html | 56 +- docs/html/globals_defs_s.html | 2 +- docs/html/globals_defs_t.html | 2 +- docs/html/globals_defs_u.html | 2 +- docs/html/globals_defs_v.html | 2 +- docs/html/globals_defs_x.html | 2 +- docs/html/globals_e.html | 2 +- docs/html/globals_enum.html | 2 +- docs/html/globals_eval.html | 2 +- docs/html/globals_eval_b.html | 2 +- docs/html/globals_eval_c.html | 2 +- docs/html/globals_eval_d.html | 2 +- docs/html/globals_eval_g.html | 37 +- docs/html/globals_eval_h.html | 17 +- docs/html/globals_eval_i.html | 20 +- docs/html/globals_eval_m.html | 2 +- docs/html/globals_eval_n.html | 2 +- docs/html/globals_eval_p.html | 2 +- docs/html/globals_eval_r.html | 2 +- docs/html/globals_eval_s.html | 2 +- docs/html/globals_eval_t.html | 2 +- docs/html/globals_eval_u.html | 2 +- docs/html/globals_f.html | 2 +- docs/html/globals_func.html | 2 +- docs/html/globals_func_b.html | 2 +- docs/html/globals_func_c.html | 2 +- docs/html/globals_func_d.html | 2 +- docs/html/globals_func_e.html | 2 +- docs/html/globals_func_f.html | 2 +- docs/html/globals_func_g.html | 14 +- docs/html/globals_func_i.html | 22 +- docs/html/globals_func_j.html | 2 +- docs/html/globals_func_l.html | 2 +- docs/html/globals_func_m.html | 2 +- docs/html/globals_func_n.html | 2 +- docs/html/globals_func_o.html | 2 +- docs/html/globals_func_p.html | 2 +- docs/html/globals_func_q.html | 2 +- docs/html/globals_func_r.html | 2 +- docs/html/globals_func_s.html | 2 +- docs/html/globals_func_t.html | 2 +- docs/html/globals_func_u.html | 2 +- docs/html/globals_func_v.html | 2 +- docs/html/globals_g.html | 51 +- docs/html/globals_h.html | 17 +- docs/html/globals_i.html | 64 +- docs/html/globals_j.html | 2 +- docs/html/globals_l.html | 2 +- docs/html/globals_m.html | 2 +- docs/html/globals_n.html | 2 +- docs/html/globals_o.html | 2 +- docs/html/globals_p.html | 2 +- docs/html/globals_q.html | 2 +- docs/html/globals_r.html | 56 +- docs/html/globals_s.html | 2 +- docs/html/globals_t.html | 2 +- docs/html/globals_type.html | 12 +- docs/html/globals_u.html | 2 +- docs/html/globals_v.html | 2 +- docs/html/globals_vars.html | 2 +- docs/html/globals_x.html | 2 +- docs/html/hierarchy.html | 177 +- docs/html/index.html | 4 +- docs/html/inertial_sense_boot_loader_8c.html | 2 +- .../inertial_sense_boot_loader_8c_source.html | 16 +- docs/html/inertial_sense_boot_loader_8h.html | 2 +- .../inertial_sense_boot_loader_8h_source.html | 2 +- docs/html/linked__list_8c.html | 2 +- docs/html/linked__list_8c_source.html | 2 +- docs/html/linked__list_8h.html | 2 +- docs/html/linked__list_8h_source.html | 2 +- docs/html/pages.html | 2 +- docs/html/ring__buffer_8c.html | 2 +- docs/html/ring__buffer_8c_source.html | 8 +- docs/html/ring__buffer_8h.html | 2 +- docs/html/ring__buffer_8h_source.html | 2 +- docs/html/search/all_0.js | 2 +- docs/html/search/all_10.js | 2 +- docs/html/search/all_12.js | 25 +- docs/html/search/all_13.js | 11 +- docs/html/search/all_14.js | 2 +- docs/html/search/all_16.js | 5 +- docs/html/search/all_17.js | 2 +- docs/html/search/all_2.js | 2 +- docs/html/search/all_3.js | 8 +- docs/html/search/all_4.js | 26 +- docs/html/search/all_7.js | 23 +- docs/html/search/all_8.js | 6 + docs/html/search/all_9.js | 9 + docs/html/search/all_c.js | 3 +- docs/html/search/all_e.js | 2 +- docs/html/search/all_f.js | 7 +- docs/html/search/classes_2.js | 2 + docs/html/search/defines_0.js | 2 +- docs/html/search/defines_4.js | 16 +- docs/html/search/defines_f.js | 20 +- docs/html/search/enumvalues_4.js | 13 +- docs/html/search/enumvalues_5.js | 7 +- docs/html/search/enumvalues_6.js | 6 + docs/html/search/enumvalues_8.js | 1 + docs/html/search/files_1.js | 4 + docs/html/search/functions_1.js | 2 +- docs/html/search/functions_10.js | 2 +- docs/html/search/functions_11.js | 9 +- docs/html/search/functions_15.js | 2 +- docs/html/search/functions_2.js | 2 +- docs/html/search/functions_3.js | 6 +- docs/html/search/functions_6.js | 3 +- docs/html/search/functions_8.js | 1 + docs/html/search/functions_a.js | 2 +- docs/html/search/functions_d.js | 7 +- docs/html/search/typedefs_6.js | 4 +- docs/html/search/variables_10.js | 3 +- docs/html/search/variables_11.js | 2 +- docs/html/search/variables_14.js | 1 - docs/html/search/variables_2.js | 4 +- docs/html/search/variables_6.js | 5 +- docs/html/search/variables_7.js | 1 + docs/html/search/variables_8.js | 2 + docs/html/search/variables_e.js | 2 +- docs/html/serial_port_8c.html | 2 +- docs/html/serial_port_8c_source.html | 2 +- docs/html/serial_port_8h.html | 2 +- docs/html/serial_port_8h_source.html | 2 +- docs/html/serial_port_platform_8c.html | 2 +- docs/html/serial_port_platform_8c_source.html | 4 +- docs/html/serial_port_platform_8h.html | 2 +- docs/html/serial_port_platform_8h_source.html | 2 +- ...ense_1_1bootloader__result__t-members.html | 2 +- ...ertial_sense_1_1bootloader__result__t.html | 8 +- ..._1com__manager__cpp__state__t-members.html | 17 +- ..._sense_1_1com__manager__cpp__state__t.html | 72 +- docs/html/struct_p_a_c_k_e_d-members.html | 307 +-- docs/html/struct_p_a_c_k_e_d.html | 705 +++---- docs/html/struct_ti_xml_cursor-members.html | 2 +- docs/html/struct_ti_xml_cursor.html | 2 +- docs/html/structalm__t-members.html | 2 +- docs/html/structalm__t.html | 34 +- .../structascii_message_map__t-members.html | 2 +- docs/html/structascii_message_map__t.html | 2 +- .../structbootload__params__t-members.html | 2 +- docs/html/structbootload__params__t.html | 2 +- .../structbootloader__state__t-members.html | 2 +- docs/html/structbootloader__state__t.html | 2 +- .../html/structbroadcast__msg__t-members.html | 2 +- docs/html/structbroadcast__msg__t.html | 2 +- docs/html/structbuf_ptr__t-members.html | 2 +- docs/html/structbuf_ptr__t.html | 2 +- docs/html/structbuf_tx_rx_ptr__t-members.html | 2 +- docs/html/structbuf_tx_rx_ptr__t.html | 2 +- docs/html/structbuffer__t-members.html | 2 +- docs/html/structbuffer__t.html | 2 +- docs/html/structcmd__options__t-members.html | 6 +- docs/html/structcmd__options__t.html | 22 +- ...structcom__manager__status__t-members.html | 2 +- docs/html/structcom__manager__status__t.html | 2 +- docs/html/structcom__manager__t-members.html | 2 +- docs/html/structcom__manager__t.html | 2 +- docs/html/structcrash__info__t-members.html | 2 +- docs/html/structcrash__info__t.html | 20 +- docs/html/structdata__info__t-members.html | 2 +- docs/html/structdata__info__t.html | 2 +- docs/html/structdiag__msg__t-members.html | 2 +- docs/html/structdiag__msg__t.html | 10 +- docs/html/structensured__pkt__t-members.html | 2 +- docs/html/structensured__pkt__t.html | 2 +- docs/html/structeph__t-members.html | 2 +- docs/html/structeph__t.html | 72 +- docs/html/structfile__info__t-members.html | 2 +- docs/html/structfile__info__t.html | 10 +- docs/html/structgeph__t-members.html | 2 +- docs/html/structgeph__t.html | 32 +- docs/html/structgtime__t-members.html | 2 +- docs/html/structgtime__t.html | 8 +- ...structinternal__diagnostic__t-members.html | 2 +- docs/html/structinternal__diagnostic__t.html | 14 +- ...struction__model__utc__alm__t-members.html | 2 +- docs/html/struction__model__utc__alm__t.html | 32 +- .../structis__comm__instance__t-members.html | 2 +- docs/html/structis__comm__instance__t.html | 2 +- .../structlinked__list__node__t-members.html | 2 +- docs/html/structlinked__list__node__t.html | 2 +- docs/html/structlinked__list__t-members.html | 2 +- docs/html/structlinked__list__t.html | 2 +- docs/html/structobs__t-members.html | 2 +- docs/html/structobs__t.html | 10 +- docs/html/structp__ack__hdr__t-members.html | 2 +- docs/html/structp__ack__hdr__t.html | 2 +- docs/html/structp__ack__t-members.html | 2 +- docs/html/structp__ack__t.html | 2 +- docs/html/structp__cnk__data__t-members.html | 2 +- docs/html/structp__cnk__data__t.html | 2 +- .../structp__data__disable__t-members.html | 2 +- docs/html/structp__data__disable__t.html | 2 +- docs/html/structp__data__get__t-members.html | 2 +- docs/html/structp__data__get__t.html | 2 +- docs/html/structp__data__hdr__t-members.html | 2 +- docs/html/structp__data__hdr__t.html | 2 +- docs/html/structp__data__t-members.html | 2 +- docs/html/structp__data__t.html | 2 +- docs/html/structpacket__ftr__t-members.html | 2 +- docs/html/structpacket__ftr__t.html | 2 +- docs/html/structpacket__hdr__t-members.html | 2 +- docs/html/structpacket__hdr__t.html | 2 +- docs/html/structpacket__t-members.html | 2 +- docs/html/structpacket__t.html | 2 +- docs/html/structpkt__info__t-members.html | 2 +- docs/html/structpkt__info__t.html | 2 +- docs/html/structprcopt__t-members.html | 2 +- docs/html/structprcopt__t.html | 90 +- .../structregistered__data__t-members.html | 2 +- docs/html/structregistered__data__t.html | 2 +- docs/html/structring__buffer__t-members.html | 2 +- docs/html/structring__buffer__t.html | 2 +- docs/html/structringbuf__t-members.html | 2 +- docs/html/structringbuf__t.html | 2 +- ...ucts_case_insensitive_compare-members.html | 2 +- .../structs_case_insensitive_compare.html | 6 +- ...ve_compare_1_1nocase__compare-members.html | 2 +- ...nsensitive_compare_1_1nocase__compare.html | 6 +- docs/html/structs_chunk_header-members.html | 2 +- docs/html/structs_chunk_header.html | 2 +- .../structs_chunk_sub_header-members.html | 2 +- docs/html/structs_chunk_sub_header.html | 2 +- docs/html/structs_kml_log-members.html | 2 +- docs/html/structs_kml_log.html | 2 +- docs/html/structs_kml_log_data-members.html | 2 +- docs/html/structs_kml_log_data.html | 2 +- docs/html/structs_lpf_o0-members.html | 2 +- docs/html/structs_lpf_o0.html | 2 +- docs/html/structs_lpf_o1-members.html | 2 +- docs/html/structs_lpf_o1.html | 2 +- docs/html/structsbsmsg__t-members.html | 2 +- docs/html/structsbsmsg__t.html | 14 +- docs/html/structserial__port__t-members.html | 2 +- docs/html/structserial__port__t.html | 2 +- .../structserial_port_handle-members.html | 2 +- docs/html/structserial_port_handle.html | 2 +- docs/html/structsta__t-members.html | 2 +- docs/html/structsta__t.html | 14 +- docs/html/structsurvey__in__t-members.html | 2 +- docs/html/structsurvey__in__t.html | 20 +- docs/html/structxmodem__chunk__t-members.html | 2 +- docs/html/structxmodem__chunk__t.html | 2 +- docs/html/time__conversion_8c.html | 2 +- docs/html/time__conversion_8c_source.html | 2 +- docs/html/time__conversion_8h.html | 2 +- docs/html/time__conversion_8h_source.html | 2 +- docs/html/tinystr_8cpp.html | 2 +- docs/html/tinystr_8cpp_source.html | 2 +- docs/html/tinystr_8h.html | 2 +- docs/html/tinystr_8h_source.html | 2 +- docs/html/tinyxml_8cpp.html | 2 +- docs/html/tinyxml_8cpp_source.html | 2 +- docs/html/tinyxml_8h.html | 2 +- docs/html/tinyxml_8h_source.html | 2 +- docs/html/tinyxmlerror_8cpp.html | 2 +- docs/html/tinyxmlerror_8cpp_source.html | 2 +- docs/html/tinyxmlparser_8cpp.html | 2 +- docs/html/tinyxmlparser_8cpp_source.html | 2 +- pySDK/CMakeLists.txt | 126 -- pySDK/MANIFEST.in | 3 - pySDK/pySDK.cpp | 56 - pySDK/pySDK.h | 12 - pySDK/pybind11-2.1.1/.appveyor.yml | 40 - pySDK/pybind11-2.1.1/.gitignore | 37 - pySDK/pybind11-2.1.1/.gitmodules | 3 - pySDK/pybind11-2.1.1/.readthedocs.yml | 3 - pySDK/pybind11-2.1.1/.travis.yml | 194 -- pySDK/pybind11-2.1.1/CMakeLists.txt | 124 -- pySDK/pybind11-2.1.1/CONTRIBUTING.md | 37 - pySDK/pybind11-2.1.1/ISSUE_TEMPLATE.md | 17 - pySDK/pybind11-2.1.1/LICENSE | 36 - pySDK/pybind11-2.1.1/MANIFEST.in | 2 - pySDK/pybind11-2.1.1/README.md | 129 -- pySDK/pybind11-2.1.1/docs/Doxyfile | 19 - .../docs/_static/theme_overrides.css | 11 - .../docs/advanced/cast/chrono.rst | 81 - .../docs/advanced/cast/custom.rst | 85 - .../docs/advanced/cast/eigen.rst | 310 --- .../docs/advanced/cast/functional.rst | 113 -- .../docs/advanced/cast/index.rst | 42 - .../docs/advanced/cast/overview.rst | 158 -- .../pybind11-2.1.1/docs/advanced/cast/stl.rst | 156 -- .../docs/advanced/cast/strings.rst | 243 --- .../pybind11-2.1.1/docs/advanced/classes.rst | 657 ------- .../docs/advanced/exceptions.rst | 142 -- .../docs/advanced/functions.rst | 409 ---- pySDK/pybind11-2.1.1/docs/advanced/misc.rst | 244 --- .../docs/advanced/pycpp/index.rst | 13 - .../docs/advanced/pycpp/numpy.rst | 379 ---- .../docs/advanced/pycpp/object.rst | 98 - .../docs/advanced/pycpp/utilities.rst | 57 - .../docs/advanced/smart_ptrs.rst | 177 -- pySDK/pybind11-2.1.1/docs/basics.rst | 289 --- pySDK/pybind11-2.1.1/docs/benchmark.py | 90 - pySDK/pybind11-2.1.1/docs/benchmark.rst | 99 - pySDK/pybind11-2.1.1/docs/changelog.rst | 568 ------ pySDK/pybind11-2.1.1/docs/classes.rst | 445 ----- pySDK/pybind11-2.1.1/docs/compiling.rst | 185 -- pySDK/pybind11-2.1.1/docs/conf.py | 332 ---- pySDK/pybind11-2.1.1/docs/faq.rst | 253 --- pySDK/pybind11-2.1.1/docs/index.rst | 45 - pySDK/pybind11-2.1.1/docs/intro.rst | 95 - pySDK/pybind11-2.1.1/docs/limitations.rst | 20 - pySDK/pybind11-2.1.1/docs/pybind11-logo.png | Bin 58510 -> 0 bytes .../docs/pybind11_vs_boost_python1.png | Bin 44653 -> 0 bytes .../docs/pybind11_vs_boost_python1.svg | 427 ---- .../docs/pybind11_vs_boost_python2.png | Bin 41121 -> 0 bytes .../docs/pybind11_vs_boost_python2.svg | 427 ---- pySDK/pybind11-2.1.1/docs/reference.rst | 80 - pySDK/pybind11-2.1.1/docs/release.rst | 24 - pySDK/pybind11-2.1.1/docs/requirements.txt | 1 - pySDK/pybind11-2.1.1/include/pybind11/attr.h | 422 ---- pySDK/pybind11-2.1.1/include/pybind11/cast.h | 1604 --------------- .../pybind11-2.1.1/include/pybind11/chrono.h | 162 -- .../include/pybind11/class_support.h | 504 ----- .../pybind11-2.1.1/include/pybind11/common.h | 719 ------- .../pybind11-2.1.1/include/pybind11/complex.h | 52 - pySDK/pybind11-2.1.1/include/pybind11/descr.h | 183 -- pySDK/pybind11-2.1.1/include/pybind11/eigen.h | 589 ------ pySDK/pybind11-2.1.1/include/pybind11/eval.h | 112 -- .../include/pybind11/functional.h | 81 - pySDK/pybind11-2.1.1/include/pybind11/numpy.h | 1393 ------------- .../include/pybind11/operators.h | 154 -- .../pybind11-2.1.1/include/pybind11/options.h | 65 - .../include/pybind11/pybind11.h | 1741 ----------------- .../pybind11-2.1.1/include/pybind11/pytypes.h | 1244 ------------ pySDK/pybind11-2.1.1/include/pybind11/stl.h | 276 --- .../include/pybind11/stl_bind.h | 587 ------ .../pybind11-2.1.1/include/pybind11/typeid.h | 53 - pySDK/pybind11-2.1.1/pybind11/__init__.py | 11 - pySDK/pybind11-2.1.1/pybind11/_version.py | 2 - pySDK/pybind11-2.1.1/setup.cfg | 10 - pySDK/pybind11-2.1.1/setup.py | 84 - pySDK/pybind11-2.1.1/tests/CMakeLists.txt | 238 --- pySDK/pybind11-2.1.1/tests/conftest.py | 239 --- .../pybind11-2.1.1/tests/constructor_stats.h | 276 --- pySDK/pybind11-2.1.1/tests/object.h | 175 -- pySDK/pybind11-2.1.1/tests/pybind11_tests.cpp | 58 - pySDK/pybind11-2.1.1/tests/pybind11_tests.h | 12 - pySDK/pybind11-2.1.1/tests/pytest.ini | 7 - .../tests/test_alias_initialization.cpp | 62 - .../tests/test_alias_initialization.py | 80 - pySDK/pybind11-2.1.1/tests/test_buffers.cpp | 117 -- pySDK/pybind11-2.1.1/tests/test_buffers.py | 62 - pySDK/pybind11-2.1.1/tests/test_callbacks.cpp | 182 -- pySDK/pybind11-2.1.1/tests/test_callbacks.py | 104 - pySDK/pybind11-2.1.1/tests/test_chrono.cpp | 65 - pySDK/pybind11-2.1.1/tests/test_chrono.py | 120 -- .../pybind11-2.1.1/tests/test_class_args.cpp | 68 - pySDK/pybind11-2.1.1/tests/test_class_args.py | 8 - .../installed_function/CMakeLists.txt | 12 - .../installed_target/CMakeLists.txt | 22 - .../tests/test_cmake_build/main.cpp | 10 - .../subdirectory_function/CMakeLists.txt | 8 - .../subdirectory_target/CMakeLists.txt | 15 - .../tests/test_cmake_build/test.py | 5 - .../tests/test_constants_and_functions.cpp | 104 - .../tests/test_constants_and_functions.py | 43 - .../tests/test_copy_move_policies.cpp | 41 - .../tests/test_copy_move_policies.py | 15 - .../tests/test_docstring_options.cpp | 62 - .../tests/test_docstring_options.py | 42 - pySDK/pybind11-2.1.1/tests/test_eigen.cpp | 294 --- pySDK/pybind11-2.1.1/tests/test_eigen.py | 626 ------ pySDK/pybind11-2.1.1/tests/test_enum.cpp | 68 - pySDK/pybind11-2.1.1/tests/test_enum.py | 117 -- pySDK/pybind11-2.1.1/tests/test_eval.cpp | 79 - pySDK/pybind11-2.1.1/tests/test_eval.py | 19 - pySDK/pybind11-2.1.1/tests/test_eval_call.py | 4 - .../pybind11-2.1.1/tests/test_exceptions.cpp | 173 -- pySDK/pybind11-2.1.1/tests/test_exceptions.py | 74 - .../pybind11-2.1.1/tests/test_inheritance.cpp | 123 -- .../pybind11-2.1.1/tests/test_inheritance.py | 78 - pySDK/pybind11-2.1.1/tests/test_issues.cpp | 400 ---- pySDK/pybind11-2.1.1/tests/test_issues.py | 251 --- .../pybind11-2.1.1/tests/test_keep_alive.cpp | 40 - pySDK/pybind11-2.1.1/tests/test_keep_alive.py | 97 - .../tests/test_kwargs_and_defaults.cpp | 93 - .../tests/test_kwargs_and_defaults.py | 108 - .../tests/test_methods_and_attributes.cpp | 297 --- .../tests/test_methods_and_attributes.py | 325 --- pySDK/pybind11-2.1.1/tests/test_modules.cpp | 58 - pySDK/pybind11-2.1.1/tests/test_modules.py | 62 - .../tests/test_multiple_inheritance.cpp | 162 -- .../tests/test_multiple_inheritance.py | 111 -- .../pybind11-2.1.1/tests/test_numpy_array.cpp | 267 --- .../pybind11-2.1.1/tests/test_numpy_array.py | 379 ---- .../tests/test_numpy_dtypes.cpp | 395 ---- .../pybind11-2.1.1/tests/test_numpy_dtypes.py | 272 --- .../tests/test_numpy_vectorize.cpp | 58 - .../tests/test_numpy_vectorize.py | 161 -- .../tests/test_opaque_types.cpp | 62 - .../pybind11-2.1.1/tests/test_opaque_types.py | 50 - .../tests/test_operator_overloading.cpp | 76 - .../tests/test_operator_overloading.py | 40 - pySDK/pybind11-2.1.1/tests/test_pickling.cpp | 83 - pySDK/pybind11-2.1.1/tests/test_pickling.py | 35 - .../tests/test_python_types.cpp | 495 ----- .../pybind11-2.1.1/tests/test_python_types.py | 535 ----- .../tests/test_sequences_and_iterators.cpp | 354 ---- .../tests/test_sequences_and_iterators.py | 125 -- pySDK/pybind11-2.1.1/tests/test_smart_ptr.cpp | 274 --- pySDK/pybind11-2.1.1/tests/test_smart_ptr.py | 222 --- .../pybind11-2.1.1/tests/test_stl_binders.cpp | 128 -- .../pybind11-2.1.1/tests/test_stl_binders.py | 198 -- .../tests/test_virtual_functions.cpp | 347 ---- .../tests/test_virtual_functions.py | 259 --- pySDK/pybind11-2.1.1/tools/FindEigen3.cmake | 81 - .../tools/FindPythonLibsNew.cmake | 194 -- pySDK/pybind11-2.1.1/tools/check-style.sh | 83 - pySDK/pybind11-2.1.1/tools/libsize.py | 38 - pySDK/pybind11-2.1.1/tools/mkdoc.py | 309 --- .../tools/pybind11Config.cmake.in | 92 - .../pybind11-2.1.1/tools/pybind11Tools.cmake | 197 -- pySDK/setup.py | 69 - pySDK/src/cltool.py | 398 ---- resources/update_doxygen_docs.bat | 2 +- src/DataJSON.cpp | 180 ++ src/DataJSON.h | 72 + src/DataKML.cpp | 12 +- src/DataKML.h | 8 +- src/DeviceLogJSON.cpp | 167 ++ src/DeviceLogJSON.h | 43 + src/ISComm.h | 2 +- src/ISConstants.h | 13 +- src/ISDataMappings.cpp | 173 +- src/ISDataMappings.h | 6 +- src/ISDisplay.cpp | 303 +-- src/ISDisplay.h | 17 +- src/ISLogger.cpp | 58 +- src/ISLogger.h | 28 +- src/ISTcpClient.cpp | 12 +- src/ISTcpClient.h | 8 + src/ISTcpServer.cpp | 90 +- src/ISTcpServer.h | 56 +- src/ISUtilities.cpp | 12 - src/ISUtilities.h | 6 - src/InertialSense.cpp | 481 +---- src/InertialSense.h | 81 +- src/cltool.cpp | 53 +- src/cltool.h | 4 +- src/cltool_main.cpp | 93 +- src/com_manager.c | 2 +- src/data_sets.c | 197 +- src/data_sets.h | 217 +- 788 files changed, 9713 insertions(+), 35139 deletions(-) create mode 100644 CLTool/VS_project/IS_logs/20180801_225711/LOG_SN30235_20180801_225711_0001.dat create mode 100644 CLTool/VS_project/IS_logs/20180801_225711/diagnostic_30235.txt create mode 100644 CLTool/VS_project/IS_logs/20180801_225711/errors.txt create mode 100644 CLTool/VS_project/IS_logs/20180801_225711/stats.txt create mode 100644 CLTool/VS_project/IS_logs/20180801_225711/stats_SN30235.txt create mode 100644 CLTool/VS_project/IS_logs/20180801_225926/LOG_SN30235_20180801_225926_0001.dat create mode 100644 CLTool/VS_project/IS_logs/20180801_225926/diagnostic_30235.txt create mode 100644 CLTool/VS_project/IS_logs/20180801_225926/errors.txt create mode 100644 CLTool/VS_project/IS_logs/20180801_225926/stats.txt create mode 100644 CLTool/VS_project/IS_logs/20180801_225926/stats_SN30235.txt create mode 100644 ExampleProjects/LogReader/CMakeLists.txt create mode 100644 ExampleProjects/LogReader/ISLogReaderExample.cpp create mode 100644 ExampleProjects/LogReader/README.md create mode 100644 ExampleProjects/LogReader/VS_Project/ISLogReader.vcxproj.filters create mode 100644 ExampleProjects/LogReader/VS_Project/ISLogReaderExample.sln create mode 100644 ExampleProjects/LogReader/VS_Project/ISLogReaderExample.vcxproj create mode 100644 docs/html/_data_j_s_o_n_8cpp.html create mode 100644 docs/html/_data_j_s_o_n_8cpp_source.html create mode 100644 docs/html/_data_j_s_o_n_8h.html create mode 100644 docs/html/_data_j_s_o_n_8h_source.html create mode 100644 docs/html/_device_log_j_s_o_n_8cpp.html create mode 100644 docs/html/_device_log_j_s_o_n_8cpp_source.html create mode 100644 docs/html/_device_log_j_s_o_n_8h.html create mode 100644 docs/html/_device_log_j_s_o_n_8h_source.html create mode 100644 docs/html/classc_data_j_s_o_n-members.html create mode 100644 docs/html/classc_data_j_s_o_n.html create mode 100644 docs/html/classc_device_log_j_s_o_n-members.html create mode 100644 docs/html/classc_device_log_j_s_o_n.html create mode 100644 docs/html/classc_device_log_j_s_o_n.png create mode 100644 docs/html/classi_i_s_tcp_server_delegate.png delete mode 100644 pySDK/CMakeLists.txt delete mode 100644 pySDK/MANIFEST.in delete mode 100644 pySDK/pySDK.cpp delete mode 100644 pySDK/pySDK.h delete mode 100644 pySDK/pybind11-2.1.1/.appveyor.yml delete mode 100644 pySDK/pybind11-2.1.1/.gitignore delete mode 100644 pySDK/pybind11-2.1.1/.gitmodules delete mode 100644 pySDK/pybind11-2.1.1/.readthedocs.yml delete mode 100644 pySDK/pybind11-2.1.1/.travis.yml delete mode 100644 pySDK/pybind11-2.1.1/CMakeLists.txt delete mode 100644 pySDK/pybind11-2.1.1/CONTRIBUTING.md delete mode 100644 pySDK/pybind11-2.1.1/ISSUE_TEMPLATE.md delete mode 100644 pySDK/pybind11-2.1.1/LICENSE delete mode 100644 pySDK/pybind11-2.1.1/MANIFEST.in delete mode 100644 pySDK/pybind11-2.1.1/README.md delete mode 100644 pySDK/pybind11-2.1.1/docs/Doxyfile delete mode 100644 pySDK/pybind11-2.1.1/docs/_static/theme_overrides.css delete mode 100644 pySDK/pybind11-2.1.1/docs/advanced/cast/chrono.rst delete mode 100644 pySDK/pybind11-2.1.1/docs/advanced/cast/custom.rst delete mode 100644 pySDK/pybind11-2.1.1/docs/advanced/cast/eigen.rst delete mode 100644 pySDK/pybind11-2.1.1/docs/advanced/cast/functional.rst delete mode 100644 pySDK/pybind11-2.1.1/docs/advanced/cast/index.rst delete mode 100644 pySDK/pybind11-2.1.1/docs/advanced/cast/overview.rst delete mode 100644 pySDK/pybind11-2.1.1/docs/advanced/cast/stl.rst delete mode 100644 pySDK/pybind11-2.1.1/docs/advanced/cast/strings.rst delete mode 100644 pySDK/pybind11-2.1.1/docs/advanced/classes.rst delete mode 100644 pySDK/pybind11-2.1.1/docs/advanced/exceptions.rst delete mode 100644 pySDK/pybind11-2.1.1/docs/advanced/functions.rst delete mode 100644 pySDK/pybind11-2.1.1/docs/advanced/misc.rst delete mode 100644 pySDK/pybind11-2.1.1/docs/advanced/pycpp/index.rst delete mode 100644 pySDK/pybind11-2.1.1/docs/advanced/pycpp/numpy.rst delete mode 100644 pySDK/pybind11-2.1.1/docs/advanced/pycpp/object.rst delete mode 100644 pySDK/pybind11-2.1.1/docs/advanced/pycpp/utilities.rst delete mode 100644 pySDK/pybind11-2.1.1/docs/advanced/smart_ptrs.rst delete mode 100644 pySDK/pybind11-2.1.1/docs/basics.rst delete mode 100644 pySDK/pybind11-2.1.1/docs/benchmark.py delete mode 100644 pySDK/pybind11-2.1.1/docs/benchmark.rst delete mode 100644 pySDK/pybind11-2.1.1/docs/changelog.rst delete mode 100644 pySDK/pybind11-2.1.1/docs/classes.rst delete mode 100644 pySDK/pybind11-2.1.1/docs/compiling.rst delete mode 100644 pySDK/pybind11-2.1.1/docs/conf.py delete mode 100644 pySDK/pybind11-2.1.1/docs/faq.rst delete mode 100644 pySDK/pybind11-2.1.1/docs/index.rst delete mode 100644 pySDK/pybind11-2.1.1/docs/intro.rst delete mode 100644 pySDK/pybind11-2.1.1/docs/limitations.rst delete mode 100644 pySDK/pybind11-2.1.1/docs/pybind11-logo.png delete mode 100644 pySDK/pybind11-2.1.1/docs/pybind11_vs_boost_python1.png delete mode 100644 pySDK/pybind11-2.1.1/docs/pybind11_vs_boost_python1.svg delete mode 100644 pySDK/pybind11-2.1.1/docs/pybind11_vs_boost_python2.png delete mode 100644 pySDK/pybind11-2.1.1/docs/pybind11_vs_boost_python2.svg delete mode 100644 pySDK/pybind11-2.1.1/docs/reference.rst delete mode 100644 pySDK/pybind11-2.1.1/docs/release.rst delete mode 100644 pySDK/pybind11-2.1.1/docs/requirements.txt delete mode 100644 pySDK/pybind11-2.1.1/include/pybind11/attr.h delete mode 100644 pySDK/pybind11-2.1.1/include/pybind11/cast.h delete mode 100644 pySDK/pybind11-2.1.1/include/pybind11/chrono.h delete mode 100644 pySDK/pybind11-2.1.1/include/pybind11/class_support.h delete mode 100644 pySDK/pybind11-2.1.1/include/pybind11/common.h delete mode 100644 pySDK/pybind11-2.1.1/include/pybind11/complex.h delete mode 100644 pySDK/pybind11-2.1.1/include/pybind11/descr.h delete mode 100644 pySDK/pybind11-2.1.1/include/pybind11/eigen.h delete mode 100644 pySDK/pybind11-2.1.1/include/pybind11/eval.h delete mode 100644 pySDK/pybind11-2.1.1/include/pybind11/functional.h delete mode 100644 pySDK/pybind11-2.1.1/include/pybind11/numpy.h delete mode 100644 pySDK/pybind11-2.1.1/include/pybind11/operators.h delete mode 100644 pySDK/pybind11-2.1.1/include/pybind11/options.h delete mode 100644 pySDK/pybind11-2.1.1/include/pybind11/pybind11.h delete mode 100644 pySDK/pybind11-2.1.1/include/pybind11/pytypes.h delete mode 100644 pySDK/pybind11-2.1.1/include/pybind11/stl.h delete mode 100644 pySDK/pybind11-2.1.1/include/pybind11/stl_bind.h delete mode 100644 pySDK/pybind11-2.1.1/include/pybind11/typeid.h delete mode 100644 pySDK/pybind11-2.1.1/pybind11/__init__.py delete mode 100644 pySDK/pybind11-2.1.1/pybind11/_version.py delete mode 100644 pySDK/pybind11-2.1.1/setup.cfg delete mode 100644 pySDK/pybind11-2.1.1/setup.py delete mode 100644 pySDK/pybind11-2.1.1/tests/CMakeLists.txt delete mode 100644 pySDK/pybind11-2.1.1/tests/conftest.py delete mode 100644 pySDK/pybind11-2.1.1/tests/constructor_stats.h delete mode 100644 pySDK/pybind11-2.1.1/tests/object.h delete mode 100644 pySDK/pybind11-2.1.1/tests/pybind11_tests.cpp delete mode 100644 pySDK/pybind11-2.1.1/tests/pybind11_tests.h delete mode 100644 pySDK/pybind11-2.1.1/tests/pytest.ini delete mode 100644 pySDK/pybind11-2.1.1/tests/test_alias_initialization.cpp delete mode 100644 pySDK/pybind11-2.1.1/tests/test_alias_initialization.py delete mode 100644 pySDK/pybind11-2.1.1/tests/test_buffers.cpp delete mode 100644 pySDK/pybind11-2.1.1/tests/test_buffers.py delete mode 100644 pySDK/pybind11-2.1.1/tests/test_callbacks.cpp delete mode 100644 pySDK/pybind11-2.1.1/tests/test_callbacks.py delete mode 100644 pySDK/pybind11-2.1.1/tests/test_chrono.cpp delete mode 100644 pySDK/pybind11-2.1.1/tests/test_chrono.py delete mode 100644 pySDK/pybind11-2.1.1/tests/test_class_args.cpp delete mode 100644 pySDK/pybind11-2.1.1/tests/test_class_args.py delete mode 100644 pySDK/pybind11-2.1.1/tests/test_cmake_build/installed_function/CMakeLists.txt delete mode 100644 pySDK/pybind11-2.1.1/tests/test_cmake_build/installed_target/CMakeLists.txt delete mode 100644 pySDK/pybind11-2.1.1/tests/test_cmake_build/main.cpp delete mode 100644 pySDK/pybind11-2.1.1/tests/test_cmake_build/subdirectory_function/CMakeLists.txt delete mode 100644 pySDK/pybind11-2.1.1/tests/test_cmake_build/subdirectory_target/CMakeLists.txt delete mode 100644 pySDK/pybind11-2.1.1/tests/test_cmake_build/test.py delete mode 100644 pySDK/pybind11-2.1.1/tests/test_constants_and_functions.cpp delete mode 100644 pySDK/pybind11-2.1.1/tests/test_constants_and_functions.py delete mode 100644 pySDK/pybind11-2.1.1/tests/test_copy_move_policies.cpp delete mode 100644 pySDK/pybind11-2.1.1/tests/test_copy_move_policies.py delete mode 100644 pySDK/pybind11-2.1.1/tests/test_docstring_options.cpp delete mode 100644 pySDK/pybind11-2.1.1/tests/test_docstring_options.py delete mode 100644 pySDK/pybind11-2.1.1/tests/test_eigen.cpp delete mode 100644 pySDK/pybind11-2.1.1/tests/test_eigen.py delete mode 100644 pySDK/pybind11-2.1.1/tests/test_enum.cpp delete mode 100644 pySDK/pybind11-2.1.1/tests/test_enum.py delete mode 100644 pySDK/pybind11-2.1.1/tests/test_eval.cpp delete mode 100644 pySDK/pybind11-2.1.1/tests/test_eval.py delete mode 100644 pySDK/pybind11-2.1.1/tests/test_eval_call.py delete mode 100644 pySDK/pybind11-2.1.1/tests/test_exceptions.cpp delete mode 100644 pySDK/pybind11-2.1.1/tests/test_exceptions.py delete mode 100644 pySDK/pybind11-2.1.1/tests/test_inheritance.cpp delete mode 100644 pySDK/pybind11-2.1.1/tests/test_inheritance.py delete mode 100644 pySDK/pybind11-2.1.1/tests/test_issues.cpp delete mode 100644 pySDK/pybind11-2.1.1/tests/test_issues.py delete mode 100644 pySDK/pybind11-2.1.1/tests/test_keep_alive.cpp delete mode 100644 pySDK/pybind11-2.1.1/tests/test_keep_alive.py delete mode 100644 pySDK/pybind11-2.1.1/tests/test_kwargs_and_defaults.cpp delete mode 100644 pySDK/pybind11-2.1.1/tests/test_kwargs_and_defaults.py delete mode 100644 pySDK/pybind11-2.1.1/tests/test_methods_and_attributes.cpp delete mode 100644 pySDK/pybind11-2.1.1/tests/test_methods_and_attributes.py delete mode 100644 pySDK/pybind11-2.1.1/tests/test_modules.cpp delete mode 100644 pySDK/pybind11-2.1.1/tests/test_modules.py delete mode 100644 pySDK/pybind11-2.1.1/tests/test_multiple_inheritance.cpp delete mode 100644 pySDK/pybind11-2.1.1/tests/test_multiple_inheritance.py delete mode 100644 pySDK/pybind11-2.1.1/tests/test_numpy_array.cpp delete mode 100644 pySDK/pybind11-2.1.1/tests/test_numpy_array.py delete mode 100644 pySDK/pybind11-2.1.1/tests/test_numpy_dtypes.cpp delete mode 100644 pySDK/pybind11-2.1.1/tests/test_numpy_dtypes.py delete mode 100644 pySDK/pybind11-2.1.1/tests/test_numpy_vectorize.cpp delete mode 100644 pySDK/pybind11-2.1.1/tests/test_numpy_vectorize.py delete mode 100644 pySDK/pybind11-2.1.1/tests/test_opaque_types.cpp delete mode 100644 pySDK/pybind11-2.1.1/tests/test_opaque_types.py delete mode 100644 pySDK/pybind11-2.1.1/tests/test_operator_overloading.cpp delete mode 100644 pySDK/pybind11-2.1.1/tests/test_operator_overloading.py delete mode 100644 pySDK/pybind11-2.1.1/tests/test_pickling.cpp delete mode 100644 pySDK/pybind11-2.1.1/tests/test_pickling.py delete mode 100644 pySDK/pybind11-2.1.1/tests/test_python_types.cpp delete mode 100644 pySDK/pybind11-2.1.1/tests/test_python_types.py delete mode 100644 pySDK/pybind11-2.1.1/tests/test_sequences_and_iterators.cpp delete mode 100644 pySDK/pybind11-2.1.1/tests/test_sequences_and_iterators.py delete mode 100644 pySDK/pybind11-2.1.1/tests/test_smart_ptr.cpp delete mode 100644 pySDK/pybind11-2.1.1/tests/test_smart_ptr.py delete mode 100644 pySDK/pybind11-2.1.1/tests/test_stl_binders.cpp delete mode 100644 pySDK/pybind11-2.1.1/tests/test_stl_binders.py delete mode 100644 pySDK/pybind11-2.1.1/tests/test_virtual_functions.cpp delete mode 100644 pySDK/pybind11-2.1.1/tests/test_virtual_functions.py delete mode 100644 pySDK/pybind11-2.1.1/tools/FindEigen3.cmake delete mode 100644 pySDK/pybind11-2.1.1/tools/FindPythonLibsNew.cmake delete mode 100644 pySDK/pybind11-2.1.1/tools/check-style.sh delete mode 100644 pySDK/pybind11-2.1.1/tools/libsize.py delete mode 100644 pySDK/pybind11-2.1.1/tools/mkdoc.py delete mode 100644 pySDK/pybind11-2.1.1/tools/pybind11Config.cmake.in delete mode 100644 pySDK/pybind11-2.1.1/tools/pybind11Tools.cmake delete mode 100644 pySDK/setup.py delete mode 100644 pySDK/src/cltool.py create mode 100644 src/DataJSON.cpp create mode 100644 src/DataJSON.h create mode 100644 src/DeviceLogJSON.cpp create mode 100644 src/DeviceLogJSON.h diff --git a/CLTool/README.md b/CLTool/README.md index fa0de1656..e995728ab 100644 --- a/CLTool/README.md +++ b/CLTool/README.md @@ -1,13 +1,13 @@ -# C++ API - Inertial Sense Class and Cltool Example Project +# C++ API - Inertial Sense Class and CLTool Example Project -The InertialSense C++ class, defined in InertialSense.h/.cpp, provides all SDK capabilities including serial communications, data logging to file, and embedded firmware update for InertialSense products. +The InertialSense C++ class, defined in InertialSense.h/.cpp, provides all SDK capabilities including serial communications, data logging to file, and embedded firmware update for InertialSense products. -## Cltool Example +## CLTool Example -The Command Line Tool (cltool) is a light weight open source project designed to illustrate InertialSense class implementation. The cltool project can be compiled on most operating systems using cmake and gcc. A Visual Studio project for Windows is also included. See [Using CLTool](../App_Usage/cltool.md) section for details on compiling and runing the cltool. +The Command Line Tool (CLTool) is an open source project designed to illustrate InertialSense C++ class implementation. The CLTool project can be compiled on most operating systems using cmake and gcc and can be used to communicate, log data, and update firmware for Inertial Sense products. A Visual Studio project for Windows is also included. See [Using CLTool](../App_Usage/cltool.md) for details on compiling and running the CLTool. ### Implementation Keywords -The following keywords are found in the cltool soure code identify the steps for InertialSense class implementation. +The following keywords are found in the CLTool soure code identify the steps for InertialSense class implementation. ```C++ /* SDK Implementation Keywords: @@ -31,9 +31,9 @@ Include the InertialSense header file. Create InertialSense object. InertialSense inertialSenseInterface(cltool_dataCallback); ``` -### Step 2: Open serial port +### Step 2: Open serial port -Open the serial by specifying the com port number, buadrate, and and The serial port used for communications +Open the serial by specifying the com port number, buadrate, and and The serial port used for communications ```C++ if (!inertialSenseInterface.Open(g_commandLineOptions.comPort.c_str(), @@ -130,10 +130,22 @@ if (!cltool_setupLogger(inertialSenseInterface)) } ``` +### Run () + +```c +// [LOGGER INSTRUCTION] Setup and start data logger +if (!cltool_setupLogger(inertialSenseInterface)) +{ + cout << "Failed to setup logger!" << endl; + return -1; +} +``` + ## Compile & Run (Linux/Mac) + 1. Create build directory ``` bash -$ cd InertialSenseCLTool +$ cd CLTool $ mkdir build ``` 2. Run cmake from within build directory @@ -157,14 +169,15 @@ $ ./bin/cltool ``` ## Compile & Run (Windows MS Visual Studio) -1. Open Visual Studio solution file (InertialSenseSDK/InertialSenseCLTool/VS_project/InertialSenseCLTool.sln) -2. Build (F7) -3. Run executable +1. [Install and Configure Visual Studio](../getting-started/#installing-and-configuring-visual-studio) +2. Open Visual Studio solution file (InertialSenseSDK/CLTool/VS_project/CLTool.sln) +3. Build (F7) +4. Run executable ``` bash -C:\InertialSenseSDK\InertialSenseCLTool\VS_project\Release\cltool.exe +C:\InertialSenseSDK\CLTool\VS_project\Release\cltool.exe ``` ## Summary -That covers all the basic functionality you need to set up and talk to InertialSense products. If this doesn't cover everything you need, feel free to reach out to us on the InertialSenseSDK github repository, and we will be happy to help. +This section has covered the basic functionality you need to set up and communicate with Inertial Sense products. If this doesn't cover everything you need, feel free to reach out to us on the Inertial Sense SDK GitHub repository, and we will be happy to help. diff --git a/CLTool/VS_project/IS_logs/20180801_225711/LOG_SN30235_20180801_225711_0001.dat b/CLTool/VS_project/IS_logs/20180801_225711/LOG_SN30235_20180801_225711_0001.dat new file mode 100644 index 0000000000000000000000000000000000000000..4e92f0a210ad9414515c661119ebc1627b87a977 GIT binary patch literal 114136 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 ut_|C8{sD-<;^-#gqHrrm> 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𝔜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 literal 0 HcmV?d00001 diff --git a/CLTool/VS_project/IS_logs/20180801_225926/diagnostic_30235.txt b/CLTool/VS_project/IS_logs/20180801_225926/diagnostic_30235.txt new file mode 100644 index 000000000..1ec2180d8 --- /dev/null +++ b/CLTool/VS_project/IS_logs/20180801_225926/diagnostic_30235.txt @@ -0,0 +1,42 @@ +RTK: 2018-08-02T04:59:47.00Z age of differential error (age=7653.5) +RTK: 2018-08-02T04:59:50.80Z age of differential error (age=7657.3) +RTK: 2018-08-02T04:59:58.40Z age of differential error (age=7664.9) +RTK: 2018-08-02T05:00:09.60Z age of differential error (age=7676.1) +RTK: 2018-08-02T05:00:12.40Z age of differential error (age=7678.9) +RTK: 2018-08-02T05:00:28.20Z age of differential error (age=7694.7) +RTK: 2018-08-02T05:00:31.00Z age of differential error (age=7697.5) +RTK: 2018-08-02T05:00:34.60Z age of differential error (age=7701.1) +RTK: 2018-08-02T05:00:47.80Z age of differential error (age=7714.3) +RTK: 2018-08-02T05:00:57.60Z age of differential error (age=7724.1) +RTK: 2018-08-02T05:01:01.20Z age of differential error (age=7727.7) +RTK: 2018-08-02T05:01:03.20Z age of differential error (age=7729.7) +RTK: 2018-08-02T05:01:07.00Z age of differential error (age=7733.5) +RTK: 2018-08-02T05:01:13.60Z age of differential error (age=7740.1) +RTK: 2018-08-02T05:01:18.60Z age of differential error (age=7745.1) +RTK: 2018-08-02T05:01:24.40Z age of differential error (age=7750.9) +RTK: 2018-08-02T05:01:33.40Z age of differential error (age=7759.9) +RTK: 2018-08-02T05:01:38.60Z age of differential error (age=7765.1) +RTK: 2018-08-02T05:01:46.60Z age of differential error (age=7773.1) +RTK: 2018-08-02T05:01:48.40Z age of differential error (age=7774.9) +RTK: 2018-08-02T05:01:50.00Z age of differential error (age=7776.5) +RTK: 2018-08-02T05:01:55.80Z age of differential error (age=7782.3) +RTK: 2018-08-02T05:01:59.60Z age of differential error (age=7786.1) +RTK: 2018-08-02T05:02:00.60Z age of differential error (age=7787.1) +RTK: 2018-08-02T05:02:12.00Z age of differential error (age=7798.5) +RTK: 2018-08-02T05:02:19.00Z age of differential error (age=7805.5) +RTK: 2018-08-02T05:02:29.20Z age of differential error (age=7815.7) +RTK: 2018-08-02T05:02:36.00Z age of differential error (age=7822.5) +RTK: 2018-08-02T05:02:38.20Z age of differential error (age=7824.7) +RTK: 2018-08-02T05:02:38.40Z age of differential error (age=7824.9) +RTK: 2018-08-02T05:02:47.60Z age of differential error (age=7834.1) +RTK: 2018-08-02T05:02:54.80Z age of differential error (age=7841.3) +RTK: 2018-08-02T05:02:55.40Z age of differential error (age=7841.9) +RTK: 2018-08-02T05:03:02.00Z age of differential error (age=7848.5) +RTK: 2018-08-02T05:03:07.00Z age of differential error (age=7853.5) +RTK: 2018-08-02T05:03:12.20Z age of differential error (age=7858.7) +RTK: 2018-08-02T05:03:17.80Z age of differential error (age=7864.3) +RTK: 2018-08-02T05:03:23.20Z age of differential error (age=7869.7) +RTK: 2018-08-02T05:03:34.00Z age of differential error (age=7880.5) +RTK: 2018-08-02T05:03:52.40Z age of differential error (age=7898.9) +RTK: 2018-08-02T05:03:56.60Z age of differential error (age=7903.1) +RTK: 2018-08-02T05:04:01.00Z age of differential error (age=7907.5) diff --git a/CLTool/VS_project/IS_logs/20180801_225926/errors.txt b/CLTool/VS_project/IS_logs/20180801_225926/errors.txt new file mode 100644 index 000000000..e69de29bb diff --git a/CLTool/VS_project/IS_logs/20180801_225926/stats.txt b/CLTool/VS_project/IS_logs/20180801_225926/stats.txt new file mode 100644 index 000000000..1413b0567 --- /dev/null +++ b/CLTool/VS_project/IS_logs/20180801_225926/stats.txt @@ -0,0 +1,143 @@ +Count: 5247 +Errors: 0 + +Data Id: 1 - devInfo +Count: 2 +Errors: 0 +Average Timestamp Delta: 0.000000 +Max Timestamp Delta: 0.000000 +Timestamp Drops: 0 + +Data Id: 3 - preintegratedImu +Count: 2298 +Errors: 0 +Average Timestamp Delta: 0.111184 +Max Timestamp Delta: 5.947603 +Timestamp Drops: 168 + +Data Id: 5 - ins2 +Count: 87 +Errors: 0 +Average Timestamp Delta: 2.918792 +Max Timestamp Delta: 6.000001 +Timestamp Drops: 27 + +Data Id: 6 - gpsPos +Count: 41 +Errors: 0 +Average Timestamp Delta: 6.385000 +Max Timestamp Delta: 28.200000 +Timestamp Drops: 25 + +Data Id: 7 - config +Count: 1 +Errors: 0 +Average Timestamp Delta: 0.000000 +Max Timestamp Delta: 0.000000 +Timestamp Drops: 0 + +Data Id: 10 - sysParams +Count: 1 +Errors: 0 +Average Timestamp Delta: 0.000000 +Max Timestamp Delta: 0.000000 +Timestamp Drops: 0 + +Data Id: 12 - flashCfg +Count: 3 +Errors: 0 +Average Timestamp Delta: 0.000000 +Max Timestamp Delta: 0.000000 +Timestamp Drops: 0 + +Data Id: 21 - gpsRtkRel +Count: 40 +Errors: 0 +Average Timestamp Delta: 6.512795 +Max Timestamp Delta: 18.400000 +Timestamp Drops: 21 + +Data Id: 30 - DID_GPS1_VEL +Count: 45 +Errors: 0 +Average Timestamp Delta: 5.804545 +Max Timestamp Delta: 23.200000 +Timestamp Drops: 26 + +Data Id: 35 - userpage0 +Count: 1 +Errors: 0 +Average Timestamp Delta: 0.000000 +Max Timestamp Delta: 0.000000 +Timestamp Drops: 0 + +Data Id: 36 - userpage1 +Count: 1 +Errors: 0 +Average Timestamp Delta: 0.000000 +Max Timestamp Delta: 0.000000 +Timestamp Drops: 0 + +Data Id: 48 - inl2States +Count: 51 +Errors: 0 +Average Timestamp Delta: 0.000000 +Max Timestamp Delta: 0.000000 +Timestamp Drops: 0 + +Data Id: 50 - inl2Status +Count: 1 +Errors: 0 +Average Timestamp Delta: 0.000000 +Max Timestamp Delta: 0.000000 +Timestamp Drops: 0 + +Data Id: 51 - inl2Misc +Count: 1 +Errors: 0 +Average Timestamp Delta: 0.000000 +Max Timestamp Delta: 0.000000 +Timestamp Drops: 0 + +Data Id: 52 - magnetometer1 +Count: 773 +Errors: 0 +Average Timestamp Delta: 0.330806 +Max Timestamp Delta: 5.959603 +Timestamp Drops: 257 + +Data Id: 53 - barometer +Count: 912 +Errors: 0 +Average Timestamp Delta: 0.280319 +Max Timestamp Delta: 5.963603 +Timestamp Drops: 298 + +Data Id: 55 - magnetometer2 +Count: 808 +Errors: 0 +Average Timestamp Delta: 0.316459 +Max Timestamp Delta: 5.959603 +Timestamp Drops: 239 + +Data Id: 59 - inl2MagObs +Count: 49 +Errors: 0 +Average Timestamp Delta: 0.000000 +Max Timestamp Delta: 0.000000 +Timestamp Drops: 0 + +Data Id: 67 - inl2Variance +Count: 90 +Errors: 0 +Average Timestamp Delta: 0.000000 +Max Timestamp Delta: 0.000000 +Timestamp Drops: 0 + +Data Id: 72 - diagnosticMsg +Count: 42 +Errors: 0 +Average Timestamp Delta: 6.195195 +Max Timestamp Delta: 18.399000 +Timestamp Drops: 22 + diff --git a/CLTool/VS_project/IS_logs/20180801_225926/stats_SN30235.txt b/CLTool/VS_project/IS_logs/20180801_225926/stats_SN30235.txt new file mode 100644 index 000000000..1413b0567 --- /dev/null +++ b/CLTool/VS_project/IS_logs/20180801_225926/stats_SN30235.txt @@ -0,0 +1,143 @@ +Count: 5247 +Errors: 0 + +Data Id: 1 - devInfo +Count: 2 +Errors: 0 +Average Timestamp Delta: 0.000000 +Max Timestamp Delta: 0.000000 +Timestamp Drops: 0 + +Data Id: 3 - preintegratedImu +Count: 2298 +Errors: 0 +Average Timestamp Delta: 0.111184 +Max Timestamp Delta: 5.947603 +Timestamp Drops: 168 + +Data Id: 5 - ins2 +Count: 87 +Errors: 0 +Average Timestamp Delta: 2.918792 +Max Timestamp Delta: 6.000001 +Timestamp Drops: 27 + +Data Id: 6 - gpsPos +Count: 41 +Errors: 0 +Average Timestamp Delta: 6.385000 +Max Timestamp Delta: 28.200000 +Timestamp Drops: 25 + +Data Id: 7 - config +Count: 1 +Errors: 0 +Average Timestamp Delta: 0.000000 +Max Timestamp Delta: 0.000000 +Timestamp Drops: 0 + +Data Id: 10 - sysParams +Count: 1 +Errors: 0 +Average Timestamp Delta: 0.000000 +Max Timestamp Delta: 0.000000 +Timestamp Drops: 0 + +Data Id: 12 - flashCfg +Count: 3 +Errors: 0 +Average Timestamp Delta: 0.000000 +Max Timestamp Delta: 0.000000 +Timestamp Drops: 0 + +Data Id: 21 - gpsRtkRel +Count: 40 +Errors: 0 +Average Timestamp Delta: 6.512795 +Max Timestamp Delta: 18.400000 +Timestamp Drops: 21 + +Data Id: 30 - DID_GPS1_VEL +Count: 45 +Errors: 0 +Average Timestamp Delta: 5.804545 +Max Timestamp Delta: 23.200000 +Timestamp Drops: 26 + +Data Id: 35 - userpage0 +Count: 1 +Errors: 0 +Average Timestamp Delta: 0.000000 +Max Timestamp Delta: 0.000000 +Timestamp Drops: 0 + +Data Id: 36 - userpage1 +Count: 1 +Errors: 0 +Average Timestamp Delta: 0.000000 +Max Timestamp Delta: 0.000000 +Timestamp Drops: 0 + +Data Id: 48 - inl2States +Count: 51 +Errors: 0 +Average Timestamp Delta: 0.000000 +Max Timestamp Delta: 0.000000 +Timestamp Drops: 0 + +Data Id: 50 - inl2Status +Count: 1 +Errors: 0 +Average Timestamp Delta: 0.000000 +Max Timestamp Delta: 0.000000 +Timestamp Drops: 0 + +Data Id: 51 - inl2Misc +Count: 1 +Errors: 0 +Average Timestamp Delta: 0.000000 +Max Timestamp Delta: 0.000000 +Timestamp Drops: 0 + +Data Id: 52 - magnetometer1 +Count: 773 +Errors: 0 +Average Timestamp Delta: 0.330806 +Max Timestamp Delta: 5.959603 +Timestamp Drops: 257 + +Data Id: 53 - barometer +Count: 912 +Errors: 0 +Average Timestamp Delta: 0.280319 +Max Timestamp Delta: 5.963603 +Timestamp Drops: 298 + +Data Id: 55 - magnetometer2 +Count: 808 +Errors: 0 +Average Timestamp Delta: 0.316459 +Max Timestamp Delta: 5.959603 +Timestamp Drops: 239 + +Data Id: 59 - inl2MagObs +Count: 49 +Errors: 0 +Average Timestamp Delta: 0.000000 +Max Timestamp Delta: 0.000000 +Timestamp Drops: 0 + +Data Id: 67 - inl2Variance +Count: 90 +Errors: 0 +Average Timestamp Delta: 0.000000 +Max Timestamp Delta: 0.000000 +Timestamp Drops: 0 + +Data Id: 72 - diagnosticMsg +Count: 42 +Errors: 0 +Average Timestamp Delta: 6.195195 +Max Timestamp Delta: 18.399000 +Timestamp Drops: 22 + diff --git a/CMakeLists.txt b/CMakeLists.txt index 15273bee5..a8b088e14 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,9 +6,11 @@ add_library(InertialSense src/DataChunk.cpp src/DataChunkSorted.cpp src/DataCSV.cpp + src/DataJSON.cpp src/DataKML.cpp src/DeviceLog.cpp src/DeviceLogCSV.cpp + src/DeviceLogJSON.cpp src/DeviceLogKML.cpp src/DeviceLogSerial.cpp src/DeviceLogSorted.cpp diff --git a/ExampleProjects/Communications/ISCommunicationsExample.c b/ExampleProjects/Communications/ISCommunicationsExample.c index 4fbe624b8..17b32fcce 100644 --- a/ExampleProjects/Communications/ISCommunicationsExample.c +++ b/ExampleProjects/Communications/ISCommunicationsExample.c @@ -27,9 +27,9 @@ static void handleInsMessage(ins_1_t* ins) ins->theta[0] * C_RAD2DEG_F, ins->theta[1] * C_RAD2DEG_F, ins->theta[2] * C_RAD2DEG_F ); } -static void handleGpsMessage(gps_nav_t* gps) +static void handleGpsMessage(gps_pos_t* pos) { - printf("GPS TimeOfWeek: %dms, LLA: %3.7f,%3.7f,%5.2f\r\n", gps->timeOfWeekMs, gps->lla[0], gps->lla[1], gps->lla[2]); + printf("GPS TimeOfWeek: %dms, LLA: %3.7f,%3.7f,%5.2f\r\n", pos->timeOfWeekMs, pos->lla[0], pos->lla[1], pos->lla[2]); } static void handleImuMessage(dual_imu_t* imu) @@ -73,7 +73,7 @@ int enable_message_broadcasting_RMC(serial_port_t *serialPort, is_comm_instance_ { // Enable broadcasts using RMC: DID_INS_1 @ 20Hz and DID_GPS_NAV @ 5Hz rmc_t rmc; - rmc.bits = RMC_BITS_INS1 | RMC_BITS_GPS_NAV; + rmc.bits = RMC_BITS_INS1 | RMC_BITS_GPS1_POS; rmc.insPeriodMs = 50; // INS @ 20Hz rmc.options = RMC_OPTIONS_SET_STARTUP_STREAM; // Current port. Preconfigure streaming (remember) for startup. @@ -204,7 +204,7 @@ int main(int argc, char* argv[]) break; case _DID_GPS_NAV: - handleGpsMessage((gps_nav_t*)buffer); + handleGpsMessage((gps_pos_t*)buffer); break; case _DID_IMU_DUAL: diff --git a/ExampleProjects/LogReader/CMakeLists.txt b/ExampleProjects/LogReader/CMakeLists.txt new file mode 100644 index 000000000..565ecdc2b --- /dev/null +++ b/ExampleProjects/LogReader/CMakeLists.txt @@ -0,0 +1,42 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.8.9) + +project(ISLogReaderExample) + +set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake) + +FIND_PACKAGE(Threads) + +add_definitions( + -O3 + -g + -pedantic +# -Wall # Enable all warnings + -Wextra + -fvisibility=hidden +# -DXPLM200 +# -DXPLM210 +# -DAPL=0 +# -DIBM=0 +# -DLIN=1 +# -fPIC +# -DNDEBUG +) + +if(APPLE) +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu11") +SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11") +else() +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu11 -fms-extensions -Wl,--no-as-needed") +SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11 -fms-extensions -Wl,--no-as-needed") +endif() + +SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) + +add_executable(ISLogReaderExample + "ISLogReaderExample.cpp" +) + +add_subdirectory(../../ ${CMAKE_CURRENT_BINARY_DIR}/SDK) + +target_link_libraries(ISLogReaderExample ${CMAKE_THREAD_LIBS_INIT}) +target_link_libraries(ISLogReaderExample InertialSense) diff --git a/ExampleProjects/LogReader/ISLogReaderExample.cpp b/ExampleProjects/LogReader/ISLogReaderExample.cpp new file mode 100644 index 000000000..453cc0674 --- /dev/null +++ b/ExampleProjects/LogReader/ISLogReaderExample.cpp @@ -0,0 +1,61 @@ +/* +MIT LICENSE + +Copyright 2014 Inertial Sense, LLC - http://inertialsense.com + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files(the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include + +// STEP 1: Add Includes +// Change these include paths to the correct paths for your project +#include "../../src/InertialSense.h" + +static void dataCallback(InertialSense* i, p_data_t* data, int pHandle) +{ + static uint64_t dataCount; + printf("Data count: %" PRIu64 " \r", ++dataCount); +} + +int main(int argc, char* argv[]) +{ + if (argc < 1) + { + printf("Please pass the data log directory path (i.e. \"C:\Users\[username]\Documents\Inertial Sense\Logs\20180716_172323)\"\r\n"); + // In Visual Studio IDE, this can be done through "Project Properties -> Debugging -> Command Arguments: COM3 kml" + return -1; + } + + + // STEP 2: Instantiate InertialSense class + // InertialSense class wraps communications and logging in a convenient, easy to use class + InertialSense inertialSense(dataCallback); + if (!inertialSense.Open(argv[1])) + { + std::cout << "Failed to open com port at " << argv[1] << std::endl; + } + + + // STEP 3: Enable data logger + // get log type from command line + cISLogger::eLogType logType = (argc < 3 ? cISLogger::eLogType::LOGTYPE_DAT : cISLogger::ParseLogType(argv[2])); + inertialSense.SetLoggerEnabled(true, "", logType); + + // utility class for display and ctrl-c handling + cInertialSenseDisplay display; + + std::cout << "Started logger..." << std::endl; + + while (!display.ControlCWasPressed()) + { + inertialSense.Update(); + } + + inertialSense.Close(); +} + diff --git a/ExampleProjects/LogReader/README.md b/ExampleProjects/LogReader/README.md new file mode 100644 index 000000000..694a02e9f --- /dev/null +++ b/ExampleProjects/LogReader/README.md @@ -0,0 +1,97 @@ +# SDK: Data Log Reader Example Project + +This [ISLogReaderExample](https://github.com/inertialsense/InertialSenseSDK/tree/master/ExampleProjects/LogReader) project demonstrates data logging with the InertialSense products (uINS, uAHRS, and uIMU) using the Inertial Sense SDK. + +## Files + +#### Project Files + +* [ISLogReaderExample.cpp](https://github.com/inertialsense/InertialSenseSDK/tree/master/ExampleProjects/LogReader/ISLogReaderExample.cpp) + +#### SDK Files + +* [SDK](https://github.com/inertialsense/InertialSenseSDK/tree/master/src) + + +## Implementation + +### Step 1: Add Includes + +```C++ +// Change these include paths to the correct paths for your project +#include "../../src/InertialSense.h" +``` + +### Step 2: Instantiate InertialSense class + +```C++ + // InertialSense class wraps communications and logging in a convenient, easy to use class + InertialSense inertialSense(dataCallback); + if (!inertialSense.Open(argv[1])) + { + std::cout << "Failed to open com port at " << argv[1] << std::endl; + } +``` + +### Step 3: Enable data logger + +```C++ + // get log type from command line + cISLogger::eLogType logType = (argc < 3 ? cISLogger::eLogType::LOGTYPE_DAT : cISLogger::ParseLogType(argv[2])); + inertialSense.SetLoggerEnabled(true, "", logType); +``` + +### Step 4: Enable data broadcasting + +```C++ + // broadcast the standard set of post processing messages (ins, imu, etc.) + inertialSense.BroadcastBinaryDataRmcPreset(); + + // instead of the rmc preset (real-time message controller) you can request individual messages... + // inertialSense.BroadcastBinaryData(DID_DUAL_IMU, 10); // imu every 10 milliseconds (100 hz) +``` + +By default, data logs will be stored in the "IS_logs" directory in the current directory. + +``` bash +build/IS_logs/LOG_SN30664_20180323_112822_0001.dat +``` + +## Compile & Run (Linux/Mac) + +1. Create build directory +``` bash +$ cd InertialSenseSDK/ExampleProjects/Logger +$ mkdir build +``` +2. Run cmake from within build directory +``` bash +$ cd build +$ cmake .. +``` +3. Compile using make + ``` bash + $ make + ``` +4. If necessary, add current user to the "dialout" group in order to read and write to the USB serial communication ports: +```bash +$ sudousermod -a -G dialout $USER +$ sudousermod -a -G plugdev $USER +(reboot computer) +``` +5. Run executable +``` bash +$ ./bin/ISLoggerExample /dev/ttyUSB0 +``` +## Compile & Run (Windows MS Visual Studio) + +1. Open Visual Studio solution file (InertialSenseSDK\ExampleProjects\Logger\VS_project\InertialSenseCLTool.sln) +2. Build (F7) +3. Run executable +``` bash +C:\InertialSenseSDK\ExampleProjects\Logger\VS_project\Release\ISLoggerExample.exe COM3 +``` + +## Summary + +That covers all the basic functionality you need to set up and talk to InertialSense products. If this doesn't cover everything you need, feel free to reach out to us on the InertialSenseSDK GitHub repository, and we will be happy to help. diff --git a/ExampleProjects/LogReader/VS_Project/ISLogReader.vcxproj.filters b/ExampleProjects/LogReader/VS_Project/ISLogReader.vcxproj.filters new file mode 100644 index 000000000..e5cb805a2 --- /dev/null +++ b/ExampleProjects/LogReader/VS_Project/ISLogReader.vcxproj.filters @@ -0,0 +1,205 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {56768eea-52d0-41b1-adf8-fd88e4eba0be} + + + + + Source Files\SDK + + + Source Files\SDK + + + Source Files\SDK + + + Source Files\SDK + + + Source Files + + + Source Files\SDK + + + Source Files\SDK + + + Source Files\SDK + + + Source Files\SDK + + + Source Files\SDK + + + Source Files\SDK + + + Source Files\SDK + + + Source Files\SDK + + + Source Files\SDK + + + Source Files\SDK + + + Source Files\SDK + + + Source Files\SDK + + + Source Files\SDK + + + Source Files\SDK + + + Source Files\SDK + + + Source Files\SDK + + + Source Files\SDK + + + Source Files\SDK + + + Source Files\SDK + + + Source Files\SDK + + + Source Files\SDK + + + Source Files\SDK + + + Source Files\SDK + + + Source Files\SDK + + + Source Files\SDK + + + Source Files\SDK + + + Source Files\SDK + + + Source Files\SDK + + + + + Source Files\SDK + + + Source Files\SDK + + + Source Files\SDK + + + Source Files\SDK + + + Source Files\SDK + + + Source Files\SDK + + + Source Files\SDK + + + Source Files\SDK + + + Source Files\SDK + + + Source Files\SDK + + + Source Files\SDK + + + Source Files\SDK + + + Source Files\SDK + + + Source Files\SDK + + + Source Files\SDK + + + Source Files\SDK + + + Source Files\SDK + + + Source Files\SDK + + + Source Files\SDK + + + Source Files\SDK + + + Source Files\SDK + + + Source Files\SDK + + + Source Files\SDK + + + Source Files\SDK + + + Source Files\SDK + + + Source Files\SDK + + + Source Files\SDK + + + Source Files\SDK + + + Source Files\SDK + + + Source Files\SDK + + + diff --git a/ExampleProjects/LogReader/VS_Project/ISLogReaderExample.sln b/ExampleProjects/LogReader/VS_Project/ISLogReaderExample.sln new file mode 100644 index 000000000..7af950a5b --- /dev/null +++ b/ExampleProjects/LogReader/VS_Project/ISLogReaderExample.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.27130.2027 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ISLogReaderExample", "ISLogReaderExample.vcxproj", "{6BC5BD0B-15A1-46B6-B561-C37D8DB83403}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {6BC5BD0B-15A1-46B6-B561-C37D8DB83403}.Debug|x64.ActiveCfg = Debug|x64 + {6BC5BD0B-15A1-46B6-B561-C37D8DB83403}.Debug|x64.Build.0 = Debug|x64 + {6BC5BD0B-15A1-46B6-B561-C37D8DB83403}.Debug|x86.ActiveCfg = Debug|Win32 + {6BC5BD0B-15A1-46B6-B561-C37D8DB83403}.Debug|x86.Build.0 = Debug|Win32 + {6BC5BD0B-15A1-46B6-B561-C37D8DB83403}.Release|x64.ActiveCfg = Release|x64 + {6BC5BD0B-15A1-46B6-B561-C37D8DB83403}.Release|x64.Build.0 = Release|x64 + {6BC5BD0B-15A1-46B6-B561-C37D8DB83403}.Release|x86.ActiveCfg = Release|Win32 + {6BC5BD0B-15A1-46B6-B561-C37D8DB83403}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {3A8508DC-68CF-404C-88A3-D31CC99B1F76} + EndGlobalSection +EndGlobal diff --git a/ExampleProjects/LogReader/VS_Project/ISLogReaderExample.vcxproj b/ExampleProjects/LogReader/VS_Project/ISLogReaderExample.vcxproj new file mode 100644 index 000000000..4253aa263 --- /dev/null +++ b/ExampleProjects/LogReader/VS_Project/ISLogReaderExample.vcxproj @@ -0,0 +1,218 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 15.0 + {2F1DB5F4-5AF6-4536-AB32-A5441FECD677} + Win32Proj + ISSimpleExample + 10.0.16299.0 + ISLogReaderExample + + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + + + + NotUsing + Level3 + Disabled + true + WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + + + Console + true + %(AdditionalDependencies) + + + + + NotUsing + Level3 + Disabled + true + _DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + + + Console + true + + + + + NotUsing + Level3 + MaxSpeed + true + true + true + WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + + + Console + true + true + true + %(AdditionalDependencies) + + + + + NotUsing + Level3 + MaxSpeed + true + true + true + NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + + + Console + true + true + true + + + + + + diff --git a/ExampleProjects/Logger/VS_Project/ISLoggerExample.vcxproj b/ExampleProjects/Logger/VS_Project/ISLoggerExample.vcxproj index 2ba82efc6..7ee1a11a4 100644 --- a/ExampleProjects/Logger/VS_Project/ISLoggerExample.vcxproj +++ b/ExampleProjects/Logger/VS_Project/ISLoggerExample.vcxproj @@ -23,10 +23,12 @@ + + @@ -58,10 +60,12 @@ + + diff --git a/ExampleProjects/Logger/VS_Project/ISLoggerExample.vcxproj.filters b/ExampleProjects/Logger/VS_Project/ISLoggerExample.vcxproj.filters index ce2fea912..abba2bf03 100644 --- a/ExampleProjects/Logger/VS_Project/ISLoggerExample.vcxproj.filters +++ b/ExampleProjects/Logger/VS_Project/ISLoggerExample.vcxproj.filters @@ -109,6 +109,12 @@ Source Files\SDK + + Source Files\SDK + + + Source Files\SDK + @@ -201,5 +207,11 @@ Source Files\SDK + + Source Files\SDK + + + Source Files\SDK + \ No newline at end of file diff --git a/README.md b/README.md index 1558416e5..b4c813b96 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,5 @@ * Email - support@inertialsense.com - ************************************************ -(c) 2014-2018 Inertial Sense, LLC \ No newline at end of file +(c) 2014-2018 Inertial Sense, Inc. \ No newline at end of file diff --git a/VS_project/InertialSenseLib.vcxproj b/VS_project/InertialSenseLib.vcxproj index 356dd37e4..7693e15e6 100644 --- a/VS_project/InertialSenseLib.vcxproj +++ b/VS_project/InertialSenseLib.vcxproj @@ -19,6 +19,8 @@ + + @@ -58,6 +60,8 @@ + + diff --git a/VS_project/InertialSenseLib.vcxproj.filters b/VS_project/InertialSenseLib.vcxproj.filters index ca9a9929e..9eed27e9c 100644 --- a/VS_project/InertialSenseLib.vcxproj.filters +++ b/VS_project/InertialSenseLib.vcxproj.filters @@ -118,6 +118,12 @@ Source Files + + Source Files + + + Source Files + @@ -228,5 +234,11 @@ Source Files + + Source Files + + + Source Files + \ No newline at end of file diff --git a/docs/html/_data_c_s_v_8cpp.html b/docs/html/_data_c_s_v_8cpp.html index 4df7a97be..f5d42f476 100644 --- a/docs/html/_data_c_s_v_8cpp.html +++ b/docs/html/_data_c_s_v_8cpp.html @@ -23,7 +23,7 @@ Logo

SDK -  Release 1.6.2 +  Release 1.6.4
Communications, logger, and bootloader libraries.
diff --git a/docs/html/_data_c_s_v_8cpp_source.html b/docs/html/_data_c_s_v_8cpp_source.html index 27e2a9137..0706f9744 100644 --- a/docs/html/_data_c_s_v_8cpp_source.html +++ b/docs/html/_data_c_s_v_8cpp_source.html @@ -23,7 +23,7 @@ Logo
SDK -  Release 1.6.2 +  Release 1.6.4
Communications, logger, and bootloader libraries.
@@ -72,7 +72,7 @@
DataCSV.cpp
-Go to the documentation of this file.
1 /*
2 MIT LICENSE
3 
4 Copyright 2014 Inertial Sense, LLC - http://inertialsense.com
5 
6 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files(the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions :
7 
8 The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
9 
10 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
11 */
12 
13 #include <ctime>
14 #include <time.h>
15 #include <string>
16 #include <sstream>
17 #include <sys/types.h>
18 #include <sys/stat.h>
19 #include <iomanip>
20 #include <iostream>
21 #include <fstream>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <stddef.h>
25 #include <inttypes.h>
26 #include <math.h>
27 #include "DataCSV.h"
28 #include "ISLogger.h"
29 #include "data_sets.h"
30 #include "ISDataMappings.h"
31 #include "ISUtilities.h"
32 #include "ISConstants.h"
33 
34 #ifdef USE_IS_INTERNAL
35 # include "../../libs/IS_internal.h"
36 #endif
37 
38 int cDataCSV::WriteHeaderToFile(FILE* pFile, int id)
39 {
40  // Verify file pointer
41  if (pFile == NULL)
42  {
43  return 0;
44  }
45  map_lookup_name_t::const_iterator offsetMap = cISDataMappings::GetMap().find(id);
46  if (offsetMap == cISDataMappings::GetMap().end())
47  {
48  return 0;
49  }
50  string header("_ID_");
51  for (map_name_to_info_t::const_iterator offset = offsetMap->second.begin(); offset != offsetMap->second.end(); offset++)
52  {
53  header += ",";
54  header += offset->first;
55  }
56  header += "\n";
57  fputs(header.c_str(), pFile);
58  return (int)header.length();
59 }
60 
61 
62 int cDataCSV::ReadHeaderFromFile(FILE* pFile, int id, vector<string>& columnHeaders)
63 {
64  (void)id;
65 
66  char line[8192];
67  line[0] = '\0';
68  if (fgets(line, _ARRAY_BYTE_COUNT(line), pFile) == NULL || ferror(pFile) != 0)
69  {
70  return 0;
71  }
72  stringstream stream(line);
73  string columnHeader;
74  columnHeaders.clear();
75  while (stream.good())
76  {
77  getline(stream, columnHeader, ',');
78  while (columnHeader.length() > 0 && (columnHeader[columnHeader.size() - 1] == '\r' || columnHeader[columnHeader.size() - 1] == '\n'))
79  {
80  columnHeader.resize(columnHeader.size() - 1);
81  }
82  if (columnHeader.length() == 0)
83  {
84  columnHeader = "UNKNOWN";
85  }
86  columnHeaders.push_back(columnHeader);
87  }
88  return (int)strnlen(line, _ARRAY_BYTE_COUNT(line));
89 }
90 
91 int cDataCSV::WriteDataToFile(uint64_t orderId, FILE* pFile, const p_data_hdr_t& dataHdr, const uint8_t* dataBuf)
92 {
93  // Verify file pointer
94  if (pFile == NULL)
95  {
96  return 0;
97  }
98  map_lookup_name_t::const_iterator offsetMap = cISDataMappings::GetMap().find(dataHdr.id);
99  if (offsetMap == cISDataMappings::GetMap().end())
100  {
101  return 0;
102  }
103  string s;
104  if (!DataToStringCSV(dataHdr, dataBuf, s))
105  {
106  return 0;
107  }
108  char tmp[64];
109  SNPRINTF(tmp, 64, "%llu", (long long unsigned int)orderId);
110  fputs(tmp, pFile);
111  fputc(',', pFile);
112  fputs(s.c_str(), pFile);
113 
114  // return the data string length plus comma plus order id string
115  return (int)s.length() + 1 + (int)strnlen(tmp, sizeof(tmp));
116 }
117 
118 bool cDataCSV::StringCSVToData(string& s, p_data_hdr_t& hdr, uint8_t* buf, uint32_t bufSize, const vector<string>& columnHeaders)
119 {
120  map_lookup_name_t::const_iterator offsetMap = cISDataMappings::GetMap().find(hdr.id);
121  if (offsetMap == cISDataMappings::GetMap().end() || hdr.offset != 0 || hdr.size == 0 || bufSize < hdr.size)
122  {
123  return false;
124  }
125  while (s.length() > 0 && (s[s.size() - 1] == '\r' || s[s.size() - 1] == '\n'))
126  {
127  s.resize(s.size() - 1);
128  }
129  // for parsing logic, last comma will allow last field to parse properly
130  s += ",";
131  string columnData;
132  string::const_iterator start = s.begin();
133  uint32_t index = 0;
134  hdr.offset = 0;
135  hdr.size = cISDataMappings::GetSize(hdr.id);
136  map_name_to_info_t::const_iterator offset;
137  bool inQuotes = false;
138  uint32_t foundQuotes = 0;
139  memset(buf, 0, hdr.size);
140  for (string::const_iterator i = start; i < s.end() && index < columnHeaders.size(); i++)
141  {
142  if (*i == ',' && !inQuotes)
143  {
144  // end field
145  columnData = string(start + foundQuotes, i - foundQuotes);
146  start = i + 1;
147  offset = offsetMap->second.find(columnHeaders[index++]);
148  if (offset != offsetMap->second.end() && !cISDataMappings::StringToData(columnData.c_str(), (int)columnData.length(), &hdr, buf, offset->second))
149  {
150  return false;
151  }
152  foundQuotes = false;
153  }
154  else if (*i == '"')
155  {
156  inQuotes = !inQuotes;
157  foundQuotes |= (uint32_t)inQuotes;
158  }
159  }
160  return true;
161 }
162 
163 
164 bool cDataCSV::DataToStringCSV(const p_data_hdr_t& hdr, const uint8_t* buf, string& csv)
165 {
166  csv.clear();
167  string columnData;
168  map_lookup_name_t::const_iterator offsetMap = cISDataMappings::GetMap().find(hdr.id);
169  if (offsetMap == cISDataMappings::GetMap().end())
170  {
171  return false;
172  }
174  const uint8_t* bufPtr = buf;
175  uint8_t tmpBuffer[MAX_DATASET_SIZE];
176  uint32_t size = cISDataMappings::GetSize(hdr.id);
177  if (size > hdr.size)
178  {
179  // copy into temp buffer, zeroing out bytes that are not part of this packet
180  memset(tmpBuffer, 0, hdr.offset);
181  memcpy(tmpBuffer + hdr.offset, buf, hdr.size);
182  uint32_t dataEnd = hdr.offset + hdr.size;
183  memset(tmpBuffer + dataEnd, 0, size - dataEnd);
184  bufPtr = tmpBuffer;
185  }
186 
187  // copy header as we are now storing an entire struct, even if we got a partial hdr and buf
188  p_data_hdr_t hdrCopy = hdr;
189  hdrCopy.offset = 0;
190  hdrCopy.size = size;
191 
192  for (map_name_to_info_t::const_iterator offset = offsetMap->second.begin(); offset != offsetMap->second.end(); offset++)
193  {
194  cISDataMappings::DataToString(offset->second, &hdrCopy, bufPtr, tmp);
195  if (csv.length() != 0)
196  {
197  csv += ",";
198  }
199  csv += tmp;
200  }
201  csv += "\n";
202  return true;
203 }
204 
static uint32_t GetSize(uint32_t dataId)
+Go to the documentation of this file.
1 /*
2 MIT LICENSE
3 
4 Copyright 2014 Inertial Sense, LLC - http://inertialsense.com
5 
6 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files(the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions :
7 
8 The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
9 
10 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
11 */
12 
13 #include <ctime>
14 #include <time.h>
15 #include <string>
16 #include <sstream>
17 #include <sys/types.h>
18 #include <sys/stat.h>
19 #include <iomanip>
20 #include <iostream>
21 #include <fstream>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <stddef.h>
25 #include <inttypes.h>
26 #include <math.h>
27 #include "DataCSV.h"
28 #include "ISLogger.h"
29 #include "data_sets.h"
30 #include "ISDataMappings.h"
31 #include "ISUtilities.h"
32 #include "ISConstants.h"
33 
34 #ifdef USE_IS_INTERNAL
35 # include "../../libs/IS_internal.h"
36 #endif
37 
38 int cDataCSV::WriteHeaderToFile(FILE* pFile, int id)
39 {
40  // Verify file pointer
41  if (pFile == NULL)
42  {
43  return 0;
44  }
45  map_lookup_name_t::const_iterator offsetMap = cISDataMappings::GetMap().find(id);
46  if (offsetMap == cISDataMappings::GetMap().end())
47  {
48  return 0;
49  }
50  string header("_ID_");
51  for (map_name_to_info_t::const_iterator offset = offsetMap->second.begin(); offset != offsetMap->second.end(); offset++)
52  {
53  header += ",";
54  header += offset->first;
55  }
56  header += "\n";
57  fputs(header.c_str(), pFile);
58  return (int)header.length();
59 }
60 
61 
62 int cDataCSV::ReadHeaderFromFile(FILE* pFile, int id, vector<string>& columnHeaders)
63 {
64  (void)id;
65 
66  char line[8192];
67  line[0] = '\0';
68  if (fgets(line, _ARRAY_BYTE_COUNT(line), pFile) == NULL || ferror(pFile) != 0)
69  {
70  return 0;
71  }
72  stringstream stream(line);
73  string columnHeader;
74  columnHeaders.clear();
75  while (stream.good())
76  {
77  getline(stream, columnHeader, ',');
78  while (columnHeader.length() > 0 && (columnHeader[columnHeader.size() - 1] == '\r' || columnHeader[columnHeader.size() - 1] == '\n'))
79  {
80  columnHeader.resize(columnHeader.size() - 1);
81  }
82  if (columnHeader.length() == 0)
83  {
84  columnHeader = "UNKNOWN";
85  }
86  columnHeaders.push_back(columnHeader);
87  }
88  return (int)strnlen(line, _ARRAY_BYTE_COUNT(line));
89 }
90 
91 int cDataCSV::WriteDataToFile(uint64_t orderId, FILE* pFile, const p_data_hdr_t& dataHdr, const uint8_t* dataBuf)
92 {
93  // Verify file pointer
94  if (pFile == NULL)
95  {
96  return 0;
97  }
98  map_lookup_name_t::const_iterator offsetMap = cISDataMappings::GetMap().find(dataHdr.id);
99  if (offsetMap == cISDataMappings::GetMap().end())
100  {
101  return 0;
102  }
103  string s;
104  if (!DataToStringCSV(dataHdr, dataBuf, s))
105  {
106  return 0;
107  }
108  char tmp[64];
109  SNPRINTF(tmp, 64, "%llu", (long long unsigned int)orderId);
110  fputs(tmp, pFile);
111  fputc(',', pFile);
112  fputs(s.c_str(), pFile);
113 
114  // return the data string length plus comma plus order id string
115  return (int)s.length() + 1 + (int)strnlen(tmp, sizeof(tmp));
116 }
117 
118 bool cDataCSV::StringCSVToData(string& s, p_data_hdr_t& hdr, uint8_t* buf, uint32_t bufSize, const vector<string>& columnHeaders)
119 {
120  map_lookup_name_t::const_iterator offsetMap = cISDataMappings::GetMap().find(hdr.id);
121  if (offsetMap == cISDataMappings::GetMap().end() || hdr.offset != 0 || hdr.size == 0 || bufSize < hdr.size)
122  {
123  return false;
124  }
125  while (s.length() > 0 && (s[s.size() - 1] == '\r' || s[s.size() - 1] == '\n'))
126  {
127  s.resize(s.size() - 1);
128  }
129  // for parsing logic, last comma will allow last field to parse properly
130  s += ",";
131  string columnData;
132  string::const_iterator start = s.begin();
133  uint32_t index = 0;
134  hdr.offset = 0;
135  hdr.size = cISDataMappings::GetSize(hdr.id);
136  map_name_to_info_t::const_iterator offset;
137  bool inQuotes = false;
138  uint32_t foundQuotes = 0;
139  memset(buf, 0, hdr.size);
140  for (string::const_iterator i = start; i < s.end() && index < columnHeaders.size(); i++)
141  {
142  if (*i == ',' && !inQuotes)
143  {
144  // end field
145  columnData = string(start + foundQuotes, i - foundQuotes);
146  start = i + 1;
147  offset = offsetMap->second.find(columnHeaders[index++]);
148  if (offset != offsetMap->second.end() && !cISDataMappings::StringToData(columnData.c_str(), (int)columnData.length(), &hdr, buf, offset->second))
149  {
150  return false;
151  }
152  foundQuotes = false;
153  }
154  else if (*i == '"')
155  {
156  inQuotes = !inQuotes;
157  foundQuotes |= (uint32_t)inQuotes;
158  }
159  }
160  return true;
161 }
162 
163 
164 bool cDataCSV::DataToStringCSV(const p_data_hdr_t& hdr, const uint8_t* buf, string& csv)
165 {
166  csv.clear();
167  string columnData;
168  map_lookup_name_t::const_iterator offsetMap = cISDataMappings::GetMap().find(hdr.id);
169  if (offsetMap == cISDataMappings::GetMap().end())
170  {
171  return false;
172  }
174  const uint8_t* bufPtr = buf;
175  uint8_t tmpBuffer[MAX_DATASET_SIZE];
176  uint32_t size = cISDataMappings::GetSize(hdr.id);
177  if (size > hdr.size)
178  {
179  // copy into temp buffer, zeroing out bytes that are not part of this packet
180  memset(tmpBuffer, 0, hdr.offset);
181  memcpy(tmpBuffer + hdr.offset, buf, hdr.size);
182  uint32_t dataEnd = hdr.offset + hdr.size;
183  memset(tmpBuffer + dataEnd, 0, size - dataEnd);
184  bufPtr = tmpBuffer;
185  }
186 
187  // copy header as we are now storing an entire struct, even if we got a partial hdr and buf
188  p_data_hdr_t hdrCopy = hdr;
189  hdrCopy.offset = 0;
190  hdrCopy.size = size;
191 
192  for (map_name_to_info_t::const_iterator offset = offsetMap->second.begin(); offset != offsetMap->second.end(); offset++)
193  {
194  cISDataMappings::DataToString(offset->second, &hdrCopy, bufPtr, tmp);
195  if (csv.length() != 0)
196  {
197  csv += ",";
198  }
199  csv += tmp;
200  }
201  csv += "\n";
202  return true;
203 }
204 
static uint32_t GetSize(uint32_t dataId)
#define IS_DATA_MAPPING_MAX_STRING_LENGTH
int WriteHeaderToFile(FILE *pFile, int id)
Definition: DataCSV.cpp:38
@@ -82,17 +82,17 @@
bool DataToStringCSV(const p_data_hdr_t &hdr, const uint8_t *buf, string &csv)
Definition: DataCSV.cpp:164
-
#define _ARRAY_BYTE_COUNT(a)
Definition: ISConstants.h:293
+
#define _ARRAY_BYTE_COUNT(a)
Definition: ISConstants.h:290
int ReadHeaderFromFile(FILE *pFile, int id, vector< string > &columnHeaders)
Definition: DataCSV.cpp:62
int WriteDataToFile(uint64_t orderId, FILE *pFile, const p_data_hdr_t &dataHdr, const uint8_t *dataBuf)
Definition: DataCSV.cpp:91
+
static bool StringToData(const char *stringBuffer, int stringLength, const p_data_hdr_t *hdr, uint8_t *dataBuffer, const data_info_t &info, int radix=10, bool json=false)
#define MAX_DATASET_SIZE
Definition: ISComm.h:180
+
static bool DataToString(const data_info_t &info, const p_data_hdr_t *hdr, const uint8_t *dataBuffer, data_mapping_string_t stringBuffer, bool json=false)
bool StringCSVToData(string &s, p_data_hdr_t &hdr, uint8_t *buf, uint32_t bufSize, const vector< string > &columnHeaders)
Definition: DataCSV.cpp:118
-
#define SNPRINTF
Definition: ISConstants.h:171
-
static bool DataToString(const data_info_t &info, const p_data_hdr_t *hdr, const uint8_t *dataBuffer, data_mapping_string_t stringBuffer)
-
static bool StringToData(const char *stringBuffer, int stringLength, const p_data_hdr_t *hdr, uint8_t *dataBuffer, const data_info_t &info, int radix=10)
-
static const map_lookup_name_t & GetMap()
+
#define SNPRINTF
Definition: ISConstants.h:142
+
static const map_lookup_name_t & GetMap()
uint32_t offset
Definition: ISComm.h:487
diff --git a/docs/html/_data_c_s_v_8h.html b/docs/html/_data_c_s_v_8h.html index d23119244..189ca80f2 100644 --- a/docs/html/_data_c_s_v_8h.html +++ b/docs/html/_data_c_s_v_8h.html @@ -23,7 +23,7 @@ Logo
SDK -  Release 1.6.2 +  Release 1.6.4
Communications, logger, and bootloader libraries.
diff --git a/docs/html/_data_c_s_v_8h_source.html b/docs/html/_data_c_s_v_8h_source.html index b56ba8d6f..d0715eb2c 100644 --- a/docs/html/_data_c_s_v_8h_source.html +++ b/docs/html/_data_c_s_v_8h_source.html @@ -23,7 +23,7 @@ Logo
SDK -  Release 1.6.2 +  Release 1.6.4
Communications, logger, and bootloader libraries.
diff --git a/docs/html/_data_chunk_8cpp.html b/docs/html/_data_chunk_8cpp.html index 40a2728d1..28cf34950 100644 --- a/docs/html/_data_chunk_8cpp.html +++ b/docs/html/_data_chunk_8cpp.html @@ -23,7 +23,7 @@ Logo
SDK -  Release 1.6.2 +  Release 1.6.4
Communications, logger, and bootloader libraries.
diff --git a/docs/html/_data_chunk_8cpp_source.html b/docs/html/_data_chunk_8cpp_source.html index 4c2a0fe1a..bc7788679 100644 --- a/docs/html/_data_chunk_8cpp_source.html +++ b/docs/html/_data_chunk_8cpp_source.html @@ -23,7 +23,7 @@ Logo
SDK -  Release 1.6.2 +  Release 1.6.4
Communications, logger, and bootloader libraries.
diff --git a/docs/html/_data_chunk_8h.html b/docs/html/_data_chunk_8h.html index d9b6cdf68..3fd485722 100644 --- a/docs/html/_data_chunk_8h.html +++ b/docs/html/_data_chunk_8h.html @@ -23,7 +23,7 @@ Logo
SDK -  Release 1.6.2 +  Release 1.6.4
Communications, logger, and bootloader libraries.
diff --git a/docs/html/_data_chunk_8h_source.html b/docs/html/_data_chunk_8h_source.html index 5bb4b314e..3d6252c65 100644 --- a/docs/html/_data_chunk_8h_source.html +++ b/docs/html/_data_chunk_8h_source.html @@ -23,7 +23,7 @@ Logo
SDK -  Release 1.6.2 +  Release 1.6.4
Communications, logger, and bootloader libraries.
@@ -76,13 +76,13 @@
uint32_t dataSize
Chunk data length in bytes.
Definition: DataChunk.h:42
uint32_t marker
Chunk marker (0xFC05EA32)
Definition: DataChunk.h:37
-
#define POP_PACK
Definition: ISConstants.h:224
+
#define POP_PACK
Definition: ISConstants.h:221
#define DID_COUNT
Definition: data_sets.h:117
void logStats(const char *format,...)
Chunk Header.
Definition: DataChunk.cpp:260
uint16_t classification
Chunk classification.
Definition: DataChunk.h:39
uint32_t GetByteCountAvailableToRead()
Definition: DataChunk.h:79
-
#define PUSH_PACK_1
Definition: ISConstants.h:221
+
#define PUSH_PACK_1
Definition: ISConstants.h:218
uint32_t reserved
Unused.
Definition: DataChunk.h:47
uint32_t devSerialNum
Device serial number.
Definition: DataChunk.h:45
diff --git a/docs/html/_data_chunk_sorted_8cpp.html b/docs/html/_data_chunk_sorted_8cpp.html index 3bd2fe113..d6aa31e99 100644 --- a/docs/html/_data_chunk_sorted_8cpp.html +++ b/docs/html/_data_chunk_sorted_8cpp.html @@ -23,7 +23,7 @@ Logo
SDK -  Release 1.6.2 +  Release 1.6.4
Communications, logger, and bootloader libraries.
diff --git a/docs/html/_data_chunk_sorted_8cpp_source.html b/docs/html/_data_chunk_sorted_8cpp_source.html index 78d510c6e..3faebbf18 100644 --- a/docs/html/_data_chunk_sorted_8cpp_source.html +++ b/docs/html/_data_chunk_sorted_8cpp_source.html @@ -23,7 +23,7 @@ Logo
SDK -  Release 1.6.2 +  Release 1.6.4
Communications, logger, and bootloader libraries.
diff --git a/docs/html/_data_chunk_sorted_8h.html b/docs/html/_data_chunk_sorted_8h.html index 7fb549794..e2170aa13 100644 --- a/docs/html/_data_chunk_sorted_8h.html +++ b/docs/html/_data_chunk_sorted_8h.html @@ -23,7 +23,7 @@ Logo
SDK -  Release 1.6.2 +  Release 1.6.4
Communications, logger, and bootloader libraries.
diff --git a/docs/html/_data_chunk_sorted_8h_source.html b/docs/html/_data_chunk_sorted_8h_source.html index 10d18ecf5..a61c4574b 100644 --- a/docs/html/_data_chunk_sorted_8h_source.html +++ b/docs/html/_data_chunk_sorted_8h_source.html @@ -23,7 +23,7 @@ Logo
SDK -  Release 1.6.2 +  Release 1.6.4
Communications, logger, and bootloader libraries.
@@ -75,13 +75,13 @@ Go to the documentation of this file.
1 /*
2 MIT LICENSE
3 
4 Copyright 2014 Inertial Sense, LLC - http://inertialsense.com
5 
6 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files(the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions :
7 
8 The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
9 
10 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
11 */
12 
13 #ifndef DATA_CHUNK_SORTED_H
14 #define DATA_CHUNK_SORTED_H
15 
16 #include <stdint.h>
17 #include <vector>
18 
19 #include "com_manager.h"
20 #include "DataChunk.h"
21 
22 #define LOG_DEBUG_WRITE 0
23 #define LOG_DEBUG_READ 0
24 
26 
28 typedef struct
29 {
31  uint32_t dataSerNum;
32 
34  uint8_t buf[MAX_P_DATA_BODY_SIZE];
35 } p_cnk_data_t;
36 
37 // sub-header for sorted data chunks
38 typedef struct
39 {
41 
42  // Number of sorted data elements
43  uint32_t dCount;
45 
47 
49 {
50 public:
51  cSortedDataChunk(uint32_t maxSize = MAX_CHUNK_SIZE, const char* name = "EMPT");
52  void Clear() OVERRIDE;
53 
54  int32_t WriteAdditionalChunkHeader(FILE* pFile) OVERRIDE;
55  int32_t ReadAdditionalChunkHeader(FILE* pFile) OVERRIDE;
56  int32_t GetHeaderSize() OVERRIDE;
57 
59 };
60 
61 
62 #endif // DATA_CHUNK_SORTED_H
int32_t GetHeaderSize() OVERRIDE
int32_t ReadAdditionalChunkHeader(FILE *pFile) OVERRIDE
-
#define POP_PACK
Definition: ISConstants.h:224
+
#define POP_PACK
Definition: ISConstants.h:221
-
#define PUSH_PACK_1
Definition: ISConstants.h:221
+
#define PUSH_PACK_1
Definition: ISConstants.h:218
p_data_hdr_t dHdr
-
#define OVERRIDE
Definition: ISConstants.h:377
+
#define OVERRIDE
Definition: ISConstants.h:374
sChunkSubHeader m_subHdr
cSortedDataChunk(uint32_t maxSize=MAX_CHUNK_SIZE, const char *name="EMPT")
diff --git a/docs/html/_data_j_s_o_n_8cpp.html b/docs/html/_data_j_s_o_n_8cpp.html new file mode 100644 index 000000000..1cb40852b --- /dev/null +++ b/docs/html/_data_j_s_o_n_8cpp.html @@ -0,0 +1,105 @@ + + + + + + + +SDK: src/DataJSON.cpp File Reference + + + + + + + + + +
+
+ + + + + + + +
+
SDK +  Release 1.6.4 +
+
Communications, logger, and bootloader libraries.
+
+
+ + + + + + + + +
+
+ + +
+ +
+ + +
+
+
+
DataJSON.cpp File Reference
+
+
+
#include <ctime>
+#include <time.h>
+#include <string>
+#include <sstream>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <iomanip>
+#include <iostream>
+#include <fstream>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <inttypes.h>
+#include <math.h>
+#include "DataJSON.h"
+#include "ISLogger.h"
+#include "data_sets.h"
+#include "ISDataMappings.h"
+#include "ISUtilities.h"
+#include "ISConstants.h"
+
+

Go to the source code of this file.

+
+ + + + diff --git a/docs/html/_data_j_s_o_n_8cpp_source.html b/docs/html/_data_j_s_o_n_8cpp_source.html new file mode 100644 index 000000000..55495c537 --- /dev/null +++ b/docs/html/_data_j_s_o_n_8cpp_source.html @@ -0,0 +1,104 @@ + + + + + + + +SDK: src/DataJSON.cpp Source File + + + + + + + + + +
+
+ + + + + + + +
+
SDK +  Release 1.6.4 +
+
Communications, logger, and bootloader libraries.
+
+
+ + + + + + + + +
+
+ + +
+ +
+ + +
+
+
+
DataJSON.cpp
+
+
+Go to the documentation of this file.
1 /*
2 MIT LICENSE
3 
4 Copyright 2014 Inertial Sense, LLC - http://inertialsense.com
5 
6 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files(the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions :
7 
8 The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
9 
10 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
11 */
12 
13 #include <ctime>
14 #include <time.h>
15 #include <string>
16 #include <sstream>
17 #include <sys/types.h>
18 #include <sys/stat.h>
19 #include <iomanip>
20 #include <iostream>
21 #include <fstream>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <stddef.h>
25 #include <inttypes.h>
26 #include <math.h>
27 #include "DataJSON.h"
28 #include "ISLogger.h"
29 #include "data_sets.h"
30 #include "ISDataMappings.h"
31 #include "ISUtilities.h"
32 #include "ISConstants.h"
33 
34 #ifdef USE_IS_INTERNAL
35 # include "../../libs/IS_internal.h"
36 #endif
37 
38 int cDataJSON::WriteDataToFile(FILE* pFile, const p_data_hdr_t& dataHdr, const uint8_t* dataBuf, const char* prefix)
39 {
40  // Verify file pointer
41  if (pFile == NULL)
42  {
43  return 0;
44  }
45  map_lookup_name_t::const_iterator offsetMap = cISDataMappings::GetMap().find(dataHdr.id);
46  if (offsetMap == cISDataMappings::GetMap().end())
47  {
48  return 0;
49  }
50  string s;
51 
52  if (!DataToStringJSON(dataHdr, dataBuf, s))
53  {
54  return 0;
55  }
56  if (prefix != NULLPTR)
57  {
58  fputs(prefix, pFile);
59  }
60  fputs(s.c_str(), pFile);
61  return (int)s.length();
62 }
63 
64 bool cDataJSON::StringJSONToData(string& s, p_data_hdr_t& hdr, uint8_t* buf, uint32_t bufSize)
65 {
66  (void)s;
67  (void)buf;
68  (void)bufSize;
69 
70  size_t pos = s.find("\"id\":");
71  if (pos == string::npos)
72  {
73  return false;
74  }
75  uint32_t id = strtoul(s.c_str() + pos + 5, NULLPTR, 10);
76  hdr.id = id;
77  map_lookup_name_t::const_iterator offsetMap = cISDataMappings::GetMap().find(hdr.id);
78  if (offsetMap == cISDataMappings::GetMap().end())
79  {
80  return false;
81  }
82  hdr.size = cISDataMappings::GetSize(hdr.id);
83  char c;
84  char pc = 0;
85  map_name_to_info_t::const_iterator offset;
86  string fieldName;
87  size_t fieldStart = 0;
88  bool inName = true;
89  bool inQuote = false;
90  for (size_t i = 0; i < s.size(); i++)
91  {
92  c = s[i];
93  if (c == '"' && pc != '\\')
94  {
95  if (inQuote = !inQuote)
96  {
97  fieldStart = i + 1;
98  pc = c;
99  continue;
100  }
101  }
102 
103  if (inName)
104  {
105  if (c == ':')
106  {
107  fieldStart = i + 1;
108  inName = inQuote = false;
109  pc = c;
110  continue;
111  }
112  else if (inQuote)
113  {
114  fieldName.append(1, c);
115  }
116  }
117  else if ((c == '}' || c == '"' || (!inQuote && c == ',')) && pc != '\\')
118  {
119  if (fieldStart != 0)
120  {
121  offset = offsetMap->second.find(fieldName);
122  string json = s.substr(fieldStart, i - fieldStart);
123  if (offset != offsetMap->second.end() && !cISDataMappings::StringToData(json.c_str(), (int)json.size(), &hdr, buf, offset->second, 10, true))
124  {
125  return false;
126  }
127  }
128  fieldName.clear();
129  fieldStart = 0;
130  inName = true;
131  }
132  pc = c;
133  }
134 
135  return true;
136 }
137 
138 
139 bool cDataJSON::DataToStringJSON(const p_data_hdr_t& hdr, const uint8_t* buf, string& json)
140 {
141  json.clear();
142  map_lookup_name_t::const_iterator offsetMap = cISDataMappings::GetMap().find(hdr.id);
143  if (offsetMap == cISDataMappings::GetMap().end())
144  {
145  return false;
146  }
148  const uint8_t* bufPtr = buf;
149  uint8_t tmpBuffer[MAX_DATASET_SIZE];
150  uint32_t size = cISDataMappings::GetSize(hdr.id);
151  if (size > hdr.size)
152  {
153  // copy into temp buffer, zeroing out bytes that are not part of this packet
154  memset(tmpBuffer, 0, hdr.offset);
155  memcpy(tmpBuffer + hdr.offset, buf, hdr.size);
156  uint32_t dataEnd = hdr.offset + hdr.size;
157  memset(tmpBuffer + dataEnd, 0, size - dataEnd);
158  bufPtr = tmpBuffer;
159  }
160 
161  // copy header as we are now storing an entire struct, even if we got a partial hdr and buf
162  p_data_hdr_t hdrCopy = hdr;
163  hdrCopy.offset = 0;
164  hdrCopy.size = size;
165 
166  SNPRINTF(tmp, sizeof(tmp), "{\"id\":%d", (int)hdr.id);
167  json.append(tmp);
168  for (map_name_to_info_t::const_iterator offset = offsetMap->second.begin(); offset != offsetMap->second.end(); offset++)
169  {
170  cISDataMappings::DataToString(offset->second, &hdrCopy, bufPtr, tmp, true);
171  json.append(1, ',');
172  json.append(1, '"');
173  json.append(offset->second.name);
174  json.append(1, '"');
175  json.append(1, ':');
176  json.append(tmp);
177  }
178  json.append(1, '}');
179  return true;
180 }
static uint32_t GetSize(uint32_t dataId)
+
bool StringJSONToData(string &s, p_data_hdr_t &hdr, uint8_t *buf, uint32_t bufSize)
Definition: DataJSON.cpp:64
+
#define IS_DATA_MAPPING_MAX_STRING_LENGTH
+ +
uint32_t id
Definition: ISComm.h:481
+
uint32_t size
Definition: ISComm.h:484
+
bool DataToStringJSON(const p_data_hdr_t &hdr, const uint8_t *buf, string &json)
Definition: DataJSON.cpp:139
+
#define NULLPTR
Definition: ISConstants.h:377
+ + + + +
static bool StringToData(const char *stringBuffer, int stringLength, const p_data_hdr_t *hdr, uint8_t *dataBuffer, const data_info_t &info, int radix=10, bool json=false)
+
#define MAX_DATASET_SIZE
Definition: ISComm.h:180
+
int WriteDataToFile(FILE *pFile, const p_data_hdr_t &dataHdr, const uint8_t *dataBuf, const char *prefix)
Definition: DataJSON.cpp:38
+ +
static bool DataToString(const data_info_t &info, const p_data_hdr_t *hdr, const uint8_t *dataBuffer, data_mapping_string_t stringBuffer, bool json=false)
+
#define SNPRINTF
Definition: ISConstants.h:142
+
static const map_lookup_name_t & GetMap()
+
uint32_t offset
Definition: ISComm.h:487
+ +
+ + + + diff --git a/docs/html/_data_j_s_o_n_8h.html b/docs/html/_data_j_s_o_n_8h.html new file mode 100644 index 000000000..291ac779d --- /dev/null +++ b/docs/html/_data_j_s_o_n_8h.html @@ -0,0 +1,97 @@ + + + + + + + +SDK: src/DataJSON.h File Reference + + + + + + + + + +
+
+ + + + + + + +
+
SDK +  Release 1.6.4 +
+
Communications, logger, and bootloader libraries.
+
+
+ + + + + + + + +
+
+ + +
+ +
+ + +
+
+ +
+
DataJSON.h File Reference
+
+
+
#include <string>
+#include <map>
+#include <regex>
+#include "com_manager.h"
+
+

Go to the source code of this file.

+ + + + +

+Classes

class  cDataJSON
 
+
+ + + + diff --git a/docs/html/_data_j_s_o_n_8h_source.html b/docs/html/_data_j_s_o_n_8h_source.html new file mode 100644 index 000000000..7b5658b00 --- /dev/null +++ b/docs/html/_data_j_s_o_n_8h_source.html @@ -0,0 +1,87 @@ + + + + + + + +SDK: src/DataJSON.h Source File + + + + + + + + + +
+
+ + + + + + + +
+
SDK +  Release 1.6.4 +
+
Communications, logger, and bootloader libraries.
+
+
+ + + + + + + + +
+
+ + +
+ +
+ + +
+
+
+
DataJSON.h
+
+
+Go to the documentation of this file.
1 /*
2 MIT LICENSE
3 
4 Copyright 2014 Inertial Sense, LLC - http://inertialsense.com
5 
6 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files(the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions :
7 
8 The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
9 
10 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
11 */
12 
13 #ifndef DATA_JSON_H
14 #define DATA_JSON_H
15 
16 #include <string>
17 #include <map>
18 #include <regex>
19 
20 #include "com_manager.h"
21 
22 using namespace std;
23 
24 static inline bool IS_JSON_ESCAPE_CHAR(char c)
25 {
26  switch (c)
27  {
28  case '"':
29  case '\\':
30  case '/':
31  case '\b':
32  case '\f':
33  case '\n':
34  case '\r':
35  case '\t':
36  return true;
37  }
38  return false;
39 }
40 
41 class cDataJSON
42 {
43 public:
44  /*
45  * Write data to json file
46  * pFile the file to write to
47  * dataHdr data header
48  * dataBuf data buffer
49  * prefix prefix if data is written
50  */
51  int WriteDataToFile(FILE* pFile, const p_data_hdr_t& dataHdr, const uint8_t* dataBuf, const char* prefix);
52 
61  bool StringJSONToData(string& s, p_data_hdr_t& hdr, uint8_t* buf, uint32_t bufSize);
62 
69  bool DataToStringJSON(const p_data_hdr_t& hdr, const uint8_t* buf, string& json);
70 };
71 
72 #endif // DATA_JSON_H
+ + + +
+ + + + diff --git a/docs/html/_data_k_m_l_8cpp.html b/docs/html/_data_k_m_l_8cpp.html index 75c04ef01..a3186a8fb 100644 --- a/docs/html/_data_k_m_l_8cpp.html +++ b/docs/html/_data_k_m_l_8cpp.html @@ -23,7 +23,7 @@ Logo
SDK -  Release 1.6.2 +  Release 1.6.4
Communications, logger, and bootloader libraries.
diff --git a/docs/html/_data_k_m_l_8cpp_source.html b/docs/html/_data_k_m_l_8cpp_source.html index 867e913e5..d0244e8de 100644 --- a/docs/html/_data_k_m_l_8cpp_source.html +++ b/docs/html/_data_k_m_l_8cpp_source.html @@ -23,7 +23,7 @@ Logo
SDK -  Release 1.6.2 +  Release 1.6.4
Communications, logger, and bootloader libraries.
@@ -72,44 +72,43 @@
DataKML.cpp
-Go to the documentation of this file.
1 /*
2 MIT LICENSE
3 
4 Copyright 2014 Inertial Sense, LLC - http://inertialsense.com
5 
6 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files(the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions :
7 
8 The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
9 
10 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
11 */
12 
13 #include <ctime>
14 #include <time.h>
15 #include <string>
16 #include <sstream>
17 #include <sys/types.h>
18 #include <sys/stat.h>
19 #include <iomanip>
20 #include <iostream>
21 #include <fstream>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <stddef.h>
25 
26 #include "tinyxml.h"
27 #include "DataKML.h"
28 #include "ISLogger.h"
29 #include "ISPose.h"
30 #include "data_sets.h"
31 #include "ISUtilities.h"
32 #include "ISConstants.h"
33 
34 #ifdef USE_IS_INTERNAL
35 # include "../../libs/IS_internal.h"
36 #endif
37 
38 
40 {
41 // def[0].init( "devInfo", "Device information" );
42 // def[5].init( "ins2", "Inertial navigation data with quaternion attitude" );
43 }
44 
45 string cDataKML::GetDatasetName(int kid)
46 {
47  switch (kid)
48  {
49  default: return "";
50  case KID_INS: return "ins";
51  case KID_REF: return "ref";
52  case KID_GPS: return "gps";
53  case KID_GPS1: return "gps1";
54  case KID_GPS2: return "gps2";
55  case KID_RTK: return "rtk";
56  }
57 }
58 
59 
60 #include <inttypes.h>
61 #include <math.h>
62 #include <stdio.h>
63 #include <time.h>
64 
65 int cDataKML::WriteDataToFile(vector<sKmlLogData>& list, const p_data_hdr_t* dataHdr, const uint8_t* dataBuf)
66 {
67  uDatasets& d = (uDatasets&)(*dataBuf);
68  Euler theta;
69  sKmlLogData data;
70 
71 #ifdef USE_IS_INTERNAL
72 // uInternalDatasets &i = (uInternalDatasets&)(*dataBuf);
73 #endif
74 
75  // Write date to file
76  switch (dataHdr->id)
77  {
78  default: // Unidentified dataset
79  return 0;
80 
81  case DID_INS_1:
82  data = sKmlLogData(d.ins1.timeOfWeek, d.ins1.lla, d.ins1.theta);
83  break;
84  case DID_INS_2:
85  quat2euler(d.ins2.qn2b, theta);
86  data = sKmlLogData(d.ins2.timeOfWeek, d.ins2.lla, theta);
87  break;
88  case DID_INS_3:
89  quat2euler(d.ins3.qn2b, theta);
90  data = sKmlLogData(d.ins3.timeOfWeek, d.ins3.lla, theta);
91  break;
92  case DID_GPS_NAV:
93  case DID_GPS1_NAV:
94  case DID_GPS2_NAV:
96  break;
97  case DID_GPS_RTK_NAV:
99  break;
100  }
101 
102  list.push_back(data);
103 
104  return 0;
105 }
106 
107 
-
Vector3 Euler
Definition: ISConstants.h:733
+Go to the documentation of this file.
1 /*
2 MIT LICENSE
3 
4 Copyright 2014 Inertial Sense, LLC - http://inertialsense.com
5 
6 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files(the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions :
7 
8 The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
9 
10 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
11 */
12 
13 #include <ctime>
14 #include <time.h>
15 #include <string>
16 #include <sstream>
17 #include <sys/types.h>
18 #include <sys/stat.h>
19 #include <iomanip>
20 #include <iostream>
21 #include <fstream>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <stddef.h>
25 
26 #include "tinyxml.h"
27 #include "DataKML.h"
28 #include "ISLogger.h"
29 #include "ISPose.h"
30 #include "data_sets.h"
31 #include "ISUtilities.h"
32 #include "ISConstants.h"
33 
34 #ifdef USE_IS_INTERNAL
35 # include "../../libs/IS_internal.h"
36 #endif
37 
38 
40 {
41 // def[0].init( "devInfo", "Device information" );
42 // def[5].init( "ins2", "Inertial navigation data with quaternion attitude" );
43 }
44 
45 string cDataKML::GetDatasetName(int kid)
46 {
47  switch (kid)
48  {
49  default: return "";
50  case KID_INS: return "ins";
51  case KID_REF: return "ref";
52  case KID_GPS: return "gps";
53  case KID_GPS1: return "gps1";
54  case KID_GPS2: return "gps2";
55  case KID_RTK: return "rtk";
56  }
57 }
58 
59 
60 #include <inttypes.h>
61 #include <math.h>
62 #include <stdio.h>
63 #include <time.h>
64 
65 int cDataKML::WriteDataToFile(vector<sKmlLogData>& list, const p_data_hdr_t* dataHdr, const uint8_t* dataBuf)
66 {
67  uDatasets& d = (uDatasets&)(*dataBuf);
68  Euler theta;
69  sKmlLogData data;
70 
71 #ifdef USE_IS_INTERNAL
72 // uInternalDatasets &i = (uInternalDatasets&)(*dataBuf);
73 #endif
74 
75  // Write date to file
76  switch (dataHdr->id)
77  {
78  default: // Unidentified dataset
79  return 0;
80 
81  case DID_INS_1:
82  data = sKmlLogData(d.ins1.timeOfWeek, d.ins1.lla, d.ins1.theta);
83  break;
84  case DID_INS_2:
85  quat2euler(d.ins2.qn2b, theta);
86  data = sKmlLogData(d.ins2.timeOfWeek, d.ins2.lla, theta);
87  break;
88  case DID_INS_3:
89  quat2euler(d.ins3.qn2b, theta);
90  data = sKmlLogData(d.ins3.timeOfWeek, d.ins3.lla, theta);
91  break;
92  case DID_GPS1_POS:
93  case DID_GPS1_UBX_POS:
94  case DID_GPS2_POS:
96  break;
97  case DID_GPS1_RTK_POS:
99  break;
100  }
101 
102  list.push_back(data);
103 
104  return 0;
105 }
106 
107 
+
Vector3 Euler
Definition: ISConstants.h:730
cDataKML()
Definition: DataKML.cpp:39
string GetDatasetName(int kid)
Definition: DataKML.cpp:45
int WriteDataToFile(vector< sKmlLogData > &list, const p_data_hdr_t *dataHdr, const uint8_t *dataBuf)
Definition: DataKML.cpp:65
-
#define DID_GPS_RTK_NAV
Definition: data_sets.h:55
-
ins_3_t ins3
Definition: data_sets.h:2401
-
double timeOfWeek
Definition: data_sets.h:415
+
ins_3_t ins3
Definition: data_sets.h:2431
+
double timeOfWeek
Definition: data_sets.h:439
uint32_t id
Definition: ISComm.h:481
-
ins_2_t ins2
Definition: data_sets.h:2400
+
ins_2_t ins2
Definition: data_sets.h:2430
#define DID_INS_1
Definition: data_sets.h:38
-
double lla[3]
Definition: data_sets.h:430
+
double lla[3]
Definition: data_sets.h:454
+
#define DID_GPS1_UBX_POS
Definition: data_sets.h:40
-
#define DID_GPS2_NAV
Definition: data_sets.h:48
#define DID_INS_2
Definition: data_sets.h:39
-
float theta[3]
Definition: data_sets.h:424
+
float theta[3]
Definition: data_sets.h:448
-
float qn2b[4]
Definition: data_sets.h:453
-
gps_nav_t gpsRtkNav
Definition: data_sets.h:2417
+
float qn2b[4]
Definition: data_sets.h:477
void quat2euler(const Quat_t q, Euler_t theta)
Definition: ISPose.c:185
-
#define DID_GPS_NAV
Definition: data_sets.h:40
+
#define DID_GPS2_POS
Definition: data_sets.h:48
-
ins_1_t ins1
Definition: data_sets.h:2399
-
uint32_t timeOfWeekMs
Definition: data_sets.h:611
-
#define DID_GPS1_NAV
Definition: data_sets.h:47
-
gps_nav_t gpsNav
Definition: data_sets.h:2409
+
ins_1_t ins1
Definition: data_sets.h:2429
+
uint32_t timeOfWeekMs
Definition: data_sets.h:635
+
#define DID_GPS1_POS
Definition: data_sets.h:47
#define DID_INS_3
Definition: data_sets.h:99
+
#define DID_GPS1_RTK_POS
Definition: data_sets.h:88
- +
gps_pos_t gpsPos
Definition: data_sets.h:2439
+
diff --git a/docs/html/_data_k_m_l_8h.html b/docs/html/_data_k_m_l_8h.html index 10099b1f3..ec58a0ee9 100644 --- a/docs/html/_data_k_m_l_8h.html +++ b/docs/html/_data_k_m_l_8h.html @@ -23,7 +23,7 @@ Logo
SDK -  Release 1.6.2 +  Release 1.6.4
Communications, logger, and bootloader libraries.
diff --git a/docs/html/_data_k_m_l_8h_source.html b/docs/html/_data_k_m_l_8h_source.html index d1b3f0a12..bcafd3d49 100644 --- a/docs/html/_data_k_m_l_8h_source.html +++ b/docs/html/_data_k_m_l_8h_source.html @@ -23,7 +23,7 @@ Logo
SDK -  Release 1.6.2 +  Release 1.6.4
Communications, logger, and bootloader libraries.
@@ -72,15 +72,14 @@
DataKML.h
-Go to the documentation of this file.
1 /*
2 MIT LICENSE
3 
4 Copyright 2014 Inertial Sense, LLC - http://inertialsense.com
5 
6 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files(the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions :
7 
8 The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
9 
10 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
11 */
12 
13 #ifndef DATA_KML_H
14 #define DATA_KML_H
15 
16 // #include <stdio.h>
17 #include <string>
18 #include <vector>
19 
20 #include "tinyxml.h"
21 #include "com_manager.h"
22 
23 #ifdef USE_IS_INTERNAL
24 # include "../../libs/IS_internal.h"
25 #endif
26 
27 using namespace std;
28 
30 {
31  double time;
32  double lla[3];
33  float theta[3];
35  sKmlLogData(double _time, double _lla[3], float _theta[3])
36  {
37  time = _time;
38  lla[0] = _lla[0];
39  lla[1] = _lla[1];
40  lla[2] = _lla[2];
41  theta[0] = _theta[0];
42  theta[1] = _theta[1];
43  theta[2] = _theta[2];
44  }
45 
46  sKmlLogData(unsigned int _timeMs, double _lla[3])
47  {
48  time = _timeMs*0.001;
49  lla[0] = _lla[0];
50  lla[1] = _lla[1];
51  lla[2] = _lla[2];
52  theta[0] = theta[1] = theta[2] = 0;
53  }
54 };
55 
56 
57 class cDataKML
58 {
59 public:
60  enum MyEnum
61  {
62  KID_INS = 0,
69  };
70 
71  static inline int DID_TO_KID(int did)
72  {
73  switch (did)
74  {
75  default: return -1; // Unused
76  case DID_INS_1: return KID_INS;
77  case DID_GPS_NAV: return KID_GPS;
78  case DID_GPS1_NAV: return KID_GPS1;
79  case DID_GPS2_NAV: return KID_GPS2;
80  case DID_GPS_RTK_NAV: return KID_RTK;
81  }
82  }
83 
84  static inline int BYTES_PER_KID(int kid)
85  {
86  switch (kid)
87  {
88  default:
89  return -1; // Unused
90  case KID_INS:
91  return 130;
92  case KID_GPS:
93  case KID_GPS1:
94  case KID_GPS2:
95  case KID_RTK:
96  return 65;
97  }
98  }
99 
100  cDataKML();
101  string GetDatasetName(int kid);
102  int WriteDataToFile(vector<sKmlLogData>& list, const p_data_hdr_t* dataHdr, const uint8_t* dataBuf);
103 };
104 
105 #endif // DATA_KML_H
+Go to the documentation of this file.
1 /*
2 MIT LICENSE
3 
4 Copyright 2014 Inertial Sense, LLC - http://inertialsense.com
5 
6 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files(the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions :
7 
8 The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
9 
10 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
11 */
12 
13 #ifndef DATA_KML_H
14 #define DATA_KML_H
15 
16 // #include <stdio.h>
17 #include <string>
18 #include <vector>
19 
20 #include "tinyxml.h"
21 #include "com_manager.h"
22 
23 #ifdef USE_IS_INTERNAL
24 # include "../../libs/IS_internal.h"
25 #endif
26 
27 using namespace std;
28 
30 {
31  double time;
32  double lla[3];
33  float theta[3];
35  sKmlLogData(double _time, double _lla[3], float _theta[3])
36  {
37  time = _time;
38  lla[0] = _lla[0];
39  lla[1] = _lla[1];
40  lla[2] = _lla[2];
41  theta[0] = _theta[0];
42  theta[1] = _theta[1];
43  theta[2] = _theta[2];
44  }
45 
46  sKmlLogData(unsigned int _timeMs, double _lla[3])
47  {
48  time = _timeMs*0.001;
49  lla[0] = _lla[0];
50  lla[1] = _lla[1];
51  lla[2] = _lla[2];
52  theta[0] = theta[1] = theta[2] = 0;
53  }
54 };
55 
56 
57 class cDataKML
58 {
59 public:
60  enum MyEnum
61  {
62  KID_INS = 0,
69  };
70 
71  static inline int DID_TO_KID(int did)
72  {
73  switch (did)
74  {
75  default: return -1; // Unused
76  case DID_INS_1: return KID_INS;
77  case DID_GPS1_POS: return KID_GPS;
78  case DID_GPS1_UBX_POS: return KID_GPS1;
79  case DID_GPS2_POS: return KID_GPS2;
80  case DID_GPS1_RTK_POS: return KID_RTK;
81  }
82  }
83 
84  static inline int BYTES_PER_KID(int kid)
85  {
86  switch (kid)
87  {
88  default:
89  return -1; // Unused
90  case KID_INS:
91  return 130;
92  case KID_GPS:
93  case KID_GPS1:
94  case KID_GPS2:
95  case KID_RTK:
96  return 65;
97  }
98  }
99 
100  cDataKML();
101  string GetDatasetName(int kid);
102  int WriteDataToFile(vector<sKmlLogData>& list, const p_data_hdr_t* dataHdr, const uint8_t* dataBuf);
103 };
104 
105 #endif // DATA_KML_H
-
#define DID_GPS_RTK_NAV
Definition: data_sets.h:55
#define DID_INS_1
Definition: data_sets.h:38
sKmlLogData(unsigned int _timeMs, double _lla[3])
Definition: DataKML.h:46
+
#define DID_GPS1_UBX_POS
Definition: data_sets.h:40
-
#define DID_GPS2_NAV
Definition: data_sets.h:48
double time
Definition: DataKML.h:31
@@ -89,10 +88,11 @@
sKmlLogData()
Definition: DataKML.h:34
static int DID_TO_KID(int did)
Definition: DataKML.h:71
-
#define DID_GPS_NAV
Definition: data_sets.h:40
+
#define DID_GPS2_POS
Definition: data_sets.h:48
static int BYTES_PER_KID(int kid)
Definition: DataKML.h:84
-
#define DID_GPS1_NAV
Definition: data_sets.h:47
+
#define DID_GPS1_POS
Definition: data_sets.h:47
+
#define DID_GPS1_RTK_POS
Definition: data_sets.h:88
diff --git a/docs/html/_device_log_8cpp.html b/docs/html/_device_log_8cpp.html index 33ff40c38..79567debd 100644 --- a/docs/html/_device_log_8cpp.html +++ b/docs/html/_device_log_8cpp.html @@ -23,7 +23,7 @@ Logo
SDK -  Release 1.6.2 +  Release 1.6.4
Communications, logger, and bootloader libraries.
diff --git a/docs/html/_device_log_8cpp_source.html b/docs/html/_device_log_8cpp_source.html index 9f6d34cce..0b72360a6 100644 --- a/docs/html/_device_log_8cpp_source.html +++ b/docs/html/_device_log_8cpp_source.html @@ -23,7 +23,7 @@ Logo
SDK -  Release 1.6.2 +  Release 1.6.4
Communications, logger, and bootloader libraries.
@@ -77,7 +77,7 @@
bool SetupReadInfo(const string &directory, const string &deviceName, const string &timeStamp)
Definition: DeviceLog.cpp:114
uint32_t id
Definition: ISComm.h:481
-
static double GetTimestamp(const p_data_hdr_t *hdr, const uint8_t *buf)
+
static double GetTimestamp(const p_data_hdr_t *hdr, const uint8_t *buf)
bool OpenNextReadFile()
Definition: DeviceLog.cpp:195
@@ -95,9 +95,9 @@
uint8_t buf[MAX_DATASET_SIZE]
Definition: ISComm.h:497
- -
static uint64_t GetDirectorySpaceUsed(const string &directory, bool recursive=true)
Definition: ISLogger.cpp:410
-
#define _MKDIR(dir)
Definition: ISConstants.h:203
+ +
static uint64_t GetDirectorySpaceUsed(const string &directory, bool recursive=true)
Definition: ISLogger.cpp:411
+
#define _MKDIR(dir)
Definition: ISConstants.h:200
virtual void InitDeviceForReading()
Definition: DeviceLog.cpp:72
virtual bool OpenWithSystemApp()
Definition: DeviceLog.cpp:89
diff --git a/docs/html/_device_log_8h.html b/docs/html/_device_log_8h.html index fdd5281f8..126294583 100644 --- a/docs/html/_device_log_8h.html +++ b/docs/html/_device_log_8h.html @@ -23,7 +23,7 @@ Logo
SDK -  Release 1.6.2 +  Release 1.6.4
Communications, logger, and bootloader libraries.
diff --git a/docs/html/_device_log_8h_source.html b/docs/html/_device_log_8h_source.html index fa633e5f4..bad9a2fb7 100644 --- a/docs/html/_device_log_8h_source.html +++ b/docs/html/_device_log_8h_source.html @@ -23,7 +23,7 @@ Logo
SDK -  Release 1.6.2 +  Release 1.6.4
Communications, logger, and bootloader libraries.
@@ -97,7 +97,7 @@
uint64_t m_logSize
Definition: DeviceLog.h:77
virtual void Flush()
Definition: DeviceLog.h:47
string m_directory
Definition: DeviceLog.h:71
- +
string m_fileName
Definition: DeviceLog.h:73
uint32_t m_fileCount
Definition: DeviceLog.h:78
diff --git a/docs/html/_device_log_c_s_v_8cpp.html b/docs/html/_device_log_c_s_v_8cpp.html index 53660c9ea..e4504d33b 100644 --- a/docs/html/_device_log_c_s_v_8cpp.html +++ b/docs/html/_device_log_c_s_v_8cpp.html @@ -23,7 +23,7 @@ Logo
SDK -  Release 1.6.2 +  Release 1.6.4
Communications, logger, and bootloader libraries.
diff --git a/docs/html/_device_log_c_s_v_8cpp_source.html b/docs/html/_device_log_c_s_v_8cpp_source.html index 63e6ccf08..df90324ed 100644 --- a/docs/html/_device_log_c_s_v_8cpp_source.html +++ b/docs/html/_device_log_c_s_v_8cpp_source.html @@ -23,7 +23,7 @@ Logo
SDK -  Release 1.6.2 +  Release 1.6.4
Communications, logger, and bootloader libraries.
@@ -72,13 +72,13 @@
DeviceLogCSV.cpp
-Go to the documentation of this file.
1 /*
2 MIT LICENSE
3 
4 Copyright 2014 Inertial Sense, LLC - http://inertialsense.com
5 
6 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files(the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions :
7 
8 The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
9 
10 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
11 */
12 
13 #include <ctime>
14 #include <string>
15 #include <sstream>
16 #include <sys/types.h>
17 #include <sys/stat.h>
18 #include <iomanip>
19 #include <iostream>
20 #include <fstream>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <stddef.h>
24 #include <limits.h>
25 
26 #include "ISPose.h"
27 #include "DeviceLogCSV.h"
28 #include "ISLogger.h"
29 #include "ISDataMappings.h"
30 
31 using namespace std;
32 
33 
34 void cDeviceLogCSV::InitDeviceForWriting(int pHandle, std::string timestamp, std::string directory, uint64_t maxDiskSpace, uint32_t maxFileSize, uint32_t chunkSize)
35 {
36  m_logs.clear();
37  m_nextId = 0;
38  cDeviceLog::InitDeviceForWriting(pHandle, timestamp, directory, maxDiskSpace, maxFileSize, chunkSize);
39 }
40 
41 
43 {
45 
46  // open the first file for each possible data set
47  m_logs.clear();
48  for (uint32_t id = DID_NULL + 1; id < DID_COUNT; id++)
49  {
50  const char* dataSet = cISDataMappings::GetDataSetName(id);
51  if (dataSet != NULL)
52  {
53  string dataSetRegex = string(dataSet) + "\\.csv$";
54  vector<file_info_t> infos;
55  vector<string> files;
56  cISLogger::GetDirectorySpaceUsed(m_directory, dataSetRegex, infos, false, false);
57  if (infos.size() != 0)
58  {
59  cCsvLog log;
60  log.dataId = id;
62  for (size_t i = 0; i < infos.size(); i++)
63  {
64  files.push_back(infos[i].name);
65  }
66  m_currentFiles[id] = files;
67  m_currentFileIndex[id] = 0;
68  while (OpenNewFile(log, true) && !GetNextLineForFile(log)) {}
69  if (log.nextLine.length() != 0)
70  {
71  m_logs[id] = log;
72  }
73  }
74  }
75  }
76 }
77 
78 
80 {
82 
83  for (map<uint32_t, cCsvLog>::iterator i = m_logs.begin(); i != m_logs.end(); i++)
84  {
85  cCsvLog& log = i->second;
86  if (log.pFile)
87  {
88  fclose(log.pFile);
89  log.pFile = NULL;
90  }
91  }
92  m_logs.clear();
93  return true;
94 }
95 
96 
97 bool cDeviceLogCSV::OpenNewFile(cCsvLog& log, bool readonly)
98 {
99  const char* dataSetName = cISDataMappings::GetDataSetName(log.dataId);
100  if (dataSetName == NULL)
101  {
102  return false;
103  }
104 
105  // Close existing file
106  if (log.pFile)
107  {
108  fclose(log.pFile);
109  log.pFile = NULL;
110  }
111 
112  // Ensure directory exists
113  if (m_directory.empty())
114  {
115  return false;
116  }
117 
118  _MKDIR(m_directory.c_str());
119 
120  // Open new file
121  uint32_t serNum = m_devInfo.serialNumber;
122  if (!serNum)
123  {
124  serNum = m_pHandle;
125  }
126 
127  if (readonly)
128  {
129 tryNextFile:
130  {
131  uint32_t index = m_currentFileIndex[log.dataId];
132  vector<string>& files = m_currentFiles[log.dataId];
133  if (index >= files.size())
134  {
135  m_logs.erase(log.dataId);
136  return false;
137  }
138  string currentFile = files[index++];
139  m_currentFileIndex[log.dataId] = index;
140  log.pFile = fopen(currentFile.c_str(), "r");
141  log.fileCount++;
142  struct stat st;
143  stat(currentFile.c_str(), &st);
144  log.fileSize = st.st_size;
145  m_logSize += log.fileSize;
146  if (m_csv.ReadHeaderFromFile(log.pFile, log.dataId, log.columnHeaders) == 0)
147  {
148  goto tryNextFile;
149  }
150  }
151  }
152  else
153  {
154  log.fileCount++;
155  string fileName = GetNewFileName(serNum, log.fileCount, dataSetName);
156  log.pFile = fopen(fileName.c_str(), "w");
157 
158  // Write Header
159  int fileBytes = m_csv.WriteHeaderToFile(log.pFile, log.dataId);
160 
161  // File byte size
162  log.fileSize = fileBytes;
163  m_logSize += fileBytes;
164  }
165 
166  if (log.pFile)
167  {
168 #if LOG_DEBUG_WRITE
169  printf("Opened save file: %s\n", filename.str().c_str());
170 #endif
171  return true;
172  }
173  else
174  {
175 #if LOG_DEBUG_WRITE
176  printf("FAILED to open save file: %s\n", filename.str().c_str());
177 #endif
178  m_logs.erase(log.dataId);
179  return false;
180  }
181 }
182 
183 
184 bool cDeviceLogCSV::GetNextLineForFile(cCsvLog& log)
185 {
186  if (log.pFile == NULL)
187  {
188  return false;
189  }
190  char lineBuffer[8192];
191  if (fgets(lineBuffer, _ARRAY_BYTE_COUNT(lineBuffer), log.pFile) == NULL)
192  {
193  return false;
194  }
195  log.nextLine = lineBuffer;
196  size_t index = log.nextLine.find(',', 0);
197  if (index < log.nextLine.size())
198  {
199  log.orderId = strtoull(log.nextLine.c_str(), NULL, 10);
200  }
201  else
202  {
203  return false;
204  }
205  return true;
206 }
207 
208 
209 bool cDeviceLogCSV::SaveData(p_data_hdr_t* dataHdr, const uint8_t* dataBuf)
210 {
211  cDeviceLog::SaveData(dataHdr, dataBuf);
212 
213  // Reference current log
214  cCsvLog& log = m_logs[dataHdr->id];
215  log.dataId = dataHdr->id;
216 
217  // Create first file it it doesn't exist, return out if failure
218  if (log.pFile == NULL && (!OpenNewFile(log, false) || log.pFile == NULL))
219  {
220  return false;
221  }
222  else if (dataHdr->id == DID_DEV_INFO)
223  {
224  memcpy(&m_devInfo, dataBuf, sizeof(dev_info_t));
225  }
226 
227  // Write date to file
228  int nBytes = m_csv.WriteDataToFile(++m_nextId, log.pFile, *dataHdr, dataBuf);
229  if (ferror(log.pFile) != 0)
230  {
231  return false;
232  }
233 
234  // File byte size
235  log.fileSize += nBytes;
236  m_logSize += nBytes;
237 
238  if (log.fileSize >= m_maxFileSize)
239  {
240  // Close existing file
241  fclose(log.pFile);
242  log.pFile = NULL;
243  log.fileSize = 0;
244  }
245 
246  return true;
247 }
248 
249 
251 {
252 
253 tryAgain:
254  if (m_logs.size() == 0)
255  {
256  return NULL;
257  }
258 
259  p_data_t* data = NULL;
260  cCsvLog* nextLog = NULL;
261  uint64_t nextId = ULLONG_MAX;
262  for (map<uint32_t, cCsvLog>::iterator i = m_logs.begin(); i != m_logs.end(); )
263  {
264  if (i->second.orderId < nextId)
265  {
266  nextLog = &i->second;
267  nextId = i->second.orderId;
268  }
269  i++;
270  }
271  if (nextLog == NULL)
272  {
273  assert(false);
274  return NULL;
275  }
276  if ((data = ReadDataFromFile(*nextLog)) == NULL)
277  {
278  goto tryAgain;
279  }
280 
282  return data;
283 }
284 
285 
286 p_data_t* cDeviceLogCSV::ReadDataFromFile(cCsvLog& log)
287 {
288  if (log.pFile == NULL)
289  {
290  assert(false);
291  return NULL;
292  }
293  m_dataBuffer.hdr.id = log.dataId;
294  m_dataBuffer.hdr.size = log.dataSize;
295  if (m_csv.StringCSVToData(log.nextLine, m_dataBuffer.hdr, m_dataBuffer.buf, _ARRAY_BYTE_COUNT(m_dataBuffer.buf), log.columnHeaders))
296  {
297  if (m_dataBuffer.hdr.id == DID_DEV_INFO)
298  {
299  memcpy(&m_devInfo, m_dataBuffer.buf, sizeof(dev_info_t));
300  }
301  log.nextLine.clear();
302  while (!GetNextLineForFile(log) && OpenNewFile(log, true)) {}
303  return &m_dataBuffer;
304  }
305  log.nextLine.clear();
306  while (!GetNextLineForFile(log) && OpenNewFile(log, true)) {}
307  return NULL;
308 }
309 
310 
311 void cDeviceLogCSV::SetSerialNumber(uint32_t serialNumber)
312 {
313  m_devInfo.serialNumber = serialNumber;
314 }
315 
316 
317 
static uint32_t GetSize(uint32_t dataId)
+Go to the documentation of this file.
1 /*
2 MIT LICENSE
3 
4 Copyright 2014 Inertial Sense, LLC - http://inertialsense.com
5 
6 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files(the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions :
7 
8 The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
9 
10 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
11 */
12 
13 #include <ctime>
14 #include <string>
15 #include <sstream>
16 #include <sys/types.h>
17 #include <sys/stat.h>
18 #include <iomanip>
19 #include <iostream>
20 #include <fstream>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <stddef.h>
24 #include <limits.h>
25 
26 #include "ISPose.h"
27 #include "DeviceLogCSV.h"
28 #include "ISLogger.h"
29 #include "ISDataMappings.h"
30 
31 using namespace std;
32 
33 
34 void cDeviceLogCSV::InitDeviceForWriting(int pHandle, std::string timestamp, std::string directory, uint64_t maxDiskSpace, uint32_t maxFileSize, uint32_t chunkSize)
35 {
36  m_logs.clear();
37  m_nextId = 0;
38  cDeviceLog::InitDeviceForWriting(pHandle, timestamp, directory, maxDiskSpace, maxFileSize, chunkSize);
39 }
40 
41 
43 {
45 
46  // open the first file for each possible data set
47  m_logs.clear();
48  for (uint32_t id = DID_NULL + 1; id < DID_COUNT; id++)
49  {
50  const char* dataSet = cISDataMappings::GetDataSetName(id);
51  if (dataSet != NULL)
52  {
53  string dataSetRegex = string(dataSet) + "\\.csv$";
54  vector<file_info_t> infos;
55  vector<string> files;
56  cISLogger::GetDirectorySpaceUsed(m_directory, dataSetRegex, infos, false, false);
57  if (infos.size() != 0)
58  {
59  cCsvLog log;
60  log.dataId = id;
62  for (size_t i = 0; i < infos.size(); i++)
63  {
64  files.push_back(infos[i].name);
65  }
66  m_currentFiles[id] = files;
67  m_currentFileIndex[id] = 0;
68  while (OpenNewFile(log, true) && !GetNextLineForFile(log)) {}
69  if (log.nextLine.length() != 0)
70  {
71  m_logs[id] = log;
72  }
73  }
74  }
75  }
76 }
77 
78 
80 {
82 
83  for (map<uint32_t, cCsvLog>::iterator i = m_logs.begin(); i != m_logs.end(); i++)
84  {
85  cCsvLog& log = i->second;
86  if (log.pFile)
87  {
88  fclose(log.pFile);
89  log.pFile = NULL;
90  }
91  }
92  m_logs.clear();
93  return true;
94 }
95 
96 
97 bool cDeviceLogCSV::OpenNewFile(cCsvLog& log, bool readonly)
98 {
99  const char* dataSetName = cISDataMappings::GetDataSetName(log.dataId);
100  if (dataSetName == NULL)
101  {
102  return false;
103  }
104 
105  // Close existing file
106  if (log.pFile)
107  {
108  fclose(log.pFile);
109  log.pFile = NULL;
110  }
111 
112  // Ensure directory exists
113  if (m_directory.empty())
114  {
115  return false;
116  }
117 
118  _MKDIR(m_directory.c_str());
119 
120  // Open new file
121  uint32_t serNum = m_devInfo.serialNumber;
122  if (!serNum)
123  {
124  serNum = m_pHandle;
125  }
126 
127  if (readonly)
128  {
129 tryNextFile:
130  {
131  uint32_t index = m_currentFileIndex[log.dataId];
132  vector<string>& files = m_currentFiles[log.dataId];
133  if (index >= files.size())
134  {
135  m_logs.erase(log.dataId);
136  return false;
137  }
138  string currentFile = files[index++];
139  m_currentFileIndex[log.dataId] = index;
140  log.pFile = fopen(currentFile.c_str(), "r");
141  log.fileCount++;
142  struct stat st;
143  stat(currentFile.c_str(), &st);
144  log.fileSize = st.st_size;
145  m_logSize += log.fileSize;
146  if (m_csv.ReadHeaderFromFile(log.pFile, log.dataId, log.columnHeaders) == 0)
147  {
148  goto tryNextFile;
149  }
150  }
151  }
152  else
153  {
154  log.fileCount++;
155  string fileName = GetNewFileName(serNum, log.fileCount, dataSetName);
156  log.pFile = fopen(fileName.c_str(), "w");
157 
158  // Write Header
159  int fileBytes = m_csv.WriteHeaderToFile(log.pFile, log.dataId);
160 
161  // File byte size
162  log.fileSize = fileBytes;
163  m_logSize += fileBytes;
164  }
165 
166  if (log.pFile)
167  {
168 #if LOG_DEBUG_WRITE
169  printf("Opened save file: %s\n", filename.str().c_str());
170 #endif
171  return true;
172  }
173  else
174  {
175 #if LOG_DEBUG_WRITE
176  printf("FAILED to open save file: %s\n", filename.str().c_str());
177 #endif
178  m_logs.erase(log.dataId);
179  return false;
180  }
181 }
182 
183 
184 bool cDeviceLogCSV::GetNextLineForFile(cCsvLog& log)
185 {
186  if (log.pFile == NULL)
187  {
188  return false;
189  }
190  char lineBuffer[8192];
191  if (fgets(lineBuffer, _ARRAY_BYTE_COUNT(lineBuffer), log.pFile) == NULL)
192  {
193  return false;
194  }
195  log.nextLine = lineBuffer;
196  size_t index = log.nextLine.find(',', 0);
197  if (index < log.nextLine.size())
198  {
199  log.orderId = strtoull(log.nextLine.c_str(), NULL, 10);
200  }
201  else
202  {
203  return false;
204  }
205  return true;
206 }
207 
208 
209 bool cDeviceLogCSV::SaveData(p_data_hdr_t* dataHdr, const uint8_t* dataBuf)
210 {
211  cDeviceLog::SaveData(dataHdr, dataBuf);
212 
213  // Reference current log
214  cCsvLog& log = m_logs[dataHdr->id];
215  log.dataId = dataHdr->id;
216 
217  // Create first file it it doesn't exist, return out if failure
218  if (log.pFile == NULL && (!OpenNewFile(log, false) || log.pFile == NULL))
219  {
220  return false;
221  }
222  else if (dataHdr->id == DID_DEV_INFO)
223  {
224  memcpy(&m_devInfo, dataBuf, sizeof(dev_info_t));
225  }
226 
227  // Write date to file
228  int nBytes = m_csv.WriteDataToFile(++m_nextId, log.pFile, *dataHdr, dataBuf);
229  if (ferror(log.pFile) != 0)
230  {
231  return false;
232  }
233 
234  // File byte size
235  log.fileSize += nBytes;
236  m_logSize += nBytes;
237 
238  if (log.fileSize >= m_maxFileSize)
239  {
240  // Close existing file
241  fclose(log.pFile);
242  log.pFile = NULL;
243  log.fileSize = 0;
244  }
245 
246  return true;
247 }
248 
249 
251 {
252 
253 tryAgain:
254  if (m_logs.size() == 0)
255  {
256  return NULL;
257  }
258 
259  p_data_t* data = NULL;
260  cCsvLog* nextLog = NULL;
261  uint64_t nextId = ULLONG_MAX;
262  for (map<uint32_t, cCsvLog>::iterator i = m_logs.begin(); i != m_logs.end(); )
263  {
264  if (i->second.orderId < nextId)
265  {
266  nextLog = &i->second;
267  nextId = i->second.orderId;
268  }
269  i++;
270  }
271  if (nextLog == NULL)
272  {
273  assert(false);
274  return NULL;
275  }
276  if ((data = ReadDataFromFile(*nextLog)) == NULL)
277  {
278  goto tryAgain;
279  }
280 
282  return data;
283 }
284 
285 
286 p_data_t* cDeviceLogCSV::ReadDataFromFile(cCsvLog& log)
287 {
288  if (log.pFile == NULL)
289  {
290  assert(false);
291  return NULL;
292  }
293  m_dataBuffer.hdr.id = log.dataId;
294  m_dataBuffer.hdr.size = log.dataSize;
295  if (m_csv.StringCSVToData(log.nextLine, m_dataBuffer.hdr, m_dataBuffer.buf, _ARRAY_BYTE_COUNT(m_dataBuffer.buf), log.columnHeaders))
296  {
297  if (m_dataBuffer.hdr.id == DID_DEV_INFO)
298  {
299  memcpy(&m_devInfo, m_dataBuffer.buf, sizeof(dev_info_t));
300  }
301  log.nextLine.clear();
302  while (!GetNextLineForFile(log) && OpenNewFile(log, true)) {}
303  return &m_dataBuffer;
304  }
305  log.nextLine.clear();
306  while (!GetNextLineForFile(log) && OpenNewFile(log, true)) {}
307  return NULL;
308 }
309 
310 
311 void cDeviceLogCSV::SetSerialNumber(uint32_t serialNumber)
312 {
313  m_devInfo.serialNumber = serialNumber;
314 }
315 
316 
317 
static uint32_t GetSize(uint32_t dataId)
void OnReadData(p_data_t *data)
Definition: DeviceLog.cpp:254
uint32_t dataId
Definition: DeviceLogCSV.h:33
PUSH_PACK_1 struct PACKED dev_info_t
uint32_t id
Definition: ISComm.h:481
-
static const char * GetDataSetName(uint32_t dataId)
+
static const char * GetDataSetName(uint32_t dataId)
bool CloseAllFiles() OVERRIDE
@@ -86,7 +86,7 @@
#define DID_DEV_INFO
Definition: data_sets.h:35
virtual bool CloseAllFiles()
Definition: DeviceLog.cpp:80
virtual void InitDeviceForWriting(int pHandle, string timestamp, string directory, uint64_t maxDiskSpace, uint32_t maxFileSize, uint32_t chunkSize)
Definition: DeviceLog.cpp:59
-
#define _ARRAY_BYTE_COUNT(a)
Definition: ISConstants.h:293
+
#define _ARRAY_BYTE_COUNT(a)
Definition: ISConstants.h:290
virtual bool SaveData(p_data_hdr_t *dataHdr, const uint8_t *dataBuf)
Definition: DeviceLog.cpp:104
bool SaveData(p_data_hdr_t *dataHdr, const uint8_t *dataBuf) OVERRIDE
void SetSerialNumber(uint32_t serialNumber) OVERRIDE
@@ -105,8 +105,8 @@
uint32_t fileCount
Definition: DeviceLogCSV.h:31
vector< string > columnHeaders
Definition: DeviceLogCSV.h:37
-
static uint64_t GetDirectorySpaceUsed(const string &directory, bool recursive=true)
Definition: ISLogger.cpp:410
-
#define _MKDIR(dir)
Definition: ISConstants.h:203
+
static uint64_t GetDirectorySpaceUsed(const string &directory, bool recursive=true)
Definition: ISLogger.cpp:411
+
#define _MKDIR(dir)
Definition: ISConstants.h:200
virtual void InitDeviceForReading()
Definition: DeviceLog.cpp:72
string nextLine
Definition: DeviceLogCSV.h:36
diff --git a/docs/html/_device_log_c_s_v_8h.html b/docs/html/_device_log_c_s_v_8h.html index 1d51b53ee..da590b426 100644 --- a/docs/html/_device_log_c_s_v_8h.html +++ b/docs/html/_device_log_c_s_v_8h.html @@ -23,7 +23,7 @@ Logo
SDK -  Release 1.6.2 +  Release 1.6.4
Communications, logger, and bootloader libraries.
diff --git a/docs/html/_device_log_c_s_v_8h_source.html b/docs/html/_device_log_c_s_v_8h_source.html index 8a1e541cb..b65029566 100644 --- a/docs/html/_device_log_c_s_v_8h_source.html +++ b/docs/html/_device_log_c_s_v_8h_source.html @@ -23,7 +23,7 @@ Logo
SDK -  Release 1.6.2 +  Release 1.6.4
Communications, logger, and bootloader libraries.
@@ -76,7 +76,7 @@
uint32_t dataId
Definition: DeviceLogCSV.h:33
bool CloseAllFiles() OVERRIDE
-
#define OVERRIDE
Definition: ISConstants.h:377
+
#define OVERRIDE
Definition: ISConstants.h:374
std::string LogFileExtention() OVERRIDE
Definition: DeviceLogCSV.h:50
bool SaveData(p_data_hdr_t *dataHdr, const uint8_t *dataBuf) OVERRIDE
void SetSerialNumber(uint32_t serialNumber) OVERRIDE
diff --git a/docs/html/_device_log_j_s_o_n_8cpp.html b/docs/html/_device_log_j_s_o_n_8cpp.html new file mode 100644 index 000000000..2f3bdb846 --- /dev/null +++ b/docs/html/_device_log_j_s_o_n_8cpp.html @@ -0,0 +1,101 @@ + + + + + + + +SDK: src/DeviceLogJSON.cpp File Reference + + + + + + + + + +
+
+ + + + + + + +
+
SDK +  Release 1.6.4 +
+
Communications, logger, and bootloader libraries.
+
+
+ + + + + + + + +
+
+ + +
+ +
+ + +
+
+
+
DeviceLogJSON.cpp File Reference
+
+
+
#include <ctime>
+#include <string>
+#include <sstream>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <iomanip>
+#include <iostream>
+#include <fstream>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <limits.h>
+#include "ISPose.h"
+#include "DeviceLogJSON.h"
+#include "ISLogger.h"
+#include "ISDataMappings.h"
+
+

Go to the source code of this file.

+
+ + + + diff --git a/docs/html/_device_log_j_s_o_n_8cpp_source.html b/docs/html/_device_log_j_s_o_n_8cpp_source.html new file mode 100644 index 000000000..a6eca7a0c --- /dev/null +++ b/docs/html/_device_log_j_s_o_n_8cpp_source.html @@ -0,0 +1,102 @@ + + + + + + + +SDK: src/DeviceLogJSON.cpp Source File + + + + + + + + + +
+
+ + + + + + + +
+
SDK +  Release 1.6.4 +
+
Communications, logger, and bootloader libraries.
+
+
+ + + + + + + + +
+
+ + +
+ +
+ + +
+
+
+
DeviceLogJSON.cpp
+
+
+Go to the documentation of this file.
1 /*
2 MIT LICENSE
3 
4 Copyright 2014 Inertial Sense, LLC - http://inertialsense.com
5 
6 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files(the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions :
7 
8 The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
9 
10 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
11 */
12 
13 #include <ctime>
14 #include <string>
15 #include <sstream>
16 #include <sys/types.h>
17 #include <sys/stat.h>
18 #include <iomanip>
19 #include <iostream>
20 #include <fstream>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <stddef.h>
24 #include <limits.h>
25 
26 #include "ISPose.h"
27 #include "DeviceLogJSON.h"
28 #include "ISLogger.h"
29 #include "ISDataMappings.h"
30 
31 using namespace std;
32 
34 {
36  if (m_pFile != NULLPTR)
37  {
38  fputc(']', m_pFile);
39  fclose(m_pFile);
40  m_pFile = NULLPTR;
41  }
42  return true;
43 }
44 
45 bool cDeviceLogJSON::GetNextItemForFile()
46 {
47  m_jsonString.clear();
48  if (m_pFile == NULLPTR)
49  {
50  return false;
51  }
52  int stack = 0;
53  int c;
54  int pc = 0;
55  while ((c = fgetc(m_pFile)) >= 0)
56  {
57  if (c == '{' && pc != '\\')
58  {
59  stack++;
60  }
61  else if (c == '}' && pc != '\\')
62  {
63  stack--;
64  if (stack == 0)
65  {
66  m_jsonString.append(1, c);
67  break;
68  }
69  }
70 
71  if (stack != 0)
72  {
73  m_jsonString.append(1, c);
74  }
75 
76  pc = c;
77  }
78  return (m_jsonString.size() != 0);
79 }
80 
81 
82 bool cDeviceLogJSON::SaveData(p_data_hdr_t* dataHdr, const uint8_t* dataBuf)
83 {
84  cDeviceLog::SaveData(dataHdr, dataBuf);
85 
86  bool needsComma = true;
87 
88  // Create first file it it doesn't exist, return out if failure
89  if (m_pFile == NULLPTR)
90  {
91  needsComma = false;
92  if (!OpenNewSaveFile())
93  {
94  return false;
95  }
96  fputc('[', m_pFile);
97  }
98  else if (dataHdr->id == DID_DEV_INFO)
99  {
100  memcpy(&m_devInfo, dataBuf, sizeof(dev_info_t));
101  }
102 
103  // Write date to file
104  int nBytes = m_json.WriteDataToFile(m_pFile, *dataHdr, dataBuf, (needsComma ? ",\n" : NULLPTR));
105  if (ferror(m_pFile) != 0)
106  {
107  return false;
108  }
109 
110  // File byte size
111  m_logSize += nBytes;
112 
113  if (m_logSize >= m_maxFileSize)
114  {
115  // Close existing file
116  fputc(']', m_pFile);
117  fclose(m_pFile);
118  m_pFile = NULL;
119  m_logSize = 0;
120  }
121 
122  return true;
123 }
124 
125 
127 {
128  if (m_pFile == NULLPTR)
129  {
130  if (!OpenNextReadFile())
131  {
132  return NULLPTR;
133  }
134  }
135  p_data_t* data = ReadDataFromFile();
137  return data;
138 }
139 
140 
141 p_data_t* cDeviceLogJSON::ReadDataFromFile()
142 {
143  if (m_pFile == NULLPTR)
144  {
145  assert(false);
146  return NULL;
147  }
148  while (!GetNextItemForFile() && OpenNextReadFile()) {}
149  if (m_json.StringJSONToData(m_jsonString, m_dataBuffer.hdr, m_dataBuffer.buf, _ARRAY_BYTE_COUNT(m_dataBuffer.buf)))
150  {
151  if (m_dataBuffer.hdr.id == DID_DEV_INFO)
152  {
153  memcpy(&m_devInfo, m_dataBuffer.buf, sizeof(dev_info_t));
154  }
155  return &m_dataBuffer;
156  }
157  return NULLPTR;
158 }
159 
160 
161 void cDeviceLogJSON::SetSerialNumber(uint32_t serialNumber)
162 {
163  m_devInfo.serialNumber = serialNumber;
164 }
165 
166 
167 
void OnReadData(p_data_t *data)
Definition: DeviceLog.cpp:254
+
p_data_t * ReadData() OVERRIDE
+
PUSH_PACK_1 struct PACKED dev_info_t
+ +
uint32_t id
Definition: ISComm.h:481
+
void SetSerialNumber(uint32_t serialNumber) OVERRIDE
+
#define NULLPTR
Definition: ISConstants.h:377
+ + +
#define DID_DEV_INFO
Definition: data_sets.h:35
+
virtual bool CloseAllFiles()
Definition: DeviceLog.cpp:80
+
#define _ARRAY_BYTE_COUNT(a)
Definition: ISConstants.h:290
+
virtual bool SaveData(p_data_hdr_t *dataHdr, const uint8_t *dataBuf)
Definition: DeviceLog.cpp:104
+
bool SaveData(p_data_hdr_t *dataHdr, const uint8_t *dataBuf) OVERRIDE
+
bool CloseAllFiles() OVERRIDE
+ + + + +
+ + + + diff --git a/docs/html/_device_log_j_s_o_n_8h.html b/docs/html/_device_log_j_s_o_n_8h.html new file mode 100644 index 000000000..ab715a2fa --- /dev/null +++ b/docs/html/_device_log_j_s_o_n_8h.html @@ -0,0 +1,100 @@ + + + + + + + +SDK: src/DeviceLogJSON.h File Reference + + + + + + + + + +
+
+ + + + + + + +
+
SDK +  Release 1.6.4 +
+
Communications, logger, and bootloader libraries.
+
+
+ + + + + + + + +
+
+ + +
+ +
+ + +
+
+ +
+
DeviceLogJSON.h File Reference
+
+
+
#include <stdio.h>
+#include <string>
+#include <vector>
+#include <map>
+#include "DataJSON.h"
+#include "DeviceLog.h"
+#include "com_manager.h"
+
+

Go to the source code of this file.

+ + + + +

+Classes

class  cDeviceLogJSON
 
+
+ + + + diff --git a/docs/html/_device_log_j_s_o_n_8h_source.html b/docs/html/_device_log_j_s_o_n_8h_source.html new file mode 100644 index 000000000..8603082fc --- /dev/null +++ b/docs/html/_device_log_j_s_o_n_8h_source.html @@ -0,0 +1,97 @@ + + + + + + + +SDK: src/DeviceLogJSON.h Source File + + + + + + + + + +
+
+ + + + + + + +
+
SDK +  Release 1.6.4 +
+
Communications, logger, and bootloader libraries.
+
+
+ + + + + + + + +
+
+ + +
+ +
+ + +
+
+
+
DeviceLogJSON.h
+
+
+Go to the documentation of this file.
1 /*
2 MIT LICENSE
3 
4 Copyright 2014 Inertial Sense, LLC - http://inertialsense.com
5 
6 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files(the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions :
7 
8 The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
9 
10 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
11 */
12 
13 #ifndef DEVICE_LOG_JSON_H
14 #define DEVICE_LOG_JSON_H
15 
16 #include <stdio.h>
17 #include <string>
18 #include <vector>
19 #include <map>
20 
21 #include "DataJSON.h"
22 #include "DeviceLog.h"
23 #include "com_manager.h"
24 
25 class cDeviceLogJSON : public cDeviceLog
26 {
27 public:
28  bool CloseAllFiles() OVERRIDE;
29  bool SaveData(p_data_hdr_t* dataHdr, const uint8_t* dataBuf) OVERRIDE;
31  void SetSerialNumber(uint32_t serialNumber) OVERRIDE;
32  std::string LogFileExtention() OVERRIDE { return std::string(".json"); }
33 
34 private:
35  bool GetNextItemForFile();
36 
37  p_data_t* ReadDataFromFile();
38  string m_jsonString;
39  cDataJSON m_json;
40  p_data_t m_dataBuffer;
41 };
42 
43 #endif // DEVICE_LOG_CSV_H
std::string LogFileExtention() OVERRIDE
Definition: DeviceLogJSON.h:32
+
p_data_t * ReadData() OVERRIDE
+
void SetSerialNumber(uint32_t serialNumber) OVERRIDE
+ +
#define OVERRIDE
Definition: ISConstants.h:374
+ + +
bool SaveData(p_data_hdr_t *dataHdr, const uint8_t *dataBuf) OVERRIDE
+
bool CloseAllFiles() OVERRIDE
+ + + + + +
+ + + + diff --git a/docs/html/_device_log_k_m_l_8cpp.html b/docs/html/_device_log_k_m_l_8cpp.html index d508f5643..ef37dbda2 100644 --- a/docs/html/_device_log_k_m_l_8cpp.html +++ b/docs/html/_device_log_k_m_l_8cpp.html @@ -23,7 +23,7 @@ Logo
SDK -  Release 1.6.2 +  Release 1.6.4
Communications, logger, and bootloader libraries.
diff --git a/docs/html/_device_log_k_m_l_8cpp_source.html b/docs/html/_device_log_k_m_l_8cpp_source.html index 284148a5c..d045464c7 100644 --- a/docs/html/_device_log_k_m_l_8cpp_source.html +++ b/docs/html/_device_log_k_m_l_8cpp_source.html @@ -23,7 +23,7 @@ Logo
SDK -  Release 1.6.2 +  Release 1.6.4
Communications, logger, and bootloader libraries.
@@ -72,7 +72,7 @@
DeviceLogKML.cpp
-Go to the documentation of this file.
1 /*
2 MIT LICENSE
3 
4 Copyright 2014 Inertial Sense, LLC - http://inertialsense.com
5 
6 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files(the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions :
7 
8 The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
9 
10 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
11 */
12 
13 #include <ctime>
14 #include <string>
15 #include <sstream>
16 #include <sys/types.h>
17 #include <sys/stat.h>
18 #include <iomanip>
19 #include <iostream>
20 #include <fstream>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <stddef.h>
24 #include "ISPose.h"
25 #include "DeviceLogKML.h"
26 #include "ISLogger.h"
27 #include "ISConstants.h"
28 
29 using namespace std;
30 
31 void cDeviceLogKML::InitDeviceForWriting(int pHandle, std::string timestamp, std::string directory, uint64_t maxDiskSpace, uint32_t maxFileSize, uint32_t chunkSize)
32 {
33  memset(&m_Log, 0, sizeof(m_Log));
34 
35  cDeviceLog::InitDeviceForWriting(pHandle, timestamp, directory, maxDiskSpace, maxFileSize, chunkSize);
36 }
37 
38 
40 {
42 
43  for (int kid = 0; kid < cDataKML::MAX_NUM_KID; kid++)
44  {
45  // Close file
46  CloseWriteFile(kid, m_Log[kid]);
47  }
48 
49  return true;
50 }
51 
52 
54 {
55  // Ensure we have data
56  int64_t dataSize = (int64_t)log.data.size();
57  if (dataSize <= 0)
58  {
59  return false;
60  }
61 
62  // Ensure directory exists
63  if (m_directory.empty())
64  {
65  return false;
66  }
67 
68  _MKDIR(m_directory.c_str());
69 
70  // Create filename
71  log.fileCount++;
72  int serNum = m_devInfo.serialNumber;
73  if (!serNum)
74  {
75  serNum = m_pHandle;
76  }
77 
78  log.fileName = GetNewFileName(serNum, log.fileCount, m_kml.GetDatasetName(kid).c_str());
79 
80 #define BUF_SIZE 100
81  char buf[BUF_SIZE];
82  int styleCnt = 1;
83  string altitudeMode;
84  string iconScale = "0.5";
85  string labelScale = "0.5";
86  string iconUrl;
87 
88  if (m_showPointTimestamps)
89  labelScale = "0.5";
90  else
91  labelScale = "0.01";
92 
93  // Altitude mode
94  if(m_altClampToGround)
95  altitudeMode = "clampToGround";
96  else
97  altitudeMode = "absolute";
98 
99  // Style
100  string styleStr, colorStr;
101 
102  iconUrl = "http://maps.google.com/mapfiles/kml/shapes/shaded_dot.png";
103  // iconUrl = "http://earth.google.com/images/kml-icons/track-directional/track-none.png";
104 
105  // colors are ABGR
106  switch (kid)
107  {
108  case cDataKML::KID_INS:
109  iconUrl = "http://earth.google.com/images/kml-icons/track-directional/track-0.png";
110  colorStr = "ff00ffff"; // yellow
111  break;
112  case cDataKML::KID_GPS:
113  colorStr = "ff0000ff"; // red
114  break;
115  case cDataKML::KID_GPS1:
116  colorStr = "ffff0000"; // blue
117  break;
118  case cDataKML::KID_RTK:
119  colorStr = "ffffff00"; // cyan
120  break;
121  case cDataKML::KID_REF:
122  iconUrl = "http://earth.google.com/images/kml-icons/track-directional/track-0.png";
123  colorStr = "ffff00ff"; // magenta
124  break;
125  }
126 
127  // Add XML version info and document
129  *Style, *LineStyle, *IconStyle, *LabelStyle,
130  *Placemark, *Point, *LineString,
131  *heading,
132  *elem, *href;
133 
134  TiXmlDocument tDoc;
135 
136  TiXmlDeclaration* decl = new TiXmlDeclaration("1.0", "UTF-8", "");
137  tDoc.LinkEndChild(decl);
138 
139  TiXmlElement* kml = new TiXmlElement("kml");
140  tDoc.LinkEndChild(kml);
141 
142  TiXmlElement* Document = new TiXmlElement("Document");
143  kml->LinkEndChild(Document);
144  kml->SetAttribute("xmlns", "http://www.opengis.net/kml/2.2");
145  kml->SetAttribute("xmlns:gx", "http://www.google.com/kml/ext/2.2");
146 
147  // Show sample (dot)
148  if (m_showPoints)
149  {
150  // Style
151  styleStr = string("stylesel_");
152 
153  Style = new TiXmlElement("Style");
154  Style->SetAttribute("id", styleStr);
155  Document->LinkEndChild(Style);
156 
157  // Icon style
158  IconStyle = new TiXmlElement("IconStyle");
159  Style->LinkEndChild(IconStyle);
160 
161  elem = new TiXmlElement("color");
162  elem->LinkEndChild(new TiXmlText(colorStr));
163  IconStyle->LinkEndChild(elem);
164 
165  elem = new TiXmlElement("colorMode");
166  elem->LinkEndChild(new TiXmlText("normal"));
167  IconStyle->LinkEndChild(elem);
168 
169  elem = new TiXmlElement("scale");
170  elem->LinkEndChild(new TiXmlText(iconScale));
171  IconStyle->LinkEndChild(elem);
172 
173  heading = new TiXmlElement("heading");
174  heading->LinkEndChild(new TiXmlText("0"));
175  IconStyle->LinkEndChild(heading);
176 
177  href = new TiXmlElement("href");
178  href->LinkEndChild(new TiXmlText(iconUrl));
179  elem = new TiXmlElement("Icon");
180  elem->LinkEndChild(href);
181  IconStyle->LinkEndChild(elem);
182 
183  // Label style
184  LabelStyle = new TiXmlElement("LabelStyle");
185  Style->LinkEndChild(LabelStyle);
186 
187  elem = new TiXmlElement("colorMode");
188  elem->LinkEndChild(new TiXmlText("normal"));
189  LabelStyle->LinkEndChild(elem);
190 
191  elem = new TiXmlElement("scale");
192  elem->LinkEndChild(new TiXmlText(labelScale));
193  LabelStyle->LinkEndChild(elem);
194 
195 
196  double nextTime = log.data[0].time;
197  for (size_t i = 0; i < log.data.size(); i++)
198  {
199  sKmlLogData& item = (log.data[i]);
200 
201  // Log only every iconUpdatePeriodSec
202  if (item.time < nextTime)
203  {
204  continue;
205  }
206  nextTime = item.time - fmod(item.time, m_pointUpdatePeriodSec) + m_pointUpdatePeriodSec;
207 
208  // Placemark
209  Placemark = new TiXmlElement("Placemark");
210  Document->LinkEndChild(Placemark);
211 
212  // Name
213  elem = new TiXmlElement("name");
214  ostringstream timeStream;
215  switch (kid)
216  {
217  case cDataKML::KID_GPS:
218  case cDataKML::KID_GPS1:
219  case cDataKML::KID_GPS2:
220  case cDataKML::KID_RTK:
221  timeStream << fixed << setprecision(1) << item.time;
222  break;
223  default:
224  timeStream << fixed << setprecision(3) << item.time;
225  break;
226  }
227  elem->LinkEndChild(new TiXmlText(timeStream.str()));
228  Placemark->LinkEndChild(elem);
229 
230  // styleUrl
231  elem = new TiXmlElement("styleUrl");
232  if (item.theta[2] != 0.0f)
233  { // Style - to indicate heading
234  string styleCntStr = styleStr + to_string(styleCnt++);
235  TiXmlNode *StyleNode = Style->Clone();
236  StyleNode->ToElement()->SetAttribute("id", styleCntStr);
237  StyleNode->FirstChildElement("IconStyle")->FirstChildElement("heading")->FirstChild()->ToText()->SetValue(to_string(item.theta[2] * C_RAD2DEG_F));
238  Document->LinkEndChild(StyleNode);
239 
240  elem->LinkEndChild(new TiXmlText("#" + styleCntStr));
241  }
242  else
243  {
244  elem->LinkEndChild(new TiXmlText("#" + styleStr));
245  }
246  Placemark->LinkEndChild(elem);
247 
248  Point = new TiXmlElement("Point");
249  Placemark->LinkEndChild(Point);
250 
251  elem = new TiXmlElement("coordinates");
252 #if 1
253  double lat = _CLAMP(item.lla[0] * DEG2RADMULT, -C_PIDIV2, C_PIDIV2) * RAD2DEGMULT;
254  double lon = _CLAMP(item.lla[1] * DEG2RADMULT, -C_PI, C_PI) * RAD2DEGMULT;
255  double alt = _CLAMP(item.lla[2], -1000, 100000);
256  snprintf(buf, BUF_SIZE, "%.8lf,%.8lf,%.3lf", lon, lat, alt);
257  elem->LinkEndChild(new TiXmlText(buf));
258 #else
259  ostringstream coordinateStream; // Not getting digits of precision
260  coordinateStream
261  << fixed
262  << setprecision(8)
263  << item->lla[1] << "," // Lat
264  << item->lla[0] << "," // Lon
265  << setprecision(3)
266  << item->lla[2] << " "; // Alt
267  elem->LinkEndChild(new TiXmlText(coordinateStream.str()));
268 #endif
269  Point->LinkEndChild(elem);
270 
271  elem = new TiXmlElement("altitudeMode");
272  elem->LinkEndChild(new TiXmlText(altitudeMode));
273  Point->LinkEndChild(elem);
274  }
275  }// if (m_showSample)
276 
277 
278  // Show path (track)
279  if (m_showTracks)
280  {
281  // Track style
282  styleStr = string("stylesel_") + to_string(styleCnt++);
283 
284  Style = new TiXmlElement("Style");
285  Style->SetAttribute("id", styleStr);
286  Document->LinkEndChild(Style);
287 
288  LineStyle = new TiXmlElement("LineStyle");
289  Style->LinkEndChild(LineStyle);
290 
291  elem = new TiXmlElement("color");
292  elem->LinkEndChild(new TiXmlText(colorStr));
293  LineStyle->LinkEndChild(elem);
294 
295  elem = new TiXmlElement("colorMode");
296  elem->LinkEndChild(new TiXmlText("normal"));
297  LineStyle->LinkEndChild(elem);
298 
299  elem = new TiXmlElement("width");
300  elem->LinkEndChild(new TiXmlText("2"));
301  LineStyle->LinkEndChild(elem);
302 
303  // Track
304  Placemark = new TiXmlElement("Placemark");
305  Document->LinkEndChild(Placemark);
306 
307  elem = new TiXmlElement("name");
308  elem->LinkEndChild(new TiXmlText("Tracks"));
309  Placemark->LinkEndChild(elem);
310 
311  elem = new TiXmlElement("description");
312  elem->LinkEndChild(new TiXmlText("SN tracks"));
313  Placemark->LinkEndChild(elem);
314 
315  elem = new TiXmlElement("styleUrl");
316  elem->LinkEndChild(new TiXmlText("#" + styleStr));
317  Placemark->LinkEndChild(elem);
318 
319  LineString = new TiXmlElement("LineString");
320  Placemark->LinkEndChild(LineString);
321 
322  ostringstream coordinateStream;
323  int j = 0;
324  for (size_t i = 0; i < log.data.size(); i++)
325  {
326  sKmlLogData& item = (log.data[i]);
327  double lat = _CLAMP(item.lla[0] * DEG2RADMULT, -C_PIDIV2, C_PIDIV2) * RAD2DEGMULT;
328  double lon = _CLAMP(item.lla[1] * DEG2RADMULT, -C_PI, C_PI) * RAD2DEGMULT;
329  double alt = _CLAMP(item.lla[2], -1000, 100000);
330 
331  if (i >= log.data.size()-2)
332  {
333  j++;
334  }
335 
336  snprintf(buf, BUF_SIZE, "%.8lf,%.8lf,%.3lf ", lon, lat, alt);
337  if (strcmp("-111.65863637,40.05570543,1418.282 ", buf) == 0)
338  {
339  j++;
340  }
341 // qDebug() << string(buf);
342 // std::cout << "Value of str is : ";
343  coordinateStream << string(buf);
344  }
345 
346  elem = new TiXmlElement("coordinates");
347  elem->LinkEndChild(new TiXmlText(coordinateStream.str()));
348  LineString->LinkEndChild(elem);
349 
350  elem = new TiXmlElement("extrude");
351  elem->LinkEndChild(new TiXmlText("1"));
352  LineString->LinkEndChild(elem);
353 
354  elem = new TiXmlElement("altitudeMode");
355  elem->LinkEndChild(new TiXmlText(altitudeMode));
356  LineString->LinkEndChild(elem);
357  }
358 
359  // Write XML to file
360  if (!tDoc.SaveFile(log.fileName.c_str()))
361  {
362  return false;
363  }
364 
365  // Remove data
366  log.data.clear();
367 
368  return true;
369 }
370 
371 
373 {
374 
375 #if PLATFORM_IS_WINDOWS
376 
377  for (int kid = 0; kid < cDataKML::MAX_NUM_KID; kid++)
378  {
379  sKmlLog &log = m_Log[kid];
380 
381  if (log.fileName.empty())
382  {
383  continue;
384  }
385 
386  std::wstring stemp = std::wstring(log.fileName.begin(), log.fileName.end());
387  LPCWSTR filename = stemp.c_str();
388  ShellExecuteW(0, 0, filename, 0, 0, SW_SHOW);
389  }
390 
391 #endif
392 
393  return true;
394 }
395 
396 
397 bool cDeviceLogKML::SaveData(p_data_hdr_t *dataHdr, const uint8_t *dataBuf)
398 {
399  cDeviceLog::SaveData(dataHdr, dataBuf);
400 
401  // Save data to file
402  if (!WriteDateToFile(dataHdr, dataBuf))
403  {
404  return false;
405  }
406 
407  // Convert formats
408  uDatasets& d = (uDatasets&)(*dataBuf);
409  switch (dataHdr->id)
410  {
411  case DID_INS_2:
412  ins_1_t ins1;
413  ins1.week = d.ins2.week;
414  ins1.timeOfWeek = d.ins2.timeOfWeek;
415  ins1.hdwStatus = d.ins2.hdwStatus;
416  ins1.insStatus = d.ins2.insStatus;
417  quat2euler(d.ins2.qn2b, ins1.theta);
418  memcpy(ins1.uvw, d.ins2.uvw, 12);
419  memcpy(ins1.lla, d.ins2.lla, 24);
420  p_data_hdr_t dHdr = { DID_INS_1 , sizeof(ins_1_t), 0 };
421  // Save data to file
422  WriteDateToFile(&dHdr, (uint8_t*)&ins1);
423  break;
424  }
425 
426  return true;
427 }
428 
429 
430 bool cDeviceLogKML::WriteDateToFile(const p_data_hdr_t *dataHdr, const uint8_t* dataBuf)
431 {
432  int kid = cDataKML::DID_TO_KID(dataHdr->id);
433 
434  // Only use selected data
435  if (kid < 0)
436  {
437  return true;
438  }
439 
440  // Reference current log
441  sKmlLog &log = m_Log[kid];
442 
443  // Write date to file
444  m_kml.WriteDataToFile(log.data, dataHdr, dataBuf);
445 
446  // File byte size
447  int nBytes = (int)(log.data.size() * cDataKML::BYTES_PER_KID(kid));
448  log.fileSize = nBytes;
449  m_fileSize = _MAX(m_fileSize, log.fileSize);
450  m_logSize = nBytes;
451 
452  if (log.fileSize >= m_maxFileSize)
453  {
454  // Close existing file
455  CloseWriteFile(kid, log);
456  }
457 
458  return true;
459 }
460 
461 
463 {
464  p_data_t* data = NULL;
465 
466  // Read data from chunk
467  while (!(data = ReadDataFromChunk()))
468  {
469  // Read next chunk from file
470  if (!ReadChunkFromFile())
471  {
472  return NULL;
473  }
474  }
475 
476  // Read is good
478  return data;
479 }
480 
481 
482 p_data_t* cDeviceLogKML::ReadDataFromChunk()
483 {
484  return NULL;
485 }
486 
487 
488 bool cDeviceLogKML::ReadChunkFromFile()
489 {
490  return true;
491 }
492 
493 
494 void cDeviceLogKML::SetSerialNumber(uint32_t serialNumber)
495 {
496  m_devInfo.serialNumber = serialNumber;
497 }
498 
499 
500 
uint32_t week
Definition: data_sets.h:412
+Go to the documentation of this file.
1 /*
2 MIT LICENSE
3 
4 Copyright 2014 Inertial Sense, LLC - http://inertialsense.com
5 
6 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files(the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions :
7 
8 The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
9 
10 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
11 */
12 
13 #include <ctime>
14 #include <string>
15 #include <sstream>
16 #include <sys/types.h>
17 #include <sys/stat.h>
18 #include <iomanip>
19 #include <iostream>
20 #include <fstream>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <stddef.h>
24 #include "ISPose.h"
25 #include "DeviceLogKML.h"
26 #include "ISLogger.h"
27 #include "ISConstants.h"
28 
29 using namespace std;
30 
31 void cDeviceLogKML::InitDeviceForWriting(int pHandle, std::string timestamp, std::string directory, uint64_t maxDiskSpace, uint32_t maxFileSize, uint32_t chunkSize)
32 {
33  memset(&m_Log, 0, sizeof(m_Log));
34 
35  cDeviceLog::InitDeviceForWriting(pHandle, timestamp, directory, maxDiskSpace, maxFileSize, chunkSize);
36 }
37 
38 
40 {
42 
43  for (int kid = 0; kid < cDataKML::MAX_NUM_KID; kid++)
44  {
45  // Close file
46  CloseWriteFile(kid, m_Log[kid]);
47  }
48 
49  return true;
50 }
51 
52 
54 {
55  // Ensure we have data
56  int64_t dataSize = (int64_t)log.data.size();
57  if (dataSize <= 0)
58  {
59  return false;
60  }
61 
62  // Ensure directory exists
63  if (m_directory.empty())
64  {
65  return false;
66  }
67 
68  _MKDIR(m_directory.c_str());
69 
70  // Create filename
71  log.fileCount++;
72  int serNum = m_devInfo.serialNumber;
73  if (!serNum)
74  {
75  serNum = m_pHandle;
76  }
77 
78  log.fileName = GetNewFileName(serNum, log.fileCount, m_kml.GetDatasetName(kid).c_str());
79 
80 #define BUF_SIZE 100
81  char buf[BUF_SIZE];
82  int styleCnt = 1;
83  string altitudeMode;
84  string iconScale = "0.5";
85  string labelScale = "0.5";
86  string iconUrl;
87 
88  if (m_showPointTimestamps)
89  labelScale = "0.5";
90  else
91  labelScale = "0.01";
92 
93  // Altitude mode
94  if(m_altClampToGround)
95  altitudeMode = "clampToGround";
96  else
97  altitudeMode = "absolute";
98 
99  // Style
100  string styleStr, colorStr;
101 
102  iconUrl = "http://maps.google.com/mapfiles/kml/shapes/shaded_dot.png";
103  // iconUrl = "http://earth.google.com/images/kml-icons/track-directional/track-none.png";
104 
105  // colors are ABGR
106  switch (kid)
107  {
108  case cDataKML::KID_INS:
109  iconUrl = "http://earth.google.com/images/kml-icons/track-directional/track-0.png";
110  colorStr = "ff00ffff"; // yellow
111  break;
112  case cDataKML::KID_GPS:
113  colorStr = "ff0000ff"; // red
114  break;
115  case cDataKML::KID_GPS1:
116  colorStr = "ffff0000"; // blue
117  break;
118  case cDataKML::KID_RTK:
119  colorStr = "ffffff00"; // cyan
120  break;
121  case cDataKML::KID_REF:
122  iconUrl = "http://earth.google.com/images/kml-icons/track-directional/track-0.png";
123  colorStr = "ffff00ff"; // magenta
124  break;
125  }
126 
127  // Add XML version info and document
129  *Style, *LineStyle, *IconStyle, *LabelStyle,
130  *Placemark, *Point, *LineString,
131  *heading,
132  *elem, *href;
133 
134  TiXmlDocument tDoc;
135 
136  TiXmlDeclaration* decl = new TiXmlDeclaration("1.0", "UTF-8", "");
137  tDoc.LinkEndChild(decl);
138 
139  TiXmlElement* kml = new TiXmlElement("kml");
140  tDoc.LinkEndChild(kml);
141 
142  TiXmlElement* Document = new TiXmlElement("Document");
143  kml->LinkEndChild(Document);
144  kml->SetAttribute("xmlns", "http://www.opengis.net/kml/2.2");
145  kml->SetAttribute("xmlns:gx", "http://www.google.com/kml/ext/2.2");
146 
147  // Show sample (dot)
148  if (m_showPoints)
149  {
150  // Style
151  styleStr = string("stylesel_");
152 
153  Style = new TiXmlElement("Style");
154  Style->SetAttribute("id", styleStr);
155  Document->LinkEndChild(Style);
156 
157  // Icon style
158  IconStyle = new TiXmlElement("IconStyle");
159  Style->LinkEndChild(IconStyle);
160 
161  elem = new TiXmlElement("color");
162  elem->LinkEndChild(new TiXmlText(colorStr));
163  IconStyle->LinkEndChild(elem);
164 
165  elem = new TiXmlElement("colorMode");
166  elem->LinkEndChild(new TiXmlText("normal"));
167  IconStyle->LinkEndChild(elem);
168 
169  elem = new TiXmlElement("scale");
170  elem->LinkEndChild(new TiXmlText(iconScale));
171  IconStyle->LinkEndChild(elem);
172 
173  heading = new TiXmlElement("heading");
174  heading->LinkEndChild(new TiXmlText("0"));
175  IconStyle->LinkEndChild(heading);
176 
177  href = new TiXmlElement("href");
178  href->LinkEndChild(new TiXmlText(iconUrl));
179  elem = new TiXmlElement("Icon");
180  elem->LinkEndChild(href);
181  IconStyle->LinkEndChild(elem);
182 
183  // Label style
184  LabelStyle = new TiXmlElement("LabelStyle");
185  Style->LinkEndChild(LabelStyle);
186 
187  elem = new TiXmlElement("colorMode");
188  elem->LinkEndChild(new TiXmlText("normal"));
189  LabelStyle->LinkEndChild(elem);
190 
191  elem = new TiXmlElement("scale");
192  elem->LinkEndChild(new TiXmlText(labelScale));
193  LabelStyle->LinkEndChild(elem);
194 
195 
196  double nextTime = log.data[0].time;
197  for (size_t i = 0; i < log.data.size(); i++)
198  {
199  sKmlLogData& item = (log.data[i]);
200 
201  // Log only every iconUpdatePeriodSec
202  if (item.time < nextTime)
203  {
204  continue;
205  }
206  nextTime = item.time - fmod(item.time, m_pointUpdatePeriodSec) + m_pointUpdatePeriodSec;
207 
208  // Placemark
209  Placemark = new TiXmlElement("Placemark");
210  Document->LinkEndChild(Placemark);
211 
212  // Name
213  elem = new TiXmlElement("name");
214  ostringstream timeStream;
215  switch (kid)
216  {
217  case cDataKML::KID_GPS:
218  case cDataKML::KID_GPS1:
219  case cDataKML::KID_GPS2:
220  case cDataKML::KID_RTK:
221  timeStream << fixed << setprecision(1) << item.time;
222  break;
223  default:
224  timeStream << fixed << setprecision(3) << item.time;
225  break;
226  }
227  elem->LinkEndChild(new TiXmlText(timeStream.str()));
228  Placemark->LinkEndChild(elem);
229 
230  // styleUrl
231  elem = new TiXmlElement("styleUrl");
232  if (item.theta[2] != 0.0f)
233  { // Style - to indicate heading
234  string styleCntStr = styleStr + to_string(styleCnt++);
235  TiXmlNode *StyleNode = Style->Clone();
236  StyleNode->ToElement()->SetAttribute("id", styleCntStr);
237  StyleNode->FirstChildElement("IconStyle")->FirstChildElement("heading")->FirstChild()->ToText()->SetValue(to_string(item.theta[2] * C_RAD2DEG_F));
238  Document->LinkEndChild(StyleNode);
239 
240  elem->LinkEndChild(new TiXmlText("#" + styleCntStr));
241  }
242  else
243  {
244  elem->LinkEndChild(new TiXmlText("#" + styleStr));
245  }
246  Placemark->LinkEndChild(elem);
247 
248  Point = new TiXmlElement("Point");
249  Placemark->LinkEndChild(Point);
250 
251  elem = new TiXmlElement("coordinates");
252 #if 1
253  double lat = _CLAMP(item.lla[0] * DEG2RADMULT, -C_PIDIV2, C_PIDIV2) * RAD2DEGMULT;
254  double lon = _CLAMP(item.lla[1] * DEG2RADMULT, -C_PI, C_PI) * RAD2DEGMULT;
255  double alt = _CLAMP(item.lla[2], -1000, 100000);
256  snprintf(buf, BUF_SIZE, "%.8lf,%.8lf,%.3lf", lon, lat, alt);
257  elem->LinkEndChild(new TiXmlText(buf));
258 #else
259  ostringstream coordinateStream; // Not getting digits of precision
260  coordinateStream
261  << fixed
262  << setprecision(8)
263  << item->lla[1] << "," // Lat
264  << item->lla[0] << "," // Lon
265  << setprecision(3)
266  << item->lla[2] << " "; // Alt
267  elem->LinkEndChild(new TiXmlText(coordinateStream.str()));
268 #endif
269  Point->LinkEndChild(elem);
270 
271  elem = new TiXmlElement("altitudeMode");
272  elem->LinkEndChild(new TiXmlText(altitudeMode));
273  Point->LinkEndChild(elem);
274  }
275  }// if (m_showSample)
276 
277 
278  // Show path (track)
279  if (m_showTracks)
280  {
281  // Track style
282  styleStr = string("stylesel_") + to_string(styleCnt++);
283 
284  Style = new TiXmlElement("Style");
285  Style->SetAttribute("id", styleStr);
286  Document->LinkEndChild(Style);
287 
288  LineStyle = new TiXmlElement("LineStyle");
289  Style->LinkEndChild(LineStyle);
290 
291  elem = new TiXmlElement("color");
292  elem->LinkEndChild(new TiXmlText(colorStr));
293  LineStyle->LinkEndChild(elem);
294 
295  elem = new TiXmlElement("colorMode");
296  elem->LinkEndChild(new TiXmlText("normal"));
297  LineStyle->LinkEndChild(elem);
298 
299  elem = new TiXmlElement("width");
300  elem->LinkEndChild(new TiXmlText("2"));
301  LineStyle->LinkEndChild(elem);
302 
303  // Track
304  Placemark = new TiXmlElement("Placemark");
305  Document->LinkEndChild(Placemark);
306 
307  elem = new TiXmlElement("name");
308  elem->LinkEndChild(new TiXmlText("Tracks"));
309  Placemark->LinkEndChild(elem);
310 
311  elem = new TiXmlElement("description");
312  elem->LinkEndChild(new TiXmlText("SN tracks"));
313  Placemark->LinkEndChild(elem);
314 
315  elem = new TiXmlElement("styleUrl");
316  elem->LinkEndChild(new TiXmlText("#" + styleStr));
317  Placemark->LinkEndChild(elem);
318 
319  LineString = new TiXmlElement("LineString");
320  Placemark->LinkEndChild(LineString);
321 
322  ostringstream coordinateStream;
323  int j = 0;
324  for (size_t i = 0; i < log.data.size(); i++)
325  {
326  sKmlLogData& item = (log.data[i]);
327  double lat = _CLAMP(item.lla[0] * DEG2RADMULT, -C_PIDIV2, C_PIDIV2) * RAD2DEGMULT;
328  double lon = _CLAMP(item.lla[1] * DEG2RADMULT, -C_PI, C_PI) * RAD2DEGMULT;
329  double alt = _CLAMP(item.lla[2], -1000, 100000);
330 
331  if (i >= log.data.size()-2)
332  {
333  j++;
334  }
335 
336  snprintf(buf, BUF_SIZE, "%.8lf,%.8lf,%.3lf ", lon, lat, alt);
337  if (strcmp("-111.65863637,40.05570543,1418.282 ", buf) == 0)
338  {
339  j++;
340  }
341 // qDebug() << string(buf);
342 // std::cout << "Value of str is : ";
343  coordinateStream << string(buf);
344  }
345 
346  elem = new TiXmlElement("coordinates");
347  elem->LinkEndChild(new TiXmlText(coordinateStream.str()));
348  LineString->LinkEndChild(elem);
349 
350  elem = new TiXmlElement("extrude");
351  elem->LinkEndChild(new TiXmlText("1"));
352  LineString->LinkEndChild(elem);
353 
354  elem = new TiXmlElement("altitudeMode");
355  elem->LinkEndChild(new TiXmlText(altitudeMode));
356  LineString->LinkEndChild(elem);
357  }
358 
359  // Write XML to file
360  if (!tDoc.SaveFile(log.fileName.c_str()))
361  {
362  return false;
363  }
364 
365  // Remove data
366  log.data.clear();
367 
368  return true;
369 }
370 
371 
373 {
374 
375 #if PLATFORM_IS_WINDOWS
376 
377  for (int kid = 0; kid < cDataKML::MAX_NUM_KID; kid++)
378  {
379  sKmlLog &log = m_Log[kid];
380 
381  if (log.fileName.empty())
382  {
383  continue;
384  }
385 
386  std::wstring stemp = std::wstring(log.fileName.begin(), log.fileName.end());
387  LPCWSTR filename = stemp.c_str();
388  ShellExecuteW(0, 0, filename, 0, 0, SW_SHOW);
389  }
390 
391 #endif
392 
393  return true;
394 }
395 
396 
397 bool cDeviceLogKML::SaveData(p_data_hdr_t *dataHdr, const uint8_t *dataBuf)
398 {
399  cDeviceLog::SaveData(dataHdr, dataBuf);
400 
401  // Save data to file
402  if (!WriteDateToFile(dataHdr, dataBuf))
403  {
404  return false;
405  }
406 
407  // Convert formats
408  uDatasets& d = (uDatasets&)(*dataBuf);
409  switch (dataHdr->id)
410  {
411  case DID_INS_2:
412  ins_1_t ins1;
413  ins1.week = d.ins2.week;
414  ins1.timeOfWeek = d.ins2.timeOfWeek;
415  ins1.hdwStatus = d.ins2.hdwStatus;
416  ins1.insStatus = d.ins2.insStatus;
417  quat2euler(d.ins2.qn2b, ins1.theta);
418  memcpy(ins1.uvw, d.ins2.uvw, 12);
419  memcpy(ins1.lla, d.ins2.lla, 24);
420  p_data_hdr_t dHdr = { DID_INS_1 , sizeof(ins_1_t), 0 };
421  // Save data to file
422  WriteDateToFile(&dHdr, (uint8_t*)&ins1);
423  break;
424  }
425 
426  return true;
427 }
428 
429 
430 bool cDeviceLogKML::WriteDateToFile(const p_data_hdr_t *dataHdr, const uint8_t* dataBuf)
431 {
432  int kid = cDataKML::DID_TO_KID(dataHdr->id);
433 
434  // Only use selected data
435  if (kid < 0)
436  {
437  return true;
438  }
439 
440  // Reference current log
441  sKmlLog &log = m_Log[kid];
442 
443  // Write date to file
444  m_kml.WriteDataToFile(log.data, dataHdr, dataBuf);
445 
446  // File byte size
447  int nBytes = (int)(log.data.size() * cDataKML::BYTES_PER_KID(kid));
448  log.fileSize = nBytes;
449  m_fileSize = _MAX(m_fileSize, log.fileSize);
450  m_logSize = nBytes;
451 
452  if (log.fileSize >= m_maxFileSize)
453  {
454  // Close existing file
455  CloseWriteFile(kid, log);
456  }
457 
458  return true;
459 }
460 
461 
463 {
464  p_data_t* data = NULL;
465 
466  // Read data from chunk
467  while (!(data = ReadDataFromChunk()))
468  {
469  // Read next chunk from file
470  if (!ReadChunkFromFile())
471  {
472  return NULL;
473  }
474  }
475 
476  // Read is good
478  return data;
479 }
480 
481 
482 p_data_t* cDeviceLogKML::ReadDataFromChunk()
483 {
484  return NULL;
485 }
486 
487 
488 bool cDeviceLogKML::ReadChunkFromFile()
489 {
490  return true;
491 }
492 
493 
494 void cDeviceLogKML::SetSerialNumber(uint32_t serialNumber)
495 {
496  m_devInfo.serialNumber = serialNumber;
497 }
498 
499 
500 
uint32_t week
Definition: data_sets.h:436
uint32_t fileCount
Definition: DeviceLogKML.h:30
@@ -81,15 +81,15 @@
bool OpenWithSystemApp(void) OVERRIDE
TiXmlNode * LinkEndChild(TiXmlNode *addThis)
Definition: tinyxml.cpp:186
-
#define _CLAMP(v, minV, maxV)
Definition: ISConstants.h:273
+
#define _CLAMP(v, minV, maxV)
Definition: ISConstants.h:270
bool SaveData(p_data_hdr_t *dataHdr, const uint8_t *dataBuf) OVERRIDE
-
double timeOfWeek
Definition: data_sets.h:415
+
double timeOfWeek
Definition: data_sets.h:439
uint32_t id
Definition: ISComm.h:481
-
ins_2_t ins2
Definition: data_sets.h:2400
+
ins_2_t ins2
Definition: data_sets.h:2430
#define DID_INS_1
Definition: data_sets.h:38
-
#define C_PIDIV2
Definition: ISConstants.h:485
-
double lla[3]
Definition: data_sets.h:430
+
#define C_PIDIV2
Definition: ISConstants.h:482
+
double lla[3]
Definition: data_sets.h:454
bool SaveFile() const
Save a file using the current document value. Returns true if successful.
Definition: tinyxml.cpp:960
@@ -97,7 +97,7 @@
bool CloseWriteFile(int kid, sKmlLog &log)
#define DID_INS_2
Definition: data_sets.h:39
std::string fileName
Definition: DeviceLogKML.h:29
-
float theta[3]
Definition: data_sets.h:424
+
float theta[3]
Definition: data_sets.h:448
double time
Definition: DataKML.h:31
virtual bool CloseAllFiles()
Definition: DeviceLog.cpp:80
@@ -110,20 +110,20 @@
virtual const TiXmlText * ToText() const
Cast to a more defined type. Will return null if not of the requested type.
Definition: tinyxml.h:707
std::vector< sKmlLogData > data
Definition: DeviceLogKML.h:27
const TiXmlNode * FirstChild() const
The first child of this node. Will be null if there are no children.
Definition: tinyxml.h:528
-
#define C_PI
Definition: ISConstants.h:486
+
#define C_PI
Definition: ISConstants.h:483
virtual const TiXmlElement * ToElement() const
Cast to a more defined type. Will return null if not of the requested type.
Definition: tinyxml.h:704
virtual bool SaveData(p_data_hdr_t *dataHdr, const uint8_t *dataBuf)
Definition: DeviceLog.cpp:104
void InitDeviceForWriting(int pHandle, std::string timestamp, std::string directory, uint64_t maxDiskSpace, uint32_t maxFileSize, uint32_t chunkSize) OVERRIDE
-
float qn2b[4]
Definition: data_sets.h:453
+
float qn2b[4]
Definition: data_sets.h:477
static int DID_TO_KID(int did)
Definition: DataKML.h:71
-
float uvw[3]
Definition: data_sets.h:427
+
float uvw[3]
Definition: data_sets.h:451
void quat2euler(const Quat_t q, Euler_t theta)
Definition: ISPose.c:185
-
uint32_t insStatus
Definition: data_sets.h:418
+
uint32_t insStatus
Definition: data_sets.h:442
-
uint32_t hdwStatus
Definition: data_sets.h:421
+
uint32_t hdwStatus
Definition: data_sets.h:445
const TiXmlElement * FirstChildElement() const
Convenience function to get through elements.
Definition: tinyxml.cpp:452
-
#define RAD2DEGMULT
Definition: ISConstants.h:326
+
#define RAD2DEGMULT
Definition: ISConstants.h:323
static int BYTES_PER_KID(int kid)
Definition: DataKML.h:84
void SetAttribute(const char *name, const char *_value)
Definition: tinyxml.cpp:780
@@ -136,15 +136,15 @@
p_data_t * ReadData() OVERRIDE
-
#define C_RAD2DEG_F
Definition: ISConstants.h:503
+
#define C_RAD2DEG_F
Definition: ISConstants.h:500
void SetSerialNumber(uint32_t serialNumber) OVERRIDE
bool CloseAllFiles() OVERRIDE
-
#define _MKDIR(dir)
Definition: ISConstants.h:203
+
#define _MKDIR(dir)
Definition: ISConstants.h:200
double lla[3]
Definition: DataKML.h:32
-
#define DEG2RADMULT
Definition: ISConstants.h:323
- -
#define _MAX(a, b)
Definition: ISConstants.h:265
+
#define DEG2RADMULT
Definition: ISConstants.h:320
+ +
#define _MAX(a, b)
Definition: ISConstants.h:262
diff --git a/docs/html/_device_log_k_m_l_8h.html b/docs/html/_device_log_k_m_l_8h.html index 6f10568ed..2971e6f89 100644 --- a/docs/html/_device_log_k_m_l_8h.html +++ b/docs/html/_device_log_k_m_l_8h.html @@ -23,7 +23,7 @@ Logo
SDK -  Release 1.6.2 +  Release 1.6.4
Communications, logger, and bootloader libraries.
diff --git a/docs/html/_device_log_k_m_l_8h_source.html b/docs/html/_device_log_k_m_l_8h_source.html index 192d00deb..6d1f5ea21 100644 --- a/docs/html/_device_log_k_m_l_8h_source.html +++ b/docs/html/_device_log_k_m_l_8h_source.html @@ -23,7 +23,7 @@ Logo
SDK -  Release 1.6.2 +  Release 1.6.4
Communications, logger, and bootloader libraries.
@@ -83,7 +83,7 @@
uint32_t fileSize
Definition: DeviceLogKML.h:32
std::vector< sKmlLogData > data
Definition: DeviceLogKML.h:27
-
#define OVERRIDE
Definition: ISConstants.h:377
+
#define OVERRIDE
Definition: ISConstants.h:374
void InitDeviceForWriting(int pHandle, std::string timestamp, std::string directory, uint64_t maxDiskSpace, uint32_t maxFileSize, uint32_t chunkSize) OVERRIDE
bool OpenNewSaveFile()
Definition: DeviceLog.cpp:135
diff --git a/docs/html/_device_log_serial_8cpp.html b/docs/html/_device_log_serial_8cpp.html index 03e4c7edc..cb6f7b3b5 100644 --- a/docs/html/_device_log_serial_8cpp.html +++ b/docs/html/_device_log_serial_8cpp.html @@ -23,7 +23,7 @@ Logo
SDK -  Release 1.6.2 +  Release 1.6.4
Communications, logger, and bootloader libraries.
diff --git a/docs/html/_device_log_serial_8cpp_source.html b/docs/html/_device_log_serial_8cpp_source.html index d1bc2d963..903e7373a 100644 --- a/docs/html/_device_log_serial_8cpp_source.html +++ b/docs/html/_device_log_serial_8cpp_source.html @@ -23,7 +23,7 @@ Logo
SDK -  Release 1.6.2 +  Release 1.6.4
Communications, logger, and bootloader libraries.
diff --git a/docs/html/_device_log_serial_8h.html b/docs/html/_device_log_serial_8h.html index 132eb5c68..49975d8a1 100644 --- a/docs/html/_device_log_serial_8h.html +++ b/docs/html/_device_log_serial_8h.html @@ -23,7 +23,7 @@ Logo
SDK -  Release 1.6.2 +  Release 1.6.4
Communications, logger, and bootloader libraries.
diff --git a/docs/html/_device_log_serial_8h_source.html b/docs/html/_device_log_serial_8h_source.html index 30e97dcce..051c3cfbd 100644 --- a/docs/html/_device_log_serial_8h_source.html +++ b/docs/html/_device_log_serial_8h_source.html @@ -23,7 +23,7 @@ Logo
SDK -  Release 1.6.2 +  Release 1.6.4
Communications, logger, and bootloader libraries.
@@ -81,7 +81,7 @@
virtual void Clear()
Definition: DataChunk.cpp:98
bool CloseAllFiles() OVERRIDE
-
#define OVERRIDE
Definition: ISConstants.h:377
+
#define OVERRIDE
Definition: ISConstants.h:374
p_data_t * ReadData() OVERRIDE
void SetSerialNumber(uint32_t serialNumber) OVERRIDE
diff --git a/docs/html/_device_log_sorted_8cpp.html b/docs/html/_device_log_sorted_8cpp.html index f9609cd93..b46450c27 100644 --- a/docs/html/_device_log_sorted_8cpp.html +++ b/docs/html/_device_log_sorted_8cpp.html @@ -23,7 +23,7 @@ Logo
SDK -  Release 1.6.2 +  Release 1.6.4
Communications, logger, and bootloader libraries.
diff --git a/docs/html/_device_log_sorted_8cpp_source.html b/docs/html/_device_log_sorted_8cpp_source.html index a05766a1a..fe692e945 100644 --- a/docs/html/_device_log_sorted_8cpp_source.html +++ b/docs/html/_device_log_sorted_8cpp_source.html @@ -23,7 +23,7 @@ Logo
SDK -  Release 1.6.2 +  Release 1.6.4
Communications, logger, and bootloader libraries.
@@ -75,7 +75,7 @@ Go to the documentation of this file.
1 /*
2 MIT LICENSE
3 
4 Copyright 2014 Inertial Sense, LLC - http://inertialsense.com
5 
6 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files(the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions :
7 
8 The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
9 
10 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
11 */
12 
13 #include <ctime>
14 #include <string>
15 #include <sstream>
16 #include <sys/types.h>
17 #include <sys/stat.h>
18 #include <iomanip>
19 #include <iostream>
20 #include <fstream>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <stddef.h>
24 #include <limits.h>
25 
26 #include "DeviceLogSorted.h"
27 #include "ISLogger.h"
28 
29 
30 void cDeviceLogSorted::InitDeviceForWriting(int pHandle, std::string timestamp, std::string directory, uint64_t maxDiskSpace, uint32_t maxFileSize, uint32_t chunkSize)
31 {
32  m_chunks.resize(0);
33  m_dataSerNum = 0;
34  m_lastSerNum = 0xFFFFFFFF;
35  cDeviceLog::InitDeviceForWriting(pHandle, timestamp, directory, maxDiskSpace, maxFileSize, chunkSize);
36 }
37 
38 
40 {
41  m_chunks.resize(0);
42  m_dataSerNum = 0;
43  m_lastSerNum = 0xFFFFFFFF;
45 }
46 
47 
49 {
51 
52  // Write to file and clear any non-empty chunks to file
53  for (uint32_t id = 0; id < m_chunks.size(); id++)
54  {
55  list<cSortedDataChunk>& chunkList = m_chunks[id];
56  if (chunkList.size() != 0)
57  {
58  cSortedDataChunk& chunk = chunkList.front();
59 
60  if (chunk.GetDataSize() != 0)
61  {
62  // Create new file if needed
63  if (m_pFile == NULL && !OpenNewSaveFile())
64  {
65  return false;
66  }
67 
68  // Write to file and clear chunk
69  if (chunk.WriteToFile(m_pFile, 1) <= 0)
70  {
71  return false;
72  }
73  }
74  }
75  }
76 
77  // Close existing file
78  if (m_pFile)
79  {
80  fclose(m_pFile);
81  m_pFile = NULL;
82  }
83 
84  return true;
85 }
86 
87 
88 bool cDeviceLogSorted::SaveData(p_data_hdr_t* dataHdr, const uint8_t* dataBuf)
89 {
90  cDeviceLog::SaveData(dataHdr, dataBuf);
91 
92  uint32_t id = dataHdr->id;
93 
94  if (id >= DID_MAX_COUNT)
95  {
96  return false;
97  }
98  else if (id >= m_chunks.size())
99  {
100  m_chunks.resize(id + 1);
101  }
102 
103  cSortedDataChunk* currentChunk;
104  list<cSortedDataChunk>& chunkList = m_chunks[id];
105 
106  // First time saving to this chunk
107  if (chunkList.size() == 0)
108  {
109  cSortedDataChunk newChunk = { 0 };
110  chunkList.push_back(newChunk);
111  currentChunk = &chunkList.front();
112  currentChunk->m_subHdr.dHdr = *dataHdr;
113  currentChunk->m_hdr.pHandle = m_pHandle;
114  currentChunk->m_hdr.devSerialNum = m_devInfo.serialNumber;
115  }
116  else
117  {
118  currentChunk = &chunkList.front();
119  }
120 
121  // Add serial number if available
122  if (id == DID_DEV_INFO)
123  {
124  if (!copyDataPToStructP2(&m_devInfo, dataHdr, dataBuf, sizeof(dev_info_t)))
125  {
126  int start = dataHdr->offset;
127  int end = dataHdr->offset + dataHdr->size;
128  int snOffset = offsetof(dev_info_t, serialNumber);
129 
130  // Did we get the serial number portion of devInfo?
131  if (start <= snOffset && (int)(snOffset + sizeof(uint32_t)) <= end)
132  {
133  currentChunk->m_hdr.devSerialNum = m_devInfo.serialNumber;
134  }
135  }
136  }
137 
138  // depending on devices and sources, some logs may have different size for the same id
139  // if the size changes, flush the chunk and start a new one with the new size
140  uint32_t dataBytes;
141  if (currentChunk->m_subHdr.dHdr.size != dataHdr->size || currentChunk->m_subHdr.dHdr.offset != dataHdr->offset)
142  {
143  // force a flush of the chunk and start a new chunk with the new size
144  dataBytes = UINT_MAX;
145  }
146  else
147  {
148  dataBytes = sizeof(int32_t) + dataHdr->size;
149  }
150  if (dataBytes > currentChunk->GetByteCountAvailableToWrite())
151  {
152  // Create new file if needed
153  if (m_pFile == NULL && !OpenNewSaveFile())
154  {
155  return false;
156  }
157 
158  // Byte size
159  int nBytes = currentChunk->GetDataSize();
160 
161  if (nBytes != 0)
162  {
163  // Write to file and clear chunk
164  if ((nBytes = currentChunk->WriteToFile(m_pFile, 1)) <= 0)
165  {
166  return false;
167  }
168  }
169 
170  m_fileSize += nBytes;
171  m_logSize += nBytes;
172 
173  // File is large enough to be closed
174  if (m_fileSize >= m_maxFileSize)
175  {
176  // Write and clear remaining chunks to file and close file
177  if (!CloseAllFiles())
178  {
179  return false;
180  }
181  }
182  }
183 
184  // reset data header if it changed
185  if (dataBytes == UINT_MAX)
186  {
187  currentChunk->m_subHdr.dHdr = *dataHdr;
188  }
189 
190  // Add data header and data buffer to chunk
191  if (!currentChunk->PushBack((unsigned char*)&(m_dataSerNum), sizeof(int32_t), (unsigned char*)dataBuf, dataHdr->size))
192  {
193  return false;
194  }
195  currentChunk->m_subHdr.dCount++;
196  m_dataSerNum++;
197 
198  return true;
199 }
200 
201 
202 // Re-serialize data to original order
203 // Consider using a queue where data from chunks are added on one end and the serial order # is checked on the other end.
204 // This function needs to scan across all chunk queues and find the next lowest data to pop off.
205 
206 // Read serialized data
208 {
209  p_data_t* data;
210 
211  while (1)
212  {
213  data = SerializeDataFromChunks();
214 
215  if (data)
216  {
217  // Found data
219  return data;
220  }
221 
222  // No more data
223  m_chunks.clear();
224  while (!ReadAllChunksFromFile())
225  {
226  if (!OpenNextReadFile())
227  {
228  // No more files or data
229  return NULL;
230  }
231  }
232  }
233 }
234 
235 
237 {
238 
239 tryAgain:
240 
241  uint32_t foundId = UINT_MAX;
242  uint32_t minSerialNum = UINT_MAX;
243 
244  // while there is data in any chunk, find the chunk with the next id
245  for (uint32_t id = 0; id < m_chunks.size(); id++)
246  {
247 tryChunkListAgain:
248  list<cSortedDataChunk>& chunksForId = m_chunks[id];
249  if (chunksForId.size() == 0)
250  {
251  continue;
252  }
253  cSortedDataChunk& chunk = chunksForId.front();
254  if (chunk.GetByteCountAvailableToRead() == 0)
255  {
256  chunksForId.pop_front();
257  goto tryChunkListAgain;
258  }
259  p_cnk_data_t* cnkData = (p_cnk_data_t*)chunk.GetDataPtr();
260  if (cnkData->dataSerNum < minSerialNum)
261  {
262  foundId = id;
263  minSerialNum = cnkData->dataSerNum;
264  }
265  }
266 
267  if (foundId == UINT_MAX)
268  {
269  return NULL;
270  }
271 
272  cSortedDataChunk& chunk = m_chunks[foundId].front();
273  p_cnk_data_t* cnkData = (p_cnk_data_t*)chunk.GetDataPtr();
274 
275 #if 0 // Error check for gap data serial number. Verify we didn't drop any data.
276 
277  if (m_lastSerNum == UINT_MAX)
278  {
280  }
281  if (m_dataSerNum - m_lastSerNum > 1)
282  {
283  cout << endl << "Gap in data: " << foundId << "\t" << m_dataSerNum;
284  }
286 
287 #endif
288 
289  // Increment data serial number to one larger than current
290  m_dataSerNum = cnkData->dataSerNum + 1;
291 
292  // Data fits in temp buf
293  if (chunk.m_subHdr.dHdr.size <= MAX_DATASET_SIZE)
294  {
295  // Copy data header
296  m_data.hdr = chunk.m_subHdr.dHdr;
297 
298  // Copy data buffer
299  memcpy(m_data.buf, cnkData->buf, m_data.hdr.size);
300 
301  int pSize = chunk.m_subHdr.dHdr.size + sizeof(uint32_t);
302  chunk.PopFront(pSize);
303  return &m_data;
304  }
305  else
306  {
307  perror("Data is larger than max data set size");
308  }
309 
310  goto tryAgain;
311 }
312 
313 
315 {
316  unsigned int id;
317 
318  // Reset data serial number and file data size
319  m_fileSize = 0;
320 
321  // Read chunk and append it to existing chunks of same type
322  while (ReadChunkFromFile())
323  {
325 
326  // Expand chunk vector if necessary
327  if (id >= m_chunks.size())
328  {
329  m_chunks.resize(id + 1);
330  }
331 
332  list<cSortedDataChunk>& chunkList = m_chunks[id];
333  cSortedDataChunk* currentChunk;
334 
335  if (chunkList.size() == 0)
336  {
337  // Empty source chunk, copy Header
338  cSortedDataChunk chunk = { 0 };
340 
341  // Find lowest serial number
344 
345  chunkList.push_back(chunk);
346  currentChunk = &chunkList.front();
347  }
348  else
349  {
350  currentChunk = &chunkList.back();
351  if (currentChunk->m_subHdr.dHdr.size != m_currentReadChunk.m_subHdr.dHdr.size ||
353  {
354  // chunk data size or offset change, append a new chunk
355  cSortedDataChunk chunk = { 0 };
357  chunkList.push_back(chunk);
358  currentChunk = &chunkList.back();
359  }
360  }
361 
362  // add data count
364 
365  // Make sure chunk max size is large enough
366  currentChunk->SetMaxSize(currentChunk->GetMaxSize() + m_currentReadChunk.GetDataSize());
367 
368  // Append data
370  }
371 
372  return m_fileSize != 0;
373 }
374 
375 
377 {
378  if (m_pFile == NULL)
379  {
380  return false;
381  }
382 
383  // Read chunk from file
385 
386  // Validate chunk: non-zero size and is sorted type
387  int hdrSize = sizeof(p_data_hdr_t);
388  if (nBytes < hdrSize || m_currentReadChunk.m_hdr.grpNum != 1)
389  {
390  return false;
391  }
392 
393  // Update stats
394  m_fileSize += nBytes;
395  m_logSize += nBytes;
396 
397  return true;
398 }
399 
400 
401 void cDeviceLogSorted::SetSerialNumber(uint32_t serialNumber)
402 {
403  m_devInfo.serialNumber = serialNumber;
404  if (DID_DEV_INFO > m_chunks.size())
405  {
406  m_chunks.resize(DID_DEV_INFO + 1);
407  }
408  list<cSortedDataChunk>& chunkList = m_chunks[DID_DEV_INFO];
409  for (list<cSortedDataChunk>::iterator i = chunkList.begin(); i != chunkList.end(); i++)
410  {
411  i->m_hdr.devSerialNum = serialNumber;
412  }
413 }
414 
415 
416 
417 
418 
419 
420 
uint32_t GetDataSize()
Definition: DataChunk.h:81
void OnReadData(p_data_t *data)
Definition: DeviceLog.cpp:254
-
#define _MIN(a, b)
Definition: ISConstants.h:269
+
#define _MIN(a, b)
Definition: ISConstants.h:266
int32_t ReadFromFile(FILE *pFile)
Definition: DataChunk.cpp:153
PUSH_PACK_1 struct PACKED dev_info_t
diff --git a/docs/html/_device_log_sorted_8h.html b/docs/html/_device_log_sorted_8h.html index 1e22f84e3..5d8f13e04 100644 --- a/docs/html/_device_log_sorted_8h.html +++ b/docs/html/_device_log_sorted_8h.html @@ -23,7 +23,7 @@ Logo
SDK -  Release 1.6.2 +  Release 1.6.4
Communications, logger, and bootloader libraries.
diff --git a/docs/html/_device_log_sorted_8h_source.html b/docs/html/_device_log_sorted_8h_source.html index 20ef36a8f..be0bfa55e 100644 --- a/docs/html/_device_log_sorted_8h_source.html +++ b/docs/html/_device_log_sorted_8h_source.html @@ -23,7 +23,7 @@ Logo
SDK -  Release 1.6.2 +  Release 1.6.4
Communications, logger, and bootloader libraries.
@@ -77,7 +77,7 @@
vector< list< cSortedDataChunk > > m_chunks
-
#define OVERRIDE
Definition: ISConstants.h:377
+
#define OVERRIDE
Definition: ISConstants.h:374
cSortedDataChunk m_currentReadChunk
diff --git a/docs/html/_gps_parser_8cpp.html b/docs/html/_gps_parser_8cpp.html index 8c565f4d5..6fd823580 100644 --- a/docs/html/_gps_parser_8cpp.html +++ b/docs/html/_gps_parser_8cpp.html @@ -23,7 +23,7 @@ Logo
SDK -  Release 1.6.2 +  Release 1.6.4
Communications, logger, and bootloader libraries.
diff --git a/docs/html/_gps_parser_8cpp_source.html b/docs/html/_gps_parser_8cpp_source.html index 7cb95d252..14069fc49 100644 --- a/docs/html/_gps_parser_8cpp_source.html +++ b/docs/html/_gps_parser_8cpp_source.html @@ -23,7 +23,7 @@ Logo
SDK -  Release 1.6.2 +  Release 1.6.4
Communications, logger, and bootloader libraries.
@@ -80,7 +80,7 @@
#define UBLOX_PREAMBLE2
Definition: GpsParser.cpp:22
virtual void OnError(const cGpsParser *parser, uint32_t id, uint32_t errorCode)
Definition: GpsParser.h:149
-
#define NULLPTR
Definition: ISConstants.h:380
+
#define NULLPTR
Definition: ISConstants.h:377
virtual void OnIonosphereModelUtcAlmanacReceived(const cGpsParser *parser, ion_model_utc_alm_t *ionUtcAlm)
Definition: GpsParser.h:137
DECLARE_RTCM_DESTRUCTOR(cRtcmParser)
cInertialSenseParser(iGpsParserDelegate *delegate)
Definition: GpsParser.cpp:62
@@ -92,22 +92,22 @@
virtual void OnSbsReceived(const cGpsParser *parser, const sbsmsg_t *sbs)
Definition: GpsParser.h:115
void WriteByte(uint8_t b) OVERRIDE
Definition: GpsParser.cpp:67
unsigned int getBitsAsUInt32(const unsigned char *buffer, unsigned int pos, unsigned int len)
Definition: ISComm.c:80
-
#define OVERRIDE
Definition: ISConstants.h:377
+
#define OVERRIDE
Definition: ISConstants.h:374
- +
void WriteByte(uint8_t b) OVERRIDE
Definition: GpsParser.cpp:122
cGpsParser(iGpsParserDelegate *delegate)
Definition: GpsParser.cpp:496
virtual void OnGpsEphemerisReceived(const cGpsParser *parser, const eph_t *eph, int prn)
Definition: GpsParser.h:90
-
#define BE_SWAP16(_i)
Definition: data_sets.h:2520
+
#define BE_SWAP16(_i)
Definition: data_sets.h:2553
unsigned int calculate24BitCRCQ(unsigned char *buffer, unsigned int len)
Definition: ISComm.c:27
#define UBLOX_CHECKSUM_SIZE
Definition: GpsParser.cpp:24
virtual void OnStationReceived(const cGpsParser *parser, sta_t *sta)
Definition: GpsParser.h:126
-
int64_t time
Definition: data_sets.h:1456
+
int64_t time
Definition: data_sets.h:1473
-
uGpsRawData data
Definition: data_sets.h:2126
+
uGpsRawData data
Definition: data_sets.h:2156
virtual void OnObservationReceived(const cGpsParser *parser, const obs_t *obs)
Definition: GpsParser.h:78
#define UBLOX_PREAMBLE1
Definition: GpsParser.cpp:21
#define ALLOCATE_M_RTCM
Definition: GpsParser.cpp:47
@@ -118,15 +118,15 @@
iGpsParserDelegate * GetDelegate()
Definition: GpsParser.h:193
int32_t GetReceiverIndex() const
Definition: GpsParser.h:205
eGpsParserType
Definition: GpsParser.h:34
-
obsd_t obs[MAX_OBSERVATION_COUNT_IN_RTK_MESSAGE]
Definition: data_sets.h:2089
+
obsd_t obs[MAX_OBSERVATION_COUNT_IN_RTK_MESSAGE]
Definition: data_sets.h:2119
#define INIT_M_RTCM
Definition: GpsParser.cpp:46
-
#define _ARRAY_ELEMENT_COUNT(a)
Definition: ISConstants.h:297
+
#define _ARRAY_ELEMENT_COUNT(a)
Definition: ISConstants.h:294
cUbloxParser(iGpsParserDelegate *delegate)
Definition: GpsParser.cpp:295
- +
#define INIT_M_RAW(fmt)
Definition: GpsParser.cpp:48
#define ALLOCATE_M_RAW
Definition: GpsParser.cpp:49
diff --git a/docs/html/_gps_parser_8h.html b/docs/html/_gps_parser_8h.html index 516616857..1ffc6ad4a 100644 --- a/docs/html/_gps_parser_8h.html +++ b/docs/html/_gps_parser_8h.html @@ -23,7 +23,7 @@ Logo
SDK -  Release 1.6.2 +  Release 1.6.4
Communications, logger, and bootloader libraries.
diff --git a/docs/html/_gps_parser_8h_source.html b/docs/html/_gps_parser_8h_source.html index baa59e953..745047b8f 100644 --- a/docs/html/_gps_parser_8h_source.html +++ b/docs/html/_gps_parser_8h_source.html @@ -23,7 +23,7 @@ Logo
SDK -  Release 1.6.2 +  Release 1.6.4
Communications, logger, and bootloader libraries.
@@ -76,15 +76,15 @@
virtual void OnError(const cGpsParser *parser, uint32_t id, uint32_t errorCode)
Definition: GpsParser.h:149
virtual void OnIonosphereModelUtcAlmanacReceived(const cGpsParser *parser, ion_model_utc_alm_t *ionUtcAlm)
Definition: GpsParser.h:137
void SetReceiverIndex(int32_t index)
Definition: GpsParser.h:199
- - + +
static cGpsParser * CreateParser(eGpsParserType type, iGpsParserDelegate *delegate)
Definition: GpsParser.cpp:470
virtual void OnGlonassEphemerisReceived(const cGpsParser *parser, const geph_t *geph, int prn)
Definition: GpsParser.h:103
gtime_t g_gps_latest_time
virtual void OnSbsReceived(const cGpsParser *parser, const sbsmsg_t *sbs)
Definition: GpsParser.h:115
virtual void ParseMessage(const uint8_t *data, int dataLength)
Definition: GpsParser.h:212
- +
void Write(const uint8_t *data, int dataLength)
Definition: GpsParser.h:175
cGpsParser(iGpsParserDelegate *delegate)
Definition: GpsParser.cpp:496
virtual void OnGpsEphemerisReceived(const cGpsParser *parser, const eph_t *eph, int prn)
Definition: GpsParser.h:90
@@ -92,17 +92,17 @@
virtual void OnStationReceived(const cGpsParser *parser, sta_t *sta)
Definition: GpsParser.h:126
- +
virtual void OnObservationReceived(const cGpsParser *parser, const obs_t *obs)
Definition: GpsParser.h:78
virtual void WriteByte(uint8_t b)=0
iGpsParserDelegate * GetDelegate()
Definition: GpsParser.h:193
int32_t GetReceiverIndex() const
Definition: GpsParser.h:205
eGpsParserType
Definition: GpsParser.h:34
- +
virtual ~cGpsParser()
Definition: GpsParser.h:168
- - + + diff --git a/docs/html/_i_s_comm_8c.html b/docs/html/_i_s_comm_8c.html index 1c7c593a4..d22965c86 100644 --- a/docs/html/_i_s_comm_8c.html +++ b/docs/html/_i_s_comm_8c.html @@ -23,7 +23,7 @@ Logo
SDK -  Release 1.6.2 +  Release 1.6.4
Communications, logger, and bootloader libraries.
diff --git a/docs/html/_i_s_comm_8c_source.html b/docs/html/_i_s_comm_8c_source.html index 2fb22a167..f8315f4ff 100644 --- a/docs/html/_i_s_comm_8c_source.html +++ b/docs/html/_i_s_comm_8c_source.html @@ -23,7 +23,7 @@ Logo
SDK -  Release 1.6.2 +  Release 1.6.4
Communications, logger, and bootloader libraries.
@@ -112,7 +112,7 @@
uint32_t counter
Definition: ISComm.h:92
void flipEndianess32(uint8_t *data, int dataLength)
Definition: data_sets.c:75
unsigned int getBitsAsUInt32(const unsigned char *buffer, unsigned int pos, unsigned int len)
Definition: ISComm.c:80
-
#define SWAP32(v)
Definition: ISConstants.h:257
+
#define SWAP32(v)
Definition: ISConstants.h:254
uint32_t is_comm_parse(is_comm_instance_t *instance, uint8_t byte)
Definition: ISComm.c:415
#define DID_GPS1_VERSION
Definition: data_sets.h:51
@@ -121,9 +121,9 @@
int is_comm_stop_broadcasts(is_comm_instance_t *instance)
Definition: ISComm.c:508
uint8_t cksum2
Definition: ISComm.h:450
-
#define BE_SWAP16(_i)
Definition: data_sets.h:2520
-
#define FREE(m)
Definition: ISConstants.h:134
-
#define MALLOC(m)
Definition: ISConstants.h:133
+
#define BE_SWAP16(_i)
Definition: data_sets.h:2553
+
#define FREE(m)
Definition: ISConstants.h:135
+
#define MALLOC(m)
Definition: ISConstants.h:134
unsigned int calculate24BitCRCQ(unsigned char *buffer, unsigned int len)
Definition: ISComm.c:27
uint32_t hasStartByte
Definition: ISComm.h:104
uint8_t * ptr
Definition: ISComm.h:311
@@ -172,7 +172,7 @@
uint32_t size
Definition: ISComm.h:507
- +