Caligula Caligula - 1 month ago 12
Python Question

Twisted Websocket - Broadcasting doesn't work when called from another file

I was setting up an Websocket Server which is loggin into another server and pushing data trough the socket to the webpage (trough a subscribe function). As long as i keep calling the broadcast function from the file where the websocket runs, everything is fine. But calling the broadcast method from another python-file where my push-function is printing to command line, no client is recieving a message.

I assume, that calling the broadcast from another file creates another instance and with that the

self.clients
is empty.
So to sum up, clients connected get the broadcast from
loginGESI()
but not in my second file from
scrptCallbackHandlerExample(subType)
.

Would be happy about any help!

here is my Websocket file:

class BroadcastServerProtocol(WebSocketServerProtocol):

def onOpen(self):
self.factory.register(self)

def connectionLost(self, reason):
WebSocketServerProtocol.connectionLost(self, reason)
self.factory.unregister(self)

class BroadcastServerFactory(WebSocketServerFactory):
clients = []

def __init__(self, url):
WebSocketServerFactory.__init__(self, url)

def register(self, client):
if client not in self.clients:
print("registered client {}".format(client.peer))
self.clients.append(client)

def unregister(self, client):
if client in self.clients:
print("unregistered client {}".format(client.peer))
self.clients.remove(client)

@classmethod
def broadcast(self, msg):
print("broadcasting message '{}' ..".format(msg))
print(self.clients)
for c in self.clients:
c.sendMessage(msg.encode('utf8'))
print("message sent to {}".format(c.peer))

def login():
codesys = Test_Client("FTS_test")
result = codesys.login()
# FTS = codesys.searchForPackage("F000012")
FTS = ["15900"];
scrptContextId = [None] * len(FTS)
itemContextIds_array = [None] * len(FTS)
for i in range(0,len(FTS)):
result, scrptContextId[i] = codesys.createSubscription(c_ScrptCallbackHandlerExample, 100, int(FTS[i]))
print("SubscriptionRoomId: "+str(scrptContextId[i]))
result, itemContextIds_array[i], diagInfo = codesys.attachToSubscription(1, [FTS[i]+'.speed'], [100])
print("Subscription done for: "+str(itemContextIds_array[i]))
print("Subscription for: Speed")

BroadcastServerFactory.broadcast(str(FTS[0]))


if __name__ == '__main__':

# Logger Websocket
log.startLogging(sys.stdout)
# factory initialisieren
ServerFactory = BroadcastServerFactory
factory = ServerFactory("ws://127.0.0.1:9000")
factory.protocol = BroadcastServerProtocol
listenWS(factory)
# reactor initialisieren
webdir = File(".")
web = Site(webdir)
reactor.listenTCP(8080, web)

reactor.callLater(5, login)

reactor.run()


and here my subscription file:

# Launch of the CallbackHandler named in the createSubscription function
# CallbackHandler describes what happens to a variable which changes its value
def scrptCallbackHandlerExample(subType):
BroadcastServerFactory.broadcast('test')

# Saves the value of the variables(s) in an array
dataValue = []
for i in range(0,subType.size):
dataValue.append(subType.dataItems[i].node.dataValue)

# Print variabel informations on the screen
print "*****Callback - Data Change in a Variable*****"
print( 'Subscription ID: %d' % subType.subscrId )
for idx in range(0,subType.size):
print( '** Item %d **' % idx )
print( 'Item Id: %d' % subType.dataItems[idx].dataItemId )
print( 'Item Node ID: %s' % subType.dataItems[idx].node.nodeId )
print( 'Item data value: %s' % subType.dataItems[idx].node.dataValue )
print( 'Item data type: %s' % subType.dataItems[idx].node.dataType )
print( '******************************' )
# Define the type of the function as an eSubscriptionType
CB_FUNC_TYPE = CFUNCTYPE( None, eSubscriptionType)
c_ScrptCallbackHandlerExample = CB_FUNC_TYPE( scrptCallbackHandlerExample )


Regards

Answer

I found, in my oppinion, a pretty neat workaround.

Whenever my subscribe function is called, I connect with a local client to my websocket server and send him a message with the new values, the websocket server then pushes this to the other clients. Since I am still working on it I can't post any code but the functionality is given. So if someone is interested in a solution let me know and I can post mine.

Comments