Objectives:

  1. To serve the teaching goals of Internet of Things (IoT) in the Information Technology (IT) course in senior high schools, include MQTT in the course as a main topic.
  2. To interact with hardware through MQTT on the Python editor.
  3. To present MQTT that works behind the user cloud broadcast function; describe the relationships between MQTT and IoT instead of those between user cloud broadcast and IoT; and explain IoT based on the application of MQTT.
  4. To visualize data through MQTT.

    Recommended IoT Learning roadmap:

  • Stage 1: user cloud broadcast (use it)
  • Stage 2: introductory courses for MQTT (concepts and simple application): mkcloud + cyberpi.mqtt (mkcloud and servers based on mBlock)
  • Stage 3: advanced courses for MQTT (advanced application): mqtt.MQTTClient (Hardware) + paha-mqtt (third-party python libraries)

    Application scenarios:

    In teaching, the MQTT server used is broker.emqx.io (mq.makeblock.com is not recommended by the R&D personnel.).
  1. CyberPi communicates with the Python editor through MQTT. For example, data collected by sensors of CyberPi can be transmitted to the MQTT server, and the Python editor can receive data from the MQTT server.
  2. Two CyberPis communicate with each other through MQTT. For example, through MQTT communication, you can use CyberPi A to control the lights of CyberPi B.
  3. CyberPi can transmit data to and receive data from itself.

    Current status:

    The MQTT functions have been developed in the mkcloud library.

    MQTT APIs in the mkcloud library:

    The following describes the MQTT APIs in the mkcloud library. You are recommended to add the prefix cyberpi when using them.

    Note:

    The default prefix “MB_PY/“ is added to the topic transmitted by using mkcloud APIs. The prefix is also added when a topic is set to be received.

MQTT APIs in the mkcloud library

  1. # python 3.6
  2. import random
  3. import time
  4. from paho.mqtt import client as mqtt_client
  5. class MqTT:
  6. # default
  7. broker = 'broker.emqx.io'
  8. port = 1883
  9. # generate client ID with pub prefix randomly
  10. client_id = f'py-mqtt-mb-{random.randint(0, 1000)}'
  11. mq_client = mqtt_client.Client(client_id)
  12. is_connect = False
  13. topic_prefix = "MB_PY/"
  14. callback = None
  15. is_on_message = False
  16. def __init__(self):
  17. pass
  18. # version
  19. def version(self):
  20. return "1.0.1"
  21. # set broker
  22. def set_broker(self,client_id,server,port):
  23. if client_id != None:
  24. self.client_id = client_id
  25. self.broker = server
  26. self.port = port
  27. # connect
  28. def connect(self):
  29. self.connect_mq()
  30. self.loop_start()
  31. time.sleep(1.8)
  32. return self.is_connect
  33. # connect server
  34. def connect_mq(self):
  35. def on_connect(client, userdata, flags, rc):
  36. if rc == 0:
  37. print("Connected to MQTT Broker!")
  38. self.is_connect = True
  39. else:
  40. self.is_connect = False
  41. print("Failed to connect, return code %d\n", rc)
  42. self.mq_client = mqtt_client.Client(self.client_id)
  43. self.mq_client.on_connect = on_connect
  44. self.mq_client.connect(self.broker, self.port)
  45. return self.mq_client
  46. # disconnect
  47. def off(self):
  48. self.is_on_message == False
  49. self.is_connect = False
  50. self.mq_client.disconnect()
  51. # publish
  52. def publish_message(self,topic="mb", data="msg"):
  53. topic = self.topic_prefix + topic
  54. result = self.mq_client.publish(topic, data)
  55. # result: [0, 1]
  56. status = result[0] # 0 is ok
  57. return status
  58. def on_message(self,client, userdata, msg):
  59. #print(f"Received `{msg.payload.decode()}` from `{msg.topic}` topic")
  60. self.callback(msg.topic,msg.payload.decode())
  61. # subscribe
  62. def subscribe_message(self,topic):
  63. topic = self.topic_prefix + topic
  64. self.mq_client.subscribe(topic)
  65. if self.is_on_message == False :
  66. self.mq_client.on_message = self.on_message
  67. self.is_on_message = True
  68. # callback
  69. def set_callback(self,callback):
  70. self.callback = callback
  71. self.mq_client.on_message = self.on_message
  72. # loop_start
  73. def loop_start(self):
  74. self.mq_client.loop_start()
  75. # loop_forever
  76. def loop_forever(self):
  77. self.mq_client.loop_forever()
  78. # client
  79. def get_client(self):
  80. return self.mq_client
  81. def get_broker(self):
  82. return self.broker
  83. def get_port(self):
  84. return self.port
  85. def get_topic_prefix(self):
  86. return self.topic_prefix
  87. mqtt = MqTT()

Main APIs:

API Function
cyberpi.mqtt.set_broker(client_id, server, port) Sets the MQTT server.
Parameters:
client_id:(not mandatory)
server: str, server address
port: int, port number
cyberpi.mqtt.connect() Connects to the server.
Returned values:
True: connected
False: connection failed
cyberpi.mqtt.off() Disconnects from the server.
cyberpi.mqtt.publish_message(topic, data) Publishes messages to specified message queue.
Parameters:
topic: str, name of the message queue (in functions, the default prefix “MB_PY” is added to the topic automatically).
data: str, content in the message
cyberpi.mqtt.subscribe_message(topic) Subscribes to the messages of the specified topic.
Parameter:
topic: str, mq name (in functions, the default prefix “MB_PY” is added to the topic automatically).
cyberpi.mqtt.set_callback(callback) Set a callback function to process received messages.(For details, see the MQTT APIs in the mkcloud library.)
Parameter:
callback: function name. You can define it by yourself.