An open API service indexing awesome lists of open source software.

https://github.com/patrickkfkan/lms-cli-notifications

Node module for subscribing to and receiving notifications through Logitech Media Server's CLI.
https://github.com/patrickkfkan/lms-cli-notifications

events logitech-media-server notifications squeezebox squeezebox-server squeezelite

Last synced: about 1 month ago
JSON representation

Node module for subscribing to and receiving notifications through Logitech Media Server's CLI.

Awesome Lists containing this project

README

          

# lms-cli-notifications

Node module for subscribing to and receiving notifications through Logitech Media Server's CLI.

Where in CLI, you subscribe to notifications as follows:

```
// Telnet to LMS
$ telnet :

// Subscribe to 'mixer' notifications
# subscribe mixer

// Also subscribe to 'play' and 'pause' notifications
# subscribe mixer,play,pause

// Unsubscribe from 'play' notifications
# subscribe mixer,pause

// Output when player volume changes:
40%3A61%3A86%3Af0%3A8f%3A19 mixer volume 80

```

In Node.JS, you would do this:

```
// ESM
import { NotificationListener } from 'lms-cli-notifications';
// CJS
const { NotificationListener } = require('lms-cli-notifications');

const server = {
host: '',
port: ''
};

const notificationListener = new NotificationListener({
server,
subscribe: 'mixer' // Subscribe to 'mixer' notifications
});

notificationListener.on('notification', (data) => {
const {playerId, notification, params} = data;
console.log({playerId, notification, params});
});

await notificationListener.start();

// Also subscribe to 'play' and 'pause' notifications
await notificationListener.subscribe(['play', 'pause']);

// Unsubscribe from 'play' notifications
await notificationListener.unsubscribe('play');

...

// Output when player volume changes:
{
playerId: '40:61:86:f0:8f:19',
notification: 'mixer',
params: [ 'volume', '50' ]
}

```

Do not confuse subscription in this context with the `subscribe` *tag* in *queries* (which this library does not support).

## Install

```
npm install --save lms-cli-notifications
```

## API

### Class: `NotificationListener`

A `NotificationListener` encapsulates the process of connecting to a Logitech Media Server's CLI, subscribing to notifications and receiving them (communicating back by way of Events). You would begin by first creating a `NotificationListener` instance.

new NotificationListener([params])

Creates a `NotificationListener` instance and associates it with `server`, or `127.0.0.1:9090` if not specified.

**Params**

