run_goc.py 12.7 KB
# -*- coding: utf-8 -*-
import time
import socket
import struct
import sys
import os

# --- Interaction with Raspberry GPIO
import fcntl
import driver_rg11
import driver_cv7
import driver_dht22
import driver_mlx
import driver_came 
import driver_mife

# --- update the path of Python for util modules
py_path = os.sys.path
py_pwd = os.getcwd()
py_pwd = os.getcwd() + "/../.."
if (py_pwd not in py_path):
    (os.sys.path).append(py_pwd)
import celme
import report

# === Some debug states
roof_action = True
delay_roof_sec = 20
oled_action = True

# === Init OLED
if (oled_action == True):
    import Adafruit_SSD1306
    from PIL import Image
    from PIL import ImageDraw
    from PIL import ImageFont
    # Raspberry Pi pin configuration:
    RST = 24
    # 128x64 display with hardware I2C:
    disp = Adafruit_SSD1306.SSD1306_128_64(rst=RST)
    # Initialize library.
    disp.begin()
    # Clear display.
    disp.clear()
    disp.display()
    # Create blank image for drawing.
    # Make sure to create image with mode '1' for 1-bit color.
    width = disp.width
    height = disp.height
    panel1 = Image.new('1', (width, height))
    panel2 = Image.new('1', (width, height))
    #logo = Image.open("logo1.ppm").convert('1').resize((128,32),3)
    #création d'un objet font
    fontpath = "/usr/share/fonts/truetype/dejavu/DejaVuSansMono-Bold.ttf"
    font1 = ImageFont.truetype(fontpath,10)
    # Get drawing object to draw on image.
    draw1 = ImageDraw.Draw(panel1)
    draw2 = ImageDraw.Draw(panel2)
    # Draw a black filled box to clear the image.
    draw1.rectangle((0,0,width,height), outline=0, fill=0)
    #disp.image(logo)
    #disp.display()

# =======================================
def valid_yesno (err_int):
    if err_int==0:
        return "yes"
    else:
        return "no"

# =======================================
def compute_error_code (err_int):
    if err_int==0:
        return "0"
    else:
        return "1"

# =======================================
def get_ip_address(ifname):
    """Lecture de l'adresse IP du Raspberry. 
Exemple:

get_ip_address('eth0')
"""
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    return socket.inet_ntoa(fcntl.ioctl(
        s.fileno(),
        0x8915, 
        struct.pack('256s', ifname[:15])
    )[20:24])

# =======================================
def get_sunelev():
    date = celme.Date("now")
    site = celme.Site("GPS 2 E 43 148")
    skyobj= {'planet':'Sun'}
    outputs = ['elev']
    target = celme.Target()
    target.define(skyobj)
    output0s = ['ra','dec']
    results = target.ephem(date,site,output0s)
    ra = results['RA']
    dec = results['DEC']
    skyobj= {'RA':ra , 'DEC':dec }
    target.define(skyobj)
    results = target.ephem(date,site,outputs)
    elev = results['ELEV']
    return elev

# === print the current Python version
try:
    print (sys.version)
except:
    pass

# === print the IP address 
try:
    print("IP = ",get_ip_address('eth0'))
except:
    pass

