Socket Debugger

Luaスクリプト処理の作り方
Lua拡張について

 SocketDebuggerでは、通信処理をユーザが自由な仕様に従って
 テストが行えるよう、デフォルトの設定だけでは実現不可能な
 ビジネスロジックをLuaスクリプトにより実現することが可能です。

 例えば、ある通信伝文を受信した際に、その内容に応じた応答伝文を
 返したり、一定時間で複数の違うデータを送信したりすることができます。

 SocketDebuggerFree,SerialDebuggerも利用可能です。
Lua拡張の概要

 SocketDebuggerはLuaスクリプトで記述されたいくつかのイベントを
 状況により呼び出します。
 ユーザはその渡されたデータを判定し、用意された関数で通信などの
 アクションを起こすことが可能です。
 関数はユーザがDLLで作成することにより、用意された関数以外にも
  任意に追加することが可能です。


 スクリプト言語Luaのリファレンスは下記で検索してください。
 Google Lua 5.1 リファレンス 検索

 Luaスクリプトはポート1、ポート2それぞれに記述できます。
 それぞれの専用エディタから任意の処理を記述ください。
 プログラムは通信データとともに保存されますので
 別途ファイル保存等は必要ありません。
  スクリプト動作を実行するには「設定」−「通信設定」の
 任意ポートの「動作」から「スクリプト制御を行う」にチェックを付けてください。

SocketDebugger内Luaのイベントと関数

 SocketDebuggerで拡張した、イベントと関数について説明します。

 ■イベント一覧
 通信などの状況によりSocketDebugger本体から下記のLua関数が呼び出されます。
 ユーザは以下の関数内部を実装することにより任意のアクションが可能となります。

 OnConneted    通信接続(または開始)時に発生
 OnSendPush    送信ボタン押下時に発生
 OnTimer      タイマーイベント時に発生
 OnReceive     データ受信時に発生
 OnDisConnected  通信切断(または終了)時に発生

 ※UDP,COMの通信では接続/切断は開始/終了となります。

 ■関数一覧
 上記イベント関数内から呼び出し可能なSokcetDebuggerに指示を行う拡張関数です。

 Logput              ログ出力
 Disconnect          通信切断
 SetTimer            タイマー起動
 KillTimer           タイマー停止
 GetEditorData       送信エディタデータ取得
 SetEditorData       送信エディタデータ格納
 FileRead            ファイル読み込み
 FileWrite           ファイル書き込み
 SendData            データ送信
 BitOr               ビット演算 OR
 BitAnd              ビット演算 AND
 BitOff              ビット操作 OFF
 StringToTable      文字列からテーブル変換
 TableCat            テーブル同士の結合

 ■ユーザ関数
  ユーザは、SocketDebuggerの認識するLua命令追加処理をDLLで
  作成することにより、Luaスクリプトから呼び出す命令を追加することが可能です。
  本機能により、より複雑な仕様の実現や、専用関数を用いる処理との連携を持つことが
  可能となります。

  SocketDebuggerは、起動時にexeと同一フォルダにあるDLLを検索し対応DLLを読み込みます。
  読み込まれたDLL及び対応関数はバージョン情報ダイアログに表示されます。
  追加された命令は、Luaスクリプトエディタ上で、紫色で表示されます。

  本DLLの作成方法について、下記で説明します。
  Luaスクリプト用拡張DLLの作り方

イベント: 通信接続(または開始)
<<概要>>
TCP通信が確立した場合に発生します。
UDP/COM通信では、処理開始時に発生します。

OnConneted()

<<引数>>
無し

<< 戻り値 >>
0固定
イベント: 送信ボタン押下
<<概要>>
プログラム本体の「送信ボタン」を押下時に発生します。
シーケンスにユーザ任意のタイミングを作成したい場合に利用して下さい。

OnSendPush()

<<引数>>
無し

<<戻り値>>
0固定
イベント: タイマーイベント
<<概要>>
ユーザが起動したタイマーイベントにより発生します。

