Raspberry Pi シェル内でOS経過時刻を判定する

Raspberry Pi Zero WHに4Gモジュールを接続する3にて、OS起動時から規定経過時間以内に、PPP接続できなかった場合、OSリブートするように仕込みました。その仕込み先は、シェルスクリプトですが、規定経過をどのように判定したかを解説します。

通常、シェル内で現在時や取得できますが、OS起動からの経過時刻を取得するコマンドが見つかりませんでした。..しかし、 pythonでは組みたくない。言われてみるとWindowsにもないような... .困りました...そうだ 新しいコマンドを作ってしまえばいい。

OS起動からの経過時刻は、カーネルシステムコール:times() です。コマンドのソースコードは以下の通りです。ラズパイでは単位はmsecになるようです。

#include <stdio.h>
#include <sys/times.h>
#include <memory.h>

struct	tms	tmwk;

int main(int ac, char **av)
{
	printf("%lu\n", times( 0 ) );
}

デバック不要なので、コマンドラインで一回だけビルトします。

cc -o passtime passtime.c 

このpasstimeコマンドを、シェルから ` …` で呼出し、シェル変数に取り込みます。

START_10MSEC=`passtime`

while [ 1 ];do
   NOW_10MSEC=`passtime`
   PASS_10MSEC=$(( $NOW_10MSEC - $START_10MSEC ))

   # pass 5 min
   if [ $PASS_10MSEC -gt 30000 ];then
	shutdown -r now 
   fi

   # under flow timer
   if [ $PASS_10MSEC -lt 0 ];then
	shutdown -r now >> $ASAHI_LOG
   fi

一応、アンダーフロー時も処置しておきます。

Raspberry Pi Zero WHに4Gモジュールを接続する3

前回ラズパイと4GモジュールのPPP接続まで説明しました。今回は、実用面での課題を述べます。

① USBラインの瞬断

USBケーブルするタイプの4Gモジュールの場合、コネクタのぐらつきで瞬断する場合があります(もしくは想定されます)。IoT機器内に設置する場合、ケーブルの取り回しでストレスがかかることも。マイクロusbならなおさらです。

いろいろと試したところ、一度接続異常が発生すると、ラズバイがハングする場合があるようです。USB接続がぐらつかないよう物理的に対策をしておくことをおススメします。例としましては、

  • USBケーブルをケース等に固定する。
  • 取回しスペースが狭い場合、L字のUSBケーブルを使用する。
  • 可能な場合、ラズパイのserialポートで、4Gモジュールと接続する。

② USBラインのノイズ

USBはノイズに弱いので、規定以上発生すると、PPPが断線します。ノイズの出やすいIoT機器の場合、どこに設置されるか想定できない機器の場合、配慮が必要です。実際に弊方でも本番装置に搭載後、予期無くPPP断線しました。以下そのsyslogの内容です。

Mar  2 10:33:20 raspi kernel: [ 1435.722327] usb usb1-port1: disabled by hub (EMI?), re-enabling...
Mar  2 10:33:20 raspi kernel: [ 1435.722387] usb 1-1: USB disconnect, device number 2

EMI?(電磁障害かも)とラズパイは言いたいようです。この事象が発生すると、OSその他動作は継続するものの、OS再起動しないかぎりPPP接続が復帰しません。対策としては、PPPの接続状況を常時監視し、切断したらOS再起動さるシェルスクリプトを作成し、rcから起動し常駐化せました。以下そのスクリプト例です。

#!//bin/sh 
PPP_ON=0

while [ 1 ]
do
    # Check PPP gen device
    ifconfig ppp0 > /dev/null
    RET_PPP=$? 

    if [ $RET_PPP -eq 0 ];then
        PPP_ON=1
    else
        # Turn PPP on to off
        if [ $PPP_ON -eq 1 ];then
           echo "Catch to turn PPP on to off."
               :
           ( いろいろ後始末 )
               :
           shutdown -r now
        fi
    fi

    sleep 30
done

ifconfigコマンドで、PPP切断を判別してみました。リブート中は応答できなくても許容されるシステムに場合に限ります。

なお、本当のノイズか白黒つけるには、放射電雑試験を行うべきてすが、大きな電機メーカさんでも絡んでないと難しいです。

③ 起動時のチェック

動作環境によって、必ずしも起動時に、PPP接続できるとは限りません。可能なかぎり以下チェックをいれます。カッコ内は、チェックのためのコマンド例です。

  • 4Gモジュールを認識しているか? ( lsusb | grep Qualcomm )
  • WAN接続できているか? ( ifconfig wwan0 > /dev/null )
  • PPP接続できているか? ( ifconfig ppp0 > /dev/null )
  • ルーティングが正常か? ( route | grep ppp0 )
  • ドメインにパケットが届くか? ( ping 対象ドメイン -c 3 )

