Appearance
OID Override
Set or update the override OID for a device (object) or its related objects. This endpoint allows you to change the OID value used for a specific device identified by UID or OID.
Request
http
PUT /api/oid-overrideAuthentication Required: Must include JWT token in Authorization header.
Required Scope: objects
Content-Type: application/json
Request Body:
json
{
"uid": "ABCDEF123456", // hex string, optional
"oid": "1234567890", // hex string, optional
"related_oid": "9876543210", // hex string, optional
"new_override_oid": "1122334455" // hex string, required
}Parameter Logic:
- UID Priority: When
uidis provided,oidis ignored (UID takes precedence) - OID Fallback:
oidis only used whenuidis empty/not provided - Override Target:
- If
related_oidis specified → Updates the related object's OID override - If
related_oidis not specified → Updates the main device's OID override
- If
- At least one of
uidoroidmust be provided new_override_oidis always required
Request Examples
Set Override OID for Main Device by UID
bash
curl -X PUT "http://your-server-ip:port/api/oid-override" \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"uid": "ABCDEF123456",
"new_override_oid": "1122334455"
}'Set Override OID for Main Device by OID
bash
curl -X PUT "http://your-server-ip:port/api/oid-override" \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"oid": "1234567890",
"new_override_oid": "1122334455"
}'Set Override OID for Related Object by UID
bash
curl -X PUT "http://your-server-ip:port/api/oid-override" \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"uid": "ABCDEF123456",
"related_oid": "9876543210",
"new_override_oid": "1122334455"
}'Set Override OID for Related Object by OID (when UID is empty)
bash
curl -X PUT "http://your-server-ip:port/api/oid-override" \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"oid": "1234567890",
"related_oid": "9876543210",
"new_override_oid": "1122334455"
}'Response
Success (200 OK)
json
{
"success": true
}Error Responses
All error responses are returned as JSON:
400 Bad Request
json
{
"error": "Invalid data"
}json
{
"error": "UID or OID must be provided"
}json
{
"error": "New override OID is required"
}json
{
"error": "UID is too long"
}json
{
"error": "UID must be numeric"
}json
{
"error": "UID must be hexadecimal"
}json
{
"error": "UID parse error"
}json
{
"error": "Invalid OID"
}json
{
"error": "Invalid related_oid"
}json
{
"error": "Invalid new_override_oid"
}401 Unauthorized
json
{
"error": "NOT_LOGGED_IN"
}403 Forbidden
json
{
"error": "FORBIDDEN"
}405 Method Not Allowed
json
{
"error": "Method Not Allowed"
}503 Service Unavailable
json
{
"error": "Database is not ready"
}Parameter Precedence and Override Target
Parameter Priority Rules:
- UID Priority: When
uidis provided,oidis completely ignored - OID Fallback:
oidis only used whenuidis empty or not provided - Override Target Logic:
related_oiddetermines which object gets the override
Override Behavior:
uid=ABC123&new_override_oid=555→ Sets override OID 555 for main device ABC123 (oid ignored if present)oid=123456&new_override_oid=555(no uid) → Sets override OID 555 for main device with OID 123456uid=ABC123&related_oid=XYZ789&new_override_oid=555→ Sets override OID 555 for related object XYZ789 of device ABC123oid=123456&related_oid=XYZ789&new_override_oid=555(no uid) → Sets override OID 555 for related object XYZ789 of device with OID 123456
Important Notes:
- The override affects the OID value used for the specified object
- Main device identification follows UID priority over OID
- Related objects can have independent OID overrides from their parent device
Usage Examples
Basic OID Override
javascript
async function setOidOverride(uid = null, oid = null, relatedOid = null, newOverrideOid) {
// Validate required parameters
if (!uid && !oid) {
throw new Error('At least one of uid or oid must be provided');
}
if (!newOverrideOid) {
throw new Error('new_override_oid is required');
}
const payload = {
new_override_oid: newOverrideOid
};
if (uid) payload.uid = uid;
if (oid && !uid) payload.oid = oid; // Only include OID if UID is not provided
if (relatedOid) payload.related_oid = relatedOid;
try {
const response = await fetch('/api/oid-override', {
method: 'PUT',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify(payload)
});
if (!response.ok) {
const error = await response.json();
throw new Error(`HTTP ${response.status}: ${error.error}`);
}
const result = await response.json();
console.log('OID override set successfully');
return result;
} catch (error) {
console.error('Failed to set OID override:', error);
throw error;
}
}OID Override Manager Class
javascript
class OidOverrideManager {
constructor(token) {
this.token = token;
}
async setMainDeviceOverrideByUid(uid, newOverrideOid) {
console.log(`Setting OID override ${newOverrideOid} for main device UID ${uid}`);
return await this.setOverride({ uid, newOverrideOid });
}
async setMainDeviceOverrideByOid(oid, newOverrideOid) {
console.log(`Setting OID override ${newOverrideOid} for main device OID ${oid}`);
return await this.setOverride({ oid, newOverrideOid });
}
async setRelatedObjectOverrideByUid(parentUid, relatedOid, newOverrideOid) {
console.log(`Setting OID override ${newOverrideOid} for related object ${relatedOid} of device UID ${parentUid}`);
return await this.setOverride({ uid: parentUid, relatedOid, newOverrideOid });
}
async setRelatedObjectOverrideByOid(parentOid, relatedOid, newOverrideOid) {
console.log(`Setting OID override ${newOverrideOid} for related object ${relatedOid} of device OID ${parentOid}`);
return await this.setOverride({ oid: parentOid, relatedOid, newOverrideOid });
}
async setOverride({ uid = null, oid = null, relatedOid = null, newOverrideOid }) {
const payload = {
new_override_oid: newOverrideOid
};
if (uid) {
payload.uid = uid;
if (oid) {
console.warn('Both UID and OID provided - OID will be ignored, using UID only');
}
} else if (oid) {
payload.oid = oid;
}
if (relatedOid) {
payload.related_oid = relatedOid;
}
const response = await fetch('/api/oid-override', {
method: 'PUT',
headers: {
'Authorization': `Bearer ${this.token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify(payload)
});
if (!response.ok) {
const error = await response.json();
throw new Error(`Override failed: ${error.error}`);
}
return await response.json();
}
}
// Usage
const overrideManager = new OidOverrideManager(authToken);
// Set override for main device
await overrideManager.setMainDeviceOverrideByUid('ABC123', '1122334455');
// Set override for main device by OID (when UID not available)
await overrideManager.setMainDeviceOverrideByOid('1234567890', '1122334455');
// Set override for related object
await overrideManager.setRelatedObjectOverrideByUid('ABC123', 'SENSOR001', '1122334455');Batch Override Operations
javascript
class BatchOidOverrideManager {
constructor(token) {
this.token = token;
this.overrideManager = new OidOverrideManager(token);
}
async setMultipleOverrides(overrideOperations, confirmCallback = null) {
const results = [];
for (const operation of overrideOperations) {
try {
// Optional confirmation for each override
if (confirmCallback && !await confirmCallback(operation)) {
results.push({
operation: operation,
status: 'skipped',
reason: 'User cancelled'
});
continue;
}
const result = await this.overrideManager.setOverride(operation);
results.push({
operation: operation,
status: 'success',
result: result
});
const target = operation.relatedOid ? `related object ${operation.relatedOid}` : 'main device';
const identifier = operation.uid || operation.oid;
console.log(`✓ Set OID override ${operation.newOverrideOid} for ${target} (${identifier})`);
} catch (error) {
results.push({
operation: operation,
status: 'error',
error: error.message
});
const target = operation.relatedOid ? `related object ${operation.relatedOid}` : 'main device';
const identifier = operation.uid || operation.oid;
console.error(`✗ Failed to set override for ${target} (${identifier}): ${error.message}`);
}
}
return results;
}
async setDeviceAndComponentOverrides(deviceUid, mainOverrideOid, componentOverrides) {
const operations = [
// Main device override
{ uid: deviceUid, newOverrideOid: mainOverrideOid }
];
// Add component overrides
for (const component of componentOverrides) {
operations.push({
uid: deviceUid,
relatedOid: component.relatedOid,
newOverrideOid: component.newOverrideOid
});
}
return await this.setMultipleOverrides(operations);
}
}
// Usage
const batchOverride = new BatchOidOverrideManager(authToken);
// Set overrides for device and its components
const componentOverrides = [
{ relatedOid: 'SENSOR001', newOverrideOid: 'AAAA0001' },
{ relatedOid: 'MODULE001', newOverrideOid: 'BBBB0001' },
{ relatedOid: 'GPS001', newOverrideOid: 'CCCC0001' }
];
const results = await batchOverride.setDeviceAndComponentOverrides(
'ABC123', // Device UID
'1122334455', // Main device override OID
componentOverrides // Component overrides
);Error Handling and Validation
javascript
class OidOverrideValidator {
static validateHexString(value, fieldName) {
if (!value) return true; // Optional fields
// Check hex format
if (!/^[0-9A-Fa-f]+$/.test(value)) {
throw new Error(`${fieldName} must be in hexadecimal format`);
}
// Check length (adjust based on your system requirements)
if (value.length < 6 || value.length > 16) {
throw new Error(`${fieldName} length must be between 6 and 16 characters`);
}
return true;
}
static validateParameters(uid, oid, relatedOid, newOverrideOid) {
// At least one identifier required
if (!uid && !oid) {
throw new Error('At least one of uid or oid must be provided');
}
// New override OID is required
if (!newOverrideOid) {
throw new Error('new_override_oid is required');
}
// Warn if both UID and OID provided
if (uid && oid) {
console.warn('Both UID and OID provided - OID will be ignored, using UID only');
}
this.validateHexString(uid, 'UID');
this.validateHexString(oid, 'OID');
this.validateHexString(relatedOid, 'Related OID');
this.validateHexString(newOverrideOid, 'New Override OID');
return true;
}
}
// Usage with validation
async function safeSetOidOverride(uid, oid, relatedOid, newOverrideOid) {
try {
// Validate parameters
OidOverrideValidator.validateParameters(uid, oid, relatedOid, newOverrideOid);
// Proceed with override
return await setOidOverride(uid, oid, relatedOid, newOverrideOid);
} catch (error) {
console.error('Validation failed:', error.message);
throw error;
}
}Override Management Dashboard
javascript
class OidOverrideDashboard {
constructor(token) {
this.token = token;
this.overrideManager = new OidOverrideManager(token);
}
async showOverrideForm(deviceInfo) {
const form = {
deviceUid: deviceInfo.uid,
deviceOid: deviceInfo.oid,
currentOverride: deviceInfo.override_oid,
relatedObjects: deviceInfo.related_objects || []
};
return form;
}
async applyOverrideFromForm(formData) {
const operations = [];
// Main device override
if (formData.mainDeviceOverride) {
operations.push({
uid: formData.deviceUid,
newOverrideOid: formData.mainDeviceOverride
});
}
// Related object overrides
for (const relatedOverride of formData.relatedOverrides || []) {
if (relatedOverride.newOverrideOid) {
operations.push({
uid: formData.deviceUid,
relatedOid: relatedOverride.relatedOid,
newOverrideOid: relatedOverride.newOverrideOid
});
}
}
// Apply all overrides
const results = [];
for (const operation of operations) {
try {
const result = await this.overrideManager.setOverride(operation);
results.push({ operation, success: true, result });
} catch (error) {
results.push({ operation, success: false, error: error.message });
}
}
return results;
}
}Security Considerations
Override Validation
javascript
async function validateAndSetOverride(uid, oid, relatedOid, newOverrideOid) {
// Validate override OID format and range
if (!newOverrideOid.match(/^[0-9A-Fa-f]{8,16}$/)) {
throw new Error('Invalid override OID format');
}
// Check for conflicts with existing OIDs
const existingObjects = await getObjects();
const conflictingObject = existingObjects.find(obj =>
obj.oid === newOverrideOid || obj.override_oid === newOverrideOid
);
if (conflictingObject) {
throw new Error(`Override OID ${newOverrideOid} conflicts with existing object`);
}
return await setOidOverride(uid, oid, relatedOid, newOverrideOid);
}Audit Logging
javascript
class OverrideAuditLogger {
static async logOverride(uid, oid, relatedOid, newOverrideOid, success, error = null) {
const logEntry = {
timestamp: new Date().toISOString(),
action: 'oid_override',
target: {
uid: uid || null,
oid: oid || null,
related_oid: relatedOid || null,
new_override_oid: newOverrideOid
},
success: success,
error: error,
user: this.getCurrentUser()
};
console.log('OVERRIDE_AUDIT:', JSON.stringify(logEntry));
// Send to audit service
try {
await fetch('/api/audit/log', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(logEntry)
});
} catch (auditError) {
console.error('Failed to log audit entry:', auditError);
}
}
static getCurrentUser() {
try {
const token = localStorage.getItem('authToken');
const payload = JSON.parse(atob(token.split('.')[1]));
return payload.username || payload.sub;
} catch {
return 'unknown';
}
}
}
// Usage with audit logging
async function auditedSetOidOverride(uid, oid, relatedOid, newOverrideOid) {
try {
const result = await setOidOverride(uid, oid, relatedOid, newOverrideOid);
await OverrideAuditLogger.logOverride(uid, oid, relatedOid, newOverrideOid, true);
return result;
} catch (error) {
await OverrideAuditLogger.logOverride(uid, oid, relatedOid, newOverrideOid, false, error.message);
throw error;
}
}Important Notes
- Scope Required: Users must have the
objectsscope to access this endpoint - Override Target:
related_oiddetermines whether main device or related object gets the override - Parameter Precedence: UID always takes precedence over OID when both are provided
- Hex Format: All OID and UID values must be valid hexadecimal strings
- JSON Request: Request body must be valid JSON (unlike some GET endpoints)
- Database Dependency: Requires active database connection
- Override Persistence: OID overrides are stored permanently until changed again
- Conflict Prevention: Consider checking for OID conflicts before setting overrides