mirror of
https://github.com/meshtastic/firmware.git
synced 2025-07-30 02:15:41 +00:00
Validate serial config console override modes
This commit is contained in:
parent
7c5e2c5393
commit
41a2f8135e
@ -43,6 +43,7 @@
|
|||||||
#if !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C
|
#if !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C
|
||||||
#include "motion/AccelerometerThread.h"
|
#include "motion/AccelerometerThread.h"
|
||||||
#endif
|
#endif
|
||||||
|
#include "SerialModule.h"
|
||||||
|
|
||||||
AdminModule *adminModule;
|
AdminModule *adminModule;
|
||||||
bool hasOpenEditTransaction;
|
bool hasOpenEditTransaction;
|
||||||
@ -807,10 +808,12 @@ void AdminModule::handleSetConfig(const meshtastic_Config &c)
|
|||||||
|
|
||||||
bool AdminModule::handleSetModuleConfig(const meshtastic_ModuleConfig &c)
|
bool AdminModule::handleSetModuleConfig(const meshtastic_ModuleConfig &c)
|
||||||
{
|
{
|
||||||
// If we are in an open transaction or configuring MQTT, defer disabling Bluetooth
|
// If we are in an open transaction or configuring MQTT or Serial (which have validation), defer disabling Bluetooth
|
||||||
// Otherwise, disable Bluetooth to prevent the phone from interfering with the config
|
// Otherwise, disable Bluetooth to prevent the phone from interfering with the config
|
||||||
if (!hasOpenEditTransaction && c.which_payload_variant != meshtastic_ModuleConfig_mqtt_tag)
|
if (!hasOpenEditTransaction &&
|
||||||
|
!IS_ONE_OF(c.which_payload_variant, meshtastic_ModuleConfig_mqtt_tag, meshtastic_ModuleConfig_serial_tag)) {
|
||||||
disableBluetooth();
|
disableBluetooth();
|
||||||
|
}
|
||||||
|
|
||||||
switch (c.which_payload_variant) {
|
switch (c.which_payload_variant) {
|
||||||
case meshtastic_ModuleConfig_mqtt_tag:
|
case meshtastic_ModuleConfig_mqtt_tag:
|
||||||
@ -830,6 +833,10 @@ bool AdminModule::handleSetModuleConfig(const meshtastic_ModuleConfig &c)
|
|||||||
break;
|
break;
|
||||||
case meshtastic_ModuleConfig_serial_tag:
|
case meshtastic_ModuleConfig_serial_tag:
|
||||||
LOG_INFO("Set module config: Serial");
|
LOG_INFO("Set module config: Serial");
|
||||||
|
if (!SerialModule::isValidConfig(c.payload_variant.serial)) {
|
||||||
|
LOG_ERROR("Invalid serial config");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
moduleConfig.has_serial = true;
|
moduleConfig.has_serial = true;
|
||||||
moduleConfig.serial = c.payload_variant.serial;
|
moduleConfig.serial = c.payload_variant.serial;
|
||||||
break;
|
break;
|
||||||
@ -985,9 +992,10 @@ void AdminModule::handleGetConfig(const meshtastic_MeshPacket &req, const uint32
|
|||||||
// So even if we internally use 0 to represent 'use default' we still need to send the value we are
|
// So even if we internally use 0 to represent 'use default' we still need to send the value we are
|
||||||
// using to the app (so that even old phone apps work with new device loads).
|
// using to the app (so that even old phone apps work with new device loads).
|
||||||
// r.get_radio_response.preferences.ls_secs = getPref_ls_secs();
|
// r.get_radio_response.preferences.ls_secs = getPref_ls_secs();
|
||||||
// hideSecret(r.get_radio_response.preferences.wifi_ssid); // hmm - leave public for now, because only minimally private
|
// hideSecret(r.get_radio_response.preferences.wifi_ssid); // hmm - leave public for now, because only minimally
|
||||||
// and useful for users to know current provisioning) hideSecret(r.get_radio_response.preferences.wifi_password);
|
// private and useful for users to know current provisioning)
|
||||||
// r.get_config_response.which_payloadVariant = Config_ModuleConfig_telemetry_tag;
|
// hideSecret(r.get_radio_response.preferences.wifi_password); r.get_config_response.which_payloadVariant =
|
||||||
|
// Config_ModuleConfig_telemetry_tag;
|
||||||
res.which_payload_variant = meshtastic_AdminMessage_get_config_response_tag;
|
res.which_payload_variant = meshtastic_AdminMessage_get_config_response_tag;
|
||||||
setPassKey(&res);
|
setPassKey(&res);
|
||||||
myReply = allocDataProtobuf(res);
|
myReply = allocDataProtobuf(res);
|
||||||
@ -1071,9 +1079,10 @@ void AdminModule::handleGetModuleConfig(const meshtastic_MeshPacket &req, const
|
|||||||
// So even if we internally use 0 to represent 'use default' we still need to send the value we are
|
// So even if we internally use 0 to represent 'use default' we still need to send the value we are
|
||||||
// using to the app (so that even old phone apps work with new device loads).
|
// using to the app (so that even old phone apps work with new device loads).
|
||||||
// r.get_radio_response.preferences.ls_secs = getPref_ls_secs();
|
// r.get_radio_response.preferences.ls_secs = getPref_ls_secs();
|
||||||
// hideSecret(r.get_radio_response.preferences.wifi_ssid); // hmm - leave public for now, because only minimally private
|
// hideSecret(r.get_radio_response.preferences.wifi_ssid); // hmm - leave public for now, because only minimally
|
||||||
// and useful for users to know current provisioning) hideSecret(r.get_radio_response.preferences.wifi_password);
|
// private and useful for users to know current provisioning)
|
||||||
// r.get_config_response.which_payloadVariant = Config_ModuleConfig_telemetry_tag;
|
// hideSecret(r.get_radio_response.preferences.wifi_password); r.get_config_response.which_payloadVariant =
|
||||||
|
// Config_ModuleConfig_telemetry_tag;
|
||||||
res.which_payload_variant = meshtastic_AdminMessage_get_module_config_response_tag;
|
res.which_payload_variant = meshtastic_AdminMessage_get_module_config_response_tag;
|
||||||
setPassKey(&res);
|
setPassKey(&res);
|
||||||
myReply = allocDataProtobuf(res);
|
myReply = allocDataProtobuf(res);
|
||||||
|
@ -74,6 +74,27 @@ static Print *serialPrint = &Serial2;
|
|||||||
char serialBytes[512];
|
char serialBytes[512];
|
||||||
size_t serialPayloadSize;
|
size_t serialPayloadSize;
|
||||||
|
|
||||||
|
bool SerialModule::isValidConfig(const meshtastic_ModuleConfig_SerialConfig &config)
|
||||||
|
{
|
||||||
|
if (config.override_console_serial_port && !IS_ONE_OF(config.mode, meshtastic_ModuleConfig_SerialConfig_Serial_Mode_NMEA,
|
||||||
|
meshtastic_ModuleConfig_SerialConfig_Serial_Mode_CALTOPO)) {
|
||||||
|
const char *warning =
|
||||||
|
"Invalid Serial config: override console serial port is only supported in NMEA and CalTopo output-only modes.";
|
||||||
|
LOG_ERROR(warning);
|
||||||
|
#if !IS_RUNNING_TESTS
|
||||||
|
meshtastic_ClientNotification *cn = clientNotificationPool.allocZeroed();
|
||||||
|
cn->level = meshtastic_LogRecord_Level_ERROR;
|
||||||
|
cn->time = getValidTime(RTCQualityFromNet);
|
||||||
|
strncpy(cn->message, warning, sizeof(cn->message) - 1);
|
||||||
|
cn->message[sizeof(cn->message) - 1] = '\0'; // Ensure null termination
|
||||||
|
service->sendClientNotification(cn);
|
||||||
|
#endif
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
SerialModuleRadio::SerialModuleRadio() : MeshModule("SerialModuleRadio")
|
SerialModuleRadio::SerialModuleRadio() : MeshModule("SerialModuleRadio")
|
||||||
{
|
{
|
||||||
switch (moduleConfig.serial.mode) {
|
switch (moduleConfig.serial.mode) {
|
||||||
|
@ -20,6 +20,8 @@ class SerialModule : public StreamAPI, private concurrency::OSThread
|
|||||||
public:
|
public:
|
||||||
SerialModule();
|
SerialModule();
|
||||||
|
|
||||||
|
static bool isValidConfig(const meshtastic_ModuleConfig_SerialConfig &config);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual int32_t runOnce() override;
|
virtual int32_t runOnce() override;
|
||||||
|
|
||||||
|
140
test/test_serial/SerialModule.cpp
Normal file
140
test/test_serial/SerialModule.cpp
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
#include "DebugConfiguration.h"
|
||||||
|
#include "TestUtil.h"
|
||||||
|
#include <unity.h>
|
||||||
|
|
||||||
|
#ifdef ARCH_PORTDUINO
|
||||||
|
#include "configuration.h"
|
||||||
|
#include "modules/SerialModule.h"
|
||||||
|
|
||||||
|
#if defined(UNIT_TEST)
|
||||||
|
#define IS_RUNNING_TESTS 1
|
||||||
|
#else
|
||||||
|
#define IS_RUNNING_TESTS 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Test that empty configuration is valid.
|
||||||
|
void test_serialConfigEmptyIsValid(void)
|
||||||
|
{
|
||||||
|
meshtastic_ModuleConfig_SerialConfig config = {};
|
||||||
|
|
||||||
|
TEST_ASSERT_TRUE(SerialModule::isValidConfig(config));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that basic enabled configuration is valid.
|
||||||
|
void test_serialConfigEnabledIsValid(void)
|
||||||
|
{
|
||||||
|
meshtastic_ModuleConfig_SerialConfig config = {.enabled = true};
|
||||||
|
|
||||||
|
TEST_ASSERT_TRUE(SerialModule::isValidConfig(config));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that configuration with override_console_serial_port and NMEA mode is valid.
|
||||||
|
void test_serialConfigWithOverrideConsoleNmeaModeIsValid(void)
|
||||||
|
{
|
||||||
|
meshtastic_ModuleConfig_SerialConfig config = {
|
||||||
|
.enabled = true, .override_console_serial_port = true, .mode = meshtastic_ModuleConfig_SerialConfig_Serial_Mode_NMEA};
|
||||||
|
|
||||||
|
TEST_ASSERT_TRUE(SerialModule::isValidConfig(config));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that configuration with override_console_serial_port and CalTopo mode is valid.
|
||||||
|
void test_serialConfigWithOverrideConsoleCalTopoModeIsValid(void)
|
||||||
|
{
|
||||||
|
meshtastic_ModuleConfig_SerialConfig config = {
|
||||||
|
.enabled = true, .override_console_serial_port = true, .mode = meshtastic_ModuleConfig_SerialConfig_Serial_Mode_CALTOPO};
|
||||||
|
|
||||||
|
TEST_ASSERT_TRUE(SerialModule::isValidConfig(config));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that configuration with override_console_serial_port and DEFAULT mode is invalid.
|
||||||
|
void test_serialConfigWithOverrideConsoleDefaultModeIsInvalid(void)
|
||||||
|
{
|
||||||
|
meshtastic_ModuleConfig_SerialConfig config = {
|
||||||
|
.enabled = true, .override_console_serial_port = true, .mode = meshtastic_ModuleConfig_SerialConfig_Serial_Mode_DEFAULT};
|
||||||
|
|
||||||
|
TEST_ASSERT_FALSE(SerialModule::isValidConfig(config));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that configuration with override_console_serial_port and SIMPLE mode is invalid.
|
||||||
|
void test_serialConfigWithOverrideConsoleSimpleModeIsInvalid(void)
|
||||||
|
{
|
||||||
|
meshtastic_ModuleConfig_SerialConfig config = {
|
||||||
|
.enabled = true, .override_console_serial_port = true, .mode = meshtastic_ModuleConfig_SerialConfig_Serial_Mode_SIMPLE};
|
||||||
|
|
||||||
|
TEST_ASSERT_FALSE(SerialModule::isValidConfig(config));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that configuration with override_console_serial_port and TEXTMSG mode is invalid.
|
||||||
|
void test_serialConfigWithOverrideConsoleTextMsgModeIsInvalid(void)
|
||||||
|
{
|
||||||
|
meshtastic_ModuleConfig_SerialConfig config = {
|
||||||
|
.enabled = true, .override_console_serial_port = true, .mode = meshtastic_ModuleConfig_SerialConfig_Serial_Mode_TEXTMSG};
|
||||||
|
|
||||||
|
TEST_ASSERT_FALSE(SerialModule::isValidConfig(config));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that configuration with override_console_serial_port and PROTO mode is invalid.
|
||||||
|
void test_serialConfigWithOverrideConsoleProtoModeIsInvalid(void)
|
||||||
|
{
|
||||||
|
meshtastic_ModuleConfig_SerialConfig config = {
|
||||||
|
.enabled = true, .override_console_serial_port = true, .mode = meshtastic_ModuleConfig_SerialConfig_Serial_Mode_PROTO};
|
||||||
|
|
||||||
|
TEST_ASSERT_FALSE(SerialModule::isValidConfig(config));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that various modes work without override_console_serial_port.
|
||||||
|
void test_serialConfigVariousModesWithoutOverrideAreValid(void)
|
||||||
|
{
|
||||||
|
meshtastic_ModuleConfig_SerialConfig config = {.enabled = true, .override_console_serial_port = false};
|
||||||
|
|
||||||
|
// Test DEFAULT mode
|
||||||
|
config.mode = meshtastic_ModuleConfig_SerialConfig_Serial_Mode_DEFAULT;
|
||||||
|
TEST_ASSERT_TRUE(SerialModule::isValidConfig(config));
|
||||||
|
|
||||||
|
// Test SIMPLE mode
|
||||||
|
config.mode = meshtastic_ModuleConfig_SerialConfig_Serial_Mode_SIMPLE;
|
||||||
|
TEST_ASSERT_TRUE(SerialModule::isValidConfig(config));
|
||||||
|
|
||||||
|
// Test TEXTMSG mode
|
||||||
|
config.mode = meshtastic_ModuleConfig_SerialConfig_Serial_Mode_TEXTMSG;
|
||||||
|
TEST_ASSERT_TRUE(SerialModule::isValidConfig(config));
|
||||||
|
|
||||||
|
// Test PROTO mode
|
||||||
|
config.mode = meshtastic_ModuleConfig_SerialConfig_Serial_Mode_PROTO;
|
||||||
|
TEST_ASSERT_TRUE(SerialModule::isValidConfig(config));
|
||||||
|
|
||||||
|
// Test NMEA mode
|
||||||
|
config.mode = meshtastic_ModuleConfig_SerialConfig_Serial_Mode_NMEA;
|
||||||
|
TEST_ASSERT_TRUE(SerialModule::isValidConfig(config));
|
||||||
|
|
||||||
|
// Test CALTOPO mode
|
||||||
|
config.mode = meshtastic_ModuleConfig_SerialConfig_Serial_Mode_CALTOPO;
|
||||||
|
TEST_ASSERT_TRUE(SerialModule::isValidConfig(config));
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
initializeTestEnvironment();
|
||||||
|
|
||||||
|
UNITY_BEGIN();
|
||||||
|
RUN_TEST(test_serialConfigEmptyIsValid);
|
||||||
|
RUN_TEST(test_serialConfigEnabledIsValid);
|
||||||
|
RUN_TEST(test_serialConfigWithOverrideConsoleNmeaModeIsValid);
|
||||||
|
RUN_TEST(test_serialConfigWithOverrideConsoleCalTopoModeIsValid);
|
||||||
|
RUN_TEST(test_serialConfigWithOverrideConsoleDefaultModeIsInvalid);
|
||||||
|
RUN_TEST(test_serialConfigWithOverrideConsoleSimpleModeIsInvalid);
|
||||||
|
RUN_TEST(test_serialConfigWithOverrideConsoleTextMsgModeIsInvalid);
|
||||||
|
RUN_TEST(test_serialConfigWithOverrideConsoleProtoModeIsInvalid);
|
||||||
|
RUN_TEST(test_serialConfigVariousModesWithoutOverrideAreValid);
|
||||||
|
exit(UNITY_END());
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
initializeTestEnvironment();
|
||||||
|
LOG_WARN("This test requires the ARCH_PORTDUINO variant");
|
||||||
|
UNITY_BEGIN();
|
||||||
|
UNITY_END();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
void loop() {}
|
Loading…
Reference in New Issue
Block a user