HTTP Server config

Hi there,

I’m currently working on a prototype involving very remote monitoring stations that turn themselves on, take some measurements, post readings to a destination, then switch off.

I wanted to try to use openremote to act as the management entity of the stations, but I cannot figure out how to configure an asset/agent so that openremote expects to receive http posts from the asset.

I can see in the code base that there is a httpserver class. Can anyone give me a pointer as to how to configure such an arrangement?

2 Likes

It should be there. Sometime ago, when I needed an HTTP server, I’ve ended with AWS serverless lambda as HTTP server and Openremote as a client pulling it. Perhaps @Rich can shed more light on how to configure the embedded HTTP server now and @Don can add this to WiKi? A need for an HTTP server seems to be quite common requirement. Anyway, in case you are interested in my proxy solution then let me know, it is quite easy to setup

Thanks for the feedback. Yes, certainly an option if there is no httpserver support. Looking forward to getting some feedback from @Rich and @Don

Hi, there is indeed a HTTP server protocol but this is not a protocol that can be configured through the UI and requires some coding.

Here’s an integration test that covers the HttpServerProtocol:

The HttpServerProtocol uses JAX-RS resources to configure the REST API for your protocol (see TestHttpServerProtocol), these resources are then routed to via the existing undertow web server.

The path prefix for your custom endpoints is:

