Net (HTTP / TCP / UDP)

net関数を使うと、Luaプラグインは、obniz Cloudを経由せず、お客様自身のサーバーと直接やり取りできます。端末が現在つながっているネットワーク回線を通じてデータを送受信し、HTTP(net.http)、生のTCP(net.tcp)、UDP(net.udp)の3種類のプロトコルに対応します。

既存のAPIやプライベートなエンドポイント、obniz Cloudが扱わないサービスへ端末から接続したいときに、お使いください。


共通の挙動と制約

いずれのnet関数も、使う前にこの節をお読みください。

  • 現在のネットワーク回線に従います。 HTTPとTCPは、そのとき接続している回線(Wi-Fi、Ethernet、LTEのいずれか)を通じて動作します。UDPは、Wi-FiまたはEthernetでのみ動作し、LTEでは使えません
  • 完了するまで処理をとめます。 各関数は同期的に動作し、操作が完了するか、失敗するか、タイムアウトするまで返りません。待機中は通信ウォッチドッグに餌を与えるため、長い転送でも端末はリセットされません。ただし、その間、関数を呼んだハンドラはとまったままです。すぐに返ることを期待されるon_online_loop()on_offline_loop()の中では、長い転送を避けてください。
  • 平文のHTTPのみに対応し、TLSは使えません。 通信は暗号化されません。URLはhttp://をお使いください。https://は動作しません。機密情報を送るときは、信頼できるネットワークでのみお使いください。
  • ソケットは1本ずつお使いください。 接続を1本だけ開き、使い終えてから閉じ、その後に次の接続を開いてください。2本目以降が開けるかどうかは、空きメモリや使っているネットワーク回線の状況によります。複数を同時に開いたままにすることは、あてにしないでください。不要になったソケットは、必ず閉じてください。
  • エラーは送出されず、返り値で示されます。 失敗したとき、関数はnilと短いエラー文字列を返します。結果を使う前に、1つ目の返り値を確認してください。

net.http

net.http.get(url)

HTTPのGETリクエストを実行し、応答をすべて受け取るまで待ちます。

引数 説明
url string 対象のURLです。http://で始めます。https://には対応していません。

成功すると3つの値を、失敗するとnilとエラー文字列を返します。

返り値 説明
status number 200などのHTTPステータスコードです。
body string 応答の本文です。
headers string 応答ヘッダの生データです。

net.http.post(url, body, contentType)

指定した本文で、HTTPのPOSTリクエストを実行します。

引数 説明
url string 対象のURLです。
body string 送信するリクエスト本文です。
contentType string 任意。Content-Typeヘッダです。既定値はapplication/octet-streamです。

返り値はnet.http.get()と同じです。

net.http.request(options)

メソッド、ヘッダ、本文、タイムアウトを細かく指定して、リクエストを実行します。optionsはテーブルです。

フィールド 説明
url string 必須。対象のURLです。
method string 任意。HTTPメソッドです。既定値はGETです。
headers table 任意。リクエストヘッダです。{ ["Key"] = "Value" }または{ "Key: Value" }の形式で指定します。
body string 任意。リクエスト本文です。
timeout number 任意。待つ時間(ミリ秒)です。既定値は30000です。

返り値はnet.http.get()と同じです。

HTTPの制約

HTTPクライアントは、意図的に小さく作ってあります。次の制限に注意してください。

  • Connection: closeを送り、サーバーが接続を閉じるまで読み続けます。キープアライブは使いません。
  • リダイレクトを追いません。3xxの応答は、そのまま返します。
  • チャンク転送エンコーディングのデコードや、gzipの解凍を行いません。本文は受信したそのままを返すため、できるだけ、圧縮もチャンクもしない応答を要求してください。
  • ホスト名は、128文字未満にしてください。

net.tcp

net.tcp.connect(host, port)

平文のTCP接続を開き、ソケットのidを返します。TLSには対応していません。

引数 説明
host string ホスト名またはIPアドレスです。
port number ポート番号です。

成功するとソケットのidを、失敗するとnilとエラー文字列を返します。このidを、ほかのnet.tcp関数に渡してください。

net.tcp.write(id, data)

接続を通じてデータを送ります。すべてのデータを送り終えると返り、30秒でタイムアウトします。

引数 説明
id number net.tcp.connect()が返したソケットのidです。
data string 送信するデータです。

書き込んだバイト数を返します。失敗するとnilとエラー文字列を返します。

net.tcp.read(id, maxlen)

すでに届いているデータを読み取ります。新しいデータを待ちません。

引数 説明
id number ソケットのidです。
maxlen number 任意。読み取る最大バイト数です。既定値は1024で、上限は4096未満です。
返り値 説明
data string | nil 受信したデータです。空文字列("")は、まだデータが届いていないことを表します。nilは、接続が閉じたか、エラーが起きたことを表します。

readはすぐに返るため、1回の呼び出しでメッセージ全体を受け取ろうとせず、ループのたびに繰り返し読み取ってください。

net.tcp.close(id)

接続を閉じ、ソケットを解放します。


net.udp

UDPは、Wi-FiまたはEthernetでのみ動作します。LTEでは使えません。セルラー接続では、net.udp.open()udp not supported on cellularで失敗します。

net.udp.open(localPort)

UDPソケットを開き、そのidを返します。

引数 説明
localPort number 任意。バインドするローカルポートです。省略すると、システムが割り当てます。

成功するとソケットのidを、失敗するとnilとエラー文字列を返します。

net.udp.sendTo(id, host, port, data)

指定した宛先へ、データグラムを送ります。

引数 説明
id number ソケットのidです。
host string 宛先のホスト名またはIPアドレスです。
port number 宛先のポートです。
data string データグラムのペイロードです。

送ったバイト数を返します。失敗するとnilとエラー文字列を返します。

net.udp.receive(id, maxlen)

データグラムを1つ受け取ります。待たずに返り、届いていなければnilを返します。

引数 説明
id number ソケットのidです。
maxlen number 任意。読み取る最大バイト数です。既定値は1024で、上限は4096未満です。
返り値 説明
data string | nil 受信したペイロードです。何も届いていなければnilです。
ip string 送信元のIPアドレスです。
port number 送信元のポートです。

net.udp.close(id)

ソケットを閉じます。


Example: 1分ごとにアナログ値を送信する

以下のプラグインは、1分に一度、IO0の電圧を読み取り、JSONとして平文のHTTPでお客様自身のサーバーへ直接送信します。すべて端末上で動作し、obniz Cloudを経由しません。

last = 0;

function on_online_loop()
  -- 60秒に一度だけ実行する
  if os.getTick() - last < 60 * 1000 then
    return;
  end
  last = os.getTick();

  -- IO0のアナログ電圧を読み取る
  local voltage = ad.get(0);
  local body = '{"voltage":' .. tostring(voltage) .. '}';

  -- お客様自身のサーバーへPOSTする
  local status, resp = net.http.post("http://example.com/api/measurements", body, "application/json");

  if status == nil then
    -- 失敗したときは、2つ目の値にエラー文字列が入る
    os.log("post failed: " .. tostring(resp));
    return;
  end

  os.log("posted, status: " .. tostring(status));
end