takechi が 2024年10月30日15時53分21秒 に編集
コメント無し
本文の変更
**1. 概要** LINE Messaging APIで特定のメッセージを送信すると、扉が施錠か開錠される 鍵の状態が変化するとカメラで鍵を撮影し施錠、開錠のメッセージとともに画像を返信する **2. 概要を示す図** ![イメージ図1](https://camo.elchika.com/d7787f02efee077d91bd58850b6c42f3b0f88895/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f32636635623865302d376462302d343939322d393234392d3966626437626533386566662f61643937303061302d346332372d343734362d623335652d343939373331393631373838/) ![イメージ図2](https://camo.elchika.com/fa7decf3c4569c10fc9d91399a9e5df8614a43ce/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f32636635623865302d376462302d343939322d393234392d3966626437626533386566662f64663033656530332d653531622d346633652d613931632d333164326462386133306131/) **3. アイデアの詳細** • 施錠したいとき…LINE Messaging APIで「施錠」や「鍵閉めて」などのキーワードを送信する • 開錠したいとき…LINE Messaging APIで「開錠」や「鍵開けて」などのキーワードを送信する • サーボモータで鍵の状態が変化するとカメラで撮影する • 開錠したか施錠したかを知らせるメッセージとともに撮影した画像を返信する **4. 必要となるもの** • Raspberry Pi 4 • サーボモータ(SG90) • python(今回はver3.9.2、開発環境はThonny)
• ngrok
• ngrok [Raspberry Piでのインストール](https://ngrok.com/docs/guides/device-gateway/raspberry-pi/)
• Pi camera • LINE Messaging API v3 (pythonでは3.9以上が必要) ngrokとLINE Messaging API v3については参考文献をご覧ください。 **5. 実物** ![キャプションを入力できます](https://camo.elchika.com/6d5675821791e777d5d42ae29fdfee48e5029105/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f32636635623865302d376462302d343939322d393234392d3966626437626533386566662f35626436386165662d393366382d346534362d613239632d393063393937666362633538/) ![キャプションを入力できます](https://camo.elchika.com/7af4db3a8246f78d13d15549f01390c8c4366149/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f32636635623865302d376462302d343939322d393234392d3966626437626533386566662f35613661623063612d306436642d346438372d613461342d323137353263323964393132/) **6. ソースコード** カメラで動画をとってjpegとmp4で保存することはできたのですが、画像をテキストメッセージと同時に返信することができませんでした。返信がきても鍵がかかっているかどうか不安になることがあると思うので改善していきたいです。 ```arduino:メインのプログラム import pigpio, requests, datetime import RPi.GPIO as GPIO from picamera2 import MappedArray, Picamera2 from picamera2.encoders import H264Encoder import time, sys, io, cv2, shutil import threading, os from argparse import ArgumentParser from flask import Flask, request, abort from linebot.v3 import ( WebhookHandler ) from linebot.v3.messaging import ( Configuration, ApiClient, MessagingApi, ) from linebot.v3.exceptions import ( InvalidSignatureError ) from linebot.v3.messaging import ( Configuration, ApiClient, MessagingApi, ReplyMessageRequest, TextMessage ) from linebot.v3.webhooks import ( MessageEvent, TextMessageContent ) app = Flask(__name__) # チャンネルシークレットとチャンネルアクセストークンの登録 channel_secret = 'シークレットトークンを記入する' channel_access_token = "アクセストークンを記入する" if channel_secret is None: print('Specify LINE_CHANNEL_SECRET as environment variable.') sys.exit(1) if channel_access_token is None: print('Specify LINE_CHANNEL_ACCESS_TOKEN as environment variable.') sys.exit(1) configuration = Configuration(access_token=channel_access_token) handler = WebhookHandler(channel_secret) SERVO = 18 # サーボモータのピン番号 LED1 = 17 # LED PIR = 4 # モーションセンサー GPIO.setwarnings(False) # 警告を無視 GPIO.setmode(GPIO.BCM) # GPIOのピン番号で指定する GPIO.setup(LED1, GPIO.OUT) # LED1 出力指定 GPIO.setup(PIR, GPIO.IN) # PIR 入力指定 # pigpioを初期化 pi = pigpio.pi() # サーボモーターを特定の角度に設定する関数 def set_angle(angle): assert 0 <= angle <= 180, '角度は0から180の間で指定する' pulse_width = (angle / 180) * (2500 - 500) + 500 pi.set_servo_pulsewidth(SERVO, pulse_width) open_message = ["あけて", "開けて", "鍵開けて"] close_message = ["閉めて", "しめて", "締めて", "鍵閉めて"] def open_key(): set_angle(0) time.sleep(1) set_angle(90) time.sleep(1) print("開けました") def close_key(): set_angle(0) time.sleep(1) set_angle(90) time.sleep(1) print("締めました") @app.route("/callback", methods=['POST']) def callback(): signature = request.headers['X-Line-Signature'] body = request.get_data(as_text=True) app.logger.info("Request body: " + body) try: handler.handle(body, signature) except InvalidSignatureError: abort(400) return 'OK' @handler.add(MessageEvent, message=TextMessageContent) def handle_message(event): with ApiClient(configuration) as api_client: line_bot_api = MessagingApi(api_client) if event.message.text in open_message: open_key() response_text = "鍵を開けました" camera01() # 録画開始 elif event.message.text in close_message: close_key() response_text = "鍵を閉めました" camera01() # 録画開始 else: response_text = "認識できないメッセージです" webhook_url = "https://Webhookに入力したリンク" # image_url = "/var/www/html/movie/servo_img.mp4" line_bot_api.reply_message_with_http_info( ReplyMessageRequest( reply_token=event.reply_token, messages=[TextMessage(text=response_text)] ) ) def camera01(): print("CAMERA START") camera = Picamera2() camera.configure(camera.create_video_configuration()) camera.configure(camera.create_preview_configuration(main={"format": 'XRGB8888', "size": (640, 480)})) color = (0, 255, 0) # タイムスタンプの色を設定 origin = (0, 30) font = cv2.FONT_HERSHEY_SIMPLEX scale = 1 thickness = 2 camera.start_and_capture_file("timestamp.jpg") def apply_timestamp(request): timestamp = time.strftime("%Y-%m-%d %X") # タイムスタンプのフォーマットを設定 with MappedArray(request, "main") as m: cv2.putText(m.array, timestamp, origin, font, scale, color, thickness) camera.pre_callback = apply_timestamp encoder = H264Encoder(10000000) camera.start_recording(encoder, "timestamped.h264") # 録画開始 time.sleep(1) # 録画時間 camera.stop_recording() # 録画終了 os.system('/usr/bin/MP4Box -add timestamped.h264 timestamped.mp4') # mp4に変換 shutil.move("./timestamped.mp4", "/var/www/html/movie/") os.rename("/var/www/html/movie/timestamped.mp4", f"/var/www/html/movie/servo_img.mp4") # 録画データのファイル名変更 camera.close() # カメラ停止処理 if __name__ == "__main__": arg_parser = ArgumentParser( usage='Usage: python ' + __file__ + ' [--port ] [--help]' ) arg_parser.add_argument('-p', '--port', default=8000, help='port') arg_parser.add_argument('-d', '--debug', default=False, help='debug') options = arg_parser.parse_args() app.run(debug=options.debug, port=options.port) ``` LINEから送信したメッセージが開錠と施錠するためのキーワードが格納されている配列のopen_messageとclose_messageの文字列と一致すると、サーボモータが開錠するopen_keyと施錠するclose_keyを実行します。カメラの動作は、camera01で処理しています。その他は参考文献をご覧ください。 **7. 参考文献** - アイデア [LINEから「ただいま」と送れば、マンションのオートロックを開けてくれるシステムをRaspberry Piで作った](https://zenn.dev/yukitezuka/articles/1985fc12052e5a#python%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0%E3%81%AE%E5%AE%9F%E8%A3%85) - プログラム [LINE Messaging API SDK for Python](https://github.com/line/line-bot-sdk-python) [[無料][2024年版] LINE Messaging API v3 + Python(Flask) でボットを作る [その0 - v3 での変更点]](https://qiita.com/nozomiyamada/items/dff5f240e8c936d731fd) [line-bot-sdk-python V3のコードサンプル](https://qiita.com/cog1t0/items/970f3cdd2116bc6947b5) [【Python】オウム返しするLINE BOT作成](https://qiita.com/yuta-2001/items/914fcaee61e80a5ee1ce)