Volkszaehler with ACE3000

The Volkszaehler software should be install on a Raspberry Pi computer with an ACE3000 electric power counter, with an TTL-IR front end for reading the KWh count, see picture.

The data acquisition software vzlogger could not be used, instead I wrote a shell script similar to the example from the ACE3000 wiki page in volkszaehler.org.

The SD-card image with the Volkszaehler software already installed could be found here.

Power Counter ACE3000 Type 260

The Power Counter ACE3000 Type 260 has an Infrared interface. The power count can be read out with the TTL-IR head electronics. The jumpers for polarity must be on 2-3. A connected low cost USB-TTL converter will bring the data to the computer.

The TTL-IS head has a strong magnet in the housing, which holds the sensor in place on the power counter.


The baud rate is 300 baud 7E1 (7 data bits, Even parity, 1 Stop bit). On Linux the device should be /dev/ttyUSB0 or /dev/ttyUSB1, depending on what other serial links you have.

You can use a terminal program (minicom) to get a counter readout:

# type in the Terminal: /?! CR LF
# Answer:

Data Web Visualization

The Visualisation per Internet is shown in the screenshot underneath. All parameters are stored in cookies in the browser data. The red arrows in the screenshot should help you to find the menu items easier.

First you click on Add channel / Kanal hinzufügen (at the bottom of the window). A little windows opens in the center, and you click on Public channel / Öffentlicher Kanal. Next you click on Channel / Kanal to the up/down arrow on the right side. A drop down menu offers the already set up channels.

Click on one of them (Aussen), and the data curve will be added to the diagram. Then proceed with the other two channels (Energie_KWh, Vogelhaus) the same way.

Then you can navigate in the time axis with the buttons underneath of the diagram.

The left Y-axis is scaled in Watt, the right Y-axis is scaled in °C.



USB setup

Because the only left free USB plug for connecting the power counter sensor TTL-USB interface was a mini-USB plug on top of the computer Seagate Dockstar housing, an adapter mini-USB to USB and a gender-adapter must be placed in between, see picture on the right.

In order to have always the same device name /dev/lesekopf0, an udev rule must be setup for the USB-TTL converter.

# show attributes
$ /sbin/udevadm info -a -n /dev/ttyUSB1
  looking at parent device '/devices/platform/orion-ehci.0/usb1/1-1/1-1.1':
    ATTRS{product}=="CP2102 USB to UART Bridge Controller"

# Edit new file /etc/udev/rules.d/99-lesekopf.rules
$ cat /etc/udev/rules.d/99-lesekopf.rules
SUBSYSTEMS=="usb", ATTRS{product}=="CP2102 USB to UART Bridge Controller", ATTRS{serial}=="0001", NAME="lesekopf0", GROUP="dialout", MODE="0666"

# generate new device name "lesekopf0"
$ sudo udevadm trigger

# test device name
$ ls /dev/le*

# set communication parameters
$ minicom -s
# setup 300 baud, 7E1
# quit without RESET: CTRL-A Q

# get parameters:
$ stty -g -F /dev/lesekopf0

# set parameters per script:
$ stty -F /dev/lesekopf0 300 evenp -stopb

# stimulate counter for read out
$ echo $'\x2f\x3f\x21\x0d\x0a' > /dev/lesekopf0

# read out counter
$ od -c < /dev/lesekopf0  # does not work reliable

ACE3000 read out

Because of lack of documentation I was not able to use vzlogger.

Instead I wrote a shell script (example from ronald) to read out the power counter:

$ cat ace3000.sh
# 2014-02-12 RudolfReuter
# script for reding power counter "Itron ACE3000 Typ260"
# communication: TTL-IR Lesekopf, 300 baud 7E1
# store in /tmp (tmpfs) to avoid wearing the USB stick
# will be started by a CRON job every 5 minutes
# $ crontab -e
#   # read every 5 min the power counter ACE3000
#   */5 * * * * $HOME/Install/ace3000.sh > /dev/null

# UUID from middleware

# Init serial port
stty  -F /dev/lesekopf0 300 evenp -cstopb

# trigger power counter
( sleep 1 ; echo -e "\x2f\x3f\x21\x0d\x0a" > /dev/lesekopf0 ) &
while read -t8 line                           # wait for read out
  #echo $line >> /tmp/ace3000.txt             # for debug
  [[ "$line" =~ "1.8.0" ]] && Z1=${line:6:8}  # SML,  OBIS-ID: counter value
done < /dev/lesekopf0

