Available for OS7.1.0 and later
A transaction is a request that waits for a reply. With obniz.plugin.send() and cloud.pluginSend(), data only flows one way. With transactions, obniz.js and the Lua plugin can ask each other and get an answer back.
| Direction | Ask with | Answer with |
|---|---|---|
| obniz.js → Lua | obniz.plugin.callWait() |
the return value of the Lua script |
| Lua → obniz.js | cloud.transactionWait() |
the return value of obniz.plugin.onCloudTransaction |
The two can be combined: a script run by callWait() can ask obniz.js a question with cloud.transactionWait() while it runs.
obniz.plugin.callWait(lua_script, timeout)
Runs a Lua script on the device and waits for its return value. While execLua() only sends a script, callWait() resolves with what the script returns.
| Argument | Type | Description |
|---|---|---|
lua_script |
string | The Lua script to run. |
timeout |
number | Optional. The time to wait for the result, in milliseconds. Defaults to 30000. 0 waits without a time limit. |
Returns a Promise.
- Resolved with the first value the script
returns, as a string. A number is converted to a string. Other values, such as tables, booleans, andnil, are resolved as an empty string, so convert them to a string (for example, JSON) before returning. - Rejected when the script raises an error (with the Lua error message), when the timeout elapses, or when the connection to the device is reset.
The script runs in the same Lua environment as the plugin, so it can read and change the plugin's global variables and call its functions.
// Run Lua and wait for its return value
const result = await obniz.plugin.callWait(`return "hello from lua"`);
console.log(result); // "hello from lua"
// Read a value from the running plugin
const count = await obniz.plugin.callWait(`return tostring(counter)`);
// An error raised in Lua rejects the Promise
try {
await obniz.plugin.callWait(`MUST FAILED`);
} catch (e) {
console.log("lua error:", e.message);
}
The device can run up to 100 callWait() scripts at the same time (including scripts waiting in cloud.transactionWait()). Beyond that, the Promise is rejected with busy.
cloud.transactionWait(data, callback, timeout_ms)
Sends data from the Lua plugin to obniz.js and waits for the reply.
| Argument | Type | Description |
|---|---|---|
data |
string | The data to send to obniz.js. |
callback |
function | Optional. Called as callback(success, result) when the reply arrives or the wait times out. |
timeout_ms |
number | Optional. The time to wait for the reply, in milliseconds. Defaults to 30000. Specify an integer. |
The callback can be omitted. cloud.transactionWait(data, timeout_ms) is also accepted.
| Return | Type | Description |
|---|---|---|
success |
boolean | true when obniz.js replied normally. false when the handler threw an error, no handler is set, the wait timed out, or the request could not be made. |
result |
string | nil | The reply from obniz.js. When the handler threw an error, its message. nil on timeout. |
Where it can be called
cloud.transactionWait() suspends the running Lua code until the reply arrives. This is only possible inside a script run by obniz.plugin.callWait().
When it is called elsewhere, such as in on_online_loop(), on_command(), or the plugin loaded at startup, it does not wait and immediately returns false, nil.
While one script waits, the rest of the plugin keeps running: on_online_loop() and the other handlers continue to be called. A reply that arrives after the timeout is ignored.
-- Run inside obniz.plugin.callWait()
local success, result = cloud.transactionWait("get_config", 5000)
if success then
threshold = tonumber(result)
return "updated"
else
return "failed"
end
obniz.plugin.onCloudTransaction
The handler that answers cloud.transactionWait() on the obniz.js side.
obniz.plugin.onCloudTransaction = async (data, str) => {
// data: number[] (raw bytes), str: the same data as a string
return "reply";
};
- The handler can be an
asyncfunction. The reply is sent when the returned Promise settles. - Return a string, a byte array (
number[]), or aBuffer. Returning nothing sends an empty string. - Throwing an error (or rejecting) reports
success = falseto Lua, with the error message asresult. - If no handler is set, obniz.js replies with
success = falseimmediately, so Lua does not wait until the timeout.
Example: Asking the cloud from the device
In this example, obniz.js runs a script on the device. The script asks obniz.js for a setting value, applies it, and returns the result.
// Answer the question from the plugin
obniz.plugin.onCloudTransaction = async (data, str) => {
if (str === "get_interval") {
// For example, read the value from your database or another API here.
return "60000";
}
throw new Error(`unknown request: ${str}`);
};
// Run a script that asks the question and waits for the answer
const result = await obniz.plugin.callWait(`
local success, value = cloud.transactionWait("get_interval", 5000)
if not success then
return "failed: " .. tostring(value)
end
interval = tonumber(value)
return "interval=" .. value
`);
console.log(result); // "interval=60000"