Module to run and control leyk lightning
Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

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()