Server-code communication issue (Python)

Hi,

I experienced a strange occurrence yesterday and I’m sharing it to see if anyone has experienced something similar.

HW used:
RPI B+ with latest patches and libs, included BlynkLib 2.0.
Fiber-optical Internet connection to blynk-cloud.com server.

The Blynk code is used to activate several relays, read several relays status, read the CPU’s temperature and the board’s external IP.

Said code is run as a Service. The Blynk server connection is monitored by a routine triggered every five minutes in crontab. If no code-server connection is detected, the service is restarted.

Additionally, to prevent possible disconnections, the loop is wrapped by the try/catch routine as:

if __name__ == "__main__":
    init() #run once
    while True:
      try:
        blynk.run()
        timer.run()
        #machine.idle()
      except socket.error as e:
        if(e.errno != errno.EPIPE):
          logging.exception("msg from blynkmain @ " + str(dt.now()))
          raise
        blynk.connect()

This way, I’m assuring a steady and stable Internet connection (so I thought). The code is been running flawlessly since BlynkLib2.0 has been published.

However, last night I had to trigger a relay via the app and it didn’t work. The app turned on ok, the button changed its stage from OFF to ON and back to OFF but the relay didn’t come on, no errors were logged in /var/log/syslog, in /var/log/message nor in my own log file.

After forcing a service restart, the problem was solved but I was, defenetly, left with an ingognita to why the app tuned on, sent the signal to the server but it didn’t get to my code when existed an app-server-code connection :thinking:

All I can add is that on my RPi 3 (which also running my Local Server) I have a relatively simple Python script, controlling some GPIO pins via code and running counters. And it just sits there running 24/7 without any additional crontab (I use rc.local to start) or reconnection routines. Basically I have found it extremely stable without noting any App connection issues or script failure.

# === Start Blynk (this call should never return) ===
while True:
    blynk.run()

Mind you, I do NOT have BlynkTimer running is this particular code, I use import _thread for the counter.

Perhaps post your entire code so others can test it.

Thanks @Gunner but I’m not using a local server as I don’t trust my home server however, I could switch to it for testing purposes.

I don’t think the issue is with the code but… here it is:

#!/usr/bin/python3
#import libraries
from __future__ import print_function
import BlynkLib
from BlynkTimer import BlynkTimer
import time, json
import logging
import socket, errno
from datetime import datetime as dt
from mail import sendmail
from subprocess import check_output
from wgpio import * #from gpio.py script

VERSION = '2.0'  #adapted to BlynkLib 2.0 

# ** define colours needed **
#define BLYNK_GREEN     "#23C48E"
#define BLYNK_BLUE      "#04C0F8"
#define BLYNK_YELLOW    "#ED9D00"
BLYNK_RED = '#D3435C'
#define BLYNK_DARK_BLUE "#5F7CD8"
#define PURPLE          "#800080"
#define BLUE_VIOLET     "#8A2BE2"
#define BROWN           "#A52A2A"
#define DARK_CYAN       "#008B8B"
#define DARK_MAGENTA    "#8B008B"
#define DARK_ORCHID     "#9932CC"
#define FUCHSIA         "#FF00FF"
#define MAROON          "#800000"
#define TEAL            "#008080"
WHITE = '#FFFFFF'
BLACK = '#000000'

logging.basicConfig(filename='/home/pi/blynk.log',level=logging.DEBUG)

BLYNK_AUTH = '*****'

# Create BlynkTimer Instance
timer = BlynkTimer()

#virtual button pins
virbtns = [0,1,2,3,4,5,6,7,8,9,10]

# Initialize Blynk
blynk = BlynkLib.Blynk(BLYNK_AUTH)

#set variables
txt = "" #used for the email
set_hr = 9 #opening hour
set_min = 0 #opening minute
oldtime = 0 #used for opening time
#sblinds = 5 #blinds' det switch

#virtual leds micros
@blynk.ON('readV11')
def S_read_handler():
  if(ledsOn(0)):
    blynk.virtual_write(11, 0)
  else:
    blynk.virtual_write(11, 255)

@blynk.ON('readV12')
def XL_read_handler():
  if(ledsOn(1)):
    blynk.virtual_write(12, 0)
  else:
    blynk.virtual_write(12, 255)

@blynk.ON('readV13')
def XXL_read_handler():
  if(ledsOn(2)):
    blynk.virtual_write(13, 0)
  else:
    blynk.virtual_write(13, 255)

@blynk.ON('readV14')
def S1_read_handler():
  if(ledsOn(3)):
    blynk.virtual_write(14, 0)
  else:
    blynk.virtual_write(14, 255)

@blynk.ON('readV15')
def S2_read_handler():
  if(ledsOn(4)):
    blynk.virtual_write(15, 0)
  else:
    blynk.virtual_write(15, 255)

#updating virtual leds
def update_leds():
  S_read_handler()
  XL_read_handler()
  XXL_read_handler()
  S1_read_handler()
  S2_read_handler()

@blynk.ON('V0')
def S1_write_handler(value):
  if int(value[0]) == 1: # is the button pressed?
    relayOn(0)

@blynk.ON('V1')
def S2_write_handler(value):
  if int(value[0]) == 1:
    relayOn(1)

@blynk.ON('V2')
def S_write_handler(value):
  if int(value[0]) == 1:
    relayOn(2)

