rjwats / esp8266-react

A framework for ESP8266 & ESP32 microcontrollers with a React UI
GNU Lesser General Public License v3.0
475 stars 147 forks source link

A propper way for refreshing the front-end state from the back-end. #195

Open saniyo opened 4 years ago

saniyo commented 4 years ago

Hello, I've got some time to check the new features in the framework. Some of them became useful like manual time, disabling unnecessary features, but the thing which is in my opinion is important I couldn't find a proper way to realize. Let's assume we have some system with a thermosensor, PID regulator, some executing mechanism, which affects the thermosensor. So in this scenario creating a page where the whole data will be visualized is a common practice, behind the scene there might be a settings page with all necessary parameters, etc, etc. For the visualization page, I think it's good to use the available WebSocket feature, for the settings page more reasonable and less memory consuming is REST. Having opened the visualization page the front-end has to be automatically refreshed as soon as the back-end receives fresh data from the sensor, corrects the output value of the PID, and has to only TX those data to the front-end and refresh its state each time the new data is processed in the back-end. To partially fulfill the desired feature I have created a loop method in the LightStateService class which is called in the main loop section, where the sensor, PID chore is executing successfully, but having received the new data I'm a bit confused how it is possible to transmit it upwards and refresh the visualization page. To check the front-end I was sending the updated JSON object directly to the WS using 3-rd parties WS chat software, the front-end was successfully refreshing its state. So here the problem comes how to generate the refresh state request from the back-end loop? Looking forward to your reply.

rjwats commented 4 years ago

What you are trying to do should be fairly easy with the event driven state services, there's a section in the docs which describes this here:

https://github.com/rjwats/esp8266-react/#stateful-service

In particular you should probably be looking at calling the update method on your stateful service instance from your management loop so it broadcasts the change to the any observers (WebSocket, MQTT etc...)

Feel free to share any code, I may be able to help better that way :)

saniyo commented 4 years ago

Thanks, for the fast reaction.

The draft code is:

void LightStateService::dutyLoop(){

  new_ts = millis();

  if (new_ts - ts > 1500) {

    _state.pv = sensors.getTempCByIndex(0);

    ts = new_ts;

    myPID.Compute();

    sensors.requestTemperatures();  // async temperature request

    analogWrite(pwmPin, pidPar.op);

    Serial.println("pv=" + String(_state.pv) + " sp=" + String(pidPar.sp) + " op=" + String(_state.op));

    callUpdateHandlers("websocket");

 }

Yup, it helped a bit, Frankly, I saw it refreshing a few times with further hanging of the WebSocket. Websocket page which looks at the moment image refreshes the lost WS connection. Here is the difference in logs between serial log and WS log, By the way, they are executed each time in the same place simultaneously. image

Any ideas about what to modify? Thanks.

saniyo commented 4 years ago

Having reduced the refresh rate to 5s, I got it working more stable. But periodically the test page tries to reconnect WS due to the lost WS connection.

rjwats commented 4 years ago

I've not seen WebSocket disconnects like that, though i've never tried updating over websockets on a timer before...

What platform are you on? esp8266?

saniyo commented 4 years ago

Hello, yes at the moment I'm run on esp8266, I have doubts regarding AsyncWebServer and its WebSocket implementation. 1 year ago I had some experience with it and saw more or less the same issue. But in comparison to this test project, the previous one was more loaded, and WS had to transmit excessively big JSON object via WS, ESP8266 was used as a transparent gateway between a Modbus RTU slave device and a Back-end interface on a client. The same behavior was noticed.

rjwats commented 4 years ago

Yes. The async suff looks cool on paper. The esp8266 is quite RAM limited though so supporting many concurrent clients all sending and recieving JSON isn't practical.

On Tue, 1 Sep 2020, 20:37 saniyo, notifications@github.com wrote:

Hello, yes at the moment I'm run on esp8266, I have doubts regarding AsyncWebServer and it's WebSocket implementation. 1 year ago I had some experience with it and saw more or less the same issue. But in comparison to this test project, the previous one was more loaded, and WS had to transmit excessively big JSON object via WS, ESP8266 was used as a transparent gateway between the Modbus RTU slave device and the Back-end interface on a client. The same behavior was noticed.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/rjwats/esp8266-react/issues/195#issuecomment-685089069, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAKE4VFFOZHIY3BYLHWSHITSDVEOLANCNFSM4QMY2KVA .

saniyo commented 4 years ago

Yes. The async suff looks cool on paper. The esp8266 is quite RAM limited though so supporting many concurrent clients all sending and recieving JSON isn't practical. On Tue, 1 Sep 2020, 20:37 saniyo, @.***> wrote: Hello, yes at the moment I'm run on esp8266, I have doubts regarding AsyncWebServer and it's WebSocket implementation. 1 year ago I had some experience with it and saw more or less the same issue. But in comparison to this test project, the previous one was more loaded, and WS had to transmit excessively big JSON object via WS, ESP8266 was used as a transparent gateway between the Modbus RTU slave device and the Back-end interface on a client. The same behavior was noticed. — You are receiving this because you commented. Reply to this email directly, view it on GitHub <#195 (comment)>, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAKE4VFFOZHIY3BYLHWSHITSDVEOLANCNFSM4QMY2KVA .

I didn't mean concurrent clients, the issue appears with a single one, The correct behavior of the back-end refreshes the connections so after each iteration, we have lots of dead clients.