監視カメラ　ジャンプ　不在時に侵入者がいれば、Line通知

侵入者がいれば、不在(9:30-11:30）時にLine通知させる。
# Lineの記事
LINEは、外部アプリケーションなどからLINEアプリに通知を送信できる開発者向けサービス「LINE Notify」のサービスを、2025年3月31日に終了すると発表した。
代替として、LINE公式アカウントからメッセージを送信できる「Messaging API」（月200通まで無料、それ以上は月5000円～）の利用を検討するよう呼び掛けている。
ということで、Line通知には「Messaging API」を使うこととした。
ひまじんが1ケ月　不在想定(9:30-11:30）の時にいたとしても 31通なので問題無しと判断。
2025/1/12　不在判断をカメラとAIで人を検知させることに成功したので、侵入者がいなければ月　0通。
# 準備　　
参考サイト
https://note.com/khe00716/n/n34bb4c087fdc
https://gafuburo.net/raspi-line-message/
https://qiita.com/NaruNeko/items/36ba4d121350a94bddf3

手順はざっと以下となる。
参考サイト
https://note.com/shuzooooo/n/n311b619a3183

１．LINE Developersからログイン。
https://account.line.biz/login?redirectUri=https%3A%2F%2Fdevelopers.line.biz%2Fconsole%2F

２．プロバイダ名を作成。
m_sunafukin77　で作成しました。

３．LineBusinessIDでログインして　Messaging APIのチャネルを作成。

４．Line公式アカウントの作成

５．LINE Official Account Manager　より、　Messaging APIを利用する設定にする。
Channel secret　を　コピーする。（控える）

６．LINE Developerで　チャネルアクセストークン（長期） を発行し、控える。

# 組み込み

１．LINE Messaging API SDK for Python　を　以下よりインストール
```
pip install line-bot-sdk
```
以下メッセージがでるが、とりあえず無視。
```
warning: error parsing dependencies of gpg: invalid version: '1.14.0-unknown'
```
２．https://github.com/line/line-bot-sdk-python
に　Usageがあるので　以下の部分を控えたコードに変更し、app.py（この名前でないとダメ）で保存。
※git cloneでソースをclone すると言う意味では無い。
```
line_bot_api = LineBotApi('YOUR_CHANNEL_ACCESS_TOKEN')
handler = WebhookHandler('YOUR_CHANNEL_SECRET')
```
２．バックエンドのwebアプリとして動作するため、flaskが必要になるのでflaskもインストール。
```
pip install flask 
```
以下メッセージがでるが、とりあえず無視。
```
warning: error parsing dependencies of gpg: invalid version: '1.14.0-unknown'
```
３．flaskのインストールが終わったらflask runを実行すると先ほどのapp.pyが起動される。
```
$ flask run
* Environment: production
  WARNING: This is a development server. Do not use it in a production deployment.
  Use a production WSGI server instead.
* Debug mode: off
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
```
# サーバの設定
１．webアプリとしてデプロイするにはサーバーが必要になるが、ngrokというサーバーソフトを使用。これは一時的に自分のパソコンのポート開いてサーバーにしてくれるソフト。エングロックをインストール
```
sudo npm install ngrok -g --unsafe-perm=true --allow-root
```
２．アパッチインストール
```
sudo apt-get install apache2
```
３．https://qiita.com/murachi1208/items/39f89531ae9059d1260c
の方より、アカウント登録が必須になったとのことで以下を実施。
　アカウント登録とAuthトークン取得
　１）https://ngrok.com/ にアクセスしてアカウント登録
　２）Getting Started - Your Authtoken メニューを表示しトークンをコピー
　以下を実行
```
ngrok authtoken xxxxxxxxxxxxxxxxxxx
```
５．ngrok 80 ポートで実行＝外部公開　5000ポートで実行しようとしたが、何故か怒られたのでポート80とする。　
```
ngrok http　80
```
６．公開されている　URLアドレスをコピーして、Line DevelopersのMseesageAPIのwebhookURLにペースト。その際、pythonのプログラムで/callbackが呼び出されてときに返信するモジュールが呼び出されるように設定されている為、/callbackをつける。
```
https://XXXXX-XXXX-XXX-XXX-XXXX-XXXX-XXXX-XXXX-XXXX.ngrok-free.app/callback
```
webhookURLに設定するアドレスですが、ngrok http　80　の起動ごとに変わってしまう、その都度コピぺする必要が有り。要することに　「ngrok http　80」をやらなければよいということ。ラズパイのリブートとは関係無し。

７．応答メッセージの送信をwebhookURLに設定したwebアプリにする。

８．スマホとの接続
スマホのLINEを立ち上げて、IDまたはQRコードで検索すると自分が作成したbotが出てくるのでお友達登録する。
チャットできるか試す。　いけた。　これでまずはＯＫ。
# Line通知検証
１．以下を作成。　pushMsg.py　で保存。
```
# pushMsg.py
import requests

headers = {
    "Content_Type": "application/json",
    "Authorization": "Bearer " + 'Your Token'
    }

def SendMsg(text,uid):
    res = requests.post("https://api.line.me/v2/bot/message/push", 
                        headers=headers, 
                        json={
                            "to": uid,
                            "messages": [{
                                            "type": "text",
                                            "text": text
                                        }]
                        }
                        ).json()

if __name__ == "__main__":
    SendMsg('侵入者を検知しました!', 'Your Userid')
```
実行したら、ボクのスマホに通知がいった。ヒャッホー。
![OSSA5698.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/433305/0cab04fc-4fbf-9eb8-8ac0-5881325cd6d5.jpeg)

２．仕上げ　camera_jimkan.pyを変更。pushMsg.pyを呼ぶ処理を追加。
```
#!/usr/bin/env python3
import RPi.GPIO as GPIO
import os
import time
import datetime
import subprocess

GPIO_PIN = 18

GPIO.setmode(GPIO.BCM)
GPIO.setup(GPIO_PIN,GPIO.IN)

# 時間計測開始
t_start = time.perf_counter()

# オプション
#  HQカメラの場合
#   写真の最大サイズは4056x3040
#   動画(H.264)の最大サイズは1920x1080, 最大画角は1440x1080
image_size = (1440, 1080)  # 撮影サイズの横幅, 高さ
mode = 'movie'  # 写真なら'photo', 動画なら'movie'
# pi5 = False  # Raspberry Pi 5の場合True, それ以外はFalse (動画撮影の手順が異なる)
save_dir = '/home/pi'  # 写真や動画を保存するディレクトリ
# interval = 60  # 1度撮影した後、再開するまでのインターバル時間[秒]
movie_duration = 10  # 動画の撮影時間[秒]

if __name__ == '__main__':
    try:
        while True:
# 現在時刻取得
            t_end = time.perf_counter()
# 経過時間計算
            elaps = t_end - t_start
# ２Ｈ超えたらブレーク    
            if elaps > 7200:
                break
            print(elaps)
            if(GPIO.input(GPIO_PIN) == GPIO.HIGH):
               print("man search")
               dt = datetime.datetime.now()
               if mode == 'photo':
                    save_file = os.path.join(save_dir, dt.strftime('%y_%m%d_%H%M_%S.jpg'))
                    subprocess.run([
                        'libcamera-still', '-n', '-o',
                        os.path.join(save_file), '-t', '1', '--width',
                        str(image_size[0]), '--height',
                        str(image_size[1])
                        ])
                    subprocess.check_call('sudo python3 /home/pi/pushMsg.py', shell=True)
                    time.sleep( 10 )
                    break
               elif mode == 'movie':
                    save_file = os.path.join(save_dir, dt.strftime('%y_%m%d_%H%M_%S.mkv'))
                    h264_file = os.path.join(save_dir, 'tmp.h264')
                    pts_file = os.path.join(save_dir, 'tmp.txt')
                    subprocess.run([
                        'libcamera-vid', '-n', '-o', h264_file, '--save-pts', pts_file, '-t',
                        str(movie_duration * 1000), '--width',
                        str(image_size[0]), '--height',
                        str(image_size[1])
                        ])
                    subprocess.run(['mkvmerge', '-o', save_file, '--timecodes', '0:' + pts_file, h264_file])
                    os.remove(h264_file)
                    os.remove(pts_file)
                    subprocess.check_call('sudo python3 /home/pi/pushMsg.py', shell=True)
                    time.sleep( 10 )
                    break
            else:
                print("man no search")
                print(GPIO.input(GPIO_PIN))
                time.sleep( 1 )
    finally:
        GPIO.cleanup()
        print("GPIO clean完了")
```
これで完成。
ひまじんの環境だと　Lanとwan（インターネット）が混在するからか、ケーブルをwifiルータに接続しないとダメ。これはGithubに接続するときもそうだが。とりあえずは良し。
１）2025/1/7　人感センサーが仮想環境でないと誤作動することがわかったので仮想環境で実行させることとする。⇒誤り。2025/1/10　ノイズが原因と判明。
 2025/1/8　誤検知している。　調査中。　
 2025/1/8　21:16　以下　参考サイトでフェライトコアでノイズが消えると記載ある。
大昔　ADSLの時代に　フェライトコアいくつも付けた記憶ある。　なつかしい。
試しに大須のボントンさんで275円で購入して設置。
2025/1/9 朝8:00は誤検知解消していた。　以降　誤検知している。
2025/1/10 フェライトコアをＧＰＩＯ（Output）に正しく装着。　今のところ、誤検知していない。
2025/1/11 フェライトコアで精度はあがったとは思うが、誤検知している。
HC-SR501は実用的ではないですね。　ぼくのアイリスオーヤマのこたつの人感センサーは精度いいのにね。
もう売ってないみたいね。
https://www.amazon.co.jp/gp/product/B0099JWZTC/ref=ppx_yo_dt_b_search_asin_title?ie=UTF8&psc=1
# 2025/1/11　カメラとAIで人を検知させることにした。　決意。　2025/1/12　実装完了。
https://qiita.com/m_sunafukin77/items/291f101f88b31a3b008b

![IMG_0096.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/433305/cabcb7ae-53e5-12a0-89d9-3dc8b3074273.jpeg)
https://www.souichi.club/raspberrypi/watch-over-07/

何回か仮想環境でテストしていたので、必要なモジュールは入っていたようだ。
```
source ~/vpy/bin/activate
python3 camera_jinkan.py
deactivate
```
２）crontabの変更
```
sudo crontab -e
```
中身は以下
30 9 * * * cd /home/pi/ && /home/pi/vpy/bin/python camera_jinkan.py >> /tmp/cronj.log 2>&1

９．あまりにも標準のケーブルが短いので。ちょっとカメラの位置をかえたいので配線を30cmのケーブルに交換。位置を変えられたので、かなり広い範囲で動画がキャプチャできるようになった。

![IMG_0073.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/433305/1011549c-ae8e-9c6c-56b8-a89cd513dfda.jpeg)