# ---------------------------------------------------------------------------------------------------------------------------------------------------------------
#
#   rtl_433_wrapper.py
#
#   Wrapper script for executing "rtl_433" and processing the output as it occurs in realtime.
#   As currently written it works with the "Aculink 986" refrigerator and freezer temperature monitor.
#
#   >>>---> Changes to handle other makes/models will likely be necessary, possibly to the rtl_433 source as well because ouputting data
#           as JSON hasn't been implemented in  all of the protocol handlers :-/
#
#   The goal is to be able to use "rtl_433" unmodified so that is easy to stay current as support for additional devices/protocols are added.
#   Note: To make this "real" some refactoring of the rtl_433 source will be needed to add consistent support for JSON across the various protocol handlers.
#
# --------------------------------------------------------------------------------------------------------------------------------------------------------------
import sys
from subprocess import PIPE, Popen, STDOUT
from threading  import Thread
#import json
import datetime

# ---------------------------------------------------------------------------------------------------------------------------------------------------------------

cmd = [ '/usr/local/bin/rtl_433', '-q', '-F', 'json', '-R', '40']

# ---------------------------------------------------------------------------------------------------------------------------------------------------------------
#   A few helper functions...

def nowStr():
    return( datetime.datetime.now().strftime( '%Y-%m-%d %H:%M:%S'))

# ---------------------------------------------------------------------------------------------------------------------------------------------------------------
#stripped = lambda s: "".join(i for i in s if 31 < ord(i) < 127)


#   We're using a queue to capture output as it occurs
try:
    from Queue import Queue, Empty
except ImportError:
    from queue import Queue, Empty  # python 3.x
ON_POSIX = 'posix' in sys.builtin_module_names

def enqueue_output(src, out, queue):
    for line in iter(out.readline, b''):
        queue.put(( src, line))
    out.close()

#   Create our sub-process...
#   Note that we need to either ignore output from STDERR or merge it with STDOUT due to a limitation/bug somewhere under the covers of "subprocess"
#   > this took awhile to figure out a reliable approach for handling it...
p = Popen( cmd, stdout=PIPE, stderr=STDOUT, bufsize=1, close_fds=ON_POSIX)
q = Queue()

t = Thread(target=enqueue_output, args=('stdout', p.stdout, q))

t.daemon = True # thread dies with the program
t.start()

# ---------------------------------------------------------------------------------------------------------------------------------------------------------------

pulse = 0
while True:
    #   Other processing can occur here as needed...
    #sys.stdout.write('Made it to processing step. \n')

    try:
        src, line = q.get(timeout = 1)
    except Empty:
        pulse += 1
    else: # got line
        pulse -= 1
        #   See if the data is something we need to act on...
        if ( line.find( 'Acurite') != -1):
            #sys.stdout.write('This is the raw data: ' + line + '\n')
            dt = line[0:19] # pull out date time
            tm = line.find(": ",20) # find end of sensor description
            sens = line[20:tm] # pull out sensor description
            tv =line.find("C") # find F temp start
            ft =line[tv+1:len(line)-2] # pull F temp
            ct =line[tm+1:tv] # pull C temp
            rorf = sens[len(sens)-1] # pull R for sensor 1, F for sensor 2
            sys.stdout.write('These are the fields: \n' + dt +'\n' + sens +'\n' + ft + '\n' + ct + '\n' + rorf + '\n')
            
            #This is the raw data: 2017-01-12 10:49:27 Acurite 986 sensor 0x5c32 - 1R: 2.2 C 36 F
            #This is the raw data: 2017-01-12 10:50:55 Acurite 986 sensor 0xf653 - 2F: -15.0 C 5 F

# Change /home/pi/Documents/FreezerProjects/R1.dat to the path you want

            if (rorf == 'R'):
                with open("/home/pi/Documents/FreezerProjects/R1.dat","w") as fr:
                    fr.write("t= " + ft)
                with open("/home/pi/Documents/FreezerProjects/Stats.csv","a") as gr:
                    gr.write(dt + "," + rorf + "," + ft + "\n")
            else:
                with open("/home/pi/Documents/FreezerProjects/F1.dat", "w") as ff:
                    ff.write("t= " + ft)
                with open("/home/pi/Documents/FreezerProjects/Stats.csv","a") as gg:
                    gg.write(dt + "," + rorf + "," + ft + "\n")
                
        else:
            False
            sys.stdout.write( nowStr() + ' - stderr: ' + line)
            if (( line.find( 'Failed') != -1) or ( line.find( 'No supported devices') != -1)):
                sys.stdout.write( '   >>>---> ERROR, exiting...\n\n')
                exit( 1)

    sys.stdout.flush()
