view vanlogger.py @ 14:aa18210c2703

Improve start/end/days handling - Allow the user to specify nothing to graph todays data. - Fix bug when only specifying days. - When specifying days finish at the end of today.
author Daniel O'Connor <darius@dons.net.au>
date Thu, 11 Jan 2018 08:43:40 +1030
parents f77cc29d0b47
children 65be58857ed4 59cf68be7feb bacb798e6731
line wrap: on
line source

#!/usr/bin/env python

import sys

sys.path.append('/home/pi/logger')
import datetime
import epro.epro as epro
import giant.giant as giant
import serial
import sqlite3

def create(cur):
    cur.execute('''
CREATE TABLE IF NOT EXISTS eprolog(
    tstamp			INTEGER NOT NULL,
    main_voltage	REAL NOT NULL,
    aux_voltage		REAL NOT NULL,
    battery_curr	REAL NOT NULL,
    amp_hours		REAL NOT NULL,
    state_of_charge	REAL NOT NULL,
    time_remaining	REAL NOT NULL,
    battery_temp	REAL,
    auto_sync_volts	BOOLEAN NOT NULL,
    auto_sync_curr	BOOLEAN NOT NULL,
    e501			BOOLEAN NOT NULL,
    alarm_test		BOOLEAN NOT NULL,
    light			BOOLEAN NOT NULL,
    display_test	BOOLEAN NOT NULL,
    temp_sensor		BOOLEAN NOT NULL,
    aux_hv			BOOLEAN NOT NULL,
    aux_lv			BOOLEAN NOT NULL,
    installer_lock	BOOLEAN NOT NULL,
    main_hv			BOOLEAN NOT NULL,
    main_lv			BOOLEAN NOT NULL,
	low_battery 	BOOLEAN NOT NULL,
    battery_flat	BOOLEAN NOT NULL,
    battery_full	BOOLEAN NOT NULL,
    battery_charged	BOOLEAN NOT NULL,
    no_sync			BOOLEAN NOT NULL,
    monitor_reset	BOOLEAN NOT NULL
);
''')

    cur.execute('''
CREATE TABLE IF NOT EXISTS giantlog(
    tstamp			INTEGER NOT NULL,
	ac_act_power	REAL NOT NULL,
	ac_app_power	REAL NOT NULL,
	ac_frequency	REAL NOT NULL,
	ac_volts		REAL NOT NULL,
	batt_chr_curr	REAL NOT NULL,
	batt_dis_curr	REAL NOT NULL,
    battery_cap		REAL NOT NULL,
	battery_volts	REAL NOT NULL,
	batt_volt_ofs	REAL NOT NULL,
	bus_voltage		REAL NOT NULL,
	grid_frequency	REAL NOT NULL,
	grid_volts		REAL NOT NULL,
	hs_temperature	REAL NOT NULL,
	load_pct		REAL NOT NULL,
	pv1_chrg_pow	REAL NOT NULL,
	pv1_current		REAL NOT NULL,
	pv1_volts		REAL NOT NULL,
	scc1_volts		REAL NOT NULL,
    scc1_charging	BOOLEAN NOT NULL,
    switch			BOOLEAN NOT NULL,
	float_charge	BOOLEAN NOT NULL,
    ac_charging 	BOOLEAN NOT NULL,
	sbu_prio		BOOLEAN NOT NULL,
	b_volt_steady	BOOLEAN NOT NULL,
    charging		BOOLEAN NOT NULL
);
''')

