山pの楽しいお勉強生活

勉強の成果を垂れ流していきます

fstringの中でdictionary、setの内包表記を使用する

結論

l = ['a', 'b', 'c']
s1 = f'{ {s:s for s in l} }'  # 中括弧の後にスペースが必要
assert s1 == "{'a': 'a', 'b': 'b', 'c': 'c'}"

s2 = f'{ {s for s in l} }'  # 中括弧の後にスペースが必要
assert s2 == "{'b', 'c', 'a'}"

※setの方は順番は保証されないので↑のassertは失敗する場合がある

詳細とか

fstring内でdictionaryやsetの内包表記を普通に記載すると内包表記の記載がそのまま文字列となる

l = ['a', 'b', 'c']
s3 = f'{{s:s for s in l}}'
assert s3 == "{s:s for s in l}"

s4 = f'{{s for s in l}}'
assert s4 == "{s for s in l}"

これは中括弧は中括弧でエスケープできるという仕様のため。pep-0489で定義されている。

www.python.org

で、どうすれば良いかというとスペースを入れることでエスケープを回避する。こちらについでも同じドキュメント内に記載がある。

www.python.org

Pythonのユニットテストでimportされている変数を上書きする

結論

  • 直接モジュールの変数を上書きすれば良い
  • ただし、importされた時点でそのモジュールの変数として扱われる事に注意

※文字で見ても良くわからないと思うので下記のコードを参照

ケース1(テスト対象に直接変数がimportされている場合)

テスト対象のコード群

# a.py
from define import HOGE
class TargetClass:
    def get_hoge(self):
        return f"aaa_{HOGE}_bbb" # ここのHOGEを入れ替えたい
# define.py
HOGE = 'hoge'

ユニットテスト

import a
from a import TargetClass

def test_hoge():
    a.HOGE = 'piyo' # モジュールをインポートしてモジュールの変数を直接入れ替える
    target_class = TargetClass()
    assert target_class.get_hoge() == 'aaa_piyo_bbb'

ケース2(テスト対象で使用されている別モジュールで直接変数がimportされている場合)

テスト対象のコード群

# a.py
from b import get_hoge
class TargetClass:
    def get_hoge2(self):
        return f"aaa_{get_hoge()}_bbb"
# b.py
from define import HOGE
def get_hoge():
    return HOGE # ここのHOGEを入れ替えたい
# define.py
HOGE = 'hoge'

ユニットテスト

import b
from a import TargetClass

def test_hoge2():
    b.HOGE = 'piyo' # モジュールをインポートしてモジュールの変数を直接入れ替える
    target_class = TargetClass()
    assert target_class.get_hoge2() == 'aaa_piyo_bbb'

※結局やっているのはケース1と同じで直接bをインポートして値を入れ替える

経緯とか

  • ↑に書いた通りのことをやりたかったが調べ方もわからずハマった
  • unittest.patch だと、Mockになってしまうので、違うそうじゃない感。

蛇足

  • ケース2のようにできるのであれば、定義の方を変更できそうに見えるが通常はうまくいかない
  • 下記のユニットテスト2のように、入れ替えたいモジュール(今回であれば b )が呼び出される前であればうまくいくが、一度呼び出すとモジュール内に直接定義されるようで、想定通りにならない

テスト対象コード(ケース2と同じ)

# a.py
from b import get_hoge
class TargetClass:
    def get_hoge2(self):
        return f"aaa_{get_hoge()}_bbb"
# b.py
from define import HOGE
def get_hoge():
    return HOGE # ここのHOGEを入れ替えたい
# define.py
HOGE = 'hoge'

ユニットテスト1(うまくいかないケース)

from a import TargetClass
import define

def test_hoge():
    define.HOGE = 'piyo' # 元々定義されている値を入れ替える
    target_class = TargetClass()
    assert target_class.get_hoge2() == 'aaa_piyo_bbb' # AssertionError

テストケースの from a import TargetClass ここで a.py が読まれて、from b import get_hoge が読まれて、b.pyfrom define import HOGE まで読まれる。 これにより、b内にHOGEが定義されてしまう。 これにより、テストケース内で define.HOGE を置き換えても、b.HOGE は既に定義されているため値が変更されない。

ユニットテスト2(うまくいくがイマイチなケース)

import define
define.HOGE = 'piyo' # テストモジュールの先頭でimportした直後に値を変更する
from a import TargetClass

