I’m attempting to implement a very simple analysis that reads a device parameter, acts on it, and writes a new parameter back to the device. This is exactly what the “Operate data from devices” example snippet appears to do.
In my case, I wish to use this analysis with a Blueprint dashboard when called from a Push Button widget.
You’re very close to the correct implementation. The main issue lies in how Blueprint dashboards pass the device context and how it should be used inside your Analysis.
How It Works in a Blueprint + Push Button Setup
When using a Push Button widget in a Blueprint dashboard, TagoIO sends the device context dynamically through the scope of your Analysis, not through tokens or environment variables.
In Blueprint dashboards, the Push Button widget doesn’t know the device at configuration time. Instead, when the button is pressed, the device context is included in the scope object provided to your Analysis.
The scope array will contain an object with a device property (the device ID), and also the variable name and value that triggered the Analysis. This is different from using environment variables or static device tokens.
Correct Pattern for Blueprint Push Button → Analysis
Here’s how to reliably access device parameters in this scenario:
const { Analysis, Resources } = require("@tago-io/sdk");
async function myAnalysis(context, scope) {
try {
const variable = scope[0]; // the push button's variable
const device_id = variable.device;
// Fetch all parameters
const params = await Resources.devices.paramList(device_id);
// Find the parameter you need
const myParam = params.find(p => p.key === "my_key");
if (myParam) {
// Update the parameter if needed
await Resources.devices.paramSet(device_id, {
key: "my_key",
value: "new_value"
});
}
} catch (error) {
console.error("Analysis error:", error);
}
}
Analysis.use(myAnalysis);
Important: The Resources class requires proper access permissions in Access Management. Without them, you’ll receive an “Authorization Denied” error.
Why It Might Not Have Worked Before
Using new Device({ token, device_id }) doesn’t work because the class doesn’t expect to receive the device_id as a parameter.
zsu[@user:10061942044]zsu Thank you, that works for parameters.
I’d like to be able to to the same thing for device variables, i.e. when the script is triggered read a variable and write a new value to that same variable.
I updated the script below which executes without error, but I do not see the “my_key” value updated in the device data.
Any advice?
const { Analysis, Resources } = require("@tago-io/sdk");
async function myAnalysis(context, scope) {
try {
const variable = scope[0];
const device_id = variable.device;
// Fetch the latest value for the variable "my_key"
const data = await Resources.devices.getDeviceData(device_id, {
variables: ["my_key"],
qty: 1, // get the latest value
});
if (data.length) {
// Append the variable "my_key" with a value "my_value"
await Resources.devices.sendDeviceData(device_id, {
variable: "my_key",
value: "my_value"
});
}
} catch (error) {
console.error("Analysis error:", error);
}
}
Analysis.use(myAnalysis);
You may want to add a log to your code, since you’re conditioning the addition of my_key to only happen if there is a my_key variable in your device.
console.log(`Found ${data.length} records for my_key`);
The issue is that your getDeviceData call is looking for existing “my_key” variables, but if the device doesn’t already have a “my_key” variable, data.length will be 0 and your sendDeviceData block won’t execute.
A good suggestion. In the more verbose code (below) it does find the desired variable but still no new sendData value is seen after execution. No authorization error are seen either so it seems the access policy is ok.
Any other ideas?
const { Analysis, Device, Resources } = require("@tago-io/sdk");
async function myAnalysis(context, scope) {
try {
const variable = scope[0];
const device_id = variable.device;
// Get device token
const tokens = await Resources.devices.tokenList(device_id);
const device_token = tokens[0]?.token;
if (!device_token) {
return context.log("No token found for device");
}
const device = new Device({ token: device_token });
// Read last volt
const data = await device.getData({ variable: "volt", query: "last_item" });
console.log(`Found ${data.length} records for my_key`);
if (!data.length) {
return context.log("No previous volt data found.");
}
context.log(`Previous volt: ${data[0].value}`);
// Write new volt
await device.sendData({
variable: "volt",
value: 1234,
metadata: { source: "analysis_test" },
});
context.log("✅ Sent volt = 1234");
} catch (error) {
context.log("Analysis error:", error.message || error);
}
}
Analysis.use(myAnalysis);
Your code is working fine on my end. The issue you’re seeing is likely something else interfering with your data or preventing you from seeing that it’s actually being stored.
Here are some troubleshooting steps to try:
See if you have a Payload Parser enabled that might be filtering out data from your device.
Check the Device Live Inspector to troubleshoot what’s actually being received and stored in real-time.
Make sure the Device ID you’re checking matches the actual device you’re looking at in the Admin Panel.
If you still can’t see the variable being stored after checking these items, I’d suggest opening a support ticket. If given access, our team can dig into your account and verify if there’s something unusual happening.