hotch-potch, Note to self

いろいろ作業記録

外部信号でシャットダウン

はじめに

RaspberryPiの端子に信号が入力されると、シャットダウンする機能です。
いろいろなサンプルが公開されていますが、ここでは、systemdからスクリプトを起動して、定期的に監視する方法を説明します。

環境

  • Raspbian(2018-11-13-raspbian-stretch-lite)

スクリプト

GPIOの監視

「定数」の所は、環境に合わせて修正してください。

定数 意味
SET_WATCH_PORT GPIOピンにシャットダウン信号を入れる番号を指定
SET_TRIGGER 信号の立ち上がり・立ち下がりどちらで反応するかを設定
SET_WATCH_INTERVAL 指定した秒数ごとに、シャットダウン信号の状態を監視

ソース中の所々の[INSTALL DIR]は、お使いの環境に合わせて書き換えてください。

#!/bin/bash
#--------------------------------------------------------------------
#UPSの信号監視とシャットダウン
#--------------------------------------------------------------------
#
#install:
# $ sudo ln -s /home/pi/[INSTALL DIR]/setPowerWatcher.service /etc/systemd/system
# $ sudo systemctl enable setPowerWatcher.service
# $ sudo systemctl start setPowerWatcher.service
#--------------------------------------------------------------------
#ref:
#
# ※必ずbashを使うこと。shは関数の宣言でエラーが出ます
#   https://yatta47.hateblo.jp/entry/2014/04/20/222707
#

#----------------------------------
#定数
#----------------------------------

#監視するポート
SET_WATCH_PORT=2

#監視モード
# 1:ダウンパルス、0:アップパルス
SET_TRIGGER=1

#監視ループの間隔(sec)
SET_WATCH_INTERVAL=1


#----------------------------------
#関数
#----------------------------------

#シャットダウンの開始処理
function ShutdownGoProc ( ) {
    #シャットダウン信号を検出したメッセージを表示
    echo "  ! Shutdown signal detected. ${MESSAGE}"

    #シャットダウン処理を開始
    if [ ! "$MODE_TEST" = 1 ]; then
        #瞬停防止のため1秒だけshutdownを待つ
        /sbin/shutdown -P now
    fi
}

#シャットダウンの停止処理
function ShutdownStopProc ( ) {
    #シャットダウン信号を検出したメッセージを表示
    echo "  + Shutdown signal disappeared. ${MESSAGE}"

    #シャットダウン処理を中止
    if [ ! "$MODE_TEST" = 1 ]; then
        /sbin/shutdown -c
    fi

    #すぐにループ処理に戻らないよう、ウェイト
    sleep 1
}


#----------------------------------
#メイン処理
#----------------------------------

#実行中ユーザをチェック
if [ `/usr/bin/id -u` != "0" ]; then
    #rootでなければ異常終了
    echo " ! Please run as root."
    exit 1
fi

#主要コマンドの存在をチェック
if [ ! -x /usr/bin/gpio ]; then
    #見つからなければ異常終了
    echo " ! No 'gpio' Command."
    exit 1
fi

#自身のコマンド名を変数に入れる。usage用
CMDNAME=`basename $0`

#引数のチェックと動作フラグの生成
#https://shellscript.sunone.me/parameter.html
while getopts vt OPT
do
    case $OPT in
        "v" )
            #verboseモード
            MODE_VERBOSE=1 ;;
        "t" )
            #テストモード(シャットダウンはしない)
            MODE_TEST=1 ;;
        * )
            #それ以外の指定は、usageを表示
            echo "Usage: $CMDNAME [-v] [-t]" 1>&2
            exit 1 ;;
    esac
done

#動作モードのメッセージ
if [ ${SET_TRIGGER} -eq 1 ]; then
MESSAGE="(MODE: Down trigger)"
else
MESSAGE="(MODE: Up trigger)"
fi

