diff --git a/ConnectionSetup.py b/ConnectionSetup.py deleted file mode 100644 index a697143..0000000 --- a/ConnectionSetup.py +++ /dev/null @@ -1,31 +0,0 @@ -#!/usr/bin/python3 -# -*- coding: utf-8 -*- - -try: - from tinkerforge.ip_connection import IPConnection -except ImportError: - print("package 'tinkerforge' not installed, canceling") - raise -from SensorSetup import SensorSetup - -class ConnectionSetup(object): - - def setupConnection(self, host): - ipcon = IPConnection() - ipcon.connect(host['name'], host['port']) - return (ipcon) - - def setupConnectionAndSensors(self, host, sensors, cbtimes, cb_generic): - hostname = host['name'] - port = host['port'] - ipcon = IPConnection() - ipcon.connect(hostname, port) - sensorSetup = SensorSetup(ipcon, sensors, cbtimes, cb_generic) - connectedSensors = sensorSetup.setupSensors() - return (ipcon, connectedSensors) - - def disconnectAny(self, connections): - for connection in connections: - if not connection.get_connection_state() is IPConnection.CONNECTION_STATE_DISCONNECTED: - connection.disconnect() - diff --git a/Logger.py b/Logger.py index b6019d7..68c62ff 100644 --- a/Logger.py +++ b/Logger.py @@ -5,6 +5,8 @@ import time import sys import traceback import xml.etree.ElementTree as ET +import logging +import os from timeFunctions import * from settings import SensorType @@ -21,13 +23,34 @@ class Logger(object): self.log = log self.records = settings.records self.units = settings.SENSOR_UNITS + self.dataecho = self.setup_data_echo() + self.datalog = self.setup_data_log() + + def setup_data_log(self): + log = logging.getLogger("weatherstation.datalog") + log.setLevel(logging.INFO) + fh = logging.FileHandler(os.path.join(settings.records, "records.log")) + fformat = logging.Formatter() + fh.setFormatter(fformat) + log.addHandler(fh) + log.propagate = False + return log + + def setup_data_echo(self): + log = logging.getLogger("weatherstation.data") + log.setLevel(logging.INFO) + ch = logging.StreamHandler() + formatter = logging.Formatter('%(asctime)s:[DATA] - %(message)s') + ch.setFormatter(formatter) + log.addHandler(ch) + log.propagate = False + return log def temp_rise(self, old, new,sensor): if(old == self.temp_prev_default): return True if(((old-new) > self.temp_max_diff) or ((new-old) > self.temp_max_diff)): - self.log.write('error checking ' + sensor + ';prev(' + str(old) + ');cur(' + str(new) + '); ... @' + time.ctime() + "\n") - self.log.flush() + self.log.error('error checking ' + sensor + ';prev(' + str(old) + ');cur(' + str(new) + ');') return False else: return True @@ -36,11 +59,12 @@ class Logger(object): # common function to write value to file # ########################################## def write_value(self, value, sensor): - # TODO: catch IOError + # TODO: replace with self.datalog valuename = self.records + "/" + sensor + "_" + preptime() valuelog=open(valuename, 'a') valuelog.write(str(value) + ';' + str( int(time.time()) ) + "\n") valuelog.close() + self.datalog.info('%s;%s;%s',value, int(time.time()), sensor) ########################################## # generic callback # @@ -57,7 +81,7 @@ class Logger(object): self.write_value(value, sensor) unit = self.units[type] if not supress: - print(sensor + ': ' + str(value/unit[0]) + ' ' + unit[1] + ', ' + str(time.ctime()) ) + self.dataecho.info(sensor + ': ' + str(value/unit[0]) + ' ' + unit[1]) ########################################### # exception logging # @@ -70,7 +94,6 @@ class Logger(object): root.append(new) tree.write(settings.exceptionlog) message = 'an Exception happend @' + time.ctime()+"\n" - self.log.write(message) - self.log.flush() + self.log.error(message) print(message) diff --git a/SensorSetup.py b/Setup.py similarity index 60% rename from SensorSetup.py rename to Setup.py index ddd8ea3..5a86b78 100644 --- a/SensorSetup.py +++ b/Setup.py @@ -2,10 +2,12 @@ # -*- coding: utf-8 -*- try: + from tinkerforge.ip_connection import IPConnection from tinkerforge.bricklet_temperature import Temperature from tinkerforge.bricklet_humidity import Humidity from tinkerforge.bricklet_ambient_light import AmbientLight from tinkerforge.bricklet_barometer import Barometer + from tinkerforge.bricklet_temperature_ir import BrickletTemperatureIR except ImportError: print("package 'tinkerforge' not installed, canceling") raise @@ -13,13 +15,37 @@ from functools import partial import traceback from settings import SensorType +class ConnectionSetup(object): + def __init__(self, log): + self.log = log + + def setupConnection(self, host): + ipcon = IPConnection() + ipcon.connect(host['name'], host['port']) + return (ipcon) + + def setupConnectionAndSensors(self, host, sensors, cbtimes, cb_generic): + hostname = host['name'] + port = host['port'] + ipcon = IPConnection() + ipcon.connect(hostname, port) + sensorSetup = SensorSetup(ipcon, sensors, cbtimes, cb_generic, self.log) + connectedSensors = sensorSetup.setupSensors() + return (ipcon, connectedSensors) + + def disconnectAny(self, connections): + for connection in connections: + if not connection.get_connection_state() is IPConnection.CONNECTION_STATE_DISCONNECTED: + connection.disconnect() + class SensorSetup(object): - def __init__(self, connection, sensors, cbtimes, cb_generic): + def __init__(self, connection, sensors, cbtimes, cb_generic, log): self.connection = connection self.sensors = sensors self.cbtimes = cbtimes self.cb_generic = cb_generic + self.log = log def parametrizedCallback(self, name, type): return partial(self.cb_generic, sensor=name, type=type) @@ -52,6 +78,20 @@ class SensorSetup(object): cb = Barometer.CALLBACK_AIR_PRESSURE return obj, setcb, get, cb + def getIram(self): + obj = BrickletTemperatureIR # Object + setcb = obj.set_ambient_temperature_callback_period # set-callback-period-method-pointer + get = obj.get_ambient_temperature # value-get-method-pointer + cb = BrickletTemperatureIR.CALLBACK_AMBIENT_TEMPERATURE # callback identifier + return obj, setcb, get, cb + + def getIrob(self): + obj = BrickletTemperatureIR # Object + setcb = obj.set_object_temperature_callback_period # set-callback-period-method-pointer + get = obj.get_object_temperature # value-get-method-pointer + cb = BrickletTemperatureIR.CALLBACK_OBJECT_TEMPERATURE # callback identifier + return obj, setcb, get, cb + #def getNew(self): # obj = Bricklet # Object # setcb = obj.set_XXX_callback_period # set-callback-period-method-pointer @@ -79,14 +119,22 @@ class SensorSetup(object): var = self.getAmbi() elif sensor[1] is SensorType.baro: var = self.getBaro() + elif sensor[1] is SensorType.iram: + var = self.getIram() + elif sensor[1] is SensorType.irob: + var = self.getIrob() + else: + self.log.error("FAILED TO LOAD "+name) + return None try: obj = self.__setupSensor__(callback, sensor[0], cbtime, var) status += "OK" + self.log.info(status) except Exception as e: status += "FAIL" #print(e) #print(traceback.format_exc()) - print(status) + self.log.error(status) return obj def setupSensors(self): @@ -96,3 +144,4 @@ class SensorSetup(object): obj = self.genericSensorSetup(name, sensor) connected.append(obj) return connected + diff --git a/all.py b/all.py deleted file mode 100644 index 546de80..0000000 --- a/all.py +++ /dev/null @@ -1,82 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- - -import os.path -import os -import time - -from Logger import Logger -from ConnectionSetup import ConnectionSetup -import settings - -def check_dirs_and_files(): - # log - if not os.path.exists(settings.logs): - os.mkdir(settings.logs, 0000755) - if not os.path.exists(settings.logname): - open(settings.logname, 'w').close() - if not os.path.exists(settings.exceptionlog): - file=open(settings.exceptionlog, 'w') - file.write("") - file.close() - # lock - if not os.path.exists(settings.locks): - os.mkdir(settings.locks, 0000755) - # records - if not os.path.exists(settings.records): - os.mkdir(settings.records, 0000755) - -def obtainLock(lockfile = settings.lockname): - if not os.path.exists(lockfile): - lock = open(lockfile, 'w') - lock.write( str(time.time()) ) - lock.close() - return True - return False - -def freeLock(lockfile = settings.lockname): - if os.path.exists(lockfile): - os.remove(lockfile) - -def formatHost(host): - return "%s:%d" % (host['name'], host['port']) - -if __name__ == "__main__": - check_dirs_and_files() - log=open(settings.logname, 'a') - try: - log.write("setting up all ... @" + time.ctime() + "\n") - while True: - if obtainLock(): - logger = Logger(log) - try: - connections = [] - connectedSensors = [] - for con in settings.SENSORS: - con = settings.SENSORS[con] - conSetup = ConnectionSetup() - connection, sensors = conSetup.setupConnectionAndSensors(con['host'], con['sensors'], settings.TIMES, logger.cb_generic) - connections.append(connection) - connectedSensors.append(sensors) - log.write("started logging at " + formatHost(con['host']) + " ... @ " + time.ctime() + "\n") - log.flush() - raw_input("Press key to restart\n") - log.write("stop logging... @" + time.ctime() + "\n") - conSetup.disconnectAny(connections) - except Exception as inst: - #connection failed, log and exit - logger.printException(inst) - print(inst) - freeLock() - else: - print("lock file active!!") - log.write("lock collision: lock 'all' active @ " + time.ctime() + "\n") - print("wait for retry (" + str(settings.waitDelay) + ")") - time.sleep(settings.waitDelay) - except KeyboardInterrupt: - print(" Interrupted, cleaning up") - conSetup.disconnectAny(connections) - log.write("keyboard-interrupt happened @" + time.ctime() + "\n") - log.close() - freeLock() - diff --git a/main.py b/main.py new file mode 100644 index 0000000..378df7d --- /dev/null +++ b/main.py @@ -0,0 +1,95 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +import os.path +import os +import time +import logging + +from Logger import Logger +from Setup import ConnectionSetup +import settings + +def setupLogger(): + log = logging.getLogger("weatherstation") + log.setLevel(logging.INFO) + ch = logging.StreamHandler() + ch.setLevel(logging.DEBUG) + #formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') + formatter = logging.Formatter('%(asctime)s:[%(levelname)s] - %(message)s') + ch.setFormatter(formatter) + log.addHandler(ch) + fh = logging.FileHandler(os.path.join(settings.logs, "logging.log")) + fh.setFormatter(formatter) + log.addHandler(fh) + return log + +logi = setupLogger() + +def check_dirs_and_files(): + # log + if not os.path.exists(settings.logs): + os.mkdir(settings.logs, 0000755) + #if not os.path.exists(settings.logname): + # open(settings.logname, 'w').close() + if not os.path.exists(settings.exceptionlog): + file=open(settings.exceptionlog, 'w') + file.write("") + file.close() + # lock + if not os.path.exists(settings.locks): + os.mkdir(settings.locks, 0000755) + # records + if not os.path.exists(settings.records): + os.mkdir(settings.records, 0000755) + +def obtainLock(lockfile = settings.lockname): + if not os.path.exists(lockfile): + lock = open(lockfile, 'w') + lock.write( str(time.time()) ) + lock.close() + return True + return False + +def freeLock(lockfile = settings.lockname): + if os.path.exists(lockfile): + os.remove(lockfile) + +def formatHost(host): + return "%s:%d" % (host['name'], host['port']) + +if __name__ == "__main__": + check_dirs_and_files() + try: + logi.info("setting up all sensors") + while True: + if obtainLock(): + logger = Logger(logi) + connections = [] + connectedSensors = [] + for con in settings.SENSORS: + try: + logi.info("connecting to host '"+str(con)+"'") + con = settings.SENSORS[con] + conSetup = ConnectionSetup(logi) + connection, sensors = conSetup.setupConnectionAndSensors(con['host'], con['sensors'], settings.TIMES, logger.cb_generic) + connections.append(connection) + connectedSensors.append(sensors) + logi.info("started logging at " + formatHost(con['host'])) + except Exception as inst: + #connection failed, log and exit + #TODO: logger.printException(inst) + logi.error("connection failed: "+str(inst)) + raw_input("Press key to restart\n") + logi.info("stop logging... @" + time.ctime() + "\n") + conSetup.disconnectAny(connections) + freeLock() + else: + logi.critical("lock collision: lock 'all' active") + logi.info("wait for retry (" + str(settings.waitDelay) + ")") + time.sleep(settings.waitDelay) + except KeyboardInterrupt: + logi.info("keyboard-interrupt happened, cleaning up") + conSetup.disconnectAny(connections) + freeLock() + diff --git a/move.py b/move.py index 4d4167d..c70df56 100644 --- a/move.py +++ b/move.py @@ -3,9 +3,9 @@ import time import os +from shutil import move from timeFunctions import * from settings import locks, logs -from shutil import move checkfile=locks+'/records_moved' diff --git a/settings.py b/settings.py index 4944822..298145a 100644 --- a/settings.py +++ b/settings.py @@ -4,19 +4,14 @@ #class SensorType(Enum): class SensorType: none = 0 - temp = 1 - humi = 2 - ambi = 3 - baro = 4 - rain = 5 - - -#HOST = "localhost" -#HOST = "192.168.2.34" -HOST = "192.168.2.60" -PORT = 4223 - -SENSORS={ + temp = 1 # temperature bricklet + humi = 2 # humidity bricklet + ambi = 3 # ambient light bricklet + baro = 4 # barometer bricklet + rain = 5 # IO4 #TODO + iram = 6 # temperature ir bricklet, ambient #TODO + irob = 7 # temperature ir bricklet, object #TODO +""" 0: { "host": { "name": "192.168.2.60", @@ -32,6 +27,15 @@ SENSORS={ "temp3": ["8ms", SensorType.temp], "humi2": ["9V5", SensorType.humi], } + },""" +SENSORS={ + "irtest": { + "host":{"name": "localhost", "port":4223}, + "sensors":{ + "iram": ["c8w", SensorType.iram], + "iram2": ["c8ws", SensorType.iram], + "irob": ["c8w", SensorType.irob] + } } } @@ -40,6 +44,9 @@ TIMES={ SensorType.humi: 30000, SensorType.ambi: 60000, SensorType.baro: 60000, + SensorType.rain: 60000, + SensorType.iram: 1000, + SensorType.irob: 1000, } tempmaxdiff=200 # 200== 2.0 C @@ -49,6 +56,7 @@ logs='logs' locks='locks' records='records' +#TODO: add move-log, move-lock, logging instead of writing to files lockname=locks+"/all.lock" logname=logs+"/all.log" exceptionlog=logs+"/exceptions.xml" @@ -65,7 +73,9 @@ SENSOR_UNITS=[ (10.0, '%RH'), (10.0, 'Lux'), (1000, 'mbar'), - (2.5, 'l/qm') + (2.5, 'l/qm'), + (10.0, '°C'), + (10.0, '°C') ] ###########################