diff --git a/config_example/config.py b/config_example/config.py index f731ba3..aa480e6 100644 --- a/config_example/config.py +++ b/config_example/config.py @@ -6,7 +6,7 @@ import stringtools import task import tcp_socket -FULL_SCRREN = False +FULL_SCREEN = False # TCP-Server diff --git a/gui.py b/gui.py index 97d2d0b..8c6ac49 100755 --- a/gui.py +++ b/gui.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: UTF-8 -*- # -# generated by wxGlade 0.9.3 on Mon Sep 7 11:55:26 2020 +# generated by wxGlade 0.9.3 on Wed Sep 9 07:31:16 2020 # import wx @@ -18,18 +18,18 @@ class Wetation(wx.Frame): # begin wxGlade: Wetation.__init__ kwds["style"] = kwds.get("style", 0) | wx.DEFAULT_FRAME_STYLE wx.Frame.__init__(self, *args, **kwds) - self.SetSize((800, 628)) + self.SetSize((800, 655)) self.date = wx.StaticText(self, wx.ID_ANY, "xx.xx.xxxx", style=wx.ALIGN_LEFT) self.time = wx.StaticText(self, wx.ID_ANY, "xx:xx", style=wx.ALIGN_RIGHT) - self.heading_out_envdata = wx.StaticText(self, wx.ID_ANY, u"Außentemperatur") + self.heading_out_envdata = wx.StaticText(self, wx.ID_ANY, u"Außen") self.out_humidity = wx.StaticText(self, wx.ID_ANY, "- %", style=wx.ALIGN_RIGHT) - self.out_pressure = wx.StaticText(self, wx.ID_ANY, "- mbar", style=wx.ALIGN_RIGHT) + self.out_pressure = wx.StaticText(self, wx.ID_ANY, "- hPa", style=wx.ALIGN_RIGHT) self.out_temperature_min = wx.StaticText(self, wx.ID_ANY, u"-.- °C", style=wx.ALIGN_RIGHT) self.out_temperature_max = wx.StaticText(self, wx.ID_ANY, u"-.- °C", style=wx.ALIGN_RIGHT) self.out_temperature = wx.StaticText(self, wx.ID_ANY, u"-.- °C", style=wx.ALIGN_RIGHT) - self.heading_in_envdata = wx.StaticText(self, wx.ID_ANY, "Innentemperatur") + self.heading_in_envdata = wx.StaticText(self, wx.ID_ANY, "Innen") self.in_humidity = wx.StaticText(self, wx.ID_ANY, "- %", style=wx.ALIGN_RIGHT) - self.in_pressure = wx.StaticText(self, wx.ID_ANY, "- mbar", style=wx.ALIGN_RIGHT) + self.in_pressure = wx.StaticText(self, wx.ID_ANY, "- hPa", style=wx.ALIGN_RIGHT) self.in_temperature_min = wx.StaticText(self, wx.ID_ANY, u"-.- °C", style=wx.ALIGN_RIGHT) self.in_temperature_max = wx.StaticText(self, wx.ID_ANY, u"-.- °C", style=wx.ALIGN_RIGHT) self.in_temperature = wx.StaticText(self, wx.ID_ANY, u"-.- °C", style=wx.ALIGN_RIGHT) @@ -58,7 +58,7 @@ class Wetation(wx.Frame): self.time.SetFont(wx.Font(24, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, 0, "")) self.heading_out_envdata.SetBackgroundColour(wx.Colour(35, 35, 142)) self.heading_out_envdata.SetForegroundColour(wx.Colour(250, 249, 255)) - self.heading_out_envdata.SetFont(wx.Font(12, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, 0, "")) + self.heading_out_envdata.SetFont(wx.Font(16, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, 0, "")) self.out_humidity.SetFont(wx.Font(24, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, 0, "")) self.out_pressure.SetFont(wx.Font(24, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, 0, "")) self.out_temperature_min.SetFont(wx.Font(24, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, 0, "")) @@ -66,7 +66,7 @@ class Wetation(wx.Frame): self.out_temperature.SetFont(wx.Font(48, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, 0, "")) self.heading_in_envdata.SetBackgroundColour(wx.Colour(35, 35, 142)) self.heading_in_envdata.SetForegroundColour(wx.Colour(250, 249, 255)) - self.heading_in_envdata.SetFont(wx.Font(12, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, 0, "")) + self.heading_in_envdata.SetFont(wx.Font(16, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, 0, "")) self.in_humidity.SetFont(wx.Font(24, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, 0, "")) self.in_pressure.SetFont(wx.Font(24, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, 0, "")) self.in_temperature_min.SetFont(wx.Font(24, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, 0, "")) @@ -74,13 +74,9 @@ class Wetation(wx.Frame): self.in_temperature.SetFont(wx.Font(48, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, 0, "")) self.heading_garage.SetBackgroundColour(wx.Colour(35, 35, 142)) self.heading_garage.SetForegroundColour(wx.Colour(250, 249, 255)) - self.heading_garage.SetFont(wx.Font(12, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, 0, "")) - self.heading_garage.Hide() - self.gate_oc.Hide() - self.gate_close.Hide() + self.heading_garage.SetFont(wx.Font(16, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, 0, "")) + self.gate_oc.SetMinSize((100, 50)) self.gate_position.Enable(False) - self.gate_position.Hide() - self.gate_open.Hide() # end wxGlade def __do_layout(self): diff --git a/gui.wxg b/gui.wxg index b187523..940eef6 100644 --- a/gui.wxg +++ b/gui.wxg @@ -1,9 +1,9 @@ - + - 800, 628 + 800, 655 #faf9ff #23238e frame @@ -106,14 +106,14 @@ #23238e #faf9ff - 12 + 16 default normal 0 - + 1 @@ -161,7 +161,7 @@ - + 1 @@ -255,14 +255,14 @@ #23238e #faf9ff - 12 + 16 default normal 0 - + 1 @@ -310,7 +310,7 @@ - + 1 @@ -404,14 +404,13 @@ #23238e #faf9ff - 12 + 16 default normal 0 - 1 1 @@ -429,7 +428,7 @@ gate_oc_evt - 1 + 100, 50 @@ -438,7 +437,6 @@ 0 wxALIGN_CENTER - 1 1 @@ -449,7 +447,6 @@ wxEXPAND 1 - 1 0, 100 50 @@ -460,7 +457,6 @@ 0 wxALIGN_CENTER - 1 1 diff --git a/smarthome.py b/smarthome.py index 8d8612e..1fe3e8a 100644 --- a/smarthome.py +++ b/smarthome.py @@ -2,6 +2,8 @@ # -*- coding: UTF-8 -*- # +#TODO: Zyklischer reconnect versuch (ggf. inkl. herstellen der Schnittstelle für ein reconnect beim tcp_client) + import config import rpi_envsens as envsens import garage_protocol @@ -19,82 +21,180 @@ logger = logging.getLogger('APP') class WetationFrameProt(gui.Wetation): - def __init__(self, *args, **kwds): - gui.Wetation.__init__(self, *args, **kwds) - self.__task_data_request__ = task.periodic(10, self.__initiate_data_request__) - self.__init__communication__() + PROT_ID_GARAGE = 0 + PROT_ID_IN = 1 + PROT_ID_OUT = 2 + ALL_PROT_IDS = [PROT_ID_GARAGE, PROT_ID_IN, PROT_ID_OUT] + + REQUEST_MSGS = { + PROT_ID_GARAGE: [ + { + 'service_id': garage_protocol.my_base_protocol_tcp.SID_READ_REQUEST, + 'data_id': garage_protocol.my_base_protocol_tcp.GATE_POSITION, + }, + ], + PROT_ID_IN: [ + { + 'service_id': wetation_protocol.my_base_protocol_tcp.SID_READ_REQUEST, + 'data_id': wetation_protocol.my_base_protocol_tcp.CURRENT_ENVDATA, + }, + ], + PROT_ID_OUT: [ + { + 'service_id': wetation_protocol.my_base_protocol_tcp.SID_READ_REQUEST, + 'data_id': wetation_protocol.my_base_protocol_tcp.CURRENT_ENVDATA, + }, + ], + } - def __init__communication__(self): + + def __init__(self, *args, **kwds): + self.__prot__ = {} + self.no_data = { + self.PROT_ID_GARAGE: self.update_gate_position, + self.PROT_ID_IN: self.update_current_env_data_in, + self.PROT_ID_OUT: self.update_current_env_data_out, + } + gui.Wetation.__init__(self, *args, **kwds) + self.ShowFullScreen(config.FULL_SCREEN) + + self.__init_communication__() + self.__task_data_request__ = task.periodic(10, self.__initiate_data_request__) + + def __init_protocol__(self, prot_id, ip, port, prot_class, secret): + c_tcp = tcp_socket.tcp_client_stp(ip, port, rx_log_lvl=logging.DEBUG) + self.__prot__[prot_id] = prot_class(c_tcp, secret) + if config.server_garage_secret is not None: + self.__prot__[prot_id].authentificate() + + def __init_communication__(self): # # Start TCP-Clients - c_tcp = tcp_socket.tcp_client_stp(config.server_out_ip, config.server_out_port, rx_log_lvl=logging.DEBUG) - self.prot_out = wetation_protocol.my_base_protocol_tcp(c_tcp, config.server_out_secret) - self.prot_out.register_callback(wetation_protocol.my_base_protocol_tcp.SID_READ_RESPONSE, wetation_protocol.my_base_protocol_tcp.CURRENT_ENVDATA, self.update_current_env_data_out) - if config.server_out_secret is not None: - self.prot_out.authentificate() + self.__init_protocol__( + self.PROT_ID_GARAGE, + config.server_garage_ip, + config.server_garage_port, + garage_protocol.my_base_protocol_tcp, + config.server_garage_secret + ) + self.__prot__[self.PROT_ID_GARAGE].register_callback(garage_protocol.my_base_protocol_tcp.SID_READ_RESPONSE, None, self.__garage_data__) - c_tcp = tcp_socket.tcp_client_stp(config.server_in_ip, config.server_in_port, rx_log_lvl=logging.DEBUG) - self.prot_in = wetation_protocol.my_base_protocol_tcp(c_tcp, config.server_in_secret) - self.prot_in.register_callback(wetation_protocol.my_base_protocol_tcp.SID_READ_RESPONSE, wetation_protocol.my_base_protocol_tcp.CURRENT_ENVDATA, self.update_current_env_data_in) - if config.server_in_secret is not None: - self.prot_in.authentificate() + self.__init_protocol__( + self.PROT_ID_IN, + config.server_in_ip, + config.server_in_port, + wetation_protocol.my_base_protocol_tcp, + config.server_in_secret + ) + self.__prot__[self.PROT_ID_IN].register_callback(wetation_protocol.my_base_protocol_tcp.SID_READ_RESPONSE, None, self.__in_data__) - c_tcp = tcp_socket.tcp_client_stp(config.server_garage_ip, config.server_garage_port, rx_log_lvl=logging.DEBUG) - self.prot_garage = garage_protocol.my_base_protocol_tcp(c_tcp, config.server_garage_secret) - self.prot_garage.register_callback(garage_protocol.my_base_protocol_tcp.SID_READ_RESPONSE, garage_protocol.my_base_protocol_tcp.GATE_POSITION, self.update_gate_position) - if config.server_garage_secret is not None: - self.prot_garage.authentificate() - - def __update_current_envdata__(self, msg, temperature, humidity, pressure): - if msg.get_status() == wetation_protocol.my_base_protocol_tcp.STATUS_OKAY: - env_data = msg.get_data() - wx.CallAfter(temperature.SetLabel, "%.1f °C" % env_data[envsens.KEY_TEMPERATURE]) - wx.CallAfter(humidity.SetLabel, "%.1f %%" % env_data[envsens.KEY_HUMIDITY]) - wx.CallAfter(pressure.SetLabel, "%.0f mbar" % env_data[envsens.KEY_PRESSURE]) - wx.CallAfter(self.Layout) - return wetation_protocol.my_base_protocol_tcp.STATUS_OKAY, None - else: - logger.error('No environmental data received! MSG_STATUS was %s', wetation_protocol.my_base_protocol_tcp.STATUS_NAMES.get(msg.get_status(), repr(msg.get_status()))) - return wetation_protocol.my_base_protocol_tcp.STATUS_SERVICE_OR_DATA_UNKNOWN, None - - def update_current_env_data_out(self, msg): - return self.__update_current_envdata__(msg, self.out_temperature, self.out_humidity, self.out_pressure) - - def update_current_env_data_in(self, msg): - return self.__update_current_envdata__(msg, self.in_temperature, self.in_humidity, self.in_pressure) - - def update_gate_position(self, msg): - if msg.get_status() == garage_protocol.my_base_protocol_tcp.STATUS_OKAY: - # - # show gate section in GUI - # - 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) - # - # update gate position - # - wx.CallAfter(self.gate_position.SetValue, msg.get_data() * 100) - wx.CallAfter(self.Layout) - return garage_protocol.my_base_protocol_tcp.STATUS_OKAY, None - else: - logger.error('No gate position received! MSG_STATUS was %s', garage_protocol.my_base_protocol_tcp.STATUS_NAMES.get(msg.get_status(), repr(msg.get_status()))) - return garage_protocol.my_base_protocol_tcp.STATUS_SERVICE_OR_DATA_UNKNOWN, None - - def garage_oc_evt(self, event): # wxGlade: Wetation. - self.prot_garage.send(garage_protocol.my_base_protocol_tcp.SID_EXECUTE_REQUEST, garage_protocol.my_base_protocol_tcp.OPEN_CLOSE_GATE, None) - event.Skip() + self.__init_protocol__( + self.PROT_ID_OUT, + config.server_out_ip, + config.server_out_port, + wetation_protocol.my_base_protocol_tcp, + config.server_out_secret + ) + self.__prot__[self.PROT_ID_OUT].register_callback(wetation_protocol.my_base_protocol_tcp.SID_READ_RESPONSE, None, self.__out_data__) def __initiate_data_request__(self, rt): - self.prot_out.send(wetation_protocol.my_base_protocol_tcp.SID_READ_REQUEST, wetation_protocol.my_base_protocol_tcp.CURRENT_ENVDATA, None) - self.prot_in.send(wetation_protocol.my_base_protocol_tcp.SID_READ_REQUEST, wetation_protocol.my_base_protocol_tcp.CURRENT_ENVDATA, None) - self.prot_garage.send(garage_protocol.my_base_protocol_tcp.SID_READ_REQUEST, garage_protocol.my_base_protocol_tcp.GATE_POSITION, None) + for prot_id in self.ALL_PROT_IDS: + if self.__prot__[prot_id].is_connected(): + for request_msg in self.REQUEST_MSGS.get(prot_id, []): + service_id = request_msg['service_id'] + data_id = request_msg['data_id'] + logger.debug('Sending data request for prot_id %d, service_id %d and data_id %d', prot_id, service_id, data_id) + self.__prot__[prot_id].send(service_id, data_id, None) + else: + logger.debug('Resetting GUI for prot_id %d', prot_id) + wx.CallAfter(self.no_data[prot_id], None) + # TODO: Move the following three lines to the wx idle task - wx.CallAfter(self.time.SetLabel, time.strftime("%H:%M")) - wx.CallAfter(self.date.SetLabel, time.strftime("%d.%m.%Y")) - wx.CallAfter(self.Layout) + wx.CallAfter(self.update_time) + + def __in_data__(self, msg): + return self.__env_data__(msg, self.PROT_ID_IN) + + def __out_data__(self, msg): + return self.__env_data__(msg, self.PROT_ID_OUT) + + def __env_data__(self, msg, prot_id): + logger.debug('Received data for prot_id %d, service_id %d, data_id %d', prot_id, msg.get_service_id(), msg.get_data_id()) + if msg.get_status() == wetation_protocol.my_base_protocol_tcp.STATUS_OKAY: + if msg.get_data_id() == wetation_protocol.my_base_protocol_tcp.CURRENT_ENVDATA: + if prot_id == self.PROT_ID_IN: + wx.CallAfter(self.update_current_env_data_in, msg) + else: + wx.CallAfter(self.update_current_env_data_out, msg) + return wetation_protocol.my_base_protocol_tcp.STATUS_OKAY, None + else: + logger.warning('Received unknown data for prot_id %d, service_id %d, data_id %d', self.PROT_ID_GARAGE, msg.get_service_id(), msg.get_data_id()) + return wetation_protocol.my_base_protocol_tcp.STATUS_OKAY, None + else: + logger.error('Error, receiving environmental data! MSG_STATUS was %s with PROT_ID %d', garage_protocol.my_base_protocol_tcp.STATUS_NAMES.get(msg.get_status(), repr(msg.get_status())), prot_id) + return wetation_protocol.my_base_protocol_tcp.STATUS_SERVICE_OR_DATA_UNKNOWN, None + + def __garage_data__(self, msg): + logger.debug('Received data for prot_id %d, service_id %d, data_id %d', self.PROT_ID_GARAGE, msg.get_service_id(), msg.get_data_id()) + if msg.get_status() == garage_protocol.my_base_protocol_tcp.STATUS_OKAY: + if msg.get_data_id() == garage_protocol.my_base_protocol_tcp.GATE_POSITION: + wx.CallAfter(self.update_gate_position, msg) + return garage_protocol.my_base_protocol_tcp.STATUS_OKAY, None + else: + logger.warning('Received unknown data for prot_id %d, service_id %d, data_id %d', self.PROT_ID_GARAGE, msg.get_service_id(), msg.get_data_id()) + else: + logger.error('Error, receiving garage data! MSG_STATUS was %s', garage_protocol.my_base_protocol_tcp.STATUS_NAMES.get(msg.get_status(), repr(msg.get_status()))) + return garage_protocol.my_base_protocol_tcp.STATUS_SERVICE_OR_DATA_UNKNOWN, None + + + def update_current_env_data_in(self, msg): + if msg is None: + temperature = '-.-' + humidity = '-.-' + pressure = '-' + else: + env_data = msg.get_data() + temperature = '%.1f' % env_data[envsens.KEY_TEMPERATURE] + humidity = '%.1f' % env_data[envsens.KEY_HUMIDITY] + pressure = '%.0f' % env_data[envsens.KEY_PRESSURE] + self.in_temperature.SetLabel("%s °C" % temperature) + self.in_humidity.SetLabel("%s %%" % humidity) + self.in_pressure.SetLabel("%s hPa" % pressure) + self.Layout() + + def update_current_env_data_out(self, msg): + if msg is None: + temperature = '-.-' + humidity = '-.-' + pressure = '-' + else: + env_data = msg.get_data() + temperature = "%.1f" % env_data[envsens.KEY_TEMPERATURE] + humidity = "%.1f" % env_data[envsens.KEY_HUMIDITY] + pressure = "%.0f" % env_data[envsens.KEY_PRESSURE] + self.out_temperature.SetLabel("%s °C" % temperature) + self.out_humidity.SetLabel("%s %%" % humidity) + self.out_pressure.SetLabel("%s hPa" % pressure) + self.Layout() + + def update_gate_position(self, msg): + self.heading_garage.Show(msg is not None) + self.gate_oc.Show(msg is not None) + self.gate_open.Show(msg is not None) + self.gate_position.Show(msg is not None) + self.gate_close.Show(msg is not None) + if msg is not None: + self.gate_position.SetValue(msg.get_data() * 100) + 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): # wxGlade: Wetation. + self.prot_garage.send(garage_protocol.my_base_protocol_tcp.SID_EXECUTE_REQUEST, garage_protocol.my_base_protocol_tcp.OPEN_CLOSE_GATE, None) + event.Skip() def run(self): self.__task_data_request__.run() diff --git a/socket_protocol b/socket_protocol index b0857e4..bfcdef7 160000 --- a/socket_protocol +++ b/socket_protocol @@ -1 +1 @@ -Subproject commit b0857e4569c34b9b644f5640731be0c413ce54d4 +Subproject commit bfcdef7ad7ce8d8cb1fb1245ad7ce56ead34b39c diff --git a/tcp_socket b/tcp_socket index 62f13e2..10aa319 160000 --- a/tcp_socket +++ b/tcp_socket @@ -1 +1 @@ -Subproject commit 62f13e2d878b09b81d094c2f77dbd830d72be2c7 +Subproject commit 10aa319d2edffda001750bf26bd468753d9c2dc4