Application Structure reworked

This commit is contained in:
Dirk Alders 2021-01-30 23:21:01 +01:00
parent da88900352
commit dad7b08a98
3 changed files with 291 additions and 286 deletions

2
report

@ -1 +1 @@
Subproject commit 25889f225b3593d515e37bebffef21458c961f64 Subproject commit 139f0bd0c29b8b44e235622f7fd8db7dc0037ec0

View File

@ -9,7 +9,6 @@ import helpers
import garage_protocol import garage_protocol
import gui import gui
import logging import logging
import numbers
import os import os
import report import report
import socket_protocol import socket_protocol
@ -19,301 +18,180 @@ import time
import wetation_protocol import wetation_protocol
import wx import wx
############################################################################################################################
# #
# Application Structure #
# #
# +-----------------------------+ +------------------------------+ +---------------------------+ #
# | Data Request Task (1s) | | Data Receive Callback | | GUI Update WX-IDLE-TASK | #
# | Counter 0-9 | | | | | #
# | | | Append data to ValueStorage | | - Update all GUI Elements | #
# | *: Request door_pos | +------------------------------+ | - Check Data Status to | #
# | 0: Request env-data-in bmp | | mark all fragile con- | #
# | 1: Request env-data-in dht | | tent | #
# | 5: Request env-data-out bmp | +---------------------------+ #
# | 6: Request env-data-out dht | #
# | 9: Reconnect if needed | #
# +-----------------------------+ #
# #
############################################################################################################################
try: try:
from config import APP_NAME as ROOT_LOGGER_NAME from config import APP_NAME as ROOT_LOGGER_NAME
except ImportError: except ImportError:
ROOT_LOGGER_NAME = 'root' ROOT_LOGGER_NAME = 'root'
logger = logging.getLogger(ROOT_LOGGER_NAME).getChild(__name__)
class WetationFrameProt(gui.Wetation):
PROT_ID_GARAGE = 0
PROT_ID_IN = 1
PROT_ID_OUT = 2
ALL_PROT_IDS = [PROT_ID_GARAGE, PROT_ID_IN, PROT_ID_OUT, ]
PROT_NAMES = { class ValueStorage(dict):
PROT_ID_GARAGE: u'garage', MAX_AGE = 60 # Seconds
PROT_ID_IN: u'wet-in',
PROT_ID_OUT: u'wet-out', DATA_KEY_GATE_POSITION = 'gate_position'
DATA_KEY_HUMIDITY_IN = 'humidity_in'
DATA_KEY_HUMIDITY_OUT = 'humidity_out'
DATA_KEY_PRESSURE_IN = 'pressure_in'
DATA_KEY_PRESSURE_OUT = 'pressure_out'
DATA_KEY_TEMPERATURE_IN = 'temp_in'
DATA_KEY_TEMPERATURE_OUT = 'temp_out'
DATA_KEY_2ND_TEMPERATURE_IN = '2nd_temp_in'
DATA_KEY_2ND_TEMPERATURE_OUT = '2nd_temp_out'
FORMATTER_TEMP = ('%.1f °C', '-.- °C')
FORMATTER_HUMI = ('%.1f %%', '-.- %')
FORMATTER_PRES = ('%4d hPa', '- hPa')
DATA_KEYS_CONT_STAT = [DATA_KEY_HUMIDITY_IN, DATA_KEY_HUMIDITY_OUT, DATA_KEY_PRESSURE_IN, DATA_KEY_PRESSURE_OUT, DATA_KEY_TEMPERATURE_IN, DATA_KEY_TEMPERATURE_OUT, DATA_KEY_2ND_TEMPERATURE_IN, DATA_KEY_2ND_TEMPERATURE_OUT]
def append(self, drk, value):
tm = time.time()
logger.info('Value stored (%s): %s', drk, repr(value))
if drk in self.DATA_KEYS_CONT_STAT:
self[drk] = (value.mean, tm)
if drk + '.min' not in self or value.min < self[drk + '.min'][0]:
self[drk + '.min'] = (value.min, tm)
if drk + '.max' not in self or value.max < self[drk + '.max'][0]:
self[drk + '.max'] = (value.max, tm)
else:
self[drk] = (value, tm)
def reset_min_max(self, data_key):
del self[data_key + '.min']
del self[data_key + '.max']
def __get_formatter__(self, key):
return {
self.DATA_KEY_2ND_TEMPERATURE_IN: self.FORMATTER_TEMP,
self.DATA_KEY_2ND_TEMPERATURE_OUT: self.FORMATTER_TEMP,
self.DATA_KEY_HUMIDITY_IN: self.FORMATTER_HUMI,
self.DATA_KEY_HUMIDITY_OUT: self.FORMATTER_HUMI,
self.DATA_KEY_PRESSURE_IN: self.FORMATTER_PRES,
self.DATA_KEY_PRESSURE_OUT: self.FORMATTER_PRES,
self.DATA_KEY_TEMPERATURE_IN: self.FORMATTER_TEMP,
self.DATA_KEY_TEMPERATURE_OUT: self.FORMATTER_TEMP,
}.get(key)
def get_validated(self, key, value_type=None, default=None):
tm = time.time()
fallback = {
self.DATA_KEY_TEMPERATURE_IN: self.DATA_KEY_2ND_TEMPERATURE_IN,
self.DATA_KEY_TEMPERATURE_OUT: self.DATA_KEY_2ND_TEMPERATURE_OUT,
}.get(key)
if value_type in ['min', 'max']:
key = key + '.' + value_type
value = dict.get(self, key)
if value is None and fallback is not None:
value = dict.get(self, fallback)
if value is None:
return default
if tm - value[1] <= self.MAX_AGE:
if key == self.DATA_KEY_GATE_POSITION:
return int(value[0] * 50)
else:
return value[0]
else:
return default
def get(self, key, value_type=None, formatted=True, default=None):
formatter = self.__get_formatter__(key)
value = self.get_validated(key, value_type, default=default)
if not formatted:
return value
else:
if formatter is None:
return default
else:
try:
return formatter[0] % value
except Exception:
return formatter[1]
class Wetation(gui.Wetation):
SRC_ID_GARAGE = 0
SRC_ID_IN = 1
SRC_ID_OUT = 2
ALL_SRC_IDS = [SRC_ID_GARAGE, SRC_ID_IN, SRC_ID_OUT, ]
SRC_NAMES = {
SRC_ID_GARAGE: u'garage',
SRC_ID_IN: u'wet-in',
SRC_ID_OUT: u'wet-out',
} }
PROT_IPS = { SRC_IPS = {
PROT_ID_GARAGE: config.server_garage_ip, SRC_ID_GARAGE: config.server_garage_ip,
PROT_ID_IN: config.server_in_ip, SRC_ID_IN: config.server_in_ip,
PROT_ID_OUT: config.server_out_ip, SRC_ID_OUT: config.server_out_ip,
} }
PROT_PORTS = { SRC_PORTS = {
PROT_ID_GARAGE: config.server_garage_port, SRC_ID_GARAGE: config.server_garage_port,
PROT_ID_IN: config.server_in_port, SRC_ID_IN: config.server_in_port,
PROT_ID_OUT: config.server_out_port, SRC_ID_OUT: config.server_out_port,
} }
PROT_SECRETS = { SRC_SECRETS = {
PROT_ID_GARAGE: config.server_garage_secret, SRC_ID_GARAGE: config.server_garage_secret,
PROT_ID_IN: config.server_in_secret, SRC_ID_IN: config.server_in_secret,
PROT_ID_OUT: config.server_out_secret, SRC_ID_OUT: config.server_out_secret,
}
PROT_CLASSES = {
PROT_ID_GARAGE: garage_protocol.my_base_protocol_tcp,
PROT_ID_IN: wetation_protocol.my_base_protocol_tcp,
PROT_ID_OUT: wetation_protocol.my_base_protocol_tcp,
} }
REQUEST_MSGS_SLOW = { SRC_CLASSES = {
PROT_ID_IN: [ SRC_ID_GARAGE: garage_protocol.my_base_protocol_tcp,
{ SRC_ID_IN: wetation_protocol.my_base_protocol_tcp,
'service_id': socket_protocol.SID_READ_REQUEST, SRC_ID_OUT: wetation_protocol.my_base_protocol_tcp,
'data_id': wetation_protocol.ENVDATA_STATISTIC_DHT,
},
{
'service_id': socket_protocol.SID_READ_REQUEST,
'data_id': wetation_protocol.ENVDATA_STATISTIC_BMP,
},
],
PROT_ID_OUT: [
{
'service_id': socket_protocol.SID_READ_REQUEST,
'data_id': wetation_protocol.ENVDATA_STATISTIC_DHT,
},
{
'service_id': socket_protocol.SID_READ_REQUEST,
'data_id': wetation_protocol.ENVDATA_STATISTIC_BMP,
},
],
} }
REQUEST_MSGS_FAST = {
PROT_ID_GARAGE: [
{
'service_id': socket_protocol.SID_READ_REQUEST,
'data_id': garage_protocol.GATE_POSITION,
},
],
}
def __init__(self, *args, **kwds): def __init__(self, *args, **kwds):
self.__min_temp_in__ = None
self.__min_temp_out__ = None
self.__max_temp_in__ = None
self.__max_temp_out__ = None
self.__prot__ = {}
gui.Wetation.__init__(self, *args, **kwds) gui.Wetation.__init__(self, *args, **kwds)
self.Bind(wx.EVT_IDLE, self.gui_update)
self.in_temperature_min.Bind(wx.EVT_LEFT_DOWN, self.reset_in_temp_minmax_evt) self.in_temperature_min.Bind(wx.EVT_LEFT_DOWN, self.reset_in_temp_minmax_evt)
self.in_temperature_max.Bind(wx.EVT_LEFT_DOWN, self.reset_in_temp_minmax_evt) self.in_temperature_max.Bind(wx.EVT_LEFT_DOWN, self.reset_in_temp_minmax_evt)
self.out_temperature_min.Bind(wx.EVT_LEFT_DOWN, self.reset_out_temp_minmax_evt) self.out_temperature_min.Bind(wx.EVT_LEFT_DOWN, self.reset_out_temp_minmax_evt)
self.out_temperature_max.Bind(wx.EVT_LEFT_DOWN, self.reset_out_temp_minmax_evt) self.out_temperature_max.Bind(wx.EVT_LEFT_DOWN, self.reset_out_temp_minmax_evt)
self.ShowFullScreen(config.FULL_SCREEN) self.ShowFullScreen(config.FULL_SCREEN)
#
self.__src__ = {}
self.__value_storage__ = ValueStorage()
self.__init_communication__() self.__init_communication__()
time.sleep(3.5) # Wait for established connections before starting the tasks #
self.__drt_cnt__ = -1
self.__task_1s__ = task.periodic(1, self.__task_1s_callback__) self.__task_1s__ = task.periodic(1, self.data_request_task)
self.__task_10s__ = task.periodic(10, self.__task_10s_callback__)
self.__task_60s__ = task.periodic(60, self.__task_60s_callback__)
def __init_communication__(self): def __init_communication__(self):
# #
# Start TCP-Clients # Start TCP-Clients
for prot_id in self.ALL_PROT_IDS: for src_id in self.ALL_SRC_IDS:
cn = self.PROT_NAMES[prot_id] cn = self.SRC_NAMES[src_id]
logger = logging.getLogger(ROOT_LOGGER_NAME).getChild(__name__ + '.' + cn) c_tcp = tcp_socket.tcp_client_stp(self.SRC_IPS[src_id], self.SRC_PORTS[src_id], channel_name=cn)
logger.info('Initiating communication channel') self.__src__[src_id] = self.SRC_CLASSES[src_id](c_tcp, secret=self.SRC_SECRETS[src_id], auto_auth=True, channel_name=cn)
c_tcp = tcp_socket.tcp_client_stp(self.PROT_IPS[prot_id], self.PROT_PORTS[prot_id])
self.__prot__[prot_id] = self.PROT_CLASSES[prot_id](c_tcp, secret=self.PROT_SECRETS[prot_id], auto_auth=True, channel_name=cn)
# #
self.__prot__[prot_id].register_callback(None, None, self.__prot_resp_callbacks__, prot_id) self.__src__[src_id].register_callback(None, None, self.data_receive_callback, src_id)
def __initiate_data_request__(self, rt, request_msgs):
for prot_id in request_msgs:
cn = self.PROT_NAMES[prot_id]
logger = logging.getLogger(ROOT_LOGGER_NAME).getChild(__name__ + '.' + cn)
for request_msg in request_msgs.get(prot_id, []):
service_id = request_msg['service_id']
data_id = request_msg['data_id']
if self.__prot__[prot_id].connection_established():
logger.debug('Sending data request for service_id %d and data_id %d', service_id, data_id)
self.__prot__[prot_id].send(service_id, data_id, None)
else:
wx.CallAfter(self.__no_data__, prot_id, service_id + 1, data_id)
def __task_1s_callback__(self, rt):
# request data from fast prot ids
self.__initiate_data_request__(rt, self.REQUEST_MSGS_FAST)
# set date and time
wx.CallAfter(self.update_time)
def __task_10s_callback__(self, rt):
# request data from slow prot ids
self.__initiate_data_request__(rt, self.REQUEST_MSGS_SLOW)
def __task_60s_callback__(self, rt):
# reconnect prots if needed
for prot_id in self.ALL_PROT_IDS:
cn = self.PROT_NAMES[prot_id]
logger = logging.getLogger(ROOT_LOGGER_NAME).getChild(__name__ + '.' + cn)
if not self.__prot__[prot_id].connected():
logger.warning("Trying to reconnect prot_id %d", prot_id)
self.__prot__[prot_id].reconnect()
def __validate_response_data__(self, prot_id, service_id, data_id, data):
rv = False
cn = self.PROT_NAMES[prot_id]
logger = logging.getLogger(ROOT_LOGGER_NAME).getChild(__name__ + '.' + cn)
if prot_id == self.PROT_ID_GARAGE:
if service_id == socket_protocol.SID_READ_RESPONSE and data_id == garage_protocol.GATE_POSITION:
rv = isinstance(data, numbers.Number)
elif service_id == socket_protocol.SID_EXECUTE_RESPONSE and data_id == garage_protocol.OPEN_CLOSE_GATE:
if data is True:
rv = True
elif prot_id in [self.PROT_ID_IN, self.PROT_ID_OUT]:
if service_id == socket_protocol.SID_READ_RESPONSE and data_id == wetation_protocol.ENVDATA_STATISTIC_BMP:
rv = True
for main_key in [bmp_180.KEY_PRESSURE, bmp_180.KEY_TEMPERATURE, bmp_180.KEY_TIME]:
if main_key not in data:
rv = False
break
else:
for sub_key in ['mean', 'min_val', 'max_val', 'quantifier']:
if not isinstance(data[main_key].get(sub_key), numbers.Number):
rv = False
break
elif service_id == socket_protocol.SID_READ_RESPONSE and data_id == wetation_protocol.ENVDATA_STATISTIC_DHT:
rv = True
for main_key in [dht_22.KEY_HUMIDITY, dht_22.KEY_TEMPERATURE, dht_22.KEY_TIME]:
if main_key not in data:
rv = False
break
else:
for sub_key in ['mean', 'min_val', 'max_val', 'quantifier']:
if not isinstance(data[main_key].get(sub_key), numbers.Number):
rv = False
break
if rv is False:
logger.warning("Validation failed for message: prot_id=%s, service_id=%s, data_id=%s, data=%s", repr(prot_id), repr(service_id), repr(data_id), repr(data))
return rv
def __prot_resp_callbacks__(self, msg, prot_id):
service_id = msg.get_service_id()
data_id = msg.get_data_id()
data = msg.get_data()
if self.__validate_response_data__(prot_id, service_id, data_id, data):
wx.CallAfter(self.__data__, prot_id, service_id, data_id, data)
return socket_protocol.STATUS_OKAY, None
else:
wx.CallAfter(self.__no_data__, prot_id, service_id, data_id)
return socket_protocol.STATUS_SERVICE_OR_DATA_UNKNOWN, None
def __no_data__(self, prot_id, service_id, data_id):
cn = self.PROT_NAMES[prot_id]
logger = logging.getLogger(ROOT_LOGGER_NAME).getChild(__name__ + '.' + cn)
if prot_id == self.PROT_ID_GARAGE:
if service_id == socket_protocol.SID_READ_RESPONSE and data_id == garage_protocol.GATE_POSITION:
logger.warning('Resetting GUI elements for %s', cn)
self.heading_garage.Show(False)
self.gate_oc.Show(False)
self.gate_open.Show(False)
self.gate_position.Show(False)
self.gate_close.Show(False)
self.Layout()
return
elif service_id == socket_protocol.SID_EXECUTE_RESPONSE and data_id == garage_protocol.OPEN_CLOSE_GATE:
return
elif prot_id in [self.PROT_ID_IN, self.PROT_ID_OUT]:
if service_id == socket_protocol.SID_READ_RESPONSE and data_id == wetation_protocol.ENVDATA_STATISTIC_BMP:
logger.warning('Resetting GUI elements for %s', cn)
txt_pressure = '- hPa'
if prot_id == self.PROT_ID_IN:
self.in_pressure.SetLabel(txt_pressure)
else:
self.out_pressure.SetLabel(txt_pressure)
self.Layout()
return
elif service_id == socket_protocol.SID_READ_RESPONSE and data_id == wetation_protocol.ENVDATA_STATISTIC_DHT:
logger.warning('Resetting GUI elements for %s', cn)
txt_temperature = '-.- °C'
txt_humidity = '-.- %'
if prot_id == self.PROT_ID_IN:
self.in_temperature.SetLabel(txt_temperature)
self.in_humidity.SetLabel(txt_humidity)
else:
self.out_temperature.SetLabel(txt_temperature)
self.out_humidity.SetLabel(txt_humidity)
self.Layout()
return
logger.warning("Unknown response with no valid data for prot_id %d, service_id=%d, data_id=%d", prot_id, service_id, data_id)
def __data__(self, prot_id, service_id, data_id, data):
cn = self.PROT_NAMES[prot_id]
logger = logging.getLogger(ROOT_LOGGER_NAME).getChild(__name__ + '.' + cn)
if prot_id == self.PROT_ID_GARAGE:
if service_id == socket_protocol.SID_READ_RESPONSE and data_id == garage_protocol.GATE_POSITION:
logger.debug('Setting %s position to %3d', cn, int(data * 100))
self.heading_garage.Show(True)
self.gate_oc.Show(True)
self.gate_open.Show(True)
self.gate_position.Show(True)
self.gate_close.Show(True)
self.gate_position.SetValue(int(data * 100))
self.Layout()
return
elif service_id == socket_protocol.SID_EXECUTE_RESPONSE and data_id == garage_protocol.OPEN_CLOSE_GATE:
return
elif prot_id in [self.PROT_ID_IN, self.PROT_ID_OUT]:
if service_id == socket_protocol.SID_READ_RESPONSE and data_id == wetation_protocol.ENVDATA_STATISTIC_BMP:
data = helpers.continues_statistic_multivalue(**data)
logger.debug('Setting %s pressure to %4d hPa', cn, data[bmp_180.KEY_PRESSURE].mean)
#
# Current environmental data
if prot_id == self.PROT_ID_IN:
wx.CallAfter(self.update_current_bmp_env_data, data, self.in_pressure)
else:
wx.CallAfter(self.update_current_bmp_env_data, data, self.out_pressure)
return
elif service_id == socket_protocol.SID_READ_RESPONSE and data_id == wetation_protocol.ENVDATA_STATISTIC_DHT:
data = helpers.continues_statistic_multivalue(**data)
#
# Current environmental data
temp = data[dht_22.KEY_TEMPERATURE].mean
logger.debug('Setting %s temperature to %4.1f °C', cn, temp)
logger.debug('Setting %s humidity to %3.1f %%', cn, data[dht_22.KEY_HUMIDITY].mean)
if prot_id == self.PROT_ID_IN:
if self.__max_temp_in__ is None or temp > self.__max_temp_in__:
self.__max_temp_in__ = temp
if self.__min_temp_in__ is None or temp < self.__min_temp_in__:
self.__min_temp_in__ = temp
wx.CallAfter(self.update_current_dht_env_data, data, self.in_temperature, self.in_humidity, self.in_temperature_min, self.in_temperature_max, self.__min_temp_in__, self.__max_temp_in__)
else:
if self.__max_temp_out__ is None or temp > self.__max_temp_out__:
self.__max_temp_out__ = temp
if self.__min_temp_out__ is None or temp < self.__min_temp_out__:
self.__min_temp_out__ = temp
wx.CallAfter(self.update_current_dht_env_data, data, self.out_temperature, self.out_humidity, self.out_temperature_min, self.out_temperature_max, self.__min_temp_out__, self.__max_temp_out__)
return
logger.warning("Unknown response with valid data for prot_id %d, service_id=%d, data_id=%d", prot_id, service_id, data_id)
def update_current_bmp_env_data(self, env_data, pressure):
pressure.SetLabel('%.0f hPa' % env_data[bmp_180.KEY_PRESSURE].mean)
self.Layout()
def update_current_dht_env_data(self, env_data, temperature, humidity, temperature_min, temperature_max, value_min, value_max):
if isinstance(value_min, numbers.Number) and isinstance(value_max, numbers.Number):
temperature_min.SetLabel('%.1f' % value_min)
temperature_max.SetLabel('%.1f' % value_max)
temperature.SetLabel('%.1f °C' % env_data[dht_22.KEY_TEMPERATURE].mean)
humidity.SetLabel('%.1f %%' % env_data[dht_22.KEY_HUMIDITY].mean)
self.Layout()
def update_time(self):
self.time.SetLabel(time.strftime("%H:%M"))
self.date.SetLabel(time.strftime("%d.%m.%Y"))
self.Layout()
def gate_oc_evt(self, event): def gate_oc_evt(self, event):
cn = self.PROT_NAMES[self.PROT_ID_GARAGE]
logger = logging.getLogger(ROOT_LOGGER_NAME).getChild(__name__ + '.' + cn)
r = wx.MessageDialog( r = wx.MessageDialog(
self, self,
"Soll das Garagentor betätigt werden?", "Soll das Garagentor betätigt werden?",
@ -321,38 +199,167 @@ class WetationFrameProt(gui.Wetation):
wx.YES_NO | wx.NO_DEFAULT | wx.ICON_WARNING wx.YES_NO | wx.NO_DEFAULT | wx.ICON_WARNING
).ShowModal() ).ShowModal()
if r == wx.ID_YES: if r == wx.ID_YES:
logger.debug("Gate open/close request") logger.info("Gate open/close request")
self.__prot__[self.PROT_ID_GARAGE].send(socket_protocol.SID_EXECUTE_REQUEST, garage_protocol.OPEN_CLOSE_GATE, None) self.__src__[self.SRC_ID_GARAGE].send(socket_protocol.SID_EXECUTE_REQUEST, garage_protocol.OPEN_CLOSE_GATE, None)
event.Skip() event.Skip()
def reset_in_temp_minmax_evt(self, event): def reset_in_temp_minmax_evt(self, event):
self.__min_temp_in__ = None self.__value_storage__.reset_min_max(ValueStorage.DATA_KEY_TEMPERATURE_IN)
self.__max_temp_in__ = None self.__value_storage__.reset_min_max(ValueStorage.DATA_KEY_2ND_TEMPERATURE_IN)
self.in_temperature_min.SetLabel("-.- °C")
self.in_temperature_max.SetLabel("-.- °C")
self.Layout()
event.Skip() event.Skip()
def reset_out_temp_minmax_evt(self, event): def reset_out_temp_minmax_evt(self, event):
self.__min_temp_out__ = None self.__value_storage__.reset_min_max(ValueStorage.DATA_KEY_TEMPERATURE_OUT)
self.__max_temp_out__ = None self.__value_storage__.reset_min_max(ValueStorage.DATA_KEY_2ND_TEMPERATURE_OUT)
self.out_temperature_min.SetLabel("-.- °C") event.Skip()
self.out_temperature_max.SetLabel("-.- °C")
def data_request_task(self, rt):
(rt)
if self.__drt_cnt__ < 9:
self.__drt_cnt__ += 1
else:
self.__drt_cnt__ = 0
logger.debug('data_request_task stated with cnt = %d', self.__drt_cnt__)
#
# Request GATE_POSITION
#
self.__src__[self.SRC_ID_GARAGE].send(service_id=socket_protocol.SID_READ_REQUEST, data_id=garage_protocol.GATE_POSITION, data=None)
#
# Request WET-OUT-DATA
#
if self.__drt_cnt__ == 0:
self.__src__[self.SRC_ID_OUT].send(service_id=socket_protocol.SID_READ_REQUEST, data_id=wetation_protocol.ENVDATA_STATISTIC_BMP, data=None)
elif self.__drt_cnt__ == 1:
self.__src__[self.SRC_ID_OUT].send(service_id=socket_protocol.SID_READ_REQUEST, data_id=wetation_protocol.ENVDATA_STATISTIC_DHT, data=None)
#
# Request WET-IN-DATA
#
elif self.__drt_cnt__ == 5:
self.__src__[self.SRC_ID_IN].send(service_id=socket_protocol.SID_READ_REQUEST, data_id=wetation_protocol.ENVDATA_STATISTIC_BMP, data=None)
elif self.__drt_cnt__ == 6:
self.__src__[self.SRC_ID_IN].send(service_id=socket_protocol.SID_READ_REQUEST, data_id=wetation_protocol.ENVDATA_STATISTIC_DHT, data=None)
elif self.__drt_cnt__ == 9:
self.__reconnect__()
#
def __reconnect__(self):
for src_id in self.ALL_SRC_IDS:
if not self.__src__[src_id].is_connected():
logger.warning("Trying to reconnect prot_id %s", self.SRC_NAMES.get(src_id, 'Unknown'))
self.__src__[src_id].reconnect()
def __data_receive_key__(self, src_id, data_id, key=None, default_value=None):
return {
self.SRC_ID_GARAGE: {
garage_protocol.GATE_POSITION: {
None: ValueStorage.DATA_KEY_GATE_POSITION,
}
},
self.SRC_ID_IN: {
wetation_protocol.ENVDATA_STATISTIC_BMP: {
bmp_180.KEY_PRESSURE: ValueStorage.DATA_KEY_PRESSURE_IN,
bmp_180.KEY_TEMPERATURE: ValueStorage.DATA_KEY_2ND_TEMPERATURE_IN
},
wetation_protocol.ENVDATA_STATISTIC_DHT: {
dht_22.KEY_HUMIDITY: ValueStorage.DATA_KEY_HUMIDITY_IN,
dht_22.KEY_TEMPERATURE: ValueStorage.DATA_KEY_TEMPERATURE_IN
},
},
self.SRC_ID_OUT: {
wetation_protocol.ENVDATA_STATISTIC_BMP: {
bmp_180.KEY_PRESSURE: ValueStorage.DATA_KEY_PRESSURE_OUT,
bmp_180.KEY_TEMPERATURE: ValueStorage.DATA_KEY_2ND_TEMPERATURE_OUT
},
wetation_protocol.ENVDATA_STATISTIC_DHT: {
dht_22.KEY_HUMIDITY: ValueStorage.DATA_KEY_HUMIDITY_OUT,
dht_22.KEY_TEMPERATURE: ValueStorage.DATA_KEY_TEMPERATURE_OUT
},
}
}.get(src_id, {}).get(data_id, {}).get(key, default_value)
def data_receive_callback(self, data, src_id):
if src_id in [self.SRC_ID_IN, self.SRC_ID_OUT] and data.get_data_id() in [wetation_protocol.ENVDATA_STATISTIC_DHT, wetation_protocol.ENVDATA_STATISTIC_BMP]:
try:
for key in data.get_data():
if key != bmp_180.KEY_TIME:
drk = self.__data_receive_key__(src_id, data.get_data_id(), key)
if drk is not None:
self.__process_rx_data__(
drk,
helpers.continues_statistic(**data.get_data()[key])
)
else:
self.__warning_rx_data__('Unknown RX-Data', data, src_id)
except TypeError as e:
self.__warning_rx_data__('Wront DataType in RX-Data (%s)' % e, data, src_id)
else:
drk = self.__data_receive_key__(src_id, data.get_data_id())
if drk is not None:
self.__process_rx_data__(
drk,
data.get_data()
)
else:
self.__warning_rx_data__('Unknown RX-Data', data, src_id)
def __process_rx_data__(self, drk, data):
self.__value_storage__.append(drk, data)
def __warning_rx_data__(self, desc, data, src_id):
logger.warning('%s from %s: %s', desc, self.SRC_NAMES.get(src_id, 'Unknown'), repr(data))
def __check_data_status__(self):
if dict.get(self.__value_storage__, ValueStorage.DATA_KEY_TEMPERATURE_IN) is None and dict.get(self.__value_storage__, ValueStorage.DATA_KEY_2ND_TEMPERATURE_IN) is not None:
self.in_temperature.SetBackgroundColour((255, 255, 200, 255))
else:
self.in_temperature.SetBackgroundColour((250, 249, 255, 255))
if dict.get(self.__value_storage__, ValueStorage.DATA_KEY_TEMPERATURE_OUT) is None and dict.get(self.__value_storage__, ValueStorage.DATA_KEY_2ND_TEMPERATURE_OUT) is not None:
self.out_temperature.SetBackgroundColour((255, 255, 200, 255))
else:
self.out_temperature.SetBackgroundColour((250, 249, 255, 255))
if dict.get(self.__value_storage__, ValueStorage.DATA_KEY_GATE_POSITION) is None:
self.heading_garage.SetBackgroundColour((142, 35, 35, 255))
else:
self.heading_garage.SetBackgroundColour((35, 35, 142, 255))
def gui_update(self, event):
#
# TIME and DATE
#
self.time.SetLabel(time.strftime("%H:%M"))
self.date.SetLabel(time.strftime("%d.%m.%Y"))
#
update_list = [
# WET-OUT
(self.out_humidity.SetLabel, [ValueStorage.DATA_KEY_HUMIDITY_OUT, 'mean', True]),
(self.out_pressure.SetLabel, [ValueStorage.DATA_KEY_PRESSURE_OUT, 'mean', True]),
(self.out_temperature.SetLabel, [ValueStorage.DATA_KEY_TEMPERATURE_OUT, 'mean', True]),
(self.out_temperature_max.SetLabel, [ValueStorage.DATA_KEY_TEMPERATURE_OUT, 'max', True]),
(self.out_temperature_min.SetLabel, [ValueStorage.DATA_KEY_TEMPERATURE_OUT, 'min', True]),
# WET-IN
(self.in_humidity.SetLabel, [ValueStorage.DATA_KEY_HUMIDITY_IN, 'mean', True]),
(self.in_pressure.SetLabel, [ValueStorage.DATA_KEY_PRESSURE_IN, 'mean', True]),
(self.in_temperature.SetLabel, [ValueStorage.DATA_KEY_TEMPERATURE_IN, 'mean', True]),
(self.in_temperature_max.SetLabel, [ValueStorage.DATA_KEY_TEMPERATURE_IN, 'max', True]),
(self.in_temperature_min.SetLabel, [ValueStorage.DATA_KEY_TEMPERATURE_IN, 'min', True]),
# GATE
(self.gate_position.SetValue, [ValueStorage.DATA_KEY_GATE_POSITION, None, False, 50])
]
#
for func, args in update_list:
func(self.__value_storage__.get(*args))
self.__check_data_status__()
#
#
self.Layout() self.Layout()
event.Skip() event.Skip()
def run(self): def run(self):
self.__task_1s__.run() self.__task_1s__.run()
self.__task_10s__.run()
self.__task_60s__.run()
def close(self): def close(self):
self.__task_1s__.stop() self.__task_1s__.stop()
self.__task_1s__.join() self.__task_1s__.join()
self.__task_10s__.stop()
self.__task_10s__.join()
self.__task_60s__.stop()
self.__task_60s__.join()
def __del__(self): def __del__(self):
self.close() self.close()
@ -360,14 +367,12 @@ class WetationFrameProt(gui.Wetation):
class MyApp(wx.App): class MyApp(wx.App):
def OnInit(self): def OnInit(self):
self.frame = WetationFrameProt(None, wx.ID_ANY, "") self.frame = Wetation(None, wx.ID_ANY, "")
self.SetTopWindow(self.frame) self.SetTopWindow(self.frame)
self.frame.Show() self.frame.Show()
return True return True
if __name__ == "__main__": if __name__ == "__main__":
report.appLoggingConfigure(os.path.dirname(__file__), config.LOGTARGET, ((config.APP_NAME, config.LOGLVL), ), fmt=config.formatter, host=config.LOGHOST, port=config.LOGPORT) report.appLoggingConfigure(os.path.dirname(__file__), config.LOGTARGET, ((config.APP_NAME, config.LOGLVL), ), fmt=config.formatter, host=config.LOGHOST, port=config.LOGPORT)
# #

@ -1 +1 @@
Subproject commit b5ee20216e9215dd6555d5bae702a48e7512ecce Subproject commit a8aa15974b309b3f916fe4312538e166ae2f3691