Browse Source

New web design, storing last relay status in EEPROM

fastled
Xose Pérez 8 years ago
parent
commit
88bf902e45
5 changed files with 341 additions and 247 deletions
  1. +0
    -127
      code/data/index.css
  2. +245
    -98
      code/data/index.html
  3. +1
    -0
      code/data/spectre.min.css
  4. +1
    -1
      code/platformio.ini
  5. +94
    -21
      code/src/code.ino

+ 0
- 127
code/data/index.css View File

@ -1,127 +0,0 @@
* {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
body {
padding: 20px;
width: 600px;
}
span.status,
span.network,
span.ip {
font-weight: bold;
}
form header {
margin: 0 0 20px 0;
}
form header div {
font-size: 90%;
color: #999;
}
form header h2 {
margin: 0 0 5px 0;
}
form header img {
margin: 0 0 10px 0;
}
form > div {
clear: both;
overflow: hidden;
padding: 1px;
margin: 0 0 10px 0;
}
form > div > fieldset > div > div {
margin: 0 0 5px 0;
}
form > div > label,
legend {
width: 30%;
float: left;
padding-right: 10px;
}
form > div > div,
form > div > fieldset > div {
width: 70%;
float: right;
}
form > div > fieldset label {
font-size: 90%;
}
fieldset {
border: 0;
padding: 0;
}
input[type=text],
input[type=email],
input[type=url],
input[type=password],
textarea {
width: 100%;
border-top: 1px solid #ccc;
border-left: 1px solid #ccc;
border-right: 1px solid #eee;
border-bottom: 1px solid #eee;
}
input[type=text],
input[type=email],
input[type=url],
input[type=password] {
width: 100%;
}
input[type=text]:focus,
input[type=email]:focus,
input[type=url]:focus,
input[type=password]:focus,
textarea:focus {
outline: 0;
border-color: #4697e4;
}
@media (max-width: 600px) {
body {
width: 100%;
}
form > div {
margin: 0 0 15px 0;
}
form > div > label,
legend {
width: 100%;
float: none;
margin: 0 0 5px 0;
}
form > div > div,
form > div > fieldset > div {
width: 100%;
float: none;
}
input[type=text],
input[type=email],
input[type=url],
input[type=password],
textarea,
select {
width: 100%;
}
}

+ 245
- 98
code/data/index.html View File

@ -1,29 +1,54 @@
<!DOCTYPE html>
<html>
<head>
<title>{appname} - Configuration</title>
<title>{appname}</title>
<meta charset="utf-8" />
<link rel="stylesheet" href="index.css" />
<link rel="stylesheet" href="spectre.min.css" />
<script src="jquery-1.12.3.min.js"></script>
<style>
html, body {
font-size: 12px;
margin: 0;
padding: 0;
width: 100%;
height: 100%;
}
div.page {
display: none;
}
.bg-grey {
background-color: #efefef;
padding: 1rem;
border-radius: .3rem;
}
div.hint {
background-color: #efefef;
padding: 2rem;
margin: 20px 0;
border-left: 2px solid blue;
}
</style>
<script>
$(function() {
var updateInterval = 1000;
var timer = null;
$("#config").submit(function(event) {
$(":submit").prop("value", "Wait...").attr("disabled", true);
$("form").submit(function(event) {
button = $(":submit", this);
button.addClass("loading");
$.ajax({
'method': 'POST',
'url': '/save',
'dataType': 'json',
'data': $(this).serializeArray()
}).done(function(data) {
$(":submit").prop("value", "Connect").removeAttr("disabled");
button.removeClass("loading");
}).fail(function() {
$(":submit").prop("value", "Connect").removeAttr("disabled");
button.removeClass("loading");
});
event.preventDefault();
setTimeout(update, 200);
});
function update() {
@ -32,20 +57,52 @@
'url': '/status',
'dataType': 'json'
}).done(function(data) {
$("span.device").html(data.device);
$("span.network").html(data.network.toUpperCase());
$("span.ip").html(data.ip);
$("span.mqtt").html(data.mqtt ? "CONNECTED" : "NOT CONNECTED");
$("span.relay").html(data.relay ? "ON" : "OFF");
updateInterval = parseInt(data.interval);
setTimeout(update, updateInterval);
}).fail(function() {
setTimeout(update, updateInterval);
$("#device").val(data.device);
$("#network").val(data.network.toUpperCase());
$("#ip").val(data.ip);
$("#mqtt").val(data.mqtt ? "CONNECTED" : "NOT CONNECTED");
if (data.relay) {
$("#relay").addClass('btn-primary').html("ON");
$("#status").val(1);
} else {
$("#relay").removeClass('btn-primary').html("OFF");
$("#status").val(0);
}
});
}
update();
$("#btn-admin").click(function() {
$("#panel-admin").show();
$("#panel-status").hide();
$("#btn-admin").addClass('btn-primary');
$("#btn-status").removeClass('btn-primary');
});
$("#btn-status").click(function() {
$("#panel-admin").hide();
$("#panel-status").show();
$("#btn-admin").removeClass('btn-primary');
$("#btn-status").addClass('btn-primary');
});
$("#relay").click(function(event) {
var status = parseInt($("#status").val());
if (status == 1) {
$.ajax({'method': 'GET', 'url': '/relay/off'});
} else {
$.ajax({'method': 'GET', 'url': '/relay/on'});
}
setTimeout(update, 200);
event.preventDefault();
})
function init() {
update();
timer = setInterval(update, {updateInterval});
$("[name='rfDevice']").val({rfDevice});
}
init();
});
@ -53,105 +110,195 @@
</head>
<body>
<form id="config" action="/" method="post">
<div class="container">
<header>
<h2>{appname} - Configuration</h2>
<div>This form lets you define the WIFI network this device should try to join.</div>
<header class="navbar bg-grey">
<section class="navbar-section">
<a href="#" class="navbar-brand">{appname}</a>
</section>
<section class="navbar-section">
<button class="btn" id="btn-admin">Administration</button>
<button class="btn btn-primary" id="btn-status">Status</button>
</section>
</header>
<div>
<p>Device: <span class="device"></span></p>
<p>Network: <span class="network"></span></p>
<p>IP: <span class="ip"></span></p>
<p>MQTT: <span class="mqtt"></span></p>
<p>Relay: <span class="relay"></span></p>
</div>
<div class="page" id="panel-status" style="display: block;">
<div>
<label class="desc" for="ssid0">Network SSID 0</label>
<div>
<input id="ssid0" name="ssid0" type="text" class="field text fn" value="{ssid0}" size="8" tabindex="1">
<div class="columns">
<div class="column col-12">
<form class="form-horizontal">
<div class="form-group">
<div class="col-xs-3">
<label class="form-label" for="device">Device</label>
</div>
<div class="col-xs-9">
<input type="text" class="form-input" id="device" disabled>
</div>
</div>
<div class="form-group">
<div class="col-xs-3">
<label class="form-label" for="network">Network</label>
</div>
<div class="col-xs-9">
<input type="text" class="form-input" id="network" disabled>
</div>
</div>
<div class="form-group">
<div class="col-xs-3">
<label class="form-label" for="ip">IP</label>
</div>
<div class="col-xs-9">
<input type="text" class="form-input" id="ip" disabled>
</div>
</div>
<div class="form-group">
<div class="col-xs-3">
<label class="form-label" for="mqtt">MQTT Status</label>
</div>
<div class="col-xs-9">
<input type="text" class="form-input" id="mqtt" disabled>
</div>
</div>
<div class="form-group">
<div class="col-xs-3">
<label class="form-label" for="relay">Relay Status</label>
</div>
<div class="col-xs-6">
<input type="hidden" class="form-input" name="status" id="status" value="0" />
<a class="btn" data="0" id="relay">OFF</a>
</div>
</div>
</form>
</div>
</div>
</div>
<div>
<label class="desc" for="pass0">Network Password 0</label>
<div>
<input id="pass0" name="pass0" type="text" spellcheck="false" value="{pass0}" maxlength="255" tabindex="2">
</div>
</div>
<div class="page" id="panel-admin">
<div>
<label class="desc" for="ssid1">Network SSID 1</label>
<div>
<input id="ssid1" name="ssid1" type="text" class="field text fn" value="{ssid1}" size="8" tabindex="3">
</div>
</div>
<form action="/" method="post">
<div>
<label class="desc" for="pass1">Network Password 1</label>
<div>
<input id="pass1" name="pass1" type="text" spellcheck="false" value="{pass1}" maxlength="255" tabindex="4">
</div>
</div>
<div class="hint">
You can configure up to 3 different WiFi networks. The device will try to connect to any of them starting with the first one.
</div>
<div>
<label class="desc" for="ssid2">Network SSID 2</label>
<div>
<input id="ssid2" name="ssid2" type="text" class="field text fn" value="{ssid2}" size="8" tabindex="5">
</div>
</div>
<div class="columns">
<div>
<label class="desc" for="pass2">Network Password 2</label>
<div>
<input id="pass2" name="pass2" type="text" spellcheck="false" value="{pass2}" maxlength="255" tabindex="6">
</div>
</div>
<div class="column col-4">
<h5>Network 1</h5>
<div class="form-group">
<label class="form-label" for="ssid0">Network SSID</label>
<input name="ssid0" type="text" class="form-input" value="{ssid0}" size="8" tabindex="1" placeholder="Network SSID">
</div>
<div>
<label class="form-label" for="pass0">Network Password</label>
<input name="pass0" type="text" class="form-input" value="{pass0}" maxlength="255" tabindex="2" placeholder="Network password">
</div>
</div>
<div class="column col-4">
<h5>Network 2</h5>
<div class="form-group">
<label class="form-label" for="ssid1">Network SSID</label>
<input name="ssid1" type="text" class="form-input" value="{ssid1}" size="8" tabindex="3" placeholder="Network SSID">
</div>
<div>
<label class="form-label" for="pass1">Network Password</label>
<input name="pass1" type="text" class="form-input" value="{pass1}" maxlength="255" tabindex="4" placeholder="Network password">
</div>
</div>
<div class="column col-4">
<h5>Network 3</h5>
<div class="form-group">
<label class="form-label" for="ssid2">Network SSID</label>
<input name="ssid2" type="text" class="form-input" value="{ssid2}" size="8" tabindex="5" placeholder="Network SSID">
</div>
<div>
<label class="form-label" for="pass2">Network Password</label>
<input name="pass2" type="text" class="form-input" value="{pass2}" maxlength="255" tabindex="6" placeholder="Network password">
</div>
</div>
<div>
<label class="desc" for="mqttServer">MQTT Server</label>
<div>
<input id="mqttServer" name="mqttServer" type="text" class="field text fn" value="{mqttServer}" size="8" tabindex="7">
</div>
</div>
</div>
<div>
<label class="desc" for="mqttPort">MQTT Port</label>
<div>
<input id="mqttPort" name="mqttPort" type="text" spellcheck="false" value="{mqttPort}" maxlength="255" tabindex="8">
</div>
</div>
<div class="clearfix"></div>
<div>
<label class="desc" for="mqttTopic">MQTT Topic</label>
<div>
<input id="mqttTopic" name="mqttTopic" type="text" class="field text fn" value="{mqttTopic}" size="8" tabindex="9">
</div>
</div>
<div class="hint">
Configure an <strong>MQTT broker</strong> in your network and you will be able to change the switch status via an MQTT message. Just send a 0 or a 1 as a payload to the provided topic below.
The switch will also report its current open/close status to the same topic and its IP address to the topic you define plus "<code>/ip</code>". Leave the server field empty to disable MQTT.
</div>
<div>
<label class="desc" for="rfChannel">RF Channel</label>
<div>
<input id="rfChannel" name="rfChannel" type="text" spellcheck="false" value="{rfChannel}" maxlength="255" tabindex="10">
</div>
</div>
<div class="columns">
<div class="column col-4">
<div class="form-group">
<label class="form-label" for="mqttServer">MQTT Server</label>
<input name="mqttServer" type="text" class="form-input" value="{mqttServer}" size="8" tabindex="8" placeholder="MQTT Server">
</div>
</div>
<div class="column col-2">
<div class="form-group">
<label class="form-label" for="mqttPort">MQTT Port</label>
<input name="mqttPort" type="text" class="form-input" value="{mqttPort}" size="8" tabindex="9" placeholder="1883">
</div>
</div>
</div>
<div class="columns">
<div class="column col-4">
<div class="form-group">
<label class="form-label" for="mqttUser">MQTT User</label>
<input name="mqttUser" type="text" class="form-input" value="{mqttUser}" size="8" tabindex="10" placeholder="Leave blank if no user/pass">
</div>
</div>
<div class="column col-4">
<div class="form-group">
<label class="form-label" for="mqttPassword">MQTT Password</label>
<input name="mqttPassword" type="text" class="form-input" value="{mqttPassword}" size="8" tabindex="11" placeholder="Leave blank if no user/pass">
</div>
</div>
</div>
<div class="columns">
<div class="column col-4">
<div class="form-group">
<label class="form-label" for="mqttTopic">MQTT Topic</label>
<input name="mqttTopic" type="text" class="form-input" value="{mqttTopic}" size="8" tabindex="12" placeholder="MQTT Topic">
</div>
</div>
</div>
<div>
<label class="desc" for="rfDevice">RF Device</label>
<div>
<input id="rfDevice" name="rfDevice" type="text" class="field text fn" value="{rfDevice}" size="8" tabindex="11">
</div>
</div>
<div class="clearfix"></div>
<div>
<div>
<input id="submit" name="submit" type="submit" value="Connect">
</div>
</div>
<div class="hint">
If your device supports RF switching you can configure here the channel and device ID.
</div>
<div class="columns">
<div class="column col-2">
<div class="form-group">
<label class="form-label" for="rfChannel">RF Channel</label>
<input name="rfChannel" type="number" min="0" max="31" step="1" class="form-input" value="{rfChannel}" tabindex="13"/>
</div>
</div>
<div class="column col-2">
<div class="form-group">
<label class="form-label" for="rfDevice">RF Device</label>
<select name="rfDevice" class="form-input" tabindex="14">
<option value="0">A</a>
<option value="1">B</a>
<option value="2">C</a>
<option value="3">D</a>
<option value="4">E</a>
</select>
</div>
</div>
</div>
</form>
<div>
<div>
<button class="btn btn-primary float-right">Update</button>
</div>
</div>
</form>
</div>
</div>
</body>
</html>

+ 1
- 0
code/data/spectre.min.css
File diff suppressed because it is too large
View File


+ 1
- 1
code/platformio.ini View File

@ -38,5 +38,5 @@ framework = arduino
board = esp01_1m
lib_install = 89
upload_speed = 115200
upload_port = "192.168.1.109"
upload_port = "192.168.4.1"
upload_flags = --auth=fibonacci --port 8266

+ 94
- 21
code/src/code.ino View File

@ -26,7 +26,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <DebounceEvent.h>
#include <ArduinoOTA.h>
#include <RemoteReceiver.h>
#include <EEPROM.h>
#include "FS.h"
#include <stdio.h>
// -----------------------------------------------------------------------------
// Configuració
@ -82,9 +84,11 @@ DebounceEvent button1 = false;
#if ENABLE_MQTT
WiFiClient client;
PubSubClient mqtt(client);
String mqttServer = "192.168.1.100";
String mqttServer = "";
String mqttTopic = "/test/switch/{identifier}";
String mqttPort = "1883";
String mqttUser = "";
String mqttPassword = "";
char mqttStatusTopic[30];
char mqttIPTopic[30];
bool isMQTTMessage = false;
@ -98,6 +102,44 @@ DebounceEvent button1 = false;
String rfDevice = String(RF_DEVICE);
#endif
// -----------------------------------------------------------------------------
// Utils
// -----------------------------------------------------------------------------
char * getCompileTime(char * buffer) {
int day, month, year, hour, minute, second;
// parse date
String tmp = String(__DATE__);
day = tmp.substring(4,6).toInt();
year = tmp.substring(7).toInt();
tmp = tmp.substring(0,3);
if (tmp.equals("Jan")) month = 1;
if (tmp.equals("Feb")) month = 2;
if (tmp.equals("Mar")) month = 3;
if (tmp.equals("Apr")) month = 4;
if (tmp.equals("May")) month = 5;
if (tmp.equals("Jun")) month = 6;
if (tmp.equals("Jul")) month = 7;
if (tmp.equals("Aug")) month = 8;
if (tmp.equals("Sep")) month = 9;
if (tmp.equals("Oct")) month = 10;
if (tmp.equals("Nov")) month = 11;
if (tmp.equals("Dec")) month = 12;
// parse time
tmp = String(__TIME__);
hour = tmp.substring(0,2).toInt();
minute = tmp.substring(3,5).toInt();
second = tmp.substring(6,8).toInt();
sprintf(buffer, "%d%02d%02d%02d%02d%02d", year, month, day, hour, minute, second);
buffer[14] = 0;
return buffer;
}
// -----------------------------------------------------------------------------
// Relay
// -----------------------------------------------------------------------------
@ -113,6 +155,10 @@ void switchRelayOn() {
}
#endif
digitalWrite(RELAY_PIN, HIGH);
if (EEPROM.read(0) == 0) {
EEPROM.write(0, 1);
EEPROM.commit();
}
}
}
@ -127,6 +173,10 @@ void switchRelayOff() {
}
#endif
digitalWrite(RELAY_PIN, LOW);
if (EEPROM.read(0) == 1) {
EEPROM.write(0, 0);
EEPROM.commit();
}
}
}
@ -322,7 +372,11 @@ void wifiLoop() {
file.close();
// Replace placeholders
content.replace("{appname}", APP_NAME);
getCompileTime(buffer);
content.replace("{appname}", String(APP_NAME) + "." + String(buffer));
content.replace("{status}", digitalRead(RELAY_PIN) ? "1" : "0");
content.replace("{updateInterval}", String(STATUS_UPDATE_INTERVAL));
content.replace("{ssid0}", configSSID[0]);
content.replace("{pass0}", configPASS[0]);
content.replace("{ssid1}", configSSID[1]);
@ -332,6 +386,8 @@ void wifiLoop() {
#if ENABLE_MQTT
content.replace("{mqttServer}", mqttServer);
content.replace("{mqttPort}", mqttPort);
content.replace("{mqttUser}", mqttUser);
content.replace("{mqttPassword}", mqttPassword);
content.replace("{mqttTopic}", mqttTopic);
#endif
#if ENABLE_RF
@ -351,20 +407,30 @@ void wifiLoop() {
Serial.println("Request: /save");
#endif
configSSID[0] = server.arg("ssid0");
configPASS[0] = server.arg("pass0");
configSSID[1] = server.arg("ssid1");
configPASS[1] = server.arg("pass1");
configSSID[2] = server.arg("ssid2");
configPASS[2] = server.arg("pass2");
if (server.hasArg("status")) {
if (server.arg("status") == "1") {
switchRelayOn();
} else {
switchRelayOff();
}
}
if (server.hasArg("ssid0")) configSSID[0] = server.arg("ssid0");
if (server.hasArg("pass0")) configPASS[0] = server.arg("pass0");
if (server.hasArg("ssid1")) configSSID[1] = server.arg("ssid1");
if (server.hasArg("pass1")) configPASS[1] = server.arg("pass1");
if (server.hasArg("ssid2")) configSSID[2] = server.arg("ssid2");
if (server.hasArg("pass2")) configPASS[2] = server.arg("pass2");
#if ENABLE_MQTT
mqttServer = server.arg("mqttServer");
mqttPort = server.arg("mqttPort");
mqttTopic = server.arg("mqttTopic");
if (server.hasArg("mqttServer")) mqttServer = server.arg("mqttServer");
if (server.hasArg("mqttPort")) mqttPort = server.arg("mqttPort");
if (server.hasArg("mqttUser")) mqttUser = server.arg("mqttUser");
if (server.hasArg("mqttPassword")) mqttPassword = server.arg("mqttPassword");
if (server.hasArg("mqttTopic")) mqttTopic = server.arg("mqttTopic");
#endif
#if ENABLE_RF
rfChannel = server.arg("rfChannel");
rfDevice = server.arg("rfDevice");
if (server.hasArg("rfChannel")) rfChannel = server.arg("rfChannel");
if (server.hasArg("rfDevice")) rfDevice = server.arg("rfDevice");
#endif
server.send(202, "text/json", "{}");
@ -398,8 +464,6 @@ void wifiLoop() {
output += ", \"mqtt\": ";
output += (mqtt.connected()) ? "1": "0";
#endif
output += ", \"interval\": ";
output += (int) STATUS_UPDATE_INTERVAL;
output += "}";
server.send(200, "text/json", output);
@ -484,13 +548,11 @@ void wifiLoop() {
#endif
isMQTTMessage = true;
if ((char)payload[0] == '1') {
switchRelayOn();
} else {
switchRelayOff();
}
isMQTTMessage = false;
@ -498,7 +560,7 @@ void wifiLoop() {
void mqttConnect() {
if (!mqtt.connected()) {
if (!mqtt.connected() && (mqttServer.length()>0)) {
char buffer[mqttServer.length()+1];
mqttServer.toCharArray(buffer, mqttServer.length()+1);
@ -508,7 +570,17 @@ void wifiLoop() {
Serial.print("Connecting to MQTT broker: ");
#endif
if (mqtt.connect(getIdentifier())) {
if (mqttUser.length() > 0) {
char user[mqttUser.length() + 1];
mqttUser.toCharArray(user, mqttUser.length() + 1);
char password[mqttPassword.length() + 1];
mqttPassword.toCharArray(password, mqttPassword.length() + 1);
mqtt.connect(getIdentifier(), user, password);
} else {
mqtt.connect(getIdentifier());
}
if (mqtt.connected()) {
buildTopics();
@ -685,7 +757,7 @@ bool loadConfig() {
#if ENABLE_MQTT
else if (line.startsWith("mqttServer=")) mqttServer = line.substring(11);
else if (line.startsWith("mqttPort=")) mqttPort = line.substring(9);
else if (line.startsWith("mqttTopic=")) mqttTopic = line.substring(14);
else if (line.startsWith("mqttTopic=")) mqttTopic = line.substring(10);
#endif
#if ENABLE_RF
else if (line.startsWith("rfChannel=")) rfChannel = line.substring(10);
@ -775,6 +847,8 @@ void hardwareSetup() {
pinMode(RF_PIN, INPUT_PULLUP);
button1 = DebounceEvent(BUTTON_PIN);
SPIFFS.begin();
EEPROM.begin(1);
EEPROM.read(0) == 1 ? switchRelayOn() : switchRelayOff();
}
void blink(unsigned long delayOff, unsigned long delayOn) {
@ -822,7 +896,6 @@ void welcome() {
void setup() {
hardwareSetup();
delay(5000);
welcome();
#if ENABLE_OTA


Loading…
Cancel
Save