カテゴリ
リンク

ご迷惑をおかけします。以前の記事とリンクが切れています。ただいま修復中です。
当サイトは、玄箱PRO (KURO-BOX/Pro)を中心とした組み込み、Linuxと電子工作を扱っています。
会社案内

情報セキュリティおよび個人情報の取り扱いについて


コメントとトラックバックは、spamを予防するために、編集担当が公開の作業をするまで非公開になっています。コメントはそれぞれ投稿した人のものです。

 前回はハードウェアと全体の構成について説明しました。引き続き、ソフトウェアを説明していきます。

◆動作させるためのプログラム

 ディスプレイにニュースのヘッドラインが流れると、いっそう「電光掲示板」らしくなってきます。そこで、常に最新のヘッドラインを入手するため、ニュース・ サイト(ホームページ)からデータをもらってくることにしました。XPort に文字列データを送り込むためのプログラムも作成しておきます。
 使用した VFD は、キャラクタ・ジェネレータを内蔵しており、VFD に文字コードを送り付けるだけで表示ができます。また、特段の文字コード変換も不要で、これはラッキーでした。

全体をコントロールするスクリプト
 表示用データを持って来るサイトは任意でよいのですが、ヘッドラインとして文字列を切り出しやすいことを重視して、http://www.asahi.com/を選択しました。ヘッドラインの末尾に掲載された時間の文字列があるので、たとえば"(16:23)"、それを目安として直前の1行を切り出してきます(サイトのリニューアルによって変わることがあるので注意)。
 希望するサイトのページからコンテンツ(ソース)を得るには wget コマンドを利用しますので、インストールしておいてください。また、nkf も利用します。下に示したスクリプトを起動することで、一連のタスクが実行されます。なお、ここでは XPort へ付与する IP アドレスを 192.168.1.22 としています。このスクリプト名は control.bsh で、これが最上位スクリプトです。
#! /bin/sh

vfd=192.168.1.22
xport=/home/k-wada/program/xport/xport
file=/home/k-wada/program/xport/msg.dat
disp=/home/k-wada/program/xport/disp-asahi.bsh

t=0
$disp

while true
do
	while read message
	do
	if /bin/ping -c 1 -i 1 $vfd 2>&1 > /dev/null
	then
		echo "$message                                    " | $xport -h $vfd
	else
		echo "Networnk Error!"
    fi
	sleep 10
	t=`expr $t + 1 `
	echo $t
	if [ $t -eq 60 ]
	then
		t=0
		echo "GET!"
		$disp	
	fi
	done < $file
done

上記において、
echo "$message                                    " | $xport -h $vfd
 という部分の空白(スペース)は、一つのニュース項目(1ライン)を表示した後、その1ラインの後ろに空白部を置き、一つのニュース項目の終了をはっきりさせるために必要でした。この空白によって1ライン分のニュース文字列が完全に表示し終わった後、次のニュース項目の表示が始まります。

HTMLソースから文字列を抜き出す
 こちらのスクリプト(disp-asahi.bsh)は、サイトのページ(ソース・ファイル)より、"更新"というキーワードから更新時間を、また、()内の時間表記を頼りに、ニュース・ヘッドラインを抽出しています。
#! /bin/sh
# 2006.7.1

wget="/usr/bin/wget"
msg="/home/k-wada/program/xport/msg.dat"
nkf="/usr/bin/nkf"
awk="/usr/bin/awk"

index="/home/k-wada/program/xport/index.html"
rm -rf $index
$wget -O $index  http://www.asahi.com/

cat $index | $awk '/\更\新/'| $awk 'gsub("

", " ") {print "<<<<< "$1" >>>>>"}' | $nkf -s > $msg cat $index | $awk '/([0-9][0-9]:[0-9][0-9])/' | $awk 'gsub(">", " ") gsub("<", " ") {print $3$4$7}' | $awk '/([0-9][0-9]:[0-9][0-9])/' | $awk 'gsub("/a", " ")' | $nkf -s | sed "s/\\\\/\\\\\\\\/g" >> $msg


 以下は XPort とのインターフェース用プログラムで、C言語で書いています。

