2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

MQTT通信をトリガーにしてRaspberry Pi 3 ModelBでカメラ撮影

Last updated at Posted at 2022-02-20

目的

M5StickCを使った玄関の鍵かけ忘れ防止システム(運用編) で作ったシステムに監視カメラ的な要素を追加するため、M5StickCからのMQTT通信をトリガーにラズパイでカメラ撮影ができる仕組みを構築する

環境

全体像
image1.png

詳細

作業メモ

M5StickC→ラズパイへMQTT通信("環境"の図の①)

参考サイト
https://yoshitaku-jp.hatenablog.com/entry/2019/06/30/210000
https://qiita.com/ekzemplaro/items/ab90dd630c3ad8e819ab
https://qiita.com/ekzemplaro/items/14ab3b599a6785187f6f

  • ラズパイ側に必要なライブラリを導入(mosquitto, paho-mqtt)

まずは mosquitto を導入

$ sudo apt install mosquitto
$ sudo apt install mosquitto-clients

とりあえず起動して動作確認
(今回はmosquittoはBrokerとしてのみの動作のため、これで動作確認としては十分)

$ sudo systemctl start mosquitto

$ sudo systemctl status mosquitto
● mosquitto.service - Mosquitto MQTT v3.1/v3.1.1 Broker
   Loaded: loaded (/lib/systemd/system/mosquitto.service; enabled; vendor preset: enabled)
   Active: active (running) since Sat 2021-09-18 17:57:29 JST; 3min 53s ago
     Docs: man:mosquitto.conf(5)
           man:mosquitto(8)
 Main PID: 1281 (mosquitto)
    Tasks: 1 (limit: 1939)
   CGroup: /system.slice/mosquitto.service
           mq1281 /usr/sbin/mosquitto -c /etc/mosquitto/mosquitto.conf

 9月 18 17:57:29 raspberrypi systemd[1]: Starting Mosquitto MQTT v3.1/v3.1.1 Broker...
 9月 18 17:57:29 raspberrypi systemd[1]: Started Mosquitto MQTT v3.1/v3.1.1 Broker.

次に paho-mqtt を導入
(Pythonライブラリなので、pipでインストール)

$ sudo pip install paho-mqtt
  • M5StickCからMQTT通信するコードを作成

今回はM5StickC(MQTT Publisher)起動時に1回ラズパイ(MQTT Broker)へMQTT通信させる
(「camera_start」というメッセージを送信)

#include <M5StickC.h>
#include <Wire.h>
#include <WiFi.h>
#include <PubSubClient.h>

/*---------------------------------------------
   Global Data
-----------------------------------------------*/

/* -- 「*****」は環境に応じて設定必要 -- */
// For MQTT to raspberrypi
#define WLAN_SSID "*****"
#define WLAN_PASS "*****"

// MQTTの接続先のIP
const char *endpoint = "*****";
// MQTTのポート
const int port = 1883;
// デバイスID
char *deviceID = "*****";
// メッセージを知らせるトピック
char *pubTopic = "/pub/M5Stack";
// メッセージを待つトピック
char *subTopic = "/sub/M5Stack";
// 送信するメッセージ
char *pubMessage = "camera_start";
/* -- 環境に応じて設定必要(ここまで) -- */

WiFiClient client;
PubSubClient mqttClient(client);

void connectMQTT();

void setup() {
  M5.begin();
  Wire.begin(0,26);

  // WiFi設定
  WiFi.begin(WLAN_SSID, WLAN_PASS);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
  }

  // ラズパイへトリガー送信(MQTT)
  mqttClient.setServer(endpoint, port);
  connectMQTT();
}

void loop() {
}

void connectMQTT() {
  // Server側(ラズパイ)と接続できるまで繰り返し
  while (!mqttClient.connected()) {
    if (mqttClient.connect(deviceID)) {
      // メッセージ送信
      mqttClient.publish(pubTopic, pubMessage);

      int qos = 0;
      mqttClient.subscribe(subTopic, qos);
    } 
    else {
      Serial.print("Failed. Error state=");
      Serial.print(mqttClient.state());
      // リトライ前に1[s]wait
      delay(1000);
    }
  }
}
  • MQTT通信で来ているか動作結果

とりあえず簡単に動作確認するため、mosquittoのSubscribe機能を使って通信確認
→ 送信したメッセージcamera_startが受信できていることを確認
ラズパイ側のちゃんとした対応は次項で説明

$ mosquitto_sub -d -t /pub/M5Stack
Client mosqsub|1861-raspberryp sending CONNECT
Client mosqsub|1861-raspberryp received CONNACK (0)
Client mosqsub|1861-raspberryp sending SUBSCRIBE (Mid: 1, Topic: /pub/M5Stack, QoS: 0)
Client mosqsub|1861-raspberryp received SUBACK
Subscribed (mid: 1): 0
Client mosqsub|1861-raspberryp received PUBLISH (d0, q0, r0, m0, '/pub/M5Stack', ... (12 bytes))
camera_start

