mirror of
https://github.com/UtilitechAS/amsreader-firmware.git
synced 2026-04-05 13:55:01 +00:00
Compare commits
18 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
889b9153fa | ||
|
|
7b52efd332 | ||
|
|
c936f605d6 | ||
|
|
9d0ceb9ca8 | ||
|
|
b33273e3cc | ||
|
|
ab016fff93 | ||
|
|
a215aa7766 | ||
|
|
30d73c3a6e | ||
|
|
bd905c3595 | ||
|
|
1a2e70b1fb | ||
|
|
d6da7b2715 | ||
|
|
059a430f9a | ||
|
|
8ade50c2a6 | ||
|
|
5b94d8ff61 | ||
|
|
232b9c279d | ||
|
|
9b6a6af6ec | ||
|
|
9671e1eba3 | ||
|
|
2ddfc16d6a |
13
.github/workflows/release.yml
vendored
13
.github/workflows/release.yml
vendored
@@ -19,6 +19,7 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
GITHUB_REF: ${{ github.ref }}
|
GITHUB_REF: ${{ github.ref }}
|
||||||
run: echo ::set-output name=tag::$(echo ${GITHUB_REF:11})
|
run: echo ::set-output name=tag::$(echo ${GITHUB_REF:11})
|
||||||
|
run: echo ::set-env name=GITHUB_TAG::$(echo ${GITHUB_REF##*/})
|
||||||
- name: Cache Python dependencies
|
- name: Cache Python dependencies
|
||||||
uses: actions/cache@v1
|
uses: actions/cache@v1
|
||||||
with:
|
with:
|
||||||
@@ -52,7 +53,7 @@ jobs:
|
|||||||
draft: false
|
draft: false
|
||||||
prerelease: false
|
prerelease: false
|
||||||
- name: Upload hw1esp12e binary to release
|
- name: Upload hw1esp12e binary to release
|
||||||
uses: actions/upload-release-asset@v1.0.1
|
uses: actions/upload-release-asset@v1
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
with:
|
with:
|
||||||
@@ -61,7 +62,7 @@ jobs:
|
|||||||
asset_name: ams2mqtt-hw1esp12e-${{ steps.release_tag.outputs.tag }}.bin
|
asset_name: ams2mqtt-hw1esp12e-${{ steps.release_tag.outputs.tag }}.bin
|
||||||
asset_content_type: application/octet-stream
|
asset_content_type: application/octet-stream
|
||||||
- name: Upload esp12e binary to release
|
- name: Upload esp12e binary to release
|
||||||
uses: actions/upload-release-asset@v1.0.1
|
uses: actions/upload-release-asset@v1
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
with:
|
with:
|
||||||
@@ -70,7 +71,7 @@ jobs:
|
|||||||
asset_name: ams2mqtt-esp12e-${{ steps.release_tag.outputs.tag }}.bin
|
asset_name: ams2mqtt-esp12e-${{ steps.release_tag.outputs.tag }}.bin
|
||||||
asset_content_type: application/octet-stream
|
asset_content_type: application/octet-stream
|
||||||
- name: Upload d1mini binary to release
|
- name: Upload d1mini binary to release
|
||||||
uses: actions/upload-release-asset@v1.0.1
|
uses: actions/upload-release-asset@v1
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
with:
|
with:
|
||||||
@@ -79,7 +80,7 @@ jobs:
|
|||||||
asset_name: ams2mqtt-d1mini-${{ steps.release_tag.outputs.tag }}.bin
|
asset_name: ams2mqtt-d1mini-${{ steps.release_tag.outputs.tag }}.bin
|
||||||
asset_content_type: application/octet-stream
|
asset_content_type: application/octet-stream
|
||||||
- name: Upload esp32 binary to release
|
- name: Upload esp32 binary to release
|
||||||
uses: actions/upload-release-asset@v1.0.1
|
uses: actions/upload-release-asset@v1
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
with:
|
with:
|
||||||
@@ -88,7 +89,7 @@ jobs:
|
|||||||
asset_name: ams2mqtt-esp32-${{ steps.release_tag.outputs.tag }}.bin
|
asset_name: ams2mqtt-esp32-${{ steps.release_tag.outputs.tag }}.bin
|
||||||
asset_content_type: application/octet-stream
|
asset_content_type: application/octet-stream
|
||||||
- name: Upload lolind32 binary to release
|
- name: Upload lolind32 binary to release
|
||||||
uses: actions/upload-release-asset@v1.0.1
|
uses: actions/upload-release-asset@v1
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
with:
|
with:
|
||||||
@@ -97,7 +98,7 @@ jobs:
|
|||||||
asset_name: ams2mqtt-lolind32-${{ steps.release_tag.outputs.tag }}.bin
|
asset_name: ams2mqtt-lolind32-${{ steps.release_tag.outputs.tag }}.bin
|
||||||
asset_content_type: application/octet-stream
|
asset_content_type: application/octet-stream
|
||||||
- name: Upload featheresp32 binary to release
|
- name: Upload featheresp32 binary to release
|
||||||
uses: actions/upload-release-asset@v1.0.1
|
uses: actions/upload-release-asset@v1
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
with:
|
with:
|
||||||
|
|||||||
@@ -7,6 +7,9 @@ There is also a web interface available on runtime, showing meter data in real t
|
|||||||
|
|
||||||
<img src="webui.jpg" width="480">
|
<img src="webui.jpg" width="480">
|
||||||
|
|
||||||
|
## Hardware options
|
||||||
|
Look in [hardware section](/hardware) for more details about supported hardware
|
||||||
|
|
||||||
## Release binaries
|
## Release binaries
|
||||||
|
|
||||||
In the [Release section](https://github.com/gskjold/AmsToMqttBridge/releases) of this repository, you will find precompiled binaries for some common boards.
|
In the [Release section](https://github.com/gskjold/AmsToMqttBridge/releases) of this repository, you will find precompiled binaries for some common boards.
|
||||||
|
|||||||
BIN
doc/Aidon-HAN-Interface-Description-v11A-ID-34331.pdf
Normal file
BIN
doc/Aidon-HAN-Interface-Description-v11A-ID-34331.pdf
Normal file
Binary file not shown.
@@ -1,7 +1,7 @@
|
|||||||
import os
|
import os
|
||||||
|
|
||||||
FILENAME_VERSION_H = 'src/version.h'
|
FILENAME_VERSION_H = 'src/version.h'
|
||||||
version = os.environ.get('GITHUB_REF')
|
version = os.environ.get('GITHUB_TAG')
|
||||||
if version == None:
|
if version == None:
|
||||||
version = "SNAPSHOT"
|
version = "SNAPSHOT"
|
||||||
|
|
||||||
|
|||||||
@@ -163,10 +163,12 @@ void AmsData::extractFromAidon(HanReader& hanReader, int listSize) {
|
|||||||
activeExportPower = hanReader.getInt( (int)Aidon_List3PhaseIT::ActiveExportPower);
|
activeExportPower = hanReader.getInt( (int)Aidon_List3PhaseIT::ActiveExportPower);
|
||||||
reactiveExportPower = hanReader.getInt( (int)Aidon_List3PhaseIT::ReactiveExportPower);
|
reactiveExportPower = hanReader.getInt( (int)Aidon_List3PhaseIT::ReactiveExportPower);
|
||||||
l1current = ((double) hanReader.getInt( (int)Aidon_List3PhaseIT::CurrentL1)) / 10;
|
l1current = ((double) hanReader.getInt( (int)Aidon_List3PhaseIT::CurrentL1)) / 10;
|
||||||
|
l2current = 0;
|
||||||
l3current = ((double) hanReader.getInt( (int)Aidon_List3PhaseIT::CurrentL3)) / 10;
|
l3current = ((double) hanReader.getInt( (int)Aidon_List3PhaseIT::CurrentL3)) / 10;
|
||||||
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;
|
||||||
threePhase = true;
|
threePhase = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,15 +48,15 @@ public:
|
|||||||
bool isThreePhase();
|
bool isThreePhase();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
unsigned long lastUpdateMillis;
|
unsigned long lastUpdateMillis = 0;
|
||||||
int listType;
|
int listType = 0;
|
||||||
unsigned long packageTimestamp;
|
unsigned long packageTimestamp = 0;
|
||||||
String listId, meterId, meterType;
|
String listId, meterId, meterType;
|
||||||
unsigned long meterTimestamp;
|
unsigned long meterTimestamp = 0;
|
||||||
int activeImportPower, reactiveImportPower, activeExportPower, reactiveExportPower;
|
int activeImportPower = 0, reactiveImportPower = 0, activeExportPower = 0, reactiveExportPower = 0;
|
||||||
double l1voltage, l2voltage, l3voltage, l1current, l2current, l3current;
|
double l1voltage = 0, l2voltage = 0, l3voltage = 0, l1current = 0, l2current = 0, l3current = 0;
|
||||||
double activeImportCounter, reactiveImportCounter, activeExportCounter, reactiveExportCounter;
|
double activeImportCounter = 0, reactiveImportCounter = 0, activeExportCounter = 0, reactiveExportCounter = 0;
|
||||||
bool threePhase;
|
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);
|
||||||
|
|||||||
@@ -1,10 +1,23 @@
|
|||||||
/*
|
/**
|
||||||
Name: AmsToMqttBridge.ino
|
* @brief ESP8266 based program to receive data from AMS electric meters and send to MQTT
|
||||||
Created: 3/13/2018 7:40:28 PM
|
*
|
||||||
Author: roarf
|
* @details Originally developed by Roar Fredriksen, this program was created to receive data from
|
||||||
*/
|
* AMS electric meters via M-Bus, decode and send to a MQTT broker. The data packet structure
|
||||||
|
* supported by this software is specific to Norwegian meters, but may also support data from
|
||||||
|
* electricity providers in other countries. It was originally based on ESP8266, but have also been
|
||||||
|
* adapted to work with ESP32.
|
||||||
|
*
|
||||||
|
* @author Roar Fredriksen (@roarfred)
|
||||||
|
* The original developer for this project
|
||||||
|
* https://github.com/roarfred/AmsToMqttBridge
|
||||||
|
*
|
||||||
|
* @author Gunnar Skjold (@gskjold)
|
||||||
|
* Maintainer of current code
|
||||||
|
* https://github.com/gskjold/AmsToMqttBridge
|
||||||
|
*/
|
||||||
|
|
||||||
#include "AmsToMqttBridge.h"
|
#include "AmsToMqttBridge.h"
|
||||||
|
#define ARDUINOJSON_POSITIVE_EXPONENTIATION_THRESHOLD 1e9
|
||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
#include <MQTT.h>
|
#include <MQTT.h>
|
||||||
#include <DNSServer.h>
|
#include <DNSServer.h>
|
||||||
@@ -33,7 +46,7 @@ AmsConfiguration config;
|
|||||||
AmsWebServer ws;
|
AmsWebServer ws;
|
||||||
|
|
||||||
WiFiClient *client;
|
WiFiClient *client;
|
||||||
MQTTClient mqtt(384);
|
MQTTClient mqtt(512);
|
||||||
|
|
||||||
Stream* debugger = NULL;
|
Stream* debugger = NULL;
|
||||||
|
|
||||||
@@ -172,24 +185,26 @@ int lastError = 0;
|
|||||||
|
|
||||||
void loop() {
|
void loop() {
|
||||||
unsigned long now = millis();
|
unsigned long now = millis();
|
||||||
if (digitalRead(AP_BUTTON_PIN) == LOW) {
|
if(AP_BUTTON_PIN != INVALID_BUTTON_PIN) {
|
||||||
if (buttonActive == false) {
|
if (digitalRead(AP_BUTTON_PIN) == LOW) {
|
||||||
buttonActive = true;
|
if (buttonActive == false) {
|
||||||
buttonTimer = now;
|
buttonActive = true;
|
||||||
}
|
buttonTimer = now;
|
||||||
|
}
|
||||||
if ((now - buttonTimer > longPressTime) && (longPressActive == false)) {
|
|
||||||
longPressActive = true;
|
if ((now - buttonTimer > longPressTime) && (longPressActive == false)) {
|
||||||
swapWifiMode();
|
longPressActive = true;
|
||||||
}
|
swapWifiMode();
|
||||||
} else {
|
}
|
||||||
if (buttonActive == true) {
|
} else {
|
||||||
if (longPressActive == true) {
|
if (buttonActive == true) {
|
||||||
longPressActive = false;
|
if (longPressActive == true) {
|
||||||
} else {
|
longPressActive = false;
|
||||||
// Single press action
|
} else {
|
||||||
|
// Single press action
|
||||||
|
}
|
||||||
|
buttonActive = false;
|
||||||
}
|
}
|
||||||
buttonActive = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,11 @@ double HwTools::getVcc() {
|
|||||||
#if defined(ARDUINO_ESP8266_WEMOS_D1MINI)
|
#if defined(ARDUINO_ESP8266_WEMOS_D1MINI)
|
||||||
return (((double) ESP.getVcc()) / 900); // This board has a voltage divider on VCC. Yes, 900 is correct
|
return (((double) ESP.getVcc()) / 900); // This board has a voltage divider on VCC. Yes, 900 is correct
|
||||||
#elif defined(ESP8266)
|
#elif defined(ESP8266)
|
||||||
return ((double) ESP.getVcc()) / 1024;
|
#if defined(ESP_VCC_CALIB_FACTOR)
|
||||||
|
return ((double) ESP.getVcc()) / 1024 * ESP_VCC_CALIB_FACTOR;
|
||||||
|
#else
|
||||||
|
return ((double) ESP.getVcc()) / 1024;
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -293,7 +293,7 @@ void AmsWebServer::dataJson() {
|
|||||||
StaticJsonDocument<768> json;
|
StaticJsonDocument<768> json;
|
||||||
|
|
||||||
String jsonStr;
|
String jsonStr;
|
||||||
if(data.getActiveImportPower() > 0) {
|
if(data.getLastUpdateMillis() > 0) {
|
||||||
int maxPwr = this->maxPwr;
|
int maxPwr = this->maxPwr;
|
||||||
if(maxPwr == 0) {
|
if(maxPwr == 0) {
|
||||||
if(data.isThreePhase()) {
|
if(data.isThreePhase()) {
|
||||||
@@ -357,10 +357,10 @@ void AmsWebServer::dataJson() {
|
|||||||
json["meterType"] = config->getMeterType();
|
json["meterType"] = config->getMeterType();
|
||||||
json["currentMillis"] = now;
|
json["currentMillis"] = now;
|
||||||
double vcc = hw.getVcc();
|
double vcc = hw.getVcc();
|
||||||
json["vcc"] = vcc > 0 ? vcc : 0;
|
json["vcc"] = serialized(String(vcc, 3));
|
||||||
|
|
||||||
double temp = hw.getTemperature();
|
double temp = hw.getTemperature();
|
||||||
json["temp"] = temp;
|
json["temp"] = serialized(String(temp, 2));
|
||||||
|
|
||||||
json.createNestedObject("wifi");
|
json.createNestedObject("wifi");
|
||||||
float rssi = WiFi.RSSI();
|
float rssi = WiFi.RSSI();
|
||||||
@@ -383,13 +383,12 @@ void AmsWebServer::dataJson() {
|
|||||||
}
|
}
|
||||||
json["status"]["esp"] = espStatus;
|
json["status"]["esp"] = espStatus;
|
||||||
|
|
||||||
unsigned long lastHan = json.isNull() ? 0 : json["up"].as<unsigned long>();
|
|
||||||
String hanStatus;
|
String hanStatus;
|
||||||
if(config->getMeterType() == 0) {
|
if(config->getMeterType() == 0) {
|
||||||
hanStatus = "secondary";
|
hanStatus = "secondary";
|
||||||
} else if(now - lastHan < 15000) {
|
} else if(now - data.getLastUpdateMillis() < 15000) {
|
||||||
hanStatus = "success";
|
hanStatus = "success";
|
||||||
} else if(now - lastHan < 30000) {
|
} else if(now - data.getLastUpdateMillis() < 30000) {
|
||||||
hanStatus = "warning";
|
hanStatus = "warning";
|
||||||
} else {
|
} else {
|
||||||
hanStatus = "danger";
|
hanStatus = "danger";
|
||||||
@@ -464,8 +463,6 @@ void AmsWebServer::handleSave() {
|
|||||||
config->setMqttSubscribeTopic(server.arg("mqttSubscribeTopic"));
|
config->setMqttSubscribeTopic(server.arg("mqttSubscribeTopic"));
|
||||||
config->setMqttUser(server.arg("mqttUser"));
|
config->setMqttUser(server.arg("mqttUser"));
|
||||||
config->setMqttPassword(server.arg("mqttPassword"));
|
config->setMqttPassword(server.arg("mqttPassword"));
|
||||||
config->setAuthUser(server.arg("authUser"));
|
|
||||||
config->setAuthPassword(server.arg("authPassword"));
|
|
||||||
} else {
|
} else {
|
||||||
config->clearMqtt();
|
config->clearMqtt();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user