Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Send SSTV Command & GDL Config on web client #267

Merged
merged 1 commit into from
Jun 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions project/metadata/gfs_commands.json
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,12 @@
"details": "Sends the APRS location from the telemetry module.",
"value": "0x3003",
"cmd_key": "apl"
},
"send_sstv_image": {
"name": "Send SSTV Image",
"details": "Sends the SSTV image from the telemetry module. Only works if SSTV is enabled.",
"value": "0x3004",
"cmd_key": "stv"
}
},
"extension_module": {
Expand Down
2 changes: 1 addition & 1 deletion project/metadata/gfs_configuration.json
Original file line number Diff line number Diff line change
Expand Up @@ -474,7 +474,7 @@
"type": "string",
"name": "APRS Destination Address",
"description": "This is the destination address that will be used in all packets. See the APRS specification for more information.",
"default": "APRS",
"default": "APZ441",
"max": 6,
"min": 3,
"pattern": ""
Expand Down
1 change: 1 addition & 0 deletions src/common/command_ids.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ enum class CommandId : uint16_t {
TELEMETRY_MODULE_sendRssi=0x3001, // Send RSSI
TELEMETRY_MODULE_sendSnr=0x3002, // Send SNR
TELEMETRY_MODULE_sendAprsLocation=0x3003, // Send APRS Location
TELEMETRY_MODULE_sendSstvImage=0x3004, // Send SSTV Image
EXTENSION_MODULE_addPreConfiguredExtension=0x4000 // Add Pre-Configured Extension
};
// NOLINTEND(readability-identifier-naming)
Expand Down
1 change: 1 addition & 0 deletions src/common/command_ids_strings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ const std::unordered_map<std::string, CommandId> K_STRING_TO_COMMAND_MAP {
{"TELEMETRY_MODULE_sendRssi",CommandId::TELEMETRY_MODULE_sendRssi},
{"TELEMETRY_MODULE_sendSnr",CommandId::TELEMETRY_MODULE_sendSnr},
{"TELEMETRY_MODULE_sendAprsLocation",CommandId::TELEMETRY_MODULE_sendAprsLocation},
{"TELEMETRY_MODULE_sendSstvImage",CommandId::TELEMETRY_MODULE_sendSstvImage},
{"EXTENSION_MODULE_addPreConfiguredExtension",CommandId::EXTENSION_MODULE_addPreConfiguredExtension}
};

Expand Down
2 changes: 1 addition & 1 deletion src/data_link/include/gdl_constants.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ inline constexpr static uint32_t GDL_EXCHANGE_CONNECTION_TIMEOUT_MS =

/// @brief If we don't have an exchange message within this time, we will send a
/// ping to check the connection.
inline constexpr static uint32_t GDL_EXCHANGE_PING_INTERVAL_MS = 20 * 1000;
inline constexpr static uint32_t GDL_EXCHANGE_PING_INTERVAL_MS = 60 * 1000;
// GDL_EXCHANGE_CONNECTION_TIMEOUT_MS / 2;

inline constexpr static uint32_t GDL_DOWNLINK_TIMEOUT_MS = 200 * 1000;
Expand Down
1 change: 1 addition & 0 deletions src/data_link/network_layer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ bool NetworkLayer::txAprsPositionPacket(const Packet &packet) {
pos_packet.altitude = loc.altitude;
pos_packet.speed = loc.speed;
pos_packet.course = loc.heading;
pos_packet.time_code = loc.time_code;

modulator_.encode(pos_packet);
modulator_.writeToPulseAudio();
Expand Down
8 changes: 4 additions & 4 deletions src/data_link/server/gdl_server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -211,11 +211,11 @@ bool GdlServer::setConfigFromJson(const json &config) {
log_.warn("Failed to load source_callsign from json or is set to default");
}

if (is_valid_number("source_ssid") && config["source_ssid"] != 0) {
if (is_valid_number("source_ssid")) {
gdl_config_.setSSID(config["source_ssid"]);
} else {
valid = false;
log_.warn("Failed to load source_ssid from json or is set to default");
log_.warn("Failed to load source_ssid from json");
}

if (is_valid_string("remote_callsign") &&
Expand All @@ -226,11 +226,11 @@ bool GdlServer::setConfigFromJson(const json &config) {
log_.warn("Failed to load remote_callsign from json or is set to default");
}

if (is_valid_number("remote_ssid") && config["remote_ssid"] != 0) {
if (is_valid_number("remote_ssid")) {
gdl_config_.setRemoteSSID(config["remote_ssid"]);
} else {
valid = false;
log_.warn("Failed to load remote_ssid from json or is set to default");
log_.warn("Failed to load remote_ssid from json");
}

if (is_valid_bool("proactive_keep_alive")) {
Expand Down
3 changes: 2 additions & 1 deletion src/data_link/transport_layer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,9 @@ bool TransportLayer::send(Message &message) {
}

// if it's an exchange message, we need to make sure we're connected.
// but only in proactive keep alive mode
if (message.getType() == Message::Type::EXCHANGE) {
if (!isConnected()) {
if (!isConnected() && config_.getProactiveKeepAlive()) {
return false;
}
current_tx_packet_ = message;
Expand Down
2 changes: 1 addition & 1 deletion src/flight_system/configuration/configuration.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,7 @@ class TelemetryAprs : public cfg::CfgSection {
int position_packet_interval_ = 600;
std::string frequency_ = "144.3900";
int ssid_ = 0;
std::string destination_address_ = "APRS";
std::string destination_address_ = "APZ441";
int destination_ssid_ = 0;
cfg::gEnum::AprsSymbolTable symbol_table_ = cfg::gEnum::AprsSymbolTable::PRIMARY;
std::string symbol_ = "/";
Expand Down
4 changes: 3 additions & 1 deletion src/flight_system/control/command_processor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,8 @@ bool parseTelemetryModuleCommand(const std::string &command_id_str,
{"nae", cmd::CommandId::TELEMETRY_MODULE_sendNumActiveErrors},
{"rsi", cmd::CommandId::TELEMETRY_MODULE_sendRssi},
{"snr", cmd::CommandId::TELEMETRY_MODULE_sendSnr},
{"apl", cmd::CommandId::TELEMETRY_MODULE_sendAprsLocation}};
{"apl", cmd::CommandId::TELEMETRY_MODULE_sendAprsLocation},
{"stv", cmd::CommandId::TELEMETRY_MODULE_sendSstvImage}};
if (!K_COMMAND_ID_MAP.contains(command_id_str)) {
return false;
}
Expand All @@ -217,6 +218,7 @@ bool parseTelemetryModuleCommand(const std::string &command_id_str,
case cmd::CommandId::TELEMETRY_MODULE_sendRssi:
case cmd::CommandId::TELEMETRY_MODULE_sendSnr:
case cmd::CommandId::TELEMETRY_MODULE_sendAprsLocation:
case cmd::CommandId::TELEMETRY_MODULE_sendSstvImage:
if (arg.length() != 0) {
return false;
}
Expand Down
4 changes: 4 additions & 0 deletions src/flight_system/modules/module.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,10 @@ class Module {
*/
void info(std::string info = "");

/**
* @brief Used internally for debug messages.
* @param info The debug message.
*/
void debug(std::string info);

/**
Expand Down
11 changes: 9 additions & 2 deletions src/flight_system/modules/telemetry/telemetry_module.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ void modules::TelemetryModule::sendAprsPositionPacket() {
/// @todo Maybe use the last valid GPS frame instead, but first there needs to
/// be a time stamp as to when this one was generated. I have a fear of DST
/// and time zones causing issues here.
auto loc = position.last_gps_frame;
auto loc = position.last_valid_gps_frame;
if (!loc.is_valid) {
/// @todo log an error
return;
Expand All @@ -144,7 +144,7 @@ void modules::TelemetryModule::sendAprsPositionPacket() {
gdl_loc.latitude = loc.latitude;
gdl_loc.longitude = loc.longitude;
gdl_loc.altitude = loc.altitude;
gdl_loc.speed = loc.horizontal_speed;
gdl_loc.speed = loc.horizontal_speed; // @todo Convert to mph
gdl_loc.heading = loc.heading_of_motion;

gdl::Message message{};
Expand All @@ -161,6 +161,10 @@ void modules::TelemetryModule::sendAprsPositionPacket() {
aprs_position_packet_timer_.reset();
}

void modules::TelemetryModule::sendSstvImage() {
info("Sending SSTV image not implemented.");
}

void modules::TelemetryModule::processCommand(const cmd::Command &command) {
int int_buffer = 0;
double double_buffer = 0.0;
Expand All @@ -183,6 +187,9 @@ void modules::TelemetryModule::processCommand(const cmd::Command &command) {
gdl_.sendText("cmd/tlm/snr/ : " + std::to_string(double_buffer),
getNextMessageId());
break;
case cmd::CommandId::TELEMETRY_MODULE_sendSstvImage:
sendSstvImage();
break;
default:
error(DiagnosticId::TELEMETRY_invalidCommand);
break;
Expand Down
7 changes: 7 additions & 0 deletions src/flight_system/modules/telemetry/telemetry_module.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,13 @@ class TelemetryModule : public Module {
*/
void sendAprsPositionPacket();

/**
* @brief Send an SSTV image.
* @details Only functions if SSTV is configured. Requires a camera to be
* connected.
*/
void sendSstvImage();

/**
* @brief Process commands that are received from the flight runner.
* @param command - The command to process.
Expand Down
45 changes: 45 additions & 0 deletions src/ground_station/gdl_connection/gdl_connection.js
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ module.exports = class GdlConnection {
self.new_config
);
self.new_config = null;
self.config_up_to_date = false;
} else {
new_request = new RequestMessage("ggs", "gdl", next_request_rsc);
}
Expand Down Expand Up @@ -277,6 +278,50 @@ module.exports = class GdlConnection {
return "success";
}

getConfig() {
return {
values: this.config_data,
metadata: {
logging_level: {
name: "Logging Level",
description: "The level of logging to use.",
type: "enum",
options: ["INFO", "WARN"],
},
logging_print_to_stdout: {
name: "Print to Stdout",
description: "Whether to print logs to stdout.",
type: "bool",
},
proactive_keep_alive: {
name: "Proactive Keep Alive",
description: "Whether to send keep alive messages proactively.",
type: "bool",
},
remote_callsign: {
name: "Remote Callsign",
description: "The callsign of the remote station.",
type: "string",
},
remote_ssid: {
name: "Remote SSID",
description: "The SSID of the remote station.",
type: "int",
},
source_callsign: {
name: "Source Callsign",
description: "The callsign of the source station.",
type: "string",
},
source_ssid: {
name: "Source SSID",
description: "The SSID of the source station.",
type: "int",
},
},
};
}

/**
* @brief Reads settings relevant to this class from the database and
* stores them in the class.
Expand Down
19 changes: 13 additions & 6 deletions src/ground_station/http_api/gdl_handler.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,20 @@ const router = express.Router();

module.exports = function (global_state) {
// /api/gdl/settings
// router.get("/settings", (req, res, next) => {
// parseGetQuery(req, res, "gfs", "settings", global_state);
// });
router.get("/settings", (req, res, next) => {
res.json(global_state.gdl_connection.getConfig());
});

// router.put("/settings", (req, res, next) => {
// res.json({ message: "Not yet implemented!" });
// });
router.put("/settings", (req, res, next) => {
let result = global_state.gdl_connection.setConfig(req.body);
if (result !== "success") {
res.status(400).json({
message: "Failed to set config. " + result,
});
return;
}
res.json({ message: "success" });
});

// /api/gdl/data
router.get("/status", (req, res, next) => {
Expand Down
3 changes: 3 additions & 0 deletions src/web_client/src/pages/setup.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
Card,
CardMasonryLayout,
CardContentCentered,
CardBreak,
} from "../core/PageParts";
import gws_setup from "../assets/gws_setup.jpg";
import { useContext, useState } from "react";
Expand Down Expand Up @@ -115,6 +116,8 @@ function SetupPage() {

<Card title="Giraffe Data Link">
<EditBox resource="ggs" category="gdl" />
<CardBreak />
<EditBox resource="gdl" category="all" />
</Card>

<Card title="InfluxDB Setup">
Expand Down
Loading