#!/usr/bin/python
import sys
#import Gpib
import random
import imp
import vxi11
import time
import numpy as np

rangev = 10
rangev2 = 2
if (rangev == 10e-3):
    range_lbl = "10m"
elif (rangev == 100e-3):
    range_lbl = "100m"
elif (rangev == 1):
    range_lbl = "1"
elif (rangev == 10):
    range_lbl = "10"
elif (rangev == 20):
    range_lbl = "20"
elif (rangev == 100):
    range_lbl = "100"
elif (rangev == 200):
    range_lbl = "200"
elif (rangev == 1000):
    range_lbl = "1k"

dval  = " XHP3458A  "
dval2 = " XHP3459X  "
dval3 = " XHP3458FF "
dval4 = " K2002LTC  "
dval5 = " D1281-F   "
dval6 = " HP34420A-1"
dval7 = " HP34401A  "
dval8 = " K2001     "
dval9 = " K2001M    "

nplc = 10
min_volt = -2.099
max_volt = -min_volt
soak_time = 8
use_samples = 3

fname = "../teckit/dcl_rnd_2vdut_%sv_h1_k2001_nplc%d_soak%ds_comp_samples-%d_jun2026" % (range_lbl, nplc, soak_time, use_samples)
log_name = fname + ".dsv"
logr_name = fname + "_raw.dsv"

ext_temp     = 0.0
ext_rh       = 0.0
ext_pressure = 1000.0
thp = imp.load_source('f1620' , 'thp_client.py')              # Load Fluke 1620 support
env_sensor = thp.THP_socket('192.168.1.11', 10001 )

def read_environment():
    global ext_temp, ext_rh, ext_pressure
    error, stemp, srh, spressure = env_sensor.getTHP()
    ext_temp = float(stemp)
    ext_rh = float(srh)
    ext_pressure = float(spressure)

#fluke = Gpib.Gpib(0, 1, timeout=30) 
fluke = vxi11.Instrument("192.168.1.10", "gpib0,2") # Fluke 5720A, GPIB Address = 1
fluke.timeout = 30
#fluke.clear()
fluke.write("*IDN?")
print ("Source detected = %s" % fluke.read())

dmm = vxi11.Instrument("192.168.1.10", "gpib0,1") # Keysight 3458A
dmm.timeout = 30

dmm2 = vxi11.Instrument("192.168.1.12", "gpib0,11") # Keysight 3459X-X9D
dmm2.timeout = 30

dmm3 = vxi11.Instrument("192.168.1.12", "gpib0,18") # Keysight-xDevs 3458FF
dmm3.timeout = 30

dmm4 = vxi11.Instrument("192.168.1.12", "gpib0,6") # K2002LTC
dmm4.timeout = 30

dmm5 = vxi11.Instrument("192.168.1.10", "gpib0,8") # D1281
dmm5.timeout = 30

dmm6 = vxi11.Instrument("192.168.1.12", "gpib0,13") # HP34420A CH1
dmm6.timeout = 30

dmm7 = vxi11.Instrument("192.168.1.12", "gpib0,23") # HP34401
dmm7.timeout = 60

dmm8 = vxi11.Instrument("192.168.1.10", "gpib0,22") # K2001
dmm8.timeout = 60

dmm9 = vxi11.Instrument("192.168.1.12", "gpib0,27") # K2001M
dmm9.timeout = 60

fluke.write("STBY")
print ("MFC SRC prepare...")
fluke.write("RANGELCK OFF")
fluke.write("OUT 2 V, 0 Hz")
fluke.write("RANGELCK ON")
fluke.write("EXTSENSE OFF")
fluke.write("EXTGUARD OFF")
fluke.write("STBY")
fluke.write("OUT 0.0 V, 0 Hz")
fluke.write("EXTGUARD OFF")
fluke.write("OPER")
time.sleep(3)
print ("MFC SRC configured 10V")

dmm.write("BEEP")
dmm.write("END ALWAYS")
dmm.write("DCV %.3f" % rangev)
dmm.write("NPLC %.3f" % nplc)
dmm.write("NDIG 8")
dmm.write("TRIG AUTO")
dmm.write("MATH OFF")
print ("DMM1 configured")

