def getTrueQueuePosition(controllerID): """Taking into account priority and acquisition time, determines the true queue position""" estimate = -1 # This will look very similar to the code in the background processing script, but here we'll be counting how many # controllerIDs are ahead of us. con = fountain.db_connect() c = con.cursor() # Check if we're even in the queue. If not, don't return anything. c.execute(queries.CHECK_IF_IM_IN_THE_QUEUE, {'controllerID': controllerID}) r = c.fetchone() if r[0] == 0: print ("Not even in the queue... Controller ID is in position 0 already: " + str(controllerID)) fountain.db_close(con) return -2 c.execute("SELECT queuePosition FROM controlQueue WHERE controllerID=:controllerID", {'controllerID': controllerID}) r = c.fetchone() n = r[0] fountain.db_close(con) return n
def gPatterns(): """Queries the known, enabled patterns.""" con = fountain.db_connect() c = con.cursor() c.execute(queries.QUERY_PATTERNS) res = jsonRows(c) fountain.db_close(con) return res
def gValves(): """Queries the valve descriptions and current valve states.""" con = fountain.db_connect() c = con.cursor() c.execute(queries.QUERY_VALVES) res = jsonRows(c) fountain.db_close(con) return res
def gQueryControl(): """Returns the current control queue.""" con = fountain.db_connect() c = con.cursor() c.execute(queries.QUERY_CONTROL_QUEUE) res = jsonRows(c) fountain.db_close(con) return res
def gValvesID(id): """Queries a specific valve.""" con = fountain.db_connect() c = con.cursor() c.execute(queries.QUERY_VALVE, {'id': id}) res = jsonRow(c) fountain.db_close(con) if res is None or len(res) == 0: return {'success': 'false', 'message': 'Invalid valve ID.'} else: return res
def pReleaseControl(): """Releases the control from a specific controllerID.""" if not checkAPIKey(): return getAPIKeyFail() if not 'controllerID' in request.json.keys(): return {'success': 'false', 'message': 'Must specify controllerID to release.'} con = fountain.db_connect() c = con.cursor() c.execute(queries.RELEASE_CONTROL, {'controllerID': request.json['controllerID']}) fountain.db_close(con) return {'success': 'true', 'message': 'Control released.'}
def checkAPIKey(): """Verifies the requesting API key. These need to be verified on POST requests.""" if not 'apikey' in request.json.keys(): log('No API key with request.') return False con = fountain.db_connect() c = con.cursor() c.execute(queries.QUERY_API_KEY_COUNT, {'key': request.json['apikey']}) # This query is an aggregation (so don't need None check) - the number of matching keys. Should be > 0 (and probably 1). r = c.fetchone() isValid = True if r[0] == 1 else False fountain.db_close(con) return isValid
def pPatternsID(id): """Sets a specific pattern to active.""" if not checkAPIKey(): return getAPIKeyFail() if not 'controllerID' in request.json.keys(): return {'success': 'false', 'message': 'Need to provide controllerID.'} # TODO: check for control # TODO: also disengage other patterns from playing (probably a separate query to run before this one) con = fountain.db_connect() c = con.cursor() c.execute(queries.ENGAGE_PATTERN, {'id': id}) fountain.db_close(con) return {'success': 'true'}
def pValvesID(id): """Updates a single valve based on ID.""" if not checkAPIKey(): return getAPIKeyFail() if not 'controllerID' in request.json.keys(): return {'success': 'false', 'message': 'Must specify controllerID to set valves.'} if not 'spraying' in request.json.keys(): return {'success': 'false', 'message': 'Must specify spraying value to set.'} con = fountain.db_connect() c = con.cursor() # TODO: check control c.execute(queries.SET_VALVE, {'spraying': int(request.json['spraying']), 'id': id}) fountain.db_close(con) return {'success': 'true'}
def getTrueEta(controllerID): """Assuming this controller were to be in position zero, about how long would it have control?""" con = fountain.db_connect() c = con.cursor() ret = -2 for row in c.execute(queries.QUERY_CONTROL_QUEUE): if int(row[0]) != int(controllerID): continue if row[1] > 0: ret = row[1] + row[2] - time() break else: ret = 0 fountain.db_close(con) return ret
def pValves(): """Updates the valves based on a bitmask.""" if not checkAPIKey(): return getAPIKeyFail() if not 'controllerID' in request.json.keys(): return {'success': 'false', 'message': 'Must specify controllerID to set valves.'} if not 'bitmask' in request.json.keys(): return {'success': 'false', 'message': 'Must specify bitmask to set valves.'} bm = int(request.json['bitmask']) # Store bitmask so we can shift it around while reading out the valve states con = fountain.db_connect() c = con.cursor() for i in range(1, constants.NUM_VALVES + 1): val = bm & 1 c.execute(queries.SET_VALVE, {'spraying': val, 'id': i}) bm >>= 1 fountain.db_close(con) return {'success': 'true'}
def pRequestControl(): """ Requests control for an API key and returns a controllerID to the user which they should watch to see when they gain control. """ if not checkAPIKey(): return getAPIKeyFail() if not 'requestedLength' in request.json.keys(): return {'success': 'false', 'Message': 'Must specify requested length for control.'} con = fountain.db_connect() c = con.cursor() c.execute(queries.REQUEST_CONTROL, {'priority': getAPIKeyPriority(), 'ttl': request.json['requestedLength'], 'apikey': request.json['apikey']}) # No concurrency worries with lastrowid, I think, as it's per-connection. controllerID = c.lastrowid fountain.db_close(con) # TODO: Implement variable length TTL part and some additional sanity checks. return {'success': 'true', 'ttl': request.json['requestedLength'], 'controllerID': controllerID}