- `params`: ([`NotificationListenerParams`](docs/api/interfaces/NotificationListenerParams.md)) (*optional* and *all properties optional*)
- `server`:
- `host`: (string) address of server to connect to (default: '127.0.0.1`).
- `port`: (string) server's CLI port (default: '9090').
- `username`: (string) username for login - omit if not applicable.
- `password`: (string) password for login - omit if not applicable.
- `subscribe`: (string | Array\)
- If string, the notification to subscribe to.
- If array, the list of notifications to subscribe to.

The `subscribe` param is included merely for convenience. You can subscribe to notifications at any stage by calling `subscribe()`. So the following:
```
const server = { ... };
const notifications = ['client', 'mixer'];

const notificationListener = new NotificationListener({
server,
subscribe: notifications
});
notificationListener.start();
```

has the same effect as:

```
...
const notificationListener = new NotificationListener({ server });
notificationListener.subscribe(notifications);

notificationListener.start();
```

---

notificationListener.start()

Establishes connection with the server and subscribes to the notification(s) specified at construction time.

**Returns**

Promise that resolves to `true` on success.

---

notificationListener.stop()

Terminates connection with the server.

**Returns**

Promise that resolves to `true` on success.

---

notificationListener.isConnected()

Whether the `NotificationListener` instance is connected to the server.

**Returns**

Boolean

---

notificationListener.subscribe(notification)

Subscribes to `notification`.

>If server is not yet connected, subscription will be deferred until connection is established.

**Params**

- `notification` (string | Array\):
- If string, a single notification to subscribe to.
- If array, the list of notifications to subscribe to.

**Returns**

- If server is not yet connected, a Promise that resolves after adding `notification` to the list of pending subscriptions.
- If server is already connected, a Promise that resolves on successful subscription.

notificationListener.unsubscribe(notification)

Unsubscribes from `notification`.

**Params**

- `notification` (string | Array\):
- If string, a single notification to unsubscribe from.
- If array, the list of notifications to unsubscribe from.

**Returns**

- If server is not yet connected, a Promise that resolves when `notification` is removed from the list of pending subscriptions.
- If server is already connected, a Promise that resolves on successful unsubscription.

---

notificationListener.getSubscribed()

Returns the list of currently-subscribed notifications. The list will be empty if there is no connection with the server.

**Returns**

Array\

---

### Events

notificationListener.on('connect', (server) => ...)

Emitted when connection to `server` is established.

**Listener Params**
- `server`:
- `host`: (string)
- `port`: (string)

---

notificationListener.on('disconnect', (server) => ...)

Emitted when server is disconnected.

**Listener Params**
- `server`:
- `host`: (string)
- `port`: (string)

---

notificationListener.on('notification', (data) => ...)

Emitted when a subscribed notification is received.

`NotificationListener` parses the raw message received from the server and converts it from something like this:
```
08%3A00%3A27%3Aa0%3Ad1%3A2c mixer volume 70
```
into this:

|Property |Value |
|------------------------------|------------------------------------------------|
|`playerId` \* |'08:00:27:a0:d1:2c' |
|`notification` \ |'mixer' |
|`params` \ |['volume', '70'] |
|`raw` \ |'08%3A00%3A27%3Aa0%3Ad1%3A2c mixer volume 70' |
|`server` \ |{ host: ..., port: ... } |

**Listener Params**
- `data`: ([Notification](docs/api/interfaces/Notification.md))
- `playerId`: (string)
- `notification`: (string)
- `params`: (Array\)
- `raw`: (string) unprocessed notification message
- `server`: (object)
- `host`: (string)
- `port`: (string)

> Notifications that are not associated with a specific player, such as 'rescan', will not have the `playerId` param.

---

### Errors

Breaking change from v0.x to v1.x

In v0.x, error codes are defined as standalone constants.

In v1.x, they are defined in the [`NotificationListenerErrorCode`](docs/api/enums/NotificationListenerErrorCode.md) enum.

```
notificationListener.start()
.then(() => {
...
})
.catch((err) => {
...
});
```
Where an error is an instance of [`NotificationListenerError`](docs/api/classes/NotificationListenerError.md), you can obtain more information about it:

```
if (err instanceof NotificationListenerError) {
console.log(`
Error: ${ err.message },
Code: ${ err.code }, // Can be undefined
Cause: ${ err.cause } // Underlying error (can be undefined)
`);
...
}
```

#### Error codes

| Enum: [`NotificationListenerErrorCode`](docs/api/enums/NotificationListenerErrorCode.md) | Description |
|-------------------------|---------------------------------------------------------------------------------------------------------------------|
|`AuthError` | Login attempt failed for a password-protected server. |
|`SendCommandError` | A command could not be sent to the server. The underlying error can be obtained from `err.cause`. |
|`CommandResponseTimeout` | After sending a command to the server, a response is expected but not received within a timeout period of 5 seconds.|

---

## Running the Example
```
// ESM
npm run example -- -h [server address] -p [server CLI port] -u [username] -pw [password]

// CJS
node index.cjs -h [server address] -p [server CLI port] -u [username] -pw [password]
```

Only include options that are applicable. Generally, you do not have to specify `-p` since most
LMS installations use the default 9090 port for CLI.

## Changelog

1.0.0:
- Migrate to TypeScript and package as ESM / CJS hybrid module

0.1.2:
- Fix blank credentials causing login timeout

0.1.1:
- Fix example

0.1.0:
- Initial release

## License
MIT