counter

RedHat 7.1J, 7.3, 8 に OMRON BX50XFV(UPS)を接続

このページでは、RedHat Linux に、OMRON BX50XFV(UPS)を接続して、シャットダウンソフトに genpowerd を使用した設定例を紹介いたします.

RedHat Linux 7.1J に、OMRONの低価格UPS BX50XFVを導入しました.

BX50XFVは、POWLI(パウリ、Power ine nsurance)の愛称を持ったUPSで、常時商用タイプの500VA(300W)用のものです.

当初、RedHat Linux 7.1J に導入していましたが、現在(2003年2月)は、RedHat Linux 7.3 および RedHat Linux 8 の上で使用しています.

OMRONのHPによれば、
2003年)1月30日付けで、製品に添付されている 自動シャットダウンソフトPA〔(PowerAssistant)Ver1.12 Linux版〕が RedHat 6.2J, 7.1J, 7.3, 8 に対応しています.

OMRONのHPによれば、
2003年)7月29日付けで、RedHat Linux 9 に対応した 「PA Linux for Red hat 9」 が公開されています.

このページは、Microsoft Internet Explorer 5.5 SP2 と Netscape(R) Communicator 4.73 で動作確認を行っています.

フォント・サイズは、"小" を推奨いたします.




======= 1)導入背景の章 ===========================================

OMRONBX50XFV です.

4年前にBX352とBX510を導入後、特に問題もなく順調に使用していましたが、昨年(2001年)暮れにBX352が昇天してしまいました. 考えてみれば、その間バッテリ交換やメンテナンスなど何もやっておらず、バッテリの寿命が2年程度との事から、まあ、よく持ったものとの思いです.

更新にあたり、Linuxからでもシャットダウンが可能な自動シャットダウンソフトが添付されており、かつ、低価格のものをと物色した結果、このBX50XFV(オムロンダイレクト通販価格 19,800円)が目に止まりました.

TOPに戻る

 
 
======= 2)実装と設定の章 =========================================

しかし、OMRON のカスタマサポートセンタに問い合わせると、添付の自動シャットダウンソフト「PowerAssistant」は、RedHat Linix 6.2J には対応しているが新しいバージョン 7.1J には対応していない事が判りました.

せっかくですから、24時間稼動しているLinux機でも自動シャットダウン機能を使用したいもので、カスタマサポートセンタに聞くと、あくまで参考情報ですよ、との但し書き付きで下記のURLを教えて頂きました.

ここには、OSに debian、UPSにBX50XFVの姉妹機BX35XFとシャットダウンソフトに genpowerd を使用した例が掲示されています.

今回は、このページと、その中でリンクしている 仙台電波高専熊谷研究室さん のページを参考にしつつ、BX50XFVの取扱説明書と格闘する事になりました.


通信インターフェイス
BX50XFVとパソコンとの通信インターフェイスは、PowerAssistantプロトコルに対応したシリアル方式と従来からの接点方式の2種類があります.

シリアル方式とは、RS−232Cを用いてパソコン側からコマンドをBX50XFVに送ると、BX50XFVは、コマンドに対応した各種情報を返すことにより、BX50XFVの状態を知るものです.

接点方式とは、BX50XFV側にあるスイッチ(オープンコレクタです)のオン・オフによりBX50XFVの状態を知る方法です.

今回のLinuxでの使用は、従来からの接点方式を使用する事とします.
BX50XFV側の接点方式の場合の信号入出力は下図のような構成になっています. また、信号入出力コネクタは、DSUB9Pinメスです.

BUとBLは、オープンコレクタなので何らかの方法でプルアップする必要があります.

BX50XFV-I/F BX50XFV
PinNo信号名称入出力機  能備 考
BU出力バックアップ信号
停電中継続してBU-COM間がONになる
 
BS入力バックアップ電源停止信号
外部から信号電圧(High)を加えることでバック
アップ電源の停止させる
 
COM--Common/GND 
BL出力バッテリーLow信号
バックアップ運転時でバッテリの残量が
少なくなった時にBL-COM間がONになります
 
BLは、バックアップが停止する2分以上前にONになります. ただし、バッテリが劣化し、バックアップ時間が短くなると2分未満になることがあります.

