wether station gui client
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

smarthome.py 8.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. #!/usr/bin/env python
  2. # -*- coding: UTF-8 -*-
  3. #
  4. #TODO: Zyklischer reconnect versuch (ggf. inkl. herstellen der Schnittstelle für ein reconnect beim tcp_client)
  5. import config
  6. import rpi_envsens as envsens
  7. import garage_protocol
  8. import gui
  9. import logging
  10. import os
  11. import report
  12. import task
  13. import tcp_socket
  14. import time
  15. import wetation_protocol
  16. import wx
  17. logger = logging.getLogger('APP')
  18. class WetationFrameProt(gui.Wetation):
  19. PROT_ID_GARAGE = 0
  20. PROT_ID_IN = 1
  21. PROT_ID_OUT = 2
  22. ALL_PROT_IDS = [PROT_ID_GARAGE, PROT_ID_IN, PROT_ID_OUT]
  23. REQUEST_MSGS = {
  24. PROT_ID_GARAGE: [
  25. {
  26. 'service_id': garage_protocol.my_base_protocol_tcp.SID_READ_REQUEST,
  27. 'data_id': garage_protocol.my_base_protocol_tcp.GATE_POSITION,
  28. },
  29. ],
  30. PROT_ID_IN: [
  31. {
  32. 'service_id': wetation_protocol.my_base_protocol_tcp.SID_READ_REQUEST,
  33. 'data_id': wetation_protocol.my_base_protocol_tcp.CURRENT_ENVDATA,
  34. },
  35. ],
  36. PROT_ID_OUT: [
  37. {
  38. 'service_id': wetation_protocol.my_base_protocol_tcp.SID_READ_REQUEST,
  39. 'data_id': wetation_protocol.my_base_protocol_tcp.CURRENT_ENVDATA,
  40. },
  41. ],
  42. }
  43. def __init__(self, *args, **kwds):
  44. self.__prot__ = {}
  45. self.no_data = {
  46. self.PROT_ID_GARAGE: self.update_gate_position,
  47. self.PROT_ID_IN: self.update_current_env_data_in,
  48. self.PROT_ID_OUT: self.update_current_env_data_out,
  49. }
  50. gui.Wetation.__init__(self, *args, **kwds)
  51. self.ShowFullScreen(config.FULL_SCREEN)
  52. self.__init_communication__()
  53. self.__task_data_request__ = task.periodic(10, self.__initiate_data_request__)
  54. def __init_protocol__(self, prot_id, ip, port, prot_class, secret):
  55. c_tcp = tcp_socket.tcp_client_stp(ip, port, rx_log_lvl=logging.DEBUG)
  56. self.__prot__[prot_id] = prot_class(c_tcp, secret)
  57. if config.server_garage_secret is not None:
  58. self.__prot__[prot_id].authentificate()
  59. def __init_communication__(self):
  60. #
  61. # Start TCP-Clients
  62. self.__init_protocol__(
  63. self.PROT_ID_GARAGE,
  64. config.server_garage_ip,
  65. config.server_garage_port,
  66. garage_protocol.my_base_protocol_tcp,
  67. config.server_garage_secret
  68. )
  69. self.__prot__[self.PROT_ID_GARAGE].register_callback(garage_protocol.my_base_protocol_tcp.SID_READ_RESPONSE, None, self.__garage_data__)
  70. self.__init_protocol__(
  71. self.PROT_ID_IN,
  72. config.server_in_ip,
  73. config.server_in_port,
  74. wetation_protocol.my_base_protocol_tcp,
  75. config.server_in_secret
  76. )
  77. self.__prot__[self.PROT_ID_IN].register_callback(wetation_protocol.my_base_protocol_tcp.SID_READ_RESPONSE, None, self.__in_data__)
  78. self.__init_protocol__(
  79. self.PROT_ID_OUT,
  80. config.server_out_ip,
  81. config.server_out_port,
  82. wetation_protocol.my_base_protocol_tcp,
  83. config.server_out_secret
  84. )
  85. self.__prot__[self.PROT_ID_OUT].register_callback(wetation_protocol.my_base_protocol_tcp.SID_READ_RESPONSE, None, self.__out_data__)
  86. def __initiate_data_request__(self, rt):
  87. for prot_id in self.ALL_PROT_IDS:
  88. if self.__prot__[prot_id].is_connected():
  89. for request_msg in self.REQUEST_MSGS.get(prot_id, []):
  90. service_id = request_msg['service_id']
  91. data_id = request_msg['data_id']
  92. logger.debug('Sending data request for prot_id %d, service_id %d and data_id %d', prot_id, service_id, data_id)
  93. self.__prot__[prot_id].send(service_id, data_id, None)
  94. else:
  95. logger.debug('Resetting GUI for prot_id %d', prot_id)
  96. wx.CallAfter(self.no_data[prot_id], None)
  97. # TODO: Move the following three lines to the wx idle task
  98. wx.CallAfter(self.update_time)
  99. def __in_data__(self, msg):
  100. return self.__env_data__(msg, self.PROT_ID_IN)
  101. def __out_data__(self, msg):
  102. return self.__env_data__(msg, self.PROT_ID_OUT)
  103. def __env_data__(self, msg, prot_id):
  104. logger.debug('Received data for prot_id %d, service_id %d, data_id %d', prot_id, msg.get_service_id(), msg.get_data_id())
  105. if msg.get_status() == wetation_protocol.my_base_protocol_tcp.STATUS_OKAY:
  106. if msg.get_data_id() == wetation_protocol.my_base_protocol_tcp.CURRENT_ENVDATA:
  107. if prot_id == self.PROT_ID_IN:
  108. wx.CallAfter(self.update_current_env_data_in, msg)
  109. else:
  110. wx.CallAfter(self.update_current_env_data_out, msg)
  111. return wetation_protocol.my_base_protocol_tcp.STATUS_OKAY, None
  112. else:
  113. 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())
  114. return wetation_protocol.my_base_protocol_tcp.STATUS_OKAY, None
  115. else:
  116. 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)
  117. return wetation_protocol.my_base_protocol_tcp.STATUS_SERVICE_OR_DATA_UNKNOWN, None
  118. def __garage_data__(self, msg):
  119. 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())
  120. if msg.get_status() == garage_protocol.my_base_protocol_tcp.STATUS_OKAY:
  121. if msg.get_data_id() == garage_protocol.my_base_protocol_tcp.GATE_POSITION:
  122. wx.CallAfter(self.update_gate_position, msg)
  123. return garage_protocol.my_base_protocol_tcp.STATUS_OKAY, None
  124. else:
  125. 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())
  126. else:
  127. 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())))
  128. return garage_protocol.my_base_protocol_tcp.STATUS_SERVICE_OR_DATA_UNKNOWN, None
  129. def update_current_env_data_in(self, msg):
  130. if msg is None:
  131. temperature = '-.-'
  132. humidity = '-.-'
  133. pressure = '-'
  134. else:
  135. env_data = msg.get_data()
  136. temperature = '%.1f' % env_data[envsens.KEY_TEMPERATURE]
  137. humidity = '%.1f' % env_data[envsens.KEY_HUMIDITY]
  138. pressure = '%.0f' % env_data[envsens.KEY_PRESSURE]
  139. self.in_temperature.SetLabel("%s °C" % temperature)
  140. self.in_humidity.SetLabel("%s %%" % humidity)
  141. self.in_pressure.SetLabel("%s hPa" % pressure)
  142. self.Layout()
  143. def update_current_env_data_out(self, msg):
  144. if msg is None:
  145. temperature = '-.-'
  146. humidity = '-.-'
  147. pressure = '-'
  148. else:
  149. env_data = msg.get_data()
  150. temperature = "%.1f" % env_data[envsens.KEY_TEMPERATURE]
  151. humidity = "%.1f" % env_data[envsens.KEY_HUMIDITY]
  152. pressure = "%.0f" % env_data[envsens.KEY_PRESSURE]
  153. self.out_temperature.SetLabel("%s °C" % temperature)
  154. self.out_humidity.SetLabel("%s %%" % humidity)
  155. self.out_pressure.SetLabel("%s hPa" % pressure)
  156. self.Layout()
  157. def update_gate_position(self, msg):
  158. self.heading_garage.Show(msg is not None)
  159. self.gate_oc.Show(msg is not None)
  160. self.gate_open.Show(msg is not None)
  161. self.gate_position.Show(msg is not None)
  162. self.gate_close.Show(msg is not None)
  163. if msg is not None:
  164. self.gate_position.SetValue(msg.get_data() * 100)
  165. self.Layout()
  166. def update_time(self):
  167. self.time.SetLabel(time.strftime("%H:%M"))
  168. self.date.SetLabel(time.strftime("%d.%m.%Y"))
  169. self.Layout()
  170. def gate_oc_evt(self, event): # wxGlade: Wetation.<event_handler>
  171. self.prot_garage.send(garage_protocol.my_base_protocol_tcp.SID_EXECUTE_REQUEST, garage_protocol.my_base_protocol_tcp.OPEN_CLOSE_GATE, None)
  172. event.Skip()
  173. def run(self):
  174. self.__task_data_request__.run()
  175. def close(self):
  176. self.__task_data_request__.stop()
  177. self.__task_data_request__.join()
  178. def __del__(self):
  179. self.close()
  180. class MyApp(wx.App):
  181. def OnInit(self):
  182. self.frame = WetationFrameProt(None, wx.ID_ANY, "")
  183. self.SetTopWindow(self.frame)
  184. self.frame.Show()
  185. return True
  186. if __name__ == "__main__":
  187. report.appLoggingConfigure(os.path.dirname(__file__), config.LOGTARGET, config.loggers)
  188. #
  189. app = MyApp(0)
  190. app.frame.run()
  191. app.MainLoop()
  192. app.frame.close()