Search code examples
pythonkivymqtt

How to pass mqtt variable out of on_message function to kivy


I want to pass paho-mqtt variable of on_message function out of it to use it in my kivy app this is my main app

class MyApp(MDApp):
def build(self):
    self.theme_cls.theme_style = "Light"
    self.theme_cls.primary_palette = "BlueGray"
    self.title = "IAD"
    return Builder.load_file("my.kv")
def remove_item(self, instance):
    self.root.get_screen('Home').ids.md_list.remove_widget(instance)

def on_start(self):
    topic = "python/mqtt"
    def onConnect(client,userdata,flags,rc):
        mqttc.subscribe(topic, 0)
    
    def onMessage(client,userdata,msg):
        global gmsg 
        gmsg = msg.payload.decode('utf-8')
        print(gmsg)
    self.root.get_screen('Home').ids.md_list.add_widget(
        SwipeToDeleteItem(text=f"{gmsg}")
    )
        
    mqttc = mqtt.Client(client_id="kivy", clean_session=True)
    mqttc.on_connect = onConnect
    mqttc.on_message = onMessage
    mqttc.connect('broker.emqx.io',1883, keepalive=60, bind_address="")
    mqttc.loop_start()

MyApp().run()

I've tried evreything here but didn't work I tried passing self" parameter to mqtt.Client constructor, putting self.root.get_screen('Home').ids.md_list.add_widget( SwipeToDeleteItem(text=f"{gmsg}") but I got an error which is TypeError: Cannot create graphics instruction outside the main Kivy thread I used @mainthread but it didn't work, and global variable.


Solution

  • Try defining a new method in yur App that adds the SwipeToDeleteItem widget, and call that method through Clock.schedule_once(). That new method could be:

    def doit(self, gmsg, _dt):
        self.root.get_screen('Home').ids.md_list.add_widget(SwipeToDeleteItem(text=f"{gmsg}")
    

    and then call that method from your onMessage() method:

    def onMessage(client,userdata,msg):
        global gmsg 
        gmsg = msg.payload.decode('utf-8')
        print(gmsg)
        Clock.schedule_once(partial(self.doit, gmsg))
    

    This puts the add_widget() on the main thread.