energy-manager-iot
Version:
Library for energy management in IoT devices via MQTT protocol. Documentation: https://jonhvmp.github.io/energy-manager-iot-docs/
208 lines (207 loc) • 7.77 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
const index_1 = require("../../index");
const mqtt = __importStar(require("mqtt"));
/**
* Integration tests for MQTT communication
*
* These tests require a local MQTT broker running on port 1883.
* Tests will be skipped if the broker is not available.
*
* @group integration
*/
// This test requires a local MQTT broker running on port 1883
// Skip if not available
const localBrokerAvailable = async () => {
let client = undefined;
let timeoutHandle = null;
try {
return new Promise((resolve) => {
// Create timeout to avoid test hanging waiting for connection
timeoutHandle = setTimeout(() => {
if (client) {
client.removeAllListeners();
client.end(true, {}, () => resolve(false));
}
else {
resolve(false);
}
}, 1000);
// Try to connect
client = mqtt.connect('mqtt://localhost:1883', {
connectTimeout: 1000,
reconnectPeriod: 0
});
client.on('connect', () => {
if (timeoutHandle)
clearTimeout(timeoutHandle);
client?.end(true, {}, () => resolve(true));
});
client.on('error', () => {
if (timeoutHandle)
clearTimeout(timeoutHandle);
client?.removeAllListeners();
client?.end(true, {}, () => resolve(false));
});
});
}
catch (e) {
if (timeoutHandle)
clearTimeout(timeoutHandle);
// Fix type error using explicit type check
// and a non-null assertion to ensure TypeScript recognizes client
if (client) {
const mqttClient = client;
mqttClient.removeAllListeners();
mqttClient.end(true, {});
}
return false;
}
};
describe('MQTT Integration', () => {
let energyManager;
let testClient;
let brokerAvailable = false;
// Check if broker is available before tests
beforeAll(async () => {
try {
brokerAvailable = await localBrokerAvailable();
if (!brokerAvailable) {
console.warn('Local MQTT broker not available. Integration tests will be skipped.');
}
}
catch (error) {
console.error('Error checking broker availability:', error);
brokerAvailable = false;
}
});
beforeEach(async () => {
if (!brokerAvailable) {
return;
}
// Create manager instance
energyManager = new index_1.EnergyManager({
topicPrefix: 'test/devices/'
});
// Connect to broker
await energyManager.connect('mqtt://localhost:1883');
// Test client to simulate devices
testClient = mqtt.connect('mqtt://localhost:1883', {
clientId: `test-client-${Date.now()}`
});
// Wait for test client to connect
await new Promise((resolve) => {
testClient.on('connect', () => resolve());
});
});
afterEach(async () => {
if (!brokerAvailable) {
return;
}
// Clean up resources
if (energyManager) {
await energyManager.disconnect();
}
if (testClient) {
await new Promise((resolve) => {
testClient.end(false, {}, () => resolve());
});
}
});
test('should update status when receiving message from device', async () => {
if (!brokerAvailable) {
return;
}
// Register device
energyManager.registerDevice('sensor1', 'Test Sensor', index_1.DeviceType.SENSOR);
// Set up status listener
const statusUpdatePromise = new Promise((resolve) => {
energyManager.on('statusUpdate', (deviceId, status) => {
if (deviceId === 'sensor1' && status.batteryLevel === 85) {
resolve();
}
});
});
// Publish status message simulating the device
testClient.publish('test/devices/sensor1/status', JSON.stringify({
batteryLevel: 85,
powerMode: index_1.PowerMode.NORMAL,
connectionStatus: index_1.ConnectionStatus.ONLINE
}));
// Wait for status update
await statusUpdatePromise;
// Verify status was updated
const device = energyManager.getDevice('sensor1');
expect(device.status).toBeDefined();
expect(device.status?.batteryLevel).toBe(85);
expect(device.status?.powerMode).toBe(index_1.PowerMode.NORMAL);
}, 5000); // 5 second timeout
test('should send command to device', async () => {
if (!brokerAvailable) {
return;
}
// Register device
energyManager.registerDevice('sensor1', 'Test Sensor', index_1.DeviceType.SENSOR);
// Promise to verify command reception
const commandReceivedPromise = new Promise((resolve) => {
testClient.subscribe('test/devices/sensor1/command', (err) => {
if (err) {
console.error('Error subscribing to command topic:', err);
}
});
testClient.on('message', (topic, message) => {
if (topic === 'test/devices/sensor1/command') {
try {
const command = JSON.parse(message.toString());
resolve(command);
}
catch (e) {
console.error('Error parsing command:', e);
}
}
});
});
// Fixed: Using CommandType enum instead of string literal
await energyManager.sendCommand('sensor1', index_1.CommandType.SLEEP, { duration: 300 });
// Wait for command reception
const command = await commandReceivedPromise;
// Verify command
expect(command).toBeDefined();
expect(command.type).toBe(index_1.CommandType.SLEEP);
expect(command.payload).toEqual({ duration: 300 });
expect(command.requestId).toBeDefined();
}, 5000); // 5 second timeout
});