diff --git a/.gitignore b/.gitignore index 4a2040c..e5676f8 100755 --- a/.gitignore +++ b/.gitignore @@ -26,3 +26,6 @@ admin/i18n/*/flat.txt # ioBroker dev-server .dev-server/ .vscode/secrets.txt +.vscode/info.md +.vscode/info.xlsx +.vscode/~$info.xlsx diff --git a/.markdownlint.json b/.markdownlint.json index 0fa289c..70a34d0 100644 --- a/.markdownlint.json +++ b/.markdownlint.json @@ -1,10 +1,6 @@ { - "list-marker-space": { - "ul_multi": 3, - "ul_single": 3 - }, - "ul-indent": { - "indent": 4 - }, - "first-line-heading": false -} + "first-line-heading": false, + "MD013": { + "tables": false + } +} diff --git a/.vscode/launch.json b/.vscode/launch.json index afaae86..f34e1b0 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -1,6 +1,18 @@ { "version": "0.2.0", "configurations": [ + { + "name": "Launch Program", + "program": "../iobroker.repochecker/index.js", + "args": ["https://github.com/oweitman/ioBroker.squeezeboxrpc","main","--local"], + "request": "launch", + "stopOnEntry": true, + "runtimeExecutable": "c:/Users/oweit/AppData/Roaming/fnm/aliases/default/node.exe", + "skipFiles": [ + "/**" + ], + "type": "node" + }, { "type": "node", "request": "launch", diff --git a/.vscode/settings.json b/.vscode/settings.json index bc3396a..1315e00 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -11,5 +11,8 @@ "fileMatch": ["admin/jsonConfig.json", "admin/jsonCustom.json", "admin/jsonTab.json"], "url": "https://raw.githubusercontent.com/ioBroker/adapter-react-v5/main/schemas/jsonConfig.json" } - ] + ], + "[markdown]": { + "editor.wordWrap": "off" + } } diff --git a/README.md b/README.md index 4bca06e..cefe908 100644 --- a/README.md +++ b/README.md @@ -15,10 +15,10 @@ This is an alternative Adapter that uses the `JSON/RPC`-protocol to get data and send commands to the Logitech Media Server ([LMS](https://de.wikipedia.org/wiki/Logitech_Media_Server)) for controlling connected devices like -- native [squeezebox](https://de.wikipedia.org/wiki/Squeezebox), -- raspberry pi with additional audio module and small linux based firmwares +- native [squeezebox](https://de.wikipedia.org/wiki/Squeezebox), +- raspberry pi with additional audio module and small linux based firmwares like [picoreplayer](https://picoreplayer.org/) or [max2play](https://www.max2play.com). -- with plugins chromecast, airplay or `UPnP/DLNA`-Devices +- with plugins chromecast, airplay or `UPnP/DLNA`-Devices The `LMS`-Server can manage/provide very big music collections on harddrives or `NAS`, connect to different streaming providers like `Spotify`, `Deezer`, @@ -32,76 +32,74 @@ all needed informations or send commands to the server/players. ## Features -- most of data that the `LMS`-Service provides is available in the adapter -- detailed information about the player status, song title, artist, +- most of [data](#server) that the `LMS`-Service provides is available in the adapter +- detailed [information](#players) about the player status, song title, artist, album, artwork, playlist -- many control features to play, pause, stop, forward, rewind, repeat, - shuffle, play favorite, jump to time (absolute and relative) , jump to - playlist index (absolute and relative), power on/off and preset buttons -- all favorites and all sub levels from server -- many widgets for the iobroker-vis component are included to create own +- [many control features](#provided-states) to play, pause, stop, forward,\ + rewind, repeat, shuffle, play favorite, jump to time\ + (absolute and relative) , jump to playlist index (absolute and relative),\ + power on/off and preset buttons +- all [favorites](#favorites) and all sub levels from server +- many [widgets](#widgets) for the iobroker-vis component are included to\ + create own control user interfaces (select player,select favorites, manage syncgroups, buttons for play/pause,fwd,rew, repeat mode and shuffle mode selection) -Documentation for the vis-widgets are available inside vis or [Widget-Documentation/german](https://htmlpreview.github.io/?https://github.com/oweitman/ioBroker.squeezeboxrpc/blob/master/widgets/squeezeboxrpc/doc.html) - ## Installation -- Install the package -- Create an instance -- Configure the Instance with the IP of the logitech media server +- Install the package +- Create an instance +- Configure the Instance with the IP of the logitech media server and the port (normaly 9000) -- start/restart the instance +- start/restart the instance ## Update -- after changes in the widget code and upadte of the adapter, iobroker - should upload webfiles to the internal webserver. user reported that this - sometimes didnt happend or only with delay. you can trigger this action - with the following command +- After installation or update, it may sometimes be necessary\ + to execute the following command if problems have arisen in vis-1 -iobroker upload squeezeboxpc +`iobroker upload squeezeboxpc` ## Provided states ### Server -| state | Description | -| ---------------- | ----------------------------- | -| LastScan | timestamp of last music scan | -| PlayerCount | Number of known players | -| PlayerCountOther | Number of known other Players | -| PlayerCountSN | Number of known SN Players | -| TotalAlbums | Number of all known Albums | -| TotalArtists | Number of all known Artists | -| TotalDuration | Sum playtime of all songs | -| TotalGenres | Number of all known Genres | -| TotalSongs | Number of all known songs | -| SyncGroups | Existing Syncgroups | -| Version | Version of `LMS` | -| mac | MAC-ID of the server | -| uuid | uuid of the `LMS`-instance | +| state | Description | +| ------------------ | ----------------------------- | +| `LastScan` | timestamp of last music scan | +| `PlayerCount` | Number of known players | +| `PlayerCountOther` | Number of known other Players | +| `PlayerCountSN` | Number of known SN Players | +| `TotalAlbums` | Number of all known Albums | +| `TotalArtists` | Number of all known Artists | +| `TotalDuration` | Sum playtime of all songs | +| `TotalGenres` | Number of all known Genres | +| `TotalSongs` | Number of all known songs | +| `SyncGroups` | Existing Syncgroups | +| `Version` | Version of `LMS` | +| `mac` | MAC-ID of the server | +| `uuid` | uuid of the `LMS`-instance | additional a defined button to refresh the favorites -| button | Description | -| ------------ | --------------------------------- | -| getFavorites | request all favorites from server | +| button | Description | +| -------------- | --------------------------------- | +| `getFavorites` | request all favorites from server | ### Favorites For each favorite All attributes are read only -| state | Description | -| -------- | ------------------------------------------ | -| Name | Name of the favorite | -| hasitems | indicates if this is a dir | -| id | id of the favorite | -| image | image/icon for favorite if available | -| isaudio | isaudio | -| type | Example types: link, text, audio, playlist | -| url | url of the track | +| state | Description | +| ---------- | ------------------------------------------ | +| `Name` | Name of the favorite | +| `hasitems` | indicates if this is a dir | +| `id` | id of the favorite | +| `image` | image/icon for favorite if available | +| `isaudio` | isaudio | +| `type` | Example types: link, text, audio, playlist | +| `url` | url of the track | All sub levels (subdirectories) of favorite are available. @@ -111,370 +109,649 @@ for each player The mode shows if you can change the value. the taken action is described at the attribute -| state | mode | Description | -| -------------------- | ---- | ----------------------------------------------------------------------------------------------------------------------------- | -| Alarms | R/- | All registered Alarms for this player as JSON | -| Album | R/- | Name of the current album | -| Artist | R/- | Name of Artist | -| ArtworkUrl | R/- | url to the Artwork | -| Bitrate | R/- | Bitrate of the track | -| Connected | R/- | connectionstate of player (0/1) | -| Duration | R/- | Duration of the track | -| Genre | R/- | genre of the track | -| IP | R/- | IP of the player | -| Mode | R/- | play / pause / stop | -| Playername | R/- | Name of the Player | -| PlayerID | R/- | Player ID | -| Playlist | R/- | The actual Playlist as JSON | -| PlaylistCurrentIndex | R/W | go to a absolut position by specifying the
trackindex or go relative with a + or - at the
beginning. Example 10,-3,+2 | -| PlaylistRepeat | R/W | Repeat song(1)/playlist(2)/dont repeat(0) | -| PlaylistShuffle | R/W | shuffle playlist(1)/shuffle album(2)/dont shuffle(0) | -| Power | R/W | get/set Powerstate of player off(0)/on(1) | -| RadioName | R/- | Name of Radiostation | -| Rate | R/- | Rating of the song | -| Remote | R/- | If remote stream (1) | -| SyncMaster | R/- | ID/MAC of Syncmaster | -| SyncSlaves | R/- | ID/Mac of Players in Syncgroup | -| Time | R/- | elapsed song time | -| Title | R/- | song title | -| Type | R/- | type of media (eg MP3 Radio) | -| Url | R/- | Url of track / stream | -| Volume | R/W | get/set Volume of the player (0-100) | -| state | R/W | get/set play state: pause(0),play(1),stop(2) | +| state | mode | Description | +| ---------------------- | ---- | -------------------------------------------------------------------------------------------------------------------- | +| `Alarms` | R/- | All registered Alarms for this player as JSON | +| `Album` | R/- | Name of the current album | +| `Artist` | R/- | Name of Artist | +| `ArtworkUrl` | R/- | url to the Artwork | +| `Bitrate` | R/- | Bitrate of the track | +| `Connected` | R/- | connectionstate of player (0/1) | +| `Duration` | R/- | Duration of the track | +| `Genre` | R/- | genre of the track | +| `IP` | R/- | IP of the player | +| `Mode` | R/- | play / pause / stop | +| `Playername` | R/- | Name of the Player | +| `PlayerID` | R/- | Player ID | +| `Playlist` | R/- | The actual Playlist as JSON | +| `PlaylistCurrentIndex` | R/W | go to a absolut position by specifying thetrackindex or go relative with a + or - at the beginning. Example 10,-3,+2 | +| `PlaylistRepeat` | R/W | Repeat song(1)/playlist(2)/dont repeat(0) | +| `PlaylistShuffle` | R/W | shuffle playlist(1)/shuffle album(2)/dont shuffle(0) | +| `Power` | R/W | get/set Powerstate of player off(0)/on(1) | +| `RadioName` | R/- | Name of Radiostation | +| `Rate` | R/- | Rating of the song | +| `Remote` | R/- | If remote stream (1) | +| `SyncMaster` | R/- | ID/MAC of Syncmaster | +| `SyncSlaves` | R/- | ID/Mac of Players in Syncgroup | +| `Time` | R/- | elapsed song time | +| `Title` | R/- | song title | +| `Type` | R/- | type of media (eg MP3 Radio) | +| `Url` | R/- | Url of track / stream | +| `Volume` | R/W | get/set Volume of the player (0-100) | +| `state` | R/W | get/set play state: pause(0),play(1),stop(2) | The playlist provide actual the following attributes if available in `LMS`. Somme attributes depends of the type of songs (stream/file/...) All attributes are read only -| attribute | Description | -| ---------- | --------------------------------- | -| Album | Name of the current album | -| Artist | Name of Artist | -| ArtworkUrl | url to the Artwork | -| Bitrate | Bitrate of the track | -| Duration | Duration of the track | -| RadioName | Name of Radiostation | -| Rate | Rating of the song | -| title | song title | -| Type | type of media (eg MP3 Radio) | -| url | Url of track / stream | -| index | index of the song in the playlist | -| id | id of the song | +| attribute | Description | +| ------------ | --------------------------------- | +| `Album` | Name of the current album | +| `Artist` | Name of Artist | +| `ArtworkUrl` | url to the Artwork | +| `Bitrate` | Bitrate of the track | +| `Duration` | Duration of the track | +| `RadioName` | Name of Radiostation | +| `Rate` | Rating of the song | +| `title` | song title | +| `Type` | type of media (eg MP3 Radio) | +| `url` | Url of track / stream | +| `index` | index of the song in the playlist | +| `id` | id of the song | additional defined buttons: -| button | Description | -| --------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| btnForward | Next song | -| btnRewind | Previous song | -| btnPreset\_\* | 1-6 buttons to define in player or server | -| cmdGeneral | a general command field to send commands to the player. every field must enclosed by quotation marks. parameters musst be seperated by comma. Example: "play","1" | -| cmdPlayFavorite | to play a favorite set the id of the favorite | -| cmdPlayUrl | to play a url´example ";" | -| cmdGoTime | jump to a absolut position by specifying a number of seconds or jump relative with a + or - at the beginning of the seconds. Example 100,-50,+50 | +| button | Description | +| ----------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `btnForward` | Next song | +| `btnRewind` | Previous song | +| `btnPreset\_\*` | 1-6 buttons to define in player or server | +| `cmdGeneral` | a general command field to send commands to the player. every field must enclosed by quotation marks. parameters musst be seperated by comma. Example: "play","1" | +| `cmdPlayFavorite` | to play a favorite set the id of the favorite | +| `cmdPlayUrl` | to play a url´example ";" | +| `cmdGoTime` | jump to a absolut position by specifying a number of seconds or jump relative with a + or - at the beginning of the seconds. Example 100,-50,+50 | + +#### Remarks on Datapoints depending of the Setting TPE2 in LMS + +Depending on the setting, different MP3 tags are delivered to the data points. +The capitalized names are the names of the mp3 tags + +| Setting TPE2 in LMS | Artist | Albumartist | Trackartist | Band | +| ------------------------------ | ----------- | ----------- | ----------- | ----------- | +| as a band | ARTIST | empty | TRACKARTIST | ALBUMARTIST | +| as the performers of the album | ALBUMARTIST | ALBUMARTIST | empty | empty | + +### Further API documentation For more information visit the CLI-documentation: - + + +## Widgets + +### Player button bar + +![Player button bar](/widgets/squeezeboxrpc/img/players.png) + +All players that are integrated into your Logitech Media Server can be selected\ +using this widget. After selecting a `squeezerpc.?` instance, the available\ +players are displayed in the widget. + +#### Attributes + +| Group | Attribute | Description | +| ----------------------- | --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| SqueezeboxRPC instance | General group | Select an instance of the squeezeboxrpc adapter. Only these are recognized as valid here. | +| Widget format | General group | The widget type can be selected here. The "formatbutton" type has the full range of functions and also works with the SyncGroup widget. The "formatselect" type is a simple selection box. The player name or an individual text is used as the name. | +| Display index | General group | Individual buttons can be hidden or displayed in a different order by deleting the button’s index. To hide them, simply delete the respective index position, including the comma. Index numbers are displayed on the respective button in edit mode if edit mode help is enabled. | +| Line break in CamelCase | General group | If the player name is written in CamelCase, a line break can be activated here so that the player name appears larger on the button. | +| Edit mode help | General group | If this help is activated, index numbers are displayed on the respective button, and the “transparency” setting in the button settings has no effect. | +| Image width | button settings | Image width of a button | +| Image height | button settings | Image height of a button | +| Transparency | button settings | If the button is not activated, it is hidden against the background. 0 = Invisible, 1 = Fully visible | +| Border width | button settings | Border width in pixels around the button | +| Border display | button settings | Type of border display, e.g., solid, dashed. | +| Normal border color | button settings | If the button is not activated, it is shown by this color. | +| Border color active | button settings | If the button is activated, it is shown by this color. | +| border-radius | button settings | A radius in pixels can be entered here for curved border corners. | +| Background color | button settings | Background color for text | +| Image | button[x] | An image can be defined individually here. The image takes precedence over the text. | +| Text | button[x] | Text can be defined individually here. The image takes precedence over the text. | + +### Favorites button bar + +![Favorites button bar](/widgets/squeezeboxrpc/img/favorites.png) + +You can use this widget to select all of the favorites that have been\ +created in your Logitech Media Server. +After selecting the Player widget, the available favorites are displayed in the widget. + +| Group | Attribute | Description | +| ------------------- | --------------- | ----------------------------------------------------------------------------------------------------- | +| Player widget | General group | Select the Player widget. | +| Display index | General group | Individual buttons can be hidden or displayed in a different order using the index. | +| Edit mode help | General group | If this help is activated, index numbers are displayed on each respective button. | +| Image width | button settings | Image width of a button | +| Image height | button settings | Image height of a button | +| Transparency | button settings | If the button is not activated, it is hidden against the background. 0 = Invisible, 1 = Fully visible | +| Border width | button settings | Border width in pixels around the button | +| Border display | button settings | Type of border display, e.g., solid, dashed. | +| Normal border color | button settings | If the button is not activated, it is displayed with this color. | +| Border color active | button settings | If the button is activated, it is displayed with this color. | +| border-radius | button settings | A radius in pixels can be entered here for curved border corners. | +| Background color | button settings | Background color for text | +| Image | button[x] | An image can be individually defined here. The image takes precedence over the text. | +| Text | button[x] | Text can be individually defined here. The image takes precedence over the text. | + +### Play Button + +![Play Button](/widgets/squeezeboxrpc/img/play.png) + +The play button starts or stops the music on the selected player.\ +To prepare, you must connect the button to the player widget.\ +The button has its own graphics (SVG),\ +alternatively you can also select your own graphics. + +#### Attributes for Play button + +| Group | Attribute | Description | +| ------------- | ------------------ | ------------------------------- | +| Player Widget | General group | Selection of the player widget. | +| Pause image | General group | Image for pause | +| Play image | General group | Image for play | +| Stop image | General group | Image for stop | +| fillcolor | SVG settings group | Fill color of the button | +| strokecolor | SVG settings group | Color for the border | +| strokewidth | SVG settings group | Width of the border in pixels | + +### Forward + +![Forward](/widgets/squeezeboxrpc/img/fwd.png) + +The Forward widget allows you to skip forward in the current track.\ +The button can be configured to skip forward by a specific amount\ +of time if the player supports this feature. + +#### Attributes for Forward button + +| Group | Attribute | Description | +| ------------- | ------------- | ---------------------------------------------------------------- | +| Player widget | General group | Selection of the Player widget. | +| Step size | General group | Specifies the amount of time in seconds to skip forward. | +| Button label | General group | Customizable label for the button. | +| Button icon | General group | Selection of an icon for the button, e.g., for skipping forward. | + +### Rewind + +![Rewind](/widgets/squeezeboxrpc/img/rew.png) + +The Rewind widget allows you to jump back in the current track.\ +Similar to the Forward widget, a time period can be set. + +#### Attributes for Rewind button + +| Group | Attribute | Description | +| ------------- | ------------- | ------------------------------------------------------------- | +| Player widget | General group | Selection of the Player widget. | +| Step size | General group | Specifies the time period in seconds by which to jump back. | +| Button label | General group | Customizable label for the button. | +| Button symbol | General group | Selection of a symbol for the button, e.g., for jumping back. | + +### Repeat + +![Repeat](/widgets/squeezeboxrpc/img/repeat0.svg) + +The Repeat widget allows you to activate or deactivate the repeat function\ +for the current track or playlist if this function is supported by the player. + +#### Attributes for Repeat button + +| Group | Attribute | Description | +| ------------- | ------------- | ------------------------------------------------------------------------------------------- | +| Player widget | General group | Selection of the Player widget. | +| Button label | General group | Customizable label for the button. | +| Button symbol | General group | Selection of a symbol for the button, e.g., for repeat. | +| Repeat mode | General group | The mode can be selected here, for example single repeat (track) or list repeat (playlist). | + +### Shuffle + +![Shuffle](/widgets/squeezeboxrpc/img/shuffle0.svg) + +The Shuffle widget enables or disables shuffle for the current playlist,\ +if this feature is supported by the player. + +#### Attributes for Shuffle button + +| Group | Attribute | Description | +| ------------- | ------------- | ------------------------------------------------------- | +| Player widget | General group | Selection of the Player widget. | +| Button label | General group | Customizable label for the button. | +| Button icon | General group | Selection of an icon for the button, e.g., for shuffle. | +| Enabled state | General group | Color or style of the button when shuffle is enabled. | + +### Volume + +![Volume](/widgets/squeezeboxrpc/img/volume.png) + +The Volume widget displays the current volume level of the player and\ +allows you to adjust the volume. + +#### Attributes for Volume button + +| Group | Attribute | Description | +| --------------------------- | ------------- | ----------------------------------------------------------------- | +| Player widget | General group | Selection of the Player widget. | +| Volume step size | General group | Specifies the step size for increasing or decreasing the volume. | +| Maximum volume | General group | Sets the maximum value for the volume, e.g., 100. | +| Volume bar main color | General group | Color for the area of the bar that represents the current volume. | +| Volume bar background color | General group | Color for the area of the bar that is not covered by the volume. | +| Button icon | General group | Selection of an icon for the volume control. | + +### SyncGroup button bar + +![SyncGroup button bar](/widgets/squeezeboxrpc/img/syncgroups.png) + +This widget can be used in conjunction with the player widget to control\ +the synchronization of the players with each other. +Most of the settings for the number of buttons, labels or images are taken\ +over by the player widget. +To prepare, you must connect the button to the player widget. +After selecting a player in the player widget, the current synchronization\ +is visible in the SyncGroup widget. +The sync status is shown using the various adjustable colors. +The player selected in the player widget cannot be selected in the SyncGroup widget. +If a player is selected in the SyncGroup widget that is already in\ +another group, it is automatically removed from this group. + +#### Attributes for SyncGroup button + +| Group | Attribute | Description | +| ----------------------------- | --------------- | ---------------------------------------------------------------------------------------------- | +| Player widget | General group | Selection of the player widget. | +| Border width | button settings | Border width/border width in pixels around the button. | +| Border display | button settings | Type of border display, e.g. solid, dashed. | +| Border color - Not in group | button settings | The button gets a border with this color if the player is not in a group. | +| Border color - In group | button settings | The button gets a border with this color if the player is in a group with the selected player. | +| Border color - In other group | button settings | The button gets a border with this color if the player is in another group. | +| border-radius | button settings | A radius in pixels can be entered here for curved border corners. | +| Background color | button settings | Background color for text. | + +### Playtime bar + +![Playtime bar](/widgets/squeezeboxrpc/img/playtime.png) + +The playtime bar visually shows the progress of the song currently being played,\ +provided that a total running time (duration) is provided by the server.\ +This is usually not the case with online streams. The width of the bar\ +corresponds to 100% of the playing time of the song. By clicking on a point on\ +the bar you can jump to the desired point in the song.\ +To prepare, you must connect the button to the player widget. + +#### Attributes for Playtime bar + +| Group | Attribute | Description | +| -------------- | ------------- | --------------------------------------------------------------- | +| Player widget | General group | Selection of the player widget. | +| Bar main color | General group | The background color of the bar for times not yet played. | +| Playtime color | General group | The color of the bar for times played. | +| Frame width | General group | Frame width/border width in pixels around the button. | +| Border display | General group | Type of border display, e.g. solid, dashed. | +| Border color | General group | Color of the border around the bar. | +| border radius | General group | A radius in pixels can be entered here for curved edge corners. | + +### String/character string + +![String](/widgets/squeezeboxrpc/img/string.png) + +Display of player-specific character strings. To prepare, you must connect\ +the button to the player widget. + +#### Attributes for String + +| Group | Attribute | Description | +| ---------------- | ------------- | ----------------------------------------------------------------- | +| Player widget | General group | Selection of the player widget. | +| Player Attribute | General group | Selection list of all available attributes of a player. | +| Test text | General group | Text that should be displayed in the editor for testing purposes. | + +### Number + +![Number](/widgets/squeezeboxrpc/img/number.png) + +Display of numbers with additional formatting options. To prepare,\ +you must connect the button to the player widget. + +#### Attributes for Number + +| Group | Attribute | Description | +| --------------------- | ----------------- | ----------------------------------------------------------------- | +| Player widget | General group | Selection of the player widget. | +| Player Attribute | General group | Selection list of all available attributes of a player. | +| Prepend HTML | General group | Text or HTML code that is placed in front of the number. | +| Append HTML | General group | Text or HTML code that is appended to the number. | +| Test text | General group | Text that should be displayed in the editor for testing purposes. | +| Character after comma | Advanced settings | Number of decimal places. | +| Comma as separator | Advanced settings | A comma is used to separate the decimal places. | +| Thousands separator | Advanced settings | For large numbers, a separator is inserted every 3 places. | ## Todo -- more testing/fixing -- reduce dependencys to other packages (squeezenode) -- more configuration to optionaly turn features on/off to improve memory and performance -- add playlist widget -- add browse widget to browse in `LMS`-Menu -- add player controlled circle knob widget -- stop playing if favorite button is pressed again. -- cmdGeneral für Server. -- ~~add telnet communication to get push events from the server to optimize the polling~~ -- ~~implement a command state to place user individual commands (via json) for server and player~~ -- ~~implement more control features (select playlist pos to play,ffwd,frew,jump to a time position in song,repeat song,random song)~~ -- ~~add the playlist to playerdata as json array~~ -- ~~add artwork (station-logo/playlist-cover) for favorites~~ -- ~~implement more levels (subdirectories) of favorites~~ -- ~~autodiscover logitech media server~~ +- more testing/fixing +- reduce dependencys to other packages (squeezenode) +- more configuration to optionaly turn features on/off to improve memory and performance +- add playlist widget +- add browse widget to browse in `LMS`-Menu +- add player controlled circle knob widget +- stop playing if favorite button is pressed again. +- cmdGeneral für Server. +- ~~add telnet communication to get push events from the server to\ + optimize the polling~~ +- ~~implement a command state to place user individual commands (via json)\ + for server and player~~ +- ~~implement more control features (select playlist pos to play,ffwd,frew,\ + jump to a time position in song,repeat song,random song)~~ +- ~~add the playlist to playerdata as json array~~ +- ~~add artwork (station-logo/playlist-cover) for favorites~~ +- ~~implement more levels (subdirectories) of favorites~~ +- ~~autodiscover logitech media server~~ ## Changelog +### **WORK IN PROGRESS** + +- move widget documentation from html to markdown + ### 1.4.0-alpha.0 (2024-10-24) -- jsonConfig add sizing options for differenz screen sizes -- test implementation of TPE2 handling. switch in settings -- add datapoints album_artist, track_artist, artistOriginal +- jsonConfig add sizing options for differenz screen sizes +- test implementation of TPE2 handling. switch in settings +- add datapoints album_artist, track_artist, artistOriginal ### 1.3.17 (2024-10-23) -- add edit button to the vie index field of favorites widget +- add edit button to the vie index field of favorites widget ### 1.3.16 (2024-10-23) -- fixed icons of the favorites widget +- fixed icons of the favorites widget ### 1.3.15 (2024-08-09) -- due to a adapter checker issue i have to remove the release 1.3.13 from npm. +- due to a adapter checker issue i have to remove the release 1.3.13 from npm. but changes from 1.3.13 are included in 1.3.14 ### 1.3.14 (2024-08-05) -- fix formatting +- fix formatting ### 1.3.13 (2024-08-05) -- revert the fix for artist handling due to negative effect of spotify +- revert the fix for artist handling due to negative effect of spotify ### 1.3.12 (2024-08-05) -- improve cmdGoto handling by kairauer, close PR #74 -- fix issues from adapter checker -- integrate squeezenode lib +- improve cmdGoto handling by kairauer, close PR #74 +- fix issues from adapter checker +- integrate squeezenode lib ### 1.3.11 (2024-08-05) -- update adapter structure and switch to jsonconfig +- update adapter structure and switch to jsonconfig ### 1.3.10 -- getalbumartist as artist if setting of TPE2/TPE3 in `LMS` are changed" +- getalbumartist as artist if setting of TPE2/TPE3 in `LMS` are changed" ### 1.3.9 -- fix error with deleting favorites -- fix wrong type for datapoint +- fix error with deleting favorites +- fix wrong type for datapoint ### 1.3.8 -- fix forward button widget +- fix forward button widget ### 1.3.7 -- fix object creation of states in player modul +- fix object creation of states in player modul ### 1.3.6 -- fix object creation of states +- fix object creation of states ### 1.3.5 -- fix object creation for favorites +- fix object creation for favorites ### 1.3.4 -- fix object creation for favorites / \* center widgets in sidebar +- fix object creation for favorites / \* center widgets in sidebar ### 1.3.3 -- repair imageproxy for image datapoints of favorites +- repair imageproxy for image datapoints of favorites ### 1.3.2 -- fix for Alarm contains only enabled Alarms +- fix for Alarm contains only enabled Alarms ### 1.3.1 -- fix problem with git dependency url +- fix problem with git dependency url ### 1.3.0 -- fix problem wit setting own icon in player widget / \* add infos about alarms to a player datapoint +- fix problem wit setting own icon in player widget / \* add infos about\ + alarms to a player datapoint ### 1.2.1 -- fix small issue in last version +- fix small issue in last version ### 1.2.0 -- improve handling of imageproxy artwork +- improve handling of imageproxy artwork ### 1.1.0 -- make request of favorites configurable +- make request of favorites configurable ### 1.0.1 -- change setstate/createobject logic -- fix role and type for Mode-state -- update tests -- update dependency versions -- improve io-package.json +- change setstate/createobject logic +- fix role and type for Mode-state +- update tests +- update dependency versions +- improve io-package.json ### 1.0.0 -- prepare for stable repository +- prepare for stable repository ### 0.8.32 -- the adapter function iobroker.deleteChannel didnt works as expected. it didnt delete the whole subtree of states. now i implement my own delete function +- the adapter function iobroker.deleteChannel didnt works as expected.\ + It didnt delete the whole subtree of states. now i implement my own delete function ### 0.8.31 -- change behaviour of deleting favorites +- change behaviour of deleting favorites ### 0.8.30 -- change from the issue of the adapter checker +- change from the issue of the adapter checker ### 0.8.29 -- optimize handling of player state power and connected +- optimize handling of player state power and connected ### 0.8.28 -- add advanced signaling function with telnet and fix some more authorization issues with `LMS` +- add advanced signaling function with telnet and fix some more authorization\ + issues with `LMS` ### 0.8.27 -- initialization for the new calctype property if empty in volumebar +- initialization for the new calctype property if empty in volumebar ### 0.8.26 -- more improvement and fixing at volumebar / remove playlist widget from master. not ready yet +- more improvement and fixing at volumebar / remove playlist widget from\ + master. not ready yet ### 0.8.25 -- fixing css-settings on volumebar +- fixing css-settings on volumebar ### 0.8.24 -- volumebar didnt get events between the segments, change clickevent and calculation +- volumebar didnt get events between the segments, change clickevent and calculation ### 0.8.23 -- adjust dependencies to remove vulnerabilities in dependend packages. alos remove travis due of unresolvable build-failures for win+node10/12 +- adjust dependencies to remove vulnerabilities in dependend packages.\ + also remove travis due of unresolvable build-failures for win+node10/12 ### 0.8.22 -- due to iobroker.controller 2.0 a command in the api changed (socket to vis.conn.\_socket) +- due to iobroker.controller 2.0 a command in the api changed (socket to vis.conn.\_socket) ### 0.8.21 -- add command für playing urls +- add command für playing urls ### 0.8.20 -- remove node v6 test setting +- remove node v6 test setting ### 0.8.19 -- shorten news history +- shorten news history ### 0.8.18 (2019-06-27) -- last minute changes. +- last minute changes. ### 0.8.17 (2019-06-26) -- add more widges: playtime bar, string, number, datetime, image. add button margin to player and favorite widget, improve editing of viewindex. do some refactoring. +- add more widges: playtime bar, string, number, datetime, image.\ + add button margin to player and favorite widget, improve editing of viewindex.\ + do some refactoring. ### 0.8.16 (2019-06-24) -- resolve a cross browser issue for firefox. the style.font attribute is empty and you have to construct the font string by yourself +- resolve a cross browser issue for firefox. the style.\ + font attribute is empty and you have to construct the font string by yourself ### 0.8.15 (2019-06-19) -- minor issue with not ready states +- minor issue with not ready states ### 0.8.14 (2019-06-19) -- add syncgroups as new server-datapoint,add syncgroup widget, change some jquery event logic +- add syncgroups as new server-datapoint,add syncgroup widget,/ + change some jquery event logic ### 0.8.13 (2019-06-16) -- rename widgetset from squeezeboxrpcwidgets to squeezeboxrpc +- rename widgetset from squeezeboxrpcwidgets to squeezeboxrpc ### 0.8.12 (2019-06-16) -- sync version with npm +- sync version with npm ### 0.8.11 (2019-06-15) -- try to integrate the widgets into the main adapter +- try to integrate the widgets into the main adapter ### 0.8.10 (2019-05-15) -- another try to fix the EADDRINUSE error of the server discovery +- another try to fix the EADDRINUSE error of the server discovery ### 0.8.9 (2019-05-15) -- try to fix the EADDRINUSE error of the server discovery +- try to fix the EADDRINUSE error of the server discovery ### 0.8.8 (2019-05-14) -- make discover configurable +- make discover configurable ### 0.8.7 (2019-05-11) -- more control features (select playlist pos to play,ffwd,frew,jump to a time position in song,repeat song,random song) +- more control features (select playlist pos to play,ffwd,frew,jump to/ + a time position in song,repeat song,random song) ### 0.8.6 (2019-05-10) -- move some configuration options into seperate tabs +- move some configuration options into seperate tabs ### 0.8.5 (2019-05-08) -- change serverdiscovery interval method, remove some double cmd lines, additional minor changes advised from eslint +- change serverdiscovery interval method, remove some double cmd lines,/ + additional minor changes advised from eslint ### 0.8.4 -- move some files to lib directory +- move some files to lib directory ### 0.8.3 -- close port for discovery on unload +- close port for discovery on unload ### 0.8.2 -- sync version with npm +- sync version with npm ### 0.8.1 -- set compact mode flag +- set compact mode flag ### 0.8.0 -- implementation of compact mode, change version to represent a realistic feature completness +- implementation of compact mode, change version to represent a realistic/ + feature completness ### 0.0.9 -- debug options are now configurable +- debug options are now configurable ### 0.0.8 -- More playlist attributes + remove trailing and leading spaces from source +- More playlist attributes + remove trailing and leading spaces from source ### 0.0.7 -- Add the playlist to each player as json +- Add the playlist to each player as json ### 0.0.6 -- More config options +- More config options ### 0.0.5 -- All levels/subdirectories of favorites are now available in iobroker +- All levels/subdirectories of favorites are now available in iobroker ### 0.0.4 -- added the cmdPlayFavorite for each player +- added the cmdPlayFavorite for each player ### 0.0.3 -- repair the no-data symbols for buttons in vis +- repair the no-data symbols for buttons in vis ### 0.0.2 -- added autodiscovery +- added autodiscovery ### 0.0.1 -- initial release +- initial release ## License diff --git a/admin/jsonConfig.json b/admin/jsonConfig.json index 28fb78a..b6b22b7 100644 --- a/admin/jsonConfig.json +++ b/admin/jsonConfig.json @@ -72,21 +72,6 @@ "lg": 4, "xl": 4, "newLine": true - }, - "TPE2Handling": { - "type": "select", - "label": "TPE2 Handling", - "options": [ - { "label": "TPE2 as Band", "value": "TPE2Band" }, - { "label": "TPE2 as Artist of Album (default)", "value": "TPE2Artist" } - ], - "default": "TPE2Artist", - "xs": 12, - "sm": 12, - "md": 6, - "lg": 4, - "xl": 4, - "newLine": true } } }, diff --git a/lib/iosbplayer.js b/lib/iosbplayer.js index 1acb86e..05dea53 100755 --- a/lib/iosbplayer.js +++ b/lib/iosbplayer.js @@ -34,7 +34,7 @@ function ioSBPlayer(server, playerdata) { this.islogsilly = this.adapter.config.outputplayersilly; this.islogdebug = this.adapter.config.outputplayerdebug; - this.TPE2Handling = this.adapter.config.TPE2Handling || "TPE2Artist"; + this.TPE2Handling = 1; this.FORBIDDEN_CHARS = /[^\d\w_]+/gm; //test the regex: https://regex101.com/r/Ed0WhH/1 @@ -265,31 +265,30 @@ function ioSBPlayer(server, playerdata) { role: "media.artist", exist: false }, - "artistOriginal": { - name: "ArtistOriginal", + "albumartist": { + name: "Albumartist", read: true, write: false, type: "string", role: "media.artist", exist: false }, - "albumartist": { - name: "Albumartist", + "trackartist": { + name: "Trackartist", read: true, write: false, type: "string", role: "media.artist", exist: false }, - "trackartist": { - name: "Trackartist", + "band": { + name: "Band", read: true, write: false, type: "string", role: "media.artist", exist: false - }, - "url": { + }, "url": { name: "Url", read: true, write: false, @@ -603,45 +602,11 @@ function ioSBPlayer(server, playerdata) { value = decodeURIComponent(m[1]); } } - if (key == "artist") { - const artist = value; - if (this.TPE2Handling == "TPE2Band") { - if (Object.prototype.hasOwnProperty.call(playerdata, "trackartist")) { - value = playerdata["trackartist"]; - } - if (Object.prototype.hasOwnProperty.call(playerdata, "albumartist")) { - value = playerdata["albumartist"]; - } - } else { - if (Object.prototype.hasOwnProperty.call(playerdata, "albumartist")) { - value = playerdata["albumartist"]; - } - } - this.setState(this.sbPlayerStatusLoop["artistOriginal"].name, this.convertState(this.sbPlayerStatusLoop["artistOriginal"], artist), this.statePath, this.playername); - } - if (key == "albumartist") { - if (this.TPE2Handling == "TPE2Band") { - if (Object.prototype.hasOwnProperty.call(playerdata, "trackartist")) { - value = playerdata["trackartist"]; - } - if (Object.prototype.hasOwnProperty.call(playerdata, "albumartist")) { - value = playerdata["albumartist"]; - } - } else { - if (Object.prototype.hasOwnProperty.call(playerdata, "albumartist")) { - value = playerdata["albumartist"]; - } - } - this.setState(this.sbPlayerStatusLoop["artist"].name, this.convertState(this.sbPlayerStatusLoop["artist"], value), this.statePath, this.playername); - } - if (key == "trackartist") { - if (this.TPE2Handling == "TPE2Band") { - if (Object.prototype.hasOwnProperty.call(playerdata, "trackartist") && !Object.prototype.hasOwnProperty.call(playerdata, "albumartist")) { - value = playerdata["trackartist"]; - } - } - this.setState(this.sbPlayerStatusLoop["artist"].name, this.convertState(this.sbPlayerStatusLoop["artist"], value), this.statePath, this.playername); - } + /* if (key == "artist" || key == "albumartist" || key == "trackartist") { + console.log("artist", playerdata["artist"]); + console.log("albumartist", playerdata["albumartist"]); + console.log("trackartist", playerdata["trackartist"]); + } */ this.setState(this.sbPlayerStatusLoop[key].name, this.convertState(this.sbPlayerStatusLoop[key], value), this.statePath, this.playername); } else { if (key == "remote_title" && this.remote == 0) { @@ -802,8 +767,12 @@ function ioSBPlayer(server, playerdata) { } if (idParts[0] == "cmdGeneral") { if (state.val !== " ") { - const cmd = JSON.parse("[" + state.val + "]"); - this.request(this.playerid, cmd); + try { + const cmd = JSON.parse("[" + state.val + "]"); + this.request(this.playerid, cmd); + } catch (error) { + this.logerror("cmdGeneral, Parameter error: " + state.val); + } this.setState(idParts[0], " ", this.statePath, this.playername, false); } } @@ -870,6 +839,9 @@ function ioSBPlayer(server, playerdata) { this.request = function (playerid, params, callback) { if (this.connected) this.server.request(playerid, params, callback); }; + this.setTPE2Handling = function (value) { + this.TPE2Handling = value; + }; this.setState = function (name, value, level1path, level2path, check = true) { name = (level1path ? level1path + "." : "") + (level2path ? level2path + "." : "") + name; if (this.currentStates[name] !== value && check) { diff --git a/lib/iosbserver.js b/lib/iosbserver.js index 5319c57..2ee199c 100755 --- a/lib/iosbserver.js +++ b/lib/iosbserver.js @@ -378,28 +378,33 @@ function IoSbServer(adapter) { }); this.telnet.on("data", (data) => { this.logdebug("doTelnet received Data: " + data.toString()); + //console.log(decodeURIComponent(data.toString())); const regex = /^((?:[0-9A-Fa-f]{2}[:-]){5}(?:[0-9A-Fa-f]{2}))\s*(.*)/gm; let m; - if ((m = regex.exec(decodeURIComponent(data.toString()))) !== null) { - if (m[2] == "client reconnect") { - this.logdebug("doTelnet received reconnect for : " + m[1]); - this.getServerstatus(); - } - if (m[2] == "client disconnect") { - this.logdebug("doTelnet received disconnect for : " + m[1]); - this.getServerstatus(); - } - if (m[2] == "client new") { - this.logdebug("doTelnet received disconnect for : " + m[1]); - this.getServerstatus(); - } - if (m[2] == "power 0") { - this.logdebug("doTelnet received power off : " + m[1]); - this.getServerstatus(); - } - if (m[2] == "power 1") { - this.logdebug("doTelnet received power on : " + m[1]); - this.getServerstatus(); + const cmdQueue = decodeURIComponent(data.toString()).split("\r\n"); + for (const cmd of cmdQueue) { + + if ((m = regex.exec(cmd)) !== null) { + if (m[2] == "client reconnect") { + this.logdebug("doTelnet received reconnect for : " + m[1]); + this.getServerstatus(); + } + if (m[2] == "client disconnect") { + this.logdebug("doTelnet received disconnect for : " + m[1]); + this.getServerstatus(); + } + if (m[2] == "client new") { + this.logdebug("doTelnet received disconnect for : " + m[1]); + this.getServerstatus(); + } + if (m[2] == "power 0") { + this.logdebug("doTelnet received power off : " + m[1]); + this.getServerstatus(); + } + if (m[2] == "power 1") { + this.logdebug("doTelnet received power on : " + m[1]); + this.getServerstatus(); + } } } }); @@ -556,6 +561,7 @@ function IoSbServer(adapter) { }; this.checkPlayer = function (playersdata) { this.logdebug("checkPlayer"); + this.checkTPE2(); for (const key in playersdata) { if (this.players[playersdata[key].playerid].connected != playersdata[key].connected) { if (playersdata[key].connected == 0) { @@ -567,6 +573,22 @@ function IoSbServer(adapter) { } } }; + this.checkTPE2 = function () { + const that = this; + this.request("", ["pref", "useTPE2AsAlbumArtist", "?"], function (result) { + if (result.ok) { + if (Object.keys(result.result).length > 0) { + const value = result.result[Object.keys(result.result)[0]]; + for (const key in that.players) { + if (Object.prototype.hasOwnProperty.call(that.players, key)) { + // console.log("setTPE2Handling", key, value); + that.players[key].setTPE2Handling(parseInt(value)); + } + } + } + } + }.bind(this)); + }; this.stateChange = function (id, state) { this.logsilly("stateChange"); // Warning, state can be null if it was deleted diff --git a/package-lock.json b/package-lock.json index 7fff7bf..c5f7404 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "1.4.0-alpha.0", "license": "MIT", "dependencies": { - "@iobroker/adapter-core": "^3.1.6", + "@iobroker/adapter-core": "^3.2.2", "jayson": "^3.2.0", "lodash": "^4.17.4", "request": "^2.88.0", @@ -133,18 +133,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@alcalzone/pak/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/@alcalzone/release-script": { "version": "3.8.0", "resolved": "https://registry.npmjs.org/@alcalzone/release-script/-/release-script-3.8.0.tgz", @@ -266,18 +254,6 @@ "node": ">= 6" } }, - "node_modules/@alcalzone/release-script-plugin-iobroker/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/@alcalzone/release-script-plugin-license": { "version": "3.7.0", "resolved": "https://registry.npmjs.org/@alcalzone/release-script-plugin-license/-/release-script-plugin-license-3.7.0.tgz", @@ -320,18 +296,6 @@ "node": ">=12.20" } }, - "node_modules/@alcalzone/release-script-plugin-package/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/@alcalzone/release-script-plugin-version": { "version": "3.7.0", "resolved": "https://registry.npmjs.org/@alcalzone/release-script-plugin-version/-/release-script-plugin-version-3.7.0.tgz", @@ -348,18 +312,6 @@ "node": ">=12.20" } }, - "node_modules/@alcalzone/release-script-plugin-version/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/@alcalzone/release-script/node_modules/axios": { "version": "1.7.3", "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.3.tgz", @@ -385,18 +337,6 @@ "node": ">= 6" } }, - "node_modules/@alcalzone/release-script/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/@babel/helper-string-parser": { "version": "7.24.8", "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz", @@ -407,9 +347,9 @@ } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", - "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", + "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", "dev": true, "engines": { "node": ">=6.9.0" @@ -836,73 +776,6 @@ "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, - "node_modules/@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", - "dev": true, - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint/eslintrc/node_modules/debug": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", - "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@eslint/eslintrc/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/@eslint/eslintrc/node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@eslint/js": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", - "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, "node_modules/@esm2cjs/execa": { "version": "6.1.1-cjs.1", "resolved": "https://registry.npmjs.org/@esm2cjs/execa/-/execa-6.1.1-cjs.1.tgz", @@ -1151,13 +1024,13 @@ } }, "node_modules/@humanwhocodes/config-array": { - "version": "0.11.14", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", - "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", + "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", "deprecated": "Use @eslint/config-array instead", "dev": true, "dependencies": { - "@humanwhocodes/object-schema": "^2.0.2", + "@humanwhocodes/object-schema": "^2.0.3", "debug": "^4.3.1", "minimatch": "^3.0.5" }, @@ -1166,12 +1039,12 @@ } }, "node_modules/@humanwhocodes/config-array/node_modules/debug": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", - "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", "dev": true, "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -1183,9 +1056,9 @@ } }, "node_modules/@humanwhocodes/config-array/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true }, "node_modules/@humanwhocodes/module-importer": { @@ -1209,14 +1082,14 @@ "dev": true }, "node_modules/@iobroker/adapter-core": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/@iobroker/adapter-core/-/adapter-core-3.1.6.tgz", - "integrity": "sha512-cArv8IzVsP3r8HivsYwO02e5WueboIH9v66PkHSGtadeUQQKUyxV32dzirM6YArWcI6+Iw5USQgVR9E+ryP3xg==", + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@iobroker/adapter-core/-/adapter-core-3.2.2.tgz", + "integrity": "sha512-Cuiga42WRkJ/NduyrIGgSVWpLgD6ihIflIvZiWVThwgWfDyI+Okgw3snVSlf/p4ki6BAr3MH6Dfa0qPySCGWvQ==", "engines": { - "npm": ">=7.0.0" + "node": ">=16" }, "peerDependencies": { - "@iobroker/types": "^6.0.0" + "@iobroker/types": "^6.0.11" } }, "node_modules/@iobroker/adapter-dev": { @@ -1415,18 +1288,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@iobroker/dev-server/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/@iobroker/testing": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/@iobroker/testing/-/testing-4.1.3.tgz", @@ -1517,9 +1378,9 @@ } }, "node_modules/@iobroker/types": { - "version": "6.0.9", - "resolved": "https://registry.npmjs.org/@iobroker/types/-/types-6.0.9.tgz", - "integrity": "sha512-8+u5c/cawj5cmnQaW95TJv1vBMs68GaepPko7urvylGfixPE/vJ0nwNq392v67B52PwHPi41kctmR9gNt9M+tw==", + "version": "6.0.11", + "resolved": "https://registry.npmjs.org/@iobroker/types/-/types-6.0.11.tgz", + "integrity": "sha512-RNDURjtL5Cm9wt6ocCqdRi86Qx1350zBIvvrJ9+Fjgasoi6cWCdoOghkwEeb95TH2j//q/uLqWwL8SZ0vxx6Kw==", "peer": true, "engines": { "node": ">=12.0.0" @@ -3082,18 +2943,6 @@ "node": ">=0.3.1" } }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/dom-compare-temp": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/dom-compare-temp/-/dom-compare-temp-0.1.0.tgz", @@ -3501,9 +3350,9 @@ } }, "node_modules/escalade": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", - "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "dev": true, "engines": { "node": ">=6" @@ -3560,16 +3409,17 @@ } }, "node_modules/eslint": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", - "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", + "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", + "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.57.0", - "@humanwhocodes/config-array": "^0.11.14", + "@eslint/js": "8.57.1", + "@humanwhocodes/config-array": "^0.13.0", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", "@ungap/structured-clone": "^1.2.0", @@ -3693,13 +3543,45 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/eslint/node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/@eslint/js": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", + "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, "node_modules/eslint/node_modules/debug": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", - "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", "dev": true, "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -3710,6 +3592,18 @@ } } }, + "node_modules/eslint/node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/eslint/node_modules/glob-parent": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", @@ -3722,6 +3616,21 @@ "node": ">=10.13.0" } }, + "node_modules/eslint/node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/eslint/node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -3736,9 +3645,9 @@ } }, "node_modules/eslint/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true }, "node_modules/eslint/node_modules/optionator": { @@ -4516,21 +4425,24 @@ } }, "node_modules/glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", - "minimatch": "^3.0.4", + "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" }, "engines": { "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/glob-parent": { @@ -4545,21 +4457,6 @@ "node": ">= 6" } }, - "node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", - "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/globalyzer": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/globalyzer/-/globalyzer-0.1.0.tgz", @@ -5344,18 +5241,6 @@ "node": ">=8" } }, - "node_modules/jsdoc/node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/jsdom": { "version": "6.5.1", "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-6.5.1.tgz", @@ -6041,18 +5926,6 @@ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true }, - "node_modules/mocha/node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/mocha/node_modules/supports-color": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", @@ -6206,18 +6079,6 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, - "node_modules/nodemon/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/nodemon/node_modules/supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -6441,7 +6302,7 @@ "node_modules/path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", "dev": true, "engines": { "node": ">=0.10.0" @@ -6689,18 +6550,6 @@ "node": ">=10" } }, - "node_modules/protobufjs-cli/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -7074,6 +6923,18 @@ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, + "node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/send": { "version": "0.16.2", "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", @@ -7334,18 +7195,6 @@ "node": ">=10" } }, - "node_modules/simple-update-notifier/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/sinon": { "version": "18.0.0", "resolved": "https://registry.npmjs.org/sinon/-/sinon-18.0.0.tgz", @@ -7745,6 +7594,18 @@ "node": ">=6" } }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/stubs": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/stubs/-/stubs-3.0.0.tgz", diff --git a/package.json b/package.json index bac0f2b..eed08f3 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "node": ">= 18" }, "dependencies": { - "@iobroker/adapter-core": "^3.1.6", + "@iobroker/adapter-core": "^3.2.2", "jayson": "^3.2.0", "lodash": "^4.17.4", "request": "^2.88.0", diff --git a/widgets/squeezeboxrpc/doc.html b/widgets/squeezeboxrpc/doc.html deleted file mode 100644 index ac7a33a..0000000 --- a/widgets/squeezeboxrpc/doc.html +++ /dev/null @@ -1,389 +0,0 @@ - - - - Dokumentation SqueezeboxRPC Widgets - - - -

Dokumentation SqueezeboxRPC Widgets

- -

Player Knopfleiste

-
-Über dieses Widget können alle Player, die in deimem Logitech Media Server eingebunden sind ausgewählt werden. -Nach Auswahl einer squeezerpc.? Instanz, werden die verfügbaren Player im Widget angezeigt. -

Attribute

-
SqueezeboxRPC Instanz - Gruppe Allgemein
-Auswahl einer Instanz des squeezeboxrpc-Adapters. Nur diese werden hier als gültig anerkannt. -
Widgetformat - Gruppe Allgemein
-Hier kann der widgettyp ausgewählt werden. Der Typ "formatbutton" hat den kompletten Funktionsumfang und arbeitet auch mit dem SyncGroup Widget zusammen. -Der Typ "formatselect" ist ein einfache Auswahlbox. Als Bezeichnung wird der Playername oder, falls eingegeben, ein individueller Text verwendet. -
Anzeigeindex - Gruppe Allgemein
-Darüber können einzelne Knöpfe ausgeblendet oder in einer anderen Reihenfolge angezeigt werden. -indem der Index des Knopfes herausgelöscht wird. Für das ausblenden einfach die jeweilige Indexposition inklusive Komma herauslöschen. -Für eine andere Position, wird die Indexnummer an einer anderen Position im Viewindex eingefügt. -Falls bei dem editieren dieses Feldes entwas schief gegangen ist, dann kann der Ursprung durch das leeren des gesamten Feldes -wieder hergestellt werden. -Für jeden Eintrag wird ein separates Untermenü erstellt, in dem ein eigenes Bild oder ein Text angegeben werden kann. -
-Zur Erleichterung werden die Indexzahlen an dem jeweiligen Knopf im Edit-Modus angezeigt, wenn die Edit-Mode-Hilfe aktiviert ist. -
Umbruch bei CamelCase - Gruppe Allgemein
-Falls der Playername in CamelCase notiert ist, kann darüber ein Zeilenumbruch aktiviert werden, so dass der Playername größer auf dem Knopf angezeigt wird. -
Edit-Mode-Hilfe - Gruppe Allgemein
-Wenn diese Hilfe aktiviert ist, werden Indexzahlen an dem jeweiligen Knopf angezeigt und Eisntellung zur "Durchsichtigkeit" bei den Knopfeinstellungen besitzt keine Wirkung. -
Bildbreite - Knopfeinstellungen
-Bildbreite eines Knopfes -
Bildhöhe - Knopfeinstellungen
-Bildhöhe eines Knopfes -
Durchsichtigkeit - Knopfeinstellungen
-Wenn der Knopf nicht aktiviert ist, wird er gegen den Hintergrund ausgeblendet. 0= Unsichtbar, 1=Voll sichtbar -
Rahmenbreite - Knopfeinstellungen
-Rahmenbreite/Randbreite in Pixel um den Knopf -
Randdarstellung - Knopfeinstellungen
-Art der Randdarstellung bspw durchgezogen, gestrichelt. -
Randfarbe normal - Knopfeinstellungen
-Wenn der Knopf nicht aktiviert ist, wird dies durch diese Farbe dargestellt. -
Randfarbe aktiv - Knopfeinstellungen
-Wenn der Knopf aktiviert ist, wird dies durch diese Farbe dargestellt. -
border-radius - Knopfeinstellungen
-Für gebogene Randeckecn, kann hier ein Radius in Pixel eingegeben werden -
Hintergrundfarbe - Knopfeinstellungen
-Hintergrundfarbe bei Text -
Bild - Knopf[x]
-Hier kann individuell ein Bild definiert werden. Das Bild hat vorrang vor dem Text. -
Text - Knopf[x]
-Hier kann individuell ein Text definiert werden. Das Bild hat vorrang vor dem Text. -

- - -

Favoriten Knopfleiste

-
-Über dieses Widget können alle Favoriten, die in deimem Logitech Media Server angelegt worden sind ausgewählt werden. -Nach Auswahl des Player widgets werden die verfügbaren Favoriten im widget angezeigt. -Idealerweiße hast du in deiner Favoritendatei des Logitech Media Servers eine Grafik mit angegeben (manuelle Nacharbeit der Datei auf dem LMS-server notwendig). -Falls nicht, dann wird der einzelne Knopf einmal nach der FavoritenID benannt (kann im Adapter nachgeschaut werden), -sowie einem Index, der bei 0 beginnt und hochgezählt wird. -Zur Vorbereitung musst du das Favoriten widget mit dem Player widget verbinden. Wenn du dann einen Player im Player widget ausgewählt hast, -wird nach Anwahl eines Favoriten dieser auf dem jeweiligen Player abgespielt. -

Attribute

-
Player widget - Gruppe Allgemein
-Auswahl des Player widgets. -
Anzeigeindex - Gruppe Allgemein
-Darüber können einzelne Knöpfe ausgeblendet oder in einer anderen Reihenfolge angezeigt werden. -indem der Index des Knopfes herausgelöscht wird. Für das ausblenden einfach die jeweilige Indexposition inklusive Komma herauslöschen. -Für eine andere Position, wird die Indexnummer an einer anderen Position im Viewindex eingefügt. -Falls bei dem editieren dieses Feldes entwas schief gegangen ist, dann kann der Ursprung durch das leeren des gesamten Feldes -wieder hergestellt werden. -Für jeden Eintrag wird ein separates Untermenü erstellt, in dem ein eigenes Bild oder ein Text angegeben werden kann. -
-Zur Erleichterung werden die Indexzahlen an dem jeweiligen Knopf im Edit-Modus angezeigt, wenn die Edit-Mode-Hilfe aktiviert ist. -
Edit-Mode-Hilfe - Gruppe Allgemein
-Wenn diese Hilfe aktiviert ist, werden Indexzahlen an dem jeweiligen Knopf angezeigt und Eisntellung zur "Durchsichtigkeit" bei den Knopfeinstellungen besitzt keine Wirkung. -
Bildbreite - Knopfeinstellungen
-Bildbreite eines Knopfes -
Bildhöhe - Knopfeinstellungen
-Bildhöhe eines Knopfes -
Durchsichtigkeit - Knopfeinstellungen
-Wenn der Knopf nicht aktiviert ist, wird er gegen den Hintergrund ausgeblendet. 0= Unsichtbar, 1=Voll sichtbar -
Rahmenbreite - Knopfeinstellungen
-Rahmenbreite/Randbreite in Pixel um den Knopf -
Randdarstellung - Knopfeinstellungen
-Art der Randdarstellung bspw durchgezogen, gestrichelt. -
Randfarbe normal - Knopfeinstellungen
-Wenn der Knopf nicht aktiviert ist, wird dies durch diese Farbe dargestellt. -
Randfarbe aktiv - Knopfeinstellungen
-Wenn der Knopf aktiviert ist, wird dies durch diese Farbe dargestellt. -
border-radius - Knopfeinstellungen
-Für gebogene Randeckecn, kann hier ein Radius in Pixel eingegeben werden -
Hintergrundfarbe - Knopfeinstellungen
-Hintergrundfarbe bei Text -
Bild - Knopf[x]
-Hier kann individuell ein Bild definiert werden. Das Bild hat vorrang vor dem Text. -
Text - Knopf[x]
-Hier kann individuell ein Text definiert werden. Das Bild hat vorrang vor dem Text. -

- - -

Play Button

-
-Der Playknopf startet oder stoppt die Musik auf dem jeweiligen ausgewählten Player. -Zur Vorbereitung musst du den Knopf mit dem Player widget verbinden. -Der Knopf bring bereits eigene Grafiken (SVG) mit. Alternativ kannst du auch eigene Grafiken auswählen. -

Attribute

-
Player widget - Gruppe Allgemein
-Auswahl des Player widgets. -
Bild pause - Gruppe Allgemein
-Bild für Pause -
Bild play - Gruppe Allgemein
-Bild für Play -
Bild stop - Gruppe Allgemein
-Bild für Stopp -
fillcolor - Gruppe SVG Einstellungen
-Füllfarbe des Knopfes -
strokecolor - Gruppe SVG Einstellungen
-Farbe für den Rand -
strokewidth - Gruppe SVG Einstellungen
-Breite des Rands in Pixel -

- - -

Forward Button

-
-Der Knopf springt zum nächsten Titel in der Playlist. -Zur Vorbereitung musst du den Knopf mit dem Player widget verbinden. -Der Knopf bring bereits eigene Grafiken (SVG) mit. Alternativ kannst du auch eigene Grafiken auswählen. -

Attribute

-
Player widget - Gruppe Allgemein
-Auswahl des Player widgets. -
Bild - Gruppe Allgemein
-Bild für den Knopf -
fillcolor - Gruppe SVG Einstellungen
-Füllfarbe des Knopfes -
strokecolor - Gruppe SVG Einstellungen
-Farbe für den Rand -
strokewidth - Gruppe SVG Einstellungen
-Breite des Rands in Pixel -

- - -

Rewind Button

-
-Der Knopf springt zum vorherigen Titel in der Playlist. -Zur Vorbereitung musst du den Knopf mit dem Player widget verbinden. -Der Knopf bring bereits eigene Grafiken (SVG) mit. Alternativ kannst du auch eigene Grafiken auswählen. -

Attribute

-
Player widget - Gruppe Allgemein
-Auswahl des Player widgets. -
Bild - Gruppe Allgemein
-Bild für den Knopf -
fillcolor - Gruppe SVG Einstellungen
-Füllfarbe des Knopfes -
strokecolor - Gruppe SVG Einstellungen
-Farbe für den Rand -
strokewidth - Gruppe SVG Einstellungen
-Breite des Rands in Pixel -

- - -

Repeat Button

-
-Der Knopf steuert die Wiederholung eines Titels oder einer ganzen Playlist/Album -Zur Vorbereitung musst du den Knopf mit dem Player widget verbinden. -Der Knopf bring bereits eigene Grafiken (SVG) mit. Alternativ kannst du auch eigene Grafiken auswählen. -

Attribute

-
Player widget - Gruppe Allgemein
-Auswahl des Player widgets. -
Bild ohne- Gruppe Allgemein
-Bild für deaktivierte Wiederholung -
Bild Titel- Gruppe Allgemein
-Bild für Wiederholung des aktuellen Titels -
Bild Playlist- Gruppe Allgemein
-Bild für Wiederholung der ganzen Playlist -
fillcolor - Gruppe SVG Einstellungen
-Füllfarbe des Knopfes -
strokecolor - Gruppe SVG Einstellungen
-Farbe für den Rand -
strokewidth - Gruppe SVG Einstellungen
-Breite des Rands in Pixel -

- - -

Shuffle Button

-
-Der Knopf steuert die zufällige eines Titels oder einer ganzen Playlist/Album -Zur Vorbereitung musst du den Knopf mit dem Player widget verbinden. -Der Knopf bring bereits eigene Grafiken (SVG) mit. Alternativ kannst du auch eigene Grafiken auswählen. -

Attribute

-
Player widget - Gruppe Allgemein
-Auswahl des Player widgets. -
Bild ohne- Gruppe Allgemein
Bild für deaktivierten Zufall -
Bild Titel- Gruppe Allgemein
-Bild für Zufällige Titelreihenfolge -
Bild Playlist- Gruppe Allgemein
-Bild für Zufällige Albumreihenfolge -
fillcolor - Gruppe SVG Einstellungen
-Füllfarbe des Knopfes -
strokecolor - Gruppe SVG Einstellungen
-Farbe für den Rand -
strokewidth - Gruppe SVG Einstellungen
-Breite des Rands in Pixel -

- -

Volume Bar

-
-Dieses Widget zeigt und steuert die Lautstärke eines Players. -Zur Vorbereitung musst du den Knopf mit dem Player widget verbinden. -

Attribute

-
Player widget - Gruppe Allgemein
-Auswahl des Player widgets. -
CalcType - Gruppe Allgemein
-Steuerung der Berechnung der Lautstärke anhand der Position, wo im Volumebar geklickt wird.

-Einstellung segstep: Hier wird die Lautstärke auf Basis der Klickposition jeweils auf die Anzahl der Segmente gerundet.
-Beispiel: 11 Segmente ergeben ein Segment für 0 sowie weitere 10 Segmente für die Lautstärke in 10er Schritten. d.h.
-klick auf das erste Segment ergibt 0% Lautstärke,
-klick auf das zweite Segment ergibt 10% Lautstärke,
-klick auf das sechste Segment ergibt 50% Lautstärke

-Einstellung exact: Hier wird die Lautstärke auf Basis der Klickposition exakt berechnet.
-Beispiel: 11 Segmente ergeben ein Segment für 0 sowie weitere 10 Segmente für die Lautstärke
-klick auf das erste Segment ergibt 0% Lautstärke,
-klick auf das 2 Segment im niedrigen Bereich ergibt igendwas zwischen 1% und 4%,
-klick auf das 2 Segment im mittleren Bereich ergibt igendwas zwischen 3% und 7%,
-klick auf das 2 Segment im hohen Bereich ergibt igendwas zwischen 6% und 10%,
-Nachteil: Einen genauen Prozentwert oder beispielsweise die genauen 100% sind nur schwer exakt zu klicken.
-
Segmente - Gruppe Allgemein
-Die Anzahl der angezeigtne Lautstärkesegmente. -Für Lautstärke 0 muss immer ein extra Segment mit einberechnet werden. -Also für eine Abstufung von 10% benötigst du 11 Segmente. -
Format - Gruppe Allgemein
-Das steuert die Formatierung für horizontal und vertikale Darstellung. -Die Volume Bar kannst du dann selbst in die gewünschte Form und Größe bringen -
Wert umkehren - Gruppe Allgemein
-Steuert die Seite, an der die aktiven Segmente angezeigt werden. -
fillcolornormal - Gruppe Segmente
-Füllfarbe des Segmentes im nicht aktivierten Zustand -
fillcoloractive - Gruppe Segmente
-Füllfarbe des Segmentes im aktivierten Zustand -
Randfarbe normal - Gruppe Segmente
-Randfarbe des Segmentes im nicht aktivierten Zustand -
Randfarbe aktive - Gruppe Segmente
-Randfarbe des Segmentes im aktivierten Zustand -
margin - Gruppe Segmente
-Abstand um ein Segment herum in Pixel. -

- - -

SyncGroup Knopfleiste

-
-Über dieses Widget kann in Verbindung mit dem Playerwidget die Synchonisation der Player untereinander gesteuert werden.
-Die meisten Einstellungen zur Anzahl der Knöpfe, der Beschriftung oder Bildern wird vom Playerwidget übernommen.
-Zur Vorbereitung musst du den Knopf mit dem Player widget verbinden.
-Nach Auswahl eines Players im Playerwidget ist die aktuelle Synchronisation im SyncGroup widget sichtbar.
-Der Sync-Status wird über die verschiedenen einstellbaren Farben dargestellt.
-Der im Player widget ausdwählte Player kann im SyncGroup Widget nicht ausgewählt werden.
-Wird im SyncGroup widget ein Player ausgewählt, der sich bereits in einer anderen Gruppe befindet, wird er aus diser Gruppe automatisch entfernt.
-

Attribute

-
Player widget - Gruppe Allgemein
-Auswahl des Player widgets. -
Rahmenbreite - Knopfeinstellungen
-Rahmenbreite/Randbreite in Pixel um den Knopf -
Randdarstellung - Knopfeinstellungen
-Art der Randdarstellung bspw durchgezogen, gestrichelt. -
Randfarbe - Nicht in Gruppe - Knopfeinstellungen
-Der Knopf erhält einen Rand mit dieser Farbe, wenn der Player sich nicht in einer Gruppe befindet. -
Randfarbe - In Gruppe - Knopfeinstellungen
-Der Knopf erhält einen Rand mit dieser Farbe, wenn der Player sich in einer Gruppe mit dem ausgewählten Player befindet. -
Randfarbe - In anderer Gruppe - Knopfeinstellungen
-Der Knopf erhält einen Rand mit dieser Farbe, wenn der Player sich in einer anderen Gruppe befindet. -
border-radius - Knopfeinstellungen
-Für gebogene Randeckecn, kann hier ein Radius in Pixel eingegeben werden -
Hintergrundfarbe - Knopfeinstellungen
-Hintergrundfarbe bei Text -

- -

Playtime Balken

-
-Der Playtime Balken zeigt den Fortschritt des gerade gespielten Titels visuell an, sofern eine Gesamtlaufzeit (Duration) vom Server -mitgegeben wird. Bei Online-Streams, ist das meist nicht der Fall. Die Breite des Balkens sind 100% Spielzeit des Titels. -Über einen Klick auf eine entsprechende Stelle des Balkens, kann an die gewünschte Stelle des Liedes gesprungen werden. -Zur Vorbereitung musst du den Knopf mit dem Player widget verbinden.
-

Attribute

-
Player widget - Gruppe Allgemein
-Auswahl des Player widgets. -
Balkenhauptfarbe - Gruppe Allgemein
-Die Hintergrundfarbe des Balkens, für noch nicht gespielte Zeiten -
Playtimefarbe - Gruppe Allgemein
-Die Farbe des Balkens, für gespielte Zeiten -
Rahmenbreite - Gruppe Allgemein
-Rahmenbreite/Randbreite in Pixel um den Knopf -
Randdarstellung - Gruppe Allgemein
-Art der Randdarstellung bspw durchgezogen, gestrichelt. -
Randfarbe - Gruppe Allgemein
-Farbe des Randes um den Balken. -
border-radius - Gruppe Allgemein
-Für gebogene Randeckecn, kann hier ein Radius in Pixel eingegeben werden -

- -

String/Zeichenkette

-
-Darstellung von Player-individuellen Zeichenketten -Zur Vorbereitung musst du den Knopf mit dem Player widget verbinden.
-

Attribute

-
Player widget - Gruppe Allgemein
-Auswahl des Player widgets. -
Player Attribut - Gruppe Allgemein
-Auswahlliste aller verfügbaren Attribute eines Players -
Testtext - Gruppe Allgemein
-Text, der im Editor testweise angezeigt werden soll -

- -

Zahl/Number

-
-Darstellung von Zahlen mit zusätzlichen Formatierungsoptionen -Zur Vorbereitung musst du den Knopf mit dem Player widget verbinden.
-

Attribute

-
Player widget - Gruppe Allgemein
-Auswahl des Player widgets. -
Player Attribut - Gruppe Allgemein
-Auswahlliste aller verfügbaren Attribute eines Players -
HTML Voranstellen - Gruppe Allgemein
-Text oder HTML-Code, der der Zahl vorangestellt wird. -
HTML anhängen - Gruppe Allgemein
-Text oder HTML-Code, der der Zahl angehängt wird. -
Testtext - Gruppe Allgemein
-Text, der im Editor testweise angezeigt werden soll -
Zeichen nach Komma - Erweiterte Einstellungen
-Anzahl der Nachkommastellen -
Komma als Trennung - Erweiterte Einstellungen
-Zum trennen der Nachkommastellen wird anders wie im amerikanischen ein Komma verwendet. -
Tausender Trennzeichen - Erweiterte Einstellungen
-Bei großen Zahlen, wird alle 3stellen ein Komma oder Punkt eingefügt. Abhängig von der Einstellung "Komma als Trennung" -

- -

Datum Zeit/Date Time

-
-Darstellung von Zeiten/Uhrzeiten/Datum mit Formatierungsoptionen. -Der Wert muss als Zahl in Millisekunden vorliegen und nicht als bereits formatierte Datumszeichenkette. -Falls der Wert noch nicht in Millisekunden vorliegt, kann über das Feld ein entpsrechender Faktor erfasst werden. -bspw. Sekunden = 1000, Minuten = 60000, Stunden = 3600000, Tage= 86400000 -Zur Vorbereitung musst du den Knopf mit dem Player widget verbinden.
-

Attribute

-
Player widget - Gruppe Allgemein
-Auswahl des Player widgets. -
Player Attribut - Gruppe Allgemein
-Auswahlliste aller verfügbaren Attribute eines Players -
HTML Voranstellen - Gruppe Allgemein
-Text oder HTML-Code, der der Zahl vorangestellt wird. -
HTML anhängen - Gruppe Allgemein
-Text oder HTML-Code, der der Zahl angehängt wird. -
Testtext - Gruppe Allgemein
-Text, der im Editor testweise angezeigt werden soll -
Multiplikation - Erweiterte Einstellungen
-Multiplikation des zugrundeliegenden Wertes, um auf Millisekunden zu kommen. -Da die Zeit in den Datenpunkten bei LMS meist in Sekunden angegeben sind, sollte der Wert hier 1000 betragen. -
Format - Erweiterte Einstellungen
-Zeichenkette um das Ergebnis entsprechend zu formatieren. -alle Formatangaben vgl. Github date.format.js
-Beispiel: "H:i:s" im format 00:00:00 für Stunden:Minuten:Sekunden mit führender 0 im 24 Stundenformat. -

- -

Bild/Image

-
-Darstellung von Bildern auf Basis von Links aus einem Playerattribut. -Zur Vorbereitung musst du den Knopf mit dem Player widget verbinden.
-

Attribute

-
Player widget - Gruppe Allgemein
-Auswahl des Player widgets. -
Player Attribut - Gruppe Allgemein
-Auswahlliste aller verfügbaren Attribute eines Players -
Strecken - Gruppe Allgemein
-Bild wird entsprechend der Größe des Widgets gestreckt.´ -
HTML Voranstellen - Gruppe Allgemein
-Text oder HTML-Code, der der Zahl vorangestellt wird. -
HTML anhängen - Gruppe Allgemein
-Text oder HTML-Code, der der Zahl angehängt wird. -
Testtext - Gruppe Allgemein
-Bilderlink, der im Editor testweise angezeigt werden soll -

- - - -