Reputation: 21
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:
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
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