XPort にデータを送り込む
 C言語で書いたプログラムで、XPort にコネクションを張って、シリアル・ポートに VFD への制御コードと表示用の文字列データ送り込むものです。このソースの記述の中に、VFD の表示モードの指定やスクロール速度の指定などがあります。
 詳細を知りたい方は、「ノリタケ伊勢電子」のサイトから GU256X16M-3900 の仕様書をダウンロードしてください。複数の XPort を使用する場合、そのIP アドレスの指定は上位のスクリプト内で指定することになります。
/*
 * XPort program 2008.4
 */ 

#include 
#include 
#include 
#include 
#include 
#include 
#include 

#include 

#define     SVR_HOSTNAME    "localhost"
#define     SVR_PORT        14000    /* port for XPort */

#define     OPT_HOSTNAME    0x01
#define     OPT_PORT        0x02
/*#define   OPT_XPORT       0x04*/
#define     OPT_VERBOSE     0x08
#define     OPT_CONFIG      0x10    /* configuration confirm */
#define     OPT_WRITE       0x20    /* write active/unactive */
#define     OPT_READ        0x40    /* read port status */
#define     OPT_READSIMPLE  0x80    /* read port status (extra) */

#define     CP1             0x00010000;    /* XPort CP1 */
#define     CP2             0x00020000;    /* XPort CP2 */
#define     CP3             0x00040000;    /* XPort CP3 */

#define     XPORT_CONFIG        0x01    /* check configuration status */
#define     XPORT_WRITE         0x02    /* write port */
#define     XPORT_READ          0x03    /* read port */
#define     XPORT_SAVEAPPLET    0x04    /* Java Applet save */
#define     XPORT_LOADAPPLET    0x05    /* Java Applet load */

FILE *fp;

char tmp[1024];

void verbose(pre, buf, len)
char *pre, *buf;
int len;
{
    int n = 0;

    printf("%s: ", pre);
    while(n < len){
        printf("%02X ", 0x0ff & *(buf+n));
        n++;
    }
    putchar('\n');
}

/*
 * xport_readconfig -- 設定状態の確認
 *
 * args:
 *  sock    ソケット
 *  buf        保存先
 * ret:
 *  == -1    エラー
 *  != -1    正常終了(読み込んだバイト数)
 */
int xport_readconfig(sock, buf)
int sock;
char *buf;
{
    int l;
    char ch = XPORT_CONFIG;

    /* 設定状態確認コマンドを発行 */
    if(write(sock, &ch, 1) < 1)
        return -1;

    /* 設定状態の読み込み */
    if((l = read(sock, buf, 5)) < 5)
        return -1;

    return l;
}

/*
 * xport_read -- 汎用ポートの状態読み込み
 *
 * args:
 *  sock    ソケット
 *  buf        保存先
 * ret:
 *  == -1    エラー
 *  != -1    正常終了(読み込んだバイト数)
 */
int xport_read(sock, buf)
int sock;
char *buf;
{
    int l;
    char ch = XPORT_READ;

    /* 汎用ポート状態確認コマンドを発行 */
    if(write(sock, &ch, 1) < 1)
        return -1;

    /* 汎用ポート状態の読み込み */
    if((l = read(sock, buf,2)) < 2)
        return -1;

    return l;
}

/*
 * xport_write -- ポートの状態書き込み
 */
