Pre-release demo version 0.0.1-rc
authorNirgal <contact_ampy@nirgal.com>
Thu, 5 Sep 2019 09:19:37 +0000 (09:19 +0000)
committerNirgal <contact_ampy@nirgal.com>
Sat, 12 Oct 2019 22:02:56 +0000 (22:02 +0000)
Readme.
"counter" file for historical total used.
Interface improvement: dynamic data with ajax, period selection,
favicon, config file.
init file for autostart.

14 files changed:
countercron [new file with mode: 0755]
html/ampy.php [new file with mode: 0644]
html/config.php [new file with mode: 0644]
html/currentjson.php
html/currentjson_chunked.php [new file with mode: 0644]
html/favicon.svg [new file with mode: 0644]
html/graph.php
html/index.php
html/index2.php [new file with mode: 0644]
html/lastupdate.php [new file with mode: 0644]
init [new file with mode: 0755]
readme
record.py [changed mode: 0644->0755]
run.py

diff --git a/countercron b/countercron
new file mode 100755 (executable)
index 0000000..ec964da
--- /dev/null
@@ -0,0 +1,31 @@
+#!/usr/bin/php -f
+<?php
+include("html/config.php");
+
+exec("/usr/bin/rrdtool flushcached --daemon ".RRDSOCK." ".RRDFILE);
+
+$fd = fopen(COUNTERFILE, 'r');
+$mtime = fstat($fd)['mtime'];
+$counter = (double)fread($fd, 128);
+fclose($fd);
+echo("oldcounter=$counter\n");
+
+$params = [
+       '--daemon', RRDSOCK,
+       '-s', $mtime,
+       'DEF:watts='.RRDFILE.':watts:AVERAGE',
+       'VDEF:avg=watts,AVERAGE',
+       'PRINT:avg:%lf',
+];
+$info=rrd_graph( '-', $params);
+$watts_since_counter = (double)$info['calcpr'][0];
+echo("watts_since_counter=$watts_since_counter\n");
+echo('hours_since_counter='.((time() - $mtime) / 3600.)."\n");
+$wh_since_counter = $watts_since_counter * (time() - $mtime) / 3600.;
+echo("wh_since_counter=$wh_since_counter\n");
+$newcounter = $counter + $wh_since_counter / 1000.;
+echo('newcounter='.$newcounter." kWh\n");
+
+file_put_contents(COUNTERFILE.'.new', $newcounter);
+rename(COUNTERFILE.'.new', COUNTERFILE);
+?>
diff --git a/html/ampy.php b/html/ampy.php
new file mode 100644 (file)
index 0000000..991ca67
--- /dev/null
@@ -0,0 +1,25 @@
+<?php
+$RRDFILE='/home/nirgal/ampy/power.rrd';
+$COUNTERFILE='/home/nirgal/ampy/counter';
+
+function get_counter() {
+       $fd = fopen($COUNTERFILE, 'r');
+       $mtime = fstat($fd)['mtime'];
+       $counter = (double)fread($fd, 128) * 1000;
+       fclose($fd);
+       #echo($mtime.'<br>');
+       #echo('counter='.$counter.'<br>');
+       
+       $info=rrd_graph( '-', ['-s', $mtime, 'DEF:watts='.$RRDFILE.':watts:AVERAGE', 'VDEF:avg=watts,AVERAGE', 'PRINT:avg:%lf']);
+       #print_r($info);
+       $watts_since_counter = (double)$info['calcpr'][0];
+       #echo('watts_since_counter='.$watts_since_counter.'<br>');
+       #echo('hours_since_counter='.((time() - $mtime) / 3600.).'<br>');
+       $wh_since_counter = $watts_since_counter * (time() - $mtime) / 3600.;
+       #echo('wh_since_counter='.$wh_since_counter.'<br>');
+       $counter += $wh_since_counter;
+       #echo('newcounter='.($counter/1000).' kWh<br>');
+
+       return $counter/1000.;
+}
+?>
diff --git a/html/config.php b/html/config.php
new file mode 100644 (file)
index 0000000..7bd1ade
--- /dev/null
@@ -0,0 +1,7 @@
+<?php
+define("RRDSOCK", "/var/run/rrdcached.sock");
+define("RRDFILE", "/var/lib/rrdcached/db/power.rrd");
+define("COUNTERFILE", "/var/lib/ampy/counter");
+define("IMGWIDTH", 970);
+define("IMGHEIGHT", 490);
+?>
index f3c8f315871e464a9106ec669c79d0fa14998d26..41b39ed953a7d91bd32bb665e504cccee7d198b2 100644 (file)
@@ -1,7 +1,40 @@
 <?php
