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