mirror of
https://github.com/koush/scrypted.git
synced 2026-03-16 23:22:07 +00:00
214 lines
7.8 KiB
Markdown
214 lines
7.8 KiB
Markdown
# Table of Contents
|
|
* [Getting Started](#getting-started)
|
|
* [Typescript Sample Setup](#typescript-sample-setup)
|
|
* [Creating a Switch](#creating-a-switch)
|
|
* [Core Concepts](#core-concepts)
|
|
* [Interfaces](#interfaces)
|
|
* [Events](#events)
|
|
* [Creating Multiple Devices](#creating-multiple-devices)
|
|
* [Full Reference](/modules)
|
|
* [Sample Plugins](https://github.com/koush/scrypted/tree/main/plugins)
|
|
* [Camera Provider Sample](https://github.com/koush/scrypted-sample-cameraprovider)
|
|
|
|
<br/>
|
|
<br/>
|
|
|
|
# Getting Started
|
|
|
|
The quickest way to get started is to check out the the [Typescript sample](https://github.com/koush/scrypted-vscode-typescript) and open it in Visual Studio Code. The setup instructions can be found in the readme for the [project](https://github.com/koush/scrypted-vscode-typescript).
|
|
|
|
<br/>
|
|
|
|
## Typescript Sample Setup
|
|
|
|
These instructions can be followed on your preferred development machine, and do not need to be run on the Scrypted Server itself. The Scrypted SDK can deploy and **debug** plugins running on a remote server. For example, the VS Code development environment can be running on a Mac, while the server is running on a Raspberry Pi.
|
|
|
|
1. npm install
|
|
2. Open this plugin director yin VS Code.
|
|
3. Edit `.vscode/settings.json` to point to the IP address of your Scrypted server. The default is `127.0.0.1`, your local machine.
|
|
4. Press Launch (green arrow button in the Run and Debug sidebar) to start debugging.
|
|
* The VS Code `Terminal` area may show an authentication failure and prompt you to log in to the Scrypted Management Console with `npx scrypted login`. You will only need to do this once. You can then relaunch afterwards.
|
|
|
|
<p align="center">
|
|
<img width="538" alt="image" src="https://user-images.githubusercontent.com/73924/151676616-c730eb56-26dd-466d-b7f5-25783300b3bc.png">
|
|
</p>
|
|
<br/>
|
|
|
|
## Creating a Switch
|
|
|
|
The aforementioned sample will create a single switch device.
|
|
|
|
```typescript
|
|
import axios from 'axios';
|
|
import { OnOff, ScryptedDeviceBase } from '@scrypted/sdk';
|
|
|
|
console.log('Hello World. This will create a virtual OnOff device.');
|
|
// OnOff is a simple binary switch. See "interfaces" in package.json
|
|
// to add support for more capabilities, like Brightness or Lock.
|
|
|
|
class TypescriptLight extends ScryptedDeviceBase implements OnOff {
|
|
constructor() {
|
|
super();
|
|
this.on = this.on || false;
|
|
}
|
|
async turnOff() {
|
|
this.console.log('turnOff was called!');
|
|
this.on = false;
|
|
}
|
|
async turnOn() {
|
|
// set a breakpoint here.
|
|
this.console.log('turnOn was called!');
|
|
|
|
this.console.log("Let's pretend to perform a web request on an API that would turn on a light.");
|
|
const ip = await axios.get('http://jsonip.com');
|
|
this.console.log(`my ip: ${ip.data.ip}`);
|
|
|
|
this.on = true;
|
|
}
|
|
}
|
|
|
|
export default TypescriptLight;
|
|
```
|
|
<br/>
|
|
<br/>
|
|
|
|
# Core Concepts
|
|
|
|
Devices the core entry points and objects within Scrypted. A device can be a physical device, a virtual device, a provider of other devices (like a hub), a webhook, etc. Devices have two primary properties: Interfaces and Events.
|
|
<br/>
|
|
|
|
## Interfaces
|
|
|
|
Interfaces are how devices expose their capabilities to Scrypted. An OnOff interface represents a binary switch. The Brightness interface represents a light that can be dimmed. The ColorSettingRgb interface indicates the light can change color. A device may expose multiple different interfaces to describe its functionality.
|
|
|
|
For example, given the following devices, the interfaces they would implement:
|
|
|
|
Outlet: OnOff,
|
|
Dimmer Switch: OnOff, Brightness,
|
|
Color Bulb: OnOff, Brightness, ColorSettingRgb
|
|
Interfaces aren't only used represent characteristics of physical devices. As mentioned, they provide ways to hook into Scrypted. The HttpRequestHandler lets you add a web hook to handle incoming web requests. EventListener lets you create handlers that respond to events. DeviceProvider acts as a controller platform (like Hue or Lifx) for exposing multiple other devices to Scrypted.
|
|
|
|
Interfaces also provide a way to query the device state. Such as checking whether an outlet is on or off, the current brightness level, or the current color.
|
|
|
|
```typescript
|
|
// Interfaces describe how the current state of a device, and can be used to modify that state.
|
|
if (light.on) {
|
|
light.turnOff();
|
|
}
|
|
else {
|
|
light.turnOn();
|
|
}
|
|
```
|
|
<br/>
|
|
|
|
## Events
|
|
|
|
Scrypted maintains the state of all connected devices. Whenever the state of an interface is updated on a device, an Event will be triggered for that particular interface.
|
|
|
|
For example, when a light turns on, the Light device would send an OnOff event. If a Slack message is received, the Slack device would send a MessagingEndpoint event. Setting a schedule for sunrise on weekdays would send an Alarm event on that schedule.
|
|
|
|
Automations subscribe to these events in your smart home setup and react accordingly.
|
|
|
|
```
|
|
// Events are triggered by the device on update, and can be observed.
|
|
light.listen('OnOff', (eventSource: ScryptedDevice, eventDetails: EventDetails, eventData: object) => {
|
|
if (eventData) {
|
|
log.i('The light was turned on.');
|
|
}
|
|
else {
|
|
log.i('The light was turned off.');
|
|
}
|
|
});
|
|
```
|
|
<br/>
|
|
<br/>
|
|
|
|
# Creating Multiple Devices
|
|
|
|
Most plugins will want to create multiple devices. This is done by implementing the DeviceProvider interface.
|
|
|
|
To do this, thep project `package.json` needs to update the `scrypted` section that describes the plugin:
|
|
|
|
```json
|
|
"scrypted": {
|
|
"name": "TypeScript Light Provider",
|
|
"type": "DeviceProvider",
|
|
"interfaces": [
|
|
"DeviceProvider"
|
|
]
|
|
},
|
|
```
|
|
|
|
Then, the code is updated to support multiple lights:
|
|
|
|
```typescript
|
|
import axios from 'axios';
|
|
import sdk, { DeviceProvider, OnOff, ScryptedDeviceBase, ScryptedDeviceType, ScryptedInterface } from '@scrypted/sdk';
|
|
|
|
class TypescriptLight extends ScryptedDeviceBase implements OnOff {
|
|
constructor(nativeId?: string) {
|
|
super(nativeId);
|
|
this.on = this.on || false;
|
|
}
|
|
async turnOff() {
|
|
this.console.log('turnOff was called!');
|
|
this.on = false;
|
|
}
|
|
async turnOn() {
|
|
// set a breakpoint here.
|
|
this.console.log('turnOn was called!');
|
|
|
|
this.console.log("Let's pretend to perform a web request on an API that would turn on a light.");
|
|
const ip = await axios.get('http://jsonip.com');
|
|
this.console.log(`my ip: ${ip.data.ip}`);
|
|
|
|
this.on = true;
|
|
}
|
|
}
|
|
|
|
class MyDeviceProvider extends ScryptedDeviceBase implements DeviceProvider {
|
|
constructor(nativeId?: string) {
|
|
super(nativeId);
|
|
|
|
this.prepareDevices();
|
|
}
|
|
|
|
async prepareDevices() {
|
|
// "Discover" the lights provided by this provider to Scrypted.
|
|
await sdk.deviceManager.onDevicesChanged({
|
|
devices: [
|
|
{
|
|
// the native id is the unique identifier for this light within
|
|
// your plugin.
|
|
nativeId: 'light1',
|
|
name: 'Light 1',
|
|
type: ScryptedDeviceType.Light,
|
|
interfaces: [
|
|
ScryptedInterface.OnOff,
|
|
]
|
|
},
|
|
{
|
|
nativeId: 'light2',
|
|
name: 'Light 1',
|
|
type: ScryptedDeviceType.Light,
|
|
interfaces: [
|
|
ScryptedInterface.OnOff,
|
|
]
|
|
}
|
|
]
|
|
});
|
|
}
|
|
|
|
// After the lights are discovered, Scrypted will request the plugin create the
|
|
// instance that can be used to control and query the light.
|
|
getDevice(nativeId: string) {
|
|
return new TypescriptLight(nativeId);
|
|
}
|
|
}
|
|
|
|
// Export the provider from the plugin, rather than the individual light.
|
|
export default MyDeviceProvider;
|
|
```
|
|
|
|
Running the sample will then create 3 devices: the plugin/hub and the 2 lights it controls.
|