[eventlet] how to socket.emit from the callback function
See original GitHub issueHi @miguelgrinberg I hope you are fill ok
Project description I’m currently building an application to visualization pressing key pianino for handling midi adapter I’m using this lib rtmidi.
for practice, my python skill I pickup to create a midi-adapter on python and via socket connect it into an angular application.
The my issue the PoC works fine, but I got a big delay in emitting so I was star searching and I found some example how to implement the eventlet and on this key testing via using setup_midi_port_mock and setup_midi_port_mock_5_keys looks pretty good but emit from callback stop working 😭
POC project as I mentioned before I got a big delay | this screnshot is for this setup on def init: setup_midi_port_mock_5_keys
left time is from the client after receive right side is from python server
[[source]]
name = "pypi"
url = "https://pypi.org/simple"
verify_ssl = true
[dev-packages]
[packages]
python-rtmidi = "*"
flask = "*"
flask-socketio = "*"
[requires]
python_version = "3.6"
from flask import Flask
from flask_socketio import SocketIO
import rtmidi
from datetime import datetime
'''
Setup Socket IO
'''
app = Flask(__name__)
socket = SocketIO(app, logger=True, engineio_logger=True, cors_allowed_origins="*")
# app.debug = True
# app.host = '0.0.0.0'
'''
Setup midiIn
'''
midiIn = rtmidi.MidiIn()
@socket.on('init')
def init(data):
setup_midi_port()
# setup_midi_port_mock()
# setup_midi_port_mock_5_keys()
def rise_key(data):
emit_data = {
'action': data[0][0],
'key': data[0][1],
'emphasis': data[0][2],
'duration': data[1],
'time': datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3]
}
socket.emit('rise-key', emit_data, broadcast=True, namespace='/')
socket.sleep(0.0001)
def click_key(data):
emit_data = {
'action': data[0][0],
'key': data[0][1],
'emphasis': data[0][2],
'duration': data[1],
'time': datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3]
}
socket.emit('click-key', emit_data, broadcast=True, namespace='/')
socket.sleep(0.0001)
def setup_midi_port():
available_ports_in = midiIn.get_ports()
if available_ports_in:
midiIn.close_port()
print('Setup midi call back')
midiIn.open_port(0)
midiIn.set_callback(lambda data, time: rise_key(data) if data[0][0] == 128 else click_key(data))
def setup_midi_port_mock():
loop = 20
while True:
loop = 21 if loop == 109 else loop + 1
click_key(([144, loop, 64], 0.009))
rise_key(([128,loop,64], 0.009))
def setup_midi_port_mock_5_keys():
while True:
click_key(([144, 61, 64], 0.009))
click_key(([144, 62, 64], 0.009))
click_key(([144, 63, 64], 0.009))
click_key(([144, 64, 64], 0.009))
click_key(([144, 65, 64], 0.009))
socket.sleep(0.1)
rise_key(([128, 65, 64], 0.009))
rise_key(([128, 64, 64], 0.009))
rise_key(([128, 63, 64], 0.009))
rise_key(([128, 62, 64], 0.009))
rise_key(([128, 61, 64], 0.009))
socket.sleep(0.1)
if __name__ == '__main__':
socket.run(app, host = '127.0.0.1')
**Project with eventlet ** as I mentioned before in this case for below option everything is working properly without any troubles and animation lags on angular application eventlet.spawn(setup_midi_port_mock) eventlet.spawn(setup_midi_port_mock_5_keys)
but 😭 but this configuration eventlet.spawn(setup_midi_port) is not working. more information you will find under code
[[source]]
name = "pypi"
url = "https://pypi.org/simple"
verify_ssl = true
[dev-packages]
[packages]
python-rtmidi = "*"
flask = "*"
flask-socketio = "*"
eventlet = "*"
[requires]
python_version = "3.6"
import eventlet
eventlet.monkey_patch()
from flask import Flask
from flask_socketio import SocketIO
import rtmidi
from datetime import datetime
app = Flask(__name__)
socket = SocketIO(app, logger=True, engineio_logger=True, cors_allowed_origins="*")
'''
Setup midiIn
'''
midiIn = rtmidi.MidiIn()
@socket.on('init')
def init(data):
eventlet.spawn(setup_midi_port)
#eventlet.spawn(setup_midi_port_mock)
#eventlet.spawn(setup_midi_port_mock_5_keys)
def rise_key(data):
emit_data = {
'action': data[0][0],
'key': data[0][1],
'emphasis': data[0][2],
'duration': data[1],
'time': datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3]
}
socket.emit('rise-key', emit_data, broadcast=True, namespace='/')
eventlet.sleep(0)
def click_key(data):
emit_data = {
'action': data[0][0],
'key': data[0][1],
'emphasis': data[0][2],
'duration': data[1],
'time': datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3]
}
socket.emit('click-key', emit_data, broadcast=True, namespace='/')
eventlet.sleep(0)
def setup_midi_port():
available_ports_in = midiIn.get_ports()
if available_ports_in:
midiIn.close_port()
print('Setup midi call back')
midiIn.open_port(0)
midiIn.set_callback(lambda data, time: rise_key(data) if data[0][0] == 128 else click_key(data))
'''
Working without any lags, animations are perfect
'''
def setup_midi_port_mock():
loop = 20
while True:
loop = 21 if loop == 109 else loop + 1
click_key(([144, loop, 64], 0.009))
rise_key(([128,loop,64], 0.009))
'''
Working without any lags, animations are perfect
after emit eventlet.sleep(0) is set to 0 to imit human press all
'''
def setup_midi_port_mock_5_keys():
while True:
click_key(([144, 61, 64], 0.009))
click_key(([144, 62, 64], 0.009))
click_key(([144, 63, 64], 0.009))
click_key(([144, 64, 64], 0.009))
click_key(([144, 65, 64], 0.009))
eventlet.sleep(0.1)
rise_key(([128, 65, 64], 0.009))
rise_key(([128, 64, 64], 0.009))
rise_key(([128, 63, 64], 0.009))
rise_key(([128, 62, 64], 0.009))
rise_key(([128, 61, 64], 0.009))
eventlet.sleep(0.1)
if __name__ == '__main__':
socket.run(app, host='127.0.0.1')
so what is occured for eventlet.spawn(setup_midi_port)
Logs after launch application and call @socket.on(‘init’)
Logs after press key on keyboard
From logs, it looks like everything is ok, but UI doesn’t get any message, after play some times I got this logs (Yes I know the session is not the same as on previous images 😉, but the issue occurred before too and this I’ve made after restart everything)
I hope you have some idea how to modify it 😉 Thanks in advance
Issue Analytics
- State:
- Created 3 years ago
- Comments:9 (4 by maintainers)
See https://en.wikipedia.org/wiki/Push_technology#Long_polling.
Yes, I think for now in peer to peer communication this limitation is acceptable.
Thanks in tone.