Long-Lived Websocket connection not working when I have multiple requests - python

I'm using Python to connect to a websocket that generates real-time market data. In order to obtain my data I need to follow these 3 steps:
1 - Estabilish a connection with the websocket
2 - Insert the token using the message: {"action":"initialData", "token": "MY_TOKEN"}
3 - Execute the desired request which in my case is: {"action": "startStreamQuote","symbols":["PETR4"]}
This is what I've writen so far:
url = "wss://svc.aebroadcast.com.br/stock/ws"
ws = create_connection(url)
ws.recv()
ws.send(json.dumps({"action":"initialData", "token": "eY6Hw9olpa93......"}))
ws.recv()
ws.send(json.dumps({"action": "startStreamQuote","symbols":["PETR4"]}))
ws.recv()
print("Received" + ws.recv())
The following code creates the connection and pulls the information but then stops so I need to keep executing it if I wanna see more info, but if I execute 2 times and there's no new info, it gets duplicated. Anyway...
I was reading the websocket documentation and found this example for long-lived connections:
import websocket
import _thread
import time
import rel
def on_message(ws, message):
print(message)
def on_error(ws, error):
print(error)
def on_close(ws, close_status_code, close_msg):
print("### closed ###")
def on_open(ws):
print("Opened connection")
if __name__ == "__main__":
websocket.enableTrace(True)
ws = websocket.WebSocketApp("wss://api.gemini.com/v1/marketdata/BTCUSD",
on_open=on_open,
on_message=on_message,
on_error=on_error,
on_close=on_close)
ws.run_forever(dispatcher=rel) # Set dispatcher to automatic reconnection
rel.signal(2, rel.abort) # Keyboard Interrupt
rel.dispatch()
Although this example fits very well and succeeds in mainting an open connection running, I don't know where I should insert my two requests (2 and 3 of the list above) 'initialData' and 'startStreamQuote' into this structure. I've tried using ws.send(json.dumps('.....generical request.....')) and depending on the position inside the code it returns a connection closed error or simply doesn't return anything about the request.
Can someone help me with that?

Related

Image streaming using websocket in Python

I have a camera module with a WiFi chip that runs its own HTTP/websocket server. A GUI can be accessed by opening the address '192.168.1.1' in a browser (Chrome).
This GUI allows to control the camera and change some parameters from the camera module.
If I open the Network monitoring in Chrome, I can see that when the camera is activated, a stream of jpg images are received by the browser.
I would like to read this stream of data (images) using Python in order to real-time process them, for example with openCV. To do so, I was using the websocket package, but I receive the Following Error:
[Errno 111] Connection refused - goodbye
[Errno 111] Connection refused
### closed ###
My current python code is:
import websocket
import _thread
import time
import rel
def on_message(ws, message):
print(message)
def on_error(ws, error):
print(error)
def on_close(ws, close_status_code, close_msg):
print("### closed ###")
def on_open(ws):
print("Opened connection")
websocket.enableTrace(True)
ws = websocket.WebSocketApp("wss://192.168.1.1",
on_open=on_open,
on_message=on_message,
on_error=on_error,
on_close=on_close)
ws.run_forever(dispatcher=rel)
rel.signal(2, rel.abort)
rel.dispatch()
Can someone please tell me what is wrong and how should I proceed?

How to stop python websocket connection after some seconds?

I am trying to develop a short script that connects to a real-time stock data provider through a websocket API, gets some data, makes some calculations, stores the results in a database and stops.
EDIT: I need to keep the connection alive for a few seconds until I get all required data. Thus, breaking the connection after the first message is not an option.
The problem I am facing is how to stop the run_forever() connection.
This is what I have so far:
import websocket
import json
def on_open(ws):
channel_data = {
"action": "subscribe",
"symbols": "ETH-USD,BTC-USD"
}
ws.send(json.dumps(channel_data))
def on_message(ws, message):
# Do some stuff (store messages for a few seconds)
print(message)
def on_close(ws):
print("Close connection")
socket = "wss://ws.url"
ws = websocket.WebSocketApp(socket, on_open=on_open, on_message=on_message)
ws.run_forever()
ws.close()
# Once the connection is closed, continue with the program
I do not want to stay connected after the "Do some stuff" is executed, how can I force the connection close?
Your help is much appreciated.
I managed how to solve this. I leave my solution in case it is useful to someone.
I just added some attributes to the ws object that allows me to track the number of messages received and store them into a list to work with once the connection is closed.
import websocket
import json
def on_open(ws):
channel_data = {
"action": "subscribe",
"symbols": "ETH-USD,BTC-USD"
}
ws.send(json.dumps(channel_data))
def on_message(ws, message):
ws.messages_count+=1
ws.messages_storage.append(message)
if ws.messages_count>50:
ws.close()
def on_close(ws):
print("Close connection")
socket = "wss://ws.url"
ws = websocket.WebSocketApp(socket, on_open=on_open, on_message=on_message)
# Create a counter and an empty list to store messages
ws.messages_count = 0
ws.messages_storage = []
# Run connection
ws.run_forever()
# Close connection
ws.close()
# Continue with the program

Connection WebSocket with Session

