openc3 7.2.1 → 7.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (502) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -1
  3. data/Guardfile +0 -0
  4. data/LICENSE.md +0 -0
  5. data/README.md +0 -0
  6. data/Rakefile +0 -0
  7. data/bin/openc3cli +235 -6
  8. data/bin/pipinstall +5 -4
  9. data/bin/pipuninstall +5 -1
  10. data/bin/uvinstall +156 -0
  11. data/data/config/_array_params.yaml +0 -0
  12. data/data/config/_canvas_values.yaml +0 -0
  13. data/data/config/_graph_params.yaml +0 -0
  14. data/data/config/_id_items.yaml +0 -0
  15. data/data/config/_id_params.yaml +0 -0
  16. data/data/config/_interfaces.yaml +0 -0
  17. data/data/config/_items.yaml +0 -0
  18. data/data/config/_params.yaml +0 -0
  19. data/data/config/command.yaml +0 -0
  20. data/data/config/command_modifiers.yaml +2 -0
  21. data/data/config/command_telemetry.yaml +0 -0
  22. data/data/config/conversions.yaml +0 -0
  23. data/data/config/graph_settings.yaml +0 -0
  24. data/data/config/interface_modifiers.yaml +103 -1
  25. data/data/config/item_modifiers.yaml +2 -1
  26. data/data/config/microservice.yaml +9 -2
  27. data/data/config/param_item_modifiers.yaml +0 -0
  28. data/data/config/parameter_modifiers.yaml +0 -0
  29. data/data/config/plugins.yaml +0 -0
  30. data/data/config/processors.yaml +0 -0
  31. data/data/config/protocols.yaml +0 -0
  32. data/data/config/screen.yaml +2 -1
  33. data/data/config/settings.yaml +0 -0
  34. data/data/config/table_manager.yaml +0 -0
  35. data/data/config/table_parameter_modifiers.yaml +0 -0
  36. data/data/config/target.yaml +21 -0
  37. data/data/config/target_config.yaml +0 -0
  38. data/data/config/telemetry.yaml +0 -0
  39. data/data/config/telemetry_modifiers.yaml +2 -0
  40. data/data/config/tool.yaml +3 -1
  41. data/data/config/unknown.yaml +0 -0
  42. data/data/config/widgets.yaml +22 -3
  43. data/data/xtce_schemas/SpaceSystem_20180204.xsd +5918 -0
  44. data/data/xtce_schemas/xml.xsd +116 -0
  45. data/ext/openc3/ext/array/array.c +0 -0
  46. data/ext/openc3/ext/array/extconf.rb +0 -0
  47. data/ext/openc3/ext/buffered_file/buffered_file.c +0 -0
  48. data/ext/openc3/ext/buffered_file/extconf.rb +0 -0
  49. data/ext/openc3/ext/burst_protocol/burst_protocol.c +6 -0
  50. data/ext/openc3/ext/burst_protocol/extconf.rb +0 -0
  51. data/ext/openc3/ext/config_parser/config_parser.c +0 -0
  52. data/ext/openc3/ext/config_parser/extconf.rb +0 -0
  53. data/ext/openc3/ext/crc/crc.c +0 -0
  54. data/ext/openc3/ext/crc/extconf.rb +0 -0
  55. data/ext/openc3/ext/openc3_io/extconf.rb +0 -0
  56. data/ext/openc3/ext/openc3_io/openc3_io.c +0 -0
  57. data/ext/openc3/ext/packet/extconf.rb +0 -0
  58. data/ext/openc3/ext/packet/packet.c +0 -0
  59. data/ext/openc3/ext/platform/extconf.rb +0 -0
  60. data/ext/openc3/ext/platform/platform.c +4 -1
  61. data/ext/openc3/ext/polynomial_conversion/extconf.rb +0 -0
  62. data/ext/openc3/ext/polynomial_conversion/polynomial_conversion.c +0 -0
  63. data/ext/openc3/ext/string/extconf.rb +0 -0
  64. data/ext/openc3/ext/string/string.c +0 -0
  65. data/ext/openc3/ext/structure/structure.c +49 -17
  66. data/ext/openc3/ext/tabbed_plots_config/extconf.rb +0 -0
  67. data/ext/openc3/ext/tabbed_plots_config/tabbed_plots_config.c +0 -0
  68. data/ext/openc3/ext/telemetry/extconf.rb +0 -0
  69. data/ext/openc3/ext/telemetry/telemetry.c +1 -1
  70. data/lib/cosmos.rb +0 -0
  71. data/lib/cosmosc2.rb +0 -0
  72. data/lib/openc3/accessors/accessor.rb +0 -0
  73. data/lib/openc3/accessors/binary_accessor.rb +63 -9
  74. data/lib/openc3/accessors/cbor_accessor.rb +0 -0
  75. data/lib/openc3/accessors/form_accessor.rb +0 -0
  76. data/lib/openc3/accessors/html_accessor.rb +0 -0
  77. data/lib/openc3/accessors/http_accessor.rb +0 -0
  78. data/lib/openc3/accessors/json_accessor.rb +0 -0
  79. data/lib/openc3/accessors/template_accessor.rb +2 -2
  80. data/lib/openc3/accessors/xml_accessor.rb +0 -0
  81. data/lib/openc3/accessors.rb +0 -0
  82. data/lib/openc3/api/README.md +0 -0
  83. data/lib/openc3/api/api.rb +0 -0
  84. data/lib/openc3/api/authorized_api.rb +0 -0
  85. data/lib/openc3/api/calendar_api.rb +0 -0
  86. data/lib/openc3/api/cmd_api.rb +1 -1
  87. data/lib/openc3/api/config_api.rb +0 -0
  88. data/lib/openc3/api/interface_api.rb +2 -2
  89. data/lib/openc3/api/limits_api.rb +27 -13
  90. data/lib/openc3/api/metrics_api.rb +1 -1
  91. data/lib/openc3/api/offline_access_api.rb +1 -1
  92. data/lib/openc3/api/router_api.rb +3 -3
  93. data/lib/openc3/api/settings_api.rb +22 -18
  94. data/lib/openc3/api/stash_api.rb +1 -1
  95. data/lib/openc3/api/target_api.rb +0 -0
  96. data/lib/openc3/api/tlm_api.rb +5 -4
  97. data/lib/openc3/bridge/bridge.rb +0 -0
  98. data/lib/openc3/bridge/bridge_config.rb +0 -0
  99. data/lib/openc3/bridge/bridge_interface_thread.rb +0 -0
  100. data/lib/openc3/bridge/bridge_router_thread.rb +0 -0
  101. data/lib/openc3/ccsds/ccsds_packet.rb +0 -0
  102. data/lib/openc3/ccsds/ccsds_parser.rb +0 -0
  103. data/lib/openc3/config/config_parser.rb +78 -17
  104. data/lib/openc3/config/meta_config_parser.rb +0 -0
  105. data/lib/openc3/conversions/bit_reverse_conversion.rb +0 -0
  106. data/lib/openc3/conversions/conversion.rb +0 -0
  107. data/lib/openc3/conversions/generic_conversion.rb +0 -0
  108. data/lib/openc3/conversions/ip_read_conversion.rb +0 -0
  109. data/lib/openc3/conversions/ip_write_conversion.rb +0 -0
  110. data/lib/openc3/conversions/object_read_conversion.rb +0 -0
  111. data/lib/openc3/conversions/object_write_conversion.rb +0 -0
  112. data/lib/openc3/conversions/packet_time_formatted_conversion.rb +0 -0
  113. data/lib/openc3/conversions/packet_time_seconds_conversion.rb +0 -0
  114. data/lib/openc3/conversions/polynomial_conversion.rb +0 -0
  115. data/lib/openc3/conversions/processor_conversion.rb +0 -0
  116. data/lib/openc3/conversions/received_count_conversion.rb +0 -0
  117. data/lib/openc3/conversions/received_time_formatted_conversion.rb +0 -0
  118. data/lib/openc3/conversions/received_time_seconds_conversion.rb +0 -0
  119. data/lib/openc3/conversions/segmented_polynomial_conversion.rb +0 -0
  120. data/lib/openc3/conversions/unix_time_conversion.rb +0 -0
  121. data/lib/openc3/conversions/unix_time_formatted_conversion.rb +0 -0
  122. data/lib/openc3/conversions/unix_time_seconds_conversion.rb +0 -0
  123. data/lib/openc3/conversions.rb +0 -0
  124. data/lib/openc3/core_ext/array.rb +0 -0
  125. data/lib/openc3/core_ext/binding.rb +0 -0
  126. data/lib/openc3/core_ext/class.rb +0 -0
  127. data/lib/openc3/core_ext/exception.rb +0 -0
  128. data/lib/openc3/core_ext/faraday.rb +0 -0
  129. data/lib/openc3/core_ext/file.rb +0 -0
  130. data/lib/openc3/core_ext/io.rb +0 -0
  131. data/lib/openc3/core_ext/kernel.rb +0 -0
  132. data/lib/openc3/core_ext/math.rb +0 -0
  133. data/lib/openc3/core_ext/matrix.rb +0 -0
  134. data/lib/openc3/core_ext/objectspace.rb +0 -0
  135. data/lib/openc3/core_ext/openc3_io.rb +0 -0
  136. data/lib/openc3/core_ext/range.rb +0 -0
  137. data/lib/openc3/core_ext/socket.rb +0 -0
  138. data/lib/openc3/core_ext/string.rb +0 -0
  139. data/lib/openc3/core_ext/stringio.rb +0 -0
  140. data/lib/openc3/core_ext/tempfile.rb +0 -0
  141. data/lib/openc3/core_ext/time.rb +0 -0
  142. data/lib/openc3/core_ext.rb +0 -0
  143. data/lib/openc3/ext/.keep +0 -0
  144. data/lib/openc3/interfaces/file_interface.rb +0 -0
  145. data/lib/openc3/interfaces/http_client_interface.rb +1 -1
  146. data/lib/openc3/interfaces/http_server_interface.rb +0 -0
  147. data/lib/openc3/interfaces/interface.rb +5 -4
  148. data/lib/openc3/interfaces/mqtt_interface.rb +0 -0
  149. data/lib/openc3/interfaces/mqtt_stream_interface.rb +2 -0
  150. data/lib/openc3/interfaces/protocols/burst_protocol.rb +27 -0
  151. data/lib/openc3/interfaces/protocols/cmd_response_protocol.rb +0 -0
  152. data/lib/openc3/interfaces/protocols/cobs_protocol.rb +0 -0
  153. data/lib/openc3/interfaces/protocols/crc_protocol.rb +0 -0
  154. data/lib/openc3/interfaces/protocols/fixed_protocol.rb +0 -0
  155. data/lib/openc3/interfaces/protocols/ignore_packet_protocol.rb +0 -0
  156. data/lib/openc3/interfaces/protocols/length_protocol.rb +7 -0
  157. data/lib/openc3/interfaces/protocols/preidentified_protocol.rb +7 -0
  158. data/lib/openc3/interfaces/protocols/protocol.rb +4 -4
  159. data/lib/openc3/interfaces/protocols/slip_protocol.rb +0 -0
  160. data/lib/openc3/interfaces/protocols/template_protocol.rb +2 -2
  161. data/lib/openc3/interfaces/protocols/terminated_protocol.rb +0 -0
  162. data/lib/openc3/interfaces/serial_interface.rb +2 -0
  163. data/lib/openc3/interfaces/simulated_target_interface.rb +0 -0
  164. data/lib/openc3/interfaces/stream_interface.rb +0 -0
  165. data/lib/openc3/interfaces/tcpip_client_interface.rb +2 -0
  166. data/lib/openc3/interfaces/tcpip_server_interface.rb +0 -0
  167. data/lib/openc3/interfaces/udp_interface.rb +16 -5
  168. data/lib/openc3/interfaces.rb +0 -0
  169. data/lib/openc3/io/buffered_file.rb +0 -0
  170. data/lib/openc3/io/io_multiplexer.rb +0 -0
  171. data/lib/openc3/io/json_api.rb +3 -2
  172. data/lib/openc3/io/json_api_object.rb +0 -0
  173. data/lib/openc3/io/json_drb.rb +44 -12
  174. data/lib/openc3/io/json_drb_object.rb +0 -0
  175. data/lib/openc3/io/json_drb_rack.rb +0 -0
  176. data/lib/openc3/io/json_rpc.rb +0 -2
  177. data/lib/openc3/io/posix_serial_driver.rb +0 -0
  178. data/lib/openc3/io/serial_driver.rb +0 -0
  179. data/lib/openc3/io/stderr.rb +0 -0
  180. data/lib/openc3/io/stdout.rb +0 -0
  181. data/lib/openc3/io/udp_sockets.rb +38 -8
  182. data/lib/openc3/io/win32_serial_driver.rb +1 -0
  183. data/lib/openc3/logs/buffered_packet_log_reader.rb +0 -0
  184. data/lib/openc3/logs/buffered_packet_log_writer.rb +0 -0
  185. data/lib/openc3/logs/log_writer.rb +43 -7
  186. data/lib/openc3/logs/packet_log_constants.rb +0 -0
  187. data/lib/openc3/logs/packet_log_reader.rb +23 -2
  188. data/lib/openc3/logs/packet_log_writer.rb +6 -2
  189. data/lib/openc3/logs/stream_log.rb +1 -1
  190. data/lib/openc3/logs/stream_log_pair.rb +0 -0
  191. data/lib/openc3/logs/text_log_writer.rb +0 -0
  192. data/lib/openc3/logs.rb +0 -0
  193. data/lib/openc3/microservices/cleanup_microservice.rb +0 -0
  194. data/lib/openc3/microservices/decom_common.rb +0 -0
  195. data/lib/openc3/microservices/decom_microservice.rb +0 -0
  196. data/lib/openc3/microservices/interface_decom_common.rb +2 -1
  197. data/lib/openc3/microservices/interface_microservice.rb +73 -26
  198. data/lib/openc3/microservices/log_microservice.rb +0 -0
  199. data/lib/openc3/microservices/microservice.rb +3 -3
  200. data/lib/openc3/microservices/multi_microservice.rb +1 -1
  201. data/lib/openc3/microservices/periodic_microservice.rb +2 -2
  202. data/lib/openc3/microservices/plugin_microservice.rb +0 -0
  203. data/lib/openc3/microservices/queue_microservice.rb +0 -0
  204. data/lib/openc3/microservices/router_microservice.rb +0 -0
  205. data/lib/openc3/microservices/scope_cleanup_microservice.rb +0 -0
  206. data/lib/openc3/microservices/text_log_microservice.rb +0 -0
  207. data/lib/openc3/migrations/20220420190000_log_stuff.rb +0 -0
  208. data/lib/openc3/migrations/20221202214600_add_target_names.rb +0 -0
  209. data/lib/openc3/migrations/20221210174900_convert_to_multi.rb +0 -0
  210. data/lib/openc3/migrations/20230915000002_no_scope_log_messages.rb +0 -0
  211. data/lib/openc3/migrations/20231022000000_tlm_viewer_config.rb +0 -0
  212. data/lib/openc3/migrations/20241208080000_no_critical_cmd.rb +0 -0
  213. data/lib/openc3/migrations/20241208080001_no_trigger_group.rb +0 -0
  214. data/lib/openc3/migrations/20250108060000_news_feed.rb +0 -0
  215. data/lib/openc3/migrations/20250402000000_periodic_only_default.rb +0 -0
  216. data/lib/openc3/migrations/20260203000000_remove_store_id.rb +0 -0
  217. data/lib/openc3/migrations/20260204000000_remove_decom_reducer.rb +0 -0
  218. data/lib/openc3/migrations/20260701000000_updated_at_to_int.rb +0 -0
  219. data/lib/openc3/migrations/20260704000000_default_bridge.rb +38 -0
  220. data/lib/openc3/migrations/20260731000000_system_health_json.rb +52 -0
  221. data/lib/openc3/models/activity_model.rb +0 -0
  222. data/lib/openc3/models/auth_model.rb +35 -7
  223. data/lib/openc3/models/bridge_model.rb +133 -0
  224. data/lib/openc3/models/config_keyword_model.rb +63 -0
  225. data/lib/openc3/models/cvt_model.rb +5 -5
  226. data/lib/openc3/models/db_sharded_model.rb +0 -0
  227. data/lib/openc3/models/environment_model.rb +0 -0
  228. data/lib/openc3/models/gem_model.rb +13 -10
  229. data/lib/openc3/models/host_interface_microservice_model.rb +114 -0
  230. data/lib/openc3/models/info_model.rb +0 -0
  231. data/lib/openc3/models/interface_model.rb +179 -20
  232. data/lib/openc3/models/interface_status_model.rb +0 -0
  233. data/lib/openc3/models/metadata_model.rb +0 -0
  234. data/lib/openc3/models/metric_model.rb +0 -0
  235. data/lib/openc3/models/microservice_model.rb +26 -18
  236. data/lib/openc3/models/microservice_status_model.rb +0 -0
  237. data/lib/openc3/models/migration_model.rb +0 -0
  238. data/lib/openc3/models/model.rb +0 -0
  239. data/lib/openc3/models/news_model.rb +0 -0
  240. data/lib/openc3/models/note_model.rb +0 -0
  241. data/lib/openc3/models/offline_access_model.rb +0 -0
  242. data/lib/openc3/models/ping_model.rb +0 -0
  243. data/lib/openc3/models/plugin_model.rb +211 -50
  244. data/lib/openc3/models/plugin_store_model.rb +0 -0
  245. data/lib/openc3/models/process_status_model.rb +0 -0
  246. data/lib/openc3/models/python_package_model.rb +211 -15
  247. data/lib/openc3/models/queue_model.rb +0 -0
  248. data/lib/openc3/models/reaction_model.rb +0 -0
  249. data/lib/openc3/models/reingest_job_model.rb +0 -0
  250. data/lib/openc3/models/router_model.rb +0 -0
  251. data/lib/openc3/models/router_status_model.rb +0 -0
  252. data/lib/openc3/models/scope_model.rb +85 -56
  253. data/lib/openc3/models/script_engine_model.rb +0 -0
  254. data/lib/openc3/models/script_status_model.rb +0 -0
  255. data/lib/openc3/models/secret_model.rb +0 -0
  256. data/lib/openc3/models/setting_model.rb +546 -3
  257. data/lib/openc3/models/sorted_model.rb +0 -0
  258. data/lib/openc3/models/stash_model.rb +0 -0
  259. data/lib/openc3/models/target_model.rb +210 -31
  260. data/lib/openc3/models/timeline_model.rb +0 -0
  261. data/lib/openc3/models/tool_config_model.rb +0 -0
  262. data/lib/openc3/models/tool_model.rb +34 -20
  263. data/lib/openc3/models/trigger_group_model.rb +0 -0
  264. data/lib/openc3/models/trigger_model.rb +20 -0
  265. data/lib/openc3/models/widget_model.rb +0 -0
  266. data/lib/openc3/operators/microservice_operator.rb +79 -8
  267. data/lib/openc3/operators/operator.rb +4 -4
  268. data/lib/openc3/packets/binary_accessor.rb +0 -0
  269. data/lib/openc3/packets/command_validator.rb +0 -0
  270. data/lib/openc3/packets/commands.rb +4 -4
  271. data/lib/openc3/packets/json_packet.rb +0 -0
  272. data/lib/openc3/packets/limits.rb +15 -7
  273. data/lib/openc3/packets/limits_response.rb +0 -0
  274. data/lib/openc3/packets/packet.rb +5 -1
  275. data/lib/openc3/packets/packet_config.rb +0 -0
  276. data/lib/openc3/packets/packet_item.rb +0 -0
  277. data/lib/openc3/packets/packet_item_limits.rb +0 -0
  278. data/lib/openc3/packets/parsers/format_string_parser.rb +0 -0
  279. data/lib/openc3/packets/parsers/limits_parser.rb +0 -0
  280. data/lib/openc3/packets/parsers/limits_response_parser.rb +0 -0
  281. data/lib/openc3/packets/parsers/packet_item_parser.rb +0 -0
  282. data/lib/openc3/packets/parsers/packet_parser.rb +0 -0
  283. data/lib/openc3/packets/parsers/processor_parser.rb +0 -0
  284. data/lib/openc3/packets/parsers/state_parser.rb +1 -1
  285. data/lib/openc3/packets/parsers/xtce_converter.rb +183 -103
  286. data/lib/openc3/packets/parsers/xtce_parser.rb +71 -23
  287. data/lib/openc3/packets/structure.rb +9 -3
  288. data/lib/openc3/packets/structure_item.rb +0 -0
  289. data/lib/openc3/packets/telemetry.rb +3 -3
  290. data/lib/openc3/processors/processor.rb +2 -0
  291. data/lib/openc3/processors/statistics_processor.rb +0 -0
  292. data/lib/openc3/processors/watermark_processor.rb +0 -0
  293. data/lib/openc3/processors.rb +0 -0
  294. data/lib/openc3/script/api_shared.rb +0 -0
  295. data/lib/openc3/script/autonomic.rb +12 -12
  296. data/lib/openc3/script/calendar.rb +0 -0
  297. data/lib/openc3/script/commands.rb +1 -1
  298. data/lib/openc3/script/critical_cmd.rb +0 -0
  299. data/lib/openc3/script/exceptions.rb +0 -0
  300. data/lib/openc3/script/extract.rb +20 -25
  301. data/lib/openc3/script/limits.rb +0 -0
  302. data/lib/openc3/script/metadata.rb +0 -0
  303. data/lib/openc3/script/packages.rb +0 -0
  304. data/lib/openc3/script/plugins.rb +0 -0
  305. data/lib/openc3/script/queue.rb +0 -0
  306. data/lib/openc3/script/screen.rb +0 -0
  307. data/lib/openc3/script/script.rb +2 -2
  308. data/lib/openc3/script/script_runner.rb +0 -0
  309. data/lib/openc3/script/storage.rb +4 -4
  310. data/lib/openc3/script/suite.rb +0 -0
  311. data/lib/openc3/script/suite_results.rb +0 -0
  312. data/lib/openc3/script/suite_runner.rb +26 -0
  313. data/lib/openc3/script/tables.rb +0 -0
  314. data/lib/openc3/script/telemetry.rb +9 -3
  315. data/lib/openc3/script/web_socket_api.rb +247 -134
  316. data/lib/openc3/script.rb +0 -0
  317. data/lib/openc3/script_engines/script_engine.rb +0 -0
  318. data/lib/openc3/streams/mqtt_stream.rb +0 -0
  319. data/lib/openc3/streams/serial_stream.rb +0 -0
  320. data/lib/openc3/streams/stream.rb +0 -0
  321. data/lib/openc3/streams/tcpip_client_stream.rb +0 -0
  322. data/lib/openc3/streams/tcpip_socket_stream.rb +0 -0
  323. data/lib/openc3/streams/web_socket_client_stream.rb +0 -0
  324. data/lib/openc3/subpacketizers/subpacketizer.rb +0 -0
  325. data/lib/openc3/system/system.rb +0 -0
  326. data/lib/openc3/system/target.rb +0 -0
  327. data/lib/openc3/system.rb +0 -0
  328. data/lib/openc3/tools/cmd_tlm_server/api.rb +0 -0
  329. data/lib/openc3/tools/cmd_tlm_server/interface_thread.rb +7 -0
  330. data/lib/openc3/tools/table_manager/table.rb +0 -0
  331. data/lib/openc3/tools/table_manager/table_config.rb +0 -0
  332. data/lib/openc3/tools/table_manager/table_item.rb +0 -0
  333. data/lib/openc3/tools/table_manager/table_item_parser.rb +0 -0
  334. data/lib/openc3/tools/table_manager/table_manager_core.rb +0 -0
  335. data/lib/openc3/tools/table_manager/table_parser.rb +0 -0
  336. data/lib/openc3/tools/test_runner/test.rb +0 -0
  337. data/lib/openc3/top_level.rb +1 -1
  338. data/lib/openc3/topics/autonomic_topic.rb +0 -0
  339. data/lib/openc3/topics/calendar_topic.rb +0 -0
  340. data/lib/openc3/topics/command_decom_topic.rb +16 -1
  341. data/lib/openc3/topics/command_topic.rb +0 -0
  342. data/lib/openc3/topics/config_topic.rb +0 -0
  343. data/lib/openc3/topics/decom_interface_topic.rb +2 -1
  344. data/lib/openc3/topics/interface_topic.rb +8 -2
  345. data/lib/openc3/topics/limits_event_topic.rb +1 -1
  346. data/lib/openc3/topics/notebook_topic.rb +0 -0
  347. data/lib/openc3/topics/queue_topic.rb +0 -0
  348. data/lib/openc3/topics/router_topic.rb +6 -1
  349. data/lib/openc3/topics/system_events_topic.rb +0 -0
  350. data/lib/openc3/topics/telemetry_decom_topic.rb +0 -0
  351. data/lib/openc3/topics/telemetry_topic.rb +0 -0
  352. data/lib/openc3/topics/timeline_topic.rb +0 -0
  353. data/lib/openc3/topics/topic.rb +0 -0
  354. data/lib/openc3/utilities/authentication.rb +4 -4
  355. data/lib/openc3/utilities/authorization.rb +0 -0
  356. data/lib/openc3/utilities/aws_bucket.rb +12 -4
  357. data/lib/openc3/utilities/bucket.rb +1 -1
  358. data/lib/openc3/utilities/bucket_file_cache.rb +55 -22
  359. data/lib/openc3/utilities/bucket_require.rb +0 -0
  360. data/lib/openc3/utilities/bucket_utilities.rb +3 -4
  361. data/lib/openc3/utilities/cli_generator.rb +0 -0
  362. data/lib/openc3/utilities/cmd_log.rb +0 -0
  363. data/lib/openc3/utilities/config_overlay.rb +75 -0
  364. data/lib/openc3/utilities/cosmos_rails_formatter.rb +0 -0
  365. data/lib/openc3/utilities/crc.rb +59 -32
  366. data/lib/openc3/utilities/csv.rb +5 -5
  367. data/lib/openc3/utilities/ctrf.rb +0 -0
  368. data/lib/openc3/utilities/env_helper.rb +0 -0
  369. data/lib/openc3/utilities/local_bucket.rb +0 -0
  370. data/lib/openc3/utilities/local_mode.rb +36 -7
  371. data/lib/openc3/utilities/logger.rb +30 -8
  372. data/lib/openc3/utilities/message_log.rb +0 -0
  373. data/lib/openc3/utilities/metric.rb +0 -0
  374. data/lib/openc3/utilities/migration.rb +0 -0
  375. data/lib/openc3/utilities/open_telemetry.rb +0 -0
  376. data/lib/openc3/utilities/process_manager.rb +0 -0
  377. data/lib/openc3/utilities/pypi_url.rb +0 -0
  378. data/lib/openc3/utilities/python_proxy.rb +0 -0
  379. data/lib/openc3/utilities/python_venv.rb +135 -0
  380. data/lib/openc3/utilities/quaternion.rb +0 -0
  381. data/lib/openc3/utilities/questdb_client.rb +0 -0
  382. data/lib/openc3/utilities/redis_secrets.rb +0 -0
  383. data/lib/openc3/utilities/reingest_job.rb +0 -0
  384. data/lib/openc3/utilities/ruby_lex_utils.rb +5 -1
  385. data/lib/openc3/utilities/rubygems_url.rb +39 -0
  386. data/lib/openc3/utilities/running_script.rb +119 -95
  387. data/lib/openc3/utilities/s3_autoload.rb +5 -5
  388. data/lib/openc3/utilities/script.rb +52 -12
  389. data/lib/openc3/utilities/secrets.rb +48 -3
  390. data/lib/openc3/utilities/simulated_target.rb +0 -0
  391. data/lib/openc3/utilities/sleeper.rb +0 -0
  392. data/lib/openc3/utilities/store.rb +0 -0
  393. data/lib/openc3/utilities/store_autoload.rb +2 -2
  394. data/lib/openc3/utilities/store_queued.rb +0 -0
  395. data/lib/openc3/utilities/target_file.rb +18 -1
  396. data/lib/openc3/utilities/thread_manager.rb +0 -0
  397. data/lib/openc3/utilities/throttle.rb +0 -0
  398. data/lib/openc3/utilities/zip.rb +0 -0
  399. data/lib/openc3/utilities.rb +0 -0
  400. data/lib/openc3/version.rb +6 -6
  401. data/lib/openc3/win32/excel.rb +0 -0
  402. data/lib/openc3/win32/win32.rb +0 -0
  403. data/lib/openc3/win32/win32_main.rb +0 -0
  404. data/lib/openc3.rb +2 -2
  405. data/tasks/gemfile_stats.rake +0 -0
  406. data/tasks/spec.rake +0 -0
  407. data/templates/command_validator/command_validator.py +0 -0
  408. data/templates/command_validator/command_validator.rb +0 -0
  409. data/templates/conversion/conversion.py +0 -0
  410. data/templates/conversion/conversion.rb +0 -0
  411. data/templates/limits_response/response.py +0 -0
  412. data/templates/limits_response/response.rb +0 -0
  413. data/templates/microservice/microservices/TEMPLATE/microservice.py +0 -0
  414. data/templates/microservice/microservices/TEMPLATE/microservice.rb +0 -0
  415. data/templates/plugin/.gitignore +0 -0
  416. data/templates/plugin/LICENSE.md +0 -0
  417. data/templates/plugin/README.md +0 -0
  418. data/templates/plugin/Rakefile +0 -0
  419. data/templates/plugin/plugin.gemspec +1 -1
  420. data/templates/plugin/plugin.txt +0 -0
  421. data/templates/processor/processor.py +1 -1
  422. data/templates/processor/processor.rb +0 -0
  423. data/templates/target/targets/TARGET/cmd_tlm/cmd.txt +0 -0
  424. data/templates/target/targets/TARGET/cmd_tlm/tlm.txt +0 -0
  425. data/templates/target/targets/TARGET/lib/target.py +0 -0
  426. data/templates/target/targets/TARGET/lib/target.rb +0 -0
  427. data/templates/target/targets/TARGET/procedures/procedure.py +0 -0
  428. data/templates/target/targets/TARGET/procedures/procedure.rb +0 -0
  429. data/templates/target/targets/TARGET/public/README.txt +0 -0
  430. data/templates/target/targets/TARGET/screens/status.txt +0 -0
  431. data/templates/target/targets/TARGET/target.txt +0 -0
  432. data/templates/tool_angular/.editorconfig +0 -0
  433. data/templates/tool_angular/.gitignore +0 -0
  434. data/templates/tool_angular/.vscode/extensions.json +0 -0
  435. data/templates/tool_angular/.vscode/launch.json +0 -0
  436. data/templates/tool_angular/.vscode/tasks.json +0 -0
  437. data/templates/tool_angular/angular.json +0 -0
  438. data/templates/tool_angular/extra-webpack.config.js +0 -0
  439. data/templates/tool_angular/package.json +2 -2
  440. data/templates/tool_angular/src/app/app-routing.module.ts +0 -0
  441. data/templates/tool_angular/src/app/app.component.html +0 -0
  442. data/templates/tool_angular/src/app/app.component.scss +0 -0
  443. data/templates/tool_angular/src/app/app.component.spec.ts +0 -0
  444. data/templates/tool_angular/src/app/app.component.ts +0 -0
  445. data/templates/tool_angular/src/app/app.module.ts +0 -0
  446. data/templates/tool_angular/src/app/custom-overlay-container.ts +0 -0
  447. data/templates/tool_angular/src/app/empty-route/empty-route.component.ts +0 -0
  448. data/templates/tool_angular/src/app/openc3-api.d.ts +0 -0
  449. data/templates/tool_angular/src/assets/.gitkeep +0 -0
  450. data/templates/tool_angular/src/environments/environment.prod.ts +0 -0
  451. data/templates/tool_angular/src/environments/environment.ts +0 -0
  452. data/templates/tool_angular/src/favicon.ico +0 -0
  453. data/templates/tool_angular/src/index.html +0 -0
  454. data/templates/tool_angular/src/main.single-spa.ts +0 -0
  455. data/templates/tool_angular/src/single-spa/asset-url.ts +0 -0
  456. data/templates/tool_angular/src/single-spa/single-spa-props.ts +0 -0
  457. data/templates/tool_angular/src/styles.scss +0 -0
  458. data/templates/tool_angular/tsconfig.app.json +0 -0
  459. data/templates/tool_angular/tsconfig.json +0 -0
  460. data/templates/tool_angular/tsconfig.spec.json +0 -0
  461. data/templates/tool_react/.eslintrc +0 -0
  462. data/templates/tool_react/.gitignore +0 -0
  463. data/templates/tool_react/.prettierignore +0 -0
  464. data/templates/tool_react/babel.config.json +0 -0
  465. data/templates/tool_react/jest.config.js +0 -0
  466. data/templates/tool_react/package.json +1 -1
  467. data/templates/tool_react/src/openc3-tool_name.js +0 -0
  468. data/templates/tool_react/src/root.component.js +0 -0
  469. data/templates/tool_react/src/root.component.test.js +0 -0
  470. data/templates/tool_react/webpack.config.js +0 -0
  471. data/templates/tool_svelte/.gitignore +0 -0
  472. data/templates/tool_svelte/.prettierignore +0 -0
  473. data/templates/tool_svelte/.prettierrc.js +0 -0
  474. data/templates/tool_svelte/babel.config.js +0 -0
  475. data/templates/tool_svelte/build/smui.css +0 -0
  476. data/templates/tool_svelte/jest.config.js +0 -0
  477. data/templates/tool_svelte/package.json +1 -1
  478. data/templates/tool_svelte/rollup.config.js +0 -0
  479. data/templates/tool_svelte/src/App.svelte +0 -0
  480. data/templates/tool_svelte/src/App.test.js +0 -0
  481. data/templates/tool_svelte/src/theme/_smui-theme.scss +0 -0
  482. data/templates/tool_svelte/src/tool_name.js +0 -0
  483. data/templates/tool_vue/.env.standalone +0 -0
  484. data/templates/tool_vue/.gitignore +0 -0
  485. data/templates/tool_vue/.prettierrc.cjs +0 -0
  486. data/templates/tool_vue/eslint.config.mjs +0 -0
  487. data/templates/tool_vue/jsconfig.json +0 -0
  488. data/templates/tool_vue/package.json +3 -3
  489. data/templates/tool_vue/src/App.vue +0 -0
  490. data/templates/tool_vue/src/main.js +0 -0
  491. data/templates/tool_vue/src/router.js +0 -0
  492. data/templates/tool_vue/src/tools/tool_name/tool_name.vue +0 -0
  493. data/templates/tool_vue/vite.config.js +1 -1
  494. data/templates/widget/.prettierrc.cjs +0 -0
  495. data/templates/widget/LICENSE.md +0 -0
  496. data/templates/widget/Rakefile +0 -0
  497. data/templates/widget/package.json +2 -2
  498. data/templates/widget/src/Widget.vue +0 -0
  499. data/templates/widget/vite.config.js +0 -0
  500. metadata +40 -11
  501. data/templates/tool_vue/.nycrc +0 -3
  502. data/templates/widget/.nycrc +0 -3