def test_hoge():
    target_class = TargetClass()
    assert target_class.get_hoge2() == 'aaa_piyo_bbb'

うまく動作するには動作するが、linterに指摘されますし、実際に動かすときには1ファイルのテストだけではないと思われるので、先に実行される他のテストでbがimportされていたら結局同じ事が発生すると思われる。

GitHub ActionsでLOCALEがja_JP.UTF-8のPostgreSQLを使用する方法

結論

  • サービスコンテナでLOCALEに ja_JP.UTF-8 を設定することはできない
  • 自力でLOCALEを追加するイメージを作って、docker run で起動する

Dockerfile

FROM postgres:11.5
RUN localedef -i ja_JP -c -f UTF-8 -A /usr/share/locale/locale.alias ja_JP.UTF-8

GitHub Actionsのワークフロー設定

  • 正しい呼び名がわからず
name: postgresql

on: [push]

jobs:
  postgresql:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - name: PostgreSQL container build & run
        run: |
          docker build -t postgresql_i .github/workflows
          docker run -d --name postgresql_t -p 5432:5432 -e POSTGRES_PASSWORD=postgres -e LC_ALL=ja_JP.UTF-8 postgresql_i
      - name: wait for db
        run: until docker exec postgresql_t pg_isready -U postgres; do sleep 1; done
      - name: show locale
        run: docker exec postgresql_t psql -U postgres -c "SHOW LC_COLLATE;"

ファイル構成

└ .github
    └ workflows
        ├ Dockerfile
        └postgresql.yml
  • Dockerfileはどこに置くのが良いのかわからず
    • .github/actions みたいなフォルダ作ってそこに置くのが良い?

出力

Run docker exec postgresql_t psql -U postgres -c "SHOW LC_COLLATE;"
 lc_collate  
-------------
 ja_JP.UTF-8
(1 行)

詳細

  • PostgreSQLはデフォルトのLOCALE( en_US.utf8 )だと日本語のソートが想定外の動きをする場合がある
  • Linuxでは設定したいLOCALEである ja_JP.UTF-8 はインストールする必要がある
  • GitHub ActionsでPostgreSQLを使用する場合、サービスコンテナを使用するのが定石な様子
  • サービスコンテナ内で起動前にコマンド実行ができないようなので、LOCALEのインストールができない
  • 自前でimageを作る必要がある
    • ↑の例ではDockerfileをリポジトリ内に置いてbuildしているが、DockerHubなり、GitHub Container Registryなりに置いてそれを使っても良い

参考

PostgreSQLのデフォルトLOCALEでは日本語文字列のソート結果が想定と異なる

概要

  • PostgreSQLをデフォルトのまま使用すると日本語文字列のソート結果が想定と異なる
  • LOCALEを正しく設定することで修正可能
  • 文字列の並び順は LC_COLLATE で制御されるこの設定がデフォルトだと en_US.utf8 となっていることが原因

動作確認環境

対応方法

FROM postgres:11.5
RUN localedef -i ja_JP -c -f UTF-8 -A /usr/share/locale/locale.alias ja_JP.UTF-8
ENV TZ=Asia/Tokyo
ENV LANG=ja_JP.UTF-8
ENV LANGUAGE=ja_JP:ja
ENV LC_ALL=ja_JP.UTF-8

詳細及び再現手順

再現

起動

docker run -d --name postgres_1 postgres:11.5
docker exec -it postgres_1 psql -U postgres

SQL

create table hoge ( id int, value varchar(10));
insert into hoge values
(1, ''),
(2, 'あ(ほげ)'),
(3, ''),
(4, 'い(ふが)')
;
select * from hoge order by value;

結果

postgres=# select * from hoge order by value;
 id |   value    
----+------------
  1 | あ
  3 | い
  2 | あ(ほげ)
  4 | い(ふが)
(4 rows)

LOCALEの確認

postgres=# SHOW LC_COLLATE;
 lc_collate 
------------
 en_US.utf8
(1 row)

対応

Dockerfile

FROM postgres:11.5
RUN localedef -i ja_JP -c -f UTF-8 -A /usr/share/locale/locale.alias ja_JP.UTF-8
ENV TZ=Asia/Tokyo
ENV LANG=ja_JP.UTF-8
ENV LANGUAGE=ja_JP:ja
ENV LC_ALL=ja_JP.UTF-8

起動

