diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 158595c8..cc5540b3 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -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
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 8d6805c5..e54acb5c 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -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
diff --git a/README.md b/README.md
index 973f8a61..6bba8ceb 100644
--- a/README.md
+++ b/README.md
@@ -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.
+
+
## 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
\ No newline at end of file
diff --git a/hardware/README.md b/hardware/README.md
index 9ebec2fa..b37dcb8e 100644
--- a/hardware/README.md
+++ b/hardware/README.md
@@ -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)
diff --git a/hardware/img/wemos_d1_mini.jpg b/hardware/img/wemos_d1_mini.jpg
new file mode 100644
index 00000000..82e56dad
Binary files /dev/null and b/hardware/img/wemos_d1_mini.jpg differ
diff --git a/lib/HanConfigAp/src/HanConfigAp.cpp b/lib/HanConfigAp/src/HanConfigAp.cpp
index 0db20c8d..edc8e0bf 100644
--- a/lib/HanConfigAp/src/HanConfigAp.cpp
+++ b/lib/HanConfigAp/src/HanConfigAp.cpp
@@ -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 */
diff --git a/lib/HanReader/src/Aidon.h b/lib/HanReader/src/Aidon.h
index 9f577dda..ffe0dc87 100644
--- a/lib/HanReader/src/Aidon.h
+++ b/lib/HanReader/src/Aidon.h
@@ -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
diff --git a/lib/HanReader/src/HanReader.cpp b/lib/HanReader/src/HanReader.cpp
index 6012a432..9d6df8b4 100644
--- a/lib/HanReader/src/HanReader.cpp
+++ b/lib/HanReader/src/HanReader.cpp
@@ -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);
}
diff --git a/lib/HanReader/src/HanReader.h b/lib/HanReader/src/HanReader.h
index 95753b9b..5e91e6ce 100644
--- a/lib/HanReader/src/HanReader.h
+++ b/lib/HanReader/src/HanReader.h
@@ -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;
diff --git a/lib/HanToJson/src/HanToJson.cpp b/lib/HanToJson/src/HanToJson.cpp
index 1202bf79..ee8f7185 100644
--- a/lib/HanToJson/src/HanToJson.cpp
+++ b/lib/HanToJson/src/HanToJson.cpp
@@ -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;
diff --git a/platformio-user.ini-example b/platformio-user.ini-example
index cd08b246..b232ae10 100644
--- a/platformio-user.ini-example
+++ b/platformio-user.ini-example
@@ -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
diff --git a/platformio.ini b/platformio.ini
index 40f5cfde..326212b3 100755
--- a/platformio.ini
+++ b/platformio.ini
@@ -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
diff --git a/src/AmsToMqttBridge.h b/src/AmsToMqttBridge.h
new file mode 100644
index 00000000..0b984c9f
--- /dev/null
+++ b/src/AmsToMqttBridge.h
@@ -0,0 +1,64 @@
+#define WIFI_CONNECTION_TIMEOUT 30000;
+
+
+#if defined(ESP8266)
+#include
+#elif defined(ESP32)
+#include
+#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
+#include
+#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 *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 *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 *hanSerial = new SoftwareSerial(5);
+#endif
+
+
+#if defined TEMP_SENSOR_PIN
+OneWire oneWire(TEMP_SENSOR_PIN);
+DallasTemperature tempSensor(&oneWire);
+#endif
\ No newline at end of file
diff --git a/src/AmsToMqttBridge.ino b/src/AmsToMqttBridge.ino
index 9adaddfb..ede0a441 100644
--- a/src/AmsToMqttBridge.ino
+++ b/src/AmsToMqttBridge.ino
@@ -4,55 +4,26 @@
Author: roarf
*/
-ADC_MODE(ADC_VCC);
+#if defined(ESP8266)
+ADC_MODE(ADC_VCC);
+#endif
+#include "AmsToMqttBridge.h"
#include
#include
-#if HAS_DALLAS_TEMP_SENSOR
-#include
-#include
-#endif
-
-#if defined(ESP8266)
-#include
-#elif defined(ESP32)
-#include
-#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;
diff --git a/src/web/AmsWebServer.cpp b/src/web/AmsWebServer.cpp
index e83fbebb..06fa5546 100644
--- a/src/web/AmsWebServer.cpp
+++ b/src/web/AmsWebServer.cpp
@@ -44,13 +44,21 @@ void AmsWebServer::loop() {
void AmsWebServer::setJson(StaticJsonDocument<500> json) {
if(!json.isNull()) {
p = json["data"]["P"].as();
+
if(json["data"].containsKey("U1")) {
u1 = json["data"]["U1"].as();
- u2 = json["data"]["U2"].as();
- u3 = json["data"]["U3"].as();
i1 = json["data"]["I1"].as();
- i2 = json["data"]["I2"].as();
- i3 = json["data"]["I3"].as();
+
+ if(json["data"].containsKey("U2")) {
+ u2 = json["data"]["U2"].as();
+ i2 = json["data"]["I2"].as();
+
+ if(json["data"].containsKey("U3")) {
+ u3 = json["data"]["U3"].as();
+ i3 = json["data"]["I3"].as();
+ }
+ }
+
if(maxPwr == 0 && config->hasConfig() && config->fuseSize > 0 && config->distSys > 0) {
int volt = config->distSys == 2 ? 400 : 230;
diff --git a/web/boot.css b/web/boot.css
index c3239894..5b9b1906 100644
--- a/web/boot.css
+++ b/web/boot.css
@@ -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;
-}
diff --git a/web/configuration.html b/web/configuration.html
index f89f10cd..d0faab58 100644
--- a/web/configuration.html
+++ b/web/configuration.html
@@ -5,7 +5,7 @@
AMS reader - configuration
-
+