@@ -134,7 +134,7 @@ module OpenC3
134
134
  break
135
135
  end
136
136
  end
137
- raise "Item '#{target_name} #{packet_name} #{item_name}' does not exist" unless found_item
137
+ raise "Item '#{target_name} #{packet_name} #{item_name}' does not exist while enabling limits" unless found_item
138
138
 
139
139
  TargetModel.set_packet(target_name, packet_name, packet, scope: scope)
140
140
 
@@ -167,7 +167,7 @@ module OpenC3
167
167
  break
168
168
  end
169
169
  end
170
- raise "Item '#{target_name} #{packet_name} #{item_name}' does not exist" unless found_item
170
+ raise "Item '#{target_name} #{packet_name} #{item_name}' does not exist while disabling limits" unless found_item
171
171
 
172
172
  TargetModel.set_packet(target_name, packet_name, packet, scope: scope)
173
173
 
@@ -239,7 +239,7 @@ module OpenC3
239
239
  end
240
240
  end
241
241
  end
242
- raise "Item '#{target_name} #{packet_name} #{item_name}' does not exist" unless found_item
242
+ raise "Item '#{target_name} #{packet_name} #{item_name}' does not exist while setting limits" unless found_item
243
243
  message = "Setting '#{target_name} #{packet_name} #{item_name}' limits to #{red_low} #{yellow_low} #{yellow_high} #{red_high}"
