ホーム » コンピュータ » Raspberry-Pi

Raspberry-Pi」カテゴリーアーカイブ

システム

最近の投稿

アーカイブ

カテゴリー

CCS811空気品質センサーに温湿度補正の実行

CCS811を使った空気品質センサーを使っているけど、夜になると次第に異常な値になっていく。

原因はよく掴めないままだけど、CCS811の機能の中に温湿度で補正をかける処理がある。補正といってもちょっとした程度かと思っているけど、時間経過とともに大きく変化していることから、1時間おきに温湿度補正をかけるようにプログラムを追加してみた。

色々と処理を触ってみるけど、時間が経つと大きな値が取れる状態になってしまう。倍率みたいな設定項目あるのかな…

Kindle Fire HD

ママが、電子書籍で読む機会が増えた…ということで、Kindle Fire HD を購入した。早速セットアップ。自宅ネットワークに登録し、アカウントの設定やら Netflix アカウントの登録やらを終える。

Alexa

んで、Alexa も使えるし「Alexa, 今日の天気は?」を試してる。まあ、我が家はすでに Homebridge が動いていて「Hey Siri」、「OK Google」で、温湿度確認やらTVのON/OFFやら色々なことができる状態。でも、homebridge オタ状態なので「Alexa, テレビをつけて!」もやりたくなってくる。

homebridge-alexa

ググると、当然のように「Alexa経由で家の外からRaspberry Pi(Homebridge)に指示」というページが見つかる。このページに記載されているように、(1) homebridge-alexa をインストール、(2) 中継用のクラウドのアカウント作成、(3) Kindle 側に homebridge スキルのインストールを行う。

Switchbot Plug の制御

電気毛布が必要な時期、外出時の電源を切り忘れるのを防ぐために、昨年導入していた Switchbot Plug 。

スマホの SwitchBot アプリのタイマー機能で朝に強制オフの制御していたけど、寝る時にスイッチを入れるのは、自分が不在の時だとムダだし、homebridge や cron で制御するのも面白そう。

switchbot-utility のインストール

ということで、Raspberry-Pi に、switchbot-utility をインストール。

((( 事前にSwitchbot アプリは設定済み )))
$ sudo pip3 install switchbot-utility
$ cd /usr/local/lib/python3.9/dist-packages/switchbot_utility

制御するには、Switchbot アプリのトークンと秘密鍵が必要なので、アプリを起動して「プロフィール」、「設定」の画面を開いて、「アプリバージョン」の表示を 10 回連打すると、「開発者向けオプション」を表示できる。この画面を開いてトークンとクライアントシークレットをコピーし、上記の switchbot_utility のフォルダ内に、settings.json のファイル名で保存。

Python で以下のスクリプトを実行すると、switchbot-utility で扱えるデバイスの一覧 deviceList.txt が作られる。

((( settings.json )))
// Switchbot アプリで取得したトークンとシークレットを、
// switchbot_utilitiy のフォルダに settings.json で保存しておく
{
    "token": "xxxxx....",
    "secret": "yyyyy...."
}
((( devicelist.py )))
// Python で以下のスクリプトを実行すると、deviceList.txt が作られる。
// 以下を devicelist.py で保存し、python3 devicelist.py で実行!

from switchbot_utility.switchbot import Switchbot

switchbot = Switchbot()
switchbot.devicelist()

((( deviceList.txt )))
441793xxxxxx, 電気毛布, Plug, 000000000000
C5B496xxxxxx, エアコン, Bot, 000000000000

実際に、Switchbot Plug を動かすために、下記のscriptでスイッチを制御できるようにしてみた。

#!/usr/bin/python3
# -*- mode: python; coding: utf-8; tab-width: 4 ; -*-
# SwitchBot をON/OFFする
import sys
import time
import os

from switchbot_utility.switchbot_plug import SwitchbotPlug
#                      ~~~~~~~~~~~~~~        ~~~~~~~~~~~~~
# 制御するSwitchBot に合わせて、上記~~~ を書き換える。 
sb_dir = '/usr/local/lib/python3.9/dist-packages/switchbot_utility'

# Switch Bot Plug MAC ADDR
#   deviceList.txt 調べた MACアドレスを記入 
sb_plug_macaddr = '441793xxxxxx'

