Skip to content

Control Device

Send control commands to a device (object) identified by its partial UID. This endpoint allows you to send raw data commands to devices and optionally wait for their responses.

Request

http
POST /api/control-device

Authentication Required: Must include JWT token in Authorization header.

Required Scope: device_control

Special Scope: If the user has the omit_mpass scope, the operation can proceed without requiring the master password.

Content-Type: application/json

Request Body

json
{
  "partial_uid": "ABCDEF123456",
  "request_id": "req-123",
  "data": "...device control message...",
  "cloud_access_code": "123456",
  "response_required": true
}

Request Fields

FieldTypeRequiredDescription
partial_uidstringYesPartial UID of the target device (hex format)
request_idstringNoOptional identifier for tracking this request
datastringYesCommand data to send to device (hex format)
cloud_access_codestringNoCloud access code for the device
response_requiredbooleanNoWhether to wait for device response (default: false)

Request Examples

Send Command Without Response

bash
curl -X POST "http://your-server-ip:port/api/control-device" \
     -H "Authorization: Bearer YOUR_JWT_TOKEN" \
     -H "Content-Type: application/json" \
     -d '{
       "partial_uid": "ABC123",
       "data": "...device control message..."
     }'

Send Command and Wait for Response

bash
curl -X POST "http://your-server-ip:port/api/control-device" \
     -H "Authorization: Bearer YOUR_JWT_TOKEN" \
     -H "Content-Type: application/json" \
     -d '{
       "partial_uid": "ABC123",
       "request_id": "status-check-001",
       "data": "...device control message...",
       "response_required": true
     }'

Response

Success (200 OK)

Command Sent Successfully (with response):

json
{
  "partial_uid": "ABCDEF123456",
  "request_id": "req-123",
  "uid": "AABBCCDDEEFF",
  "data": ["...device response data...", "...additional response data..."],
  "hw_id": "01",
  "oid": "1234567890"
}

Command Sent Successfully (no response required):

json
{
  "partial_uid": "ABCDEF123456",
  "request_id": "req-123",
  "uid": "AABBCCDDEEFF",
  "hw_id": "01",
  "oid": "1234567890"
}

Error:

json
{
  "partial_uid": "ABCDEF123456",
  "request_id": "req-123",
  "uid": "AABBCCDDEEFF",
  "error": "See error table below for possible values",
  "hw_id": "01",
  "oid": "1234567890"
}

Response Fields

FieldTypeDescription
partial_uidstringThe queried partial UID
request_idstringRequest identifier (if provided)
uidstringFull unique identifier of the device
dataarrayArray of response data packets from device (hex format). Only present when response_required is true and device responds
errorstringError message if command failed or device reported an error (optional)
hw_idstringHardware identifier (optional)
oidstringObject identifier (optional)

Error Responses

HTTP Error Responses

400 Bad Request (Plain Text)

Invalid request

401 Unauthorized (Plain Text)

NOT_LOGGED_IN

403 Forbidden (Plain Text)

FORBIDDEN

405 Method Not Allowed (Plain Text)

Method Not Allowed

JSON Response with Errors

Even when the HTTP status is 200 OK, the response may contain an error field indicating issues with the request or device communication:

Error Response Example:

json
{
  "partial_uid": "ABCDEF123456",
  "request_id": "req-123",
  "uid": "AABBCCDDEEFF",
  "error": "NO_RESPONSE",
  "hw_id": "01",
  "oid": "1234567890"
}

Possible Error Field Values

Error CodeOccurs only when response_required is trueDescription
FIELD_UID_IS_MISSINGNoRequired partial_uid field is missing from request
INVALID_DATANoCommand data format is invalid (not valid hex)
BAD_DATANoCommand data is malformed or corrupted
NO_OBJECTNoDevice with specified partial UID not found
NO_CONNECTIONNoDevice is not connected or unreachable
MPASS_IS_INCORRECTNoIncorrect cloud access code provided
NO_RESPONSEYesDevice did not respond within timeout period (10 seconds)
INVALID_PACKET_NUMBERYesDevice response contained invalid packet number
INVALID_PACKET_COUNTYesDevice response contained invalid packet count

Command Reference

Device control commands are documented in the Control Command Reference page.

Usage Examples

Basic Device Control

javascript
async function sendDeviceCommand(partialUid, commandData, waitForResponse = false) {
  try {
    const response = await fetch('/api/control-device', {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${token}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        partial_uid: partialUid,
        data: commandData,
        response_required: waitForResponse,
        request_id: `cmd-${Date.now()}`
      })
    });
    
    if (!response.ok) {
      const error = await response.text();
      throw new Error(`HTTP ${response.status}: ${error}`);
    }
    
    const result = await response.json();
    
    if (waitForResponse && result.data) {
      console.log(`Device ${partialUid} responded with:`, result.data);
    } else {
      console.log(`Command sent to device ${partialUid}`);
    }
    
    return result;
  } catch (error) {
    console.error('Device control failed:', error);
    throw error;
  }
}

Device Status Check

javascript
async function checkDeviceStatus(partialUid) {
  // Send status query command (example hex data)
  const statusCommand = "010203"; // Replace with actual status command
  
  try {
    const result = await sendDeviceCommand(partialUid, statusCommand, true);
    
    if (result.data && result.data.length > 0) {
      // Parse device response
      const statusData = result.data[0];
      console.log(`Device ${partialUid} status: ${statusData}`);
      return parseDeviceStatus(statusData);
    }
    
    throw new Error('No status data received');
  } catch (error) {
    console.error(`Failed to get status for device ${partialUid}:`, error);
    throw error;
  }
}

