def testNoDataAlarm(self): self.mia_alarm = Rule.Create(self.e) self.mia_alarm.Update(name="No Data", sensortype_id=self.spedometer.key().id(), column="speed", trigger=RULE.NO_DATA, duration=5000) # No data for > 5s self.mia_alarm.put() self.process = ProcessTask.Create(self.e) self.process.Update(spec=None, rule_ids=[self.mia_alarm.key().id()]) self.process.put() # Apply our process to our sensor self.sp = SensorProcessTask.Create(self.e, self.process, self.vehicle_1) self.sp.dt_last_run = datetime.now() - timedelta(minutes=2) self.sp.put() self.__runProcessing() # Process last 2 minutes, with no new data, fires alarm alarms = Alarm.Fetch(self.vehicle_1, self.mia_alarm) # self.assertEqual(len(alarms), 1) batch_1 = {'speed': [1, 1, 1, 1, 1]} self.__createNewRecords(batch_1, interval_secs=3) self.__runProcessing() # We get data every 3 seconds, so 5-second no-data alarm doesn't fire alarms = Alarm.Fetch(self.vehicle_1, self.mia_alarm) self.assertEqual(len(alarms), 0)
def testAlarmWithPayment(self): # Create smartphone report sensor self.smartphone_sensor_type = SensorType.Create(self.e) schema = {'agreement': {'unit': '1-5 scale'}} self.smartphone_sensor_type.Update(name="Report Sensor", schema=json.dumps(schema)) self.smartphone_sensor_type.put() self.smartphone_sensor = Sensor.Create( self.e, "1000", self.smartphone_sensor_type.key().id()) self.smartphone_sensor.Update( sensortype_id=self.smartphone_sensor_type.key().id(), name="Smartphone Reports 1", contacts={"user": self.owner.key().id()}) self.smartphone_sensor.put() # Create smartphone report rule with payment on any report PMNT_AMOUNT = 10.0 self.any_report_rule = Rule.Create(self.e) self.any_report_rule.Update( name="Any Report", sensortype_id=self.smartphone_sensor_type.key().id(), column="agreement", trigger=RULE.ANY_DATA, payment_contacts=["user"], payment_amount=PMNT_AMOUNT, consecutive_limit=RULE. ANY, # Deactivate immediately (should be == 1) duration=0) self.any_report_rule.put() self.assertTrue(self.any_report_rule.payments_enabled()) self.process = ProcessTask.Create(self.e) self.process.Update(rule_ids=[self.any_report_rule.key().id()]) self.process.put() # Apply our process to our sensor self.sp = SensorProcessTask.Create(self.e, self.process, self.smartphone_sensor) self.sp.put() BATCH_SIZE = 3 BATCH_1 = { 'agreement': [random.randint(1, 5) for x in range(BATCH_SIZE)], } self.__createNewRecords(BATCH_1, first_dt=datetime.now(), sensor=self.smartphone_sensor) self.__runProcessing() # This batch should have fired 3 alarms for any report, and created # 3 payments. pmnts = Payment.Fetch(self.owner) self.assertEqual(len(pmnts), 3) total_payments = BATCH_SIZE * PMNT_AMOUNT self.assertEqual(total_payments, sum([p.amount for p in pmnts]))
def testGeoFenceAlarm(self): self.geosensor = SensorType.Create(self.e) schema = { 'location': { 'unit': 'deg', 'label': "Location", 'role': [COLUMN.LOCATION], 'type': 'latlng' } } self.geosensor.Update(name="Geo Sensor", schema=json.dumps(schema)) self.geosensor.put() # Create off route alarm self.offroute_alarm = Rule.Create(self.e) self.offroute_alarm.Update(name="Off Route", sensortype_id=self.spedometer.key().id(), column="location", trigger=RULE.GEOFENCE_OUT, value_complex=json.dumps(DUMMY_GEOFENCE)) self.offroute_alarm.put() self.process = ProcessTask.Create(self.e) self.process.Update(rule_ids=[self.offroute_alarm.key().id()]) self.process.put() self.vehicle_2 = Sensor.Create(self.e, TEST_SENSOR_ID, self.geosensor.key().id()) self.vehicle_2.Update(name="Vehicle Sensor 2") # Apply our process to our sensor self.sp = SensorProcessTask.Create(self.e, self.process, self.vehicle_2) self.sp.put() # Process 8 location datapoints (3 in bounds, 3 out, 2 back in) BATCH_1 = { 'location': ["%s,%s" % (coord[0], coord[1]) for coord in ROUTE_DIVERSION] } self.__createNewRecords(BATCH_1, first_dt=datetime.now() - timedelta(minutes=20), interval_secs=30) self.__runProcessing() # Confirm off-route alarm fired upon datapoint 4, and deactivates on 7 (back in fence) alarms = Alarm.Fetch(self.vehicle_2, self.offroute_alarm) self.assertEqual(len(alarms), 1) a = alarms[0] first_record_in_alarm = a.first_record self.assertEqual(a.duration().seconds, 60) # 3 datapoints, 30 second gap oob_record = ROUTE_DIVERSION[3] self.assertEqual(first_record_in_alarm.columnValue('location'), "%s,%s" % (oob_record[0], oob_record[1]))
def setUp(self): self.set_application(tst_app) self.setup_testbed() self.init_datastore_stub() self.init_memcache_stub() self.init_taskqueue_stub() self.init_mail_stub() self.register_search_api_stub() self.init_urlfetch_stub() self.init_modules_stub() # Create enterprise, sensortype and sensor self.e = Enterprise.Create() self.e.Update(name="Test Ent", timezone="Africa/Nairobi") self.e.put() self.owner = User.Create(self.e, phone=OWNER_NUM, notify=False) self.owner.Update(name=OWNER_NAME, currency="KES") self.owner.put() self.spedometer = SensorType.Create(self.e) schema = { 'speed': { 'unit': 'kph' }, 'bearing': { 'unit': 'deg' }, 'location': { 'unit': 'degrees' }, 'hard_braking': { 'unit': 'boolean' } } self.spedometer.Update(name="Geo Sensor", schema=json.dumps(schema)) self.spedometer.put() self.vehicle_1 = Sensor.Create(self.e, TEST_SENSOR_ID, self.spedometer.key().id()) self.vehicle_1.Update(sensortype_id=self.spedometer.key().id(), name="Vehicle Sensor 1", contacts={"owner": self.owner.key().id()}) self.vehicle_1.put() # Create alarm self.speeding_alarm = Rule.Create(self.e) self.speeding_alarm.Update(name="Speeding", sensortype_id=self.spedometer.key().id(), column="speed", trigger=RULE.CEILING, value2=80.0, alert_contacts=["owner"], alert_message=SPEEDING_ALERT_MESSAGE, duration=0) self.speeding_alarm.put()
def testAlarmPeriodLimit(self): # Create hard braking (boolean) alarm self.brake_rule = Rule.Create(self.e) self.brake_rule.Update(name="Braking", sensortype_id=self.spedometer.key().id(), column="hard_braking", trigger=RULE.CEILING, consecutive_limit=RULE.ANY, value2=0.0, alert_contacts=["owner"], plimit_type=RULE.HOUR, plimit=1) # 1 alarm each hour self.brake_rule.put() self.process = ProcessTask.Create(self.e) self.process.Update(rule_ids=[self.brake_rule.key().id()]) self.process.put() # Apply our process to our sensor self.sp = SensorProcessTask.Create(self.e, self.process, self.vehicle_1) self.sp.put() # Batch 1 creates 1 alarm in 11am window, skips second alarm # and then creates another alarm in 12pm window. start = datetime(2016, 1, 1, 11, 57) # 11:57am 2016-01-01 BATCH_1 = { # v below should alarm, s should skip (already 1 in same period) # | is passing an hour marker (12pm) # v s | v 'hard_braking': [0, 1, 1, 0, 1] } self.__createNewRecords(BATCH_1, first_dt=start, interval_secs=60) self.__runProcessing() alarms = Alarm.Fetch(self.vehicle_1, self.brake_rule) self.assertEqual(len(alarms), 2) # 1 in each hour last_alarm = alarms[-1] self.assertTrue(last_alarm.dt_start.hour, 12) self.assertTrue(last_alarm.dt_start.minute, 1) # Batch 2 fetches the prior 12pm window alarm, and fails to create # second alarm. start = datetime(2016, 1, 1, 12, 2) # 12:02pm 2016-01-01 BATCH_2 = { # s s 'hard_braking': [0, 0, 1, 0, 1] } self.__createNewRecords(BATCH_2, first_dt=start, interval_secs=60) self.__runProcessing() alarms = Alarm.Fetch(self.vehicle_1, self.brake_rule) self.assertEqual(len(alarms), 2) # still 2, no new alarms created
def testAlarmBuffer(self): # Create hard braking (boolean) alarm self.brake_alarm = Rule.Create(self.e) self.brake_alarm.Update( name="Braking", sensortype_id=self.spedometer.key().id(), column="hard_braking", trigger=RULE.CEILING, value2=0.0, alert_contacts=["owner"], buffer=30000, # 30 s duration=0) self.brake_alarm.put() self.process = ProcessTask.Create(self.e) self.process.Update(rule_ids=[self.brake_alarm.key().id()]) self.process.put() # Apply our process to our sensor self.sp = SensorProcessTask.Create(self.e, self.process, self.vehicle_1) self.sp.put() BATCH_1 = { # v below should alarm, s are skipped since they fall within 30s buffer # v s s s v 'hard_braking': [0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0] # Alternative boolean alarms } self.__createNewRecords(BATCH_1, first_dt=datetime.now() - timedelta(minutes=5), interval_secs=5) self.__runProcessing() # Confirm braking alarms (2) alarms = Alarm.Fetch(self.vehicle_1, self.brake_alarm) self.assertEqual(len(alarms), 2)
def testGeoRadiusAlarm(self): # Create in radius alarm self.in_radius_alarm = Rule.Create(self.e) self.in_radius_alarm.Update( name="In Town", sensortype_id=self.tracker.key().id(), column="location", trigger=RULE.GEORADIUS_IN, value2=RADIUS, # m value_complex=json.dumps(RADIUS_CENTER), alert_contacts=["owner"], consecutive_limit=RULE.DISABLED, duration=0) self.in_radius_alarm.put() self.process = ProcessTask.Create(self.e) self.process.Update(rule_ids=[self.in_radius_alarm.key().id()]) self.process.put() self.vehicle_2 = Sensor.Create(self.e, TEST_SENSOR_ID, self.tracker.key().id()) self.vehicle_2.Update(name="Vehicle Sensor 2") # Apply our process to our sensor self.sp = SensorProcessTask.Create(self.e, self.process, self.vehicle_2) self.sp.put() INTERVAL_SECS = 4 test_data_start = datetime.now() - timedelta(minutes=20) # Process first data points entering radius BATCH_1 = { 'location': ["%s,%s" % (coord[0], coord[1]) for coord in ENTERS_RADIUS] } last_record = self.__createNewRecords(BATCH_1, first_dt=test_data_start, interval_secs=INTERVAL_SECS) self.__runProcessing() # Confirm in-radius alarm fired upon datapoint 4... alarms = Alarm.Fetch(self.vehicle_2, self.in_radius_alarm) self.assertEqual(len(alarms), 1) a = alarms[0] # Process second batch of data points exiting radius BATCH_2 = { 'location': ["%s,%s" % (coord[0], coord[1]) for coord in EXITS_RADIUS] } self.__createNewRecords(BATCH_2, interval_secs=INTERVAL_SECS) self.__runProcessing() # Confirm we still just have the single alarm record alarms = Alarm.Fetch(self.vehicle_2, self.in_radius_alarm) self.assertEqual(len(alarms), 1) a = alarms[0] duration_td = a.duration() self.assertIsNotNone(duration_td) # 3 datapoints in radius print a.json()
def setUp(self): self.set_application(tst_app) self.setup_testbed() self.init_datastore_stub() self.init_memcache_stub() self.init_taskqueue_stub() self.init_mail_stub() self.register_search_api_stub() self.init_urlfetch_stub() self.init_modules_stub() # Create enterprise, sensortype and sensor self.e = Enterprise.Create() self.e.Update(name="Test Ent", timezone="Africa/Nairobi") self.e.put() self.tracker = SensorType.Create(self.e) schema = { 'speed': { 'unit': 'kph' }, 'ign_on': { 'unit': 'boolean' }, 'ign_off': { 'unit': 'boolean' } } self.tracker.Update(name="Tracker Sensor", schema=json.dumps(schema)) self.tracker.put() self.vehicle_1 = Sensor.Create(self.e, TEST_SENSOR_ID, self.tracker.key().id()) self.vehicle_1.Update( sensortype_id=self.tracker.key().id(), name="Vehicle Sensor 1" ) self.vehicle_1.put() # Create alarm self.ign_on_alarm = Rule.Create(self.e) self.ign_on_alarm.Update( name="Ignition On", sensortype_id=self.tracker.key().id(), column="ign_on", trigger=RULE.CEILING, value2=0, consecutive_limit=-1, duration=0) self.ign_on_alarm.put() self.ign_off_alarm = Rule.Create(self.e) self.ign_off_alarm.Update( name="Ignition Off", sensortype_id=self.tracker.key().id(), column="ign_off", trigger=RULE.CEILING, value2=0, consecutive_limit=-1, duration=0, spec=json.dumps({'processers': [ { 'analysis_key_pattern': ANALYSIS_KEY_PATTERN, 'expr': '. + SINCE(LAST_ALARM(%d)) / 1000' % self.ign_on_alarm.key().id(), 'column': 'on_secs' } ]})) self.ign_off_alarm.put()