OnTimer(id)

<<引数>>
id(数値)        発生したタイマー番号
                0 or 1
                0:タイマー1
                1:タイマー2

<<戻り値>>
0固定
イベント: データ受信
<<概要>>
データ受信時に発生します。
COMは、通信設定した受信データ区切りにより発生を制御します。

OnReceive(recv)

<<引数>>
recv(テーブル)      受信データ

<<戻り値>>
0固定
イベント: 通信切断(または終了)
<< 概要 >>
TCPでは通信の切断時、
UDP,COMでは通信処理の終了時に発生します。

OnDisConnected()

<<引数>>
無し

<<戻り値>>
0固定

関数: ログ出力
<<概要>>
指定したコメント(文字列、数値)を通信ログに出力する。

Logput( number, string )
Logput( number, number )

<<引数>>
number(数値)        出力するログのカテゴリ番号
                    1:情報
                    2:注意
                    3:警告
                    上記以外を認識した場合、3:警告として扱う
string(文字列)      格納する文字列データ
number(数値)        格納する文字列データ

<<戻り値>>
無し

<<例>>
(1)
Logput( 1, "ABCDEFG" )
└文字列"ABCDEFG"を通信ログに追加する。

(2)
Logput( 1, 5.5 )
└数値"5.5"を通信ログに追加する。

<<備考>>
ログの内容が"パラメータエラー [1]"等となった場合は
パラメータに誤りがある。
数値の内容を下記に示す。
1:パラメータ個数エラー
2:カテゴリ数値取得エラー
3:データ部認識エラー
関数: 通信切断
<<概要>>
通信の切断を要求する。
(動作しているLuaイベント終了後に切断が行われる。)

Disconnect()

<<引数>>
無し

<<戻り値>>
無し
関数: タイマー起動
<<概要>>
指定したタイマーを起動する。
起動後は、指定したミリ秒でイベント"OnTimer(id)"が周期発生する。
idは起動時に指定したタイマー番号が入る。

result = SetTimer( id, cycle )
result = SetTimer( id, cycle, autooff )
result = SetTimer( cycle )

<<引数>>
id(数値)            タイマー番号
                    0:タイマー1
                    1:タイマー2
                    省略時はタイマー1として認識
cycle(数値)         タイマーイベント起動周期(ミリ秒)
                    1〜2147483647の範囲で指定可能
autooff(数値)       1回タイマー指定
                    0で指定なし。
                    0以外で1度イベント発生後、
                    自動停止するタイマーを起動する。

<<戻り値>>
数値                0:正常終了
                    (稼動中だった場合は指示が無視される)
                    1:パラメータエラー
                    2:パラメータ数値認識エラー

<<例>>
(1)
result = SetTimer( 0, 3000 )
└タイマー1を3秒周期で起動する。

(2)
result = SetTimer( 1, 5000, 1 )
└タイマー2を使い、5秒後に1度イベントを発生させる。
result = SetTimer( 1, 5000, 2 )
└上記でも発生は1度。

(3)
result = SetTimer( 3000 )
└省略時はタイマー1の指定となる。
関数: タイマー停止
<<概要>>
稼動中のタイマーを停止する。

result = KillTimer( id )
result = KillTimer()

<<引数>>
id(数値)            タイマー番号
                    0:タイマー1
                    1:タイマー2
                    省略時はタイマー1として認識

<<戻り値>>
数値                0:正常終了
                    (稼動中で無かったタイマーを指定しても正常が返る)
                    1:パラメータエラー
                    2:パラメータ数値認識エラー

<<例>>
(1)
result = KillTimer( 0 )
└タイマー1の停止

(1)
result = KillTimer()
└省略時はタイマー1の停止
関数: 送信エディタデータ取得
<<概要>>
送信エディタのデータを読み込み、テーブル配列に格納する。

result = GetEditorData()

<<引数>>
無し

<<戻り値>>
テーブル            送信エディタのデータ
数値                異常終了
                    1:パラメータエラー

<<例>>
result = GetEditorData()
└result(テーブル)に送信エディタのデータが格納される。
  エラー発生時はresultは数値型であり、エラーコードが格納される。
  送信エディタが空であった場合、resultは長さ0の配列となる。
関数: 送信エディタデータ格納
<<概要>>
送信エディタにデータを格納する。

result = SetEditorData( table )
result = SetEditorData( string )

<<引数>>
table(テーブル)     格納するバイナリデータ
string(文字列)      格納する文字列データ

<<戻り値>>
数値                0:正常終了
                    1:パラメータエラー
                    2:データ型認識エラー

<<例>>
(1)
result = SetEditorData( table )
└table(テーブル)の内容が送信エディタに格納される。
  resultにエラーコードが格納される。

(2)
result = SetEditorData( "ABCDEFG" )
└"ABCDEFG"(文字列)が送信エディタに格納される。
  resultにエラーコードが格納される。

(3)
result = SetEditorData( "" )
└データ部が空文字や、配列長0のテーブルの場合、
送信エディタはクリアされる。
  resultにエラーコードが格納される。(この場合でも正常終了)
関数: ファイル読み込み
<<概要>>
指定したファイルからデータを読み込み、テーブル配列に格納する。

result = FileRead( filename )

<<引数>>
filename(文字列)    読み込むファイル名称

<<戻り値>>
テーブル            読み込んだデータ
数値                異常終了
                    1:パラメータエラー
                    2:ファイル名文字列認識エラー
					3:ファイル存在エラー
                    4:ファイルサイズZERO
                    5:ファイルオープンエラー
                    6:ファイル読み込みサイズエラー
                    7:ファイル読み込みエラー

<<例>>
result = FileRead( "C:\\receive.dat" )
└ファイル"C:\receive.dat"の内容がresult(テーブル)に格納される。
  エラー発生時はresultは数値型であり、エラーコードが格納される。
関数: ファイル書き込み
<<概要>>
渡されたテーブルデータ(バイナリデータ)を指定したファイルに書き込む。
同名ファイルがあった場合は、古いファイルは削除されたうえで作成される。

result = FileWrite( table, filename )
result = FileWrite( string, filename )

<<引数>>
table(テーブル)     保存するバイナリデータ
string(文字列)      保存する文字列データ
filename(文字列)    保存するファイル名称

<<戻り値>>
数値                0:正常終了
                    1:パラメータエラー
                    2:ファイル名文字列認識エラー
                    3:データ型認識エラー
                    4:ファイルオープンエラー
                    5:ファイル書き込みエラー

<<例>>
(1)
result = FileWrite( tbl, "C:\\receive.dat" )
└ファイル"C:\receive.dat"にtblテーブルのデータが格納される
  resultにエラーコードが格納される。

(2)
result = FileWrite( "ABCDEFG", "C:\\receive.dat" )
└ファイル"C:\receive.dat"に文字列"ABCDEFGが格納される
  resultにエラーコードが格納される。

(3)
result = FileWrite( "", "C:\\receive.dat" )
└データ部が空文字や、配列長0のテーブルの場合、
  ファイルは0で作成される。
  resultにエラーコードが格納される。(この場合でも正常終了)
関数: データ送信
<<概要>>
指定したデータの送信を行います。
送信データはテーブル、文字列の2種類が可能です。
また、送信するポートの指定が可能です。

SendData( table )
SendData( table, option )
SendData( string )
SendData( string, option )

<<引数>>
table(テーブル)     送信するテーブルデータを指定します。
                    データはテーブルに格納された
                    符号無1バイトデータ(0〜255)で
                    ある必要があります。
string(文字列)      送信する文字列データを指定します。
option(数値)        データの送信ポートを指定します。
                    0:現在の制御中の接続ポートで送信します。
                    1:ポート1で接続中の全通信から送信します。
                    2:ポート2で接続中の全通信から送信します。
                    省略時、上記以外を指定した場合は0指定となります。

