Merge branch 'master' into low_power

This commit is contained in:
Gunnar Skjold 2020-02-09 13:45:27 +01:00
commit 6d3d4adc7e
19 changed files with 422 additions and 120 deletions

View File

@ -40,6 +40,8 @@ jobs:
run: |
python -m pip install --upgrade pip
pip install -U platformio
- name: Configure build targets
run: echo "[platformio]\ndefault_envs = hw1esp12e, esp12e, esp32" > platformio-user.ini
- name: PlatformIO lib install
run: pio lib install
- name: PlatformIO run

View File

@ -51,6 +51,15 @@ jobs:
release_name: Release ${{ github.ref }}
draft: false
prerelease: false
- name: Upload hw1esp12e binary to release
uses: actions/upload-release-asset@v1.0.1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: .pio/build/hw1esp12e/firmware.bin
asset_name: ams2mqtt-hw1esp12e-${{ steps.release_tag.outputs.tag }}.bin
asset_content_type: application/octet-stream
- name: Upload esp12e binary to release
uses: actions/upload-release-asset@v1.0.1
env:
@ -60,14 +69,32 @@ jobs:
asset_path: .pio/build/esp12e/firmware.bin
asset_name: ams2mqtt-esp12e-${{ steps.release_tag.outputs.tag }}.bin
asset_content_type: application/octet-stream
- name: Upload hw1esp12e binary to release
- name: Upload d1mini binary to release
uses: actions/upload-release-asset@v1.0.1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: .pio/build/hw1esp12e/firmware.bin
asset_name: ams2mqtt-hw1esp12e-${{ steps.release_tag.outputs.tag }}.bin
asset_path: .pio/build/d1mini/firmware.bin
asset_name: ams2mqtt-d1mini-${{ steps.release_tag.outputs.tag }}.bin
asset_content_type: application/octet-stream
- name: Upload esp32 binary to release
uses: actions/upload-release-asset@v1.0.1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: .pio/build/esp32/firmware.bin
asset_name: ams2mqtt-esp32-${{ steps.release_tag.outputs.tag }}.bin
asset_content_type: application/octet-stream
- name: Upload lolind32 binary to release
uses: actions/upload-release-asset@v1.0.1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: .pio/build/lolind32/firmware.bin
asset_name: ams2mqtt-lolind32-${{ steps.release_tag.outputs.tag }}.bin
asset_content_type: application/octet-stream
- name: Upload featheresp32 binary to release
uses: actions/upload-release-asset@v1.0.1

View File

