emit bradcast message in callback with flask socketIO - python-3.x

I have trouble using Flask socketio. Here is the code I use:
import json
import time
from flask import Flask, render_template
from flask_socketio import SocketIO, emit
from engineio.async_drivers import gevent
from flask_cors import CORS
from gevent.pywsgi import WSGIServer
from geventwebsocket.handler import WebSocketHandler
app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret!'
socketio = SocketIO(app, cors_allowed_origins="*")
import queue
queue_notification_thread = queue.Queue()
def callback_notification(data):
print("callback device {}".format(data))
notification_thread = threading.Thread(target=notification_job, args=(data))
notification_thread.start()
queue_notification_thread.put(notification_thread)
def notification_job(data):
print("callback device in notification job {}".format(data))
socketio.emit("notification", data, broadcast=True)
#socketio.on('request')
def handle_message(data):
Logger.instance().debug('received message: {}'.format(data))
try:
if data.__contains__('data'):
response_message = dict()
response_message['Devices'] = dict()
response_message['Devices']['event'] = 'MY_EVENT'
socketio.emit('notification', response_message, broadcast=True)
else:
Logger.instance().error('Can\'t parse data {}'.format(data))
except OSError as err:
print('Error: when process {} \n ValueError {}'.format(data, err))
#socketio.on_error_default # handles all namespaces without an explicit error handler
def default_error_handler(e):
print('An error occured:')
print(e)
if __name__ == '__main__':
serialReader = SerialReader()
serialReader.start_reading(callback_notification)
http_server = WSGIServer(('', 5000), app, handler_class=WebSocketHandler)
http_server.serve_forever()
And the reader with call asynchronisly:
class SerialController:
serial_port: str
serial_device: serial.Serial
reading_thread: threading.Thread
device_name: str
def __init__(self, serial_port: str = "/dev/ttyACM0", baudrate=115200, read_timeout=0.2, device_name=''):
self.serial_port = serial_port
self.device_name = device_name
self.serial_device = serial.Serial(port=self.serial_port, baudrate=baudrate, timeout=0.2)
def start_reading(self, callback_function):
self.reading_callback = callback_function
# run the thread to
self.reading_thread = threading.Thread(target=self.read_job)
self.reading_thread.start()
def read_job(self):
available_data = 0
while True:
if self.serial_device.in_waiting > available_data:
available_data = self.serial_device.in_waiting
print('available_data {}'.format(available_data))
time.sleep(0.1)
else:
if available_data != 0:
data = self.serial_device.readall()
available_data = 0
if data != b'' and data != b'\n':
if self.reading_callback != None:
message = dict()
message["Reader"] = dict()
message["Reader"]["device"] = self.device_name
message["Reader"]["data"] = data
self.reading_callback(message)
time.sleep(1)
When I receive a message in #socketio.on('request') the bradcast emission work properly with no delay. When I use callback_notification called from my serial reader the breadcast emission have variable delay ( from 1seconde to 10 secondes).
On my server the message "callback device ..." is printed instantly but the client receive the message after few second.
I tried to the emission call in a thread like in the shown code but there is no improvment

Related

TypeError: signal.<locals>.decorator.<locals>.emit_signal() missing 1 required positional argument: 'self'

I am broadcasting a signal from server and need to catch in client side but I don't know how to do it here is code and getting the error in server.
Objective : broadcasting the signal from server and catching client I need to just see it's getting signal or not in d-feet it's showing the signal.
SERVER.PY
'''
#!/usr/bin/env python3
import dbus
from gi.repository import GLib
import dbus.service
import dbus.mainloop.glib
INTERVAL = 2
class DBusService_XML(dbus.service.Object):
#dbus.service.signal("org.example.demo.test")
def qSignal(slef,name):
pass
def give_data(self):
myData = input("Enter the data to send :")
object.qSignal(myData)
return myData
if __name__ == "__main__":
print("server demo 11 is started")
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
bus = dbus.SessionBus()
loop = GLib.MainLoop()
name = dbus.service.BusName("org.example.demo.test", bus)
object = DBusService_XML(bus, "/org/example/demo/test")
GLib.timeout_add_seconds(interval=INTERVAL,
function=DBusService_XML.qSignal)
loop.run()
'''
CLIENT.PY
'''
#!/usr/bin/env python3
import dbus
from gi.repository import GLib
import sys
import dbus.service
import dbus.mainloop.glib
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
bus = dbus.SessionBus()
BUS = "org.example.demo.test"
server_object = bus.get_object(BUS, "/org/example/demo/test")
loop = GLib.MainLoop()
INTERVAL = 2
bus = dbus.SessionBus()
def make_method_call():
reply = server_object.give_data()
print(reply)
return True
if __name__ == '__main__':
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
bus = dbus.SessionBus()
object = bus.get_object("org.example.demo.test", "/org/example/demo/test")
object.connect_to_signal(
"qSignal", make_method_call, dbus_interface="org.example.demo.test")
GLib.timeout_add_seconds(interval=INTERVAL,
function=make_method_call)
loop.run()
'''

