HttpApi, update attribute with timestamp

I have question regarding updating assets at a defined timestamp.
When I try to update some historical data, I see in console:
Event is older than current attribute value so marking as outdated:
My scenario: I’m using openremote http api only, I have low-power sensor that is connecting to the openremote for the first time. I want to upload all historical data. If I understand swagger docs correctly, I can’t create an attribute with custom timestamp (by default it uses current timestamp).
So neither I can create attribute with custom timestamp, nor I can update historical data. Is that correct? Is there way to create a asset from scratch with historical data using only HttpApi?

To be clear: I’m using endpoint /asset/{assetId}/attribute/{attributeName}/{timestamp} and the Result from PUT is 200, however attribute in openremote is not updated with historical data because of message you can see above (" Event is older than current attribute value so marking as outdated).
Looks like updating the historical value with Rest API doesn’t work. If you have some idea about quick-fix I would be really grateful.

When I create asset, attribute and set initially the attribute timestamp with some very old value, then the uptading with timestamp in the past works fine.

HTH
BR,Vladimir

Good morning @wrazik,

What is happening here is that the attribute event that has been sent has a timestamp that is in the past of the attribute value that is currently in the asset itself.

So for example, if I have a device that creates an attribute event with a specific timestamp, like 9am, and I update the attribute in the manager UI at 10am, but the 9am value arrives to OpenRemote at 11am, then that value is marked as outdated.

An outdated value is still inserted in the historic datapoint table, but it is not inserted in the current asset view.

Take care and check if that is indeed happening for you, and let me know if you encounter any issues.

Best of luck!

@niv Do you know how to set initial timestamp?
Maybe I will explain how I do it step-by-step with all requests detailed:

  • Let’s create an asset:
POST /api/master/asset
{
    "name": "timestamptest",
    "accessPublicRead": false,
    "realm": "master",
    "type": "Thing",
    "attributes": {
        "temp": {
            "meta": {
                "storeDataPoints": true,
                "readOnly": true,
                "dataPointsMaxAgeDays": 999999999
            },
            "value": {
                "t1": 44
            }
        }
    }
}

In a response, I’m receiving something like this:

{
    "id": "6eog2E4d3IlKIQe5iLu9dg",
    "version": 0,
    "createdOn": 1737186049503,
    "name": "timestamptest",
    "accessPublicRead": false,
    "realm": "master",
    "type": "Thing",
    "path": [
        "6eog2E4d3IlKIQe5iLu9dg"
    ],
    "attributes": {
        "temp": {
            "name": "temp",
            "meta": {
                "storeDataPoints": true,
                "readOnly": true,
                "dataPointsMaxAgeDays": 999999999
            },
            "value": {
                "t1": 44
            },
            "timestamp": 1737186049473
        }
    }
}

Now, let’s update attribute value from hour ago:

PUT /api/master/asset/6eog2E4d3IlKIQe5iLu9dg/attribute/temp/1737182576000

30

In a response, I receive some id:

{
    "ref": {
        "id": "6eog2E4d3IlKIQe5iLu9dg",
        "name": "temp"
    }
}

Now, let’s ask for a datapoint history:

POST /api/master/asset/datapoint/6eog2E4d3IlKIQe5iLu9dg/temp
{  
"fromTimestamp":1737096176000,
"toTimestamp":1737186385000
}

In a response, I see only initial value:

[
    {
        "x": 1737186049473,
        "y": {
            "t1": 44
        }
    }
]

If I update the timestamp after point was created, e.g. 1737186325000, I will receive something like:

[
    {
        "x": 1737186325000,
        "y": 30
    },
    {
        "x": 1737186049473,
        "y": {
            "t1": 44
        }
    }
]

So I’m assuming I’m using timestamp endpoint correctly but it doesn’t work as expected.

So what’s going on here is that when you create the asset and add a value to an attribute, the attribute has the creation time (roughly, some millis off) of the asset itself as a timestamp.

So since you created (the asset and) the attribute itself at 1737186049473 (January 18, 2025 7:40:49.473) and gave it a value, when you try to update the attribute right below with a timestamp of 1737182576000 (January 18, 2025 6:42:56 AM), that value is actually before the attribute creation timestamp.

So, that new update at 7:40AM is considered outdated, as the attribute itself has a more recent attribute value, at 6:42AM.

Of course, if you update the attribute with a timestamp after 7:40AM, like at 8:45AM as you show, it’s going to update the attribute properly.

This is intended behavior, maybe a solution for you would be to create the asset itself before any attribute updates, or not give the attribute a value upon creation of the asset.

Hope this helps, let me know if you have any issues!

@wrazik forgot to tag!

So - how I can create attribure without timestamp / with custom timestamp using Rest API? Can you give me example to verify it?

@wrazik I would try to add the timestamp of the attribute itself in the asset creation request, in the same way you see in the response, and having that in the past. I’m not sure if that works but you could try. You can also try adding a timestamp to the asset itself.

Best of luck!

Let’s consider scenario, when I’m creating an asset with a timestamp:

POST /api/master/asset
{
    "name": "timestamptest4",
    "accessPublicRead": false,
    "realm": "master",
    "type": "Thing",
    "attributes": {
        "temp": {
            "meta": {
                "storeDataPoints": true,
                "readOnly": true,
                "dataPointsMaxAgeDays": 999999999
            },
            "value": 44,
            "timestamp": 1579333525000
        }
    }
}

Then, I can add value with timestamp > 1579333525000:

PUT api/master/asset/6hAve4oBtq0WOlAk4oeVXp/attribute/temp/1642059925000
[
    {
        "x": 1642059925000,
        "y": 32
    },
    {
        "x": 1579333525000,
        "y": 44
    }
]

But it’s impossible now to add point before 1642059925000:

PUT /api/master/asset/6hAve4oBtq0WOlAk4oeVXp/attribute/temp/1641800725000
Resp 200 OK

Querying about historical data shows only two points:

POST /api/master/asset/datapoint/6hAve4oBtq0WOlAk4oeVXp/temp
{
"fromTimestamp":1547538325000,
"toTimestamp":1737186385000
}
Resp 200 OK
[
    {
        "x": 1642059925000,
        "y": 32
    },
    {
        "x": 1579333525000,
        "y": 44
    }
]

As I receive data from the device unordered, I can’t update the value…
When I’m trying to update the timestamp using endpoint:

PUT /api/master/asset/6hAve4oBtq0WOlAk4oeVXp
{
    "id": "6hAve4oBtq0WOlAk4oeVXp",
    "version": 0,
    "createdOn": 1737293493910,
    "name": "timestamptest4",
    "accessPublicRead": false,
    "realm": "master",
    "type": "Thing",
    "path": [
        "6hAve4oBtq0WOlAk4oeVXp"
    ],
    "attributes": {
        "temp": {
            "name": "temp",
            "meta": {
                "storeDataPoints": true,
                "readOnly": true,
                "dataPointsMaxAgeDays": 999999999
            },
            "value": 32,
            "timestamp": 1547538325000
        }
    }
}

The timestamp is ignored and it is set to current date:

(...)
    "attributes": {
        "temp": {
            "name": "temp",
            "meta": {
                "storeDataPoints": true,
                "readOnly": true,
                "dataPointsMaxAgeDays": 999999999
            },
            "value": 32,
            "timestamp": 1737294011901
        }
    }
(...)

Which makes things more complicated, because now I can’t add data before 1737294011901.

Wouldn’t it be more intuitive to allow update values before attributes timestamp? I am slowly losing faith that my scenario can be realized :frowning:

@panos Any thoughts? Wouldn’t be better to be able to overwrite any timestamp, not only the future ones?

@panos ? …anyone?
To sum up:
with endpoint /asset/{assetId}/attribute/{attributeName}/{timestamp} it is possible only to put data in the future from the last change, it’s not possible to add datapoints in the past

@Rich maybe you have any ideas for this? The issue is that the data is coming in unordered

@Rich Please let me know if you need any information. Maybe you can just point me where this filtering is done and I will fork the OpenRemote?

If there is anyone who can help me I would be very grateful!

Hey @wrazik, sorry for the delayed response.

The AssetProcessingService does indeed keep track of attribute timestamps and it generates an OutdatedAttributeEvent when the value currently stored in the attribute has a newer timestamp.

What is missing is for the AssetDatapointService to still commit the value to the asset_datapoint table, I don’t think you need to do this as a fork I will create a PR and get this minor change integrated and included in the next release. Follow along here: