@7365admin1/core 3.130.0 → 3.131.1

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/dist/index.js CHANGED
@@ -250,6 +250,7 @@ __export(src_exports, {
250
250
  OUNITECH_BRAND: () => OUNITECH_BRAND,
251
251
  OUNITECH_BRAND_DEFINITION: () => OUNITECH_BRAND_DEFINITION,
252
252
  OUNITECH_CAPABILITIES: () => OUNITECH_CAPABILITIES,
253
+ OUNITECH_FRESH_MS: () => OUNITECH_FRESH_MS,
253
254
  OUNITECH_PENDING_COMMANDS: () => OUNITECH_PENDING_COMMANDS,
254
255
  OUNITECH_REGION_BASE_URLS: () => OUNITECH_REGION_BASE_URLS,
255
256
  OUNITECH_TIMESTAMP_FORMAT: () => OUNITECH_TIMESTAMP_FORMAT,
@@ -617,6 +618,7 @@ __export(src_exports, {
617
618
  orgRoleSets: () => orgRoleSets,
618
619
  orgSchema: () => orgSchema,
619
620
  ounitechFault: () => ounitechFault,
621
+ ounitechJobWords: () => ounitechJobWords,
620
622
  ounitechRobotFromHomeRow: () => ounitechRobotFromHomeRow,
621
623
  overnight_parking_requests_namespace_collection: () => overnight_parking_requests_namespace_collection,
622
624
  padbotAccountKey: () => padbotAccountKey,
@@ -4834,6 +4836,63 @@ function useMemberRepo() {
4834
4836
  throw error;
4835
4837
  }
4836
4838
  }
4839
+ async function peoplePage(query2, page2, limit, rowStages) {
4840
+ const noSite = { $in: ["", null] };
4841
+ const orgWide = await collection.distinct("user", {
4842
+ org: query2.org,
4843
+ type: query2.type,
4844
+ siteId: noSite,
4845
+ status: { $ne: "deleted" }
4846
+ });
4847
+ const { type: orgType, siteId: pinned, ...rest } = query2;
4848
+ const limitedRow = {
4849
+ siteId: pinned ?? { $nin: ["", null] },
4850
+ user: { $nin: orgWide }
4851
+ };
4852
+ const head = [
4853
+ // `$text` (search) may only sit in the first stage.
4854
+ { $match: { ...rest, type: { $nin: ["resident", "admin"] } } },
4855
+ { $match: pinned ? limitedRow : { $or: [{ type: orgType }, limitedRow] } },
4856
+ { $sort: { _id: -1 } },
4857
+ {
4858
+ $group: {
4859
+ _id: { $ifNull: ["$user", "$_id"] },
4860
+ doc: { $first: "$$ROOT" },
4861
+ orgWide: {
4862
+ $max: { $and: [{ $eq: ["$type", orgType] }, { $in: [{ $ifNull: ["$siteId", ""] }, ["", null]] }] }
4863
+ },
4864
+ limitedTo: { $push: { siteId: "$siteId", siteName: "$siteName", role: "$role" } }
4865
+ }
4866
+ },
4867
+ {
4868
+ $replaceRoot: {
4869
+ newRoot: { $mergeObjects: ["$doc", { limitedTo: { $cond: ["$orgWide", [], "$limitedTo"] } }] }
4870
+ }
4871
+ }
4872
+ ];
4873
+ const items = await collection.aggregate([...head, { $sort: { _id: -1 } }, { $skip: page2 * limit }, { $limit: limit }, ...rowStages]).toArray();
4874
+ const [counted] = await collection.aggregate([...head, { $count: "n" }]).toArray();
4875
+ const ids2 = (key) => [...new Set(items.flatMap((i) => (i.limitedTo ?? []).map((l) => l[key]?.toString?.() ?? "")))].filter((id) => import_mongodb14.ObjectId.isValid(id)).map((id) => new import_mongodb14.ObjectId(id));
4876
+ const [sites, roles] = await Promise.all([
4877
+ db2.collection("sites").find({ _id: { $in: ids2("siteId") } }, { projection: { name: 1 } }).toArray(),
4878
+ db2.collection("roles").find({ _id: { $in: ids2("role") } }, { projection: { name: 1 } }).toArray()
4879
+ ]);
4880
+ const nameOf = (list) => new Map(list.map((d) => [d._id.toString(), d.name ?? ""]));
4881
+ const siteName = nameOf(sites);
4882
+ const roleName = nameOf(roles);
4883
+ for (const item of items) {
4884
+ const bySite = /* @__PURE__ */ new Map();
4885
+ for (const l of item.limitedTo ?? []) {
4886
+ const site = l.siteId?.toString?.() ?? "";
4887
+ const role = roleName.get(l.role?.toString?.() ?? "") ?? "";
4888
+ const entry = bySite.get(site) ?? { siteId: site, siteName: siteName.get(site) || l.siteName || "", roleName: "" };
4889
+ entry.roleName = [entry.roleName, role].filter(Boolean).join(", ");
4890
+ bySite.set(site, entry);
4891
+ }
4892
+ item.limitedTo = [...bySite.values()].sort((a, b) => a.siteName.localeCompare(b.siteName));
4893
+ }
4894
+ return { items, length: counted?.n ?? 0 };
4895
+ }
4837
4896
  async function getAll({
4838
4897
  search = "",
4839
4898
  page: page2 = 1,
@@ -4844,7 +4903,8 @@ function useMemberRepo() {
4844
4903
  siteIds,
4845
4904
  type = "",
4846
4905
  status = "",
4847
- roleState = ""
4906
+ roleState = "",
4907
+ people = false
4848
4908
  }) {
4849
4909
  limit = limit > 0 ? limit : 10;
4850
4910
  search = search || "";
@@ -4903,6 +4963,9 @@ function useMemberRepo() {
4903
4963
  query2.$or = await otherSiteRoleClauses2(query2.org);
4904
4964
  cacheOptions.roleState = roleState;
4905
4965
  }
4966
+ const peopleMode = people && type === "organization" && !!query2.org && !siteId && !roleState;
4967
+ if (peopleMode)
4968
+ cacheOptions.people = 1;
4906
4969
  const cacheKey = (0, import_node_server_utils15.makeCacheKey)(namespace_collection3, cacheOptions);
4907
4970
  const cachedData = await getCache(cacheKey);
4908
4971
  if (cachedData) {
@@ -4910,15 +4973,7 @@ function useMemberRepo() {
4910
4973
  return cachedData;
4911
4974
  }
4912
4975
  try {
4913
- const items = await collection.aggregate([
4914
- { $match: query2 },
4915
- { $sort: { _id: -1 } },
4916
- // `paginate()` only LABELS the range ("11-20 of 42"); it does not
4917
- // slice. Without this $skip every page returned page 1's rows under
4918
- // a later page's heading. `page` is already zero-based above, and
4919
- // this is the same $skip/$limit pair the two getOrgs* reads use.
4920
- { $skip: page2 * limit },
4921
- { $limit: limit },
4976
+ const rowStages = [
4922
4977
  {
4923
4978
  $lookup: {
4924
4979
  from: "roles",
@@ -4992,11 +5047,29 @@ function useMemberRepo() {
4992
5047
  dateInvited: { $ifNull: ["$dateInvited", "$createdAt"] },
4993
5048
  siteId: 1,
4994
5049
  siteName: 1,
4995
- type: 1
5050
+ type: 1,
5051
+ limitedTo: 1
4996
5052
  }
4997
5053
  }
4998
- ]).toArray();
4999
- const length = await collection.countDocuments(query2);
5054
+ ];
5055
+ let items;
5056
+ let length;
5057
+ if (peopleMode) {
5058
+ ({ items, length } = await peoplePage(query2, page2, limit, rowStages));
5059
+ } else {
5060
+ items = await collection.aggregate([
5061
+ { $match: query2 },
5062
+ { $sort: { _id: -1 } },
5063
+ // `paginate()` only LABELS the range ("11-20 of 42"); it does not
5064
+ // slice. Without this $skip every page returned page 1's rows under
5065
+ // a later page's heading. `page` is already zero-based above, and
5066
+ // this is the same $skip/$limit pair the two getOrgs* reads use.
5067
+ { $skip: page2 * limit },
5068
+ { $limit: limit },
5069
+ ...rowStages
5070
+ ]).toArray();
5071
+ length = await collection.countDocuments(query2);
5072
+ }
5000
5073
  const data = { ...(0, import_node_server_utils15.paginate)(items, page2, limit, length), total: length };
5001
5074
  setCache(cacheKey, data, 15 * 60).then(() => {
5002
5075
  import_node_server_utils15.logger.info(`Cache set for key: ${cacheKey}`);
@@ -11183,15 +11256,15 @@ function robotConnectionText(robotName, online, minutes) {
11183
11256
  }
11184
11257
  var OFFLINE_FAULT_CODE = "OFFLINE";
11185
11258
  var SAME_OCCURRENCE_MS = 1e3;
11186
- function planFaultChanges(open, reading) {
11259
+ function planFaultChanges(open, reading2) {
11187
11260
  const byCode = new Map(open.map((r) => [r.code, r]));
11188
11261
  const want = [];
11189
- const offline = !reading.ok || reading.online === false;
11262
+ const offline = !reading2.ok || reading2.online === false;
11190
11263
  if (offline) {
11191
- const reason = reading.ok ? "" : String(reading.error ?? "").slice(0, 200);
11264
+ const reason = reading2.ok ? "" : String(reading2.error ?? "").slice(0, 200);
11192
11265
  want.push({ code: OFFLINE_FAULT_CODE, message: reason ? `Not reporting: ${reason}` : "Not reporting" });
11193
11266
  }
11194
- const fault = reading.ok && reading.fault?.code ? reading.fault : null;
11267
+ const fault = reading2.ok && reading2.fault?.code ? reading2.fault : null;
11195
11268
  if (fault)
11196
11269
  want.push({ code: fault.code, message: fault.message || fault.code, since: fault.since });
11197
11270
  const clear = [];
@@ -11223,12 +11296,12 @@ function planFaultChanges(open, reading) {
11223
11296
  return { open: toOpen, clear, refresh };
11224
11297
  }
11225
11298
  function robotFaultSweepConfig(env2 = process.env) {
11226
- const num3 = (v, def, min, max) => {
11299
+ const num4 = (v, def, min, max) => {
11227
11300
  const n = Math.floor(Number(v));
11228
11301
  return Number.isFinite(n) && String(v ?? "").trim() !== "" ? Math.min(max, Math.max(min, n)) : def;
11229
11302
  };
11230
11303
  const enabled = String(env2.ROBOT_FAULT_SWEEP ?? "on").trim().toLowerCase() !== "off";
11231
- const asked = num3(env2.ROBOT_FAULT_SWEEP_SECONDS, 60, 10, 3600);
11304
+ const asked = num4(env2.ROBOT_FAULT_SWEEP_SECONDS, 60, 10, 3600);
11232
11305
  const pick = (steps, v) => steps.filter((d) => d <= v).pop() ?? steps[0];
11233
11306
  const subMinute = asked < 60;
11234
11307
  const step = subMinute ? pick([10, 12, 15, 20, 30], asked) : pick([1, 2, 3, 4, 5, 6, 10, 12, 15, 20, 30, 60], Math.floor(asked / 60));
@@ -11238,9 +11311,9 @@ function robotFaultSweepConfig(env2 = process.env) {
11238
11311
  enabled,
11239
11312
  seconds,
11240
11313
  cron: cron2,
11241
- concurrency: num3(env2.ROBOT_FAULT_SWEEP_CONCURRENCY, 4, 1, 16),
11242
- timeoutMs: num3(env2.ROBOT_FAULT_SWEEP_TIMEOUT_MS, 1e4, 1e3, 6e4),
11243
- offlineAlertMinutes: num3(env2.ROBOT_OFFLINE_ALERT_MINUTES, 10, 1, 1440)
11314
+ concurrency: num4(env2.ROBOT_FAULT_SWEEP_CONCURRENCY, 4, 1, 16),
11315
+ timeoutMs: num4(env2.ROBOT_FAULT_SWEEP_TIMEOUT_MS, 1e4, 1e3, 6e4),
11316
+ offlineAlertMinutes: num4(env2.ROBOT_OFFLINE_ALERT_MINUTES, 10, 1, 1440)
11244
11317
  };
11245
11318
  }
11246
11319
  function withTimeout(promise, ms2, label2 = "Timed out") {
@@ -24001,6 +24074,29 @@ async function requireNotOwnerUnlessOwner(req, orgId, targetUser) {
24001
24074
  return;
24002
24075
  throw new import_node_server_utils58.UnauthorizedError("Only the organisation's owner can change the owner's access.");
24003
24076
  }
24077
+ async function requireMemberGrantor(req, input) {
24078
+ const { orgId, targetUser, roleId } = input;
24079
+ const siteId = input.siteId?.toString() ?? "";
24080
+ const id = await requireSiteAccessEditor(req, orgId);
24081
+ await requireNotOwnerUnlessOwner(req, orgId, targetUser);
24082
+ if (staffMayBypass(await resolveInviteActor(id)))
24083
+ return;
24084
+ if (siteId)
24085
+ await requireSiteServedByOrg(siteId, orgId);
24086
+ if (await hasOrgOwnership(id, orgId))
24087
+ return;
24088
+ const db2 = import_node_server_utils58.useAtlas.getDb();
24089
+ if (!db2 || !import_mongodb54.ObjectId.isValid(roleId))
24090
+ return;
24091
+ const role = await db2.collection("roles").findOne({ _id: new import_mongodb54.ObjectId(roleId) }, { projection: { permissions: 1 } });
24092
+ if (isOwnerRole(role)) {
24093
+ const rows = await db2.collection("members").find({ user: new import_mongodb54.ObjectId(id), org: new import_mongodb54.ObjectId(orgId), status: "active" }, { projection: { role: 1 } }).toArray();
24094
+ const held = rows.map((m) => m.role?.toString?.() ?? "").filter((r) => import_mongodb54.ObjectId.isValid(r)).map((r) => new import_mongodb54.ObjectId(r));
24095
+ const holdsOwner = held.length ? await db2.collection("roles").countDocuments({ _id: { $in: held }, permissions: "*", status: "active" }) : 0;
24096
+ if (!holdsOwner)
24097
+ throw new import_node_server_utils58.UnauthorizedError("Only the organisation's owner can give an owner role.");
24098
+ }
24099
+ }
24004
24100
  async function requireSiteReachInOrg(req, siteId, orgId) {
24005
24101
  if (await hasOrgOwnership(callerId(req), orgId)) {
24006
24102
  await requireSiteServedByOrg(siteId, orgId);
@@ -27025,7 +27121,7 @@ function usePersonRepo() {
27025
27121
  }
27026
27122
  async function pushVehicleById(id, plate, session) {
27027
27123
  const { plateNumber, recNo } = plate;
27028
- const updatedAt = (/* @__PURE__ */ new Date()).toISOString();
27124
+ const updatedAt2 = (/* @__PURE__ */ new Date()).toISOString();
27029
27125
  const _id = (0, import_node_server_utils64.toObjectId)(id);
27030
27126
  try {
27031
27127
  const updateExisting = await collection.updateOne(
@@ -27036,7 +27132,7 @@ function usePersonRepo() {
27036
27132
  {
27037
27133
  $set: {
27038
27134
  "plates.$.recNo": recNo,
27039
- updatedAt
27135
+ updatedAt: updatedAt2
27040
27136
  }
27041
27137
  },
27042
27138
  { session }
@@ -27052,7 +27148,7 @@ function usePersonRepo() {
27052
27148
  }
27053
27149
  },
27054
27150
  $set: {
27055
- updatedAt
27151
+ updatedAt: updatedAt2
27056
27152
  }
27057
27153
  },
27058
27154
  { session }
@@ -27063,7 +27159,7 @@ function usePersonRepo() {
27063
27159
  }
27064
27160
  }
27065
27161
  async function pullVehicleByRecNo(recNo, scope, session) {
27066
- const updatedAt = (/* @__PURE__ */ new Date()).toISOString();
27162
+ const updatedAt2 = (/* @__PURE__ */ new Date()).toISOString();
27067
27163
  const owner = scope?.peopleId ? (0, import_node_server_utils64.toObjectId)(scope.peopleId) : null;
27068
27164
  const site = scope?.site ? (0, import_node_server_utils64.toObjectId)(scope.site) : null;
27069
27165
  if (!owner && !site) {
@@ -27102,7 +27198,7 @@ function usePersonRepo() {
27102
27198
  plates: match
27103
27199
  },
27104
27200
  $set: {
27105
- updatedAt
27201
+ updatedAt: updatedAt2
27106
27202
  }
27107
27203
  },
27108
27204
  { session }
@@ -29244,7 +29340,9 @@ function useMemberController() {
29244
29340
  siteId: import_joi29.default.string().hex().optional().allow("", null),
29245
29341
  type: import_joi29.default.string().required(),
29246
29342
  status: import_joi29.default.string().required(),
29247
- roleState: import_joi29.default.string().valid("other-site").optional().allow("", null)
29343
+ roleState: import_joi29.default.string().valid("other-site").optional().allow("", null),
29344
+ // Organization app Members: every person, site-limited ones included.
29345
+ people: import_joi29.default.boolean().truthy("1").falsy("0").optional().allow("", null)
29248
29346
  });
29249
29347
  const query2 = { ...req.query };
29250
29348
  const { error } = validation.validate(query2);
@@ -29299,7 +29397,8 @@ function useMemberController() {
29299
29397
  siteIds,
29300
29398
  type,
29301
29399
  status,
29302
- roleState: req.query.roleState ?? ""
29400
+ roleState: req.query.roleState ?? "",
29401
+ people: ["1", "true"].includes(String(req.query.people ?? ""))
29303
29402
  });
29304
29403
  res.json(items);
29305
29404
  return;
@@ -29440,7 +29539,7 @@ function useMemberController() {
29440
29539
  await requireOrgReach(req, orgId);
29441
29540
  await requireSelfEnrolRole(req, orgId, roleId);
29442
29541
  } else {
29443
- await requireOrgAccess(req, orgId);
29542
+ await requireMemberGrantor(req, { orgId, targetUser: userId, roleId, siteId });
29444
29543
  }
29445
29544
  const data = await _createMemberDirect({ userId, orgId, roleId, app, siteId, siteName, onboardingRequired, callerId: callerId(req) });
29446
29545
  res.status(201).json(data);
@@ -48321,7 +48420,7 @@ var MKeyLog = class {
48321
48420
  organization = "",
48322
48421
  serviceProvider = "",
48323
48422
  createdAt = /* @__PURE__ */ new Date(),
48324
- updatedAt = /* @__PURE__ */ new Date(),
48423
+ updatedAt: updatedAt2 = /* @__PURE__ */ new Date(),
48325
48424
  template,
48326
48425
  status = "Available",
48327
48426
  updatedBy = "",
@@ -48342,7 +48441,7 @@ var MKeyLog = class {
48342
48441
  this.organization = organization;
48343
48442
  this.serviceProvider = serviceProvider;
48344
48443
  this.createdAt = createdAt;
48345
- this.updatedAt = updatedAt;
48444
+ this.updatedAt = updatedAt2;
48346
48445
  this.template = template;
48347
48446
  this.status = status;
48348
48447
  this.updatedBy = updatedBy;
@@ -56981,7 +57080,7 @@ var MAccessCard = class {
56981
57080
  isLiftCard,
56982
57081
  liftAccessLevel,
56983
57082
  createdAt,
56984
- updatedAt,
57083
+ updatedAt: updatedAt2,
56985
57084
  assignedUnit,
56986
57085
  userType,
56987
57086
  doorName,
@@ -57008,7 +57107,7 @@ var MAccessCard = class {
57008
57107
  this.isLiftCard = isLiftCard;
57009
57108
  this.liftAccessLevel = liftAccessLevel;
57010
57109
  this.createdAt = createdAt;
57011
- this.updatedAt = updatedAt;
57110
+ this.updatedAt = updatedAt2;
57012
57111
  this.assignedUnit = assignedUnit;
57013
57112
  this.userType = userType;
57014
57113
  this.doorName = doorName;
@@ -57187,8 +57286,8 @@ function encryptPayload(payloadHex) {
57187
57286
  );
57188
57287
  return encrypted.toString("base64");
57189
57288
  }
57190
- function toHex(num3, length) {
57191
- return num3.toString(16).padStart(length * 2, "0");
57289
+ function toHex(num4, length) {
57290
+ return num4.toString(16).padStart(length * 2, "0");
57192
57291
  }
57193
57292
  function buildPayload(cardNumber, validityMinutes) {
57194
57293
  const randomHex = import_crypto5.default.randomBytes(2).toString("hex");
@@ -57368,8 +57467,8 @@ function UseAccessManagementRepo() {
57368
57467
  }
57369
57468
  }
57370
57469
  function generateCardNo() {
57371
- const num3 = Math.floor(Math.random() * 65536);
57372
- return num3.toString().padStart(10, "0");
57470
+ const num4 = Math.floor(Math.random() * 65536);
57471
+ return num4.toString().padStart(10, "0");
57373
57472
  }
57374
57473
  async function createQrData({
57375
57474
  cardNumber,
@@ -58609,13 +58708,13 @@ function UseAccessManagementRepo() {
58609
58708
  const prevCard = res && res?.[1]?.cardNo || "-1";
58610
58709
  const currentCard = res && res?.[0]?.cardNo || "0";
58611
58710
  let availableCardNo = [];
58612
- let num3 = parseInt(prevCard, 10) + 1;
58711
+ let num4 = parseInt(prevCard, 10) + 1;
58613
58712
  while (availableCardNo.length < (unit.length > 0 ? unit.length : quantity)) {
58614
- if (num3 === parseInt(currentCard, 10)) {
58615
- num3++;
58713
+ if (num4 === parseInt(currentCard, 10)) {
58714
+ num4++;
58616
58715
  }
58617
- availableCardNo.push(num3);
58618
- num3++;
58716
+ availableCardNo.push(num4);
58717
+ num4++;
58619
58718
  }
58620
58719
  const cardNumbers = availableCardNo.map(
58621
58720
  (no2) => no2.toString().padStart(10, "0")
@@ -64334,13 +64433,13 @@ function parseRobotCommand(body) {
64334
64433
  if (has2(k))
64335
64434
  return { ok: false, message: `${k} is not valid for a ${kind} command.` };
64336
64435
  }
64337
- const num3 = (k) => typeof b[k] === "number" && Number.isFinite(b[k]);
64338
- if (!num3("x") || !num3("y"))
64436
+ const num4 = (k) => typeof b[k] === "number" && Number.isFinite(b[k]);
64437
+ if (!num4("x") || !num4("y"))
64339
64438
  return { ok: false, message: `${kind} needs x and y (metres).` };
64340
64439
  if (kind === "navigate") {
64341
64440
  if (has2("floorNo"))
64342
64441
  return { ok: false, message: "floorNo is not valid for a navigate command." };
64343
- if (has2("theta") && !num3("theta"))
64442
+ if (has2("theta") && !num4("theta"))
64344
64443
  return { ok: false, message: "theta must be a number (radians)." };
64345
64444
  return {
64346
64445
  ok: true,
@@ -64352,7 +64451,7 @@ function parseRobotCommand(body) {
64352
64451
  }
64353
64452
  };
64354
64453
  }
64355
- if (!num3("theta"))
64454
+ if (!num4("theta"))
64356
64455
  return { ok: false, message: "relocalize needs theta (radians)." };
64357
64456
  if (!Number.isInteger(b.floorNo))
64358
64457
  return { ok: false, message: "relocalize needs an integer floorNo." };
@@ -64776,23 +64875,81 @@ var OUNITECH_CAPABILITIES = {
64776
64875
  var OUNITECH_PENDING_COMMANDS = ["pause", "resume", "cancel"].map(
64777
64876
  (kind) => ({ kind, reason: "awaiting Ounitech's robot-control action numbers" })
64778
64877
  );
64779
- function propertyNumber(row, key) {
64780
- const p = row.robotState?.properties?.find((x) => x?.key === key);
64781
- const n = p?.value != null && String(p.value).trim() !== "" ? Number(p.value) : NaN;
64782
- return Number.isFinite(n) ? n : null;
64783
- }
64784
64878
  var finite = (v) => typeof v === "number" && Number.isFinite(v);
64785
- function ounitechRobotFromHomeRow(row) {
64786
- const st = row.robotState ?? {};
64787
- const flag = finite(st.statusFlag) ? st.statusFlag : void 0;
64788
- const online = flag !== void 0 && flag !== 99;
64879
+ function num(v) {
64880
+ if (finite(v))
64881
+ return v;
64882
+ if (typeof v === "string" && v.trim() !== "") {
64883
+ const n = Number(v);
64884
+ return Number.isFinite(n) ? n : void 0;
64885
+ }
64886
+ return void 0;
64887
+ }
64888
+ function reading(st, key) {
64889
+ const v = st.properties?.find((x) => x?.key === key)?.value;
64890
+ return v == null || String(v).trim() === "" ? void 0 : String(v).trim();
64891
+ }
64892
+ var OUNITECH_FRESH_MS = 3 * 6e4;
64893
+ var STATUS_CODE_BY_READING = {
64894
+ \u5F85\u673A: 1,
64895
+ \u7A7A\u95F2: 1,
64896
+ \u6E05\u626B\u4E2D: 2,
64897
+ \u5DE5\u4F5C\u4E2D: 2,
64898
+ \u6682\u505C: 3,
64899
+ \u6682\u505C\u4E2D: 3,
64900
+ \u5EFA\u56FE\u4E2D: 4,
64901
+ \u56DE\u5145\u4E2D: 6,
64902
+ \u8FD4\u56DE\u5145\u7535: 6,
64903
+ \u6545\u969C: 7,
64904
+ \u5F02\u5E38: 7,
64905
+ \u5145\u7535\u4E2D: 8,
64906
+ \u65AD\u70B9\u5145\u7535\u4E2D: 16,
64907
+ \u5DF2\u5145\u6EE1: 9,
64908
+ \u5145\u6EE1: 9,
64909
+ \u6025\u505C: 11,
64910
+ \u5173\u673A: 14,
64911
+ \u79BB\u7EBF: 99
64912
+ };
64913
+ var JOB_WORDS = {
64914
+ \u5DF2\u7ED3\u675F: "job finished",
64915
+ \u5DF2\u5B8C\u6210: "job finished",
64916
+ \u5B8C\u6210: "job finished",
64917
+ \u6E05\u626B\u4E2D: "job in progress",
64918
+ \u8FDB\u884C\u4E2D: "job in progress",
64919
+ \u6682\u505C: "job paused",
64920
+ \u6682\u505C\u4E2D: "job paused",
64921
+ \u672A\u5F00\u59CB: "no job started",
64922
+ \u5DF2\u53D6\u6D88: "job cancelled",
64923
+ \u53D6\u6D88: "job cancelled"
64924
+ };
64925
+ function ounitechJobWords(st) {
64926
+ const v = reading(st, "job");
64927
+ return v ? JOB_WORDS[v] ?? null : null;
64928
+ }
64929
+ function updatedAt(v) {
64930
+ const n = num(v);
64931
+ if (n !== void 0)
64932
+ return n < 1e12 ? n * 1e3 : n;
64933
+ const t = typeof v === "string" ? Date.parse(v) : NaN;
64934
+ return Number.isFinite(t) ? t : null;
64935
+ }
64936
+ function ounitechRobotFromHomeRow(row, live2, now = Date.now()) {
64937
+ const listed = row.robotState ?? {};
64938
+ const st = live2 ? { ...listed, ...live2, properties: live2.properties?.length ? live2.properties : listed.properties } : listed;
64939
+ const statusReading = reading(st, "status");
64940
+ const flag = num(st.statusFlag) ?? (statusReading ? STATUS_CODE_BY_READING[statusReading] : void 0);
64941
+ const at2 = updatedAt(st.updateOn);
64942
+ const fresh = at2 !== null && now - at2 <= OUNITECH_FRESH_MS;
64943
+ const online = flag !== 99 && (flag !== void 0 || fresh);
64789
64944
  const mode = online ? robotMode(flag) : "UNAVAILABLE";
64790
- const pct = propertyNumber(row, "battery-percent") ?? (finite(st.battery) ? st.battery : null);
64945
+ const pct = num(reading(st, "battery-percent")) ?? num(st.battery) ?? null;
64791
64946
  const task = row.taskState;
64792
64947
  const jobPct = task && String(task.statusFlag) === "1" && finite(task.accPercent) ? Math.round(task.accPercent) : null;
64793
- const words = flag === void 0 ? "Unknown" : ROBOT_STATUS_NAMES[flag] ?? `Status ${flag}`;
64948
+ const words = flag !== void 0 ? ROBOT_STATUS_NAMES[flag] ?? `Status ${flag}` : online ? "Online - status not reported" : "Unknown";
64794
64949
  const model = String(row.modelCode || row.modelName || "").trim().slice(0, 40);
64795
- return {
64950
+ const x = num(st.x);
64951
+ const y = num(st.y);
64952
+ const robot = {
64796
64953
  robotSn: row.robotSn,
64797
64954
  name: row.aliasName || row.robotName,
64798
64955
  ...model ? { model } : {},
@@ -64802,8 +64959,16 @@ function ounitechRobotFromHomeRow(row) {
64802
64959
  batteryPercent: online && pct !== null && pct >= 0 && pct <= 100 ? Math.round(pct) : null,
64803
64960
  floorNo: Number.isInteger(row.floorNo) ? row.floorNo : null,
64804
64961
  floorKnown: Number.isInteger(row.floorNo),
64805
- position: online && finite(st.x) && finite(st.y) ? { x: st.x, y: st.y, theta: finite(st.theta) ? st.theta : 0 } : null
64962
+ position: online && x !== void 0 && y !== void 0 ? { x, y, theta: num(st.theta) ?? 0 } : null
64806
64963
  };
64964
+ if (online && (flag === 7 || Array.isArray(st.rtFaultList) && st.rtFaultList.length)) {
64965
+ robot.fault = ounitechFault(st.rtFaultList);
64966
+ }
64967
+ return robot;
64968
+ }
64969
+ function needsLiveState(row) {
64970
+ const f = num(row.robotState?.statusFlag);
64971
+ return finite(row.robotId) && (f === void 0 || f === 99 || f === 7);
64807
64972
  }
64808
64973
  function ounitechFault(list) {
64809
64974
  const f = Array.isArray(list) ? list[0] : null;
@@ -64820,6 +64985,9 @@ function ounitechFault(list) {
64820
64985
  var robotTime = (d) => robotCloudTimestamp(d, "yyyy-MM-dd HH:mm:ss", "Asia/Shanghai");
64821
64986
  function createOunitechAdapter(credentials, options) {
64822
64987
  const cloud = useRobotCloudService(credentials, options);
64988
+ async function liveFor(row) {
64989
+ return needsLiveState(row) ? cloud.getRobotState(row.robotId).catch(() => null) : null;
64990
+ }
64823
64991
  async function rowFor(robotSn) {
64824
64992
  return (await cloud.getHomeRobots()).find((r) => r.robotSn === robotSn) ?? null;
64825
64993
  }
@@ -64828,7 +64996,7 @@ function createOunitechAdapter(credentials, options) {
64828
64996
  displayName: "Ounitech (Q3-G / Q3-W)",
64829
64997
  capabilities: OUNITECH_CAPABILITIES,
64830
64998
  async listRobots() {
64831
- return (await cloud.getHomeRobots()).map(ounitechRobotFromHomeRow);
64999
+ return Promise.all((await cloud.getHomeRobots()).map(async (row) => ounitechRobotFromHomeRow(row, await liveFor(row))));
64832
65000
  },
64833
65001
  async getRobot(robotSn) {
64834
65002
  const row = await rowFor(robotSn);
@@ -64844,12 +65012,7 @@ function createOunitechAdapter(credentials, options) {
64844
65012
  position: null
64845
65013
  };
64846
65014
  }
64847
- const robot = ounitechRobotFromHomeRow(row);
64848
- if (row.robotState?.statusFlag === 7 && finite(row.robotId)) {
64849
- const state = await cloud.getRobotState(row.robotId).catch(() => null);
64850
- robot.fault = ounitechFault(state?.rtFaultList);
64851
- }
64852
- return robot;
65015
+ return ounitechRobotFromHomeRow(row, await liveFor(row));
64853
65016
  },
64854
65017
  async sendCommand(robotSn, command) {
64855
65018
  const options2 = {
@@ -64964,10 +65127,19 @@ function createOunitechAdapter(credentials, options) {
64964
65127
  const window = { timeFrom: robotTime(from), timeTo: robotTime(to) };
64965
65128
  await run("live state (get-robot-state-v2.0)", ROBOT_CLOUD_PATHS.robotState, { robotId }, async () => {
64966
65129
  const s = await cloud.getRobotState(robotId);
65130
+ const r = ounitechRobotFromHomeRow(row, s);
65131
+ const level2 = (...keys) => keys.map((k) => num(reading(s, k))).find((n) => n !== void 0) ?? null;
65132
+ const at2 = updatedAt(s.updateOn);
64967
65133
  return {
65134
+ online: r.online,
65135
+ status: r.statusName,
65136
+ job: ounitechJobWords(s),
65137
+ battery: r.batteryPercent,
65138
+ cleanWater: level2("clean-water", "clean-percent"),
65139
+ dirtyWater: level2("dirty-water", "dirty-percent"),
65140
+ fault: r.fault ?? null,
64968
65141
  statusFlag: s.statusFlag,
64969
- status: finite(s.statusFlag) ? ROBOT_STATUS_NAMES[s.statusFlag] ?? null : null,
64970
- updateOn: s.updateOn ? new Date(s.updateOn).toISOString() : null,
65142
+ updateOn: at2 !== null ? new Date(at2).toISOString() : null,
64971
65143
  x: s.x,
64972
65144
  y: s.y,
64973
65145
  theta: s.theta,
@@ -66899,7 +67071,7 @@ function statesByType(entry) {
66899
67071
  }
66900
67072
  var PADBOT_ONLINE_WINDOW_MS = 12e4;
66901
67073
  var ms = (t) => typeof t === "string" ? Date.parse(t) : NaN;
66902
- var num = (v) => typeof v === "number" && Number.isFinite(v) ? v : null;
67074
+ var num2 = (v) => typeof v === "number" && Number.isFinite(v) ? v : null;
66903
67075
  function padbotMode(states, now = Date.now()) {
66904
67076
  const hb = ms(states["1000"]?.updatedAt);
66905
67077
  const online = Number.isFinite(hb) && now - hb <= PADBOT_ONLINE_WINDOW_MS;
@@ -66907,7 +67079,7 @@ function padbotMode(states, now = Date.now()) {
66907
67079
  return { online: false, mode: "UNAVAILABLE", statusName: "Not reporting to PadBot" };
66908
67080
  const nav = states["1003"] ?? {};
66909
67081
  const work = states["1010"] ?? {};
66910
- const battery = num(states["1001"]?.batteryPercent);
67082
+ const battery = num2(states["1001"]?.batteryPercent);
66911
67083
  const charging = states["1002"]?.chargingState === 1;
66912
67084
  const type = Number(nav.actionType) || 0;
66913
67085
  const st = Number(nav.actionState) || 0;
@@ -66944,7 +67116,7 @@ function padbotCommandBlock(states, kind, now = Date.now()) {
66944
67116
  return "The robot is not reporting to PadBot, so it cannot take a command. Check it is switched on and connected.";
66945
67117
  if (states["1006"]?.emergencyStopState === 1)
66946
67118
  return "The robot's emergency stop button is pressed. Release the red button on the robot, then try again.";
66947
- const battery = num(states["1001"]?.batteryPercent);
67119
+ const battery = num2(states["1001"]?.batteryPercent);
66948
67120
  if (kind !== "return" && battery !== null && battery < 10)
66949
67121
  return `The battery is at ${battery}%. PadBot robots do not start jobs under 10%; send it to charge first.`;
66950
67122
  if (kind === "return" && [1, 2].includes(states["1002"]?.chargingState))
@@ -66966,7 +67138,7 @@ function padbotReadiness(states, now = Date.now()) {
66966
67138
  heartbeatAt: st["1000"]?.updatedAt ?? null,
66967
67139
  emergencyStopPressed: es.emergencyStopState === 1,
66968
67140
  wheelLockState: es.wheelLockState ?? null,
66969
- batteryPercent: num(st["1001"]?.batteryPercent),
67141
+ batteryPercent: num2(st["1001"]?.batteryPercent),
66970
67142
  chargingState: charging ?? null,
66971
67143
  map: { id: st["1007"]?.mapId ?? null, name: st["1007"]?.mapDisplayName ?? null, floor: st["1007"]?.floor ?? null },
66972
67144
  navigation: { actionType: nav.actionType ?? null, actionState: nav.actionState ?? null, message: nav.message ?? null, updatedAt: nav.updatedAt ?? null },
@@ -67023,19 +67195,19 @@ function padbotMotion(m, now) {
67023
67195
  }
67024
67196
  function networkText(net) {
67025
67197
  const say = (label2, v) => v < 0 ? ` \xB7 ${label2} ${v} dBm` : ` \xB7 ${label2} signal ${v}`;
67026
- const wifi = num(net?.wifi?.signalStrength);
67198
+ const wifi = num2(net?.wifi?.signalStrength);
67027
67199
  if (wifi !== null)
67028
67200
  return say("Wi-Fi", wifi);
67029
- const cell = num(net?.cellular?.signalStrength);
67201
+ const cell = num2(net?.cellular?.signalStrength);
67030
67202
  return cell !== null ? say("Mobile", cell) : "";
67031
67203
  }
67032
67204
  function padbotPlanShare(frame2, x, y) {
67033
- const w = num(frame2?.width), h = num(frame2?.height), r = num(frame2?.resolution);
67034
- const wx = num(x), wy = num(y);
67205
+ const w = num2(frame2?.width), h = num2(frame2?.height), r = num2(frame2?.resolution);
67206
+ const wx = num2(x), wy = num2(y);
67035
67207
  if (!w || !h || !r || r <= 0 || wx === null || wy === null)
67036
67208
  return null;
67037
- const px = (wx - (num(frame2?.originX) ?? 0)) / r;
67038
- const pyUp = (wy - (num(frame2?.originY) ?? 0)) / r;
67209
+ const px = (wx - (num2(frame2?.originX) ?? 0)) / r;
67210
+ const pyUp = (wy - (num2(frame2?.originY) ?? 0)) / r;
67039
67211
  const sx = px / w * 100, sy = 100 - pyUp / h * 100;
67040
67212
  if (sx < 0 || sx > 100 || sy < 0 || sy > 100)
67041
67213
  return null;
@@ -67065,9 +67237,9 @@ function padbotCurrentMap(maps, ids2, floor) {
67065
67237
  }
67066
67238
  function padbotChargingPoint(map) {
67067
67239
  const piles = (Array.isArray(map?.targetPoints) ? map.targetPoints : []).filter(
67068
- (t) => Number(t?.targetPointType) === 10 && num(t?.worldX) !== null && num(t?.worldY) !== null
67240
+ (t) => Number(t?.targetPointType) === 10 && num2(t?.worldX) !== null && num2(t?.worldY) !== null
67069
67241
  );
67070
- return piles.length === 1 ? { worldX: num(piles[0].worldX), worldY: num(piles[0].worldY), yaw: piles[0].yaw } : null;
67242
+ return piles.length === 1 ? { worldX: num2(piles[0].worldX), worldY: num2(piles[0].worldY), yaw: piles[0].yaw } : null;
67071
67243
  }
67072
67244
  var PADBOT_OTHER_MAP_TEXT = "The robot must be on this map first.";
67073
67245
  function padbotAlarmFault(alarm) {
@@ -67162,9 +67334,9 @@ function padbotPatrolRecord(r) {
67162
67334
  result: PATROL_RESULT[r?.completionState] ?? "unknown",
67163
67335
  startedAt: r?.startedAt ?? null,
67164
67336
  endedAt: r?.endedAt ?? null,
67165
- durationS: num(r?.duration),
67166
- distanceM: num(r?.mileage),
67167
- alarmCount: num(r?.alarmCount) ?? 0
67337
+ durationS: num2(r?.duration),
67338
+ distanceM: num2(r?.mileage),
67339
+ alarmCount: num2(r?.alarmCount) ?? 0
67168
67340
  };
67169
67341
  }
67170
67342
  function padbotCheckpointVisit(d) {
@@ -67174,15 +67346,15 @@ function padbotCheckpointVisit(d) {
67174
67346
  skipped: d?.skipped === true,
67175
67347
  imageUrl: d?.visibleLightImageUrl ?? null,
67176
67348
  thermalImageUrl: d?.thermalImageUrl ?? null,
67177
- centerTempC: num(d?.centerTemperature),
67178
- maxTempC: num(d?.maxTemperature)
67349
+ centerTempC: num2(d?.centerTemperature),
67350
+ maxTempC: num2(d?.maxTemperature)
67179
67351
  };
67180
67352
  }
67181
67353
  var asList = (d) => Array.isArray(d) ? d : Array.isArray(d?.items) ? d.items : Array.isArray(d?.list) ? d.list : Array.isArray(d?.records) ? d.records : [];
67182
67354
  var page = (data, map) => ({
67183
67355
  items: (Array.isArray(data?.items) ? data.items : []).map(map),
67184
- total: num(data?.totalItems) ?? 0,
67185
- pages: num(data?.totalPages) ?? 0
67356
+ total: num2(data?.totalItems) ?? 0,
67357
+ pages: num2(data?.totalPages) ?? 0
67186
67358
  });
67187
67359
  function createPadbotClient(credentials, options = {}) {
67188
67360
  const baseUrl = (options.baseUrl ?? padbotBaseUrl()).replace(/\/+$/, "");
@@ -67404,7 +67576,7 @@ function createPadbotAdapter(credentials, options = {}) {
67404
67576
  const { online, mode, statusName } = padbotMode(st, now());
67405
67577
  const floor = st["1007"]?.floor;
67406
67578
  const restBatteryAt = ms(st["1001"]?.updatedAt);
67407
- const battery = heard?.batteryPercent !== void 0 && (!Number.isFinite(restBatteryAt) || (heard.batteryAt ?? 0) > restBatteryAt) ? heard.batteryPercent : num(st["1001"]?.batteryPercent);
67579
+ const battery = heard?.batteryPercent !== void 0 && (!Number.isFinite(restBatteryAt) || (heard.batteryAt ?? 0) > restBatteryAt) ? heard.batteryPercent : num2(st["1001"]?.batteryPercent);
67408
67580
  const failed = lastFailure.get(`${account}:${robotSn}`);
67409
67581
  const showFailure = online && failed && now() - failed.at < PADBOT_FAILURE_SHOW_MS && /^(Standing by|Charging)/.test(statusName);
67410
67582
  const robot = {
@@ -67431,15 +67603,15 @@ function createPadbotAdapter(credentials, options = {}) {
67431
67603
  return robot;
67432
67604
  const [loc, openA] = await Promise.all([locRead, alarmRead]);
67433
67605
  const alarm = robot.fault ? null : openA;
67434
- const lx = num(loc?.worldX ?? loc?.x);
67435
- const ly = num(loc?.worldY ?? loc?.y);
67606
+ const lx = num2(loc?.worldX ?? loc?.x);
67607
+ const ly = num2(loc?.worldY ?? loc?.y);
67436
67608
  if (typeof loc?.mapId === "string" && loc.mapId)
67437
67609
  robot.mapId = loc.mapId;
67438
67610
  const map = await maps(robotSn).then((all) => padbotCurrentMap(all, [robot.mapId, st["1007"]?.mapId], robot.floorNo)).catch(() => null);
67439
67611
  if (map)
67440
67612
  robot.mapId = map.mapId;
67441
67613
  if (lx !== null && ly !== null) {
67442
- robot.position = { x: lx, y: ly, theta: (num(loc.yaw ?? loc.r) ?? 0) * Math.PI / 180 };
67614
+ robot.position = { x: lx, y: ly, theta: (num2(loc.yaw ?? loc.r) ?? 0) * Math.PI / 180 };
67443
67615
  robot.planPosition = padbotPlanShare(map, lx, ly);
67444
67616
  }
67445
67617
  const mo = motions.get(`${account}:${robotSn}`);
@@ -67459,7 +67631,7 @@ function createPadbotAdapter(credentials, options = {}) {
67459
67631
  const onCharger = [1, 2].includes(st["1002"]?.chargingState);
67460
67632
  const pile = onCharger && !robot.position ? padbotChargingPoint(map) : null;
67461
67633
  if (pile) {
67462
- robot.position = { x: pile.worldX, y: pile.worldY, theta: (num(pile.yaw) ?? 0) * Math.PI / 180 };
67634
+ robot.position = { x: pile.worldX, y: pile.worldY, theta: (num2(pile.yaw) ?? 0) * Math.PI / 180 };
67463
67635
  robot.planPosition = padbotPlanShare(map, pile.worldX, pile.worldY);
67464
67636
  if (!going || going.done)
67465
67637
  robot.statusName = `${robot.statusName} \xB7 At charger`;
@@ -67559,12 +67731,12 @@ function createPadbotAdapter(credentials, options = {}) {
67559
67731
  throw new import_node_server_utils164.BadRequestError(block);
67560
67732
  lastFailure.delete(`${account}:${robotSn}`);
67561
67733
  const heard = padbotLive(account, robotSn)?.pose;
67562
- const lx = num(where?.loc?.worldX);
67563
- const ly = num(where?.loc?.worldY);
67734
+ const lx = num2(where?.loc?.worldX);
67735
+ const ly = num2(where?.loc?.worldY);
67564
67736
  let target = null;
67565
67737
  if (command.kind === "go-to-point") {
67566
67738
  const pt = (where?.all ?? []).flatMap((m) => Array.isArray(m?.targetPoints) ? m.targetPoints : []).find((t) => t?.targetPointId === command.targetPointId);
67567
- target = { name: String(pt?.name || "the chosen point"), x: num(pt?.worldX), y: num(pt?.worldY) };
67739
+ target = { name: String(pt?.name || "the chosen point"), x: num2(pt?.worldX), y: num2(pt?.worldY) };
67568
67740
  }
67569
67741
  motion = {
67570
67742
  kind: command.kind,
@@ -68616,11 +68788,11 @@ function decodeTrackingFrame(data) {
68616
68788
  if (!parsed || typeof parsed !== "object")
68617
68789
  return null;
68618
68790
  const frame2 = parsed;
68619
- const num3 = (v) => typeof v === "number" && Number.isFinite(v) ? v : null;
68620
- const x = num3(frame2.x);
68621
- const y = num3(frame2.y);
68622
- const theta = num3(frame2.theta);
68623
- const statusFlag = num3(frame2.status);
68791
+ const num4 = (v) => typeof v === "number" && Number.isFinite(v) ? v : null;
68792
+ const x = num4(frame2.x);
68793
+ const y = num4(frame2.y);
68794
+ const theta = num4(frame2.theta);
68795
+ const statusFlag = num4(frame2.status);
68624
68796
  if (x === null || y === null || theta === null || statusFlag === null) {
68625
68797
  return null;
68626
68798
  }
@@ -69144,22 +69316,22 @@ function useRobotFaultSweep(deps) {
69144
69316
  if (!robot)
69145
69317
  return;
69146
69318
  out.robots++;
69147
- let reading;
69319
+ let reading2;
69148
69320
  try {
69149
69321
  const state = deps?.readState ? await deps.readState(robot) : await readRobotState(robot, { timeoutMs: cfg.timeoutMs });
69150
69322
  if (deps?.readState)
69151
69323
  rememberRobotState(robot, state);
69152
- reading = { ok: true, online: state.online === true, fault: state.fault ?? null };
69153
- if (reading.fault)
69154
- Object.assign(reading.fault, { floorNo: state.floorNo ?? null });
69324
+ reading2 = { ok: true, online: state.online === true, fault: state.fault ?? null };
69325
+ if (reading2.fault)
69326
+ Object.assign(reading2.fault, { floorNo: state.floorNo ?? null });
69155
69327
  } catch (error) {
69156
69328
  if (deps?.readState)
69157
69329
  rememberRobotState(robot, null);
69158
- reading = { ok: false, error: error?.message ?? "no answer" };
69330
+ reading2 = { ok: false, error: error?.message ?? "no answer" };
69159
69331
  }
69160
69332
  const records = byRobot2.get(String(robot._id)) ?? [];
69161
69333
  const offlineRec = records.find((r) => r.code === OFFLINE_FAULT_CODE);
69162
- const plan = planFaultChanges(records, reading);
69334
+ const plan = planFaultChanges(records, reading2);
69163
69335
  for (const id of plan.clear) {
69164
69336
  await repo.clearFault(id);
69165
69337
  out.cleared++;
@@ -69172,7 +69344,7 @@ function useRobotFaultSweep(deps) {
69172
69344
  out.alerts++;
69173
69345
  }
69174
69346
  for (const f of plan.open) {
69175
- const detail = reading.ok && reading.fault?.code === f.code ? reading.fault : null;
69347
+ const detail = reading2.ok && reading2.fault?.code === f.code ? reading2.fault : null;
69176
69348
  const r = await openFaultRecord(robot, detail ? { ...detail, ...f } : f, { notify: true, notifyFn: deps?.notifyFn });
69177
69349
  if (r.opened)
69178
69350
  out.opened++;
@@ -70490,7 +70662,7 @@ function measurementScale(vertices, meas) {
70490
70662
  return est.length ? est.reduce((n, v) => n + v, 0) / est.length : null;
70491
70663
  }
70492
70664
  var pval = (p) => Array.isArray(p) ? p[1] : p;
70493
- var num2 = (v, fallback = 0) => v !== null && v !== "" && Number.isFinite(Number(v)) ? Number(v) : fallback;
70665
+ var num3 = (v, fallback = 0) => v !== null && v !== "" && Number.isFinite(Number(v)) ? Number(v) : fallback;
70494
70666
  var str60 = (v) => String(v ?? "").slice(0, 60);
70495
70667
  function decodeParams(raw) {
70496
70668
  const out = {};
@@ -70510,7 +70682,7 @@ function fileVertexParams(raw) {
70510
70682
  const v = raw[k];
70511
70683
  if (v === void 0 || v === null)
70512
70684
  continue;
70513
- out[k] = k.startsWith("is_") ? Boolean(v) : k === "merge_radius" ? clamp3(num2(v), 0, 100) : str60(v);
70685
+ out[k] = k.startsWith("is_") ? Boolean(v) : k === "merge_radius" ? clamp3(num3(v), 0, 100) : str60(v);
70514
70686
  }
70515
70687
  return out;
70516
70688
  }
@@ -70583,14 +70755,14 @@ function fromBuildingYaml(doc) {
70583
70755
  const raw = names.map((name) => {
70584
70756
  const y = doc.levels[name] ?? {};
70585
70757
  const vertices = (Array.isArray(y.vertices) ? y.vertices : []).map((v) => ({
70586
- x: num2(v?.[0]),
70587
- y: num2(v?.[1]) * flip,
70758
+ x: num3(v?.[0]),
70759
+ y: num3(v?.[1]) * flip,
70588
70760
  name: str60(v?.[3]),
70589
70761
  params: fileVertexParams(decodeParams(v?.[4]))
70590
70762
  }));
70591
- const fiducials = (Array.isArray(y.fiducials) ? y.fiducials : []).map((f) => ({ x: num2(f?.[0]), y: num2(f?.[1]) * flip, name: str60(f?.[2]) }));
70592
- const meas = edgeList(y.measurements).map((e) => [e.a, e.b, num2(e.p.distance)]);
70593
- return { name: str60(name), y, vertices, fiducials, meas, elevation: num2(y.elevation) };
70763
+ const fiducials = (Array.isArray(y.fiducials) ? y.fiducials : []).map((f) => ({ x: num3(f?.[0]), y: num3(f?.[1]) * flip, name: str60(f?.[2]) }));
70764
+ const meas = edgeList(y.measurements).map((e) => [e.a, e.b, num3(e.p.distance)]);
70765
+ return { name: str60(name), y, vertices, fiducials, meas, elevation: num3(y.elevation) };
70594
70766
  });
70595
70767
  const refName = raw.some((l) => l.name === doc.reference_level_name) ? String(doc.reference_level_name) : raw[0].name;
70596
70768
  const ref = raw.find((l) => l.name === refName);
@@ -70664,20 +70836,20 @@ function fromBuildingYaml(doc) {
70664
70836
  const extra = {};
70665
70837
  if (e.p.texture_name !== void 0 && e.p.texture_name !== "default")
70666
70838
  extra.textureName = str60(e.p.texture_name);
70667
- if (e.p.alpha !== void 0 && num2(e.p.alpha, 1) !== 1)
70668
- extra.alpha = clamp3(num2(e.p.alpha, 1), 0, 1);
70669
- if (e.p.texture_height !== void 0 && num2(e.p.texture_height, 2.5) !== 2.5)
70670
- extra.textureHeight = clamp3(num2(e.p.texture_height, 2.5), 0, 100);
70671
- if (e.p.texture_width !== void 0 && num2(e.p.texture_width, 1) !== 1)
70672
- extra.textureWidth = clamp3(num2(e.p.texture_width, 1), 0, 100);
70673
- if (e.p.texture_scale !== void 0 && num2(e.p.texture_scale, 1) !== 1)
70674
- extra.textureScale = clamp3(num2(e.p.texture_scale, 1), 0, 100);
70839
+ if (e.p.alpha !== void 0 && num3(e.p.alpha, 1) !== 1)
70840
+ extra.alpha = clamp3(num3(e.p.alpha, 1), 0, 1);
70841
+ if (e.p.texture_height !== void 0 && num3(e.p.texture_height, 2.5) !== 2.5)
70842
+ extra.textureHeight = clamp3(num3(e.p.texture_height, 2.5), 0, 100);
70843
+ if (e.p.texture_width !== void 0 && num3(e.p.texture_width, 1) !== 1)
70844
+ extra.textureWidth = clamp3(num3(e.p.texture_width, 1), 0, 100);
70845
+ if (e.p.texture_scale !== void 0 && num3(e.p.texture_scale, 1) !== 1)
70846
+ extra.textureScale = clamp3(num3(e.p.texture_scale, 1), 0, 100);
70675
70847
  level2.walls.push({ v1: ids2[e.a], v2: ids2[e.b], ...extra });
70676
70848
  }
70677
70849
  for (const e of edgeList(lv.y.doors).filter(ok)) {
70678
70850
  const type = String(e.p.type ?? "hinged");
70679
- const degrees = clamp3(num2(e.p.motion_degrees, 90), -360, 360);
70680
- const ratio = clamp3(num2(e.p.right_left_ratio, 1), 0, 10);
70851
+ const degrees = clamp3(num3(e.p.motion_degrees, 90), -360, 360);
70852
+ const ratio = clamp3(num3(e.p.right_left_ratio, 1), 0, 10);
70681
70853
  const plugin = str60(e.p.plugin ?? "normal");
70682
70854
  level2.doors.push({
70683
70855
  name: str60(e.p.name ?? "").trim() || `door_${level2.doors.length + 1}`,
@@ -70686,13 +70858,13 @@ function fromBuildingYaml(doc) {
70686
70858
  type: ["hinged", "double_hinged", "sliding", "double_sliding"].includes(type) ? type : "hinged",
70687
70859
  ...e.p.motion_axis === "end" ? { motionAxis: "end" } : {},
70688
70860
  ...degrees !== 90 ? { motionDegrees: degrees } : {},
70689
- ...num2(e.p.motion_direction, 1) < 0 ? { motionDirection: -1 } : {},
70861
+ ...num3(e.p.motion_direction, 1) < 0 ? { motionDirection: -1 } : {},
70690
70862
  ...ratio !== 1 ? { rightLeftRatio: ratio } : {},
70691
70863
  ...plugin !== "normal" ? { plugin } : {}
70692
70864
  });
70693
70865
  }
70694
70866
  for (const e of edgeList(lv.y.lanes).filter(ok)) {
70695
- const gi = Math.round(num2(e.p.graph_idx, 0));
70867
+ const gi = Math.round(num3(e.p.graph_idx, 0));
70696
70868
  if (gi < 0 || gi > 8) {
70697
70869
  warnings.push(`Floor ${lv.name}: a lane on graph ${gi} was skipped (graphs 0-8 only).`);
70698
70870
  continue;
@@ -70705,14 +70877,14 @@ function fromBuildingYaml(doc) {
70705
70877
  graphIdx: gi,
70706
70878
  bidirectional: e.p.bidirectional === true,
70707
70879
  ...orientation ? { orientation } : {},
70708
- ...num2(e.p.speed_limit) > 0 ? { speedLimit: clamp3(num2(e.p.speed_limit), 0, 20) } : {},
70880
+ ...num3(e.p.speed_limit) > 0 ? { speedLimit: clamp3(num3(e.p.speed_limit), 0, 20) } : {},
70709
70881
  ...e.p.mutex ? { mutex: str60(e.p.mutex) } : {},
70710
70882
  ...e.p.demo_mock_floor_name ? { demoMockFloorName: str60(e.p.demo_mock_floor_name) } : {},
70711
70883
  ...e.p.demo_mock_lift_name ? { demoMockLiftName: str60(e.p.demo_mock_lift_name) } : {}
70712
70884
  });
70713
70885
  }
70714
70886
  for (const e of edgeList(lv.y.measurements).filter(ok)) {
70715
- const d = num2(e.p.distance);
70887
+ const d = num3(e.p.distance);
70716
70888
  if (d >= 0.01)
70717
70889
  level2.measurements.push({ v1: ids2[e.a], v2: ids2[e.b], distanceM: Math.min(d, 1e4) });
70718
70890
  }
@@ -70743,14 +70915,14 @@ function fromBuildingYaml(doc) {
70743
70915
  if (ly?.reference_floor_name && !levelNames.has(ly.reference_floor_name)) {
70744
70916
  warnings.push(`Lift ${str60(liftName)}: its reference floor "${str60(ly.reference_floor_name)}" is not in the file; ${refName} was used.`);
70745
70917
  }
70746
- const c = applyXform(xf(refFloor), { x: num2(ly?.x), y: num2(ly?.y) * flip });
70918
+ const c = applyXform(xf(refFloor), { x: num3(ly?.x), y: num3(ly?.y) * flip });
70747
70919
  const doors = Object.entries(ly?.doors ?? {}).slice(0, 8).map(([dn, d]) => ({
70748
70920
  name: str60(dn),
70749
- type: MSG_LIFT_DOOR_TYPE[Math.round(num2(d?.door_type, 2))] ?? "double_sliding",
70750
- x: r3(clamp3(num2(d?.x), -20, 20)),
70751
- y: r3(clamp3(num2(d?.y), -20, 20)),
70752
- widthM: r3(clamp3(num2(d?.width, 1), 0.3, 10)),
70753
- axisYawRad: clamp3(num2(d?.motion_axis_orientation), -10, 10)
70921
+ type: MSG_LIFT_DOOR_TYPE[Math.round(num3(d?.door_type, 2))] ?? "double_sliding",
70922
+ x: r3(clamp3(num3(d?.x), -20, 20)),
70923
+ y: r3(clamp3(num3(d?.y), -20, 20)),
70924
+ widthM: r3(clamp3(num3(d?.width, 1), 0.3, 10)),
70925
+ axisYawRad: clamp3(num3(d?.motion_axis_orientation), -10, 10)
70754
70926
  }));
70755
70927
  const doorNames = new Set(doors.map((d) => d.name));
70756
70928
  const levelDoors = Object.entries(ly?.level_doors ?? {}).filter(([level2]) => levelNames.has(level2)).map(([level2, list]) => ({ level: level2, doors: (Array.isArray(list) ? list : []).map(str60).filter((d) => doorNames.has(d)) }));
@@ -70759,9 +70931,9 @@ function fromBuildingYaml(doc) {
70759
70931
  name: str60(liftName),
70760
70932
  x: r3(c.x),
70761
70933
  y: r3(c.y),
70762
- yawRad: clamp3(num2(ly?.yaw), -10, 10),
70763
- widthM: r3(clamp3(num2(ly?.width, 2), 0.3, 20)),
70764
- depthM: r3(clamp3(num2(ly?.depth, 2), 0.3, 20)),
70934
+ yawRad: clamp3(num3(ly?.yaw), -10, 10),
70935
+ widthM: r3(clamp3(num3(ly?.width, 2), 0.3, 20)),
70936
+ depthM: r3(clamp3(num3(ly?.depth, 2), 0.3, 20)),
70765
70937
  referenceFloor: refFloor,
70766
70938
  ...floorName(ly?.initial_floor_name) ? { initialFloor: floorName(ly.initial_floor_name) } : {},
70767
70939
  ...floorName(ly?.lowest_floor) ? { lowestFloor: floorName(ly.lowest_floor) } : {},
@@ -70815,7 +70987,7 @@ function fromNavGraph(doc, graphIdx) {
70815
70987
  level2.vertices = verts.map((v, k) => {
70816
70988
  const p = v?.[2] && typeof v[2] === "object" ? v[2] : {};
70817
70989
  const params = fileVertexParams(p);
70818
- return { id: `v${k + 1}`, x: r3(num2(v?.[0])), y: r3(num2(v?.[1])), ...p.name ? { name: str60(p.name) } : {}, ...Object.keys(params).length ? { params } : {} };
70990
+ return { id: `v${k + 1}`, x: r3(num3(v?.[0])), y: r3(num3(v?.[1])), ...p.name ? { name: str60(p.name) } : {}, ...Object.keys(params).length ? { params } : {} };
70819
70991
  });
70820
70992
  if (Array.isArray(ly?.lanes) && ly.lanes.length > 1e4)
70821
70993
  throw new RmfImportError(`Floor ${str60(name)} has more than 10000 one-way lanes - more than a building map can hold.`);
@@ -70855,7 +71027,7 @@ function fromNavGraph(doc, graphIdx) {
70855
71027
  graphIdx,
70856
71028
  bidirectional,
70857
71029
  ...o === "forward" || o === "backward" ? { orientation: o } : {},
70858
- ...num2(p.speed_limit) > 0 ? { speedLimit: clamp3(num2(p.speed_limit), 0, 20) } : {},
71030
+ ...num3(p.speed_limit) > 0 ? { speedLimit: clamp3(num3(p.speed_limit), 0, 20) } : {},
70859
71031
  ...p.mutex ? { mutex: str60(p.mutex) } : {},
70860
71032
  ...p.demo_mock_floor_name ? { demoMockFloorName: str60(p.demo_mock_floor_name) } : {},
70861
71033
  ...p.demo_mock_lift_name ? { demoMockLiftName: str60(p.demo_mock_lift_name) } : {}
@@ -83074,7 +83246,7 @@ function useAccessManagementController() {
83074
83246
  liftName,
83075
83247
  unit = [],
83076
83248
  createdAt,
83077
- updatedAt,
83249
+ updatedAt: updatedAt2,
83078
83250
  startDate,
83079
83251
  endDate,
83080
83252
  isWinsland
@@ -83110,7 +83282,7 @@ function useAccessManagementController() {
83110
83282
  startDate,
83111
83283
  endDate,
83112
83284
  createdAt,
83113
- updatedAt,
83285
+ updatedAt: updatedAt2,
83114
83286
  isWinsland
83115
83287
  });
83116
83288
  if (error) {
@@ -83132,7 +83304,7 @@ function useAccessManagementController() {
83132
83304
  startDate,
83133
83305
  endDate,
83134
83306
  createdAt,
83135
- updatedAt,
83307
+ updatedAt: updatedAt2,
83136
83308
  isWinsland
83137
83309
  });
83138
83310
  return res.status(201).json({
@@ -106835,6 +107007,7 @@ function usePersonalEmergencyChainController() {
106835
107007
  OUNITECH_BRAND,
106836
107008
  OUNITECH_BRAND_DEFINITION,
106837
107009
  OUNITECH_CAPABILITIES,
107010
+ OUNITECH_FRESH_MS,
106838
107011
  OUNITECH_PENDING_COMMANDS,
106839
107012
  OUNITECH_REGION_BASE_URLS,
106840
107013
  OUNITECH_TIMESTAMP_FORMAT,
@@ -107202,6 +107375,7 @@ function usePersonalEmergencyChainController() {
107202
107375
  orgRoleSets,
107203
107376
  orgSchema,
107204
107377
  ounitechFault,
107378
+ ounitechJobWords,
107205
107379
  ounitechRobotFromHomeRow,
107206
107380
  overnight_parking_requests_namespace_collection,
107207
107381
  padbotAccountKey,