#起動メッセージ
if [ "$MODE_VERBOSE" = 1 ]; then

  #メッセージ
  echo " * Monitor the GPIO signal and shutdown * ${MESSAGE}"

  #テストモードのメッセージ表示
  if [ "$MODE_TEST" = 1 ]; then
    echo '  - test mode (no shutdown)'
  fi
fi

#ポートの初期化
`/usr/bin/gpio -g mode ${SET_WATCH_PORT} in`

#監視ポートの状態変数の初期化と問い合わせ
STAT_PORT_PREV=`/usr/bin/gpio -g read ${SET_WATCH_PORT}`

#監視ループ
while :
do
    #監視ポートの状態を問い合わせ
    STAT_PORT_NOW=`/usr/bin/gpio -g read ${SET_WATCH_PORT}`

    if [ ${SET_TRIGGER} -eq 1 -a ${STAT_PORT_PREV} = "1"  -a  ${STAT_PORT_NOW} = "0" ]; then
        #ダウントリガで検知
        ShutdownGoProc
    elif [ ${SET_TRIGGER} -eq 0 -a ${STAT_PORT_PREV} = "0"  -a  ${STAT_PORT_NOW} = "1" ]; then
        #アップトリガで検知
        ShutdownGoProc 

    elif [ ${SET_TRIGGER} -eq 1 -a ${STAT_PORT_PREV} = "0"  -a  ${STAT_PORT_NOW} = "1" ]; then
        #アップトリガで検知
        ShutdownStopProc
    elif [ ${SET_TRIGGER} -eq 0 -a ${STAT_PORT_PREV} = "1"  -a  ${STAT_PORT_NOW} = "0" ]; then
        #ダウントリガで検知
        ShutdownStopProc 
    fi

    #監視ポートの状態変数に、現在の状態を代入
    STAT_PORT_PREV=${STAT_PORT_NOW}

    #ウェイト
    sleep ${SET_WATCH_INTERVAL}
done

exit 0

systemdに登録するserviceファイル

[Unit]
Description=Monitor the GPIO signal and shutdown
After=local-fs.target
ConditionPathExists=/home/pi/[INSTALL DIR]

[Service]
ExecStart=/home/pi/[INSTALL DIR]/setPowerWatcher.sh
ExecStop=/bin/kill ${MAINPID}
Restart=on-failure
StartLimitInterval=60
StartLimitBurst=3
KillMode=mixed
Type=simple
User=root
Group=root

[Install]
WantedBy=multi-user.target

インストール手順

systemdへ登録

systemdに登録して、サービスを起動します。

$ sudo ln -s /home/pi/[INSTALL DIR]/setPowerWatcher.service /etc/systemd/system
$ sudo systemctl enable /home/pi/[INSTALL DIR]/setPowerWatcher.service

serviceファイルを修正した時

下記のように都度、リロードします。

$ sudo systemctl daemon-reload

状態を確認

systemctl statusコマンドで、状態を確認します。
まだ起動していません

$ systemctl status setPowerWatcher.service
● setPowerWatcher.service - Monitor the GPIO signal and shutdown
   Loaded: loaded (/home/pi/[INSTALL DIR]/setPowerWatcher.service; linked; vendor preset: enabled)
   Active: inactive (dead)

起動

$ sudo systemctl start setPowerWatcher.service

状態を確認

下記のようになっていて、左上の●が緑色になっていれば、正常に起動しています。

$ systemctl status setPowerWatcher.service
● setPowerWatcher.service - Monitor the GPIO signal and shutdown
   Loaded: loaded (/home/pi/[INSTALL DIR]/setPowerWatcher.service; enabled; vendor preset: enabled)
   Active: active (running) since Sat 2019-03-09 15:47:22 JST; 9s ago
 Main PID: 537 (setPowerWatcher)
   CGroup: /system.slice/setPowerWatcher.service
           tq537 /bin/bash /home/pi/[INSTALL DIR]/setPowerWatcher.sh
           mq564 sleep 1