ケーブル
BX50XFVには、自動シャットダウンソフト「PowerAssistant」が添付されており、これ用のケーブルも同梱されています.
このケーブルは、両端がそれぞれ9PinDSUBのオスとメスのコネクタのストレートケーブルです.

今回は、このケーブルを流用したいと考えました.
しかし、このままでは下の表のような接続となり、BUとBLに必要なプルアップの手段がありません.

UPS(無停電電源装置)を接続する の記事を読むとDTRとRTSをHighにする必要があると書かれていました. これでプルアップ用の電源は確保できるとしてもプルアップ抵抗がありません.

PinNoUPS方 向P C備 考
BL-->DCDバッテリーLow信号
---->RXD 
BS<--TXDバックアップ電源停止信号
--<--DTR 
COM<-->COMCOM
---->DSR 
--<--RTS 
BU-->CTSバックアップ信号
---->RI 

プルアップ抵抗は、BX50XFVに内蔵されているのだろうと推測し、再び OMRON のカスタマサポートセンタに問い合わせると、次のような返事が返ってきました.

BX50XFV用に、Windows NT 標準シャットダウンに対応した DOS/V インタフェースケーブル BUC16 を別売している.
これは、BX50XFVの接点方式を使用するものであるが、ケーブル内には抵抗は入っていない.
そのために、BX50XFV側で何らかの工夫をしている.

具体的には、BX50XFV側でどのような事が行われているのか詳しく聞く事はできませんでしたが、BX50XFV内部にBUとBLのプルアップ抵抗がある事は確信できました. 同時にBX50XFVの1−4ピンおよび7−8ピン間の抵抗を測ると5〜6KΩとなっていました.

こんな経緯があり、ケーブルはBX50XFVに同梱されているケーブルをそのまま使用する事となりました.
このケーブルは、両端がそれぞれ9PinDSUBのオスとメスのコネクタのストレートケーブルです.

信号線のまとめ
これらのことをまとめると、
ケーブル
BX50XFVに同梱のものを使用する.
両端がそれぞれ9PinDSUBのオスとメスのコネクタのストレートケーブル
プルアップ電源
genpowerd 起動時にBUとBLのプルアップ電源としてRTSとDTRを共にHighに設定する.
プルアップ抵抗は、BX50XFV側にある(と確信する)ものを使用する.
電源異常の監視と認識
BX50XFVのBU端子が接続されたCTSを監視する.
正常時はHigh、電源異常(停電)時はLowとなる
バッテリ容量低下の監視と認識
BX50XFVのBL端子が接続されたDCDを監視する.
正常時はHigh、バッテリ容量低下時はLowとなる
バックアップ電源停止信号
BX50XFVのBS端子が接続されたTXDを使用する.
正常時はLow、バックアップ電源停止時にHighを設定する

TOPに戻る


======= 3)genpowerd の設定の章 =============================

genpowerd の入手
sunsite より入手可能です. 現在、genpower-1.0.2.tar.gz が最新バージョンのようです.
sunsite 以外でも Google 等の検索サイトでダウンロード可能なサイトが見つかります.

適当な場所にコピー後、
  % tar -xzf genpower-1.0.2.tar.gz
で解凍しておきます.

genpowerd.h の編集
{NULL} の行の前に、第2章の検討結果で得られたBX50XFVの信号仕様に合わせた設定を加え、末尾の PWRSTAT と UPSSTAT の定義を変更します.

/* OMRON BX35/50XFV */
  {7, "omron-powli", {(TIOCM_DTR | TIOCM_RTS),0}, {TIOCM_ST,0}, 10, {TIOCM_CTS,0}, {TIOCM_CAR,0}, {0,0}},
  {-1, NULL}
};
  ・
  ・
#define PWRSTAT    "/var/run/powerstatus"
#define UPSSTAT    "/var/run/upsstatus"
設定内容
 項  目内  容備 考
7通し番号 
"omron-powli"UPSの名称 
{(TIOCM_DTR | TIOCM_RTS),0}BU、BL用プルアップ電源
DTR および RTS に通常Highを出力
 
{TIOCM_ST,0}, 10バックアップ電源停止信号
TXDに通常Lowを出力
バックアップ電源停止時Highを10秒出力
 
{TIOCM_CTS,0}バックアップ信号
正常時CTSはHigh
電源異常時にLowとなる
 
{TIOCM_CAR,0}バッテリーLow信号
正常時DCDはHigh
バッテリ容量低下時にLowとなる
 
{0,0}ケーブルチェック
このままでOK
 
TIOCM_CAR は、TIOCM_DCD と同じ.

genpowerfail の編集
genpowerd.h の修正に合わせて upsstatus のパスを変更とシャットダウン動作を再起動 -r から停止 -h に全て変更します.

さらに、case "$stats" in の中の処理を少々変更・追加します.
これは、RedHat Linux 7.1J において、
genpowerd の起動直後に、正常にもかかわらず shutdown を開始する事があったため、これの回避.
電源異常で shutdown 待機中にバッテリーLow信号が発生しても直ちに shutdown されない場合があったため、これの対策.
電源異常で shutdown 待機中に電源が復旧しても shutdown が継続される場合があったため、これの対策.
電源異常での shutdown 待機時間を2分から15分に延長した.
短時間の停電で、即、シャットダウンするのもイヤなので shutdown までの時間を出来る限りかせぐようにした.
ただし、バッテリの容量低下によりバッテリーLow信号が発生するまでバッテリを酷使する事となるのでバッテリの寿命に影響があるかも知れない.


# Set location of upsstatus file
statpath="/var/run/upsstatus"
     ・
     ・
     ・
    if [ -r $statpath ]
    then
            stats=`head -1 $statpath`

        case "$stats" in
            FAIL)  # Power is down
                shutdown -h +15 "THE POWER IS DOWN! SHUTTING DOWN SYSTEM! PLEASE LOG OFF NOW!" < /dev/console &
                ;;
            SCRAM) # Battery is low
                shutdown -c "THE POWER IS DOWN!"
                shutdown -h now "THE POWER IS DOWN! BATTERY POWER IS LOW!  EMERGENCY SHUTDOWN!" < /dev/console &
                ;;
            CABLE) # Possible bad cable
                shutdown -h +1 "POSSIBLE BAD CABLE! SHUTTING DOWN SYSTEM! PLEASE LOG OFF NOW!" < /dev/console &
                ;;
            OK) # 
                shutdown -c "THE POWER IS BACK-02"
                ;;
            *)     # Unknown message, assume power is down
                shutdown -h +2 "THE POWER IS DOWN! SHUTTING DOWN SYSTEM! PLEASE LOG OFF NOW!" < /dev/console &
                ;;
        esac
    else
        # genowerfail called, and upsstatus dosen't exist.
        # Assume user is using powerd, and shutdown.
        shutdown -h +2 "THE POWER IS DOWN! SHUTTING DOWN SYSTEM! PLEASE LOG OFF NOW!" < /dev/console &
     ・
     ・
genpowerd のコンパイルとインストール
make all
su
      <== ルート権限に
make install

その他の変更と設定

/etc/inittab
停電時の処理として genpowerfail を使用するように変更する.
# When our UPS tells us power has failed, assume we have a few minutes
# of power left.  Schedule a shutdown for 2 minutes from now.
# This does, of course, assume you have powerd installed and your
# UPS connected and working correctly.
#pf::powerfail:/sbin/shutdown -f -h +2 "Power Failure; System Shutting Down"
pf::powerfail:/etc/genpowerfail start

# If power was restored before the shutdown kicked in, cancel it.
#pr:12345:powerokwait:/sbin/shutdown -c "Power Restored; Shutdown Cancelled"
pr:12345:powerokwait:/etc/genpowerfail stop
/etc/rc.d/rc.local
Linuxの起動時に genpowerd を起動するように変更する.
rc.local の末尾に追加します. omron-powli は、genpowerd.h に追加したUPSの名称
# ADD support for the BX50XFV
echo "Starting genpowerd daemon..."
if [ -x /sbin/genpowerd ]; then
    /sbin/genpowerd /dev/UPS omron-powli
