HTTP Request "Error: socket hang up"

Hi,

Short version of the problem:
I am sending a URL to an http request node to control my air conditioning, but node red returns, "Error: socket hang up". I know the URL is valid, because when pasted into a browser, it works (e.g. aircon powers on) and returns a valid json message with acknowledgement. Furthermore, the request does successfully execute the command from node red (e.g. aircon powers on), but node red returns the hang up error.

Longer version of the problem, with more detail, at the end of this post.

What I have discovered so far
I researched as far as I can, and found a discussion on stackoverflow, indicating that the hang up error occurs when a 'connection end event' is not sent to end the request, or if there is no timely response from the server.

Here's the link to the discussion: https://stackoverflow.com/questions/16995184/nodejs-what-does-socket-hang-up-actually-mean

What can I do?
I don't know what to do from here; it appears that either:

  1. node red is not sending a connection end event

or

  1. node red does not receive a timely response

Can anyone advise how I can proceed?

Long version of the problem:
I have created a flow for controlling my air conditioning which is connected my home network (via WiFi), and accepts json commands. (I learnt the commands by proxying my iphone to my PC using Fiddler).

If I paste one of the aircon commands into my web browser, the command is executed successfully (e.g. aircon turns on), and an acknowledgement is returned to the browser, for example:

When pasted into a browser window, this:
http://192.168.99.99:2025/setAircon?json={"ac1":{"info":{"state":"on","countDownToOn":"0","countDownToOff":"0"}}}

Returns this...
{"request":"setAircon","ack":true}

However, if I paste exactly the same URL into an http request node, the command executes on the aircon, but the following error is displayed as an error by the http request node:
Error: socket hang up

Sounds like an url encoding issue. Can you post your flow (for the get request part) ?
Are you using the http request node with a url filled in url are you using msg.url ?

The http request node accepts mustache style formatting, which could fail on urls containing { } as it tries to parse it. I have never seen json as url parameter, is this something that can be changed ?

Thank you for your response (and my apologies for not responding sooner).

I have certainly learnt something from your post, thank you... I wasn't aware of the mustache formatting in the http request node, but I am now!

I have created a basic test 'rig', using typicode.com to pass information into a query string using mustache formatting. It's a simple:

Inject > change [set msg.query] > http request

This works fine.

However, as you have suggested, I think the problem is that the json style required for my aircon query is causing problems because of the {} delimiters. I would have thought that there is some way to escape the {}, but I cannot find a way of doing it in node-red.

Unfortunately, I have no choice about the json formatting; it's the way the aircon works, and I have no control over the formatting for the query.

If someone can advise on escaping the characters in node-red, I'd be grateful.

Curly braces are considered insecure in an url and not according to the RFC standard.

You can replace { with %7B and } with %7D

Thank you for your prompt response.

I have already tried encoding as you have suggested, but with the same result.

I suppose air conditioning suppliers aren't particularly interested in security! I suppose they are assuming that security is not an issue because it runs on a private network, or they are just ignorant.

I wonder if the {} are a red herring; I get the socket hang-up regardless of whether they are encoded or not. I am 100% certain that I have got the URL formatting correct; if I copy the 'failing' URL from node red and paste into a web browser, I get an ack in a json response from the air conditioning controller.

I am not knowledgeable enough to diagnose any further, to determine what is causing the lack of response / not sending a connection end event.

I do appreciate your input. Thank you.

there may be some extra headers your browser is setting that the far end expects... (as you are sending json like payload). Other thing to try is to try it with a curl command
eg curl http://192.168.99.99:2025/setAircon?json={"ac1":{"info":{"state":"on","countDownToOn":"0","countDownToOff":"0"}}} which should be fairly unadorned and see if that works.
Is there a manual for the AC unit that details the interface at all ?

Thanks for the suggestion about headers; yes that's definitely something to examine.

curl doesn't like the exact command that you suggested ( [globbing] nested brace in column 53), however, your suggestion has pointed me in the right direction, thank you.

I'm planning on going back to my original network sniffing exercise (which is how I discovered the json packages), so I can examine those headers. The aircon app for iphone sends the json request out raw, so I should be able to get the headers (I'm no expert, but hopefully I can figure it out).

I was thinking that, ultimately, if all else fails in Node Red, I can make the json calls in Python (just because I am familiar with Python), and then I can call the Python script from Node Red and get the results back too; the airon unit sends useful results back in json).

Unfortunately, the aircon manual does not include anything useful (other than typical user controls!); supplier is not interested in providing information; they make money from selling home automation systems, so they wouldn't want me implementing my own Siri & Google compatible home automation system for the price of a Raspberry Pi!

Incidentally, node red is switching the aircon on and off successfully as mentioned in my original post; it's just that I can't get the ack back because of the socket hangup issue. I can trap the error with a node red catch, but I'd like to keep it nice and tidy and feed that results from the aircon back into the flow.