Tello programming

Im trying to connect to my Tello drone with Spyder by socket but the dron dosen't send an answer back. It prints that the Tello drone refuses to enter command mode.
import socket
import threading
import time
import traceback
class Tello:
self.abort_flag = False
self.command_timeout = command_timeout
self.imperial = imperial
self.response = None
self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.tello_address = (tello_ip, tello_port)
self.socket.bind((local_ip, local_port))
self.receive_thread = threading.Thread(target=self._receive_thread)
self.receive_thread.daemon=True
self.receive_thread.start()
if self.send_command('command') != 'OK':
raise RuntimeError('Tello rejected attempt to enter command mode')
def __del__(self):
self.socket.close()
def _receive_thread(self):
while True:
try:
self.response, ip = self.socket.recvfrom(256)
except Exception:
break
def send_command(self, command):
self.abort_flag = False
timer = threading.Timer(self.command_timeout, self.set_abort_flag)
self.socket.sendto(command.encode('utf-8'), self.tello_address)
timer.start()
while self.response is None:
if self.abort_flag is True:
raise RuntimeError('No response to command')
timer.cancel()
response = self.response.decode('utf-8')
self.response = None
return response
def set_abort_flag(self):
"""Sets self.abort_flag to True.
Used by the timer in Tello.send_command() to indicate to that a response
timeout has occurred.
"""
self.abort_flag = True

How to process many messages in parallel in mqtt