function parseDeviceStatus(hexData) {
  // Example status parsing - replace with actual parsing logic
  return {
    battery: parseInt(hexData.substr(0, 2), 16),
    signal: parseInt(hexData.substr(2, 2), 16),
    mode: parseInt(hexData.substr(4, 2), 16)
  };
}

Batch Device Control

javascript
class DeviceController {
  constructor(token) {
    this.token = token;
    this.pendingCommands = new Map();
  }
  
  async sendCommand(partialUid, data, options = {}) {
    const requestId = options.requestId || `cmd-${Date.now()}-${Math.random()}`;
    
    const command = {
      partial_uid: partialUid,
      data: data,
      request_id: requestId,
      response_required: options.waitForResponse || false,
      cloud_access_code: options.cloudAccessCode
    };
    
    try {
      const response = await fetch('/api/control-device', {
        method: 'POST',
        headers: {
          'Authorization': `Bearer ${this.token}`,
          'Content-Type': 'application/json'
        },
        body: JSON.stringify(command)
      });
      
      if (!response.ok) {
        throw new Error(await response.text());
      }
      
      return await response.json();
    } catch (error) {
      console.error(`Command failed for device ${partialUid}:`, error);
      throw error;
    }
  }
  
  async sendToMultipleDevices(devices, commandData) {
    const results = [];
    
    for (const device of devices) {
      try {
        const result = await this.sendCommand(device.partial_uid, commandData);
        results.push({
          device: device.partial_uid,
          status: 'success',
          result: result
        });
      } catch (error) {
        results.push({
          device: device.partial_uid,
          status: 'error',
          error: error.message
        });
      }
    }
    
    return results;
  }
}

// Usage
const controller = new DeviceController(authToken);

// Send command to single device
await controller.sendCommand('ABC123', '010203', {
  waitForResponse: true,
  requestId: 'status-check'
});

// Send same command to multiple devices
const devices = [
  { partial_uid: 'ABC123' },
  { partial_uid: 'DEF456' },
  { partial_uid: 'GHI789' }
];

const results = await controller.sendToMultipleDevices(devices, '040506');

Command Queue Management

javascript
class CommandQueue {
  constructor(maxConcurrent = 5) {
    this.queue = [];
    this.running = new Set();
    this.maxConcurrent = maxConcurrent;
  }
  
  async addCommand(partialUid, data, options = {}) {
    return new Promise((resolve, reject) => {
      this.queue.push({
        partialUid,
        data,
        options,
        resolve,
        reject
      });
      
      this.processQueue();
    });
  }
  
  async processQueue() {
    if (this.running.size >= this.maxConcurrent || this.queue.length === 0) {
      return;
    }
    
    const command = this.queue.shift();
    const commandPromise = this.executeCommand(command);
    
    this.running.add(commandPromise);
    
    try {
      const result = await commandPromise;
      command.resolve(result);
    } catch (error) {
      command.reject(error);
    } finally {
      this.running.delete(commandPromise);
      this.processQueue(); // Process next command
    }
  }
  
  async executeCommand(command) {
    return sendDeviceCommand(
      command.partialUid,
      command.data,
      command.options.waitForResponse
    );
  }
}

// Usage
const commandQueue = new CommandQueue(3); // Max 3 concurrent commands

// Queue multiple commands
commandQueue.addCommand('ABC123', '010203');
commandQueue.addCommand('DEF456', '040506');
commandQueue.addCommand('GHI789', '070809');

Data Format Guidelines

Hex String Format

  • Use uppercase or lowercase hex characters (A-F, 0-9)
  • No spaces, hyphens, or other separators
  • Examples: 01020304, ABCDEF123456, FF00AA55

Command Structure

Commands should follow your device's protocol specification:

[HEADER][COMMAND][DATA][CHECKSUM]

Example command breakdown:

  • 01 - Header
  • 02 - Command type
  • 0304 - Data payload
  • AB - Checksum

Response Parsing

Device responses are returned as hex strings in an array:

json
{
  "data": ["010203ABCDEF", "040506789012"]
}

Each array element represents a separate response packet from the device.

Security Considerations

Scope Requirements

  • device_control: Required for all device control operations
  • omit_mpass: Special scope that bypasses master password requirements

Master Password

  • Some operations may require master password verification
  • Users with omit_mpass scope can bypass this requirement
  • Implement additional security checks in your application if needed

Command Validation

  • Validate hex data format before sending
  • Implement command whitelisting for security
  • Log all device control operations for audit trails

Timeout and Reliability

Response Timeout

  • Device response timeout is 10 seconds
  • Commands without response_required return immediately after sending
  • Consider device communication latency in your application

Retry Logic

javascript
async function sendCommandWithRetry(partialUid, data, maxRetries = 3) {
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      return await sendDeviceCommand(partialUid, data, true);
    } catch (error) {
      if (attempt === maxRetries) throw error;
      
      console.log(`Command attempt ${attempt} failed, retrying...`);
      await new Promise(resolve => setTimeout(resolve, 1000 * attempt));
    }
  }
}

Important Notes

  • Scope Required: Users must have the device_control scope
  • Hex Format: All data must be in valid hexadecimal format
  • Response Timeout: 10 seconds maximum wait time for device responses
  • Multiple Packets: Device may respond with multiple data packets
  • Request Tracking: Use request_id for operation tracking and logging
  • Error Formats: Mix of JSON and plain text error responses
  • Master Password: May be required unless user has omit_mpass scope

Released under the MIT License.