Skip to content

Commit

Permalink
Merge pull request #184 from pierr3/unicom-guard
Browse files Browse the repository at this point in the history
Add unicom / guard
  • Loading branch information
pierr3 authored Oct 26, 2024
2 parents 77af85b + 6b622bc commit 37913e0
Show file tree
Hide file tree
Showing 24 changed files with 555 additions and 83 deletions.
20 changes: 9 additions & 11 deletions backend/include/Helpers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ class Helpers {
* @param frequency The frequency value to be cleaned up.
* @return The cleaned up frequency value.
*/
inline static int CleanUpFrequency(int frequency)
static int CleanUpFrequency(int frequency)
{
// We don't clean up an unset frequency
if (std::abs(frequency) == OBS_FREQUENCY) {
Expand All @@ -37,7 +37,7 @@ class Helpers {
* @return A string representation of the frequency in a human-readable format (e.g. "122.800"
* for 122800000 Hz)
*/
inline static std::string ConvertHzToHumanString(unsigned int frequencyHz)
static std::string ConvertHzToHumanString(unsigned int frequencyHz)
{
std::string temp = std::to_string(frequencyHz / 1000);
return temp.substr(0, 3) + "." + temp.substr(3, 7);
Expand All @@ -52,8 +52,7 @@ class Helpers {
* opposite of currentValue if the property is "toggle", or the currentValue if
* incoming value is undefined or invalid.
*/
inline static bool ConvertBoolOrToggleToBool(
const nlohmann::json& incomingValue, bool currentValue)
static bool ConvertBoolOrToggleToBool(const nlohmann::json& incomingValue, bool currentValue)
{
if (incomingValue.is_null()) {
TRACK_LOG_INFO("ConvertBoolOrToggleToBool: Incoming value wasn't specified, returning "
Expand Down Expand Up @@ -94,10 +93,11 @@ class NapiHelpers {
NapiHelpers::callbackAvailable = true;
}

inline static void callElectron(
static void callElectron(
const std::string& eventName, const std::string& data = "", const std::string& data2 = "")
{
if (!NapiHelpers::callbackAvailable || NapiHelpers::callbackRef == nullptr) {
if (!NapiHelpers::callbackAvailable || NapiHelpers::callbackRef == nullptr
|| NapiHelpers::_requestExit.load()) {
return;
}

Expand All @@ -111,10 +111,8 @@ class NapiHelpers {
});
}

inline static void sendErrorToElectron(const std::string& message)
{
callElectron("error", message);
}
static void sendErrorToElectron(const std::string& message) { callElectron("error", message); }

inline static std::mutex _callElectronMutex;
};
inline static std::atomic<bool> _requestExit = false;
};
16 changes: 11 additions & 5 deletions backend/include/RadioHelper.hpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
#pragma once

#include "Helpers.hpp"
#include "Shared.hpp"
#include "sdk.hpp"
#include <optional>

class RadioState {
public:
Expand All @@ -22,8 +24,8 @@ class RadioHelper {
* @return true The state was set successfully
* @return false The state was not set successfully
*/
inline static bool SetRadioState(
const std::shared_ptr<SDK>& mApiServer, const RadioState& newState)
static bool SetRadioState(const std::shared_ptr<SDK>& mApiServer, const RadioState& newState,
const std::string& stationCallsign = "")
{
if (!mClient->IsVoiceConnected()) {
TRACK_LOG_TRACE("Voice is not connected, not setting radio state");
Expand Down Expand Up @@ -56,6 +58,7 @@ class RadioHelper {

mClient->SetOnHeadset(newState.frequency, newState.headset);


if (!oldRxValue && newState.rx) {
// When turning on RX, we refresh the transceivers
auto states = mClient->getRadioState();
Expand All @@ -66,14 +69,17 @@ class RadioHelper {
}

// Included for legacy reasons in case some older client depends on this message.
mApiServer->handleAFVEventForWebsocket(sdk::types::Event::kFrequencyStateUpdate, {}, {});
mApiServer->handleAFVEventForWebsocket(
sdk::types::Event::kFrequencyStateUpdate, std::nullopt, std::nullopt);

// New event that only notifies of the change to this specific station.
auto stateJson = mApiServer->buildStationStateJson(std::nullopt, newState.frequency);
std::optional<std::string> optionalCallsign
= stationCallsign.empty() ? std::nullopt : std::optional<std::string>(stationCallsign);
auto stateJson = mApiServer->buildStationStateJson(optionalCallsign, newState.frequency);
mApiServer->publishStationState(stateJson);
NapiHelpers::callElectron("station-state-update", stateJson.dump());

return true;
}
};
;
;
13 changes: 7 additions & 6 deletions backend/include/Shared.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,19 +23,20 @@
#define VERSION_CHECK_ENDPOINT "/pierr3/TrackAudio/main/MANDATORY_VERSION"

#define OBS_FREQUENCY 199998000 // 199.998
#define UNICOM_FREQUENCY = 122800000 // 122.800
#define UNICOM_FREQUENCY 122800000 // 122.800
#define GUARD_FREQUENCY 121500000 // 121.500

#define API_SERVER_PORT 49080

constexpr semver::version VERSION = semver::version { 1, 3, 0, semver::prerelease::beta, 2 };
constexpr semver::version VERSION = semver::version { 1, 3, 0, semver::prerelease::beta, 3 };
// NOLINTNEXTLINE
const std::string CLIENT_NAME = std::string("TrackAudio-") + VERSION.to_string();

// NOLINTNEXTLINE
static std::unique_ptr<afv_native::api::atcClient> mClient = nullptr;

struct FileSystem {
inline static std::filesystem::path GetStateFolderPath()
static std::filesystem::path GetStateFolderPath()
{
return std::filesystem::path(sago::getStateDir()) / "trackaudio";
}
Expand Down Expand Up @@ -71,7 +72,7 @@ struct UserSettings {
// NOLINTNEXTLINE
inline static CSimpleIniA ini;

inline static void load()
static void load()
{
try {
_load();
Expand All @@ -80,7 +81,7 @@ struct UserSettings {
}
}

inline static void save()
static void save()
{
std::string settingsFilePath = (FileSystem::GetStateFolderPath() / "settings.ini").string();

Expand All @@ -103,7 +104,7 @@ struct UserSettings {
}

protected:
inline static void _load()
static void _load()
{
std::string settingsFilePath = (FileSystem::GetStateFolderPath() / "settings.ini").string();
ini.SetUnicode();
Expand Down
74 changes: 59 additions & 15 deletions backend/src/main.cpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
#include "LogFactory.h"
#include "afv-native/afv/dto/StationTransceiver.h"
#include "afv-native/atcClientWrapper.h"
#include "afv-native/event.h"
#include "afv-native/hardwareType.h"
#include "spdlog/sinks/rotating_file_sink.h"
#include "spdlog/spdlog.h"
#include <absl/strings/ascii.h>
#include <absl/strings/match.h>
#include <atomic>
Expand Down Expand Up @@ -39,7 +38,7 @@ struct MainThreadShared {

inline static std::unique_ptr<InputHandler> inputHandler = nullptr;
};

namespace {
Napi::Array GetAudioApis(const Napi::CallbackInfo& info)
{
Napi::Env env = info.Env();
Expand Down Expand Up @@ -123,6 +122,28 @@ void Disconnect(const Napi::CallbackInfo& /*info*/)
sdk::types::Event::kDisconnectFrequencyStateUpdate, {}, {});
}

void SetGuardAndUnicomTransceivers()
{
const auto transceivers = mClient->GetTransceivers();
const auto states = mClient->getRadioState();

std::vector<afv_native::afv::dto::StationTransceiver> guardAndUnicomTransceivers;
for (const auto& [frequency, state] : states) {
if (frequency == UNICOM_FREQUENCY || frequency == GUARD_FREQUENCY || !state.rx) {
continue;
}

if (transceivers.find(state.stationName) != transceivers.end()) {
for (const auto& transceiver : transceivers.at(state.stationName)) {
guardAndUnicomTransceivers.push_back(transceiver);
}
}
}

mClient->SetManualTransceivers(UNICOM_FREQUENCY, guardAndUnicomTransceivers);
mClient->SetManualTransceivers(GUARD_FREQUENCY, guardAndUnicomTransceivers);
}

void SetAudioSettings(const Napi::CallbackInfo& info)
{
if (mClient->IsVoiceConnected()) {
Expand Down Expand Up @@ -155,7 +176,7 @@ Napi::Boolean AddFrequency(const Napi::CallbackInfo& info)
return Napi::Boolean::New(info.Env(), false);
}

RadioState newState;
RadioState newState {};

newState.frequency = frequency;
newState.rx = false;
Expand All @@ -164,13 +185,13 @@ Napi::Boolean AddFrequency(const Napi::CallbackInfo& info)
newState.headset = true;
newState.xca = false;

auto result = RadioHelper::SetRadioState(MainThreadShared::mApiServer, newState);
auto result = RadioHelper::SetRadioState(MainThreadShared::mApiServer, newState, callsign);
return Napi::Boolean::New(info.Env(), result);
}

void RemoveFrequency(const Napi::CallbackInfo& info)
{
RadioState newState;
RadioState newState {};

newState.frequency = info[0].As<Napi::Number>().Int32Value();
newState.rx = false;
Expand All @@ -189,7 +210,7 @@ void Reset(const Napi::CallbackInfo& /*info*/) { mClient->reset(); }

Napi::Boolean SetFrequencyState(const Napi::CallbackInfo& info)
{
RadioState newState;
RadioState newState {};

newState.frequency = info[0].As<Napi::Number>().Int32Value();
newState.rx = info[1].As<Napi::Boolean>().Value();
Expand All @@ -199,6 +220,8 @@ Napi::Boolean SetFrequencyState(const Napi::CallbackInfo& info)
newState.headset = !info[4].As<Napi::Boolean>().Value();
newState.xca = info[5].As<Napi::Boolean>().Value(); // Not used

// SetGuardAndUnicomTransceivers();

auto result = RadioHelper::SetRadioState(MainThreadShared::mApiServer, newState);
return Napi::Boolean::New(info.Env(), result);
}
Expand Down Expand Up @@ -323,7 +346,22 @@ void SetRadioGain(const Napi::CallbackInfo& info)
float gain = info[0].As<Napi::Number>().FloatValue();
UserSession::currentRadioGain = gain;

mClient->SetRadioGainAll(gain);
auto states = mClient->getRadioState();
for (const auto& state : states) {
if (state.second.Frequency == UNICOM_FREQUENCY
|| state.second.Frequency == GUARD_FREQUENCY) {
continue;
}
mClient->SetRadioGain(state.first, gain);
}
}

void SetFrequencyRadioGain(const Napi::CallbackInfo& info)
{
int frequency = info[0].As<Napi::Number>().Int32Value();
float gain = info[1].As<Napi::Number>().FloatValue();

mClient->SetRadioGain(frequency, gain);
}

Napi::String Version(const Napi::CallbackInfo& info)
Expand Down Expand Up @@ -427,7 +465,7 @@ void RequestPttKeyName(const Napi::CallbackInfo& info)
}

// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast,readability-function-cognitive-complexity)
static void HandleAfvEvents(afv_native::ClientEventType eventType, void* data, void* data2)
void HandleAfvEvents(afv_native::ClientEventType eventType, void* data, void* data2)
{
if (!NapiHelpers::callbackAvailable) {
return;
Expand Down Expand Up @@ -458,7 +496,7 @@ static void HandleAfvEvents(afv_native::ClientEventType eventType, void* data, v
break;
}
}

SetGuardAndUnicomTransceivers();
NapiHelpers::callElectron(
"StationTransceiversUpdated", station, std::to_string(transceiverCount));
}
Expand Down Expand Up @@ -486,7 +524,7 @@ static void HandleAfvEvents(afv_native::ClientEventType eventType, void* data, v
}

NapiHelpers::callElectron("StationDataReceived", callsign, std::to_string(frequency));
MainThreadShared::mApiServer->publishStationAdded(callsign, frequency);
MainThreadShared::mApiServer->publishStationAdded(callsign, static_cast<int>(frequency));
}

if (eventType == afv_native::ClientEventType::VccsReceived) {
Expand All @@ -508,7 +546,8 @@ static void HandleAfvEvents(afv_native::ClientEventType eventType, void* data, v
}

NapiHelpers::callElectron("StationDataReceived", callsign, std::to_string(frequency));
MainThreadShared::mApiServer->publishStationAdded(callsign, frequency);
MainThreadShared::mApiServer->publishStationAdded(
callsign, static_cast<int>(frequency));
}
}

Expand Down Expand Up @@ -728,16 +767,18 @@ Napi::Object Bootstrap(const Napi::CallbackInfo& info)
Napi::Boolean Exit(const Napi::CallbackInfo& info)
{
TRACK_LOG_INFO("Awaiting to exit TrackAudio...");
std::lock_guard<std::mutex> HelperLock(NapiHelpers::_callElectronMutex);
TRACK_LOG_INFO("Exiting TrackAudio...")
NapiHelpers::_requestExit.store(true);
if (mClient->IsVoiceConnected()) {
TRACK_LOG_INFO("Forcing disconnect...");
mClient->Disconnect();
}

MainThreadShared::mApiServer.reset();
MainThreadShared::mRemoteDataHandler.reset();
MainThreadShared::inputHandler.reset();

mClient.reset();
TRACK_LOG_INFO("Exiting TrackAudio...")
LogFactory::destroyLoggers();

return Napi::Boolean::New(info.Env(), true);
Expand Down Expand Up @@ -790,6 +831,9 @@ Napi::Object Init(Napi::Env env, Napi::Object exports)

exports.Set(Napi::String::New(env, "SetPtt"), Napi::Function::New(env, SetPtt));

exports.Set(Napi::String::New(env, "SetFrequencyRadioGain"),
Napi::Function::New(env, SetFrequencyRadioGain));

exports.Set(Napi::String::New(env, "SetRadioGain"), Napi::Function::New(env, SetRadioGain));

exports.Set(
Expand Down Expand Up @@ -824,5 +868,5 @@ Napi::Object Init(Napi::Env env, Napi::Object exports)

return exports;
}

NODE_API_MODULE(addon, Init)
}
2 changes: 1 addition & 1 deletion backend/src/sdk.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@ void SDK::handleVoiceConnectedEventForWebsocket(bool isVoiceConnected)

jsonMessage["value"]["connected"] = isVoiceConnected;
this->broadcastOnWebsocket(jsonMessage.dump());
return;
}

// NOLINTNEXTLINE
Expand Down Expand Up @@ -330,6 +329,7 @@ void SDK::handleGetStationStates()

// Collect the states for all the radios
auto allRadios = mClient->getRadioState();
stationStates.reserve(allRadios.size());
for (const auto& [frequency, state] : allRadios) {
stationStates.push_back(this->buildStationStateJson(state.stationName, frequency));
}
Expand Down
1 change: 1 addition & 0 deletions backend/types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ declare namespace TrackAudioAfv {
export function SetCid(cid: string): void;

export function SetRadioGain(gain: number): void;
export function SetFrequencyRadioGain(frequency: number, gain: number): void;
export function SetPtt(activate: boolean): void;

export function SetRadioEffects(type: string): void;
Expand Down
4 changes: 4 additions & 0 deletions fast-afv-update.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
cd backend/extern/afv-native
git pull origin $1
cd ../../../
npm run build:backend-fast
Loading

0 comments on commit 37913e0

Please sign in to comment.