vitotai / BrewManiacEsp8266

BrewManiac on ESP8266. Only ESP8266 needed.
155 stars 71 forks source link

sync HTTPClient in async webserver #1

Closed mkeyno closed 7 years ago

mkeyno commented 7 years ago

sorry for open ticket for my question but I 'm curious about how your HttpUpdateHandler class actually work without any problem with async library , I've notice user can manually requested for _firmwareUpdateStart and define remote server _firmwareUpdateUrl , when this request replied , set new status to US_FirmwareUpdatePending and in loop runUpdate() always check the status and when is US_FirmwareUpdatePending , ESPhttpUpdate.update(_firmwareUpdateUrl, _fwVersion); do the rest , however as you well aware ESPhttpUpdate.update use sync HTTPClientand probably not compatible with async client , I was wondering why use this approach without any problem ? why don't use async client to connect the remote server for update firmware thanks

vitotai commented 7 years ago

There are two parts of the HTTP Update.

  1. the interface, a web page for user It's simply a web page and some code to "change updating state" and "get information from user". It is run as parts of the Async Server.
  2. the execution, the updating action. The HttpUpdateHandler has a method "runUpdate()", which is called and run in the main loop. This method check the state/commands set by the web interface and execute it. The action runs SYNChronized HTTPClient.

The web serving code doesn't execute the action itself for some reason. One of the most important one is to keep the response time quick and reasonable. Moreover, invoking another network connection in the context of processing HTTP request is not a good idea, IMO.

There is already a ESPhttpUpdate library there, I don't want to create an ASYNC one.

mkeyno commented 7 years ago

The web serving code doesn't execute the action itself for some reason. One of the most important one is to keep the response time quick and reasonable. Moreover, invoking another network connection in the context of processing HTTP request is not a good idea, IMO.

actually this is part that I'm not really clear about it , because I thought asynWebServer is fast and lighter than syncServer and create new sync client may mess with async client whenever asynWebServer try to respond to one of them , that's why I was thinking this is better way to create async client to remote website and catch the respond with asynWebServer handler , please enlighten me what is my assumption is incorrect ? sometime may need to send the request to site like gmail.com and handle the respond , obviously we cant wait in asynWebServer , can you explain what is the best way for such job? thanks

vitotai commented 7 years ago

Geting the update image has nothing to do with the Asnyc WebServer. The Async WebServer serves the page to users and let users have a chance to start the action. How the action is performed depends on the design. The actions here are downloading files from another server. Yes, the download could be implemented by HTTP over Async TCP, but I don't because

  1. Synchronized connection is easier, and there is already a well-tested library there.
  2. My experience with Async TCP was not good enough. I've tried the Async file manager but found that uploaded files were truncated from time to time. I've also tried to port the ESP8266HTTPUpdateServer(the one that user upload binary image to update) to use Async Web server, but the system crashed.
  3. I suppose the updating operation is rarely done. During the updating, we care nothing but the updating. Therefore, it should not hurt anything by using SYNC HTTP client.
mkeyno commented 7 years ago

thanks @vitotai for clearing that up , I was headache to how to communicate with site like gmail, my attempt to send async client request to website and catch the respond by asyncWebServer was failure, also I've tried to create separate asyncServer and onDate handler for such purpose , but no success yet, as you said we probably nothing to do when updating by using SYNC HTTP client but it may not correct in other situation . I really appreciated to have your advise for this situation

vitotai commented 7 years ago

Are you trying to access GMAIL api on ESP8266? As far as I know, Google does not support HTTP, but only HTTPS. Although ESP8266 can do HTTPS, it needs a lot of memory. I've tried HTTTPs for Google Script. It worked if there is no other code that allocates memory. Because I used a lot of memory for other jobs, HTTPS is hence useless.

mkeyno commented 7 years ago

no just for google , actually it is Telegram , I want to control my module by Telegram bot as well, but not yet success to create the AsyncClient and connect to remote server and get the data by onData callback, my sketch look like following but every time I've tried to connect to server it crashed on call back function

 AsyncClient  *client;

void             onPoll(void *obj, AsyncClient* c){  Serial.printf("onPoll:%lu\n", millis());}//AcConnectHandler
void            onError(void *obj, AsyncClient* c, int8_t error) {  Serial.printf("onError:%d\n", error);}
void              onAck(void *obj, AsyncClient* c, size_t len, uint32_t time){  Serial.printf("onAck:%u:%u\n", len, time);}
void       onDisconnect(void *obj, AsyncClient* c) {  Serial.printf("onDisconnect\n");  c->free();  delete c;  client = NULL;}//AcConnectHandler
void          onTimeout(void *obj, AsyncClient* c, uint32_t time) {  Serial.printf("onTimeout:%u\n", time);  client->close();}
void             onData(void *obj, AsyncClient* c, void *buf, size_t len){
 Serial.printf("onData:%u\n", len);
  size_t i;
  for(i=0; i<len; i++){
    while(((U0S >> USTXC) & 0x7F) != 0);
      U0F = ((uint8_t*)buf)[i];
  }
}
void onClient(void *obj, AsyncClient* c){//AcConnectHandler
  if(client){    Serial.printf("r\n");    if(client->connected())     client->close();  }
  Serial.printf("c\n");
  client = c;
  client->onError(onError);
  client->onAck(onAck);
  client->onDisconnect(onDisconnect);
  client->onTimeout(onTimeout);
  client->onData(onData);
  client->onPoll(onPoll);
}

setup(){

....
 client->onError(onError);
  client->onAck(onAck);
  client->onDisconnect(onDisconnect);
  client->onTimeout(onTimeout);
  client->onData(onData);
  client->onPoll(onPoll);
.....
}
loop{

delay(5000);
connect2server();

}

void connect2server(void){

 client=  new AsyncClient();
      client->onError(onError);
  client->onAck(onAck);
  client->onDisconnect(onDisconnect);
  client->onTimeout(onTimeout);
  client->onData(onData);
  client->onPoll(onPoll);

client->connect("www.google.com",80);

}
vitotai commented 7 years ago

I can't help you. I don't have much experience with AsyncTcp.