#!/usr/bin/python

import types
import traceback
import binascii
import threading
import time
import thread
import os
import struct
import sys
import serial
import minimalmodbus
import pickle
import re
from device_base import deviceBase
import micro800 as u800

import requests
try:
    import json
except:
    import simplejson as json

min_upload_time = 30
addr = '192.168.1.20'





class start(threading.Thread, deviceBase):
    channels = {}
    def updateGPS(self):
        gps = self.mcu.gps
        print("GPS found me at {0}".format(gps))
        self.sendtodb("gps", gps, 0)

    def setupChannels(self):
        with open('drivers/vfd_ipp_channels.p', 'rb') as ch_f:
            self.channels = pickle.load(ch_f)
        print("Channel List\n================")
        for x in self.channels.keys():
            print x
        print("================")

    def __init__(self, name=None, number=None, mac=None, Q=None, mcu=None, companyId=None, offset=None, mqtt=None, Nodes=None):
        threading.Thread.__init__(self)
        deviceBase.__init__(self, name=name, number=number, mac=mac, Q=Q, mcu=mcu, companyId=companyId, offset=offset, mqtt=mqtt, Nodes=Nodes)

        self.daemon = True
        self.version = "2"
        self.device_address = addr
        self.finished = threading.Event()
        threading.Thread.start(self)
        self.sendtodbJSON("device_address", self.device_address, 0)
        self.setupChannels()
        # self.run()


        # self.updateGPS()
    # this is a required function for all drivers, its goal is to upload some piece of data
    # about your device so it can be seen on the web
    def register(self):
        self.channels["status"]["last_value"] = ""

    def run(self):
        print("****************\n*************\nEXECUTING RUN\n********************\n****************")
        self.runLoopStatus = ""
        last_OK_state = 0
        while True:
            if len(self.channels) > 0:
                try:
                    for i in self.channels:
                        runLoopStatus = i
                        print("reading {0}".format(i))
                        valData = u800.readMicroTag(self.device_address, self.channels[i]['tag'])
                        print(valData)
                        if valData:
                            nowVal = valData[0]
                            ch = self.channels[i]
                            if ch['data_type'] == "BOOL":
                                if ch['last_value'] == "":
                                    self.sendtodbJSON(i, nowVal, 0)
                                    ch['last_time_uploaded'] = time.time()
                                    ch['last_value'] = nowVal
                                elif (not (ch['last_value'] == nowVal)) or ((time.time() - ch['last_time_uploaded']) > ch['max_time_between_uploads']):
                                    self.sendtodbJSON(i, nowVal, 0)
                                    ch['last_time_uploaded'] = time.time()
                                    ch['last_value'] = nowVal
                            if (ch['data_type'] == "REAL") or (ch['data_type'][-3:] == "INT"):
                                if ch['last_value'] == "":
                                    self.sendtodbJSON(i, nowVal, 0)
                                    ch['last_time_uploaded'] = time.time()
                                    ch['last_value'] = nowVal
                                elif (abs(ch['last_value'] - nowVal) > ch['change_amount']) or ((time.time() - ch['last_time_uploaded']) > ch['max_time_between_uploads']):
                                    self.sendtodbJSON(i, nowVal, 0)
                                    ch['last_time_uploaded'] = time.time()
                                    ch['last_value'] = nowVal

                    runLoopStatus = "Complete"
                    OK_state = 1
                    if not OK_state == last_OK_state:
                        self.sendtodbJSON("driver_ok", OK_state, 0)
                        last_OK_state = OK_state
                    time.sleep(10)
                except Exception, e:
                    OK_state = 0
                    if not OK_state == last_OK_state:
                        self.sendtodbJSON("driver_ok", OK_state, 0)
                        last_OK_state = OK_state
                    sleep_timer = 30
                    print "Error during {0} of run loop: {1}\nWill try again in {2} seconds...".format(runLoopStatus, e, sleep_timer)
                    time.sleep(sleep_timer)
            else:
                print("Apparently no self.channels... length shows {0}".format(len(self.channels)))
                print self.channels
                self.setupChannels()
                time.sleep(30)
    def write_vfdconfig(self):
        print("Writing config to drive")
        return u800.writeMicroTag(addr, 'VFD_Write', 1)

    def vfdipp_sync(self, name, value):
        self.sendtodb("connected", "true", 0)
        return True

    def vfdipp_address(self, name, value):
        self.device_address = value
        return True

    def vfdipp_gpsUpdate(self, name, value):
        updateGPS()
        return True

    def vfdipp_dhpressurestartupenabled(self, name, value):
        print('trying to set DH_Pressure_Startup_Enabled to {0}'.format(value))
        return u800.writeMicroTag(addr, 'DH_Pressure_Startup_Enabled', int(value))

    def vfdipp_vfddisabled(self, name, value):
        print('trying to set VFD_Disabled to {0}'.format(value))
        return u800.writeMicroTag(addr, 'VFD_Disabled', int(value))

    def vfdipp_vfdnameplatefla(self, name, value):
        print('trying to set cfg_NameplateFLA to {0}'.format(value))
        if u800.writeMicroTag(addr, 'cfg_NameplateFLA', float(value)):
            return self.write_vfdconfig()
        else:
            return False

    def vfdipp_dhpressurestartup(self, name, value):
        print('trying to set DH_Pressure_Startup to {0}'.format(value))
        return u800.writeMicroTag(addr, 'DH_Pressure_Startup', float(value))

    def vfdipp_automode(self, name, value):
        print('trying to set Auto_Mode to {0}'.format(value))
        return u800.writeMicroTag(addr, 'Auto_Mode', int(value))

    def vfdipp_vfdmotorpoles(self, name, value):
        print('trying to set cfg_MotorPoles to {0}'.format(value))
        if u800.writeMicroTag(addr, 'cfg_MotorPoles', int(value)):
            return self.write_vfdconfig()
        else:
            return False

    def vfdipp_tubingpressurealarmdelay(self, name, value):
        print('trying to set TubingPressure_Alarm_Delay to {0}'.format(value))
        return u800.writeMicroTag(addr, 'TubingPressure_Alarm_Delay', int(value))

    def vfdipp_dhtempshutdown(self, name, value):
        print('trying to set DH_Temp_Shutdown to {0}'.format(value))
        return u800.writeMicroTag(addr, 'DH_Temp_Shutdown', float(value))

    def vfdipp_dhtempstartuplimit(self, name, value):
        print('trying to set DH_Temp_Startup to {0}'.format(value))
        return u800.writeMicroTag(addr, 'DH_Temp_Startup', float(value))

    def vfdipp_vfdmaxfreq(self, name, value):
        print('trying to set cfg_MaxFreq to {0}'.format(value))
        if u800.writeMicroTag(addr, 'cfg_MaxFreq', float(value)):
            return self.write_vfdconfig()
        else:
            return False

    def vfdipp_tubingpressurelosp(self, name, value):
        print('trying to set TubingPressure_Lo_SP to {0}'.format(value))
        return u800.writeMicroTag(addr, 'TubingPressure_Lo_SP', float(value))

    def vfdipp_vfdacceltime(self, name, value):
        print('trying to set VFD_AccelTime to {0}'.format(value))
        return u800.writeMicroTag(addr, 'VFD_AccelTime', float(value))

    def vfdipp_vfdnameplateolcurrent(self, name, value):
        print('trying to set cfg_NameplateOLCurrent to {0}'.format(value))
        if u800.writeMicroTag(addr, 'cfg_NameplateOLCurrent', float(value)):
            return self.write_vfdconfig()
        else:
            return False

    def vfdipp_offmode(self, name, value):
        print('trying to set Off_Mode to {0}'.format(value))
        return u800.writeMicroTag(addr, 'Off_Mode', int(value))

    def vfdipp_tubingpressurealarmstartupdelay(self, name, value):
        print('trying to set TubingPressure_Alarm_Startup_Delay to {0}'.format(value))
        return u800.writeMicroTag(addr, 'TubingPressure_Alarm_Startup_Delay', int(value))

    def vfdipp_dhpressureshutdownenabled(self, name, value):
        print('trying to set DH_Pressure_Shutdown_Enabled to {0}'.format(value))
        return u800.writeMicroTag(addr, 'DH_Pressure_Shutdown_Enabled', int(value))

    def vfdipp_dhtempshutdownenabled(self, name, value):
        print('trying to set DH_Temp_Shutdown_Enabled to {0}'.format(value))
        return u800.writeMicroTag(addr, 'DH_Temp_Shutdown_Enabled', int(value))

    def vfdipp_tubingpressureeumin(self, name, value):
        print('trying to set TubingPressure_EU_Min to {0}'.format(value))
        return u800.writeMicroTag(addr, 'TubingPressure_EU_Min', float(value))

    def vfdipp_vfddeceltime(self, name, value):
        print('trying to set VFD_DecelTime to {0}'.format(value))
        return u800.writeMicroTag(addr, 'VFD_DecelTime', float(value))

    def vfdipp_vfdnameplaterpm(self, name, value):
        print('trying to set cfg_NameplateRPM to {0}'.format(value))
        if u800.writeMicroTag(addr, 'cfg_NameplateRPM', float(value)):
            return self.write_vfdconfig()
        else:
            return False

    def vfdipp_vfdspeedref(self, name, value):
        print('trying to set VFD_SpeedRef to {0}'.format(value))
        return u800.writeMicroTag(addr, 'VFD_SpeedRef', float(value))

    def vfdipp_tubingpressureeumax(self, name, value):
        print('trying to set TubingPressure_EU_Max to {0}'.format(value))
        return u800.writeMicroTag(addr, 'TubingPressure_EU_Max', float(value))

    def vfdipp_handmode(self, name, value):
        print('trying to set Hand_Mode to {0}'.format(value))
        return u800.writeMicroTag(addr, 'Hand_Mode', int(value))

    def vfdipp_tubingpressurehisp(self, name, value):
        print('trying to set TubingPressure_Hi_SP to {0}'.format(value))
        return u800.writeMicroTag(addr, 'TubingPressure_Hi_SP', float(value))

    def vfdipp_remoteshutdowndisabled(self, name, value):
        print('trying to set Remote_Shutdown_Disabled to {0}'.format(value))
        return u800.writeMicroTag(addr, 'Remote_Shutdown_Disabled', int(value))

    def vfdipp_dhpressureshutdownlimit(self, name, value):
        print('trying to set DH_Pressure_Shutdown to {0}'.format(value))
        return u800.writeMicroTag(addr, 'DH_Pressure_Shutdown', float(value))

    def vfdipp_vfdnameplatevolts(self, name, value):
        print('trying to set cfg_NameplateVolts to {0}'.format(value))
        if u800.writeMicroTag(addr, 'cfg_NameplateVolts', float(value)):
            return self.write_vfdconfig()
        else:
            return False

    def vfdipp_downholetoolenabled(self, name, value):
        print('trying to set Downhole_Tool_Enabled to {0}'.format(value))
        return u800.writeMicroTag(addr, 'Downhole_Tool_Enabled', int(value))

    def vfdipp_vfdnameplatehz(self, name, value):
        print('trying to set cfg_NameplateHz to {0}'.format(value))
        if u800.writeMicroTag(addr, 'cfg_NameplateHz', float(value)):
            return self.write_vfdconfig()
        else:
            return False

    def vfdipp_tubingpressuretransducerenabled(self, name, value):
        print('trying to set TubingPressure_Transducer_Enabled to {0}'.format(value))
        return u800.writeMicroTag(addr, 'TubingPressure_Transducer_Enabled', int(value))

    def vfdipp_dhtempstartupenabled(self, name, value):
        print('trying to set DH_Temp_Startup_Enabled to {0}'.format(value))
        return u800.writeMicroTag(addr, 'DH_Temp_Startup_Enabled', int(value))

    def vfdipp_vfdnameplatehp(self, name, value):
        print('trying to set cfg_NameplateHP to {0}'.format(value))
        if u800.writeMicroTag(addr, 'cfg_NameplateHP', float(value)):
            return self.write_vfdconfig()
        else:
            return False

    def vfdipp_vfdminfreq(self, name, value):
        print('trying to set cfg_MinFreq to {0}'.format(value))
        if u800.writeMicroTag(addr, 'cfg_MinFreq', float(value)):
            return self.write_vfdconfig()
        else:
            return False

    def vfdipp_startcommand(self, name, value):
        print('trying to set Start_Command to 1')
        if u800.writeMicroTag(addr, 'Start_Command', 1):
            print("Set Start_Command to 1")
            time.sleep(3)
            return u800.writeMicroTag(addr, 'Start_Command', 0)
        else:
            print("Couldn't set Start_Command to 1")
            return False

    def vfdipp_stopcommand(self, name, value):
        print('trying to set Stop_Command to 1')
        if u800.writeMicroTag(addr, 'Stop_Command', 1):
            print("Set Stop_Command to 1")
            time.sleep(3)
            return u800.writeMicroTag(addr, 'Stop_Command', 0)
        else:
            print("Couldn't set Stop_Command to 1")
            return False

    def vfdipp_vfdclearfault(self, name, value):
        print('trying to set VFD_ClearFault to 1')
        if u800.writeMicroTag(addr, 'VFD_ClearFault', 1):
            print("Set VFD_ClearFault to 1")
            time.sleep(3)
            return u800.writeMicroTag(addr, 'VFD_ClearFault', 0)
        else:
            print("Couldn't set VFD_ClearFault to 1")
            return False