/rest/<DEPLOYMENT_PATH> where <DEPLOYMENT_PATH> comes from the HttpServerAgent deploymentPath attribute (this allows multiple instances of the same HttpServerProtocol to be deployed at different endpoints.

The main thing you will need to code for a custom HttpServerProtocol is what do with the data received on the endpoints, in the TestHttpServerProtocol the TestResourceImpl just keeps the posted assets in memory which isn’t very useful in the real world, much more likely to want to persist the asset update attributes etc. which can be done easily with the various methods available on AbstractProtocol.

I don’t know how much control you have over the HTTP client as you could post to the existing AssetResouce writeAttributeValue PUT /api/asset/{assetId}/attribute/{attributeName}.

To be able to do this you can either add the Access Public Write configuration item to the attribute(s) you want to be able to update or you will have to create a keycloak client that has ServiceAccount enabled to allow programmatic login and then your HTTP client will need to support OAuth client_credentials grant type.

Can you please provide a curl example with the call? I was trying to do this and was unsuccessful. My public asset is:

  {
        "id": "6KLG9PZ86WRk7P4doYnafR",
        "version": 2,
        "createdOn": 1618311310006,
        "name": "New Asset",
        "accessPublicRead": true,
        "parentId": "29jOhQRhEu3IHXlHiHMi0m",
        "realm": "master",
        "parentName": "New Asset",
        "parentType": "WebsocketClientAgent",
        "type": "ShipAsset",
        "path": [
            "6KLG9PZ86WRk7P4doYnafR",
            "29jOhQRhEu3IHXlHiHMi0m"
        ],
        "attributes": {
            "speed": {
                "type": "positiveNumber",
                "value": null,
                "name": "speed",
                "meta": {
                    "storeDataPoints": true,
                    "accessPublicWrite": true,
                    "accessPublicRead": true
                },
                "timestamp": 1618311633189
            }
        }
    }

Thanks for the reply @Rich. Is it possible to look at adding HTTP server support within the GUI? I am not a developer, and so I’m not 100% sure where to start with what you’ve mentioned in your response. Could you give me some guidance on that? I assume that I would have to access the docker in order to make a change?

Apologies in my haste I missed the realm from the request path:

/api/{realm}/asset/{assetId}/attribute/{attributeName}

Here’s a curl example for an attribute called humidity on an asset in the master realm.

curl -i -X PUT \
   -H "Content-Type:application/json" \
   -d \
'50' \
 'http://localhost:8080/api/master/asset/5syzbGGCxe4ZZFvRNdjYJF/attribute/humidity'
1 Like

If you can’t take on any development then the simplest solution is to create the asset(s) in the OpenRemote GUI and add all the attributes you require to this asset(s) and add the Access public write configuration item to each attribute that you want to populate from your sensors.

Your installation will need to be exposed to the internet (port 443) and ideally you should have a domain name pointing to your system (OpenRemote can generate an SSL certificate automatically then).

Then it is a matter of doing a HTTP PUT to:

https://my.domain.co/api/master/asset/{assetId}/attribute/{attributeName}

With the body of the request set to the value you want to assign to the atttribute in JSON format e.g. if you wanted to set a string attribute then the body would need to be enclosed in quotations:

"string_value"

Hi @Rich . Sorry it’s me again. I’m probably doing something daft, but I’m not sure if what I am trying to do is correct.

So I’ve managed to get PUT sort of working using curl just to test the concept, however, I am getting 204 No Content, which I assume is the reason it’s not working.

Here’s the curl request:

curl -i -k -X PUT -H Content-Type:application/json -d ‘“777”’ https://hostname/api/master/asset/2kI17ciuwWsgSdQ365OMCT/attribute/EC

and the response:

HTTP/1.1 204 No Content
date: Wed, 14 Apr 2021 11:04:22 GMT

I was expecting it to produce a data point, and if I did it again, another data point. i.e. to store historical readings.

Have I totally missed the point?

Glad you got it to work; in order to store historic values you need to add the Store data points configuration item to the attributes (this happens automatically for attributes that have an Agent link configuration item but for others you have to specify it.

@Rich again, done that and that is ok. However, no values are actually stored.

I seem to get a 204 No Content response, which I assume means the body part doesn’t seem to be accepted. It seems to change the attribute name rather than a data point. What is wrong with the curl I’m doing?

Hi scm7mae,

Was following this topic and wanted to try myself. It sets the value correctly. What I noticed from your command is that you dont have the " around “Content-Type:application/json”, and the ’ you have at ‘“777”’ are these ` and not ’ these… not sure whether that will make a difference, but you can give it a go :slight_smile:
So it would be curl -i -k -X PUT -H "Content-Type:application/json" -d '"777"' https://hostname/api/master/asset/2kI17ciuwWsgSdQ365OMCT/attribute/EC
Also, you mean 777 to be a string then right? Otherwise go for ‘777’

As far as the 204 No Content response goes, Google tells me that is a success :wink: “The HTTP 204 No Content success status response code indicates that a request has succeeded, but that the client doesn’t need to navigate away from its current page.”

Don

Hi @Don. Thanks for your response. The issue I have, is that when you look at the history of the data for the attribute EC, in my case, I do not see the value, I only see the date timestamp. So my question really was to @Rich or someone as to what I’m doing wrong, as it appears that the data point is not stored, only the date timestamp.

Any ideas?

204 is a good response (as for HTTP every 2xx is OK). If you don’t see you data points stored have you checked if ‘Store data points’ is enabled?

@michal Yes - definitely, it is selected for that attribute. I was trying to attach a screen grab, but I cannot attach anything, it says access denied.
@Rich
Basically, in the History section, I see Value which is blank, but the timestamp is there. so even though the attribute is set, the data in History is not there.

What’s the type of your EC attribute? Looks like you’re using JSON Object as I see the data table in your screenshot. I would guess that the data in your PUT cannot be converted to the correct type for the attribute or the history data table doesn’t know how to represent the data.

Do you see a value in the attribute field itself (not in the history panel)?

Hi @Rich. It’s configured to be text type. Is that wrong? The attribute shows the value when I use the curl request:

OK so looks like it’s just a frontend issue with the history data table not rendering correctly, I’ll put this on the list and try and find time to investigate but I’d say you have the sending part working ok.

thanks @Rich. I’ve managed to resolve the issue. I’ve changed the parameter to number and all is well. However I guess as you said, something to add to the backlog.

@Rich, thanks again for all your support. One last question on http request to PUT data. What URL would I need to call in order to set multiple attributes against an asset?

I tried the following but get 403 Forbidden:

curl -i -k -X PUT -H “Content-Type:application/json” -d ‘{“temp”:5.42,“ORP”:10.122}’ https://{hostname}/api/master/asset/2kI17ciuwWsgSdQ365OMCT/

Is it possible to set multiple parameters with one HTTP PUT?

2 Likes