@7365admin1/core 3.85.0 → 3.86.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +25 -0
- package/dist/index.d.ts +166 -87
- package/dist/index.js +478 -168
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +468 -165
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
- package/test/demo-adapter.test.mjs +164 -0
- package/test/robot-adapter.test.mjs +83 -32
package/dist/index.js
CHANGED
|
@@ -79,6 +79,8 @@ __export(src_exports, {
|
|
|
79
79
|
DEFAULT_RING_SECONDS: () => DEFAULT_RING_SECONDS,
|
|
80
80
|
DEFAULT_SCALE_M_PER_PX: () => DEFAULT_SCALE_M_PER_PX,
|
|
81
81
|
DEFAULT_SITE_TIMEZONE: () => DEFAULT_SITE_TIMEZONE,
|
|
82
|
+
DEMO_BRAND: () => DEMO_BRAND,
|
|
83
|
+
DEMO_CAPABILITIES: () => DEMO_CAPABILITIES,
|
|
82
84
|
DEVICE_STATUS: () => DEVICE_STATUS,
|
|
83
85
|
DOBStatus: () => DOBStatus,
|
|
84
86
|
DUPLICATE_TERMS_VERSION_MESSAGE: () => DUPLICATE_TERMS_VERSION_MESSAGE,
|
|
@@ -300,6 +302,7 @@ __export(src_exports, {
|
|
|
300
302
|
VisitorStatus: () => VisitorStatus,
|
|
301
303
|
WALL_HEIGHT_M: () => WALL_HEIGHT_M,
|
|
302
304
|
WALL_THICKNESS_M: () => WALL_THICKNESS_M,
|
|
305
|
+
adapterForRobot: () => adapterForRobot,
|
|
303
306
|
addressSchema: () => addressSchema,
|
|
304
307
|
allowedFieldsSite: () => allowedFieldsSite,
|
|
305
308
|
allowedNatures: () => allowedNatures,
|
|
@@ -339,13 +342,14 @@ __export(src_exports, {
|
|
|
339
342
|
chatSchema: () => chatSchema,
|
|
340
343
|
claimReadsAsStale: () => claimReadsAsStale,
|
|
341
344
|
clampPtzSpeed: () => clampPtzSpeed,
|
|
342
|
-
|
|
345
|
+
clearRobotBrands: () => clearRobotBrands,
|
|
343
346
|
clockDriftSeconds: () => clockDriftSeconds,
|
|
344
347
|
commandSupported: () => commandSupported,
|
|
345
348
|
consoleRoleAllows: () => consoleRoleAllows,
|
|
346
349
|
consoleRoleAllowsAll: () => consoleRoleAllowsAll,
|
|
347
350
|
consoleSpellings: () => consoleSpellings,
|
|
348
351
|
console_audit_namespace_collection: () => console_audit_namespace_collection,
|
|
352
|
+
createDemoAdapter: () => createDemoAdapter,
|
|
349
353
|
createLiftSimulator: () => createLiftSimulator,
|
|
350
354
|
createManpowerRemarksDaily: () => createManpowerRemarksDaily,
|
|
351
355
|
createOunitechAdapter: () => createOunitechAdapter,
|
|
@@ -369,6 +373,7 @@ __export(src_exports, {
|
|
|
369
373
|
disconnectedState: () => disconnectedState,
|
|
370
374
|
emitNotificationCreated: () => emitNotificationCreated,
|
|
371
375
|
emptyPersonalEmergencyChain: () => emptyPersonalEmergencyChain,
|
|
376
|
+
encodeGreyscalePng: () => encodeGreyscalePng,
|
|
372
377
|
encodeHidPacsCard: () => encodeHidPacsCard,
|
|
373
378
|
entitledSiteScope: () => entitledSiteScope,
|
|
374
379
|
events_namespace_collection: () => events_namespace_collection,
|
|
@@ -387,6 +392,7 @@ __export(src_exports, {
|
|
|
387
392
|
getIO: () => getIO,
|
|
388
393
|
getSessionIdFromRequest: () => getSessionIdFromRequest,
|
|
389
394
|
grabWithSubStreamFallback: () => grabWithSubStreamFallback,
|
|
395
|
+
greyscalePngDataUri: () => greyscalePngDataUri,
|
|
390
396
|
guests_namespace_collection: () => guests_namespace_collection,
|
|
391
397
|
hasAnyCapability: () => hasAnyCapability,
|
|
392
398
|
hasAnyPermission: () => hasAnyPermission,
|
|
@@ -488,8 +494,9 @@ __export(src_exports, {
|
|
|
488
494
|
recordConsoleAction: () => recordConsoleAction,
|
|
489
495
|
refuseServiceProviderInviteAction: () => refuseServiceProviderInviteAction,
|
|
490
496
|
registerCameraTransport: () => registerCameraTransport,
|
|
497
|
+
registerDemoBrand: () => registerDemoBrand,
|
|
491
498
|
registerOunitechBrand: () => registerOunitechBrand,
|
|
492
|
-
|
|
499
|
+
registerRobotBrand: () => registerRobotBrand,
|
|
493
500
|
registeredRobotBrands: () => registeredRobotBrands,
|
|
494
501
|
relayForRecorder: () => relayForRecorder,
|
|
495
502
|
remarksSchema: () => remarksSchema,
|
|
@@ -508,7 +515,7 @@ __export(src_exports, {
|
|
|
508
515
|
resolveSiteTimezone: () => resolveSiteTimezone,
|
|
509
516
|
resolveStaffRole: () => resolveStaffRole,
|
|
510
517
|
robotActionsFor: () => robotActionsFor,
|
|
511
|
-
|
|
518
|
+
robotBrandFor: () => robotBrandFor,
|
|
512
519
|
robotCloudBody: () => robotCloudBody,
|
|
513
520
|
robotCloudSign: () => robotCloudSign,
|
|
514
521
|
robotCloudSigningString: () => robotCloudSigningString,
|
|
@@ -20390,8 +20397,8 @@ function useDahuaService() {
|
|
|
20390
20397
|
}
|
|
20391
20398
|
}
|
|
20392
20399
|
}
|
|
20393
|
-
async function handleBuffer(
|
|
20394
|
-
partialBuffer = Buffer.concat([partialBuffer,
|
|
20400
|
+
async function handleBuffer(chunk2, onDetected2) {
|
|
20401
|
+
partialBuffer = Buffer.concat([partialBuffer, chunk2]);
|
|
20395
20402
|
while (true) {
|
|
20396
20403
|
const boundaryIndex = partialBuffer.indexOf(Buffer.from(boundary));
|
|
20397
20404
|
if (boundaryIndex === -1)
|
|
@@ -20642,12 +20649,12 @@ function useDahuaService() {
|
|
|
20642
20649
|
resolve("aborted");
|
|
20643
20650
|
};
|
|
20644
20651
|
signal.addEventListener("abort", onAbort, { once: true });
|
|
20645
|
-
response.res.on("data", (
|
|
20652
|
+
response.res.on("data", (chunk2) => {
|
|
20646
20653
|
if (signal.aborted) {
|
|
20647
20654
|
response.res.destroy();
|
|
20648
20655
|
return;
|
|
20649
20656
|
}
|
|
20650
|
-
bufferQueue.enqueue(
|
|
20657
|
+
bufferQueue.enqueue(chunk2);
|
|
20651
20658
|
});
|
|
20652
20659
|
response.res.on("end", () => {
|
|
20653
20660
|
signal.removeEventListener("abort", onAbort);
|
|
@@ -23251,10 +23258,10 @@ function buildAdapter(params) {
|
|
|
23251
23258
|
return;
|
|
23252
23259
|
let buffered = "";
|
|
23253
23260
|
const decoder = new TextDecoder();
|
|
23254
|
-
for await (const
|
|
23261
|
+
for await (const chunk2 of body) {
|
|
23255
23262
|
if (params2.signal.aborted)
|
|
23256
23263
|
return;
|
|
23257
|
-
buffered += decoder.decode(
|
|
23264
|
+
buffered += decoder.decode(chunk2, { stream: true });
|
|
23258
23265
|
let at2 = buffered.indexOf(marker);
|
|
23259
23266
|
while (at2 >= 0) {
|
|
23260
23267
|
const next = buffered.indexOf(marker, at2 + marker.length);
|
|
@@ -23566,16 +23573,16 @@ function useCameraViewService() {
|
|
|
23566
23573
|
() => finish(new Error("camera-timeout")),
|
|
23567
23574
|
CAMERA_RTSP_TIMEOUT_MS
|
|
23568
23575
|
);
|
|
23569
|
-
child.stdout.on("data", (
|
|
23570
|
-
bytes +=
|
|
23576
|
+
child.stdout.on("data", (chunk2) => {
|
|
23577
|
+
bytes += chunk2.length;
|
|
23571
23578
|
if (bytes > CAMERA_SNAPSHOT_MAX_BYTES) {
|
|
23572
23579
|
finish(new Error("camera-picture-too-large"));
|
|
23573
23580
|
return;
|
|
23574
23581
|
}
|
|
23575
|
-
chunks.push(
|
|
23582
|
+
chunks.push(chunk2);
|
|
23576
23583
|
});
|
|
23577
|
-
child.stderr?.on("data", (
|
|
23578
|
-
const text2 = carry +
|
|
23584
|
+
child.stderr?.on("data", (chunk2) => {
|
|
23585
|
+
const text2 = carry + chunk2.toString("latin1");
|
|
23579
23586
|
if (/401\s*unauthorized|\bunauthorized\b/i.test(text2))
|
|
23580
23587
|
rejected = true;
|
|
23581
23588
|
carry = text2.slice(-32);
|
|
@@ -32871,8 +32878,8 @@ function useOccurrenceBookRepo() {
|
|
|
32871
32878
|
const chunkSize = 500;
|
|
32872
32879
|
let totalInserted = 0;
|
|
32873
32880
|
for (let i = 0; i < payloads.length; i += chunkSize) {
|
|
32874
|
-
const
|
|
32875
|
-
const operations =
|
|
32881
|
+
const chunk2 = payloads.slice(i, i + chunkSize);
|
|
32882
|
+
const operations = chunk2.map((item) => ({
|
|
32876
32883
|
insertOne: {
|
|
32877
32884
|
document: {
|
|
32878
32885
|
...item,
|
|
@@ -52167,9 +52174,9 @@ function useVisitorTransactionService() {
|
|
|
52167
52174
|
expectedCheckIn
|
|
52168
52175
|
} = value;
|
|
52169
52176
|
for (let i = 0; i < value.members.length; i += chunkSize) {
|
|
52170
|
-
const
|
|
52177
|
+
const chunk2 = value.members.slice(i, i + chunkSize);
|
|
52171
52178
|
await Promise.all(
|
|
52172
|
-
|
|
52179
|
+
chunk2.map(async (member) => {
|
|
52173
52180
|
const clonedMember = structuredClone(member);
|
|
52174
52181
|
const { visitorPass, passKeys, nric: nric2, name: name2, contact: contact2 } = clonedMember;
|
|
52175
52182
|
if (/^(guest|walk-in|contractor|delivery)$/.test(type2 ?? "invalid") && site2) {
|
|
@@ -52411,9 +52418,9 @@ function useVisitorTransactionService() {
|
|
|
52411
52418
|
unitName
|
|
52412
52419
|
} = value;
|
|
52413
52420
|
for (let i = 0; i < value.members.length; i += chunkSize) {
|
|
52414
|
-
const
|
|
52421
|
+
const chunk2 = value.members.slice(i, i + chunkSize);
|
|
52415
52422
|
await Promise.all(
|
|
52416
|
-
|
|
52423
|
+
chunk2.map(async (member) => {
|
|
52417
52424
|
const clonedMember = structuredClone(member);
|
|
52418
52425
|
const { visitorPass, passKeys, nric: nric2, name: name2, contact: contact2 } = clonedMember;
|
|
52419
52426
|
if (/^(guest|walk-in|contractor|delivery)$/.test(type2 ?? "invalid") && site2) {
|
|
@@ -56870,8 +56877,8 @@ function useAccessManagementSvc() {
|
|
|
56870
56877
|
return new Promise((resolve, reject) => {
|
|
56871
56878
|
const fileStream = import_stream.Readable.from(bufferFile);
|
|
56872
56879
|
let fileBuffer = Buffer.alloc(0);
|
|
56873
|
-
fileStream.on("data", (
|
|
56874
|
-
fileBuffer = Buffer.concat([fileBuffer,
|
|
56880
|
+
fileStream.on("data", (chunk2) => {
|
|
56881
|
+
fileBuffer = Buffer.concat([fileBuffer, chunk2]);
|
|
56875
56882
|
});
|
|
56876
56883
|
fileStream.on("end", () => {
|
|
56877
56884
|
try {
|
|
@@ -59710,10 +59717,10 @@ function parseRobotCommand(body) {
|
|
|
59710
59717
|
function createSseParser() {
|
|
59711
59718
|
let buffer = "";
|
|
59712
59719
|
let dataLines = [];
|
|
59713
|
-
function push(
|
|
59714
|
-
if (!
|
|
59720
|
+
function push(chunk2) {
|
|
59721
|
+
if (!chunk2)
|
|
59715
59722
|
return { events: [], sawActivity: false };
|
|
59716
|
-
buffer +=
|
|
59723
|
+
buffer += chunk2;
|
|
59717
59724
|
const events = [];
|
|
59718
59725
|
buffer = buffer.replace(/\r\n|\r/g, "\n");
|
|
59719
59726
|
const lines = buffer.split("\n");
|
|
@@ -59979,26 +59986,44 @@ function commandSupported(capabilities, kind) {
|
|
|
59979
59986
|
return false;
|
|
59980
59987
|
return supports(capabilities, needed);
|
|
59981
59988
|
}
|
|
59982
|
-
var
|
|
59983
|
-
function
|
|
59984
|
-
if (!
|
|
59985
|
-
throw new Error("A robot
|
|
59986
|
-
|
|
59989
|
+
var brands = /* @__PURE__ */ new Map();
|
|
59990
|
+
function registerRobotBrand(brand) {
|
|
59991
|
+
if (!brand?.brand)
|
|
59992
|
+
throw new Error("A robot brand must name itself.");
|
|
59993
|
+
if (typeof brand.create !== "function") {
|
|
59994
|
+
throw new Error(`Robot brand "${brand.brand}" has no way to build an adapter.`);
|
|
59995
|
+
}
|
|
59996
|
+
brands.set(brand.brand, brand);
|
|
59987
59997
|
}
|
|
59988
|
-
function
|
|
59998
|
+
function robotBrandFor(brand) {
|
|
59989
59999
|
if (typeof brand !== "string" || !brand)
|
|
59990
60000
|
return null;
|
|
59991
|
-
return
|
|
60001
|
+
return brands.get(brand) ?? null;
|
|
60002
|
+
}
|
|
60003
|
+
function adapterForRobot(robot) {
|
|
60004
|
+
const brandName = (robot?.brand ?? "").trim();
|
|
60005
|
+
const brand = robotBrandFor(brandName);
|
|
60006
|
+
if (!brand) {
|
|
60007
|
+
throw new Error(
|
|
60008
|
+
brandName ? `No robot adapter is registered for the brand "${brandName}".` : `Robot "${robot?.name ?? "unknown"}" does not say which brand it is.`
|
|
60009
|
+
);
|
|
60010
|
+
}
|
|
60011
|
+
const appid = (robot.appKey ?? "").trim();
|
|
60012
|
+
const secret = (robot.appToken ?? "").trim();
|
|
60013
|
+
if (!appid || !secret) {
|
|
60014
|
+
throw new Error(`Robot "${robot?.name ?? brandName}" has no cloud credentials saved.`);
|
|
60015
|
+
}
|
|
60016
|
+
return brand.create({ appid, secret });
|
|
59992
60017
|
}
|
|
59993
60018
|
function registeredRobotBrands() {
|
|
59994
|
-
return [...
|
|
59995
|
-
brand:
|
|
59996
|
-
displayName:
|
|
59997
|
-
tier: robotTier(
|
|
60019
|
+
return [...brands.values()].map((b) => ({
|
|
60020
|
+
brand: b.brand,
|
|
60021
|
+
displayName: b.displayName,
|
|
60022
|
+
tier: robotTier(b.capabilities)
|
|
59998
60023
|
}));
|
|
59999
60024
|
}
|
|
60000
|
-
function
|
|
60001
|
-
|
|
60025
|
+
function clearRobotBrands() {
|
|
60026
|
+
brands.clear();
|
|
60002
60027
|
}
|
|
60003
60028
|
|
|
60004
60029
|
// src/utils/lift-contract.util.ts
|
|
@@ -60454,122 +60479,6 @@ function useRobotCloudService(credentials, options = {}) {
|
|
|
60454
60479
|
};
|
|
60455
60480
|
}
|
|
60456
60481
|
|
|
60457
|
-
// src/services/robot-fleet.service.ts
|
|
60458
|
-
function credentialsOf(robot) {
|
|
60459
|
-
const appid = (robot.appKey ?? "").trim();
|
|
60460
|
-
const secret = (robot.appToken ?? "").trim();
|
|
60461
|
-
if (!appid || !secret) {
|
|
60462
|
-
throw new import_node_server_utils157.BadRequestError(
|
|
60463
|
-
`Robot "${robot.name}" has no cloud credentials saved.`
|
|
60464
|
-
);
|
|
60465
|
-
}
|
|
60466
|
-
return { appid, secret };
|
|
60467
|
-
}
|
|
60468
|
-
function useRobotFleetService(deps) {
|
|
60469
|
-
const cloudFor = deps?.cloudFor ?? useRobotCloudService;
|
|
60470
|
-
function clientFor(robot) {
|
|
60471
|
-
return cloudFor(credentialsOf(robot));
|
|
60472
|
-
}
|
|
60473
|
-
async function resolveRobotSn(robot) {
|
|
60474
|
-
const stored = (robot.robotSn ?? "").trim();
|
|
60475
|
-
if (stored)
|
|
60476
|
-
return stored;
|
|
60477
|
-
const fleet = await clientFor(robot).getRobots();
|
|
60478
|
-
if (fleet.length === 0) {
|
|
60479
|
-
throw new import_node_server_utils157.NotFoundError(
|
|
60480
|
-
`Robot "${robot.name}": the cloud reports no robots for these credentials.`
|
|
60481
|
-
);
|
|
60482
|
-
}
|
|
60483
|
-
if (fleet.length > 1) {
|
|
60484
|
-
throw new import_node_server_utils157.BadRequestError(
|
|
60485
|
-
`Robot "${robot.name}": these credentials cover ${fleet.length} robots, so the serial cannot be determined automatically. Set it explicitly.`
|
|
60486
|
-
);
|
|
60487
|
-
}
|
|
60488
|
-
const robotSn = fleet[0].robotSn;
|
|
60489
|
-
if (!robotSn) {
|
|
60490
|
-
throw new import_node_server_utils157.BadRequestError(
|
|
60491
|
-
`Robot "${robot.name}": the cloud returned a robot with no serial.`
|
|
60492
|
-
);
|
|
60493
|
-
}
|
|
60494
|
-
const id = robot._id ? String(robot._id) : "";
|
|
60495
|
-
if (id && deps?.saveRobotSn) {
|
|
60496
|
-
await deps.saveRobotSn(id, robotSn).catch(() => void 0);
|
|
60497
|
-
}
|
|
60498
|
-
return robotSn;
|
|
60499
|
-
}
|
|
60500
|
-
async function getFleetRobot(robot) {
|
|
60501
|
-
const robotSn = await resolveRobotSn(robot);
|
|
60502
|
-
const fleet = await clientFor(robot).getRobots();
|
|
60503
|
-
const match = fleet.find(
|
|
60504
|
-
(r) => r.robotSn === robotSn
|
|
60505
|
-
);
|
|
60506
|
-
if (!match) {
|
|
60507
|
-
return {
|
|
60508
|
-
id: robot._id ? String(robot._id) : "",
|
|
60509
|
-
name: robot.name,
|
|
60510
|
-
robotSn,
|
|
60511
|
-
statusFlag: null,
|
|
60512
|
-
statusName: "Not found in the robot cloud",
|
|
60513
|
-
mode: "UNAVAILABLE",
|
|
60514
|
-
online: false,
|
|
60515
|
-
dispatchable: false
|
|
60516
|
-
};
|
|
60517
|
-
}
|
|
60518
|
-
const mode = robotModeFromList(match);
|
|
60519
|
-
return {
|
|
60520
|
-
id: robot._id ? String(robot._id) : "",
|
|
60521
|
-
name: robot.name,
|
|
60522
|
-
robotSn,
|
|
60523
|
-
statusFlag: typeof match.statusFlag === "number" ? match.statusFlag : null,
|
|
60524
|
-
statusName: match.statusName ?? "",
|
|
60525
|
-
mode,
|
|
60526
|
-
online: match.onlineFlag !== false,
|
|
60527
|
-
dispatchable: mode === "IDLE" || mode === "CHARGED"
|
|
60528
|
-
};
|
|
60529
|
-
}
|
|
60530
|
-
async function getMaps(robot) {
|
|
60531
|
-
const robotSn = await resolveRobotSn(robot);
|
|
60532
|
-
return clientFor(robot).getMaps(robotSn);
|
|
60533
|
-
}
|
|
60534
|
-
async function getMapImages(robot, fileKeys) {
|
|
60535
|
-
const robotSn = await resolveRobotSn(robot);
|
|
60536
|
-
return clientFor(robot).getFileUrls(robotSn, fileKeys);
|
|
60537
|
-
}
|
|
60538
|
-
async function dispatch(robot, command) {
|
|
60539
|
-
const robotSn = await resolveRobotSn(robot);
|
|
60540
|
-
const cloud = clientFor(robot);
|
|
60541
|
-
if (command.kind === "return") {
|
|
60542
|
-
return cloud.returnToBase(robotSn);
|
|
60543
|
-
}
|
|
60544
|
-
const state = await getFleetRobot(robot);
|
|
60545
|
-
if (!state.dispatchable) {
|
|
60546
|
-
throw new import_node_server_utils157.BadRequestError(
|
|
60547
|
-
`Robot "${robot.name}" is ${state.statusName || state.mode} and cannot take a new job.`
|
|
60548
|
-
);
|
|
60549
|
-
}
|
|
60550
|
-
switch (command.kind) {
|
|
60551
|
-
case "full":
|
|
60552
|
-
return cloud.startFullCleaning(robotSn, command.options);
|
|
60553
|
-
case "area":
|
|
60554
|
-
return cloud.startAreaCleaning(robotSn, command.areas, command.options);
|
|
60555
|
-
case "spot":
|
|
60556
|
-
return cloud.startSpotCleaning(robotSn, command.points, command.options);
|
|
60557
|
-
}
|
|
60558
|
-
}
|
|
60559
|
-
async function getPlans(robot) {
|
|
60560
|
-
const robotSn = await resolveRobotSn(robot);
|
|
60561
|
-
return clientFor(robot).getPlans(robotSn);
|
|
60562
|
-
}
|
|
60563
|
-
return {
|
|
60564
|
-
resolveRobotSn,
|
|
60565
|
-
getFleetRobot,
|
|
60566
|
-
getMaps,
|
|
60567
|
-
getMapImages,
|
|
60568
|
-
dispatch,
|
|
60569
|
-
getPlans
|
|
60570
|
-
};
|
|
60571
|
-
}
|
|
60572
|
-
|
|
60573
60482
|
// src/services/ounitech.adapter.ts
|
|
60574
60483
|
var OUNITECH_BRAND = "ounitech";
|
|
60575
60484
|
var OUNITECH_CAPABILITIES = {
|
|
@@ -60673,25 +60582,412 @@ function createOunitechAdapter(credentials, options) {
|
|
|
60673
60582
|
async getMaps(robotSn) {
|
|
60674
60583
|
return cloud.getMaps(robotSn);
|
|
60675
60584
|
},
|
|
60585
|
+
async getMapImages(robotSn, fileKeys) {
|
|
60586
|
+
return cloud.getFileUrls(robotSn, fileKeys);
|
|
60587
|
+
},
|
|
60676
60588
|
async getPlans(robotSn) {
|
|
60677
60589
|
return cloud.getPlans(robotSn);
|
|
60678
60590
|
}
|
|
60679
60591
|
};
|
|
60680
60592
|
}
|
|
60681
60593
|
function registerOunitechBrand() {
|
|
60682
|
-
|
|
60683
|
-
throw new Error(
|
|
60684
|
-
"No Ounitech credentials for this robot. Add the app key and token on the robot's record."
|
|
60685
|
-
);
|
|
60686
|
-
};
|
|
60687
|
-
registerRobotAdapter({
|
|
60594
|
+
registerRobotBrand({
|
|
60688
60595
|
brand: OUNITECH_BRAND,
|
|
60689
60596
|
displayName: "Ounitech (Q3-G / Q3-W)",
|
|
60690
60597
|
capabilities: OUNITECH_CAPABILITIES,
|
|
60691
|
-
|
|
60692
|
-
getRobot: async () => unconfigured()
|
|
60598
|
+
create: (credentials) => createOunitechAdapter(credentials)
|
|
60693
60599
|
});
|
|
60694
60600
|
}
|
|
60601
|
+
registerOunitechBrand();
|
|
60602
|
+
|
|
60603
|
+
// src/utils/png-encoder.util.ts
|
|
60604
|
+
var import_zlib = require("zlib");
|
|
60605
|
+
function crc32(buffer) {
|
|
60606
|
+
let crc = ~0;
|
|
60607
|
+
for (let i = 0; i < buffer.length; i++) {
|
|
60608
|
+
crc ^= buffer[i];
|
|
60609
|
+
for (let bit = 0; bit < 8; bit++) {
|
|
60610
|
+
crc = crc & 1 ? crc >>> 1 ^ 3988292384 : crc >>> 1;
|
|
60611
|
+
}
|
|
60612
|
+
}
|
|
60613
|
+
return ~crc >>> 0;
|
|
60614
|
+
}
|
|
60615
|
+
function chunk(type, data) {
|
|
60616
|
+
const length = Buffer.alloc(4);
|
|
60617
|
+
length.writeUInt32BE(data.length, 0);
|
|
60618
|
+
const typed = Buffer.concat([Buffer.from(type, "ascii"), data]);
|
|
60619
|
+
const crc = Buffer.alloc(4);
|
|
60620
|
+
crc.writeUInt32BE(crc32(typed), 0);
|
|
60621
|
+
return Buffer.concat([length, typed, crc]);
|
|
60622
|
+
}
|
|
60623
|
+
function encodeGreyscalePng(pixels, width, height) {
|
|
60624
|
+
if (width <= 0 || height <= 0)
|
|
60625
|
+
throw new Error("A PNG needs a positive size.");
|
|
60626
|
+
if (pixels.length < width * height) {
|
|
60627
|
+
throw new Error("A PNG needs one byte per pixel.");
|
|
60628
|
+
}
|
|
60629
|
+
const raw = Buffer.alloc((width + 1) * height);
|
|
60630
|
+
for (let y = 0; y < height; y++) {
|
|
60631
|
+
raw[y * (width + 1)] = 0;
|
|
60632
|
+
for (let x = 0; x < width; x++) {
|
|
60633
|
+
raw[y * (width + 1) + 1 + x] = pixels[y * width + x];
|
|
60634
|
+
}
|
|
60635
|
+
}
|
|
60636
|
+
const ihdr = Buffer.alloc(13);
|
|
60637
|
+
ihdr.writeUInt32BE(width, 0);
|
|
60638
|
+
ihdr.writeUInt32BE(height, 4);
|
|
60639
|
+
ihdr[8] = 8;
|
|
60640
|
+
ihdr[9] = 0;
|
|
60641
|
+
ihdr[10] = 0;
|
|
60642
|
+
ihdr[11] = 0;
|
|
60643
|
+
ihdr[12] = 0;
|
|
60644
|
+
return Buffer.concat([
|
|
60645
|
+
Buffer.from([137, 80, 78, 71, 13, 10, 26, 10]),
|
|
60646
|
+
chunk("IHDR", ihdr),
|
|
60647
|
+
chunk("IDAT", (0, import_zlib.deflateSync)(raw)),
|
|
60648
|
+
chunk("IEND", Buffer.alloc(0))
|
|
60649
|
+
]);
|
|
60650
|
+
}
|
|
60651
|
+
function greyscalePngDataUri(pixels, width, height) {
|
|
60652
|
+
return `data:image/png;base64,${encodeGreyscalePng(pixels, width, height).toString("base64")}`;
|
|
60653
|
+
}
|
|
60654
|
+
|
|
60655
|
+
// src/services/demo.adapter.ts
|
|
60656
|
+
var DEMO_BRAND = "demo";
|
|
60657
|
+
var DEMO_CAPABILITIES = {
|
|
60658
|
+
readLocation: true,
|
|
60659
|
+
navigateToPoint: true,
|
|
60660
|
+
pauseResume: true,
|
|
60661
|
+
pathAndEta: true,
|
|
60662
|
+
battery: true,
|
|
60663
|
+
sendToDock: true,
|
|
60664
|
+
relocalize: true,
|
|
60665
|
+
startProcess: true,
|
|
60666
|
+
pauseProcess: true,
|
|
60667
|
+
processCompletion: true,
|
|
60668
|
+
floorReporting: true,
|
|
60669
|
+
multiFloor: true
|
|
60670
|
+
};
|
|
60671
|
+
var SCALE = 0.05;
|
|
60672
|
+
var PLAN_W = 260;
|
|
60673
|
+
var PLAN_H = 180;
|
|
60674
|
+
var DEMO_ROBOTS = [
|
|
60675
|
+
{ robotSn: "DEMO-0001", name: "Demo Cleaner 01", model: "Demo S1", floorNo: 1, phase: 0 },
|
|
60676
|
+
{ robotSn: "DEMO-0002", name: "Demo Cleaner 02", model: "Demo S1", floorNo: 1, phase: 0.37 },
|
|
60677
|
+
{ robotSn: "DEMO-0003", name: "Demo Scrubber 03", model: "Demo X2", floorNo: 2, phase: 0.68 }
|
|
60678
|
+
];
|
|
60679
|
+
var commanded = /* @__PURE__ */ new Map();
|
|
60680
|
+
function demoPlanPixels(floorNo) {
|
|
60681
|
+
const px = new Uint8Array(PLAN_W * PLAN_H).fill(255);
|
|
60682
|
+
const set = (x, y) => {
|
|
60683
|
+
if (x >= 0 && x < PLAN_W && y >= 0 && y < PLAN_H)
|
|
60684
|
+
px[y * PLAN_W + x] = 0;
|
|
60685
|
+
};
|
|
60686
|
+
for (let x = 0; x < PLAN_W; x++) {
|
|
60687
|
+
for (const t of [0, 1]) {
|
|
60688
|
+
set(x, t);
|
|
60689
|
+
set(x, PLAN_H - 1 - t);
|
|
60690
|
+
}
|
|
60691
|
+
}
|
|
60692
|
+
for (let y = 0; y < PLAN_H; y++) {
|
|
60693
|
+
for (const t of [0, 1]) {
|
|
60694
|
+
set(t, y);
|
|
60695
|
+
set(PLAN_W - 1 - t, y);
|
|
60696
|
+
}
|
|
60697
|
+
}
|
|
60698
|
+
const wallX = Math.floor(PLAN_W * (floorNo === 1 ? 0.45 : 0.6));
|
|
60699
|
+
for (let y = 2; y < PLAN_H - 2; y++) {
|
|
60700
|
+
if (y > PLAN_H * 0.45 && y < PLAN_H * 0.6)
|
|
60701
|
+
continue;
|
|
60702
|
+
set(wallX, y);
|
|
60703
|
+
set(wallX + 1, y);
|
|
60704
|
+
}
|
|
60705
|
+
if (floorNo === 2) {
|
|
60706
|
+
const wallY = Math.floor(PLAN_H * 0.5);
|
|
60707
|
+
for (let x = 2; x < wallX; x++) {
|
|
60708
|
+
if (x > PLAN_W * 0.15 && x < PLAN_W * 0.25)
|
|
60709
|
+
continue;
|
|
60710
|
+
set(x, wallY);
|
|
60711
|
+
set(x, wallY + 1);
|
|
60712
|
+
}
|
|
60713
|
+
}
|
|
60714
|
+
return px;
|
|
60715
|
+
}
|
|
60716
|
+
function demoPosition(robot, now) {
|
|
60717
|
+
const t = (now / 9e4 + robot.phase) % 1;
|
|
60718
|
+
const angle = t * Math.PI * 2;
|
|
60719
|
+
const cx = PLAN_W * 0.5 * SCALE;
|
|
60720
|
+
const cy = PLAN_H * 0.5 * SCALE;
|
|
60721
|
+
const rx = PLAN_W * 0.28 * SCALE;
|
|
60722
|
+
const ry = PLAN_H * 0.28 * SCALE;
|
|
60723
|
+
return {
|
|
60724
|
+
x: cx + Math.cos(angle) * rx,
|
|
60725
|
+
y: cy + Math.sin(angle) * ry,
|
|
60726
|
+
// Facing along the direction of travel, which is the tangent.
|
|
60727
|
+
theta: angle + Math.PI / 2
|
|
60728
|
+
};
|
|
60729
|
+
}
|
|
60730
|
+
function demoBattery(robot, now) {
|
|
60731
|
+
const t = (now / 36e5 + robot.phase) % 1;
|
|
60732
|
+
return Math.round(t < 0.8 ? 100 - t / 0.8 * 75 : 25 + (t - 0.8) / 0.2 * 75);
|
|
60733
|
+
}
|
|
60734
|
+
function demoState(robot, now) {
|
|
60735
|
+
const order = commanded.get(robot.robotSn);
|
|
60736
|
+
const active = order && order.until > now ? order.mode : null;
|
|
60737
|
+
const battery = demoBattery(robot, now);
|
|
60738
|
+
const mode = battery <= 25 ? "CHARGING_CYCLE" : active ?? "IDLE";
|
|
60739
|
+
return {
|
|
60740
|
+
robotSn: robot.robotSn,
|
|
60741
|
+
name: robot.name,
|
|
60742
|
+
model: robot.model,
|
|
60743
|
+
online: true,
|
|
60744
|
+
mode,
|
|
60745
|
+
statusName: mode === "WORKING" ? "Cleaning" : mode === "CHARGING_CYCLE" ? "Charging" : "Idle",
|
|
60746
|
+
batteryPercent: battery,
|
|
60747
|
+
floorNo: robot.floorNo,
|
|
60748
|
+
// The demo DOES know its floor - unlike Ounitech today - so the map can
|
|
60749
|
+
// draw it. That contrast is part of what the demo shows.
|
|
60750
|
+
floorKnown: true,
|
|
60751
|
+
position: demoPosition(robot, now)
|
|
60752
|
+
};
|
|
60753
|
+
}
|
|
60754
|
+
function createDemoAdapter(options) {
|
|
60755
|
+
const now = options?.now ?? Date.now;
|
|
60756
|
+
return {
|
|
60757
|
+
brand: DEMO_BRAND,
|
|
60758
|
+
displayName: "Demo robots (simulated)",
|
|
60759
|
+
capabilities: DEMO_CAPABILITIES,
|
|
60760
|
+
async listRobots() {
|
|
60761
|
+
const at2 = now();
|
|
60762
|
+
return DEMO_ROBOTS.map((r) => demoState(r, at2));
|
|
60763
|
+
},
|
|
60764
|
+
async getRobot(robotSn) {
|
|
60765
|
+
const robot = DEMO_ROBOTS.find((r) => r.robotSn === robotSn);
|
|
60766
|
+
return robot ? demoState(robot, now()) : null;
|
|
60767
|
+
},
|
|
60768
|
+
async sendCommand(robotSn, command) {
|
|
60769
|
+
const robot = DEMO_ROBOTS.find((r) => r.robotSn === robotSn);
|
|
60770
|
+
if (!robot)
|
|
60771
|
+
throw new Error(`No demo robot with serial ${robotSn}.`);
|
|
60772
|
+
const at2 = now();
|
|
60773
|
+
switch (command.kind) {
|
|
60774
|
+
case "full":
|
|
60775
|
+
case "area":
|
|
60776
|
+
case "spot":
|
|
60777
|
+
commanded.set(robotSn, { mode: "WORKING", until: at2 + 10 * 6e4 });
|
|
60778
|
+
return;
|
|
60779
|
+
case "return":
|
|
60780
|
+
commanded.set(robotSn, { mode: "CHARGING_CYCLE", until: at2 + 5 * 6e4 });
|
|
60781
|
+
return;
|
|
60782
|
+
case "pause":
|
|
60783
|
+
commanded.set(robotSn, { mode: "PAUSED", until: at2 + 10 * 6e4 });
|
|
60784
|
+
return;
|
|
60785
|
+
case "resume":
|
|
60786
|
+
commanded.set(robotSn, { mode: "WORKING", until: at2 + 10 * 6e4 });
|
|
60787
|
+
return;
|
|
60788
|
+
case "cancel":
|
|
60789
|
+
commanded.delete(robotSn);
|
|
60790
|
+
return;
|
|
60791
|
+
case "navigate":
|
|
60792
|
+
case "relocalize":
|
|
60793
|
+
commanded.set(robotSn, { mode: "WORKING", until: at2 + 6e4 });
|
|
60794
|
+
return;
|
|
60795
|
+
}
|
|
60796
|
+
},
|
|
60797
|
+
async getMaps() {
|
|
60798
|
+
return DEMO_ROBOTS.map((r) => r.floorNo).filter((floorNo, i, all) => all.indexOf(floorNo) === i).sort((a, b) => a - b).map((floorNo) => ({
|
|
60799
|
+
floorNo,
|
|
60800
|
+
mapName: `Demo Building L${floorNo}`,
|
|
60801
|
+
backgroundFileKey: `demo/L${floorNo}.png`,
|
|
60802
|
+
partitionFileKey: `demo/L${floorNo}.png`,
|
|
60803
|
+
originX: 0,
|
|
60804
|
+
originY: 0,
|
|
60805
|
+
resolution: SCALE,
|
|
60806
|
+
totalArea: Math.round(PLAN_W * PLAN_H * SCALE * SCALE),
|
|
60807
|
+
baseX: 12,
|
|
60808
|
+
baseY: 3,
|
|
60809
|
+
baseTheta: 0,
|
|
60810
|
+
createTime: (/* @__PURE__ */ new Date(0)).toISOString(),
|
|
60811
|
+
areaList: [
|
|
60812
|
+
{ areaName: `L${floorNo}-LOBBY`, rgba: "FF0B0B83", x: 60, y: 60 },
|
|
60813
|
+
{ areaName: `L${floorNo}-OFFICE`, rgba: "B7CAEFFF", x: 190, y: 60 },
|
|
60814
|
+
{ areaName: `L${floorNo}-CORRIDOR`, rgba: "BA144BFF", x: 120, y: 140 }
|
|
60815
|
+
]
|
|
60816
|
+
}));
|
|
60817
|
+
},
|
|
60818
|
+
/**
|
|
60819
|
+
* Data URIs rather than signed links.
|
|
60820
|
+
*
|
|
60821
|
+
* A demo must work with no storage account and no network, and a `data:`
|
|
60822
|
+
* URI is same-origin so the canvas is not tainted — which matters, because
|
|
60823
|
+
* the layout is built by reading these pixels back.
|
|
60824
|
+
*/
|
|
60825
|
+
async getMapImages(_robotSn, fileKeys) {
|
|
60826
|
+
return fileKeys.map((fileKey) => {
|
|
60827
|
+
const floorNo = fileKey.includes("L2") ? 2 : 1;
|
|
60828
|
+
return {
|
|
60829
|
+
fileKey,
|
|
60830
|
+
url: greyscalePngDataUri(demoPlanPixels(floorNo), PLAN_W, PLAN_H)
|
|
60831
|
+
};
|
|
60832
|
+
});
|
|
60833
|
+
},
|
|
60834
|
+
async getPlans() {
|
|
60835
|
+
return [
|
|
60836
|
+
{
|
|
60837
|
+
planId: 1,
|
|
60838
|
+
dateList: [1, 2, 3, 4, 5],
|
|
60839
|
+
startTime: "08:00",
|
|
60840
|
+
endTime: "10:00",
|
|
60841
|
+
enableFlag: true,
|
|
60842
|
+
jobList: [
|
|
60843
|
+
{
|
|
60844
|
+
floorNo: 1,
|
|
60845
|
+
rangeFlag: 3,
|
|
60846
|
+
cleanTimes: 1,
|
|
60847
|
+
pointList: [],
|
|
60848
|
+
colorList: [{ r: 255, g: 11, b: 11, a: 131 }],
|
|
60849
|
+
modeFlag: 1,
|
|
60850
|
+
subModeFlag: 0,
|
|
60851
|
+
levelFlag: 1
|
|
60852
|
+
}
|
|
60853
|
+
]
|
|
60854
|
+
}
|
|
60855
|
+
];
|
|
60856
|
+
}
|
|
60857
|
+
};
|
|
60858
|
+
}
|
|
60859
|
+
function registerDemoBrand() {
|
|
60860
|
+
registerRobotBrand({
|
|
60861
|
+
brand: DEMO_BRAND,
|
|
60862
|
+
displayName: "Demo robots (simulated)",
|
|
60863
|
+
capabilities: DEMO_CAPABILITIES,
|
|
60864
|
+
create: () => createDemoAdapter()
|
|
60865
|
+
});
|
|
60866
|
+
}
|
|
60867
|
+
registerDemoBrand();
|
|
60868
|
+
|
|
60869
|
+
// src/services/robot-fleet.service.ts
|
|
60870
|
+
function useRobotFleetService(deps) {
|
|
60871
|
+
const adapterFor = deps?.adapterFor ?? ((robot) => adapterForRobot(robot));
|
|
60872
|
+
function capabilitiesOf(robot) {
|
|
60873
|
+
return robotBrandFor(robot.brand ?? "")?.capabilities ?? {};
|
|
60874
|
+
}
|
|
60875
|
+
async function resolveRobotSn(robot) {
|
|
60876
|
+
const stored = (robot.robotSn ?? "").trim();
|
|
60877
|
+
if (stored)
|
|
60878
|
+
return stored;
|
|
60879
|
+
const fleet = await adapterFor(robot).listRobots();
|
|
60880
|
+
if (fleet.length === 0) {
|
|
60881
|
+
throw new import_node_server_utils157.NotFoundError(
|
|
60882
|
+
`Robot "${robot.name}": the robot cloud reports no robots for these credentials.`
|
|
60883
|
+
);
|
|
60884
|
+
}
|
|
60885
|
+
if (fleet.length > 1) {
|
|
60886
|
+
throw new import_node_server_utils157.BadRequestError(
|
|
60887
|
+
`Robot "${robot.name}": these credentials cover ${fleet.length} robots, so the serial cannot be determined automatically. Set it explicitly.`
|
|
60888
|
+
);
|
|
60889
|
+
}
|
|
60890
|
+
const robotSn = fleet[0].robotSn;
|
|
60891
|
+
if (!robotSn) {
|
|
60892
|
+
throw new import_node_server_utils157.BadRequestError(`Robot "${robot.name}": the cloud returned a robot with no serial.`);
|
|
60893
|
+
}
|
|
60894
|
+
const id = robot._id ? String(robot._id) : "";
|
|
60895
|
+
if (id && deps?.saveRobotSn) {
|
|
60896
|
+
await deps.saveRobotSn(id, robotSn).catch(() => void 0);
|
|
60897
|
+
}
|
|
60898
|
+
return robotSn;
|
|
60899
|
+
}
|
|
60900
|
+
async function getFleetRobot(robot) {
|
|
60901
|
+
const adapter = adapterFor(robot);
|
|
60902
|
+
const robotSn = await resolveRobotSn(robot);
|
|
60903
|
+
const found = await adapter.getRobot(robotSn);
|
|
60904
|
+
const id = robot._id ? String(robot._id) : "";
|
|
60905
|
+
const brand = adapter.brand;
|
|
60906
|
+
if (!found) {
|
|
60907
|
+
return {
|
|
60908
|
+
id,
|
|
60909
|
+
name: robot.name,
|
|
60910
|
+
brand,
|
|
60911
|
+
robotSn,
|
|
60912
|
+
statusName: "Not found in the robot cloud",
|
|
60913
|
+
mode: "UNAVAILABLE",
|
|
60914
|
+
online: false,
|
|
60915
|
+
dispatchable: false,
|
|
60916
|
+
batteryPercent: null,
|
|
60917
|
+
floorNo: null,
|
|
60918
|
+
floorKnown: false,
|
|
60919
|
+
position: null
|
|
60920
|
+
};
|
|
60921
|
+
}
|
|
60922
|
+
const free = found.mode === "IDLE" || found.mode === "CHARGED";
|
|
60923
|
+
return {
|
|
60924
|
+
id,
|
|
60925
|
+
name: robot.name,
|
|
60926
|
+
brand,
|
|
60927
|
+
robotSn,
|
|
60928
|
+
statusName: found.statusName ?? "",
|
|
60929
|
+
mode: found.mode,
|
|
60930
|
+
online: found.online,
|
|
60931
|
+
dispatchable: found.online && free && commandSupported(adapter.capabilities, "full"),
|
|
60932
|
+
batteryPercent: found.batteryPercent ?? null,
|
|
60933
|
+
floorNo: found.floorNo ?? null,
|
|
60934
|
+
floorKnown: found.floorKnown === true,
|
|
60935
|
+
position: found.position ?? null
|
|
60936
|
+
};
|
|
60937
|
+
}
|
|
60938
|
+
async function getMaps(robot) {
|
|
60939
|
+
const adapter = adapterFor(robot);
|
|
60940
|
+
if (!adapter.getMaps)
|
|
60941
|
+
return [];
|
|
60942
|
+
return adapter.getMaps(await resolveRobotSn(robot));
|
|
60943
|
+
}
|
|
60944
|
+
async function getMapImages(robot, fileKeys) {
|
|
60945
|
+
const adapter = adapterFor(robot);
|
|
60946
|
+
if (!adapter.getMapImages || !fileKeys.length)
|
|
60947
|
+
return [];
|
|
60948
|
+
return adapter.getMapImages(await resolveRobotSn(robot), fileKeys);
|
|
60949
|
+
}
|
|
60950
|
+
async function getPlans(robot) {
|
|
60951
|
+
const adapter = adapterFor(robot);
|
|
60952
|
+
if (!adapter.getPlans)
|
|
60953
|
+
return [];
|
|
60954
|
+
return adapter.getPlans(await resolveRobotSn(robot));
|
|
60955
|
+
}
|
|
60956
|
+
async function dispatch(robot, command) {
|
|
60957
|
+
const adapter = adapterFor(robot);
|
|
60958
|
+
if (!adapter.sendCommand) {
|
|
60959
|
+
throw new import_node_server_utils157.BadRequestError(
|
|
60960
|
+
`${adapter.displayName} robots cannot be commanded through their API.`
|
|
60961
|
+
);
|
|
60962
|
+
}
|
|
60963
|
+
if (!commandSupported(adapter.capabilities, command.kind)) {
|
|
60964
|
+
throw new import_node_server_utils157.BadRequestError(
|
|
60965
|
+
`${adapter.displayName} does not support "${command.kind}" through its API yet.`
|
|
60966
|
+
);
|
|
60967
|
+
}
|
|
60968
|
+
const robotSn = await resolveRobotSn(robot);
|
|
60969
|
+
if (command.kind === "return") {
|
|
60970
|
+
return adapter.sendCommand(robotSn, command);
|
|
60971
|
+
}
|
|
60972
|
+
const state = await getFleetRobot(robot);
|
|
60973
|
+
if (!state.dispatchable) {
|
|
60974
|
+
throw new import_node_server_utils157.BadRequestError(
|
|
60975
|
+
`Robot "${robot.name}" is ${state.statusName || state.mode} and cannot take a new job.`
|
|
60976
|
+
);
|
|
60977
|
+
}
|
|
60978
|
+
return adapter.sendCommand(robotSn, command);
|
|
60979
|
+
}
|
|
60980
|
+
return {
|
|
60981
|
+
adapterFor,
|
|
60982
|
+
capabilitiesOf,
|
|
60983
|
+
resolveRobotSn,
|
|
60984
|
+
getFleetRobot,
|
|
60985
|
+
getMaps,
|
|
60986
|
+
getMapImages,
|
|
60987
|
+
getPlans,
|
|
60988
|
+
dispatch
|
|
60989
|
+
};
|
|
60990
|
+
}
|
|
60695
60991
|
|
|
60696
60992
|
// src/services/robot-tracking.service.ts
|
|
60697
60993
|
var import_axios4 = __toESM(require("axios"));
|
|
@@ -60793,10 +61089,10 @@ function startRobotTracking(options) {
|
|
|
60793
61089
|
onEvent({ type: "reconnected", at: now() });
|
|
60794
61090
|
everConnected = true;
|
|
60795
61091
|
attempt = 0;
|
|
60796
|
-
stream.on("data", (
|
|
61092
|
+
stream.on("data", (chunk2) => {
|
|
60797
61093
|
if (stopped)
|
|
60798
61094
|
return;
|
|
60799
|
-
const { events, sawActivity } = parser.push(
|
|
61095
|
+
const { events, sawActivity } = parser.push(chunk2.toString("utf8"));
|
|
60800
61096
|
if (sawActivity)
|
|
60801
61097
|
lastActivityAt = now();
|
|
60802
61098
|
for (const event of events) {
|
|
@@ -60958,7 +61254,14 @@ function useRobotFleetController(deps) {
|
|
|
60958
61254
|
req.on("aborted", close);
|
|
60959
61255
|
res.on("error", close);
|
|
60960
61256
|
}
|
|
60961
|
-
|
|
61257
|
+
async function getBrands(_req, res, next) {
|
|
61258
|
+
try {
|
|
61259
|
+
res.json({ items: registeredRobotBrands() });
|
|
61260
|
+
} catch (error) {
|
|
61261
|
+
fail(next, error);
|
|
61262
|
+
}
|
|
61263
|
+
}
|
|
61264
|
+
return { getState, getMaps, getMapImages, getPlans, sendCommand: sendCommand2, trackRobot, getBrands };
|
|
60962
61265
|
}
|
|
60963
61266
|
|
|
60964
61267
|
// src/models/patrol-question.model.ts
|
|
@@ -94319,6 +94622,8 @@ function usePersonalEmergencyChainController() {
|
|
|
94319
94622
|
DEFAULT_RING_SECONDS,
|
|
94320
94623
|
DEFAULT_SCALE_M_PER_PX,
|
|
94321
94624
|
DEFAULT_SITE_TIMEZONE,
|
|
94625
|
+
DEMO_BRAND,
|
|
94626
|
+
DEMO_CAPABILITIES,
|
|
94322
94627
|
DEVICE_STATUS,
|
|
94323
94628
|
DOBStatus,
|
|
94324
94629
|
DUPLICATE_TERMS_VERSION_MESSAGE,
|
|
@@ -94540,6 +94845,7 @@ function usePersonalEmergencyChainController() {
|
|
|
94540
94845
|
VisitorStatus,
|
|
94541
94846
|
WALL_HEIGHT_M,
|
|
94542
94847
|
WALL_THICKNESS_M,
|
|
94848
|
+
adapterForRobot,
|
|
94543
94849
|
addressSchema,
|
|
94544
94850
|
allowedFieldsSite,
|
|
94545
94851
|
allowedNatures,
|
|
@@ -94579,13 +94885,14 @@ function usePersonalEmergencyChainController() {
|
|
|
94579
94885
|
chatSchema,
|
|
94580
94886
|
claimReadsAsStale,
|
|
94581
94887
|
clampPtzSpeed,
|
|
94582
|
-
|
|
94888
|
+
clearRobotBrands,
|
|
94583
94889
|
clockDriftSeconds,
|
|
94584
94890
|
commandSupported,
|
|
94585
94891
|
consoleRoleAllows,
|
|
94586
94892
|
consoleRoleAllowsAll,
|
|
94587
94893
|
consoleSpellings,
|
|
94588
94894
|
console_audit_namespace_collection,
|
|
94895
|
+
createDemoAdapter,
|
|
94589
94896
|
createLiftSimulator,
|
|
94590
94897
|
createManpowerRemarksDaily,
|
|
94591
94898
|
createOunitechAdapter,
|
|
@@ -94609,6 +94916,7 @@ function usePersonalEmergencyChainController() {
|
|
|
94609
94916
|
disconnectedState,
|
|
94610
94917
|
emitNotificationCreated,
|
|
94611
94918
|
emptyPersonalEmergencyChain,
|
|
94919
|
+
encodeGreyscalePng,
|
|
94612
94920
|
encodeHidPacsCard,
|
|
94613
94921
|
entitledSiteScope,
|
|
94614
94922
|
events_namespace_collection,
|
|
@@ -94627,6 +94935,7 @@ function usePersonalEmergencyChainController() {
|
|
|
94627
94935
|
getIO,
|
|
94628
94936
|
getSessionIdFromRequest,
|
|
94629
94937
|
grabWithSubStreamFallback,
|
|
94938
|
+
greyscalePngDataUri,
|
|
94630
94939
|
guests_namespace_collection,
|
|
94631
94940
|
hasAnyCapability,
|
|
94632
94941
|
hasAnyPermission,
|
|
@@ -94728,8 +95037,9 @@ function usePersonalEmergencyChainController() {
|
|
|
94728
95037
|
recordConsoleAction,
|
|
94729
95038
|
refuseServiceProviderInviteAction,
|
|
94730
95039
|
registerCameraTransport,
|
|
95040
|
+
registerDemoBrand,
|
|
94731
95041
|
registerOunitechBrand,
|
|
94732
|
-
|
|
95042
|
+
registerRobotBrand,
|
|
94733
95043
|
registeredRobotBrands,
|
|
94734
95044
|
relayForRecorder,
|
|
94735
95045
|
remarksSchema,
|
|
@@ -94748,7 +95058,7 @@ function usePersonalEmergencyChainController() {
|
|
|
94748
95058
|
resolveSiteTimezone,
|
|
94749
95059
|
resolveStaffRole,
|
|
94750
95060
|
robotActionsFor,
|
|
94751
|
-
|
|
95061
|
+
robotBrandFor,
|
|
94752
95062
|
robotCloudBody,
|
|
94753
95063
|
robotCloudSign,
|
|
94754
95064
|
robotCloudSigningString,
|