wether station gui client
Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  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. SLOW_PROT_IDS = [PROT_ID_IN, PROT_ID_OUT, ]
  24. FAST_PROT_IDS = [PROT_ID_GARAGE, ]
  25. REQUEST_MSGS = {
  26. PROT_ID_GARAGE: [
  27. {
  28. 'service_id': garage_protocol.my_base_protocol_tcp.SID_READ_REQUEST,
  29. 'data_id': garage_protocol.my_base_protocol_tcp.GATE_POSITION,
  30. },
  31. ],
  32. PROT_ID_IN: [
  33. {
  34. 'service_id': wetation_protocol.my_base_protocol_tcp.SID_READ_REQUEST,
  35. 'data_id': wetation_protocol.my_base_protocol_tcp.CURRENT_ENVDATA,
  36. },
  37. ],
  38. PROT_ID_OUT: [
  39. {
  40. 'service_id': wetation_protocol.my_base_protocol_tcp.SID_READ_REQUEST,
  41. 'data_id': wetation_protocol.my_base_protocol_tcp.CURRENT_ENVDATA,
  42. },
  43. ],
  44. }
  45. def __init__(self, *args, **kwds):
  46. self.__prot__ = {}
  47. self.no_data = {
  48. self.PROT_ID_GARAGE: self.update_gate_position,
  49. self.PROT_ID_IN: self.update_current_env_data_in,
  50. self.PROT_ID_OUT: self.update_current_env_data_out,
  51. }
  52. gui.Wetation.__init__(self, *args, **kwds)
  53. self.ShowFullScreen(config.FULL_SCREEN)
  54. self.__init_communication__()
  55. self.__task_1s__ = task.periodic(1, self.__task_1s_callback__)
  56. self.__task_10s__ = task.periodic(10, self.__task_10s_callback__)
  57. self.__task_60s__ = task.periodic(60, self.__task_60s_callback__)
  58. def __init_protocol__(self, prot_id, ip, port, prot_class, secret):
  59. c_tcp = tcp_socket.tcp_client_stp(ip, port, rx_log_lvl=logging.DEBUG)
  60. self.__prot__[prot_id] = prot_class(c_tcp, secret)
  61. if config.server_garage_secret is not None:
  62. self.__prot__[prot_id].authentificate()
  63. def __init_communication__(self):
  64. #
  65. # Start TCP-Clients
  66. self.__init_protocol__(
  67. self.PROT_ID_GARAGE,
  68. config.server_garage_ip,
  69. config.server_garage_port,
  70. garage_protocol.my_base_protocol_tcp,
  71. config.server_garage_secret
  72. )
  73. self.__prot__[self.PROT_ID_GARAGE].register_callback(garage_protocol.my_base_protocol_tcp.SID_READ_RESPONSE, None, self.__garage_data__)
  74. self.__init_protocol__(
  75. self.PROT_ID_IN,
  76. config.server_in_ip,
  77. config.server_in_port,
  78. wetation_protocol.my_base_protocol_tcp,
  79. config.server_in_secret
  80. )
  81. self.__prot__[self.PROT_ID_IN].register_callback(wetation_protocol.my_base_protocol_tcp.SID_READ_RESPONSE, None, self.__in_data__)
  82. self.__init_protocol__(
  83. self.PROT_ID_OUT,
  84. config.server_out_ip,
  85. config.server_out_port,
  86. wetation_protocol.my_base_protocol_tcp,
  87. config.server_out_secret
  88. )
  89. self.__prot__[self.PROT_ID_OUT].register_callback(wetation_protocol.my_base_protocol_tcp.SID_READ_RESPONSE, None, self.__out_data__)
  90. def __task_1s_callback__(self, rt):
  91. # request data from fast prot ids
  92. self.__initiate_data_request__(rt, self.FAST_PROT_IDS)
  93. # set date and time
  94. wx.CallAfter(self.update_time)
  95. def __task_10s_callback__(self, rt):
  96. # request data from slow prot ids
  97. self.__initiate_data_request__(rt, self.SLOW_PROT_IDS)
  98. def __task_60s_callback__(self, rt):
  99. # reconnect prots if needed
  100. for prot_id in self.ALL_PROT_IDS:
  101. if not self.__prot__[prot_id].is_connected():
  102. logger.debug("Trying to reconnect prot_id %d", prot_id)
  103. self.__prot__[prot_id].reconnect()
  104. def __initiate_data_request__(self, rt, prot_ids):
  105. for prot_id in prot_ids:
  106. if self.__prot__[prot_id].is_connected():
  107. for request_msg in self.REQUEST_MSGS.get(prot_id, []):
  108. service_id = request_msg['service_id']
  109. data_id = request_msg['data_id']
  110. logger.debug('Sending data request for prot_id %d, service_id %d and data_id %d', prot_id, service_id, data_id)
  111. self.__prot__[prot_id].send(service_id, data_id, None)
  112. else:
  113. logger.debug('Resetting GUI for prot_id %d', prot_id)
  114. wx.CallAfter(self.no_data[prot_id], None)
  115. def __in_data__(self, msg):
  116. return self.__env_data__(msg, self.PROT_ID_IN)
  117. def __out_data__(self, msg):
  118. return self.__env_data__(msg, self.PROT_ID_OUT)
  119. def __env_data__(self, msg, prot_id):
  120. logger.debug('Received data for prot_id %d, service_id %d, data_id %d', prot_id, msg.get_service_id(), msg.get_data_id())
  121. if msg.get_status() == wetation_protocol.my_base_protocol_tcp.STATUS_OKAY:
  122. if msg.get_data_id() == wetation_protocol.my_base_protocol_tcp.CURRENT_ENVDATA:
  123. if prot_id == self.PROT_ID_IN:
  124. wx.CallAfter(self.update_current_env_data_in, msg)
  125. else:
  126. wx.CallAfter(self.update_current_env_data_out, msg)
  127. return wetation_protocol.my_base_protocol_tcp.STATUS_OKAY, None
  128. else:
  129. 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())
  130. return wetation_protocol.my_base_protocol_tcp.STATUS_OKAY, None
  131. else:
  132. 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)
  133. return wetation_protocol.my_base_protocol_tcp.STATUS_SERVICE_OR_DATA_UNKNOWN, None
  134. def __garage_data__(self, msg):
  135. 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())
  136. if msg.get_status() == garage_protocol.my_base_protocol_tcp.STATUS_OKAY:
  137. if msg.get_data_id() == garage_protocol.my_base_protocol_tcp.GATE_POSITION:
  138. wx.CallAfter(self.update_gate_position, msg)
  139. return garage_protocol.my_base_protocol_tcp.STATUS_OKAY, None
  140. else:
  141. 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())
  142. else:
  143. 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())))
  144. return garage_protocol.my_base_protocol_tcp.STATUS_SERVICE_OR_DATA_UNKNOWN, None
  145. def update_current_env_data_in(self, msg):
  146. if msg is None:
  147. temperature = '-.-'
  148. humidity = '-.-'
  149. pressure = '-'
  150. else:
  151. env_data = msg.get_data()
  152. temperature = '%.1f' % env_data[envsens.KEY_TEMPERATURE]
  153. humidity = '%.1f' % env_data[envsens.KEY_HUMIDITY]
  154. pressure = '%.0f' % env_data[envsens.KEY_PRESSURE]
  155. self.in_temperature.SetLabel("%s °C" % temperature)
  156. self.in_humidity.SetLabel("%s %%" % humidity)
  157. self.in_pressure.SetLabel("%s hPa" % pressure)
  158. self.Layout()
  159. def update_current_env_data_out(self, msg):
  160. if msg is None:
  161. temperature = '-.-'
  162. humidity = '-.-'
  163. pressure = '-'
  164. else:
  165. env_data = msg.get_data()
  166. temperature = "%.1f" % env_data[envsens.KEY_TEMPERATURE]
  167. humidity = "%.1f" % env_data[envsens.KEY_HUMIDITY]
  168. pressure = "%.0f" % env_data[envsens.KEY_PRESSURE]
  169. self.out_temperature.SetLabel("%s °C" % temperature)
  170. self.out_humidity.SetLabel("%s %%" % humidity)
  171. self.out_pressure.SetLabel("%s hPa" % pressure)
  172. self.Layout()
  173. def update_gate_position(self, msg):
  174. self.heading_garage.Show(msg is not None)
  175. self.gate_oc.Show(msg is not None)
  176. self.gate_open.Show(msg is not None)
  177. self.gate_position.Show(msg is not None)
  178. self.gate_close.Show(msg is not None)
  179. if msg is not None:
  180. self.gate_position.SetValue(msg.get_data() * 100)
  181. self.Layout()
  182. def update_time(self):
  183. self.time.SetLabel(time.strftime("%H:%M"))
  184. self.date.SetLabel(time.strftime("%d.%m.%Y"))
  185. self.Layout()
  186. def gate_oc_evt(self, event): # wxGlade: Wetation.<event_handler>
  187. logger.debug("Gate open/close request")
  188. self.__prot__[self.PROT_ID_GARAGE].send(garage_protocol.my_base_protocol_tcp.SID_EXECUTE_REQUEST, garage_protocol.my_base_protocol_tcp.OPEN_CLOSE_GATE, None)
  189. event.Skip()
  190. def run(self):
  191. self.__task_1s__.run()
  192. self.__task_10s__.run()
  193. self.__task_60s__.run()
  194. def close(self):
  195. self.__task_1s__.stop()
  196. self.__task_1s__.join()
  197. self.__task_10s__.stop()
  198. self.__task_10s__.join()
  199. self.__task_60s__.stop()
  200. self.__task_60s__.join()
  201. def __del__(self):
  202. self.close()
  203. class MyApp(wx.App):
  204. def OnInit(self):
  205. self.frame = WetationFrameProt(None, wx.ID_ANY, "")
  206. self.SetTopWindow(self.frame)
  207. self.frame.Show()
  208. return True
  209. if __name__ == "__main__":
  210. report.appLoggingConfigure(os.path.dirname(__file__), config.LOGTARGET, config.loggers)
  211. #
  212. app = MyApp(0)
  213. app.frame.run()
  214. app.MainLoop()
  215. app.frame.close()