Multipliers for HAN data

This commit is contained in:
Gunnar Skjold 2022-03-18 19:16:03 +01:00
parent b9234f6f64
commit 40016f314e
10 changed files with 151 additions and 11 deletions

View File

@ -645,6 +645,14 @@ bool AmsConfiguration::hasConfig() {
configVersion = 0;
return false;
}
case 93:
configVersion = -1; // Prevent loop
if(relocateConfig93()) {
configVersion = 94;
} else {
configVersion = 0;
return false;
}
case EEPROM_CHECK_SUM:
return true;
default:
@ -775,8 +783,6 @@ bool AmsConfiguration::relocateConfig91() {
}
bool AmsConfiguration::relocateConfig92() {
saveToFs();
WiFiConfig wifi;
EEPROM.begin(EEPROM_SIZE);
EEPROM.get(CONFIG_WIFI_START, wifi);
@ -797,6 +803,21 @@ bool AmsConfiguration::relocateConfig92() {
return ret;
}
bool AmsConfiguration::relocateConfig93() {
MeterConfig meter;
EEPROM.begin(EEPROM_SIZE);
EEPROM.get(CONFIG_METER_START_93, meter);
meter.wattageMultiplier = 0;
meter.voltageMultiplier = 0;
meter.amperageMultiplier = 0;
meter.accumulatedMultiplier = 0;
EEPROM.put(CONFIG_METER_START, meter);
EEPROM.put(EEPROM_CONFIG_ADDRESS, 94);
bool ret = EEPROM.commit();
EEPROM.end();
return ret;
}
bool AmsConfiguration::save() {
EEPROM.begin(EEPROM_SIZE);
EEPROM.put(EEPROM_CONFIG_ADDRESS, EEPROM_CHECK_SUM);

View File

@ -4,12 +4,12 @@
#include "Arduino.h"
#define EEPROM_SIZE 1024*3
#define EEPROM_CHECK_SUM 93 // Used to check if config is stored. Change if structure changes
#define EEPROM_CHECK_SUM 94 // Used to check if config is stored. Change if structure changes
#define EEPROM_CONFIG_ADDRESS 0
#define EEPROM_TEMP_CONFIG_ADDRESS 2048
#define CONFIG_SYSTEM_START 8
#define CONFIG_METER_START 224
#define CONFIG_METER_START 32
#define CONFIG_GPIO_START 266
#define CONFIG_ENTSOE_START 290
#define CONFIG_WIFI_START 360
@ -24,6 +24,7 @@
#define CONFIG_METER_START_87 784
#define CONFIG_ENTSOE_START_90 286
#define CONFIG_WIFI_START_91 16
#define CONFIG_METER_START_93 224
struct SystemConfig {
@ -94,7 +95,11 @@ struct MeterConfig {
uint8_t productionCapacity;
uint8_t encryptionKey[16];
uint8_t authenticationKey[16];
}; // 41
uint16_t wattageMultiplier;
uint16_t voltageMultiplier;
uint16_t amperageMultiplier;
uint16_t accumulatedMultiplier;
}; // 49
struct MeterConfig87 {
uint8_t type;
@ -259,6 +264,7 @@ private:
bool relocateConfig90(); // 2.0.0
bool relocateConfig91(); // 2.0.2
bool relocateConfig92(); // 2.0.3
bool relocateConfig93(); // 2.1 beta
void saveToFs();
bool loadFromFs(uint8_t version);

View File

@ -832,7 +832,7 @@ bool readHanPort() {
len = 0;
if(pos > 0) {
debugD("Valid data, start at byte %d", pos);
data = IEC6205675(((char *) (hanBuffer)) + pos, meterState.getMeterType(), meterConfig.distributionSystem, timestamp, hc);
data = IEC6205675(((char *) (hanBuffer)) + pos, meterState.getMeterType(), &meterConfig, timestamp, hc);
} else {
if(Debug.isActive(RemoteDebug::WARNING)) {
switch(pos) {

View File

@ -2,7 +2,7 @@
#include "lwip/def.h"
#include "Timezone.h"
IEC6205675::IEC6205675(const char* d, uint8_t useMeterType, uint8_t distributionSystem, CosemDateTime packageTimestamp, HDLCConfig* hc) {
IEC6205675::IEC6205675(const char* d, uint8_t useMeterType, MeterConfig* meterConfig, CosemDateTime packageTimestamp, HDLCConfig* hc) {
double val;
char str[64];
@ -360,12 +360,35 @@ IEC6205675::IEC6205675(const char* d, uint8_t useMeterType, uint8_t distribution
lastUpdateMillis = millis();
}
if(meterConfig->wattageMultiplier > 0) {
activeImportPower = activeImportPower > 0 ? activeImportPower * (meterConfig->wattageMultiplier / 1000.0) : 0;
activeExportPower = activeExportPower > 0 ? activeExportPower * (meterConfig->wattageMultiplier / 1000.0) : 0;
reactiveImportPower = reactiveImportPower > 0 ? reactiveImportPower * (meterConfig->wattageMultiplier / 1000.0) : 0;
reactiveExportPower = reactiveExportPower > 0 ? reactiveExportPower * (meterConfig->wattageMultiplier / 1000.0) : 0;
}
if(meterConfig->voltageMultiplier > 0) {
l1voltage = l1voltage > 0 ? l1voltage * (meterConfig->voltageMultiplier / 1000.0) : 0;
l2voltage = l2voltage > 0 ? l2voltage * (meterConfig->voltageMultiplier / 1000.0) : 0;
l3voltage = l3voltage > 0 ? l3voltage * (meterConfig->voltageMultiplier / 1000.0) : 0;
}
if(meterConfig->amperageMultiplier > 0) {
l1current = l1current > 0 ? l1current * (meterConfig->amperageMultiplier / 1000.0) : 0;
l2current = l2current > 0 ? l2current * (meterConfig->amperageMultiplier / 1000.0) : 0;
l3current = l3current > 0 ? l3current * (meterConfig->amperageMultiplier / 1000.0) : 0;
}
if(meterConfig->accumulatedMultiplier > 0) {
activeImportCounter = activeImportCounter > 0 ? activeImportCounter * (meterConfig->accumulatedMultiplier / 1000.0) : 0;
activeExportCounter = activeExportCounter > 0 ? activeExportCounter * (meterConfig->accumulatedMultiplier / 1000.0) : 0;
reactiveImportCounter = reactiveImportCounter > 0 ? reactiveImportCounter * (meterConfig->accumulatedMultiplier / 1000.0) : 0;
reactiveExportCounter = reactiveExportCounter > 0 ? reactiveExportCounter * (meterConfig->accumulatedMultiplier / 1000.0) : 0;
}
threePhase = l1voltage > 0 && l2voltage > 0 && l3voltage > 0;
if(!threePhase)
twoPhase = (l1voltage > 0 && l2voltage > 0) || (l2voltage > 0 && l3voltage > 0) || (l3voltage > 0 && l1voltage > 0);
// Special case for Norwegian IT/TT meters that does not report all values
if(distributionSystem == 1) {
if(meterConfig->distributionSystem == 1) {
if(threePhase) {
if(l2current == 0.0 && l1current > 0.0 && l3current > 0.0) {
l2current = (((activeImportPower - activeExportPower) * sqrt(3)) - (l1voltage * l1current) - (l3voltage * l3current)) / l2voltage;

View File

@ -3,6 +3,7 @@
#include "AmsData.h"
#include "ams/hdlc.h"
#include "AmsConfiguration.h"
#define NOVALUE 0xFFFFFFFF
@ -13,7 +14,7 @@ struct AmsOctetTimestamp {
class IEC6205675 : public AmsData {
public:
IEC6205675(const char* payload, uint8_t useMeterType, uint8_t distributionSystem, CosemDateTime packageTimestamp, HDLCConfig* hc);
IEC6205675(const char* payload, uint8_t useMeterType, MeterConfig* meterConfig, CosemDateTime packageTimestamp, HDLCConfig* hc);
private:
CosemData* getCosemDataAt(uint8_t index, const char* ptr);

View File

@ -49,6 +49,7 @@
#include "root/energyprice_json.h"
#include "root/thresholds_html.h"
#include "root/configfile_html.h"
#include "root/meteradvanced_html.h"
#include "base64.h"
@ -75,6 +76,7 @@ void AmsWebServer::setup(AmsConfiguration* config, GpioConfig* gpioConfig, Meter
server.on("/temperature", HTTP_POST, std::bind(&AmsWebServer::temperaturePost, this));
server.on("/temperature.json", HTTP_GET, std::bind(&AmsWebServer::temperatureJson, this));
server.on("/meter", HTTP_GET, std::bind(&AmsWebServer::configMeterHtml, this));
server.on("/meteradvanced", HTTP_GET, std::bind(&AmsWebServer::configMeterAdvancedHtml, this));
server.on("/wifi", HTTP_GET, std::bind(&AmsWebServer::configWifiHtml, this));
server.on("/mqtt", HTTP_GET, std::bind(&AmsWebServer::configMqttHtml, this));
server.on("/web", HTTP_GET, std::bind(&AmsWebServer::configWebHtml, this));
@ -388,6 +390,29 @@ void AmsWebServer::configMeterHtml() {
server.sendContent_P(FOOT_HTML);
}
void AmsWebServer::configMeterAdvancedHtml() {
printD("Serving /meteradvanced.html over http...");
if(!checkSecurity(1))
return;
snprintf_P(buf, BufferSize, METERADVANCED_HTML,
meterConfig->wattageMultiplier / 1000.0,
meterConfig->voltageMultiplier / 1000.0,
meterConfig->amperageMultiplier / 1000.0,
meterConfig->accumulatedMultiplier / 1000.0
);
server.sendHeader(HEADER_CACHE_CONTROL, CACHE_CONTROL_NO_CACHE);
server.sendHeader(HEADER_PRAGMA, PRAGMA_NO_CACHE);
server.sendHeader(HEADER_EXPIRES, EXPIRES_OFF);
server.setContentLength(strlen(buf) + HEAD_HTML_LEN + FOOT_HTML_LEN);
server.send_P(200, MIME_HTML, HEAD_HTML);
server.sendContent(buf);
server.sendContent_P(FOOT_HTML);
}
void AmsWebServer::configWifiHtml() {
printD("Serving /wifi.html over http...");
@ -1134,6 +1159,7 @@ void AmsWebServer::handleSave() {
if(server.hasArg("mc") && server.arg("mc") == "true") {
printD("Received meter config");
config->getMeterConfig(*meterConfig);
meterConfig->baud = server.arg("b").toInt();
meterConfig->parity = server.arg("c").toInt();
meterConfig->invert = server.hasArg("i") && server.arg("i") == "true";
@ -1156,6 +1182,16 @@ void AmsWebServer::handleSave() {
config->setMeterConfig(*meterConfig);
}
if(server.hasArg("ma") && server.arg("ma") == "true") {
printD("Received meter advanced config");
config->getMeterConfig(*meterConfig);
meterConfig->wattageMultiplier = server.arg("wm").toDouble() * 1000;
meterConfig->voltageMultiplier = server.arg("vm").toDouble() * 1000;
meterConfig->amperageMultiplier = server.arg("am").toDouble() * 1000;
meterConfig->accumulatedMultiplier = server.arg("cm").toDouble() * 1000;
config->setMeterConfig(*meterConfig);
}
if(server.hasArg("wc") && server.arg("wc") == "true") {
printD("Received WiFi config");
WiFiConfig wifi;

View File

@ -76,6 +76,7 @@ private:
void temperaturePost();
void temperatureJson();
void configMeterHtml();
void configMeterAdvancedHtml();
void configWifiHtml();
void configMqttHtml();
void configWebHtml();

View File

@ -39,7 +39,7 @@
<hr/>
<div class="row form-group">
<div class="col-6">
<a href="/" class="btn btn-outline-secondary">Back</a>
<a href="/mqtt" class="btn btn-outline-secondary">Back</a>
</div>
<div class="col-6 text-right">
<button class="btn btn-primary">Save</button>

View File

@ -115,9 +115,12 @@
</div>
</div>
<div class="row mt-3">
<div class="col-12">
<div class="col-sm-6">
<a href="/thresholds">Configure tariff thresholds</a>
</div>
<div class="col-sm-6 text-right">
<a href="/meteradvanced">Multipliers</a>
</div>
</div>
</div>
<hr/>

49
web/meteradvanced.html Normal file
View File

@ -0,0 +1,49 @@
<form method="post" action="/save">
<input type="hidden" name="ma" value="true"/>
<div class="my-3 p-3 bg-white rounded shadow">
<h6>Multipliers</h6>
<div class="row">
<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">Instant</span>
</div>
<input type="number" class="form-control text-right" name="wm" value="%.2f" min="0.00" max="655.35" step="0.01"/>
</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">Voltage</span>
</div>
<input type="number" class="form-control text-right" name="vm" value="%.2f" min="0.00" max="655.35" step="0.01"/>
</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">Amperage</span>
</div>
<input type="number" class="form-control text-right" name="am" value="%.2f" min="0.00" max="655.35" step="0.01"/>
</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">Accumulated</span>
</div>
<input type="number" class="form-control text-right" name="cm" value="%.2f" min="0.00" max="655.35" step="0.01"/>
</div>
</div>
</div>
</div>
<hr/>
<div class="row form-group">
<div class="col-6">
<a href="/meter" class="btn btn-outline-secondary">Back</a>
</div>
<div class="col-6 text-right">
<button class="btn btn-primary">Save</button>
</div>
</div>
</form>