main.py 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  1. #!/usr/bin/env python
  2. # coding: utf-8
  3. # #################################################################################### #
  4. # this file is deprecated and replaced by the c implementation for performance reasons #
  5. # #################################################################################### #
  6. import re
  7. import time
  8. import json
  9. from datetime import datetime, timedelta
  10. from PIL import Image
  11. import errno
  12. from socket import error as socket_error
  13. from luma.led_matrix.device import max7219
  14. from luma.core.interface.serial import spi, noop
  15. from luma.core.render import canvas
  16. from luma.core.virtual import viewport
  17. from luma.core.legacy import text, show_message, textsize
  18. from luma.core.sprite_system import framerate_regulator
  19. from luma.core.legacy.font import proportional, CP437_FONT, TINY_FONT, SINCLAIR_FONT, LCD_FONT
  20. #import context # Ensures paho is in PYTHONPATH
  21. import paho.mqtt.client as mqtt
  22. # create matrix device
  23. serial = spi(port=0, device=0, gpio=noop())
  24. device = max7219(serial, cascaded=4, block_orientation=-90, rotate=0)
  25. print("Created device")
  26. umlauts = {
  27. u'\xe4': u'ae', #CP437 \x84
  28. u'\xf6': u'oe', #CP437 \x94
  29. u'\xfc': u'ue', #CP437 \x81
  30. u'\xc4': u'Ae', #CP437 \x8e
  31. u'\xd6': u'Oe', #CP437 \x99
  32. u'\xdc': u'Ue', #CP437 \x9a
  33. u'\xdf': u'ss', #CP437 \xe1
  34. u'\xb0': u'\x7f', # LCD °
  35. }
  36. # start demo
  37. txt = []
  38. status = ""
  39. c = 0
  40. sleep = 0
  41. bar = [50, 25]
  42. device.contrast(0)
  43. def on_message(mqttc, obj, msg):
  44. global txt, c, bar, status, sleep
  45. if msg.topic == "Minecraft/log":
  46. txt.append(msg.payload.decode("utf-8")[33:])
  47. elif msg.topic == "Room/display":
  48. txt.append(msg.payload.decode("utf-8"))
  49. elif msg.topic == "Timer/weather":
  50. w = json.loads(msg.payload)
  51. txt.append(u"{} {}°C".format(w["detail"], w["tempc"]))
  52. #txt.append(str(w["mintemp"]-273.15) + u'\x7fC - ' + str(w["maxtemp"]-273.15) + u'\x7fC')
  53. txt.append(u"LF {}%".format(w["humidity"]))
  54. txt.append(u"WLK {}%".format(w["clouds"]))
  55. txt.append(u"{} m/s".format(w["windspeed"]))
  56. elif msg.topic == "Timer/forecast":
  57. return
  58. pass
  59. #w = json.loads(str(msg.payload))
  60. #print(msg.topic + " " + str(w))
  61. elif msg.topic == "Timer/alert/1" and msg.payload != "-1":
  62. txt.append("Wecker: " + msg.payload.decode("utf-8")[0:5])
  63. elif msg.topic == "Timer/isDark":
  64. c &= ~2
  65. c |= (msg.payload == "0") * 2
  66. elif msg.topic == "Timer/isNight":
  67. c &= ~1
  68. c |= (msg.payload == "0")
  69. elif msg.topic == "Relaybox/3":
  70. sleep = 1 if msg.payload == "1" else 0
  71. else:
  72. print(msg.topic + " " + msg.payload.decode("utf-8"))
  73. #device.contrast(c * 32)
  74. def on_log(mqttc, obj, level, string):
  75. print(string)
  76. def on_connect(client, userdata, flags, rc):
  77. print("Connected with result code "+str(rc))
  78. mqttc.subscribe("Relaybox/3", 2)
  79. mqttc.subscribe("Timer/#", 2)
  80. mqttc.subscribe("Minecraft/log", 2)
  81. mqttc.subscribe("Room/display", 2)
  82. mqttc = mqtt.Client()
  83. mqttc.on_message = on_message
  84. mqttc.on_connect = on_connect
  85. # Uncomment to enable debug messages
  86. #mqttc.on_log = on_log
  87. mqttc.connect_async("localhost", 1883, 60)
  88. mqttc.loop_start()
  89. pos = 0
  90. words = []
  91. t = datetime.now()
  92. class TimeDisplay:
  93. def __init__(self, y):
  94. self.y = y
  95. self.current_y = 1
  96. self.isAnimating = False
  97. self.t = None
  98. self.draw = None
  99. def helper(self):
  100. hours = self.t.strftime('%H')
  101. minutes = self.t.strftime('%M')
  102. if hours[0] == "0":
  103. text(self.draw, (7, self.y+1), hours[1], fill="white", font=LCD_FONT)
  104. else:
  105. text(self.draw, (0, self.y+1), hours, fill="white", font=LCD_FONT)
  106. if self.t.second % 2:
  107. text(self.draw, (15, self.y+1), ":", fill="white", font=proportional(TINY_FONT))
  108. text(self.draw, (17, self.y+self.current_y), minutes, fill="white", font=LCD_FONT)
  109. def show(self, draw, t, currentLine):
  110. self.t = t
  111. self.draw = draw
  112. if t.second == 59 and not self.isAnimating and currentLine == self.y:
  113. self.isAnimating = True
  114. self.current_y = 1
  115. if self.isAnimating:
  116. self.helper()
  117. minutes = (self.t + timedelta(0,1)).strftime('%M')
  118. text(self.draw, (17, self.y+self.current_y-8), minutes, fill="white", font=LCD_FONT)
  119. self.current_y += 1
  120. if self.current_y > 9:
  121. self.current_y = 1
  122. self.isAnimating = False
  123. return False
  124. return True
  125. elif currentLine > self.y-8 and currentLine < self.y+8:
  126. self.helper()
  127. return False
  128. class DateDisplay:
  129. def __init__(self, y):
  130. self.y = y
  131. def show(self, draw, t, currentLine):
  132. if currentLine > self.y-8 and currentLine < self.y+8:
  133. day = t.strftime("%d")
  134. month = t.strftime("%m")
  135. text(draw, (0, self.y+1), day, fill="white", font=LCD_FONT)
  136. text(draw, (14, self.y+2), ".", fill="white", font=proportional(TINY_FONT))
  137. text(draw, (16, self.y+1), month, fill="white", font=LCD_FONT)
  138. text(draw, (31, self.y+2), ".", fill="white", font=proportional(TINY_FONT))
  139. return False
  140. class ScrollText:
  141. def __init__(self, y):
  142. self.font = proportional(LCD_FONT)
  143. self.y = y
  144. self.draw = None
  145. self.setText("LED Matrix")
  146. def helper(self, x, chars):
  147. text(self.draw, (x, self.y), chars, fill="white", font=self.font)
  148. def show(self, draw, t, currentLine):
  149. self.draw = draw
  150. if currentLine <= self.y-8 or currentLine >= self.y+8:
  151. return False
  152. self.helper(self.x + self.headLen, self.txt[self.charIndex:self.charIndex+8])
  153. if self.len >= 32:
  154. self.x -= 1
  155. else:
  156. self.x = 0
  157. if self.x + self.headLen <= -self.currentCharWidth and self.charIndex + 1 < len(self.txt):
  158. self.charIndex += 1
  159. self.headLen += self.currentCharWidth
  160. self.currentCharWidth, _ = textsize(self.txt[self.charIndex], self.font)
  161. if self.x <= -self.len:
  162. self.x = 31
  163. self.currentCharWidth, _ = textsize(self.txt[0], self.font)
  164. self.charIndex = 0
  165. self.headLen = 0
  166. if self.x == 0:
  167. return False
  168. return True
  169. def setText(self, txt):
  170. self.len, _ = textsize(txt, self.font)
  171. self.txt = txt + " "
  172. self.x = 0
  173. self.currentCharWidth, _ = textsize(self.txt[0], self.font)
  174. self.charIndex = 0
  175. self.headLen = 0
  176. class NightDisplay:
  177. def __init__(self, y):
  178. self.y = y
  179. self.t = None
  180. self.draw = None
  181. def helper(self):
  182. hours = self.t.strftime('%H')
  183. minutes = self.t.strftime('%M')
  184. for i in range(6):
  185. if self.t.hour & (2**i):
  186. self.draw.point((28 - i*5, self.y), fill="white")
  187. if self.t.minute & (2**i):
  188. self.draw.point((28 - i*5, self.y+3), fill="white")
  189. if self.t.second & (2**i):
  190. self.draw.point((28 - i*5, self.y+6), fill="white")
  191. def show(self, draw, t, currentLine):
  192. self.t = t
  193. self.draw = draw
  194. if currentLine <= self.y-8 or currentLine >= self.y+8:
  195. return False
  196. self.helper()
  197. return False
  198. lines = [
  199. (TimeDisplay(0), 1),
  200. (DateDisplay(8), 30),
  201. (ScrollText(16), 20),
  202. (TimeDisplay(24), 10),
  203. (NightDisplay(32), 5)
  204. ]
  205. virtual = viewport(device, width=device.width, height=device.height*len(lines), mode="1")
  206. currentLine = 0
  207. targetLine = 0
  208. regulator = framerate_regulator(30)
  209. nextElem = datetime.now()
  210. try:
  211. while True:
  212. #if len(txt) == 0:
  213. if datetime.now().second != t.second:
  214. t = datetime.now()
  215. i = int(targetLine/8)
  216. line, secs = lines[i]
  217. if t >= nextElem:
  218. targetLine = (targetLine+8) % 32
  219. if sleep == 1:
  220. targetLine = 32
  221. i = int(targetLine/8)
  222. line, secs = lines[i]
  223. print("{} line={} time={}".format(t.strftime('%H:%M:%S'), i, secs))
  224. nextElem = t + timedelta(0,secs)
  225. if i == 2 and len(txt) > 0:
  226. msg = u" +++ ".join(txt)
  227. txt = []
  228. print(msg.encode('utf-8'))
  229. if len(msg) > 0:
  230. msg = list(msg)
  231. for i in range(len(msg)):
  232. if msg[i] in umlauts:
  233. msg[i] = umlauts[msg[i]]
  234. line.setText("".join(msg))
  235. while True:
  236. animate = True
  237. if currentLine == 24 and targetLine < 12:
  238. currentLine = 0
  239. elif currentLine == 0 and targetLine > 12:
  240. currentLine = 24
  241. elif currentLine < targetLine:
  242. currentLine += 1
  243. elif currentLine > targetLine:
  244. currentLine -= 1
  245. else:
  246. animate = False
  247. virtual._position = (0, currentLine)
  248. with regulator:
  249. with canvas(virtual) as draw:
  250. for line, _ in lines:
  251. animate |= line.show(draw, t, currentLine)
  252. if not animate:
  253. break
  254. else:
  255. time.sleep(1.0 - datetime.now().microsecond/1000000.0)
  256. except KeyboardInterrupt:
  257. pass