diff --git a/ioBroker/DEV/NSPanelTs.ts b/ioBroker/DEV/NSPanelTs.ts index 9a30a7f9..cf71aded 100644 --- a/ioBroker/DEV/NSPanelTs.ts +++ b/ioBroker/DEV/NSPanelTs.ts @@ -95,11 +95,12 @@ ReleaseNotes: - 03.02.2024 - v4.3.3.31 Remove: adapterPlayerInstance from every card except cardMedia - 03.02.2024 - v4.3.3.31 [dev]: optional with type - cardMedia has adapterPlayerInstance all other not - 03.02.2024 - v4.3.3.31 [dev]: add PlayerType some more work to do - - 03.02.2024 - v4.3.3.31 changed: adapterPlayerInstance instance 0-9 allowed. Always require a '.' at the end. - - 04.01.2024 - v4.3.3.32 Hotfix Spotify + - 03.02.2024 - v4.3.3.31 changed: adapterPlayerInstance instance 0-9 allowed. Always require a '.' at the end. + - 04.01.2024 - v4.3.3.32 Hotfix Spotify - 04.01.2024 - v4.3.3.32 [DEV] Add Types see commits - 04.01.2024 - v4.3.3.32 Add more details to types for: leftScreensaverEntity, indicatorScreensaverEntity, PageThermo, PageMedia - 04.01.2024 - v4.3.3.32 Remove not uses propertys from PageItem + - 05.01.2024 - v4.3.3.32 Add Body for BoseSoundtouch-Player Todo: - XX.XX.XXXX - v5.0.0 Change the bottomScreensaverEntity (rolling) if more than 6 entries are defined @@ -4693,6 +4694,21 @@ function subscribeMediaSubscriptionsAlexaAdd(id: string): void { }); } +function subscribeMediaSubscriptionsBoseAdd(id: string): void { + on({id: [id + '.DURATION', + id + '.ELAPSED'], change: "any"}, async function () { + (function () { if (timeoutMedia) { clearTimeout(timeoutMedia); timeoutMedia = null; } })(); + timeoutMedia = setTimeout(async function () { + if (useMediaEvents) { + GeneratePage(activePage!); + setTimeout(async function () { + GeneratePage(activePage!); + }, 50); + } + },50) + }); +} + async function createAutoMediaAlias (id: string, mediaDevice: string, adapterPlayerInstance: adapterPlayerInstanceType) { if (autoCreateAlias) { if (isSetOptionActive) { @@ -4908,10 +4924,11 @@ async function createAutoMediaAlias (id: string, mediaDevice: string, adapterPla log('bosesoundtouch Alias ' + id + ' does not exist - will be created now', 'info'); try { - let dpPath: string = adapterPlayerInstance + 'keys'; + let dpPath: string = adapterPlayerInstance; await extendObjectAsync(id, {_id: id, type: 'channel', common: {role: 'media', name: 'media'}, native: {}}); - await createAliasAsync(id + '.ACTUAL', dpPath + '.volume', true, {type: 'number', role: 'value.volume', name: 'ACTUAL'}); - await createAliasAsync(id + '.VOLUME', dpPath + '.volume', true, {type: 'number', role: 'level.volume', name: 'VOLUME'}); + await createAliasAsync(id + '.ACTUAL', dpPath + 'volume', true, {type: 'number', role: 'value.volume', name: 'ACTUAL'}); + await createAliasAsync(id + '.VOLUME', dpPath + 'volume', true, {type: 'number', role: 'level.volume', name: 'VOLUME'}); + await createAliasAsync(id + '.STATE', dpPath + 'on', true, {type: 'boolean', role: 'media.state', name: 'STATE'}); dpPath = adapterPlayerInstance + 'nowPlaying'; await createAliasAsync(id + '.ALBUM', dpPath + '.album', true, {type: 'string', role: 'media.album', name: 'ALBUM'}); @@ -4923,7 +4940,6 @@ async function createAutoMediaAlias (id: string, mediaDevice: string, adapterPla await createAliasAsync(id + '.SHUFFLE', dpPath + '.shuffle', true, {type: 'boolean', role: 'media.mode.shuffle', name: 'SHUFFLE'}); dpPath = adapterPlayerInstance + 'keys'; - await createAliasAsync(id + '.STATE', dpPath + '.POWER', true, {type: 'boolean', role: 'media.state', name: 'STATE'}); await createAliasAsync(id + '.NEXT', dpPath + '.NEXT_TRACK', true, {type: 'boolean', role: 'button.next', name: 'NEXT'}); await createAliasAsync(id + '.PREV', dpPath + '.PREV_TRACK', true, {type: 'boolean', role: 'button.prev', name: 'PREV'}); await createAliasAsync(id + '.PLAY', dpPath + '.PLAY', true, {type: 'boolean', role: 'button.play', name: 'PLAY'}); @@ -4975,7 +4991,7 @@ function GenerateMediaPage(page: PageMedia): Payload[] { } let vMediaDevice = (page.items[0].mediaDevice != undefined) ? page.items[0].mediaDevice : ''; - + if (isPlayerWithMediaDevice(v2Adapter)) { if (!vMediaDevice) throw new Error(`Error in cardMedia! mediaDevice is empty! Page: ${JSON.stringify(page)}`); } @@ -4995,6 +5011,8 @@ function GenerateMediaPage(page: PageMedia): Payload[] { subscribeMediaSubscriptionsSonosAdd(page.items[0].id); } else if (v2Adapter == 'alexa2') { subscribeMediaSubscriptionsAlexaAdd(page.items[0].id); + } else if (v2Adapter == 'bosesoundtouch') { + subscribeMediaSubscriptionsBoseAdd(page.items[0].id); } } } @@ -5005,7 +5023,9 @@ function GenerateMediaPage(page: PageMedia): Payload[] { if (v2Adapter == 'sonos') { subscribeMediaSubscriptionsSonosAdd(page.items[0].id); } else if (v2Adapter == 'alexa2') { - subscribeMediaSubscriptionsAlexaAdd(page.items[0].id); + subscribeMediaSubscriptionsAlexaAdd(page.items[0].id); + } else if (v2Adapter == 'bosesoundtouch') { + subscribeMediaSubscriptionsBoseAdd(page.items[0].id); } } else if (page.type == 'cardMedia' && pageCounter == -1) { //Do Nothing @@ -5055,7 +5075,15 @@ function GenerateMediaPage(page: PageMedia): Payload[] { vDuration = vDuration.slice(4); } title = title + ' (' + vElapsed + '|' + vDuration + ')'; - } + } else if (v2Adapter == 'bosesoundtouch') { + if (Debug) log(getState(id + '.ELAPSED').val, 'info'); + let elapsedSeconds = parseInt(getState(id + '.ELAPSED').val)%60 < 10 ? '0' : '' + let vElapsed = Math.floor(getState(id + '.ELAPSED').val/60) + ":" + elapsedSeconds + getState(id + '.ELAPSED').val%60 + if (Debug) log(getState(id + '.DURATION').val, 'info'); + let durationSeconds = parseInt(getState(id + '.DURATION').val)%60 < 10 ? '0' : '' + let vDuration = Math.floor(getState(id + '.DURATION').val/60) + ":" + durationSeconds + getState(id + '.DURATION').val%60 + title = title + ' (' + vElapsed + '|' + vDuration + ')'; + } } let author = getState(id + '.ARTIST').val; let shuffle = getState(id + '.SHUFFLE').val; @@ -5110,6 +5138,24 @@ function GenerateMediaPage(page: PageMedia): Payload[] { } } + //Bose Soundtouch + if (v2Adapter == 'bosesoundtouch') { + media_icon = Icons.GetIcon('alpha-b-circle'); + name = page.heading; + + if ((getState(id + '.ALBUM').val).length > 0) { + author = getState(id + '.ARTIST').val + ' | ' + getState(id + '.ALBUM').val; + if (author.length > 37) { + author = author.slice(0,37) + '...'; + } + } else { + author = getState(id + '.ARTIST').val; + } + if ((getState(id + '.ARTIST').val).length == 0) { + author = findLocale('media','no_music_to_control'); + } + } + //Logitech Squeezebox RPC if (v2Adapter == 'squeezeboxrpc') { media_icon = Icons.GetIcon('dlna'); @@ -5198,7 +5244,9 @@ function GenerateMediaPage(page: PageMedia): Payload[] { } else if (v2Adapter == 'sonos') { currentSpeaker = getState(([page.items[0].adapterPlayerInstance, 'root.', page.items[0].mediaDevice, '.members'].join(''))).val; } else if (v2Adapter == 'squeezeboxrpc') { - currentSpeaker = getState(([page.items[0].adapterPlayerInstance, '.Players.', page.items[0].mediaDevice, '.Playername'].join(''))).val; + currentSpeaker = getState(([page.items[0].adapterPlayerInstance, 'Players.', page.items[0].mediaDevice, '.Playername'].join(''))).val; + } else if (v2Adapter == 'bosesoundtouch') { + currentSpeaker = getState(([page.items[0].adapterPlayerInstance, 'deviceInfo.name'].join(''))).val; } //------------------------------------------------------------------------------------------------------------- // All Alexa devices (the online / player and commands directory is available) are listed and linked below @@ -5400,6 +5448,14 @@ function GenerateMediaPage(page: PageMedia): Payload[] { repeatIcon = Icons.GetIcon('repeat-once'); repeatIconCol = rgb_dec565(HMIOn); } + } else if (v2Adapter == 'bosesoundtouch') { + if (getState(id + '.REPEAT').val == 'REPEAT_ALL') { + repeatIcon = Icons.GetIcon('repeat-variant'); + repeatIconCol = rgb_dec565(HMIOn); + } else if (getState(id + '.REPEAT').val == 'REPEAT_ONE') { + repeatIcon = Icons.GetIcon('repeat-once'); + repeatIconCol = rgb_dec565(HMIOn); + } } else if (v2Adapter == 'squeezeboxrpc') { if (getState(id + '.REPEAT').val == 1) { repeatIcon = Icons.GetIcon('repeat-once'); @@ -5418,7 +5474,12 @@ function GenerateMediaPage(page: PageMedia): Payload[] { } } - if (v2Adapter == 'spotify-premium' || v2Adapter == 'alexa2' || v2Adapter == 'sonos' || v2Adapter == 'volumio' || v2Adapter == 'squeezeboxrpc') { + if (v2Adapter == 'spotify-premium' || + v2Adapter == 'alexa2' || + v2Adapter == 'sonos' || + v2Adapter == 'bosesoundtouch' || + v2Adapter == 'volumio' || + v2Adapter == 'squeezeboxrpc') { repeatButtonString = 'button' + '~' + id + '?repeat' + '~' + repeatIcon + '~' + @@ -7958,6 +8019,10 @@ function GenerateDetailPage(type: string, optional: mediaOptional | undefined, p //Todo Richtiges Device finden actualState = formatInSelText(getState(pageItem.adapterPlayerInstance + 'Echo-Devices.' + pageItem.mediaDevice + '.Info.name').val); } + } else if (vAdapter == 'bosesoundtouch') { + if (existsObject(pageItem.adapterPlayerInstance + 'deviceInfo.name')) { + actualState = formatInSelText(getState(pageItem.adapterPlayerInstance + 'deviceInfo.name').val); + } } else if (vAdapter == 'squeezeboxrpc') { actualState = pageItem.mediaDevice; } @@ -7993,6 +8058,16 @@ function GenerateDetailPage(type: string, optional: mediaOptional | undefined, p tempPlayList[i] = formatInSelText(tPlayList[i]); } optionalString = pageItem.playList != undefined ? tempPlayList.join('?') : '' + } else if (vAdapter == 'bosesoundtouch') { + if (existsObject(pageItem.adapterPlayerInstance + 'deviceInfo.name')) { + actualState = formatInSelText(getState(pageItem.adapterPlayerInstance + 'deviceInfo.name').val); + log(actualState); + } + let tempPlayList: string[] = []; + for (let i = 0; i < pageItem.playList!.length; i++) { + tempPlayList[i] = formatInSelText(pageItem.playList![i]); + } + optionalString = pageItem.playList != undefined ? tempPlayList.join('?') : '' } else if (vAdapter == 'sonos') { if (Debug) log(pageItem.adapterPlayerInstance + 'root.' + pageItem.mediaDevice + '.playlist_set', 'info'); if (existsObject(pageItem.adapterPlayerInstance + 'root.' + pageItem.mediaDevice + '.playlist_set')) {