diff --git a/.gitignore b/.gitignore index eeabbad..35300ae 100644 --- a/.gitignore +++ b/.gitignore @@ -8,4 +8,3 @@ thumbs.db #storage/profiles #config.py .idea/* -.DS_Store diff --git a/kiln-controller.py b/kiln-controller.py index 35ea742..17fc3f9 100755 --- a/kiln-controller.py +++ b/kiln-controller.py @@ -8,8 +8,7 @@ import json import bottle import gevent import geventwebsocket - -# from bottle import post, get +#from bottle import post, get from gevent.pywsgi import WSGIServer from geventwebsocket.handler import WebSocketHandler from geventwebsocket import WebSocketError @@ -17,11 +16,10 @@ from geventwebsocket import WebSocketError try: sys.dont_write_bytecode = True import config - sys.dont_write_bytecode = False except: - print("Could not import config file.") - print("Copy config.py.EXAMPLE to config.py and adapt it for your setup.") + print ("Could not import config file.") + print ("Copy config.py.EXAMPLE to config.py and adapt it for your setup.") exit(1) logging.basicConfig(level=config.log_level, format=config.log_format) @@ -29,7 +27,7 @@ log = logging.getLogger("kiln-controller") log.info("Starting kiln controller") script_dir = os.path.dirname(os.path.realpath(__file__)) -sys.path.insert(0, script_dir + "/lib/") +sys.path.insert(0, script_dir + '/lib/') profile_path = config.kiln_profiles_directory from oven import SimulatedOven, RealOven, Profile @@ -47,99 +45,93 @@ ovenWatcher = OvenWatcher(oven) # this ovenwatcher is used in the oven class for restarts oven.set_ovenwatcher(ovenWatcher) - -@app.route("/") +@app.route('/') def index(): - return bottle.redirect("/picoreflow/index.html") + return bottle.redirect('/picoreflow/index.html') - -@app.get("/api/stats") +@app.get('/api/stats') def handle_api(): log.info("/api/stats command received") - if hasattr(oven, "pid"): - if hasattr(oven.pid, "pidstats"): + if hasattr(oven,'pid'): + if hasattr(oven.pid,'pidstats'): return json.dumps(oven.pid.pidstats) -@app.post("/api") +@app.post('/api') def handle_api(): log.info("/api is alive") + # run a kiln schedule - if bottle.request.json["cmd"] == "run": - wanted = bottle.request.json["profile"] - log.info("api requested run of profile = %s" % wanted) + if bottle.request.json['cmd'] == 'run': + wanted = bottle.request.json['profile'] + log.info('api requested run of profile = %s' % wanted) # start at a specific minute in the schedule # for restarting and skipping over early parts of a schedule - startat = 0 - if "startat" in bottle.request.json: - startat = bottle.request.json["startat"] + startat = 0; + if 'startat' in bottle.request.json: + startat = bottle.request.json['startat'] # get the wanted profile/kiln schedule profile = find_profile(wanted) if profile is None: - return {"success": False, "error": "profile %s not found" % wanted} + return { "success" : False, "error" : "profile %s not found" % wanted } # FIXME juggling of json should happen in the Profile class profile_json = json.dumps(profile) profile = Profile(profile_json) - oven.run_profile(profile, startat=startat) + oven.run_profile(profile,startat=startat) ovenWatcher.record(profile) - if bottle.request.json["cmd"] == "stop": + if bottle.request.json['cmd'] == 'stop': log.info("api stop command received") oven.abort_run() - if bottle.request.json["cmd"] == "memo": + if bottle.request.json['cmd'] == 'memo': log.info("api memo command received") - memo = bottle.request.json["memo"] + memo = bottle.request.json['memo'] log.info("memo=%s" % (memo)) # get stats during a run - if bottle.request.json["cmd"] == "stats": + if bottle.request.json['cmd'] == 'stats': log.info("api stats command received") - if hasattr(oven, "pid"): - if hasattr(oven.pid, "pidstats"): + if hasattr(oven,'pid'): + if hasattr(oven.pid,'pidstats'): return json.dumps(oven.pid.pidstats) - return {"success": True} - + return { "success" : True } def find_profile(wanted): - """ + ''' given a wanted profile name, find it and return the parsed json profile object or None. - """ - # load all profiles from disk + ''' + #load all profiles from disk profiles = get_profiles() json_profiles = json.loads(profiles) # find the wanted profile for profile in json_profiles: - if profile["name"] == wanted: + if profile['name'] == wanted: return profile return None - -@app.route("/picoreflow/:filename#.*#") +@app.route('/picoreflow/:filename#.*#') def send_static(filename): log.debug("serving %s" % filename) - return bottle.static_file( - filename, - root=os.path.join(os.path.dirname(os.path.realpath(sys.argv[0])), "public"), - ) + return bottle.static_file(filename, root=os.path.join(os.path.dirname(os.path.realpath(sys.argv[0])), "public")) def get_websocket_from_request(): env = bottle.request.environ - wsock = env.get("wsgi.websocket") + wsock = env.get('wsgi.websocket') if not wsock: - abort(400, "Expected WebSocket request.") + abort(400, 'Expected WebSocket request.') return wsock -@app.route("/control") +@app.route('/control') def handle_control(): wsock = get_websocket_from_request() log.info("websocket (control) opened") @@ -151,7 +143,7 @@ def handle_control(): msgdict = json.loads(message) if msgdict.get("cmd") == "RUN": log.info("RUN command received") - profile_obj = msgdict.get("profile") + profile_obj = msgdict.get('profile') if profile_obj: profile_json = json.dumps(profile_obj) profile = Profile(profile_json) @@ -159,15 +151,15 @@ def handle_control(): ovenWatcher.record(profile) elif msgdict.get("cmd") == "SIMULATE": log.info("SIMULATE command received") - # profile_obj = msgdict.get('profile') - # if profile_obj: + #profile_obj = msgdict.get('profile') + #if profile_obj: # profile_json = json.dumps(profile_obj) # profile = Profile(profile_json) - # simulated_oven = Oven(simulate=True, time_step=0.05) - # simulation_watcher = OvenWatcher(simulated_oven) - # simulation_watcher.add_observer(wsock) - # simulated_oven.run_profile(profile) - # simulation_watcher.record(profile) + #simulated_oven = Oven(simulate=True, time_step=0.05) + #simulation_watcher = OvenWatcher(simulated_oven) + #simulation_watcher.add_observer(wsock) + #simulated_oven.run_profile(profile) + #simulation_watcher.record(profile) elif msgdict.get("cmd") == "STOP": log.info("Stop command received") oven.abort_run() @@ -177,7 +169,7 @@ def handle_control(): log.info("websocket (control) closed") -@app.route("/storage") +@app.route('/storage') def handle_storage(): wsock = get_websocket_from_request() log.info("websocket (storage) opened") @@ -198,18 +190,18 @@ def handle_storage(): wsock.send(get_profiles()) elif msgdict.get("cmd") == "DELETE": log.info("DELETE command received") - profile_obj = msgdict.get("profile") + profile_obj = msgdict.get('profile') if delete_profile(profile_obj): - msgdict["resp"] = "OK" + msgdict["resp"] = "OK" wsock.send(json.dumps(msgdict)) - # wsock.send(get_profiles()) + #wsock.send(get_profiles()) elif msgdict.get("cmd") == "PUT": log.info("PUT command received") - profile_obj = msgdict.get("profile") - # force = msgdict.get('force', False) + profile_obj = msgdict.get('profile') + #force = msgdict.get('force', False) force = True if profile_obj: - # del msgdict["cmd"] + #del msgdict["cmd"] if save_profile(profile_obj, force): msgdict["resp"] = "OK" else: @@ -223,7 +215,7 @@ def handle_storage(): log.info("websocket (storage) closed") -@app.route("/config") +@app.route('/config') def handle_config(): wsock = get_websocket_from_request() log.info("websocket (config) opened") @@ -236,7 +228,7 @@ def handle_config(): log.info("websocket (config) closed") -@app.route("/status") +@app.route('/status') def handle_status(): wsock = get_websocket_from_request() ovenWatcher.add_observer(wsock) @@ -253,39 +245,31 @@ def handle_status(): def get_profiles(): try: profile_files = os.listdir(profile_path) - profile_files.sort() except: profile_files = [] profiles = [] for filename in profile_files: - if filename.startswith("._"): - pass - else: - if filename.endswith(".json"): - with open(os.path.join(profile_path, filename), "r") as f: - profiles.append(json.load(f)) - else: - pass + with open(os.path.join(profile_path, filename), 'r') as f: + profiles.append(json.load(f)) return json.dumps(profiles) def save_profile(profile, force=False): profile_json = json.dumps(profile) - filename = profile["name"] + ".json" + filename = profile['name']+".json" filepath = os.path.join(profile_path, filename) if not force and os.path.exists(filepath): log.error("Could not write, %s already exists" % filepath) return False - with open(filepath, "w+") as f: + with open(filepath, 'w+') as f: f.write(profile_json) f.close() log.info("Wrote %s" % filepath) return True - def delete_profile(profile): profile_json = json.dumps(profile) - filename = profile["name"] + ".json" + filename = profile['name']+".json" filepath = os.path.join(profile_path, filename) os.remove(filepath) log.info("Deleted %s" % filepath) @@ -293,15 +277,11 @@ def delete_profile(profile): def get_config(): - return json.dumps( - { - "temp_scale": config.temp_scale, - "time_scale_slope": config.time_scale_slope, - "time_scale_profile": config.time_scale_profile, - "kwh_rate": config.kwh_rate, - "currency_type": config.currency_type, - } - ) + return json.dumps({"temp_scale": config.temp_scale, + "time_scale_slope": config.time_scale_slope, + "time_scale_profile": config.time_scale_profile, + "kwh_rate": config.kwh_rate, + "currency_type": config.currency_type}) def main(): @@ -309,7 +289,8 @@ def main(): port = config.listening_port log.info("listening on %s:%d" % (ip, port)) - server = WSGIServer((ip, port), app, handler_class=WebSocketHandler) + server = WSGIServer((ip, port), app, + handler_class=WebSocketHandler) server.serve_forever()