I want to receive messages from many sensors (in the code I've tried from two) and process these messages in parallel by sending a command to the lights at the same time if the two sensors return "1". So I've done that in a separate thread but it doesn't work. It stops sending to the bedroom once someone enters the kitchen!
from class_light import Light
from test_class import Mqtt
import paho.mqtt.client as mqtt
import sys
import threading
import time
from MongoDB import is_circadian_Light
Broker = "broker.mqttdashboard.com"
username = "growthtechnology"
password = "growthtechnology"
PortaBroker = 1883
KeepAliveBroker = 60
client_name = "Local"
topic_sub = "testtopic/1"
topic_pub = "testtopic/3"
light = Mqtt()
occupancy_sensor = [("testtopic/4", 0), ("testtopic/5", 0)]
tunable_light = Light("deviceID")
def on_connect(client, userdata, flags, rc):
print("Connection to the broker. Result : "+str(rc))
client.subscribe(topic_sub)
client.subscribe(occupancy_sensor)
def on_publish(client,userdata,result):
print("Message published")
def on_disconnect(client, userdata, rc):
if rc != 0:
print("Unexpected disconnection.")
try:
print("[STATUS] Inicializando MQTT...")
#inicializing MQTT:
client = mqtt.Client()
client.username_pw_set(username, password)
client.on_connect = on_connect
client.on_message = light.message()
client.on_disconnect = on_disconnect
client.on_publish = on_publish
client.connect(Broker, PortaBroker, KeepAliveBroker)
def publishing():
while True:
msg = light.messages # calling for the variable "messages" to get PUBLISH messages
print(msg)
time.sleep(3)
topic = light.topic
if msg == "1" and topic == "testtopic/4":
if is_circadian_Light("device2") == 1 :
client.publish("testtopic/Bedroom",tunable_light.circadianLight())
time.sleep(10)
def publishing_kitchen():
while True:
msg_kitchen = light.messages
topic = light.topic
if msg_kitchen == "1" and topic == "testtopic/5":
if is_circadian_Light("device2") == 1 :
client.publish("testtopic/Kitchen",tunable_light.circadianLight())
time.sleep(10)
#code to turn off lights after 1 min
pub = threading.Thread(target= publishing)
pub.start()
pub_k = threading.Thread(target= publishing_kitchen)
pub_k.start()
client.loop_forever()
except KeyboardInterrupt:
print ("\nCtrl+C pressionado, encerrando aplicacao e saindo...")
sys.exit(0)
This the class Mqtt that I have created:
import paho.mqtt.client as mqtt
import time
class Mqtt():
def __init__(self, messages = "", topic = "", topic_1 = ""):
self._messages = messages
self._topic = topic
#property
def messages(self):
return self._messages
#messages.setter
def messages(self, messages):
self._messages = messages
#property
def topic(self):
return self._topic
#topic.setter
def topic(self, topic):
self._topic = topic
def message(self):
def on_message(client, userdata, msg):
Message = str(msg.payload.decode("utf-8"))
self._messages = Message
if msg.topic == "testtopic/4":
self._topic = msg.topic
print("[Receiving msg] Topic:" +msg.topic+" / Message: "+Message)
return on_message

Exception error in EReader thread running ibapi

I am running Python ib-api to receive the realtime market data from Interactive Brokers. It can provide the data I expected but it ends with "unhandled exception in EReader thread".
from ibapi.client import EClient
from ibapi.wrapper import EWrapper
from ibapi.contract import Contract as IBcontract
from threading import Thread
import queue
import pandas as pd
from ibapi.ticktype import TickTypeEnum`
`DEFAULT_PRICE_DATA_ID = 1001`
`FINISHED = object()
STARTED = object()
TIME_OUT = object()`
class finishableQueue(object):
def __init__(self, queue_to_finish):
self._queue = queue_to_finish
self.status = STARTED
def get(self, timeout):
contents_of_queue=[]
finished=False
while not finished:
try:
current_element = self._queue.get(timeout=timeout)
if current_element is FINISHED:
finished = True
self.status = FINISHED
else:
contents_of_queue.append(current_element)
except queue.Empty:
finished = True
self.status = TIME_OUT
return contents_of_queue
def timed_out(self):
return self.status is TIME_OUT
class TestWrapper(EWrapper):
def __init__(self):
self._my_price_data_dict = {}
def get_error(self, timeout=5):
if self.is_error():
try:
return self._my_errors.get(timeout=timeout)
except queue.Empty:
return None
return None
def is_error(self):
an_error_if=not self._my_errors.empty()
return an_error_if
def init_error(self):
error_queue=queue.Queue()
self._my_errors = error_queue
def error(self, id, errorCode, errorString):
## Overriden method
errormsg = "IB error id %d errorcode %d string %s" % (id, errorCode, errorString)
self._my_errors.put(errormsg)
def init_ibprices(self, tickerid):
ibprice_data_queue = self._my_price_data_dict[tickerid] = queue.Queue()
return ibprice_data_queue
def tickPrice(self, reqId, tickType, price, attrib):
tickdata = (TickTypeEnum.to_str(tickType), price)
price_data_dict = self._my_price_data_dict
if reqId not in price_data_dict.keys():
self.init_ibprices(reqId)
price_data_dict[reqId].put(tickdata)
class TestClient(EClient):
def __init__(self, wrapper):
EClient.__init__(self, wrapper)
def error(self, reqId, errorCode, errorString):
print("Error: ", reqId, " ", errorCode, " ", errorString)
def getIBrealtimedata(self, ibcontract, tickerid=DEFAULT_PRICE_DATA_ID):
ib_data_queue = finishableQueue(self.init_ibprices(tickerid))
self.reqMktData(
tickerid,
ibcontract,
"",
False,
False,
[]
)
MAX_WAIT_SECONDS = 5
print("Getting data from the server... could take %d seconds to complete " % MAX_WAIT_SECONDS)
price_data = ib_data_queue.get(timeout = MAX_WAIT_SECONDS)
while self.wrapper.is_error():
print(self.get_error())
if ib_data_queue.timed_out():
print("Exceeded maximum wait for wrapper to confirm finished - seems to be normal behaviour")
self.cancelMktData(tickerid)
return price_data
class TestApp(TestWrapper, TestClient):
def __init__(self, ipaddress, portid, clientid):
TestWrapper.__init__(self)
TestClient.__init__(self, wrapper=self)
self.connect(ipaddress, portid, clientid)
thread = Thread(target = self.run)
thread.start()
setattr(self, "_thread", thread)
self.init_error()
def main(slist):
app = TestApp("127.0.0.1", 7497, 1)
for i in slist:
ibcontract = IBcontract()
ibcontract.secType = "STK"
ibcontract.symbol = i
ibcontract.exchange ="SEHK"
Lastprice = app.getIBrealtimedata(ibcontract)
df = pd.DataFrame(Lastprice)
print(ibcontract.symbol, df.head())
app.disconnect()
if __name__ == "__main__":
seclist = [700,2318,5,12]
main(seclist)
Here are the error messages:
unhandled exception in EReader thread
Traceback (most recent call last):
File "D:\Anaconda3\envs\myweb\lib\site-packages\ibapi\reader.py", line 34, >in run
data = self.conn.recvMsg()
File "D:\Anaconda3\envs\myweb\lib\site-packages\ibapi\connection.py", line >99, in recvMsg
buf = self._recvAllMsg()
File "D:\Anaconda3\envs\myweb\lib\site-packages\ibapi\connection.py", line >119, in _recvAllMsg
buf = self.socket.recv(4096)
OSError: [WinError 10038] An operation was attempted on something that is >not a socket
A separate thread is started to read incoming messages from the socket:
thread = Thread(target = self.run)
thread.start()
But this thread is never stopped, and is still running when you call disconnect(). As a result, it tries to access the socket object which is now None, triggering the error. Try stopping the EReader thread prior to disconnecting by setting done=True.
As a side note, since this error happens at the very end of the program at the disconnection it shouldn't interfere with receiving the expected data.
A workaround to avoid the warning.
Implement this at your EClient / EWrapper subclass:
Create a socket shutdown function:
import socket, time
[...]
def _socketShutdown(self):
self.conn.lock.acquire()
try:
if self.conn.socket is not None:
self.conn.socket.shutdown(socket.SHUT_WR)
finally:
self.conn.lock.release()
Use it before closing the connection:
self._socketShutdown()
time.sleep(1)
self.disconnect()

Poloniex New Websocket API

I am trying to use the new websocket API with Poloniex. Wamp is now deprecated and there is very little information around how to do a simple call for real time public data such as volume etc.
I have found this code which seems to implement this socket, but appears in bitestream. When I run the code it calls the header fine and gets a response header fine as well and seems to send and receive data but then closes the socket. How can I subscribe to the volume channel and have decoded streaming data?
import websocket
import threading
import time
import json
from threading import Thread
def on_message(ws, message):
print(message)
def on_error(ws, error):
print(error)
def on_close(ws):
print("### closed ###")
def on_open(ws):
print("ON OPEN")
def run(*args):
ws.send(json.dumps({'command':'subscribe','channel':1003}))
while True:
time.sleep(1)
ws.close()
print("thread terminating...")
threading.Thread(target=run).start()
if __name__ == "__main__":
websocket.enableTrace(True)
ws = websocket.WebSocketApp("wss://api2.poloniex.com/",
on_message = on_message,
on_error = on_error,
on_close = on_close)
ws.on_open = on_open
ws.run_forever()
Am expecting a streaming connection to volume data but get this:
ON OPEN
send: b"\x81\xa9.)\x1d\xb8U\x0b~\xd7CD|\xd6J\x0b'\x98\x0cZh\xda]Jo\xd1LL?\x94\x0e\x0b~\xd0OGs\xddB\x0b'\x98\x1f\x19-\x8bS"
[1003,1]
unorderable types: float() > NoneType()
send: b'\x88\x82fWPGe\xbf'
### closed ###
Polo seems to think I am subscribed:
Strange because I can't reproduce your error, try this:
import websocket
import threading
import time
import json
from threading import Thread
def on_message(ws, message):
json_msg = json.loads(message)
channel_id = int(json_msg[0])
if (channel_id==1003) and len(json_msg)>2:
print("volume update")
print(json_msg[2][2])
def on_error(ws, error):
print(error)
def on_close(ws):
print("### closed ###")
def on_open(ws):
print("ON OPEN")
def run(*args):
ws.send(json.dumps({'command':'subscribe','channel':"1003"}))
threading.Thread(target=run).start()
if __name__ == "__main__":
websocket.enableTrace(True)
ws = websocket.WebSocketApp("wss://api2.poloniex.com/",
on_message = on_message,
on_error = on_error,
on_close = on_close)
ws.on_open = on_open
ws.run_forever()
Which give you:
[...]
ON OPEN
send: '\x81\xab\xc0\xe6~#\xbb\xc4\x1dL\xad\x8b\x1fM\xa4\xc4D\x03\xe2\x95\x0bA\xb3\x85\x0cJ\xa2\x83\\\x0f\xe0\xc4\x1dK\xa1\x88\x10F\xac\xc4D\x03\xe2\xd7N\x13\xf3\xc4\x03'
volume update
{u'USDT': u'5340084.934', u'ETH': u'914.931', u'XMR': u'194.895', u'BTC': u'1927.227', u'USDC': u'1275367.951'}

Resources