current commit
210418.5 · bin: more tweaks to voltage detector
#!/usr/bin/env /home/andrew/clones/sense/ve/bin/python

import csv
import json
import subprocess
import time

import sense_energy

LOG_CSV_FILE = '/m/data/home/sense/realtime.csv'
USERNAME = 'jamslam@gmail.com'
PASS_PATH = 'home/sense'
FIELDS = ['ts', 'datetime', 'volt', 'volt1', 'volt2', 'hertz', 'watts', 'raw']
LOG_EVERY = 1000
BACKOFF = 10  # seconds to wait if a timeout occurs
DIALECT = csv.unix_dialect
DIALECT.quoting = csv.QUOTE_MINIMAL


def get_password():
    stdout = subprocess.check_output(['pass', 'home/sense'])
    return stdout.decode('utf-8').splitlines()[0].strip()


def timestamp_to_datetime(ts):
    # I remember in the Python 2 days, doing this required a third party
    # package and it was a huge pain. Maybe Python 3 has solved it, but this
    # is just so much simpler.
    cmd = ['date', '-d', f'@{ts}']
    return subprocess.check_output(cmd).decode('utf-8').strip()


def loop(wtr, password):
    last_log = time.time()

    sense = sense_energy.Senseable()
    sense.authenticate(USERNAME, password)
    sense.update_realtime()
    for i, v in enumerate(sense.get_realtime_stream()):
        ts = time.time()
        voltage = v.get('voltage', [0.0, 0.0])
        wtr.writerow({
            'ts': ts,
            'datetime': timestamp_to_datetime(ts),
            'volt': voltage[0] + voltage[1],
            'volt1': voltage[0],
            'volt2': voltage[1],
            'hertz': v.get('hz', 0.0),
            'watts': v.get('w', 0.0),
            'raw': json.dumps(v),
        })
        if i == 0 or i % LOG_EVERY != 0:
            continue
        diff = time.time() - last_log
        print(f'logged {LOG_EVERY} events in {diff:0.03} seconds')
        last_log = time.time()


if __name__ == '__main__':
    password = get_password()
    print(f'{LOG_CSV_FILE}: writing Sense realtime data events to log')
    with open(LOG_CSV_FILE, mode='a', buffering=1) as out:
        wtr = csv.DictWriter(
            out,
            fieldnames=FIELDS,
            dialect=DIALECT,
        )
        while True:
            try:
                loop(wtr, password)
            except sense_energy.sense_exceptions.SenseAPITimeoutException:
                print(
                    f'WebSocket Sense API timeout, sleeping for {BACKOFF} '
                    f'seconds before starting again',
                )
                time.sleep(BACKOFF)
                print('starting main loop again...')