diff --git a/CHANGELOG.md b/CHANGELOG.md index 92893e3b..d5c1f028 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,9 +5,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ## [Unreleased] ### Added -- added excel exporter of equipmentincome report -- added excel exporter of shopfloorsaving report -- added excel exporter of equipmentload report +- None. ### Changed - None. @@ -18,6 +16,48 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ### Removed - None. + +## [v1.1.0] - 2021-03-18 +### Added +- added excel exporter of equipmentefficiency report. +- added excel exporter of conbinedequipmentefficiency report in API. +- added 'optional' tips to meter,virtual meter and offline meter setting in admin UI. +- added Optional key to translation in admin UI. +- added cominbedequipmentefficiency report to api and web. +- added equipmentefficiency report api. + +### Changed +- updated cost file controller in admin UI +- updated user login session expire time to 8 hours. +- changed web UI and API to set contact of space is optional. + +### Fixed +- fixed http headers issues of offlinemeterfile, knowledgefile and costfile in admin UI +- changed float datatype to Decimal datatype for offline meter normalization. +- fixed issue of add space in web UI. +- added historical database close and disconnect at the end of reports. + +### Removed +- None. + +## [v1.0.8] - 2021-03-11 +### Added +- added excel exporter of combinedequipmentstatistics report +- added translation for German +- added excel exporter of storesaving report +- added excel exporter of equipmentincome report +- added excel exporter of shopfloorsaving report +- added excel exporter of equipmentload report + +### Changed +- Changed default reporting range in EnergyFlowDiagram. + +### Fixed +- None. + +### Removed +- None. + ## [v1.0.7] - 2021-03-07 ### Added - added excel exporter of storeload report @@ -79,7 +119,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ### Removed - None. -[Unreleased]: https://github.com/MyEMS/myems/compare/v1.0.7...HEAD +[Unreleased]: https://github.com/MyEMS/myems/compare/v1.1.0...HEAD +[v1.0.8]: https://github.com/MyEMS/myems/compare/v1.0.8...v1.1.0 +[v1.0.8]: https://github.com/MyEMS/myems/compare/v1.0.7...v1.0.8 [v1.0.7]: https://github.com/MyEMS/myems/compare/v1.0.6...v1.0.7 [v1.0.6]: https://github.com/MyEMS/myems/compare/v1.0.5...v1.0.6 [v1.0.5]: https://github.com/MyEMS/myems/releases/tag/v1.0.5 diff --git a/README.md b/README.md index 864b4435..b7e0215b 100644 --- a/README.md +++ b/README.md @@ -22,49 +22,55 @@ MyEMS是行业领先的开源能源管理系统,利用云计算、物联网、 ## MyEMS组件(社区版) MyEMS项目由下列组件构成: +### MyEMS 数据库 +SQL -### MyEMS Web UI +[安装 数据库](./database/README.md) -参考[web](./web/README.md) 获取更多信息。 +### MyEMS API 应用程序接口 +Python + +[安装 myems-api](./myems-api/README.md) ### MyEMS 管理 UI +AngularJS -参考[admin](./admin/README.md) 获取更多信息。 - -### MyEMS 数据库 - -参考[database](./database/README.md) 获取更多信息。 - -### MyEMS 数据清洗服务 - -参考[myems-cleaning](./myems-cleaning/README.md) 获取更多信息。 - -### MyEMS 数据规范化服务 - -参考[myems-normalization](./myems-normalization/README.md) 获取更多信息。 - -### MyEMS 数据汇总服务 - -参考[myems-aggregation](./myems-aggregation/README.md) 获取更多信息。 - -### MyEMS 数据接口API - -参考[myems-api](./myems-api/README.md) 获取更多信息。 - -### MyEMS MQTT 数据发布服务 (从MyEMS转发到第三方) - -参考[myems-mqtt-publisher](./myems-mqtt-publisher/README.md) 获取更多信息。 +[安装 admin UI](./admin/README.md) ### MyEMS BACnet/IP 数据采集服务 +Python -参考[myems-bacnet](./myems-bacnet/README.md) 获取更多信息。 +[安装 myems-bacnet](./myems-bacnet/README.md) ### MyEMS Modbus TCP 数据采集服务 +Python -参考[myems-modbus-tcp](./myems-modbus-tcp/README.md) 获取更多信息。 +[安装 myems-modbus-tcp](./myems-modbus-tcp/README.md) -## MyEMS截图 -![MyEMS Screenshot](/docs/images/screenshot-2020.12.01-16_53_12.png) +### MyEMS MQTT数据转发服务 +Python + +[安装 myems-mqtt-publisher](./myems-mqtt-publisher/README.md) + +### MyEMS 数据清洗服务 +Python + +[安装 myems-cleaning](./myems-cleaning/README.md) + +### MyEMS 数据规范化服务 +Python + +[安装 myems-normalization](./myems-normalization/README.md) + +### MyEMS 数据汇总服务 +Python + +[安装 myems-aggregation](./myems-aggregation/README.md) + +### MyEMS Web UI +ReactJS + +[安装 web UI](./web/README.md) ## 功能版本对比 | 功能 |社区版(MyEMS) |企业版(AlbertEOS)| @@ -149,7 +155,8 @@ MyEMS项目由下列组件构成: | 能流图分析 | ✔️ | ✔️ | | 配电系统分析 | ✔️ | ✔️ | | REST API | ✔️ | ✔️ | -| Web APP | ✔️ | ✔️ | +| Web UI | ✔️ | ✔️ | +| Admin UI | ✔️ | ✔️ | | MQTT 协议订阅数据 | ❌ | ✔️ | | Modbus RTU 协议 | ❌ | ✔️ | | OPC UA 协议 | ❌ | ✔️ | @@ -159,13 +166,18 @@ MyEMS项目由下列组件构成: | Johnson Controls Metasys | ✔️ | ✔️ | | Honeywell EBI | ✔️ | ✔️ | | SIEMENS Desigo CC | ❌ | ✔️ | -| FDD 能效故障诊断规系统 | ❌ | ✔️ | +| QWeather API | ❌ | ✔️ | +| FDD 能效故障诊断系统 | ❌ | ✔️ | | 高级报表系统 | ❌ | ✔️ | | 组态图形绘制工具 | ❌ | ✔️ | | 设备远程控制 | ❌ | ✔️ | | BACnet Server | ❌ | ✔️ | +| Modbus TCP Server(Slave) | ❌ | ✔️ | +| OPC UA Server | ❌ | ✔️ | | iOS APP | ❌ | ✔️ | | Android APP | ❌ | ✔️ | +| 微信小程序 | ❌ | ✔️ | +| 支付宝小程序 | ❌ | ✔️ | | 工控机硬件网关(数据采集和远程控制) | ❌ | ✔️ | | LoRa无线数传电台模块(数据采集和远程控制)| ❌ | ✔️ | | 重点用能单位能耗在线监测系统上传省级平台通信协议| ❌ | ✔️ | @@ -179,6 +191,11 @@ MyEMS项目由下列组件构成: | 投标技术支持服务 | ❌ | ✔️ | | 二次开发技术支持服务 | ❌ | ✔️ | +## MyEMS截图 +![MyEMS Space EnergyCategory1](/docs/images/myems-space-energycategory1.gif) +![MyEMS Space EnergyCategory2](/docs/images/myems-space-energycategory2.gif) +![MyEMS Space EnergyCategory3](/docs/images/myems-space-energycategory3.gif) +![MyEMS Large Screen Dashboard](/docs/images/myems-large-screen-dashboard.gif) ## MyEMS镜像 diff --git a/README_DE.md b/README_DE.md index bf670b57..73212bb5 100644 --- a/README_DE.md +++ b/README_DE.md @@ -23,48 +23,56 @@ MyEMS wird von einem erfahrenen Entwicklungsteam entwickelt und gewartet, und de Dieses Projekt besteht aus folgenden Komponenten: -### MyEMS Web UI - -Weitere Informationen finden Sie [web](./web/README.md). - -### MyEMS Admin UI - -Weitere Informationen finden Sie im [admin](./admin/README.md). - ### MyEMS Database +SQL -Weitere Informationen finden Sie im [database](./database/README.md). - -### MyEMS Cleaning Service - -Weitere Informationen finden Sie im [myems-cleaning](./myems-cleaning/README.md). - -### MyEMS Normalization Service - -Weitere Informationen finden Sie im [myems-normalization](./myems-normalization/README.md). - -### MyEMS Aggregation Service - -Weitere Informationen finden Sie im [myems-aggregation](./myems-aggregation/README.md). +[Installieren database](./database/README.md) ### MyEMS API +Python -Weitere Informationen finden Sie im [myems-api](./myems-api/README.md). +[Installieren myems-api](./myems-api/README.md) -### MyEMS MQTT Data Publisher Service (transmit data from MyEMS to 3rd Party) +### MyEMS Admin UI +AngularJS -Weitere Informationen finden Sie im [myems-mqtt-publisher](./myems-mqtt-publisher/README.md). +[Installieren admin UI](./admin/README.md) ### MyEMS BACnet/IP Acquisition Service +Python -Weitere Informationen finden Sie im [myems-bacnet](./myems-bacnet/README.md). +[Installieren myems-bacnet](./myems-bacnet/README.md) ### MyEMS Modbus TCP Acquisition Service +Python -Weitere Informationen finden Sie im [myems-modbus-tcp](./myems-modbus-tcp/README.md). +[Installieren myems-modbus-tcp](./myems-modbus-tcp/README.md) + +### MyEMS MQTT Data vorwärts Service +Python + +[Installieren myems-mqtt-publisher](./myems-mqtt-publisher/README.md) + +### MyEMS Cleaning Service +Python + +[Installieren myems-cleaning](./myems-cleaning/README.md) + +### MyEMS Normalization Service +Python + +[Installieren myems-normalization](./myems-normalization/README.md) + +### MyEMS Aggregation Service +Python + +[Installieren myems-aggregation](./myems-aggregation/README.md) + +### MyEMS Web UI +ReactJS + +[Installieren web UI](./web/README.md) -## MyEMS Bildschirmfoto -![MyEMS Bildschirmfoto](/docs/images/screenshot-2020.12.01-16_53_12.png) ## Editionen vergleichen @@ -152,7 +160,8 @@ Weitere Informationen finden Sie im [myems-modbus-tcp](./myems-modbus-tcp/README | Energy Flow Diagram | ✔️ | ✔️ | | Distribution System | ✔️ | ✔️ | | REST API | ✔️ | ✔️ | -| Web APP | ✔️ | ✔️ | +| Web UI | ✔️ | ✔️ | +| Admin UI | ✔️ | ✔️ | | MQTT Subscriber | ❌ | ✔️ | | Modbus RTU | ❌ | ✔️ | | OPC UA | ❌ | ✔️ | @@ -162,17 +171,22 @@ Weitere Informationen finden Sie im [myems-modbus-tcp](./myems-modbus-tcp/README | Johnson Controls Metasys | ✔️ | ✔️ | | Honeywell EBI | ✔️ | ✔️ | | SIEMENS Desigo CC | ❌ | ✔️ | +| QWeather API | ❌ | ✔️ | | FDD Rule Engine | ❌ | ✔️ | | Advanced Reporting Engine | ❌ | ✔️ | -| Graphics Drwaing Tool | ❌ | ✔️ | +| Graphics Drawing Tool | ❌ | ✔️ | | Equipments Remote Control | ❌ | ✔️ | | BACnet Server | ❌ | ✔️ | +| Modbus TCP Server(Slave) | ❌ | ✔️ | +| OPC UA Server | ❌ | ✔️ | | iOS APP | ❌ | ✔️ | | Android APP | ❌ | ✔️ | +| WeChat Mini Program | ❌ | ✔️ | +| Alipay Mini Program | ❌ | ✔️ | | IPC Hardware Gateway (Data Acquisition and Remote Control)| ❌ | ✔️ | | LoRa Radio Module (Data Acquisition and Remote Control)| ❌ | ✔️ | | Protocol for Uploading to Provincial Platform of On-line monitoring system for Key Energy-Consuming Unit| ❌ | ✔️ | -| 3rd Party Systems Integration | ❌ | ✔️ | +| 3rd Party Systems Integration Service | ❌ | ✔️ | | Online Community Customer Support| ✔️ | ✔️ | | Email Customer Support | ✔️ | ✔️ | | Telephone Customer Support | ❌ | ✔️ | @@ -182,6 +196,13 @@ Weitere Informationen finden Sie im [myems-modbus-tcp](./myems-modbus-tcp/README | Bidding Support Service | ❌ | ✔️ | | Customize Support Service | ❌ | ✔️ | + +## MyEMS Bildschirmfoto +![MyEMS Space EnergyCategory1](/docs/images/myems-space-energycategory1.gif) +![MyEMS Space EnergyCategory2](/docs/images/myems-space-energycategory2.gif) +![MyEMS Space EnergyCategory3](/docs/images/myems-space-energycategory3.gif) +![MyEMS Großbild-Dashboard](/docs/images/myems-large-screen-dashboard.gif) + ## MyEMS Spiegel [1]. http://github.com/MyEMS/myems diff --git a/README_EN.md b/README_EN.md index aa108d00..86bffdb8 100644 --- a/README_EN.md +++ b/README_EN.md @@ -23,48 +23,56 @@ MyEMS is being developed and maintained by an experienced development team, and This project is compose of following components: -### MyEMS Web UI - -See the repository [web](./web/README.md) for more information. - -### MyEMS Admin UI - -See [admin](./admin/README.md) for more information. - ### MyEMS Database +SQL -See [database](./database/README.md) for more information. - -### MyEMS Cleaning Service - -See [myems-cleaning](./myems-cleaning/README.md) for more information. - -### MyEMS Normalization Service - -See [myems-normalization](./myems-normalization/README.md) for more information. - -### MyEMS Aggregation Service - -See [myems-aggregation](./myems-aggregation/README.md) for more information. +[Install database](./database/README.md) ### MyEMS API +Python -See the repository [myems-api](./myems-api/README.md) for more information. +[Install myems-api](./myems-api/README.md) -### MyEMS MQTT Data Publisher Service (transmit data from MyEMS to 3rd Party) +### MyEMS Admin UI +ReactJS -See [myems-mqtt-publisher](./myems-mqtt-publisher/README.md) for more information. +[Install admin UI](./admin/README.md) ### MyEMS BACnet/IP Acquisition Service +Python -See [myems-bacnet](./myems-bacnet/README.md) for more information. +[Install myems-bacnet](./myems-bacnet/README.md) ### MyEMS Modbus TCP Acquisition Service +Python -See [myems-modbus-tcp](./myems-modbus-tcp/README.md) for more information. +[Install myems-modbus-tcp](./myems-modbus-tcp/README.md) + +### MyEMS MQTT Data Forwarding Service +Python + +[Install myems-mqtt-publisher](./myems-mqtt-publisher/README.md) + +### MyEMS Cleaning Service +Python + +[Install myems-cleaning](./myems-cleaning/README.md) + +### MyEMS Normalization Service +Python + +[Install myems-normalization](./myems-normalization/README.md) + +### MyEMS Aggregation Service +Python + +[Install myems-aggregation](./myems-aggregation/README.md) + +### MyEMS Web UI +AngularJS + +[Install web UI](./web/README.md) -## MyEMS Screenshot -![MyEMS Screenshot](/docs/images/screenshot-2020.12.01-16_53_12.png) ## Compare Editions @@ -152,7 +160,8 @@ See [myems-modbus-tcp](./myems-modbus-tcp/README.md) for more information. | Energy Flow Diagram | ✔️ | ✔️ | | Distribution System | ✔️ | ✔️ | | REST API | ✔️ | ✔️ | -| Web APP | ✔️ | ✔️ | +| Web UI | ✔️ | ✔️ | +| Admin UI | ✔️ | ✔️ | | MQTT Subscriber | ❌ | ✔️ | | Modbus RTU | ❌ | ✔️ | | OPC UA | ❌ | ✔️ | @@ -162,17 +171,22 @@ See [myems-modbus-tcp](./myems-modbus-tcp/README.md) for more information. | Johnson Controls Metasys | ✔️ | ✔️ | | Honeywell EBI | ✔️ | ✔️ | | SIEMENS Desigo CC | ❌ | ✔️ | +| QWeather API | ❌ | ✔️ | | FDD Rule Engine | ❌ | ✔️ | | Advanced Reporting Engine | ❌ | ✔️ | -| Graphics Drwaing Tool | ❌ | ✔️ | +| Graphics Drawing Tool | ❌ | ✔️ | | Equipments Remote Control | ❌ | ✔️ | | BACnet Server | ❌ | ✔️ | +| Modbus TCP Server(Slave) | ❌ | ✔️ | +| OPC UA Server | ❌ | ✔️ | | iOS APP | ❌ | ✔️ | | Android APP | ❌ | ✔️ | +| WeChat Mini Program | ❌ | ✔️ | +| Alipay Mini Program | ❌ | ✔️ | | IPC Hardware Gateway (Data Acquisition and Remote Control)| ❌ | ✔️ | | LoRa Radio Module (Data Acquisition and Remote Control)| ❌ | ✔️ | | Protocol for Uploading to Provincial Platform of On-line monitoring system for Key Energy-Consuming Unit| ❌ | ✔️ | -| 3rd Party Systems Integration | ❌ | ✔️ | +| 3rd Party Systems Integration Service | ❌ | ✔️ | | Online Community Customer Support| ✔️ | ✔️ | | Email Customer Support | ✔️ | ✔️ | | Telephone Customer Support | ❌ | ✔️ | @@ -182,6 +196,13 @@ See [myems-modbus-tcp](./myems-modbus-tcp/README.md) for more information. | Bidding Support Service | ❌ | ✔️ | | Customize Support Service | ❌ | ✔️ | +## MyEMS Screenshot +![MyEMS Space EnergyCategory1](/docs/images/myems-space-energycategory1.gif) +![MyEMS Space EnergyCategory2](/docs/images/myems-space-energycategory2.gif) +![MyEMS Space EnergyCategory3](/docs/images/myems-space-energycategory3.gif) +![MyEMS Large Screen Dashboard](/docs/images/myems-large-screen-dashboard.gif) + + ## MyEMS Mirrors [1]. http://github.com/MyEMS/myems diff --git a/admin/app/controllers/login/login.controller.js b/admin/app/controllers/login/login.controller.js index 7eb16420..19502fba 100644 --- a/admin/app/controllers/login/login.controller.js +++ b/admin/app/controllers/login/login.controller.js @@ -7,7 +7,6 @@ app.controller('LoginController', function ($rootScope, $window, $common, $uibModal, - $cookies, $scope, $interval, LoginService, diff --git a/admin/app/controllers/settings/costcenter/cost-file.controller.js b/admin/app/controllers/settings/costcenter/cost-file.controller.js index 11a76ad1..0cad0e27 100644 --- a/admin/app/controllers/settings/costcenter/cost-file.controller.js +++ b/admin/app/controllers/settings/costcenter/cost-file.controller.js @@ -1,6 +1,17 @@ 'use strict'; -app.controller('CostFileController', function ($scope, $common, $translate, $uibModal, $interval, CostFileService, toaster, SweetAlert) { +app.controller('CostFileController', function ( + $scope, + $window, + $common, + $translate, + $uibModal, + $interval, + CostFileService, + toaster, + SweetAlert) { + + $scope.cur_user = JSON.parse($window.localStorage.getItem("currentUser")); $scope.getAllCostFiles = function () { CostFileService.getAllCostFiles(function (error, data) { @@ -17,7 +28,8 @@ app.controller('CostFileController', function ($scope, $common, $translate, $ui url: getAPI() + 'offlinecostfiles', acceptedFiles: '.xlsx', dictDefaultMessage: 'Click(or Drop) to add files', - maxFilesize: '100' + maxFilesize: '100', + headers: { "User-UUID": $scope.cur_user.uuid, "Token": $scope.cur_user.token } }; $scope.dzCallbacks = { diff --git a/admin/app/controllers/settings/knowledgefile/knowledgefile.controller.js b/admin/app/controllers/settings/knowledgefile/knowledgefile.controller.js index 0bdc22a5..e591a6ef 100644 --- a/admin/app/controllers/settings/knowledgefile/knowledgefile.controller.js +++ b/admin/app/controllers/settings/knowledgefile/knowledgefile.controller.js @@ -1,6 +1,16 @@ 'use strict'; -app.controller('KnowledgeFileController', function ($scope, $common, $cookies, $translate, $uibModal, KnowledgeFileService, toaster, SweetAlert) { +app.controller('KnowledgeFileController', function ( + $scope, + $window, + $common, + $translate, + $uibModal, + KnowledgeFileService, + toaster, + SweetAlert) { + + $scope.cur_user = JSON.parse($window.localStorage.getItem("currentUser")); $scope.getAllKnowledgeFiles = function () { KnowledgeFileService.getAllKnowledgeFiles(function (error, data) { @@ -18,7 +28,7 @@ app.controller('KnowledgeFileController', function ($scope, $common, $cookies, $ acceptedFiles: '.xlsx,.xls,.pdf,.docx,.doc,.dwg,.jpg,.png,.csv', dictDefaultMessage: 'Click(or Drop) to add files', maxFilesize: '100', - headers: { "User-UUID": $cookies.get("user_uuid"), "Token": $cookies.get("token") } + headers: { "User-UUID": $scope.cur_user.uuid, "Token": $scope.cur_user.token } }; $scope.dzCallbacks = { diff --git a/admin/app/controllers/settings/meter/offline-meter-file.controller.js b/admin/app/controllers/settings/meter/offline-meter-file.controller.js index 71bd0b9e..99af4854 100644 --- a/admin/app/controllers/settings/meter/offline-meter-file.controller.js +++ b/admin/app/controllers/settings/meter/offline-meter-file.controller.js @@ -1,6 +1,17 @@ 'use strict'; -app.controller('OfflineMeterFileController', function($scope, $common, $cookies, $translate,$uibModal,$interval, OfflineMeterFileService, toaster, SweetAlert) { +app.controller('OfflineMeterFileController', function( + $scope, + $window, + $common, + $translate, + $uibModal, + $interval, + OfflineMeterFileService, + toaster, + SweetAlert) { + + $scope.cur_user = JSON.parse($window.localStorage.getItem("currentUser")); $scope.getAllOfflineMeterFiles = function() { OfflineMeterFileService.getAllOfflineMeterFiles(function(error, data) { @@ -16,9 +27,9 @@ app.controller('OfflineMeterFileController', function($scope, $common, $cookies $scope.dzOptions = { url: getAPI() + 'offlinemeterfiles', acceptedFiles: '.xlsx', - dictDefaultMessage : 'Click(or Drop) to add files', + dictDefaultMessage: 'Click(or Drop) to add files', maxFilesize: '100', - headers: { "User-UUID": $cookies.get("user_uuid"), "Token": $cookies.get("token") } + headers: { "User-UUID": $scope.cur_user.uuid, "Token": $scope.cur_user.token } }; $scope.dzCallbacks = { @@ -27,22 +38,22 @@ app.controller('OfflineMeterFileController', function($scope, $common, $cookies }, 'success': function(file, xhr) { //console.log('File success to upload from dropzone', file, xhr); - var templateName = file.name; + var templateName = file.name; - var popType = 'TOASTER.SUCCESS'; - var popTitle = $common.toaster.success_title; - var popBody = $common.toaster.success_add_body; + var popType = 'TOASTER.SUCCESS'; + var popTitle = $common.toaster.success_title; + var popBody = $common.toaster.success_add_body; - popType = $translate.instant(popType); - popTitle = $translate.instant(popTitle); - popBody = $translate.instant(popBody,{template: templateName}); + popType = $translate.instant(popType); + popTitle = $translate.instant(popTitle); + popBody = $translate.instant(popBody,{template: templateName}); - toaster.pop({ - type: popType, - title: popTitle, - body: popBody, - showCloseButton: true, - }); + toaster.pop({ + type: popType, + title: popTitle, + body: popBody, + showCloseButton: true, + }); // toaster.pop({ // type: 'success', @@ -77,15 +88,15 @@ app.controller('OfflineMeterFileController', function($scope, $common, $cookies $scope.deleteOfflineMeterFile = function(offlinemeterfile) { SweetAlert.swal({ - title: $translate.instant($common.sweet.title), - text: $translate.instant($common.sweet.text), - type: "warning", - showCancelButton: true, - confirmButtonColor: "#DD6B55", - confirmButtonText: $translate.instant($common.sweet.confirmButtonText), - cancelButtonText: $translate.instant($common.sweet.cancelButtonText), - closeOnConfirm: true, - closeOnCancel: true + title: $translate.instant($common.sweet.title), + text: $translate.instant($common.sweet.text), + type: "warning", + showCancelButton: true, + confirmButtonColor: "#DD6B55", + confirmButtonText: $translate.instant($common.sweet.confirmButtonText), + cancelButtonText: $translate.instant($common.sweet.cancelButtonText), + closeOnConfirm: true, + closeOnCancel: true }, function(isConfirm) { if (isConfirm) { diff --git a/admin/app/controllers/settings/space/space.controller.js b/admin/app/controllers/settings/space/space.controller.js index 7f64b949..841b6e5b 100644 --- a/admin/app/controllers/settings/space/space.controller.js +++ b/admin/app/controllers/settings/space/space.controller.js @@ -136,7 +136,9 @@ app.controller('SpaceController', function ($scope, $common, $uibModal, SpaceSer modalInstance.result.then(function (space) { space.timezone_id = space.timezone.id; space.cost_center_id = space.cost_center.id; - space.contact_id = space.contact.id; + if (space.contact != null) { + space.contact_id = space.contact.id; + } SpaceService.addSpace(space, function (error, status) { if (angular.isDefined(status) && status == 201) { var templateName = "COMMON.SPACE"; diff --git a/admin/app/translations.js b/admin/app/translations.js index 2c12e3af..9b78a045 100644 --- a/admin/app/translations.js +++ b/admin/app/translations.js @@ -228,6 +228,7 @@ function config($translateProvider) { ON: 'On', OFF: 'OFF', OK: 'OK', + OPTIONAL: 'Optional', ADD_SPACE: 'Add Space', ADD_TENANT: 'Add Tenant', ADD_STORE: 'Add Store', @@ -387,7 +388,7 @@ function config($translateProvider) { CONTACT: { EMAIL: 'Email', PHONE: 'Phone', - DESCRIPTION: 'Description(Optional)', + DESCRIPTION: 'Description', INPUT_EMAIL: 'Please Input Email', INPUT_PHONE: 'Please Input Phone', INPUT_DESCRIPTION: 'Please Input Description', @@ -453,7 +454,7 @@ function config($translateProvider) { SELECT_DISTRIBUTION_SYSTEM: 'Select Distribution System', SVG: 'SVG', INPUT_SVG: 'Please Input SVG', - DESCRIPTION: 'Description(Optional)', + DESCRIPTION: 'Description', DISTRIBUTION_CIRCUIT: 'Distribution Circuit', N_S_DISTRIBUTION_CIRCUIT: ' Associated Distribution Circuit', ADD_DISTRIBUTION_CIRCUIT: 'Add Distribution Circuit', @@ -483,7 +484,7 @@ function config($translateProvider) { SELECT_EQUIPMENT: 'Please Select Equipment', COST_CENTER: 'Cost Center', SELECT_COST_CENTER: 'Please Select Cost Center', - DESCRIPTION: 'Description(Optional)', + DESCRIPTION: 'Description', INPUT_DESCRIPTION: 'Please Input Description', INPUT_METER: 'Please Input Meter', OUTPUT_METER: 'Output Meter', @@ -512,7 +513,7 @@ function config($translateProvider) { SELECT_COMBINED_EQUIPMENT: 'Please Select Combined Equipment', COST_CENTER: 'Cost Center', SELECT_COST_CENTER: 'Please Select Cost Center', - DESCRIPTION: 'Description(Optional)', + DESCRIPTION: 'Description', INPUT_DESCRIPTION: 'Please Input Description', BIND_EQUIPMENT: 'Bind Equipment', N_S_EQUIPMENT: 'Bound Equipments', @@ -549,7 +550,7 @@ function config($translateProvider) { PARENT_SPACE: 'Parent Space', AREA: 'Area', INPUT_AREA: 'Please Input Area', - DESCRIPTION: 'Description(Optional)', + DESCRIPTION: 'Description', INPUT_DESCRIPTION: 'Please Input Description', CURRENT_SELECTED_SPACE: 'Current Selected Space', CHILD_SPACES: 'Child Spaces', @@ -571,7 +572,7 @@ function config($translateProvider) { LATITUDE: 'Latitude', LONGITUDE: 'Longitude', TYPE: 'Store Type', - DESCRIPTION: 'Description(Optional)', + DESCRIPTION: 'Description', INPUT_ADDRESS: 'Please Input Address', INPUT_LATITUDE: 'Please Input Latitude', INPUT_LONGITUDE: 'Please Input Longitude', @@ -587,7 +588,7 @@ function config($translateProvider) { LEASE_START_DATETIME: 'Lease Start Datetime', LEASE_END_DATETIME: 'Lease End Datetime', IS_IN_LEASE: 'Is In Lease', - DESCRIPTION: 'Description(Optional)', + DESCRIPTION: 'Description', INPUT_BUILDINGS: 'Please Input Buildings', INPUT_FLOORS: 'Please Input Floors', INPUT_ROOMS: 'Rooms', @@ -600,7 +601,7 @@ function config($translateProvider) { SELECT_SHOPFLOOR: 'Select Shopfloor', AREA: 'Area', INPUT_AREA: 'Please Input Area', - DESCRIPTION: 'Description(Optional)', + DESCRIPTION: 'Description', INPUT_DESCRIPTION: 'Please Input Description', BIND_EQUIPMENT: 'Bind Equipment', N_S_EQUIPMENT: 'Bound Equipments', @@ -611,7 +612,7 @@ function config($translateProvider) { INPUT_HOURLY_LOW_LIMIT: 'Please Input Hourly Low Limit', HOURLY_HIGH_LIMIT: 'Hourly High Limit (Inclusive)', INPUT_HOURLY_HIGH_LIMIT: 'Please Input Hourly High Limit', - DESCRIPTION: 'Description(Optional)', + DESCRIPTION: 'Description', INPUT_DESCRIPTION: 'Please Input Description', MASTER_METER: 'Master Meter', SELECT_MASTER_METER: 'Select Master Meter', @@ -622,7 +623,7 @@ function config($translateProvider) { ADD_SENSOR: 'Add Sensor', EDIT_SENSOR: 'Edit Sensor', DELETE_SENSOR: 'Delete Sensor', - DESCRIPTION: 'Description(Optional)', + DESCRIPTION: 'Description', INPUT_DESCRIPTION: 'Please Input Description', SELECT_SENSOR: 'Select Sensor', }, @@ -1275,6 +1276,7 @@ function config($translateProvider) { ON: '打开', OFF: '关闭', OK: '确定', + OPTIONAL: '可选', ADD_SPACE: '添加空间', ADD_TENANT: '添加租户', ADD_STORE: '添加门店', @@ -1444,7 +1446,7 @@ function config($translateProvider) { CONTACT: { EMAIL: '邮箱', PHONE: '电话', - DESCRIPTION: '描述(可选)', + DESCRIPTION: '描述', INPUT_EMAIL: '请输入邮箱', INPUT_PHONE: '请输入电话', INPUT_DESCRIPTION: '请输入描述', @@ -1473,7 +1475,7 @@ function config($translateProvider) { RATIO: '比例系数', IS_TREND: '保存趋势', ADDRESS: '地址(JSON)', - DESCRIPTION: '描述(可选)', + DESCRIPTION: '描述', INPUT_HIGH_LIMIT: '请输入高限', INPUT_LOW_LIMIT: '请输入低限', INPUT_RATIO: '请输入比例系数', @@ -1488,7 +1490,7 @@ function config($translateProvider) { SELECT_DISTRIBUTION_SYSTEM: '请选择配电系统', SVG: 'SVG', INPUT_SVG: '请输入SVG', - DESCRIPTION: '描述(可选)', + DESCRIPTION: '描述', DISTRIBUTION_CIRCUIT: '配电回路', N_S_DISTRIBUTION_CIRCUIT: '所属配电回路', ADD_DISTRIBUTION_CIRCUIT: '添加配电回路', @@ -1540,7 +1542,7 @@ function config($translateProvider) { SELECT_COMBINED_EQUIPMENT: '请选择组合设备', COST_CENTER: '成本中心', SELECT_COST_CENTER: '请选择成本中心', - DESCRIPTION: '描述(可选)', + DESCRIPTION: '描述', BIND_EQUIPMENT: '绑定设备', N_S_EQUIPMENT: '绑定的设备', EQUIPMENT_LIST: '设备列表', @@ -1573,7 +1575,7 @@ function config($translateProvider) { SELECT_EQUIPMENT: '请选择设备', COST_CENTER: '成本中心', SELECT_COST_CENTER: '请选择成本中心', - DESCRIPTION: '描述(可选)', + DESCRIPTION: '描述', INPUT_METER: '请输入表', INPUT_DESCRIPTION: '请输入描述', OUTPUT_METER: '输出表', @@ -1608,7 +1610,7 @@ function config($translateProvider) { PARENT_SPACE: '上级', AREA: '面积', INPUT_AREA: '请输入面积', - DESCRIPTION: '描述(可选)', + DESCRIPTION: '描述', INPUT_DESCRIPTION: '请输入描述', CURRENT_SELECTED_SPACE: '当前选中空间', CHILD_SPACES: '子空间', @@ -1641,7 +1643,7 @@ function config($translateProvider) { LEASE_START_DATETIME: '租赁开始日期时间', LEASE_END_DATETIME: '租赁结束日期时间', IS_IN_LEASE: '是否在租', - DESCRIPTION: '描述(可选)', + DESCRIPTION: '描述', INPUT_BUILDINGS: '请输入建筑', INPUT_FLOORS: '请输入楼层', INPUT_ROOMS: '请输入房间', @@ -1653,7 +1655,7 @@ function config($translateProvider) { LATITUDE: '纬度', LONGITUDE: '经度', TYPE: '门店类型', - DESCRIPTION: '描述(可选)', + DESCRIPTION: '描述', INPUT_ADDRESS: '请输入地址', INPUT_LATITUDE: '请输入纬度', INPUT_LONGITUDE: '请输入经度', @@ -1665,7 +1667,7 @@ function config($translateProvider) { SELECT_SHOPFLOOR: '请选择车间', AREA: '面积', INPUT_AREA: '请输入面积', - DESCRIPTION: '描述(可选)', + DESCRIPTION: '描述', INPUT_DESCRIPTION: '请输入描述', BIND_EQUIPMENT: '绑定设备', N_S_EQUIPMENT: '绑定的设备', @@ -1676,7 +1678,7 @@ function config($translateProvider) { INPUT_HOURLY_LOW_LIMIT: '请输入每小时最小值', HOURLY_HIGH_LIMIT: '每小时最大值(包含)', INPUT_HOURLY_HIGH_LIMIT: '请输入每小时最大值', - DESCRIPTION: '描述(可选)', + DESCRIPTION: '描述', INPUT_DESCRIPTION: '请输入描述', MASTER_METER: '上级计量表', SELECT_MASTER_METER: '选择上级计量表', @@ -1687,7 +1689,7 @@ function config($translateProvider) { ADD_SENSOR: '添加传感器', EDIT_SENSOR: '编辑传感器', DELETE_SENSOR: '删除传感器', - DESCRIPTION: '描述(可选)', + DESCRIPTION: '描述', INPUT_DESCRIPTION: '请输入描述', SELECT_SENSOR: '选择传感器', }, @@ -2322,6 +2324,7 @@ function config($translateProvider) { ON: 'anmachen', OFF: 'Herunterfahren', OK: 'bestimmen', + OPTIONAL: 'Optional', ADD_SPACE: 'Platz hinzufügen', ADD_TENANT: 'Mieter hinzufügen', ADD_STORE: 'Laden hinzufügen', @@ -2491,7 +2494,7 @@ function config($translateProvider) { CONTACT: { EMAIL: 'Briefkasten', PHONE: 'Telefon', - DESCRIPTION: 'Beschreibung (optional)', + DESCRIPTION: 'Beschreibung', INPUT_EMAIL: 'Bitte geben Sie Ihre E-Mail-Adresse ein', INPUT_PHONE: 'Bitte geben Sie das Telefon ein', INPUT_DESCRIPTION: 'Bitte geben Sie eine Beschreibung ein', @@ -2520,7 +2523,7 @@ function config($translateProvider) { RATIO: 'Skalierungsfaktor', IS_TREND: 'Trend speichern', ADDRESS: 'Adresse (JSON)', - DESCRIPTION: 'Beschreibung (optional)', + DESCRIPTION: 'Beschreibung', INPUT_HIGH_LIMIT: 'Bitte geben Sie das obere Limit ein', INPUT_LOW_LIMIT: 'Bitte geben Sie die Untergrenze ein', INPUT_RATIO: 'Bitte geben Sie den Skalierungsfaktor ein', @@ -2535,7 +2538,7 @@ function config($translateProvider) { SELECT_DISTRIBUTION_SYSTEM: 'Bitte wählen Sie das Stromverteilungssystem', SVG: 'SVG', INPUT_SVG: 'Bitte geben Sie SVG ein', - DESCRIPTION: 'Beschreibung (optional)', + DESCRIPTION: 'Beschreibung', DISTRIBUTION_CIRCUIT: 'Verteilerkreis', N_S_DISTRIBUTION_CIRCUIT: 'Eigener Verteilerkreis', ADD_DISTRIBUTION_CIRCUIT: 'Verteilerkreis hinzufügen', @@ -2587,7 +2590,7 @@ function config($translateProvider) { SELECT_COMBINED_EQUIPMENT: 'Bitte wählen Sie ein Kombinationsgerät', COST_CENTER: 'Kostenstelle', SELECT_COST_CENTER: 'Bitte wählen Sie eine Kostenstelle', - DESCRIPTION: 'Beschreibung (optional)', + DESCRIPTION: 'Beschreibung', BIND_EQUIPMENT: 'Gerät binden', N_S_EQUIPMENT: 'Gebundenes Gerät', EQUIPMENT_LIST: 'Geräteliste', @@ -2620,7 +2623,7 @@ function config($translateProvider) { SELECT_EQUIPMENT: 'Bitte wählen Sie ein Gerät', COST_CENTER: 'Kostenstelle', SELECT_COST_CENTER: 'Bitte wählen Sie eine Kostenstelle', - DESCRIPTION: 'Beschreibung (optional)', + DESCRIPTION: 'Beschreibung', INPUT_METER: 'Bitte geben Sie die Tabelle ein', INPUT_DESCRIPTION: 'Bitte geben Sie eine Beschreibung ein', OUTPUT_METER: 'Ausgabetabelle', @@ -2655,7 +2658,7 @@ function config($translateProvider) { PARENT_SPACE: 'Überlegen', AREA: 'Bereich', INPUT_AREA: 'Bitte betreten Sie den Bereich', - DESCRIPTION: 'Beschreibung (optional)', + DESCRIPTION: 'Beschreibung', INPUT_DESCRIPTION: 'Bitte geben Sie eine Beschreibung ein', CURRENT_SELECTED_SPACE: 'Derzeit ausgewählter Platz', CHILD_SPACES: 'Unterraum', @@ -2688,7 +2691,7 @@ function config($translateProvider) { LEASE_START_DATETIME: 'Datum und Uhrzeit des Mietbeginns', LEASE_END_DATETIME: 'Datum und Uhrzeit des Leasingendes', IS_IN_LEASE: 'Mieten Sie?', - DESCRIPTION: 'Beschreibung (optional)', + DESCRIPTION: 'Beschreibun', INPUT_BUILDINGS: 'Bitte betreten Sie das Gebäude', INPUT_FLOORS: 'Bitte betreten Sie den Boden', INPUT_ROOMS: 'Bitte betreten Sie den Raum', @@ -2700,7 +2703,7 @@ function config($translateProvider) { LATITUDE: 'Breite', LONGITUDE: 'Längengrad', TYPE: 'Speichertyp', - DESCRIPTION: 'Beschreibung (optional)', + DESCRIPTION: 'Beschreibung', INPUT_ADDRESS: 'Bitte geben Sie die Adresse ein', INPUT_LATITUDE: 'Bitte geben Sie den Breitengrad ein', INPUT_LONGITUDE: 'Bitte geben Sie den Längengrad ein', @@ -2712,7 +2715,7 @@ function config($translateProvider) { SELECT_SHOPFLOOR: 'Bitte Workshop auswählen', AREA: 'Bereich', INPUT_AREA: 'Bitte betreten Sie den Bereich', - DESCRIPTION: 'Beschreibung (optional)', + DESCRIPTION: 'Beschreibung', INPUT_DESCRIPTION: 'Bitte geben Sie eine Beschreibung ein', BIND_EQUIPMENT: 'Gerät binden', N_S_EQUIPMENT: 'Gebundenes Gerät', @@ -2723,7 +2726,7 @@ function config($translateProvider) { INPUT_HOURLY_LOW_LIMIT: 'Bitte geben Sie das stündliche Minimum ein', HOURLY_HIGH_LIMIT: 'Stundenmaximum (inklusive)', INPUT_HOURLY_HIGH_LIMIT: 'Bitte geben Sie das Stundenmaximum ein', - DESCRIPTION: 'Beschreibung (optional)', + DESCRIPTION: 'Beschreibung', INPUT_DESCRIPTION: 'Bitte geben Sie eine Beschreibung ein', MASTER_METER: 'Überlegenes Messgerät', SELECT_MASTER_METER: 'Wählen Sie das übergeordnete Messgerät aus', @@ -2734,7 +2737,7 @@ function config($translateProvider) { ADD_SENSOR: 'Sensor hinzufügen', EDIT_SENSOR: 'Sensor bearbeiten', DELETE_SENSOR: 'Sensor entfernen', - DESCRIPTION: 'Beschreibung (optional)', + DESCRIPTION: 'Beschreibung', INPUT_DESCRIPTION: 'Bitte geben Sie eine Beschreibung ein', SELECT_SENSOR: 'Sensor auswählen', }, diff --git a/admin/views/common/footer-login.html b/admin/views/common/footer-login.html index 3ceedced..ea45221c 100644 --- a/admin/views/common/footer-login.html +++ b/admin/views/common/footer-login.html @@ -1,5 +1,5 @@ diff --git a/admin/views/common/footer.html b/admin/views/common/footer.html index d5534c93..b241f94c 100644 --- a/admin/views/common/footer.html +++ b/admin/views/common/footer.html @@ -3,6 +3,6 @@ https://myems.io
- {{'MY_EMS_NAME' | translate}} V1.0.7 + {{'MY_EMS_NAME' | translate}} v1.1.0
diff --git a/admin/views/login/login.html b/admin/views/login/login.html index 66e71281..069f81eb 100644 --- a/admin/views/login/login.html +++ b/admin/views/login/login.html @@ -20,6 +20,7 @@
{{'LANGUAGE' | translate}} diff --git a/admin/views/settings/combinedequipment/combinedequipment.html b/admin/views/settings/combinedequipment/combinedequipment.html index 109dd89c..d96692fa 100644 --- a/admin/views/settings/combinedequipment/combinedequipment.html +++ b/admin/views/settings/combinedequipment/combinedequipment.html @@ -17,7 +17,7 @@ {{'SETTING.IS_INPUT_COUNTED' | translate}} {{'SETTING.IS_OUTPUT_COUNTED' | translate}} {{'COMBINED_EQUIPMENT.COST_CENTER' | translate}} - {{'COMBINED_EQUIPMENT.DESCRIPTION' | translate}} + {{'COMBINED_EQUIPMENT.DESCRIPTION' | translate}} ({{'SETTING.OPTIONAL' | translate}}) {{'SETTING.ACTION' | translate}} diff --git a/admin/views/settings/combinedequipment/combinedequipment.model.html b/admin/views/settings/combinedequipment/combinedequipment.model.html index 0e987c87..420c5299 100644 --- a/admin/views/settings/combinedequipment/combinedequipment.model.html +++ b/admin/views/settings/combinedequipment/combinedequipment.model.html @@ -42,7 +42,7 @@
-
+
{{'COMBINED_EQUIPMENT.INPUT_DESCRIPTION' | translate}} diff --git a/admin/views/settings/contact/contact.html b/admin/views/settings/contact/contact.html index fe4d3ed9..b5568580 100644 --- a/admin/views/settings/contact/contact.html +++ b/admin/views/settings/contact/contact.html @@ -15,7 +15,7 @@ {{'SETTING.NAME' | translate}} {{'CONTACT.EMAIL' | translate}} {{'CONTACT.PHONE' | translate}} - {{'CONTACT.DESCRIPTION' | translate}} + {{'CONTACT.DESCRIPTION' | translate}} ({{'SETTING.OPTIONAL' | translate}}) {{'SETTING.ACTION' | translate}} diff --git a/admin/views/settings/contact/contact.model.html b/admin/views/settings/contact/contact.model.html index 5133c9ea..515bb78f 100644 --- a/admin/views/settings/contact/contact.model.html +++ b/admin/views/settings/contact/contact.model.html @@ -33,7 +33,7 @@
-
+
diff --git a/admin/views/settings/datasource/datasource.html b/admin/views/settings/datasource/datasource.html index 2476c26b..93c7bc22 100644 --- a/admin/views/settings/datasource/datasource.html +++ b/admin/views/settings/datasource/datasource.html @@ -71,7 +71,7 @@ {{'POINT.RATIO' | translate}} {{'POINT.IS_TREND' | translate}} {{'POINT.ADDRESS' | translate}} - {{'POINT.DESCRIPTION' | translate}} + {{'POINT.DESCRIPTION' | translate}} ({{'SETTING.OPTIONAL' | translate}}) {{'SETTING.ACTION' | translate}} diff --git a/admin/views/settings/datasource/point.model.html b/admin/views/settings/datasource/point.model.html index 6d0eff16..00c1bc12 100644 --- a/admin/views/settings/datasource/point.model.html +++ b/admin/views/settings/datasource/point.model.html @@ -82,7 +82,7 @@
-
+
diff --git a/admin/views/settings/distributionsystem/distributionsystem.html b/admin/views/settings/distributionsystem/distributionsystem.html index 2ed22e39..5ae1b772 100644 --- a/admin/views/settings/distributionsystem/distributionsystem.html +++ b/admin/views/settings/distributionsystem/distributionsystem.html @@ -13,7 +13,7 @@ {{'SETTING.ID' | translate}} {{'SETTING.NAME' | translate}} {{'DISTRIBUTION_SYSTEM.SVG' | translate}} - {{'DISTRIBUTION_SYSTEM.DESCRIPTION' | translate}} + {{'DISTRIBUTION_SYSTEM.DESCRIPTION' | translate}} ({{'SETTING.OPTIONAL' | translate}}) {{'SETTING.ACTION' | translate}} diff --git a/admin/views/settings/distributionsystem/distributionsystem.model.html b/admin/views/settings/distributionsystem/distributionsystem.model.html index 758843af..d85d0912 100644 --- a/admin/views/settings/distributionsystem/distributionsystem.model.html +++ b/admin/views/settings/distributionsystem/distributionsystem.model.html @@ -20,7 +20,7 @@
-
+
diff --git a/admin/views/settings/equipment/equipment.html b/admin/views/settings/equipment/equipment.html index 30dc6983..abba5542 100644 --- a/admin/views/settings/equipment/equipment.html +++ b/admin/views/settings/equipment/equipment.html @@ -15,7 +15,7 @@ {{'SETTING.IS_INPUT_COUNTED' | translate}} {{'SETTING.IS_OUTPUT_COUNTED' | translate}} {{'EQUIPMENT.COST_CENTER' | translate}} - {{'EQUIPMENT.DESCRIPTION' | translate}} + {{'EQUIPMENT.DESCRIPTION' | translate}} ({{'SETTING.OPTIONAL' | translate}}) {{'SETTING.ACTION' | translate}} diff --git a/admin/views/settings/equipment/equipment.model.html b/admin/views/settings/equipment/equipment.model.html index 970d62bd..2f448f8b 100644 --- a/admin/views/settings/equipment/equipment.model.html +++ b/admin/views/settings/equipment/equipment.model.html @@ -42,7 +42,7 @@
-
+
{{'EQUIPMENT.INPUT_DESCRIPTION' | translate}} diff --git a/admin/views/settings/meter/meter.html b/admin/views/settings/meter/meter.html index ac37e5cf..0f34f7a6 100644 --- a/admin/views/settings/meter/meter.html +++ b/admin/views/settings/meter/meter.html @@ -15,13 +15,13 @@ {{'SETTING.ID' | translate}} {{'SETTING.NAME' | translate}} {{'SETTING.CATEGORY' | translate}} - {{'SETTING.ENERGY_ITEM' | translate}} + {{'SETTING.ENERGY_ITEM' | translate}} ({{'SETTING.OPTIONAL' | translate}}) {{'SETTING.IS_INPUT_COUNTED' | translate}} {{'METER.HOURLY_LOW_LIMIT' | translate}} {{'METER.HOURLY_HIGH_LIMIT' | translate}} {{'SETTING.COSTCENTER' | translate}} - {{'METER.MASTER_METER' | translate}} - {{'METER.DESCRIPTION' | translate}} + {{'METER.MASTER_METER' | translate}} ({{'SETTING.OPTIONAL' | translate}}) + {{'METER.DESCRIPTION' | translate}} ({{'SETTING.OPTIONAL' | translate}}) {{'SETTING.ACTION' | translate}} @@ -167,19 +167,13 @@ {{'SETTING.ID' | translate}} {{'SETTING.NAME' | translate}} {{'SETTING.CATEGORY' | translate}} - {{'SETTING.ENERGY_ITEM' | translate}} - - - {{'SETTING.IS_INPUT_COUNTED' | translate}} - {{'METER.HOURLY_LOW_LIMIT' | translate}} - - - {{'METER.HOURLY_HIGH_LIMIT' | translate}} - {{'SETTING.COSTCENTER' | translate}} - - {{'METER.MASTER_METER' | translate}} - - {{'METER.DESCRIPTION' | translate}} + {{'SETTING.ENERGY_ITEM' | translate}} ({{'SETTING.OPTIONAL' | translate}}) + {{'SETTING.IS_INPUT_COUNTED' | translate}} + {{'METER.HOURLY_LOW_LIMIT' | translate}} + {{'METER.HOURLY_HIGH_LIMIT' | translate}} + {{'SETTING.COSTCENTER' | translate}} + {{'METER.MASTER_METER' | translate}} + {{'METER.DESCRIPTION' | translate}} ({{'SETTING.OPTIONAL' | translate}}) @@ -218,10 +212,10 @@ {{'SETTING.ID' | translate}} {{'SETTING.NAME' | translate}} {{'SETTING.CATEGORY' | translate}} - {{'SETTING.ENERGY_ITEM' | translate}} + {{'SETTING.ENERGY_ITEM' | translate}} ({{'SETTING.OPTIONAL' | translate}}) {{'SETTING.IS_INPUT_COUNTED' | translate}} {{'SETTING.COSTCENTER' | translate}} - {{'METER.DESCRIPTION' | translate}} + {{'METER.DESCRIPTION' | translate}} ({{'SETTING.OPTIONAL' | translate}}) {{'SETTING.ACTION' | translate}} @@ -259,12 +253,12 @@ {{'SETTING.ID' | translate}} {{'SETTING.NAME' | translate}} {{'SETTING.CATEGORY' | translate}} - {{'SETTING.ENERGY_ITEM' | translate}} + {{'SETTING.ENERGY_ITEM' | translate}} ({{'SETTING.OPTIONAL' | translate}}) {{'SETTING.IS_INPUT_COUNTED' | translate}} {{'METER.HOURLY_LOW_LIMIT' | translate}} {{'METER.HOURLY_HIGH_LIMIT' | translate}} {{'SETTING.COSTCENTER' | translate}} - {{'METER.DESCRIPTION' | translate}} + {{'METER.DESCRIPTION' | translate}} ({{'SETTING.OPTIONAL' | translate}}) {{'SETTING.ACTION' | translate}} diff --git a/admin/views/settings/meter/meter.model.html b/admin/views/settings/meter/meter.model.html index 4a892d39..44b8af2f 100644 --- a/admin/views/settings/meter/meter.model.html +++ b/admin/views/settings/meter/meter.model.html @@ -27,7 +27,7 @@
-
+
{{$select.selected.name}} @@ -79,7 +79,7 @@
-
+
{{$select.selected.name}} @@ -93,7 +93,7 @@
-
+
diff --git a/admin/views/settings/meter/offline-meter.model.html b/admin/views/settings/meter/offline-meter.model.html index 67c254e3..ed260dcf 100644 --- a/admin/views/settings/meter/offline-meter.model.html +++ b/admin/views/settings/meter/offline-meter.model.html @@ -27,7 +27,7 @@
-
+
{{$select.selected.name}} @@ -81,7 +81,7 @@
-
+
diff --git a/admin/views/settings/meter/virtual-meter.model.html b/admin/views/settings/meter/virtual-meter.model.html index 048daa9b..e32108f3 100644 --- a/admin/views/settings/meter/virtual-meter.model.html +++ b/admin/views/settings/meter/virtual-meter.model.html @@ -30,7 +30,7 @@
-
+
{{$select.selected.name}} @@ -76,7 +76,7 @@
-
+
diff --git a/admin/views/settings/sensor/sensor.html b/admin/views/settings/sensor/sensor.html index 9818c887..94c64ec2 100644 --- a/admin/views/settings/sensor/sensor.html +++ b/admin/views/settings/sensor/sensor.html @@ -13,7 +13,7 @@ {{'SETTING.ID' | translate}} {{'SETTING.NAME' | translate}} - {{'SENSOR.DESCRIPTION' | translate}} + {{'SENSOR.DESCRIPTION' | translate}} ({{'SETTING.OPTIONAL' | translate}}) {{'SETTING.ACTION' | translate}} diff --git a/admin/views/settings/sensor/sensor.model.html b/admin/views/settings/sensor/sensor.model.html index 66385c6f..e7f7165d 100644 --- a/admin/views/settings/sensor/sensor.model.html +++ b/admin/views/settings/sensor/sensor.model.html @@ -13,7 +13,7 @@
-
+
diff --git a/admin/views/settings/shopfloor/shopfloor.html b/admin/views/settings/shopfloor/shopfloor.html index 94c8e4fe..b1243cde 100644 --- a/admin/views/settings/shopfloor/shopfloor.html +++ b/admin/views/settings/shopfloor/shopfloor.html @@ -17,7 +17,7 @@ {{'SETTING.CONTACT' | translate}} {{'SETTING.IS_INPUT_COUNTED' | translate}} {{'SETTING.COSTCENTER' | translate}} - {{'SHOPFLOOR.DESCRIPTION' | translate}} + {{'SHOPFLOOR.DESCRIPTION' | translate}} ({{'SETTING.OPTIONAL' | translate}}) {{'SETTING.ACTION' | translate}} diff --git a/admin/views/settings/shopfloor/shopfloor.model.html b/admin/views/settings/shopfloor/shopfloor.model.html index f0f0cc94..8951b162 100644 --- a/admin/views/settings/shopfloor/shopfloor.model.html +++ b/admin/views/settings/shopfloor/shopfloor.model.html @@ -54,7 +54,7 @@
-
+
diff --git a/admin/views/settings/space/space.html b/admin/views/settings/space/space.html index e56ae709..ed380e84 100644 --- a/admin/views/settings/space/space.html +++ b/admin/views/settings/space/space.html @@ -40,7 +40,7 @@ {{'SETTING.IS_OUTPUT_COUNTED' | translate}} {{'SETTING.COSTCENTER' | translate}} - {{'SPACE.DESCRIPTION' | translate}} + {{'SPACE.DESCRIPTION' | translate}} ({{'SETTING.OPTIONAL' | translate}}) {{'SETTING.ACTION' | translate}} @@ -94,7 +94,7 @@ {{'SETTING.IS_OUTPUT_COUNTED' | translate}} {{'SETTING.COSTCENTER' | translate}} - {{'SPACE.DESCRIPTION' | translate}} + {{'SPACE.DESCRIPTION' | translate}} ({{'SETTING.OPTIONAL' | translate}}) {{'SETTING.ACTION' | translate}} diff --git a/admin/views/settings/space/space.model.html b/admin/views/settings/space/space.model.html index 007eb02d..ad044385 100644 --- a/admin/views/settings/space/space.model.html +++ b/admin/views/settings/space/space.model.html @@ -28,10 +28,10 @@
-
+
- + {{$select.selected.name}}
@@ -101,7 +101,7 @@
-
+
{{'SETTING.CONTACT' | translate}} {{'SETTING.IS_INPUT_COUNTED' | translate}} {{'SETTING.COSTCENTER' | translate}} - {{'STORE.DESCRIPTION' | translate}} + {{'STORE.DESCRIPTION' | translate}} ({{'SETTING.OPTIONAL' | translate}}) {{'SETTING.ACTION' | translate}} diff --git a/admin/views/settings/store/store.model.html b/admin/views/settings/store/store.model.html index 791990b8..2c535c1b 100644 --- a/admin/views/settings/store/store.model.html +++ b/admin/views/settings/store/store.model.html @@ -90,7 +90,7 @@
-
+
diff --git a/admin/views/settings/tenant/tenant.html b/admin/views/settings/tenant/tenant.html index 2791c3bd..48c615ba 100644 --- a/admin/views/settings/tenant/tenant.html +++ b/admin/views/settings/tenant/tenant.html @@ -26,7 +26,7 @@ {{'TENANT.LEASE_END_DATETIME' | translate}} {{'TENANT.IS_IN_LEASE' | translate}} {{'SETTING.COSTCENTER' | translate}} - {{'TENANT.DESCRIPTION' | translate}} + {{'TENANT.DESCRIPTION' | translate}} ({{'SETTING.OPTIONAL' | translate}}) {{'SETTING.ACTION' | translate}} diff --git a/admin/views/settings/tenant/tenant.model.html b/admin/views/settings/tenant/tenant.model.html index 2fa837b9..486047bd 100644 --- a/admin/views/settings/tenant/tenant.model.html +++ b/admin/views/settings/tenant/tenant.model.html @@ -124,7 +124,7 @@
-
+
diff --git a/database/myems_fdd_db.sql b/database/myems_fdd_db.sql index 39ee7567..caac4aac 100644 --- a/database/myems_fdd_db.sql +++ b/database/myems_fdd_db.sql @@ -72,13 +72,15 @@ CREATE TABLE IF NOT EXISTS `myems_fdd_db`.`tbl_rules` ( `id` BIGINT NOT NULL AUTO_INCREMENT, `name` VARCHAR(128) NOT NULL, `uuid` CHAR(36) NOT NULL, - `fdd_code` VARCHAR(128) NOT NULL COMMENT 'SYSTEM01, SYSTEM02, ... SPACE01, SPACE02, ... METER01, METER02, ...', - `category` VARCHAR(128) NOT NULL COMMENT 'SYSTEM, SPACE, METER, TENANT, STORE, SHOPFLOOR, EQUIPMENT, COMBINEDEQUIPMENT', + `category` VARCHAR(128) NOT NULL COMMENT 'REALTIME, SYSTEM, SPACE, METER, TENANT, STORE, SHOPFLOOR, EQUIPMENT, COMBINEDEQUIPMENT', + `fdd_code` VARCHAR(128) NOT NULL COMMENT 'REALTIME01, REALTIME01... SYSTEM01, SYSTEM02, ... SPACE01, SPACE02, ... METER01, METER02, ...', `priority` VARCHAR(128) NOT NULL COMMENT 'CRITICAL, HIGH, MEDIUM, LOW', `channel` VARCHAR(128) NOT NULL COMMENT 'WEB, EMAIL, SMS, WECHAT, CALL', `expression` JSON NOT NULL COMMENT 'JSON string of diagnosed objects, points, values, and recipients', `message_template` TEXT NOT NULL COMMENT 'Plain text template that supports $-substitutions', `is_enabled` BOOL NOT NULL, + `last_run_datetime_utc` DATETIME, + `next_run_datetime_utc` DATETIME, PRIMARY KEY (`id`)); CREATE INDEX `tbl_rules_index_1` ON `myems_fdd_db`.`tbl_rules` (`name`); diff --git a/database/myems_system_db.sql b/database/myems_system_db.sql index f257c121..10629e9e 100644 --- a/database/myems_system_db.sql +++ b/database/myems_system_db.sql @@ -1686,7 +1686,7 @@ USE `myems_system_db`; INSERT INTO `myems_system_db`.`tbl_stores` (`id`, `name`, `uuid`, `address`, `latitude`, `longitude`, `area`, `store_type_id`, `is_input_counted`, `contact_id`, `cost_center_id`, `description`) VALUES - (1, '麦当劳(祈年大街得来速店)', 'd8a24322-4bab-4ba2-aedc-5d55a84c3db8', '北京市东城区东打磨厂街7号', 39.899493, 116.412041, 500.000, 1, true, 1, 1, 'MacDonald\'s'); + (1, '麦当劳(祈年大街得来速店)', 'd8a24322-4bab-4ba2-aedc-5d55a84c3db8', '北京市东城区东打磨厂街7号', 39.899493, 116.412041, 500.000, 1, true, 1, 1, 'MacDonalds'); COMMIT; -- --------------------------------------------------------------------------------------------------------------------- @@ -2249,6 +2249,6 @@ USE `myems_system_db`; INSERT INTO `myems_system_db`.`tbl_versions` (`id`, `version`, `release_date`) VALUES -(1, '1.0.5', '2021-02-23'); +(1, '1.1.0', '2021-03-18'); COMMIT; diff --git a/database/upgrade1.0.8.sql b/database/upgrade1.0.8.sql new file mode 100644 index 00000000..4f79b759 --- /dev/null +++ b/database/upgrade1.0.8.sql @@ -0,0 +1,3 @@ + +-- UPDATE VERSION NUMBER +UPDATE myems_system_db.tbl_versions SET version='1.0.8', release_date='2021-03-11' WHERE id=1; diff --git a/database/upgrade1.1.0.sql b/database/upgrade1.1.0.sql new file mode 100644 index 00000000..9b2b5ee4 --- /dev/null +++ b/database/upgrade1.1.0.sql @@ -0,0 +1,3 @@ + +-- UPDATE VERSION NUMBER +UPDATE myems_system_db.tbl_versions SET version='1.1.0', release_date='2021-03-18' WHERE id=1; diff --git a/database/upgrade1.1.1.sql b/database/upgrade1.1.1.sql new file mode 100644 index 00000000..5c088f81 --- /dev/null +++ b/database/upgrade1.1.1.sql @@ -0,0 +1,6 @@ + +-- UPDATE VERSION NUMBER +UPDATE myems_system_db.tbl_versions SET version='1.1.1', release_date='2021-03-22' WHERE id=1; + +ALTER TABLE myems_fdd_db.tbl_rules ADD last_run_datetime_utc DATETIME NULL; +ALTER TABLE myems_fdd_db.tbl_rules ADD next_run_datetime_utc DATETIME NULL; diff --git a/docs/images/myems-large-screen-dashboard.gif b/docs/images/myems-large-screen-dashboard.gif new file mode 100644 index 00000000..da0cd75e Binary files /dev/null and b/docs/images/myems-large-screen-dashboard.gif differ diff --git a/docs/images/myems-space-energycategory1.gif b/docs/images/myems-space-energycategory1.gif new file mode 100644 index 00000000..6fa2bdf9 Binary files /dev/null and b/docs/images/myems-space-energycategory1.gif differ diff --git a/docs/images/myems-space-energycategory2.gif b/docs/images/myems-space-energycategory2.gif new file mode 100644 index 00000000..ff33b633 Binary files /dev/null and b/docs/images/myems-space-energycategory2.gif differ diff --git a/docs/images/myems-space-energycategory3.gif b/docs/images/myems-space-energycategory3.gif new file mode 100644 index 00000000..6b507359 Binary files /dev/null and b/docs/images/myems-space-energycategory3.gif differ diff --git a/docs/images/screenshot-2020.12.01-16_53_12.png b/docs/images/screenshot-2020.12.01-16_53_12.png deleted file mode 100644 index 4035d44a..00000000 Binary files a/docs/images/screenshot-2020.12.01-16_53_12.png and /dev/null differ diff --git a/myems-aggregation/combined_equipment_energy_input_category.py b/myems-aggregation/combined_equipment_energy_input_category.py index b03a93eb..bbca4468 100644 --- a/myems-aggregation/combined_equipment_energy_input_category.py +++ b/myems-aggregation/combined_equipment_energy_input_category.py @@ -207,13 +207,12 @@ def worker(combined_equipment): except Exception as e: error_string = "Error in step 3.1 of combined_equipment_energy_input_category.worker " + str(e) - print(error_string) - return error_string - finally: if cursor_system_db: cursor_system_db.close() if cnx_system_db: cnx_system_db.close() + print(error_string) + return error_string #################################################################################################################### # Step 4: get all equipments associated with the combined equipment diff --git a/myems-aggregation/combined_equipment_energy_input_item.py b/myems-aggregation/combined_equipment_energy_input_item.py index 570b4bf5..f91f3a50 100644 --- a/myems-aggregation/combined_equipment_energy_input_item.py +++ b/myems-aggregation/combined_equipment_energy_input_item.py @@ -210,13 +210,12 @@ def worker(combined_equipment): except Exception as e: error_string = "Error in step 3.1 of combined_equipment_energy_input_item.worker " + str(e) - print(error_string) - return error_string - finally: if cursor_system_db: cursor_system_db.close() if cnx_system_db: cnx_system_db.close() + print(error_string) + return error_string #################################################################################################################### # Step 4: get all equipments associated with the combined equipment @@ -412,7 +411,7 @@ def worker(combined_equipment): try: for equipment in equipment_list: equipment_id = str(equipment['id']) - query = (" SELECT start_datetime_utc, energy_category_id, actual_value " + query = (" SELECT start_datetime_utc, energy_item_id, actual_value " " FROM tbl_equipment_input_item_hourly " " WHERE equipment_id = %s " " AND start_datetime_utc >= %s " @@ -428,9 +427,9 @@ def worker(combined_equipment): current_datetime_utc = row_value[0] if current_datetime_utc not in energy_equipment_hourly[equipment_id]: energy_equipment_hourly[equipment_id][current_datetime_utc] = dict() - energy_category_id = row_value[1] + energy_item_id = row_value[1] actual_value = row_value[2] - energy_equipment_hourly[equipment_id][current_datetime_utc][energy_category_id] = \ + energy_equipment_hourly[equipment_id][current_datetime_utc][energy_item_id] = \ actual_value except Exception as e: error_string = "Error in step 9 of combined_equipment_energy_input_item.worker " + str(e) @@ -564,9 +563,9 @@ def worker(combined_equipment): equipment_id = str(equipment['id']) meta_data_dict = energy_equipment_hourly[equipment_id].get(current_datetime_utc, None) if meta_data_dict is not None and len(meta_data_dict) > 0: - for energy_category_id, actual_value in meta_data_dict.items(): - aggregated_value['meta_data'][energy_category_id] = \ - aggregated_value['meta_data'].get(energy_category_id, Decimal(0.0)) + actual_value + for energy_item_id, actual_value in meta_data_dict.items(): + aggregated_value['meta_data'][energy_item_id] = \ + aggregated_value['meta_data'].get(energy_item_id, Decimal(0.0)) + actual_value aggregated_values.append(aggregated_value) diff --git a/myems-aggregation/combined_equipment_energy_output_category.py b/myems-aggregation/combined_equipment_energy_output_category.py index d3aa50ff..7eb7acc8 100644 --- a/myems-aggregation/combined_equipment_energy_output_category.py +++ b/myems-aggregation/combined_equipment_energy_output_category.py @@ -207,13 +207,12 @@ def worker(combined_equipment): except Exception as e: error_string = "Error in step 3.1 of combined_equipment_energy_output_category.worker " + str(e) - print(error_string) - return error_string - finally: if cursor_system_db: cursor_system_db.close() if cnx_system_db: cnx_system_db.close() + print(error_string) + return error_string #################################################################################################################### # Step 4: get all equipments associated with the combined equipment diff --git a/myems-api/README.md b/myems-api/README.md index 6af162ae..dcd86d63 100644 --- a/myems-api/README.md +++ b/myems-api/README.md @@ -1164,13 +1164,16 @@ Result in JSON | id | integer | Rule ID | | name | string | Rule Name | | uuid | string | Rule UUID | -| fdd_code | string | SYSTEM01, SYSTEM02, ... SPACE01, SPACE02, ... METER01, METER02, ... | -| category | string | SYSTEM, SPACE, METER, TENANT, STORE, SHOPFLOOR, EQUIPMENT, COMBINEDEQUIPMENT | +| fdd_code | string | SYSTEM01, SYSTEM02, ..., REALTIME01, REALTIME02, ..., SPACE01, SPACE02, ... METER01, METER02, ... | +| category | string | SYSTEM, REALTIME, SPACE, METER, TENANT, STORE, SHOPFLOOR, EQUIPMENT, COMBINEDEQUIPMENT | | priority | string | CRITICAL, HIGH, MEDIUM, LOW | | channel | string | WEB, EMAIL, SMS, WECHAT, CALL | | expression | string | JSON string of diagnosed objects, points, values, and recipients | | message_template | string | Plain text template that supports $-substitutions | | is_enabled | boolean | Indicates if this rule is enabled | +| last_run_datetime | float | null, or the number of milliseconds since January 1, 1970, 00:00:00, universal time | +| next_run_datetime | float | null, or the number of milliseconds since January 1, 1970, 00:00:00, universal time | + ```bash $ curl -i -X GET {{base_url}}/rules/{id} diff --git a/myems-api/core/offlinemeterfile.py b/myems-api/core/offlinemeterfile.py index 10d779a5..37de469b 100644 --- a/myems-api/core/offlinemeterfile.py +++ b/myems-api/core/offlinemeterfile.py @@ -208,8 +208,8 @@ class OfflineMeterFileItem: # remove the file from disk os.remove(file_path) except Exception as ex: - raise falcon.HTTPError(falcon.HTTP_400, title='API.ERROR', - description='API.OFFLINE_METER_FILE_NOT_FOUND') + # ignore exception and don't return API.OFFLINE_METER_FILE_NOT_FOUND error + pass # Note: the energy data imported from the deleted file will not be deleted cursor.execute(" DELETE FROM tbl_offline_meter_files WHERE id = %s ", (id_,)) diff --git a/myems-api/core/rule.py b/myems-api/core/rule.py index b7aa8865..e1c64102 100644 --- a/myems-api/core/rule.py +++ b/myems-api/core/rule.py @@ -1,8 +1,9 @@ import falcon import json import mysql.connector -import config import uuid +from datetime import datetime, timezone, timedelta +import config class RuleCollection: @@ -20,9 +21,9 @@ class RuleCollection: cursor = cnx.cursor(dictionary=True) query = (" SELECT id, name, uuid, " - " fdd_code, category, priority, " + " category, fdd_code, priority, " " channel, expression, message_template, " - " is_enabled " + " is_enabled, last_run_datetime_utc, next_run_datetime_utc " " FROM tbl_rules " " ORDER BY id ") cursor.execute(query) @@ -33,11 +34,22 @@ class RuleCollection: result = list() if rows is not None and len(rows) > 0: for row in rows: + last_run_datetime = None + if row['last_run_datetime_utc'] is not None: + last_run_datetime = row['last_run_datetime_utc'].replace(tzinfo=timezone.utc).timestamp() * 1000 + + next_run_datetime = None + if row['next_run_datetime_utc'] is not None: + next_run_datetime = row['next_run_datetime_utc'].replace(tzinfo=timezone.utc).timestamp() * 1000 + meta_result = {"id": row['id'], "name": row['name'], "uuid": row['uuid'], - "fdd_code": row['fdd_code'], "category": row['category'], "priority": row['priority'], + "category": row['category'], "fdd_code": row['fdd_code'], "priority": row['priority'], "channel": row['channel'], "expression": row['expression'], "message_template": row['message_template'].replace("
", ""), - "is_enabled": bool(row['is_enabled'])} + "is_enabled": bool(row['is_enabled']), + "last_run_datetime": last_run_datetime, + "next_run_datetime": next_run_datetime, + } result.append(meta_result) resp.body = json.dumps(result) @@ -58,6 +70,17 @@ class RuleCollection: description='API.INVALID_RULE_NAME') name = str.strip(new_values['data']['name']) + if 'category' not in new_values['data'].keys() or \ + not isinstance(new_values['data']['category'], str) or \ + len(str.strip(new_values['data']['category'])) == 0 or \ + str.strip(new_values['data']['category']) not in \ + ('SYSTEM', 'REALTIME', 'SPACE', 'METER', 'TENANT', 'STORE', 'SHOPFLOOR', 'EQUIPMENT', + 'COMBINEDEQUIPMENT'): + raise falcon.HTTPError(falcon.HTTP_400, + title='API.BAD_REQUEST', + description='API.INVALID_CATEGORY') + category = str.strip(new_values['data']['category']) + if 'fdd_code' not in new_values['data'].keys() or \ not isinstance(new_values['data']['fdd_code'], str) or \ len(str.strip(new_values['data']['fdd_code'])) == 0: @@ -66,16 +89,6 @@ class RuleCollection: description='API.INVALID_FDD_CODE') fdd_code = str.strip(new_values['data']['fdd_code']) - if 'category' not in new_values['data'].keys() or \ - not isinstance(new_values['data']['category'], str) or \ - len(str.strip(new_values['data']['category'])) == 0 or \ - str.strip(new_values['data']['category']) not in \ - ('SYSTEM', 'SPACE', 'METER', 'TENANT', 'STORE', 'SHOPFLOOR', 'EQUIPMENT', 'COMBINEDEQUIPMENT'): - raise falcon.HTTPError(falcon.HTTP_400, - title='API.BAD_REQUEST', - description='API.INVALID_CATEGORY') - category = str.strip(new_values['data']['category']) - if 'priority' not in new_values['data'].keys() or \ not isinstance(new_values['data']['priority'], str) or \ len(str.strip(new_values['data']['priority'])) == 0 or \ @@ -171,7 +184,8 @@ class RuleItem: query = (" SELECT id, name, uuid, " " fdd_code, category, priority, " - " channel, expression, message_template, is_enabled " + " channel, expression, message_template, " + " is_enabled, last_run_datetime_utc, next_run_datetime_utc " " FROM tbl_rules " " WHERE id = %s ") cursor.execute(query, (id_,)) @@ -181,12 +195,22 @@ class RuleItem: if row is None: raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.RULE_NOT_FOUND') + last_run_datetime = None + if row['last_run_datetime_utc'] is not None: + last_run_datetime = row['last_run_datetime_utc'].replace(tzinfo=timezone.utc).timestamp() * 1000 + + next_run_datetime = None + if row['next_run_datetime_utc'] is not None: + next_run_datetime = row['next_run_datetime_utc'].replace(tzinfo=timezone.utc).timestamp() * 1000 result = {"id": row['id'], "name": row['name'], "uuid": row['uuid'], "fdd_code": row['fdd_code'], "category": row['category'], "priority": row['priority'], "channel": row['channel'], "expression": row['expression'], "message_template": row['message_template'].replace("
", ""), - "is_enabled": bool(row['is_enabled'])} + "is_enabled": bool(row['is_enabled']), + "last_run_datetime": last_run_datetime, + "next_run_datetime": next_run_datetime, + } resp.body = json.dumps(result) @staticmethod @@ -236,6 +260,17 @@ class RuleItem: description='API.INVALID_RULE_NAME') name = str.strip(new_values['data']['name']) + if 'category' not in new_values['data'].keys() or \ + not isinstance(new_values['data']['category'], str) or \ + len(str.strip(new_values['data']['category'])) == 0 or \ + str.strip(new_values['data']['category']) not in \ + ('SYSTEM', 'REALTIME', 'SPACE', 'METER', 'TENANT', 'STORE', 'SHOPFLOOR', 'EQUIPMENT', + 'COMBINEDEQUIPMENT'): + raise falcon.HTTPError(falcon.HTTP_400, + title='API.BAD_REQUEST', + description='API.INVALID_CATEGORY') + category = str.strip(new_values['data']['category']) + if 'fdd_code' not in new_values['data'].keys() or \ not isinstance(new_values['data']['fdd_code'], str) or \ len(str.strip(new_values['data']['fdd_code'])) == 0: @@ -244,16 +279,6 @@ class RuleItem: description='API.INVALID_FDD_CODE') fdd_code = str.strip(new_values['data']['fdd_code']) - if 'category' not in new_values['data'].keys() or \ - not isinstance(new_values['data']['category'], str) or \ - len(str.strip(new_values['data']['category'])) == 0 or \ - str.strip(new_values['data']['category']) not in \ - ('SYSTEM', 'SPACE', 'METER', 'TENANT', 'STORE', 'SHOPFLOOR', 'EQUIPMENT', 'COMBINEDEQUIPMENT'): - raise falcon.HTTPError(falcon.HTTP_400, - title='API.BAD_REQUEST', - description='API.INVALID_CATEGORY') - category = str.strip(new_values['data']['category']) - if 'priority' not in new_values['data'].keys() or \ not isinstance(new_values['data']['priority'], str) or \ len(str.strip(new_values['data']['priority'])) == 0 or \ diff --git a/myems-api/core/space.py b/myems-api/core/space.py index c4831f25..f4838553 100644 --- a/myems-api/core/space.py +++ b/myems-api/core/space.py @@ -567,7 +567,7 @@ class SpaceItem: description='API.INVALID_IS_OUTPUT_COUNTED_VALUE') is_output_counted = new_values['data']['is_output_counted'] - if 'contact_id' in new_values['data'].keys(): + if 'contact_id' in new_values['data'].keys() and new_values['data']['contact_id'] is not None: if new_values['data']['contact_id'] <= 0: raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', description='API.INVALID_CONTACT_ID') @@ -608,7 +608,7 @@ class SpaceItem: if cursor.fetchone() is not None: cursor.close() cnx.disconnect() - raise falcon.HTTPError(falcon.HTTP_404, title='API.BAD_REQUEST', + raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', description='API.SPACE_NAME_IS_ALREADY_IN_USE') if parent_space_id is not None: diff --git a/myems-api/core/user.py b/myems-api/core/user.py index d39e8a5d..e1c30418 100644 --- a/myems-api/core/user.py +++ b/myems-api/core/user.py @@ -432,7 +432,7 @@ class UserLogin: " VALUES (%s, %s, %s) ") user_uuid = result['uuid'] token = hashlib.sha1(os.urandom(24)).hexdigest() - utc_expires = datetime.utcnow() + timedelta(seconds=1000 * 60 * 60 * 8) + utc_expires = datetime.utcnow() + timedelta(seconds=60 * 60 * 8) cursor.execute(add_session, (user_uuid, token, utc_expires)) cnx.commit() cursor.close() diff --git a/myems-api/core/version.py b/myems-api/core/version.py index 041ded6e..f1ef5dfa 100644 --- a/myems-api/core/version.py +++ b/myems-api/core/version.py @@ -14,8 +14,8 @@ class VersionItem: @staticmethod def on_get(req, resp): - result = {"version": 'MyEMS 1.0.7 (Community Edition)', - "release-date": '20210307', + result = {"version": 'MyEMS 1.1.0 (Community Edition)', + "release-date": '202103018', "website": "https://myems.io"} resp.body = json.dumps(result) diff --git a/myems-api/excelexporters/combinedequipmentefficiency.py b/myems-api/excelexporters/combinedequipmentefficiency.py new file mode 100644 index 00000000..d91e620d --- /dev/null +++ b/myems-api/excelexporters/combinedequipmentefficiency.py @@ -0,0 +1,603 @@ +import base64 +import uuid +import os +from openpyxl.chart import ( + PieChart, + LineChart, + BarChart, + Reference, +) +from openpyxl.styles import PatternFill, Border, Side, Alignment, Font +from openpyxl.drawing.image import Image +from openpyxl import Workbook +from openpyxl.chart.label import DataLabelList +import openpyxl.utils.cell as format_cell + + +#################################################################################################################### +# PROCEDURES +# Step 1: Validate the report data +# Step 2: Generate excel file +# Step 3: Encode the excel file bytes to Base64 +#################################################################################################################### + + +def export(report, + name, + reporting_start_datetime_local, + reporting_end_datetime_local, + period_type): + #################################################################################################################### + # Step 1: Validate the report data + #################################################################################################################### + if report is None: + return None + print(report) + + #################################################################################################################### + # Step 2: Generate excel file from the report data + #################################################################################################################### + filename = generate_excel(report, + name, + reporting_start_datetime_local, + reporting_end_datetime_local, + period_type) + #################################################################################################################### + # Step 3: Encode the excel file to Base64 + #################################################################################################################### + try: + with open(filename, 'rb') as binary_file: + binary_file_data = binary_file.read() + except IOError as ex: + pass + + # Base64 encode the bytes + base64_encoded_data = base64.b64encode(binary_file_data) + # get the Base64 encoded data using human-readable characters. + base64_message = base64_encoded_data.decode('utf-8') + # delete the file from server + try: + os.remove(filename) + except NotImplementedError as ex: + pass + return base64_message + + +def generate_excel(report, + name, + reporting_start_datetime_local, + reporting_end_datetime_local, + period_type): + wb = Workbook() + ws = wb.active + + # Row height + ws.row_dimensions[1].height = 102 + for i in range(2, 2000 + 1): + ws.row_dimensions[i].height = 42 + + # Col width + ws.column_dimensions['A'].width = 1.5 + + ws.column_dimensions['B'].width = 25.0 + + for i in range(ord('C'), ord('L')): + ws.column_dimensions[chr(i)].width = 15.0 + + # Font + name_font = Font(name='Constantia', size=15, bold=True) + title_font = Font(name='宋体', size=15, bold=True) + data_font = Font(name='Franklin Gothic Book', size=11) + + table_fill = PatternFill(fill_type='solid', fgColor='1F497D') + f_border = Border(left=Side(border_style='medium', color='00000000'), + right=Side(border_style='medium', color='00000000'), + bottom=Side(border_style='medium', color='00000000'), + top=Side(border_style='medium', color='00000000') + ) + b_border = Border( + bottom=Side(border_style='medium', color='00000000'), + ) + + b_c_alignment = Alignment(vertical='bottom', + horizontal='center', + text_rotation=0, + wrap_text=True, + shrink_to_fit=False, + indent=0) + c_c_alignment = Alignment(vertical='center', + horizontal='center', + text_rotation=0, + wrap_text=True, + shrink_to_fit=False, + indent=0) + b_r_alignment = Alignment(vertical='bottom', + horizontal='right', + text_rotation=0, + wrap_text=True, + shrink_to_fit=False, + indent=0) + c_r_alignment = Alignment(vertical='bottom', + horizontal='center', + text_rotation=0, + wrap_text=True, + shrink_to_fit=False, + indent=0) + # Img + img = Image("excelexporters/myems.png") + img.width = img.width * 0.85 + img.height = img.height * 0.85 + # img = Image("myems.png") + ws.add_image(img, 'B1') + + # Title + ws.row_dimensions[3].height = 60 + + ws['B3'].font = name_font + ws['B3'].alignment = b_r_alignment + ws['B3'] = 'Name:' + ws['C3'].border = b_border + ws['C3'].alignment = b_c_alignment + ws['C3'].font = name_font + ws['C3'] = name + + ws['D3'].font = name_font + ws['D3'].alignment = b_r_alignment + ws['D3'] = 'Period:' + ws['E3'].border = b_border + ws['E3'].alignment = b_c_alignment + ws['E3'].font = name_font + ws['E3'] = period_type + + ws['F3'].font = name_font + ws['F3'].alignment = b_r_alignment + ws['F3'] = 'Date:' + ws['G3'].border = b_border + ws['G3'].alignment = b_c_alignment + ws['G3'].font = name_font + ws['G3'] = reporting_start_datetime_local + "__" + reporting_end_datetime_local + ws.merge_cells("G3:H3") + + if "reporting_period_efficiency" not in report.keys() or \ + "names" not in report['reporting_period_efficiency'].keys() or len( + report['reporting_period_efficiency']['names']) == 0: + filename = str(uuid.uuid4()) + '.xlsx' + wb.save(filename) + + return filename + + ################################## + + current_row_number = 6 + + reporting_period_data = report['reporting_period_efficiency'] + + has_names_data_flag = True + + if "names" not in reporting_period_data.keys() or \ + reporting_period_data['names'] is None or \ + len(reporting_period_data['names']) == 0: + has_names_data_flag = False + + if has_names_data_flag: + ws['B' + str(current_row_number)].font = title_font + ws['B' + str(current_row_number)] = name + ' 报告期累积效率' + + current_row_number += 1 + + category = reporting_period_data['names'] + ca_len = len(category) + + ws.row_dimensions[current_row_number].height = 80 + ws['B' + str(current_row_number)].fill = table_fill + ws['B' + str(current_row_number)].border = f_border + + col = 'C' + + for i in range(0, ca_len): + ws[col + str(current_row_number)].fill = table_fill + ws[col + str(current_row_number)].font = name_font + ws[col + str(current_row_number)].alignment = c_c_alignment + ws[col + str(current_row_number)].border = f_border + ws[col + str(current_row_number)] = \ + reporting_period_data['names'][i] + " (" + reporting_period_data['units'][i] + ")" + + col = chr(ord(col) + 1) + + current_row_number += 1 + + ws['B' + str(current_row_number)].font = title_font + ws['B' + str(current_row_number)].alignment = c_c_alignment + ws['B' + str(current_row_number)].border = f_border + ws['B' + str(current_row_number)] = '累积效率' + + col = 'C' + + for i in range(0, ca_len): + ws[col + str(current_row_number)].font = name_font + ws[col + str(current_row_number)].alignment = c_c_alignment + ws[col + str(current_row_number)].border = f_border + ws[col + str(current_row_number)] = round(reporting_period_data['cumulations'][i], 2) + + col = chr(ord(col) + 1) + + current_row_number += 1 + + ws['B' + str(current_row_number)].font = title_font + ws['B' + str(current_row_number)].alignment = c_c_alignment + ws['B' + str(current_row_number)].border = f_border + ws['B' + str(current_row_number)] = '环比' + + col = 'C' + + for i in range(0, ca_len): + ws[col + str(current_row_number)].font = name_font + ws[col + str(current_row_number)].alignment = c_c_alignment + ws[col + str(current_row_number)].border = f_border + ws[col + str(current_row_number)] = str( + round(reporting_period_data['increment_rates'][i] * 100, 2)) + '%' \ + if reporting_period_data['increment_rates'][i] is not None else '-' + + col = chr(ord(col) + 1) + + current_row_number += 2 + + ##################################### + + has_parameters_names_and_timestamps_and_values_data = True + current_sheet_parameters_row_number = current_row_number + + if 'parameters' not in report.keys() or \ + report['parameters'] is None or \ + 'names' not in report['parameters'].keys() or \ + report['parameters']['names'] is None or \ + len(report['parameters']['names']) == 0 or \ + 'timestamps' not in report['parameters'].keys() or \ + report['parameters']['timestamps'] is None or \ + len(report['parameters']['timestamps']) == 0 or \ + 'values' not in report['parameters'].keys() or \ + report['parameters']['values'] is None or \ + len(report['parameters']['values']) == 0 or \ + timestamps_data_all_equal_0(report['parameters']['timestamps']): + + has_parameters_names_and_timestamps_and_values_data = False + + ##################################### + + has_values_data = True + has_timestamps_data = True + + if 'values' not in reporting_period_data.keys() or \ + reporting_period_data['values'] is None or \ + len(reporting_period_data['values']) == 0: + has_values_data = False + + if 'timestamps' not in reporting_period_data.keys() or \ + reporting_period_data['timestamps'] is None or \ + len(reporting_period_data['timestamps']) == 0 or \ + len(reporting_period_data['timestamps'][0]) == 0: + has_timestamps_data = False + + if has_values_data and has_timestamps_data: + ca_len = len(reporting_period_data['names']) + time = reporting_period_data['timestamps'][0] + + ws['B' + str(current_row_number)].font = title_font + ws['B' + str(current_row_number)] = name + ' 报告期累积效率' + + current_row_number += 1 + + chart_start_row_number = current_row_number + + current_row_number += ca_len * 6 + 1 + + if has_parameters_names_and_timestamps_and_values_data: + current_sheet_parameters_row_number = current_row_number + real_timestamps_len = timestamps_data_not_equal_0(report['parameters']['timestamps']) + current_row_number += 6*real_timestamps_len + 2 + + ws['B' + str(current_row_number)].font = title_font + ws['B' + str(current_row_number)] = name + ' 详细数据' + + current_row_number += 1 + + table_start_row_number = current_row_number + + ws.row_dimensions[current_row_number].height = 85 + ws['B' + str(current_row_number)].fill = table_fill + ws['B' + str(current_row_number)].font = title_font + ws['B' + str(current_row_number)].alignment = c_c_alignment + ws['B' + str(current_row_number)].border = f_border + ws['B' + str(current_row_number)] = '日期时间' + + col = 'C' + + for i in range(0, ca_len): + ws[col + str(current_row_number)].fill = table_fill + ws[col + str(current_row_number)].font = title_font + ws[col + str(current_row_number)].alignment = c_c_alignment + ws[col + str(current_row_number)].border = f_border + ws[col + str(current_row_number)] = \ + reporting_period_data['names'][i] + " (" + reporting_period_data['units'][i] + ")" + col = chr(ord(col) + 1) + + current_row_number += 1 + + for i in range(0, len(time)): + ws['B' + str(current_row_number)].font = title_font + ws['B' + str(current_row_number)].alignment = c_c_alignment + ws['B' + str(current_row_number)].border = f_border + ws['B' + str(current_row_number)] = time[i] + + col = 'C' + for j in range(0, ca_len): + ws[col + str(current_row_number)].font = title_font + ws[col + str(current_row_number)].alignment = c_c_alignment + ws[col + str(current_row_number)].border = f_border + ws[col + str(current_row_number)] = round(reporting_period_data['values'][j][i], 2) \ + if reporting_period_data['values'][j][i] is not None else 0.00 + col = chr(ord(col) + 1) + + current_row_number += 1 + + table_end_row_number = current_row_number - 1 + + ws['B' + str(current_row_number)].font = title_font + ws['B' + str(current_row_number)].alignment = c_c_alignment + ws['B' + str(current_row_number)].border = f_border + ws['B' + str(current_row_number)] = '小计' + + col = 'C' + + for i in range(0, ca_len): + ws[col + str(current_row_number)].font = title_font + ws[col + str(current_row_number)].alignment = c_c_alignment + ws[col + str(current_row_number)].border = f_border + ws[col + str(current_row_number)] = round(reporting_period_data['cumulations'][i], 2) + col = chr(ord(col) + 1) + + current_row_number += 2 + + format_time_width_number = 1.0 + min_len_number = 1.0 + min_width_number = 11.0 # format_time_width_number * min_len_number + 4 and min_width_number > 11.0 + + if period_type == 'hourly': + format_time_width_number = 4.0 + min_len_number = 2 + min_width_number = 12.0 + elif period_type == 'daily': + format_time_width_number = 2.5 + min_len_number = 4 + min_width_number = 14.0 + elif period_type == 'monthly': + format_time_width_number = 2.1 + min_len_number = 4 + min_width_number = 12.4 + elif period_type == 'yearly': + format_time_width_number = 1.5 + min_len_number = 5 + min_width_number = 11.5 + + for i in range(0, ca_len): + line = LineChart() + line.title = '报告期累积效率 - ' + \ + reporting_period_data['names'][i] + " (" + reporting_period_data['units'][i] + ")" + labels = Reference(ws, min_col=2, min_row=table_start_row_number + 1, max_row=table_end_row_number) + line_data = Reference(ws, min_col=3 + i, min_row=table_start_row_number, max_row=table_end_row_number) + line.add_data(line_data, titles_from_data=True) + line.set_categories(labels) + line_data = line.series[0] + line_data.marker.symbol = "circle" + line_data.smooth = True + line.x_axis.crosses = 'min' + line.height = 8.25 + line.width = format_time_width_number * len(time) if len(time) > min_len_number else min_width_number + if line.width > 24: + line.width = 24 + line.dLbls = DataLabelList() + line.dLbls.dLblPos = 't' + line.dLbls.showVal = True + line.dLbls.showPercent = False + chart_col = 'B' + chart_cell = chart_col + str(chart_start_row_number) + chart_start_row_number += 6 + ws.add_chart(line, chart_cell) + + ##################################################################### + + if has_parameters_names_and_timestamps_and_values_data: + + ############################### + # new worksheet + ############################### + + parameters_data = report['parameters'] + parameters_names_len = len(parameters_data['names']) + + parameters_ws = wb.create_sheet('相关参数') + + parameters_timestamps_data_max_len = \ + get_parameters_timestamps_lists_max_len(list(parameters_data['timestamps'])) + + # Row height + parameters_ws.row_dimensions[1].height = 102 + for i in range(2, 7 + 1): + parameters_ws.row_dimensions[i].height = 42 + + for i in range(8, parameters_timestamps_data_max_len + 10): + parameters_ws.row_dimensions[i].height = 60 + + # Col width + parameters_ws.column_dimensions['A'].width = 1.5 + + parameters_ws.column_dimensions['B'].width = 25.0 + + for i in range(3, 12+parameters_names_len*3): + parameters_ws.column_dimensions[format_cell.get_column_letter(i)].width = 15.0 + + # Img + img = Image("excelexporters/myems.png") + img.width = img.width * 0.85 + img.height = img.height * 0.85 + # img = Image("myems.png") + parameters_ws.add_image(img, 'B1') + + # Title + parameters_ws.row_dimensions[3].height = 60 + + parameters_ws['B3'].font = name_font + parameters_ws['B3'].alignment = b_r_alignment + parameters_ws['B3'] = 'Name:' + parameters_ws['C3'].border = b_border + parameters_ws['C3'].alignment = b_c_alignment + parameters_ws['C3'].font = name_font + parameters_ws['C3'] = name + + parameters_ws['D3'].font = name_font + parameters_ws['D3'].alignment = b_r_alignment + parameters_ws['D3'] = 'Period:' + parameters_ws['E3'].border = b_border + parameters_ws['E3'].alignment = b_c_alignment + parameters_ws['E3'].font = name_font + parameters_ws['E3'] = period_type + + parameters_ws['F3'].font = name_font + parameters_ws['F3'].alignment = b_r_alignment + parameters_ws['F3'] = 'Date:' + parameters_ws['G3'].border = b_border + parameters_ws['G3'].alignment = b_c_alignment + parameters_ws['G3'].font = name_font + parameters_ws['G3'] = reporting_start_datetime_local + "__" + reporting_end_datetime_local + parameters_ws.merge_cells("G3:H3") + + parameters_ws_current_row_number = 6 + + parameters_ws['B' + str(parameters_ws_current_row_number)].font = title_font + parameters_ws['B' + str(parameters_ws_current_row_number)] = name + ' 相关参数' + + parameters_ws_current_row_number += 1 + + parameters_table_start_row_number = parameters_ws_current_row_number + + parameters_ws.row_dimensions[parameters_ws_current_row_number].height = 80 + + parameters_ws_current_row_number += 1 + + table_current_col_number = 'B' + + for i in range(0, parameters_names_len): + + if len(parameters_data['timestamps'][i]) == 0: + continue + + parameters_ws[table_current_col_number + str(parameters_ws_current_row_number-1)].fill = table_fill + parameters_ws[table_current_col_number + str(parameters_ws_current_row_number-1)].border = f_border + + col = chr(ord(table_current_col_number) + 1) + + parameters_ws[col + str(parameters_ws_current_row_number-1)].fill = table_fill + parameters_ws[col + str(parameters_ws_current_row_number-1)].border = f_border + parameters_ws[col + str(parameters_ws_current_row_number-1)].font = name_font + parameters_ws[col + str(parameters_ws_current_row_number-1)].alignment = c_c_alignment + parameters_ws[col + str(parameters_ws_current_row_number-1)] = parameters_data['names'][i] + + table_current_row_number = parameters_ws_current_row_number + + for j, value in enumerate(list(parameters_data['timestamps'][i])): + col = table_current_col_number + + parameters_ws[col + str(table_current_row_number)].border = f_border + parameters_ws[col + str(table_current_row_number)].font = title_font + parameters_ws[col + str(table_current_row_number)].alignment = c_c_alignment + parameters_ws[col + str(table_current_row_number)] = value + + col = chr(ord(col) + 1) + + parameters_ws[col + str(table_current_row_number)].border = f_border + parameters_ws[col + str(table_current_row_number)].font = title_font + parameters_ws[col + str(table_current_row_number)].alignment = c_c_alignment + parameters_ws[col + str(table_current_row_number)] = round(parameters_data['values'][i][j], 2) + + table_current_row_number += 1 + + table_current_col_number = chr(ord(table_current_col_number) + 3) + + ######################################################## + # parameters chart and parameters table + ######################################################## + + ws['B' + str(current_sheet_parameters_row_number)].font = title_font + ws['B' + str(current_sheet_parameters_row_number)] = name + ' 相关参数' + + current_sheet_parameters_row_number += 1 + + chart_start_row_number = current_sheet_parameters_row_number + + col_index = 0 + + for i in range(0, parameters_names_len): + + if len(parameters_data['timestamps'][i]) == 0: + continue + + line = LineChart() + data_col = 3+col_index*3 + labels_col = 2+col_index*3 + col_index += 1 + line.title = '相关参数 - ' + \ + parameters_ws.cell(row=parameters_table_start_row_number, column=data_col).value + labels = Reference(parameters_ws, min_col=labels_col, min_row=parameters_table_start_row_number + 1, + max_row=(len(parameters_data['timestamps'][i])+parameters_table_start_row_number)) + line_data = Reference(parameters_ws, min_col=data_col, min_row=parameters_table_start_row_number, + max_row=(len(parameters_data['timestamps'][i])+parameters_table_start_row_number)) + line.add_data(line_data, titles_from_data=True) + line.set_categories(labels) + line_data = line.series[0] + line_data.marker.symbol = "circle" + line_data.smooth = True + line.x_axis.crosses = 'min' + line.height = 8.25 + line.width = 24 + line.dLbls = DataLabelList() + line.dLbls.dLblPos = 't' + line.dLbls.showVal = False + line.dLbls.showPercent = False + chart_col = 'B' + chart_cell = chart_col + str(chart_start_row_number) + chart_start_row_number += 6 + ws.add_chart(line, chart_cell) + + current_sheet_parameters_row_number = chart_start_row_number + + current_sheet_parameters_row_number += 1 + + filename = str(uuid.uuid4()) + '.xlsx' + wb.save(filename) + + return filename + + +def get_parameters_timestamps_lists_max_len(parameters_timestamps_lists): + max_len = 0 + for i, value in enumerate(list(parameters_timestamps_lists)): + if len(value) > max_len: + max_len = len(value) + + return max_len + + +def timestamps_data_all_equal_0(lists): + for i, value in enumerate(list(lists)): + if len(value) > 0: + return False + + return True + + +def timestamps_data_not_equal_0(lists): + number = 0 + for i, value in enumerate(list(lists)): + if len(value) > 0: + number += 1 + return number diff --git a/myems-api/excelexporters/equipmentefficiency.py b/myems-api/excelexporters/equipmentefficiency.py new file mode 100644 index 00000000..d91e620d --- /dev/null +++ b/myems-api/excelexporters/equipmentefficiency.py @@ -0,0 +1,603 @@ +import base64 +import uuid +import os +from openpyxl.chart import ( + PieChart, + LineChart, + BarChart, + Reference, +) +from openpyxl.styles import PatternFill, Border, Side, Alignment, Font +from openpyxl.drawing.image import Image +from openpyxl import Workbook +from openpyxl.chart.label import DataLabelList +import openpyxl.utils.cell as format_cell + + +#################################################################################################################### +# PROCEDURES +# Step 1: Validate the report data +# Step 2: Generate excel file +# Step 3: Encode the excel file bytes to Base64 +#################################################################################################################### + + +def export(report, + name, + reporting_start_datetime_local, + reporting_end_datetime_local, + period_type): + #################################################################################################################### + # Step 1: Validate the report data + #################################################################################################################### + if report is None: + return None + print(report) + + #################################################################################################################### + # Step 2: Generate excel file from the report data + #################################################################################################################### + filename = generate_excel(report, + name, + reporting_start_datetime_local, + reporting_end_datetime_local, + period_type) + #################################################################################################################### + # Step 3: Encode the excel file to Base64 + #################################################################################################################### + try: + with open(filename, 'rb') as binary_file: + binary_file_data = binary_file.read() + except IOError as ex: + pass + + # Base64 encode the bytes + base64_encoded_data = base64.b64encode(binary_file_data) + # get the Base64 encoded data using human-readable characters. + base64_message = base64_encoded_data.decode('utf-8') + # delete the file from server + try: + os.remove(filename) + except NotImplementedError as ex: + pass + return base64_message + + +def generate_excel(report, + name, + reporting_start_datetime_local, + reporting_end_datetime_local, + period_type): + wb = Workbook() + ws = wb.active + + # Row height + ws.row_dimensions[1].height = 102 + for i in range(2, 2000 + 1): + ws.row_dimensions[i].height = 42 + + # Col width + ws.column_dimensions['A'].width = 1.5 + + ws.column_dimensions['B'].width = 25.0 + + for i in range(ord('C'), ord('L')): + ws.column_dimensions[chr(i)].width = 15.0 + + # Font + name_font = Font(name='Constantia', size=15, bold=True) + title_font = Font(name='宋体', size=15, bold=True) + data_font = Font(name='Franklin Gothic Book', size=11) + + table_fill = PatternFill(fill_type='solid', fgColor='1F497D') + f_border = Border(left=Side(border_style='medium', color='00000000'), + right=Side(border_style='medium', color='00000000'), + bottom=Side(border_style='medium', color='00000000'), + top=Side(border_style='medium', color='00000000') + ) + b_border = Border( + bottom=Side(border_style='medium', color='00000000'), + ) + + b_c_alignment = Alignment(vertical='bottom', + horizontal='center', + text_rotation=0, + wrap_text=True, + shrink_to_fit=False, + indent=0) + c_c_alignment = Alignment(vertical='center', + horizontal='center', + text_rotation=0, + wrap_text=True, + shrink_to_fit=False, + indent=0) + b_r_alignment = Alignment(vertical='bottom', + horizontal='right', + text_rotation=0, + wrap_text=True, + shrink_to_fit=False, + indent=0) + c_r_alignment = Alignment(vertical='bottom', + horizontal='center', + text_rotation=0, + wrap_text=True, + shrink_to_fit=False, + indent=0) + # Img + img = Image("excelexporters/myems.png") + img.width = img.width * 0.85 + img.height = img.height * 0.85 + # img = Image("myems.png") + ws.add_image(img, 'B1') + + # Title + ws.row_dimensions[3].height = 60 + + ws['B3'].font = name_font + ws['B3'].alignment = b_r_alignment + ws['B3'] = 'Name:' + ws['C3'].border = b_border + ws['C3'].alignment = b_c_alignment + ws['C3'].font = name_font + ws['C3'] = name + + ws['D3'].font = name_font + ws['D3'].alignment = b_r_alignment + ws['D3'] = 'Period:' + ws['E3'].border = b_border + ws['E3'].alignment = b_c_alignment + ws['E3'].font = name_font + ws['E3'] = period_type + + ws['F3'].font = name_font + ws['F3'].alignment = b_r_alignment + ws['F3'] = 'Date:' + ws['G3'].border = b_border + ws['G3'].alignment = b_c_alignment + ws['G3'].font = name_font + ws['G3'] = reporting_start_datetime_local + "__" + reporting_end_datetime_local + ws.merge_cells("G3:H3") + + if "reporting_period_efficiency" not in report.keys() or \ + "names" not in report['reporting_period_efficiency'].keys() or len( + report['reporting_period_efficiency']['names']) == 0: + filename = str(uuid.uuid4()) + '.xlsx' + wb.save(filename) + + return filename + + ################################## + + current_row_number = 6 + + reporting_period_data = report['reporting_period_efficiency'] + + has_names_data_flag = True + + if "names" not in reporting_period_data.keys() or \ + reporting_period_data['names'] is None or \ + len(reporting_period_data['names']) == 0: + has_names_data_flag = False + + if has_names_data_flag: + ws['B' + str(current_row_number)].font = title_font + ws['B' + str(current_row_number)] = name + ' 报告期累积效率' + + current_row_number += 1 + + category = reporting_period_data['names'] + ca_len = len(category) + + ws.row_dimensions[current_row_number].height = 80 + ws['B' + str(current_row_number)].fill = table_fill + ws['B' + str(current_row_number)].border = f_border + + col = 'C' + + for i in range(0, ca_len): + ws[col + str(current_row_number)].fill = table_fill + ws[col + str(current_row_number)].font = name_font + ws[col + str(current_row_number)].alignment = c_c_alignment + ws[col + str(current_row_number)].border = f_border + ws[col + str(current_row_number)] = \ + reporting_period_data['names'][i] + " (" + reporting_period_data['units'][i] + ")" + + col = chr(ord(col) + 1) + + current_row_number += 1 + + ws['B' + str(current_row_number)].font = title_font + ws['B' + str(current_row_number)].alignment = c_c_alignment + ws['B' + str(current_row_number)].border = f_border + ws['B' + str(current_row_number)] = '累积效率' + + col = 'C' + + for i in range(0, ca_len): + ws[col + str(current_row_number)].font = name_font + ws[col + str(current_row_number)].alignment = c_c_alignment + ws[col + str(current_row_number)].border = f_border + ws[col + str(current_row_number)] = round(reporting_period_data['cumulations'][i], 2) + + col = chr(ord(col) + 1) + + current_row_number += 1 + + ws['B' + str(current_row_number)].font = title_font + ws['B' + str(current_row_number)].alignment = c_c_alignment + ws['B' + str(current_row_number)].border = f_border + ws['B' + str(current_row_number)] = '环比' + + col = 'C' + + for i in range(0, ca_len): + ws[col + str(current_row_number)].font = name_font + ws[col + str(current_row_number)].alignment = c_c_alignment + ws[col + str(current_row_number)].border = f_border + ws[col + str(current_row_number)] = str( + round(reporting_period_data['increment_rates'][i] * 100, 2)) + '%' \ + if reporting_period_data['increment_rates'][i] is not None else '-' + + col = chr(ord(col) + 1) + + current_row_number += 2 + + ##################################### + + has_parameters_names_and_timestamps_and_values_data = True + current_sheet_parameters_row_number = current_row_number + + if 'parameters' not in report.keys() or \ + report['parameters'] is None or \ + 'names' not in report['parameters'].keys() or \ + report['parameters']['names'] is None or \ + len(report['parameters']['names']) == 0 or \ + 'timestamps' not in report['parameters'].keys() or \ + report['parameters']['timestamps'] is None or \ + len(report['parameters']['timestamps']) == 0 or \ + 'values' not in report['parameters'].keys() or \ + report['parameters']['values'] is None or \ + len(report['parameters']['values']) == 0 or \ + timestamps_data_all_equal_0(report['parameters']['timestamps']): + + has_parameters_names_and_timestamps_and_values_data = False + + ##################################### + + has_values_data = True + has_timestamps_data = True + + if 'values' not in reporting_period_data.keys() or \ + reporting_period_data['values'] is None or \ + len(reporting_period_data['values']) == 0: + has_values_data = False + + if 'timestamps' not in reporting_period_data.keys() or \ + reporting_period_data['timestamps'] is None or \ + len(reporting_period_data['timestamps']) == 0 or \ + len(reporting_period_data['timestamps'][0]) == 0: + has_timestamps_data = False + + if has_values_data and has_timestamps_data: + ca_len = len(reporting_period_data['names']) + time = reporting_period_data['timestamps'][0] + + ws['B' + str(current_row_number)].font = title_font + ws['B' + str(current_row_number)] = name + ' 报告期累积效率' + + current_row_number += 1 + + chart_start_row_number = current_row_number + + current_row_number += ca_len * 6 + 1 + + if has_parameters_names_and_timestamps_and_values_data: + current_sheet_parameters_row_number = current_row_number + real_timestamps_len = timestamps_data_not_equal_0(report['parameters']['timestamps']) + current_row_number += 6*real_timestamps_len + 2 + + ws['B' + str(current_row_number)].font = title_font + ws['B' + str(current_row_number)] = name + ' 详细数据' + + current_row_number += 1 + + table_start_row_number = current_row_number + + ws.row_dimensions[current_row_number].height = 85 + ws['B' + str(current_row_number)].fill = table_fill + ws['B' + str(current_row_number)].font = title_font + ws['B' + str(current_row_number)].alignment = c_c_alignment + ws['B' + str(current_row_number)].border = f_border + ws['B' + str(current_row_number)] = '日期时间' + + col = 'C' + + for i in range(0, ca_len): + ws[col + str(current_row_number)].fill = table_fill + ws[col + str(current_row_number)].font = title_font + ws[col + str(current_row_number)].alignment = c_c_alignment + ws[col + str(current_row_number)].border = f_border + ws[col + str(current_row_number)] = \ + reporting_period_data['names'][i] + " (" + reporting_period_data['units'][i] + ")" + col = chr(ord(col) + 1) + + current_row_number += 1 + + for i in range(0, len(time)): + ws['B' + str(current_row_number)].font = title_font + ws['B' + str(current_row_number)].alignment = c_c_alignment + ws['B' + str(current_row_number)].border = f_border + ws['B' + str(current_row_number)] = time[i] + + col = 'C' + for j in range(0, ca_len): + ws[col + str(current_row_number)].font = title_font + ws[col + str(current_row_number)].alignment = c_c_alignment + ws[col + str(current_row_number)].border = f_border + ws[col + str(current_row_number)] = round(reporting_period_data['values'][j][i], 2) \ + if reporting_period_data['values'][j][i] is not None else 0.00 + col = chr(ord(col) + 1) + + current_row_number += 1 + + table_end_row_number = current_row_number - 1 + + ws['B' + str(current_row_number)].font = title_font + ws['B' + str(current_row_number)].alignment = c_c_alignment + ws['B' + str(current_row_number)].border = f_border + ws['B' + str(current_row_number)] = '小计' + + col = 'C' + + for i in range(0, ca_len): + ws[col + str(current_row_number)].font = title_font + ws[col + str(current_row_number)].alignment = c_c_alignment + ws[col + str(current_row_number)].border = f_border + ws[col + str(current_row_number)] = round(reporting_period_data['cumulations'][i], 2) + col = chr(ord(col) + 1) + + current_row_number += 2 + + format_time_width_number = 1.0 + min_len_number = 1.0 + min_width_number = 11.0 # format_time_width_number * min_len_number + 4 and min_width_number > 11.0 + + if period_type == 'hourly': + format_time_width_number = 4.0 + min_len_number = 2 + min_width_number = 12.0 + elif period_type == 'daily': + format_time_width_number = 2.5 + min_len_number = 4 + min_width_number = 14.0 + elif period_type == 'monthly': + format_time_width_number = 2.1 + min_len_number = 4 + min_width_number = 12.4 + elif period_type == 'yearly': + format_time_width_number = 1.5 + min_len_number = 5 + min_width_number = 11.5 + + for i in range(0, ca_len): + line = LineChart() + line.title = '报告期累积效率 - ' + \ + reporting_period_data['names'][i] + " (" + reporting_period_data['units'][i] + ")" + labels = Reference(ws, min_col=2, min_row=table_start_row_number + 1, max_row=table_end_row_number) + line_data = Reference(ws, min_col=3 + i, min_row=table_start_row_number, max_row=table_end_row_number) + line.add_data(line_data, titles_from_data=True) + line.set_categories(labels) + line_data = line.series[0] + line_data.marker.symbol = "circle" + line_data.smooth = True + line.x_axis.crosses = 'min' + line.height = 8.25 + line.width = format_time_width_number * len(time) if len(time) > min_len_number else min_width_number + if line.width > 24: + line.width = 24 + line.dLbls = DataLabelList() + line.dLbls.dLblPos = 't' + line.dLbls.showVal = True + line.dLbls.showPercent = False + chart_col = 'B' + chart_cell = chart_col + str(chart_start_row_number) + chart_start_row_number += 6 + ws.add_chart(line, chart_cell) + + ##################################################################### + + if has_parameters_names_and_timestamps_and_values_data: + + ############################### + # new worksheet + ############################### + + parameters_data = report['parameters'] + parameters_names_len = len(parameters_data['names']) + + parameters_ws = wb.create_sheet('相关参数') + + parameters_timestamps_data_max_len = \ + get_parameters_timestamps_lists_max_len(list(parameters_data['timestamps'])) + + # Row height + parameters_ws.row_dimensions[1].height = 102 + for i in range(2, 7 + 1): + parameters_ws.row_dimensions[i].height = 42 + + for i in range(8, parameters_timestamps_data_max_len + 10): + parameters_ws.row_dimensions[i].height = 60 + + # Col width + parameters_ws.column_dimensions['A'].width = 1.5 + + parameters_ws.column_dimensions['B'].width = 25.0 + + for i in range(3, 12+parameters_names_len*3): + parameters_ws.column_dimensions[format_cell.get_column_letter(i)].width = 15.0 + + # Img + img = Image("excelexporters/myems.png") + img.width = img.width * 0.85 + img.height = img.height * 0.85 + # img = Image("myems.png") + parameters_ws.add_image(img, 'B1') + + # Title + parameters_ws.row_dimensions[3].height = 60 + + parameters_ws['B3'].font = name_font + parameters_ws['B3'].alignment = b_r_alignment + parameters_ws['B3'] = 'Name:' + parameters_ws['C3'].border = b_border + parameters_ws['C3'].alignment = b_c_alignment + parameters_ws['C3'].font = name_font + parameters_ws['C3'] = name + + parameters_ws['D3'].font = name_font + parameters_ws['D3'].alignment = b_r_alignment + parameters_ws['D3'] = 'Period:' + parameters_ws['E3'].border = b_border + parameters_ws['E3'].alignment = b_c_alignment + parameters_ws['E3'].font = name_font + parameters_ws['E3'] = period_type + + parameters_ws['F3'].font = name_font + parameters_ws['F3'].alignment = b_r_alignment + parameters_ws['F3'] = 'Date:' + parameters_ws['G3'].border = b_border + parameters_ws['G3'].alignment = b_c_alignment + parameters_ws['G3'].font = name_font + parameters_ws['G3'] = reporting_start_datetime_local + "__" + reporting_end_datetime_local + parameters_ws.merge_cells("G3:H3") + + parameters_ws_current_row_number = 6 + + parameters_ws['B' + str(parameters_ws_current_row_number)].font = title_font + parameters_ws['B' + str(parameters_ws_current_row_number)] = name + ' 相关参数' + + parameters_ws_current_row_number += 1 + + parameters_table_start_row_number = parameters_ws_current_row_number + + parameters_ws.row_dimensions[parameters_ws_current_row_number].height = 80 + + parameters_ws_current_row_number += 1 + + table_current_col_number = 'B' + + for i in range(0, parameters_names_len): + + if len(parameters_data['timestamps'][i]) == 0: + continue + + parameters_ws[table_current_col_number + str(parameters_ws_current_row_number-1)].fill = table_fill + parameters_ws[table_current_col_number + str(parameters_ws_current_row_number-1)].border = f_border + + col = chr(ord(table_current_col_number) + 1) + + parameters_ws[col + str(parameters_ws_current_row_number-1)].fill = table_fill + parameters_ws[col + str(parameters_ws_current_row_number-1)].border = f_border + parameters_ws[col + str(parameters_ws_current_row_number-1)].font = name_font + parameters_ws[col + str(parameters_ws_current_row_number-1)].alignment = c_c_alignment + parameters_ws[col + str(parameters_ws_current_row_number-1)] = parameters_data['names'][i] + + table_current_row_number = parameters_ws_current_row_number + + for j, value in enumerate(list(parameters_data['timestamps'][i])): + col = table_current_col_number + + parameters_ws[col + str(table_current_row_number)].border = f_border + parameters_ws[col + str(table_current_row_number)].font = title_font + parameters_ws[col + str(table_current_row_number)].alignment = c_c_alignment + parameters_ws[col + str(table_current_row_number)] = value + + col = chr(ord(col) + 1) + + parameters_ws[col + str(table_current_row_number)].border = f_border + parameters_ws[col + str(table_current_row_number)].font = title_font + parameters_ws[col + str(table_current_row_number)].alignment = c_c_alignment + parameters_ws[col + str(table_current_row_number)] = round(parameters_data['values'][i][j], 2) + + table_current_row_number += 1 + + table_current_col_number = chr(ord(table_current_col_number) + 3) + + ######################################################## + # parameters chart and parameters table + ######################################################## + + ws['B' + str(current_sheet_parameters_row_number)].font = title_font + ws['B' + str(current_sheet_parameters_row_number)] = name + ' 相关参数' + + current_sheet_parameters_row_number += 1 + + chart_start_row_number = current_sheet_parameters_row_number + + col_index = 0 + + for i in range(0, parameters_names_len): + + if len(parameters_data['timestamps'][i]) == 0: + continue + + line = LineChart() + data_col = 3+col_index*3 + labels_col = 2+col_index*3 + col_index += 1 + line.title = '相关参数 - ' + \ + parameters_ws.cell(row=parameters_table_start_row_number, column=data_col).value + labels = Reference(parameters_ws, min_col=labels_col, min_row=parameters_table_start_row_number + 1, + max_row=(len(parameters_data['timestamps'][i])+parameters_table_start_row_number)) + line_data = Reference(parameters_ws, min_col=data_col, min_row=parameters_table_start_row_number, + max_row=(len(parameters_data['timestamps'][i])+parameters_table_start_row_number)) + line.add_data(line_data, titles_from_data=True) + line.set_categories(labels) + line_data = line.series[0] + line_data.marker.symbol = "circle" + line_data.smooth = True + line.x_axis.crosses = 'min' + line.height = 8.25 + line.width = 24 + line.dLbls = DataLabelList() + line.dLbls.dLblPos = 't' + line.dLbls.showVal = False + line.dLbls.showPercent = False + chart_col = 'B' + chart_cell = chart_col + str(chart_start_row_number) + chart_start_row_number += 6 + ws.add_chart(line, chart_cell) + + current_sheet_parameters_row_number = chart_start_row_number + + current_sheet_parameters_row_number += 1 + + filename = str(uuid.uuid4()) + '.xlsx' + wb.save(filename) + + return filename + + +def get_parameters_timestamps_lists_max_len(parameters_timestamps_lists): + max_len = 0 + for i, value in enumerate(list(parameters_timestamps_lists)): + if len(value) > max_len: + max_len = len(value) + + return max_len + + +def timestamps_data_all_equal_0(lists): + for i, value in enumerate(list(lists)): + if len(value) > 0: + return False + + return True + + +def timestamps_data_not_equal_0(lists): + number = 0 + for i, value in enumerate(list(lists)): + if len(value) > 0: + number += 1 + return number diff --git a/myems-api/reports/combinedequipmentcost.py b/myems-api/reports/combinedequipmentcost.py index ed366dcb..1da3e452 100644 --- a/myems-api/reports/combinedequipmentcost.py +++ b/myems-api/reports/combinedequipmentcost.py @@ -148,10 +148,10 @@ class Reporting: if cnx_billing: cnx_billing.disconnect() - if cnx_historical: - cnx_historical.close() if cursor_historical: - cursor_historical.disconnect() + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.COMBINED_EQUIPMENT_NOT_FOUND') @@ -205,10 +205,10 @@ class Reporting: if cnx_billing: cnx_billing.disconnect() - if cnx_historical: - cnx_historical.close() if cursor_historical: - cursor_historical.disconnect() + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.ENERGY_CATEGORY_NOT_FOUND') @@ -452,6 +452,11 @@ class Reporting: if cnx_billing: cnx_billing.disconnect() + if cursor_historical: + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() + result = dict() result['combined_equipment'] = dict() diff --git a/myems-api/reports/combinedequipmentefficiency.py b/myems-api/reports/combinedequipmentefficiency.py index 5d4f4d8b..a1d809c3 100644 --- a/myems-api/reports/combinedequipmentefficiency.py +++ b/myems-api/reports/combinedequipmentefficiency.py @@ -5,6 +5,7 @@ import config from datetime import datetime, timedelta, timezone from core import utilities from decimal import Decimal +import excelexporters.combinedequipmentefficiency class Reporting: @@ -20,16 +21,13 @@ class Reporting: # PROCEDURES # Step 1: valid parameters # Step 2: query the combined equipment - # Step 3: query associated equipments - # Step 4: query energy categories - # Step 5: query associated points - # Step 6: query base period energy input - # Step 7: query base period energy output - # Step 8: query reporting period energy input - # Step 9: query reporting period energy output - # Step 10: query tariff data - # Step 11: query associated points data - # Step 12: construct the report + # Step 3: query associated points + # Step 4: query associated fractions + # Step 5: query fractions' numerator and denominator + # Step 6: calculate base period fractions + # Step 7: calculate reporting period fractions + # Step 8: query associated points data + # Step 9: construct the report #################################################################################################################### @staticmethod def on_get(req, resp): @@ -45,14 +43,12 @@ class Reporting: # Step 1: valid parameters ################################################################################################################ if combined_equipment_id is None: - raise falcon.HTTPError(falcon.HTTP_400, - title='API.BAD_REQUEST', + raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', description='API.INVALID_COMBINED_EQUIPMENT_ID') else: combined_equipment_id = str.strip(combined_equipment_id) if not combined_equipment_id.isdigit() or int(combined_equipment_id) <= 0: - raise falcon.HTTPError(falcon.HTTP_400, - title='API.BAD_REQUEST', + raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', description='API.INVALID_COMBINED_EQUIPMENT_ID') if period_type is None: @@ -72,7 +68,7 @@ class Reporting: try: base_start_datetime_utc = datetime.strptime(base_start_datetime_local, '%Y-%m-%dT%H:%M:%S').replace(tzinfo=timezone.utc) - \ - timedelta(minutes=timezone_offset) + timedelta(minutes=timezone_offset) except ValueError: raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', description="API.INVALID_BASE_PERIOD_START_DATETIME") @@ -83,7 +79,7 @@ class Reporting: try: base_end_datetime_utc = datetime.strptime(base_end_datetime_local, '%Y-%m-%dT%H:%M:%S').replace(tzinfo=timezone.utc) - \ - timedelta(minutes=timezone_offset) + timedelta(minutes=timezone_offset) except ValueError: raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', description="API.INVALID_BASE_PERIOD_END_DATETIME") @@ -101,7 +97,7 @@ class Reporting: try: reporting_start_datetime_utc = datetime.strptime(reporting_start_datetime_local, '%Y-%m-%dT%H:%M:%S').replace(tzinfo=timezone.utc) - \ - timedelta(minutes=timezone_offset) + timedelta(minutes=timezone_offset) except ValueError: raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', description="API.INVALID_REPORTING_PERIOD_START_DATETIME") @@ -114,7 +110,7 @@ class Reporting: try: reporting_end_datetime_utc = datetime.strptime(reporting_end_datetime_local, '%Y-%m-%dT%H:%M:%S').replace(tzinfo=timezone.utc) - \ - timedelta(minutes=timezone_offset) + timedelta(minutes=timezone_offset) except ValueError: raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', description="API.INVALID_REPORTING_PERIOD_END_DATETIME") @@ -150,110 +146,20 @@ class Reporting: if cnx_energy: cnx_energy.disconnect() - if cnx_historical: - cnx_historical.close() if cursor_historical: - cursor_historical.disconnect() - raise falcon.HTTPError(falcon.HTTP_404, - title='API.NOT_FOUND', + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() + raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.COMBINED_EQUIPMENT_NOT_FOUND') combined_equipment = dict() combined_equipment['id'] = row_combined_equipment[0] combined_equipment['name'] = row_combined_equipment[1] combined_equipment['cost_center_id'] = row_combined_equipment[2] - ################################################################################################################ - # Step 3: query associated equipments - ################################################################################################################ - # todo ################################################################################################################ - # Step 4: query input energy categories and output energy categories - ################################################################################################################ - energy_category_set_input = set() - energy_category_set_output = set() - # query input energy categories in base period - cursor_energy.execute(" SELECT DISTINCT(energy_category_id) " - " FROM tbl_combined_equipment_input_category_hourly " - " WHERE combined_equipment_id = %s " - " AND start_datetime_utc >= %s " - " AND start_datetime_utc < %s ", - (combined_equipment['id'], base_start_datetime_utc, base_end_datetime_utc)) - rows_energy_categories = cursor_energy.fetchall() - if rows_energy_categories is not None or len(rows_energy_categories) > 0: - for row_energy_category in rows_energy_categories: - energy_category_set_input.add(row_energy_category[0]) - - # query input energy categories in reporting period - cursor_energy.execute(" SELECT DISTINCT(energy_category_id) " - " FROM tbl_combined_equipment_input_category_hourly " - " WHERE combined_equipment_id = %s " - " AND start_datetime_utc >= %s " - " AND start_datetime_utc < %s ", - (combined_equipment['id'], reporting_start_datetime_utc, reporting_end_datetime_utc)) - rows_energy_categories = cursor_energy.fetchall() - if rows_energy_categories is not None or len(rows_energy_categories) > 0: - for row_energy_category in rows_energy_categories: - energy_category_set_input.add(row_energy_category[0]) - - # query output energy categories in base period - cursor_energy.execute(" SELECT DISTINCT(energy_category_id) " - " FROM tbl_combined_equipment_output_category_hourly " - " WHERE combined_equipment_id = %s " - " AND start_datetime_utc >= %s " - " AND start_datetime_utc < %s ", - (combined_equipment['id'], base_start_datetime_utc, base_end_datetime_utc)) - rows_energy_categories = cursor_energy.fetchall() - if rows_energy_categories is not None or len(rows_energy_categories) > 0: - for row_energy_category in rows_energy_categories: - energy_category_set_output.add(row_energy_category[0]) - - # query output energy categories in reporting period - cursor_energy.execute(" SELECT DISTINCT(energy_category_id) " - " FROM tbl_combined_equipment_output_category_hourly " - " WHERE combined_equipment_id = %s " - " AND start_datetime_utc >= %s " - " AND start_datetime_utc < %s ", - (combined_equipment['id'], reporting_start_datetime_utc, reporting_end_datetime_utc)) - rows_energy_categories = cursor_energy.fetchall() - if rows_energy_categories is not None or len(rows_energy_categories) > 0: - for row_energy_category in rows_energy_categories: - energy_category_set_output.add(row_energy_category[0]) - - # query properties of all energy categories above - cursor_system.execute(" SELECT id, name, unit_of_measure, kgce, kgco2e " - " FROM tbl_energy_categories " - " ORDER BY id ", ) - rows_energy_categories = cursor_system.fetchall() - if rows_energy_categories is None or len(rows_energy_categories) == 0: - if cursor_system: - cursor_system.close() - if cnx_system: - cnx_system.disconnect() - - if cursor_energy: - cursor_energy.close() - if cnx_energy: - cnx_energy.disconnect() - - if cnx_historical: - cnx_historical.close() - if cursor_historical: - cursor_historical.disconnect() - raise falcon.HTTPError(falcon.HTTP_404, - title='API.NOT_FOUND', - description='API.ENERGY_CATEGORY_NOT_FOUND') - energy_category_dict = dict() - for row_energy_category in rows_energy_categories: - if row_energy_category[0] in energy_category_set_input or \ - row_energy_category[0] in energy_category_set_output: - energy_category_dict[row_energy_category[0]] = {"name": row_energy_category[1], - "unit_of_measure": row_energy_category[2], - "kgce": row_energy_category[3], - "kgco2e": row_energy_category[4]} - - ################################################################################################################ - # Step 5: query associated points + # Step 3: query associated points ################################################################################################################ point_list = list() cursor_system.execute(" SELECT p.id, p.name, p.units, p.object_type " @@ -266,84 +172,181 @@ class Reporting: for row in rows_points: point_list.append({"id": row[0], "name": row[1], "units": row[2], "object_type": row[3]}) + print(point_list) ################################################################################################################ - # Step 6: query base period energy input + # Step 4: query associated fractions ################################################################################################################ - base_input = dict() - if energy_category_set_input is not None and len(energy_category_set_input) > 0: - for energy_category_id in energy_category_set_input: - base_input[energy_category_id] = dict() - base_input[energy_category_id]['timestamps'] = list() - base_input[energy_category_id]['values'] = list() - base_input[energy_category_id]['subtotal'] = Decimal(0.0) + fraction_list = list() + cursor_system.execute(" SELECT id, name, numerator_meter_uuid, denominator_meter_uuid " + " FROM tbl_combined_equipments_parameters " + " WHERE combined_equipment_id = %s AND parameter_type = 'fraction' ", + (combined_equipment['id'],)) + rows_fractions = cursor_system.fetchall() + if rows_fractions is not None and len(rows_fractions) > 0: + for row in rows_fractions: + fraction_list.append({"id": row[0], + "name": row[1], + "numerator_meter_uuid": row[2], + "denominator_meter_uuid": row[3], + }) - cursor_energy.execute(" SELECT start_datetime_utc, actual_value " - " FROM tbl_combined_equipment_input_category_hourly " - " WHERE combined_equipment_id = %s " - " AND energy_category_id = %s " - " AND start_datetime_utc >= %s " - " AND start_datetime_utc < %s " - " ORDER BY start_datetime_utc ", - (combined_equipment['id'], - energy_category_id, - base_start_datetime_utc, - base_end_datetime_utc)) - rows_combined_equipment_hourly = cursor_energy.fetchall() + print(fraction_list) - rows_combined_equipment_periodically = \ - utilities.aggregate_hourly_data_by_period(rows_combined_equipment_hourly, + ################################################################################################################ + # Step 5: query fractions' numerator and denominator + ################################################################################################################ + # get all meters + meter_dict = dict() + query = (" SELECT m.id, m.uuid, ec.unit_of_measure " + " FROM tbl_meters m, tbl_energy_categories ec " + " WHERE m.energy_category_id = ec.id ") + cursor_system.execute(query) + rows_meters = cursor_system.fetchall() + + if rows_meters is not None and len(rows_meters) > 0: + for row in rows_meters: + meter_dict[row[1]] = {'id': row[0], 'unit': row[2]} + # get all offline meters + offline_meter_dict = dict() + query = (" SELECT m.id, m.uuid, ec.unit_of_measure " + " FROM tbl_offline_meters m, tbl_energy_categories ec " + " WHERE m.energy_category_id = ec.id ") + cursor_system.execute(query) + rows_offline_meters = cursor_system.fetchall() + + if rows_offline_meters is not None and len(rows_offline_meters) > 0: + for row in rows_offline_meters: + offline_meter_dict[row[1]] = {'id': row[0], 'unit': row[2]} + # get all virtual meters + virtual_meter_dict = dict() + query = (" SELECT m.id, m.uuid, ec.unit_of_measure " + " FROM tbl_virtual_meters m, tbl_energy_categories ec " + " WHERE m.energy_category_id = ec.id ") + cursor_system.execute(query) + rows_virtual_meters = cursor_system.fetchall() + + if rows_virtual_meters is not None and len(rows_virtual_meters) > 0: + for row in rows_virtual_meters: + virtual_meter_dict[row[1]] = {'id': row[0], 'unit': row[2]} + + if fraction_list is not None and len(fraction_list) > 0: + for fraction in fraction_list: + if fraction['numerator_meter_uuid'] in offline_meter_dict: + fraction['numerator_meter_id'] = offline_meter_dict[fraction['numerator_meter_uuid']]['id'] + fraction['numerator_meter_unit'] = offline_meter_dict[fraction['numerator_meter_uuid']]['unit'] + fraction['numerator_meter_type'] = 'offline_meter' + elif fraction['numerator_meter_uuid'] in virtual_meter_dict: + fraction['numerator_meter_id'] = virtual_meter_dict[fraction['numerator_meter_uuid']]['id'] + fraction['numerator_meter_unit'] = virtual_meter_dict[fraction['numerator_meter_uuid']]['unit'] + fraction['numerator_meter_type'] = 'virtual_meter' + elif fraction['numerator_meter_uuid'] in meter_dict: + fraction['numerator_meter_id'] = meter_dict[fraction['numerator_meter_uuid']]['id'] + fraction['numerator_meter_unit'] = meter_dict[fraction['numerator_meter_uuid']]['unit'] + fraction['numerator_meter_type'] = 'meter' + + if fraction['denominator_meter_uuid'] in offline_meter_dict: + fraction['denominator_meter_id'] = offline_meter_dict[fraction['denominator_meter_uuid']]['id'] + fraction['denominator_meter_unit'] = offline_meter_dict[fraction['denominator_meter_uuid']]['unit'] + fraction['denominator_meter_type'] = 'offline_meter' + elif fraction['denominator_meter_uuid'] in virtual_meter_dict: + fraction['denominator_meter_id'] = virtual_meter_dict[fraction['denominator_meter_uuid']]['id'] + fraction['denominator_meter_unit'] = virtual_meter_dict[fraction['denominator_meter_uuid']]['unit'] + fraction['denominator_meter_type'] = 'virtual_meter' + elif fraction['denominator_meter_uuid'] in meter_dict: + fraction['denominator_meter_id'] = meter_dict[fraction['denominator_meter_uuid']]['id'] + fraction['denominator_meter_unit'] = meter_dict[fraction['denominator_meter_uuid']]['unit'] + fraction['denominator_meter_type'] = 'meter' + + print(fraction_list) + + ################################################################################################################ + # Step 5: calculate base period fractions + ################################################################################################################ + base = dict() + if fraction_list is not None and len(fraction_list) > 0: + for fraction in fraction_list: + base[fraction['id']] = dict() + base[fraction['id']]['name'] = fraction['name'] + base[fraction['id']]['unit'] = fraction['numerator_meter_unit'] + '/' + \ + fraction['denominator_meter_unit'] + base[fraction['id']]['numerator_timestamps'] = list() + base[fraction['id']]['numerator_values'] = list() + base[fraction['id']]['numerator_cumulation'] = Decimal(0.0) + base[fraction['id']]['denominator_timestamps'] = list() + base[fraction['id']]['denominator_values'] = list() + base[fraction['id']]['denominator_cumulation'] = Decimal(0.0) + base[fraction['id']]['timestamps'] = list() + base[fraction['id']]['values'] = list() + base[fraction['id']]['cumulation'] = Decimal(0.0) + # query numerator meter output + if fraction['numerator_meter_type'] == 'meter': + query = (" SELECT start_datetime_utc, actual_value " + " FROM tbl_meter_hourly " + " WHERE meter_id = %s " + " AND start_datetime_utc >= %s " + " AND start_datetime_utc < %s " + " ORDER BY start_datetime_utc ") + elif fraction['numerator_meter_type'] == 'offline_meter': + query = (" SELECT start_datetime_utc, actual_value " + " FROM tbl_offline_meter_hourly " + " WHERE offline_meter_id = %s " + " AND start_datetime_utc >= %s " + " AND start_datetime_utc < %s " + " ORDER BY start_datetime_utc ") + elif fraction['numerator_meter_type'] == 'virtual_meter': + query = (" SELECT start_datetime_utc, actual_value " + " FROM tbl_virtual_meter_hourly " + " WHERE virtual_meter_id = %s " + " AND start_datetime_utc >= %s " + " AND start_datetime_utc < %s " + " ORDER BY start_datetime_utc ") + + cursor_energy.execute(query, (fraction['numerator_meter_id'], + base_start_datetime_utc, + base_end_datetime_utc)) + rows_numerator_meter_hourly = cursor_energy.fetchall() + + rows_numerator_meter_periodically = \ + utilities.aggregate_hourly_data_by_period(rows_numerator_meter_hourly, base_start_datetime_utc, base_end_datetime_utc, period_type) - for row_combined_equipment_periodically in rows_combined_equipment_periodically: - current_datetime_local = row_combined_equipment_periodically[0].replace(tzinfo=timezone.utc) + \ - timedelta(minutes=timezone_offset) - if period_type == 'hourly': - current_datetime = current_datetime_local.strftime('%Y-%m-%dT%H:%M:%S') - elif period_type == 'daily': - current_datetime = current_datetime_local.strftime('%Y-%m-%d') - elif period_type == 'monthly': - current_datetime = current_datetime_local.strftime('%Y-%m') - elif period_type == 'yearly': - current_datetime = current_datetime_local.strftime('%Y') + # query denominator meter input + if fraction['denominator_meter_type'] == 'meter': + query = (" SELECT start_datetime_utc, actual_value " + " FROM tbl_meter_hourly " + " WHERE meter_id = %s " + " AND start_datetime_utc >= %s " + " AND start_datetime_utc < %s " + " ORDER BY start_datetime_utc ") + elif fraction['denominator_meter_type'] == 'offline_meter': + query = (" SELECT start_datetime_utc, actual_value " + " FROM tbl_offline_meter_hourly " + " WHERE offline_meter_id = %s " + " AND start_datetime_utc >= %s " + " AND start_datetime_utc < %s " + " ORDER BY start_datetime_utc ") + elif fraction['denominator_meter_type'] == 'virtual_meter': + query = (" SELECT start_datetime_utc, actual_value " + " FROM tbl_virtual_meter_hourly " + " WHERE virtual_meter_id = %s " + " AND start_datetime_utc >= %s " + " AND start_datetime_utc < %s " + " ORDER BY start_datetime_utc ") - actual_value = Decimal(0.0) if row_combined_equipment_periodically[1] is None \ - else row_combined_equipment_periodically[1] - base_input[energy_category_id]['timestamps'].append(current_datetime) - base_input[energy_category_id]['values'].append(actual_value) - base_input[energy_category_id]['subtotal'] += actual_value + cursor_energy.execute(query, (fraction['denominator_meter_id'], + base_start_datetime_utc, + base_end_datetime_utc)) + rows_denominator_meter_hourly = cursor_energy.fetchall() - ################################################################################################################ - # Step 7: query base period energy output - ################################################################################################################ - base_output = dict() - if energy_category_set_output is not None and len(energy_category_set_output) > 0: - for energy_category_id in energy_category_set_output: - base_output[energy_category_id] = dict() - base_output[energy_category_id]['timestamps'] = list() - base_output[energy_category_id]['values'] = list() - base_output[energy_category_id]['subtotal'] = Decimal(0.0) - - cursor_energy.execute(" SELECT start_datetime_utc, actual_value " - " FROM tbl_combined_equipment_output_category_hourly " - " WHERE combined_equipment_id = %s " - " AND energy_category_id = %s " - " AND start_datetime_utc >= %s " - " AND start_datetime_utc < %s " - " ORDER BY start_datetime_utc ", - (combined_equipment['id'], - energy_category_id, - base_start_datetime_utc, - base_end_datetime_utc)) - rows_combined_equipment_hourly = cursor_energy.fetchall() - - rows_combined_equipment_periodically = \ - utilities.aggregate_hourly_data_by_period(rows_combined_equipment_hourly, + rows_denominator_meter_periodically = \ + utilities.aggregate_hourly_data_by_period(rows_denominator_meter_hourly, base_start_datetime_utc, base_end_datetime_utc, period_type) - for row_combined_equipment_periodically in rows_combined_equipment_periodically: - current_datetime_local = row_combined_equipment_periodically[0].replace(tzinfo=timezone.utc) + \ + + for row_numerator_meter_periodically in rows_numerator_meter_periodically: + current_datetime_local = row_numerator_meter_periodically[0].replace(tzinfo=timezone.utc) + \ timedelta(minutes=timezone_offset) if period_type == 'hourly': current_datetime = current_datetime_local.strftime('%Y-%m-%dT%H:%M:%S') @@ -354,91 +357,133 @@ class Reporting: elif period_type == 'yearly': current_datetime = current_datetime_local.strftime('%Y') - actual_value = Decimal(0.0) if row_combined_equipment_periodically[1] is None \ - else row_combined_equipment_periodically[1] - base_output[energy_category_id]['timestamps'].append(current_datetime) - base_output[energy_category_id]['values'].append(actual_value) - base_output[energy_category_id]['subtotal'] += actual_value + actual_value = Decimal(0.0) if row_numerator_meter_periodically[1] is None \ + else row_numerator_meter_periodically[1] + + base[fraction['id']]['numerator_timestamps'].append(current_datetime) + base[fraction['id']]['numerator_values'].append(actual_value) + base[fraction['id']]['numerator_cumulation'] += actual_value + + for row_denominator_meter_periodically in rows_denominator_meter_periodically: + current_datetime_local = row_denominator_meter_periodically[0].replace(tzinfo=timezone.utc) + \ + timedelta(minutes=timezone_offset) + if period_type == 'hourly': + current_datetime = current_datetime_local.strftime('%Y-%m-%dT%H:%M:%S') + elif period_type == 'daily': + current_datetime = current_datetime_local.strftime('%Y-%m-%d') + elif period_type == 'monthly': + current_datetime = current_datetime_local.strftime('%Y-%m') + elif period_type == 'yearly': + current_datetime = current_datetime_local.strftime('%Y') + + actual_value = Decimal(0.0) if row_denominator_meter_periodically[1] is None \ + else row_denominator_meter_periodically[1] + + base[fraction['id']]['denominator_timestamps'].append(current_datetime) + base[fraction['id']]['denominator_values'].append(actual_value) + base[fraction['id']]['denominator_cumulation'] += actual_value + + for i in range(len(base[fraction['id']]['denominator_timestamps'])): + timestamp = base[fraction['id']]['denominator_timestamps'][i] + base[fraction['id']]['timestamps'].append(timestamp) + value = (base[fraction['id']]['numerator_values'][i] / + base[fraction['id']]['denominator_values'][i]) \ + if base[fraction['id']]['denominator_values'][i] > Decimal(0.0) else Decimal(0.0) + base[fraction['id']]['values'].append(value) + + cumulation = (base[fraction['id']]['numerator_cumulation'] / + base[fraction['id']]['denominator_cumulation']) \ + if base[fraction['id']]['denominator_cumulation'] > Decimal(0.0) else Decimal(0.0) + base[fraction['id']]['cumulation'] = cumulation + ################################################################################################################ - # Step 8: query reporting period energy input + # Step 6: calculate reporting period fractions ################################################################################################################ - reporting_input = dict() - if energy_category_set_input is not None and len(energy_category_set_input) > 0: - for energy_category_id in energy_category_set_input: + reporting = dict() + if fraction_list is not None and len(fraction_list) > 0: + for fraction in fraction_list: + reporting[fraction['id']] = dict() + reporting[fraction['id']]['name'] = fraction['name'] + reporting[fraction['id']]['unit'] = fraction['numerator_meter_unit'] + '/' + \ + fraction['denominator_meter_unit'] + reporting[fraction['id']]['numerator_timestamps'] = list() + reporting[fraction['id']]['numerator_values'] = list() + reporting[fraction['id']]['numerator_cumulation'] = Decimal(0.0) + reporting[fraction['id']]['denominator_timestamps'] = list() + reporting[fraction['id']]['denominator_values'] = list() + reporting[fraction['id']]['denominator_cumulation'] = Decimal(0.0) + reporting[fraction['id']]['timestamps'] = list() + reporting[fraction['id']]['values'] = list() + reporting[fraction['id']]['cumulation'] = Decimal(0.0) + # query numerator meter output + if fraction['numerator_meter_type'] == 'meter': + query = (" SELECT start_datetime_utc, actual_value " + " FROM tbl_meter_hourly " + " WHERE meter_id = %s " + " AND start_datetime_utc >= %s " + " AND start_datetime_utc < %s " + " ORDER BY start_datetime_utc ") + elif fraction['numerator_meter_type'] == 'offline_meter': + query = (" SELECT start_datetime_utc, actual_value " + " FROM tbl_offline_meter_hourly " + " WHERE offline_meter_id = %s " + " AND start_datetime_utc >= %s " + " AND start_datetime_utc < %s " + " ORDER BY start_datetime_utc ") + elif fraction['numerator_meter_type'] == 'virtual_meter': + query = (" SELECT start_datetime_utc, actual_value " + " FROM tbl_virtual_meter_hourly " + " WHERE virtual_meter_id = %s " + " AND start_datetime_utc >= %s " + " AND start_datetime_utc < %s " + " ORDER BY start_datetime_utc ") - reporting_input[energy_category_id] = dict() - reporting_input[energy_category_id]['timestamps'] = list() - reporting_input[energy_category_id]['values'] = list() - reporting_input[energy_category_id]['subtotal'] = Decimal(0.0) + cursor_energy.execute(query, (fraction['numerator_meter_id'], + reporting_start_datetime_utc, + reporting_end_datetime_utc)) + rows_numerator_meter_hourly = cursor_energy.fetchall() - cursor_energy.execute(" SELECT start_datetime_utc, actual_value " - " FROM tbl_combined_equipment_input_category_hourly " - " WHERE combined_equipment_id = %s " - " AND energy_category_id = %s " - " AND start_datetime_utc >= %s " - " AND start_datetime_utc < %s " - " ORDER BY start_datetime_utc ", - (combined_equipment['id'], - energy_category_id, - reporting_start_datetime_utc, - reporting_end_datetime_utc)) - rows_combined_equipment_hourly = cursor_energy.fetchall() - - rows_combined_equipment_periodically = \ - utilities.aggregate_hourly_data_by_period(rows_combined_equipment_hourly, + rows_numerator_meter_periodically = \ + utilities.aggregate_hourly_data_by_period(rows_numerator_meter_hourly, reporting_start_datetime_utc, reporting_end_datetime_utc, period_type) - for row_combined_equipment_periodically in rows_combined_equipment_periodically: - current_datetime_local = row_combined_equipment_periodically[0].replace(tzinfo=timezone.utc) + \ - timedelta(minutes=timezone_offset) - if period_type == 'hourly': - current_datetime = current_datetime_local.strftime('%Y-%m-%dT%H:%M:%S') - elif period_type == 'daily': - current_datetime = current_datetime_local.strftime('%Y-%m-%d') - elif period_type == 'monthly': - current_datetime = current_datetime_local.strftime('%Y-%m') - elif period_type == 'yearly': - current_datetime = current_datetime_local.strftime('%Y') + # query denominator meter input + if fraction['denominator_meter_type'] == 'meter': + query = (" SELECT start_datetime_utc, actual_value " + " FROM tbl_meter_hourly " + " WHERE meter_id = %s " + " AND start_datetime_utc >= %s " + " AND start_datetime_utc < %s " + " ORDER BY start_datetime_utc ") + elif fraction['denominator_meter_type'] == 'offline_meter': + query = (" SELECT start_datetime_utc, actual_value " + " FROM tbl_offline_meter_hourly " + " WHERE offline_meter_id = %s " + " AND start_datetime_utc >= %s " + " AND start_datetime_utc < %s " + " ORDER BY start_datetime_utc ") + elif fraction['denominator_meter_type'] == 'virtual_meter': + query = (" SELECT start_datetime_utc, actual_value " + " FROM tbl_virtual_meter_hourly " + " WHERE virtual_meter_id = %s " + " AND start_datetime_utc >= %s " + " AND start_datetime_utc < %s " + " ORDER BY start_datetime_utc ") - actual_value = Decimal(0.0) if row_combined_equipment_periodically[1] is None \ - else row_combined_equipment_periodically[1] - reporting_input[energy_category_id]['timestamps'].append(current_datetime) - reporting_input[energy_category_id]['values'].append(actual_value) - reporting_input[energy_category_id]['subtotal'] += actual_value + cursor_energy.execute(query, (fraction['denominator_meter_id'], + reporting_start_datetime_utc, + reporting_end_datetime_utc)) + rows_denominator_meter_hourly = cursor_energy.fetchall() - ################################################################################################################ - # Step 9: query reporting period energy output - ################################################################################################################ - reporting_output = dict() - if energy_category_set_output is not None and len(energy_category_set_output) > 0: - for energy_category_id in energy_category_set_output: - - reporting_output[energy_category_id] = dict() - reporting_output[energy_category_id]['timestamps'] = list() - reporting_output[energy_category_id]['values'] = list() - reporting_output[energy_category_id]['subtotal'] = Decimal(0.0) - - cursor_energy.execute(" SELECT start_datetime_utc, actual_value " - " FROM tbl_combined_equipment_output_category_hourly " - " WHERE combined_equipment_id = %s " - " AND energy_category_id = %s " - " AND start_datetime_utc >= %s " - " AND start_datetime_utc < %s " - " ORDER BY start_datetime_utc ", - (combined_equipment['id'], - energy_category_id, - reporting_start_datetime_utc, - reporting_end_datetime_utc)) - rows_combined_equipment_hourly = cursor_energy.fetchall() - - rows_combined_equipment_periodically = \ - utilities.aggregate_hourly_data_by_period(rows_combined_equipment_hourly, + rows_denominator_meter_periodically = \ + utilities.aggregate_hourly_data_by_period(rows_denominator_meter_hourly, reporting_start_datetime_utc, reporting_end_datetime_utc, period_type) - for row_combined_equipment_periodically in rows_combined_equipment_periodically: - current_datetime_local = row_combined_equipment_periodically[0].replace(tzinfo=timezone.utc) + \ + + for row_numerator_meter_periodically in rows_numerator_meter_periodically: + current_datetime_local = row_numerator_meter_periodically[0].replace(tzinfo=timezone.utc) + \ timedelta(minutes=timezone_offset) if period_type == 'hourly': current_datetime = current_datetime_local.strftime('%Y-%m-%dT%H:%M:%S') @@ -449,42 +494,53 @@ class Reporting: elif period_type == 'yearly': current_datetime = current_datetime_local.strftime('%Y') - actual_value = Decimal(0.0) if row_combined_equipment_periodically[1] is None \ - else row_combined_equipment_periodically[1] - reporting_output[energy_category_id]['timestamps'].append(current_datetime) - reporting_output[energy_category_id]['values'].append(actual_value) - reporting_output[energy_category_id]['subtotal'] += actual_value + actual_value = Decimal(0.0) if row_numerator_meter_periodically[1] is None \ + else row_numerator_meter_periodically[1] + + reporting[fraction['id']]['numerator_timestamps'].append(current_datetime) + reporting[fraction['id']]['numerator_values'].append(actual_value) + reporting[fraction['id']]['numerator_cumulation'] += actual_value + + for row_denominator_meter_periodically in rows_denominator_meter_periodically: + current_datetime_local = row_denominator_meter_periodically[0].replace(tzinfo=timezone.utc) + \ + timedelta(minutes=timezone_offset) + if period_type == 'hourly': + current_datetime = current_datetime_local.strftime('%Y-%m-%dT%H:%M:%S') + elif period_type == 'daily': + current_datetime = current_datetime_local.strftime('%Y-%m-%d') + elif period_type == 'monthly': + current_datetime = current_datetime_local.strftime('%Y-%m') + elif period_type == 'yearly': + current_datetime = current_datetime_local.strftime('%Y') + + actual_value = Decimal(0.0) if row_denominator_meter_periodically[1] is None \ + else row_denominator_meter_periodically[1] + + reporting[fraction['id']]['denominator_timestamps'].append(current_datetime) + reporting[fraction['id']]['denominator_values'].append(actual_value) + reporting[fraction['id']]['denominator_cumulation'] += actual_value + + for i in range(len(reporting[fraction['id']]['denominator_timestamps'])): + timestamp = reporting[fraction['id']]['denominator_timestamps'][i] + reporting[fraction['id']]['timestamps'].append(timestamp) + value = reporting[fraction['id']]['numerator_values'][i] / \ + reporting[fraction['id']]['denominator_values'][i] \ + if reporting[fraction['id']]['denominator_values'][i] > Decimal(0.0) else Decimal(0.0) + reporting[fraction['id']]['values'].append(value) + + cumulation = (reporting[fraction['id']]['numerator_cumulation'] / + reporting[fraction['id']]['denominator_cumulation']) \ + if reporting[fraction['id']]['denominator_cumulation'] > Decimal(0.0) else Decimal(0.0) + reporting[fraction['id']]['cumulation'] = cumulation ################################################################################################################ - # Step 10: query tariff data + # Step 7: query associated points data ################################################################################################################ parameters_data = dict() parameters_data['names'] = list() parameters_data['timestamps'] = list() parameters_data['values'] = list() - if energy_category_set_input is not None and len(energy_category_set_input) > 0: - for energy_category_id in energy_category_set_input: - energy_category_tariff_dict = utilities.get_energy_category_tariffs( - combined_equipment['cost_center_id'], - energy_category_id, - reporting_start_datetime_utc, - reporting_end_datetime_utc) - tariff_timestamp_list = list() - tariff_value_list = list() - for k, v in energy_category_tariff_dict.items(): - # convert k from utc to local - k = k + timedelta(minutes=timezone_offset) - tariff_timestamp_list.append(k.isoformat()[0:19][0:19]) - tariff_value_list.append(v) - - parameters_data['names'].append('TARIFF-' + energy_category_dict[energy_category_id]['name']) - parameters_data['timestamps'].append(tariff_timestamp_list) - parameters_data['values'].append(tariff_value_list) - - ################################################################################################################ - # Step 11: query associated points data - ################################################################################################################ for point in point_list: point_values = [] point_timestamps = [] @@ -548,7 +604,7 @@ class Reporting: parameters_data['values'].append(point_values) ################################################################################################################ - # Step 12: construct the report + # Step 8: construct the report ################################################################################################################ if cursor_system: cursor_system.close() @@ -565,119 +621,11 @@ class Reporting: result['combined_equipment'] = dict() result['combined_equipment']['name'] = combined_equipment['name'] - result['base_period_input'] = dict() - result['base_period_input']['names'] = list() - result['base_period_input']['units'] = list() - result['base_period_input']['timestamps'] = list() - result['base_period_input']['values'] = list() - result['base_period_input']['subtotals'] = list() - if energy_category_set_input is not None and len(energy_category_set_input) > 0: - for energy_category_id in energy_category_set_input: - result['base_period_input']['names'].append(energy_category_dict[energy_category_id]['name']) - result['base_period_input']['units'].append(energy_category_dict[energy_category_id]['unit_of_measure']) - result['base_period_input']['timestamps'].append(base_input[energy_category_id]['timestamps']) - result['base_period_input']['values'].append(base_input[energy_category_id]['values']) - result['base_period_input']['subtotals'].append(base_input[energy_category_id]['subtotal']) - - result['base_period_output'] = dict() - result['base_period_output']['names'] = list() - result['base_period_output']['units'] = list() - result['base_period_output']['timestamps'] = list() - result['base_period_output']['values'] = list() - result['base_period_output']['subtotals'] = list() - - if energy_category_set_output is not None and len(energy_category_set_output) > 0: - for energy_category_id in energy_category_set_output: - result['base_period_output']['names'].append(energy_category_dict[energy_category_id]['name']) - result['base_period_output']['units'].append( - energy_category_dict[energy_category_id]['unit_of_measure']) - result['base_period_output']['timestamps'].append(base_output[energy_category_id]['timestamps']) - result['base_period_output']['values'].append(base_output[energy_category_id]['values']) - result['base_period_output']['subtotals'].append(base_output[energy_category_id]['subtotal']) - result['base_period_efficiency'] = dict() - result['base_period_efficiency']['names'] = list() - result['base_period_efficiency']['units'] = list() result['base_period_efficiency']['timestamps'] = list() result['base_period_efficiency']['values'] = list() result['base_period_efficiency']['cumulations'] = list() - if energy_category_set_output is not None and len(energy_category_set_output) > 0: - for energy_category_id_output in energy_category_set_output: - for energy_category_id_input in energy_category_set_input: - result['base_period_efficiency']['names'].append( - energy_category_dict[energy_category_id_output]['name'] + '/' + - energy_category_dict[energy_category_id_input]['name']) - result['base_period_efficiency']['units'].append( - energy_category_dict[energy_category_id_output]['unit_of_measure'] + '/' + - energy_category_dict[energy_category_id_input]['unit_of_measure']) - result['base_period_efficiency']['timestamps'].append( - base_output[energy_category_id_output]['timestamps']) - efficiency_values = list() - for i in range(len(base_output[energy_category_id_output]['timestamps'])): - efficiency_values.append((base_output[energy_category_id_output]['values'][i] / - base_input[energy_category_id_input]['values'][i]) - if base_input[energy_category_id_input]['values'][i] > Decimal(0.0) - else None) - result['base_period_efficiency']['values'].append(efficiency_values) - - base_cumulation = (base_output[energy_category_id_output]['subtotal'] / - base_input[energy_category_id_input]['subtotal']) if \ - base_input[energy_category_id_input]['subtotal'] > Decimal(0.0) else None - result['base_period_efficiency']['cumulations'].append(base_cumulation) - - result['reporting_period_input'] = dict() - result['reporting_period_input']['names'] = list() - result['reporting_period_input']['energy_category_ids'] = list() - result['reporting_period_input']['units'] = list() - result['reporting_period_input']['timestamps'] = list() - result['reporting_period_input']['values'] = list() - result['reporting_period_input']['subtotals'] = list() - result['reporting_period_input']['increment_rates'] = list() - - if energy_category_set_input is not None and len(energy_category_set_input) > 0: - for energy_category_id in energy_category_set_input: - result['reporting_period_input']['names'].append(energy_category_dict[energy_category_id]['name']) - result['reporting_period_input']['energy_category_ids'].append(energy_category_id) - result['reporting_period_input']['units'].append( - energy_category_dict[energy_category_id]['unit_of_measure']) - result['reporting_period_input']['timestamps'].append( - reporting_input[energy_category_id]['timestamps']) - result['reporting_period_input']['values'].append( - reporting_input[energy_category_id]['values']) - result['reporting_period_input']['subtotals'].append( - reporting_input[energy_category_id]['subtotal']) - result['reporting_period_input']['increment_rates'].append( - (reporting_input[energy_category_id]['subtotal'] - - base_input[energy_category_id]['subtotal']) / - base_input[energy_category_id]['subtotal'] - if base_input[energy_category_id]['subtotal'] > 0.0 else None) - - result['reporting_period_output'] = dict() - result['reporting_period_output']['names'] = list() - result['reporting_period_output']['energy_category_ids'] = list() - result['reporting_period_output']['units'] = list() - result['reporting_period_output']['timestamps'] = list() - result['reporting_period_output']['values'] = list() - result['reporting_period_output']['subtotals'] = list() - result['reporting_period_output']['increment_rates'] = list() - - if energy_category_set_output is not None and len(energy_category_set_output) > 0: - for energy_category_id in energy_category_set_output: - result['reporting_period_output']['names'].append(energy_category_dict[energy_category_id]['name']) - result['reporting_period_output']['energy_category_ids'].append(energy_category_id) - result['reporting_period_output']['units'].append( - energy_category_dict[energy_category_id]['unit_of_measure']) - result['reporting_period_output']['timestamps'].append( - reporting_output[energy_category_id]['timestamps']) - result['reporting_period_output']['values'].append(reporting_output[energy_category_id]['values']) - result['reporting_period_output']['subtotals'].append(reporting_output[energy_category_id]['subtotal']) - result['reporting_period_output']['increment_rates'].append( - (reporting_output[energy_category_id]['subtotal'] - - base_output[energy_category_id]['subtotal']) / - base_output[energy_category_id]['subtotal'] - if base_output[energy_category_id]['subtotal'] > 0.0 else None) - result['reporting_period_efficiency'] = dict() result['reporting_period_efficiency']['names'] = list() result['reporting_period_efficiency']['units'] = list() @@ -685,39 +633,19 @@ class Reporting: result['reporting_period_efficiency']['values'] = list() result['reporting_period_efficiency']['cumulations'] = list() result['reporting_period_efficiency']['increment_rates'] = list() - - if energy_category_set_output is not None and len(energy_category_set_output) > 0: - for energy_category_id_output in energy_category_set_output: - for energy_category_id_input in energy_category_set_input: - result['reporting_period_efficiency']['names'].append( - energy_category_dict[energy_category_id_output]['name'] + '/' + - energy_category_dict[energy_category_id_input]['name']) - result['reporting_period_efficiency']['units'].append( - energy_category_dict[energy_category_id_output]['unit_of_measure'] + '/' + - energy_category_dict[energy_category_id_input]['unit_of_measure']) - result['reporting_period_efficiency']['timestamps'].append( - reporting_output[energy_category_id_output]['timestamps']) - efficiency_values = list() - for i in range(len(reporting_output[energy_category_id_output]['timestamps'])): - efficiency_values.append((reporting_output[energy_category_id_output]['values'][i] / - reporting_input[energy_category_id_input]['values'][i]) - if reporting_input[energy_category_id_input]['values'][i] > - Decimal(0.0) else None) - result['reporting_period_efficiency']['values'].append(efficiency_values) - - base_cumulation = (base_output[energy_category_id_output]['subtotal'] / - base_input[energy_category_id_input]['subtotal']) if \ - base_input[energy_category_id_input]['subtotal'] > Decimal(0.0) else None - - reporting_cumulation = (reporting_output[energy_category_id_output]['subtotal'] / - reporting_input[energy_category_id_input]['subtotal']) if \ - reporting_input[energy_category_id_input]['subtotal'] > Decimal(0.0) else None - - result['reporting_period_efficiency']['cumulations'].append(reporting_cumulation) - result['reporting_period_efficiency']['increment_rates'].append( - ((reporting_cumulation - base_cumulation) / base_cumulation if (base_cumulation > Decimal(0.0)) - else None) - ) + if fraction_list is not None and len(fraction_list) > 0: + for fraction in fraction_list: + result['base_period_efficiency']['timestamps'].append(base[fraction['id']]['timestamps']) + result['base_period_efficiency']['values'].append(base[fraction['id']]['values']) + result['base_period_efficiency']['cumulations'].append(base[fraction['id']]['cumulation']) + result['reporting_period_efficiency']['names'].append(reporting[fraction['id']]['name']) + result['reporting_period_efficiency']['units'].append(reporting[fraction['id']]['unit']) + result['reporting_period_efficiency']['timestamps'].append(reporting[fraction['id']]['timestamps']) + result['reporting_period_efficiency']['values'].append(reporting[fraction['id']]['values']) + result['reporting_period_efficiency']['cumulations'].append(reporting[fraction['id']]['cumulation']) + result['reporting_period_efficiency']['increment_rates'].append( + (reporting[fraction['id']]['cumulation'] - base[fraction['id']]['cumulation']) / + base[fraction['id']]['cumulation'] if base[fraction['id']]['cumulation'] > Decimal(0.0) else None) result['parameters'] = { "names": parameters_data['names'], @@ -725,4 +653,11 @@ class Reporting: "values": parameters_data['values'] } + # export result to Excel file and then encode the file to base64 string + result['excel_bytes_base64'] = excelexporters.combinedequipmentefficiency.export(result, + combined_equipment['name'], + reporting_start_datetime_local, + reporting_end_datetime_local, + period_type) + resp.body = json.dumps(result) diff --git a/myems-api/reports/combinedequipmentenergycategory.py b/myems-api/reports/combinedequipmentenergycategory.py index 91a62864..0bc905d4 100644 --- a/myems-api/reports/combinedequipmentenergycategory.py +++ b/myems-api/reports/combinedequipmentenergycategory.py @@ -148,10 +148,10 @@ class Reporting: if cnx_energy: cnx_energy.disconnect() - if cnx_historical: - cnx_historical.close() if cursor_historical: - cursor_historical.disconnect() + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.COMBINED_EQUIPMENT_NOT_FOUND') @@ -205,10 +205,10 @@ class Reporting: if cnx_energy: cnx_energy.disconnect() - if cnx_historical: - cnx_historical.close() if cursor_historical: - cursor_historical.disconnect() + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.ENERGY_CATEGORY_NOT_FOUND') @@ -466,6 +466,11 @@ class Reporting: if cnx_energy: cnx_energy.disconnect() + if cursor_historical: + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() + result = dict() result['combined_equipment'] = dict() diff --git a/myems-api/reports/combinedequipmentenergyitem.py b/myems-api/reports/combinedequipmentenergyitem.py index 5e25004a..ced3add1 100644 --- a/myems-api/reports/combinedequipmentenergyitem.py +++ b/myems-api/reports/combinedequipmentenergyitem.py @@ -148,10 +148,10 @@ class Reporting: if cnx_energy: cnx_energy.disconnect() - if cnx_historical: - cnx_historical.close() if cursor_historical: - cursor_historical.disconnect() + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.COMBINED_EQUIPMENT_NOT_FOUND') @@ -207,10 +207,10 @@ class Reporting: if cnx_energy: cnx_energy.disconnect() - if cnx_historical: - cnx_historical.close() if cursor_historical: - cursor_historical.disconnect() + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.ENERGY_ITEM_NOT_FOUND') @@ -456,6 +456,11 @@ class Reporting: if cnx_energy: cnx_energy.disconnect() + if cursor_historical: + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() + result = dict() result['combined_equipment'] = dict() diff --git a/myems-api/reports/combinedequipmentincome.py b/myems-api/reports/combinedequipmentincome.py index 4c8a0ade..af64fc8d 100644 --- a/myems-api/reports/combinedequipmentincome.py +++ b/myems-api/reports/combinedequipmentincome.py @@ -148,10 +148,10 @@ class Reporting: if cnx_billing: cnx_billing.disconnect() - if cnx_historical: - cnx_historical.close() if cursor_historical: - cursor_historical.disconnect() + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.COMBINED_EQUIPMENT_NOT_FOUND') @@ -205,10 +205,10 @@ class Reporting: if cnx_billing: cnx_billing.disconnect() - if cnx_historical: - cnx_historical.close() if cursor_historical: - cursor_historical.disconnect() + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.ENERGY_CATEGORY_NOT_FOUND') @@ -432,6 +432,11 @@ class Reporting: if cnx_billing: cnx_billing.disconnect() + if cursor_historical: + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() + result = dict() result['combined_equipment'] = dict() diff --git a/myems-api/reports/combinedequipmentload.py b/myems-api/reports/combinedequipmentload.py index e47d9752..0751dc6e 100644 --- a/myems-api/reports/combinedequipmentload.py +++ b/myems-api/reports/combinedequipmentload.py @@ -148,10 +148,10 @@ class Reporting: if cnx_energy: cnx_energy.disconnect() - if cnx_historical: - cnx_historical.close() if cursor_historical: - cursor_historical.disconnect() + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.COMBINED_EQUIPMENT_NOT_FOUND') @@ -205,10 +205,10 @@ class Reporting: if cnx_energy: cnx_energy.disconnect() - if cnx_historical: - cnx_historical.close() if cursor_historical: - cursor_historical.disconnect() + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.ENERGY_CATEGORY_NOT_FOUND') @@ -452,6 +452,11 @@ class Reporting: if cnx_energy: cnx_energy.disconnect() + if cursor_historical: + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() + result = dict() result['combined_equipment'] = dict() diff --git a/myems-api/reports/combinedequipmentoutput.py b/myems-api/reports/combinedequipmentoutput.py index 60e30665..28aeb015 100644 --- a/myems-api/reports/combinedequipmentoutput.py +++ b/myems-api/reports/combinedequipmentoutput.py @@ -148,10 +148,10 @@ class Reporting: if cnx_energy: cnx_energy.disconnect() - if cnx_historical: - cnx_historical.close() if cursor_historical: - cursor_historical.disconnect() + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.COMBINED_EQUIPMENT_NOT_FOUND') @@ -205,10 +205,10 @@ class Reporting: if cnx_energy: cnx_energy.disconnect() - if cnx_historical: - cnx_historical.close() if cursor_historical: - cursor_historical.disconnect() + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.ENERGY_CATEGORY_NOT_FOUND') @@ -432,6 +432,11 @@ class Reporting: if cnx_energy: cnx_energy.disconnect() + if cursor_historical: + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() + result = dict() result['combined_equipment'] = dict() diff --git a/myems-api/reports/combinedequipmentsaving.py b/myems-api/reports/combinedequipmentsaving.py index e66b21d1..b55dbcbc 100644 --- a/myems-api/reports/combinedequipmentsaving.py +++ b/myems-api/reports/combinedequipmentsaving.py @@ -156,10 +156,10 @@ class Reporting: if cnx_energy_baseline: cnx_energy_baseline.disconnect() - if cnx_historical: - cnx_historical.close() if cursor_historical: - cursor_historical.disconnect() + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.COMBINED_EQUIPMENT_NOT_FOUND') @@ -218,10 +218,10 @@ class Reporting: if cnx_energy_baseline: cnx_energy_baseline.disconnect() - if cnx_historical: - cnx_historical.close() if cursor_historical: - cursor_historical.disconnect() + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.ENERGY_CATEGORY_NOT_FOUND') @@ -586,6 +586,11 @@ class Reporting: if cnx_energy_baseline: cnx_energy_baseline.disconnect() + if cursor_historical: + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() + result = dict() result['combined_equipment'] = dict() diff --git a/myems-api/reports/combinedequipmentstatistics.py b/myems-api/reports/combinedequipmentstatistics.py index c24ec5b1..5e9b579c 100644 --- a/myems-api/reports/combinedequipmentstatistics.py +++ b/myems-api/reports/combinedequipmentstatistics.py @@ -148,10 +148,10 @@ class Reporting: if cnx_energy: cnx_energy.disconnect() - if cnx_historical: - cnx_historical.close() if cursor_historical: - cursor_historical.disconnect() + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.COMBINED_EQUIPMENT_NOT_FOUND') @@ -205,10 +205,10 @@ class Reporting: if cnx_energy: cnx_energy.disconnect() - if cnx_historical: - cnx_historical.close() if cursor_historical: - cursor_historical.disconnect() + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.ENERGY_CATEGORY_NOT_FOUND') @@ -458,6 +458,11 @@ class Reporting: if cnx_energy: cnx_energy.disconnect() + if cursor_historical: + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() + result = dict() result['combined_equipment'] = dict() diff --git a/myems-api/reports/equipmentcost.py b/myems-api/reports/equipmentcost.py index e6c2cf53..ed96fea5 100644 --- a/myems-api/reports/equipmentcost.py +++ b/myems-api/reports/equipmentcost.py @@ -143,10 +143,10 @@ class Reporting: if cnx_billing: cnx_billing.disconnect() - if cnx_historical: - cnx_historical.close() if cursor_historical: - cursor_historical.disconnect() + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.EQUIPMENT_NOT_FOUND') equipment = dict() @@ -198,10 +198,10 @@ class Reporting: if cnx_billing: cnx_billing.disconnect() - if cnx_historical: - cnx_historical.close() if cursor_historical: - cursor_historical.disconnect() + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.ENERGY_CATEGORY_NOT_FOUND') @@ -441,6 +441,11 @@ class Reporting: if cnx_billing: cnx_billing.disconnect() + if cursor_historical: + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() + result = dict() result['equipment'] = dict() diff --git a/myems-api/reports/equipmentefficiency.py b/myems-api/reports/equipmentefficiency.py index 45f23f95..e4794163 100644 --- a/myems-api/reports/equipmentefficiency.py +++ b/myems-api/reports/equipmentefficiency.py @@ -5,6 +5,7 @@ import config from datetime import datetime, timedelta, timezone from core import utilities from decimal import Decimal +import excelexporters.equipmentefficiency class Reporting: @@ -20,17 +21,13 @@ class Reporting: # PROCEDURES # Step 1: valid parameters # Step 2: query the equipment - # Step 3: query energy categories - # Step 4: query associated constants - # Step 4: query associated points - # Step 5: query associated fractions - # Step 5: query base period energy input - # Step 6: query base period energy output - # Step 7: query reporting period energy input - # Step 8: query reporting period energy output - # Step 9: query tariff data - # Step 10: query associated points data - # Step 11: construct the report + # Step 3: query associated points + # Step 4: query associated fractions + # Step 5: query fractions' numerator and denominator + # Step 6: calculate base period fractions + # Step 7: calculate reporting period fractions + # Step 8: query associated points data + # Step 9: construct the report #################################################################################################################### @staticmethod def on_get(req, resp): @@ -147,10 +144,10 @@ class Reporting: if cnx_energy: cnx_energy.disconnect() - if cnx_historical: - cnx_historical.close() if cursor_historical: - cursor_historical.disconnect() + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.EQUIPMENT_NOT_FOUND') equipment = dict() @@ -159,92 +156,7 @@ class Reporting: equipment['cost_center_id'] = row_equipment[2] ################################################################################################################ - # Step 3: query input energy categories and output energy categories - ################################################################################################################ - energy_category_set_input = set() - energy_category_set_output = set() - # query input energy categories in base period - cursor_energy.execute(" SELECT DISTINCT(energy_category_id) " - " FROM tbl_equipment_input_category_hourly " - " WHERE equipment_id = %s " - " AND start_datetime_utc >= %s " - " AND start_datetime_utc < %s ", - (equipment['id'], base_start_datetime_utc, base_end_datetime_utc)) - rows_energy_categories = cursor_energy.fetchall() - if rows_energy_categories is not None or len(rows_energy_categories) > 0: - for row_energy_category in rows_energy_categories: - energy_category_set_input.add(row_energy_category[0]) - - # query input energy categories in reporting period - cursor_energy.execute(" SELECT DISTINCT(energy_category_id) " - " FROM tbl_equipment_input_category_hourly " - " WHERE equipment_id = %s " - " AND start_datetime_utc >= %s " - " AND start_datetime_utc < %s ", - (equipment['id'], reporting_start_datetime_utc, reporting_end_datetime_utc)) - rows_energy_categories = cursor_energy.fetchall() - if rows_energy_categories is not None or len(rows_energy_categories) > 0: - for row_energy_category in rows_energy_categories: - energy_category_set_input.add(row_energy_category[0]) - - # query output energy categories in base period - cursor_energy.execute(" SELECT DISTINCT(energy_category_id) " - " FROM tbl_equipment_output_category_hourly " - " WHERE equipment_id = %s " - " AND start_datetime_utc >= %s " - " AND start_datetime_utc < %s ", - (equipment['id'], base_start_datetime_utc, base_end_datetime_utc)) - rows_energy_categories = cursor_energy.fetchall() - if rows_energy_categories is not None or len(rows_energy_categories) > 0: - for row_energy_category in rows_energy_categories: - energy_category_set_output.add(row_energy_category[0]) - - # query output energy categories in reporting period - cursor_energy.execute(" SELECT DISTINCT(energy_category_id) " - " FROM tbl_equipment_output_category_hourly " - " WHERE equipment_id = %s " - " AND start_datetime_utc >= %s " - " AND start_datetime_utc < %s ", - (equipment['id'], reporting_start_datetime_utc, reporting_end_datetime_utc)) - rows_energy_categories = cursor_energy.fetchall() - if rows_energy_categories is not None or len(rows_energy_categories) > 0: - for row_energy_category in rows_energy_categories: - energy_category_set_output.add(row_energy_category[0]) - - # query properties of all energy categories above - cursor_system.execute(" SELECT id, name, unit_of_measure, kgce, kgco2e " - " FROM tbl_energy_categories " - " ORDER BY id ", ) - rows_energy_categories = cursor_system.fetchall() - if rows_energy_categories is None or len(rows_energy_categories) == 0: - if cursor_system: - cursor_system.close() - if cnx_system: - cnx_system.disconnect() - - if cursor_energy: - cursor_energy.close() - if cnx_energy: - cnx_energy.disconnect() - - if cnx_historical: - cnx_historical.close() - if cursor_historical: - cursor_historical.disconnect() - raise falcon.HTTPError(falcon.HTTP_404, - title='API.NOT_FOUND', - description='API.ENERGY_CATEGORY_NOT_FOUND') - energy_category_dict = dict() - for row_energy_category in rows_energy_categories: - if row_energy_category[0] in energy_category_set_input or \ - row_energy_category[0] in energy_category_set_output: - energy_category_dict[row_energy_category[0]] = {"name": row_energy_category[1], - "unit_of_measure": row_energy_category[2], - "kgce": row_energy_category[3], - "kgco2e": row_energy_category[4]} - - ################################################################################################################ - # Step 4: query associated points + # Step 3: query associated points ################################################################################################################ point_list = list() cursor_system.execute(" SELECT p.id, p.name, p.units, p.object_type " @@ -257,36 +169,181 @@ class Reporting: for row in rows_points: point_list.append({"id": row[0], "name": row[1], "units": row[2], "object_type": row[3]}) + print(point_list) ################################################################################################################ - # Step 5: query base period energy input + # Step 4: query associated fractions ################################################################################################################ - base_input = dict() - if energy_category_set_input is not None and len(energy_category_set_input) > 0: - for energy_category_id in energy_category_set_input: - base_input[energy_category_id] = dict() - base_input[energy_category_id]['timestamps'] = list() - base_input[energy_category_id]['values'] = list() - base_input[energy_category_id]['subtotal'] = Decimal(0.0) + fraction_list = list() + cursor_system.execute(" SELECT id, name, numerator_meter_uuid, denominator_meter_uuid " + " FROM tbl_equipments_parameters " + " WHERE equipment_id = %s AND parameter_type = 'fraction' ", + (equipment['id'],)) + rows_fractions = cursor_system.fetchall() + if rows_fractions is not None and len(rows_fractions) > 0: + for row in rows_fractions: + fraction_list.append({"id": row[0], + "name": row[1], + "numerator_meter_uuid": row[2], + "denominator_meter_uuid": row[3], + }) - cursor_energy.execute(" SELECT start_datetime_utc, actual_value " - " FROM tbl_equipment_input_category_hourly " - " WHERE equipment_id = %s " - " AND energy_category_id = %s " - " AND start_datetime_utc >= %s " - " AND start_datetime_utc < %s " - " ORDER BY start_datetime_utc ", - (equipment['id'], - energy_category_id, - base_start_datetime_utc, - base_end_datetime_utc)) - rows_equipment_hourly = cursor_energy.fetchall() + print(fraction_list) - rows_equipment_periodically = utilities.aggregate_hourly_data_by_period(rows_equipment_hourly, - base_start_datetime_utc, - base_end_datetime_utc, - period_type) - for row_equipment_periodically in rows_equipment_periodically: - current_datetime_local = row_equipment_periodically[0].replace(tzinfo=timezone.utc) + \ + ################################################################################################################ + # Step 5: query fractions' numerator and denominator + ################################################################################################################ + # get all meters + meter_dict = dict() + query = (" SELECT m.id, m.uuid, ec.unit_of_measure " + " FROM tbl_meters m, tbl_energy_categories ec " + " WHERE m.energy_category_id = ec.id ") + cursor_system.execute(query) + rows_meters = cursor_system.fetchall() + + if rows_meters is not None and len(rows_meters) > 0: + for row in rows_meters: + meter_dict[row[1]] = {'id': row[0], 'unit': row[2]} + # get all offline meters + offline_meter_dict = dict() + query = (" SELECT m.id, m.uuid, ec.unit_of_measure " + " FROM tbl_offline_meters m, tbl_energy_categories ec " + " WHERE m.energy_category_id = ec.id ") + cursor_system.execute(query) + rows_offline_meters = cursor_system.fetchall() + + if rows_offline_meters is not None and len(rows_offline_meters) > 0: + for row in rows_offline_meters: + offline_meter_dict[row[1]] = {'id': row[0], 'unit': row[2]} + # get all virtual meters + virtual_meter_dict = dict() + query = (" SELECT m.id, m.uuid, ec.unit_of_measure " + " FROM tbl_virtual_meters m, tbl_energy_categories ec " + " WHERE m.energy_category_id = ec.id ") + cursor_system.execute(query) + rows_virtual_meters = cursor_system.fetchall() + + if rows_virtual_meters is not None and len(rows_virtual_meters) > 0: + for row in rows_virtual_meters: + virtual_meter_dict[row[1]] = {'id': row[0], 'unit': row[2]} + + if fraction_list is not None and len(fraction_list) > 0: + for fraction in fraction_list: + if fraction['numerator_meter_uuid'] in offline_meter_dict: + fraction['numerator_meter_id'] = offline_meter_dict[fraction['numerator_meter_uuid']]['id'] + fraction['numerator_meter_unit'] = offline_meter_dict[fraction['numerator_meter_uuid']]['unit'] + fraction['numerator_meter_type'] = 'offline_meter' + elif fraction['numerator_meter_uuid'] in virtual_meter_dict: + fraction['numerator_meter_id'] = virtual_meter_dict[fraction['numerator_meter_uuid']]['id'] + fraction['numerator_meter_unit'] = virtual_meter_dict[fraction['numerator_meter_uuid']]['unit'] + fraction['numerator_meter_type'] = 'virtual_meter' + elif fraction['numerator_meter_uuid'] in meter_dict: + fraction['numerator_meter_id'] = meter_dict[fraction['numerator_meter_uuid']]['id'] + fraction['numerator_meter_unit'] = meter_dict[fraction['numerator_meter_uuid']]['unit'] + fraction['numerator_meter_type'] = 'meter' + + if fraction['denominator_meter_uuid'] in offline_meter_dict: + fraction['denominator_meter_id'] = offline_meter_dict[fraction['denominator_meter_uuid']]['id'] + fraction['denominator_meter_unit'] = offline_meter_dict[fraction['denominator_meter_uuid']]['unit'] + fraction['denominator_meter_type'] = 'offline_meter' + elif fraction['denominator_meter_uuid'] in virtual_meter_dict: + fraction['denominator_meter_id'] = virtual_meter_dict[fraction['denominator_meter_uuid']]['id'] + fraction['denominator_meter_unit'] = virtual_meter_dict[fraction['denominator_meter_uuid']]['unit'] + fraction['denominator_meter_type'] = 'virtual_meter' + elif fraction['denominator_meter_uuid'] in meter_dict: + fraction['denominator_meter_id'] = meter_dict[fraction['denominator_meter_uuid']]['id'] + fraction['denominator_meter_unit'] = meter_dict[fraction['denominator_meter_uuid']]['unit'] + fraction['denominator_meter_type'] = 'meter' + + print(fraction_list) + + ################################################################################################################ + # Step 5: calculate base period fractions + ################################################################################################################ + base = dict() + if fraction_list is not None and len(fraction_list) > 0: + for fraction in fraction_list: + base[fraction['id']] = dict() + base[fraction['id']]['name'] = fraction['name'] + base[fraction['id']]['unit'] = fraction['numerator_meter_unit'] + '/' + \ + fraction['denominator_meter_unit'] + base[fraction['id']]['numerator_timestamps'] = list() + base[fraction['id']]['numerator_values'] = list() + base[fraction['id']]['numerator_cumulation'] = Decimal(0.0) + base[fraction['id']]['denominator_timestamps'] = list() + base[fraction['id']]['denominator_values'] = list() + base[fraction['id']]['denominator_cumulation'] = Decimal(0.0) + base[fraction['id']]['timestamps'] = list() + base[fraction['id']]['values'] = list() + base[fraction['id']]['cumulation'] = Decimal(0.0) + # query numerator meter output + if fraction['numerator_meter_type'] == 'meter': + query = (" SELECT start_datetime_utc, actual_value " + " FROM tbl_meter_hourly " + " WHERE meter_id = %s " + " AND start_datetime_utc >= %s " + " AND start_datetime_utc < %s " + " ORDER BY start_datetime_utc ") + elif fraction['numerator_meter_type'] == 'offline_meter': + query = (" SELECT start_datetime_utc, actual_value " + " FROM tbl_offline_meter_hourly " + " WHERE offline_meter_id = %s " + " AND start_datetime_utc >= %s " + " AND start_datetime_utc < %s " + " ORDER BY start_datetime_utc ") + elif fraction['numerator_meter_type'] == 'virtual_meter': + query = (" SELECT start_datetime_utc, actual_value " + " FROM tbl_virtual_meter_hourly " + " WHERE virtual_meter_id = %s " + " AND start_datetime_utc >= %s " + " AND start_datetime_utc < %s " + " ORDER BY start_datetime_utc ") + + cursor_energy.execute(query, (fraction['numerator_meter_id'], + base_start_datetime_utc, + base_end_datetime_utc)) + rows_numerator_meter_hourly = cursor_energy.fetchall() + + rows_numerator_meter_periodically = \ + utilities.aggregate_hourly_data_by_period(rows_numerator_meter_hourly, + base_start_datetime_utc, + base_end_datetime_utc, + period_type) + # query denominator meter input + if fraction['denominator_meter_type'] == 'meter': + query = (" SELECT start_datetime_utc, actual_value " + " FROM tbl_meter_hourly " + " WHERE meter_id = %s " + " AND start_datetime_utc >= %s " + " AND start_datetime_utc < %s " + " ORDER BY start_datetime_utc ") + elif fraction['denominator_meter_type'] == 'offline_meter': + query = (" SELECT start_datetime_utc, actual_value " + " FROM tbl_offline_meter_hourly " + " WHERE offline_meter_id = %s " + " AND start_datetime_utc >= %s " + " AND start_datetime_utc < %s " + " ORDER BY start_datetime_utc ") + elif fraction['denominator_meter_type'] == 'virtual_meter': + query = (" SELECT start_datetime_utc, actual_value " + " FROM tbl_virtual_meter_hourly " + " WHERE virtual_meter_id = %s " + " AND start_datetime_utc >= %s " + " AND start_datetime_utc < %s " + " ORDER BY start_datetime_utc ") + + cursor_energy.execute(query, (fraction['denominator_meter_id'], + base_start_datetime_utc, + base_end_datetime_utc)) + rows_denominator_meter_hourly = cursor_energy.fetchall() + + rows_denominator_meter_periodically = \ + utilities.aggregate_hourly_data_by_period(rows_denominator_meter_hourly, + base_start_datetime_utc, + base_end_datetime_utc, + period_type) + + for row_numerator_meter_periodically in rows_numerator_meter_periodically: + current_datetime_local = row_numerator_meter_periodically[0].replace(tzinfo=timezone.utc) + \ timedelta(minutes=timezone_offset) if period_type == 'hourly': current_datetime = current_datetime_local.strftime('%Y-%m-%dT%H:%M:%S') @@ -297,42 +354,15 @@ class Reporting: elif period_type == 'yearly': current_datetime = current_datetime_local.strftime('%Y') - actual_value = Decimal(0.0) if row_equipment_periodically[1] is None \ - else row_equipment_periodically[1] - base_input[energy_category_id]['timestamps'].append(current_datetime) - base_input[energy_category_id]['values'].append(actual_value) - base_input[energy_category_id]['subtotal'] += actual_value + actual_value = Decimal(0.0) if row_numerator_meter_periodically[1] is None \ + else row_numerator_meter_periodically[1] - ################################################################################################################ - # Step 6: query base period energy output - ################################################################################################################ - base_output = dict() - if energy_category_set_output is not None and len(energy_category_set_output) > 0: - for energy_category_id in energy_category_set_output: - base_output[energy_category_id] = dict() - base_output[energy_category_id]['timestamps'] = list() - base_output[energy_category_id]['values'] = list() - base_output[energy_category_id]['subtotal'] = Decimal(0.0) + base[fraction['id']]['numerator_timestamps'].append(current_datetime) + base[fraction['id']]['numerator_values'].append(actual_value) + base[fraction['id']]['numerator_cumulation'] += actual_value - cursor_energy.execute(" SELECT start_datetime_utc, actual_value " - " FROM tbl_equipment_output_category_hourly " - " WHERE equipment_id = %s " - " AND energy_category_id = %s " - " AND start_datetime_utc >= %s " - " AND start_datetime_utc < %s " - " ORDER BY start_datetime_utc ", - (equipment['id'], - energy_category_id, - base_start_datetime_utc, - base_end_datetime_utc)) - rows_equipment_hourly = cursor_energy.fetchall() - - rows_equipment_periodically = utilities.aggregate_hourly_data_by_period(rows_equipment_hourly, - base_start_datetime_utc, - base_end_datetime_utc, - period_type) - for row_equipment_periodically in rows_equipment_periodically: - current_datetime_local = row_equipment_periodically[0].replace(tzinfo=timezone.utc) + \ + for row_denominator_meter_periodically in rows_denominator_meter_periodically: + current_datetime_local = row_denominator_meter_periodically[0].replace(tzinfo=timezone.utc) + \ timedelta(minutes=timezone_offset) if period_type == 'hourly': current_datetime = current_datetime_local.strftime('%Y-%m-%dT%H:%M:%S') @@ -343,42 +373,114 @@ class Reporting: elif period_type == 'yearly': current_datetime = current_datetime_local.strftime('%Y') - actual_value = Decimal(0.0) if row_equipment_periodically[1] is None \ - else row_equipment_periodically[1] - base_output[energy_category_id]['timestamps'].append(current_datetime) - base_output[energy_category_id]['values'].append(actual_value) - base_output[energy_category_id]['subtotal'] += actual_value + actual_value = Decimal(0.0) if row_denominator_meter_periodically[1] is None \ + else row_denominator_meter_periodically[1] + + base[fraction['id']]['denominator_timestamps'].append(current_datetime) + base[fraction['id']]['denominator_values'].append(actual_value) + base[fraction['id']]['denominator_cumulation'] += actual_value + + for i in range(len(base[fraction['id']]['denominator_timestamps'])): + timestamp = base[fraction['id']]['denominator_timestamps'][i] + base[fraction['id']]['timestamps'].append(timestamp) + value = (base[fraction['id']]['numerator_values'][i] / + base[fraction['id']]['denominator_values'][i]) \ + if base[fraction['id']]['denominator_values'][i] > Decimal(0.0) else Decimal(0.0) + base[fraction['id']]['values'].append(value) + + cumulation = (base[fraction['id']]['numerator_cumulation'] / + base[fraction['id']]['denominator_cumulation']) \ + if base[fraction['id']]['denominator_cumulation'] > Decimal(0.0) else Decimal(0.0) + base[fraction['id']]['cumulation'] = cumulation + ################################################################################################################ - # Step 7: query reporting period energy input + # Step 6: calculate reporting period fractions ################################################################################################################ - reporting_input = dict() - if energy_category_set_input is not None and len(energy_category_set_input) > 0: - for energy_category_id in energy_category_set_input: + reporting = dict() + if fraction_list is not None and len(fraction_list) > 0: + for fraction in fraction_list: + reporting[fraction['id']] = dict() + reporting[fraction['id']]['name'] = fraction['name'] + reporting[fraction['id']]['unit'] = fraction['numerator_meter_unit'] + '/' + \ + fraction['denominator_meter_unit'] + reporting[fraction['id']]['numerator_timestamps'] = list() + reporting[fraction['id']]['numerator_values'] = list() + reporting[fraction['id']]['numerator_cumulation'] = Decimal(0.0) + reporting[fraction['id']]['denominator_timestamps'] = list() + reporting[fraction['id']]['denominator_values'] = list() + reporting[fraction['id']]['denominator_cumulation'] = Decimal(0.0) + reporting[fraction['id']]['timestamps'] = list() + reporting[fraction['id']]['values'] = list() + reporting[fraction['id']]['cumulation'] = Decimal(0.0) + # query numerator meter output + if fraction['numerator_meter_type'] == 'meter': + query = (" SELECT start_datetime_utc, actual_value " + " FROM tbl_meter_hourly " + " WHERE meter_id = %s " + " AND start_datetime_utc >= %s " + " AND start_datetime_utc < %s " + " ORDER BY start_datetime_utc ") + elif fraction['numerator_meter_type'] == 'offline_meter': + query = (" SELECT start_datetime_utc, actual_value " + " FROM tbl_offline_meter_hourly " + " WHERE offline_meter_id = %s " + " AND start_datetime_utc >= %s " + " AND start_datetime_utc < %s " + " ORDER BY start_datetime_utc ") + elif fraction['numerator_meter_type'] == 'virtual_meter': + query = (" SELECT start_datetime_utc, actual_value " + " FROM tbl_virtual_meter_hourly " + " WHERE virtual_meter_id = %s " + " AND start_datetime_utc >= %s " + " AND start_datetime_utc < %s " + " ORDER BY start_datetime_utc ") - reporting_input[energy_category_id] = dict() - reporting_input[energy_category_id]['timestamps'] = list() - reporting_input[energy_category_id]['values'] = list() - reporting_input[energy_category_id]['subtotal'] = Decimal(0.0) + cursor_energy.execute(query, (fraction['numerator_meter_id'], + reporting_start_datetime_utc, + reporting_end_datetime_utc)) + rows_numerator_meter_hourly = cursor_energy.fetchall() - cursor_energy.execute(" SELECT start_datetime_utc, actual_value " - " FROM tbl_equipment_input_category_hourly " - " WHERE equipment_id = %s " - " AND energy_category_id = %s " - " AND start_datetime_utc >= %s " - " AND start_datetime_utc < %s " - " ORDER BY start_datetime_utc ", - (equipment['id'], - energy_category_id, - reporting_start_datetime_utc, - reporting_end_datetime_utc)) - rows_equipment_hourly = cursor_energy.fetchall() + rows_numerator_meter_periodically = \ + utilities.aggregate_hourly_data_by_period(rows_numerator_meter_hourly, + reporting_start_datetime_utc, + reporting_end_datetime_utc, + period_type) + # query denominator meter input + if fraction['denominator_meter_type'] == 'meter': + query = (" SELECT start_datetime_utc, actual_value " + " FROM tbl_meter_hourly " + " WHERE meter_id = %s " + " AND start_datetime_utc >= %s " + " AND start_datetime_utc < %s " + " ORDER BY start_datetime_utc ") + elif fraction['denominator_meter_type'] == 'offline_meter': + query = (" SELECT start_datetime_utc, actual_value " + " FROM tbl_offline_meter_hourly " + " WHERE offline_meter_id = %s " + " AND start_datetime_utc >= %s " + " AND start_datetime_utc < %s " + " ORDER BY start_datetime_utc ") + elif fraction['denominator_meter_type'] == 'virtual_meter': + query = (" SELECT start_datetime_utc, actual_value " + " FROM tbl_virtual_meter_hourly " + " WHERE virtual_meter_id = %s " + " AND start_datetime_utc >= %s " + " AND start_datetime_utc < %s " + " ORDER BY start_datetime_utc ") - rows_equipment_periodically = utilities.aggregate_hourly_data_by_period(rows_equipment_hourly, - reporting_start_datetime_utc, - reporting_end_datetime_utc, - period_type) - for row_equipment_periodically in rows_equipment_periodically: - current_datetime_local = row_equipment_periodically[0].replace(tzinfo=timezone.utc) + \ + cursor_energy.execute(query, (fraction['denominator_meter_id'], + reporting_start_datetime_utc, + reporting_end_datetime_utc)) + rows_denominator_meter_hourly = cursor_energy.fetchall() + + rows_denominator_meter_periodically = \ + utilities.aggregate_hourly_data_by_period(rows_denominator_meter_hourly, + reporting_start_datetime_utc, + reporting_end_datetime_utc, + period_type) + + for row_numerator_meter_periodically in rows_numerator_meter_periodically: + current_datetime_local = row_numerator_meter_periodically[0].replace(tzinfo=timezone.utc) + \ timedelta(minutes=timezone_offset) if period_type == 'hourly': current_datetime = current_datetime_local.strftime('%Y-%m-%dT%H:%M:%S') @@ -389,43 +491,15 @@ class Reporting: elif period_type == 'yearly': current_datetime = current_datetime_local.strftime('%Y') - actual_value = Decimal(0.0) if row_equipment_periodically[1] is None \ - else row_equipment_periodically[1] - reporting_input[energy_category_id]['timestamps'].append(current_datetime) - reporting_input[energy_category_id]['values'].append(actual_value) - reporting_input[energy_category_id]['subtotal'] += actual_value + actual_value = Decimal(0.0) if row_numerator_meter_periodically[1] is None \ + else row_numerator_meter_periodically[1] - ################################################################################################################ - # Step 8: query reporting period energy output - ################################################################################################################ - reporting_output = dict() - if energy_category_set_output is not None and len(energy_category_set_output) > 0: - for energy_category_id in energy_category_set_output: + reporting[fraction['id']]['numerator_timestamps'].append(current_datetime) + reporting[fraction['id']]['numerator_values'].append(actual_value) + reporting[fraction['id']]['numerator_cumulation'] += actual_value - reporting_output[energy_category_id] = dict() - reporting_output[energy_category_id]['timestamps'] = list() - reporting_output[energy_category_id]['values'] = list() - reporting_output[energy_category_id]['subtotal'] = Decimal(0.0) - - cursor_energy.execute(" SELECT start_datetime_utc, actual_value " - " FROM tbl_equipment_output_category_hourly " - " WHERE equipment_id = %s " - " AND energy_category_id = %s " - " AND start_datetime_utc >= %s " - " AND start_datetime_utc < %s " - " ORDER BY start_datetime_utc ", - (equipment['id'], - energy_category_id, - reporting_start_datetime_utc, - reporting_end_datetime_utc)) - rows_equipment_hourly = cursor_energy.fetchall() - - rows_equipment_periodically = utilities.aggregate_hourly_data_by_period(rows_equipment_hourly, - reporting_start_datetime_utc, - reporting_end_datetime_utc, - period_type) - for row_equipment_periodically in rows_equipment_periodically: - current_datetime_local = row_equipment_periodically[0].replace(tzinfo=timezone.utc) + \ + for row_denominator_meter_periodically in rows_denominator_meter_periodically: + current_datetime_local = row_denominator_meter_periodically[0].replace(tzinfo=timezone.utc) + \ timedelta(minutes=timezone_offset) if period_type == 'hourly': current_datetime = current_datetime_local.strftime('%Y-%m-%dT%H:%M:%S') @@ -436,40 +510,34 @@ class Reporting: elif period_type == 'yearly': current_datetime = current_datetime_local.strftime('%Y') - actual_value = Decimal(0.0) if row_equipment_periodically[1] is None \ - else row_equipment_periodically[1] - reporting_output[energy_category_id]['timestamps'].append(current_datetime) - reporting_output[energy_category_id]['values'].append(actual_value) - reporting_output[energy_category_id]['subtotal'] += actual_value + actual_value = Decimal(0.0) if row_denominator_meter_periodically[1] is None \ + else row_denominator_meter_periodically[1] + + reporting[fraction['id']]['denominator_timestamps'].append(current_datetime) + reporting[fraction['id']]['denominator_values'].append(actual_value) + reporting[fraction['id']]['denominator_cumulation'] += actual_value + + for i in range(len(reporting[fraction['id']]['denominator_timestamps'])): + timestamp = reporting[fraction['id']]['denominator_timestamps'][i] + reporting[fraction['id']]['timestamps'].append(timestamp) + value = reporting[fraction['id']]['numerator_values'][i] / \ + reporting[fraction['id']]['denominator_values'][i] \ + if reporting[fraction['id']]['denominator_values'][i] > Decimal(0.0) else Decimal(0.0) + reporting[fraction['id']]['values'].append(value) + + cumulation = (reporting[fraction['id']]['numerator_cumulation'] / + reporting[fraction['id']]['denominator_cumulation']) \ + if reporting[fraction['id']]['denominator_cumulation'] > Decimal(0.0) else Decimal(0.0) + reporting[fraction['id']]['cumulation'] = cumulation ################################################################################################################ - # Step 9: query tariff data + # Step 7: query associated points data ################################################################################################################ parameters_data = dict() parameters_data['names'] = list() parameters_data['timestamps'] = list() parameters_data['values'] = list() - if energy_category_set_input is not None and len(energy_category_set_input) > 0: - for energy_category_id in energy_category_set_input: - energy_category_tariff_dict = utilities.get_energy_category_tariffs(equipment['cost_center_id'], - energy_category_id, - reporting_start_datetime_utc, - reporting_end_datetime_utc) - tariff_timestamp_list = list() - tariff_value_list = list() - for k, v in energy_category_tariff_dict.items(): - # convert k from utc to local - k = k + timedelta(minutes=timezone_offset) - tariff_timestamp_list.append(k.isoformat()[0:19][0:19]) - tariff_value_list.append(v) - parameters_data['names'].append('TARIFF-' + energy_category_dict[energy_category_id]['name']) - parameters_data['timestamps'].append(tariff_timestamp_list) - parameters_data['values'].append(tariff_value_list) - - ################################################################################################################ - # Step 10: query associated sensors and points data - ################################################################################################################ for point in point_list: point_values = [] point_timestamps = [] @@ -533,7 +601,7 @@ class Reporting: parameters_data['values'].append(point_values) ################################################################################################################ - # Step 11: construct the report + # Step 8: construct the report ################################################################################################################ if cursor_system: cursor_system.close() @@ -550,119 +618,11 @@ class Reporting: result['equipment'] = dict() result['equipment']['name'] = equipment['name'] - result['base_period_input'] = dict() - result['base_period_input']['names'] = list() - result['base_period_input']['units'] = list() - result['base_period_input']['timestamps'] = list() - result['base_period_input']['values'] = list() - result['base_period_input']['subtotals'] = list() - if energy_category_set_input is not None and len(energy_category_set_input) > 0: - for energy_category_id in energy_category_set_input: - result['base_period_input']['names'].append(energy_category_dict[energy_category_id]['name']) - result['base_period_input']['units'].append(energy_category_dict[energy_category_id]['unit_of_measure']) - result['base_period_input']['timestamps'].append(base_input[energy_category_id]['timestamps']) - result['base_period_input']['values'].append(base_input[energy_category_id]['values']) - result['base_period_input']['subtotals'].append(base_input[energy_category_id]['subtotal']) - - result['base_period_output'] = dict() - result['base_period_output']['names'] = list() - result['base_period_output']['units'] = list() - result['base_period_output']['timestamps'] = list() - result['base_period_output']['values'] = list() - result['base_period_output']['subtotals'] = list() - - if energy_category_set_output is not None and len(energy_category_set_output) > 0: - for energy_category_id in energy_category_set_output: - result['base_period_output']['names'].append(energy_category_dict[energy_category_id]['name']) - result['base_period_output']['units'].append( - energy_category_dict[energy_category_id]['unit_of_measure']) - result['base_period_output']['timestamps'].append(base_output[energy_category_id]['timestamps']) - result['base_period_output']['values'].append(base_output[energy_category_id]['values']) - result['base_period_output']['subtotals'].append(base_output[energy_category_id]['subtotal']) - result['base_period_efficiency'] = dict() - result['base_period_efficiency']['names'] = list() - result['base_period_efficiency']['units'] = list() result['base_period_efficiency']['timestamps'] = list() result['base_period_efficiency']['values'] = list() result['base_period_efficiency']['cumulations'] = list() - if energy_category_set_output is not None and len(energy_category_set_output) > 0: - for energy_category_id_output in energy_category_set_output: - for energy_category_id_input in energy_category_set_input: - result['base_period_efficiency']['names'].append( - energy_category_dict[energy_category_id_output]['name'] + '/' + - energy_category_dict[energy_category_id_input]['name']) - result['base_period_efficiency']['units'].append( - energy_category_dict[energy_category_id_output]['unit_of_measure'] + '/' + - energy_category_dict[energy_category_id_input]['unit_of_measure']) - result['base_period_efficiency']['timestamps'].append( - base_output[energy_category_id_output]['timestamps']) - efficiency_values = list() - for i in range(len(base_output[energy_category_id_output]['timestamps'])): - efficiency_values.append((base_output[energy_category_id_output]['values'][i] / - base_input[energy_category_id_input]['values'][i]) - if base_input[energy_category_id_input]['values'][i] > Decimal(0.0) - else None) - result['base_period_efficiency']['values'].append(efficiency_values) - - base_cumulation = (base_output[energy_category_id_output]['subtotal'] / - base_input[energy_category_id_input]['subtotal']) if \ - base_input[energy_category_id_input]['subtotal'] > Decimal(0.0) else None - result['base_period_efficiency']['cumulations'].append(base_cumulation) - - result['reporting_period_input'] = dict() - result['reporting_period_input']['names'] = list() - result['reporting_period_input']['energy_category_ids'] = list() - result['reporting_period_input']['units'] = list() - result['reporting_period_input']['timestamps'] = list() - result['reporting_period_input']['values'] = list() - result['reporting_period_input']['subtotals'] = list() - result['reporting_period_input']['increment_rates'] = list() - - if energy_category_set_input is not None and len(energy_category_set_input) > 0: - for energy_category_id in energy_category_set_input: - result['reporting_period_input']['names'].append(energy_category_dict[energy_category_id]['name']) - result['reporting_period_input']['energy_category_ids'].append(energy_category_id) - result['reporting_period_input']['units'].append( - energy_category_dict[energy_category_id]['unit_of_measure']) - result['reporting_period_input']['timestamps'].append( - reporting_input[energy_category_id]['timestamps']) - result['reporting_period_input']['values'].append( - reporting_input[energy_category_id]['values']) - result['reporting_period_input']['subtotals'].append( - reporting_input[energy_category_id]['subtotal']) - result['reporting_period_input']['increment_rates'].append( - (reporting_input[energy_category_id]['subtotal'] - - base_input[energy_category_id]['subtotal']) / - base_input[energy_category_id]['subtotal'] - if base_input[energy_category_id]['subtotal'] > 0.0 else None) - - result['reporting_period_output'] = dict() - result['reporting_period_output']['names'] = list() - result['reporting_period_output']['energy_category_ids'] = list() - result['reporting_period_output']['units'] = list() - result['reporting_period_output']['timestamps'] = list() - result['reporting_period_output']['values'] = list() - result['reporting_period_output']['subtotals'] = list() - result['reporting_period_output']['increment_rates'] = list() - - if energy_category_set_output is not None and len(energy_category_set_output) > 0: - for energy_category_id in energy_category_set_output: - result['reporting_period_output']['names'].append(energy_category_dict[energy_category_id]['name']) - result['reporting_period_output']['energy_category_ids'].append(energy_category_id) - result['reporting_period_output']['units'].append( - energy_category_dict[energy_category_id]['unit_of_measure']) - result['reporting_period_output']['timestamps'].append( - reporting_output[energy_category_id]['timestamps']) - result['reporting_period_output']['values'].append(reporting_output[energy_category_id]['values']) - result['reporting_period_output']['subtotals'].append(reporting_output[energy_category_id]['subtotal']) - result['reporting_period_output']['increment_rates'].append( - (reporting_output[energy_category_id]['subtotal'] - - base_output[energy_category_id]['subtotal']) / - base_output[energy_category_id]['subtotal'] - if base_output[energy_category_id]['subtotal'] > 0.0 else None) - result['reporting_period_efficiency'] = dict() result['reporting_period_efficiency']['names'] = list() result['reporting_period_efficiency']['units'] = list() @@ -670,40 +630,19 @@ class Reporting: result['reporting_period_efficiency']['values'] = list() result['reporting_period_efficiency']['cumulations'] = list() result['reporting_period_efficiency']['increment_rates'] = list() - - if energy_category_set_output is not None and len(energy_category_set_output) > 0: - for energy_category_id_output in energy_category_set_output: - for energy_category_id_input in energy_category_set_input: - result['reporting_period_efficiency']['names'].append( - energy_category_dict[energy_category_id_output]['name'] + '/' + - energy_category_dict[energy_category_id_input]['name']) - result['reporting_period_efficiency']['units'].append( - energy_category_dict[energy_category_id_output]['unit_of_measure'] + '/' + - energy_category_dict[energy_category_id_input]['unit_of_measure']) - result['reporting_period_efficiency']['timestamps'].append( - reporting_output[energy_category_id_output]['timestamps']) - efficiency_values = list() - for i in range(len(reporting_output[energy_category_id_output]['timestamps'])): - efficiency_values.append((reporting_output[energy_category_id_output]['values'][i] / - reporting_input[energy_category_id_input]['values'][i]) - if reporting_input[energy_category_id_input]['values'][i] > - Decimal(0.0) else None) - result['reporting_period_efficiency']['values'].append(efficiency_values) - - base_cumulation = (base_output[energy_category_id_output]['subtotal'] / - base_input[energy_category_id_input]['subtotal']) if \ - base_input[energy_category_id_input]['subtotal'] > Decimal(0.0) else None - - reporting_cumulation = (reporting_output[energy_category_id_output]['subtotal'] / - reporting_input[energy_category_id_input]['subtotal']) if \ - reporting_input[energy_category_id_input]['subtotal'] > Decimal(0.0) else None - - result['reporting_period_efficiency']['cumulations'].append(reporting_cumulation) - result['reporting_period_efficiency']['increment_rates'].append( - ((reporting_cumulation - base_cumulation) / base_cumulation if (base_cumulation is not None and - base_cumulation > Decimal(0.0)) - else None) - ) + if fraction_list is not None and len(fraction_list) > 0: + for fraction in fraction_list: + result['base_period_efficiency']['timestamps'].append(base[fraction['id']]['timestamps']) + result['base_period_efficiency']['values'].append(base[fraction['id']]['values']) + result['base_period_efficiency']['cumulations'].append(base[fraction['id']]['cumulation']) + result['reporting_period_efficiency']['names'].append(reporting[fraction['id']]['name']) + result['reporting_period_efficiency']['units'].append(reporting[fraction['id']]['unit']) + result['reporting_period_efficiency']['timestamps'].append(reporting[fraction['id']]['timestamps']) + result['reporting_period_efficiency']['values'].append(reporting[fraction['id']]['values']) + result['reporting_period_efficiency']['cumulations'].append(reporting[fraction['id']]['cumulation']) + result['reporting_period_efficiency']['increment_rates'].append( + (reporting[fraction['id']]['cumulation'] - base[fraction['id']]['cumulation']) / + base[fraction['id']]['cumulation'] if base[fraction['id']]['cumulation'] > Decimal(0.0) else None) result['parameters'] = { "names": parameters_data['names'], @@ -711,4 +650,11 @@ class Reporting: "values": parameters_data['values'] } + # export result to Excel file and then encode the file to base64 string + result['excel_bytes_base64'] = excelexporters.equipmentefficiency.export(result, + equipment['name'], + reporting_start_datetime_local, + reporting_end_datetime_local, + period_type) + resp.body = json.dumps(result) diff --git a/myems-api/reports/equipmentenergycategory.py b/myems-api/reports/equipmentenergycategory.py index a955b7b7..fd490d3b 100644 --- a/myems-api/reports/equipmentenergycategory.py +++ b/myems-api/reports/equipmentenergycategory.py @@ -144,10 +144,10 @@ class Reporting: if cnx_energy: cnx_energy.disconnect() - if cnx_historical: - cnx_historical.close() if cursor_historical: - cursor_historical.disconnect() + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.EQUIPMENT_NOT_FOUND') equipment = dict() @@ -199,10 +199,10 @@ class Reporting: if cnx_energy: cnx_energy.disconnect() - if cnx_historical: - cnx_historical.close() if cursor_historical: - cursor_historical.disconnect() + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.ENERGY_CATEGORY_NOT_FOUND') @@ -456,6 +456,11 @@ class Reporting: if cnx_energy: cnx_energy.disconnect() + if cursor_historical: + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() + result = dict() result['equipment'] = dict() diff --git a/myems-api/reports/equipmentenergyitem.py b/myems-api/reports/equipmentenergyitem.py index 3f642350..20fb744c 100644 --- a/myems-api/reports/equipmentenergyitem.py +++ b/myems-api/reports/equipmentenergyitem.py @@ -144,10 +144,10 @@ class Reporting: if cnx_energy: cnx_energy.disconnect() - if cnx_historical: - cnx_historical.close() if cursor_historical: - cursor_historical.disconnect() + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.EQUIPMENT_NOT_FOUND') equipment = dict() @@ -201,10 +201,10 @@ class Reporting: if cnx_energy: cnx_energy.disconnect() - if cnx_historical: - cnx_historical.close() if cursor_historical: - cursor_historical.disconnect() + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.ENERGY_ITEM_NOT_FOUND') @@ -448,6 +448,11 @@ class Reporting: if cnx_energy: cnx_energy.disconnect() + if cursor_historical: + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() + result = dict() result['equipment'] = dict() diff --git a/myems-api/reports/equipmentincome.py b/myems-api/reports/equipmentincome.py index 220e7cb5..55ae0fff 100644 --- a/myems-api/reports/equipmentincome.py +++ b/myems-api/reports/equipmentincome.py @@ -144,10 +144,10 @@ class Reporting: if cnx_billing: cnx_billing.disconnect() - if cnx_historical: - cnx_historical.close() if cursor_historical: - cursor_historical.disconnect() + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.EQUIPMENT_NOT_FOUND') equipment = dict() @@ -199,10 +199,10 @@ class Reporting: if cnx_billing: cnx_billing.disconnect() - if cnx_historical: - cnx_historical.close() if cursor_historical: - cursor_historical.disconnect() + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.ENERGY_CATEGORY_NOT_FOUND') @@ -423,6 +423,11 @@ class Reporting: if cnx_billing: cnx_billing.disconnect() + if cursor_historical: + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() + result = dict() result['equipment'] = dict() diff --git a/myems-api/reports/equipmentload.py b/myems-api/reports/equipmentload.py index 2c61cf54..71091a23 100644 --- a/myems-api/reports/equipmentload.py +++ b/myems-api/reports/equipmentload.py @@ -144,10 +144,10 @@ class Reporting: if cnx_energy: cnx_energy.disconnect() - if cnx_historical: - cnx_historical.close() if cursor_historical: - cursor_historical.disconnect() + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.EQUIPMENT_NOT_FOUND') equipment = dict() @@ -199,10 +199,10 @@ class Reporting: if cnx_energy: cnx_energy.disconnect() - if cnx_historical: - cnx_historical.close() if cursor_historical: - cursor_historical.disconnect() + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.ENERGY_CATEGORY_NOT_FOUND') @@ -445,6 +445,11 @@ class Reporting: if cnx_energy: cnx_energy.disconnect() + if cursor_historical: + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() + result = dict() result['equipment'] = dict() diff --git a/myems-api/reports/equipmentoutput.py b/myems-api/reports/equipmentoutput.py index 15e2f3bf..92680c82 100644 --- a/myems-api/reports/equipmentoutput.py +++ b/myems-api/reports/equipmentoutput.py @@ -144,10 +144,10 @@ class Reporting: if cnx_energy: cnx_energy.disconnect() - if cnx_historical: - cnx_historical.close() if cursor_historical: - cursor_historical.disconnect() + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.EQUIPMENT_NOT_FOUND') equipment = dict() @@ -199,10 +199,10 @@ class Reporting: if cnx_energy: cnx_energy.disconnect() - if cnx_historical: - cnx_historical.close() if cursor_historical: - cursor_historical.disconnect() + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.ENERGY_CATEGORY_NOT_FOUND') @@ -423,6 +423,11 @@ class Reporting: if cnx_energy: cnx_energy.disconnect() + if cursor_historical: + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() + result = dict() result['equipment'] = dict() diff --git a/myems-api/reports/equipmentsaving.py b/myems-api/reports/equipmentsaving.py index af3a3247..797e7794 100644 --- a/myems-api/reports/equipmentsaving.py +++ b/myems-api/reports/equipmentsaving.py @@ -152,10 +152,10 @@ class Reporting: if cnx_energy_baseline: cnx_energy_baseline.disconnect() - if cnx_historical: - cnx_historical.close() if cursor_historical: - cursor_historical.disconnect() + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.EQUIPMENT_NOT_FOUND') equipment = dict() @@ -212,10 +212,10 @@ class Reporting: if cnx_energy_baseline: cnx_energy_baseline.disconnect() - if cnx_historical: - cnx_historical.close() if cursor_historical: - cursor_historical.disconnect() + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.ENERGY_CATEGORY_NOT_FOUND') @@ -575,6 +575,11 @@ class Reporting: if cnx_energy_baseline: cnx_energy_baseline.disconnect() + if cursor_historical: + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() + result = dict() result['equipment'] = dict() diff --git a/myems-api/reports/equipmentstatistics.py b/myems-api/reports/equipmentstatistics.py index 168d6ed2..b4aff44d 100644 --- a/myems-api/reports/equipmentstatistics.py +++ b/myems-api/reports/equipmentstatistics.py @@ -144,10 +144,10 @@ class Reporting: if cnx_energy: cnx_energy.disconnect() - if cnx_historical: - cnx_historical.close() if cursor_historical: - cursor_historical.disconnect() + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.EQUIPMENT_NOT_FOUND') equipment = dict() @@ -199,10 +199,10 @@ class Reporting: if cnx_energy: cnx_energy.disconnect() - if cnx_historical: - cnx_historical.close() if cursor_historical: - cursor_historical.disconnect() + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.ENERGY_CATEGORY_NOT_FOUND') @@ -451,6 +451,11 @@ class Reporting: if cnx_energy: cnx_energy.disconnect() + if cursor_historical: + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() + result = dict() result['equipment'] = dict() diff --git a/myems-api/reports/shopfloorcost.py b/myems-api/reports/shopfloorcost.py index 374ac1d1..6a618690 100644 --- a/myems-api/reports/shopfloorcost.py +++ b/myems-api/reports/shopfloorcost.py @@ -145,10 +145,10 @@ class Reporting: if cnx_billing: cnx_billing.disconnect() - if cnx_historical: - cnx_historical.close() if cursor_historical: - cursor_historical.disconnect() + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.SHOPFLOOR_NOT_FOUND') shopfloor = dict() @@ -201,10 +201,10 @@ class Reporting: if cnx_billing: cnx_billing.disconnect() - if cnx_historical: - cnx_historical.close() if cursor_historical: - cursor_historical.disconnect() + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.ENERGY_CATEGORY_NOT_FOUND') @@ -457,6 +457,11 @@ class Reporting: if cnx_billing: cnx_billing.disconnect() + if cursor_historical: + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() + result = dict() result['shopfloor'] = dict() diff --git a/myems-api/reports/shopfloorenergycategory.py b/myems-api/reports/shopfloorenergycategory.py index 68c987e6..ceff62bc 100644 --- a/myems-api/reports/shopfloorenergycategory.py +++ b/myems-api/reports/shopfloorenergycategory.py @@ -145,10 +145,10 @@ class Reporting: if cnx_energy: cnx_energy.disconnect() - if cnx_historical: - cnx_historical.close() if cursor_historical: - cursor_historical.disconnect() + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.SHOPFLOOR_NOT_FOUND') shopfloor = dict() @@ -201,10 +201,10 @@ class Reporting: if cnx_energy: cnx_energy.disconnect() - if cnx_historical: - cnx_historical.close() if cursor_historical: - cursor_historical.disconnect() + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.ENERGY_CATEGORY_NOT_FOUND') @@ -471,6 +471,11 @@ class Reporting: if cnx_energy: cnx_energy.disconnect() + if cursor_historical: + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() + result = dict() result['shopfloor'] = dict() diff --git a/myems-api/reports/shopfloorenergyitem.py b/myems-api/reports/shopfloorenergyitem.py index be542b1e..ed59f557 100644 --- a/myems-api/reports/shopfloorenergyitem.py +++ b/myems-api/reports/shopfloorenergyitem.py @@ -145,10 +145,10 @@ class Reporting: if cnx_energy: cnx_energy.disconnect() - if cnx_historical: - cnx_historical.close() if cursor_historical: - cursor_historical.disconnect() + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.SHOPFLOOR_NOT_FOUND') shopfloor = dict() @@ -203,10 +203,10 @@ class Reporting: if cnx_energy: cnx_energy.disconnect() - if cnx_historical: - cnx_historical.close() if cursor_historical: - cursor_historical.disconnect() + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.ENERGY_ITEM_NOT_FOUND') @@ -463,6 +463,11 @@ class Reporting: if cnx_energy: cnx_energy.disconnect() + if cursor_historical: + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() + result = dict() result['shopfloor'] = dict() diff --git a/myems-api/reports/shopfloorload.py b/myems-api/reports/shopfloorload.py index fa67ee6a..307b8777 100644 --- a/myems-api/reports/shopfloorload.py +++ b/myems-api/reports/shopfloorload.py @@ -145,10 +145,10 @@ class Reporting: if cnx_energy: cnx_energy.disconnect() - if cnx_historical: - cnx_historical.close() if cursor_historical: - cursor_historical.disconnect() + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.SHOPFLOOR_NOT_FOUND') shopfloor = dict() @@ -201,10 +201,10 @@ class Reporting: if cnx_energy: cnx_energy.disconnect() - if cnx_historical: - cnx_historical.close() if cursor_historical: - cursor_historical.disconnect() + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.ENERGY_CATEGORY_NOT_FOUND') @@ -460,6 +460,11 @@ class Reporting: if cnx_energy: cnx_energy.disconnect() + if cursor_historical: + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() + result = dict() result['shopfloor'] = dict() diff --git a/myems-api/reports/shopfloorsaving.py b/myems-api/reports/shopfloorsaving.py index 1438f7d6..86a89c0a 100644 --- a/myems-api/reports/shopfloorsaving.py +++ b/myems-api/reports/shopfloorsaving.py @@ -153,10 +153,10 @@ class Reporting: if cnx_energy_baseline: cnx_energy_baseline.disconnect() - if cnx_historical: - cnx_historical.close() if cursor_historical: - cursor_historical.disconnect() + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.SHOPFLOOR_NOT_FOUND') shopfloor = dict() @@ -214,10 +214,10 @@ class Reporting: if cnx_energy_baseline: cnx_energy_baseline.disconnect() - if cnx_historical: - cnx_historical.close() if cursor_historical: - cursor_historical.disconnect() + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.ENERGY_CATEGORY_NOT_FOUND') @@ -590,6 +590,11 @@ class Reporting: if cnx_energy_baseline: cnx_energy_baseline.disconnect() + if cursor_historical: + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() + result = dict() result['shopfloor'] = dict() diff --git a/myems-api/reports/shopfloorstatistics.py b/myems-api/reports/shopfloorstatistics.py index a9347114..53f4839a 100644 --- a/myems-api/reports/shopfloorstatistics.py +++ b/myems-api/reports/shopfloorstatistics.py @@ -145,10 +145,10 @@ class Reporting: if cnx_energy: cnx_energy.disconnect() - if cnx_historical: - cnx_historical.close() if cursor_historical: - cursor_historical.disconnect() + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.SHOPFLOOR_NOT_FOUND') shopfloor = dict() @@ -201,10 +201,10 @@ class Reporting: if cnx_energy: cnx_energy.disconnect() - if cnx_historical: - cnx_historical.close() if cursor_historical: - cursor_historical.disconnect() + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.ENERGY_CATEGORY_NOT_FOUND') @@ -466,6 +466,11 @@ class Reporting: if cnx_energy: cnx_energy.disconnect() + if cursor_historical: + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() + result = dict() result['shopfloor'] = dict() diff --git a/myems-api/reports/spacecost.py b/myems-api/reports/spacecost.py index 941af121..b3393e09 100644 --- a/myems-api/reports/spacecost.py +++ b/myems-api/reports/spacecost.py @@ -147,10 +147,10 @@ class Reporting: if cnx_billing: cnx_billing.disconnect() - if cnx_historical: - cnx_historical.close() if cursor_historical: - cursor_historical.disconnect() + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.SPACE_NOT_FOUND') space = dict() @@ -203,10 +203,10 @@ class Reporting: if cnx_billing: cnx_billing.disconnect() - if cnx_historical: - cnx_historical.close() if cursor_historical: - cursor_historical.disconnect() + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.ENERGY_CATEGORY_NOT_FOUND') @@ -499,6 +499,11 @@ class Reporting: if cnx_billing: cnx_billing.disconnect() + if cursor_historical: + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() + result = dict() result['space'] = dict() diff --git a/myems-api/reports/spaceefficiency.py b/myems-api/reports/spaceefficiency.py index b95fabf5..b39314e6 100644 --- a/myems-api/reports/spaceefficiency.py +++ b/myems-api/reports/spaceefficiency.py @@ -146,10 +146,10 @@ class Reporting: if cnx_energy: cnx_energy.disconnect() - if cnx_historical: - cnx_historical.close() if cursor_historical: - cursor_historical.disconnect() + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.SPACE_NOT_FOUND') space = dict() @@ -227,10 +227,10 @@ class Reporting: if cnx_energy: cnx_energy.disconnect() - if cnx_historical: - cnx_historical.close() if cursor_historical: - cursor_historical.disconnect() + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.ENERGY_CATEGORY_NOT_FOUND') @@ -554,6 +554,11 @@ class Reporting: if cnx_energy: cnx_energy.disconnect() + if cursor_historical: + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() + result = dict() result['space'] = dict() diff --git a/myems-api/reports/spaceenergycategory.py b/myems-api/reports/spaceenergycategory.py index ce88b13f..d91a7d98 100644 --- a/myems-api/reports/spaceenergycategory.py +++ b/myems-api/reports/spaceenergycategory.py @@ -147,10 +147,10 @@ class Reporting: if cnx_energy: cnx_energy.disconnect() - if cnx_historical: - cnx_historical.close() if cursor_historical: - cursor_historical.disconnect() + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.SPACE_NOT_FOUND') space = dict() @@ -203,10 +203,10 @@ class Reporting: if cnx_energy: cnx_energy.disconnect() - if cnx_historical: - cnx_historical.close() if cursor_historical: - cursor_historical.disconnect() + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.ENERGY_CATEGORY_NOT_FOUND') @@ -519,6 +519,11 @@ class Reporting: if cnx_energy: cnx_energy.disconnect() + if cursor_historical: + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() + result = dict() result['space'] = dict() diff --git a/myems-api/reports/spaceenergyitem.py b/myems-api/reports/spaceenergyitem.py index 1e273a61..f8b2b7b6 100644 --- a/myems-api/reports/spaceenergyitem.py +++ b/myems-api/reports/spaceenergyitem.py @@ -147,10 +147,10 @@ class Reporting: if cnx_energy: cnx_energy.disconnect() - if cnx_historical: - cnx_historical.close() if cursor_historical: - cursor_historical.disconnect() + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.SPACE_NOT_FOUND') space = dict() @@ -205,10 +205,10 @@ class Reporting: if cnx_energy: cnx_energy.disconnect() - if cnx_historical: - cnx_historical.close() if cursor_historical: - cursor_historical.disconnect() + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.ENERGY_ITEM_NOT_FOUND') @@ -506,6 +506,11 @@ class Reporting: if cnx_energy: cnx_energy.disconnect() + if cursor_historical: + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() + result = dict() result['space'] = dict() diff --git a/myems-api/reports/spaceincome.py b/myems-api/reports/spaceincome.py index 5ad66776..83d0d0df 100644 --- a/myems-api/reports/spaceincome.py +++ b/myems-api/reports/spaceincome.py @@ -147,10 +147,10 @@ class Reporting: if cnx_billing: cnx_billing.disconnect() - if cnx_historical: - cnx_historical.close() if cursor_historical: - cursor_historical.disconnect() + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.SPACE_NOT_FOUND') space = dict() @@ -203,10 +203,10 @@ class Reporting: if cnx_billing: cnx_billing.disconnect() - if cnx_historical: - cnx_historical.close() if cursor_historical: - cursor_historical.disconnect() + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.ENERGY_CATEGORY_NOT_FOUND') @@ -480,6 +480,11 @@ class Reporting: if cnx_billing: cnx_billing.disconnect() + if cursor_historical: + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() + result = dict() result['space'] = dict() diff --git a/myems-api/reports/spaceload.py b/myems-api/reports/spaceload.py index 3b8c3553..96bf3851 100644 --- a/myems-api/reports/spaceload.py +++ b/myems-api/reports/spaceload.py @@ -145,10 +145,10 @@ class Reporting: if cnx_energy: cnx_energy.disconnect() - if cnx_historical: - cnx_historical.close() if cursor_historical: - cursor_historical.disconnect() + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.SPACE_NOT_FOUND') space = dict() @@ -201,10 +201,10 @@ class Reporting: if cnx_energy: cnx_energy.disconnect() - if cnx_historical: - cnx_historical.close() if cursor_historical: - cursor_historical.disconnect() + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.ENERGY_CATEGORY_NOT_FOUND') @@ -460,6 +460,11 @@ class Reporting: if cnx_energy: cnx_energy.disconnect() + if cursor_historical: + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() + result = dict() result['space'] = dict() diff --git a/myems-api/reports/spaceoutput.py b/myems-api/reports/spaceoutput.py index a1dc983b..0955b525 100644 --- a/myems-api/reports/spaceoutput.py +++ b/myems-api/reports/spaceoutput.py @@ -147,10 +147,10 @@ class Reporting: if cnx_energy: cnx_energy.disconnect() - if cnx_historical: - cnx_historical.close() if cursor_historical: - cursor_historical.disconnect() + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.SPACE_NOT_FOUND') space = dict() @@ -203,10 +203,10 @@ class Reporting: if cnx_energy: cnx_energy.disconnect() - if cnx_historical: - cnx_historical.close() if cursor_historical: - cursor_historical.disconnect() + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.ENERGY_CATEGORY_NOT_FOUND') @@ -480,6 +480,11 @@ class Reporting: if cnx_energy: cnx_energy.disconnect() + if cursor_historical: + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() + result = dict() result['space'] = dict() diff --git a/myems-api/reports/spacesaving.py b/myems-api/reports/spacesaving.py index fc74b2f2..9f6dc75d 100644 --- a/myems-api/reports/spacesaving.py +++ b/myems-api/reports/spacesaving.py @@ -155,10 +155,10 @@ class Reporting: if cnx_energy_baseline: cnx_energy_baseline.disconnect() - if cnx_historical: - cnx_historical.close() if cursor_historical: - cursor_historical.disconnect() + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.SPACE_NOT_FOUND') space = dict() @@ -216,10 +216,10 @@ class Reporting: if cnx_energy_baseline: cnx_energy_baseline.disconnect() - if cnx_historical: - cnx_historical.close() if cursor_historical: - cursor_historical.disconnect() + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.ENERGY_CATEGORY_NOT_FOUND') @@ -661,6 +661,11 @@ class Reporting: if cnx_energy_baseline: cnx_energy_baseline.disconnect() + if cursor_historical: + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() + result = dict() result['space'] = dict() diff --git a/myems-api/reports/spacestatistics.py b/myems-api/reports/spacestatistics.py index 1a34f03b..9ccbc6b5 100644 --- a/myems-api/reports/spacestatistics.py +++ b/myems-api/reports/spacestatistics.py @@ -145,10 +145,10 @@ class Reporting: if cnx_energy: cnx_energy.disconnect() - if cnx_historical: - cnx_historical.close() if cursor_historical: - cursor_historical.disconnect() + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.SPACE_NOT_FOUND') space = dict() @@ -201,10 +201,10 @@ class Reporting: if cnx_energy: cnx_energy.disconnect() - if cnx_historical: - cnx_historical.close() if cursor_historical: - cursor_historical.disconnect() + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.ENERGY_CATEGORY_NOT_FOUND') @@ -464,6 +464,11 @@ class Reporting: if cnx_energy: cnx_energy.disconnect() + if cursor_historical: + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() + result = dict() result['space'] = dict() diff --git a/myems-api/reports/storecost.py b/myems-api/reports/storecost.py index fa01c452..55700365 100644 --- a/myems-api/reports/storecost.py +++ b/myems-api/reports/storecost.py @@ -145,10 +145,10 @@ class Reporting: if cnx_billing: cnx_billing.disconnect() - if cnx_historical: - cnx_historical.close() if cursor_historical: - cursor_historical.disconnect() + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.STORE_NOT_FOUND') store = dict() @@ -201,10 +201,10 @@ class Reporting: if cnx_billing: cnx_billing.disconnect() - if cnx_historical: - cnx_historical.close() if cursor_historical: - cursor_historical.disconnect() + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.ENERGY_CATEGORY_NOT_FOUND') @@ -455,6 +455,11 @@ class Reporting: if cnx_billing: cnx_billing.disconnect() + if cursor_historical: + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() + result = dict() result['store'] = dict() diff --git a/myems-api/reports/storeenergycategory.py b/myems-api/reports/storeenergycategory.py index 5b909327..e752e688 100644 --- a/myems-api/reports/storeenergycategory.py +++ b/myems-api/reports/storeenergycategory.py @@ -145,10 +145,10 @@ class Reporting: if cnx_energy: cnx_energy.disconnect() - if cnx_historical: - cnx_historical.close() if cursor_historical: - cursor_historical.disconnect() + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.STORE_NOT_FOUND') store = dict() @@ -201,10 +201,10 @@ class Reporting: if cnx_energy: cnx_energy.disconnect() - if cnx_historical: - cnx_historical.close() if cursor_historical: - cursor_historical.disconnect() + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.ENERGY_CATEGORY_NOT_FOUND') @@ -469,6 +469,11 @@ class Reporting: if cnx_energy: cnx_energy.disconnect() + if cursor_historical: + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() + result = dict() result['store'] = dict() diff --git a/myems-api/reports/storeenergyitem.py b/myems-api/reports/storeenergyitem.py index 63697e38..14e0ed98 100644 --- a/myems-api/reports/storeenergyitem.py +++ b/myems-api/reports/storeenergyitem.py @@ -145,10 +145,10 @@ class Reporting: if cnx_energy: cnx_energy.disconnect() - if cnx_historical: - cnx_historical.close() if cursor_historical: - cursor_historical.disconnect() + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.STORE_NOT_FOUND') store = dict() @@ -203,10 +203,10 @@ class Reporting: if cnx_energy: cnx_energy.disconnect() - if cnx_historical: - cnx_historical.close() if cursor_historical: - cursor_historical.disconnect() + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.ENERGY_ITEM_NOT_FOUND') @@ -461,6 +461,11 @@ class Reporting: if cnx_energy: cnx_energy.disconnect() + if cursor_historical: + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() + result = dict() result['store'] = dict() diff --git a/myems-api/reports/storeload.py b/myems-api/reports/storeload.py index be2d95bd..7bc04fc3 100644 --- a/myems-api/reports/storeload.py +++ b/myems-api/reports/storeload.py @@ -145,10 +145,10 @@ class Reporting: if cnx_energy: cnx_energy.disconnect() - if cnx_historical: - cnx_historical.close() if cursor_historical: - cursor_historical.disconnect() + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.STORE_NOT_FOUND') store = dict() @@ -201,10 +201,10 @@ class Reporting: if cnx_energy: cnx_energy.disconnect() - if cnx_historical: - cnx_historical.close() if cursor_historical: - cursor_historical.disconnect() + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.ENERGY_CATEGORY_NOT_FOUND') @@ -460,6 +460,11 @@ class Reporting: if cnx_energy: cnx_energy.disconnect() + if cursor_historical: + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() + result = dict() result['store'] = dict() diff --git a/myems-api/reports/storesaving.py b/myems-api/reports/storesaving.py index edac5b5d..651548c7 100644 --- a/myems-api/reports/storesaving.py +++ b/myems-api/reports/storesaving.py @@ -153,10 +153,10 @@ class Reporting: if cnx_energy_baseline: cnx_energy_baseline.disconnect() - if cnx_historical: - cnx_historical.close() if cursor_historical: - cursor_historical.disconnect() + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.STORE_NOT_FOUND') store = dict() @@ -214,10 +214,10 @@ class Reporting: if cnx_energy_baseline: cnx_energy_baseline.disconnect() - if cnx_historical: - cnx_historical.close() if cursor_historical: - cursor_historical.disconnect() + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.ENERGY_CATEGORY_NOT_FOUND') @@ -586,6 +586,11 @@ class Reporting: if cnx_energy_baseline: cnx_energy_baseline.disconnect() + if cursor_historical: + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() + result = dict() result['store'] = dict() diff --git a/myems-api/reports/storestatistics.py b/myems-api/reports/storestatistics.py index 34ef4fb5..a5c2f16a 100644 --- a/myems-api/reports/storestatistics.py +++ b/myems-api/reports/storestatistics.py @@ -146,10 +146,10 @@ class Reporting: if cnx_energy: cnx_energy.disconnect() - if cnx_historical: - cnx_historical.close() if cursor_historical: - cursor_historical.disconnect() + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.STORE_NOT_FOUND') store = dict() @@ -202,10 +202,10 @@ class Reporting: if cnx_energy: cnx_energy.disconnect() - if cnx_historical: - cnx_historical.close() if cursor_historical: - cursor_historical.disconnect() + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.ENERGY_CATEGORY_NOT_FOUND') @@ -465,6 +465,11 @@ class Reporting: if cnx_energy: cnx_energy.disconnect() + if cursor_historical: + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() + result = dict() result['store'] = dict() diff --git a/myems-api/reports/tenantcost.py b/myems-api/reports/tenantcost.py index c9366671..cad4f0a7 100644 --- a/myems-api/reports/tenantcost.py +++ b/myems-api/reports/tenantcost.py @@ -145,10 +145,10 @@ class Reporting: if cnx_billing: cnx_billing.disconnect() - if cnx_historical: - cnx_historical.close() if cursor_historical: - cursor_historical.disconnect() + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.TENANT_NOT_FOUND') tenant = dict() @@ -201,10 +201,10 @@ class Reporting: if cnx_billing: cnx_billing.disconnect() - if cnx_historical: - cnx_historical.close() if cursor_historical: - cursor_historical.disconnect() + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.ENERGY_CATEGORY_NOT_FOUND') @@ -455,6 +455,11 @@ class Reporting: if cnx_billing: cnx_billing.disconnect() + if cursor_historical: + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() + result = dict() result['tenant'] = dict() diff --git a/myems-api/reports/tenantenergycategory.py b/myems-api/reports/tenantenergycategory.py index 4a34a59c..c5827be6 100644 --- a/myems-api/reports/tenantenergycategory.py +++ b/myems-api/reports/tenantenergycategory.py @@ -145,10 +145,10 @@ class Reporting: if cnx_energy: cnx_energy.disconnect() - if cnx_historical: - cnx_historical.close() if cursor_historical: - cursor_historical.disconnect() + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.TENANT_NOT_FOUND') tenant = dict() @@ -201,10 +201,10 @@ class Reporting: if cnx_energy: cnx_energy.disconnect() - if cnx_historical: - cnx_historical.close() if cursor_historical: - cursor_historical.disconnect() + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.ENERGY_CATEGORY_NOT_FOUND') @@ -469,6 +469,11 @@ class Reporting: if cnx_energy: cnx_energy.disconnect() + if cursor_historical: + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() + result = dict() result['tenant'] = dict() diff --git a/myems-api/reports/tenantenergyitem.py b/myems-api/reports/tenantenergyitem.py index 740cc972..515589db 100644 --- a/myems-api/reports/tenantenergyitem.py +++ b/myems-api/reports/tenantenergyitem.py @@ -145,10 +145,10 @@ class Reporting: if cnx_energy: cnx_energy.disconnect() - if cnx_historical: - cnx_historical.close() if cursor_historical: - cursor_historical.disconnect() + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.TENANT_NOT_FOUND') tenant = dict() @@ -203,10 +203,10 @@ class Reporting: if cnx_energy: cnx_energy.disconnect() - if cnx_historical: - cnx_historical.close() if cursor_historical: - cursor_historical.disconnect() + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.ENERGY_ITEM_NOT_FOUND') @@ -461,6 +461,11 @@ class Reporting: if cnx_energy: cnx_energy.disconnect() + if cursor_historical: + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() + result = dict() result['tenant'] = dict() diff --git a/myems-api/reports/tenantload.py b/myems-api/reports/tenantload.py index 637d4bf9..a87b02e7 100644 --- a/myems-api/reports/tenantload.py +++ b/myems-api/reports/tenantload.py @@ -145,10 +145,10 @@ class Reporting: if cnx_energy: cnx_energy.disconnect() - if cnx_historical: - cnx_historical.close() if cursor_historical: - cursor_historical.disconnect() + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.TENANT_NOT_FOUND') tenant = dict() @@ -201,10 +201,10 @@ class Reporting: if cnx_energy: cnx_energy.disconnect() - if cnx_historical: - cnx_historical.close() if cursor_historical: - cursor_historical.disconnect() + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.ENERGY_CATEGORY_NOT_FOUND') @@ -460,6 +460,11 @@ class Reporting: if cnx_energy: cnx_energy.disconnect() + if cursor_historical: + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() + result = dict() result['tenant'] = dict() diff --git a/myems-api/reports/tenantsaving.py b/myems-api/reports/tenantsaving.py index f376579f..bf503c47 100644 --- a/myems-api/reports/tenantsaving.py +++ b/myems-api/reports/tenantsaving.py @@ -153,10 +153,10 @@ class Reporting: if cnx_energy_baseline: cnx_energy_baseline.disconnect() - if cnx_historical: - cnx_historical.close() if cursor_historical: - cursor_historical.disconnect() + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.TENANT_NOT_FOUND') tenant = dict() @@ -214,10 +214,10 @@ class Reporting: if cnx_energy_baseline: cnx_energy_baseline.disconnect() - if cnx_historical: - cnx_historical.close() if cursor_historical: - cursor_historical.disconnect() + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.ENERGY_CATEGORY_NOT_FOUND') @@ -586,6 +586,11 @@ class Reporting: if cnx_energy_baseline: cnx_energy_baseline.disconnect() + if cursor_historical: + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() + result = dict() result['tenant'] = dict() diff --git a/myems-api/reports/tenantstatistics.py b/myems-api/reports/tenantstatistics.py index ffcbd2f0..3f189a5c 100644 --- a/myems-api/reports/tenantstatistics.py +++ b/myems-api/reports/tenantstatistics.py @@ -145,10 +145,10 @@ class Reporting: if cnx_energy: cnx_energy.disconnect() - if cnx_historical: - cnx_historical.close() if cursor_historical: - cursor_historical.disconnect() + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.TENANT_NOT_FOUND') tenant = dict() @@ -201,10 +201,10 @@ class Reporting: if cnx_energy: cnx_energy.disconnect() - if cnx_historical: - cnx_historical.close() if cursor_historical: - cursor_historical.disconnect() + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.ENERGY_CATEGORY_NOT_FOUND') @@ -464,6 +464,11 @@ class Reporting: if cnx_energy: cnx_energy.disconnect() + if cursor_historical: + cursor_historical.close() + if cnx_historical: + cnx_historical.disconnect() + result = dict() result['tenant'] = dict() diff --git a/myems-normalization/offlinemeter.py b/myems-normalization/offlinemeter.py index 631b10ba..8bb0a8a2 100644 --- a/myems-normalization/offlinemeter.py +++ b/myems-normalization/offlinemeter.py @@ -2,6 +2,7 @@ import time from datetime import datetime, timedelta import mysql.connector from openpyxl import load_workbook +from decimal import Decimal import config ################################################################################################################ @@ -71,7 +72,7 @@ def calculate_hourly(logger): # STEP 2: for each new files, dump file object to local file and then load workbook from the local file ################################################################################################################ for excel_file in excel_file_list: - print("read data from each offline meter file" + excel_file['name']) + print("read data from offline meter file" + excel_file['name']) is_valid_file = True fw = None try: @@ -134,20 +135,20 @@ def calculate_hourly(logger): elif col_num > 3: # get date of the cell try: - offline_datetime = datetime(year=ws['A2'].value, - month=ws['B2'].value, - day=col_num - 3) + start_datetime_local = datetime(year=ws['A2'].value, + month=ws['B2'].value, + day=col_num - 3) except ValueError: # invalid date and go to next cell in this row until reach max_col continue - offline_datetime_utc = offline_datetime - timedelta(minutes=timezone_offset) + start_datetime_utc = start_datetime_local - timedelta(minutes=timezone_offset) if cell.value is None: # if the cell is empty then stop at that day break else: - offline_meter_data['data'][offline_datetime_utc] = cell.value + offline_meter_data['data'][start_datetime_utc] = Decimal(cell.value) if len(offline_meter_data['data']) > 0: print("offline_meter_data:" + str(offline_meter_data)) @@ -224,10 +225,10 @@ def calculate_hourly(logger): for energy_data_item in energy_data_list: offline_meter_id = energy_data_item['offline_meter_id'] print(energy_data_item['data'].items()) - for k, v in energy_data_item['data'].items(): - start_datetime_utc = k + for start_datetime_utc, daily_value in energy_data_item['data'].items(): end_datetime_utc = start_datetime_utc + timedelta(hours=24) - actual_value = v / (24 * 60 / config.minutes_to_count) + actual_value = \ + daily_value / (Decimal(24) * Decimal(60) / Decimal(config.minutes_to_count)) cursor.execute(" DELETE FROM tbl_offline_meter_hourly " " WHERE offline_meter_id = %s " " AND start_datetime_utc >= %s " diff --git a/web/package.json b/web/package.json index d195882f..34c4e7c9 100644 --- a/web/package.json +++ b/web/package.json @@ -1,6 +1,6 @@ { "name": "myems", - "version": "1.0.7", + "version": "1.1.0", "private": true, "dependencies": { "@fortawesome/fontawesome-svg-core": "^1.2.28", diff --git a/web/src/components/MyEMS/AuxiliarySystem/EnergyFlowDiagram.js b/web/src/components/MyEMS/AuxiliarySystem/EnergyFlowDiagram.js index 51232e3f..7ae80801 100644 --- a/web/src/components/MyEMS/AuxiliarySystem/EnergyFlowDiagram.js +++ b/web/src/components/MyEMS/AuxiliarySystem/EnergyFlowDiagram.js @@ -50,8 +50,8 @@ const EnergyFlowDiagram = ({ setRedirect, setRedirectUrl, t }) => { // Query Parameters const [energyFlowDiagramList, setEnergyFlowDiagramList] = useState([]); const [selectedEnergyFlowDiagram, setSelectedEnergyFlowDiagram] = useState(undefined); - const [reportingPeriodBeginsDatetime, setReportingPeriodBeginsDatetime] = useState(current_moment.clone().startOf('month')); - const [reportingPeriodEndsDatetime, setReportingPeriodEndsDatetime] = useState(current_moment); + const [reportingPeriodBeginsDatetime, setReportingPeriodBeginsDatetime] = useState(current_moment.clone().subtract(1, 'months').startOf('month')); + const [reportingPeriodEndsDatetime, setReportingPeriodEndsDatetime] = useState(current_moment.clone().subtract(1, 'months').endOf('month')); const { isDark } = useContext(AppContext); // buttons diff --git a/web/src/components/MyEMS/CombinedEquipment/CombinedEquipmentEfficiency.js b/web/src/components/MyEMS/CombinedEquipment/CombinedEquipmentEfficiency.js index 8b175b8c..c37a3fb4 100644 --- a/web/src/components/MyEMS/CombinedEquipment/CombinedEquipmentEfficiency.js +++ b/web/src/components/MyEMS/CombinedEquipment/CombinedEquipmentEfficiency.js @@ -25,11 +25,11 @@ import LineChart from '../common/LineChart'; import { getCookieValue, createCookie } from '../../../helpers/utils'; import withRedirect from '../../../hoc/withRedirect'; import { withTranslation } from 'react-i18next'; -import { periodTypeOptions } from '../common/PeriodTypeOptions'; -import { comparisonTypeOptions } from '../common/ComparisonTypeOptions'; import { toast } from 'react-toastify'; import ButtonIcon from '../../common/ButtonIcon'; import { APIBaseURL } from '../../../config'; +import { periodTypeOptions } from '../common/PeriodTypeOptions'; +import { comparisonTypeOptions } from '../common/ComparisonTypeOptions'; const DetailedDataTable = loadable(() => import('../common/DetailedDataTable')); @@ -68,15 +68,15 @@ const CombinedEquipmentEfficiency = ({ setRedirect, setRedirectUrl, t }) => { const [basePeriodEndsDatetimeDisabled, setBasePeriodEndsDatetimeDisabled] = useState(true); const [reportingPeriodBeginsDatetime, setReportingPeriodBeginsDatetime] = useState(current_moment.clone().startOf('month')); const [reportingPeriodEndsDatetime, setReportingPeriodEndsDatetime] = useState(current_moment); - const [fractionParameter, setFractionParameter] = useState(1); const [cascaderOptions, setCascaderOptions] = useState(undefined); // buttons const [submitButtonDisabled, setSubmitButtonDisabled] = useState(true); const [spinnerHidden, setSpinnerHidden] = useState(true); const [exportButtonHidden, setExportButtonHidden] = useState(true); - + //Results + const [cardSummaryList, setCardSummaryList] = useState([]); const [combinedEquipmentLineChartLabels, setCombinedEquipmentLineChartLabels] = useState([]); const [combinedEquipmentLineChartData, setCombinedEquipmentLineChartData] = useState({}); const [combinedEquipmentLineChartOptions, setCombinedEquipmentLineChartOptions] = useState([]); @@ -114,7 +114,7 @@ const CombinedEquipmentEfficiency = ({ setRedirect, setRedirectUrl, t }) => { setCascaderOptions(json); setSelectedSpaceName([json[0]].map(o => o.label)); setSelectedSpaceID([json[0]].map(o => o.value)); - // get Combined Equipments by root Space ID + // get CombinedEquipments by root Space ID let isResponseOK = false; fetch(APIBaseURL + '/spaces/' + [json[0]].map(o => o.value) + '/combinedequipments', { method: 'GET', @@ -150,7 +150,7 @@ const CombinedEquipmentEfficiency = ({ setRedirect, setRedirectUrl, t }) => { }).catch(err => { console.log(err); }); - // end of get Combined Equipments by root Space ID + // end of get CombinedEquipments by root Space ID } else { toast.error(json.description) } @@ -159,13 +159,11 @@ const CombinedEquipmentEfficiency = ({ setRedirect, setRedirectUrl, t }) => { }); }, []); - - const fractionParameterOptions = [ - { value: 1, label: '综合能效比EER' },]; - + const labelClasses = 'ls text-uppercase text-600 font-weight-semi-bold mb-0'; let onSpaceCascaderChange = (value, selectedOptions) => { + console.log(value, selectedOptions); setSelectedSpaceName(selectedOptions.map(o => o.label).join('/')); setSelectedSpaceID(value[value.length - 1]); @@ -198,6 +196,9 @@ const CombinedEquipmentEfficiency = ({ setRedirect, setRedirectUrl, t }) => { // disable submit button setSubmitButtonDisabled(true); } + + // hide export buttion + setExportButtonHidden(true) } else { toast.error(json.description) } @@ -206,7 +207,6 @@ const CombinedEquipmentEfficiency = ({ setRedirect, setRedirectUrl, t }) => { }); } - let onComparisonTypeChange = ({ target }) => { console.log(target.value); setComparisonType(target.value); @@ -279,12 +279,13 @@ const CombinedEquipmentEfficiency = ({ setRedirect, setRedirectUrl, t }) => { console.log('handleSubmit'); console.log(selectedSpaceID); console.log(selectedCombinedEquipment); + console.log(comparisonType); console.log(periodType); console.log(basePeriodBeginsDatetime != null ? basePeriodBeginsDatetime.format('YYYY-MM-DDTHH:mm:ss') : undefined); console.log(basePeriodEndsDatetime != null ? basePeriodEndsDatetime.format('YYYY-MM-DDTHH:mm:ss') : undefined); console.log(reportingPeriodBeginsDatetime.format('YYYY-MM-DDTHH:mm:ss')); console.log(reportingPeriodEndsDatetime.format('YYYY-MM-DDTHH:mm:ss')); - + // disable submit button setSubmitButtonDisabled(true); // show spinner @@ -298,7 +299,6 @@ const CombinedEquipmentEfficiency = ({ setRedirect, setRedirectUrl, t }) => { let isResponseOK = false; fetch(APIBaseURL + '/reports/combinedequipmentefficiency?' + 'combinedequipmentid=' + selectedCombinedEquipment + - '&fractionparameterid=' + fractionParameter + '&periodtype=' + periodType + '&baseperiodstartdatetime=' + (basePeriodBeginsDatetime != null ? basePeriodBeginsDatetime.format('YYYY-MM-DDTHH:mm:ss') : '') + '&baseperiodenddatetime=' + (basePeriodEndsDatetime != null ? basePeriodEndsDatetime.format('YYYY-MM-DDTHH:mm:ss') : '') + @@ -315,185 +315,124 @@ const CombinedEquipmentEfficiency = ({ setRedirect, setRedirectUrl, t }) => { }).then(response => { if (response.ok) { isResponseOK = true; - }; + } return response.json(); }).then(json => { if (isResponseOK) { console.log(json) - - setCombinedEquipmentLineChartLabels({ - a0: ['2020-07-01','2020-07-02', '2020-07-03', '2020-07-04', '2020-07-05', '2020-07-06', '2020-07-07', '2020-07-08', '2020-07-09','2020-07-10','2020-07-11','2020-07-12'], - a1: ['2020-07-01','2020-07-02', '2020-07-03', '2020-07-04', '2020-07-05', '2020-07-06', '2020-07-07', '2020-07-08', '2020-07-09','2020-07-10','2020-07-11','2020-07-12'], - a2: ['2020-07-01','2020-07-02', '2020-07-03', '2020-07-04', '2020-07-05', '2020-07-06', '2020-07-07', '2020-07-08', '2020-07-09','2020-07-10','2020-07-11','2020-07-12'], - a3: ['2020-07-01','2020-07-02', '2020-07-03', '2020-07-04', '2020-07-05', '2020-07-06', '2020-07-07', '2020-07-08', '2020-07-09','2020-07-10','2020-07-11','2020-07-12'], - }); - - setCombinedEquipmentLineChartData({ - a0: [4, 1, 6, 2, 7, 12, 4, 6, 5, 4, 5, 10], - a1: [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5, 8], - a2: [1, 0, 2, 1, 2, 1, 1, 0, 0, 1, 0, 2], - a3: [1, 0, 2, 1, 2, 1, 1, 0, 0, 1, 0, 2] - }); - - setCombinedEquipmentLineChartOptions([ - { value: 'a', label: '综合能效比EER' }, - ]); - setParameterLineChartLabels({ - a0: ['2020-07-01','2020-07-02', '2020-07-03', '2020-07-04', '2020-07-05', '2020-07-06', '2020-07-07', '2020-07-08', '2020-07-09','2020-07-10','2020-07-11','2020-07-12'], - a1: ['2020-07-01','2020-07-02', '2020-07-03', '2020-07-04', '2020-07-05', '2020-07-06', '2020-07-07', '2020-07-08', '2020-07-09','2020-07-10','2020-07-11','2020-07-12'], - a2: ['2020-07-01','2020-07-02', '2020-07-03', '2020-07-04', '2020-07-05', '2020-07-06', '2020-07-07', '2020-07-08', '2020-07-09','2020-07-10','2020-07-11','2020-07-12'], - a3: ['2020-07-01','2020-07-02', '2020-07-03', '2020-07-04', '2020-07-05', '2020-07-06', '2020-07-07', '2020-07-08', '2020-07-09','2020-07-10','2020-07-11','2020-07-12'], + let cardSummaryArray = [] + json['reporting_period_efficiency']['names'].forEach((currentValue, index) => { + let cardSummaryItem = {} + cardSummaryItem['name'] = json['reporting_period_efficiency']['names'][index]; + cardSummaryItem['unit'] = json['reporting_period_efficiency']['units'][index]; + cardSummaryItem['cumulation'] = json['reporting_period_efficiency']['cumulations'][index]; + cardSummaryItem['increment_rate'] = parseFloat(json['reporting_period_efficiency']['increment_rates'][index] * 100).toFixed(2) + "%"; + cardSummaryArray.push(cardSummaryItem); }); - - setParameterLineChartData({ - a0: [40, 31, 36, 32, 27, 32, 34, 26, 25, 24, 25, 30], - a1: [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5, 8], - a2: [1, 0, 2, 1, 2, 1, 1, 0, 0, 1, 0, 2], - a3: [1, 0, 2, 1, 2, 1, 1, 0, 0, 1, 0, 2], - a4: [1, 0, 2, 1, 2, 1, 1, 0, 0, 1, 0, 2] + setCardSummaryList(cardSummaryArray); + + let timestamps = {} + json['reporting_period_efficiency']['timestamps'].forEach((currentValue, index) => { + timestamps['a' + index] = currentValue; }); + setCombinedEquipmentLineChartLabels(timestamps); + + let values = {} + json['reporting_period_efficiency']['values'].forEach((currentValue, index) => { + values['a' + index] = currentValue; + }); + setCombinedEquipmentLineChartData(values); + + let names = Array(); + json['reporting_period_efficiency']['names'].forEach((currentValue, index) => { + let unit = json['reporting_period_efficiency']['units'][index]; + names.push({ 'value': 'a' + index, 'label': currentValue + ' (' + unit + ')'}); + }); + setCombinedEquipmentLineChartOptions(names); + + timestamps = {} + json['parameters']['timestamps'].forEach((currentValue, index) => { + timestamps['a' + index] = currentValue; + }); + setParameterLineChartLabels(timestamps); - setParameterLineChartOptions([ - { value: 'a0', label: '室外温度' }, - { value: 'a1', label: '相对湿度' }, - { value: 'a2', label: '电费率' }, - { value: 'a3', label: '自来水费率' }, - { value: 'a4', label: '天然气费率' } - ]); - - setDetailedDataTableData([ - { - id: 1, - startdatetime: '2020-07-01', - a: '9872', - b: '55975', - c: '5.67', - }, - { - id: 2, - startdatetime: '2020-07-02', - a: '9872', - b: '55975', - c: '5.67', - }, - { - id: 3, - startdatetime: '2020-07-03', - a: '9872', - b: '55975', - c: '5.67', - }, - { - id: 4, - startdatetime: '2020-07-04', - a: '9872', - b: '55975', - c: '5.67', - }, - { - id: 5, - startdatetime: '2020-07-05', - a: '9872', - b: '55975', - c: '5.67', - }, - { - id: 6, - startdatetime: '2020-07-06', - a: '9872', - b: '55975', - c: '5.67', - }, - { - id: 7, - startdatetime: '2020-07-07', - a: '9872', - b: '55975', - c: '5.67', - }, - { - id: 8, - startdatetime: '2020-07-08', - a: '9872', - b: '55975', - c: '5.67', - }, - { - id: 9, - startdatetime: '2020-07-09', - a: '9872', - b: '55975', - c: '5.67', - }, - { - id: 10, - startdatetime: '2020-07-10', - a: '9872', - b: '55975', - c: '5.67', - }, - { - id: 11, - startdatetime: '2020-07-11', - a: '9872', - b: '55975', - c: '5.67', - }, - { - id: 12, - startdatetime: '2020-07-12', - a: '9872', - b: '55975', - c: '5.67', - }, - { - id: 13, - startdatetime: t('Total'), - a: '118464', - b: '671700', - c: '5.67', + values = {} + json['parameters']['values'].forEach((currentValue, index) => { + values['a' + index] = currentValue; + }); + setParameterLineChartData(values); + + names = Array(); + json['parameters']['names'].forEach((currentValue, index) => { + if (currentValue.startsWith('TARIFF-')) { + currentValue = t('Tariff') + currentValue.replace('TARIFF-', '-'); } - ]); + + names.push({ 'value': 'a' + index, 'label': currentValue }); + }); + setParameterLineChartOptions(names); + + let detailed_value_list = []; + if (json['reporting_period_efficiency']['timestamps'].length > 0) { + json['reporting_period_efficiency']['timestamps'][0].forEach((currentTimestamp, timestampIndex) => { + let detailed_value = {}; + detailed_value['id'] = timestampIndex; + detailed_value['startdatetime'] = currentTimestamp; + json['reporting_period_efficiency']['values'].forEach((currentValue, parameterIndex) => { + if (json['reporting_period_efficiency']['values'][parameterIndex][timestampIndex] != null) { + detailed_value['a' + parameterIndex] = json['reporting_period_efficiency']['values'][parameterIndex][timestampIndex].toFixed(2); + } else { + detailed_value['a' + parameterIndex] = ''; + }; + }); + + detailed_value_list.push(detailed_value); + }); + }; - setDetailedDataTableColumns([ - { - dataField: 'startdatetime', - text: t('Datetime'), + let detailed_value = {}; + detailed_value['id'] = detailed_value_list.length; + detailed_value['startdatetime'] = t('Subtotal'); + json['reporting_period_efficiency']['cumulations'].forEach((currentValue, index) => { + detailed_value['a' + index] = currentValue.toFixed(2); + }); + detailed_value_list.push(detailed_value); + setDetailedDataTableData(detailed_value_list); + + let detailed_column_list = []; + detailed_column_list.push({ + dataField: 'startdatetime', + text: t('Datetime'), + sort: true + }) + json['reporting_period_efficiency']['names'].forEach((currentValue, index) => { + let unit = json['reporting_period_efficiency']['units'][index]; + detailed_column_list.push({ + dataField: 'a' + index, + text: currentValue + ' (' + unit + ')', sort: true - }, { - dataField: 'a', - text: '电 (kWh)', - sort: true - }, { - dataField: 'b', - text: '冷 (kWh)', - sort: true - }, { - dataField: 'c', - text: '综合能效比EER (kWh/kWh)', - sort: true - } - ]); + }) + }); + setDetailedDataTableColumns(detailed_column_list); setExcelBytesBase64(json['excel_bytes_base64']); - + // enable submit button setSubmitButtonDisabled(false); // hide spinner setSpinnerHidden(true); // show export buttion setExportButtonHidden(false); - + } else { toast.error(json.description) } }).catch(err => { console.log(err); - }); - + }); }; - + const handleExport = e => { e.preventDefault(); const mimeType='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' @@ -511,6 +450,7 @@ const CombinedEquipmentEfficiency = ({ setRedirect, setRedirectUrl, t }) => { }); }; + return (
@@ -551,21 +491,6 @@ const CombinedEquipmentEfficiency = ({ setRedirect, setRedirectUrl, t }) => { - - - - setFractionParameter(target.value)} - > - {fractionParameterOptions.map((fractionParameter, index) => ( - - ))} - - -