Test Smart Brain implementation
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.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396
  1. import colored
  2. import config
  3. import inspect
  4. import simulation.devices as devices
  5. import time
  6. DT_TOGGLE = 0.3
  7. TEST_FULL = 'full'
  8. TEST_SMOKE = 'smoke'
  9. #
  10. COLOR_SUCCESS = colored.fg("light_green")
  11. COLOR_FAIL = colored.fg("light_red")
  12. class test_smarthome(object):
  13. def __init__(self, rooms):
  14. # add testcases for switching devices
  15. for name in rooms.getmembers():
  16. obj = rooms.getobjbyname(name)
  17. if obj.__class__.__name__ == "videv_light":
  18. common_name = '.'.join(name.split('.')[:-1]) + '.' + name.split('.')[-1][6:]
  19. try:
  20. li_device = rooms.getobjbyname(common_name + '_zigbee') if obj.enable_brightness or obj.enable_color_temp else None
  21. except AttributeError:
  22. li_device = rooms.getobjbyname(common_name + '_zigbee_1') if obj.enable_brightness or obj.enable_color_temp else None
  23. try:
  24. sw_device = rooms.getobjbyname(common_name) if obj.enable_state else None
  25. except AttributeError:
  26. # must be a device without switching device
  27. sw_device = li_device
  28. setattr(self, common_name.replace('.', '_'), testcase_light(obj, sw_device, li_device))
  29. # add testcases for heating devices
  30. for name in rooms.getmembers():
  31. obj = rooms.getobjbyname(name)
  32. if obj.__class__.__name__ == "videv_heating":
  33. common_name = '.'.join(name.split('.')[:-1]) + '.' + name.split('.')[-1][6:]
  34. heat_device = rooms.getobjbyname(common_name + '_valve')
  35. setattr(self, common_name.replace('.', '_'), testcase_heating(obj, heat_device))
  36. # synchronisation
  37. self.gfw_dirk_cd_player_amplifier_sync = testcase_synchronisation(
  38. rooms.gfw.dirk.cd_player, None, None,
  39. rooms.gfw.dirk.amplifier)
  40. self.gfw_floor_main_light_sync = testcase_synchronisation(
  41. rooms.gfw.floor.main_light, rooms.gfw.floor.videv_main_light, rooms.gfw.floor.videv_main_light,
  42. rooms.gfw.floor.main_light_zigbee_1, rooms.gfw.floor.main_light_zigbee_2
  43. )
  44. self.ffe_diningroom_main_light_floor_lamp_sync = testcase_synchronisation(
  45. rooms.ffe.diningroom.main_light, None, None,
  46. rooms.ffe.diningroom.floor_lamp)
  47. self.ffe_livingroom_main_light_floor_lamp_sync = testcase_synchronisation(
  48. rooms.ffe.livingroom.main_light, rooms.ffe.livingroom.videv_floor_lamp, rooms.ffe.livingroom.videv_floor_lamp,
  49. *[getattr(rooms.ffe.livingroom, "floor_lamp_zigbee_%d" % i) for i in range(1, 7)]
  50. )
  51. # add test collection
  52. self.all = test_collection(self)
  53. def getmembers(self, prefix=''):
  54. rv = []
  55. for name, obj in inspect.getmembers(self):
  56. if prefix:
  57. full_name = prefix + '.' + name
  58. else:
  59. full_name = name
  60. if not name.startswith('_'):
  61. try:
  62. if obj.__class__.__bases__[0].__name__ == "testcase" or obj.__class__.__name__ == "test_collection":
  63. rv.append(full_name)
  64. else:
  65. rv.extend(obj.getmembers(full_name))
  66. except AttributeError:
  67. pass
  68. return rv
  69. def getobjbyname(self, name):
  70. if name.startswith("test."):
  71. name = name[5:]
  72. obj = self
  73. for subname in name.split('.'):
  74. obj = getattr(obj, subname)
  75. return obj
  76. def command(self, full_command):
  77. try:
  78. parameter = " " + full_command.split(' ')[1]
  79. except IndexError:
  80. parameter = ""
  81. command = full_command.split(' ')[0].split('.')[-1] + parameter
  82. device_name = '.'.join(full_command.split(' ')[0].split('.')[:-1])
  83. self.getobjbyname(device_name).command(command)
  84. class test_result_base(object):
  85. def __init__(self):
  86. self.__init_test_counters__()
  87. def __init_test_counters__(self):
  88. self.test_counter = 0
  89. self.success_tests = 0
  90. self.failed_tests = 0
  91. def statistic(self):
  92. return (self.test_counter, self.success_tests, self.failed_tests)
  93. def print_statistic(self):
  94. color = COLOR_SUCCESS if self.test_counter == self.success_tests else COLOR_FAIL
  95. print(color + "*** SUCCESS: (%4d/%4d) FAIL: (%4d/%4d) ***\n" % (self.success_tests,
  96. self.test_counter, self.failed_tests, self.test_counter) + colored.attr("reset"))
  97. class test_collection(test_result_base):
  98. def __init__(self, test_instance):
  99. super().__init__()
  100. self.test_instance = test_instance
  101. def capabilities(self):
  102. return [TEST_FULL, TEST_SMOKE]
  103. def command(self, command):
  104. self.__init_test_counters__()
  105. for member in self.test_instance.getmembers():
  106. obj = self.test_instance.getobjbyname(member)
  107. if id(obj) != id(self):
  108. obj.test_all(command)
  109. num, suc, fail = obj.statistic()
  110. self.test_counter += num
  111. self.success_tests += suc
  112. self.failed_tests += fail
  113. self.print_statistic()
  114. class testcase(test_result_base):
  115. def __init__(self):
  116. super().__init__()
  117. self.__test_list__ = []
  118. def capabilities(self):
  119. if len(self.__test_list__) > 0 and not 'test_all' in self.__test_list__:
  120. self.__test_list__.append('test_all')
  121. self.__test_list__.sort()
  122. return self.__test_list__
  123. def test_all(self, test=TEST_FULL):
  124. test_counter = 0
  125. success_tests = 0
  126. failed_tests = 0
  127. for tc_name in self.capabilities():
  128. if tc_name != "test_all":
  129. self.command(tc_name, test)
  130. test_counter += self.test_counter
  131. success_tests += self.success_tests
  132. failed_tests += self.failed_tests
  133. self.test_counter = test_counter
  134. self.success_tests = success_tests
  135. self.failed_tests = failed_tests
  136. def command(self, command, test=TEST_FULL):
  137. self.__init_test_counters__()
  138. tc = getattr(self, command)
  139. self.__init_test_counters__()
  140. tc(test)
  141. self.print_statistic()
  142. def heading(self, desciption):
  143. print(desciption)
  144. def sub_heading(self, desciption):
  145. print(2 * " " + desciption)
  146. def result(self, desciption, success):
  147. self.test_counter += 1
  148. if success:
  149. self.success_tests += 1
  150. else:
  151. self.failed_tests += 1
  152. print(4 * " " + ("SUCCESS - " if success else "FAIL - ") + desciption)
  153. class testcase_light(testcase):
  154. def __init__(self, videv, sw_device, li_device):
  155. self.videv = videv
  156. self.sw_device = sw_device
  157. self.li_device = li_device
  158. self.__test_list__ = []
  159. if self.videv.enable_state:
  160. self.__test_list__.append('test_power_on_off')
  161. if self.videv.enable_brightness:
  162. self.__test_list__.append('test_brightness')
  163. if self.videv.enable_color_temp:
  164. self.__test_list__.append('test_color_temp')
  165. def test_power_on_off(self, test=TEST_FULL):
  166. self.heading("Power On/ Off test (%s)" % self.videv.topic)
  167. #
  168. sw_state = self.sw_device.get(self.sw_device.KEY_OUTPUT_0)
  169. #
  170. for i in range(0, 2):
  171. self.sub_heading("State change of switching device")
  172. #
  173. self.sw_device.set(self.sw_device.KEY_OUTPUT_0, not self.sw_device.get(self.sw_device.KEY_OUTPUT_0))
  174. time.sleep(DT_TOGGLE)
  175. self.result("Virtual device state after Switch on by switching device", sw_state != self.videv.get(self.videv.KEY_OUTPUT_0))
  176. self.result("Switching device state after Switch on by switching device",
  177. sw_state != self.sw_device.get(self.sw_device.KEY_OUTPUT_0))
  178. self.sub_heading("State change of virtual device")
  179. #
  180. self.videv.set(self.videv.KEY_OUTPUT_0, not self.videv.get(self.videv.KEY_OUTPUT_0))
  181. time.sleep(DT_TOGGLE)
  182. self.result("Virtual device state after Switch off by virtual device", sw_state == self.videv.get(self.videv.KEY_OUTPUT_0))
  183. self.result("Switching device state after Switch on by switching device",
  184. sw_state == self.sw_device.get(self.sw_device.KEY_OUTPUT_0))
  185. def test_brightness(self, test=TEST_FULL):
  186. self.heading("Brightness test (%s)" % self.videv.topic)
  187. #
  188. br_state = self.li_device.get(self.li_device.KEY_BRIGHTNESS)
  189. delta = -15 if br_state > 50 else 15
  190. self.sw_device.set(self.sw_device.KEY_OUTPUT_0, True)
  191. time.sleep(DT_TOGGLE)
  192. for i in range(0, 2):
  193. self.sub_heading("Brightness change by light device")
  194. #
  195. self.li_device.set(self.li_device.KEY_BRIGHTNESS, br_state + delta)
  196. time.sleep(DT_TOGGLE)
  197. self.result("Virtual device state after setting brightness by light device",
  198. br_state + delta == self.videv.get(self.videv.KEY_BRIGHTNESS))
  199. self.result("Light device state after setting brightness by light device", br_state +
  200. delta == self.li_device.get(self.li_device.KEY_BRIGHTNESS))
  201. self.sub_heading("Brightness change by virtual device")
  202. #
  203. self.videv.set(self.videv.KEY_BRIGHTNESS, br_state)
  204. time.sleep(DT_TOGGLE)
  205. self.result("Virtual device state after setting brightness by light device", br_state == self.videv.get(self.videv.KEY_BRIGHTNESS))
  206. self.result("Light device state after setting brightness by light device",
  207. br_state == self.li_device.get(self.li_device.KEY_BRIGHTNESS))
  208. self.sw_device.set(self.sw_device.KEY_OUTPUT_0, False)
  209. time.sleep(DT_TOGGLE)
  210. def test_color_temp(self, test=TEST_FULL):
  211. self.heading("Color temperature test (%s)" % self.videv.topic)
  212. #
  213. ct_state = self.li_device.get(self.li_device.KEY_COLOR_TEMP)
  214. delta = -3 if ct_state > 5 else 3
  215. self.sw_device.set(self.sw_device.KEY_OUTPUT_0, True)
  216. time.sleep(DT_TOGGLE)
  217. for i in range(0, 2):
  218. self.sub_heading("Color temperature change by light device")
  219. #
  220. self.li_device.set(self.li_device.KEY_COLOR_TEMP, ct_state + delta)
  221. time.sleep(DT_TOGGLE)
  222. self.result("Virtual device state after setting color temperature by light device",
  223. ct_state + delta == self.videv.get(self.videv.KEY_COLOR_TEMP))
  224. self.result("Light device state after setting color temperature by light device", ct_state +
  225. delta == self.li_device.get(self.li_device.KEY_COLOR_TEMP))
  226. self.sub_heading("Color temperature change by virtual device")
  227. #
  228. self.videv.set(self.videv.KEY_COLOR_TEMP, ct_state)
  229. time.sleep(DT_TOGGLE)
  230. self.result("Virtual device state after setting color temperature by light device",
  231. ct_state == self.videv.get(self.videv.KEY_COLOR_TEMP))
  232. self.result("Light device state after setting color temperature by light device",
  233. ct_state == self.li_device.get(self.li_device.KEY_COLOR_TEMP))
  234. self.sw_device.set(self.sw_device.KEY_OUTPUT_0, False)
  235. time.sleep(DT_TOGGLE)
  236. class testcase_synchronisation(testcase):
  237. def __init__(self, sw_master, br_master, ct_master, *follower):
  238. super().__init__()
  239. self.sw_master = sw_master
  240. self.br_master = br_master
  241. self.ct_master = ct_master
  242. self.follower = follower
  243. self.__test_list__ = []
  244. if sw_master is not None:
  245. self.__test_list__.append('test_power_on_off_sync')
  246. if br_master is not None:
  247. self.__test_list__.append('test_brightness_sync')
  248. def test_power_on_off_sync(self, test=TEST_FULL):
  249. self.heading("Power On/ Off sychronisation test")
  250. #
  251. # set sw_master to slave state as precondition
  252. f_state = self.follower[0].get(self.follower[0].KEY_OUTPUT_0)
  253. self.sw_master.set(self.sw_master.KEY_OUTPUT_0, f_state)
  254. time.sleep(DT_TOGGLE)
  255. for i in range(0, 2):
  256. self.sub_heading("State change of sw_master device")
  257. #
  258. self.sw_master.set(self.sw_master.KEY_OUTPUT_0, not f_state)
  259. time.sleep(DT_TOGGLE)
  260. f_state = not f_state
  261. for fo in self.follower:
  262. self.result("Follower device state after switching (%s)" % fo.topic,
  263. f_state == fo.get(fo.KEY_OUTPUT_0))
  264. def test_brightness_sync(self, test=TEST_FULL):
  265. self.heading("Power On/ Off sychronisation test")
  266. #
  267. # set precondition
  268. sw_state = self.sw_master.get(self.sw_master.KEY_OUTPUT_0)
  269. self.sw_master.set(self.sw_master.KEY_OUTPUT_0, True)
  270. time.sleep(DT_TOGGLE)
  271. target = self.follower[0].get(self.follower[0].KEY_BRIGHTNESS)
  272. delta = 15 if target < 50 else -15
  273. for i in range(0, 2):
  274. target = target + delta
  275. self.sub_heading("State change of br_master device")
  276. #
  277. self.br_master.set(self.br_master.KEY_BRIGHTNESS, target)
  278. time.sleep(DT_TOGGLE)
  279. for fo in self.follower:
  280. self.result("Follower device brightness after change (%s)" % fo.topic,
  281. target == fo.get(fo.KEY_BRIGHTNESS))
  282. delta = -delta
  283. # reset changes of precondition
  284. self.sw_master.set(self.sw_master.KEY_OUTPUT_0, sw_state)
  285. time.sleep(DT_TOGGLE)
  286. class testcase_heating(testcase):
  287. def __init__(self, videv, valve):
  288. self.__videv__ = videv
  289. self.__valve__ = valve
  290. self.__default_temperature__ = config.DEFAULT_TEMPERATURE.get(self.__valve__.topic)
  291. self.__test_list__ = ["test_user_temperature_setpoint", "test_default_temperature", ]
  292. def test_user_temperature_setpoint(self, test=TEST_FULL):
  293. self.heading("User temperature setpoint test (%s)" % self.__videv__.topic)
  294. #
  295. mtemp = round(self.__valve__.TEMP_RANGE[0] + (self.__valve__.TEMP_RANGE[1] - self.__valve__.TEMP_RANGE[0]) / 2, 1)
  296. setp = self.__valve__.get(self.__valve__.KEY_TEMPERATURE_SETPOINT)
  297. delta = 5 if setp < mtemp else -5
  298. for i in range(0, 2):
  299. self.sub_heading("Setpoint change by valve device")
  300. #
  301. self.__valve__.set(self.__valve__.KEY_TEMPERATURE_SETPOINT, setp + delta)
  302. time.sleep(DT_TOGGLE)
  303. self.result("Virtual device valve temperature after setting temperature by valve device",
  304. setp + delta == self.__videv__.get(self.__videv__.KEY_VALVE_TEMPERATURE_SETPOINT))
  305. self.result("Virtual device user temperature after setting temperature by valve device",
  306. setp + delta == self.__videv__.get(self.__videv__.KEY_USER_TEMPERATURE_SETPOINT))
  307. self.sub_heading("Setpoint change by videv device")
  308. #
  309. self.__videv__.set(self.__videv__.KEY_USER_TEMPERATURE_SETPOINT, setp)
  310. time.sleep(DT_TOGGLE)
  311. self.result("Valve device temperature setpoint after setting temperature by videv device",
  312. setp == self.__valve__.get(self.__valve__.KEY_TEMPERATURE_SETPOINT))
  313. self.result("Virtual device valve temperature after setting temperature by videv device",
  314. setp == self.__videv__.get(self.__videv__.KEY_VALVE_TEMPERATURE_SETPOINT))
  315. def test_default_temperature(self, test=TEST_FULL):
  316. self.heading("Default temperature setpoint test (%s)" % self.__videv__.topic)
  317. #
  318. dtemp = config.DEFAULT_TEMPERATURE.get(self.__valve__.topic)
  319. mtemp = round(self.__valve__.TEMP_RANGE[0] + (self.__valve__.TEMP_RANGE[1] - self.__valve__.TEMP_RANGE[0]) / 2, 1)
  320. ptemp = dtemp + (5 if dtemp < mtemp else -5)
  321. self.sub_heading("Setting setpoint to a value unequal default as precondition")
  322. self.__valve__.set(self.__valve__.KEY_TEMPERATURE_SETPOINT, ptemp)
  323. time.sleep(DT_TOGGLE)
  324. self.result("Valve device temperature setpoint after setting precondition temperature",
  325. ptemp == self.__valve__.get(self.__valve__.KEY_TEMPERATURE_SETPOINT))
  326. self.sub_heading("Triggering default temperature by videv device")
  327. self.__videv__.set(self.__videv__.KEY_SET_DEFAULT_TEMPERATURE, None)
  328. time.sleep(DT_TOGGLE)
  329. self.result("Valve device temperature setpoint after setting default temperature",
  330. dtemp == self.__valve__.get(self.__valve__.KEY_TEMPERATURE_SETPOINT))
  331. def test_summer_mode(self, test=TEST_FULL):
  332. pass
  333. def test_away_mode(self, test=TEST_FULL):
  334. pass
  335. def test_boost_mode(self, test=TEST_FULL):
  336. pass
  337. if test == TEST_FULL:
  338. # test boost timer
  339. pass