fi
/etc/rc.d/init.d/halt
shutdown 時にUPSを停止するように変更する.
halt の末尾の直前に追加します.
# Shutdown by the argument -k of genpowerd.
if [ -r /var/run/upsstatus ]; then
    status=`head -1 /var/run/upsstatus`
# If the status of UPS is not OK.
    if [ $status != "OK" ]; then
        echo "Killing Power..."
        sleep 5
        genpowerd -k /dev/UPS omron-powli
    fi
fi

# Now halt or reboot.
echo $"$message"
if [ -f /fastboot ]; then
 echo $"On the next boot fsck will be skipped."
elif [ -f /forcefsck ]; then
 echo $"On the next boot fsck will be forced."
fi

HALTARGS="-i -d"
if [ -f /poweroff -o ! -f /halt ]; then
 HALTARGS="$HALTARGS -p"
fi

eval $command $HALTARGS
シンボリックリンクの設定
BX50XFVの監視に使用するCOMポートを設定します.
COM1 ならば、/dev/cua0 を、COM2 ならば、/dev/cua1 を指定します.

ln -s /dev/cua0 /dev/UPS


TOPに戻る


======= 4)動作検証の章 ====================================

この動作検証を行っているあいだLinux機は、検証中のBX50XFVから電源の供給を受けるのではなく別の電源に接続します.
また、Linix機を再起動して genpowerd デーモンを起動させておきます.

停電時および電源復帰時の動作検証
停電時
BX50XFVの電源ケーブルをコンセントから抜いて停電状態を作ります.

下記のメッセージが表示されます.

Broadcast message from root (console) Sun Jan 20 11:36:43 2002...

THE POWER IS DOWN! SHUTTING DOWN SYSTEM! PLEASE LOG OFF NOW! 
The system is going DOWN for system halt in 15 minutes !!
停電からの復帰時
BX50XFVの電源ケーブルをコンセントに挿して電源を復帰させます.

下記のメッセージが表示されます. この後15分以上監視しシャットダウンがキャンセルされている事を確認します.

Broadcast message from root (console) Sun Jan 20 11:36:57 2002...

THE POWER IS BACK-02 
停電の継続時
再度、BX50XFVの電源ケーブルを抜いて停電状態としたまま放置します.

1 のメッセージが表示された後、15分後にシャットダウンが行われる事を確認します. ただし、バッテリ残容量によりそれ以前にシャットダウンが開始される場合もあります.


バッテリ容量低下時の動作検証
BX50XFVに適当な負荷を接続します.
BX50XFVの電源ケーブルをコンセントから抜いて停電状態を作ります.
BX50XFVのブザー音が4秒間隔から1秒間隔になったと同時にシャットダウンが開始される事を確認します.

TOPに戻る


======= 5)gentest の章 ====================================

ダウンロードした genpowerd には、UPSの挙動(正常動作や停電時の信号線の様子)やケーブルの接続状態をテストする gentest というプログラムが入っています.

使用方法は、

#  gentest  [-r -d]  <serial port> 
-r :RTSをHighに設定する.
-d :DTRをHighに設定する.

# gentest -r -d /dev/UPS
---------------
DTR = Set
RTS = Set

CAR = High  (*)
CTS = High  (*)
DSR = High  (*)
RNG = Low   ( )
起動すると各端子の情報を表示します. 変化のあった端子は (*) を付けて表示されます.
CAR は、DCD の事です.
CTRL + C で停止するまで各端子に変化があるたびに新しい情報を表示してくれます.

次の実行例は、genpowerd を起動中に gentest も並行して起動後、BX50XFVを正常 → 停電 → 電源復帰と変化させたものです.
CTS がHighからLowに落ちることにより genpowerd が電源異常を感知しシャットダウンを開始する様子と、CTS がHighに復帰することで先のシャットダウンを取り消して THE POWER IS BACK-02 のメッセージを出している様子が見れます.

# gentest -r -d /dev/UPS
---------------
DTR = Set
RTS = Set

CAR = High  (*)
CTS = High  (*)
DSR = High  (*)
RNG = Low   ( )
---------------
DTR = Set
RTS = Set