244
244
  message << " #{green_low} #{green_high}" if green_low && green_high
245
245
  message << " in set #{limits_set} with persistence #{persistence} as enabled #{enabled}"
@@ -262,14 +262,19 @@ module OpenC3
262
262
  # @param packet_name [String] Packet name
263
263
  # @param item_name [String] Item name
264
264
  # @param state_name [String] Name of the state to change (e.g. 'CONNECTED')
265
- # @param color [String] New color for the state. Must be GREEN, YELLOW, or RED.
265
+ # @param color [String, nil] New color for the state. Must be GREEN, YELLOW,
266
+ # or RED. Pass nil to clear (remove) the state color. Setting a color also
267
+ # enables limits for the item, but clearing the color (nil) does not change
268
+ # whether limits are enabled.
266
269
  def set_state_color(target_name, packet_name, item_name, state_name, color,
267
270
  manual: false, scope: $openc3_scope, token: $openc3_token)
268
271
  authorize(permission: 'tlm_set', target_name: target_name, packet_name: packet_name, manual: manual, scope: scope, token: token)
269
272
  state_name = state_name.to_s.upcase
270
- color = color.to_s.upcase
271
- unless PacketItem::STATE_COLORS.include?(color.intern)
272
- raise "Invalid state color #{color}. Must be one of #{PacketItem::STATE_COLORS.join(' ')}."
273
+ unless color.nil?
274
+ color = color.to_s.upcase
275
+ unless PacketItem::STATE_COLORS.include?(color.intern)
276
+ raise "Invalid state color '#{color}'. Must be one of #{PacketItem::STATE_COLORS.join(', ')}."
277
+ end
273
278
  end
