跳到主要内容

Over-The-Air (OTA) Updates

Over-The-Air (OTA) updates allow you to update the firmware of your nodes remotely without physical access to the device.

Overview

OTA updates in RainMaker enable you to:

  • Check for available firmware updates
  • Initiate OTA updates for nodes
  • Monitor the status of OTA update jobs

Check OTA Update

Check if there is an Over-The-Air (OTA) update available for the node using the checkOTAUpdate method.

try {
const otaResponse = await node.checkOTAUpdate();
console.log("OTA update availability:", otaResponse);

if (otaResponse.otaAvailable) {
console.log("Update available:", otaResponse.fwVersion);
console.log("OTA Job ID:", otaResponse.otaJobId);
console.log("File size:", otaResponse.fileSize);
}
} catch (error) {
console.error("Error checking OTA update:", error);
}

ESPOTAUpdateResponse Interface

The checkOTAUpdate method returns an ESPOTAUpdateResponse object containing detailed information about the OTA update availability and details.

PropertyTypeRequiredDescription
otaAvailablebooleanYesIndicates whether an OTA update is available for the device.
statusstringYesThe status of the OTA update.
descriptionstringYesDescription of the OTA update.
fwVersionstringYesThe firmware version available for update.
otaJobIdstringYesThe OTA job ID that can be used to initiate the update.
fileSizenumberYesThe size of the firmware file in bytes.
urlstringNoThe URL from which the firmware can be downloaded.
fileMD5stringNoThe MD5 hash of the firmware file for verification.
streamIdstringNoThe stream ID for the OTA update.
metadataRecord<string, any>NoAdditional metadata associated with the OTA update.

Example: Check OTA Update and Use Response

try {
const otaResponse = await node.checkOTAUpdate();

if (otaResponse.otaAvailable) {
console.log("OTA Update Available!");
console.log("Firmware Version:", otaResponse.fwVersion);
console.log("Description:", otaResponse.description);
console.log("File Size:", otaResponse.fileSize, "bytes");
console.log("Status:", otaResponse.status);
console.log("OTA Job ID:", otaResponse.otaJobId);

// Use otaJobId to initiate the update
if (otaResponse.otaJobId) {
// You can use this job ID with pushOTAUpdate
console.log("Ready to update with job ID:", otaResponse.otaJobId);
}

// Optional fields
if (otaResponse.url) {
console.log("Firmware URL:", otaResponse.url);
}

if (otaResponse.fileMD5) {
console.log("File MD5:", otaResponse.fileMD5);
}

if (otaResponse.metadata) {
console.log("Metadata:", otaResponse.metadata);
}
} else {
console.log("No OTA update available. Current status:", otaResponse.status);
}
} catch (error) {
console.error("Error checking OTA update:", error);
}

Example: Validate OTA Update Before Proceeding

try {
const otaResponse = await node.checkOTAUpdate();

if (otaResponse.otaAvailable) {
// Validate that we have all required information
if (!otaResponse.otaJobId) {
console.error("OTA Job ID is missing");
return;
}

// Check file size if needed
if (otaResponse.fileSize > 0) {
console.log(`Update size: ${(otaResponse.fileSize / 1024 / 1024).toFixed(2)} MB`);
}

// Verify MD5 if available
if (otaResponse.fileMD5) {
console.log("File verification hash:", otaResponse.fileMD5);
}

// Proceed with update using the job ID
console.log("Proceeding with OTA update...");
// Use otaResponse.otaJobId with pushOTAUpdate
}
} catch (error) {
console.error("Error checking OTA update:", error);
}

Push OTA Update

Initiate an Over-The-Air (OTA) update for the node using a specified OTA job ID with the pushOTAUpdate method. The OTA job ID is obtained from the checkOTAUpdate response.

try {
// First, check for available OTA updates
const otaResponse = await node.checkOTAUpdate();

if (otaResponse.otaAvailable && otaResponse.otaJobId) {
// Use the otaJobId from checkOTAUpdate response
const response = await node.pushOTAUpdate(otaResponse.otaJobId);
console.log("OTA update initiated:", response);
} else {
console.log("No OTA update available or job ID missing");
}
} catch (error) {
console.error("Error initiating OTA update:", error);
}

Example: Complete OTA Update Flow

try {
// Step 1: Check for available OTA updates
const otaResponse = await node.checkOTAUpdate();

if (!otaResponse.otaAvailable) {
console.log("No OTA update available. Status:", otaResponse.status);
return;
}

console.log("OTA Update Available!");
console.log("Firmware Version:", otaResponse.fwVersion);
console.log("File Size:", otaResponse.fileSize, "bytes");

// Step 2: Initiate the OTA update using the job ID
if (otaResponse.otaJobId) {
const pushResponse = await node.pushOTAUpdate(otaResponse.otaJobId);
console.log("OTA update initiated:", pushResponse);

// Step 3: Monitor the update status
const status = await node.getOTAUpdateStatus(otaResponse.otaJobId);
console.log("OTA update status:", status);
}
} catch (error) {
console.error("Error in OTA update flow:", error);
}

Get OTA Update Status

Check the status of a previously initiated Over-The-Air (OTA) update for the node using the getOTAUpdateStatus method. Use the OTA job ID obtained from checkOTAUpdate or pushOTAUpdate.

try {
// Get the OTA job ID from checkOTAUpdate response
const otaResponse = await node.checkOTAUpdate();

if (otaResponse.otaJobId) {
const statusResponse = await node.getOTAUpdateStatus(otaResponse.otaJobId);
console.log("OTA update status:", statusResponse.status);
console.log("Node ID:", statusResponse.nodeId);
console.log("Timestamp:", new Date(statusResponse.timestamp));
console.log("Additional Info:", statusResponse.additionalInfo);
}
} catch (error) {
console.error("Error fetching OTA update status:", error);
}

ESPOTAUpdateStatusResponse Interface

The getOTAUpdateStatus method returns an ESPOTAUpdateStatusResponse object containing the current status of the OTA update.

PropertyTypeRequiredDescription
statusstringYesThe current status of the OTA update (e.g., "in_progress", "completed", "failed").
nodeIdstringYesThe ID of the node for which the OTA update status is being checked.
timestampnumberYesThe timestamp when the status was last updated (Unix timestamp in milliseconds).
additionalInfostringYesAdditional information about the OTA update status.

Example: Monitor OTA Update Progress

async function monitorOTAUpdate(node, otaJobId) {
try {
const maxAttempts = 30; // Maximum number of status checks
let attempts = 0;

while (attempts < maxAttempts) {
const statusResponse = await node.getOTAUpdateStatus(otaJobId);
const status = statusResponse.status;

console.log(`OTA Update Status (Attempt ${attempts + 1}):`, status);
console.log("Node ID:", statusResponse.nodeId);
console.log("Last Updated:", new Date(statusResponse.timestamp).toLocaleString());

if (statusResponse.additionalInfo) {
console.log("Additional Info:", statusResponse.additionalInfo);
}

// Check if update is complete or failed
if (status === "completed" || status === "failed") {
console.log("OTA update finished with status:", status);
return statusResponse;
}

// Wait before next check (e.g., 5 seconds)
await new Promise(resolve => setTimeout(resolve, 5000));
attempts++;
}

console.log("Status check timeout");
return null;
} catch (error) {
console.error("Error monitoring OTA update:", error);
throw error;
}
}

// Usage
try {
const otaResponse = await node.checkOTAUpdate();
if (otaResponse.otaAvailable && otaResponse.otaJobId) {
await node.pushOTAUpdate(otaResponse.otaJobId);
const finalStatus = await monitorOTAUpdate(node, otaResponse.otaJobId);

if (finalStatus) {
console.log("Final Status:", finalStatus.status);
console.log("Completed at:", new Date(finalStatus.timestamp).toLocaleString());
}
}
} catch (error) {
console.error("Error in OTA update process:", error);
}

Example: Handle Different OTA Status Values

try {
const otaResponse = await node.checkOTAUpdate();

if (otaResponse.otaAvailable && otaResponse.otaJobId) {
await node.pushOTAUpdate(otaResponse.otaJobId);

const statusResponse = await node.getOTAUpdateStatus(otaResponse.otaJobId);

switch (statusResponse.status) {
case "in_progress":
console.log("OTA update is in progress...");
console.log("Additional Info:", statusResponse.additionalInfo);
break;
case "completed":
console.log("OTA update completed successfully!");
console.log("Completed at:", new Date(statusResponse.timestamp).toLocaleString());
break;
case "failed":
console.error("OTA update failed!");
console.error("Error details:", statusResponse.additionalInfo);
break;
case "pending":
console.log("OTA update is pending...");
break;
default:
console.log("Unknown status:", statusResponse.status);
}
}
} catch (error) {
console.error("Error in OTA update process:", error);
}

OTA Update Flow

The following sequence diagram illustrates the complete OTA update flow between the SDK, App, and Node:

On this page