├── README.md └── show.py /README.md: -------------------------------------------------------------------------------- 1 | # Dynaframe 2 | A Dynamic Photo and Video Picture Frame script written in Python. It was created to provide a simple way to do not only slideshows on a raspberry pi connected to a monitor, but to also do videos for effects such as cinemagraphs or plotagraphs. The initial version includes control via MQTT or HTTP, so that it can easily be controlled via home autoamtion or tablets/phones/computers remotely. 3 | 4 | I've created a video of the project at: https://www.youtube.com/watch?v=2f92ypMnDEs&feature=youtu.be 5 | 6 | This is my first Python project, so feedback is much appreciated! 7 | -------------------------------------------------------------------------------- /show.py: -------------------------------------------------------------------------------- 1 | import os 2 | import random 3 | import threading 4 | import time 5 | import socket 6 | import sys 7 | # from bluepy.btle import Scanner, DefaultDelegate 8 | import paho.mqtt.client as mqtt 9 | 10 | from http.server import HTTPServer, BaseHTTPRequestHandler 11 | from urllib.parse import urlparse, parse_qs 12 | 13 | 14 | # customize before using! 15 | brokeraddress = "test.mosquitto.org" # you can use this as a test broker, or setup msoquitto on a rpi as an internal broker 16 | mqttclient = "dynaframe1" # must be unique for each frame... 17 | brokerport = 1883 18 | subscriptionname = "jfarro/house/makerspace/display" # this should be a string that is unique and describes where your frame is 19 | 20 | 21 | # initial variables 22 | refresh = False # controls when the frame needs to close aps and start over 23 | 24 | imagePath = "" # path to the current folder of images 25 | webpageEnd = "" # the 'footer' of the webpage 26 | refreshInterval = 30 # number of seconds between images in a slideshow 27 | 28 | # webpageBody is the main template for the http served webpage. This is where you can make that page..prettier 29 | webpageBody = ''' 30 | 31 | Dynamic Screen Config 32 | 53 | 54 | 55 | 56 | ''' 57 | 58 | webpage = webpageBody 59 | 60 | 61 | class SimpleHTTPRequestHandler(BaseHTTPRequestHandler): 62 | 63 | def do_GET(self): 64 | qs = {} 65 | refreshfolders() 66 | path = self.path 67 | # print("Path is: " + path) 68 | qs = parse_qs(path) 69 | 70 | for key, value in qs.items(): 71 | print ("- " + key, value) 72 | 73 | if "/?dir" in qs : 74 | print("Dir is.....! " + qs['/?dir'][0]) 75 | 76 | if qs['/?dir'][0] == "exit" : 77 | os.system("killall -9 feh"); 78 | os.system("killall -9 omxplayer.bin") 79 | global imagePath 80 | imagePath = "" 81 | sys.exit() 82 | 83 | imagePath = qs['/?dir'][0] 84 | 85 | global refresh 86 | refresh = True 87 | os.system("killall -9 omxplayer.bin") 88 | print("HTTPHandler - ImagePath set to: " + imagePath) 89 | 90 | self.send_response(200) 91 | self.end_headers() 92 | self.wfile.write(webpage.encode('UTF-8')) 93 | self.wfile.write(b"


ImagePath is now: " + 94 | imagePath.encode('UTF-8') 95 | + b"") 96 | 97 | 98 | def refreshfolders(): 99 | global webpageEnd 100 | webpageEnd = "" 101 | # add dirs to webpage as links 102 | folders = os.listdir() 103 | for folder in folders: 104 | if os.path.isdir(folder) and ("log" not in folder): 105 | print("folder found: " + folder) 106 | webpageEnd += "" + folder + "

" 107 | global webpage 108 | webpageEnd += "Exit

" 109 | webpage = webpageBody + webpageEnd 110 | 111 | 112 | def getrandomfolder(): 113 | global imagePath 114 | folders = os.listdir() 115 | validfolder = False 116 | while validfolder is False: 117 | imagePath = random.choice(folders) 118 | if os.path.isdir(imagePath) and imagePath != "logs": 119 | validfolder = True 120 | break 121 | 122 | 123 | def MQTTSubscribe(): 124 | client = mqtt.Client(mqttclient) # create new instance 125 | client.connect(brokeraddress,brokerport) # connect to broker 126 | client.subscribe(subscriptionname) # subscribe 127 | client.on_message=on_message 128 | client.on_log=on_log 129 | client.loop_start() 130 | 131 | 132 | def on_log(client, userdata, level, buf): 133 | print("log: ", buf) 134 | 135 | 136 | def on_message(client, userdata, message): 137 | print("message received ", str(message.payload.decode("utf-8"))) 138 | print("message topic=", message.topic) 139 | print("message qos=", message.qos) 140 | print("message retain flag=", message.retain) 141 | global imagePath 142 | imagePath = str(message.payload.decode("utf-8")) 143 | 144 | global refresh 145 | refresh = True 146 | os.system("killall -9 omxplayer.bin"); 147 | 148 | print("Imagepath set to: " + imagePath); 149 | 150 | 151 | getrandomfolder() 152 | print("ImagePath is: " + imagePath) 153 | 154 | 155 | time.sleep(10.0) 156 | # get local machine ip 157 | s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 158 | s.connect(("8.8.8.8", 80)) 159 | ip = s.getsockname()[0] 160 | s.close() 161 | 162 | print("Starting server at: " + ip + ":8000") 163 | httpd = HTTPServer((ip, 8000), SimpleHTTPRequestHandler) 164 | thread = threading.Thread(target=httpd.serve_forever) 165 | thread.daemon = True 166 | thread.start() 167 | 168 | refreshfolders() 169 | 170 | 171 | imageCheck = "" 172 | dirs = os.listdir(imagePath) 173 | 174 | 175 | def refreshPath(): 176 | global dirs 177 | del dirs 178 | dirs = os.listdir(imagePath) 179 | global imageCheck 180 | imageCheck = imagePath 181 | 182 | 183 | 184 | refreshPath() 185 | 186 | 187 | # init...clean up any other running instances 188 | os.system("killall -9 feh") 189 | os.system("killall -9 omxplayer.bin") 190 | 191 | MQTTSubscribe() 192 | 193 | while True: 194 | for file in dirs: 195 | print ("Mainloop: Image Path is: " + imagePath + " and has: " + str(len(imagePath)) + " files.") 196 | file = "./" + imagePath + "/" + file 197 | 198 | if imageCheck != imagePath: 199 | print("imageCheck " + imageCheck) 200 | print("imagePath " + imagePath) 201 | refreshPath() 202 | break 203 | 204 | if imagePath == "": 205 | quit() 206 | 207 | print("File is: " + file) 208 | os.system("killall -9 feh") 209 | os.system("killall -9 omxplayer.bin") 210 | 211 | if file.upper().endswith(".MOV"): 212 | os.system('omxplayer ' + file) 213 | if file.upper().endswith(".MP4"): 214 | os.system('omxplayer ' + file) 215 | if file.upper().endswith(".JPG"): 216 | time.sleep(1.0) 217 | os.system("DISPLAY=:0.0 feh -x " + file + "&") 218 | count = 0 219 | print("Showing: " + file) 220 | print("refresh is: " + str(refresh)) 221 | print("refreshInterval is: " + str(refreshInterval)) 222 | while refresh is False: 223 | time.sleep(1.0) 224 | print("refresh is: " + str(refresh)) 225 | print("refreshInterval is: " + str(refreshInterval)) 226 | count = count + 1 227 | if count > refreshInterval: 228 | break 229 | 230 | refresh = False 231 | --------------------------------------------------------------------------------