今の車載Raspberry Pi zero 2 W は、車載警報装置のイヤホンマイクをGPIOに接続して、発報すると、イヤホンマイクスイッチがONになるので、それをトリガにメール&SMS送信するようになっている。
加えて、カメラを追加して、bluetooth ヘッドホンの Open Run Proが接続していないと、motion をスタートさせて、動体検知記録する。
つまり、車に乗って、bluetooth ヘッドホンを接続していれば、動体検知はOFFで、車から離れて、bluetooth接続が切れたら、動体検知ONになるようにしている。
今回やろうとしてるのは、動体検知ONの時に、GPSで現在位置を保存して、定期的に車の移動距離を測定し、車が100m移動してたらメールを飛ばそうというもの。
【rx7pi新スペック】
- 車載警報装置 発報でガラケーのイヤホンマイクスイッチをONにしてくれるやつで、ラスタバナナのステレオ変換アダプタに接続して、GPIOに配線。
- LTE回線 donedone ASUS zenfone max pro(m2)に挿して、USBテザリング
- カメラOV5647
- USB GPSドングルVK172
※写真貼るのが面倒なので、アフィリエイト利用
とりあえず、USBのGPSドングルが余っていたので、Raspberry Pi zero 2 Wへ接続。
VK172って、2019年に1,090円で買ったけど、円安のせいで値上がりしとるなあ。
1 |
sudo apt install gpsd gpsd-clients |
gpsd をインストール。
既定の動作の設定
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
# Default settings for the gpsd init script and the hotplug wrapper. # Start the gpsd daemon automatically at boot time START_DAEMON="true" # Use USB hotplugging to add new USB devices automatically to the daemon USBAUTO="true" # Devices gpsd should collect to at boot time. # They need to be read/writeable, either by user gpsd or the group dialout. DEVICES="/dev/ttyACM0" # Other options you want to pass to gpsd GPSD_OPTIONS="-n -G" |
VPN経由で、FoxtrotGPSや、xgps、gpsmonが自端末で見れるようにListenStream=0.0.0.0:2947 にする。
1 2 3 4 5 6 7 8 9 10 11 12 |
[Unit] Description=GPS (Global Positioning System) Daemon Sockets [Socket] ListenStream=/var/run/gpsd.sock ListenStream=[::1]:2947 #ListenStream=127.0.0.1:2947 ListenStream=0.0.0.0:2947 SocketMode=0600 [Install] WantedBy=sockets.target |
設定ファイルの再読込と、サービスの再起動
1 2 |
$ sudo systemctl deamon-reload $ sudo systemctl restart gpsd.service |
ガレージを中心にそこそこの精度。
今回、新規作成した gpsd の出力から、緯度、経度を抜き出すプログラム。巷で出回ってるGPS出力から時間を抜くスクリプトの改造版(笑)
1 2 3 |
#!/bin/sh /usr/bin/gpspipe -w | /usr/bin/head -10 | /bin/grep TPV | /bin/sed -r 's/.*"lat":([^"]*),"lon":([^"]*),.*/\1,\2/' | /usr/bin/head -1 |
そして、2点の緯度経度から、距離を計算するプログラムだが、これは、次のページのpythonプログラムをシェルスクリプト用に書き直した。
情報源: Python で2点の緯度経度から距離を計測する方法 – GIS奮闘記
ありがとうございます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
#!/bin/bash START=(${1//,/ }) END=(${2//,/ }) cat << _EOD_|bc -l scale=20 pole_radius=6356752.314245 /* 極半径 */ equator_radius=6378137.0 /* 赤道半径 */ pi=4*a(1)/180 start_lat=${START[0]}*pi start_lon=${START[1]}*pi end_lat=${END[0]}*pi end_lon=${END[1]}*pi diff_lat=start_lat-end_lat diff_lon=start_lon-end_lon avg_lat=(start_lat+end_lat)/2 /* 平均緯度 */ e2=(equator_radius^2-pole_radius^2)/equator_radius^2 /* 第一離心率^2 */ w=sqrt(1-e2*(s(avg_lat)^2)) m=equator_radius*(1-e2)/(w^3) n=equator_radius/w distance=sqrt((m*diff_lat)^2+(n*diff_lon*c(avg_lat))^2) scale=2 distance/1 _EOD_ |
distance.sh 緯度1,経度1 緯度2,経度2 で距離(m)を出力する。
元のページは km 単位で、最後に1,000で割ってたけど、わしが欲しいのはメートル単位なので、1,000では割ってない。
ただ、 bc で、平方根使うと、小数点以下20位まで有効になるので、最後に scale=2を指定して、1で割り算して、小数点以下2桁までにしている。
どうせ、GPSの測定誤差が数十メートル単位で出るので、メートルの小数点以下はほぼ無意味だけどね。 🙂
上の2つを新たに組み込んだ車載警報装置モニタプログラムがこちら。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 |
#!/bin/bash GPIO=26 GPIO_DIR=/sys/class/gpio MOTION_PID=/dev/shm/motion.pid MOTION_STOP=/dev/shm/motion.stop GPS_BASE=/dev/shm/gps_base #BTMAC=XX:XX:XX:XX:XX:XX # OPPO Reno3 A BTMAC=XX:XX:XX:XX:XX:XX # OpenRun Pro by Shokz initialize(){ # GPIO26を有効化。プルアップ抵抗ON echo $GPIO >${GPIO_DIR}/export sleep 0.1 echo in >${GPIO_DIR}/gpio${GPIO}/direction sleep 0.1 echo high >${GPIO_DIR}/gpio${GPIO}/direction } shutdown_handler(){ # GPIOクリーンアップ echo $GPIO >$GPIO_DIR/unexport motion_stop exit 0 } mail_send(){ cat << _EOD_|/usr/sbin/sendmail -t -f yuji@noizumi.org From: yuji@noizumi.org To: yuji@noizumi.org Subject: Car Security alert $1 Car Security alarm was $1 at `date +"%Y/%m/%d %H:%M:%S"` $2 _EOD_ } sms_send(){ DATEMES=`date +"%Y/%m/%d %H:%M:%S"` curl -X POST https://api.twilio.com/2010-04-01/Accounts/[アカウント]/Messages.json \ --data-urlencode "Body=Car Security alarm was $1 at $DATEMES" \ --data-urlencode "From=[twilio電話番号]" \ --data-urlencode "To=[わしの携帯電話番号]" \ -u [twilioアカウント]:[twilioパスワード] -o /home/noizumi/logs/twilio.log } button_pushed(){ motion_start mail_send activated sms_send activated # ボタンが押されている間、ループ while [ "`cat ${GPIO_DIR}/gpio${GPIO}/value`" = "0" ]; do sleep 1 done mail_send stopped sms_send stopped } motion_start(){ if [ ! -e ${MOTION_PID} ]; then # 動体検知開始時の現在位置の保存 gpslatlon.sh >${GPS_BASE} motion -n & echo $! >${MOTION_PID} fi } motion_stop(){ if [ -e ${MOTION_PID} ]; then kill -TERM `cat ${MOTION_PID}` rm -f ${MOTION_PID} || true rm -f ${GPS_BASE} || true fi } bluetooth_connect(){ # 接続状態確認 CONNECTED=`cat << _EOD_|bluetoothctl|grep "Connected: yes" power on info ${BTMAC} quit _EOD_ ` # bluetooth 接続状態確認 if [ "${CONNECTED}" != "" ]; then # 接続してたら、動体検知止める motion_stop else # 接続してなかったら、動体検知スタート motion_start fi } initialize trap shutdown_handler 1 2 3 15 # pulseaudo 起動確認 if [ "`ps ux|grep -e \"${USER}.*pulseaudio\"|grep -v grep`" = "" ]; then pulseaudio --start sudo systemctl restart bluetooth.service fi while :; do # イヤホンマイクボタンが押された時 if [ "`cat ${GPIO_DIR}/gpio${GPIO}/value`" = "0" ]; then button_pushed fi bluetooth_connect if [ -e ${GPS_BASE} ]; then # 動体検知開始時の現在位置の取得 GPS_SAVE=`cat ${GPS_BASE}` # 現在位置の取得 GPS_NOW=`gpslatlon.sh` # 移動距離計算 DISTANCE=`distance.sh $GPS_SAVE $GPS_NOW` # 100m以上移動していたらメール送信 if [ "`echo \"${DISTANCE}>100\"|bc`" = "1" ]; then mail_send "GPS Warning! ${DISTANCE}m moved." "https://maps.google.com/maps?q=${GPS_NOW}" fi else sleep 1 fi done |
そして、1m以上移動で異常にして、強引にメール送信させてみた。
1 2 3 4 5 6 7 8 |
From: yuji@noizumi.org To: yuji@noizumi.org Subject: Car Security alert GPS Warning! 4.66m moved. Message-Id: <E1orXIB-0004oY-9k@rx7pi> Date: Sun, 06 Nov 2022 13:29:55 +0900 Car Security alarm was GPS Warning! 4.66m moved. at 2022/11/06 13:29:55 https://maps.google.com/maps?q=35.68519148229406,139.75279343187816 |
google maps のURL付きにしたので、クリックすれば、車の位置がすぐ分かるようになっている。座標の方は、すり替えておいたのさ 🙂