# Debug
echo "$datum : counter: $Z1" >> /tmp/counterlog.txt

# process temperatures
if [ -e $TPATH ]; then
    TV=`cut -d ":" -f 6 $TPATH`
    TA=`cut -d ":" -f 7 $TPATH`
    # store value, and old value
    TV_old=$(cat /tmp/TV)
    echo $TV_old > /tmp/TV_old
    echo $TV > /tmp/TV
    TA_old=$(cat /tmp/TA)
    echo $TA_old > /tmp/TA_old
    echo $TA > /tmp/TA
    # do not copy to database, if value has not changed
    [ "$TV" == "$TV_old" ] && TV=""
    [ "$TA" == "$TA_old" ] && TA=""
    [ -z "$TV" ] || /usr/local/bin/vzclient -u $UUID_TV add data value=$TV > /dev/null
    [ -z "$TA" ] || /usr/local/bin/vzclient -u $UUID_TA add data value=$TA > /dev/null

# store value, and old value
Z1_old=$(cat /tmp/Z1)
echo $Z1_old > /tmp/Z1_old
echo $Z1 > /tmp/Z1

# do not copy to database, if value has not changed
[ "$Z1" == "$Z1_old" ] && Z1=""

[ -z "$Z1" ] || /usr/local/bin/vzclient -u $UUID_Z1 add data value=$Z1 > /dev/null

Because on the same computer a temperature measurement is already running, the 2 temperatures are added to the visualization.

/!\ After a restart of Linux, this script does not read out the counter, it just hangs in the process list. Running then a Python test programm, reads out the counter. Then I have to kill the pending scripts, which are started every 5 minutes via cron. At the next cron job the meter readout works with this script.

It looks like a timing problem (2015-05-18). As a counter measure I renamed the cron prefix from S02 to S89 in the run levels 2-5, in order to start the cron service later in the boot process.

$ sudo mv /etc/rc2.d/S02cron /etc/rc2.d/S89cron
$ sudo mv /etc/rc3.d/S02cron /etc/rc3.d/S89cron
$ sudo mv /etc/rc4.d/S02cron /etc/rc4.d/S89cron
$ sudo mv /etc/rc5.d/S02cron /etc/rc5.d/S89cron

Installing Web-Frontend, vzlogger

Just for reference I will document the setup of program vzlogger. Example of vzlogger automatic start

Test procedure in Python for the power counter readout:

$ ./volkszaehler_ace3000.py

Prerequisites for installing:

$ sudo apt-get install git-core libapache2-mod-php5 php5-cli php5-mysql php-apc mysql-server mysql-client

# Get install script
$ sudo wget --no-check-certificate https://raw.github.com/volkszaehler/volkszaehler.org/master/misc/tools/install.sh

# Edit setup.sh wget --no-check-certificate

$ sudo ./setup.sh

# if you get an error: Could not reliably determine the server's fully qualified domain name
# Edit file /etc/apache2/apache2.conf
# Add at the beginning
ServerName localhost

$ sudo /etc/init.d/apache2 restart

Install composer:

$ cd /var/www/volkszaehler.org

$ curl -k -sS https://getcomposer.org/installer | php

$ sudo composer install

# test for updates
$ sudo composer self-update
You are already using composer version 7343198817f365b1676ced0f353808f0e408ff9a.

More tools for compilation:

$ cd etc

$ sudo cp volkszaehler.conf.template.php volkszaehler.conf.php

# Edit volkszaehler.conf.php (password, etc)

$ sudo apt-get install build-essentials  61 MB

$ sudo apt-get install pkg-config libcurl3-dev libjson0-dev libmicrohttpd-dev

$ apt-get install uuid-dev uuid-runtime

$ sudo env GIT_SSL_NO_VERIFY=true git clone http://github.com/dailab/libsml.git

$ cd libsml

$ sudo make

$ sudo apt-get install cmake

$ sudo env GIT_SSL_NO_VERIFY=true  git clone https://github.com/volkszaehler/vzlogger.git
$ cd vzlogger

$ sudo apt-get install libsasl2-dev

$ sudo cmake . -DSML_HOME=../libsml/sml

$ sudo make
$ sudo make install
-- Install configuration: ""
-- Installing: /usr/local/share/doc/vzlogger-0-3/README
-- Installing: /usr/local/share/doc/vzlogger-0-3/INSTALL
-- Installing: /usr/local/share/doc/vzlogger-0-3/COPYING
-- Installing: /usr/local/bin/vzlogger


