kopia lustrzana https://github.com/jbruce12000/kiln-controller
				
				
				
			
		
			
				
	
	
		
			221 wiersze
		
	
	
		
			6.6 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
			
		
		
	
	
			221 wiersze
		
	
	
		
			6.6 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
#!/usr/bin/env python2
 | 
						|
 | 
						|
import os
 | 
						|
import sys
 | 
						|
import logging
 | 
						|
import json
 | 
						|
 | 
						|
import bottle
 | 
						|
import gevent
 | 
						|
import geventwebsocket
 | 
						|
from gevent.pywsgi import WSGIServer
 | 
						|
from geventwebsocket.handler import WebSocketHandler
 | 
						|
 | 
						|
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."
 | 
						|
    exit(1)
 | 
						|
 | 
						|
logging.basicConfig(level=config.log_level, format=config.log_format)
 | 
						|
log = logging.getLogger("kiln-controller")
 | 
						|
log.info("Starting kill controller")
 | 
						|
 | 
						|
script_dir = os.path.dirname(os.path.realpath(__file__))
 | 
						|
sys.path.insert(0, script_dir + '/lib/')
 | 
						|
profile_path = os.path.join(script_dir, "storage", "profiles")
 | 
						|
 | 
						|
from oven import Oven, Profile
 | 
						|
from ovenWatcher import OvenWatcher
 | 
						|
 | 
						|
app = bottle.Bottle()
 | 
						|
oven = Oven()
 | 
						|
ovenWatcher = OvenWatcher(oven)
 | 
						|
 | 
						|
 | 
						|
@app.route('/')
 | 
						|
def index():
 | 
						|
    return bottle.redirect('/picoreflow/index.html')
 | 
						|
 | 
						|
 | 
						|
@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"))
 | 
						|
 | 
						|
 | 
						|
def get_websocket_from_request():
 | 
						|
    env = bottle.request.environ
 | 
						|
    wsock = env.get('wsgi.websocket')
 | 
						|
    if not wsock:
 | 
						|
        abort(400, 'Expected WebSocket request.')
 | 
						|
    return wsock
 | 
						|
 | 
						|
 | 
						|
@app.route('/control')
 | 
						|
def handle_control():
 | 
						|
    wsock = get_websocket_from_request()
 | 
						|
    log.info("websocket (control) opened")
 | 
						|
    while True:
 | 
						|
        try:
 | 
						|
            message = wsock.receive()
 | 
						|
            log.info("Received (control): %s" % message)
 | 
						|
            msgdict = json.loads(message)
 | 
						|
            if msgdict.get("cmd") == "RUN":
 | 
						|
                log.info("RUN command received")
 | 
						|
                profile_obj = msgdict.get('profile')
 | 
						|
                if profile_obj:
 | 
						|
                    profile_json = json.dumps(profile_obj)
 | 
						|
                    profile = Profile(profile_json)
 | 
						|
                oven.run_profile(profile)
 | 
						|
                ovenWatcher.record(profile)
 | 
						|
            elif msgdict.get("cmd") == "SIMULATE":
 | 
						|
                log.info("SIMULATE command received")
 | 
						|
                #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)
 | 
						|
            elif msgdict.get("cmd") == "STOP":
 | 
						|
                log.info("Stop command received")
 | 
						|
                oven.abort_run()
 | 
						|
        except WebSocketError:
 | 
						|
            break
 | 
						|
    log.info("websocket (control) closed")
 | 
						|
 | 
						|
 | 
						|
@app.route('/storage')
 | 
						|
