homebridge-sleeptracker
Version:
Homebridge plugin for SleepTracker smart beds - Control your bed's position and features through HomeKit
292 lines • 12.2 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.SleepTrackerAccessory = void 0;
const client_1 = require("./api/client");
const types_1 = require("./api/types");
class SleepTrackerAccessory {
constructor(platform, accessory) {
this.platform = platform;
this.accessory = accessory;
this.isInitialized = false;
this.lastKnownState = {
temperature: null,
humidity: null,
};
this.MAX_RETRIES = 3;
this.RETRY_DELAY = 1000; // 1초
this.client = new client_1.SleepTrackerClient(this.platform.config.username, this.platform.config.password, this.platform.config.deviceId);
this.accessory.getService(this.platform.Service.AccessoryInformation)
.setCharacteristic(this.platform.Characteristic.Manufacturer, 'SleepTracker')
.setCharacteristic(this.platform.Characteristic.Model, 'Smart Bed')
.setCharacteristic(this.platform.Characteristic.SerialNumber, this.platform.config.deviceId);
// Head Up switch
this.headUpService = this.accessory.getService('Head Up') ||
this.accessory.addService(this.platform.Service.Switch, 'Head Up', 'head-up');
this.headUpService.getCharacteristic(this.platform.Characteristic.On)
.onSet(this.setHeadUp.bind(this))
.onGet(this.getHeadUp.bind(this));
// Head Down switch
this.headDownService = this.accessory.getService('Head Down') ||
this.accessory.addService(this.platform.Service.Switch, 'Head Down', 'head-down');
this.headDownService.getCharacteristic(this.platform.Characteristic.On)
.onSet(this.setHeadDown.bind(this))
.onGet(this.getHeadDown.bind(this));
// Foot Up switch
this.footUpService = this.accessory.getService('Foot Up') ||
this.accessory.addService(this.platform.Service.Switch, 'Foot Up', 'foot-up');
this.footUpService.getCharacteristic(this.platform.Characteristic.On)
.onSet(this.setFootUp.bind(this))
.onGet(this.getFootUp.bind(this));
// Foot Down switch
this.footDownService = this.accessory.getService('Foot Down') ||
this.accessory.addService(this.platform.Service.Switch, 'Foot Down', 'foot-down');
this.footDownService.getCharacteristic(this.platform.Characteristic.On)
.onSet(this.setFootDown.bind(this))
.onGet(this.getFootDown.bind(this));
// Preset services
this.flatPresetService = this.accessory.getService('Flat Position') ||
this.accessory.addService(this.platform.Service.Switch, 'Flat Position', 'flat-preset');
this.flatPresetService.getCharacteristic(this.platform.Characteristic.On)
.onSet(this.setFlatPreset.bind(this))
.onGet(this.getPresetState.bind(this));
this.zeroGPresetService = this.accessory.getService('Zero G') ||
this.accessory.addService(this.platform.Service.Switch, 'Zero G', 'zerog-preset');
this.zeroGPresetService.getCharacteristic(this.platform.Characteristic.On)
.onSet(this.setZeroGPreset.bind(this))
.onGet(this.getPresetState.bind(this));
this.antiSnorePresetService = this.accessory.getService('Anti Snore') ||
this.accessory.addService(this.platform.Service.Switch, 'Anti Snore', 'antisnore-preset');
this.antiSnorePresetService.getCharacteristic(this.platform.Characteristic.On)
.onSet(this.setAntiSnorePreset.bind(this))
.onGet(this.getPresetState.bind(this));
this.tvPresetService = this.accessory.getService('TV Position') ||
this.accessory.addService(this.platform.Service.Switch, 'TV Position', 'tv-preset');
this.tvPresetService.getCharacteristic(this.platform.Characteristic.On)
.onSet(this.setTVPreset.bind(this))
.onGet(this.getPresetState.bind(this));
// Initialize device with retries
this.initializeDeviceWithRetry();
// Start polling for updates (only for environment sensors)
if (this.platform.config.enableEnvironmentSensors) {
setInterval(() => this.updateState(), this.platform.config.refreshInterval * 1000 || 30000);
}
}
async initializeDeviceWithRetry(retryCount = 0) {
try {
await this.initializeDevice();
this.isInitialized = true;
}
catch (error) {
if (retryCount < this.MAX_RETRIES) {
this.platform.log.warn(`Failed to initialize device, retrying in ${this.RETRY_DELAY}ms...`);
setTimeout(() => this.initializeDeviceWithRetry(retryCount + 1), this.RETRY_DELAY);
}
else {
this.platform.log.error('Failed to initialize device after maximum retries');
}
}
}
async initializeDevice() {
const deviceInfo = await this.client.getDeviceInfo(this.platform.config.deviceId);
// Setup environment sensors if enabled
if (this.platform.config.enableEnvironmentSensors && deviceInfo.productFeatures.includes('env_sensors')) {
this.setupEnvironmentSensors();
}
}
setupEnvironmentSensors() {
// Temperature sensor
this.temperatureService = this.accessory.getService('Temperature') ||
this.accessory.addService(this.platform.Service.TemperatureSensor, 'Temperature', 'temperature');
// Humidity sensor
this.humidityService = this.accessory.getService('Humidity') ||
this.accessory.addService(this.platform.Service.HumiditySensor, 'Humidity', 'humidity');
}
async updateState() {
if (!this.isInitialized || !this.platform.config.enableEnvironmentSensors) {
return;
}
try {
// Update environment sensors if available
if (this.temperatureService || this.humidityService) {
const sensorData = await this.client.getEnvironmentSensorData(this.platform.config.deviceId);
if (sensorData.temperature !== null && this.temperatureService) {
this.lastKnownState.temperature = sensorData.temperature;
this.temperatureService.updateCharacteristic(this.platform.Characteristic.CurrentTemperature, sensorData.temperature);
}
if (sensorData.humidity !== null && this.humidityService) {
this.lastKnownState.humidity = sensorData.humidity;
this.humidityService.updateCharacteristic(this.platform.Characteristic.CurrentRelativeHumidity, sensorData.humidity);
}
}
}
catch (error) {
this.platform.log.error('Failed to update environment sensors:', error);
}
}
async sendCommandWithRetry(command, retryCount = 0) {
try {
await this.client.sendCommand(this.platform.config.deviceId, command);
}
catch (error) {
if (retryCount < this.MAX_RETRIES) {
this.platform.log.warn(`Command failed, retrying in ${this.RETRY_DELAY}ms...`);
await new Promise(resolve => setTimeout(resolve, this.RETRY_DELAY));
return this.sendCommandWithRetry(command, retryCount + 1);
}
throw error;
}
}
// Head position handlers
async setHeadUp(value) {
if (value) {
try {
await this.sendCommandWithRetry(types_1.Commands.HeadUp);
}
catch (error) {
this.platform.log.error('Failed to start head up movement:', error);
throw error;
}
}
else {
try {
await this.sendCommandWithRetry(types_1.Commands.Stop);
}
catch (error) {
this.platform.log.error('Failed to stop movement:', error);
throw error;
}
}
}
async getHeadUp() {
return false; // Always return false to allow toggling
}
async setHeadDown(value) {
if (value) {
try {
await this.sendCommandWithRetry(types_1.Commands.HeadDown);
}
catch (error) {
this.platform.log.error('Failed to start head down movement:', error);
throw error;
}
}
else {
try {
await this.sendCommandWithRetry(types_1.Commands.Stop);
}
catch (error) {
this.platform.log.error('Failed to stop movement:', error);
throw error;
}
}
}
async getHeadDown() {
return false; // Always return false to allow toggling
}
// Foot position handlers
async setFootUp(value) {
if (value) {
try {
await this.sendCommandWithRetry(types_1.Commands.FootUp);
}
catch (error) {
this.platform.log.error('Failed to start foot up movement:', error);
throw error;
}
}
else {
try {
await this.sendCommandWithRetry(types_1.Commands.Stop);
}
catch (error) {
this.platform.log.error('Failed to stop movement:', error);
throw error;
}
}
}
async getFootUp() {
return false; // Always return false to allow toggling
}
async setFootDown(value) {
if (value) {
try {
await this.sendCommandWithRetry(types_1.Commands.FootDown);
}
catch (error) {
this.platform.log.error('Failed to start foot down movement:', error);
throw error;
}
}
else {
try {
await this.sendCommandWithRetry(types_1.Commands.Stop);
}
catch (error) {
this.platform.log.error('Failed to stop movement:', error);
throw error;
}
}
}
async getFootDown() {
return false; // Always return false to allow toggling
}
// Preset handlers
async setFlatPreset(value) {
if (value) {
try {
await this.sendCommandWithRetry(types_1.Commands.Flat);
this.resetPresetSwitch(this.flatPresetService);
}
catch (error) {
this.platform.log.error('Failed to set Flat preset:', error);
throw error;
}
}
}
async setZeroGPreset(value) {
if (value) {
try {
await this.sendCommandWithRetry(types_1.Commands.ZeroG);
this.resetPresetSwitch(this.zeroGPresetService);
}
catch (error) {
this.platform.log.error('Failed to set Zero G preset:', error);
throw error;
}
}
}
async setAntiSnorePreset(value) {
if (value) {
try {
await this.sendCommandWithRetry(types_1.Commands.AntiSnore);
this.resetPresetSwitch(this.antiSnorePresetService);
}
catch (error) {
this.platform.log.error('Failed to set Anti Snore preset:', error);
throw error;
}
}
}
async setTVPreset(value) {
if (value) {
try {
await this.sendCommandWithRetry(types_1.Commands.TV);
this.resetPresetSwitch(this.tvPresetService);
}
catch (error) {
this.platform.log.error('Failed to set TV preset:', error);
throw error;
}
}
}
async getPresetState() {
return false;
}
resetPresetSwitch(service) {
setTimeout(() => {
service.updateCharacteristic(this.platform.Characteristic.On, false);
}, 1000);
}
}
exports.SleepTrackerAccessory = SleepTrackerAccessory;
//# sourceMappingURL=sleepTrackerAccessory.js.map