274
279
  packet = TargetModel.packet(target_name, packet_name, scope: scope)
275
280
  found_item = nil
@@ -278,16 +283,25 @@ module OpenC3
278
283
  unless item['states'] && item['states'][state_name]
279
284
  raise "State '#{state_name}' does not exist for item '#{target_name} #{packet_name} #{item_name}'"
280
285
  end
281
- item['states'][state_name]['color'] = color
282
- # Defining a state color implies limits are enabled for the item
283
- item['limits'] ||= {}
284
- item['limits']['enabled'] = true
286
+ if color.nil?
287
+ # Clear the state color
288
+ item['states'][state_name].delete('color')
289
+ else
290
+ item['states'][state_name]['color'] = color
291
+ # Defining a state color implies limits are enabled for the item
292
+ item['limits'] ||= {}
293
+ item['limits']['enabled'] = true
294
+ end
285
295
  found_item = item
286
296
  break
287
297
  end
288
298
  end
289
- raise "Item '#{target_name} #{packet_name} #{item_name}' does not exist" unless found_item
290
- message = "Setting '#{target_name} #{packet_name} #{item_name}' state #{state_name} color to #{color}"
299
+ raise "Item '#{target_name} #{packet_name} #{item_name}' does not exist while setting state color" unless found_item
300
+ if color.nil?
301
+ message = "Clearing '#{target_name} #{packet_name} #{item_name}' state #{state_name} color"
302
+ else
303
+ message = "Setting '#{target_name} #{packet_name} #{item_name}' state #{state_name} color to #{color}"
304
+ end
291
305
  Logger.info(message, scope: scope)
