-
-
Save fasmide/96592c5cc690cd06c831 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
local units = ["", "Wh", "kWh", "MWh", "GWh", "j", "kj", "Mj", | |
"Gj", "Cal", "kCal", "Mcal", "Gcal", "varh", | |
"kvarh", "Mvarh", "Gvarh", "VAh", "kVAh", | |
"MVAh", "GVAh", "kW", "kW", "MW", "GW", | |
"kvar", "kvar", "Mvar", "Gvar", "VA", "kVA", | |
"MVA", "GVA", "V", "A", "kV", "kA", "C", | |
"K", "l", "m3", "l/h", "m3/h", "m3xC", | |
"ton", "ton/h", "h", "hh:mm:ss", "yy:mm:dd", | |
"yyyy:mm:dd", "mm:dd", "", "bar", "RTC", | |
"ASCII", "m3 x 10", "ton x 10", "GJ x 10", | |
"minutes", "Bitfield", "s", "ms", "days", | |
"RTC-Q", "Datetime" | |
] | |
local thingsToReceive = [ | |
{ | |
var = 0x000d, | |
name = "Energy in hi-res" | |
}, | |
{ | |
var = 0x041e, | |
name = "Voltage p1" | |
}, | |
{ | |
var = 0x041f, | |
name = "Voltage p2" | |
}, | |
{ | |
var = 0x0434, | |
name = "Current p1" | |
}, | |
{ | |
var = 0x0435, | |
name = "Current p2" | |
}, | |
{ | |
var = 0x0438, | |
name = "Power p1" | |
}, | |
{ | |
var = 0x0439, | |
name = "Power p2" | |
} | |
]; | |
function isEscape(x) { | |
if(x == 0x06) { | |
return true; | |
} | |
if(x == 0x0d) { | |
return true; | |
} | |
if(x == 0x1b) { | |
return true; | |
} | |
if(x == 0x40) { | |
return true; | |
} | |
if(x == 0x80) { | |
return true; | |
} | |
return false; | |
} | |
function crc_1021(message) { | |
local poly = 0x1021; | |
local reg = 0x0000; | |
foreach(byte in message) { | |
local mask = 0x80; | |
while(mask > 0) { | |
//server.log(format("mask: %d",mask)); | |
reg = reg << 1; | |
if(byte & mask) { | |
reg = reg | 1; | |
} | |
mask = mask >> 1 | |
if(reg & 0x10000) { | |
reg = reg & 0xffff; | |
reg = reg ^ poly; | |
} | |
} | |
} | |
return reg; | |
} | |
function sendToKamstrup(pfx, msg) { | |
local b = msg; | |
b.append(0) | |
b.append(0) | |
local c = crc_1021(b) | |
b[b.len()-2] = c >> 8; | |
b[b.len()-1] = c & 0xff; | |
c = []; | |
c.append(pfx) | |
foreach(i in b) { | |
if(isEscape(i)) { | |
c.append(0x1b) | |
c.append(i ^ 0xff) | |
} else { | |
c.append(i); | |
} | |
} | |
c.append(0x0d); | |
foreach(send in c) { | |
hardware.uart57.write(send); | |
//server.log(send); | |
} | |
} | |
function recvKam() { | |
hardware.uart57.flush(); | |
local b = []; | |
local readErrors = 0; | |
while(true) { | |
local d = hardware.uart57.read(); | |
if(d == -1) { | |
readErrors++; | |
if(readErrors > 10) { | |
return null; | |
} | |
imp.sleep(0.02); | |
continue; | |
} | |
if(d == 0x40) { | |
b = []; | |
} | |
//server.log(format("in: %d", d)); | |
b.append(d); | |
if(d == 0x0d) { | |
break; | |
} | |
} | |
local c = []; | |
local i = 1; | |
while(i < b.len() - 1) { | |
if(b[i] == 0x1b) { | |
local v = b[i + 1] ^ 0xff; | |
if(!isEscape(v)) { | |
server.log(format("Missing Escape %02x" % v)); | |
} | |
c.append(v); | |
i += 2; | |
} else { | |
c.append(b[i]); | |
i += 1; | |
} | |
} | |
if(crc_1021(c)) { | |
server.log("CRC error"); | |
} | |
return c; | |
} | |
function readvar(var) { | |
sendToKamstrup(0x80,[0x3f, 0x10, 0x01, (var >> 8), (var & 0xff)]); | |
local b = recvKam(); | |
if(b == null) { | |
return {value = "TO", unit = "NA"}; | |
} | |
if(b[0] != 0x3f || b[1] != 0x10) { | |
return {value = "NA", unit = "NA"}; | |
} | |
if(b[2] != (var >> 8) || b[3] != (var & 0xff)) { | |
return {value = "NA", unit = "NA"}; | |
} | |
local u = "None"; | |
if(units[b[4]]) { | |
u = units[b[4]] | |
} | |
//Decode the mantissa | |
local x = 0 | |
for (local i = 0; i < b[5]; i++) { | |
x = x << 8; | |
x = x | b[i + 7]; | |
} | |
// Decode the exponent | |
local i = b[6] & 0x3f; | |
if(b[6] & 0x40) { | |
i = -i; | |
} | |
i = math.pow(10,i); | |
if(b[6] & 0x80) { | |
i = -i | |
} | |
x *= i | |
//return format("%g %s", x, u); | |
return {value = format("%g", x), unit = u}; | |
} | |
function readEverything() { | |
nv.data = nv.data + format("%d,", time()); | |
foreach(x in thingsToReceive) { | |
local response = readvar(x.var); | |
nv.data = nv.data + format("%s,", response.value); | |
imp.sleep(0.1) //give kamstrup time to recover.. | |
} | |
nv.data = nv.data + "\n"; | |
} | |
// configure a pin pair for UART TX/RX | |
hardware.uart57.configure(9600, 8, PARITY_NONE, 1, NO_CTSRTS); | |
t <- time(); | |
function hourly() { | |
if(nv.data != "") { | |
local output = OutputPort("data", "string"); | |
imp.configure("Kamstrup", [], [output]); | |
server.log("Sending data..."); | |
local responseCode = output.set(nv.data); | |
if(responseCode != 0) { | |
if(responseCode == SEND_ERROR_NOT_CONNECTED) { | |
server.log("Send error not connected"); | |
} | |
if(responseCode == SEND_ERROR_TIMEOUT) { | |
server.log("Send error timeout"); | |
} | |
if(responseCode == SEND_ERROR_DISCONNECTED) { | |
server.log("The connection was disconnected before all data was sent to the server."); | |
} | |
} | |
server.log("Data sent... "); | |
if(server.flush(20)) { | |
server.log("Flush timed out"); | |
} | |
} else { | |
server.log("Nothing to send, first boot?"); | |
} | |
nv.data = ""; | |
server.expectonlinein(3600); | |
//server.expectonlinein(120); | |
} | |
function log() { | |
if (!("nv" in getroottable())) { | |
nv <- { data = "" }; | |
hourly(); | |
} | |
local min = (t/60) % 60; | |
readEverything(); | |
if (min == 59) { | |
hourly(); | |
} | |
imp.onidle(function() { imp.deepsleepfor(60 - (time() % 60)); }); | |
} | |
log(); | |
/*local dog = 0; | |
function watchdog() { | |
server.show("Watchdog: " + dog.tostring()); | |
dog++; | |
imp.wakeup(20, watchdog); | |
} | |
watchdog();*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment