š§ Enhanced Technical Implementation with HCBB11
HCBB11 Multi-Status Configuration
// HCBB11 Beacon Configuration for MPHS
const HCBB11_CONFIG = {
uuid: "550e8400-e29b-41d4-a716-446655440000", // MPHS UUID
major: 1001, // Zone ID
minor: 2345, // Unique Premise ID
// Visual Configuration
led: {
count: 12,
colors: ['RED', 'ORANGE', 'YELLOW', 'BLUE', 'GREEN', 'WHITE'],
brightness: 100, // 0-100%
patterns: {
SOLID: { interval: 0 },
BLINK: { interval: 500 },
ALTERNATE: { interval: 1000 },
SEQUENCE: { interval: 800 },
RAPID: { interval: 200 }
}
},
// Audio Configuration
buzzer: {
patterns: {
OFF: { frequency: 0, duration: 0 },
BEEP_SLOW: { frequency: 2000, duration: 100, interval: 2000 },
BEEP_FAST: { frequency: 2500, duration: 50, interval: 500 },
CONTINUOUS: { frequency: 3000, duration: -1 }
}
},
// Power Management
battery: {
type: 'CR2477',
capacity: 1000, // mAh
lowThreshold: 20, // %
standbyConsumption: 31.4 // uA
}
};
Enhanced Multi-Status Detection Algorithm
class PremiseStatusManager {
constructor(premise) {
this.premise = premise;
this.statusFlags = [];
this.beacon = new HCBB11Controller(premise.beaconId);
}
analyzeStatus() {
this.statusFlags = [];
// Check all conditions with priorities
if (this.premise.operationalStatus === 'CLOSED') {
this.statusFlags.push({
type: 'CLOSED',
color: 'RED',
priority: 100,
sound: 'BEEP_FAST'
});
}
if (!this.premise.hasValidLicense) {
this.statusFlags.push({
type: 'NO_LICENSE',
color: 'ORANGE',
priority: 80,
sound: 'BEEP_FAST'
});
}
if (this.premise.licenseExpired) {
const daysExpired = this.getDaysExpired();
this.statusFlags.push({
type: 'LICENSE_EXPIRED',
color: 'YELLOW',
priority: 60 + Math.min(20, daysExpired * 0.5),
sound: daysExpired > 30 ? 'BEEP_FAST' : 'BEEP_SLOW'
});
}
if (this.premise.overdueInspection) {
const daysOverdue = this.getDaysOverdue();
this.statusFlags.push({
type: 'OVERDUE_INSPECTION',
color: 'BLUE',
priority: 40 + Math.min(20, daysOverdue * 0.2),
sound: 'BEEP_SLOW'
});
}
// Temperature violations get special handling
if (this.premise.hasTemperatureViolation) {
this.statusFlags.push({
type: 'TEMP_VIOLATION',
color: 'RED',
priority: 95,
sound: 'CONTINUOUS',
override: true // This overrides other patterns
});
}
return this.statusFlags;
}
updateBeaconPattern() {
const statuses = this.analyzeStatus();
if (statuses.length === 0) {
// All OK
this.beacon.setPattern({
colors: ['GREEN'],
pattern: 'SOLID',
sound: 'OFF'
});
return;
}
// Check for override conditions
const override = statuses.find(s => s.override);
if (override) {
this.beacon.setPattern({
colors: [override.color],
pattern: 'RAPID',
sound: override.sound,
brightness: 100
});
return;
}
// Sort by priority
statuses.sort((a, b) => b.priority - a.priority);
// Generate pattern based on number of issues
let pattern;
if (statuses.length === 1) {
pattern = {
colors: [statuses[0].color],
pattern: 'SOLID',
sound: statuses[0].sound
};
} else if (statuses.length === 2) {
pattern = {
colors: statuses.map(s => s.color),
pattern: 'ALTERNATE',
sound: 'BEEP_FAST'
};
} else {
// 3 or more issues
pattern = {
colors: statuses.slice(0, 4).map(s => s.color), // Max 4 colors
pattern: 'SEQUENCE',
sound: 'BEEP_FAST',
brightness: 100
};
}
this.beacon.setPattern(pattern);
}
}
Real-time Beacon Control API
// WebSocket API for real-time beacon control
class BeaconControlAPI {
constructor() {
this.ws = new WebSocket('wss://api.mphs.gov.my/beacon-control');
this.setupHandlers();
}
// Inspector controls specific beacon
findPremise(beaconId) {
this.send({
action: 'FIND_MODE',
beaconId: beaconId,
pattern: {
colors: ['WHITE'],
pattern: 'RAPID',
sound: 'BEEP_FAST',
duration: 30000 // 30 seconds
}
});
}
// Command center broadcasts
emergencyAlert(zoneId) {
this.send({
action: 'EMERGENCY_BROADCAST',
zoneId: zoneId,
pattern: {
colors: ['RED', 'WHITE'],
pattern: 'RAPID',
sound: 'CONTINUOUS',
override: true
}
});
}
// Batch update for efficiency
batchUpdateBeacons(updates) {
this.send({
action: 'BATCH_UPDATE',
updates: updates.map(u => ({
beaconId: u.beaconId,
pattern: this.generatePattern(u.statuses)
}))
});
}
// Pattern analytics
getZonePatternSummary(zoneId) {
return this.request({
action: 'GET_ZONE_PATTERNS',
zoneId: zoneId
}).then(data => {
return {
total: data.beacons.length,
byStatus: {
green: data.beacons.filter(b => b.pattern === 'SOLID_GREEN').length,
singleIssue: data.beacons.filter(b => b.issues === 1).length,
multiIssue: data.beacons.filter(b => b.issues > 1).length,
critical: data.beacons.filter(b => b.priority > 90).length
}
};
});
}
}
Enhanced Database Schema for Multi-Status
-- Enhanced Premises Table
CREATE TABLE premises (
id UUID PRIMARY KEY,
beacon_minor INTEGER UNIQUE,
name VARCHAR(255),
type VARCHAR(100),
-- License Information
license_number VARCHAR(50),
license_expiry DATE,
license_status ENUM('VALID', 'EXPIRED', 'NONE'),
-- Operational Status
operational_status ENUM('OPEN', 'CLOSED', 'SUSPENDED'),
closure_reason VARCHAR(255),
-- Inspection Status
last_inspection_date TIMESTAMP,
next_inspection_due DATE,
current_grade CHAR(1),
-- Beacon Configuration
beacon_pattern JSON, -- Current pattern settings
beacon_battery_level INTEGER,
beacon_last_seen TIMESTAMP,
-- Multi-Status Flags
status_flags JSON, -- Array of current issues
priority_score INTEGER, -- Calculated priority
created_at TIMESTAMP,
updated_at TIMESTAMP
);
-- Beacon Pattern History
CREATE TABLE beacon_patterns (
id UUID PRIMARY KEY,
premise_id UUID REFERENCES premises(id),
timestamp TIMESTAMP,
pattern JSON, -- Pattern configuration
trigger_reason VARCHAR(100), -- What triggered the change
inspector_id UUID,
duration_seconds INTEGER
);
-- Status Change Events
CREATE TABLE status_events (
id UUID PRIMARY KEY,
premise_id UUID REFERENCES premises(id),
event_type VARCHAR(50), -- CLOSED, LICENSE_EXPIRED, etc
event_timestamp TIMESTAMP,
previous_status VARCHAR(50),
new_status VARCHAR(50),
beacon_pattern_change JSON,
notes TEXT
);
-- Real-time Analytics View
CREATE VIEW premise_status_summary AS
SELECT
p.zone_id,
COUNT(*) as total_premises,
SUM(CASE WHEN status_flags = '[]' THEN 1 ELSE 0 END) as ok_count,
SUM(CASE WHEN JSON_LENGTH(status_flags) = 1 THEN 1 ELSE 0 END) as single_issue,
SUM(CASE WHEN JSON_LENGTH(status_flags) = 2 THEN 1 ELSE 0 END) as double_issue,
SUM(CASE WHEN JSON_LENGTH(status_flags) >= 3 THEN 1 ELSE 0 END) as multi_issue,
SUM(CASE WHEN priority_score >= 90 THEN 1 ELSE 0 END) as critical_count
FROM premises p
GROUP BY p.zone_id;
Complete System Integration Flow
// Complete integration flow
async function completeInspectionFlow(inspectorId, location) {
// 1. Detect all beacons in range
const detectedBeacons = await scanForBeacons(location, 100); // 100m radius
// 2. Batch fetch premise data with status
const premises = await fetchPremiseData(detectedBeacons.map(b => b.id));
// 3. Calculate multi-status for each
const premisesWithStatus = premises.map(premise => {
const statusManager = new PremiseStatusManager(premise);
const statuses = statusManager.analyzeStatus();
return {
...premise,
statuses: statuses,
priorityScore: calculatePriorityScore(premise, statuses),
beaconPattern: statusManager.getBeaconPattern()
};
});
// 4. Update all beacon patterns via batch API
const beaconUpdates = premisesWithStatus.map(p => ({
beaconId: p.beaconMinor,
pattern: p.beaconPattern
}));
await beaconControlAPI.batchUpdateBeacons(beaconUpdates);
// 5. Sort by priority and return to app
return premisesWithStatus.sort((a, b) => b.priorityScore - a.priorityScore);
}
// Inspector selects a premise
async function startInspection(premiseId, inspectorId) {
// 1. Activate find mode
await beaconControlAPI.findPremise(premiseId);
// 2. Log inspection start
await logInspectionStart(premiseId, inspectorId);
// 3. Get real-time updates during inspection
const updateStream = subscribeToUpdates(premiseId);
return {
premiseId,
startTime: new Date(),
updateStream
};
}
// Complete inspection and update status
async function completeInspection(inspection, results) {
// 1. Calculate new status based on results
const newStatuses = calculateNewStatus(results);
// 2. Update beacon pattern immediately
const pattern = generatePatternFromStatus(newStatuses);
await beaconControlAPI.updateBeacon(inspection.premiseId, pattern);
// 3. Save to database
await saveInspectionResults(inspection, results, newStatuses);
// 4. Notify command center
await notifyCommandCenter({
premiseId: inspection.premiseId,
previousStatus: inspection.previousStatus,
newStatus: newStatuses,
inspectorId: inspection.inspectorId
});
}
Performance & Battery Optimization
// Intelligent battery management for HCBB11
class BeaconBatteryOptimizer {
constructor() {
this.batteryThresholds = {
critical: 10, // %
low: 20, // %
medium: 50, // %
good: 80 // %
};
}
optimizePattern(pattern, batteryLevel) {
// Reduce brightness and frequency based on battery
if (batteryLevel < this.batteryThresholds.critical) {
// Critical battery - minimal operation
return {
...pattern,
brightness: 30,
sound: 'OFF',
pattern: pattern.colors.length > 1 ? 'SLOW_ALTERNATE' : 'SOLID',
interval: pattern.interval * 3 // Triple the interval
};
} else if (batteryLevel < this.batteryThresholds.low) {
// Low battery - reduced operation
return {
...pattern,
brightness: 50,
sound: pattern.sound === 'CONTINUOUS' ? 'BEEP_SLOW' : pattern.sound,
interval: pattern.interval * 2
};
} else if (batteryLevel < this.batteryThresholds.medium) {
// Medium battery - slight optimization
return {
...pattern,
brightness: 80,
interval: pattern.interval * 1.5
};
}
// Good battery - full operation
return pattern;
}
// Predictive battery life calculation
calculateRemainingLife(beacon) {
const consumption = this.calculateConsumption(beacon.currentPattern);
const remainingCapacity = beacon.batteryLevel * beacon.batteryCapacity / 100;
return {
days: Math.floor(remainingCapacity / (consumption * 24)),
accuracy: this.getAccuracy(beacon.patternHistory)
};
}
}