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 22KB

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