mirror of
https://github.com/UtilitechAS/amsreader-firmware.git
synced 2026-03-21 00:57:46 +00:00
Compare commits
36 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
38eb2d8c19 | ||
|
|
d95137adbc | ||
|
|
cde3f80fca | ||
|
|
cdc012743f | ||
|
|
23c90315a5 | ||
|
|
8d938f111c | ||
|
|
cff6c02d57 | ||
|
|
0c92f7401c | ||
|
|
195a0d4e77 | ||
|
|
43f50e0e0a | ||
|
|
f2f20afd9c | ||
|
|
f22cfbb223 | ||
|
|
803c5116bd | ||
|
|
a542fbc931 | ||
|
|
85a70016fa | ||
|
|
778daf8645 | ||
|
|
efa99f970c | ||
|
|
953f2d4110 | ||
|
|
c3c0ca0a1b | ||
|
|
dc83853d2e | ||
|
|
f5123e9aa1 | ||
|
|
2da69dd451 | ||
|
|
2858123c1b | ||
|
|
9d4488f8df | ||
|
|
f78c8e3582 | ||
|
|
431d6714b5 | ||
|
|
550a3c1a0b | ||
|
|
b6f5e72638 | ||
|
|
958ff37d7d | ||
|
|
1ea9da22c7 | ||
|
|
0c93c52e3d | ||
|
|
41784511e9 | ||
|
|
a78fdc0b59 | ||
|
|
cc032fdf29 | ||
|
|
f696e0b59b | ||
|
|
f67f12a188 |
4
.github/workflows/build.yml
vendored
4
.github/workflows/build.yml
vendored
@@ -9,7 +9,7 @@ on:
|
|||||||
- web/**
|
- web/**
|
||||||
- platformio.ini
|
- platformio.ini
|
||||||
branches:
|
branches:
|
||||||
- master
|
- '*'
|
||||||
tags:
|
tags:
|
||||||
- '*'
|
- '*'
|
||||||
- '!v*.*.*'
|
- '!v*.*.*'
|
||||||
@@ -39,7 +39,7 @@ jobs:
|
|||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
python -m pip install --upgrade pip
|
python -m pip install --upgrade pip
|
||||||
pip install -U platformio
|
pip install -U platformio css_html_js_minify
|
||||||
- name: Configure build targets
|
- name: Configure build targets
|
||||||
run: echo "[platformio]\ndefault_envs = hw1esp12e, esp12e, esp32" > platformio-user.ini
|
run: echo "[platformio]\ndefault_envs = hw1esp12e, esp12e, esp32" > platformio-user.ini
|
||||||
- name: PlatformIO lib install
|
- name: PlatformIO lib install
|
||||||
|
|||||||
20
.github/workflows/release.yml
vendored
20
.github/workflows/release.yml
vendored
@@ -40,7 +40,7 @@ jobs:
|
|||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
python -m pip install --upgrade pip
|
python -m pip install --upgrade pip
|
||||||
pip install -U platformio
|
pip install -U platformio css_html_js_minify
|
||||||
- name: PlatformIO lib install
|
- name: PlatformIO lib install
|
||||||
run: pio lib install
|
run: pio lib install
|
||||||
- name: PlatformIO run
|
- name: PlatformIO run
|
||||||
@@ -109,3 +109,21 @@ jobs:
|
|||||||
asset_path: .pio/build/featheresp32/firmware.bin
|
asset_path: .pio/build/featheresp32/firmware.bin
|
||||||
asset_name: ams2mqtt-featheresp32-${{ steps.release_tag.outputs.tag }}.bin
|
asset_name: ams2mqtt-featheresp32-${{ steps.release_tag.outputs.tag }}.bin
|
||||||
asset_content_type: application/octet-stream
|
asset_content_type: application/octet-stream
|
||||||
|
- name: Upload azdevkit4 binary to release
|
||||||
|
uses: actions/upload-release-asset@v1
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
with:
|
||||||
|
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||||
|
asset_path: .pio/build/az-delivery-devkit-v4/firmware.bin
|
||||||
|
asset_name: ams2mqtt-azdevkit4-${{ steps.release_tag.outputs.tag }}.bin
|
||||||
|
asset_content_type: application/octet-stream
|
||||||
|
- name: Upload doitdevkit1 binary to release
|
||||||
|
uses: actions/upload-release-asset@v1
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
with:
|
||||||
|
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||||
|
asset_path: .pio/build/esp32doit-devkit-v1/firmware.bin
|
||||||
|
asset_name: ams2mqtt-doitdevkit1-${{ steps.release_tag.outputs.tag }}.bin
|
||||||
|
asset_content_type: application/octet-stream
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
#include "HanReader.h"
|
#include "HanReader.h"
|
||||||
|
|
||||||
HanReader::HanReader()
|
HanReader::HanReader() {
|
||||||
{
|
// Central European Time (Frankfurt, Paris)
|
||||||
|
TimeChangeRule CEST = {"CEST", Last, Sun, Mar, 2, 120}; // Central European Summer Time
|
||||||
|
TimeChangeRule CET = {"CET ", Last, Sun, Oct, 3, 60}; // Central European Standard Time
|
||||||
|
localZone = new Timezone(CEST, CET);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HanReader::setup(Stream *hanPort, RemoteDebug *debug)
|
void HanReader::setup(Stream *hanPort, RemoteDebug *debug)
|
||||||
@@ -10,11 +13,6 @@ void HanReader::setup(Stream *hanPort, RemoteDebug *debug)
|
|||||||
bytesRead = 0;
|
bytesRead = 0;
|
||||||
debugger = debug;
|
debugger = debug;
|
||||||
|
|
||||||
// Central European Time (Frankfurt, Paris)
|
|
||||||
TimeChangeRule CEST = {"CEST", Last, Sun, Mar, 2, 120}; // Central European Summer Time
|
|
||||||
TimeChangeRule CET = {"CET ", Last, Sun, Oct, 3, 60}; // Central European Standard Time
|
|
||||||
localZone = new Timezone(CEST, CET);
|
|
||||||
|
|
||||||
if (debug) debug->println("MBUS serial setup complete");
|
if (debug) debug->println("MBUS serial setup complete");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,6 +110,12 @@ String HanReader::getString(int objectId) {
|
|||||||
return getString(objectId, buffer, 0, bytesRead);
|
return getString(objectId, buffer, 0, bytesRead);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int HanReader::getBuffer(byte* buf) {
|
||||||
|
for (int i = 0; i < bytesRead; i++) {
|
||||||
|
buf[i] = buffer[i];
|
||||||
|
}
|
||||||
|
return bytesRead;
|
||||||
|
}
|
||||||
|
|
||||||
int HanReader::findValuePosition(int dataPosition, byte *buffer, int start, int length) {
|
int HanReader::findValuePosition(int dataPosition, byte *buffer, int start, int length) {
|
||||||
// The first byte after the header gives the length
|
// The first byte after the header gives the length
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ public:
|
|||||||
uint32_t getUint(int objectId); // Only for uint32
|
uint32_t getUint(int objectId); // Only for uint32
|
||||||
String getString(int objectId);
|
String getString(int objectId);
|
||||||
time_t getTime(int objectId);
|
time_t getTime(int objectId);
|
||||||
|
int getBuffer(byte* buf);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
RemoteDebug* debugger;
|
RemoteDebug* debugger;
|
||||||
|
|||||||
@@ -5,10 +5,12 @@
|
|||||||
|
|
||||||
enum class Kamstrup
|
enum class Kamstrup
|
||||||
{
|
{
|
||||||
|
List1PhaseShort = 0x11,
|
||||||
|
List1PhaseLong = 0x1B,
|
||||||
List3PhaseShort = 0x19,
|
List3PhaseShort = 0x19,
|
||||||
List3PhaseLong = 0x23,
|
List3PhaseLong = 0x23,
|
||||||
List1PhaseShort = 0x11,
|
List3PhaseITShort = 0x17,
|
||||||
List1PhaseLong = 0x1B
|
List3PhaseITLong = 0x21
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class Kamstrup_List3Phase
|
enum class Kamstrup_List3Phase
|
||||||
@@ -83,5 +85,43 @@ enum class Kamstrup_List1Phase
|
|||||||
CumulativeReactiveExportEnergy
|
CumulativeReactiveExportEnergy
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class Kamstrup_List3PhaseIT
|
||||||
|
{
|
||||||
|
ListSize,
|
||||||
|
ListVersionIdentifier,
|
||||||
|
MeterID_OBIS,
|
||||||
|
MeterID,
|
||||||
|
MeterType_OBIS,
|
||||||
|
MeterType,
|
||||||
|
ActiveImportPower_OBIS,
|
||||||
|
ActiveImportPower,
|
||||||
|
ActiveExportPower_OBIS,
|
||||||
|
ActiveExportPower,
|
||||||
|
ReactiveImportPower_OBIS,
|
||||||
|
ReactiveImportPower,
|
||||||
|
ReactiveExportPower_OBIS,
|
||||||
|
ReactiveExportPower,
|
||||||
|
CurrentL1_OBIS,
|
||||||
|
CurrentL1,
|
||||||
|
CurrentL3_OBIS,
|
||||||
|
CurrentL3,
|
||||||
|
VoltageL1_OBIS,
|
||||||
|
VoltageL1,
|
||||||
|
VoltageL2_OBIS,
|
||||||
|
VoltageL2,
|
||||||
|
VoltageL3_OBIS,
|
||||||
|
VoltageL3,
|
||||||
|
MeterClock_OBIS,
|
||||||
|
MeterClock,
|
||||||
|
CumulativeActiveImportEnergy_OBIS,
|
||||||
|
CumulativeActiveImportEnergy,
|
||||||
|
CumulativeActiveExportEnergy_OBIS,
|
||||||
|
CumulativeActiveExportEnergy,
|
||||||
|
CumulativeReactiveImportEnergy_OBIS,
|
||||||
|
CumulativeReactiveImportEnergy,
|
||||||
|
CumulativeReactiveExportEnergy_OBIS,
|
||||||
|
CumulativeReactiveExportEnergy
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ framework = arduino
|
|||||||
lib_deps = HanReader@1.0.1, ArduinoJson@6.14.1, MQTT@2.4.7, DallasTemperature@3.8.1, EspSoftwareSerial@6.7.1, Base64@1.0.0, RemoteDebug@3.0.5, Time@1.6
|
lib_deps = HanReader@1.0.1, ArduinoJson@6.14.1, MQTT@2.4.7, DallasTemperature@3.8.1, EspSoftwareSerial@6.7.1, Base64@1.0.0, RemoteDebug@3.0.5, Time@1.6
|
||||||
|
|
||||||
[env:hw1esp12e]
|
[env:hw1esp12e]
|
||||||
platform = espressif8266@2.3.3
|
platform = espressif8266@2.5.1
|
||||||
board = esp12e
|
board = esp12e
|
||||||
framework = ${common.framework}
|
framework = ${common.framework}
|
||||||
lib_deps = ${common.lib_deps}
|
lib_deps = ${common.lib_deps}
|
||||||
@@ -18,7 +18,7 @@ extra_scripts =
|
|||||||
scripts/makeweb.py
|
scripts/makeweb.py
|
||||||
|
|
||||||
[env:esp12e]
|
[env:esp12e]
|
||||||
platform = espressif8266@2.3.3
|
platform = espressif8266@2.5.1
|
||||||
board = esp12e
|
board = esp12e
|
||||||
framework = ${common.framework}
|
framework = ${common.framework}
|
||||||
lib_deps = ${common.lib_deps}
|
lib_deps = ${common.lib_deps}
|
||||||
@@ -27,7 +27,7 @@ extra_scripts =
|
|||||||
scripts/makeweb.py
|
scripts/makeweb.py
|
||||||
|
|
||||||
[env:d1mini]
|
[env:d1mini]
|
||||||
platform = espressif8266@2.3.3
|
platform = espressif8266@2.5.1
|
||||||
board = d1_mini
|
board = d1_mini
|
||||||
framework = ${common.framework}
|
framework = ${common.framework}
|
||||||
lib_deps = ${common.lib_deps}
|
lib_deps = ${common.lib_deps}
|
||||||
@@ -36,7 +36,7 @@ extra_scripts =
|
|||||||
scripts/makeweb.py
|
scripts/makeweb.py
|
||||||
|
|
||||||
[env:esp32]
|
[env:esp32]
|
||||||
platform = espressif32@1.11.2
|
platform = espressif32@1.12.1
|
||||||
board = esp32dev
|
board = esp32dev
|
||||||
framework = ${common.framework}
|
framework = ${common.framework}
|
||||||
lib_deps = ${common.lib_deps}
|
lib_deps = ${common.lib_deps}
|
||||||
@@ -45,7 +45,7 @@ extra_scripts =
|
|||||||
scripts/makeweb.py
|
scripts/makeweb.py
|
||||||
|
|
||||||
[env:lolind32]
|
[env:lolind32]
|
||||||
platform = espressif32@1.11.2
|
platform = espressif32@1.12.1
|
||||||
board = lolin_d32
|
board = lolin_d32
|
||||||
framework = ${common.framework}
|
framework = ${common.framework}
|
||||||
lib_deps = ${common.lib_deps}
|
lib_deps = ${common.lib_deps}
|
||||||
@@ -54,10 +54,28 @@ extra_scripts =
|
|||||||
scripts/makeweb.py
|
scripts/makeweb.py
|
||||||
|
|
||||||
[env:featheresp32]
|
[env:featheresp32]
|
||||||
platform = espressif32@1.11.2
|
platform = espressif32@1.12.1
|
||||||
board = featheresp32
|
board = featheresp32
|
||||||
framework = ${common.framework}
|
framework = ${common.framework}
|
||||||
lib_deps = ${common.lib_deps}
|
lib_deps = ${common.lib_deps}
|
||||||
extra_scripts =
|
extra_scripts =
|
||||||
pre:scripts/addversion.py
|
pre:scripts/addversion.py
|
||||||
scripts/makeweb.py
|
scripts/makeweb.py
|
||||||
|
|
||||||
|
[env:az-delivery-devkit-v4]
|
||||||
|
platform = espressif32@1.12.1
|
||||||
|
board = az-delivery-devkit-v4
|
||||||
|
framework = ${common.framework}
|
||||||
|
lib_deps = ${common.lib_deps}
|
||||||
|
extra_scripts =
|
||||||
|
pre:scripts/addversion.py
|
||||||
|
scripts/makeweb.py
|
||||||
|
|
||||||
|
[env:esp32doit-devkit-v1]
|
||||||
|
platform = espressif32@1.12.1
|
||||||
|
board = esp32doit-devkit-v1
|
||||||
|
framework = ${common.framework}
|
||||||
|
lib_deps = ${common.lib_deps}
|
||||||
|
extra_scripts =
|
||||||
|
pre:scripts/addversion.py
|
||||||
|
scripts/makeweb.py
|
||||||
|
|||||||
@@ -1,10 +1,14 @@
|
|||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import shutil
|
import shutil
|
||||||
|
from css_html_js_minify import html_minify, js_minify, css_minify
|
||||||
|
|
||||||
webroot = "web"
|
webroot = "web"
|
||||||
srcroot = "src/web/root"
|
srcroot = "src/web/root"
|
||||||
|
|
||||||
|
version = os.environ.get('GITHUB_TAG')
|
||||||
|
if version == None:
|
||||||
|
version = "SNAPSHOT"
|
||||||
|
|
||||||
if os.path.exists(srcroot):
|
if os.path.exists(srcroot):
|
||||||
shutil.rmtree(srcroot)
|
shutil.rmtree(srcroot)
|
||||||
@@ -20,11 +24,25 @@ for filename in os.listdir(webroot):
|
|||||||
|
|
||||||
varname = basename.upper()
|
varname = basename.upper()
|
||||||
|
|
||||||
|
with open(srcfile, encoding="utf-8") as f:
|
||||||
|
content = f.read().replace("${version}", version)
|
||||||
|
|
||||||
|
if filename.endswith(".html"):
|
||||||
|
content = html_minify(content)
|
||||||
|
elif filename.endswith(".css"):
|
||||||
|
content = css_minify(content)
|
||||||
|
elif filename.endswith(".js") and filename != 'gaugemeter.js':
|
||||||
|
content = js_minify(content)
|
||||||
|
|
||||||
with open(dstfile, "w") as dst:
|
with open(dstfile, "w") as dst:
|
||||||
dst.write("const char ")
|
dst.write("const char ")
|
||||||
dst.write(varname)
|
dst.write(varname)
|
||||||
dst.write("[] PROGMEM = R\"==\"==(\n")
|
dst.write("[] PROGMEM = R\"==\"==(")
|
||||||
with open(srcfile, "r") as src:
|
dst.write(content)
|
||||||
for line in src.readlines():
|
dst.write(")==\"==\";\n")
|
||||||
dst.write(line)
|
dst.write("const int ");
|
||||||
dst.write("\n)==\"==\";\n")
|
dst.write(varname)
|
||||||
|
dst.write("_LEN = ");
|
||||||
|
dst.write(str(len(content)))
|
||||||
|
dst.write(";");
|
||||||
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -3,6 +3,59 @@
|
|||||||
#include <EEPROM.h>
|
#include <EEPROM.h>
|
||||||
#include "Arduino.h"
|
#include "Arduino.h"
|
||||||
|
|
||||||
|
struct ConfigObject {
|
||||||
|
uint8_t boardType;
|
||||||
|
char wifiSsid[32];
|
||||||
|
char wifiPassword[64];
|
||||||
|
char wifiIp[15];
|
||||||
|
char wifiGw[15];
|
||||||
|
char wifiSubnet[15];
|
||||||
|
char wifiDns1[15];
|
||||||
|
char wifiDns2[15];
|
||||||
|
char wifiHostname[32];
|
||||||
|
char mqttHost[128];
|
||||||
|
uint16_t mqttPort;
|
||||||
|
char mqttClientId[32];
|
||||||
|
char mqttPublishTopic[64];
|
||||||
|
char mqttSubscribeTopic[64];
|
||||||
|
char mqttUser[64];
|
||||||
|
char mqttPassword[64];
|
||||||
|
uint8_t mqttPayloadFormat;
|
||||||
|
bool mqttSsl;
|
||||||
|
uint8_t authSecurity;
|
||||||
|
char authUser[64];
|
||||||
|
char authPassword[64];
|
||||||
|
uint8_t meterType;
|
||||||
|
uint8_t distributionSystem;
|
||||||
|
uint8_t mainFuse;
|
||||||
|
uint8_t productionCapacity;
|
||||||
|
bool substituteMissing;
|
||||||
|
bool sendUnknown;
|
||||||
|
|
||||||
|
bool debugTelnet;
|
||||||
|
bool debugSerial;
|
||||||
|
uint8_t debugLevel;
|
||||||
|
|
||||||
|
uint8_t hanPin;
|
||||||
|
uint8_t apPin;
|
||||||
|
uint8_t ledPin;
|
||||||
|
bool ledInverted;
|
||||||
|
uint8_t ledPinRed;
|
||||||
|
uint8_t ledPinGreen;
|
||||||
|
uint8_t ledPinBlue;
|
||||||
|
bool ledRgbInverted;
|
||||||
|
uint8_t tempSensorPin;
|
||||||
|
uint8_t vccPin;
|
||||||
|
uint16_t vccMultiplier;
|
||||||
|
uint8_t vccBootLimit;
|
||||||
|
|
||||||
|
uint16_t domoELIDX;
|
||||||
|
uint16_t domoVL1IDX;
|
||||||
|
uint16_t domoVL2IDX;
|
||||||
|
uint16_t domoVL3IDX;
|
||||||
|
uint16_t domoCL1IDX;
|
||||||
|
};
|
||||||
|
|
||||||
class AmsConfiguration {
|
class AmsConfiguration {
|
||||||
public:
|
public:
|
||||||
bool hasConfig();
|
bool hasConfig();
|
||||||
@@ -10,128 +63,200 @@ public:
|
|||||||
|
|
||||||
bool load();
|
bool load();
|
||||||
bool save();
|
bool save();
|
||||||
|
|
||||||
|
uint8_t getBoardType();
|
||||||
|
void setBoardType(uint8_t boardType);
|
||||||
|
|
||||||
String getWifiSsid();
|
char* getWifiSsid();
|
||||||
void setWifiSsid(String wifiSsid);
|
void setWifiSsid(const char* wifiSsid);
|
||||||
String getWifiPassword();
|
char* getWifiPassword();
|
||||||
void setWifiPassword(String wifiPassword);
|
void setWifiPassword(const char* wifiPassword);
|
||||||
String getWifiIp();
|
char* getWifiIp();
|
||||||
void setWifiIp(String wifiIp);
|
void setWifiIp(const char* wifiIp);
|
||||||
String getWifiGw();
|
char* getWifiGw();
|
||||||
void setWifiGw(String wifiGw);
|
void setWifiGw(const char* wifiGw);
|
||||||
String getWifiSubnet();
|
char* getWifiSubnet();
|
||||||
void setWifiSubnet(String wifiSubnet);
|
void setWifiSubnet(const char* wifiSubnet);
|
||||||
String getWifiDns1();
|
char* getWifiDns1();
|
||||||
void setWifiDns1(String wifiDns1);
|
void setWifiDns1(const char* wifiDns1);
|
||||||
String getWifiDns2();
|
char* getWifiDns2();
|
||||||
void setWifiDns2(String wifiDns1);
|
void setWifiDns2(const char* wifiDns1);
|
||||||
String getWifiHostname();
|
char* getWifiHostname();
|
||||||
void setWifiHostname(String wifiHostname);
|
void setWifiHostname(const char* wifiHostname);
|
||||||
|
void clearWifi();
|
||||||
void clearWifiIp();
|
void clearWifiIp();
|
||||||
|
|
||||||
bool isWifiChanged();
|
bool isWifiChanged();
|
||||||
void ackWifiChange();
|
void ackWifiChange();
|
||||||
|
|
||||||
String getMqttHost();
|
char* getMqttHost();
|
||||||
void setMqttHost(String mqttHost);
|
void setMqttHost(const char* mqttHost);
|
||||||
int getMqttPort();
|
uint16_t getMqttPort();
|
||||||
void setMqttPort(int mqttPort);
|
void setMqttPort(uint16_t mqttPort);
|
||||||
String getMqttClientId();
|
char* getMqttClientId();
|
||||||
void setMqttClientId(String mqttClientId);
|
void setMqttClientId(const char* mqttClientId);
|
||||||
String getMqttPublishTopic();
|
char* getMqttPublishTopic();
|
||||||
void setMqttPublishTopic(String mqttPublishTopic);
|
void setMqttPublishTopic(const char* mqttPublishTopic);
|
||||||
String getMqttSubscribeTopic();
|
char* getMqttSubscribeTopic();
|
||||||
void setMqttSubscribeTopic(String mqttSubscribeTopic);
|
void setMqttSubscribeTopic(const char* mqttSubscribeTopic);
|
||||||
String getMqttUser();
|
char* getMqttUser();
|
||||||
void setMqttUser(String mqttUser);
|
void setMqttUser(const char* mqttUser);
|
||||||
String getMqttPassword();
|
char* getMqttPassword();
|
||||||
void setMqttPassword(String mqttPassword);
|
void setMqttPassword(const char* mqttPassword);
|
||||||
int getMqttPayloadFormat();
|
uint8_t getMqttPayloadFormat();
|
||||||
void setMqttPayloadFormat(int mqttPayloadFormat);
|
void setMqttPayloadFormat(uint8_t mqttPayloadFormat);
|
||||||
|
bool isMqttSsl();
|
||||||
|
void setMqttSsl(bool mqttSsl);
|
||||||
void clearMqtt();
|
void clearMqtt();
|
||||||
|
|
||||||
|
void setMqttChanged();
|
||||||
bool isMqttChanged();
|
bool isMqttChanged();
|
||||||
void ackMqttChange();
|
void ackMqttChange();
|
||||||
|
|
||||||
byte getAuthSecurity();
|
byte getAuthSecurity();
|
||||||
void setAuthSecurity(byte authSecurity);
|
void setAuthSecurity(byte authSecurity);
|
||||||
String getAuthUser();
|
char* getAuthUser();
|
||||||
void setAuthUser(String authUser);
|
void setAuthUser(const char* authUser);
|
||||||
String getAuthPassword();
|
char* getAuthPassword();
|
||||||
void setAuthPassword(String authPassword);
|
void setAuthPassword(const char* authPassword);
|
||||||
void clearAuth();
|
void clearAuth();
|
||||||
|
|
||||||
int getMeterType();
|
uint8_t getMeterType();
|
||||||
void setMeterType(int meterType);
|
void setMeterType(uint8_t meterType);
|
||||||
int getDistributionSystem();
|
uint8_t getDistributionSystem();
|
||||||
void setDistributionSystem(int distributionSystem);
|
void setDistributionSystem(uint8_t distributionSystem);
|
||||||
int getMainFuse();
|
uint8_t getMainFuse();
|
||||||
void setMainFuse(int mainFuse);
|
void setMainFuse(uint8_t mainFuse);
|
||||||
int getProductionCapacity();
|
uint8_t getProductionCapacity();
|
||||||
void setProductionCapacity(int productionCapacity);
|
void setProductionCapacity(uint8_t productionCapacity);
|
||||||
|
bool isSubstituteMissing();
|
||||||
|
void setSubstituteMissing(bool substituteMissing);
|
||||||
|
bool isSendUnknown();
|
||||||
|
void setSendUnknown(bool sendUnknown);
|
||||||
|
void clearMeter();
|
||||||
|
|
||||||
bool isDebugTelnet();
|
bool isDebugTelnet();
|
||||||
void setDebugTelnet(bool debugTelnet);
|
void setDebugTelnet(bool debugTelnet);
|
||||||
bool isDebugSerial();
|
bool isDebugSerial();
|
||||||
void setDebugSerial(bool debugSerial);
|
void setDebugSerial(bool debugSerial);
|
||||||
int getDebugLevel();
|
uint8_t getDebugLevel();
|
||||||
void setDebugLevel(int debugLevel);
|
void setDebugLevel(uint8_t debugLevel);
|
||||||
|
|
||||||
|
bool pinUsed(uint8_t pin);
|
||||||
|
|
||||||
|
uint8_t getHanPin();
|
||||||
|
void setHanPin(uint8_t hanPin);
|
||||||
|
uint8_t getApPin();
|
||||||
|
void setApPin(uint8_t apPin);
|
||||||
|
uint8_t getLedPin();
|
||||||
|
void setLedPin(uint8_t ledPin);
|
||||||
|
bool isLedInverted();
|
||||||
|
void setLedInverted(bool ledInverted);
|
||||||
|
|
||||||
|
uint8_t getLedPinRed();
|
||||||
|
void setLedPinRed(uint8_t ledPinRed);
|
||||||
|
uint8_t getLedPinGreen();
|
||||||
|
void setLedPinGreen(uint8_t ledPinGreen);
|
||||||
|
uint8_t getLedPinBlue();
|
||||||
|
void setLedPinBlue(uint8_t ledPinBlue);
|
||||||
|
bool isLedRgbInverted();
|
||||||
|
void setLedRgbInverted(bool ledRgbInverted);
|
||||||
|
|
||||||
|
uint8_t getTempSensorPin();
|
||||||
|
void setTempSensorPin(uint8_t tempSensorPin);
|
||||||
|
uint8_t getVccPin();
|
||||||
|
void setVccPin(uint8_t vccPin);
|
||||||
|
double getVccMultiplier();
|
||||||
|
void setVccMultiplier(double vccMultiplier);
|
||||||
|
double getVccBootLimit();
|
||||||
|
void setVccBootLimit(double vccBootLimit);
|
||||||
|
|
||||||
void print(Print* debugger);
|
void print(Print* debugger);
|
||||||
|
|
||||||
|
uint16_t getDomoELIDX();
|
||||||
|
uint16_t getDomoVL1IDX();
|
||||||
|
uint16_t getDomoVL2IDX();
|
||||||
|
uint16_t getDomoVL3IDX();
|
||||||
|
uint16_t getDomoCL1IDX();
|
||||||
|
void setDomoELIDX(uint16_t domoELIDX);
|
||||||
|
void setDomoVL1IDX(uint16_t domoVL1IDX);
|
||||||
|
void setDomoVL2IDX(uint16_t domoVL2IDX);
|
||||||
|
void setDomoVL3IDX(uint16_t domoVL3IDX);
|
||||||
|
void setDomoCL1IDX(uint16_t domoCL1IDX);
|
||||||
|
void clearDomo();
|
||||||
|
|
||||||
|
bool isDomoChanged();
|
||||||
|
void ackDomoChange();
|
||||||
|
|
||||||
|
void clear();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int configVersion = 0;
|
int configVersion = 0;
|
||||||
|
ConfigObject config {
|
||||||
|
0, // Board type
|
||||||
|
"", // SSID
|
||||||
|
"", // PSK
|
||||||
|
"", // IP
|
||||||
|
"", // GW
|
||||||
|
"", // Subnet
|
||||||
|
"", // DNS 1
|
||||||
|
"", // DNS 2
|
||||||
|
"", // Hostname
|
||||||
|
"", // MQTT host
|
||||||
|
1883, // Port
|
||||||
|
"", // Client ID
|
||||||
|
"", // Publish topic
|
||||||
|
"", // Subscribe topic
|
||||||
|
"", // Username
|
||||||
|
"", // Password
|
||||||
|
0, // Format
|
||||||
|
false, // SSL
|
||||||
|
0, // Web security
|
||||||
|
"", // Username
|
||||||
|
"", // Password
|
||||||
|
0, // Meter type
|
||||||
|
0, // Distribution system
|
||||||
|
0, // Main fuse
|
||||||
|
0, // Production capacity
|
||||||
|
false, // Substitute
|
||||||
|
false, // Send unknown
|
||||||
|
false, // Debug telnet
|
||||||
|
false, // Debug serial
|
||||||
|
5, // Debug level
|
||||||
|
0x03, // HAN pin
|
||||||
|
0xFF, // AP pin
|
||||||
|
0x02, // LED pin
|
||||||
|
true, // Inverted
|
||||||
|
0xFF, // Red
|
||||||
|
0xFF, // Green
|
||||||
|
0xFF, // Blue
|
||||||
|
true, // Inverted
|
||||||
|
0xFF, // Temp sensor
|
||||||
|
0xFF, // Vcc
|
||||||
|
100, // Multiplier
|
||||||
|
0, // Boot limit
|
||||||
|
//Domoticz
|
||||||
|
0, // ELIDX
|
||||||
|
0, // VL1IDX
|
||||||
|
0, // VL2IDX
|
||||||
|
0, // VL3IDX
|
||||||
|
0 // CL1IDX
|
||||||
|
// 786 bytes
|
||||||
|
};
|
||||||
|
bool wifiChanged, mqttChanged, domoChanged;
|
||||||
|
|
||||||
String wifiSsid;
|
const int EEPROM_SIZE = 790; // Config size + 4 bytes for config version
|
||||||
String wifiPassword;
|
const int EEPROM_CHECK_SUM = 82; // Used to check if config is stored. Change if structure changes
|
||||||
String wifiIp;
|
|
||||||
String wifiGw;
|
|
||||||
String wifiSubnet;
|
|
||||||
String wifiDns1;
|
|
||||||
String wifiDns2;
|
|
||||||
String wifiHostname;
|
|
||||||
bool wifiChanged = false;
|
|
||||||
|
|
||||||
String mqttHost;
|
|
||||||
int mqttPort = 1883;
|
|
||||||
String mqttClientId;
|
|
||||||
String mqttPublishTopic;
|
|
||||||
String mqttSubscribeTopic;
|
|
||||||
String mqttUser;
|
|
||||||
String mqttPassword;
|
|
||||||
int mqttPayloadFormat = 0;
|
|
||||||
bool mqttChanged = false;
|
|
||||||
|
|
||||||
byte authSecurity;
|
|
||||||
String authUser;
|
|
||||||
String authPassword;
|
|
||||||
|
|
||||||
int meterType = 0, distributionSystem = 0, mainFuse = 0, productionCapacity = 0;
|
|
||||||
|
|
||||||
bool debugTelnet = false, debugSerial = false;
|
|
||||||
int debugLevel = 3;
|
|
||||||
|
|
||||||
const int EEPROM_SIZE = 512;
|
|
||||||
const int EEPROM_CHECK_SUM = 81; // Used to check if config is stored. Change if structure changes
|
|
||||||
const int EEPROM_CONFIG_ADDRESS = 0;
|
const int EEPROM_CONFIG_ADDRESS = 0;
|
||||||
|
|
||||||
bool loadConfig72(int address);
|
|
||||||
bool loadConfig75(int address);
|
|
||||||
bool loadConfig80(int address);
|
bool loadConfig80(int address);
|
||||||
bool loadConfig81(int address);
|
bool loadConfig81(int address);
|
||||||
|
|
||||||
int saveString(int pAddress, const char* pString);
|
|
||||||
int readString(int pAddress, char* pString[]);
|
int readString(int pAddress, char* pString[]);
|
||||||
int saveInt(int pAddress, int pValue);
|
|
||||||
int readInt(int pAddress, int *pValue);
|
int readInt(int pAddress, int *pValue);
|
||||||
int saveBool(int pAddress, bool pValue);
|
|
||||||
int readBool(int pAddress, bool *pValue);
|
int readBool(int pAddress, bool *pValue);
|
||||||
int saveByte(int pAddress, byte pValue);
|
|
||||||
int readByte(int pAddress, byte *pValue);
|
int readByte(int pAddress, byte *pValue);
|
||||||
|
|
||||||
template <class T> int writeAnything(int ee, const T& value);
|
|
||||||
template <class T> int readAnything(int ee, T& value);
|
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
AmsData::AmsData() {}
|
AmsData::AmsData() {}
|
||||||
|
|
||||||
AmsData::AmsData(int meterType, HanReader& hanReader) {
|
AmsData::AmsData(int meterType, bool substituteMissing, HanReader& hanReader) {
|
||||||
lastUpdateMillis = millis();
|
lastUpdateMillis = millis();
|
||||||
packageTimestamp = hanReader.getPackageTime();
|
packageTimestamp = hanReader.getPackageTime();
|
||||||
|
|
||||||
@@ -15,10 +15,10 @@ AmsData::AmsData(int meterType, HanReader& hanReader) {
|
|||||||
extractFromKaifa(hanReader, listSize);
|
extractFromKaifa(hanReader, listSize);
|
||||||
break;
|
break;
|
||||||
case METER_TYPE_AIDON:
|
case METER_TYPE_AIDON:
|
||||||
extractFromAidon(hanReader, listSize);
|
extractFromAidon(hanReader, listSize, substituteMissing);
|
||||||
break;
|
break;
|
||||||
case METER_TYPE_KAMSTRUP:
|
case METER_TYPE_KAMSTRUP:
|
||||||
extractFromKamstrup(hanReader, listSize);
|
extractFromKamstrup(hanReader, listSize, substituteMissing);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -87,7 +87,7 @@ void AmsData::extractFromKaifa(HanReader& hanReader, int listSize) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AmsData::extractFromAidon(HanReader& hanReader, int listSize) {
|
void AmsData::extractFromAidon(HanReader& hanReader, int listSize, bool substituteMissing) {
|
||||||
switch(listSize) {
|
switch(listSize) {
|
||||||
case (int)Aidon::List1:
|
case (int)Aidon::List1:
|
||||||
listType = 1;
|
listType = 1;
|
||||||
@@ -168,19 +168,23 @@ void AmsData::extractFromAidon(HanReader& hanReader, int listSize) {
|
|||||||
l1voltage = ((double) hanReader.getInt( (int)Aidon_List3PhaseIT::VoltageL1)) / 10;
|
l1voltage = ((double) hanReader.getInt( (int)Aidon_List3PhaseIT::VoltageL1)) / 10;
|
||||||
l2voltage = ((double) hanReader.getInt( (int)Aidon_List3PhaseIT::VoltageL2)) / 10;
|
l2voltage = ((double) hanReader.getInt( (int)Aidon_List3PhaseIT::VoltageL2)) / 10;
|
||||||
l3voltage = ((double) hanReader.getInt( (int)Aidon_List3PhaseIT::VoltageL3)) / 10;
|
l3voltage = ((double) hanReader.getInt( (int)Aidon_List3PhaseIT::VoltageL3)) / 10;
|
||||||
//l2current = ((activeImportPower * sqrt(3)) - (l1voltage * l1current) - (l3voltage * l3current)) / l2voltage;
|
if(substituteMissing) {
|
||||||
|
l2current = ((activeImportPower * sqrt(3)) - (l1voltage * l1current) - (l3voltage * l3current)) / l2voltage;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AmsData::extractFromKamstrup(HanReader& hanReader, int listSize) {
|
void AmsData::extractFromKamstrup(HanReader& hanReader, int listSize, bool substituteMissing) {
|
||||||
switch(listSize) {
|
switch(listSize) {
|
||||||
|
case (int)Kamstrup::List3PhaseITShort:
|
||||||
case (int)Kamstrup::List3PhaseShort:
|
case (int)Kamstrup::List3PhaseShort:
|
||||||
threePhase = true;
|
threePhase = true;
|
||||||
case (int)Kamstrup::List1PhaseShort:
|
case (int)Kamstrup::List1PhaseShort:
|
||||||
listType = 2;
|
listType = 2;
|
||||||
break;
|
break;
|
||||||
|
case (int)Kamstrup::List3PhaseITLong:
|
||||||
case (int)Kamstrup::List3PhaseLong:
|
case (int)Kamstrup::List3PhaseLong:
|
||||||
threePhase = true;
|
threePhase = true;
|
||||||
case (int)Kamstrup::List1PhaseLong:
|
case (int)Kamstrup::List1PhaseLong:
|
||||||
@@ -189,6 +193,23 @@ void AmsData::extractFromKamstrup(HanReader& hanReader, int listSize) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch(listSize) {
|
switch(listSize) {
|
||||||
|
case (int)Kamstrup::List1PhaseLong:
|
||||||
|
meterTimestamp = hanReader.getTime( (int)Kamstrup_List1Phase::MeterClock);
|
||||||
|
activeImportCounter = ((double) hanReader.getInt((int)Kamstrup_List1Phase::CumulativeActiveImportEnergy)) / 100;
|
||||||
|
activeExportCounter = ((double) hanReader.getInt((int)Kamstrup_List1Phase::CumulativeActiveExportEnergy)) / 100;
|
||||||
|
reactiveImportCounter = ((double) hanReader.getInt((int)Kamstrup_List1Phase::CumulativeReactiveImportEnergy)) / 100;
|
||||||
|
reactiveExportCounter = ((double) hanReader.getInt((int)Kamstrup_List1Phase::CumulativeReactiveExportEnergy)) / 100;
|
||||||
|
case (int)Kamstrup::List1PhaseShort:
|
||||||
|
listId = hanReader.getString( (int)Kamstrup_List1Phase::ListVersionIdentifier);
|
||||||
|
meterId = hanReader.getString( (int)Kamstrup_List1Phase::MeterID);
|
||||||
|
meterType = hanReader.getString( (int)Kamstrup_List1Phase::MeterType);
|
||||||
|
activeImportPower = hanReader.getInt( (int)Kamstrup_List1Phase::ActiveImportPower);
|
||||||
|
reactiveImportPower = hanReader.getInt( (int)Kamstrup_List1Phase::ReactiveImportPower);
|
||||||
|
activeExportPower = hanReader.getInt( (int)Kamstrup_List1Phase::ActiveExportPower);
|
||||||
|
reactiveExportPower = hanReader.getInt( (int)Kamstrup_List1Phase::ReactiveExportPower);
|
||||||
|
l1current = ((double) hanReader.getInt((int)Kamstrup_List1Phase::CurrentL1)) / 100;
|
||||||
|
l1voltage = hanReader.getInt( (int)Kamstrup_List1Phase::VoltageL1);
|
||||||
|
break;
|
||||||
case (int)Kamstrup::List3PhaseLong:
|
case (int)Kamstrup::List3PhaseLong:
|
||||||
meterTimestamp = hanReader.getTime( (int)Kamstrup_List3Phase::MeterClock);
|
meterTimestamp = hanReader.getTime( (int)Kamstrup_List3Phase::MeterClock);
|
||||||
activeImportCounter = ((double) hanReader.getInt((int)Kamstrup_List3Phase::CumulativeActiveImportEnergy)) / 100;
|
activeImportCounter = ((double) hanReader.getInt((int)Kamstrup_List3Phase::CumulativeActiveImportEnergy)) / 100;
|
||||||
@@ -210,22 +231,29 @@ void AmsData::extractFromKamstrup(HanReader& hanReader, int listSize) {
|
|||||||
l2voltage = hanReader.getInt( (int)Kamstrup_List3Phase::VoltageL2);
|
l2voltage = hanReader.getInt( (int)Kamstrup_List3Phase::VoltageL2);
|
||||||
l3voltage = hanReader.getInt( (int)Kamstrup_List3Phase::VoltageL3);
|
l3voltage = hanReader.getInt( (int)Kamstrup_List3Phase::VoltageL3);
|
||||||
break;
|
break;
|
||||||
case (int)Kamstrup::List1PhaseLong:
|
case (int)Kamstrup::List3PhaseITLong:
|
||||||
meterTimestamp = hanReader.getTime( (int)Kamstrup_List1Phase::MeterClock);
|
meterTimestamp = hanReader.getTime( (int)Kamstrup_List3Phase::MeterClock);
|
||||||
activeImportCounter = ((double) hanReader.getInt((int)Kamstrup_List1Phase::CumulativeActiveImportEnergy)) / 100;
|
activeImportCounter = ((double) hanReader.getInt((int)Kamstrup_List3Phase::CumulativeActiveImportEnergy)) / 100;
|
||||||
activeExportCounter = ((double) hanReader.getInt((int)Kamstrup_List1Phase::CumulativeActiveExportEnergy)) / 100;
|
activeExportCounter = ((double) hanReader.getInt((int)Kamstrup_List3Phase::CumulativeActiveExportEnergy)) / 100;
|
||||||
reactiveImportCounter = ((double) hanReader.getInt((int)Kamstrup_List1Phase::CumulativeReactiveImportEnergy)) / 100;
|
reactiveImportCounter = ((double) hanReader.getInt((int)Kamstrup_List3Phase::CumulativeReactiveImportEnergy)) / 100;
|
||||||
reactiveExportCounter = ((double) hanReader.getInt((int)Kamstrup_List1Phase::CumulativeReactiveExportEnergy)) / 100;
|
reactiveExportCounter = ((double) hanReader.getInt((int)Kamstrup_List3Phase::CumulativeReactiveExportEnergy)) / 100;
|
||||||
case (int)Kamstrup::List1PhaseShort:
|
case (int)Kamstrup::List3PhaseITShort:
|
||||||
listId = hanReader.getString( (int)Kamstrup_List1Phase::ListVersionIdentifier);
|
listId = hanReader.getString( (int)Kamstrup_List3Phase::ListVersionIdentifier);
|
||||||
meterId = hanReader.getString( (int)Kamstrup_List1Phase::MeterID);
|
meterId = hanReader.getString( (int)Kamstrup_List3Phase::MeterID);
|
||||||
meterType = hanReader.getString( (int)Kamstrup_List1Phase::MeterType);
|
meterType = hanReader.getString( (int)Kamstrup_List3Phase::MeterType);
|
||||||
activeImportPower = hanReader.getInt( (int)Kamstrup_List1Phase::ActiveImportPower);
|
activeImportPower = hanReader.getInt( (int)Kamstrup_List3Phase::ActiveImportPower);
|
||||||
reactiveImportPower = hanReader.getInt( (int)Kamstrup_List1Phase::ReactiveImportPower);
|
reactiveImportPower = hanReader.getInt( (int)Kamstrup_List3Phase::ReactiveImportPower);
|
||||||
activeExportPower = hanReader.getInt( (int)Kamstrup_List1Phase::ActiveExportPower);
|
activeExportPower = hanReader.getInt( (int)Kamstrup_List3Phase::ActiveExportPower);
|
||||||
reactiveExportPower = hanReader.getInt( (int)Kamstrup_List1Phase::ReactiveExportPower);
|
reactiveExportPower = hanReader.getInt( (int)Kamstrup_List3Phase::ReactiveExportPower);
|
||||||
l1current = ((double) hanReader.getInt((int)Kamstrup_List1Phase::CurrentL1)) / 100;
|
l1current = ((double) hanReader.getInt((int)Kamstrup_List3Phase::CurrentL1)) / 100;
|
||||||
l1voltage = hanReader.getInt( (int)Kamstrup_List1Phase::VoltageL1);
|
l2current = 0;
|
||||||
|
l3current = ((double) hanReader.getInt((int)Kamstrup_List3Phase::CurrentL3)) / 100;
|
||||||
|
l1voltage = hanReader.getInt( (int)Kamstrup_List3Phase::VoltageL1);
|
||||||
|
l2voltage = hanReader.getInt( (int)Kamstrup_List3Phase::VoltageL2);
|
||||||
|
l3voltage = hanReader.getInt( (int)Kamstrup_List3Phase::VoltageL3);
|
||||||
|
if(substituteMissing) {
|
||||||
|
l2current = ((activeImportPower * sqrt(3)) - (l1voltage * l1current) - (l3voltage * l3current)) / l2voltage;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
class AmsData {
|
class AmsData {
|
||||||
public:
|
public:
|
||||||
AmsData();
|
AmsData();
|
||||||
AmsData(int meterType, HanReader& hanReader);
|
AmsData(int meterType, bool substituteMissing, HanReader& hanReader);
|
||||||
|
|
||||||
void apply(AmsData& other);
|
void apply(AmsData& other);
|
||||||
|
|
||||||
@@ -60,8 +60,8 @@ private:
|
|||||||
bool threePhase = false;
|
bool threePhase = false;
|
||||||
|
|
||||||
void extractFromKaifa(HanReader& hanReader, int listSize);
|
void extractFromKaifa(HanReader& hanReader, int listSize);
|
||||||
void extractFromAidon(HanReader& hanReader, int listSize);
|
void extractFromAidon(HanReader& hanReader, int listSize, bool substituteMissing);
|
||||||
void extractFromKamstrup(HanReader& hanReader, int listSize);
|
void extractFromKamstrup(HanReader& hanReader, int listSize, bool substituteMissing);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
10
src/AmsStorage.h
Normal file
10
src/AmsStorage.h
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
#ifndef _AMSSTORAGE_H
|
||||||
|
#define _AMSSTORAGE_H
|
||||||
|
|
||||||
|
#define FILE_FIRMWARE "/firmware.bin"
|
||||||
|
|
||||||
|
#define FILE_MQTT_CA "/mqtt-ca.pem"
|
||||||
|
#define FILE_MQTT_CERT "/mqtt-cert.pem"
|
||||||
|
#define FILE_MQTT_KEY "/mqtt-key.pem"
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -5,73 +5,17 @@
|
|||||||
|
|
||||||
#define INVALID_BUTTON_PIN 0xFFFFFFFF
|
#define INVALID_BUTTON_PIN 0xFFFFFFFF
|
||||||
|
|
||||||
|
#include <SoftwareSerial.h>
|
||||||
|
|
||||||
#if defined(ESP8266)
|
#if defined(ESP8266)
|
||||||
#include <ESP8266WiFi.h>
|
#include <ESP8266WiFi.h>
|
||||||
#include <ESP8266mDNS.h>
|
#include <ESP8266mDNS.h>
|
||||||
#elif defined(ESP32)
|
#elif defined(ESP32)
|
||||||
#include <WiFi.h>
|
#include <WiFi.h>
|
||||||
|
#include <WiFiClientSecure.h>
|
||||||
#include <ESPmDNS.h>
|
#include <ESPmDNS.h>
|
||||||
#include "SPIFFS.h"
|
#include "SPIFFS.h"
|
||||||
#include "Update.h"
|
#include "Update.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define RGB_RED 1
|
|
||||||
#define RGB_GREEN 2
|
|
||||||
#define RGB_YELLOW 3
|
|
||||||
#define RGB_ON 1
|
|
||||||
#define RGB_OFF 0
|
|
||||||
|
|
||||||
// Build settings for custom hardware by Roar Fredriksen
|
|
||||||
#if HW_ROARFRED
|
|
||||||
#define LED_PIN 2 // The blue on-board LED of the ESP8266 custom AMS board
|
|
||||||
#define LED_ACTIVE_HIGH 0
|
|
||||||
#define AP_BUTTON_PIN 0
|
|
||||||
|
|
||||||
HardwareSerial *hanSerial = &Serial;
|
|
||||||
|
|
||||||
// Build settings for Wemos Lolin D32
|
|
||||||
#elif defined(ARDUINO_LOLIN_D32)
|
|
||||||
#define LED_PIN 5
|
|
||||||
#define LED_ACTIVE_HIGH 0
|
|
||||||
#define AP_BUTTON_PIN 4
|
|
||||||
|
|
||||||
HardwareSerial *hanSerial = &Serial2;
|
|
||||||
|
|
||||||
// Build settings for Wemos D1 mini
|
|
||||||
#elif defined(ARDUINO_ESP8266_WEMOS_D1MINI)
|
|
||||||
#define LED_PIN D4
|
|
||||||
#define LED_ACTIVE_HIGH 0
|
|
||||||
#define AP_BUTTON_PIN D2
|
|
||||||
|
|
||||||
#define SOFTWARE_SERIAL 1
|
|
||||||
#include <SoftwareSerial.h>
|
|
||||||
SoftwareSerial *hanSerial = new SoftwareSerial(D1);
|
|
||||||
|
|
||||||
// Build settings for Adafruit Feather ESP32
|
|
||||||
#elif defined(ARDUINO_FEATHER_ESP32)
|
|
||||||
#define LED_PIN LED_BUILTIN
|
|
||||||
#define LED_ACTIVE_HIGH 1
|
|
||||||
#define AP_BUTTON_PIN INVALID_BUTTON_PIN
|
|
||||||
|
|
||||||
HardwareSerial *hanSerial = &Serial2;
|
|
||||||
|
|
||||||
// Default build for ESP32
|
|
||||||
#elif defined(ESP32)
|
|
||||||
#define LED_PIN INVALID_BUTTON_PIN
|
|
||||||
#define LED_ACTIVE_HIGH 1
|
|
||||||
#define AP_BUTTON_PIN INVALID_BUTTON_PIN
|
|
||||||
|
|
||||||
HardwareSerial *hanSerial = &Serial2;
|
|
||||||
|
|
||||||
// Default build settings
|
|
||||||
#else
|
|
||||||
#define LED_PIN 2
|
|
||||||
#define LED_ACTIVE_HIGH 0
|
|
||||||
#define AP_BUTTON_PIN INVALID_BUTTON_PIN
|
|
||||||
#define SOFTWARE_SERIAL 1
|
|
||||||
#include <SoftwareSerial.h>
|
|
||||||
SoftwareSerial *hanSerial = new SoftwareSerial(5);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,8 @@
|
|||||||
#include "HanToJson.h"
|
#include "HanToJson.h"
|
||||||
|
|
||||||
void hanToJson(JsonDocument& json, AmsData& data, HwTools& hw, double temperature) {
|
void hanToJson(JsonDocument& json, AmsData& data, HwTools& hw, double temperature, String name) {
|
||||||
json["id"] = WiFi.macAddress();
|
json["id"] = WiFi.macAddress();
|
||||||
|
json["name"] = name;
|
||||||
json["up"] = millis();
|
json["up"] = millis();
|
||||||
json["t"] = data.getPackageTimestamp();
|
json["t"] = data.getPackageTimestamp();
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,6 @@
|
|||||||
#include "AmsData.h"
|
#include "AmsData.h"
|
||||||
#include "HwTools.h"
|
#include "HwTools.h"
|
||||||
|
|
||||||
void hanToJson(JsonDocument& json, AmsData& data, HwTools& hw, double temperature);
|
void hanToJson(JsonDocument& json, AmsData& data, HwTools& hw, double temperature, String name);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
194
src/HwTools.cpp
194
src/HwTools.cpp
@@ -1,44 +1,184 @@
|
|||||||
#include "HwTools.h"
|
#include "HwTools.h"
|
||||||
|
|
||||||
|
void HwTools::setTempSensorPin(int tempSensorPin) {
|
||||||
|
if(tempSensorPin != this->tempSensorPin) {
|
||||||
|
this->tempSensorInit = false;
|
||||||
|
if(tempSensor)
|
||||||
|
delete tempSensor;
|
||||||
|
if(oneWire)
|
||||||
|
delete oneWire;
|
||||||
|
if(tempSensorPin > 0 && tempSensorPin < 40) {
|
||||||
|
this->tempSensorPin = tempSensorPin;
|
||||||
|
pinMode(tempSensorPin, INPUT);
|
||||||
|
} else {
|
||||||
|
this->tempSensorPin = 0xFF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HwTools::setVccPin(int vccPin) {
|
||||||
|
if(vccPin > 0 && vccPin < 40) {
|
||||||
|
pinMode(vccPin, INPUT);
|
||||||
|
this->vccPin = vccPin;
|
||||||
|
} else {
|
||||||
|
this->vccPin = 0xFF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HwTools::setVccMultiplier(double vccMultiplier) {
|
||||||
|
this->vccMultiplier = vccMultiplier;
|
||||||
|
}
|
||||||
|
|
||||||
double HwTools::getVcc() {
|
double HwTools::getVcc() {
|
||||||
double volts = 0.0;
|
double volts = 0.0;
|
||||||
#if defined(ARDUINO_ESP8266_WEMOS_D1MINI)
|
if(vccPin != 0xFF) {
|
||||||
volts = (((double) ESP.getVcc()) / 900.0); // This board has a voltage divider on VCC.
|
#if defined(ESP8266)
|
||||||
#elif defined(ARDUINO_LOLIN_D32)
|
volts = (analogRead(vccPin) / 1024.0) * 3.3;
|
||||||
volts = (analogRead(GPIO_NUM_35) / 4095.0) * 3.3 * 2.25; // We are actually reading battery voltage here
|
#elif defined(ESP32)
|
||||||
#elif defined(ESP8266)
|
volts = (analogRead(vccPin) / 4095.0) * 3.3;
|
||||||
volts = ((double) ESP.getVcc()) / 1024.0;
|
#endif
|
||||||
#endif
|
} else {
|
||||||
|
#if defined(ESP8266)
|
||||||
|
volts = ((double) ESP.getVcc()) / 1024.0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(ESP_VCC_CALIB_FACTOR)
|
return volts > 0.0 ? volts * vccMultiplier : 0.0;
|
||||||
return volts * ESP_VCC_CALIB_FACTOR;
|
|
||||||
#else
|
|
||||||
return volts;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
double HwTools::getTemperature() {
|
double HwTools::getTemperature() {
|
||||||
|
if(tempSensorPin != 0xFF) {
|
||||||
|
if(!tempSensorInit) {
|
||||||
|
oneWire = new OneWire(tempSensorPin);
|
||||||
|
tempSensor = new DallasTemperature(this->oneWire);
|
||||||
|
tempSensor->begin();
|
||||||
|
delay(50);
|
||||||
|
tempSensor->requestTemperatures();
|
||||||
|
hasTempSensor = tempSensor->getTempCByIndex(0) != DEVICE_DISCONNECTED_C;
|
||||||
|
tempSensorInit = true;
|
||||||
|
}
|
||||||
|
|
||||||
#if defined TEMP_SENSOR_PIN
|
if(hasTempSensor) {
|
||||||
if(!tempSensorInit) {
|
tempSensor->requestTemperatures();
|
||||||
tempSensor->begin();
|
return tempSensor->getTempCByIndex(0);
|
||||||
delay(50);
|
} else {
|
||||||
tempSensor->requestTemperatures();
|
return DEVICE_DISCONNECTED_C;
|
||||||
hasTempSensor = tempSensor->getTempCByIndex(0) != DEVICE_DISCONNECTED_C;
|
}
|
||||||
tempSensorInit = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(hasTempSensor) {
|
|
||||||
tempSensor->requestTemperatures();
|
|
||||||
return tempSensor->getTempCByIndex(0);
|
|
||||||
} else {
|
|
||||||
return DEVICE_DISCONNECTED_C;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return DEVICE_DISCONNECTED_C;
|
return DEVICE_DISCONNECTED_C;
|
||||||
}
|
}
|
||||||
|
|
||||||
int HwTools::getWifiRssi() {
|
int HwTools::getWifiRssi() {
|
||||||
int rssi = WiFi.RSSI();
|
int rssi = WiFi.RSSI();
|
||||||
return isnan(rssi) ? -100.0 : rssi;
|
return isnan(rssi) ? -100.0 : rssi;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HwTools::setLed(uint8_t ledPin, bool ledInverted) {
|
||||||
|
if(ledPin > 0 && ledPin < 40) {
|
||||||
|
this->ledPin = ledPin;
|
||||||
|
this->ledInverted = ledInverted;
|
||||||
|
pinMode(ledPin, OUTPUT);
|
||||||
|
ledOff(LED_INTERNAL);
|
||||||
|
} else {
|
||||||
|
this->ledPin = 0xFF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HwTools::setLedRgb(uint8_t ledPinRed, uint8_t ledPinGreen, uint8_t ledPinBlue, bool ledRgbInverted) {
|
||||||
|
this->ledRgbInverted = ledRgbInverted;
|
||||||
|
if(ledPinRed > 0 && ledPinRed < 40) {
|
||||||
|
this->ledPinRed = ledPinRed;
|
||||||
|
pinMode(ledPinRed, OUTPUT);
|
||||||
|
ledOff(LED_RED);
|
||||||
|
} else {
|
||||||
|
this->ledPinRed = 0xFF;
|
||||||
|
}
|
||||||
|
if(ledPinGreen > 0 && ledPinGreen < 40) {
|
||||||
|
this->ledPinGreen = ledPinGreen;
|
||||||
|
pinMode(ledPinGreen, OUTPUT);
|
||||||
|
ledOff(LED_GREEN);
|
||||||
|
} else {
|
||||||
|
this->ledPinGreen = 0xFF;
|
||||||
|
}
|
||||||
|
if(ledPinBlue > 0 && ledPinBlue < 40) {
|
||||||
|
this->ledPinBlue = ledPinBlue;
|
||||||
|
pinMode(ledPinBlue, OUTPUT);
|
||||||
|
ledOff(LED_BLUE);
|
||||||
|
} else {
|
||||||
|
this->ledPinBlue = 0xFF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HwTools::ledOn(uint8_t color) {
|
||||||
|
if(color == LED_INTERNAL) {
|
||||||
|
return writeLedPin(color, ledInverted ? LOW : HIGH);
|
||||||
|
} else {
|
||||||
|
return writeLedPin(color, ledRgbInverted ? LOW : HIGH);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HwTools::ledOff(uint8_t color) {
|
||||||
|
if(color == LED_INTERNAL) {
|
||||||
|
return writeLedPin(color, ledInverted ? HIGH : LOW);
|
||||||
|
} else {
|
||||||
|
return writeLedPin(color, ledRgbInverted ? HIGH : LOW);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HwTools::ledBlink(uint8_t color, uint8_t blink) {
|
||||||
|
for(int i = 0; i < blink; i++) {
|
||||||
|
if(!ledOn(color)) return false;
|
||||||
|
delay(50);
|
||||||
|
ledOff(color);
|
||||||
|
if(i != blink)
|
||||||
|
delay(50);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HwTools::writeLedPin(uint8_t color, uint8_t state) {
|
||||||
|
switch(color) {
|
||||||
|
case LED_INTERNAL:
|
||||||
|
if(ledPin != 0xFF) {
|
||||||
|
digitalWrite(ledPin, state);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case LED_RED:
|
||||||
|
if(ledPinRed != 0xFF) {
|
||||||
|
digitalWrite(ledPinRed, state);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case LED_GREEN:
|
||||||
|
if(ledPinGreen != 0xFF) {
|
||||||
|
digitalWrite(ledPinGreen, state);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case LED_BLUE:
|
||||||
|
if(ledPinBlue != 0xFF) {
|
||||||
|
digitalWrite(ledPinBlue, state);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case LED_YELLOW:
|
||||||
|
if(ledPinRed != 0xFF && ledPinGreen != 0xFF) {
|
||||||
|
digitalWrite(ledPinRed, state);
|
||||||
|
digitalWrite(ledPinGreen, state);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|||||||
@@ -12,35 +12,38 @@
|
|||||||
#include <DallasTemperature.h>
|
#include <DallasTemperature.h>
|
||||||
#include <OneWire.h>
|
#include <OneWire.h>
|
||||||
|
|
||||||
#if HW_ROARFRED
|
#define LED_INTERNAL 0
|
||||||
#define TEMP_SENSOR_PIN 5
|
#define LED_RED 1
|
||||||
#elif defined(ARDUINO_LOLIN_D32)
|
#define LED_GREEN 2
|
||||||
#define TEMP_SENSOR_PIN 14
|
#define LED_BLUE 3
|
||||||
#elif defined(ARDUINO_ESP8266_WEMOS_D1MINI)
|
#define LED_YELLOW 4
|
||||||
#define TEMP_SENSOR_PIN D5
|
|
||||||
#else
|
|
||||||
#define TEMP_SENSOR_PIN 0xFFFFFFFF
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class HwTools {
|
class HwTools {
|
||||||
public:
|
public:
|
||||||
|
void setTempSensorPin(int tempSensorPin);
|
||||||
|
void setVccPin(int vccPin);
|
||||||
|
void setVccMultiplier(double vccMultiplier);
|
||||||
double getVcc();
|
double getVcc();
|
||||||
double getTemperature();
|
double getTemperature();
|
||||||
int getWifiRssi();
|
int getWifiRssi();
|
||||||
|
void setLed(uint8_t ledPin, bool ledInverted);
|
||||||
|
void setLedRgb(uint8_t ledPinRed, uint8_t ledPinGreen, uint8_t ledPinBlue, bool ledRgbInverted);
|
||||||
|
bool ledOn(uint8_t color);
|
||||||
|
bool ledOff(uint8_t color);
|
||||||
|
bool ledBlink(uint8_t color, uint8_t blink);
|
||||||
|
|
||||||
HwTools() {
|
HwTools() {};
|
||||||
#if defined(ARDUINO_LOLIN_D32)
|
|
||||||
pinMode(GPIO_NUM_35, INPUT);
|
|
||||||
#endif
|
|
||||||
oneWire = new OneWire(TEMP_SENSOR_PIN);
|
|
||||||
tempSensor = new DallasTemperature(this->oneWire);
|
|
||||||
};
|
|
||||||
private:
|
private:
|
||||||
|
uint8_t tempSensorPin = -1;
|
||||||
|
uint8_t vccPin = -1;
|
||||||
|
uint8_t ledPin = -1, ledPinRed = -1, ledPinGreen = -1, ledPinBlue = -1;
|
||||||
|
bool ledInverted, ledRgbInverted;
|
||||||
|
double vccMultiplier = 1.0;
|
||||||
bool tempSensorInit, hasTempSensor;
|
bool tempSensorInit, hasTempSensor;
|
||||||
OneWire *oneWire;
|
OneWire *oneWire;
|
||||||
DallasTemperature *tempSensor;
|
DallasTemperature *tempSensor;
|
||||||
|
|
||||||
|
bool writeLedPin(uint8_t color, uint8_t state);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -20,9 +20,11 @@
|
|||||||
#if defined(ESP8266)
|
#if defined(ESP8266)
|
||||||
#include <ESP8266WiFi.h>
|
#include <ESP8266WiFi.h>
|
||||||
#include <ESP8266WebServer.h>
|
#include <ESP8266WebServer.h>
|
||||||
|
#include <ESP8266HTTPClient.h>
|
||||||
#elif defined(ESP32) // ARDUINO_ARCH_ESP32
|
#elif defined(ESP32) // ARDUINO_ARCH_ESP32
|
||||||
#include <WiFi.h>
|
#include <WiFi.h>
|
||||||
#include <WebServer.h>
|
#include <WebServer.h>
|
||||||
|
#include <HTTPClient.h>
|
||||||
#include "SPIFFS.h"
|
#include "SPIFFS.h"
|
||||||
#include "Update.h"
|
#include "Update.h"
|
||||||
#else
|
#else
|
||||||
@@ -31,7 +33,7 @@
|
|||||||
|
|
||||||
class AmsWebServer {
|
class AmsWebServer {
|
||||||
public:
|
public:
|
||||||
AmsWebServer(RemoteDebug* Debug);
|
AmsWebServer(RemoteDebug* Debug, HwTools* hw);
|
||||||
void setup(AmsConfiguration* config, MQTTClient* mqtt);
|
void setup(AmsConfiguration* config, MQTTClient* mqtt);
|
||||||
void loop();
|
void loop();
|
||||||
|
|
||||||
@@ -40,11 +42,12 @@ public:
|
|||||||
private:
|
private:
|
||||||
RemoteDebug* debugger;
|
RemoteDebug* debugger;
|
||||||
int maxPwr = 0;
|
int maxPwr = 0;
|
||||||
HwTools hw;
|
HwTools* hw;
|
||||||
AmsConfiguration* config;
|
AmsConfiguration* config;
|
||||||
AmsData data;
|
AmsData data;
|
||||||
MQTTClient* mqtt;
|
MQTTClient* mqtt;
|
||||||
File firmwareFile;
|
bool uploading = false;
|
||||||
|
File file;
|
||||||
bool performRestart = false;
|
bool performRestart = false;
|
||||||
|
|
||||||
#if defined(ESP8266)
|
#if defined(ESP8266)
|
||||||
@@ -56,22 +59,48 @@ private:
|
|||||||
bool checkSecurity(byte level);
|
bool checkSecurity(byte level);
|
||||||
|
|
||||||
void indexHtml();
|
void indexHtml();
|
||||||
|
void applicationJs();
|
||||||
void configMeterHtml();
|
void configMeterHtml();
|
||||||
void configWifiHtml();
|
void configWifiHtml();
|
||||||
void configMqttHtml();
|
void configMqttHtml();
|
||||||
void configWebHtml();
|
void configWebHtml();
|
||||||
|
void configDomoticzHtml();
|
||||||
void bootCss();
|
void bootCss();
|
||||||
void gaugemeterJs();
|
void gaugemeterJs();
|
||||||
|
void githubSvg();
|
||||||
void dataJson();
|
void dataJson();
|
||||||
|
|
||||||
|
void handleSetup();
|
||||||
void handleSave();
|
void handleSave();
|
||||||
|
|
||||||
void configSystemHtml();
|
void configSystemHtml();
|
||||||
void configSystemPost();
|
String getSerialSelectOptions(int selected);
|
||||||
void configSystemUpload();
|
void firmwareHtml();
|
||||||
|
void firmwareUpload();
|
||||||
|
void firmwareDownload();
|
||||||
void restartWaitHtml();
|
void restartWaitHtml();
|
||||||
void isAliveCheck();
|
void isAliveCheck();
|
||||||
|
|
||||||
|
void uploadHtml(const char* label, const char* action, const char* menu);
|
||||||
|
void deleteHtml(const char* label, const char* action, const char* menu);
|
||||||
|
void uploadFile(const char* path);
|
||||||
|
void deleteFile(const char* path);
|
||||||
|
void uploadPost();
|
||||||
|
void mqttCa();
|
||||||
|
void mqttCaUpload();
|
||||||
|
void mqttCaDelete();
|
||||||
|
void mqttCert();
|
||||||
|
void mqttCertUpload();
|
||||||
|
void mqttCertDelete();
|
||||||
|
void mqttKey();
|
||||||
|
void mqttKeyUpload();
|
||||||
|
void mqttKeyDelete();
|
||||||
|
|
||||||
|
void factoryResetHtml();
|
||||||
|
void factoryResetPost();
|
||||||
|
|
||||||
|
void notFound();
|
||||||
|
|
||||||
void printD(String fmt, ...);
|
void printD(String fmt, ...);
|
||||||
void printI(String fmt, ...);
|
void printI(String fmt, ...);
|
||||||
void printW(String fmt, ...);
|
void printW(String fmt, ...);
|
||||||
|
|||||||
339
web/application.js
Normal file
339
web/application.js
Normal file
@@ -0,0 +1,339 @@
|
|||||||
|
var nextVersion;
|
||||||
|
var im, em;
|
||||||
|
$(function() {
|
||||||
|
im = $("#importMeter");
|
||||||
|
if(im && im.gaugeMeter) {
|
||||||
|
im.gaugeMeter({
|
||||||
|
percent: 0,
|
||||||
|
text: "-",
|
||||||
|
append: "W"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
em = $("#exportMeter");
|
||||||
|
if(em && em.gaugeMeter) {
|
||||||
|
em.gaugeMeter({
|
||||||
|
percent: 0,
|
||||||
|
text: "-",
|
||||||
|
append: "W"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
var meters = $('.SimpleMeter');
|
||||||
|
|
||||||
|
if(meters.length > 0) {
|
||||||
|
fetch();
|
||||||
|
}
|
||||||
|
|
||||||
|
// For config-mqtt
|
||||||
|
$('#mqttEnable').on('change', function() {
|
||||||
|
var inputs = $('.mqtt-config');
|
||||||
|
inputs.prop('disabled', !$(this).is(':checked'));
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#mqttPayloadFormat').on('change', function() {
|
||||||
|
var val = parseInt($(this).val());
|
||||||
|
if(val == 3) {
|
||||||
|
$('.format-type-domoticz').show();
|
||||||
|
} else {
|
||||||
|
$('.format-type-domoticz').hide();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#mqttSsl').on('change', function() {
|
||||||
|
var port = $('#mqttPort');
|
||||||
|
if($(this).is(':checked')) {
|
||||||
|
if(port.val() == 1883) {
|
||||||
|
port.val(8883);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if(port.val() == 8883) {
|
||||||
|
port.val(1883);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#mqttEnable').trigger('change');
|
||||||
|
$('#mqttPayloadFormat').trigger('change');
|
||||||
|
|
||||||
|
// For config-meter
|
||||||
|
$('.subtitute-dependent').on('change', function() {
|
||||||
|
console.log("test");
|
||||||
|
if(($('#meterType').val() == 2 || $('#meterType').val() == 3) && $('#distributionSystem').val() == 1) {
|
||||||
|
$('#substitute').show();
|
||||||
|
} else {
|
||||||
|
$('#substitute').hide();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
$('#meterType').trigger('change');
|
||||||
|
|
||||||
|
// For config-wifi
|
||||||
|
$('#wifiIpType').on('change', function() {
|
||||||
|
if($(this).is(':checked')) {
|
||||||
|
$('#staticIp').show();
|
||||||
|
} else {
|
||||||
|
$('#staticIp').hide();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
$('#wifiIpType').trigger('change');
|
||||||
|
|
||||||
|
// For config-web
|
||||||
|
$('#authSecurity').on('change', function() {
|
||||||
|
var inputs = $('.auth-config');
|
||||||
|
inputs.prop('disabled', $(this).val() == 0);
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#authSecurity').trigger('change');
|
||||||
|
|
||||||
|
// For file upload
|
||||||
|
$('#fileUploadField').on('change',function(){
|
||||||
|
var fileName = $(this).val();
|
||||||
|
$(this).next('.custom-file-label').html(fileName);
|
||||||
|
})
|
||||||
|
|
||||||
|
switch(window.location.pathname) {
|
||||||
|
case '/config-meter':
|
||||||
|
$('#config-meter-link').addClass('active');
|
||||||
|
break;
|
||||||
|
case '/config-wifi':
|
||||||
|
$('#config-wifi-link').addClass('active');
|
||||||
|
break;
|
||||||
|
case '/config-mqtt':
|
||||||
|
case '/mqtt-ca':
|
||||||
|
case '/mqtt-cert':
|
||||||
|
case '/mqtt-key':
|
||||||
|
case '/config-domoticz':
|
||||||
|
$('#config-mqtt-link').addClass('active');
|
||||||
|
break;
|
||||||
|
case '/config-web':
|
||||||
|
$('#config-web-link').addClass('active');
|
||||||
|
break;
|
||||||
|
case '/config-system':
|
||||||
|
case '/firmware':
|
||||||
|
case '/reset':
|
||||||
|
$('#config-system-link').addClass('active');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
var swv = $('#swVersion')
|
||||||
|
if(meters.length > 0 && swv.length == 1 && swv.text() != "SNAPSHOT") {
|
||||||
|
var v = swv.text().substring(1).split('.');
|
||||||
|
var v_major = parseInt(v[0]);
|
||||||
|
var v_minor = parseInt(v[1]);
|
||||||
|
var v_patch = parseInt(v[2]);
|
||||||
|
$.ajax({
|
||||||
|
url: swv.data('url'),
|
||||||
|
dataType: 'json'
|
||||||
|
}).done(function(releases) {
|
||||||
|
releases.reverse();
|
||||||
|
var me;
|
||||||
|
var next_patch;
|
||||||
|
var next_minor;
|
||||||
|
var next_major;
|
||||||
|
$.each(releases, function(i, release) {
|
||||||
|
var ver2 = release.tag_name;
|
||||||
|
var v2 = ver2.substring(1).split('.');
|
||||||
|
var v2_major = parseInt(v2[0]);
|
||||||
|
var v2_minor = parseInt(v2[1]);
|
||||||
|
var v2_patch = parseInt(v2[2]);
|
||||||
|
|
||||||
|
if(v2_major == v_major) {
|
||||||
|
if(v2_minor == v_minor) {
|
||||||
|
if(v2_patch > v_patch) {
|
||||||
|
next_patch = release;
|
||||||
|
}
|
||||||
|
} else if(v2_minor == v_minor+1) {
|
||||||
|
next_minor = release;
|
||||||
|
}
|
||||||
|
} else if(v2_major == v_major+1) {
|
||||||
|
if(next_major) {
|
||||||
|
var mv = next_major.tag_name.substring(1).split('.');
|
||||||
|
var mv_major = parseInt(mv[0]);
|
||||||
|
var mv_minor = parseInt(mv[1]);
|
||||||
|
var mv_patch = parseInt(mv[2]);
|
||||||
|
if(v2_minor == mv_minor) {
|
||||||
|
next_major = release;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
next_major = release;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if(next_minor) {
|
||||||
|
nextVersion = next_minor;
|
||||||
|
} else if(next_major) {
|
||||||
|
nextVersion = next_major;
|
||||||
|
} else if(next_patch) {
|
||||||
|
nextVersion = next_patch;
|
||||||
|
}
|
||||||
|
if(nextVersion) {
|
||||||
|
$('#newVersionTag').text(nextVersion.tag_name);
|
||||||
|
$('#newVersionUrl').prop('href', nextVersion.html_url);
|
||||||
|
$('#newVersion').removeClass('d-none');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var setStatus = function(id, status) {
|
||||||
|
var item = $('#'+id);
|
||||||
|
item.removeClass('d-none');
|
||||||
|
item.removeClass (function (index, className) {
|
||||||
|
return (className.match (/(^|\s)badge-\S+/g) || []).join(' ');
|
||||||
|
});
|
||||||
|
item.addClass('badge badge-' + status);
|
||||||
|
};
|
||||||
|
|
||||||
|
var interval = 5000;
|
||||||
|
var fetch = function() {
|
||||||
|
$.ajax({
|
||||||
|
url: '/data.json',
|
||||||
|
timeout: 10000,
|
||||||
|
dataType: 'json',
|
||||||
|
}).done(function(json) {
|
||||||
|
if(im && em) {
|
||||||
|
$(".SimpleMeter").hide();
|
||||||
|
im.show();
|
||||||
|
em.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
for(var id in json) {
|
||||||
|
var str = json[id];
|
||||||
|
if(typeof str === "object")
|
||||||
|
continue;
|
||||||
|
if(isNaN(str)) {
|
||||||
|
$('#'+id).html(str);
|
||||||
|
} else {
|
||||||
|
var num = parseFloat(str);
|
||||||
|
$('#'+id).html(num.toFixed(num < 0 ? 0 : num < 10 ? 2 : 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(window.moment) {
|
||||||
|
$('#currentMillis').html(moment.duration(parseInt(json.uptime_seconds), 'seconds').humanize());
|
||||||
|
$('#currentMillis').closest('.row').show();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(json.status) {
|
||||||
|
for(var id in json.status) {
|
||||||
|
setStatus(id, json.status[id]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(json.mqtt) {
|
||||||
|
$('.mqtt-error').addClass('d-none');
|
||||||
|
$('.mqtt-error'+json.mqtt.lastError).removeClass('d-none');
|
||||||
|
$('#mqtt-lastError').html(json.mqtt.lastError);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(json.wifi) {
|
||||||
|
for(var id in json.wifi) {
|
||||||
|
var str = json.wifi[id];
|
||||||
|
dst = $('#'+id);
|
||||||
|
if(isNaN(str)) {
|
||||||
|
dst.html(str);
|
||||||
|
} else {
|
||||||
|
var num = parseFloat(str);
|
||||||
|
dst.html(num.toFixed(0));
|
||||||
|
$('#'+id+'-row').show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(json.data) {
|
||||||
|
var p = 0;
|
||||||
|
var p_pct = parseInt(json.p_pct);
|
||||||
|
var p_append = "W";
|
||||||
|
if(json.data.P) {
|
||||||
|
p = parseFloat(json.data.P);
|
||||||
|
if(p > 1000) {
|
||||||
|
p = (p/1000).toFixed(1);
|
||||||
|
p_append = "kW";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(im && im.gaugeMeter) {
|
||||||
|
im.gaugeMeter({
|
||||||
|
percent: p_pct,
|
||||||
|
text: p,
|
||||||
|
append: p_append
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
var po = 0;
|
||||||
|
var po_pct = parseInt(json.po_pct);
|
||||||
|
var po_append = "W";
|
||||||
|
if(json.data.PO) {
|
||||||
|
po = parseFloat(json.data.PO);
|
||||||
|
if(po > 1000) {
|
||||||
|
po = (po/1000).toFixed(1);
|
||||||
|
po_append = "kW";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(em && em.gaugeMeter) {
|
||||||
|
em.gaugeMeter({
|
||||||
|
percent: po_pct,
|
||||||
|
text: po,
|
||||||
|
append: po_append
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
for(var id in json.data) {
|
||||||
|
var str = json.data[id];
|
||||||
|
if(isNaN(str)) {
|
||||||
|
$('#'+id).html(str);
|
||||||
|
} else {
|
||||||
|
var num = parseFloat(str);
|
||||||
|
$('#'+id).html(num.toFixed(1));
|
||||||
|
$('#'+id+'-row').show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if(im && im.gaugeMeter) {
|
||||||
|
im.gaugeMeter({
|
||||||
|
percent: 0,
|
||||||
|
text: "-",
|
||||||
|
append: "W"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if(em && em.gaugeMeter) {
|
||||||
|
em.gaugeMeter({
|
||||||
|
percent: 0,
|
||||||
|
text: "-",
|
||||||
|
append: "W"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setTimeout(fetch, interval);
|
||||||
|
}).fail(function() {
|
||||||
|
setTimeout(fetch, interval*4);
|
||||||
|
|
||||||
|
if(im && im.gaugeMeter) {
|
||||||
|
im.gaugeMeter({
|
||||||
|
percent: 0,
|
||||||
|
text: "-",
|
||||||
|
append: "W"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if(em && em.gaugeMeter) {
|
||||||
|
em.gaugeMeter({
|
||||||
|
percent: 0,
|
||||||
|
text: "-",
|
||||||
|
append: "W"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
setStatus("mqtt", "secondary");
|
||||||
|
setStatus("wifi", "secondary");
|
||||||
|
setStatus("han", "secondary");
|
||||||
|
setStatus("esp", "danger");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
var upgrade = function() {
|
||||||
|
if(nextVersion) {
|
||||||
|
if(confirm("Are you sure you want to perform upgrade to " + nextVersion.tag_name + "?")) {
|
||||||
|
window.location.href="/upgrade?version=" + nextVersion.tag_name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
152
web/boot.css
152
web/boot.css
@@ -56,24 +56,9 @@ body {
|
|||||||
.bg-purple {
|
.bg-purple {
|
||||||
background-color: var(--purple);
|
background-color: var(--purple);
|
||||||
}
|
}
|
||||||
.text-white-50 {
|
|
||||||
color: rgba(255,255,255,.5)!important;
|
|
||||||
}
|
|
||||||
.mb-0, .my-0 {
|
|
||||||
margin-bottom: 0!important;
|
|
||||||
}
|
|
||||||
.m-2 {
|
|
||||||
margin: .5rem!important;
|
|
||||||
}
|
|
||||||
.mb-2, .my-2 {
|
|
||||||
margin-bottom: .5rem!important;
|
|
||||||
}
|
|
||||||
.mt-2, .my-2 {
|
.mt-2, .my-2 {
|
||||||
margin-top: .5rem!important;
|
margin-top: .5rem!important;
|
||||||
}
|
}
|
||||||
.pb-2, .py-2 {
|
|
||||||
padding-bottom: .5rem!important;
|
|
||||||
}
|
|
||||||
.p-3 {
|
.p-3 {
|
||||||
padding: 1rem!important;
|
padding: 1rem!important;
|
||||||
}
|
}
|
||||||
@@ -89,19 +74,9 @@ body {
|
|||||||
.shadow {
|
.shadow {
|
||||||
box-shadow: 0 .5rem 1rem rgba(0,0,0,.15)!important;
|
box-shadow: 0 .5rem 1rem rgba(0,0,0,.15)!important;
|
||||||
}
|
}
|
||||||
.align-items-center {
|
|
||||||
-ms-flex-align: center!important;
|
|
||||||
align-items: center!important;
|
|
||||||
}
|
|
||||||
.border-bottom {
|
|
||||||
border-bottom: 1px solid #dee2e6!important;
|
|
||||||
}
|
|
||||||
.rounded {
|
.rounded {
|
||||||
border-radius: .25rem!important;
|
border-radius: .25rem!important;
|
||||||
}
|
}
|
||||||
div {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
.container {
|
.container {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding-right: 15px;
|
padding-right: 15px;
|
||||||
@@ -115,15 +90,9 @@ article, aside, figcaption, figure, footer, header, hgroup, main, nav, section {
|
|||||||
main {
|
main {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
.text-white {
|
|
||||||
color: #fff!important;
|
|
||||||
}
|
|
||||||
.text-right {
|
.text-right {
|
||||||
text-align: right!important;
|
text-align: right!important;
|
||||||
}
|
}
|
||||||
.text-center {
|
|
||||||
text-align: center!important;
|
|
||||||
}
|
|
||||||
.h1, .h2, .h3, .h4, .h5, .h6, h1, h2, h3, h4, h5, h6 {
|
.h1, .h2, .h3, .h4, .h5, .h6, h1, h2, h3, h4, h5, h6 {
|
||||||
margin-bottom: .5rem;
|
margin-bottom: .5rem;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
@@ -133,6 +102,9 @@ h1, h2, h3, h4, h5, h6 {
|
|||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
margin-bottom: .5rem;
|
margin-bottom: .5rem;
|
||||||
}
|
}
|
||||||
|
.h5, h5 {
|
||||||
|
font-size: 1.25rem;
|
||||||
|
}
|
||||||
.h6, h6 {
|
.h6, h6 {
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
}
|
}
|
||||||
@@ -150,48 +122,14 @@ h1, h2, h3, h4, h5, h6 {
|
|||||||
padding-right: 15px;
|
padding-right: 15px;
|
||||||
padding-left: 15px;
|
padding-left: 15px;
|
||||||
}
|
}
|
||||||
.col-2 {
|
|
||||||
-ms-flex: 0 0 16.666667%;
|
|
||||||
flex: 0 0 16.666667%;
|
|
||||||
max-width: 16.666667%;
|
|
||||||
}
|
|
||||||
.col-3 {
|
|
||||||
-ms-flex: 0 0 25%;
|
|
||||||
flex: 0 0 25%;
|
|
||||||
max-width: 25%;
|
|
||||||
}
|
|
||||||
.col-4 {
|
|
||||||
-ms-flex: 0 0 33.333333%;
|
|
||||||
flex: 0 0 33.333333%;
|
|
||||||
max-width: 33.333333%;
|
|
||||||
}
|
|
||||||
.col-5 {
|
|
||||||
-ms-flex: 0 0 41.666667%;
|
|
||||||
flex: 0 0 41.666667%;
|
|
||||||
max-width: 41.666667%;
|
|
||||||
}
|
|
||||||
.col-6 {
|
.col-6 {
|
||||||
-ms-flex: 0 0 50%;
|
-ms-flex: 0 0 50%;
|
||||||
flex: 0 0 50%;
|
flex: 0 0 50%;
|
||||||
max-width: 50%;
|
max-width: 50%;
|
||||||
}
|
}
|
||||||
.col-8 {
|
|
||||||
-ms-flex: 0 0 66.666667%;
|
|
||||||
flex: 0 0 66.666667%;
|
|
||||||
max-width: 66.666667%;
|
|
||||||
}
|
|
||||||
.col-9 {
|
|
||||||
-ms-flex: 0 0 75%;
|
|
||||||
flex: 0 0 75%;
|
|
||||||
max-width: 75%;
|
|
||||||
}
|
|
||||||
.d-none {
|
.d-none {
|
||||||
display: none!important;
|
display: none!important;
|
||||||
}
|
}
|
||||||
.d-flex {
|
|
||||||
display: -ms-flexbox!important;
|
|
||||||
display: flex!important;
|
|
||||||
}
|
|
||||||
.flex-row {
|
.flex-row {
|
||||||
-ms-flex-direction: row!important;
|
-ms-flex-direction: row!important;
|
||||||
flex-direction: row!important;
|
flex-direction: row!important;
|
||||||
@@ -225,9 +163,11 @@ a {
|
|||||||
border-radius: .25rem;
|
border-radius: .25rem;
|
||||||
transition: color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;
|
transition: color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;
|
||||||
}
|
}
|
||||||
.btn-outline-secondary {
|
.btn-group-sm>.btn, .btn-sm {
|
||||||
color: #6c757d;
|
padding: .25rem .5rem;
|
||||||
border-color: #6c757d;
|
font-size: .875rem;
|
||||||
|
line-height: 1.5;
|
||||||
|
border-radius: .2rem;
|
||||||
}
|
}
|
||||||
.btn-primary {
|
.btn-primary {
|
||||||
color: #fff;
|
color: #fff;
|
||||||
@@ -295,46 +235,6 @@ a {
|
|||||||
.navbar-dark .navbar-nav .active>.nav-link, .navbar-dark .navbar-nav .nav-link.active, .navbar-dark .navbar-nav .nav-link.show, .navbar-dark .navbar-nav .show>.nav-link {
|
.navbar-dark .navbar-nav .active>.nav-link, .navbar-dark .navbar-nav .nav-link.active, .navbar-dark .navbar-nav .nav-link.show, .navbar-dark .navbar-nav .show>.nav-link {
|
||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
.badge {
|
|
||||||
display: inline-block;
|
|
||||||
padding: .25em .4em;
|
|
||||||
font-size: 75%;
|
|
||||||
font-weight: 700;
|
|
||||||
line-height: 1;
|
|
||||||
text-align: center;
|
|
||||||
white-space: nowrap;
|
|
||||||
vertical-align: baseline;
|
|
||||||
border-radius: .25rem;
|
|
||||||
transition: color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;
|
|
||||||
}
|
|
||||||
.badge-secondary {
|
|
||||||
color: #fff;
|
|
||||||
background-color: #6c757d;
|
|
||||||
}
|
|
||||||
.badge-success {
|
|
||||||
color: #fff;
|
|
||||||
background-color: #28a745;
|
|
||||||
}
|
|
||||||
.badge-warning {
|
|
||||||
color: #212529;
|
|
||||||
background-color: #ffc107;
|
|
||||||
}
|
|
||||||
.badge-danger {
|
|
||||||
color: #fff;
|
|
||||||
background-color: #dc3545;
|
|
||||||
}
|
|
||||||
.alert {
|
|
||||||
position: relative;
|
|
||||||
padding: .75rem 1.25rem;
|
|
||||||
margin-bottom: 1rem;
|
|
||||||
border: 1px solid transparent;
|
|
||||||
border-radius: .25rem;
|
|
||||||
}
|
|
||||||
.alert-warning {
|
|
||||||
color: #856404;
|
|
||||||
background-color: #fff3cd;
|
|
||||||
border-color: #ffeeba;
|
|
||||||
}
|
|
||||||
.form-group {
|
.form-group {
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
}
|
}
|
||||||
@@ -386,6 +286,9 @@ input[type="radio"], input[type="checkbox"] {
|
|||||||
.input-group-append {
|
.input-group-append {
|
||||||
margin-left: -1px;
|
margin-left: -1px;
|
||||||
}
|
}
|
||||||
|
.input-group-prepend {
|
||||||
|
margin-right: -1px;
|
||||||
|
}
|
||||||
.input-group-append, .input-group-prepend {
|
.input-group-append, .input-group-prepend {
|
||||||
display: -ms-flexbox;
|
display: -ms-flexbox;
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -394,6 +297,14 @@ input[type="radio"], input[type="checkbox"] {
|
|||||||
border-top-left-radius: 0;
|
border-top-left-radius: 0;
|
||||||
border-bottom-left-radius: 0;
|
border-bottom-left-radius: 0;
|
||||||
}
|
}
|
||||||
|
.input-group>.input-group-append:last-child>.btn:not(:last-child):not(.dropdown-toggle), .input-group>.input-group-append:last-child>.input-group-text:not(:last-child), .input-group>.input-group-append:not(:last-child)>.btn, .input-group>.input-group-append:not(:last-child)>.input-group-text, .input-group>.input-group-prepend>.btn, .input-group>.input-group-prepend>.input-group-text {
|
||||||
|
border-top-right-radius: 0;
|
||||||
|
border-bottom-right-radius: 0;
|
||||||
|
}
|
||||||
|
.input-group>.custom-select:not(:first-child), .input-group>.form-control:not(:first-child) {
|
||||||
|
border-top-left-radius: 0;
|
||||||
|
border-bottom-left-radius: 0;
|
||||||
|
}
|
||||||
.input-group-text {
|
.input-group-text {
|
||||||
display: -ms-flexbox;
|
display: -ms-flexbox;
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -453,6 +364,11 @@ dl, ol, ul {
|
|||||||
.container, .container-sm {
|
.container, .container-sm {
|
||||||
max-width: 540px;
|
max-width: 540px;
|
||||||
}
|
}
|
||||||
|
.col-sm-6 {
|
||||||
|
-ms-flex: 0 0 50%;
|
||||||
|
flex: 0 0 50%;
|
||||||
|
max-width: 50%;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@media (min-width: 768px) {
|
@media (min-width: 768px) {
|
||||||
.container, .container-md, .container-sm {
|
.container, .container-md, .container-sm {
|
||||||
@@ -463,11 +379,6 @@ dl, ol, ul {
|
|||||||
flex: 0 0 25%;
|
flex: 0 0 25%;
|
||||||
max-width: 25%;
|
max-width: 25%;
|
||||||
}
|
}
|
||||||
.col-md-4 {
|
|
||||||
-ms-flex: 0 0 33.333333%;
|
|
||||||
flex: 0 0 33.333333%;
|
|
||||||
max-width: 33.333333%;
|
|
||||||
}
|
|
||||||
.col-md-6 {
|
.col-md-6 {
|
||||||
-ms-flex: 0 0 50%;
|
-ms-flex: 0 0 50%;
|
||||||
flex: 0 0 50%;
|
flex: 0 0 50%;
|
||||||
@@ -499,6 +410,21 @@ dl, ol, ul {
|
|||||||
.container, .container-lg, .container-md, .container-sm, .container-xl {
|
.container, .container-lg, .container-md, .container-sm, .container-xl {
|
||||||
max-width: 1140px;
|
max-width: 1140px;
|
||||||
}
|
}
|
||||||
|
.col-xl-2 {
|
||||||
|
-ms-flex: 0 0 16.666667%;
|
||||||
|
flex: 0 0 16.666667%;
|
||||||
|
max-width: 16.666667%;
|
||||||
|
}
|
||||||
|
.col-xl-3 {
|
||||||
|
-ms-flex: 0 0 25%;
|
||||||
|
flex: 0 0 25%;
|
||||||
|
max-width: 25%;
|
||||||
|
}
|
||||||
|
.col-xl-4 {
|
||||||
|
-ms-flex: 0 0 33.333333%;
|
||||||
|
flex: 0 0 33.333333%;
|
||||||
|
max-width: 33.333333%;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
*, ::after, ::before {
|
*, ::after, ::before {
|
||||||
|
|||||||
60
web/configdomoticz.html
Normal file
60
web/configdomoticz.html
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
<form method="post" action="/save">
|
||||||
|
<input type="hidden" name="domoConfig" value="true"/>
|
||||||
|
<div class="my-3 p-3 bg-white rounded shadow">
|
||||||
|
<p>Domoticz Configuration. Requires that a Domoticz MQTT-message-broker is setup. HOWTO: https://www.domoticz.com/wiki/MQTT.</p>
|
||||||
|
<p>The following virtual sensors can currently be used:</p>
|
||||||
|
<ul>
|
||||||
|
<li>Electricity (instant and counter)</li>
|
||||||
|
<li>Electricity Current/Ampere 3 Phase</li>
|
||||||
|
<li>Voltage</li>
|
||||||
|
</ul>
|
||||||
|
<p>see: <a href="https://www.domoticz.com/wiki/Domoticz_API/JSON_URL's">https://www.domoticz.com/wiki/Domoticz_API/JSON_URL's</a></p>
|
||||||
|
<p>Create the sensors in Domoticz under Hardware > Dummy > Create virtual sensor, and use the IDX assigned to the sensor as input here.</p>
|
||||||
|
<p>"Electricity (instant and counter)" relies on Total energy import "tPI" and will not start before the first value is read (once an hour).</p>
|
||||||
|
</div>
|
||||||
|
<div class="my-3 p-3 bg-white rounded shadow">
|
||||||
|
<div class="d-flex flex-row flex-wrap">
|
||||||
|
<div class="m-2 input-group input-group-sm" style="width: 200px;">
|
||||||
|
<div class="input-group-prepend">
|
||||||
|
<span class="input-group-text">Electricity IDX</span>
|
||||||
|
</div>
|
||||||
|
<input type="number" class="form-control" name="domoELIDX" value="${config.domoELIDX}" min="0" max="65535"/>
|
||||||
|
</div>
|
||||||
|
<div class="m-2 input-group input-group-sm" style="width: 240px;">
|
||||||
|
<div class="input-group-prepend">
|
||||||
|
<span class="input-group-text">Current (3 Phase) IDX</span>
|
||||||
|
</div>
|
||||||
|
<input type="number" class="form-control" name="domoCL1IDX" value="${config.domoCL1IDX}" min="0" max="65535"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="d-flex flex-row flex-wrap">
|
||||||
|
<div class="m-2 input-group input-group-sm" style="width: 200px;">
|
||||||
|
<div class="input-group-prepend">
|
||||||
|
<span class="input-group-text">Voltage L1 IDX</span>
|
||||||
|
</div>
|
||||||
|
<input type="number" class="form-control" name="domoVL1IDX" value="${config.domoVL1IDX}" min="0" max="65535"/>
|
||||||
|
</div>
|
||||||
|
<div class="m-2 input-group input-group-sm" style="width: 200px;">
|
||||||
|
<div class="input-group-prepend">
|
||||||
|
<span class="input-group-text">Voltage L1 IDX</span>
|
||||||
|
</div>
|
||||||
|
<input type="number" class="form-control" name="domoVL2IDX" value="${config.domoVL2IDX}" min="0" max="65535"/>
|
||||||
|
</div>
|
||||||
|
<div class="m-2 input-group input-group-sm" style="width: 200px;">
|
||||||
|
<div class="input-group-prepend">
|
||||||
|
<span class="input-group-text">Voltage L1 IDX</span>
|
||||||
|
</div>
|
||||||
|
<input type="number" class="form-control" name="domoVL3IDX" value="${config.domoVL3IDX}" min="0" max="65535"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<hr/>
|
||||||
|
<div class="row form-group">
|
||||||
|
<div class="col-6">
|
||||||
|
<a href="/" class="btn btn-outline-secondary">Back</a>
|
||||||
|
</div>
|
||||||
|
<div class="col-6 text-right">
|
||||||
|
<button class="btn btn-primary">Save</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
@@ -1,106 +1,78 @@
|
|||||||
<html>
|
<form method="post" action="/save">
|
||||||
<head>
|
<input type="hidden" name="meterConfig" value="true"/>
|
||||||
<meta charset="UTF-8">
|
<div class="my-3 p-3 bg-white rounded shadow">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<div class="row">
|
||||||
<title>AMS reader - Meter configuration</title>
|
<div class="col-lg-3 col-md-4 col-sm-6">
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
<div class="m-2 input-group input-group-sm">
|
||||||
<link rel="stylesheet" type="text/css" href="boot.css"/>
|
<div class="input-group-prepend">
|
||||||
</head>
|
<span class="input-group-text">Meter type</span>
|
||||||
<body class="bg-light">
|
|
||||||
<main role="main" class="container">
|
|
||||||
<header class="navbar navbar-expand navbar-dark flex-column flex-md-row bg-purple rounded mt-2 mb-4" style="background-color: var(--purple);">
|
|
||||||
<a href="/" class=""><h6 class="navbar-brand">AMS reader <small>${version}</small></h6></a>
|
|
||||||
<div class="navbar-nav-scroll">
|
|
||||||
<ul class="navbar-nav bd-navbar-nav flex-row">
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link active" href="/config-meter">Meter</a>
|
|
||||||
</li>
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" href="/config-wifi">WiFi</a>
|
|
||||||
</li>
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" href="/config-mqtt">MQTT</a>
|
|
||||||
</li>
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" href="/config-web">Web</a>
|
|
||||||
</li>
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" href="/config-system">System</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<ul class="navbar-nav flex-row ml-md-auto d-none d-md-flex">
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link p-2" href="https://github.com/gskjold/AmsToMqttBridge" target="_blank" rel="noopener" aria-label="GitHub">
|
|
||||||
<svg class="d-inline-block align-text-top" style="width: 2rem; height: 2rem;" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 499.36" focusable="false"><title>GitHub</title><path d="M256 0C114.64 0 0 114.61 0 256c0 113.09 73.34 209 175.08 242.9 12.8 2.35 17.47-5.56 17.47-12.34 0-6.08-.22-22.18-.35-43.54-71.2 15.49-86.2-34.34-86.2-34.34-11.64-29.57-28.42-37.45-28.42-37.45-23.27-15.84 1.73-15.55 1.73-15.55 25.69 1.81 39.21 26.38 39.21 26.38 22.84 39.12 59.92 27.82 74.5 21.27 2.33-16.54 8.94-27.82 16.25-34.22-56.84-6.43-116.6-28.43-116.6-126.49 0-27.95 10-50.8 26.35-68.69-2.63-6.48-11.42-32.5 2.51-67.75 0 0 21.49-6.88 70.4 26.24a242.65 242.65 0 0 1 128.18 0c48.87-33.13 70.33-26.24 70.33-26.24 14 35.25 5.18 61.27 2.55 67.75 16.41 17.9 26.31 40.75 26.31 68.69 0 98.35-59.85 120-116.88 126.32 9.19 7.9 17.38 23.53 17.38 47.41 0 34.22-.31 61.83-.31 70.23 0 6.85 4.61 14.81 17.6 12.31C438.72 464.97 512 369.08 512 256.02 512 114.62 397.37 0 256 0z" fill="currentColor" fill-rule="evenodd"></path></svg>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</header>
|
|
||||||
<form method="post" action="/save">
|
|
||||||
<input type="hidden" name="meterConfig" value="true"/>
|
|
||||||
<div class="my-3 p-3 bg-white rounded shadow">
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-md-4">
|
|
||||||
<div class="row form-group">
|
|
||||||
<label class="col-6">Meter type</label>
|
|
||||||
<div class="col-6">
|
|
||||||
<select class="form-control" name="meterType">
|
|
||||||
<option value="0" ${config.meterType0}>Autodetect</option>
|
|
||||||
<option value="1" ${config.meterType1}>Kaifa</option>
|
|
||||||
<option value="2" ${config.meterType2}>Aidon</option>
|
|
||||||
<option value="3" ${config.meterType3}>Kamstrup</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row form-group">
|
|
||||||
<label class="col-6">Distribution system</label>
|
|
||||||
<div class="col-6">
|
|
||||||
<select class="form-control" name="distributionSystem">
|
|
||||||
<option value="0" ${config.distributionSystem0}></option>
|
|
||||||
<option value="1" ${config.distributionSystem1}>IT (230V)</option>
|
|
||||||
<option value="2" ${config.distributionSystem2}>TN (400V)</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
<select id="meterType" class="form-control subtitute-dependent" name="meterType">
|
||||||
|
<option value="0" ${config.meterType0}>Autodetect</option>
|
||||||
|
<option value="1" ${config.meterType1}>Kaifa</option>
|
||||||
|
<option value="2" ${config.meterType2}>Aidon</option>
|
||||||
|
<option value="3" ${config.meterType3}>Kamstrup</option>
|
||||||
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-4">
|
</div>
|
||||||
<div class="row form-group">
|
<div class="col-xl-3 col-lg-4 col-md-5 col-sm-6">
|
||||||
<label class="col-6">Main fuse</label>
|
<div class="m-2 input-group input-group-sm">
|
||||||
<div class="col-6">
|
<div class="input-group-prepend">
|
||||||
<select class="form-control" name="mainFuse">
|
<span class="input-group-text">Distribution system</span>
|
||||||
<option value="0" ${config.mainFuse0}></option>
|
|
||||||
<option value="25" ${config.mainFuse25}>25A</option>
|
|
||||||
<option value="32" ${config.mainFuse32}>32A</option>
|
|
||||||
<option value="35" ${config.mainFuse32}>35A</option>
|
|
||||||
<option value="40" ${config.mainFuse40}>40A</option>
|
|
||||||
<option value="50" ${config.mainFuse50}>50A</option>
|
|
||||||
<option value="63" ${config.mainFuse63}>63A</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="row form-group">
|
<select id="distributionSystem" class="form-control subtitute-dependent" name="distributionSystem">
|
||||||
<label class="col-6">Production capacity</label>
|
<option value="0" ${config.distributionSystem0}></option>
|
||||||
<div class="col-6">
|
<option value="1" ${config.distributionSystem1}>IT (230V)</option>
|
||||||
<div class="input-group">
|
<option value="2" ${config.distributionSystem2}>TN (400V)</option>
|
||||||
<input class="form-control" name="productionCapacity" type="number" min="0" max="50" value="${config.productionCapacity}"/>
|
</select>
|
||||||
<div class="input-group-append"><span class="input-group-text">kWp</span></div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="col-xl-2 col-md-3 col-sm-5">
|
||||||
|
<div class="m-2 input-group input-group-sm">
|
||||||
|
<div class="input-group-prepend">
|
||||||
|
<span class="input-group-text">Main fuse</span>
|
||||||
|
</div>
|
||||||
|
<select class="form-control" name="mainFuse">
|
||||||
|
<option value="0" ${config.mainFuse0}></option>
|
||||||
|
<option value="25" ${config.mainFuse25}>25A</option>
|
||||||
|
<option value="32" ${config.mainFuse32}>32A</option>
|
||||||
|
<option value="35" ${config.mainFuse32}>35A</option>
|
||||||
|
<option value="40" ${config.mainFuse40}>40A</option>
|
||||||
|
<option value="50" ${config.mainFuse50}>50A</option>
|
||||||
|
<option value="63" ${config.mainFuse63}>63A</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-xl-3 col-lg-4 col-md-5 col-sm-7">
|
||||||
|
<div class="m-2 input-group input-group-sm">
|
||||||
|
<div class="input-group-prepend">
|
||||||
|
<span class="input-group-text">Production capacity</span>
|
||||||
|
</div>
|
||||||
|
<input class="form-control" name="productionCapacity" type="number" min="0" max="50" value="${config.productionCapacity}"/>
|
||||||
|
<div class="input-group-append">
|
||||||
|
<span class="input-group-text">kWp</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div id="substitute" class="col-lg-3 col-md-4 col-sm-5">
|
||||||
<hr/>
|
<div class="m-2">
|
||||||
<div class="row form-group">
|
<label class="small"><input id="substituteMissing" type="checkbox" name="substituteMissing" value="true" ${config.substituteMissing}/> Substitute missing values</label>
|
||||||
<div class="col-6">
|
</div>
|
||||||
<a href="/" class="btn btn-outline-secondary">Back</a>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="col-6 text-right">
|
<div class="col-lg-3 col-md-4 col-sm-5">
|
||||||
<button class="btn btn-primary">Save</button>
|
<div class="m-2">
|
||||||
|
<label class="small"><input type="checkbox" name="sendUnknown" value="true" ${config.sendUnknown}/> Send unknown packets to MQTT</label>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</div>
|
||||||
</main>
|
<hr/>
|
||||||
</body>
|
<div class="row form-group">
|
||||||
</html>
|
<div class="col-6">
|
||||||
|
<a href="/" class="btn btn-outline-secondary">Back</a>
|
||||||
|
</div>
|
||||||
|
<div class="col-6 text-right">
|
||||||
|
<button class="btn btn-primary">Save</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|||||||
@@ -1,103 +1,123 @@
|
|||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
<title>AMS reader - WiFi configuration</title>
|
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
||||||
<link rel="stylesheet" type="text/css" href="boot.css"/>
|
|
||||||
<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
|
|
||||||
</head>
|
|
||||||
<body class="bg-light">
|
|
||||||
<main role="main" class="container">
|
|
||||||
<header class="navbar navbar-expand navbar-dark flex-column flex-md-row bg-purple rounded mt-2 mb-4" style="background-color: var(--purple);">
|
|
||||||
<a href="/" class=""><h6 class="navbar-brand">AMS reader <small>${version}</small></h6></a>
|
|
||||||
<div class="navbar-nav-scroll">
|
|
||||||
<ul class="navbar-nav bd-navbar-nav flex-row">
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" href="/config-meter">Meter</a>
|
|
||||||
</li>
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" href="/config-wifi">WiFi</a>
|
|
||||||
</li>
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link active" href="/config-mqtt">MQTT</a>
|
|
||||||
</li>
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" href="/config-web">Web</a>
|
|
||||||
</li>
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" href="/config-system">System</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<ul class="navbar-nav flex-row ml-md-auto d-none d-md-flex">
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link p-2" href="https://github.com/gskjold/AmsToMqttBridge" target="_blank" rel="noopener" aria-label="GitHub">
|
|
||||||
<svg class="d-inline-block align-text-top" style="width: 2rem; height: 2rem;" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 499.36" focusable="false"><title>GitHub</title><path d="M256 0C114.64 0 0 114.61 0 256c0 113.09 73.34 209 175.08 242.9 12.8 2.35 17.47-5.56 17.47-12.34 0-6.08-.22-22.18-.35-43.54-71.2 15.49-86.2-34.34-86.2-34.34-11.64-29.57-28.42-37.45-28.42-37.45-23.27-15.84 1.73-15.55 1.73-15.55 25.69 1.81 39.21 26.38 39.21 26.38 22.84 39.12 59.92 27.82 74.5 21.27 2.33-16.54 8.94-27.82 16.25-34.22-56.84-6.43-116.6-28.43-116.6-126.49 0-27.95 10-50.8 26.35-68.69-2.63-6.48-11.42-32.5 2.51-67.75 0 0 21.49-6.88 70.4 26.24a242.65 242.65 0 0 1 128.18 0c48.87-33.13 70.33-26.24 70.33-26.24 14 35.25 5.18 61.27 2.55 67.75 16.41 17.9 26.31 40.75 26.31 68.69 0 98.35-59.85 120-116.88 126.32 9.19 7.9 17.38 23.53 17.38 47.41 0 34.22-.31 61.83-.31 70.23 0 6.85 4.61 14.81 17.6 12.31C438.72 464.97 512 369.08 512 256.02 512 114.62 397.37 0 256 0z" fill="currentColor" fill-rule="evenodd"></path></svg>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</header>
|
|
||||||
<form method="post" action="/save">
|
<form method="post" action="/save">
|
||||||
<input type="hidden" name="mqttConfig" value="true"/>
|
<input type="hidden" name="mqttConfig" value="true"/>
|
||||||
<div class="my-3 p-3 bg-white rounded shadow">
|
<div class="my-3 p-3 bg-white rounded shadow">
|
||||||
|
<label class="m-2"><input id="mqttEnable" type="checkbox" name="mqtt" value="true" ${config.mqtt}/> Enable</label>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-3">
|
<div class="col-xl-4 col-lg-5 col-md-6">
|
||||||
<div class="row form-group">
|
<div class="m-2 input-group input-group-sm">
|
||||||
<label class="col-4">Enable</label>
|
<div class="input-group-prepend">
|
||||||
<div class="col-8">
|
<span class="input-group-text">Host</span>
|
||||||
<input id="mqttEnable" type="checkbox" name="mqtt" value="true" ${config.mqtt}/>
|
|
||||||
</div>
|
</div>
|
||||||
|
<input type="text" class="form-control mqtt-config" name="mqttHost" value="${config.mqttHost}" maxlength="128"/>
|
||||||
</div>
|
</div>
|
||||||
<div class="row form-group">
|
</div>
|
||||||
<label class="col-4">Payload</label>
|
<div class="col-xl-2 col-lg-3 col-md-3 col-sm-4">
|
||||||
<div class="col-8">
|
<div class="m-2 input-group input-group-sm">
|
||||||
<select class="form-control mqtt-config" name="mqttPayloadFormat">
|
<div class="input-group-prepend">
|
||||||
<option value="0" ${config.mqttPayloadFormat0}>JSON</option>
|
<span class="input-group-text">Port</span>
|
||||||
<option value="1" ${config.mqttPayloadFormat1}>Raw</option>
|
</div>
|
||||||
</select>
|
<input id="mqttPort" type="number" class="form-control mqtt-config" name="mqttPort" value="${config.mqttPort}" min="1024" max="65535" placeholder="1883"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-xl-3 col-lg-4 col-md-6 col-sm-8">
|
||||||
|
<div class="m-2 input-group input-group-sm">
|
||||||
|
<div class="input-group-prepend">
|
||||||
|
<span class="input-group-text">Client ID</span>
|
||||||
|
</div>
|
||||||
|
<input type="text" class="form-control mqtt-config" name="mqttClientId" value="${config.mqttClientId}" maxlength="32"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-xl-3 col-lg-4 col-md-6">
|
||||||
|
<div class="m-2 input-group input-group-sm">
|
||||||
|
<div class="input-group-prepend">
|
||||||
|
<span class="input-group-text">Publish topic</span>
|
||||||
|
</div>
|
||||||
|
<input type="text" class="form-control mqtt-config" name="mqttPublishTopic" value="${config.mqttPublishTopic}" maxlength="64"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-xl-3 col-lg-4 col-md-6 col-sm-6">
|
||||||
|
<div class="m-2 input-group input-group-sm">
|
||||||
|
<div class="input-group-prepend">
|
||||||
|
<span class="input-group-text">Username</span>
|
||||||
|
</div>
|
||||||
|
<input type="text" class="form-control mqtt-config" name="mqttUser" value="${config.mqttUser}" maxlength="64"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-xl-3 col-lg-4 col-md-6 col-sm-6">
|
||||||
|
<div class="m-2 input-group input-group-sm">
|
||||||
|
<div class="input-group-prepend">
|
||||||
|
<span class="input-group-text">Password</span>
|
||||||
|
</div>
|
||||||
|
<input type="password" class="form-control mqtt-config" name="mqttPassword" value="${config.mqttPassword}" maxlength="64"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-3 col-md-4 col-sm-6">
|
||||||
|
<div class="m-2 input-group input-group-sm">
|
||||||
|
<div class="input-group-prepend">
|
||||||
|
<span class="input-group-text">Payload</span>
|
||||||
|
</div>
|
||||||
|
<select id="mqttPayloadFormat" class="form-control mqtt-config" name="mqttPayloadFormat">
|
||||||
|
<option value="0" ${config.mqttPayloadFormat0}>JSON</option>
|
||||||
|
<option value="1" ${config.mqttPayloadFormat1}>Raw (minimal)</option>
|
||||||
|
<option value="2" ${config.mqttPayloadFormat2}>Raw (full)</option>
|
||||||
|
<option value="3" ${config.mqttPayloadFormat3}>Domoticz</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-3 col-sm-6 format-type-domoticz">
|
||||||
|
<div class="m-2">
|
||||||
|
<a href="/config-domoticz" class="btn btn-sm btn-outline-secondary">Configuration</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="my-3 p-3 bg-white rounded shadow">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-2">
|
||||||
|
<label class="m-2"><input id="mqttSsl" type="checkbox" name="mqttSsl" value="true" ${config.mqttSsl}/> SSL</label>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-2 col-md-3">
|
||||||
|
<div class="m-2 input-group input-group-sm">
|
||||||
|
<div class="input-group-prepend">
|
||||||
|
<span class="input-group-text">CA</span>
|
||||||
|
</div>
|
||||||
|
<div class="input-group-append">
|
||||||
|
<span style="display: ${display.ca.upload};">
|
||||||
|
<a href="/mqtt-ca" class="btn btn-sm btn-outline-secondary">Upload</a>
|
||||||
|
</span>
|
||||||
|
<span style="display: ${display.ca.file};">
|
||||||
|
<a href="/mqtt-ca" class="btn btn-sm btn-danger">Delete</a>
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-3">
|
<div class="col-xl-2 col-md-3">
|
||||||
<div class="row form-group">
|
<div class="m-2 input-group input-group-sm">
|
||||||
<label class="col-4">Hostname</label>
|
<div class="input-group-prepend">
|
||||||
<div class="col-8">
|
<span class="input-group-text">Certificate</span>
|
||||||
<input type="text" class="form-control mqtt-config" name="mqttHost" value="${config.mqttHost}"/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="input-group-append">
|
||||||
<div class="row form-group">
|
<span style="display: ${display.cert.upload};">
|
||||||
<label class="col-4">Port</label>
|
<a href="/mqtt-cert" class="btn btn-sm btn-outline-secondary">Upload</a>
|
||||||
<div class="col-8">
|
</span>
|
||||||
<input type="text" class="form-control mqtt-config" name="mqttPort" value="${config.mqttPort}"/>
|
<span style="display: ${display.cert.file};">
|
||||||
|
<a href="/mqtt-cert" class="btn btn-sm btn-danger">Delete</a>
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-3">
|
<div class="col-xl-2 col-md-4">
|
||||||
<div class="row form-group">
|
<div class="m-2 input-group input-group-sm">
|
||||||
<label class="col-4">Client ID</label>
|
<div class="input-group-prepend">
|
||||||
<div class="col-8">
|
<span class="input-group-text">Private key</span>
|
||||||
<input type="text" class="form-control mqtt-config" name="mqttClientId" value="${config.mqttClientId}"/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="input-group-append">
|
||||||
<div class="row form-group">
|
<span style="display: ${display.key.upload};">
|
||||||
<label class="col-4">Topic</label>
|
<a href="/mqtt-key" class="btn btn-sm btn-outline-secondary">Upload</a>
|
||||||
<div class="col-8">
|
</span>
|
||||||
<input type="text" class="form-control mqtt-config" name="mqttPublishTopic" value="${config.mqttPublishTopic}"/>
|
<span style="display: ${display.key.file};">
|
||||||
</div>
|
<a href="/mqtt-key" class="btn btn-sm btn-danger">Delete</a>
|
||||||
</div>
|
</span>
|
||||||
</div>
|
|
||||||
<div class="col-md-3">
|
|
||||||
<div class="row form-group">
|
|
||||||
<label class="col-4">Username</label>
|
|
||||||
<div class="col-8">
|
|
||||||
<input type="text" class="form-control mqtt-config" name="mqttUser" value="${config.mqttUser}"/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row form-group">
|
|
||||||
<label class="col-4">Password</label>
|
|
||||||
<div class="col-8">
|
|
||||||
<input type="password" class="form-control mqtt-config" name="mqttPassword" value="${config.mqttPassword}"/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -113,16 +133,3 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</main>
|
|
||||||
<script>
|
|
||||||
$('#mqttEnable').on('change', function() {
|
|
||||||
var inputs = $('.mqtt-config');
|
|
||||||
inputs.prop('disabled', !$(this).is(':checked'));
|
|
||||||
});
|
|
||||||
|
|
||||||
$(function() {
|
|
||||||
$('#mqttEnable').trigger('change');
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|||||||
@@ -1,100 +1,134 @@
|
|||||||
<html>
|
<div class="alert alert-warning">!!WARNING!!<br/>Do not change anything here unless you know exactly what you are doing! Changing things here could cause the device to stop responding</div>
|
||||||
<head>
|
<form method="post" action="/save">
|
||||||
<meta charset="UTF-8">
|
<input type="hidden" name="sysConfig" value="true"/>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<div class="my-3 p-3 bg-white rounded shadow">
|
||||||
<title>AMS reader - System configuration</title>
|
<h6>GPIO settings</h6>
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
<div class="row">
|
||||||
<link rel="stylesheet" type="text/css" href="boot.css"/>
|
<div class="col-xl-2 col-md-3 col-sm-6 col-6">
|
||||||
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.4.1/css/bootstrap.min.css"/>
|
<div class="m-2 input-group input-group-sm">
|
||||||
</head>
|
<div class="input-group-prepend">
|
||||||
<body class="bg-light">
|
<span class="input-group-text">HAN</span>
|
||||||
<main role="main" class="container">
|
</div>
|
||||||
<header class="navbar navbar-expand navbar-dark flex-column flex-md-row bg-purple rounded mt-2 mb-4" style="background-color: var(--purple);">
|
<select name="hanPin" class="form-control">
|
||||||
<a href="/" class=""><h6 class="navbar-brand">AMS reader <small>${version}</small></h6></a>
|
${options.han}
|
||||||
<div class="navbar-nav-scroll">
|
</select>
|
||||||
<ul class="navbar-nav bd-navbar-nav flex-row">
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" href="/config-meter">Meter</a>
|
|
||||||
</li>
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link " href="/config-wifi">WiFi</a>
|
|
||||||
</li>
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link " href="/config-mqtt">MQTT</a>
|
|
||||||
</li>
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" href="/config-web">Web</a>
|
|
||||||
</li>
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link active" href="/config-system">System</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<ul class="navbar-nav flex-row ml-md-auto d-none d-md-flex">
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link p-2" href="https://github.com/gskjold/AmsToMqttBridge" target="_blank" rel="noopener" aria-label="GitHub">
|
|
||||||
<svg class="d-inline-block align-text-top" style="width: 2rem; height: 2rem;" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 499.36" focusable="false"><title>GitHub</title><path d="M256 0C114.64 0 0 114.61 0 256c0 113.09 73.34 209 175.08 242.9 12.8 2.35 17.47-5.56 17.47-12.34 0-6.08-.22-22.18-.35-43.54-71.2 15.49-86.2-34.34-86.2-34.34-11.64-29.57-28.42-37.45-28.42-37.45-23.27-15.84 1.73-15.55 1.73-15.55 25.69 1.81 39.21 26.38 39.21 26.38 22.84 39.12 59.92 27.82 74.5 21.27 2.33-16.54 8.94-27.82 16.25-34.22-56.84-6.43-116.6-28.43-116.6-126.49 0-27.95 10-50.8 26.35-68.69-2.63-6.48-11.42-32.5 2.51-67.75 0 0 21.49-6.88 70.4 26.24a242.65 242.65 0 0 1 128.18 0c48.87-33.13 70.33-26.24 70.33-26.24 14 35.25 5.18 61.27 2.55 67.75 16.41 17.9 26.31 40.75 26.31 68.69 0 98.35-59.85 120-116.88 126.32 9.19 7.9 17.38 23.53 17.38 47.41 0 34.22-.31 61.83-.31 70.23 0 6.85 4.61 14.81 17.6 12.31C438.72 464.97 512 369.08 512 256.02 512 114.62 397.37 0 256 0z" fill="currentColor" fill-rule="evenodd"></path></svg>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</header>
|
|
||||||
<form method="post" action="/save">
|
|
||||||
<input type="hidden" name="sysConfig" value="true"/>
|
|
||||||
<div class="my-3 p-3 bg-white rounded shadow">
|
|
||||||
<div class="alert alert-warning">!!WARNING!!<br/>Remote debugging is considered insecure and should not be left enabled when not debugging</div>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-md-3">
|
|
||||||
<label><input type="checkbox" name="debugTelnet" value="true" ${config.debugTelnet}/> Telnet debugger</label>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-3">
|
</div>
|
||||||
<label><input type="checkbox" name="debugSerial" value="true" ${config.debugSerial}/> Serial debugger</label>
|
<div class="col-xl-2 col-lg-3 col-md-4 col-sm-5 col-6">
|
||||||
|
<div class="m-2 input-group input-group-sm">
|
||||||
|
<div class="input-group-prepend">
|
||||||
|
<span class="input-group-text">LED</span>
|
||||||
|
</div>
|
||||||
|
<input name="ledPin" type="number" min="2" max="${gpio.max}" class="form-control" value="${config.ledPin}"/>
|
||||||
|
<div class="input-group-append" title="Inverted">
|
||||||
|
<label class="input-group-text">
|
||||||
|
<input type="checkbox" name="ledInverted" value="true" ${config.ledInverted}/> inv
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-5">
|
</div>
|
||||||
<div class="row form-group">
|
<div class="col-xl-3 col-lg-4 col-md-6">
|
||||||
<label class="col-6">Debug level</label>
|
<div class="m-2 input-group input-group-sm">
|
||||||
<div class="col-6">
|
<div class="input-group-prepend">
|
||||||
<select class="form-control" name="debugLevel">
|
<span class="input-group-text">RGB</span>
|
||||||
<option value="2" ${config.debugLevel2}>Debug</option>
|
</div>
|
||||||
<option value="3" ${config.debugLevel3}>Info</option>
|
<input name="ledPinRed" type="number" min="2" max="${gpio.max}" class="form-control" value="${config.ledPinRed}"/>
|
||||||
<option value="4" ${config.debugLevel4}>Warning</option>
|
<input name="ledPinGreen" type="number" min="2" max="${gpio.max}" class="form-control" value="${config.ledPinGreen}"/>
|
||||||
<option value="5" ${config.debugLevel5}>Error</option>
|
<input name="ledPinBlue" type="number" min="2" max="${gpio.max}" class="form-control" value="${config.ledPinBlue}"/>
|
||||||
</select>
|
<div class="input-group-append" title="Inverted">
|
||||||
|
<label class="input-group-text">
|
||||||
|
<input type="checkbox" name="ledRgbInverted" value="true" ${config.ledRgbInverted}/> inv
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-2 col-md-3 col-sm-6 col-6">
|
||||||
|
<div class="m-2 input-group input-group-sm">
|
||||||
|
<div class="input-group-prepend">
|
||||||
|
<span class="input-group-text">AP button</span>
|
||||||
|
</div>
|
||||||
|
<input name="apPin" type="number" min="0" max="${gpio.max}" class="form-control" value="${config.apPin}"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-xl-2 col-lg-3 col-md-4 col-sm-6 col-6">
|
||||||
|
<div class="m-2 input-group input-group-sm">
|
||||||
|
<div class="input-group-prepend">
|
||||||
|
<span class="input-group-text">Temperature</span>
|
||||||
|
</div>
|
||||||
|
<input name="tempSensorPin" type="number" min="0" max="${gpio.max}" class="form-control" value="${config.tempSensorPin}"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-xl-6 col-lg-8">
|
||||||
|
<div class="row p-2">
|
||||||
|
<div class="col-sm-3 col-5">
|
||||||
|
<div class="input-group input-group-sm">
|
||||||
|
<div class="input-group-prepend">
|
||||||
|
<span class="input-group-text">Vcc</span>
|
||||||
|
</div>
|
||||||
|
<input name="vccPin" type="number" min="0" max="${gpio.max}" class="form-control" value="${config.vccPin}"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-4 col-7">
|
||||||
|
<div class="input-group input-group-sm">
|
||||||
|
<div class="input-group-prepend">
|
||||||
|
<span class="input-group-text">Multiplier</span>
|
||||||
|
</div>
|
||||||
|
<input type="number" min="0.1" max="10" step="0.01" class="form-control" name="vccMultiplier" value="${config.vccMultiplier}" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-4 col-7">
|
||||||
|
<div class="input-group input-group-sm">
|
||||||
|
<div class="input-group-prepend">
|
||||||
|
<span class="input-group-text">Boot limit</span>
|
||||||
|
</div>
|
||||||
|
<input type="number" min="2.5" max="3.5" step="0.1" class="form-control" name="vccBootLimit" value="${config.vccBootLimit}" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-1 text-right">
|
|
||||||
<button class="btn btn-primary">Save</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</div>
|
||||||
|
<div class="my-3 p-3 bg-white rounded shadow">
|
||||||
<form method="post" enctype="multipart/form-data">
|
<h6>Debugger</h6>
|
||||||
<div class="my-3 p-3 bg-white rounded shadow">
|
<div class="row">
|
||||||
<div class="alert alert-warning">!!WARNING!!<br/>Do not use this unless you know what you are doing. Uploading the wrong image could cause your device to stop working. Use with extreme caution!</div>
|
<div class="col-xl-2 col-md-3">
|
||||||
<div class="row">
|
<label><input type="checkbox" name="debugTelnet" value="true" ${config.debugTelnet}/> Telnet debugger</label>
|
||||||
<div class="col-md-4">
|
</div>
|
||||||
<div class="row form-group">
|
<div class="col-xl-2 col-md-3">
|
||||||
<label class="col-4">Firmware</label>
|
<label><input type="checkbox" name="debugSerial" value="true" ${config.debugSerial}/> Serial debugger</label>
|
||||||
<div class="col-8">
|
</div>
|
||||||
<input type="file" name="file"/>
|
<div class="col-xl-3 col-md-4">
|
||||||
</div>
|
<div class="row form-group">
|
||||||
|
<label class="col-6">Debug level</label>
|
||||||
|
<div class="col-6">
|
||||||
|
<select class="form-control form-control-sm" name="debugLevel">
|
||||||
|
<option value="2" ${config.debugLevel2}>Debug</option>
|
||||||
|
<option value="3" ${config.debugLevel3}>Info</option>
|
||||||
|
<option value="4" ${config.debugLevel4}>Warning</option>
|
||||||
|
<option value="5" ${config.debugLevel5}>Error</option>
|
||||||
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-8 text-right">
|
|
||||||
<button class="btn btn-primary">Upload</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<hr/>
|
</div>
|
||||||
<div class="row form-group">
|
<div class="my-3 p-3 bg-white rounded shadow">
|
||||||
|
<div class="row">
|
||||||
<div class="col-6">
|
<div class="col-6">
|
||||||
<a href="/" class="btn btn-outline-secondary">Back</a>
|
<a href="/firmware" class="btn btn-sm btn-outline-secondary">Upload firmware</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-6 text-right">
|
<div class="col-6 text-right">
|
||||||
|
<a href="/reset" class="btn btn-sm btn-danger">Factory reset</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</div>
|
||||||
</main>
|
<hr/>
|
||||||
</body>
|
<div class="row form-group">
|
||||||
</html>
|
<div class="col-6">
|
||||||
|
<a href="/" class="btn btn-outline-secondary">Back</a>
|
||||||
|
</div>
|
||||||
|
<div class="col-6 text-right">
|
||||||
|
<button class="btn btn-primary">Save</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|||||||
@@ -1,97 +1,44 @@
|
|||||||
<html>
|
<form method="post" action="/save">
|
||||||
<head>
|
<input type="hidden" name="authConfig" value="true"/>
|
||||||
<meta charset="UTF-8">
|
<div class="my-3 p-3 bg-white rounded shadow">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<div class="row">
|
||||||
<title>AMS reader - Meter configuration</title>
|
<div class="col-xl-3 col-lg-4 col-md-7">
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
<div class="m-2 input-group input-group-sm">
|
||||||
<link rel="stylesheet" type="text/css" href="boot.css"/>
|
<div class="input-group-prepend">
|
||||||
<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
|
<span class="input-group-text">Security</span>
|
||||||
</head>
|
|
||||||
<body class="bg-light">
|
|
||||||
<main role="main" class="container">
|
|
||||||
<header class="navbar navbar-expand navbar-dark flex-column flex-md-row bg-purple rounded mt-2 mb-4" style="background-color: var(--purple);">
|
|
||||||
<a href="/" class=""><h6 class="navbar-brand">AMS reader <small>${version}</small></h6></a>
|
|
||||||
<div class="navbar-nav-scroll">
|
|
||||||
<ul class="navbar-nav bd-navbar-nav flex-row">
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" href="/config-meter">Meter</a>
|
|
||||||
</li>
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" href="/config-wifi">WiFi</a>
|
|
||||||
</li>
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" href="/config-mqtt">MQTT</a>
|
|
||||||
</li>
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link active" href="/config-web">Web</a>
|
|
||||||
</li>
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" href="/config-system">System</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<ul class="navbar-nav flex-row ml-md-auto d-none d-md-flex">
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link p-2" href="https://github.com/gskjold/AmsToMqttBridge" target="_blank" rel="noopener" aria-label="GitHub">
|
|
||||||
<svg class="d-inline-block align-text-top" style="width: 2rem; height: 2rem;" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 499.36" focusable="false"><title>GitHub</title><path d="M256 0C114.64 0 0 114.61 0 256c0 113.09 73.34 209 175.08 242.9 12.8 2.35 17.47-5.56 17.47-12.34 0-6.08-.22-22.18-.35-43.54-71.2 15.49-86.2-34.34-86.2-34.34-11.64-29.57-28.42-37.45-28.42-37.45-23.27-15.84 1.73-15.55 1.73-15.55 25.69 1.81 39.21 26.38 39.21 26.38 22.84 39.12 59.92 27.82 74.5 21.27 2.33-16.54 8.94-27.82 16.25-34.22-56.84-6.43-116.6-28.43-116.6-126.49 0-27.95 10-50.8 26.35-68.69-2.63-6.48-11.42-32.5 2.51-67.75 0 0 21.49-6.88 70.4 26.24a242.65 242.65 0 0 1 128.18 0c48.87-33.13 70.33-26.24 70.33-26.24 14 35.25 5.18 61.27 2.55 67.75 16.41 17.9 26.31 40.75 26.31 68.69 0 98.35-59.85 120-116.88 126.32 9.19 7.9 17.38 23.53 17.38 47.41 0 34.22-.31 61.83-.31 70.23 0 6.85 4.61 14.81 17.6 12.31C438.72 464.97 512 369.08 512 256.02 512 114.62 397.37 0 256 0z" fill="currentColor" fill-rule="evenodd"></path></svg>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</header>
|
|
||||||
<form method="post" action="/save">
|
|
||||||
<input type="hidden" name="authConfig" value="true"/>
|
|
||||||
<div class="my-3 p-3 bg-white rounded shadow">
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-md-4">
|
|
||||||
<div class="row form-group">
|
|
||||||
<label class="col-4">Security</label>
|
|
||||||
<div class="col-8">
|
|
||||||
<select id="authSecurity" class="form-control" name="authSecurity">
|
|
||||||
<option value="0" ${config.authSecurity0}>None</option>
|
|
||||||
<option value="1" ${config.authSecurity1}>Only configuration</option>
|
|
||||||
<option value="2" ${config.authSecurity2}>Everything</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
<select id="authSecurity" class="form-control" name="authSecurity">
|
||||||
|
<option value="0" ${config.authSecurity0}>None</option>
|
||||||
|
<option value="1" ${config.authSecurity1}>Only configuration</option>
|
||||||
|
<option value="2" ${config.authSecurity2}>Everything</option>
|
||||||
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-4">
|
</div>
|
||||||
<div class="row form-group">
|
<div class="col-xl-3 col-lg-4 col-md-6">
|
||||||
<label class="col-4">Username</label>
|
<div class="m-2 input-group input-group-sm">
|
||||||
<div class="col-8">
|
<div class="input-group-prepend">
|
||||||
<input type="text" class="form-control auth-config" name="authUser" value="${config.authUser}"/>
|
<span class="input-group-text">Username</span>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
<input type="text" class="form-control auth-config" name="authUser" value="${config.authUser}" maxlength="64"/>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-4">
|
</div>
|
||||||
<div class="row form-group">
|
<div class="col-xl-3 col-lg-4 col-md-6">
|
||||||
<label class="col-4">Password</label>
|
<div class="m-2 input-group input-group-sm">
|
||||||
<div class="col-8">
|
<div class="input-group-prepend">
|
||||||
<input type="password" class="form-control auth-config" name="authPassword" value="${config.authPassword}"/>
|
<span class="input-group-text">Password</span>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
<input type="password" class="form-control auth-config" name="authPassword" value="${config.authPassword}" maxlength="64"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<hr/>
|
</div>
|
||||||
<div class="row form-group">
|
<hr/>
|
||||||
<div class="col-6">
|
<div class="row form-group">
|
||||||
<a href="/" class="btn btn-outline-secondary">Back</a>
|
<div class="col-6">
|
||||||
</div>
|
<a href="/" class="btn btn-outline-secondary">Back</a>
|
||||||
<div class="col-6 text-right">
|
|
||||||
<button class="btn btn-primary">Save</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</form>
|
<div class="col-6 text-right">
|
||||||
</main>
|
<button class="btn btn-primary">Save</button>
|
||||||
<script>
|
</div>
|
||||||
$('#authSecurity').on('change', function() {
|
</div>
|
||||||
var inputs = $('.auth-config');
|
</form>
|
||||||
inputs.prop('disabled', $(this).val() == 0);
|
|
||||||
});
|
|
||||||
|
|
||||||
$(function() {
|
|
||||||
$('#authSecurity').trigger('change');
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|||||||
@@ -1,132 +1,85 @@
|
|||||||
<html>
|
<form method="post" action="/save">
|
||||||
<head>
|
<input type="hidden" name="wifiConfig" value="true"/>
|
||||||
<meta charset="UTF-8">
|
<div class="my-3 p-3 bg-white rounded shadow">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<div class="row">
|
||||||
<title>AMS reader - WiFi configuration</title>
|
<div class="col-xl-3 col-md-6 form-group">
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
<div class="input-group input-group-sm">
|
||||||
<link rel="stylesheet" type="text/css" href="boot.css"/>
|
<div class="input-group-prepend">
|
||||||
<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
|
<span class="input-group-text">SSID</span>
|
||||||
</head>
|
</div>
|
||||||
<body class="bg-light">
|
<input type="text" name="wifiSsid" class="form-control" maxlength="32" placeholder="Name of your WiFi" value="${config.wifiSsid}" required/>
|
||||||
<main role="main" class="container">
|
</div>
|
||||||
<header class="navbar navbar-expand navbar-dark flex-column flex-md-row bg-purple rounded mt-2 mb-4" style="background-color: var(--purple);">
|
</div>
|
||||||
<a href="/" class=""><h6 class="navbar-brand">AMS reader <small>${version}</small></h6></a>
|
<div class="col-xl-3 col-md-6 form-group">
|
||||||
<div class="navbar-nav-scroll">
|
<div class="input-group input-group-sm">
|
||||||
<ul class="navbar-nav bd-navbar-nav flex-row">
|
<div class="input-group-prepend">
|
||||||
<li class="nav-item">
|
<span class="input-group-text">PSK</span>
|
||||||
<a class="nav-link" href="/config-meter">Meter</a>
|
</div>
|
||||||
</li>
|
<input type="password" name="wifiPassword" class="form-control" maxlength="63" placeholder="Password for WiFi" value="${config.wifiPassword}" required/>
|
||||||
<li class="nav-item">
|
</div>
|
||||||
<a class="nav-link active" href="/config-wifi">WiFi</a>
|
</div>
|
||||||
</li>
|
<div class="col-xl-4 col-md-6 form-group">
|
||||||
<li class="nav-item">
|
<div class="input-group input-group-sm">
|
||||||
<a class="nav-link" href="/config-mqtt">MQTT</a>
|
<div class="input-group-prepend">
|
||||||
</li>
|
<span class="input-group-text">Hostname</span>
|
||||||
<li class="nav-item">
|
</div>
|
||||||
<a class="nav-link" href="/config-web">Web</a>
|
<input type="text" name="wifiHostname" class="form-control" maxlength="32" pattern="[a-z0-9_-]+" placeholder="Optional, ex.: ams-reader" value="${config.wifiHostname}"/>
|
||||||
</li>
|
</div>
|
||||||
<li class="nav-item">
|
</div>
|
||||||
<a class="nav-link" href="/config-system">System</a>
|
<div class="col-xl-2 col-md-6 form-group">
|
||||||
</li>
|
<label><input id="wifiIpType" type="checkbox" name="wifiIpType" value="1" ${config.wifiStaticIp}/> Static IP</label>
|
||||||
</ul>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<ul class="navbar-nav flex-row ml-md-auto d-none d-md-flex">
|
<div class="row" id="staticIp">
|
||||||
<li class="nav-item">
|
<div class="col-xl-3 col-lg-4 form-group">
|
||||||
<a class="nav-link p-2" href="https://github.com/gskjold/AmsToMqttBridge" target="_blank" rel="noopener" aria-label="GitHub">
|
<div class="input-group input-group-sm">
|
||||||
<svg class="d-inline-block align-text-top" style="width: 2rem; height: 2rem;" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 499.36" focusable="false"><title>GitHub</title><path d="M256 0C114.64 0 0 114.61 0 256c0 113.09 73.34 209 175.08 242.9 12.8 2.35 17.47-5.56 17.47-12.34 0-6.08-.22-22.18-.35-43.54-71.2 15.49-86.2-34.34-86.2-34.34-11.64-29.57-28.42-37.45-28.42-37.45-23.27-15.84 1.73-15.55 1.73-15.55 25.69 1.81 39.21 26.38 39.21 26.38 22.84 39.12 59.92 27.82 74.5 21.27 2.33-16.54 8.94-27.82 16.25-34.22-56.84-6.43-116.6-28.43-116.6-126.49 0-27.95 10-50.8 26.35-68.69-2.63-6.48-11.42-32.5 2.51-67.75 0 0 21.49-6.88 70.4 26.24a242.65 242.65 0 0 1 128.18 0c48.87-33.13 70.33-26.24 70.33-26.24 14 35.25 5.18 61.27 2.55 67.75 16.41 17.9 26.31 40.75 26.31 68.69 0 98.35-59.85 120-116.88 126.32 9.19 7.9 17.38 23.53 17.38 47.41 0 34.22-.31 61.83-.31 70.23 0 6.85 4.61 14.81 17.6 12.31C438.72 464.97 512 369.08 512 256.02 512 114.62 397.37 0 256 0z" fill="currentColor" fill-rule="evenodd"></path></svg>
|
<div class="input-group-prepend">
|
||||||
</a>
|
<span class="input-group-text">IP</span>
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</header>
|
|
||||||
<form method="post" action="/save">
|
|
||||||
<input type="hidden" name="wifiConfig" value="true"/>
|
|
||||||
<div class="my-3 p-3 bg-white rounded shadow">
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-md-4">
|
|
||||||
<div class="row form-group">
|
|
||||||
<label class="col-3">SSID</label>
|
|
||||||
<div class="col-9">
|
|
||||||
<input type="text" class="form-control" name="wifiSsid" value="${config.wifiSsid}"/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row form-group">
|
|
||||||
<label class="col-3">Password</label>
|
|
||||||
<div class="col-9">
|
|
||||||
<input type="password" class="form-control" name="wifiPassword" value="${config.wifiPassword}"/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row form-group">
|
|
||||||
<label class="col-3">Hostname</label>
|
|
||||||
<div class="col-9">
|
|
||||||
<input type="text" class="form-control" name="wifiHostname" value="${config.wifiHostname}"/>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
<input type="text" name="wifiIp" class="form-control" pattern="\d?\d?\d.\d?\d?\d.\d?\d?\d.\d?\d?\d" placeholder="Ex: 192.168.1.200" value="${config.wifiIp}"/>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-4">
|
</div>
|
||||||
<div class="row form-group">
|
<div class="col-xl-3 col-lg-4 form-group">
|
||||||
<label class="col-6">IP configuration</label>
|
<div class="input-group input-group-sm">
|
||||||
<div class="col-6">
|
<div class="input-group-prepend">
|
||||||
<select id="wifiIpType" class="form-control" name="wifiIpType">
|
<span class="input-group-text">Subnet</span>
|
||||||
<option value="0" ${config.wifiIpType0}>DHCP</option>
|
|
||||||
<option value="1" ${config.wifiIpType1}>Static</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row form-group">
|
|
||||||
<label class="col-6">IP</label>
|
|
||||||
<div class="col-6">
|
|
||||||
<input type="text" class="form-control wifiip-config" name="wifiIp" value="${config.wifiIp}"/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row form-group">
|
|
||||||
<label class="col-6">Subnet</label>
|
|
||||||
<div class="col-6">
|
|
||||||
<input type="text" class="form-control wifiip-config" name="wifiSubnet" value="${config.wifiSubnet}"/>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
<input type="text" name="wifiSubnet" class="form-control" pattern="\d?\d?\d.\d?\d?\d.\d?\d?\d.\d?\d?\d" placeholder="Ex.: 255.255.255.0" value="${config.wifiSubnet}"/>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-4">
|
</div>
|
||||||
<div class="row form-group">
|
<div class="col-xl-3 col-lg-4 form-group">
|
||||||
<label class="col-6">Gateway</label>
|
<div class="input-group input-group-sm">
|
||||||
<div class="col-6">
|
<div class="input-group-prepend">
|
||||||
<input type="text" class="form-control wifiip-config" name="wifiGw" value="${config.wifiGw}"/>
|
<span class="input-group-text">Gateway</span>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="row form-group">
|
<input type="text" name="wifiGw" class="form-control" pattern="\d?\d?\d.\d?\d?\d.\d?\d?\d.\d?\d?\d" placeholder="Ex.: 192.168.1.1" value="${config.wifiGw}"/>
|
||||||
<label class="col-6">Primary DNS</label>
|
</div>
|
||||||
<div class="col-6">
|
</div>
|
||||||
<input type="text" class="form-control wifiip-config" name="wifiDns1" value="${config.wifiDns1}"/>
|
<div class="col-xl-4 col-lg-5 form-group">
|
||||||
</div>
|
<div class="input-group input-group-sm">
|
||||||
|
<div class="input-group-prepend">
|
||||||
|
<span class="input-group-text">Primary DNS</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="row form-group">
|
<input type="text" name="wifiDns1" class="form-control" pattern="\d?\d?\d.\d?\d?\d.\d?\d?\d.\d?\d?\d" placeholder="Ex.: 192.168.1.1" value="${config.wifiDns1}"/>
|
||||||
<label class="col-6">Secondary DNS</label>
|
</div>
|
||||||
<div class="col-6">
|
</div>
|
||||||
<input type="text" class="form-control wifiip-config" name="wifiDns2" value="${config.wifiDns2}"/>
|
<div class="col-xl-4 col-lg-5 form-group">
|
||||||
</div>
|
<div class="input-group input-group-sm">
|
||||||
|
<div class="input-group-prepend">
|
||||||
|
<span class="input-group-text">Secondary DNS</span>
|
||||||
</div>
|
</div>
|
||||||
|
<input type="text" name="wifiDns2" class="form-control" pattern="\d?\d?\d.\d?\d?\d.\d?\d?\d.\d?\d?\d" placeholder="Ex.: 8.8.8.8" value="${config.wifiDns2}"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<hr/>
|
</div>
|
||||||
<div class="row form-group">
|
<hr/>
|
||||||
<div class="col-6">
|
<div class="row form-group">
|
||||||
<a href="/" class="btn btn-outline-secondary">Back</a>
|
<div class="col-6">
|
||||||
</div>
|
<a href="/" class="btn btn-outline-secondary">Back</a>
|
||||||
<div class="col-6 text-right">
|
|
||||||
<button class="btn btn-primary">Save</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</form>
|
<div class="col-6 text-right">
|
||||||
</main>
|
<button class="btn btn-primary">Save</button>
|
||||||
<script>
|
</div>
|
||||||
$('#wifiIpType').on('change', function() {
|
</div>
|
||||||
var inputs = $('.wifiip-config');
|
</form>
|
||||||
inputs.prop('disabled', $(this).val() != 1);
|
|
||||||
});
|
|
||||||
|
|
||||||
$(function() {
|
|
||||||
$('#wifiIpType').trigger('change');
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|||||||
14
web/delete.html
Normal file
14
web/delete.html
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
<form method="post">
|
||||||
|
<div class="my-3 p-3 bg-white rounded shadow">
|
||||||
|
<div class="alert alert-warning">Are you sure you want to delete this file?</div>
|
||||||
|
</div>
|
||||||
|
<hr/>
|
||||||
|
<div class="row form-group">
|
||||||
|
<div class="col-6">
|
||||||
|
<a href="javascript:history.back();" class="btn btn-outline-secondary">Back</a>
|
||||||
|
</div>
|
||||||
|
<div class="col-6 text-right">
|
||||||
|
<button class="btn btn-danger">Delete</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
13
web/foot.html
Normal file
13
web/foot.html
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<div id="newVersion" class="alert alert-info d-none">New version <span id="newVersionTag"></span>! <a id="newVersionUrl" href="#" target="_blank">view</a></div>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
|
||||||
|
<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.min.js"></script>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js"></script>
|
||||||
|
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js"></script>
|
||||||
|
<script src="gaugemeter.js"></script>
|
||||||
|
<script src="application.js"></script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -58,7 +58,7 @@
|
|||||||
"White" === option.theme && (t = "#fff"),
|
"White" === option.theme && (t = "#fff"),
|
||||||
"Black" === option.theme && (t = "#000"),
|
"Black" === option.theme && (t = "#000"),
|
||||||
t;
|
t;
|
||||||
}
|
};
|
||||||
/* The label below gauge. */
|
/* The label below gauge. */
|
||||||
function createLabel(t, a) {
|
function createLabel(t, a) {
|
||||||
if(t.children("b").length === 0){
|
if(t.children("b").length === 0){
|
||||||
@@ -67,7 +67,7 @@
|
|||||||
color: option.label_color
|
color: option.label_color
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
/* Prepend and append text, the gauge text or percentage value. */
|
/* Prepend and append text, the gauge text or percentage value. */
|
||||||
function createSpanTag(t) {
|
function createSpanTag(t) {
|
||||||
var fgcolor = "";
|
var fgcolor = "";
|
||||||
@@ -90,7 +90,7 @@
|
|||||||
"font-size": option.text_size * option.size + "px",
|
"font-size": option.text_size * option.size + "px",
|
||||||
color: fgcolor
|
color: fgcolor
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
/* Get data attributes as options from div tag. Fall back to defaults when not exists. */
|
/* Get data attributes as options from div tag. Fall back to defaults when not exists. */
|
||||||
function getDataAttr(t) {
|
function getDataAttr(t) {
|
||||||
$.each(dataAttr, function (index, element) {
|
$.each(dataAttr, function (index, element) {
|
||||||
@@ -116,10 +116,10 @@
|
|||||||
option[element] = parseFloat(option[element]);
|
option[element] = parseFloat(option[element]);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
/* Draws the gauge. */
|
/* Draws the gauge. */
|
||||||
function drawGauge(a) {
|
function drawGauge(a) {
|
||||||
if(M < 0) M = 0;
|
if(M < 0) M = 0;
|
||||||
if(M > 100) M = 100;
|
if(M > 100) M = 100;
|
||||||
var lw = option.width < 1 || isNaN(option.width) ? option.size / 20 : option.width;
|
var lw = option.width < 1 || isNaN(option.width) ? option.size / 20 : option.width;
|
||||||
g.clearRect(0, 0, b.width, b.height);
|
g.clearRect(0, 0, b.width, b.height);
|
||||||
@@ -141,7 +141,7 @@
|
|||||||
c > M && (M += z, requestAnimationFrame(function(){
|
c > M && (M += z, requestAnimationFrame(function(){
|
||||||
drawGauge(Math.min(M, c) / 100);
|
drawGauge(Math.min(M, c) / 100);
|
||||||
}, p));
|
}, p));
|
||||||
}
|
};
|
||||||
|
|
||||||
$(this).attr("data-id", $(this).attr("id"));
|
$(this).attr("data-id", $(this).attr("id"));
|
||||||
var r,
|
var r,
|
||||||
|
|||||||
6
web/github.svg
Normal file
6
web/github.svg
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" standalone="no"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 499.36" focusable="false">
|
||||||
|
<title>GitHub</title>
|
||||||
|
<path d="M256 0C114.64 0 0 114.61 0 256c0 113.09 73.34 209 175.08 242.9 12.8 2.35 17.47-5.56 17.47-12.34 0-6.08-.22-22.18-.35-43.54-71.2 15.49-86.2-34.34-86.2-34.34-11.64-29.57-28.42-37.45-28.42-37.45-23.27-15.84 1.73-15.55 1.73-15.55 25.69 1.81 39.21 26.38 39.21 26.38 22.84 39.12 59.92 27.82 74.5 21.27 2.33-16.54 8.94-27.82 16.25-34.22-56.84-6.43-116.6-28.43-116.6-126.49 0-27.95 10-50.8 26.35-68.69-2.63-6.48-11.42-32.5 2.51-67.75 0 0 21.49-6.88 70.4 26.24a242.65 242.65 0 0 1 128.18 0c48.87-33.13 70.33-26.24 70.33-26.24 14 35.25 5.18 61.27 2.55 67.75 16.41 17.9 26.31 40.75 26.31 68.69 0 98.35-59.85 120-116.88 126.32 9.19 7.9 17.38 23.53 17.38 47.41 0 34.22-.31 61.83-.31 70.23 0 6.85 4.61 14.81 17.6 12.31C438.72 464.97 512 369.08 512 256.02 512 114.62 397.37 0 256 0z" fill="#f8f9fa" fill-rule="evenodd"></path>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.1 KiB |
86
web/head.html
Normal file
86
web/head.html
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<title>AMS reader</title>
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css">
|
||||||
|
<style>
|
||||||
|
.GaugeMeter {
|
||||||
|
position: Relative;
|
||||||
|
text-align: Center;
|
||||||
|
overflow: Hidden;
|
||||||
|
cursor: Default;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.GaugeMeter SPAN, .GaugeMeter B {
|
||||||
|
width: 54%;
|
||||||
|
position: Absolute;
|
||||||
|
text-align: Center;
|
||||||
|
display: Inline-Block;
|
||||||
|
color: RGBa(0,0,0,.8);
|
||||||
|
font-weight: 100;
|
||||||
|
font-family: "Open Sans", Arial;
|
||||||
|
overflow: Hidden;
|
||||||
|
white-space: NoWrap;
|
||||||
|
text-overflow: Ellipsis;
|
||||||
|
margin: 0 23%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.GaugeMeter[data-style="Semi"] B {
|
||||||
|
width: 80%;
|
||||||
|
margin: 0 10%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.GaugeMeter S, .GaugeMeter U {
|
||||||
|
text-decoration: None;
|
||||||
|
font-size: .60em;
|
||||||
|
font-weight: 200;
|
||||||
|
opacity: .6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.GaugeMeter B {
|
||||||
|
color: #000;
|
||||||
|
font-weight: 200;
|
||||||
|
opacity: .8;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body class="bg-light">
|
||||||
|
<main role="main" class="container">
|
||||||
|
<header class="navbar navbar-expand navbar-dark flex-column flex-lg-row rounded mt-2 mb-4" style="background-color: var(--purple);">
|
||||||
|
<a href="/" class=""><h6 class="navbar-brand">AMS reader <small id="swVersion" data-url="https://api.github.com/repos/gskjold/AmsToMqttBridge/releases">${version}</small></h6></a>
|
||||||
|
<div class="navbar-nav-scroll">
|
||||||
|
<ul class="navbar-nav bd-navbar-nav flex-row">
|
||||||
|
<li class="nav-item">
|
||||||
|
<a id="config-meter-link" class="nav-link" href="/config-meter">Meter</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a id="config-wifi-link" class="nav-link" href="/config-wifi">WiFi</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a id="config-mqtt-link" class="nav-link" href="/config-mqtt">MQTT</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a id="config-web-link" class="nav-link" href="/config-web">Web</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a id="config-system-link" class="nav-link" href="/config-system">System</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="flex-row">
|
||||||
|
<div id="esp" class="d-none m-2">ESP</div>
|
||||||
|
<div id="han" class="d-none m-2">HAN</div>
|
||||||
|
<div id="wifi" class="d-none m-2">WiFi</div>
|
||||||
|
<div id="mqtt" class="d-none m-2">MQTT</div>
|
||||||
|
</div>
|
||||||
|
<ul class="navbar-nav flex-row ml-md-auto d-none d-lg-flex">
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link p-2" href="https://github.com/gskjold/AmsToMqttBridge" target="_blank" rel="noopener" aria-label="GitHub">
|
||||||
|
<img class="d-inline-block align-text-top" style="width: 2rem; height: 2rem;" src="github.svg"/>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</header>
|
||||||
453
web/index.html
453
web/index.html
@@ -1,358 +1,107 @@
|
|||||||
<html>
|
<div class="my-3 p-3 bg-white rounded shadow">
|
||||||
<head>
|
<div class="row">
|
||||||
<meta charset="UTF-8">
|
<div class="col-sm-6 col-lg-3">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<div class="text-center">
|
||||||
<title>AMS reader</title>
|
<div id="P" class="SimpleMeter" style="display: inline;">
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
${data.P} W
|
||||||
<link rel="stylesheet" type="text/css" href="boot.css"/>
|
|
||||||
<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
|
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.min.js"></script>
|
|
||||||
<script src="gaugemeter.js"></script>
|
|
||||||
<style>
|
|
||||||
.GaugeMeter {
|
|
||||||
position: Relative;
|
|
||||||
text-align: Center;
|
|
||||||
overflow: Hidden;
|
|
||||||
cursor: Default;
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.GaugeMeter SPAN, .GaugeMeter B {
|
|
||||||
width: 54%;
|
|
||||||
position: Absolute;
|
|
||||||
text-align: Center;
|
|
||||||
display: Inline-Block;
|
|
||||||
color: RGBa(0,0,0,.8);
|
|
||||||
font-weight: 100;
|
|
||||||
font-family: "Open Sans", Arial;
|
|
||||||
overflow: Hidden;
|
|
||||||
white-space: NoWrap;
|
|
||||||
text-overflow: Ellipsis;
|
|
||||||
margin: 0 23%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.GaugeMeter[data-style="Semi"] B {
|
|
||||||
width: 80%;
|
|
||||||
margin: 0 10%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.GaugeMeter S, .GaugeMeter U {
|
|
||||||
text-decoration: None;
|
|
||||||
font-size: .60em;
|
|
||||||
font-weight: 200;
|
|
||||||
opacity: .6;
|
|
||||||
}
|
|
||||||
|
|
||||||
.GaugeMeter B {
|
|
||||||
color: #000;
|
|
||||||
font-weight: 200;
|
|
||||||
opacity: .8;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body class="bg-light">
|
|
||||||
<main role="main" class="container">
|
|
||||||
<header class="navbar navbar-expand navbar-dark flex-column flex-md-row rounded mt-2 mb-4" style="background-color: var(--purple);">
|
|
||||||
<a href="/" class=""><h6 class="navbar-brand">AMS reader <small>${version}</small></h6></a>
|
|
||||||
<div class="navbar-nav-scroll">
|
|
||||||
<ul class="navbar-nav bd-navbar-nav flex-row">
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" href="/config-meter">Meter</a>
|
|
||||||
</li>
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" href="/config-wifi">WiFi</a>
|
|
||||||
</li>
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" href="/config-mqtt">MQTT</a>
|
|
||||||
</li>
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" href="/config-web">Web</a>
|
|
||||||
</li>
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" href="/config-system">System</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="flex-row ml-md-auto d-md-flex">
|
|
||||||
<div id="esp" class="d-none m-2">ESP</div>
|
|
||||||
<div id="han" class="d-none m-2">HAN</div>
|
|
||||||
<div id="wifi" class="d-none m-2">WiFi</div>
|
|
||||||
<div id="mqtt" class="d-none m-2">MQTT</div>
|
|
||||||
</div>
|
|
||||||
<ul class="navbar-nav flex-row ml-md-auto d-none d-md-flex">
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link p-2" href="https://github.com/gskjold/AmsToMqttBridge" target="_blank" rel="noopener" aria-label="GitHub">
|
|
||||||
<svg class="d-inline-block align-text-top" style="width: 2rem; height: 2rem;" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 499.36" focusable="false"><title>GitHub</title><path d="M256 0C114.64 0 0 114.61 0 256c0 113.09 73.34 209 175.08 242.9 12.8 2.35 17.47-5.56 17.47-12.34 0-6.08-.22-22.18-.35-43.54-71.2 15.49-86.2-34.34-86.2-34.34-11.64-29.57-28.42-37.45-28.42-37.45-23.27-15.84 1.73-15.55 1.73-15.55 25.69 1.81 39.21 26.38 39.21 26.38 22.84 39.12 59.92 27.82 74.5 21.27 2.33-16.54 8.94-27.82 16.25-34.22-56.84-6.43-116.6-28.43-116.6-126.49 0-27.95 10-50.8 26.35-68.69-2.63-6.48-11.42-32.5 2.51-67.75 0 0 21.49-6.88 70.4 26.24a242.65 242.65 0 0 1 128.18 0c48.87-33.13 70.33-26.24 70.33-26.24 14 35.25 5.18 61.27 2.55 67.75 16.41 17.9 26.31 40.75 26.31 68.69 0 98.35-59.85 120-116.88 126.32 9.19 7.9 17.38 23.53 17.38 47.41 0 34.22-.31 61.83-.31 70.23 0 6.85 4.61 14.81 17.6 12.31C438.72 464.97 512 369.08 512 256.02 512 114.62 397.37 0 256 0z" fill="currentColor" fill-rule="evenodd"></path></svg>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</header>
|
|
||||||
<div class="my-3 p-3 bg-white rounded shadow">
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-md-3">
|
|
||||||
<div class="text-center">
|
|
||||||
<div id="P" class="SimpleMeter" style="display: inline;">
|
|
||||||
${data.P} W
|
|
||||||
</div>
|
|
||||||
<div id="importMeter" class="GaugeMeter rounded"
|
|
||||||
style="display: none;"
|
|
||||||
data-size="200px"
|
|
||||||
data-text_size="0.11"
|
|
||||||
data-width="25"
|
|
||||||
data-style="Arch"
|
|
||||||
data-theme="Green-Gold-Red"
|
|
||||||
data-animationstep="0"
|
|
||||||
data-label="${text.import}"
|
|
||||||
></div>
|
|
||||||
</div>
|
</div>
|
||||||
|
<div id="importMeter" class="GaugeMeter rounded"
|
||||||
|
style="display: none;"
|
||||||
|
data-size="200px"
|
||||||
|
data-text_size="0.11"
|
||||||
|
data-width="25"
|
||||||
|
data-style="Arch"
|
||||||
|
data-theme="Green-Gold-Red"
|
||||||
|
data-animationstep="0"
|
||||||
|
data-label="${text.import}"
|
||||||
|
></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-3">
|
|
||||||
<div id="U1-row" class="row" style="display: ${display.P1};">
|
|
||||||
<div class="col-2">P1</div>
|
|
||||||
<div class="col-5 text-right"><span id="U1">${data.U1}</span> V</div>
|
|
||||||
<div class="col-5 text-right"><span id="I1">${data.I1}</span> A</div>
|
|
||||||
</div>
|
|
||||||
<div id="U2-row" class="row" style="display: ${display.P2};">
|
|
||||||
<div class="col-2">P2</div>
|
|
||||||
<div class="col-5 text-right"><span id="U2">${data.U2}</span> V</div>
|
|
||||||
<div class="col-5 text-right"><span id="I2">${data.I2}</span> A</div>
|
|
||||||
</div>
|
|
||||||
<div id="U3-row" class="row" style="display: ${display.P3};">
|
|
||||||
<div class="col-2">P3</div>
|
|
||||||
<div class="col-5 text-right"><span id="U3">${data.U3}</span> V</div>
|
|
||||||
<div class="col-5 text-right"><span id="I3">${data.I3}</span> A</div>
|
|
||||||
</div>
|
|
||||||
<hr/>
|
|
||||||
<div id="tPI-row" class="row" style="display: ${display.accumulative};">
|
|
||||||
<div class="col-6">Active in</div>
|
|
||||||
<div class="col-6 text-right"><span id="tPI">${data.tPI}</span> kWh</div>
|
|
||||||
</div>
|
|
||||||
<div id="tPO-row" class="row" style="display: ${display.accumulative};">
|
|
||||||
<div class="col-6">Active out</div>
|
|
||||||
<div class="col-6 text-right"><span id="tPO">${data.tPO}</span> kWh</div>
|
|
||||||
</div>
|
|
||||||
<div id="tQI-row" class="row" style="display: ${display.accumulative};">
|
|
||||||
<div class="col-6">Reactive in</div>
|
|
||||||
<div class="col-6 text-right"><span id="tQI">${data.tQI}</span> kvarh</div>
|
|
||||||
</div>
|
|
||||||
<div id="tQO-row" class="row" style="display: ${display.accumulative};">
|
|
||||||
<div class="col-6">Reactive out</div>
|
|
||||||
<div class="col-6 text-right"><span id="tQO">${data.tQO}</span> kvarh</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-md-3">
|
|
||||||
<div class="text-center" style="display: ${display.export};">
|
|
||||||
<div id="P" class="SimpleMeter" style="display: inline;">
|
|
||||||
${data.PO} W
|
|
||||||
</div>
|
|
||||||
<div id="exportMeter" class="GaugeMeter rounded"
|
|
||||||
style="display: none;"
|
|
||||||
data-size="200px"
|
|
||||||
data-text_size="0.11"
|
|
||||||
data-width="25"
|
|
||||||
data-style="Arch"
|
|
||||||
data-theme="DarkGreen-LightGreen"
|
|
||||||
data-animationstep="0"
|
|
||||||
data-label="Export"
|
|
||||||
></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-3">
|
<div class="col-sm-6 col-lg-3">
|
||||||
<hr class="d-md-inline"/>
|
<div id="U1-row" class="row" style="display: ${display.P1};">
|
||||||
<div class="row">
|
<div class="col-2">L1</div>
|
||||||
<div class="col-6">Vcc</div>
|
<div class="col-5 text-right"><span id="U1">${data.U1}</span> V</div>
|
||||||
<div class="col-6 text-right"><span id="vcc">${vcc}</span> V</div>
|
<div class="col-5 text-right"><span id="I1">${data.I1}</span> A</div>
|
||||||
</div>
|
|
||||||
<div class="row" style="display: ${display.temp};">
|
|
||||||
<div class="col-6">Temperature</div>
|
|
||||||
<div class="col-6 text-right"><span id="temp">${temp}</span> °C</div>
|
|
||||||
</div>
|
|
||||||
<div class="row" style="display: none;">
|
|
||||||
<div class="col-6">Uptime</div>
|
|
||||||
<div class="col-6 text-right"><span id="currentMillis">${currentMillis}</span></div>
|
|
||||||
</div>
|
|
||||||
<hr/>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-6">SSID</div>
|
|
||||||
<div class="col-6 text-right"><span id="ssid">${wifi.ssid}</span></div>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-6">Channel</div>
|
|
||||||
<div class="col-6 text-right"><span id="channel">${wifi.channel}</span></div>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-6">RSSI</div>
|
|
||||||
<div class="col-6 text-right"><span id="rssi">${wifi.rssi}</span> dBm</div>
|
|
||||||
</div>
|
|
||||||
<hr class="d-none mqtt-error mqtt-error-1 mqtt-error-2 mqtt-error-3 mqtt-error-4 mqtt-error-5 mqtt-error-6 mqtt-error-7 mqtt-error-8 mqtt-error-9 mqtt-error-10 mqtt-error-11 mqtt-error-12 mqtt-error-13"/>
|
|
||||||
<div class="d-none badge badge-danger mqtt-error mqtt-error-1 mqtt-error-2 mqtt-error-5 mqtt-error-6 mqtt-error-7 mqtt-error-8 mqtt-error-9 mqtt-error-12">MQTT communication error (<span id="mqtt-lastError">-</span>)</div>
|
|
||||||
<div class="d-none badge badge-danger mqtt-error mqtt-error-3">MQTT failed to connect</div>
|
|
||||||
<div class="d-none badge badge-danger mqtt-error mqtt-error-4">MQTT network timeout</div>
|
|
||||||
<div class="d-none badge badge-danger mqtt-error mqtt-error-10">MQTT connection denied</div>
|
|
||||||
<div class="d-none badge badge-danger mqtt-error mqtt-error-11">MQTT failed to subscribe</div>
|
|
||||||
<div class="d-none badge badge-danger mqtt-error mqtt-error-13">MQTT lost connection</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
<div id="U2-row" class="row" style="display: ${display.P2};">
|
||||||
|
<div class="col-2">L2</div>
|
||||||
|
<div class="col-5 text-right"><span id="U2">${data.U2}</span> V</div>
|
||||||
|
<div class="col-5 text-right"><span id="I2">${data.I2}</span> A</div>
|
||||||
|
</div>
|
||||||
|
<div id="U3-row" class="row" style="display: ${display.P3};">
|
||||||
|
<div class="col-2">L3</div>
|
||||||
|
<div class="col-5 text-right"><span id="U3">${data.U3}</span> V</div>
|
||||||
|
<div class="col-5 text-right"><span id="I3">${data.I3}</span> A</div>
|
||||||
|
</div>
|
||||||
|
<hr/>
|
||||||
|
<div id="tPI-row" class="row" style="display: ${display.accumulative};">
|
||||||
|
<div class="col-6">Active in</div>
|
||||||
|
<div class="col-6 text-right"><span id="tPI">${data.tPI}</span> kWh</div>
|
||||||
|
</div>
|
||||||
|
<div id="tPO-row" class="row" style="display: ${display.accumulative};">
|
||||||
|
<div class="col-6">Active out</div>
|
||||||
|
<div class="col-6 text-right"><span id="tPO">${data.tPO}</span> kWh</div>
|
||||||
|
</div>
|
||||||
|
<div id="tQI-row" class="row" style="display: ${display.accumulative};">
|
||||||
|
<div class="col-6">Reactive in</div>
|
||||||
|
<div class="col-6 text-right"><span id="tQI">${data.tQI}</span> kvarh</div>
|
||||||
|
</div>
|
||||||
|
<div id="tQO-row" class="row" style="display: ${display.accumulative};">
|
||||||
|
<div class="col-6">Reactive out</div>
|
||||||
|
<div class="col-6 text-right"><span id="tQO">${data.tQO}</span> kvarh</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-6 col-lg-3">
|
||||||
|
<div class="text-center" style="display: ${display.export};">
|
||||||
|
<div id="P" class="SimpleMeter" style="display: inline;">
|
||||||
|
${data.PO} W
|
||||||
|
</div>
|
||||||
|
<div id="exportMeter" class="GaugeMeter rounded"
|
||||||
|
style="display: none;"
|
||||||
|
data-size="200px"
|
||||||
|
data-text_size="0.11"
|
||||||
|
data-width="25"
|
||||||
|
data-style="Arch"
|
||||||
|
data-theme="DarkGreen-LightGreen"
|
||||||
|
data-animationstep="0"
|
||||||
|
data-label="Export"
|
||||||
|
></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-6 col-lg-3">
|
||||||
|
<hr class="d-md-inline"/>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-6">Vcc</div>
|
||||||
|
<div class="col-6 text-right"><span id="vcc">${vcc}</span> V</div>
|
||||||
|
</div>
|
||||||
|
<div class="row" style="display: ${display.temp};">
|
||||||
|
<div class="col-6">Temperature</div>
|
||||||
|
<div class="col-6 text-right"><span id="temp">${temp}</span> °C</div>
|
||||||
|
</div>
|
||||||
|
<div class="row" style="display: none;">
|
||||||
|
<div class="col-6">Uptime</div>
|
||||||
|
<div class="col-6 text-right"><span id="currentMillis">${currentMillis}</span></div>
|
||||||
|
</div>
|
||||||
|
<hr/>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-6">SSID</div>
|
||||||
|
<div class="col-6 text-right"><span id="ssid">${wifi.ssid}</span></div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-6">Channel</div>
|
||||||
|
<div class="col-6 text-right"><span id="channel">${wifi.channel}</span></div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-6">RSSI</div>
|
||||||
|
<div class="col-6 text-right"><span id="rssi">${wifi.rssi}</span> dBm</div>
|
||||||
|
</div>
|
||||||
|
<hr class="d-none mqtt-error mqtt-error-1 mqtt-error-2 mqtt-error-3 mqtt-error-4 mqtt-error-5 mqtt-error-6 mqtt-error-7 mqtt-error-8 mqtt-error-9 mqtt-error-10 mqtt-error-11 mqtt-error-12 mqtt-error-13"/>
|
||||||
|
<div class="d-none badge badge-danger mqtt-error mqtt-error-1 mqtt-error-2 mqtt-error-5 mqtt-error-6 mqtt-error-7 mqtt-error-8 mqtt-error-9 mqtt-error-12">MQTT communication error (<span id="mqtt-lastError">-</span>)</div>
|
||||||
|
<div class="d-none badge badge-danger mqtt-error mqtt-error-3">MQTT failed to connect</div>
|
||||||
|
<div class="d-none badge badge-danger mqtt-error mqtt-error-4">MQTT network timeout</div>
|
||||||
|
<div class="d-none badge badge-danger mqtt-error mqtt-error-10">MQTT connection denied</div>
|
||||||
|
<div class="d-none badge badge-danger mqtt-error mqtt-error-11">MQTT failed to subscribe</div>
|
||||||
|
<div class="d-none badge badge-danger mqtt-error mqtt-error-13">MQTT lost connection</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</div>
|
||||||
<script>
|
|
||||||
var im = $("#importMeter")
|
|
||||||
im.gaugeMeter({
|
|
||||||
percent: 0,
|
|
||||||
text: "-",
|
|
||||||
append: "W"
|
|
||||||
});
|
|
||||||
|
|
||||||
var em = $("#exportMeter")
|
|
||||||
em.gaugeMeter({
|
|
||||||
percent: 0,
|
|
||||||
text: "-",
|
|
||||||
append: "W"
|
|
||||||
});
|
|
||||||
|
|
||||||
var setStatus = function(id, status) {
|
|
||||||
var item = $('#'+id);
|
|
||||||
item.removeClass('d-none');
|
|
||||||
item.removeClass (function (index, className) {
|
|
||||||
return (className.match (/(^|\s)badge-\S+/g) || []).join(' ');
|
|
||||||
});
|
|
||||||
item.addClass('badge badge-' + status);
|
|
||||||
};
|
|
||||||
|
|
||||||
var interval = 5000;
|
|
||||||
var fetch = function() {
|
|
||||||
$.ajax({
|
|
||||||
url: '/data.json',
|
|
||||||
timeout: 10000,
|
|
||||||
dataType: 'json',
|
|
||||||
}).done(function(json) {
|
|
||||||
$(".SimpleMeter").hide();
|
|
||||||
im.show();
|
|
||||||
em.show();
|
|
||||||
|
|
||||||
for(var id in json) {
|
|
||||||
var str = json[id];
|
|
||||||
if(typeof str === "object")
|
|
||||||
continue;
|
|
||||||
if(isNaN(str)) {
|
|
||||||
$('#'+id).html(str);
|
|
||||||
} else {
|
|
||||||
var num = parseFloat(str);
|
|
||||||
$('#'+id).html(num.toFixed(num < 0 ? 0 : num < 10 ? 2 : 1));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(window.moment) {
|
|
||||||
$('#currentMillis').html(moment.duration(parseInt(json.uptime_seconds), 'seconds').humanize());
|
|
||||||
$('#currentMillis').closest('.row').show();
|
|
||||||
}
|
|
||||||
|
|
||||||
if(json.status) {
|
|
||||||
for(var id in json.status) {
|
|
||||||
setStatus(id, json.status[id]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(json.mqtt) {
|
|
||||||
$('.mqtt-error').addClass('d-none');
|
|
||||||
$('.mqtt-error'+json.mqtt.lastError).removeClass('d-none');
|
|
||||||
$('#mqtt-lastError').html(json.mqtt.lastError);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(json.wifi) {
|
|
||||||
for(var id in json.wifi) {
|
|
||||||
var str = json.wifi[id];
|
|
||||||
dst = $('#'+id);
|
|
||||||
if(isNaN(str)) {
|
|
||||||
dst.html(str);
|
|
||||||
} else {
|
|
||||||
var num = parseFloat(str);
|
|
||||||
dst.html(num.toFixed(0));
|
|
||||||
$('#'+id+'-row').show();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(json.data) {
|
|
||||||
var p = 0;
|
|
||||||
var p_pct = parseInt(json.p_pct);
|
|
||||||
var p_append = "W";
|
|
||||||
if(json.data.P) {
|
|
||||||
p = parseFloat(json.data.P);
|
|
||||||
if(p > 1000) {
|
|
||||||
p = (p/1000).toFixed(1);
|
|
||||||
p_append = "kW";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
im.gaugeMeter({
|
|
||||||
percent: p_pct,
|
|
||||||
text: p,
|
|
||||||
append: p_append
|
|
||||||
});
|
|
||||||
|
|
||||||
var po = 0;
|
|
||||||
var po_pct = parseInt(json.po_pct);
|
|
||||||
var po_append = "W";
|
|
||||||
if(json.data.PO) {
|
|
||||||
po = parseFloat(json.data.PO);
|
|
||||||
if(po > 1000) {
|
|
||||||
po = (po/1000).toFixed(1);
|
|
||||||
po_append = "kW";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
em.gaugeMeter({
|
|
||||||
percent: po_pct,
|
|
||||||
text: po,
|
|
||||||
append: po_append
|
|
||||||
});
|
|
||||||
|
|
||||||
for(var id in json.data) {
|
|
||||||
var str = json.data[id];
|
|
||||||
if(isNaN(str)) {
|
|
||||||
$('#'+id).html(str);
|
|
||||||
} else {
|
|
||||||
var num = parseFloat(str);
|
|
||||||
$('#'+id).html(num.toFixed(1));
|
|
||||||
$('#'+id+'-row').show();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
im.gaugeMeter({
|
|
||||||
percent: 0,
|
|
||||||
text: "-",
|
|
||||||
append: "W"
|
|
||||||
});
|
|
||||||
|
|
||||||
em.gaugeMeter({
|
|
||||||
percent: 0,
|
|
||||||
text: "-",
|
|
||||||
append: "W"
|
|
||||||
});
|
|
||||||
}
|
|
||||||
setTimeout(fetch, interval);
|
|
||||||
}).fail(function() {
|
|
||||||
setTimeout(fetch, interval*4);
|
|
||||||
|
|
||||||
im.gaugeMeter({
|
|
||||||
percent: 0,
|
|
||||||
text: "-",
|
|
||||||
append: "W"
|
|
||||||
});
|
|
||||||
|
|
||||||
em.gaugeMeter({
|
|
||||||
percent: 0,
|
|
||||||
text: "-",
|
|
||||||
append: "W"
|
|
||||||
});
|
|
||||||
|
|
||||||
setStatus("mqtt", "secondary");
|
|
||||||
setStatus("wifi", "secondary");
|
|
||||||
setStatus("han", "secondary");
|
|
||||||
setStatus("esp", "danger");
|
|
||||||
});
|
|
||||||
}
|
|
||||||
fetch();
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|||||||
14
web/reset.html
Normal file
14
web/reset.html
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
<form method="post">
|
||||||
|
<div class="my-3 p-3 bg-white rounded shadow">
|
||||||
|
<div class="alert alert-danger">Are you sure you want reset this device to factory settings? ALL configuration will be erased!</div>
|
||||||
|
</div>
|
||||||
|
<hr/>
|
||||||
|
<div class="row form-group">
|
||||||
|
<div class="col-6">
|
||||||
|
<a href="javascript:history.back();" class="btn btn-outline-secondary">Back</a>
|
||||||
|
</div>
|
||||||
|
<div class="col-6 text-right">
|
||||||
|
<button class="btn btn-danger" name="perform" value="true">Perform factory reset</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
@@ -5,35 +5,15 @@
|
|||||||
<title>AMS reader - Restarting, please wait</title>
|
<title>AMS reader - Restarting, please wait</title>
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
<link rel="stylesheet" type="text/css" href="boot.css"/>
|
<link rel="stylesheet" type="text/css" href="boot.css"/>
|
||||||
<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
|
|
||||||
</head>
|
</head>
|
||||||
<body class="bg-light">
|
<body class="bg-light">
|
||||||
<main role="main" class="container">
|
<main role="main" class="container">
|
||||||
<header class="navbar navbar-expand navbar-dark flex-column flex-md-row bg-purple rounded mt-2 mb-4" style="background-color: var(--purple);">
|
<header class="navbar navbar-expand navbar-dark flex-column flex-md-row bg-purple rounded mt-2 mb-4" style="background-color: var(--purple);">
|
||||||
<a href="/" class=""><h6 class="navbar-brand">AMS reader <small>${version}</small></h6></a>
|
<a href="/" class=""><h6 class="navbar-brand">AMS reader <small>${version}</small></h6></a>
|
||||||
<div class="navbar-nav-scroll">
|
|
||||||
<ul class="navbar-nav bd-navbar-nav flex-row">
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" href="/config-meter">Meter</a>
|
|
||||||
</li>
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" href="/config-wifi">WiFi</a>
|
|
||||||
</li>
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" href="/config-mqtt">MQTT</a>
|
|
||||||
</li>
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" href="/config-web">Web</a>
|
|
||||||
</li>
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" href="/config-system">System</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<ul class="navbar-nav flex-row ml-md-auto d-none d-md-flex">
|
<ul class="navbar-nav flex-row ml-md-auto d-none d-md-flex">
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link p-2" href="https://github.com/gskjold/AmsToMqttBridge" target="_blank" rel="noopener" aria-label="GitHub">
|
<a class="nav-link p-2" href="https://github.com/gskjold/AmsToMqttBridge" target="_blank" rel="noopener" aria-label="GitHub">
|
||||||
<svg class="d-inline-block align-text-top" style="width: 2rem; height: 2rem;" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 499.36" focusable="false"><title>GitHub</title><path d="M256 0C114.64 0 0 114.61 0 256c0 113.09 73.34 209 175.08 242.9 12.8 2.35 17.47-5.56 17.47-12.34 0-6.08-.22-22.18-.35-43.54-71.2 15.49-86.2-34.34-86.2-34.34-11.64-29.57-28.42-37.45-28.42-37.45-23.27-15.84 1.73-15.55 1.73-15.55 25.69 1.81 39.21 26.38 39.21 26.38 22.84 39.12 59.92 27.82 74.5 21.27 2.33-16.54 8.94-27.82 16.25-34.22-56.84-6.43-116.6-28.43-116.6-126.49 0-27.95 10-50.8 26.35-68.69-2.63-6.48-11.42-32.5 2.51-67.75 0 0 21.49-6.88 70.4 26.24a242.65 242.65 0 0 1 128.18 0c48.87-33.13 70.33-26.24 70.33-26.24 14 35.25 5.18 61.27 2.55 67.75 16.41 17.9 26.31 40.75 26.31 68.69 0 98.35-59.85 120-116.88 126.32 9.19 7.9 17.38 23.53 17.38 47.41 0 34.22-.31 61.83-.31 70.23 0 6.85 4.61 14.81 17.6 12.31C438.72 464.97 512 369.08 512 256.02 512 114.62 397.37 0 256 0z" fill="currentColor" fill-rule="evenodd"></path></svg>
|
<img class="d-inline-block align-text-top" style="width: 2rem; height: 2rem;" src="github.svg"/>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
@@ -44,7 +24,6 @@
|
|||||||
</main>
|
</main>
|
||||||
<script>
|
<script>
|
||||||
var tries = 0;
|
var tries = 0;
|
||||||
|
|
||||||
var ip = "${ip}";
|
var ip = "${ip}";
|
||||||
var hostname = "${hostname}";
|
var hostname = "${hostname}";
|
||||||
var url;
|
var url;
|
||||||
@@ -60,15 +39,22 @@
|
|||||||
} else {
|
} else {
|
||||||
url = "";
|
url = "";
|
||||||
}
|
}
|
||||||
if(console) console.log("Trying url " + url)
|
if(console) console.log("Trying url " + url);
|
||||||
$.ajax({
|
|
||||||
url: url + '/is-alive',
|
var retry = function() {
|
||||||
timeout: 5000
|
|
||||||
}).done(function(json) {
|
|
||||||
window.location.href = url ? url : "/";
|
|
||||||
}).fail(function() {
|
|
||||||
setTimeout(fetch, 1000);
|
setTimeout(fetch, 1000);
|
||||||
|
};
|
||||||
|
|
||||||
|
var xhr = new XMLHttpRequest();
|
||||||
|
xhr.timeout = 5000;
|
||||||
|
xhr.addEventListener('abort', retry);
|
||||||
|
xhr.addEventListener('error', retry);
|
||||||
|
xhr.addEventListener('timeout', retry);
|
||||||
|
xhr.addEventListener('load', function(e) {
|
||||||
|
window.location.href = url ? url : "/";
|
||||||
});
|
});
|
||||||
|
xhr.open("GET", url + "/is-alive", true);
|
||||||
|
xhr.send();
|
||||||
};
|
};
|
||||||
setTimeout(fetch, 10000);
|
setTimeout(fetch, 10000);
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
137
web/setup.html
Normal file
137
web/setup.html
Normal file
@@ -0,0 +1,137 @@
|
|||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<title>AMS reader - Setup</title>
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<link rel="stylesheet" type="text/css" href="boot.css"/>
|
||||||
|
</head>
|
||||||
|
<body class="bg-light">
|
||||||
|
<main role="main" class="container">
|
||||||
|
<header class="navbar navbar-expand navbar-dark flex-column flex-md-row bg-purple rounded mt-2 mb-4">
|
||||||
|
<a href="/" class=""><h6 class="navbar-brand">AMS reader <small>${version}</small></h6></a>
|
||||||
|
<ul class="navbar-nav flex-row ml-md-auto d-none d-md-flex">
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link p-2" href="https://github.com/gskjold/AmsToMqttBridge" target="_blank" rel="noopener" aria-label="GitHub">
|
||||||
|
<img style="width: 2rem; height: 2rem;" src="github.svg"/>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</header>
|
||||||
|
<form method="post">
|
||||||
|
<div class="my-3 p-3 bg-white rounded shadow">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-xl-4 col-md-6">
|
||||||
|
<h5>Hardware</h5>
|
||||||
|
<select name="board" class="form-control">
|
||||||
|
<optgroup label="Custom hardware">
|
||||||
|
<option value="0" ${config.boardType0}>Custom hardware by Roar Fredriksen</option>
|
||||||
|
<option value="1" ${config.boardType1}>Kamstrup module by Egil Opsahl</option>
|
||||||
|
<option value="2" ${config.boardType2}>HAN Reader 2.0 by Max Spencer</option>
|
||||||
|
</optgroup>
|
||||||
|
<optgroup label="ESP8266">
|
||||||
|
<option value="101" ${config.boardType101}>Wemos D1</option>
|
||||||
|
<option value="100" ${config.boardType100}>Generic ESP8266</option>
|
||||||
|
</optgroup>
|
||||||
|
<optgroup label="ESP32">
|
||||||
|
<option value="201" ${config.boardType201}>Wemos LOLIN D32</option>
|
||||||
|
<option value="202" ${config.boardType202}>Adafruit HUZZAH32</option>
|
||||||
|
<option value="203" ${config.boardType203}>DevKitC</option>
|
||||||
|
<option value="200" ${config.boardType200}>Generic ESP32</option>
|
||||||
|
</optgroup>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="col-xl-2 col-md-3">
|
||||||
|
<h5>Meter</h5>
|
||||||
|
<select name="meterType" class="form-control">
|
||||||
|
<option value="0" ${config.meterType0}>Autodetect</option>
|
||||||
|
<option value="1" ${config.meterType1}>Kaifa</option>
|
||||||
|
<option value="2" ${config.meterType2}>Aidon</option>
|
||||||
|
<option value="3" ${config.meterType3}>Kamstrup</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="my-3 p-3 bg-white rounded shadow">
|
||||||
|
<h5>WiFi</h5>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-xl-3 col-md-6 form-group">
|
||||||
|
<div class="input-group">
|
||||||
|
<div class="input-group-prepend">
|
||||||
|
<span class="input-group-text">SSID</span>
|
||||||
|
</div>
|
||||||
|
<input type="text" name="wifiSsid" class="form-control" maxlength="32" placeholder="Name of your WiFi" required value="${config.wifiSsid}"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-xl-3 col-md-6 form-group">
|
||||||
|
<div class="input-group">
|
||||||
|
<div class="input-group-prepend">
|
||||||
|
<span class="input-group-text">PSK</span>
|
||||||
|
</div>
|
||||||
|
<input type="password" name="wifiPassword" class="form-control" maxlength="63" placeholder="Password for WiFi" required value="${config.wifiPassword}"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-xl-4 col-md-6 form-group">
|
||||||
|
<div class="input-group">
|
||||||
|
<div class="input-group-prepend">
|
||||||
|
<span class="input-group-text">Hostname</span>
|
||||||
|
</div>
|
||||||
|
<input type="text" name="wifiHostname" class="form-control" maxlength="32" pattern="[a-z0-9_-]+" placeholder="Optional, ex.: ams-reader" value="${config.wifiHostname}"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-xl-2 col-md-6 form-group">
|
||||||
|
<label><input type="checkbox" name="wifiIpType" value="1" onchange="staticChecked(this);" ${config.wifiStaticIp}/> Static IP</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row" id="staticIp">
|
||||||
|
<div class="col-xl-3 col-lg-4 col-sm-6 form-group">
|
||||||
|
<div class="input-group">
|
||||||
|
<div class="input-group-prepend">
|
||||||
|
<span class="input-group-text">IP</span>
|
||||||
|
</div>
|
||||||
|
<input type="text" name="wifiIp" class="form-control" pattern="\d?\d?\d.\d?\d?\d.\d?\d?\d.\d?\d?\d" placeholder="Ex: 192.168.1.200" value="${config.wifiIp}"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-xl-3 col-lg-4 col-sm-6 form-group">
|
||||||
|
<div class="input-group">
|
||||||
|
<div class="input-group-prepend">
|
||||||
|
<span class="input-group-text">Subnet</span>
|
||||||
|
</div>
|
||||||
|
<input type="text" name="wifiSubnet" class="form-control" pattern="\d?\d?\d.\d?\d?\d.\d?\d?\d.\d?\d?\d" placeholder="Ex.: 255.255.255.0" value="${config.wifiSubnet}"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-xl-3 col-lg-4 col-sm-6 form-group">
|
||||||
|
<div class="input-group">
|
||||||
|
<div class="input-group-prepend">
|
||||||
|
<span class="input-group-text">Gateway</span>
|
||||||
|
</div>
|
||||||
|
<input type="text" name="wifiGw" class="form-control" pattern="\d?\d?\d.\d?\d?\d.\d?\d?\d.\d?\d?\d" placeholder="Ex.: 192.168.1.1" value="${config.wifiGw}"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-xl-3 col-lg-4 col-sm-6 form-group">
|
||||||
|
<div class="input-group">
|
||||||
|
<div class="input-group-prepend">
|
||||||
|
<span class="input-group-text">DNS</span>
|
||||||
|
</div>
|
||||||
|
<input type="text" name="wifiDns1" class="form-control" pattern="\d?\d?\d.\d?\d?\d.\d?\d?\d.\d?\d?\d" placeholder="Ex.: 192.168.1.1" value="${config.wifiDns1}"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<hr/>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-6"></div>
|
||||||
|
<div class="col-6 text-right">
|
||||||
|
<button type="submit" class="btn btn-primary">Save & reboot</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</main>
|
||||||
|
<script>
|
||||||
|
document.getElementById('staticIp').style.display = "none";
|
||||||
|
var staticChecked = function(el) {
|
||||||
|
document.getElementById('staticIp').style.display = el.checked ? "" : "none";
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
26
web/upload.html
Normal file
26
web/upload.html
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
<form method="post" enctype="multipart/form-data">
|
||||||
|
<div class="my-3 p-3 bg-white rounded shadow">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-6">
|
||||||
|
<div class="input-group mb-3">
|
||||||
|
<div class="input-group-prepend">
|
||||||
|
<span class="input-group-text">Upload</span>
|
||||||
|
</div>
|
||||||
|
<div class="custom-file">
|
||||||
|
<input name="file" type="file" class="custom-file-input" id="fileUploadField">
|
||||||
|
<label class="custom-file-label" for="fileUploadField">Choose file</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<hr/>
|
||||||
|
<div class="row form-group">
|
||||||
|
<div class="col-6">
|
||||||
|
<a href="javascript:history.back();" class="btn btn-outline-secondary">Back</a>
|
||||||
|
</div>
|
||||||
|
<div class="col-6 text-right">
|
||||||
|
<button class="btn btn-primary">Upload</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
Reference in New Issue
Block a user