Atmosoric1
Atmosoric1

Reputation: 21

Howto Python Push websocket client , tutorial ? tried pusher without success (incomplete example ?)

I am new to websocket and push technologies. I have to develop a push client, based on Python (on an RPI) to communicate with a server.

The push server is based on Push Laravel technology, (push + websocket). Access to the serveur is protected via https + login/password registration.

I am able to connect/register to the server using htpps, but I don't know how to subscribe to the channels of the server.

I find an example of python push client here https://github.com/deepbrook/Pysher and also the question here : Receiving events in Pusher client but I think these examples are not complete since in those examples the WS server is not specified in the code...

Here is what I did (I removed confidential info and replace with ...) :

global pusher
LOGIN_URL = ...
URL = ...
EMAIL= ...
PASSWORD= ...
headers = {
    'accept': 'text/html,application/xhtml+xml,application/xml',
    'user-agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36'
}

client = requests.session()
response=client.get(LOGIN_URL)
soup = BeautifulSoup(response.text, 'html.parser')
csrftoken = soup.select_one('meta[name="csrftoken"]')['content']
login_data = dict(_token=csrftoken,email=EMAIL, password=PASSWORD, )
r = client.post(URL, data=login_data, headers=dict(Referer=URL))
ws = create_connection("wss://......../app/...key...?protocol=7&client=js&version=7.0.0&flash=false")

root = logging.getLogger()
root.setLevel(logging.INFO)
ch = logging.StreamHandler(sys.stdout)
root.addHandler(ch)

def  my_func(*args, **kwargs):
    print("processing Args:", args)
    print("processing Kwargs:", kwargs)
    
def connect_handler(data):
    channel = pusher.subscribe('presence-chat')
    channel.bind('App\\Events\\MessageSent', my_func)

appkey='....'
PUSHER_APP_ID='..'
PUSHER_APP_KEY='...'
PUSHER_APP_SECRET='...'
PUSHER_APP_CLUSTER='...'

pusher = pusherclient.Pusher(PUSHER_APP_ID, PUSHER_APP_KEY, PUSHER_APP_SECRET, PUSHER_APP_CLUSTER)
pusher.connection.bind('pusher:connection_established', connect_handler)
pusher.connect()

while True:
    # Do other things in the meantime here...
    time.sleep(1)

But I get these error when executed :

error from callback <bound method Connection._on_open of <Connection(Thread-1, started daemon 14552)>>: _on_open() missing 1 required positional argument: 'ws'
error from callback <bound method Connection._on_message of <Connection(Thread-1, started daemon 14552)>>: _on_message() missing 1 required positional argument: 'message'
error from callback <bound method Connection._on_close of <Connection(Thread-1, started daemon 14552)>>: _on_close() missing 1 required positional argument: 'ws'

probably because I don't specify the WS server address to pusher but I don't know how to do it (and surprisingly the example I found above don't specify such WS address either).

Another possibility is to directly code push dialog using only python websocket lib (so without pusher lib), as this :

client = requests.session()
response=client.get(LOGIN_URL)
soup = BeautifulSoup(response.text, 'html.parser')
csrftoken = soup.select_one('meta[name="csrf-token"]')['content']
login_data = dict(_token=csrftoken,email=EMAIL, password=PASSWORD, )
r = client.post(URL, data=login_data, headers=dict(Referer=URL))

async def hello():
    async with websockets.connect(
        URI, ssl=True #ssl_context
    ) as websocket:
        name = input("Message to send ? ")

        await websocket.send(name)
        print(f"Sent message : {name}")

        greeting = await websocket.recv()
        print(f"Received : {greeting}")

asyncio.get_event_loop().run_until_complete(hello())

with this code I am able to establish a connection :

"event":"pusher:connection_established","data":"{\"socket_id\":\"54346.8202313328\",\"activity_timeout\":30}"}

but I don't know then how to subscribe to channel. I guess I have to form a command using json etc, but would need some example...

Any help, pointer or whatever would be very appreciated since I am completely lost now.

All the best for year 2021 that can't be worst as this one ! Regards, Atmos

Upvotes: 1

Views: 793

Answers (1)

Atmosoric1
Atmosoric1

Reputation: 21

Finally I resolve the problem : the push server address is hard coded in the class Pusher file "pusherclient/init.py", host="wss:ws....com"

Unfortunately I still have some errors :

error from callback <bound method Connection._on_error of <Connection(Thread-1, started daemon 8332)>>: _on_error() missing 1 required positional argument: 'error'
error from callback <bound method Connection._on_close of <Connection(Thread-1, started daemon 8332)>>: _on_close() missing 1 required positional argument: 'ws'

Upvotes: 1

Related Questions