@blynk.ON('V3')
def XL_write_handler(value):
  if int(value[0]) == 1:
    relayOn(3)

@blynk.ON('V4')
def XXL_write_handler(value):
  if int(value[0]) == 1:
    relayOn(4)

@blynk.ON('V5')
def sirena_write_handler(value):
  if int(value[0]) == 1:
    relayOn(5)

btnStatus = 0

@blynk.ON('V16')
def btn_handler(value):
    global btnStatus
    btnStatus = int(value[0])
    if btnStatus == 1:
      blynk.set_property(6, 'offLabel', 'Activado')
      blynk.set_property(6, 'offColor', WHITE)
      blynk.set_property(6, 'offBackColor', BLYNK_RED)
    else:
      blynk.set_property(6, 'offLabel', 'Desactivado')
      blynk.set_property(6, 'offColor', BLACK)
      blynk.set_property(6, 'offBackColor', WHITE)

@blynk.ON('V6')
def blinds_write_handler(value):
  if (int(value[0]) == 1 and btnStatus == 1):
      relayOn(6)

@blynk.ON('V7')
def cx_write_handler(value):
  if int(value[0]) == 1:
    relayOn(7)

@blynk.ON('V8')
def door_write_handler(value):
  if int(value[0]) == 1:
    relayOn(8)

@blynk.ON('V9')
def lights_write_handler(value):
  if int(value[0]) == 1:
    relayOn(9)

@blynk.ON('V10')
def wifi_write_handler(value):
  if int(value[0]) == 1:
    relayOn(10)

@blynk.ON('readV18')
def get_external_ip():
    fname = "/home/pi/data/data.json"
    f = open(fname, "r")
    data = json.load(f)
    ext_ip = data["ext_ip"]["ext_ip"]
    f.close()
    blynk.virtual_write(18, ext_ip)

@blynk.ON('readV19')
def cpu_temp():
    cmd = 'vcgencmd measure_temp'
    t = check_output(cmd, shell = True).decode("utf-8")
    t = t.rstrip('\n\r')
    t = t.replace('temp=','')
    t = t.replace("'C",'')
    #t = t + 'ºC'
    blynk.virtual_write(19, t)

@blynk.ON('readV17')
def rpi_uptime():
    #get board total uptime
    cmd = 'uptime -p'
    t = check_output(cmd, shell = True).decode("utf-8")
    t = t.rstrip('\n\r') 
    t = t.replace('up','')
    #t = t.replace('day','d')
    #t = t.replace('days','d')
    #t = t.replace('hour','hr')
    #t = t.replace('hours','hr')
    #t = t.replace('minutes','m')
    #t = t.replace(',',' ')
    # this widget will show uptime..
    blynk.virtual_write(17, t)

@blynk.ON("connected")
def blynk_connected():
  print("Updating leds values from the server...")
  blynk.sync_virtual(11,12,13,14,15)

def open_blinds():
  global oldtime, txt
  t = time.localtime()
  newtime = t.tm_min
  if(t.tm_hour == set_hr and t.tm_min == set_min and not (oldtime == newtime)):
    txt = "Persiana abierta a las "
    txt += time.strftime("%H:%M:%S")
    relayOn(6) #open blinds
    if(sendmail(txt)):
      print('Email sent - open_blinds')
  oldtime = newtime

def checkAC():
  global txt, emailsent
  if(ACcheck() == 1):
    txt = "No hay electricidad en la tienda - hora: "
    txt += time.strftime("%H:%M:%S")
    if(sendmail(txt)):
      print('Email sent - checkAC')

#activate timers
timer.set_interval(2, update_leds) #update virtual leds 2 secs
timer.set_interval(14, open_blinds) #check for opening time 15 secs
timer.set_interval(61, rpi_uptime) #update uptime display 1 minute
timer.set_interval(120, cpu_temp) #check cpu temperature 20m
timer.set_interval(900, checkAC) #check for AC every 15m
timer.set_interval(1803, get_external_ip) #check for external ip 30 minutes

if __name__ == "__main__":
    init() #run once from wgpio.py
    while True:
      try:
        blynk.run()
        timer.run()
        #machine.idle()
      except socket.error as e:
        if(e.errno != errno.EPIPE):
          logging.exception("msg from blynkmain @ " + str(dt.now()))
          raise
        blynk.connect()

Bumping this up as the problem continues.

I noticed that after several hours/days running the code, the micros type

@blynk.ON('V0') 
def S1_write_handler(value):
  if int(value[0]) == 1: # is the button pressed?
    relayOn(0)

stop responding. However, micro

@blynk.ON('readV19')
def cpu_temp():
    cmd = 'vcgencmd measure_temp'
    t = check_output(cmd, shell = True).decode("utf-8")
    t = t.rstrip('\n\r')
    t = t.replace('temp=','')
    t = t.replace("'C",'')
    #t = t + 'ºC'
    blynk.virtual_write(19, t)

keeps working as the temperature/uptime data is pushed to the app.

Therefore, I can say that the code is communicating with the server OK and that there’s no disconnections errors.

Having said that, is there anyone who has experienced this type of problem?

TIA

Am I alone in this room? :sob:

Just you and a few pythons :snake:

“Snakes, why did it have to be snakes?”