Mar 09 15:47:22 raspizwh systemd[1]: Started Monitor the GPIO signal and shutdown.

動作確認

GPIOに信号を入れると、間もなくシャットダウンします
その際syslogには、下記のメッセージが残ります。

Mar  9 15:58:13 raspizwh setPowerWatcher.sh[537]:   ! Shutdown signal detected. (MODE: Down trigger)

RaspberryPi上のPython3でSQLServerに読み書き

はじめに

Raspbian上で動かすPython3のスクリプトから、別のサーバのSQLServerに対しデータを書き込む方法について。(Python2.7と違って、apt-getでpymssqlのパッケージが入れられなかったので、そのインストール手順の覚え書きです)

環境

  • Raspbian(2018-11-13-raspbian-stretch-lite)
  • Python3

SQLServer用のライブラリ「pymssql」をインストール

pipを使用するので、インストールしていなければ下記を実行

$ sudo apt-get install python3-pip

pymssqlのコンパイルに必要なライブラリをインストール

$ sudo apt-get install freetds-dev -y
(補足)FreeTDS-devを入れ忘れると・・・

コンパイル中に下記のエラーが出ます

...
    creating build/temp.linux-armv6l-3.5/src
    arm-linux-gnueabihf-gcc -pthread -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -g -fdebug-prefix-map=/build/python3.5-6waWnr/python3.5-3.5.3=. -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -fPIC -I/usr/local/include -I/usr/include/python3.5m -c src/_mssql.c -o build/temp.linux-armv6l-3.5/src/_mssql.o -DMSDBLIB
    src/_mssql.c:594:22: fatal error: sqlfront.h: No such file or directory
     #include "sqlfront.h"
                          ^
    compilation terminated.
    error: command 'arm-linux-gnueabihf-gcc' failed with exit status 1

    ----------------------------------------
Command "/usr/bin/python3 -u -c "import setuptools, tokenize;__file__='/tmp/pip-build-zgxb1qiz/pymssql/setup.py';f=getattr(tokenize, 'open', open)(__file__);code=f.read().replace('\r\n', '\n');f.close();exec(compile(code, __file__, 'exec'))" install --record /tmp/pip-_78s2jjv-record/install-record.txt --single-version-externally-managed --compile --user --prefix=" failed with error code 1 in /tmp/pip-build-zgxb1qiz/pymssql/

pipからpymssqlをインストール

インストールを完了するのに、RaspberryPi3で15分程度、RaspberryPiZeroWで1時間弱掛かります。

$ pip3 install pymssql
Collecting pymssql
  Downloading https://files.pythonhosted.org/packages/2e/81/99562b93d75f3fc5956fa65decfb35b38a4ee97cf93c1d0d3cb799fffb99/pymssql-2.1.4.tar.gz (691kB)
    100% |????????????????????????????????| 696kB 97kB/s
Building wheels for collected packages: pymssql
  Running setup.py bdist_wheel for pymssql ... done
  Stored in directory: /home/pi/.cache/pip/wheels/21/35/92/911576b44bbe7c19ff65d0f90a4af9a9571db4af36ffd3ede1
Successfully built pymssql
Installing collected packages: pymssql
Successfully installed pymssql-2.1.4

pymssqlの動作チェック

テーブルにレコードをf追加する簡単なスクリプトでテストします。

SqlServerのテーブルを作成

create table T_LogTest(
	DateAppend datetime,
	ClientID NVARCHAR(255),
	Value0 smallint,
	Value1 smallint,
	Value2 smallint);

書き込みスクリプト

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from os import getenv
import pymssql

conn = pymssql.connect('<host name>', '<database name>', '<user name>', '<password>')
cursor = conn.cursor()

