images, gifs and messages added to frontend

This commit is contained in:
Neythen 2021-10-11 20:16:04 +01:00
parent acd46c0aef
commit 5beb927bf0
11 changed files with 237 additions and 147 deletions

View File

@ -1 +1 @@
{"speed": "medium", "animation": "continuous", "title": true, "pause": "", "images": ["open.gif"]} {"speed": "medium", "animation": "continuous", "title": true, "pause": "", "images": ["open.gif", "close.gif"]}

View File

@ -1 +1 @@
["Custom Images"] ["Custom Messages"]

View File

@ -0,0 +1 @@
{"feature": "Custom Messages", "speed": "Medium", "animation": "Continuous", "title": true, "messages": [{"name": "1", "text": "123", "text_colour": "White", "size": "Medium", "background_colour": "Black"}, {"name": "13", "text": "123", "text_colour": "Red", "size": "Medium", "background_colour": "Purple"}]}

Binary file not shown.

Binary file not shown.

17
log.txt
View File

@ -1,17 +0,0 @@
[Errno 2] No such file or directory: '/home/pi/Desktop/stock_ticker/XOM.png'. file: stockTicker.py. line: 2230. type: <class 'FileNotFoundError'>
Traceback (most recent call last):
File "stockTicker.py", line 2230, in <module>
stock_ticker.process_msg(msg)
File "stockTicker.py", line 2194, in process_msg
self.scrollFunctionsAnimated(userSettings, animation = 'down')
File "stockTicker.py", line 309, in scrollFunctionsAnimated
self.updateMultiple([options[0]])
File "stockTicker.py", line 276, in updateMultiple
img = self.functions[option]()
File "stockTicker.py", line 1953, in getUserImage
image = self.openImage(os.path.join(os.path.dirname(os.path.abspath(__file__)), image))
File "stockTicker.py", line 76, in openImage
image = Image.open(image_file)
File "/usr/lib/python3/dist-packages/PIL/Image.py", line 2634, in open
fp = builtins.open(filename, "rb")
FileNotFoundError: [Errno 2] No such file or directory: '/home/pi/Desktop/stock_ticker/XOM.png'

View File

@ -365,6 +365,9 @@ def feature_settings():
elif feature in ['Custom GIFs', 'Custom Images']: elif feature in ['Custom GIFs', 'Custom Images']:
save_image_settings(input_settings) save_image_settings(input_settings)
elif feature == 'Custom Messages':
save_message_settings(input_settings)
return index() return index()
# saves files uploaded to the webpage for images and GIFs # saves files uploaded to the webpage for images and GIFs
@ -503,7 +506,10 @@ def save_image_settings(input_settings):
del current_settings['feature'] del current_settings['feature']
json.dump(current_settings, open('csv/' + filename, 'w+')) json.dump(current_settings, open('csv/' + filename, 'w+'))
def save_message_settings(input_settings):
json.dump(input_settings, open('csv/message_settings.json', 'w+'))
@app.route("/stop") @app.route("/stop")
def stop(): def stop():
print('stop') print('stop')

View File

@ -489,26 +489,7 @@ var allFeaturesFileAddBtn = [
var uploaded_images = [];
var uploaded_GIFs = [];
allFeaturesFileAddBtn.map((value, index) => {
if (value !== null) {
value.addEventListener("click", () => {
var tag = document.createElement("li");
tag.innerHTML = allFeaturesFile[index].files[0].name;
if (index == 10) {
uploaded_images.push(allFeaturesFile[index].files[0]);
} else if (index == 11) {
uploaded_GIFs.push(allFeaturesFile[index].files[0]);
}
allFeatures[index].appendChild(tag);
changeVarValue();
addEventOnFeaturesList();
});
}
});
// features input text // features input text
var stocksText = document.getElementById("inputText3"); var stocksText = document.getElementById("inputText3");
@ -724,7 +705,7 @@ function saveSettings() {
method:"POST", method:"POST",
body:data body:data
}); });
} }
} }
let saveSettingsButtons = document.querySelectorAll(".save-btn-div").forEach(button => let saveSettingsButtons = document.querySelectorAll(".save-btn-div").forEach(button =>
@ -801,6 +782,29 @@ function getSportsSettings(page){
return settings; return settings;
} }
var uploaded_images = [];
var uploaded_GIFs = [];
allFeaturesFileAddBtn.map((value, index) => {
if (value !== null) {
value.addEventListener("click", () => {
var tag = document.createElement("li");
tag.innerHTML = allFeaturesFile[index].files[0].name;
if (index == 10) {
uploaded_images.push(allFeaturesFile[index].files[0]);
} else if (index == 11) {
uploaded_GIFs.push(allFeaturesFile[index].files[0]);
}
allFeatures[index].appendChild(tag);
changeVarValue();
addEventOnFeaturesList();
});
}
});
//images and GIFs //images and GIFs
function getImageSettings(page){ function getImageSettings(page){
let pause = page.querySelectorAll(".pause-select")[0].value; let pause = page.querySelectorAll(".pause-select")[0].value;
@ -814,8 +818,48 @@ function getImageSettings(page){
return settings; return settings;
} }
function getMessageSettings(page) {
var messages = [];
messagesTextAddBtn.addEventListener("click", () => {
let pageSelector = "Page13";
let page = document.getElementById(pageSelector);
let msg_name = messagesText.value;
//let speed = getSelected(page.querySelectorAll(".speed-select")[0]);
//let animation = getSelected(page.querySelectorAll(".animation-select")[0]);
let message_text = page.querySelectorAll(".message-input")[0].value;
let text_colour = getSelected(page.querySelectorAll(".text-colour")[0]);
let text_size = getSelected(page.querySelectorAll(".text-size")[0]);
let background_colour = getSelected(page.querySelectorAll(".back-colour")[0]);
let message = {'name':msg_name, 'text':message_text, 'text_colour':text_colour, 'size':text_size, 'background_colour':background_colour};
messages.push(message);
});
function getMessageSettings(page) {
let messages_el = page.querySelectorAll(".message-list")[0];
let message_names = getListItems(messages_el);
//remove any messages that arent in the list
let new_messages = [];
for (let i = 0; i < messages.length; i++){
if (message_names.includes(messages[i]['name'])) {
new_messages.push(messages[i]);
}
}
let title = page.querySelectorAll(".title-select")[0].checked;
return {'title':title, 'messages':new_messages};
} }

View File

@ -45,7 +45,7 @@ class StockTicker():
self.blank = Image.new('RGB', (10, 32)) self.blank = Image.new('RGB', (10, 32))
self.running = True self.running = True
self.brightness = 1.0 self.brightness = 1.0
self.delay = 0.02
# Configuration for the matrix # Configuration for the matrix
options = RGBMatrixOptions() options = RGBMatrixOptions()
@ -62,7 +62,7 @@ class StockTicker():
'Daily Forecast':self.getDailyWeatherImage, 'Current Weather': self.getTodayWeatherImage, 'Daily Forecast':self.getDailyWeatherImage, 'Current Weather': self.getTodayWeatherImage,
'Sports (Team Stats)':lambda : self.getLeagueTableImage('premier_league'), 'Sports (Past Games)': lambda:self.getLeagueImage('NBA', 'past'), 'Sports (Team Stats)':lambda : self.getLeagueTableImage('premier_league'), 'Sports (Past Games)': lambda:self.getLeagueImage('NBA', 'past'),
'Sports (Upcoming Games)': lambda : self.getLeagueImage('NHL', 'future'), 'Sports (Live Games)': lambda: self.getLeagueImage('NBA', 'live'), 'Sports (Upcoming Games)': lambda : self.getLeagueImage('NHL', 'future'), 'Sports (Live Games)': lambda: self.getLeagueImage('NBA', 'live'),
'News':self.getNewsImage, 'Custom Messages': self.getUserText, 'Custom Images': self.getUserImage, 'Custom GIFs':self.getUserGIF, 'News':self.getNewsImage, 'Custom Messages': self.getUserMessages,
'Stocks Prof': self.getStockProfessional, 'Crypto Prof': self.getCryptoProfessional, 'Forex Prof': self.getForexProfessional, 'Stocks Prof': self.getStockProfessional, 'Crypto Prof': self.getCryptoProfessional, 'Forex Prof': self.getForexProfessional,
@ -74,6 +74,7 @@ class StockTicker():
def openImage(self, image_file): def openImage(self, image_file):
image = Image.open(image_file) image = Image.open(image_file)
image = image.convert('RGB')
# Make image fit our screen. # Make image fit our screen.
#image.thumbnail((self.matrix.width, self.matrix.height), Image.ANTIALIAS) #image.thumbnail((self.matrix.width, self.matrix.height), Image.ANTIALIAS)
@ -273,9 +274,10 @@ class StockTicker():
def updateMultiple(self, options): def updateMultiple(self, options):
for option in options: for option in options:
img = self.functions[option]()
if option not in ['Custom GIFs']: # aving the gif like this kills the animation
if option not in ['Custom GIFs', 'Custom Images', 'Custom Messages']: # these images are already saved in user uploads, dodnt need to update them
img = self.functions[option]()
img.save('./display_images/'+ option+ '.ppm') img.save('./display_images/'+ option+ '.ppm')
@ -317,69 +319,84 @@ class StockTicker():
update_process = Process(target = self.updateMultiple, args = ([options[(i+1) % len(options)]],)) update_process = Process(target = self.updateMultiple, args = ([options[(i+1) % len(options)]],))
update_process.start() update_process.start()
self.delay = 0.02
if options[i % len(options)] == 'Custom Images':
images = self.getUserImages()
elif options[i % len(options)] == 'Custom GIFs':
images = self.getUserGIFs()
elif options[i % len(options)] == 'Custom Messages':
images = self.getUserMessages()
if options[i % len(options)] != 'Custom GIFs': else: #these options just have a single ppm image
image = self.openImage('./display_images/' + options[i % len(options)] +'.ppm') image = self.openImage('./display_images/' + options[i % len(options)] +'.ppm')
image = image.convert('RGB')
else: images = [image]
image = self.openImage('./display_images/Custom GIFs.gif')
img_width, img_height = image.size for image in images:
img_width, img_height = image.size
offset_x = 0
if animation == 'traditional':
offset_x = 128
elif animation == 'continuous':
offset_x = 0 offset_x = 0
elif animation in ['up', 'down']: if animation == 'traditional':
offset_x = max(0, 128-img_width) offset_x = 128
elif animation == 'continuous':
offset_y = 0 offset_x = 0
#first scroll image in from bottom elif animation in ['up', 'down']:
offset_x = max(0, 128-img_width)
frame_skip = int((1/15)/self.delay) #controls how fast gifs run
self.frame = 0
pause_frames = int(0.5/self.delay)
if animation == 'up':
offset_y = 33
direction = -1
kill = self.scrollImageY(image, direction = direction, offset_x = offset_x, offset_y = offset_y, frame_skip = frame_skip, gif = options[i % len(options)] == 'Custom GIFs')
elif animation == 'down':
direction = 1
offset_y = -33
kill = self.scrollImageY(image, direction = direction, offset_x = offset_x, offset_y = offset_y, frame_skip = frame_skip, gif = options[i % len(options)] == 'Custom GIFs')
if kill: break offset_y = 0
offset_y = 0 #first scroll image in from bottom
if animation in ['up', 'down']:
while pause_frames > 0:
if pause_frames%frame_skip == 0:
self.incrementGIF(image)
pause_frames -=1
if options[i % len(options)] != 'Custom GIFs':
self.double_buffer.SetImage(image, offset_x, offset_y)
else:
self.double_buffer.SetImage(image.convert('RGB'), offset_x, offset_y)
self.double_buffer = self.matrix.SwapOnVSync(self.double_buffer)
frame_skip = int((1/15)/self.delay) #controls how fast gifs run
self.frame = 0
pause_frames = int(0.5/self.delay)
if animation == 'up':
offset_y = 33
direction = -1
kill = self.scrollImageY(image, direction = direction, offset_x = offset_x, offset_y = offset_y, frame_skip = frame_skip, gif = options[i % len(options)] == 'Custom GIFs')
elif animation == 'down':
direction = 1
offset_y = -33
kill = self.scrollImageY(image, direction = direction, offset_x = offset_x, offset_y = offset_y, frame_skip = frame_skip, gif = options[i % len(options)] == 'Custom GIFs')
if kill: break
offset_y = 0
if animation in ['up', 'down']:
while pause_frames > 0:
if pause_frames%frame_skip == 0:
self.incrementGIF(image)
pause_frames -=1
if options[i % len(options)] != 'Custom GIFs':
self.double_buffer.SetImage(image, offset_x, offset_y)
else:
self.double_buffer.SetImage(image.convert('RGB'), offset_x, offset_y)
self.double_buffer = self.matrix.SwapOnVSync(self.double_buffer)
time.sleep(self.delay)
kill = self.checkKilled()
if kill: break
time.sleep(self.delay)
kill = self.checkKilled()
if kill: break if kill: break
if kill: break if kill: break
kill = self.scrollImage(image, offset_x = offset_x, offset_y = offset_y, frame_skip = frame_skip, gif = options[i % len(options)] == 'Custom GIFs')
if kill: break
if kill: break
kill = self.scrollImage(image, offset_x = offset_x, offset_y = offset_y, frame_skip = frame_skip, gif = options[i % len(options)] == 'Custom GIFs') if kill:break
if kill: break
update_process.join() update_process.join()
i+=1 i+=1
@ -458,7 +475,7 @@ class StockTicker():
if kill: break if kill: break
i+=1 i+=1
def textImage(self, text, font, r = 255, g = 255, b = 255, matrix_height = False, w_buff = 3, h_buff = 3): def textImage(self, text, font, r = 255, g = 255, b = 255, matrix_height = False, w_buff = 3, h_buff = 3, background = False):
''' '''
creates and returns a ppm image containing the text in the supplied font and colour creates and returns a ppm image containing the text in the supplied font and colour
''' '''
@ -469,29 +486,55 @@ class StockTicker():
height = 32 height = 32
img = Image.new('RGB', (width + w_buff, height + h_buff)) img = Image.new('RGB', (width + w_buff, height + h_buff))
d = ImageDraw.Draw(img) d = ImageDraw.Draw(img)
if background:
br, bg, bb = background
d.rectangle(xy = (0, 0, width + w_buff, height + h_buff),
fill = (br, bg, bb))
#outline = (255, 255, 255),
#width = 0) #use outline and width to add a border
d.text((0, 0), text, fill=(r, g, b), font=font) d.text((0, 0), text, fill=(r, g, b), font=font)
return img return img
def getUserText(self): def getUserMessages(self):
''' '''
displays the text entered in the webpage by the user. displays the text entered in the webpage by the user.
''' '''
f = open('csv/scroll_text.csv', 'r')
CSV = csv.reader(f)
text, r, g, b = next(CSV)
f = open('csv/message_settings.json', 'r')
all_settings = json.load(f)
f.close() f.close()
title_img = self.openImage('feature_titles/message.png') if all_settings['title']:
title_img = self.openImage('feature_titles/message.png')
font = ImageFont.load("./fonts/texgyre-27.pil") imgs = [title_img]
else:
imgs = []
img = self.textImage(text, font, int(r), int(g), int(b), True, w_buff = 50) colours = {'Black':(0,0,0),
return self.stitchImage([title_img, img]) 'White':(255,255,255),
'Red':(255,0,0),
'Green':(0,255,0),
'Blue':(0,0,255),
'Purple':(255,0,255),
'Yellow':(255,255,0),
'Cyan':(0,255,255)}
for message in all_settings['messages']:
font = ImageFont.load("./fonts/texgyre-27.pil")
r,g,b = colours[message['text_colour']]
background = colours[message['background_colour']]
img = self.textImage(message['text'], font, int(r), int(g), int(b), True, w_buff = 50, background = background)
imgs.append(img)
return imgs
def displayGIF(self, gif): def displayGIF(self, gif):
# To iterate through the entire gif # To iterate through the entire gif
@ -1937,7 +1980,7 @@ class StockTicker():
time.sleep(self.delay*1.1) time.sleep(self.delay*1.1)
def getUserImage(self): def getUserImages(self):
title_img = self.openImage('feature_titles/images.png') title_img = self.openImage('feature_titles/images.png')
@ -1950,21 +1993,30 @@ class StockTicker():
imgs = [] imgs = []
for image in all_settings['images']: for image in all_settings['images']:
image = self.openImage(os.path.join(os.path.dirname(os.path.abspath(__file__)), image))
img = self.openImage(os.path.join(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'user_uploads'), image))
imgs.append(img)
return self.stitchImage(imgs) return imgs
def getUserGIF(self):
title_img = self.openImage('feature_titles/gifs.png')
gif = Image.open(os.path.join(os.path.dirname(os.path.abspath(__file__)), all_settings['images'][0]))
def getUserGIFs(self):
f = open('csv/GIF_settings.json', 'r') f = open('csv/GIF_settings.json', 'r')
all_settings = json.load(f) all_settings = json.load(f)
f.close() f.close()
if all_settings['title']:
title_img = self.openImage('feature_titles/gifs.png')
GIFs = [title_img]
else:
GIFs = []
for f in all_settings['images']:
GIF = Image.open(os.path.join(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'user_uploads'), f))
GIFs.append(GIF)
#below code stitches title and GIF together
'''
frames = [] frames = []
for i, frame in enumerate(ImageSequence.Iterator(gif)): for i, frame in enumerate(ImageSequence.Iterator(gif)):
@ -1977,9 +2029,9 @@ class StockTicker():
frames[0].save('./display_images/Custom GIFs.gif', save_all=True, append_images=frames[1:], loop=0, optimize = False) frames[0].save('./display_images/Custom GIFs.gif', save_all=True, append_images=frames[1:], loop=0, optimize = False)
'''
return None return GIFs
def displayStocks(self): def displayStocks(self):

View File

@ -2301,12 +2301,13 @@
<input <input
type="text" type="text"
id="inputText14" id="inputText14"
class="form-control" class="form-control message-input"
aria-describedby="TextHelpInline" aria-describedby="TextHelpInline"
/> />
</div> </div>
</div> </div>
<!--
<div class="row g-3 align-items-center mt-3"> <div class="row g-3 align-items-center mt-3">
<div class="col-auto"> <div class="col-auto">
<label for="inputText15" class="col-form-label" <label for="inputText15" class="col-form-label"
@ -2322,7 +2323,8 @@
/> />
</div> </div>
</div> </div>
<div class="row g-3 align-items-center mt-3"> <div class="row g-3 align-items-center mt-3">
<div class="col-auto"> <div class="col-auto">
<label for="inputScrollSpeed14" class="col-form-label" <label for="inputScrollSpeed14" class="col-form-label"
@ -2338,6 +2340,7 @@
</div> </div>
</div> </div>
<div class="row g-3 align-items-center mt-3"> <div class="row g-3 align-items-center mt-3">
<div class="col-auto"> <div class="col-auto">
<label for="inputScrollSpeed15" class="col-form-label" <label for="inputScrollSpeed15" class="col-form-label"
@ -2352,6 +2355,7 @@
</select> </select>
</div> </div>
</div> </div>
-->
<div class="row g-3 align-items-center mt-3"> <div class="row g-3 align-items-center mt-3">
<div class="col-auto"> <div class="col-auto">
@ -2360,10 +2364,15 @@
</label> </label>
</div> </div>
<div class="col-auto"> <div class="col-auto">
<select id="inputScrollSpeed16" class="form-select"> <select id="inputScrollSpeed16" class="form-select text-colour">
<option>White</option> <option>White</option>
<option></option> <option>Black</option>
<option></option> <option>Red</option>
<option>Green</option>
<option>Blue</option>
<option>Purple</option>
<option>Yellow</option>
<option>Cyan</option>
</select> </select>
</div> </div>
</div> </div>
@ -2375,14 +2384,16 @@
</label> </label>
</div> </div>
<div class="col-auto"> <div class="col-auto">
<select id="inputScrollSpeed17" class="form-select"> <select id="inputScrollSpeed17" class="form-select text-size">
<option>Medium</option> <option>Medium</option>
<option>Small</option> <option>Small</option>
<option>Large</option> <option>Large</option>
</select> </select>
</div> </div>
</div> </div>
<!--
<div class="row g-3 align-items-center mt-3"> <div class="row g-3 align-items-center mt-3">
<div class="col-auto"> <div class="col-auto">
<label for="inputScrollSpeed18" class="col-form-label" <label for="inputScrollSpeed18" class="col-form-label"
@ -2397,6 +2408,7 @@
</select> </select>
</div> </div>
</div> </div>
-->
<div class="row g-3 align-items-center mt-3"> <div class="row g-3 align-items-center mt-3">
<div class="col-auto"> <div class="col-auto">
@ -2405,10 +2417,15 @@
</label> </label>
</div> </div>
<div class="col-auto"> <div class="col-auto">
<select id="inputScrollSpeed19" class="form-select"> <select id="inputScrollSpeed19" class="form-select back-colour">
<option>Black</option>
<option>White</option>
<option>Red</option>
<option>Green</option> <option>Green</option>
<option></option> <option>Blue</option>
<option></option> <option>Purple</option>
<option>Yellow</option>
<option>Cyan</option>
</select> </select>
</div> </div>
</div> </div>
@ -2421,7 +2438,7 @@
</div> </div>
<div class="col-auto"> <div class="col-auto">
<input <input
class="form-check-input" class="form-check-input title-select"
type="checkbox" type="checkbox"
value="" value=""
id="flexCheckChecked29" id="flexCheckChecked29"
@ -2435,23 +2452,10 @@
<div class="features-div-two"> <div class="features-div-two">
<ul <ul
id="messages-features" id="messages-features"
class="display-features-list text-dark" class="display-features-list text-dark message-list"
> >
<li>Custom Message 1</li>
<li>Custom Message 1</li>
<li>Custom Message 1</li>
<li>Custom Message 1</li>
<li>Custom Message 1</li>
<li>Custom Message 1</li>
<li>Custom Message 1</li>
<li>Custom Message 1</li>
<li>Custom Message 1</li>
<li>Custom Message 1</li>
<li>Custom Message 1</li>
<li>Custom Message 1</li>
</ul> </ul>
</div> </div>
</div> </div>

BIN
user_uploads/close.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 821 B