Logo

TODAY I LEARNED

Connecting Ruby to AWS IoT Core using MQTT client

If you need to use Ruby to connect to Aws Iot Core, this is all you need:

require 'aws-sdk-iot'
require 'aws-sdk-secretsmanager'
require 'json'
require 'mqtt'

secrets_manager = Aws::SecretsManager::Client.new(
    region: ENV["IOT_AWS_REGION"],
    access_key_id: ENV["IOT_AWS_ACCESS_KEY"],
    secret_access_key: ENV["IOT_AWS_SECRET_ACCESS_KEY"]
    )

client = Aws::IoT::Client.new(
    region: ENV["IOT_AWS_REGION"],
    access_key_id: ENV["IOT_AWS_ACCESS_KEY"],
    secret_access_key: ENV["IOT_AWS_SECRET_ACCESS_KEY"]
    )

# Creates new ssl certificate
cert = client.create_keys_and_certificate(set_as_active: true)

# A policy named iot-mqtt needs to exist with permissions to publish and read
# any topic names
client.attach_policy(policy_name: "iot-mqtt", target: cert.certificate_arn)

# Stores the certificate in aws secrets manager
secrets_manager.create_secret(name: "iot_cert_pem", secret_string: cert.certificate_pem)
secrets_manager.create_secret(name: "iot_private_key", secret_string: cert.key_pair.private_key)

# Reads the certificate from aws secrets manager
cert_pem = secrets_manager.get_secret_value(secret_id: "iot_cert_pem").secret_string
private_key = secrets_manager.get_secret_value(secret_id: "iot_private_key").secret_string

# Connects to aws iot core endpoint using mqtts
mqtt_client = MQTT::Client.new(ENV["IOT_AWS_ENDPOINT"])
mqtt_client.cert = cert_pem
mqtt_client.key = private_key
mqtt_client.connect(MQTT::Client.generate_client_id("my-awesome-app-"))

# Publishes a message
message = { desired: { speed_limit: 35 } }
mqtt_client.publish("$aws/things/sensor_home/shadow/update", { state: message }.to_json)

# Listens to all accepted shadow updates
mqtt_client.get("$aws/things/+/shadow/+/accepted") do |topic, message|
    payload = JSON.decode(message)
    puts "Got #{topic}"
    puts "With #{payload}"
end

Learned by Edwin Cruz on Feb 11, 2021

973983 adforcodereview v3 0211021 c02 021121