cursor.execute("""
    INSERT INTO T_LogTest (
        DateAppend ,
        ClientID ,
        Value0 ,
        Value1 ,
        Value2)
    VALUES (
        GETDATE(),
        'hoge',
        2000,
        2010,
        2020)
    """)

conn.commit()

conn.close()

JETSONの"apt-get update"エラー

はじめに

久しぶり(18年10月以来ぶり)にJETSONを起動して、Ubuntuのアップデートをしようと思ったら、エラーが出てしまいました。
そのときの処置のメモです。

症状

nvidia@tegra-ubuntu:~$ sudo apt-get update
...
GPG error: file:/var/cuda-repo-9-0-local  Release: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY F60F4B3D7FA2AF80
...

処置

こちらを参考にしました。
https://devtalk.nvidia.com/default/topic/1030999/jetson-tx2/fresh-install-of-the-new-jetpack-with-errors/

キーの登録をし直す必要があるみたいです。

nvidia@tegra-ubuntu:~$ sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys F60F4B3D7FA2AF80
nvidia@tegra-ubuntu:~$ sudo apt-get update
nvidia@tegra-ubuntu:~$ sudo apt-get upgrade -y
nvidia@tegra-ubuntu:~$ sudo apt-get autoremove
nvidia@tegra-ubuntu:~$ sync
nvidia@tegra-ubuntu:~$ sudo reboot
...
nvidia@tegra-ubuntu:~$ uname -a
Linux tegra-ubuntu 4.4.38-tegra #1 SMP PREEMPT Thu Mar 1 20:49:20 PST 2018 aarch64 aarch64 aarch64 GNU/Linux

RaspberryPiにROSを簡単に入れてみる

はじめに

Raspbian(2018-11-13-raspbian-stretch)のROSパッケージをそのままインストールしてみました。
古いバージョンを使うことになるので、実際の所、良いのか分かりませんが、ひとまず手順を残します。

ROSの入門は、こちらを教科書にさせて頂きました。
ROS講座00 目次 - Qiita

下調べ

apt-cache で、RaspbianのROSのバージョンを調べてみました。
だいぶ古いバージョン(2016年春頃のリリース)のようです。

~ $ apt-cache show ros-core
Package: ros-core
Source: ros-metapackages
Version: 1.7
Installed-Size: 8
Maintainer: Debian Science Maintainers <debian-science-maintainers@lists.alioth.debian.org>
Architecture: all
Depends: python-rosclean, python-rosbag, python-rosgraph, python-roslaunch, python-rosmaster, python-rosmsg, python-rosnode, python-rosparam, python-rosservice, python-rostopic, python-message-filters, python-roswtf, rosout, topic-tools
Recommends: rosbash
Size: 2380
SHA256: e256a50ff7da3fb0c7ba72b73d2caeb5a26106fd5da2e73668f49525c08729b1
SHA1: 894bb519f4775444c2282053a13ce3ec2e5737e5
MD5sum: e7e6afb83388f46e2f52cf06672bacd3
Description: Robot OS core metapackage
 This package is part of Robot OS (ROS). It is a metapackage
 providing all the ROS core system.
 .
 Different to upstream, this packages does not provide geneus and
 rosbag_migration_rule.
 Please install them from source, if you need them.
Description-md5: 4b79f51f56b69a7611fb956936b6da3c
Section: metapackages
Priority: extra
Filename: pool/main/r/ros-metapackages/ros-core_1.7_all.deb

インストール

”desktop-full-dev”というパッケージで、一通り必要な機能が入ります。
こちらを参考にしています。
ROS講座02 インストール - Qiita

pi@raspi3:~ $ sudo apt-get install ros-desktop-full-dev
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following additional packages will be installed:
  autoconf automake autopoint autotools-dev bzip2-doc bzr catkin cl-actionlib cl-actionlib-msgs cl-bond
...
  x11proto-scrnsaver-dev x11proto-xext-dev x11proto-xf86vidmode-dev x11proto-xinerama-dev xorg-sgml-doctools
  xtrans-dev