docker build . -t yamap55/postgres:11.5_jajp
docker run -d --name postgres_2 yamap55/postgres:11.5_jajp
docker exec -it postgres_2 psql -U postgres

SQL

create table hoge ( id int, value varchar(10));
insert into hoge values
(1, ''),
(2, 'あ(ほげ)'),
(3, ''),
(4, 'い(ふが)')
;
select * from hoge order by value;

結果

postgres=# select * from hoge order by value;
 id |   value    
----+------------
  1 | あ
  2 | あ(ほげ)
  3 | い
  4 | い(ふが)
(4 行)

LOCALEの確認

postgres=# SHOW LC_COLLATE;
 lc_collate  
-------------
 ja_JP.UTF-8
(1 行)

参考

背景とか蛇足とか

MySQLでも試した

起動、接続

docker run --name mysql_1 -e MYSQL_ROOT_PASSWORD=mysql -d mysql
docker exec -it mysql_1 mysql -u root -p -h 127.0.0.1 -D mysql -pmysql

結果

mysql> create table hoge ( id int, value varchar(10));
Query OK, 0 rows affected (0.04 sec)

mysql> insert into hoge values
    -> (1, ''),
    -> (2, ''),
    -> (3, ''),
    -> (4, '')
    -> ;
Query OK, 4 rows affected (0.01 sec)
Records: 4  Duplicates: 0  Warnings: 0

mysql> select * from hoge;
+------+-------+
| id   | value |
+------+-------+
|    1 |       |
|    2 |       |
|    3 |       |
|    4 |       |
+------+-------+
4 rows in set (0.00 sec)

mysql> 

AtCoder用Python環境を作った

概要

最近AtCoderを始めたのでPython用の環境を作りました。 割といい感じにできた気がしましたのでTemplate Repositoryにしています。これから始める方、AtCoder上で書いている方などは是非試してみてください。

一方、まだ私自身が使い込んでいないので、既に環境ある方やAtCoderをある程度やり込んでいる方には不満があるかもしれません。 何かありましたら IssueTwitter などでご連絡頂けたら助かります。

github.com

導入ツール

  • devcontainer
    • VSCode, Git, DockerさえあればOK
  • black
    • 自動フォーマット
  • online-judge-tools
    • VSCode上でテストを実行
  • atcoder-cli
  • atcoder-python-snippets
    • AtCoder用のスニペット
    • あまり洗練されていないので、独自の関数をテンプレートファイルに記載しています
    • 独自のスニペットを追加したい場合には本記事末尾のQAを参照

環境作成(ローカルのVSCodeの場合)

※この文章でわからなければ README を参照してください。

環境作成(GitHub Codespacesの場合)

f:id:yamap_55:20210116171613p:plain
Open with Codespaces
f:id:yamap_55:20210116171759p:plain
New codespaces

※特にCodespaces用の設定はしていないので不具合があったら教えてください

回答までの流れ

VSCode内のターミナルでコマンドを実行します

  1. ログイン
    • acc login
    • oj login https://atcoder.jp/
  2. contestID を取得
    • https://atcoder.jp/contests/abs の場合、 abs
  3. ディレクトリ作成(問題を選択)
    • acc new ${contestID}
    • 例: acc new abs
  4. 回答する問題のディレクトリに移動
    • cd {contestID}/{問題}
  5. 回答を作成
    • main.py に回答を記載
  6. 回答をテスト
    • ojt
    • oj t -c "python main.py" と同じ
  7. 回答を提出
    • acc submit
    • acc s と同じ

使用例

acc new abs
cd abs/practicea/
vi main.py
ojt
acc s

QA

テンプレートファイルを変更したい

templates/py/main.py を変更してください

独自のスニペットを追加したい

  • .vscode/python.code-snippets を作成し、以下のように記載する
{
  "input number": {
    "prefix": ["input-n"],
    "body": ["import sys\nn = int(sys.stdin.buffer.readline())"],
    "description": "input number."
  }
}

Django REST Framework 条件に応じてAPI処理を切り替える方法

全然サンプル見つからなかったので誰かに役に立つかも?と、妥協点はあるもののとりあえず実装としては良さそうなのでメモ

やりたかったこと

  • 条件によって特定のAPI処理全体を切り替えたい
    • 複数発生した場合を考えると if hogeflag: みたいな事はやりたくない
  • この条件というのがログインユーザ毎、特定のデータの場合という事ではなく、環境変数や設定ファイルなど動作する環境毎に切り替えたい。
  • 切り替わったら、その環境では選択されなかった処理は一切使用される事はない