It's very satisfying to ask Google to turn off the aircon, and then to see the fan icon spinning down on the iOS Home app!

I won't have a chance to do anything with this until the weekend, but thanks for your help.

1 Like

Try this:
curl -H 'Content-Type: application/json' -H 'Accept: application/json' -X PUT -d '{"ac1":{"info":{"state":"on","countDownToOn":"0","countDownToOff":"0"}}}' http://192.168.99.99:2025/setAircon?json=

Not sure if the url will work correctly but json data can be send by curl if it has a header apperently.

I just wanted to note that I have chosen an alternative solution to the problem; I have tried a number of solutions within node red, and whatever I do, I still get the hangup error.

My solution was to write a script in Python that handles the node red commands and queries via MQTT...

When node red receives a message from Google Home, Apple Homekit, or the node red UI, to change or query the status of the aircon, it publishes an MQTT message with the appropriate command or query. The MQTT message is received by the Python script, which sends the request to the aircon unit. The script then parses the response from the aircon, and feeds that result back to node red via an MQTT message, so node red can update the UI, Google Home and Apple Homekit with the current status.

I spent many hours trying to solve this issue in node red (with the help of forum contributors), and decided to take the pragmatic approach; I created a proof of concept in Python within an hour, and then finished script after an additional hour (it's a while since I used MQTT in Python). Fewer than 50 lines of Python code were needed.

Incidentally, it appears that some of the 'json' that is returned from the aircon (specifically when I do a full status query), is malformed; I had to write my own parser to pull out the data that I needed. I now only need to add a few lines of code to be able to do things like query and set the temperatures in individual rooms.

I'd like to thank those of you who offered assistance; your help is much appreciated. I'm a little disappointed that I couldn't solve it in node red, but more than happy to have a working solution with accurate feedback from the aircon.

1 Like

I ran into the exact same problem today while writing my first nodejs homebridge plugin to work with my Advantage Air aircon system. Reading the link you provided on what does socket hang up actually mean, I noted mention of blocking because of user-agent. So I set the user-agent in the http.get options and the issue was solved (no need to do any encoding).

You can literally put anything in user-agent and it will work
headers: {
'User-Agent': 'Issue Solved'
}

4 Likes

@stevewilliam007 what does installing itunes have to do with Node-RED?

Have flagged their response as spam. We get posts linking to that iTunes Support url on occasion and they are usually caught by the spam filter. If @stevewilliam007 is a legitimate user and they posted that in good faith, then my apologies...

I've just solved this problem with my own Advantage Air controller today.
I ended up using a string instead of a json object.
My url ended up looking like this:

http://192.168.0.111:2025/setAircon?json={"ac1":{"info":{"state":"{{payload}}"}}}

With {{payload}} being either "on" or "off".

Not ideal but it just wouldn't parse otherwise.

Okay im a new user so i have to split this into multiple posts becuase of some silly rule about images when i tried to post this first...

Here is a guide for you all :slight_smile:

Hello, I wanted to reply to this as i've just figured it out for my own advantage air system.

@dwagner is 100% correct, you need to add a User-Agent set to anything for the system to even talk to you, however in my case it was also throwing errors about being unable to parse the json so i will present my solution as a whole here.

Here is a working example

the inject node will put a json object, that contains your request to the AC system
image

1 Like

This is then passed into a function that executes the following code.
image
1, this will add a property to the msg object called 'json' containing the stringified result of the json in the payload from the inject node.
2, it will then replace all instances of " with %22 as node red will use a http encode on the field rather than a url encode this means that without this step it will change " into " and since we're using it in a url we need %22
3, it adds a headers object and sets the User-Agent to Testd anything can go here.

Finally, we take advantage of mustache templating to inject the json object directly onto the url, don't use the 'append msg.payload' feature as it will http encode rather than url encode the string and this will cause the airconditioner server to end your connection.

An example of how I've got mine setup in a full configuration that allows voice control is as follows

I'm using gbridge connected to my google home account when i say something like "Hey google, turn on the ac" or "Hey google start the aircon" it will come in through those nodes, they get converted into "on /off" since they arrive as 0,1,start,stop that is piped back into gbridge so you can ask "Hey google is my ac on" and it will respond correctly.

Then, i format the json object as in my example above, inject the headers and talk to the control panel server all the same as the example above.

Hope this helps! Enjoy your $50 raspberry pi smart aircon :stuck_out_tongue:

You can literally put anything in user-agent and it will work

My issue was the node "http request" was getting the error "Error: socket hang up" from a Wix.com site running HTTPS with a Let's Encrypt certificate. All other SSL sites worked fine but for some reason Wix.com with LE cert will NOT work without a User-Agent header set.

Set msg.headers to JSON {"User-Agent":"Mozilla/5.0 (compatible; node-red/1.0.6)"}

I recommend that if the header is not set by the flow that node-red use a default agent header as

"Mozilla/5.0 (compatible; node-red/1.0.6)"

image