Cornell
ip-10-92-53-53.ec2.internal — Last seen:
Loading license status…
Health
| Pod | Functions | Overrides | Score |
|---|---|---|---|
| kwGithubExt | 20 | 0 | 100% |
| kwLinkAnalyticsExt | 326 | 50 | 85% |
| kwLinkCoreExt | 154 | 4 | 97% |
| kwLinkDevToolsExt | 17 | 0 | 100% |
| kwLinkDiagnosticsExt | 55 | 0 | 100% |
| kwLinkegratorExt | 100 | 1 | 99% |
| kwLinkEnergyAgentExt | 169 | 29 | 83% |
| kwLinkEventsExt | 22 | 0 | 100% |
| kwLinkMbcxExt | 47 | 1 | 98% |
| kwLinkModelExt | 191 | 10 | 95% |
| kwLinkRuleExt | 177 | 9 | 95% |
| kwLinkUMichRuleExt | 84 | 0 | 100% |
| kwLinkVirtualExt | 95 | 10 | 89% |
| kwLinkWorkflowExt | 22 | 0 | 100% |
| evseExt | 20 | 0 | 100% |
Show / hide diffs (113)
buildingLoopDigest
--- buildingLoopDigest (pod) +++ buildingLoopDigest (local) @@ -24,9 +24,11 @@ condenserId: try nestedEquips.find(r => r.has("plantLoop") and r.has("condenser")).get("id") catch null // Override Opts Handling - if (opts.get("primaryLoopOverride").isRef) primaryId = opts.get("primaryLoopOverride") - if (opts.get("secondaryLoopOverride").isRef) secondaryId = opts.get("secondaryLoopOverride") - if (opts.get("condenserLoopOverride").isRef) condenserId = opts.get("condenserLoopOverride") + if (opts.get("primaryLoopOverride").isRef) primaryId = opts.get("primaryLoopOverride") + if (opts.get("primaryLoopOverride") == "null") primaryId = null + if (opts.get("secondaryLoopOverride").isRef) secondaryId = opts.get("secondaryLoopOverride") + if (opts.get("secondaryLoopOverride") == "null") secondaryId = null + if (opts.get("condenserLoopOverride").isRef) condenserId = opts.get("condenserLoopOverride") if(mode == "idMode") do if(secondaryId.isNonNull) return secondaryId else return primaryId
func_euiLibrary
--- func_euiLibrary (pod) +++ func_euiLibrary (local) @@ -74,7 +74,7 @@ {primaryFunction:"Strip Mall", eui_source:228.8, eui_site:103.5}, {primaryFunction:"Lifestyle Center", eui_source:228.8, eui_site:103.5}, {primaryFunction:"Retail Store", eui_source:120, eui_site:103.5}, - {primaryFunction:"Laboratory", eui_source:318.2, eui_site:115.3}, + {primaryFunction:"Laboratory", eui_source:318.2, eui_site:256}, {primaryFunction:"Drinking Water Treatment & Distribution", eui_source:5.9, eui_site:2.3}, {primaryFunction:"Repair Services (Vehicle, Shoe, Locksmith, etc)", eui_source:96.9, eui_site:47.9}, {primaryFunction:"Personal Services (Health/Beauty, Dry Cleaning, etc)", eui_source:96.9, eui_site:47.9},
getCHWMeterSummary
--- getCHWMeterSummary (pod) +++ getCHWMeterSummary (local) @@ -7,7 +7,6 @@ //normalize inputs siteRec: site.toRec siteId: site->id - dates = dates.toSpan //get opts debug: if(opts.has("debug")) opts.get("debug") @@ -57,14 +56,14 @@ if (points.vals.all(v=>v==missingPointValue)) return {dis:"Missing all required points", action:"Add a site meter and the required points"} //define col meta options on points - if (chw_intervalCons!=null and chw_intervalCons!=missingValue) chw_intervalCons= chw_intervalCons .merge({dis:"Chilled Water Consumption", chartGroup:"chw", color:"skyBlue"}) - if (chw_intervalModelCons!=null and chw_intervalModelCons!=missingValue) chw_intervalModelCons= chw_intervalModelCons .merge({dis:"Chilled Water Model", chartGroup:"chw", color:"skyBlue", strokeDasharray:"1,1"}) + if (chw_intervalCons!=null and chw_intervalCons!=missingValue) chw_intervalCons= chw_intervalCons .merge({dis:"Chilled Water Consumption", chartGroup:"chw", color:"purple"}) + if (chw_intervalModelCons!=null and chw_intervalModelCons!=missingValue) chw_intervalModelCons= chw_intervalModelCons .merge({dis:"Chilled Water Model", chartGroup:"chw", color:"purple", strokeDasharray:"1,1"}) if (chw_intervalSavingsCons!=null and chw_intervalSavingsCons!=missingValue) chw_intervalSavingsCons= chw_intervalSavingsCons .merge({}) if (chw_intervalSavingsCost!=null and chw_intervalSavingsCost!=missingValue) chw_intervalSavingsCost= chw_intervalSavingsCost .merge({}) if (chw_intervalCost!=null and chw_intervalCost!=missingValue) chw_intervalCost= chw_intervalCost .merge({}) - if (chw_monthlyCons!=null and chw_monthlyCons!=missingValue) chw_monthlyCons= chw_monthlyCons .merge({dis:"Chilled Water Consumption", chartGroup:"chw", color:"skyBlue"}) - if (chw_monthlyModelCons!=null and chw_monthlyModelCons!=missingValue) chw_monthlyModelCons= chw_monthlyModelCons .merge({dis:"Chilled Water Model", chartGroup:"chw", color:"skyBlue", strokeDasharray:"1,1"}) + if (chw_monthlyCons!=null and chw_monthlyCons!=missingValue) chw_monthlyCons= chw_monthlyCons .merge({dis:"Chilled Water Consumption", chartGroup:"chw", color:"purple"}) + if (chw_monthlyModelCons!=null and chw_monthlyModelCons!=missingValue) chw_monthlyModelCons= chw_monthlyModelCons .merge({dis:"Chilled Water Model", chartGroup:"chw", color:"purple", strokeDasharray:"1,1"}) if (chw_monthlySavingsCons!=null and chw_monthlySavingsCons!=missingValue) chw_monthlySavingsCons= chw_monthlySavingsCons .merge({}) if (chw_monthlySavingsCost!=null and chw_monthlySavingsCost!=missingValue) chw_monthlySavingsCost= chw_monthlySavingsCost .merge({}) if (chw_monthlyCost!=null and chw_monthlyCost!=missingValue) chw_monthlyCost= chw_monthlyCost .merge({}) @@ -73,11 +72,11 @@ //get his - his_chw_intervalCons: try chw_intervalCons.hisRead(dates, {-limit}).renameCol("v0","chw_intervalCons") catch null - his_chw_intervalModelCons: try chw_intervalModelCons.hisRead(dates, {-limit}).renameCol("v0","chw_intervalModelCons") catch null - his_chw_intervalSavingsCons: try chw_intervalSavingsCons.hisRead(dates, {-limit}).hisRollup(avg, 1hr).renameCol("v0","chw_intervalSavingsCons") catch null - his_chw_intervalSavingsCost: try chw_intervalSavingsCost.hisRead(dates, {-limit}).renameCol("v0","chw_intervalSavingsCost") catch null - his_chw_intervalCost: try chw_intervalCost.hisRead(dates, {-limit}).renameCol("v0","chw_intervalCost") catch null + his_chw_intervalCons: try chw_intervalCons.hisRead(dates, {-limit}).hisRollup(avg, 1hr).hisInterpolate().renameCol("v0","chw_intervalCons") catch null + his_chw_intervalModelCons: try chw_intervalModelCons.hisRead(dates, {-limit}).hisRollup(avg, 1hr).hisInterpolate().renameCol("v0","chw_intervalModelCons") catch null + his_chw_intervalSavingsCons: try chw_intervalSavingsCons.hisRead(dates, {-limit}).hisRollup(avg, 1hr).hisInterpolate().renameCol("v0","chw_intervalSavingsCons") catch null + his_chw_intervalSavingsCost: try chw_intervalSavingsCost.hisRead(dates, {-limit}).hisRollup(avg, 1hr).hisInterpolate().renameCol("v0","chw_intervalSavingsCost") catch null + his_chw_intervalCost: try chw_intervalCost.hisRead(dates, {-limit}).hisRollup(avg, 1hr).hisInterpolate().renameCol("v0","chw_intervalCost") catch null his_chw_monthlyCons: try chw_monthlyCons.hisRead(dates, {-limit}).renameCol("v0","chw_monthlyCons") catch null his_chw_monthlyModelCons: try chw_monthlyModelCons.hisRead(dates, {-limit}).renameCol("v0","chw_monthlyModelCons") catch null
getElecMeterSummary
--- getElecMeterSummary (pod) +++ getElecMeterSummary (local) @@ -7,7 +7,6 @@ //normalize inputs siteRec: site.getRecord siteId: site->id - dates = dates.toSpan //get opts debug: if (opts.has("debug")) opts.get("debug") @@ -78,11 +77,11 @@ //get his and rename columns - his_elec_intervalPwr: try elec_intervalPwr.hisRead(dates, {-limit}).hisRollup(avg,1hr).renameCol("v0","elec_intervalPwr").hisClean catch null - his_elec_modelPwr: try elec_modelPwr.hisRead(dates, {-limit}).hisRollup(avg,1hr).renameCol("v0","elec_modelPwr").hisClean catch null - his_elec_savingsPwr: try elec_savingsPwr.hisRead(dates, {-limit}).hisRollup(avg,1hr).renameCol("v0","elec_savingsPwr").hisClean catch null - his_elec_intervalSavingsCost: try elec_intervalSavingsCost.hisRead(dates, {-limit}).hisRollup(avg,1hr).renameCol("v0","elec_intervalSavingsCost").hisClean catch null - his_elec_intervalCost: try elec_intervalCost.hisRead(dates, {-limit}).hisRollup(avg,1hr).renameCol("v0","elec_intervalCost").hisClean catch null + his_elec_intervalPwr: try elec_intervalPwr.hisRead(dates, {-limit}).hisRollup(avg,1hr).hisInterpolate().renameCol("v0","elec_intervalPwr").hisClean catch null + his_elec_modelPwr: try elec_modelPwr.hisRead(dates, {-limit}).hisRollup(avg,1hr).hisInterpolate().renameCol("v0","elec_modelPwr").hisClean catch null + his_elec_savingsPwr: try elec_savingsPwr.hisRead(dates, {-limit}).hisRollup(avg,1hr).hisInterpolate().renameCol("v0","elec_savingsPwr").hisClean catch null + his_elec_intervalSavingsCost: try elec_intervalSavingsCost.hisRead(dates, {-limit}).hisRollup(avg,1hr).hisInterpolate().renameCol("v0","elec_intervalSavingsCost").hisClean catch null + his_elec_intervalCost: try elec_intervalCost.hisRead(dates, {-limit}).hisRollup(avg,1hr).hisInterpolate().renameCol("v0","elec_intervalCost").hisClean catch null his_elec_monthlyEnergy: try elec_monthlyEnergy.hisRead(dates, {-limit}).hisRollup(sum,1mo).renameCol("v0","elec_monthlyEnergy").hisClean catch null his_elec_modelEnergy: try elec_modelEnergy.hisRead(dates, {-limit}).hisRollup(sum,1mo).renameCol("v0","elec_modelEnergy").hisClean catch null @@ -125,9 +124,9 @@ if (debug=="his") return hisSummary //rollup data into summary values we can use quickly in widgets - rollup_elec_intervalPwr: try his_elec_intervalPwr.hisRollup(avg,1hr).hisMap(v=>v.as("kWh")).hisRollup(sum,"*").first.get("elec_intervalPwr") catch missingValue - rollup_elec_modelPwr: try his_elec_modelPwr.hisRollup(avg,1hr).hisMap(v=>v.as("kWh")).hisRollup(sum,"*").first.get("elec_modelPwr") catch missingValue - rollup_elec_savingsPwr: try his_elec_savingsPwr.hisRollup(avg,1hr).hisMap(v=>v.as("kWh")).hisRollup(sum,"*").first.get("elec_savingsPwr") catch missingValue + rollup_elec_intervalPwr: try his_elec_intervalPwr.hisRollup(avg,1hr).hisMap(v=>v.to("kW")).hisMap(v=>v.as("kWh")).hisRollup(sum,"*").first.get("elec_intervalPwr") catch missingValue + rollup_elec_modelPwr: try his_elec_modelPwr.hisRollup(avg,1hr).hisMap(v=>v.to("kW")).hisMap(v=>v.as("kWh")).hisRollup(sum,"*").first.get("elec_modelPwr") catch missingValue + rollup_elec_savingsPwr: try his_elec_savingsPwr.hisRollup(avg,1hr).hisMap(v=>v.to("kW")).hisMap(v=>v.as("kWh")).hisRollup(sum,"*").first.get("elec_savingsPwr") catch missingValue rollup_elec_intervalSavingsCost: try his_elec_intervalSavingsCost.hisRollup(sum,"*").first.get("elec_intervalSavingsCost") catch missingValue rollup_elec_intervalCost: try his_elec_intervalCost.hisRollup(sum,"*").first.get("elec_intervalCost") catch missingValue @@ -199,22 +198,22 @@ //get effective rollups - only for the points that are relevant rollup_elec_usage: if (rollup_elec_intervalPwr!=null and rollup_elec_intervalPwr!=missingValue) rollup_elec_intervalPwr else if (rollup_elec_monthlyEnergy!=null and rollup_elec_monthlyEnergy!=missingValue) rollup_elec_monthlyEnergy - else missingValue + else null rollup_elec_model: if (rollup_elec_modelPwr!=null and rollup_elec_modelPwr!=missingValue) rollup_elec_modelPwr else if (rollup_elec_modelEnergy!=null and rollup_elec_modelEnergy!=missingValue) rollup_elec_modelEnergy - else missingValue + else null rollup_elec_savings: if (rollup_elec_savingsPwr!=null and rollup_elec_savingsPwr!=missingValue) rollup_elec_savingsPwr else if (rollup_elec_savingsEnergy!=null and rollup_elec_savingsEnergy!=missingValue) rollup_elec_savingsEnergy - else missingValue + else null rollup_elec_cost: if (rollup_elec_intervalCost!=null and rollup_elec_intervalCost!=missingValue) rollup_elec_intervalCost else if (rollup_elec_monthlyCost!=null and rollup_elec_monthlyCost!=missingValue) rollup_elec_monthlyCost - else missingValue + else null rollup_elec_savingsCost: if (rollup_elec_intervalSavingsCost!=null and rollup_elec_intervalSavingsCost!=missingValue) rollup_elec_intervalSavingsCost else if (rollup_elec_monthlySavingsCost!=null and rollup_elec_monthlySavingsCost!=missingValue) rollup_elec_monthlySavingsCost - else missingValue + else null rollup_elec_rate: if (siteRec.has("elecRate")) siteRec.get("elecRate") else if (rollup_elec_monthlyRateCost!=null and rollup_elec_monthlyRateCost!=missingValue) rollup_elec_monthlyRateCost - else missingValue + else null effectiveRollup: {elec_usage: rollup_elec_usage, elec_model: rollup_elec_model,
getHWMeterSummary
--- getHWMeterSummary (pod) +++ getHWMeterSummary (local) @@ -7,7 +7,6 @@ //normalize inputs siteRec: site.toRec siteId: site->id - dates = dates.toSpan //get opts debug: if(opts.has("debug")) opts.get("debug") @@ -57,14 +56,14 @@ if (points.vals.all(v=>v==missingPointValue)) return {dis:"Missing all required points", action:"Add a site meter and the required points"} //define col meta options on points - if (hw_intervalCons!=null and hw_intervalCons!=missingValue) hw_intervalCons= hw_intervalCons .merge({dis:"Hot Water Consumption", chartGroup:"hw", color:"tomato"}) - if (hw_intervalModelCons!=null and hw_intervalModelCons!=missingValue) hw_intervalModelCons= hw_intervalModelCons .merge({dis:"Hot Water Model", chartGroup:"hw", color:"tomato", strokeDasharray:"1,1"}) + if (hw_intervalCons!=null and hw_intervalCons!=missingValue) hw_intervalCons= hw_intervalCons .merge({dis:"Hot Water Consumption", chartGroup:"hw", color:"purple"}) + if (hw_intervalModelCons!=null and hw_intervalModelCons!=missingValue) hw_intervalModelCons= hw_intervalModelCons .merge({dis:"Hot Water Model", chartGroup:"hw", color:"purple", strokeDasharray:"1,1"}) if (hw_intervalSavingsCons!=null and hw_intervalSavingsCons!=missingValue) hw_intervalSavingsCons= hw_intervalSavingsCons .merge({}) if (hw_intervalSavingsCost!=null and hw_intervalSavingsCost!=missingValue) hw_intervalSavingsCost= hw_intervalSavingsCost .merge({}) if (hw_intervalCost!=null and hw_intervalCost!=missingValue) hw_intervalCost= hw_intervalCost .merge({}) - if (hw_monthlyCons!=null and hw_monthlyCons!=missingValue) hw_monthlyCons= hw_monthlyCons .merge({dis:"Hot Water Consumption", chartGroup:"hw", color:"tomato"}) - if (hw_monthlyModelCons!=null and hw_monthlyModelCons!=missingValue) hw_monthlyModelCons= hw_monthlyModelCons .merge({dis:"Hot Water Model", chartGroup:"hw", color:"tomato", strokeDasharray:"1,1"}) + if (hw_monthlyCons!=null and hw_monthlyCons!=missingValue) hw_monthlyCons= hw_monthlyCons .merge({dis:"Hot Water Consumption", chartGroup:"hw", color:"purple"}) + if (hw_monthlyModelCons!=null and hw_monthlyModelCons!=missingValue) hw_monthlyModelCons= hw_monthlyModelCons .merge({dis:"Hot Water Model", chartGroup:"hw", color:"purple", strokeDasharray:"1,1"}) if (hw_monthlySavingsCons!=null and hw_monthlySavingsCons!=missingValue) hw_monthlySavingsCons= hw_monthlySavingsCons .merge({}) if (hw_monthlySavingsCost!=null and hw_monthlySavingsCost!=missingValue) hw_monthlySavingsCost= hw_monthlySavingsCost .merge({}) if (hw_monthlyCost!=null and hw_monthlyCost!=missingValue) hw_monthlyCost= hw_monthlyCost .merge({})
getSteamMeterSummary
--- getSteamMeterSummary (pod) +++ getSteamMeterSummary (local) @@ -7,7 +7,6 @@ //normalize inputs siteRec: site.toRec siteId: site->id - dates = dates.toSpan //get opts debug: if(opts.has("debug")) opts.get("debug") @@ -57,14 +56,14 @@ if (points.vals.all(v=>v==missingPointValue)) return {dis:"Missing all required points", action:"Add a site meter and the required points"} //define col meta options on points - if (steam_intervalCons!=null and steam_intervalCons!=missingValue) steam_intervalCons= steam_intervalCons .merge({dis:"Steam Consumption", chartGroup:"steam", color:"slateBlue"}) - if (steam_intervalModelCons!=null and steam_intervalModelCons!=missingValue) steam_intervalModelCons= steam_intervalModelCons .merge({dis:"Steam Model", chartGroup:"steam", color:"slateBlue", strokeDasharray:"1,1"}) + if (steam_intervalCons!=null and steam_intervalCons!=missingValue) steam_intervalCons= steam_intervalCons .merge({dis:"Steam Consumption", chartGroup:"steam", color:"purple"}) + if (steam_intervalModelCons!=null and steam_intervalModelCons!=missingValue) steam_intervalModelCons= steam_intervalModelCons .merge({dis:"Steam Model", chartGroup:"steam", color:"purple", strokeDasharray:"1,1"}) if (steam_intervalSavingsCons!=null and steam_intervalSavingsCons!=missingValue) steam_intervalSavingsCons= steam_intervalSavingsCons .merge({}) if (steam_intervalSavingsCost!=null and steam_intervalSavingsCost!=missingValue) steam_intervalSavingsCost= steam_intervalSavingsCost .merge({}) if (steam_intervalCost!=null and steam_intervalCost!=missingValue) steam_intervalCost= steam_intervalCost .merge({}) - if (steam_monthlyCons!=null and steam_monthlyCons!=missingValue) steam_monthlyCons= steam_monthlyCons .merge({dis:"Steam Consumption", chartGroup:"steam", color:"slateBlue"}) - if (steam_monthlyModelCons!=null and steam_monthlyModelCons!=missingValue) steam_monthlyModelCons= steam_monthlyModelCons .merge({dis:"Steam Model", chartGroup:"steam", color:"slateBlue", strokeDasharray:"1,1"}) + if (steam_monthlyCons!=null and steam_monthlyCons!=missingValue) steam_monthlyCons= steam_monthlyCons .merge({dis:"Steam Consumption", chartGroup:"steam", color:"purple"}) + if (steam_monthlyModelCons!=null and steam_monthlyModelCons!=missingValue) steam_monthlyModelCons= steam_monthlyModelCons .merge({dis:"Steam Model", chartGroup:"steam", color:"purple", strokeDasharray:"1,1"}) if (steam_monthlySavingsCons!=null and steam_monthlySavingsCons!=missingValue) steam_monthlySavingsCons= steam_monthlySavingsCons .merge({}) if (steam_monthlySavingsCost!=null and steam_monthlySavingsCost!=missingValue) steam_monthlySavingsCost= steam_monthlySavingsCost .merge({}) if (steam_monthlyCost!=null and steam_monthlyCost!=missingValue) steam_monthlyCost= steam_monthlyCost .merge({}) @@ -73,11 +72,11 @@ //get his - his_steam_intervalCons: try steam_intervalCons.hisRead(dates, {-limit}).renameCol("v0","steam_intervalCons") catch null - his_steam_intervalModelCons: try steam_intervalModelCons.hisRead(dates, {-limit}).renameCol("v0","steam_intervalModelCons") catch null - his_steam_intervalSavingsCons: try steam_intervalSavingsCons.hisRead(dates, {-limit}).hisRollup(avg, 1hr).renameCol("v0","steam_intervalSavingsCons") catch null - his_steam_intervalSavingsCost: try steam_intervalSavingsCost.hisRead(dates, {-limit}).renameCol("v0","steam_intervalSavingsCost") catch null - his_steam_intervalCost: try steam_intervalCost.hisRead(dates, {-limit}).renameCol("v0","steam_intervalCost") catch null + his_steam_intervalCons: try steam_intervalCons.hisRead(dates, {-limit}).hisRollup(avg,1hr).hisInterpolate().renameCol("v0","steam_intervalCons") catch null + his_steam_intervalModelCons: try steam_intervalModelCons.hisRead(dates, {-limit}).hisRollup(avg,1hr).hisInterpolate().renameCol("v0","steam_intervalModelCons") catch null + his_steam_intervalSavingsCons: try steam_intervalSavingsCons.hisRead(dates, {-limit}).hisRollup(avg, 1hr).hisInterpolate().renameCol("v0","steam_intervalSavingsCons") catch null + his_steam_intervalSavingsCost: try steam_intervalSavingsCost.hisRead(dates, {-limit}).hisRollup(avg,1hr).hisInterpolate().renameCol("v0","steam_intervalSavingsCost") catch null + his_steam_intervalCost: try steam_intervalCost.hisRead(dates, {-limit}).hisRollup(avg,1hr).hisInterpolate().renameCol("v0","steam_intervalCost") catch null his_steam_monthlyCons: try steam_monthlyCons.hisRead(dates, {-limit}).renameCol("v0","steam_monthlyCons") catch null his_steam_monthlyModelCons: try steam_monthlyModelCons.hisRead(dates, {-limit}).renameCol("v0","steam_monthlyModelCons") catch null @@ -120,9 +119,9 @@ if (debug=="his") return hisSummary //rollup data into summary values we can use quickly in widgets - rollup_steam_intervalCons: try his_steam_intervalCons.hisRollup(avg,1hr).hisRollup(sum,"*").first.get("steam_intervalCons") catch missingValue - rollup_steam_intervalModelCons: try his_steam_intervalModelCons.hisRollup(avg,1hr).hisRollup(sum,"*").first.get("steam_intervalModelCons") catch missingValue - rollup_steam_intervalSavingsCons: try his_steam_intervalSavingsCons.hisRollup(avg,1hr).hisRollup(sum,"*").first.get("steam_intervalSavingsCons") catch missingValue + rollup_steam_intervalCons: try his_steam_intervalCons.hisRollup(avg,1hr)/*.hisRollup(sum,"*")*/.first.get("steam_intervalCons") catch missingValue + rollup_steam_intervalModelCons: try his_steam_intervalModelCons.hisRollup(avg,1hr)/*.hisRollup(sum,"*")*/.first.get("steam_intervalModelCons") catch missingValue + rollup_steam_intervalSavingsCons: try his_steam_intervalSavingsCons.hisRollup(avg,1hr)/*.hisRollup(sum,"*")*/.first.get("steam_intervalSavingsCons") catch missingValue rollup_steam_intervalSavingsCost: try his_steam_intervalSavingsCost.hisRollup(sum,"*").first.get("steam_intervalSavingsCost") catch missingValue rollup_steam_intervalCost: try his_steam_intervalCost.hisRollup(sum,"*").first.get("steam_intervalCost") catch missingValue
getUtilityMeterSummary
--- getUtilityMeterSummary (pod) +++ getUtilityMeterSummary (local) @@ -1,7 +1,6 @@ (site, dates, opts:{}) => do //options - dates = dates.toSpan //get elec data elec: getElecMeterSummary(site, dates, opts) @@ -9,14 +8,6 @@ elecMeta: elec.meta //elec = elec.hisMap(v=>v.to("kW")) combined: elec.addMeta({elecMeta:elecMeta}) - - //get Gas data - gas: getGasMeterSummary(site, dates, opts) - if (not gas.isDict) do - gasMeta: gas.meta - //hw = hw.hisMap(v=>v.to("kBTU/h")) - combined = hisJoin([combined, gas]).addMeta({gasMeta:gasMeta}) - end //get Hot Water data hw: getHWMeterSummary(site, dates, opts)
logic_ahu_ahuCoolingLoad
--- logic_ahu_ahuCoolingLoad (pod) +++ logic_ahu_ahuCoolingLoad (local) @@ -6,14 +6,12 @@ //normalize inputs ahuRec: ahu.toRec ahuId: ahuRec->id - dates = dates.toSpan //opts rollupOverride: try if (opts.get("rollupOverride").isNull) null else if (opts.get("rollupOverride").isStr) opts.get("rollupOverride").parseNumber else if (opts.get("rollupOverride").isNumber) opts.get("rollupOverride") else null catch null if (rollupOverride.isNull and (dates.end - dates.start).to(1hr)<=25hr) rollupOverride=1hr constant: if (opts.has("constant")) opts.get("constant") else 1 debug: opts.has("debug") and opts.get("debug")!="Disable" - occDisp: opts.optNorm("occDisp", false) //get points requiredPoints: ["mat_sensor","dat_sensor"] @@ -31,18 +29,13 @@ if (vavFlowPoints.size==0 and not points.get("daFlow_sensor").isRef) return "No vav flow points" //get his - if(occDisp) hisDict: points.retrieveHis(dates, {}) - else hisDict: points.retrieveHis(dates, {rollupOverride:rollupOverride}) + hisDict: points.retrieveHis(dates, {rollupOverride:rollupOverride}) if (debug and opts.get("debug")=="His") return hisDict if (hisDict.has("err")) throw {dis:hisDict.get("err").size+" errors", errList:hisDict.get("err")} - his: try do - if(occDisp) hisDict.vals.findAll(v=>v.isGrid).hisJoin.hisFindInPeriods(logic_ahu_occPeriods(ahuId, dates, {}, {})).hisRollupAuto(rollupOverride) - else hisDict.vals.findAll(v=>v.isGrid).hisJoin - end + his: try hisDict.vals.findAll(v=>v.isGrid).hisJoin catch return "no his" - if(occDisp) vavFlowPointsHis: vavFlowPoints.hisRead(dates,{-limit}).hisFindInPeriods(logic_ahu_occPeriods(ahuId, dates, {}, {})).hisRollupAuto(rollupOverride, his=>avg) - else vavFlowPointsHis: vavFlowPoints.hisRead(dates,{-limit}).hisRollupAuto(rollupOverride, his=>avg) + vavFlowPointsHis: vavFlowPoints.hisRead(dates,{-limit}).hisRollupAuto(rollupOverride, his=>avg) if (vavFlowPointsHis.hisClip.size==0) "No vav flow his" else vavFlowPointsHis=vavFlowPointsHis.hisFoldCols(sum).renameCol("v0","flow")
logic_chw_supTempSpReset
--- logic_chw_supTempSpReset (pod) +++ logic_chw_supTempSpReset (local) @@ -44,6 +44,10 @@ //points points: buildingLoopDigest(equipId, opts) + plantId: readById(points.get("buildingLoop").first.get("chw_supply_temp"))->equipRef->equipRef.nestedEquips.find(e=>e.get("navName").contains("Primary"))->id + priVlvCmd: try read(primary and cmd and valve and equipRef == plantId) catch null + priVlvPos: try read(primary and valve and position and equipRef == plantId) catch null + try chw_supply_temp_sp: points.get("buildingLoop").first.get("chw_supply_temp_sp") catch return blankChart("No Chilled Water Loops Present") try chw_supply_temp: points.get("buildingLoop").first.get("chw_supply_temp") catch return blankChart("No Chilled Water Loops Present") points ={chw_supply_temp_sp:chw_supply_temp_sp, chw_supply_temp:chw_supply_temp} @@ -58,6 +62,10 @@ if (hisDict.has("err")) return "missingHis" his: try hisDict.vals.findAll(v=>v.isGrid).hisJoin catch return "missingHis" + + + priVlvCmdHis: try priVlvCmd.hisRead(dates) catch null + priVlvPosHis: try priVlvPos.hisRead(dates) catch null //look back in time to find min/max searchStart: dates.start - lookBack @@ -106,7 +114,7 @@ .addColMetaClean("chw_supply_temp",{chartGroup:"supTemp"}) out = out.removeCol("delta") + out = [out, priVlvCmdHis, priVlvPosHis].hisJoin return out.addMeta(outMeta) - end
logic_chws_deltaT
--- logic_chws_deltaT (pod) +++ logic_chws_deltaT (local) @@ -54,12 +54,12 @@ bLoopId: buildingLoopDigest(targetId, opts) // Call Logic Func - pumpRunningHis: logic_chws_equipsRunning(bLoopId, dates, {equip:"pump"}) + pumpRunningHis: if (opts.get("secondaryLoopOverride") != "null") logic_chws_equipsRunning(bLoopId, dates, {equip:"pump"}) else null // Handle edge-case if (pumpRunningHis.isStr) return pumpRunningHis - pumpRunningHis = pumpRunningHis.keepCols(["ts", "anyEquipRunning"]).findAll(r => r.get("anyEquipRunning").isNonNull) + pumpRunningHis = try pumpRunningHis.keepCols(["ts", "anyEquipRunning"]).findAll(r => r.get("anyEquipRunning").isNonNull) catch null if(pumpRunningHis.isNonNull) his = his.hisFindInPeriods(pumpRunningHis)
logic_chws_energyData
--- logic_chws_energyData (pod) +++ logic_chws_energyData (local) @@ -14,94 +14,26 @@ * Thomas Kuhrke Limia 8/02/2024 - Initial Creation * Thomas Kuhrke Limia 10/8/2024 - Passed opts into chwsDigest function call (Line 30) */ -(target, dates, opts : {}) => do - - // Handle Opts - quickModeUsage : opts.get("quickModeUsage") == true - quickModeDemand : opts.get("quickModeDemand") == true +(target, date, opts : {}) => do // Normalize Inputs targetRec: target.toRec targetId: targetRec->id site: targetRec.get("siteRef") - dates = dates.toSpan() + date = date.toSpan() // Retrieve points - points: chwsDigest(targetId, opts) - - // Retrieve loops from logic. - primaryLoop : points.get("primaryLoop").toGrid - secondaryLoop: points.get("secondaryLoop").toGrid - condenserLoop: points.get("condenserLoop").toGrid - - // Edge-case where no loop has equip data. - if (primaryLoop.isStr and secondaryLoop.isStr and condenserLoop.isStr) return "No equips in any existing loop." - - loops: [primaryLoop, secondaryLoop, condenserLoop] - equipPowerPoints: [] - loops.each() (loop) => do - if (loop.isGrid) do - // Retrieve all possible equip list from loop - chillers : loop.first.get("chillers") - pumps : loop.first.get("pumps") - coolingTowers : loop.first.get("coolingTowers") - - // If chillers are present, retrieve its power points if they exist - if (chillers.isGrid) do - chillerPowerPoints: chillers.colToList("points").map(v => v.get("chlr_power")).findAll(v => v.isRef) - if (not chillerPowerPoints.isEmpty) equipPowerPoints = equipPowerPoints.add(chillerPowerPoints) - end - - // If pumps are present, rertrieve its power points if they exist. - if (pumps.isGrid) do - priPowerPoints: pumps.colToList("points").map(v => v.get("pri_pump_power")).findAll(v => v.isRef) - secPowerPoints: pumps.colToList("points").map(v => v.get("sec_pump_power")).findAll(v => v.isRef) - if (not priPowerPoints.isEmpty) equipPowerPoints = equipPowerPoints.add(priPowerPoints) - if (not secPowerPoints.isEmpty) equipPowerPoints = equipPowerPoints.add(secPowerPoints) - end - - // If cooling towers are present, retrieve its power points if they exist - if (coolingTowers.isGrid) do - ctPowerPoints: coolingTowers.colToList("points").map(v => v.get("clgtwr_power")).findAll(v => v.isRef) - if (not ctPowerPoints.isEmpty) equipPowerPoints = equipPowerPoints.add(ctPowerPoints) - end - end - end - equipPowerPoints = equipPowerPoints.flatten + points: try "chilledWater_intervalCons".pointQuery({read, siteRef: site}) catch null // Handle Edge-Case where no equip power points where found, but equips were found. - if (equipPowerPoints.isEmpty) return "No power point in any of the equips of the system." + if (points.isNull or points.isEmpty) return "No energy point on the system." // Perform a hisRead on all the points - equipPowerHis: equipPowerPoints.hisRead(dates, {-limit}).hisInterpolate.hisClip + his : points.hisRead(date, {-limit}).hisInterpolate.hisClip // Edge-case for when the points exist, but have no his data for the given dates. - if (equipPowerHis.isEmpty) return "No his data found" + if (his.isEmpty) return "No his data found" - // Calculate the system demand and usage. - systemDemand : equipPowerHis.hisFoldCols(sum).renameCol("v0", "systemDemand") - systemUsage : systemDemand.hisRollup(avg, 1h).hisMap(v => v.as(1kWh)).renameCol("systemDemand", "systemUsage") + return his - // QuickMode - if (quickModeUsage) return systemUsage - if (quickModeDemand) return systemDemand - - // Combine grids. - his : hisJoin([systemUsage, equipPowerHis, systemDemand]) - - // CHWS 2.0 Preparation - funcName: "logic_chws_energyData" - titles: logicFuncTitle(funcName, targetRec, dates) - outputMeta: {title:titles[0], - subtitle: titles[1], - funcName: funcName, - } - - // Add Meta - his = his.stream - .addColMeta("systemUsage", {chartGroup: "usage", dis: "Usage (kWh)", subtitle: "System Usage", color: "blue"}) - .addColMeta("systemDemand", {chartGroup: "demand", dis: "Demand (kW)", subtitle: "System Demand", color:"green"}) - .addMeta(outputMeta) - .collect - return his end
logic_chws_equipSummary
--- logic_chws_equipSummary (pod) +++ logic_chws_equipSummary (local) @@ -43,7 +43,7 @@ // Retrieve condenser loop (added check to use the override with priority) condLoop: if (opts.get("condenserLoopOverride").isRef) opts.get("condenserLoopOverride") - else try read(chilled and equip and water and condenserLoop and output and equipRef == chws)->id + else try read(condenser and equip and water and condenserLoop and output and equipRef == chws)->id //ADDED (condenser, removed chilled) catch null if (opts.get("equip") == "cdwp" and condLoop.isNull) return "No Condenser Loop Available" @@ -54,8 +54,8 @@ targets: if (opts.get("equip") == "chlr") try chillersDigest(primaryLoop).colToList("equip") catch (err) return "No Chillers Available" else if (opts.get("equip") == "chwp") try do - list1: pumpsDigest(primaryLoop).colToList("equip") - list2: pumpsDigest(secondaryLoop).colToList("equip") + list1: try pumpsDigest(primaryLoop).colToList("equip") catch (err) //ADDED (try catch) + list2: try pumpsDigest(secondaryLoop).colToList("equip") catch (err) //ADDED (try catch) [list1, list2].flatten end catch (err) return "No Chilled Water Loop Pumps Available" @@ -113,12 +113,20 @@ val : if (res.isNull or res.isEmpty) "missing" else if (res.isDict and res.has("max")) ((res.get("max")*10).round)/10 else ((res.get(res.names.get(0))*10).round)/10 - if (incompleteCache and valueSource == "kpi" and val != "missing") return {kpi: func(curFunc).get("dis"), value : val.toStr + " (Incomplete Cache)"} - else return {kpi: func(curFunc).get("dis"), value : val} + if (incompleteCache and valueSource == "kpi" and val != "missing") return {kpi: func(curFunc).get("dis"), value : val.toStr + " (Incomplete Cache)", help: func(curFunc).get("help")} //ADDED (help tag/val) + else return {kpi: func(curFunc).get("dis"), value : val, help: func(curFunc).get("help")} //ADDED (help tag/val) end).toGrid out = try out.addColMeta("value", {dis: target.toRec.get("navName"), enum:{missing: {icon:"x", iconColor:"#FF0000", dis:""}}}).renameCol("value", "v" + res.size) catch out res = res.add(out) end + + //ADDED start + + help: res.first.keepCols(["kpi", "help"]) + + res = res.map(g => return g.removeCol("help")).add(help) + + //ADDED end // Join all equips out : res.joinAll("kpi")
logic_chws_equipsRunning
Sources are identical.
logic_chws_systemSummary
--- logic_chws_systemSummary (pod) +++ logic_chws_systemSummary (local) @@ -33,22 +33,22 @@ target: targets.toRec.get("id") // KPI Funcs - funcs: [kpi_chws_kWTonAvg, + funcs: [//kpi_chws_kWTonAvg, kpi_chws_totalSystemEnergyUse, kpi_chws_systemPeakDemand, - kpi_chws_avgDeltaT, + kpi_chws_avgMeterDeltaT, kpi_chws_avgCHWSupplySetpoint, + kpi_chwp_percentRuntime_chws_dashboard, kpi_chws_avgSystemFlow, - kpi_chws_primaryLoop_percentRuntimeOnePump, - kpi_chws_primaryLoop_percentRuntimeMultiplePumps, + kpi_chws_primaryLoopDeltaT, + kpi_chws_avgCHWSupplyTempPrimaryLoop, + //kpi_chws_primaryLoop_percentRuntimeOnePump, + //kpi_chws_primaryLoop_percentRuntimeMultiplePumps, + kpi_chws_secondaryLoopDeltaT, + kpi_chws_avgCHWSupplyTempSecondaryLoop, kpi_chws_secondaryLoop_percentRuntimeOnePump, kpi_chws_secondaryLoop_percentRuntimeMultiplePumps, - kpi_chws_condenserLoop_percentRuntimeOnePump, - kpi_chws_condenserLoop_percentRuntimeMultiplePumps, - kpi_chws_condenserLoop_percentRuntimeOneTower, - kpi_chws_condenserLoop_percentRuntimeMultipleTowers, - kpi_chws_primaryLoop_percentRuntimeOneChiller, - kpi_chws_primaryLoop_percentRuntimeMultipleChillers + kpi_chwp_averagePumpSpeedSecLoop, ] // Create Output (NOTE: Add support for retrieving "min" values by checking the funcs displayName) @@ -61,9 +61,9 @@ val : if (res.isNull or res.isEmpty) "missing" else if (res.isDict and res.has("max")) ((res.get("max")*10).round)/10 else ((res.get(res.names.get(0))*10).round)/10 - if (incompleteCache and valueSource == "kpi" and val != "missing") return {kpi: func(curFunc).get("dis"), value : val.toStr + " (Incomplete Cache)"} - else return {kpi: func(curFunc).get("dis"), value : val} - end).toGrid + if (incompleteCache and valueSource == "kpi" and val != "missing") return {kpi: func(curFunc).get("dis"), value : val.toStr + " (Incomplete Cache)", help: func(curFunc).get("help")} //ADDED (help tag/val) + else return {kpi: func(curFunc).get("dis"), value : val, help: func(curFunc).get("help")} //ADDED (help tag/val) + end).toGrid.reorderKeepCols(["kpi", "value", "help"]) // Empty Values Opt if (hideEmptyValues) out = out.findAll(r => not r.rowToList[1..-1].all(v => v=="missing")) @@ -71,7 +71,7 @@ // Add Meta out = out.stream .addColMeta("kpi", {dis: "KPI"}) - .addColMeta("value", {dis: "System", enum:{missing: {icon:"x", iconColor:"#FF0000", dis:""}}}) + .addColMeta("value", {dis: "Values", enum:{missing: {icon:"x", iconColor:"#FF0000", dis:""}}}) .collect() return out end
logic_cwp_pumpIsRunning
--- logic_cwp_pumpIsRunning (pod) +++ logic_cwp_pumpIsRunning (local) @@ -41,7 +41,7 @@ existing : if (not (pri_pump_speed.isStr and sec_pump_speed.isStr)) [pri_pump_speed, sec_pump_speed].find(v => not v.isStr) else if (not (pri_pump_power.isStr and sec_pump_power.isStr)) [pri_pump_power, sec_pump_power].find(v => not v.isStr) else if (not (pri_pump_status.isStr and sec_pump_status.isStr)) [pri_pump_status, sec_pump_status].find(v => not v.isStr) - else "All points doesn't exist, or the existing ones have no his." + else "All points don't exist, or the existing ones have no his." // Handle edge case where there are no existing points if (existing.isStr) return existing @@ -53,7 +53,7 @@ if (his.isEmpty) return "No his data" // Transform number hisGrid into boolean - if (his.first.get("v0").isNumber) his = his.hisRollupAuto().map(r => return {ts: r.get("ts"), v0: r.get("v0") > 1}) + if (his.first.get("v0").isNumber) his = his.map(r => return {ts: r.get("ts"), v0: r.get("v0") > 1}) // Return boolean grid if opt is present if (boolPeriods) return his
logic_hhw_deltaT
--- logic_hhw_deltaT (pod) +++ logic_hhw_deltaT (local) @@ -51,8 +51,8 @@ //Filter for when any building loop pump is running opts = opts.set("id", true) bLoopId: logic_hws_buildingLoopDigest(targetId, opts) - pumpRunningHis: logic_hhws_equipsRunning(bLoopId, dates, {equip:"pump"}).keepCols(["ts", "anyEquipRunning"]) - .findAll(r => r.get("anyEquipRunning").isNonNull) + pumpRunningHis: try logic_hhws_equipsRunning(bLoopId, dates, {equip:"pump"}).keepCols(["ts", "anyEquipRunning"]) + .findAll(r => r.get("anyEquipRunning").isNonNull) catch null //ADDED try catch if(pumpRunningHis.isNonNull) his = his.hisFindInPeriods(pumpRunningHis) his = his.map() r => if(r.get("delta") < 0) r = r.set("delta", abs(r.get("delta"))) else r = r
logic_hhwp_pumpIsRunning
--- logic_hhwp_pumpIsRunning (pod) +++ logic_hhwp_pumpIsRunning (local) @@ -52,7 +52,7 @@ if (his.isEmpty) return "No his data" // Transform number hisGrid into boolean - if (his.first.get("v0").isNumber) his = his.hisRollupAuto().map(r => return {ts: r.get("ts"), v0: r.get("v0") > 1}) + if (his.first.get("v0").isNumber) his = his.map(r => return {ts: r.get("ts"), v0: r.get("v0") > 1}) // Return boolean grid if opt is present if (boolPeriods) return his.renameCol("v0", "running") @@ -61,7 +61,7 @@ his = his.conditionToPeriods("running", r => r.get("v0") == true).addColMeta("v0", his.col("v0").meta) // CHWS 2.0 Preparation - funcName: "logic_cwp_pumpIsRunning" + funcName: "logic_hhwp_pumpIsRunning" titles: logicFuncTitle(funcName, targetRec, dates) outputMeta: {title:titles[0], subtitle: titles[1],
logic_hhws_equipsRunning
Sources are identical.
logic_hhws_systemSummary
--- logic_hhws_systemSummary (pod) +++ logic_hhws_systemSummary (local) @@ -36,24 +36,24 @@ // KPI Funcs funcs: [kpi_hws_percentTimeDPAtSetpoint, - kpi_hhws_systemPeakElectricDemand, - kpi_hhws_peakSystemEnergyUse, + //kpi_hhws_systemPeakElectricDemand, + //kpi_hhws_peakSystemEnergyUse, kpi_hhws_totalSystemEnergyUse, kpi_hhw_avgDeltaT, kpi_hhw_percentTimeLowDeltaT, - kpi_hhw_avgBypassValvePosition, + //kpi_hhw_avgBypassValvePosition, kpi_hhw_avgHHWReturnTemp, kpi_hhw_avgHHWSupplySetpoint, kpi_hhw_avgHHWSupplyTemp, kpi_hhw_avgHHWSupplyFlow, kpi_hhw_percentTimeSupTempAtSetpoint, kpi_hws_percentTimeDPAtSetpoint, - kpi_hhws_primaryLoop_percentRuntimeOnePump, - kpi_hhws_primaryLoop_percentRuntimeMultiplePumps, + //kpi_hhws_primaryLoop_percentRuntimeOnePump, + //kpi_hhws_primaryLoop_percentRuntimeMultiplePumps, kpi_hhws_secondaryLoop_percentRuntimeOnePump, kpi_hhws_secondaryLoop_percentRuntimeMultiplePumps, - kpi_hhws_primaryLoop_percentRuntimeOneBlr, - kpi_hhws_primaryLoop_percentRuntimeMultipleBlrs + //kpi_hhws_primaryLoop_percentRuntimeOneBlr, + //kpi_hhws_primaryLoop_percentRuntimeMultipleBlrs ] // Create Output (NOTE: Add support for retrieving "min" values by checking the funcs displayName) @@ -61,7 +61,7 @@ cacheResSize : try ruleKpis(target, dates, read(rule and ruleFunc == curFunc.get("name")).colToList("date")) catch null incompleteCache : cacheResSize != date.numDays engineRes: if (valueSource == "auto" or valueSource == "kpi") betterRuleKpis(curFunc, target, date) else null// Read rule cache - res : if (valueSource != "kpi" and (engineRes.isNull or valueSource == "call" or incompleteCache)) call(curFunc, [{target: target, date: date, opts: opts}]).get("out") + res : if (valueSource != "kpi" and (engineRes.isNull or valueSource == "call" or incompleteCache)) try call(curFunc, [{target: target, date: date, opts: opts}]).get("out") catch null //ADDED try catch else engineRes // Call the function regularly if the cache had no info. val : if (res.isNull or res.isEmpty) "missing" else if (res.isDict and res.has("max")) ((res.get("max")*10).round)/10
pumpDigest
Sources are identical.
wdg_ahu_table_summaryAnalytics
--- wdg_ahu_table_summaryAnalytics (pod) +++ wdg_ahu_table_summaryAnalytics (local) @@ -76,10 +76,12 @@ "hwValveOpenHot", "avgChwValve", "chwValveOpenCold", + "avgDaFlow", "simultaneousHeatingCooling", "occupied247", "sparks", - "economizingProperly" + "economizingProperly", + "occHours" ] //calculate total hours @@ -87,14 +89,14 @@ //AHU LOOP units: readAll((mau or ahu or rtu) and equip and siteRef==site->id and not ahuSummaryNoShow) - table: units.map row => do + table: units.map() (row,idx) => do //normalize input id: row->id //get points requiredPoints: [] - optionalPoints: ["occ_cmd","daFan_run","daFan_speed","dat_sensor","dat_sp","dsp_sensor", "dsp_sp", "clgValve_cmd","htgValve_cmd","phtValve_cmd","daFan_speed","rtnFan_speed","rlfFan_speed","exhFan_speed","siteOcc_cmd"] + optionalPoints: ["occ_cmd","daFan_run","daFan_speed","dat_sensor","dat_sp","dsp_sensor", "dsp_sp", "clgValve_cmd","htgValve_cmd","phtValve_cmd","daFlow_sensor","daFan_speed","rtnFan_speed","rlfFan_speed","exhFan_speed","siteOcc_cmd"] points: retrievePoints(requiredPoints, optionalPoints, {equipRef:id}) if (debug and opts.get("debug")=="Points") return points if (not points.get("htgValve_cmd").isRef and points.get("phtValve_cmd").isRef) points=points.set("htgValve_cmd",points.get("phtValve_cmd")) @@ -150,6 +152,13 @@ else points.get("clgValve_cmd") catch (err) err.get("dis") if (not debug and avgChwValve.isStr) avgChwValve=noDataValue + + avgDaFlow: try + if (points.get("daFlow_sensor").isRef) + logic_ahu_pointRollup(points.get("daFlow_sensor"), dates, avg, curOpts) + else points.get("daFlow_sensor") + catch (err) err.get("dis") + if (not debug and avgChwValve.isStr) avgDaFlow=noDataValue hwValveOpenHot: try if (points.get("htgValve_cmd").isRef) @@ -241,12 +250,16 @@ //put together dict analytics: {id: id, + order: row.get("order"), avgSupplyFan: if (avgSupplyFan.isNumber) avgSupplyFan.round else avgSupplyFan, avgReturnFan: if (avgReturnFan.isNumber) avgReturnFan.round else avgReturnFan, avgReliefFan: if (avgReliefFan.isNumber) avgReliefFan.round else avgReliefFan, avgExhaustFan: if (avgExhaustFan.isNumber) avgExhaustFan.round else avgExhaustFan, avgHwValve: if (avgHwValve.isNumber) avgHwValve.round else avgHwValve, avgChwValve: if (avgChwValve.isNumber) avgChwValve.round else avgChwValve, + + avgDaFlow: if (avgDaFlow.isNumber) avgDaFlow.round else avgDaFlow, + hwValveOpenHot: if (hwValveOpenHot.isNumber) hwValveOpenHot.round else hwValveOpenHot, chwValveOpenCold: if (chwValveOpenCold.isNumber) chwValveOpenCold.round else chwValveOpenCold, simultaneousHeatingCooling:if (simultaneousHeatingCooling.isNumber) simultaneousHeatingCooling.round else simultaneousHeatingCooling, @@ -259,6 +272,7 @@ occHours: if (occHours.isNumber) occHours.round else occHours, occupied247: if (occupied247.isStr) occupied247 else "Couldn't Calculate", economizingProperly: if (economizingProperly.isNumber) economizingProperly.round else economizingProperly, + mod:now() } end @@ -268,31 +282,36 @@ out: table.toGrid .stream - .addColMetaClean("id", {dis:"id"}) - .addColMetaClean("avgSupplyFan" ,{dis:"Avg Supply Fan Spd", color:fanColor, viz:"barCell"}) - .addColMetaClean("avgReturnFan" ,{dis:"Avg Rtn Fan Spd", color:fanColor, viz:"barCell"}) - .addColMetaClean("avgReliefFan" ,{dis:"Avg Rlf Fan Spd", color:fanColor, viz:"barCell"}) - .addColMetaClean("avgExhaustFan" ,{dis:"Avg Exh Fan Spd", color:fanColor, viz:"barCell"}) - .addColMetaClean("avgHwValve" ,{dis:"Avg Heating Demand", color:hwColor, viz:"barCell"}) - .addColMetaClean("avgChwValve" ,{dis:"Avg Cooling Demand", color:chwColor, viz:"barCell"}) - .addColMetaClean("hwValveOpenHot" ,{dis:"Heating While > "+hotTemp+"F", color:hwColor, viz:"barCell"}) - .addColMetaClean("chwValveOpenCold",{dis:"Cooling While < "+coldTemp+"F", color:chwColor, viz:"barCell"}) + .addColMetaClean("id", {dis:"AHU"}) + .addColMetaClean("avgSupplyFan" ,{dis:"Avg Supply Fan Spd", color:fanColor, viz:"barCell", chartMax:100%,}) + .addColMetaClean("avgReturnFan" ,{dis:"Avg Rtn Fan Spd", color:fanColor, viz:"barCell", chartMax:100%,}) + .addColMetaClean("avgReliefFan" ,{dis:"Avg Rlf Fan Spd", color:fanColor, viz:"barCell", chartMax:100%,}) + .addColMetaClean("avgExhaustFan" ,{dis:"Avg Exh Fan Spd", color:fanColor, viz:"barCell", chartMax:100%,}) + .addColMetaClean("avgHwValve" ,{dis:"Avg Heating Demand", color:hwColor, viz:"barCell", chartMax:100%,}) + .addColMetaClean("avgChwValve" ,{dis:"Avg Cooling Demand", color:chwColor, viz:"barCell", chartMax:100%,}) + + .addColMetaClean("avgDaFlow" ,{dis:"Avg Discharge Flow"})//, color:chwColor, viz:"barCell", chartMax:100%,}) + + .addColMetaClean("hwValveOpenHot" ,{dis:"Heating While > "+hotTemp+"F", color:hwColor, viz:"barCell", chartMax:100%,}) + .addColMetaClean("chwValveOpenCold",{dis:"Cooling While < "+coldTemp+"F", color:chwColor, viz:"barCell", chartMax:100%,}) .addColMetaClean("simultaneousHeatingCooling" ,{dis:"Simult Heat/Cool", color:sparkColor, viz:"barCell", chartMax:hours}) .addColMetaClean("datResetting" ,{dis:"DAT Resetting", color:"", viz:"barCell", }) .addColMetaClean("dspResetting" ,{dis:"DSP Resetting", color:"", viz:"barCell", }) - .addColMetaClean("datMeetingSp" ,{dis:"DAT Meeting Sp", color:meetingSpColor, viz:"barCell"}) - .addColMetaClean("dspMeetingSp" ,{dis:"DSP Meeting Sp", color:meetingSpColor, viz:"barCell"}) - .addColMetaClean("supplyFanRuntime",{dis:"Supply Fan Runtime", color:fanColor, viz:"barCell"}) + .addColMetaClean("datMeetingSp" ,{dis:"DAT Meeting Sp", color:meetingSpColor, viz:"barCell", chartMax:100%}) + .addColMetaClean("dspMeetingSp" ,{dis:"DSP Meeting Sp", color:meetingSpColor, viz:"barCell", chartMax:100%}) + .addColMetaClean("supplyFanRuntime",{dis:"Supply Fan Runtime", color:fanColor, viz:"barCell", chartMax:100%}) .addColMetaClean("sparks" ,{dis:"Total Sparks", color:sparkColor, viz:"barCell", }) .addColMetaClean("occHours" ,{dis:"Occupied Hours", }) .addColMetaClean("occupied247" ,{dis:"Zones Occupied 24/7", }) - .addColMetaClean("economizingProperly",{dis:"Economizing Properly", color:meetingSpColor, viz:"barCell"}) + .addColMetaClean("economizingProperly",{dis:"Economizing Properly", color:meetingSpColor, viz:"barCell", chartMax:100%}) + .addColMetaClean("mod",{hidden}) .collect(toGrid) .reorderKeepCols(colOrder) .sort("id") + .sort("order") //apply sorting - ahuTableSortBy.split(",").each(c => if (c.startsWith("r_")) out=out.sortr(c.replace("r_","")) else out=out.sort(c)) + //ahuTableSortBy.split(",").each(c => if (c.startsWith("r_")) out=out.sortr(c.replace("r_","")) else out=out.sort(c)) //add prez
wdg_ahu_widgetSelector
--- wdg_ahu_widgetSelector (pod) +++ wdg_ahu_widgetSelector (local) @@ -13,6 +13,7 @@ if (widget=="Economizing") return wdg_ahu_chart_economizing(ahu, dates, opts) if (widget=="DAT/DSP Meeting Sp") return wdg_ahu_chart_datDspMeetingSp(ahu, dates, opts) if (widget=="DAT/DSP Resets") return wdg_ahu_chart_datDspResets(ahu, dates, opts) + if (widget=="DAF Sp Delta") return logic_ahu_flowSpDelta(ahu, dates, opts) //cards
wdg_chw_chart_supTempSpReset
--- wdg_chw_chart_supTempSpReset (pod) +++ wdg_chw_chart_supTempSpReset (local) @@ -16,7 +16,6 @@ catch (err) return blankChart("Unable to calculate.", err.dis) if(data.isStr) return blankChart(data) - //format out: data
wdg_chw_chart_temperaturesDeltaT
--- wdg_chw_chart_temperaturesDeltaT (pod) +++ wdg_chw_chart_temperaturesDeltaT (local) @@ -52,7 +52,7 @@ // CHWS 2.0 Preparation funcName: "wdg_chw_chart_temperaturesDeltaT" titles: logicFuncTitle(funcName, equipRec, dates) - outputMeta: {title:titles[0], + outputMeta: {title:"Temperature ΔT", subtitle: titles[1], funcName: funcName, chartLegend:"hide"
wdg_chws_chart_chillerStaging
--- wdg_chws_chart_chillerStaging (pod) +++ wdg_chws_chart_chillerStaging (local) @@ -37,6 +37,7 @@ // Replaced logic to support loop overrides. chillers: try chwsDigest(equipId, opts).get("primaryLoop").first.get("chillers") catch return blankChart("No Chillers in this Site") + if (chillers.isNull) return blankChart("No Chillers in this Site") // ADDED isNull CHECKING // Retrieve Temp Points tempPoints:[]
wdg_chws_table_systemSummary
--- wdg_chws_table_systemSummary (pod) +++ wdg_chws_table_systemSummary (local) @@ -32,7 +32,7 @@ // Add Additional Meta out : grid.stream .addColMeta("val", {dis: "Info"}) - .addMeta({title: "System"}) + .addMeta({title: site->dis + " KPIs"}) .collect return out.table
wdg_chws_widgetSelector
--- wdg_chws_widgetSelector (pod) +++ wdg_chws_widgetSelector (local) @@ -36,6 +36,9 @@ if (widget == "Supply Temperature Setpoint Resetting") return wdg_chw_chart_supTempSpReset(targetId, dates, opts) if (widget == "Temperature ΔT") return wdg_chw_chart_temperaturesDeltaT(targetId, dates, opts) + if (widget == "Building vs Plant ΔT") return wdg_chw_chart_bldgVsPlantDeltaT(targetId, dates, opts) + if (widget == "CHW Valve Position") return wdg_chw_valves_chart(targetId, dates, opts) + // Cards /* None for now*/
wdg_hhws_chart_pumpSpeeds
Sources are identical.
wdg_hhws_chart_temperaturesDeltaT
--- wdg_hhws_chart_temperaturesDeltaT (pod) +++ wdg_hhws_chart_temperaturesDeltaT (local) @@ -53,5 +53,5 @@ } out: his.keepCols(["ts","delta"]).createHistogram(numBars,{}).addMeta(outputMeta) - return out.chart + return out.chart.addMeta({title:"HW System - Temperatures (ΔT)"}) end
wdg_hhws_table_boilersSummary
Sources are identical.
wdg_hhws_table_hhwpSummary
Sources are identical.
wdg_hhws_table_systemSummary
--- wdg_hhws_table_systemSummary (pod) +++ wdg_hhws_table_systemSummary (local) @@ -32,7 +32,7 @@ // Add Additional Meta out : grid.stream .addColMeta("val", {dis: "Info"}) - .addMeta({title: "System"}) + .addMeta({title: site->dis + " KPIs"}) .collect return out.table
wdg_hhws_widgetSelector
Sources are identical.
wdg_portfolio_card_energy
--- wdg_portfolio_card_energy (pod) +++ wdg_portfolio_card_energy (local) @@ -1,7 +1,7 @@ //todo add emissions data (dates, opts:{}) => do - dates = dates.toSpan + //validate and authorize current user kwLinkValidate("analytics") @@ -11,55 +11,121 @@ debug: debugVal!="Disable" and debugVal!=null //debug:true + //Before caching + /* //get sites - grid: xq().xqProjs(navProjNames()) + grid: xq().xqTimeout(5min).xqProjs(navProjNames()) .xqDefine("dates",dates) .xqReadAll(site) .xqMap("site => try {site:site->id}.merge(getUtilityMeterSummary(site,dates).meta) catch (err) {site:site->id, err:err}") .xqExecute + */ - totalSites: grid.size - errSites: grid.findAll(r=>r.has("err")).size - goodSites: grid.findAll(r=>r.missing("err")).size + //Get Cached records + startDate: dates.start + endDate: dates.end + grid: readAll(cache and cache_portfolio_energySummary and cacheYear=="all" and ts >=startDate and ts<= endDate) + //.findAll(r => r.get("ts") >= startDate and r.get("ts") <= endDate) + //.reorderKeepCols(["ts"]) + .removeCols(["id", "cache", "cacheYear", "cache_portfolio_energySummary"]) + gridCols: grid.colNames.moveTo("ts", 0) + grid = grid.reorderCols(gridCols) + //.renameCol("siteR", "site") + //return grid + + //totalSites: grid.size + //errSites: grid.findAll(r=>r.has("err")).size + //goodSites: grid.findAll(r=>r.missing("err")).size if (debug=="Enable") return grid.reorderKeepCols(["site","err","elecMeta","gasMeta"]) - - + //return grid + todaysDate: today() + card: {title:"Energy Summary"} //split elec and gas - elecGrid: grid.colToList("elecMeta").findAll(v=>v!=null).toGrid.map(r=>r.get("effectiveRollup")) - gasGrid: grid.colToList("gasMeta").findAll(v=>v!=null).toGrid.map(r=>r.get("effectiveRollup")) - - if (debug=="Elec") return elecGrid - if (debug=="Gas") return gasGrid - - //split it up into new card - gas_usage_numbers: gasGrid.colToList("gas_usage").findAll(v=>v.isNumber) - gas_usage: gas_usage_numbers.fold(sum) - gas_cost: gasGrid.colToList("gas_cost").findAll(v=>v.isNumber).fold(sum) - gasMessage: errSites+" errs, "+ (goodSites - gas_usage_numbers.size)+" missing" - - elec_usage_numbers: elecGrid.colToList("elec_usage").findAll(v=>v.isNumber) - elec_usage: elec_usage_numbers.fold(sum) - elec_cost: try elecGrid.colToList("elec_cost").findAll(v=>v.isNumber).fold(sum) catch "Costs unavailable" - elecMessage: errSites+" errs, "+ (goodSites - elec_usage_numbers.size)+" missing" - - card: {title:"Energy Summary", - elecUse: elec_usage, - elecCost: elec_cost, - elecMessage:elecMessage, - gasUse: gas_usage, - gasCost: gas_cost, - gasMessage: gasMessage, - } + /* + if(grid.colNames.contains("elecMeta")) do + elecGrid: grid.colToList("elecMeta").findAll(v=>v!=null).toGrid.map(r=>r.get("effectiveRollup")) + elec_usage_numbers: elecGrid.colToList("elec_usage").findAll(v=>v.isNumber) + elec_usage: elec_usage_numbers.fold(sum) + elec_cost: try elecGrid.colToList("elec_cost").findAll(v=>v.isNumber).fold(sum) catch "Costs unavailable" + elecMessage: errSites+" errs, "+ (goodSites - elec_usage_numbers.size)+" missing" + card = card.merge({"elecUse": elec_usage, "elecCost": elec_cost/*, "elecMessage":elecMessage*/}) + end + */ + //return grid.colNames + elec_usage_col_names : grid.colNames.findAll(r => r.contains("elec_usage")).add("ts") + x: grid.keepCols(elec_usage_col_names) + elec_usage: try x.hisFoldCols(sum).colToList("v0").fold(sum) catch "Incompatible Units" + elec_cost_col_names : grid.colNames.findAll(r => r.contains("elec_cost")).add("ts") + y: grid.keepCols(elec_cost_col_names) + elec_cost: y.hisFoldCols(sum).colToList("v0").fold(sum) + card = card.merge({"elecUse": elec_usage, "elecCost": elec_cost/*, "elecMessage":elecMessage*/}) + /* + if(grid.colNames.contains("hwMeta")) do + hwGrid: grid.colToList("hwMeta").findAll(v=>v!=null).toGrid.map(r=>r.get("effectiveRollup")) + hw_usage_numbers: hwGrid.colToList("hw_usage").findAll(v=>v.isNumber).map(s => return s.to("MMBTU/h")) + hw_usage: hw_usage_numbers.fold(sum).as("MMBTU") + hw_cost: try hwGrid.colToList("hw_cost").findAll(v=>v.isNumber).fold(sum) catch "Costs unavailable" + hwMessage: errSites+" errs, "+ (goodSites - hw_usage_numbers.size)+" missing" + card = card.merge({"hwUse": hw_usage, "hwCost": hw_cost/*, "hwMessage":hwMessage*/}) + end + */ + hw_usage_col_names : grid.colNames.findAll(r => r.contains("hw_usage")).add("ts") + x= grid.keepCols(hw_usage_col_names) + hw_usage: try x.hisFoldCols(sum).colToList("v0").fold(sum) catch "Incompatible Units" + hw_cost_col_names : grid.colNames.findAll(r => r.contains("hw_cost")).add("ts") + y= grid.keepCols(hw_cost_col_names) + hw_cost: y.hisFoldCols(sum).colToList("v0").fold(sum) + card = card.merge({"hwUse": hw_usage, "hwCost": hw_cost/*, "hwMessage":hwMessage*/}) + /* + if(grid.colNames.contains("chwMeta")) do + chwGrid: grid.colToList("chwMeta").findAll(v=>v!=null).toGrid.map(r=>r.get("effectiveRollup")) + chw_usage_numbers: chwGrid.colToList("chw_usage").findAll(v=>v.isNumber) + chw_usage: chw_usage_numbers.fold(sum) + chw_cost: try chwGrid.colToList("chw_cost").findAll(v=>v.isNumber).fold(sum) catch "Costs unavailable" + chwMessage: errSites+" errs, "+ (goodSites - chw_usage_numbers.size)+" missing" + card = card.merge({"chwUse": chw_usage, "chwCost": chw_cost/*, "chwMessage":chwMessage*/}) + end + */ + chw_usage_col_names : grid.colNames.findAll(r => r.contains("chw_usage")).add("ts") + x= grid.keepCols(chw_usage_col_names) + chw_usage: try x.hisFoldCols(sum).colToList("v0").fold(sum) catch "Incompatible Units" + chw_cost_col_names : grid.colNames.findAll(r => r.contains("chw_cost")).add("ts") + y= grid.keepCols(chw_cost_col_names) + chw_cost: y.hisFoldCols(sum).colToList("v0").fold(sum) + card = card.merge({"chwUse": chw_usage, "chwCost": chw_cost/*, "hwMessage":hwMessage*/}) + /* + if(grid.colNames.contains("steamMeta")) do + steamGrid: grid.colToList("steamMeta").findAll(v=>v!=null).toGrid.map(r=>r.get("effectiveRollup")) + steam_usage_numbers: steamGrid.colToList("steam_usage").findAll(v=>v.isNumber).map(s => return s.to("klb/h")) + steam_usage: steam_usage_numbers.fold(sum).as("klb") + steam_cost: try steamGrid.colToList("steam_cost").findAll(v=>v.isNumber).fold(sum) catch "Costs unavailable" + steamMessage: errSites+" errs, "+ (goodSites - steam_usage_numbers.size)+" missing" + card = card.merge({"steamUse": steam_usage, "steamCost": steam_cost/*, "steamMessage":steamMessage*/}) + end + */ + steam_usage_col_names : grid.colNames.findAll(r => r.contains("steam_usage")).add("ts") + x= grid.keepCols(steam_usage_col_names) + steam_usage: try x.hisFoldCols(sum).colToList("v0").fold(sum) catch "Incompatible Units" + steam_cost_col_names : grid.colNames.findAll(r => r.contains("steam_cost")).add("ts") + y= grid.keepCols(steam_cost_col_names) + steam_cost: y.hisFoldCols(sum).colToList("v0").fold(sum) + card = card.merge({"steamUse": steam_usage, "steamCost": steam_cost/*, "steamMessage":steamMessage*/}) out: card.toGrid - try out=out.addColMeta("elecCost", {viz:"barCell", color:"orange", dis: "Electricity Cost", }) catch null - try out=out.addColMeta("elecUse", {color:"orange", dis: "Electricity Use", }) catch null - try out=out.addColMeta("elecMessage", {color:"lightGray", dis: "Warning", }) catch null - try out=out.addColMeta("gasCost", {viz:"barCell", color:"purple", dis: "Gas Cost", }) catch null - try out=out.addColMeta("gasUse", {color:"purple", dis: "Gas Use", }) catch null - try out=out.addColMeta("gasMessage", {color:"lightGray", dis: "Warning", }) catch null - try out=out.addMeta({vizByUnit}) catch null + try out=out.addColMetaClean("elecCost", {viz:"barCell", color:"orange", dis: "Electricity Cost", }) catch null + try out=out.addColMetaClean("elecUse", {color:"orange", dis: "Electricity Use", }) catch null + try out=out.addColMetaClean("elecMessage", {color:"lightGray", dis: "Electricity Warning", }) catch null + try out=out.addColMetaClean("hwCost", {viz:"barCell", color:"orangeRed", dis: "Hot Water Cost", }) catch null + try out=out.addColMetaClean("hwUse", {color:"orangeRed", dis: "Hot Water Use", }) catch null + try out=out.addColMetaClean("hwMessage", {color:"lightGray", dis: "Hot Water Warning", }) catch null + try out=out.addColMetaClean("chwCost", {viz:"barCell", color:"skyBlue", dis: "Chilled Water Cost", }) catch null + try out=out.addColMetaClean("chwUse", {color:"skyBlue", dis: "Chilled Water Use", }) catch null + try out=out.addColMetaClean("chwMessage", {color:"lightGray", dis: "Chilled Water Warning", }) catch null + try out=out.addColMetaClean("steamCost", {viz:"barCell", color:"slateBlue", dis: "Steam Cost", }) catch null + try out=out.addColMetaClean("steamUse", {color:"slateBlue", dis: "Steam Use", }) catch null + try out=out.addColMetaClean("steamMessage", {color:"lightGray", dis: "Steam Warning", }) catch null + try out=out.reorderKeepCols(["elecUse", "elecCost", "chwUse", "chwCost", "steamUse", "steamCost"]) catch null - return out + return out//.sort() end
wdg_portfolio_card_energySavings
--- wdg_portfolio_card_energySavings (pod) +++ wdg_portfolio_card_energySavings (local) @@ -1,7 +1,7 @@ //todo add emissions data (dates, opts:{}) => do - dates = dates.toSpan + //validate and authorize current user kwLinkValidate("analytics") @@ -12,9 +12,9 @@ //debug:true //get sites - grid : xq().xqProjs(navProjNames()) + grid : xq().xqTimeout(5min).xqProjs(navProjNames()) .xqDefine("dates",dates) - .xqReadAll(site) + .xqReadAll(site and workedOn) .xqMap("""site => do dict: {site:site->id} grid: wdg_site_card_costSavings(site,dates) @@ -27,47 +27,38 @@ totalSites: grid.size errSites: grid.findAll(r=>r.has("err")).size goodSites: grid.findAll(r=>r.missing("err")).size + //return goodSites if (debug=="Enable") return grid.reorderKeepCols(["site","err"]) + //return grid + //split it up into columns + chwCost_numbers: grid.colToList("chwCost").findAll(v=>v.isNumber) + chwCost: chwCost_numbers.fold(sum) - //split it up into columns - gasCost_numbers: grid.colToList("gasCost").findAll(v=>v.isNumber and v>0) - gasCost: gasCost_numbers.fold(sum) + steamCost_numbers: grid.colToList("steamCost").findAll(v=>v.isNumber) + steamCost: steamCost_numbers.fold(sum) - elecCost_numbers: grid.colToList("elecCost").findAll(v=>v.isNumber and v>0) + elecCost_numbers: grid.colToList("elecCost").findAll(v=>v.isNumber) elecCost: elecCost_numbers.fold(sum) - savingsIncentives_numbers: grid.colToList("incentives").findAll(v=>v.isNumber and v>0) - savingsIncentives: savingsIncentives_numbers.fold(sum) - savingsExtendedLife_numbers: grid.colToList("savingsExtendedLife").findAll(v=>v.isNumber and v>0) - savingsExtendedLife: savingsExtendedLife_numbers.fold(sum) - - savingsAvoidedOutsourcing_numbers: grid.colToList("savingsAvoidedOutsourcing").findAll(v=>v.isNumber and v>0) - savingsAvoidedOutsourcing: savingsAvoidedOutsourcing_numbers.fold(sum) - - totalCost: [gasCost,elecCost,savingsIncentives,savingsExtendedLife,savingsAvoidedOutsourcing].findAll(v=>v.isNumber and v>0).fold(sum) + totalCost: [elecCost,chwCost,steamCost].findAll(v=>v.isNumber).fold(sum) //put data into card and convert to grid card : {title:"Cost Savings", totalCost : totalCost, elecCost : elecCost, - gasCost : gasCost, - savingsExtendedLife: savingsExtendedLife, - savingsAvoidedOutsourcing: savingsAvoidedOutsourcing, - incentives: savingsIncentives + chwCost : chwCost, + steamCost : steamCost, } //return card out: card.toGrid .addMeta({vizByUnit}) - .reorderKeepCols(["totalCost","elecCost","gasCost"]) + .reorderKeepCols(["totalCost","elecCost","chwCost","steamCost"]) out=out.addColMetaClean("totalCost",{dis:"Total Cost Savings", viz:"barCell", color:"gray"}) .addColMetaClean("elecCost", {dis:"Elec Cost Savings", viz:"barCell", color:"orange"}) - .addColMetaClean("gasCost", {dis:"Gas Cost Savings", viz:"barCell", color:"purple"}) - .addColMetaClean("savingsExtendedLife", {dis:"Extended Life", viz:"barCell", color:"green"}) - .addColMetaClean("savingsAvoidedOutsourcing", {dis:"Avoided Outsourcing", viz:"barCell", color:"blue"}) - .addColMetaClean("incentives", {dis:"Incentives Paid", viz:"barCell", color:"pink"}) - + .addColMetaClean("chwCost", {dis:"Chilled Water Cost Savings", viz:"barCell", color:"skyBlue"}) + .addColMetaClean("steamCost", {dis:"Steam Cost Savings", viz:"barCell", color:"slateBlue"}) //check if anything is not a number and alter the colMeta so it shows up return out end
wdg_portfolio_card_sitesConnected
--- wdg_portfolio_card_sitesConnected (pod) +++ wdg_portfolio_card_sitesConnected (local) @@ -1,10 +1,14 @@ -() => do +(opts:{}) => do //validate and authorize current user kwLinkValidate("analytics") + //opts + projSel: opts.get("projSel") + //get all sites - sites: xq().xqReadAll(site).xqExecute() + //sites: xq().xqReadAll(site).xqExecute() + sites: readById(projSel).get("siteList").toRecList sitesWithPoints: sites.map(r => {site:r->id, points:xq().xqReadAll(point and hisEnd and siteRef==r->id).xqExecute().size}).findAll(r => r.get("points")>0) card: {primary: sitesWithPoints.size.toStr+"/"+sites.size.toStr,
wdg_portfolio_chart_cumulativeSavings
--- wdg_portfolio_chart_cumulativeSavings (pod) +++ wdg_portfolio_chart_cumulativeSavings (local) @@ -1,28 +1,35 @@ (dates, opts:{}) => do - dates = dates.toSpan + //validate and authorize current user kwLinkValidate("analytics") + if(dates.end.date > today()) dates= (dates.start..(today()-10day)).toSpan //opts debugVal: opts.get("debug") debug: debugVal!=null and debugVal!="Disable" - + projSel: opts.get("projSel") + projTypeName: readById(projSel).get("projName") + siteList: readById(projSel).get("siteList") + //return siteList //get arcs and sites - sites: xq().xqReadAll(site).xqExecute + sites: xq().xqTimeout(5min).xqReadAll(site).xqExecute if (sites.size==0) return blankChart("No sites", "Please add sites to get started") - portfolio: xq().xqProjs(navProjNames()) + + portfolio: xq().xqTimeout(5min) + .xqProjs(navProjNames()) .xqDefine("dates",dates) .xqDefine("preDate",dates.start - 1s) - .xqReadAll(site) + .xqReadByIds(siteList) .xqMap("""site => do - try {site: site->id, output:wdg_site_chart_cumulativeSavings(site->id,dates).hisFoldCols(sum).addRow({ts:preDate,v0:0\$}).addColMeta(\"v0\",{dis:site.dis}).renameCol(\"v0\",site.dis.toTagName)} + try {site: site->id, output:wdg_site_chart_cumulativeSavings(site->id,dates).hisInterpolate().hisFoldCols(sum).addRow({ts:preDate,v0:0\$}).addColMeta(\"v0\",{dis:site.dis}).renameCol(\"v0\",site.dis.toTagName)} catch (err) {site:site->id, err:err} end """) .xqExecute() //handle errors + //return portfolio if (debug) return portfolio goodSites: portfolio.findAll(r=>r.missing("err") and r.has("output") and r.get("output").meta.has("hisStart")) badSites: portfolio.findAll(r=>r.has("err") and r.has("output") and r.get("output").meta.missing("hisStart")) @@ -34,11 +41,12 @@ .hisJoin .addColMetaAll({hisMode:"cov"}) - + //return goodData //output - try combinedHis: goodData.hisInterpolate.stackedAreaChart.hisRollup(avg,1mo).addColMetaAll({-hisMode}) + try combinedHis: goodData.hisInterpolate.stackedAreaChart.hisRollup(avg,1day).addColMetaAll({-hisMode}) catch (err) return blankChart("Error - please report.", err.get("dis")) - out: combinedHis.addMeta({title:"Cumulative Cost Savings", subtitle:"Gas and Electric - "+goodSites.size+" / "+totalSites+" sites", -chartLegend}) + //return combinedHis//.hisFoldCols(sum) + out: combinedHis.addMeta({title: "Project: " + projTypeName + " Cumulative Cost Savings", subtitle:"Electric, Hot Water, Chilled Water, Steam - "+goodSites.size+" / "+totalSites+" sites", -chartLegend}) return out end
wdg_portfolio_chart_energy
--- wdg_portfolio_chart_energy (pod) +++ wdg_portfolio_chart_energy (local) @@ -1,5 +1,5 @@ (dates, opts:{}) => do - dates = dates.toSpan + //validate and authorize current user kwLinkValidate("analytics") @@ -8,18 +8,21 @@ debug: debugVal!=null and debugVal!="Disable" //get arcs and sites - sites: xq().xqReadAll(site).xqExecute + sites: xq().xqTimeout(5min).xqReadAll(site).xqExecute if (sites.size==0) return blankChart("No sites", "Please add sites to get started") //get energy data - portfolio: xq().xqProjs(navProjNames()) + portfolio: xq().xqTimeout(5min) + .xqProjs(navProjNames()) .xqDefine("dates",dates) .xqReadAll(site) .xqMap("""site => do - output: try getUtilityMeterSummary(site->id,dates).keepCols("ts,elec_usage,gas_usage".split(",")).hisRollupAuto + output: try getUtilityMeterSummary(site->id,dates).keepCols("ts,elec_usage,hw_usage,chw_usage,steam_usage".split(",")).hisRollupAuto catch (err) err try output=output.addColMeta("elec_usage", {chartGroup:"Elec", dis:site.dis+" (Elec)", -color, subtitle:"Electricity"}) catch null - try output=output.addColMeta("gas_usage", {chartGroup:"Gas", dis:site.dis+" (Gas)", -color, subtitle:"Gas"}) catch null + try output=output.addColMeta("hw_usage", {chartGroup:"Hot Water", dis:site.dis+" (HW)", -color, subtitle:"Hot Water"}) catch null + try output=output.addColMeta("chw_usage", {chartGroup:"Chilled Water", dis:site.dis+" (CHW)", -color, subtitle:"Chilled Water"}) catch null + try output=output.addColMeta("steam_usage", {chartGroup:"Steam", dis:site.dis+" (Steam)", -color, subtitle:"Steam"}) catch null if (output.isDict) {site:site->id, err:output} else {site: site->id, output:output} end @@ -27,7 +30,7 @@ .xqExecute() //handle errors - if (debug) return portfolio + if (debug) return portfolio.table goodSites: portfolio.findAll(r=>r.missing("err") and r.has("output") and r.get("output").meta.has("hisStart")) badSites: portfolio.findAll(r=>r.has("err") and r.has("output") and r.get("output").meta.missing("hisStart")) totalSites: portfolio.size @@ -38,7 +41,7 @@ .hisJoin //output - out: goodData.addMeta({title:"Energy Usage", subtitle:"Gas and Electric - "+goodSites.size+" / "+totalSites+" sites"}) + out: goodData.addMeta({title:"Energy Usage", subtitle:"Electric, Steam, Hot Water, and Chilled Water - "+goodSites.size+" / "+totalSites+" sites"}) - return out + return out.addMeta({chartLegend:"hide"}).hisClip() end
wdg_portfolio_chart_savings
--- wdg_portfolio_chart_savings (pod) +++ wdg_portfolio_chart_savings (local) @@ -1,5 +1,5 @@ (dates, opts:{}) => do - dates = dates.toSpan + //validate and authorize current user kwLinkValidate("analytics") @@ -8,19 +8,22 @@ debug: debugVal!=null and debugVal!="Disable" //get arcs and sites - sites: xq().xqReadAll(site).xqExecute + sites: xq().xqTimeout(5min).xqReadAll(site).xqExecute if (sites.size==0) return blankChart("No sites", "Please add sites to get started") //get energy data - portfolio: xq().xqProjs(navProjNames()) + portfolio: xq().xqTimeout(5min) + .xqProjs(navProjNames()) .xqDefine("dates",dates) .xqReadAll(site) .xqMap("""site => do - output: try getUtilityMeterSummary(site->id,dates).keepCols("ts,elec_savings,gas_savings".split(",")).hisRollupAuto + output: try getUtilityMeterSummary(site->id,dates).keepCols("ts,elec_savings,steam_savings,hw_savings,chw_savings".split(",")).hisRollupAuto catch (err) err try output=output.addColMeta("elec_savings", {chartGroup:"Elec", dis:site.dis+" (Elec)", -color, subtitle:"Electricity"}) catch null - try output=output.addColMeta("gas_savings", {chartGroup:"Gas", dis:site.dis+" (Gas)", -color, subtitle:"Gas"}) catch null + try output=output.addColMeta("steam_savings", {chartGroup:"Steam", dis:site.dis+" (Steam)", -color, subtitle:"Steam"}) catch null + try output=output.addColMeta("hw_savings", {chartGroup:"HW", dis:site.dis+" (HW)", -color, subtitle:"Hot Water"}) catch null + try output=output.addColMeta("chw_savings", {chartGroup:"CHW", dis:site.dis+" (CHW)", -color, subtitle:"Chilled Water"}) catch null if (output.isDict) {site:site->id, err:output} else {site: site->id, output:output} end
wdg_portfolio_widgetSelector
Sources are identical.
wdg_site_card_costSavings
--- wdg_site_card_costSavings (pod) +++ wdg_site_card_costSavings (local) @@ -1,5 +1,5 @@ (site, dates, opts:{}, debug:false) => do - dates = dates.toSpan + //validate and authorize current user kwLinkValidate("analytics") @@ -10,47 +10,43 @@ //opts //get site kickoff date, when savings started - savingsDate: getSiteKickoffDate(site) + savingsDate: null//getSiteKickoffDate(site) //if no savings date, just take the first day of this year - if (savingsDate==null) savingsDate = (dates.end - 1day).year.toSpan.start.date + if (savingsDate==null) savingsDate = (dates.start.date) //get utility meter summary data: try getUtilityMeterSummary(site, dates).meta catch (err) return {title:"Error! Action Required", error:(err.get("dis")), action:err.get("action")} - elecMeta: data.get("elecMeta") - gasMeta: data.get("gasMeta") +// elecMeta: data.get("elecMeta") +// gasMeta: data.get("gasMeta") //get utility rates - elecRate: if (siteRec.has("elecRate")) siteRec.get("elecRate") - else if (elecMeta.get("effectiveRollup").get("elec_rate").isNumber) elecMeta.get("effectiveRollup").get("elec_rate") - else null - gasRate: if (siteRec.has("gasRate")) siteRec.get("gasRate") - else if (gasMeta.get("effectiveRollup").get("gas_rate").isNumber) gasMeta.get("effectiveRollup").get("gas_rate") - else null //get additional savings year: (dates.end - 1day).year.toSpan - arcs: taskRun(xq().xqReadAll(arc and projectTracker).xqExecute()).futureGet - .filter(projectSite==siteId or siteRef==siteId) - additionalSavings: getArcAdditionalSavings(year, arcs) + //return data + //additionalSavings: getArcAdditionalSavings(year, arcs) //put data together for card - elecCost: data.get("elecMeta").get("effectiveRollup").get("elec_savingsCost") - gasCost: data.get("gasMeta").get("effectiveRollup").get("gas_savingsCost") - savingsExtendedLife: additionalSavings.get("savingsExtendedLife") - savingsAvoidedOutsourcing: additionalSavings.get("savingsAvoidedOutsourcing") - savingsIncentives: additionalSavings.get("savingsIncentives") - totalCost: [elecCost, gasCost, savingsExtendedLife, savingsAvoidedOutsourcing, savingsIncentives].findAll(v=>v.isNumber and v>0).fold(sum) + elecCost: try data.get("elecMeta").get("effectiveRollup").get("elec_savingsCost") catch null +// hwCost: data.meta.get("effectiveRollup").get("hw_savingsCost") + chwCost: try data.get("chwMeta").get("effectiveRollup").get("chw_savingsCost") catch null + steamCost: try data.get("steamMeta").get("effectiveRollup").get("steam_savingsCost") catch null + //gasCost: data.get("gasMeta").get("effectiveRollup").get("gas_savingsCost") + //savingsExtendedLife: additionalSavings.get("savingsExtendedLife") + //savingsAvoidedOutsourcing: additionalSavings.get("savingsAvoidedOutsourcing") + //savingsIncentives: additionalSavings.get("savingsIncentives") + totalCost: [elecCost, chwCost, steamCost].findAll(v=>v.isNumber).fold(sum) if (not totalCost.isNumber) totalCost = 0.as("\$") //round numbers if (elecCost.isNumber) elecCost = elecCost.round else "missing" - if (gasCost.isNumber) gasCost = gasCost.round + if (chwCost.isNumber) chwCost = chwCost.round else "missing" - if (savingsExtendedLife.isNumber) savingsExtendedLife = savingsExtendedLife.round - if (savingsAvoidedOutsourcing.isNumber) savingsAvoidedOutsourcing = savingsAvoidedOutsourcing.round - if (savingsIncentives.isNumber) savingsIncentives = savingsIncentives.round + if (steamCost.isNumber) steamCost = steamCost.round + else "missing" + if (totalCost.isNumber) totalCost = totalCost.round //put data into card and convert to grid @@ -58,24 +54,21 @@ subtitle : savingsDate.format("MMM DD YYYY").toStr+" to date", totalCost : totalCost, elecCost : elecCost, - gasCost : gasCost, - savingsExtendedLife: savingsExtendedLife, - savingsAvoidedOutsourcing: savingsAvoidedOutsourcing, - incentives: savingsIncentives + chwCost : chwCost, + steamCost : steamCost, } out: card.toGrid .addMeta({vizByUnit}) - .reorderKeepCols(["totalCost","elecCost","gasCost"]) - .addColMetaClean("totalCost",{dis:"Total Cost Savings", viz:"barCell", color:"gray"}) - .addColMetaClean("elecCost", {dis:"Elec Cost Savings", viz:"barCell", color:"orange"}) - .addColMetaClean("gasCost", {dis:"Gas Cost Savings", viz:"barCell", color:"purple"}) - .addColMetaClean("savingsExtendedLife", {dis:"Extended Life", viz:"barCell", color:"green"}) - .addColMetaClean("savingsAvoidedOutsourcing", {dis:"Avoided Outsourcing", viz:"barCell", color:"blue"}) - .addColMetaClean("incentives", {dis:"Incentives Paid", viz:"barCell", color:"pink"}) + .reorderKeepCols(["totalCost","elecCost","chwCost","steamCost"]) + .addColMetaClean("totalCost",{dis:"Total Cost Savings", viz:"barCell", color:"gray", format:"U#,###."}) + .addColMetaClean("elecCost", {dis:"Elec Cost Savings", viz:"barCell", color:"orange", format:"U#,###."}) + .addColMetaClean("chwCost", {dis:"Chilled Water Cost Savings", viz:"barCell", color:"skyBlue", format:"U#,###."}) + .addColMetaClean("steamCost", {dis:"Steam Cost Savings", viz:"barCell", color:"slateBlue", format:"U#,###."}) //check if anything is not a number and alter the colMeta so it shows up if (not elecCost.isNumber) out = out.addColMetaClean("elecCost",{-viz}) - if (not gasCost.isNumber) out = out.addColMetaClean("gasCost",{-viz}) + if (not chwCost.isNumber) out = out.addColMetaClean("chwCost",{-viz}) + if (not steamCost.isNumber) out = out.addColMetaClean("steamCost",{-viz}) return out
wdg_site_card_energyBenchmarks
Sources are identical.
wdg_site_card_energyCosts
--- wdg_site_card_energyCosts (pod) +++ wdg_site_card_energyCosts (local) @@ -1,5 +1,5 @@ (site, dates, opts:{}) => do - dates = dates.toSpan + //validate and authorize current user kwLinkValidate("analytics") @@ -12,50 +12,64 @@ //get data data: try getUtilityMeterSummary(site, dates).meta catch (err) return {title:"Error! Action Required", error:(err.get("dis")), action:err.get("action")} elecMeta: data.get("elecMeta") - gasMeta: data.get("gasMeta") + steamMeta: data.get("steamMeta") + chwMeta: data.get("chwMeta") + //get costs from meta elecCost: try elecMeta.get("effectiveRollup").get("elec_cost") catch "missing" - gasCost: try gasMeta.get("effectiveRollup").get("gas_cost") catch "missing" - totalCost: [elecCost, gasCost].findAll(v=>v.isNumber).fold(sum) + steamCost: try steamMeta.get("effectiveRollup").get("steam_cost") catch "missing" + chwCost: try chwMeta.get("effectiveRollup").get("chw_cost") catch "missing" + totalCost: [elecCost, steamCost, chwCost].findAll(v=>v.isNumber).fold(sum) //get hisEnd from effective points - asOfElecDate: elecMeta.get("effectivePoints").get("elec_cost").toRec.get("hisEnd").date - if (asOfElecDate > dates.end.date) asOfElecDate = dates.end.date + asOfElecDate: try elecMeta.get("effectivePoints").get("elec_cost").toRec.get("hisEnd").date catch "missing" + if (asOfElecDate!="missing" and asOfElecDate > dates.end.date) asOfElecDate = dates.end.date elecDateMsg: try "(as of "+asOfElecDate.format("MMM D YYYY") +")" catch "(no data)" - asOfGasDate: gasMeta.get("effectivePoints").get("gas_cost").toRec.get("hisEnd").date - if (asOfGasDate > dates.end.date) asOfGasDate = dates.end.date - gasDateMsg: try "(as of "+asOfGasDate.format("MMM D YYYY") +")" + + asOfsteamDate: try steamMeta.get("effectivePoints").get("steam_cost").toRec.get("hisEnd").date catch "missing" + if (asOfsteamDate!="missing" and asOfsteamDate > dates.end.date) asOfsteamDate = dates.end.date + steamDateMsg: try "(as of "+asOfsteamDate.format("MMM D YYYY") +")" catch "(no data)" + asOfchwDate: try chwMeta.get("effectivePoints").get("chw_cost").toRec.get("hisEnd").date catch "missing" + if (asOfchwDate!="missing" and asOfchwDate > dates.end.date) asOfchwDate = dates.end.date + chwDateMsg: try "(as of "+asOfchwDate.format("MMM D YYYY") +")" + catch "(no data)" //round numbers if (elecCost.isNumber) elecCost = elecCost.round.as(1) - if (gasCost.isNumber) gasCost = gasCost.round.as(1) + if (steamCost.isNumber) steamCost = steamCost.round.as(1) + if (chwCost.isNumber) chwCost = chwCost.round.as(1) + if (totalCost.isNumber) totalCost = totalCost.round.as(1) else if (totalCost.isNull) totalCost = 0 //dates string dateString: if (dates.end > now()) dates.start.date.format("MMM YYYY").toStr + " to " + "date" - else dates.start.date.format("MMM YYYY").toStr + " to " + dates.end.date.format("MMM-YYYY").toStr + else dates.start.date.format("MMM DD YYYY").toStr + " to " + dates.end.date.format("MMM-YYYY").toStr card : {title:"Energy Costs", subtitle : dateString, - totalCost : "", - totalCostVal : totalCost, - elecCost : elecDateMsg, - elecCostVal : elecCost, - gasCost : gasDateMsg, - gasCostVal : gasCost, + totalCost : "", + totalCostVal : totalCost, + elecCost : elecDateMsg, + elecCostVal : elecCost, + steamCost : steamDateMsg, + steamCostVal : steamCost, + chwCost : chwDateMsg, + chwCostVal : chwCost, } out: card.toGrid.addMeta({vizByUnit}) - .addColMeta("totalCost",{dis:"Total Energy Costs"}) - .addColMeta("elecCost",{dis:"Elec Cost ", color:"lightGray"}) - .addColMeta("gasCost",{dis:"Gas Cost ", color:"lightGray"}) - .addColMeta("totalCostVal",{dis:"", viz:"barCell", color:"gray", format:"\$#,###,###"}) - .addColMeta("elecCostVal",{dis:"", viz:"barCell", color:"orange", format:"\$#,###,###"}) - .addColMeta("gasCostVal",{dis:"", viz:"barCell", color:"purple", format:"\$#,###,###"}) - .reorderKeepCols(["totalCost","totalCostVal","elecCost","elecCostVal","gasCost","gasCostVal"]) + .addColMetaClean("totalCost",{dis:"Total Energy Costs"}) + .addColMetaClean("elecCost",{dis:"Elec Cost ", color:"lightGray"}) + .addColMetaClean("steamCost",{dis:"Steam Cost ", color:"lightGray"}) + .addColMetaClean("chwCost",{dis:"CHW Cost ", color:"lightGray"}) + .addColMetaClean("totalCostVal",{dis:"", viz:"barCell", color:"gray", format:"\$#,###,###"}) + .addColMetaClean("elecCostVal",{dis:"", viz:"barCell", color:"orange", format:"\$#,###,###"}) + .addColMetaClean("steamCostVal",{dis:"", viz:"barCell", color:"slateBlue", format:"\$#,###,###"}) + .addColMetaClean("chwCostVal",{dis:"", viz:"barCell", color:"skyBlue", format:"\$#,###,###"}) + .reorderKeepCols(["totalCost","totalCostVal","elecCost","elecCostVal","steamCost","steamCostVal","chwCost","chwCostVal"]) end
wdg_site_chart_baselineEnergy
--- wdg_site_chart_baselineEnergy (pod) +++ wdg_site_chart_baselineEnergy (local) @@ -2,15 +2,17 @@ //validate and authorize current user kwLinkValidate("analytics") + hisEndVal : if (dates.end > now()) now() else dates.end + dates = (dates.start..hisEndVal).toSpan + + siteDis: try site.toRec.dis catch null - dates = dates.toSpan - //opts rollup: null //1hr rollupFunc: avg chartType: "line" - strokeDasharray:"1,1" + strokeDasharray:"8,5" //get kickoff date for site kickoffDate: getSiteKickoffDate(site) @@ -19,27 +21,29 @@ //get data try grid: getUtilityMeterSummary(site, dates) catch (err) return blankChart("Error: "+err.get("dis"), err.get("action")) - colNames: grid.colNames.findAll(r => r.contains("_usage") or r.contains("_model")).add("ts") - grid=grid.keepCols(colNames) + grid=grid.keepCols(["ts","elec_usage","elec_model", "steam_usage","steam_model", "chw_usage","chw_model", "hw_usage", "hw_model"]) + //grid = grid.addMeta({hisEnd:hisEndVal}) if (grid==null) return blankChart("Energy Compared To Baseline", "No data found for "+siteDis) out: grid.toGrid.addMeta({title:"Energy Compared To Baseline", subtitle:siteDis}) .hisRollupAuto(rollup, his=>rollupFunc) - if (out.meta.get("hisEnd") > now()) out=out.addMeta({hisEnd:now()}) + //if (out.meta.get("hisEnd") > now()) out=out.addMeta({hisEnd:now()}) - out= out.addColMetaClean("elec_usage", {chartType:chartType}) - .addColMetaClean("elec_model", {chartType:chartType, strokeDasharray:strokeDasharray}) - .addColMetaClean("gas_usage", {chartType:chartType}) - .addColMetaClean("gas_model", {chartType:chartType, strokeDasharray:strokeDasharray}) + out= out.addColMetaClean("elec_usage", {chartType:chartType, color: "orange"}) + .addColMetaClean("elec_model", {chartType:chartType, strokeDasharray:strokeDasharray, color: "orange"}) + .addColMetaClean("steam_usage", {chartType:chartType, color: "slateBlue"}) + .addColMetaClean("steam_model", {chartType:chartType, strokeDasharray:strokeDasharray, color: "slateBlue"}) + .addColMetaClean("chw_usage", {chartType:chartType, color: "skyBlue"}) + .addColMetaClean("chw_model", {chartType:chartType, strokeDasharray:strokeDasharray, color: "skyBlue"}) .addColMetaClean("hw_usage", {chartType:chartType}) .addColMetaClean("hw_model", {chartType:chartType, strokeDasharray:strokeDasharray}) - .addColMetaClean("chw_usage", {chartType:chartType}) - .addColMetaClean("chw_model", {chartType:chartType, strokeDasharray:strokeDasharray}) - .addColMetaClean("steam_usage", {chartType:chartType}) - .addColMetaClean("steam_model", {chartType:chartType, strokeDasharray:strokeDasharray}) + + //g: wdg_site_chart_cumulativeSavings(site, dates)//.addMeta({chartGroup: "savings"}) + //outFinal : hisJoin([out, g]) + + return out//.addMeta({hisEnd:hisEndVal}) - return out end
wdg_site_chart_cumulativeSavings
--- wdg_site_chart_cumulativeSavings (pod) +++ wdg_site_chart_cumulativeSavings (local) @@ -1,17 +1,18 @@ // 6/3/24 JG fix bug on line 37, convert dates to span -(site, dates) => do +(site, dates, opts:{showStackedAreaChart:false}) => do //validate and authorize current user kwLinkValidate("analytics") - dates = dates.toSpan + dates = dates//.toSpan //normalize inputs siteRec: site.toRec siteId: siteRec->id //opts - showKickoffDate: true + showKickoffDate: false + showStackedAreaChart: opts.get("showStackedAreaChart") //get kickoff date savingsDate: getSiteKickoffDate(siteId) @@ -20,28 +21,32 @@ data: try getUtilityMeterSummary(site, dates) catch (err) return blankChart("Error: "+err.get("dis"), err.get("action")) //keep savings for gas/elec - savings: data.keepCols(["ts","elec_savingsCost","gas_savingsCost"]) + savings: data.keepCols(["ts","elec_savingsCost","hw_savingsCost","chw_savingsCost","steam_savingsCost"]) .hisRollup(sum, 1day) //if both savings columns are empty, return blank grid - if (savings.isColBlank("gas_savingsCost") and savings.isColBlank("elec_savingsCost")) + if (savings.isColBlank("hw_savingsCost") and savings.isColBlank("elec_savingsCost") and savings.isColBlank("chw_savingsCost") and savings.isColBlank("steam_savingsCost")) return blankChart("Cost savings data is unavailable", "Check cost savings points", dates) + hisEndVal : if (dates.end > now()) now() else savings.meta.get("hisEnd") + //add cumulative sum columns + out: savings.addMeta({title:"Cumulative Cost Savings", subtitle:readById(site).dis, hisEnd:hisEndVal}) + //.findAll(r => r->ts.date >= savingsDate) + .addColCuSum("steamSum","steam_savingsCost") + .addColCuSum("chwSum","chw_savingsCost") + //.addColCuSum("hwSum","hw_savingsCost") + .addColCuSum("elecSum","elec_savingsCost") + .keepCols(["ts","chwSum","elecSum","steamSum"]) + if (out.isColBlank("steamSum") and out.isColBlank("elecSum") and out.isColBlank("chwSum") and out.isColBlank("hwSum")) return blankChart("Cost savings data is unavailable", "No data after kickoff date", dates) - //add cumulative sum columns - out: savings.addMeta({title:"Cumulative Cost Savings", subtitle:readById(site).dis}) - .findAll(r => r->ts.date >= savingsDate) - .addColCuSum("gasSum","gas_savingsCost") - .addColCuSum("elecSum","elec_savingsCost") - .keepCols(["ts","gasSum","elecSum"]) - - if (out.isColBlank("gasSum") and out.isColBlank("elecSum")) return blankChart("Cost savings data is unavailable", "No data after kickoff date", dates) - - try out = out.stackedAreaChart() catch out - out=out.addColMetaClean("gasSum",{chartGroup:"main", color:"purple", dis:"Gas Savings"}) - .addColMetaClean("elecSum",{chartGroup:"main", color:"orange", dis:"Electricity Savings", title:"Cumulative Cost Savings - "+site.toRec.dis}) + if(showStackedAreaChart) try out = out.stackedAreaChart() catch out + out=out.addColMetaClean("steamSum",{chartGroup:"savings", color:"slateBlue", dis:"Steam Savings"}) + .addColMetaClean("elecSum",{chartGroup:"savings", color:"orange", dis:"Electricity Savings"}) + .addColMetaClean("chwSum",{chartGroup:"savings", color:"skyBlue", dis:"Chilled Water Savings"}) + //.addColMetaClean("hwSum",{chartGroup:"main", color:"orange", dis:"Hot Water Savings", title:"Cumulative Cost Savings - "+site.toRec.dis}) //fix hisEnd so chart axes are correct - if (dates.end > now()) out=out.addMeta({hisEnd:now()}) + // ERRORING IN 3.1.11 + //if (dates.toDateSpan.end > now()) out=out.addMeta({hisEnd:out.last.get("ts")}) //add kickoff date line if (showKickoffDate) do @@ -50,5 +55,5 @@ .addColMetaClean("kickoff",{chartGroup:"main", dis:"Kickoff Date", strokeDasharray:"2,4", color:"black", format:"#"}) end - return out + return out.addMeta({chartNoScroll})//hisJoin([out, wdg_site_chart_baselineEnergy(site, dates)]).addMeta({chartLegendNoSort}) end
wdg_site_chart_monthlykBTUUsage
Sources are identical.
wdg_terminalUnits_chart_damperPositions
--- wdg_terminalUnits_chart_damperPositions (pod) +++ wdg_terminalUnits_chart_damperPositions (local) @@ -54,8 +54,9 @@ if (colm.name !="ts") do avg: his.colToList(colm.name).fold(avg,"*") pointMeta: colm.meta - color: "#B2E1FA" - strokeWidth:0.25 + //color: "#B2f1FA" + color: "#007BFE" + strokeWidth: 0.25 if (avg>90) do color = "red" strokeWidth=2
wdg_terminalUnits_chart_hotColdZones
--- wdg_terminalUnits_chart_hotColdZones (pod) +++ wdg_terminalUnits_chart_hotColdZones (local) @@ -28,19 +28,17 @@ end opts = opts.set("rollupOverride",rollupOverride) - occDisp: opts.optNorm("occDisp", false) - //logic //check status function checkStatus: (val) => do - if (val==null) "unknown" + if (val==null) "unkown" else if (val > 0) "too hot" else if (val < 0) "too cold" else "good" end - + if(vavRecList.isNull or vavRecList.isEmpty) return "No Data" //create output grid grid: [] errGrid: [] @@ -71,36 +69,17 @@ unknown: vals.findAll(v=>v=="unknown").size } end - //add total cannot calculate vav number - out = out.map(r=> do - cold: r.get("cold") - good: r.get("good") - hot: r.get("hot") - unknown: r.get("unknown") - totalCalculated: cold + good + hot + unknown - totalVavs: readAll(equip and vav and siteRef == vavs.first->siteRef).size - r = r.set("cannotCalc", totalVavs-totalCalculated) - end) //format if (showUpstreamData) try out = [out, wdg_terminalUnits_chart_upstreamData(goodPoints.first.toRec.get("equipRef"), dates, opts)].hisJoin catch null -return out = out.stream - .reorderCols(["ts","cold","good","hot", "unknown", "cannotCalc"]) - .addColMetaClean("cold", {dis:"Too Cold", chartType:"area", chartAreaMode:"zero", color:"blue", chartMin:0, chartMax:vavRecList.size, title:"VAV Zone Status", subtitle:"Blue = cold, Red = hot, Green = good, Gray = unknown, Purple = cannot calculate"}) + out = out.stream + .reorderCols(["ts","cold","good","hot", "unknown"]) + .addColMetaClean("cold", {dis:"Too Cold", chartType:"area", chartAreaMode:"zero", color:"blue", chartMin:0, chartMax:grid.size, title:"VAV Zone Status", subtitle:"Blue = cold, Red = hot, Green = good, Gray = unknown"}) .addColMetaClean("good", {dis:"Good", chartType:"area", chartAreaMode:"prevSeries", color:"green"}) .addColMetaClean("hot", {dis:"Too Hot", chartType:"area", chartAreaMode:"prevSeries", color:"red"}) .addColMetaClean("unknown", {dis:"Unknown", chartType:"area", chartAreaMode:"prevSeries", color:"gray"}) - .addColMetaClean("cannotCalc", {dis:"Cannot Calculate", chartType:"area", chartAreaMode:"prevSeries", color:"purple"}) .collect .stackedAreaChart - - if (occDisp) do - if (ahuId.isNonNull) ahuIds: [ahuId] - else ahuIds: vavRecList.map(v => v.get("airRef")).unique.findAll(v => v.isNonNull) - occHis: ahuIds.map(v => v.logic_ahu_occPeriods(dates, {}, {})) - out = [out].addAll(occHis).hisJoin - end - return out -end +end //end func
wdg_terminalUnits_chart_zonesHeatingCooling
--- wdg_terminalUnits_chart_zonesHeatingCooling (pod) +++ wdg_terminalUnits_chart_zonesHeatingCooling (local) @@ -1,4 +1,3 @@ -// Updated 2025-08-27 by Kyle Wolfe to add occ/AHU status to display if occDisp option is true (ahu, dates, opts:{}, vavs:null) => do //validate and authorize current user @@ -29,10 +28,8 @@ end opts = opts.set("rollupOverride",rollupOverride) - occDisp: opts.optNorm("occDisp", false) - //logic - + if(vavRecList.isNull or vavRecList.isEmpty) return "No Data" //create output grid grid: [] errGrid: [] @@ -74,13 +71,5 @@ .addColMetaClean("unknown", {dis:"Unknown", chartType:"area", chartAreaMode:"prevSeries", color:"gray"}) .collect .stackedAreaChart - - if (occDisp) do - if (ahuId.isNonNull) ahuIds: [ahuId] - else ahuIds: vavRecList.map(v => v.get("airRef")).unique.findAll(v => v.isNonNull) - occHis: ahuIds.map(v => v.logic_ahu_occPeriods(dates, {}, {})) - out = [out].addAll(occHis).hisJoin - end - return out -end +end //end func
wdg_terminalUnits_table_ahuSummary
--- wdg_terminalUnits_table_ahuSummary (pod) +++ wdg_terminalUnits_table_ahuSummary (local) @@ -1,5 +1,6 @@ -// Updated by Kyle Wolfe on 2025-08-27 to get sparks from both the individual points on the AHU, -// and the AHU rec itself +// Updated by Kyle Wolfe on 2025-08-27 to get sparks from both the individual points on the AHU, and the AHU rec itself +// Updated by Justin Brunner on 2026-01-23 to add supplyOnly opt that will filter all vav lists to be supply only vavs when true + (site, dates, opts:{}) => do //validate and authorize current user @@ -14,6 +15,7 @@ rollupOverride: if (opts.has("rollupOverride")) opts.get("rollupOverride") else null debug: opts.get("debug")!=null and opts.get("debug")!="Disable" occOnly: if (opts.has("occOnly")) opts.get("occOnly") else true + supplyOnly: if (opts.has("supplyOnly")) opts.get("supplyOnly") else false //AHU LOOP ahus: readAll(ahu and siteRef==siteId and equip and not vavSummaryNoShow) @@ -28,6 +30,7 @@ //get downstream units downstream: readAll(equip and airRef==row->id) + if(supplyOnly) downstream = downstream.filter(supply) downstreamIds: try downstream.colToList("id") catch null rules: readAll(rule and not disabled) @@ -47,9 +50,11 @@ end //get undefined and all units - undefined: try readAll(siteRef==siteId and vav and not airRef and equip).colToList("id") + undefined: try if(supplyOnly) readAll(siteRef==siteId and vav and not airRef and equip and supply).colToList("id") + else readAll(siteRef==siteId and vav and not airRef and equip).colToList("id") catch [] - all: try readAll(siteRef==siteId and equip and vav).colToList("id") + all: try if(supplyOnly) readAll(siteRef==siteId and equip and vav and supply).colToList("id") + else readAll(siteRef==siteId and equip and vav).colToList("id") catch [] out: grid.sort("id")
cacheGrid
--- cacheGrid (pod) +++ cacheGrid (local) @@ -1,15 +1,23 @@ (records, specialTagName, dates) => do - cipherText : - "AxD:T1BkkICIb4SOTMNJwbx-wA::PFhoj0MDm4_m4f9zzsJ0r_2M-Jv19NOtXHFa-dXnXemkHI9vgIdn" + - "KI3TBsEUEto9uneAdwPxA5TYYbg5op3Exs2g0mcAtC2nSFl-g-ZIX6N0H9xJLgsiF5MhjetDhkor5QdG" + - "qIzzrBZcQ_lZiZ-NLEvj6038-R0XV8tZFbPv3iIDcAxPX5Zfq-j82GnABIdiUd3v-tMDlLql3-TDf622" + - "0wrebG9FJDy7a7hZCwuK26r0UMve0W54qs_ADpr0GLK4EEEd5Ld0KRhYtlsLaWn11LXNx6M9qwLx_FLl" + - "JS7Av6E-2QoTCmFzPRiWhpu5m8m01-tpPaDyB--paC2NzvlVfP0NUqqjn0vKyoGsrBeoonpcqhFqYs5x" + - "B5bEUL1PWuS4xJLeUNSf_eCymbRzE1zwIJkrk9Cm_Yku3X8gQVbGarqBz7LD92WbxPxC2kaY0EL7fzZI" + - "MiPj7rmj9ep3y9sEqUoyfjYK7w3uQrG4Cd5AngMwprhL_lwYLwcTSA5Ci1f9DSIg92LU8w2wK6AyZogB" + - "tihcDWo3j7W2T8BS3ptKSZ80UGlcXWNAacH16FbjHC4mEvJ06wFIwwtnnrEhzdmlHpE8LDe0RUbheqo0" + - "oLoIiBWsKAO_ctuuEyN729NuwPpRS4tENIYqFWtkTD79eJIxnHSUo6N8paPpN1nCJ1PXK5_gBBth4xTx" + - "iBXgPJYoB9qutd5LxHIAnHIfyHO2IsjpbkX7VgYmdj3P_U2zije45u4" - keyFunc : () => "ddJNIRm2qio2Z7CXpKADiw" - return afAxonEncryptorRt_callFunc("cacheGrid", cipherText, [records, specialTagName, dates], keyFunc) + if(not dates.isSpan) dates = try dates.toSpan catch "all" + dateYear: try dates.start.year() catch "all" + if(records.isNull) return "First parameter needs to be a grid" + if(records.isEmpty) return "First parameter needs to be a grid" + if(not specialTagName.isStr) return "Second parameter needs to be a string" + //if(dateYear == "all") filter: "cache and " + specialTagName + " and cacheYear==everything" + filter: "cache and " + specialTagName + previousCachedRecs: readAll(parseFilter(filter)).findAll(r => r.get("cacheYear") == dateYear) + if(previousCachedRecs.size > 0) do + //recDelete(previousCachedRecs) + previousCachedRecs.each() p => do + diff(p, {trash}, {remove}).commit + end + end + //Write to the cache + //if(specialTagName.contains("portfolio")) records = records.renameCol("site", "siteR") + records.each() r => do + newTags: {cache:marker(), cacheYear:dateYear}.set(specialTagName.toStr, marker()) + r = r.merge(newTags) + diff(null, r, {add}).commit() + end end
logic_hisPoint_missingData
--- logic_hisPoint_missingData (pod) +++ logic_hisPoint_missingData (local) @@ -1,16 +1,48 @@ +/* +* Description : +* Retrieves the periods in which the historized point is missing data. +* +* Parameters : +* Type Name Description +* Ref target Historized Point +* DateSpan dates Dates to look at +* Dict opts Additional Options +* +* Output : +* Type Name Description +* hisGrid out - Period Grid of missing periods, or null if no history found. +* +* Work : +* Who When Change +* Thomas Kuhrke Limia 08/22/2025 - Initial Creation +*/ (target, dates, opts: {}) => do - cipherText : - "AxD:tnVmPw83PQLMOKwn-pkJeA::ckW6lCkR97Mf2mjlP2jqEEqYo9IYSPGYT5z6X0x9d0ttkHwpJ7j1" + - "Rd-BFOMN8fajur85oSps3v8-f5B14FJgQzh3u3NQsunH7zENgNuLkDqpDu29PlWFju5EVk2daOEQbUQz" + - "6tLidM3mcTfnWTUULp19ofGH_XpSq3vbFs6Nyywq1N-9B1hIVMBR3Ze1ex0tYbBCHVg1_Ix3lSCQGGXZ" + - "rXP8hyjKfhINXzaWrXsY-gdE4MQPb3TnHWqM2lvYrhsZYQ_itA1TPgRzdEAI_3q3rgieUv19XxwLoV7u" + - "9PftpgqpskBDN71X2dZL2CyAzwXBI1xyJoHr-Ou-WEQ4lRI5mDpT0kwzF3nD3tQepHuAc_VYu4O89V6Q" + - "Kpq0DmzGHV5pXq_YGDXWD6X6XfxfoO9t24KGfX6LrDMJX5hgxzq9b0c_YIXWyQA4fFdrwbM9MQAqI3VD" + - "j3jkTpGW0bakHSV5mvY4l65uFVCv3jqNSVBEq5JVXvOX3sZBl9XvRIrFknyBgj8wOpe4r07pKkP_eom3" + - "ewuHx7-Jr5GoxCc-H1XliBn36JDWTabYt3VUvjapAI3x4j9hhauwnaCXrPax-9IfVJdl1B4d_nupqhw3" + - "cGGr-eqY1EjPFtu4TGHiNPr_FyHTPpSVBe8aRyJFNCMold5RdWcSfwvWMSkZ4t1D5ACCrR9YpqzR59a9" + - "DbixgAQXmMpyJndvANPAIbrY3iAzsYhO_OHhmFfzEZSom54-pvPwd-juS4neMQmwIg6c8HEWgQkYcarA" + - "Ui2AoMoPhNgqpmu0aA" - keyFunc : () => "ddJNIRm2qio2Z7CXpKADiw" - return afAxonEncryptorRt_callFunc("logic_hisPoint_missingData", cipherText, [target, dates, opts], keyFunc) + + // Normalize Inputs + targetRec: target.toRec + targetId: targetRec.get("id") + dates = dates.toSpan + + // Retrieve his data, and calculate durations between timestamps + his: targetId.hisRead(dates, {-limit}) + + // Edge-case (Empty His returns null) + if (his.hisClip.isEmpty) return null + + // Add the delta column of durations + deltaHis: his.addColDelta("ts") + + // Determine Data Interval to use (prefer meta interval, and fallback on median) + dataInterval: deltaHis.foldCol("delta", median) + + // Find periods where the dataInterval doesnt match + periods: deltaHis.keepCols(["ts", "delta"]) + .hisFindPeriods(v => v.isNumber and v != dataInterval) + .renameCol("delta", "dur") + + // Combine all data for output + out: hisJoin([his, periods]) + + // Return + return out end
pointQueryLookup
--- pointQueryLookup (pod) +++ pointQueryLookup (local) @@ -1,61 +1,325 @@ -(target: null, opts: {}) => do - cipherText : - "AxD:J7ik5GzASro65uWVIxMkAg::7cPS7lsTZSH5N2vG2V_-JnF7WnnW0YzEzAkoWuWN0t33cekbuST1" + - "jdwUtsnrnsWKnY2ZJ11FgjHRBw-4DchwEYWtNDzsPhtoG9qIeWzimhGiuRu1zA5WRrk0313ancLuQXcH" + - "zUsoSr9-_gDRNSvmhd8jJ8XaV0eozzR7scJJx801Sxs1lYKqn9-efJgMoGE5yUdio-ucRJMKwXCuww-J" + - "b8TqM0LRciBpX_qgy9sWW83-toyx1g1E6NXoPfuyE4EB_DXdpr3CmMSWscawuIAE3KH2FmPCMCU8ihr3" + - "tr_mcJm1MYsEo96AokjwJZusgH38mbnKrRoCf8NHPHr0pfCbgMSC-bF-D68vIgcs7pkROhkb8dHHy0Yb" + - "BGZHrQwecGLFxh3jego2SM4MSQxMksgcXyMChH17bY10l6VEqvIczPolCB66sNO2bVrCc5FWAFPGXxtr" + - "m_T7E__lMU78LEPWLfO1UMWE_FLJtlEAQbuv_xhB4jUy4kyqpWCjuwNLkCrYY7sWHzyE90-Ys6SJzJLF" + - "INz9kBTIPWsbbjDHx0satQxguftZqyzoAjtoNJvymRdqyVTMTH2kLe1zoF_fI7afvDstxdp_YJ1Snx8y" + - "b3DLsnyLYJmKX7M8z4og1VWfRq6MdK-OCyjnRkLCO8Yv2ieCKWXBBbt7b5H7sVq8aZe-QHMINJW9XJQa" + - "AnOn9ePqiMWZoCfUbSB_dpwe89a9xMwOB_Ndj9gW8AoXEiK2uUgBEN_p4zcjOmNOJemXpluU-yQDFqJ3" + - "bZKgktkwNLUwrhYAYsp8Rg12CkGeXqx5hEEhEeXaUZisO7OKUHC9iFpi0CXbKbIB7bQc5kmWXCQNOKpk" + - "WJX_EPBrGrlmKXXseMsPuT78bkNoPxGbYxGwE4cSIfDqE0wkZOpILvuYXWkc5_jIdwuNsHSNLMXtEG2W" + - "NZ2dCBXpdFS7pFE5KrdkkydqepBBHgcCia5uNWcm1Sm9MuqqhjSK3R2r8D8VxPAJNIP-B05znD5pcUt8" + - "H-XKlS1RIkPpOpT3_0o_ieo7Dk2A51Ta4aSMsV1dkCGA78aq6mSF6oBYWefmW2FGYsmJjl0_KhJ30cuM" + - "-VLV1Tm58wPWB4gk-VTLLCCYqcu2eiH2XOMA5h2A0Jqm8nAp0-VH8rIvsgcdXV7OyBp7RThiFhmXrczT" + - "9UjSq1fDGg5ss22R-nyAlL6Cy9lFNgAwJXhhZGyoeEmKAnTju_Eszm8fkclrd66V2OG8Oumqyo_uLyAT" + - "WaOvw-a_AV8IniBRcJsnpdMFFuoGLKQ_IeAojF82KpVG0sB7Q9SR5iOJOCgu1zOfjmbJJuRiKt_5lvlX" + - "vjjxxHEwjXF_f-PFNDclHEwLpjwPm0u3Vln7BaLW0nbWkRsC8_GugIUsI0JIOZXfv7gCowIcqWPqFl2k" + - "AQTXjulVkhATkjviOkhCRzRpJgBt_4vjZzIPZKnJZqEq1aIDDCk8TxIBlABWT2Secx_B7z6vXxM6sKJO" + - "nThHzuHjlsJYDXrMEq1NVYtIz6HOv86FEksDz8zR7cCtSfQE2z-PMEeIBL0g5g4k5lDduU0ltFQDamy8" + - "jGokPxsAKgmYeqtWlvQDFircTDaUEURdVC0t0aRmXAOHIlhqYslE5vMmXfaZyB8tY8XC-QO4RwKRNOsA" + - "Ii_lUujsAX-uRZib_Qj79SArzhQVKHalYEglFumjDyOfjftf0dAqW7Lm3RzLBPnSAP5drZMTfCqr_keo" + - "qCRPNnnsdgVhHpauC4oI3UwJJ3cnm6wK1qCQzw3LQTapoht77RJRHPZ0uepNmuxAENkXf0tm_ViUbsSj" + - "6EFCV5CDWQqH3aXWIdkiCAU4A0RkucCfFULcqINf2dfBkY3R9167QcyyhIIR335dIg-Jn2S3Ms2TuOiJ" + - "mVIx3ht7V091uCY6UWCmpIKebvMwnDubPnelivQ9tAwKnC2jR4eo_SppqT981sI61cG0tmud_TU6lwIW" + - "KoCXkm74hOIIw-JtB0zwfMXU1joh9m0_aPdw2FHyn4IhZVKpLeLYGlq8LtA_f723YpAqGzUM3VdjBqBq" + - "evHqr-YL5X8Rq5CdMndKEk5xKgy7a9tabPjmQINlDJvPOh69qnCXU0EjY9YJkJAfVBM0-QUw2ENrkk8X" + - "0Jnerfrdo-jFmA4UGKQlRooB3WU2zRbzNHpUOlUhdr1PGvwaKFeZBVgD8mKPorQ9M9fpbfvLv94j4u0a" + - "vGuJnHS8fIEIIttwkptkl6dZY5VJPirMexsQ8x9h7WlmoJc5KmkWxBQhDvM3Ct_MUx1rZJNrOLNi4Ie5" + - "Js_rUphBPRUBvsZoHHP6a7BkoGVK1Jkkz94oVE3S43QHcwxLRg7LerPwKMIfnnNynQDm7IE0n7FJ6I1J" + - "SrIJnQ0Lw2TrKHGF3LxRqJPpnzxYXyk__AlFTONjPxdh5D5GWbOXxupbq2XetLrtcbPlXiVhewejzhdo" + - "9AAHINpe-THmsGMM0YgSq6TGY-nbox6NZfQIV7lFpKfbhb4-vRv6CTcrSo2nPxcPPJklUYDX8AK7h4L2" + - "Hmc6n3T-BFv3rttrQnM2kmSPKZ2CzO3cMuLCOIdgoO12BVTnhT6Q46g5gwL6YSdsuOcRR1lpko7AMUmv" + - "KYDmI_qQ3gpToK2m2VtjzmpdQwQPsHEoGZ3KCv3FE37x64gVBjFjkcJuOj8PL87x2xJVivML5GYLopia" + - "u6glIJnSB-lRUd_NZZanFi05MKqaD37mr4thZHmNgUbyKKJceApVRwPQnH5JXZ-hIdOkErcKotzzFSXH" + - "QElnlHMJwPqlMH-_7FC2pKOgpjeIZTaAZtI5yubMlvRu6xEYYZMVWjko6C0w6JGAztBsbGGih-cp9UgZ" + - "vqVdxZpueTfDpepAdIPFNYl5GthaQfyzfldAD2a16HgTl7_RGNKkecRQEq_KUr6iX9Q1PyvswN4LSN6v" + - "AMgI8Uimcz0ZFZ2GT9AV8rWnSSLxTq-QIMjbJORY3LwDzKOG9IOs4T-5ZAuGoaDwmNklXTxUyPrCAGgT" + - "koFLAbO8hgV3OIuAMAjOFf77vsgFVzsQhSCAx9uDKsowXuxTnwwfkWn60jPoeZFW_D_IMw_SUil3b73h" + - "XvVU9TzYdYzAldUUSs8c9T32w_EqTx3dAFeq_UZenGz-Hpb0UvrdWaG4Nak31iEDMWgEaa6A5m7DVrCp" + - "Ep95i5hgSxW_A9piXVMf0yuX0nS2pUk9I156QvkqM_nqLi0KeHTdObLNxq40FWgvzE8yh-1xYXkUOS9C" + - "x2pkdEnzNWPzvKEIUPKyaNS6rDKHi4OW2Z20UHi9G08mrHfFWV-tv59bisy7pJA5Gaa2sB7GFqUqyh5X" + - "mLu9Vy98861yGdSVdKybEmwLrOgz20N63ie0ACuRk6UVaQaFgQX5ZZFBKSO19gsqiNxAGTPucd-9-K8y" + - "cBtQJ3bJgjboXjjQ7J-ehZxYvVJI-88Rsst_hnmgLUlmqwcZEtOVPuZEl7PjecfjB_2TzH0YQcW1BfWZ" + - "kr7fT7nwjf-Ow_za4spUGPe2BVMsG8wxDTvVwzzP8Qs-CrExhKiqxD7vImKOyel2BXU79lSJ80EFZJpV" + - "AmWma5DPsQHQGWxHVYCSe4MBvKBFvu0nE2P3YohFlxU4eR4FDC9ELCSuzy3O-FPmIDZNlb5H-CxKSDf-" + - "x7RL9sAPVduoRyKm30xnjUh61B2MOlORwB4buvAMVFIqURU86jNv6UqSUjHK_JigaLN9FDz-QJfUT72e" + - "XX10CJiRvdf9MNPOQ6UZ3scFY0OgFNW6g6BCs3u_wrRvljuvkFI5LYLENV1XGLKLjjmBufV3vfjSql3f" + - "ihfVGCGjXRLXgutD5lSZpGbSF05Clf1JxfSUJCq1rP4V_3GzXMwZD9AB7_Z3loOAkeRAmsjGndYKW833" + - "DbR_zGnFc6EoVlDvHScL_l1UYF-piWIb9IOUZ5WdGc0LDiOfSIj3oltosUnyC73nBmLcnRiBKbbKgIlm" + - "TnyGvqONb_vKNBsOM5f36dcW9AeFBrxLl0-huFK3XA81fp9shkvpybeJz06GmRhVIu9kzAWhqH-rRoE2" + - "7YuB8U4a6I-5VpHQGdMxAN7tIqpziaSDjsVjlqmvOPk0VQzES2d4Asf6IYRyiA7W-OfGi5pBiw3f2JNR" + - "leiFvUGd_nBA0Rc-6C9HGTzMLmMzIr_SXfvUxJvBvJRfoEQkWwfdb-FE5dkCupIiFrTR0Lu699B7ACEJ" + - "k1itx5Q-p3jUqdSEG7AeqdLT6JJ5CwBoEiC1wa15itVs4q2TlsYKVgVWfXDQ06ax7qGwWgYQyk_xwTfE" + - "p7erfra5P0wL3XDCtKE_oMX0HSpgVgqvKAzDF7GulOpzs8pFiGlNa2a0-6MeZ3cY3Id9vjlDSfdwtg_r" + - "5yPKDd7I10BFV9PSq6PtI6LVpZDGgTsThjMRpjnloYsrcik5Y_JN8HdTDe2UUZzLlQ" - keyFunc : () => "ddJNIRm2qio2Z7CXpKADiw" - return afAxonEncryptorRt_callFunc("pointQueryLookup", cipherText, [target, opts], keyFunc) +(target:null, opts:{}) => do + + //opts + + + colMeta: if(opts.has("colMeta")) true else false + show: if(opts.has("show")) true else false + + + queries: [ + /////////////////////// AHUS ///////////////////////////////// + //temps + {target:"oat_sensor", query:"temp and air and point and outside and sensor", colMeta:{color:"#00b843"} }, + {target:"dat_sensor", query:"temp and air and point and discharge and sensor and not leaving and not entering", colMeta:{color:"#0547fc"} }, + {target:"dat_sp", query:"temp and air and point and discharge and sp", colMeta:{color:"#5cb3ff"} }, + {target:"mat_sensor", query:"temp and air and point and mixed and sensor", colMeta:{color:"#FFD580"} }, + {target:"mat_sp", query:"temp and air and point and mixed and sp", colMeta:{color:"#FFA500"} }, + {target:"eat_sensor", query:"temp and air and point and exhaust and sensor", colMeta:{color:null} }, + {target:"rat_sensor", query:"temp and air and point and return and sensor", colMeta:{color:"#FF0000"} }, + {target:"zntClg_sp", query:"temp and air and point and effective and zone and cooling and sp", colMeta:{color:"#0547fc"} }, + {target:"zntHtg_sp", query:"temp and air and point and effective and zone and heating and sp", colMeta:{color:"#FF0000"} }, + {target:"znt_sensor", query:"temp and air and point and zone and sensor", colMeta:{color:"#00b843"} }, + {target:"znt_sp", query:"temp and air and point and zone and sp and not heating and not cooling", colMeta:{color:"#71bd8d"} }, + + //pressures + {target:"dsp_sensor", query:"pressure and air and point and discharge and sensor and not filter" ,colMeta:{color:null} }, + {target:"dsp_sp", query:"pressure and air and point and discharge and sp and not filter" ,colMeta:{color:null} }, + {target:"bldg_press_sensor", query:"air and building and point and pressure and sensor" ,colMeta:{color:null} }, + {target:"bldg_press_sp", query:"air and building and point and pressure and sp" ,colMeta:{color:null} }, + //Flow + {target:"daFlow_sensor", query:"flow and air and point and discharge and sensor" ,colMeta:{color:null} }, + {target:"daFlow_sp", query:"flow and air and point and discharge and sp" ,colMeta:{color:null} }, + {target:"eaFlow_sensor", query:"flow and air and point and exhaust and sensor" ,colMeta:{color:null} }, + {target:"eaFlow_sp", query:"flow and air and point and exhaust and sp" ,colMeta:{color:null} }, + {target:"raFlow_sensor", query:"flow and air and point and return and sensor" ,colMeta:{color:null} }, + {target:"raFlow_sp", query:"flow and air and point and return and sp" ,colMeta:{color:null} }, + {target:"znflow_sp", query:"flow and air and point and discharge and sp" ,colMeta:{color:null} }, + {target:"znflow_sensor", query:"flow and air and point and discharge and sensor" ,colMeta:{color:null} }, + {target:"tot_daFlow_sensor", query:"flow and air and point and discharge and sensor and total" ,colMeta:{color:null} }, + {target:"tot_eaFlow_sensor", query:"flow and air and point and exhaust and sensor and total" ,colMeta:{color:null} }, + {target:"znDiffFlow_sensor", query:"flow and air and point and delta and zone" ,colMeta:{color:null} }, + //valves + {target:"htgValve_cmd", query:"point and cmd and valve and water and (reheat or hot)" ,colMeta:{color:null} }, + {target:"clgValve_cmd", query:"point and water and (cool or chilled) and cmd and valve" ,colMeta:{color:null} }, + {target:"phtValve_cmd", query:"point and preheat and cmd and valve" ,colMeta:{color:null} }, + //dampers + {target:"oaDmpr_cmd", query:"damper and air and point and outside and cmd" ,colMeta:{color:null} }, + {target:"maDmpr_cmd", query:"damper and air and point and mixed and cmd" ,colMeta:{color:null} }, + {target:"eaDmpr_cmd", query:"damper and air and point and exhaust and cmd" ,colMeta:{color:null} }, + {target:"raDmpr_cmd", query:"damper and air and point and return and cmd" ,colMeta:{color:null} }, + {target:"rlfDmpr_cmd", query:"damper and air and point and relief and cmd" ,colMeta:{color:null} }, + {target:"dmpr_cmd", query:"damper and air and point and cmd" ,colMeta:{color:null} }, + //fans + {target:"rtnFan_speed", query:"return and point and fan and speed and cmd" ,colMeta:{color:null} }, + {target:"rtnFan_cmd", query:"return and point and fan and run and cmd" ,colMeta:{color:null} }, + {target:"rlfFan_speed", query:"relief and point and fan and speed and cmd" ,colMeta:{color:null} }, + {target:"rlfFan_cmd", query:"relief and point and fan and run and cmd" ,colMeta:{color:null} }, + {target:"exhFan_speed", query:"exhaust and point and fan and speed and cmd" ,colMeta:{color:null} }, + {target:"daFan_speed", query:"discharge and point and fan and speed and cmd" ,colMeta:{color:null} }, + {target:"daFan_run", query:"discharge and point and fan and run and cmd" ,colMeta:{color:null} }, + + //humidity + {target:"daHumid_sensor", query:"point and sensor and discharge and air and humidity" ,colMeta:{color:null} }, + {target:"humidifier_cmd", query:"point and air and cmd and humidifier and not output" ,colMeta:{color:null} }, + //lab + {target:"savFlow_sensor", query:"(discharge or supply) and point and flow and sensor"}, + //other + {target:"occ_cmd", query:"occupied and point and cmd"}, + {target:"znOcc_cmd", query:"occupied and point and cmd"}, + {target:"labOcc_cmd", query:"occupied and point and cmd and lab"}, + {target:"fumeHoodOcc_cmd", query:"occupied and point and cmd and fumeHood"}, + {target:"siteOcc_cmd", query:"occupied and sitePoint"}, + {target:"ahu_state", query:"point and (ahu or ahuState)"}, + //dual duct + {target:"hotDeck_daFlow_sensor", query:"hotDeck and flow and air and point and discharge and sensor"}, + {target:"hotDeck_daFlow_sp", query:"hotDeck and flow and air and point and discharge and sp"}, + {target:"hotDeck_dmpr_cmd", query:"hotDeck and damper and air and point and cmd"}, + {target:"hotDeck_dmpr_reset", query:"hotDeck and damper and air and point and cmd and reset"}, + + {target:"coldDeck_daFlow_sensor", query:"coldDeck and flow and air and point and discharge and sensor"}, + {target:"coldDeck_daFlow_sp", query:"coldDeck and flow and air and point and discharge and sp"}, + {target:"coldDeck_dmpr_cmd", query:"coldDeck and damper and air and point and cmd"}, + {target:"coldDeck_dmpr_reset", query:"coldDeck and damper and air and point and cmd and reset"}, + + //buildingHealth + {target:"site_eui", query:"point and eui and equipRef->buildingHealth"}, + {target:"other_eui", query:"point and other and equipRef->buildingHealth"}, + {target:"chw_eui", query:"point and chilledWater and euiContributor and equipRef->buildingHealth"}, + {target:"elec_eui", query:"point and elec and euiContributor and equipRef->buildingHealth"}, + {target:"hw_eui", query:"point and hotWater and euiContributor and equipRef->buildingHealth"}, + {target:"naturalGas_eui", query:"point and naturalGas and euiContributor and equipRef->buildingHealth"}, + {target:"natGas_eui", query:"point and naturalGas and euiContributor and equipRef->buildingHealth"}, + {target:"site_eci", query:"point and eci and equipRef->buildingHealth"}, + {target:"site_uncomfortableVAVs", query:"point and vavScorePt and uncomfortable and equipRef->buildingHealth"}, + {target:"site_comfortableVAVs", query:"point and vavScorePt and comfortable and equipRef->buildingHealth"}, + {target:"site_equipLife", query:"point and equipmentLife and equipRef->buildingHealth"}, + {target:"site_buildingComfort", query:"point and buildingScore and comfort and equipRef->buildingHealth"}, + {target:"site_buildingArea", query:"point and buildingArea and equipRef->buildingHealth"}, + //elec meter + {target:"elec_intervalPwr", query:"elec and power and interval and equipRef->siteMeter and not cost and not modelPoint and not syntheticPoint and not savings"}, + {target:"elec_modelPwr", query:"elec and power and calculated and modelHisFunction and modelPoint and interval and equipRef->siteMeter"}, + {target:"elec_monthlyEnergy", query:"elec and energy and monthly and not cost and not rateCost and equipRef->siteMeter and not modelPoint and not savings"}, + {target:"elec_modelEnergy", query:"elec and energy and monthly and equipRef->siteMeter and modelPoint"}, + {target:"elec_monthlyCost", query:"elec and energy and monthly and equipRef->siteMeter and cost"}, + {target:"elec_intervalCost", query:"elec and power and interval and equipRef->siteMeter and cost and not savings"}, + {target:"elec_monthlyRateCost", query:"elec and energy and monthly and equipRef->siteMeter and rateCost"}, + {target:"elec_intervalSavingsCost", query:"elec and power and interval and equipRef->siteMeter and savings and cost"}, + {target:"elec_savingsPwr", query:"elec and power and interval and equipRef->siteMeter and savings and not cost"}, + {target:"elec_monthlySavingsCost", query:"elec and energy and monthly and equipRef->siteMeter and savings and cost"}, + {target:"elec_savingsEnergy", query:"elec and energy and monthly and equipRef->siteMeter and savings and not cost"}, + {target:"elec_genAIModelDemand", query:"elec and power and syntheticPoint and mlPoint and interval and equipRef->siteMeter"}, + //natGas meter + {target:"natGas_intervalCons", query:"naturalGas and consumption and interval and equipRef->siteMeter and not cost and not modelPoint and not syntheticPoint and not savings"}, + {target:"natGas_intervalModelCons", query:"naturalGas and consumption and calculated and modelHisFunction and modelPoint and interval and equipRef->siteMeter"}, + {target:"natGas_monthlyCons", query:"naturalGas and consumption and monthly and not cost and not rateCost and equipRef->siteMeter and not modelPoint and not savings"}, + {target:"natGas_monthlyModelCons", query:"naturalGas and consumption and monthly and equipRef->siteMeter and modelPoint"}, + {target:"natGas_monthlyCost", query:"naturalGas and consumption and monthly and equipRef->siteMeter and cost"}, + {target:"natGas_intervalCost", query:"naturalGas and consumption and interval and equipRef->siteMeter and cost and not savings"}, + {target:"natGas_monthlyRateCost", query:"naturalGas and consumption and monthly and equipRef->siteMeter and rateCost"}, + {target:"natGas_intervalSavingsCost", query:"naturalGas and consumption and interval and equipRef->siteMeter and savings and cost"}, + {target:"natGas_intervalSavingsCons", query:"naturalGas and consumption and interval and equipRef->siteMeter and savings and not cost"}, + {target:"natGas_monthlySavingsCost", query:"naturalGas and consumption and monthly and equipRef->siteMeter and savings and cost"}, + {target:"natGas_monthlySavingsCons", query:"naturalGas and consumption and monthly and equipRef->siteMeter and savings and not cost"}, + {target:"natGas_genAIModelCons", query:"naturalGas and consumption and interval and syntheticPoint and mlPoint and equipRef->siteMeter"}, + //hot water meter + {target:"hotWater_intervalCons", query:"hot and water and interval and equipRef->siteMeter and not cost and not modelPoint and not syntheticPoint and not savings"}, + {target:"hotWater_intervalModelCons", query:"hot and water and calculated and modelHisFunction and modelPoint and interval and equipRef->siteMeter"}, + {target:"hotWater_monthlyCons", query:"hot and water and monthly and not cost and not rateCost and equipRef->siteMeter and not modelPoint and not savings"}, + {target:"hotWater_monthlyModelCons", query:"hot and water and monthly and equipRef->siteMeter and modelPoint"}, + {target:"hotWater_monthlyCost", query:"hot and water and monthly and equipRef->siteMeter and cost"}, + {target:"hotWater_intervalCost", query:"hot and water and interval and equipRef->siteMeter and not savings and cost"}, + {target:"hotWater_monthlyRateCost", query:"hot and water and monthly and equipRef->siteMeter and rateCost"}, + {target:"hotWater_intervalSavingsCost", query:"hot and water and interval and equipRef->siteMeter and savings and cost"}, + {target:"hotWater_intervalSavingsCons", query:"hot and water and interval and equipRef->siteMeter and savings and not cost"}, + {target:"hotWater_monthlySavingsCost", query:"hot and water and monthly and equipRef->siteMeter and savings and cost"}, + {target:"hotWater_monthlySavingsCons", query:"hot and water and monthly and equipRef->siteMeter and savings and not cost"}, + {target:"hotWater_genAIModelCons", query:"hot and water and interval and syntheticPoint and mlPoint and equipRef->siteMeter"}, + //chilled water meter + {target:"chilledWater_intervalCons", query:"chilled and water and interval and equipRef->siteMeter and not cost and not modelPoint and not syntheticPoint and not savings"}, + {target:"chilledWater_intervalModelCons", query:"chilled and water and calculated and modelHisFunction and modelPoint and interval and equipRef->siteMeter"}, + {target:"chilledWater_monthlyCons", query:"chilled and water and monthly and not cost and not rateCost and equipRef->siteMeter and not modelPoint and not savings"}, + {target:"chilledWater_monthlyModelCons", query:"chilled and water and monthly and equipRef->siteMeter and modelPoint"}, + {target:"chilledWater_monthlyCost", query:"chilled and water and monthly and equipRef->siteMeter and cost"}, + {target:"chilledWater_intervalCost", query:"chilled and water and interval and equipRef->siteMeter and cost and not savings"}, + {target:"chilledWater_monthlyRateCost", query:"chilled and water and monthly and equipRef->siteMeter and rateCost"}, + {target:"chilledWater_intervalSavingsCost", query:"chilled and water and interval and equipRef->siteMeter and savings and cost"}, + {target:"chilledWater_intervalSavingsCons", query:"chilled and water and interval and equipRef->siteMeter and savings and not cost"}, + {target:"chilledWater_monthlySavingsCost", query:"chilled and water and monthly and equipRef->siteMeter and savings and cost"}, + {target:"chilledWater_monthlySavingsCons", query:"chilled and water and monthly and equipRef->siteMeter and savings and not cost"}, + {target:"chilledWater_genAIModelCons", query:"chilled and water and interval and syntheticPoint and mlPoint and equipRef->siteMeter"}, + //steam meter + {target:"steam_intervalCons", query:"steam and interval and equipRef->siteMeter and not cost and not modelPoint and not syntheticPoint and not savings"}, + {target:"steam_intervalModelCons", query:"steam and calculated and modelHisFunction and modelPoint and interval and equipRef->siteMeter"}, + {target:"steam_monthlyCons", query:"steam and monthly and not cost and not rateCost and equipRef->siteMeter and not modelPoint and not savings"}, + {target:"steam_monthlyModelCons", query:"steam and monthly and equipRef->siteMeter and modelPoint"}, + {target:"steam_monthlyCost", query:"steam and monthly and equipRef->siteMeter and cost"}, + {target:"steam_intervalCost", query:"steam and interval and equipRef->siteMeter and cost and not savings"}, + {target:"steam_monthlyRateCost", query:"steam and monthly and equipRef->siteMeter and rateCost"}, + {target:"steam_intervalSavingsCost", query:"steam and interval and equipRef->siteMeter and savings and cost"}, + {target:"steam_intervalSavingsCons", query:"steam and interval and equipRef->siteMeter and savings and not cost"}, + {target:"steam_monthlySavingsCost", query:"steam and monthly and equipRef->siteMeter and savings and cost"}, + {target:"steam_monthlySavingsCons", query:"steam and monthly and equipRef->siteMeter and savings and not cost"}, + {target:"steam_genAIModelCons", query:"steam and interval and syntheticPoint and mlPoint and equipRef->siteMeter"}, + //water meter + {target:"water_intervalCons", query:"water and not chilled and not hot and consumption and interval and equipRef->siteMeter and not cost and not modelPoint and not savings"}, + + //hot water + {target:"hw_delta_press", query:"hot and water and pressure and delta and sensor"}, + {target:"hw_flow", query:"hot and water and flow and sensor"}, + {target:"hw_pri_pump_speed", query:"hot and water and pump and speed and cmd and primary"}, + {target:"hw_pri_pump_status", query:"hot and water and pump and run and cmd and primary"}, + {target:"hw_sec_pump_speed", query:"hot and water and pump and speed and cmd and secondary"}, + {target:"hw_sec_pump_status", query:"hot and water and pump and run and cmd and secondary"}, + {target:"hw_pri_pump_power", query:"hot and water and pump and power and sensor and primary"}, + {target:"hw_sec_pump_power", query:"hot and water and pump and power and sensor and secondary"}, + {target:"hw_supply_temp", query:"hot and water and supply and temp and sensor"}, + {target:"hw_return_temp", query:"hot and water and return and temp and sensor and not domestic"}, + {target:"hw_supply_temp_sp", query:"hot and water and supply and temp and sp"}, + {target:"hw_delta_press_sp", query:"hot and water and pressure and delta and sp"}, + {target:"hw_delta_temp", query:"hot and water and temp and delta and sensor"}, + {target:"hw_sys_load", query:"hot and water and load and energy"}, + {target:"hw_bypass_valve", query:"hot and water and bypass and valve and cmd"}, + + //chilled water + {target:"chw_delta_press", query:"chilled and water and pressure and delta and sensor"}, + {target:"chw_flow", query:"chilled and water and flow and sensor and not bypass"}, + {target:"chw_pri_pump_speed", query:"chilled and water and pump and speed and cmd and primary"}, + {target:"chw_sec_pump_speed", query:"chilled and water and pump and speed and cmd and secondary"}, + {target:"chw_pri_pump_status", query:"chilled and water and pump and run and cmd and primary"}, + {target:"chw_sec_pump_status", query:"chilled and water and pump and run and cmd and secondary"}, + {target:"chw_pri_pump_power", query:"chilled and water and pump and power and sensor and primary"}, + {target:"chw_sec_pump_power", query:"chilled and water and pump and power and sensor and secondary"}, + //{target:"chw_pri_pump_status", query:"chilled and water and pump and run and cmd and primary"}, + //{target:"chw_sec_pump_status", query:"chilled and water and pump and run and cmd and secondary"}, + {target:"chw_supply_temp", query:"chilled and water and supply and temp and sensor"}, + {target:"chw_return_temp", query:"chilled and water and return and temp and sensor"}, + {target:"chw_supply_temp_sp", query:"chilled and water and supply and temp and sp"}, + {target:"chw_delta_press_sp", query:"chilled and water and pressure and delta and sp"}, + {target:"chw_delta_temp", query:"chilled and water and temp and delta and sensor"}, + {target:"chw_sys_load", query:"chilled and water and load and energy"}, + + //General Pump Points + {target:"pri_pump_speed", query:"water and pump and speed and cmd and primary"}, + {target:"sec_pump_speed", query:"water and pump and speed and cmd and secondary"}, + {target:"pri_pump_status", query:"water and pump and run and cmd and primary"}, + {target:"sec_pump_status", query:"water and pump and run and cmd and secondary"}, + {target:"pri_pump_power", query:"water and pump and power and sensor and primary"}, + {target:"sec_pump_power", query:"water and pump and power and sensor and secondary"}, + + //chillers + {target:"chlr_status", query:"chiller and cmd and run"}, + {target:"chlr_power", query:"chiller and power and sensor"}, + {target:"chlr_entering_temp", query:"chiller and chilled and entering and temp and water and sensor and not condenser"}, + {target:"chlr_leaving_temp", query:"chiller and chilled and leaving and temp and water and sensor and not condenser"}, + {target:"chlr_flow", query:"chiller and chilled and flow and water and sensor"}, + {target:"chlr_fla", query:"chiller and fla and sensor"}, + {target:"chlr_cw_entering_temp", query:"chiller and condenser and entering and temp and water and sensor"}, + {target:"chlr_cw_leaving_temp", query:"chiller and condenser and leaving and temp and water and sensor"}, + + //boilers + {target:"blr_firing_rate", query:"boiler and firingRate and sensor"}, + {target:"blr_entering_temp", query:"boiler and hot and (entering or return) and temp and water and sensor"}, + {target:"blr_leaving_temp", query:"boiler and hot and leaving and temp and water and sensor"}, + {target:"blr_leaving_temp_sp", query:"boiler and hot and leaving and temp and water and sp"}, + {target:"blr_run_status", query:"boiler and run and cmd"}, + {target:"blr_enable", query:"boiler and cmd and enable"}, + {target:"blr_gas_flow_rate", query:"boiler and flow and rate and sensor and naturalGas"}, + {target:"blr_flow", query:"boiler and notImplemented"}, + {target:"blr_power", query:"boiler and power and sensor"}, + + + //cooling tower + {target:"clgtwr_leaving_temp", query:"coolingTower and temp and (leaving or supply) and water and sensor"}, + {target:"clgtwr_entering_temp", query:"coolingTower and temp and (entering or return) and water and sensor"}, + {target:"clgtwr_fan_speed", query:"coolingTower and fan and speed and air and cmd"}, + {target:"clgtwr_power", query:"coolingTower and power and sensor"}, + {target:"clgtwr_fan_status", query:"coolingTower and cmd and run"}, + + + //condenser water + {target:"cws_supply_temp", query:"condenser and water and supply and temp and sensor"}, + {target:"cws_supply_temp_sp", query:"condenser and water and supply and temp and sp"}, + {target:"cws_return_temp", query:"condenser and water and return and temp and sensor"}, + + //miscellaneous + {target:"wet_bulb", query:"temp and wetBulb"}, + {target:"oah_sensor", query:"humidity and air and point and outside and sensor"}, + + // Heat Recovery Coil + // Discharge + {target:"disHRC_ea_sensor", query:"heatRecovery and coil and air and temp and sensor and discharge and entering"}, + {target:"disHRC_la_sensor", query:"heatRecovery and coil and air and temp and sensor and discharge and leaving"}, + {target:"disHRC_flow_sensor", query:"heatRecovery and coil and air and flow and sensor and discharge"}, + {target:"disHRC_valve_cmd", query:"heatRecovery and coil and water and valve and cmd and discharge"}, + // Exhaust + {target:"exHRC_ea_sensor", query:"heatRecovery and coil and air and temp and sensor and exhaust and entering"}, + {target:"exHRC_la_sensor", query:"heatRecovery and coil and air and temp and sensor and exhaust and leaving"}, + {target:"exHRC_flow_sensor", query:"heatRecovery and coil and air and flow and sensor and exhaust"}, + {target:"exHRC_valve_cmd", query:"heatRecovery and coil and water and valve and cmd and exhaust"}, + + // Heat Recovery Wheel + {target:"disHRW_ea_sensor", query:"heatRecovery and wheel and air and temp and sensor and discharge and entering"}, + {target:"disHRW_la_sensor", query:"heatRecovery and wheel and air and temp and sensor and discharge and leaving"}, + {target:"disHRW_flow_sensor", query:"heatRecovery and wheel and air and flow and sensor and discharge"}, + + {target:"exHRW_ea_sensor", query:"heatRecovery and wheel and air and temp and sensor and exhaust and entering"}, + {target:"exHRW_la_sensor", query:"heatRecovery and wheel and air and temp and sensor and exhaust and leaving"}, + {target:"exHRW_flow_sensor", query:"heatRecovery and wheel and air and flow and sensor and exhaust"}, + + {target:"hrw_status", query:"heatRecovery and wheel and sensor and run"}, + {target:"hrw_cmd", query:"heatRecovery and wheel and cmd"}, + + // Lab Spaces + {target:"ach", query:"ach and air and sensor"}, + {target:"sash_cmd", query:"sash and cmd and fumeHood"}, + + //Coil Temps + //hot + {target:"chw_entg_temp", query:"chilled and water and valve"}, + {target:"chw_lvg_temp", query:"humidity and air and point and outside and sensor"}, + + //chilled + {target:"hw_entg_temp", query:"temp and wetBulb"}, + {target:"hw_lvg_temp", query:"humidity and air and point and outside and sensor"}, + + //Baseline Search + {target:"baseline_calc", query:"point and calculated and modelPoint and not cost and not savings"}, + + //Utility Level Points for Dashboards + //Elec + {target:"portfolioDashboard_elecUsage", query:"portfolioDashboardPoint and elec and not cost and not savings"}, + {target:"portfolioDashboard_elecCost", query:"portfolioDashboardPoint and elec and cost and not savings"}, + {target:"portfolioDashboard_elecSavingsCost", query:"portfolioDashboardPoint and elec and cost and savings"}, + {target:"portfolioDashboard_elecSavings", query:"portfolioDashboardPoint and elec and usage and savings and not cost"}, + + //Steam + {target:"portfolioDashboard_steamUsage", query:"portfolioDashboardPoint and steam and not cost and not savings"}, + {target:"portfolioDashboard_steamCost", query:"portfolioDashboardPoint and steam and cost and not savings"}, + {target:"portfolioDashboard_steamSavingsCost", query:"portfolioDashboardPoint and steam and cost and savings"}, + {target:"portfolioDashboard_steamSavings", query:"portfolioDashboardPoint and steam and usage and savings and not cost"}, + + //Chilled Water + {target:"portfolioDashboard_chwUsage", query:"portfolioDashboardPoint and chw and not cost and not savings"}, + {target:"portfolioDashboard_chwCost", query:"portfolioDashboardPoint and chw and cost and not savings"}, + {target:"portfolioDashboard_chwSavingsCost", query:"portfolioDashboardPoint and chw and cost and savings"}, + {target:"portfolioDashboard_chwSavings", query:"portfolioDashboardPoint and chw and usage and savings and not cost"}, + + //Hot Water + {target:"portfolioDashboard_hwUsage", query:"portfolioDashboardPoint and hw and not cost and not savings"}, + {target:"portfolioDashboard_hwCost", query:"portfolioDashboardPoint and hw and cost and not savings"}, + {target:"portfolioDashboard_hwSavingsCost", query:"portfolioDashboardPoint and hw and cost and savings"}, + {target:"portfolioDashboard_hwSavings", query:"portfolioDashboardPoint and hw and usage and savings and not cost"}, + ].toGrid + + + if(show) return queries + + match: queries.find(r => r.get("target")==target) + if (match.isNull) throw "Cannot find query: "+target + + out: if (colMeta) match.get("colMeta") + else match.get("query") + + return out end
stackedAreaChart
--- stackedAreaChart (pod) +++ stackedAreaChart (local) @@ -1,18 +1,57 @@ -(data, opts: {}) => do - cipherText : - "AxD:38dDwRQ-pgdqgJiurXebHQ::mhXfpADGbIC7GxoTqRSqdV464RPnMp4CLuc657aoHaKd9_HM1D4a" + - "HIskOslaBmvn9jSqOhTYxcOCs_3woqg599Elx2Fcyc1JBY-NqdgSwE8XsMz7_c1Wz8fyLkddRGT1pzE_" + - "kw5hFRL3Sr_Q8-KUBzP8fTjHvzOitZVKQDCcmThHuvxjhdgAtGmeIwmHXrzAEOxrOicz38xgiAcerjFi" + - "CpxfehBlJt-8borMQX1bT-eBm-mTZqCbijfc1guvAfAQscQLYCYuTD5cpMps-6wkk2689l5Z7eTAehHB" + - "v6mxCJS_95jACQ_Kez_os1YNCoNMO45G-fkjaKq-Jhu8BfrxOMxAm4GKBGVQUE-hmd9ktMBgmzjx_k_R" + - "csMl5bYyW8CsJ38vK4TOIit_9K8vKk4BK2aWwqOeca1VB16VFgt3_K53nqDujbk6zLct1BSPZVrUL9_B" + - "RTqmKKAIiHUR57r7R84k1J5C57XfI_Bk-3EcqyUVrrfHZPdxiYUMEsMXgiODwQ8HMdO4pz7lO9Vjuti8" + - "nqXRwMZm3o3x7DKDAQdRHSaawNBUrJnBpM2VKmA-ZcEud5xZZQl177mVpVtxMFRxllIJxBRJ864BVXxD" + - "rzwWf-UyEcxauEhCcTZYqJSgIWzuTydLATJlBjQLceRRGcNo0TKcxwbZ-4H1bOa5pK-bmQKz7AI7FBNB" + - "5IcHwyPZXydqmnIQ44Y93vyeA1GzOyyVL_IvI2_16095Rklz96bRvj654lLJaKwTCcKpcZX7hMwovOTj" + - "J_utAqV0DN2mr2U-t1ImzPNCNF2umqB799KwX1AZkHikHM-9HVfliUKCndI51prCfo2Axd7aERcdkOxv" + - "Xz5g3wgMzTBskd5UdgYG9YQ4kMEQauanpxvKe_ySHg7vy3_zWq1TXZJSjRKt4lKUJRSfbwuB909fW26j" + - "-j9CRykqL9T-ArZqZ02B455KDjUyAkFw8XtYRxjLHkYyNII5c7EmNvL6Kl8_trUYcbiA8iA" - keyFunc : () => "ddJNIRm2qio2Z7CXpKADiw" - return afAxonEncryptorRt_callFunc("stackedAreaChart", cipherText, [data, opts], keyFunc) +(data, opts:{}) => do + + //STACK FUNCTION + stack: (data) => do + // map column names to their index + colNames: data.colNames + colNameToIndex: {} + colNames[1..-1].each((n,i) => do + colNameToIndex = colNameToIndex.set(n, i+1) + end) + + // map the data cells to the sum of values to the left + stream: data.stream.map(r => do + r.map((v, n) => do + if (n == "ts" or n=="time") return v + sum: 0 + index: colNameToIndex[n] + (1..index).each(i => sum = sum + r[colNames[i]]) + return sum + end) + end) + + // add area mode tag to value columes + colNames[1..-1].each((c,i) => do + mode: if (i == 0) "zero" else "prevSeries" + clmMeta: if (opts.has("removeColor")) {chartAreaMode:mode, -color} + else {chartAreaMode:mode} + stream = stream.addColMeta(c,clmMeta) + end) + + // ensure column order of input data + return stream.addMeta({chartLegendNoSort}).reorderCols(colNames).collect(toGrid) + end + + //check incoming grid for empty columns + //filter empty colms + if (data.cols.any(colm => data.colToList(colm).all(v=>v==null))) do + nonEmptyCols: data.cols.findAll(colm => not data.colToList(colm).all(v=>v==null)) + data = data.keepCols(nonEmptyCols) + end + + //check how many unique units + units: data.cols.map(r => r.meta.get("unit")).findAll(v=>v!=null).unique + unitCount: units.size + + if (unitCount<2) return data.stack() + else do + out: [] + units.each u => do + unitCols: data.cols.findAll(c=>c.meta.get("unit")==u) + unitData: data.keepCols(["ts"].addAll(unitCols)) + out=out.add(unitData.stack()) + end + return out.hisJoin + end + end
setIgnoredTags
--- setIgnoredTags (pod) +++ setIgnoredTags (local) @@ -1,10 +1,3 @@ () => do - cipherText : - """AxD:Yxba0aIY9Y5BKvFonyFhAQ::BtgrCvguDM6BZW0ICtmF0cD4evFw471bebhtHhIy1K8RTeLq6tL0 - SJr_hQfimBgLDmfLzNoOdBZ2-SVOsFjM9oz5iYgXoxAPfxoLWDlTRgS-bigO-p1P0hSeVxJ1yEoyVvx3 - NnLH1R6QO4AtEgHgk6T6GGRbTwPwBPoAcOJ233Fdj_wKuiOFsuCLCG5YJ_e6A6uAhre_POD25IjZpNej - 3WMNzKuTOr6oamZQs4aS4yqXPS7bddsCzncgbn0YJaOR6mIBLdT8PbY1BnSoV0LIjwa8IVemqeVLF89v - bkfHFw0h9HD-j3lOxjpE_0voXJzI""" - keyFunc : () => "uF_n7EQ34krJ1dsJbt7y5w" - return afAxonEncryptorRt_callFunc("setIgnoredTags", cipherText, [], keyFunc) + ["clarificationNeeded","manualReview","clarificationComment","clarificationComment_kw","notDuplicate","g36DashReady","emcsPoint"] end
construct_ts
Sources are identical.
kpi_siteMeter_actualElecKwh
--- kpi_siteMeter_actualElecKwh (pod) +++ kpi_siteMeter_actualElecKwh (local) @@ -10,7 +10,7 @@ target: {} date: {} out: {readonly} - elec_intervalPwr: {bind:"elec and power and interval and equipRef->siteMeter and not cost and not modelPoint and not savings and equipRef=={{target->id}}"} + elec_intervalPwr: {bind:"elec and power and interval and equipRef->siteMeter and not cost and not modelPoint and not syntheticPoint and not savings and equipRef=={{target->id}}"} opts: {bindTuning:"opts", defVal:{}} do
kpi_siteMeter_actualSteamKlbs
--- kpi_siteMeter_actualSteamKlbs (pod) +++ kpi_siteMeter_actualSteamKlbs (local) @@ -10,7 +10,7 @@ target: {} date: {} out: {readonly} - steam_intervalCons: {bind:"steam and interval and equipRef->siteMeter and not cost and not modelPoint and not savings and equipRef=={{target->id}}"} + steam_intervalCons: {bind:"steam and interval and equipRef->siteMeter and not cost and not modelPoint and not syntheticPoint and not savings and equipRef=={{target->id}}"} opts: {bindTuning:"opts", defVal:{}} do
kpi_siteMeter_actualchwTonHrs
--- kpi_siteMeter_actualchwTonHrs (pod) +++ kpi_siteMeter_actualchwTonHrs (local) @@ -10,7 +10,7 @@ target: {} date: {} out: {readonly} - chilledWater_intervalCons: {bind:"chilled and water and interval and equipRef->siteMeter and not cost and not modelPoint and not savings and equipRef=={{target->id}}"} + chilledWater_intervalCons: {bind:"chilled and water and interval and equipRef->siteMeter and not cost and not modelPoint and not syntheticPoint and not savings and equipRef=={{target->id}}"} opts: {bindTuning:"opts", defVal:{}} do
kpi_siteMeter_maxChwsDemand
--- kpi_siteMeter_maxChwsDemand (pod) +++ kpi_siteMeter_maxChwsDemand (local) @@ -10,7 +10,7 @@ target: {} date: {} out: {readonly} - chilledWater_intervalCons: {bind:"chilled and water and interval and equipRef->siteMeter and not cost and not modelPoint and not savings and equipRef=={{target->id}}"} + chilledWater_intervalCons: {bind:"chilled and water and interval and equipRef->siteMeter and not cost and not modelPoint and not syntheticPoint and not savings and equipRef=={{target->id}}"} opts: {bindTuning:"opts", defVal:{}} do
kpi_siteMeter_maxElecDemand
--- kpi_siteMeter_maxElecDemand (pod) +++ kpi_siteMeter_maxElecDemand (local) @@ -10,7 +10,7 @@ target: {} date: {} out: {readonly} - elec_intervalPwr: {bind:"elec and power and interval and equipRef->siteMeter and not cost and not modelPoint and not savings and equipRef=={{target->id}}"} + elec_intervalPwr: {bind:"elec and power and interval and equipRef->siteMeter and not cost and not modelPoint and not syntheticPoint and not savings and equipRef=={{target->id}}"} opts: {bindTuning:"opts", defVal:{}} do
kpi_siteMeter_maxSteamDemand
--- kpi_siteMeter_maxSteamDemand (pod) +++ kpi_siteMeter_maxSteamDemand (local) @@ -10,7 +10,7 @@ target: {} date: {} out: {readonly} - steam_intervalCons: {bind:"steam and interval and equipRef->siteMeter and not cost and not modelPoint and not savings and equipRef=={{target->id}}"} + steam_intervalCons: {bind:"steam and interval and equipRef->siteMeter and not cost and not modelPoint and not syntheticPoint and not savings and equipRef=={{target->id}}"} opts: {bindTuning:"opts", defVal:{}} do
logic_anomaly_anomalyImpact
--- logic_anomaly_anomalyImpact (pod) +++ logic_anomaly_anomalyImpact (local) @@ -28,4 +28,63 @@ // end // // Double checking logic // return {totalUsage:totalUsage, totalKWH:totalKWH} -// +// ------------------------------------------------------------------------ +// // Case 2: For a random gas meter (fails and throws err) +// logic_elecMeter_usage(@p:kwLink_energyAgent:r:2ee9da19-8d561eae, 2023) +// ------------------------------------------------------------------------ + +(meter, dates, opts:{}, pointOverrides:{}) => do + + ////////////////////////////////////////////////////////////////////////////////////////// + // NORMALIZE + VALIDATE INPUTS + ////////////////////////////////////////////////////////////////////////////////////////// + + if (meter.isNull) return "meter point missing" + meterRec: meter.toRec + meterId: meterRec.get("id") + dates = dates.toSpan + + ////////////////////////////////////////////////////////////////////////////////////////// + // OPTS + ////////////////////////////////////////////////////////////////////////////////////////// + + debug: opts.optNorm("debug", "Disable").lower // Available options: "all anomalies", "filtered anomalies", "filtered anomaly count" + + ////////////////////////////////////////////////////////////////////////////////////////// + // LOGIC + ////////////////////////////////////////////////////////////////////////////////////////// + + // Points + allAnomalies: readAll(anomaly and targetVarRef==meterId) + if (debug=="all anomalies") return allAnomalies + + // Only keep the anomalies within the selected span + filteredAnomalies: allAnomalies.findAll(v=> v.get("ts") >= dates.start and v.get("ts") < dates.end ) // Robust: check if ts + duration is outside dates.end? Would we still count it as an anomaly for this span? + if (debug=="filtered anomalies") return filteredAnomalies + if (debug=="filtered anomaly count") return filteredAnomalies.size + + // Calculate total anomaly impact over the selected span + totalAnomalyImpact: 0 + + filteredAnomalies.each() r=> do + anomalyImpact: r.get("anomalyImpactLikely") + totalAnomalyImpact = if (anomalyImpact >= 0) totalAnomalyImpact + anomalyImpact else if (anomalyImpact < 0) totalAnomalyImpact // workaround for now. TODO: Update the anomaly detection funcs to include +ve only anomalies. + end + + + if (debug=="enable") return {errList: ["TODO: Add potential errors above in try catch statements and list them out here"], powerGrid:powerGrid, usageGrid:usageGrid, totalUsage:totalUsage} + + // TODO: Add potential errors above in try catch statements + + ////////////////////////////////////////////////////////////////////////////////////////// + // FORMAT + ////////////////////////////////////////////////////////////////////////////////////////// + + + ////////////////////////////////////////////////////////////////////////////////////////// + //RETURN RESULT + ////////////////////////////////////////////////////////////////////////////////////////// + + return totalAnomalyImpact + +end
logic_energyAgent_meterPointToPredictionsChart
--- logic_energyAgent_meterPointToPredictionsChart (pod) +++ logic_energyAgent_meterPointToPredictionsChart (local) @@ -49,14 +49,8 @@ ////////////////////////////////////////////////////////////////////////////////////////// meterHisGrid: meterPointRef.hisRead(dates) - modelPoint: try read(syntheticPoint and pointRef==meterPointRef).toRec catch null - //akTODO: Just return Meter history if model point missing - if (modelPoint.isNull) do - //out: meterPointRef.hisRead(dates) - gridMeta: {title: "Meter history for "+meterPointRec.get("navName"), - subtitle: "(Run model to show predictions)"} - return meterHisGrid.addColMeta("v0", {dis:"Meter readings", strokeWidth:1, chartGroup: "modelFit", chartType:"line"}).addMeta(gridMeta)// - end + modelPoint: try read(syntheticPoint and pointRef==meterPointRef, false).toRec catch null + if (modelPoint.isNull) return {info: modelPoint}.toGrid.addMeta({noData: "Model point missing for the selected utility."}).addColMeta("info", {dis: "Information"}) modelPointRef: modelPoint.get("id") // Retrieve the detailed model results @@ -72,6 +66,7 @@ end modelPredictionsGrid = modelPredictionsGrid.removeCol("v0").reorderKeepCols(["ts"]).filter((ts>dates.start) and (ts<dates.end)).addMeta({hisStart: dates.start, hisEnd: dates.end}) + modelPredictionsGrid = hisJoin([modelPredictionsGrid, meterHisGrid]).reorderKeepCols(["ts", "v0"]) // akTODO: add spanStart to modelPointStart meter his
logic_kwModeling_anomalyDetection_simPreview_v2
--- logic_kwModeling_anomalyDetection_simPreview_v2 (pod) +++ logic_kwModeling_anomalyDetection_simPreview_v2 (local) @@ -88,4 +88,63 @@ // ReadHis for meter and model points data : points.hisRead(dateSpan, {-limit}) - .hisRollup(avg, 1h) // + .hisRollup(avg, 1h) // ------- Double check logic robustness for all units. Should we use hisRollupAuto (1h) instead? Can it handle 15 minute kW/kWh data both? + .hisClip +//return data +//////// Add checks: hisStart and hisEnd for both points against the extended span + + requiredCols: ["ts", "v0", "v1"] + if (requiredCols.any(v => data.missing(v) == true)) return [].toGrid.addMeta({noData: "Missing Data Error. Missing required column(s): " + requiredCols.findAll(v=>his.missing(v) == true)}) + // hisRead create a grid that has v1 col even if the col doesn't have any data. So the above condition doesn't fail. + + if (not (data.col("v0").meta.has("hisStart") or data.col("v0").meta.has("hisEnd"))) return blankChart("Meter Point missing hisStart or hisEnd tags. Might be missing his data for the selected span.") + if (not (data.col("v1").meta.has("hisStart") or data.col("v1").meta.has("hisEnd"))) return blankChart("Model Point missing hisStart or hisEnd tags. Might be missing his data for the selected span.") + + if (data.col("v0").meta.get("hisStart") > dateSpan.start) return "Meter Point his data start date (" + data.col("v0").meta.get("hisStart").date.toStr + ") is later than selected span start date. Select a span that begins a week after this date." + if (data.col("v1").meta.get("hisStart") > dateSpan.start) return "Model Point his data start date (" + data.col("v1").meta.get("hisStart").date.toStr + ") is later than selected span start date. Select a span that begins a week after this date." + + if (data.col("v0").meta.get("hisEnd") < dateSpan.end) return "Meter Point his data end date (" + data.col("v0").meta.get("hisEnd").date.toStr + ") is before the selected span end date. Select a span that ends before this date." + if (data.col("v1").meta.get("hisEnd") < dateSpan.end) return "Model Point his data end date (" + data.col("v1").meta.get("hisEnd").date.toStr + ") is before the selected span end date. Select a span that ends before this date." + + +//////// Get confidence interval data + + // Get confidence intervals for the model point + confIntervals: logic_kwModeling_getModelPointResults(modelPoint).reorderKeepCols(["ts"]) + if (confIntervals.isStr) return confIntervals + if (confIntervals.first.get("ts") > dateSpan.start) return "The results file his data start date (" + confIntervals.first.get("ts").date.toStr + ") is later than selected span start date. Select a span that begins a week after this date." + + // Filter for extendedDateSpan and update meta based on extendedSpan (needed for processing results) + filteredConfIntervals: confIntervals.findAll() r=> (r.get("ts") >= dateSpan.start and r.get("ts") < dateSpan.end) + filteredConfIntervals= filteredConfIntervals.addMeta({hisStart:dateSpan.start, hisEnd: dateSpan.end}) +//return confIntervals + + // hisJoin meter data, predictions and confidence intervals + out : hisJoin([data, filteredConfIntervals]).reorderKeepCols(["ts", "v0", "v1"]) +//return out +//////// Find and flag different types of anomalies + + // Process hisGrid to find anomalous periods and their durations Send to + out = out.logic_kwModeling_anomalyDetection_processSimResults_v2(sensitivity, opts) + if (out.isStr) return out + + // Filter for selected dateSpan + out = out.findAll() r=> (r.get("ts") >= dateSpan.start and r.get("ts") < dateSpan.end) + + + + ////////////////////////////////////////////////////////////////////////////////////////// + // FORMAT + ////////////////////////////////////////////////////////////////////////////////////////// + + // Update meta based on actual selected Span + out = out.addMeta({hisStart:dateSpan.start, hisEnd: dateSpan.end}) + + + ////////////////////////////////////////////////////////////////////////////////////////// + //RETURN RESULT + ////////////////////////////////////////////////////////////////////////////////////////// + + return out + +end
logic_meter_dataStagnant
Sources are identical.
spark_chilledWaterMeter_dataGaps
Sources are identical.
spark_chilledWaterMeter_dataStagnant
Sources are identical.
spark_elecMeter_dataGaps
Sources are identical.
spark_elecMeter_dataStagnant
Sources are identical.
spark_gasMeter_dataGaps
Sources are identical.
spark_hotWaterMeter_dataGaps
Sources are identical.
spark_hotWaterMeter_dataStagnant
Sources are identical.
spark_steamMeter_dataGaps
Sources are identical.
spark_steamMeter_dataStagnant
Sources are identical.
task_energyAgent_anomalyArcOrchestrator
--- task_energyAgent_anomalyArcOrchestrator (pod) +++ task_energyAgent_anomalyArcOrchestrator (local) @@ -1,10 +1,10 @@ (opts: {syncDuration: 1wk, testMode:false}) => do // Sync all model points - callTask("task_energyAgent_syncGenAIModels", [], true) + //callTask("task_energyAgent_syncGenAIModels", [], true) // Delete old anomaly recs - readAll(anomaly).colToList("id").recDelete + try readAll(anomaly or anomalyTrigger).colToList("id").recDelete catch null // Find triggers and anomalies callTask("task_energyAgent_syncDataAndFindAnomalyTriggers", [opts], true)
task_energyAgent_syncDataAndFindAnomalyTriggers
--- task_energyAgent_syncDataAndFindAnomalyTriggers (pod) +++ task_energyAgent_syncDataAndFindAnomalyTriggers (local) @@ -2,7 +2,7 @@ syncDuration: opts.optNorm("syncDuration", 1wk) - modelPoints: readAll(syntheticPoint and modelType=="adaptiveBaseline" and hisSize) + modelPoints: readAll(syntheticPoint and modelType=="adaptiveBaseline" and hisSize).toRecList modelPoints.each() mp => do //Get Meter Point @@ -11,31 +11,29 @@ meterHisEnd : meterPoint.get("hisEnd") logInfo("energyAgentTask", "EnergyAgent Evaluating model for "+meterPoint.dis) - // TODO?: Add check for modelPoint hisEnd, compare to old/new hisEnds. Include the following code chunk in a conditional as well? - // modelPoint => virtualSyncHis - modelPointRef: mp.get("id") - modelEndDate: mp.get("hisEnd") + modelPointRef : mp.get("id") + modelHisEnd : mp.get("hisEnd") + siteTz: meterPoint.get("siteRef").toRec.get("tz") + // Overwritten date on Cornell. Might just default to past month for the pod + anomalyFindingStartDate: parseDateTime("2025-08-01 00:00:00", "YYYY-MM-DD hh:mm:SS", siteTz) // Add check for anomalyArc status, only find new triggers if no open arcs exist. - // akTODO: Also check if triggers exist. Figure out the unique conditional + //========================================================> Also check if triggers exist. Figure out the unique conditional // Otherwise need to delete triggers before each run - openArcs: readAll(anomalyArc and arcOn==meterPointRef).findAll(v=>v.get("anomalyArcState")!="resolved") - // Only map through the meterPoints that got updated? - //if(newHisEnd.date > oldHisEnd.date and openArcs.size == 0) do + //openArcs: readAll(anomalyArc and arcOn==meterPointRef).findAll(v=>v.get("anomalyArcState")!="resolved") + // No more auto creating arcs (might want to fit this in again once we finalize the MBCx pipeline anomaly arc creation + // Only map through the meterPoints that got updated? //if(newHisEnd.date > oldHisEnd.date and openArcs.size == 0) do - if(openArcs.size == 0) do + if(modelHisEnd>anomalyFindingStartDate and meterHisEnd>anomalyFindingStartDate) do //Find and commit anomalyTriggers - //dateSpan: (oldHisEnd..newHisEnd).toSpan - modelPointHisEnd: mp.get("hisEnd") - targetPointHisEnd: mp.get("pointRef")->hisEnd - modelEnd: if(modelPointHisEnd < targetPointHisEnd) modelPointHisEnd else targetPointHisEnd - dateSpan: (modelEnd-3mo..modelEnd).toSpan // (Only finds triggers/anomalies for the past 3 months. Anchor a start date instead? akTODO: potentially YES, different for different projects) - sensitivityOpts: {minAnomalyDuration:24h, highAnomalyThreshold:10%, sustainedAnomalyThreshold:24h} - + modelEnd: if(modelHisEnd < meterHisEnd) modelHisEnd else meterHisEnd + //logInfo("energyAgentTask", "Task 1: Checkpoint 2") + dateSpan: (anomalyFindingStartDate..modelEnd).toSpan + sensitivityOpts: {minAnomalyDuration:24hr, highAnomalyThreshold:10%, sustainedAnomalyThreshold:24hr} try anomalyTrigger: logic_kwModeling_anomalyDetection_findAndCommitAnomalyTriggers(mp, dateSpan, sensitivity:"high", sensitivityOpts, opts:{commitToRec:true}) catch(err) return diff(mp, {anomalyTriggerCreationErr: err.dis}, {transient}).commit() - + //logInfo("energyAgentTask", "Task 1: Anomaly trigger found: "+anomalyTrigger.get("id").toStr) end //end end
task_energyAgent_syncGenAIModels
--- task_energyAgent_syncGenAIModels (pod) +++ task_energyAgent_syncGenAIModels (local) @@ -1,5 +1,5 @@ () => do - syncDuration: 1wk + syncDuration: 7day modelPoints: readAll(syntheticPoint and modelType=="adaptiveBaseline" and hisSize) modelPoints.each() mp => do //Get Meter Point
wdg_anomalyDetection_v2_chart_modelPredictionsPreview_v2
--- wdg_anomalyDetection_v2_chart_modelPredictionsPreview_v2 (pod) +++ wdg_anomalyDetection_v2_chart_modelPredictionsPreview_v2 (local) @@ -42,7 +42,7 @@ else if (utilityType=="water") try pointQuery("water_intervalCons", {read, siteRef: siteRef, checked: false}) catch null // return chart = blankChart(meterRec.toStr) if (meterRec.isNull) return {info: meterRec}.toGrid.addMeta({noData: "Utility meter point missing or tagged incorrectly."}).addColMeta("info", {dis: "Information"}) - else if (meterRec.isNonNull) return chart: logic_energyAgent_meterPointToPredictionsChart(meterRec, dateSpan) + else if (meterRec.isNonNull) return chart: logic_energyAgent_meterPointToPredictionsChart_v2(meterRec, dateSpan) if (chart.isNonNull) return chart @@ -72,4 +72,101 @@ targetVarRef : anomalyRec.get("targetVarRef") //staticModelConfig: try anomalyRec.get("staticModelConfigRef").toRec catch return blankChart("Old anomaly record. Missing staticModelConfigRef. Reobserve anomalies and try again.") - // Dates + // Dates -----> -3mo to +3mo? + anomalyStartTS : anomalyRec.get("ts") + extendedStartTS : anomalyStartTS - 3mo + anomalyEndTS : anomalyStartTS + anomalyRec.get("duration") + extendedEndTS : anomalyEndTS + 3mo + + // Check hisStart and hisEnd for both points + modelPointStartDate: modelPointRef.toRec.get("hisStart") + modelPointEndDate : modelPointRef.toRec.get("hisEnd") + // Usually model point would be the bottleneck ===================> TODO: How can we show the meter data and perhaps the adaptiveBaseline modelPoint along with confInts for the previous 3 months? + //if (modelPointStartDate > extendedStartTS) extendedStartTS = modelPointStartDate + //if (modelPointEndDate < extendedEndTS) extendedEndTS = modelPointEndDate + + extendedSpan : (extendedStartTS..extendedEndTS).toSpan + + // His + hisGrid: [targetVarRef, modelPointRef].hisRead(dateSpan).hisClip + //hisGrid: try logic_kwModeling_getBaselineModelResults(staticModelConfig) catch (err) return blankChart(err.toStr) + // if (hisGrid.isStr) return blankChart(hisGrid) + + confIntGrid : try logic_kwModeling_getModelPointResults(modelPointRef).reorderKeepCols(["ts"]) catch (err) return blankChart(err.dis) + filteredConfIntGrid : confIntGrid.findAll(v=> v.get("ts") >= dateSpan.start and v.get("ts") < dateSpan.end) // filteredHisGrid.first.get("ts") -1hr? + loCol : confIntGrid.colNames.find() r=>r.contains("lo") + hiCol : confIntGrid.colNames.find() r=>r.contains("hi") + + //filteredHisGrid: hisGrid.findAll(v=> v.get("ts") >= extendedStartTS and v.get("ts") < extendedEndTS ) + // if (filteredHisGrid.last.get("ts") < extendedEndTS) extendedEndTS = filteredHisGrid.last.get("ts") + + //return blankChart(hisGrid.colNames.toStr)//.map(r=> {"colName":r}).toGrid + //// Fill in the inital 3 months with Adaptive baseline modelPoint his data + //if (filteredHisGrid.first.get("ts") > extendedStartTS) do + // + // // Get points: + // meterPoint: anomalyRec.get("targetVarRef") + // adaptiveBaselineModelPoint: try anomalyRec.get("anomalyTriggerRef").toRec.get("dynamicModelPointRef") catch (err) return blankChart("Widget trying to read a deleted Anomaly Trigger - Rerun Energy Agent Task", err.dis) + // //return blankChart(adaptiveBaselineModelPoint.toStr) + // // Get His + // preAnomalySpan: (extendedStartTS..filteredHisGrid.first.get("ts")).toSpan // filteredHisGrid.first.get("ts") -1hr? + // + // adaptiveModelHisGrid: [meterPoint, adaptiveBaselineModelPoint].hisRead(preAnomalySpan).hisClip + // + // confIntGrid : try logic_kwModeling_getModelPointResults(adaptiveBaselineModelPoint) catch (err) return blankChart(err.dis) + // filteredConfIntGrid : confIntGrid.findAll(v=> v.get("ts") >= extendedStartTS and v.get("ts") < filteredHisGrid.first.get("ts")) // filteredHisGrid.first.get("ts") -1hr? + // loCol : confIntGrid.colNames.find() r=>r.contains("lo") + // hiCol : confIntGrid.colNames.find() r=>r.contains("hi") + // + // preAnomalyHisGrid: hisJoin([adaptiveModelHisGrid, filteredConfIntGrid]).reorderKeepCols(["ts", "v0", hiCol, "v1", loCol]).renameCol("v1", "timegpt") + // preAnomalyHisGrid = transferMeta(hisGrid, preAnomalyHisGrid) +// + // hisGrid = addRows(filteredHisGrid, preAnomalyHisGrid) + // + //end + + + //holidayCalendar: read(calendar and dis=="Holiday Calendar", false).scheduleHis(extendedSpan) + // .map(r=> r = if (r.get("val")!= true) r.set("val", false) else r.set("val", true)) + // .addColMeta("holidayCalendar", {chartGroup: "duration"}) + + + //Create Anomaly Duration Grid + anomalyDurationGrid: {ts: anomalyStartTS, anomalyDuration: anomalyRec.get("duration")}.toGrid.addMeta({hisStart: dateSpan.start, hisEnd: dateSpan.end, hisSize:1}) + + + allAnomalies: readAll(anomaly and targetVarRef==anomalyRec.get("targetVarRef") and ts >= dateSpan.start and ts < dateSpan.end) + try allAnomalies = allAnomalies.reorderCols(["ts", "duration"]).toGrid.addMeta({hisStart: dateSpan.start, hisEnd: dateSpan.end, hisSize:allAnomalies.size}) catch null + + //out: hisJoin([hisGrid, anomalyDurationGrid, allAnomalies, holidayCalendar]) + lineCharts: hisJoin([hisGrid, filteredConfIntGrid]).addMeta({hisStart: dateSpan.start, hisEnd: dateSpan.end}) + runtimeCharts: hisJoin([ anomalyDurationGrid, allAnomalies]) + out: hisJoin([lineCharts, runtimeCharts]) + + ////////////////////////////////////////////////////////////////////////////////////////// + // FORMAT + ////////////////////////////////////////////////////////////////////////////////////////// + + gridMeta: {title: "Extended Model Prediction Preview - " + anomalyRec.get("siteRef").toRec.get("dis"), subtitle: anomalyRec.get("targetVarRef").toRec.get("navName").toStr + " ("+dateSpan.start.date+" to "+dateSpan.end.date+")", hisStart:dateSpan.start, hisEnd:dateSpan.end} + + // prezGrid for anomalyImpact color? + + out = out.stream + .addColMeta("ts", {dis:"Timestamp"}) + .addColMeta("v0", {dis:"Actual", strokeWidth:1, chartGroup: "predictions", chartType:"line"})// + .addColMeta(hiCol, {dis:"Upper Bound", strokeWidth:0.5, chartGroup: "predictions", chartAreaMode: "nextSeries", color:"#FDD081", opacity: 0.01, chartType:"line"})// + .addColMeta("v1", {dis:"Model", strokeWidth:1.5, chartGroup: "predictions", chartType:"line", strokeDasharray:"6,3"})// + .addColMeta(loCol, {dis:"Lower Bound", strokeWidth:0.5, chartGroup: "predictions", chartAreaMode: "prevSeries", color:"#FDD081", opacity: 0.01, chartType:"line"})// + .addColMeta("anomalyDuration", {chartGroup: "xduration", chartType:"runtime", dis:"Active Anomaly"}) + .addColMeta("duration", {chartGroup: "xduration", chartType:"runtime", dis: "All Anomalies"}) + .addMeta(gridMeta) + .addPrez_chartOrder("", [ "v0", "v1", loCol, hiCol])// + .collect + + ////////////////////////////////////////////////////////////////////////////////////////// + //RETURN RESULT + ////////////////////////////////////////////////////////////////////////////////////////// + + return out.reorderKeepCols(["ts", "v0", hiCol, "v1", loCol, "anomalyDuration", "duration"]) + +end
wdg_chart_energyAgent_portfolioHealthOverview_portfolioPointPredictions
--- wdg_chart_energyAgent_portfolioHealthOverview_portfolioPointPredictions (pod) +++ wdg_chart_energyAgent_portfolioHealthOverview_portfolioPointPredictions (local) @@ -41,18 +41,18 @@ ////////////////////////////////////////////////////////////////////////////////////////// // Find relevant portfolio level calculatedPoint/virtualPoint based on utility - portfolioMeterPoint: if (utilType=="all") try read(portfolioPoint and elec and power and his and virtualPoint and not cost and not savings and not modelPoint and not syntheticPoint) catch null - else if (utilType=="elec") try read(portfolioPoint and elec and power and his and virtualPoint and not cost and not savings and not modelPoint and not syntheticPoint) catch null - else if (utilType=="chw") try read(portfolioPoint and chilled and water and his and virtualPoint and not cost and not savings and not modelPoint and not syntheticPoint) catch null - else if (utilType=="steam") try read(portfolioPoint and steam and his and virtualPoint and not cost and not savings and not modelPoint and not syntheticPoint) catch null - else if (utilType=="gas") try read(portfolioPoint and naturalGas and his and virtualPoint and not cost and not savings and not modelPoint and not syntheticPoint) catch null + portfolioMeterPoint: if (utilType=="all") read(portfolioPoint and elec and power and his and virtualPoint and not cost and not savings and not modelPoint and not syntheticPoint) + else if (utilType=="elec") read(portfolioPoint and elec and power and his and virtualPoint and not cost and not savings and not modelPoint and not syntheticPoint) + else if (utilType=="chw") read(portfolioPoint and chilled and water and his and virtualPoint and not cost and not savings and not modelPoint and not syntheticPoint) + else if (utilType=="steam") read(portfolioPoint and steam and his and virtualPoint and not cost and not savings and not modelPoint and not syntheticPoint) + else if (utilType=="gas") read(portfolioPoint and naturalGas and his and virtualPoint and not cost and not savings and not modelPoint and not syntheticPoint) if (portfolioMeterPoint.isNull) return {info: "Portfolio Level Meter point doesn't exist for the selected utility."}.toGrid.addMeta({noData: "Portfolio Level Meter point doesn't exist for the selected utility."}).addColMeta("info", {dis: "Information"}) // pointQuery portfolio summed calculatedPoint/virtualPoint - out: logic_energyAgent_meterPointToPredictionsChart(portfolioMeterPoint, dateSpan, opts) + out: logic_energyAgent_meterPointToPredictionsChart_v2(portfolioMeterPoint, dateSpan, opts) return out @@ -64,7 +64,10 @@ // FORMAT ////////////////////////////////////////////////////////////////////////////////////////// - gridMeta: {title: "Extended Model Prediction Preview - " + anomalyRec.get("siteRef").toRec.get("dis"), subtitle: anomalyRec.get("targetVarRef").toRec.get("navName").toStr + " ("+dateSpan.start.date+" to "+dateSpan.end.date+")", hisStart:dateSpan.start, hisEnd:dateSpan.end} + gridMeta: {title: "Extended Model Prediction Preview - " + anomalyRec.get("siteRef").toRec.get("dis"), + subtitle: anomalyRec.get("targetVarRef").toRec.get("navName").toStr + " ("+dateSpan.start.date+" to "+dateSpan.end.date+")", + hisStart:dateSpan.start, + hisEnd:dateSpan.end} // prezGrid for anomalyImpact color?
wdg_energyAgent_anomalyDetection_widgetSelector
--- wdg_energyAgent_anomalyDetection_widgetSelector (pod) +++ wdg_energyAgent_anomalyDetection_widgetSelector (local) @@ -15,7 +15,7 @@ * Apoorv Khanuja 05/21/2025 - Initial Creation */ -(wdg, site, utilityType, dates, rules, opts:{}) => do +(wdg, site, utility, dates, rules, opts:{}) => do ////////////////////////////////////////////////////////////////////////////////////////// // NORMALIZE + VALIDATE INPUTS @@ -32,9 +32,7 @@ // anomalyRec : anomalyRef.toRec // anomalyRef = anomalyRec.get("id") //end catch return blankChart("Please refresh page and select an anomaly to populate charts") - - site = site.toRec - siteRef: site.get("id") + anomalyRef:null // Nav resolve site, let the wdg input be resolved siteRef //return blankChart(site.toStr) @@ -50,20 +48,16 @@ // LOGIC ////////////////////////////////////////////////////////////////////////////////////////// - meterRec: if (utilityType=="elec" or utilityType=="all") try pointQuery("elec_intervalPwr", {read, siteRef: siteRef, checked: false}) catch null - else if (utilityType=="steam") try pointQuery("steam_intervalCons", {read, siteRef: siteRef, checked: false}) catch null - else if (utilityType=="chw") try pointQuery("chilledWater_intervalCons", {read, siteRef: siteRef, checked: false}) catch null - else if (utilityType=="hhw") try pointQuery("hotWater_intervalCons", {read, siteRef: siteRef, checked: false}) catch null - else if (utilityType=="naturalGas") try pointQuery("natGas_intervalCons", {read, siteRef: siteRef, checked: false}) catch null - else if (utilityType=="water") try pointQuery("water_intervalCons", {read, siteRef: siteRef, checked: false}) catch null - // Call individual wdg/logic funcs here // Handle which wdg to call/skip depending on available inputs here/ - // akTODO: update wdg_energyAgent_anomalyDetection_exoVarProcessedHis and wdg_energyAgent_anomalyDetection_shapOverTime to work without anomalyRef - if (wdg=="exoVarHis") wdg_energyAgent_anomalyDetection_exoVarProcessedHis(meterRec, dates) // return blankChart("exoVarHis widget implementation in Progress") //wdg_energyAgent_anomalyDetection_exoVarProcessedHis - else if (wdg=="exoVarSHAP") wdg_energyAgent_anomalyDetection_shapOverTime(meterRec, dates) + // akTODO: update wdg_energyAgent_anomalyDetection_exoVarProcessedHis and wdg_energyAgent_anomalyDetection_shapOverTime to work without anomalyRef + if (wdg=="exoVarHis") wdg_energyAgent_anomalyDetection_exoVarProcessedHis(anomalyRef, dates) // return blankChart("exoVarHis widget implementation in Progress") //wdg_energyAgent_anomalyDetection_exoVarProcessedHis + else if (wdg=="exoVarSHAP") wdg_energyAgent_anomalyDetection_shapOverTime(anomalyRef, dates) else if (wdg=="siteSparks") wdg_energyAgent_anomalyDetection_concurrentSparks(site, dates, rules, opts) + //else if (wdg=="modelPredictionsWithAnomalyRef") wdg_anomalyDetection_v2_chart_modelPredictionsPreview_v2(anomalyRef) //return blankChart("modelPredictionsWithAnomalyRef widget implementation in Progress") + + // modelPredictionsWithoutAnomaly needs a specific utility, not "all" // Consolidate in a single func, check for @null/null i/p, call the logicFunc for modelPredictionsWithoutAnomaly
wdg_portfolioDashboard_chart_anomalyImpactDollarPieChart
Sources are identical.
wdg_site_table_monthlyUsage
--- wdg_site_table_monthlyUsage (pod) +++ wdg_site_table_monthlyUsage (local) @@ -28,13 +28,48 @@ out = out.addColMetaAll({viz:"barCell"}).addColMeta("ts", {format:"MMM-YYYY"}).addMeta({view:"chart", chartType: "bar", chartLegend: "hide", - title: title: "Monthly Usage", + title: title: sites.toRec.get("dis") + " Monthly Usage", subtitle: if (dateStart==dateEnd) dateStart.format("MMM YYYY") else dateStart.format("MMM YYYY") + " - " + dateEnd.format("MMM YYYY")}) out.colNames.map(v => if (out.col(v).meta.get("unit")=="therm") out = out.addColMeta(v, {color: "purple"}) // dis: out.col(v).meta.get("siteRef").toRec.get("dis") + " - Natural Gas Use" else if (out.col(v).meta.get("unit")=="kW") out = out.addColMeta(v, {color: "orange"}))//, dis: out.col(v).meta.get("siteRef").toRec.get("dis") + " - Electricity Use" + // Shorten column names to only include navName instead of equipRef and navName + elecList:[] + gasList:[] + steamList:[] + chilledList:[] + out.colNames.each()c => do + meta: out.col(c).meta + if(meta.has("elec")) elecList = elecList.add(c) + if(meta.has("gas")) gasList = gasList.add(c) + if(meta.has("steam")) steamList = steamList.add(c) + if(meta.has("chilled")) chilledList = chilledList.add(c) + end - return out + out = out.colNames.reduce(out, (g, v) => do + meta: g.col(v).meta + if (meta.has("equipRef")) do + equip: meta.get("equipRef").toRec + navDis: equip.get("navName") + g.setColMeta(v, meta.set("disMacro", navDis + " \$navName")) + else + g + end) + + + out = out.map() r => do + out.colNames.each() c => do + if(c == "ts") return null + if(r.get(c).unit == "kW") r = r.set(c, r.get(c).as("kWh")) + else if(r.get(c).unit == "lb/h") r = r.set(c, r.get(c).as("lb")) + else if(r.get(c).unit == "tonref") r = r.set(c, r.get(c).as("tonrefh")) + end + return r = r + end + + + colOrder: [["ts"], elecList, gasList, steamList, chilledList].flatten//.toList + return out.reorderKeepCols(colOrder) end
getSiteKickoffDate
--- getSiteKickoffDate (pod) +++ getSiteKickoffDate (local) @@ -13,7 +13,8 @@ if (arcs.size==null) return missingVal types: "active".split(",") - + //return types + //return arcs //timeline where each row is an arc and its transition dates timeline: arcs.map row => do @@ -22,15 +23,15 @@ out: {id: row->id} types.each type => do - if (type=="new") out=out.set(type, row.get("created")) - else out=out.set(type, try audits.find(r => r.get("audit").get("new").get("projectTrackerState")==type).get("ts") catch null) + if (type=="new") out=out.set(type, row.get("estCompleteDate")) + else out=out.set(type, try audits.find(r => r.get("audit").get("new").get("projectTrackerState")==type).get("audit").get("new").get("estCompleteDate") catch null) end return out end - + //return timeline resolved: timeline.filter(active) + //return resolved if (resolved.size<1) return missingVal - - return resolved.sort("active").first.get("active").date + return resolved.sort("active").first.get("active")//.date end
action_createCalculatedPoint
--- action_createCalculatedPoint (pod) +++ action_createCalculatedPoint (local) @@ -52,7 +52,7 @@ pointDefs.each r => do tag: r.toStr if(pointTags.contains(tag)) do - intersectDict = intersectDict.set(tag, marker()) + intersectDict = intersectDict//.set(tag, marker()) NOTE: This was disabled to prevent automatic tagging of point end end
action_kwModeling_myModels_activateModel
--- action_kwModeling_myModels_activateModel (pod) +++ action_kwModeling_myModels_activateModel (local) @@ -36,10 +36,8 @@ modelPointRef: modelConfigRec.get("modelPointRef") // Figure out activation span based on model engine. - startDate: if ((modelConfigRec.get("pointRef").toRec.get("hisEnd") - 52wk) < modelConfigRec.get("pointRef").toRec.get("hisStart")) modelConfigRec.get("pointRef").toRec.get("hisStart") - else modelConfigRec.get("pointRef").toRec.get("hisEnd") - 52wk dates: if (modelConfigRec.get("modelEngine") == "nmecpy") (modelConfigRec.get("modelParameters").get("trainDates").start..modelConfigRec.get("modelParameters").get("testDates").end).toSpan - else (startDate..(modelConfigRec.get("pointRef").toRec.get("hisEnd"))) + else (2025-01-01..(modelConfigRec.get("pointRef").toRec.get("hisEnd"))) // 2025-01-01 for campus level points 03-01 for others // Populate the modelPoint with data callTask("virtualSyncHis", [modelPointRef, dates], getVal: true)
func_syncCalculatedPoints
Sources are identical.
logic_kwModeling_autoCreateModelConfig
--- logic_kwModeling_autoCreateModelConfig (pod) +++ logic_kwModeling_autoCreateModelConfig (local) @@ -27,10 +27,11 @@ modelEngine: opts.get("modelEngine") modelMethod: opts.get("modelMethod") tempPointId: read(point and temp and weatherStationRef == pointRec.get("siteRef").toRec.get("weatherStationRef"), false).toRec.get("id") + logInfo("kwBulkModeling", "Temp Point selected: " + tempPointId) occPointId: if (opts.has("occ")) opts.get("occ").toRec.get("id") else try read(wifi and occ and point and sensor and calculatedPercent and siteRef == siteRef).toRec.get("id") catch null - additionalPoints: if (opts.has("additionalPoints") and opts.get("additionalPoints").isList and not opts.get("additionalPoints").isEmpty) opts.get("additionalPoints") else try readAll(indicatorVariable).colToList("id") catch null + additionalPoints: if (opts.has("additionalPoints") and opts.get("additionalPoints").isList and not opts.get("additionalPoints").isEmpty) opts.get("additionalPoints").findAll(v=>v.isNonNull) else try readAll(indicatorVariable).colToList("id") catch null // PreProcess Configs Retrieval zScoreOutlierExclusion: if (opts.get("zScoreOutlierExclusion").isNonNull) opts.get("zScoreOutlierExclusion") @@ -83,8 +84,8 @@ span: dates, confInterval: confInterval, testTrainSplitDate: (dates.end-1wk), - additionalPoint: if (additionalPoints.isNull) [] // Removed occ Point (occPointId) - else [additionalPoints].flatten.findAll(v=>v.isNonNull), + additionalPoint: if (additionalPoints.isNull) [occPointId].flatten.findAll(v=>v.isNonNull) // Removed occ Point (occPointId) + else [occPointId, additionalPoints].flatten.findAll(v=>v.isNonNull), }, preProcessConfig: { includeTOW: includeTOW, @@ -94,16 +95,13 @@ end // action_kwModeling_runModel returns a taskFuture, so we follow logic rather than call it itself. - modelConfigRec: try logic_kwModeling_saveModelConfig_v2(dict, opts) - catch (err) return {point: pointId, err: err} + logInfo("kwBulkModeling", "Attempting to save ModelConfig"+dict.toStr) + + modelConfigRec: logic_kwModeling_saveModelConfig_v2(dict, opts) //try + //catch (err) return {point: pointId, err: err} updatedRec: diff(modelConfigRec, {"modelRunState": "queued"}, {update}).commit() - - // NOTE: Change so after the callTask is done, we retrieve the future and check if done vs. done error - //try callTask(logic_kwModeling_runModel, [updatedRec], getVal: true) - //catch (err) return {modelConfigRec: updatedRec, err: err} - // Edit 06/2025: Running the config is unnecessary. Just save config and activate point. - + logInfo("kwBulkModeling", "ModelConfig saved.") // Return the updated/created modelRec return updatedRec end
logic_kwModeling_bulkGenerateModelPoints
--- logic_kwModeling_bulkGenerateModelPoints (pod) +++ logic_kwModeling_bulkGenerateModelPoints (local) @@ -80,46 +80,6 @@ successfulConfigs: modelConfigs.findAll(r => r.isDict and r.missing("err")) failedConfigs: modelConfigs.findAll(r => r.isDict and r.has("err")) - // Report as a warning the configs that werent able to create a config. - //if (not failedConfigs.isEmpty) logWarn("kwBulkModeling", failedConfigs.size + " of valid points failed to create a config.", failedConfigs) - // Commented out for now. - //Fails with: Func failed: logWarn(Obj tags,Str msg,Dict err); args: (Str,Str,GbGrid) - // sys::ArgErr: java.lang.IllegalArgumentException: argument type mismatch - -// // Point-Per-Task Opt -// pointPerTask: opts.get("pointPerTask") -// bulkMode: opts.get("bulkMode") -// -// // Reset pointPerTask to 1 if bulkMode is single-task -// if (pointPerTask < 1 or bulkMode=="Single-Task") pointPerTask = 1 -// -// // Split model configs into buckets for efficient/safe task processing -// buckets: [] -// idx: 0 -// successfulConfigs.each(r => do -// try do -// subGrid: buckets.get(idx) -// if (subGrid.size < pointPerTask) buckets = buckets.set(idx, subGrid.add(r->id)) -// else do -// idx = idx + 1 -// throw "Create new bucket" // Dummy throw to jump into the catch -// end -// catch do -// buckets = buckets.add([r->id]) -// end -// end) -// -// // Log progress (buckets were created) -// logInfo("kwBulkModeling", buckets.size + " bucket(s) created. Initializing Bulk Modeling Activation") -// -// // Activate models using a taskRun/futureGet pair on a per-bucket basis (bucket size is dependant on pointPerTask Opt) -// buckets.each() (bucket) => do -// logInfo("kwBulkModeling", "Activating these models at the same time: " + bucket.toStr) -// bucket.each() (modelConfigRef) => do -// if (modelConfigRef != bucket.last) callTask(action_kwModeling_myModels_activateModel, [modelConfigRef], getVal:false) -// else callTask(action_kwModeling_myModels_activateModel, [modelConfigRef], getVal:true) -// end -// end // Activating one config at a time successfulConfigs.each() r => do
logic_kwModeling_createModelPointRec_v2
--- logic_kwModeling_createModelPointRec_v2 (pod) +++ logic_kwModeling_createModelPointRec_v2 (local) @@ -29,12 +29,8 @@ modelPointBlueprint : try read(virtualBlueprint and navName=="GenAI Adaptive Baseline Model Point") catch throw "No modelPoint Blueprint found." - modelActivationConfig: if (modelConfigRec.get("modelEngine")=="timegpt") {trainLength: 6mo, forecastLength: 1week} + modelActivationConfig: if (modelConfigRec.get("modelEngine")=="timegpt") {trainLength: 12mo, forecastLength: 1week} else if (modelConfigRec.get("modelEngine")=="nmecpy") {trainLength: 12mo, forecastLength: 1week} - - meterHisStart : modelConfigRec.get("pointRef").toRec.get("hisStart") - meterHisEnd : modelConfigRec.get("pointRef").toRec.get("hisEnd") - trainStartDateOverride : if (meterHisStart < meterHisEnd - 12mo) meterHisEnd - 12mo else meterHisStart virtualPointTags: modelPointBlueprint.get("virtualPointTags").listTagsToDict @@ -48,7 +44,6 @@ equipRef : try modelConfigRec.get("pointRef")->equipRef catch null, unit : try modelConfigRec.get("pointRef")->unit catch null, siteRef : modelConfigRec.get("siteRef"), - trainStartDateOverride : trainStartDateOverride, tz : modelConfigRec.get("siteRef").toRec.get("tz"), modelType : modelType, mlIdentificationPeriod : mlIdentificationPeriod,
logic_kwModeling_modelParameterWeightsPlot
--- logic_kwModeling_modelParameterWeightsPlot (pod) +++ logic_kwModeling_modelParameterWeightsPlot (local) @@ -23,6 +23,24 @@ // Extract modelCoeffs modelCoeffs: modelCacheRec.get("modelCoeffs") + //return modelCoeffs.colNames + // Extract other colMeta information for better column names + modelConfigRec : modelCacheRec.get("modelConfigRef").toRec + modelParameters: modelConfigRec.get("modelParameters") + exoVarPoints: [modelParameters.get("temp"), modelParameters.get("additionalPoint")].flatten.findAll(v=>v.isNonNull) + + exoVarMeta: {}.toGrid + + exoVarPoints.each() (r,idx) => do + exoVarNum: idx + 1 + exoVarLabel: "v"+exoVarNum.toStr + + curVarMeta: {exoVarLabel:exoVarLabel, curVarDis: r.toRec.get("navName")} + exoVarMeta = exoVarMeta.addRow(curVarMeta) + end +//return exoVarMeta.findAll(v => v.get("exoVarLabel")=="v1").toRec.get("curVarDis") //blankChart(exoVarMeta.size.toStr) + + ////////////////////// If modelCoeffs is a number (In case of nmecpy>towt model) @@ -46,12 +64,24 @@ //////// v1: regular grid with average model weights else if (modelCoeffs.debugType=="haystack::GbGrid") do - outString: "SHAP Value implemenation in progress." - out: blankChart(outString)/*modelCoeffs.stream + return {info: "SHAP Value implemenation in progress."}.toGrid.addColMeta("info", {dis:"Information"}) + // Shows up as "No Data" + // akTODO: Finish writing this chunk with the new SHAP values grid + modelCoeffs = modelCoeffs.removeCols(["unique_id", "ts", "timegpt", "base_value"]).map() r => do + if (r.has("v1")) r = r.set("v1", r.get("v1").abs) + if (r.has("v2")) r = r.set("v2", r.get("v2").abs) + if (r.has("v3")) r = r.set("v3", r.get("v3").abs) + if (r.has("v4")) r = r.set("v4", r.get("v4").abs) + if (r.has("v5")) r = r.set("v5", r.get("v5").abs) // Works for up to 5 exo variables + + end + // + return modelCoeffs//.colNames + out: modelCoeffs.stream .addMeta({title: "Average weights of exogenous variable used for predictions", chartType:"bar", chartLegend:"hide"}) .addColMeta("timeOfWeek", {dis: "Time of week"}) .collect - .chart*/ + .chart end
logic_kwModeling_validatePointModeling
--- logic_kwModeling_validatePointModeling (pod) +++ logic_kwModeling_validatePointModeling (local) @@ -65,15 +65,12 @@ if (wsHisSize < 1) errors = errors.add("Weather Station has no historized data.") if (wsHisEnd < now()-2year) warnings = warnings.add("Weather Station's hisEnd is older than 2 years from today: " + pointRec.get("hisEnd") + ".") // NOTE: Make this logic better? - if (pointRec.has("hisEnd") and - ((pointRec.get("hisEnd") - 1year) < wsHisStart) or - pointRec.get("hisEnd") > wsHisEnd) errors = errors.add("Overlap data between Point and Temp is not complete") + if (pointRec.has("hisEnd") and ((pointRec.get("hisEnd") - 1year) < wsHisStart) or pointRec.get("hisEnd") > wsHisEnd) errors = errors.add("Overlap data between Point and Temp is not complete") end end // NOTE: Change to pointQuery - //if (readAll(kwStockSchedule).isEmpty) errors = errors.add("No Occupancy Schedule (kwStockSchedule) in this Project.") - // Commented out. Don't really need Stock schedule for EA. + if (readAll(kwStockSchedule).isEmpty) errors = errors.add("No Occupancy Schedule (kwStockSchedule) in this Project.") // Miscellaneous Checks from current modeling app if (modelEngine == "nmecpy" and (modelMethod != "TOWT" and modelMethod != "HD-CD")) errors = errors.add("Additional Points unsupported by " + modelMethod + ". Select a valid model method for additional points, or remove the additional point from this model method. Supported Model Methods for Additional Points: [\"TOWT\", \"HD-CD\"]")
view_calculateSavings
--- view_calculateSavings (pod) +++ view_calculateSavings (local) @@ -36,7 +36,9 @@ equip: modelPoint->equipRef basePt: readById(modelPoint->modelRef)->pointRef interval: modelPoint.get("hisRollupInterval") - weather: readAll(weatherStationRef==equip->siteRef->weatherStationRef and temp) + weather: readById(readById(modelPoint->modelRef)->modelConfig->viewInputs->temp)//readAll(weatherStationRef==equip->siteRef->weatherStationRef and temp and not enthalpy) //Added filter to remove enthalpy as an accidentally considered point here + weatherUnit: weather.get("unit") + if(weatherUnit == "°F") temp = 50°F else if (weatherUnit == "btu/lb_dry") temp = 28.as("btu/lb_dry") weatherHis: weather.hisRead(dates, {-limit}).renameCol("v0","oat").setColMeta("oat",{chartGroup:"a", color:"gray", opacity:0.1, strokeDasharray:"2,2", dis:"Outside Air Temp"}) siteDis: readById(modelPoint->siteRef).dis modelDis: modelPoint.dis
virtual_kwModeling_forecast_syncModelPointPredictions_timegpt
--- virtual_kwModeling_forecast_syncModelPointPredictions_timegpt (pod) +++ virtual_kwModeling_forecast_syncModelPointPredictions_timegpt (local) @@ -54,7 +54,6 @@ spanX : if (trainStartDateOverride.isNull) ((r - trainLength)..spanEnd).toSpan else (trainStartDateOverride..spanEnd).toSpan spans = spans.add(spanX) end - fakeModelConfigRec : modelConfigRec.remove("id").remove("mod").remove("modelConfig2") fakeModelConfigRecGrid : {}.toGrid
kpi_chwp_averagePumpSpeed
Sources are identical.
kpi_chwp_percentRuntime
--- kpi_chwp_percentRuntime (pod) +++ kpi_chwp_percentRuntime (local) @@ -15,12 +15,12 @@ target: {} date: {} out: {readonly} - pri_pump_speed : {bind:"water and pump and speed and cmd and primary and equipRef=={{target->id}}"} - sec_pump_speed : {bind:"water and pump and speed and cmd and secondary and equipRef=={{target->id}}"} - pri_pump_status : {bind:"water and pump and run and cmd and primary and equipRef=={{target->id}}"} - sec_pump_status : {bind:"water and pump and run and cmd and secondary and equipRef=={{target->id}}"} - pri_pump_power : {bind:"water and pump and power and sensor and primary and equipRef=={{target->id}}"} - sec_pump_power : {bind:"water and pump and power and sensor and secondary and equipRef=={{target->id}}"} + pri_pump_speed : {bind:"water and pump and speed and cmd and primary and equipRef->equipRef->equipRef=={{target->id}}"} + sec_pump_speed : {bind:"water and pump and speed and cmd and secondary and equipRef->equipRef->equipRef=={{target->id}}"} + pri_pump_status : {bind:"water and pump and run and cmd and primary and equipRef->equipRef->equipRef=={{target->id}}"} + sec_pump_status : {bind:"water and pump and run and cmd and secondary and equipRef->equipRef->equipRef=={{target->id}}"} + pri_pump_power : {bind:"water and pump and power and sensor and primary and equipRef->equipRef->equipRef=={{target->id}}"} + sec_pump_power : {bind:"water and pump and power and sensor and secondary and equipRef->equipRef->equipRef=={{target->id}}"} do // Call logic function his: logic_cwp_pumpIsRunning(target, date)
kpi_chws_avgDeltaT
Sources are identical.
kpi_chws_avgSystemFlow
--- kpi_chws_avgSystemFlow (pod) +++ kpi_chws_avgSystemFlow (local) @@ -14,6 +14,9 @@ opts: {bindTuning:"opts", defVal:{}} do + + opts = {secondaryLoopOverride: "null"} + // Retrieve loop points: buildingLoopDigest(target, opts).get("buildingLoop") @@ -38,9 +41,9 @@ pumpRunningHis: logic_chws_equipsRunning(bLoopId, date, {equip:"pump"}) // Edge-case handling - if (pumpRunningHis.isStr) return pumpRunningHis + //if (pumpRunningHis.isStr) return pumpRunningHis - pumpRunningHis = pumpRunningHis.keepCols(["ts", "anyEquipRunning"]).findAll(r => r.get("anyEquipRunning").isNonNull) + pumpRunningHis = try pumpRunningHis.keepCols(["ts", "anyEquipRunning"]).findAll(r => r.get("anyEquipRunning").isNonNull) catch null if(pumpRunningHis.isNonNull) his = his.hisFindInPeriods(pumpRunningHis)
kpi_chws_secondaryLoop_percentRuntimeOnePump
Sources are identical.
kpi_chws_systemPeakDemand
--- kpi_chws_systemPeakDemand (pod) +++ kpi_chws_systemPeakDemand (local) @@ -22,8 +22,8 @@ if (demandHis.isStr) return null // Fold resulting hisGrid column based on min/max, and return. - maxPeak : demandHis.foldCol("systemDemand", max) - minPeak : demandHis.foldCol("systemDemand", min) + maxPeak : demandHis.foldCol("v0", max) + minPeak : demandHis.foldCol("v0", min) out = {min: minPeak, max: maxPeak} end
kpi_chws_totalSystemEnergyUse
--- kpi_chws_totalSystemEnergyUse (pod) +++ kpi_chws_totalSystemEnergyUse (local) @@ -22,7 +22,7 @@ if (usageHis.isStr) return null // Fold resulting hisGrid column based on min/max, and return. - totalUsage : usageHis.findAll(r => not r.get("systemUsage").isNaN).foldCol("systemUsage", sum) + totalUsage : usageHis.findAll(r => not r.get("v0").isNaN).foldCol("v0", sum) out = {sum: totalUsage} end
kpi_hhws_secondaryLoop_percentRuntimeOnePump
--- kpi_hhws_secondaryLoop_percentRuntimeOnePump (pod) +++ kpi_hhws_secondaryLoop_percentRuntimeOnePump (local) @@ -11,7 +11,7 @@ target: {} date: {} out: {readonly} - opts: {bindTuning:"opts", defVal:{}} + opts: {bindTuning:"opts", defVal:{}} do // Normalize Inputs
spark_chws_notMeetingSupplySetpoint
Sources are identical.
action_virtualPoints_createSiteMeterPts
--- action_virtualPoints_createSiteMeterPts (pod) +++ action_virtualPoints_createSiteMeterPts (local) @@ -1,9 +1,12 @@ -(dicts) => do - +(list) => do //normalize inputs to grid //dict contains ONLY ID, mod, and CHANGES made to form - input: actionNormInput(dicts,"dicts").toGrid - + //input: actionNormInput(dicts,"dicts").toGrid + input: [] + list.each(r => input=input.add(r.toStr.split("|")[2].parseRef)) + input = readByIds(input) + equip: list[0].toStr.split("|")[1].parseRef + site: list[0].toStr.split("|")[0].parseRef //match input dict up with blueprint list blueprints: wdg_virtualPoints_table_blueprintList() @@ -18,7 +21,7 @@ catch (err) blueprint.merge({result:"failure", err:err}) //return result - out: if (dict.missing("err")) diff(null, dict, {add}).commit.merge({result:"succes"}) + out: if (dict.missing("err")) diff(null, dict.set("equipRef", equip).set("siteRef", site), {add}).commit.merge({result:"succes"}) else dict end recs: readByIds(results.colToList("id"))
calcTMRASavings
--- calcTMRASavings (pod) +++ calcTMRASavings (local) @@ -1,4 +1,4 @@ -(siteId, savingsHis, modelPt, meterPt, performancePeriodStartDate, performancePeriodEndDate, mildTempRangeLower: "40", mildTempRangeUpper: "65") => do +(siteId, savingsHis, modelPt, meterPt, performancePeriodStartDate, performancePeriodEndDate, mildTempRangeLower: "35", mildTempRangeUpper: "50") => do mildTempRange: (mildTempRangeLower.parseNumber.as("°F")..mildTempRangeUpper.parseNumber.as("°F")) performancePeriod : (performancePeriodStartDate..performancePeriodEndDate).toDateSpan siteRec: siteId.toRec
logic_eui
--- logic_eui (pod) +++ logic_eui (local) @@ -36,20 +36,18 @@ //convert units if (not eci) do if (p.get("unit")=="kW") pointHis = pointHis.hisRollup(avg,1hr).hisMap(v=>v.as("kWh")) + if (p.get("unit")=="MW") pointHis = pointHis.hisMap(v=>v.to("kW")).hisRollup(avg,1hr).hisMap(v=>v.as("kWh")) if (p.get("unit")=="BTU/h") pointHis = pointHis.hisRollup(avg,1hr).hisMap(v=>v.as("BTU")) if (p.get("unit")=="kBTU/h") pointHis = pointHis.hisRollup(avg,1hr).hisMap(v=>v.as("kBTU")) if (p.get("unit")=="lb/h") do - pointHis = pointHis.hisRollup(avg,1hr).hisMap(v=>(v*0.0012850675).as("kBTU")) + pointHis = pointHis.hisRollup(avg,1hr).hisMap(v=>(v*1.03).as("kBTU")) end if (p.get("unit")=="tonref") do - pointHis = pointHis.hisRollup(avg,1hr).hisMap(v=>(v*12000).as("kBTU")) + pointHis = pointHis.hisRollup(avg,1hr).hisMap(v=>(v*12).as("kBTU")) end if (p.get("unit")=="klb/h") do - pointHis = pointHis.hisRollup(avg,1hr).hisMap(v=>(v*1.2850675).as("kBTU")) - end - if (p.get("unit")=="ft³_gas") do - pointHis = pointHis.hisRollup(avg,1hr).hisMap(v=>v.as("kBTU")) + pointHis = pointHis.hisRollup(avg,1hr).hisMap(v=>(v*1030).as("kBTU")) end end
siteMeter_retrieveRequiredVirtualPoints
--- siteMeter_retrieveRequiredVirtualPoints (pod) +++ siteMeter_retrieveRequiredVirtualPoints (local) @@ -22,32 +22,56 @@ meterScope : smRec.get("scope") type : if (smRec.has("elec")) "elec" else if (smRec.has("gas") or smRec.has("naturalGas") or smRec.has("natGas")) "gas" + else if (smRec.has("hot") and smRec.has("water")) "hotWater" + else if (smRec.has("chilled") and smRec.has("water")) "chilledWater" + else if (smRec.has("steam")) "steam" else "invalid" // Retrieve Required pointQueryTarget Tags - tags: if (meterScope == "interval" and type=="elec") ["elec_modelPwr", "elec_monthlyEnergy", "elec_monthlyCost", "elec_monthlyRateCost", "elec_intervalPwr", "elec_modelPwr", "elec_savingsPwr", "elec_intervalSavingsCost", "elec_intervalCost"] - else if (meterScope == "interval" and type=="gas") ["natGas_intervalModelCons", "natGas_monthlyCons", "natGas_monthlyCost", "natGas_monthlyRateCost", "natGas_intervalModelCons", "natGas_intervalCost", "natGas_intervalSavingsCost", "natGas_intervalSavingsCons", "natGas_intervalCons"] - else if (meterScope == "monthly" and type=="elec") ["elec_modelEnergy", "elec_monthlyEnergy", "elec_monthlyCost", "elec_monthlyRateCost", "elec_modelEnergy", "elec_savingsEnergy", "elec_monthlySavingsCost"] - else if (meterScope == "monthly" and type=="gas") ["natGas_monthlyModelCons", "natGas_monthlyCons", "natGas_monthlyCost", "natGas_monthlyRateCost", "natGas_monthlyModelCons", "natGas_monthlySavingsCost", "natGas_monthlySavingsCons"] - else [] + tags: if (meterScope == "interval" and type=="elec") ["elec_intervalPwr", "elec_modelPwr", "elec_savingsPwr", "elec_intervalSavingsCost", "elec_intervalCost"] + else if (meterScope == "interval" and type=="hotWater") ["hotWater_intervalCons", "hotWater_intervalModelCons", "hotWater_intervalSavingsCons", "hotWater_intervalSavingsCost", "hotWater_intervalCost"] + else if (meterScope == "interval" and type=="chilledWater") ["chilledWater_intervalCons", "chilledWater_intervalModelCons", "chilledWater_intervalSavingsCons", "chilledWater_intervalSavingsCost", "chilledWater_intervalCost"] + else if (meterScope == "interval" and type=="steam") ["steam_intervalCons", "steam_intervalModelCons", "steam_intervalSavingsCons", "steam_intervalSavingsCost", "steam_intervalCost"] + else if (meterScope == "interval" and type=="gas") ["elec_intervalPwr", "elec_modelPwr", "elec_savingsPwr", "elec_intervalSavingsCost", "elec_intervalCost"] + else if (meterScope == "monthly" and type=="elec") ["elec_intervalPwr", "elec_modelPwr", "elec_savingsPwr", "elec_intervalSavingsCost", "elec_intervalCost"] + else if (meterScope == "monthly" and type=="hotWater") ["elec_intervalPwr", "elec_modelPwr", "elec_savingsPwr", "elec_intervalSavingsCost", "elec_intervalCost"] + else if (meterScope == "monthly" and type=="chilledWater") ["elec_intervalPwr", "elec_modelPwr", "elec_savingsPwr", "elec_intervalSavingsCost", "elec_intervalCost"] + else if (meterScope == "monthly" and type=="steam") ["elec_intervalPwr", "elec_modelPwr", "elec_savingsPwr", "elec_intervalSavingsCost", "elec_intervalCost"] + else if (meterScope == "monthly" and type=="gas") ["elec_intervalPwr", "elec_modelPwr", "elec_savingsPwr", "elec_intervalSavingsCost", "elec_intervalCost"] + else [] // Determine return value based on pointType opt. - if (opts.get("pointType") == "tags") return tags - if (opts.get("pointType") == "valid") return tags.map(point => if (pointQuery(point, {equipRef: smId}).isNonNull) pointQuery(point, {equipRef: smId}) else null).findAll(v => v.isNonNull).toGrid + if (opts.get("pointType") == "tags") return tags + if (opts.get("pointType") == "valid") do + validRecs: tags.map(point => if (pointQuery(point, {equipRef: smId}).isNonNull) pointQuery(point, {equipRef: smId}) else null).findAll(v => v.isNonNull).toGrid + if(validRecs.isNonNull and validRecs.has("id")) validRecs = validRecs.unique("id") + return validRecs + end if (opts.get("pointType") == "missing") do // Find Missing Points through the blueprint list and pointQueryLookups missing: getVirtualBlueprintList().findAll(r => tags.contains(r.get("pointQueryTarget")) and pointQuery(r.get("pointQueryTarget"), {equipRef: smId}).isNull) .map(r=> r.set("tz", smRec.get("siteRef").toRec.get("tz"))) // Add Model Point Missing Message - if (meterScope == "interval" and type=="elec" and pointQuery("elec_modelPwr", {equipRef: smId}).isNull) missing = missing.addRow({virtualPointCategory: "Missing Model Point"}) - else if (meterScope == "interval" and type=="gas" and pointQuery("natGas_intervalModelCons", {equipRef: smId}).isNull) missing = missing.addRow({virtualPointCategory: "Missing Model Point"}) - else if (meterScope == "monthly" and type=="elec" and pointQuery("elec_modelEnergy", {equipRef: smId}).isNull) missing = missing.addRow({virtualPointCategory: "Missing Model Point"}) - else if (meterScope == "monthly" and type=="gas" and pointQuery("natGas_monthlyModelCons", {equipRef: smId}).isNull) missing = missing.addRow({virtualPointCategory: "Missing Model Point"}) + if (meterScope == "interval" and type=="elec" and pointQuery("elec_modelPwr", {equipRef: smId}).isNull) missing = missing.addRow({virtualPointCategory: "Missing Model Point"}) + if (meterScope == "interval" and type=="hotWater" and pointQuery("hotWater_intervalModelCons", {equipRef: smId}).isNull) missing = missing.addRow({virtualPointCategory: "Missing Model Point"}) + if (meterScope == "interval" and type=="chilledWater" and pointQuery("chilledWater_intervalModelCons", {equipRef: smId}).isNull) missing = missing.addRow({virtualPointCategory: "Missing Model Point"}) + if (meterScope == "interval" and type=="steam" and pointQuery("steam_intervalModelCons", {equipRef: smId}).isNull) missing = missing.addRow({virtualPointCategory: "Missing Model Point"}) + if (meterScope == "interval" and type=="gas" and pointQuery("natGas_intervalModelCons", {equipRef: smId}).isNull) missing = missing.addRow({virtualPointCategory: "Missing Model Point"}) + if (meterScope == "monthly" and type=="elec" and pointQuery("elec_modelEnergy", {equipRef: smId}).isNull) missing = missing.addRow({virtualPointCategory: "Missing Model Point"}) + if (meterScope == "monthly" and type=="hotWater" and pointQuery("hotWater_monthlyModelCons", {equipRef: smId}).isNull) missing = missing.addRow({virtualPointCategory: "Missing Model Point"}) + if (meterScope == "monthly" and type=="chilledWater" and pointQuery("chilledWater_monthlyModelCons", {equipRef: smId}).isNull) missing = missing.addRow({virtualPointCategory: "Missing Model Point"}) + if (meterScope == "monthly" and type=="steam" and pointQuery("steam_monthlyModelCons", {equipRef: smId}).isNull) missing = missing.addRow({virtualPointCategory: "Missing Model Point"}) + if (meterScope == "monthly" and type=="gas" and pointQuery("natGas_monthlyModelCons", {equipRef: smId}).isNull) missing = missing.addRow({virtualPointCategory: "Missing Model Point"}) return missing.sortDis() end - if (opts.get("pointType") == "extra") return readAll(point and equipRef == smId).findAll(r => r.missing("pointQueryTarget") or (r.has("pointQueryTarget") and pointQuery(r.get("pointQueryTarget"), {equipRef: smId}).isNull)).toGrid - + if (opts.get("pointType") == "extra") do + validRecs: tags.map(point => if (pointQuery(point, {equipRef: smId}).isNonNull) pointQuery(point, {equipRef: smId}) else null).findAll(v => v.isNonNull).toGrid + extras: readAll(point and equipRef == smId).findAll(r => r.missing("pointQueryTarget") or (r.has("pointQueryTarget") and pointQuery(r.get("pointQueryTarget"), {equipRef: smId}).isNull)).toGrid + if(validRecs.isNull or validRecs.isEmpty) return extras + extras = extras.findAll(r => not validRecs.colToList("id").contains(r.get("id"))) + return extras + end // If none of the opts is called, return the opt key name and the valid values for that key. return {info: "Accepted \"pointType\" Opts: [tags, valid, missing, extra]"}.toGrid.addColMeta("info", {dis: "Information"}) end
virtualBlueprintToPoint
--- virtualBlueprintToPoint (pod) +++ virtualBlueprintToPoint (local) @@ -8,17 +8,20 @@ blueprint = blueprint.remove("id").remove("mod") //check for required tags - if (blueprint.missing("siteRef")) throw "Failed - missing siteRef" - if (blueprint.missing("equipRef")) throw "Failed - missing equipRef" + //if (blueprint.missing("siteRef")) throw "Failed - missing siteRef" + //if (blueprint.missing("equipRef")) throw "Failed - missing equipRef" //add and convert tags - tz: blueprint.get("siteRef").toRec.get("tz") + tz: blueprint.get("tz") virtualPointTags: blueprint.get("virtualPointTags").listTagsToDict if (virtualPointTags.isNull) virtualPointTags = {} dict: blueprint.merge({point, virtualPoint, his, tz:tz, + unit: blueprint.get("unit"), + siteRef: blueprint.get("siteRef"), + equipRef: blueprint.get("equipRef"), -virtualBlueprint, virtualPointCreator: userCur()->id, -virtualPointTags,
virtualSyncHis
--- virtualSyncHis (pod) +++ virtualSyncHis (local) @@ -103,6 +103,7 @@ //find all the non-null data // Added != nan() check 6/24/2025 + if(data.isList) data = data.toGrid.reorderKeepCols(["ts"]) data = data.findAll(r => r.get(data.colNames[1]).isNonNull and r.get(data.colNames[1]) != nan() and r.get(data.colNames[1]) != na()) //check if units match
wdg_hisPoint_displayMissingDataPeriods
Sources are identical.
wdg_hisPoint_missingDataPeriods
Sources are identical.
wdg_siteMeterManager_missingPoints
--- wdg_siteMeterManager_missingPoints (pod) +++ wdg_siteMeterManager_missingPoints (local) @@ -16,5 +16,5 @@ out: siteMeter_retrieveRequiredVirtualPoints(smId, {pointType: "missing"}) out = out.map(r => return r.set("mixyRefs", smRec.get("siteRef").toStr+"|"+smId.toStr+"|"+r.get("id"))) if (out.isEmpty) out = {info: "No Missing Points found."}.toGrid.addColMeta("info", {dis: "Information"}) - return out.addMeta({title: "❌ Missing Points ❌"}).addColMeta("mixyRefs", {hide, hidden}) + return out.addMeta({title: "❌ Missing Points ❌"}) end
wdg_siteMeterManager_siteMeters
Sources are identical.
Browser Checks
Loading…
{SKYSPARK_USER},
{SKYSPARK_PASS}, and {port} are resolved from env vars on the sidecar.
Loading…
Current Pods
| Pod | Reported | Canonical | Modified | Status |
|---|---|---|---|---|
| constellationBrowser | 1.0.31 | 1.0.33 | mismatch | |
| constellationSftp | 1.0.26 | 1.0.40 | mismatch | |
| kWEnergyCapExt | — | 1.0.7 | not reported | |
| kWEPOExt | 1.8 | 1.8 | ok | |
| kwGithubExt | 1.1.1 | 1.1.1 | ok | |
| kwLinkAlc | 0.0.5 | 0.0.5 | ok | |
| kwLinkAnalyticsExt | 1.5.31 | 1.5.31 | ok | |
| kwLinkArcadia | 2.0.16 | 2.0.16 | ok | |
| kwLinkBlink | — | 0.0.1 | not reported | |
| kwLinkCoreExt | 1.3.47 | 1.3.48 | mismatch | |
| kwLinkDesigo | 2.0.9 | 2.0.9 | ok | |
| kwLinkDevToolsExt | 1.0.12 | 1.0.12 | ok | |
| kwLinkDiagnosticsExt | — | 0.1.4 | not reported | |
| kwLinkegratorExt | — | 2.0.1 | not reported | |
| kwLinkEmcs | 0.0.1 | 0.0.1 | ok | |
| kwLinkEnergyAgentExt | 0.0.29 | 0.0.26 | mismatch | |
| kwLinkEventsExt | 0.1.0 | 0.1.0 | ok | |
| kwLinkFCoreExt | 1.0.39 | 1.0.39 | ok | |
| kwLinkLicenseExt | — | 1.0.4 | not reported | |
| kwLinkMbcxExt | 1.4.54 | 1.4.54 | ok | |
| kwLinkModelExt | 1.1.21 | 1.1.21 | ok | |
| kwLinkRuleExt | 0.4.0 | 0.4.2 | mismatch | |
| kwLinkUMichRuleExt | — | 0.0.6 | not reported | |
| kwLinkVirtualExt | 1.2.25 | 1.2.25 | ok | |
| kwLinkWorkflowExt | — | 0.2.0 | not reported | |
| kWMonnitExt | — | 1.1 | not reported | |
| kWTrackerExt | — | 1.11 | not reported | |
| kWUtilityAPIExt | — | 1.0.15 | not reported | |
| evseExt | — | 1.0 | not reported | |
| ocpp | — | 3.1.12 | not reported | |
| ocpp1_6 | — | 3.1.12 | not reported | |
| ocpp2_0_1 | — | 3.1.12 | not reported | |
| ocppExt | — | 3.1.12 | not reported |
Queue Update
Updates are queued here and downloaded by the instance on its next check-in.
Configuration (.props)
Saved content will be written to lib/local/constellationSftp.props on the instance's next check-in.
Live Pod Status
Last report:Loading…
Update Log
| Pushed At | Pod | Version | Status | Error | Restart |
|---|---|---|---|---|---|
| constellationSftp | 1.0.26 | success | — | — | |
| constellationBrowser | 1.0.31 | success | — | — | |
| constellationBrowser | 1.0.29 | success | — | — | |
| constellationBrowser | 1.0.27 | success | — | — | |
| constellationBrowser | 1.0.25 | success | — | — | |
| constellationBrowser | 1.0.24 | success | — | — | |
| constellationBrowser | 1.0.22 | success | — | — | |
| constellationBrowser | 1.0.21 | success | — | — | |
| constellationBrowser | 1.0.20 | success | — | — | |
| constellationBrowser | 1.0.19 | success | — | — | |
| constellationBrowser | 1.0.18 | success | — | — | |
| constellationBrowser | 1.0.15 | success | — | — | |
| constellationSftp | 1.0.26 | success | — | — | |
| constellationBrowser | 1.0.14 | success | — | — | |
| constellationBrowser | 1.0.13 | success | — | — | |
| constellationSftp | 1.0.25 | success | — | — | |
| constellationBrowser | 1.0.11 | success | — | — | |
| constellationSftp | 1.0.22 | success | — | — | |
| constellationBrowser | 1.0.4 | success | — | — | |
| constellationSftp | 1.0.22 | success | — | — | |
| constellationBrowser | 1.0.4 | success | — | — | |
| constellationBrowser | 1.0.8 | success | — | — | |
| constellationBrowser | 1.0.7 | success | — | — |
Loading network data...