# === Main loop
greenled_state = 0;
t0 = time.time()
t0closing = 0
t0file = 0
while True:

    # === Blink the green led
    if greenled_state == 0:
        driver_mife.do_led_green(18,1)
        greenled_state = 1
    else:
        driver_mife.do_led_green(18,0)
        greenled_state = 0

    # === Clear the OLED displays
    try:
        draw1.rectangle((0,0,width,height), outline=0, fill=0)
        draw2.rectangle((0,0,width,height), outline=0, fill=0)
    except:
        pass

    # === Get Sun elevation
    sunelev = get_sunelev();

    # === Init the error supercode
    err = 0

    # === Get RG11 data
    err_rg11, power_mife_rg11, rain_state, rain_state, power_mife_msg, rain_state_msg, pin34, pin36, pin38 = driver_rg11.get_data(19,20,25,0)
    oled_rain = "RG11 : "
    if (err_rg11>0):
        print("RG11 err=",err_rg11)
        err+=1
        oled_rain += "Err"+str(err_rg11)
    else:
        oled_rain += rain_state_msg

    # === Get CV7 data
    err_cv7, power_mife_cv7, wind_dir_deg, wind_speed_ms, wind_tmp_degC, power_mife_msg, msg_wind, msg_temp  = driver_cv7.get_data("/dev/ttyS0", 25,0)
    oled_wind_speed = "Wind : "
    oled_wind_dir = "Wind dir : "
    if (err_cv7>0):
        print("CV7 err=",err_cv7)
        err+=2
        oled_wind_speed += "Err"+str(err_cv7)
        oled_wind_dir += "Err"+str(err_cv7)
    else:
        oled_wind_speed += '{:.2f}'.format(wind_speed_ms)+" m/s"
        oled_wind_dir += '{:3.0f}'.format(wind_dir_deg)+ " deg"

    # === Get DHT22 data
    err_dht22, tmp, hum, seuil, data = driver_dht22.get_data(13,0)
    oled_tmp = "Temp : "
    oled_hum = "Humidity : "
    if (err_dht22>0):
        print("DHT22 err=",err_dht22)
        err+=4
        oled_tmp += "Err"+str(err_dht22)
        oled_hum += "Err"+str(err_dht22)
    else:
        oled_tmp += "{:.1f}".format(tmp) + " degC"
        oled_hum += "{:.0f}".format(hum) + " %"

    # === Get MLX data
    err_mlx, tmp_ciel, tmp_boit, raw_data_ciel, raw_data_boit =driver_mlx.get_data(0)
    tmp_cielcor = tmp_ciel - tmp_boit * 0.7; 
    oled_skytmp = "Sky temp : "
    if (err_mlx>0):
        print("mlx err =",err_mlx)
        err+=8
        oled_skytmp += "Err"+str(err_mlx)
    else:
        oled_skytmp += "{:.2f}".format(tmp_ciel)+" degC"

    # === Get Came data
    err_came, power_came, mode_came, roof_state, power_came_msg, mode_came_msg, roof_state_msg, pin48, pin39, pin41,pin31 = driver_came.get_data(26,22,5,6,1)
    oled_came1 = "Roof mode : "
    oled_came2 = "Roof state : "
    if (err_came>0):
        oled_came1 += "Err"+str(err_mlx)
        oled_came2 += "Err"+str(err_mlx)
    else:
        oled_came1 += mode_came_msg
        oled_came2 += roof_state_msg

    # === Compute the meteo conditions
    meteo_conditions = 0
    if (err_mlx==0):
        if (tmp_cielcor > -5):
           meteo_conditions = meteo_conditions +1
    if (err_rg11==0) and (rain_state==1):
        meteo_conditions = meteo_conditions +2
    if (err_cv7==0) and (wind_speed_ms>10):
        meteo_conditions = meteo_conditions +4
    if (err_rg11==1):
        # --- critical error
        meteo_conditions = meteo_conditions +8

    # === Json status
    date = celme.Date("now")
    date_iso_utc = date.iso();
    rep = report.Status_json()
    rep.new_status("PLC","20181010_1910")
    rep.append_entity("PLC_STATUS", "Raspberry", "20181010_1911", "Guitalens Observatory",date_iso_utc)
    # --- Json device Came
    rep.append_device("Came", "roof_controler", "S/N_A5EM", compute_error_code(err_came))
    rep.append_value(  "Error_code",  "int",str(err_came),"","","0=OK 1=PowerPB 2=SwitchPB")
    rep.append_value(  "Power_input", "int",str(power_came),"","","0=0Volt 1=24Volts")
    rep.append_value(  "Mode_came",   "int",str(mode_came),"","","0=Manual 1=Auto")
    rep.append_value(  "Roof_state",  "int",str(roof_state),"","","0=Closed 1=Opened 2=Intermediate")
    rep.append_value(  "Meteo_conditions",   "int",str(meteo_conditions),"","","0=OK +1=Clouds +2=Rain +4=Wind +8=CriticalError")
    rep.append_value(  "Sun_elevation",   "float","{:+.3f}".format(sunelev),"deg","","Local elevation of the Sun")
    # --- Json device CV7
    rep.append_device("CV7", "weather_station", "S/N_09172419", compute_error_code(err_cv7))
    rep.append_value(  "Error_code",  "int",str(err_cv7),"","","0=OK 1=SerialPB 2=FramePB")
    rep.append_value(  "Power_input",  "int",str(power_mife_cv7),"","","0=0Volt 1=12Volts (Power from MiFe board)")
    rep.append_value(  "Wind_dir",  "float",str(wind_dir_deg),"degrees","Wind_direction","0=North 90=East")
    rep.append_value(  "Wind_speed",  "float",str(wind_speed_ms),"m/s","Wind_speed","Wind speed from ultrasonic sensors")
    rep.append_value(  "OutsideTemperature",  "float",str(wind_tmp_degC),"degC","Temperature_outside","Temperature of the anemometer")
    # --- Json device DHT22
    rep.append_device("DHT22", "weather_station", "MiFe_DHT1_1", compute_error_code(err_dht22))
    rep.append_value(  "Error_code",  "int",str(err_dht22),"","","0=OK 1=CheksumPB 2=LengthPB 3=NodataPB")
    rep.append_value(  "Temperature",  "float","{:+.0f}".format(tmp),"degC","Temperature_outside","Temperature inside PLC box")
    rep.append_value(  "Humidity",  "float","{:.0f}".format(hum),"percent","Humidity_outside","Humidity inside PLC box")
    # --- device RG11
    rep.append_device("RG11", "weather_station", "S/N_207588", compute_error_code(err_rg11))
    rep.append_value(  "Error_code",  "int",str(err_rg11),"","","0=OK +1=PowerPB +2=NopowerPB +4=AllonePB")
    rep.append_value(  "RainSate",  "int",str(rain_state),"","Rain_boolean","0=Dry 1=Rain 2=Unknown")
    # --- device MLX90614
    rep.append_device("MLX90614", "weather_station", "1", compute_error_code(err_mlx))
    rep.append_value(  "Error_code",  "int",str(err_mlx),"","","0=OK 1=DataPB")
    rep.append_value(  "SkyTemperature",  "float","{:+5.2f}".format(tmp_ciel),"degC","","Temperature of the sky")
    rep.append_value(  "CanTemperature",  "float","{:+5.2f}".format(tmp_boit),"degC","","Temperature of the TO can")
    rep.append_value(  "SkyTemperatureCor", "float","{:+5.2f}".format(tmp_cielcor),"degC","Temperature_sky","Corrected temperature of the sky")
    # --- save the Json status report
    rep.save_json("/var/www/html/meteo/plc_guitalens.json")

    # === String of results
    date_jd_utc = date.jd();
    date_digits_utc = date.digits(0)
    msg_gene = "{:13.5f} {} {:+6.2f} {:2d} {:1d}  ".format(date_jd_utc, date_digits_utc, sunelev,err,meteo_conditions)
    msg_came = "{:2d} {:1d} {:1d} {:1d}  ".format(err_came, power_came, mode_came, roof_state)
    msg_mlx = "{:2d} {:+6.2f} {:+6.2f} {:+6.2f}  ".format(err_mlx, tmp_ciel, tmp_boit, tmp_cielcor)
    msg_rg11 = "{:2d} {:1d} {:1d}  ".format(err_rg11, power_mife_rg11, rain_state)
    msg_dht22 = "{:2d} {:+3.0f} {:3.0f}  ".format(err_dht22, tmp, hum)
    msg_cv7 = "{:2d} {:1d} {:3.0f} {:6.2f} {:+3.0f}   ".format(err_cv7, power_mife_cv7, wind_dir_deg, wind_speed_ms, wind_tmp_degC)
    msg = msg_gene + msg_came + msg_mlx + msg_rg11 + msg_dht22 + msg_cv7
    print(msg)

    # === File for web site
    try:
        dt = time.time()-t0file;
        if (dt>30):
            dateymdhms= date.ymdhms()
            fic = "/var/www/html/meteo/meteo_{:04d}{:02d}{:02d}.txt".format(dateymdhms[0],dateymdhms[1],dateymdhms[2])
            fichier = open(fic,"a")
            fichier.write(msg)
            fichier.write("\n")
            fichier.close()
            t0file = time.time()
    except: 
      pass    

    # === Display OLED
    try:
        dt = time.time()-t0;
        if (dt<6):
            draw1.text((0, 10),oled_came1,  font=font1, fill=255)
            draw1.text((0, 20),oled_skytmp,  font=font1, fill=255)
            draw1.text((0, 30),oled_tmp,  font=font1, fill=255)
            draw1.text((0, 40),oled_hum,  font=font1, fill=255)
            disp.image(panel1)
        elif (dt<12):
            draw2.text((0, 10),oled_came2,  font=font1, fill=255)
            draw2.text((0, 20),oled_wind_speed,  font=font1, fill=255)
            draw2.text((0, 30),oled_wind_dir,  font=font1, fill=255)
            draw2.text((0, 40),oled_rain,  font=font1, fill=255)
            disp.image(panel2)
        else:
            t0 = time.time()
        disp.display()
    except: 
      pass    

    # === Roof action according security rules
    if (mode_came_msg=="Auto") and (err_came==0):
        dt = time.time()-t0closing;
        if (sunelev>0):
            # --- Il fait jour
            if (roof_state_msg != 'Closed'):
                print("==> Il fait jour et le toit n'est pas ferme. On ferme.")
                if roof_action == True:
                    driver_came.do_close_roof(23)
                time.sleep(delay_roof_sec)
        else:
            # --- Il fait nuit
            if (meteo_conditions>0):
                # --- Il ne fait pas beau
                if (roof_state_msg != 'Closed'):
                    print("==> Il fait nuit, il ne fait pas beau {} et le toit n'est pas ferme. On ferme.".format(meteo_conditions))
                    if roof_action == True:
                        driver_came.do_close_roof(23)
                    time.sleep(delay_roof_sec)
                t0closing = time.time()
            else:
                # --- Il fait beau
                if (roof_state_msg != 'Opened'):
                    if (dt>600):
                        # --- Cela fait + de 600s que le toit avait ete prealablement ferme
                        print("==> Il fait nuit, il fait beau {} depuis +600s et le toit n'est pas ouvert. On ouvre.".format(meteo_conditions))
                        if roof_action == True:
                            driver_came.do_open_roof(27)
                        time.sleep(delay_roof_sec)
                    else:
                        print("==> Il fait nuit, il fait beau {} mais -600s ({:.0f}) depuis la precedente fermeture.".format(meteo_conditions,dt))

    # === Wait 1 seconds before the next read
    time.sleep(1)