Dave H
Dave H

Reputation: 21

Server using socketio.emit is failing to broadcast an event for my client to receive (all local and connecting otherwise)

first time using stackoverflow - apologies if I do something wrong.

I've been trying for a few days to create a react-based web app that can interact with LEDs and switches on a raspberry pi. The approach I took is:

  1. An rpi4 running a python script importing flask, flask_socketio and gpiozero controlling and exposing the GPIO. Gevent is also installed.
  2. The same rpi serving a production build of a react web app importing socket.io-client

The script and web app both run easily, the websocket connects and connection/disconnection events are accessible in the client. When I try to perform a server-originated event based on a physical GPIO switch the function runs and prints to the server script, but the socketio.emit command either doesn't send or isn't triggering my React useEffect listener.

I've been going through every example I can find online as well as the docs and API for the libraries - if someone can see what I'm doing wrong I'd love the help!

Here's the barebones react app client - app.js:

import './App.css';
import { io } from 'socket.io-client';
import { useState, useEffect } from 'react';
import { Panel } from './components/Panel';

const socket = io('localhost:5001/', {
  transports: ['websocket'],
  cors: {
    origin: 'http://localhost:3000/',
  },
});

function App() {
  const [connected, setConnected] = useState(false);
  useEffect(() => {
    socket.on('connect', () => {
      setConnected(true);
    });

    socket.on('disconnect', () => {
      setConnected(false);
    });

    socket.on('switch', data => {
      console.log('Incoming data from socket:');
      console.log(data);
    });

    return () => {
      socket.off('connect');
      socket.off('disconnect');
      socket.off('switch');
    };
  }, []);

  console.log(socket);
  return (
    <div className="App">
      <header className="App-header">
        <h1>Panel Websocket Interface v2.1</h1>
        <p>Connected: {'' + connected}</p>
        <Panel socket={socket} />
      </header>
    </div>
  );
}

export default App;

And here's server.py


from flask import Flask, request, jsonify
from flask_socketio import SocketIO, emit
from flask_cors import CORS
from gpiozero import LED, Button

# GPIO panel definitions
LEDS = ["red", "yellow", "green"]
LED_PINS = [2,3,4]
LED_STATUS = [0,0,0]
SWITCHES = ["one"]
SWITCH_PINS = [27]
SWITCH_STATUS = [0]

# setup GPIO
redLed=LED(4)
yellowLed=LED(3)
greenLed=LED(2)

switch1=Button(27)

redLed.source = switch1

# create a new Flask app
app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret!'
CORS(app,resources={r"/*":{"origins":"*"}})
socketio = SocketIO(app,cors_allowed_origins="*")

@app.route("/http-call")
def http_call():
    """return JSON with string data as the value"""
    data = {'data':'This text was fetched using an HTTP call to server on render'}
    return jsonify(data)

@socketio.on("connect")
def connected():
    """event listener when client connects to the server"""
    print(request.sid)
    print("client has connected")
    emit("connect",{"data":f"id: {request.sid} is connected"})

@socketio.on('data')
def handle_message(data):
    """event listener when client types a message"""
    print("data from the front end: ",str(data))
    emit("data",{'data':data,'id':request.sid},broadcast=True)

@socketio.on("disconnect")
def disconnected():
    """event listener when client disconnects to the server"""
    print("user disconnected")
    emit("disconnect",f"user {request.sid} disconnected",broadcast=True)

# switch handlers

def switch1On():
    print("Switch 1 on")
    socketio.emit('switch',{'id':1,'state':1});

def switch1Off():
    print("Switch 1 off")
    socketio.emit('switch',{'id':1,'state':0});

switch1.when_pressed = switch1On
switch1.when_released = switch1Off

if __name__ == '__main__':
  socketio.run(app, debug=True,port=5001)

Upvotes: 1

Views: 405

Answers (1)

Dave H
Dave H

Reputation: 21

As Miguel suggested, the issue was with the async features of flask-socketio and gpiozero conflicting. I solved this problem in the end by rebuilding the program using a nodejs server and onoff which works perfectly. Thanks for the help!

Upvotes: 1

Related Questions