def handle_storage():
 | 
						|
    wsock = get_websocket_from_request()
 | 
						|
    log.info("websocket (storage) opened")
 | 
						|
    while True:
 | 
						|
        try:
 | 
						|
            message = wsock.receive()
 | 
						|
            if not message:
 | 
						|
                break
 | 
						|
            log.debug("websocket (storage) received: %s" % message)
 | 
						|
 | 
						|
            try:
 | 
						|
                msgdict = json.loads(message)
 | 
						|
            except:
 | 
						|
                msgdict = {}
 | 
						|
 | 
						|
            if message == "GET":
 | 
						|
                log.info("GET command recived")
 | 
						|
                wsock.send(get_profiles())
 | 
						|
            elif msgdict.get("cmd") == "DELETE":
 | 
						|
                log.info("DELETE command received")
 | 
						|
                profile_obj = msgdict.get('profile')
 | 
						|
                if delete_profile(profile_obj):
 | 
						|
                  msgdict["resp"] = "OK"
 | 
						|
                wsock.send(json.dumps(msgdict))
 | 
						|
                #wsock.send(get_profiles())
 | 
						|
            elif msgdict.get("cmd") == "PUT":
 | 
						|
                log.info("PUT command received")
 | 
						|
                profile_obj = msgdict.get('profile')
 | 
						|
                #force = msgdict.get('force', False)
 | 
						|
                force = True
 | 
						|
                if profile_obj:
 | 
						|
                    #del msgdict["cmd"]
 | 
						|
                    if save_profile(profile_obj, force):
 | 
						|
                        msgdict["resp"] = "OK"
 | 
						|
                    else:
 | 
						|
                        msgdict["resp"] = "FAIL"
 | 
						|
                    log.debug("websocket (storage) sent: %s" % message)
 | 
						|
 | 
						|
                    wsock.send(json.dumps(msgdict))
 | 
						|
                    wsock.send(get_profiles())
 | 
						|
        except WebSocketError:
 | 
						|
            break
 | 
						|
    log.info("websocket (storage) closed")
 | 
						|
 | 
						|
 | 
						|
@app.route('/config')
 | 
						|
def handle_config():
 | 
						|
    wsock = get_websocket_from_request()
 | 
						|
    log.info("websocket (config) opened")
 | 
						|
    while True:
 | 
						|
        try:
 | 
						|
            message = wsock.receive()
 | 
						|
            wsock.send(get_config())
 | 
						|
        except WebSocketError:
 | 
						|
            break
 | 
						|
    log.info("websocket (config) closed")
 | 
						|
 | 
						|
 | 
						|
@app.route('/status')
 | 
						|
def handle_status():
 | 
						|
    wsock = get_websocket_from_request()
 | 
						|
    ovenWatcher.add_observer(wsock)
 | 
						|
    log.info("websocket (status) opened")
 | 
						|
    while True:
 | 
						|
        try:
 | 
						|
            message = wsock.receive()
 | 
						|
            wsock.send("Your message was: %r" % message)
 | 
						|
        except WebSocketError:
 | 
						|
            break
 | 
						|
    log.info("websocket (status) closed")
 | 
						|
 | 
						|
 | 
						|
def get_profiles():
 | 
						|
    try:
 | 
						|
        profile_files = os.listdir(profile_path)
 | 
						|
    except:
 | 
						|
        profile_files = []
 | 
						|
    profiles = []
 | 
						|
    for filename in profile_files:
 | 
						|
        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"
 | 
						|
    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:
 | 
						|
        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"
 | 
						|
    filepath = os.path.join(profile_path, filename)
 | 
						|
    os.remove(filepath)
 | 
						|
    log.info("Deleted %s" % filepath)
 | 
						|
    return True
 | 
						|
 | 
						|
 | 
						|
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})    
 | 
						|
 | 
						|
 | 
						|
def main():
 | 
						|
    ip = config.listening_ip
 | 
						|
    port = config.listening_port
 | 
						|
    log.info("listening on %s:%d" % (ip, port))
 | 
						|
 | 
						|
    server = WSGIServer((ip, port), app,
 | 
						|
                        handler_class=WebSocketHandler)
 | 
						|
    server.serve_forever()
 | 
						|
 | 
						|
 | 
						|
if __name__ == "__main__":
 | 
						|
    main()
 |