UNPKG

@chazepps/homebridge-hejhome

Version:

The Hejhome plugin allows you to access your Hejhome device(s) from HomeKit.

176 lines 7.64 kB
import Bluebird from 'bluebird'; import deepmerge from 'deepmerge'; import { EventEmitter } from 'events'; import lodash from 'lodash'; import mqtt from 'paho-mqtt'; import ws from 'ws'; import { EVENT_MOTION_DETECTED } from '../accessories/sensor_mo.js'; import { EVENT_BUTTON_PRESSED } from '../accessories/smart_button.js'; import { getDevices } from './get_devices.js'; import { getFamilies } from './get_family.js'; import { getRooms } from './get_rooms.js'; import { HEJ_CLIENT_ID, HEJ_CLIENT_SECRET } from './get_token.js'; const { Client } = mqtt; const { differenceBy, get, set } = lodash; global.WebSocket = ws; export const hejEvent = new EventEmitter(); export const hejAccessories = {}; export const hejDevices = {}; const deviceOverrides = {}; const families = {}; const client = new Client('ws://mqtt.hej.so:15675/ws', ''); const loadSnapshot = async (platform) => { const _families = await getFamilies(platform); await Bluebird.each(_families, async (family) => { set(families, `${family.familyId}`, { familyId: family.familyId, name: family.name, rooms: get(families, `${family.familyId}.rooms`, {}), }); const _rooms = await getRooms(platform, family.familyId); const allDevices = (await getDevices(platform, family.familyId)).map((i) => ({ ...i, deviceId: i.id })); allDevices.forEach((device) => { hejDevices[device.id] = device; }); const roomAssignedDeviceIds = []; await Bluebird.each(_rooms.rooms, async (room) => { set(families, `${family.familyId}.rooms.${room.room_id}`, { roomId: room.room_id, name: room.name, devices: [], }); const _devices = await getDevices(platform, family.familyId, room.room_id); await Bluebird.each(_devices, async (device) => { if (hejDevices[device.id]) { hejDevices[device.id].roomId = room.room_id; } roomAssignedDeviceIds.push(device.id); families[family.familyId].rooms[room.room_id].devices.push(device.id); }); }); const roomUnassignedDevices = differenceBy(allDevices.map((i) => i.id), roomAssignedDeviceIds); families[family.familyId].rooms['-1'] = { roomId: -1, name: 'Unassigned', devices: roomUnassignedDevices, }; }); }; export const startRealtime = async (platform) => { try { client.disconnect(); } catch (e) { // Handle error if needed } client.onConnectionLost = (e) => { platform.log.error('mqtt onConnectionLost', e); }; client.onMessageArrived = (e) => { try { const data = JSON.parse(e.payloadString); const devId = data.deviceDataReport?.devId; data.deviceDataReport?.status?.map((i) => { platform.log.debug(`MQTT device event: ${i.code}@${data.deviceDataReport?.devId}${i.value}`); }); if (data.deviceDataReport) { data.deviceDataReport.status.forEach((status) => { switch (status.code) { case 'switch_led': set(deviceOverrides, `${devId}.deviceState.power`, status.value); break; case 'work_mode': switch (status.value) { case 'white': { set(deviceOverrides, `${devId}.deviceState.lightMode`, 'WHITE'); break; } case 'colour': { set(deviceOverrides, `${devId}.deviceState.lightMode`, 'COLOR'); break; } case 'scene': { set(deviceOverrides, `${devId}.deviceState.lightMode`, 'SCENE'); break; } default: break; } break; case 'scene_data': set(deviceOverrides, `${devId}.deviceState.sceneValues`, status.value); break; case 'colour_data': { const { h, s, v } = JSON.parse(status.value); set(deviceOverrides, `${devId}.deviceState.hsvColor`, { hue: h, saturation: s / 256 * 100, brightness: v / 256 * 100, }); break; } case 'pir': hejEvent.emit(EVENT_MOTION_DETECTED, devId, status.value); break; case 'bright_value': set(deviceOverrides, `${devId}.deviceState.brightness`, status.value / 256 * 100); break; case 'switch_1': set(deviceOverrides, `${devId}.deviceState.power1`, status.value); break; case 'switch_2': set(deviceOverrides, `${devId}.deviceState.power2`, status.value); break; case 'switch1_value': case 'switch2_value': case 'switch3_value': case 'switch4_value': { const idx = Number(status.code.replace('switch', '').replace('_value', '')) - 1; hejEvent.emit(EVENT_BUTTON_PRESSED, devId, idx, status.value); break; } default: platform.log.info('unknown status code', status); break; } }); } if (devId) { const cached = hejDevices[devId]; if (cached) { const updated = deviceOverrides[devId] || {}; hejDevices[devId] = deepmerge(cached, updated); } hejEvent.emit('deviceUpdated', hejDevices[devId]); } } catch (error) { platform.log.error('mqtt onMessageArrived processing error', error); } }; client.connect({ timeout: 3, keepAliveInterval: 30, userName: HEJ_CLIENT_ID, password: HEJ_CLIENT_SECRET, useSSL: false, onSuccess: () => { const email = platform.config.credentials?.email.replace(/\./gi, '-').replace(/%40/gi, '@'); client.subscribe(`custom.${email}.*`, { qos: 1, timeout: 10, onSuccess: () => { platform.log.info('mqtt subscribe onSuccess'); }, onFailure: () => { platform.log.info('mqtt subscribe onFailure'); }, }); }, onFailure: (e) => { platform.log.info('mqtt conn onFailure', e.errorMessage, e.errorCode); }, }); await loadSnapshot(platform); }; //# sourceMappingURL=realtime.js.map