Issue with mindergas.nl api, executeCommandLine and curl

I am trying to publish my gas meter readings to the https://www.mindergas.nl website.

When I use this command on the command line it works:

curl -s -w %{http_code} -k -H "Content-Type:application/json" -H "Accept:application/json" -H "AUTH-TOKEN:mytoken" -d '{"date":"2016-05-19","reading":"988.545"}' https://www.mindergas.nl/api/gas_meter_readings

From openHAB I run this command that gives a 401 error (unauthorized)

var String token = "mytoken"
var String api="https://www.mindergas.nl/api/gas_meter_readings"
var String pubdate="2016-05-19"
var String pubstand="988.545"
var String body    = '{"date":"' + pubdate + '","reading":"' + pubstand + '"}'
var String command = 'curl@@-s@@-w@@%{http_code}@@-k@@-H@@"Content-Type:application/json"@@-H@@"Accept:application/json"@@-H@@"AUTH-TOKEN:' + token + '"' + "@@-d@@'" + body + "'@@" + api 
var String result = executeCommandLine(command, 5000)

I suspect the curl command is not formatted properly. Can anyone guide me to solve this issue?

The most common problem people face with the Exec binding and executeCommandLine is with permissions, but I don’t think that is the case here.

While the “@@” space substitution is often required with the Exec binding, I don’t think it is even supported with executeCommandLine (I could be wrong). Have you tried it without the "@@"s?

Have you tried using the --trace-ascii debugdump.txt option on curl and reviewed debugdump.txt to see what exactly curl is sending? You can compare that with the version that worked and see if what the curl from OH is sending that is different.

1 Like

I have tried both without @@’ and with the --trace-ascii flag and that seems to be getting me somewhere. I apparently don’t need the @@ and the dump showed that the quotations around in inside the JSON where different from the working example:

unix command line:

=> Send data, 41 bytes (0x29)
0000: {"date":"2016-05-19","reading":"988.545"}
== Info: upload completely sent off: 41 out of 41 bytes

script without @@:

=> Send data, 43 bytes (0x2b)
0000: '{"date":"2016-05-19","reading":"989.231"}'
== Info: upload completely sent off: 43 out of 43 bytes

That’s better!

Then I removed the single quotes (and @@) from the command:

old:

var String command = 'curl@@-s@@-w@@%{http_code}@@-k@@-H@@"Content-Type:application/json"@@-H@@"Accept:application/json"@@-H@@"AUTH-TOKEN:' + token + '"' + "@@-d@@'" + body + "'@@" + api 

new:

var String command = 'curl -s -w %{http_code} -k -H "Content-Type:application/json" -H "Accept:application/json" -H "AUTH-TOKEN:' + token + '"' + " -d " + body + " " + api 

Now the output in the dump file shows JSON without any quotes:

=> Send data, 33 bytes (0x21)
0000: {date:2016-05-19,reading:989.231}
== Info: upload completely sent off: 33 out of 33 bytes

Quotation hell!

Apparently I need the single quotes but I can’t get these into the command.

@rlkoshak Do you have any suggestions?

Escape the quotes.

var String body = "{\"date\":\"" + pubdate + "\",\"reading\":\"" + pubstand + "\"}"

I tried escaping, but that delivered similar results. After trial-and-erroring some variants, it looks like I’ve found a way to do this: using @@ and removing all single and double quotes in the command variable. The only quotes remaining are those in the body.

This code seems to work, I will monitor in the coming days and report back.

var String token = "mytoken"
var String api = "https://www.mindergas.nl/api/gas_meter_readings"
var String pubdate = "2016-05-19"
var String pubstand = "988.545"
var String body = '{"date":"' + pubdate + '","reading":"' + pubstand + '"}'
var String command = 'curl@@-s@@-w@@%{http_code}@@-k@@-H@@Content-Type:application/json@@-H@@Accept:application/json@@-H@@AUTH-TOKEN:' + token + "@@-d@@" + body + "@@" + api 
var String result = executeCommandLine(command, 5000)

@rlkoshak Thanks for your help.

I have been monitoring for a few days and the solution is working.

Can someone help to convert this code to OH3 standards? Help is appreciated.

I’m getting the following error:
An error occurred during the script execution: Could not invoke method: org.eclipse.xtext.xbase.lib.ObjectExtensions.operator_plus(java.lang.Object,java.lang.String) on instance: null in mindergas

var String token = "xxxxxxxxxxx"
var String api = "https://www.mindergas.nl/api/gas_meter_readings"
var DateTime pubdate = CurrentDate.state
var Number pubstand = M3Meter_M3meterValue.state
var String body = '{"date":"' + pubdate + '","reading":"' + pubstand + '"}'
var String command = 'curl@@-s@@-w@@%{http_code}@@-k@@-H@@Content-Type:application/json@@-H@@Accept:application/json@@-H@@AUTH-TOKEN:' + token + "@@-d@@" + body + "@@" + api
var String result = executeCommandLine(command, 5000)

The syntax of the executeCommandLine command has changed. Check here for an example (ignore the fact that the topic is about Jython): Jython helper libraries for OH3 - #24 by rkrisi

Hi,

This seems to work for me now with OH3. Still in a rules file because I do not know how to import / use the DateTimeRormatter via the GUI.


import java.time.format.DateTimeFormatter// put at top of file
rule "dsmr_gas_minderGasNL"
        when
           Time cron "00 59 23 * * ?"
        then
         var String token = "AUTH-TOKEN:<TOKEN>"
         var String api = "https://www.mindergas.nl/api/meter_readings"
         var String pubdate = (now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))).toString
         var String pubstand = ((GasMeter_Delivery.state as QuantityType<Number>).doubleValue).toString
         var String body = '{\"date\":\"' + pubdate + '\",\"reading\":' + pubstand + '}'
         //logInfo("minderGasNL", api)
         //logInfo("minderGasNL", token)
         //logInfo("minderGasNL", pubdate)
         //logInfo("minderGasNL", pubstand)
         var String result = executeCommandLine(Duration.ofSeconds(10), "curl", "-v", "-H", "Content-Type:application/json", "-H", token, "-d", body, api)
         //logInfo("minderGasNL", result)
end

Need to work on error handling but at least the readings are uploaded again.

If using Rules DSL as the language for a Script Action, exactly the same as you do in a .rules file. Put the import at the top of the script.

import java.time.format.DateTimeFormatter// put at top of file

// rest of code goes here

Thanks, but somehow adding the line to the top of my UI created DSL script produces the following in the log:

  1. The method or field import is undefined; line 1, column 0, length 6
  2. The method or field DateTimeFormatter is undefined; line 5, column 244, length 17

Probably not doing it right, would you have a tip how to solve this? Thanks!

I don’t use Rules DSL and haven’t for a couple of years, and never in the UI. I can’t think of a reason why an import would not be allowed but it appears to not be. So your options are:

  • instead of importing it reference the class by it’s full name now().format(java.time.format.DateTimeFormatter...
  • keep it in a .rules file
  • move to a different language.

Thanks, referring to the class by the full name works.

I’d like to migrate everything to JavaScript at some point in the future but for now I’m happy that everything is working under OpenHAB3.

Thanks again for your help!

Any update on how to handle errors? I would like to be notified if the request has failed…