# コマンドライン引数プロセス名
script_file_name = sys.argv.pop( 0 )
# コマンドライン引数 -d <デバイスID>
while len( sys.argv ) >= 2 and sys.argv[0] == '-d' :
        sys.argv.pop( 0 )
        sb_plug_macaddr = sys.argv.pop( 0 )

# setting.jsonを読み込むため
os.chdir( sb_dir )

# SwitchBot Plug に接続
sb_plug = SwitchbotPlug( sb_plug_macaddr )
#         ~~~~~~~~~~~~~ この部分に制御対象用のコンストラクタを書けばいい

if len( sys.argv ) == 0 :
        # 引数なしは、状態を表示
        print( sb_plug.get_power() )
elif len( sys.argv ) == 1 :
        # status | on | off | toggle or turn
        arg = sys.argv.pop()
        if arg == 'status' :
                # exitでスイッチ状態を返す
                sys.exit( 0 if sb_plug.get_power() == 'on' else 1 )
        elif arg == 'on' :
                sb_plug.turn_on()       # ON
        elif arg  == 'off' :
                sb_plug.turn_off()      # OFF
        elif arg == 'toggle' or arg == 'turn' :
                # スイッチを反転
                pw = sb_plug.get_power()
                if pw == 'on' :
                        sb_plug.turn_off()
                elif pw == 'off' :
                        sb_plug.turn_on()

このプログラムを、homebridge-cmdswitch2 の設定に加える。

{
    "platform": "cmdSwitch2",
    "name": "cmdSwitch2",
    "switches": [
        {
            "name": "電気毛布",
            "on_cmd": "/usr/local/bin/switchbot-plug.py on",
            "off_cmd": "/usr/local/bin/switchbot-plug.py off",
            "state_cmd": "/usr/local/bin/switchbot-plug.py status"
        }
    ]
}

ということで、「OK Google, 電気毛布を点ける」でON、朝は起床時間にあわせたタイマーでOFF完成。

Raspberry Pi のUSB電源ケーブルを交換

MZ80C筐体の Raspberry-Pi に温湿度センサーBME280をつけてトイレに置いてあるけど、ボードを Raspberry-Pi 3 model A+に替えたら、電圧不足の記録が残ってて週に1度のペースでフリーズしてる。USBの電源アダプターも2A以上だせる物に替えても効果なし。ただ、USB電源ケーブルの長さが足りなくて、古いUSB延長ケーブルを挟んでいるんだけど、これが怪しいのかな。長い太目のUSB電源ケーブルに交換し、延長ケーブルを取り外す。効き目あるかな。

交換して半日たったけど “vcgencmd get_throttled” を見ても、電圧低下の警告が出ていない。効果ありかな。

(追記)2日間運用して、電圧低下の警告が1度も発生していない。これで安心

Rapberry-Pi の更新で GPIO が動かない

64bit OS の arm64 で動かしている Raspberry-Pi で、rpi-update を実行したら、kernel が Linux 6.1.61-v8+ となり、自作スクリプトのいくつかが動かなくなった。原因は wiringPi や GPIO など絡んだ処理の中では、/proc/cpuinfo にアクセスして “Hardware” を取得しその値に合わせてアクセスするポートなどを切り替えているみたい。しかしながら、linux-6.x になったら /proc/cpuinfo で Hardware 情報が取れなくなったため、wiringPi, GPIO関連のプログラムが動かなくなった。

BME280 温湿度センサーを GPIO 経由から ioctl() から I2C を制御する処理に書き換え

$ ./bme280
Oops: Unable to determine board revision from /proc/cpuinfo
-> No "Hardware" line
->  You'd best google the error to find out why.

参考にしていたプログラムが wiringPi 経由で I2C 接続の温湿度センサー bme280 を使っていたけど、仕方がないのでプログラムを修正し、ioctl() 経由に修正。

bit 演算が多用されていて、unsigned char と char の宣言を手抜きしたら、異常値が出るようになった。char型の部分を unsigned char に修正したら、大きな値にずれる異常値はなくなった。でも、その後も時々小さな値となる異常値が発生した。どうも nagios やら munin で監視していると時々同じタイミングで bme280 の値取得の処理が起動されるようで、I2C デバイスの競合が発生していると思われた。このため、I2C デバイス /dev/i2c-* を開く際に flock() による、排他処理も追加した。

