mirror of
https://github.com/koush/scrypted.git
synced 2026-02-07 07:52:12 +00:00
Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
adcdd18497 | ||
|
|
a95b77fe26 | ||
|
|
3ff75f0fde | ||
|
|
eecd38d271 | ||
|
|
7128af20af | ||
|
|
c651c2164b | ||
|
|
6caafd73f5 | ||
|
|
05cb505783 | ||
|
|
07baddc9c3 | ||
|
|
76ac260bf7 | ||
|
|
dfee7c6b09 | ||
|
|
b3ce6a2af3 | ||
|
|
933c0cac0f | ||
|
|
1fb1334a00 | ||
|
|
cb45a00c25 |
4
plugins/hikvision/package-lock.json
generated
4
plugins/hikvision/package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@scrypted/hikvision",
|
||||
"version": "0.0.161",
|
||||
"version": "0.0.162",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@scrypted/hikvision",
|
||||
"version": "0.0.161",
|
||||
"version": "0.0.162",
|
||||
"license": "Apache",
|
||||
"dependencies": {
|
||||
"@scrypted/common": "file:../../common",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@scrypted/hikvision",
|
||||
"version": "0.0.161",
|
||||
"version": "0.0.162",
|
||||
"description": "Hikvision Plugin for Scrypted",
|
||||
"author": "Scrypted",
|
||||
"license": "Apache",
|
||||
|
||||
@@ -161,14 +161,9 @@ export class HikvisionCamera extends RtspSmartCamera implements Camera, Intercom
|
||||
|
||||
const now = Date.now();
|
||||
let detections: ObjectDetectionResult[] = xml.EventNotificationAlert?.DetectionRegionList?.map(region => {
|
||||
const { DetectionRegionEntry } = region;
|
||||
const dre = DetectionRegionEntry[0];
|
||||
if (!DetectionRegionEntry)
|
||||
const name = region?.DetectionRegionEntry?.[0]?.detectionTarget?.name;
|
||||
if (!name)
|
||||
return;
|
||||
const { detectionTarget } = dre;
|
||||
// const { TargetRect } = dre;
|
||||
// const { X, Y, width, height } = TargetRect[0];
|
||||
const [name] = detectionTarget;
|
||||
return {
|
||||
score: 1,
|
||||
className: detectionMap[name] || name,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { sleep } from '@scrypted/common/src/sleep';
|
||||
import sdk, { Brightness, Camera, Device, DeviceCreatorSettings, DeviceInformation, DeviceProvider, Intercom, MediaObject, ObjectDetectionTypes, ObjectDetector, ObjectsDetected, OnOff, PanTiltZoom, PanTiltZoomCommand, Reboot, RequestPictureOptions, ScryptedDeviceBase, ScryptedDeviceType, ScryptedInterface, Setting } from "@scrypted/sdk";
|
||||
import sdk, { Sleep, Brightness, Camera, Device, DeviceCreatorSettings, DeviceInformation, DeviceProvider, Intercom, MediaObject, ObjectDetectionTypes, ObjectDetector, ObjectsDetected, OnOff, PanTiltZoom, PanTiltZoomCommand, Reboot, RequestPictureOptions, ScryptedDeviceBase, ScryptedDeviceType, ScryptedInterface, Setting } from "@scrypted/sdk";
|
||||
import { StorageSettings } from '@scrypted/sdk/storage-settings';
|
||||
import { EventEmitter } from "stream";
|
||||
import { createRtspMediaStreamOptions, Destroyable, RtspProvider, RtspSmartCamera, UrlMediaStreamOptions } from "../../rtsp/src/rtsp";
|
||||
@@ -78,7 +78,7 @@ class ReolinkCameraFloodlight extends ScryptedDeviceBase implements OnOff, Brigh
|
||||
}
|
||||
}
|
||||
|
||||
class ReolinkCamera extends RtspSmartCamera implements Camera, DeviceProvider, Reboot, Intercom, ObjectDetector, PanTiltZoom {
|
||||
class ReolinkCamera extends RtspSmartCamera implements Camera, DeviceProvider, Reboot, Intercom, ObjectDetector, PanTiltZoom, Sleep {
|
||||
client: ReolinkCameraClient;
|
||||
clientWithToken: ReolinkCameraClient;
|
||||
onvifClient: OnvifCameraAPI;
|
||||
@@ -362,7 +362,7 @@ class ReolinkCamera extends RtspSmartCamera implements Camera, DeviceProvider, R
|
||||
if (this.hasSiren() || this.hasFloodlight())
|
||||
interfaces.push(ScryptedInterface.DeviceProvider);
|
||||
if (this.hasBattery()) {
|
||||
interfaces.push(ScryptedInterface.Battery, ScryptedInterface.Online);
|
||||
interfaces.push(ScryptedInterface.Battery, ScryptedInterface.Sleep);
|
||||
this.startBatteryCheckInterval();
|
||||
}
|
||||
|
||||
@@ -378,14 +378,20 @@ class ReolinkCamera extends RtspSmartCamera implements Camera, DeviceProvider, R
|
||||
const api = this.getClientWithToken();
|
||||
|
||||
try {
|
||||
const { batteryPercent, sleep } = await api.getBatteryInfo();
|
||||
const { batteryPercent, sleeping } = await api.getBatteryInfo();
|
||||
this.batteryLevel = batteryPercent;
|
||||
this.online = !sleep;
|
||||
|
||||
if (sleeping !== this.sleeping) {
|
||||
this.sleeping = sleeping;
|
||||
}
|
||||
if (batteryPercent !== this.batteryLevel) {
|
||||
this.batteryLevel = batteryPercent;
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
this.console.log('Error in getting battery info', e);
|
||||
}
|
||||
}, 1000 * 60 * 30);
|
||||
}, 1000 * 10);
|
||||
}
|
||||
|
||||
async reboot() {
|
||||
@@ -557,10 +563,19 @@ class ReolinkCamera extends RtspSmartCamera implements Camera, DeviceProvider, R
|
||||
(async () => {
|
||||
while (!killed) {
|
||||
try {
|
||||
const { value, data } = await client.getMotionState();
|
||||
if (value)
|
||||
triggerMotion();
|
||||
ret.emit('data', JSON.stringify(data));
|
||||
// Battey cameras do not have AI state, they just send events in case of PIR sensor triggered
|
||||
// which equals a motion detected
|
||||
if (this.hasBattery()) {
|
||||
const { value, data } = await client.getPidActive();
|
||||
if (value)
|
||||
triggerMotion();
|
||||
ret.emit('data', JSON.stringify(data));
|
||||
} else {
|
||||
const { value, data } = await client.getMotionState();
|
||||
if (value)
|
||||
triggerMotion();
|
||||
ret.emit('data', JSON.stringify(data));
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
ret.emit('error', e);
|
||||
|
||||
@@ -492,7 +492,35 @@ export class ReolinkCameraClient {
|
||||
|
||||
return {
|
||||
batteryPercent: batteryInfoEntry?.batteryPercent,
|
||||
sleep: channelStatusEntry?.sleep === 1,
|
||||
sleeping: channelStatusEntry?.sleep === 1,
|
||||
}
|
||||
}
|
||||
|
||||
async getPidActive() {
|
||||
const url = new URL(`http://${this.host}/api.cgi`);
|
||||
|
||||
const body = [
|
||||
{
|
||||
cmd: "GetEvents",
|
||||
action: 0,
|
||||
param: { channel: this.channelId }
|
||||
},
|
||||
];
|
||||
|
||||
const response = await this.requestWithLogin({
|
||||
url,
|
||||
responseType: 'json',
|
||||
method: 'POST',
|
||||
}, this.createReadable(body));
|
||||
|
||||
const error = response.body?.find(elem => elem.error)?.error;
|
||||
if (error) {
|
||||
this.console.error('error during call to getEvents', error);
|
||||
}
|
||||
|
||||
return {
|
||||
value: !!response.body?.[0]?.value?.ai?.other?.alarm_state,
|
||||
data: response.body,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ import { AutoenableMixinProvider } from "@scrypted/common/src/autoenable-mixin-p
|
||||
import { AuthFetchCredentialState, authHttpFetch } from '@scrypted/common/src/http-auth-fetch';
|
||||
import { RefreshPromise, TimeoutError, createMapPromiseDebouncer, singletonPromise, timeoutPromise } from "@scrypted/common/src/promise-utils";
|
||||
import { SettingsMixinDeviceBase, SettingsMixinDeviceOptions } from "@scrypted/common/src/settings-mixin";
|
||||
import sdk, { BufferConverter, Camera, DeviceManifest, DeviceProvider, FFmpegInput, HttpRequest, HttpRequestHandler, HttpResponse, MediaObject, MediaObjectOptions, MixinProvider, Online, RequestMediaStreamOptions, RequestPictureOptions, ResponsePictureOptions, ScryptedDevice, ScryptedDeviceType, ScryptedInterface, ScryptedMimeTypes, Setting, SettingValue, Settings, VideoCamera, WritableDeviceState } from "@scrypted/sdk";
|
||||
import sdk, { BufferConverter, Camera, DeviceManifest, DeviceProvider, FFmpegInput, HttpRequest, HttpRequestHandler, HttpResponse, MediaObject, MediaObjectOptions, MixinProvider, RequestMediaStreamOptions, RequestPictureOptions, ResponsePictureOptions, ScryptedDevice, ScryptedDeviceType, ScryptedInterface, ScryptedMimeTypes, Setting, SettingValue, Settings, Sleep, VideoCamera, WritableDeviceState } from "@scrypted/sdk";
|
||||
import { StorageSettings } from "@scrypted/sdk/storage-settings";
|
||||
import https from 'https';
|
||||
import os from 'os';
|
||||
@@ -161,7 +161,7 @@ class SnapshotMixin extends SettingsMixinDeviceBase<Camera> implements Camera {
|
||||
}
|
||||
}
|
||||
|
||||
const realDevice = systemManager.getDeviceById<VideoCamera & Online>(this.id);
|
||||
const realDevice = systemManager.getDeviceById<VideoCamera & Sleep>(this.id);
|
||||
|
||||
let takePrebufferPicture: () => Promise<Buffer>;
|
||||
const preparePrebufferSnapshot = async () => {
|
||||
@@ -263,7 +263,7 @@ class SnapshotMixin extends SettingsMixinDeviceBase<Camera> implements Camera {
|
||||
}
|
||||
try {
|
||||
// consider waking the camera if
|
||||
if (!eventSnapshot && this.mixinDeviceInterfaces.includes(ScryptedInterface.Battery) && !realDevice.online)
|
||||
if (!eventSnapshot && this.mixinDeviceInterfaces.includes(ScryptedInterface.Sleep) && realDevice.sleeping)
|
||||
throw new Error('Not waking sleeping camera for periodic snapshot.');
|
||||
return await this.mixinDevice.takePicture(takePictureOptions).then(mo => mediaManager.convertMediaObjectToBuffer(mo, 'image/jpeg'))
|
||||
}
|
||||
|
||||
4
sdk/package-lock.json
generated
4
sdk/package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@scrypted/sdk",
|
||||
"version": "0.3.110",
|
||||
"version": "0.3.112",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@scrypted/sdk",
|
||||
"version": "0.3.110",
|
||||
"version": "0.3.112",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@babel/preset-typescript": "^7.26.0",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@scrypted/sdk",
|
||||
"version": "0.3.110",
|
||||
"version": "0.3.112",
|
||||
"description": "",
|
||||
"main": "dist/src/index.js",
|
||||
"exports": {
|
||||
|
||||
4
sdk/types/package-lock.json
generated
4
sdk/types/package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@scrypted/types",
|
||||
"version": "0.3.102",
|
||||
"version": "0.3.104",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@scrypted/types",
|
||||
"version": "0.3.102",
|
||||
"version": "0.3.104",
|
||||
"license": "ISC"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@scrypted/types",
|
||||
"version": "0.3.102",
|
||||
"version": "0.3.104",
|
||||
"description": "",
|
||||
"main": "dist/index.js",
|
||||
"author": "",
|
||||
|
||||
@@ -321,8 +321,8 @@ class ObjectDetectionResult(TypedDict):
|
||||
boundingBox: tuple[float, float, float, float] # x, y, width, height
|
||||
className: str # The detection class of the object.
|
||||
clipPaths: list[ClipPath] # The detection clip paths that outlines various features or segments, like traced facial features.
|
||||
clipped: bool # Flag that indicates whether the detection was clipped by the detection input and may not be a full bounding box.
|
||||
cost: float # The certainty that this is correct tracked object.
|
||||
descriptor: str # A base64 encoded Float32Array that represents the vector descriptor of the detection. Can be used to compute euclidian distance to determine similarity.
|
||||
embedding: str # Base64 encoded embedding float32 vector.
|
||||
history: ObjectDetectionHistory
|
||||
id: str # The id of the tracked object.
|
||||
@@ -467,6 +467,7 @@ class ClusterForkInterfaceOptions(TypedDict):
|
||||
|
||||
class ClusterWorker(TypedDict):
|
||||
|
||||
address: str
|
||||
forks: list[ClusterFork]
|
||||
id: str
|
||||
labels: list[str]
|
||||
@@ -956,7 +957,7 @@ class TamperState(TypedDict):
|
||||
pass
|
||||
|
||||
|
||||
TYPES_VERSION = "0.3.102"
|
||||
TYPES_VERSION = "0.3.104"
|
||||
|
||||
|
||||
class AirPurifier:
|
||||
|
||||
@@ -1558,6 +1558,10 @@ export interface ObjectDetectionResult extends BoundingBoxResult {
|
||||
* The certainty that this is correct tracked object.
|
||||
*/
|
||||
cost?: number;
|
||||
/**
|
||||
* Flag that indicates whether the detection was clipped by the detection input and may not be a full bounding box.
|
||||
*/
|
||||
clipped?: boolean;
|
||||
/**
|
||||
* The detection class of the object.
|
||||
*/
|
||||
@@ -1574,11 +1578,6 @@ export interface ObjectDetectionResult extends BoundingBoxResult {
|
||||
* The score of the label.
|
||||
*/
|
||||
labelScore?: number;
|
||||
/**
|
||||
* A base64 encoded Float32Array that represents the vector descriptor of the detection.
|
||||
* Can be used to compute euclidian distance to determine similarity.
|
||||
*/
|
||||
descriptor?: string;
|
||||
/**
|
||||
* The detection landmarks, like key points in a face landmarks.
|
||||
*/
|
||||
@@ -2714,6 +2713,7 @@ export interface ClusterWorker {
|
||||
labels: string[];
|
||||
forks: ClusterFork[];
|
||||
mode: 'server' | 'client';
|
||||
address: string;
|
||||
}
|
||||
|
||||
export interface ClusterManager {
|
||||
|
||||
12
server/package-lock.json
generated
12
server/package-lock.json
generated
@@ -1,18 +1,18 @@
|
||||
{
|
||||
"name": "@scrypted/server",
|
||||
"version": "0.129.0",
|
||||
"version": "0.134.1",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@scrypted/server",
|
||||
"version": "0.129.0",
|
||||
"version": "0.134.1",
|
||||
"hasInstallScript": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@scrypted/ffmpeg-static": "^6.1.0-build3",
|
||||
"@scrypted/node-pty": "^1.0.22",
|
||||
"@scrypted/types": "^0.3.100",
|
||||
"@scrypted/types": "^0.3.104",
|
||||
"adm-zip": "^0.5.16",
|
||||
"body-parser": "^1.20.3",
|
||||
"cookie-parser": "^1.4.7",
|
||||
@@ -557,9 +557,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@scrypted/types": {
|
||||
"version": "0.3.100",
|
||||
"resolved": "https://registry.npmjs.org/@scrypted/types/-/types-0.3.100.tgz",
|
||||
"integrity": "sha512-s/07QCxjMWqODgWj2UpLehzeo2cGFrCA9X8mvpG3owT/+q+sb8v/UUcw9TLHGSN6yIriNhceg3i9WO07kEIT6A==",
|
||||
"version": "0.3.104",
|
||||
"resolved": "https://registry.npmjs.org/@scrypted/types/-/types-0.3.104.tgz",
|
||||
"integrity": "sha512-aFqB9mDmKoKLGF6O3+N71V+fPeMkIO2xC+2/oUF/xOvhG0D9fmQwTaV2gJtwVZJwx/ZgWGU85dIWqmxP8YfcDg==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/@types/adm-zip": {
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
{
|
||||
"name": "@scrypted/server",
|
||||
"version": "0.130.3",
|
||||
"version": "0.135.0",
|
||||
"description": "",
|
||||
"dependencies": {
|
||||
"@scrypted/ffmpeg-static": "^6.1.0-build3",
|
||||
"@scrypted/node-pty": "^1.0.22",
|
||||
"@scrypted/types": "^0.3.100",
|
||||
"@scrypted/types": "^0.3.104",
|
||||
"adm-zip": "^0.5.16",
|
||||
"body-parser": "^1.20.3",
|
||||
"cookie-parser": "^1.4.7",
|
||||
|
||||
@@ -12,6 +12,7 @@ import { computeClusterObjectHash } from './cluster/cluster-hash';
|
||||
import { getClusterLabels, getClusterWorkerWeight } from './cluster/cluster-labels';
|
||||
import { getScryptedClusterMode, InitializeCluster, setupCluster } from './cluster/cluster-setup';
|
||||
import type { ClusterObject } from './cluster/connect-rpc-object';
|
||||
import { getScryptedFFmpegPath } from './plugin/ffmpeg-path';
|
||||
import { getPluginVolume, getScryptedVolume } from './plugin/plugin-volume';
|
||||
import { prepareZip } from './plugin/runtime/node-worker-common';
|
||||
import { getBuiltinRuntimeHosts } from './plugin/runtime/runtime-host';
|
||||
@@ -23,15 +24,20 @@ import { EnvControl } from './services/env';
|
||||
import { Info } from './services/info';
|
||||
import { ServiceControl } from './services/service-control';
|
||||
import { sleep } from './sleep';
|
||||
import { getScryptedFFmpegPath } from './plugin/ffmpeg-path';
|
||||
|
||||
installSourceMapSupport({
|
||||
environment: 'node',
|
||||
});
|
||||
|
||||
async function start(mainFilename: string, serviceControl?: ServiceControl) {
|
||||
serviceControl ||= new ServiceControl();
|
||||
startClusterClient(mainFilename, serviceControl);
|
||||
async function start(mainFilename: string, options?: {
|
||||
onClusterWorkerCreated?: (options?: {
|
||||
clusterPluginHosts?: ReturnType<typeof getBuiltinRuntimeHosts>,
|
||||
}) => Promise<void>,
|
||||
serviceControl?: ServiceControl;
|
||||
}) {
|
||||
options ||= {};
|
||||
options.serviceControl ||= new ServiceControl();
|
||||
startClusterClient(mainFilename, options);
|
||||
}
|
||||
|
||||
export default start;
|
||||
@@ -122,12 +128,11 @@ export interface ClusterForkResultInterface {
|
||||
|
||||
export type ClusterForkParam = (runtime: string, options: RuntimeWorkerOptions, peerLiveness: PeerLiveness, getZip: () => Promise<Buffer>) => Promise<ClusterForkResultInterface>;
|
||||
|
||||
function createClusterForkParam(mainFilename: string, clusterId: string, clusterSecret: string, clusterWorkerId: string) {
|
||||
function createClusterForkParam(mainFilename: string, clusterId: string, clusterSecret: string, clusterWorkerId: string, clusterPluginHosts: ReturnType<typeof getBuiltinRuntimeHosts>) {
|
||||
const clusterForkParam: ClusterForkParam = async (runtime, runtimeWorkerOptions, peerLiveness, getZip) => {
|
||||
let runtimeWorker: RuntimeWorker;
|
||||
|
||||
const builtins = getBuiltinRuntimeHosts();
|
||||
const rt = builtins.get(runtime);
|
||||
const rt = clusterPluginHosts.get(runtime);
|
||||
if (!rt)
|
||||
throw new Error('unknown runtime ' + runtime);
|
||||
|
||||
@@ -205,7 +210,12 @@ function createClusterForkParam(mainFilename: string, clusterId: string, cluster
|
||||
return clusterForkParam;
|
||||
}
|
||||
|
||||
export function startClusterClient(mainFilename: string, serviceControl?: ServiceControl) {
|
||||
export function startClusterClient(mainFilename: string, options?: {
|
||||
onClusterWorkerCreated?: (options?: {
|
||||
clusterPluginHosts?: ReturnType<typeof getBuiltinRuntimeHosts>,
|
||||
}) => Promise<void>,
|
||||
serviceControl?: ServiceControl;
|
||||
}) {
|
||||
console.log('Cluster client starting.');
|
||||
|
||||
const envControl = new EnvControl();
|
||||
@@ -217,6 +227,10 @@ export function startClusterClient(mainFilename: string, serviceControl?: Servic
|
||||
const clusterSecret = process.env.SCRYPTED_CLUSTER_SECRET;
|
||||
const clusterMode = getScryptedClusterMode();
|
||||
const [, host, port] = clusterMode;
|
||||
|
||||
const clusterPluginHosts = getBuiltinRuntimeHosts();
|
||||
options?.onClusterWorkerCreated?.({ clusterPluginHosts });
|
||||
|
||||
(async () => {
|
||||
while (true) {
|
||||
// this sleep is here to prevent a tight loop if the server is down.
|
||||
@@ -259,7 +273,7 @@ export function startClusterClient(mainFilename: string, serviceControl?: Servic
|
||||
process.env.SCRYPTED_CLUSTER_ADDRESS = socket.localAddress;
|
||||
|
||||
const peer = preparePeer(socket, 'client');
|
||||
peer.params['service-control'] = serviceControl;
|
||||
peer.params['service-control'] = options?.serviceControl;
|
||||
peer.params['env-control'] = envControl;
|
||||
peer.params['info'] = new Info();
|
||||
peer.params['fs.promises'] = {
|
||||
@@ -294,7 +308,7 @@ export function startClusterClient(mainFilename: string, serviceControl?: Servic
|
||||
const clusterPeerSetup = setupCluster(peer);
|
||||
await clusterPeerSetup.initializeCluster({ clusterId, clusterSecret, clusterWorkerId });
|
||||
|
||||
peer.params['fork'] = createClusterForkParam(mainFilename, clusterId, clusterSecret, clusterWorkerId);
|
||||
peer.params['fork'] = createClusterForkParam(mainFilename, clusterId, clusterSecret, clusterWorkerId, clusterPluginHosts);
|
||||
|
||||
await peer.killed;
|
||||
}
|
||||
@@ -316,7 +330,7 @@ export function createClusterServer(mainFilename: string, scryptedRuntime: Scryp
|
||||
labels: getClusterLabels(),
|
||||
id: scryptedRuntime.serverClusterWorkerId,
|
||||
peer: undefined,
|
||||
fork: Promise.resolve(createClusterForkParam(mainFilename, scryptedRuntime.clusterId, scryptedRuntime.clusterSecret, scryptedRuntime.serverClusterWorkerId)),
|
||||
fork: Promise.resolve(createClusterForkParam(mainFilename, scryptedRuntime.clusterId, scryptedRuntime.clusterSecret, scryptedRuntime.serverClusterWorkerId, scryptedRuntime.pluginHosts)),
|
||||
name: process.env.SCRYPTED_CLUSTER_WORKER_NAME || os.hostname(),
|
||||
address: process.env.SCRYPTED_CLUSTER_ADDRESS,
|
||||
weight: getClusterWorkerWeight(),
|
||||
|
||||
@@ -8,6 +8,7 @@ import vm from 'vm';
|
||||
import { getScryptedClusterMode } from './cluster/cluster-setup';
|
||||
import { PluginError } from './plugin/plugin-error';
|
||||
import { isNodePluginWorkerProcess } from './plugin/runtime/node-fork-worker';
|
||||
import type { getBuiltinRuntimeHosts } from './plugin/runtime/runtime-host';
|
||||
import { RPCResultError, startPeriodicGarbageCollection } from './rpc';
|
||||
import type { Runtime } from './scrypted-server-main';
|
||||
import { getDotEnvPath } from './services/env';
|
||||
@@ -16,6 +17,9 @@ import type { ServiceControl } from './services/service-control';
|
||||
function start(mainFilename: string, options?: {
|
||||
serviceControl?: ServiceControl,
|
||||
onRuntimeCreated?: (runtime: Runtime) => Promise<void>,
|
||||
onClusterWorkerCreated?: (options?: {
|
||||
clusterPluginHosts?: ReturnType<typeof getBuiltinRuntimeHosts>,
|
||||
}) => Promise<void>,
|
||||
}) {
|
||||
// Allow including a custom file path for platforms that require
|
||||
// compatibility hacks. For example, Android may need to patch
|
||||
@@ -71,7 +75,7 @@ function start(mainFilename: string, options?: {
|
||||
const clusterMode = getScryptedClusterMode();
|
||||
if (clusterMode?.[0] === 'client') {
|
||||
const start = require('./scrypted-cluster-main').default;
|
||||
return start(mainFilename, options?.serviceControl);
|
||||
return start(mainFilename, options);
|
||||
}
|
||||
else {
|
||||
const start = require('./scrypted-server-main').default;
|
||||
|
||||
@@ -109,6 +109,7 @@ export class ClusterForkService {
|
||||
labels: worker.labels,
|
||||
forks: [...worker.forks] as ClusterFork[],
|
||||
mode: worker.mode,
|
||||
address: worker.address,
|
||||
};
|
||||
}
|
||||
return ret;
|
||||
|
||||
Reference in New Issue
Block a user