#!/usr/bin/python2.6

# Rev 5 - moving through these quickly...

# I have made some changes to the Mate class, to make things simpler here.
# It now uses ints and floats, so I will also use those in the DB.  It also
# has a new 'scanGet' method that returns the dictionary for the device that
# was updated on a given scan.  (Do I need to return the slot number too?
# I don't need it *now*, but that would be useful if I had multiples of a
# device...)

from mate_enum_gl import Mate
from jacexml import Jace
from datetime import datetime
import sqlite3
import time

serport = '/dev/mate'
ser = Mate(serport)

server = 'server.name'
user = 'user.name'
passwd = 'password'
jace = Jace (server, user, passwd)

dbname = 'logger.dbname'
dbconn = sqlite3.connect (dbname)
db = dbconn.cursor()

# Set up the tables if needed...
db.execute ("""create table if not exists FX (ts timestamp, battVolts float,
        fxMode int, acOutVolts int, sellAmps int, acInVolts int,
        buyAmps int, chgAmps int, invAmps int)""")

db.execute ("""create table if not exists CC (ts timestamp, battVolts float, 
        auxMode int, chgMode int, pvVolts int, pvAmps int, chgAmps float,
        dailyAH int, dailykWh float)""")

db.execute ("""create table if not exists DC (ts timestamp, aAmps float, 
        bAmps float, battTemp int, chgParmsMet int, aAccumAH int, 
        aAccumKWH float, bAccumAH int, bAccumKWH float, daysSinceFull float,
        todayMinSOC int, todayNetInAH int, todayNetOutAH int, 
        todayNetInKWH float, todayNetOutKWH float, battNetInOut int)""")


# Logging values.  These are the only values that will be checked to see
# if an update needs to occur, also sets the deadband for each one.  Also
# sets the min update time (seconds) should no changes occur.

fxDeltas = {'battVolts':0.2, 'fxMode':0, 'acInVolts':10}
fxMinWrite = 600

ccDeltas = {'battVolts': 0.2, 'auxMode':0, 'chgMode':0, 'pvVolts':2,
        'chgAmps':0.5, 'dailyAH':0}
ccMinWrite = 600

dcDeltas = {'aAmps':0.5, 'bAmps':0.5, 'battTemp':1, 'chgParmsMet':0,
        'aAccumAH':0, 'bAccumAH':0, 'todayMinSOC':0, 'todayNetInAH':0,
        'todayNetOutAH':0, 'battNetInOut':0}
dcMinWrite = 600

jaceIntvl = 5


# Check the supplied dicts for deltas...
def checkD (newD, lastD, deltas):
    update = False
    for key in deltas:
        if key not in lastD or abs(newD[key] - lastD[key]) > deltas[key]:
            update = True

    return update


# Write FX data...
def fxWrite (newD):
    values = ['battVolts', 'fxMode', 'acOutVolts', 'sellAmps', 'acInVolts',
            'buyAmps', 'chgAmps', 'invAmps']

    l = [datetime.today()]
    for value in values:
        l.append(newD[value])

    db.execute ("insert into FX values (?, ?, ?, ?, ?, ?, ?, ?, ?)", tuple(l))
    dbconn.commit()


# Write CC data...
def ccWrite (newD):
    values = ['battVolts', 'auxMode', 'chgMode', 'pvVolts', 'pvAmps',
            'chgAmps', 'dailyAH', 'dailykWh']

    l = [datetime.today()]
    for value in values:
        l.append(newD[value])

    db.execute ("insert into CC values (?, ?, ?, ?, ?, ?, ?, ?, ?)", tuple(l))
    dbconn.commit()


# Write DC data...
# DC won't always have all values present, must check for existence...
def dcWrite (newD):
    values = ['aAmps', 'bAmps', 'battTemp', 'chgParmsMet', 'aAccumAH', 
            'aAccumKWH', 'bAccumAH', 'bAccumKWH', 'daysSinceFull', 
            'todayMinSOC', 'todayNetInAH', 'todayNetOutAH', 'todayNetInKWH',
            'todayNetOutKWH', 'battNetInOut']

    l = [datetime.today()]
    for value in values:
        if value in newD:
            l.append(newD[value])
        else:
            l.append(0)

    db.execute ("insert into DC values (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)", tuple(l))
    dbconn.commit()


# Now, loop and read...
lastFX = {}
lastCC = {}
lastDC = {}

fxLastWrite = 0
ccLastWrite = 0
dcLastWrite = 0

jaceLastWrite = 0

while 1:
    newD = ser.scanGet(jace.fxModeCmd, jace.fxAuxCmd)

    if time.time() - jaceLastWrite > jaceIntvl:
        data = ser.getDevices()
        jace.update (data)
        jaceIntvl = time.time()

    if newD['dev'] == 'FX':
        if checkD (newD, lastFX, fxDeltas) or \
            time.time() - fxLastWrite > fxMinWrite:
            
            fxWrite (newD)
            lastFX = newD.copy()
            fxLastWrite = time.time()

    elif newD['dev'] == 'CC':
        if checkD (newD, lastCC, ccDeltas) or \
            time.time() - ccLastWrite > ccMinWrite:

            ccWrite (newD)
            lastCC = newD.copy()
            ccLastWrite = time.time()

    elif newD['dev'] == 'DC':
        if checkD (newD, lastDC, dcDeltas) or \
            time.time() - dcLastWrite > dcMinWrite:

            dcWrite (newD)
            lastDC = newD.copy()
            dcLastWrite = time.time()