OLED ディスプレィ SSD1306 の処理を Adafruit_CircuitPython_SSD1306 に変更

Adafruit_Python_SSD1306 を使って表示させていた処理が動かなくなる。内部で WiringPi などを使っているのか “RuntimeError: Could not determine platform…” といったメッセージが出て動かなくなる。これも GPIO あたりのトラブル。調べていると Adafruit_CircuitPython_SSD1306 なら動きそう。

$ sudo pip3 install adafruit-circuitpython-ssd1306

若干のプログラム修正で動くようになった。

スクリプト言語の比較

Raspberry Pi で、自宅内の温湿度管理とか色々やっていて、shell や perl や python などのスクリプトを使っているけど、ただでさえ遅い Raspberry-Pi だし、少しでも軽く動いてほしくて、lua なども使っている。

でも、shell だと、bash で書いているけど、高機能な分だけ遅いし、少しでも軽くなればと、インストールされているスクリプト言語のサイズを改めて比較をしてみた。

$ ls -al <いろいろ>
-rwxr-xr-x 1 root root   14000  1月  2  2021 /usr/bin/lua50
-rwxr-xr-x 1 root root   91904 12月 10  2020 /bin/dash
-rwxr-xr-x 1 root root   92292 12月 22  2018 /bin/sed 
-rwxr-xr-x 1 root root  120704  2月 17  2020 /usr/bin/mawk
-rwxr-xr-x 1 root root  133048  8月  1  2016 /usr/bin/lua5.1
-rwxr-xr-x 1 root root  974312  3月 28  2022 /bin/bash
-rwxr-xr-x 2 root root 3201036  9月 25  2021 /usr/bin/perl5.32.1
-rwxr-xr-x 1 root root 4703672  3月 12  2021 /usr/bin/python3.9

個人的には、軽いスクリプトというと、sed < awk < lua < bash < perl < python というイメージで使い分けをしていた。

しかし、これを見ると、bash と dash で10倍の差、軽くなればと使っていた lua だけど、lua5.1 と lua50 でも 10 倍の差がある。perl だと bash の 3倍、python だと bash の5倍。バイナリのサイズが単純に処理速度に反映される訳ではないけど、これを見る限り、自分で書いている手抜きスクリプトであれば、dash や lua50 で動かした方がよさそうだな。

また、下手に Perl を使うぐらいなら、bash の中で sed や awk を交えながらスクリプトを書くことも多いけど、下手に bash の中で sed や awk をガシガシ使ったら、あんまり早くなさそうだな。

これからは、lua50 < dash < sed , awk < bash < perl < python かな。

RPi-MZ80Cのボード入替え

Raspberry-Pi による ミニチュア MZ80C のボードを入れ替えして、表示部分も入替え。
{CAPTION}
以前より導入していたBME280の温度・湿度・気圧に加え、不快指数とYahoo天気の天気情報を表示するようにしてみた。

Raspberry-Pi MZ80C のボード差し替え

RPi model A+ が異常

以前に購入した Raspberry-Pi model A+ の MZ80C だけど、ボードがおかしくなっているのか、CPU 負荷がアイドル状態なのに 100% となっている。同様の Rapberry Pi と処理速度も変わらないし、何か変。RPi3 のボードに比べると処理速度も遅いし、RPi 3 model A+ のボードが同じ RPi3 model B より割安なのでボード差し替えをやってみる。

RPi 3 model A+ に差し替え

せっかくだし、表示部分も I2C 接続の SSD1306 の OLED Display を買う。

https://github.com/adafruit/Adafruit_Python_SSD1306

((( SSD1306 )))
GND VCC SCL SDA
黒  白  灰  紫

((( BME280 )))
VDD GND NC  SDI SDO SCK
VDD GND --  SDA --- SCL
白  赤  ×  黄 ×   青

((( Raspberry-Pi )))
3.3 SDA SCK × GND

BME280, Adafruit SSD1306を使えるように

