Skip to content
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
65 changes: 65 additions & 0 deletions MMDVM-Host.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1921,6 +1921,8 @@ bool CMMDVMHost::createModem()
return false;
}

writeJSONModem();

return true;
}

Expand Down Expand Up @@ -3522,6 +3524,69 @@ void CMMDVMHost::writeJSONMode(const std::string& mode)
WriteJSON("MMDVM", json);
}

void CMMDVMHost::buildModemInfo(nlohmann::json& json)
{
json["timestamp"] = CUtils::createTimestamp();

if (m_modem == nullptr) {
json["open"] = false;
return;
}

json["open"] = true;
json["protocol"] = m_modem->getVersion();
json["description"] = m_modem->getDescription();
if (!m_modem->getCPU().empty())
json["cpu"] = m_modem->getCPU();
if (!m_modem->getUDID().empty())
json["udid"] = m_modem->getUDID();

nlohmann::json modes = nlohmann::json::array();
if (m_modem->hasDStar())
modes.push_back("D-Star");
if (m_modem->hasDMR())
modes.push_back("DMR");
if (m_modem->hasYSF())
modes.push_back("YSF");
if (m_modem->hasP25())
modes.push_back("P25");
if (m_modem->hasNXDN())
modes.push_back("NXDN");
if (m_modem->hasFM())
modes.push_back("FM");
if (m_modem->hasPOCSAG())
modes.push_back("POCSAG");
json["modes"] = modes;

std::string protocol = m_conf.getModemProtocol();
json["connection"] = protocol;
if (protocol == "uart") {
json["port"] = m_conf.getModemUARTPort();
json["speed"] = m_conf.getModemUARTSpeed();
} else if (protocol == "i2c") {
json["port"] = m_conf.getModemI2CPort();
} else if (protocol == "udp") {
json["address"] = m_conf.getModemModemAddress();
json["port"] = m_conf.getModemModemPort();
}
}

void CMMDVMHost::buildModemInfoString(std::string& str)
{
nlohmann::json json;
buildModemInfo(json);

str = json.dump(-1, ' ', false, nlohmann::json::error_handler_t::ignore);
}

void CMMDVMHost::writeJSONModem()
{
nlohmann::json json;
buildModemInfo(json);

WriteJSON("Modem", json);
}

