Skip to content

Commit b222aed

Browse files
yudataguyMikefly123ineskhou
authored
Add Antenna Depolyer Param for Startup Sequence (#93)
* add antenna deploy seq, need to fix tests * fix test * fix test * fix test * Appease Linter * removed new testing * idk man * corrected syntax * returned the guy * back cmake * removing some tests * up the table size * fix solar current and another antenna deployment test * Appease the Linter (Again) --------- Co-authored-by: Michael Pham <[email protected]> Co-authored-by: ineskhou <[email protected]> Co-authored-by: ineskhou <[email protected]>
1 parent d228c7a commit b222aed

File tree

8 files changed

+135
-12
lines changed

8 files changed

+135
-12
lines changed

CMakeLists.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,5 +34,11 @@ fprime_setup_included_code()
3434

3535
# This includes project-wide objects
3636
add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/FprimeZephyrReference")
37+
if (FPRIME_USE_POSIX)
38+
set_target_properties(Drv_Ip PROPERTIES EXCLUDE_FROM_ALL TRUE)
39+
set_target_properties(Drv_TcpServer PROPERTIES EXCLUDE_FROM_ALL TRUE)
40+
set_target_properties(Drv_TcpClient PROPERTIES EXCLUDE_FROM_ALL TRUE)
41+
set_target_properties(Drv_Udp PROPERTIES EXCLUDE_FROM_ALL TRUE)
42+
endif()
3743
set_target_properties(Svc_FatalHandler PROPERTIES EXCLUDE_FROM_ALL TRUE)
3844
set_target_properties(fprime-zephyr_Drv_ZephyrSpiDriver PROPERTIES EXCLUDE_FROM_ALL TRUE)

FprimeZephyrReference/Components/AntennaDeployer/AntennaDeployer.cpp

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
#include "FprimeZephyrReference/Components/AntennaDeployer/AntennaDeployer.hpp"
22

3+
#include "Os/File.hpp"
4+
#include "Os/FileSystem.hpp"
5+
36
namespace Components {
47

58
// ----------------------------------------------------------------------
@@ -61,6 +64,13 @@ void AntennaDeployer ::distanceIn_handler(FwIndexType portNum, F32 distance, boo
6164
// ----------------------------------------------------------------------
6265

6366
void AntennaDeployer ::DEPLOY_cmdHandler(FwOpcodeType opCode, U32 cmdSeq) {
67+
// Check if antenna has already been deployed
68+
if (this->readDeploymentState()) {
69+
this->log_ACTIVITY_HI_DeploymentAlreadyComplete();
70+
this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK);
71+
return;
72+
}
73+
6474
if (this->m_state != DeploymentState::IDLE) {
6575
this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::BUSY);
6676
return;
@@ -81,6 +91,28 @@ void AntennaDeployer ::DEPLOY_STOP_cmdHandler(FwOpcodeType opCode, U32 cmdSeq) {
8191
this->finishDeployment(Components::DeployResult::DEPLOY_RESULT_ABORT);
8292
}
8393

94+
void AntennaDeployer ::RESET_DEPLOYMENT_STATE_cmdHandler(FwOpcodeType opCode, U32 cmdSeq) {
95+
Fw::ParamValid is_valid;
96+
auto file_path = this->paramGet_DEPLOYED_STATE_FILE(is_valid);
97+
FW_ASSERT(is_valid == Fw::ParamValid::VALID || is_valid == Fw::ParamValid::DEFAULT);
98+
99+
(void)Os::FileSystem::removeFile(file_path.toChar());
100+
this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK);
101+
}
102+
103+
void AntennaDeployer ::SET_DEPLOYMENT_STATE_cmdHandler(FwOpcodeType opCode, U32 cmdSeq, bool deployed) {
104+
if (deployed) {
105+
this->writeDeploymentState();
106+
} else {
107+
Fw::ParamValid is_valid;
108+
auto file_path = this->paramGet_DEPLOYED_STATE_FILE(is_valid);
109+
FW_ASSERT(is_valid == Fw::ParamValid::VALID || is_valid == Fw::ParamValid::DEFAULT);
110+
(void)Os::FileSystem::removeFile(file_path.toChar());
111+
}
112+
113+
this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK);
114+
}
115+
84116
// ----------------------------------------------------------------------
85117
// Internal helpers
86118
// ----------------------------------------------------------------------
@@ -213,6 +245,9 @@ void AntennaDeployer ::finishDeployment(Components::DeployResult result) {
213245

214246
if (result == Components::DeployResult::DEPLOY_RESULT_SUCCESS) {
215247
this->log_ACTIVITY_HI_DeploySuccess(this->m_currentAttempt);
248+
249+
// Mark antenna as deployed by writing state file
250+
this->writeDeploymentState();
216251
}
217252

218253
this->log_ACTIVITY_HI_DeployFinish(result, this->m_currentAttempt);
@@ -266,4 +301,31 @@ void AntennaDeployer ::logBurnSignalCount() {
266301
}
267302
}
268303

304+
bool AntennaDeployer ::readDeploymentState() {
305+
Fw::ParamValid is_valid;
306+
auto file_path = this->paramGet_DEPLOYED_STATE_FILE(is_valid);
307+
FW_ASSERT(is_valid == Fw::ParamValid::VALID || is_valid == Fw::ParamValid::DEFAULT);
308+
309+
Os::File file;
310+
Os::File::Status status = file.open(file_path.toChar(), Os::File::OPEN_READ);
311+
bool deployed = (status == Os::File::OP_OK);
312+
(void)file.close();
313+
return deployed;
314+
}
315+
316+
void AntennaDeployer ::writeDeploymentState() {
317+
Fw::ParamValid is_valid;
318+
auto file_path = this->paramGet_DEPLOYED_STATE_FILE(is_valid);
319+
FW_ASSERT(is_valid == Fw::ParamValid::VALID || is_valid == Fw::ParamValid::DEFAULT);
320+
321+
Os::File file;
322+
Os::File::Status status = file.open(file_path.toChar(), Os::File::OPEN_CREATE, Os::File::OVERWRITE);
323+
if (status == Os::File::OP_OK) {
324+
U8 marker = 1;
325+
FwSizeType size = sizeof(marker);
326+
(void)file.write(&marker, size);
327+
}
328+
(void)file.close();
329+
}
330+
269331
} // namespace Components

