@7365admin1/core 3.133.0 → 3.134.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 +12 -0
- package/dist/index.d.ts +113 -4
- package/dist/index.js +342 -19
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +333 -19
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/test/e2e/robot-vendor-errors.e2e.test.mjs +3 -2
- package/test/ounitech-api-2025-10.test.mjs +153 -4
- package/test/robot-vendor-errors.test.mjs +7 -0
package/package.json
CHANGED
|
@@ -144,8 +144,9 @@ describe("robot vendor failures are handled answers; diagnose names the step", {
|
|
|
144
144
|
mode = "ok";
|
|
145
145
|
const ok = await h.api(`/robots/${id.robot}/diagnose`, { sid: staffSid });
|
|
146
146
|
assert.equal(ok.body.failedStep, null, JSON.stringify(ok.body));
|
|
147
|
-
// credentials, sign-in, get robot, maps, then the
|
|
148
|
-
|
|
147
|
+
// credentials, sign-in, get robot, maps, then the 16 read-only 2025.10 calls (all answered;
|
|
148
|
+
// this mock's map has no numeric mapId, so the 4 per-map layer reads are skipped).
|
|
149
|
+
assert.equal(ok.body.steps.length, 20, JSON.stringify(ok.body.steps.map((s) => s.step)));
|
|
149
150
|
assert.ok(ok.body.steps.every((s) => s.ok), JSON.stringify(ok.body.steps.filter((s) => !s.ok)));
|
|
150
151
|
assert.match(ok.body.steps[2].detail, /model Q3, battery 88%, floor 1/);
|
|
151
152
|
assert.ok(ok.body.clock?.vendorDate, "the vendor's clock is reported");
|
|
@@ -21,6 +21,14 @@ import {
|
|
|
21
21
|
ounitechTime,
|
|
22
22
|
pngSize,
|
|
23
23
|
clearOunitechCaches,
|
|
24
|
+
ounitechShapes,
|
|
25
|
+
ounitechTrack,
|
|
26
|
+
ounitechStatusLog,
|
|
27
|
+
ounitechAppAction,
|
|
28
|
+
ounitechSettings,
|
|
29
|
+
ounitechObstacleImage,
|
|
30
|
+
ounitechMapVersion,
|
|
31
|
+
ounitechFloorMapHistory,
|
|
24
32
|
} from "./.build/services/ounitech.adapter.mjs";
|
|
25
33
|
|
|
26
34
|
/* --------------------------------------------------------------------------
|
|
@@ -121,6 +129,28 @@ const ALERTS = [
|
|
|
121
129
|
{ deviceFlag: 1, errCode: "621 - 右轮驱动器重置( 4)(Resolved)", errMsg: "621 - 右轮驱动器重置( 4)(Resolved)", createTime: "2025-10-20 14:23:45" },
|
|
122
130
|
];
|
|
123
131
|
|
|
132
|
+
/* The ten read-only map-layer / log / settings replies, in the document's shapes (2025.10.22 §3083-3688, §6989-7204, §1478). */
|
|
133
|
+
const WALLS = [{ wallId: 216395, wallName: "大门口", pointList: [[-1, -5], [1.5, -2.25], [9, 9]] }, { wallId: 216396, wallName: "", pointList: [[0, 0]] }];
|
|
134
|
+
const SAFE = [{ zoneId: 1, zoneName: "test", pointList: [[0.1, 0.1], [0.5, 0.5], [0.9, 0.1]] }];
|
|
135
|
+
const SLOW = [{ zoneId: 6, zoneName: "", pointList: [[-1, -5], [0, -5], [0, -4]] }];
|
|
136
|
+
const PNG_B64 = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8BQDwAEhQGAhKmMIQAAAABJRU5ErkJggg==";
|
|
137
|
+
const TEACH = { since: "2025-03-04 11:29:10", offset: "2025-03-04 11:29:10", trackList: [{ x: 1, y: 1, theta: 0, mapid: 1 }, { x: 2, y: -1, theta: 0, mapid: 1 }, { x: 5, y: 5, theta: 0, mapid: 99 }] };
|
|
138
|
+
const VERSIONS = [{ versionId: 11206, versionNo: 1, mapId: 1, latestFlag: true, partitionFileKey: "/z.png", mapFileKey: "", backgroundFileKey: "/b.png", creatorFlag: 0, creatorId: 0, createTime: "2025-05-28 19:06:48" }];
|
|
139
|
+
const FLOOR_MAPS = [
|
|
140
|
+
{ mapId: 2139, mapName: "欧亚学院 2F", sceneId: 94, backgroundFileKey: "/a.png", totalArea: 6106.217, floorNo: 2, latestFlag: true, enableFlag: true, createTime: "2024-08-20 16:26:45", updateTime: "2025-03-12 19:20:16" },
|
|
141
|
+
{ mapId: 2071, mapName: "5楼会议室", sceneId: 94, totalArea: 22.585, floorNo: 2, latestFlag: false, enableFlag: false, createTime: "2024-07-26 14:22:18", updateTime: "2024-07-26 18:37:42" },
|
|
142
|
+
];
|
|
143
|
+
const ROBOT_LOG = [
|
|
144
|
+
{ taskId: 1822883, robotId: 590, robotName: "2A7F25DE96E56", sceneId: 603, sceneName: "2A7F25DE96E56", typeFlag: "9", timeFrom: "2025-10-22 17:48:39", typeName: "充电完成" },
|
|
145
|
+
{ taskId: 1822707, robotId: 590, sceneId: 603, typeFlag: "16", timeFrom: "2025-10-22 17:01:06", typeName: "断点充电中" },
|
|
146
|
+
{ taskId: 1822460, robotId: 590, sceneId: 603, typeFlag: "2", timeFrom: "2025-10-22 15:55:21", typeName: "清洁中" },
|
|
147
|
+
];
|
|
148
|
+
const USER_LOG = [
|
|
149
|
+
{ robotId: 318, actionId: 181630, actionName: "原地停止", createTime: "2025-10-20 14:22:32", userName: "梁家茂", userPhone: "17875645433" },
|
|
150
|
+
{ robotId: 318, actionId: 181629, actionName: "下发清洁", createTime: "2025-10-20 14:22:07", userName: "梁家茂", userPhone: "17875645433" },
|
|
151
|
+
];
|
|
152
|
+
const SETTING = { fanLevel: 0, soundLevel: 80, enablePlanFlag: true, wifiName: "SiteWifi", wifiPwd: "wifi-secret-123", minCleanBatteryPerc: 50, language: "zh", timeZone: 8, clean_speed_mode: "standard", garbage_threshold: 15 };
|
|
153
|
+
|
|
124
154
|
let server;
|
|
125
155
|
let base;
|
|
126
156
|
const seen = [];
|
|
@@ -194,11 +224,32 @@ before(async () => {
|
|
|
194
224
|
case ROBOT_CLOUD_PATHS.haltPlans:
|
|
195
225
|
return ok({ total: 1, planList: [{ planId: 4, robotId: body.robotId, dateList: [1, 2, 3, 4, 5], actionTime: "20:00", actionFlag: 0, enableFlag: true, remark: "1-5 晚8点关机" }] });
|
|
196
226
|
case ROBOT_CLOUD_PATHS.stationState:
|
|
227
|
+
if (body.robotId === 425) return res.end(JSON.stringify({ ok: false, msg: "no station bound (e=59)" })); // robot 424 on prod
|
|
197
228
|
return ok({ state: { stationId: 4560, updateOn: Date.now(), statusFlag: "0", statusName: "Offline", properties: [s("clean-water", "3.300", "double", "升"), s("charge-err", "false", "bool")] } });
|
|
198
229
|
case ROBOT_CLOUD_PATHS.liftList:
|
|
199
230
|
return ok({ liftlist: [{ liftid: 45, liftno: 3701, liftname: "Lift A", floorno: 13, onlineflag: 1, enableflag: true, simno: "868327073829804" }] });
|
|
200
231
|
case ROBOT_CLOUD_PATHS.mapList:
|
|
201
232
|
return ok({ mapList: [{ floorNo: 1 }] });
|
|
233
|
+
case ROBOT_CLOUD_PATHS.wallList:
|
|
234
|
+
return ok({ wallList: body.mapId === 1 ? WALLS : [] });
|
|
235
|
+
case ROBOT_CLOUD_PATHS.safeZoneList:
|
|
236
|
+
return ok({ safeZoneList: body.mapId === 1 ? SAFE : [] });
|
|
237
|
+
case ROBOT_CLOUD_PATHS.slowZoneList:
|
|
238
|
+
return ok({ slowZoneList: body.mapId === 1 ? SLOW : [] });
|
|
239
|
+
case ROBOT_CLOUD_PATHS.obstacleLayer:
|
|
240
|
+
return ok({ version: 123123123123, image: PNG_B64 });
|
|
241
|
+
case ROBOT_CLOUD_PATHS.teachTrack:
|
|
242
|
+
return ok(TEACH);
|
|
243
|
+
case ROBOT_CLOUD_PATHS.mapVersions:
|
|
244
|
+
return ok({ total: 1, versionList: VERSIONS });
|
|
245
|
+
case ROBOT_CLOUD_PATHS.floorMapHistory:
|
|
246
|
+
return ok({ total: 2, mapList: FLOOR_MAPS });
|
|
247
|
+
case ROBOT_CLOUD_PATHS.robotLog:
|
|
248
|
+
return ok({ total: 342, logList: ROBOT_LOG });
|
|
249
|
+
case ROBOT_CLOUD_PATHS.userLog:
|
|
250
|
+
return ok({ actionList: USER_LOG, total: 38 });
|
|
251
|
+
case ROBOT_CLOUD_PATHS.cleaningSetting:
|
|
252
|
+
return ok(SETTING);
|
|
202
253
|
default:
|
|
203
254
|
return text(res, 404, "not found");
|
|
204
255
|
}
|
|
@@ -266,11 +317,22 @@ test("status 7 costs one extra read, get-robot-state-v2.0 by robotId, to name th
|
|
|
266
317
|
assert.deepEqual(ounitechFault([]), { code: "error", message: "The robot reports an error" });
|
|
267
318
|
});
|
|
268
319
|
|
|
269
|
-
test("maps: get-floor-maps by the robot's sceneId, latest only, walls left out", async () => {
|
|
320
|
+
test("maps: get-floor-maps by the robot's sceneId, latest only, raw walls left out (drawn as zones)", async () => {
|
|
270
321
|
clearOunitechCaches();
|
|
271
322
|
seen.length = 0;
|
|
272
323
|
const maps = await adapter().getMaps("F8FCA9A1B1C4C");
|
|
273
|
-
assert.deepEqual(seen.map((s) => s.path), [
|
|
324
|
+
assert.deepEqual(seen.map((s) => s.path), [
|
|
325
|
+
ROBOT_CLOUD_PATHS.homeRobotList,
|
|
326
|
+
ROBOT_CLOUD_PATHS.floorMaps,
|
|
327
|
+
ROBOT_CLOUD_PATHS.filePreview,
|
|
328
|
+
ROBOT_CLOUD_PATHS.wallList,
|
|
329
|
+
ROBOT_CLOUD_PATHS.safeZoneList,
|
|
330
|
+
ROBOT_CLOUD_PATHS.slowZoneList,
|
|
331
|
+
ROBOT_CLOUD_PATHS.teachTrack,
|
|
332
|
+
]);
|
|
333
|
+
assert.equal(seen[3].body.mapId, 1);
|
|
334
|
+
assert.equal(seen[6].body.robotId, 424);
|
|
335
|
+
assert.match(seen[6].body.offset, /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/);
|
|
274
336
|
assert.equal(seen[1].body.sceneId, 438);
|
|
275
337
|
assert.equal(seen[1].body.enableFlag, 1);
|
|
276
338
|
assert.equal(maps.length, 1);
|
|
@@ -519,7 +581,12 @@ test("records: a robot not on the account says so", async () => {
|
|
|
519
581
|
test("alert, reading, task and schedule mapping (pure, recorded shapes)", () => {
|
|
520
582
|
const a = ounitechAlertRecord({ errMsg: "785 - (提示)定位准备完成( 5)", createTime: "2026-09-30 07:02:57" });
|
|
521
583
|
assert.deepEqual(a, { code: "785", level: "Notice", message: "Localisation ready", vendorText: "定位准备完成", resolved: false, at: "2026-09-29T23:02:57.000Z" });
|
|
522
|
-
assert.equal(ounitechAlertRecord({ errMsg: "999 - (警告)未知( 3)" }).message, "未知", "unknown code
|
|
584
|
+
assert.equal(ounitechAlertRecord({ errMsg: "999 - (警告)未知( 3)" }).message, "Robot alert 999: 未知", "unknown code: code first, the vendor's words kept");
|
|
585
|
+
// Robot 424's other prod alerts (2026-09-30) read in English.
|
|
586
|
+
assert.equal(ounitechAlertRecord({ errMsg: "589 - (提示)定时关机( 5)" }).message, "Switched off by the timed power schedule");
|
|
587
|
+
assert.equal(ounitechAlertRecord({ errMsg: "205 - 边刷驱动器离线( 4)" }).message, "Side brush driver offline");
|
|
588
|
+
assert.equal(ounitechAlertRecord({ errMsg: "900 - plain words" }).message, "plain words");
|
|
589
|
+
assert.equal(ounitechConsumable({ unitcode: "scraper", workminutes: 60 }).part, "Scraper");
|
|
523
590
|
assert.equal(ounitechAlertRecord({ errMsg: "999 - (警告)未知( 3)" }).level, "Warning");
|
|
524
591
|
|
|
525
592
|
// Robot 424's live readings on prod (2026-09-30); IP and SIM left out.
|
|
@@ -549,7 +616,89 @@ test("alert, reading, task and schedule mapping (pure, recorded shapes)", () =>
|
|
|
549
616
|
assert.equal(t.map, null);
|
|
550
617
|
assert.equal(t.start, "2026-09-30T00:00:00.000Z");
|
|
551
618
|
assert.equal(ounitechTime("garbage"), null);
|
|
552
|
-
assert.deepEqual(ounitechConsumable({ unitcode: "new_part_x", workminutes: 90 }), { part: "
|
|
619
|
+
assert.deepEqual(ounitechConsumable({ unitcode: "new_part_x", workminutes: 90 }), { part: "New part x", hours: 1.5, days: null });
|
|
553
620
|
assert.equal(ounitechPowerPlan({ dateList: [6, 7, 9], actionTime: "07:30", actionFlag: 1 }).action, "on");
|
|
554
621
|
assert.deepEqual(ounitechPowerPlan({ dateList: [6, 7, 9] }).days, [6, 7]);
|
|
555
622
|
});
|
|
623
|
+
|
|
624
|
+
test("records: 'no station bound (e=59)' means no base station - no error shown", async () => {
|
|
625
|
+
const r = await adapter().getRecords("OFFLINE1");
|
|
626
|
+
assert.deepEqual(r.station, { items: [] });
|
|
627
|
+
});
|
|
628
|
+
|
|
629
|
+
test("map layers: walls, safe and slow zones and the taught route drawn on the robot's map (get-wall/safezone/slowzone-list, get-teach-track)", async () => {
|
|
630
|
+
clearOunitechCaches();
|
|
631
|
+
const [m] = await adapter().getMaps("F8FCA9A1B1C4C");
|
|
632
|
+
// Map: 200 x 100 px, origin (-1, -5), 0.05 m/px. (-1,-5) = bottom-left corner; (1.5,-2.25) = 25 %, 45 %; (9,9) past the edge -> clamped.
|
|
633
|
+
assert.deepEqual(m.zones[0], { kind: "wall", name: "大门口", points: [{ x: 0, y: 100 }, { x: 25, y: 45 }, { x: 100, y: 0 }] });
|
|
634
|
+
assert.equal(m.zones.filter((z) => z.kind === "wall").length, 1, "a one-point wall is not drawn");
|
|
635
|
+
assert.deepEqual(m.zones.find((z) => z.kind === "safe").name, "test");
|
|
636
|
+
assert.deepEqual(m.zones.find((z) => z.kind === "slow"), { kind: "slow", name: "Slow zone 1", points: [{ x: 0, y: 100 }, { x: 10, y: 100 }, { x: 10, y: 80 }] });
|
|
637
|
+
// Taught route: only points on this map (mapid 1); (1,1) -> 20 %, (1+5)/0.05=120 px up of 100 -> clamped top; (2,-1) -> 30 %, 20 %.
|
|
638
|
+
assert.deepEqual(m.taughtRoute, [{ x: 20, y: 0 }, { x: 30, y: 20 }]);
|
|
639
|
+
});
|
|
640
|
+
|
|
641
|
+
test("records: the ten slow reads - status log, app actions, settings (no Wi-Fi), obstacles, map versions, floor map history, zones", async () => {
|
|
642
|
+
clearOunitechCaches();
|
|
643
|
+
seen.length = 0;
|
|
644
|
+
const a = adapter();
|
|
645
|
+
const r = await a.getRecords("F8FCA9A1B1C4C");
|
|
646
|
+
assert.equal(seen.some((x) => COMMAND_PATHS.has(x.path)), false, "never a command");
|
|
647
|
+
assert.deepEqual(r.statusLog.items.map((x) => x.status), ["Charged", "Charging (mid-job)", "Cleaning"]);
|
|
648
|
+
assert.equal(r.statusLog.items[0].at, "2025-10-22T09:48:39.000Z");
|
|
649
|
+
const log = seen.find((x) => x.path === ROBOT_CLOUD_PATHS.robotLog).body;
|
|
650
|
+
assert.deepEqual([log.robotId, log.sceneId, log.pageSize], ["424", "438", 50], "robot log takes ids as strings (document)");
|
|
651
|
+
assert.deepEqual(r.appActions.items, [
|
|
652
|
+
{ at: "2025-10-20T06:22:32.000Z", action: "Stopped in place", by: "梁家茂" },
|
|
653
|
+
{ at: "2025-10-20T06:22:07.000Z", action: "Started a cleaning job", by: "梁家茂" },
|
|
654
|
+
]);
|
|
655
|
+
const json = JSON.stringify(r);
|
|
656
|
+
assert.equal(json.includes("17875645433"), false, "app user's phone number left out");
|
|
657
|
+
assert.equal(json.includes("wifi-secret-123") || json.includes("SiteWifi"), false, "Wi-Fi name/password never passed on");
|
|
658
|
+
assert.ok(r.settings.items.some((x) => x.label === "Sound level" && x.value === "80 %"));
|
|
659
|
+
assert.ok(r.settings.items.some((x) => x.label === "Robot language" && x.value === "Chinese"));
|
|
660
|
+
assert.ok(r.settings.items.some((x) => x.label === "Robot time zone" && x.value === "UTC+8"));
|
|
661
|
+
assert.ok(r.settings.items.some((x) => x.group === "Other settings" && x.label === "garbage_threshold"));
|
|
662
|
+
assert.equal(r.obstacles.items[0].image, `data:image/png;base64,${PNG_B64}`);
|
|
663
|
+
assert.deepEqual(r.mapVersions.items, [{ version: 1, latest: true, createdAt: "2025-05-28T11:06:48.000Z" }]);
|
|
664
|
+
assert.equal(seen.find((x) => x.path === ROBOT_CLOUD_PATHS.mapVersions).body.mapId, 1);
|
|
665
|
+
assert.deepEqual(r.mapHistory.items.map((x) => [x.name, x.areaM2, x.latest, x.inUse]), [["欧亚学院 2F", 6106.2, true, true], ["5楼会议室", 22.6, false, false]]);
|
|
666
|
+
assert.deepEqual(seen.find((x) => x.path === ROBOT_CLOUD_PATHS.floorMapHistory).body.floorNo, 3);
|
|
667
|
+
assert.deepEqual(r.mapLayers.items[0].zones.map((z) => z.kind), ["wall", "safe", "slow"]);
|
|
668
|
+
assert.ok(r.tasks && r.alerts, "the fast records are still there");
|
|
669
|
+
const calls = seen.length;
|
|
670
|
+
await a.getRecords("F8FCA9A1B1C4C");
|
|
671
|
+
assert.equal(seen.length, calls, "both caches serve the second read");
|
|
672
|
+
});
|
|
673
|
+
|
|
674
|
+
test("the ten reads, pure mapping from the document's replies", () => {
|
|
675
|
+
assert.deepEqual(ounitechStatusLog({ typeFlag: "15", timeFrom: "2025-10-22 16:58:56", typeName: "断点回充" }), { at: "2025-10-22T08:58:56.000Z", status: "Returning to charge (mid-job)" });
|
|
676
|
+
assert.equal(ounitechStatusLog({ typeFlag: "77", typeName: "x" }).status, "x");
|
|
677
|
+
assert.equal(ounitechAppAction({ actionName: "示教路径控制" }).action, "Controlled a taught route");
|
|
678
|
+
assert.equal(ounitechAppAction({ actionName: "新动作" }).action, "App action: 新动作", "untranslated text is labelled, never bare Chinese");
|
|
679
|
+
assert.deepEqual(ounitechSettings({ wifiName: "a", wifiPwd: "b", ok: true, msg: null, enableWorkSound: true }), [
|
|
680
|
+
{ key: "enableWorkSound", group: "Sound", label: "Sounds while working", value: "On", attention: false },
|
|
681
|
+
]);
|
|
682
|
+
assert.equal(ounitechObstacleImage({ image: "" }), null);
|
|
683
|
+
assert.equal(ounitechObstacleImage({ image: "/9j/abc" }).image, "data:image/jpeg;base64,/9j/abc");
|
|
684
|
+
assert.equal(ounitechObstacleImage({ image: "A".repeat(1_500_001) }).tooLarge, true);
|
|
685
|
+
assert.deepEqual(ounitechMapVersion({ versionNo: 3, latestFlag: false, createTime: "2025-05-28 19:06:48" }), { version: 3, latest: false, createdAt: "2025-05-28T11:06:48.000Z" });
|
|
686
|
+
assert.equal(ounitechFloorMapHistory({ mapId: 5 }).name, "Map 5");
|
|
687
|
+
const frame = { width: 200, height: 100, resolution: 0.05, originX: -1, originY: -5 };
|
|
688
|
+
assert.deepEqual(ounitechShapes(frame, "safe", [{ zoneName: "", pointList: [[0.1, 0.1], [0.5, 0.5]] }])[0].name, "Safe zone 1");
|
|
689
|
+
assert.deepEqual(ounitechShapes(null, "wall", WALLS), [], "no frame, nothing drawn");
|
|
690
|
+
assert.equal(ounitechTrack({ ...frame, mapId: "1" }, Array.from({ length: 2000 }, () => ({ x: 0, y: 0, mapid: 1 }))).length, 500, "long routes thinned to 500 points");
|
|
691
|
+
});
|
|
692
|
+
|
|
693
|
+
test("diagnose: the ten reads each answered, no Wi-Fi password, no phone number", async () => {
|
|
694
|
+
clearOunitechCaches();
|
|
695
|
+
const steps = await adapter().diagnose("F8FCA9A1B1C4C");
|
|
696
|
+
for (const name of ["virtual walls", "safe zones", "slow zones", "map versions", "floor map history", "obstacle layer", "taught route", "robot status log", "app action log", "robot settings"]) {
|
|
697
|
+
const st = steps.find((x) => x.step.startsWith(name));
|
|
698
|
+
assert.ok(st, `step ${name}`);
|
|
699
|
+
assert.equal(st.code, 0, `${name}: ${st.message}`);
|
|
700
|
+
}
|
|
701
|
+
const json = JSON.stringify(steps);
|
|
702
|
+
assert.equal(json.includes("wifi-secret-123") || json.includes("17875645433"), false);
|
|
703
|
+
assert.equal(steps.find((x) => x.step.startsWith("obstacle layer")).data.imageChars, PNG_B64.length, "image size only, not the picture");
|
|
704
|
+
});
|
|
@@ -233,6 +233,13 @@ test("diagnose: every step passes on a healthy account, with the vendor's clock"
|
|
|
233
233
|
["power schedule (halt-plan/get)", true],
|
|
234
234
|
["base station (get-station-detail-state)", true],
|
|
235
235
|
["lifts (get-lift-list)", true],
|
|
236
|
+
// This account's map has no numeric mapId, so the per-map layer reads (walls, zones, versions) are skipped.
|
|
237
|
+
["floor map history (v2405/get-floor-maplist)", true],
|
|
238
|
+
["obstacle layer (get-obstacle-layer)", true],
|
|
239
|
+
["taught route (get-teach-track)", true],
|
|
240
|
+
["robot status log, last 7 days (get-robot-log-list)", true],
|
|
241
|
+
["app action log, last 7 days (get-user-logs)", true],
|
|
242
|
+
["robot settings (get-cleaning-setting)", true],
|
|
236
243
|
["current job (robot list taskState)", true],
|
|
237
244
|
]);
|
|
238
245
|
assert.equal(seen.slice(from).some((b) => /cleanTimes|areaList|pointList|actionNo/.test(b)), false, "no command body was sent");
|