From 5073c388007693b4e5a5fa118f8e649176285da4 Mon Sep 17 00:00:00 2001 From: Todd <66568100+BuckoWA@users.noreply.github.com> Date: Wed, 27 Jan 2021 11:39:25 -0800 Subject: [PATCH] Add START/STOP Button to iSpindel graphing sessions (#219) * Adds iSpindel support for the server. iSpindel Server Address should be configured for picobrew.com and Path/URI to /API/iSpindel * Update session_parser.py Removed unnecessary comment * Update config.example.yaml Fixed typo * Update config.py Fixed all caps on ZYMATIC * Updating to latest master from chiefwgms * Minor fixes * Update routes_frontend for latest files * Fxing iSpindel_graph_socketio javascript call since it exists in index.html * Updating the iSpindel file error handling to be similar to ferm. Fixing str type declaration on iSpindle ID. * Update model.py * Update model.py * Adding iSpindel START/STOP button * Adding iSpindel START/STOP to server * Updated iSpindel START/STOP PR with changes based on review * Update app/main/routes_frontend.py Co-authored-by: Pete --- app/main/model.py | 1 + app/main/routes_frontend.py | 7 ++- app/main/routes_iSpindel_api.py | 58 +++++++++++++----------- app/main/routes_picoferm_api.py | 5 +- app/main/session_parser.py | 14 +++--- app/static/js/iSpindel_graph.js | 2 +- app/static/js/iSpindel_graph_socketio.js | 2 +- app/static/js/index.js | 52 ++++++++++++++++++++- app/templates/index.html | 19 ++++++++ 9 files changed, 121 insertions(+), 39 deletions(-) diff --git a/app/main/model.py b/app/main/model.py index 599ae25..f52a711 100644 --- a/app/main/model.py +++ b/app/main/model.py @@ -123,6 +123,7 @@ def __init__(self): self.file = None self.filepath = None self.alias = '' + self.active = False self.uninit = True self.voltage = '-' self.start_time = None diff --git a/app/main/routes_frontend.py b/app/main/routes_frontend.py index 29d9583..5b1a86f 100644 --- a/app/main/routes_frontend.py +++ b/app/main/routes_frontend.py @@ -31,6 +31,7 @@ def index(): iSpindel_sessions=load_active_iSpindel_sessions()) + @main.route('/brew_history') def brew_history(): return render_template_with_defaults('brew_history.html', sessions=load_brew_sessions(), invalid=get_invalid_sessions('brew')) @@ -173,6 +174,8 @@ def update_device_session(uid, session_type): update = request.get_json() if session_type == 'ferm': session = active_ferm_sessions[uid] + elif session_type == 'iSpindel': + session = active_iSpindel_sessions[uid] if update['active'] == False: session.active = False @@ -180,7 +183,7 @@ def update_device_session(uid, session_type): session.file.seek(0, os.SEEK_END) if session.file.tell() > 0: # mark for completion and archive session file - session.file.seek(session.file.tell() - 1, os.SEEK_SET) # Remove trailing , from last data set + session.file.seek(session.file.tell() - 1, os.SEEK_SET) # Remove trailing comma from last data set session.file.write('\n]') session.cleanup() else: @@ -514,6 +517,8 @@ def load_active_iSpindel_sessions(): iSpindel_sessions = [] for uid in active_iSpindel_sessions: iSpindel_sessions.append({'alias': active_iSpindel_sessions[uid].alias, + 'uid' : uid, + 'active': active_iSpindel_sessions[uid].active, 'graph': get_iSpindel_graph_data(uid, active_iSpindel_sessions[uid].voltage, active_iSpindel_sessions[uid].data)}) return iSpindel_sessions diff --git a/app/main/routes_iSpindel_api.py b/app/main/routes_iSpindel_api.py index 3584e1f..5a03cd6 100644 --- a/app/main/routes_iSpindel_api.py +++ b/app/main/routes_iSpindel_api.py @@ -30,35 +30,41 @@ def process_iSpindel_data(): data = request.get_json() uid = str(data['ID']) - if uid not in active_iSpindel_sessions or active_iSpindel_sessions[uid].uninit: + if (uid not in active_iSpindel_sessions or active_iSpindel_sessions[uid].uninit) and active_iSpindel_sessions[uid].active: create_new_session(uid) - time = ((datetime.utcnow() - datetime(1970, 1, 1)).total_seconds() * 1000) - session_data = [] - log_data = '' - point = { - 'time': time, - 'temp': data['temperature'], - 'gravity': data['gravity'], - } + if active_iSpindel_sessions[uid].active: + time = ((datetime.utcnow() - datetime(1970, 1, 1)).total_seconds() * 1000) + session_data = [] + log_data = '' + point = { + 'time': time, + 'temp': data['temperature'], + 'gravity': data['gravity'], + } - session_data.append(point) - log_data += '\t{},\n'.format(json.dumps(point)) - - active_iSpindel_sessions[uid].data.extend(session_data) - active_iSpindel_sessions[uid].voltage = str(data['battery']) + 'V' - - graph_update = json.dumps({'voltage': data['battery'], 'data': session_data}) - socketio.emit('iSpindel_session_update|{}'.format(data['ID']), graph_update) - - if (datetime.now().date() - active_iSpindel_sessions[uid].start_time.date()).days > 14: - active_iSpindel_sessions[uid].file.write('{}\n]\n'.format(log_data[:-2])) - active_iSpindel_sessions[uid].cleanup() - return ('', 200) + session_data.append(point) + log_data += '\n\t{},'.format(json.dumps(point)) + + active_iSpindel_sessions[uid].data.extend(session_data) + active_iSpindel_sessions[uid].voltage = str(data['battery']) + 'V' + + graph_update = json.dumps({'voltage': data['battery'], 'data': session_data}) + socketio.emit('iSpindel_session_update|{}'.format(data['ID']), graph_update) + + + # end fermentation only when user specifies fermentation is complete + if (active_iSpindel_sessions[uid].uninit == False and active_iSpindel_sessions[uid].active == False): + active_iSpindel_sessions[uid].file.write('{}\n\n]'.format(log_data[:-2])) + active_iSpindel_sessions[uid].cleanup() + return('', 200) + else: + active_iSpindel_sessions[uid].active = True + active_iSpindel_sessions[uid].file.write(log_data) + active_iSpindel_sessions[uid].file.flush() + return('', 200) else: - active_iSpindel_sessions[uid].file.write(log_data) - active_iSpindel_sessions[uid].file.flush() - return ('', 200) + return('', 200) # -------- Utility -------- def create_new_session(uid): @@ -68,4 +74,4 @@ def create_new_session(uid): active_iSpindel_sessions[uid].start_time = datetime.now() # Not now, but X samples * 60*RATE sec ago active_iSpindel_sessions[uid].filepath = iSpindel_active_sessions_path().joinpath('{0}#{1}.json'.format(active_iSpindel_sessions[uid].start_time.strftime('%Y%m%d_%H%M%S'), uid)) active_iSpindel_sessions[uid].file = open(active_iSpindel_sessions[uid].filepath, 'w') - active_iSpindel_sessions[uid].file.write('[\n') + active_iSpindel_sessions[uid].file.write('[') diff --git a/app/main/routes_picoferm_api.py b/app/main/routes_picoferm_api.py index 9b8f2ce..8af9c82 100644 --- a/app/main/routes_picoferm_api.py +++ b/app/main/routes_picoferm_api.py @@ -110,12 +110,13 @@ def process_log_ferm_dataset(args): } session_data.append(point) time = time + time_delta - log_data += '\t{},\n'.format(json.dumps(point)) + log_data += '\n\t{},'.format(json.dumps(point)) active_ferm_sessions[uid].data.extend(session_data) active_ferm_sessions[uid].voltage = str(args['voltage']) + 'V' graph_update = json.dumps({'voltage': args['voltage'], 'data': session_data}) socketio.emit('ferm_session_update|{}'.format(args['uid']), graph_update) + # end fermentation only when user specifies fermentation is complete if active_ferm_sessions[uid].uninit == False and active_ferm_sessions[uid].active == False: active_ferm_sessions[uid].file.write('{}\n\n]'.format(log_data[:-2])) @@ -139,4 +140,4 @@ def create_new_session(uid): active_ferm_sessions[uid].start_time = datetime.now() # Not now, but X samples * 60*RATE sec ago active_ferm_sessions[uid].filepath = ferm_active_sessions_path().joinpath('{0}#{1}.json'.format(active_ferm_sessions[uid].start_time.strftime('%Y%m%d_%H%M%S'), uid)) active_ferm_sessions[uid].file = open(active_ferm_sessions[uid].filepath, 'w') - active_ferm_sessions[uid].file.write('[\n') + active_ferm_sessions[uid].file.write('[') diff --git a/app/main/session_parser.py b/app/main/session_parser.py index 2a3693c..a334681 100644 --- a/app/main/session_parser.py +++ b/app/main/session_parser.py @@ -307,9 +307,9 @@ def restore_active_iSpindel_sessions(): active_iSpindel_session_files = list(iSpindel_active_sessions_path().glob(file_glob_pattern)) for file in active_iSpindel_session_files: # print('DEBUG: restore_active_sessions() found {} as an active session'.format(file)) - ferm_session = load_iSpindel_session(file) + iSpindel_session = load_iSpindel_session(file) # print('DEBUG: restore_active_sessions() {}'.format(ferm_session)) - uid = ferm_session['uid'] + uid = iSpindel_session['uid'] if uid not in active_iSpindel_sessions: active_iSpindel_sessions[uid] = iSpindelSession() @@ -317,17 +317,17 @@ def restore_active_iSpindel_sessions(): session.file = open(file, 'a') session.file.flush() session.filepath = file - session.start_time = datetime.strptime(ferm_session['date'], '%Y%m%d_%H%M%S') + session.start_time = datetime.strptime(iSpindel_session['date'], '%Y%m%d_%H%M%S') + session.active = True session.uninit = False - session.data = ferm_session['data'] - session.graph = ferm_session['graph'] + session.data = iSpindel_session['data'] + session.graph = iSpindel_session['graph'] active_iSpindel_sessions[uid] = session - def restore_active_sessions(): # initialize active sessions during start up restore_active_brew_sessions() restore_active_ferm_sessions() - restore_active_iSpindel_sessions() \ No newline at end of file + restore_active_iSpindel_sessions() diff --git a/app/static/js/iSpindel_graph.js b/app/static/js/iSpindel_graph.js index 1032640..deb516f 100644 --- a/app/static/js/iSpindel_graph.js +++ b/app/static/js/iSpindel_graph.js @@ -49,7 +49,7 @@ Highcharts.chart(graph_data.chart_id, { title: { text: 'Specific Gravity' }, - min: 0.9, + min: 1.0, //max: 1.1 opposite: true }], diff --git a/app/static/js/iSpindel_graph_socketio.js b/app/static/js/iSpindel_graph_socketio.js index 79c477a..d65427c 100644 --- a/app/static/js/iSpindel_graph_socketio.js +++ b/app/static/js/iSpindel_graph_socketio.js @@ -65,7 +65,7 @@ yAxis: [ title: { text: 'Specific Gravity' }, - min: 0.9, + min: 1.0, //max: 1.1 opposite: true }], diff --git a/app/static/js/index.js b/app/static/js/index.js index c1a5b3d..a32d916 100644 --- a/app/static/js/index.js +++ b/app/static/js/index.js @@ -51,4 +51,54 @@ function start_fermentation(uid) { //setTimeout(function () { window.location.href = "pico_recipes";}, 2000); }, }); -} \ No newline at end of file +} + +function start_iSpindel_fermentation(uid) { + var session = {} + session.active = true + $.ajax({ + url: '/device/' + uid + '/sessions/iSpindel', + type: 'PUT', + data: JSON.stringify(session), + dataType: "json", + processData: false, + contentType: "application/json; charset=UTF-8", + success: function (data) { + showAlert("Success!", "success"); + + $("#bstart_" + uid).toggleClass('d-block d-none') + $("#bstop_" + uid).toggleClass('d-block d-none') + // setTimeout(function () { window.location.href = "/"; }, 2000); + }, + error: function (request, status, error) { + showAlert("Error: " + request.responseText, "danger"); + //setTimeout(function () { window.location.href = "pico_recipes";}, 2000); + }, + }); + +}; + + function stop_iSpindel_fermentation(uid) { + var session = {} + session.active = false + $.ajax({ + url: '/device/' + uid + '/sessions/iSpindel', + type: 'PUT', + data: JSON.stringify(session), + dataType: "json", + processData: false, + contentType: "application/json; charset=UTF-8", + success: function (data) { + showAlert("Success!", "success"); + $("#bstart_" + uid).toggleClass('d-block d-none') + $("#bstop_" + uid).toggleClass('d-block d-none') + + // until socketio publishes a new "empty" state just force a refresh (which will clear the graphs) + setTimeout(function () { window.location.href = "/"; }, 2000); + }, + error: function (request, status, error) { + showAlert("Error: " + request.responseText, "danger"); + //setTimeout(function () { window.location.href = "pico_recipes";}, 2000); + }, + }); +} diff --git a/app/templates/index.html b/app/templates/index.html index 33f2e19..616382e 100644 --- a/app/templates/index.html +++ b/app/templates/index.html @@ -84,6 +84,25 @@
{% if iSpindel_session.alias is defined and iSpindel_session.alias|length %}{{iSpindel_session.alias}}{% else %}{{iSpindel_session.graph.chart_id}}{% endif %} + {% if iSpindel_session.active %} + + + {% else %} + + + {% endif %}