こちらの記事で作成したModbus通信の温湿度計を、AWS IoT GreenGrass経由で操作してみました。
概要
やりたいことの概要です、MQTT経由でコマンドを送り、温度、または湿度を指定して値を取得してみようと思います。(Raspberry Pi 3B+を利用しています)
Lambda作成
GreenGrassにデプロイするLambdaを作成します。Python3.7にします。
細かい内容は冒頭でも書いたこちらの記事に記載しています。
コードを載せておきます。
import sys import json import time import logging import greengrasssdk import serial import RPi.GPIO as GPIO INPUT_TOPIC = "test/command" OUTPUT_TOPIC = "test/get_value" # Modbus Commands TEMPERATURE_CMD = bytes.fromhex("010400010001600A") HUMIDITY_CMD = bytes.fromhex("010400020001900A") # Setup logger = logging.getLogger(__name__) logging.basicConfig(stream=sys.stdout, level=logging.DEBUG) client = greengrasssdk.client("iot-data") # Setup GPIO GPIO.setwarnings(False) GPIO.setmode(GPIO.BCM) GPIO.setup(17, GPIO.OUT) GPIO.output(17, False) GPIO.setup(18, GPIO.OUT) GPIO.output(18, True) ser = serial.Serial("/dev/ttyS0", 9600, timeout=None) def is_valid_input_topic(context): try: topic = context.client_context.custom["subject"] if topic == INPUT_TOPIC: return True except Exception as e: logging.error("Topic could not be parsed. " + repr(e)) return False def get_input_metrics(event): metrics = event["metrics"] return metrics def get_sensor_data(command): ser.write(command) time.sleep(1) res = ser.read_all() sensor_value = int(res.hex()[22:26], 16) / 10 return sensor_value def get_value_by_metrics(metrics): if metrics.lower() == "temperature": return get_sensor_data(TEMPERATURE_CMD) elif metrics.lower() == "humidity": return get_sensor_data(HUMIDITY_CMD) else: return "" def publish_aws_iot_topic(topic, data): mqtt_conn = greengrasssdk.client("iot-data") mqtt_conn.publish( topic=topic, queueFullPolicy="AllOrException", payload=data, ) def lambda_handler(event, context): try: if is_valid_input_topic(context): metrics = get_input_metrics(event) logger.warn(f"metrics -> {metrics}") value = get_value_by_metrics(metrics) logger.warn(f"value -> {value}") publish_aws_iot_topic( OUTPUT_TOPIC, json.dumps( { "metrics": metrics, "value": value, } ), ) except Exception as e: logging.error(e)
エイリアスを切って保存します。
GreenGrass設定
Lambda設定
先程作成したLambdaを設定します。
Lambdaにローカルリソースを指定します。
例えば /dev/ttyS0
を使ってシリアル通信する場合は以下のように設定します。
今回はGPIOも利用するので、 /dev/gpiomem
も設定します。
サブスクリプション設定
IoT CloudからLambdaにコマンドを送り、Lambdaからの結果をIoT Cloudで受け取る設定にします。
デプロイ
デプロイします。
動かしてみる
test/get_value
トピックををサブスクライブしながら、 test/command
トピックに以下のようなPayloadを発行してみます。
{ "metrics": "temperature" }
metricsに temperature
を指定すれば温度、humidity
を指定すれば湿度が返ってきました。想定した通り動いていそうです。
プロトコルアダプター
Modbus-RTU用のプロトコルアダプタが準備されているので、それを使うこともできます。