Konfiguration File: /var/www/volkszaehler/etc/vzlogger/etc/vzlogger.conf

If needed, setting up the baud rate at cold start of Linux:

# init baud rate at coldstart
# edit file: /etc/rc.local
  # set baud rate for vzlogger - already done in script ace3000.sh
  #stty -F /dev/lesekopf0 300 evenp -stopb

# edit file: /etc/vzlogger.conf

In doubt you can stop/start vzlogger:

# Stop
$ sudo killall vzlogger

# Delete the logfile
$ sudo rm /var/log/vzlogger.log  

# Start vzlogger:
$ sudo vzlogger 

Using vzlogger

Unfortunately I did not got vzlogger to operate as expected, instead I use now a shell script

According to file meter.h there are 2 diffrent protocol types:

 * - sensors:   a readout is triggered in equidistant intervals by calling
 *              the read function with an POSIX timer.
 *              The interval is set in the configuration.
 * - meters:    the meter itselfs triggers a readout.
 *              The pointer to the read function should be NULL.
 *              The 'interval' column in the configuration as no meaning.

The test configuration file is:

$ cat /etc/vzlogger.conf
 * vzlogger configuration
 * use proper encoded JSON with javascript comments
 * take a look at the wiki for detailed information:
 * http://wiki.volkszaehler.org/software/controller/vzlogger#configuration

"retry" : 30,                   /* how long to sleep between failed requests, in seconds */
"daemon": false,                /* run periodically */
"foreground" : true,            /* dont run in background (prevents forking) */

"verbosity" : 15,               /* between 0 and 15 */
"log" : "/var/log/vzlogger.log",/* path to logfile, optional */

