#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#commands:
# - vent1 0x1n
#   0x10 Vent1 off 
#   0x11 Vent1 100% 
#   0x12 Vent1 20%
#   ...
#   0x19 Vent1 90%
# - vent2 0x2n
#   0x20 Vent1 off
#   0x21 Vent1 100%
#   0x22 Vent1 20%
#   ...
#   0x29 Vent1 90%
# - temp sensors 0x3n
#   0x31 get Temp1 (4 values)
#   0x32 get Temp2 (4 values)
#   0x33 get Temp3 (4 values)
#   0x34 get Temp4 (4 values) 
# - tacho 0x4n
#   0x41 get Tacho1
#   0x42 get Tacho2
# 

from smbus import SMBus
from time import sleep
import serial
import glob
import json
import paho.mqtt.client as mqtt

port = 1 # (0 for rev.1, 1 for rev 2!)
bus = SMBus(port)
TeensyAddr = 0x20

ser = serial.Serial("/dev/ttyAMA0",baudrate =9600,timeout = .5)
ser.flushInput()
sleep(1)

deviceFolder = glob.glob('/sys/bus/w1/devices/28*')  # find the file
deviceFolderString = deviceFolder[0]
deviceFile = deviceFolderString + '/w1_slave'

clientID = "ventilation"
brokerIP = "192.168.1.60"
brokerPort = 1883
topic  = "weigu/attic/attic/ventilation"
DEBUG=0

# Callback that is executed when the client receives a CONNACK response from the server.
def onConnect(client, userdata, flags, rc):
   if DEBUG: print("Connected with result code " + str(rc))
   mqttc.subscribe(topic, 0)  # Subscribe to the topic (topic name, QoS)

# Callback that is executed when we disconnect from the broker.
def onDisconnect(client, userdata, message):
   if DEBUG: print("Disconnected from the broker.")

# Callback that is executed when subscribing to a topic
def onSubscribe(client, userdata, mid, granted_qos):
   if DEBUG: print('Subscribed on topic.')   

# Callback that is executed when unsubscribing to a topic
def onUnsubscribe(client, userdata, mid, granted_qos):
   if DEBUG: print('Unsubscribed on topic.')
   
# Callback that is executed when a message is received.
def onMessage(client, userdata, message):
    if DEBUG: print('message received:')
    io = message.payload.decode("utf-8");
    #print(io)
    if (io[0:4] != "{\"in"): # ignore own message on same topic
        try:  
             ioj=json.loads(io)
             flow = int(ioj["flow-rate"])
             '''if len(flow)==1 and flow[0:1]=='0':
                 c = 0
             if len(flow)==3 and flow[0:3]=='100':
                 c = 1                      
             if len(flow)==2:
                 flow = int(flow[0:2]) 
                 if (flow/10) in range(2,10):
                     c = flow//10
             print(c)'''
             if (flow/10) in range(2,10):
                 c = flow//10
             if flow == 100:
                 c = 1                 
             if flow > 100:
                 c = 70
             print(c)                 
             rd = bus.write_byte(TeensyAddr,0x10+c)
             sleep(0.001)
             rd = bus.write_byte(TeensyAddr,0x20+c)
             sleep(0.001)

      

        except:
             print("onmessage loop not executed (json error or I2C I/O error?)")

def readTemp():
    try:
        f = open(deviceFile, 'r')
    except IOError:
        print('IOError')
    line1 = f.readline()
    line2 = f.readline()
    f.close()
    pos = line2.find('t=')
    if pos != -1:
        tempString = line2[pos + 2:]
        temp = round(float(tempString) / 1000.0, 1)
    else:
        print('error')
    return temp

#------------------------------------------------------------------------------
# MAIN
#------------------------------------------------------------------------------

mqttc = mqtt.Client(client_id=clientID, clean_session=True) # create client

mqttc.on_connect      = onConnect   # define the callback functions
mqttc.on_disconnect   = onDisconnect
mqttc.on_subscribe    = onSubscribe
mqttc.on_unsubscribe  = onUnsubscribe
mqttc.on_message      = onMessage