292
306
 
293
307
  TargetModel.set_packet(target_name, packet_name, packet, scope: scope)
@@ -1,6 +1,6 @@
1
1
  # encoding: ascii-8bit
2
2
 
3
- # Copyright 2023 OpenC3, Inc
3
+ # Copyright 2026 OpenC3, Inc.
4
4
  # All Rights Reserved.
5
5
  #
6
6
  # This program is distributed in the hope that it will be useful,
@@ -1,6 +1,6 @@
1
1
  # encoding: ascii-8bit
2
2
 
3
- # Copyright 2022 OpenC3, Inc
3
+ # Copyright 2026 OpenC3, Inc.
4
4
  # All Rights Reserved.
5
5
  #
6
6
  # This program is distributed in the hope that it will be useful,
@@ -46,7 +46,7 @@ module OpenC3
46
46
  def get_router(router_name, manual: false, scope: $openc3_scope, token: $openc3_token)
47
47
  authorize(permission: 'system', router_name: router_name, manual: manual, scope: scope, token: token)
48
48
  router = RouterModel.get(name: router_name, scope: scope)
49
- raise "Router '#{router_name}' does not exist" unless router
49
+ raise "Router '#{router_name}' does not exist (get_router)" unless router
50
50
 
51
51
  router.merge(RouterStatusModel.get(name: router_name, scope: scope))
