Python App Emulator

Yes, exactly like that

The function gets called everytime the timer triggers (from memory every 3 seconds after the program starts)

In the function

global blynkapp

States that tehre is a variable called blynkapp that happens to be a global variable

The line I asked you to add calls the blynk class created earlier and asks it to return the result of connected() which is true when authentication is complete and false otherwise

So in this case, everytime the timer triggers, if we are not connected the function will do nothing (just return)

My Blynk Server hates me…

2021-06-14 01:36:27,672 [INFO]  Authenticating user: <REDACTED>@gmail.com
2021-06-14 01:36:27,688 [DEBUG]  Sending BlynkLoginMessage - BlynkCommand(Login) ID(1): ['<REDACTED>@gmail.com', 'ZvA1i+O1MUmo+TkxqztW5VlQiFBKvfPvWQhQdCDPGhQ=', 'Python App', '0.2.6_app', 'Blynk']
2021-06-14 01:36:27,750 [DEBUG]  Received BlynkMessage - BlynkCommand(Response) ID(1): [3]
2021-06-14 01:36:27,813 [ERROR]  Auth stage failed: User not registered

Too many servers… OK this time I tried my original one on the RPi (last time was my .ddns.net)

2021-06-14 01:39:43,308 [INFO]  Connecting to 10.10.3.13:9443
2021-06-14 01:39:43,324 [INFO]  Using SSL socket...
2021-06-14 01:39:43,558 [INFO]  Connection to Blynk server established
2021-06-14 01:39:43,574 [DEBUG]  Request(auth details)
2021-06-14 01:39:43,574 [INFO]  Authenticating user: <REDACTED>@gmail.com
2021-06-14 01:39:43,574 [DEBUG]  Sending BlynkLoginMessage - BlynkCommand(Login) ID(1): ['<REDACTED>@gmail.com', 'ZvA1i+O1MUmo+TkxqztW5VlQiFBKvfPvWQhQdCDPGhQ=', 'Python App', '0.2.6_app', 'Blynk']
2021-06-14 01:39:43,605 [DEBUG]  Received BlynkMessage - BlynkCommand(Response) ID(1): [200]
2021-06-14 01:39:43,621 [INFO]  User successfully authenticated
2021-06-14 01:39:43,621 [DEBUG]  Event(connect) -> ()
2021-06-14 01:39:43,621 [INFO]  Requesting user profile/dashboards
2021-06-14 01:39:43,621 [DEBUG]  Sending BlynkMessage - BlynkCommand(Load Profile) ID(2): []
2021-06-14 01:39:43,636 [DEBUG]  Recording message awaiting reply BlynkMessage - BlynkCommand(Load Profile) ID(2): []
2021-06-14 01:39:44,324 [ERROR]  Message length error: Received 16377 bytes, expected 18547
2021-06-14 01:39:44,402 [WARNING]  Unhandled Event(disconnect) -> ()

:rofl:

At least you now have gotten to the authentication stage, the app is sending the login message and the Blynk server is responsing with (1) which equals the Blynk Command Response and the response code 3 which equals User not registered, so that username is not registered as a valid user on the Blynk server you are connecting to

I run my Blynk server on a real server, not a Raspberry Pi, perhaps the Pi is too slow to send the data and the message is not being read all in real time

Try again to increase the Timeout, perhaps from 0.05 to 0.10 and see if that helps

I’ll add to this, the library reads the first 7 bytes from the server. If there is NO data at all, it assumes there is no message at present and so just returns and tries again later

If seven bytes is read, it parses the header, figures out how many more bytes to read and then grabs those as well, all in one go. If it doesn’t get all those bytes in one hit then it fails with the error you saw

:stuck_out_tongue_closed_eyes:

Well… I am not a real programmer, so it fits :smiley:

1 Like

Well, I adjusted the SOCK_TIMEOUT a bit (it is an old RPi3 :stuck_out_tongue: ) between 0.05 and 1 but still the same error.

I am wondering if I missed a step, as even at 1 seconds the loop is immediate, not the expected “20 times waiting for an authentication” … or am I mixing two issues /patches here (look at me, trying to think but nothing happens :crazy_face: )

