openhab / openhab-addons

Add-ons for openHAB
https://www.openhab.org/
Eclipse Public License 2.0
1.85k stars 3.56k forks source link

[meater] Bad response from API #16982

Closed jlaur closed 1 day ago

jlaur commented 4 days ago

I don't know if this is bug, something changed in the service, or just a temporary issue, but nevertheless sharing it quickly in case something needs to be done on our side before release 4.2.

I noticed this in my logs today:

2024-07-02 22:47:37.205 [TRACE] [ng.meater.internal.api.MeaterRestAPI] - API response: {"status":"Bad Request","statusCode":400,"message":"Invalid JSON","help":"https://github.com/apption-labs/meater-cloud-public-rest-api"}
2024-07-02 22:47:37.206 [DEBUG] [ng.meater.internal.api.MeaterRestAPI] - getFromApi failed, HTTP status: 400
2024-07-02 22:47:37.206 [WARN ] [ng.meater.internal.api.MeaterRestAPI] - Failed to refresh! Failed to fetch class="afterFrom marked"> from API!

My meaterapi Thing is therefore offline.

Expected Behavior

Binding should be able to communicate with the cloud API.

Current Behavior

See above.

Possible Solution

Not yet known.

Steps to Reproduce

I don't know if anything particular is needed. I have a Meater Block with four probes.

Context

We are close to 4.2RC.

Your Environment

jlaur commented 3 days ago

@jannegpriv, @digitaldan - do you have the same issue? I went through my saved Postman requests yesterday (login + getdevices) without any issues, but the binding still has this issue today.

digitaldan commented 3 days ago

Yep, i have this too.

digitaldan commented 3 days ago

Good thing i'm just grilling burgers for Independence day tomorrow and not steaks! I depend on my Alexa to tell me when their ready!

fals3illusion commented 3 days ago

I am getting the same thing too. I even disabled my meater thing as it is not in use and trying to silence the warnings, but I am still getting them.

[WARN ] [ng.meater.internal.api.MeaterRestAPI] - Failed to refresh! Failed to fetch class="afterFrom marked"> from API!
[WARN ] [.core.thing.binding.BaseThingHandler] - Handler MeaterBridgeHandler tried updating the thing status although the handler was already disposed.

meater

jannegpriv commented 2 days ago

My MEATER is in my summer house, I will travel there in the week-end so I'll look into it. I'll start to check for any known changes to the API.

jlaur commented 2 days ago

My MEATER is in my summer house, I will travel there in the week-end so I'll look into it. I'll start to check for any known changes to the API.

My MEATER is in a drawer. Luckily it's not needed to reproduce this issue which happens even for an empty device list. 😉

I had a short look yesterday, but was not able to figure out the difference between my Postman requests (resulting in 200) and the binding request (resulting in 400). Getting the token works in both cases, but retrieving devices fails for the binding, whereas my Postman request resulted in an empty list and HTTP status code 200. I even tried to manipulate user-agent in case we are blocked, but this didn't help either.

jlaur commented 2 days ago

So this:

curl --location 'https://public-api.cloud.meater.com/v1/devices' \
--header 'Authorization: Bearer xxx' \
--header 'Content-Type: application/json' \
--header 'Accept-Language: da' \
--header 'Accept: application/json'

outputs:

{"status":"OK","statusCode":200,"data":{"devices":[]},"meta":{}}

But this:

https://github.com/openhab/openhab-addons/blob/2d412023a9b588b0421663f6c9bf23d45ab7dc5d/bundles/org.openhab.binding.meater/src/main/java/org/openhab/binding/meater/internal/api/MeaterRestAPI.java#L55-L58

https://github.com/openhab/openhab-addons/blob/2d412023a9b588b0421663f6c9bf23d45ab7dc5d/bundles/org.openhab.binding.meater/src/main/java/org/openhab/binding/meater/internal/api/MeaterRestAPI.java#L138-L143

logs:

{"status":"Bad Request","statusCode":400,"message":"Invalid JSON","help":"https://github.com/apption-labs/meater-cloud-public-rest-api"}

I checked token and language within the binding, seems correct.

jlaur commented 2 days ago

I also tried to swap token between binding and curl request, but this did not change anything. So I believe token issues can be ruled out.

lsiepel commented 2 days ago

The order of the header is different, but can't believe that is the issue.

Edit: When looking at https://github.com/apption-labs/meater-cloud-public-rest-api the exmaple only requires the JWT token to be set, the language and accept and other headers are omitted.

digitaldan commented 2 days ago

So in trying to debug this, i actually got it to kinda work, but i'm still not sure why (need to dig in a little more).

Basically i setup my Caddy http server to act as a man in the middle proxy to see what jetty is actually sending, weirdly this now works. By default Caddy sends the exact same headers as the request, the only thing i overwrite was to make sure the HOST header was set to "public-api.cloud.meater.com" instead of my local proxy (otherwise cloudflare can't route the request)

So strange!

digitaldan commented 2 days ago

hmmm, this is odd, looks like there are 2 duplicate Content-Type entries, thats not right, i wonder if my caddy is cleaning that up on the way out..... i bet that might be it


 "request": {
        "remote_ip": "192.168.91.10",
        "remote_port": "36326",
        "client_ip": "192.168.91.10",
        "proto": "HTTP/1.1",
        "method": "POST",
        "host": "xxxxxxxx",
        "uri": "/v1/login",
        "headers": {
            "Accept-Encoding": [
                "gzip"
            ],
            "User-Agent": [
                "Jetty/9.4.54.v20240208"
            ],
            "Accept": [
                "application/json"
            ],
            "Content-Type": [
                "application/json",
                "application/json"
            ],
            "Content-Length": [
                "63"
            ]
        },
        "tls": {
            "resumed": false,
            "version": 772,
            "cipher_suite": 4865,
            "proto": "",
            "server_name": "xxxxxxxx"
        }
    }
digitaldan commented 2 days ago

i think this line is what the problem is

            request.header(HttpHeader.CONTENT_TYPE, JSON_CONTENT_TYPE);
            request.content(new StringContentProvider(json), JSON_CONTENT_TYPE);

the second one adds the content type as a convenience, so dropping the first line my fix it ?

jlaur commented 2 days ago

@digitaldan - thanks a lot, Dan! Now it's pretty obvious: https://github.com/openhab/openhab-addons/blob/2d412023a9b588b0421663f6c9bf23d45ab7dc5d/bundles/org.openhab.binding.meater/src/main/java/org/openhab/binding/meater/internal/api/MeaterRestAPI.java#L138-L143

we shouldn't have any content-type, because we have no content. And for the login (which strangely works):

https://github.com/openhab/openhab-addons/blob/2d412023a9b588b0421663f6c9bf23d45ab7dc5d/bundles/org.openhab.binding.meater/src/main/java/org/openhab/binding/meater/internal/api/MeaterRestAPI.java#L107-L108

We have two!

It works now, I'll create a PR quickly.

digitaldan commented 2 days ago

Ha! Jinx ! (we posted the same time)

jlaur commented 2 days ago

@digitaldan - now back to preparing burgers for Independence Day. 😄 Enjoy and thanks again.

digitaldan commented 2 days ago

You too, thanks for the fix !

jannegpriv commented 2 days ago

I was 30 min too late :-)

image

After fix:

image
jannegpriv commented 2 days ago
image
jlaur commented 2 days ago

Here are some JARs for production systems until upgraded to 4.2 final which hopefully will include the fix:

MMi1603 commented 2 days ago

I have the same problem with my Meater+ since some days ( failed to fetch class="afterFrom marked"> from API).

In this post I see mainly the Meater Block discussed and would be glad if your solution also covers the Meater+.

Thanks in advance,

jlaur commented 2 days ago

In this post I see mainly the Meater Block discussed and would be glad if your solution also covers the Meater+.

The fix is for the cloud communication which is broken for any product supported by the binding.