How to use autobahn-python with existing code ?

#1

Hi,

I’m trying to play a bit with crossbar/autobahn and I’m having problems trying to use code already existing with autobahn.

When I look the examples documentation, it seems the code is always written “for autobahn”. What I mean here is, it sound like the code is always looking something like that:

class MyClass(ApplicationSession):

  (...)

  onJoin(self, details):

      do thing

      def function_interesting(details=None):

            do the thing I really need

      def other_interesting(details=None):

            do other things I need....

If there is other ways to use autobahn, I did not found it (until now).

What I was looking for was a way to use already existing code (i.e an async protocol, a library or something else) to interact with autobahn. In example, I’ve got a protocol to read and decode serial data (not like the twisted example in autobahn), what I want to do is:

class MySerial(asyncio.protocol):
(…)

   def data_received(self, data):

          parse_mydata(data)

          call something here to send data with authobahn, using an existing ApplicationSession instance           <---- missing part

Until now, I’ve tried a lot of things (nothing working), my best hope was using asyncio.queue, in the protocol, I do a queue.put_nowait(data), and in the onJoin:

async def onJoin(self, details):

while True:

    value = await myqueue.get()          <---- sounds like not working since next line is never called

    print(value)

What is the proper way to do things like that without implementing all the logic inside the ApplicationSession ?

If things are not clear and you have an interest in this, I’ve put my code here: https://github.com/potens1/solar . I know is not pretty code and some things annoy me a lot (i.e the way to start an event loop and run a Runner)

I’m sorry if this is a noob question, but I tried that on a big part of my weekend without any success (and I guess I miss something important), so, if you have clue or example…

Regards,

Nicolas

0 Likes

#2

Hi guys,

Still no luck for me at this, but I discovered something. I refactored a bit my code and put a coroutine only there to show if the loop started by autobhan is running, and seems it’s not. Does someone here have clue about that ?

My code is:

#!/usr/bin/env python

-- coding: utf-8 --

import asyncio

import uvloop

asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())

from autobahn.asyncio.wamp import ApplicationSession, ApplicationRunner

class MyComponent(ApplicationSession):

def __init__(self, config=None):

    ApplicationSession.__init__(self, config)

    print("component created")

    self.q = self.config.extra['commqueue']

    self.tasks = []

async def read_queue(self):

    while True:

        print("Reading queue")

        elem = await self.q.get()

        print("Received %d" % elem)

async def give_life_sign(self):

    while True:

        await asyncio.sleep(2)

        print("Autobahn alive")

async def onJoin(self, details):

    print(details)

    print("session ready")

    self.tasks.append(asyncio.ensure_future(self.read_queue()))

    self.tasks.append(asyncio.ensure_future(self.give_life_sign()))

    print("Done!")

def onLeave(self, details):

    print("session left")

    for task in self.tasks:

        task.cancel()

    self.disconnect()

def onDisconnect(self):

    print("transport disconnected")

if name == “main”:

runner = ApplicationRunner(url=u"ws://localhost:8080/ws", 

                           realm=u"realm1",

                           extra={"commqueue":asyncio.Queue()})

runner.run(MyComponent)

If I start that only everything seems running, I get the “Autobahn alive” line every 2 seconds.

But, if I try to run the complete program, the serial reading part (https://github.com/potens1/solar/blob/master/readserial2.py) run well, but the autobahn one seems to be initialized only and not running. To start it, I do

#!/usr/bin/env python

-- coding: utf-8 --

import asyncio

import uvloop

from autobahn.asyncio.wamp import ApplicationRunner

from readserial2 import serial_echo_client

from sendreadings2 import MyComponent

import functools

ARDUINO = ‘/dev/ttyACM0’

SPEED = 115200

commqueue = asyncio.Queue()

asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())

if name == ‘main’:

loop = asyncio.get_event_loop()

coro = serial_echo_client(commqueue, loop)

asyncio.ensure_future(coro, loop=loop)

runner = ApplicationRunner(url=u"ws://localhost:8080/ws", 

                           realm=u"realm1", 

                           extra={"commqueue":commqueue})

runner.run(MyComponent)

The only difference is there is a future that is running in the same loop.

I know it will not be the solution since this way, I do not have any control on the loop (i.e, ctrl-c stop the autobhan part, but I don’t have any way to stop the serial_echo_client) and the way it is working is not really what I’m looking for (I feel like the ApplicationSession should look like a i.e. a DB instance, and other parts of the program should only do call of method on it to do things) but, at least I can have a almost working proof of concept.

If someone has an idea, please let me know. I feel I miss a detail that block me.

Thank you in advance and have a nice day,

Nicolas

0 Likes

#3

Hi,

I’ve found my problem (for the records) it was not anything related to autobhan but it was because I was trying to use uvloop.

For those of you trying the uvloop, be aware that you have to switch the default policy very early in your program, before doing anything else, I’d say.

My bug was:

commqueue = asyncio.Queue()

asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())

To correct it, I had to do:

asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())

commqueue = asyncio.Queue()

And, while I was at it, I put it on top of my file, just after the uvloop import.

Haaaa, feel better…

Have a nice w-e

0 Likes