diff --git a/Logger.py b/Logger.py index 3c27b4a..08af988 100644 --- a/Logger.py +++ b/Logger.py @@ -5,12 +5,11 @@ import time import sys import traceback import xml.etree.ElementTree as ET -import logging import os from timeFunctions import * -from settings import SensorType -import settings +from settings import SensorType, setup_data_echo, setup_data_log +from settings import settings class Logger(object): def __init__(self, log): @@ -22,29 +21,8 @@ class Logger(object): self.temp_max_diff = settings.tempmaxdiff 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, settings.recordlog)) - 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 + self.dataecho = setup_data_echo() + self.datalog = setup_data_log() def temp_rise(self, old, new,sensor): if(old == self.temp_prev_default): @@ -79,16 +57,15 @@ class Logger(object): return else: self.write_value(value, sensor) - unit = self.units[type] + unit = settings.sensor_properties[type] if not supress: - self.dataecho.info(sensor + ': ' + str(value/unit[0]) + ' ' + unit[1]) + self.dataecho.info(sensor + ': ' + str(value/unit[1]) + ' ' + unit[2]) ########################################### # exception logging # ########################################### def printException(self, inst): - #TODO: LOG - tree = ET.parse(settings.exceptionlog) + tree = ET.parse(os.path.join(settings.log,settings.exceptionlog)) root = tree.getroot() new = ET.Element('exception', {'class':str( type(inst) ).split("'")[1], 'date':str( time.ctime() ), 'time':str( int(time.time()) ), 'type':str(inst)}) new.text = traceback.format_exc() diff --git a/Setup.py b/Setup.py index 5143372..3b439f8 100644 --- a/Setup.py +++ b/Setup.py @@ -14,6 +14,7 @@ except ImportError: from functools import partial import traceback from settings import SensorType +from settings import settings class ConnectionSetup(object): def __init__(self, log): @@ -24,12 +25,12 @@ class ConnectionSetup(object): ipcon.connect(host['name'], host['port']) return (ipcon) - def setupConnectionAndSensors(self, host, sensors, cbtimes, cb_generic): + def setupConnectionAndSensors(self, host, sensors, cb_generic): hostname = host['name'] port = host['port'] ipcon = IPConnection() ipcon.connect(hostname, port) - sensorSetup = SensorSetup(ipcon, sensors, cbtimes, cb_generic, self.log) + sensorSetup = SensorSetup(ipcon, sensors, cb_generic, self.log) connectedSensors = sensorSetup.setupSensors() return (ipcon, connectedSensors) @@ -40,10 +41,9 @@ class ConnectionSetup(object): class SensorSetup(object): - def __init__(self, connection, sensors, cbtimes, cb_generic, log): + def __init__(self, connection, sensors, cb_generic, log): self.connection = connection self.sensors = sensors - self.cbtimes = cbtimes self.cb_generic = cb_generic self.log = log self._previous_sensors={} @@ -117,7 +117,7 @@ class SensorSetup(object): def genericSensorSetup(self, name, sensor): status = "setup device "+ sensor[0] +" ("+ name +"):" callback = self.parametrizedCallback(name, type=sensor[1]) - cbtime = self.cbtimes[sensor[1]] + cbtime = settings.sensor_properties[sensor[1]][0] obj = None if sensor[1] is SensorType.temp: var = self.getTemp() @@ -141,7 +141,7 @@ class SensorSetup(object): obj = self.__setupSensor__(callback, sensor[0], cbtime, var) self.log.info("%s OK", status) except Exception as e: - self.log.error("%s FAIL:: %s",status, e) + self.log.error("%s FAIL:: %s (%s)",status, e,traceback.format_exc()) return obj def setupSensors(self): diff --git a/main.py b/main.py index 07be8d2..e4b511a 100644 --- a/main.py +++ b/main.py @@ -1,30 +1,15 @@ #!/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 +from settings import settings, setupLogger -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, settings.logname)) - fh.setFormatter(formatter) - log.addHandler(fh) - return log - -logi = setupLogger() +log = setupLogger() +lockpath=os.path.join(settings.locks,settings.lockname) def check_dirs_and_files(): # log @@ -41,19 +26,17 @@ def check_dirs_and_files(): if not os.path.exists(settings.records): os.mkdir(settings.records, 0o000755) -def obtainLock(lockfile = settings.lockname): - #TODO: path - if not os.path.exists(lockfile): - lock = open(lockfile, 'w') +def obtainLock(): + if not os.path.exists(lockpath): + lock = open(lockpath, 'w') lock.write( str(time.time()) ) lock.close() return True return False -def freeLock(lockfile = settings.lockname): - #TODO: path - if os.path.exists(lockfile): - os.remove(lockfile) +def freeLock(): + if os.path.exists(lockpath): + os.remove(lockpath) def formatHost(host): return "%s:%d" % (host['name'], host['port']) @@ -64,36 +47,36 @@ if __name__ == "__main__": except NameError: pass check_dirs_and_files() + conSetup = ConnectionSetup(log) + connectedSensors = [] + connections = [] try: - logi.info("setting up all sensors") + log.info("setting up all sensors") while True: if obtainLock(): - logger = Logger(logi) - connections = [] - connectedSensors = [] - for con in settings.SENSORS: + logger = Logger(log) + for con in settings.hosts: 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) + log.info("connecting to host '"+str(con)+"'") + con = settings.hosts[con] + connection, sensors = conSetup.setupConnectionAndSensors(con['host'], con['sensors'], logger.cb_generic) connections.append(connection) connectedSensors.append(sensors) - logi.info("started logging at " + formatHost(con['host'])) + log.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)) + log.error("connection failed: "+str(inst)) input("Press key to restart\n") - logi.info("stop logging... @" + time.ctime() + "\n") + log.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) + ")") + log.critical("lock collision: lock 'all' active") + log.info("wait for retry (" + str(settings.waitDelay) + ")") time.sleep(settings.waitDelay) except KeyboardInterrupt: - logi.info("keyboard-interrupt happened, cleaning up") + log.info("keyboard-interrupt happened, cleaning up") conSetup.disconnectAny(connections) freeLock() diff --git a/move.py b/move.py index 71f335a..9860230 100644 --- a/move.py +++ b/move.py @@ -7,7 +7,8 @@ import logging from shutil import move from timeFunctions import * -from settings import locks, logs, arch, records, movelog, movelock +from settings import settings +#from settings import locks, logs, arch, records, movelog, movelock def setupLogger(): log = logging.getLogger("weatherstation.move") @@ -17,26 +18,26 @@ def setupLogger(): formatter = logging.Formatter('%(asctime)s:[%(levelname)s] - %(message)s') ch.setFormatter(formatter) log.addHandler(ch) - fh = logging.FileHandler(os.path.join(logs, movelog)) + fh = logging.FileHandler(os.path.join(settings.logs, settings.movelog)) fh.setFormatter(formatter) log.addHandler(fh) return log log = setupLogger() -checkfile=os.path.join(locks,movelock) +checkfile=os.path.join(settings.locks,settings.movelock) if not os.path.exists(checkfile): open(checkfile,'w').close() -if not os.path.exists(arch): +if not os.path.exists(settings.arch): os.mkdir(arch, 0o000755) def mycopy(keep): - names = os.listdir(records) + names = os.listdir(settings.records) for name in names: if keep in name: continue - move(os.path.join(records, name), arch) + move(os.path.join(settings.records, name), settings.arch) check=open(checkfile,'r') temp=check.read() diff --git a/set.json b/set.json new file mode 100644 index 0000000..f70b16d --- /dev/null +++ b/set.json @@ -0,0 +1,40 @@ +{ + "hosts": { + "irtest": { + "host":{ + "name": "localhost", + "port":4223 + }, + "sensors":{ + "iram": ["c8w", "SensorType.iram"], + "irob": ["c8w", "SensorType.irob"] + } + } + }, + "sensor_properties":{ + "SensorType.none": [0, 0, ""], + "SensorType.temp": [30000, 100.0, "°C"], + "SensorType.humi": [30000, 10.0, "%RH"], + "SensorType.ambi": [60000, 10.0, "Lux"], + "SensorType.baro": [60000, 1000, "mbar"], + "SensorType.rain": [0, 2.5, "l/qm"], + "SensorType.iram": [1000, 10.0, "°C"], + "SensorType.irob": [1000, 10.0, "°C"] + }, + "tempmaxdiff": 200, + "prev_temps_default": 20000, + "logs": "logs", + "locks": "locks", + "records": "records", + "arch": "arch", + "lockname": "all.lock", + "logname": "logging.log", + "exceptionlog": "exceptions.xml", + "recordlog": "record.log", + "movelog": "move.log", + "movelock": "last_move", + "waitDelay" : 10, + "loglevel": "info", + "datalog": "info", + "dataecho": "info" +} diff --git a/settings.py b/settings.py index 5e904dc..908da6b 100644 --- a/settings.py +++ b/settings.py @@ -1,7 +1,10 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- -#class SensorType(Enum): +import json +import logging +import os + class SensorType: none = 0 temp = 1 # temperature bricklet @@ -12,69 +15,110 @@ class SensorType: iram = 6 # temperature ir bricklet, ambient irob = 7 # temperature ir bricklet, object -SENSORS={ - "irtest": { - "host":{"name": "localhost", "port":4223}, - "sensors":{ - "iram": ["c8w", SensorType.iram], - "irob": ["c8w", SensorType.irob] - } - } +DEFAULTS ={ + "hosts":{ + "HOSTDESC_i":{ + "host":{"name":"HOSTNAME_OR_IP","port":4223}, + "sensors":{ + "NAME":["UID", "SensorType.TYPE"]} + } + }, + "sensor_properties":{ + "SensorType.none": [0, 0, ""], + "SensorType.temp": [30000, 100.0, "°C"], + "SensorType.humi": [30000, 10.0, "%RH"], + "SensorType.ambi": [60000, 10.0, "Lux"], + "SensorType.baro": [60000, 1000, "mbar"], + "SensorType.rain": [0, 2.5, "l/qm"], + "SensorType.iram": [1000, 10.0, "°C"], + "SensorType.irob": [1000, 10.0, "°C"]}, + "tempmaxdiff":200, + "prev_temps_default":20000, + "logs":'logs', + "locks":'locks', + "records":'records', + "arch":'arch', + "lockname":"all.lock", + "logname":"logging.log", + "exceptionlog":"exceptions.xml", + "recordlog":"record.log", + "movelog":"move.log", + "movelock":"last_move", + "waitDelay":10, + "tempSensors":0, + "loglevel": "info", + "datalog": "info", + "dataecho": "info" } +class Settings(dict): + def __getattr__(self,name): + if name in self: + return self[name] + return DEFAULTS[name] + def __setattr__(self,name,value): + self[name]=value + def __delattr__(self,name): + del self[name] +def load_json(filename="set.json"): + values=json.load(open('set.json'), object_hook=Settings) + sensors_name="hosts" + if sensors_name in values: + for host in values[sensors_name]: + for sensor in values[sensors_name][host]["sensors"]: + sensor = values[sensors_name][host]["sensors"][sensor] + sensor[1] = eval(sensor[1]) + sensor_props = "sensor_properties" + if sensor_props in values: + new_units={} + for unit in values[sensor_props]: + new_units[eval(unit)] = values[sensor_props][unit] + values[sensor_props] = new_units + return values +def setupLogger(): + level = getattr(logging, settings.loglevel.upper(), logging.INFO) + log = logging.getLogger("weatherstation") + log.setLevel(level) + ch = logging.StreamHandler() + #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, settings.logname)) + fh.setFormatter(formatter) + log.addHandler(fh) + return log -TIMES={ - SensorType.temp: 30000, - SensorType.humi: 30000, - SensorType.ambi: 60000, - SensorType.baro: 60000, - SensorType.rain: 0, - SensorType.iram: 60000, - SensorType.irob: 60000, -} +def setup_data_log(): + level = getattr(logging, settings.datalog.upper(), logging.INFO) + log = logging.getLogger("weatherstation.datalog") + log.setLevel(level) + fh = logging.FileHandler(os.path.join(settings.records, settings.recordlog)) + fformat = logging.Formatter() + fh.setFormatter(fformat) + log.addHandler(fh) + log.propagate = False + return log -tempmaxdiff=200 # 200== 2.0 C -prev_temps_default=20000 - -logs='logs' -locks='locks' -records='records' -arch='arch' - -#TODO: lockname, exceptionslog: path.join -lockname=locks+"/all.lock" -logname="logging.log" -exceptionlog=logs+"/exceptions.xml" -recordlog="record.log" -movelog="move.log" -movelock="last_move" - -waitDelay = 10 - -######################################## -# only change when new sensor is added # -######################################## - -SENSOR_UNITS=[ - (0,''), - (100.0, '°C'), - (10.0, '%RH'), - (10.0, 'Lux'), - (1000, 'mbar'), - (2.5, 'l/qm'), - (10.0, '°C'), - (10.0, '°C') -] - -########################### -# no manual change needed # -########################### - -tempSensors=0 -for i in SENSORS: - for j in SENSORS[i]['sensors']: - if SENSORS[i]['sensors'][j][1] == SensorType.temp: - tempSensors+=1 +def setup_data_echo(): + level = getattr(logging, settings.dataecho.upper(), logging.INFO) + log = logging.getLogger("weatherstation.data") + log.setLevel(level) + ch = logging.StreamHandler() + formatter = logging.Formatter('%(asctime)s:[DATA] - %(message)s') + ch.setFormatter(formatter) + log.addHandler(ch) + log.propagate = False + return log +settings=load_json() +hosts_name = "hosts" +if hosts_name in settings: + tempSensors=0 + for i in settings[hosts_name]: + for j in settings[hosts_name][i]['sensors']: + if settings[hosts_name][i]['sensors'][j][1] == SensorType.temp: + tempSensors+=1 + settings.tempSensors=tempSensors """ 0: { "host": {