Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions SMTplugins/BlackJack/blackjack_route.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
from SMTplugins.BlackJack.blackjack_widget import BlackjackWidget
blackjack_bp = Blueprint('blackjack_bp', __name__)

def get_blueprint():
return blackjack_bp

SUITS = ['hearts', 'diamonds', 'spades', 'clubs']
VALUES = ['A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K']

Expand Down Expand Up @@ -37,11 +40,11 @@ def stand():
data = request.json
deck = data.get('deck', [])
dealer_hand = data.get('dealer_hand', [])

# Dealer must hit until score >= 17
while get_score(dealer_hand) < 17:
dealer_hand.append(deck.pop())

return jsonify({
"dealer_hand": dealer_hand,
"remaining_deck": deck,
Expand Down
3 changes: 3 additions & 0 deletions SMTplugins/Calendar/calendar_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
_widget = calendarWidget()
_widget.update()

def get_blueprint():
return calendar_bp

@calendar_bp.route("/widget/calendar")
def calendar_view():
return render_template("calendar_widget.html", data=_widget.widgetData)
Expand Down
3 changes: 3 additions & 0 deletions SMTplugins/FakeLight/fakeLight_route.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@

fakeLight_bp = Blueprint('fakeLight', __name__)

def get_blueprint():
return fakeLight_bp

light_instance = FakeLightWidget()

@fakeLight_bp.route('/api/light/status', methods=['GET'])
Expand Down
11 changes: 7 additions & 4 deletions SMTplugins/GoogleTasks/googleTasks_route.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
googleTasks_bp = Blueprint('googleTasks_bp', __name__)
tasks = GoogleTasksWidget()

def get_blueprint():
return googleTasks_bp

@googleTasks_bp.route("/api/google/tasks")
def get_google_tasks():
data = tasks.update()
Expand All @@ -16,7 +19,7 @@ def get_google_tasks():
def complete_task():
data = request.get_json()
task_id = data.get('task_id')

if not task_id:
return jsonify({"error": "No task ID provided"}), 400

Expand All @@ -28,11 +31,11 @@ def complete_task():
# Use patch to update the status to 'completed'
# Google requires the task ID and the '@default' list ID
service.tasks().patch(
tasklist='@default',
task=task_id,
tasklist='@default',
task=task_id,
body={'status': 'completed'}
).execute()

return jsonify({"status": "success", "message": "Task marked as completed"})

except Exception as e:
Expand Down
3 changes: 3 additions & 0 deletions SMTplugins/Package/package_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@

package_bp = Blueprint('package', __name__)

def get_blueprint():
return package_bp

_widget = packageWidget()


Expand Down
15 changes: 9 additions & 6 deletions SMTplugins/Spotify/spotify_route.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@
# Blueprint for Spotify
spotify_bp = Blueprint("spotify_bp", __name__)

# Spotify API credentials that are needed
def get_blueprint():
return spotify_bp

# Spotify API credentials that are needed
CLIENT_ID = "f77a81fa784b46d6a3513a1fddbd3a2f"
CLIENT_SECRET = "8ea40647f6c34ed7bae3afa7c5e1a267"
REDIRECT_URI = "http://127.0.0.1:5000/callback"
Expand All @@ -23,7 +26,7 @@ def get_auth_header():
return {"Authorization": f"Basic {auth_base64}"}


# Creates a bearer token header for the API calls
# Creates a bearer token header for the API calls
def get_bearer_header():
return {"Authorization": f"Bearer {access_token}"}

Expand Down Expand Up @@ -52,7 +55,7 @@ def refresh_access_token():
return True


# Route needed to redirect user to Spotify login page
# Route needed to redirect user to Spotify login page
@spotify_bp.route("/login")
def spotify_login():
scope = "user-read-currently-playing user-modify-playback-state"
Expand All @@ -66,7 +69,7 @@ def spotify_login():
return redirect(auth_url)


# Call back route after Spotify login
# Call back route after Spotify login
@spotify_bp.route("/callback")
def spotify_callback():
global access_token, refresh_token
Expand Down Expand Up @@ -113,13 +116,13 @@ def get_spotify():
"isPlaying": False
})

