diff --git a/README.md b/README.md index 758fac14..42320d65 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,11 @@ MyEMS是行业领先的开源能源管理系统,利用云计算、物联网、大数据、人工智能等信息化技术构建而成。MyEMS可用于构建统一规范、功能强大的综合能源管理服务平台。MyEMS由资深专业团队开发维护,系统代码基于MIT开源软件许可协议发布。 ## MyEMS架构 -![MyEMS Architecture](/docs/images/architecture.png) + +![MyEMS Architecture Function View](/docs/images/architecture-function-view.png) + +![MyEMS Architecture Site View](/docs/images/architecture-site-view.png) + ## MyEMS组件(社区版) @@ -63,123 +67,129 @@ MyEMS项目由下列组件构成: [安装 web UI](./web/README.md) ## 功能版本对比 -| 功能 |社区版(MyEMS) |企业版(AlbertEOS)| -| :--- | :----: | :----: | -| 开源 | ✔️ | ❌ | -| 定价模式 | 免费 | 按项目付费 | -| 更换品牌名称与标志LOGO | ✔️ | ✔️ | -| Modbus TCP 协议 | ✔️ | ✔️ | -| BACnet/IP 协议 | ✔️ | ✔️ | -| MQTT 协议发布数据 | ✔️ | ✔️ | -| 数据点数 | 无限制 |无限制 | -| 计量表数 | 无限制 |无限制 | -| 设备数 | 无限制 |无限制 | -| 用能单位数 | 无限制 |无限制 | -| Docker容器化部署 | ✔️ | ✔️ | -| Kubernetes部署 | ✔️ | ✔️ | -| MySQL | ✔️ | ✔️ | -| MariaDB | ✔️ | ✔️ | -| SingleStore | ✔️ | ✔️ | -| AWS 云部署 | ✔️ | ✔️ | -| AZure 云部署 | ✔️ | ✔️ | -| 阿里云部署 | ✔️ | ✔️ | -| 私有云部署 | ✔️ | ✔️ | -| 总览页 | ✔️ | ✔️ | -| 数据比较分析(同比、环比、自由比) | ✔️ | ✔️ | -| 数据分析结果导出到Excel | ✔️ | ✔️ | -| 空间数据/能耗分类分析 | ✔️ | ✔️ | -| 空间数据/能耗分项分析 | ✔️ | ✔️ | -| 空间数据/成本分析 | ✔️ | ✔️ | -| 空间数据/产出分析 | ✔️ | ✔️ | -| 空间数据/收入分析 | ✔️ | ✔️ | -| 空间数据/效率分析 | ✔️ | ✔️ | -| 空间数据/负荷分析 | ✔️ | ✔️ | -| 空间数据/统计分析 | ✔️ | ✔️ | -| 空间数据/节能分析 | ❌ | ✔️ | -| 设备数据/能耗分类分析 | ✔️ | ✔️ | -| 设备数据/能耗分项分析 | ✔️ | ✔️ | -| 设备数据/成本分析 | ✔️ | ✔️ | -| 设备数据/产出分析 | ✔️ | ✔️ | -| 设备数据/收入分析 | ✔️ | ✔️ | -| 设备数据/效率分析 | ✔️ | ✔️ | -| 设备数据/负荷分析 | ✔️ | ✔️ | -| 设备数据/统计分析 | ✔️ | ✔️ | -| 设备数据/节能分析 | ❌ | ✔️ | -| 设备数据/设备台账 | ✔️ | ✔️ | -| 计量表数据/能耗分析 | ✔️ | ✔️ | -| 计量表数据/成本分析 | ✔️ | ✔️ | -| 计量表数据/趋势分析 | ✔️ | ✔️ | -| 计量表数据/实时分析 | ✔️ | ✔️ | -| 计量表数据/总分表平衡分析 | ✔️ | ✔️ | -| 计量表数据/离线表能耗分析 | ✔️ | ✔️ | -| 计量表数据/离线表成本分析 | ✔️ | ✔️ | -| 计量表数据/虚拟表能耗分析 | ✔️ | ✔️ | -| 计量表数据/虚拟表成本分析 | ✔️ | ✔️ | -| 计量表数据/计量表台账 | ✔️ | ✔️ | -| 租户数据/能耗分类分析 | ✔️ | ✔️ | -| 租户数据/能耗分项分析 | ✔️ | ✔️ | -| 租户数据/成本分析 | ✔️ | ✔️ | -| 租户数据/负荷分析 | ✔️ | ✔️ | -| 租户数据/统计分析 | ✔️ | ✔️ | -| 租户数据/节能分析 | ❌ | ✔️ | -| 租户数据/租户账单 | ✔️ | ✔️ | -| 门店数据/能耗分类分析 | ✔️ | ✔️ | -| 门店数据/能耗分项分析 | ✔️ | ✔️ | -| 门店数据/成本分析 | ✔️ | ✔️ | -| 门店数据/负荷分析 | ✔️ | ✔️ | -| 门店数据/统计分析 | ✔️ | ✔️ | -| 门店数据/节能分析 | ❌ | ✔️ | -| 车间数据/能耗分类分析 | ✔️ | ✔️ | -| 车间数据/能耗分项分析 | ✔️ | ✔️ | -| 车间数据/成本分析 | ✔️ | ✔️ | -| 车间数据/负荷分析 | ✔️ | ✔️ | -| 车间数据/统计分析 | ✔️ | ✔️ | -| 车间数据/节能分析 | ❌ | ✔️ | -| 组合设备数据/成本分析 | ✔️ | ✔️ | -| 组合设备数据/产出分析 | ✔️ | ✔️ | -| 组合设备数据/收入分析 | ✔️ | ✔️ | -| 组合设备数据/效率分析 | ✔️ | ✔️ | -| 组合设备数据/负荷分析 | ✔️ | ✔️ | -| 组合设备数据/统计分析 | ✔️ | ✔️ | -| 组合设备数据/节能分析 | ❌ | ✔️ | -| 能流图分析 | ✔️ | ✔️ | -| 配电系统分析 | ✔️ | ✔️ | -| REST API | ✔️ | ✔️ | -| Web UI | ✔️ | ✔️ | -| Admin UI | ✔️ | ✔️ | -| MQTT 协议订阅数据 | ❌ | ✔️ | -| Modbus RTU 协议 | ❌ | ✔️ | -| OPC UA 协议 | ❌ | ✔️ | -| OPC DA 协议 | ❌ | ✔️ | -| Siemens S7 协议 | ❌ | ✔️ | -| IEC 104 协议 | ❌ | ✔️ | -| Johnson Controls Metasys | ✔️ | ✔️ | -| Honeywell EBI | ✔️ | ✔️ | -| SIEMENS Desigo CC | ❌ | ✔️ | -| QWeather API | ❌ | ✔️ | -| FDD 能效故障诊断系统 | ❌ | ✔️ | -| 高级报表系统 | ❌ | ✔️ | -| 组态图形绘制工具 | ❌ | ✔️ | -| 设备远程控制 | ❌ | ✔️ | -| BACnet Server | ❌ | ✔️ | -| Modbus TCP Server(Slave) | ❌ | ✔️ | -| OPC UA Server | ❌ | ✔️ | -| iOS APP | ❌ | ✔️ | -| Android APP | ❌ | ✔️ | -| 微信小程序 | ❌ | ✔️ | -| 支付宝小程序 | ❌ | ✔️ | -| 工控机硬件网关(数据采集和远程控制) | ❌ | ✔️ | -| LoRa无线数传电台模块(数据采集和远程控制)| ❌ | ✔️ | -| 重点用能单位能耗在线监测系统上传省级平台通信协议| ❌ | ✔️ | -| 第三方系统集成服务 | ❌ | ✔️ | -| 在线社区技术支持 | ✔️ | ✔️ | -| 邮件技术支持 | ✔️ | ✔️ | -| 电话技术支持服务 | ❌ | ✔️ | -| 微信技术支持服务 | ❌ | ✔️ | -| 远程桌面技术支持服务 | ❌ | ✔️ | -| 现场技术支持服务 | ❌ | ✔️ | -| 投标技术支持服务 | ❌ | ✔️ | -| 二次开发技术支持服务 | ❌ | ✔️ | +| 功能 |社区版 |企业版 | 说明 | +| :--- | :----: | :----: | :----: | +| 开源 | ✔️ | ❌ | | +| 价格 | 免费 | 收费 | 标准组件授权费;定制组件开发费; | +| 更换品牌名称与标志LOGO | ✔️ | ✔️ | | +| Modbus TCP 协议 | ✔️ | ✔️ | 采集数据 | +| BACnet/IP 协议 | ✔️ | ✔️ | 采集数据 | +| MQTT 协议发布 | ✔️ | ✔️ | 发布最新采集到的数据 | +| 数据点数量 | 无限制 |无限制 | 仅受硬件性能限制 | +| 计量表数量 | 无限制 |无限制 | 仅受硬件性能限制 | +| 空间数量 | 无限制 |无限制 | 仅受硬件性能限制 | +| 设备数量 | 无限制 |无限制 | 仅受硬件性能限制 | +| 租户数量 | 无限制 |无限制 | 仅受硬件性能限制 | +| 门店数量 | 无限制 |无限制 | 仅受硬件性能限制 | +| 车间数量 | 无限制 |无限制 | 仅受硬件性能限制 | +| 组合设备数量 | 无限制 |无限制 | 仅受硬件性能限制 | +| Docker容器化部署 | ✔️ | ✔️ | | +| Kubernetes部署 | ✔️ | ✔️ | | +| MySQL | ✔️ | ✔️ | | +| MariaDB | ✔️ | ✔️ | | +| SingleStore | ✔️ | ✔️ | | +| AWS 云部署 | ✔️ | ✔️ | | +| AZure 云部署 | ✔️ | ✔️ | | +| 阿里云部署 | ✔️ | ✔️ | | +| 私有云部署 | ✔️ | ✔️ | | +| 总览页 | ✔️ | ✔️ | | +| 数据比较分析 | ✔️ | ✔️ | 同比、环比、自由比、不比 | +| Excel 导出 | ✔️ | ✔️ | 表格、曲线图、柱状图、饼状图 | +| 计量表数据/能耗分析 | ✔️ | ✔️ | | +| 计量表数据/成本分析 | ✔️ | ✔️ | | +| 计量表数据/趋势分析 | ✔️ | ✔️ | | +| 计量表数据/实时分析 | ✔️ | ✔️ | | +| 计量表数据/总分表平衡分析 | ✔️ | ✔️ | | +| 计量表数据/离线表能耗分析 | ✔️ | ✔️ | | +| 计量表数据/离线表成本分析 | ✔️ | ✔️ | | +| 计量表数据/虚拟表能耗分析 | ✔️ | ✔️ | | +| 计量表数据/虚拟表成本分析 | ✔️ | ✔️ | | +| 计量表数据/计量表台账 | ✔️ | ✔️ | | +| 空间数据/能耗分类分析 | ✔️ | ✔️ | | +| 空间数据/能耗分项分析 | ✔️ | ✔️ | | +| 空间数据/成本分析 | ✔️ | ✔️ | | +| 空间数据/产出分析 | ✔️ | ✔️ | | +| 空间数据/收入分析 | ✔️ | ✔️ | | +| 空间数据/效率分析 | ✔️ | ✔️ | | +| 空间数据/负荷分析 | ✔️ | ✔️ | | +| 空间数据/统计分析 | ✔️ | ✔️ | | +| 空间数据/节能分析 | ❌ | ✔️ | 需要能耗预测组件许可 | +| 设备数据/能耗分类分析 | ✔️ | ✔️ | | +| 设备数据/能耗分项分析 | ✔️ | ✔️ | | +| 设备数据/成本分析 | ✔️ | ✔️ | | +| 设备数据/产出分析 | ✔️ | ✔️ | | +| 设备数据/收入分析 | ✔️ | ✔️ | | +| 设备数据/效率分析 | ✔️ | ✔️ | | +| 设备数据/负荷分析 | ✔️ | ✔️ | | +| 设备数据/统计分析 | ✔️ | ✔️ | | +| 设备数据/节能分析 | ❌ | ✔️ | 需要能耗预测组件许可 | +| 设备数据/设备台账 | ✔️ | ✔️ | | +| 租户数据/能耗分类分析 | ✔️ | ✔️ | | +| 租户数据/能耗分项分析 | ✔️ | ✔️ | | +| 租户数据/成本分析 | ✔️ | ✔️ | | +| 租户数据/负荷分析 | ✔️ | ✔️ | | +| 租户数据/统计分析 | ✔️ | ✔️ | | +| 租户数据/节能分析 | ❌ | ✔️ | 需要能耗预测组件许可 | +| 租户数据/租户账单 | ✔️ | ✔️ | | +| 门店数据/能耗分类分析 | ✔️ | ✔️ | | +| 门店数据/能耗分项分析 | ✔️ | ✔️ | | +| 门店数据/成本分析 | ✔️ | ✔️ | | +| 门店数据/负荷分析 | ✔️ | ✔️ | | +| 门店数据/统计分析 | ✔️ | ✔️ | | +| 门店数据/节能分析 | ❌ | ✔️ | 需要能耗预测组件许可 | +| 车间数据/能耗分类分析 | ✔️ | ✔️ | | +| 车间数据/能耗分项分析 | ✔️ | ✔️ | | +| 车间数据/成本分析 | ✔️ | ✔️ | | +| 车间数据/负荷分析 | ✔️ | ✔️ | | +| 车间数据/统计分析 | ✔️ | ✔️ | | +| 车间数据/节能分析 | ❌ | ✔️ | 需要能耗预测组件许可 | +| 组合设备数据/成本分析 | ✔️ | ✔️ | | +| 组合设备数据/产出分析 | ✔️ | ✔️ | | +| 组合设备数据/收入分析 | ✔️ | ✔️ | | +| 组合设备数据/效率分析 | ✔️ | ✔️ | | +| 组合设备数据/负荷分析 | ✔️ | ✔️ | | +| 组合设备数据/统计分析 | ✔️ | ✔️ | | +| 组合设备数据/节能分析 | ❌ | ✔️ | 需要能耗预测组件许可 | +| 能流图分析 | ✔️ | ✔️ | | +| 配电系统分析 | ✔️ | ✔️ | | +| REST API | ✔️ | ✔️ | | +| Web UI | ✔️ | ✔️ | | +| Admin UI | ✔️ | ✔️ | | +| MQTT 协议订阅数据 | ❌ | ✔️ | 需要标准组件许可 | +| Modbus RTU 协议 | ❌ | ✔️ | 需要标准组件许可 | +| OPC UA 协议 | ❌ | ✔️ | 需要标准组件许可 | +| OPC DA 协议 | ❌ | ✔️ | 需要标准组件许可 | +| Siemens S7 协议 | ❌ | ✔️ | 需要标准组件许可 | +| IEC 104 协议 | ❌ | ✔️ | 需要标准组件许可 | +| Johnson Controls Metasys API | ✔️ | ✔️ | 需要标准组件许可 | +| Honeywell EBI | ✔️ | ✔️ | | +| SIEMENS Desigo CC | ❌ | ✔️ | 需要标准组件许可 | +| QWeather API | ❌ | ✔️ | 需要标准组件许可 | +| FDD 能效故障诊断系统 | ❌ | ✔️ | 需要标准组件许可或定制开发 | +| 高级报表系统 | ❌ | ✔️ | 需要标准组件许可或定制开发 | +| 组态图形绘制工具 | ❌ | ✔️ | 需要标准组件许可 | +| 设备远程控制 | ❌ | ✔️ | 需要标准组件许可或定制开发 | +| BACnet Server | ❌ | ✔️ | 需要标准组件许可 | +| Modbus TCP Server(Slave) | ❌ | ✔️ | 需要标准组件许可 | +| OPC UA Server | ❌ | ✔️ | 需要标准组件许可 | +| iOS APP | ❌ | ✔️ | 需要标准组件许可或定制开发 | +| Android APP | ❌ | ✔️ | 需要标准组件许可或定制开发 | +| 微信小程序 | ❌ | ✔️ | 需要标准组件许可或定制开发 | +| 支付宝小程序 | ❌ | ✔️ | 需要标准组件许可或定制开发 | +| 工控机硬件网关(数据采集和远程控制) | ❌ | ✔️ | MyEMS认证工控机硬件 | +| LoRa无线数传电台模块(数据采集和远程控制)| ❌ | ✔️ | MyEMS认证LoRa硬件设备 | +| 重点用能单位能耗在线监测系统上传省级平台通信协议| ❌ | ✔️ | 需要标准组件许可或定制开发 | +| 第三方系统集成服务 | ❌ | ✔️ | 定制开发 | +| 线上软件使用培训 | ✔️ | ✔️ | 免费 | +| 线下软件使用培训 | ❌ | ✔️ | | +| 在线社区技术支持 | ✔️ | ✔️ | 免费 | +| 邮件技术支持 | ✔️ | ✔️ | 免费 | +| 电话技术支持服务 | ❌ | ✔️ | | +| 微信技术支持服务 | ❌ | ✔️ | | +| 远程桌面技术支持服务 | ❌ | ✔️ | | +| 投标技术支持服务 | ❌ | ✔️ | | +| 二次开发技术支持服务 | ❌ | ✔️ | | +| 现场技术支持服务 | ❌ | ✔️ | | ## MyEMS截图 ![MyEMS Space EnergyCategory1](/docs/images/myems-space-energycategory1.gif) diff --git a/README_DE.md b/README_DE.md index b5509178..de0d491a 100644 --- a/README_DE.md +++ b/README_DE.md @@ -17,7 +17,11 @@ MyEMS ist ein branchenführendes Open-Source-Energiemanagementsystem, das auf Cl MyEMS wird von einem erfahrenen Entwicklungsteam entwickelt und gewartet, und der Quellcode des Systems wird unter MIT-Lizenz veröffentlicht. ## MyEMS Architektur -![MyEMS Architecture](/docs/images/architecture.png) + +![MyEMS Architecture Function View](/docs/images/architecture-function-view.png) + +![MyEMS Architecture Site View](/docs/images/architecture-site-view.png) + ## MyEMS Komponenten (GCommunity Edition) @@ -66,125 +70,131 @@ Dieses Projekt besteht aus folgenden Komponenten: ## Editionen vergleichen -| Eigenschaften |Community Edition (MyEMS) |Enterprise Edition (AlbertEOS)| -| :--- | :----: | :----: | -| Open Source | ✔️ | ❌ | -| Pricing | Free | Pay for Projects | -| Change Name and Logo | ✔️ | ✔️ | -| Modbus TCP | ✔️ | ✔️ | -| BACnet/IP | ✔️ | ✔️ | -| MQTT Publisher | ✔️ | ✔️ | -| Data Points Number | Unlimited |Unlimited | -| Meters Number | Unlimited |Unlimited | -| Equipments Number | Unlimited |Unlimited | -| Spaces Number | Unlimited |Unlimited | -| Docker | ✔️ | ✔️ | -| Kubernetes | ✔️ | ✔️ | -| MySQL | ✔️ | ✔️ | -| MariaDB | ✔️ | ✔️ | -| SingleStore | ✔️ | ✔️ | -| AWS Cloud | ✔️ | ✔️ | -| AZure Cloud | ✔️ | ✔️ | -| Alibaba Cloud | ✔️ | ✔️ | -| Private Cloud | ✔️ | ✔️ | -| Data Comparison(Year-on-Year、Month-on-Month、Any-on-Any) | ✔️ | ✔️ | -| Export result to Excel | ✔️ | ✔️ | -| Space/Energy Category Data | ✔️ | ✔️ | -| Space/Energy Item Data | ✔️ | ✔️ | -| Space/Cost Data | ✔️ | ✔️ | -| Space/Output Data | ✔️ | ✔️ | -| Space/Income Data | ✔️ | ✔️ | -| Space/Efficiency Data | ✔️ | ✔️ | -| Space/Load Data | ✔️ | ✔️ | -| Space/Statistics | ✔️ | ✔️ | -| Space/Saving Data | ❌ | ✔️ | -| Equipment/Energy Category Data | ✔️ | ✔️ | -| Equipment/Energy Item Data | ✔️ | ✔️ | -| Equipment/Cost Data | ✔️ | ✔️ | -| Equipment/Output Data | ✔️ | ✔️ | -| Equipment/Income Data | ✔️ | ✔️ | -| Equipment/Efficiency Data | ✔️ | ✔️ | -| Equipment/Load Data | ✔️ | ✔️ | -| Equipment/Statistics | ✔️ | ✔️ | -| Equipment/Saving Data | ❌ | ✔️ | -| Equipment/Equipment Tracking | ✔️ | ✔️ | -| Meter/Energy Data | ✔️ | ✔️ | -| Meter/Cost Data | ✔️ | ✔️ | -| Meter/Trend Data | ✔️ | ✔️ | -| Meter/Realtime Data | ✔️ | ✔️ | -| Meter/Master Meter Submeters Balance | ✔️ | ✔️ | -| Meter/Offline Meter Energy Data | ✔️ | ✔️ | -| Meter/Offline Meter Cost Data | ✔️ | ✔️ | -| Meter/Virtual Meter Energy Data | ✔️ | ✔️ | -| Meter/Virtual Meter Cost Data | ✔️ | ✔️ | -| Meter/Meter Tracking | ✔️ | ✔️ | -| Tenant/Energy Category Data | ✔️ | ✔️ | -| Tenant/Energy Item Data | ✔️ | ✔️ | -| Tenant/Cost Data | ✔️ | ✔️ | -| Tenant/Load Data | ✔️ | ✔️ | -| Tenant/Statistics | ✔️ | ✔️ | -| Tenant/Saving Data | ❌ | ✔️ | -| Tenant/Tenant Bill | ✔️ | ✔️ | -| Store/Energy Category Data | ✔️ | ✔️ | -| Store/Energy Item Data | ✔️ | ✔️ | -| Store/Cost Data | ✔️ | ✔️ | -| Store/Load Data | ✔️ | ✔️ | -| Store/Statistics | ✔️ | ✔️ | -| Store/Saving Data | ❌ | ✔️ | -| Shopfloor/Energy Category Data | ✔️ | ✔️ | -| Shopfloor/Energy Item Data | ✔️ | ✔️ | -| Shopfloor/Cost Data | ✔️ | ✔️ | -| Shopfloor/Load Data | ✔️ | ✔️ | -| Shopfloor/Statistics | ✔️ | ✔️ | -| Shopfloor/Saving Data | ❌ | ✔️ | -| Combined Equipment/Energy Category Data | ✔️ | ✔️ | -| Combined Equipment/Energy Item Data | ✔️ | ✔️ | -| Combined Equipment/Cost Data | ✔️ | ✔️ | -| Combined Equipment/Output Data | ✔️ | ✔️ | -| Combined Equipment/Income Data | ✔️ | ✔️ | -| Combined Equipment/Efficiency Data | ✔️ | ✔️ | -| Combined Equipment/Load Data | ✔️ | ✔️ | -| Combined Equipment/Statistics | ✔️ | ✔️ | -| Combined Equipment/Saving Data | ❌ | ✔️ | -| Energy Dashboard | ✔️ | ✔️ | -| Energy Flow Diagram | ✔️ | ✔️ | -| Distribution System | ✔️ | ✔️ | -| REST API | ✔️ | ✔️ | -| Web UI | ✔️ | ✔️ | -| Admin UI | ✔️ | ✔️ | -| MQTT Subscriber | ❌ | ✔️ | -| Modbus RTU | ❌ | ✔️ | -| OPC UA | ❌ | ✔️ | -| OPC DA | ❌ | ✔️ | -| Siemens S7 | ❌ | ✔️ | -| IEC 104 | ❌ | ✔️ | -| Johnson Controls Metasys | ✔️ | ✔️ | -| Honeywell EBI | ✔️ | ✔️ | -| SIEMENS Desigo CC | ❌ | ✔️ | -| QWeather API | ❌ | ✔️ | -| FDD Rule Engine | ❌ | ✔️ | -| Advanced Reporting Engine | ❌ | ✔️ | -| 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 Service | ❌ | ✔️ | -| Online Community Customer Support| ✔️ | ✔️ | -| Email Customer Support | ✔️ | ✔️ | -| Telephone Customer Support | ❌ | ✔️ | -| WeChat Customer Support | ❌ | ✔️ | -| Remote Desktop Customer Support | ❌ | ✔️ | -| Onsite Customer Support | ❌ | ✔️ | -| Bidding Support Service | ❌ | ✔️ | -| Customize Support Service | ❌ | ✔️ | +| Eigenschaften | Gemeinschaftsausgabe | Enterprise Edition | Erläuterung | +| :--- | :----: | :----: | :----: | +| Open Source | ✔️ | ❌ | | +| Pricing | Free | Pay for Projects | | +| Change Name and Logo | ✔️ | ✔️ | | +| Modbus TCP | ✔️ | ✔️ | | +| BACnet/IP | ✔️ | ✔️ | | +| MQTT Publisher | ✔️ | ✔️ | | +| Data Points Number | Unbegrenzt | Unbegrenzt | Nur durch die Hardwareleistung begrenzt | +| Meters Number | Unbegrenzt | Unbegrenzt | Nur durch die Hardwareleistung begrenzt | +| Spaces Number | Unbegrenzt | Unbegrenzt | Nur durch die Hardwareleistung begrenzt | +| Equipments Number | Unbegrenzt | Unbegrenzt | Nur durch die Hardwareleistung begrenzt | +| Tenants Number | Unbegrenzt | Unbegrenzt | Nur durch die Hardwareleistung begrenzt | +| Stores Number | Unbegrenzt | Unbegrenzt | Nur durch die Hardwareleistung begrenzt | +| Shopfloors Number | Unbegrenzt | Unbegrenzt | Nur durch die Hardwareleistung begrenzt | +| Combined Equipments Number | Unbegrenzt | Unbegrenzt | Nur durch die Hardwareleistung begrenzt | +| Docker | ✔️ | ✔️ | | +| Kubernetes | ✔️ | ✔️ | | +| MySQL | ✔️ | ✔️ | | +| MariaDB | ✔️ | ✔️ | | +| SingleStore | ✔️ | ✔️ | | +| AWS Cloud | ✔️ | ✔️ | | +| AZure Cloud | ✔️ | ✔️ | | +| Alibaba Cloud | ✔️ | ✔️ | | +| Private Cloud | ✔️ | ✔️ | | +| Data Comparison | ✔️ | ✔️ | Jahr für Jahr, Monat für Monat, Freier Vergleich, Kein Vergleich | +| Excel Exporter | ✔️ | ✔️ | Tabellen, Liniendiagramme, Säulendiagramme, Kreisdiagramme | +| Meter/Energy Data | ✔️ | ✔️ | | +| Meter/Cost Data | ✔️ | ✔️ | | +| Meter/Trend Data | ✔️ | ✔️ | | +| Meter/Realtime Data | ✔️ | ✔️ | | +| Meter/Master Meter Submeters Balance | ✔️ | ✔️ | | +| Meter/Offline Meter Energy Data | ✔️ | ✔️ | | +| Meter/Offline Meter Cost Data | ✔️ | ✔️ | | +| Meter/Virtual Meter Energy Data | ✔️ | ✔️ | | +| Meter/Virtual Meter Cost Data | ✔️ | ✔️ | | +| Meter/Meter Tracking | ✔️ | ✔️ | | +| Space/Energy Category Data | ✔️ | ✔️ | | +| Space/Energy Item Data | ✔️ | ✔️ | | +| Space/Cost Data | ✔️ | ✔️ | | +| Space/Output Data | ✔️ | ✔️ | | +| Space/Income Data | ✔️ | ✔️ | | +| Space/Efficiency Data | ✔️ | ✔️ | | +| Space/Load Data | ✔️ | ✔️ | | +| Space/Statistics | ✔️ | ✔️ | | +| Space/Saving Data | ❌ | ✔️ | Erfordert eine Komponente zur Vorhersage des Energieverbrauchs | +| Equipment/Energy Category Data | ✔️ | ✔️ | | +| Equipment/Energy Item Data | ✔️ | ✔️ | | +| Equipment/Cost Data | ✔️ | ✔️ | | +| Equipment/Output Data | ✔️ | ✔️ | | +| Equipment/Income Data | ✔️ | ✔️ | | +| Equipment/Efficiency Data | ✔️ | ✔️ | | +| Equipment/Load Data | ✔️ | ✔️ | | +| Equipment/Statistics | ✔️ | ✔️ | | +| Equipment/Saving Data | ❌ | ✔️ | Erfordert eine Komponente zur Vorhersage des Energieverbrauchs | +| Equipment/Equipment Tracking | ✔️ | ✔️ | | +| Tenant/Energy Category Data | ✔️ | ✔️ | | +| Tenant/Energy Item Data | ✔️ | ✔️ | | +| Tenant/Cost Data | ✔️ | ✔️ | | +| Tenant/Load Data | ✔️ | ✔️ | | +| Tenant/Statistics | ✔️ | ✔️ | | +| Tenant/Saving Data | ❌ | ✔️ | Erfordert eine Komponente zur Vorhersage des Energieverbrauchs | +| Tenant/Tenant Bill | ✔️ | ✔️ | | +| Store/Energy Category Data | ✔️ | ✔️ | | +| Store/Energy Item Data | ✔️ | ✔️ | | +| Store/Cost Data | ✔️ | ✔️ | | +| Store/Load Data | ✔️ | ✔️ | | +| Store/Statistics | ✔️ | ✔️ | | +| Store/Saving Data | ❌ | ✔️ | | +| Shopfloor/Energy Category Data | ✔️ | ✔️ | | +| Shopfloor/Energy Item Data | ✔️ | ✔️ | | +| Shopfloor/Cost Data | ✔️ | ✔️ | | +| Shopfloor/Load Data | ✔️ | ✔️ | | +| Shopfloor/Statistics | ✔️ | ✔️ | | +| Shopfloor/Saving Data | ❌ | ✔️ | Erfordert eine Komponente zur Vorhersage des Energieverbrauchs | +| Combined Equipment/Energy Category Data | ✔️ | ✔️ | | +| Combined Equipment/Energy Item Data | ✔️ | ✔️ | | +| Combined Equipment/Cost Data | ✔️ | ✔️ | | +| Combined Equipment/Output Data | ✔️ | ✔️ | | +| Combined Equipment/Income Data | ✔️ | ✔️ | | +| Combined Equipment/Efficiency Data | ✔️ | ✔️ | | +| Combined Equipment/Load Data | ✔️ | ✔️ | | +| Combined Equipment/Statistics | ✔️ | ✔️ | | +| Combined Equipment/Saving Data | ❌ | ✔️ | Erfordert eine Komponente zur Vorhersage des Energieverbrauchs | +| Energy Dashboard | ✔️ | ✔️ | | +| Energy Flow Diagram | ✔️ | ✔️ | | +| Distribution System | ✔️ | ✔️ | | +| REST API | ✔️ | ✔️ | | +| Web UI | ✔️ | ✔️ | | +| Admin UI | ✔️ | ✔️ | | +| MQTT Subscriber | ❌ | ✔️ | Erfordert eine Standardkomponentenlizenz | +| Modbus RTU | ❌ | ✔️ | Erfordert eine Standardkomponentenlizenz | +| OPC UA | ❌ | ✔️ | Erfordert eine Standardkomponentenlizenz | +| OPC DA | ❌ | ✔️ | Erfordert eine Standardkomponentenlizenz | +| Siemens S7 | ❌ | ✔️ | Erfordert eine Standardkomponentenlizenz | +| IEC 104 | ❌ | ✔️ | Erfordert eine Standardkomponentenlizenz | +| Johnson Controls Metasys API | ❌ | ✔️ | Erfordert eine Standardkomponentenlizenz | +| Honeywell EBI | ✔️ | ✔️ | | +| SIEMENS Desigo CC | ❌ | ✔️ | Erfordert eine Standardkomponentenlizenz | +| QWeather API | ❌ | ✔️ | Erfordert eine Standardkomponentenlizenz | +| FDD Rule Engine | ❌ | ✔️ | Erfordert eine Standardkomponentenlizenz | +| Advanced Reporting Engine | ❌ | ✔️ | Erfordert eine Standardkomponentenlizenz oder eine benutzerdefinierte Entwicklung | +| Graphics Drawing Tool | ❌ | ✔️ | Erfordert eine Standardkomponentenlizenz | +| Equipments Remote Control | ❌ | ✔️ | Erfordert eine Standardkomponentenlizenz oder eine benutzerdefinierte Entwicklung | +| BACnet Server | ❌ | ✔️ | Erfordert eine Standardkomponentenlizenz | +| Modbus TCP Server(Slave) | ❌ | ✔️ | Erfordert eine Standardkomponentenlizenz | +| OPC UA Server | ❌ | ✔️ | Erfordert eine Standardkomponentenlizenz | +| iOS APP | ❌ | ✔️ | Erfordert eine Standardkomponentenlizenz oder eine benutzerdefinierte Entwicklung | +| Android APP | ❌ | ✔️ | Erfordert eine Standardkomponentenlizenz oder eine benutzerdefinierte Entwicklung | +| WeChat Mini Program | ❌ | ✔️ | Erfordert eine Standardkomponentenlizenz oder eine benutzerdefinierte Entwicklung | +| Alipay Mini Program | ❌ | ✔️ | Erfordert eine Standardkomponentenlizenz oder eine benutzerdefinierte Entwicklung | +| IPC Hardware Gateway (Data Acquisition and Remote Control)| ❌| ✔️ | MyEMS-zertifizierte industrielle Computerhardware | +| LoRa Radio Module (Data Acquisition and Remote Control) | ❌| ✔️ | MyEMS-zertifiziertes LoRa-Hardwaregerät | +| Protocol for Uploading to Provincial Platform of On-line monitoring system for Key Energy-Consuming Unit | ❌ | ✔️ | | +| 3rd Party Systems Integration Service | ❌ | ✔️ | Kundenspezifische Entwicklung | +| Online software training | ✔️ | ✔️ | Kostenlos | +| Face to face software training | ❌ | ✔️ | | +| Online Community Customer Support| ✔️ | ✔️ | Kostenlos | +| Email Customer Support | ✔️ | ✔️ | Kostenlos | +| Telephone Customer Support | ❌ | ✔️ | | +| WeChat Customer Support | ❌ | ✔️ | | +| Remote Desktop Customer Support | ❌ | ✔️ | | +| Onsite Customer Support | ❌ | ✔️ | | +| Bidding Support Service | ❌ | ✔️ | | +| Customize Support Service | ❌ | ✔️ | | ## MyEMS Bildschirmfoto diff --git a/README_EN.md b/README_EN.md index 1f43377d..e5afb6ca 100644 --- a/README_EN.md +++ b/README_EN.md @@ -17,7 +17,11 @@ MyEMS is being developed and maintained by an experienced development team, and the system's source code is published under MIT license. ## MyEMS Architecture -![MyEMS Architecture](/docs/images/architecture.png) + +![MyEMS Architecture Function View](/docs/images/architecture-function-view.png) + +![MyEMS Architecture Site View](/docs/images/architecture-site-view.png) + ## MyEMS Components (Community Edition) @@ -66,125 +70,131 @@ This project is compose of following components: ## Compare Editions -| Features |Communit Edition (MyEMS) |Enterprise Edition (AlbertEOS)| -| :--- | :----: | :----: | -| Open Source | ✔️ | ❌ | -| Pricing | Free | Pay for Projects | -| Change Name and Logo | ✔️ | ✔️ | -| Modbus TCP | ✔️ | ✔️ | -| BACnet/IP | ✔️ | ✔️ | -| MQTT Publisher | ✔️ | ✔️ | -| Data Points Number | Unlimited |Unlimited | -| Meters Number | Unlimited |Unlimited | -| Equipments Number | Unlimited |Unlimited | -| Spaces Number | Unlimited |Unlimited | -| Docker | ✔️ | ✔️ | -| Kubernetes | ✔️ | ✔️ | -| MySQL | ✔️ | ✔️ | -| MariaDB | ✔️ | ✔️ | -| SingleStore | ✔️ | ✔️ | -| AWS Cloud | ✔️ | ✔️ | -| AZure Cloud | ✔️ | ✔️ | -| Alibaba Cloud | ✔️ | ✔️ | -| Private Cloud | ✔️ | ✔️ | -| Data Comparison(Year-on-Year、Month-on-Month、Any-on-Any)| ✔️ | ✔️ | -| Export result to Excel | ✔️ | ✔️ | -| Space/Energy Category Data | ✔️ | ✔️ | -| Space/Energy Item Data | ✔️ | ✔️ | -| Space/Cost Data | ✔️ | ✔️ | -| Space/Output Data | ✔️ | ✔️ | -| Space/Income Data | ✔️ | ✔️ | -| Space/Efficiency Data | ✔️ | ✔️ | -| Space/Load Data | ✔️ | ✔️ | -| Space/Statistics | ✔️ | ✔️ | -| Space/Saving Data | ❌ | ✔️ | -| Equipment/Energy Category Data | ✔️ | ✔️ | -| Equipment/Energy Item Data | ✔️ | ✔️ | -| Equipment/Cost Data | ✔️ | ✔️ | -| Equipment/Output Data | ✔️ | ✔️ | -| Equipment/Income Data | ✔️ | ✔️ | -| Equipment/Efficiency Data | ✔️ | ✔️ | -| Equipment/Load Data | ✔️ | ✔️ | -| Equipment/Statistics | ✔️ | ✔️ | -| Equipment/Saving Data | ❌ | ✔️ | -| Equipment/Equipment Tracking | ✔️ | ✔️ | -| Meter/Energy Data | ✔️ | ✔️ | -| Meter/Cost Data | ✔️ | ✔️ | -| Meter/Trend Data | ✔️ | ✔️ | -| Meter/Realtime Data | ✔️ | ✔️ | -| Meter/Master Meter Submeters Balance | ✔️ | ✔️ | -| Meter/Offline Meter Energy Data | ✔️ | ✔️ | -| Meter/Offline Meter Cost Data | ✔️ | ✔️ | -| Meter/Virtual Meter Energy Data | ✔️ | ✔️ | -| Meter/Virtual Meter Cost Data | ✔️ | ✔️ | -| Meter/Meter Tracking | ✔️ | ✔️ | -| Tenant/Energy Category Data | ✔️ | ✔️ | -| Tenant/Energy Item Data | ✔️ | ✔️ | -| Tenant/Cost Data | ✔️ | ✔️ | -| Tenant/Load Data | ✔️ | ✔️ | -| Tenant/Statistics | ✔️ | ✔️ | -| Tenant/Saving Data | ❌ | ✔️ | -| Tenant/Tenant Bill | ✔️ | ✔️ | -| Store/Energy Category Data | ✔️ | ✔️ | -| Store/Energy Item Data | ✔️ | ✔️ | -| Store/Cost Data | ✔️ | ✔️ | -| Store/Load Data | ✔️ | ✔️ | -| Store/Statistics | ✔️ | ✔️ | -| Store/Saving Data | ❌ | ✔️ | -| Shopfloor/Energy Category Data | ✔️ | ✔️ | -| Shopfloor/Energy Item Data | ✔️ | ✔️ | -| Shopfloor/Cost Data | ✔️ | ✔️ | -| Shopfloor/Load Data | ✔️ | ✔️ | -| Shopfloor/Statistics | ✔️ | ✔️ | -| Shopfloor/Saving Data | ❌ | ✔️ | -| Combined Equipment/Energy Category Data | ✔️ | ✔️ | -| Combined Equipment/Energy Item Data | ✔️ | ✔️ | -| Combined Equipment/Cost Data | ✔️ | ✔️ | -| Combined Equipment/Output Data | ✔️ | ✔️ | -| Combined Equipment/Income Data | ✔️ | ✔️ | -| Combined Equipment/Efficiency Data | ✔️ | ✔️ | -| Combined Equipment/Load Data | ✔️ | ✔️ | -| Combined Equipment/Statistics | ✔️ | ✔️ | -| Combined Equipment/Saving Data | ❌ | ✔️ | -| Energy Dashboard | ✔️ | ✔️ | -| Energy Flow Diagram | ✔️ | ✔️ | -| Distribution System | ✔️ | ✔️ | -| REST API | ✔️ | ✔️ | -| Web UI | ✔️ | ✔️ | -| Admin UI | ✔️ | ✔️ | -| MQTT Subscriber | ❌ | ✔️ | -| Modbus RTU | ❌ | ✔️ | -| OPC UA | ❌ | ✔️ | -| OPC DA | ❌ | ✔️ | -| Siemens S7 | ❌ | ✔️ | -| IEC 104 | ❌ | ✔️ | -| Johnson Controls Metasys | ✔️ | ✔️ | -| Honeywell EBI | ✔️ | ✔️ | -| SIEMENS Desigo CC | ❌ | ✔️ | -| QWeather API | ❌ | ✔️ | -| FDD Rule Engine | ❌ | ✔️ | -| Advanced Reporting Engine | ❌ | ✔️ | -| 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 Service | ❌ | ✔️ | -| Online Community Customer Support| ✔️ | ✔️ | -| Email Customer Support | ✔️ | ✔️ | -| Telephone Customer Support | ❌ | ✔️ | -| WeChat Customer Support | ❌ | ✔️ | -| Remote Desktop Customer Support | ❌ | ✔️ | -| Onsite Customer Support | ❌ | ✔️ | -| Bidding Support Service | ❌ | ✔️ | -| Customize Support Service | ❌ | ✔️ | +| Features | Community Edition | Enterprise Edition | Explanation | +| :--- | :----: | :----: | :----: | +| Open Source | ✔️ | ❌ | | +| Pricing | Free | Pay for Projects | | +| Change Name and Logo | ✔️ | ✔️ | | +| Modbus TCP | ✔️ | ✔️ | | +| BACnet/IP | ✔️ | ✔️ | | +| MQTT Publisher | ✔️ | ✔️ | | +| Data Points Number | Unlimited | Unlimited | Limited only by hardware performance | +| Meters Number | Unlimited | Unlimited | Limited only by hardware performance | +| Spaces Number | Unlimited | Unlimited | Limited only by hardware performance | +| Equipments Number | Unlimited | Unlimited | Limited only by hardware performance | +| Tenants Number | Unlimited | Unlimited | Limited only by hardware performance | +| Stores Number | Unlimited | Unlimited | Limited only by hardware performance | +| Shopfloors Number | Unlimited | Unlimited | Limited only by hardware performance | +| Combined Equipments Number | Unlimited | Unlimited | Limited only by hardware performance | +| Docker | ✔️ | ✔️ | | +| Kubernetes | ✔️ | ✔️ | | +| MySQL | ✔️ | ✔️ | | +| MariaDB | ✔️ | ✔️ | | +| SingleStore | ✔️ | ✔️ | | +| AWS Cloud | ✔️ | ✔️ | | +| AZure Cloud | ✔️ | ✔️ | | +| Alibaba Cloud | ✔️ | ✔️ | | +| Private Cloud | ✔️ | ✔️ | | +| Data Comparison | ✔️ | ✔️ | Year-on-Year, Month-on-Month, Free Comparison, None Comparison | +| Excel Exporter | ✔️ | ✔️ | Tables, Line Charts, Column Charts, Pie Charts | +| Meter/Energy Data | ✔️ | ✔️ | | +| Meter/Cost Data | ✔️ | ✔️ | | +| Meter/Trend Data | ✔️ | ✔️ | | +| Meter/Realtime Data | ✔️ | ✔️ | | +| Meter/Master Meter Submeters Balance | ✔️ | ✔️ | | +| Meter/Offline Meter Energy Data | ✔️ | ✔️ | | +| Meter/Offline Meter Cost Data | ✔️ | ✔️ | | +| Meter/Virtual Meter Energy Data | ✔️ | ✔️ | | +| Meter/Virtual Meter Cost Data | ✔️ | ✔️ | | +| Meter/Meter Tracking | ✔️ | ✔️ | | +| Space/Energy Category Data | ✔️ | ✔️ | | +| Space/Energy Item Data | ✔️ | ✔️ | | +| Space/Cost Data | ✔️ | ✔️ | | +| Space/Output Data | ✔️ | ✔️ | | +| Space/Income Data | ✔️ | ✔️ | | +| Space/Efficiency Data | ✔️ | ✔️ | | +| Space/Load Data | ✔️ | ✔️ | | +| Space/Statistics | ✔️ | ✔️ | | +| Space/Saving Data | ❌ | ✔️ | Requires Energy consumption prediction component | +| Equipment/Energy Category Data | ✔️ | ✔️ | | +| Equipment/Energy Item Data | ✔️ | ✔️ | | +| Equipment/Cost Data | ✔️ | ✔️ | | +| Equipment/Output Data | ✔️ | ✔️ | | +| Equipment/Income Data | ✔️ | ✔️ | | +| Equipment/Efficiency Data | ✔️ | ✔️ | | +| Equipment/Load Data | ✔️ | ✔️ | | +| Equipment/Statistics | ✔️ | ✔️ | | +| Equipment/Saving Data | ❌ | ✔️ | Requires Energy consumption prediction component | +| Equipment/Equipment Tracking | ✔️ | ✔️ | | +| Tenant/Energy Category Data | ✔️ | ✔️ | | +| Tenant/Energy Item Data | ✔️ | ✔️ | | +| Tenant/Cost Data | ✔️ | ✔️ | | +| Tenant/Load Data | ✔️ | ✔️ | | +| Tenant/Statistics | ✔️ | ✔️ | | +| Tenant/Saving Data | ❌ | ✔️ | Requires Energy consumption prediction component | +| Tenant/Tenant Bill | ✔️ | ✔️ | | +| Store/Energy Category Data | ✔️ | ✔️ | | +| Store/Energy Item Data | ✔️ | ✔️ | | +| Store/Cost Data | ✔️ | ✔️ | | +| Store/Load Data | ✔️ | ✔️ | | +| Store/Statistics | ✔️ | ✔️ | | +| Store/Saving Data | ❌ | ✔️ | Requires Energy consumption prediction component | +| Shopfloor/Energy Category Data | ✔️ | ✔️ | | +| Shopfloor/Energy Item Data | ✔️ | ✔️ | | +| Shopfloor/Cost Data | ✔️ | ✔️ | | +| Shopfloor/Load Data | ✔️ | ✔️ | | +| Shopfloor/Statistics | ✔️ | ✔️ | | +| Shopfloor/Saving Data | ❌ | ✔️ | Requires Energy consumption prediction component | +| Combined Equipment/Energy Category Data | ✔️ | ✔️ | | +| Combined Equipment/Energy Item Data | ✔️ | ✔️ | | +| Combined Equipment/Cost Data | ✔️ | ✔️ | | +| Combined Equipment/Output Data | ✔️ | ✔️ | | +| Combined Equipment/Income Data | ✔️ | ✔️ | | +| Combined Equipment/Efficiency Data | ✔️ | ✔️ | | +| Combined Equipment/Load Data | ✔️ | ✔️ | | +| Combined Equipment/Statistics | ✔️ | ✔️ | | +| Combined Equipment/Saving Data | ❌ | ✔️ | Requires Energy consumption prediction component | +| Energy Dashboard | ✔️ | ✔️ | | +| Energy Flow Diagram | ✔️ | ✔️ | | +| Distribution System | ✔️ | ✔️ | | +| REST API | ✔️ | ✔️ | | +| Web UI | ✔️ | ✔️ | | +| Admin UI | ✔️ | ✔️ | | +| MQTT Subscriber | ❌ | ✔️ | Requires standard component license | +| Modbus RTU | ❌ | ✔️ | Requires standard component license | +| OPC UA | ❌ | ✔️ | Requires standard component license | +| OPC DA | ❌ | ✔️ | Requires standard component license | +| Siemens S7 | ❌ | ✔️ | Requires standard component license | +| IEC 104 | ❌ | ✔️ | Requires standard component license | +| Johnson Controls Metasys API | ❌ | ✔️ | Requires standard component license | +| Honeywell EBI | ✔️ | ✔️ | | +| SIEMENS Desigo CC | ❌ | ✔️ | Requires standard component license | +| QWeather API | ❌ | ✔️ | Requires standard component license | +| FDD Rule Engine | ❌ | ✔️ | Requires standard component license or custom development | +| Advanced Reporting Engine | ❌ | ✔️ | Requires standard component license or custom development | +| Graphics Drawing Tool | ❌ | ✔️ | | +| Equipments Remote Control | ❌ | ✔️ | Requires standard component license or custom development | +| BACnet Server | ❌ | ✔️ | | +| Modbus TCP Server(Slave) | ❌ | ✔️ | | +| OPC UA Server | ❌ | ✔️ | | +| iOS APP | ❌ | ✔️ | Requires standard component license or custom development | +| Android APP | ❌ | ✔️ | Requires standard component license or custom development | +| WeChat Mini Program | ❌ | ✔️ | Requires standard component license or custom development | +| Alipay Mini Program | ❌ | ✔️ | Requires standard component license or custom development | +| IPC Hardware Gateway (Data Acquisition and Remote Control)| ❌ | ✔️ | MyEMS certified industrial computer hardware | +| LoRa Radio Module (Data Acquisition and Remote Control)| ❌ | ✔️ | MyEMS certified LoRa hardware device | +| Protocol for Uploading to Provincial Platform of On-line monitoring system for Key Energy-Consuming Unit | ❌ | ✔️ | Requires standard component license or custom development | +| 3rd Party Systems Integration Service | ❌ | ✔️ | Custom development | +| Online software training | ✔️ | ✔️ | Free | +| Face to face software training | ❌ | ✔️ | | +| Online Community Customer Support| ✔️ | ✔️ | Free | +| Email Customer Support | ✔️ | ✔️ | Free | +| Telephone Customer Support | ❌ | ✔️ | | +| WeChat Customer Support | ❌ | ✔️ | | +| Remote Desktop Customer Support | ❌ | ✔️ | | +| Onsite Customer Support | ❌ | ✔️ | | +| Bidding Support Service | ❌ | ✔️ | | +| Customize Support Service | ❌ | ✔️ | | ## MyEMS Screenshot ![MyEMS Space EnergyCategory1](/docs/images/myems-space-energycategory1.gif) diff --git a/docs/architecture.rst b/docs/architecture.rst index 2afc69d1..a3d7c378 100644 --- a/docs/architecture.rst +++ b/docs/architecture.rst @@ -1,3 +1,4 @@ Architecture ============== -.. image:: images/architecture.png +.. image:: images/architecture-site-view.png +.. image:: images/architecture-function-view.png diff --git a/docs/images/architecture-function-view.png b/docs/images/architecture-function-view.png new file mode 100644 index 00000000..a2e1ecca Binary files /dev/null and b/docs/images/architecture-function-view.png differ diff --git a/docs/images/architecture-site-view.png b/docs/images/architecture-site-view.png new file mode 100644 index 00000000..ec9d3f5b Binary files /dev/null and b/docs/images/architecture-site-view.png differ diff --git a/myems-api/excelexporters/spacecost.py b/myems-api/excelexporters/spacecost.py index 5ad658ae..cf1147a5 100644 --- a/myems-api/excelexporters/spacecost.py +++ b/myems-api/excelexporters/spacecost.py @@ -11,6 +11,7 @@ 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 #################################################################################################################### @@ -417,8 +418,9 @@ def generate_excel(report, times = reporting_period_data['timestamps'] has_detail_data_flag = True ca_len = len(report['reporting_period']['names']) - table_row = (current_row_number + 1) + ca_len * 6 - current_end_row_number = (current_row_number + 1) + ca_len * 6 + len(times[0]) + 3 + real_timestamps_len = timestamps_data_not_equal_0(report['parameters']['timestamps']) + table_row = (current_row_number + 1) + ca_len * 6 + real_timestamps_len * 7 + current_end_row_number = (current_row_number + 1) + ca_len * 6 + len(times[0]) + 3 + real_timestamps_len * 7 if "timestamps" not in reporting_period_data.keys() or \ reporting_period_data['timestamps'] is None or \ len(reporting_period_data['timestamps']) == 0: @@ -491,6 +493,7 @@ def generate_excel(report, line.dLbls.showPercent = False chart_col = 'B' chart_cell = chart_col + str(current_row_number + 1 + 6 * i) + table_start_draw_flag = current_row_number ws.add_chart(line, chart_cell) row = str(max_row + 1) @@ -645,7 +648,188 @@ def generate_excel(report, current_row_number += 5 current_row_number += 1 + ########################################## + current_sheet_parameters_row_number = table_start_draw_flag + ca_len * 6 + 1 + has_parameters_names_and_timestamps_and_values_data = True + 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 + 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) @@ -658,3 +842,28 @@ def reporting_period_values_every_day_sum(reporting_period_data, every_day_index every_day_sum += reporting_period_data['values'][i][every_day_index] return every_day_sum + + +def timestamps_data_all_equal_0(lists): + for i, value in enumerate(list(lists)): + if len(value) > 0: + return False + + return True + + +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_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/spaceenergycategory.py b/myems-api/excelexporters/spaceenergycategory.py index 9ad48e65..dd6c00f4 100644 --- a/myems-api/excelexporters/spaceenergycategory.py +++ b/myems-api/excelexporters/spaceenergycategory.py @@ -11,6 +11,8 @@ 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 @@ -512,11 +514,11 @@ def generate_excel(report, reporting_period_data = report['reporting_period'] times = reporting_period_data['timestamps'] ca_len = len(report['reporting_period']['names']) - + real_timestamps_len = timestamps_data_not_equal_0(report['parameters']['timestamps']) ws['B' + str(current_row_number)].font = title_font ws['B' + str(current_row_number)] = name + ' 详细数据' - table_start_row_number = (current_row_number + 1) + ca_len * 6 + table_start_row_number = (current_row_number + 2) + ca_len * 6 + real_timestamps_len * 7 current_row_number = table_start_row_number time = times[0] @@ -691,8 +693,214 @@ def generate_excel(report, if ca_len % 2 == 1: current_row_number += 5 current_row_number += 1 + ########################################## + current_sheet_parameters_row_number = table_start_draw_flag + ca_len * 6 + 1 + has_parameters_names_and_timestamps_and_values_data = True + 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 + 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 timestamps_data_all_equal_0(lists): + for i, value in enumerate(list(lists)): + if len(value) > 0: + return False + + return True + + +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_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/spaceenergyitem.py b/myems-api/excelexporters/spaceenergyitem.py index e1d62d29..60a2b974 100644 --- a/myems-api/excelexporters/spaceenergyitem.py +++ b/myems-api/excelexporters/spaceenergyitem.py @@ -11,6 +11,7 @@ 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 #################################################################################################################### @@ -337,7 +338,7 @@ def generate_excel(report, if has_values_data and has_timestamps_data: ca_len = len(reporting_period_data['names']) time = reporting_period_data['timestamps'][0] - + real_timestamps_len = timestamps_data_not_equal_0(report['parameters']['timestamps']) ws['B' + str(current_row_number)].font = title_font ws['B' + str(current_row_number)] = name + ' 详细数据' @@ -345,7 +346,7 @@ def generate_excel(report, chart_start_row_number = current_row_number - current_row_number += ca_len * 6 + current_row_number += ca_len * 6 + real_timestamps_len * 7 + 1 table_start_row_number = current_row_number ws.row_dimensions[current_row_number].height = 60 @@ -539,7 +540,188 @@ def generate_excel(report, current_row_number += 5 current_row_number += 1 + ########################################## + current_sheet_parameters_row_number = chart_start_row_number + 1 + has_parameters_names_and_timestamps_and_values_data = True + 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 + 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) @@ -553,3 +735,28 @@ def group_by_category(category_list): category_dict[value] = list() category_dict[value].append(i) return category_dict + + +def timestamps_data_all_equal_0(lists): + for i, value in enumerate(list(lists)): + if len(value) > 0: + return False + + return True + + +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_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/spaceincome.py b/myems-api/excelexporters/spaceincome.py index 8f850218..6506fb70 100644 --- a/myems-api/excelexporters/spaceincome.py +++ b/myems-api/excelexporters/spaceincome.py @@ -12,6 +12,7 @@ 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 #################################################################################################################### @@ -344,7 +345,8 @@ def generate_excel(report, times = reporting_period_data['timestamps'] has_detail_data_flag = True ca_len = len(report['reporting_period']['names']) - table_row = (current_row_number + 1) + ca_len * 6 + real_timestamps_len = timestamps_data_not_equal_0(report['parameters']['timestamps']) + table_row = (current_row_number + 1) + ca_len * 6 + real_timestamps_len * 7 current_end_row_number = current_row_number if "timestamps" not in reporting_period_data.keys() or \ reporting_period_data['timestamps'] is None or \ @@ -420,6 +422,7 @@ def generate_excel(report, line.dLbls.showPercent = False chart_col = 'B' chart_cell = chart_col + str(current_row_number + 1 + 6 * i) + table_start_draw_flag = current_row_number ws.add_chart(line, chart_cell) row = str(max_row + 1) @@ -480,7 +483,7 @@ def generate_excel(report, if has_child_flag: child = report['child_space'] - + current_row_number = int(row) + 1 ws['B' + str(current_row_number)].font = title_font ws['B' + str(current_row_number)] = name + ' 子空间数据' @@ -578,7 +581,187 @@ def generate_excel(report, current_row_number += 1 ############################################# + current_sheet_parameters_row_number = table_start_draw_flag + ca_len * 6 + 1 + has_parameters_names_and_timestamps_and_values_data = True + 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 + 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) @@ -591,3 +774,28 @@ def reporting_period_values_every_day_sum(reporting_period_data, every_day_index every_day_sum += reporting_period_data['values'][i][every_day_index] return every_day_sum + + +def timestamps_data_all_equal_0(lists): + for i, value in enumerate(list(lists)): + if len(value) > 0: + return False + + return True + + +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_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/spaceload.py b/myems-api/excelexporters/spaceload.py index 07233d69..d9a8ad57 100644 --- a/myems-api/excelexporters/spaceload.py +++ b/myems-api/excelexporters/spaceload.py @@ -11,6 +11,7 @@ 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 #################################################################################################################### @@ -369,13 +370,13 @@ def generate_excel(report, name, reporting_start_datetime_local, reporting_end_d ca_len = len(category) times = reporting_period_data['timestamps'] time = times[0] - + real_timestamps_len = timestamps_data_not_equal_0(report['parameters']['timestamps']) ws['B' + str(current_row_number)].font = title_font ws['B' + str(current_row_number)] = name + '详细数据' current_row_number += 1 chart_start_number = current_row_number - + current_row_number += real_timestamps_len * 7 + 1 if has_sub_averages_data_flag: current_row_number = (current_row_number + ca_len * 6) @@ -487,9 +488,214 @@ def generate_excel(report, name, reporting_start_datetime_local, reporting_end_d line.dLbls.showVal = True ws.add_chart(line, "B" + str(current_chart_row_number)) current_chart_row_number += 6 - current_chart_col_number += 1 + ########################################## + current_sheet_parameters_row_number = current_chart_row_number + 1 + has_parameters_names_and_timestamps_and_values_data = True + 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 + 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 timestamps_data_all_equal_0(lists): + for i, value in enumerate(list(lists)): + if len(value) > 0: + return False + + return True + + +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_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/spaceoutput.py b/myems-api/excelexporters/spaceoutput.py index 4aeb611e..9d13a891 100644 --- a/myems-api/excelexporters/spaceoutput.py +++ b/myems-api/excelexporters/spaceoutput.py @@ -11,6 +11,7 @@ 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 #################################################################################################################### @@ -276,7 +277,7 @@ def generate_excel(report, if has_values_data and has_timestamps_data: ca_len = len(reporting_period_data['names']) time = reporting_period_data['timestamps'][0] - + real_timestamps_len = timestamps_data_not_equal_0(report['parameters']['timestamps']) ws['B' + str(current_row_number)].font = title_font ws['B' + str(current_row_number)] = name + ' 详细数据' @@ -284,7 +285,7 @@ def generate_excel(report, chart_start_row_number = current_row_number - current_row_number += ca_len * 6 + current_row_number += ca_len * 6 + real_timestamps_len * 7 + 1 table_start_row_number = current_row_number ws.row_dimensions[current_row_number].height = 60 @@ -475,11 +476,214 @@ def generate_excel(report, current_row_number += 5 current_row_number += 1 + ########################################## + current_sheet_parameters_row_number = chart_start_row_number + 1 + has_parameters_names_and_timestamps_and_values_data = True + 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 + 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 timestamps_data_all_equal_0(lists): + for i, value in enumerate(list(lists)): + if len(value) > 0: + return False + return True + + +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_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/spacesaving.py b/myems-api/excelexporters/spacesaving.py index 07c47ad5..975a87e8 100644 --- a/myems-api/excelexporters/spacesaving.py +++ b/myems-api/excelexporters/spacesaving.py @@ -11,6 +11,7 @@ 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 #################################################################################################################### @@ -478,7 +479,7 @@ def generate_excel(report, if has_values_saving_data and has_timestamps_data: ca_len = len(reporting_period_data['names']) time = reporting_period_data['timestamps'][0] - + real_timestamps_len = timestamps_data_not_equal_0(report['parameters']['timestamps']) ws['B' + str(current_row_number)].font = title_font ws['B' + str(current_row_number)] = name + ' 详细数据' @@ -486,7 +487,7 @@ def generate_excel(report, chart_start_row_number = current_row_number - current_row_number += ca_len * 6 + current_row_number += ca_len * 6 + real_timestamps_len * 7 + 1 table_start_row_number = current_row_number ws.row_dimensions[current_row_number].height = 60 @@ -683,7 +684,188 @@ def generate_excel(report, current_row_number += 5 current_row_number += 1 + ########################################## + current_sheet_parameters_row_number = chart_start_row_number + 1 + has_parameters_names_and_timestamps_and_values_data = True + 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 + 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) @@ -698,3 +880,27 @@ def sum_list(lists): return total + +def timestamps_data_all_equal_0(lists): + for i, value in enumerate(list(lists)): + if len(value) > 0: + return False + + return True + + +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_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/spacestatistics.py b/myems-api/excelexporters/spacestatistics.py index 3a47901f..63cdca41 100644 --- a/myems-api/excelexporters/spacestatistics.py +++ b/myems-api/excelexporters/spacestatistics.py @@ -9,6 +9,7 @@ from openpyxl.chart.label import DataLabelList from openpyxl.styles import PatternFill, Border, Side, Alignment, Font from openpyxl.drawing.image import Image from openpyxl import Workbook +import openpyxl.utils.cell as format_cell #################################################################################################################### @@ -175,8 +176,6 @@ def generate_excel(report, if has_energy_data_flag: ws['B6'].font = title_font ws['B6'] = name + ' 统计分析' - # ws['D6'].font = title_font - # ws['D6'] = '面积' +report['space']['area'] category = reporting_period_data['names'] @@ -441,11 +440,12 @@ def generate_excel(report, names = reporting_period_data['names'] ca_len = len(names) time_len = len(timestamps) + real_timestamps_len = timestamps_data_not_equal_0(report['parameters']['timestamps']) # title - line_charts_row_number = 6 * ca_len + line_charts_row_number = 6 * ca_len + real_timestamps_len * 7 analysis_end_row_number = 12 + 3 * ca_len detailed_start_row_number = analysis_end_row_number + line_charts_row_number + 1 - + ws['B' + str(detailed_start_row_number)].font = title_font ws['B' + str(detailed_start_row_number)] = name + ' 详细数据' # table_title @@ -525,8 +525,214 @@ def generate_excel(report, ser.marker.symbol = "diamond" ser.marker.size = 5 ws.add_chart(line, 'B' + str(analysis_end_row_number + 6 * i)) + ########################################## + current_sheet_parameters_row_number = analysis_end_row_number + ca_len * 6 + 1 + has_parameters_names_and_timestamps_and_values_data = True + 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 + 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 timestamps_data_all_equal_0(lists): + for i, value in enumerate(list(lists)): + if len(value) > 0: + return False + + return True + + +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_not_equal_0(lists): + number = 0 + for i, value in enumerate(list(lists)): + if len(value) > 0: + number += 1 + return number