Data Send/Recv

This document describes how to exchange data between a Lua plugin running on the obniz OS and the obniz JavaScript SDK.

Overview

You can facilitate communication between a Lua plugin operating on the device OS and the JavaScript SDK. This allows for bidirectional data transfer and efficient handling of large data sets.

obniz.plugin.send()

Sends a binary data sequence from the obniz.js side to the Lua plugin.

Javascript Example

// Send string data
obniz.plugin.send("obniz.js send data get device?");

// Send byte array
obniz.plugin.send([0x00, 0x01, 0x02]);

Lua Plugin Side

On the Lua side, use the on_command() function to receive the data.

function on_command(command)
  -- 'command' contains the data sent from JS
  os.log(command)
end

obniz.plugin.onreceive

This event handler receives a binary data sequence sent from the Lua plugin to the obniz.js side.

Javascript Example

obniz.plugin.onreceive = (data) => {
  console.log(data);
};

Lua Plugin Side

Use cloud.pluginSend() to send data to the JavaScript SDK.

cloud.pluginSend("123");

obniz.plugin.onFrameStart / onFrameEnd

These handlers are triggered when frame information is sent from the plugin side.

These functions are particularly useful for segmenting and managing large data transfers.

  • onFrameStart: Receives the frame_id and the total length of the data.
  • onreceive: For large payloads, the data will be received in multiple chunks through this handler.
  • onFrameEnd: Called once all data defined in the frame has been completely received.

Javascript Example

// Handle the start of a frame
obniz.plugin.onFrameStart = (frame_id, length) => {
  console.log(`Frame start: ID=${frame_id}, Total Length=${length}`);
};

// Handle the end of a frame
obniz.plugin.onFrameEnd = () => {
  console.log("Frame reception completed");
};

// Receive chunks of data
obniz.plugin.onreceive = (data) => {
  console.log(`Received chunk: ${Buffer.from(data).toString()}`);
};

Lua Plugin Side

To use framing in a Lua plugin, use the following commands:

local frame_id = 1
local total_length = 9

cloud.pluginSendFrameStart(frame_id, total_length); -- Start framing 

cloud.pluginSend("123");
cloud.pluginSend("456");
cloud.pluginSend("789");

cloud.pluginSendFrameEnd(); -- End framing 

obniz.plugin.callWait()

Available for OS7.1.0 and later

Runs a Lua script on the device and waits for its return value. While execLua() simply fires a script and forgets it, callWait() resolves with whatever the script returns.

The script runs inside a coroutine on the device, which lets the Lua side call cloud.transactionWait() (see below) while it runs.

obniz.plugin.callWait(lua_script, timeout)
  • lua_script (string): The Lua script to run. Its return value is resolved as a string.
  • timeout (number, optional): The time to wait for a result, in milliseconds. Defaults to 30000.

If the script raises an error, the returned Promise is rejected with that error message.

// Javascript Example

// Run Lua and wait for its return value
const result = await obniz.plugin.callWait(`return "hello from lua"`);
console.log(result); // "hello from lua"

// Lua can compute and return a value
const sum = await obniz.plugin.callWait(`
  local x = 0
  for i = 1, 10 do x = x + i end
  return tostring(x)
`);
console.log(sum); // "55"

// An error raised in Lua rejects the Promise
try {
  await obniz.plugin.callWait(`MUST FAILED`);
} catch (e) {
  console.log("lua error:", e.message);
}

cloud.transactionWait() / obniz.plugin.onCloudTransaction

Available for OS7.1.0 and later

Unlike cloud.pluginSend(), which only sends data one way, cloud.transactionWait() sends data to obniz.js and waits for a reply. The plugin can therefore ask the cloud a question and continue once the answer arrives.

Lua Plugin Side

cloud.transactionWait() sends data and suspends until obniz.js responds, then returns the result. Because it suspends, it must run inside a Lua coroutine. The obniz.plugin.callWait() method on the obniz.js side runs the script within a coroutine for you.

cloud.transactionWait(data, callback, timeout_ms)
  • data (string): The data to send to obniz.js.
  • callback (function, optional): Called as callback(success, result) when the reply arrives.
  • timeout_ms (number, optional): The time to wait for a reply, in milliseconds. Defaults to 30000.

It returns two values: success (boolean) and result (string or nil).

os.log("start");

-- Ask the cloud and wait for the reply (timeout 5000ms)
local success, result = cloud.transactionWait("ping", 5000)
if success then
  return result
else
  return "transaction failed"
end

Javascript Example

Handle the request from the plugin with obniz.plugin.onCloudTransaction. Whatever the handler returns is passed back to the waiting Lua coroutine with success = true. Throwing an error reports success = false to the plugin.

// Called when the plugin runs cloud.transactionWait(data).
obniz.plugin.onCloudTransaction = async (data, str) => {
  console.log("lua asked cloud:", str);
  // For example, call an external API here and return its response.
  return `echo:${str}`;
};

// callWait runs the script inside a coroutine so transactionWait can wait.
const result = await obniz.plugin.callWait(`
  local success, result = cloud.transactionWait("ping", 5000)
  if success then
    return result
  else
    return "transaction failed"
  end
`);
console.log("lua got back:", result); // "echo:ping"