dmm2.write("BEEP")
dmm2.write("END ALWAYS")
dmm2.write("DCV %.3f" % rangev)
dmm2.write("NPLC %.3f" % nplc)
dmm2.write("NDIG 8")
dmm2.write("TRIG AUTO")
dmm2.write("MATH OFF")
print ("DMM2 configured")

dmm3.write("BEEP")
dmm3.write("END ALWAYS")
dmm3.write("DCV %.3f" % rangev)
dmm3.write("NPLC %.3f" % nplc)
dmm3.write("NDIG 8")
dmm3.write("TRIG AUTO")
dmm3.write("MATH OFF")
print ("DMM3 configured")

# K2002
dmm4.write("*RST")
dmm4.write(":INIT:CONT OFF")
dmm4.write(":SYST:PRES")
dmm4.write(":FORM:ELEM READ")
dmm4.write(":SYST:AZER:STAT ON")
dmm4.write(":ABOR")
dmm4.write(":INP:PRE:STAT 0")
dmm4.write(":SENS:FUNC 'VOLT:DC'")
dmm4.write(":SENS:VOLT:DC:RANG %.3f" % rangev2)
dmm4.write(":SENS:VOLT:DC:NPLC %.2f" % nplc)
dmm4.write(":SENS:VOLT:DC:AVER:STAT OFF")
dmm4.write(":SENS:VOLT:DC:DIG 9")
print ("DUT4 configured")

dmm5.write("*RST")
dmm5.write("TRG_SRCE EXT")
dmm5.write("DCV %.2f,FILT_OFF,RESL8,FAST_OFF" % rangev2)
dmm5.write("GUARD INT")
dmm5.write("AVG OFF")
dmm5.write("INPUT FRONT")
#dmmd.write("GATE FAST_OFF")
#dmmd.write("C LAST_RDG")
#dmmd.write("SUB_C OFF")
print "DUT5 configured"

# HP34420A
dmm6.write("*RST")
dmm6.write(":SENS:FUNC 'VOLT:DC'")
dmm6.write(":ROUT:TERM FRON1")
dmm6.write(":SENS1:VOLT:NPLC %.3f" % nplc)
dmm6.write(":SENS1:VOLT:RES MIN")
dmm6.write(":SENS1:VOLT:RANG %.2f" % rangev)
print ("HP34420 configured")

# HP34401A
dmm7.write("*RST")
dmm7.write(":SENS:FUNC 'VOLT:DC'")
dmm7.write(":SENS:FUNC 'VOLT:DC'")
dmm7.write(":SENS:VOLT:DC:NPLC %.3f" % nplc)
dmm7.write(":SENS:VOLT:DC:RANG %.2f" % rangev)
print ("HP34401A configured")

'''
#dmm5.write("*RST")
dmm5.write(":INIT:CONT OFF")
dmm5.write(":SYST:PRES")
dmm5.write(":FORM:ELEM READ")
dmm5.write(":SYST:AZER:STAT ON")
dmm5.write(":ABOR")
dmm5.write(":SENS:FUNC 'VOLT:DC'")
dmm5.write(":INP:PRE:STAT OFF")
dmm5.write(":SENS:VOLT:DC:RANG 10")
dmm5.write(":SENS:VOLT:DC:NPLC 20")
dmm5.write(":SENS:VOLT:DC:AVER:STAT OFF")
dmm5.write(":SENS:VOLT:DC:DIG 9")
print ("DUT5 configured")

#dmm6.write("*RST")
dmm6.write(":INIT:CONT OFF")
dmm6.write(":SYST:PRES")
dmm6.write(":FORM:ELEM READ")
dmm6.write(":SYST:AZER:STAT ON")
dmm6.write(":ABOR")
dmm6.write(":SENS:FUNC 'VOLT:DC'")
dmm6.write(":INP:PRE:STAT OFF")
dmm6.write(":SENS:VOLT:DC:RANG 10")
dmm6.write(":SENS:VOLT:DC:NPLC 20")
dmm6.write(":SENS:VOLT:DC:AVER:STAT OFF")
dmm6.write(":SENS:VOLT:DC:DIG 9")
print ("DUT6 configured")
'''
dmm8.write("*RST")
dmm8.write(":INIT:CONT OFF")
dmm8.write(":SYST:PRES")
dmm8.write(":FORM:ELEM READ")
dmm8.write(":SYST:AZER:STAT ON")
dmm8.write(":SENS:VOLT:DIG 8")
dmm8.write(":ABOR")
dmm8.write(":SENS:FUNC 'VOLT:DC'")
dmm8.write(":SENS:VOLT:DC:NPLC %.2f" % nplc)
dmm8.write(":SENS:VOLT:DC:RANG %.2f" % rangev2)