0 upgraded, 863 newly installed, 0 to remove and 1 not upgraded.
Need to get 323 MB of archives.
After this operation, 1520 MB of additional disk space will be used.
Do you want to continue? [Y/n] y
...

インストール前後のディスク使用量

インストール前
pi@raspi3:~ $ df -h
Filesystem      Size  Used Avail Use% Mounted on
/dev/root        15G  9.9G  4.0G  72% /
インストール後
pi@raspi3:~ $ df -h
Filesystem      Size  Used Avail Use% Mounted on
/dev/root        15G   12G  2.2G  85% /

ROSの初期化

pi@raspi3:~ $ sudo rosdep init
Wrote /etc/ros/rosdep/sources.list.d/20-default.list
Recommended: please run

        rosdep update

pi@raspi3:~ $ rosdep update
reading in sources list data from /etc/ros/rosdep/sources.list.d
Hit https://raw.githubusercontent.com/ros/rosdistro/master/rosdep/osx-homebrew.yaml
Hit https://raw.githubusercontent.com/ros/rosdistro/master/rosdep/base.yaml
Hit https://raw.githubusercontent.com/ros/rosdistro/master/rosdep/python.yaml
Hit https://raw.githubusercontent.com/ros/rosdistro/master/rosdep/ruby.yaml
Hit https://raw.githubusercontent.com/ros/rosdistro/master/releases/fuerte.yaml
Query rosdistro index https://raw.githubusercontent.com/ros/rosdistro/master/index.yaml
Add distro "ardent"
Add distro "bouncy"
Add distro "crystal"
Add distro "groovy"
Add distro "hydro"
Add distro "indigo"
Add distro "jade"
Add distro "kinetic"
Add distro "lunar"
Add distro "melodic"
updated cache in /home/pi/.ros/rosdep/sources.cache

catkinの準備

pi@raspi3:~ $ mkdir -p ~/catkin_ws/src
pi@raspi3:~ $ cd ~/catkin_ws/src
pi@raspi3:~/catkin_ws/src $ catkin_init_workspace
Creating symlink "/home/pi/catkin_ws/src/CMakeLists.txt" pointing to "/usr/share/catkin/cmake/toplevel.cmake"
pi@raspi3:~/catkin_ws/src $ ls -la
total 8
drwxr-xr-x 2 pi pi 4096 Feb  6 17:34 .
drwxr-xr-x 3 pi pi 4096 Feb  6 17:34 ..
lrwxrwxrwx 1 pi pi   38 Feb  6 17:34 CMakeLists.txt -> /usr/share/catkin/cmake/toplevel.cmake
pi@raspi3:~/catkin_ws/src $ cd ~/catkin_ws
pi@raspi3:~/catkin_ws $ catkin_make
Base path: /home/pi/catkin_ws
Source space: /home/pi/catkin_ws/src
Build space: /home/pi/catkin_ws/build
Devel space: /home/pi/catkin_ws/devel
Install space: /home/pi/catkin_ws/install
####
#### Running command: "cmake /home/pi/catkin_ws/src -DCATKIN_DEVEL_PREFIX=/home/pi/catkin_ws/devel -DCMAKE_INSTALL_PREFIX=/home/pi/catkin_ws/install -G Unix Makefiles" in "/home/pi/catkin_ws/build"
####
-- The C compiler identification is GNU 6.3.0
-- The CXX compiler identification is GNU 6.3.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Using CATKIN_DEVEL_PREFIX: /home/pi/catkin_ws/devel
-- Using CMAKE_PREFIX_PATH:
-- Found PythonInterp: /usr/bin/python (found version "2.7.13")
-- Using PYTHON_EXECUTABLE: /usr/bin/python
-- Using Debian Python package layout
-- Using empy: /usr/bin/empy
-- Using CATKIN_ENABLE_TESTING: ON
-- Call enable_testing()
-- Using CATKIN_TEST_RESULTS_DIR: /home/pi/catkin_ws/build/test_results
-- Found gtest sources under '/usr/src/gtest': gtests will be built
-- nosetests not found, Python tests can not be run (try installing package 'python-nose')
-- catkin 0.7.4
-- BUILD_SHARED_LIBS is on
-- Configuring done
-- Generating done
-- Build files have been written to: /home/pi/catkin_ws/build
####
#### Running command: "make -j4 -l4" in "/home/pi/catkin_ws/build"
####

