Browse Source

Allow static IP

fastled
Xose Pérez 7 years ago
parent
commit
cafb6eadaa
6 changed files with 213 additions and 80 deletions
  1. +1
    -1
      code/espurna/config/general.h
  2. +40
    -2
      code/espurna/web.ino
  3. +18
    -3
      code/espurna/wifi.ino
  4. +20
    -2
      code/html/custom.css
  5. +54
    -6
      code/html/custom.js
  6. +80
    -66
      code/html/index.html

+ 1
- 1
code/espurna/config/general.h View File

@ -41,7 +41,7 @@
// -----------------------------------------------------------------------------
#define WIFI_RECONNECT_INTERVAL 300000
#define WIFI_MAX_NETWORKS 3
#define WIFI_MAX_NETWORKS 5
#define ADMIN_PASS "fibonacci"
#define HTTP_USERNAME "admin"
#define WS_BUFFER_SIZE 5


+ 40
- 2
code/espurna/web.ino View File

@ -161,6 +161,18 @@ void _wsParse(uint32_t client_id, uint8_t * payload, size_t length) {
}
if (key == "pass") {
key = key + String(network);
}
if (key == "ip") {
key = key + String(network);
}
if (key == "gw") {
key = key + String(network);
}
if (key == "mask") {
key = key + String(network);
}
if (key == "dns") {
key = key + String(network);
++network;
}
@ -184,6 +196,26 @@ void _wsParse(uint32_t client_id, uint8_t * payload, size_t length) {
}
#endif
// Clean wifi networks
for (int i = 0; i < network; i++) {
if (getSetting("pass" + String(i)).length() == 0) delSetting("pass" + String(i));
if (getSetting("ip" + String(i)).length() == 0) delSetting("ip" + String(i));
if (getSetting("gw" + String(i)).length() == 0) delSetting("gw" + String(i));
if (getSetting("mask" + String(i)).length() == 0) delSetting("mask" + String(i));
if (getSetting("dns" + String(i)).length() == 0) delSetting("dns" + String(i));
}
for (int i = network; i<WIFI_MAX_NETWORKS; i++) {
if (getSetting("ssid" + String(i)).length() > 0) {
dirty = true;
}
delSetting("ssid" + String(i));
delSetting("pass" + String(i));
delSetting("ip" + String(i));
delSetting("gw" + String(i));
delSetting("mask" + String(i));
delSetting("dns" + String(i));
}
// Save settings
if (dirty) {
@ -239,7 +271,7 @@ void _wsStart(uint32_t client_id) {
root["device"] = String(DEVICE);
root["hostname"] = getSetting("hostname", HOSTNAME);
root["network"] = getNetwork();
root["ip"] = getIP();
root["deviceip"] = getIP();
root["mqttStatus"] = mqttConnected();
root["mqttServer"] = getSetting("mqttServer", MQTT_SERVER);
@ -308,11 +340,17 @@ void _wsStart(uint32_t client_id) {
root["powActivePower"] = getActivePower();
#endif
root["maxNetworks"] = WIFI_MAX_NETWORKS;
JsonArray& wifi = root.createNestedArray("wifi");
for (byte i=0; i<3; i++) {
for (byte i=0; i<WIFI_MAX_NETWORKS; i++) {
if (getSetting("ssid" + String(i)).length() == 0) break;
JsonObject& network = wifi.createNestedObject();
network["ssid"] = getSetting("ssid" + String(i));
network["pass"] = getSetting("pass" + String(i));
network["ip"] = getSetting("ip" + String(i));
network["gw"] = getSetting("gw" + String(i));
network["mask"] = getSetting("mask" + String(i));
network["dns"] = getSetting("dns" + String(i));
}
String output;


+ 18
- 3
code/espurna/wifi.ino View File

@ -52,9 +52,24 @@ void wifiConfigure() {
jw.setSoftAP(getSetting("hostname", HOSTNAME).c_str(), getSetting("adminPass", ADMIN_PASS).c_str());
jw.setAPMode(AP_MODE_ALONE);
jw.cleanNetworks();
if (getSetting("ssid0").length() > 0) jw.addNetwork(getSetting("ssid0").c_str(), getSetting("pass0").c_str());
if (getSetting("ssid1").length() > 0) jw.addNetwork(getSetting("ssid1").c_str(), getSetting("pass1").c_str());
if (getSetting("ssid2").length() > 0) jw.addNetwork(getSetting("ssid2").c_str(), getSetting("pass2").c_str());
for (int i = 0; i< WIFI_MAX_NETWORKS; i++) {
if (getSetting("ssid" + String(i)).length() == 0) break;
if (getSetting("ip" + String(i)).length() == 0) {
jw.addNetwork(
getSetting("ssid" + String(i)).c_str(),
getSetting("pass" + String(i)).c_str()
);
} else {
jw.addNetwork(
getSetting("ssid" + String(i)).c_str(),
getSetting("pass" + String(i)).c_str(),
getSetting("ip" + String(i)).c_str(),
getSetting("gw" + String(i)).c_str(),
getSetting("mask" + String(i)).c_str(),
getSetting("dns" + String(i)).c_str()
);
}
}
}
void wifiSetup() {


+ 20
- 2
code/html/custom.css View File

@ -41,6 +41,15 @@
background: rgb(0, 202, 0);
margin-left: 5px;
}
.button-add-network {
background: rgb(28, 184, 65);
}
.button-del-network {
background: rgb(202, 60, 60);
}
.button-more-network {
background: rgb(223, 117, 20);
}
.pure-g {
margin-bottom: 20px;
}
@ -57,14 +66,23 @@ div.hint {
font-size: 80%;
color: #ccc;
}
.break {
margin-top: 5px;
}
#networks .pure-g {
padding-bottom: 10px;
margin-bottom: 5px;
border-bottom: 2px dashed #e5e5e5;
}
#networks div.more {
display: none;
}
.module {
display: none;
}
.template {
display: none;
}
.pure-form .center {
margin: .5em 0 .2em;
}

+ 54
- 6
code/html/custom.js View File

@ -1,5 +1,6 @@
var websock;
var password = false;
var maxNetworks;
// http://www.the-art-of-web.com/javascript/validate-password/
function checkPassword(str) {
@ -132,6 +133,38 @@ function createIdxs(count) {
}
function delNetwork() {
var parent = $(this).parents(".pure-g");
$(parent).remove();
}
function moreNetwork() {
var parent = $(this).parents(".pure-g");
$("div.more", parent).toggle();
}
function addNetwork() {
var numNetworks = $("#networks > div").length;
if (numNetworks >= maxNetworks) {
alert("Max number of networks reached");
return;
}
var tabindex = 200 + numNetworks * 10;
var template = $("#networkTemplate").children();
var line = $(template).clone();
$(line).find("input").each(function() {
$(this).attr("tabindex", tabindex++);
});
$(line).find(".button-del-network").on('click', delNetwork);
$(line).find(".button-more-network").on('click', moreNetwork);
line.appendTo("#networks");
return line;
}
function processData(data) {
// title
@ -178,17 +211,32 @@ function processData(data) {
}
if (key == "maxNetworks") {
maxNetworks = parseInt(data.maxNetworks);
return;
}
// Wifi
if (key == "wifi") {
var groups = $("#panel-wifi .pure-g");
for (var i in data.wifi) {
var networks = data.wifi;
for (var i in networks) {
// add a new row
var line = addNetwork();
// fill in the blanks
var wifi = data.wifi[i];
Object.keys(wifi).forEach(function(key) {
var id = "input[name=" + key + "]";
if ($(id, groups[i]).length) $(id, groups[i]).val(wifi[key]);
var element = $("input[name=" + key + "]", line);
if (element.length) element.val(wifi[key]);
});
};
}
return;
}
// Relay status
@ -233,7 +281,6 @@ function processData(data) {
// Enable options
if (key.endsWith("Visible")) {
var module = key.slice(0,-7);
console.log(module);
$(".module-" + module).show();
return;
}
@ -305,6 +352,7 @@ function init() {
$(".button-reconnect").on('click', doReconnect);
$(".button-apikey").on('click', doGenerateAPIKey);
$(".pure-menu-link").on('click', showPanel);
$(".button-add-network").on('click', addNetwork);
$.ajax({
'method': 'GET',


+ 80
- 66
code/html/index.html View File

@ -111,8 +111,8 @@
</div>
<div class="pure-g">
<label class="pure-u-1 pure-u-sm-1-4" for="ip">IP</label>
<input class="pure-u-1 pure-u-sm-3-4" type="text" name="ip" readonly />
<label class="pure-u-1 pure-u-sm-1-4" for="deviceip">IP</label>
<input class="pure-u-1 pure-u-sm-3-4" type="text" name="deviceip" readonly />
</div>
<div class="pure-g">
@ -143,13 +143,6 @@
<div id="relays">
</div>
<div id="relayTemplate" class="template">
<div class="pure-g">
<label class="pure-u-1 pure-u-sm-1-4">Relay<span class="relay_id"></span> Status</label>
<div class="pure-u-1 pure-u-sm-1-4"><input type="checkbox" class="relayStatus" data="0" /></div>
</div>
</div>
</fieldset>
</form>
@ -192,7 +185,7 @@
<div class="pure-g module module-multirelay">
<label class="pure-u-1 pure-u-md-1-4" for="relaySync">Relay sync mode</label>
<div class="pure-u-1 pure-u-md-3-4">
<select name="relaySync" class="pure-u-1-2" tabindex="2">
<select name="relaySync" class="pure-u-1-2" tabindex="3">
<option value="0">No synchonisation</a>
<option value="1">Zero or one relays active</a>
<option value="2">One and just one relay active</a>
@ -225,7 +218,7 @@
<div class="pure-g">
<label class="pure-u-1 pure-u-md-1-4" for="adminPass1">Admin password</label>
<input name="adminPass1" class="pure-u-1 pure-u-md-3-4" type="password" tabindex="3" />
<input name="adminPass1" class="pure-u-1 pure-u-md-3-4" type="password" tabindex="11" />
<div class="pure-u-0 pure-u-md-1-4">&nbsp;</div>
<div class="pure-u-1 pure-u-md-3-4 hint">
The administrator password is used to access this web interface (user 'admin'), but also to connect to the device when in AP mode or to flash a new firmware over-the-air (OTA).<br />
@ -234,7 +227,7 @@
<div class="pure-g">
<label class="pure-u-1 pure-u-md-1-4" for="adminPass2">Admin password (repeat)</label>
<input name="adminPass2" class="pure-u-1 pure-u-md-3-4" type="password" tabindex="3" />
<input name="adminPass2" class="pure-u-1 pure-u-md-3-4" type="password" tabindex="12" />
</div>
<div class="pure-g">
@ -244,7 +237,7 @@
<div class="pure-g">
<label class="pure-u-1 pure-u-md-1-4" for="apiKey">HTTP API Key</label>
<input name="apiKey" class="pure-u-3-4 pure-u-md-1-2" type="text" tabindex="4" />
<input name="apiKey" class="pure-u-3-4 pure-u-md-1-2" type="text" tabindex="13" />
<div class=" pure-u-1-4 pure-u-md-1-4"><button class="pure-button button-apikey pure-u-23-24">Generate</button></div>
<div class="pure-u-0 pure-u-md-1-4">&nbsp;</div>
<div class="pure-u-1 pure-u-md-3-4 hint">This is the key you will have to pass with every HTTP request to the API, either to get or write values.</div>
@ -258,51 +251,17 @@
<div class="header">
<h1>WIFI</h1>
<h2>You can configure up to 3 different WiFi networks. The device will try to connect in order of signal strength.</h2>
<h2>You can configure up to 5 different WiFi networks. The device will try to connect in order of signal strength.</h2>
</div>
<div class="page">
<fieldset>
<legend>First network</legend>
<div class="pure-g">
<div class="pure-u-1 pure-u-md-1-2">
<label for="ssid">SSID</label>
<input type="text" class="pure-u-23-24" tabindex="10" name="ssid" />
</div>
<div class="pure-u-1 pure-u-md-1-2">
<label for="pass">Password</label>
<input type="text" class="pure-u-23-24" tabindex="11" name="pass" />
</div>
</div>
<legend>Second network</legend>
<div class="pure-g">
<div class="pure-u-1 pure-u-md-1-2">
<label for="ssid">SSID</label>
<input type="text" class="pure-u-23-24" tabindex="12" name="ssid" />
</div>
<div class="pure-u-1 pure-u-md-1-2">
<label for="pass">Password</label>
<input type="text" class="pure-u-23-24" tabindex="13" name="pass" />
</div>
<div id="networks">
</div>
<legend>Third network</legend>
<div class="pure-g">
<div class="pure-u-1 pure-u-md-1-2">
<label for="ssid">SSID</label>
<input type="text" class="pure-u-23-24" tabindex="14" name="ssid" />
</div>
<div class="pure-u-1 pure-u-md-1-2">
<label for="pass">Password</label>
<input type="text" class="pure-u-23-24" tabindex="15" name="pass" />
</div>
</div>
<button type="button" class="pure-button button-add-network">Add network</button>
</fieldset>
</div>
@ -321,27 +280,27 @@
<div class="pure-g">
<label class="pure-u-1 pure-u-md-1-4" for="mqttServer">MQTT Server</label>
<input class="pure-u-1 pure-u-md-3-4" name="mqttServer" type="text" size="20" tabindex="10" placeholder="MQTT Server" />
<input class="pure-u-1 pure-u-md-3-4" name="mqttServer" type="text" size="20" tabindex="21" placeholder="MQTT Server" />
</div>
<div class="pure-g">
<label class="pure-u-1 pure-u-md-1-4" for="mqttPort">MQTT Port</label>
<input class="pure-u-1 pure-u-md-3-4" name="mqttPort" type="text" size="6" tabindex="11" placeholder="1883" />
<input class="pure-u-1 pure-u-md-3-4" name="mqttPort" type="text" size="6" tabindex="22" placeholder="1883" />
</div>
<div class="pure-g">
<label class="pure-u-1 pure-u-md-1-4" for="mqttUser">MQTT User</label>
<input class="pure-u-1 pure-u-md-3-4" name="mqttUser" type="text" size="20" tabindex="12" placeholder="Leave blank if no user/pass" />
<input class="pure-u-1 pure-u-md-3-4" name="mqttUser" type="text" size="20" tabindex="23" placeholder="Leave blank if no user/pass" />
</div>
<div class="pure-g">
<label class="pure-u-1 pure-u-md-1-4" for="mqttPassword">MQTT Password</label>
<input class="pure-u-1 pure-u-md-3-4" name="mqttPassword" type="text" size="20" tabindex="13" placeholder="Leave blank if no user/pass" />
<input class="pure-u-1 pure-u-md-3-4" name="mqttPassword" type="text" size="20" tabindex="24" placeholder="Leave blank if no user/pass" />
</div>
<div class="pure-g">
<label class="pure-u-1 pure-u-md-1-4" for="mqttTopic">MQTT Root Topic</label>
<input class="pure-u-1 pure-u-md-3-4" name="mqttTopic" type="text" size="20" tabindex="14" />
<input class="pure-u-1 pure-u-md-3-4" name="mqttTopic" type="text" size="20" tabindex="25" />
<div class="pure-u-0 pure-u-md-1-4">&nbsp;</div>
<div class="pure-u-1 pure-u-md-3-4 hint">This is the root topic for this device. The {identifier} placeholder will be replaces by the device hostname.<br />
- <strong>&lt;root&gt;/relay/#</strong> Send a 0 or a 1 as a payload to this topic to switch it on or off. You can also send a 2 to toggle its current state. Replace # with the relay ID (starting from 0). If the board has only one relay it will be 0.<br />
@ -371,25 +330,17 @@
<div class="pure-g">
<label class="pure-u-1 pure-u-md-1-4" for="dczTopicIn">Domoticz IN Topic</label>
<input class="pure-u-1 pure-u-md-3-4" name="dczTopicIn" type="text" tabindex="41" placeholder="domoticz/in" />
<input class="pure-u-1 pure-u-md-3-4" name="dczTopicIn" type="text" tabindex="31" placeholder="domoticz/in" />
</div>
<div class="pure-g">
<label class="pure-u-1 pure-u-md-1-4" for="dczTopicOut">Domoticz OUT Topic</label>
<input class="pure-u-1 pure-u-md-3-4" name="dczTopicOut" type="text" tabindex="42" placeholder="domoticz/out" />
<input class="pure-u-1 pure-u-md-3-4" name="dczTopicOut" type="text" tabindex="32" placeholder="domoticz/out" />
</div>
<div id="idxs">
</div>
<div id="idxTemplate" class="template">
<div class="pure-g">
<label class="pure-u-1 pure-u-sm-1-4">Relay<span class="id"></span> IDX</label>
<div class="pure-u-1 pure-u-sm-1-8"><input class="pure-u-sm-23-24 dczIdx" name="dczIdx" type="number" min="0" tabindex="0" data="0" /></div>
<div class="pure-u-1 pure-u-sm-5-8 hint center">Set to 0 to disable notifications.</div>
</div>
</div>
</fieldset>
</div>
@ -410,7 +361,7 @@
<div class="pure-g">
<label class="pure-u-1 pure-u-md-1-4" for="powExpectedPower">AC RMS Active Power</label>
<input class="pure-u-1 pure-u-md-3-4 powExpected" name="powExpectedPower" type="text" size="8" tabindex="50" placeholder="0" />
<input class="pure-u-1 pure-u-md-3-4 powExpected" name="powExpectedPower" type="text" size="8" tabindex="41" placeholder="0" />
<div class="pure-u-0 pure-u-md-1-4">&nbsp;</div>
<div class="pure-u-1 pure-u-md-3-4 hint">If you are using a pure resistive load like a bulb this will be writen on it, otherwise use a socket multimeter to get this value.</div>
</div>
@ -425,6 +376,69 @@
</div> <!-- layout -->
<!-- Templates -->
<div id="networkTemplate" class="template">
<div class="pure-g">
<label class="pure-u-md-1-6 pure-u-1-4" for="ssid">Network SSID</label>
<div class="pure-u-md-3-4 pure-u-5-8"><input name="ssid" type="text" class="pure-u-23-24" value="" size="8" tabindex="0" placeholder="Network SSID" required /></div>
<div class="pure-u-md-1-12 pure-u-1-8"><button type="button" class="pure-button button-more-network pure-u-1">...</button></div>
<div class="more">
<div class="break" />
<label class="pure-u-md-1-6 pure-u-1-4" for="pass">Password</label>
<input class="pure-u-md-5-6 pure-u-3-4" name="pass" type="password" value="" tabindex="0" />
<div class="break" />
<label class="pure-u-md-1-6 pure-u-1-4" for="ip">Static IP</label>
<input class="pure-u-md-5-6 pure-u-3-4" name="ip" type="text" value="" size="15" tabindex="0" />
<div class="pure-u-md-1-6 pure-u-1-4"></div>
<div class="pure-u-md-5-6 pure-u-3-4 hint">Leave empty for DNS negotiation</div>
<label class="pure-u-md-1-6 pure-u-1-4" for="gw">Gateway IP</label>
<input class="pure-u-md-5-6 pure-u-3-4" name="gw" type="text" value="" size="15" tabindex="0" />
<div class="pure-u-md-1-6 pure-u-1-4"></div>
<div class="pure-u-md-5-6 pure-u-3-4 hint">Set when using a static IP</div>
<label class="pure-u-md-1-6 pure-u-1-4" for="mask">Network Mask</label>
<input class="pure-u-md-5-6 pure-u-3-4" name="mask" type="text" value="" size="15" tabindex="0" placeholder="255.255.255.0" />
<div class="pure-u-md-1-6 pure-u-1-4"></div>
<div class="pure-u-md-5-6 pure-u-3-4 hint">Usually 255.255.255.0 for /24 networks</div>
<label class="pure-u-md-1-6 pure-u-1-4" for="dns">DNS IP</label>
<input class="pure-u-md-5-6 pure-u-3-4" name="dns" type="text" value="" size="15" tabindex="0" placeholder="8.8.8.8" />
<div class="pure-u-md-1-6 pure-u-1-4"></div>
<div class="pure-u-md-5-6 pure-u-3-4 hint">Set the Domain Name Server IP to use when using a static IP</div>
<div class="pure-u-md-1-6 pure-u-1-4"></div>
<div class="pure-u-md-1-6 pure-u-1-4"><button type="button" class="pure-button button-del-network pure-u-5-6 pure-u-md-5-6">Del</button></div>
</div>
</div>
</div>
<div id="relayTemplate" class="template">
<div class="pure-g">
<label class="pure-u-1 pure-u-sm-1-4">Relay<span class="relay_id"></span> Status</label>
<div class="pure-u-1 pure-u-sm-1-4"><input type="checkbox" class="relayStatus" data="0" /></div>
</div>
</div>
<div id="idxTemplate" class="template">
<div class="pure-g">
<label class="pure-u-1 pure-u-sm-1-4">Relay<span class="id"></span> IDX</label>
<div class="pure-u-1 pure-u-sm-1-8"><input class="pure-u-sm-23-24 dczIdx" name="dczIdx" type="number" min="0" tabindex="0" data="0" /></div>
<div class="pure-u-1 pure-u-sm-5-8 hint center">Set to 0 to disable notifications.</div>
</div>
</div>
</body>
<!-- build:js script.js -->


Loading…
Cancel
Save