myio-js-library 0.1.13 → 0.1.14
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/README.md +7 -6
- package/dist/index.cjs +4 -7
- package/dist/index.d.cts +4 -4
- package/dist/index.js +3 -6
- package/dist/myio-js-library.umd.js +3 -6
- package/dist/myio-js-library.umd.min.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -570,16 +570,17 @@ calcDeltaPercent(100, 100); // { value: 0, type: "neutral" }
|
|
|
570
570
|
calcDeltaPercent(0, 100); // { value: 100, type: "increase" }
|
|
571
571
|
```
|
|
572
572
|
|
|
573
|
-
##### `
|
|
573
|
+
##### `formatWaterByGroup(value: number, group: string): string`
|
|
574
574
|
|
|
575
|
-
Formats
|
|
575
|
+
Formats water group totals in m³. For values ≥ 1000, it returns the value in thousands of m³ with a simplified `x 10³` suffix.
|
|
576
576
|
|
|
577
|
+
**Examples**
|
|
577
578
|
```javascript
|
|
578
|
-
import {
|
|
579
|
+
import { formatWaterByGroup } from 'myio-js-library';
|
|
579
580
|
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
581
|
+
formatWaterByGroup(178, "Caixas D'Água"); // "1,78 m.c.a."
|
|
582
|
+
formatWaterByGroup(750, "Lojas"); // "750,00 M³"
|
|
583
|
+
formatWaterByGroup(2500, "Lojas"); // "2,50 M³ x 10³ "
|
|
583
584
|
```
|
|
584
585
|
|
|
585
586
|
#### Water Date Utilities
|
package/dist/index.cjs
CHANGED
|
@@ -43,9 +43,9 @@ __export(index_exports, {
|
|
|
43
43
|
formatDateToYMD: () => formatDateToYMD,
|
|
44
44
|
formatDateWithTimezoneOffset: () => formatDateWithTimezoneOffset,
|
|
45
45
|
formatEnergy: () => formatEnergy,
|
|
46
|
-
formatEnergyByGroup: () => formatEnergyByGroup,
|
|
47
46
|
formatNumberReadable: () => formatNumberReadable,
|
|
48
47
|
formatTankHeadFromCm: () => formatTankHeadFromCm,
|
|
48
|
+
formatWaterByGroup: () => formatWaterByGroup,
|
|
49
49
|
formatWaterVolumeM3: () => formatWaterVolumeM3,
|
|
50
50
|
getAvailableContexts: () => getAvailableContexts,
|
|
51
51
|
getDateRangeArray: () => getDateRangeArray,
|
|
@@ -189,18 +189,15 @@ function calcDeltaPercent(prev, current) {
|
|
|
189
189
|
return { value: 0, type: "neutral" };
|
|
190
190
|
}
|
|
191
191
|
}
|
|
192
|
-
function
|
|
192
|
+
function formatWaterByGroup(value, group) {
|
|
193
193
|
if (value === null || value === void 0 || isNaN(value)) {
|
|
194
194
|
return "-";
|
|
195
195
|
}
|
|
196
196
|
if (group === "Caixas D'\xC1gua") {
|
|
197
197
|
return formatTankHeadFromCm(value);
|
|
198
198
|
}
|
|
199
|
-
if (value >= 1e6) {
|
|
200
|
-
return formatWaterVolumeM3(value / 1e6) + " (GWh scale)";
|
|
201
|
-
}
|
|
202
199
|
if (value >= 1e3) {
|
|
203
|
-
return formatWaterVolumeM3(value / 1e3) + "
|
|
200
|
+
return formatWaterVolumeM3(value / 1e3) + " x 10\xB3 ";
|
|
204
201
|
}
|
|
205
202
|
return formatWaterVolumeM3(value);
|
|
206
203
|
}
|
|
@@ -1428,9 +1425,9 @@ function renderCardComponent({
|
|
|
1428
1425
|
formatDateToYMD,
|
|
1429
1426
|
formatDateWithTimezoneOffset,
|
|
1430
1427
|
formatEnergy,
|
|
1431
|
-
formatEnergyByGroup,
|
|
1432
1428
|
formatNumberReadable,
|
|
1433
1429
|
formatTankHeadFromCm,
|
|
1430
|
+
formatWaterByGroup,
|
|
1434
1431
|
formatWaterVolumeM3,
|
|
1435
1432
|
getAvailableContexts,
|
|
1436
1433
|
getDateRangeArray,
|
package/dist/index.d.cts
CHANGED
|
@@ -59,12 +59,12 @@ declare function calcDeltaPercent(prev: number, current: number): {
|
|
|
59
59
|
type: 'increase' | 'decrease' | 'neutral';
|
|
60
60
|
};
|
|
61
61
|
/**
|
|
62
|
-
* Formats
|
|
63
|
-
* @param value - The value to format
|
|
62
|
+
* Formats water values based on group type (from MAIN_WATER controller)
|
|
63
|
+
* @param value - The value to format in cubic meters
|
|
64
64
|
* @param group - The group type ('Caixas D\'Água', 'Lojas', 'Área Comum')
|
|
65
65
|
* @returns Formatted string with appropriate unit
|
|
66
66
|
*/
|
|
67
|
-
declare function
|
|
67
|
+
declare function formatWaterByGroup(value: number, group: string): string;
|
|
68
68
|
/**
|
|
69
69
|
* Formats all values in the same unit for consistent display
|
|
70
70
|
* @param values - Array of values to format
|
|
@@ -386,4 +386,4 @@ declare function renderCardComponent({ entityObject, handleActionDashboard, hand
|
|
|
386
386
|
handleClickCard: any;
|
|
387
387
|
}): any;
|
|
388
388
|
|
|
389
|
-
export { type StoreRow, type TimedValue, type WaterRow, addDetectionContext, addNamespace, averageByDay, buildWaterReportCSV, buildWaterStoresCSV, calcDeltaPercent, classify, classifyWaterLabel, classifyWaterLabels, decodePayload, decodePayloadBase64Xor, detectDeviceType, determineInterval, exportToCSV, exportToCSVAll, findValue, fmtPerc$1 as fmtPerc, fmtPerc as fmtPercLegacy, formatAllInSameUnit, formatAllInSameWaterUnit, formatDateForInput, formatDateToYMD, formatDateWithTimezoneOffset, formatEnergy,
|
|
389
|
+
export { type StoreRow, type TimedValue, type WaterRow, addDetectionContext, addNamespace, averageByDay, buildWaterReportCSV, buildWaterStoresCSV, calcDeltaPercent, classify, classifyWaterLabel, classifyWaterLabels, decodePayload, decodePayloadBase64Xor, detectDeviceType, determineInterval, exportToCSV, exportToCSVAll, findValue, fmtPerc$1 as fmtPerc, fmtPerc as fmtPercLegacy, formatAllInSameUnit, formatAllInSameWaterUnit, formatDateForInput, formatDateToYMD, formatDateWithTimezoneOffset, formatEnergy, formatNumberReadable, formatTankHeadFromCm, formatWaterByGroup, formatWaterVolumeM3, getAvailableContexts, getDateRangeArray, getSaoPauloISOString, getSaoPauloISOStringFixed, getValueByDatakey, getValueByDatakeyLegacy, getWaterCategories, groupByDay, isWaterCategory, normalizeRecipients, numbers, parseInputDateToDate, renderCardComponent, strings, timeWindowFromInputYMD, toCSV, toFixedSafe };
|
package/dist/index.js
CHANGED
|
@@ -126,18 +126,15 @@ function calcDeltaPercent(prev, current) {
|
|
|
126
126
|
return { value: 0, type: "neutral" };
|
|
127
127
|
}
|
|
128
128
|
}
|
|
129
|
-
function
|
|
129
|
+
function formatWaterByGroup(value, group) {
|
|
130
130
|
if (value === null || value === void 0 || isNaN(value)) {
|
|
131
131
|
return "-";
|
|
132
132
|
}
|
|
133
133
|
if (group === "Caixas D'\xC1gua") {
|
|
134
134
|
return formatTankHeadFromCm(value);
|
|
135
135
|
}
|
|
136
|
-
if (value >= 1e6) {
|
|
137
|
-
return formatWaterVolumeM3(value / 1e6) + " (GWh scale)";
|
|
138
|
-
}
|
|
139
136
|
if (value >= 1e3) {
|
|
140
|
-
return formatWaterVolumeM3(value / 1e3) + "
|
|
137
|
+
return formatWaterVolumeM3(value / 1e3) + " x 10\xB3 ";
|
|
141
138
|
}
|
|
142
139
|
return formatWaterVolumeM3(value);
|
|
143
140
|
}
|
|
@@ -1364,9 +1361,9 @@ export {
|
|
|
1364
1361
|
formatDateToYMD,
|
|
1365
1362
|
formatDateWithTimezoneOffset,
|
|
1366
1363
|
formatEnergy,
|
|
1367
|
-
formatEnergyByGroup,
|
|
1368
1364
|
formatNumberReadable,
|
|
1369
1365
|
formatTankHeadFromCm,
|
|
1366
|
+
formatWaterByGroup,
|
|
1370
1367
|
formatWaterVolumeM3,
|
|
1371
1368
|
getAvailableContexts,
|
|
1372
1369
|
getDateRangeArray,
|
|
@@ -132,18 +132,15 @@
|
|
|
132
132
|
return { value: 0, type: "neutral" };
|
|
133
133
|
}
|
|
134
134
|
}
|
|
135
|
-
function
|
|
135
|
+
function formatWaterByGroup(value, group) {
|
|
136
136
|
if (value === null || value === void 0 || isNaN(value)) {
|
|
137
137
|
return "-";
|
|
138
138
|
}
|
|
139
139
|
if (group === "Caixas D'\xC1gua") {
|
|
140
140
|
return formatTankHeadFromCm(value);
|
|
141
141
|
}
|
|
142
|
-
if (value >= 1e6) {
|
|
143
|
-
return formatWaterVolumeM3(value / 1e6) + " (GWh scale)";
|
|
144
|
-
}
|
|
145
142
|
if (value >= 1e3) {
|
|
146
|
-
return formatWaterVolumeM3(value / 1e3) + "
|
|
143
|
+
return formatWaterVolumeM3(value / 1e3) + " x 10\xB3 ";
|
|
147
144
|
}
|
|
148
145
|
return formatWaterVolumeM3(value);
|
|
149
146
|
}
|
|
@@ -1370,9 +1367,9 @@
|
|
|
1370
1367
|
exports.formatDateToYMD = formatDateToYMD;
|
|
1371
1368
|
exports.formatDateWithTimezoneOffset = formatDateWithTimezoneOffset;
|
|
1372
1369
|
exports.formatEnergy = formatEnergy;
|
|
1373
|
-
exports.formatEnergyByGroup = formatEnergyByGroup;
|
|
1374
1370
|
exports.formatNumberReadable = formatNumberReadable;
|
|
1375
1371
|
exports.formatTankHeadFromCm = formatTankHeadFromCm;
|
|
1372
|
+
exports.formatWaterByGroup = formatWaterByGroup;
|
|
1376
1373
|
exports.formatWaterVolumeM3 = formatWaterVolumeM3;
|
|
1377
1374
|
exports.getAvailableContexts = getAvailableContexts;
|
|
1378
1375
|
exports.getDateRangeArray = getDateRangeArray;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
(function(global,factory){typeof exports==="object"&&typeof module!=="undefined"?factory(exports):typeof define==="function"&&define.amd?define(["exports"],factory):(global=typeof globalThis!=="undefined"?globalThis:global||self,factory(global.MyIOLibrary={}))})(this,function(exports){"use strict";var __defProp=Object.defineProperty;var __export=(target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:true})};function formatEnergy(value,unit){if(value===null||value===void 0||isNaN(value)){return"-"}let adjustedValue=value;let adjustedUnit=unit;if(!adjustedUnit){if(value>=1e6){adjustedValue=value/1e6;adjustedUnit="GWh"}else if(value>=1e3){adjustedValue=value/1e3;adjustedUnit="MWh"}else{adjustedUnit="kWh"}}const formattedValue=adjustedValue.toLocaleString("pt-BR",{minimumFractionDigits:2,maximumFractionDigits:2});return`${formattedValue} ${adjustedUnit}`}function formatAllInSameUnit(values,targetUnit,sourceUnit="kWh"){const unitMultipliers={kWh:1,MWh:1e3,GWh:1e6};const targetMultiplier=unitMultipliers[targetUnit]||1;if(typeof values[0]==="number"){const numberValues=values;const sourceMultiplier=unitMultipliers[sourceUnit]||1;return numberValues.map(value=>{if(value===null||value===void 0||isNaN(value)){return"-"}const convertedValue=value*sourceMultiplier/targetMultiplier;return formatEnergy(convertedValue,targetUnit)})}const objectValues=values;return objectValues.map(item=>{if(item.value===null||item.value===void 0||isNaN(item.value)){return"-"}const sourceMultiplier=unitMultipliers[item.unit]||1;const convertedValue=item.value*sourceMultiplier/targetMultiplier;return formatEnergy(convertedValue,targetUnit)})}function fmtPerc(value){if(value===null||value===void 0||isNaN(value)||!isFinite(value)){return"-"}const percentage=value*100;return percentage.toLocaleString("pt-BR",{minimumFractionDigits:2,maximumFractionDigits:2})+"%"}function formatNumberReadable(value,locale="pt-BR",minimumFractionDigits=2,maximumFractionDigits=2){const n=typeof value==="string"?Number(value.replace(",",".")):Number(value);if(!Number.isFinite(n)){return"-"}const safe=Object.is(n,-0)?0:n;return safe.toLocaleString(locale,{minimumFractionDigits:minimumFractionDigits,maximumFractionDigits:maximumFractionDigits})}function formatWaterVolumeM3(value,locale="pt-BR"){if(value===null||value===void 0||isNaN(value)){return"-"}const formattedValue=value.toLocaleString(locale,{minimumFractionDigits:2,maximumFractionDigits:2});return`${formattedValue} M³`}function formatTankHeadFromCm(valueCm,locale="pt-BR"){if(valueCm===null||valueCm===void 0||isNaN(valueCm)){return"-"}const valueMeters=valueCm/100;const formattedValue=valueMeters.toLocaleString(locale,{minimumFractionDigits:2,maximumFractionDigits:2});return`${formattedValue} m.c.a.`}function calcDeltaPercent(prev,current){if(prev===null||prev===void 0||isNaN(prev)||current===null||current===void 0||isNaN(current)){return{value:0,type:"neutral"}}if(prev===0&¤t===0){return{value:0,type:"neutral"}}if(prev===0&¤t>0){return{value:100,type:"increase"}}if(prev===0&¤t<0){return{value:100,type:"decrease"}}const percentChange=(current-prev)/prev*100;if(percentChange>0){return{value:percentChange,type:"increase"}}else if(percentChange<0){return{value:Math.abs(percentChange),type:"decrease"}}else{return{value:0,type:"neutral"}}}function formatEnergyByGroup(value,group){if(value===null||value===void 0||isNaN(value)){return"-"}if(group==="Caixas D'Água"){return formatTankHeadFromCm(value)}if(value>=1e6){return formatWaterVolumeM3(value/1e6)+" (GWh scale)"}if(value>=1e3){return formatWaterVolumeM3(value/1e3)+" (MWh scale)"}return formatWaterVolumeM3(value)}function formatAllInSameWaterUnit(values){const max=Math.max(...values.filter(v=>!isNaN(v)&&v!==null&&v!==void 0));let divisor=1;let unit="M³";if(max>=1e6){divisor=1e6;unit="M³"}else if(max>=1e3){divisor=1e3;unit="M³"}return{format:val=>{if(val===null||val===void 0||isNaN(val)){return"-"}return(val/divisor).toFixed(2)+" "+unit},unit:unit}}function formatDateToYMD(date){if(!date){return""}const dateObj=new Date(date);if(isNaN(dateObj.getTime())){return""}const year=dateObj.getFullYear();const month=String(dateObj.getMonth()+1).padStart(2,"0");const day=String(dateObj.getDate()).padStart(2,"0");return`${year}-${month}-${day}`}function determineInterval(startDate,endDate){const start=new Date(startDate);const end=new Date(endDate);if(isNaN(start.getTime())||isNaN(end.getTime())){return"day"}const diffMs=end.getTime()-start.getTime();const diffDays=diffMs/(1e3*60*60*24);if(diffDays<=1){return"hour"}else if(diffDays<=7){return"day"}else if(diffDays<=31){return"week"}else if(diffDays<=365){return"month"}else{return"year"}}function getSaoPauloISOString(date,edge="start"){const dateObj=new Date(date);if(isNaN(dateObj.getTime())){return""}const saoPauloOffset=-3;const saoPauloDate=new Date(dateObj.getTime()+saoPauloOffset*60*60*1e3);if(edge==="start"){saoPauloDate.setHours(0,0,0,0)}else{saoPauloDate.setHours(23,59,59,999)}const utcDate=new Date(saoPauloDate.getTime()-saoPauloOffset*60*60*1e3);return utcDate.toISOString()}function getDateRangeArray(startDate,endDate,interval="day"){const start=new Date(startDate);const end=new Date(endDate);const dates=[];if(isNaN(start.getTime())||isNaN(end.getTime())||start>end){return dates}const current=new Date(start);while(current<=end){dates.push(new Date(current));switch(interval){case"day":current.setDate(current.getDate()+1);break;case"week":current.setDate(current.getDate()+7);break;case"month":current.setMonth(current.getMonth()+1);break;case"year":current.setFullYear(current.getFullYear()+1);break;default:current.setDate(current.getDate()+1)}}return dates}function formatDateForInput(date){if(!date||isNaN(date.getTime())){return""}const year=date.getFullYear();const month=String(date.getMonth()+1).padStart(2,"0");const day=String(date.getDate()).padStart(2,"0");return`${year}-${month}-${day}`}function parseInputDateToDate(inputDateStr){if(!inputDateStr){return null}const parts=inputDateStr.split("-");if(parts.length!==3){return null}const year=parseInt(parts[0],10);const month=parseInt(parts[1],10)-1;const day=parseInt(parts[2],10);if(isNaN(year)||isNaN(month)||isNaN(day)){return null}return new Date(year,month,day,0,0,0,0)}function timeWindowFromInputYMD(startYmd,endYmd,tzOffset="-03:00"){if(!startYmd||!endYmd){return{startTs:0,endTs:0}}const startParts=startYmd.split("-");const endParts=endYmd.split("-");if(startParts.length!==3||endParts.length!==3){return{startTs:0,endTs:0}}const startDate=new Date(parseInt(startParts[0],10),parseInt(startParts[1],10)-1,parseInt(startParts[2],10),0,0,0,0);const endDate=new Date(parseInt(endParts[0],10),parseInt(endParts[1],10)-1,parseInt(endParts[2],10),23,59,59,999);return{startTs:startDate.getTime(),endTs:endDate.getTime()}}function formatDateWithTimezoneOffset(date,endOfDay=false,tzOffset="-03:00"){if(!date||isNaN(date.getTime())){return""}const year=date.getFullYear();const month=String(date.getMonth()+1).padStart(2,"0");const day=String(date.getDate()).padStart(2,"0");let hours,minutes,seconds,milliseconds;if(endOfDay){hours="23";minutes="59";seconds="59";milliseconds="999"}else{hours=String(date.getHours()).padStart(2,"0");minutes=String(date.getMinutes()).padStart(2,"0");seconds=String(date.getSeconds()).padStart(2,"0");milliseconds=String(date.getMilliseconds()).padStart(3,"0")}return`${year}-${month}-${day}T${hours}:${minutes}:${seconds}.${milliseconds}${tzOffset}`}function getSaoPauloISOStringFixed(dateStr,endOfDay=false){if(!dateStr)return"";if(endOfDay){return`${dateStr}T23:59:59.999-03:00`}else{return`${dateStr}T00:00:00.000-03:00`}}function averageByDay(data){if(!data||data.length===0){return[]}const grouped={};data.forEach(item=>{if(!item||item.value===null||item.value===void 0||isNaN(item.value)){return}const date=new Date(item.ts);if(isNaN(date.getTime())){return}const day=date.toISOString().split("T")[0];if(!grouped[day]){grouped[day]=[]}grouped[day].push(Number(item.value))});const result=Object.entries(grouped).map(([day,values])=>{const sum=values.reduce((acc,val)=>acc+val,0);const average=sum/values.length;return{day:day,average:average}});result.sort((a,b)=>a.day.localeCompare(b.day));return result}function groupByDay(data){if(!data||data.length===0){return{}}const grouped={};data.forEach(item=>{if(!item||item.value===null||item.value===void 0||isNaN(item.value)){return}const date=new Date(item.ts);if(isNaN(date.getTime())){return}const day=date.toISOString().split("T")[0];if(!grouped[day]){grouped[day]=[]}grouped[day].push(Number(item.value))});return grouped}function exportToCSV(data,headers,filename){if(!data||data.length===0){return""}const csvHeaders=headers.join(",");const csvRows=data.map(row=>headers.map(header=>{const value=row[header];if(value===null||value===void 0){return""}const stringValue=String(value);if(stringValue.includes(",")||stringValue.includes('"')||stringValue.includes("\n")){return`"${stringValue.replace(/"/g,'""')}"`}return stringValue}).join(","));const csvContent=[csvHeaders,...csvRows].join("\n");return csvContent}function exportToCSVAll(storesData,headers,filename){if(!storesData||Object.keys(storesData).length===0){return""}const csvRows=[];const csvHeaders=["Store",...headers].join(",");csvRows.push(csvHeaders);Object.entries(storesData).forEach(([storeName,storeData])=>{if(!storeData||storeData.length===0){return}storeData.forEach(row=>{let formattedStoreName=storeName;if(storeName.includes(",")||storeName.includes('"')||storeName.includes("\n")){formattedStoreName=`"${storeName.replace(/"/g,'""')}"`}const csvRow=[formattedStoreName,...headers.map(header=>{const value=row[header];if(value===null||value===void 0){return""}const stringValue=String(value);if(stringValue.includes(",")||stringValue.includes('"')||stringValue.includes("\n")){return`"${stringValue.replace(/"/g,'""')}"`}return stringValue})].join(",");csvRows.push(csvRow)})});return csvRows.join("\n")}function buildWaterReportCSV(rows,meta){if(!rows||rows.length===0){return""}const csvRows=[];let totalConsumption=0;rows.forEach(row=>{const consumptionStr=String(row.totalConsumption).replace(",",".");const consumption=Number(consumptionStr)||0;totalConsumption+=consumption});const finalTotal=meta.total!==void 0?meta.total:totalConsumption;csvRows.push(["DATA EMISSÃO",meta.issueDate]);csvRows.push(["Total",finalTotal.toFixed(2)]);if(meta.name&&meta.identifier){csvRows.push(["Loja:",meta.name,meta.identifier])}csvRows.push(["Data","Dia da Semana","Consumo Médio (m³)","Consumo Mínimo (m³)","Consumo Máximo (m³)","Consumo (m³)"]);rows.forEach(row=>{csvRows.push([row.formattedDate,row.day,String(row.avgConsumption),String(row.minDemand),String(row.maxDemand),String(row.totalConsumption)])});return csvRows.map(row=>row.join(";")).join("\n")}function buildWaterStoresCSV(rows,meta){if(!rows||rows.length===0){return""}const csvRows=[];let totalConsumption=0;rows.forEach(row=>{const consumption=row.consumptionM3!==void 0?row.consumptionM3:row.consumptionKwh||0;totalConsumption+=consumption});const finalTotal=meta.total!==void 0?meta.total:totalConsumption;csvRows.push(["DATA EMISSÃO",meta.issueDate]);csvRows.push(["Total",finalTotal.toFixed(2)]);csvRows.push(["Loja","Identificador","Consumo"]);rows.forEach(row=>{const label=row.entityLabel||row.deviceName||"-";const deviceId=row.deviceId||"-";const consumption=row.consumptionM3!==void 0?row.consumptionM3:row.consumptionKwh||0;const formattedConsumption=consumption!==null&&consumption!==void 0?formatNumberReadable(consumption):"0,00";csvRows.push([label,deviceId,formattedConsumption])});return csvRows.map(row=>row.join(";")).join("\n")}function toCSV(rows,delimiter=";"){if(!rows||rows.length===0){return""}return rows.map(row=>row.map(cell=>{const value=String(cell);if(value.includes(delimiter)||value.includes('"')||value.includes("\n")){return`"${value.replace(/"/g,'""')}"`}return value}).join(delimiter)).join("\n")}function classify(entity,criteria){if(!entity||!criteria){return{category:"unknown",confidence:0}}let category="unknown";let subcategory;let confidence=0;if(entity.type){switch(entity.type.toLowerCase()){case"consumption":category="energy_consumption";confidence=.9;break;case"generation":category="energy_generation";confidence=.9;break;case"storage":category="energy_storage";confidence=.9;break;case"distribution":category="energy_distribution";confidence=.8;break;default:category="energy_other";confidence=.5}}if(entity.powerRating){const power=parseFloat(entity.powerRating);if(!isNaN(power)){if(power<1e3){subcategory="small_scale"}else if(power<1e4){subcategory="medium_scale"}else{subcategory="large_scale"}confidence=Math.min(confidence+.1,1)}}return{category:category,subcategory:subcategory,confidence:confidence}}function classifyWaterLabel(label){if(!label){console.warn('classifyWaterLabel: empty label, defaulting to "Lojas"');return"Lojas"}const normalizedLabel=label.toLowerCase().trim();if(/rel[óo]gio|caixa|superior|inferior|nível_terraço/.test(normalizedLabel)){return"Caixas D'Água"}if(/administra|bomba|chiller|adm/.test(normalizedLabel)){return"Área Comum"}return"Lojas"}function classifyWaterLabels(labels){const counts={"Caixas D'Água":0,Lojas:0,"Área Comum":0,total:0};labels.forEach(label=>{const category=classifyWaterLabel(label);counts[category]++;counts.total++});return counts}function getWaterCategories(){return["Caixas D'Água","Lojas","Área Comum"]}function isWaterCategory(label,category){return classifyWaterLabel(label)===category}function getValueByDatakey(data,datakey){if(!data||!datakey){return void 0}if(Array.isArray(data)){for(const item of data){const value=getValueByDatakey(item,datakey);if(value!==void 0){return value}}return void 0}if(typeof data==="object"&&data!==null){const keys=datakey.split(".");let current=data;for(const key of keys){if(current===null||current===void 0){return void 0}if(key.includes("[")&&key.includes("]")){const arrayKey=key.substring(0,key.indexOf("["));const indexMatch=key.match(/\[(\d+)\]/);if(indexMatch){const index=parseInt(indexMatch[1],10);current=current[arrayKey];if(Array.isArray(current)&&index>=0&&index<current.length){current=current[index]}else{return void 0}}else{return void 0}}else{current=current[key]}}return current}return void 0}function getValueByDatakeyLegacy(dataList,dataSourceNameTarget,dataKeyTarget){if(!Array.isArray(dataList)||!dataSourceNameTarget||!dataKeyTarget){return void 0}for(const item of dataList){if(item&&item.dataSourceName===dataSourceNameTarget&&item.dataKey===dataKeyTarget){return item.value}}return void 0}function findValue(data,keyOrPath,legacyDataKey){if(legacyDataKey!==void 0){return getValueByDatakeyLegacy(data,keyOrPath,legacyDataKey)}return getValueByDatakey(data,keyOrPath)}var contexts={building:name=>{const upper=name.toUpperCase();if(upper.includes("COMPRESSOR"))return"COMPRESSOR";if(upper.includes("VENT"))return"VENTILADOR";if(upper.includes("AUTOMATICO")||upper.includes("AUTOMÁTICO"))return"SELETOR_AUTO_MANUAL";if(upper.includes("TERMOSTATO"))return"TERMOSTATO";if(upper.includes("3F"))return"3F_MEDIDOR";if(upper.includes("TERMO")||upper.includes("TEMP"))return"TERMOSTATO";if(upper.includes("HIDR"))return"HIDROMETRO";if(upper.includes("ABRE"))return"SOLENOIDE";if(upper.includes("RECALQUE"))return"MOTOR";if(upper.includes("AUTOMACAO")||upper.includes("AUTOMAÇÃO"))return"GLOBAL_AUTOMACAO";if(upper.includes("AC"))return"CONTROLE REMOTO";if(upper.includes("SCD"))return"CAIXA_D_AGUA";return"default"},mall:name=>{const upper=name.toUpperCase();if(upper.includes("CHILLER"))return"CHILLER";if(upper.includes("ESCADA"))return"ESCADA_ROLANTE";if(upper.includes("LOJA"))return"LOJA_SENSOR";if(upper.includes("ILUMINACAO")||upper.includes("ILUMINAÇÃO"))return"ILUMINACAO";return"default"}};function detectDeviceType(name,context="building"){if(typeof name!=="string"){throw new Error("Device name must be a string.")}const detectFunction=contexts[context];if(!detectFunction){console.warn(`[myio-js-library] Context "${context}" not found. Using default fallback.`);return contexts.building(name)}return detectFunction(name)}function getAvailableContexts(){return Object.keys(contexts)}function addDetectionContext(contextName,detectFunction){if(typeof contextName!=="string"){throw new Error("Context name must be a string.")}if(typeof detectFunction!=="function"){throw new Error("Detection function must be a function.")}contexts[contextName]=detectFunction}function addNamespace(payload,namespace=""){if(!payload||typeof payload!=="object"||Array.isArray(payload)){throw new Error("Payload must be an object.")}const keys=Object.keys(payload);const suffix=namespace.trim()?` (${namespace.trim()})`:"";return keys.reduce((acc,key)=>{acc[`${key}${suffix}`]=payload[key];return acc},{})}var numbers_exports={};__export(numbers_exports,{fmtPerc:()=>fmtPerc2,toFixedSafe:()=>toFixedSafe});function fmtPerc2(x,digits=2){if(!Number.isFinite(x))return"—";return(x*100).toFixed(digits)+"%"}function toFixedSafe(x,digits=2){if(!Number.isFinite(x))return"—";return x.toFixed(digits)}var strings_exports={};__export(strings_exports,{normalizeRecipients:()=>normalizeRecipients});function normalizeRecipients(val){if(val===null||val===void 0||val==="")return"";if(Object.prototype.toString.call(val)==="[object Array]"){return val.filter(Boolean).join(",")}let s=String(val).trim();if(/^\s*\[/.test(s)){try{const arr=JSON.parse(s);if(Object.prototype.toString.call(arr)==="[object Array]"){return arr.filter(Boolean).join(",")}}catch{}}s=s.replace(/[;\s]+/g,",");s=s.replace(/,+/g,",").replace(/^,|,$/g,"");return s}function decodePayload(encoded,key){const bytes=base64ToBytesStrict(encoded);if(bytes.length===0)return"";if(key===""||key===void 0||key===null){return(new TextDecoder).decode(bytes)}if(typeof key==="number"&&Number.isFinite(key)){const k=key&255;for(let i=0;i<bytes.length;i++)bytes[i]^=k;return(new TextDecoder).decode(bytes)}const keyStr=String(key);const keyBytes=(new TextEncoder).encode(keyStr);if(keyBytes.length===0){return(new TextDecoder).decode(bytes)}for(let i=0;i<bytes.length;i++){bytes[i]^=keyBytes[i%keyBytes.length]}return(new TextDecoder).decode(bytes)}function decodePayloadBase64Xor(encoded,xorKey=73){const bytes=base64ToBytesStrict(encoded);for(let i=0;i<bytes.length;i++)bytes[i]^=xorKey&255;return(new TextDecoder).decode(bytes)}function base64ToBytesStrict(b64){if(b64===""||b64===void 0||b64===null)return new Uint8Array;const s=String(b64).replace(/\s+/g,"");const re=/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/;if(!re.test(s))throw new Error("Invalid base64");if(typeof Buffer!=="undefined"&&Buffer.from){return Uint8Array.from(Buffer.from(s,"base64"))}const bin=atob(s);const out=new Uint8Array(bin.length);for(let i=0;i<bin.length;i++)out[i]=bin.charCodeAt(i);return out}function renderCardComponent({entityObject:entityObject,handleActionDashboard:handleActionDashboard,handleActionReport:handleActionReport,handleActionSettings:handleActionSettings,handleSelect:handleSelect,handInfo:handInfo,handleClickCard:handleClickCard}){const{entityId:entityId,labelOrName:labelOrName,entityType:entityType,deviceType:deviceType,slaveId:slaveId,ingestionId:ingestionId,val:val,centralId:centralId,updatedIdentifiers:updatedIdentifiers={},isOn:isOn=false,perc:perc=0,group:group,connectionStatus:connectionStatus,centralName:centralName,connectionStatusTime:connectionStatusTime,timaVal:timaVal,valType:valType}=entityObject;const MyIO=typeof MyIOLibrary!=="undefined"&&MyIOLibrary||typeof window!=="undefined"&&window.MyIOLibrary||{formatEnergyByGroup:(v,g)=>`${v} kWh`,formatNumberReadable:n=>Number(n??0).toFixed(1)};let valFormatted=MyIO.formatEnergyByGroup(val);if(valType==="ENERGY"){valFormatted=MyIO.formatEnergyByGroup(val)}else if(valType==="WATER"){valFormatted=`${val} m³`}else if(valType==="TANK"){valFormatted=`${val} m.c.a`}else{valFormatted=val}const percFormatted=MyIO.formatNumberReadable(perc);if(!document.getElementById("myio-card-styles")){const style=document.createElement("style");style.id="myio-card-styles";style.textContent=` \n.device-card-centered,\n.clickable {\n width: 100%;\n border-radius: 10px;\n padding: 8px 12px;\n background: #fff;\n box-shadow: 0 4px 10px rgba(0, 0, 0, .05);\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n transition: transform .2s;\n min-height: 140px;\n box-sizing: border-box;\n overflow: hidden;\n}\n\n.device-card-centered:hover,\n.clickable:hover {\n transform: scale(1.05);\n}\n\n.device-title-row {\n width: 100%;\n display: flex;\n justify-content: center;\n align-items: center;\n margin-bottom: 4px;\n padding: 0 4px;\n min-height: 22px;\n}\n\n.device-title {\n font-weight: 700;\n font-size: .85rem;\n text-align: center;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n max-width: 90%;\n line-height: 1.1;\n}\n\n.device-image {\n max-height: 44px;\n width: auto;\n margin: 4px 0;\n display: block;\n}\n\n.device-data-row {\n display: flex;\n justify-content: center;\n align-items: center;\n margin-top: auto;\n margin-bottom: 6px;\n gap: 6px;\n width: 100%;\n}\n\n.consumption-main {\n font-size: .9rem;\n font-weight: 700;\n color: #28a745;\n display: flex;\n align-items: center;\n gap: 6px;\n justify-content: center;\n white-space: nowrap;\n}\n\n.device-title-percent {\n font-size: .75rem;\n color: rgba(0, 0, 0, .45);\n font-weight: 500;\n}\n\n.flash {\n animation: flash 1s infinite;\n color: #ff9800;\n}\n\n@keyframes flash {\n 0% {\n opacity: 1;\n }\n 50% {\n opacity: .2;\n }\n 100% {\n opacity: 1;\n }\n}\n\n.card-actions {\n width: 10%;\n height: 100%;\n box-shadow: 1px 0 2px rgba(0, 0, 0, .1);\n display: flex;\n flex-direction: column;\n padding: 0 4px;\n justify-content: space-around;\n align-items: center;\n}\n\n.card-action img {\n width: 24px;\n height: 24px;\n transition: transform .2s ease;\n cursor: pointer;\n}\n\n.card-action img:hover {\n transform: scale(1.15);\n}\n\n.device-card-centered.offline {\n border: 2px solid #ff4d4f;\n animation: border-blink 1s infinite;\n}\n\n\n.device-info {\n position: absolute;\n top: 8px; /* distância do topo */\n right: 8px; /* distância da direita */\n background: none;\n border: none;\n cursor: pointer;\n padding: 4px;\n border-radius: 50%;\n transition: background 0.2s;\n}\n\n.device-info:hover {\n background: rgba(0, 0, 0, 0.05);\n}\n\n.device-card-centered.flipped .device-card-inner {\n transform: rotateY(180deg);\n}\n\n@keyframes border-blink {\n 0%, 100% { box-shadow: 0 0 8px rgba(255, 77, 79, 0.9); }\n 50% { box-shadow: 0 0 16px rgba(255, 0, 0, 0.6); }\n}\n\n.device-card-centered.offline .flash-icon {\n color: #ff4d4f !important;\n font-size: 1.2rem;\n} \n.device-card-centered {\n perspective: 1000px; /* perspectiva para 3D */\n}\n\n.device-card-inner {\n position: relative;\n width: 100%;\n height: 100%;\n transform-style: preserve-3d;\n}\n\n.device-card-front {\n display: flex;\n flex-direction: row;\n justify-content: flex-start;\n align-items: flex-start; /* topo */\n position: absolute;\n width: 100%;\n height: 100%;\n top: 0;\n left: 0;\n backface-visibility: hidden;\n}\n\n.device-card-back {\n display: flex;\n flex-direction: column; /* muda para coluna se quiser empilhar elementos verticalmente */\n justify-content: flex-start; /* conteúdo começa do topo */\n align-items: center; /* centraliza horizontalmente */\n position: absolute;\n width: 100%;\n height: 100%;\n top: 0;\n left: 0;\n backface-visibility: hidden;\n transform: rotateY(180deg); /* mantém flip */\n padding: 10px; /* opcional: espaço interno */\n gap: 10px; /* opcional: espaço entre elementos */\n}\n\n\n\n.device-info {\n position: absolute;\n top: 8px; /* distância do topo */\n right: 8px; /* distância da direita */\n background: none;\n border: none;\n cursor: pointer;\n padding: 4px;\n border-radius: 50%;\n transition: background 0.2s;l\n}\n.device-card-back {\n transform: rotateY(180deg); /* faz o flip funcionar */\n}\n\n.device-card-front .device-info,\n.device-card-back .device-info {\n position: absolute; /* tira do fluxo do flex */\n top: 0; /* topo do card */\n right: 8px; /* canto direito */\n margin: 0; /* remove qualquer margem que empurre o botão */\n display: flex; /* mantém o conteúdo do botão centralizado */\n align-items: center; \n justify-content: center; \n padding: 4px; \n border-radius: 50%; \n cursor: pointer;\n z-index: 10; \n}\n\n\n.device-card-back {\n\n display: flex;\n flex-direction: column; /* empilha os elementos */\n justify-content: flex-start;\n align-items: flex-start; /* tudo à esquerda por padrão */\n padding: 10px;\n gap: 10px;\n height: 100%;\n margin-left: -10px; \n}\n\n.device-card-back .value-container {\n display: flex;\n flex-direction: row; /* ícone e valor lado a lado */\n align-items: center;\n gap: 5px;\n color: #c19efc; /* roxo clarinho */\n align-self: center; /* centraliza horizontalmente no card */\n}\n\n.device-card-back #lastconsumptionTime {\n\n display: flex;\n flex-direction: column;\n align-items: flex-start; /* mantém à esquerda */\n gap: 2px;\n font-size: 11px;\n font-weight: bold;\n color: black;\n}\n\n\n.device-card-centered.flipped .device-card-inner {\n transform: rotateY(180deg);\n}\n\n.flash-icon.flash {\n animation: icon-blink 1s infinite;\n}\n\n@keyframes icon-blink {\n 0%, 100% { opacity: 1; transform: scale(1); }\n 50% { opacity: 0.2; transform: scale(1.2); }\n}\n\n.device-card-centered.offline .flash-icon {\n color: #ff4d4f !important;\n}\n\n.device-card-centered.online .flash-icon {\n color: #28a745 !important; /* verde premium para online */\n}\n `;document.head.appendChild(style)}let formattedDateVal;let formattedDate;let Infcolor="#5cb85c";if(connectionStatusTime){const date=new Date(connectionStatusTime);const day=String(date.getDate()).padStart(2,"0");const month=String(date.getMonth()+1).padStart(2,"0");const year=date.getFullYear();const hours=String(date.getHours()).padStart(2,"0");const minutes=String(date.getMinutes()).padStart(2,"0");formattedDate=`Online: (${day}/${month}/${year} - ${hours}:${minutes})`;const datVal=new Date(timaVal);const dayVal=String(datVal.getDate()).padStart(2,"0");const monthVal=String(datVal.getMonth()+1).padStart(2,"0");const yearVal=date.getFullYear();const hoursVal=String(date.getHours()).padStart(2,"0");const minutesVal=String(date.getMinutes()).padStart(2,"0");const now=new Date;const diffMs=now-datVal;const diffMinutes=Math.floor(diffMs/(1e3*60));const diffHours=Math.floor(diffMs/(1e3*60*60));const diffDays=Math.floor(diffMs/(1e3*60*60*24));let diffText="";if(diffMinutes<60){diffText=`${diffMinutes} minuto${diffMinutes!==1?"s":""}`}else if(diffHours<24){diffText=`${diffHours} hora${diffHours!==1?"s":""}`}else{diffText=`${diffDays} dia${diffDays!==1?"s":""} `}formattedDateVal=`${dayVal}/${monthVal}/${yearVal} - ${hoursVal}:${minutesVal} (${diffText})`;if(diffHours>=24){Infcolor="#cc2900"}else if(diffMinutes>=30){Infcolor="#e89105"}}else{Infcolor="#d6dcdd"}function normalizeString(str){return str.normalize("NFD").replace(/[\u0300-\u036f]/g,"").toUpperCase()}const deviceImages={MOTOR:"https://dashboard.myio-bas.com/api/images/public/8Ezn8qVBJ3jXD0iDfnEAZ0MZhAP1b5Ts","3F_MEDIDOR":"https://dashboard.myio-bas.com/api/images/public/f9Ce4meybsdaAhAkUlAfy5ei3I4kcN4k",RELOGIO:"https://dashboard.myio-bas.com/api/images/public/ljHZostWg0G5AfKiyM8oZixWRIIGRASB",HIDROMETRO:"https://dashboard.myio-bas.com/api/images/public/aMQYFJbGHs9gQbQkMn6XseAlUZHanBR4",ENTRADA:"https://dashboard.myio-bas.com/api/images/public/TQHPFqiejMW6lOSVsb8Pi85WtC0QKOLU",CAIXA_DAGUA:"https://dashboard.myio-bas.com/api/images/public/3t6WVhMQJFsrKA8bSZmrngDsNPkZV7fq"};const defaultImage="https://cdn-icons-png.flaticon.com/512/1178/1178428.png";const nameType=normalizeString(deviceType);const img=deviceImages[nameType]||defaultImage;const html=`\n <div class="device-card-centered clickable ${connectionStatus==="offline"?"offline":""}"\n data-entity-id="${entityId}"\n data-entity-label="${labelOrName}"\n data-entity-type="${entityType}"\n data-entity-slaveid="${slaveId}"\n data-entity-ingestionid="${ingestionId}"\n data-entity-consumption="${val}"\n data-entity-centralid="${centralId}"\n data-entity-updated-identifiers='${JSON.stringify(updatedIdentifiers)}'>\n <div class="device-card-inner" style="width:100%; height:100%; transform-style: preserve-3d; transition: transform 0.6s;">\n <div class="device-card-front">\n\n <div class="card-actions" >\n ${typeof handleActionDashboard==="function"?`\n <div class="card-action action-dashboard" data-action="dashboard" title="Dashboard">\n <img src="https://dashboard.myio-bas.com/api/images/public/TAVXE0sTbCZylwGsMF9lIWdllBB3iFtS"/>\n </div>`:``}\n ${typeof handleActionReport==="function"?`\n <div class="card-action action-report" data-action="report" title="Relatório">\n <img src="https://dashboard.myio-bas.com/api/images/public/d9XuQwMYQCG2otvtNSlqUHGavGaSSpz4"/>\n </div>`:``}\n ${typeof handleActionSettings==="function"?`\n <div class="card-action action-settings" data-action="settings" title="Configurações">\n <img src="https://dashboard.myio-bas.com/api/images/public/5n9tze6vED2uwIs5VvJxGzNNZ9eV4yoz"/>\n </div>`:``}\n ${typeof handleSelect==="function"?`\n <input class="card-action action-checker" data-action="checker" title="Selecionar" type="checkbox">`:``}\n </div>\n\n <div style="display:flex;flex-direction:column;justify-content:center;align-items:center;height:100%;width:85%">\n <div class="device-title-row">\n <span class="device-title" title="${labelOrName}">\n ${String(labelOrName??"").length>15?String(labelOrName).slice(0,15)+"…":String(labelOrName??"")}\n </span>\n </div>\n <img class="device-image" src="${img}" />\n <div class="device-data-row">\n <div class="consumption-main">\n <span class="flash-icon ${connectionStatus==="offline"?"flash":isOn?"flash":""}">\n ${connectionStatus==="offline"?"🚨":"⚡"}\n </span>\n <span class="consumption-value" data-entity-consumption="${val}">${valFormatted}</span>\n <span class="device-title-percent">(${percFormatted}%)</span>\n </div>\n </div>\n </div>\n \n ${handInfo?`\n <button id="infoButtom-front" class="device-info info-button">\n <svg xmlns="http://www.w3.org/2000/svg" height="17px" viewBox="0 -960 960 960" width="17px" fill=${Infcolor}>\n <path d="M440-280h80v-240h-80v240Zm40-320q17 0 28.5-11.5T520-640q0-17-11.5-28.5T480-680q-17 0-28.5 11.5T440-640q0 17 11.5 28.5T480-600Zm0 520q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm0-80q134 0 227-93t93-227q0-134-93-227t-227-93q-134 0-227 93t-93 227q0 134 93 227t227 93Zm0-320Z"/>\n </svg>\n </button>`:``}\n </div>\n <div class="device-card-back" >\n <div id="status-bar"> \n <div id="status-information">\n <div style="font-size: 0.85rem; font-weight: bold; line-height: 1;"><span>Central: ${centralName}</span></div>\n <div style="display: flex; flex-direction: row; gap: 4px; font-weight: bold; align-items: center;">\n <div style="font-size: 12px; font-weight: bold; line-height: 1;"><span> ${formattedDate}</span></div>\n <div style="font-size: 10px; line-height: 1;"><span></span></div> \n </div>\n </div>\n <button id="infoButtom-back" class="device-info" style="background:none; border:none; cursor:pointer;">\n <svg xmlns="http://www.w3.org/2000/svg" height="17px" viewBox="0 -960 960 960" width="17px" fill=${Infcolor}>\n <path d="M440-280h80v-240h-80v240Zm40-320q17 0 28.5-11.5T520-640q0-17-11.5-28.5T480-680q-17 0-28.5 11.5T440-640q0 17 11.5 28.5T480-600Zm0 520q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm0-80q134 0 227-93t93-227q0-134-93-227t-227-93q-134 0-227 93t-93 227q0 134 93 227t227 93Zm0-320Z"/>\n </svg>\n </button>\n </div>\n\n <div class="value-container">\n <svg xmlns="http://www.w3.org/2000/svg" height="30px" viewBox="0 -960 960 960" width="30px" fill="#dea404">\n <path d="m456-200 174-340H510v-220L330-420h126v220Zm24 120q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm0-80q134 0 227-93t93-227q0-134-93-227t-227-93q-134 0-227 93t-93 227q0 134 93 227t227 93Zm0-320Z"/>\n </svg>\n <div><span>${MyIO.formatEnergyByGroup(val/1e3)||"-"}</span></div>\n </div>\n\n <div id="lastconsumptionTime">\n <div style="font-size: 12px; font-weight: bold; color: black; line-height: 1;">Ultima Telemetria:</div>\n <div style="font-size: 11px; font-weight: bold; color: black; line-height: 1;">${formattedDateVal}</div>\n </div>\n </div>\n </div>\n </div> \n </div>\n \n `;const $card=$(html);if(typeof handleActionDashboard==="function"){$card.find(".action-dashboard").on("click",e=>{e.stopPropagation();handleActionDashboard(entityObject)})}if(typeof handleActionReport==="function"){$card.find(".action-report").on("click",e=>{e.stopPropagation();handleActionReport(entityObject)})}if(typeof handleActionSettings==="function"){$card.find(".action-settings").on("click",e=>{e.stopPropagation();handleActionSettings(entityObject)})}if(typeof handleSelect==="function"){$card.find(".action-checker").on("click",e=>{e.stopPropagation();handleSelect(entityObject)})}if(typeof handleClickCard==="function"){$card.find(".action-checker").on("click",e=>{e.stopPropagation();handleClickCard(entityObject)})}$card.on("click",e=>{if(!$(e.target).closest(".card-action").length){if(typeof handleClickCard==="function"){handleClickCard(entityObject)}else if(typeof handleActionDashboard==="function"){handleActionDashboard(entityObject)}}});$card.find("#infoButtom-front").on("click",function(e){e.stopPropagation();$(this).closest(".device-card-centered").addClass("flipped")});$card.find("#infoButtom-back").on("click",function(e){e.stopPropagation();$(this).closest(".device-card-centered").removeClass("flipped")});return $card}exports.addDetectionContext=addDetectionContext;exports.addNamespace=addNamespace;exports.averageByDay=averageByDay;exports.buildWaterReportCSV=buildWaterReportCSV;exports.buildWaterStoresCSV=buildWaterStoresCSV;exports.calcDeltaPercent=calcDeltaPercent;exports.classify=classify;exports.classifyWaterLabel=classifyWaterLabel;exports.classifyWaterLabels=classifyWaterLabels;exports.decodePayload=decodePayload;exports.decodePayloadBase64Xor=decodePayloadBase64Xor;exports.detectDeviceType=detectDeviceType;exports.determineInterval=determineInterval;exports.exportToCSV=exportToCSV;exports.exportToCSVAll=exportToCSVAll;exports.findValue=findValue;exports.fmtPerc=fmtPerc;exports.fmtPercLegacy=fmtPerc2;exports.formatAllInSameUnit=formatAllInSameUnit;exports.formatAllInSameWaterUnit=formatAllInSameWaterUnit;exports.formatDateForInput=formatDateForInput;exports.formatDateToYMD=formatDateToYMD;exports.formatDateWithTimezoneOffset=formatDateWithTimezoneOffset;exports.formatEnergy=formatEnergy;exports.formatEnergyByGroup=formatEnergyByGroup;exports.formatNumberReadable=formatNumberReadable;exports.formatTankHeadFromCm=formatTankHeadFromCm;exports.formatWaterVolumeM3=formatWaterVolumeM3;exports.getAvailableContexts=getAvailableContexts;exports.getDateRangeArray=getDateRangeArray;exports.getSaoPauloISOString=getSaoPauloISOString;exports.getSaoPauloISOStringFixed=getSaoPauloISOStringFixed;exports.getValueByDatakey=getValueByDatakey;exports.getValueByDatakeyLegacy=getValueByDatakeyLegacy;exports.getWaterCategories=getWaterCategories;exports.groupByDay=groupByDay;exports.isWaterCategory=isWaterCategory;exports.normalizeRecipients=normalizeRecipients;exports.numbers=numbers_exports;exports.parseInputDateToDate=parseInputDateToDate;exports.renderCardComponent=renderCardComponent;exports.strings=strings_exports;exports.timeWindowFromInputYMD=timeWindowFromInputYMD;exports.toCSV=toCSV;exports.toFixedSafe=toFixedSafe});
|
|
1
|
+
(function(global,factory){typeof exports==="object"&&typeof module!=="undefined"?factory(exports):typeof define==="function"&&define.amd?define(["exports"],factory):(global=typeof globalThis!=="undefined"?globalThis:global||self,factory(global.MyIOLibrary={}))})(this,function(exports){"use strict";var __defProp=Object.defineProperty;var __export=(target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:true})};function formatEnergy(value,unit){if(value===null||value===void 0||isNaN(value)){return"-"}let adjustedValue=value;let adjustedUnit=unit;if(!adjustedUnit){if(value>=1e6){adjustedValue=value/1e6;adjustedUnit="GWh"}else if(value>=1e3){adjustedValue=value/1e3;adjustedUnit="MWh"}else{adjustedUnit="kWh"}}const formattedValue=adjustedValue.toLocaleString("pt-BR",{minimumFractionDigits:2,maximumFractionDigits:2});return`${formattedValue} ${adjustedUnit}`}function formatAllInSameUnit(values,targetUnit,sourceUnit="kWh"){const unitMultipliers={kWh:1,MWh:1e3,GWh:1e6};const targetMultiplier=unitMultipliers[targetUnit]||1;if(typeof values[0]==="number"){const numberValues=values;const sourceMultiplier=unitMultipliers[sourceUnit]||1;return numberValues.map(value=>{if(value===null||value===void 0||isNaN(value)){return"-"}const convertedValue=value*sourceMultiplier/targetMultiplier;return formatEnergy(convertedValue,targetUnit)})}const objectValues=values;return objectValues.map(item=>{if(item.value===null||item.value===void 0||isNaN(item.value)){return"-"}const sourceMultiplier=unitMultipliers[item.unit]||1;const convertedValue=item.value*sourceMultiplier/targetMultiplier;return formatEnergy(convertedValue,targetUnit)})}function fmtPerc(value){if(value===null||value===void 0||isNaN(value)||!isFinite(value)){return"-"}const percentage=value*100;return percentage.toLocaleString("pt-BR",{minimumFractionDigits:2,maximumFractionDigits:2})+"%"}function formatNumberReadable(value,locale="pt-BR",minimumFractionDigits=2,maximumFractionDigits=2){const n=typeof value==="string"?Number(value.replace(",",".")):Number(value);if(!Number.isFinite(n)){return"-"}const safe=Object.is(n,-0)?0:n;return safe.toLocaleString(locale,{minimumFractionDigits:minimumFractionDigits,maximumFractionDigits:maximumFractionDigits})}function formatWaterVolumeM3(value,locale="pt-BR"){if(value===null||value===void 0||isNaN(value)){return"-"}const formattedValue=value.toLocaleString(locale,{minimumFractionDigits:2,maximumFractionDigits:2});return`${formattedValue} M³`}function formatTankHeadFromCm(valueCm,locale="pt-BR"){if(valueCm===null||valueCm===void 0||isNaN(valueCm)){return"-"}const valueMeters=valueCm/100;const formattedValue=valueMeters.toLocaleString(locale,{minimumFractionDigits:2,maximumFractionDigits:2});return`${formattedValue} m.c.a.`}function calcDeltaPercent(prev,current){if(prev===null||prev===void 0||isNaN(prev)||current===null||current===void 0||isNaN(current)){return{value:0,type:"neutral"}}if(prev===0&¤t===0){return{value:0,type:"neutral"}}if(prev===0&¤t>0){return{value:100,type:"increase"}}if(prev===0&¤t<0){return{value:100,type:"decrease"}}const percentChange=(current-prev)/prev*100;if(percentChange>0){return{value:percentChange,type:"increase"}}else if(percentChange<0){return{value:Math.abs(percentChange),type:"decrease"}}else{return{value:0,type:"neutral"}}}function formatWaterByGroup(value,group){if(value===null||value===void 0||isNaN(value)){return"-"}if(group==="Caixas D'Água"){return formatTankHeadFromCm(value)}if(value>=1e3){return formatWaterVolumeM3(value/1e3)+" x 10³ "}return formatWaterVolumeM3(value)}function formatAllInSameWaterUnit(values){const max=Math.max(...values.filter(v=>!isNaN(v)&&v!==null&&v!==void 0));let divisor=1;let unit="M³";if(max>=1e6){divisor=1e6;unit="M³"}else if(max>=1e3){divisor=1e3;unit="M³"}return{format:val=>{if(val===null||val===void 0||isNaN(val)){return"-"}return(val/divisor).toFixed(2)+" "+unit},unit:unit}}function formatDateToYMD(date){if(!date){return""}const dateObj=new Date(date);if(isNaN(dateObj.getTime())){return""}const year=dateObj.getFullYear();const month=String(dateObj.getMonth()+1).padStart(2,"0");const day=String(dateObj.getDate()).padStart(2,"0");return`${year}-${month}-${day}`}function determineInterval(startDate,endDate){const start=new Date(startDate);const end=new Date(endDate);if(isNaN(start.getTime())||isNaN(end.getTime())){return"day"}const diffMs=end.getTime()-start.getTime();const diffDays=diffMs/(1e3*60*60*24);if(diffDays<=1){return"hour"}else if(diffDays<=7){return"day"}else if(diffDays<=31){return"week"}else if(diffDays<=365){return"month"}else{return"year"}}function getSaoPauloISOString(date,edge="start"){const dateObj=new Date(date);if(isNaN(dateObj.getTime())){return""}const saoPauloOffset=-3;const saoPauloDate=new Date(dateObj.getTime()+saoPauloOffset*60*60*1e3);if(edge==="start"){saoPauloDate.setHours(0,0,0,0)}else{saoPauloDate.setHours(23,59,59,999)}const utcDate=new Date(saoPauloDate.getTime()-saoPauloOffset*60*60*1e3);return utcDate.toISOString()}function getDateRangeArray(startDate,endDate,interval="day"){const start=new Date(startDate);const end=new Date(endDate);const dates=[];if(isNaN(start.getTime())||isNaN(end.getTime())||start>end){return dates}const current=new Date(start);while(current<=end){dates.push(new Date(current));switch(interval){case"day":current.setDate(current.getDate()+1);break;case"week":current.setDate(current.getDate()+7);break;case"month":current.setMonth(current.getMonth()+1);break;case"year":current.setFullYear(current.getFullYear()+1);break;default:current.setDate(current.getDate()+1)}}return dates}function formatDateForInput(date){if(!date||isNaN(date.getTime())){return""}const year=date.getFullYear();const month=String(date.getMonth()+1).padStart(2,"0");const day=String(date.getDate()).padStart(2,"0");return`${year}-${month}-${day}`}function parseInputDateToDate(inputDateStr){if(!inputDateStr){return null}const parts=inputDateStr.split("-");if(parts.length!==3){return null}const year=parseInt(parts[0],10);const month=parseInt(parts[1],10)-1;const day=parseInt(parts[2],10);if(isNaN(year)||isNaN(month)||isNaN(day)){return null}return new Date(year,month,day,0,0,0,0)}function timeWindowFromInputYMD(startYmd,endYmd,tzOffset="-03:00"){if(!startYmd||!endYmd){return{startTs:0,endTs:0}}const startParts=startYmd.split("-");const endParts=endYmd.split("-");if(startParts.length!==3||endParts.length!==3){return{startTs:0,endTs:0}}const startDate=new Date(parseInt(startParts[0],10),parseInt(startParts[1],10)-1,parseInt(startParts[2],10),0,0,0,0);const endDate=new Date(parseInt(endParts[0],10),parseInt(endParts[1],10)-1,parseInt(endParts[2],10),23,59,59,999);return{startTs:startDate.getTime(),endTs:endDate.getTime()}}function formatDateWithTimezoneOffset(date,endOfDay=false,tzOffset="-03:00"){if(!date||isNaN(date.getTime())){return""}const year=date.getFullYear();const month=String(date.getMonth()+1).padStart(2,"0");const day=String(date.getDate()).padStart(2,"0");let hours,minutes,seconds,milliseconds;if(endOfDay){hours="23";minutes="59";seconds="59";milliseconds="999"}else{hours=String(date.getHours()).padStart(2,"0");minutes=String(date.getMinutes()).padStart(2,"0");seconds=String(date.getSeconds()).padStart(2,"0");milliseconds=String(date.getMilliseconds()).padStart(3,"0")}return`${year}-${month}-${day}T${hours}:${minutes}:${seconds}.${milliseconds}${tzOffset}`}function getSaoPauloISOStringFixed(dateStr,endOfDay=false){if(!dateStr)return"";if(endOfDay){return`${dateStr}T23:59:59.999-03:00`}else{return`${dateStr}T00:00:00.000-03:00`}}function averageByDay(data){if(!data||data.length===0){return[]}const grouped={};data.forEach(item=>{if(!item||item.value===null||item.value===void 0||isNaN(item.value)){return}const date=new Date(item.ts);if(isNaN(date.getTime())){return}const day=date.toISOString().split("T")[0];if(!grouped[day]){grouped[day]=[]}grouped[day].push(Number(item.value))});const result=Object.entries(grouped).map(([day,values])=>{const sum=values.reduce((acc,val)=>acc+val,0);const average=sum/values.length;return{day:day,average:average}});result.sort((a,b)=>a.day.localeCompare(b.day));return result}function groupByDay(data){if(!data||data.length===0){return{}}const grouped={};data.forEach(item=>{if(!item||item.value===null||item.value===void 0||isNaN(item.value)){return}const date=new Date(item.ts);if(isNaN(date.getTime())){return}const day=date.toISOString().split("T")[0];if(!grouped[day]){grouped[day]=[]}grouped[day].push(Number(item.value))});return grouped}function exportToCSV(data,headers,filename){if(!data||data.length===0){return""}const csvHeaders=headers.join(",");const csvRows=data.map(row=>headers.map(header=>{const value=row[header];if(value===null||value===void 0){return""}const stringValue=String(value);if(stringValue.includes(",")||stringValue.includes('"')||stringValue.includes("\n")){return`"${stringValue.replace(/"/g,'""')}"`}return stringValue}).join(","));const csvContent=[csvHeaders,...csvRows].join("\n");return csvContent}function exportToCSVAll(storesData,headers,filename){if(!storesData||Object.keys(storesData).length===0){return""}const csvRows=[];const csvHeaders=["Store",...headers].join(",");csvRows.push(csvHeaders);Object.entries(storesData).forEach(([storeName,storeData])=>{if(!storeData||storeData.length===0){return}storeData.forEach(row=>{let formattedStoreName=storeName;if(storeName.includes(",")||storeName.includes('"')||storeName.includes("\n")){formattedStoreName=`"${storeName.replace(/"/g,'""')}"`}const csvRow=[formattedStoreName,...headers.map(header=>{const value=row[header];if(value===null||value===void 0){return""}const stringValue=String(value);if(stringValue.includes(",")||stringValue.includes('"')||stringValue.includes("\n")){return`"${stringValue.replace(/"/g,'""')}"`}return stringValue})].join(",");csvRows.push(csvRow)})});return csvRows.join("\n")}function buildWaterReportCSV(rows,meta){if(!rows||rows.length===0){return""}const csvRows=[];let totalConsumption=0;rows.forEach(row=>{const consumptionStr=String(row.totalConsumption).replace(",",".");const consumption=Number(consumptionStr)||0;totalConsumption+=consumption});const finalTotal=meta.total!==void 0?meta.total:totalConsumption;csvRows.push(["DATA EMISSÃO",meta.issueDate]);csvRows.push(["Total",finalTotal.toFixed(2)]);if(meta.name&&meta.identifier){csvRows.push(["Loja:",meta.name,meta.identifier])}csvRows.push(["Data","Dia da Semana","Consumo Médio (m³)","Consumo Mínimo (m³)","Consumo Máximo (m³)","Consumo (m³)"]);rows.forEach(row=>{csvRows.push([row.formattedDate,row.day,String(row.avgConsumption),String(row.minDemand),String(row.maxDemand),String(row.totalConsumption)])});return csvRows.map(row=>row.join(";")).join("\n")}function buildWaterStoresCSV(rows,meta){if(!rows||rows.length===0){return""}const csvRows=[];let totalConsumption=0;rows.forEach(row=>{const consumption=row.consumptionM3!==void 0?row.consumptionM3:row.consumptionKwh||0;totalConsumption+=consumption});const finalTotal=meta.total!==void 0?meta.total:totalConsumption;csvRows.push(["DATA EMISSÃO",meta.issueDate]);csvRows.push(["Total",finalTotal.toFixed(2)]);csvRows.push(["Loja","Identificador","Consumo"]);rows.forEach(row=>{const label=row.entityLabel||row.deviceName||"-";const deviceId=row.deviceId||"-";const consumption=row.consumptionM3!==void 0?row.consumptionM3:row.consumptionKwh||0;const formattedConsumption=consumption!==null&&consumption!==void 0?formatNumberReadable(consumption):"0,00";csvRows.push([label,deviceId,formattedConsumption])});return csvRows.map(row=>row.join(";")).join("\n")}function toCSV(rows,delimiter=";"){if(!rows||rows.length===0){return""}return rows.map(row=>row.map(cell=>{const value=String(cell);if(value.includes(delimiter)||value.includes('"')||value.includes("\n")){return`"${value.replace(/"/g,'""')}"`}return value}).join(delimiter)).join("\n")}function classify(entity,criteria){if(!entity||!criteria){return{category:"unknown",confidence:0}}let category="unknown";let subcategory;let confidence=0;if(entity.type){switch(entity.type.toLowerCase()){case"consumption":category="energy_consumption";confidence=.9;break;case"generation":category="energy_generation";confidence=.9;break;case"storage":category="energy_storage";confidence=.9;break;case"distribution":category="energy_distribution";confidence=.8;break;default:category="energy_other";confidence=.5}}if(entity.powerRating){const power=parseFloat(entity.powerRating);if(!isNaN(power)){if(power<1e3){subcategory="small_scale"}else if(power<1e4){subcategory="medium_scale"}else{subcategory="large_scale"}confidence=Math.min(confidence+.1,1)}}return{category:category,subcategory:subcategory,confidence:confidence}}function classifyWaterLabel(label){if(!label){console.warn('classifyWaterLabel: empty label, defaulting to "Lojas"');return"Lojas"}const normalizedLabel=label.toLowerCase().trim();if(/rel[óo]gio|caixa|superior|inferior|nível_terraço/.test(normalizedLabel)){return"Caixas D'Água"}if(/administra|bomba|chiller|adm/.test(normalizedLabel)){return"Área Comum"}return"Lojas"}function classifyWaterLabels(labels){const counts={"Caixas D'Água":0,Lojas:0,"Área Comum":0,total:0};labels.forEach(label=>{const category=classifyWaterLabel(label);counts[category]++;counts.total++});return counts}function getWaterCategories(){return["Caixas D'Água","Lojas","Área Comum"]}function isWaterCategory(label,category){return classifyWaterLabel(label)===category}function getValueByDatakey(data,datakey){if(!data||!datakey){return void 0}if(Array.isArray(data)){for(const item of data){const value=getValueByDatakey(item,datakey);if(value!==void 0){return value}}return void 0}if(typeof data==="object"&&data!==null){const keys=datakey.split(".");let current=data;for(const key of keys){if(current===null||current===void 0){return void 0}if(key.includes("[")&&key.includes("]")){const arrayKey=key.substring(0,key.indexOf("["));const indexMatch=key.match(/\[(\d+)\]/);if(indexMatch){const index=parseInt(indexMatch[1],10);current=current[arrayKey];if(Array.isArray(current)&&index>=0&&index<current.length){current=current[index]}else{return void 0}}else{return void 0}}else{current=current[key]}}return current}return void 0}function getValueByDatakeyLegacy(dataList,dataSourceNameTarget,dataKeyTarget){if(!Array.isArray(dataList)||!dataSourceNameTarget||!dataKeyTarget){return void 0}for(const item of dataList){if(item&&item.dataSourceName===dataSourceNameTarget&&item.dataKey===dataKeyTarget){return item.value}}return void 0}function findValue(data,keyOrPath,legacyDataKey){if(legacyDataKey!==void 0){return getValueByDatakeyLegacy(data,keyOrPath,legacyDataKey)}return getValueByDatakey(data,keyOrPath)}var contexts={building:name=>{const upper=name.toUpperCase();if(upper.includes("COMPRESSOR"))return"COMPRESSOR";if(upper.includes("VENT"))return"VENTILADOR";if(upper.includes("AUTOMATICO")||upper.includes("AUTOMÁTICO"))return"SELETOR_AUTO_MANUAL";if(upper.includes("TERMOSTATO"))return"TERMOSTATO";if(upper.includes("3F"))return"3F_MEDIDOR";if(upper.includes("TERMO")||upper.includes("TEMP"))return"TERMOSTATO";if(upper.includes("HIDR"))return"HIDROMETRO";if(upper.includes("ABRE"))return"SOLENOIDE";if(upper.includes("RECALQUE"))return"MOTOR";if(upper.includes("AUTOMACAO")||upper.includes("AUTOMAÇÃO"))return"GLOBAL_AUTOMACAO";if(upper.includes("AC"))return"CONTROLE REMOTO";if(upper.includes("SCD"))return"CAIXA_D_AGUA";return"default"},mall:name=>{const upper=name.toUpperCase();if(upper.includes("CHILLER"))return"CHILLER";if(upper.includes("ESCADA"))return"ESCADA_ROLANTE";if(upper.includes("LOJA"))return"LOJA_SENSOR";if(upper.includes("ILUMINACAO")||upper.includes("ILUMINAÇÃO"))return"ILUMINACAO";return"default"}};function detectDeviceType(name,context="building"){if(typeof name!=="string"){throw new Error("Device name must be a string.")}const detectFunction=contexts[context];if(!detectFunction){console.warn(`[myio-js-library] Context "${context}" not found. Using default fallback.`);return contexts.building(name)}return detectFunction(name)}function getAvailableContexts(){return Object.keys(contexts)}function addDetectionContext(contextName,detectFunction){if(typeof contextName!=="string"){throw new Error("Context name must be a string.")}if(typeof detectFunction!=="function"){throw new Error("Detection function must be a function.")}contexts[contextName]=detectFunction}function addNamespace(payload,namespace=""){if(!payload||typeof payload!=="object"||Array.isArray(payload)){throw new Error("Payload must be an object.")}const keys=Object.keys(payload);const suffix=namespace.trim()?` (${namespace.trim()})`:"";return keys.reduce((acc,key)=>{acc[`${key}${suffix}`]=payload[key];return acc},{})}var numbers_exports={};__export(numbers_exports,{fmtPerc:()=>fmtPerc2,toFixedSafe:()=>toFixedSafe});function fmtPerc2(x,digits=2){if(!Number.isFinite(x))return"—";return(x*100).toFixed(digits)+"%"}function toFixedSafe(x,digits=2){if(!Number.isFinite(x))return"—";return x.toFixed(digits)}var strings_exports={};__export(strings_exports,{normalizeRecipients:()=>normalizeRecipients});function normalizeRecipients(val){if(val===null||val===void 0||val==="")return"";if(Object.prototype.toString.call(val)==="[object Array]"){return val.filter(Boolean).join(",")}let s=String(val).trim();if(/^\s*\[/.test(s)){try{const arr=JSON.parse(s);if(Object.prototype.toString.call(arr)==="[object Array]"){return arr.filter(Boolean).join(",")}}catch{}}s=s.replace(/[;\s]+/g,",");s=s.replace(/,+/g,",").replace(/^,|,$/g,"");return s}function decodePayload(encoded,key){const bytes=base64ToBytesStrict(encoded);if(bytes.length===0)return"";if(key===""||key===void 0||key===null){return(new TextDecoder).decode(bytes)}if(typeof key==="number"&&Number.isFinite(key)){const k=key&255;for(let i=0;i<bytes.length;i++)bytes[i]^=k;return(new TextDecoder).decode(bytes)}const keyStr=String(key);const keyBytes=(new TextEncoder).encode(keyStr);if(keyBytes.length===0){return(new TextDecoder).decode(bytes)}for(let i=0;i<bytes.length;i++){bytes[i]^=keyBytes[i%keyBytes.length]}return(new TextDecoder).decode(bytes)}function decodePayloadBase64Xor(encoded,xorKey=73){const bytes=base64ToBytesStrict(encoded);for(let i=0;i<bytes.length;i++)bytes[i]^=xorKey&255;return(new TextDecoder).decode(bytes)}function base64ToBytesStrict(b64){if(b64===""||b64===void 0||b64===null)return new Uint8Array;const s=String(b64).replace(/\s+/g,"");const re=/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/;if(!re.test(s))throw new Error("Invalid base64");if(typeof Buffer!=="undefined"&&Buffer.from){return Uint8Array.from(Buffer.from(s,"base64"))}const bin=atob(s);const out=new Uint8Array(bin.length);for(let i=0;i<bin.length;i++)out[i]=bin.charCodeAt(i);return out}function renderCardComponent({entityObject:entityObject,handleActionDashboard:handleActionDashboard,handleActionReport:handleActionReport,handleActionSettings:handleActionSettings,handleSelect:handleSelect,handInfo:handInfo,handleClickCard:handleClickCard}){const{entityId:entityId,labelOrName:labelOrName,entityType:entityType,deviceType:deviceType,slaveId:slaveId,ingestionId:ingestionId,val:val,centralId:centralId,updatedIdentifiers:updatedIdentifiers={},isOn:isOn=false,perc:perc=0,group:group,connectionStatus:connectionStatus,centralName:centralName,connectionStatusTime:connectionStatusTime,timaVal:timaVal,valType:valType}=entityObject;const MyIO=typeof MyIOLibrary!=="undefined"&&MyIOLibrary||typeof window!=="undefined"&&window.MyIOLibrary||{formatEnergyByGroup:(v,g)=>`${v} kWh`,formatNumberReadable:n=>Number(n??0).toFixed(1)};let valFormatted=MyIO.formatEnergyByGroup(val);if(valType==="ENERGY"){valFormatted=MyIO.formatEnergyByGroup(val)}else if(valType==="WATER"){valFormatted=`${val} m³`}else if(valType==="TANK"){valFormatted=`${val} m.c.a`}else{valFormatted=val}const percFormatted=MyIO.formatNumberReadable(perc);if(!document.getElementById("myio-card-styles")){const style=document.createElement("style");style.id="myio-card-styles";style.textContent=` \n.device-card-centered,\n.clickable {\n width: 100%;\n border-radius: 10px;\n padding: 8px 12px;\n background: #fff;\n box-shadow: 0 4px 10px rgba(0, 0, 0, .05);\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n transition: transform .2s;\n min-height: 140px;\n box-sizing: border-box;\n overflow: hidden;\n}\n\n.device-card-centered:hover,\n.clickable:hover {\n transform: scale(1.05);\n}\n\n.device-title-row {\n width: 100%;\n display: flex;\n justify-content: center;\n align-items: center;\n margin-bottom: 4px;\n padding: 0 4px;\n min-height: 22px;\n}\n\n.device-title {\n font-weight: 700;\n font-size: .85rem;\n text-align: center;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n max-width: 90%;\n line-height: 1.1;\n}\n\n.device-image {\n max-height: 44px;\n width: auto;\n margin: 4px 0;\n display: block;\n}\n\n.device-data-row {\n display: flex;\n justify-content: center;\n align-items: center;\n margin-top: auto;\n margin-bottom: 6px;\n gap: 6px;\n width: 100%;\n}\n\n.consumption-main {\n font-size: .9rem;\n font-weight: 700;\n color: #28a745;\n display: flex;\n align-items: center;\n gap: 6px;\n justify-content: center;\n white-space: nowrap;\n}\n\n.device-title-percent {\n font-size: .75rem;\n color: rgba(0, 0, 0, .45);\n font-weight: 500;\n}\n\n.flash {\n animation: flash 1s infinite;\n color: #ff9800;\n}\n\n@keyframes flash {\n 0% {\n opacity: 1;\n }\n 50% {\n opacity: .2;\n }\n 100% {\n opacity: 1;\n }\n}\n\n.card-actions {\n width: 10%;\n height: 100%;\n box-shadow: 1px 0 2px rgba(0, 0, 0, .1);\n display: flex;\n flex-direction: column;\n padding: 0 4px;\n justify-content: space-around;\n align-items: center;\n}\n\n.card-action img {\n width: 24px;\n height: 24px;\n transition: transform .2s ease;\n cursor: pointer;\n}\n\n.card-action img:hover {\n transform: scale(1.15);\n}\n\n.device-card-centered.offline {\n border: 2px solid #ff4d4f;\n animation: border-blink 1s infinite;\n}\n\n\n.device-info {\n position: absolute;\n top: 8px; /* distância do topo */\n right: 8px; /* distância da direita */\n background: none;\n border: none;\n cursor: pointer;\n padding: 4px;\n border-radius: 50%;\n transition: background 0.2s;\n}\n\n.device-info:hover {\n background: rgba(0, 0, 0, 0.05);\n}\n\n.device-card-centered.flipped .device-card-inner {\n transform: rotateY(180deg);\n}\n\n@keyframes border-blink {\n 0%, 100% { box-shadow: 0 0 8px rgba(255, 77, 79, 0.9); }\n 50% { box-shadow: 0 0 16px rgba(255, 0, 0, 0.6); }\n}\n\n.device-card-centered.offline .flash-icon {\n color: #ff4d4f !important;\n font-size: 1.2rem;\n} \n.device-card-centered {\n perspective: 1000px; /* perspectiva para 3D */\n}\n\n.device-card-inner {\n position: relative;\n width: 100%;\n height: 100%;\n transform-style: preserve-3d;\n}\n\n.device-card-front {\n display: flex;\n flex-direction: row;\n justify-content: flex-start;\n align-items: flex-start; /* topo */\n position: absolute;\n width: 100%;\n height: 100%;\n top: 0;\n left: 0;\n backface-visibility: hidden;\n}\n\n.device-card-back {\n display: flex;\n flex-direction: column; /* muda para coluna se quiser empilhar elementos verticalmente */\n justify-content: flex-start; /* conteúdo começa do topo */\n align-items: center; /* centraliza horizontalmente */\n position: absolute;\n width: 100%;\n height: 100%;\n top: 0;\n left: 0;\n backface-visibility: hidden;\n transform: rotateY(180deg); /* mantém flip */\n padding: 10px; /* opcional: espaço interno */\n gap: 10px; /* opcional: espaço entre elementos */\n}\n\n\n\n.device-info {\n position: absolute;\n top: 8px; /* distância do topo */\n right: 8px; /* distância da direita */\n background: none;\n border: none;\n cursor: pointer;\n padding: 4px;\n border-radius: 50%;\n transition: background 0.2s;l\n}\n.device-card-back {\n transform: rotateY(180deg); /* faz o flip funcionar */\n}\n\n.device-card-front .device-info,\n.device-card-back .device-info {\n position: absolute; /* tira do fluxo do flex */\n top: 0; /* topo do card */\n right: 8px; /* canto direito */\n margin: 0; /* remove qualquer margem que empurre o botão */\n display: flex; /* mantém o conteúdo do botão centralizado */\n align-items: center; \n justify-content: center; \n padding: 4px; \n border-radius: 50%; \n cursor: pointer;\n z-index: 10; \n}\n\n\n.device-card-back {\n\n display: flex;\n flex-direction: column; /* empilha os elementos */\n justify-content: flex-start;\n align-items: flex-start; /* tudo à esquerda por padrão */\n padding: 10px;\n gap: 10px;\n height: 100%;\n margin-left: -10px; \n}\n\n.device-card-back .value-container {\n display: flex;\n flex-direction: row; /* ícone e valor lado a lado */\n align-items: center;\n gap: 5px;\n color: #c19efc; /* roxo clarinho */\n align-self: center; /* centraliza horizontalmente no card */\n}\n\n.device-card-back #lastconsumptionTime {\n\n display: flex;\n flex-direction: column;\n align-items: flex-start; /* mantém à esquerda */\n gap: 2px;\n font-size: 11px;\n font-weight: bold;\n color: black;\n}\n\n\n.device-card-centered.flipped .device-card-inner {\n transform: rotateY(180deg);\n}\n\n.flash-icon.flash {\n animation: icon-blink 1s infinite;\n}\n\n@keyframes icon-blink {\n 0%, 100% { opacity: 1; transform: scale(1); }\n 50% { opacity: 0.2; transform: scale(1.2); }\n}\n\n.device-card-centered.offline .flash-icon {\n color: #ff4d4f !important;\n}\n\n.device-card-centered.online .flash-icon {\n color: #28a745 !important; /* verde premium para online */\n}\n `;document.head.appendChild(style)}let formattedDateVal;let formattedDate;let Infcolor="#5cb85c";if(connectionStatusTime){const date=new Date(connectionStatusTime);const day=String(date.getDate()).padStart(2,"0");const month=String(date.getMonth()+1).padStart(2,"0");const year=date.getFullYear();const hours=String(date.getHours()).padStart(2,"0");const minutes=String(date.getMinutes()).padStart(2,"0");formattedDate=`Online: (${day}/${month}/${year} - ${hours}:${minutes})`;const datVal=new Date(timaVal);const dayVal=String(datVal.getDate()).padStart(2,"0");const monthVal=String(datVal.getMonth()+1).padStart(2,"0");const yearVal=date.getFullYear();const hoursVal=String(date.getHours()).padStart(2,"0");const minutesVal=String(date.getMinutes()).padStart(2,"0");const now=new Date;const diffMs=now-datVal;const diffMinutes=Math.floor(diffMs/(1e3*60));const diffHours=Math.floor(diffMs/(1e3*60*60));const diffDays=Math.floor(diffMs/(1e3*60*60*24));let diffText="";if(diffMinutes<60){diffText=`${diffMinutes} minuto${diffMinutes!==1?"s":""}`}else if(diffHours<24){diffText=`${diffHours} hora${diffHours!==1?"s":""}`}else{diffText=`${diffDays} dia${diffDays!==1?"s":""} `}formattedDateVal=`${dayVal}/${monthVal}/${yearVal} - ${hoursVal}:${minutesVal} (${diffText})`;if(diffHours>=24){Infcolor="#cc2900"}else if(diffMinutes>=30){Infcolor="#e89105"}}else{Infcolor="#d6dcdd"}function normalizeString(str){return str.normalize("NFD").replace(/[\u0300-\u036f]/g,"").toUpperCase()}const deviceImages={MOTOR:"https://dashboard.myio-bas.com/api/images/public/8Ezn8qVBJ3jXD0iDfnEAZ0MZhAP1b5Ts","3F_MEDIDOR":"https://dashboard.myio-bas.com/api/images/public/f9Ce4meybsdaAhAkUlAfy5ei3I4kcN4k",RELOGIO:"https://dashboard.myio-bas.com/api/images/public/ljHZostWg0G5AfKiyM8oZixWRIIGRASB",HIDROMETRO:"https://dashboard.myio-bas.com/api/images/public/aMQYFJbGHs9gQbQkMn6XseAlUZHanBR4",ENTRADA:"https://dashboard.myio-bas.com/api/images/public/TQHPFqiejMW6lOSVsb8Pi85WtC0QKOLU",CAIXA_DAGUA:"https://dashboard.myio-bas.com/api/images/public/3t6WVhMQJFsrKA8bSZmrngDsNPkZV7fq"};const defaultImage="https://cdn-icons-png.flaticon.com/512/1178/1178428.png";const nameType=normalizeString(deviceType);const img=deviceImages[nameType]||defaultImage;const html=`\n <div class="device-card-centered clickable ${connectionStatus==="offline"?"offline":""}"\n data-entity-id="${entityId}"\n data-entity-label="${labelOrName}"\n data-entity-type="${entityType}"\n data-entity-slaveid="${slaveId}"\n data-entity-ingestionid="${ingestionId}"\n data-entity-consumption="${val}"\n data-entity-centralid="${centralId}"\n data-entity-updated-identifiers='${JSON.stringify(updatedIdentifiers)}'>\n <div class="device-card-inner" style="width:100%; height:100%; transform-style: preserve-3d; transition: transform 0.6s;">\n <div class="device-card-front">\n\n <div class="card-actions" >\n ${typeof handleActionDashboard==="function"?`\n <div class="card-action action-dashboard" data-action="dashboard" title="Dashboard">\n <img src="https://dashboard.myio-bas.com/api/images/public/TAVXE0sTbCZylwGsMF9lIWdllBB3iFtS"/>\n </div>`:``}\n ${typeof handleActionReport==="function"?`\n <div class="card-action action-report" data-action="report" title="Relatório">\n <img src="https://dashboard.myio-bas.com/api/images/public/d9XuQwMYQCG2otvtNSlqUHGavGaSSpz4"/>\n </div>`:``}\n ${typeof handleActionSettings==="function"?`\n <div class="card-action action-settings" data-action="settings" title="Configurações">\n <img src="https://dashboard.myio-bas.com/api/images/public/5n9tze6vED2uwIs5VvJxGzNNZ9eV4yoz"/>\n </div>`:``}\n ${typeof handleSelect==="function"?`\n <input class="card-action action-checker" data-action="checker" title="Selecionar" type="checkbox">`:``}\n </div>\n\n <div style="display:flex;flex-direction:column;justify-content:center;align-items:center;height:100%;width:85%">\n <div class="device-title-row">\n <span class="device-title" title="${labelOrName}">\n ${String(labelOrName??"").length>15?String(labelOrName).slice(0,15)+"…":String(labelOrName??"")}\n </span>\n </div>\n <img class="device-image" src="${img}" />\n <div class="device-data-row">\n <div class="consumption-main">\n <span class="flash-icon ${connectionStatus==="offline"?"flash":isOn?"flash":""}">\n ${connectionStatus==="offline"?"🚨":"⚡"}\n </span>\n <span class="consumption-value" data-entity-consumption="${val}">${valFormatted}</span>\n <span class="device-title-percent">(${percFormatted}%)</span>\n </div>\n </div>\n </div>\n \n ${handInfo?`\n <button id="infoButtom-front" class="device-info info-button">\n <svg xmlns="http://www.w3.org/2000/svg" height="17px" viewBox="0 -960 960 960" width="17px" fill=${Infcolor}>\n <path d="M440-280h80v-240h-80v240Zm40-320q17 0 28.5-11.5T520-640q0-17-11.5-28.5T480-680q-17 0-28.5 11.5T440-640q0 17 11.5 28.5T480-600Zm0 520q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm0-80q134 0 227-93t93-227q0-134-93-227t-227-93q-134 0-227 93t-93 227q0 134 93 227t227 93Zm0-320Z"/>\n </svg>\n </button>`:``}\n </div>\n <div class="device-card-back" >\n <div id="status-bar"> \n <div id="status-information">\n <div style="font-size: 0.85rem; font-weight: bold; line-height: 1;"><span>Central: ${centralName}</span></div>\n <div style="display: flex; flex-direction: row; gap: 4px; font-weight: bold; align-items: center;">\n <div style="font-size: 12px; font-weight: bold; line-height: 1;"><span> ${formattedDate}</span></div>\n <div style="font-size: 10px; line-height: 1;"><span></span></div> \n </div>\n </div>\n <button id="infoButtom-back" class="device-info" style="background:none; border:none; cursor:pointer;">\n <svg xmlns="http://www.w3.org/2000/svg" height="17px" viewBox="0 -960 960 960" width="17px" fill=${Infcolor}>\n <path d="M440-280h80v-240h-80v240Zm40-320q17 0 28.5-11.5T520-640q0-17-11.5-28.5T480-680q-17 0-28.5 11.5T440-640q0 17 11.5 28.5T480-600Zm0 520q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm0-80q134 0 227-93t93-227q0-134-93-227t-227-93q-134 0-227 93t-93 227q0 134 93 227t227 93Zm0-320Z"/>\n </svg>\n </button>\n </div>\n\n <div class="value-container">\n <svg xmlns="http://www.w3.org/2000/svg" height="30px" viewBox="0 -960 960 960" width="30px" fill="#dea404">\n <path d="m456-200 174-340H510v-220L330-420h126v220Zm24 120q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm0-80q134 0 227-93t93-227q0-134-93-227t-227-93q-134 0-227 93t-93 227q0 134 93 227t227 93Zm0-320Z"/>\n </svg>\n <div><span>${MyIO.formatEnergyByGroup(val/1e3)||"-"}</span></div>\n </div>\n\n <div id="lastconsumptionTime">\n <div style="font-size: 12px; font-weight: bold; color: black; line-height: 1;">Ultima Telemetria:</div>\n <div style="font-size: 11px; font-weight: bold; color: black; line-height: 1;">${formattedDateVal}</div>\n </div>\n </div>\n </div>\n </div> \n </div>\n \n `;const $card=$(html);if(typeof handleActionDashboard==="function"){$card.find(".action-dashboard").on("click",e=>{e.stopPropagation();handleActionDashboard(entityObject)})}if(typeof handleActionReport==="function"){$card.find(".action-report").on("click",e=>{e.stopPropagation();handleActionReport(entityObject)})}if(typeof handleActionSettings==="function"){$card.find(".action-settings").on("click",e=>{e.stopPropagation();handleActionSettings(entityObject)})}if(typeof handleSelect==="function"){$card.find(".action-checker").on("click",e=>{e.stopPropagation();handleSelect(entityObject)})}if(typeof handleClickCard==="function"){$card.find(".action-checker").on("click",e=>{e.stopPropagation();handleClickCard(entityObject)})}$card.on("click",e=>{if(!$(e.target).closest(".card-action").length){if(typeof handleClickCard==="function"){handleClickCard(entityObject)}else if(typeof handleActionDashboard==="function"){handleActionDashboard(entityObject)}}});$card.find("#infoButtom-front").on("click",function(e){e.stopPropagation();$(this).closest(".device-card-centered").addClass("flipped")});$card.find("#infoButtom-back").on("click",function(e){e.stopPropagation();$(this).closest(".device-card-centered").removeClass("flipped")});return $card}exports.addDetectionContext=addDetectionContext;exports.addNamespace=addNamespace;exports.averageByDay=averageByDay;exports.buildWaterReportCSV=buildWaterReportCSV;exports.buildWaterStoresCSV=buildWaterStoresCSV;exports.calcDeltaPercent=calcDeltaPercent;exports.classify=classify;exports.classifyWaterLabel=classifyWaterLabel;exports.classifyWaterLabels=classifyWaterLabels;exports.decodePayload=decodePayload;exports.decodePayloadBase64Xor=decodePayloadBase64Xor;exports.detectDeviceType=detectDeviceType;exports.determineInterval=determineInterval;exports.exportToCSV=exportToCSV;exports.exportToCSVAll=exportToCSVAll;exports.findValue=findValue;exports.fmtPerc=fmtPerc;exports.fmtPercLegacy=fmtPerc2;exports.formatAllInSameUnit=formatAllInSameUnit;exports.formatAllInSameWaterUnit=formatAllInSameWaterUnit;exports.formatDateForInput=formatDateForInput;exports.formatDateToYMD=formatDateToYMD;exports.formatDateWithTimezoneOffset=formatDateWithTimezoneOffset;exports.formatEnergy=formatEnergy;exports.formatNumberReadable=formatNumberReadable;exports.formatTankHeadFromCm=formatTankHeadFromCm;exports.formatWaterByGroup=formatWaterByGroup;exports.formatWaterVolumeM3=formatWaterVolumeM3;exports.getAvailableContexts=getAvailableContexts;exports.getDateRangeArray=getDateRangeArray;exports.getSaoPauloISOString=getSaoPauloISOString;exports.getSaoPauloISOStringFixed=getSaoPauloISOStringFixed;exports.getValueByDatakey=getValueByDatakey;exports.getValueByDatakeyLegacy=getValueByDatakeyLegacy;exports.getWaterCategories=getWaterCategories;exports.groupByDay=groupByDay;exports.isWaterCategory=isWaterCategory;exports.normalizeRecipients=normalizeRecipients;exports.numbers=numbers_exports;exports.parseInputDateToDate=parseInputDateToDate;exports.renderCardComponent=renderCardComponent;exports.strings=strings_exports;exports.timeWindowFromInputYMD=timeWindowFromInputYMD;exports.toCSV=toCSV;exports.toFixedSafe=toFixedSafe});
|