手動でも回せるオートロック（セットアップ編）

ここまででハードの設計とオートロックのプログラムの作成を行ってきました。

前回までの記事はこちらから参照してください。

https://qiita.com/takuteh/items/67b4089ee78e66b868dc

最後は作ったプログラムをどのラズパイでもすぐに動かせるように、セットアップと自動起動などを行えるようにしていきます。

目次
[1.プログラムをOS起動時に自動実行させる](#1)
[2.プログラムをmakeでコンパイルする](#2)
[3.各種設定を実行するスクリプトの作成をする](#3)

こちらに今回作成したプログラム等があります。

https://github.com/takuteh/autolock

# 1.プログラムをラズパイ起動時にsystemdで自動実行させる

systemdとは現在ほとんどのLinuxで採用されているプロセス管理の方法です。
Unitファイルは以下のように設定します。
```autolock.service
[Unit]
Description=autolock
After=pigpiod.service

[Service]
Type=simple
User=root
Group=root
WorkingDirectory=/home/pi/autolock/gear_version
ExecStart=/home/pi/autolock/gear_version/autolock
ExecStop=/bin/kill -WINCH ${MAINPID}
Restart=on-failure
RestartSec=5s

[Install]
WantedBy=multi-user.target
```
このファイルを作成したらsystemdに登録する必要があります。まずは、このファイルを`/etc/systemd/system`にコピー、その後systemdにファイルを読み込ませます。最後に自動起動にするため、serviceをenableに設定します。
```
cp autolock.service /etc/systemd/system
sudo systemctl daemon-reload
sudo systemctl enable autolock.service
```

# 2\. プログラムをmakeコマンドでコンパイルする
元の記事に載せているプログラムは一つにまとめているのでライブラリのリンクだけでいいですが、実際私が運用しているコードはもう少し長いのでコードを分割しています。そのため、コンパイル時にリンクを複数しないといけないのでコマンドが長くなってしまい、打つのが大変です。そのため、Makefileを作成しmakeコマンドだけでコンパイルできるようにしましょう。
```
g++ -o autolock autolock.cpp control_servo.cpp min_mqtt.cpp -lpigpiod_if2 -lmosquitto -Ijson/include
```
gear_version/srcにMakefileを作成します。
```Makefile:Makefile
# Compiler
CXX = g++

# Compiler flags
CXXFLAGS = -Ijson/include

# Libraries
LIBS = -lpigpiod_if2 -lmosquitto

# Output executable
TARGET = autolock

# Source files
SRC = autolock.cpp control_servo.cpp min_mqtt.cpp

# Object files
OBJ = $(SRC:.cpp=.o)
TARDIR= ..

# Default target
all: $(TARGET)

# Compile source files to object files
%.o: %.cpp
	$(CXX) $(CXXFLAGS) -c $< -o $@

# Link object files to create the executable
$(TARGET): $(OBJ)
	$(CXX) -o $(TARDIR)/$(TARGET) $(OBJ) $(LIBS)

# Clean up build artifacts
clean:
	rm -f $(TARGET) $(OBJ)

# Phony targets
.PHONY: all clean
```
これでsrc内で`make`とすれば、gear_version以下にautolockの実行ファイルができます。

# 3\. 依存ライブラリや各種設定を実行するスクリプトの作成をする
依存ライブラリのインストール、各種設定（特にMQTT）、systemdへの登録や自動起動などやることが多いので、これも自動でやってくれるスクリプトを作成します。
```setup.sh
#!/bin/sh

ask_yes_no() {
    while true; do
        echo -n "$* [y/n]:"
        read ANS
        case $ANS in
        [Yy]*)
            return 0
            ;;
        [Nn]*)
            return 1
            ;;
        *)
            echo "Input y or n!"
            ;;
        esac
    done
}

WD=$(pwd)
#パッケージインストール
apt install pigpio mosquitto libmosquitto-dev

#mqtt設定
MQTT_CONFIG="/etc/mosquitto/mosquitto.conf"
if ! grep -q "listener" "$MQTT_CONFIG"; then
    echo "listener 1883" >> "$MQTT_CONFIG"
    MQTT_PORT=1883
else
#既にmqttのポートが設定されている場合そのポートを代入
    MQTT_PORT=$(grep "listener" "$MQTT_CONFIG"|awk '{print $2}')
fi

#外部からのアクセスを許可
if ! grep -q "allow_anonymous true" "$MQTT_CONFIG"; then
    echo "allow_anonymous true" >> "$MQTT_CONFIG"
fi

echo "Mqtt listener port is" $MQTT_PORT

#setting.jsonにMQTTのポートを設定
if ! grep -q "mqtt_port" autolock_setting.json; then
    echo "mqtt_port:$MQTT_PORT" >> autolock_setting.json
else 
    sed -i "s/\"mqtt_port\":[0-9]*/\"mqtt_port\":$MQTT_PORT/" autolock_setting.json
fi

#autolockコンパイル
cd src
make

#systemd登録
sed -i "s|^WorkingDirectory=.*|WorkingDirectory=$WD|" "service/autolock.service"
sed -i "s|^ExecStart=.*|ExecStart=$WD/autolock|" "service/autolock.service"
cp service/autolock.service /etc/systemd/system
systemctl daemon-reload 
systemctl enable autolock.service
systemctl enable pigpiod.service

if ask_yes_no "All tasks are completed. Do you want to reboot the system?"; then
    echo "Rebooting the system..."
    reboot
else
    echo "Aborting"
    exit 1
fi
```
コメントを見て貰えばなんとなくわかると思います。すでにmosquittoを設定していて別ポートを設定していても、そのポートをそのまま使用できるようにオートロックの設定(autolock_setting.json)を変更しています。
systemdの登録部分ですがgit cloneする場所やユーザー名によりautolockの場所が異なると思うので、書き換えるようにします。
これで、setup.shを実行すれば再起動したときにオートロックが動き出します。再起動せずに`pigpiod.service`と`autolock.service`をstartさせても動きます。