-$RRDFILE="/home/nirgal/ampy/power.rrd";
 
-$info=rrd_lastupdate($RRDFILE);
+require("config.php");
+
+exec("/usr/bin/rrdtool flushcached --daemon ".RRDSOCK." ".RRDFILE);
+
+$fd = fopen(COUNTERFILE, 'r');
+$mtime = fstat($fd)['mtime'];
+$counter = (double)fread($fd, 128) * 1000;
+fclose($fd);
+#echo($mtime.'<br>');
+#echo('counter='.$counter.'<br>');
+
+$params = [
+       '--daemon', RRDSOCK,
+       '-s', $mtime,
+       'DEF:watts='.RRDFILE.':watts:AVERAGE',
+       'VDEF:avg=watts,AVERAGE',
+       #'VDEF:last=watts,LAST',
+       'PRINT:avg:%lf',
+       #'PRINT:last:%lf',
+];
+/*header("Content-Type: text/plain");
+foreach ($params as $param) echo(escapeshellarg($param)." ");
+return;*/
+$info=rrd_graph( '-', $params);
+#print_r($info);
+$watts_since_counter = (double)$info['calcpr'][0];
+#$watts_last = (double)$info['calcpr'][1];
+#echo('watts_since_counter='.$watts_since_counter.'<br>');
+#echo('hours_since_counter='.((time() - $mtime) / 3600.).'<br>');
+$wh_since_counter = $watts_since_counter * (time() - $mtime) / 3600.;
+#echo('wh_since_counter='.$wh_since_counter.'<br>');
+$newcounter = $counter + $wh_since_counter;
+#echo('newcounter='.$newcounter.' kWh<br>');
+
+$info=rrd_lastupdate(RRDFILE);
 if ($info === FALSE)
        $result=[
                'last_update' => 'unknown',
@@ -10,8 +43,13 @@ if ($info === FALSE)
 else
        $result=[
                'last_update' => $info['last_update'],
-               'watts' => $info['data'][0]
+               'watts' => (double)$info['data'][0]
        ];
+
+#$result=[];
+#$result['watts'] = $watts_last;
+$result['counter'] = $newcounter / 1000.;
+
 header("Content-Type: text/json");
 echo(json_encode($result));
 ?>
diff --git a/html/currentjson_chunked.php b/html/currentjson_chunked.php
new file mode 100644 (file)
index 0000000..34f5c8b
--- /dev/null
@@ -0,0 +1,34 @@
+<?php
+$RRDFILE="/home/nirgal/ampy/power.rrd";
+
+header("Content-Type: text/json");
+header("Transfer-Encoding: chunked");
+flush();
+
+
+// Send chunk to browser
+function send_chunk($chunk)
+{
+       // The chunk must fill the output buffer or php won't send it
+       $chunk = str_pad($chunk, 4096);
+
+       printf("%x\r\n%s\r\n", strlen($chunk), $chunk);
+       flush();
+}
+
+while (True) {
+       $info=rrd_lastupdate($RRDFILE);
+       if ($info === FALSE)
+               $result=[
+                       'last_update' => 'unknown',
+                       'watts' => 'unknown'
+               ];
+       else
+               $result=[
+                       'last_update' => $info['last_update'],
+                       'watts' => $info['data'][0]
+               ];
+       send_chunk(json_encode($result));
+       sleep(10);
+}
+?>
diff --git a/html/favicon.svg b/html/favicon.svg
new file mode 100644 (file)
index 0000000..03e4b3b
--- /dev/null
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Notepad -->
+<!-- (PD) January 25, 2006 - _Crotalus horridus_  -->
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.0" width="40" height="40" id="Stylized Lightning Bolt on Circle">
+  <defs>
+    <radialGradient id="CircleGradient" gradientUnits="userSpaceOnUse" cx="20" cy="20" fx="20" fy="20" r="13">
+      <stop offset="0%" stop-color="#FFFF00" stop-opacity="1.0"/>
+      <stop offset="100%" stop-color="#FFFFFF" stop-opacity="0.0"/>
+    </radialGradient>
+  </defs>
+  <ellipse fill="#FF8000" stroke="#000000" stroke-width="1" cx="20" cy="20" rx="13" ry="13" id="Background Circle"/>
+  <ellipse fill="url(#CircleGradient)" fill-opacity="1.0" cx="20" cy="20" rx="13" ry="13" id="Shading Circle"/>
+  <path fill="#FFFF00" stroke="#000000" stroke-width="1" stroke-linecap="round" stroke-linejoin="round" d="M 36,4 L 12,16 18,21 4,36 28,24 22,19 Z" id="Lightning Bolt"/>
+</svg>
\ No newline at end of file
index 4675620a0e5066fcd760aa1d9fd75ec001f70c17..9f6f4e70e9472e6ef806b59b3b37dba970c7de1c 100644 (file)
@@ -1,25 +1,47 @@
 <?php
-$RRDFILE="/home/nirgal/ampy/power.rrd";
+
+require("config.php");
+
 $IMGFILE="/tmp/power.svg";
-$REFRESH=30;
 
-$result=rrd_graph("$IMGFILE", [
+$hours = array_key_exists('h', $_REQUEST) ? (int)$_REQUEST['h'] : 0;
+$minutes = array_key_exists('m', $_REQUEST) ? (int)$_REQUEST['m'] : 0;
+if (!$hours && !$minutes)
+       $hours = 1;
+$params = [
+       "--daemon", RRDSOCK,
        "--imgformat", "SVG",
-       "-s", "now-1h",
-       #"-e", "now-8h",
-       "--width", "1000",
-       "--height", "500",
+       "-s", "now-".$hours."h".$minutes."m",
+       "--width", "".IMGWIDTH,
+       "--height", "".IMGHEIGHT,
        "--vertical-label", "watts",
        "--lower-limit", "0",
-       #"--logarithmic",
-       "DEF:watts=${RRDFILE}:watts:AVERAGE",
-       "LINE1:watts#FF0000"
-]);
+       "DEF:watts=".RRDFILE.":watts:AVERAGE",
+       #"DEF:maxwatts=".RRDFILE.":watts:MAX:step=".(60*(60*$hours)+$minutes),
+       #"DEF:maxwatts=".RRDFILE.":watts:MAX",
+       "CDEF:wh_raw=watts,".(float)($hours+$minutes/60.).",*",
+       "VDEF:watts_avg=watts,AVERAGE",
+       "VDEF:wh=wh_raw,AVERAGE",
+       "AREA:watts#FF0000",
+       "LINE:watts_avg#00FF00",
+       "GPRINT:watts_avg:Average %6.2lf %swatts",
+       "GPRINT:wh:Total %6.2lf %swh",
+       #"LINE:maxwatts#0000FF",
+       #"GPRINT:maxwatts:Max %6.2lf %sW",
+];
+
+/*header("Content-Type: text/plain");
+foreach ($params as $param) echo(escapeshellarg($param)." ");
+return;*/
+
+$result=rrd_graph("$IMGFILE", $params);
 if ($result === FALSE) {
-       echo("Error in rrd_graph");
+       echo("Error in rrd_graph:<br>");
+       echo(rrd_error());
        die();
 }
 header("Content-Type: image/svg+xml");
-#header("Refresh: $REFRESH");
+header("Cache-Control: no-cache, max-age=0, must-revalidate");
+header("Refresh: ".(60*(60*$hours)+$minutes)/IMGWIDTH);
 readfile($IMGFILE);
 ?>
index db29c6ae0b98d0ff0d506658e94841630be362af..1b16c7e93d8ab70b00c8c83c79110a126992dbf4 100644 (file)
@@ -1,22 +1,48 @@
 <!DOCTYPE html>
 <meta charset="UTF-8">
+<link rel="shortcut icon" href="favicon.svg">
+<title>ampy - Le compteur espion qui ne moucharde pas</title>
 <script src='/javascript/jquery/jquery.js'></script>
 <script>
 function refresh_power() {
        $.ajax({
                url : 'currentjson.php',
                success : function(result) {
-                       document.getElementById('currentpower').innerHTML = result['watts'];
+                       document.getElementById('currentpower').innerHTML = result['watts'].toFixed(1);
+                       document.getElementById('totalpower').innerHTML = result['counter'].toFixed(5);
                },
                complete : function() {
                        setTimeout(refresh_power, 1000);
                }
        });
 }
+function refresh_graph(hours=0, minutes=0) {
+       img = document.getElementById('loadcurve');
+       img.src = 'graph.php?h='+hours+'&m='+minutes+'&t='+new Date().getTime();
+}
 </script>
 
-Puissance instannée: <span id=currentpower>unknown</span> watts<br>
+Puissance instantannée: <span id=currentpower>unknown</span> watts
 <script>refresh_power();</script>
 
+-
+
+Compteur: <span id=totalpower>unknown</span> kWh
+
+-
+
+Graphique:
+<a href='javascript:refresh_graph(0,5)'>5m</a> 
+<a href='javascript:refresh_graph(0,30)'>30m</a> 
+<a href='javascript:refresh_graph(1)'>1h</a> 
+<a href='javascript:refresh_graph(2)'>2h</a>
+<a href='javascript:refresh_graph(6)'>6h</a>
+<a href='javascript:refresh_graph(12)'>12h</a>
+<a href='javascript:refresh_graph(24)'>1d</a>
+<a href='javascript:refresh_graph(2*24)'>2d</a>
+<a href='javascript:refresh_graph(7*24)'>7d</a>
+<a href='javascript:refresh_graph(30*24)'>30d</a>
+
+<br>
 
-<img src="graph.php">
+<img id='loadcurve' src='graph.php'>
diff --git a/html/index2.php b/html/index2.php
new file mode 100644 (file)
index 0000000..9134f27
--- /dev/null
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<meta charset="UTF-8">
+<script src='/javascript/jquery/jquery.js'></script>
+
+<hr>
+<span id=debugg>
+</span>
+<hr>
+
+Puissance instannée: <span id=currentpower>Unknown</span> watts<br>
+
+<script>
+xhr = new XMLHttpRequest();
+xhr.onreadystatechange = function() {
+       document.getElementById('debugg').innerHTML += ""+xhr.readyState+"<br>";
+       document.getElementById('debugg').innerHTML += ""+xhr.status+" "+xhr.statusText+"<br>";
+       document.getElementById('debugg').innerHTML += ""+xhr.responseText+"<br>";
+       this.response = "";
+}
+xhr.open('GET', 'currentjson_chunked.php', true /*async*/);
+xhr.send(null);
+
+//autorefresh_power = 1;
+//function refresh_power() {
+//     $.ajax({
+//             url : 'currentjson_chunked.php',
+//             success : function(result) {
+//                     document.getElementById('debugg').innerHTML = document.getElementById('debugg').innerHTML + "success<br>";
+//                     alert(result);
+//                     document.getElementById('currentpower').innerHTML = result['watts'];
+//             },
+//             complete : function(textStatus) {
+//                     document.getElementById('debugg').innerHTML = document.getElementById('debugg').innerHTML + "complete<br>";
+//             //      if (autorefresh_power)
+//             //              setTimeout("refresh_power()", 1000);
+//             }
+//     });
+//}
+//refresh_power();
+</script>
+
+
+<img src="graph.php">
diff --git a/html/lastupdate.php b/html/lastupdate.php
new file mode 100644 (file)
index 0000000..980a11e
--- /dev/null
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<meta charset="UTF-8">
+
+<?php
+$RRDFILE="/home/nirgal/ampy/power.rrd";
+
+$info=rrd_lastupdate($RRDFILE);
+if ($info === FALSE)
+       echo("error in rrd_lastupdate");
+else
+       print_r($info);
+?>
diff --git a/init b/init
new file mode 100755 (executable)
index 0000000..1ed9146
--- /dev/null
+++ b/init
@@ -0,0 +1,59 @@
+#!/bin/sh
+### BEGIN INIT INFO
+# Provides:          ampy
+# Required-Start:    $remote_fs
+# Required-Stop:     $remote_fs
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+# Short-Description: ampy
+# Description:       Listen to ampmeter on microphone and fill in an rrd file
+### END INIT INFO
+
+PATH=/bin:/usr/bin:/sbin:/usr/sbin
+PIDFILE=/var/run/ampy.pid
+USER=nirgal
+GROUP=ampy
+PROG=/usr/bin/python3
+ARGS=/home/nirgal/ampy/run.py
+NICE=-10
+
+set -e
+
+. /lib/lsb/init-functions
+
+d_start () {
+       log_daemon_msg "Starting ampmeter recording" "ampy"
+       if start-stop-daemon --start --quiet --background --exec $PROG --user $USER --pidfile $PIDFILE --chuid $USER:$GROUP --umask 002 --make-pidfile --nicelevel $NICE -- $ARGS
+       then
+               log_success_msg
+       else
+               log_failure_msg
+       fi
+}
+
+d_stop () {
+       log_daemon_msg "Stopping ampmeter recording" "ampy"
+       if start-stop-daemon --stop --quiet --exec $PROG --user $USER --pidfile $PIDFILE -- $ARGS
+       then
+               log_success_msg
+       else
+               log_failure_msg
+       fi
+}
+
+case $1 in
+       start)
+               d_start
+       ;;
+       stop)
+               d_stop
+       ;;
+       restart|force-reload)
+               d_stop
+               d_start
+       ;;
+       *)
+               log_success_msg "Usage: ampy {start|stop|restart|force-reload}"
+               exit 1
+       ;;
+esac
diff --git a/readme b/readme
index 75c0776af1fd8566acd0de865ee2473692090a41..9defae2a2b0cf0a5417eb5eea3820d951f36884d 100644 (file)
--- a/readme
+++ b/readme
@@ -1,3 +1,21 @@
 https://learn.openenergymonitor.org/electricity-monitoring/ct-sensors/yhdc-sct-013-000-ct-sensor-report
 