52
52
  end
@@ -144,7 +144,7 @@ module OpenC3
144
144
  # TODO: Check if they have command authority for the targets mapped to this router
145
145
  authorize(permission: 'system_set', router_name: router_name, manual: manual, scope: scope, token: token)
146
146
  router = RouterModel.get_model(name: router_name, scope: scope)
147
- raise "Router '#{router_name}' does not exist" unless router
147
+ raise "Router '#{router_name}' does not exist (map_target_to_router)" unless router
148
148
 
149
149
  if Array === target_name
150
150
  target_names = target_name
@@ -167,7 +167,7 @@ module OpenC3
167
167
  # TODO: Check if they have command authority for the targets mapped to this router
168
168
  authorize(permission: 'system_set', router_name: router_name, manual: manual, scope: scope, token: token)
169
169
  router = RouterModel.get_model(name: router_name, scope: scope)
170
- raise "Router '#{router_name}' does not exist" unless router
170
+ raise "Router '#{router_name}' does not exist (unmap_target_from_router)" unless router
171
171
 
172
172
  if Array === target_name
173
173
  target_names = target_name
@@ -81,26 +81,30 @@ module OpenC3
81
81
 
82
82
  # Update the news feed on demand to respond to frontend setting changes
83
83
  def update_news(manual: false, scope: $openc3_scope, token: $openc3_token)
84
+ # Authorize outside the begin/rescue so AuthError propagates to the caller
85
+ # rather than being swallowed and written into the news feed
84
86
  authorize(permission: 'admin', manual: manual, scope: scope, token: token)
85
- conn = Faraday.new(
86
- url: 'https://news.openc3.com',
87
- params: {version: VERSION, enterprise: ENTERPRISE},
88
- )
89
- response = conn.get('/news')
90
- if response.success?
91
- NewsModel.set(response.body)
92
- else
93
- NewsModel.news_error("Error contacting OpenC3 news feed (status: #{response.status})")
94
- end
87
+ begin
88
+ conn = Faraday.new(
89
+ url: 'https://news.openc3.com',
90
+ params: {version: VERSION, enterprise: ENTERPRISE},
91
+ )
92
+ response = conn.get('/news')
93
+ if response.success?
94
+ NewsModel.set(response.body)
95
+ else
96
+ NewsModel.news_error("Error contacting OpenC3 news feed (status: #{response.status})")
97
+ end
95
98
 
96
- # Test code to update the news feed with a dummy message
97
- # data = NewsModel.all()
98
- # json = JSON.parse(data)
99
- # json.unshift( { date: Time.now.utc.iso8601, title: "News at #{Time.now}", body: "The news feed has been updated at #{Time.now}." })
100
- # json.pop if json.length > 5
101
- # NewsModel.set(json.to_json)
102
- rescue Exception => e
103
- NewsModel.news_error("Error contacting OpenC3 news feed. #{e.message})")
99
+ # Test code to update the news feed with a dummy message
100
+ # data = NewsModel.all()
101
+ # json = JSON.parse(data)
102
+ # json.unshift( { date: Time.now.utc.iso8601, title: "News at #{Time.now}", body: "The news feed has been updated at #{Time.now}." })
103
+ # json.pop if json.length > 5
104
+ # NewsModel.set(json.to_json)
105
+ rescue StandardError => e
106
+ NewsModel.news_error("Error contacting OpenC3 news feed. #{e.message}")
107
+ end
104
108
  end
105
109
 
106
110
  # Update the local copy of the plugin store data
@@ -1,6 +1,6 @@
1
1
  # encoding: ascii-8bit
2
2
 
3
- # Copyright 2024 OpenC3, Inc
3
+ # Copyright 2026 OpenC3, Inc.
4
4
  # All Rights Reserved.
5
5
  #
6
6
  # This program is distributed in the hope that it will be useful,
File without changes
@@ -117,13 +117,14 @@ module OpenC3
117
117
  # @param packet_name [String] Packet name of the packet
118
118
  # @param item_hash [Hash] Hash of item_name and value for each item you want to change from the current value table
119
119
  # @param type [Symbol] Telemetry type, :RAW, :CONVERTED (default), :FORMATTED
120
- def inject_tlm(target_name, packet_name, item_hash = nil, type: :CONVERTED, stored: false, manual: false, scope: $openc3_scope, token: $openc3_token)
120
+ # @param received_time [Integer, nil] Optional received time as nanoseconds since Unix epoch
121
+ def inject_tlm(target_name, packet_name, item_hash = nil, type: :CONVERTED, stored: false, received_time: nil, manual: false, scope: $openc3_scope, token: $openc3_token)
121
122
  authorize(permission: 'tlm_set', target_name: target_name, packet_name: packet_name, manual: manual, scope: scope, token: token)
122
123
  type = type.to_s.intern
123
124
  target_name = target_name.upcase
124
125
  packet_name = packet_name.upcase