起動後、すぐにPPP接続はできないので、数秒置きに数分繰り返し、PPP接続できない場合はOSリブートするしかないですね。上位の管理機器があれば、そちらに知らせて処置するが妥当でありましょう。

Raspberry Pi Zero WHに4Gモジュールを接続する2

前回ラズパイと4Gモジュールの接続確認を説明しました。今回はインターネット接続まで行います。

① PPP接続準備

まずPPPパッケージ(ドライバ?)を以下のようにインストールします。

$ apt-get install ppp

ppp接続を、APN(インターネットプロバイダ)毎の設定を編集します。ひな形の入手先は忘れましたのでファイル全体をのっけときます。以下太字部をAPNに合わせて変更します。ファイル名はAPN名とします。今回は “rnet” としました。

# example configuration for a dialup connection authenticated with PAP or CHAP
#
# This is the default configuration used by pon(1) and poff(1).
# See the manual page pppd(8) for information on all the options.

# MUST CHANGE: replace myusername@realm with the PPP login name given to
# your by your provider.
# There should be a matching entry with the password in /etc/ppp/pap-secrets
# and/or /etc/ppp/chap-secrets.
user "APNログイン名@APNパスワード名"
# MUST CHANGE: replace ******** with the phone number of your provider.
# The /etc/chatscripts/pap chat script may be modified to change the
# modem initialization string.
connect "/usr/sbin/chat -v -f /etc/chatscripts/gprs -T APN名"
# Serial device to which the modem is connected.
4Gモジュールの接続先デバイスファイル名(例:/dev/ttyUSB2)
# Speed of the serial line.
4Gモジュールとの通信速度(例:115200)
# Assumes that your IP address is allocated dynamically by the ISP.
noipdefault
# Try to get the name server addresses from the ISP.
usepeerdns
# Use this connection as the default route.
defaultroute
# Makes pppd "dial again" when the connection is lost.
persist
# Do not ask the remote to authenticate.
noauth

ラズパイのGPIOで接続指示するタイプの4Gモジュールの場合は、GPIOへの出力を開始します。以下、GPIO 6で、接続を開始する一例です。

#!/bin/sh

# Port of 4G-module on/off is enable.
echo "6" > /sys/class/gpio/export
sleep 0.1

# Set port of 4G-module on/off mode to output.
echo "out" > /sys/class/gpio/gpio6/direction

# Turn on 4G-module.
echo "0" > /sys/class/gpio/gpio6/value

② PPP接続実行

“rnet”は、/etc/ppp/peers/ に配置します。配置後、PPP接続コマンド”pon”を以下のようにたたきます。もちろんスーパーユーザで。

$ pon APN名

接続を確認するには、ifconfig をたたけばよいです。以下のようなにppp0とwwan0が現れればOKです。

ifconfig

ppp0: flags=4305<UP,POINTOPOINT,RUNNING,NOARP,MULTICAST>  mtu 1500
        inet 100.70.xx.xx  netmask 255.255.255.255  destination 10.64.xx.xx
     (中略)

wwan0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 169.xxx.xx.xx  netmask 255.255.0.0  broadcast 169.xxx.xx.xx
    (中略)

接続が確認できない場合は、エラー内容はsyslog に出力されているので、内容を確認します。尚接続解除は、”poff”コマンドをたたきます。

OS再起動時、PPPは自動接続されますが、ラズパイのGPIOで接続指示するタイプの4Gモジュールの場合は、rcスクリプトにGPIOへの出力を追加する必要があります。

③ インターネット接続確認

適当なドメインにpingで確認すればよいでしょう。PPP側のルーティング情報を、ルーティングコマンド”route”で以下のように追加設定します。

$ route add -net 0.0.0.0 ppp0

pingの結果は、以下のとおりです。初回すこし時間かかります。ping拒否のドメインもあるので、yahoo かgoole、自社ドメインが適当です。

$ ping yahoo.co.jp
	
PING yahoo.co.jp (183.79.xx.xx) 56(84) bytes of data.
64 bytes from 183.79.xx.xxx (183.79.xxx.xxx): icmp_seq=1 ttl=51 time=46.5 ms
64 bytes from 183.79.xx.xxx (183.79.xxx.xxx): icmp_seq=2 ttl=51 time=159 ms
  ( 後 略 )

④ 自動接続設定