void CMMDVMHost::writeJSONMessage(const std::string& message)
{
nlohmann::json json;
Expand Down
5 changes: 5 additions & 0 deletions MMDVM-Host.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@
#include "Modem.h"
#include "Conf.h"

#include <nlohmann/json.hpp>

#include <string>

class CMMDVMHost
Expand All @@ -56,6 +58,7 @@ class CMMDVMHost

void buildNetworkStatusString(std::string &str);
void buildNetworkHostsString(std::string &str);
void buildModemInfoString(std::string &str);

private:
void setListenOnly(bool on);
Expand Down Expand Up @@ -229,6 +232,8 @@ class CMMDVMHost

void writeJSONMode(const std::string& mode);
void writeJSONMessage(const std::string& message);
void buildModemInfo(nlohmann::json& json);
void writeJSONModem();

static void onDisplay(const unsigned char* message, unsigned int length);
static void onQSOInfo(const unsigned char* message, unsigned int length);
Expand Down
54 changes: 52 additions & 2 deletions Modem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include <cmath>
#include <cstdio>
#include <cassert>
#include <cctype>
#include <cstdint>
#include <ctime>

Expand Down Expand Up @@ -344,6 +345,9 @@ m_fmExtEnable(false),
#endif
m_capabilities1(0x00U),
m_capabilities2(0x00U),
m_description(),
m_cpu(),
m_udid(),
m_serialDataLen(0U)
{
m_buffer = new unsigned char[BUFFER_LENGTH];
Expand Down Expand Up @@ -2307,32 +2311,63 @@ bool CModem::readVersion()
if ((resp == RESP_TYPE_MMDVM::OK) && (m_buffer[2U] == MMDVM_GET_VERSION)) {
m_protocolVersion = m_buffer[3U];
switch (m_protocolVersion) {
case 1U:
case 1U: {
LogInfo("MMDVM protocol version: 1, description: %.*s", m_length - 4U, m_buffer + 4U);
// Firmware built with its chip ID sends it as text after
// a NUL that ends the description.
unsigned int descLen = 0U;
while ((4U + descLen) < m_length && m_buffer[4U + descLen] != 0x00U)
descLen++;
m_description = std::string((char*)(m_buffer + 4U), descLen);
m_cpu.clear();
m_udid.clear();
for (unsigned int i = 4U + descLen + 1U; i < m_length && m_buffer[i] != 0x00U; i++) {
if (::isxdigit(m_buffer[i]))
m_udid += char(::toupper(m_buffer[i]));
}
if (!m_udid.empty())
LogInfo("UDID: %s", m_udid.c_str());
m_capabilities1 = CAP1_DSTAR | CAP1_DMR | CAP1_YSF | CAP1_P25 | CAP1_NXDN;
m_capabilities2 = CAP2_POCSAG;
if (::strstr((char*)(m_buffer + 4U), "v1.6.") != nullptr)
m_capabilities1 |= CAP1_M17;
break;
}

case 2U:
case 2U: {
LogInfo("MMDVM protocol version: 2, description: %.*s", m_length - 23U, m_buffer + 23U);
m_description = std::string((char*)(m_buffer + 23U), m_length - 23U);
m_cpu.clear();
m_udid.clear();
unsigned int udidLen = 0U;
switch (m_buffer[6U]) {
case 0U:
LogInfo("CPU: Atmel ARM, UDID: %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X", m_buffer[7U], m_buffer[8U], m_buffer[9U], m_buffer[10U], m_buffer[11U], m_buffer[12U], m_buffer[13U], m_buffer[14U], m_buffer[15U], m_buffer[16U], m_buffer[17U], m_buffer[18U], m_buffer[19U], m_buffer[20U], m_buffer[21U], m_buffer[22U]);
m_cpu = "Atmel ARM";
udidLen = 16U;
break;
case 1U:
LogInfo("CPU: NXP ARM, UDID: %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X", m_buffer[7U], m_buffer[8U], m_buffer[9U], m_buffer[10U], m_buffer[11U], m_buffer[12U], m_buffer[13U], m_buffer[14U], m_buffer[15U], m_buffer[16U], m_buffer[17U], m_buffer[18U], m_buffer[19U], m_buffer[20U], m_buffer[21U], m_buffer[22U]);
m_cpu = "NXP ARM";
udidLen = 16U;
break;
case 2U:
LogInfo("CPU: ST-Micro ARM, UDID: %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X", m_buffer[7U], m_buffer[8U], m_buffer[9U], m_buffer[10U], m_buffer[11U], m_buffer[12U], m_buffer[13U], m_buffer[14U], m_buffer[15U], m_buffer[16U], m_buffer[17U], m_buffer[18U]);
m_cpu = "ST-Micro ARM";
udidLen = 12U;
break;
default:
LogInfo("CPU: Unknown type: %u", m_buffer[6U]);
break;
}
for (unsigned int i = 0U; i < udidLen; i++) {
char hex[3U];
::snprintf(hex, 3U, "%02X", m_buffer[7U + i]);
m_udid += hex;
}
m_capabilities1 = m_buffer[4U];
m_capabilities2 = m_buffer[5U];
}
break;

default:
Expand Down Expand Up @@ -2372,6 +2407,21 @@ bool CModem::readVersion()
return false;
}

std::string CModem::getDescription() const
{
return m_description;
}

std::string CModem::getCPU() const
{
return m_cpu;
}

std::string CModem::getUDID() const
{
return m_udid;
}

bool CModem::readStatus()
{
assert(m_port != nullptr);
Expand Down
10 changes: 10 additions & 0 deletions Modem.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,13 @@ class CModem {

unsigned int getVersion() const;

// What the modem said in its version reply: its description, CPU
// (protocol 2 only) and chip ID (protocol 2, or protocol 1 firmware
// built to send one), each empty when it did not say.
std::string getDescription() const;
std::string getCPU() const;
std::string getUDID() const;

#if defined(USE_DSTAR)
unsigned int readDStarData(unsigned char* data);
#endif
Expand Down Expand Up @@ -435,6 +442,9 @@ class CModem {
#endif
unsigned char m_capabilities1;
unsigned char m_capabilities2;
std::string m_description;
std::string m_cpu;
std::string m_udid;

bool readVersion();
bool readStatus();
Expand Down
10 changes: 10 additions & 0 deletions RemoteControl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,16 @@ REMOTE_COMMAND CRemoteControl::getCommand(const std::string& command)
}

m_command = REMOTE_COMMAND::CONFIG_HOSTS;
} else if (m_args.at(0U) == "modem") {
// The modem's details as JSON, the same as the "Modem" message
// sent when it was opened.
if (m_host != nullptr) {
m_host->buildModemInfoString(reply);
} else {
reply = "KO";
}

m_command = REMOTE_COMMAND::MODEM_INFO;
} else {
reply = "KO";
}
Expand Down
3 changes: 2 additions & 1 deletion RemoteControl.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,8 @@ enum class REMOTE_COMMAND {
LISTEN_OFF,
RELOAD,
CONNECTION_STATUS,
CONFIG_HOSTS
CONFIG_HOSTS,
MODEM_INFO
};

class CRemoteControl {
Expand Down
20 changes: 19 additions & 1 deletion schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@
"loss": {"type": "number", "minimum": 0.0},
"ber": {"type": "number", "minimum": 0.0},
"rssi": {"type": "integer", "minimum": -200, "maximum": -10},
"timestamp": {"type": "string"}
"timestamp": {"type": "string"},
"modem_mode": {"type": "string", "enum": ["D-Star", "DMR", "YSF", "P25", "NXDN", "FM", "POCSAG"]},
"modem_connection": {"type": "string", "enum": ["uart", "udp", "i2c", "null"]}
},

"MMDVM": {
Expand Down Expand Up @@ -182,6 +184,22 @@
"required": ["timestamp", "state"]
},

"Modem": {
"type": "object",
"timestamp": {"$ref": "#/$defs/timestamp"},
"open": {"type": "boolean"},
"protocol": {"type": "integer", "enum": [1, 2]},
"description": {"type": "string"},
"cpu": {"type": "string"},
"udid": {"type": "string"},
"modes": {"type": "array", "items": {"$ref": "#/$defs/modem_mode"}},
"connection": {"$ref": "#/$defs/modem_connection"},
"port": {"type": ["string", "integer"]},
"speed": {"type": "integer"},
"address": {"type": "string"},
"required": ["timestamp", "open"]
},

"M17": {
"type": "object",
"timestamp": {"$ref": "#/$defs/timestamp"},
Expand Down