raspberryPIでWEBからの指令でルーターにコマンドを送るシステム

0

    前のraspberryPI関連の記事でsshでログインしてパイプを使って制御コマンドの送受信を行う部分を作成しました。
    今回はそれをWEBから制御する部分を書きます。
    前の記事は
     http://miha.jugem.cc/?eid=127

    今回のはちょっと難しい。
    肝になるのは前回作ったraspberryPiからルーターを制御して結果を取得する部分なんだけど、
    それと、ずっと前に作った
    WEB画面からの制御で100Vの電灯をON/OFFする記事
     http://miha.jugem.cc/?eid=105
    のWEB制御による遠隔システムを組み合わせる。

    システム構成

    システム構成

    このシステムの利点はraspberryPiを相手先のプライベートネットワークへ置かせてもらう事によって、
    ちょっと難しいルーター設定を拠点へ行かなくても遠隔でメンテナンスが可能になる事です。
    拠点にインターネットに接続できる環境さえあれば実施可能でハードルは低いように思えます。

    プログラムの一覧と簡単な解説
    構成図の右上から順番に行きます。
    拡張子.cgiはperlのプログラムです。ちなみに環境はMicrosoftAzureです。
    現時点でazureは標準ではperlをサポートしていませんが、
    perlの環境構築する記事は他にもありますが、
    自分なりに噛み砕いた記事をそのうち書きます。
    以下ではルーターと表現していますが、基本的にsshまたはtelnetでログイン可能なものは制御可能です。

    -1.edit.cgi
     ルーターのコマンドを登録する画面です。
     ルーターコマンドのだけでは制御が難しくてコマンド体系は以下の感じになっている
     コマンドは6種類でコロンを含めて7桁の英字です。
      ID  : ルーターにログインする為のユーザIDを指定
      PASS: ルーターにログインする為のパスワードを指定
      TEL : telnetでルーターにログイン
      SSH : sshでルーターにログイン
      TIME: WAITコマンドで何秒まで待つかを指定する
      WAIT: ルーターからの応答を待つ。指定した文字列が来るか、WAITで指定した時間経過するまで待つ
      SEND: ルーターへ送信するコマンド
     上記のコマンドを組み合わせたテキストを入力してOKをクリックする。

    -2.touroku.cgi
     edit.cgiから呼び出されて渡されたテキストの情報をサーバーに書き込む
    き.req.cgi
     raspberryPi側から呼び出されるCGIです
     最後にtouroku.cgiで書き込まれたテキストを返します。
    ΝЛweb-client-req-exec-result.c
     raspberryPiの中で動くプログラムです。c言語です。
     req.cgiで取得したコマンドをルーターに送信したり、一定時間待ったり、ルーターからの応答をWebサーバーへ送るプログラムです。
     結果をWebサーバーへ送る部分はresult.cgiを呼び出す。
    result.cgi
     raspberryPiから送信された結果をWebサーバーに書き込む
    control.cgi
     指示を出されたら一定間隔で呼び出される。というか自身でreloadしている。
     サーバーから最後の電文が来るとreloadは停止する。

    という感じで動きます。

    実際に動いているところ

    今回送信したコマンドはこちら。
     TIME:10
     ID  :none
     PASS:P@ssw0rd
     TEL :192.168.33.241
     TIME:30
     WAIT:c1812J>
     SEND:enable
     WAIT:assword:
     SEND:P@ssw0rd
     WAIT:c1812J#
     SEND:terminal length 0
     WAIT:c1812J#
     SEND:show run
     WAIT:c1812J#
     SEND:show ip interface brief
     WAIT:c1812J#
     SEND:configure  terminal
     WAIT:c1812J#
     SEND:interface FastEthernet1
     WAIT:c1812J(config-if)#
     SEND:ip address 192.168.20.254 255.255.255.0
     WAIT:c1812J(config-if)#
     SEND:no shutdown
     WAIT:c1812J(config-if)#
     SEND:end
     WAIT:c1812J#
     SEND:show ip interface brief
     WAIT:c1812J#
     SEND:exit
     TIME:3
     WAIT:%
    ciscoの1812Jに対してコマンドを送信します。
    実際のコマンド設定部分は
     「ip address 192.168.20.254 255.255.255.0」と「no shutdown」の所で、
     一回目の「show ip interface brief」でadministratively downになっていたFastEthernet0が
     二回目の「show ip interface brief」ではStatusがUPになってIPアドレスが設定されています。

    NW機器たち。上がYAMAHAのRTX1100。下がciscoの1812J
    ルーターやNW機器


    それとraspberryPI3
    raspberryPi3

    raspberryPIの所は前に公開した肝の部分にwebアクセスを追加したものなのでWebサーバー部分のプログラムを以下に掲載しておきます。
    ■■■■■■■■■■■
    ■edit.cgi
    ■■■■■■■■■■■
    use CGI;
    my $q = new CGI;
    $para1 = $q->param('para1');

    # HTML出力
    print "Content-type: text/html¥n¥n";
    print "<html>¥n";
    print "<head>¥n";
    print " <META http-equiv=Control content=no-cache>¥n";
    print " <META http-equiv=Pragma content=no-cache>¥n";
    print " <META http-equiv=Content-type content='text/html; charset=Shift_JIS'>¥n";
    print "<title>AgentSystem 編集</title>¥n";
    print "</head>¥n";
    print "<body>¥n";

    LockON();
    print("<hr>");
    print("<font size=+10>AgentSystem</font>");
    print("<hr>");
    print("編集<br>");
    print("<hr>");

    if(!open(request_file, "agent/request.dat")){
     EmergencyStop(1000);
    }

    print ("<form method=post action=touroku.cgi>");
    print (" <textarea name=set cols=40 rows=20>");
    while($InRec=<request_file>){
     $a = substr ($InRec , 0 , 5 );
     if($a eq "REQ :"){
      ;
     }
     else{
      print("$InRec");
     }
    }
    print (" </textarea>");
    print (" <input type=submit value=OK>");
    print ("</form>");
    close(request_file);


    LockOFF();

    # HTML出力
    print "</body>¥n";
    print "</html>¥n";

    exit;

    sub LockON
    {
     if(!open(LOCK, "> agent/LOCK")){
      EmergencyStop(1000);
     }
     flock(LOCK, 2);      
    }

    sub LockOFF
    {
     close(LOCK);
    }

    sub EmergencyStop
    {
     $line = $_[0];
     $Status = $_[0];
     
     if( $Status eq "0" ){
      
     }
     print "EmergencyStop($line)";
     
     exit( -1 );
    }

    sub SpaceCut
    {
     local($String) = @_;

     $String =~ s/ //g; #// 全角空白を削除
     $String =~ s/ //g; #// 半角空白を削除
     $String =~ s/¥n//g; #// enterを削除

     return ($String);
    }

    ■■■■■■■■■■■
    ■touroku.cgi
    ■■■■■■■■■■■
    use CGI;
    my $q = new CGI;
    $set = $q->param('set');

    # HTML出力
    print "Content-type: text/html¥n¥n";
    print "<html>¥n";
    print "<head>¥n";
    print " <META http-equiv=Control content=no-cache>¥n";
    print " <META http-equiv=Pragma content=no-cache>¥n";
    print " <META http-equiv=Content-type content='text/html; charset=Shift_JIS'>¥n";
    print " <meta http-equiv=refresh content='3 ; URL=control.cgi'>¥n";
    print "<title>AgentSystem 登録完了</title>¥n";
    print "</head>¥n";
    print "<body>¥n";

    LockON();

    print("<hr>");
    print("<font size=+10>AgentSystem</font>");
    print("<hr>");
    print("登録<br>");
    print("<hr>");

    ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
    my $yyyymmddhhmmss = sprintf("%04d%02d%02d%02d%02d%02d", $year + 1900, $mon + 1, $mday, $hour, $min, $sec);
    print ("REQ :$yyyymmddhhmmss<br>¥n");
    print ("<a href=control.cgi>戻る</a><br>¥n");

    if(!open(request, "> agent/request.dat")){
     EmergencyStop(1000);
    }

    print request "REQ :$yyyymmddhhmmss¥n";
    print request "$set";
    close(request);

    #resultファイルを初期化
    if(!open(result, "> agent/result.dat")){
     EmergencyStop(1000);
    }
    close(result);
    #doneファイルを初期化
    if(!open(done, "> agent/done.dat")){
     EmergencyStop(1000);
    }
    close(done);

    LockOFF();

    # HTML出力
    print "</body>¥n";
    print "</html>¥n";

    exit;

    sub LockON
    {
     if(!open(LOCK, "> agent/LOCK")){
      EmergencyStop(1000);
     }
     flock(LOCK, 2);      
    }

    sub LockOFF
    {
     close(LOCK);
    }

    sub EmergencyStop
    {
     $line = $_[0];
     $Status = $_[0];
     
     if( $Status eq "0" ){
      
     }
     print "EmergencyStop($line)";
     
     exit( -1 );
    }

    sub SpaceCut
    {
     local($String) = @_;

     $String =~ s/ //g; #// 全角空白を削除
     $String =~ s/ //g; #// 半角空白を削除
     $String =~ s/¥n//g; #// enterを削除

     return ($String);
    }

    ■■■■■■■■■■■
    ■req.cgi
    ■■■■■■■■■■■
    use CGI;
    my $q = new CGI;

    # HTML出力
    print "Content-type: text/plain¥n¥n";

    LockON();
    if(!open(request_file, "agent/request.dat")){
     EmergencyStop(1000);
    }
    while($InRec=<request_file>){
     print $InRec
    }
    close(request_file);

    if(!open(agent, "> agent/agent.dat")){
     EmergencyStop(1000);
    }

    @youbi = ('日', '月', '火', '水', '木', '金', '土');
    ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
    $year += 1900;
    $mon += 1;
    print agent "$year年$mon月$mday日($youbi[$wday]) $hour時$min分$sec秒¥n";
    close(agent);

    LockOFF();

    exit;

    sub LockON
    {
     if(!open(LOCK, "> agent/LOCK")){
      EmergencyStop(1000);
     }
     flock(LOCK, 2);      
    }

    sub LockOFF
    {
     close(LOCK);
    }

    sub SpaceCut
    {
     local($String) = @_;

     $String =~ s/ //g; #// 全角空白を削除
     $String =~ s/ //g; #// 半角空白を削除
     $String =~ s/¥n//g; #// enterを削除

     return ($String);
    }

    sub EmergencyStop
    {
     $line = $_[0];
     $Status = $_[0];
     
     if( $Status eq "0" ){
      
     }
     print "EmergencyStop($line)";
     
    }

    ■■■■■■■■■■■
    ■result.cgi
    ■■■■■■■■■■■
    use CGI;
    my $q = new CGI;

    $argc = $q->param('argc');
    $upload_flag = $q->param('flag');

    # HTML出力
    print "Content-type: text/plain¥n¥n";
    LockON();

    if($upload_flag eq "0"){
     if(!open(result, "> agent/result.dat")){
      EmergencyStop(1000);
     }
    }
    else{
     if(!open(result, ">> agent/result.dat")){
      EmergencyStop(1000);
     }
    }

    print "argc=$argc¥n";
    for ($count = 0; $count < $argc; $count++){
     $key = $count;
     my $read_line = $q->param("$key");
     print result "$read_line¥n";
     print "key=$key:read_line=$read_line¥n";
    }
    close(result);
    #
    if(!open(done, "> agent/done.dat")){
     EmergencyStop(1000);
    }
    if($upload_flag eq 0){
     print done "RUNNING...";
    }
    if($upload_flag eq 1){
     print done "RUNNING...";
    }
    if($upload_flag eq 2){
     print done "...DONE";
    }
    close(done);

    LockOFF();

    exit;

    sub LockON
    {
     if(!open(LOCK, "> agent/LOCK")){
      EmergencyStop(1000);
     }
     flock(LOCK, 2);      
    }

    sub LockOFF
    {
     close(LOCK);
    }

    sub EmergencyStop
    {
     $line = $_[0];
     $Status = $_[0];
     
     if( $Status eq "0" ){
      
     }
     print "EmergencyStop($line)";
     
     exit( -1 );
    }

    sub SpaceCut
    {
     local($String) = @_;

     $String =~ s/ //g; #// 全角空白を削除
     $String =~ s/ //g; #// 半角空白を削除
     $String =~ s/¥n//g; #// enterを削除

     return ($String);
    }

    ■■■■■■■■■■■
    ■control.cgi
    ■■■■■■■■■■■
    use CGI;
    my $q = new CGI;
    $para1 = $q->param('para1');

    if(!open(done_file, "agent/done.dat")){
     EmergencyStop(1000);
    }
    $DoneStr=<done_file>;
    close(done_file);

    # HTML出力
    print "Content-type: text/html¥n¥n";
    print "<html>¥n";
    print "<head>¥n";
    print " <META http-equiv=Control content=no-cache>¥n";
    print " <META http-equiv=Pragma content=no-cache>¥n";
    print " <META http-equiv=Content-type content='text/html; charset=Shift_JIS'>¥n";
    if( $DoneStr ne "...DONE" ){
     print " <meta http-equiv=Refresh content=5>¥n";
    }
    print "<title>AgentSystem</title>¥n";
    print "</head>¥n";
    print "<body>¥n";

    print("<hr>");
    print("<font size=+10>AgentSystem</font>");
    print("  <a href='edit.cgi'>編集</a>");
    print("<hr>");
    print("要求<br>");
    print("<hr>");

    LockON();
    if(!open(request_file, "agent/request.dat")){
     EmergencyStop(1000);
    }
    while($InRec=<request_file>){
     print $InRec;
     print("<br>");
    }
    close(request_file);

    printf("<hr>");
    print("結果<br>");
    printf("<hr>");
    printf("<xmp>");
    if(!open(request_file, "agent/result.dat")){
     EmergencyStop(1000);
    }
    while($InRec=<request_file>){
     print $InRec;
    }
    close(request_file);
    print $DoneStr;

    printf("</xmp>");
    printf("<hr>");
    print("Agent最終アクセス時間<br>");
    printf("<hr>");
    if(!open(agent_file, "agent/agent.dat")){
     EmergencyStop(1000);
    }
    while($InRec=<agent_file>){
     print $InRec;
    }
    close(agent_file);
    printf("<hr>");
    print("<a href='edit.cgi'>編集</a>");
    printf("<hr>");


    LockOFF();

    # HTML出力
    print "</body>¥n";
    print "</html>¥n";

    exit;

    sub LockON
    {
     if(!open(LOCK, "> agent/LOCK")){
      EmergencyStop(1000);
     }
     flock(LOCK, 2);      
    }

    sub LockOFF
    {
     close(LOCK);
    }

    sub EmergencyStop
    {
     $line = $_[0];
     $Status = $_[0];
     
     if( $Status eq "0" ){
      
     }
     print "EmergencyStop($line)";
     
     exit( -1 );
    }

    sub SpaceCut
    {
     local($String) = @_;

     $String =~ s/ //g; #// 全角空白を削除
     $String =~ s/ //g; #// 半角空白を削除
     $String =~ s/¥n//g; #// enterを削除

     return ($String);
    }


    スポンサーサイト

    0
      • 2019.10.22 Tuesday
      • -
      • 12:41
      • -
      • -
      • by スポンサードリンク


      PR

      calendar

      S M T W T F S
        12345
      6789101112
      13141516171819
      20212223242526
      2728293031  
      << October 2019 >>

      selected entries

      categories

      archives

      recent comment

      recent trackback

      profile

      search this site.

      others

      mobile

      qrcode

      powered

      無料ブログ作成サービス JUGEM