code tidied up, redundant api calls removed and real time brightness and speed controls added

This commit is contained in:
Neythen 2021-05-03 11:39:31 +01:00
parent 61c27e5935
commit c8f8e24667
26 changed files with 137 additions and 140 deletions

View File

@ -1,3 +1,11 @@
MSFT,NFLX,GOOG,TSLA,AAPL,INTC,TXN,HPQ,HOG,LUV,WMT
MSFT,NFLX,GOOG,TSLA,AAPL,INTC,TXN,HPQ,HOG,LUV,WMT
MSFT,NFLX,GOOG,TSLA,AAPL,INTC,TXN,HPQ,HOG,LUV,WMT
MSFT
NFLX
GOOG
TSLA
AAPL
INTC
TXN
HPQ
HOG
LUV
WMT

1 MSFT NFLX GOOG TSLA AAPL INTC TXN HPQ HOG LUV WMT
2 MSFT NFLX NFLX GOOG TSLA AAPL INTC TXN HPQ HOG LUV WMT
3 MSFT GOOG NFLX GOOG TSLA AAPL INTC TXN HPQ HOG LUV WMT
4 TSLA
5 AAPL
6 INTC
7 TXN
8 HPQ
9 HOG
10 LUV
11 WMT

BIN
final.ppm

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.9 KiB

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 912 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 918 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 118 B

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 246 B

After

Width:  |  Height:  |  Size: 199 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 242 B

After

Width:  |  Height:  |  Size: 192 B

View File

@ -30,7 +30,7 @@ ALLOWED_EXTENSIONS = {'csv', 'png'}
#ticker.stdin.write(b'from server')
#print(ticker.stdout.readlines())
#(output, errs)
child = pexpect.spawn("sudo -E python3 stockTicker.py")
ticker = pexpect.spawn("sudo -E python3 stockTicker.py")
#stock_ticker = StockTicker()
@ -89,9 +89,20 @@ def Speed():
global speedTime
speedTime = request.form['text']
print(speedTime)
ticker.sendline(speedTime)
global LastCommand
LastCommand = 'Change Speed'
return hello()
@app.route("/Brightness", methods=['POST'])
def Brightness():
global brightness
brightness = request.form['text']
print(brightness)
ticker.sendline(brightness)
global LastCommand
LastCommand = 'Change Brightness'
return hello()
@app.route("/Ticker", methods=['POST'])
def Ticker():
@ -143,7 +154,7 @@ def matrix():
#child.sendline('sent from server')
#process = Popen(["sudo", "-E", "python3", "stockTicker.py"], stdin=PIPE, stdout=PIPE, stderr=PIPE)
child.sendline('S')
ticker.sendline('S')
print('back in flask')
@ -155,7 +166,7 @@ def matrix():
try:
#stock_ticker.stopStockTicker()
LastCommand = 'Stop display at next checkpoint'
child.sendline('K')
ticker.sendline('K')
except:
print("none running")
elif "Shutdown the pi" in request.form:

View File

@ -31,24 +31,15 @@ class StockTicker():
def __init__(self):
#Define global resources
self.symbols = []
#self.ApiKeys = [["b1be6696d54342bdb5c8f59a052854fd","237d183faf984e7eba708a647c55153a","3012b3cb19784ed4be2b02e9907e53cb"],["f835e85df2a74df1904fe6dc53bcc17a","41ec268496744c34a96e3c408081300b","2d566fc71ade46d688713b13730c5219"]]
#self.ApiKeys = [["6172b84d1f464ad88b95ed52e4391bce","979f9b8c9ee748fbbb57cb490ccaaf42","593fa818a44144699b75433aafd92d15"]]
self.ApiKey = "c24qddqad3ickpckgg80"
self.SandboxApiKey = "sandbox_c24qddqad3ickpckgg8g"
self.retrievedList = []
self.greenORred = (255, 255, 255)
self.ListStocks = []
self.blank = Image.open('logos/blank.png')
self.ApiCalledError = False
self.keySwapper = 0
self.displayTime = 60
self.speedDisplay = 25
#self.blank = Image.open('logos/blank.png')
self.blank = Image.new('RGB', (0, 32))
self.running = True
self.Delay = 20
self.parseCSV = 0
self.symbolLength = 0
self.brightness = 1.0
self.delay = 0.02
# Configuration for the matrix
options = RGBMatrixOptions()
options.rows = 64
@ -69,7 +60,7 @@ class StockTicker():
return image
def SetImage(self, image, offset_x = 0, offset_y = 0, unsafe=False):
def setImage(self, image, offset_x = 0, offset_y = 0, unsafe=False):
if (image.mode != "RGB"):
@ -96,8 +87,7 @@ class StockTicker():
self.matrix.SetPixel(x + offset_x, y + offset_y, r*self.brightness, g*self.brightness, b*self.brightness)
def ScrollImage(self, image_file, offset_x = 0, offset_y = 0, delay = 0.05):
def scrollImage(self, image_file, offset_x = 0, offset_y = 0):
image = self.openImage(image_file)
img_width, img_height = image.size
@ -106,18 +96,16 @@ class StockTicker():
while offset_x > -img_width:
offset_x -= 1
self.SetImage(image, offset_x = offset_x, offset_y = offset_y)
self.setImage(image, offset_x = offset_x, offset_y = offset_y)
time.sleep(delay)
def ScrollImageTransition(self, image_files, offset_x = 0, offset_y = 0, delay = 0.05):
def scrollImageTransition(self, image_files, offset_x = 0, offset_y = 0):
# use two image files and switch between them with a seemless transition
current_img = 1
#while True:
if current_img == 1:
image = self.openImage(image_files[0])
elif current_img == 2:
@ -130,15 +118,26 @@ class StockTicker():
offset_x -= 1
self.SetImage(image, offset_x = offset_x, offset_y = offset_y)
time.sleep(delay)
self.setImage(image, offset_x = offset_x, offset_y = offset_y)
time.sleep(self.delay)
try:
if getInput() == 'K':
msg = getInput()
if msg == 'K':
self.resetMatrix()
break
elif msg == 's':
stock_ticker.delay = 0.04
elif msg == 'm':
stock_ticker.delay = 0.02
elif msg == 'f':
stock_ticker.delay = 0.01
elif msg in ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']:
self.brightness = min(1.0, float(msg)/10 + 0.1)
except KeyboardInterrupt:
sys.stdout.flush()
pass
@ -149,11 +148,6 @@ class StockTicker():
elif current_img == 2:
current_img = 1
offset_x = 0
#Get the logo from file that is the same as ticker name
def getLogo(self, Ticker):
@ -200,12 +194,12 @@ class StockTicker():
d = ImageDraw.Draw(img)
d.text((4, 0), TICKER, fill=(255, 255, 255), font=font)
d.text((4, 13), CURRENT, fill=self.greenORred, font=font)
d.text((4, 16), CURRENT, fill=self.greenORred, font=font)
text_width_current, text_height = self.get_text_dimensions(CURRENT, font)
img.paste(ARROW, ((text_width_current + 9),18))
d.text(((text_width_current+29), 13), CHANGE, fill=self.greenORred, font=font)
d.text(((text_width_current+29), 16), CHANGE, fill=self.greenORred, font=font)
text_width_change, text_height = self.get_text_dimensions(CHANGE, font)
@ -215,54 +209,38 @@ class StockTicker():
return img
#Stitch the logo & prices picture into one image
def stitchImage(self, IMAGES):
widths, heights = zip(*(i.size for i in IMAGES))
def stitchImage(self, image_list):
widths, heights = zip(*(i.size for i in image_list))
total_width = sum(widths)
max_height = max(heights)
new_im = Image.new('RGB', (total_width, max_height))
x_offset = 0
for im in IMAGES:
for im in image_list:
new_im.paste(im, (x_offset,0))
x_offset += im.size[0]
print('width:', im.size[0])
return new_im
#Get current prices and day prices for the ticker then format the response into an array
def getStockPrices(self, SYMBOLS):
def getStockPrices(self, symbols):
apiCalledError = False
stock_info = []
try:
symbols_list = SYMBOLS.split(",")
quotes = [self.finnhubClient.quote(symbol) for symbol in symbols_list]
quotes = [self.finnhubClient.quote(symbol) for symbol in symbols]
current_prices = [quote['c'] for quote in quotes]
opening_prices = [quote['o'] for quote in quotes]
for i, symbol in enumerate(symbols_list):
self.retrievedList.append([symbol, current_prices[i], opening_prices[i]])
for i, symbol in enumerate(symbols):
stock_info.append([symbol, current_prices[i], opening_prices[i]])
print(self.retrievedList)
'''
td = TDClient(apikey=APIKEY)
tmin = td.time_series(symbol=SYMBOLS, interval="1min", outputsize='1').as_json()
tday = td.time_series(symbol=SYMBOLS, interval="1day", outputsize='2').as_json()
for i in range(len(symbols_list)):
currentMinPriceList = tmin[symbols_list[i]]
currentDayPriceList = list(tday[symbols_list[i]])
del currentDayPriceList[0]
currentMinPriceClose = tmin[symbols_list[i]][0]['close']
currentDayPriceClose = currentDayPriceList[0]['close']
self.retrievedList.append([])
self.retrievedList[i].append(symbols_list[i])
self.retrievedList[i].append(currentMinPriceClose)
self.retrievedList[i].append(currentDayPriceClose)
'''
except Exception as e:
print("Could not fetch data - API CALLS REACHED? - Will display old image")
print(e)
self.ApiCalledError = True
apiCalledError = True
return stock_info, apiCalledError
def resetMatrix(self):
for x in range(self.matrix.width):
for y in range(self.matrix.height):
@ -273,94 +251,75 @@ class StockTicker():
#Connect all the pieces togeather creating 1 long final stock image
def getFullStockImage(self):
self.ApiCalledError = False
self.ListStocks = []
self.retrievedList = []
start = time.time()
print('elapsed time: ' + str((time.time()-start)))
j=0
while (j<3):
# NT: this weird API key thing doesnt work, when I hard code the API key in the above function it does
self.getStockPrices(self.symbols[(j+self.parseCSV)][0])
if (self.ApiCalledError == False):
j+=1
print('elapsed time after api call: ' + str((time.time()-start)))
for i in range(len(self.retrievedList)):
print('elapsed timethrough loop: ' + str((time.time()-start)))
Change = float(self.retrievedList[i][1])-float(self.retrievedList[i][2]) #TEXT
Ticker = self.retrievedList[i][0] #TEXT
Current = '%.2f' % float(self.retrievedList[i][1]) #TEXT
Logo = self.getLogo(self.retrievedList[i][0])
Arrow, Change = self.getArrow(Change)
Change = '%.2f' % Change
MidFrame = self.textToImage(Ticker, Current, Change, Arrow) #IMAGE THE TEXT
StitchedStock = self.stitchImage([Logo,MidFrame])
self.ListStocks.append(self.blank)
self.ListStocks.append(StitchedStock)
self.retrievedList = []
else:
break
image_list = []
start = time.time()
stock_info, apiCalledError = self.getStockPrices(self.symbols)
if (apiCalledError == False):
for i in range(len(stock_info)):
change = float(stock_info[i][1])-float(stock_info[i][2]) #TEXT
ticker = stock_info[i][0] #TEXT
current = '%.2f' % float(stock_info[i][1]) #TEXT
logo = self.getLogo(stock_info[i][0])
arrow, change = self.getArrow(change)
change = '%.2f' % change
midFrame = self.textToImage(ticker, current, change, arrow) #IMAGE THE TEXT
stitchedStock = self.stitchImage([logo,midFrame])
image_list.append(self.blank)
image_list.append(stitchedStock)
print('elapsed time loop ended: ' + str((time.time()-start)))
if (self.ApiCalledError == False):
FinalDisplayImage = self.stitchImage(self.ListStocks)
FinalDisplayImage.save('final.ppm')
print(self.retrievedList)
if (apiCalledError == False):
finalDisplayImage = self.stitchImage(image_list)
finalDisplayImage.save('final.ppm')
#Send the final stitched image to the display for set amount of time
def displayMatrix(self):
#os.system("sudo ./demo -D1 final.ppm -t " + str(displayTime) +" -m "+ str(speedDisplay) +" --led-gpio-mapping=adafruit-hat --led-rows=32 --led-cols=256")
#os.system("sudo ./demo -D1 final.ppm -t " + str(self.displayTime) +" -m "+ str(self.speedDisplay) +" --led-gpio-mapping=adafruit-hat --led-rows=64 --led-cols=64 --led-slowdown-gpio=4 ")
self.ScrollImageTransition(['final.ppm', 'final.ppm'], offset_x = 0, offset_y = 0, delay = 0.02)
self.scrollImageTransition(['final.ppm', 'final.ppm'], offset_x = 0, offset_y = 0)
#Retrieve symbols from the CSV file
def GetSymbols(self):
def getSymbols(self):
self.symbols = []
CSV = csv.reader(open('csv/tickers.csv', 'r'))
z = 0
for row in CSV:
self.symbols.append([])
endLine = str(row[0]+','+row[1]+','+row[2]+','+row[3]+','+row[4]+','+row[5]+','+row[6]+','+row[7]+','+row[8]+','+row[9]+','+row[10])
self.symbols[z].append(endLine)
z+=1
print(row)
self.symbols.append(row[0])
print(self.symbols)
#Main run definition called by server
def runStockTicker(self, RUNTIME, DELAY, SPEEDTIME):
def runStockTicker(self, runtime, delay, speedtime):
self.parseCSV = 0
self.Delay = DELAY
self.displayTime = RUNTIME
self.speedDisplay = SPEEDTIME
self.GetSymbols()
self.symbolLength = (len(self.symbols) - 3)
self.getSymbols()
self.GetfullStockImage()
self.keySwapper += 1
self.running = True
self.parseCSV += 3
while (True):
if (self.running == True):
if (self.keySwapper<=1):
if(self.parseCSV <= self.symbolLength):
#th = threading.Thread(target=self.displayMatrix)
#th.start()
self.displayMatrix()
time.sleep((int(self.displayTime) - int(self.Delay)))
self.GetfullStockImage()
self.keySwapper += 1
th.join()
self.parseCSV += 3
else:
self.parseCSV = 0
else:
self.keySwapper = 0
#th = threading.Thread(target=self.displayMatrix)
#th.start()
self.displayMatrix()
time.sleep((int(runtime) - int(delay)))
self.getfullStockImage()
#th.join()
else:
break;
@ -376,9 +335,9 @@ if __name__ == '__main__':
#print(sys.stdin.readlines())
stock_ticker = StockTicker()
stock_ticker.GetSymbols()
stock_ticker.getFullStockImage()
stock_ticker.displayMatrix()
stock_ticker.getSymbols()
#stock_ticker.getFullStockImage()
#stock_ticker.displayMatrix()
while True:
@ -386,5 +345,16 @@ if __name__ == '__main__':
if msg == 'S':
stock_ticker.getFullStockImage()
stock_ticker.displayMatrix()
elif msg == 's':
stock_ticker.delay = 0.04
elif msg == 'm':
stock_ticker.delay = 0.02
elif msg == 'f':
stock_ticker.delay = 0.01
elif msg in ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']:
stock_ticker.brightness = min(1.0, float(msg)/10 + 0.1)

Binary file not shown.

View File

@ -23,11 +23,17 @@
<input name="text" placeholder="20"style="height:24px">
<input type="submit" value="Delay"style="height:30px">
</form>
<p>Set the speed the image scrolls across the screen (m/s, lower is faster)</p>
<p>Set the speed the image scrolls across the screen (s, m of f for slow, medium or fast)</p>
<form action="/Speed" method="POST">
<input name="text" placeholder="25"style="height:24px">
<input name="text" placeholder="m"style="height:24px">
<input type="submit" value="Speed"style="height:30px">
</form>
<p>Set the brightness, an integer between 0 and 9, higher is brighter</p>
<form action="/Brightness" method="POST">
<input name="text" placeholder="9"style="height:24px">
<input type="submit" value="Brightness"style="height:30px">
</form>
<br><br>
<h3>Tickers to display</h3>
@ -50,8 +56,7 @@
<p><input type=file name=file style="height:30px">
<input type=submit value=Upload style="height:30px">
</form>
<p>Logos currently in file:</p>
<p>{{ logofiles }}</p>
<br><br>
<form action="/matrix" method="POST">
@ -61,6 +66,9 @@
</form>
<br><br>
<br><br>
<p>Logos currently in file:</p>
<p>{{ logofiles }}</p>
</center>
</body>
</html>
</html>