myio-js-library 0.1.526 → 0.1.528
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.cjs +434 -31
- package/dist/index.d.cts +228 -8
- package/dist/index.d.ts +228 -8
- package/dist/index.js +423 -31
- package/dist/myio-js-library.umd.js +421 -31
- package/dist/myio-js-library.umd.min.js +1 -1
- package/package.json +3 -1
package/dist/index.cjs
CHANGED
|
@@ -53,6 +53,8 @@ __export(src_exports, {
|
|
|
53
53
|
AlarmsSummaryTooltip: () => AlarmsSummaryTooltip,
|
|
54
54
|
AnnotationIndicator: () => AnnotationIndicator,
|
|
55
55
|
AnnotationTooltip: () => AnnotationTooltip,
|
|
56
|
+
BAKED_PROFILE_KEYS: () => BAKED_PROFILE_KEYS,
|
|
57
|
+
BAKED_PROFILE_VERSION: () => BAKED_PROFILE_VERSION,
|
|
56
58
|
BASDashboardController: () => BASDashboardController,
|
|
57
59
|
BASDashboardView: () => BASDashboardView,
|
|
58
60
|
BAS_DASHBOARD_CSS_PREFIX: () => BAS_DASHBOARD_CSS_PREFIX,
|
|
@@ -375,6 +377,7 @@ __export(src_exports, {
|
|
|
375
377
|
createAmbienteGroupModal: () => createAmbienteGroupModal,
|
|
376
378
|
createAnnotationIndicator: () => createAnnotationIndicator,
|
|
377
379
|
createBASDashboard: () => createBASDashboard,
|
|
380
|
+
createBakedProfileSource: () => createBakedProfileSource,
|
|
378
381
|
createButtonBar: () => createButtonBar,
|
|
379
382
|
createConsumption7DaysChart: () => createConsumption7DaysChart,
|
|
380
383
|
createConsumptionChartWidget: () => createConsumptionChartWidget,
|
|
@@ -486,8 +489,10 @@ __export(src_exports, {
|
|
|
486
489
|
fetchThingsboardCustomerAttrsFromStorage: () => fetchThingsboardCustomerAttrsFromStorage,
|
|
487
490
|
fetchThingsboardCustomerServerScopeAttrs: () => fetchThingsboardCustomerServerScopeAttrs,
|
|
488
491
|
fetchTicketsForDevice: () => fetchTicketsForDevice,
|
|
492
|
+
findNode: () => findNode,
|
|
489
493
|
findValue: () => findValue,
|
|
490
494
|
findValueWithDefault: () => findValueWithDefault,
|
|
495
|
+
flattenTree: () => flattenTree,
|
|
491
496
|
fmtPerc: () => fmtPerc,
|
|
492
497
|
fmtPercLegacy: () => fmtPerc2,
|
|
493
498
|
formatAlarmRelativeTime: () => formatAlarmRelativeTime,
|
|
@@ -620,6 +625,7 @@ __export(src_exports, {
|
|
|
620
625
|
isAlarmActive: () => isAlarmActive,
|
|
621
626
|
isAnnotationOverdue: () => isOverdue,
|
|
622
627
|
isAssetCode: () => isAssetCode,
|
|
628
|
+
isBakedStale: () => isBakedStale,
|
|
623
629
|
isConnectionStale: () => isConnectionStale,
|
|
624
630
|
isCustomerCode: () => isCustomerCode,
|
|
625
631
|
isDeviceIconType: () => isDeviceIconType,
|
|
@@ -640,6 +646,7 @@ __export(src_exports, {
|
|
|
640
646
|
isValidDeviceStatus: () => isValidDeviceStatus,
|
|
641
647
|
isValidTimeFormat: () => isValidTimeFormat,
|
|
642
648
|
isWaterCategory: () => isWaterCategory,
|
|
649
|
+
liftProfileToTree: () => liftProfileToTree,
|
|
643
650
|
listDomains: () => listDomains,
|
|
644
651
|
listGroups: () => listGroups,
|
|
645
652
|
mapConnectionStatus: () => mapConnectionStatus,
|
|
@@ -728,8 +735,11 @@ __export(src_exports, {
|
|
|
728
735
|
reopenFreshdeskTicket: () => reopenTicket,
|
|
729
736
|
resolveActiveProfile: () => resolveActiveProfile,
|
|
730
737
|
resolveCategory: () => resolveCategory,
|
|
738
|
+
resolveClassification: () => resolveClassification,
|
|
731
739
|
resolveGroup: () => resolveGroup,
|
|
732
740
|
resolvePercentDecimals: () => resolvePercentDecimals,
|
|
741
|
+
resolveSubcategory: () => resolveSubcategory,
|
|
742
|
+
resolveWithFallback: () => resolveWithFallback,
|
|
733
743
|
schedCreateDateInput: () => createDateInput,
|
|
734
744
|
schedCreateNumberInput: () => createNumberInput,
|
|
735
745
|
schedCreateSelect: () => createSelect,
|
|
@@ -758,6 +768,7 @@ __export(src_exports, {
|
|
|
758
768
|
updateFreshdeskTicket: () => updateTicket,
|
|
759
769
|
upsertAlarmAnnotation: () => upsertAlarmAnnotation,
|
|
760
770
|
validateProfile: () => validateProfile,
|
|
771
|
+
validateTree: () => validateTree,
|
|
761
772
|
version: () => version,
|
|
762
773
|
waterDeviceStatusIcons: () => waterDeviceStatusIcons,
|
|
763
774
|
writeFreshdeskSyncedAtToTB: () => writeFreshdeskSyncedAtToTB,
|
|
@@ -768,7 +779,7 @@ module.exports = __toCommonJS(src_exports);
|
|
|
768
779
|
// package.json
|
|
769
780
|
var package_default = {
|
|
770
781
|
name: "myio-js-library",
|
|
771
|
-
version: "0.1.
|
|
782
|
+
version: "0.1.528",
|
|
772
783
|
description: "A clean, standalone JS SDK for MYIO projects",
|
|
773
784
|
license: "MIT",
|
|
774
785
|
repository: "github:gh-myio/myio-js-library",
|
|
@@ -815,6 +826,8 @@ var package_default = {
|
|
|
815
826
|
"build:umd": "rollup -c",
|
|
816
827
|
"minify:umd": "terser dist/myio-js-library.umd.js -o dist/myio-js-library.umd.min.js --comments=false",
|
|
817
828
|
postbuild: "node scripts/verify-dts.js",
|
|
829
|
+
"gen:baked-profile": "node scripts/gen-baked-profile.mjs",
|
|
830
|
+
prebuild: "node scripts/gen-baked-profile.mjs --check",
|
|
818
831
|
build: "npm run clean && npm run build:tsup && npm run build:umd && npm run minify:umd",
|
|
819
832
|
lint: "eslint .",
|
|
820
833
|
test: "vitest run",
|
|
@@ -3123,7 +3136,7 @@ var DEFAULT_DEVICE_CLASSIFICATION_PROFILE = {
|
|
|
3123
3136
|
name: "elevadores",
|
|
3124
3137
|
// ELEVADORES_DEVICE_TYPES_SET + buildSummary ELEVADOR_PATTERNS
|
|
3125
3138
|
deviceProfiles: ["ELEVADOR"],
|
|
3126
|
-
|
|
3139
|
+
profileContains: ["ELEVADOR"],
|
|
3127
3140
|
identifierFallback: {
|
|
3128
3141
|
// ELEVADORES_IDENTIFIERS_SET + buildSummary id prefix ELV-
|
|
3129
3142
|
identifierEquals: ["ELV", "ELEVADOR", "ELEVADORES"],
|
|
@@ -3134,7 +3147,7 @@ var DEFAULT_DEVICE_CLASSIFICATION_PROFILE = {
|
|
|
3134
3147
|
name: "escadas_rolantes",
|
|
3135
3148
|
// ESCADAS_DEVICE_TYPES_SET + buildSummary ESCADA_PATTERNS
|
|
3136
3149
|
deviceProfiles: ["ESCADA_ROLANTE"],
|
|
3137
|
-
|
|
3150
|
+
profileContains: ["ESCADA", "ROLANTE"],
|
|
3138
3151
|
identifierFallback: {
|
|
3139
3152
|
// ESCADAS_IDENTIFIERS_SET + buildSummary id prefix ESC-
|
|
3140
3153
|
identifierEquals: ["ESC", "ESCADA", "ESCADASROLANTES"],
|
|
@@ -3145,17 +3158,21 @@ var DEFAULT_DEVICE_CLASSIFICATION_PROFILE = {
|
|
|
3145
3158
|
name: "climatizacao",
|
|
3146
3159
|
// CLIMATIZACAO_DEVICE_TYPES_SET
|
|
3147
3160
|
deviceProfiles: ["CHILLER", "AR_CONDICIONADO", "HVAC", "FANCOIL"],
|
|
3148
|
-
// buildSummary CLIMATIZACAO_PATTERNS (superset of the deviceProfiles)
|
|
3149
|
-
|
|
3161
|
+
// buildSummary CLIMATIZACAO_PATTERNS (superset of the deviceProfiles).
|
|
3162
|
+
// NB: BOMBA_HIDRAULICA/BOMBASHIDRAULICAS foram REMOVIDOS (2026-07-23):
|
|
3163
|
+
// bomba hidráulica é recalque de água, não climatização — deve cair em
|
|
3164
|
+
// 'outros' (igual a BOMBA_INCENDIO). BOMBA_CAG continua em climatização
|
|
3165
|
+
// via `conditional`/`identifierFallback` (CAG), sem depender destas
|
|
3166
|
+
// strings. Alinhado a equipmentCategory.js (hvacProfiles NÃO inclui bomba
|
|
3167
|
+
// hidráulica) e a openUpsellModal (BOMBA_HIDRAULICA = energy_common_area).
|
|
3168
|
+
profileContains: [
|
|
3150
3169
|
"CHILLER",
|
|
3151
3170
|
"FANCOIL",
|
|
3152
3171
|
"HVAC",
|
|
3153
3172
|
"AR_CONDICIONADO",
|
|
3154
3173
|
"COMPRESSOR",
|
|
3155
3174
|
"VENTILADOR",
|
|
3156
|
-
"CLIMATIZA"
|
|
3157
|
-
"BOMBA_HIDRAULICA",
|
|
3158
|
-
"BOMBASHIDRAULICAS"
|
|
3175
|
+
"CLIMATIZA"
|
|
3159
3176
|
],
|
|
3160
3177
|
// CLIMATIZACAO conditional (perfis BOMBA/MOTOR) + identifier requirement
|
|
3161
3178
|
conditional: {
|
|
@@ -3240,9 +3257,6 @@ function profileOf(item) {
|
|
|
3240
3257
|
function identifierOf(item) {
|
|
3241
3258
|
return up(item?.identifier ?? "").trim();
|
|
3242
3259
|
}
|
|
3243
|
-
function combinedOf(item) {
|
|
3244
|
-
return `${up(item?.labelWidget ?? "")} ${up(item?.deviceProfile ?? "")} ${up(item?.label ?? "")}`;
|
|
3245
|
-
}
|
|
3246
3260
|
function matchesIdentifier(id, m) {
|
|
3247
3261
|
if (!m) return false;
|
|
3248
3262
|
if (m.identifierEquals) {
|
|
@@ -3297,13 +3311,12 @@ function resolveCategory(item, profile = getActiveProfile(), domain = "energy")
|
|
|
3297
3311
|
}
|
|
3298
3312
|
}
|
|
3299
3313
|
}
|
|
3300
|
-
const combined = combinedOf(item);
|
|
3301
3314
|
const id = identifierOf(item);
|
|
3302
3315
|
for (const rule of rules) {
|
|
3303
|
-
if (rule.
|
|
3304
|
-
for (const pattern of rule.
|
|
3305
|
-
if (
|
|
3306
|
-
return { category: rule.name, matchedBy: "
|
|
3316
|
+
if (dp && rule.profileContains) {
|
|
3317
|
+
for (const pattern of rule.profileContains) {
|
|
3318
|
+
if (dp.includes(up(pattern))) {
|
|
3319
|
+
return { category: rule.name, matchedBy: "profileContains" };
|
|
3307
3320
|
}
|
|
3308
3321
|
}
|
|
3309
3322
|
}
|
|
@@ -3379,6 +3392,12 @@ function validateProfile(profile) {
|
|
|
3379
3392
|
if (!Array.isArray(r.deviceProfiles)) {
|
|
3380
3393
|
errors.push(`${domain}.categories.rules["${r?.name}"]: missing deviceProfiles array`);
|
|
3381
3394
|
}
|
|
3395
|
+
if (r.profileContains !== void 0 && !Array.isArray(r.profileContains)) {
|
|
3396
|
+
errors.push(`${domain}.categories.rules["${r?.name}"].profileContains: must be an array`);
|
|
3397
|
+
}
|
|
3398
|
+
if (r.combinedContains !== void 0 && !Array.isArray(r.combinedContains)) {
|
|
3399
|
+
errors.push(`${domain}.categories.rules["${r?.name}"].combinedContains: must be an array`);
|
|
3400
|
+
}
|
|
3382
3401
|
}
|
|
3383
3402
|
const inlineFallbacks = catRules.filter((r) => r.fallback === true).length;
|
|
3384
3403
|
const hasOutros = cats.fallback && cats.fallback.name === "outros" ? 1 : 0;
|
|
@@ -3419,7 +3438,13 @@ function normalizeProfile(raw) {
|
|
|
3419
3438
|
}
|
|
3420
3439
|
for (const r of dom.categories.rules ?? []) {
|
|
3421
3440
|
r.deviceProfiles = upArr(r.deviceProfiles) ?? [];
|
|
3422
|
-
|
|
3441
|
+
const _pc = upArr(r.profileContains);
|
|
3442
|
+
const _legacy = upArr(r.combinedContains);
|
|
3443
|
+
if (_pc || _legacy) {
|
|
3444
|
+
const merged = [..._pc ?? [], ..._legacy ?? []];
|
|
3445
|
+
r.profileContains = merged.filter((v, i) => merged.indexOf(v) === i);
|
|
3446
|
+
}
|
|
3447
|
+
delete r.combinedContains;
|
|
3423
3448
|
if (r.conditional) {
|
|
3424
3449
|
r.conditional.deviceProfiles = upArr(r.conditional.deviceProfiles) ?? upArr(r.conditional.deviceTypes) ?? [];
|
|
3425
3450
|
delete r.conditional.deviceTypes;
|
|
@@ -3463,8 +3488,364 @@ function listGroups(profile = getActiveProfile(), domain = "") {
|
|
|
3463
3488
|
return rules.map((r) => ({ key: r.name, fallback: !!r.fallback }));
|
|
3464
3489
|
}
|
|
3465
3490
|
|
|
3491
|
+
// src/utils/devices/classificationNodeTree.ts
|
|
3492
|
+
var up2 = (v) => String(v ?? "").toUpperCase();
|
|
3493
|
+
var profileOf2 = (i) => up2(i?.deviceProfile ?? "");
|
|
3494
|
+
var identifierOf2 = (i) => up2(i?.identifier ?? "").trim();
|
|
3495
|
+
function matchesIdentifier2(id, m) {
|
|
3496
|
+
if (!m) return false;
|
|
3497
|
+
for (const v of m.identifierEquals ?? []) if (id === up2(v)) return true;
|
|
3498
|
+
for (const v of m.identifierExact ?? []) if (id === up2(v)) return true;
|
|
3499
|
+
for (const v of m.identifierContains ?? []) if (id.includes(up2(v))) return true;
|
|
3500
|
+
for (const p of m.identifierPrefixes ?? []) if (id.startsWith(up2(p))) return true;
|
|
3501
|
+
return false;
|
|
3502
|
+
}
|
|
3503
|
+
function matchExact(dp, rules) {
|
|
3504
|
+
if (!rules || !dp) return false;
|
|
3505
|
+
for (const c of rules.deviceProfiles ?? []) if (dp === up2(c)) return true;
|
|
3506
|
+
return false;
|
|
3507
|
+
}
|
|
3508
|
+
function matchLoose(dp, id, rules) {
|
|
3509
|
+
if (!rules) return null;
|
|
3510
|
+
if (dp) {
|
|
3511
|
+
for (const p of rules.profileContains ?? []) if (dp.includes(up2(p))) return "profileContains";
|
|
3512
|
+
}
|
|
3513
|
+
const cond = rules.conditional;
|
|
3514
|
+
if (cond && (cond.deviceProfiles ?? []).some((t) => dp === up2(t))) {
|
|
3515
|
+
if (matchesIdentifier2(id, cond)) return "conditional";
|
|
3516
|
+
}
|
|
3517
|
+
if (matchesIdentifier2(id, rules)) return "identifier";
|
|
3518
|
+
return null;
|
|
3519
|
+
}
|
|
3520
|
+
function byOrder(a, b) {
|
|
3521
|
+
const d = (a.order ?? 0) - (b.order ?? 0);
|
|
3522
|
+
return d !== 0 ? d : String(a.key).localeCompare(String(b.key));
|
|
3523
|
+
}
|
|
3524
|
+
function classifiable(nodes) {
|
|
3525
|
+
return nodes.filter((n) => n.role !== "residual" && n.role !== "total");
|
|
3526
|
+
}
|
|
3527
|
+
function resolveClassification(item, tree) {
|
|
3528
|
+
if (!Array.isArray(tree) || tree.length === 0) return null;
|
|
3529
|
+
const dp = profileOf2(item);
|
|
3530
|
+
const id = identifierOf2(item);
|
|
3531
|
+
for (const n of [...tree].sort(byOrder)) {
|
|
3532
|
+
if (n.role !== "ocultos") continue;
|
|
3533
|
+
if (matchExact(dp, n.rules) || matchLoose(dp, id, n.rules)) {
|
|
3534
|
+
return { key: n.key, nodePath: [n.key], matchedBy: "ocultos" };
|
|
3535
|
+
}
|
|
3536
|
+
}
|
|
3537
|
+
const path = [];
|
|
3538
|
+
let level = classifiable(tree).filter((n) => n.role !== "ocultos");
|
|
3539
|
+
let matchedBy = "fallback";
|
|
3540
|
+
let current = null;
|
|
3541
|
+
while (true) {
|
|
3542
|
+
const siblings = [...level].sort(byOrder);
|
|
3543
|
+
let hit = null;
|
|
3544
|
+
let hitBy = null;
|
|
3545
|
+
for (const n of siblings) {
|
|
3546
|
+
if (matchExact(dp, n.rules)) {
|
|
3547
|
+
hit = n;
|
|
3548
|
+
hitBy = "deviceProfile";
|
|
3549
|
+
break;
|
|
3550
|
+
}
|
|
3551
|
+
}
|
|
3552
|
+
if (!hit) {
|
|
3553
|
+
for (const n of siblings) {
|
|
3554
|
+
const by = matchLoose(dp, id, n.rules);
|
|
3555
|
+
if (by) {
|
|
3556
|
+
hit = n;
|
|
3557
|
+
hitBy = by;
|
|
3558
|
+
break;
|
|
3559
|
+
}
|
|
3560
|
+
}
|
|
3561
|
+
}
|
|
3562
|
+
if (!hit) {
|
|
3563
|
+
const fb = siblings.find((n) => n.role === "fallback");
|
|
3564
|
+
if (fb) {
|
|
3565
|
+
hit = fb;
|
|
3566
|
+
hitBy = "fallback";
|
|
3567
|
+
}
|
|
3568
|
+
}
|
|
3569
|
+
if (!hit) break;
|
|
3570
|
+
current = hit;
|
|
3571
|
+
matchedBy = hitBy ?? "fallback";
|
|
3572
|
+
path.push(hit.key);
|
|
3573
|
+
const kids = classifiable(hit.children ?? []).filter((n) => n.role !== "ocultos");
|
|
3574
|
+
if (kids.length === 0) break;
|
|
3575
|
+
level = kids;
|
|
3576
|
+
}
|
|
3577
|
+
if (!current) return null;
|
|
3578
|
+
return { key: current.key, nodePath: path, matchedBy };
|
|
3579
|
+
}
|
|
3580
|
+
function resolveSubcategory(item, groupKey, tree) {
|
|
3581
|
+
const group = findNode(tree, groupKey);
|
|
3582
|
+
if (!group) return null;
|
|
3583
|
+
const kids = classifiable(group.children ?? []);
|
|
3584
|
+
if (kids.length === 0) return null;
|
|
3585
|
+
const r = resolveClassification(item, kids);
|
|
3586
|
+
return r ? { ...r, nodePath: [groupKey, ...r.nodePath] } : null;
|
|
3587
|
+
}
|
|
3588
|
+
function findNode(tree, key) {
|
|
3589
|
+
for (const n of tree ?? []) {
|
|
3590
|
+
if (n.key === key) return n;
|
|
3591
|
+
const deep = findNode(n.children ?? [], key);
|
|
3592
|
+
if (deep) return deep;
|
|
3593
|
+
}
|
|
3594
|
+
return null;
|
|
3595
|
+
}
|
|
3596
|
+
function flattenTree(tree) {
|
|
3597
|
+
const out = [];
|
|
3598
|
+
for (const n of [...tree ?? []].sort(byOrder)) {
|
|
3599
|
+
out.push(n);
|
|
3600
|
+
out.push(...flattenTree(n.children ?? []));
|
|
3601
|
+
}
|
|
3602
|
+
return out;
|
|
3603
|
+
}
|
|
3604
|
+
function validateTree(tree) {
|
|
3605
|
+
const errors = [];
|
|
3606
|
+
const seenKeys = /* @__PURE__ */ new Map();
|
|
3607
|
+
const seenProfiles = /* @__PURE__ */ new Map();
|
|
3608
|
+
const walkLevel = (nodes, parentPath) => {
|
|
3609
|
+
const fallbacks = nodes.filter((n) => n.role === "fallback");
|
|
3610
|
+
if (fallbacks.length > 1) {
|
|
3611
|
+
errors.push(
|
|
3612
|
+
`${parentPath}: ${fallbacks.length} n\xF3s role:'fallback' entre irm\xE3os (esperado no m\xE1ximo 1)`
|
|
3613
|
+
);
|
|
3614
|
+
}
|
|
3615
|
+
if (fallbacks.length === 1) {
|
|
3616
|
+
const fb = fallbacks[0];
|
|
3617
|
+
const maxOther = nodes.filter((n) => n !== fb && n.role !== "ocultos" && n.role !== "residual" && n.role !== "total").reduce((m, n) => Math.max(m, n.order ?? 0), Number.NEGATIVE_INFINITY);
|
|
3618
|
+
if (maxOther !== Number.NEGATIVE_INFINITY && (fb.order ?? 0) <= maxOther) {
|
|
3619
|
+
errors.push(
|
|
3620
|
+
`${parentPath}: fallback "${fb.key}" tem order ${fb.order} <= ${maxOther} de um irm\xE3o real \u2014 o catch-all sombrearia a regra`
|
|
3621
|
+
);
|
|
3622
|
+
}
|
|
3623
|
+
}
|
|
3624
|
+
for (const n of nodes) {
|
|
3625
|
+
const path = `${parentPath}/${n.key || "<sem key>"}`;
|
|
3626
|
+
if (!n.key) errors.push(`${path}: key vazia`);
|
|
3627
|
+
if (!n.label) errors.push(`${path}: label vazio`);
|
|
3628
|
+
if (!Number.isInteger(n.order)) {
|
|
3629
|
+
errors.push(`${path}: order ausente ou n\xE3o-inteiro (RFC-0207 \xA7B.1-1 exige expl\xEDcito)`);
|
|
3630
|
+
}
|
|
3631
|
+
seenKeys.set(n.key, (seenKeys.get(n.key) ?? 0) + 1);
|
|
3632
|
+
for (const dp of n.rules?.deviceProfiles ?? []) {
|
|
3633
|
+
const k = up2(dp);
|
|
3634
|
+
const owner = seenProfiles.get(k);
|
|
3635
|
+
if (owner && owner !== n.key) {
|
|
3636
|
+
errors.push(`aloca\xE7\xE3o n\xE3o-\xFAnica: deviceProfile "${k}" em "${owner}" e "${n.key}"`);
|
|
3637
|
+
} else {
|
|
3638
|
+
seenProfiles.set(k, n.key);
|
|
3639
|
+
}
|
|
3640
|
+
}
|
|
3641
|
+
if (n.children?.length) walkLevel(n.children, path);
|
|
3642
|
+
}
|
|
3643
|
+
};
|
|
3644
|
+
walkLevel(tree ?? [], "");
|
|
3645
|
+
for (const [key, count] of seenKeys) {
|
|
3646
|
+
if (count > 1) errors.push(`key duplicada na \xE1rvore: "${key}" (${count}x)`);
|
|
3647
|
+
}
|
|
3648
|
+
for (const n of flattenTree(tree ?? [])) {
|
|
3649
|
+
const refs = [...n.formula?.of ?? [], ...n.formula?.subtract ?? []];
|
|
3650
|
+
if (n.formula?.from) refs.push(n.formula.from);
|
|
3651
|
+
for (const ref of refs) {
|
|
3652
|
+
if (!seenKeys.has(ref)) errors.push(`formula de "${n.key}" referencia key inexistente "${ref}"`);
|
|
3653
|
+
}
|
|
3654
|
+
}
|
|
3655
|
+
return errors;
|
|
3656
|
+
}
|
|
3657
|
+
var LABELS = {
|
|
3658
|
+
ocultos: "Ocultos",
|
|
3659
|
+
entrada: "Entrada",
|
|
3660
|
+
lojas: "Lojas",
|
|
3661
|
+
areacomum: "\xC1rea Comum",
|
|
3662
|
+
caixadagua: "Caixa d'\xC1gua",
|
|
3663
|
+
banheiros: "Banheiros",
|
|
3664
|
+
climatizavel: "Climatiz\xE1vel",
|
|
3665
|
+
nao_climatizavel: "N\xE3o Climatiz\xE1vel",
|
|
3666
|
+
climatizacao: "Climatiza\xE7\xE3o",
|
|
3667
|
+
elevadores: "Elevadores",
|
|
3668
|
+
escadas_rolantes: "Escadas Rolantes",
|
|
3669
|
+
outros: "Outros Equipamentos"
|
|
3670
|
+
};
|
|
3671
|
+
function labelFor(key) {
|
|
3672
|
+
return LABELS[key] ?? key.charAt(0).toUpperCase() + key.slice(1).replace(/_/g, " ");
|
|
3673
|
+
}
|
|
3674
|
+
function liftProfileToTree(profile = getActiveProfile(), domain = "energy") {
|
|
3675
|
+
const dom = profile?.domains?.[domain];
|
|
3676
|
+
if (!dom) return [];
|
|
3677
|
+
const tree = [];
|
|
3678
|
+
let order = 0;
|
|
3679
|
+
tree.push({
|
|
3680
|
+
key: "ocultos",
|
|
3681
|
+
label: labelFor("ocultos"),
|
|
3682
|
+
role: "ocultos",
|
|
3683
|
+
order: order++,
|
|
3684
|
+
rules: { profileContains: [...dom.groups?.ocultosProfilePatterns ?? []] }
|
|
3685
|
+
});
|
|
3686
|
+
const groupRules = (dom.groups?.rules ?? []).filter((r) => !r.fallback);
|
|
3687
|
+
const groupFallback = (dom.groups?.rules ?? []).find((r) => r.fallback);
|
|
3688
|
+
const cats = dom.categories;
|
|
3689
|
+
for (const r of groupRules) {
|
|
3690
|
+
tree.push({
|
|
3691
|
+
key: r.name,
|
|
3692
|
+
label: labelFor(r.name),
|
|
3693
|
+
role: r.name === "entrada" ? "entrada" : "consumer",
|
|
3694
|
+
order: order++,
|
|
3695
|
+
rules: { deviceProfiles: [...r.deviceProfiles ?? []] }
|
|
3696
|
+
});
|
|
3697
|
+
}
|
|
3698
|
+
if (cats) {
|
|
3699
|
+
const lojas = tree.find((n) => n.key === "lojas");
|
|
3700
|
+
if (lojas && cats.storeDeviceProfile) {
|
|
3701
|
+
lojas.rules = lojas.rules ?? {};
|
|
3702
|
+
const list = lojas.rules.deviceProfiles ?? [];
|
|
3703
|
+
if (!list.some((v) => up2(v) === up2(cats.storeDeviceProfile))) list.push(cats.storeDeviceProfile);
|
|
3704
|
+
lojas.rules.deviceProfiles = list;
|
|
3705
|
+
}
|
|
3706
|
+
for (const r of cats.rules) {
|
|
3707
|
+
tree.push({
|
|
3708
|
+
key: r.name,
|
|
3709
|
+
label: labelFor(r.name),
|
|
3710
|
+
role: "consumer",
|
|
3711
|
+
order: order++,
|
|
3712
|
+
rules: {
|
|
3713
|
+
deviceProfiles: [...r.deviceProfiles ?? []],
|
|
3714
|
+
profileContains: r.profileContains ? [...r.profileContains] : void 0,
|
|
3715
|
+
identifierExact: r.identifierFallback?.identifierEquals ? [...r.identifierFallback.identifierEquals] : void 0,
|
|
3716
|
+
identifierContains: r.identifierFallback?.identifierContains ? [...r.identifierFallback.identifierContains] : void 0,
|
|
3717
|
+
identifierPrefixes: r.identifierFallback?.identifierPrefixes ? [...r.identifierFallback.identifierPrefixes] : void 0,
|
|
3718
|
+
conditional: r.conditional ? { ...r.conditional } : void 0
|
|
3719
|
+
}
|
|
3720
|
+
});
|
|
3721
|
+
}
|
|
3722
|
+
tree.push({
|
|
3723
|
+
key: cats.fallback?.name ?? "outros",
|
|
3724
|
+
label: labelFor(cats.fallback?.name ?? "outros"),
|
|
3725
|
+
role: "fallback",
|
|
3726
|
+
order: order++
|
|
3727
|
+
});
|
|
3728
|
+
if (groupFallback) {
|
|
3729
|
+
const consumers = tree.filter((n) => n.role === "consumer" || n.role === "fallback").map((n) => n.key);
|
|
3730
|
+
tree.push({
|
|
3731
|
+
key: groupFallback.name,
|
|
3732
|
+
label: labelFor(groupFallback.name),
|
|
3733
|
+
role: "residual",
|
|
3734
|
+
order: order++,
|
|
3735
|
+
formula: { op: "subtract", from: "entrada", subtract: consumers }
|
|
3736
|
+
});
|
|
3737
|
+
}
|
|
3738
|
+
} else if (groupFallback) {
|
|
3739
|
+
tree.push({
|
|
3740
|
+
key: groupFallback.name,
|
|
3741
|
+
label: labelFor(groupFallback.name),
|
|
3742
|
+
role: "fallback",
|
|
3743
|
+
order: order++
|
|
3744
|
+
});
|
|
3745
|
+
}
|
|
3746
|
+
return tree;
|
|
3747
|
+
}
|
|
3748
|
+
|
|
3749
|
+
// src/utils/devices/bakedProfile.generated.ts
|
|
3750
|
+
var BAKED_PROFILE_VERSION = "d861298603d0";
|
|
3751
|
+
var BAKED_PROFILE_KEYS = Object.freeze([
|
|
3752
|
+
"energy",
|
|
3753
|
+
"energy.categories.climatizacao",
|
|
3754
|
+
"energy.categories.elevadores",
|
|
3755
|
+
"energy.categories.escadas_rolantes",
|
|
3756
|
+
"energy.categories.lojas",
|
|
3757
|
+
"energy.categories.outros",
|
|
3758
|
+
"energy.groups.areacomum",
|
|
3759
|
+
"energy.groups.entrada",
|
|
3760
|
+
"energy.groups.lojas",
|
|
3761
|
+
"energy.groups.ocultos",
|
|
3762
|
+
"temperature",
|
|
3763
|
+
"temperature.groups.climatizavel",
|
|
3764
|
+
"temperature.groups.nao_climatizavel",
|
|
3765
|
+
"temperature.groups.ocultos",
|
|
3766
|
+
"water",
|
|
3767
|
+
"water.groups.areacomum",
|
|
3768
|
+
"water.groups.caixadagua",
|
|
3769
|
+
"water.groups.entrada",
|
|
3770
|
+
"water.groups.lojas",
|
|
3771
|
+
"water.groups.ocultos"
|
|
3772
|
+
]);
|
|
3773
|
+
|
|
3774
|
+
// src/utils/devices/profileSource.ts
|
|
3775
|
+
function createBakedProfileSource() {
|
|
3776
|
+
return {
|
|
3777
|
+
name: "baked",
|
|
3778
|
+
async resolve() {
|
|
3779
|
+
return {
|
|
3780
|
+
version: BAKED_PROFILE_VERSION,
|
|
3781
|
+
source: "baked",
|
|
3782
|
+
profile: DEFAULT_DEVICE_CLASSIFICATION_PROFILE,
|
|
3783
|
+
degraded: true,
|
|
3784
|
+
reason: "baked-default"
|
|
3785
|
+
};
|
|
3786
|
+
}
|
|
3787
|
+
};
|
|
3788
|
+
}
|
|
3789
|
+
function withTimeout(p, ms) {
|
|
3790
|
+
if (!ms || ms <= 0) return p;
|
|
3791
|
+
return new Promise((resolve, reject) => {
|
|
3792
|
+
const t = setTimeout(() => reject(new Error(`profile source timeout after ${ms}ms`)), ms);
|
|
3793
|
+
p.then(
|
|
3794
|
+
(v) => {
|
|
3795
|
+
clearTimeout(t);
|
|
3796
|
+
resolve(v);
|
|
3797
|
+
},
|
|
3798
|
+
(e) => {
|
|
3799
|
+
clearTimeout(t);
|
|
3800
|
+
reject(e);
|
|
3801
|
+
}
|
|
3802
|
+
);
|
|
3803
|
+
});
|
|
3804
|
+
}
|
|
3805
|
+
async function resolveWithFallback(primary, opts) {
|
|
3806
|
+
const baked = opts.baked ?? createBakedProfileSource();
|
|
3807
|
+
const logger = opts.logger ?? console;
|
|
3808
|
+
const degrade = async (reason) => {
|
|
3809
|
+
const floor = await baked.resolve(opts.customerId);
|
|
3810
|
+
const info = {
|
|
3811
|
+
source: "baked",
|
|
3812
|
+
reason,
|
|
3813
|
+
customerId: opts.customerId,
|
|
3814
|
+
bakedVersion: floor.version
|
|
3815
|
+
};
|
|
3816
|
+
logger.warn(`[RFC-0207] profile degraded \u2192 baked ${JSON.stringify(info)}`);
|
|
3817
|
+
try {
|
|
3818
|
+
opts.onDegraded?.(info);
|
|
3819
|
+
} catch {
|
|
3820
|
+
}
|
|
3821
|
+
return { ...floor, degraded: true, reason };
|
|
3822
|
+
};
|
|
3823
|
+
let resolved;
|
|
3824
|
+
try {
|
|
3825
|
+
resolved = await withTimeout(primary.resolve(opts.customerId), opts.timeoutMs ?? 0);
|
|
3826
|
+
} catch (err) {
|
|
3827
|
+
return degrade(`${primary.name}:${err?.message || "resolve threw"}`);
|
|
3828
|
+
}
|
|
3829
|
+
if (!resolved || !resolved.profile) {
|
|
3830
|
+
return degrade(`${primary.name}:empty-response`);
|
|
3831
|
+
}
|
|
3832
|
+
const errors = validateProfile(resolved.profile);
|
|
3833
|
+
if (errors.length > 0) {
|
|
3834
|
+
return degrade(`${primary.name}:invalid-profile:${errors.slice(0, 3).join("; ")}`);
|
|
3835
|
+
}
|
|
3836
|
+
return {
|
|
3837
|
+
...resolved,
|
|
3838
|
+
profile: normalizeProfile(resolved.profile),
|
|
3839
|
+
degraded: resolved.degraded ?? false
|
|
3840
|
+
};
|
|
3841
|
+
}
|
|
3842
|
+
function isBakedStale(resolved, authoredVersion) {
|
|
3843
|
+
if (!authoredVersion) return false;
|
|
3844
|
+
return resolved.source === "baked" && resolved.version !== authoredVersion;
|
|
3845
|
+
}
|
|
3846
|
+
|
|
3466
3847
|
// src/utils/devices/classificationTree.ts
|
|
3467
|
-
function
|
|
3848
|
+
function up3(s) {
|
|
3468
3849
|
return String(s ?? "").trim().toUpperCase();
|
|
3469
3850
|
}
|
|
3470
3851
|
function isUsable(node) {
|
|
@@ -3476,7 +3857,7 @@ function collectProfiles(node) {
|
|
|
3476
3857
|
const kids = [...n.children ?? []].filter(isUsable).sort((a, b) => (a.sortOrder ?? 0) - (b.sortOrder ?? 0));
|
|
3477
3858
|
for (const child of kids) {
|
|
3478
3859
|
if ((child.entityType ?? "").toUpperCase() === "PROFILE") {
|
|
3479
|
-
const key =
|
|
3860
|
+
const key = up3(child.entityKey);
|
|
3480
3861
|
if (key && !out.includes(key)) out.push(key);
|
|
3481
3862
|
}
|
|
3482
3863
|
walk(child);
|
|
@@ -6155,8 +6536,8 @@ function openDeviceProfileModal(params) {
|
|
|
6155
6536
|
onClose
|
|
6156
6537
|
} = params;
|
|
6157
6538
|
void customerId;
|
|
6158
|
-
const working =
|
|
6159
|
-
params.profile || DEFAULT_DEVICE_CLASSIFICATION_PROFILE
|
|
6539
|
+
const working = normalizeProfile(
|
|
6540
|
+
deepClone(params.profile || DEFAULT_DEVICE_CLASSIFICATION_PROFILE)
|
|
6160
6541
|
);
|
|
6161
6542
|
working.domains = working.domains || {};
|
|
6162
6543
|
if (!working.domains.energy) {
|
|
@@ -6328,11 +6709,13 @@ function openDeviceProfileModal(params) {
|
|
|
6328
6709
|
accent: accentFor(r.name),
|
|
6329
6710
|
infoIcon: "\u{1F527}",
|
|
6330
6711
|
infoHtml: cardInfoText(
|
|
6331
|
-
`Breakdown <b>${escHtml(r.name)}</b> (preced\xEAncia): 1) deviceProfile exato; 2) identifier cont\xE9m/prefixo
|
|
6712
|
+
`Breakdown <b>${escHtml(r.name)}</b> (preced\xEAncia): 1) <b>deviceProfile</b> exato; 2) <b>deviceProfile cont\xE9m</b> (substring); 3) identifier cont\xE9m/prefixo.<br><br>
|
|
6713
|
+
S\xF3 o <b>deviceProfile</b> e o <b>identifier</b> s\xE3o avaliados \u2014 nunca o nome/label do device.`
|
|
6332
6714
|
)
|
|
6333
6715
|
},
|
|
6334
6716
|
`
|
|
6335
6717
|
<div class="mdp-field"><label>deviceProfile</label>${chipList(`cat-${i}-dp`, r.deviceProfiles || [], ro)}</div>
|
|
6718
|
+
<div class="mdp-field"><label>deviceProfile cont\xE9m</label>${chipList(`cat-${i}-pc`, r.profileContains || [], ro)}</div>
|
|
6336
6719
|
<div class="mdp-field"><label>identifier cont\xE9m</label>${chipList(`cat-${i}-idc`, r.identifierFallback?.identifierContains || [], ro)}</div>
|
|
6337
6720
|
<div class="mdp-field"><label>identifier prefixo</label>${chipList(`cat-${i}-idp`, r.identifierFallback?.identifierPrefixes || [], ro)}</div>`
|
|
6338
6721
|
)
|
|
@@ -6388,11 +6771,11 @@ function openDeviceProfileModal(params) {
|
|
|
6388
6771
|
}
|
|
6389
6772
|
const cats = d.categories;
|
|
6390
6773
|
if (!cats) return null;
|
|
6391
|
-
m = key.match(/^cat-(\d+)-(dp|
|
|
6774
|
+
m = key.match(/^cat-(\d+)-(dp|pc|idc|idp)$/);
|
|
6392
6775
|
if (m) {
|
|
6393
6776
|
const rule = cats.rules[Number(m[1])];
|
|
6394
6777
|
if (m[2] === "dp") return rule.deviceProfiles = rule.deviceProfiles || [];
|
|
6395
|
-
if (m[2] === "
|
|
6778
|
+
if (m[2] === "pc") return rule.profileContains = rule.profileContains || [];
|
|
6396
6779
|
rule.identifierFallback = rule.identifierFallback || {};
|
|
6397
6780
|
if (m[2] === "idc")
|
|
6398
6781
|
return rule.identifierFallback.identifierContains = rule.identifierFallback.identifierContains || [];
|
|
@@ -68806,14 +69189,14 @@ var DefaultSettingsPersister = class {
|
|
|
68806
69189
|
const limitsList = [];
|
|
68807
69190
|
statuses.forEach((statusKey) => {
|
|
68808
69191
|
const down = formData[`${statusKey}LimitDownConsumption`];
|
|
68809
|
-
const
|
|
68810
|
-
if (down !== void 0 && down !== "" ||
|
|
69192
|
+
const up4 = formData[`${statusKey}LimitUpConsumption`];
|
|
69193
|
+
if (down !== void 0 && down !== "" || up4 !== void 0 && up4 !== "") {
|
|
68811
69194
|
limitsList.push({
|
|
68812
69195
|
deviceStatusName: statusMap[statusKey],
|
|
68813
69196
|
limitsValues: {
|
|
68814
69197
|
// Converte para Number ou null
|
|
68815
69198
|
baseValue: down !== "" && down !== void 0 ? Number(down) : null,
|
|
68816
|
-
topValue:
|
|
69199
|
+
topValue: up4 !== "" && up4 !== void 0 ? Number(up4) : null
|
|
68817
69200
|
}
|
|
68818
69201
|
});
|
|
68819
69202
|
}
|
|
@@ -86061,10 +86444,17 @@ function _applyTheme(root) {
|
|
|
86061
86444
|
}
|
|
86062
86445
|
function _formatValue(value, domain) {
|
|
86063
86446
|
const cfg = DOMAIN_CFG[domain] || DOMAIN_CFG.energy;
|
|
86064
|
-
const
|
|
86447
|
+
const U = typeof window !== "undefined" ? window.MyIOUtils : void 0;
|
|
86448
|
+
if (domain === "energy" && typeof U?.formatEnergyWithSettings === "function") {
|
|
86449
|
+
return U.formatEnergyWithSettings(value);
|
|
86450
|
+
}
|
|
86451
|
+
if (domain === "water" && typeof U?.formatWaterWithSettings === "function") {
|
|
86452
|
+
return U.formatWaterWithSettings(value);
|
|
86453
|
+
}
|
|
86454
|
+
const dec = domain === "temperature" ? 1 : 3;
|
|
86065
86455
|
const ptBR = (v, d) => v.toLocaleString("pt-BR", { minimumFractionDigits: d, maximumFractionDigits: d });
|
|
86066
86456
|
if (cfg.threshold && cfg.unitLarge && Math.abs(value) >= cfg.threshold) {
|
|
86067
|
-
return `${ptBR(value / cfg.threshold,
|
|
86457
|
+
return `${ptBR(value / cfg.threshold, 3)} ${cfg.unitLarge}`;
|
|
86068
86458
|
}
|
|
86069
86459
|
return `${ptBR(value, dec)} ${cfg.unit}`;
|
|
86070
86460
|
}
|
|
@@ -86199,7 +86589,7 @@ async function _fetchSeriesTotals(domain, boundaries, viewGran, fetchGran) {
|
|
|
86199
86589
|
async function _fetchDayData(domain) {
|
|
86200
86590
|
const boundaries = _buildDayBoundaries(_periodStart, _periodEnd);
|
|
86201
86591
|
const labels = boundaries.map((b) => b.label);
|
|
86202
|
-
const totals = await _fetchSeriesTotals(domain, boundaries, "
|
|
86592
|
+
const totals = await _fetchSeriesTotals(domain, boundaries, "1h", "1h") ?? await _fetchTotalsThrottled(domain, boundaries, "1d");
|
|
86203
86593
|
return { labels, totals };
|
|
86204
86594
|
}
|
|
86205
86595
|
async function _fetchHourData(domain, dateISO) {
|
|
@@ -86247,7 +86637,9 @@ async function _fetchPrevYearTotals(domain, gran, boundaries) {
|
|
|
86247
86637
|
pe.setFullYear(pe.getFullYear() - 1);
|
|
86248
86638
|
return { ...b, startTs: ps.getTime(), endTs: pe.getTime() };
|
|
86249
86639
|
});
|
|
86250
|
-
const
|
|
86640
|
+
const seriesViewGran = gran === "1d" ? "1h" : gran;
|
|
86641
|
+
const seriesFetchGran = gran === "1M" ? "1d" : gran === "1d" ? "1h" : gran;
|
|
86642
|
+
const viaSeries = await _fetchSeriesTotals(domain, prevBoundaries, seriesViewGran, seriesFetchGran);
|
|
86251
86643
|
if (viaSeries) return viaSeries;
|
|
86252
86644
|
const fetchFn = _options.fetchConsumption;
|
|
86253
86645
|
const totals = new Array(prevBoundaries.length).fill(0);
|
|
@@ -155415,6 +155807,8 @@ var version = package_default.version || "0.0.0";
|
|
|
155415
155807
|
AlarmsSummaryTooltip,
|
|
155416
155808
|
AnnotationIndicator,
|
|
155417
155809
|
AnnotationTooltip,
|
|
155810
|
+
BAKED_PROFILE_KEYS,
|
|
155811
|
+
BAKED_PROFILE_VERSION,
|
|
155418
155812
|
BASDashboardController,
|
|
155419
155813
|
BASDashboardView,
|
|
155420
155814
|
BAS_DASHBOARD_CSS_PREFIX,
|
|
@@ -155737,6 +156131,7 @@ var version = package_default.version || "0.0.0";
|
|
|
155737
156131
|
createAmbienteGroupModal,
|
|
155738
156132
|
createAnnotationIndicator,
|
|
155739
156133
|
createBASDashboard,
|
|
156134
|
+
createBakedProfileSource,
|
|
155740
156135
|
createButtonBar,
|
|
155741
156136
|
createConsumption7DaysChart,
|
|
155742
156137
|
createConsumptionChartWidget,
|
|
@@ -155848,8 +156243,10 @@ var version = package_default.version || "0.0.0";
|
|
|
155848
156243
|
fetchThingsboardCustomerAttrsFromStorage,
|
|
155849
156244
|
fetchThingsboardCustomerServerScopeAttrs,
|
|
155850
156245
|
fetchTicketsForDevice,
|
|
156246
|
+
findNode,
|
|
155851
156247
|
findValue,
|
|
155852
156248
|
findValueWithDefault,
|
|
156249
|
+
flattenTree,
|
|
155853
156250
|
fmtPerc,
|
|
155854
156251
|
fmtPercLegacy,
|
|
155855
156252
|
formatAlarmRelativeTime,
|
|
@@ -155982,6 +156379,7 @@ var version = package_default.version || "0.0.0";
|
|
|
155982
156379
|
isAlarmActive,
|
|
155983
156380
|
isAnnotationOverdue,
|
|
155984
156381
|
isAssetCode,
|
|
156382
|
+
isBakedStale,
|
|
155985
156383
|
isConnectionStale,
|
|
155986
156384
|
isCustomerCode,
|
|
155987
156385
|
isDeviceIconType,
|
|
@@ -156002,6 +156400,7 @@ var version = package_default.version || "0.0.0";
|
|
|
156002
156400
|
isValidDeviceStatus,
|
|
156003
156401
|
isValidTimeFormat,
|
|
156004
156402
|
isWaterCategory,
|
|
156403
|
+
liftProfileToTree,
|
|
156005
156404
|
listDomains,
|
|
156006
156405
|
listGroups,
|
|
156007
156406
|
mapConnectionStatus,
|
|
@@ -156090,8 +156489,11 @@ var version = package_default.version || "0.0.0";
|
|
|
156090
156489
|
reopenFreshdeskTicket,
|
|
156091
156490
|
resolveActiveProfile,
|
|
156092
156491
|
resolveCategory,
|
|
156492
|
+
resolveClassification,
|
|
156093
156493
|
resolveGroup,
|
|
156094
156494
|
resolvePercentDecimals,
|
|
156495
|
+
resolveSubcategory,
|
|
156496
|
+
resolveWithFallback,
|
|
156095
156497
|
schedCreateDateInput,
|
|
156096
156498
|
schedCreateNumberInput,
|
|
156097
156499
|
schedCreateSelect,
|
|
@@ -156120,6 +156522,7 @@ var version = package_default.version || "0.0.0";
|
|
|
156120
156522
|
updateFreshdeskTicket,
|
|
156121
156523
|
upsertAlarmAnnotation,
|
|
156122
156524
|
validateProfile,
|
|
156525
|
+
validateTree,
|
|
156123
156526
|
version,
|
|
156124
156527
|
waterDeviceStatusIcons,
|
|
156125
156528
|
writeFreshdeskSyncedAtToTB,
|