2021-06-14 01:57:44,776 [INFO]  User successfully authenticated
2021-06-14 01:57:44,776 [DEBUG]  Event(connect) -> ()
2021-06-14 01:57:44,776 [INFO]  Requesting user profile/dashboards
2021-06-14 01:57:44,791 [DEBUG]  Sending BlynkMessage - BlynkCommand(Load Profile) ID(2): []
2021-06-14 01:57:44,791 [DEBUG]  Recording message awaiting reply BlynkMessage - BlynkCommand(Load Profile) ID(2): []
2021-06-14 01:57:44,869 [ERROR]  Message length error: Received 16377 bytes, expected 18704
2021-06-14 01:57:44,932 [WARNING]  Unhandled Event(disconnect) -> ()

It wants 2327 more bytes… This is Python, so can I just add that in with an import 2327bytes :stuck_out_tongue_closed_eyes:

Yep, it is 2am… the crazy is real.

I am going to call it a night… clean up my servers a bit tomorrow and see if I feel like another stab at it later.

Thanks for your time @jaybee73, allowing me to turn your demo into a demolition :laughing:

BTW. over the last while I have been testing with a project called py app test that contains 1 button and one display, both set to V0 (just so they show a dynamic change without an active device)

blynkapp = {'dashname': 'py app test', 'widgets': {'button': {}, 'sensor': {}}}

Not sure of the demo needs just the name, or am I to spoon-feed it all the data?? If not, what is it supposed to do anyhow with/to the widgets?

The app still uses port 443, but an app update was needed to be able to connect (if I remember correctly), so something changed.
All connected with the move to Blynk 2.0 as far as I know.

Pete.

I’ll answer this first as it is easier

It will find the dashboard called “py app test”

It will then search that dashboard and look for a widget with the label “button” and a widget with the label “sensor”

If it finds all this, then the program gets into the business end:

  1. The program will get the state of the current widgets (button and sensor) and save them
  2. Every 30 seconds the program will flip the value of button and send that as a virtual write to the dashboard.
  3. The Blynk server will forward all state changes to all widgets to the app which will collate and log them to the screen

This has the effect of logging any changes from the IoT device connected to (if it measures temperature, it will display the temperature everytime it changes, if it has a push button, it will update the state of that button to screen). It also has the effect of you toggling the “button” widget from on->off->on->off every 30 seconds

Sounds like the code was fixed to ignore the expiry date on the certificate

1 Like

The 20 times loop is ONLY for the authentication step (sending username/password and waiting for a reply in the __authenticate() method)

Otherwise, the blynk.run() command will call __process_server_msg() which will call BlynkMessage.ReadSocketMessage() to get the next packet

One thing you can try is to comment out the following two lines in __recv_bytes()

 if len(readbuf) != length:
            raise BlynkError(f'Message length error: Received {len(readbuf)} bytes, expected {length}')

This will at least let the function continue and see what happens. I am not sure if that will work as the response to the command (18704 bytes) is gzipped and needs to be uncompressed to get to the next step. Who knows what will happen if that fails

The interesting thing with 16377 is that if you add the header (7 bytes) it is exactly 16kB

Without debugging on my end, try the following as all the code in the __recv_bytes() function

readbuf = b''
try:
    self.__socket.settimeout(self.SOCK_TIMEOUT)
    now = time.time()
    while len(readbuf) != length and time.time() < now + 2:
        readbuf += self.__socket.recv(length - len(readbuf))
        if len(readbuf) == 0: raise BlynkError(f'Connection closed by server')

    if len(readbuf) != length:
        raise BlynkError(f'Message length error: Received {len(readbuf)} bytes, expected {length}')
    return readbuf

except (IOError, OSError) as err:
    raise BlynkTimeoutError(f'Timeout on socket - {err}')

__recv_bytes() is used to read length bytes from the server and return them OR fail with one of two possible errors (Connection closed or Message length error)

This change will get the current time, then loop until EITHER:

  • All the requested bytes are read
  • OR 2 seconds has elapsed

In the loop, it will try to read how ever many remaining bytes are expected from the server failing with error if the connection has been closed

When the loop terminates, if the total number of bytes read is too low, then it raises that error message instead

In case I misread your question here, you should replace ‘button’ and ‘sensor’ with whatever label you gave the button and display in the Blynk app/dashboard

:rofl: