mirror of
https://github.com/koush/scrypted.git
synced 2026-02-10 09:12:03 +00:00
Merge branch 'main' of github.com:koush/scrypted
This commit is contained in:
@@ -37,12 +37,14 @@ export abstract class SettingsMixinDeviceBase<T> extends MixinDeviceBase<T & Set
|
||||
}
|
||||
catch (e) {
|
||||
const name = this.name;
|
||||
const description = `${name} Extension settings failed to load.`;
|
||||
this.console.error(description, e)
|
||||
allSettings.push({
|
||||
key: Math.random().toString(),
|
||||
title: name,
|
||||
value: 'Settings Error',
|
||||
group: 'Errors',
|
||||
description: `${name} Extension settings failed to load.`,
|
||||
description,
|
||||
readonly: true,
|
||||
});
|
||||
}
|
||||
@@ -57,12 +59,14 @@ export abstract class SettingsMixinDeviceBase<T> extends MixinDeviceBase<T & Set
|
||||
}
|
||||
catch (e) {
|
||||
const name = deviceManager.getDeviceState(this.mixinProviderNativeId).name;
|
||||
const description = `${name} Extension settings failed to load.`;
|
||||
this.console.error(description, e)
|
||||
allSettings.push({
|
||||
key: Math.random().toString(),
|
||||
title: name,
|
||||
value: 'Settings Error',
|
||||
group: 'Errors',
|
||||
description: `${name} Extension settings failed to load.`,
|
||||
description,
|
||||
readonly: true,
|
||||
});
|
||||
}
|
||||
|
||||
4
plugins/hikvision/package-lock.json
generated
4
plugins/hikvision/package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@scrypted/hikvision",
|
||||
"version": "0.0.84",
|
||||
"version": "0.0.85",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@scrypted/hikvision",
|
||||
"version": "0.0.84",
|
||||
"version": "0.0.85",
|
||||
"license": "Apache",
|
||||
"dependencies": {
|
||||
"@koush/axios-digest-auth": "^0.8.5",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@scrypted/hikvision",
|
||||
"version": "0.0.84",
|
||||
"version": "0.0.85",
|
||||
"description": "HikVision Plugin for Scrypted",
|
||||
"author": "Scrypted",
|
||||
"license": "Apache",
|
||||
|
||||
@@ -52,21 +52,22 @@ export class HikVisionCameraAPI {
|
||||
resolve(deviceModel);
|
||||
} catch (e) {
|
||||
this.console.error('error checking NVR model', e);
|
||||
resolve("unknown");
|
||||
resolve(undefined);
|
||||
}
|
||||
});
|
||||
}
|
||||
return await this.deviceModel;
|
||||
}
|
||||
|
||||
async checkIsOldModel(): Promise<boolean> {
|
||||
async checkIsOldModel() {
|
||||
// The old Hikvision DS-7608NI-E2 doesn't support channel capability checks, and the requests cause errors
|
||||
const model = await this.checkDeviceModel();
|
||||
if (!model)
|
||||
return;
|
||||
return !!model?.match(/DS-7608NI-E2/);
|
||||
}
|
||||
|
||||
async checkStreamSetup(channel: string): Promise<HikVisionCameraStreamSetup> {
|
||||
const isOld = await this.checkIsOldModel();
|
||||
async checkStreamSetup(channel: string, isOld: boolean): Promise<HikVisionCameraStreamSetup> {
|
||||
if (isOld) {
|
||||
this.console.error('NVR is old version. Defaulting camera capabilities to H.264/AAC');
|
||||
return {
|
||||
|
||||
@@ -2,14 +2,33 @@ import sdk, { MediaObject, Camera, ScryptedInterface } from "@scrypted/sdk";
|
||||
import { EventEmitter } from "stream";
|
||||
import { HikVisionCameraAPI } from "./hikvision-camera-api";
|
||||
import { Destroyable, UrlMediaStreamOptions, RtspProvider, RtspSmartCamera } from "../../rtsp/src/rtsp";
|
||||
import { sleep } from "../../../common/src/sleep";
|
||||
import { HikVisionCameraEvent } from "./hikvision-camera-api";
|
||||
const { mediaManager } = sdk;
|
||||
|
||||
class HikVisionCamera extends RtspSmartCamera implements Camera {
|
||||
hasCheckedCodec = false;
|
||||
channelIds: Promise<string[]>;
|
||||
client: HikVisionCameraAPI;
|
||||
|
||||
// bad hack, but whatever.
|
||||
codecCheck = (async () => {
|
||||
while (true) {
|
||||
try {
|
||||
const streamSetup = await this.client.checkStreamSetup(this.getRtspChannel(), await this.isOld());
|
||||
if (streamSetup.videoCodecType !== 'H.264') {
|
||||
this.log.a(`This camera is configured for ${streamSetup.videoCodecType} on the main channel. Configuring it it for H.264 is recommended for optimal performance.`);
|
||||
}
|
||||
if (!this.isAudioDisabled() && streamSetup.audioCodecType && streamSetup.audioCodecType !== 'AAC') {
|
||||
this.log.a(`This camera is configured for ${streamSetup.audioCodecType} on the main channel. Configuring it for AAC is recommended for optimal performance.`);
|
||||
}
|
||||
break;
|
||||
}
|
||||
catch (e) {
|
||||
await sleep(60000);
|
||||
}
|
||||
}
|
||||
})();
|
||||
|
||||
listenEvents() {
|
||||
let motionTimeout: NodeJS.Timeout;
|
||||
const ret = new EventEmitter() as (EventEmitter & Destroyable);
|
||||
@@ -84,19 +103,6 @@ class HikVisionCamera extends RtspSmartCamera implements Camera {
|
||||
getClient() {
|
||||
if (!this.client)
|
||||
this.client = this.createClient();
|
||||
(async () => {
|
||||
if (this.hasCheckedCodec)
|
||||
return;
|
||||
const streamSetup = await this.client.checkStreamSetup(this.getRtspChannel());
|
||||
this.hasCheckedCodec = true;
|
||||
if (streamSetup.videoCodecType !== 'H.264') {
|
||||
this.log.a(`This camera is configured for ${streamSetup.videoCodecType} on the main channel. Configuring it it for H.264 is recommended for optimal performance.`);
|
||||
}
|
||||
if (!this.isAudioDisabled() && streamSetup.audioCodecType && streamSetup.audioCodecType !== 'AAC') {
|
||||
this.log.a(`This camera is configured for ${streamSetup.audioCodecType} on the main channel. Configuring it for AAC is recommended for optimal performance.`);
|
||||
}
|
||||
})();
|
||||
|
||||
return this.client;
|
||||
}
|
||||
|
||||
@@ -142,11 +148,25 @@ class HikVisionCamera extends RtspSmartCamera implements Camera {
|
||||
return this.storage.getItem('rtspUrlParams') || '?transportmode=unicast';
|
||||
}
|
||||
|
||||
async isOld() {
|
||||
const client = this.getClient();
|
||||
let isOld: boolean;
|
||||
if (this.storage.getItem('isOld')) {
|
||||
isOld = this.storage.getItem('isOld') === 'true';
|
||||
}
|
||||
else {
|
||||
isOld = await client.checkIsOldModel();
|
||||
this.storage.setItem('isOld', isOld?.toString());
|
||||
}
|
||||
return isOld;
|
||||
}
|
||||
|
||||
async getConstructedVideoStreamOptions(): Promise<UrlMediaStreamOptions[]> {
|
||||
if (!this.channelIds) {
|
||||
const client = this.getClient();
|
||||
this.channelIds = new Promise(async (resolve, reject) => {
|
||||
const isOld = await client.checkIsOldModel();
|
||||
const isOld = await this.isOld();
|
||||
|
||||
if (isOld) {
|
||||
this.console.error('Old NVR. Defaulting to two camera configuration');
|
||||
const camNumber = this.getCameraNumber() || '1';
|
||||
|
||||
4
plugins/homekit/package-lock.json
generated
4
plugins/homekit/package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@scrypted/homekit",
|
||||
"version": "0.0.173",
|
||||
"version": "0.0.176",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@scrypted/homekit",
|
||||
"version": "0.0.173",
|
||||
"version": "0.0.176",
|
||||
"dependencies": {
|
||||
"hap-nodejs": "file:../../external/HAP-NodeJS",
|
||||
"lodash": "^4.17.21",
|
||||
|
||||
@@ -40,5 +40,5 @@
|
||||
"@types/qrcode": "^1.4.1",
|
||||
"@types/url-parse": "^1.4.3"
|
||||
},
|
||||
"version": "0.0.173"
|
||||
"version": "0.0.176"
|
||||
}
|
||||
|
||||
@@ -198,6 +198,7 @@ addSupportedType({
|
||||
return;
|
||||
|
||||
const reconfigured: MediaStreamOptions = Object.assign({
|
||||
id: selectedStream?.id,
|
||||
video: {
|
||||
},
|
||||
}, selectedStream || {});
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
import { Entry, ScryptedDevice, ScryptedDeviceType, ScryptedInterface } from '@scrypted/sdk'
|
||||
import { Entry, EntrySensor, ScryptedDevice, ScryptedDeviceType, ScryptedInterface } from '@scrypted/sdk'
|
||||
import { addSupportedType, bindCharacteristic, DummyDevice } from '../common'
|
||||
import { Characteristic, CharacteristicEventTypes, CharacteristicSetCallback, CharacteristicValue, NodeCallback, Service } from '../hap';
|
||||
import { makeAccessory } from './common';
|
||||
@@ -9,7 +9,7 @@ addSupportedType({
|
||||
probe(device: DummyDevice): boolean {
|
||||
return device.interfaces.includes(ScryptedInterface.Entry) && device.interfaces.includes(ScryptedInterface.EntrySensor);
|
||||
},
|
||||
getAccessory: async (device: ScryptedDevice & Entry) => {
|
||||
getAccessory: async (device: ScryptedDevice & Entry & EntrySensor) => {
|
||||
const accessory = makeAccessory(device);
|
||||
|
||||
const service = accessory.addService(Service.GarageDoorOpener, device.name);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
import { VideoCamera, MediaPlayer, MediaPlayerState, ScryptedDevice, ScryptedDeviceType, ScryptedInterface } from '@scrypted/sdk'
|
||||
import { VideoCamera, MediaPlayer, MediaPlayerState, ScryptedDevice, ScryptedDeviceType, ScryptedInterface, StartStop } from '@scrypted/sdk'
|
||||
import { addSupportedType, bindCharacteristic, DummyDevice } from '../common'
|
||||
import { Categories, Characteristic, CharacteristicEventTypes, CharacteristicSetCallback, CharacteristicValue, NodeCallback, Service } from '../hap';
|
||||
import { makeAccessory } from './common';
|
||||
@@ -12,7 +12,7 @@ addSupportedType({
|
||||
probe(device: DummyDevice) {
|
||||
return device.interfaces.includes(ScryptedInterface.MediaPlayer);
|
||||
},
|
||||
getAccessory: async (device: ScryptedDevice & MediaPlayer) => {
|
||||
getAccessory: async (device: ScryptedDevice & MediaPlayer & StartStop) => {
|
||||
const accessory = makeAccessory(device);
|
||||
accessory.category = Categories.TELEVISION;
|
||||
const service = accessory.addService(Service.Television, "Television", "Television");
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
import { MotionSensor, BinarySensor, ScryptedDevice, ScryptedDeviceType, ScryptedInterface, Thermometer } from '@scrypted/sdk'
|
||||
import { MotionSensor, BinarySensor, ScryptedDevice, ScryptedDeviceType, ScryptedInterface, Thermometer, HumiditySensor, AudioSensor, AmbientLightSensor } from '@scrypted/sdk'
|
||||
import { addSupportedType, bindCharacteristic, DummyDevice } from '../common'
|
||||
import { Characteristic, Service } from '../hap';
|
||||
import { makeAccessory } from './common';
|
||||
@@ -9,21 +9,30 @@ addSupportedType({
|
||||
probe(device: DummyDevice) {
|
||||
return device.interfaces.includes(ScryptedInterface.Thermometer) || device.interfaces.includes(ScryptedInterface.BinarySensor) || device.interfaces.includes(ScryptedInterface.MotionSensor);
|
||||
},
|
||||
getAccessory: async (device: ScryptedDevice & BinarySensor & MotionSensor & Thermometer) => {
|
||||
getAccessory: async (device: ScryptedDevice & AmbientLightSensor & AudioSensor & BinarySensor & MotionSensor & Thermometer & HumiditySensor) => {
|
||||
const accessory = makeAccessory(device);
|
||||
|
||||
if (device.interfaces.includes(ScryptedInterface.BinarySensor)) {
|
||||
const contactSensorService = accessory.addService(Service.ContactSensor, device.name);
|
||||
contactSensorService.getCharacteristic(Characteristic.ContactSensorState)
|
||||
|
||||
bindCharacteristic(device, ScryptedInterface.BinarySensor, contactSensorService, Characteristic.ContactSensorState,
|
||||
const service = accessory.addService(Service.ContactSensor, device.name);
|
||||
bindCharacteristic(device, ScryptedInterface.BinarySensor, service, Characteristic.ContactSensorState,
|
||||
() => !!device.binaryState);
|
||||
}
|
||||
|
||||
if (device.interfaces.includes(ScryptedInterface.MotionSensor)) {
|
||||
const motionSensorService = accessory.addService(Service.MotionSensor, device.name);
|
||||
if (device.interfaces.includes(ScryptedInterface.AmbientLightSensor)) {
|
||||
const service = accessory.addService(Service.LightSensor, device.name);
|
||||
bindCharacteristic(device, ScryptedInterface.AmbientLightSensor, service, Characteristic.CurrentAmbientLightLevel,
|
||||
() => device.ambientLight || 0);
|
||||
}
|
||||
|
||||
bindCharacteristic(device, ScryptedInterface.MotionSensor, motionSensorService, Characteristic.MotionDetected,
|
||||
if (device.interfaces.includes(ScryptedInterface.AudioSensor)) {
|
||||
const service = accessory.addService(Service.ContactSensor, device.name + ' Alarm Sound', 'AudioSensor');
|
||||
bindCharacteristic(device, ScryptedInterface.AudioSensor, service, Characteristic.ContactSensorState,
|
||||
() => !!device.audioDetected);
|
||||
}
|
||||
|
||||
if (device.interfaces.includes(ScryptedInterface.MotionSensor)) {
|
||||
const service = accessory.addService(Service.MotionSensor, device.name);
|
||||
bindCharacteristic(device, ScryptedInterface.MotionSensor, service, Characteristic.MotionDetected,
|
||||
() => !!device.motionDetected, true);
|
||||
}
|
||||
|
||||
@@ -31,7 +40,12 @@ addSupportedType({
|
||||
const service = accessory.addService(Service.TemperatureSensor, device.name);
|
||||
bindCharacteristic(device, ScryptedInterface.Thermometer, service, Characteristic.CurrentTemperature,
|
||||
() => device.temperature || 0);
|
||||
}
|
||||
|
||||
if (device.interfaces.includes(ScryptedInterface.HumiditySensor)) {
|
||||
const service = accessory.addService(Service.HumiditySensor, device.name);
|
||||
bindCharacteristic(device, ScryptedInterface.HumiditySensor, service, Characteristic.CurrentRelativeHumidity,
|
||||
() => device.humidity || 0);
|
||||
}
|
||||
|
||||
// todo: more sensors.
|
||||
|
||||
4
plugins/mqtt/package-lock.json
generated
4
plugins/mqtt/package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@scrypted/mqtt",
|
||||
"version": "0.0.36",
|
||||
"version": "0.0.37",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@scrypted/mqtt",
|
||||
"version": "0.0.36",
|
||||
"version": "0.0.37",
|
||||
"dependencies": {
|
||||
"@types/node": "^16.6.1",
|
||||
"aedes": "^0.46.1",
|
||||
|
||||
@@ -38,5 +38,5 @@
|
||||
"@scrypted/sdk": "file:../../sdk",
|
||||
"@types/nunjucks": "^3.2.0"
|
||||
},
|
||||
"version": "0.0.36"
|
||||
"version": "0.0.37"
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { ScryptedDeviceType, ScryptedInterface } from "@scrypted/sdk";
|
||||
|
||||
export function canMixin(type: ScryptedDeviceType, interfaces: string[]): boolean {
|
||||
export function isPublishable(type: ScryptedDeviceType, interfaces: string[]): boolean {
|
||||
const set = new Set(interfaces);
|
||||
set.delete(ScryptedInterface.ObjectDetection);
|
||||
set.delete(ScryptedInterface.DeviceDiscovery);
|
||||
@@ -13,5 +13,6 @@ export function canMixin(type: ScryptedDeviceType, interfaces: string[]): boolea
|
||||
set.delete(ScryptedInterface.Settings);
|
||||
set.delete(ScryptedInterface.Readme);
|
||||
set.delete(ScryptedInterface.BufferConverter);
|
||||
set.delete(ScryptedInterface.ScryptedPlugin);
|
||||
return !!set.size;
|
||||
}
|
||||
|
||||
4
plugins/unifi-protect/package-lock.json
generated
4
plugins/unifi-protect/package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@scrypted/unifi-protect",
|
||||
"version": "0.0.84",
|
||||
"version": "0.0.88",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@scrypted/unifi-protect",
|
||||
"version": "0.0.84",
|
||||
"version": "0.0.88",
|
||||
"license": "Apache",
|
||||
"dependencies": {
|
||||
"@koush/unifi-protect": "file:../../external/unifi-protect",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@scrypted/unifi-protect",
|
||||
"version": "0.0.84",
|
||||
"version": "0.0.88",
|
||||
"description": "Unifi Protect Plugin for Scrypted",
|
||||
"author": "Scrypted",
|
||||
"license": "Apache",
|
||||
|
||||
@@ -10,11 +10,15 @@ export class UnifiLock extends ScryptedDeviceBase implements Lock {
|
||||
}
|
||||
|
||||
async lock(): Promise<void> {
|
||||
await this.protect.loginFetch(this.protect.api.doorlocksUrl() + `/${this.nativeId}/close`);
|
||||
await this.protect.loginFetch(this.protect.api.doorlocksUrl() + `/${this.nativeId}/close`, {
|
||||
method: 'POST',
|
||||
});
|
||||
}
|
||||
|
||||
async unlock(): Promise<void> {
|
||||
await this.protect.loginFetch(this.protect.api.doorlocksUrl() + `/${this.nativeId}/open`);
|
||||
await this.protect.loginFetch(this.protect.api.doorlocksUrl() + `/${this.nativeId}/open`, {
|
||||
method: 'POST',
|
||||
});
|
||||
}
|
||||
|
||||
findLock() {
|
||||
|
||||
@@ -30,9 +30,6 @@ export class UnifiProtect extends ScryptedDeviceBase implements Settings, Device
|
||||
}
|
||||
|
||||
handleUpdatePacket(packet: any): void {
|
||||
if (packet.action?.modelKey !== "camera") {
|
||||
return;
|
||||
}
|
||||
if (packet.action.action !== "update") {
|
||||
return;
|
||||
}
|
||||
@@ -42,6 +39,7 @@ export class UnifiProtect extends ScryptedDeviceBase implements Settings, Device
|
||||
|
||||
const device = this.api.cameras?.find(c => c.id === packet.action.id)
|
||||
|| this.api.lights?.find(c => c.id === packet.action.id)
|
||||
|| this.api.doorlocks?.find(c => c.id === packet.action.id)
|
||||
|| this.api.sensors?.find(c => c.id === packet.action.id);
|
||||
|
||||
if (!device) {
|
||||
@@ -69,6 +67,8 @@ export class UnifiProtect extends ScryptedDeviceBase implements Settings, Device
|
||||
|
||||
listener = (event: Buffer) => {
|
||||
const updatePacket = ProtectApiUpdates.decodeUpdatePacket(this.console, event);
|
||||
this.console.log('update', updatePacket);
|
||||
|
||||
this.handleUpdatePacket(updatePacket);
|
||||
|
||||
if (!updatePacket) {
|
||||
@@ -270,7 +270,7 @@ export class UnifiProtect extends ScryptedDeviceBase implements Settings, Device
|
||||
}
|
||||
|
||||
if (!this.api) {
|
||||
this.api = new ProtectApi(ip, username, password, this.console);
|
||||
this.api = new ProtectApi(ip, username, password);
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
4
plugins/webhook/package-lock.json
generated
4
plugins/webhook/package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@scrypted/webhook",
|
||||
"version": "0.0.16",
|
||||
"version": "0.0.17",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@scrypted/webhook",
|
||||
"version": "0.0.16",
|
||||
"version": "0.0.17",
|
||||
"dependencies": {
|
||||
"@types/node": "^16.6.1"
|
||||
},
|
||||
|
||||
@@ -33,5 +33,5 @@
|
||||
"devDependencies": {
|
||||
"@scrypted/sdk": "file:../../sdk"
|
||||
},
|
||||
"version": "0.0.16"
|
||||
"version": "0.0.17"
|
||||
}
|
||||
|
||||
@@ -6,6 +6,8 @@ import { randomBytes } from 'crypto';
|
||||
const allInterfaceMethods: string[] = [].concat(...Object.values(ScryptedInterfaceDescriptors).map((type: any) => type.methods));
|
||||
const allInterfaceProperties: string[] = [].concat(...Object.values(ScryptedInterfaceDescriptors).map((type: any) => type.properties));
|
||||
|
||||
import { isPublishable} from '../../mqtt/src/publishable-types';
|
||||
|
||||
const { systemManager, endpointManager, mediaManager } = sdk;
|
||||
|
||||
const mediaObjectMethods = [
|
||||
@@ -187,19 +189,7 @@ class WebhookPlugin extends ScryptedDeviceBase implements Settings, MixinProvide
|
||||
}
|
||||
|
||||
async canMixin(type: ScryptedDeviceType, interfaces: string[]): Promise<string[]> {
|
||||
const set = new Set(interfaces);
|
||||
set.delete(ScryptedInterface.ObjectDetection);
|
||||
set.delete(ScryptedInterface.DeviceDiscovery);
|
||||
set.delete(ScryptedInterface.DeviceCreator);
|
||||
set.delete(ScryptedInterface.DeviceProvider);
|
||||
set.delete(ScryptedInterface.MixinProvider);
|
||||
set.delete(ScryptedInterface.PushHandler);
|
||||
set.delete(ScryptedInterface.EngineIOHandler);
|
||||
set.delete(ScryptedInterface.HttpRequestHandler);
|
||||
set.delete(ScryptedInterface.Settings);
|
||||
set.delete(ScryptedInterface.Readme);
|
||||
set.delete(ScryptedInterface.BufferConverter);
|
||||
if (!set.size)
|
||||
if (!isPublishable(type, interfaces))
|
||||
return;
|
||||
return [
|
||||
ScryptedInterface.Settings,
|
||||
|
||||
@@ -633,6 +633,12 @@ export interface AudioSensor {
|
||||
export interface MotionSensor {
|
||||
motionDetected?: boolean;
|
||||
}
|
||||
export interface AmbientLightSensor {
|
||||
/**
|
||||
* The ambient light in lux.
|
||||
*/
|
||||
ambientLight: number;
|
||||
}
|
||||
export interface OccupancySensor {
|
||||
occupied?: boolean;
|
||||
}
|
||||
@@ -1230,6 +1236,7 @@ export enum ScryptedInterface {
|
||||
PowerSensor = "PowerSensor",
|
||||
AudioSensor = "AudioSensor",
|
||||
MotionSensor = "MotionSensor",
|
||||
AmbientLightSensor = "AmbientLightSensor",
|
||||
OccupancySensor = "OccupancySensor",
|
||||
FloodSensor = "FloodSensor",
|
||||
UltravioletSensor = "UltravioletSensor",
|
||||
|
||||
4
sdk/package-lock.json
generated
4
sdk/package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@scrypted/sdk",
|
||||
"version": "0.0.148",
|
||||
"version": "0.0.151",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@scrypted/sdk",
|
||||
"version": "0.0.148",
|
||||
"version": "0.0.151",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@babel/plugin-proposal-class-properties": "^7.14.5",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@scrypted/sdk",
|
||||
"version": "0.0.148",
|
||||
"version": "0.0.151",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
|
||||
@@ -59,6 +59,7 @@ class ScryptedDeviceType(Enum):
|
||||
Valve = "Valve"
|
||||
|
||||
class ScryptedInterface(Enum):
|
||||
AmbientLightSensor = "AmbientLightSensor"
|
||||
AudioSensor = "AudioSensor"
|
||||
Authenticator = "Authenticator"
|
||||
Battery = "Battery"
|
||||
@@ -417,6 +418,10 @@ class Setting(TypedDict):
|
||||
value: SettingValue
|
||||
pass
|
||||
|
||||
class AmbientLightSensor:
|
||||
ambientLight: float
|
||||
pass
|
||||
|
||||
class AudioSensor:
|
||||
audioDetected: bool
|
||||
pass
|
||||
@@ -935,6 +940,7 @@ class ScryptedInterfaceProperty(Enum):
|
||||
powerDetected = "powerDetected"
|
||||
audioDetected = "audioDetected"
|
||||
motionDetected = "motionDetected"
|
||||
ambientLight = "ambientLight"
|
||||
occupied = "occupied"
|
||||
flooded = "flooded"
|
||||
ultraviolet = "ultraviolet"
|
||||
@@ -1236,6 +1242,13 @@ class DeviceState:
|
||||
def motionDetected(self, value: bool):
|
||||
self.setScryptedProperty("motionDetected", value)
|
||||
|
||||
@property
|
||||
def ambientLight(self) -> float:
|
||||
self.getScryptedProperty("ambientLight")
|
||||
@ambientLight.setter
|
||||
def ambientLight(self, value: float):
|
||||
self.setScryptedProperty("ambientLight", value)
|
||||
|
||||
@property
|
||||
def occupied(self) -> bool:
|
||||
self.getScryptedProperty("occupied")
|
||||
|
||||
10
sdk/types.d.ts
vendored
10
sdk/types.d.ts
vendored
@@ -41,6 +41,7 @@ export interface DeviceState {
|
||||
powerDetected?: boolean;
|
||||
audioDetected?: boolean;
|
||||
motionDetected?: boolean;
|
||||
ambientLight?: number;
|
||||
occupied?: boolean;
|
||||
flooded?: boolean;
|
||||
ultraviolet?: number;
|
||||
@@ -91,6 +92,7 @@ export declare class DeviceBase implements DeviceState {
|
||||
powerDetected?: boolean;
|
||||
audioDetected?: boolean;
|
||||
motionDetected?: boolean;
|
||||
ambientLight?: number;
|
||||
occupied?: boolean;
|
||||
flooded?: boolean;
|
||||
ultraviolet?: number;
|
||||
@@ -141,6 +143,7 @@ export declare enum ScryptedInterfaceProperty {
|
||||
powerDetected = "powerDetected",
|
||||
audioDetected = "audioDetected",
|
||||
motionDetected = "motionDetected",
|
||||
ambientLight = "ambientLight",
|
||||
occupied = "occupied",
|
||||
flooded = "flooded",
|
||||
ultraviolet = "ultraviolet",
|
||||
@@ -728,6 +731,12 @@ export interface AudioSensor {
|
||||
export interface MotionSensor {
|
||||
motionDetected?: boolean;
|
||||
}
|
||||
export interface AmbientLightSensor {
|
||||
/**
|
||||
* The ambient light in lux.
|
||||
*/
|
||||
ambientLight: number;
|
||||
}
|
||||
export interface OccupancySensor {
|
||||
occupied?: boolean;
|
||||
}
|
||||
@@ -1271,6 +1280,7 @@ export declare enum ScryptedInterface {
|
||||
PowerSensor = "PowerSensor",
|
||||
AudioSensor = "AudioSensor",
|
||||
MotionSensor = "MotionSensor",
|
||||
AmbientLightSensor = "AmbientLightSensor",
|
||||
OccupancySensor = "OccupancySensor",
|
||||
FloodSensor = "FloodSensor",
|
||||
UltravioletSensor = "UltravioletSensor",
|
||||
|
||||
@@ -47,6 +47,7 @@ var ScryptedInterfaceProperty;
|
||||
ScryptedInterfaceProperty["powerDetected"] = "powerDetected";
|
||||
ScryptedInterfaceProperty["audioDetected"] = "audioDetected";
|
||||
ScryptedInterfaceProperty["motionDetected"] = "motionDetected";
|
||||
ScryptedInterfaceProperty["ambientLight"] = "ambientLight";
|
||||
ScryptedInterfaceProperty["occupied"] = "occupied";
|
||||
ScryptedInterfaceProperty["flooded"] = "flooded";
|
||||
ScryptedInterfaceProperty["ultraviolet"] = "ultraviolet";
|
||||
@@ -404,6 +405,13 @@ exports.ScryptedInterfaceDescriptors = {
|
||||
'motionDetected'
|
||||
]
|
||||
},
|
||||
AmbientLightSensor: {
|
||||
name: 'AmbientLightSensor',
|
||||
methods: [],
|
||||
properties: [
|
||||
'ambientLight'
|
||||
]
|
||||
},
|
||||
OccupancySensor: {
|
||||
name: 'OccupancySensor',
|
||||
methods: [],
|
||||
@@ -650,6 +658,7 @@ var ScryptedInterface;
|
||||
ScryptedInterface["PowerSensor"] = "PowerSensor";
|
||||
ScryptedInterface["AudioSensor"] = "AudioSensor";
|
||||
ScryptedInterface["MotionSensor"] = "MotionSensor";
|
||||
ScryptedInterface["AmbientLightSensor"] = "AmbientLightSensor";
|
||||
ScryptedInterface["OccupancySensor"] = "OccupancySensor";
|
||||
ScryptedInterface["FloodSensor"] = "FloodSensor";
|
||||
ScryptedInterface["UltravioletSensor"] = "UltravioletSensor";
|
||||
|
||||
17
sdk/types.ts
17
sdk/types.ts
@@ -42,6 +42,7 @@ export interface DeviceState {
|
||||
powerDetected?: boolean
|
||||
audioDetected?: boolean
|
||||
motionDetected?: boolean
|
||||
ambientLight?: number
|
||||
occupied?: boolean
|
||||
flooded?: boolean
|
||||
ultraviolet?: number
|
||||
@@ -93,6 +94,7 @@ export class DeviceBase implements DeviceState {
|
||||
powerDetected?: boolean
|
||||
audioDetected?: boolean
|
||||
motionDetected?: boolean
|
||||
ambientLight?: number
|
||||
occupied?: boolean
|
||||
flooded?: boolean
|
||||
ultraviolet?: number
|
||||
@@ -145,6 +147,7 @@ export enum ScryptedInterfaceProperty {
|
||||
powerDetected = "powerDetected",
|
||||
audioDetected = "audioDetected",
|
||||
motionDetected = "motionDetected",
|
||||
ambientLight = "ambientLight",
|
||||
occupied = "occupied",
|
||||
flooded = "flooded",
|
||||
ultraviolet = "ultraviolet",
|
||||
@@ -505,6 +508,13 @@ export const ScryptedInterfaceDescriptors: { [scryptedInterface: string]: Scrypt
|
||||
'motionDetected'
|
||||
]
|
||||
},
|
||||
AmbientLightSensor: {
|
||||
name: 'AmbientLightSensor',
|
||||
methods: [],
|
||||
properties: [
|
||||
'ambientLight'
|
||||
]
|
||||
},
|
||||
OccupancySensor: {
|
||||
name: 'OccupancySensor',
|
||||
methods: [],
|
||||
@@ -1272,6 +1282,12 @@ export interface AudioSensor {
|
||||
export interface MotionSensor {
|
||||
motionDetected?: boolean;
|
||||
}
|
||||
export interface AmbientLightSensor {
|
||||
/**
|
||||
* The ambient light in lux.
|
||||
*/
|
||||
ambientLight: number;
|
||||
}
|
||||
export interface OccupancySensor {
|
||||
occupied?: boolean;
|
||||
}
|
||||
@@ -1869,6 +1885,7 @@ export enum ScryptedInterface {
|
||||
PowerSensor = "PowerSensor",
|
||||
AudioSensor = "AudioSensor",
|
||||
MotionSensor = "MotionSensor",
|
||||
AmbientLightSensor = "AmbientLightSensor",
|
||||
OccupancySensor = "OccupancySensor",
|
||||
FloodSensor = "FloodSensor",
|
||||
UltravioletSensor = "UltravioletSensor",
|
||||
|
||||
18
server/package-lock.json
generated
18
server/package-lock.json
generated
@@ -1,17 +1,17 @@
|
||||
{
|
||||
"name": "@scrypted/server",
|
||||
"version": "0.0.133",
|
||||
"version": "0.0.134",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@scrypted/server",
|
||||
"version": "0.0.133",
|
||||
"version": "0.0.134",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@mapbox/node-pre-gyp": "^1.0.5",
|
||||
"@scrypted/ffmpeg": "^1.0.9",
|
||||
"@scrypted/sdk": "^0.0.148",
|
||||
"@scrypted/sdk": "^0.0.151",
|
||||
"adm-zip": "^0.5.3",
|
||||
"axios": "^0.21.1",
|
||||
"body-parser": "^1.19.0",
|
||||
@@ -858,9 +858,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@scrypted/sdk": {
|
||||
"version": "0.0.148",
|
||||
"resolved": "https://registry.npmjs.org/@scrypted/sdk/-/sdk-0.0.148.tgz",
|
||||
"integrity": "sha512-yXa7C99D4yLBIx3A4Ed8yAsxK3JeZKJ4X/rmjsWRYQHqGufy1Nl1Yza3eTubsyzPQHWQdrS58CmEcLDfa1+Z9Q==",
|
||||
"version": "0.0.151",
|
||||
"resolved": "https://registry.npmjs.org/@scrypted/sdk/-/sdk-0.0.151.tgz",
|
||||
"integrity": "sha512-0xVuMvQcc76Df2T1BS7zpNpdFxwWJxX0XjMhBDxdArA+4kxr2oRXNUSY4g3sqIXG0Z5tLHJUSd3FZ1Mf1Uqm2g==",
|
||||
"dependencies": {
|
||||
"@babel/plugin-proposal-class-properties": "^7.14.5",
|
||||
"@babel/plugin-proposal-nullish-coalescing-operator": "^7.14.5",
|
||||
@@ -5891,9 +5891,9 @@
|
||||
}
|
||||
},
|
||||
"@scrypted/sdk": {
|
||||
"version": "0.0.148",
|
||||
"resolved": "https://registry.npmjs.org/@scrypted/sdk/-/sdk-0.0.148.tgz",
|
||||
"integrity": "sha512-yXa7C99D4yLBIx3A4Ed8yAsxK3JeZKJ4X/rmjsWRYQHqGufy1Nl1Yza3eTubsyzPQHWQdrS58CmEcLDfa1+Z9Q==",
|
||||
"version": "0.0.151",
|
||||
"resolved": "https://registry.npmjs.org/@scrypted/sdk/-/sdk-0.0.151.tgz",
|
||||
"integrity": "sha512-0xVuMvQcc76Df2T1BS7zpNpdFxwWJxX0XjMhBDxdArA+4kxr2oRXNUSY4g3sqIXG0Z5tLHJUSd3FZ1Mf1Uqm2g==",
|
||||
"requires": {
|
||||
"@babel/plugin-proposal-class-properties": "^7.14.5",
|
||||
"@babel/plugin-proposal-nullish-coalescing-operator": "^7.14.5",
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
{
|
||||
"name": "@scrypted/server",
|
||||
"version": "0.0.133",
|
||||
"version": "0.0.134",
|
||||
"description": "",
|
||||
"dependencies": {
|
||||
"@mapbox/node-pre-gyp": "^1.0.5",
|
||||
"@scrypted/ffmpeg": "^1.0.9",
|
||||
"@scrypted/sdk": "^0.0.148",
|
||||
"@scrypted/sdk": "^0.0.151",
|
||||
"adm-zip": "^0.5.3",
|
||||
"axios": "^0.21.1",
|
||||
"body-parser": "^1.19.0",
|
||||
|
||||
Reference in New Issue
Block a user