int xport_write(sock)
int sock;
{
  char buff[1024];
  int i;
  char tmp[1];
  char cmd[] = {0x1b, 0x40,   // イニシャライズ
                0x1f, 0x28, 0x67, 0x1, 0x2, // フォントサイズ
                0x1f, 0x28, 0x67, 0x2, 0x1, // 2バイトコード
                0x1b, 0x74, 0x1, //カタカナ
                0x1f, 0x1,       //オーバライド
                0x1f, 0x24, 0x0, 0x0, 0x0, 0x0, //カーソルセット
                0xc,  //画面クリア
                0x1f, 0x28, 0x67, 0x40, 0x1, 0x1, //キャラクタ拡大
                };


  char cmd2[] = {0x1b, 0x40,   // イニシャライズ
                0x1f, 0x58, 0x02, // 輝度 50%
                0x1f, 0x28, 0x67, 0x1, 0x2, // フォントサイズ
                0x1f, 0x28, 0x67, 0x2, 0x1, // 2バイトコード
                0x1b, 0x74, 0x1, //カタカナ
                0x1f, 0x1,       //オーバライド
                0xc,  //画面クリア
                0x1f, 0x28, 0x67, 0x40, 0x1, 0x1, //キャラクタ拡大
                0x1f, 0x28, 0x61, 0x10, 0x4, 0x0, 0x0, 0x0, 0x1, //スクロール表示指定
                0x1f, 0x03, // 横スクロールモード
                0x1f, 0x73, 0x02, // スクロール速度
                0x1f, 0x6d, 0x01, // スクロール品質(高)
                0x1f, 0x24, 0xfe, 0x0, 0x0, 0x0, // カーソルをセット
                };
  write(sock, cmd2, sizeof(cmd2));
  gets(buff);
  write(sock, buff, strlen(buff));

  return(0);
}


usage()
{
    printf("usage: xport [-crR] [-h hostname] [-p port] [-w#={0|1} ...]\n");
    exit(0);
}