-rrdtool create power.rrd --start now-2h --step 1s DS:watts:GAUGE:1:0:6600 RRA:AVERAGE:0.5:1s:1d  # Buggy: nécessite des updates toutes les 500 ms
+rrdtool create power.rrd --step 1s DS:watts:GAUGE:1:0:6600 RRA:AVERAGE:0.5:1s:1d  # Buggy: nécessite des updates toutes les 500 ms
+rrdtool create power.rrd --daemon /var/run/rrdcached.sock --step 1s DS:watts:GAUGE:1:0:6600 RRA:AVERAGE:0.5:1s:1d  # Buggy: nécessite des updates toutes les 500 ms
+
+rrdtool create /var/lib/rrdcached/db/power.rrd \
+       --step 1s \
+       DS:watts:GAUGE:1s:0:10000 \
+       RRA:AVERAGE:0.5:1s:1d \
+       RRA:AVERAGE:0.5:1m:3d \
+       RRA:AVERAGE:0.5:15m:1w \
+       RRA:AVERAGE:0.5:1h:30d \
+       RRA:AVERAGE:0.5:1d:3y \
+       RRA:MAX:0.5:1d:3y \
+       RRA:AVERAGE:0.5:1month:10y \
+       RRA:MAX:0.5:1month:10y
+
+Ceci n'est pas rafraîchi très souvent:
+watch -n 0.5 rrdtool graphv - '-s' '1546280606' 'DEF:watts=/var/lib/rrdcached/db/power.rrd:watts:AVERAGE' 'VDEF:avg=watts,AVERAGE' 'VDEF:last=watts,LAST' 'PRINT:avg:%lf' 'PRINT:last:%lf'
+Alors que ça si:
+watch -n 0.5 rrdtool lastupdate --daemon /var/run/rrdcached.sock /var/lib/rrdcached/db/power.rrd
old mode 100644 (file)
new mode 100755 (executable)
index a113104..8b4207d
--- a/record.py
+++ b/record.py
@@ -1,3 +1,4 @@
+#!/usr/bin/python3
 """
 PyAudio example: Record a few seconds of audio and save to a WAVE
 file.
diff --git a/run.py b/run.py
index c4bbf79ad5f81f17394b7bdac0373cdd98edcf36..edff65e72883ee0666989c1aaf740239b713b5c5 100755 (executable)
--- a/run.py
+++ b/run.py
@@ -9,45 +9,109 @@ import pyaudio
 import wave
 import sys
 import struct
+import time
 
+FORMAT = pyaudio.paInt32  # Format
+STRUCTFORMAT = 'i'  # Format for python struct module
 DEVICE = 3  # which alsa decive to read
-CHUNK = 1024  # how many bytes at a time?
-FORMAT = pyaudio.paInt16  # Format
 RATE = 44100
 RECORD_SECONDS = 0.5
 
-VOLUME_CONSTANT = 11.975454545454545
-
-p = pyaudio.PyAudio()
-
-stream = p.open(format=FORMAT,
-                channels=1,  # Our ampmeter always returns 0 on the second channel
-                rate=RATE,
-                input=True,
-                input_device_index=DEVICE,
-                frames_per_buffer=CHUNK)
-
-while(True):
-    total = 0
-    for i in range(0, int(RATE * RECORD_SECONDS / CHUNK)):
-        data = stream.read(CHUNK, exception_on_overflow=False)
-        values = struct.unpack('h'*CHUNK, data)
-        #print(values)
-        chunk_total = 0
-        for value in values:
-            if value > 0:
-                chunk_total += value
-            else:
-                chunk_total -= value
-        chunk_total /= len(values)
-        #print(chunk_total)
-        total += chunk_total
-    avg = total / int(RATE * RECORD_SECONDS / CHUNK)
-    watts = avg / VOLUME_CONSTANT
-    print("average {:.0f}W".format(watts))
-    os.system("rrdtool update power.rrd N:{:.0f}".format(watts))
-
-stream.stop_stream()
-stream.close()
-p.terminate()
+VOLUME_CONSTANT = 132360.98315789475
 
+#amixer -c 1 contents
+# numid=23,iface=MIXER,name='Capture Volume'
+#   ; type=INTEGER,access=rw---R--,values=2,min=0,max=46,step=0
+#   : values=17,17
+#   | dBscale-min=-16.00dB,step=1.00dB,mute=0
+# => Set volume to 18
+
+# https://www.actutem.com/valeur-crete-moyenne-et-efficace-dune-tension-ac/
+# math.pi/math.sqrt(2)/2 = 1.1107207345395915
+
+# Pour 30 A à 230V ( 6900 W )
+# abs(Sndmax) = 2147483520
+# Sndavg = 2147483520/math.pi = 683565234.8327662
+# Sndeff = 683565234.8327662 * 1.1107207345395915 = 759250079.7391784
+
+# https://fr.wikipedia.org/wiki/Compteur_%C3%A9lectrique
+# Mon compteur tourne à une vitesse proportionnelle à la puissance instantanée
+
+# https://fr.wikipedia.org/wiki/%C3%89lectricit%C3%A9_domestique#Tension
+# En france, ERDF fourni 230V EFFICACES (=> 207.0727527161344 moyenne)
+
+#raw average: 636207384.4738322 - min: -2147483648 - max: 2147483392
+#average 4806.6W  
+
+def loop(optrecord, optstats):
+    p = pyaudio.PyAudio()
+    
+    print("opened")
+    NSAMPLE = int(RATE * RECORD_SECONDS)
+    stream = p.open(format=FORMAT,
+                    channels=1,  # Our ampmeter always returns 0 on the second channel
+                    rate=RATE,
+                    input=True,
+                    input_device_index=DEVICE)
+    structformat = '<' + STRUCTFORMAT * NSAMPLE
+    while(True):
+        try:
+            total = 0
+            minvalue = 0
+            maxvalue = 0
+            data = stream.read(NSAMPLE, exception_on_overflow=False)
+            values = struct.unpack(structformat, data)
+            #print(values)
+            #for x in range(100): print('**{:04x}**{}**'.format(values[x], values[x]))
+            for value in values:
+                if value > 0:
+                    total += value
+                else:
+                    total -= value
+                if value > maxvalue:
+                    maxvalue = value
+                if value < minvalue:
+                    minvalue = value
+            avg = float(total) / NSAMPLE
+            if optstats:
+                print("raw average: {} - min: {} - max: {}".format(avg, minvalue, maxvalue))
+            watts = avg / VOLUME_CONSTANT
+            print("average {:.1f}W  ".format(watts), end='\r')
+            if optrecord:
+                #os.system("rrdtool update --daemon /var/run/rrdcached.sock power.rrd N:{}".format(watts))
+                os.system("rrdtool update --daemon /var/run/rrdcached.sock /var/lib/rrdcached/db/power.rrd {}:{}".format(time.time(), watts))
+        except KeyboardInterrupt:
+            print("Received KeyboardInterrupt: exiting")
+            break
+    
+    stream.stop_stream()
+    stream.close()
+    p.terminate()
+
+def main():
+    import argparse
+
+    parser = argparse.ArgumentParser(description='Ampemeter processing')
+    parser.add_argument(
+            '--stats',
+            action='store_true',
+            default=False,
+            help='Dump recording level stats for every chunk',
+            )
+    parser.add_argument(
+            '--norecord',
+            action='store_false',
+            default=True,
+            help='Disable recording in RRD file',
+            dest='record',
+            )
+    args = parser.parse_args()
+
+    if not args.record:
+        print('Recording disabled.')
+
+    loop(optrecord=args.record, optstats=args.stats)
+
+if __name__ == '__main__':
+    main()