具体的な例とか

  • アプリケーションがパッケージ販売されていて、特定の環境では処理を変更したい
  • 拡張機能などがあり、特定の処理を任意で上書きたい

対応方法

概要

DjangoのMiddlewareを使用する。

Middlewareとは、実際の処理の前後に行わせることができる処理です。hookとか言ったりします。
settings.pyMIDDLEWARE = [] と配列として記載する事で設定しますので、実際のアプリケーションで使われている事が確認できるかと思います。認証処理などもここで行っています。

詳細

# extensions.test_middleware
from django.http import JsonResponse
from rest_framework.request import Request

from extensions.hoge import HogeView

class SimpleMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        response = self.get_response(request)
        return response

    def process_view(self, request, view_func, view_args, view_kwargs):
        # if view_func.__name__ == 'HogeView': # Classで比較する場合
        if request.path == '/api/v1/hogehoge/': # URLPATHで比較する場合
            # DjangoのRequestとDRFのRequestが異なるため変換
            # django.core.handlers.wsgi.WSGIRequest -> rest_framework.request.Request
            req = Request(request)
            res = HogeView.get(HogeView, req)

            # process_viewではdjango.http.Responseを返す必要があり、
            # rest_framework.response.Responseをそのまま返す事ができないため、値を取得して変換している
            return JsonResponse(res.data, status=res.status_code)
        else:
            # Noneを返す事で既存の処理が行われる
            return None
# extensions.hoge.HogeView
from rest_framework.response import Response
from rest_framework.views import APIView
class HogeView(APIView):
    def get(self, request):
        return Response({'aaa': 'bbb'})
# settings.py

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'extensions.test_middleware.SimpleMiddleware'
]

コードの実物に近い形

直接クラス名とか書いていたら、各処理にifと書くのと何にも変わらない。 ので、設定系は全部DBに突っ込んで、DBの内容と合致したら設定に従ってリフレクションで処理を呼ぶようにした。

class SimpleMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        return self.get_response(request)

    def process_view(self, request, view_func, view_args, view_kwargs):
        extension = Extension.objects.filter(class_name=view_func.__name__).first()
        if extension:
            _cls = getattr(importlib.import_module(extension.module_name), extension.class_name)
            method = getattr(_cls, request.method.lower())
            return JsonResponse(method(_cls, Request(request)).data, status=res.status_code)

没とした案

urls.pyで対応

実装して動作するところまでは確認

詳細

urlpatterns は先勝ち(ドキュメントは調べてない!)なので、既存処理の設定をする前に独自処理のパターンをどこからか読み込んで設定すれば既存処理を上書きする事ができる。

没とした理由

ユニットテストが大変。

実際にはDBに設定が入っている事を想定していたため、urls.py のurlpatternsの設定する所でDBアクセスする必要がある。

  1. エラー処理の対応が必要
    • url.pyはDjangoの基本機能らしく、 python manage.py migration などでも処理が行われるので、migration前にテーブルがあるわけないのでエラー(ProgramingError)となる。
    • exceptして対応する事も可能は可能。(1度は実装した)
  2. ユニットテストでエラーとなる
    • django.test.TestCaserest_framework.test.APITestCase などのフレームワーク提供のTestCaseを使用する場合に@DB等のDBを使用する旨のデコレータをつけろとエラーになる。
    • これは各テストケース内ではなく、↑のTestCaseを利用する事でDjangoの初期化処理が走るため、url.pyも同様に処理され発生する。
    • 回避したとしたとしても、Djangoの初期処理はテスト全体で一回なので、通常処理の場合と今回の対応を行った場合の2パターンを処理する事ができない。
    • あえてやろうとすると以下の感じになる?(机上の空論)
      • urls.py内でテストかどうかを確認してテストだったらDBにアクセスしない
      • 今回の対応を行う場合のユニットテストsetUpClassDjangoを再起動する

参考

自宅Raspberry Pi再構築メモ

自宅のRaspberry Piを再構築したのでメモです。既存のRaspberry Piスクリプト関連はGitHubにあったものの、環境関連の情報が何も残っていなかったので新規に記事に起こしています。(文章にした記憶はあるものの見つからず)

