Skip to content

Commit

Permalink
feat: add new toggle, isOn, getBrightnessInLumen and `getTemper…
Browse files Browse the repository at this point in the history
…atureInKelvin` functions, plus `litra-toggle` CLI

* Add functions to get current power state, brightness and temp
Add function to toggle power on/off
Fix typos

Resolves #42

* Update README.md to include new getter and toggle functions

Ref #42

* Update CLI to provide brightness and temp
Add CLI command for toggle

Ref #42

* Add missing power state tests

* Apply suggestions from code review for README.md

Co-authored-by: Tim Rogers <[email protected]>

* Update command descriptions

* Change getPowerState to isOn

* Update tests/driver.test.ts

Co-authored-by: Tim Rogers <[email protected]>

* Update src/cli/litra-toggle.ts

Co-authored-by: Tim Rogers <[email protected]>

* Update tests/driver.test.ts

Co-authored-by: Tim Rogers <[email protected]>

* chore: build Typescript

---------

Co-authored-by: Tim Rogers <[email protected]>
  • Loading branch information
hhaidar and timrogers authored Mar 28, 2023
1 parent c6224b1 commit 01c53f8
Show file tree
Hide file tree
Showing 19 changed files with 538 additions and 73 deletions.
98 changes: 76 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,31 +4,32 @@ This JavaScript driver allows you to control [Logitech Litra Glow](https://www.l

With this driver, you can:

* Turn your light on and off
* Set the brightness of your light
* Set the temperature of your light
- Turn your light on and off
- Check if the light is on or off
- Set and get the brightness of your light
- Set and get the temperature of your light

## Compatibility

This library is only tested on macOS Monterey (12.5). It's powered by [`node-hid`](https://github.com/node-hid/node-hid), which is compatible with other macOS versions, Windows and Linux, so it would be expected to work there too, but your milage may vary 🙏
This library is only tested on macOS Monterey (12.5) and Windows 11. It's powered by [`node-hid`](https://github.com/node-hid/node-hid), which is compatible with other macOS versions, Windows and Linux, so it would be expected to work there too, but your milage may vary 🙏

## Using as a command line tool

Make sure you have Node.js available on your machine, and then install the package with `npm install -g litra`.

With the package installed:

* Use the `litra-on` and `litra-off` commands to turn your light on and off.
* Use the `litra-brightness` command to set your Litra's brightness to a percentage of its maximum (e.g. `litra-brightness 90`).
* Use the `litra-brightness-lm` command to set your Litra's brightness to a value in Lumen (e.g. `litra-brightness 250`).
* Use the `litra-temperature-k` command to set your Litra's temperature to a value in Kelvin (e.g. `litra-temperature-k 6500`).
- Use the `litra-on`, `litra-off` and `litra-toggle` commands to turn your light on and off.
- Use the `litra-brightness` command to set your Litra's brightness to a percentage of its maximum (e.g. `litra-brightness 90`).
- Use the `litra-brightness-lm` command to get or set your Litra's brightness to a value in Lumen (e.g. `litra-brightness 250`).
- Use the `litra-temperature-k` command to get or set your Litra's temperature to a value in Kelvin (e.g. `litra-temperature-k 6500`).

All of the these commands support a `--serial-number`/`-s` argument to specify the serial number of the device you want to target. If you only have one Litra device, you can omit this argument. If you have multiple devices, we recommend specifying it. If it isn't specified, the "first" device will be picked, but this isn't guaranteed to be stable between command runs.

You can also use:

* `litra-devices` to list Litra devices connected to your machine, including in JSON format with `--json`
* `litra-identify` to interactively identify the serial numbers of your Litra devices, if you have multiple connected
- `litra-devices` to list Litra devices connected to your machine, including in JSON format with `--json`
- `litra-identify` to interactively identify the serial numbers of your Litra devices, if you have multiple connected

Each CLI command can also be called with `--help` for more detailed documentation.

Expand All @@ -46,7 +47,7 @@ npm install --save litra

#### Checking if a Litra device is plugged in

The `findDevice` function checks your computer to find whether a Logitech Litra device is plugged in.
The `findDevice` function checks your computer to find whether a Logitech Litra device is plugged in.

If it is, it returns an object representing the device, which you can pass into other function. If it isn't, it returns `null`.

Expand All @@ -64,7 +65,7 @@ if (device) {
}
```

If you're a *huge* fan of Litra devices and you have multiple plugged in at the same time, use `findDevices` instead:
If you're a _huge_ fan of Litra devices and you have multiple plugged in at the same time, use `findDevices` instead:

```js
const devices = findDevices();
Expand All @@ -85,38 +86,78 @@ if (devices.length > 0) {

Find your device with `findDevice`, and then use the simple `turnOn` and `turnOff` functions. They just take one parameter: the device.

You can also use the `isOn` function to check if your device is on/off.

```js
import { findDevice, turnOff, turnOn } from 'litra';
import { findDevice, turnOff, turnOn, isOn } from 'litra';

const device = findDevice();

// Turn your light on, then turn it off again after 5 seconds
if (device) {
turnOn(device);
setTimeout(() => turnOff(device), 5000));

if (isOn(device)) {
console.log(
`Your device is now on!`,
);
}

setTimeout(() => {
turnOff(device)

if (!isOn(device)) {
console.log(
`Your device is now off!`,
);
}
}, 5000));
}
```

#### Setting the brightness of your Litra device
Alternatively, you can use the `toggle` function to switch your device on if it's off and vice-versa.

```js
import { findDevice, toggle } from 'litra';

const device = findDevice();

// Turn your light on if it's currently off, and vice-versa
toggle();
```

#### Setting and getting the brightness of your Litra device

You can set the brightness of your Litra device, measured in Lumen, using the `setBrightnessInLumen` function.
You can set the brightness of your Litra device, measured in Lumen, using the `setBrightnessInLumen` function.

To get the current brightness of your device, use the `getBrightnessInLumen` function.

The Litra Glow supports brightness between 20 and 250 Lumen. The Litra Beam supports brightness between 20 and 400 Lumen.

You can programatically check what brightness levels are supported by your device. Once you know what brightness levels are supported, you can set the brightness in Lumen. If you try to set a value that isn't allowed by your device, an error will be thrown:

```js
import { findDevice, getMaximumBrightnessInLumenForDevice, getMinimumBrightnessInLumenForDevice, setBrightnessInLumen } from 'litra';
import {
findDevice,
getMaximumBrightnessInLumenForDevice,
getMinimumBrightnessInLumenForDevice,
setBrightnessInLumen,
} from 'litra';

const device = findDevice();

if (device) {
const minimumBrightness = getMinimumBrightnessInLumenForDevice(device);
const maximumBrightness = getMaximumBrightnessInLumenForDevice(device);

console.log(`The minimum allowed brightness is ${minimumBrightness} and the maximum is ${maximumBrightness}`);
console.log(
`The minimum allowed brightness is ${minimumBrightness} and the maximum is ${maximumBrightness}`,
);

setBrightnessInLumen(device, 150);

// Will return 150
getBrightnessInLumen(device);
}
```

Expand All @@ -136,12 +177,20 @@ if (device) {

You can set the temperature of your Litra device, measured in Kelvin, using the `setTemperatureInKelvin` function.

The `getTemperatureInKelvin` function can be used to get the current temperature your device is set to.

Both the Litra Glow and Litra Beam support temperatures which are multiples of 100 between 2700 and 6500 Kelvin (i.e.. 2700, 2800, 2900, etc.).

You can check programatically what temperature levels are supported by your device. Once you know what temperature levels are supported, you can set the temperature in Kelvin. If you try to set a value that isn't allowed by your device, an error will be thrown:

```js
import { findDevice, getAllowedTemperaturesInKelvinForDevice, getMaximumTemperatureInKelvinForDevice, getMinimumTemperatureInKelvinForDevice, setTemperatureInKelvin } from 'litra';
import {
findDevice,
getAllowedTemperaturesInKelvinForDevice,
getMaximumTemperatureInKelvinForDevice,
getMinimumTemperatureInKelvinForDevice,
setTemperatureInKelvin,
} from 'litra';

const device = findDevice();

Expand All @@ -150,16 +199,21 @@ if (device) {
const maximumTemperature = getMaximumTemperatureInKelvinForDevice(device);
const allowedTemperatures = getAllowedTemperaturesInKelvinForDevice(device);

console.log(`The minimum allowed temperature is ${minimumTemperature} and the maximum is ${maximumTemperature}`);
console.log(
`The minimum allowed temperature is ${minimumTemperature} and the maximum is ${maximumTemperature}`,
);
console.log(`The following temperature are allowed: ${allowedTemperatures.join(', ')}`);

setTemperatureInKelvin(device, 6500);

// Should return 6500
getTemeratureInKelvin(device);
}
```

## Using with Raycast

Litra integrates with [Raycast](https://www.raycast.com/) so you can manage your Litra device from the Raycast launcher.
Litra integrates with [Raycast](https://www.raycast.com/) so you can manage your Litra device from the Raycast launcher.

To use the integration, just install this package globally with `npm install -g litra`, add the "Logitech Litra" extension from the [Raycast Store](https://www.raycast.com/timrogers/logitech-litra) (source code [here](https://github.com/timrogers/raycast-logitech-litra)), find the "Manage Devices" command and then follow the instructions to configure the extension.

Expand All @@ -169,4 +223,4 @@ Litra integrates with [Oversight](https://objective-see.org/products/oversight.h

To use the integration, just point Oversight at the `litra-oversight` CLI command. You can find the path of the binary on Unix machines by running `which litra-oversight` from a terminal after installing this package.

If you have multiple Litra devices, they will all be targeted when `litra-oversight` runs
If you have multiple Litra devices, they will all be targeted when `litra-oversight` runs
11 changes: 8 additions & 3 deletions dist/commonjs/cli/litra-brightness-lm.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,20 @@ const driver_1 = require("../driver");
const utils_1 = require("./utils");
commander_1.program
.name('litra-brightness')
.description('Sets the brightness of a Litra device to a value in Lumen')
.description("Manages the brightness of a Litra device. If a brightness argument is provided, it sets the device's brightness to the supplied value in Lumen. If no brightness argument is provided, it returns the current brightness in Lumen.")
.option('-s, --serial-number <serialNumber>', 'serial number of the Litra device. If this is not specified and multiple devices are connected, this will default to the first identified device, which is not guaranteed to be the same every time you run this command')
.argument('<brightness>', 'the brightness in Lumen, e.g. `80`', utils_1.parseIntOption);
.argument('[brightness]', 'the brightness in Lumen, e.g. `80`', utils_1.parseIntOption);
commander_1.program.parse();
const { serialNumber } = commander_1.program.opts();
const [brightness] = commander_1.program.processedArgs;
try {
const device = (0, utils_1.getDeviceForCLI)(serialNumber);
(0, driver_1.setBrightnessInLumen)(device, brightness);
if (brightness) {
(0, driver_1.setBrightnessInLumen)(device, brightness);
}
else {
console.log((0, driver_1.getBrightnessInLumen)(device));
}
process.exit(0);
}
catch (e) {
Expand Down
11 changes: 8 additions & 3 deletions dist/commonjs/cli/litra-temperature-k.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,20 @@ const driver_1 = require("../driver");
const utils_1 = require("./utils");
commander_1.program
.name('litra-temperature-k')
.description('Sets the temperature of a Litra device to a value in Kelvin')
.description("Manages the temperature of a Litra device. If a temperature argument is provided, it sets the device's temperature to the supplied value in Kelvin. If no temperature argument is provided, it returns the current temperature in Kelvin.")
.option('-s, --serial-number <serialNumber>', 'serial number of the Litra device. If this is not specified and multiple devices are connected, this will default to the first identified device, which is not guaranteed to be the same every time you run this command')
.argument('<temperature>', 'the temperature in Kelvin, e.g. `2000`', utils_1.parseIntOption);
.argument('[temperature]', 'the temperature in Kelvin, e.g. `2000`', utils_1.parseIntOption);
commander_1.program.parse();
const { serialNumber } = commander_1.program.opts();
const [temperature] = commander_1.program.processedArgs;
try {
const device = (0, utils_1.getDeviceForCLI)(serialNumber);
(0, driver_1.setTemperatureInKelvin)(device, temperature);
if (temperature) {
(0, driver_1.setTemperatureInKelvin)(device, temperature);
}
else {
console.log((0, driver_1.getTemperatureInKelvin)(device));
}
process.exit(0);
}
catch (e) {
Expand Down
2 changes: 2 additions & 0 deletions dist/commonjs/cli/litra-toggle.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#!/usr/bin/env node
export {};
21 changes: 21 additions & 0 deletions dist/commonjs/cli/litra-toggle.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#!/usr/bin/env node
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const commander_1 = require("commander");
const driver_1 = require("../driver");
const utils_1 = require("./utils");
commander_1.program
.name('litra-toggle')
.description('Toggles a Litra device on or off')
.option('-s, --serial-number <serialNumber>', 'serial number of the Litra device. If this is not specified and multiple devices are connected, this will default to the first identified device, which is not guaranteed to be the same every time you run this command');
commander_1.program.parse();
const { serialNumber } = commander_1.program.opts();
try {
const device = (0, utils_1.getDeviceForCLI)(serialNumber);
(0, driver_1.toggle)(device);
process.exit(0);
}
catch (e) {
console.log(e);
process.exit(1);
}
38 changes: 33 additions & 5 deletions dist/commonjs/driver.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export declare enum DeviceType {
export interface Device {
hid: {
write: (values: number[] | Buffer) => number;
readSync(): number[];
};
type: DeviceType;
serialNumber: string;
Expand All @@ -30,17 +31,30 @@ export declare const findDevice: () => Device | null;
*/
export declare const findDevices: () => Device[];
/**
* Turns your Logitech Litra device on.
* Turns your Logitech Litra device on
*
* @param {Device} device The device to set the temperature of
* @param {Device} device The device to turn on
*/
export declare const turnOn: (device: Device) => void;
/**
* Turns your Logitech Litra device off.
* Turns your Logitech Litra device off
*
* @param {Device} device The device to set the temperature of
* @param {Device} device The device to turn off
*/
export declare const turnOff: (device: Device) => void;
/**
* Toggles your Logitech Litra device on or off
*
* @param {Device} device The device to toggle on or off
*/
export declare const toggle: (device: Device) => void;
/**
* Gets the current power state of your Logitech Litra device
*
* @param {Device} device The device to get the current power state for
* @returns {boolean} Current power state where true = on and false = off
*/
export declare const isOn: (device: Device) => boolean;
/**
* Sets the temperature of your Logitech Litra device
*
Expand All @@ -52,15 +66,29 @@ export declare const turnOff: (device: Device) => void;
* and maximum temperature for your device.
*/
export declare const setTemperatureInKelvin: (device: Device, temperatureInKelvin: number) => void;
/**
* Gets the temperature of your Logitech Litra device
*
* @param {Device} device The device to get the temperature for
* @returns {number} The current temperature in Kelvin
*/
export declare const getTemperatureInKelvin: (device: Device) => number;
/**
* Sets the brightness of your Logitech Litra device, measured in Lumen
*
* @param {Device} device The device to set the temperature of
* @param {Device} device The device to set the brightness of
* @param {number} brightnessInLumen The brightness to set in Lumen. Use the
* `getMinimumBrightnessInLumenForDevice` and `getMaximumBrightnessInLumenForDevice`
* functions to get the minimum and maximum brightness for your device.
*/
export declare const setBrightnessInLumen: (device: Device, brightnessInLumen: number) => void;
/**
* Gets the current brightness of your Logitech Litra device, measured in Lumen
*
* @param {Device} device The device to get the current brightness for
* @returns {number} The current brightness in Lumen
*/
export declare const getBrightnessInLumen: (device: Device) => number;
/**
* Set the brightness of your Logitech Litra device to a percentage
* of the device's maximum brightness
Expand Down
Loading

0 comments on commit 01c53f8

Please sign in to comment.