2026年2月19日木曜日

AIと相談してコレクタで、古いPCのリナックスサーバーに方向検知をRFID読み取りで記録してみた


簡単にRFIDできるツールとして、マニカ コレクタがあります。

 https://www.hayato.info/collector.htm 

です。

前回は「プロセスを起動する」を使いましたが、今回は「Webサーバへ投げる」です。


「サーバへ投げる」のところで、
nec/cgi-bin/collect/add.cgi?PC=REUSE1&TAG=[タグID]&YYYYMMDD=[YYYYMMDD]&HHMMSS=[HHMMSS]&ANT=[アンテナNO]

を設定しました。(サーバーPCの名前は「nec」でPCのhostsに設定してあります。)


MANICAコレクタは、HTTPまたはHTTPSにてGETメソッドで送信することができます。

なので、送信先のWebサーバーに対して自分のPC名(PC=REUSE1)と、コレクタが置き換えてくれる値を設定します。

(引数の書き方はAIに相談すると教えてくれます。)


さらにAIに相談しました。

「会社には、もう古くなって誰も使わないWindows7のPCがあります。これをWebサーバーにしたいのですが良い案はありますか?」

と質問すると、

AIは「Ubuntu Linux(ウブンツ リナックス)」という無償ソフトに入れ替えればすれば快適にWebサーバーを作れます。」

と回答があったので試すことにしました。

ということで、「どうやってインストールするのですか?」「試したらこういうエラーになったのですが原因を推測できますか?」「なるほど、それを試して見ます!」ということを、繰り返していたら動くようになりました。


Webサーバーでは、

(1)HTTPでGETメソッドでデータを受け取ったら、受け取ったデータをテキストファイルに追記する。

(2)次に、その履歴データから最新の20行を抜き出す。

(3)次に、上記(2)のデータの秒単位の時刻経過とアンテナ番号とEPCを判断する。

(4)次に、上記(3)の方向検出データでhtmlファイルを書き換える。

(5)htmlファイルでは、ブラウザに対して、数秒置きに再度読み取らせる。

ということをしたいです。

と、AIに相談すると、かくかくしかじか推奨です。と回答してくれます。

上記の(5)についてはhtmlファイルにて

<head>
<meta charset="utf-8">
<meta http-equiv="Refreshcontent="1">
<title>LIST - MANICAコレクタ</title></head>
</head>

書けば、ほっておいても、PCではブラウザが読み直してくれるので、最新のデータを表示できます。

まぁ簡単!

上記(1)から(4)については、AIに質問して試してみて、巧く行かなかったらまたAIに質問して、を地道に繰り返します。

AIに相談してWebサーバーで動かすスクリプトも作成しました。


すると、できました!


左のウィンドウはMANICAコレクタのログ画面です。

右のウィンドウはWebブラウザで状況表示しています。

コレクタが読取ると、Webブラウザ画面にすぐに反映されています。


今は使っていない古いPCと、お金のかからないリナックス。

コレクタが動くPCと組み合わせて便利に使うことができました。


AIに相談して作った、Webサーバーで動かしたスクリプトも紹介しておきますね。

名前はadd.cgiです。

#!/usr/bin/perl
#@TOP マニカコレクタ用のCGI

#@使うモジュール
use CGI;
use Time::Piece;
use utf8;

#@ここから始まり。
my $qq = new CGI;
my($bContinue)=1;

#@EPCと製品名を紐づけるグローバル変数
my(%TagInfo)=(); # EPCと詳細情報を紐づけるデータ
$TagInfo{'000000000000000000000230'}="治具(一般的)";
$TagInfo{'000000000000000000000231'}="治具(その1)";
$TagInfo{'000000000000000000000232'}="治具(その2)";
$TagInfo{'000000000000000000000233'}="治具(その3)";
$TagInfo{'000000000000000000000234'}="治具(その4)";
$TagInfo{'000000000000000000000235'}="治具(その5)";
$TagInfo{'000000000000000000000000'}="治具(一般的)";

#@エラーログを開く
open $efh, '>> ', "error.txt" ; # エラーログを開く
flock($efh,2) or die; # Ubuntu Linuxだと、ブロックされて待ちになるな、、。
print $efh "start. ----------\n"; # エラーログに追加

