eive-tmtc/eive_tmtc/tmtc/solar_array_deployment.py

145 lines
4.3 KiB
Python
Raw Normal View History

2022-10-13 18:04:35 +02:00
# -*- coding: utf-8 -*-
"""
@file solar_array_deployment.py
2023-06-19 17:16:00 +02:00
@brief The test function in this file simply returns a command which triggers the solar array
deployment.
2022-10-13 18:04:35 +02:00
@author J. Meier
@date 15.02.2021
"""
2023-02-01 11:17:04 +01:00
import logging
2022-10-13 18:04:35 +02:00
import struct
2023-01-20 12:19:57 +01:00
from spacepackets.ecss import PusTelecommand
2022-10-13 18:04:35 +02:00
from tmtccmd.config.tmtc import (
2023-11-22 14:13:00 +01:00
CmdTreeNode,
2022-10-13 18:04:35 +02:00
)
2023-11-10 19:23:06 +01:00
from tmtccmd.pus.s8_fsfw_action import create_action_cmd
2023-11-22 14:13:00 +01:00
from tmtccmd.tmtc import DefaultPusQueueHelper
from eive_tmtc.config.object_ids import SOLAR_ARRAY_DEPLOYMENT_ID
2022-10-13 18:04:35 +02:00
class OpCode:
2022-10-13 18:04:35 +02:00
MANUAL_DEPLOYMENT = "man_depl"
2023-01-20 12:19:57 +01:00
BURN_SA_0_ONLY = "burn_sa_0"
BURN_SA_1_ONLY = "burn_sa_1"
2022-10-13 18:04:35 +02:00
class Info:
MANUAL_DEPLOYMENT = "Manual Solar Array Deployment"
2023-01-20 12:19:57 +01:00
BURN_SA_0_ONLY = "Only burn SA0"
BURN_SA_1_ONLY = "Only burn SA1"
2022-10-13 18:04:35 +02:00
class ActionId:
2022-10-13 18:04:35 +02:00
MANUAL_DEPLOYMENT = 5
2023-11-22 14:13:00 +01:00
def add_solar_array_deployment_node() -> CmdTreeNode:
node = CmdTreeNode("solar_array_deployment", "Solar Array Deployment")
node.add_child(CmdTreeNode(OpCode.MANUAL_DEPLOYMENT, Info.MANUAL_DEPLOYMENT))
node.add_child(CmdTreeNode(OpCode.BURN_SA_0_ONLY, Info.BURN_SA_0_ONLY))
node.add_child(CmdTreeNode(OpCode.BURN_SA_1_ONLY, Info.BURN_SA_1_ONLY))
return node
2022-10-13 18:04:35 +02:00
2023-11-22 14:13:00 +01:00
def pack_solar_array_deployment_test_into(q: DefaultPusQueueHelper, cmd_str: str):
2023-01-20 12:19:57 +01:00
switch_interval_ms = 0
2023-11-22 14:13:00 +01:00
if cmd_str == OpCode.MANUAL_DEPLOYMENT:
2023-01-20 12:19:57 +01:00
while True:
burn_time_secs = prompt_burn_time()
if burn_time_secs < 0:
continue
# Default configuration: Burn each side for half of the burn time.
switch_interval_ms = int(round(burn_time_secs * 0.5 * 1000))
break
while True:
dry_run = prompt_dry_run()
if dry_run < 0:
continue
dry_run = bool(dry_run)
break
if dry_run:
dry_run_str = " as dry run"
else:
dry_run_str = ""
q.add_log_cmd(
f"Testing S/A Deployment with burn time {burn_time_secs}{dry_run_str}"
)
q.add_pus_tc(
pack_manual_array_depl_cmd(burn_time_secs, switch_interval_ms, dry_run)
)
2023-11-22 14:13:00 +01:00
elif cmd_str == OpCode.BURN_SA_0_ONLY:
2023-01-20 12:19:57 +01:00
burn_one_channel_only(q, 0)
2023-11-22 14:13:00 +01:00
elif cmd_str == OpCode.BURN_SA_1_ONLY:
2023-01-20 12:19:57 +01:00
burn_one_channel_only(q, 1)
def prompt_burn_time() -> int:
burn_time = int(input("Please specify burn time in seconds [0-120 secs]: "))
if burn_time < 0 or burn_time > 120:
2023-02-01 11:17:04 +01:00
logging.getLogger(__name__).warning(f"Invalid burn time {burn_time}")
2023-01-20 12:19:57 +01:00
return -1
return burn_time
def prompt_dry_run() -> int:
dry_run = input("Dry run? [y/n]: ")
if dry_run in ["yes", "y", "1"]:
return 1
elif dry_run in ["no", "n", "0"]:
return 0
else:
2023-02-01 11:17:04 +01:00
logging.getLogger(__name__).warning("Invalid input for dry run parameter")
2023-01-20 12:19:57 +01:00
return -1
def burn_one_channel_only(q: DefaultPusQueueHelper, channel: int):
2022-10-13 18:04:35 +02:00
while True:
2023-01-20 12:19:57 +01:00
burn_time_secs = prompt_burn_time()
if burn_time_secs < 0:
2022-10-13 18:04:35 +02:00
continue
break
while True:
2023-01-20 12:19:57 +01:00
dry_run = prompt_dry_run()
if dry_run < 0:
2022-10-13 18:04:35 +02:00
continue
2023-01-20 12:19:57 +01:00
dry_run = bool(dry_run)
2022-10-13 18:04:35 +02:00
break
2023-01-20 12:19:57 +01:00
if dry_run:
2022-10-13 18:04:35 +02:00
dry_run_str = " as dry run"
else:
dry_run_str = ""
2023-01-20 12:19:57 +01:00
q.add_log_cmd(
f"Testing S/A Deployment Channel {channel} only with "
f"burn time {burn_time_secs}{dry_run_str}"
)
q.add_pus_tc(pack_one_channel_only_cmd(burn_time_secs, channel, dry_run))
def pack_one_channel_only_cmd(
burn_time_seconds: int, channel: int, dry_run: bool
) -> PusTelecommand:
user_data = bytearray()
user_data.extend(struct.pack("!I", burn_time_seconds))
# Burn channel for the entire time
user_data.extend(struct.pack("!I", round(int((burn_time_seconds + 1) * 1000))))
user_data.append(channel)
user_data.append(dry_run)
return create_action_cmd(
SOLAR_ARRAY_DEPLOYMENT_ID, ActionId.MANUAL_DEPLOYMENT, user_data
)
def pack_manual_array_depl_cmd(
burn_time_seconds: int, channel_switch_interval_ms: int, dry_run: bool
) -> PusTelecommand:
user_data = bytearray()
user_data.extend(struct.pack("!I", burn_time_seconds))
user_data.extend(struct.pack("!I", channel_switch_interval_ms))
user_data.append(0)
user_data.append(dry_run)
return create_action_cmd(
SOLAR_ARRAY_DEPLOYMENT_ID, ActionId.MANUAL_DEPLOYMENT, user_data
2022-10-13 18:04:35 +02:00
)