ルーティング設定は、OS再起動するとなくなるため、OS起動毎に設定する必要があります。当方では、ppp接続後に自動呼出しされるスクリプト”/etc/ppp/ip-up”に追加しました。

#!/bin/sh
    (中  略  )
# if pon was called with the "quick" argument, stop pppd
if [ -e /var/run/ppp-quick ]; then
  rm /var/run/ppp-quick
  wait
  kill $PPPD_PID
fi

/sbin/route add -net 0.0.0.0 ppp0

# Donot exec this shell. exec from /etc/init.d.
##/home/remolog/remolog_main.sh &

また、当方ではラズパイの無線LAN側を、DHCPでなく固定IPでないとうまくいきませんでした。何かの誤りかもしれませんが、注記いたしておきます。

PPP接続側は、/etc/network/interfaces に以下太字部を追加します。

# interfaces(5) file used by ifup(8) and ifdown(8)

# Please note that this file is written to be used with dhcpcd
# For static IP, consult /etc/dhcpcd.conf and 'man dhcpcd.conf'

# Include files from /etc/network/interfaces.d:
auto rnet
iface rnet inet ppp
provider rnet

source-directory /etc/network/interfaces.d

Raspberry Pi Zero WHに4Gモジュールを接続する1

コンパクトなRaspberry Pi Zero Wに、4Gモジュールを接続してIoTシステムを構築しました。Pi Zeroと4Gモジュールの接続について解説していきます。諸事情により4Gモジュールの機種は非公開ですが、USB接続、コアチップはQualcomm製ですのでHowToとしは汎用性があるかと。以下テーマに分けて解説していきます。

① ラズパイ側の対応

始めるまでしりませんでしたが、ラズバイは4G接続に予め対応しています。ただしOSは、Raspbian GNU/Linux 10 kernel 5.15あたり以降が良いようです。kernel 5.4では認識しませんでした。その上で以下のように最新化したほうがよいでしょう。尚当方ではsudoは使用せず、su – rootで常時スーパーユーザで作業しています。

apt update
apt -y upgradeapt dist-upgrade -y
rpi-update
apt autoremove -y
apt autoclean

4GとUSBでつなぐので場合、標準のserial通信は殺します。

systemctl disable serial-getty@ttyS0.service

4Gモジュールをラズバイに接続して、以下のコマンドをたたくと認識しているか確認できます。

②4Gとの初期チェック

まず初期チェック用に、”minicom”ユーティリティをいれます。以下コマンドです。

apt-get install minicom

4GモジュールとUSBがつながると、/dev/ttyUSB2 に通信ポートが割り当てられます。以下コマンドをたたきます。通信速度は11,520程度、echo backはONにします。

minicom -D /dev/ttyUSB2

4Gモジュールとのやり取りは、ATコマンドを使用します。ATコマンドは元々有線電話回線用の標準コマンドでしたが、無線用に拡張されて今に至っているようです。ネットで検索すると、いろいろ仕様がでてきます。”minicom”で以下の”AT ~”の部分たたき、以下のように応答が返ってくればOKです。SIMは差しておきます。

AT                            
OK
AT+CNMP=38
OK
AT+CSQ
+CSQ: 19,99
OK
AT+CREG?
+CREG: 0,1
OK
AT+COPS?
+COPS: 0,0,"NTT DOCOMO NTT DOCOMO",7
OK
AT+CPSI?
+CPSI: LTE,Online,440-10,0x1249,49418752,201,EUTRAN-BAND1,276,4,4,-74,-1005,-746
OK

最後のコマンドで “Low Power Mode” となる場合、PCから電源供給しているれようなら、5VのACアダプタから供給したほうがよいでしょう。

ms office2003のツールバー設定を他PCに移す

MS Office 2003の情報は、今やネット上に情報が少ないので、まとめておきます。

1)Execlの場合

ユーザフォルダから、特定ファイルを移動元から、移動先にコピーし、Execlで開きます。一回で出来ない場合があるようです。数回やってみます。

2)Wordの場合

他officeツールとことなり、レジストリ保持のようです。移動元PCでエクスポートして、移動先で登録します。

3)パワポの場合

特定ファイルのコピーだけで済みます。

VAIO Pro PG / VJPG11*を、500GB NVMe SSDに換装する

お出かけ用開発期「VAIO Pro PG / VJPG11*」は、Win11対応のCPU、RAM 8GB、指紋認証、made in Japan、軽量、中古なら3万円程度ととでも良いマシンです。しかしWindows、組込み、モバイルと開発環境をいれると、ストレージ容量はいっぱいです。SSDの換装に踏み切ります。