この RPi は、2Fのトイレに設置して、2Fの廊下全体の温度を測っていた。なので、載せ替えした RPi にも同様の機能を移植。

なんとか動くようになったかな。

ただ、syslog を見ると、電源電圧不足の警告が出ているし、たまに繋がらなくなる。確認すると再起動してる。USB電源アダプタ電流とれるやつに差し替えが必要だな。

Raspberry Pi の bullseye 更新

いつも大きい更新をかける時は、依存関係でトラブルから、利用頻度の低いパッケージを削除したり、重要なパッケージだけ個別に更新していたけど、”apt upgrade –without-new-pkgs” は、便利なコマンド。これなら、ディスク容量が少ない Raspberry-Pi でも途中で容量不足で止まったりといった心配も少ない。

((( busterで更新 )))
$ sudo aptitude update ; sudo aptitude safe-upgrade

((( bullseyeの登録 )))
$ sudo vi /etc/apt/sources.list.d/11-bullseye.list
deb http://raspbian.raspberrypi.org/raspbian/ bullseye main contrib non-free rpi
deb-src http://raspbian.raspberrypi.org/raspbian/ bullseye main contrib non-free rpi

((( 最小限アップグレード )))
$ sudo aptitude
$ sudo apt upgrade --without-new-pkgs
$ sudo aptitude safe-upgrade

2台まとめての buster→bullseye 更新でいくつか、自分の家専用の処理が動かなくなったが、ボチボチと修正し復帰かな。

WiFiスキャンをさせてみた

自宅内のネットワークに繋がらない時があって悩んだら、外で使っていたモバイルルータがつけっぱなしで、自宅内ネットワークのサービスに接続できないのが原因だったりする。パケットも無駄に消費するので、自宅内でモバイルルータが動いていたら警告させるようにしたい。

wifi scan

メインサーバは有線だけなので、有線LAN接続で WiFi が空いている Raspberry-Pi で監視させてみた。

$ sudo iw dev wlan0 scan | grep "SSID: ルータのSSID"

最初は homebridge の homebridge-cmdswitch2 の state_cmd に仕込んでみたけど、モバイルルータが動いていたら警告してほしい。Siri のオートメーション経由で警告することもできるかもしれないけど、スマホに頼る形になるなぁ。

nagios で警告させたいけど、raspberry-pi に nagios を入れるのは資源のムダに思える。ということで、Raspberry-Pi には nagios の監視をリモートで呼び出す nagios-nrpe-server を 入れて、上記 iw コマンドを動かす check スクリプトを書いてみた。

check_iwscan

nagios-nrpe-server から呼出す際に、Raspberry-Pi で動かすのもあるし、OS 負荷が軽くなるように Lua で書いてみた。

#!/usr/bin/lua

-- 見つけるべきSSID
local check_list = {}
check_list[ "tsaitoh.net" ] = "ok"
check_list[ "tsaitoh.net_e5785" ] = "warning"
check_list[ "tsaitoh.net_hwd14" ] = "critical"

-- 見つけたSSID毎の数
local count = {}
count[ "ok" ] = 0
count[ "warning" ] = 0
count[ "critical" ] = 0

-- スキャン結果を処理
local handle = io.popen( "/usr/bin/sudo /sbin/iw dev wlan0 scan" , "r" )

if handle then
   for line in handle:lines() do
      -- SSID を抽出
      ssid = string.match( line , "^%s*SSID: (.+)$" )
      if ssid then
         -- SSID のカウント
         local lv = check_list[ssid]
         if lv then
            count[lv] = count[lv] + 1
         end
         -- print( ssid ) ;
      end
   end
   handle:close()
end

-- カウント結果に応じたexit値を決める
local status = 0
local st_mess = "Ok"

if count["critical"] > 0 then
   status = 2
   st_mess = "Critical"
elseif count[ "warning" ] > 0 then
   status = 1
   st_mess = "Warning"
end

-- 結果の表示
print( string.format( "IWSCAN %s - ok:%d/warn:%d/critical:%d" ,
                      st_mess , count["ok"] , count["warning"] , count["critical"] ) )
os.exit( status )

Google 検索

My Google   Yahoo

Microsoft

ファンサイト