mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-07 08:19:52 +03:00
add network options, IPv6 for mqtt
This commit is contained in:
@@ -2,14 +2,16 @@
|
||||
|
||||
## Added
|
||||
|
||||
- support for IPv6 (#83)
|
||||
- support for IPv6 (web/api/mqtt, not syslog) (#83)
|
||||
- System Log in Web UI will show current time if the NTP Service is enabled (#82)
|
||||
- Network settings for Tx-power, WiFi-bandwidth, WiFi-sleepmode (#83)
|
||||
- optional low clockrate (160 MHz) (#83)
|
||||
|
||||
## Fixed
|
||||
|
||||
## Changed
|
||||
|
||||
- removed Rx echo failures counting as incomplete telegrams. BAd telegrams show as Warning and not Errors. [#80](https://github.com/emsesp/EMS-ESP32/issues/80)
|
||||
- removed Rx echo failures counting as incomplete telegrams. Bad telegrams show as Warning and not Errors. [#80](https://github.com/emsesp/EMS-ESP32/issues/80)
|
||||
- add upload_sec to `api/system/info` and removed # from some names to keep consistent with MQTT heartbeat
|
||||
- added debug target to PlatformIO build to help hunt down system crashes
|
||||
|
||||
|
||||
@@ -51,7 +51,11 @@ class NetworkSettingsForm extends React.Component<NetworkStatusFormProps> {
|
||||
ssid: selectedNetwork.ssid,
|
||||
password: '',
|
||||
hostname: props.data.hostname,
|
||||
static_ip_config: false
|
||||
static_ip_config: false,
|
||||
enableIPv6: false,
|
||||
bandwidth20: false,
|
||||
tx_power: 20,
|
||||
nosleep: false
|
||||
};
|
||||
props.setData(networkSettings);
|
||||
}
|
||||
@@ -145,6 +149,53 @@ class NetworkSettingsForm extends React.Component<NetworkStatusFormProps> {
|
||||
onChange={handleValueChange('hostname')}
|
||||
margin="normal"
|
||||
/>
|
||||
<TextValidator
|
||||
validators={['required', 'isNumber', 'minNumber:0', 'maxNumber:20']}
|
||||
errorMessages={[
|
||||
'Tx Power is required',
|
||||
'Must be a number',
|
||||
'Must be greater than 0dBm ',
|
||||
'Max value is 20dBm'
|
||||
]}
|
||||
name="tx_power"
|
||||
label="WiFi Tx Power (dBm)"
|
||||
fullWidth
|
||||
variant="outlined"
|
||||
value={data.tx_power}
|
||||
type="number"
|
||||
onChange={handleValueChange('tx_power')}
|
||||
margin="normal"
|
||||
/>
|
||||
<BlockFormControlLabel
|
||||
control={
|
||||
<Checkbox
|
||||
value="enableIPv6"
|
||||
checked={data.enableIPv6}
|
||||
onChange={handleValueChange('enableIPv6')}
|
||||
/>
|
||||
}
|
||||
label="Enable IPv6"
|
||||
/>
|
||||
<BlockFormControlLabel
|
||||
control={
|
||||
<Checkbox
|
||||
value="bandwidth20"
|
||||
checked={data.bandwidth20}
|
||||
onChange={handleValueChange('bandwidth20')}
|
||||
/>
|
||||
}
|
||||
label="WiFi Low Bandwidth"
|
||||
/>
|
||||
<BlockFormControlLabel
|
||||
control={
|
||||
<Checkbox
|
||||
value="nosleep"
|
||||
checked={data.nosleep}
|
||||
onChange={handleValueChange('nosleep')}
|
||||
/>
|
||||
}
|
||||
label="Disable Wifi Sleepmode"
|
||||
/>
|
||||
<BlockFormControlLabel
|
||||
control={
|
||||
<Checkbox
|
||||
|
||||
@@ -37,6 +37,10 @@ export interface NetworkSettings {
|
||||
password: string;
|
||||
hostname: string;
|
||||
static_ip_config: boolean;
|
||||
enableIPv6: boolean;
|
||||
bandwidth20: boolean;
|
||||
nosleep: boolean;
|
||||
tx_power: number;
|
||||
local_ip?: string;
|
||||
gateway_ip?: string;
|
||||
subnet_mask?: string;
|
||||
|
||||
@@ -414,6 +414,16 @@ class EMSESPSettingsForm extends Component<EMSESPSettingsFormProps> {
|
||||
}
|
||||
label="Enable ADC"
|
||||
/>
|
||||
<BlockFormControlLabel
|
||||
control={
|
||||
<Checkbox
|
||||
checked={data.low_clock}
|
||||
onChange={handleValueChange('low_clock')}
|
||||
value="low_clock"
|
||||
/>
|
||||
}
|
||||
label="Low Clockrate (160MHz, changed on next reboot)"
|
||||
/>
|
||||
<Grid
|
||||
container
|
||||
spacing={0}
|
||||
|
||||
@@ -16,6 +16,7 @@ export interface EMSESPSettings {
|
||||
dallas_parasite: boolean;
|
||||
led_gpio: number;
|
||||
hide_led: boolean;
|
||||
low_clock: boolean;
|
||||
notoken_api: boolean;
|
||||
analog_enabled: boolean;
|
||||
pbutton_gpio: number;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
const ipAddressRegexp = /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;
|
||||
const ipv6AddressRegexp = /^([a-fA-F0-9]{0,4}:([a-fA-F0-9]{0,4}:){1,6}[a-fA-F0-9]{0,4})$/;
|
||||
|
||||
export default function isIp(ipAddress: string) {
|
||||
return ipAddressRegexp.test(ipAddress);
|
||||
return ipAddressRegexp.test(ipAddress) || ipv6AddressRegexp.test(ipAddress);
|
||||
}
|
||||
|
||||
@@ -12,8 +12,10 @@ AsyncMqttClient::AsyncMqttClient()
|
||||
, _lastPingRequestTime(0)
|
||||
, _generatedClientId{0}
|
||||
, _ip()
|
||||
, _ipv6()
|
||||
, _host(nullptr)
|
||||
, _useIp(false)
|
||||
, _useIpv6(false)
|
||||
#if ASYNC_TCP_SSL_ENABLED
|
||||
, _secure(false)
|
||||
#endif
|
||||
@@ -112,18 +114,35 @@ AsyncMqttClient& AsyncMqttClient::setWill(const char* topic, uint8_t qos, bool r
|
||||
|
||||
AsyncMqttClient& AsyncMqttClient::setServer(IPAddress ip, uint16_t port) {
|
||||
_useIp = true;
|
||||
_useIpv6 = false;
|
||||
_ip = ip;
|
||||
_port = port;
|
||||
return *this;
|
||||
}
|
||||
|
||||
AsyncMqttClient& AsyncMqttClient::setServer(const char* host, uint16_t port) {
|
||||
AsyncMqttClient& AsyncMqttClient::setServer(IPv6Address ipv6, uint16_t port) {
|
||||
_useIpv6 = true;
|
||||
_useIp = false;
|
||||
_host = host;
|
||||
_ipv6 = ipv6;
|
||||
_port = port;
|
||||
return *this;
|
||||
}
|
||||
|
||||
AsyncMqttClient& AsyncMqttClient::setServer(const char* host, uint16_t port) {
|
||||
_port = port;
|
||||
_useIp = false;
|
||||
_useIpv6 = false;
|
||||
_host = host;
|
||||
if (_ipv6.fromString(host)) {
|
||||
_useIpv6 = true;
|
||||
_useIp = false;
|
||||
} else if (_ip.fromString(host)) {
|
||||
_useIpv6 = false;
|
||||
_useIp = true;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
#if ASYNC_TCP_SSL_ENABLED
|
||||
AsyncMqttClient& AsyncMqttClient::setSecure(bool secure) {
|
||||
_secure = secure;
|
||||
@@ -698,6 +717,8 @@ void AsyncMqttClient::connect() {
|
||||
#else
|
||||
if (_useIp) {
|
||||
_client.connect(_ip, _port);
|
||||
} else if (_useIpv6) {
|
||||
_client.connect(_ipv6, _port);
|
||||
} else {
|
||||
_client.connect(_host, _port);
|
||||
}
|
||||
|
||||
@@ -62,6 +62,7 @@ class AsyncMqttClient {
|
||||
AsyncMqttClient& setCredentials(const char* username, const char* password = nullptr);
|
||||
AsyncMqttClient& setWill(const char* topic, uint8_t qos, bool retain, const char* payload = nullptr, size_t length = 0);
|
||||
AsyncMqttClient& setServer(IPAddress ip, uint16_t port);
|
||||
AsyncMqttClient& setServer(IPv6Address ipv6, uint16_t port);
|
||||
AsyncMqttClient& setServer(const char* host, uint16_t port);
|
||||
#if ASYNC_TCP_SSL_ENABLED
|
||||
AsyncMqttClient& setSecure(bool secure);
|
||||
@@ -102,8 +103,10 @@ class AsyncMqttClient {
|
||||
|
||||
char _generatedClientId[18 + 1]; // esp8266-abc123 and esp32-abcdef123456
|
||||
IPAddress _ip;
|
||||
IPv6Address _ipv6;
|
||||
const char* _host;
|
||||
bool _useIp;
|
||||
bool _useIpv6;
|
||||
#if ASYNC_TCP_SSL_ENABLED
|
||||
bool _secure;
|
||||
#endif
|
||||
|
||||
@@ -47,6 +47,7 @@ void APSettingsService::manageAP() {
|
||||
|
||||
void APSettingsService::startAP() {
|
||||
WiFi.softAPConfig(_state.localIP, _state.gatewayIP, _state.subnetMask);
|
||||
esp_wifi_set_bandwidth(ESP_IF_WIFI_AP, WIFI_BW_HT20);
|
||||
WiFi.softAP(_state.ssid.c_str(), _state.password.c_str());
|
||||
if (!_dnsServer) {
|
||||
IPAddress apIp = WiFi.softAPIP();
|
||||
|
||||
@@ -101,6 +101,7 @@ void MqttSettingsService::WiFiEvent(WiFiEvent_t event, WiFiEventInfo_t info) {
|
||||
switch (event) {
|
||||
case SYSTEM_EVENT_STA_GOT_IP:
|
||||
case SYSTEM_EVENT_ETH_GOT_IP:
|
||||
case SYSTEM_EVENT_GOT_IP6:
|
||||
if (_state.enabled) {
|
||||
// emsesp::EMSESP::logger().info(F("Network connection found, starting MQTT client"));
|
||||
onConfigUpdated();
|
||||
|
||||
@@ -19,12 +19,6 @@ NetworkSettingsService::NetworkSettingsService(AsyncWebServer * server, FS * fs,
|
||||
WiFi.mode(WIFI_MODE_MAX);
|
||||
WiFi.mode(WIFI_MODE_NULL);
|
||||
|
||||
#if defined(EMSESP_WIFI_TWEAK)
|
||||
// www.esp32.com/viewtopic.php?t=12055
|
||||
esp_wifi_set_bandwidth(ESP_IF_WIFI_STA, WIFI_BW_HT20);
|
||||
esp_wifi_set_bandwidth(ESP_IF_WIFI_AP, WIFI_BW_HT20);
|
||||
#endif
|
||||
|
||||
WiFi.onEvent(std::bind(&NetworkSettingsService::WiFiEvent, this, _1));
|
||||
|
||||
addUpdateHandler([&](const String & originId) { reconfigureWiFiConnection(); }, false);
|
||||
@@ -68,6 +62,19 @@ void NetworkSettingsService::manageSTA() {
|
||||
}
|
||||
|
||||
WiFi.setHostname(_state.hostname.c_str()); // set hostname
|
||||
// www.esp32.com/viewtopic.php?t=12055
|
||||
read([&](NetworkSettings & networkSettings) {
|
||||
if (networkSettings.bandwidth20) {
|
||||
esp_wifi_set_bandwidth(ESP_IF_WIFI_STA, WIFI_BW_HT20);
|
||||
} else {
|
||||
esp_wifi_set_bandwidth(ESP_IF_WIFI_STA, WIFI_BW_HT40);
|
||||
}
|
||||
esp_wifi_set_max_tx_power(networkSettings.tx_power * 4);
|
||||
if (networkSettings.nosleep) {
|
||||
WiFi.setSleep(false); // turn off sleep - WIFI_PS_NONE
|
||||
}
|
||||
|
||||
});
|
||||
WiFi.begin(_state.ssid.c_str(), _state.password.c_str()); // attempt to connect to the network
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,9 +7,7 @@
|
||||
#include <JsonUtils.h>
|
||||
|
||||
#ifndef EMSESP_STANDALONE
|
||||
#if defined(EMSESP_WIFI_TWEAK)
|
||||
#include <esp_wifi.h>
|
||||
#endif
|
||||
#include <ETH.h>
|
||||
#endif
|
||||
|
||||
@@ -36,6 +34,10 @@ class NetworkSettings {
|
||||
String password;
|
||||
String hostname;
|
||||
bool staticIPConfig;
|
||||
bool enableIPv6;
|
||||
bool bandwidth20;
|
||||
int8_t tx_power;
|
||||
bool nosleep;
|
||||
|
||||
// optional configuration for static IP address
|
||||
IPAddress localIP;
|
||||
@@ -50,6 +52,10 @@ class NetworkSettings {
|
||||
root["password"] = settings.password;
|
||||
root["hostname"] = settings.hostname;
|
||||
root["static_ip_config"] = settings.staticIPConfig;
|
||||
root["enableIPv6"] = settings.enableIPv6;
|
||||
root["bandwidth20"] = settings.bandwidth20;
|
||||
root["tx_power"] = settings.tx_power;
|
||||
root["nosleep"] = settings.nosleep;
|
||||
|
||||
// extended settings
|
||||
JsonUtils::writeIP(root, "local_ip", settings.localIP);
|
||||
@@ -64,6 +70,10 @@ class NetworkSettings {
|
||||
settings.password = root["password"] | FACTORY_WIFI_PASSWORD;
|
||||
settings.hostname = root["hostname"] | FACTORY_WIFI_HOSTNAME;
|
||||
settings.staticIPConfig = root["static_ip_config"] | false;
|
||||
settings.enableIPv6 = root["enableIPv6"] | false;
|
||||
settings.bandwidth20 = root["bandwidth20"] | false;
|
||||
settings.tx_power = root["tx_power"] | 20;
|
||||
settings.nosleep = root["nosleep"] | false;
|
||||
|
||||
// extended settings
|
||||
JsonUtils::readIP(root, "local_ip", settings.localIP);
|
||||
|
||||
@@ -206,6 +206,9 @@ void System::get_settings() {
|
||||
// ADC
|
||||
analog_enabled_ = settings.analog_enabled;
|
||||
|
||||
// Sysclock
|
||||
low_clock_ = settings.low_clock;
|
||||
|
||||
// Syslog
|
||||
syslog_enabled_ = settings.syslog_enabled;
|
||||
syslog_level_ = settings.syslog_level;
|
||||
@@ -275,6 +278,12 @@ void System::start(uint32_t heap_start) {
|
||||
// load in all the settings first
|
||||
get_settings();
|
||||
|
||||
#ifndef EMSESP_STANDALONE
|
||||
if (low_clock_) {
|
||||
setCpuFrequencyMhz(160);
|
||||
}
|
||||
#endif
|
||||
|
||||
EMSESP::esp8266React.getNetworkSettingsService()->read([&](NetworkSettings & networkSettings) {
|
||||
hostname(networkSettings.hostname.c_str()); // sets the hostname
|
||||
LOG_INFO(F("System name: %s"), hostname().c_str());
|
||||
|
||||
@@ -96,10 +96,14 @@ class System {
|
||||
void ethernet_connected(bool b) {
|
||||
ethernet_connected_ = b;
|
||||
}
|
||||
void network_connected(bool b) {
|
||||
network_connected_ = b;
|
||||
}
|
||||
|
||||
bool network_connected() {
|
||||
#ifndef EMSESP_STANDALONE
|
||||
return (ethernet_connected_ || WiFi.isConnected());
|
||||
// return (ethernet_connected_ || WiFi.isConnected());
|
||||
return network_connected_;
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
@@ -147,6 +151,7 @@ class System {
|
||||
uint32_t last_system_check_ = 0;
|
||||
bool upload_status_ = false; // true if we're in the middle of a OTA firmware upload
|
||||
bool ethernet_connected_ = false;
|
||||
bool network_connected_ = false;
|
||||
uint16_t analog_;
|
||||
|
||||
// settings
|
||||
@@ -155,6 +160,7 @@ class System {
|
||||
uint8_t led_gpio_;
|
||||
bool syslog_enabled_;
|
||||
bool analog_enabled_;
|
||||
bool low_clock_;
|
||||
String board_profile_;
|
||||
uint8_t pbutton_gpio_;
|
||||
int8_t syslog_level_;
|
||||
|
||||
@@ -55,6 +55,7 @@ void WebSettings::read(WebSettings & settings, JsonObject & root) {
|
||||
root["dallas_parasite"] = settings.dallas_parasite;
|
||||
root["led_gpio"] = settings.led_gpio;
|
||||
root["hide_led"] = settings.hide_led;
|
||||
root["low_clock"] = settings.low_clock;
|
||||
root["notoken_api"] = settings.notoken_api;
|
||||
root["analog_enabled"] = settings.analog_enabled;
|
||||
root["pbutton_gpio"] = settings.pbutton_gpio;
|
||||
@@ -165,9 +166,10 @@ StateUpdateResult WebSettings::update(JsonObject & root, WebSettings & settings)
|
||||
settings.hide_led = root["hide_led"] | EMSESP_DEFAULT_HIDE_LED;
|
||||
check_flag(prev, settings.hide_led, ChangeFlags::LED);
|
||||
|
||||
// these both need reboots to be applied
|
||||
// these need reboots to be applied
|
||||
settings.ems_bus_id = root["ems_bus_id"] | EMSESP_DEFAULT_EMS_BUS_ID;
|
||||
settings.master_thermostat = root["master_thermostat"] | EMSESP_DEFAULT_MASTER_THERMOSTAT;
|
||||
settings.low_clock = root["low_clock"] | false;;
|
||||
|
||||
// doesn't need any follow-up actions
|
||||
settings.notoken_api = root["notoken_api"] | EMSESP_DEFAULT_NOTOKEN_API;
|
||||
|
||||
@@ -50,6 +50,7 @@ class WebSettings {
|
||||
bool dallas_parasite;
|
||||
uint8_t led_gpio;
|
||||
bool hide_led;
|
||||
bool low_clock;
|
||||
bool notoken_api;
|
||||
bool analog_enabled;
|
||||
uint8_t pbutton_gpio;
|
||||
|
||||
@@ -35,15 +35,20 @@ void WebStatusService::WiFiEvent(WiFiEvent_t event, WiFiEventInfo_t info) {
|
||||
switch (event) {
|
||||
case SYSTEM_EVENT_STA_DISCONNECTED:
|
||||
EMSESP::logger().info(F("WiFi Disconnected. Reason code=%d"), info.disconnected.reason);
|
||||
EMSESP::system_.network_connected(false);
|
||||
break;
|
||||
|
||||
case SYSTEM_EVENT_STA_GOT_IP:
|
||||
#ifndef EMSESP_STANDALONE
|
||||
EMSESP::logger().info(F("WiFi Connected with IP=%s, hostname=%s"), WiFi.localIP().toString().c_str(), WiFi.getHostname());
|
||||
#endif
|
||||
EMSESP::system_.wifi_tweak();
|
||||
EMSESP::esp8266React.getNetworkSettingsService()->read([&](NetworkSettings & networkSettings) {
|
||||
if (!networkSettings.enableIPv6) {
|
||||
EMSESP::system_.network_connected(true);
|
||||
EMSESP::system_.send_heartbeat();
|
||||
EMSESP::system_.syslog_start();
|
||||
}
|
||||
});
|
||||
break;
|
||||
|
||||
case SYSTEM_EVENT_ETH_START:
|
||||
@@ -57,8 +62,13 @@ void WebStatusService::WiFiEvent(WiFiEvent_t event, WiFiEventInfo_t info) {
|
||||
#ifndef EMSESP_STANDALONE
|
||||
EMSESP::logger().info(F("Ethernet Connected with IP=%s, speed %d Mbps"), ETH.localIP().toString().c_str(), ETH.linkSpeed());
|
||||
#endif
|
||||
EMSESP::esp8266React.getNetworkSettingsService()->read([&](NetworkSettings & networkSettings) {
|
||||
if (!networkSettings.enableIPv6) {
|
||||
EMSESP::system_.network_connected(true);
|
||||
EMSESP::system_.send_heartbeat();
|
||||
EMSESP::system_.syslog_start();
|
||||
}
|
||||
});
|
||||
EMSESP::system_.ethernet_connected(true);
|
||||
}
|
||||
break;
|
||||
@@ -66,20 +76,30 @@ void WebStatusService::WiFiEvent(WiFiEvent_t event, WiFiEventInfo_t info) {
|
||||
case SYSTEM_EVENT_ETH_DISCONNECTED:
|
||||
EMSESP::logger().info(F("Ethernet Disconnected"));
|
||||
EMSESP::system_.ethernet_connected(false);
|
||||
EMSESP::system_.network_connected(false);
|
||||
break;
|
||||
|
||||
case SYSTEM_EVENT_ETH_STOP:
|
||||
EMSESP::logger().info(F("Ethernet Stopped"));
|
||||
EMSESP::system_.ethernet_connected(false);
|
||||
EMSESP::system_.network_connected(false);
|
||||
break;
|
||||
|
||||
#ifndef EMSESP_STANDALONE
|
||||
case SYSTEM_EVENT_STA_CONNECTED:
|
||||
EMSESP::esp8266React.getNetworkSettingsService()->read([&](NetworkSettings & networkSettings) {
|
||||
if (networkSettings.enableIPv6) {
|
||||
WiFi.enableIpV6();
|
||||
}
|
||||
});
|
||||
break;
|
||||
|
||||
case SYSTEM_EVENT_ETH_CONNECTED:
|
||||
EMSESP::esp8266React.getNetworkSettingsService()->read([&](NetworkSettings & networkSettings) {
|
||||
if (networkSettings.enableIPv6) {
|
||||
ETH.enableIpV6();
|
||||
}
|
||||
});
|
||||
break;
|
||||
|
||||
case SYSTEM_EVENT_GOT_IP6:
|
||||
@@ -88,6 +108,9 @@ void WebStatusService::WiFiEvent(WiFiEvent_t event, WiFiEventInfo_t info) {
|
||||
} else {
|
||||
EMSESP::logger().info(F("WiFi Connected with IP=%s, hostname=%s"), WiFi.localIPv6().toString().c_str(), WiFi.getHostname());
|
||||
}
|
||||
EMSESP::system_.network_connected(true);
|
||||
EMSESP::system_.send_heartbeat();
|
||||
EMSESP::system_.syslog_start();
|
||||
break;
|
||||
#endif
|
||||
|
||||
|
||||
Reference in New Issue
Block a user