DarrenHill

Display Hat Mini Trixie

Nov 11th, 2025
130
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 31.23 KB | Source Code | 0 0
  1. #!/usr/bin/env python3
  2.  
  3. import sys
  4. import datetime
  5. import signal
  6. import math
  7.  
  8. import paho.mqtt.client as mqtt
  9.  
  10. import urllib.request as request
  11. import json
  12.  
  13. from signal import *
  14. from time import sleep
  15. from PIL import Image, ImageDraw, ImageFont
  16. from displayhatmini import DisplayHATMini, ST7789
  17.  
  18. MQTT_SERVER = "removed"
  19. MQTT_PORT = removed
  20. MQTT_TOPIC = "displaypi/data/#"
  21. MQTT_STATUS = "displaypi/state"
  22. MQTT_CONTROL = "displaypi/control"
  23. MQTT_RESPONSE = "displaypi/response"
  24. MQTT_PRESENCE = "displaypi/presence"
  25. MQTT_MONITOR = "monitor/data/#"
  26. MQTT_NEWS = "news/headlines"
  27. MQTT_WEATHER_DAILY = "metweather/daily"
  28. MQTT_WEATHER_CURRENT = "metweather/current"
  29.  
  30.  
  31. # Set these to use authorisation
  32. MQTT_USER = "removed"
  33. MQTT_PASS = "removed"
  34.  
  35. rotation = 180
  36.  
  37. #disp = ST7789(
  38. #    height=240,
  39. #    width=320,
  40. #    rotation=rotation,
  41. #    port=0,
  42. #    cs=1,
  43. #    dc=9,
  44. #    backlight=13,
  45. #    spi_speed_hz=60 * 1000 * 1000,
  46. #    offset_left=0,
  47. #    offset_top=0
  48. #)
  49.  
  50. #disp.begin()
  51.  
  52. WIDTH = DisplayHATMini.WIDTH
  53. HEIGHT = DisplayHATMini.HEIGHT
  54.  
  55. RP0_IP = "removed"
  56. RP1_IP = "removed"
  57. RP2_IP = "removed"
  58.  
  59. font30 = ImageFont.truetype('orbitron.ttf', 30)
  60. font28 = ImageFont.truetype('orbitron.ttf', 28)
  61. font24 = ImageFont.truetype('orbitron.ttf', 24)
  62. font20 = ImageFont.truetype('orbitron.ttf', 20)
  63. font18 = ImageFont.truetype('orbitron.ttf', 18)
  64. font14 = ImageFont.truetype('orbitron.ttf', 14)
  65. clockfont = ImageFont.truetype('dig-m.ttf', 64)
  66. tagfont = ImageFont.truetype('FontAwesome6-Free-Solid.otf', 20)
  67. brandfont = ImageFont.truetype('FontAwesome6-Free-Brands.otf', 20)
  68.  
  69. DISPLAYSCREEN = "clock"
  70. OLDSCREEN = ""
  71. status = "stop"
  72. people = ["removed","removed","removed","removed"]
  73. presence = ["init","init","init","init"]
  74.  
  75. monitorname = ["removed1", "removed2", "removed3", "removed4", "removed5", "removed6", "removed7", "removed8", "removed9", "Internet"]
  76. monitordevice = ["removed1", "removed2", "removed3", "removed4", "removed5", "removed6", "removed7", "removed8", "removed9", "Internet"]
  77. monitorstatus = ["Pending", "Pending", "Pending", "Pending", "Pending", "Pending", "Pending", "Pending", "Pending", "Pending"]
  78.  
  79. piname =   ["removed1", "removed2", "removed3", "removed4", "removed5", "removed6", "removed7", "removed8", "removed9", "removed0"]
  80. pidevice = ["removed1", "removed2", "removed3", "removed4", "removed5", "removed6", "removed7", "removed8", "removed9", "removed0"]
  81. pistatus = ["Pending", "Pending", "Pending", "Pending", "Pending", "Pending", "Pending", "Pending", "Pending", "Pending"]
  82.  
  83. newsptr = 0
  84. newslist = ["", "", "", "", "", "", "", "", "", ""]
  85. newswidth = 22
  86.  
  87. weather = {}
  88. weatherd = {}
  89.  
  90.  
  91. def ordinal_suffix(day):
  92.     if 3 < day < 21 or 23 < day < 31:
  93.         return 'th'
  94.     else:
  95.         return {1: 'st', 2: 'nd', 3: 'rd'}[day % 10]
  96.  
  97. def draw_centred_text(image, text, ypos, font, r, g, b):
  98.     indent = int((WIDTH - int(font.getlength(text)))/2)
  99.     draw = ImageDraw.Draw(image)
  100.     bbox = draw.textbbox((0,0), text, font=font)
  101.     width = bbox[2] - bbox[0]
  102.     height = bbox[3] - bbox[1]
  103.     textimage = Image.new('RGBA', (width, height), (0, 0, 0, 0))
  104.     textdraw = ImageDraw.Draw(textimage)
  105.     textdraw.text((0, 0), text, font=font, fill=(r, g, b))
  106.     rotated = textimage.rotate(0, expand=1)
  107.     position = tuple((indent, ypos))
  108.     image.paste(rotated, position, rotated)
  109.     return
  110.  
  111. def draw_text(image, text, xpos, ypos, font, r, g, b):
  112.     draw = ImageDraw.Draw(image)
  113.     bbox = draw.textbbox((0,0), text, font=font)
  114.     width = bbox[2] - bbox[0]
  115.     height = bbox[3] - bbox[1]
  116.     textimage = Image.new('RGBA', (width, height), (0, 0, 0, 0))
  117.     textdraw = ImageDraw.Draw(textimage)
  118.     textdraw.text((0, 0), text, font=font, fill=(r, g, b))
  119.     rotated = textimage.rotate(0, expand=1)
  120.     position = tuple((xpos, ypos))
  121.     image.paste(rotated, position, rotated)
  122.     return
  123.  
  124. def clear_display():
  125.     global img, draw, disp, WIDTH, HEIGHT
  126.     img = Image.new('RGB', (WIDTH, HEIGHT), color=(0, 0, 0))
  127.     draw = ImageDraw.Draw(img)
  128.     return
  129.  
  130. def button_callback(pin):
  131.     global DISPLAYSCREEN, RP0_IP, RP1_IP, RP2_IP, newsptr, newslist, newswidth, rotation
  132.  
  133.     if rotation == 0:
  134.         btn_TL=display_hat.BUTTON_Y
  135.         btn_TR=display_hat.BUTTON_B
  136.         btn_BL=display_hat.BUTTON_X
  137.         btn_BR=display_hat.BUTTON_A
  138.     elif rotation == 180:
  139.         btn_TL=display_hat.BUTTON_A
  140.         btn_TR=display_hat.BUTTON_X
  141.         btn_BL=display_hat.BUTTON_B
  142.         btn_BR=display_hat.BUTTON_Y
  143.  
  144.     if not display_hat.read_button(pin):
  145.         return
  146.  
  147.     if DISPLAYSCREEN == "clock":
  148.         if pin == btn_TL:
  149.             DISPLAYSCREEN = "weather"
  150.             return
  151.         elif pin == btn_TR:
  152.             DISPLAYSCREEN = "clock_2"
  153.             return
  154.         elif pin == btn_BL:
  155.             DISPLAYSCREEN = "radio_0"
  156.             return
  157.         elif pin == btn_BR:
  158.             DISPLAYSCREEN = "blank"
  159.             return
  160.         return
  161.  
  162.     if DISPLAYSCREEN == "clock_2":
  163.         if pin == btn_TL:
  164.             DISPLAYSCREEN = "news"
  165.             return
  166.         elif pin == btn_TR:
  167.             DISPLAYSCREEN = "clock"
  168.             return
  169.         elif pin == btn_BL:
  170.             DISPLAYSCREEN = "people"
  171.             return
  172.         elif pin == btn_BR:
  173.             DISPLAYSCREEN = "monitor"
  174.             return
  175.         return
  176.  
  177.     if DISPLAYSCREEN == "weather":
  178.         if pin == btn_TL:
  179.             DISPLAYSCREEN = "clock"
  180.         elif pin == btn_BL:
  181.             DISPLAYSCREEN = "weatherd"
  182.             return
  183.         return
  184.  
  185.     if DISPLAYSCREEN == "weatherd":
  186.         if pin == btn_TL:
  187.             DISPLAYSCREEN = "clock"
  188.         elif pin == btn_BL:
  189.             DISPLAYSCREEN = "weather"
  190.             return
  191.         return
  192.  
  193.     if DISPLAYSCREEN == "news":
  194.         if pin == btn_TL:
  195.             DISPLAYSCREEN = "clock_2"
  196.             return
  197.         elif pin == btn_BL:
  198.             newswidth = newswidth + 1
  199.             if newswidth > 26:
  200.                 newswidth = 18
  201.             DISPLAYSCREEN = "news_redraw"
  202.             return
  203.         elif pin == btn_TR:
  204.             newsptr = newsptr -1
  205.             if newsptr < 0:
  206.                 newsptr = len(newslist) - 1
  207.             DISPLAYSCREEN = "news_redraw"
  208.             return
  209.         elif pin == btn_BR:
  210.             newsptr = newsptr + 1
  211.             if newsptr >= len(newslist):
  212.                 newsptr = 0
  213.             DISPLAYSCREEN = "news_redraw"
  214.             return
  215.         return
  216.  
  217.     if DISPLAYSCREEN == "radio_0":
  218.         if pin == btn_TL:
  219.             DISPLAYSCREEN = "clock"
  220.             return
  221.         elif pin == btn_BL:
  222.             DISPLAYSCREEN = "radio_1"
  223.             return
  224.         elif pin == btn_TR:
  225.             request.urlopen('http://' + RP0_IP + '/api/v1/commands/?cmd=toggle')
  226.             return
  227.         elif pin == btn_BR:
  228.             request.urlopen('http://' + RP0_IP + '/api/v1/commands/?cmd=next')
  229.             return
  230.         return
  231.  
  232.     if DISPLAYSCREEN == "radio_1":
  233.         if pin == btn_TL:
  234.             DISPLAYSCREEN = "clock"
  235.             return
  236.         elif pin == btn_BL:
  237.             DISPLAYSCREEN = "radio_2"
  238.             return
  239.         elif pin == btn_TR:
  240.             request.urlopen('http://' + RP1_IP + '/api/v1/commands/?cmd=toggle')
  241.             return
  242.         elif pin == btn_BR:
  243.             request.urlopen('http://' + RP1_IP + '/api/v1/commands/?cmd=next')
  244.             return
  245.         return
  246.  
  247.     if DISPLAYSCREEN == "radio_2":
  248.         if pin == btn_TL:
  249.             DISPLAYSCREEN = "clock"
  250.             return
  251.         elif pin == btn_BL:
  252.             DISPLAYSCREEN = "radio_0"
  253.             return
  254.         elif pin == btn_TR:
  255.             request.urlopen('http://' + RP2_IP + '/api/v1/commands/?cmd=toggle')
  256.             return
  257.         elif pin == btn_BR:
  258.             request.urlopen('http://' + RP2_IP + '/api/v1/commands/?cmd=next')
  259.             return
  260.         return
  261.  
  262.     if DISPLAYSCREEN == "people":
  263.         if pin == btn_TL:
  264.             DISPLAYSCREEN = "clock_2"
  265.             return
  266.         elif pin == btn_BL:
  267.             DISPLAYSCREEN = "people_refresh"
  268.             return
  269.         return
  270.  
  271.     if DISPLAYSCREEN == "monitor":
  272.         if pin == btn_TL:
  273.             DISPLAYSCREEN = "clock_2"
  274.             return
  275. #        elif pin == btn_BL:
  276. #            return
  277.         elif pin == btn_TR:
  278.             DISPLAYSCREEN = "monitor_2"
  279.             return
  280. #        elif pin == btn_BR:
  281. #            return
  282.         return
  283.  
  284.  
  285.     if DISPLAYSCREEN == "monitor_2":
  286.         if pin == btn_TL:
  287.             DISPLAYSCREEN = "clock_2"
  288.             return
  289. #        elif pin == btn_BL:
  290. #            return
  291.         elif pin == btn_TR:
  292.             DISPLAYSCREEN = "monitor"
  293.             return
  294. #        elif pin == btn_BR:
  295. #            return
  296.         return
  297.  
  298.     if DISPLAYSCREEN == "blank":
  299.         DISPLAYSCREEN = "clock"
  300.         return
  301.  
  302.     return
  303.  
  304. def draw_tags():
  305.     global DISPLAYSCREEN, status
  306.  
  307.     if DISPLAYSCREEN == "clock":
  308.         draw_tag(img, u"\uf743", "Y", font=tagfont)  # Weather
  309.         draw_tag(img, u"\uf13a", "B", font=tagfont)  # Circle Chevron Down
  310.         draw_tag(img, u"\uf001", "X", font=tagfont)  # Radio
  311.         draw_tag(img, u"\uf00d", "A", font=tagfont)  # Blank
  312.         return
  313.  
  314.     if DISPLAYSCREEN == "clock_2":
  315.         draw_tag(img, u"\uf1ea", "Y", font=tagfont)  # News
  316.         draw_tag(img, u"\uf139", "B", font=tagfont)  # Circle Chevron Up
  317.         draw_tag(img, u"\uf0c0", "X", font=tagfont)  # People
  318.         draw_tag(img, u"\uf06e", "A", font=tagfont)  # Eye
  319.         return
  320.  
  321.     elif DISPLAYSCREEN == "weather":
  322.         draw_tag(img, u"\uf017", "Y", font=tagfont)  # Clock
  323.         draw_tag(img, u"\uf185", "X", font=tagfont)  # Sun (Weatherd)
  324.         return
  325.  
  326.     elif DISPLAYSCREEN == "weatherd":
  327.         draw_tag(img, u"\uf017", "Y", font=tagfont)  # Clock
  328.         draw_tag(img, u"\uf743", "X", font=tagfont)  # Weather
  329.         return
  330.  
  331.     elif DISPLAYSCREEN == "news":
  332.         draw_tag(img, u"\uf017", "Y", font=tagfont)  # Clock
  333.         draw_tag(img, u"\uf139", "B", font=tagfont)  # Circle Chevron Up
  334.         draw_tag(img, u"\uf035", "X", font=tagfont)  # Text Width
  335.         draw_tag(img, u"\uf13a", "A", font=tagfont)  # Circle Chevron Down
  336.         return
  337.  
  338.     elif DISPLAYSCREEN == "people":
  339.         draw_tag(img, u"\uf017", "Y", font=tagfont)  # Clock
  340.         draw_tag(img, u"\uf2f1", "X", font=tagfont)  # Refresh (rotate arrows)
  341.         return
  342.  
  343.     elif DISPLAYSCREEN == "monitor":
  344.         draw_tag(img, u"\uf017", "Y", font=tagfont)  # Clock
  345.         draw_tag(img, u"\uf7bb", "B", font=brandfont)  # Robot (RasPi doesn't work!)
  346.         return
  347.  
  348.     elif DISPLAYSCREEN == "monitor_2":
  349.         draw_tag(img, u"\uf017", "Y", font=tagfont)  # Clock
  350.         draw_tag(img, u"\uf06e", "B", font=tagfont)  # Eye
  351.         return
  352.  
  353.     elif DISPLAYSCREEN == "radio_0":
  354.         draw_tag(img, u"\uf017", "Y", font=tagfont)  # Clock
  355.         if status == "play":
  356.             draw_tag(img, u"\uf04c", "B", font=tagfont)  # Pause
  357.         else:
  358.             draw_tag(img, u"\uf04b", "B", font=tagfont)  # Play
  359.         draw_tag(img, u"\u0031", "X", font=tagfont)  # One
  360.         draw_tag(img, u"\uf04e", "A", font=tagfont)  # Forward
  361.         return
  362.  
  363.     elif DISPLAYSCREEN == "radio_1":
  364.         draw_tag(img, u"\uf017", "Y", font=tagfont)  # Clock
  365.         if status == "play":
  366.             draw_tag(img, u"\uf04c", "B", font=tagfont)  # Pause
  367.         else:
  368.             draw_tag(img, u"\uf04b", "B", font=tagfont)  # Play
  369.         draw_tag(img, u"\u0032", "X", font=tagfont)  # Two
  370.         draw_tag(img, u"\uf04e", "A", font=tagfont)  # Forward
  371.         return
  372.  
  373.     elif DISPLAYSCREEN == "radio_2":
  374.         draw_tag(img, u"\uf017", "Y", font=tagfont)  # Clock
  375.         if status == "play":
  376.             draw_tag(img, u"\uf04c", "B", font=tagfont)  # Pause
  377.         else:
  378.             draw_tag(img, u"\uf04b", "B", font=tagfont)  # Play
  379.         draw_tag(img, u"\u0030", "X", font=tagfont)  # Zero
  380.         draw_tag(img, u"\uf04e", "A", font=tagfont)  # Forward
  381.         return
  382.  
  383.     return
  384.  
  385. def draw_tag(image, text, btn, font):
  386.  
  387.     if btn == "A":
  388.         position = tuple((295, 160))
  389.     elif btn == "B":
  390.         position = tuple((295, 65))
  391.     elif btn == "X":
  392.         position = tuple((5, 160))
  393.     elif btn == "Y":
  394.         position = tuple((5, 65))
  395.  
  396.     draw = ImageDraw.Draw(image)
  397.     bbox = draw.textbbox((0,0), text, font=font)
  398.     width = bbox[2] - bbox[0]
  399.     height = bbox[3] - bbox[1]
  400.     textimage = Image.new('RGBA', (width, height), (0, 0, 0, 0))
  401.     textdraw = ImageDraw.Draw(textimage)
  402.     textdraw.text((0, 0), text, font=font, fill=(255, 255, 255))
  403.     rotated = textimage.rotate(0, expand=1)
  404.     image.paste(rotated, position, rotated)
  405.     return
  406.  
  407. def read_radio(ip):
  408.  
  409.     global DISPLAYSCREEN, img, status
  410.  
  411.     try:
  412.         with request.urlopen('http://' + ip + '/api/v1/getState') as response:
  413.             source = response.read()
  414.             data = json.loads(source)
  415.         status = data['status']
  416.         title = data['title'].strip()
  417.         uri = data['uri']
  418.     except:
  419.         status = "offline"
  420.         title = ""
  421.         uri = ""
  422.         station = ""
  423.  
  424.     if status == "stop":
  425.         song = "Idle"
  426.         artist = ""
  427.  
  428.     elif status == "offline":
  429.         song = "Offline"
  430.         artist = ""
  431.  
  432.     elif status == "play" and len(title) > 3:
  433.         try:
  434.             song, artist = title.split(' - ',2)
  435.         except:
  436.             song = ""
  437.             artist = ""
  438.     else:
  439.         song = "Unknown"
  440.         artist = "Unknown"
  441.  
  442.     if uri != "":
  443.         if uri.count("absolute80s") > 0:
  444.             station = "Absolute 80s"
  445.         elif uri.count("absoluteclassicrock") > 0:
  446.             station = "Absolute Classic Rock"
  447.         elif uri.count("absoluteradio") > 0:
  448.             station = "Absolute Radio"
  449.         elif uri.count("absolutecountry") > 0:
  450.             station = "Absolute Country"
  451.         elif uri.count("Heart80s") > 0:
  452.             station = "Heart 80s"
  453.         else:
  454.             station = "Internet Radio"
  455.     else:
  456.         station = ""
  457.  
  458.     if len(song) < 17:
  459.         draw_centred_text(img, song, 65, font20, 255, 255, 255)
  460.     else:
  461.         if(song.count(" ")) > 0:
  462.             song = song.strip()[:32]
  463.             song1 = ""
  464.             song2 = ""
  465.             songspace = True
  466.             songlist = song.split()
  467.             songlen = len(songlist)
  468.             count = 0
  469.  
  470.             while count < songlen:
  471.                 next = songlist[count]
  472.                 if songspace == True and ((len(next) + len(song1)) < 16):
  473.                     song1 = song1 + " " + songlist[count]
  474.                     song1 = song1.strip()
  475.                     count = count + 1
  476.                 else:
  477.                     songspace = False
  478.                     song2 = song2 + " " + songlist[count]
  479.                     song2 = song2.strip()
  480.                     count = count + 1
  481.             draw_centred_text(img, song1, 50, font20, 255, 255, 255)
  482.             draw_centred_text(img, song2, 80, font20, 255, 255, 255)
  483.         else:
  484.             div = math.floor(len(song)/2)
  485.             draw_centred_text(img, song[:16], 50, font20, 255, 255, 255)
  486.             draw_centred_text(img, song[16:32], 80, font20, 255, 255, 255)
  487.  
  488.  
  489.     if len(artist) < 17:
  490.         draw_centred_text(img, artist, 135, font20, 255, 255, 255)
  491.     else:
  492.         if(artist.count(" ")) > 0:
  493.             artist = artist.strip()[:32]
  494.             art1 = ""
  495.             art2 = ""
  496.             artspace = True
  497.             artlist = artist.split()
  498.             artlen = len(artlist)
  499.             count = 0
  500.             while count < artlen:
  501.                 next = artlist[count]
  502.                 if artspace == True and ((len(next) + len(art1)) < 16):
  503.                     art1 = art1 + " " + artlist[count]
  504.                     art1 = art1.strip()
  505.                     count = count + 1
  506.                 else:
  507.                     artspace = False
  508.                     art2 = art2 + " " + artlist[count]
  509.                     art2 = art2.strip()
  510.                     count = count + 1
  511.             draw_centred_text(img, art1, 120, font20, 255, 255, 255)
  512.             draw_centred_text(img, art2, 150, font20, 255, 255, 255)
  513.         else:
  514.             div = math.floor(len(artist)/2)
  515.             draw_centred_text(img, artist[:16], 120, font20, 255, 255, 255)
  516.             draw_centred_text(img, artist[16:32], 150, font20, 255, 255, 255)
  517.  
  518.     draw_centred_text(img, station, 190, font20, 255, 0, 255)
  519.     return
  520.  
  521. def show_news():
  522.     global newsptr, newslist, newswidth, img
  523.     draw_centred_text(img, "News - " + str(newsptr + 1), 10, font24, 255, 0, 0)
  524.     news_lines = ["", "", "", "", "", ""]
  525.     headline = newslist[newsptr]
  526.     headsplit = headline.split()
  527.     headlen = len(headsplit)
  528.     line = 0
  529.  
  530.     x = 0
  531.     if len(headsplit) > 1:
  532.         while x < len(headsplit):
  533.             if ( len(headsplit[x]) + len(news_lines[line]) ) < newswidth:
  534.                news_lines[line] = (news_lines[line] + " " +  headsplit[x]).strip()
  535.                x = x + 1
  536.             elif len(headsplit[x]) > (newswidth - 1):
  537.                 if line < len(news_lines):
  538.                     line = line + 1
  539.                     news_lines[line] = headsplit[x]
  540.                 x = x + 1
  541.             else:
  542.                 line = line + 1
  543.  
  544.     x = 0
  545.     while x < len(news_lines):
  546.         draw_centred_text(img, news_lines[x], (80 + (x * 20)), font18, 255, 255, 255)
  547.         x = x + 1
  548.  
  549.     draw_centred_text(img, str(newswidth), 190, font14, 255, 0, 255)
  550.     return
  551.  
  552. def show_weather(): # the current one
  553.     global weather
  554.     draw_centred_text(img, "Current Weather", 10, font24, 255, 0, 0)
  555.     draw_centred_text(img, str(weather['state']), 60, font20, 255, 255, 255)
  556.     draw_centred_text(img, "Temp - " + str(round(weather['temperature'],1)) + " (" + str(round(weather['feels_like'],1)) + ") C", 90, font20, 255, 255, 255)
  557.     draw_centred_text(img, "Wind - " + str(round(weather['wind_speed'],1)) + " m/s ("+ str(weather['wind_dir']) + ")", 120, font20, 255, 255, 255)
  558.     draw_centred_text(img, "Hum - " + str(round(weather['humidity'])) + " %", 150, font20, 255, 255, 255)
  559.     draw_centred_text(img, "UV - " + str(weather['uv_index']), 180, font20, 255, 255, 255)
  560.     draw_centred_text(img, "Rain - " + str(round(weather['prob_precipitation'])) + " % / " +  str(weather['precipitation_rate']), 210, font20, 255, 255, 255)
  561.  
  562.     return
  563.  
  564. def show_weatherd(): # the daily summary
  565.     global weatherd
  566.     draw_centred_text(img, "Daily Weather", 10, font24, 255, 0, 0)
  567.     draw_centred_text(img, str(weatherd['weather']), 60, font20, 255, 255, 255)
  568.     draw_centred_text(img, "Temp - " + str(weatherd['temperature']) + " (" + str(weatherd['feels_like']) + ") C", 90, font20, 255, 255, 255)
  569.     draw_centred_text(img, "Wind - " + str(weatherd['wind_speed']) + " m/s ("+ str(weatherd['wind_dir']) + ")", 120, font20, 255, 255, 255)
  570.     draw_centred_text(img, "Hum - " + str(weatherd['humidity']) + " %", 150, font20, 255, 255, 255)
  571.     draw_centred_text(img, "UV - " + str(weatherd['uv_index']), 180, font20, 255, 255, 255)
  572.     draw_centred_text(img, "Rain - " + str(weatherd['prob_precipitation']), 210, font20, 255, 255, 255)
  573.     return
  574.  
  575. def show_monitor():
  576.     global monitordevice, monitorstatus, monitorname
  577.     draw_centred_text(img, "Monitor", 10, font24, 255, 255, 255)
  578.     x=0
  579.     col1 = 40
  580.     col2 = 170
  581.     width = 10
  582.  
  583.     while x < 5:
  584.         if monitorstatus[x] == "Online":
  585.             draw_text(img, monitorname[x].center(width), col1, 80 + (x * 20), font20, 0, 255, 0)
  586.         elif monitorstatus[x] == "Offline":
  587.             draw_text(img, monitorname[x].center(width), col1, 80 + (x * 20), font20, 255, 0, 0)
  588.         elif monitorstatus[x] == "Play":
  589.             draw_text(img, monitorname[x].center(width), col1, 80 + (x * 20), font20, 255, 0, 255)
  590.         elif monitorstatus[x] == "Idle":
  591.             draw_text(img, monitorname[x].center(width), col1, 80 + (x * 20), font20, 0, 0, 255)
  592.         x = x +1
  593.  
  594.     x=5
  595.     while x < 10:
  596.         if monitorstatus[x] == "Online":
  597.             draw_text(img, monitorname[x].center(width), col2, 80 + ((x - 5) * 20), font20, 0, 255, 0)
  598.         elif monitorstatus[x] == "Offline":
  599.             draw_text(img, monitorname[x].center(width), col2, 80 + ((x - 5) * 20), font20, 255, 0, 0)
  600.         elif monitorstatus[x] == "Play":
  601.             draw_text(img, monitorname[x].center(width), col2, 80 + ((x - 5) * 20), font20, 255, 0, 255)
  602.         elif monitorstatus[x] == "Idle":
  603.             draw_text(img, monitorname[x].center(width), col2, 80 + ((x - 5) * 20), font20, 0, 0, 255)
  604.         x = x +1
  605.  
  606.     return
  607.  
  608. def show_monitor_2():
  609.     global pidevice, pistatus, piname
  610.     draw_centred_text(img, "Pi Monitor", 10, font24, 255, 255, 255)
  611.     x=0
  612.     col1 = 40
  613.     col2 = 170
  614.     width = 10
  615.  
  616.     while x < 5:
  617.         if pistatus[x] == "Online":
  618.             draw_text(img, piname[x].center(width), col1, 80 + (x * 20), font20, 0, 255, 0)
  619.         elif pistatus[x] == "Offline":
  620.             draw_text(img, piname[x].center(width), col1, 80 + (x * 20), font20, 255, 0, 0)
  621.         x = x +1
  622.  
  623.     x=5
  624.     while x < 10:
  625.         if pistatus[x] == "Online":
  626.             draw_text(img, piname[x].center(width), col2, 80 + ((x - 5) * 20), font20, 0, 255, 0)
  627.         elif pistatus[x] == "Offline":
  628.             draw_text(img, piname[x].center(width), col2, 80 + ((x - 5) * 20), font20, 255, 0, 0)
  629.         x = x +1
  630.  
  631.     return
  632.  
  633.  
  634. def clean(*args):
  635.     clear_display()
  636.     display_hat.set_backlight(False)
  637.     display_hat.display(img)
  638.     sys.exit(0)
  639.  
  640. def on_connect(client, userdata, flags, rc):
  641.     if rc == 0:
  642.       DISPLAYSCREEN = "clock"
  643.       ret = client.publish(MQTT_RESPONSE,"MQTT Connected")
  644.       ret = client.publish(MQTT_STATUS,"clock", qos=0, retain = True)
  645.       client.subscribe(MQTT_TOPIC)
  646.       client.subscribe(MQTT_CONTROL)
  647.       client.subscribe(MQTT_PRESENCE)
  648.       client.subscribe(MQTT_NEWS)
  649.       client.subscribe(MQTT_WEATHER_DAILY)
  650.       client.subscribe(MQTT_WEATHER_CURRENT)
  651.       client.subscribe(MQTT_MONITOR)
  652.       display_hat.set_led(0, 0, 0)
  653.     else:
  654.       display_hat.set_led(0.05, 0, 0)
  655.     return
  656.  
  657.  
  658. def on_disconnect(client, userdata, rc):
  659.     display_hat.set_led(0.05, 0, 0)
  660.     return
  661.  
  662. def on_subscribe(client, userdata, mid, granted_qos):
  663.     ret = client.publish(MQTT_RESPONSE,"MQTT Subscribed")
  664.     return
  665.  
  666. def on_message(client, userdata, msg):
  667.     global DISPLAYSCREEN, people, presence, newslist, RP0_STATION, RP1_STATION, RP2_STATION, weather, weatherd
  668.     global monitordevice, monitorstatus, pidevice, pistatus
  669.     screenlist = ["clock", "clock_2", "weather", "weatherd", "news", "people", "radio_0", "radio_1", "radio_2", "monitor", "monitor_2", "blank"]
  670.  
  671.     if msg.topic == MQTT_CONTROL:
  672.  
  673.         data = msg.payload.decode("utf-8").lower()
  674.         if data in screenlist:
  675.             ret = client.publish(MQTT_RESPONSE, data + " displayed", qos=0, retain = True)
  676.             DISPLAYSCREEN = data
  677.             return
  678.         else:
  679.             ret = client.publish(MQTT_RESPONSE, "Unknown screen - " + data, qos=0, retain = True)
  680.         return
  681.  
  682.     if msg.topic.find("monitor/data/") == 0 and msg.topic != "monitor/data/control":
  683.  
  684.         jdata = json.loads(msg.payload.decode('utf-8'))
  685.         device = jdata['device']
  686.         status = jdata['status']
  687.         if device in monitordevice:
  688.             x = monitordevice.index(device)
  689.             monitorstatus[x] = status
  690.         if device in pidevice:
  691.             x = pidevice.index(device)
  692.             pistatus[x] = status
  693.         return
  694.  
  695.     if msg.topic == MQTT_PRESENCE:
  696.         jdata = json.loads(msg.payload.decode('utf-8'))
  697.         person = jdata['person'].lower()
  698.         status = jdata['status'].lower()
  699.  
  700.         try:
  701.             loc = people.index(person)
  702.             presence[loc] = status
  703.         except:
  704.             ret = client.publish(MQTT_RESPONSE,"Person not found - " + person)
  705.             print("Person not found - " + person)
  706.         return
  707.  
  708.     if msg.topic == MQTT_NEWS:
  709.         newslist = json.loads(msg.payload.decode('utf-8'))
  710.         return
  711.  
  712.     if msg.topic == MQTT_WEATHER_CURRENT:
  713.         weather = json.loads(msg.payload.decode('utf-8'))
  714.         return
  715.  
  716.     if msg.topic == msg.topic == MQTT_WEATHER_DAILY:
  717.         weatherd = json.loads(msg.payload.decode('utf-8'))
  718.         return
  719.  
  720.     return
  721.  
  722.  
  723. for sig in (SIGABRT, SIGILL, SIGINT, SIGSEGV, SIGTERM):
  724.     signal(sig, clean)
  725.  
  726. display_hat = DisplayHATMini(buffer=None, backlight_pwm=True)
  727. display_hat.on_button_pressed(button_callback)
  728.  
  729. client = mqtt.Client()
  730. client.on_connect = on_connect
  731. client.on_disconnect = on_disconnect
  732. client.on_message = on_message
  733. client.on_subscribe = on_subscribe
  734.  
  735. if MQTT_USER is not None and MQTT_PASS is not None:
  736.     client.username_pw_set(username=MQTT_USER, password=MQTT_PASS)
  737.  
  738. client.connect(MQTT_SERVER, MQTT_PORT, 60)
  739. client.loop_start()
  740.  
  741. while True:
  742.     while DISPLAYSCREEN == "clock":
  743.         clear_display()
  744.         display_hat.set_backlight(True)
  745.         x = datetime.datetime.now()
  746.         today = datetime.date.today()
  747.         date_string = today.strftime('%-d{suffix} %B')
  748.         if (x.second / 2) == int(x.second / 2):
  749.             draw_centred_text(img, x.strftime("%H:%M:%S"), 48, clockfont, 255, 255, 255)
  750.         else:
  751.             draw_centred_text(img, x.strftime("%H %M %S"), 48, clockfont, 255, 255, 255)
  752.         draw_centred_text(img, x.strftime('%A'), 144, font28, 255, 255, 255)
  753.         draw_centred_text(img, date_string.format(suffix=ordinal_suffix(today.day)), 192, font28, 255, 255, 255)
  754.         draw_tags()
  755.         display_hat.display(img)
  756.         if OLDSCREEN != "clock":
  757.             ret = client.publish(MQTT_STATUS,"clock", qos=0, retain = True)
  758.             OLDSCREEN = "clock"
  759.         sleep(0.1)
  760.  
  761.     while DISPLAYSCREEN == "clock_2":
  762.         clear_display()
  763.         display_hat.set_backlight(True)
  764.         x = datetime.datetime.now()
  765.         today = datetime.date.today()
  766.         date_string = today.strftime('%-d{suffix} %B')
  767.         if (x.second / 2) == int(x.second / 2):
  768.             draw_centred_text(img, x.strftime("%H:%M:%S"), 48, clockfont, 255, 255, 255)
  769.         else:
  770.             draw_centred_text(img, x.strftime("%H %M %S"), 48, clockfont, 255, 255, 255)
  771.         draw_centred_text(img, x.strftime('%A'), 144, font28, 255, 255, 255)
  772.         draw_centred_text(img, date_string.format(suffix=ordinal_suffix(today.day)), 192, font28, 255, 255, 255)
  773.         draw_tags()
  774.         display_hat.display(img)
  775.         if OLDSCREEN != "clock_2":
  776.             ret = client.publish(MQTT_STATUS,"clock_2", qos=0, retain = True)
  777.             OLDSCREEN = "clock_2"
  778.         sleep(0.1)
  779.  
  780.     while DISPLAYSCREEN == "people":
  781.         clear_display()
  782.         display_hat.set_backlight(True)
  783.         draw_tags()
  784.  
  785.         offset = 0
  786.         for x in people:
  787.             loc = people.index(x)
  788.             if presence[loc] == "home":
  789.                 draw_centred_text(img, x.capitalize(), ((loc * 40) + 50), font30, 0, 255, 0)
  790.             elif presence[loc] == "not_home":
  791.                 draw_centred_text(img, x.capitalize(), ((loc * 40) + 50), font30, 0, 0, 255)
  792.             else:
  793.                 draw_centred_text(img, x.capitalize(), ((loc * 40) + 50), font30, 255, 0, 0)
  794.  
  795.         display_hat.display(img)
  796.         if OLDSCREEN != "people":
  797.             ret = client.publish(MQTT_STATUS,"people", qos=0, retain = True)
  798.             OLDSCREEN = "people"
  799.         sleep(0.1)
  800.  
  801.     while DISPLAYSCREEN =="people_refresh":
  802.         clear_display()
  803.         display_hat.display(img)
  804.         if OLDSCREEN != "people_refresh":
  805.             ret = client.publish(MQTT_STATUS,"people_refresh", qos=0, retain = True)
  806.             OLDSCREEN = "people_refresh"
  807.         DISPLAYSCREEN = "people"
  808.  
  809.     while DISPLAYSCREEN == "radio_0":
  810.         clear_display()
  811.         display_hat.set_backlight(True)
  812.         draw_centred_text(img, "Radio Pi Zero", 10, font24, 255, 0, 0)
  813.         read_radio(RP0_IP)
  814.         draw_tags()
  815.         display_hat.display(img)
  816.         if OLDSCREEN != "radio_0":
  817.             ret = client.publish(MQTT_STATUS,"radio_0", qos=0, retain = True)
  818.             OLDSCREEN = "radio_0"
  819.         sleep(0.1)
  820.  
  821.     while DISPLAYSCREEN == "radio_1":
  822.         clear_display()
  823.         display_hat.set_backlight(True)
  824.         draw_centred_text(img, "Radio Pi One", 10, font24, 0, 255, 0)
  825.         read_radio(RP1_IP)
  826.         draw_tags()
  827.         display_hat.display(img)
  828.         if OLDSCREEN != "radio_1":
  829.             ret = client.publish(MQTT_STATUS,"radio_1", qos=0, retain = True)
  830.             OLDSCREEN = "radio_1"
  831.         sleep(0.1)
  832.  
  833.     while DISPLAYSCREEN == "radio_2":
  834.         clear_display()
  835.         display_hat.set_backlight(True)
  836.         draw_centred_text(img, "Radio Pi Two", 10, font24, 0, 0, 255)
  837.         read_radio(RP2_IP)
  838.         draw_tags()
  839.         display_hat.display(img)
  840.         if OLDSCREEN != "radio_2":
  841.             ret = client.publish(MQTT_STATUS,"radio_2", qos=0, retain = True)
  842.             OLDSCREEN = "radio_2"
  843.         sleep(0.1)
  844.  
  845.     while DISPLAYSCREEN == "weather":
  846.         clear_display()
  847.         display_hat.set_backlight(True)
  848.         show_weather()
  849.         draw_tags()
  850.         display_hat.display(img)
  851.         if OLDSCREEN != "weather":
  852.             ret = client.publish(MQTT_STATUS,"weather", qos=0, retain = True)
  853.             OLDSCREEN = "weather"
  854.         sleep(0.1)
  855.  
  856.     while DISPLAYSCREEN =="weatherd":
  857.         clear_display()
  858.         display_hat.set_backlight(True)
  859.         show_weatherd()
  860.         draw_tags()
  861.         display_hat.display(img)
  862.         if OLDSCREEN != "weatherd":
  863.             ret = client.publish(MQTT_STATUS,"weatherd", qos=0, retain = True)
  864.             OLDSCREEN = "weatherd"
  865.         sleep(0.1)
  866.  
  867.     while DISPLAYSCREEN == "news":
  868.         clear_display()
  869.         display_hat.set_backlight(True)
  870.         show_news()
  871.         draw_tags()
  872.         display_hat.display(img)
  873.         if OLDSCREEN != "news":
  874.             ret = client.publish(MQTT_STATUS,"news", qos=0, retain = True)
  875.             OLDSCREEN = "news"
  876.         sleep(0.1)
  877.  
  878.     while DISPLAYSCREEN =="news_redraw":
  879.         clear_display()
  880.         display_hat.display(img)
  881.         if OLDSCREEN != "news_redraw":
  882.             ret = client.publish(MQTT_STATUS,"news_redraw", qos=0, retain = True)
  883.             OLDSCREEN = "news_redraw"
  884.         DISPLAYSCREEN = "news"
  885.  
  886.     while DISPLAYSCREEN == "monitor":
  887.         clear_display()
  888.         display_hat.set_backlight(True)
  889.         show_monitor()
  890.         draw_tags()
  891.         display_hat.display(img)
  892.         if OLDSCREEN != "monitor":
  893.             ret = client.publish(MQTT_STATUS,"monitor", qos=0, retain = True)
  894.             OLDSCREEN = "monitor"
  895.         sleep(0.1)
  896.  
  897.     while DISPLAYSCREEN == "monitor_2":
  898.         clear_display()
  899.         display_hat.set_backlight(True)
  900.         show_monitor_2()
  901.         draw_tags()
  902.         display_hat.display(img)
  903.         if OLDSCREEN != "monitor_2":
  904.             ret = client.publish(MQTT_STATUS,"monitor_2", qos=0, retain = True)
  905.             OLDSCREEN = "monitor_2"
  906.         sleep(0.1)
  907.  
  908.     while DISPLAYSCREEN =="blank":
  909.         clear_display()
  910.         display_hat.set_backlight(False)
  911.         display_hat.display(img)
  912.         if OLDSCREEN != "blank":
  913.             ret = client.publish(MQTT_STATUS,"blank", qos=0, retain = True)
  914.             OLDSCREEN = "blank"
  915.         sleep(0.1)
  916.  
  917.     sleep(0.1)
  918.  
Tags: python
Advertisement
Add Comment
Please, Sign In to add comment