dmm9.write("*RST")
dmm9.write(":INIT:CONT OFF")
dmm9.write(":SYST:PRES")
dmm9.write(":FORM:ELEM READ")
dmm9.write(":SYST:AZER:STAT ON")
dmm9.write(":SENS:VOLT:DIG 8")
dmm9.write(":ABOR")
dmm9.write(":SENS:FUNC 'VOLT:DC'")
dmm9.write(":SENS:VOLT:DC:NPLC %.2f" % nplc)
dmm9.write(":SENS:VOLT:DC:RANG %.2f" % rangev2)
print ("K2001s configured")

'''
dmm.write("ACAL DCV")
dmm2.write("ACAL DCV")
dmm3.write("ACAL DCV")
print ("HP3458s started ACAL DCV")
#dmm4.write("ACAL DCV")
#dmm5.write("ACAL DCV")
#dmm6.write("ACAL DCV")
time.sleep(147)
'''

'''
for vcnt in range (0,2):
    dmm3.write("*TRG;GET;RDG?")
    dmm3.read()
    dmm4.write("READ?") # Get reading
    dmm4.read()
'''
#dmm.write("TARM SGL")
#dmm.read()
#dmm2.write("TARM SGL")
#dmm2.read()
#dmm3.write("TARM SGL")
#dmm3.read()
#dmm4.write("TARM SGL")
#dmm4.read()
#dmm4.write("TARM SGL")
#dmm4.read()
#dmm5.write("TARM SGL") # Get reading
#dmm5.read()
#dmm6.write("TARM SGL") # Get reading
#dmm6.read()

#dmm.write("MATH NULL")
#dmm2.write("MATH NULL")
#dmm3.write("MATH NULL")
#dmm4.write("MATH NULL")
#dmm5.write("MATH NULL")
#dmm6.write("MATH NULL")
#dmm3.write("SUB_C OFF") # Null math
#dmm.write("TARM SGL") # Get reading
#dmm.read()
#dmm2.write("TARM SGL") # Get reading
#dmm2.read()
#dmm3.write("TARM SGL") # Get reading
#dmm3.read()
#dmm3.write("*TRG;GET;RDG?") # Get reading
#dmm3.read()
#dmm4.write("READ?") # Get reading
#dmm4.read()
#print ("HP3458s nulled")

with open(log_name, 'a') as dile:
    dile.write ("date;source;3458b;3459x;3458ff;2002ltc;d1281;h34420a;h34401;k2001;k2001m;sdev;sdev2;sdev3;sdev4;sdev5;sdev6;sdev7;sdev8;sdev9;temp;temp2;temp3;temp4;temp5;roomtemp;roomr;roomp;\r\n")
dile.close()

with open(logr_name, 'a') as dilr:
    dilr.write ("date;source;3458b;3459x;3458ff;2002ltc;d1281;h34420a;h34401;k2001;k2001m;sdev;sdev2;sdev3;sdev4;sdev5;sdev6;sdev7;sdev8;sdev9;temp;temp2;temp3;temp4;temp5;roomtemp;roomr;roomp;\r\n")
dilr.close()

vcnt = 0 # temporary counter
print ("Log into %s started" % log_name)

read_environment()
print ("Ambient temp: %.3f C , Humidity: %.1f %%, Pressure : %.2f hPa" % (ext_temp, ext_rh, ext_pressure))