# Request current playback
# Request current playback
response = requests.get(
"https://api.spotify.com/v1/me/player/currently-playing",
headers=get_bearer_header()
)

# This is when no song is playing
# This is when no song is playing
if response.status_code == 204:
return jsonify({
"track": "Nothing Playing",
Expand Down
7 changes: 5 additions & 2 deletions SMTplugins/TempSensor_Dummy/flaskTempSensorDummy.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,15 @@

fTemp_bp = Blueprint('FakeTeperature', __name__)

def get_blueprint():
return fTemp_bp

DATA_FILE = "SMTplugins/TempSensor_Dummy/sensor_data.json"

@fTemp_bp.route("/temperature")
def get_temp():
current_val = "NAN "

# Check if the file exists before trying to read it
if os.path.exists(DATA_FILE):
try:
Expand All @@ -22,7 +25,7 @@ def get_temp():

# Pass the value to Widget Subsystem
temp_widget = tempSensorWidget()
temp_widget.updateTemp(current_val)
temp_widget.updateTemp(current_val)
return jsonify({"temp": temp_widget.update()})

#FOR HOME ASSISTANT UNTESTED
Expand Down
5 changes: 4 additions & 1 deletion SMTplugins/TimeZoneClock/timeZone_route.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
timeZone_bp = Blueprint('timeZone_bp', __name__)
DATA_FILE = os.path.join("SMTplugins", "TimeZoneClock", "locations.json")

def get_blueprint():
return timeZone_bp

@timeZone_bp.route("/api/timezone/data")
def get_location_times():
output = []
Expand All @@ -27,5 +30,5 @@ def get_location_times():
})
except Exception as e:
return jsonify({"error": str(e)}), 500

return jsonify(output)
11 changes: 7 additions & 4 deletions SMTplugins/Weather/weather_route.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
weather_bp = Blueprint('weather_bp', __name__)
geolocator = Nominatim(user_agent="SMT_Terminal_Project")

def get_blueprint():
return weather_bp

