def handle(self, *args, **options): for device in PurpleRobotDevice.objects.filter(mute_alerts=False): level = device.last_battery() if level >= 33: cancel_alert(tags='device_last_battery', user_id=device.hash_key) elif level >= 25: log_alert(message='Battery level is less than 33%.', severity=1, tags='device_last_battery', user_id=device.hash_key) else: log_alert(message='Battery level is less than 25%.', severity=2, tags='device_last_battery', user_id=device.hash_key)
def handle(self, *args, **options): for device in PurpleRobotDevice.objects.filter(mute_alerts=False): pending = device.last_pending_count() if pending < 250: cancel_alert(tags='device_pending_files', user_id=device.hash_key) elif pending < 1000: log_alert(message=str(pending) + ' files are awaiting upload.', severity=1, tags='device_pending_files', user_id=device.hash_key) else: log_alert(message=str(pending) + ' files are awaiting upload.', severity=2, tags='device_pending_files', user_id=device.hash_key)
def handle(self, *args, **options): for device in PurpleRobotDevice.objects.all(): payload = PurpleRobotPayload.objects.filter(user_id=device.hash_key).order_by('-added').first() now = timezone.now() if payload == None: log_alert(message='No payloads have been uploaded yet.', severity=1, tags='device_last_upload', user_id=device.hash_key) elif (now - payload.added).total_seconds() > (60 * 60 * 12): log_alert(message='No payloads have been uploaded in the last 12 hours.', severity=2, tags='device_last_upload', user_id=device.hash_key) else: cancel_alert(tags='device_last_upload', user_id=device.hash_key)
def handle(self, *args, **options): if os.access('/tmp/expected_probe_missing_check.lock', os.R_OK): t = os.path.getmtime('/tmp/expected_probe_missing_check.lock') created = datetime.datetime.fromtimestamp(t) if (datetime.datetime.now() - created).total_seconds() > 60 * 60 * 4: print('expected_probe_missing_check: Stale lock - removing...') os.remove('/tmp/expected_probe_missing_check.lock') else: return touch('/tmp/expected_probe_missing_check.lock') start = timezone.now() - datetime.timedelta(days=START_DAYS) for device in PurpleRobotDevice.objects.all().order_by('device_id'): config = None default = PurpleRobotConfiguration.objects.filter(slug='default').first() if device.configuration != None: config = device.configuration elif device.device_group.configuration != None: config = device.device_group.configuration elif config == None: config = default if config == None: log_alert(message='No configuration associated with ' + device.device_id + '.', severity=2, tags=TAG, user_id=device.hash_key) else: config_probes = enabled_probes(loads(config.contents, true='#t', false='#f')) missing_probes = [] for probe in config_probes: found = device.most_recent_reading(probe) if found == None or found.logged < start: missing_probes.append(probe.split('.')[-1]) # if found == None: # print(device.device_id + ' ' + str(config) + ': ' + probe) if len(missing_probes) == 0: cancel_alert(tags=TAG, user_id=device.hash_key) else: log_alert(message='Missing data from ' + str(len(missing_probes)) + ' probe(s). Absent probes: ' + ', '.join(missing_probes), severity=2, tags=TAG, user_id=device.hash_key) os.remove('/tmp/expected_probe_missing_check.lock')
def handle(self, *args, **options): for device in PurpleRobotDevice.objects.filter(mute_alerts=False): for sensor in HARDWARE_SENSORS: last = device.most_recent_reading(sensor) if last != None: hardwares = set() start = timezone.now() - datetime.timedelta(days=3) for reading in PurpleRobotReading.objects.filter(user_id=device.hash_key, probe=sensor, logged__gte=start): payload = json.loads(reading.payload) if 'SENSOR' in payload: hardwares.add(payload['SENSOR']['NAME']) if len(hardwares) < 2: cancel_alert(tags='device_sensor_changed_' + my_slugify(sensor.replace('edu.northwestern.cbits.purple_robot_manager.', '')), user_id=device.hash_key) else: log_alert(message='Multiple hardware sensors observed for ' + sensor.replace('edu.northwestern.cbits.purple_robot_manager.', '') + '. Multiple devices are likely sharing the same user identifier.', severity=2, tags='device_sensor_changed_' + my_slugify(sensor.replace('edu.northwestern.cbits.purple_robot_manager.', '')), user_id=device.hash_key)
def handle(self, *args, **options): for device in PurpleRobotDevice.objects.filter(mute_alerts=False): start = timezone.now() - datetime.timedelta(days=3) mac = None same_mac = True for reading in PurpleRobotReading.objects.filter(user_id=device.hash_key, probe=HARDWARE_PROBE, logged__gte=start): payload = json.loads(reading.payload) if 'WIFI_MAC' in payload: if mac == None: mac = payload['WIFI_MAC'] elif mac != payload['WIFI_MAC']: same_mac = False if same_mac: cancel_alert(tags=TAG, user_id=device.hash_key) else: log_alert(message='Device hardware changed.', severity=2, tags=TAG, user_id=device.hash_key)
def handle(self, *args, **options): play_url = 'https://play.google.com/store/apps/details?id=edu.northwestern.cbits.purple_robot_manager' request = requests.get(play_url) soup = BeautifulSoup(request.text) if soup is not None: changelog = '' changes = soup.findAll('div', {'class': 'recent-change'}) for change in changes: if len(changelog) > 0: changelog += '\n' changelog += change.contents[0].strip() version_html = soup.find('div', {'class': 'content', 'itemprop': 'softwareVersion'}) version = version_html.contents[0].strip() # version_code_html = soup.findAll('button', {'class': 'dropdown-child'}) # for div in version_code_html: # if div.contents[0].strip() == 'Latest Version': # version_code = float(div['data-dropdown-value']) for device in PurpleRobotDevice.objects.filter(mute_alerts=False): device_version = device.config_last_user_agent if device_version is None: log_alert(message='Unable to determine installed version.', severity=1, tags=TAG, user_id=device.hash_key) elif device_version.endswith(str(version)): cancel_alert(tags=TAG, user_id=device.hash_key) else: log_alert(message='Running an older version on Purple Robot: ' + device_version + '.', severity=1, tags=TAG, user_id=device.hash_key) else: print 'Unable to fetch Play Store metadata.'
def handle(self, *args, **options): start = datetime.datetime.now() - datetime.timedelta(days=START_DAYS) for device in PurpleRobotDevice.objects.filter(mute_alerts=False): payload = PurpleRobotPayload.objects.filter(user_id=device.hash_key, added__gte=start).order_by('-added').first() reading = PurpleRobotReading.objects.filter(user_id=device.hash_key, logged__gte=start).order_by('-logged').first() if payload != None and reading != None: diff = payload.added - reading.logged seconds = diff.total_seconds() if seconds < (10 * 60): cancel_alert(tags='device_payload_reading_gap', user_id=device.hash_key) elif seconds < (30 * 60): log_alert(message='{0:.2f}'.format(seconds / 60) + ' minute gap between payload and reading.', severity=1, tags='device_payload_reading_gap', user_id=device.hash_key) else: log_alert(message='{0:.2f}'.format(seconds / 60) + ' minute gap between payload and reading.', severity=2, tags='device_payload_reading_gap', user_id=device.hash_key) elif payload == None: log_alert(message='Unable to determine reading-payload gap. No payloads uploaded in the last week.', severity=2, tags='device_payload_reading_gap', user_id=device.hash_key) elif reading == None: log_alert(message='Unable to determine reading-payload gap. No readings uploaded in the last week.', severity=2, tags='device_payload_reading_gap', user_id=device.hash_key)
def handle(self, *args, **options): if os.access('/tmp/expected_probe_missing_check.lock', os.R_OK): t = os.path.getmtime('/tmp/expected_probe_missing_check.lock') created = datetime.datetime.fromtimestamp(t) if (datetime.datetime.now() - created).total_seconds() > 60 * 60 * 4: print('expected_probe_missing_check: Stale lock - removing...') os.remove('/tmp/expected_probe_missing_check.lock') else: return touch('/tmp/expected_probe_missing_check.lock') start = timezone.now() - datetime.timedelta(days=START_DAYS) for device in PurpleRobotDevice.objects.filter(mute_alerts=False).order_by('device_id'): model = device.last_model() mfgr = device.last_manufacturer() config = None default = PurpleRobotConfiguration.objects.filter(slug='default').first() if device.configuration != None: config = device.configuration elif device.device_group != None and device.device_group.configuration != None: config = device.device_group.configuration elif config == None: config = default if config == None: log_alert(message='No configuration associated with ' + device.device_id + '.', severity=2, tags=TAG, user_id=device.hash_key) else: config_probes = enabled_probes(loads(config.contents, true='#t', false='#f')) missing_probes = [] for probe in config_probes: if can_sense(mfgr, model, probe): found = device.most_recent_reading(probe) if found == None or found.logged < start: missing_probes.append(probe.split('.')[-1]) # if found == None: # print(device.device_id + ' ' + str(config) + ': ' + probe) platform = device.last_platform() if platform != None and platform.startswith('Android 5'): if 'ApplicationLaunchProbe' in missing_probes: missing_probes.remove('ApplicationLaunchProbe') if 'RunningSoftwareProbe' in missing_probes: missing_probes.remove('RunningSoftwareProbe') if len(missing_probes) == 0: cancel_alert(tags=TAG, user_id=device.hash_key) else: missing_probes_str = ', '.join(missing_probes[:4]) if len(missing_probes) > 4: missing_probes_str = missing_probes_str + ', and ' + str(len(missing_probes) - 4) + ' more' log_alert(message='Missing data from ' + str(len(missing_probes)) + ' probe(s). Absent probes: ' + missing_probes_str, severity=2, tags=TAG, user_id=device.hash_key) os.remove('/tmp/expected_probe_missing_check.lock')
def handle(self, *args, **options): for device in PurpleRobotDevice.objects.filter(mute_alerts=False): cancel_alert(tags="device_projected_lifetime", user_id=device.hash_key)