mirror of
https://github.com/UtilitechAS/amsreader-firmware.git
synced 2026-01-18 17:26:46 +00:00
Some changes after testing
This commit is contained in:
parent
f425abb52d
commit
ab101c8622
@ -5,12 +5,14 @@
|
||||
#include <Timezone.h>
|
||||
|
||||
enum AmsType {
|
||||
AmsTypeAutodetect = 0x00,
|
||||
AmsTypeAidon = 0x01,
|
||||
AmsTypeKaifa = 0x02,
|
||||
AmsTypeKamstrup = 0x03,
|
||||
AmsTypeIskra = 0x08,
|
||||
AmsTypeLandis = 0x09,
|
||||
AmsTypeSagemcom = 0x0A,
|
||||
AmsTypeCustom = 0x88,
|
||||
AmsTypeUnknown = 0xFF
|
||||
};
|
||||
|
||||
|
||||
@ -689,6 +689,9 @@ void readHanPort() {
|
||||
}
|
||||
return;
|
||||
}
|
||||
for(int i = len; i<BUF_SIZE; i++) {
|
||||
buf[i] = 0x00;
|
||||
}
|
||||
if(pos == HDLC_ENCRYPTION_CONFIG_MISSING) {
|
||||
hc = new HDLCConfig();
|
||||
memcpy(hc->encryption_key, meterConfig.encryptionKey, 16);
|
||||
|
||||
@ -271,9 +271,8 @@ IEC6205675::IEC6205675(const char* d, uint8_t useMeterType, CosemDateTime packag
|
||||
AmsOctetTimestamp* amst = (AmsOctetTimestamp*) meterTs;
|
||||
time_t ts = getTimestamp(amst->dt);
|
||||
if(meterType == AmsTypeKamstrup || meterType == AmsTypeAidon) {
|
||||
this->packageTimestamp = tz.toUTC(ts);
|
||||
this->packageTimestamp = this->packageTimestamp > 0 ? tz.toUTC(this->packageTimestamp) : 0;
|
||||
this->meterTimestamp = tz.toUTC(ts);
|
||||
Serial.printf("\nKamstrup/Aidon time: %d\n", meterTimestamp);
|
||||
} else {
|
||||
meterTimestamp = ts;
|
||||
}
|
||||
@ -457,7 +456,7 @@ time_t IEC6205675::getTimestamp(CosemDateTime timestamp) {
|
||||
tm.Minute = timestamp.minute;
|
||||
tm.Second = timestamp.second;
|
||||
|
||||
Serial.printf("\nY: %d, M: %d, D: %d, h: %d, m: %d, s: %d, deviation: 0x%2X, status: 0x%1X\n", tm.Year, tm.Month, tm.Day, tm.Hour, tm.Minute, tm.Second, timestamp.deviation, timestamp.status);
|
||||
//Serial.printf("\nY: %d, M: %d, D: %d, h: %d, m: %d, s: %d, deviation: 0x%2X, status: 0x%1X\n", tm.Year, tm.Month, tm.Day, tm.Hour, tm.Minute, tm.Second, timestamp.deviation, timestamp.status);
|
||||
|
||||
time_t time = makeTime(tm);
|
||||
int16_t deviation = ntohs(timestamp.deviation);
|
||||
|
||||
@ -23,17 +23,17 @@ int HDLC_validate(const uint8_t* d, int length, HDLCConfig* config, CosemDateTim
|
||||
// Length field (11 lsb of format)
|
||||
int len = (ntohs(h->format) & 0x7FF) + 2;
|
||||
if(len > length)
|
||||
return -4;
|
||||
return HDLC_FRAME_INCOMPLETE;
|
||||
|
||||
HDLCFooter* f = (HDLCFooter*) (d + len - sizeof *f);
|
||||
|
||||
// First and last byte should be MBUS_HAN_TAG
|
||||
if(h->flag != HDLC_FLAG || f->flag != HDLC_FLAG)
|
||||
return -1;
|
||||
return HDLC_BOUNDRY_FLAG_MISSING;
|
||||
|
||||
// Verify FCS
|
||||
if(ntohs(f->fcs) != crc16_x25(d + 1, len - sizeof *f - 1))
|
||||
return -2;
|
||||
return HDLC_FCS_ERROR;
|
||||
|
||||
int headersize = 8;
|
||||
int footersize = 3;
|
||||
@ -60,7 +60,7 @@ int HDLC_validate(const uint8_t* d, int length, HDLCConfig* config, CosemDateTim
|
||||
|
||||
// Verify HCS
|
||||
if(ntohs(t3->hcs) != crc16_x25(d + 1, ptr-d))
|
||||
return -3;
|
||||
return HDLC_HCS_ERROR;
|
||||
|
||||
ptr += sizeof *t3;
|
||||
}
|
||||
@ -138,7 +138,28 @@ int HDLC_validate(const uint8_t* d, int length, HDLCConfig* config, CosemDateTim
|
||||
}
|
||||
mbedtls_gcm_free(&m_ctx);
|
||||
#endif
|
||||
ptr += 36; // TODO: Come to this number in a proper way...
|
||||
|
||||
ptr += 23; // TODO: Come to this number in a proper way...
|
||||
|
||||
// ADPU timestamp
|
||||
CosemData* dateTime = (CosemData*) ptr;
|
||||
if(dateTime->base.type == CosemTypeOctetString) {
|
||||
if(dateTime->base.length == 0x0C) {
|
||||
memcpy(timestamp, ptr+1, dateTime->base.length);
|
||||
}
|
||||
ptr += 2 + dateTime->base.length;
|
||||
} else if(dateTime->base.type == CosemTypeNull) {
|
||||
timestamp = 0;
|
||||
ptr++;
|
||||
} else if(dateTime->base.type == CosemTypeDateTime) {
|
||||
memcpy(timestamp, ptr, dateTime->base.length);
|
||||
} else if(dateTime->base.type == 0x0C) { // Kamstrup bug...
|
||||
memcpy(timestamp, ptr, 0x0C);
|
||||
ptr += 13;
|
||||
} else {
|
||||
return -99;
|
||||
}
|
||||
|
||||
return ptr-d;
|
||||
}
|
||||
|
||||
|
||||
@ -6,6 +6,8 @@
|
||||
|
||||
#define HDLC_FLAG 0x7E
|
||||
#define HDLC_BOUNDRY_FLAG_MISSING -1
|
||||
#define HDLC_FCS_ERROR -2
|
||||
#define HDLC_HCS_ERROR -3
|
||||
#define HDLC_FRAME_INCOMPLETE -4
|
||||
#define HDLC_ENCRYPTION_CONFIG_MISSING -90
|
||||
|
||||
|
||||
@ -349,6 +349,8 @@ void AmsWebServer::indexHtml() {
|
||||
|
||||
html.replace("{P}", String(meterState->getActiveImportPower()));
|
||||
html.replace("{PO}", String(meterState->getActiveExportPower()));
|
||||
html.replace("{Q}", String(meterState->getReactiveImportPower()));
|
||||
html.replace("{QO}", String(meterState->getReactiveExportPower()));
|
||||
html.replace("{de}", meterConfig->productionCapacity > 0 ? "" : "none");
|
||||
html.replace("{dn}", meterConfig->productionCapacity > 0 ? "none" : "");
|
||||
html.replace("{ti}", meterConfig->productionCapacity > 0 ? "Import" : "Use");
|
||||
|
||||
@ -6,11 +6,17 @@ var ep;
|
||||
var ea;
|
||||
var eo = {
|
||||
title: 'Last 24 hours',
|
||||
curveType: 'function',
|
||||
titleTextStyle: {
|
||||
fontSize: 14
|
||||
},
|
||||
bar: { groupWidth: '90%' },
|
||||
legend: { position: 'none' },
|
||||
vAxis: {
|
||||
title: 'kWh',
|
||||
viewWindowMode: 'maximized'
|
||||
}
|
||||
},
|
||||
tooltip: { trigger: 'none'},
|
||||
enableInteractivity: false,
|
||||
};
|
||||
|
||||
// Month plot
|
||||
@ -18,11 +24,17 @@ var mp;
|
||||
var ma;
|
||||
var mo = {
|
||||
title: 'Last month',
|
||||
curveType: 'function',
|
||||
titleTextStyle: {
|
||||
fontSize: 14
|
||||
},
|
||||
bar: { groupWidth: '90%' },
|
||||
legend: { position: 'none' },
|
||||
vAxis: {
|
||||
title: 'kWh',
|
||||
viewWindowMode: 'maximized'
|
||||
}
|
||||
},
|
||||
tooltip: { trigger: 'none'},
|
||||
enableInteractivity: false,
|
||||
};
|
||||
|
||||
// Voltage plot
|
||||
@ -328,8 +340,8 @@ var zeropad = function(num) {
|
||||
}
|
||||
|
||||
var setupChart = function() {
|
||||
ep = new google.visualization.LineChart(document.getElementById('ep'));
|
||||
mp = new google.visualization.LineChart(document.getElementById('mp'));
|
||||
ep = new google.visualization.ColumnChart(document.getElementById('ep'));
|
||||
mp = new google.visualization.ColumnChart(document.getElementById('mp'));
|
||||
vp = new google.visualization.ColumnChart(document.getElementById('vp'));
|
||||
ap = new google.visualization.ColumnChart(document.getElementById('ap'));
|
||||
ip = new google.visualization.PieChart(document.getElementById('ip'));
|
||||
@ -353,19 +365,19 @@ var drawEnergy = function() {
|
||||
timeout: 30000,
|
||||
dataType: 'json',
|
||||
}).done(function(json) {
|
||||
data = [['Hour','Value']];
|
||||
data = [['Hour','kWh', { role: 'style' }, { role: 'annotation' }]];
|
||||
var r = 1;
|
||||
var hour = moment.utc().hours();
|
||||
var offset = moment().utcOffset()/60;
|
||||
var min = 0;
|
||||
for(var i = hour; i<24; i++) {
|
||||
var val = json["h"+zeropad(i)];
|
||||
data[r++] = [zeropad((i+offset)%24), val];
|
||||
data[r++] = [zeropad((i+offset)%24), val, "color: #6f42c1;opacity: 0.9;", val.toFixed(1)];
|
||||
Math.min(0, val);
|
||||
};
|
||||
for(var i = 0; i < hour; i++) {
|
||||
var val = json["h"+zeropad(i)];
|
||||
data[r++] = [zeropad((i+offset)%24), val];
|
||||
data[r++] = [zeropad((i+offset)%24), val, "color: #6f42c1;opacity: 0.9;", val.toFixed(1)];
|
||||
Math.min(0, val);
|
||||
};
|
||||
ea = google.visualization.arrayToDataTable(data);
|
||||
@ -378,19 +390,19 @@ var drawEnergy = function() {
|
||||
timeout: 30000,
|
||||
dataType: 'json',
|
||||
}).done(function(json) {
|
||||
data = [['Day','Value']];
|
||||
data = [['Day','kWh', { role: 'style' }, { role: 'annotation' }]];
|
||||
var r = 1;
|
||||
var day = moment().date();
|
||||
var start = moment().subtract(1, 'months').endOf('month').date();
|
||||
var min = 0;
|
||||
for(var i = day; i<=start; i++) {
|
||||
var val = json["d"+zeropad(i)];
|
||||
data[r++] = [zeropad((i)), val];
|
||||
data[r++] = [zeropad((i)), val, "color: #6f42c1;opacity: 0.9;", val.toFixed(0)];
|
||||
Math.min(0, val);
|
||||
}
|
||||
for(var i = 1; i < day; i++) {
|
||||
var val = json["d"+zeropad(i)];
|
||||
data[r++] = [zeropad((i)), val];
|
||||
data[r++] = [zeropad((i)), val, "color: #6f42c1;opacity: 0.9;", val.toFixed(0)];
|
||||
Math.min(0, val);
|
||||
}
|
||||
ma = google.visualization.arrayToDataTable(data);
|
||||
@ -535,21 +547,21 @@ var fetch = function() {
|
||||
t += u1;
|
||||
c++;
|
||||
var pct = (Math.max(parseFloat(json.u1)-195.5, 1)*100/69);
|
||||
arr[r++] = ['L1', u1, voltcol(pct), u1 + "V"];
|
||||
arr[r++] = ['L1', u1, "color: " + voltcol(pct) + ";opacity: 0.9;", u1 + "V"];
|
||||
}
|
||||
if(json.u2) {
|
||||
var u2 = parseFloat(json.u2);
|
||||
t += u2;
|
||||
c++;
|
||||
var pct = (Math.max(parseFloat(json.u2)-195.5, 1)*100/69);
|
||||
arr[r++] = ['L2', u2, voltcol(pct), u2 + "V"];
|
||||
arr[r++] = ['L2', u2, "color: " + voltcol(pct) + ";opacity: 0.9;", u2 + "V"];
|
||||
}
|
||||
if(json.u3) {
|
||||
var u3 = parseFloat(json.u3);
|
||||
t += u3;
|
||||
c++;
|
||||
var pct = (Math.max(parseFloat(json.u3)-195.5, 1)*100/69);
|
||||
arr[r++] = ['L3', u3, voltcol(pct), u3 + "V"];
|
||||
arr[r++] = ['L3', u3, "color: " + voltcol(pct) + ";opacity: 0.9;", u3 + "V"];
|
||||
}
|
||||
v = t/c;
|
||||
if(v > 0) {
|
||||
@ -566,19 +578,19 @@ var fetch = function() {
|
||||
var i1 = parseFloat(json.i1);
|
||||
a = Math.max(a, i1);
|
||||
var pct = (parseFloat(json.i1)/parseInt(json.mf))*100;
|
||||
arr[r++] = ['L1', pct, ampcol(pct), i1 + "A"];
|
||||
arr[r++] = ['L1', pct, "color: " + ampcol(pct) + ";opacity: 0.9;", i1 + "A"];
|
||||
}
|
||||
if(json.i2) {
|
||||
var i2 = parseFloat(json.i2);
|
||||
a = Math.max(a, i2);
|
||||
var pct = (parseFloat(json.i2)/parseInt(json.mf))*100;
|
||||
arr[r++] = ['L2', pct, ampcol(pct), i2 + "A"];
|
||||
arr[r++] = ['L2', pct, "color: " + ampcol(pct) + ";opacity: 0.9;", i2 + "A"];
|
||||
}
|
||||
if(json.i3) {
|
||||
var i3 = parseFloat(json.i3);
|
||||
a = Math.max(a, i3);
|
||||
var pct = (parseFloat(json.i3)/parseInt(json.mf))*100;
|
||||
arr[r++] = ['L3', pct, ampcol(pct), i3 + "A"];
|
||||
arr[r++] = ['L3', pct, "color: " + ampcol(pct) + ";opacity: 0.9;", i3 + "A"];
|
||||
}
|
||||
if(a > 0) {
|
||||
aa = google.visualization.arrayToDataTable(arr);
|
||||
|
||||
@ -56,7 +56,15 @@
|
||||
<div class="col-sm-6 mb-3" style="display: {dn};">
|
||||
<div class="bg-white rounded shadow p-3" style="display: {da};">
|
||||
<h5 class="text-center">Reactive</h5>
|
||||
<div class="row rri">
|
||||
<div class="col-12 font-weight-bold">Instant</div>
|
||||
<div class="col-4">In</div>
|
||||
<div class="col-8 text-right"><span class="jri">{Q}</span> var</div>
|
||||
<div class="col-4">Out</div>
|
||||
<div class="col-8 text-right"><span class="jre">{QO}</span> var</div>
|
||||
</div>
|
||||
<div class="row rric">
|
||||
<div class="col-12 font-weight-bold">Total</div>
|
||||
<div class="col-4">In</div>
|
||||
<div class="col-8 text-right"><span class="jric">{tQI}</span> kvarh</div>
|
||||
<div class="col-4">Out</div>
|
||||
@ -64,29 +72,45 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-12 mb-3" style="display: {de};">
|
||||
<div class="col-12 mb-3" style="display: {de};">
|
||||
<div class="bg-white rounded shadow p-3" style="display: {da};">
|
||||
<div class="row rrec">
|
||||
<div class="col-4 col-sm-2">In</div>
|
||||
<div class="col-8 col-sm-4 text-right"><span class="jric">{tQI}</span> kvarh</div>
|
||||
<div class="col-4 col-sm-2">Out</div>
|
||||
<div class="col-8 col-sm-4 text-right"><span class="jrec">{tQO}</span> kvarh</div>
|
||||
<div class="col-sm-4 font-weight-bold">Instant reactive</div>
|
||||
<div class="col-4 col-sm-1">In</div>
|
||||
<div class="col-8 col-sm-3 text-right"><span class="jric">{tQI}</span> kvarh</div>
|
||||
<div class="col-4 col-sm-1">Out</div>
|
||||
<div class="col-8 col-sm-3 text-right"><span class="jrec">{tQO}</span> kvarh</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-3 col-sm-6 mb-3">
|
||||
<div class="bg-white rounded shadow p-3">
|
||||
<div class="text-center">
|
||||
<div id="vp" class="plot2"></div>
|
||||
<div class="col-lg-6">
|
||||
<div class="row">
|
||||
<div class="col-sm-6 mb-3">
|
||||
<div class="bg-white rounded shadow p-3">
|
||||
<div class="text-center">
|
||||
<div id="vp" class="plot2"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-3 col-sm-6 mb-3">
|
||||
<div class="bg-white rounded shadow p-3">
|
||||
<div class="text-center">
|
||||
<div id="ap" class="plot2"></div>
|
||||
<div class="col-sm-6 mb-3">
|
||||
<div class="bg-white rounded shadow p-3">
|
||||
<div class="text-center">
|
||||
<div id="ap" class="plot2"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 mb-3" style="display: {de};">
|
||||
<div class="bg-white rounded shadow p-3" style="display: {da};">
|
||||
<div class="row rrec">
|
||||
<div class="col-sm-4 font-weight-bold">Total reactive</div>
|
||||
<div class="col-4 col-sm-1">In</div>
|
||||
<div class="col-8 col-sm-3 text-right"><span class="jric">{tQI}</span> kvarh</div>
|
||||
<div class="col-4 col-sm-1">Out</div>
|
||||
<div class="col-8 col-sm-3 text-right"><span class="jrec">{tQO}</span> kvarh</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user