Browse Source

Configuration changes, using ArduinoJson for AJAX responses, EmonLiteESP with custom reading callbacks

fastled
Xose Pérez 8 years ago
parent
commit
45f96155b3
9 changed files with 564 additions and 462 deletions
  1. +98
    -28
      code/data/index.html
  2. +5
    -1
      code/lib/DebounceEvent/DebounceEvent.cpp
  3. +3
    -2
      code/lib/DebounceEvent/DebounceEvent.h
  4. +22
    -6
      code/lib/EmonLiteESP/EmonLiteESP.cpp
  5. +7
    -2
      code/lib/EmonLiteESP/EmonLiteESP.h
  6. +2
    -0
      code/platformio.ini
  7. +89
    -0
      code/src/Config.cpp
  8. +68
    -0
      code/src/Config.h
  9. +270
    -423
      code/src/main.cpp

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

@ -1,7 +1,7 @@
<!DOCTYPE html>
<html>
<head>
<title>{appname}</title>
<title>ESPurna</title>
<meta charset="utf-8" />
<link rel="stylesheet" href="spectre.min.css" />
<script src="jquery-1.12.3.min.js"></script>
@ -51,16 +51,41 @@
setTimeout(update, 200);
});
function init() {
$.ajax({
'method': 'GET',
'url': '/init',
'dataType': 'json'
}).done(function(data) {
keys = Object.keys(data);
for (index in keys) {
key = "#" + keys[index];
value = data[keys[index]];
try {
if ($(key).prop('tagName') == 'INPUT') {
$(key).val(value);
} else {
$(key).html(value);
}
} catch(err) {
// nope
};
};
timer = setInterval(update, data.updateInterval);
document.title = data.hostname;
$("[name='pwMainsVoltage']").val(data.pwMainsVoltage);
$("[name='rfDevice']").val(data.rfDevice);
});
}
function update() {
$.ajax({
'method': 'GET',
'url': '/status',
'dataType': 'json'
}).done(function(data) {
$("#device").val(data.device);
$("#network").val(data.network.toUpperCase());
$("#ip").val(data.ip);
$("#mqtt").val(data.mqtt ? "CONNECTED" : "NOT CONNECTED");
$("#power").val((data.power | 0) + "W");
if (data.relay) {
$("#relay").addClass('btn-primary').html("ON");
$("#status").val(1);
@ -72,8 +97,8 @@
}
$("#btn-admin").click(function() {
$("#panel-admin").show();
$("#panel-status").hide();
$("#panel-admin").show();
$("#btn-admin").addClass('btn-primary');
$("#btn-status").removeClass('btn-primary');
});
@ -96,13 +121,8 @@
event.preventDefault();
})
function init() {
update();
timer = setInterval(update, {updateInterval});
$("[name='rfDevice']").val({rfDevice});
}
init();
update();
});
@ -114,7 +134,7 @@
<header class="navbar bg-grey">
<section class="navbar-section">
<a href="#" class="navbar-brand">{appname}</a>
<a href="#" class="navbar-brand"><span id="appname"></span></a>
</section>
<section class="navbar-section">
<button class="btn" id="btn-admin">Administration</button>
@ -129,10 +149,26 @@
<form class="form-horizontal">
<div class="form-group">
<div class="col-xs-3">
<label class="form-label" for="device">Device</label>
<label class="form-label" for="manufacturer">Manufacturer</label>
</div>
<div class="col-xs-9">
<input type="text" class="form-input" id="manufacturer" value="" disabled>
</div>
</div>
<div class="form-group">
<div class="col-xs-3">
<label class="form-label" for="model">Model</label>
</div>
<div class="col-xs-9">
<input type="text" class="form-input" id="model" value="" disabled>
</div>
</div>
<div class="form-group">
<div class="col-xs-3">
<label class="form-label" for="hostname">Hostname</label>
</div>
<div class="col-xs-9">
<input type="text" class="form-input" id="device" disabled>
<input type="text" class="form-input" id="hostname" value="" disabled>
</div>
</div>
<div class="form-group">
@ -140,7 +176,7 @@
<label class="form-label" for="network">Network</label>
</div>
<div class="col-xs-9">
<input type="text" class="form-input" id="network" disabled>
<input type="text" class="form-input" id="network" value="" disabled>
</div>
</div>
<div class="form-group">
@ -148,7 +184,7 @@
<label class="form-label" for="ip">IP</label>
</div>
<div class="col-xs-9">
<input type="text" class="form-input" id="ip" disabled>
<input type="text" class="form-input" id="ip" value="" disabled>
</div>
</div>
<div class="form-group">
@ -159,6 +195,14 @@
<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="power">Power</label>
</div>
<div class="col-xs-6">
<input type="text" class="form-input" id="power" disabled>
</div>
</div>
<div class="form-group">
<div class="col-xs-3">
<label class="form-label" for="relay">Relay Status</label>
@ -187,33 +231,33 @@
<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">
<input name="ssid0" id="ssid0" type="text" class="form-input" 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">
<input name="pass0" id="pass0" type="text" class="form-input" 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">
<input name="ssid1" id="ssid1" type="text" class="form-input" 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">
<input name="pass1" id="pass1" type="text" class="form-input" 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">
<input name="ssid2" id="ssid2" type="text" class="form-input" 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">
<input name="pass2" id="pass2" type="text" class="form-input" maxlength="255" tabindex="6" placeholder="Network password">
</div>
</div>
@ -230,13 +274,13 @@
<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">
<input name="mqttServer" id="mqttServer" type="text" class="form-input" 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">
<input name="mqttPort" id="mqttPort" type="text" class="form-input" size="8" tabindex="9" placeholder="1883">
</div>
</div>
</div>
@ -244,13 +288,13 @@
<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">
<input name="mqttUser" id="mqttUser" type="text" class="form-input" 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">
<input name="mqttPassword" id="mqttPassword" type="text" class="form-input" size="8" tabindex="11" placeholder="Leave blank if no user/pass">
</div>
</div>
</div>
@ -258,7 +302,7 @@
<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">
<input name="mqttTopic" id="mqttTopic" type="text" class="form-input" size="8" tabindex="12" maxlength="35" placeholder="MQTT Topic">
</div>
</div>
</div>
@ -273,7 +317,7 @@
<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"/>
<input name="rfChannel" id="rfChannel" type="number" min="0" max="31" step="1" class="form-input" tabindex="13"/>
</div>
</div>
<div class="column col-2">
@ -290,6 +334,32 @@
</div>
</div>
<div class="clearfix"></div>
<div class="hint">
If your device supports power measurement, here you can configure line potential and current ratio.
</div>
<div class="columns">
<div class="column col-2">
<div class="form-group">
<label class="form-label" for="pwMainsVoltage">AC RMS Voltage</label>
<select name="pwMainsVoltage" class="form-input" tabindex="15">
<option value="125">125</a>
<option value="220">220</a>
<option value="230">230</a>
<option value="240">240</a>
</select>
</div>
</div>
<div class="column col-2">
<div class="form-group">
<label class="form-label" for="pwCurrentRatio">Current ratio</label>
<input name="pwCurrentRatio" id="pwCurrentRatio" type="text" class="form-input" size="8" tabindex="16" placeholder="30">
</div>
</div>
</div>
<div>
<div>
<button class="btn btn-primary float-right">Update</button>


