washo4evr / Socket.io-v1.x-Library

Socket.io Library for Arduino
108 stars 58 forks source link

ESP8266 won't connect to server #1

Open deepikavira opened 8 years ago

deepikavira commented 8 years ago

@washo4evr, have you used this library for a server code written by you? In your comment you write that you are trying to connect to spark fun via HTTP commands. Please clarify if this is a socket.io connection that you are trying to establish or just a TCP connection.

washo4evr commented 8 years ago

I had forgotten to update the headet it is now done this library will not try to connect to sparkfun via HTTP you need to run a node.js server with socket.io installed and running on it. i have provided an example

washo4evr commented 8 years ago

you need to adjust char host[] = "192.168.0.5"; int port = 1234; to match your own server

deepikavira commented 8 years ago

Ok thank you so much for replying. I am stuck at getting the ESP connect to our server. I will try using your app.js code and see if I can connect to it.

washo4evr commented 8 years ago

let me know if you need any assistance running it. ESP is still considered beta

deepikavira commented 8 years ago

So now I ran your server. i.e app.js then I ran the Hello_Time_esp8266 code on the ESP module. It is able to connect to the wifi, and gets the ip address but for connection to server it fails. Here is the output

WiFi connected IP address: 172.16.42.43 172.16.42.43 connection failed.

I wanted to know if char host[] = "192.168.0.5"; int port = 1234; fields remain same while trying to connect to your server.

washo4evr commented 8 years ago

you need to adjust these 2 lines depending on your server if you used app.js then port should still be 1234 but you will have to change the IP to match yours

washo4evr commented 8 years ago

you will also need to update a line in index.html

to match your server IP

deepikavira commented 8 years ago

Can you tell me how to find what ip address did the server get?

washo4evr commented 8 years ago

you could use http://www.whatsmyip.org/ also, if you are trying to connect to a remote server (and not a local server running in a computer near you) you might have to redirect the port 1234 to you server IP address on the INO file, you would then put xxx.xxx.xxx.xxx (according to http://www.whatsmyip.org/) same for index.html and on your router, you would redirect all traffic for port 1234 to the local IP of the server (usually something like 192.168.0.55)

deepikavira commented 8 years ago

@washo4evr Thank you so much!!! I am able to connect to our servers now. Your library has made my day. I will keep you in loop as to how my project goes.

washo4evr commented 8 years ago

Awesome!! Glad I could be of some assistance Good luck with your project

deepikavira commented 8 years ago

One last question, can you throw some light on how you have implemented custom events in your code? Are you waiting on some specific message from the server to start listening to it?

washo4evr commented 8 years ago

you can send messages (in app.js or index.html) via socket.emit('arduino' ,"Hello World!"); or client.send (in arduino) and you can use RID in arduino code to check what you have received or socket.on('connection', function (data) {console.log(data); }); as long as the "word" matches on both ends, it will work I will update the example because 'atime' is not very explicit and include a full documentation as soon as I can

deepikavira commented 8 years ago

