Module to run and control leyk lightning
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

piface_function.py 21KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589
  1. #!/usr/bin/env python
  2. # -*- coding: UTF-8 -*-
  3. try:
  4. import pifacedigitalio
  5. except ImportError:
  6. pifacedigitalio = None
  7. import config
  8. import geo
  9. import json
  10. import logging
  11. import mqtt
  12. import state_machine
  13. import task
  14. import random
  15. import socket
  16. import time
  17. try:
  18. from config import APP_NAME as ROOT_LOGGER_NAME
  19. except ImportError:
  20. ROOT_LOGGER_NAME = 'root'
  21. logger = logging.getLogger(ROOT_LOGGER_NAME).getChild(__name__)
  22. class pi_face(object):
  23. LOG_PREFIX = 'PiFace:'
  24. PF_OUT_NAMES = ['Output 0', # 0
  25. 'Output 1', # 1
  26. 'Output 2', # 2
  27. 'Ploenlein', # 3
  28. 'Bakery', # 4
  29. 'Mill', # 5
  30. 'Reese House', # 6
  31. 'Bake House'] # 7
  32. def __init__(self, client):
  33. self.__client__ = client
  34. if pifacedigitalio is not None:
  35. pifacedigitalio.init()
  36. pi = pifacedigitalio.PiFaceDigital()
  37. self.__pf_outputs__ = pi.output_pins
  38. self.__pf_output_states__ = 8 * [False]
  39. #
  40. self._reload = 0
  41. self._task_10ms = task.periodic(0.01 - 0.007, self.task_10ms)
  42. #
  43. for i in range(0, 8):
  44. self.set_output(i, self.__pf_output_states__[i])
  45. def set_output(self, index, state, tries=5):
  46. tries = min(max(1, tries), 5)
  47. try_txt = ['1st', '2nd', '3rd', '4th', '5th']
  48. state = state is True
  49. if pifacedigitalio is not None:
  50. cnt = 0
  51. while (cnt < tries) and (self.__pf_outputs__[index].value != state):
  52. self.__pf_outputs__[index].value = 1 * state
  53. time.sleep(0.1)
  54. cnt += 1
  55. if self.__pf_outputs__[index].value != state:
  56. logger.warning('%s Control of output[%d] (%s) after %s try not successfull!', self.LOG_PREFIX, index, self.PF_OUT_NAMES[index], try_txt[cnt - 1])
  57. else:
  58. logger.info('%s Set output "%s" to %s.', self.LOG_PREFIX, self.PF_OUT_NAMES[index], repr(state))
  59. self.__pf_output_states__[index] = self.__pf_outputs__[index].value == 1
  60. else:
  61. logger.info('%s Set virtual output "%s" to %s.', self.LOG_PREFIX, self.PF_OUT_NAMES[index], repr(state))
  62. self.__pf_output_states__[index] = state
  63. def get_output(self, index):
  64. return self.__pf_output_states__[index]
  65. def get_ploenlein(self):
  66. return self.get_output(3)
  67. def set_bakery(self, state):
  68. self.set_output(4, state)
  69. def get_bakery(self):
  70. return self.get_output(4)
  71. def set_mill(self, state):
  72. self.set_output(5, state)
  73. def get_mill(self):
  74. return self.get_output(5)
  75. def set_ploenlein(self, state):
  76. self.set_output(3, state)
  77. def set_reese_house(self, state):
  78. self.set_output(6, state)
  79. def get_reese_house(self):
  80. return self.get_output(6)
  81. def set_bake_house(self, state):
  82. if state is True:
  83. self.set_output(7, state)
  84. self._task_10ms.run()
  85. elif state is False:
  86. self._task_10ms.stop()
  87. self.join()
  88. time.sleep(0.1)
  89. self.set_output(7, state)
  90. def get_bake_house(self):
  91. return not self._task_10ms._stopped
  92. def task_10ms(self, task_inst):
  93. if self._reload <= 0:
  94. if pifacedigitalio is not None:
  95. self.__pf_outputs__[7].turn_on()
  96. self._reload = random.choice(2 * [0] + 20 * [1] + 1 * [2])
  97. else:
  98. if pifacedigitalio is not None:
  99. self.__pf_outputs__[7].turn_off()
  100. self._reload -= 1
  101. def join(self):
  102. self._task_10ms.join()
  103. def stop(self):
  104. try:
  105. self._task_10ms.stop()
  106. self._task_10ms.join()
  107. except AttributeError:
  108. pass # seems that there was an exception before init of task
  109. for i in range(0, 8):
  110. self.set_output(i, False)
  111. pifacedigitalio.deinit()
  112. def __del__(self):
  113. self.stop()
  114. class state_machine_mode(state_machine.state_machine):
  115. LOG_PREFIX = 'LeykMode:'
  116. STATE_AUTOMATIC = 'automatic'
  117. STATE_MANUAL = 'manual'
  118. CONDITION_EXTERNAL_TRIGGER = 'external_trigger'
  119. TRANSITIONS = {
  120. STATE_AUTOMATIC: (
  121. (CONDITION_EXTERNAL_TRIGGER, 1, STATE_MANUAL),
  122. ),
  123. STATE_MANUAL: (
  124. (CONDITION_EXTERNAL_TRIGGER, 1, STATE_AUTOMATIC),
  125. ),
  126. }
  127. def __init__(self, **kwargs):
  128. state_machine.state_machine.__init__(self, self.STATE_AUTOMATIC, logging.INFO)
  129. self.__reset_triggers__()
  130. def __reset_triggers__(self):
  131. self.__to_automatic__ = False
  132. self.__to_manual__ = False
  133. def external_trigger(self):
  134. rv = False
  135. if self.this_state() == self.STATE_AUTOMATIC:
  136. rv = self.__to_manual__
  137. elif self.this_state() == self.STATE_MANUAL:
  138. rv = self.__to_automatic__
  139. self.__reset_triggers__()
  140. return rv
  141. def trigger_to_maual(self):
  142. if self.this_state() == self.STATE_AUTOMATIC:
  143. self.__to_manual__ = True
  144. return True
  145. return False
  146. def trigger_to_automatic(self):
  147. if self.this_state() == self.STATE_MANUAL:
  148. self.__to_automatic__ = True
  149. return True
  150. return False
  151. class state_machine_day_state(state_machine.state_machine):
  152. LOG_PREFIX = 'LeykState:'
  153. STATE_IDLE = 'idle'
  154. STATE_WAKE = 'wake'
  155. STATE_SUNRISE = 'sunrise'
  156. STATE_SUNSET = 'sunset'
  157. STATE_SLEEP = 'sleep'
  158. CONDITION_WAKE = 'condition_wake'
  159. CONDITION_SUNRISE = 'condition_sunrise'
  160. CONDITION_SUNSET = 'condition_sunset'
  161. CONDITION_SLEEP = 'condition_sleep'
  162. CONDITION_IDLE = 'condition_idle'
  163. TRANSITIONS = {
  164. STATE_IDLE: (
  165. (CONDITION_WAKE, 1, STATE_WAKE),
  166. (CONDITION_SUNRISE, 1, STATE_SUNRISE),
  167. (CONDITION_SUNSET, 1, STATE_SUNSET),
  168. (CONDITION_SLEEP, 1, STATE_SLEEP),
  169. ),
  170. STATE_WAKE: (
  171. (CONDITION_SUNRISE, 1, STATE_SUNRISE),
  172. (CONDITION_IDLE, 1, STATE_IDLE),
  173. ),
  174. STATE_SUNRISE: (
  175. (CONDITION_SLEEP, 1, STATE_SLEEP),
  176. (CONDITION_SUNSET, 1, STATE_SUNSET),
  177. (CONDITION_IDLE, 1, STATE_IDLE),
  178. ),
  179. STATE_SUNSET: (
  180. (CONDITION_SLEEP, 1, STATE_SLEEP),
  181. (CONDITION_IDLE, 1, STATE_IDLE),
  182. ),
  183. STATE_SLEEP: (
  184. (CONDITION_WAKE, 1, STATE_WAKE),
  185. (CONDITION_SUNRISE, 1, STATE_SUNRISE),
  186. (CONDITION_IDLE, 1, STATE_IDLE),
  187. ),
  188. }
  189. def __init__(self, **kwargs):
  190. state_machine.state_machine.__init__(self, self.STATE_IDLE, logging.INFO, **kwargs)
  191. def __current_state_calc__(self):
  192. def wake_time():
  193. tm = time.localtime()
  194. tm = list(tm)
  195. tm[3] = 6 # tm_hour
  196. tm[4] = 0 # tm_min
  197. tm[5] = 0 # tm_sec=0
  198. return time.mktime(time.struct_time(tm))
  199. def sunrise_time():
  200. return time.mktime(geo.sun.sunrise(config.GEO_POSITION)) + 30 * 60
  201. def sunset_time():
  202. return time.mktime(geo.sun.sunset(config.GEO_POSITION)) - 30 * 60
  203. def sleep_time():
  204. tm = time.localtime()
  205. tm = list(tm)
  206. tm[3] = 21 # tm_hour
  207. tm[4] = 15 # tm_min
  208. tm[5] = 0 # tm_sec=0
  209. return time.mktime(time.struct_time(tm))
  210. now = time.mktime(time.localtime())
  211. if now > sleep_time():
  212. return self.STATE_SLEEP
  213. elif now > sunset_time():
  214. return self.STATE_SUNSET
  215. elif now > sunrise_time():
  216. return self.STATE_SUNRISE
  217. elif now > wake_time():
  218. return self.STATE_WAKE
  219. else:
  220. return self.STATE_IDLE
  221. def condition_wake(self):
  222. if self.condition_idle():
  223. return False
  224. return self.__current_state_calc__() == self.STATE_WAKE
  225. def condition_sunrise(self):
  226. if self.condition_idle():
  227. return False
  228. return self.__current_state_calc__() == self.STATE_SUNRISE
  229. def condition_sunset(self):
  230. if self.condition_idle():
  231. return False
  232. return self.__current_state_calc__() == self.STATE_SUNSET
  233. def condition_sleep(self):
  234. if self.condition_idle():
  235. return False
  236. return self.__current_state_calc__() == self.STATE_SLEEP
  237. def condition_idle(self):
  238. return not self.sm_mode.this_state_is(self.sm_mode.STATE_AUTOMATIC)
  239. def report_sunset_sunrise(self):
  240. state_machine.logger.debug('Sunrise: %s - Sunset: %s;', time.strftime("%H:%M", geo.sun.sunrise(config.GEO_POSITION)), time.strftime("%H:%M", geo.sun.sunset(config.GEO_POSITION))
  241. )
  242. class leyk(object):
  243. LOG_PREFIX = 'Leyk:'
  244. TOPIC_BAKE_HOUSE = config.MQTT_TOPIC + '/status/Bake House'
  245. TOPIC_BAKERY = config.MQTT_TOPIC + '/status/Bakery'
  246. TOPIC_MILL = config.MQTT_TOPIC + '/status/Mill'
  247. TOPIC_MODE = config.MQTT_TOPIC + '/status/mode'
  248. TOPIC_MODE_BOOL = config.MQTT_TOPIC + '/status/mode_bool'
  249. TOPIC_PLOENLEIN = config.MQTT_TOPIC + '/status/Ploenlein'
  250. TOPIC_REESE_HOUSE = config.MQTT_TOPIC + '/status/Reese House'
  251. TOPIC_STATE = config.MQTT_TOPIC + '/status/state'
  252. RX_TOPIC_BAKE_HOUSE = config.MQTT_TOPIC + '/set/Bake House'
  253. RX_TOPIC_BAKERY = config.MQTT_TOPIC + '/set/Bakery'
  254. RX_TOPIC_MILL = config.MQTT_TOPIC + '/set/Mill'
  255. RX_TOPIC_MODE = config.MQTT_TOPIC + '/set/mode'
  256. RX_TOPIC_PLOENLEIN = config.MQTT_TOPIC + '/set/Ploenlein'
  257. RX_TOPIC_REESE_HOUSE = config.MQTT_TOPIC + '/set/Reese House'
  258. RX_TOPICS = [
  259. RX_TOPIC_BAKE_HOUSE,
  260. RX_TOPIC_BAKERY,
  261. RX_TOPIC_MILL,
  262. RX_TOPIC_MODE,
  263. RX_TOPIC_PLOENLEIN,
  264. RX_TOPIC_REESE_HOUSE
  265. ]
  266. def __init__(self):
  267. self.__client__ = mqtt.mqtt_client(config.APP_NAME, config.MQTT_SERVER, 1883, config.MQTT_USER, config.MQTT_PASS)
  268. self.__client__.add_callback(self.RX_TOPIC_BAKE_HOUSE, self.__rx_bake_house__)
  269. self.__client__.add_callback(self.RX_TOPIC_BAKERY, self.__rx_bakery__)
  270. self.__client__.add_callback(self.RX_TOPIC_MILL, self.__rx_mill__)
  271. self.__client__.add_callback(self.RX_TOPIC_PLOENLEIN, self.__rx_ploenlein__)
  272. self.__client__.add_callback(self.RX_TOPIC_REESE_HOUSE, self.__rx_reese_house__)
  273. self.__client__.add_callback(self.RX_TOPIC_MODE, self.__rx_mode__)
  274. self.TOPIC_DATA = {
  275. self.TOPIC_BAKE_HOUSE: self.get_bake_house,
  276. self.TOPIC_BAKERY: self.get_bakery,
  277. self.TOPIC_MILL: self.get_mill,
  278. self.TOPIC_MODE: self.get_mode,
  279. self.TOPIC_MODE_BOOL: self.get_mode_bool,
  280. self.TOPIC_PLOENLEIN: self.get_ploenlein,
  281. self.TOPIC_REESE_HOUSE: self.get_reese_house,
  282. self.TOPIC_STATE: self.get_state
  283. }
  284. self.sm_mode = state_machine_mode()
  285. self.sm_day_state = state_machine_day_state(sm_mode=self.sm_mode)
  286. self.__pf__ = pi_face(self.__client__)
  287. self._queue = task.threaded_queue()
  288. self._queue.run()
  289. self._task_1s = task.periodic(1, self.task_1s)
  290. self._task_1s.run()
  291. self.sm_mode.register_state_change_callback(self.sm_mode.STATE_MANUAL, None, self._queue.clean_queue)
  292. self.sm_mode.register_state_change_callback(None, None, self.publish, self.TOPIC_MODE)
  293. self.sm_mode.register_state_change_callback(None, None, self.publish, self.TOPIC_MODE_BOOL)
  294. self.sm_day_state.register_state_change_callback(None, None, self.clean_queue)
  295. self.sm_day_state.register_state_change_callback(None, None, self.publish, self.TOPIC_STATE)
  296. self.sm_day_state.register_state_change_callback(self.sm_day_state.STATE_SLEEP, None, self.sm_day_state.report_sunset_sunrise)
  297. self.sm_day_state.register_state_change_callback(self.sm_day_state.STATE_SLEEP, None, self.fill_sleep_queue)
  298. self.sm_day_state.register_state_change_callback(self.sm_day_state.STATE_SUNRISE, None, self.sm_day_state.report_sunset_sunrise)
  299. self.sm_day_state.register_state_change_callback(self.sm_day_state.STATE_SUNRISE, None, self.fill_sunrise_queue)
  300. self.sm_day_state.register_state_change_callback(self.sm_day_state.STATE_SUNSET, None, self.sm_day_state.report_sunset_sunrise)
  301. self.sm_day_state.register_state_change_callback(self.sm_day_state.STATE_SUNSET, None, self.fill_sunset_queue)
  302. self.sm_day_state.register_state_change_callback(self.sm_day_state.STATE_WAKE, None, self.sm_day_state.report_sunset_sunrise)
  303. self.sm_day_state.register_state_change_callback(self.sm_day_state.STATE_WAKE, None, self.fill_wake_queue)
  304. self.publish(self.TOPIC_MODE)
  305. self.publish(self.TOPIC_MODE_BOOL)
  306. self.publish(self.TOPIC_STATE)
  307. def __rx_bake_house__(self, client, userdata, message):
  308. self.set_bake_house(message.payload == b'true')
  309. def __rx_bakery__(self, client, userdata, message):
  310. self.set_bakery(message.payload == b'true')
  311. def __rx_mill__(self, client, userdata, message):
  312. self.set_mill(message.payload == b'true')
  313. def __rx_ploenlein__(self, client, userdata, message):
  314. self.set_ploenlein(message.payload == b'true')
  315. def __rx_reese_house__(self, client, userdata, message):
  316. self.set_reese_house(message.payload == b'true')
  317. def __rx_mode__(self, client, userdata, message):
  318. self.set_mode(self.sm_mode.STATE_AUTOMATIC if message.payload == b'true' else self.sm_mode.STATE_MANUAL)
  319. def publish_states(self):
  320. for name in self.TOPIC_DATA:
  321. self.publish(name)
  322. def publish(self, topic):
  323. logger.info("Sending Leyk status information to mqtt %s = %s", topic, json.dumps(self.TOPIC_DATA[topic]()))
  324. try:
  325. self.__client__.send(topic, json.dumps(self.TOPIC_DATA[topic]()))
  326. except (socket.timeout, OSError) as e:
  327. logger.warning("Error while sending state information information")
  328. def set_mode(self, mode):
  329. if mode == self.sm_mode.STATE_AUTOMATIC:
  330. rv = self.sm_mode.trigger_to_automatic()
  331. elif mode == self.sm_mode.STATE_MANUAL:
  332. rv = self.sm_mode.trigger_to_maual()
  333. else:
  334. rv = False
  335. return rv
  336. def get_mode(self):
  337. return self.sm_mode.this_state()
  338. def get_mode_bool(self):
  339. return self.get_mode() == self.sm_mode.STATE_AUTOMATIC
  340. def get_state(self):
  341. return self.sm_day_state.this_state()
  342. def __queue_wrapper__(self, queue_inst, function, *args, **kwargs):
  343. function(*args, **kwargs)
  344. def set_ploenlein(self, state, force=False):
  345. if force or self.sm_mode.this_state_is(self.sm_mode.STATE_MANUAL):
  346. self.__pf__.set_ploenlein(state)
  347. self.publish(self.TOPIC_PLOENLEIN)
  348. return True
  349. else:
  350. return False
  351. def get_ploenlein(self):
  352. return self.__pf__.get_ploenlein()
  353. def set_bakery(self, state, force=False):
  354. if force or self.sm_mode.this_state_is(self.sm_mode.STATE_MANUAL):
  355. self.__pf__.set_bakery(state)
  356. self.publish(self.TOPIC_BAKERY)
  357. return True
  358. else:
  359. return False
  360. def get_bakery(self):
  361. return self.__pf__.get_bakery()
  362. def set_bake_house(self, state, force=False):
  363. if force or self.sm_mode.this_state_is(self.sm_mode.STATE_MANUAL):
  364. self.__pf__.set_bake_house(state)
  365. self.publish(self.TOPIC_BAKE_HOUSE)
  366. return True
  367. else:
  368. return False
  369. def get_bake_house(self):
  370. return self.__pf__.get_bake_house()
  371. def set_mill(self, state, force=False):
  372. if force or self.sm_mode.this_state_is(self.sm_mode.STATE_MANUAL):
  373. self.__pf__.set_mill(state)
  374. self.publish(self.TOPIC_MILL)
  375. return True
  376. else:
  377. return False
  378. def get_mill(self):
  379. return self.__pf__.get_mill()
  380. def set_reese_house(self, state, force=False):
  381. if force or self.sm_mode.this_state_is(self.sm_mode.STATE_MANUAL):
  382. self.__pf__.set_reese_house(state)
  383. self.publish(self.TOPIC_REESE_HOUSE)
  384. return True
  385. else:
  386. return False
  387. def get_reese_house(self):
  388. return self.__pf__.get_reese_house()
  389. def wake_time(self):
  390. tm = time.localtime()
  391. tm = list(tm)
  392. tm[3] = 6 # tm_hour
  393. tm[4] = 0 # tm_min
  394. tm[5] = 0 # tm_sec=0
  395. return time.mktime(time.struct_time(tm))
  396. def sunrise_time(self):
  397. return time.mktime(geo.sun.sunrise(config.GEO_POSITION)) + 30 * 60
  398. def sunset_time(self):
  399. return time.mktime(geo.sun.sunset(config.GEO_POSITION)) - 30 * 60
  400. def sleep_time(self):
  401. tm = time.localtime()
  402. tm = list(tm)
  403. tm[3] = 21 # tm_hour
  404. tm[4] = 15 # tm_min
  405. tm[5] = 0 # tm_sec=0
  406. return time.mktime(time.struct_time(tm))
  407. def identify_current_state(self):
  408. now = time.mktime(time.localtime())
  409. if now > self.sleep_time():
  410. return self.ST_SLEEP
  411. elif now > self.sunset_time():
  412. return self.ST_SUNSET
  413. elif now > self.sunrise_time():
  414. return self.ST_SUNRISE
  415. elif now > self.wake_time():
  416. return self.ST_WAKE
  417. else:
  418. return self.ST_SLEEP
  419. def wait(self, queue_inst, delay):
  420. if delay > 0:
  421. logger.debug('%s Wait for %d seconds initiated. %d elements left in queue.', self.LOG_PREFIX, delay, queue_inst.qsize())
  422. cnt = 0
  423. while cnt < delay * 5:
  424. if queue_inst.qsize() == 0:
  425. logger.debug('%s Quit wait for %d seconds. %d elements left in queue.', self.LOG_PREFIX, delay, queue_inst.qsize())
  426. break
  427. time.sleep(0.2)
  428. cnt += 1
  429. def clean_queue(self):
  430. if self._queue.qsize() > 0:
  431. logger.info('Cleaning up remaining %d elements from queue', self._queue.qsize())
  432. self._queue.clean_queue()
  433. def fill_wake_queue(self):
  434. no_delay = self.sm_day_state.previous_state_was(self.sm_day_state.STATE_IDLE)
  435. # WAKE
  436. self._queue.enqueue(1, self.__queue_wrapper__, self.set_bakery, True, True)
  437. self._queue.enqueue(2, self.wait, 0 if no_delay else 5 * 60)
  438. self._queue.enqueue(3, self.__queue_wrapper__, self.set_bake_house, True, True)
  439. self._queue.enqueue(4, self.wait, 0 if no_delay else 10 * 60)
  440. self._queue.enqueue(5, self.__queue_wrapper__, self.set_reese_house, True, True)
  441. self._queue.enqueue(6, self.wait, 0 if no_delay else 7 * 60)
  442. self._queue.enqueue(7, self.__queue_wrapper__, self.set_ploenlein, True, True)
  443. self._queue.enqueue(8, self.wait, 0 if no_delay else 8 * 60)
  444. self._queue.enqueue(9, self.__queue_wrapper__, self.set_mill, True, True)
  445. def fill_sunrise_queue(self):
  446. no_delay = self.sm_day_state.previous_state_was(self.sm_day_state.STATE_IDLE)
  447. # SUNRISE
  448. self._queue.enqueue(1, self.__queue_wrapper__, self.set_bake_house, True, True)
  449. self._queue.enqueue(2, self.__queue_wrapper__, self.set_ploenlein, False, True)
  450. self._queue.enqueue(3, self.wait, 0 if no_delay else 5 * 60)
  451. self._queue.enqueue(4, self.__queue_wrapper__, self.set_mill, False, True)
  452. self._queue.enqueue(5, self.wait, 0 if no_delay else 8 * 60)
  453. self._queue.enqueue(6, self.__queue_wrapper__, self.set_bakery, False, True)
  454. self._queue.enqueue(7, self.wait, 0 if no_delay else 12 * 60)
  455. self._queue.enqueue(8, self.__queue_wrapper__, self.set_reese_house, False, True)
  456. def fill_sunset_queue(self):
  457. no_delay = self.sm_day_state.previous_state_was(self.sm_day_state.STATE_IDLE)
  458. # SUNSET
  459. self._queue.enqueue(1, self.__queue_wrapper__, self.set_bake_house, True, True)
  460. self._queue.enqueue(2, self.__queue_wrapper__, self.set_bakery, True, True)
  461. self._queue.enqueue(3, self.wait, 0 if no_delay else 10 * 60)
  462. self._queue.enqueue(4, self.__queue_wrapper__, self.set_reese_house, True, True)
  463. self._queue.enqueue(5, self.wait, 0 if no_delay else 8 * 60)
  464. self._queue.enqueue(6, self.__queue_wrapper__, self.set_mill, True, True)
  465. self._queue.enqueue(7, self.wait, 0 if no_delay else 7 * 60)
  466. self._queue.enqueue(8, self.__queue_wrapper__, self.set_ploenlein, True, True)
  467. def fill_sleep_queue(self):
  468. no_delay = self.sm_day_state.previous_state_was(self.sm_day_state.STATE_IDLE)
  469. # SLEEP
  470. self._queue.enqueue(1, self.__queue_wrapper__, self.set_bake_house, False, True)
  471. self._queue.enqueue(2, self.wait, 0 if no_delay else 5 * 60)
  472. self._queue.enqueue(3, self.__queue_wrapper__, self.set_bakery, False, True)
  473. self._queue.enqueue(4, self.wait, 0 if no_delay else 9 * 60)
  474. self._queue.enqueue(5, self.__queue_wrapper__, self.set_ploenlein, False, True)
  475. self._queue.enqueue(6, self.wait, 0 if no_delay else 9 * 60)
  476. self._queue.enqueue(7, self.__queue_wrapper__, self.set_mill, False, True)
  477. self._queue.enqueue(8, self.wait, 0 if no_delay else 6 * 60)
  478. self._queue.enqueue(9, self.__queue_wrapper__, self.set_reese_house, False, True)
  479. def task_1s(self, task_inst):
  480. self.sm_mode.work()
  481. self.sm_day_state.work()
  482. def join(self):
  483. self._task_1s.join()
  484. self._queue.join()
  485. def stop(self):
  486. self._task_1s.stop()
  487. self._queue.stop()
  488. def __del__(self):
  489. self.__client__.loop_stop() # stop the loop
  490. self.stop()