Created
May 13, 2014 21:13
-
-
Save fasmide/3c76f209c6781bc5c7bd to your computer and use it in GitHub Desktop.
Kamstrup with sleep and nvram storage
This file contains hidden or 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