# Copyright (C) 2020 Daniel Richardson richardson.daniel@hotmail.co.uk # # This file is part of stockTicker project for justinodunn. # # stockTicker can not be copied and/or distributed without the express # permission of Daniel Richardson from flask import Flask, render_template, request from stockTicker import StockTicker from werkzeug.utils import secure_filename import os import datetime import threading import csv import pexpect import time import json from multiprocessing import Process from subprocess import Popen, PIPE import numpy as np #stock_ticker = StockTicker() print('API CALLER NOT STARTED') #api_caller = pexpect.spawn("sudo -E python3 api_caller.py") command = 300 tickerList = 0 DelayTime = 20 LastCommand = '' speedTime = 25 LOGO_FOLDER = 'logos/' CSV_FOLDER = 'csv/new/' ALLOWED_EXTENSIONS = {'csv', 'png'} ticker = pexpect.spawn("sudo -E taskset -c 3 python3 stockTicker.py") ticker.sendline('A') # run by default def allowed_file(filename): return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS def process_file(path, filename): default_csv = csv.writer(open('csv/tickers.csv', 'w')) new_csv = csv.reader(open((path), 'r')) for row in new_csv: default_csv.writerow(row) app = Flask(__name__) @app.route("/", methods=['GET', 'POST']) def index(): global command all_features = ['Current Weather','Daily Forecast','News', 'Sports (Upcoming Games)','Sports (Past Games)','Sports (Live Games)', 'Sports (Team Stats)','Custom Images', 'Custom GIFs', 'Custom Messages', 'Stocks', 'Crypto', 'Forex'] currently_displaying = json.load(open('csv/display_settings.json', 'r')) not_displaying = [f for f in all_features if f not in currently_displaying] now = datetime.datetime.now() timeString = now.strftime("%Y-%m-%d %H:%M") logos_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'logos') LogoList = os.listdir(logos_path) stocks_settings = json.load(open('csv/stocks_settings.json', 'r')) crypto_settings = json.load(open('csv/crypto_settings.json', 'r')) forex_settings = json.load(open('csv/forex_settings.json', 'r')) current_weather= json.load(open('csv/current_weather.json', 'r')) daily_weather = json.load(open('csv/daily_weather.json', 'r')) news_settings = json.load(open('csv/news_settings.json', 'r')) upcoming_games = json.load(open('csv/upcoming_games.json', 'r')) live_games = json.load(open('csv/live_games.json', 'r')) past_games = json.load(open('csv/past_games.json', 'r')) team_stats = json.load(open('csv/league_tables.json', 'r')) image_settings = json.load(open('csv/image_settings.json', 'r')) GIF_settings = json.load(open('csv/GIF_settings.json', 'r')) message_settings = json.load(open('csv/message_settings.json', 'r')) templateData = { 'currently_displaying': currently_displaying, 'not_displaying': not_displaying, 'stocks_settings': stocks_settings, 'crypto_settings': crypto_settings, 'forex_settings': forex_settings, 'current_weather': current_weather, 'daily_weather': daily_weather, 'news_settings': news_settings, 'upcoming_games': upcoming_games, 'past_games': past_games, 'live_games': live_games, 'team_stats': team_stats, 'image_settings':image_settings, 'GIF_settings':GIF_settings, 'message_settings':message_settings } return render_template('index.html', **templateData) @app.route("/Runtime", methods=['POST']) def Runtime(): command = request.form['text'] LastCommand = 'Change runtime' return index() @app.route("/Delay", methods=['POST']) def Delay(): global DelayTime DelayTime = request.form['text'] global LastCommand LastCommand = 'Change Delay' return index() @app.route("/Speed", methods=['POST']) def Speed(): global speed speed = request.form['text'] ticker.sendline(speed) f = open('csv/settings.csv', 'r') CSV = csv.reader(f) next(CSV) for line in CSV: _, brightness = line f.close() f = open('csv/settings.csv', 'w+') f.write('speed,brightness\n') f.write(str(speed) + ',' + brightness) f.close() global LastCommand LastCommand = 'Change Speed' return index() @app.route("/Brightness", methods=['POST']) def Brightness(): global brightness brightness = int(request.form['text'])-1 ticker.sendline(str(brightness)) f = open('csv/settings.csv', 'r') CSV = csv.reader(f) next(CSV) for line in CSV: speed, _ = line f.close() f = open('csv/settings.csv', 'w+') f.write('speed,brightness\n') f.write(str(speed) + ',' + str(brightness)) f.close() global LastCommand LastCommand = 'Change Brightness' return index() @app.route("/DisplayText", methods=['POST']) def DisplayText(): text = request.form['text'] f = open('csv/scroll_text.csv', 'w+') f.write(text) f.close() ticker.sendline('K') ticker.sendline('T') return index() @app.route("/SetNews", methods=['POST']) def SetNews(): text = request.form['text'] #args = ['q', 'sources', 'category', 'country'] args = ['q', 'category', 'country'] arg_dict = {} lst = text.split(',') try: for i, arg in enumerate(args): if len(lst[i])>0: arg_dict[arg] = lst[i] json.dump( arg_dict, open( "csv/news_settings.json", 'w+' )) except Exception as e: #reset settings f = open( "csv/news_settings.json", 'w+' ) f.close() api_caller.sendline('R') return index() @app.route("/SetWeather", methods=['POST']) def SetWeather(): text = request.form['text'] #args = ['q', 'sources', 'category', 'country'] f = open( "csv/weather_location.txt", 'w+' ) f.write(text) f.close() api_caller.sendline('R') return index() @app.route("/DisplayGIF", methods=['POST']) def DisplayGIF(): if request.method == 'POST': if 'file' not in request.files: print('No file attached in request') return hello() fle = request.files['file'] if fle.filename == '': print('No file selected') return hello() if fle: filename = 'user_gif.gif' fle.save(os.path.join(os.path.dirname(os.path.abspath(__file__)),os.path.join('display_images', filename))) global LastCommand LastCommand = 'Add a new logo file' ticker.sendline('K') ticker.sendline('G') return hello() return index() @app.route("/DisplayImage", methods=['POST']) def DisplayImage(): if request.method == 'POST': if 'file' not in request.files: print('No file attached in request') return hello() fle = request.files['file'] if fle.filename == '': print('No file selected') return hello() if fle: filename = 'user_image.ppm' fle.save(os.path.join(os.path.dirname(os.path.abspath(__file__)),os.path.join('display_images', filename))) global LastCommand LastCommand = 'Add a new logo file' ticker.sendline('K') ticker.sendline('I') return hello() return index() @app.route("/Ticker", methods=['POST']) def Ticker(): if request.method == 'POST': if 'file' not in request.files: print('No file attached in request') return hello() fle = request.files['file'] if fle.filename == '': print('No file selected') return hello() if fle and allowed_file(fle.filename): filename = secure_filename(fle.filename) fle.save(os.path.join(CSV_FOLDER, filename)) process_file(os.path.join(CSV_FOLDER, filename), filename) global LastCommand LastCommand = 'Change CSV file' return hello() return index() @app.route("/AddLogo", methods=['POST']) def AddLogo(): if request.method == 'POST': if 'file' not in request.files: print('No file attached in request') return hello() fle = request.files['file'] if fle.filename == '': print('No file selected') return hello() if fle and allowed_file(fle.filename): filename = secure_filename(fle.filename) fle.save(os.path.join(LOGO_FOLDER, filename)) global LastCommand LastCommand = 'Add a new logo file' return hello() return index() professional = False @app.route("/start", methods = ['PUT', 'POST']) def start(): print(professional) data = str(request.data) all_settings = ['Stocks', 'Crypto', 'Forex', 'Current Weather', 'Daily Forecast', 'News', 'Sports (Upcoming Games)', 'Sports (Past Games)', 'Sports (Live Games)', 'Sports (Team Stats)', 'Custom Images', 'Custom GIFs', 'Custom Messages'] if professional: all_settings = ['Stocks', 'Crypto', 'Forex', 'Current Weather', 'News'] positions = [] display_settings = [] for setting in all_settings: pos = data.find(setting) if pos != -1: if professional: setting += ' Prof' display_settings.append(setting) positions.append(pos) # sort settings by display inds = np.argsort(positions) display_settings = np.array(display_settings)[inds] with open('csv/display_settings.json', 'w+') as f: json.dump(list(display_settings), f) ticker.sendline('K') ticker.sendline('A') return index() @app.route("/display_format", methods = ['PUT', 'POST', 'GET']) def display_format(): global professional data = str(request.data) if "Standard" in data: professional = False elif "Professional" in data: professional = True print(professional) return index() @app.route("/feature_settings", methods = ['PUT', 'POST', 'GET']) def feature_settings(): data = str(request.data.decode('utf-8')) input_settings = json.loads(data) print(input_settings) feature = input_settings['feature'] if feature in ['Stocks', 'Crypto', 'Forex']: save_trade_settings(input_settings) elif feature in ['Current Weather', 'Daily Forecast']: save_weather_settings(input_settings) elif feature == 'News': save_news_settings(input_settings) elif 'Sports' in feature: save_sports_settings(input_settings) elif feature in ['Custom GIFs', 'Custom Images']: save_image_settings(input_settings) elif feature == 'Custom Messages': save_message_settings(input_settings) return index() # saves files uploaded to the webpage for images and GIFs @app.route("/upload", methods = ['PUT', 'POST', 'GET']) def upload(): try: images = request.files names = list(request.files.keys()) for name in names: images[name].save('user_uploads/' +name) except Exception as e: print(e) return index() def combine_dict(current_settings, input_symbols, current_key): # removes keys not in input from current_settings[current_key] and adds keys not in current from input current_symbols = list(current_settings[current_key].keys()) # add any stock that arent current in the settings for IS in input_symbols: if IS not in current_symbols: current_settings[current_key][IS] = -1 # remove stocks not in settings for CS in current_symbols: if CS not in input_symbols: del current_settings[current_key][CS] return current_settings def save_trade_settings(input_settings): filename = input_settings['feature'].lower() + '_settings.json' current_settings = json.load(open('csv/' + filename, 'r')) current_settings['speed'] = input_settings['speed'].lower() current_settings['animation'] = input_settings['animation'].lower() current_settings['percent'] = input_settings['percent'] current_settings['point'] = input_settings['point'] current_settings['logos'] = input_settings['logos'] current_settings['chart'] = input_settings['chart'] current_settings['title'] = input_settings['title'] current_settings = combine_dict(current_settings, input_settings['symbols'], 'symbols') json.dump(current_settings, open('csv/' + filename, 'w+')) def save_weather_settings(input_settings): filename = 'current_weather.json' if input_settings['feature'] == 'Current Weather' else 'daily_weather.json' current_settings = json.load(open('csv/' + filename, 'r')) current_settings['speed'] = input_settings['speed'].lower() current_settings['animation'] = input_settings['animation'].lower() current_settings['temp'] = input_settings['temp'].lower() current_settings['wind_speed'] = input_settings['wind_speed'].lower() current_settings['colour'] = input_settings['colour'].lower() current_settings['city_colour'] = input_settings['city_colour'].lower() current_settings['title'] = input_settings['title'] if input_settings['feature'] == 'Daily Forecast': current_settings['current_weather'] = input_settings['current_weather'] current_settings = combine_dict(current_settings, input_settings['locations'], 'locations') json.dump(current_settings, open('csv/' + filename, 'w+')) def save_news_settings(input_settings): filename = 'news_settings.json' current_settings = json.load(open('csv/' + filename, 'r')) current_settings['speed'] = input_settings['speed'].lower() current_settings['animation'] = input_settings['animation'].lower() current_settings['title'] = input_settings['title'] current_settings['category'] = input_settings['category'].lower() current_settings['country'] = input_settings['country'] current_settings['sources'] = list(set(current_settings['sources'] + input_settings['sources'])) json.dump(current_settings, open('csv/' + filename, 'w+')) def save_sports_settings(input_settings): feature = input_settings['feature'] if feature == 'Sports (Upcoming Games)': filename = 'upcoming_games.json' elif feature == 'Sports (Past Games)': filename = 'past_games.json' elif feature == 'Sports (Live Games)': filename = 'live_games.json' elif feature == 'Sports (Team Stats)': filename = 'league_tables.json' current_settings = json.load(open('csv/' + filename, 'r')) current_settings['speed'] = input_settings['speed'].lower() current_settings['animation'] = input_settings['animation'].lower() current_settings['title'] = input_settings['title'] current_settings['feature'] = input_settings['feature'] current_settings = combine_dict(current_settings, input_settings['leagues'], 'leagues') json.dump(current_settings, open('csv/' + filename, 'w+')) # for images and GIFs def save_image_settings(input_settings): filename = 'image_settings.json' if input_settings['feature'] == 'Custom Images' else 'GIF_settings.json' current_settings = input_settings current_settings['speed'] = input_settings['speed'].lower() current_settings['animation'] = input_settings['animation'].lower() current_settings['title'] = input_settings['title'] del current_settings['feature'] 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") def stop(): print('stop') ticker.sendline('K') return index() @app.route("/shutdown") def shutdown(): os.system("sudo shutdown now") return index() @app.route("/matrix") def matrix(): if "Run Stocks" in request.form: ticker.sendline('K') ticker.sendline('S') elif "Run Crypto" in request.form: ticker.sendline('K') ticker.sendline('C') elif "Run Forex" in request.form: ticker.sendline('K') ticker.sendline('F') elif "Run News" in request.form: ticker.sendline('K') ticker.sendline('N') elif "Run Weather" in request.form: ticker.sendline('K') ticker.sendline('W') elif "Run Daily Weather" in request.form: ticker.sendline('K') ticker.sendline('D') elif "Past NHL" in request.form: ticker.sendline('K') ticker.sendline('P') elif "Future NHL" in request.form: ticker.sendline('K') ticker.sendline('l') elif "Live NHL" in request.form: ticker.sendline('K') ticker.sendline('L') elif "Premier league table" in request.form: ticker.sendline('K') ticker.sendline('t') elif "Professional" in request.form: ticker.sendline('K') ticker.sendline('b') elif "All" in request.form: ticker.sendline('K') ticker.sendline('A') elif "Multiple" in request.form: ticker.sendline('K') ticker.sendline('+') elif "Stop Display" in request.form: LastCommand = 'Stop display at next checkpoint' ticker.sendline('K') elif "Shutdown the pi" in request.form: try: os.system("sudo shutdown now") except: print("couldn't shutdown") return index() if __name__ == "__main__": app.run(host='0.0.0.0', port=1024, debug=False) # the debuggger causes flickering #sudo ./demo -D1 final.ppm -t 50 -m 25 --led-gpio-mapping=adafruit-hat --led-rows=32 --led-cols=256 --led-slowdown-gpio=4