<<戻り値>>
無し                エラー発生時は、通信ログに表示されます。

<<例>>
(1)
SendData( table )
└指定したテーブルデータをバイナリ配列として送信します。
  送信するポートは自接続ポートです。

(2)
SendData( "ABCDEFG" )
└文字列"ABCDEFG"を送信します。
  送信するポートは自接続ポートです。

(3)
SendData( "ABCDEFG", 2 )
└文字列"ABCDEFG"をポート2で接続中の全通信ポートから送信します。
関数: ビット演算 ビットOR
<<概要>>
指定した2つの数値のOR値を返します。
内部では、符号無1バイト(unsigned char)として扱うため
制限を超える値を指示した場合、
想定した値と違う戻り値が戻る場合があります。

result = BitOr( base, param )

<<引数>>
base(数値)          ORを行う右値を指定します。
                    符号無1バイトを範囲とします。
param(数値)        ORを行う左値を指定します。
                    符号無1バイトを範囲とします。

<<戻り値>>
数値                base,paramのOR値を返します。
                    値が戻らない(nil)の場合、
                    パラメータエラーが発生したものとする。

<<例>>
(1)
result = BitOr( 0xFF, 0x80 )
└resultは、0xFFとなる。

(2)
result = BitOr( 0x04, 0x40 )
└resultは、0x44となる。
関数: ビット演算 ビットAND
<<概要>>
指定した2つの数値のAND値を返します。
内部では、符号無1バイト(unsigned char)として扱うため
制限を超える値を指示した場合、
想定した値と違う戻り値が戻る場合があります。

result = BitAnd( base, param )

<<引数>>
base(数値)          ANDを行う右値を指定します。
                    符号無1バイトを範囲とします。
param(数値)        ANDを行う左値を指定します。
                    符号無1バイトを範囲とします。

<<戻り値>>
数値                base,paramのAND値を返します。
                    値が戻らない(nil)の場合、
                    パラメータエラーが発生したものとする。

<<例>>
(1)
result = BitAnd( 0xFF, 0x80 )
└resultは、0x80となる。

(2)
result = BitAnd( 0x7F, 0x80 )
└resultは、0x00となる。
関数: ビット演算 ビットOFF
<<概要>>
元の値から指定したビットをOFFした値を返します。
内部では、符号無1バイト(unsigned char)として扱うため
制限を超える値を指示した場合、
想定した値と違う戻り値が戻る場合があります。

result = BitOff( base, param )

<<引数>>
base(数値)          ビット操作の元の値を指定します。
                    符号無1バイトを範囲とします。
param(数値)        OFFを行うビットに1をたてた値を指定します。
                    符号無1バイトを範囲とします。

<<戻り値>>
数値                baseの値からparamのビットを落とした値を返す。
                    値が戻らない(nil)の場合、
                    パラメータエラーが発生したものとする。

<<例>>
(1)
result = BitOff( 0xFF, 0x80 )
└resultは、0x7Fとなる。

(2)
result = BitOff( 0xFF, 0x8F )
└resultは、0x70となる。
関数: 文字列からテーブル変換
<<概要>>
渡された文字列をテーブル配列に格納する。

result = StringToTable( string )

<<引数>>
string(文字列)      変換する文字列

<<戻り値>>
テーブル            正常終了
                    変換データが格納される
数値                異常終了
                    1:パラメータエラー
                    2:文字列認識エラー

<<例>>
result = FileReadEx( "20071104" )
└result(テーブル)にASCII分解された文字列が格納される
  エラー発生時はresultは数値型であり、エラーコードが格納される。
関数: テーブル同士の結合
<<概要>>
テーブル同士を結合してひとつのテーブルに編集する。

result = TableCat( table1, table2 )

<<引数>>
table1(テーブル)    前結合データ
table2(テーブル)    後結合データ