#mqttc.username_pw_set(config['MQTT']['userMQTT'], password=config['MQTT']['passwdMQTT'])
mqttc.connect(brokerIP, brokerPort, keepalive=60, bind_address="") # connect to the broker
mqttc.loop_start() # start loop to process callbacks! (new thread!) 

try:
    rd = bus.write_byte(TeensyAddr,0x17)
    sleep(0.001)
    rd = bus.write_byte(TeensyAddr,0x27)
    sleep(0.001)
except:
    print("OSError occured: 121 RemoteI/O error")
            


try:
    while (True):
        SENS=["","","","","","","",""]
        TACHO=["","","",""]        
        for i in range(1,5):
            try:
                d = bus.write_byte(TeensyAddr,0x30+i)
                rd1 = bus.read_byte(TeensyAddr)
                rd2 = bus.read_byte(TeensyAddr)
                STemp = str(round(((rd1*256+rd2)/100),1))
                if i==1:
                    print ("inflow: ", end='')
                elif i==2:
                    print ("outflow: ", end='')
                elif i==3:
                    print ("exhaust: ", end='')
                else:
                    print ("fresh: ", end='')
                print ("temp: " + STemp, end='')
                rd1 = bus.read_byte(TeensyAddr)
                rd2 = bus.read_byte(TeensyAddr)
                SHum = str(round((rd1*256+rd2)/100))
                print ("°C hum: " + SHum, end='')
                print ("%")
                rd1 = bus.read_byte(TeensyAddr)
                rd2 = bus.read_byte(TeensyAddr)
                #print ("Dewp: " + str((rd1*256+rd2)/100) + "°C ",end='')
                rd1 = bus.read_byte(TeensyAddr)
                rd2 = bus.read_byte(TeensyAddr)
                #print ("Humidity@37°C: " + str((rd1*256+rd2)/100) + "%",end='')
                SENS[(i-1)*2]= STemp
                SENS[(i-1)*2+1]= SHum      
            except:
                continue
        for i in range(1,3): # 3 pulses/rotation, speed 3100/min = 5,7*3 = 155 meas: 151
            try:
                rd = bus.write_byte(TeensyAddr,0x40+i)
                rd1 = bus.read_byte(TeensyAddr)
                Tacho = str(rd1)
                Tachop = str(round(rd1*100/151))
                if i==1:
                    print ("tacho out: ", end='')
                else:
                    print ("tacho in:  ", end='')
                print(Tachop, end='')
                print ("%  ", end='')
                print(Tacho)
                TACHO[(i-1)*2] = Tachop
                TACHO[(i-1)*2+1] = Tacho
                
            except:
                continue
        try:
            ser.flushInput()
            ser.write(b"\xFE\x44\x00\x08\x02\x9F\x25")
            sleep(.5)
            resp = ser.read(7)    
            co2 = (resp[3]*256) + resp[4]
            CO2 = str(co2)
            print ("CO2 in ppm: " + CO2)
            sleep(0.1)
        except:
            continue
        ATEMP = str(readTemp())
        print("vent housing temp in °C:",ATEMP)
        sleep(60)
        print('\n')
        #print(SENS,TACHO,CO2,ATEMP)
        mqttc.publish(topic,'{"air_flows":{"in":{"temp_C":' + SENS[0] +
                      ',"hum_%":' + SENS[1] + '},"out":{"temp_C":' +
                      SENS[2] + ',"hum_%":' + SENS[3] + '},"exhaust":'
                      '{"temp_C":' + SENS[4] + ',"hum_%":' + SENS[5] +
                      '},"fresh":{"temp_C":' + SENS[6] + ',"hum_%":' +
                      SENS[7] + '}},"tacho":{"out_%":' + TACHO[0] +
                      ',"out":' + TACHO[1] + ',"in_%":' + TACHO[2] +
                      ',"in":' + TACHO[3] + '},"co2_ppm":' + CO2 +
                      ',"case_temp_C":' + ATEMP + '}')#publish
        
##        try:
##            sleep(0.001)
##            ##rd = bus.read_i2c_block_data(K30Addr,0x08,4)
##            rd = bus.read_byte(K30Addr)
##            print(rd)
##        except:
##            continue

        

except KeyboardInterrupt:
    print("Keyboard interrupt by user")