「CrysalDiskinfo」で調べると元々搭載されていたSSDは以下のとおりでした。

SAMSUNG MZNLM256HAJQ

日本設計と安さと以下のものを選びました。

KIOXIA 内蔵 SSD 500GB NVMe M.2 Type 2280 PCIe Gen 3.0×4」

購入してみて、最近のノート用SSDのインターフェイスも「SATA」と「PCIe」の二種類があるとは知りませんでした。オリジナルは「SATA」です。果たして使えるのでしょうか?

VAIOサポートサイトでは、別モデルですが近い年式では対応していると情報がありました。

「VJS111,VJS131,VJZ131*] PCI Express対応SSDについて」

VAIOを開けます。VAIO Zなどと比べると開けやすく、SSDも簡単に外せます。KBとのフラットケーブルはロック解除方法が分からず、外さず作業しました。SSDの長さもマッチしてました。

内容のコピーは、NVMe用のSSDコピー用アダプタは種類も少なく高く、コピーツール無しで以下のように行います。

  1. SSD-USBメモリに、Windows Backupで換装前のディスクイメージを作成。
  2. Window 11起動USBメモリを作成。
  3. SSDを差し替え。
  4. 上記2で、上記1をディスクイメージを回復させる。

BIOSは、新しいSSDを認識しているので、「PCIe」でも行けそうです。しかしOS起動時に「INACCESSABLE_BOOT_DEVICE」なるエラーが出ました。

Windows11の「自動復旧」が効いたのか、何回か再起動を繰り返していると治りました。SSDの認識状態は、以下のとおりです。転送速度は倍早いらしいですが気持ちそんな感じ。温度が高めなのが気になります。

専用のユーティリティが用意されているのもユニークです。

しかし、アプリテスト用Windows10英語は動作しなくなりました。古いWin10はドライバが対応していないのかもしれせん。こちらはOS再インストールしました。

Office2003は未だ認証できるか?

やっぱりofficeは2003が完成形。C#化された最近は、余計な機能で効率が落ちます。吹出しのデフォルト文字と背景色、吹出しの書式付きコピー、右ペインに出る書式や図形のプロパティ、図形グループ化後の図形移動、shiftよよる水平垂直線の廃止、見にくい游ゴシックフォントなど。良いところは、Execelの行数上限UPくらいですかね。2022だと多少ユーザが切替れるようになっているようではあります。

外部に提出時に変換すれば一応セキュリティ面も保たれるかと、まだ内部は2003です。PCを追加したので2003を追加導入。2021年は、オンラインライセンス認証できましたが、2023年5月はどうでしょうか?

まだいけますね。ヨカッタ。

Xamarin Projectを下位Version移す時

DISKTOPでVS2019で作成しているXamarinのProjectを、移動中作業のためVS2017 を入れた低スペックノートに移すと以下のエラーがでました。なるべくメモリ食わないVisual Sdudioを入れたいのですが、、、

メッセージ形式は以下のような模様てす。

The ${TargetFrameworkVersion} for プロジェクト名(現在のandroid SDKバージョン) is less than the minimun requied ${TargetFrameworkVersion} form Xamarin.Froms(必要なandroid SDKバージョン ) You need increase the ${TargetFrameworkVersion} for プロジェクト名.

どうもVisual Studioバージョンに対して、使えるAndrod SDK バージョンが決まっているようです。VS2017に、上位バージョンのAndrod SDKを無理くりコピーしてに認知されません。

Androd SDK の上限とVisual Studioバージョンをインストールしながら試すと以下ようでした。

Visual StudioAndrod SDK
2017-15.48
2019-16.09
2019-16.410
2019-16.711

対策は、*.csproj をエディタで開いて編集すると良いようです。

  <PackageReference Include="Xamarin.Forms" Version="5.0.0.2515" /> 

ここはどうもProject作成時に設定されて、IDEが直接変更できないようです。VS2017に対応されるには以下のように修正します。

<PackageReference Include=”Xamarin.Forms” Version=”3.4.0.1008975″ />

*.csproj は、「プロジェクト名」のフォルダと、「プロジェクト名_Andriod 」の2つあります。両方を修正します。

しかし、「ダークモード」はAndrod SDK 10からサポートのため、「ダークモード」判定を入れているプログラムは、そのimportと判定部を避ける必要がありました。

AWS IoT Mqttのエラー処理

AWS IoTにてサーバリクエストを行う「MQTT」。比較的簡易ですが、エラー処理面でやや留意点がありました。必ずしもではないかとおもいますが、記録しておきます。機器はラズパイ、言語はPythonです。

