UNPKG

node-red-contrib-smartnora

Version:

Google Smart Home integration via Smart Nora https://smart-nora.eu/

238 lines (237 loc) 12.2 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const nora_firebase_common_1 = require("@andrei-tatar/nora-firebase-common"); const rxjs_1 = require("rxjs"); const media_device_1 = require("../nora/media-device"); const util_1 = require("./util"); module.exports = function (RED) { RED.nodes.registerType('noraf-media', function (config) { var _a, _b, _c, _d; RED.nodes.createNode(this, config); const noraConfig = RED.nodes.getNode(config.nora); if (!(noraConfig === null || noraConfig === void 0 ? void 0 : noraConfig.valid)) { return; } const deviceType = `action.devices.types.${config.deviceType}`; if (!(0, nora_firebase_common_1.isDeviceType)(deviceType)) { this.warn(`Device type not supported: ${deviceType}`); return; } const deviceConfig = { type: deviceType, traits: [], name: { name: config.devicename, }, roomHint: config.roomhint, willReportState: true, attributes: {}, state: { online: true, }, noraSpecific: {}, }; const asyncCommandExecution = []; if (config.supportOnOff) { deviceConfig.traits.push('action.devices.traits.OnOff'); if ((0, nora_firebase_common_1.isOnOff)(deviceConfig)) { deviceConfig.state.on = false; deviceConfig.noraSpecific.returnOnOffErrorCodeIfStateAlreadySet = !!config.errorifstateunchaged; } if (config.asyncCmdOnOff) { asyncCommandExecution.push('action.devices.commands.OnOff'); } } if (config.supportVolume) { deviceConfig.traits.push('action.devices.traits.Volume'); if ((0, nora_firebase_common_1.isVolumeDevice)(deviceConfig)) { const volumeState = { currentVolume: 40, isMuted: false, }; Object.assign(deviceConfig.state, volumeState); const volumeAttributes = { volumeCanMuteAndUnmute: !!config.volumeCanMuteAndUnmute, volumeMaxLevel: 100, levelStepSize: parseInt(config.volumeLevelStepSize, 10) || undefined, }; Object.assign(deviceConfig.attributes, volumeAttributes); } if (config.asyncCmdVolume) { asyncCommandExecution.push('action.devices.commands.setVolume', 'action.devices.commands.mute', 'action.devices.commands.volumeRelative'); } } if (config.supportMediaState) { deviceConfig.traits.push('action.devices.traits.MediaState'); if ((0, nora_firebase_common_1.isMediaStateDevice)(deviceConfig)) { const mediaState = {}; Object.assign(deviceConfig.state, mediaState); const mediaStateAttributes = { supportActivityState: config.supportActivityState, supportPlaybackState: config.supportPlaybackState, }; Object.assign(deviceConfig.attributes, mediaStateAttributes); } } if (config.supportTransportControl && ((_a = config.transportControlCommands) === null || _a === void 0 ? void 0 : _a.length) > 0) { deviceConfig.traits.push('action.devices.traits.TransportControl'); if ((0, nora_firebase_common_1.isTransportControlDevice)(deviceConfig)) { const transportControlAttributes = { transportControlSupportedCommands: config.transportControlCommands, }; Object.assign(deviceConfig.attributes, transportControlAttributes); } if (config.asyncCmdTransportControl) { asyncCommandExecution.push('action.devices.commands.mediaStop', 'action.devices.commands.mediaNext', 'action.devices.commands.mediaPrevious', 'action.devices.commands.mediaPause', 'action.devices.commands.mediaResume', 'action.devices.commands.mediaSeekRelative', 'action.devices.commands.mediaSeekToPosition', 'action.devices.commands.mediaRepeatMode', 'action.devices.commands.mediaShuffle', 'action.devices.commands.mediaClosedCaptioningOn', 'action.devices.commands.mediaClosedCaptioningOff'); } } const mediaInputs = config.mediaInputs; if (config.supportInputSelector && (mediaInputs === null || mediaInputs === void 0 ? void 0 : mediaInputs.length) >= 1) { deviceConfig.traits.push('action.devices.traits.InputSelector'); if ((0, nora_firebase_common_1.isInputSelectorDevice)(deviceConfig)) { const inputSelectorAttributes = { availableInputs: mediaInputs.map(i => ({ key: i.v, names: [{ lang: config.language, name_synonym: i.n.split(',').map(s => s.trim()), }], })), orderedInputs: true, }; Object.assign(deviceConfig.attributes, inputSelectorAttributes); const inputSelectorState = { currentInput: ((_b = mediaInputs.find(i => i.d)) !== null && _b !== void 0 ? _b : mediaInputs[0]).v, }; Object.assign(deviceConfig.state, inputSelectorState); } if (config.asyncCmdInputSelector) { asyncCommandExecution.push('action.devices.commands.SetInput', 'action.devices.commands.NextInput', 'action.devices.commands.PreviousInput'); } } const mediaApps = config.mediaApps; if (config.supportAppSelector && (mediaApps === null || mediaApps === void 0 ? void 0 : mediaApps.length) >= 1) { deviceConfig.traits.push('action.devices.traits.AppSelector'); if ((0, nora_firebase_common_1.isAppSelectorDevice)(deviceConfig)) { const appSelectorAttributes = { availableApplications: mediaApps.map(i => ({ key: i.v, names: [{ lang: config.appsLanguage, name_synonym: i.n.split(',').map(s => s.trim()), }], })) }; Object.assign(deviceConfig.attributes, appSelectorAttributes); const appSelectorState = { currentApplication: (_d = (_c = mediaApps.find(i => i.d)) === null || _c === void 0 ? void 0 : _c.v) !== null && _d !== void 0 ? _d : 'unknown', }; Object.assign(deviceConfig.state, appSelectorState); } if (config.asyncCmdAppSelector) { asyncCommandExecution.push('action.devices.commands.appSelect', 'action.devices.commands.appSearch', 'action.devices.commands.appInstall'); } } const channels = config.mediaChannels; if (config.supportChannel && (channels === null || channels === void 0 ? void 0 : channels.length) >= 1) { deviceConfig.traits.push('action.devices.traits.Channel'); if ((0, nora_firebase_common_1.isChannelDevice)(deviceConfig)) { const channelAttributes = { availableChannels: channels.map(c => ({ key: c.k, names: c.n.split(',').map(n => n.trim()), number: c.i, })), }; Object.assign(deviceConfig.attributes, channelAttributes); } if (config.asyncCmdChannel) { asyncCommandExecution.push('action.devices.commands.selectChannel', 'action.devices.commands.relativeChannel', 'action.devices.commands.returnChannel'); } } (0, util_1.registerNoraDevice)(this, RED, config, { deviceConfig: Object.assign(Object.assign({}, deviceConfig), { noraSpecific: Object.assign(Object.assign({}, deviceConfig.noraSpecific), { asyncCommandExecution }) }), updateStatus: ({ state, update }) => { const states = []; if (isOnOffState(state)) { states.push(state.on ? 'on' : 'off'); } if (isVolumeState(state)) { states.push(state.isMuted ? 'mute' : `${state.currentVolume}`); } if (isMediaStateDeviceState(state)) { if (state.activityState) { states.push(state.activityState.toLowerCase()); } if (state.playbackState) { states.push(state.playbackState.toLowerCase()); } } if (isInputSelectorState(state)) { states.push(state.currentInput); } if (isAppSelectorState(state)) { states.push(state.currentApplication); } update(states.join(',')); }, mapStateToOutput: state => ({ payload: Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, (isOnOffState(state) ? { on: state.on } : null)), (isVolumeState(state) ? { volume: state.currentVolume, mute: state.isMuted, } : null)), (isMediaStateDeviceState(state) ? { activity: state.activityState, playback: state.playbackState, } : null)), (isInputSelectorState(state) ? { input: state.currentInput, } : null)), (isAppSelectorState(state) ? { application: state.currentApplication, } : null)), }), handleNodeInput: async ({ msg, updateState }) => { await updateState(msg === null || msg === void 0 ? void 0 : msg.payload, [{ from: 'volume', to: 'currentVolume', }, { from: 'mute', to: 'isMuted', }, { from: 'activity', to: 'activityState', }, { from: 'playback', to: 'playbackState', }, { from: 'input', to: 'currentInput', }, { from: 'application', to: 'currentApplication', }]); }, customRegistration: device$ => device$.pipe((0, rxjs_1.switchMap)(d => d instanceof media_device_1.FirebaseMediaDevice ? d.mediaCommand$ : rxjs_1.EMPTY), (0, rxjs_1.tap)(command => { this.send([null, { payload: command, topic: config.topic, }]); })), }); function isOnOffState(state) { return (0, nora_firebase_common_1.isOnOff)(deviceConfig) && 'on' in state; } function isMediaStateDeviceState(state) { return (0, nora_firebase_common_1.isMediaStateDevice)(deviceConfig) && ('activityState' in state || 'playbackState' in state); } function isVolumeState(state) { return (0, nora_firebase_common_1.isVolumeDevice)(deviceConfig) && 'currentVolume' in state; } function isInputSelectorState(state) { return (0, nora_firebase_common_1.isInputSelectorDevice)(deviceConfig) && 'currentInput' in state; } function isAppSelectorState(state) { return (0, nora_firebase_common_1.isAppSelectorDevice)(deviceConfig) && 'currentApplication' in state; } }); };