@washo4evr : I have been using your library for a week now. Its really helpful and I have been able to send some data to our server. We have a little problem now. We have a custom even named init device which expects "message" in the following form: client.send("init_device", "message", "\"{'device_id': '1111', 'device_model': '2'}\""); when I send this on our server side we don't receive any data. When I tried sending his same string without the quote marks i.e
client.send("init_device", "message", "{device_id: 1111, device_model: 2}"); we do receive the string but unfortunately we cannot parse it in json. If you have faced any issue of this kind do let me know. It would be helpful to discuss. I also noticed that if i send a single quote (') my server receives it as (\') why does the server adds this backslash on its own I have no idea.

washo4evr commented 8 years ago

Hey, I know why Rmessage can only be one word for now JSON will be added very soon it all comes down to the syntax of (inside socketio.cpp // function send) String message = "42[\"" + RID + "\",{\"" + Rname + "\":\"" + Rcontent + "\"}]"; I will modify it to accept JSON probably will be another function sendJSON or something that will allow to send formated strings I will keep you posted

deepikavira commented 8 years ago

Okay I will also try adding support on my end. Lets see if I can get something going. Thanks for replying

washo4evr commented 8 years ago

Hi, If you send something like

String message = "42[\"JSON\",{\"Date\":\"17.03.2012 15:28 : 47\",\"bindings\": [{\"ircEvent\": \"PRIVMSG\", \"method\": \"newURI\", \"regex\": \"^http://._\"},{\"ircEvent\": \"PRIVMSG\", \"method\": \"deleteURI\", \"regex\": \"^delete._\"},{\"ircEvent\": \"PRIVMSG\", \"method\": \"randomURI\", \"regex\": \"^random.*\"}]}]";

from the ESP8266, you need, inside app.js to add

function ParseJson(jsondata) { try { return JSON.parse(jsondata); } catch (error) { return null; } } socket.on('JSON', function (data) { // console.log(data); var jsonStr = JSON.stringify(data); var parsed = ParseJson(jsonStr); //console.log(parsed); console.log(parsed.bindings[0].ircEvent); });

the last console.log will return PRIVMSG

Im still adding support inside the library but that works already like that

washo4evr commented 8 years ago

I have updated the library as well as the esp8266 example and app.js

let me know if everything works

deepikavira commented 8 years ago

Okay will try the updated code on Monday. I don't have my gadgets with me at the moment! Thanks a lot.

deepikavira commented 8 years ago

@washo4evr . Hi so I tried with the updated code, I can send strings to my server without any problem now. Later I figured out that there was problem when I tried sending \" specifically.

I had a question for you though, like the client.send() method do you have any receive method that will display the message received from the server?

washo4evr commented 8 years ago

Im glad you got it working client.monitor() is the function that will get the reply it will update RID, Rname and Rcontent if you sent a regular client.send for now, until the next version, the JSON answer is not automatically parsed (RID will still be updated)

deepikavira commented 8 years ago

@washo4evr. Its been two weeks that I have tested my module on the server. Everything is fine except power failure. When my module gets accidentally powered down it cannot connect back to the server. I have to re-start my server instance each time something like this occurs. Upon debugging the code I found that this particular code snippet from your SocketIOClient.cpp file is where the client fails to connect to the server over web socket.

bool SocketIOClient::readHandshake() { ...... ..... .... .... ... // reconnect on websocket connection if (!client.connect(hostname, port)) { Serial.print(F("Websocket failed.")); return false;}

Why do we have to reconnect over websocket connection? Cant the communication go through socket.io itself

washo4evr commented 8 years ago

you need to do that after the upgrade, else you are not connected via websocket

on power loss, the module should be able to reconnect at the point, the server should give a new SID to the module

this is the behavior I get here

deepikavira commented 8 years ago

Hey so from what I understood is that we first establish a connection over socket.io then we upgrade and establish connection via websockets. once the websocket connection is done we then start sending data via custom events like atime etc.. Please correct me if I got it wrong

washo4evr commented 8 years ago

the 1st connection is a classic GET over TCP protocol then, the module ask to upgrade the server replies 101 switching protocol module closes TCP connection and reconnect using websockets

thats why the module checks for 101 before closing connection

deepikavira commented 8 years ago

When I get this kind of a response: Connected. SID=9ZuBP3v9QFvHjAIOAABJ Websocket failed.connection failed

Does it me that the classic GET over the TCP protocol goes through but the server didn't respond with 101 switching protocol hence the module responds back saying Websocket Failure?

washo4evr commented 8 years ago

if you get the SID, you should be able to do a websocket connection you could edit the CPP file to uncomment the serial.println used for debugging with that, you will have all the connection details on the serial console

let me know, we will figure it out

deepikavira commented 8 years ago

wifi connected IP address: Connecting to ec2-52-26-22-243.us-west-2.compute.amazonaws.comHTTP/1.1 200 OK Content-Type: text/plain; charset=UTF-8 Content-Length: 100 Access-Control-Allow-Credentials: true Access-Control-Allow-Origin: Arduino Set-Cookie: io=hIZusRncALhSzPkjAAAS Date: Wed, 16 Mar 2016 21:27:53 GMT Connection: keep-alive

97:0{"sid":"hIZusRncALhSzPkjAAAS","upgrades":["websocket"],"pingInterval":25000,"pingTimeout":60000} Connected. SID=hIZusRncALhSzPkjAAAS Websocket failed.connection failed

deepikavira commented 8 years ago

Hi Here is the output after uncommenting all the debugging print lines. I might have added a couple of print statements of my own. Lets analyze this. From the response HTTP/1.1 200 OK seems to be the response from the server. And the rest is the response for handshake I guess?

washo4evr commented 8 years ago

you get 200 OK for the 1st connection (TCP) the weird part is that you actually get the SID after that, it fails

while (client.available()) readLine(); client.stop(); delay(1000); // did you try changing the delay? maybe 1000 is too big / not enough since you are connecting far // reconnect on websocket connection if (!client.connect(hostname, port)) { //that line has no reason to not work because it is the same making the 1st connection Serial.print(F("Websocket failed.")); return false; }

do you know if amazonaws has some kind of time out? a restriction to avoid multiple connections?

I would 1st try to change the delay maybe 0, 500, 2000, 5000, 10000 just to see

deepikavira commented 8 years ago

I think I might have figured out the problem. in the readHandShake() function I added this feature.

// reconnect on websocket connection if (!client.connect(hostname, port)) { Serial.print(F("Websocket failed.trying again")); if (!client.connect(hostname, port)){ Serial.print(F("Websocket failed again")); return false;} }

Giving one extra chance to make connection and usually it fails once but on the second try it goes through and web socket connection is established. I will also try changing the delay maybe increasing the delay could solve the problem.

washo4evr commented 8 years ago

nice catch I will add that (or adjust the delay depending on your findings) to the next version

I have been busier than expected but the release is soon

deepikavira commented 8 years ago

Actually, this time it failed to connect both times. Do you think there could be a issue on the server side?

washo4evr commented 8 years ago

did you change the delay? it could be server related how fast does the 1st part go? is it quick to connect?

deepikavira commented 8 years ago

I did try 0 , 5000, 10000 delays so far. Yes the first part actually goes through in a second or two actually.

deepikavira commented 8 years ago

https://www.youtube.com/watch?v=sQ4PkcvcJmU&feature=youtu.be

In this video I have tried to capture the output window, the delay is 2000 before it tries to connect over Websocket

washo4evr commented 8 years ago

the 1st wait is a bit long maybe amazonaws is far (ping high)

you could try to change the if by a while and see how long it takes (add a delay(500) to avoid spamming the server

Galilei11 commented 8 years ago

@washo4evr, Thank you for your work, I did try to use your socketio programs 4 days ago. It works but, I have a big problem, with the too long connecting time. After starts the Arduino it needs 18sec until goes to "Connecting via Websocket" and 61sec to "Upgrade to WebSocket confirmed" !!!!! I have red the comments above, i wrote these lines to cpp too: ...... if (!client.connect(hostname, port)){Serial.print(F("Websocket failed again"));.......

This is the timestamped log about it:

WiFi connected IP address: 10.1.0.100 was here: connect timestamp (ms): 1275 was here: ::sendHandshake timestamp (ms): 18048 was here: ::readHandshake timestamp (ms): 18048 was here: ::waitForInput timestamp (ms): 18048 was here: ::readLine timestamp (ms): 18048 HTTP/1.1 200 OK was here: ::eatHeader timestamp (ms): 18049 was here: ::readLine timestamp (ms): 18049 Content-Type: text/plain; charset=UTF-8 was here: ::readLine timestamp (ms): 18057 Content-Length: 100 was here: ::readLine timestamp (ms): 18065 Access-Control-Allow-Credentials: true was here: ::readLine timestamp (ms): 18073 Access-Control-Allow-Origin: Arduino was here: ::readLine timestamp (ms): 18082 Set-Cookie: io=dbrTorAM3M-ko-HBAAAF was here: ::readLine timestamp (ms): 18090 Date: Thu, 17 Mar 2016 09:39:18 GMT was here: ::readLine timestamp (ms): 18090 Connection: keep-alive was here: ::readLine timestamp (ms): 18098 was here: ::readLine timestamp (ms): 18107 97:0{"sid":"dbrTorAM3M-ko-HBAAAF","upgrades":["websocket"],"pingInterval":25000,"pingTimeout":60000} Connected. SID=dbrTorAM3M-ko-HBAAAF Connecting via Websocket was here: ::waitForInput timestamp (ms): 60787 was here: ::readLine timestamp (ms): 60787 HTTP/1.1 101 Switching Protocols was here: ::readLine timestamp (ms): 60788 Upgrade: websocket was here: ::readLine timestamp (ms): 60788 Connection: Upgrade was here: ::readLine timestamp (ms): 60788 Sec-WebSocket-Accept: HQ5C77iTalBq00QNQp3bAkwF7JY= was here: ::eatHeader timestamp (ms): 60796 was here: ::readLine timestamp (ms): 60796 was here: while (client.available() timestamp (ms): 61419 was here: ::readLine timestamp (ms): 61419 �40�40 was here: SocketIOClient::parser timestamp (ms): 61419 Message size = 2 Received message = 40 was here: SocketIOClient::parser case 4 timestamp (ms): 61419 Upgrade to WebSocket confirmed was here: SocketIOClient::parser case 40 timestamp (ms): 61420 was here: while (client.available() timestamp (ms): 61428 was here: ::readLine timestamp (ms): 61436 �_42["welcome",{"message":"Connected !!!!"}]�_42["welcome",{"message":"Connected !!!!"}] was here: SocketIOClient::parser timestamp (ms): 61444 Message size = 42 Received message = 42["welcome",{"message":"Connected !!!!"}] was here: SocketIOClient::parser case 4 timestamp (ms): 61461 RID = welcome Rname = message Rcontent = Connected !!!! 42["welcome",{"message":"Connected !!!!"}] was here: SocketIOClient::parser case 42 timestamp (ms): 61469 was here: connectedben timestamp (ms): 61478 was here: ::send(String timestamp (ms): 61478 {"sensor":"gps","time":1351824120,"data":[48.756081,2.302038]} was here: ::send(String timestamp (ms): 62301 was here: ::sendJSON timestamp (ms): 62910 was here: while (client.available() timestamp (ms): 63758 was here: ::readLine timestamp (ms): 63758 �/42["atime",{"time":"2016-03-17T09:40:03.346Z"}]�/42["atime",{"time":"2016-03-17T09:40:03.346Z"}] was here: SocketIOClient::parser timestamp (ms): 63758 Message size = 47

washo4evr commented 8 years ago

it is indeed a very long time to connect what board are you using? is the server remote or local? for instance, here, doing tests in local, it takes about 5 seconds to be connected with websocket

Galilei11 commented 8 years ago

I use nodeMCU1.0 -ESP-12E with Arduino IDE 1.6.7 and ESP8266 2.1.0-rc2 first I tried it on my local apache server (localhost) : 18sec until goes to "Connecting via Websocket" and 61sec to "Upgrade to WebSocket confirmed"

second I tried with remote remote server: 7sec until goes to "Connecting via Websocket" and 21sec to "Upgrade to WebSocket confirmed"

My sw and hw system can connect within 1sec with this arduino websocket, https://github.com/Links2004/arduinoWebSockets

washo4evr commented 8 years ago

Hi, I still had the 2.0.0 upgraded to 2.1.0 and it took 19 sec from ON to connected via socket with arduino 1.6.5. I don't know why it is even slower in your case when connecting locally Is it the same delay if you connect from your computer to your node server? what version are you running of node / socket?

Galilei11 commented 8 years ago

hi, I tried Hello_Time_ESP8266.ino with different ESP8266 core versions: 2.0.0-rc1 : connect time on local server 18sec and 61sec AND client.monitor() works 2.0.0-rc2 : connect time on local server 18sec and 61sec AND client.monitor() works 2.1.0-rc1 : connect time on local server 18sec and 61sec AND client.monitor() NOT works !!!

on local server the node install file is: node-v5.6.0-x64.msi

washo4evr commented 8 years ago

did you try after disabling your antivirus / firewall? I don't see a lot of possibilities for such long delays. wish I had a better answer for you... especially since next version won't change any of the connection parameters, only add new REST functions

Galilei11 commented 8 years ago

A new problem, in SocketIOClient::parser doesnt work well if the incoming socket lenght bigger than 126 byte, I think the program doesnt takes different between small and larger size of soket.

antivirus / firewall: I think if the antivirus / firewall makes the problem the connect never works, but it works with long delay.

Galilei11 commented 8 years ago

the problem, in SocketIOClient::parser fixed, now works

   int sizemsg = databuffer[index + 1];   // 0-125 byte, index ok
  if(databuffer[index + 1]>125)       
      { 
        sizemsg = databuffer[index + 2];    // 126-255 byte
        index+=1;       // index correction to start
      } 
washo4evr commented 8 years ago

awesome, great fix, thx. I will incorporate it in the next version

Galilei11 commented 8 years ago

Hi, pls help, I cant reconnect to server after I stop and start the socket.io server. I tried lot of combinations of connect, reconnect, disconnect, connected...... nothing success :( What is the solution? (client:nodeMCU 1.0 and server: socket.io 1.4.5)

washo4evr commented 8 years ago

you need to check for the absence of communication from the server and if nothing received for the last xxx seconds / minutes then, you can do client.stop or reconnect I will check something : maybe the server sends a special text to say that it is going offline, in which case, I could read that text and do auto client.stop.

i have been super busy recently, but the project is still alive.

deepikavira commented 8 years ago

@washo4evr Have you ever tried using a mobile app to feed the wifi SSID and Password into the chip at run time? I am trying to so that I can take my project anywhere and connect to the WIFI network available there without having to program the chip exclusively for my home WIFI where I have been developing the project

washo4evr commented 8 years ago

That is a great idea I have not tried it yet It would require running the ESP in access point mode, receive the data and then "reboot" to connect to another network.

I will give it a try, not sure when. I start my new job on monday. I will keep you posted