· 6 years ago · Jul 10, 2019, 02:48 PM
1# !/usr/bin/python
2# coding=utf-8
3# Import generali
4from __future__ import print_function
5from decimal import Decimal
6import urllib, time, sys, os, serial, struct
7import RPi.GPIO as GPIO
8from random import randint
9from firebase import firebase
10import datetime
11
12# -----------------Configurazione parametri manuali ------------------
13# Key per l'accesso al canale
14api_key = "ERCQYDCKHXJH5JGS"
15
16# Canale di manutenzione
17api_key_maintenance = "5HQPZPZ8KEPGR1YC"
18
19# Campi Firebase
20idSensore = "Salerno01-S"
21isMobile = False
22typeNode = "Urban PM-CO2-O3"
23zone = "Salerno"
24
25SECRET_KEY = '0JuzXIx0GkGP1OKS4LltwLVgQrnaaYX5MDP421KT'
26URL = 'https://sensesquaredb.firebaseio.com/'
27
28#DATABASE D'APPOGGIO
29# SECRET_KEY='RmLzDFMYaHc1l1Z1rNZHRWBpvuZ4uGaANt7GTGuo'
30# URL='https://newproj-3f870.firebaseio.com/'
31
32email = idSensore + zone + "@centralinassq.com"
33
34# Posizione in coordinate decimali
35longitude = 14.79358434677124
36latitude = 40.762536083618954
37
38#DATI CELLA NO2
39C1=684
40C2=692
41SENS=0.4488
42
43#DATI CELLA O3
44K1=438
45K2=454
46SENS_2=0.20805
47# ---------------------------------------------------------------------
48
49
50# Import OPC-N2*
51import spidev, opc
52
53# Import BME680*
54import bme680
55
56# Import ADS1115*
57import Adafruit_ADS1x15
58
59# Import NEO-6M GPS
60sys.path.append("/home/pi/")
61from neo_m import neo_gps
62
63__author__ = "Massimo Moffa"
64# --- INIZIO CONFIGURAZIONE ---
65
66
67# Field dove inserire i dati
68field_temp = "field2"
69field_humidity = "field1"
70field_pressure = "field3"
71field_o3 = "field7"
72field_pm1 = "field4"
73field_pm2_5 = "field5"
74field_pm10 = "field6"
75field_no2 = "field8"
76# field_no2 = "field8"
77
78# Tempo di campionamento
79sampling_time = 15
80
81# Tempo di break
82break_duration = 120
83
84# BME680 valore BaseLine
85hum_bl = -1 # DEFAULT VALUE (cambierà durante l'esecuzione)
86gas_bl = -1 # DEFAULT VALUE (cambierà durante l'esecuzione)
87hum_weighting = 0.25
88
89# ADS1115 parametri
90nt = 0 # DEFAULT VALUE (cambierà durante l'esecuzione)
91GAIN = 2/3
92mlv = 0.1875
93
94# Salvataggio del log offline
95save_log_offline = False
96
97# Switch OPC/PMS
98opc_enabled = False
99pms_enabled = True
100
101# Canale di manutenzione
102# api_key_maintenance = "QPJ8QS2LW7MW21BB"
103maintenance_channele_enabled = True
104field_dir_vento = "field1"
105field_int_vento = "field2"
106field_gas_m = "field3"
107field_program_status = "field4"
108field_cpu_temp = "field5"
109field_nt = "field6"
110fields_maintenance = []
111values_maintenance = []
112data_log_maintenance = []
113field_lat = "field7"
114field_lon = "field8"
115
116# --- FINE CONFIGURAZIONE ---
117
118first_start = True
119first_start_bme = True
120GPIO.setmode(GPIO.BCM)
121GPIO.setwarnings(False)
122GPIO.setup(26, GPIO.OUT)
123GPIO.setup(13, GPIO.OUT)
124GPIO.setup(5, GPIO.OUT)
125GPIO.setup(20, GPIO.OUT)
126GPIO.setup(21, GPIO.OUT)
127# System status
128status_internet = True
129# status_gps = True
130status_opc = True
131status_bme = True
132status_pms = True
133status_ads = True
134system_integrity = True
135system_counter_integrity = True
136counter_to_reset = 0
137
138
139# -----------------------FUNZIONI PER FIREBASE----------------------------
140
141def accessdbFirebaseWithAuth(dsn, SECRET_KEY, email, admin=False):
142 '''
143 ------------FUNZIONAMENTO----------------
144 Funzione tramite la quale si apre la connessione col Database
145
146 Parametri d'ingresso: dsn -> url del database
147 SECRET_KEY -> Chiave segreta del database Firebase
148 email -> email fittizia da attribuire ad ogni centralina (utile alla scrittura dei log)
149 admin -> possibilità di accedere al database in modalità admin (utile all'utilizzo della funzione quando il file viene richiamato come script per effettuare test)
150 Parametro di ritorno: db -> variabile che contiene il collegamento al database tramite cui si effettuano le operazioni su di esso
151
152 '''
153
154 from firebase import firebase
155 import datetime
156
157 auth = firebase.FirebaseAuthentication(SECRET_KEY, email, admin,
158 admin) # funzione che serve a creare l'autenticazione
159 db = firebase.FirebaseApplication(dsn,
160 auth) # accedo al database con l'url "dsn" e l'autorizzazione e istanzio l'oggetto db
161
162 return db # ritorna l'oggetto tramite il quale accediamo al DataBase
163
164
165def buildPath(nodoSensore):
166 '''
167 ------------FUNZIONAMENTO----------------
168 Funzione che si occupa di costruire il path per il nuovo record che arriva dal sensore.
169 Il path viene generato su ora e data in modo da risultare univoco.
170
171 '''
172
173 # definisco il Formato dell'ora che finisce nel path
174 date = datetime.datetime.now()
175
176 year = date.strftime('%Y')
177 month = date.strftime('%m')
178 day = date.strftime('%d')
179 hour = date.strftime('%H')
180 minute = date.strftime('%M')
181 second = date.strftime('%S')
182
183 return "Sensori/" + nodoSensore + "/feeds/" + year + "M" + month + "/D" + day + "/H" + hour, "/M" + minute + "S" + second
184
185
186def initializeNode(db, IDsensore, isMobile, type, zone):
187 '''
188 ------------FUNZIONAMENTO----------------
189 Funzione di inizializzazione di una nuova centralina
190
191 Parametri d'ingresso: db -> collegamento al database
192 IDSensore -> nome del nuovo nodo/centralina che deve essere uguale a quello usato su thingspeak per riconoscerlo
193 isMobile -> informazioni se la centralina è mobile oppure no
194 type -> versione della centralina (definita dall'azienda)
195 zone -> Zona d'installazione orientativa
196 parametri di ritorno: true o false in base a se viene inizializzata la centralina
197 (se è gia presente un nodo con lo stesso nome ritorna false)
198 Il nodo viene inizializzato SE E SOLO SE non esiste un'altra centralina con lo stesso IDsensorE
199
200 '''
201 header = {}
202 header['MobileSensor'] = isMobile
203 header['Type'] = type
204 header['Zone'] = zone
205
206 check = db.get("/Sensori/" + IDsensore, None)
207 check2 = db.get("/Sensori/" + IDsensore + "/Header", None)
208
209 if (check == None or check2 == None):
210 db.put("/Sensori/" + IDsensore, "/Header", header)
211 return True
212 else:
213 print("ID già utilizzato")
214 return False
215
216
217# Costruisce i campi per Firebase Nelle centraline con Anemometro
218def buildFieldForFirebase(field, field_maintenance):
219 '''
220 ------------FUNZIONAMENTO----------------
221 Funzione che si occupa di inizializzare il vettore contenente i campi che saranno salvati in seguito su Firebase
222
223 Parametri d'ingresso: field, field_maintenance-> i due vettori dei campi che vengono passati a thingspeak (rispettivamente del canale front, e maintenance)
224
225 parmetri di ritorno: fieldFirebase-> vettore utilie per l'inserimento su Firebase
226
227 '''
228
229 fieldFirebase = []
230
231 correspondingField = {"field2": 'temperatura',
232 "field1": 'umidità',
233 "field3": 'pressione',
234 "field7": 'o3',
235 "field4": 'pm1',
236 "field5": 'pm2_5',
237 "field6": 'pm10',
238 "field8": 'co'}
239
240 # Canale di manutenzione
241 correspondingFieldMaintenance = {"field1": "direzione_vento",
242 "field2": "intensita_vento",
243 "field3": "gas_m",
244 "field4": "programStatus",
245 "field5": "cpuTemperature",
246 "field6": "nt",
247 "field7": "latitude",
248 "field8": "longitude"}
249
250 for iField in field:
251 fieldFirebase.append(correspondingField[iField])
252 for iField in field_maintenance:
253 fieldFirebase.append(correspondingFieldMaintenance[iField])
254
255 return fieldFirebase
256
257
258def sendDataToFirebase(db, idSensore, field, field_maintenance, values, values_maintenance):
259 global latitude, longitude
260
261 '''
262 ------------FUNZIONAMENTO----------------
263 Funzione per l'invio dei dati su firebase.
264 Combina i due vettori dei campi e i due vettori dei valori e provvedere all'invio su firebase.
265
266 Parametri d'ingresso: db -> collegamento al database
267 IDSensore -> nome del nuovo nodo/centralina che deve essere uguale a quello usato su thingspeak per riconoscerlo
268 field, field_maintenance -> vettori dei campi per l'invio su thingSpeak
269 values, values_maintenance -> vettori dei valori per l'invio su thingspeak
270 Nessun parametro di ritorno.
271
272 '''
273 valuesForFirebase = {}
274 valuesTemp = {}
275 fieldForFirebase = buildFieldForFirebase(field, field_maintenance)
276
277 for i in range(0, len(values)):
278 valuesForFirebase[fieldForFirebase[i]] = values[i]
279 valuesTemp[fieldForFirebase[i]] = values[i]
280 __numberValues__ = i + 1
281
282 for i in range(__numberValues__, __numberValues__ + len(values_maintenance)):
283 valuesForFirebase[fieldForFirebase[i]] = values_maintenance[i - len(values)]
284 __numberValuesMaintenance__ = i
285
286 valuesTemp['latitude'] = latitude
287 valuesForFirebase['latitude'] = latitude
288
289 valuesTemp['longitude'] = longitude
290 valuesForFirebase['longitude'] = longitude
291
292 try:
293 valuesTemp['intensita_vento'] = valuesForFirebase['intensita_vento']
294 valuesTemp['direzione_vento'] = valuesForFirebase['direzione_vento']
295 except:
296 pass
297
298 pathforRecord = {}
299 pathforRecord = buildPath(idSensore)
300
301 try:
302 db.put(pathforRecord[0], pathforRecord[1], valuesTemp)
303 db.put(pathforRecord[0], pathforRecord[1], valuesForFirebase)
304 print("Inserimento avvenuto con successo")
305 except:
306 print("Errore nell'inserimento")
307
308
309# ------------------------------------------------------------------------
310
311
312def startImage():
313 print(
314 "------------------------------------------------------------------------------------------------------------------------\n")
315 print(
316 " .dBBBBP dBBBP dBBBBb .dBBBBP dBBBP .dBBBBP dBBBBP dBP dBP dBBBBBb dBBBBBb dBBBP ")
317 print(
318 " BP dBP BP BP dBP.BP BB dBP ")
319 print(
320 " `BBBBb dBBP dBP dBP `BBBBb dBBP `BBBBb dBP.BP dBP dBP dBP BB dBBBBK dBBP ")
321 print(
322 " dBP dBP dBP dBP dBP dBP dBP dBP.BB dBP_dBP dBP BB dBP BB dBP ")
323 print(
324 "dBBBBP' dBBBBP dBP dBP dBBBBP' dBBBBP dBBBBP' dBBBB'B dBBBBBP dBBBBBBB dBP dB' dBBBBP \n")
325 print("SENSORI : OPC-N2 & BME680 & ADS1115 & PMS")
326 print("SALVATAGGIO OFFLINE LOG : " + (str(save_log_offline)).capitalize())
327 print("CANALE MANUTENZIONE : " + (str(maintenance_channele_enabled)).capitalize())
328 if not system_integrity:
329 print("\n\n\nMODALITA' MODULARE : UNO o PIU' DISPOSITIVI NON FUNZIONANO CORRETTAMENTE!")
330 print(
331 "------------------------------------------------------------------------------------------------------------------------\n\n\n")
332
333
334# Funzione per il backup dati
335def backupLog(data, file_name="SSQ---BACKUP-LOG"):
336 localtime = time.asctime(time.localtime(time.time()))
337 try:
338 file = open(file_name, 'a')
339 with file:
340 file.write("\n\n\n\n\n----DATI SENSORI----\ndata : " + localtime + "\n")
341 for s in data:
342 file.write(str(s[0]) + " : ")
343 for i in range(1, (17 - len(s[0]))):
344 file.write(" ")
345 file.write(str(s[1]) + "\n")
346 file.close()
347 except IOError:
348 file = open(file_name, 'w')
349 with file:
350 file.write("\n\n\n\n\n----DATI SENSORI----\ndata : " + localtime + "\n")
351 for s in data:
352 file.write(str(s[0]) + " : ")
353 for i in range(1, (17 - len(s[0]))):
354 file.write(" ")
355 file.write(str(s[1]) + "\n")
356 file.close()
357
358
359# Funzione per il risparmio energetico
360def breakTime(sensor1, sensor2, time=break_duration):
361 if sensor1 is not None:
362 sensor.off()
363 elif sensor2 is not None:
364 GPIO.output(5, 0)
365
366 print("\n\n\nSleeping....")
367 showCountdownTime(time)
368 main()
369
370
371# Funzione per il controllo del sistema
372
373
374"""
375def getGpsData(gps):
376 global first_start, break_duration
377 try:
378 gps.elaborateData()
379 data = []
380 data.append(("lat", gps.latitude))
381 data.append(("lon", gps.longitude))
382 time = (gps.time).split(':')
383 if time[0] != "":
384 if int(time[0]) > 18 or int(time[0]) < 9:
385 break_duration = 1380
386 first_start = True
387 else:
388 break_duration = 120
389 first_start = False
390 return data
391 except Exception as error:
392 print("Errore GPS : " + str(error))
393 checkEverything()
394"""
395
396
397def systemChecker():
398 error_code = ""
399 devices = [str(int(status_opc)), str(int(status_bme)), str(int(status_ads)), str(int(status_pms)), str(int(status_internet))]
400 for s in devices:
401 error_code += s
402 return (int(error_code, 2))
403
404
405def setSystemIntegrity():
406 global system_integrity
407 try:
408
409 with open("system_reset_counter", "r+") as file:
410 data = file.read(2)
411 num = int(data)
412 if num == -1:
413 system_integrity = False
414 file.seek(0, 0);
415 file.write("0 ")
416
417 except:
418 print("", end="")
419
420
421def resetFileCounter(n="0 "):
422 try:
423
424 with open("system_reset_counter", 'w') as file:
425 file.write(n)
426
427 except:
428 print("", end="")
429
430
431def resetSystem(errors):
432 global system_integrity, fields_maintenance, values_maintenance, data_log_maintenance, first_start
433 localtime = time.asctime(time.localtime(time.time()))
434 try:
435
436 with open("system_reset_counter", 'r+') as file:
437 data_file = file.read(2)
438 counter = int(data_file)
439 if counter >= 3:
440 file.seek(0, 0);
441 file.write("0")
442 '''for error in errors:
443 file.write("\n" + error)'''
444 file.write("\nDATA : " + str(localtime))
445 fields_maintenance.append(field_program_status)
446 values_maintenance.append(8)
447 data_log_maintenance.append(("status", 8))
448 system_integrity = False
449 first_start = True
450 main()
451 else:
452 file.seek(0, 0);
453 file.write(str(counter + 1))
454
455 print("\n\n\nSYSTEM REBOOT... \nCTRL + C per interrompere")
456 showCountdownTime(15)
457 os.system("reboot")
458 except IOError:
459 file = open("system_reset_counter", 'w')
460 with file:
461 file.write("1")
462 file.close()
463 print("\n\n\nSYSTEM REBOOT... \nCTRL + C per interrompere")
464 showCountdownTime(15)
465 os.system("reboot")
466
467
468def checkEverything():
469 print("\n\n\n\n----CONTROLLORE----")
470 global status_internet, status_opc, status_bme, status_ads, system_integrity, fields_maintenance, values_maintenance, data_log_maintenance
471 control_number = 0
472 unstable = True
473 internet = False
474 # gps = False
475 if opc_enabled:
476 sensor_OPC = False
477 else:
478 sensor_OPC = True
479 sensor_BME = False
480 sensor_ADS = False
481 if pms_enabled:
482 sensor_PMS = False
483 else:
484 sensor_PMS = True
485 while unstable:
486 control_number = control_number + 1
487 errors = []
488 # Controllo INTERNET
489 try:
490 test = urllib.urlopen("https://www.google.com")
491 internet = True
492 test.close()
493 except Exception as error:
494
495 errors.append(error)
496 internet = False
497
498 print("----CONTROLLO N." + str(control_number) + "----")
499 print("Internet : " + str(internet))
500
501 if opc_enabled:
502 sensore_opc = initializeOPC()
503 time.sleep(2)
504 try:
505 alpha = opc.OPCN2(sensore_opc)
506 alpha.off()
507 sensor_OPC = True
508 except Exception as error:
509 sensor_OPC = False
510 errors.append(("Errore OPC : " + str(error)))
511 print("Sensore OPC : " + str(sensor_OPC))
512 # Controllo SENSORE BME
513 try:
514 sensor_bme = bme680.BME680()
515 sensor_BME = True
516 except Exception as error:
517 sensor_BME = False
518 errors.append(("Errore BME : " + str(error)))
519 print("Sensore BME : " + str(sensor_BME))
520 # Controllo SENSORE ADS
521 try:
522 ads = Adafruit_ADS1x15.ADS1115()
523 test = ads.read_adc(0, gain=GAIN)
524 sensor_ADS = True
525 except Exception as error:
526 sensor_ADS = False
527 errors.append(("Errore ADS : " + str(error)))
528 print("Sensore ADS : " + str(sensor_ADS))
529
530 # Controllo SENSORE PMS
531 if pms_enabled:
532 GPIO.output(5, 1)
533 try:
534 pms = serial.Serial("/dev/ttyS0", 9600, timeout=2)
535 sensor_PMS = True
536 pms.close()
537 except Exception as error:
538 sensor_PMS = False
539 errors.append(("Errore PMS : " + str(error)))
540 print("Sensore PMS : " + str(sensor_PMS))
541 # VERIFICA FINALE
542 if internet and sensor_OPC and sensor_BME and sensor_PMS and sensor_ADS:
543 unstable = False
544 status_internet = internet
545 status_opc = sensor_OPC
546 status_bme = sensor_BME
547 status_ads = sensor_ADS
548 status_pms = sensor_PMS
549 # status_gps = gps
550 system_integrity = True
551 resetFileCounter()
552 print("Check : OK!\n\n\n\n")
553 else:
554 print("Check : NON OK!\n\n")
555 '''for value in errors:
556 pass #print(value + "\n")
557 '''
558 if control_number == 5:
559 os.system("clear")
560 status_internet = internet
561 # status_gps = gps
562 status_opc = sensor_OPC
563 status_bme = sensor_BME
564 status_ads = sensor_ADS
565 resetSystem(errors)
566 showLoaderTime(30)
567 status_code = systemChecker()
568 if status_code:
569 if internet:
570 sendDataToChannel(api_key_maintenance, field_program_status, status_code)
571 data_log_maintenance.append(("status", status_code))
572 main()
573
574
575# Funzione per il caricamento
576def showLoaderTime(sec):
577 print("\n\nLoading -> ", end="")
578 for i in range(1, sec):
579 time.sleep(1)
580 print("|", end=""),
581 sys.stdout.flush()
582 print("\n\n")
583
584
585def showCountdownTime(sec):
586 for i in range(1, sec):
587 time.sleep(1)
588 print("Mancano " + str(sec - i) + " secondi ", end='\r'),
589 sys.stdout.flush()
590 print("DONE \n\n")
591
592
593# Funzioni per l'uscita dei dati
594def sendDataToChannelArray(key, field, content):
595 time.sleep(0.5)
596 if field and content:
597
598 url = "http://api.thingspeak.com:80/update.json?api_key=" + key
599 print("\n----RISPOSTE SERVER----\n")
600 for i in range(0, len(field)):
601 url = url + "&" + field[i] + "=" + str(content[i])
602 print(url)
603 try:
604 connection = urllib.urlopen(url)
605 print("Risposta Server : ", connection.code)
606 connection.close()
607 except Exception as error:
608 print("\n\nErrore Connessione Server : " + str(error))
609 checkEverything()
610
611
612def sendDataToChannel(key, field, content):
613 url = "http://api.thingspeak.com:80/update.json?api_key=" + key + "&" + field + "=" + str(content)
614 try:
615 # time.sleep(1)
616 connection = urllib.urlopen(url)
617 # print("Risposta Server : ", connection.code, "valore passato: ", str(content))
618 connection.close()
619 except Exception as error:
620 print("\n\nErrore Connessione Server : " + str(error))
621 checkEverything()
622
623
624def printSensorData(data):
625 if not data:
626 print("L'array dei dati e' VUOTO")
627 else:
628 print("\n\n\n\n----DATI SENSORE----\n")
629 for e in data:
630 print(str(e[0]) + " : " + str(e[1]))
631
632
633# Funzioni per l'acquisizione dei dati
634def getOPCData(sensor):
635 try:
636 data = []
637 for key, value in sensor.pm().items():
638 data.append((key, value))
639 return data
640 except Exception as error:
641 print("Errore OPC : " + str(error))
642 checkEverything()
643
644
645def getBMEData(sensor):
646 data = []
647 global first_start_bme, fields_maintenance, values_maintenance, data_log_maintenance
648 try:
649 if sensor.get_sensor_data():
650 data.append(("Temp", sensor.data.temperature))
651 data.append(("Humidity", sensor.data.humidity))
652 data.append(("Pressure", sensor.data.pressure))
653 if sensor.data.heat_stable:
654 data_gas_c = ((sensor.data.gas_resistance) / 1000)
655 fields_maintenance.append(field_gas_m)
656 values_maintenance.append(data_gas_c)
657 data_log_maintenance.append(("gas resistance", data_gas_c))
658 #data.append(
659 # ("Air Quality", elaborateBMEScoreData(sensor.data.humidity, ((sensor.data.gas_resistance) / 1000))))
660 return data
661 else:
662 if not first_start_bme:
663 print("Errore BME : " + "Non ci sono dati")
664 checkEverything()
665 else:
666 first_start_bme = False
667 return None
668 except Exception as error:
669 print("Errore BME : " + str(error))
670 checkEverything()
671
672
673def getPMSData(pms):
674 data = None
675 for i in range(1, 3):
676 verify = False
677 time.sleep(0.1)
678 for l in range(1, 100):
679 c = pms.read(1) # 1st header
680 if len(c) >= 1:
681 if ord(c[0]) == 0x42:
682 c = pms.read(1) # 2nd header
683 if len(c) >= 1:
684 if ord(c[0]) == 0x4d:
685 verify = True
686 break;
687 if verify:
688 time.sleep(0.7)
689 pms_data = pms.read(30)
690 check = 0x42 + 0x4d
691 for c in pms_data[0:28]:
692 check += ord(c)
693 pms7003_data = struct.unpack('!HHHHHHHHHHHHHBBH', pms_data)
694 if check != pms7003_data[15]:
695 continue
696 data = []
697 data.append(("pm 1", pms7003_data[1]))
698 data.append(("pm 2.5", pms7003_data[2]))
699 data.append(("pm 10", pms7003_data[3]))
700 return data
701
702def getADSData(ads, pin=0):
703 data = []
704
705 if pin == 0:
706 pin1 = 0
707 pin2 = 1
708 else:
709 pin1 = 2
710 pin2 = 3
711 if ads:
712 try:
713 data.append((ads.read_adc(pin1, gain=GAIN)) * mlv)
714 data.append((ads.read_adc(pin2, gain=GAIN)) * mlv)
715 time.sleep(2)
716 return data
717 except Exception as error:
718 print("Errore ADS : " + str(error))
719
720 else:
721 if not first_start:
722 print("Errore ADS : " + "L'ads non è stato inizzializzato correttamente")
723 checkEverything()
724 else:
725 return None
726
727# Funzioni per l'inizializzazione
728def initializeOPC():
729 spi = spidev.SpiDev()
730 spi.open(0, 0)
731 spi.mode = 1
732 spi.max_speed_hz = 500000
733 return spi
734
735
736def initializeBME():
737 try:
738 sensor = bme680.BME680()
739 sensor.set_humidity_oversample(bme680.OS_2X)
740 sensor.set_pressure_oversample(bme680.OS_4X)
741 sensor.set_temperature_oversample(bme680.OS_8X)
742 sensor.set_filter(bme680.FILTER_SIZE_3)
743
744 sensor.set_gas_status(bme680.ENABLE_GAS_MEAS)
745 sensor.set_gas_heater_temperature(320)
746 sensor.set_gas_heater_duration(150)
747 sensor.select_gas_heater_profile(0)
748 return sensor
749 except Exception as error:
750 print("Errore BME : " + str(error))
751 checkEverything()
752
753
754def initializePMS():
755 try:
756 pms = serial.Serial("/dev/ttyAMA0", 9600, timeout=0.7)
757 # GPIO.output(5, 1)
758 return pms
759 except Exception as error:
760 print("Errore PMS : " + str(error))
761 checkEverything()
762
763def initializeADS(address=0):
764 try:
765 if address == 1:
766 ads = Adafruit_ADS1x15.ADS1115(0x48)
767 print("Inizializzato primo ADS: 0x48")
768 elif address == 2:
769 ads = Adafruit_ADS1x15.ADS1115(0x49)
770 print("Inizializzato secondo ADS: 0x49")
771 elif address == 3:
772 ads = Adafruit_ADS1x15.ADS1115(0x4A)
773 print("Inizializzato terzo ADS: 0x4A")
774 elif address == 4:
775 ads = Adafruit_ADS1x15.ADS1115(0x4B)
776 print("Inizializzato quarto ADS: 0x4B")
777 else:
778 ads = Adafruit_ADS1x15.ADS1115()
779 print("Inizializzato primo ADS: 0x48")
780 return ads
781 except Exception as error:
782 print("Errore ADS : " + str(error))
783
784
785"""
786def initializeGPS():
787 try:
788 gps = neo_gps("/dev/serial/by-path/platform-3f980000.usb-usb-0:1.2:1.1-port0") #port="/dev/serial/by-id/usb-Prolific_Technology_Inc._USB-Serial_Controller-if00-port0"
789 return gps
790 except Exception as error:
791 print("Errore GPS : " + str(error))
792 checkEverything()
793"""
794
795
796def initializeBaseLine(sensor):
797 hum_data = []
798 gas_data = []
799
800 global hum_bl, gas_bl
801
802 hum_bl = 0
803 gas_bl = 0
804
805 print("Loading BaseLine...")
806
807 for i in range(50):
808 if sensor.get_sensor_data():
809 hum_data.append(sensor.data.humidity)
810 if sensor.data.heat_stable:
811 gas_data.append(sensor.data.gas_resistance)
812 time.sleep(5)
813 print("Mancano " + str(250 - ((i + 1) * 5)) + " secondi ", end='\r'),
814 sys.stdout.flush()
815 if hum_data and gas_data:
816 for values in hum_data:
817 hum_bl = hum_bl + values
818 hum_bl = hum_bl / len(hum_data)
819 for values in gas_data:
820 gas_bl = gas_bl + values
821 gas_bl = gas_bl / len(gas_data)
822 else:
823 print("Errore BME : Non ci sono dati per le BaseLine")
824 checkEverything()
825 print("BaseLine OK! ")
826
827def set_nt(temp):
828 x = temp
829 termini = []
830 global nt
831 termini.append(-1.289682539 * pow(10, - 11) * pow(x, 8))
832 termini.append(9.424603166 * pow(10, -10) * pow(x, 7))
833 termini.append(9.027777778 * pow(10, -9) * pow(x, 6))
834 termini.append(-1.52361111 * pow(10, -6) * pow(x, 5))
835 termini.append(2.777777763 * pow(10, -6) * pow(x, 4))
836 termini.append(7.055555551 * pow(10, -4) * pow(x, 3))
837 termini.append(1.144841276 * pow(10, -3) * pow(x, 2))
838 termini.append(- 4.126190473 * pow(10, -2) * x)
839 termini.append(6.999999997 * pow(10, -1))
840 nt_temp= 0
841 for term in termini:
842 nt_temp+=term
843 nt=round(nt_temp,10)
844 return nt
845
846def set_nt_2(temp):
847 x = temp
848 termini = []
849 global nt
850 termini.append(-3.968253966 * pow(10, - 13) * pow(x, 8))
851 termini.append( 4.76190476 * pow(10, -11) * pow(x, 7))
852 termini.append(-1.111111111 * pow(10, -9) * pow(x, 6))
853 termini.append(-4.999999997 * pow(10, -8) * pow(x, 5))
854 termini.append(2.305555555 * pow(10, -6) * pow(x, 4))
855 termini.append(-1.666666689 * pow(10, -6) * pow(x, 3))
856 termini.append(-7.19047619 * pow(10, -4) * pow(x, 2))
857 termini.append(2.561904764 * pow(10, -2) * x)
858 termini.append(1.3)
859 nt_temp= 0
860 for term in termini:
861 nt_temp+=term
862 nt=round(nt_temp,10)
863 return nt
864
865
866def elaborateBMEScoreData(hum, gas):
867 gas_offset = gas_bl - gas
868 hum_offset = hum - hum_bl
869 if hum_offset > 0:
870 hum_score = (100 - hum_bl - hum_offset) / (100 - hum_bl) * (hum_weighting * 100)
871 else:
872 hum_score = (hum_bl + hum_offset) / hum_bl * (hum_weighting * 100)
873
874 if gas_offset > 0:
875 gas_score = (gas / gas_bl) * (100 - (hum_weighting * 100))
876 else:
877 gas_score = 100 - (hum_weighting * 100)
878 air_quality_score = hum_score + gas_score
879 return air_quality_score
880
881def elaborateADSData(data ,temp, humidity):
882
883
884
885 if data:
886 op1=data[0]
887 op2=data[1]
888 nt = set_nt(temp)
889 coeff=0.00196305880253413*0.13 # (44/22414 * 0.13)
890
891 CO=(((op1-C1)-nt*(op2-C2))/SENS)*coeff
892
893 return ("co", '{0:.3g}'.format(CO))
894
895def elaborateADSData_2(data ,temp, humidity):
896
897
898
899 if data:
900 op1=data[0]
901 op2=data[1]
902 nt = set_nt_2(temp)
903 coeff=1.96 # (44/22414 * 0.13)
904 O3=(((op1-K1)-nt*(op2-K2))/SENS_2)*coeff
905
906 return ("o3", '{0:.3g}'.format(O3))
907
908# Modalità
909def energySaverMode():
910 global first_start, first_start_bme, sensor_bme, counter_to_reset, fields_maintenance, values_maintenance, data_log_maintenance, date_last_send
911 global nt
912 data_opc = None
913 data_bme = None
914 data_ads = None
915 data_ads_2=None
916 # data_gps = None
917 data_pms = None
918 check_date(date_last_send, datetime.datetime.now())
919
920 if opc_enabled and status_opc:
921 try:
922 opc_n2 = opc.OPCN2(initializeOPC())
923 opc_n2.set_laser_power(255)
924 opc_n2.set_fan_power(255)
925 opc_n2.on()
926 except Exception as error:
927 print("Error OPC : " + str(error))
928 checkEverything()
929 if pms_enabled and status_pms:
930 pms = initializePMS()
931 if status_bme:
932 bme = initializeBME()
933 if status_ads:
934 ads = initializeADS()
935 # if status_gps:
936 # gps = initializeGPS()
937 GPIO.setup(20, GPIO.OUT)
938 GPIO.setup(21, GPIO.OUT)
939 time.sleep(0.5)
940 GPIO.output(26, 1)
941 GPIO.output(21, 0)
942 GPIO.cleanup(20)
943
944 print("Initializing...")
945 showCountdownTime(15)
946
947 GPIO.output(26, 0)
948 GPIO.cleanup(21)
949
950
951 if first_start and status_bme:
952 if not isMobile:
953 if datetime.datetime.now().hour==0:
954 initializeBaseLine(bme)
955 else:
956 if datetime.datetime.now().hour ==8:
957 initializeBaseLine(bme)
958 first_start = False
959
960 sampling_number = 0
961
962
963 if opc_enabled and status_opc:
964 reset_opc = getOPCData(opc_n2)
965
966 while True:
967 check_date(date_last_send, datetime.datetime.now())
968 # Reset
969 fields = []
970 data = []
971 fields_maintenance = []
972 values_maintenance = []
973 data_log_maintenance = []
974 data_bmeForNo2 = []
975
976 sampling_number = sampling_number + 1
977 showLoaderTime(sampling_time)
978 if opc_enabled and status_opc:
979 data_opc = getOPCData(opc_n2)
980 if status_bme:
981 data_bme = getBMEData(bme)
982 if status_ads:
983 data_ads = getADSData(ads)
984 data_ads_2=getADSData(ads,1)
985 if pms_enabled and status_pms:
986 data_pms = getPMSData(pms)
987 # if status_gps:
988 # data_gps = getGpsData(gps)
989
990 if not first_start_bme:
991
992 if opc_enabled and status_opc:
993 if data_opc != None and data_opc[2][1] != 0:
994 fields = fields + [field_pm2_5, field_pm1, field_pm10]
995 for key, value in data_opc:
996 data.append((key, value))
997 if status_bme:
998 if data_bme != None:
999 fields = fields + [field_temp, field_humidity, field_pressure]
1000 for key, value in data_bme:
1001 if(len(data_bmeForNo2 )!= 2):
1002 data_bmeForNo2.append(value)
1003 data.append((key, value))
1004
1005
1006 if status_ads != None:
1007 if data_ads and data_bme:
1008 fields.append(field_no2)
1009 data.append(elaborateADSData(data_ads, data_bmeForNo2[0], data_bmeForNo2[1]))
1010 if data_ads_2 and data_bme:
1011 fields.append(field_o3)
1012 data.append(elaborateADSData_2(data_ads_2, data_bmeForNo2[0], data_bmeForNo2[1]))
1013
1014 if pms_enabled and status_pms:
1015 if data_pms != None:
1016 fields = fields + [field_pm1, field_pm2_5, field_pm10]
1017 for key, value in data_pms:
1018 data.append((key, value))
1019 anem_data = anem()
1020
1021 if anem_data[0] is True:
1022 fields_maintenance.append(field_dir_vento)
1023 values_maintenance.append(anem_data[1])
1024 fields_maintenance.append(field_int_vento)
1025 values_maintenance.append(anem_data[2])
1026 print("\nDati Anemometro--------")
1027 print("Direzione del vento: " + str(anem_data[1]))
1028 print("Intensità del vento: " + str(anem_data[2]))
1029 elif anem_data[0] is False:
1030 pass
1031 if data:
1032 values = []
1033 for key, value in data:
1034 val = Decimal(value)
1035 values.append(round(val, 2))
1036 '''if status_bme:
1037 if data_bme:
1038 setNT(data_bme[0][1])'''
1039 printSensorData(data)
1040
1041 if sampling_number >= 5:
1042 if save_log_offline or not status_internet:
1043 backupLog(data)
1044 if maintenance_channele_enabled:
1045 status_code = systemChecker()
1046 if status_code:
1047 fields_maintenance.append(field_program_status)
1048 values_maintenance.append(status_code)
1049
1050 try:
1051 tFile = open('/sys/class/thermal/thermal_zone0/temp')
1052 temp = float(tFile.read())
1053 tempC = temp / 1000
1054 fields_maintenance.append(field_cpu_temp)
1055 values_maintenance.append(tempC)
1056 data_log_maintenance.append(("Temp CPU", tempC))
1057 except:
1058 print("", end="")
1059 if status_internet:
1060 fields_maintenance.append(field_nt)
1061 values_maintenance.append(nt)
1062 sendDataToChannelArray(api_key_maintenance, fields_maintenance, values_maintenance)
1063
1064 else:
1065 if values_maintenance:
1066 if data_log_maintenance:
1067 backupLog(data_log_maintenance, "Data_log_maintenance_SSQ_noInternet")
1068 if status_internet:
1069 time.sleep(1)
1070 # Invio ThingSpeak
1071 sendDataToChannelArray(api_key, fields, values)
1072 # invio Firebase
1073 dbFirebase = accessdbFirebaseWithAuth(URL, SECRET_KEY, email)
1074 sendDataToFirebase(dbFirebase, idSensore, fields, fields_maintenance, values,
1075 values_maintenance)
1076 date_last_send = datetime.datetime.now()
1077 with open('timedelta.txt' ,'w') as file:
1078 file.write(str(date_last_send))
1079 print("Appena scritta la data")
1080 if not system_integrity:
1081 counter_to_reset = counter_to_reset + 1
1082 if counter_to_reset >= 10:
1083 counter_to_reset = 0
1084 resetFileCounter("-1")
1085 os.system("reboot")
1086 if opc_enabled and status_opc:
1087 breakTime(opc_n2, None)
1088 elif pms_enabled and status_pms:
1089 breakTime(None, pms)
1090 else:
1091 breakTime()
1092 first_start_bme = False
1093
1094
1095def anem():
1096 import os, urllib, time
1097 # os.system('cd /home/pi/Desktop/swpi-master/TX23 ')
1098
1099 time.sleep(2)
1100 os.system('./readTX23 > /home/pi/anem.txt')
1101 my_path = "/home/pi/anem.txt"
1102 time.sleep(3)
1103 flag = False
1104 x = -1
1105 y = -1
1106
1107 if os.path.exists(my_path) and os.path.getsize(my_path) > 0:
1108
1109 with open('/home/pi/anem.txt', 'r') as file:
1110 data = []
1111
1112 for line in file:
1113 dir_x, vel_y = line.split()
1114 x = int(dir_x)
1115 y = int(vel_y)
1116
1117 flag = True
1118
1119 data.append((x, y))
1120
1121 if not flag:
1122 x = -2
1123 y = -2
1124
1125 # ritorna il flag per far capire se i dati sono consistenti o no
1126 # il secondo valore è la direzione
1127 return [flag, x, y]
1128
1129
1130def heat():
1131 GPIO.setmode(GPIO.BCM) # Broadcom pin-numbering scheme
1132
1133 GPIO.setup(20, GPIO.OUT) # output rf
1134 try:
1135
1136 # print("set GIOP high")
1137 GPIO.output(20, GPIO.LOW)
1138 time.sleep(60)
1139 # GPIO.output(38, GPIO.HIGH)
1140 # except KeyboardInterrupt: # If CTRL+C is pressed, exit cleanly:
1141 # print("Keyboard interrupt")
1142
1143 except KeyboardInterrupt:
1144 pass
1145 finally:
1146
1147 GPIO.cleanup(20)
1148
1149
1150def newFilename(file_error_name):
1151 numb = ''
1152 for i in range(0, len(file_error_name)):
1153
1154 if file_error_name[i].isdigit():
1155 for x in file_error_name[i:]:
1156 numb += x
1157 split = file_error_name.split(file_error_name[i])
1158 file_error_name = split[0] + str(int(numb) + 1).zfill(2)
1159 break
1160 return file_error_name
1161
1162
1163file_error_name = "ErrorFileLog01.txt"
1164import traceback
1165
1166
1167def checkInternet():
1168 try:
1169 test = urllib.urlopen("https://www.google.com")
1170 return True
1171 test.close()
1172 except Exception as error:
1173 return False
1174
1175
1176def check_date(date1, date2):
1177 delta = date2 - date1
1178 seconds = delta.total_seconds()
1179
1180 if seconds >= 600:
1181 print("Chiudo il programma")
1182 sys.exit()
1183 else:
1184 print("Non chiudo")
1185 pass
1186
1187
1188date_last_send = 0
1189
1190
1191def main():
1192 global first_start_bme
1193 first_start_bme = True
1194 global initializedNode
1195 initializedNode = False
1196 if first_start:
1197 if checkInternet() and not initializedNode:
1198 firebaseDB = accessdbFirebaseWithAuth(URL, SECRET_KEY, email)
1199 initializedNode = initializeNode(firebaseDB, idSensore, isMobile, typeNode, zone)
1200 startImage()
1201 setSystemIntegrity()
1202 energySaverMode()
1203
1204
1205if __name__ == '__main__':
1206 print("Starting...")
1207 time.sleep(5)
1208 showCountdownTime(5)
1209 date_last_send = datetime.datetime.now()
1210 with open('timedelta.txt' ,'w') as file:
1211 file.write(str(date_last_send))
1212 print("Appena scritta la data")
1213 try:
1214
1215 main()
1216 except Exception as error:
1217 print(error)
1218 exc_type, exc_value, exc_traceback = sys.exc_info()
1219 t = (traceback.format_exception(exc_type, exc_value, exc_traceback))
1220 print(t)
1221 trac = ''
1222 for x in t:
1223 trac += x
1224 line = "Time: " + str(datetime.datetime.now()) + "\n" + str(error) + "\n" + trac
1225 timex = datetime.datetime.now()
1226 timeforpath = timex.strftime('%Y-%m-%d')
1227 print(timeforpath)
1228 complete_path = os.path.join('/home/pi', 'ErrorLog')
1229 complete_file_error_name = timeforpath + file_error_name
1230 if not os.path.isdir(complete_path):
1231 os.makedirs(complete_path)
1232
1233 f = open(complete_path + "/" + complete_file_error_name, "a")
1234 f.write(str("\n\n------------" + line + "\n"))
1235 f.close()
1236 print("ErrorLog riportato sul file: " + file_error_name)
1237 time.sleep(10)
1238 sys.exit()