104 lines
4.0 KiB
Python
104 lines
4.0 KiB
Python
#!/usr/bin/python3
|
|
# -*- coding: utf-8 -*-
|
|
|
|
from functools import partial
|
|
import traceback
|
|
|
|
try:
|
|
from tinkerforge.ip_connection import IPConnection
|
|
except ImportError:
|
|
print("package 'tinkerforge' not installed, canceling")
|
|
raise Exception("package 'tinkerforge' not installed, canceling")
|
|
|
|
from config import SensorType, settings, SENSOR_CONFIGS
|
|
|
|
|
|
class ConnectionSetup(object):
|
|
def __init__(self, log):
|
|
self.log = log
|
|
self.__connections__ = []
|
|
|
|
def setup_connection(self, host):
|
|
ipcon = IPConnection()
|
|
try:
|
|
ipcon.connect(host['name'], host['port'])
|
|
self.log.info("connection to '%s:%s' established", host['name'], host['port'])
|
|
except ConnectionError:
|
|
self.log.error("connection to '%s:%s' failed", host['name'], host['port'])
|
|
self.__connections__.append(ipcon)
|
|
return ipcon
|
|
|
|
def setup_connection_and_sensors(self, host, sensors, logger):
|
|
ipcon = self.setup_connection(host)
|
|
sensor_setup = SensorSetup(ipcon, sensors, logger, self.log)
|
|
connected_sensors = sensor_setup.setup_sensors()
|
|
return ipcon, connected_sensors
|
|
|
|
def disconnect_any(self, connections):
|
|
if connections is None:
|
|
connections = self.__connections__
|
|
for connection in connections:
|
|
if not connection.get_connection_state() is IPConnection.CONNECTION_STATE_DISCONNECTED:
|
|
self.log.debug("disconnecting (%s)", connection)
|
|
connection.disconnect()
|
|
|
|
|
|
class SensorSetup(object):
|
|
def __init__(self, connection, sensors, logger, log):
|
|
self.connection = connection
|
|
self.sensors = sensors
|
|
self.logger = logger
|
|
self.log = log
|
|
self._previous_sensors = {}
|
|
|
|
def parametrized_callback(self, name, type):
|
|
return partial(self.logger.cb_generic, sensor=name, type=type)
|
|
|
|
def parametrized_callback_delta(self, name, type, getter):
|
|
return partial(self.logger.cb_delta, name=name, type=type, getter=getter)
|
|
|
|
def __setupSensor__(self, name, sensor):
|
|
sensor_id = sensor[0]
|
|
sensor_type = sensor[1]
|
|
var = SENSOR_CONFIGS[sensor_type]
|
|
if sensor_id in self._previous_sensors:
|
|
self.log.debug("reusing instance for %s", sensor_id)
|
|
obj = self._previous_sensors[sensor_id] # restore instance for another callback
|
|
else:
|
|
self.log.debug("new instance for %s", sensor_id)
|
|
obj = var['obj'](sensor_id, self.connection) # construct instance
|
|
self._previous_sensors[sensor_id] = obj # save instance for multiple callbacks
|
|
cbtime = settings.sensor_properties[sensor_type][0]
|
|
if 'delta' in var:
|
|
callback = self.parametrized_callback_delta(name, sensor_type, partial(var['get'], obj))
|
|
else:
|
|
callback = self.parametrized_callback(name, type=sensor_type)
|
|
var['setcb'](obj, cbtime) # set callback period
|
|
callback(var['get'](obj)) # execute callback with raw getter as value
|
|
obj.register_callback(var['cb'], callback) # register callback
|
|
return obj
|
|
|
|
def generic_sensor_setup(self, name, sensor):
|
|
status = "setup device " + sensor[0] + " (" + name + "):"
|
|
obj = None
|
|
if sensor[1] is SensorType.rain:
|
|
self.log.error("rain is not yet implemented (%s, %s)", sensor[0], name)
|
|
return None
|
|
elif not sensor[1] in SENSOR_CONFIGS:
|
|
self.log.error("%s FAIL (unknown type)", status)
|
|
return None
|
|
try:
|
|
obj = self.__setupSensor__(name, sensor)
|
|
self.log.info("%s OK", status)
|
|
except Exception as e:
|
|
self.log.error("%s FAIL:: %s (%s)", status, e, traceback.format_exc())
|
|
return obj
|
|
|
|
def setup_sensors(self):
|
|
connected = []
|
|
for name in self.sensors:
|
|
sensor = self.sensors[name]
|
|
obj = self.generic_sensor_setup(name, sensor)
|
|
connected.append(obj)
|
|
return connected
|