MQTT通信を検知→カメラ撮影("環境"の図の②、③)

参考サイト
https://qiita.com/ekzemplaro/items/14ab3b599a6785187f6f
https://www.raspberrypi.com/documentation/accessories/camera.html

  • MQTT通信を検知するコードを作成(paho-mqttを利用)

brokertopicを環境に応じて設定が必要
カメラモジュールのオプションなどは 参考サイト を参照

pahomqtt.py
#!/usr/bin/python3

import random
import subprocess
import datetime

from paho.mqtt import client as mqtt_client

# brokerにはラズパイのIPアドレスを指定
broker = '*****'
port = 1883
# M5StickCで指定したトピックと同じトピックを指定
topic = "/pub/M5Stack"
# client IDをランダム生成
client_id = f'python-mqtt-{random.randint(0, 100)}'

def connect_mqtt() -> mqtt_client:
    def on_connect(client, userdata, flags, rc):
        if rc == 0:
            print("Connected to MQTT Broker!")
        else:
            print("Failed to connect, return code %d\n", rc)
            sys.exit(rc)

    client = mqtt_client.Client(client_id)
    client.on_connect = on_connect
    client.connect(broker, port)
    return client


def subscribe(client: mqtt_client):
    def on_message(client, userdata, msg):
        # 撮影した画像のファイル名:[year][month][date][time].jpg
        t_delta = datetime.timedelta(hours=9)
        JST = datetime.timezone(t_delta, 'JST')
        now = datetime.datetime.now(JST)
        date = now.strftime('%Y%m%d%H%M%S')
        print(f"Received `{msg.payload.decode()}` from `{msg.topic}` topic")
        if "camera_start" in msg.payload.decode():
            try:
                # 解像度1024x768/quality=75で撮影
                cmd = "raspistill -o /home/pi/{0}.jpg -hf -vf -w 1024 -h 768 -q 75".format(date)
                res = subprocess.check_call(cmd, shell=True)
            except:
                print("rasp camera error")

    client.subscribe(topic)
    client.on_message = on_message


def run():
    client = connect_mqtt()
    subscribe(client)
    client.loop_forever()


if __name__ == '__main__':
    run()

動作確認

M5StickCからのMQTT通信を受信できると、/home/pi以下に撮影画像が保存される

$ ls ~/
20220220172347.jpg
....
  • 作成したコードを常時動作させるようにService化

以前自分で書いた記事 を見つつ、常時動作ためのService登録をする

ここでは、先ほど作ったpahomqtt.pyを起動時に一度だけ実行する、Serviceを登録する
(pahomqtt.pyはloopしてMQTT通信を待つ作りになっているので、実行は一度だけでいい)

mqtt_run.service
[Unit]
Description=MQTT SUBSCRIBE
After=multi-user.target
DefaultDependencies=no

[Service]
Type=simple
ExecStart=/usr/bin/pahomqtt.py
Restart=no

[Install]
WantedBy=multi-user.target

必要なファイルを必要な場所に配置

$ chmod u+x pahomqtt.py
$ sudo cp pahomqtt.py /usr/bin/
$ sudo cp mqtt_run.service /etc/systemd/system/

再起動してServiceが正常に動いていることを確認

$ sudo systemctl status mqtt_run.service
● mqtt_run.service - MQTT SUBSCRIBE
   Loaded: loaded (/etc/systemd/system/mqtt_run.service; enabled; vendor preset:
   Active: active (running) since Sun 2022-02-20 18:26:29 JST; 2min 25s ago
 Main PID: 924 (pahomqtt.py)
    Tasks: 1 (limit: 1939)
   CGroup: /system.slice/mqtt_run.service
           mq924 /usr/bin/python3 /usr/bin/pahomqtt.py

 2月 20 18:26:29 raspberrypi systemd[1]: Started MQTT SUBSCRIBE.
  • MQTT通信を検知 → カメラ撮影の動作確認

Service登録ができた状態でM5StickCを起動 → ラズパイでのカメラ撮影ができることを確認

$ ls ~/
20220220172347.jpg   # こちらはお試し動作確認したときに撮った画像
20220220183642.jpg
....

まとめ

目標を達成!!

M5StickCを使った玄関の鍵かけ忘れ防止システム(運用編) で作ったシステムに監視カメラ的な要素を追加するため、M5StickCからのMQTT通信をトリガーにラズパイでカメラ撮影ができる仕組みを構築する

今後は M5StickCを使った玄関の鍵かけ忘れ防止システム(運用編) に今回の内容をマージしていきたい

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?