#@データファイルを開き、http通信で受け取ったデータ記録する。
my($fh);
my($pf_name)=sprintf("log.txt");
if($bContinue){
    open $fh, '>> ', $pf_name ;
    flock($fh,2) or die; # Ubuntu Linuxだと、ブロックされて待ちになるな、、。
}

if($bContinue){ #@受け取ったデータを記録する。
    # PC,ANT,YYYYMMDD,HHMMSS,TAG
    print $fh $qq->param("PC").",";
    print $fh $qq->param("ANT").",";
    print $fh $qq->param("YYYYMMDD").",";
    print $fh $qq->param("HHMMSS").",";
    print $fh $qq->param("TAG")."\n";
    close $fh; #閉じる。
}

#@データを記録するグローバル変数配列を宣言する。
my(@aPC)=();
my(@aANT)=();
my(@aYYYYMMDD)=();
my(@aHHMMSS)=();
my(@aTAG)=();
my(@aMove)=(); #移動方向を記録する。

#@データを記録する
if($bContinue){
    $/ = undef;
    my($tmpFName)="tmp.$$.txt"; #print $efh "tmpf=".$tmpFName."\n";
    system("tac ".$pf_name." | head -20 >$tmpFName"); #最新データをピックアップ。
    open $fh2, '< ', $tmpFName ;
    my($buf)=<$fh2>;
    close $fh2;
    unlink($tmpFName);
    
    my(@aBuf)=split(/\n/,$buf);
    for (my $m=0; $m < @aBuf; $m++ ){ #行単位
	my(@aLine)=split(/,/,$aBuf[$m]); #カンマ区切り単位
	push(@aPC,$aLine[0]);
	push(@aANT,$aLine[1]);
	push(@aYYYYMMDD,$aLine[2]);
	push(@aHHMMSS,$aLine[3]);
	push(@aTAG,$aLine[4]);
	push(@aMove," "); #数を合わせるため、空行を入れる。
    }
}

#@記録されたデータから、移動方向を判断する。
if($bContinue){
    my $aNum=@aPC; #print $efh "aNum=".$aNum."\n";
    if ( $aNum == 0 ) {
	# データが空っぽならNOP
    }
    else{
	for(my $m=0; $m < $aNum; $m++){ #print $efh '$m='.$m."\n";
	    if($m == ($aNum -1)){
		# 最後のデータは、ひとつ後の行とは差分をとれない。	    }
	    }
	    else{ # PCがどこなのか、今のところチェックしない。
		#直近の同じEPCのタグを探す。見つからない可能性はある。
		#print $efh "m=".$m.":";
		my($mm)=0;
		for($mm=$m+1; $mm < ($aNum-1); $mm++){ # $mmを設定。
		    if($aTAG[$m] eq $aTAG[$mm]){
			#print $efh "aNum=".$aNum.":TAG ID HIT. mm=".$mm.":[".$aTAG[$m]."][".$aTAG[$mm]."] last\n";
			last;
		    }
		}
		#print $efh " mm=".$mm."\n";
		if($aTAG[$m] eq $aTAG[$mm]){ # タグのIDは同じか?
		    #print $efh "[".$aYYYYMMDD[$m].$aHHMMSS[$m]."][".$aYYYYMMDD[$mm].$aHHMMSS[$mm]."]\n";
		    my $t  = Time::Piece->strptime($aYYYYMMDD[$m].$aHHMMSS[$m],     '%Y%m%d%H%M%S');
		    my $t2 = Time::Piece->strptime($aYYYYMMDD[$mm].$aHHMMSS[$mm], '%Y%m%d%H%M%S');
		    my $diff = $t - $t2;

		    #print $efh "[".$aYYYYMMDD[$m].$aHHMMSS[$m]."][".$aYYYYMMDD[$mm].$aHHMMSS[$mm]."]\n";
		    #print $efh "diff sec = ".$diff->seconds."\n";
		    if ($diff->seconds < 20){ # 間隔の最大値は、この秒数とする。
		     	if($aANT[$m] eq $aANT[$mm]){ #print $efh "移動なし"."\n";
			    $aMove[$m]="移動なし";
		     	}
		     	elsif($aANT[$m] eq "1"){ #print $efh "持ち込み"."\n";
			    $aMove[$m]="持ち込み";
		     	}
		     	elsif($aANT[$m] eq "2"){ #print $efh "持ち出し"."\n";
			    $aMove[$m]="持ち出し";
		     	 }
		     	else{ #print $efh "空間転移"."\n";
			    $aMove[$m]="空間転移";
		     	}
		    }
		    else{#print $efh "タイムアウト"."\n";
			$aMove[$m]="";
		    }
		}
	    }
	}
    }
}

#@htmlのテーブル部分を作成する。
my($tableStr)=""; #@テーブル部分を作成する。
if($bContinue){
    my $aNum=@aPC; #print $efh "aNum=".$aNum."\n";
    if ( $aNum == 0 ) {
	# データが空っぽならNOP
    }
    else{
	$tableStr="";
	$tableStr .= '<table border="1">'."\n";;
	$tableStr .= "<tr><th>移動方向</th><th>年月日</th><th>時分秒</th>";
	$tableStr .= "<th>読取PC</th><th>アンテナ</th><th>EPC</th><th>タグ情報</th></tr>\n";
	for(my $m=0; $m < $aNum; $m++){ #print $efh '$m='.$m."\n";
	    $tableStr .= "<tr>";
	    $tableStr .= "<td>".$aMove[$m]."</td>";
	    $tableStr .= "<td>".$aYYYYMMDD[$m]."</td>";
	    $tableStr .= "<td>".$aHHMMSS[$m]."</td>";
	    $tableStr .= "<td>".$aPC[$m]."</td>";
	    $tableStr .= "<td>".$aANT[$m]."</td>";
	    $tableStr .= "<td>".$aTAG[$m]."</td>";
	    if ( exists($TagInfo{$aTAG[$m]}) ){
		$tableStr .= "<td>".$TagInfo{$aTAG[$m]}."</td>";
	    }
	    else{
		$tableStr .= "<td>"."未登録タグ"."</td>";
	    }
	    $tableStr .= "</tr>\n";
	}
	$tableStr .= '</table>';
    }
}

#@htmlファイルを更新する。
my($htmlStr)=""; #@html全体を作ってhtmlファイルを更新する。
if($bContinue){
    my($t)=1; # htmlファイルの再読み込み間隔秒
    $htmlStr = $htmlStr. "<html>\n";
    $htmlStr = $htmlStr. "<head>\n";
    $htmlStr = $htmlStr. '<meta charset="utf-8">'."\n";
    $htmlStr = $htmlStr. "<meta http-equiv=\"Refresh\" content=\"$t\">"."\n";
    $htmlStr = $htmlStr. "<title>LIST - MANICAコレクタ</title></head>\n";
    $htmlStr = $htmlStr. "</head>\n";
    $htmlStr = $htmlStr. "<body>\n";
    $htmlStr = $htmlStr. '<h1>MANINCAコレクタ 方向検出の最新読取情報</h1>';
    $htmlStr = $htmlStr. "最新のデータが".$t."秒ごとに再度読み込みされます。"."\n";
    $htmlStr = $htmlStr. "<hr>\n";
    $htmlStr = $htmlStr.$tableStr."<br>\n";
    $htmlStr = $htmlStr. "<hr>\n";
    $htmlStr = $htmlStr. "</body>\n";
    $htmlStr = $htmlStr. "</html>\n";

    my($fhHtml);
    open $fhHtml, '> ', '/var/www/html/collect/direct.html' ;
    flock($fhHtml,2) or die; # Ubuntu Linuxだと、ブロックされて待ちになるな、、。
    print $fhHtml $htmlStr;
    close $fhHtml;
}

#@エラーログを閉じる。
print $efh "end. ----------\n"; # ログファイルに追加
close $efh; # エラーログを閉じる

#@呼び出すPCが判断できるように応答を返す。
#もし応答しないと、コレクタはWebサーバーの内部障害として認識する。
print "Content-Type: text/html\n\n";
print "<html><head><title>response</title></head>\n";
print "<body>\n";
print "OK\n";
print "</body>\n";
print "</html>\n";

1;

以上です。


0 件のコメント:

コメントを投稿