Ben's notes

Linux, Unix, network, radio...

User Tools

Site Tools


serial_data_logger

This is an old revision of the document!


Smart Meter - P1 data logger

This script will log serial data and prepend time/date stamp. The example below if P1 data from a smart meter. You can pipe this to rotatelogs to save the output to rotated logs.

# /usr/local/bin/serialWatch.exp ttyUSB0

2014-06-16,21:25:44 Log starting...
spawn [open ...]
2014-06-16,21:25:45: 0
2014-06-16,21:25:45: /XMX5XMXABCE000046867
2014-06-16,21:25:45:
2014-06-16,21:25:45: 0-0:96.1.1(31333430303738362020202020202020)
2014-06-16,21:25:45: 1-0:1.8.1(05062.220*kWh)
2014-06-16,21:25:45: 1-0:1.8.2(04235.032*kWh)
2014-06-16,21:25:45: 1-0:2.8.1(00000.000*kWh)
2014-06-16,21:25:45: 1-0:2.8.2(00000.000*kWh)
2014-06-16,21:25:45: 0-0:96.14.0(0002)
2014-06-16,21:25:45: 1-0:1.7.0(0000.75*kW)
2014-06-16,21:25:45: 1-0:2.7.0(0000.00*kW)
2014-06-16,21:25:45: 0-0:17.0.0(999*A)
2014-06-16,21:25:45: 0-0:96.3.10(1)
2014-06-16,21:25:45: 0-0:96.13.1()
2014-06-16,21:25:45: 0-0:96.13.0()
2014-06-16,21:25:45: 0-1:96.1.0(3238303131303038323335313030333132)
2014-06-16,21:25:45: 0-1:24.1.0(03)
2014-06-16,21:25:45: 0-1:24.3.0(140616210000)(08)(60)(1)(0-1:24.2.0)(m3)
2014-06-16,21:25:45: (02418.609)
2014-06-16,21:25:45: 0-1:24.4.0(1)
2014-06-16,21:25:45: !
#! /bin/sh
# the next line restarts using expect \
exec expect $0 ${1+"$@"}

#!/usr/bin/expect -f
#
# serialWatch.exp
#   Connect up to a device on a serial port
#   Time stamp any incoming lines to stdout

       # port is any serial port (omit the /dev/ prefix)
       # e.g. ttya, cua0, serialA, serialB, boca01 - boca16

if {$argc != 1} {
  puts "$argc, $argv"
  puts "usage: serial.exp port"
  exit
}

proc timeStamp {} {
  global tcl_version
  if {$tcl_version >= 7.5} {
    # "clock" command requires Tcl v7.5 or greater
    # internal routine a little faster than making a system call
    set stamp [clock format [clock seconds] -format %Y-%m-%d,%T]
  } else {
    # fall back to standard UNIX system call
    set stamp [exec /bin/date +%Y-%m-%d,%T]
  }
  return $stamp
}

puts "\n[timeStamp] Log starting..."
set port /dev/$argv
set spawned [spawn -open [open $port w+]]
puts "[timeStamp]: [string trim $spawned \r\n]"
set baud 9600
    # -parenb means don't use a parity bit
    # -cstopb means "not 2 stop bits, but 1"
    # cs8 means 8 bits
    # -echo means no echo (full duplex?)
stty ispeed $baud ospeed $baud raw -echo cs7 parenb -parodd -cstopb onlcr < $port
log_user 0

# log each input line
#  add a timeStamp at the beginning of each line
while {1} {
  expect "\n" {
    puts "[timeStamp]: [string trim $expect_out(buffer) \r\n]"
  }
}
  • Start logging after boot. Add to /etc/rc.local:
    echo "nohup /usr/local/bin/serialWatch.exp ttyUSB0 | rotatelogs -f /mnt/ram/p1data 86400 100M &" | at now+1min

rsync / init script

You can use the following script to sync the RAM disk to NAS. It wil also sync before shutdown. This has been tested on Raspbian (Raspberry PI) Debian.

  • Create script /etc/init.d/rsync-p1-data
    #!/bin/bash
    #
    # chkconfig: - 95 05
    
    ### BEGIN INIT INFO
    # Provides: rsync-p1-data
    # Required-Stop: $network $local_fs $remote_fs
    # Required-Start: $syslog
    # Default-Start: 2
    # Default-Stop: 0 1 6
    # Short-Description: sync RAM disk to NAS
    # Description: rsync network captures from RAM disk to NAS
    ### END INIT INFO
    
    prog=`basename $0`
    lockfile=/var/lock/$prog
    ramdisk=/mnt/ram
    nas=/mnt/pd-p1smartmeter
    
    stop() {
            [ "$EUID" != "0" ] && exit 4
            echo -n $"$prog, syncing RAM disk to NAS before shutdown."
            echo " ---- STOP runlevel: `/sbin/runlevel` date:  `date`" >> /var/log/rsync.log
            /usr/bin/rsync --quiet -a --log-file=/var/log/rsync.log $ramdisk/ $nas
            RETVAL=$?
            echo
            [ $RETVAL -eq 0 ] && rm -f $lockfile
            return $RETVAL
    }
    
    start() {
            [ "$EUID" != "0" ] && exit 4
            echo -n $"$prog, sync not needed at start-up."
            echo " ---- START runlevel: `/sbin/runlevel` date: `date`" >> /var/log/rsync.log
            RETVAL=$?
            echo
            [ $RETVAL -eq 0 ] && touch $lockfile
            return $RETVAL
    }
    
    sync() {
            [ "$EUID" != "0" ] && exit 4
            # Sync all files but last (the one open for writing) to nas dir and year/day subdirs.
            # remove source files from RAM disk, if sync was succesful.
    
            # first create directory structure
            mkdir -p $nas/`date +%Y/%m/%d`
          
            # sync files
            ls $ramdisk | sort -t. -k2 | head -n -1 | /usr/bin/rsync --quiet -a --remove-source-files --log-file=/var/log/rsync.log --files-from=- $ramdisk/ $nas/`date +%Y/%m/%d`
            RETVAL=$?
            return $RETVAL
    }
    
    # See how we were called.
    case "$1" in
      stop) 
            stop
            ;;
      start)
            start
            ;;
      sync) 
            sync
            ;;
    
      *)
            echo $"Usage: $0 {start|stop|sync}"
            exit 2
    esac
  • Enable script to run at stop/start
    update-rc.d rsync-p1-data defaults
    update-rc.d rsync-p1-data enable
  • Enable automatic sync every hour. Add to crontab:
    1 * * * * /etc/init.d/rsync-p1-data sync
serial_data_logger.1404732625.txt.gz · Last modified: 2014/07/07 11:30 by admin