for i in range(0,2000,1):
    median = 0.0
    sdev = 0.0
    array = []
    median2 = 0.0
    sdev2 = 0.0
    array2 = []
    median3 = 0.0
    sdev3 = 0.0
    array3 = []
    median4 = 0.0
    sdev4 = 0.0
    array4 = []
    median5 = 0.0
    sdev5 = 0.0
    array5 = []
    median6 = 0.0
    sdev6 = 0.0
    array6 = []
    median7 = 0.0
    sdev7 = 0.0
    array7 = []
    median8 = 0.0
    sdev8 = 0.0
    array8 = []
    median9 = 0.0
    sdev9 = 0.0
    array9 = []
    dmm.write("TEMP?")
    dmm2.write("TEMP?")
    dmm3.write("TEMP?")
    #dmm4.write("TEMP?")
    #dmm5.write("TEMP?")
    #dmm6.write("TEMP?")
    temp =  float(dmm.read())
    temp2 = float(dmm2.read())
    temp3 = float(dmm3.read())
    temp4 = 23#float(dmm4.read())
    temp5 = 23#float(dmm5.read())

    set_value = round(random.uniform(min_volt, max_volt), 6)
    #if (abs(set_value) < 100.00001):
    #    print ("5700A cannot source below 100V on 1kV range")
    #    continue
    fluke.write("OUT %.6f;*CLS;OPER" % set_value)
    fluke.write("OPER")

    print ("Soaking %.3f seconds for sample %d ..." % (soak_time, i))
    time.sleep(soak_time)

    print("\033[30;43m* SOURCE >> \033[44;1m\033[36;1m %s %s %s %s  %s %s %s  %s %s  \033[49;39m" % (dval, dval2, dval3, dval4, dval5, dval6, dval7, dval8, dval9 ))
    for ix in range (0,use_samples+2): #take more samples
        read_environment()
        dmm.write("TARM SGL")
        dmm2.write("TARM SGL")
        dmm3.write("TARM SGL")
        dmm4.write("READ?")
        dmm5.write("*TRG;GET;RDG?")
        dmm6.write("READ?")
        dmm7.write("READ?")
        dmm8.write("READ?")
        dmm9.write("READ?")
        val = float(dmm.read())
        val2 = float(dmm2.read())
        val3 = float(dmm3.read())
        val4 = float(dmm4.read())
        val5 = float(dmm5.read())
        val6 = float(dmm6.read())
        val7 = float(dmm7.read())
        val8 = float(dmm8.read())
        val9 = float(dmm9.read())
        array.extend([val])
        array2.extend([val2])
        array3.extend([val3])
        array4.extend([val4])
        array5.extend([val5])
        array6.extend([val6])
        array7.extend([val7])
        array8.extend([val8])
        array9.extend([val9])
        dev1 = ((val / set_value) - 1) * 1e6
        dev2 = ((val2 / set_value) - 1) * 1e6
        dev3 = ((val3 / set_value) - 1) * 1e6
        dev4 = ((val4 / set_value) - 1) * 1e6
        dev5 = ((val5 / set_value) - 1) * 1e6
        dev6 = ((val6 / set_value) - 1) * 1e6
        dev7 = ((val7 / set_value) - 1) * 1e6
        dev8 = ((val8 / set_value) - 1) * 1e6
        dev9 = ((val9 / set_value) - 1) * 1e6

        #if abs(set_value) >= 0.05:
        print("\033[33;1m %.6f \033[35;1m %11.8f %11.8f %11.8f %11.8f  %11.8f %11.8f %11.8f  %11.8f %11.8f  \033[39;0m" % (set_value, val, val2, val3, val4, val5, val6, val7, val8, val9 ))
        print("\033[33;1m DELTAs \033[36;1m %11.3f %11.3f %11.3f %11.3f  %11.3f %11.3f %11.3f  %11.3f %11.3f  \033[39;0m" % ( dev1, dev2, dev3, dev4, dev5, dev6, dev7, dev8, dev9 ))
        if (ix >= 3):
            with open(logr_name, 'a') as dilr:
                dilr.write (time.strftime("%m%d%Y-%H:%M:%S;") + ("%.9g;%.9g;%.9g;%.9g;%.9g;%.9g;%.9g;%.9g;%.9g;%.9g;%.1f;%.1f;%.1f;%.1f;%.1f;%.3f;%.1f;%.2f;\r\n" % (set_value, val, val2, val3, val4, val5, val6, val7, val8, val9, temp, temp2, temp3, temp4, temp5, ext_temp, ext_rh, ext_pressure)))
            dilr.close()
        if (abs(val) >= 9.9e36) or (abs(val2) >= 9.9e36):
            print ("Smoke escaped, check connections")
            fluke.write("OUT 0 V")
            fluke.write("STBY")
            quit()
    sdev = np.std(array[-use_samples:])
    sdev2 = np.std(array2[-use_samples:])
    sdev3 = np.std(array3[-use_samples:])
    sdev4 = np.std(array4[-use_samples:])
    sdev5 = np.std(array5[-use_samples:])
    sdev6 = np.std(array6[-use_samples:])
    sdev7 = np.std(array7[-use_samples:])
    sdev8 = np.std(array8[-use_samples:])
    sdev9 = np.std(array9[-use_samples:])
    median = np.median(array[-use_samples:])
    median2 = np.median(array2[-use_samples:])
    median4 = np.median(array4[-use_samples:])
    median3 = np.median(array3[-use_samples:])
    median5 = np.median(array5[-use_samples:])
    median6 = np.median(array6[-use_samples:])
    median7 = np.median(array7[-use_samples:])
    median8 = np.median(array8[-use_samples:])
    median9 = np.median(array9[-use_samples:])
    if abs(float(i) / 10) >= 0.0005:
        dev1 = ((median / set_value - 1) * 1e6)
        dev2 = ((median2 /set_value - 1) * 1e6)
        dev3 = ((median3 /set_value - 1) * 1e6)
        dev4 = ((median4 /set_value - 1) * 1e6)
        dev5 = ((median5 /set_value - 1) * 1e6)
        dev6 = ((median6 /set_value - 1) * 1e6)
        dev7 = ((median7 /set_value - 1) * 1e6)
        dev8 = ((median8 /set_value - 1) * 1e6)
        dev9 = ((median9 /set_value - 1) * 1e6)
        print("\033[32;1mSRC %.6f \033[33;1mA %.9f, sdev = %.3f uV \033[34;1mB %.9f, sdevB = %.3f uV\033[35;1mC %.9f, sdev = %.3f uV\033[36;1mD %.9f, sdev = %.3f uV\033[37;1mE %.9f, sdev = %.3f uV \033[39;0m" % (set_value, median, sdev*1e6, median2, sdev2*1e6, median3, sdev3*1e6, median4, sdev4*1e6, median5, sdev5*1e6 ))
        print ("\rAmbient temp: %.3f C , Humidity: %.1f %%, Pressure : %.2f hPa" % (ext_temp, ext_rh, ext_pressure))
        #dmm.write("DISP MSG,'%5.3f %2.1fV" % (dev1,set_value ))
        #dmm2.write("DISP MSG,'%5.3f %2.1fV" % (dev2,set_value ))
    with open(log_name, 'a') as dile:
        dile.write (time.strftime("%m%d%Y-%H:%M:%S;") + ("%.9g;%.9g;%.9g;%.9g;%.9g;%.9g;%.9g;%.9g;%.9g;%.9g;%.6g;%.6g;%.6g;%.6g;%.6g;%.6g;%.6g;%.6g;%.6g;%.1f;%.1f;%.1f;%.1f;%.1f;%.3f;%.1f;%.2f;\r\n" % (set_value, median, median2, median3, median4, median5, median6, median7, median8, median9, sdev, sdev2, sdev3, sdev4, sdev5, sdev6, sdev7, sdev8, sdev9, temp, temp2, temp3, temp4, temp5, ext_temp, ext_rh, ext_pressure)))
    dile.close()

fluke.write("OUT 0 V")
fluke.write("STBY")
fluke.write("RANGELCK OFF")
dmm.write("RESET")
dmm2.write("RESET")
dmm3.write("RESET")
#dmm4.write("RESET")
#dmm5.write("RESET")
#dmm6.write("RESET")
#dmm4.write("*RST")
#dmm5.write("*RST")
#dmm6.write("*RST")
#dmm9.write("*RST")
