Appearance
Configure Device
Send configuration commands to a device (object) identified by its partial UID. This endpoint is specifically designed for device configuration operations, distinct from general control commands.
Request
http
POST /api/config-deviceAuthentication 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": "config-123",
"data": "01020304ABCDEF",
"cloud_access_code": "XYZ123",
"response_required": true
}Request Fields
| Field | Type | Required | Description |
|---|---|---|---|
partial_uid | string | Yes | Partial UID of the target device (hex format) |
request_id | string | No | Optional identifier for tracking this configuration request |
data | string | Yes | Configuration data to send to device (hex format) |
cloud_access_code | string | No | Cloud access code for the device |
response_required | boolean | No | Whether to wait for device response (default: false) |
Request Examples
Send Configuration Without Response
bash
curl -X POST "http://your-server-ip:port/api/config-device" \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"partial_uid": "ABC123",
"data": "050607080910"
}'Send Configuration and Wait for Response
bash
curl -X POST "http://your-server-ip:port/api/config-device" \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"partial_uid": "ABC123",
"request_id": "config-update-001",
"data": "050607080910ABCDEF",
"response_required": true
}'Response
Success (200 OK)
Configuration Applied Successfully:
json
{
"partial_uid": "ABCDEF123456",
"request_id": "config-123",
"uid": "AABBCCDDEEFF",
"data": ["050607080910", "ABCDEF123456"],
"hw_id": "01",
"oid": "1234567890"
}Configuration Sent (No Response Required):
json
{
"partial_uid": "ABCDEF123456",
"request_id": "config-123",
"status": "configuration_sent"
}Response Fields
| Field | Type | Description |
|---|---|---|
partial_uid | string | The queried partial UID |
request_id | string | Request identifier (if provided) |
uid | string | Full unique identifier of the device |
data | array | Array of response data packets from device (hex format) |
hw_id | string | Hardware identifier |
oid | string | Object identifier |
status | string | Operation status (when no response required) |
Error Responses
400 Bad Request (Plain Text)
FIELD_UID_IS_MISSINGINVALID_DATAInvalid request401 Unauthorized (Plain Text)
NOT_LOGGED_IN403 Forbidden (Plain Text)
FORBIDDEN405 Method Not Allowed (Plain Text)
Method Not AllowedTimeout (JSON)
json
{
"error": "NO_RESPONSE",
"message": "Device did not respond within 10 seconds"
}Configuration Errors (JSON)
json
{
"error": "Device not connected"
}json
{
"error": "Invalid configuration format"
}Usage Examples
Basic Device Configuration
javascript
async function configureDevice(partialUid, configData, waitForResponse = false) {
try {
const response = await fetch('/api/config-device', {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
partial_uid: partialUid,
data: configData,
response_required: waitForResponse,
request_id: `config-${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} configuration response:`, result.data);
} else {
console.log(`Configuration sent to device ${partialUid}`);
}
return result;
} catch (error) {
console.error('Device configuration failed:', error);
throw error;
}
}Device Settings Update
javascript
class DeviceConfigurator {
constructor(token) {
this.token = token;
}
async updateDeviceSettings(partialUid, settings) {
// Convert settings object to device-specific hex format
const configData = this.encodeSettings(settings);
try {
const result = await this.sendConfiguration(partialUid, configData, true);
if (result.data && result.data.length > 0) {
// Parse configuration confirmation
const confirmation = this.parseConfigResponse(result.data[0]);
console.log(`Device ${partialUid} configuration updated:`, confirmation);
return confirmation;
}
throw new Error('No configuration confirmation received');
} catch (error) {
console.error(`Failed to configure device ${partialUid}:`, error);
throw error;
}
}
async sendConfiguration(partialUid, data, waitForResponse = false) {
const response = await fetch('/api/config-device', {
method: 'POST',
headers: {
'Authorization': `Bearer ${this.token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
partial_uid: partialUid,
data: data,
response_required: waitForResponse,
request_id: `config-${Date.now()}`
})
});
if (!response.ok) {
throw new Error(await response.text());
}
return await response.json();
}
encodeSettings(settings) {
// Example: Convert settings to device protocol format
// This would be device-specific implementation
let configHex = '';
// Configuration header
configHex += '05'; // Config command
// Ping interval (2 bytes)
if (settings.pingInterval) {
const interval = settings.pingInterval.toString(16).padStart(4, '0');
configHex += interval;
}
// Enable/disable features (1 byte)
let features = 0;
if (settings.enableGPS) features |= 0x01;
if (settings.enableSMS) features |= 0x02;
if (settings.enableAlerts) features |= 0x04;
configHex += features.toString(16).padStart(2, '0');
return configHex.toUpperCase();
}
parseConfigResponse(hexData) {
// Example: Parse device configuration response
return {
status: hexData.substr(0, 2) === '06' ? 'success' : 'error',
configApplied: hexData.substr(2, 2) === 'FF',
deviceTime: parseInt(hexData.substr(4, 8), 16)
};
}
}
// Usage
const configurator = new DeviceConfigurator(authToken);
// Update device settings
await configurator.updateDeviceSettings('ABC123', {
pingInterval: 300,
enableGPS: true,
enableSMS: true,
enableAlerts: false
});Batch Configuration
javascript
async function configureMultipleDevices(devices, configData) {
const results = [];
for (const device of devices) {
try {
const result = await configureDevice(device.partial_uid, configData, true);
results.push({
device: device.partial_uid,
status: 'success',
result: result,
timestamp: new Date().toISOString()
});
// Small delay between configurations to avoid overwhelming devices
await new Promise(resolve => setTimeout(resolve, 1000));
} catch (error) {
results.push({
device: device.partial_uid,
status: 'error',
error: error.message,
timestamp: new Date().toISOString()
});
}
}
return results;
}
// Usage
const deviceList = [
{ partial_uid: 'ABC123', type: 'sensor' },
{ partial_uid: 'DEF456', type: 'controller' },
{ partial_uid: 'GHI789', type: 'monitor' }
];
const commonConfig = '050A003C01'; // Example configuration
const results = await configureMultipleDevices(deviceList, commonConfig);
// Log results
results.forEach(result => {
if (result.status === 'success') {
console.log(`✓ Device ${result.device} configured successfully`);
} else {
console.log(`✗ Device ${result.device} failed: ${result.error}`);
}
});Configuration Validation
javascript
class ConfigurationValidator {
static validateHexData(data) {
// Check if valid hex string
if (!/^[0-9A-Fa-f]+$/.test(data)) {
throw new Error('Invalid hex format');
}
// Check minimum length for configuration commands
if (data.length < 4) {
throw new Error('Configuration data too short');
}
// Check if even length (complete bytes)
if (data.length % 2 !== 0) {
throw new Error('Configuration data must have even length');
}
return true;
}
static validateConfiguration(config) {
// Validate configuration object
if (!config.partial_uid) {
throw new Error('Partial UID is required');
}
if (!config.data) {
throw new Error('Configuration data is required');
}
this.validateHexData(config.data);
return true;
}
}
// Usage with validation
async function safeConfigureDevice(partialUid, configData) {
try {
// Validate before sending
ConfigurationValidator.validateConfiguration({
partial_uid: partialUid,
data: configData
});
return await configureDevice(partialUid, configData, true);
} catch (error) {
console.error('Configuration validation failed:', error);
throw error;
}
}Configuration Examples
Device Time Synchronization
javascript
async function syncDeviceTime(partialUid) {
const currentTime = Math.floor(Date.now() / 1000);
const timeHex = currentTime.toString(16).padStart(8, '0');
const configData = `10${timeHex}`; // Command 0x10 + timestamp
return await configureDevice(partialUid, configData, true);
}Update Reporting Interval
javascript
async function setReportingInterval(partialUid, intervalMinutes) {
const intervalHex = intervalMinutes.toString(16).padStart(4, '0');
const configData = `20${intervalHex}`; // Command 0x20 + interval
return await configureDevice(partialUid, configData, true);
}Configure Alert Thresholds
javascript
async function setAlertThresholds(partialUid, thresholds) {
let configData = '30'; // Command 0x30
// Temperature threshold (1 byte, signed)
const tempThreshold = (thresholds.temperature + 128) & 0xFF;
configData += tempThreshold.toString(16).padStart(2, '0');
// Humidity threshold (1 byte)
configData += thresholds.humidity.toString(16).padStart(2, '0');
// Battery threshold (1 byte, percentage)
configData += thresholds.battery.toString(16).padStart(2, '0');
return await configureDevice(partialUid, configData, true);
}
// Usage
await setAlertThresholds('ABC123', {
temperature: 35, // °C
humidity: 80, // %
battery: 20 // %
});Error Handling and Recovery
javascript
async function configureWithRetry(partialUid, configData, maxRetries = 3) {
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
const result = await configureDevice(partialUid, configData, true);
// Verify configuration was applied
if (result.data && result.data[0].startsWith('06')) {
console.log(`Configuration successful on attempt ${attempt}`);
return result;
} else {
throw new Error('Configuration not confirmed by device');
}
} catch (error) {
console.log(`Configuration attempt ${attempt} failed:`, error.message);
if (attempt === maxRetries) {
throw new Error(`Configuration failed after ${maxRetries} attempts: ${error.message}`);
}
// Exponential backoff
const delay = Math.pow(2, attempt) * 1000;
await new Promise(resolve => setTimeout(resolve, delay));
}
}
}Security and Best Practices
Configuration Logging
javascript
class ConfigurationLogger {
static log(operation, partialUid, configData, result) {
const logEntry = {
timestamp: new Date().toISOString(),
operation: operation,
device: partialUid,
config: configData,
result: result.status || 'unknown',
user: this.getCurrentUser() // Implement based on your auth system
};
// Send to audit log
console.log('CONFIG_AUDIT:', JSON.stringify(logEntry));
}
static getCurrentUser() {
// Extract user from JWT token
try {
const token = localStorage.getItem('authToken');
const payload = JSON.parse(atob(token.split('.')[1]));
return payload.username || payload.sub;
} catch {
return 'unknown';
}
}
}
// Use in configuration functions
const result = await configureDevice(partialUid, configData);
ConfigurationLogger.log('device_config', partialUid, configData, result);Important Notes
- Scope Required: Users must have the
device_controlscope - Configuration vs Control: Use this endpoint for device settings, use
/api/control-devicefor operational commands - Hex Format: All configuration data must be in valid hexadecimal format
- Response Timeout: 10 seconds maximum wait time for device responses
- Validation: Always validate configuration data before sending
- Device Protocol: Configuration format depends on specific device protocol implementation