Так что я считаю, что суть моей проблемы заключается в том, что обнаружение событий Python GPIO является многопоточным, как и в Socket.IO Emit. Я пытаюсь вызвать Emit, когда срабатывает обнаружение событий GPIO. И я получаю сообщения об ошибках, не ожидая socket.io.emit, когда я пытаюсь бросить await перед ним, я получаю неверный синтаксис. веб-клиент, когда прерывание происходит на IO. Например, мигает светодиод, я хочу отправить это клиенту. Использование socket.io передает сообщение клиентской части, а GPIO прерывает через обнаружение событий, выполняет другую часть (без привязки к приложению). Мне просто нужно отправить эти обнаружения событий из GPIO в socket.io, который излучает каким-то образом.
Также я использую веб-сервер Sanic.
В любом случае вот код:
sio = socketio.AsyncServer(async_mode='sanic')
app = Sanic()
sio.attach(app)
GPIO.setmode(GPIO.BOARD)
GPIO.setup(18, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
#this gets called when the gpio.add_event_detect event is hit upon the gpio pin #going high (led lighting up). This works fine except sio.emit needs to be #awaited, but if I throw an await in front of it I get bad syntax, I put async #in front of the function def and then I get errors saying I never awaited the #function my_callback_one when it gets called from the GPIO.add_event_detect #event firing. I'm not sure what to do or if this is possible.
def my_callback_one(channel):
sio.emit('my_response', {'data': 'test'})
print('========button press LED lighting detected========')
GPIO.add_event_detect(18, GPIO.RISING, callback=my_callback_one)
#Starts the web application
if __name__ == "__main__":
app.run(host='0.0.0.0', port= 8090, workers=4)
В нормальных условиях я мог бы делать потоки с веб-сервера в многопоточном режиме, например, так:
async def background_task():
count = 0
while count < 10:
await sio.sleep(.05)
print("message sent to client")
count += 1
await sio.emit('my_response', {'data': count})
pass
@app.listener('before_server_start')
def before_server_start(sanic, loop):
sio.start_background_task(background_task)
Это прекрасно работает, но как только я пытаюсь сделать это sio.emit из обратного вызова gpio (другой поток), у меня возникают проблемы с ожиданием sio.emit. Я попытался сделать мой asyc def my_callback_one (channel) определенным, но это не помогло. (async def my_callback_one (channel))
Я знаю, что это проблема с многопоточностью, но я просто не уверен, что с ней делать.