main(argc, argv)
int argc;
char *argv[];
{
int ii;
    int ret = 255;                  /* return value */
    int ch, d, n, len;
    int flag = OPT_READSIMPLE;      /* フラグ */
    int sock;                       /* ソケット */
    int port;                       /* ポート番号 */
    int xport[] = {-1, -1, -1, -1}; /* ライト用XPortポート配列 */
    char *p;
    char cliname[BUFSIZ];           /* 自ホスト名格納用 */
    char svrname[BUFSIZ];           /* サーバ名格納用 */
    char str[16];                   /* メッセージバッファ */
    char msg[BUFSIZ];               /* メッセージ表示用 */
    char data[BUFSIZ];              /* データバッファ用 */
    struct hostent *host;           /* サーバ用ホスト構造体 */
    struct sockaddr_in svr;         /* サーバの情報 */
    struct sockaddr_in cli;         /* クライアントの情報 */
    struct in_addr tmp_ip;


    while((ch = getopt(argc, argv, "ch:p:w:rv")) != -1){
        switch(ch){
        case 'c':        /* read XPort configuration */
            flag |= OPT_CONFIG;
            break;

        case 'p':        /* port number */
            port = atoi(optarg);
            flag |= OPT_PORT;
            break;

        case 'h':        /* server name */
            len = strlen(optarg);
            len = (len > BUFSIZ-1) ? BUFSIZ-1 : len;
             strncpy(svrname, optarg, len+1);    /* copy whole null termination */
            flag |= OPT_HOSTNAME;
            break;

        case 'r':        /* read XPort */
            flag |= OPT_READ;
            break;

        case 'R':        /* read XPort extra */
            flag |= OPT_READSIMPLE;
            break;

        case 'w':        /* output to port */
            if(isdigit(optarg[0]) && optarg[1] == '='
                        && isdigit(optarg[2])){
                /* XPort No. (CP1~3) */
                n = optarg[0] - '0';
                n = (n < 1 || n > 3) ? 1 : n;

                /* switch */
                xport[n] = (atoi(optarg+2)) ? 1 : 0;
                flag |= (0x00010000 << n) | OPT_WRITE;
            }
            break;

        case 'v':        /* verbose mode */
            flag |= OPT_VERBOSE;
            break;

        case '?':
        default:
            usage();
        }
    }
    argc -= optind;
    argv += optind;


    /* ソケットアドレス構造体のクリア */
    bzero(&svr, sizeof(svr));

    /* サーバのホスト情報の取得 */
    if(flag & OPT_HOSTNAME){
        p = svrname;
    }else{
        p = SVR_HOSTNAME;
    }
    host = gethostbyname(p);

    /* アドレスファミリの設定 */
    svr.sin_family = AF_INET;

    /* サーバのIPアドレスをソケットアドレス構造体にセットする */
    bcopy(host->h_addr, &svr.sin_addr, host->h_length);

    /* アドレスファミリの設定 */
    svr.sin_family = host->h_addrtype;    /* AF_INET */

    /* 接続ポート番号の設定 */
    if(!(flag & OPT_PORT)){
        port = SVR_PORT;
    }
    svr.sin_port = htons(port);

    /* ソケットの作成 */
    if((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0){
        perror("Error: can't create socket.");
    }

    /* 自ホスト名の取得 */
    gethostname(cliname, sizeof(cliname));

    /* ソケット構造体の初期化 */
    bzero(&cli, sizeof(cli));

    /* インタフェースが複数あるホストの場合、
                    どちらのインタフェースも特定しないためのアドレス */
    cli.sin_addr.s_addr = INADDR_ANY;

    /* クライアントをシステムに登録する */
    if(bind(sock, (struct sockaddr *)&cli, sizeof(cli)) < 0){
        perror("Error: can't create bind.");
    }


    /* サーバへ接続する */
    if(connect(sock, (struct sockaddr *)&svr, sizeof(svr)) < 0){
        perror("Error: can't create connect");
    }

    xport_write(sock);

exit:
    /* 通信が終了したらソケットを解放する */
    close( sock );
    exit(0);
}



  これをコンパイルしておきます。必要なプログラムをまとめておきましたので、xport-vfd.tarをダウンロードしてお使いください。Makefile が用意されています。
xport.c             Xport へのインターフェース・プログラム
xport.o             オブジェクト
xport*              実行ファイル
Makefile            Make 用
control.bsh*        上位ファイル(これを起動する)
disp-asahi.bsh*     下位ファイル(上記から起動される)
index.html          ニュースサイトから wget されたソース・ファイル
msg.dat             VFD 用に加工された文字列データ

XPort にパラメータをセットする
 XPort Installer を利用して必要なパラメータをセットしますが、こちらの様子を三つのスナップでお見せします。
一番始めに XPort を見つけ出します。皆さんもこのようにプライベート・アドレスを利用されるのではないでしょうか。
 
x2XPort-setting-1.jpg  ネットワーク系の設定を行います。

x2XPort-setting-2.jpg
 I/O 系の設定をします。シリアル部分のパラメータを確認しておいてください。

x2XPort-setting-3.jpg

◆玄箱からいろいろな表示をさせて楽しむ

 要するにホームページ上にある文字データであればコンテンツとして表示が可能です。そこで、皆さんの興味に合わせてデータを引っ張り、加工して表示させてみてください。
 http://www.linkage-club.co.jp/ExamInfo&Data/toeic.htmのような場所には英単語データがありますし、天気予報のサイトから情報を持ってくるのも面白いと思います(画像データの場合には、そのファイル名に合わせて文字列変換を行えばよいでしょう)。

◆さて、次回は?

 XPort には3本の汎用 I/O 端子があります。本数は少ないですが、いろいろと面白く活用している人がいます。たった1本の入力でも、たとえば、鑑賞植物の土壌に水分がなくなったことを検出して、携帯電話にメールするようなことをしている記事も見掛けました。
 下は LED 点灯を実験中の写真です。オンとオフだけはできるようになりましたので、次回はこのあたりの話しをしましょう。

x2smallP1040341.jpg
x2smallP1040345.jpg
<和田 好司>

 カテゴリ

トラックバック(0)

このブログ記事を参照しているブログ一覧: XPort活用 「その1」《電工掲示板編》(後編)

このブログ記事に対するトラックバックURL: http://www.eleki-jack.com/mt/mt-tb.cgi/1512

コメントする

おすすめ書籍
Powered by
Movable Type Publishing Platform 4.0