def test_save_wont_overwrite_newer_value(self): """ Don't save the value/timestamp to datapoint if it is older then the msg stored there. """ field_values = self.default_field_values.copy() # Ensure there is a newer msg available that will prevent saving. expected_value = "3.14159" self.datapoint.last_value = expected_value ts = 1596240000000 expected_timestamp = datetime_from_timestamp(ts, tz_aware=True) self.datapoint.last_value_timestamp = expected_timestamp self.datapoint.save() older_value = "-2.0" ts = 1200000000000 older_timestamp = datetime_from_timestamp(ts, tz_aware=True) field_values.update({ "value": older_value, "timestamp": older_timestamp }) self.generic_field_value_test(field_values=field_values) self.datapoint.refresh_from_db() actual_value = self.datapoint.last_value actual_timestamp = self.datapoint.last_value_timestamp self.assertEqual(actual_value, expected_value) self.assertEqual(actual_timestamp, expected_timestamp)
def test_save_stores_as_last_setpoint(self): """ The model should save the latest setpoint/timestamp in datapoint too. """ field_values = self.default_field_values.copy() # Ensure there is no newer msg available that would prevent saving. self.datapoint.last_setpoint = None self.datapoint.last_setpoint_timestamp = None self.datapoint.save() expected_setpoint = [{ 'from_timestamp': None, 'to_timestamp': 1564489613492, 'value': 21 }, { 'from_timestamp': 1564489613492, 'to_timestamp': None, 'value': None }] ts = 1596220000001 expected_timestamp = datetime_from_timestamp(ts, tz_aware=True) field_values.update({ "setpoint": expected_setpoint, "timestamp": expected_timestamp }) self.generic_field_value_test(field_values=field_values) self.datapoint.refresh_from_db() actual_setpoint = self.datapoint.last_setpoint actual_timestamp = self.datapoint.last_setpoint_timestamp self.assertEqual(actual_setpoint, expected_setpoint) self.assertEqual(actual_timestamp, expected_timestamp)
def setUpClass(cls): # Datapoint model is abstract, hence no table exists. Here we # create a concrete model as child of datapoint and create a table # on the fly for testing. class Datapoint(DatapointTemplate): class Meta: app_label = "test_message_format_models_4" class DatapointSetpoint(DatapointSetpointTemplate): class Meta: app_label = "test_message_format_models_4" # The datapoint foreign key must be overwritten as it points # to the abstract datapoint model by default. datapoint = models.ForeignKey( Datapoint, on_delete=models.CASCADE, ) cls.Datapoint = Datapoint cls.DatapointSetpoint = DatapointSetpoint with connection.schema_editor() as schema_editor: schema_editor.create_model(cls.Datapoint) schema_editor.create_model(cls.DatapointSetpoint) # Create a dummy datapoint to be used as foreign key for the msgs. cls.datapoint = cls.Datapoint(type="sensor") cls.datapoint.save() # Here are the default field values: cls.default_field_values = { "datapoint": cls.datapoint, "timestamp": datetime_from_timestamp(1612860152000), "setpoint": [], }
def test_save_stores_as_last_value(self): """ The model should save the latest value/timestamp in datapoint too. """ field_values = self.default_field_values.copy() # Ensure there is no newer msg available that would prevent saving. self.datapoint.last_value = None self.datapoint.last_value_timestamp = None self.datapoint.save() expected_value = "3.14159" ts = 1596240000000 expected_timestamp = datetime_from_timestamp(ts, tz_aware=True) field_values.update({ "value": expected_value, "timestamp": expected_timestamp }) self.generic_field_value_test(field_values=field_values) self.datapoint.refresh_from_db() actual_value = self.datapoint.last_value actual_timestamp = self.datapoint.last_value_timestamp self.assertEqual(actual_value, expected_value) self.assertEqual(actual_timestamp, expected_timestamp)
def create(self, request, dp_id): datapoint = get_object_or_404(self.datapoint_model, id=dp_id) # Returns HTTP 400 (by exception) if sent data is not valid. serializer = self.serializer_class(datapoint, data=request.data) serializer.is_valid(raise_exception=True) validated_data = serializer.validated_data dt = datetime_from_timestamp(validated_data["timestamp"]) if self.create_for_actuators_only and datapoint.type != "actuator": raise ValidationError( "This message can only be written for an actuator datapoint.") object, created = self.model.objects.get_or_create(datapoint=datapoint, timestamp=dt) if not created: raise ValidationError({ "timestamp": ["Entry for this datapoint and timestamp exists already."], }) for field in validated_data: if field == "timestamp": continue setattr(object, field, validated_data[field]) object.save() return Response(validated_data, status=status.HTTP_201_CREATED)
def retrieve(self, request, dp_id, timestamp=None): datapoint = get_object_or_404(Datapoint, id=dp_id) dt = datetime_from_timestamp(timestamp) object = get_object_or_404(self.model.objects, datapoint=datapoint, timestamp=dt) serializer = self.serializer_class(object) return Response(serializer.data)
def destroy(self, request, dp_id, timestamp=None): datapoint = get_object_or_404(self.datapoint_model, id=dp_id) dt = datetime_from_timestamp(timestamp) object = get_object_or_404(self.model, datapoint=datapoint, timestamp=dt) object.delete() return Response(status=status.HTTP_204_NO_CONTENT)
def test_last_schedule_timestamp_exists(self): """ This field stores datapoint payload. """ field_values = self.default_field_values.copy() ts = 1596240000000 ts_datetime = datetime_from_timestamp(ts, tz_aware=True) field_values.update({"last_schedule_timestamp": ts_datetime}) self.generic_field_value_test(field_values=field_values)
def test_field_timestamp_exists(self): """ Verify that we can store the setpoints timestamp. """ field_values = self.default_field_values.copy() ts = 1596240000000 ts_datetime = datetime_from_timestamp(ts, tz_aware=True) field_values.update({"timestamp": ts_datetime}) self.generic_field_value_test(field_values=field_values)
def test_save_wont_overwrite_newer_setpoint(self): """ Don't save the value/timestamp to datapoint if it is older then the msg stored there. """ field_values = self.default_field_values.copy() # Ensure there is a newer msg available that will prevent saving. expected_setpoint = [{ 'from_timestamp': None, 'to_timestamp': 1564489613492, 'value': 21 }, { 'from_timestamp': 1564489613492, 'to_timestamp': None, 'value': None }] self.datapoint.last_setpoint = expected_setpoint ts = 1596220000000 expected_timestamp = datetime_from_timestamp(ts, tz_aware=True) self.datapoint.last_setpoint_timestamp = expected_timestamp self.datapoint.save() older_setpoint = [] ts = 1200000000000 older_timestamp = datetime_from_timestamp(ts, tz_aware=True) field_values.update({ "setpoint": older_setpoint, "timestamp": older_timestamp }) self.generic_field_value_test(field_values=field_values) self.datapoint.refresh_from_db() actual_setpoint = self.datapoint.last_setpoint actual_timestamp = self.datapoint.last_setpoint_timestamp self.assertEqual(actual_setpoint, expected_setpoint) self.assertEqual(actual_timestamp, expected_timestamp)
def update(self, request, dp_id, timestamp=None): # Returns HTTP 400 (by exception) if sent data is not valid. serializer = self.serializer_class(data=request.data) serializer.is_valid(raise_exception=True) validated_data = serializer.validated_data datapoint = get_object_or_404(self.datapoint_model, id=dp_id) dt = datetime_from_timestamp(validated_data["timestamp"]) object, created = self.model.objects.get_or_create(datapoint=datapoint, timestamp=dt) for field in validated_data: if field == "timestamp": continue setattr(object, field, validated_data[field]) object.save() return Response(validated_data, status=status.HTTP_201_CREATED)
def filter_timestamp(self, queryset, lookup_expr, value): lookup = "__".join([lookup_expr]) ts_as_dt = datetime_from_timestamp(float(value)) return queryset.filter(**{lookup: ts_as_dt})