1 . connect()でエラーになりやすい場合

インターネットおよびLANも生物ですから不安定な場合もあります。そのせいか当方では、MQTTクライアントのconnect()メソッドでエラー一時的に多発しました。

よくよく調べると、connect()メソッドのタイムアウトのデフォルト値は5秒です。

これではすぐに引っかかりそうです。AWSサーバで生成した「接続キット」のサンプルコードのままではNGです。30秒は欲しいところです。以下のように修正しました。

    mqttc = AWSIoTMQTTClient(clientId)
            ( 中 略 )
           
    mqttc.configureConnectDisconnectTimeout(30)  
    mqttc.configureMQTTOperationTimeout(30)
    mqttc.connect( )

ついでに、publish()メソッドのタイムアウト値も延ばしておきます。

2 . publish()がエラーにならずスルーする

publish()メソッドのエラー検出のテストのため、テストコードで先にmqttc.closeメソッドし、publish()したところ、エラーにならずスルーしました。

これは疑似的なので仕方ないと、実機テストに踏み切ったところ、たまたまネットワークが切れ、サーバ受信にできなかったのですが、publish()側では正常スルーなりました。ネットワーク本体が切れると、スルーしてしまうのかな?

しかなく、Pythonスクリプトとは別に、シェルスクリプトでネットワークデバイスを、数秒置きに監視しするようにしました。当方では、4Gによるppp接続だったため以下のようにした。

while [ 1 ]
do
    ifconfig ppp0 > /dev/null
    RET_PPP=$? 

    if [ $RET_PPP -eq 0 ];then
	PPP_ON=1
    else
    	# flash disk cash
	sync
	sync
	sync
	shutdown -r now
    fi

    sleep 30
done

少し乱暴ですが、pppが切れる要因によっては復帰できない場合もあるため、一律リブートとしました。

AWS で暗号化zipを試す

AWSで、ユーザがダウンロードするファイルは、暗号化したいところです。まず「CloudShell」で、「S3」のファイルを暗号化Zipする練習してみました。

以下のシェルでできました。

#!/usr/bin/bash
MY_BUCKET=S3対象のバケット
MY_CSV=対象ファイル
MY_ZIP=$MY_CSV.zip
MY_PASS=パスワード
cd /tmp

if test -z $MY_CSV; then
        exit 1
fi

if test -z $MY_PASS; then
        exit 2
fi

rm -f $MY_CSV $MY_ZIP

aws s3 cp s3://$MY_BUCKET/$MY_CSV  .
if test $? -ne 0; then
        exit 3
fi

zip -e --password $MY_PASS $MY_ZIP $MY_CSV
if test $? -ne 0; then
        exit 4
fi

aws s3 mv $MY_ZIP s3://$MY_BUCKET
if test $? -ne 0; then
        exit 5
fi

exit 0

これを「Lamdba」から呼出せばと安直にかんがえていましたが、「Lamdba」と「CloudShell」は、全く別空間なので呼び出せません。

「Lamdba」の「レイヤー」でシェルを試したりしましたが、結局「Lamdba」でUNIXシェルは接動かせず、「Lamdba」の上でZipコマンドは未サポートでした。この作戦はNG。「EC2」なら呼べるらしいですが、今回は常に仮想サーバが必要でシステムではないので控えました。

Python側の「zipfile」に頼ります。ヘルプではいちおうパスワードが指定できるようになっていますね。

ZipFile.setpassword(pwd)
Set pwd (a bytes object) as default password to extract encrypted files.

しかしこれは読込時のみでした。書込み時は、pythonから未サポートの旨のエラーが出ます。なんかzipの暗号化はライセンス上の制約があるとか、昔なにかで聞いたことがある気がします。

ネットで探すと、暗号化zipのpythonライブラリ「pyminizip」がありますね。「EC2」にもっていってためします。(EC2用に再Buildが必要だったかもしたかもしれません)

とりあえず「Lamdba」の「レイヤー」に追加するため、「pyminizip」をzipにまとめてから、PCローカルに「scp」でコピーします。windowsから行う場合、少し事前準備が必要でした。

「pyminizip.zip」を、「Lamdba」の「レイヤー」に追加して、Lamdba関数側で、pyminizpをimportします。実行すると、import時点でエラーになってしまいます。

他ネット記事によると、python3用にいじってリビルドするといけるらしいのですが、

業務での使用ですので際どいことは避け、信頼性の面から、控えておきました。

そのうちサポートされるかもしれませんし…