initial bare-bones implementation of dvmmon; enhance REST API to return more detailed status information (for use by dvmmon); cleanup file code style;
parent
298cd8da1f
commit
d45af90c07
@ -0,0 +1,25 @@
|
||||
#
|
||||
# Digital Voice Modem - Monitor Configuration
|
||||
#
|
||||
# @package DVM / Monitor
|
||||
#
|
||||
|
||||
#
|
||||
# Channel Identity Table Configuration
|
||||
#
|
||||
iden_table:
|
||||
# Full path to the identity table file.
|
||||
file: iden_table.dat
|
||||
# Amount of time between updates of identity table file. (minutes)
|
||||
time: 30
|
||||
|
||||
#
|
||||
# DVM Channels to Monitor
|
||||
#
|
||||
channels:
|
||||
# REST API IP Address for channel.
|
||||
- restAddress: 127.0.0.1
|
||||
# REST API Port number for channel.
|
||||
restPort: 9990
|
||||
# REST API access password for channel.
|
||||
restPassword: "PASSWORD"
|
||||
@ -0,0 +1,144 @@
|
||||
/**
|
||||
* Digital Voice Modem - Host Software
|
||||
* GPLv2 Open Source. Use is subject to license terms.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* @package DVM / Host Software
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* Copyright (C) 2023 by Bryan Biedenkapp N2PLL
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
#if !defined(__INHIBIT_SUBSCRIBER_WND_H__)
|
||||
#define __INHIBIT_SUBSCRIBER_WND_H__
|
||||
|
||||
#include "monitor/TransmitWndBase.h"
|
||||
|
||||
#include <final/final.h>
|
||||
using namespace finalcut;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Class Declaration
|
||||
// This class implements the inhibit subscriber window.
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
class HOST_SW_API InhibitSubscriberWnd final : public TransmitWndBase {
|
||||
public:
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the InhibitSubscriberWnd class.
|
||||
/// </summary>
|
||||
/// <param name="channel"></param>
|
||||
/// <param name="widget"></param>
|
||||
explicit InhibitSubscriberWnd(lookups::VoiceChData channel, FWidget* widget = nullptr) : TransmitWndBase{channel, widget}
|
||||
{
|
||||
/* stub */
|
||||
}
|
||||
|
||||
private:
|
||||
FLabel m_dialogLabel{"Inhibit Subscriber", this};
|
||||
|
||||
FLabel m_subscriberLabel{"Subscriber ID: ", this};
|
||||
FSpinBox m_subscriber{this};
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
void initLayout() override
|
||||
{
|
||||
FDialog::setText("Inhibit Subscriber");
|
||||
FDialog::setSize(FSize{60, 16});
|
||||
|
||||
TransmitWndBase::initLayout();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
void initControls() override
|
||||
{
|
||||
TransmitWndBase::initControls();
|
||||
|
||||
if (m_hideModeSelect) {
|
||||
FDialog::setSize(FSize{60, 12});
|
||||
resizeControls();
|
||||
}
|
||||
|
||||
// subscriber entry
|
||||
{
|
||||
if (!m_hideModeSelect) {
|
||||
m_dialogLabel.setGeometry(FPoint(2, 6), FSize(20, 2));
|
||||
}
|
||||
else {
|
||||
m_dialogLabel.setGeometry(FPoint(2, 2), FSize(20, 2));
|
||||
}
|
||||
m_dialogLabel.setEmphasis();
|
||||
m_dialogLabel.setAlignment(Align::Center);
|
||||
|
||||
if (!m_hideModeSelect) {
|
||||
m_subscriberLabel.setGeometry(FPoint(2, 8), FSize(25, 1));
|
||||
m_subscriber.setGeometry(FPoint(28, 8), FSize(20, 1));
|
||||
}
|
||||
else {
|
||||
m_subscriberLabel.setGeometry(FPoint(2, 4), FSize(25, 1));
|
||||
m_subscriber.setGeometry(FPoint(28, 4), FSize(20, 1));
|
||||
}
|
||||
m_subscriber.setRange(1, 16777211);
|
||||
m_subscriber.setValue(1);
|
||||
m_subscriber.setShadow(false);
|
||||
}
|
||||
|
||||
m_subscriberLabel.redraw();
|
||||
redraw();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
void setTransmit() override
|
||||
{
|
||||
std::string method = PUT_DMR_RID;
|
||||
json::object req = json::object();
|
||||
req["command"].set<std::string>(RID_CMD_INHIBIT);
|
||||
uint32_t dstId = m_subscriber.getValue();
|
||||
req["dstId"].set<uint32_t>(dstId);
|
||||
|
||||
switch (m_mode) {
|
||||
case modem::STATE_DMR:
|
||||
{
|
||||
uint8_t slot = m_dmrSlot.getValue();
|
||||
req["slot"].set<uint8_t>(slot);
|
||||
}
|
||||
break;
|
||||
case modem::STATE_P25:
|
||||
{
|
||||
method = PUT_P25_RID;
|
||||
}
|
||||
break;
|
||||
case modem::STATE_NXDN:
|
||||
return;
|
||||
}
|
||||
|
||||
// callback REST API
|
||||
int ret = RESTClient::send(m_selectedCh.address(), m_selectedCh.port(), m_selectedCh.password(),
|
||||
HTTP_PUT, method, req, g_debug);
|
||||
if (ret != network::rest::http::HTTPPayload::StatusType::OK) {
|
||||
::LogError(LOG_HOST, "failed to send request to %s:%u", m_selectedCh.address().c_str(), m_selectedCh.port());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif // __INHIBIT_SUBSCRIBER_WND_H__
|
||||
@ -0,0 +1,144 @@
|
||||
/**
|
||||
* Digital Voice Modem - Host Software
|
||||
* GPLv2 Open Source. Use is subject to license terms.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* @package DVM / Host Software
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* Copyright (C) 2023 by Bryan Biedenkapp N2PLL
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
#if !defined(__PAGE_SUBSCRIBER_WND_H__)
|
||||
#define __PAGE_SUBSCRIBER_WND_H__
|
||||
|
||||
#include "monitor/TransmitWndBase.h"
|
||||
|
||||
#include <final/final.h>
|
||||
using namespace finalcut;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Class Declaration
|
||||
// This class implements the page subscriber window.
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
class HOST_SW_API PageSubscriberWnd final : public TransmitWndBase {
|
||||
public:
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the PageSubscriberWnd class.
|
||||
/// </summary>
|
||||
/// <param name="channel"></param>
|
||||
/// <param name="widget"></param>
|
||||
explicit PageSubscriberWnd(lookups::VoiceChData channel, FWidget* widget = nullptr) : TransmitWndBase{channel, widget}
|
||||
{
|
||||
/* stub */
|
||||
}
|
||||
|
||||
private:
|
||||
FLabel m_dialogLabel{"Page Subscriber", this};
|
||||
|
||||
FLabel m_subscriberLabel{"Subscriber ID: ", this};
|
||||
FSpinBox m_subscriber{this};
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
void initLayout() override
|
||||
{
|
||||
FDialog::setText("Page Subscriber");
|
||||
FDialog::setSize(FSize{60, 16});
|
||||
|
||||
TransmitWndBase::initLayout();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
void initControls() override
|
||||
{
|
||||
TransmitWndBase::initControls();
|
||||
|
||||
if (m_hideModeSelect) {
|
||||
FDialog::setSize(FSize{60, 12});
|
||||
resizeControls();
|
||||
}
|
||||
|
||||
// subscriber entry
|
||||
{
|
||||
if (!m_hideModeSelect) {
|
||||
m_dialogLabel.setGeometry(FPoint(2, 6), FSize(20, 2));
|
||||
}
|
||||
else {
|
||||
m_dialogLabel.setGeometry(FPoint(2, 2), FSize(20, 2));
|
||||
}
|
||||
m_dialogLabel.setEmphasis();
|
||||
m_dialogLabel.setAlignment(Align::Center);
|
||||
|
||||
if (!m_hideModeSelect) {
|
||||
m_subscriberLabel.setGeometry(FPoint(2, 8), FSize(25, 1));
|
||||
m_subscriber.setGeometry(FPoint(28, 8), FSize(20, 1));
|
||||
}
|
||||
else {
|
||||
m_subscriberLabel.setGeometry(FPoint(2, 4), FSize(25, 1));
|
||||
m_subscriber.setGeometry(FPoint(28, 4), FSize(20, 1));
|
||||
}
|
||||
m_subscriber.setRange(1, 16777211);
|
||||
m_subscriber.setValue(1);
|
||||
m_subscriber.setShadow(false);
|
||||
}
|
||||
|
||||
m_subscriberLabel.redraw();
|
||||
redraw();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
void setTransmit() override
|
||||
{
|
||||
std::string method = PUT_DMR_RID;
|
||||
json::object req = json::object();
|
||||
req["command"].set<std::string>(RID_CMD_PAGE);
|
||||
uint32_t dstId = m_subscriber.getValue();
|
||||
req["dstId"].set<uint32_t>(dstId);
|
||||
|
||||
switch (m_mode) {
|
||||
case modem::STATE_DMR:
|
||||
{
|
||||
uint8_t slot = m_dmrSlot.getValue();
|
||||
req["slot"].set<uint8_t>(slot);
|
||||
}
|
||||
break;
|
||||
case modem::STATE_P25:
|
||||
{
|
||||
method = PUT_P25_RID;
|
||||
}
|
||||
break;
|
||||
case modem::STATE_NXDN:
|
||||
return;
|
||||
}
|
||||
|
||||
// callback REST API
|
||||
int ret = RESTClient::send(m_selectedCh.address(), m_selectedCh.port(), m_selectedCh.password(),
|
||||
HTTP_PUT, method, req, g_debug);
|
||||
if (ret != network::rest::http::HTTPPayload::StatusType::OK) {
|
||||
::LogError(LOG_HOST, "failed to send request to %s:%u", m_selectedCh.address().c_str(), m_selectedCh.port());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif // __PAGE_SUBSCRIBER_WND_H__
|
||||
@ -0,0 +1,144 @@
|
||||
/**
|
||||
* Digital Voice Modem - Host Software
|
||||
* GPLv2 Open Source. Use is subject to license terms.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* @package DVM / Host Software
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* Copyright (C) 2023 by Bryan Biedenkapp N2PLL
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
#if !defined(__RADIO_CHECK_SUBSCRIBER_WND_H__)
|
||||
#define __RADIO_CHECK_SUBSCRIBER_WND_H__
|
||||
|
||||
#include "monitor/TransmitWndBase.h"
|
||||
|
||||
#include <final/final.h>
|
||||
using namespace finalcut;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Class Declaration
|
||||
// This class implements the radio check subscriber window.
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
class HOST_SW_API RadioCheckSubscriberWnd final : public TransmitWndBase {
|
||||
public:
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the RadioCheckSubscriberWnd class.
|
||||
/// </summary>
|
||||
/// <param name="channel"></param>
|
||||
/// <param name="widget"></param>
|
||||
explicit RadioCheckSubscriberWnd(lookups::VoiceChData channel, FWidget* widget = nullptr) : TransmitWndBase{channel, widget}
|
||||
{
|
||||
/* stub */
|
||||
}
|
||||
|
||||
private:
|
||||
FLabel m_dialogLabel{"Radio Check Subscriber", this};
|
||||
|
||||
FLabel m_subscriberLabel{"Subscriber ID: ", this};
|
||||
FSpinBox m_subscriber{this};
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
void initLayout() override
|
||||
{
|
||||
FDialog::setText("Radio Check Subscriber");
|
||||
FDialog::setSize(FSize{60, 16});
|
||||
|
||||
TransmitWndBase::initLayout();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
void initControls() override
|
||||
{
|
||||
TransmitWndBase::initControls();
|
||||
|
||||
if (m_hideModeSelect) {
|
||||
FDialog::setSize(FSize{60, 12});
|
||||
resizeControls();
|
||||
}
|
||||
|
||||
// subscriber entry
|
||||
{
|
||||
if (!m_hideModeSelect) {
|
||||
m_dialogLabel.setGeometry(FPoint(2, 6), FSize(20, 2));
|
||||
}
|
||||
else {
|
||||
m_dialogLabel.setGeometry(FPoint(2, 2), FSize(20, 2));
|
||||
}
|
||||
m_dialogLabel.setEmphasis();
|
||||
m_dialogLabel.setAlignment(Align::Center);
|
||||
|
||||
if (!m_hideModeSelect) {
|
||||
m_subscriberLabel.setGeometry(FPoint(2, 8), FSize(25, 1));
|
||||
m_subscriber.setGeometry(FPoint(28, 8), FSize(20, 1));
|
||||
}
|
||||
else {
|
||||
m_subscriberLabel.setGeometry(FPoint(2, 4), FSize(25, 1));
|
||||
m_subscriber.setGeometry(FPoint(28, 4), FSize(20, 1));
|
||||
}
|
||||
m_subscriber.setRange(1, 16777211);
|
||||
m_subscriber.setValue(1);
|
||||
m_subscriber.setShadow(false);
|
||||
}
|
||||
|
||||
m_subscriberLabel.redraw();
|
||||
redraw();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
void setTransmit() override
|
||||
{
|
||||
std::string method = PUT_DMR_RID;
|
||||
json::object req = json::object();
|
||||
req["command"].set<std::string>(RID_CMD_CHECK);
|
||||
uint32_t dstId = m_subscriber.getValue();
|
||||
req["dstId"].set<uint32_t>(dstId);
|
||||
|
||||
switch (m_mode) {
|
||||
case modem::STATE_DMR:
|
||||
{
|
||||
uint8_t slot = m_dmrSlot.getValue();
|
||||
req["slot"].set<uint8_t>(slot);
|
||||
}
|
||||
break;
|
||||
case modem::STATE_P25:
|
||||
{
|
||||
method = PUT_P25_RID;
|
||||
}
|
||||
break;
|
||||
case modem::STATE_NXDN:
|
||||
return;
|
||||
}
|
||||
|
||||
// callback REST API
|
||||
int ret = RESTClient::send(m_selectedCh.address(), m_selectedCh.port(), m_selectedCh.password(),
|
||||
HTTP_PUT, method, req, g_debug);
|
||||
if (ret != network::rest::http::HTTPPayload::StatusType::OK) {
|
||||
::LogError(LOG_HOST, "failed to send request to %s:%u", m_selectedCh.address().c_str(), m_selectedCh.port());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif // __RADIO_CHECK_SUBSCRIBER_WND_H__
|
||||
@ -0,0 +1,124 @@
|
||||
/**
|
||||
* Digital Voice Modem - Monitor
|
||||
* GPLv2 Open Source. Use is subject to license terms.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* @package DVM / Monitor
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* Copyright (C) 2023 by Bryan Biedenkapp N2PLL
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
#if !defined(__SELECTED_NODE_WND_H__)
|
||||
#define __SELECTED_NODE_WND_H__
|
||||
|
||||
#include "monitor/MonitorMainWnd.h"
|
||||
|
||||
#include <final/final.h>
|
||||
using namespace finalcut;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Class Declaration
|
||||
// This class implements the selected node display window.
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
class HOST_SW_API SelectedNodeWnd final : public finalcut::FDialog {
|
||||
public:
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the SelectedNodeWnd class.
|
||||
/// </summary>
|
||||
/// <param name="widget"></param>
|
||||
explicit SelectedNodeWnd(FWidget* widget = nullptr) : FDialog{widget}
|
||||
{
|
||||
/* stub */
|
||||
}
|
||||
/// <summary>Copy constructor.</summary>
|
||||
SelectedNodeWnd(const SelectedNodeWnd&) = delete;
|
||||
/// <summary>Move constructor.</summary>
|
||||
SelectedNodeWnd(SelectedNodeWnd&&) noexcept = delete;
|
||||
/// <summary>Finalizes an instance of the SelectedNodeWnd class.</summary>
|
||||
~SelectedNodeWnd() noexcept override = default;
|
||||
|
||||
/// <summary>Disable copy assignment operator (=).</summary>
|
||||
auto operator= (const SelectedNodeWnd&) -> SelectedNodeWnd& = delete;
|
||||
/// <summary>Disable move assignment operator (=).</summary>
|
||||
auto operator= (SelectedNodeWnd&&) noexcept -> SelectedNodeWnd& = delete;
|
||||
|
||||
/// <summary>Disable set X coordinate.</summary>
|
||||
void setX(int, bool = true) override { }
|
||||
/// <summary>Disable set Y coordinate.</summary>
|
||||
void setY(int, bool = true) override { }
|
||||
/// <summary>Disable set position.</summary>
|
||||
void setPos(const FPoint&, bool = true) override { }
|
||||
|
||||
/// <summary></summary>
|
||||
void setSelectedText(std::string str)
|
||||
{
|
||||
m_selectedHost.setText(str);
|
||||
redraw();
|
||||
}
|
||||
|
||||
private:
|
||||
FLabel m_selectedHostLabel{"Selected Host: ", this};
|
||||
FLabel m_selectedHost{this};
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
void initLayout() override
|
||||
{
|
||||
std::size_t maxWidth;
|
||||
const auto& rootWidget = getRootWidget();
|
||||
|
||||
if (rootWidget) {
|
||||
maxWidth = rootWidget->getClientWidth() - 3;
|
||||
}
|
||||
else {
|
||||
// fallback to xterm default size
|
||||
maxWidth = 77;
|
||||
}
|
||||
|
||||
FDialog::setGeometry(FPoint{2, 2}, FSize{maxWidth, 2});
|
||||
FDialog::setMinimumSize(FSize{80, 5});
|
||||
FDialog::setResizeable(false);
|
||||
FDialog::setMinimizable(false);
|
||||
FDialog::setTitlebarButtonVisibility(false);
|
||||
FDialog::setShadow(false);
|
||||
|
||||
m_selectedHostLabel.setGeometry(FPoint(2, 1), FSize(18, 1));
|
||||
m_selectedHost.setGeometry(FPoint(20, 1), FSize(30, 1));
|
||||
m_selectedHost.setText("None");
|
||||
|
||||
FDialog::initLayout();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
void draw() override
|
||||
{
|
||||
setColor();
|
||||
clearArea();
|
||||
|
||||
const auto& wc = getColorTheme();
|
||||
setColor(wc->dialog_resize_fg, getBackgroundColor());
|
||||
|
||||
finalcut::drawBorder(this, FRect(FPoint{1, 1}, FPoint{(int)getWidth(), (int)getHeight()}));
|
||||
}
|
||||
};
|
||||
|
||||
#endif // __SELECTED_NODE_WND_H__
|
||||
@ -0,0 +1,285 @@
|
||||
/**
|
||||
* Digital Voice Modem - Host Software
|
||||
* GPLv2 Open Source. Use is subject to license terms.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* @package DVM / Host Software
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* Copyright (C) 2023 by Bryan Biedenkapp N2PLL
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
#if !defined(__TRANSMIT_WND_BASE_H__)
|
||||
#define __TRANSMIT_WND_BASE_H__
|
||||
|
||||
#include "lookups/AffiliationLookup.h"
|
||||
#include "network/RESTDefines.h"
|
||||
#include "remote/RESTClient.h"
|
||||
|
||||
#include <final/final.h>
|
||||
using namespace finalcut;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Class Declaration
|
||||
// This class implements the base class for transmit windows.
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
class HOST_SW_API TransmitWndBase : public finalcut::FDialog {
|
||||
public:
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the TransmitWndBase class.
|
||||
/// </summary>
|
||||
/// <param name="channel"></param>
|
||||
/// <param name="widget"></param>
|
||||
explicit TransmitWndBase(lookups::VoiceChData channel, FWidget* widget = nullptr) : FDialog{widget},
|
||||
m_selectedCh(channel)
|
||||
{
|
||||
/* stub */
|
||||
}
|
||||
|
||||
protected:
|
||||
bool m_hideModeSelect = false;
|
||||
lookups::VoiceChData m_selectedCh;
|
||||
|
||||
uint8_t m_mode = modem::STATE_DMR;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
virtual void initLayout() override
|
||||
{
|
||||
FDialog::setMinimizable(true);
|
||||
FDialog::setShadow();
|
||||
|
||||
std::size_t maxWidth, maxHeight;
|
||||
const auto& rootWidget = getRootWidget();
|
||||
|
||||
if (rootWidget) {
|
||||
maxWidth = rootWidget->getClientWidth();
|
||||
maxHeight = rootWidget->getClientHeight();
|
||||
}
|
||||
else {
|
||||
// fallback to xterm default size
|
||||
maxWidth = 80;
|
||||
maxHeight = 24;
|
||||
}
|
||||
|
||||
const int x = 1 + int((maxWidth - getWidth()) / 2);
|
||||
const int y = 1 + int((maxHeight - getHeight()) / 3);
|
||||
FWindow::setPos(FPoint{x, y}, false);
|
||||
FDialog::adjustSize();
|
||||
|
||||
FDialog::setModal();
|
||||
|
||||
initControls();
|
||||
|
||||
FDialog::initLayout();
|
||||
|
||||
rootWidget->redraw(); // bryanb: wtf?
|
||||
redraw();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
virtual void initControls()
|
||||
{
|
||||
resizeControls();
|
||||
|
||||
m_dmrSlotLabel.setGeometry(FPoint(2, 4), FSize(10, 1));
|
||||
m_dmrSlot.setGeometry(FPoint(18, 4), FSize(5, 1));
|
||||
m_dmrSlot.setRange(1, 2);
|
||||
m_dmrSlot.setValue(1);
|
||||
m_dmrSlot.setShadow(false);
|
||||
|
||||
// callback REST API to get status of the channel
|
||||
json::object req = json::object();
|
||||
json::object rsp = json::object();
|
||||
|
||||
int ret = RESTClient::send(m_selectedCh.address(), m_selectedCh.port(), m_selectedCh.password(),
|
||||
HTTP_GET, GET_STATUS, req, rsp, g_debug);
|
||||
if (ret != network::rest::http::HTTPPayload::StatusType::OK) {
|
||||
::LogError(LOG_HOST, "failed to get status for %s:%u", m_selectedCh.address().c_str(), m_selectedCh.port());
|
||||
}
|
||||
|
||||
try {
|
||||
if (rsp["fixedMode"].get<bool>()) {
|
||||
m_mode = rsp["state"].is<uint8_t>();
|
||||
m_hideModeSelect = true;
|
||||
}
|
||||
|
||||
bool dmrCC = rsp["dmrCC"].get<bool>();
|
||||
bool p25CC = rsp["p25CC"].get<bool>();
|
||||
bool nxdnCC = rsp["nxdnCC"].get<bool>();
|
||||
|
||||
// are we a dedicated control channel?
|
||||
if (dmrCC || p25CC || nxdnCC) {
|
||||
m_hideModeSelect = true;
|
||||
if (dmrCC) {
|
||||
m_mode = modem::STATE_DMR;
|
||||
}
|
||||
|
||||
if (p25CC) {
|
||||
m_mode = modem::STATE_P25;
|
||||
m_dmrSlot.setEnable(false);
|
||||
redraw();
|
||||
}
|
||||
|
||||
if (nxdnCC) {
|
||||
m_mode = modem::STATE_NXDN;
|
||||
m_dmrSlot.setEnable(false);
|
||||
redraw();
|
||||
}
|
||||
}
|
||||
|
||||
// are we hiding the mode select?
|
||||
if (!m_hideModeSelect) {
|
||||
bool dmrEnabled = rsp["dmrEnabled"].get<bool>();
|
||||
bool p25Enabled = rsp["p25Enabled"].get<bool>();
|
||||
bool nxdnEnabled = rsp["nxdnEnabled"].get<bool>();
|
||||
|
||||
m_digModeGroup.setGeometry(FPoint(2, 1), FSize(56, 2));
|
||||
if (dmrEnabled) {
|
||||
m_modeDMR.setPos(FPoint(1, 1));
|
||||
m_modeDMR.addCallback("toggled", [&]() {
|
||||
if (m_modeDMR.isChecked()) {
|
||||
m_mode = modem::STATE_DMR;
|
||||
m_dmrSlot.setEnable(true);
|
||||
redraw();
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
m_modeDMR.setVisible(false);
|
||||
}
|
||||
|
||||
if (p25Enabled) {
|
||||
m_modeP25.setPos(FPoint(13, 1));
|
||||
m_modeP25.addCallback("toggled", [&]() {
|
||||
if (m_modeP25.isChecked()) {
|
||||
m_mode = modem::STATE_P25;
|
||||
m_dmrSlot.setEnable(false);
|
||||
redraw();
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
m_modeP25.setVisible(false);
|
||||
}
|
||||
|
||||
if (nxdnEnabled) {
|
||||
m_modeNXDN.setPos(FPoint(22, 1));
|
||||
m_modeNXDN.addCallback("toggled", [&]() {
|
||||
if (m_modeNXDN.isChecked()) {
|
||||
m_mode = modem::STATE_NXDN;
|
||||
m_dmrSlot.setEnable(false);
|
||||
redraw();
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
m_modeNXDN.setVisible(false);
|
||||
}
|
||||
}
|
||||
else {
|
||||
m_digModeGroup.setVisible(false);
|
||||
m_modeDMR.setVisible(false);
|
||||
m_modeP25.setVisible(false);
|
||||
m_modeNXDN.setVisible(false);
|
||||
m_dmrSlotLabel.setVisible(false);
|
||||
m_dmrSlot.setVisible(false);
|
||||
redraw();
|
||||
}
|
||||
}
|
||||
catch (std::exception&) {
|
||||
/* stub */
|
||||
}
|
||||
|
||||
focusFirstChild();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
void resizeControls()
|
||||
{
|
||||
// transmit button and close button logic
|
||||
m_txButton.setGeometry(FPoint(3, int(getHeight()) - 6), FSize(10, 3));
|
||||
m_txButton.addCallback("clicked", [&]() { setTransmit(); });
|
||||
|
||||
m_closeButton.setGeometry(FPoint(17, int(getHeight()) - 6), FSize(9, 3));
|
||||
m_closeButton.addCallback("clicked", [&]() { hide(); });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
virtual void adjustSize() override
|
||||
{
|
||||
FDialog::adjustSize();
|
||||
}
|
||||
|
||||
/*
|
||||
** Event Handlers
|
||||
*/
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="e"></param>
|
||||
virtual void onKeyPress(finalcut::FKeyEvent* e)
|
||||
{
|
||||
const auto key = e->key();
|
||||
if (key == FKey::F12) {
|
||||
setTransmit();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="e"></param>
|
||||
virtual void onClose(FCloseEvent* e) override
|
||||
{
|
||||
hide();
|
||||
}
|
||||
|
||||
protected:
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
virtual void setTransmit()
|
||||
{
|
||||
/* stub */
|
||||
}
|
||||
|
||||
private:
|
||||
FButton m_txButton{"Transmit", this};
|
||||
FButton m_closeButton{"Close", this};
|
||||
|
||||
FButtonGroup m_digModeGroup{"Digital Mode", this};
|
||||
FRadioButton m_modeDMR{"DMR", &m_digModeGroup};
|
||||
FRadioButton m_modeP25{"P25", &m_digModeGroup};
|
||||
FRadioButton m_modeNXDN{"NXDN", &m_digModeGroup};
|
||||
|
||||
FLabel m_dmrSlotLabel{"DMR Slot: ", this};
|
||||
|
||||
protected:
|
||||
FSpinBox m_dmrSlot{this};
|
||||
};
|
||||
|
||||
#endif // __TRANSMIT_WND_BASE_H__
|
||||
@ -0,0 +1,144 @@
|
||||
/**
|
||||
* Digital Voice Modem - Host Software
|
||||
* GPLv2 Open Source. Use is subject to license terms.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* @package DVM / Host Software
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* Copyright (C) 2023 by Bryan Biedenkapp N2PLL
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
#if !defined(__UNINHIBIT_SUBSCRIBER_WND_H__)
|
||||
#define __UNINHIBIT_SUBSCRIBER_WND_H__
|
||||
|
||||
#include "monitor/TransmitWndBase.h"
|
||||
|
||||
#include <final/final.h>
|
||||
using namespace finalcut;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Class Declaration
|
||||
// This class implements the uninhibit subscriber window.
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
class HOST_SW_API UninhibitSubscriberWnd final : public TransmitWndBase {
|
||||
public:
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the UninhibitSubscriberWnd class.
|
||||
/// </summary>
|
||||
/// <param name="channel"></param>
|
||||
/// <param name="widget"></param>
|
||||
explicit UninhibitSubscriberWnd(lookups::VoiceChData channel, FWidget* widget = nullptr) : TransmitWndBase{channel, widget}
|
||||
{
|
||||
/* stub */
|
||||
}
|
||||
|
||||
private:
|
||||
FLabel m_dialogLabel{"Uninhibit Subscriber", this};
|
||||
|
||||
FLabel m_subscriberLabel{"Subscriber ID: ", this};
|
||||
FSpinBox m_subscriber{this};
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
void initLayout() override
|
||||
{
|
||||
FDialog::setText("Uninhibit Subscriber");
|
||||
FDialog::setSize(FSize{60, 16});
|
||||
|
||||
TransmitWndBase::initLayout();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
void initControls() override
|
||||
{
|
||||
TransmitWndBase::initControls();
|
||||
|
||||
if (m_hideModeSelect) {
|
||||
FDialog::setSize(FSize{60, 12});
|
||||
resizeControls();
|
||||
}
|
||||
|
||||
// subscriber entry
|
||||
{
|
||||
if (!m_hideModeSelect) {
|
||||
m_dialogLabel.setGeometry(FPoint(2, 6), FSize(20, 2));
|
||||
}
|
||||
else {
|
||||
m_dialogLabel.setGeometry(FPoint(2, 2), FSize(20, 2));
|
||||
}
|
||||
m_dialogLabel.setEmphasis();
|
||||
m_dialogLabel.setAlignment(Align::Center);
|
||||
|
||||
if (!m_hideModeSelect) {
|
||||
m_subscriberLabel.setGeometry(FPoint(2, 8), FSize(25, 1));
|
||||
m_subscriber.setGeometry(FPoint(28, 8), FSize(20, 1));
|
||||
}
|
||||
else {
|
||||
m_subscriberLabel.setGeometry(FPoint(2, 4), FSize(25, 1));
|
||||
m_subscriber.setGeometry(FPoint(28, 4), FSize(20, 1));
|
||||
}
|
||||
m_subscriber.setRange(1, 16777211);
|
||||
m_subscriber.setValue(1);
|
||||
m_subscriber.setShadow(false);
|
||||
}
|
||||
|
||||
m_subscriberLabel.redraw();
|
||||
redraw();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
void setTransmit() override
|
||||
{
|
||||
std::string method = PUT_DMR_RID;
|
||||
json::object req = json::object();
|
||||
req["command"].set<std::string>(RID_CMD_UNINHIBIT);
|
||||
uint32_t dstId = m_subscriber.getValue();
|
||||
req["dstId"].set<uint32_t>(dstId);
|
||||
|
||||
switch (m_mode) {
|
||||
case modem::STATE_DMR:
|
||||
{
|
||||
uint8_t slot = m_dmrSlot.getValue();
|
||||
req["slot"].set<uint8_t>(slot);
|
||||
}
|
||||
break;
|
||||
case modem::STATE_P25:
|
||||
{
|
||||
method = PUT_P25_RID;
|
||||
}
|
||||
break;
|
||||
case modem::STATE_NXDN:
|
||||
return;
|
||||
}
|
||||
|
||||
// callback REST API
|
||||
int ret = RESTClient::send(m_selectedCh.address(), m_selectedCh.port(), m_selectedCh.password(),
|
||||
HTTP_PUT, method, req, g_debug);
|
||||
if (ret != network::rest::http::HTTPPayload::StatusType::OK) {
|
||||
::LogError(LOG_HOST, "failed to send request to %s:%u", m_selectedCh.address().c_str(), m_selectedCh.port());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif // __UNINHIBIT_SUBSCRIBER_WND_H__
|
||||
Loading…
Reference in new issue