├── 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 |
--------------------------------------------------------------------------------