From b8e12b777ebabaa05383ab0a57f1c4e000c47feb Mon Sep 17 00:00:00 2001 From: "Warkanum@Anya" Date: Mon, 6 Apr 2015 16:33:34 +0200 Subject: [PATCH] Fixed the issues with threads. Should not work more stable and not crash. --- build1/boot.py | 308 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 202 insertions(+), 106 deletions(-) diff --git a/build1/boot.py b/build1/boot.py index 9ef845e..728b568 100755 --- a/build1/boot.py +++ b/build1/boot.py @@ -1,5 +1,6 @@ -#!/usr/bin/python3 -from threading import Thread +#!/opt/python3.3/bin/python3.3 +##!/usr/bin/python3 +import threading import RPi.GPIO as GPIO import time @@ -9,8 +10,11 @@ import sys import dht11_sensor import psycopg2 import copy +import logging +import queue ###-----------------Hardware Settings----------------------- +logging.basicConfig(filename='boot.log',level=logging.WARNING) PIN_LC=25 #Light Sensor (GPIO.IN, pull_up_down=GPIO.PUD_UP) PIN_MC=17 #Motion Sensor (GPIO.IN, pull_up_down=GPIO.PUD_UP) @@ -39,39 +43,104 @@ GPIO.setup(PIN_MC, GPIO.IN, pull_up_down=GPIO.PUD_UP) GPIO.output(PIN_LED1,GPIO.LOW) GPIO.output(PIN_LED2,GPIO.LOW) +WORK_QUE = queue.Queue(4096) + + +class SaveThread(threading.Thread): + def __init__(self, name='Saving Thread'): + threading.Thread.__init__(self) + self.name = name + self.quit = False + logging.info(self.name + ' starting thread') + self.pgconn = psycopg2.connect(host=SQL_SRV, user=SQL_USER,password=SQL_PASSWD,database=SQL_DB, application_name="PiDevWarkanum") + + + def __del__(self): + if self.pgconn: + self.pgconn.close() + + def stop(self): + self.quit = True + + def run(self): + while True: + if self.quit: + logging.debug(self.name + ' Quit!') + break + + try: + print('Check Jobs.') + while True: + item = WORK_QUE.get() + WORK_QUE.task_done() + + if not item: + break + else: + print('Job left: ' + str(WORK_QUE.qsize())) + + results = save_data(item, self.pgconn) + logging.debug(self.name + ' Completed job') + del item + + print('Completed job.') + + #Sleep + time.sleep(0.5) + + + except KeyboardInterrupt as e: + logging.warning(self.name + ' Keyboard Interrupt. ' + str(e)) + break + + except: + errordetail = str(sys.exc_info()) + logging.error(self.name + ' Error: '+errordetail) + time.sleep(0.5) + + def UnixLocalEpoch(): dt = datetime.datetime.now() return int((dt - datetime.datetime(1970,1,1)).total_seconds()) def PhotoSensor(RCpin): - reading = 0 - GPIO.setup(RCpin, GPIO.OUT) - GPIO.output(RCpin, GPIO.LOW) - time.sleep(0.1) + try: + reading = 0 + GPIO.setup(RCpin, GPIO.OUT) + GPIO.output(RCpin, GPIO.LOW) + time.sleep(0.1) - GPIO.setup(RCpin, GPIO.IN) - # This takes about 1 millisecond per loop cycle - while (GPIO.input(RCpin) == GPIO.LOW): - reading += 1 + GPIO.setup(RCpin, GPIO.IN) + # This takes about 1 millisecond per loop cycle + while (GPIO.input(RCpin) == GPIO.LOW): + reading += 1 + except: + errordetail = str(sys.exc_info()[0]) + logging.error('PhotoSensor Error: '+errordetail) + reading = 0 + return reading def TempsensorRead(): ### Loop through the temp sensor library until we get a valid reading ### + try: - for i in range(1,100): - data = dht11_sensor.read(PIN_TC_WP) - #print('Temp={0}*C Humidity={1}% Status={2} Error={3}'.format(data['temperature'], data['humidity'], data['valid'], data['err'])) - if data['valid'] == 1: + for i in range(1,100): + data = dht11_sensor.read(PIN_TC_WP) + #print('Temp={0}*C Humidity={1}% Status={2} Error={3}'.format(data['temperature'], data['humidity'], data['valid'], data['err'])) + if data['valid'] == 1: return data + except: + errordetail = str(sys.exc_info()[0]) + logging.error('TempsensorRead Error: '+errordetail) return None -def save_data(p_SensorValues): +def save_data(p_SensorValues, p_sql_connection): try: - sql_con = psycopg2.connect(host=SQL_SRV, user=SQL_USER,password=SQL_PASSWD,database=SQL_DB) - sql_cur = sql_con.cursor() + sql_cur = p_sql_connection.cursor() print('2temp->' + str(p_SensorValues['temperature']['save'])) print('2light->' + str(p_SensorValues['light']['save'])) @@ -112,9 +181,9 @@ def save_data(p_SensorValues): VALUES(%s, %s, TIMESTAMP 'epoch' + %s * INTERVAL '1 second',TIMESTAMP 'epoch' + %s * INTERVAL '1 second')""", ('humidity', p_SensorValues['temperature']['humidity'], p_SensorValues['temperature']['read'], p_SensorValues['temperature']['read'] )) - sql_con.commit() + p_sql_connection.commit() sql_cur.close() - sql_con.close() + except psycopg2.Error as e: print("SQL error in save_data: " + str(e)) @@ -124,98 +193,125 @@ def save_data(p_SensorValues): def main(): - SensorValue = {} - TICK_LT = 0 #light detect ticker - TICK_LTI = 0 #light insert ticker - TICK_TMP = 0 #temp ticker - - BlueLed = False + t = SaveThread() + t.setDaemon(True) + t.start() - while True: - changed = False - + try: - motionData = GPIO.input(PIN_MC) - if not SensorValue.get('motion', None): - SensorValue['motion'] = {'data': motionData , 'read': UnixLocalEpoch(), 'changed': UnixLocalEpoch(), 'save': False} - - SensorValue['motion']['save'] = False - - if int(SensorValue['motion'].get('data', 0)) != int(motionData) : - changed = True - SensorValue['motion']['changed'] = UnixLocalEpoch() - SensorValue['motion']['save'] = True - SensorValue['motion']['data'] = int(motionData) - SensorValue['motion']['read'] = UnixLocalEpoch() - - - if (SensorValue['motion']['data'] > 0): - #GPIO.output(PIN_LED1,GPIO.HIGH) #flash led - SensorValue['motion']['lastmotion'] = UnixLocalEpoch() - BlueLed = True - else: - #GPIO.output(PIN_LED1,GPIO.LOW) #flash led stop - BlueLed = False + SensorValue = {} + TICK_LT = 0 #light detect ticker + TICK_LTI = 0 #light insert ticker + TICK_TMP = 0 #temp ticker + + BlueLed = False - #Measure Light - if not SensorValue.get('light', None): - SensorValue['light'] = {'data': PhotoSensor(PIN_LC) , 'read': UnixLocalEpoch(), 'save': False } - - SensorValue['light']['save'] = False - - lightChanges = 0 - if (TICK_LT < time.perf_counter()): - TICK_LT = time.perf_counter()+1 - lightData = PhotoSensor(PIN_LC) - lightChanges = abs(SensorValue['light'].get('data', 0) - lightData) - #print("LC->" + str(lightData ) + "DF:" + str(lightChanges)) - - if (TICK_LTI < time.perf_counter() or (lightData > 600 and lightChanges > 200) or (lightData < 600 and lightChanges > 30)): - TICK_LTI = time.perf_counter()+30 - - if SensorValue['light'].get('data', 0) != lightData : - changed = True - SensorValue['light']['changed'] = UnixLocalEpoch() - SensorValue['light']['save'] = True - - SensorValue['light']['data'] = lightData - SensorValue['light']['read'] = UnixLocalEpoch() - - #Measure Temprature, this might hold the thread for a few seconds at most. - if not SensorValue.get('temperature', None): - SensorValue['temperature'] = {'temperature': 0, 'humidity': 0, 'changed': 0, 'save': False} - - SensorValue['temperature']['save'] = False - - if (TICK_TMP < time.perf_counter()): - TICK_TMP = time.perf_counter()+10 - tempData = TempsensorRead() - if tempData: - print('temperature reading...') - if (SensorValue['temperature'].get('temperature', 0) != tempData['temperature'] - or SensorValue['temperature'].get('humidity', 0) != tempData['humidity']): - SensorValue['temperature']['changed'] = UnixLocalEpoch() - SensorValue['temperature']['temperature'] = tempData['temperature'] - SensorValue['temperature']['humidity'] = tempData['humidity'] - SensorValue['temperature']['save'] = True - changed = True - SensorValue['temperature']['read'] = UnixLocalEpoch() - - if changed: - print('---------------change-------------') - print('temp->' + str(SensorValue['temperature']['save'])) - print('light->' + str(SensorValue['light']['save'])) - print('motion->' + str(SensorValue['motion']['save'])) - #Gosh we need a copy cause sql can be to slow sometimes - - ThreadsData = copy.deepcopy(SensorValue) - t = Thread(target=save_data, args=(ThreadsData,)) - t.start() + while True: + changed = False + + try: + motionData = GPIO.input(PIN_MC) + if not SensorValue.get('motion', None): + SensorValue['motion'] = {'data': motionData , 'read': UnixLocalEpoch(), 'changed': UnixLocalEpoch(), 'save': False} - - time.sleep(0.01) + SensorValue['motion']['save'] = False + + if int(SensorValue['motion'].get('data', 0)) != int(motionData) : + changed = True + SensorValue['motion']['changed'] = UnixLocalEpoch() + SensorValue['motion']['save'] = True + SensorValue['motion']['data'] = int(motionData) + SensorValue['motion']['read'] = UnixLocalEpoch() + + + if (SensorValue['motion']['data'] > 0): + #GPIO.output(PIN_LED1,GPIO.HIGH) #flash led + SensorValue['motion']['lastmotion'] = UnixLocalEpoch() + BlueLed = True + else: + #GPIO.output(PIN_LED1,GPIO.LOW) #flash led stop + BlueLed = False + + + #Measure Light + if not SensorValue.get('light', None): + SensorValue['light'] = {'data': PhotoSensor(PIN_LC) , 'read': UnixLocalEpoch(), 'save': False } + + SensorValue['light']['save'] = False + + lightChanges = 0 + if (TICK_LT < time.perf_counter()): + TICK_LT = time.perf_counter()+1 + lightData = PhotoSensor(PIN_LC) + lightChanges = abs(SensorValue['light'].get('data', 0) - lightData) + #print("LC->" + str(lightData ) + "DF:" + str(lightChanges)) + + if (TICK_LTI < time.perf_counter() or (lightData > 600 and lightChanges > 200) or (lightData < 600 and lightChanges > 30)): + TICK_LTI = time.perf_counter()+30 + + if SensorValue['light'].get('data', 0) != lightData : + changed = True + SensorValue['light']['changed'] = UnixLocalEpoch() + SensorValue['light']['save'] = True + + SensorValue['light']['data'] = lightData + SensorValue['light']['read'] = UnixLocalEpoch() + + #Measure Temprature, this might hold the thread for a few seconds at most. + if not SensorValue.get('temperature', None): + SensorValue['temperature'] = {'temperature': 0, 'humidity': 0, 'changed': 0, 'save': False} + + SensorValue['temperature']['save'] = False + + if (TICK_TMP < time.perf_counter()): + TICK_TMP = time.perf_counter()+10 + tempData = TempsensorRead() + if tempData: + print('temperature reading...') + if (SensorValue['temperature'].get('temperature', 0) != tempData['temperature'] + or SensorValue['temperature'].get('humidity', 0) != tempData['humidity']): + SensorValue['temperature']['changed'] = UnixLocalEpoch() + SensorValue['temperature']['temperature'] = tempData['temperature'] + SensorValue['temperature']['humidity'] = tempData['humidity'] + SensorValue['temperature']['save'] = True + changed = True + SensorValue['temperature']['read'] = UnixLocalEpoch() + + if changed: + print('---------------change-------------') + print('temp->' + str(SensorValue['temperature']['save'])) + print('light->' + str(SensorValue['light']['save'])) + print('motion->' + str(SensorValue['motion']['save'])) + #Gosh we need a copy cause sql can be to slow sometimes + + WORK_QUE.put(copy.deepcopy(SensorValue), False) + + #ThreadsData = copy.deepcopy(SensorValue) + #t = Thread(target=save_data, args=(ThreadsData,)) + #t.start() + + except KeyboardInterrupt as e: + logging.warning('Loop Keyboard Interrupt.') + t.stop() + break + + except: + errordetail = str(sys.exc_info()[0]) + logging.error('Loop Error: '+errordetail) + + time.sleep(0.01) + + except KeyboardInterrupt as e: + logging.warning('Main Keyboard Interrupt.') + t.stop() + + except: + errordetail = str(sys.exc_info()[0]) + logging.error('Main Error: '+errordetail) + + t.stop() if __name__ == '__main__': - sys.exit(main()) \ No newline at end of file + sys.exit(main())