ROSのサンプルプログラムを試してみる

こちらを参考にします。
ROS講座03 Pub &amp; Sub 通信 - Qiita

コンパイルまで終わらせます。

pi@raspi3:~/catkin_ws $ catkin_make
Base path: /home/pi/catkin_ws
Source space: /home/pi/catkin_ws/src
Build space: /home/pi/catkin_ws/build
Devel space: /home/pi/catkin_ws/devel
Install space: /home/pi/catkin_ws/install
####
#### Running command: "make cmake_check_build_system" in "/home/pi/catkin_ws/build"
####
####
#### Running command: "make -j4 -l4" in "/home/pi/catkin_ws/build"
####
[100%] Built target basic_simple_talker
[100%] Built target basic_simple_listener

ターミナル1つ目:roscoreを動かします

pi@raspi3:~/catkin_ws $ source ~/catkin_ws/devel/setup.bash
pi@raspi3:~/catkin_ws $ roscore
... logging to /home/pi/.ros/log/2ab1e868-29f0-11e9-8b33-b827ebaf3240/roslaunch-raspi3-1072.log
Checking log directory for disk usage. This may take awhile.
Press Ctrl-C to interrupt
Done checking log file disk usage. Usage is <1GB.

started roslaunch server http://raspi3:41255/
ros_comm version 1.12.6


SUMMARY
========

PARAMETERS
 * /rosdistro: kinetic
 * /rosversion: 1.12.6

NODES

auto-starting new master
process[master]: started with pid [1082]
ROS_MASTER_URI=http://raspi3:11311/

setting /run_id to 2ab1e868-29f0-11e9-8b33-b827ebaf3240
process[rosout-1]: started with pid [1095]
started core service [/rosout]

ターミナル2つ目:talkerを動かします

pi@raspi3:~/catkin_ws $ source ~/catkin_ws/devel/setup.bash
pi@raspi3:~ $ rosrun basic_lecture basic_simple_talker
[ INFO] [1549445114.110764374]: hello world!
[ INFO] [1549445114.210512172]: hello world!
...

ターミナル3つ目:listenerを動かします

pi@raspi3:~/catkin_ws $ source ~/catkin_ws/devel/setup.bash
pi@raspi3:~ $ rosrun basic_lecture basic_simple_listener
[ INFO] [1549445114.412048604]: I heard: [hello world!]
[ INFO] [1549445114.511398797]: I heard: [hello world!]
...

talkerの方のターミナルで、プログラムを止めるとメッセージが止まり、プログラムを動かすとメッセージが流れます。
ターミナルを開くたびに、毎回

source ~/catkin_ws/devel/setup.bash

を入力していますが、教科書の通り、.bashrcに追記した方が良いですね。

(覚え)roscoreを動かし忘れたとき

このようなエラーメッセージが出ます。

ターミナル2つ目:talker
pi@raspi3:~ $ rosrun basic_lecture basic_simple_talker
[ERROR] [1549445150.003231955]: [registerPublisher] Failed to contact master at [localhost:11311].  Retrying...
^Cpi@raspi3:~ $
ターミナル3つ目:listener
pi@raspi3:~ $ rosrun basic_lecture basic_simple_listener
[ERROR] [1549445154.933464174]: [registerPublisher] Failed to contact master at [localhost:11311].  Retrying...
^Cpi@raspi3:~ $