I am trying to connect to binance websocket API using python. But it fails with this error: [Errno 8] nodename nor servname provided, or not known
import websocket
import sys
import pkg_resources
SOCKET = 'wss://stream.binance.com:9443/ws/ethusdt#kline_1m'
def on_open(ws):
print('opened connection')
def on_close(ws):
print('close connection')
def on_message(ws, message):
print('received message')
def on_error(ws, error):
print(error)
websocket.enableTrace(True)
ws = websocket.WebSocketApp(SOCKET, on_open=on_open, on_close=on_close, on_message=on_message, on_error=on_error)
ws.run_forever()
Anyone has an idea how should I resolve the issue. Are their APIs reliable?
Thanks in advance
Binanic api change consistently with each upgrade to the API. There a few ways of approaching the problem .
firstly check that the WSS socket is live ...
SOCKET = 'wss://stream.binance.com:9443/ws/ethusdt#kline_1m'
Then
A: check that you can log on manually through their documentation site as there live testing facility on there
If that is not successful.
B: Check that you API keys are still valid for account interaction
C: check the api version they currently using
E: on the API documentation there is live examples you can test the
get requests
D: Their service sometimes has limits on how often you can call their
API Make sure you within range
Over an above that if you have tested their api live examples for get requests there no reason that is should not work . As a rule of thumb I always use postman or insomnia to check the requests before I implement it in my own code as sometimes your header in the post requests do not match their header requirements
Insomnia
or
Postman
I personally always use the insomnia first to make sure the requests work then implement it in my code to match the format .
Related
I am trying to connect to Lightstremer to use the IG API streaming, and I would like to use the websockets library.
I am wondering if it is possible.
What I am struggling with is how to get the URI to use to create the connection with the server.
I can get the lightstreamer endpoint from IG and it looks like 'http://demo-apd.marketdatasystem.com'.
If I run
import websockets
import asyncio
ws_url = 'http://demo-apd.marketdatasystem.com/lighstreamer'
connection = await websockets.connect(ws_url)
I get the error https://demo-apd.marketdatasystems.com/lighstreamer isn't a valid URI
If I change the code below
ws_url = 'wss://demo-apd.marketdatasystem.com/lighstreamer'
connection = await websockets.connect(ws_url)
I have a message of failed connection
thanks for your time
Think you need to use a Lightstreamer client instead of WebSockets. As I understand it, they are two different protocols.
Official Python client from Lightstreamer - https://sdk.lightstreamer.com/ls-python-client/1.0.1/api/intro.html
I want to send a message to a websocket client when it connects to the server on AWS lambda and API gateway. Currently, I use wscat as a client. Since the response 'connected' is not shown on the wscat console when I connect to the server, I added post_to_connection to send a message 'hello world' to the client. However, it raises GoneException.
An error occurred (GoneException) when calling the PostToConnection
operation
How can I solve this problem and send some message to wscat when connecting to the server?
My python code is below. I use Python 3.8.5.
import os
import boto3
import botocore
dynamodb = boto3.resource('dynamodb')
connections = dynamodb.Table(os.environ['TABLE_NAME'])
def lambda_handler(event, context):
domain_name = event.get('requestContext',{}).get('domainName')
stage = event.get('requestContext',{}).get('stage')
connection_id = event.get('requestContext',{}).get('connectionId')
result = connections.put_item(Item={ 'id': connection_id })
apigw_management = boto3.client('apigatewaymanagementapi',
endpoint_url=F"https://{domain_name}/{stage}")
ret = "hello world";
try:
_ = apigw_management.post_to_connection(ConnectionId=connection_id,
Data=ret)
except botocore.exceptions.ClientError as e:
print(e);
return { 'statusCode': 500,
'body': 'something went wrong' }
return { 'statusCode': 200,
"body": 'connected'};
Self-answer: you cannot post_to_connection to the connection itself in onconnect.
I have found that the GoneException can occur when the client that initiated the websocket has disconnected from the socket and its connectionId can no longer be found. Is there something causing the originating client to disconnect from the socket before it can receive your return message?
My use case is different but I am basically using a DB to check the state of a connection before replying to it, and not using the request context to do that. This error's appearance was reduced by writing connectionIds to DynamoDB on connect, and deleting them from the table upon disconnect events. Messaging now writes to connectionIds in the table instead of the id in the request context. Most messages go through but some errors are still emitted when the client leaves the socket but does not emit a proper disconnect event which leaves orphans in the table. The next step is to enforce item deletes when irregular disconnections occur. Involving a DB may be overkill for your situation, just sharing what helped me make progress on the GoneException error.
We need to post to connection after connecting (i.e. when the routeKey is not $connect)
routeKey = event.get('requestContext', {}).get('routeKey')
print(routeKey) # for debugging
if routeKey != '$connect': # if we have defined multiple route keys we can choose the right one here
apigw_management.post_to_connection(ConnectionId=connection_id, Data=ret)
#nemy's answer is totally true but it doesn't explain the reason. So, I just want to explain...
So, first of all What is GoneException or GoneError 410 ?
A 410 Gone error occurs when a user tries to access an asset which no longer exists on the requested server. In order for a request to return a 410 Gone status, the resource must also have no forwarding address and be considered to be gone permanently.
you can find more details about GoneException in this article.
In here, GoneException has occured; it means that the POST connection we are trying to make, doesn't exist - which fits perfectly in the scenario. Because we still haven't established the connection between Client and Server. The way APIGatewayWebsocketAPIs work is that you request an Endpoint(Route) and that Endpoint will invoke that Lambda Function (In our case it is ConnectionLambdaFunction for $connect Route).
Now, if The Lambda function resolves with statusCode: 200 then and only then the API Gateway will allow the connection to be established. So, basically untill we return statusCode: 200 from our Lambda Function we are not connected and untill then we are totally unknown to server and thats why the Post call that has been made before the return statement itself will throw an error.
I am new to Microsoft Bot Framework, I am learning it through a youtube video https://youtu.be/ynG6Muox81o and making my bot on python3 on Ubuntu.
The Microsoft Bot Emulator says "sending failed. Retry".
Visual Studio Code shows KeyError: 'HTTP_CONTEXT_TYPE'.
I did everything right, my bot is connected to http://localhost:3978/, and bot emulator is connected to http://localhost:3978/api/messages/.
Many people on stackoverflow who had the same issue faced it due to windows firewall, but mine is ubuntu and i did check if it was enabled but its not.
app.py
from flask import Flask, request, Response
from botbuilder.schema import Activity
from botbuilder.core import BotFrameworkAdapter,BotFrameworkAdapterSettings
import asyncio
from echobot import EchoBot
app = Flask(__name__)
loop = asyncio.get_event_loop()
botadaptersettings=BotFrameworkAdapterSettings("","")
botadapter = BotFrameworkAdapter(botadaptersettings)
ebot = EchoBot()
#POST is the message
#app.route("/api/messages",methods=["POST"])
def messages():
#checking if HTTP file format is JSON or not
if "application/json" in request.headers["context-type"]:
#reading the JSON message
jsonmessage = request.json
else:
#unsupported media type 415
return Response(status=415)
activity = Activity().deserialize(jsonmessage)
async def turn_call(turn_context):
await ebot.on_turn(turn_context)
task = loop.create_task(botadapter.process_activity(activity,"",turn_call))
loop.run_until_complete(task)
if __name__ == '__main__':
app.run('localhost',3978)
echobot.py
from botbuilder.core import TurnContext
class EchoBot:
async def on_turn(self,turn_context:TurnContext):
await turn_context.send_activity(turn_context.activity.text)
I cant seem to understand the issue and how to fix it. it would be really helpfull if someone could help me fix this as i am really interested in building bots.
I have uploaded my Bot Project on gitlab https://gitlab.com/pdmnbhrawal/myechobot01.
This is a simple typo. You've written "context-type" instead of "content-type." The YouTube tutorial you linked to tells you to write a line like this:
if "application/json" in request.headers["content-type"]:
In order to avoid this kind of typo, you can download the source code that the video links to directly instead of trying to rewrite it yourself.
You can troubleshoot this kind of error yourself by noticing in the stack trace that it tells you what line of code is throwing the error. When it says KeyError: 'HTTP_CONTEXT_TYPE' that should indicate to you that you've entered the wrong key and you should check for a typo. You can also try using a debugger and stepping through your code.
There are a few other problems with the bot that you may notice. It doesn't handle conversation update activities correctly because it doesn't account for the incoming activity having no text. It also doesn't return an HTTP response from the api/messages endpoint. You might want to fix those problems later, but your bot will run despite them.
Im trying to make a post to the following url (http://localhost:1880/notifData) using python in a rpi. For this purpose im using bottle with no problems:
from bottle import get, post, run, request
#post('/notifData')
def notifData():
print(request.body.getvalue())
run(host='localhost', port=1880, debug=True)
But when I try to use the requests library im getting a [Errno 111] Conection refused error:
import requests
r = requests.post('http://localhost:1880/notifData/')
print(r.text)
Can someone explain why its not working?
Thanks in advance!
Requests raise a connection error when there is an event of a network-related issue such as DNS failure or connection refusal. Looking at your code and the error, I would suggest:
Making sure that the port (1880) is available for new connections,
Disabling proxy on localhost:
import os
os.environ['NO_PROXY'] = '127.0.0.1'
before sending the post request,
Use '127.0.0.1' instead of 'localhost' to send the post request.
Your post method handling function notifData is missing a return statement.
from bottle import get, post, run, request
#post('/notifData')
def notifData():
reqBody = request.body.getvalue()
print(reqBody)
return reqBody
run(host='localhost', port=1880, debug=True)
The URL path in the client code making call is incorrect. Remove the extra / at the end.
r = requests.post('http://localhost:1880/notifData')
I am trying to connect to the Binance websocket stream.
Following their documentation I use the below code to establish the connection:
from websocket import create_connection
ws = create_connection('wss://fstream.binance.com/')
When running it though, I get the following error:
WebSocketBadStatusException: Handshake status 400 Bad Request
I could not find any info on the web about this error.
Does anyone know how to fix this?
This Point is somewhat unclear in the Binance API-Docs.
The base urls for the futures are:
wss://fstream.binance.com
wss://fstream3.binance.com
But if you just connect to these base urls you get the mentioned exception.
You should complement the url-strings to
wss://fstream.binance.com/ws
wss://fstream3.binance.com/ws
This is the same for spot markets and all the other websockets. Always put a "/ws" at the end.
You could also start subscribing with the connection-url then it looks like this spot-market example:
wss://stream.binance.com:9443/ws/btcusdt#aggTrade
(But i think connecting just with "/ws" and then live subscribing/unsubscribing as explained in the docs to streams is the better way.)
I gotta say it took me a long time to figure the solution out but here it goes.
Binance API documentation should be edited because it is missing the port for the fstream.binance.com
The port is 443.
So you should use
"fstream.binance.com:443" instead of
"fstream.binance.com".
Hope it helps. (Hell yeah it does!)
You could install python-binance and use the BinanceSocketManager
python -m pip install python-binance
Use the following code I found here
import time
from binance.client import Client # Import the Binance Client
from binance.websockets import BinanceSocketManager # Import the Binance Socket Manager
# Although fine for tutorial purposes, your API Keys should never be placed directly in the script like below.
# You should use a config file (cfg or yaml) to store them and reference when needed.
PUBLIC = '<YOUR-PUBLIC-KEY>'
SECRET = '<YOUR-SECRET-KEY>'
# Instantiate a Client
client = Client(api_key=PUBLIC, api_secret=SECRET)
# Instantiate a BinanceSocketManager, passing in the client that you instantiated
bm = BinanceSocketManager(client)
# This is our callback function. For now, it just prints messages as they come.
def handle_message(msg):
print(msg)
# Start trade socket with 'ETHBTC' and use handle_message to.. handle the message.
conn_key = bm.start_trade_socket('ETHBTC', handle_message)
# then start the socket manager
bm.start()
# let some data flow..
time.sleep(10)
# stop the socket manager
bm.stop_socket(conn_key)
You are missing the path on websocket connect!
Take a look to the binance api docs:
https://binance-docs.github.io/apidocs/futures/en/#websocket-market-streams
python-binance does not support websocket to binance futures endpoints, so you can use unicorn-binance-websocket-api instead, here is an example for future endpoints:
https://github.com/oliver-zehentleitner/unicorn-binance-websocket-api/blob/master/example_binance_futures.py