"local" : {
        "enabled" : false,      /* should we start the local HTTPd for serving live readings? */
        "port" : 80,            /* the TCP port for the local HTTPd */
        "index" : true,         /* should we provide a index listing of available channels? */
        "timeout" : 30,         /* timeout for long polling comet requests, 0 disables comet, in seconds */
        "buffer" : 600          /* how long to buffer readings for the local interface, in seconds */

"meters" : [{
        "enabled" : true,       /* disabled meters will be ignored */
        "protocol" : "sml",     /* use 'vzlogger -h' for list of available protocols */
        "device" : "/dev/lesekopf0",
        "channels": [{
                "protocol" : "vz", /* volkszaehler.org */
                "uuid" : "a9774800-934a-11e3-87f8-81f5f2ae8dbe",
                "middleware" : "http://localhost/volkszaehler/middleware.php",
//              "identifier" : "counter",  /* alias for '1-0:1.8.0' */
                "identifier" : "1-0:1.8.0",  /* power counter */

When starting vzlogger it stops without showing data:

$ sudo vzlogger -f -v15
[Feb 11 19:53:28]       Start parsing configuration from /etc/vzlogger.conf
[Feb 11 19:53:28][mtr0] Creating new meter with protocol sml.
[Feb 11 19:53:28][mtr0] Meter configured. enabled
[Feb 11 19:53:28]       New meter initialized (protocol=sml)
[Feb 11 19:53:28]       Configure channel.
[Feb 11 19:53:28][chn0] New channel initialized (uuid=...ae8dbe protocol=vz id=1-0:1.8.0)
[Feb 11 19:53:28]       Have 1 meters.
[Feb 11 19:53:28][main] foreground=1, daemon=0, local=0
[Feb 11 19:53:28]       NOT Daemonize process...
[Feb 11 19:53:28]       Opened logfile /var/log/vzlogger.log
[Feb 11 19:53:28][]     ===> Start meters.
[Feb 11 19:53:28][mtr0] Meter connection established
[Feb 11 19:53:28][mtr0] Meter thread started
[Feb 11 19:53:28][mtr0] meter is opened. Start channels.
[Feb 11 19:53:28][chn0] Logging thread started
[Feb 11 19:53:28][]     Startup done.
[Feb 11 19:53:28][chn0] Start logging thread for vz-api. Running as daemon: no
[Feb 11 19:53:28][mtr0] Number of readers: 32
[Feb 11 19:53:28][mtr0] Config.daemon: 0
[Feb 11 19:53:28][mtr0] Config.local: 0
[Feb 11 19:53:28][chn0] Using default api:

Setup Web Frontend

Route your Internet browser to address: URL:8080/frontend

# click on: add channel
  Title: Energie_KWh
  Typ: Elektrische Energie (Zaehlerstaende)
  UUID: a9774800-934a-11e3-87f8-81f5f2axxxxx
  Aktiv: Yes
  Cookie: Yes
  Auflösung: 1

Temperature measurement

Once the electric energy measurement is working, it make sense to add also 2 temperatures. On this computer a temperature measuring for inside and outside was already setup, with a sampling rate of 5 minutes. For details see TempMess.

$ cat rrdtool/rrd_data.dat

# channel(1) #5 is inside temperature Vogelhaus
# channel(1) #6 is outside

Database utility vzclient

For the maintenance of the volkszaehler database there is a utility vzclient. For easier use, setup a configuration file:

$ cat /etc/vzclient.conf

Give the user the right to drop and delete:

$ mysql -u root -p
Enter password:
mysql > grant all on volkszaehler.* to 'vz'@'localhost';
Query OK, 0 rows affected (0.01 sec)
mysql> quit

# show all channel properties
$ vzclient get channel
{"version":"0.3","channels":[{"uuid":"5e98c9b0-9400-11e3-be1c-95c24f7a6629","type":"temperature","active":true,"color":"black","public":true,"style":"lines","title":"Vogelhaus"},{"uuid":"748c7050-9400-11e3-805b-cff6be5bf3db","type":"temperature","active":true,"color":"red","public":true,"style":"lines","title":"Aussen"},{"uuid":"a9774800-934a-11e3-87f8-81f5f2ae8dbe","type":"electric meter","color":"aqua","cost":0.0003,"public":true,"resolution":1,"style":"lines","title":"Energie_KWh"}]}

# delete unused channel
$ vzclient -u cdb2cbc0-926a-11e3-badc-c5ffaebea3fc delete channel

# edit channel property
$ vzclient -u a9774800-934a-11e3-87f8-81f5f2axxxxx edit channel cost=0.0003

# get data tuples
$ vzclient -u a9774800-934a-11e3-87f8-81f5f2axxxxx get data tuples=10

Database service

In the database the absolute electric counter value is stored. But it is not possible to access this value via JSON. So, I will show what other methods are available to access the database directly.


The standard method is to use local the utility mysql from the command line. The data value is the total electric counter value (6046 KWh). First you have to login to the computer:

$ ssl peter@
password: xxx

$ mysql --user=root --password=xxx volkszaehler
# get the first data entries
$ mysql> SELECT * FROM `data` LIMIT 0, 5;
| id | channel_id | timestamp     | value  |
|  6 |          4 | 1392203663705 | 6046.8 |

One difficulty is, that volkszaehler logs the timestamp in mili seconds, while mysql does it in seconds. Therefore you have a factor 1000 to consider, if you want to work with date and time. To get the data values from a specific date:

mysql> SELECT value FROM data WHERE  timestamp BETWEEN UNIX_TIMESTAMP('2014-03-10 08:00:00')*1000 AND UNIX_TIMESTAMP('2014-03-10 08:15:00')*1000 LIMIT 0, 3;
| value  |
|   18.4 |
| 6532.5 |

If you just want to see the electric counter value you have to specify also the channel_id.

mysql> SELECT value FROM data WHERE  channel_id=4 AND timestamp BETWEEN UNIX_TIMESTAMP('2014-03-10 08:00:00')*1000 AND UNIX_TIMESTAMP('2014-03-10 08:15:00')*1000 LIMIT 0, 3;
| value  |
| 6532.5 |
| 6532.6 |


With the PHP program phpmyadmin it is much easier to service data in the mysql database, via web browser. But for getting the absolute electric counter values, you need also to use SQL statements, as shown with mysql before. To call phpmyadmin you need to surf to URL phpmyadmin.

But it is more dangerous to have this program on line. Therefore the configuration file is usually moved to another place, and just used in case:

# to use phpmyadmin, do from the command line:
$ cd Install
$ sudo mv phpmyadmin.conf /etc/apache2/conf.d/phpmyadmin.conf
$ sudo /etc/init.d/apache2 reload

# access the mysql database via web browser.

# and remove it after use
$ sudo rm /etc/apache2/conf.d/phpmyadmin.conf
$ sudo /etc/init.d/apache2 reload

Data Compression

For data compression over time there is the tool vzcompress2.php. See at the Links for the operation.

Improve calculation speed

In order to improve the calculation speed over a longer visualization time (>= week), calculation data (sums) over a day can be aggregated in an extra table aggregate in the database. A detailed description can be found at the Links. A short how to:

# database user "vz" must have the "grant" to "drop", see "vzclient" use above.

# Create extra database table "aggregate"
$ php /var/www/volkszaehler.org/misc/tools/aggregate.php create

#----- The procedures below needs further testing --------
# Calculate sums for the history, may needs hours if the database has more than a year data
$ php /var/www/volkszaehler.org/misc/tools/aggregate.php -m full -l day -l hour run

# Automate the sum calculation
$ crontab -e
# volkszaehler.org, calculation of sums (aggregate)
* 2 * * * php /var/www/volkszaehler.org/misc/tools/aggregate.php -m delta -l day run
9 * * * * php /var/www/volkszaehler.org/misc/tools/aggregate.php -m delta -l hour run

# update cron service
$ sudo service cron reload


Readout Power counter

In order to document month values for a comparison, you have to query the data base. It is useful to read the absolute value at the first day of a month.

The read out should be made comfortable with a web browser. Therefore I developed a PHP script. After making a call to the program you get the result like in the picture to the right. With selecting month and year, the actual month is taken. When selecting a month and year, a click on the button submit will show the data.

If you use this PHP programm, please adopt the database variables to your environment: $username, $password, $channel_id.

The PHP file must be placed on the web server in folder htdocs.

Web address in the local network: <IP-Adresse>/vz_read_strom.php

   1 <?php // program "vz_read_strom.php", 2014-05-09 RudolfReuter 
   2 // Version Zaehler Itron ACE3000
   3 ?>
   4 <h3>Stromzaehler auslesen</h3>
   5 <?php
   6 if (isset($_GET['month']) && isset($_GET['year'])) {
   7     $month = $_GET['month'];
   8     $year = $_GET['year'];
   9 }
  10 else {
  11     $month = date("m");
  12     //echo "actual date \n";
  13     $year = date("Y");
  14 }
  15 ?>
  16 <form id="user_form" action="vz_read_strom.php" method="get">
  17     <fieldset>
  18         <select name="month">
  19             <option value="01">Januar</option>
  20             <option value="02">Februar</option>
  21             <option value="03">Maerz</option>
  22             <option value="04">April</option>
  23             <option value="05">Mai</option>
  24             <option value="06">Juni</option>
  25             <option value="07">Juli</option>
  26             <option value="08">August</option>
  27             <option value="09">September</option>
  28             <option value="10">Oktober</option>
  29             <option value="11">November</option>
  30             <option value="12">Dezember</option>
  31         </select>
  32         <select name="year">
  33             <option value="2014">2014</option>
  34             <option value="2015">2015</option>
  35             <option value="2016">2016</option>
  36             <option value="2017">2017</option>
  37             <option value="2018">2018</option>
  38             <option value="2019">2019</option>
  39             <option value="2020">2020</option>
  40             <option value="2021">2021</option>
  41             <option value="2022">2022</option>
  42             <option value="2023">2023</option>
  43         </select>
  44         <input type="submit" name="submit" value="submit">
  45     </fieldset>
  46 </form>
  47 <?php
  48     $str_from = "$year-$month-01 08:00:00";
  49     $date1 = new DateTime($str_from);
  50     //echo $date1->format('Y-m-d H:i:s') . "\n";
  51     $time_from = $date1->getTimestamp() * 1000;
  52     //echo $time_from . "\n";
  54     $str_to = "$year-$month-01 08:15:00";
  55     $date2 =  new DateTime($str_to);
  56     $time_to = $date2->getTimestamp() * 1000;
  57     //echo $time_to . "\n";
  59     $username="root";
  60     $password="xxxxx";
  61     $channel_id="4";
  62     $str_sql = "SELECT value FROM data WHERE channel_id=$channel_id AND timestamp BETWEEN $time_from AND $time_to LIMIT 0, 1";
  63     //echo $str_sql . "\n";
  64     $db = mysql_connect('localhost', $username, $password);
  65     if (!$db) {
  66         die('Verbindung schlug fehl: ' . mysql_error());
  67     }
  68     $db_vz = mysql_select_db('volkszaehler', $db);
  69     $sql_res = mysql_query($str_sql);
  70     $row = mysql_fetch_assoc($sql_res);
  71     echo ($row["value"]) . " KWh, ";
  72     echo "$year-$month-01 08:00 \n";
  73 ?>


vzvis - alternative to the volkszaehler visualisation

List of pages in this category:

-- PeterReuter 2014-02-08 16:19:49

Go back to CategoryVolkszaehler or FrontPage

VolkszaehlerACE3000 (last edited 2018-04-03 21:30:35 by RudolfReuter)