+ 5
- 1
code/lib/DebounceEvent/DebounceEvent.cpp View File

@ -22,12 +22,16 @@
#include "DebounceEvent.h"
DebounceEvent::DebounceEvent(uint8_t pin, callback_t callback, uint8_t defaultStatus, unsigned long delay) {
_callback = callback;
DebounceEvent(pin, defaultStatus, delay);
}
DebounceEvent::DebounceEvent(uint8_t pin, uint8_t defaultStatus, unsigned long delay) {
// store configuration
_pin = pin;
_status = _defaultStatus = defaultStatus;
_delay = delay;
_callback = callback;
// set up button
if (_defaultStatus == LOW) {


+ 3
- 2
code/lib/DebounceEvent/DebounceEvent.h View File

@ -46,11 +46,12 @@ class DebounceEvent {
unsigned long _last_start;
uint8_t _defaultStatus;
unsigned long _delay;
callback_t _callback;
callback_t _callback = false;
public:
DebounceEvent(uint8_t pin, callback_t callback = false, uint8_t defaultStatus = HIGH, unsigned long delay = DEBOUNCE_DELAY);
DebounceEvent(uint8_t pin, callback_t callback, uint8_t defaultStatus = HIGH, unsigned long delay = DEBOUNCE_DELAY);
DebounceEvent(uint8_t pin, uint8_t defaultStatus = HIGH, unsigned long delay = DEBOUNCE_DELAY);
bool pressed();
bool loop();
uint8_t getEvent();


+ 22
- 6
code/lib/EmonLiteESP/EmonLiteESP.cpp View File

@ -8,13 +8,18 @@
#include "Arduino.h"
#include "EmonLiteESP.h"
void EnergyMonitor::initCurrent(unsigned int pin, double ref, double ratio) {
_currentPin = pin;
void EnergyMonitor::initCurrent(current_c callback, double ref, double ratio) {
_currentCallback = callback;
_referenceVoltage = ref;
_currentRatio = ratio;
_currentMidPoint = (ADC_COUNTS>>1);
// Calculate default precision
calculatePrecision();
};
void EnergyMonitor::calculatePrecision() {
_currentFactor = _currentRatio * _referenceVoltage / ADC_COUNTS;
_precision = 0;
_multiplier = 1;
@ -24,8 +29,15 @@ void EnergyMonitor::initCurrent(unsigned int pin, double ref, double ratio) {
}
--_precision;
_multiplier /= 10;
}
};
void EnergyMonitor::setReference(double ref) {
_referenceVoltage = ref;
}
void EnergyMonitor::setCurrentRatio(double ratio) {
_currentRatio = ratio;
}
byte EnergyMonitor::getPrecision() {
return _precision;
@ -46,10 +58,10 @@ double EnergyMonitor::getCurrent(unsigned int samples) {
for (unsigned int n = 0; n < samples; n++) {
// Read analog value
sample = analogRead(_currentPin);
sample = _currentCallback();
// Digital low pass filter extracts the VDC offset
_currentMidPoint = (_currentMidPoint + (sample - _currentMidPoint) / 1024.0);
_currentMidPoint = (_currentMidPoint + (sample - _currentMidPoint) / 10.0);
filtered = sample - _currentMidPoint;
// Root-mean-square method
@ -59,7 +71,11 @@ double EnergyMonitor::getCurrent(unsigned int samples) {
double rms = int(sqrt(sum / samples) - 0.5);
double current = _currentFactor * rms;
Serial.println(sum);
Serial.println(rms);
Serial.println(current);
current = round(current * _multiplier) / _multiplier;
Serial.println(current);
return current;
};

+ 7
- 2
code/lib/EmonLiteESP/EmonLiteESP.h View File

@ -11,18 +11,23 @@
#define ADC_BITS 10
#define ADC_COUNTS (1<<ADC_BITS)
typedef unsigned int (*current_c)();
class EnergyMonitor {
public:
void initCurrent(unsigned int pin, double ref, double ratio);
void initCurrent(current_c callback, double ref, double ratio);
double getCurrent(unsigned int samples);
byte getPrecision();
void setPrecision(byte precision);
void setReference(double ref);
void setCurrentRatio(double ratio);
void calculatePrecision();
private:
unsigned int _currentPin;
current_c _currentCallback;
double _referenceVoltage;
double _currentRatio;
double _currentMidPoint;


+ 2
- 0
code/platformio.ini View File

@ -25,6 +25,7 @@ platform = espressif
framework = arduino
board = esp01_1m
lib_install = 89,64
build_flags = -Wl,-Tesp8266.flash.1m256.ld
[env:node]
platform = espressif
@ -37,6 +38,7 @@ platform = espressif
framework = arduino
board = esp01_1m
lib_install = 89,64
build_flags = -Wl,-Tesp8266.flash.1m256.ld
upload_speed = 115200
upload_port = "192.168.4.1"
upload_flags = --auth=fibonacci --port 8266

+ 89
- 0
code/src/Config.cpp View File

@ -0,0 +1,89 @@
/*
Config
Configuration file
*/
#include "Config.h"
#include "FS.h"
bool ConfigClass::save() {
File file = SPIFFS.open(CONFIG_PATH, "w");
if (file) {
file.println("hostname=" + hostname);
file.println("ssid0=" + ssid[0]);
file.println("pass0=" + pass[0]);
file.println("ssid1=" + ssid[1]);
file.println("pass1=" + pass[1]);
file.println("ssid2=" + ssid[2]);
file.println("pass2=" + pass[2]);
file.println("mqttServer=" + mqttServer);
file.println("mqttPort=" + mqttPort);
file.println("mqttTopic=" + mqttTopic);
file.println("rfChannel=" + rfChannel);
file.println("rfDevice=" + rfDevice);
file.println("otaServer=" + otaServer);
file.println("otaInterval=" + otaInterval);
file.println("pwMainsVoltage=" + pwMainsVoltage);
file.println("pwCurrentRatio=" + pwCurrentRatio);
file.close();
return true;
}
return false;
}
bool ConfigClass::load() {
if (SPIFFS.exists(CONFIG_PATH)) {
#ifdef DEBUG
Serial.println("Reading config file");
#endif
// Read contents
File file = SPIFFS.open(CONFIG_PATH, "r");
String content = file.readString();
file.close();
// Parse contents
content.replace("\r\n", "\n");
content.replace("\r", "\n");
int start = 0;
int end = content.indexOf("\n", start);
while (end > 0) {
String line = content.substring(start, end);
if (line.startsWith("hostname=")) hostname = line.substring(9);
else if (line.startsWith("ssid0=")) ssid[0] = line.substring(6);
else if (line.startsWith("pass0=")) pass[0] = line.substring(6);
else if (line.startsWith("ssid1=")) ssid[1] = line.substring(6);
else if (line.startsWith("pass1=")) pass[1] = line.substring(6);
else if (line.startsWith("ssid2=")) ssid[2] = line.substring(6);
else if (line.startsWith("pass2=")) pass[2] = line.substring(6);
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(10);
else if (line.startsWith("rfChannel=")) rfChannel = line.substring(10);
else if (line.startsWith("rfDevice=")) rfDevice = line.substring(9);
else if (line.startsWith("otaServer=")) otaServer = line.substring(10);
else if (line.startsWith("otaInterval=")) otaInterval = line.substring(12);
else if (line.startsWith("pwMainsVoltage=")) pwMainsVoltage = line.substring(15);
else if (line.startsWith("pwCurrentRatio=")) pwCurrentRatio = line.substring(15);
if (end < 0) break;
start = end + 1;
end = content.indexOf("\n", start);
}
return true;
}
return false;
}
ConfigClass config;

+ 68
- 0
code/src/Config.h View File

@ -0,0 +1,68 @@
/*
Config
Configuration file
*/
#ifndef Config_h
#define Config_h
#include "Arduino.h"
// -----------------------------------------------------------------------------
// Defaults
// -----------------------------------------------------------------------------
#define CONFIG_PATH "/.config"
#define NETWORK_BUFFER 3
#define MQTT_SERVER "192.168.1.100"
#define MQTT_PORT 1883
#define MQTT_TOPIC "/test/switch/{identifier}"
#define AUTOOTA_SERVER "http://192.168.1.100"
#define AUTOOTA_INTERVAL 600000
#define MAINS_VOLTAGE 230
#define CURRENT_RATIO 156
#define RF_CHANNEL 31
#define RF_DEVICE 1
// -----------------------------------------------------------------------------
// Class definition
// -----------------------------------------------------------------------------
class ConfigClass {
public:
String hostname;
String ssid[NETWORK_BUFFER];
String pass[NETWORK_BUFFER];
String mqttServer = MQTT_SERVER;
String mqttPort = String(MQTT_PORT);
String mqttTopic = MQTT_TOPIC;
String mqttUser = "";
String mqttPassword = "";
String rfChannel = String(RF_CHANNEL);
String rfDevice = String(RF_DEVICE);
String otaServer = String(AUTOOTA_SERVER);
String otaInterval = String(AUTOOTA_INTERVAL);
String pwMainsVoltage = String(MAINS_VOLTAGE);
String pwCurrentRatio = String(CURRENT_RATIO);
bool save();
bool load();
};
extern ConfigClass config;
#endif

+ 270
- 423
code/src/main.cpp
File diff suppressed because it is too large
View File


Loading…
Cancel
Save