def log_epro(p, cur):
    # Check we have all the packets we need in the queue
    msgtypes = set([x.msgtype for x in p.packets])
    wantedtypes = set([
        epro.MainVoltage.MSGTYPE,
        epro.AmpHours.MSGTYPE,
        epro.BatteryCurrent.MSGTYPE,
        epro.StateOfCharge.MSGTYPE,
        epro.TimeRemaining.MSGTYPE,
        epro.BatteryTemperature.MSGTYPE,
        epro.MonitorStatus.MSGTYPE,
        epro.AuxVoltage.MSGTYPE,
        ])
    if msgtypes < wantedtypes:
        return

    row = {}
    usedtypes = set()
    while len(p.packets) > 0:
        pkt = p.packets.pop() # Read latest packets first
        if pkt.msgtype == epro.MainVoltage.MSGTYPE:
            row['main_voltage'] = pkt.volts
        elif pkt.msgtype == epro.AmpHours.MSGTYPE:
            row['amp_hours'] = pkt.amphrs
        elif pkt.msgtype == epro.BatteryCurrent.MSGTYPE:
            row['battery_curr'] = pkt.amps
        elif pkt.msgtype == epro.StateOfCharge.MSGTYPE:
            row['state_of_charge'] = pkt.soc
        elif pkt.msgtype == epro.TimeRemaining.MSGTYPE:
            row['time_remaining'] = pkt.time
        elif pkt.msgtype == epro.BatteryTemperature.MSGTYPE:
            row['battery_temp'] = pkt.temp
        elif pkt.msgtype == epro.MonitorStatus.MSGTYPE:
            row['auto_sync_volts'] = pkt.autosyncvolt
            row['auto_sync_curr'] = pkt.autosyncamp
            row['e501'] = pkt.e501compat
            row['alarm_test'] = pkt.alarmtst
            row['light'] = pkt.backlight
            row['display_test'] = pkt.disptst
            row['temp_sensor'] = pkt.tempsense
            row['aux_hv'] = pkt.auxhv
            row['aux_lv'] = pkt.auxlv
            row['installer_lock'] = pkt.lock
            row['main_hv'] = pkt.mainhv
            row['main_lv'] = pkt.mainlv
            row['low_battery'] = pkt.lowbatalarm
            row['battery_flat'] = pkt.batflat
            row['battery_full'] = pkt.batfull
            row['battery_charged'] = pkt.charged
            row['no_sync'] = pkt.nosync
            row['monitor_reset'] = pkt.monreset
        elif pkt.msgtype == epro.AuxVoltage.MSGTYPE:
            row['aux_voltage'] = pkt.volts

        usedtypes.add(pkt.msgtype)
        if usedtypes >= wantedtypes:
            p.packets = []
            break

    row['tstamp'] = int(datetime.datetime.now().strftime('%s'))
    cur.execute('INSERT INTO eprolog VALUES (:tstamp, :main_voltage, :aux_voltage, :battery_curr, :amp_hours, :state_of_charge, :time_remaining, :battery_temp, :auto_sync_volts, :auto_sync_curr, :e501, :alarm_test, :light, :display_test, :temp_sensor, :aux_hv, :aux_lv, :installer_lock, :main_hv, :main_lv, :low_battery, :battery_flat, :battery_full, :battery_charged, :no_sync, :monitor_reset)', row)

def log_giant(gstat, cur):
    row = {}
    row['ac_act_power'] = gstat['ACActPower']
    row['ac_app_power'] = gstat['ACAppPower']
    row['ac_frequency'] = gstat['ACFreq']
    row['ac_volts'] = gstat['ACVolts']
    row['batt_chr_curr'] = gstat['BattChrCurr']
    row['batt_dis_curr'] = gstat['BattDisCurr']
    row['battery_cap'] = gstat['BattCap']
    row['battery_volts'] = gstat['BattVolts']
    row['batt_volt_ofs'] = gstat['BattVoltOfs']
    row['bus_voltage'] = gstat['BusVolts']
    row['grid_frequency'] = gstat['GridFreq']
    row['grid_volts'] = gstat['GridVolts']
    row['hs_temperature'] = gstat['HSTemp']
    row['load_pct'] = gstat['LoadPct']
    row['pv1_chrg_pow'] = gstat['PVChrgPow1']
    row['pv1_current'] = gstat['PVCurr1']
    row['pv1_volts'] = gstat['PVVolt1']
    row['scc1_volts'] = gstat['SCC1Volt']
    row['scc1_charging'] = gstat['Status']['SCC1Charging']
    row['switch'] = gstat['Status']['Switch']
    row['float_charge'] = gstat['Status']['FloatCharge']
    if gstat['Status']['ChargeType'] == 'Both' or gstat['Status']['ChargeType'] == 'AC':
        row['ac_charging'] = True
    else:
        row['ac_charging'] = False
    row['sbu_prio'] = gstat['Status']['SBUPrio']
    row['b_volt_steady'] = gstat['Status']['BattVoltSteady']
    row['charging'] = gstat['Status']['Charging']

    row['tstamp'] = int(datetime.datetime.now().strftime('%s'))
    cur.execute('INSERT INTO giantlog VALUES(:tstamp, :ac_act_power, :ac_app_power, :ac_frequency, :ac_volts, :batt_chr_curr, :batt_dis_curr, :battery_cap, :battery_volts, :batt_volt_ofs, :bus_voltage, :grid_frequency, :grid_volts, :hs_temperature, :load_pct, :pv1_chrg_pow, :pv1_current, :pv1_volts, :scc1_volts, :scc1_charging, :switch, :float_charge, :ac_charging, :sbu_prio, :b_volt_steady, :charging)', row)

def main():
    dbh = sqlite3.connect('/home/pi/vanlogger/log.db')
    cur = dbh.cursor()
    create(cur)
    s = serial.Serial('/dev/ttyUSB0', 2400, parity='E')
    s.timeout = 0.2

    p = epro.Processor()
    ips = giant.GiantIPS()

    then = None
    while True:
        dolog = False
        if then == None or datetime.datetime.now() - then > datetime.timedelta(seconds = 60):
            dolog = True
            then = datetime.datetime.now()
        p.process(s.read(1024))
        if dolog:
            log_epro(p, cur)
            dbh.commit()

        gstat = None
        try:
            gstat = ips.getStatus()
        except:
            pass
        if gstat != None and dolog:
            log_giant(gstat, cur)
            dbh.commit()
            #print(gstat)

if __name__ == '__main__':
    main()