完全に自分用なので、本来ならば別の記事に分けたほうが良いものも多数あり、読みにくいと思いますがご了承ください。 また、そもそもGUIいらなかったのではないかとか、先にSSH設定して全部母艦からやればよかったのではないかとか、色々ありますがその辺りは次回構築時に改善していく予定、(いつ?)
GUIについては、以前CUIWifi設定に手こずったのが、一瞬でできたのでそれだけでも入っていてよかったと思う。)

※随時更新予定(最終更新 : 2020/06/16)

環境

$ cat /etc/debian_version 
10.4
$ cat /etc/issue
Raspbian GNU/Linux 10 \n \l
$ lsb_release  -a
No LSB modules are available.
Distributor ID: Raspbian
Description:    Raspbian GNU/Linux 10 (buster)
Release:    10
Codename:   buster
$ uname -a
Linux raspberrypi 4.19.97-v7+ #1294 SMP Thu Jan 30 13:15:58 GMT 2020 armv7l GNU/Linux

基本設定

起動まで

ユーザ関連

  • ユーザの整理
    • rootのパスワード変更
      • sudo passwd root
    • mainで操作するユーザ追加
      • sudo adduser ${username}
    • 追加したユーザにpiユーザと同じグループを紐付ける
      • groups pi
        • 出力 : pi : pi adm dialout cdrom sudo audio video plugdev games users input netdev spi i2c gpio
      • sudo usermod -G pi,adm,dialout,cdrom,sudo,audio,video,plugdev,games,users,input,netdev,spi,i2c,gpio ${username}

