MQTT in BGE

Hi guys. I have huge problem with my code. Try to publish data by paho-mqtt (localhost, port=1883).
Blender is not frozen but I don’t receive anything on:
mosquitto_sub -v -t ‘#’ -h localhost -p 1883.
My code looks like that:

import threading
import weakref
import paho.mqtt.client as mqtt
import time
from bge import logic
def main():
    thread = Worker()
    thread.start()
class Worker(threading.Thread):
    def __init__(self, *args):
        weakref.finalize(logic, self.kill)
        threading.Thread.__init__(self)
        scene = bge.logic.getCurrentScene()
        cube = scene.objects['Cube']
    def kill(self):
        self.alive = False
    def on_message(client, userdata, message):
        print(message.topic)
    def run(self):
        client = mqtt.Client("relayr")
        client.on_message = self.on_message
        client.connect("localhost", 1883)
        client.loop_start()
        while self.alive:
            client.publish("devices/position/x", cube.position.x)
            client.publish("devices/position/y", cube.position.y)
            client.publish("devices/position/z", cube.position.z)
            time.sleep(5)
        client.disconnect()
        client.loop_stop()
if __name__ == "__main__":
    main()

And logic game is like that:

I would be grateful for any help.
Common loop (while, or loop_forever) caused blender freezing.

Maybe you need to turn the Always sensor to be always active?
The way you have it set up it fires on the 1st frame and stops, I think.

explain to me why you need an infinite loop to send three values and sleep for five seconds.

just run the script periodically and be done with it. put the sensor on repeat and have it wait between positive pulses. if you need the reference to the client assign it to a property. if you need to make sure the cleanup runs then bind it to the escape key.

unfortunately, it doesn’t help :frowning_face:

Seems to be great idea… but how can I run this script periodically?
I thought that threading is the only way… :slight_smile:

I want to run it once per 1.5 sec without closing game mode :slight_smile:

delay sensor with repeat enabled. delay should be equal to seconds times logic tics per second.

so run the update method through this setup. initialization through the always like you already do. then terminate the client when exit key is pressed.

as for saving a reference to the client, simple as

game_object[property_name] = any_python_object
1 Like

Your setup looks ok, but I think you need to run a server somehow. You are only running clients right now, but no servers. Is that correct?

In response to your first post:

Are you getting any errors in the console? Firstly, I don’t believe paho is an included module in blender. Are you using a custom build or install it into blender some other way? Secondly, your code should error on line 13 - ‘bge’ is not defined as you are importing ‘logic’ from the ‘bge’ module and not ‘bge’ itself. so you can delete the ‘bge.’ from that and simply use logic.getCurrentScene()

Further:

As Liebranca pointed out, you can run your script periodically by enabling pulse mode and setting the skip parameter equal to your desired period - 1.5 seconds = 90 ticks. So, no need for threading unless you have another use for it.

To create your client and hold the reference you would need to add an initialization to your ‘main’ function, such as:

# Get reference to our game object - use 'owner' to refer to self
owner = logic.getCurrentController().owner
def main():
    if not 'client' in owner:
        # This runs only once
        owner['client'] = mqtt.Client("relayr")
    # This runs every time main is called
    owner['client'].connect("localhost", 1883)
    ...
    owner['client'].disconnect()

If this run on the cube itself, you can use ‘owner’ when referring to the position instead of ‘cube’ (or you can call the owner ‘cube’ if you wish)

Finally, I will mention that ‘position’ is deprecated and would recommend using ‘worldPosition’ or ‘localPosition’ instead -
owner.worldPosition.x

Thank you very much for an answer. Will check it tomorrow and let you know :smile:

Correct! So I should run server as well… will try to figure out how to do this :slight_smile:

Thank you very much for answer in so much details. Will try to combine yours and Liebranca answers. Seems that should work… will let you know :slight_smile:

I find it a bit hard to navigate resources about MQTT, but hopefully the following helps:

https://github.com/mqtt/mqtt.github.io/wiki/servers

Thank you very much! :slight_smile:

Guys, thanks everyone for help. For now i combine solution from Liebranca and sodsm_live and it works for me!! In near future I wanna set some service for this and just for training will try to do this threading using WKnight02 solution. When I will finish it will share with you :slight_smile: Thanks once again