<<戻り値>>
テーブル            正常終了
                    結合データが格納される
数値                異常終了
                    1:パラメータエラー
                    2:前結合データ認識エラー
                    3:後結合データ認識エラー

<<例>>
result = TableCat( a, b )
└result(テーブル)に結合されたデータが返る
  エラー発生時はresultは数値型であり、エラーコードが格納される。


スクリプトの例

 以下にスクリプトの例を示します。




例1
受信したデータを判定して内容にあった
ファイルデータを送信、または通信切断を行う。
---------------------------------------------
-- 接続完了通知
---------------------------------------------
function OnConnected()
    Logput(1,'OnConnected')
    return 0
end
---------------------------------------------
-- 送信ボタン押下
---------------------------------------------
function OnSendPush()
    Logput(1,'OnSendPush')
    a = GetEditorData()
    SendData(a)
    return 0
end
---------------------------------------------
-- タイマー通知
---------------------------------------------
function OnTimer(id)
    Logput(1,'OnTimer')
    return 0
end
---------------------------------------------
-- 受信通知
---------------------------------------------
function OnReceive(recv)
    Logput(1,'OnReceive')
    if recv[1] == 0x00 then
        -- 先頭が0x00ならば data1 を返す
        Logput(1,'DATA 1')
        s = FileRead( 'c:\\debug\\data1.bin' )
        SendData(s)
    elseif recv[1] == 0x01 then
        -- 先頭が0x01ならば data2 を返す
        Logput(1,'DATA 2')
        s = FileRead( 'c:\\debug\\data2.bin' )
        SendData(s)
    elseif recv[1] == 0xFF then
        -- 先頭が0xFFならば 通信切断
        Logput(1,'Disconnect')
        Disconnect()
    end
    return 0
end
---------------------------------------------
-- 切断通知
---------------------------------------------
function OnDisConnected()
    Logput(1,'OnDisConnected')
    return 0
end
例2
受信したデータを判定して
内容を改変して送信する。
---------------------------------------------
-- 接続完了通知
---------------------------------------------
function OnConnected()
    Logput(1,'OnConnected')
    return 0
end
---------------------------------------------
-- 送信ボタン押下
---------------------------------------------
function OnSendPush()
    Logput(1,'OnSendPush')
    a = GetEditorData()
    SendData(a)
    return 0
end
---------------------------------------------
-- タイマー通知
---------------------------------------------
function OnTimer(id)
    Logput(1,'OnTimer')
    return 0
end
---------------------------------------------
-- 受信通知
---------------------------------------------
function OnReceive(recv)
    Logput(1,'OnReceive')
    if BitAnd( recv[1], 0x80 ) ~= 0 then
        -- 先頭がBIT ONならば OFFにして返す
        Logput(1,'BIT ON -> OFF')
        recv[1] = BitOff( recv[1], 0x80 )
    else
        -- 先頭がBIT OFFならば ONにして返す
        Logput(1,'BIT OFF -> ON')
        recv[1] = BitOr( recv[1], 0x80 )
    end
    SendData(recv)
    return 0
end
---------------------------------------------
-- 切断通知
---------------------------------------------
function OnDisConnected()
    Logput(1,'OnDisConnected')
    return 0
end
例3
受信したデータを判定して
内容を改変して送信する。
---------------------------------------------
-- 接続完了通知
---------------------------------------------
function OnConnected()
    Logput(1,'OnConnected')
    return 0
end
---------------------------------------------
-- 送信ボタン押下
---------------------------------------------
function OnSendPush()
    Logput(1,'OnSendPush')
    a = GetEditorData()
    SendData(a)
    return 0
end
---------------------------------------------
-- タイマー通知
---------------------------------------------
function OnTimer(id)
    Logput(1,'OnTimer')
    return 0