FprimeZephyrReference/Components/AntennaDeployer/AntennaDeployer.fpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,14 @@ module Components {
2525
@ DEPLOY_STOP stops the deployment procedure
2626
sync command DEPLOY_STOP()
2727

28+
@ RESET_DEPLOYMENT_STATE resets the deployment state flag for ground testing
29+
sync command RESET_DEPLOYMENT_STATE()
30+
31+
@ SET_DEPLOYMENT_STATE forces the persistent deployment state for ground testing
32+
sync command SET_DEPLOYMENT_STATE(
33+
deployed: bool @< True to mark as deployed, false to clear the flag
34+
)
35+
2836
######################################################################
2937
# Telemetry
3038
######################################################################
@@ -74,6 +82,11 @@ module Components {
7482
) severity activity low \
7583
format "Burn signal active for {} scheduler ticks"
7684

85+
@ Emitted when deployment is skipped because antenna was already deployed
86+
event DeploymentAlreadyComplete() \
87+
severity activity high \
88+
format "Antenna deployment skipped - antenna already deployed"
89+
7790
######################################################################
7891
# Ports
7992
######################################################################
@@ -113,6 +126,9 @@ module Components {
113126
@ Distance readings below this value (cm) are considered invalid
114127
param INVALID_THRESHOLD_BOTTOM_CM: F32 default 0.1
115128

129+
@ File path for persistent deployment state (file exists = deployed)
130+
param DEPLOYED_STATE_FILE: string default "/antenna_deployed.bin"
131+
116132
########################################################################
117133
# Standard AC Ports: Required for Channels, Events, Commands, Parameters
118134
########################################################################

FprimeZephyrReference/Components/AntennaDeployer/AntennaDeployer.hpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ class AntennaDeployer final : public AntennaDeployerComponentBase {
3636
// ----------------------------------------------------------------------
3737
void DEPLOY_cmdHandler(FwOpcodeType opCode, U32 cmdSeq) override;
3838
void DEPLOY_STOP_cmdHandler(FwOpcodeType opCode, U32 cmdSeq) override;
39+
void RESET_DEPLOYMENT_STATE_cmdHandler(FwOpcodeType opCode, U32 cmdSeq) override;
40+
void SET_DEPLOYMENT_STATE_cmdHandler(FwOpcodeType opCode, U32 cmdSeq, bool deployed) override;
3941

4042
// ----------------------------------------------------------------------
4143
// Internal helpers
@@ -53,6 +55,8 @@ class AntennaDeployer final : public AntennaDeployerComponentBase {
5355
bool isDistanceDeployed(F32 distance);
5456
void ensureBurnwireStopped();
5557
void logBurnSignalCount();
58+
bool readDeploymentState();
59+
void writeDeploymentState();
5660

5761
DeploymentState m_state = DeploymentState::IDLE;
5862
U32 m_currentAttempt = 0;

FprimeZephyrReference/project/config/CommandDispatcherImplCfg.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
// Define configuration values for dispatcher
1212

1313
enum {
14-
CMD_DISPATCHER_DISPATCH_TABLE_SIZE = 100, // !< The size of the table holding opcodes to dispatch
14+
CMD_DISPATCHER_DISPATCH_TABLE_SIZE = 128, // !< The size of the table holding opcodes to dispatch
1515
CMD_DISPATCHER_SEQUENCER_TABLE_SIZE = 10, // !< The size of the table holding commands in progress
1616
};
1717

FprimeZephyrReference/test/int/antenna_deployer_test.py

Lines changed: 41 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ def test_deploy_without_distance_sensor(fprime_test_api: IntegrationTestAPI, sta
5757
proves_send_and_assert_command(fprime_test_api, f"{antenna_deployer}.DEPLOY")
5858

5959
attempt_event: EventData = fprime_test_api.assert_event(
60-
f"{antenna_deployer}.DeployAttempt", args=[1], timeout=5
60+
f"{antenna_deployer}.DeployAttempt", timeout=5
6161
)
6262
assert attempt_event.args[0].val == 1, (
6363
"First deployment attempt should be attempt #1"
@@ -98,7 +98,7 @@ def test_change_quiet_time_sec(fprime_test_api: IntegrationTestAPI, start_gds):
9898

9999
# Verify deployment attempt starts after quiet time expires
100100
attempt_event: EventData = fprime_test_api.assert_event(
101-
f"{antenna_deployer}.DeployAttempt", args=[1], timeout=2
101+
f"{antenna_deployer}.DeployAttempt", timeout=2
102102
)
103103
assert attempt_event.args[0].val == 1, (
104104
"First deployment attempt should be attempt #1"
@@ -140,7 +140,7 @@ def test_multiple_deploy_attempts(fprime_test_api: IntegrationTestAPI, start_gds
140140

141141
# Verify first attempt
142142
attempt_event: EventData = fprime_test_api.assert_event(
143-
f"{antenna_deployer}.DeployAttempt", args=[1], timeout=5
143+
f"{antenna_deployer}.DeployAttempt", timeout=5
144144
)
145145
assert attempt_event.args[0].val == 1, "First attempt should be #1"
146146

@@ -153,7 +153,7 @@ def test_multiple_deploy_attempts(fprime_test_api: IntegrationTestAPI, start_gds
153153

154154
# Wait for retry delay and verify second attempt
155155
attempt_event = fprime_test_api.assert_event(
156-
f"{antenna_deployer}.DeployAttempt", args=[2], timeout=15
156+
f"{antenna_deployer}.DeployAttempt", timeout=15
157157
)
158158
assert attempt_event.args[0].val == 2, "Second attempt should be #2"
159159

@@ -166,7 +166,7 @@ def test_multiple_deploy_attempts(fprime_test_api: IntegrationTestAPI, start_gds
166166

167167
# Wait for retry delay and verify third attempt
168168
attempt_event = fprime_test_api.assert_event(
169-
f"{antenna_deployer}.DeployAttempt", args=[3], timeout=15
169+
f"{antenna_deployer}.DeployAttempt", timeout=15
170170
)
171171
assert attempt_event.args[0].val == 3, "Third attempt should be #3"
172172

@@ -205,7 +205,7 @@ def test_burn_duration_sec(fprime_test_api: IntegrationTestAPI, start_gds):
205205

206206
# Wait for deployment attempt to start
207207
attempt_event: EventData = fprime_test_api.assert_event(
208-
f"{antenna_deployer}.DeployAttempt", args=[1], timeout=5
208+
f"{antenna_deployer}.DeployAttempt", timeout=5
209209
)
210210
assert attempt_event.args[0].val == 1, (
211211
"First deployment attempt should be attempt #1"
@@ -230,3 +230,38 @@ def test_burn_duration_sec(fprime_test_api: IntegrationTestAPI, start_gds):
230230
f"{antenna_deployer}.DeployFinish", timeout=10
231231
)
232232
assert finish_event.args[0].val == "DEPLOY_RESULT_FAILED"
233+
234+
235+
def test_deployment_prevention_after_success(
236+
fprime_test_api: IntegrationTestAPI, start_gds
237+
):
238+
"""Verify that deployment is prevented once the deployed-state flag is asserted and can be reset"""
239+
240+
# Ensure the persistent flag is cleared before starting
241+
proves_send_and_assert_command(
242+
fprime_test_api, f"{antenna_deployer}.SET_DEPLOYMENT_STATE", [False]
243+
)
244+
245+
# Force the antenna to appear deployed without completing a deployment cycle
246+
proves_send_and_assert_command(
247+
fprime_test_api, f"{antenna_deployer}.SET_DEPLOYMENT_STATE", [True]
248+
)
249+
250+
fprime_test_api.clear_histories()
251+
252+
# Deployment should be skipped immediately
253+
proves_send_and_assert_command(fprime_test_api, f"{antenna_deployer}.DEPLOY")
254+
fprime_test_api.assert_event(
255+
f"{antenna_deployer}.DeploymentAlreadyComplete", timeout=2
256+
)
257+
# Verify that DeployAttempt event does NOT occur (assert_event will raise AssertionError if event is missing)
258+
with pytest.raises(AssertionError):
259+
fprime_test_api.assert_event(f"{antenna_deployer}.DeployAttempt", timeout=1)
260+
261+
# Clear the flag and confirm deployments are permitted again
262+
proves_send_and_assert_command(
263+
fprime_test_api, f"{antenna_deployer}.SET_DEPLOYMENT_STATE", [False]
264+
)
265+
fprime_test_api.clear_histories()
266+
proves_send_and_assert_command(fprime_test_api, f"{antenna_deployer}.DEPLOY")
267+
fprime_test_api.assert_event(f"{antenna_deployer}.DeployAttempt", timeout=5)

FprimeZephyrReference/test/int/power_monitor_test.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ def test_01_power_manager_telemetry(fprime_test_api: IntegrationTestAPI, start_g
4242
sol_voltage: ChData = fprime_test_api.assert_telemetry(
4343
f"{ina219SolManager}.Voltage", start=start, timeout=65
4444
)
45-
sol_current: ChData = fprime_test_api.assert_telemetry(
45+
_: ChData = fprime_test_api.assert_telemetry(
4646
f"{ina219SolManager}.Current", start=start, timeout=65
4747
)
4848
_: ChData = fprime_test_api.assert_telemetry(
@@ -54,14 +54,16 @@ def test_01_power_manager_telemetry(fprime_test_api: IntegrationTestAPI, start_g
5454
sys_current_reading: dict[float] = sys_current.get_val()
5555
# sys_power_reading: dict[float] = sys_power.get_val()
5656
sol_voltage_reading: dict[float] = sol_voltage.get_val()
57-
sol_current_reading: dict[float] = sol_current.get_val()
57+
# sol_current_reading: dict[float] = sol_current.get_val()
5858
# sol_power_reading: dict[float] = sol_power.get_val()
5959

6060
assert sys_voltage_reading != 0, "System voltage reading should be non-zero"
6161
assert sys_current_reading != 0, "System current reading should be non-zero"
6262
# assert sys_power_reading != 0, "System power reading should be non-zero"
6363
assert sol_voltage_reading != 0, "Solar voltage reading should be non-zero"
64-
assert sol_current_reading != 0, "Solar current reading should be non-zero"
64+
# Solar current can be 0.0 in valid scenarios (no sunlight, etc.)
65+
# Existence is already verified by assert_telemetry() above
66+
# assert sol_current_reading != 0, "Solar current reading should be non-zero"
6567
# assert sol_power_reading != 0, "Solar power reading should be non-zero"
6668

6769

sequences/startup.seq

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@ R00:00:00 ReferenceDeployment.antennaDeployer.DEPLOY
55
R00:00:00 ReferenceDeployment.startupManager.ARMED_PRM_SET FALSE
66
R00:00:00 ReferenceDeployment.startupManager.ARMED_PRM_SAVE
77

8-
; TODO: ARM antenna deployment
9-
108
R00:00:00 FileHandling.prmDb.PRM_SAVE_FILE
119

1210
R00:00:00 ReferenceDeployment.lora.TRANSMIT ENABLED

0 commit comments

Comments
 (0)