def get_temp_and_humidity_history(device_uuid): humidity_array = [] temp_array = [] result_json = {"RH": humidity_array, "temp": temp_array} if device_uuid is None or device_uuid is "None": return result_json temp_vals = datastore.get_device_data(datastore.DS_temp_KEY, device_uuid, count=1000) rh_vals = datastore.get_device_data(datastore.DS_rh_KEY, device_uuid, count=1000) if 0 == len(temp_vals) or 0 == len(rh_vals): return result_json for val in temp_vals: ts = utils.bytes_to_string(val["timestamp"]) value = utils.bytes_to_string(val["value"]) result_json["temp"].append({"value": value, "time": ts}) for val in rh_vals: ts = utils.bytes_to_string(val["timestamp"]) value = utils.bytes_to_string(val["value"]) result_json["RH"].append({"value": value, "time": ts}) return result_json
def get_temp_and_humidity_history(device_uuid): humidity_array = [] temp_array = [] result_json = {'RH': humidity_array, 'temp': temp_array} if device_uuid is None or device_uuid is 'None': return result_json # First, try to get the data from the datastore... device_data = get_by_key_from_DS(DS_device_data_KEY, device_uuid) if device_data is None or \ (DS_temp_KEY not in device_data and \ DS_rh_KEY not in device_data): # If we didn't find any data in the DS, look in BQ... return get_temp_and_humidity_history_from_BQ(device_uuid) # process the vars list from the DS into the same format as BQ # Get temp values if DS_temp_KEY in device_data: valuesList = device_data[DS_temp_KEY] for val in valuesList: ts = utils.bytes_to_string(val['timestamp']) value = utils.bytes_to_string(val['value']) result_json["temp"].append({'value': value, 'time': ts}) # Get RH values if DS_rh_KEY in device_data: valuesList = device_data[DS_rh_KEY] for val in valuesList: ts = utils.bytes_to_string(val['timestamp']) value = utils.bytes_to_string(val['value']) result_json["RH"].append({'value': value, 'time': ts}) return result_json
def get_latest_val_from_DeviceData(dd, key): if dd is None or key not in dd: return '', '' valsList = dd.get(key, []) # list of values # return latest value and timestamp value = valsList[0].get('value', b'') value = utils.bytes_to_string(value) # could be bytes, so decode ts = valsList[0].get('timestamp', b'') ts = utils.bytes_to_string(ts) # could be bytes, so decode return value, ts
def get_co2_history(device_uuid): if device_uuid is None or device_uuid is "None": return [] co2_vals = datastore.get_device_data(datastore.DS_co2_KEY, device_uuid, count=1000) if 0 == len(co2_vals): return [] results = [] for val in co2_vals: ts = utils.bytes_to_string(val["timestamp"]) value = utils.bytes_to_string(val["value"]) results.append({"value": value, "time": ts}) return results
def get_DeviceData_active_last_hour_count_from_DS(): DS = get_client() if DS is None: return 0 query = DS.query(kind=DS_device_data_KIND) entities = list(query.fetch()) # get all entities count = 0 utc = dt.datetime.utcnow() - dt.timedelta(hours=1) one_hour_ago = utc.strftime('%FT%XZ') for e in entities: # status message are sent every 5 min. status = e.get(DS_status_KEY, [None])[0] #print( e.key.id_or_name ) if status is not None: try: ts = status.get('timestamp', b'') ts = utils.bytes_to_string(ts) if ts > one_hour_ago: count = count + 1 except: pass #<Entity('DeviceData', 'EDU-11A8F684-f4-5e-ab-67-5d-ad') {'status': [<Entity {'timestamp': b'2018-11-16T15:58:07Z', 'value': b'{"timestamp": "2018-11-16T15:58:07Z", "IP": "10.33.136.13", "package_version": "1.0-4", "device_config": "edu-v0.3.0", "status": "OK", "internet_connection": "True", "memory_available": "98M", "disk_available": "945M", "iot_status": "2018-11-16-T15:46:42Z", "iot_received_message_count": 2, "iot_published_message_count": 2, "recipe_percent_complete": 33.199074074074076, "recipe_percent_complete_string": "33.20 %", "recipe_time_remaining_minutes": 28858, "recipe_time_remaining_string": "20 Days 0 Hours 58 Minutes", "recipe_time_elapsed_string": "9 Days 23 Hours 2 Minutes"}', 'name': b'None'}>, return count
def get_co2_history(device_uuid): if device_uuid is None or device_uuid is 'None': return [] # First, try to get the data from the datastore... device_data = get_by_key_from_DS(DS_device_data_KEY, device_uuid) if device_data is None or DS_co2_KEY not in device_data: # If we didn't find any data in the DS, look in BQ... return get_co2_history_from_BQ(device_uuid) # process the vars list from the DS into the same format as BQ results = [] valuesList = device_data[DS_co2_KEY] for val in valuesList: ts = utils.bytes_to_string(val['timestamp']) value = utils.bytes_to_string(val['value']) results.append({'value': value, 'time': ts}) return results
def get_led_panel_history(device_uuid): if device_uuid is None or device_uuid is "None": return [] led_vals = datastore.get_device_data(datastore.DS_led_KEY, device_uuid, count=1000) if 0 == len(led_vals): return [] results = [] for val in led_vals: led_json = utils.bytes_to_string(val["value"]) results.append(led_json) return results
def decode_url(image_entity): url = image_entity.get('URL', '') return utils.bytes_to_string(url)
def get_list_of_device_data_from_DS(): res = {} DS = get_client() if DS is None: return res res['devices'] = [] # list of devices with data from each query = DS.query(kind=DS_devices_KIND) devices = list(query.fetch()) # get all devices for d in devices: device = {} device_uuid = d.get('device_uuid', '') device['device_uuid'] = device_uuid device['device_name'] = d.get('device_name', '') user_uuid = d.get('user_uuid', '') device['user_name'] = user_uuid if 0 != len(user_uuid): user = get_one_from_DS(DS_users_KIND, 'user_uuid', user_uuid) if user is not None: device['user_name'] = user.get('username', 'None') # Get the DeviceData for this device ID dd = None if 0 < len(device_uuid): dd = get_by_key_from_DS(DS_device_data_KIND, device_uuid) device['remote_URL'] = '' device['access_point'] = '' if dd is not None and DS_boot_KEY in dd: boot = dd.get(DS_boot_KEY) # list of boot messages # get latest boot message last_boot = boot[0].get('value') # convert binary into string and then a dict boot_dict = json.loads(utils.bytes_to_string(last_boot)) # the serveo link needs to be lower case remote_URL = boot_dict.get('remote_URL') if remote_URL is not None: remote_URL = remote_URL.lower() device['remote_URL'] = remote_URL # get the AP access_point = boot_dict.get('access_point') if access_point is not None: # extract just the wifi code if access_point.startswith('BeagleBone-'): ap = access_point.split('-') if 2 <= len(ap): access_point = ap[1] device['access_point'] = access_point epoch = '1970-01-01T00:00:00Z' last_message_time = epoch val, ts = get_latest_val_from_DeviceData(dd, DS_rh_KEY) device[DS_rh_KEY] = val if ts > last_message_time: last_message_time = ts val, ts = get_latest_val_from_DeviceData(dd, DS_temp_KEY) device[DS_temp_KEY] = val if ts > last_message_time: last_message_time = ts val, ts = get_latest_val_from_DeviceData(dd, DS_co2_KEY) device[DS_co2_KEY] = val if ts > last_message_time: last_message_time = ts val, ts = get_latest_val_from_DeviceData(dd, DS_h20_ec_KEY) device[DS_h20_ec_KEY] = val if ts > last_message_time: last_message_time = ts val, ts = get_latest_val_from_DeviceData(dd, DS_h20_ph_KEY) device[DS_h20_ph_KEY] = val if ts > last_message_time: last_message_time = ts val, ts = get_latest_val_from_DeviceData(dd, DS_h20_temp_KEY) device[DS_h20_temp_KEY] = val if ts > last_message_time: last_message_time = ts if last_message_time == epoch: last_message_time = 'Never' device['last_message_time'] = last_message_time device['stale'] = get_minutes_since_UTC_timestamp(last_message_time) device['last_image'] = get_latest_image_URL(device_uuid) res['devices'].append(device) res['timestamp'] = dt.datetime.utcnow().strftime('%FT%XZ') return res
def get_list_of_devices_from_DS(): res = {} DS = get_client() if DS is None: return res res['devices'] = [] # list of devices query = DS.query(kind=DS_devices_KIND) devices = list(query.fetch()) # get all devices for d in devices: device = {} rd = d.get('registration_date', None) # web ui reg date if rd is None: device['registration_date'] = '' else: device['registration_date'] = rd.strftime('%FT%XZ') device['device_name'] = d.get('device_name', '') device['device_notes'] = d.get('device_notes', '') device_uuid = d.get('device_uuid', '') device['device_uuid'] = device_uuid user_uuid = d.get('user_uuid', '') device['user_uuid'] = user_uuid device['last_config_send_time'] = 'Never' # in case no IoT device device['last_error_message'] = 'No IoT registration' device['user_name'] = 'None' if 0 != len(user_uuid): user = get_one_from_DS(DS_users_KIND, 'user_uuid', user_uuid) if user is not None: device['user_name'] = user.get('username', 'None') device['remote_URL'] = '' device['access_point'] = '' if 0 < len(device_uuid): dd = get_by_key_from_DS(DS_device_data_KIND, device_uuid) if dd is not None and DS_boot_KEY in dd: boot = dd.get(DS_boot_KEY) # list of boot messages # get latest boot message last_boot = boot[0].get('value') # convert binary into string and then a dict boot_dict = json.loads(utils.bytes_to_string(last_boot)) # the serveo link needs to be lower case remote_URL = boot_dict.get('remote_URL') if remote_URL is not None: remote_URL = remote_URL.lower() device['remote_URL'] = remote_URL # get the AP access_point = boot_dict.get('access_point') if access_point is not None: # extract just the wifi code if access_point.startswith('BeagleBone-'): ap = access_point.split('-') if 2 <= len(ap): access_point = ap[1] device['access_point'] = access_point res['devices'].append(device) res['timestamp'] = dt.datetime.utcnow().strftime('%FT%XZ') return res
def get_all_historical_values(device_uuid, start_timestamp, end_timestamp): print("Getting all historical values") co2 = [] temp = [] RH = [] leaf_count = [] plant_height = [] horticulture_notes = [] if device_uuid is None or device_uuid is "None": print(f"get_all_historical_values: No device_uuid") return temp, RH, co2, leaf_count, plant_height co2_vals = datastore.get_device_data(datastore.DS_co2_KEY, device_uuid, count=1000) temp_vals = datastore.get_device_data(datastore.DS_temp_KEY, device_uuid, count=1000) rh_vals = datastore.get_device_data(datastore.DS_rh_KEY, device_uuid, count=1000) if 0 == len(co2_vals) and 0 == len(temp_vals) and 0 == len(rh_vals): print(f"get_all_historical_values: No DeviceData for {device_uuid}") return temp, RH, co2, leaf_count, plant_height # handle None values for date range, in which case we return all start, end = None, None try: start = dt.strptime(start_timestamp, "%Y-%m-%dT%H:%M:%SZ") end = dt.strptime(end_timestamp, "%Y-%m-%dT%H:%M:%SZ") print( f"get_all_historical_values: using date range: {str(start)} to {str(end)}" ) except: start, end = None, None print(f"get_all_historical_values: no date range") # make sure the time column is the first entry in each dict for val in co2_vals: ts_str = utils.bytes_to_string(val["timestamp"]) ts = dt.strptime(ts_str, "%Y-%m-%dT%H:%M:%SZ") if start is not None and end is not None and (ts < start or ts > end): continue # this value is not in our start / end range value = utils.bytes_to_string(val["value"]) co2.append({"time": ts_str, "value": value}) for val in temp_vals: ts_str = utils.bytes_to_string(val["timestamp"]) ts = dt.strptime(ts_str, "%Y-%m-%dT%H:%M:%SZ") if start is not None and end is not None and (ts < start or ts > end): continue # this value is not in our start / end range value = utils.bytes_to_string(val["value"]) temp.append({"time": ts_str, "value": value}) for val in rh_vals: ts_str = utils.bytes_to_string(val["timestamp"]) ts = dt.strptime(ts_str, "%Y-%m-%dT%H:%M:%SZ") if start is not None and end is not None and (ts < start or ts > end): continue # this value is not in our start / end range value = utils.bytes_to_string(val["value"]) RH.append({"time": ts_str, "value": value}) # get horticulture measurements: leaf_count, plant_height query = datastore.get_client().query(kind="DailyHorticultureLog") query.add_filter("device_uuid", "=", device_uuid) query_result = list(query.fetch()) if 0 < len(query_result): for result in query_result: ts_str = str(utils.bytes_to_string(result["submitted_at"])) ts_str = ts_str.split(".")[0] try: ts = dt.strptime(ts_str, "%Y-%m-%dT%H:%M:%SZ") if start is not None and end is not None and (ts < start or ts > end): continue # this value is not in our start / end range if "leaf_count" in result: leaf_count.append({ "time": ts_str, "value": result["leaf_count"] }) if "plant_height" in result: plant_height.append({ "time": ts_str, "value": result["plant_height"] }) if "horticulture_notes" in result: horticulture_notes.append({ "time": ts_str, "value": result["horticulture_notes"] }) except: print("Invalid string format:", ts_str) continue return temp, RH, co2, leaf_count, plant_height, horticulture_notes
def get_current_device_status(): """Get the current status of a device. .. :quickref: Device; Get device status :reqheader Accept: application/json :<json string user_token: User Token returned from the /login API. :<json string device_uuid: UUID of device to apply recipe to **Example response**: .. sourcecode:: json { "progress": 0.0, "age_in_days": 0, "wifi_status": "N/A for this device", "current_temp": "N/A for this device", "runtime": 0, "response_code": 200 } """ received_form_response = json.loads(request.data.decode("utf-8")) user_token = received_form_response.get("user_token") device_uuid = received_form_response.get("device_uuid", None) if user_token is None or device_uuid is None: return error_response(message="Access denied.") device_data = datastore.get_device_data_from_DS(device_uuid) # TODO: should get this from the new DeviceData.runs list. # days, runtime = get_runtime_description(current_recipe['date_applied']) days, runtime = 0, 0 result_json = { "progress": 0.0, "age_in_days": 0, "wifi_status": "N/A for this device", "current_temp": "N/A for this device", "runtime": 0, } print('device_data', device_data) if device_data is not None: timestamp = device_data.get("timestamp") # .decode() timestamp = utils.bytes_to_string(timestamp) timenow = str(datetime.now()) fmt1 = "%Y-%m-%d %H:%M:%S.%f" fmt2 = "%Y-%m-%dT%H:%M:%SZ" t1 = datetime.strptime(timenow, fmt1) t2 = datetime.strptime(timestamp, fmt2) _, time_minutes, _ = convert_timedelta(t1 - t2) if time_minutes > 5: wifi_status = "Disconnected" else: wifi_status = "Connected" if device_data.get("air_temp"): result_json["current_temp"] = "%s C" % ( (device_data["air_temp"])) # .decode()) result_json["progress"] = int( round( float( device_data.get("percent_complete") if device_data. get("percent_complete") else "0.0")) * 100.0) result_json["wifi_status"] = wifi_status result_json["runtime"] = runtime result_json["age_in_days"] = days return success_response(results=result_json)
def read_config(self) -> dict: entity = datastore.get_by_key_from_DS(self.__kind, self.__key) json_config = entity[self.__key] config_dict = json.loads(utils.bytes_to_string(json_config)) return config_dict