# -*- 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 # === Configuration of security delay_to_open_limit = 900 wind_speed_ms_limit = 5/3.6 tmp_cielcor_lim = -5 # === Main loop greenled_state = 0 t0 = time.time() t0closing = time.time() - delay_to_open_limit delay_to_open = 0 t0file = 0 t0wind = 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 > tmp_cielcor_lim): 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>wind_speed_ms_limit): 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","20181014_0854") rep.append_entity("PLC_STATUS", "Raspberry", "20181014_0854", "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( "Delay_to_open", "int","{:.0f}".format(delay_to_open),"s","","Current delay to open since the meteo became OK") rep.append_value( "Security_delay_to_open", "int","{:.0f}".format(delay_to_open_limit),"s","","Limit delay to open since the meteo becomes OK") rep.append_value( "SkyTemperatureCor_lim", "float","{:+.2f}".format(tmp_cielcor_lim),"degC","","Limit of the corrected temperature of the sky to close roof") rep.append_value( "Wind_speed_lim", "float","{:.2f}".format(wind_speed_ms_limit),"m/s","","Limit of wind speed to close the roof") 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","{:.2f}".format(wind_dir_deg),"degrees","Wind_direction","0=North 90=East") rep.append_value( "Wind_speed", "float","{:.2f}".format(wind_speed_ms),"m/s","Wind_speed","Wind speed from ultrasonic sensors") rep.append_value( "OutsideTemperature", "float","{:+.2f}".format(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 delay_to_open = 0 if (mode_came_msg=="Auto") and (err_came==0): delay_to_open = 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) if (meteo_conditions>0): t0closing = time.time() else: # --- Il fait nuit mais pas beau 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 nuit et il fait beau if (roof_state_msg != 'Opened'): if (delay_to_open>delay_to_open_limit): # --- Cela fait + de 600s que le toit avait ete prealablement ferme print("==> Il fait nuit, il fait beau {} depuis +{}s et le toit n'est pas ouvert. On ouvre.".format(meteo_conditions,delay_to_open_limit)) if roof_action == True: driver_came.do_open_roof(27) time.sleep(delay_roof_sec) else: print("==> Il fait nuit, il fait beau {} mais -{}s ({:.0f}) depuis la precedente fermeture.".format(meteo_conditions,delay_to_open_limit,delay_to_open)) # === Wait 1 seconds before the next read time.sleep(1)