mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-08 00:39:50 +03:00
1.5.4
This commit is contained in:
13
CHANGELOG.md
13
CHANGELOG.md
@@ -5,6 +5,19 @@ All notable changes to this project will be documented in this file.
|
|||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
## [1.5.4] 2019-03-03
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- MQTT keep alive changed from 5 minutes to 1 minute
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- Callback for OTA. This is used to disable EMS bus during a firmware OTA update, which caused problems with the latest ESP89266 core libraries
|
||||||
|
- Added rough estimate of WiFi signal strength to info page
|
||||||
|
- Added the build time & date to the info page (optional in platformio.ini)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [1.5.3] 2019-02-22
|
## [1.5.3] 2019-02-22
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|||||||
Binary file not shown.
@@ -2,7 +2,8 @@
|
|||||||
* MyESP - my ESP helper class to handle Wifi, MQTT and Telnet
|
* MyESP - my ESP helper class to handle Wifi, MQTT and Telnet
|
||||||
*
|
*
|
||||||
* Paul Derbyshire - December 2018
|
* Paul Derbyshire - December 2018
|
||||||
* Version 1.1 - Feb 22 2019. Added support for ESP32
|
* Version 1.1 - Feb 22 2019. Added support for ESP32
|
||||||
|
* Version 1.1.1 - March 3 2019. Added OTA callback
|
||||||
*
|
*
|
||||||
* Ideas borrowed from Espurna https://github.com/xoseperez/espurna
|
* Ideas borrowed from Espurna https://github.com/xoseperez/espurna
|
||||||
*/
|
*/
|
||||||
@@ -13,7 +14,7 @@
|
|||||||
MyESP::MyESP() {
|
MyESP::MyESP() {
|
||||||
_app_hostname = strdup("MyESP");
|
_app_hostname = strdup("MyESP");
|
||||||
_app_name = strdup("MyESP");
|
_app_name = strdup("MyESP");
|
||||||
_app_version = strdup("1.0.0");
|
_app_version = strdup("1.1.1");
|
||||||
|
|
||||||
_boottime = strdup("unknown");
|
_boottime = strdup("unknown");
|
||||||
_load_average = 100; // calculated load average
|
_load_average = 100; // calculated load average
|
||||||
@@ -47,6 +48,8 @@ MyESP::MyESP() {
|
|||||||
_wifi_callback = NULL;
|
_wifi_callback = NULL;
|
||||||
_wifi_connected = false;
|
_wifi_connected = false;
|
||||||
|
|
||||||
|
_ota_callback = NULL;
|
||||||
|
|
||||||
_suspendOutput = false;
|
_suspendOutput = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -297,6 +300,20 @@ void MyESP::_wifi_setup() {
|
|||||||
jw.addNetwork(_wifi_ssid, _wifi_password); // Add a network
|
jw.addNetwork(_wifi_ssid, _wifi_password); // Add a network
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// set the callback function for the OTA onstart
|
||||||
|
void MyESP::setOTA(ota_callback_f OTACallback) {
|
||||||
|
_ota_callback = OTACallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
// OTA callback when the upload process starts
|
||||||
|
void MyESP::_OTACallback() {
|
||||||
|
myDebug_P(PSTR("[OTA] Start"));
|
||||||
|
SerialAndTelnet.handle(); // force flush
|
||||||
|
if (_ota_callback) {
|
||||||
|
(_ota_callback)(); // call custom function to handle mqtt receives
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// OTA Setup
|
// OTA Setup
|
||||||
void MyESP::_ota_setup() {
|
void MyESP::_ota_setup() {
|
||||||
if (!_wifi_ssid) {
|
if (!_wifi_ssid) {
|
||||||
@@ -306,7 +323,7 @@ void MyESP::_ota_setup() {
|
|||||||
//ArduinoOTA.setPort(OTA_PORT);
|
//ArduinoOTA.setPort(OTA_PORT);
|
||||||
ArduinoOTA.setHostname(_app_hostname);
|
ArduinoOTA.setHostname(_app_hostname);
|
||||||
|
|
||||||
ArduinoOTA.onStart([this]() { myDebug_P(PSTR("[OTA] Start")); });
|
ArduinoOTA.onStart([this]() { _OTACallback(); });
|
||||||
ArduinoOTA.onEnd([this]() { myDebug_P(PSTR("[OTA] Done, restarting...")); });
|
ArduinoOTA.onEnd([this]() { myDebug_P(PSTR("[OTA] Done, restarting...")); });
|
||||||
ArduinoOTA.onProgress([this](unsigned int progress, unsigned int total) {
|
ArduinoOTA.onProgress([this](unsigned int progress, unsigned int total) {
|
||||||
static unsigned int _progOld;
|
static unsigned int _progOld;
|
||||||
@@ -374,6 +391,70 @@ void MyESP::_telnet_setup() {
|
|||||||
memset(_command, 0, TELNET_MAX_COMMAND_LENGTH);
|
memset(_command, 0, TELNET_MAX_COMMAND_LENGTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#define RTC_LEAP_YEAR(year) ((((year) % 4 == 0) && ((year) % 100 != 0)) || ((year) % 400 == 0))
|
||||||
|
|
||||||
|
/* Days in a month */
|
||||||
|
static uint8_t RTC_Months[2][12] = {
|
||||||
|
{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, /* Not leap year */
|
||||||
|
{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} /* Leap year */
|
||||||
|
};
|
||||||
|
|
||||||
|
// https://stackoverflow.com/questions/43063071/the-arduino-ntp-i-want-print-out-datadd-mm-yyyy
|
||||||
|
void MyESP::_printBuildTime(unsigned long unix) {
|
||||||
|
// compensate for summer/winter time and CET. Can't be bothered to work out DST.
|
||||||
|
// add 3600 to the UNIX time during winter, (3600 s = 1 h), and 7200 during summer (DST).
|
||||||
|
unix += 3600; // add 1 hour
|
||||||
|
|
||||||
|
uint8_t Day, Month;
|
||||||
|
|
||||||
|
uint8_t Seconds = unix % 60; /* Get seconds from unix */
|
||||||
|
unix /= 60; /* Go to minutes */
|
||||||
|
uint8_t Minutes = unix % 60; /* Get minutes */
|
||||||
|
unix /= 60; /* Go to hours */
|
||||||
|
uint8_t Hours = unix % 24; /* Get hours */
|
||||||
|
unix /= 24; /* Go to days */
|
||||||
|
uint8_t WeekDay = (unix + 3) % 7 + 1; /* Get week day, monday is first day */
|
||||||
|
|
||||||
|
uint16_t year = 1970; /* Process year */
|
||||||
|
while (1) {
|
||||||
|
if (RTC_LEAP_YEAR(year)) {
|
||||||
|
if (unix >= 366) {
|
||||||
|
unix -= 366;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else if (unix >= 365) {
|
||||||
|
unix -= 365;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
year++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get year in xx format */
|
||||||
|
uint8_t Year = (uint8_t)(year - 2000);
|
||||||
|
/* Get month */
|
||||||
|
for (Month = 0; Month < 12; Month++) {
|
||||||
|
if (RTC_LEAP_YEAR(year)) {
|
||||||
|
if (unix >= (uint32_t)RTC_Months[1][Month]) {
|
||||||
|
unix -= RTC_Months[1][Month];
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else if (unix >= (uint32_t)RTC_Months[0][Month]) {
|
||||||
|
unix -= RTC_Months[0][Month];
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Month++; /* Month starts with 1 */
|
||||||
|
Day = unix + 1; /* Date starts with 1 */
|
||||||
|
|
||||||
|
SerialAndTelnet.printf("%02d:%02d:%02d %d/%d/%d", Hours, Minutes, Seconds, Day, Month, Year);
|
||||||
|
}
|
||||||
|
|
||||||
// Show help of commands
|
// Show help of commands
|
||||||
void MyESP::_consoleShowHelp() {
|
void MyESP::_consoleShowHelp() {
|
||||||
SerialAndTelnet.println();
|
SerialAndTelnet.println();
|
||||||
@@ -389,15 +470,21 @@ void MyESP::_consoleShowHelp() {
|
|||||||
#else
|
#else
|
||||||
String hostname = WiFi.hostname();
|
String hostname = WiFi.hostname();
|
||||||
#endif
|
#endif
|
||||||
SerialAndTelnet.printf("* Hostname: %s IP: %s MAC: %s",
|
SerialAndTelnet.printf("* Hostname: %s IP: %s MAC: %s",
|
||||||
hostname.c_str(),
|
hostname.c_str(),
|
||||||
WiFi.localIP().toString().c_str(),
|
WiFi.localIP().toString().c_str(),
|
||||||
WiFi.macAddress().c_str());
|
WiFi.macAddress().c_str());
|
||||||
#ifdef ARDUINO_BOARD
|
#ifdef ARDUINO_BOARD
|
||||||
SerialAndTelnet.printf(" Board: %s", ARDUINO_BOARD);
|
SerialAndTelnet.printf(" Board: %s", ARDUINO_BOARD);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef BUILD_TIME
|
||||||
|
SerialAndTelnet.print(" (Build ");
|
||||||
|
_printBuildTime(BUILD_TIME);
|
||||||
|
SerialAndTelnet.print(")");
|
||||||
|
#endif
|
||||||
SerialAndTelnet.println();
|
SerialAndTelnet.println();
|
||||||
SerialAndTelnet.printf("* Connected to WiFi SSID: %s", WiFi.SSID().c_str());
|
SerialAndTelnet.printf("* Connected to WiFi SSID: %s (signal %d%%)", WiFi.SSID().c_str(), getWifiQuality());
|
||||||
SerialAndTelnet.println();
|
SerialAndTelnet.println();
|
||||||
SerialAndTelnet.printf("* Boot time: %s", _boottime);
|
SerialAndTelnet.printf("* Boot time: %s", _boottime);
|
||||||
SerialAndTelnet.println();
|
SerialAndTelnet.println();
|
||||||
@@ -991,8 +1078,7 @@ void MyESP::_calculateLoad() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// return true if wifi is connected
|
// return true if wifi is connected:
|
||||||
// WL_NO_SHIELD = 255, // for compatibility with WiFi Shield library
|
|
||||||
// WL_IDLE_STATUS = 0,
|
// WL_IDLE_STATUS = 0,
|
||||||
// WL_NO_SSID_AVAIL = 1,
|
// WL_NO_SSID_AVAIL = 1,
|
||||||
// WL_SCAN_COMPLETED = 2,
|
// WL_SCAN_COMPLETED = 2,
|
||||||
@@ -1004,6 +1090,25 @@ bool MyESP::isWifiConnected() {
|
|||||||
return (_wifi_connected);
|
return (_wifi_connected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return the quality (Received Signal Strength Indicator) of the WiFi network.
|
||||||
|
* Returns -1 if WiFi is disconnected.
|
||||||
|
* High quality: 90% ~= -55dBm
|
||||||
|
* Medium quality: 50% ~= -75dBm
|
||||||
|
* Low quality: 30% ~= -85dBm
|
||||||
|
* Unusable quality: 8% ~= -96dBm
|
||||||
|
*/
|
||||||
|
int MyESP::getWifiQuality() {
|
||||||
|
if (WiFi.status() != WL_CONNECTED)
|
||||||
|
return -1;
|
||||||
|
int dBm = WiFi.RSSI();
|
||||||
|
if (dBm <= -100)
|
||||||
|
return 0;
|
||||||
|
if (dBm >= -50)
|
||||||
|
return 100;
|
||||||
|
return 2 * (dBm + 100);
|
||||||
|
}
|
||||||
|
|
||||||
// register new instance
|
// register new instance
|
||||||
void MyESP::begin(const char * app_hostname, const char * app_name, const char * app_version) {
|
void MyESP::begin(const char * app_hostname, const char * app_name, const char * app_version) {
|
||||||
_app_hostname = strdup(app_hostname);
|
_app_hostname = strdup(app_hostname);
|
||||||
|
|||||||
@@ -81,6 +81,7 @@ typedef enum { MYESP_FSACTION_SET, MYESP_FSACTION_LIST, MYESP_FSACTION_SAVE, MYE
|
|||||||
|
|
||||||
typedef std::function<void(unsigned int, const char *, const char *)> mqtt_callback_f;
|
typedef std::function<void(unsigned int, const char *, const char *)> mqtt_callback_f;
|
||||||
typedef std::function<void()> wifi_callback_f;
|
typedef std::function<void()> wifi_callback_f;
|
||||||
|
typedef std::function<void()> ota_callback_f;
|
||||||
typedef std::function<void(uint8_t, const char *)> telnetcommand_callback_f;
|
typedef std::function<void(uint8_t, const char *)> telnetcommand_callback_f;
|
||||||
typedef std::function<void(uint8_t)> telnet_callback_f;
|
typedef std::function<void(uint8_t)> telnet_callback_f;
|
||||||
typedef std::function<bool(MYESP_FSACTION, JsonObject & json)> fs_callback_f;
|
typedef std::function<bool(MYESP_FSACTION, JsonObject & json)> fs_callback_f;
|
||||||
@@ -107,18 +108,21 @@ class MyESP {
|
|||||||
void mqttSubscribe(const char * topic);
|
void mqttSubscribe(const char * topic);
|
||||||
void mqttUnsubscribe(const char * topic);
|
void mqttUnsubscribe(const char * topic);
|
||||||
void mqttPublish(const char * topic, const char * payload);
|
void mqttPublish(const char * topic, const char * payload);
|
||||||
void setMQTT(const char * mqtt_host,
|
void setMQTT(const char * mqtt_host,
|
||||||
const char * mqtt_username,
|
const char * mqtt_username,
|
||||||
const char * mqtt_password,
|
const char * mqtt_password,
|
||||||
const char * mqtt_base,
|
const char * mqtt_base,
|
||||||
unsigned long mqtt_keepalive,
|
unsigned long mqtt_keepalive,
|
||||||
unsigned char mqtt_qos,
|
unsigned char mqtt_qos,
|
||||||
bool mqtt_retain,
|
bool mqtt_retain,
|
||||||
const char * mqtt_will_topic,
|
const char * mqtt_will_topic,
|
||||||
const char * mqtt_will_online_payload,
|
const char * mqtt_will_online_payload,
|
||||||
const char * mqtt_will_offline_payload,
|
const char * mqtt_will_offline_payload,
|
||||||
mqtt_callback_f callback);
|
mqtt_callback_f callback);
|
||||||
|
|
||||||
|
// OTA
|
||||||
|
void setOTA(ota_callback_f OTACallback);
|
||||||
|
|
||||||
// debug & telnet
|
// debug & telnet
|
||||||
void myDebug(const char * format, ...);
|
void myDebug(const char * format, ...);
|
||||||
void myDebug_P(PGM_P format_P, ...);
|
void myDebug_P(PGM_P format_P, ...);
|
||||||
@@ -136,6 +140,8 @@ class MyESP {
|
|||||||
void setBoottime(const char * boottime);
|
void setBoottime(const char * boottime);
|
||||||
void resetESP();
|
void resetESP();
|
||||||
uint16_t getSystemLoadAverage();
|
uint16_t getSystemLoadAverage();
|
||||||
|
int getWifiQuality();
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// mqtt
|
// mqtt
|
||||||
@@ -170,7 +176,9 @@ class MyESP {
|
|||||||
bool _wifi_connected;
|
bool _wifi_connected;
|
||||||
|
|
||||||
// ota
|
// ota
|
||||||
void _ota_setup();
|
ota_callback_f _ota_callback;
|
||||||
|
void _ota_setup();
|
||||||
|
void _OTACallback();
|
||||||
|
|
||||||
// telnet & debug
|
// telnet & debug
|
||||||
TelnetSpy SerialAndTelnet;
|
TelnetSpy SerialAndTelnet;
|
||||||
@@ -205,6 +213,7 @@ class MyESP {
|
|||||||
char * _boottime;
|
char * _boottime;
|
||||||
bool _suspendOutput;
|
bool _suspendOutput;
|
||||||
bool _use_serial;
|
bool _use_serial;
|
||||||
|
void _printBuildTime(unsigned long rawTime);
|
||||||
|
|
||||||
// load average (0..100)
|
// load average (0..100)
|
||||||
void _calculateLoad();
|
void _calculateLoad();
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ env_default = d1_mini
|
|||||||
platform = espressif8266
|
platform = espressif8266
|
||||||
flash_mode = dout
|
flash_mode = dout
|
||||||
build_flags = -g -w
|
build_flags = -g -w
|
||||||
|
;build_flags = -g -w -DBUILD_TIME=$UNIX_TIME
|
||||||
|
|
||||||
wifi_settings =
|
wifi_settings =
|
||||||
; hard code if you prefer. Recommendation is to set from within the app when in Serial or AP mode
|
; hard code if you prefer. Recommendation is to set from within the app when in Serial or AP mode
|
||||||
|
|||||||
@@ -660,7 +660,7 @@ bool SettingsCallback(MYESP_FSACTION action, uint8_t wc, const char * setting, c
|
|||||||
// reset pin
|
// reset pin
|
||||||
pinMode(EMSESP_Status.led_gpio, OUTPUT);
|
pinMode(EMSESP_Status.led_gpio, OUTPUT);
|
||||||
digitalWrite(EMSESP_Status.led_gpio, (EMSESP_Status.led_gpio == LED_BUILTIN) ? HIGH : LOW); // light off. For onboard high=off
|
digitalWrite(EMSESP_Status.led_gpio, (EMSESP_Status.led_gpio == LED_BUILTIN) ? HIGH : LOW); // light off. For onboard high=off
|
||||||
ok = true;
|
ok = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// dallas_gpio
|
// dallas_gpio
|
||||||
@@ -841,6 +841,12 @@ void TelnetCommandCallback(uint8_t wc, const char * commandLine) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// OTA callback when the OTA process starts
|
||||||
|
// so we can disable the EMS to avoid any noise
|
||||||
|
void OTACallback() {
|
||||||
|
emsuart_stop();
|
||||||
|
}
|
||||||
|
|
||||||
// MQTT Callback to handle incoming/outgoing changes
|
// MQTT Callback to handle incoming/outgoing changes
|
||||||
void MQTTCallback(unsigned int type, const char * topic, const char * message) {
|
void MQTTCallback(unsigned int type, const char * topic, const char * message) {
|
||||||
// we're connected. lets subscribe to some topics
|
// we're connected. lets subscribe to some topics
|
||||||
@@ -950,7 +956,6 @@ void WIFICallback() {
|
|||||||
// go and find the boiler and thermostat types
|
// go and find the boiler and thermostat types
|
||||||
ems_discoverModels();
|
ems_discoverModels();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize the boiler settings and shower settings
|
// Initialize the boiler settings and shower settings
|
||||||
@@ -1130,8 +1135,20 @@ void setup() {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// MQTT host, username and password taken from the SPIFFS settings
|
// MQTT host, username and password taken from the SPIFFS settings
|
||||||
myESP.setMQTT(NULL, NULL, NULL, MQTT_BASE, MQTT_KEEPALIVE, MQTT_QOS, MQTT_RETAIN, MQTT_WILL_TOPIC,
|
myESP.setMQTT(NULL,
|
||||||
MQTT_WILL_ONLINE_PAYLOAD, MQTT_WILL_OFFLINE_PAYLOAD, MQTTCallback);
|
NULL,
|
||||||
|
NULL,
|
||||||
|
MQTT_BASE,
|
||||||
|
MQTT_KEEPALIVE,
|
||||||
|
MQTT_QOS,
|
||||||
|
MQTT_RETAIN,
|
||||||
|
MQTT_WILL_TOPIC,
|
||||||
|
MQTT_WILL_ONLINE_PAYLOAD,
|
||||||
|
MQTT_WILL_OFFLINE_PAYLOAD,
|
||||||
|
MQTTCallback);
|
||||||
|
|
||||||
|
// OTA callback which is called when OTA is starting
|
||||||
|
myESP.setOTA(OTACallback);
|
||||||
|
|
||||||
// custom settings in SPIFFS
|
// custom settings in SPIFFS
|
||||||
myESP.setSettings(FSCallback, SettingsCallback);
|
myESP.setSettings(FSCallback, SettingsCallback);
|
||||||
@@ -1143,7 +1160,7 @@ void setup() {
|
|||||||
if (EMSESP_Status.led_gpio != EMS_VALUE_INT_NOTSET) {
|
if (EMSESP_Status.led_gpio != EMS_VALUE_INT_NOTSET) {
|
||||||
pinMode(EMSESP_Status.led_gpio, OUTPUT);
|
pinMode(EMSESP_Status.led_gpio, OUTPUT);
|
||||||
digitalWrite(EMSESP_Status.led_gpio, (EMSESP_Status.led_gpio == LED_BUILTIN) ? HIGH : LOW); // light off. For onboard high=off
|
digitalWrite(EMSESP_Status.led_gpio, (EMSESP_Status.led_gpio == LED_BUILTIN) ? HIGH : LOW); // light off. For onboard high=off
|
||||||
ledcheckTimer.attach_ms(LEDCHECK_TIME, do_ledcheck); // blink heartbeat LED
|
ledcheckTimer.attach_ms(LEDCHECK_TIME, do_ledcheck); // blink heartbeat LED
|
||||||
}
|
}
|
||||||
|
|
||||||
// check for Dallas sensors
|
// check for Dallas sensors
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
#define MQTT_WILL_ONLINE_PAYLOAD "online" // for last will & testament payload
|
#define MQTT_WILL_ONLINE_PAYLOAD "online" // for last will & testament payload
|
||||||
#define MQTT_WILL_OFFLINE_PAYLOAD "offline" // for last will & testament payload
|
#define MQTT_WILL_OFFLINE_PAYLOAD "offline" // for last will & testament payload
|
||||||
#define MQTT_RETAIN false
|
#define MQTT_RETAIN false
|
||||||
#define MQTT_KEEPALIVE 300
|
#define MQTT_KEEPALIVE 60 // 1 minute
|
||||||
#define MQTT_QOS 1
|
#define MQTT_QOS 1
|
||||||
|
|
||||||
// MQTT for thermostat
|
// MQTT for thermostat
|
||||||
|
|||||||
@@ -6,5 +6,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#define APP_NAME "EMS-ESP"
|
#define APP_NAME "EMS-ESP"
|
||||||
#define APP_VERSION "1.5.3"
|
#define APP_VERSION "1.5.4"
|
||||||
#define APP_HOSTNAME "ems-esp"
|
#define APP_HOSTNAME "ems-esp"
|
||||||
|
|||||||
Reference in New Issue
Block a user