mirror of
https://github.com/dalathegreat/Battery-Emulator.git
synced 2025-10-03 01:39:30 +02:00
Compare commits
19 commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
f3a6157080 | ||
![]() |
867512eecd | ||
![]() |
f9109d0348 | ||
![]() |
9943406836 | ||
![]() |
18ee9d6c27 | ||
![]() |
31ea1f0928 | ||
![]() |
dad97b36e1 | ||
![]() |
19a1634f4e | ||
![]() |
aa375dc36a | ||
![]() |
a91f8ab4d4 | ||
![]() |
7fbc9ffcc6 | ||
![]() |
579e0e0bcc | ||
![]() |
b26c451eaf | ||
![]() |
ee9e78e80b | ||
![]() |
706b4a7cea | ||
![]() |
f5ba607fa6 | ||
![]() |
04d9a36292 | ||
![]() |
c6b7ff82c0 | ||
![]() |
95ee6ff9ae |
7 changed files with 99 additions and 46 deletions
|
@ -34,7 +34,7 @@
|
|||
#endif
|
||||
|
||||
// The current software version, shown on webserver
|
||||
const char* version_number = "9.1.1";
|
||||
const char* version_number = "9.2.dev";
|
||||
|
||||
// Interval timers
|
||||
volatile unsigned long currentMillis = 0;
|
||||
|
|
|
@ -483,11 +483,24 @@ void TeslaBattery::
|
|||
} else {
|
||||
clear_event(EVENT_BATTERY_FUSE);
|
||||
}
|
||||
// Raise any Tesla BMS events in BE
|
||||
// Events: Informational
|
||||
if (BMS_a145_SW_SOC_Change) { // BMS has newly recalibrated pack SOC
|
||||
set_event_latched(EVENT_BATTERY_SOC_RECALIBRATION, 0); // Latcched as BMS_a145 can be active for a while
|
||||
} else if (!BMS_a145_SW_SOC_Change) {
|
||||
clear_event(EVENT_BATTERY_SOC_RECALIBRATION);
|
||||
}
|
||||
// Events: Warning
|
||||
if (BMS_contactorState == 5) { // BMS has detected welded contactor(s)
|
||||
set_event_latched(EVENT_CONTACTOR_WELDED, 0);
|
||||
} else if (BMS_contactorState != 5) {
|
||||
clear_event(EVENT_CONTACTOR_WELDED);
|
||||
}
|
||||
|
||||
if (user_selected_tesla_GTW_chassisType > 1) { //{{0, "Model S"}, {1, "Model X"}, {2, "Model 3"}, {3, "Model Y"}};
|
||||
// Autodetect algoritm for chemistry on 3/Y packs.
|
||||
// Autodetect algorithm for chemistry on 3/Y packs.
|
||||
// NCM/A batteries have 96s, LFP has 102-108s
|
||||
// Drawback with this check is that it takes 3-5minutes before all cells have been counted!
|
||||
// Drawback with this check is that it takes 3-5 minutes before all cells have been counted!
|
||||
if (datalayer.battery.info.number_of_cells > 101) {
|
||||
datalayer.battery.info.chemistry = battery_chemistry_enum::LFP;
|
||||
}
|
||||
|
@ -528,23 +541,28 @@ void TeslaBattery::
|
|||
//Start the BMS ECU reset statemachine, only if contactors are OPEN and BMS ECU allows it
|
||||
stateMachineBMSReset = 0;
|
||||
datalayer.battery.settings.user_requests_tesla_bms_reset = false;
|
||||
logging.println("BMS reset requested");
|
||||
logging.println("INFO: BMS reset requested");
|
||||
} else {
|
||||
logging.println("ERROR: BMS reset failed due to contactors not being open, or BMS ECU not allowing it");
|
||||
stateMachineBMSReset = 0xFF;
|
||||
datalayer.battery.settings.user_requests_tesla_bms_reset = false;
|
||||
set_event(EVENT_BMS_RESET_REQ_FAIL, 0);
|
||||
clear_event(EVENT_BMS_RESET_REQ_FAIL);
|
||||
}
|
||||
}
|
||||
if (datalayer.battery.settings.user_requests_tesla_soc_reset) {
|
||||
if (datalayer.battery.status.real_soc < 1500 || datalayer.battery.status.real_soc > 9000) {
|
||||
//Start the SOC reset statemachine, only if SOC < 15% or > 90%
|
||||
if ((datalayer.battery.status.real_soc < 1500 || datalayer.battery.status.real_soc > 9000) &&
|
||||
battery_contactor == 1) {
|
||||
//Start the SOC reset statemachine, only if SOC less than 15% or greater than 90%, and contactors open
|
||||
stateMachineSOCReset = 0;
|
||||
datalayer.battery.settings.user_requests_tesla_soc_reset = false;
|
||||
logging.println("SOC reset requested");
|
||||
logging.println("INFO: SOC reset requested");
|
||||
} else {
|
||||
logging.println("ERROR: SOC reset failed due to SOC not being less than 15 or greater than 90");
|
||||
logging.println("ERROR: SOC reset failed, SOC not < 15 or > 90, or contactors not open");
|
||||
stateMachineSOCReset = 0xFF;
|
||||
datalayer.battery.settings.user_requests_tesla_soc_reset = false;
|
||||
set_event(EVENT_BATTERY_SOC_RESET_FAIL, 0);
|
||||
clear_event(EVENT_BATTERY_SOC_RESET_FAIL);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -779,7 +797,7 @@ void TeslaBattery::
|
|||
datalayer_extended.tesla.HVP_shuntBarTempStatus = HVP_shuntBarTempStatus;
|
||||
datalayer_extended.tesla.HVP_shuntAsicTempStatus = HVP_shuntAsicTempStatus;
|
||||
|
||||
//Safety checks for CAN message sesnding
|
||||
//Safety checks for CAN message sending
|
||||
if ((datalayer.system.status.inverter_allows_contactor_closing == true) &&
|
||||
(datalayer.battery.status.bms_status != FAULT) && (!datalayer.system.settings.equipment_stop_active)) {
|
||||
// Carry on: 0x221 DRIVE state & reset power down timer
|
||||
|
@ -1667,10 +1685,10 @@ void TeslaBattery::handle_incoming_can_frame(CAN_frame rx_frame) {
|
|||
}
|
||||
*/
|
||||
break;
|
||||
case 0x612: // CAN UDSs for BMS
|
||||
case 0x612: // CAN UDS responses for BMS
|
||||
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
|
||||
//BMS Query
|
||||
if (stateMachineBMSQuery != 0xFF && stateMachineBMSReset == 0xFF) {
|
||||
if (stateMachineBMSQuery != 0xFF && stateMachineBMSReset == 0xFF && stateMachineSOCReset == 0xFF) {
|
||||
if (memcmp(rx_frame.data.u8, "\x02\x50\x03\xAA\xAA\xAA\xAA\xAA", 8) == 0) {
|
||||
//Received initial response, proceed to actual query
|
||||
logging.println("CAN UDS: Received BMS query initial handshake reply");
|
||||
|
@ -1713,15 +1731,28 @@ void TeslaBattery::handle_incoming_can_frame(CAN_frame rx_frame) {
|
|||
break;
|
||||
}
|
||||
}
|
||||
//BMS Reset
|
||||
if (stateMachineBMSQuery == 0xFF) { // Make sure this is reset request not query
|
||||
if (memcmp(rx_frame.data.u8, "\x02\x67\x06\xAA\xAA\xAA\xAA\xAA", 8) == 0) {
|
||||
logging.println("CAN UDS: ECU unlocked");
|
||||
} else if (memcmp(rx_frame.data.u8, "\x03\x7F\x11\x78\xAA\xAA\xAA\xAA", 8) == 0) {
|
||||
logging.println("CAN UDS: ECU reset request successful but ECU busy, response pending");
|
||||
} else if (memcmp(rx_frame.data.u8, "\x02\x51\x01\xAA\xAA\xAA\xAA\xAA", 8) == 0) {
|
||||
logging.println("CAN UDS: ECU reset positive response, 1 second downtime");
|
||||
}
|
||||
//BMS ECU responses
|
||||
if (memcmp(rx_frame.data.u8, "\x02\x67\x06\xAA\xAA\xAA\xAA\xAA", 8) == 0) {
|
||||
logging.println("CAN UDS: BMS ECU unlocked");
|
||||
}
|
||||
if (memcmp(rx_frame.data.u8, "\x03\x7F\x11\x78\xAA\xAA\xAA\xAA", 8) == 0) {
|
||||
logging.println("CAN UDS: BMS ECU reset request successful but ECU busy, response pending");
|
||||
}
|
||||
if (memcmp(rx_frame.data.u8, "\x02\x51\x01\xAA\xAA\xAA\xAA\xAA", 8) == 0) {
|
||||
logging.println("CAN UDS: BMS ECU reset positive response, 1 second downtime");
|
||||
set_event(EVENT_BMS_RESET_REQ_SUCCESS, 0);
|
||||
clear_event(EVENT_BMS_RESET_REQ_SUCCESS);
|
||||
}
|
||||
if (memcmp(rx_frame.data.u8, "\x05\x71\x01\x04\x07\x01\xAA\xAA", 8) == 0) {
|
||||
logging.println("CAN UDS: BMS SOC reset accepted, resetting BMS ECU");
|
||||
set_event(EVENT_BATTERY_SOC_RESET_SUCCESS, 0);
|
||||
clear_event(EVENT_BATTERY_SOC_RESET_SUCCESS);
|
||||
stateMachineBMSReset = 6; // BMS ECU already unlocked etc. so we jump straight to reset
|
||||
}
|
||||
if (memcmp(rx_frame.data.u8, "\x05\x71\x01\x04\x07\x00\xAA\xAA", 8) == 0) {
|
||||
logging.println("CAN UDS: BMS SOC reset failed");
|
||||
set_event(EVENT_BATTERY_SOC_RESET_FAIL, 0);
|
||||
clear_event(EVENT_BATTERY_SOC_RESET_FAIL);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
@ -2308,7 +2339,7 @@ void TeslaBattery::printFaultCodesIfActive() {
|
|||
printDebugIfActive(BMS_a139_SW_DC_Link_V_Irrational, "ERROR: BMS_a139_SW_DC_Link_V_Irrational");
|
||||
printDebugIfActive(BMS_a141_SW_BMB_Status_Warning, "ERROR: BMS_a141_SW_BMB_Status_Warning");
|
||||
printDebugIfActive(BMS_a144_Hvp_Config_Mismatch, "ERROR: BMS_a144_Hvp_Config_Mismatch");
|
||||
printDebugIfActive(BMS_a145_SW_SOC_Change, "ERROR: BMS_a145_SW_SOC_Change");
|
||||
printDebugIfActive(BMS_a145_SW_SOC_Change, "INFO: BMS_a145_SW_SOC_Change");
|
||||
printDebugIfActive(BMS_a146_SW_Brick_Overdischarged, "ERROR: BMS_a146_SW_Brick_Overdischarged");
|
||||
printDebugIfActive(BMS_a149_SW_Missing_Config_Block, "ERROR: BMS_a149_SW_Missing_Config_Block");
|
||||
printDebugIfActive(BMS_a151_SW_external_isolation, "ERROR: BMS_a151_SW_external_isolation");
|
||||
|
|
|
@ -21,6 +21,9 @@ class StarkHal : public Esp32Hal {
|
|||
public:
|
||||
const char* name() { return "Stark CMR Module"; }
|
||||
|
||||
//Always enable BMS power on Stark CMR, it does not collide with any pin definitions
|
||||
virtual bool always_enable_bms_power() { return true; }
|
||||
|
||||
// Not needed, GPIO 16 has hardware pullup for PSRAM compatibility
|
||||
virtual gpio_num_t PIN_5V_EN() { return GPIO_NUM_NC; }
|
||||
|
||||
|
|
|
@ -67,6 +67,9 @@ void init_events(void) {
|
|||
events.entries[EVENT_BATTERY_UNDERVOLTAGE].level = EVENT_LEVEL_WARNING;
|
||||
events.entries[EVENT_BATTERY_VALUE_UNAVAILABLE].level = EVENT_LEVEL_WARNING;
|
||||
events.entries[EVENT_BATTERY_ISOLATION].level = EVENT_LEVEL_WARNING;
|
||||
events.entries[EVENT_BATTERY_SOC_RECALIBRATION].level = EVENT_LEVEL_INFO;
|
||||
events.entries[EVENT_BATTERY_SOC_RESET_SUCCESS].level = EVENT_LEVEL_INFO;
|
||||
events.entries[EVENT_BATTERY_SOC_RESET_FAIL].level = EVENT_LEVEL_INFO;
|
||||
events.entries[EVENT_VOLTAGE_DIFFERENCE].level = EVENT_LEVEL_INFO;
|
||||
events.entries[EVENT_SOH_DIFFERENCE].level = EVENT_LEVEL_WARNING;
|
||||
events.entries[EVENT_SOH_LOW].level = EVENT_LEVEL_ERROR;
|
||||
|
@ -124,6 +127,8 @@ void init_events(void) {
|
|||
events.entries[EVENT_EQUIPMENT_STOP].level = EVENT_LEVEL_ERROR;
|
||||
events.entries[EVENT_SD_INIT_FAILED].level = EVENT_LEVEL_WARNING;
|
||||
events.entries[EVENT_PERIODIC_BMS_RESET].level = EVENT_LEVEL_INFO;
|
||||
events.entries[EVENT_BMS_RESET_REQ_SUCCESS].level = EVENT_LEVEL_INFO;
|
||||
events.entries[EVENT_BMS_RESET_REQ_FAIL].level = EVENT_LEVEL_INFO;
|
||||
events.entries[EVENT_BATTERY_TEMP_DEVIATION_HIGH].level = EVENT_LEVEL_WARNING;
|
||||
events.entries[EVENT_GPIO_CONFLICT].level = EVENT_LEVEL_ERROR;
|
||||
events.entries[EVENT_GPIO_NOT_DEFINED].level = EVENT_LEVEL_ERROR;
|
||||
|
@ -244,6 +249,12 @@ String get_event_message_string(EVENTS_ENUM_TYPE event) {
|
|||
return "Battery measurement unavailable. Check 12V power supply and battery wiring!";
|
||||
case EVENT_BATTERY_ISOLATION:
|
||||
return "Battery reports isolation error. High voltage might be leaking to ground. Check battery!";
|
||||
case EVENT_BATTERY_SOC_RECALIBRATION:
|
||||
return "The BMS updated the HV battery State of Charge (SOC) by more than 3pct based on SocByOcv.";
|
||||
case EVENT_BATTERY_SOC_RESET_SUCCESS:
|
||||
return "SOC reset routine was successful.";
|
||||
case EVENT_BATTERY_SOC_RESET_FAIL:
|
||||
return "SOC reset routine failed - check SOC is < 15 or > 90, and contactors are open.";
|
||||
case EVENT_VOLTAGE_DIFFERENCE:
|
||||
return "Too large voltage diff between the batteries. Second battery cannot join the DC-link";
|
||||
case EVENT_SOH_DIFFERENCE:
|
||||
|
@ -361,7 +372,11 @@ String get_event_message_string(EVENTS_ENUM_TYPE event) {
|
|||
case EVENT_SD_INIT_FAILED:
|
||||
return "SD card initialization failed, check hardware. Power must be removed to reset the SD card.";
|
||||
case EVENT_PERIODIC_BMS_RESET:
|
||||
return "BMS Reset Event Completed.";
|
||||
return "BMS reset event completed.";
|
||||
case EVENT_BMS_RESET_REQ_SUCCESS:
|
||||
return "BMS reset request completed successfully.";
|
||||
case EVENT_BMS_RESET_REQ_FAIL:
|
||||
return "BMS reset request failed - check contactors are open.";
|
||||
case EVENT_GPIO_CONFLICT:
|
||||
return "GPIO Pin Conflict: The pin used by '" + esp32hal->failed_allocator() + "' is already allocated by '" +
|
||||
esp32hal->conflicting_allocator() + "'. Please check your configuration and assign different pins.";
|
||||
|
|
|
@ -49,6 +49,9 @@
|
|||
XX(EVENT_BATTERY_ISOLATION) \
|
||||
XX(EVENT_BATTERY_REQUESTS_HEAT) \
|
||||
XX(EVENT_BATTERY_WARMED_UP) \
|
||||
XX(EVENT_BATTERY_SOC_RECALIBRATION) \
|
||||
XX(EVENT_BATTERY_SOC_RESET_SUCCESS) \
|
||||
XX(EVENT_BATTERY_SOC_RESET_FAIL) \
|
||||
XX(EVENT_VOLTAGE_DIFFERENCE) \
|
||||
XX(EVENT_SOH_DIFFERENCE) \
|
||||
XX(EVENT_SOH_LOW) \
|
||||
|
@ -107,6 +110,8 @@
|
|||
XX(EVENT_AUTOMATIC_PRECHARGE_FAILURE) \
|
||||
XX(EVENT_SD_INIT_FAILED) \
|
||||
XX(EVENT_PERIODIC_BMS_RESET) \
|
||||
XX(EVENT_BMS_RESET_REQ_SUCCESS) \
|
||||
XX(EVENT_BMS_RESET_REQ_FAIL) \
|
||||
XX(EVENT_BATTERY_TEMP_DEVIATION_HIGH) \
|
||||
XX(EVENT_GPIO_NOT_DEFINED) \
|
||||
XX(EVENT_GPIO_CONFLICT) \
|
||||
|
|
|
@ -1058,19 +1058,19 @@ const char* getCANInterfaceName(CAN_Interface interface) {
|
|||
|
||||
<div class="if-cbms">
|
||||
<label>Battery max design voltage (V): </label>
|
||||
<input name='BATTPVMAX' pattern="^[0-9]+(\.[0-9]+)?$" type='text' value='%BATTPVMAX%'
|
||||
<input name='BATTPVMAX' pattern="[0-9]+(\.[0-9]+)?" type='text' value='%BATTPVMAX%'
|
||||
title="Maximum safe voltage for the entire battery pack in volts. Used as charge target and protection limits." />
|
||||
|
||||
<label>Battery min design voltage (V): </label>
|
||||
<input name='BATTPVMIN' pattern="^[0-9]+(\.[0-9]+)?$" type='text' value='%BATTPVMIN%'
|
||||
<input name='BATTPVMIN' pattern="[0-9]+(\.[0-9]+)?" type='text' value='%BATTPVMIN%'
|
||||
title="Minimum safe voltage for the entire battery pack in volts. Further discharge not possible below this limit." />
|
||||
|
||||
<label>Cell max design voltage (mV): </label>
|
||||
<input name='BATTCVMAX' pattern="^[0-9]+$" type='text' value='%BATTCVMAX%'
|
||||
<input name='BATTCVMAX' pattern="[0-9]+" type='text' value='%BATTCVMAX%'
|
||||
title="Maximum voltage per individual cell in millivolts. Charging stops if one cell reaches this voltage." />
|
||||
|
||||
<label>Cell min design voltage (mV): </label>
|
||||
<input name='BATTCVMIN' pattern="^[0-9]+$" type='text' value='%BATTCVMIN%'
|
||||
<input name='BATTCVMIN' pattern="[0-9]+$" type='text' value='%BATTCVMIN%'
|
||||
title="Minimum voltage per individual cell in millivolts. Discharge stops if one cell drops to this voltage." />
|
||||
</div>
|
||||
|
||||
|
@ -1104,33 +1104,33 @@ const char* getCANInterfaceName(CAN_Interface interface) {
|
|||
|
||||
<div class="if-sofar">
|
||||
<label>Sofar Battery ID (0-15): </label>
|
||||
<input name='SOFAR_ID' type='text' value="%SOFAR_ID%" pattern="^[0-9]{1,2}$" />
|
||||
<input name='SOFAR_ID' type='text' value="%SOFAR_ID%" pattern="[0-9]{1,2}" />
|
||||
</div>
|
||||
|
||||
<div class="if-pylonish">
|
||||
<label>Reported cell count (0 for default): </label>
|
||||
<input name='INVCELLS' type='text' value="%INVCELLS%" pattern="^[0-9]+$" />
|
||||
<input name='INVCELLS' type='text' value="%INVCELLS%" pattern="[0-9]+" />
|
||||
</div>
|
||||
|
||||
<div class="if-pylonish if-solax">
|
||||
<label>Reported module count (0 for default): </label>
|
||||
<input name='INVMODULES' type='text' value="%INVMODULES%" pattern="^[0-9]+$" />
|
||||
<input name='INVMODULES' type='text' value="%INVMODULES%" pattern="[0-9]+" />
|
||||
</div>
|
||||
|
||||
<div class="if-pylonish">
|
||||
<label>Reported cells per module (0 for default): </label>
|
||||
<input name='INVCELLSPER' type='text' value="%INVCELLSPER%" pattern="^[0-9]+$" />
|
||||
<input name='INVCELLSPER' type='text' value="%INVCELLSPER%" pattern="[0-9]+" />
|
||||
|
||||
<label>Reported voltage level (0 for default): </label>
|
||||
<input name='INVVLEVEL' type='text' value="%INVVLEVEL%" pattern="^[0-9]+$" />
|
||||
<input name='INVVLEVEL' type='text' value="%INVVLEVEL%" pattern="[0-9]+" />
|
||||
|
||||
<label>Reported Ah capacity (0 for default): </label>
|
||||
<input name='INVCAPACITY' type='text' value="%INVCAPACITY%" pattern="^[0-9]+$" />
|
||||
<input name='INVCAPACITY' type='text' value="%INVCAPACITY%" pattern="[0-9]+" />
|
||||
</div>
|
||||
|
||||
<div class="if-solax">
|
||||
<label>Reported battery type (in decimal): </label>
|
||||
<input name='INVBTYPE' type='text' value="%INVBTYPE%" pattern="^[0-9]+$" />
|
||||
<input name='INVBTYPE' type='text' value="%INVBTYPE%" pattern="[0-9]+" />
|
||||
|
||||
<label>Inverter should ignore contactors: </label>
|
||||
<input type='checkbox' name='INVICNT' value='on' %INVICNT% />
|
||||
|
@ -1227,7 +1227,7 @@ const char* getCANInterfaceName(CAN_Interface interface) {
|
|||
|
||||
<div class="if-extprecharge">
|
||||
<label>Precharge, maximum ms before fault: </label>
|
||||
<input name='MAXPRETIME' type='text' value="%MAXPRETIME%" pattern="^[0-9]+$" />
|
||||
<input name='MAXPRETIME' type='text' value="%MAXPRETIME%" pattern="[0-9]+" />
|
||||
|
||||
<label>Normally Open (NO) inverter disconnect contactor: </label>
|
||||
<input type='checkbox' name='NOINVDISC' value='on' %NOINVDISC% />
|
||||
|
@ -1249,14 +1249,14 @@ const char* getCANInterfaceName(CAN_Interface interface) {
|
|||
|
||||
<label>Access point name: </label>
|
||||
<input type='text' name='APNAME' value="%APNAME%"
|
||||
pattern="[A-Za-z0-9!#*]{8,63}"
|
||||
title="Name must be 8-63 characters long and may only contain letters, numbers and some special characters: !#*"
|
||||
pattern="[A-Za-z0-9!#*-]{8,63}"
|
||||
title="Name must be 8-63 characters long and may only contain letters, numbers and some special characters: !#*-"
|
||||
required />
|
||||
|
||||
<label>Access point password: </label>
|
||||
<input type='text' name='APPASSWORD' value="%APPASSWORD%"
|
||||
pattern="[A-Za-z0-9!#*]{8,63}"
|
||||
title="Password must be 8-63 characters long and may only contain letters, numbers and some special characters: !#*"
|
||||
pattern="[A-Za-z0-9!#*-]{8,63}"
|
||||
title="Password must be 8-63 characters long and may only contain letters, numbers and some special characters: !#*-"
|
||||
required />
|
||||
|
||||
<label>Wifi channel 0-14: </label>
|
||||
|
@ -1266,8 +1266,8 @@ const char* getCANInterfaceName(CAN_Interface interface) {
|
|||
|
||||
<label>Custom Wifi hostname: </label>
|
||||
<input type='text' name='HOSTNAME' value="%HOSTNAME%"
|
||||
pattern="[A-Za-z0-9!*]"
|
||||
title="Optional: Hostname may only contain only letters, numbers, ! and *" />
|
||||
pattern="[A-Za-z0-9!#*-]+"
|
||||
title="Optional: Hostname may only contain letters, numbers and some special characters: !#*-" />
|
||||
|
||||
<label>Use static IP address: </label>
|
||||
<input type='checkbox' name='STATICIP' value='on' %STATICIP% />
|
||||
|
@ -1305,18 +1305,18 @@ const char* getCANInterfaceName(CAN_Interface interface) {
|
|||
<div class='if-mqtt'>
|
||||
<label>MQTT server: </label>
|
||||
<input type='text' name='MQTTSERVER' value="%MQTTSERVER%"
|
||||
pattern="^([A-Za-z0-9.-]+|)/$"
|
||||
pattern="[A-Za-z0-9.-]+"
|
||||
title="Hostname (letters, numbers, dots, hyphens)" />
|
||||
<label>MQTT port: </label>
|
||||
<input type='number' name='MQTTPORT' value="%MQTTPORT%"
|
||||
min="1" max="65535" step="1"
|
||||
title="Port number (1-65535)" />
|
||||
<label>MQTT user: </label><input type='text' name='MQTTUSER' value="%MQTTUSER%"
|
||||
pattern="[A-Za-z0-9!#*]"
|
||||
title="MQTT username can only contain letters, numbers and some special characters: !#*" />
|
||||
pattern="[A-Za-z0-9!#*-]+"
|
||||
title="MQTT username can only contain letters, numbers and some special characters: !#*-" />
|
||||
<label>MQTT password: </label><input type='password' name='MQTTPASSWORD' value="%MQTTPASSWORD%"
|
||||
pattern="[A-Za-z0-9!#*]"
|
||||
title="MQTT password can only contain letters, numbers and some special characters: !#*" />
|
||||
pattern="[A-Za-z0-9!#*-]+"
|
||||
title="MQTT password can only contain letters, numbers and some special characters: !#*-" />
|
||||
<label>MQTT timeout ms: </label>
|
||||
<input name='MQTTTIMEOUT' type='number' value="%MQTTTIMEOUT%"
|
||||
min="1" max="60000" step="1"
|
||||
|
|
|
@ -240,7 +240,6 @@ void init_mDNS() {
|
|||
}
|
||||
|
||||
void init_WiFi_AP() {
|
||||
ssidAP = std::string("BatteryEmulator") + WiFi.macAddress().c_str();
|
||||
|
||||
DEBUG_PRINTF("Creating Access Point: %s\n", ssidAP.c_str());
|
||||
DEBUG_PRINTF("With password: %s\n", passwordAP.c_str());
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue