autobahn wamp call works in onJoin but not in button event
Hi, I am attempting to use qt5reactor in order to do crossbar.io wamp calls from a pyqt5 application. I have it working to the point that I can do a wamp call from the onJoin callback but when I try to put the call in a button event I get an immediate 'TransportLost' exception and the call does not go through.
In the code below, the call in the onJoin callback works but the call in the message_to callback (from a button) does not.
import sys, json
import qt5reactor
from PyQt5.QtWidgets import QApplication, QLabel, QMainWindow, QVBoxLayout, QLineEdit, QPushButton, QListView, QWidget
from PyQt5.QtCore import Qt
from autobahn.twisted.wamp import ApplicationSession
from autobahn.twisted.wamp import ApplicationRunner
from autobahn.wamp import auth
from autobahn.wamp.exception import SessionNotReady
from chatinclude import MessageModel, MessageDelegate
# Subclass QMainWindow to customise your application's main window
from twisted.internet.defer import inlineCallbacks
class MainWindow(QMainWindow, ApplicationSession):
def __init__(self, *args, **kwargs):
self.global_authid = "test-chat-client"
self.global_key = "MYKEY"
super(MainWindow, self).__init__()
super(ApplicationSession, self).__init__(*args, **kwargs)
# Layout the UI
l = QVBoxLayout()
self.message_input = QLineEdit("Enter message here")
# Buttons for from/to messages.
self.btn1 = QPushButton("<")
self.btn2 = QPushButton(">")
self.messages = QListView()
self.messages.setResizeMode(QListView.Adjust)
# Use our delegate to draw items in this view.
self.messages.setItemDelegate(MessageDelegate())
self.model = MessageModel()
self.messages.setModel(self.model)
self.btn1.pressed.connect(self.message_to)
self.btn2.pressed.connect(self.message_from)
l.addWidget(self.messages)
l.addWidget(self.message_input)
l.addWidget(self.btn1)
l.addWidget(self.btn2)
self.w = QWidget()
self.w.setLayout(l)
self.setCentralWidget(self.w)
@inlineCallbacks
def message_to(self):
USER_ME=0
try:
res2 = yield self.call(u'biz.domain.register_chat')
print("\nget data result: {}\n".format(res2))
self.model.add_message(USER_ME, self.message_input.text())
except Exception as e:
print("get data call error: {0}".format(e))
def message_from(self):
USER_THEM=1
self.model.add_message(USER_THEM, self.message_input.text())
def onConnect(self):
print("CONNECT", self.global_authid)
self.join(u"unwait", ['wampcra'], self.global_authid)
def onChallenge(self, challenge):
print("CHALLENGE",challenge.method)
if challenge.method == u"wampcra":
signature = auth.compute_wcs(self.global_key.encode('utf8'),
challenge.extra['challenge'].encode('utf8'))
return signature.decode('ascii')
else:
raise Exception("don't know how to handle authmethod {}".format(challenge.method))
return None
@inlineCallbacks
def onJoin(self, details):
print("JOIN")
try:
res2 = yield self.call(u'biz.domain.register_chat')
print("\nget data result: {}\n".format(res2))
except Exception as e:
print("get data call error: {0}".format(e))
def onLeave(self, details):
print("LEAVE")
def closeEvent(self, event):
pass
app = QApplication(sys.argv)
qt5reactor.install()
runner = ApplicationRunner(url='ws://IPADDR:9001/ws', realm='myrealm')
window = MainWindow()
window.show()
runner.run(MainWindow)
#app.exec_()
Sorry, this notification got lost in my pile. :[
Maybe a side note, maybe not... but I would tend to recommend away from multiple inheritance like this. Seems like a lot of stuff getting mixed together.
I can't say I have any familiarity with crossbar.io beyond having heard of it. Hopefully you have gotten some help from elsewhere by now, or solved this yourself. If not, could you share the full output error? Might help me understand which side of things the issue lies on.
Thanks for the comment. There is very little documentation on how to do it, and this is done like the only demo I could find.
On Wed, May 19, 2021 at 2:57 PM Kyle Altendorf @.***> wrote:
Sorry, this notification got lost in my pile. :[
Maybe a side note, maybe not... but I would tend to recommend away from multiple inheritance like this. Seems like a lot of stuff getting mixed together.
I can't say I have any familiarity with crossbar.io beyond having heard of it. Hopefully you have gotten some help from elsewhere by now, or solved this yourself. If not, could you share the full output error? Might help me understand which side of things the issue lies on.
— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/twisted/qt5reactor/issues/58#issuecomment-844336907, or unsubscribe https://github.com/notifications/unsubscribe-auth/AQOQRRJZRZXYAD2AO45NPCDTOP3XNANCNFSM43MOMIKQ .
I would also not do multiple inheritance like that. You're actually instantiating MainWindow twice in the above which seems likely to be the problem.
The Component interface is newer and probably more what you'll want here and can play nicely when you want to control the even-loop (as here). ApplicationRunner or autobahn.twisted.component.run are both designed as very high-level convenience APIs .. but here I think you want Qt to control the event-loop (and not Autobahn).
This is off the top of my head here, but approximately what you'll want is:
- make a
Componentinstance - hook up
on_joinandon_leavelisteners to notify your Qt application when the wamp connection is available - call
.start()on theComponentinstance
You'll likely want to disable the "chat" button when the WAMP connection isn't active. Component will re-connect automatically, so you'll get an on_leave and then (another) on_join if that happens.
Some pseudo-code:
comp = Component(...)
window = MainWindow()
@comp.on_join
def joined(session, details):
window.set_wamp_connection(session)
@comp.on_leave
def left(session, reason):
window.unset_wamp_connection()
window.show()
comp.start()
# ...
# app.exec_() or whatever runs the Qt main loop .. or just reactor.run()