motionイベントのトラップ送信スクリプト
motionとZabbixによる監視カメラシステム - GeekFactory では、監視カメラの動きを検出した時にZabbixにトラップを送信する仕組みを紹介しました。
動き検出にmotionというデーモンを利用しています。motionは動きを検出した場合に任意のスクリプトを実行できます。今回は4つのイベントを使います:
- on_event_start
- Command to be executed when an event starts. An event starts at first motion detected after a period of no motion defined by gap.
- on_event_end
- Command to be executed when an event ends after a period of no motion. The period of no motion is defined by option gap.
- on_motion_detected
- Command to be executed when a motion frame is detected.
- on_camera_lost
- Command to be executed when a camera can't be opened or if it is lost.
イベントが発生すると指定したスクリプトが実行され、画像の変化量などを受け取れます。測定値をZabbixでグラフ化する場合、変化がない間は測定値が存在しないことに注意が必要です。例えば、8時に変化量10、17時に変化量100であった場合、グラフは (8, 10)-(17, 100) を結ぶ直線になります。この場合、8時から17時の間は変化がないので変化量0で描画したいため、一工夫します。
on_event_startでは動き検出の起点が得られます。動きを検出した時点をT、変化量をDとすると、以下の測定値を出力すると、立ち上がりのグラフが描けます:
時刻 | 値 |
---|---|
T - 60秒*1 | 0 |
T | D |
この考え方でスクリプトを書き直してみました。
#!/bin/bash # # motion-zabbix-sender # # Specify this script in motion.conf: # on_event_start /usr/local/bin/motion-zabbix-sender %s on_event_start %D %i %J # on_event_end /usr/local/bin/motion-zabbix-sender %s on_event_end # on_motion_detected /usr/local/bin/motion-zabbix-sender %s on_motion_detected %D %i %J # on_camera_lost /usr/local/bin/motion-zabbix-sender %s on_camera_lost # SENDER="/usr/bin/zabbix_sender" SENDER_OPTIONS="-z xxx.xxx.xxx.xxx -p 10051" ARGS="$*" function send_traps () { ${SENDER} ${SENDER_OPTIONS} -T -i - "$@" || logger -t motion "could not send trap: $ARGS" } timestamp="$1" trigger="$2" shift 2 case "$trigger" in 'on_event_start') timestamp_previous="$(($timestamp - 60))" send_traps << EOF $HOSTNAME motion.is_alive $timestamp 1 $HOSTNAME motion.changed $timestamp $1 $HOSTNAME motion.changed $timestamp_previous 0 $HOSTNAME motion.area $timestamp $(($2 * $3)) $HOSTNAME motion.area $timestamp_previous 0 EOF ;; 'on_event_end') send_traps << EOF $HOSTNAME motion.is_alive $timestamp 1 $HOSTNAME motion.changed $timestamp 0 $HOSTNAME motion.area $timestamp 0 EOF ;; 'on_motion_detected') send_traps << EOF $HOSTNAME motion.is_alive $timestamp 1 $HOSTNAME motion.changed $timestamp $1 $HOSTNAME motion.area $timestamp $(($2 * $3)) EOF ;; 'on_camera_lost') send_traps << EOF $HOSTNAME motion.is_alive $timestamp 0 EOF ;; *) echo 'invalid argument'; exit 1;; esac
*1:できるだけ短い方がよい。60秒より短くしたらグラフがおかしくなったので、とりあえず60秒にしています。