Wired Ethernet Support!

Added ESP32 wired ethernet support.
This commit is contained in:
Robert Strouse 2023-02-26 11:50:57 -08:00
parent 7f5463250f
commit 0f2f30bf4d
12 changed files with 605 additions and 78 deletions

View file

@ -3,17 +3,17 @@
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta charset="UTF-8">
<link rel="stylesheet" href="main.css?v=1.2.3" type="text/css" />
<link rel="stylesheet" href="icons.css?v=1.2.3" type="text/css" />
<link rel="stylesheet" href="main.css?v=1.3.0" type="text/css" />
<link rel="stylesheet" href="icons.css?v=1.3.0" type="text/css" />
<link rel="icon" type="image/png" href="favicon.png" />
<script type="text/javascript" src="index.js?v=1.2.3"></script>
<script type="text/javascript" src="index.js?v=1.3.0"></script>
</head>
<body>
<div id="divContainer" class="container" style="user-select:none;position:relative;">
<div id="divRadioError" style="text-align:center;background:gainsboro;color:gray;margin-bottom:7px;text-transform:uppercase;font-weight:bold;padding:4px;border-radius:5px;">Radio Not Initialized</div>
<h1 style="text-align: center;"><span>ESPSomfy RTS</span><span class="button-outline" onclick="general.toggleConfig();" style="float:right;font-size:1.25rem;display:inline-block;vertical-align:middle;width:38px;height:38px;position:relative;padding-top:4px;"><span style="vertical-align:middle;clear:both;text-align:center;display:inline-block;"><i id="icoConfig" class="icss-gear" style=""></i></span></span></h1>
<div id="divConfigPnl" style="display:none;">
<div style="margin-top:-10px;text-align:center;font-size:12px;">
<div id="divWiFiStrength" style="margin-top:-10px;text-align:center;font-size:12px;">
<div style="display:inline-block;vertical-align:middle;">
<div><span style="text-align:right;display:inline-block;width:57px;color:#00bcd4">Network:</span><span id="spanNetworkSSID" style="padding-left:4px;display:inline-block;text-align:left;width:120px;">-------------</span></div>
<div><span style="text-align:right;display:inline-block;width:57px;color:#00bcd4">Channel:</span><span id="spanNetworkChannel" style="padding-left:4px;display:inline-block;text-align:left;width:120px;">--</span></div>
@ -24,6 +24,12 @@
<div style="position:relative;border:solid 1px silver;background-color:cornsilk;padding:2px;font-size:12px;box-shadow: 0 3px 5px rgba(0,0,0,0.19), 0 2px 2px rgba(0,0,0,0.23);float:right;border-radius:4px;margin-left:-4px;"><span id="spanNetworkStrength">---</span><span>dBm</span></div>
</div>
</div>
<div id="divEthernetStatus" style="margin-top:-10px;text-align:center;font-size:12px;display:none;">
<div style="display:inline-block;vertical-align:middle;">
<div><span style="text-align:right;display:inline-block;width:57px;color:#00bcd4">Status:</span><span id="spanEthernetStatus" style="padding-left:4px;display:inline-block;text-align:left;width:120px;">-------------</span></div>
<div><span style="text-align:right;display:inline-block;width:57px;color:#00bcd4">Speed:</span><span id="spanEthernetSpeed" style="padding-left:4px;display:inline-block;text-align:left;width:120px;">--</span></div>
</div>
</div>
<div class="tab-container"><span class="selected" data-grpid="fsGeneralSettings">General</span><span data-grpid="fsWiFiSettings">WiFi</span><span data-grpid="fsMQTTSettings">MQTT</span><span data-grpid="fsSomfySettings">Somfy</span><span data-grpid="fsUpdates">Updates</span></div>
<fieldset id="fsGeneralSettings">
<legend>General Settings</legend>
@ -33,7 +39,7 @@
<label for="fldHostname">Host Name</label>
</div>
<div class="field-group">
<select id="selTimeZone" name="timeZone" type="password" length=32 placeholder="Time Zone" style="width:100%;"></select>
<select id="selTimeZone" name="timeZone" placeholder="Time Zone" style="width:100%;"></select>
<label for="selTimeZone">Time Zone</label>
</div>
<div class="field-group">
@ -57,26 +63,101 @@
</form>
</fieldset>
<fieldset id="fsWiFiSettings" style="display:none;">
<legend>WiFi Settings</legend>
<form method="post" action="/scan">
<div id="divAps" data-lastloaded="0"></div>
<div class="button-container"><button id="btnScanAPs" type="button" onclick="wifi.loadAPs();">Scan</button></div>
</form>
<legend>WiFi/LAN Settings</legend>
<div class="field-group" style="vertical-align:middle;color:#00bcd4;margin-top:-30px;margin-bottom:18px;">
<input id="cbHardwired" name="hardwired" type="checkbox" style="display:inline-block;" onclick="wifi.useEthernetClicked();" />
<label for="cbHardwired" style="display:inline-block;cursor:pointer;">Use Ethernet</label>
<div id="divFallbackWireless" style="display:inline-block;padding-left:7px;">
<input id="cbFallbackWireless" name="fallbackwireless" type="checkbox" style="display:inline-block;" />
<label for="cbFallbackWireless" style="display:inline-block;cursor:pointer;">Fallback to Wireless</label>
</div>
</div>
<div id="divWiFiMode">
<form method="post" action="/scan">
<div id="divAps" data-lastloaded="0" style="border-radius:5px;border:solid 1px #00bcd4;margin-bottom:-10px;"></div>
<div class="button-container"><button id="btnScanAPs" type="button" onclick="wifi.loadAPs();">Scan</button></div>
<div class="field-group">
<input id="fldSsid" name="ssid" type="text" length=32 placeholder="SSID">
<label for="fldSsid">Network SSID</label>
</div>
<div class="field-group">
<input id="fldPassphrase" name="passphrase" type="password" length=32 placeholder="Passphrase">
<label for="fldPassphrase">Passphrase</label>
</div>
</form>
</div>
<div id="divEthernetMode" style="display:none;">
<form method="post" action="/ethernet">
<div class="field-group">
<select id="selETHBoardType" name="ethBoardType" placeholder="Board Type" style="width:100%;" onchange="wifi.onETHBoardTypeChanged(this);"></select>
<label for="selETHBoardType">Board Type</label>
</div>
<div id="divETHSettings">
<div class="field-group" style="width:30%;margin-right:7px;display:inline-block;">
<select id="selETHPhyType" name="ethphytype" placeholder="PHY Type" style="width:100%;"></select>
<label for="selETHPhyType">PHY Chip Type</label>
</div>
<div class="field-group" style="width:20%;display:inline-block;margin-right:7px;">
<select id="selETHAddress" name="address" placeholder="Address" style="width:100%;"></select>
<label for="selETHAddress">Address</label>
</div>
<div class="field-group" style="width:30%;display:inline-block;margin-right:7px;">
<select id="selETHClkMode" name="clkmode" placeholder="Clock Mode" style="width:100%;"></select>
<label for="selETHClkMode">Clock Mode</label>
</div>
<div class="field-group" style="width:20%;display:inline-block;margin-right:7px;">
<select id="selETHPWRPin" name="pwr" placeholder="Power Pin" style="width:100%;"></select>
<label for="selETHPWRPin">Power Pin</label>
</div>
<div class="field-group" style="width:20%;display:inline-block;margin-right:7px;">
<select id="selETHMDCPin" name="mdc" placeholder="MDC Pin" style="width:100%;"></select>
<label for="selETHPMDCPin">MDC Pin</label>
</div>
<div class="field-group" style="width:20%;display:inline-block;margin-right:7px;">
<select id="selETHMDIOPin" name="mdc" placeholder="MDIO Pin" style="width:100%;"></select>
<label for="selETHMDIOPin">MDIO Pin</label>
</div>
<hr />
</div>
<div class="field-group">
<input id="cbUseDHCP" name="dhcp" type="checkbox" style="display:inline-block;" onclick="wifi.onDHCPClicked(this);" checked="checked" />
<label for="cbUseDHCP" style="display:inline-block;cursor:pointer;">Acquire IP Address automatically (DHCP)</label>
</div>
<div id="divStaticIP" style="display:none;">
<div class="field-group">
<input id="fldIPAddress" name="staticIP" type="text" length=32 placeholder="0.0.0.0">
<label for="fldIPAddress">Static IP Address</label>
</div>
<div class="field-group">
<input id="fldSubnetMask" name="subnet" type="text" length=32 placeholder="0.0.0.0">
<label for="fldSubnetMask">Subnet Mask</label>
</div>
<div class="field-group">
<input id="fldGateway" name="gateway" type="text" length=32 placeholder="0.0.0.0">
<label for="fldGateway">Gateway</label>
</div>
<div class="field-group">
<input id="fldDNS1" name="dns1" type="text" length=32 placeholder="0.0.0.0">
<label for="fldDNS1">Domain Name Server 1</label>
</div>
<div class="field-group">
<input id="fldDNS2" name="dns2" type="text" length=32 placeholder="0.0.0.0">
<label for="fldDNS2">Domain Name Server 2</label>
</div>
</div>
</form>
</div>
<form method="post" action="/wifi" style="margin-top:8px;">
<div class="field-group">
<input id="fldSsid" name="ssid" type="text" length=32 placeholder="SSID">
<label for="fldSsid">Network SSID</label>
</div>
<div class="field-group">
<input id="fldPassphrase" name="passphrase" type="password" length=32 placeholder="Passphrase">
<label for="fldPassphrase">Passphrase</label>
</div>
<div class="button-container">
<button id="btnConnectWiFi" type="button" onclick="wifi.connectWiFi();">
<button id="btnSaveNetwork" type="button" onclick="wifi.saveNetwork();">
Save
</button>
</div>
</form>
</fieldset>
<fieldset id="fsMQTTSettings" style="display:none;">
<legend>MQTT Settings</legend>

