Google IoT and MQTT
-
Re: [SiPy](Micropython and Google IoT Core MQTT)
I was able to make this work. What made this doable is using the new pycom ucrypto library. Previously it would take ~5 minutes to generate a JWT signature. The following repository has what should be placed in /flash/lib
https://github.com/innoagg/pycom_google_iot
Next you need to setup your Google IoT registry and download the private key from that process. See these steps:
https://cloud.google.com/iot/docs/how-tos/mqtt-bridge#downloading_mqtt_server_certificates
From the steps above you should have created a private key for the device. Place this key in /flash/cert
Next you must build a configuration file with details from the Google IoT instance. here is an example mqtt_config.py that I used:
google_cloud_config = { 'project_id':'XXX', 'cloud_region':'us-central1', 'registry_id':'XXX', 'device_id':'XXX', 'mqtt_bridge_hostname':'mqtt.googleapis.com', 'mqtt_bridge_port':8883 } jwt_config = { 'algorithm':'RS256', 'token_ttl': 43200, #12 hours 'private_key':"" } try: log.info("Loading RSA Private Key...") with open('/flash/cert/private_key.pem','rb') as f: jwt_config['private_key'] = f.read() print(jwt_config['private_key']) f.close() log.info("RSA Private Key Loaded") except Exception as e: log.error("Error Loading RSA Private Key: {}".format(e)) jwt_config['private_key']
Finally, use a similar procedure to return an MQTT client:
import mqtt_config import microjwt from umqtt.simple import MQTTClient import machine import time from network import WLAN from machine import RTC import ujson print("connect wifi") wlan = WLAN(mode=WLAN.STA) wlan.connect("XXX", auth=(WLAN.WPA2, "XXX"), timeout=5000) while not wlan.isconnected(): machine.idle() rtc = RTC() rtc.init() if not rtc.synced(): rtc.ntp_sync("pool.ntp.org") while not rtc.synced(): print("RTC Syncing...") time.sleep_ms(500) print("RTC Time:{}".format(time.time())) print(wlan.ifconfig()) print("wifi connected") def on_message(topic, msg): print("Topic:{} Msg:{}".format(topic, msg)) def get_mqtt_client(project_id, cloud_region, registry_id, device_id, jwt): """Create our MQTT client. The client_id is a unique string that identifies this device. For Google Cloud IoT Core, it must be in the format below.""" client_id = 'projects/{}/locations/{}/registries/{}/devices/{}'.format(project_id, cloud_region, registry_id, device_id) print('Sending message with password {}'.format(jwt)) client = MQTTClient(client_id.encode('utf-8'),server=mqtt_config.google_cloud_config['mqtt_bridge_hostname'],port=mqtt_config.google_cloud_config['mqtt_bridge_port'],user=b'unused',password=jwt.encode('utf-8'),ssl=True) client.set_callback(on_message) client.connect(clean_session=True) client.subscribe('/devices/{}/config'.format(device_id), 1) client.subscribe('/devices/{}/commands/#'.format(device_id), 1) return client print("generate jwt") jwtObj = microjwt.new(mqtt_config.google_cloud_config['project_id'], mqtt_config.jwt_config['private_key'], 'RS256', mqtt_config.jwt_config['token_ttl']) jwt = jwtObj.encodedValue() client = get_mqtt_client(mqtt_config.google_cloud_config['project_id'], mqtt_config.google_cloud_config['cloud_region'], mqtt_config.google_cloud_config['registry_id'], mqtt_config.google_cloud_config['device_id'], jwt) temp = 0; def pub(): global temp temp = temp + 1 message = { "device_id": mqtt_config.google_cloud_config['device_id'], "temp": temp } print("Publishing message "+str(ujson.dumps(message))) mqtt_topic = '/devices/{}/{}'.format(mqtt_config.google_cloud_config['device_id'], 'events') client.publish(mqtt_topic.encode('utf-8'), ujson.dumps(message).encode('utf-8')) def checkMessages(): print("Check Messages...") client.check_msg() time.sleep(1)
-
Hey @panda are you still out there? What firmware version did you test this on? I can't get any other Google IoT libraries to work due to various firmware bugs and want to try your implementation.
-
Also refer to the mqtt library used and included in my repository:
https://github.com/micropython/micropython-lib/tree/master/umqtt.simple