check valid pins for board_profile and analog

This commit is contained in:
MichaelDvP
2024-02-08 18:52:27 +01:00
parent 119b2b9514
commit 2b88fec2ee
5 changed files with 111 additions and 65 deletions

View File

@@ -22,6 +22,26 @@ export const GPIO_VALIDATOR = {
} }
}; };
export const GPIO_VALIDATORR = {
validator(rule: InternalRuleItem, value: number, callback: (error?: string) => void) {
if (
value &&
(value === 1 ||
(value >= 6 && value <= 11) ||
(value >= 16 && value <= 17) ||
value === 20 ||
value === 24 ||
(value >= 28 && value <= 31) ||
value > 40 ||
value < 0)
) {
callback('Must be an valid GPIO port');
} else {
callback();
}
}
};
export const GPIO_VALIDATORC3 = { export const GPIO_VALIDATORC3 = {
validator(rule: InternalRuleItem, value: number, callback: (error?: string) => void) { validator(rule: InternalRuleItem, value: number, callback: (error?: string) => void) {
if (value && ((value >= 11 && value <= 19) || value > 21 || value < 0)) { if (value && ((value >= 11 && value <= 19) || value > 21 || value < 0)) {
@@ -69,6 +89,14 @@ export const createSettingsValidator = (settings: Settings) =>
tx_gpio: [{ required: true, message: 'Tx GPIO is required' }, GPIO_VALIDATOR], tx_gpio: [{ required: true, message: 'Tx GPIO is required' }, GPIO_VALIDATOR],
rx_gpio: [{ required: true, message: 'Rx GPIO is required' }, GPIO_VALIDATOR] rx_gpio: [{ required: true, message: 'Rx GPIO is required' }, GPIO_VALIDATOR]
}), }),
...(settings.board_profile === 'CUSTOM' &&
settings.platform === 'ESP32PSRAM' && {
led_gpio: [{ required: true, message: 'LED GPIO is required' }, GPIO_VALIDATORR],
dallas_gpio: [{ required: true, message: 'GPIO is required' }, GPIO_VALIDATORR],
pbutton_gpio: [{ required: true, message: 'Button GPIO is required' }, GPIO_VALIDATORR],
tx_gpio: [{ required: true, message: 'Tx GPIO is required' }, GPIO_VALIDATORR],
rx_gpio: [{ required: true, message: 'Rx GPIO is required' }, GPIO_VALIDATORR]
}),
...(settings.board_profile === 'CUSTOM' && ...(settings.board_profile === 'CUSTOM' &&
settings.platform === 'ESP32-C3' && { settings.platform === 'ESP32-C3' && {
led_gpio: [{ required: true, message: 'LED GPIO is required' }, GPIO_VALIDATORC3], led_gpio: [{ required: true, message: 'LED GPIO is required' }, GPIO_VALIDATORC3],
@@ -193,7 +221,15 @@ export const analogSensorItemValidation = (sensors: AnalogSensor[], creating: bo
n: [{ required: true, message: 'Name is required' }], n: [{ required: true, message: 'Name is required' }],
g: [ g: [
{ required: true, message: 'GPIO is required' }, { required: true, message: 'GPIO is required' },
platform === 'ESP32-S3' ? GPIO_VALIDATORS3 : platform === 'ESP32-C3' ? GPIO_VALIDATORC3 : GPIO_VALIDATOR, platform === 'ESP32-S3'
? GPIO_VALIDATORS3
: platform === 'ESP32-S2'
? GPIO_VALIDATORS2
: platform === 'ESP32-C3'
? GPIO_VALIDATORC3
: platform === 'ESP32R'
? GPIO_VALIDATORR
: GPIO_VALIDATOR,
...(creating ? [isGPIOUniqueValidator(sensors)] : []) ...(creating ? [isGPIOUniqueValidator(sensors)] : [])
] ]
}); });

View File

@@ -69,7 +69,7 @@ void AnalogSensor::reload() {
// update existing sensors // update existing sensors
bool found = false; bool found = false;
for (const auto & sensor : settings.analogCustomizations) { //search customlist for (const auto & sensor : settings.analogCustomizations) { //search customlist
if (sensor_.gpio() == sensor.gpio) { if (System::is_valid_gpio(sensor.gpio) && sensor_.gpio() == sensor.gpio) {
// for output sensors set value to new start-value // for output sensors set value to new start-value
if ((sensor.type == AnalogType::COUNTER || sensor.type >= AnalogType::DIGITAL_OUT) if ((sensor.type == AnalogType::COUNTER || sensor.type >= AnalogType::DIGITAL_OUT)
&& (sensor_.type() != sensor.type || sensor_.offset() != sensor.offset || sensor_.factor() != sensor.factor)) { && (sensor_.type() != sensor.type || sensor_.offset() != sensor.offset || sensor_.factor() != sensor.factor)) {
@@ -94,11 +94,14 @@ void AnalogSensor::reload() {
for (const auto & sensor : settings.analogCustomizations) { for (const auto & sensor : settings.analogCustomizations) {
bool found = false; bool found = false;
for (const auto & sensor_ : sensors_) { for (const auto & sensor_ : sensors_) {
if (sensor_.gpio() == sensor.gpio) { if (System::is_valid_gpio(sensor.gpio) && sensor_.gpio() == sensor.gpio) {
found = true; found = true;
} }
} }
if (!found) { if (!found) {
if (!System::is_valid_gpio(sensor.gpio)) {
continue;
}
sensors_.emplace_back(sensor.gpio, sensor.name, sensor.offset, sensor.factor, sensor.uom, sensor.type); sensors_.emplace_back(sensor.gpio, sensor.name, sensor.offset, sensor.factor, sensor.uom, sensor.type);
sensors_.back().ha_registered = false; // this will trigger recreate of the HA config sensors_.back().ha_registered = false; // this will trigger recreate of the HA config
if (sensor.type == AnalogType::COUNTER || sensor.type >= AnalogType::DIGITAL_OUT) { if (sensor.type == AnalogType::COUNTER || sensor.type >= AnalogType::DIGITAL_OUT) {
@@ -790,8 +793,6 @@ bool AnalogSensor::command_setvalue(const char * value, const int8_t gpio) {
sensor.set_value(v); sensor.set_value(v);
pinMode(sensor.gpio(), OUTPUT); pinMode(sensor.gpio(), OUTPUT);
dacWrite(sensor.gpio(), sensor.offset()); dacWrite(sensor.gpio(), sensor.offset());
publish_sensor(sensor);
return true;
} else } else
#endif #endif
if (v == 0 || v == 1) { if (v == 0 || v == 1) {

View File

@@ -420,9 +420,10 @@ void System::wifi_tweak() {
// we allow 0 as it has a special function on the NodeMCU apparently // we allow 0 as it has a special function on the NodeMCU apparently
// See https://diyprojects.io/esp32-how-to-use-gpio-digital-io-arduino-code/#.YFpVEq9KhjG // See https://diyprojects.io/esp32-how-to-use-gpio-digital-io-arduino-code/#.YFpVEq9KhjG
// and https://nodemcu.readthedocs.io/en/dev-esp32/modules/gpio/ // and https://nodemcu.readthedocs.io/en/dev-esp32/modules/gpio/
bool System::is_valid_gpio(uint8_t pin) { bool System::is_valid_gpio(uint8_t pin, bool has_psram) {
#if CONFIG_IDF_TARGET_ESP32 || EMSESP_STANDALONE #if CONFIG_IDF_TARGET_ESP32 || EMSESP_STANDALONE
if ((pin == 1) || (pin >= 6 && pin <= 11) || (pin == 20) || (pin == 24) || (pin >= 28 && pin <= 31) || (pin > 40)) { if ((pin == 1) || (pin >= 6 && pin <= 11) || (pin == 20) || (pin == 24) || (pin >= 28 && pin <= 31) || (pin > 40)
|| ((EMSESP::system_.PSram() > 0 || has_psram) && pin >= 16 && pin <= 17)) {
#elif CONFIG_IDF_TARGET_ESP32S2 #elif CONFIG_IDF_TARGET_ESP32S2
if ((pin >= 19 && pin <= 20) || (pin >= 22 && pin <= 32) || (pin > 40)) { if ((pin >= 19 && pin <= 20) || (pin >= 22 && pin <= 32) || (pin > 40)) {
#elif CONFIG_IDF_TARGET_ESP32C3 #elif CONFIG_IDF_TARGET_ESP32C3

View File

@@ -105,7 +105,7 @@ class System {
static void extractSettings(const char * filename, const char * section, JsonObject output); static void extractSettings(const char * filename, const char * section, JsonObject output);
static bool saveSettings(const char * filename, const char * section, JsonObject input); static bool saveSettings(const char * filename, const char * section, JsonObject input);
static bool is_valid_gpio(uint8_t pin); static bool is_valid_gpio(uint8_t pin, bool has_psram = false);
static bool load_board_profile(std::vector<int8_t> & data, const std::string & board_profile); static bool load_board_profile(std::vector<int8_t> & data, const std::string & board_profile);
static void restart_requested(bool restart_requested) { static void restart_requested(bool restart_requested) {

View File

@@ -76,7 +76,8 @@ void WebSettings::read(WebSettings & settings, JsonObject root) {
root["eth_power"] = settings.eth_power; root["eth_power"] = settings.eth_power;
root["eth_phy_addr"] = settings.eth_phy_addr; root["eth_phy_addr"] = settings.eth_phy_addr;
root["eth_clock_mode"] = settings.eth_clock_mode; root["eth_clock_mode"] = settings.eth_clock_mode;
root["platform"] = EMSESP_PLATFORM; String platform = EMSESP_PLATFORM;
root["platform"] = (platform == "ESP32" && EMSESP::system_.PSram()) ? "ESP32R" : platform;
} }
// call on initialization and also when settings are updated via web or console // call on initialization and also when settings are updated via web or console
@@ -88,27 +89,39 @@ StateUpdateResult WebSettings::update(JsonObject root, WebSettings & settings) {
// load default GPIO configuration based on board profile // load default GPIO configuration based on board profile
std::vector<int8_t> data; // // led, dallas, rx, tx, button, phy_type, eth_power, eth_phy_addr, eth_clock_mode std::vector<int8_t> data; // // led, dallas, rx, tx, button, phy_type, eth_power, eth_phy_addr, eth_clock_mode
settings.board_profile = root["board_profile"] | EMSESP_DEFAULT_BOARD_PROFILE; settings.board_profile = root["board_profile"] | EMSESP_DEFAULT_BOARD_PROFILE;
// for -D compile setting store it in NVS
if ((String)EMSESP_DEFAULT_BOARD_PROFILE != "default" && EMSESP::nvs_.getString("boot") == "") { if ((String)EMSESP_DEFAULT_BOARD_PROFILE != "default" && EMSESP::nvs_.getString("boot") == "") {
EMSESP::nvs_.putString("boot", (const char *)EMSESP_DEFAULT_BOARD_PROFILE); EMSESP::nvs_.putString("boot", (const char *)EMSESP_DEFAULT_BOARD_PROFILE);
} }
/*
#if CONFIG_IDF_TARGET_ESP32C3 bool psram = ESP.getPsramSize() > 0; // System::PSram() is initializd later
settings.board_profile = root["board_profile"] | "C3MINI"; if (System::load_board_profile(data, settings.board_profile.c_str())) {
#elif CONFIG_IDF_TARGET_ESP32S2 if (settings.board_profile == "CUSTOM") { //read pins, fallback to S32
settings.board_profile = root["board_profile"] | "S2MINI"; data[0] = root["led_gpio"] | 2;
#elif CONFIG_IDF_TARGET_ESP32S3 data[1] = root["dallas_gpio"] | 18;
// settings.board_profile = root["board_profile"] | "S3MINI"; data[2] = root["rx_gpio"] | 23;
settings.board_profile = root["board_profile"] | "S32S3"; // BBQKees Gateway S3 data[3] = root["tx_gpio"] | 5;
#elif CONFIG_IDF_TARGET_ESP32 data[4] = root["pbutton_gpio"] | 0;
settings.board_profile = root["board_profile"] | EMSESP_DEFAULT_BOARD_PROFILE; data[5] = root["phy_type"] | PHY_type::PHY_TYPE_NONE;
#endif data[6] = root["eth_power"] | 0;
*/ data[7] = root["eth_phy_addr"] | 0;
data[8] = root["eth_clock_mode"] | 0;
}
// check valid pins in this board profile
if (!System::is_valid_gpio(data[0], psram) || !System::is_valid_gpio(data[1], psram) || !System::is_valid_gpio(data[2], psram)
|| !System::is_valid_gpio(data[3], psram) || !System::is_valid_gpio(data[4], psram) || !System::is_valid_gpio(data[6], psram)) {
settings.board_profile = ""; // reset to factory default
}
}
// load the profile
if (!System::load_board_profile(data, settings.board_profile.c_str())) { if (!System::load_board_profile(data, settings.board_profile.c_str())) {
// unknown, check for NVS or scan for ethernet, use default E32/E32V2/S32 // unknown, check for NVS or scan for ethernet, use default E32/E32V2/S32
settings.board_profile = EMSESP::nvs_.getString("boot"); settings.board_profile = EMSESP::nvs_.getString("boot");
if (!System::load_board_profile(data, settings.board_profile.c_str())) { if (!System::load_board_profile(data, settings.board_profile.c_str())) {
#if CONFIG_IDF_TARGET_ESP32 && !defined(EMSESP_STANDALONE) #if defined(EMSESP_STANDALONE)
if (settings.board_profile == "") { // empty: new test settings.board_profile = "S32";
#elif CONFIG_IDF_TARGET_ESP32
if (settings.board_profile == "" && !psram) { // empty: new test for E32
#if ESP_ARDUINO_VERSION_MAJOR < 3 #if ESP_ARDUINO_VERSION_MAJOR < 3
if (ETH.begin(1, 16, 23, 18, ETH_PHY_LAN8720, ETH_CLOCK_GPIO0_IN)) { if (ETH.begin(1, 16, 23, 18, ETH_PHY_LAN8720, ETH_CLOCK_GPIO0_IN)) {
#else #else
@@ -118,7 +131,7 @@ StateUpdateResult WebSettings::update(JsonObject root, WebSettings & settings) {
} else { } else {
EMSESP::nvs_.putString("boot", "Test"); EMSESP::nvs_.putString("boot", "Test");
} }
} else if (settings.board_profile == "Test") { } else if (settings.board_profile == "Test" || psram) { // test E32V2
#if ESP_ARDUINO_VERSION_MAJOR < 3 #if ESP_ARDUINO_VERSION_MAJOR < 3
if (ETH.begin(0, 15, 23, 18, ETH_PHY_LAN8720, ETH_CLOCK_GPIO0_OUT)) { if (ETH.begin(0, 15, 23, 18, ETH_PHY_LAN8720, ETH_CLOCK_GPIO0_OUT)) {
#else #else
@@ -132,39 +145,58 @@ StateUpdateResult WebSettings::update(JsonObject root, WebSettings & settings) {
EMSESP::nvs_.putString("boot", "S32"); EMSESP::nvs_.putString("boot", "S32");
} }
ESP.restart(); ESP.restart();
#elif CONFIG_IDF_TARGET_ESP32C3
settings.board_profile = "C3MINI";
#elif CONFIG_IDF_TARGET_ESP32S2
settings.board_profile = "S2MINI";
#elif CONFIG_IDF_TARGET_ESP32S3
settings.board_profile = "S32S3"; // BBQKees Gateway S3
#else #else
settings.board_profile = "S32"; settings.board_profile = "S32";
System::load_board_profile(data, settings.board_profile.c_str());
#endif #endif
System::load_board_profile(data, settings.board_profile.c_str());
} }
EMSESP::logger().info("No board profile found. Re-setting to %s", settings.board_profile.c_str()); EMSESP::logger().info("No board profile found. Re-setting to %s", settings.board_profile.c_str());
} else { } else {
EMSESP::logger().info("Loading board profile %s", settings.board_profile.c_str()); EMSESP::logger().info("Loading board profile %s", settings.board_profile.c_str());
} }
uint8_t default_led_gpio = data[0];
uint8_t default_dallas_gpio = data[1];
uint8_t default_rx_gpio = data[2];
uint8_t default_tx_gpio = data[3];
uint8_t default_pbutton_gpio = data[4];
uint8_t default_phy_type = data[5];
uint8_t default_eth_power = data[6];
uint8_t default_eth_phy_addr = data[7];
uint8_t default_eth_clock_mode = data[8];
int prev; int prev;
reset_flags(); reset_flags();
// pins
prev = settings.led_gpio;
settings.led_gpio = data[0];
check_flag(prev, settings.led_gpio, ChangeFlags::LED);
prev = settings.dallas_gpio;
settings.dallas_gpio = data[1];
check_flag(prev, settings.dallas_gpio, ChangeFlags::SENSOR);
prev = settings.rx_gpio;
settings.rx_gpio = data[2];
check_flag(prev, settings.rx_gpio, ChangeFlags::RESTART);
prev = settings.tx_gpio;
settings.tx_gpio = data[3];
check_flag(prev, settings.tx_gpio, ChangeFlags::RESTART);
prev = settings.pbutton_gpio;
settings.pbutton_gpio = data[4];
check_flag(prev, settings.pbutton_gpio, ChangeFlags::BUTTON);
prev = settings.phy_type;
settings.phy_type = data[5];
check_flag(prev, settings.phy_type, ChangeFlags::RESTART);
prev = settings.eth_power;
settings.eth_power = data[6];
check_flag(prev, settings.eth_power, ChangeFlags::RESTART);
prev = settings.eth_phy_addr;
settings.eth_phy_addr = data[7];
check_flag(prev, settings.eth_phy_addr, ChangeFlags::RESTART);
prev = settings.eth_clock_mode;
settings.eth_clock_mode = data[8];
check_flag(prev, settings.eth_clock_mode, ChangeFlags::RESTART);
// tx_mode, rx and tx pins // tx_mode, rx and tx pins
prev = settings.tx_mode; prev = settings.tx_mode;
settings.tx_mode = root["tx_mode"] | EMSESP_DEFAULT_TX_MODE; settings.tx_mode = root["tx_mode"] | EMSESP_DEFAULT_TX_MODE;
check_flag(prev, settings.tx_mode, ChangeFlags::UART); check_flag(prev, settings.tx_mode, ChangeFlags::UART);
prev = settings.rx_gpio;
settings.rx_gpio = root["rx_gpio"] | default_rx_gpio;
check_flag(prev, settings.rx_gpio, ChangeFlags::RESTART);
prev = settings.tx_gpio;
settings.tx_gpio = root["tx_gpio"] | default_tx_gpio;
check_flag(prev, settings.tx_gpio, ChangeFlags::RESTART);
// syslog // syslog
prev = settings.syslog_enabled; prev = settings.syslog_enabled;
@@ -188,15 +220,7 @@ StateUpdateResult WebSettings::update(JsonObject root, WebSettings & settings) {
} }
#endif #endif
// button
prev = settings.pbutton_gpio;
settings.pbutton_gpio = root["pbutton_gpio"] | default_pbutton_gpio;
check_flag(prev, settings.pbutton_gpio, ChangeFlags::BUTTON);
// temperaturesensor // temperaturesensor
prev = settings.dallas_gpio;
settings.dallas_gpio = root["dallas_gpio"] | default_dallas_gpio;
check_flag(prev, settings.dallas_gpio, ChangeFlags::SENSOR);
prev = settings.dallas_parasite; prev = settings.dallas_parasite;
settings.dallas_parasite = root["dallas_parasite"] | EMSESP_DEFAULT_DALLAS_PARASITE; settings.dallas_parasite = root["dallas_parasite"] | EMSESP_DEFAULT_DALLAS_PARASITE;
check_flag(prev, settings.dallas_parasite, ChangeFlags::SENSOR); check_flag(prev, settings.dallas_parasite, ChangeFlags::SENSOR);
@@ -216,9 +240,6 @@ StateUpdateResult WebSettings::update(JsonObject root, WebSettings & settings) {
check_flag(prev, settings.shower_alert_coldshot, ChangeFlags::SHOWER); check_flag(prev, settings.shower_alert_coldshot, ChangeFlags::SHOWER);
// led // led
prev = settings.led_gpio;
settings.led_gpio = root["led_gpio"] | default_led_gpio;
check_flag(prev, settings.led_gpio, ChangeFlags::LED);
prev = settings.hide_led; prev = settings.hide_led;
settings.hide_led = root["hide_led"] | EMSESP_DEFAULT_HIDE_LED; settings.hide_led = root["hide_led"] | EMSESP_DEFAULT_HIDE_LED;
check_flag(prev, settings.hide_led, ChangeFlags::LED); check_flag(prev, settings.hide_led, ChangeFlags::LED);
@@ -228,19 +249,6 @@ StateUpdateResult WebSettings::update(JsonObject root, WebSettings & settings) {
settings.analog_enabled = root["analog_enabled"] | EMSESP_DEFAULT_ANALOG_ENABLED; settings.analog_enabled = root["analog_enabled"] | EMSESP_DEFAULT_ANALOG_ENABLED;
check_flag(prev, settings.analog_enabled, ChangeFlags::ADC); check_flag(prev, settings.analog_enabled, ChangeFlags::ADC);
// ethernet
prev = settings.phy_type;
settings.phy_type = root["phy_type"] | default_phy_type;
check_flag(prev, settings.phy_type, ChangeFlags::RESTART);
prev = settings.eth_power;
settings.eth_power = root["eth_power"] | default_eth_power;
check_flag(prev, settings.eth_power, ChangeFlags::RESTART);
prev = settings.eth_phy_addr;
settings.eth_phy_addr = root["eth_phy_addr"] | default_eth_phy_addr;
check_flag(prev, settings.eth_phy_addr, ChangeFlags::RESTART);
prev = settings.eth_clock_mode;
settings.eth_clock_mode = root["eth_clock_mode"] | default_eth_clock_mode;
check_flag(prev, settings.eth_clock_mode, ChangeFlags::RESTART);
// //
// these need system restarts first before settings are activated... // these need system restarts first before settings are activated...