I tested the sample code, with some minor modification (using local Blynk Server, and different pins for NodeMCU).
I haven’t found any problem as you described :
But when i force close the app (ios) and press the physical button , the state will not be updated or synced to the app.
I tested and everything is OK:
a) Press physical button, see VPIN status and LED changed on APP, iOS Version 2.26.1 (9)
b) Close iOS APP
c) Press physical button, see VPIN status and LED changed on APP
d) Open APP, the button is changed according to physical button pressed (how many times) and LED status.
And if i press the physical button fast enough like one press per 2 seconds then it works for couple of push and later the app will not update the state of the button.
Again, I pressed the physical button repetitively (faster than once per 2s) and the VPIN button is responding correctly for quite a while.
So, I guess
your Network / Router / Blynk Local Server (settings
) are creating the issue:
- the TCP packets are somehow dropped on the way to Blynk Local Server and not being resent. Therefore creating issue 2 => issue 1. Low possibility.
- The Blynk Local Server load was too high then and it couldn’t handle / ignore the packets / clients ?? Issue 2 and /or issue 1. Medium possibility.
- The Blynk Local Server default settings can limit certain number of msgs to be sent/received for clients. It can drop packets in that situation => issue 2 => issue 1.
High possibility
.
- Your ISP (if you use
DDNS
service) / Router / etc. can drop packets and we can’t control and know where and when. Low possibility.
It’s a little bit strange to me. If reliable TCP/IP
(not UDP/IP) protocol is used, the TCP/IP sender will automatically resend packets
if previous packets were lost / dropped. Certainly it depends on how the TCP/IP stack was implemented in ESP8266 core
and if it’s really reliable or not !!!. We don’t know yet.
So my best guess now is that the Blynk Local Server is the culprit
.
What kind of Local Server are you using (RPi, PC, RPi Zero W, etc…)?
If possible, you can try using the same code
as I do and see if the issue persists or not.
/* Comment this out to disable prints and save space */
#define BLYNK_PRINT Serial
#define USE_BLYNK_WM false //true
#include <ESP8266WiFi.h>
#if USE_BLYNK_WM
#include <BlynkSimpleEsp8266_WM.h>
#else
#include <BlynkSimpleEsp8266.h>
#endif
// You should get Auth Token in the Blynk App.
// Go to the Project Settings (nut icon).
char auth[] = "YourAuthToken";
#define PIN_LED 2 // Pin D4 mapped to pin GPIO2/TXD1 of ESP8266, NodeMCU and WeMoS, control on-board LED
#define PIN_D3 0 // Pin D3 mapped to pin GPIO0/FLASH of ESP8266
// Set your LED and physical button pins here
const int ledPin = PIN_LED; //D5; //7;
const int btnPin = PIN_D3; //D6; //8;
#define BLYNK_BUTTON_PIN V6
BlynkTimer timer;
void checkPhysicalButton();
int ledState = LOW;
int btnState = HIGH;
// Every time we connect to the cloud...
BLYNK_CONNECTED()
{
// Request the latest state from the server
Blynk.syncVirtual(BLYNK_BUTTON_PIN);
// Alternatively, you could override server state using:
//Blynk.virtualWrite(BLYNK_BUTTON_PIN, ledState);
}
// When App button is pushed - switch the state
BLYNK_WRITE(BLYNK_BUTTON_PIN)
{
ledState = param.asInt();
digitalWrite(ledPin, ledState);
}
void checkPhysicalButton()
{
if (digitalRead(btnPin) == LOW)
{
// btnState is used to avoid sequential toggles
if (btnState != LOW)
{
// Toggle LED state
ledState = !ledState;
digitalWrite(ledPin, ledState);
// Update Button Widget
Blynk.virtualWrite(BLYNK_BUTTON_PIN, ledState);
}
btnState = LOW;
}
else
{
btnState = HIGH;
}
}
void setup()
{
// Debug console
Serial.begin(115200);
Serial.println("\nStarting");
pinMode(ledPin, OUTPUT);
pinMode(btnPin, INPUT_PULLUP);
digitalWrite(ledPin, ledState);
#if USE_BLYNK_WM
Blynk.begin();
#else
Blynk.begin(auth);
#endif
// Setup a function to be called every 100 ms
timer.setInterval(100L, checkPhysicalButton);
}
void loop()
{
Blynk.run();
timer.run();
}
You can also try modifying server.properties
to the extreme as follows to see if it’s better.
...
#maximum number of tags allowed per account
user.tags.limit=1000
#defines maximum allowed number of user dashboards. Needed to limit possible number of tokens.
user.dashboard.max.limit=400
#defines maximum allowed widget size in KBs as json string.
user.widget.max.size.limit=200
#user is limited with 100 messages per second.
user.message.quota.limit=100
#maximum allowed number of notification queue. Queue responsible for processing email, pushes, twits sending.
#Because of performance issue - those queue is processed in separate thread, this is required due
#to blocking nature of all above operations. Usually limit shouldn't be reached.
notifications.queue.limit=2000
#Number of threads for performing blocking operations - push, twits, emails, db queries.
#Recommended to hold this value low unless you have to perform a lot of blocking operations.
blocking.processor.thread.pool.limit=12
#this setting defines how often we can send mail/tweet/push or any other notification. Specified in seconds
notifications.frequency.user.quota.limit=2
#this setting defines how often we can send webhooks. Specified in miliseconds
webhooks.frequency.user.quota.limit=1000
#this setting defines how big could be response for webhook GET request. Specified in kbs
webhooks.response.size.limit=72
#maximum size of user profile in kb's
user.profile.max.size=2048
#number of strings to store in terminal widget
terminal.strings.pool.size=25
#number of strings to store in map widget
map.strings.pool.size=25
#number of strings to store in lcd widget
lcd.strings.pool.size=6
#maximum number of rows allowed
table.rows.pool.size=100
#period in millis for saving all user DB to disk.
profile.save.worker.period=60000
#period in millis for saving stats to disk.
stats.print.worker.period=60000
#max size of web request in bytes, 256 kb (256x1024) is default
web.request.max.size=524288
#maximum number of points that are fetched during CSV export
#43200 == 60 * 24 * 30 - minutes points for 1 month
csv.export.data.points.max=43200
#specifies maximum period of time when hardware socket could be idle. After which
#socket will be closed due to non activity. In seconds. Default value 15 if not provided.
#leave it empty for infinity timeout
hard.socket.idle.timeout=30
#enable DB
enable.db=false
#enable raw data storage to DB
enable.raw.db.data.store=false
#size of async logger ring buffer. should be increased for loads >2-3k req/sec
async.logger.ring.buffer.size=81920
....