@ -1,14 +1,21 @@
# AMS <-> MQTT Bridge
Orignally designed and coded by [@roarfred](https://github.com/roarfred), see the original repo at [roarfred/AmsToMqttBridge](https://github.com/roarfred/AmsToMqttBridge)
This repository contains the code and schematics necessary to build a device to receive and convert data from AMS electrical meters installed in Norway. The code can be used on both ESP8266 and ESP32, both as custom build devices or built from readily available modules. It reads data from the HAN port of the meter and sends this to a configured MQTT bus.
This repository contains the code and schematics necessary to build a device to receive and convert data from AMS electrical meters installed in Norway. The code can be used on both ESP8266 and ESP32, both as custom build devices or built from readily available development modules. It reads data from the HAN port of the meter and sends this to a configured MQTT bus.
There is also a web interface available on runtime, showing meter data in real time.
<img src="webui.jpg" width="480">
## Release binaries
In the [Release section](https://github.com/gskjold/AmsToMqttBridge/releases) of this repository, you will find precompiled binaries for some common boards.
- _esp12e_ :: General ESP8266 board with 12E or 12F chip, ex NodeMCU board.
- _hw1esp12e_ :: First version hardware with ESP 12E of 12F chip.
- _hw1esp12e_ :: First version custom hardware with ESP 12E of 12F chip
- _esp12e_ :: General ESP8266 board with 12E or 12F chip
- _d1mini_ :: Wemos D1 mini
- _esp32_ :: General ESP32 board
- _lolind32_ :: Wemos D32
- _featheresp32_ :: Adafruit ESP32 feather
### Flashing binaries with [esptool.py](https://github.com/espressif/esptool)
@ -18,3 +25,15 @@ Linux:
Windows:
```esptool.py --port COM1 write_flash 0x0 binary-file.bin```
## Building this project with PlatformIO
To build this project, you need [PlatformIO](https://platformio.org/) installed.
It is recommended to use Visual Studio Code with the PlatformIO plugin for development.
[Visual Studio Code](https://code.visualstudio.com/download)
[PlatformIO vscode plugin](https://platformio.org/install/ide?install=vscode)
Copy the ```platformio-user.ini-example``` to ```platformio-user.ini``` and customize to your preference. The code will adapt to the platform and board set in your profile. If you are using the original board design by [@roarfred](https://github.com/roarfred) use build flag -D HW_ROARFRED=1

View File

@ -12,9 +12,25 @@ Building this project will require some skills in ordering and assembling electr
*The completed board mounted in a [3D printed enclosure](/Enclosure)*
## Assembly of readily available modules
Use a ESP based developmentboard and a M-bus module.
You can also use a ESP based development board and combine this with a M-Bus module. Here are a few boards that have been tested, each one has a dedicated firmware file in the releases section.
[Adafruit Feather M0 WiFi w/ATWINC1500](https://www.adafruit.com/product/3010)
### ESP8266 based boards
[Wemos D1 mini](https://docs.wemos.cc/en/latest/d1/d1_mini.html)
- M-Bus connected to GPIO5 (D1)
- Jump GPIO4 (D2) to GND to force AP mode during boot
### ESP32 based boards
[Wemos D32](https://docs.wemos.cc/en/latest/d32/d32.html)
- M-Bus connected to GPIO21
- Jump GPIO4 to GND to force AP mode during boot
[Adafruit HUZZAH32](https://www.adafruit.com/product/3405)
- M-Bus connected to RX
Combine one of above board with an M-Bus module. Connect 3.3v and GND together between the boards and connect the TX pin from the M-Bus board to the dedicated M-Bus pin on the ESP board.
[TSS721 M-BUS module board](https://www.aliexpress.com/item/TSS721/32751482255.html)

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

View File

@ -56,7 +56,6 @@ void HanConfigAp::setup(int accessPointButtonPin, configuration* config, Stream*
delay(2000);
WiFi.mode(WIFI_AP);
WiFi.setOutputPower(0);
WiFi.softAP(AP_SSID);
/* Setup the DNS server redirecting all the domains to this IP */

View File

@ -8,9 +8,11 @@ enum class Aidon
{
List1 = 0x01,
List1PhaseShort = 0x09,
List1PhaseLong = 0xff, // TODO: Need sample
List1PhaseLong = 0x0E,
List3PhaseShort = 0x0D,
List3PhaseLong = 0x12
List3PhaseLong = 0x12,
List3PhaseITShort = 0x0C,
List3PhaseITLong = 0x11,
};
enum class Aidon_List1
@ -73,6 +75,33 @@ enum class Aidon_List1Phase
IGN_14,
VoltageL1Int8,
VoltageL1Enum,
IGN_15,
Timestamp_OBIS,
Timestamp,
IGN_16,
CumulativeActiveImportEnergy_OBIS,
CumulativeActiveImportEnergy,
IGN_17,
CumulativeActiveImportEnergyInt8,
CumulativeActiveImportEnergyEnum,
IGN_18,
CumulativeActiveExportEnergy_OBIS,
CumulativeActiveExportEnergy,
IGN_19,
CumulativeActiveExportEnergyInt8,
CumulativeActiveExportEnergyEnum,
IGN_20,
CumulativeReactiveImportEnergy_OBIS,
CumulativeReactiveImportEnergy,
IGN_21,
CumulativeReactiveImportEnergyInt8,
CumulativeReactiveImportEnergyEnum,
IGN_22,
CumulativeReactiveExportEnergy_OBIS,
CumulativeReactiveExportEnergy,
IGN_23,
CumulativeReactiveExportEnergyInt8,
CumulativeReactiveExportEnergyEnum
};
enum class Aidon_List3Phase
@ -176,6 +205,101 @@ enum class Aidon_List3Phase
CumulativeReactiveExportEnergyEnum
};
enum class Aidon_List3PhaseIT
{
ListSize,
IGN_0,
ListVersionIdentifier_OBIS,
ListVersionIdentifier,
IGN_1,
MeterID_OBIS,
MeterID,
IGN_2,
MeterType_OBIS,
MeterType,
IGN_3,
ActiveImportPower_OBIS,
ActiveImportPower,
IGN_4,
ActiveImportPowerInt8,
ActiveImportPowerEnum,
IGN_5,
ActiveExportPower_OBIS,
ActiveExportPower,
IGN_6,
ActiveExportPowerInt8,
ActiveExportPowerEnum,
IGN_7,
ReactiveImportPower_OBIS,
ReactiveImportPower,
IGN_8,
ReactiveImportPowerInt8,
ReactiveImportPowerEnum,
IGN_9,
ReactiveExportPower_OBIS,
ReactiveExportPower,
IGN_10,
ReactiveExportPowerInt8,
ReactiveExportPowerEnum,
IGN_11,
CurrentL1_OBIS,
CurrentL1,
IGN_12,
CurrentL1Int8,
CurrentL1Enum,
IGN_13,
CurrentL3_OBIS,
CurrentL3,
IGN_14,
CurrentL3Int8,
CurrentL3Enum,
IGN_15,
VoltageL1_OBIS,
VoltageL1,
IGN_16,
VoltageL1Int8,
VoltageL1Enum,
IGN_17,
VoltageL2_OBIS,
VoltageL2,
IGN_18,
VoltageL2Int8,
VoltageL2Enum,
IGN_19,
VoltageL3_OBIS,
VoltageL3,
IGN_20,
VoltageL3Int8,
VoltageL3Enum,
IGN_21,
Timestamp_OBIS,
Timestamp,
IGN_22,
CumulativeActiveImportEnergy_OBIS,
CumulativeActiveImportEnergy,
IGN_23,
CumulativeActiveImportEnergyInt8,
CumulativeActiveImportEnergyEnum,
IGN_24,
CumulativeActiveExportEnergy_OBIS,
CumulativeActiveExportEnergy,
IGN_25,
CumulativeActiveExportEnergyInt8,
CumulativeActiveExportEnergyEnum,
IGN_26,
CumulativeReactiveImportEnergy_OBIS,
CumulativeReactiveImportEnergy,
IGN_27,
CumulativeReactiveImportEnergyInt8,
CumulativeReactiveImportEnergyEnum,
IGN_28,
CumulativeReactiveExportEnergy_OBIS,
CumulativeReactiveExportEnergy,
IGN_29,
CumulativeReactiveExportEnergyInt8,
CumulativeReactiveExportEnergyEnum
};
#endif

View File

@ -5,7 +5,7 @@ HanReader::HanReader()
}
void HanReader::setup(HardwareSerial *hanPort, Stream *debugPort)
void HanReader::setup(Stream *hanPort, Stream *debugPort)
{
han = hanPort;
bytesRead = 0;
@ -13,7 +13,7 @@ void HanReader::setup(HardwareSerial *hanPort, Stream *debugPort)
if (debug) debug->println("MBUS serial setup complete");
}
void HanReader::setup(HardwareSerial *hanPort)
void HanReader::setup(Stream *hanPort)
{
setup(hanPort, NULL);
}

View File

@ -18,8 +18,8 @@ public:
bool compensateFor09HeaderBug = false;
HanReader();
void setup(HardwareSerial *hanPort);
void setup(HardwareSerial *hanPort, Stream *debugPort);
void setup(Stream *hanPort);
void setup(Stream *hanPort, Stream *debugPort);
bool read();
bool read(byte data);
int getListSize();
@ -30,7 +30,7 @@ public:
private:
Stream *debug;
HardwareSerial *han;
Stream *han;
byte buffer[512];
int bytesRead;
DlmsReader reader;

View File

@ -101,8 +101,6 @@ static void hanToJsonAidon3phase(int listSize, JsonObject& data, HanReader& hanR
data["tQI"] = hanReader.getInt( (int)Aidon_List3Phase::CumulativeReactiveImportEnergy);
data["tQO"] = hanReader.getInt( (int)Aidon_List3Phase::CumulativeReactiveExportEnergy);
}
// TODO: Do not divide Aidon values by 10!?
}
static void hanToJsonAidon1phase(int listSize, JsonObject& data, HanReader& hanReader, Stream *debugger)
@ -118,7 +116,46 @@ static void hanToJsonAidon1phase(int listSize, JsonObject& data, HanReader& hanR
data["U1"] = ((double) hanReader.getInt( (int)Aidon_List1Phase::VoltageL1)) / 10;
}
// TODO Aidon::List1PhaseLong
if (listSize >= (int)Aidon::List1PhaseLong)
{
data["tPI"] = hanReader.getInt( (int)Aidon_List1Phase::CumulativeActiveImportEnergy);
data["tPO"] = hanReader.getInt( (int)Aidon_List1Phase::CumulativeActiveExportEnergy);
data["tQI"] = hanReader.getInt( (int)Aidon_List1Phase::CumulativeReactiveImportEnergy);
data["tQO"] = hanReader.getInt( (int)Aidon_List1Phase::CumulativeReactiveExportEnergy);
}
}
static void hanToJsonAidon3phaseIT(int listSize, JsonObject& data, HanReader& hanReader, Stream *debugger)
{
if (listSize >= (int)Aidon::List3PhaseITShort)
{
data["lv"] = hanReader.getString( (int)Aidon_List3PhaseIT::ListVersionIdentifier);
data["id"] = hanReader.getString( (int)Aidon_List3PhaseIT::MeterID);
data["type"] = hanReader.getString( (int)Aidon_List3PhaseIT::MeterType);
int p = hanReader.getInt( (int)Aidon_List3PhaseIT::ActiveImportPower);
data["P"] = p;
data["Q"] = hanReader.getInt( (int)Aidon_List3PhaseIT::ReactiveExportPower);
double i1 = ((double) hanReader.getInt( (int)Aidon_List3PhaseIT::CurrentL1)) / 10;
double i3 = ((double) hanReader.getInt( (int)Aidon_List3PhaseIT::CurrentL3)) / 10;
double u1 = ((double) hanReader.getInt( (int)Aidon_List3PhaseIT::VoltageL1)) / 10;
double u2 = ((double) hanReader.getInt( (int)Aidon_List3PhaseIT::VoltageL2)) / 10;
double u3 = ((double) hanReader.getInt( (int)Aidon_List3PhaseIT::VoltageL3)) / 10;
double i2 = 0.00;
data["I1"] = i1;
data["I2"] = i2;
data["I3"] = i3;
data["U1"] = u1;
data["U2"] = u2;
data["U3"] = u3;
}
if (listSize >= (int)Aidon::List3PhaseITLong)
{
data["tPI"] = hanReader.getInt( (int)Aidon_List3PhaseIT::CumulativeActiveImportEnergy);
data["tPO"] = hanReader.getInt( (int)Aidon_List3PhaseIT::CumulativeActiveExportEnergy);
data["tQI"] = hanReader.getInt( (int)Aidon_List3PhaseIT::CumulativeReactiveImportEnergy);
data["tQO"] = hanReader.getInt( (int)Aidon_List3PhaseIT::CumulativeReactiveExportEnergy);
}
}
static void hanToJsonAidon(JsonObject& data, HanReader& hanReader, Stream *debugger)
@ -141,6 +178,9 @@ static void hanToJsonAidon(JsonObject& data, HanReader& hanReader, Stream *debug
case (int)Aidon::List1PhaseShort:
case (int)Aidon::List1PhaseLong:
return hanToJsonAidon1phase(listSize, data, hanReader, debugger);
case (int)Aidon::List3PhaseITShort:
case (int)Aidon::List3PhaseITLong:
return hanToJsonAidon3phaseIT(listSize, data, hanReader, debugger);
default:
if (debugger) debugger->printf("Warning: Unknown listSize %d\n", listSize);
return;

View File

@ -7,8 +7,9 @@ board = esp12e
framework = ${common.framework}
lib_deps = ${common.lib_deps}
build_flags =
-D HAS_DALLAS_TEMP_SENSOR=0
-D IS_CUSTOM_AMS_BOARD=0
-D HW_ROARFRED=1
-D DEBUG_MODE=1
monitor_speed = 2400
monitor_flags = --parity E
monitor_flags =
--parity
E

View File

@ -4,19 +4,7 @@ extra_configs = platformio-user.ini
[common]
framework = arduino
lib_deps = HanConfigAp@1.0.0, HanReader@1.0.0, HanToJson@1.0.0, ArduinoJson@^6.0.0, MQTT@^2.4.0, DallasTemperature@^3.8.0
[env:esp12e]
platform = espressif8266
board = esp12e
framework = ${common.framework}
lib_deps = ${common.lib_deps}
build_flags =
-D HAS_DALLAS_TEMP_SENSOR=0
-D IS_CUSTOM_AMS_BOARD=0
extra_scripts =
pre:scripts/addversion.py
scripts/makeweb.py
lib_deps = HanConfigAp@1.0.0, HanReader@1.0.0, HanToJson@1.0.0, ArduinoJson@^6.0.0, MQTT@^2.4.0, DallasTemperature@^3.8.0, EspSoftwareSerial@^6.7.1
[env:hw1esp12e]
platform = espressif8266
@ -24,8 +12,43 @@ board = esp12e
framework = ${common.framework}
lib_deps = ${common.lib_deps}
build_flags =
-D HAS_DALLAS_TEMP_SENSOR=1
-D IS_CUSTOM_AMS_BOARD=1
-D HW_ROARFRED=1
extra_scripts =
pre:scripts/addversion.py
scripts/makeweb.py
[env:esp12e]
platform = espressif8266
board = esp12e
framework = ${common.framework}
lib_deps = ${common.lib_deps}
extra_scripts =
pre:scripts/addversion.py
scripts/makeweb.py
[env:d1mini]
platform = espressif8266
board = d1_mini
framework = ${common.framework}
lib_deps = ${common.lib_deps}
extra_scripts =
pre:scripts/addversion.py
scripts/makeweb.py
[env:esp32]
platform = espressif32
board = esp32dev
framework = ${common.framework}
lib_deps = ${common.lib_deps}
extra_scripts =
pre:scripts/addversion.py
scripts/makeweb.py
[env:lolind32]
platform = espressif32
board = lolin_d32
framework = ${common.framework}
lib_deps = ${common.lib_deps}
extra_scripts =
pre:scripts/addversion.py
scripts/makeweb.py
@ -35,9 +58,6 @@ platform = espressif32
board = featheresp32
framework = ${common.framework}
lib_deps = ${common.lib_deps}
build_flags =
-D HAS_DALLAS_TEMP_SENSOR=0
-D IS_CUSTOM_AMS_BOARD=0
extra_scripts =
pre:scripts/addversion.py
scripts/makeweb.py

64
src/AmsToMqttBridge.h Normal file
View File

@ -0,0 +1,64 @@
#define WIFI_CONNECTION_TIMEOUT 30000;
#if defined(ESP8266)
#include <ESP8266WiFi.h>
#elif defined(ESP32)
#include <WiFi.h>
#endif
// 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
#include <DallasTemperature.h>
#include <OneWire.h>
#define TEMP_SENSOR_PIN 5 // Temperature sensor connected to GPIO5
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
#define SOFTWARE_SERIAL 1
#include <SoftwareSerial.h>
SoftwareSerial *hanSerial = new SoftwareSerial(GPIO_NUM_21);
// 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 = &Serial;
// 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
#if defined TEMP_SENSOR_PIN
OneWire oneWire(TEMP_SENSOR_PIN);
DallasTemperature tempSensor(&oneWire);
#endif

View File

@ -4,55 +4,26 @@
Author: roarf
*/
ADC_MODE(ADC_VCC);
#if defined(ESP8266)
ADC_MODE(ADC_VCC);
#endif
#include "AmsToMqttBridge.h"
#include <ArduinoJson.h>
#include <MQTT.h>
#if HAS_DALLAS_TEMP_SENSOR
#include <DallasTemperature.h>
#include <OneWire.h>
#endif
#if defined(ESP8266)
#include <ESP8266WiFi.h>
#elif defined(ESP32)
#include <WiFi.h>
#endif
#include "web/AmsWebServer.h"
#include "HanConfigAp.h"
#include "HanReader.h"
#include "HanToJson.h"
#define WIFI_CONNECTION_TIMEOUT 30000;
#if IS_CUSTOM_AMS_BOARD
#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
#elif defined(ARDUINO_LOLIN_D32)
#define LED_PIN 5
#define LED_ACTIVE_HIGH 0
#define AP_BUTTON_PIN INVALID_BUTTON_PIN
#else
#define LED_PIN LED_BUILTIN
#define LED_ACTIVE_HIGH 1
#define AP_BUTTON_PIN INVALID_BUTTON_PIN
#endif
#if HAS_DALLAS_TEMP_SENSOR
#define TEMP_SENSOR_PIN 5 // Temperature sensor connected to GPIO5
OneWire oneWire(TEMP_SENSOR_PIN);
DallasTemperature tempSensor(&oneWire);
#endif
// Configuration
configuration config;
// Object used to boot as Access Point
HanConfigAp ap;
// Web server
AmsWebServer ws;
// WiFi client and MQTT client
@ -67,30 +38,35 @@ HanReader hanReader;
// the setup function runs once when you press reset or power the board
void setup() {
#if DEBUG_MODE
debugger = &Serial;
#endif
if(config.hasConfig()) {
config.load();
}
if(config.meterType == 3) {
Serial.begin(2400, SERIAL_8N1);
} else {
Serial.begin(2400, SERIAL_8E1);
}
while (!Serial);
#if DEBUG_MODE
debugger = &Serial;
#if SOFTWARE_SERIAL
debugger->begin(115200, SERIAL_8N1);
#else
if(config.meterType == 3) {
hanSerial->begin(2400, SERIAL_8N1);
} else {
hanSerial->begin(2400, SERIAL_8E1);
}
#endif
while (!&debugger);
#endif
if (debugger) {
debugger->println("");
debugger->println("Started...");
#if defined(ESP8266)
debugger->print("Voltage: ");
debugger->print(ESP.getVcc());
debugger->println("mV");
#endif
}
#if defined(ESP8266)
if (ESP.getVcc() < 3300) {
if(debugger) {
debugger->print("Voltage is too low: ");
@ -99,6 +75,7 @@ void setup() {
}
ESP.deepSleep(10000000); //Deep sleep to allow output cap to charge up
}
#endif
// Flash the LED, to indicate we can boot as AP now
pinMode(LED_PIN, OUTPUT);
@ -122,8 +99,25 @@ void setup() {
sendMqttData("Connected!");
}
// Configure uart for AMS data
#if defined SOFTWARE_SERIAL
if(config.meterType == 3) {
hanSerial->begin(2400, SWSERIAL_8N1);
} else {
hanSerial->begin(2400, SWSERIAL_8E1);
}
#else
if(config.meterType == 3) {
hanSerial->begin(2400, SERIAL_8N1);
} else {
hanSerial->begin(2400, SERIAL_8E1);
}
#if defined UART2
hanSerial->swap();
#endif
#endif
while (!&hanSerial);
hanReader.setup(&Serial, debugger);
hanReader.setup(hanSerial, debugger);
// Compensate for the known Kaifa bug
hanReader.compensateFor09HeaderBug = (config.meterType == 1);
@ -161,8 +155,13 @@ void loop()
if (millis() / 50 % 64 == 0) led_on();
else led_off();
#if defined(ESP8266)
// Make sure there is enough power to run
delay(max(10, 3500-ESP.getVcc()));
#else
delay(10);
#endif
}
ws.loop();
}
@ -242,13 +241,15 @@ void readHanPort()
json["id"] = WiFi.macAddress();
json["up"] = millis();
json["t"] = time;
#if defined(ESP8266)
json["vcc"] = ((double) ESP.getVcc()) / 1000;
#endif
// Add a sub-structure to the json object,
// to keep the data from the meter itself
JsonObject data = json.createNestedObject("data");
#if HAS_DALLAS_TEMP_SENSOR
#if defined TEMP_SENSOR_PIN
// Get the temperature too
tempSensor.requestTemperatures();
data["temp"] = tempSensor.getTempCByIndex(0);
@ -389,7 +390,9 @@ void sendMqttData(String data)
json["id"] = WiFi.macAddress();
json["up"] = millis();
json["data"] = data;
#if defined(ESP8266)
json["vcc"] = ((double) ESP.getVcc()) / 1000;
#endif
// Stringify the json
String msg;

View File

@ -44,13 +44,21 @@ void AmsWebServer::loop() {
void AmsWebServer::setJson(StaticJsonDocument<500> json) {
if(!json.isNull()) {
p = json["data"]["P"].as<int>();
if(json["data"].containsKey("U1")) {
u1 = json["data"]["U1"].as<double>();
u2 = json["data"]["U2"].as<double>();
u3 = json["data"]["U3"].as<double>();
i1 = json["data"]["I1"].as<double>();
i2 = json["data"]["I2"].as<double>();
i3 = json["data"]["I3"].as<double>();
if(json["data"].containsKey("U2")) {
u2 = json["data"]["U2"].as<double>();
i2 = json["data"]["I2"].as<double>();
if(json["data"].containsKey("U3")) {
u3 = json["data"]["U3"].as<double>();
i3 = json["data"]["I3"].as<double>();
}
}
if(maxPwr == 0 && config->hasConfig() && config->fuseSize > 0 && config->distSys > 0) {
int volt = config->distSys == 2 ? 400 : 230;

View File

@ -243,29 +243,6 @@ a {
input:not([type="image" i]) {
box-sizing: border-box;
}
input {
-webkit-writing-mode: horizontal-tb !important;
text-rendering: auto;
color: -internal-light-dark-color(black, white);
letter-spacing: normal;
word-spacing: normal;
text-transform: none;
text-indent: 0px;
text-shadow: none;
display: inline-block;
text-align: start;
-webkit-appearance: textfield;
background-color: -internal-light-dark-color(white, black);
-webkit-rtl-ordering: logical;
cursor: text;
margin: 0em;
font: 400 13.3333px Arial;
padding: 1px 0px;
border-width: 2px;
border-style: inset;
border-color: initial;
border-image: initial;
}
button, input {
overflow: visible;
}
@ -275,6 +252,10 @@ button, input, optgroup, select, textarea {
font-size: inherit;
line-height: inherit;
}
input[type="radio"], input[type="checkbox"] {
box-sizing: border-box;
padding: 0;
}
hr {
margin-top: 1rem;
margin-bottom: 1rem;
@ -324,6 +305,3 @@ hr {
*, ::after, ::before {
box-sizing: border-box;
}
*, ::after, ::before {
box-sizing: border-box;
}

View File

@ -5,7 +5,7 @@
<title>AMS reader - configuration</title>
<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="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.4.1/css/bootstrap.css"/>
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.4.1/css/bootstrap.min.css"/>
<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
<style>
.bg-purple {
@ -69,6 +69,7 @@
<option value="" ${config.fuseSize0}></option>
<option value="25" ${config.fuseSize25}>25A</option>
<option value="32" ${config.fuseSize32}>32A</option>
<option value="35" ${config.fuseSize32}>35A</option>
<option value="40" ${config.fuseSize40}>40A</option>
<option value="50" ${config.fuseSize50}>50A</option>
<option value="63" ${config.fuseSize63}>63A</option>

View File

@ -5,7 +5,7 @@
<title>AMS reader</title>
<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="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.4.1/css/bootstrap.css"/>
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.4.1/css/bootstrap.min.css"/>
<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
<script src="gaugemeter.js"></script>
<style>

BIN
webui.jpg Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 336 KiB