Flask-SocketIO: socketio.emit not working with Raspberry Pi GPIO Event Callback

Hi

I’m trying to add a flowmeter to my Raspberry Pi web app. The flowmeter is attached via GPIO and I’m listening for GPIO Events. When an event occurs the callback method gets called. Inside this method I like to send an update via websocket to the client. Unfortunately I don’t receive an event on client site. Any idea why I don’t get data on the client site?

def callback(channel):
    socketio.emit('UPDATE_FLOWMETER', "DATA", namespace='/test')
  
def initFlowmeter(data):
    import RPi.GPIO as GPIO
    GPIO.setmode(GPIO.BCM)  
    try:
       # SETUP GPIO PIN
        GPIO.setup(data.gpio, GPIO.IN, pull_up_down=GPIO.PUD_UP)
       # ADD GPIO CALLBACK 
        GPIO.add_event_detect(data.gpio, GPIO.RISING, callback=callback, bouncetime=20)
    except Exception as e:
        print e
    

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Comments: 19 (7 by maintainers)

Most upvoted comments

@sierrodc I have been working on a similar project which uses the GPIO library to detect when a button is pressed and then update the client side. After trying many different configurations, I ultimately found a solution by forcing the websocket to use gevent with monkey patching instead of eventlet. I’m not sure why this made a difference, but it worked for me. `from gevent import monkey monkey.patch_all()

app = Flask(name) socketio = SocketIO(app, async_mode=‘gevent’)`

I’m happy to share more of my code with you if that doesn’t help.

I’ve this kind of issue too.

If I put “socketio.emit” command elsewhere in my application, it works fine. Inside GPIO callback it doesn’t. Maybe because GPIO.add_event_detect is creating a background thread to control I/O and to invoke the callback and ( maybe) inside the thread there are some issues.

I’m using eventlet, with eventlet.moneky_patch() invocation just after imports.

Workaround: Basically do not use add_event_detect, but create yourself a thread (using eventlet.spawn) that check IO status:

def checkIO():
  while(True):
    currentIO = GPIO.input(pinNumber)
    if currentIO != previousIO:
      previousIO = currentIO
      if currentIO == 1: # RISING
        socketio.emit(...)
    eventlet.sleep(0.1)