end
---------------------------------------------
-- 受信通知
---------------------------------------------
function OnReceive(recv)
    Logput(1,'OnReceive')
    if recv[1] == 0x30 then
        -- 先頭が'0'ならば "1234"を返す(バイナリ送信)
        send = { 0x31, 0x32, 0x33, 0x34 }
        SendData(send)
    elseif recv[1] == 0x31 then
        -- 先頭が'1'ならば "5678"を返す(文字列送信)
        SendData("5678")
    end
    return 0
end
---------------------------------------------
-- 切断通知
---------------------------------------------
function OnDisConnected()
    Logput(1,'OnDisConnected')
    return 0
end
例4
起動時にタイマーをセットして
一定周期でデータを送信する。
---------------------------------------------
-- 接続完了通知
---------------------------------------------
function OnConnected()
    Logput(1,'OnConnected')
    -- 3秒周期で起動
    SetTimer(0,3000)
    -- 5秒周期で起動
    SetTimer(1,5000)
    return 0
end
---------------------------------------------
-- 送信ボタン押下
---------------------------------------------
function OnSendPush()
    Logput(1,'OnSendPush')
    a = GetEditorData()
    SendData(a)
    return 0
end
---------------------------------------------
-- タイマー通知
---------------------------------------------
function OnTimer(id)
    Logput(1,'OnTimer')
    if id == 0 then
        -- 送信エディタから送信
        dt = GetEditorData()
        SendData(dt)
    else
        -- 固定文字列を送信
        SendData("Notify")
    end
    return 0
end
---------------------------------------------
-- 受信通知
---------------------------------------------
function OnReceive(recv)
    Logput(1,'OnReceive')
    -- 受信したらタイマー2を停止
    KillTimer(1)
    return 0
end
---------------------------------------------
-- 切断通知
---------------------------------------------
function OnDisConnected()
    Logput(1,'OnDisConnected')
    return 0
end
例5
受信データを送信エディタにセットする。
送信ボタン押下時に送信エディタから送信する。
---------------------------------------------
-- 接続完了通知
---------------------------------------------
function OnConnected()
    Logput(1,'OnConnected')
    return 0
end
---------------------------------------------
-- 送信ボタン押下
---------------------------------------------
function OnSendPush()
    Logput(1,'OnSendPush')
    a = GetEditorData()
    SendData(a)
    return 0
end
---------------------------------------------
-- タイマー通知
---------------------------------------------
function OnTimer(id)
    Logput(1,'OnTimer')
end
---------------------------------------------
-- 受信通知
---------------------------------------------
function OnReceive(recv)
    Logput(1,'OnReceive')
    -- 受信したら送信エディタにセット
    SetEditorData(recv)
    return 0
end
---------------------------------------------
-- 切断通知
---------------------------------------------
function OnDisConnected()
    Logput(1,'OnDisConnected')
    return 0
end
例6
受信データをファイルに保存する。
送信ボタン押下時にファイルから送信する。
---------------------------------------------
-- 接続完了通知
---------------------------------------------
function OnConnected()
    Logput(1,'OnConnected')
    return 0
end
---------------------------------------------
-- 送信ボタン押下
---------------------------------------------
function OnSendPush()
    Logput(1,'OnSendPush')
    a = FileRead("c:\\debug\\data1.bin")
    SendData(a)
    return 0
end
---------------------------------------------
-- タイマー通知
---------------------------------------------
function OnTimer(id)
    Logput(1,'OnTimer')
end
---------------------------------------------
-- 受信通知
---------------------------------------------
function OnReceive(recv)
    Logput(1,'OnReceive')
    -- 受信したら送信エディタにセット
    FileWrite(recv,"c:\\debug\\data1.bin")
    return 0
end
---------------------------------------------
-- 切断通知
---------------------------------------------
function OnDisConnected()
    Logput(1,'OnDisConnected')
    return 0
end
 
機能紹介
動作環境
シェアウェア版とフリー版
使い方
使い方
拡張モジュールの作り方
Luaスクリプト
Q&A
ダウンロード
購入方法
改訂履歴
著作権
作者から

Vector