Search code examples
pythonmultithreadingwebsockettwisted

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


Solution

  • 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.