var dgram = require('dgram');
var fs = require('fs');
var http = require('http');
var iso8601 = require('iso8601');
var path = require('path');

var udp = dgram.createSocket('udp4');

var stateFile = path.normalize(path.join(process.env.HOME || '/var/tmp', '.counterstate.json'))
var envUrl = 'http://172.16.32.64/details.xml';
var cubeSvr = '127.0.0.1';

function get(cb) {
    var req = http.get(envUrl, function (res) {
        var data = '';
        res.on('data', function (chunk) { data += chunk; });
        res.on('end', function () { cb(data); });
        res.on('error', function () { });
    });

    req.on('error', function () { });
}

function next(ms) {
    var now = Date.now();
    var next = Math.ceil(now / ms) * ms;
    var wait = next - now - 500;
    if (wait < 0.25 * ms) {
        wait += ms;
    }
    return wait;
}

function send(result) {
    var buffer = new Buffer(JSON.stringify(result));
    udp.send(buffer, 0, buffer.length, 1180, cubeSvr);
    console.log(result);
}

state = loadState();
stateDirty = false;
saveState();

function saveState() {
    if (stateDirty) {
        fs.writeFileSync(stateFile, JSON.stringify(state), 'utf-8');
        stateDirty = false;
    }

    setTimeout(saveState, 1000);
}

function loadState() {
    try {
        return JSON.parse(fs.readFileSync(stateFile, 'utf-8'));
    } catch (e) {
        return {}
    }
}

function counterDiff(name, curValue) {
    var diff;
    if (state[name] !== undefined) {
        diff = curValue - state[name];
    }

    state[name] = curValue;
    stateDirty = true;

    return diff;
}

var prevCounter;
function poll() {
    var stamp = new Date();
    get(function (data) {
        var result = { type: 'reading', time: stamp, data: { } };

        var m = data.match(/<Counter_A>([0-9.]+)/);
        if (m) {
            var counter = parseInt(m[1], 10);
            result.data.impulses = counterDiff('impulses', counter);
        }

        var m = data.match(/<PrimaryValue>(-?[0-9.]+) Deg C/);
        if (m) {
            var temp = parseFloat(m[1]).toFixed(1);
            result.data.temperature = +temp;
        }

        if (result.data) {
            send(result);
        }

        setTimeout(poll, next(60000));
    });
}

poll();


@@ -1,12 +1,385 @@
+// --- Begin Configuration ---%0A%0Avar edsUrl = 'http://172.16.32.64/details.xml';%0Avar cubeSvr = '127.0.0.1';%0Avar extractions = %5B%7B%0A        exp: /%3CCounter_A%3E(%5B0-9.%5D+)/,%0A        name: 'impulses',%0A        type: 'counter'%0A    %7D, %7B%0A        exp: /%3CPrimaryValue%3E(-?%5B0-9%5D+%5C.%5B0-9%5D)%5B0-9%5D* Deg C/,%0A        name: 'temperature',%0A        type: 'gauge'%0A%7D%5D;%0A%0A// --- End of Configuration ---%0A%0A
 var dgram = 
@@ -545,25 +545,24 @@
 et('udp4');%0A
-%0A
 var stateFil
@@ -623,17 +623,16 @@
 /tmp', '
-.
 counters
@@ -647,83 +647,8 @@
 n'))
-%0Avar envUrl = 'http://172.16.32.64/details.xml';%0Avar cubeSvr = '127.0.0.1';
 %0A%0Afu
@@ -688,18 +688,18 @@
 tp.get(e
-nv
+ds
 Url, fun
@@ -1296,63 +1296,8 @@
 %0A%7D%0A%0A
-state = loadState();%0AstateDirty = false;%0AsaveState();%0A%0A
 func
@@ -1831,25 +1831,8 @@
 %0A%7D%0A%0A
-var prevCounter;%0A
 func
@@ -1965,16 +1965,59 @@
  %7B %7D %7D;%0A
+        extractions.forEach(function (ex) %7B
 %0A       
@@ -2009,32 +2009,36 @@
  (ex) %7B%0A        
+    
 var m = data.mat
@@ -2044,33 +2044,21 @@
 tch(
-/%3CCounter_A%3E(%5B0-9.%5D+)/);%0A
+ex.exp);%0A    
     
@@ -2086,110 +2086,74 @@
     
-var counter = parseInt(m%5B1%5D, 10);%0A            result.data.impulses = counterDiff('impulses', 
+    var value = +m%5B1%5D;%0A                if (ex.type == '
 counter
-);
+') %7B
 %0A   
@@ -2157,27 +2157,25 @@
         
-%7D%0A%0A
+ 
         
 var m = 
@@ -2170,186 +2170,181 @@
     
-var m = data.match(/%3CPrimaryValue%3E(-?%5B0-9.%5D+) Deg C/);%0A        if (m) %7B%0A            var temp = parseFloat(m%5B1%5D).toFixed(1);%0A            result.data.temperature = +temp;%0A        %7D
+   result.data%5Bex.name%5D = counterDiff(ex.name, value);%0A                %7D else %7B%0A                    result.data%5Bex.name%5D = value;%0A                %7D%0A            %7D%0A        %7D);
 %0A%0A  
@@ -2455,16 +2455,70 @@
  %7D);%0A%7D%0A%0A
+state = loadState();%0AstateDirty = false;%0AsaveState();%0A
 poll();%0A

Clean up configuration