CAR = High  ( )
CTS = Low   (*)   <== 停電
DSR = High  ( )
RNG = Low   ( )

Broadcast message from root (console) Sun Jan 20 21:30:40 2002...

THE POWER IS DOWN! SHUTTING DOWN SYSTEM! PLEASE LOG OFF NOW!
The system is going DOWN for system halt in 15 minutes !!
---------------
DTR = Set
RTS = Set

CAR = High  ( )
CTS = Low   ( )
DSR = High  ( )
RNG = High  (*)
---------------
DTR = Set
RTS = Set

CAR = High  ( )
CTS = High  (*)   <== 電源復帰
DSR = High  ( )
RNG = Low   (*)

Broadcast message from root (console) Sun Jan 20 21:30:49 2002...

THE POWER IS BACK-02
TOPに戻る

======= 6)起動時のUPS接続確認の章 =========================

普段、パソコンがUPSから電源の供給を受け、監視用のケーブルがUPSに接続されていれば別段問題はないのですが、第3章の設定のままでは、メンテナンスなどで他の電源に接続し監視用のケーブルを取り外して起動すると、起動直後にシャットダウンが開始されてしまいます.

これには、いささか抵抗を感じます. まあ、root でログインして2分以内に shutdown -c を実行すればいいのですがちょっと情けない気がします.

そこで、rc.local で genpowerd を起動する前に監視用のケーブルが接続されているかどうかを確認後、ケーブルが接続されている時だけ genpowerd を起動する事とします.

まず、監視用のケーブルが接続されていない状態を gentest で調べてみます.

    # gentest -d -r /dev/UPS
    ---------------
    DTR = Set
    RTS = Set

    CAR = Low   ( )
    CTS = Low   ( )
    DSR = Low   ( )
    RNG = Low   ( )
すべての信号線が Low となってます. この中で CTS をチェックするプログラム genchk.c を作成しました.
BX50XFVが正常に動作しておれば、CTS は High であり、停電時は Low となります. しかし、パソコンが起動している事を考えれば停電では無いと確信できる訳です. そこでパソコンが起動しているにも関わらず CTS が Low である事は監視ケーブルが外れているものと認識します.
しかし、本番環境であってもケーブルが外れたままでもパソコンが起動してしまいますので起動後に genpowerd が起動している事を確認する注意が必要です.

このプログラムは、CTS が High ならば "OK" を、そうでなければ "ERR" を標準出力へ出力します.

プログラム genchk.c

    #include <sys/types.h>
    #include <sys/ioctl.h>
    #include <fcntl.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <stdio.h>
    #include <string.h>
    #include <signal.h>

    /* Main program. */
    int main( int argc, char **argv )  {

        int fd;
        int rts_bit = TIOCM_RTS;
        int dtr_bit = TIOCM_DTR;
        int flags;
        int flags2;

        /*************************/
        /* Monitor the CTS line. */
        /*************************/

        /* Open monitor device. */
        if ( ( fd = open( argv[1], O_RDWR | O_NDELAY ) ) < 0 )  {
            fprintf( stderr, "%s: Open Error\n", argv[1] );
            printf( "ERR\n" );
            exit( 1 );
        }

        ioctl( fd, TIOCMBIS, &rts_bit );
        ioctl( fd, TIOCMBIS, &dtr_bit );
        sleep( 2 );

        /* Get the CTS status. */
        ioctl( fd, TIOCMGET, &flags );
        flags &= TIOCM_CTS;
        ioctl( fd, TIOCMGET, &flags2 );
        flags2 &= TIOCM_CTS;

        if ( flags && flags2 )  {
            printf( "OK\n" );
            exit( 0 );
        }
        printf( "ERR\n" );
        exit( 1 );
    }
コンパイル・インストール
    % gcc  -O  -o genchk  genchk.c
    % su                             <== root 権限に
    # cp  -p  genchk /sbin/
    # chown  root.root  /sbin/genchk
    # chmod  754  /sbin/genchk
/etc/rc.d/rc.local の変更

今までの設定を下記のように置き換えます.
genchk から OK が返ってきた場合のみ、genpowerd を起動します.

    # ADD support for the BX50XFV
    echo "Starting genpowerd daemon..."
    if [ -x /sbin/genpowerd ]; then
        if [ -x /sbin/genchk ]; then
            genstat=`/sbin/genchk /dev/UPS`
            if [ $genstat = "OK" ]; then
                /sbin/genpowerd /dev/UPS omron-powli
            fi
        fi
    fi
TOPに戻る

======= 7)RedHat 7.3 対応の章 ================================

今年(2003年)の正月休みを利用して各システムを RedHat 7.3 へ移行しました.

RedHat 7.3 への移行にあたり、前章での内容はそのまま使用できます.
従来同様、無事稼動しております.

ここでは、RedHat 7.3 への移行にあたり、genpowerd 等を RedHat 7.3 の環境で再コンパイル・インストール時の警告などの解消方法について記述します.

コンパイル時に、若干の警告と、インストール時に man8 のディレクトリが無いと文句を言われます. まあ、実際の動作には影響ないのですが・・・

この現象は、内容からして RedHat 7.1 の時代からあったものと思います. つまり、筆者がこのページへ書き忘れていただけのようです.

コンパイル時の警告は、strcmp と strcpy 関数用のプロトタイプ宣言が無いために生じるものです.
下記のように、genpowerd.c と gentest.c に #include <string.h> を追加します.

genpowerd.c

#include <signal.h>
#include <syslog.h>
#include <string.h>
#include "genpowerd.h"
gentest.c
#include <stdio.h>
#include <signal.h>
#include <string.h>

#define MAXSTRING 10
次に、インストール時の man8 のディレクトリは、下記のように Makefile を修正します.

Makefile

SCRIPTDIR   = /etc
MANDIR      = /usr/share/man/man8
OWNER       = root
TOPに戻る

======= 8)RedHat 8 対応の章 ================================

故あって、RedHat 8 でも UPS を使用する事となってしまいました.
RedHat 7.3 で無事コンパイルが完了しているので RedHat 8 でも問題なかろうと安易に考えていたのですが、コンパイラはしっかりと警告を出してくれました(笑).

$ make
cc -N -Wall -O6 genpowerd.c -o genpowerd
/tmp/ccvcKK0D.o: In function `main':
/tmp/ccvcKK0D.o(.text+0x421): `sys_errlist' is deprecated; use `strerror' or `strerror_r' instead
cc -N -Wall -O6 gentest.c -o gentest
/tmp/cc8izhey.o: In function `main':
/tmp/cc8izhey.o(.text+0x225): `sys_errlist' is deprecated; use `strerror' or `strerror_r' instead
genpowerd.c と gentest.c で sys_errlist を使っているのが気に入らなくて、strerror か strerror_r を使えと言っているようです.

RedHat 7.3 の修正に加えて、genpowerd.c で2箇所、gentest.c で1箇所を下記のように修正します.

genpowerd.c

if (pups->killtime) {
    if ((fd = open(argv[1], O_RDWR | O_NDELAY)) < 0) {
        fprintf(stderr, "%s: %s: %s\n",program_name, argv[1], strerror(errno));
        exit(1);
    }    /* if ((fd = open(argv[1], O_RDWR | O_NDELAY)) < 0) */


/* Open monitor device. */
if ((fd = open(argv[1], O_RDWR | O_NDELAY)) < 0) {
    syslog(LOG_ERR, "%s: %s", argv[1], strerror(errno));
    closelog();
    exit(1);
}    /* if ((fd = open(argv[1], O_RDWR | O_NDELAY)) < 0) */
gentest.c
/* Open monitor device. */
if ((fd = open(argv[1], O_RDWR | O_NDELAY)) < 0) {
    fprintf(stderr, "%s: %s", argv[1], strerror(errno));
    exit(1);
}    /* if ((fd = open(argv[1], O_RDWR | O_NDELAY)) < 0) */
これで無事コンパイルが通ります. これ以外は、RedHat 7.1j, 7.3 と同様です.

TOPに戻る



参考資料
UPS(無停電電源装置)を接続する
仙台電波高専熊谷研究室さん
OMRON BX50XFV 取扱説明書


mailto
無線LAN・家庭内LAN - All About [LAN]