diff --git a/backend/proto/ControlMessage.proto b/backend/proto/ControlMessage.proto index adad85b..b287334 100644 --- a/backend/proto/ControlMessage.proto +++ b/backend/proto/ControlMessage.proto @@ -87,6 +87,10 @@ message SystemState { // SoarProto v1.3.2 SYS_HEARTBEAT_LOSS_HALF_WARNING = 5; // The system has lost heartbeat and 1/2 of the time to abort has passed SYS_HEARTBEAT_LOST_ABORTING = 6; // The system has lost heartbeat and is aborting + SYS_WAIT = 7; // System has sent commands to DMB + SYS_RETRANSMIT = 8; // System timeout or receive nak from DMB + SYS_TIMEOUT = 9; // System does not receive ack in a fixed time window + SYS_SEND_NEXT_CMD = 10; // System receives ack or retransmit twice } State sys_state = 1; // The current state of the system diff --git a/backend/proto/CoreProto.proto b/backend/proto/CoreProto.proto index 570edac..1889755 100644 --- a/backend/proto/CoreProto.proto +++ b/backend/proto/CoreProto.proto @@ -51,4 +51,6 @@ enum RocketState { RS_ABORT = 10; RS_TEST = 11; RS_NONE = 12; + RS_LISTENING = 13; + RS_READY_FOR_CMD = 14; } \ No newline at end of file diff --git a/backend/proto/Python/CommandMessage_pb2.py b/backend/proto/Python/CommandMessage_pb2.py index 0a3f2df..08d2980 100644 --- a/backend/proto/Python/CommandMessage_pb2.py +++ b/backend/proto/Python/CommandMessage_pb2.py @@ -1,12 +1,22 @@ # -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! +# NO CHECKED-IN PROTOBUF GENCODE # source: CommandMessage.proto -# Protobuf Python Version: 4.25.3 +# Protobuf Python Version: 5.28.3 """Generated protocol buffer code.""" from google.protobuf import descriptor as _descriptor from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import runtime_version as _runtime_version from google.protobuf import symbol_database as _symbol_database from google.protobuf.internal import builder as _builder +_runtime_version.ValidateProtobufRuntimeVersion( + _runtime_version.Domain.PUBLIC, + 5, + 28, + 3, + '', + 'CommandMessage.proto' +) # @@protoc_insertion_point(imports) _sym_db = _symbol_database.Default() @@ -20,8 +30,8 @@ _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'CommandMessage_pb2', _globals) -if _descriptor._USE_C_DESCRIPTORS == False: - DESCRIPTOR._options = None +if not _descriptor._USE_C_DESCRIPTORS: + DESCRIPTOR._loaded_options = None _globals['_COMMANDMESSAGE']._serialized_start=49 _globals['_COMMANDMESSAGE']._serialized_end=331 _globals['_DMBCOMMAND']._serialized_start=334 diff --git a/backend/proto/Python/ControlMessage_pb2.py b/backend/proto/Python/ControlMessage_pb2.py index 03c3fa4..37304c2 100644 --- a/backend/proto/Python/ControlMessage_pb2.py +++ b/backend/proto/Python/ControlMessage_pb2.py @@ -1,12 +1,22 @@ # -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! +# NO CHECKED-IN PROTOBUF GENCODE # source: ControlMessage.proto -# Protobuf Python Version: 4.25.3 +# Protobuf Python Version: 5.28.3 """Generated protocol buffer code.""" from google.protobuf import descriptor as _descriptor from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import runtime_version as _runtime_version from google.protobuf import symbol_database as _symbol_database from google.protobuf.internal import builder as _builder +_runtime_version.ValidateProtobufRuntimeVersion( + _runtime_version.Domain.PUBLIC, + 5, + 28, + 3, + '', + 'ControlMessage.proto' +) # @@protoc_insertion_point(imports) _sym_db = _symbol_database.Default() @@ -15,13 +25,13 @@ import CoreProto_pb2 as CoreProto__pb2 -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x14\x43ontrolMessage.proto\x12\x05Proto\x1a\x0f\x43oreProto.proto\"\xec\x02\n\x0e\x43ontrolMessage\x12\x1b\n\x06source\x18\x01 \x01(\x0e\x32\x0b.Proto.Node\x12\x1b\n\x06target\x18\x02 \x01(\x0e\x32\x0b.Proto.Node\x12\x1b\n\x13source_sequence_num\x18\x04 \x01(\r\x12\x1d\n\x03\x61\x63k\x18\x05 \x01(\x0b\x32\x0e.Proto.AckNackH\x00\x12\x1e\n\x04nack\x18\x06 \x01(\x0b\x32\x0e.Proto.AckNackH\x00\x12\x1b\n\x04ping\x18\x07 \x01(\x0b\x32\x0b.Proto.PingH\x00\x12\x1e\n\x02hb\x18\x08 \x01(\x0b\x32\x10.Proto.HeartbeatH\x00\x12\'\n\tsys_state\x18\t \x01(\x0b\x32\x12.Proto.SystemStateH\x00\x12(\n\x08sys_ctrl\x18\n \x01(\x0b\x32\x14.Proto.SystemControlH\x00\x12)\n\x08hb_state\x18\x0b \x01(\x0b\x32\x15.Proto.HeartbeatStateH\x00\x42\t\n\x07message\"w\n\x07\x41\x63kNack\x12&\n\x11\x61\x63king_msg_source\x18\x01 \x01(\x0e\x32\x0b.Proto.Node\x12\'\n\racking_msg_id\x18\x02 \x01(\x0e\x32\x10.Proto.MessageID\x12\x1b\n\x13\x61\x63king_sequence_num\x18\x03 \x01(\r\"d\n\x04Ping\x12\x13\n\x0bping_ack_id\x18\x01 \x01(\r\x12\"\n\x1aping_response_sequence_num\x18\x02 \x01(\r\x12#\n\x1bsys_state_response_required\x18\x03 \x01(\x08\"-\n\tHeartbeat\x12 \n\x18hb_response_sequence_num\x18\x01 \x01(\r\"\xc4\x02\n\x0bSystemState\x12+\n\tsys_state\x18\x01 \x01(\x0e\x32\x18.Proto.SystemState.State\x12-\n\x0crocket_state\x18\x02 \x01(\x0e\x32\x12.Proto.RocketStateH\x00\x88\x01\x01\"\xc7\x01\n\x05State\x12\x0f\n\x0bSYS_INVALID\x10\x00\x12\x17\n\x13SYS_BOOTUP_COMPLETE\x10\x01\x12\x1c\n\x18SYS_ASSERT_FAILURE_RESET\x10\x02\x12\x16\n\x12SYS_UNCAUGHT_RESET\x10\x03\x12\x18\n\x14SYS_NORMAL_OPERATION\x10\x04\x12#\n\x1fSYS_HEARTBEAT_LOSS_HALF_WARNING\x10\x05\x12\x1f\n\x1bSYS_HEARTBEAT_LOST_ABORTING\x10\x06\x42\x0f\n\r_rocket_state\"\xb2\x02\n\rSystemControl\x12-\n\x07sys_cmd\x18\x01 \x01(\x0e\x32\x1c.Proto.SystemControl.Command\x12\x11\n\tcmd_param\x18\x02 \x01(\r\"\xde\x01\n\x07\x43ommand\x12\x0f\n\x0bSYS_INVALID\x10\x00\x12\r\n\tSYS_RESET\x10\x01\x12\x13\n\x0fSYS_FLASH_ERASE\x10\x02\x12\x19\n\x15SYS_LOG_PERIOD_CHANGE\x10\x03\x12\x14\n\x10HEARTBEAT_ENABLE\x10\x04\x12\x15\n\x11HEARTBEAT_DISABLE\x10\x05\x12\x18\n\x14SYS_FLASH_LOG_ENABLE\x10\x06\x12\x19\n\x15SYS_FLASH_LOG_DISABLE\x10\x07\x12!\n\x1dSYS_CRITICAL_FLASH_FULL_ERASE\x10\x08\"\xbf\x01\n\x0eHeartbeatState\x12\x35\n\x0btimer_state\x18\x01 \x01(\x0e\x32 .Proto.HeartbeatState.TimerState\x12\x14\n\x0ctimer_period\x18\x02 \x01(\r\x12\x17\n\x0ftimer_remaining\x18\x03 \x01(\r\"G\n\nTimerState\x12\x11\n\rUNINITIALIZED\x10\x00\x12\x0c\n\x08\x43OUNTING\x10\x01\x12\n\n\x06PAUSED\x10\x02\x12\x0c\n\x08\x43OMPLETE\x10\x03\x62\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x14\x43ontrolMessage.proto\x12\x05Proto\x1a\x0f\x43oreProto.proto\"\xec\x02\n\x0e\x43ontrolMessage\x12\x1b\n\x06source\x18\x01 \x01(\x0e\x32\x0b.Proto.Node\x12\x1b\n\x06target\x18\x02 \x01(\x0e\x32\x0b.Proto.Node\x12\x1b\n\x13source_sequence_num\x18\x04 \x01(\r\x12\x1d\n\x03\x61\x63k\x18\x05 \x01(\x0b\x32\x0e.Proto.AckNackH\x00\x12\x1e\n\x04nack\x18\x06 \x01(\x0b\x32\x0e.Proto.AckNackH\x00\x12\x1b\n\x04ping\x18\x07 \x01(\x0b\x32\x0b.Proto.PingH\x00\x12\x1e\n\x02hb\x18\x08 \x01(\x0b\x32\x10.Proto.HeartbeatH\x00\x12\'\n\tsys_state\x18\t \x01(\x0b\x32\x12.Proto.SystemStateH\x00\x12(\n\x08sys_ctrl\x18\n \x01(\x0b\x32\x14.Proto.SystemControlH\x00\x12)\n\x08hb_state\x18\x0b \x01(\x0b\x32\x15.Proto.HeartbeatStateH\x00\x42\t\n\x07message\"w\n\x07\x41\x63kNack\x12&\n\x11\x61\x63king_msg_source\x18\x01 \x01(\x0e\x32\x0b.Proto.Node\x12\'\n\racking_msg_id\x18\x02 \x01(\x0e\x32\x10.Proto.MessageID\x12\x1b\n\x13\x61\x63king_sequence_num\x18\x03 \x01(\r\"d\n\x04Ping\x12\x13\n\x0bping_ack_id\x18\x01 \x01(\r\x12\"\n\x1aping_response_sequence_num\x18\x02 \x01(\r\x12#\n\x1bsys_state_response_required\x18\x03 \x01(\x08\"-\n\tHeartbeat\x12 \n\x18hb_response_sequence_num\x18\x01 \x01(\r\"\x8e\x03\n\x0bSystemState\x12+\n\tsys_state\x18\x01 \x01(\x0e\x32\x18.Proto.SystemState.State\x12-\n\x0crocket_state\x18\x02 \x01(\x0e\x32\x12.Proto.RocketStateH\x00\x88\x01\x01\"\x91\x02\n\x05State\x12\x0f\n\x0bSYS_INVALID\x10\x00\x12\x17\n\x13SYS_BOOTUP_COMPLETE\x10\x01\x12\x1c\n\x18SYS_ASSERT_FAILURE_RESET\x10\x02\x12\x16\n\x12SYS_UNCAUGHT_RESET\x10\x03\x12\x18\n\x14SYS_NORMAL_OPERATION\x10\x04\x12#\n\x1fSYS_HEARTBEAT_LOSS_HALF_WARNING\x10\x05\x12\x1f\n\x1bSYS_HEARTBEAT_LOST_ABORTING\x10\x06\x12\x0c\n\x08SYS_WAIT\x10\x07\x12\x12\n\x0eSYS_RETRANSMIT\x10\x08\x12\x0f\n\x0bSYS_TIMEOUT\x10\t\x12\x15\n\x11SYS_SEND_NEXT_CMD\x10\nB\x0f\n\r_rocket_state\"\xb2\x02\n\rSystemControl\x12-\n\x07sys_cmd\x18\x01 \x01(\x0e\x32\x1c.Proto.SystemControl.Command\x12\x11\n\tcmd_param\x18\x02 \x01(\r\"\xde\x01\n\x07\x43ommand\x12\x0f\n\x0bSYS_INVALID\x10\x00\x12\r\n\tSYS_RESET\x10\x01\x12\x13\n\x0fSYS_FLASH_ERASE\x10\x02\x12\x19\n\x15SYS_LOG_PERIOD_CHANGE\x10\x03\x12\x14\n\x10HEARTBEAT_ENABLE\x10\x04\x12\x15\n\x11HEARTBEAT_DISABLE\x10\x05\x12\x18\n\x14SYS_FLASH_LOG_ENABLE\x10\x06\x12\x19\n\x15SYS_FLASH_LOG_DISABLE\x10\x07\x12!\n\x1dSYS_CRITICAL_FLASH_FULL_ERASE\x10\x08\"\xbf\x01\n\x0eHeartbeatState\x12\x35\n\x0btimer_state\x18\x01 \x01(\x0e\x32 .Proto.HeartbeatState.TimerState\x12\x14\n\x0ctimer_period\x18\x02 \x01(\r\x12\x17\n\x0ftimer_remaining\x18\x03 \x01(\r\"G\n\nTimerState\x12\x11\n\rUNINITIALIZED\x10\x00\x12\x0c\n\x08\x43OUNTING\x10\x01\x12\n\n\x06PAUSED\x10\x02\x12\x0c\n\x08\x43OMPLETE\x10\x03\x62\x06proto3') _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'ControlMessage_pb2', _globals) -if _descriptor._USE_C_DESCRIPTORS == False: - DESCRIPTOR._options = None +if not _descriptor._USE_C_DESCRIPTORS: + DESCRIPTOR._loaded_options = None _globals['_CONTROLMESSAGE']._serialized_start=49 _globals['_CONTROLMESSAGE']._serialized_end=413 _globals['_ACKNACK']._serialized_start=415 @@ -31,15 +41,15 @@ _globals['_HEARTBEAT']._serialized_start=638 _globals['_HEARTBEAT']._serialized_end=683 _globals['_SYSTEMSTATE']._serialized_start=686 - _globals['_SYSTEMSTATE']._serialized_end=1010 + _globals['_SYSTEMSTATE']._serialized_end=1084 _globals['_SYSTEMSTATE_STATE']._serialized_start=794 - _globals['_SYSTEMSTATE_STATE']._serialized_end=993 - _globals['_SYSTEMCONTROL']._serialized_start=1013 - _globals['_SYSTEMCONTROL']._serialized_end=1319 - _globals['_SYSTEMCONTROL_COMMAND']._serialized_start=1097 - _globals['_SYSTEMCONTROL_COMMAND']._serialized_end=1319 - _globals['_HEARTBEATSTATE']._serialized_start=1322 - _globals['_HEARTBEATSTATE']._serialized_end=1513 - _globals['_HEARTBEATSTATE_TIMERSTATE']._serialized_start=1442 - _globals['_HEARTBEATSTATE_TIMERSTATE']._serialized_end=1513 + _globals['_SYSTEMSTATE_STATE']._serialized_end=1067 + _globals['_SYSTEMCONTROL']._serialized_start=1087 + _globals['_SYSTEMCONTROL']._serialized_end=1393 + _globals['_SYSTEMCONTROL_COMMAND']._serialized_start=1171 + _globals['_SYSTEMCONTROL_COMMAND']._serialized_end=1393 + _globals['_HEARTBEATSTATE']._serialized_start=1396 + _globals['_HEARTBEATSTATE']._serialized_end=1587 + _globals['_HEARTBEATSTATE_TIMERSTATE']._serialized_start=1516 + _globals['_HEARTBEATSTATE_TIMERSTATE']._serialized_end=1587 # @@protoc_insertion_point(module_scope) diff --git a/backend/proto/Python/ControlMessage_pb2.pyi b/backend/proto/Python/ControlMessage_pb2.pyi index 5a9fc7c..2e74b15 100644 --- a/backend/proto/Python/ControlMessage_pb2.pyi +++ b/backend/proto/Python/ControlMessage_pb2.pyi @@ -67,6 +67,10 @@ class SystemState(_message.Message): SYS_NORMAL_OPERATION: _ClassVar[SystemState.State] SYS_HEARTBEAT_LOSS_HALF_WARNING: _ClassVar[SystemState.State] SYS_HEARTBEAT_LOST_ABORTING: _ClassVar[SystemState.State] + SYS_WAIT: _ClassVar[SystemState.State] + SYS_RETRANSMIT: _ClassVar[SystemState.State] + SYS_TIMEOUT: _ClassVar[SystemState.State] + SYS_SEND_NEXT_CMD: _ClassVar[SystemState.State] SYS_INVALID: SystemState.State SYS_BOOTUP_COMPLETE: SystemState.State SYS_ASSERT_FAILURE_RESET: SystemState.State @@ -74,6 +78,10 @@ class SystemState(_message.Message): SYS_NORMAL_OPERATION: SystemState.State SYS_HEARTBEAT_LOSS_HALF_WARNING: SystemState.State SYS_HEARTBEAT_LOST_ABORTING: SystemState.State + SYS_WAIT: SystemState.State + SYS_RETRANSMIT: SystemState.State + SYS_TIMEOUT: SystemState.State + SYS_SEND_NEXT_CMD: SystemState.State SYS_STATE_FIELD_NUMBER: _ClassVar[int] ROCKET_STATE_FIELD_NUMBER: _ClassVar[int] sys_state: SystemState.State diff --git a/backend/proto/Python/CoreProto_pb2.py b/backend/proto/Python/CoreProto_pb2.py index 3ca719a..1ffcae1 100644 --- a/backend/proto/Python/CoreProto_pb2.py +++ b/backend/proto/Python/CoreProto_pb2.py @@ -1,12 +1,22 @@ # -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! +# NO CHECKED-IN PROTOBUF GENCODE # source: CoreProto.proto -# Protobuf Python Version: 4.25.3 +# Protobuf Python Version: 5.28.3 """Generated protocol buffer code.""" from google.protobuf import descriptor as _descriptor from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import runtime_version as _runtime_version from google.protobuf import symbol_database as _symbol_database from google.protobuf.internal import builder as _builder +_runtime_version.ValidateProtobufRuntimeVersion( + _runtime_version.Domain.PUBLIC, + 5, + 28, + 3, + '', + 'CoreProto.proto' +) # @@protoc_insertion_point(imports) _sym_db = _symbol_database.Default() @@ -14,17 +24,17 @@ -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0f\x43oreProto.proto\x12\x05Proto*p\n\x04Node\x12\x10\n\x0cNODE_INVALID\x10\x00\x12\x10\n\x0cNODE_UNKNOWN\x10\x01\x12\x0c\n\x08NODE_ANY\x10\x02\x12\x0c\n\x08NODE_RCU\x10\x03\x12\x0c\n\x08NODE_DMB\x10\x04\x12\x0c\n\x08NODE_PBB\x10\x05\x12\x0c\n\x08NODE_SOB\x10\x06*w\n\tMessageID\x12\x0f\n\x0bMSG_INVALID\x10\x00\x12\x0f\n\x0bMSG_UNKNOWN\x10\x01\x12\x0f\n\x0bMSG_CONTROL\x10\x02\x12\x0f\n\x0bMSG_COMMAND\x10\x03\x12\x11\n\rMSG_TELEMETRY\x10\x04\x12\x13\n\x0fMSG_MAX_INVALID\x10\x05*\xcd\x01\n\x0bRocketState\x12\x0f\n\x0b\x44MB_INVALID\x10\x00\x12\x10\n\x0cRS_PRELAUNCH\x10\x01\x12\x0b\n\x07RS_FILL\x10\x02\x12\n\n\x06RS_ARM\x10\x03\x12\x0f\n\x0bRS_IGNITION\x10\x04\x12\r\n\tRS_LAUNCH\x10\x05\x12\x0b\n\x07RS_BURN\x10\x06\x12\x0c\n\x08RS_COAST\x10\x07\x12\x0e\n\nRS_DESCENT\x10\x08\x12\x0f\n\x0bRS_RECOVERY\x10\t\x12\x0c\n\x08RS_ABORT\x10\n\x12\x0b\n\x07RS_TEST\x10\x0b\x12\x0b\n\x07RS_NONE\x10\x0c\x62\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0f\x43oreProto.proto\x12\x05Proto*p\n\x04Node\x12\x10\n\x0cNODE_INVALID\x10\x00\x12\x10\n\x0cNODE_UNKNOWN\x10\x01\x12\x0c\n\x08NODE_ANY\x10\x02\x12\x0c\n\x08NODE_RCU\x10\x03\x12\x0c\n\x08NODE_DMB\x10\x04\x12\x0c\n\x08NODE_PBB\x10\x05\x12\x0c\n\x08NODE_SOB\x10\x06*w\n\tMessageID\x12\x0f\n\x0bMSG_INVALID\x10\x00\x12\x0f\n\x0bMSG_UNKNOWN\x10\x01\x12\x0f\n\x0bMSG_CONTROL\x10\x02\x12\x0f\n\x0bMSG_COMMAND\x10\x03\x12\x11\n\rMSG_TELEMETRY\x10\x04\x12\x13\n\x0fMSG_MAX_INVALID\x10\x05*\xf5\x01\n\x0bRocketState\x12\x0f\n\x0b\x44MB_INVALID\x10\x00\x12\x10\n\x0cRS_PRELAUNCH\x10\x01\x12\x0b\n\x07RS_FILL\x10\x02\x12\n\n\x06RS_ARM\x10\x03\x12\x0f\n\x0bRS_IGNITION\x10\x04\x12\r\n\tRS_LAUNCH\x10\x05\x12\x0b\n\x07RS_BURN\x10\x06\x12\x0c\n\x08RS_COAST\x10\x07\x12\x0e\n\nRS_DESCENT\x10\x08\x12\x0f\n\x0bRS_RECOVERY\x10\t\x12\x0c\n\x08RS_ABORT\x10\n\x12\x0b\n\x07RS_TEST\x10\x0b\x12\x0b\n\x07RS_NONE\x10\x0c\x12\x10\n\x0cRS_LISTENING\x10\r\x12\x14\n\x10RS_READY_FOR_CMD\x10\x0e\x62\x06proto3') _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'CoreProto_pb2', _globals) -if _descriptor._USE_C_DESCRIPTORS == False: - DESCRIPTOR._options = None +if not _descriptor._USE_C_DESCRIPTORS: + DESCRIPTOR._loaded_options = None _globals['_NODE']._serialized_start=26 _globals['_NODE']._serialized_end=138 _globals['_MESSAGEID']._serialized_start=140 _globals['_MESSAGEID']._serialized_end=259 _globals['_ROCKETSTATE']._serialized_start=262 - _globals['_ROCKETSTATE']._serialized_end=467 + _globals['_ROCKETSTATE']._serialized_end=507 # @@protoc_insertion_point(module_scope) diff --git a/backend/proto/Python/CoreProto_pb2.pyi b/backend/proto/Python/CoreProto_pb2.pyi index f3e32f5..2b2160f 100644 --- a/backend/proto/Python/CoreProto_pb2.pyi +++ b/backend/proto/Python/CoreProto_pb2.pyi @@ -38,6 +38,8 @@ class RocketState(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): RS_ABORT: _ClassVar[RocketState] RS_TEST: _ClassVar[RocketState] RS_NONE: _ClassVar[RocketState] + RS_LISTENING: _ClassVar[RocketState] + RS_READY_FOR_CMD: _ClassVar[RocketState] NODE_INVALID: Node NODE_UNKNOWN: Node NODE_ANY: Node @@ -64,3 +66,5 @@ RS_RECOVERY: RocketState RS_ABORT: RocketState RS_TEST: RocketState RS_NONE: RocketState +RS_LISTENING: RocketState +RS_READY_FOR_CMD: RocketState diff --git a/backend/proto/Python/TelemetryMessage_pb2.py b/backend/proto/Python/TelemetryMessage_pb2.py index 7f216db..da65274 100644 --- a/backend/proto/Python/TelemetryMessage_pb2.py +++ b/backend/proto/Python/TelemetryMessage_pb2.py @@ -1,12 +1,22 @@ # -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! +# NO CHECKED-IN PROTOBUF GENCODE # source: TelemetryMessage.proto -# Protobuf Python Version: 4.25.3 +# Protobuf Python Version: 5.28.3 """Generated protocol buffer code.""" from google.protobuf import descriptor as _descriptor from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import runtime_version as _runtime_version from google.protobuf import symbol_database as _symbol_database from google.protobuf.internal import builder as _builder +_runtime_version.ValidateProtobufRuntimeVersion( + _runtime_version.Domain.PUBLIC, + 5, + 28, + 3, + '', + 'TelemetryMessage.proto' +) # @@protoc_insertion_point(imports) _sym_db = _symbol_database.Default() @@ -20,8 +30,8 @@ _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'TelemetryMessage_pb2', _globals) -if _descriptor._USE_C_DESCRIPTORS == False: - DESCRIPTOR._options = None +if not _descriptor._USE_C_DESCRIPTORS: + DESCRIPTOR._loaded_options = None _globals['_TELEMETRYMESSAGE']._serialized_start=51 _globals['_TELEMETRYMESSAGE']._serialized_end=823 _globals['_GPS']._serialized_start=826 diff --git a/backend/src/CommControlMsg.puml b/backend/src/CommControlMsg.puml new file mode 100644 index 0000000..35d9b77 --- /dev/null +++ b/backend/src/CommControlMsg.puml @@ -0,0 +1,14 @@ +@startuml +[*] -right-> RCUInitialized : start +[*] -right-> RocketListening : start +RCUInitialized : RCU is on +RCUInitialized -right-> RCUWait : send first msg +RCUWait -up-> RCUTimeout : does not receive ack from rocket +RCUWait -up-> RCURetransmit : received nak from rocket +RCUWait -down-> RCUSendNextCMD : received ack from rocket +RCUWait -down-> RCUSendNextCMD : retransmit twice +RCUTimeout --> RCURetransmit +RCURetransmit --> RCUWait +RocketListening --> RocketInitialized : receive initialization sequence +RocketInitialized --> RocketReadyForCMD : send ack to rcu +@enduml \ No newline at end of file diff --git a/backend/src/SerialHandler.py b/backend/src/SerialHandler.py index 00f1869..0ab8fd1 100644 --- a/backend/src/SerialHandler.py +++ b/backend/src/SerialHandler.py @@ -4,25 +4,31 @@ import enum import multiprocessing as mp import threading -import time +import time, random import serial # You'll need to run `pip install pyserial` from cobs import cobs # pip install cobs import google.protobuf.message as Message +from queue import Queue # Project specific imports ======================================================================== import proto.Python.CoreProto_pb2 as ProtoCore import proto.Python.TelemetryMessage_pb2 as TelemetryProto import proto.Python.ControlMessage_pb2 as ControlProto +from proto.Python.ControlMessage_pb2 import AckNack + from src.support.Codec import Codec from src.support.ProtobufParser import ProtobufParser from src.support.CommonLogger import logger +from src.StateMachineManager import StateMachineManager from src.ThreadManager import THREAD_MESSAGE_DB_WRITE, THREAD_MESSAGE_HEARTBEAT_SERIAL, THREAD_MESSAGE_KILL, THREAD_MESSAGE_LOAD_CELL_VOLTAGE, THREAD_MESSAGE_SERIAL_WRITE, WorkQ_Message from src.Utils import Utils as utl + # Constants ======================================================================================== MIN_SERIAL_MESSAGE_LENGTH = 6 +TIME_OUT_PERIOD = 5 UART_SERIAL_PORT = "/dev/ttyAMA0" RADIO_SERIAL_PORT = "/dev/ttyUSB0" @@ -35,7 +41,7 @@ class SerialDevices(enum.Enum): # Class Definitions =============================================================================== class SerialHandler(): - def __init__(self, thread_name: str, port: str, baudrate: int, message_handler_workq: mp.Queue): + def __init__(self, thread_name: str, port: str, baudrate: int, message_handler_workq: mp.Queue, serial_event_queue : mp.Queue, state_change_event_queue: mp.Queue, serial_event: mp.Event, state_change_event: mp.Event): """ This thread class creates threads to handle incoming and outgoing serial messages over @@ -57,7 +63,14 @@ def __init__(self, thread_name: str, port: str, baudrate: int, message_handler_w self.thread_name = thread_name self.send_message_workq = message_handler_workq self.kill_rx = False - + self.serial_event_queue = serial_event_queue + self.state_change_event_queue = state_change_event_queue + self.serial_event = serial_event + self.state_change_event = state_change_event + self.current_ser_workq_msg = None + self.start_time = 0 + self.end_time = 0 + self.timer_start = False # Open serial serial port try: self.serial_port = serial.Serial(port=port, baudrate=baudrate, bytesize=8, parity=serial.PARITY_NONE, timeout=None, stopbits=serial.STOPBITS_ONE) @@ -85,30 +98,36 @@ def handle_serial_message(self): the data that was received. """ # Read the serial port - message = self._get_serial_message() - - if message == None: - return + # message = self._get_serial_message() + message = self.mock_received_message() - # Check message length - if len(message) < MIN_SERIAL_MESSAGE_LENGTH: - logger.warning(f"Message from {self.port} too short: {message}") + if message == None: + #Simulate not receiving any messages + print("No message during this time") return - # Decode, remove 0x00 byte - try: - msgId, data = Codec.Decode(message[:-1], len(message) - 1) - except cobs.DecodeError: - logger.warning(f"Invalid cobs message from {self.port}") - return + #Comment out to debug workflow with the state machine + # # Check message length + # if len(message) < MIN_SERIAL_MESSAGE_LENGTH: + # logger.warning(f"Message from {self.port} too short: {message}") + # return - # Process message according to ID - if msgId == ProtoCore.MessageID.MSG_TELEMETRY: - self.process_telemetry_message(data) - elif msgId == ProtoCore.MessageID.MSG_CONTROL: - self.process_control_message(data) - else: - logger.warning(f"Received invalid MessageID from {self.port}") + # # Decode, remove 0x00 byte + # try: + # msgId, data = Codec.Decode(message[:-1], len(message) - 1) + # except cobs.DecodeError: + # logger.warning(f"Invalid cobs message from {self.port}") + # return + + # # Process message according to ID + # if msgId == ProtoCore.MessageID.MSG_TELEMETRY: + # self.process_telemetry_message(data) + # elif msgId == ProtoCore.MessageID.MSG_CONTROL: + # self.process_control_message(data) + # else: + # logger.warning(f"Received invalid MessageID from {self.port}") + self.process_control_message(message) + def process_telemetry_message(self, data): """ @@ -159,6 +178,26 @@ def process_telemetry_message(self, data): self.send_message_workq.put(WorkQ_Message(self.thread_name, 'database', THREAD_MESSAGE_DB_WRITE, (ProtoCore.MessageID.MSG_TELEMETRY, json_str))) + def mock_received_message(self): + """ + Mock receiving message from the DMB. + """ + msg = None + mock_msg = [ProtoCore.MessageID.MSG_CONTROL] + choice = random.choice(mock_msg) + if choice == ProtoCore.MessageID.MSG_INVALID: + print("No message") + msg = None + elif choice == ProtoCore.MessageID.MSG_CONTROL: + msg = ControlProto.ControlMessage() + mock_control_msg = [1] + control_msg_choice = random.choice(mock_control_msg) + if control_msg_choice == 0: + msg.nack.acking_msg_id = 0 + elif control_msg_choice == 1: + msg.ack.acking_msg_id = 1 + return msg + def process_control_message(self, data): """ Process the incoming control message. @@ -167,24 +206,37 @@ def process_control_message(self, data): data (bytes): The data that was received. """ - received_message = ControlProto.ControlMessage() + #-------------UNCOMMENT THE TWO LINES BELOW ONCE THE BOARD IS OBTAINED-------------- + # received_message = ControlProto.ControlMessage() # Ensure we received a valid message - try: - received_message.ParseFromString(data) - except Message.DecodeError: - logger.warning(f"Unable to decode control message: {data}") - return - # Ensure the message is intended for us - if received_message.target == ProtoCore.NODE_RCU or received_message.target == ProtoCore.NODE_ANY: - control_message_type = received_message.WhichOneof('message') - logger.debug(f"Received {control_message_type} from {utl.get_node_from_enum(received_message.source)}") - else: - logger.debug(f"Received message intended for {utl.get_node_from_enum(received_message.target)}") - return - - json_str = ProtobufParser.parse_serial_to_json(data, ProtoCore.MessageID.MSG_CONTROL) - - self.send_message_workq.put(WorkQ_Message(self.thread_name, 'database', THREAD_MESSAGE_DB_WRITE, (ProtoCore.MessageID.MSG_CONTROL, json_str)))\ + # try: + # received_message.ParseFromString(data) + # except Message.DecodeError: + # logger.warning(f"Unable to decode control message: {data}") + # return + # # Ensure the message is intended for us + # if received_message.target == ProtoCore.NODE_RCU or received_message.target == ProtoCore.NODE_ANY: + # control_message_type = received_message.WhichOneof('message') + # logger.debug(f"Received {control_message_type} from {utl.get_node_from_enum(received_message.source)}") + # else: + # logger.debug(f"Received message intended for {utl.get_node_from_enum(received_message.target)}") + # return + response = None + #Check to see if it's nak or ack - Might be a better way to check for ACK vs NAK + if data.ack.acking_msg_id == 1: + response = "ACK" + elif data.nack.acking_msg_id == 0: + response = "NAK" + logger.info(f"Incoming thread received: {response}") + self.serial_event_queue.put(response) + self.serial_event.set() + + logger.info(f"Mock sending to database thread") + #-------------UNCOMMENT THE TWO LINES BELOW ONCE THE BOARD IS OBTAINED-------------- + + # json_str = ProtobufParser.parse_serial_to_json(data, ProtoCore.MessageID.MSG_CONTROL) + + # self.send_message_workq.put(WorkQ_Message(self.thread_name, 'database', THREAD_MESSAGE_DB_WRITE, (ProtoCore.MessageID.MSG_CONTROL, json_str)))\ def send_serial_command_message(self, command: str, target: str, command_param: int, source_sequence_number: int) -> bool: """ @@ -254,9 +306,13 @@ def serial_rx_thread(ser_han: SerialHandler): """ Thread function for the incoming serial data listening. """ - while not (ser_han.kill_rx): + counter_for_testing = 0 + # while not ser_han.kill_rx: + while counter_for_testing < 10: ser_han.handle_serial_message() - pass + counter_for_testing += 1 + time.sleep(4) + # pass def process_serial_workq_message(message: WorkQ_Message, ser_han: SerialHandler) -> bool: """ @@ -273,16 +329,23 @@ def process_serial_workq_message(message: WorkQ_Message, ser_han: SerialHandler) logger.debug(f"Killing {ser_han.thread_name} thread") return False elif messageID == THREAD_MESSAGE_SERIAL_WRITE: - command = message.message[0] - target = message.message[1] - command_param = message.message[2] - source_sequence_number = message.message[3] - ser_han.send_serial_command_message(command, target, command_param, source_sequence_number) + #-------------UNCOMMENT THE TWO LINES BELOW ONCE THE BOARD IS OBTAINED-------------- + # command = message.message[0] + # target = message.message[1] + # command_param = message.message[2] + # source_sequence_number = message.message[3] + print(f"Mock sending serial command message") + # ser_han.send_serial_command_message(command, target, command_param, source_sequence_number) elif messageID == THREAD_MESSAGE_HEARTBEAT_SERIAL: - ser_han.send_serial_control_message(message.message[0]) + print(f"Mock sending serial control message") + #-------------UNCOMMENT THE TWO LINES BELOW ONCE THE BOARD IS OBTAINED-------------- + # ser_han.send_serial_control_message(message.message[0]) + ser_han.current_ser_workq_msg = message + ser_han.serial_event_queue.put("WAIT") + ser_han.serial_event.set() return True -def serial_thread(thread_name: str, device: SerialDevices, baudrate: int, thread_workq: mp.Queue, message_handler_workq: mp.Queue): +def serial_thread(thread_name: str, device: SerialDevices, baudrate: int, thread_workq: mp.Queue, message_handler_workq: mp.Queue, serial_event_queue: mp.Queue, state_change_event_queue: mp.Queue, serial_event: mp.Event, state_change_event: mp.Event): """ Thread function for the incoming serial data listening. @@ -306,15 +369,46 @@ def serial_thread(thread_name: str, device: SerialDevices, baudrate: int, thread # This log line should be removed once the pi core issue is solved logger.info(f"{device.name} process: {os.getpid()}") serial_workq = thread_workq - ser_han = SerialHandler(thread_name, port, baudrate, message_handler_workq) - if ser_han.serial_port == None: - return + + #--------TO BE REMOVED----------- + #Mock putting messages in the workq + for i in range(10): + test_msg = WorkQ_Message('test1', 'test2', THREAD_MESSAGE_SERIAL_WRITE, (f"Outgoing command: {i}")) + serial_workq.put(test_msg) + logger.info(f"serial_workq size: {serial_workq.qsize()}") + #---------END COMMENTS TO BE REMOVED----------- + + ser_han = SerialHandler(thread_name, port, baudrate, message_handler_workq, serial_event_queue, state_change_event_queue, serial_event, state_change_event) + #-------------UNCOMMENT THE TWO LINES BELOW ONCE THE BOARD IS OBTAINED-------------- + # if ser_han.serial_port == None: + # return rx_thread = threading.Thread(target=serial_rx_thread, args=(ser_han,)) rx_thread.start() - while (1): + + counter_for_testing = 0 + while counter_for_testing < 10: + # while True: # then once the queue is empty read the serial port - if not process_serial_workq_message(serial_workq.get(), ser_han): - ser_han.kill_rx = True - rx_thread.join(10) - return + ser_han.state_change_event.wait() + # if ser_han.state_change_event.is_set(): + ser_han.state_change_event.clear() + if not ser_han.state_change_event_queue.empty(): + state_event = ser_han.state_change_event_queue.get() + print(f"Outgoing thread sending: {state_event}") + if state_event == ControlProto.SystemState.SYS_SEND_NEXT_CMD: + print("System in SYS_SEND_NEXT_CMD state") + if not process_serial_workq_message(serial_workq.get(), ser_han): + ser_han.kill_rx = True + rx_thread.join(10) + return + elif state_event == ControlProto.SystemState.SYS_RETRANSMIT: + print("System in SYS_RETRANSMIT state") + if ser_han.current_ser_workq_msg: + process_serial_workq_message(ser_han.current_ser_workq_msg, ser_han) + elif state_event == ControlProto.SystemState.SYS_WAIT: + print("System is in SYS_WAIT state") + counter_for_testing += 1 + print(f"counter_for_testing: {counter_for_testing}") + time.sleep(0.5) + diff --git a/backend/src/StateMachineManager.py b/backend/src/StateMachineManager.py new file mode 100644 index 0000000..942ccdc --- /dev/null +++ b/backend/src/StateMachineManager.py @@ -0,0 +1,111 @@ +""" +StateMachine.py + +This file will contain the class State and class Event to make things more modular and easier to add/remove +states and events in the future. This design pattern is selected to make it simple for a direct +translation between the FSM (Finite State Machine) and code. This aims to make it easier to understand +and work with for the future developers, who will be mostly students Both classes will utilize Enum +because it is a common way being used in our code base currently. + +The FSM diagram is CommControlMSG.puml. + +""" + +# General imports ================================================================================= +from enum import Enum, unique +import os, sys, time, random +from queue import Queue +import threading +import multiprocessing as mp +import google.protobuf.message as Message + +# Project specific imports ======================================================================== +from src.ThreadManager import * +from proto.Python.CoreProto_pb2 import RocketState +from proto.Python.ControlMessage_pb2 import SystemState + +# Class Definitions =============================================================================== +@unique +class Event(Enum): + """ + Represents the event that triggers the transition from one state to another. The events that trigger state transition + for the RCU and Rocket are both grouped in here. If there is a case to make RocketEvent and RCUEvent subclass to + inherit from the Event enum, we can explore that option at the time. For now, because state machine isn't being used + too much in our code base, we will stick with this for now. + + """ + RCU_SEND_MSG = 0 + RCU_RCVD_ACK = 1 + RCU_RCVD_NAK = 2 + RCU_NO_RCVD_ACK = 3 + RCU_RETRANSMIT_TWICE = 4 + RCU_EXIT = 5 + RCU_START = 6 + ROCKET_RCVD_CMD = 7 + ROCKET_SEND_ACK = 8 + +class StateMachineManager(): + """ + Manage state transitions for the communication between the RCU and the rocket. + + """ + def __init__(self, serial_event_queue: Queue, system_state_queue: Queue, serial_event: mp.Event, state_change_event: mp.Event): + self.retransmit_counter = 0 + self.serial_event_queue = serial_event_queue + self.system_state_queue = system_state_queue + self.serial_event = serial_event + self.state_change_event = state_change_event + + def start(self): + while True: + self.serial_event.wait() + self.serial_event.clear() + if not self.serial_event_queue.empty(): + queue_serial_event = self.serial_event_queue.get() + print(f"State machine process: {queue_serial_event}") + #Need this so we can start the timer to handle TIMEOUT event + if queue_serial_event == "WAIT": + print("State machine sets flag: SYS_WAIT") + response = SystemState.SYS_WAIT + elif queue_serial_event == "ACK": + print("State machine sets flag: SYS_SEND_NEXT_CMD") + response = SystemState.SYS_SEND_NEXT_CMD + elif queue_serial_event == "NAK": + if self.retransmit_counter < 2: + print("State machine sets flag: SYS_RETRANSMIT") + response = SystemState.SYS_RETRANSMIT + self.retransmit_counter += 1 + else: + print("State machine sets flag: SYS_SEND_NEXT_CMD") + response = SystemState.SYS_SEND_NEXT_CMD + self.retransmit_counter = 0 + elif queue_serial_event == "TIMEOUT": + if self.retransmit_counter < 2: + print("State machine sets flag: SYS_RETRANSMIT after TIMEOUT") + response = SystemState.SYS_RETRANSMIT + self.retransmit_counter += 1 + else: + print("State machine sets flag: SYS_SEND_NEXT_CMD") + response = SystemState.SYS_SEND_NEXT_CMD + self.retransmit_counter = 0 + #Put the new state in a shared queue + self.system_state_queue.put(response) + #Notify the outgoing serial thread + self.state_change_event.set() + + +# def state_machine_manager_thread (uart_queue: Queue, radio_queue: Queue, uart_event: mp.Event, radio_event: mp.Event): +def state_machine_manager_thread (serial_event_queue: Queue, system_state_queue: Queue, serial_event: mp.Event, system_state_event: mp.Event): + """ + State Machine manager function to start the state machine thread + """ + new_state_machine = StateMachineManager(serial_event_queue, system_state_queue, serial_event, system_state_event) + new_state_machine.start() + + + + + + + + diff --git a/backend/src/main(original).py b/backend/src/main(original).py new file mode 100644 index 0000000..f50062b --- /dev/null +++ b/backend/src/main(original).py @@ -0,0 +1,62 @@ + +# General imports ================================================================================= +import os, sys +import multiprocessing as mp + +# Project specific imports ======================================================================== +dirname, _ = os.path.split(os.path.abspath(__file__)) +sys.path.insert(0, os.path.join(dirname.split("backend", 1)[0], 'backend', 'proto/Python')) +sys.path.insert(0, os.path.join(dirname.split("backend", 1)[0], 'backend')) + +from src.support.CommonLogger import logger +from src.DatabaseHandler import database_thread +from src.HeartbeatHandler import heartbeat_thread +from src.SerialHandler import SerialDevices as sd, serial_thread +from src.ThreadManager import ThreadManager as tm +from src.LoadCellHandler import load_cell_thread + +# Constants ======================================================================================== +UART_BAUDRATE = 115200 +RADIO_BAUDRATE = 57600 + +# Local Procedures ================================================================================ +def initialize_threads(): + ''' + Create threads for the backend + ''' + logger.info('Initializing threads') + thread_pool = {} + uart_workq = mp.Queue() + radio_workq = mp.Queue() + db_workq = mp.Queue() + loadcell_workq = mp.Queue() + message_handler_workq = mp.Queue() + heartbeat_workq = mp.Queue() + + # Create a main thread for handling thread messages + thread_pool['message_handler'] = {'thread': None, 'workq': message_handler_workq} + + # Initialize the threads + uart_thread = mp.Process(target=serial_thread, args=('uart', sd.UART, UART_BAUDRATE, uart_workq, message_handler_workq)) + radio_thread = mp.Process(target=serial_thread, args=('radio', sd.RADIO, RADIO_BAUDRATE, radio_workq, message_handler_workq)) + db_thread = mp.Process(target=database_thread, args=('database', db_workq, message_handler_workq)) + lc_thread = mp.Process(target=load_cell_thread, args=('loadcell', loadcell_workq, message_handler_workq)) + hb_thread = mp.Process(target=heartbeat_thread, args=('heartbeat', heartbeat_workq, message_handler_workq)) + + # Add the threads to the thread pool + thread_pool['uart'] = {'thread': uart_thread, 'workq': uart_workq} + thread_pool['radio'] = {'thread': radio_thread, 'workq': radio_workq} + thread_pool['database'] = {'thread': db_thread, 'workq': db_workq} + thread_pool['loadcell'] = {'thread': lc_thread, 'workq': loadcell_workq} + thread_pool['heartbeat'] = {'thread': hb_thread, 'workq': heartbeat_workq} + + tm.thread_pool = thread_pool + return + +if __name__ == "__main__": + tm() + initialize_threads() + tm.start_threads() + + while 1: + tm.handle_thread_messages() \ No newline at end of file diff --git a/backend/src/main.py b/backend/src/main.py index f50062b..92684af 100644 --- a/backend/src/main.py +++ b/backend/src/main.py @@ -1,6 +1,6 @@ # General imports ================================================================================= -import os, sys +import os, sys, time import multiprocessing as mp # Project specific imports ======================================================================== @@ -14,6 +14,8 @@ from src.SerialHandler import SerialDevices as sd, serial_thread from src.ThreadManager import ThreadManager as tm from src.LoadCellHandler import load_cell_thread +from src.StateMachineManager import state_machine_manager_thread +from queue import Queue # Constants ======================================================================================== UART_BAUDRATE = 115200 @@ -31,32 +33,64 @@ def initialize_threads(): db_workq = mp.Queue() loadcell_workq = mp.Queue() message_handler_workq = mp.Queue() + uart_event_queue = mp.Queue() + radio_event_queue = mp.Queue() + radio_state_queue = mp.Queue() heartbeat_workq = mp.Queue() + uart_event = mp.Event() + radio_event = mp.Event() + radio_state_change_event = mp.Event() # Create a main thread for handling thread messages thread_pool['message_handler'] = {'thread': None, 'workq': message_handler_workq} # Initialize the threads - uart_thread = mp.Process(target=serial_thread, args=('uart', sd.UART, UART_BAUDRATE, uart_workq, message_handler_workq)) - radio_thread = mp.Process(target=serial_thread, args=('radio', sd.RADIO, RADIO_BAUDRATE, radio_workq, message_handler_workq)) - db_thread = mp.Process(target=database_thread, args=('database', db_workq, message_handler_workq)) - lc_thread = mp.Process(target=load_cell_thread, args=('loadcell', loadcell_workq, message_handler_workq)) - hb_thread = mp.Process(target=heartbeat_thread, args=('heartbeat', heartbeat_workq, message_handler_workq)) + # uart_thread = mp.Process(target=serial_thread, args=('uart', sd.UART, UART_BAUDRATE, uart_workq, message_handler_workq, uart_event_queue)) + radio_thread = mp.Process(target=serial_thread, args=('radio', sd.RADIO, RADIO_BAUDRATE, radio_workq, message_handler_workq, radio_event_queue, radio_state_queue, radio_event, radio_state_change_event)) + # db_thread = mp.Process(target=database_thread, args=('database', db_workq, message_handler_workq)) + # lc_thread = mp.Process(target=load_cell_thread, args=('loadcell', loadcell_workq, message_handler_workq)) + # hb_thread = mp.Process(target=heartbeat_thread, args=('heartbeat', heartbeat_workq, message_handler_workq)) + serial_state_machine_thread = mp.Process(target=state_machine_manager_thread, args=(radio_event_queue, radio_state_queue, radio_event, radio_state_change_event)) # Add the threads to the thread pool - thread_pool['uart'] = {'thread': uart_thread, 'workq': uart_workq} + # thread_pool['uart'] = {'thread': uart_thread, 'workq': uart_workq} thread_pool['radio'] = {'thread': radio_thread, 'workq': radio_workq} - thread_pool['database'] = {'thread': db_thread, 'workq': db_workq} - thread_pool['loadcell'] = {'thread': lc_thread, 'workq': loadcell_workq} - thread_pool['heartbeat'] = {'thread': hb_thread, 'workq': heartbeat_workq} + # thread_pool['database'] = {'thread': db_thread, 'workq': db_workq} + # thread_pool['loadcell'] = {'thread': lc_thread, 'workq': loadcell_workq} + # thread_pool['heartbeat'] = {'thread': hb_thread, 'workq': heartbeat_workq} + thread_pool['state_machine'] = {'thread': serial_state_machine_thread, 'workq': None} tm.thread_pool = thread_pool return if __name__ == "__main__": - tm() - initialize_threads() - tm.start_threads() + # tm() + # initialize_threads() + # tm.start_threads() + + # while 1: + # tm.handle_thread_messages() + + #Testing the work flow with the state machine integration into serial handler. + #Only testing the radio serial rx thread right now to keep things simple + #If need to do testing/debugging for longer, increment the time.sleep(X) to the desired number + #Without it, the threads will terminate immediately, thus, unable to do any debugging + radio_workq = mp.Queue() + message_handler_workq = mp.Queue() + radio_event_queue = mp.Queue() + radio_state_queue = mp.Queue() + radio_event = mp.Event() + radio_state_change_event = mp.Event() + radio_thread = mp.Process(target=serial_thread, args=('radio', sd.RADIO, RADIO_BAUDRATE, radio_workq, message_handler_workq, radio_event_queue, radio_state_queue, radio_event, radio_state_change_event)) + serial_state_machine_thread = mp.Process(target=state_machine_manager_thread, args=(radio_event_queue, radio_state_queue, radio_event, radio_state_change_event)) + radio_thread.start() + serial_state_machine_thread.start() + + time.sleep(400) + + radio_thread.terminate() + serial_state_machine_thread.terminate() + + radio_thread.join() + serial_state_machine_thread.join() - while 1: - tm.handle_thread_messages() \ No newline at end of file