good morning.
I'm trying to make an API for Quotex.com brokerage where your communication is done via websocket --> wss://ws.qxbroker.com/socket.io/?EIO=3&transport=websocket
To connect to the broker I'm using Selenium. I can recover the session, but the difficulty is to send this data back to the websocket.
My code is this, where I try to connect and then send an order to broker.
Could someone help me please.
order = '42["orders/open",{"asset":"AUDCAD_otc","amount":6,"time":1637893200,"action":"put","isDemo":1,"requestId":1637892541,"optionType":1}]'
order2 = json.dumps(order)
try:
import thread
except ImportError:
import _thread as thread
import time
def on_message(ws, message):
print(message)
def on_error(ws, error):
print(error)
def on_close(ws):
print("### closed ###")
def on_open(ws):
def run(*args):
for i in range(3):
time.sleep(1)
ws.send("""42["authorization",{"session":""" + session + ""","isDemo":1}]""")
time.sleep(1)
ws.send(order)
ws.send(order2)
ws.close()
print("thread terminating...")
thread.start_new_thread(run, ())
urlsocket = "wss://ws.qxbroker.com/socket.io/?EIO=3&transport=websocket"
ws = websocket.WebSocketApp(
urlsocket, on_message=on_message,
on_open=on_open)
ws.run_forever()
Example of analysis via google chrome devtools
Exemple Send Order for Broker

Asyncronously manage connected clients while continously sending data in Python

I have a server built in Python that uses Sanic and websockets to routinely broadcast data to clients:
#app.websocket("/")
async def websocket(request, ws):
app.ws_clients.add(ws)
await ws.send(json.dumps("hello from climate server!"))
while True:
try:
data = dict()
time_of_reading = time.ctime(time.time())
data['climateData'] = sensor.read_data()
data['systemData'] = get_system_data()
data['timestamp'] = time_of_reading
await broadcast(json.dumps(data))
time.sleep(10) # changing this to asyncio.sleep() causes the msgs to send sporatically
except KeyboardInterrupt:
sensor.clear()
pass
if __name__ == '__main__':
app.run(host='0.0.0.0', port=8080, workers=1, debug=False)
and my broadcast function which attempts to send a message, or removes a client from app.ws_clients if there is a ConnectionClosed error:
async def broadcast(message):
for ws in app.ws_clients:
try:
await ws.send(message)
print('attempting data send') # this line runs, but the clients don't receive the messages
except websockets.ConnectionClosed:
clients_to_remove.add(ws)
except KeyboardInterrupt:
sensor.clear()
pass
if (len(clients_to_remove) > 0):
await remove_dead_clients(clients_to_remove)
async def remove_dead_clients(clients_to_remove):
for client in clients_to_remove:
app.ws_clients.remove(client)
clients_to_remove.clear()
The client is able to connect just fine, and the server prints that it is trying to broadcast, but no message is ever received by the client.
I am using this broadcast function from another server that I wrote, and it works perfectly there. The difference with that one is that it only sends data when a client requests it. I feel the issue here is that the async cannot handle both continually broadcasting and removing clients simultaneously. I tried changing time.sleep() to asyncio.sleep(), but that only succeeded in successfully sending the messages dozens at a time, and then nothing at all for awhile.
Is there a pattern I could implement that would meet my needs, where I can send messages in an endless loop and also asynchronously manage connected clients?
For anyone that happens to stumble across this in the future - I had forgotten to use the await keyword prior to asyncio.sleep().

Python WebSocket Client connecting but not sending messages

While using websocket client to send test messages to a django server, I cannot get a script to work which can both send and receive messages.
The following python script is what I have attempted:
import websocket
import threading
import json
from time import sleep
# handle message event
def on_message(ws, message):
print("message recieved: %s" % message)
# handle close event
def on_close(ws):
print("channel closed")
# execute as main script
if __name__ == "__main__":
websocket.enableTrace(True)
# new app object connecting to headstation
ws = websocket.WebSocketApp("ws://192.168.0.106:8000/?testI123", on_message = on_message, on_close = on_close)
# run in a new thread - kill if script ends
ws_listener = threading.Thread(target=ws.run_forever())
ws_listener.daemon = True
# start second thread
ws_listener.start()
# attempt connection 5 times
timeout = 5
while not ws.sock.connected and timeout:
sleep(1)
timeout -= 1
# error on timeout
if (timeout == 0):
print("Connection to server timed out")
print("test 1")
# periodically send test message to server
message_num = 0
while ws.sock.connected:
# send node id and message
message = 'hello %d'%message_num
ws.send(message)
sleep(1)
message_num += 1
This connections successfully, indicted by the server, and receives messages sent from the server, but does not send anything.
Periodically, something like this is displayed on the terminal:
send: b'\x8a\x84\xe2\xe9\xa8\xe2\x8f\xdc\xe2\x84'
If I simply use
ws = websocket.WebSocket()
ws.connect(url)
ws.send("hello")
then this works perfectly. Suggesting it is something wrong with my little python script displayed above.
Found the problem, stupid mistake of course:
ws_listener = threading.Thread(target=ws.run_forever())
should be:
ws_listener = threading.Thread(target=ws.run_forever)
without parentheses.
First one passes result of ws.run_forever to the target, second one sets ws.run_forever as the target, which was the intended outcome.

Categories

Resources