Http-binding baseURL with dynamic date value

Hello,

as I am playing around a little bit with the http binding on my test-system with a new openHAB 3 installation i found a challenge, which i could not resolve so far.

I know I could work around the problem, if I just solve it in a rule, but maybe there is a way to use the binding and i just did not figure it out by now.

My problem is the baseURL which requires a date (f.e. 7 days back from today). Is there any way to use a dynamic day in the things configuration (baseURL) of the http binding?

Is inserting the date as described in the documentation. not working?

Hello Jan,

if you are talking about using “the current date (referenced as %1$)”, i have not tried so far, since the API I want to use has no valid response on the current date, but I have seen this. If I missed any thing else in the documentation please give me a link.

The problem or the question is: Is there any possibility to use %1$ in the URL to calculate an older date? If there is any possibility I would appreciate an example.

Yes, that’s what I was thinking about. I guess using HTTP requests in a rule is the way to go here. That‘s to special to cover it in a binding.

@J-N-K, thanks for your reply.

That is not the answer I hoped to get, but at least I do not need to investigate further in this case.

hello icsat

i had your same problem but didn’t want to do it all within a rule and ditch the advantages of the http-binding binding.
I have created the Http binding setting the baseURL with a fixed parameter and created a rule that updates the baseURL after some post processing. You can access the baseURL of an http-binding thing very easily from the OH REST interface by querying the object from a rule, update the obtained JSON structure (look the baseURL field) and post back (PUT instead of POST) the modified JSON structure as body. No need to escape ‘\’ anything if you use a Jython rule and json+requests libraries. javascript can also be used if you’re more familiar with.

i can provide a sample of what i’ve done if needed.

just remember to create a token for interacting with OH REST interface.

hope it helps

Cristian

Hello Cristian,

thank you for your reply and your solution. I did not use the openHAB Rest-API so far, so I sure would appreciate an example. I will try to test it if I find some time.

But you lead me to different (quick and dirty) solution, wich will work in my case.

No matter how many datasets there will be returned, I just need newest seven. Since I am able to get the result sorted by date, I always need the first seven results. I just have to set a fixed date older than seven days.
That’s not pretty smart, but will do it to get startet.

here’s how I have defined my http-binding item:

UID: http:url:ed9e5a004b
label: Rainmachine binding
thingTypeUID: http:url
configuration:
  ignoreSSLErrors: true
  baseURL: http://x.x.x.x:nnnn/api/4/zone?access_token=dynamic_token
  refresh: 60
  commandMethod: GET
  contentType: application/json
  timeout: 3000
  bufferSize: 4096
channels:
  - id: ch_zone1_name
    channelTypeUID: http:string
    label: Zone1 Active
    description: display zone name
    configuration:
      mode: READONLY
      stateTransformation: JSONPath:$.zones[0].name

as you see the baseURL of my equipment needs a dynamic 1 hour lasting token so I came with the idea to schedule a rule that takes care of authenticating, retrievemcent of the token and update of the BaseURL of the above item.

here’s the rule definition code:

triggers:
  - id: "1"
    configuration:
      cronExpression: 0 0 0/12 * * ? *
    type: timer.GenericCronTrigger
conditions: []
actions:
  - inputs: {}
    id: "2"
    configuration:
      type: application/python
      script: >
        import requests
        import json
        from org.slf4j import LoggerFactory
        logger = LoggerFactory.getLogger("org.openhab.core.automation.rules.rainmachine")
        token=''
        baseURL="http://x.x.x.x:nnnn"
        apiURL="/api/apiVer"

        authURL="/api/4/auth/login"
        zoneURL='/api/4/zone?access_token='

        session = requests.Session()
        logger.info("POSTting "+baseURL+authURL)

        r = session.post(baseURL+authURL, json={'pwd': 'devicepassword', 'remember':False})

        if r.status_code == 200:
          logger.info("HTTP Return Code=" + str(r.status_code))              
          try:
            jo=json.loads(r.text)
            logger.info("JSON Auth Object loaded succesfully")
            token=str(jo['access_token'])
            logger.info("API token: " + token)
            
          except Exception as e:
            logger.error("JSON Auth Load failed: " + str(e))  
            logger.error("BODY "+ r.text)

        else:
          logger.error("HTTP Return Code=" + str(r.status_code))
          logger.error("BODY "+ r.text)

        #preparing OH3 REST query of the http-binding thing
        auth_header={'Authorization': 'Bearer <replace this text with an OH oAuth2token>'}

        #below URL can be retrieved fro the OH Developers tools>API Explorer>things > GET /things/{thingUID}
        r = session.get("http://openhab_address:8080/rest/things/http%3Aurl%3Aed9e5a004b", headers=auth_header, verify=False)

        if r.status_code == 200:
          logger.info("HTTP Return Code=" + str(r.status_code))
          try:
            jo=json.loads(r.text)
            logger.info("JSON OH HTTP binding object loaded succesfully")
            try:
              logger.info("JSON trying to load StateExtension field")
              logger.info("JSON OH baseURL value= " +str(jo['configuration']['baseURL']) )
              #update the baseURL field of the HTTP-Binding JSON object for this Thing
              #you can add dynamic part of your URL or completely rewrite it as you like 
              jo['configuration']['baseURL'] = "http://10.10.2.251:8081/api/4/zone?access_token=" + token
             
              #now trying g to update the http-Binding thing via REST by PUTting back the modified json object
              try:
                logger.info("trying to update baseURL with new value")
                #below URL is the same as the GET one. but method for updating is PUT:
                r2 = session.put("http://10.10.1.16:8080/rest/things/http%3Aurl%3Aed9e5a004b", headers=auth_header, json=jo, verify=False)
                if r2.status_code == 200:
                  logger.info("HTTP Return Code=" + str(r2.status_code))
                else:
                  logger.error("HTTP Return Code=" + str(r2.status_code))
                  logger.error("BODY "+ r2.text)
                  
              except Exception as e:
                logger.error("JSON update of stateExtension failed: " + str(e))  
              
            except Exception as e:
              logger.error("JSON state extension load failed: " + str(e))  
              
          except Exception as e:
            logger.error("JSON OH HTTP Rainmachine binding object load failed: " + str(e))  
            logger.error("BODY "+ r.text)

            
        else:
          logger.error("HTTP Return Code=" + str(r.status_code))
          logger.error("BODY "+ r.text)

if you’re more familiar with javascript, here are the base steps to follow:

  1. create an oAuth authentication token for later access to the OH rest interface: API Tokens interface is available under the user profile management (bottom-left corner of the Main UI Interface)
  2. retrieve the REST URL of your http-binding thing from the Developers tools>API Explorer>things> GET /things/{your_thingUID}
  3. query via GET Method the obtained URL by adding the oAuth API token as header “{‘Authorization’: ‘Bearer [replace this text with an OH oAuth2token]’}”. It will return a json object representing the configuration the queried http-binding thing
  4. update the retrieved json object by updating the baseURL field in this way: json_object[‘configuration’][‘baseURL’] = “http://my_device_ip:8081/api_path?dynamic_parameter=” + your_dynamic_parameter
  5. store back the updated json configuration to OH via REST using the PUT method and same URL as the GET one (always remember to set the the same previous authentication header)

It looks complex but the code can be simplified further by removing the try&catch blocks.

Let me know if you need any more details. I’ll be happy to explain further.

1 Like