# NWS requires a unique User-Agent header
HEADERS = {
'User-Agent': '(SMT-Project, bschadoff@albany.edu)',
Expand All @@ -32,21 +35,21 @@ def get_nws_weather():
location = geolocator.geocode(city)
if not location:
return jsonify({"error": "City not found"}), 404

lat, lon = location.latitude, location.longitude

# 2) Resolve coordinates to NWS Grid Points
points_url = f"https://api.weather.gov/points/{lat},{lon}"
points_res = requests.get(points_url, headers=HEADERS)
points_res.raise_for_status()

# 3) Get the Hourly Forecast URL
forecast_url = points_res.json()['properties']['forecastHourly']
forecast_res = requests.get(forecast_url, headers=HEADERS)
forecast_res.raise_for_status()

periods = forecast_res.json()['properties']['periods']

# Current data is the first period
current = periods[0]
# Calculate H/L by looking at the next 24 hourly periods
Expand Down
20 changes: 10 additions & 10 deletions SMTplugins/Weather/weather_widget.py
Original file line number Diff line number Diff line change
@@ -1,31 +1,31 @@
from widget import Widget
from weather_route import get_nws_weather
import weather_route

class weatherrWidget(Widget):

def widgetName(self):
return "Weather"

def widgetID(self):
return "weather"

def widgetHTML(self):
return "<div id='weather'></div>"

def widgetData(self):
return get_nws_weather()

def widgetPreferences(self):
return {}

def widgetDefaultPreferences(self):
return {}

def updateTimer(self):
return 15000 #Update every 15 secs for testing

def handle_event(self, event, args):
return None

def update(self):
return get_nws_weather()
return weather_route.get_nws_weather()
3 changes: 3 additions & 0 deletions SMTplugins/clock/clock_route.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@

clock_bp = Blueprint('clock', __name__)

def get_blueprint():
return clock_bp

@clock_bp.route("/time")
def get_time():
clock = clockWidget()
Expand Down
3 changes: 3 additions & 0 deletions SMTplugins/date/date_route.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@

date_bp = Blueprint("date_bp", __name__)

def get_blueprint():
return date_bp

@date_bp.route("/api/date")
def get_date():
now = datetime.now()
Expand Down
9 changes: 0 additions & 9 deletions SMTplugins/pluginImports.py

This file was deleted.

60 changes: 43 additions & 17 deletions flaskServer.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
from flask import Flask, render_template, request, jsonify
import os
import sys
import json
import importlib

'''from SMTplugins.pluginImports import *
from SMTplugins.Calendar.calendar_plugin import calendar_bp
Expand All @@ -12,27 +14,51 @@
import os
import json

from SMTplugins.pluginImports import *
from SMTplugins.Calendar.calendar_plugin import calendar_bp
from SMTplugins.Package.package_plugin import package_bp

app = Flask(__name__)



#######PLUGINS#######
app.register_blueprint(clock_bp)
app.register_blueprint(fTemp_bp)
app.register_blueprint(weather_bp)
app.register_blueprint(timeZone_bp)
app.register_blueprint(date_bp)
app.register_blueprint(blackjack_bp) #Blackjack
app.register_blueprint(googleTasks_bp)
app.register_blueprint(spotify_bp)
app.register_blueprint(calendar_bp)
app.register_blueprint(package_bp)
app.register_blueprint(fakeLight_bp)
# IMPORTANT - Every bp file must have a function called get_blueprint() that returns the blueprint to be registered
# ALSO!!!! FOR SOME REASON YOU CANT USE FROM X IMPORT Y. ONLY USE "IMPORT Y" WHEN MAKING WIDGETS
# Recursive function that searches for all .py files in the filepath, including all subfolders in the path
def deep_search_for_module_blueprints(filepath):
returnList = []
specList = []

for filename in os.listdir(filepath):
current_filepath = filepath + "\\" + filename

# If we found a directory, recursively search it for plugins
if os.path.isdir(current_filepath) and filename != "__pycache__":
recur_returnList, recur_specList = deep_search_for_module_blueprints(current_filepath)
returnList.extend(recur_returnList)
specList.extend(recur_specList)

# If we found a module, lazily import it
elif filename.endswith('.py'):
print("Importing " + current_filepath)

module_name = filename[:-3]
spec = importlib.util.spec_from_file_location(module_name, (current_filepath))
module = importlib.util.module_from_spec(spec)
sys.modules[module_name] = module_name
returnList.append(module)
specList.append(spec)

return returnList, specList

# Retrieve our potential blueprints and specs
potential_bps, specList = deep_search_for_module_blueprints(os.getcwd() + "\\SMTplugins")

# Actually perform the code executions in our imported modules
for i in range(0, len(potential_bps)):
specList[i].loader.exec_module(potential_bps[i])

for potential_bp in potential_bps:
bp_call = getattr(potential_bp, "get_blueprint", None)
if bp_call != None:
app.register_blueprint(bp_call())


#allows for easier starting of flask from start file
Expand All @@ -47,11 +73,11 @@ def clientHome():
DATA_FILE = "layout_client.json"
with open(DATA_FILE, 'r') as f:
data = json.load(f)

# Passes the list of widgets to the template
return render_template('index.html', widgets=data['widgets'])
#return render_template("index.html")

@app.route("/settings")
def settings():
return render_template("settingspage.html")
Expand Down
5 changes: 0 additions & 5 deletions start.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,6 @@ def start():
sqlThread.start()
pluginsThread.start()
flaskServer.run_flask()
# Flask thread has to be run on the main thread because of signal
#flaskServer.thread()

# NOTE - Im gonna be kicking the can further down the road with this one but as it stands the way python threading works is
# really silly, so I'm gonna remove all the debug loops and figure out how to kill all processes cleanly on exit at a later date.

# Perform setup operations
def setup():
Expand Down