SSH関連

  • 別のマシンからSSH接続
    • 左上のアイコン → 設定 → Raspberry Pi の設定 → インターフェイス
    • SSHを有効
    • ついでにカメラも有効
    • 再起動
    • ifconfig でIPを確認
    • 別のマシンから ssh ${username}@192.168.xxx.xxx で接続
  • SSHの鍵認証設定
    • 鍵作成(母艦)
      • ssh-keygen -t rsa
    • scpでRaspberry Piに公開鍵を送る
      • scp ~/.ssh/raspberry_rsa.pub ${username}@192.168.xxx.xxx:~
    • 公開鍵を設定(Raspberry Pi
      • mkdir ~/.ssh
      • chmod 700 ~/.ssh
      • cat ~/raspberry_rsa.pub >> .ssh/authorized_keys
      • chmod 600 .ssh/authorized_keys
      • rm ./raspberry_rsa.pub
  • SSHのセキュリティとか(Raspberry Pi
    • 設定ファイル開く
      • sudo vi /etc/ssh/sshd_config
    • ポート番号変更
      • Port 60522
    • 鍵認証の有効化
      • PubkeyAuthentication yes
    • パスワード認証無効化
      • PasswordAuthentication no
      • 鍵認証が正しく設定されているか確認してからの方が良い
    • rootログインの禁止も各種サイトには書かれていたが、今のバージョンではデフォルト無効になっている?
      • 不安だったので PermitRootLogin yes としてrootでログインできてしまうことを確認した上で、下の設定を追加
      • PermitRootLogin no
    • sshデーモンを再起動
      • sudo /etc/init.d/ssh restart
    • 空パスワードを無効
      • PermitEmptyPasswords no
  • 公開鍵でアクセス(母艦)
    • 試行
      • ssh -i ~/.ssh/raspberry_rsa -p 60522 ${username}@192.168.xxx.xxx
    • configに設定追加
      • vi ~/.ssh/config
      • 内容は下記参照
    • 試行2
      • ssh raspi
  • SSHの設定確認(母艦)
    • パスワードで接続できないことを確認
      • ssh -p 60522 ${username}@192.168.xxx.xxx
Host raspi
    HostName 192.168.xxx.xxx
    User ${username}
    Port 60522
    IdentityFile ~/.ssh/raspberry_rsa

参考

ホスト名関連

  • defaultは raspberrypi なのでわかりやすく変更しておく
  • 設定変更
    • sudo vi /etc/hostname
    • sudo vi /etc/hosts
  • 再起動
    • sudo reboot
  • 確認
    • hostname
  • SSHの設定もIPだと変更される可能性があるのでホスト名でアクセスできるように変更しておく
    • 試行
      • ssh -i ~/.ssh/raspberry_rsa -p 60522 ${username}@${hostname}.local
    • configに設定追加
      • vi ~/.ssh/config
      • 内容は下記参照
Host raspi
    HostName ${hostname}
    User ${username}
    Port 60522
    IdentityFile ~/.ssh/raspberry_rsa

参考

ディスプレイ装着

手順

  • GPIOピンに差し込む
    • 一番目立つピンに多分そうだろうと思う感じで挿せば動いた
  • 以下の手順でドライバをインストール
    • sshで接続しているとインストール後にログアウトするので注意
git clone https://github.com/waveshare/LCD-show.git
cd LCD-show/
chmod +x LCD35-show
./LCD35-show

詳細

喋らせる

  • open-jtalkをインストール
sudo apt-get update
sudo apt-get install open-jtalk open-jtalk-mecab-naist-jdic hts-voice-nitech-jp-atr503-m001

参考

ローカルのVSCodeRaspberry Piの上コードを編集する

拡張機能インストール

接続

  • 左にあるアイコンが並んでいる部分から PCに<> となってるアイコンクリック
  • SSH Targets -> raspi を選択
    • しばらくしたら別WindowでVSCodeが起動する
    • TerminalタブでRaspberry Piに接続されているか確認
  • 左にあるアイコンが並んでいる部分の一番上エクスプローラクリック
    • OPEN FOLDER から指定のフォルダを開く

参考

USBカメラで写真を撮る

  • apt-get update
    • sudo apt-get update
  • 静止画取得用モジュールインストール
    • sudo apt-get install v4l-utils fswebcam
  • カメラの接続確認
  • カメラで写真撮る
    • fswebcam -r 640x480 ../raspberrypi-home/hoge2.jpg
    • -r で解像度

Python3 環境

  • Python3 のバージョン確認
    • python3 --version
    • Python 3.7.3
  • 仮想環境作成
    • python3 -m venv .venv
  • pipのバージョンアップ
    • pip install --upgrade pip
  • 必要ライブラリインストール
    • pip install -r requirements.txt

Vimの設定

  • デフォルトのVimは使いにくいので変更
  • 確認
    • dpkg -l | grep vi
  • アンインストール
    • sudo apt-get --purge remove vim-common vim-tiny
  • Vimインストール
    • sudo apt-get install vim
  • Gitのエディタを変更
    • git config --global core.editor 'vim -c "set fenc=utf-8"'
  • システム?のデフォルト?のエディタを変更
    • sudo update-alternatives --config editor

参考

BluetoothリモートシャッターとRaspberry Piのカメラを連携

  • bluetooth用のライブラリインストール
    • sudo apt-get install bluetooth pi-bluetooth
  • Bluetoothリモートシャッター用のライブラリをインストール
  • 現在のユーザをbluetoothグループに追加
    • デフォルトだとbluetoothグループに入ってないとbluetoothは使用できない用に設定されている
    • sudo usermod -a -G bluetooth ${username}
  • bluetoothctlでBluetoothリモートシャッターの認識とペアリング
    • 対話式なので注意
$ bluetoothctl
Agent registered
[bluetooth]# power on
Changing power on succeeded
[bluetooth]# scan on
Discovery started
[NEW] Device XX:XX:XX:XX:XX:XX AB Shutter3       
[bluetooth]# pair XX:XX:XX:XX:XX:XX
[AB Shutter3       ]# trust XX:XX:XX:XX:XX:XX
[CHG] Device XX:XX:XX:XX:XX:XX Trusted: yes
  • 設定ファイル作成
    • vi ./bluebutton.conf
keyup=echo UP
keydown=echo DOWN
longup=echo LONG UP
longdown=echo LONG DOWN
  • 試行
    • sudo bluebutton -d="AB Shutter3" -c "/home/yamap55/raspberrypi-home/bluebutton.conf"
    • リモートシャッターのボタン押してメッセージが表示されればOK
    • 接続が切れていたからか、反応するまで少し時間がかかることがあったので注意
  • 処理を修正
    • keyup=/home/yamap55/raspberrypi-home/script/takePhoto.sh >> /home/yamap55/raspberrypi-home/logs/takePhoto.log 2>&1
  • デーモン起動
    • sudo bluebutton -d="AB Shutter3" -c "/home/yamap55/raspberrypi-home/bluebutton.conf" &
  • OS起動時に常駐するように設定
    • vi /etc/rc.local
    • exit 0 の前辺りに追加
      • sudo bluebutton -d="AB Shutter3" -c "/home/yamap55/raspberrypi-home/bluebutton.conf" &

参考