View file

@ -227,9 +227,6 @@ async function initSockets() {
return value;
});
switch (eventName) {
case 'wifiStrength':
wifi.procWifiStrength(msg);
break;
case 'remoteFrame':
somfy.procRemoteFrame(msg);
break;
@ -240,6 +237,13 @@ async function initSockets() {
break;
case 'shadeAdded':
break;
case 'ethernet':
wifi.procEthernet(msg);
break;
case 'wifiStrength':
wifi.procWifiStrength(msg);
break;
}
} catch (err) {
console.log({ eventName: eventName, data: data, err: err });
@ -274,6 +278,8 @@ async function initSockets() {
}
};
socket.onclose = (evt) => {
procWifiStrength({ ssid: '', channel: -1, strength: -100 });
procEthernet({ connected: '', speed: 0, fullduplex: false });
if (document.getElementsByClassName('socket-wait') === 0)
waitMessage(document.getElementById('divContainer')).classList.add('socket-wait');
if (evt.wasClean) {
@ -328,7 +334,7 @@ async function reopenSocket() {
await initSockets();
}
class General {
appVersion = 'v1.2.3';
appVersion = 'v1.3.0';
reloadApp = false;
async init() {
this.setAppVersion();
@ -552,9 +558,64 @@ class General {
};
var general = new General();
class Wifi {
ethBoardTypes = [{ val: 0, label: 'Custom Config' },
{ val: 1, label: 'WT32-ETH01', clk: 0, ct: 0, addr: 1, pwr: 16, mdc: 23, mdio: 18 },
{ val: 2, label: 'Olimex ESP32-POE', clk: 3, ct: 0, addr: 0, pwr: 12, mdc: 23, mdio: 18 },
{ val: 3, label: 'Olimex ESP32-EVB', clk: 0, ct: 0, addr: 0, pwr: -1, mdc: 23, mdio: 18 },
{ val: 4, label: 'LILYGO T-Internet POE', clk: 3, ct: 0, addr: 0, pwr: 16, mdc: 23, mdio: 18 },
{ val: 5, label: 'wESP32 v7+', clk: 0, ct: 3, addr: 0, pwr: -1, mdc: 16, mdio: 17 },
{ val: 6, label: 'wESP32 < v7', clk: 0, ct: 0, addr: 0, pwr: -1, mdc: 16, mdio: 17 }
];
ethClockModes = [{ val: 0, label: 'GPIO0 IN' }, { val: 1, label: 'GPIO0 OUT' }, { val: 2, label: 'GPIO16 OUT' }, { val: 3, label: 'GPIO17 OUT' }];
ethPhyTypes = [{ val: 0, label: 'LAN8720' }, { val: 1, label: 'TLK110' }, { val: 2, label: 'RTL8201' }, { val: 3, label: 'DP83848' }, { val: 4, label: 'DM9051' }, { val: 5, label: 'KZ8081' }];
init() {
document.getElementById("divNetworkStrength").innerHTML = this.displaySignal(-100);
let addr = [];
this.loadETHDropdown(document.getElementById('selETHClkMode'), this.ethClockModes);
this.loadETHDropdown(document.getElementById('selETHPhyType'), this.ethPhyTypes);
this.loadETHDropdown(document.getElementById('selETHBoardType'), this.ethBoardTypes);
for (let i = 0; i < 32; i++) addr.push({ val: i, label: `PHY ${i}` });
this.loadETHDropdown(document.getElementById('selETHAddress'), addr);
this.loadETHPins(document.getElementById('selETHPWRPin'), 'power');
this.loadETHPins(document.getElementById('selETHMDCPin'), 'mdc', 23);
this.loadETHPins(document.getElementById('selETHMDIOPin'), 'mdio', 18);
if (typeof document.querySelector('div.tab-container > span.selected[data-grpid="fsWiFiSettings"]') !== 'undefined') {
this.loadNetwork();
}
};
loadETHPins(sel, type, selected) {
let arr = [];
switch (type) {
case 'power':
arr.push({ val: -1, label: 'None' });
break;
}
for (let i = 0; i < 36; i++) {
arr.push({ val: i, label: `GPIO ${i}` });
}
this.loadETHDropdown(sel, arr, selected);
};
loadETHDropdown(sel, arr, selected) {
while (sel.firstChild) sel.removeChild(sel.firstChild);
for (let i = 0; i < arr.length; i++) {
let elem = arr[i];
sel.options[sel.options.length] = new Option(elem.label, elem.val, elem.val === selected, elem.val === selected);
}
};
onETHBoardTypeChanged(sel) {
let type = this.ethBoardTypes.find(elem => parseInt(sel.value, 10) === elem.val);
if (typeof type !== 'undefined') {
// Change the values to represent what the board type says.
if(typeof type.ct !== 'undefined') document.getElementById('selETHPhyType').value = type.ct;
if (typeof type.clk !== 'undefined') document.getElementById('selETHClkMode').value = type.clk;
if (typeof type.addr !== 'undefined') document.getElementById('selETHAddress').value = type.addr;
if (typeof type.pwr !== 'undefined') document.getElementById('selETHPWRPin').value = type.pwr;
if (typeof type.mdc !== 'undefined') document.getElementById('selETHMDCPin').value = type.mdc;
if (typeof type.mdio !== 'undefined') document.getElementById('selETHMDIOPin').value = type.mdio;
document.getElementById('divETHSettings').style.display = type.val === 0 ? '' : 'none';
}
};
onDHCPClicked(cb) { document.getElementById('divStaticIP').style.display = cb.checked ? 'none' : ''; };
loadNetwork() {
let overlay = waitMessage(document.getElementById('fsWiFiSettings'));
getJSON('/networksettings', (err, settings) => {
@ -566,10 +627,47 @@ class Wifi {
else {
document.getElementById('fldSsid').value = settings.wifi.ssid;
document.getElementById('fldPassphrase').value = settings.wifi.passphrase;
document.getElementById('selETHBoardType').value = settings.ethernet.boardType;
document.getElementById('cbUseDHCP').checked = settings.ethernet.dhcp;
document.getElementById('cbHardwired').checked = settings.connType >= 2;
document.getElementById('cbFallbackWireless').checked = settings.connType === 3;
document.getElementById('selETHPhyType').value = settings.ethernet.phyType;
document.getElementById('selETHAddress').value = settings.ethernet.phyAddress;
document.getElementById('selETHClkMode').value = settings.ethernet.CLKMode;
document.getElementById('selETHPWRPin').value = settings.ethernet.PWRPin;
document.getElementById('selETHMDCPin').value = settings.ethernet.MDCPin;
document.getElementById('selETHMDIOPin').value = settings.ethernet.MDIOPin;
document.getElementById('fldIPAddress').value = settings.ethernet.ip;
document.getElementById('fldSubnetMask').value = settings.ethernet.subnet;
document.getElementById('fldGateway').value = settings.ethernet.gateway;
document.getElementById('fldDNS1').value = settings.ethernet.dns1;
document.getElementById('fldDNS2').value = settings.ethernet.dns2;
if (settings.connType >= 2) {
document.getElementById('divWiFiMode').style.display = 'none';
document.getElementById('divEthernetMode').style.display = '';
document.getElementById('divFallbackWireless').style.display = 'inline-block';
}
else {
document.getElementById('divWiFiMode').style.display = '';
document.getElementById('divEthernetMode').style.display = 'none';
document.getElementById('divFallbackWireless').style.display = 'none';
}
if (settings.ethernet.boardType === 0) {
document.getElementById('divETHSettings').style.display = '';
}
else {
document.getElementById('divETHSettings').style.display = 'none';
}
}
});
};
useEthernetClicked() {
let useEthernet = document.getElementById('cbHardwired').checked;
document.getElementById('divWiFiMode').style.display = useEthernet ? 'none' : '';
document.getElementById('divEthernetMode').style.display = useEthernet ? '' : 'none';
document.getElementById('divFallbackWireless').style.display = useEthernet ? 'inline-block' : 'none';
}
async loadAPs() {
if (document.getElementById('btnScanAPs').classList.contains('disabled')) return;
document.getElementById('divAps').innerHTML = '<div style="display:flex;justify-content:center;align-items:center;"><div class="lds-roller"><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div></div></div>';
@ -636,6 +734,81 @@ class Wifi {
displaySignal(sig) {
return `<div class="signal waveStrength-${this.calcWaveStrength(sig)}"><div class="wv4 wave"><div class="wv3 wave"><div class="wv2 wave"><div class="wv1 wave"><div class="wv0 wave"></div></div></div></div></div></div>`;
};
saveNetwork() {
let obj = {
connType: document.getElementById('cbHardwired').checked ? document.getElementById('cbFallbackWireless').checked ? 3 : 2 : 1,
wifi: {},
ethernet: {}
};
if (obj.connType >= 2) {
// We are connecting to a LAN but we need the user to be sure about this since
// the information needs to be correct. Incorrect settings can destroy the board.
obj.ethernet = {
boardType: parseInt(document.getElementById('selETHBoardType').value, 10),
phyType: parseInt(document.getElementById('selETHPhyType').value, 10),
phyAddress: parseInt(document.getElementById('selETHAddress').value, 10),
dhcp: document.getElementById('cbUseDHCP').checked,
CLKMode: parseInt(document.getElementById('selETHClkMode').value, 10),
PWRPin: parseInt(document.getElementById('selETHPWRPin').value, 10),
MDCPin: parseInt(document.getElementById('selETHMDCPin').value, 10),
MDIOPin: parseInt(document.getElementById('selETHMDIOPin').value, 10),
ip: document.getElementById('fldIPAddress').value,
subnet: document.getElementById('fldSubnetMask').value,
gateway: document.getElementById('fldGateway').value,
dns1: document.getElementById('fldDNS1').value,
dns2: document.getElementById('fldDNS2').value
}
let boardType = this.ethBoardTypes.find(elem => obj.ethernet.boardType === elem.val);
let phyType = this.ethPhyTypes.find(elem => obj.ethernet.phyType === elem.val);
let clkMode = this.ethClockModes.find(elem => obj.ethernet.CLKMode === elem.val);
let div = document.createElement('div');
let html = `<form id="frmSetLAN"><div id="divLanSettings" class="instructions" style="display:block;height:auto;min-height:100%">`;
html += '<div style="width:100%;color:red;text-align:center;font-weight:bold;"><span style="background:yellow;padding:10px;display:inline-block;border-radius:5px;background:white;">BEWARE ... WARNING ... DANGER<span></div>';
html += '<hr style="width:100%;margin:0px;"></hr>';
html += '<p style="font-size:14px;">Incorrect Ethernet settings can damage your ESP32. Please verify the settings below and ensure they match the manufacturer spec sheet.</p>';
html += '<p style="font-size:14px;">If you are unsure do not press the Red button and press the Green button. If any of the settings are incorrect please use the Custom Board type and set them to the correct values.';
html += '<hr/><div>';
html += `<div class="eth-setting-line"><label>Board Type</label><span>${boardType.label} [${boardType.val}]</span></div>`;
html += `<div class="eth-setting-line"><label>PHY Chip Type</label><span>${phyType.label} [${phyType.val}]</span></div>`;
html += `<div class="eth-setting-line"><label>PHY Address</label><span>${obj.ethernet.phyAddress}</span ></div >`;
html += `<div class="eth-setting-line"><label>Clock Mode</label><span>${clkMode.label} [${clkMode.val}]</span></div >`;
html += `<div class="eth-setting-line"><label>Power Pin</label><span>${obj.ethernet.PWRPin === -1 ? 'None' : obj.ethernet.PWRPin}</span></div>`;
html += `<div class="eth-setting-line"><label>MDC Pin</label><span>${obj.ethernet.MDCPin}</span></div>`;
html += `<div class="eth-setting-line"><label>MDIO Pin</label><span>${obj.ethernet.MDIOPin}</span></div>`;
html += '</div>'
html += `<div class="button-container">`
html += `<button id="btnSaveEthernet" type="button" style="padding-left:20px;padding-right:20px;display:inline-block;background:orangered;">Save Ethernet Settings</button>`
html += `<button id="btnCancel" type="button" style="padding-left:20px;padding-right:20px;display:inline-block;background:lawngreen;color:gray" onclick="document.getElementById('frmSetLAN').remove();">Cancel</button>`
html += `</div><form>`;
div.innerHTML = html;
document.getElementById('divContainer').appendChild(div);
div.querySelector('#btnSaveEthernet').addEventListener('click', (el, event) => {
console.log(obj);
document.getElementById('frmSetLAN').remove();
this.sendNetworkSettings(obj);
});
}
else {
obj.wifi = {
ssid: document.getElementsByName('ssid')[0].value,
passphrase: document.getElementsByName('passphrase')[0].value
};
this.sendNetworkSettings(obj);
}
}
sendNetworkSettings(obj) {
if (document.getElementById('btnSaveNetwork').classList.contains('disabled')) return;
document.getElementById('btnSaveNetwork').classList.add('disabled');
let overlay = waitMessage(document.getElementById('divContainer'));
putJSON('/setNetwork', obj, (err, response) => {
overlay.remove();
document.getElementById('btnSaveNetwork').classList.remove('disabled');
console.log(response);
});
}
connectWiFi() {
if (document.getElementById('btnConnectWiFi').classList.contains('disabled')) return;
document.getElementById('btnConnectWiFi').classList.add('disabled');
@ -663,6 +836,13 @@ class Wifi {
}
document.getElementById('spanNetworkStrength').innerHTML = (isNaN(strength.strength) || strength.strength <= -100) ? '----' : strength.strength;
}
procEthernet(ethernet) {
console.log(ethernet);
document.getElementById('divEthernetStatus').style.display = ethernet.connected ? '' : 'none';
document.getElementById('divWiFiStrength').style.display = ethernet.connected ? 'none' : '';
document.getElementById('spanEthernetStatus').innerHTML = ethernet.connected ? 'Connected' : 'Disconnected';
document.getElementById('spanEthernetSpeed').innerHTML = !ethernet.connected ? '--------' : `${ethernet.speed}Mbps ${ethernet.fullduplex ? 'Full-duplex' : 'Half-duplex'}`;
}
};
var wifi = new Wifi();
class Somfy {
@ -1569,7 +1749,7 @@ class Firmware {
}
break;
case '/updateFirmware':
if (filename.indexOf('.ino.esp') === -1 || !filename.endsWith('.bin')) {
if (filename.indexOf('.ino.') === -1 || !filename.endsWith('.bin')) {
errorMessage(el, 'This file is not a valid firmware binary file.');
return;
}

View file

@ -630,4 +630,20 @@ div.waitoverlay > .lds-roller {
}
.shade-positioner label .shade-target {
display:inline-block;
}
div.eth-setting-line {
font-size:12px;
padding-top:0px;
padding-bottom:0px;
}
div.eth-setting-line span {
margin-left:7px;
}
div.eth-setting-line label {
margin-left: 40px;
display:inline-block;
width: 90px;
text-align:right;
color:mediumspringgreen;
}