From 850f61d2d0ec9662b77662de8733f2e47061a239 Mon Sep 17 00:00:00 2001 From: Jonathan Bennett Date: Mon, 28 Oct 2024 21:48:10 -0500 Subject: [PATCH] Native config.d (#5165) * Add support for loading yaml from a config directory * Add waveshare hats to the new config.d approach * Move to available.d for module inactive module configs --- .github/workflows/package_amd64.yml | 3 + .github/workflows/package_raspbian.yml | 3 + .github/workflows/package_raspbian_armv7l.yml | 3 + bin/config-dist.yaml | 11 +- bin/config.d/display-waveshare-2.8.yaml | 18 + bin/config.d/lora-waveshare-sxxx.yaml | 8 + src/platform/portduino/PortduinoGlue.cpp | 375 +++++++++--------- src/platform/portduino/PortduinoGlue.h | 7 +- 8 files changed, 239 insertions(+), 189 deletions(-) create mode 100644 bin/config.d/display-waveshare-2.8.yaml create mode 100644 bin/config.d/lora-waveshare-sxxx.yaml diff --git a/.github/workflows/package_amd64.yml b/.github/workflows/package_amd64.yml index 0b5093f24..a5442246a 100644 --- a/.github/workflows/package_amd64.yml +++ b/.github/workflows/package_amd64.yml @@ -50,11 +50,14 @@ jobs: mkdir -p .debpkg/usr/share/doc/meshtasticd/web mkdir -p .debpkg/usr/sbin mkdir -p .debpkg/etc/meshtasticd + mkdir -p .debpkg/etc/meshtasticd/config.d + mkdir -p .debpkg/etc/meshtasticd/available.d mkdir -p .debpkg/usr/lib/systemd/system/ tar -xf build.tar -C .debpkg/usr/share/doc/meshtasticd/web gunzip .debpkg/usr/share/doc/meshtasticd/web/*.gz cp release/meshtasticd_linux_x86_64 .debpkg/usr/sbin/meshtasticd cp bin/config-dist.yaml .debpkg/etc/meshtasticd/config.yaml + cp bin/config.d/* .debpkg/etc/meshtasticd/available.d/ chmod +x .debpkg/usr/sbin/meshtasticd cp bin/meshtasticd.service .debpkg/usr/lib/systemd/system/meshtasticd.service echo "/etc/meshtasticd/config.yaml" > .debpkg/DEBIAN/conffiles diff --git a/.github/workflows/package_raspbian.yml b/.github/workflows/package_raspbian.yml index bcbda53e2..89efba1de 100644 --- a/.github/workflows/package_raspbian.yml +++ b/.github/workflows/package_raspbian.yml @@ -50,11 +50,14 @@ jobs: mkdir -p .debpkg/usr/share/doc/meshtasticd/web mkdir -p .debpkg/usr/sbin mkdir -p .debpkg/etc/meshtasticd + mkdir -p .debpkg/etc/meshtasticd/config.d + mkdir -p .debpkg/etc/meshtasticd/available.d mkdir -p .debpkg/usr/lib/systemd/system/ tar -xf build.tar -C .debpkg/usr/share/doc/meshtasticd/web gunzip .debpkg/usr/share/doc/meshtasticd/web/*.gz cp release/meshtasticd_linux_aarch64 .debpkg/usr/sbin/meshtasticd cp bin/config-dist.yaml .debpkg/etc/meshtasticd/config.yaml + cp bin/config.d/* .debpkg/etc/meshtasticd/available.d/ chmod +x .debpkg/usr/sbin/meshtasticd cp bin/meshtasticd.service .debpkg/usr/lib/systemd/system/meshtasticd.service echo "/etc/meshtasticd/config.yaml" > .debpkg/DEBIAN/conffiles diff --git a/.github/workflows/package_raspbian_armv7l.yml b/.github/workflows/package_raspbian_armv7l.yml index 1308fe925..5cbc27097 100644 --- a/.github/workflows/package_raspbian_armv7l.yml +++ b/.github/workflows/package_raspbian_armv7l.yml @@ -50,11 +50,14 @@ jobs: mkdir -p .debpkg/usr/share/doc/meshtasticd/web mkdir -p .debpkg/usr/sbin mkdir -p .debpkg/etc/meshtasticd + mkdir -p .debpkg/etc/meshtasticd/config.d + mkdir -p .debpkg/etc/meshtasticd/available.d mkdir -p .debpkg/usr/lib/systemd/system/ tar -xf build.tar -C .debpkg/usr/share/doc/meshtasticd/web gunzip .debpkg/usr/share/doc/meshtasticd/web/*.gz cp release/meshtasticd_linux_armv7l .debpkg/usr/sbin/meshtasticd cp bin/config-dist.yaml .debpkg/etc/meshtasticd/config.yaml + cp bin/config.d/* .debpkg/etc/meshtasticd/available.d/ chmod +x .debpkg/usr/sbin/meshtasticd cp bin/meshtasticd.service .debpkg/usr/lib/systemd/system/meshtasticd.service echo "/etc/meshtasticd/config.yaml" > .debpkg/DEBIAN/conffiles diff --git a/bin/config-dist.yaml b/bin/config-dist.yaml index e20ab0d33..bf1331a2b 100644 --- a/bin/config-dist.yaml +++ b/bin/config-dist.yaml @@ -1,15 +1,11 @@ +### Many device configs have been moved to /etc/meshtasticd/available.d +### To activate, simply copy or link the appropriate file into /etc/meshtasticd/config.d + ### Define your devices here using Broadcom pin numbering ### Uncomment the block that corresponds to your hardware ### Including the "Module:" line! --- Lora: -# Module: sx1262 # Waveshare SX126X XXXM -# DIO2_AS_RF_SWITCH: true -# CS: 21 -# IRQ: 16 -# Busy: 20 -# Reset: 18 -# SX126X_ANT_SW: 6 # Module: sx1262 # Waveshare SX1302 LISTEN ONLY AT THIS TIME! # CS: 7 @@ -179,3 +175,4 @@ Webserver: General: MaxNodes: 200 MaxMessageQueue: 100 + ConfigDirectory: /etc/meshtasticd/config.d/ \ No newline at end of file diff --git a/bin/config.d/display-waveshare-2.8.yaml b/bin/config.d/display-waveshare-2.8.yaml new file mode 100644 index 000000000..2e28276d8 --- /dev/null +++ b/bin/config.d/display-waveshare-2.8.yaml @@ -0,0 +1,18 @@ +Display: + +### Waveshare 2.8inch RPi LCD + Panel: ST7789 + CS: 8 + DC: 22 # Data/Command pin + Backlight: 18 + Width: 240 + Height: 320 + Reset: 27 + Rotate: true + Invert: true + +Touchscreen: +### Note, at least for now, the touchscreen must have a CS pin defined, even if you let Linux manage the CS switching. + Module: XPT2046 # Waveshare 2.8inch + CS: 7 + IRQ: 17 \ No newline at end of file diff --git a/bin/config.d/lora-waveshare-sxxx.yaml b/bin/config.d/lora-waveshare-sxxx.yaml new file mode 100644 index 000000000..a9ff13653 --- /dev/null +++ b/bin/config.d/lora-waveshare-sxxx.yaml @@ -0,0 +1,8 @@ +Lora: + Module: sx1262 # Waveshare SX126X XXXM + DIO2_AS_RF_SWITCH: true + CS: 21 + IRQ: 16 + Busy: 20 + Reset: 18 + SX126X_ANT_SW: 6 diff --git a/src/platform/portduino/PortduinoGlue.cpp b/src/platform/portduino/PortduinoGlue.cpp index e56016a5b..78562e47a 100644 --- a/src/platform/portduino/PortduinoGlue.cpp +++ b/src/platform/portduino/PortduinoGlue.cpp @@ -11,6 +11,7 @@ #include "PortduinoGlue.h" #include "linux/gpio/LinuxGPIOPin.h" #include "yaml-cpp/yaml.h" +#include #include #include #include @@ -100,33 +101,22 @@ void portduinoSetup() settingsStrings[displayspidev] = ""; settingsMap[spiSpeed] = 2000000; settingsMap[ascii_logs] = !isatty(1); + settingsMap[displayPanel] = no_screen; + settingsMap[touchscreenModule] = no_touchscreen; YAML::Node yamlConfig; if (configPath != nullptr) { - std::cout << "Using " << configPath << " as config file" << std::endl; - try { - yamlConfig = YAML::LoadFile(configPath); - } catch (YAML::Exception &e) { - std::cout << "Could not open " << configPath << " because of error: " << e.what() << std::endl; + if (loadConfig(configPath)) { + std::cout << "Using " << configPath << " as config file" << std::endl; + } else { + std::cout << "Unable to use " << configPath << " as config file" << std::endl; exit(EXIT_FAILURE); } - } else if (access("config.yaml", R_OK) == 0) { + } else if (access("config.yaml", R_OK) == 0 && loadConfig("config.yaml")) { std::cout << "Using local config.yaml as config file" << std::endl; - try { - yamlConfig = YAML::LoadFile("config.yaml"); - } catch (YAML::Exception &e) { - std::cout << "*** Exception " << e.what() << std::endl; - exit(EXIT_FAILURE); - } - } else if (access("/etc/meshtasticd/config.yaml", R_OK) == 0) { + } else if (access("/etc/meshtasticd/config.yaml", R_OK) == 0 && loadConfig("/etc/meshtasticd/config.yaml")) { std::cout << "Using /etc/meshtasticd/config.yaml as config file" << std::endl; - try { - yamlConfig = YAML::LoadFile("/etc/meshtasticd/config.yaml"); - } catch (YAML::Exception &e) { - std::cout << "*** Exception " << e.what() << std::endl; - exit(EXIT_FAILURE); - } } else { std::cout << "No 'config.yaml' found, running simulated." << std::endl; settingsMap[maxnodes] = 200; // Default to 200 nodes @@ -136,170 +126,21 @@ void portduinoSetup() return; } + if (settingsStrings[config_directory] != "") { + std::string filetype = ".yaml"; + for (const std::filesystem::directory_entry &entry : + std::filesystem::directory_iterator{settingsStrings[config_directory]}) { + if (ends_with(entry.path().string(), ".yaml")) { + std::cout << "Also using " << entry << " as additional config file" << std::endl; + loadConfig(entry.path().c_str()); + } + } + } + // Rather important to set this, if not running simulated. randomSeed(time(NULL)); - try { - if (yamlConfig["Logging"]) { - if (yamlConfig["Logging"]["LogLevel"].as("info") == "trace") { - settingsMap[logoutputlevel] = level_trace; - } else if (yamlConfig["Logging"]["LogLevel"].as("info") == "debug") { - settingsMap[logoutputlevel] = level_debug; - } else if (yamlConfig["Logging"]["LogLevel"].as("info") == "info") { - settingsMap[logoutputlevel] = level_info; - } else if (yamlConfig["Logging"]["LogLevel"].as("info") == "warn") { - settingsMap[logoutputlevel] = level_warn; - } else if (yamlConfig["Logging"]["LogLevel"].as("info") == "error") { - settingsMap[logoutputlevel] = level_error; - } - settingsStrings[traceFilename] = yamlConfig["Logging"]["TraceFile"].as(""); - if (yamlConfig["Logging"]["AsciiLogs"]) { - // Default is !isatty(1) but can be set explicitly in config.yaml - settingsMap[ascii_logs] = yamlConfig["Logging"]["AsciiLogs"].as(); - } - } - if (yamlConfig["Lora"]) { - settingsMap[use_sx1262] = false; - settingsMap[use_rf95] = false; - settingsMap[use_sx1280] = false; - settingsMap[use_sx1268] = false; - - if (yamlConfig["Lora"]["Module"] && yamlConfig["Lora"]["Module"].as("") == "sx1262") { - settingsMap[use_sx1262] = true; - } else if (yamlConfig["Lora"]["Module"] && yamlConfig["Lora"]["Module"].as("") == "RF95") { - settingsMap[use_rf95] = true; - } else if (yamlConfig["Lora"]["Module"] && yamlConfig["Lora"]["Module"].as("") == "sx1280") { - settingsMap[use_sx1280] = true; - } else if (yamlConfig["Lora"]["Module"] && yamlConfig["Lora"]["Module"].as("") == "sx1268") { - settingsMap[use_sx1268] = true; - } - settingsMap[dio2_as_rf_switch] = yamlConfig["Lora"]["DIO2_AS_RF_SWITCH"].as(false); - settingsMap[dio3_tcxo_voltage] = yamlConfig["Lora"]["DIO3_TCXO_VOLTAGE"].as(false); - settingsMap[cs] = yamlConfig["Lora"]["CS"].as(RADIOLIB_NC); - settingsMap[irq] = yamlConfig["Lora"]["IRQ"].as(RADIOLIB_NC); - settingsMap[busy] = yamlConfig["Lora"]["Busy"].as(RADIOLIB_NC); - settingsMap[reset] = yamlConfig["Lora"]["Reset"].as(RADIOLIB_NC); - settingsMap[txen] = yamlConfig["Lora"]["TXen"].as(RADIOLIB_NC); - settingsMap[rxen] = yamlConfig["Lora"]["RXen"].as(RADIOLIB_NC); - settingsMap[sx126x_ant_sw] = yamlConfig["Lora"]["SX126X_ANT_SW"].as(RADIOLIB_NC); - settingsMap[gpiochip] = yamlConfig["Lora"]["gpiochip"].as(0); - settingsMap[ch341Quirk] = yamlConfig["Lora"]["ch341_quirk"].as(false); - settingsMap[spiSpeed] = yamlConfig["Lora"]["spiSpeed"].as(2000000); - gpioChipName += std::to_string(settingsMap[gpiochip]); - - settingsStrings[spidev] = "/dev/" + yamlConfig["Lora"]["spidev"].as("spidev0.0"); - if (settingsStrings[spidev].length() == 14) { - int x = settingsStrings[spidev].at(11) - '0'; - int y = settingsStrings[spidev].at(13) - '0'; - if (x >= 0 && x < 10 && y >= 0 && y < 10) { - settingsMap[spidev] = x + y << 4; - settingsMap[displayspidev] = settingsMap[spidev]; - settingsMap[touchscreenspidev] = settingsMap[spidev]; - } - } - } - if (yamlConfig["GPIO"]) { - settingsMap[user] = yamlConfig["GPIO"]["User"].as(RADIOLIB_NC); - } - if (yamlConfig["GPS"]) { - std::string serialPath = yamlConfig["GPS"]["SerialPath"].as(""); - if (serialPath != "") { - Serial1.setPath(serialPath); - settingsMap[has_gps] = 1; - } - } - if (yamlConfig["I2C"]) { - settingsStrings[i2cdev] = yamlConfig["I2C"]["I2CDevice"].as(""); - } - settingsMap[displayPanel] = no_screen; - if (yamlConfig["Display"]) { - if (yamlConfig["Display"]["Panel"].as("") == "ST7789") - settingsMap[displayPanel] = st7789; - else if (yamlConfig["Display"]["Panel"].as("") == "ST7735") - settingsMap[displayPanel] = st7735; - else if (yamlConfig["Display"]["Panel"].as("") == "ST7735S") - settingsMap[displayPanel] = st7735s; - else if (yamlConfig["Display"]["Panel"].as("") == "ST7796") - settingsMap[displayPanel] = st7796; - else if (yamlConfig["Display"]["Panel"].as("") == "ILI9341") - settingsMap[displayPanel] = ili9341; - else if (yamlConfig["Display"]["Panel"].as("") == "ILI9342") - settingsMap[displayPanel] = ili9342; - else if (yamlConfig["Display"]["Panel"].as("") == "ILI9488") - settingsMap[displayPanel] = ili9488; - else if (yamlConfig["Display"]["Panel"].as("") == "HX8357D") - settingsMap[displayPanel] = hx8357d; - else if (yamlConfig["Display"]["Panel"].as("") == "X11") - settingsMap[displayPanel] = x11; - settingsMap[displayHeight] = yamlConfig["Display"]["Height"].as(0); - settingsMap[displayWidth] = yamlConfig["Display"]["Width"].as(0); - settingsMap[displayDC] = yamlConfig["Display"]["DC"].as(-1); - settingsMap[displayCS] = yamlConfig["Display"]["CS"].as(-1); - settingsMap[displayRGBOrder] = yamlConfig["Display"]["RGBOrder"].as(false); - settingsMap[displayBacklight] = yamlConfig["Display"]["Backlight"].as(-1); - settingsMap[displayBacklightInvert] = yamlConfig["Display"]["BacklightInvert"].as(false); - settingsMap[displayBacklightPWMChannel] = yamlConfig["Display"]["BacklightPWMChannel"].as(-1); - settingsMap[displayReset] = yamlConfig["Display"]["Reset"].as(-1); - settingsMap[displayOffsetX] = yamlConfig["Display"]["OffsetX"].as(0); - settingsMap[displayOffsetY] = yamlConfig["Display"]["OffsetY"].as(0); - settingsMap[displayRotate] = yamlConfig["Display"]["Rotate"].as(false); - settingsMap[displayOffsetRotate] = yamlConfig["Display"]["OffsetRotate"].as(1); - settingsMap[displayInvert] = yamlConfig["Display"]["Invert"].as(false); - settingsMap[displayBusFrequency] = yamlConfig["Display"]["BusFrequency"].as(40000000); - if (yamlConfig["Display"]["spidev"]) { - settingsStrings[displayspidev] = "/dev/" + yamlConfig["Display"]["spidev"].as("spidev0.1"); - if (settingsStrings[displayspidev].length() == 14) { - int x = settingsStrings[displayspidev].at(11) - '0'; - int y = settingsStrings[displayspidev].at(13) - '0'; - if (x >= 0 && x < 10 && y >= 0 && y < 10) { - settingsMap[displayspidev] = x + y << 4; - settingsMap[touchscreenspidev] = settingsMap[displayspidev]; - } - } - } - } - settingsMap[touchscreenModule] = no_touchscreen; - if (yamlConfig["Touchscreen"]) { - if (yamlConfig["Touchscreen"]["Module"].as("") == "XPT2046") - settingsMap[touchscreenModule] = xpt2046; - else if (yamlConfig["Touchscreen"]["Module"].as("") == "STMPE610") - settingsMap[touchscreenModule] = stmpe610; - else if (yamlConfig["Touchscreen"]["Module"].as("") == "GT911") - settingsMap[touchscreenModule] = gt911; - else if (yamlConfig["Touchscreen"]["Module"].as("") == "FT5x06") - settingsMap[touchscreenModule] = ft5x06; - settingsMap[touchscreenCS] = yamlConfig["Touchscreen"]["CS"].as(-1); - settingsMap[touchscreenIRQ] = yamlConfig["Touchscreen"]["IRQ"].as(-1); - settingsMap[touchscreenBusFrequency] = yamlConfig["Touchscreen"]["BusFrequency"].as(1000000); - settingsMap[touchscreenRotate] = yamlConfig["Touchscreen"]["Rotate"].as(-1); - settingsMap[touchscreenI2CAddr] = yamlConfig["Touchscreen"]["I2CAddr"].as(-1); - if (yamlConfig["Touchscreen"]["spidev"]) { - settingsStrings[touchscreenspidev] = "/dev/" + yamlConfig["Touchscreen"]["spidev"].as(""); - if (settingsStrings[touchscreenspidev].length() == 14) { - int x = settingsStrings[touchscreenspidev].at(11) - '0'; - int y = settingsStrings[touchscreenspidev].at(13) - '0'; - if (x >= 0 && x < 10 && y >= 0 && y < 10) { - settingsMap[touchscreenspidev] = x + y << 4; - } - } - } - } - if (yamlConfig["Input"]) { - settingsStrings[keyboardDevice] = (yamlConfig["Input"]["KeyboardDevice"]).as(""); - } - - if (yamlConfig["Webserver"]) { - settingsMap[webserverport] = (yamlConfig["Webserver"]["Port"]).as(-1); - settingsStrings[webserverrootpath] = (yamlConfig["Webserver"]["RootPath"]).as(""); - } - - settingsMap[maxnodes] = (yamlConfig["General"]["MaxNodes"]).as(200); - settingsMap[maxtophone] = (yamlConfig["General"]["MaxMessageQueue"]).as(100); - - } catch (YAML::Exception &e) { - std::cout << "*** Exception " << e.what() << std::endl; - exit(EXIT_FAILURE); - } + gpioChipName += std::to_string(settingsMap[gpiochip]); for (configNames i : GPIO_lines) { if (settingsMap.count(i) && settingsMap[i] > max_GPIO) @@ -402,4 +243,178 @@ int initGPIOPin(int pinNum, const std::string gpioChipName) #else return ERRNO_OK; #endif +} + +bool loadConfig(const char *configPath) +{ + YAML::Node yamlConfig; + try { + yamlConfig = YAML::LoadFile(configPath); + if (yamlConfig["Logging"]) { + if (yamlConfig["Logging"]["LogLevel"].as("info") == "trace") { + settingsMap[logoutputlevel] = level_trace; + } else if (yamlConfig["Logging"]["LogLevel"].as("info") == "debug") { + settingsMap[logoutputlevel] = level_debug; + } else if (yamlConfig["Logging"]["LogLevel"].as("info") == "info") { + settingsMap[logoutputlevel] = level_info; + } else if (yamlConfig["Logging"]["LogLevel"].as("info") == "warn") { + settingsMap[logoutputlevel] = level_warn; + } else if (yamlConfig["Logging"]["LogLevel"].as("info") == "error") { + settingsMap[logoutputlevel] = level_error; + } + settingsStrings[traceFilename] = yamlConfig["Logging"]["TraceFile"].as(""); + if (yamlConfig["Logging"]["AsciiLogs"]) { + // Default is !isatty(1) but can be set explicitly in config.yaml + settingsMap[ascii_logs] = yamlConfig["Logging"]["AsciiLogs"].as(); + } + } + if (yamlConfig["Lora"]) { + settingsMap[use_sx1262] = false; + settingsMap[use_rf95] = false; + settingsMap[use_sx1280] = false; + settingsMap[use_sx1268] = false; + + if (yamlConfig["Lora"]["Module"] && yamlConfig["Lora"]["Module"].as("") == "sx1262") { + settingsMap[use_sx1262] = true; + } else if (yamlConfig["Lora"]["Module"] && yamlConfig["Lora"]["Module"].as("") == "RF95") { + settingsMap[use_rf95] = true; + } else if (yamlConfig["Lora"]["Module"] && yamlConfig["Lora"]["Module"].as("") == "sx1280") { + settingsMap[use_sx1280] = true; + } else if (yamlConfig["Lora"]["Module"] && yamlConfig["Lora"]["Module"].as("") == "sx1268") { + settingsMap[use_sx1268] = true; + } + settingsMap[dio2_as_rf_switch] = yamlConfig["Lora"]["DIO2_AS_RF_SWITCH"].as(false); + settingsMap[dio3_tcxo_voltage] = yamlConfig["Lora"]["DIO3_TCXO_VOLTAGE"].as(false); + settingsMap[cs] = yamlConfig["Lora"]["CS"].as(RADIOLIB_NC); + settingsMap[irq] = yamlConfig["Lora"]["IRQ"].as(RADIOLIB_NC); + settingsMap[busy] = yamlConfig["Lora"]["Busy"].as(RADIOLIB_NC); + settingsMap[reset] = yamlConfig["Lora"]["Reset"].as(RADIOLIB_NC); + settingsMap[txen] = yamlConfig["Lora"]["TXen"].as(RADIOLIB_NC); + settingsMap[rxen] = yamlConfig["Lora"]["RXen"].as(RADIOLIB_NC); + settingsMap[sx126x_ant_sw] = yamlConfig["Lora"]["SX126X_ANT_SW"].as(RADIOLIB_NC); + settingsMap[gpiochip] = yamlConfig["Lora"]["gpiochip"].as(0); + settingsMap[ch341Quirk] = yamlConfig["Lora"]["ch341_quirk"].as(false); + settingsMap[spiSpeed] = yamlConfig["Lora"]["spiSpeed"].as(2000000); + + settingsStrings[spidev] = "/dev/" + yamlConfig["Lora"]["spidev"].as("spidev0.0"); + if (settingsStrings[spidev].length() == 14) { + int x = settingsStrings[spidev].at(11) - '0'; + int y = settingsStrings[spidev].at(13) - '0'; + if (x >= 0 && x < 10 && y >= 0 && y < 10) { + settingsMap[spidev] = x + y << 4; + settingsMap[displayspidev] = settingsMap[spidev]; + settingsMap[touchscreenspidev] = settingsMap[spidev]; + } + } + } + if (yamlConfig["GPIO"]) { + settingsMap[user] = yamlConfig["GPIO"]["User"].as(RADIOLIB_NC); + } + if (yamlConfig["GPS"]) { + std::string serialPath = yamlConfig["GPS"]["SerialPath"].as(""); + if (serialPath != "") { + Serial1.setPath(serialPath); + settingsMap[has_gps] = 1; + } + } + if (yamlConfig["I2C"]) { + settingsStrings[i2cdev] = yamlConfig["I2C"]["I2CDevice"].as(""); + } + if (yamlConfig["Display"]) { + if (yamlConfig["Display"]["Panel"].as("") == "ST7789") + settingsMap[displayPanel] = st7789; + else if (yamlConfig["Display"]["Panel"].as("") == "ST7735") + settingsMap[displayPanel] = st7735; + else if (yamlConfig["Display"]["Panel"].as("") == "ST7735S") + settingsMap[displayPanel] = st7735s; + else if (yamlConfig["Display"]["Panel"].as("") == "ST7796") + settingsMap[displayPanel] = st7796; + else if (yamlConfig["Display"]["Panel"].as("") == "ILI9341") + settingsMap[displayPanel] = ili9341; + else if (yamlConfig["Display"]["Panel"].as("") == "ILI9342") + settingsMap[displayPanel] = ili9342; + else if (yamlConfig["Display"]["Panel"].as("") == "ILI9488") + settingsMap[displayPanel] = ili9488; + else if (yamlConfig["Display"]["Panel"].as("") == "HX8357D") + settingsMap[displayPanel] = hx8357d; + else if (yamlConfig["Display"]["Panel"].as("") == "X11") + settingsMap[displayPanel] = x11; + settingsMap[displayHeight] = yamlConfig["Display"]["Height"].as(0); + settingsMap[displayWidth] = yamlConfig["Display"]["Width"].as(0); + settingsMap[displayDC] = yamlConfig["Display"]["DC"].as(-1); + settingsMap[displayCS] = yamlConfig["Display"]["CS"].as(-1); + settingsMap[displayRGBOrder] = yamlConfig["Display"]["RGBOrder"].as(false); + settingsMap[displayBacklight] = yamlConfig["Display"]["Backlight"].as(-1); + settingsMap[displayBacklightInvert] = yamlConfig["Display"]["BacklightInvert"].as(false); + settingsMap[displayBacklightPWMChannel] = yamlConfig["Display"]["BacklightPWMChannel"].as(-1); + settingsMap[displayReset] = yamlConfig["Display"]["Reset"].as(-1); + settingsMap[displayOffsetX] = yamlConfig["Display"]["OffsetX"].as(0); + settingsMap[displayOffsetY] = yamlConfig["Display"]["OffsetY"].as(0); + settingsMap[displayRotate] = yamlConfig["Display"]["Rotate"].as(false); + settingsMap[displayOffsetRotate] = yamlConfig["Display"]["OffsetRotate"].as(1); + settingsMap[displayInvert] = yamlConfig["Display"]["Invert"].as(false); + settingsMap[displayBusFrequency] = yamlConfig["Display"]["BusFrequency"].as(40000000); + if (yamlConfig["Display"]["spidev"]) { + settingsStrings[displayspidev] = "/dev/" + yamlConfig["Display"]["spidev"].as("spidev0.1"); + if (settingsStrings[displayspidev].length() == 14) { + int x = settingsStrings[displayspidev].at(11) - '0'; + int y = settingsStrings[displayspidev].at(13) - '0'; + if (x >= 0 && x < 10 && y >= 0 && y < 10) { + settingsMap[displayspidev] = x + y << 4; + settingsMap[touchscreenspidev] = settingsMap[displayspidev]; + } + } + } + } + if (yamlConfig["Touchscreen"]) { + if (yamlConfig["Touchscreen"]["Module"].as("") == "XPT2046") + settingsMap[touchscreenModule] = xpt2046; + else if (yamlConfig["Touchscreen"]["Module"].as("") == "STMPE610") + settingsMap[touchscreenModule] = stmpe610; + else if (yamlConfig["Touchscreen"]["Module"].as("") == "GT911") + settingsMap[touchscreenModule] = gt911; + else if (yamlConfig["Touchscreen"]["Module"].as("") == "FT5x06") + settingsMap[touchscreenModule] = ft5x06; + settingsMap[touchscreenCS] = yamlConfig["Touchscreen"]["CS"].as(-1); + settingsMap[touchscreenIRQ] = yamlConfig["Touchscreen"]["IRQ"].as(-1); + settingsMap[touchscreenBusFrequency] = yamlConfig["Touchscreen"]["BusFrequency"].as(1000000); + settingsMap[touchscreenRotate] = yamlConfig["Touchscreen"]["Rotate"].as(-1); + settingsMap[touchscreenI2CAddr] = yamlConfig["Touchscreen"]["I2CAddr"].as(-1); + if (yamlConfig["Touchscreen"]["spidev"]) { + settingsStrings[touchscreenspidev] = "/dev/" + yamlConfig["Touchscreen"]["spidev"].as(""); + if (settingsStrings[touchscreenspidev].length() == 14) { + int x = settingsStrings[touchscreenspidev].at(11) - '0'; + int y = settingsStrings[touchscreenspidev].at(13) - '0'; + if (x >= 0 && x < 10 && y >= 0 && y < 10) { + settingsMap[touchscreenspidev] = x + y << 4; + } + } + } + } + if (yamlConfig["Input"]) { + settingsStrings[keyboardDevice] = (yamlConfig["Input"]["KeyboardDevice"]).as(""); + } + + if (yamlConfig["Webserver"]) { + settingsMap[webserverport] = (yamlConfig["Webserver"]["Port"]).as(-1); + settingsStrings[webserverrootpath] = (yamlConfig["Webserver"]["RootPath"]).as(""); + } + + if (yamlConfig["General"]) { + settingsMap[maxnodes] = (yamlConfig["General"]["MaxNodes"]).as(200); + settingsMap[maxtophone] = (yamlConfig["General"]["MaxMessageQueue"]).as(100); + settingsStrings[config_directory] = (yamlConfig["General"]["ConfigDirectory"]).as(""); + } + + } catch (YAML::Exception &e) { + std::cout << "*** Exception " << e.what() << std::endl; + return false; + } + return true; +} + +// https://stackoverflow.com/questions/874134/find-out-if-string-ends-with-another-string-in-c +static bool ends_with(std::string_view str, std::string_view suffix) +{ + return str.size() >= suffix.size() && str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0; } \ No newline at end of file diff --git a/src/platform/portduino/PortduinoGlue.h b/src/platform/portduino/PortduinoGlue.h index 8ee96717e..95d82c1a2 100644 --- a/src/platform/portduino/PortduinoGlue.h +++ b/src/platform/portduino/PortduinoGlue.h @@ -55,7 +55,8 @@ enum configNames { webserverrootpath, maxtophone, maxnodes, - ascii_logs + ascii_logs, + config_directory }; enum { no_screen, x11, st7789, st7735, st7735s, st7796, ili9341, ili9342, ili9488, hx8357d }; enum { no_touchscreen, xpt2046, stmpe610, gt911, ft5x06 }; @@ -64,4 +65,6 @@ enum { level_error, level_warn, level_info, level_debug, level_trace }; extern std::map settingsMap; extern std::map settingsStrings; extern std::ofstream traceFile; -int initGPIOPin(int pinNum, std::string gpioChipname); \ No newline at end of file +int initGPIOPin(int pinNum, std::string gpioChipname); +bool loadConfig(const char *configPath); +static bool ends_with(std::string_view str, std::string_view suffix); \ No newline at end of file