125
126
  unless CvtModel::VALUE_TYPES.include?(type)
126
- raise "Unknown type '#{type}' for #{target_name} #{packet_name}"
127
+ raise "Unknown type '#{type}' for #{target_name} #{packet_name} (inject_tlm)"
127
128
  end
128
129
 
129
130
  if item_hash
@@ -155,9 +156,9 @@ module OpenC3
155
156
 
156
157
  # Use an interface microservice if it exists, other use the decom microservice
157
158
  if interface_name
158
- InterfaceTopic.inject_tlm(interface_name, target_name, packet_name, item_hash, type: type, stored: stored, scope: scope)
159
+ InterfaceTopic.inject_tlm(interface_name, target_name, packet_name, item_hash, type: type, stored: stored, received_time: received_time, scope: scope)
159
160
  else
160
- DecomInterfaceTopic.inject_tlm(target_name, packet_name, item_hash, type: type, stored: stored, scope: scope)
161
+ DecomInterfaceTopic.inject_tlm(target_name, packet_name, item_hash, type: type, stored: stored, received_time: received_time, scope: scope)
161
162
  end
162
163
  end
163
164
 
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -166,19 +166,46 @@ module OpenC3
166
166
  return ERB.new(read_file(template_name).comment_erb(), trim_mode: "-").result(b)
167
167
  end
168
168
 
169
- # Can be called during parsing to read a referenced file
169
+ # Can be called during parsing to read a referenced file. The filename must
170
+ # be relative to the configuration file being parsed and must resolve to a
171
+ # location inside that file's directory.
170
172
  def read_file(filename)
171
- # Assume the file is there. If not we raise a pretty obvious error
172
- if File.expand_path(filename) == filename # absolute path
173
- path = filename
174
- else # relative to the current @filename
175
- path = File.join(File.dirname(@filename), filename)
176
- end
173
+ path = resolve_config_path(filename)
177
174
  OpenC3.set_working_dir(File.dirname(path)) do
178
175
  return File.read(path).force_encoding("UTF-8")
179
176
  end
180
177
  end
181
178
 
179
+ # Resolves a filename referenced by a configuration file (TEMPLATE_FILE, ERB
180
+ # render, etc) into an absolute path contained by the directory of the file
181
+ # being parsed. Absolute paths and paths containing '..' are rejected so a
182
+ # configuration file can not read arbitrary files on the filesystem.
183
+ #
184
+ # @param filename [String] Relative path from the configuration file
185
+ # @return [String] Absolute path to the referenced file
186
+ private def resolve_config_path(filename)
187
+ filename = filename.to_s
188
+ raise Error.new(self, "Filename must be given") if filename.strip.empty?
189
+
190
+ if File.absolute_path?(filename) or File.expand_path(filename) == filename
191
+ raise Error.new(self, "Absolute paths are not allowed: #{filename}")
192
+ end
193
+ if filename.include?('..')
194
+ raise Error.new(self, "Path traversal is not allowed: #{filename}")
195
+ end
196
+ if @filename.nil? or @filename.to_s.empty?
197
+ raise Error.new(self, "No configuration file is being parsed, can not resolve: #{filename}")
198
+ end
199
+
200
+ base = File.expand_path(File.dirname(@filename))
201
+ path = File.expand_path(File.join(base, filename))
202
+ # Final containment check in case the OS or Ruby normalizes something unexpected
203
+ unless path.start_with?(base + File::SEPARATOR)
204
+ raise Error.new(self, "Path is outside the configuration directory: #{filename}")
205
+ end
206
+ path
207
+ end
208
+
182
209
  # Processes a file and yields |config| to the given block
183
210
  #
184
211
  # @param filename [String] The full name and path of the configuration file
@@ -307,6 +334,38 @@ module OpenC3
307
334
  return value
308
335
  end
309
336
 
337
+ # Values handle_true_false_strict accepts. Deliberately NOT shared with
338
+ # handle_true_false, which passes unrecognized values through and so can't
339
+ # tell the number 1 from a boolean - TABLE_MANAGER item defaults rely on 1
340
+ # staying 1. Named and scoped so they can't be mistaken for a truth table
341
+ # the whole parser honors.
342
+ STRICT_TRUE_VALUES = ['TRUE', '1']
343
+ STRICT_FALSE_VALUES = ['FALSE', '0', '']
344
+ private_constant :STRICT_TRUE_VALUES, :STRICT_FALSE_VALUES
345
+
346
+ # Converts a String containing 'TRUE', '1', 'FALSE', '0' or '' to a true or
347
+ # false Ruby primitive. Unlike handle_true_false, which returns anything it
348
+ # doesn't recognize unchanged, an unrecognized value raises.
349
+ #
350
+ # Use this for a flag where guessing is worse than failing - notably an
351
+ # environment variable that is enabled by presence elsewhere in COSMOS, so
352
+ # that 'VAR=false' (or 'VAR=0') means off here rather than the surprising on.
353
+ #
354
+ # @param value [Object] value to convert, nil returns the default
355
+ # @param description [String] what the value is, used in the error message
356
+ # @param default [true|false] returned when value is nil
357
+ # @return [true|false]
358
+ def self.handle_true_false_strict(value, description: 'value', default: false)
359
+ return default if value.nil?
360
+ normalized = value.to_s.strip.upcase
361
+ return true if STRICT_TRUE_VALUES.include?(normalized)
362
+ return false if STRICT_FALSE_VALUES.include?(normalized)
363
+ # Name empty explicitly - it is accepted (as false) but isn't a value
364
+ # anyone can read off the list
365
+ raise ArgumentError, "Invalid value #{value.to_s.strip.inspect} for #{description}. " \
366
+ "Must be one of: #{(STRICT_TRUE_VALUES + STRICT_FALSE_VALUES - ['']).join(', ')}, or empty"
367
+ end
368
+
310
369
  # Converts a String containing '', 'NIL', 'NULL', 'TRUE' or 'FALSE' to nil,
311
370
  # true or false Ruby primitives. All other values are simply returned.
312
371
  #
@@ -321,6 +380,8 @@ module OpenC3
321
380
  return false
322
381
  when '', 'NIL', 'NULL'
323
382
  return nil
383
+ else
384
+ # All other strings are returned unmodified below
324
385
  end
325
386
  end
326
387
  return value
@@ -378,11 +439,12 @@ module OpenC3
378
439
  return Float::INFINITY
379
440
  when 'NEG_INFINITY'
380
441
  return -Float::INFINITY
442
+ else
443
+ # NOTE: The else case does not raise because of the following scenario:
444
+ # If the value type is a UINT but they have a WRITE_CONVERSION that takes a string
445
+ # then the default value will be a string. In that case we just want to return the string.
446
+ # For example, the IP_ADDRESS parameter in the TIME_OFFSET command in the Demo plugin.
381
447
  end
382
- # NOTE: No else case because of the following scenario:
383
- # If the value type is a UINT but they have a WRITE_CONVERSION that takes a string
384
- # then the default value will be a string. In that case we just want to return the string.
385
- # For example, the IP_ADDRESS parameter in the TIME_OFFSET command in the Demo plugin.
386
448
  end
387
449
  return value
388
450
  end
@@ -494,8 +556,8 @@ module OpenC3
494
556
  while true
495
557
  @line_number += 1
496
558
 
497
- if @@progress_callback && ((@line_number % 10) == 0)
498
- @@progress_callback.call(io.pos / size) if size > 0.0
559
+ if @@progress_callback && ((@line_number % 10) == 0) && size > 0.0
560
+ @@progress_callback.call(io.pos / size)
499
561
  end
500
562
 
501
563
  begin
@@ -586,10 +648,9 @@ module OpenC3
586
648
  # KEYWORD PARAM #This is a comment
587
649
  # But still process Ruby string interpolations such as:
588
650
  # KEYWORD PARAM #{var}
589
- if (string.length > 0) && (string[0] == '#')
590
- if !((string.length > 1) && (string[1] == '{'))
591
- break
592
- end
651
+ if (string.length > 0) && (string[0] == '#') &&
652
+ !((string.length > 1) && (string[1] == '{'))
653
+ break
593
654
  end
594
655
 
595
656
  if remove_quotes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
data/lib/openc3/ext/.keep CHANGED
File without changes
File without changes
@@ -237,7 +237,7 @@ module OpenC3
237
237
  result['read_timeout'] = @read_timeout
238
238
  result['connect_timeout'] = @connect_timeout
239
239
  result['include_request_in_response'] = @include_request_in_response
240
- result['request_queue_length'] = @request_queue.length
240
+ result['response_queue_length'] = @response_queue.length
241
241
  return result
242
242
  end
243
243
  end
File without changes
@@ -15,6 +15,7 @@
15
15
  # This file may also be used under the terms of a commercial license
16
16
  # if purchased from OpenC3, Inc.
17
17
 
18
+ require 'openc3/packets/packet'
18
19
  require 'openc3/api/api'
19
20
  require 'openc3/logs/stream_log_pair'
20
21
  require 'openc3/utilities/secrets'
@@ -433,8 +434,8 @@ module OpenC3
433
434
  config['name'] = @name
434
435
  config['state'] = @state
435
436
  config['clients'] = self.num_clients
436
- config['txsize'] = @write_queue_size
437
- config['rxsize'] = @read_queue_size
437
+ config['txsize'] = self.write_queue_size
438
+ config['rxsize'] = self.read_queue_size
438
439
  config['txbytes'] = @bytes_written
439
440
  config['rxbytes'] = @bytes_read
440
441
  config['txcnt'] = @write_count
@@ -677,12 +678,12 @@ module OpenC3
677
678
  result['read_raw_data'] = @read_raw_data
678
679
  result['written_raw_data'] = @written_raw_data
679
680
  if @read_raw_data_time
680
- result['read_raw_data_time'] = @read_raw_data_time.iso8601
681
+ result['read_raw_data_time'] = @read_raw_data_time.getutc.iso8601(6)
681
682
  else
682
683
  result['read_raw_data_time'] = nil
683
684
  end
684
685
  if @written_raw_data_time
685
- result['written_raw_data_time'] = @written_raw_data_time.iso8601
686
+ result['written_raw_data_time'] = @written_raw_data_time.getutc.iso8601(6)
686
687
  else
687
688
  result['written_raw_data_time'] = nil
688
689
  end
File without changes
@@ -49,6 +49,8 @@ module OpenC3
49
49
 
50
50
  # Creates a new {SerialStream} using the parameters passed in the constructor
51
51
  def connect
52
+ # Cleanly close any existing stream rather than leaving it open
53
+ @stream.disconnect if @stream
52
54
  @stream = MqttStream.new(@hostname, @port, @ssl, @write_topic, @read_topic, @ack_timeout)
53
55
  @stream.username = @username if @username
54
56
  @stream.password = @password if @password
@@ -23,6 +23,14 @@ module OpenC3
23
23
  # Reads all data available on the interface and creates a packet
24
24
  # with that data.
25
25
  class BurstProtocol < Protocol
26
+ # Maximum number of bytes which will be buffered while waiting for a
27
+ # complete packet. This bounds the memory a peer can cause the interface
28
+ # to allocate by declaring an enormous packet length (LENGTH, PREIDENTIFIED)
29
+ # or by never sending a terminator (TERMINATED). Deliberately much larger
30
+ # than any realistic packet so it does not affect existing configurations.
31
+ # Override with the OPENC3_PROTOCOL_MAX_BUFFER_SIZE environment variable.
32
+ DEFAULT_MAX_BUFFER_SIZE = 100_000_000
33
+
26
34
  # @param discard_leading_bytes [Integer] The number of bytes to discard
27
35
  # from the binary data after reading. Note that this is often
28
36
  # used to remove a sync pattern from the final packet data.
@@ -37,6 +45,7 @@ module OpenC3
37
45
  @sync_pattern = ConfigParser.handle_nil(sync_pattern)
38
46
  @sync_pattern = @sync_pattern.hex_to_byte_string if @sync_pattern
39
47
  @fill_fields = ConfigParser.handle_true_false(fill_fields)
48
+ @max_buffer_size = Integer(ENV.fetch('OPENC3_PROTOCOL_MAX_BUFFER_SIZE', DEFAULT_MAX_BUFFER_SIZE))
40
49
  end
41
50
 
42
51
  def reset
@@ -60,6 +69,7 @@ module OpenC3
60
69
  # @return [String|nil] Data for a packet consisting of the bytes read
61
70
  def read_data(data, extra = nil)
62
71
  @data << data
72
+ check_buffer_size()
63
73
  @extra = extra unless (data.length == 0 and extra.nil?) # Maintain extra from last read read_data
64
74
 
65
75
  while true
@@ -192,6 +202,21 @@ module OpenC3
192
202
  return super(data, extra)
193
203
  end
194
204
 
205
+ # Raises if the accumulation buffer has grown past @max_buffer_size. Called
206
+ # from read_data by both the Ruby and the C implementations. Raising causes
207
+ # Interface#read to log the error and disconnect, which drops the offending
208
+ # peer and resets this protocol.
209
+ def check_buffer_size
210
+ length = @data.length
211
+ return if length <= @max_buffer_size
212
+
213
+ # Release the buffer and clear any partially reduced state now rather than
214
+ # waiting for the interface to disconnect and reset() us
215
+ reset()
216
+ raise "#{@interface ? @interface.name : ""}: Protocol buffer of #{length} bytes exceeds maximum of #{@max_buffer_size} bytes. " \
217
+ "Increase OPENC3_PROTOCOL_MAX_BUFFER_SIZE."
218
+ end
219
+
195
220
  def log_discard(length, found)
196
221
  Logger.error("#{@interface ? @interface.name : ""}: Sync #{'not ' unless found}found. Discarding #{length} bytes of data.")
197
222
  if @data.length >= 0
@@ -210,6 +235,7 @@ module OpenC3
210
235
  result['discard_leading_bytes'] = @discard_leading_bytes
211
236
  result['sync_pattern'] = @sync_pattern.inspect
212
237
  result['fill_fields'] = @fill_fields
238
+ result['max_buffer_size'] = @max_buffer_size
213
239
  return result
214
240
  end
215
241
 
@@ -218,6 +244,7 @@ module OpenC3
218
244
  result['discard_leading_bytes'] = @discard_leading_bytes
219
245
  result['sync_pattern'] = @sync_pattern.inspect
220
246
  result['fill_fields'] = @fill_fields
247
+ result['max_buffer_size'] = @max_buffer_size
221
248
  return result
222
249
  end
223
250
  end
File without changes
File without changes
File without changes
@@ -168,6 +168,13 @@ module OpenC3
168
168
  raise "Length value received larger than max_length: #{length} > #{@max_length}" if @max_length and length > @max_length
169
169
 
170
170
  packet_length = (length * @length_bytes_per_count) + @length_value_offset
171
+ # Reject up front rather than buffering the declared number of bytes first
172
+ if packet_length > @max_buffer_size
173
+ reset() # Drop the partial frame rather than holding it until disconnect
174
+ raise "Calculated packet length of #{packet_length} bytes exceeds maximum buffer size of #{@max_buffer_size} bytes. " \
175
+ "Increase OPENC3_PROTOCOL_MAX_BUFFER_SIZE."
176
+ end
177
+
171
178
  # Ensure the calculated packet length is long enough to support the location of the length field
172
179
  # without overlap into the next packet
173
180
  if (packet_length * 8) < (@length_bit_offset + @length_bit_size)