#!/usr/bin/env python3
'''
Runs rtlamr to watch for IDM broadcasts from power meter. If meter id
is in the list, usage is sent to 'readings/{meter id}/meter_reading'
topic on the MQTT broker specified in settings.

WATCHED_METERS = A Python list indicating those meter IDs to record and post.
MQTT_HOST = String containing the MQTT server address.
MQTT_PORT = An int containing the port the MQTT server is active on.

'''
import time
time.sleep(15)
import subprocess
import signal
import sys
import paho.mqtt.publish as publish
import settings

# uses signal to shutdown and hard kill opened processes and self
def shutdown(signum, frame):
    subprocess.call('/usr/bin/pkill -9 rtlamr', shell=True)
    subprocess.call('/usr/bin/pkill -9 rtl_tcp', shell=True)
    subprocess.call('/usr/bin/pkill -9 amridm2mqtt', shell=True)
    sys.exit(0)

signal.signal(signal.SIGTERM, shutdown)
signal.signal(signal.SIGINT, shutdown)

# stores last interval id to avoid duplication, includes getter and setter
last_reading = {}

auth = None

if len(settings.MQTT_USER) and len(settings.MQTT_PASSWORD):
	auth = {'username':settings.MQTT_USER, 'password':settings.MQTT_PASSWORD}

# send data to MQTT broker defined in settings
def send_mqtt(topic, payload,):
    try:
        publish.single(topic, payload=payload, qos=1, hostname=settings.MQTT_HOST, port=settings.MQTT_PORT, auth=auth)
    except Exception as ex:
        print("MQTT Publish Failed: " + str(ex))

# start the rtl_tcp program
rtltcp = subprocess.Popen([settings.RTL_TCP + " > /dev/null 2>&1 &"], shell=True,
    stdin=None, stdout=None, stderr=None, close_fds=True)
time.sleep(15)

# start the rtlamr program.
rtlamr = subprocess.Popen([settings.RTLAMR,
    '-msgtype=scm',
    '-symbollength=32',
    '-unique=true',
    '-format=csv'], stdout=subprocess.PIPE)

while True:

    try:
        # rtlamr's readline returns byte list, remove whitespace and convert to string
        amrline = rtlamr.stdout.readline().strip().decode()
        # split string on commas
        flds = amrline.split(',')

        if len(flds) != 9:

            # proper SCM results have 9 fields
            continue

        # make sure the meter id is one we want
        meter_id = int(flds[3])
        if len(settings.WATCHED_METERS) and meter_id not in settings.WATCHED_METERS:
            continue

        # get some required info: current meter reading, current interval id, most recent interval usage
        read_cur = int(flds[7])

        meter_type = int(flds[4])
        if(meter_type == 7):
            # Perform WH_MULTIPLIER math only on electric meters
            meter_reading_adj = (read_cur * settings.WH_MULTIPLIER) / 1000
        elif (meter_type == 13):
            # Perform GAL_MULTIPLIER math only on water meters
            meter_reading_adj = (read_cur * settings.GAL_MULTIPLIER) / 1000
        else:
            meter_reading_adj = read_cur

        send_mqtt(
            'readings/' + str(meter_id) + '/meter_reading',
            '%s' % (meter_reading_adj)
        )

    except:
        time.sleep(2)
