方案1:图形识别
用 Python 图像识别 + 自动化操作 来实现风机时长的监控与统计:
1.1用python 编程思想实现思路
⸻
✅ 总体实现目标拆解
🎯 你的目标: 1. 识别所有风机当前状态(绿色 = 开,灰色 = 关); 2. 定时检测状态变更并记录起止时间; 3. 自动翻页切换不同楼层(右上角点击); 4. 周期性汇总统计开机时间并导出 Excel。
⸻
✅ 建议方案:使用 Python 自动化框架
| 技术模块 | 工具/库 |
|---|---|
| 图像识别(颜色识别) | PIL 或 OpenCV |
| 屏幕截图 | pyautogui 或 mss |
| 自动点击楼层切换按钮 | pyautogui |
| 数据存储/导出 | pandas + openpyxl |
| 后台定时运行 | threading + schedule(可选) |
⸻
🧠 基础原理说明 1. 每个风机是一个“卡片”,中间是一个 风扇图标,颜色为绿或灰; 2. 每页图标数量固定、排布整齐,因此可以用网格方式计算每个图标的坐标中心点; 3. 每隔 1 分钟截图,检测每个点的颜色变化,并更新运行时间记录; 4. 每页监测完后,点击右上角箭头(你提供图中那个 蓝色圆形图标),进入下一页继续识别; 5. 所有页完成后,等待一分钟继续下一轮。
⸻
✅ 核心流程与代码框架
🖼️ 1. 获取风机位置坐标(手动标一次)
你只需在屏幕分辨率一致的前提下,用截图工具标出第一排第一个风机图标中心坐标,比如:(120, 240),每个风机宽约 120px,高约 100px,则:
假设界面有6行 × 8列风机卡片
fan_positions = []
start_x, start_y = 120, 240
x_spacing, y_spacing = 120, 100
rows, cols = 6, 8
for r in range(rows):
for c in range(cols):
fan_positions.append((
start_x + c * x_spacing,
start_y + r * y_spacing
))
⸻
🎨 2. 判断图标颜色是否为绿色
from PIL import ImageGrab
def is_fan_on(pixel):
r, g, b = pixel
return g > 180 and r < 100 and b < 100 # 绿色
def check_fan_status(x, y):
screenshot = ImageGrab.grab()
pixel = screenshot.getpixel((x, y))
return "ON" if is_fan_on(pixel) else "OFF"
⸻
🖱️ 3. 自动点击右上角翻页按钮
import pyautogui
def click_next_floor():
pyautogui.moveTo(990, 140) # 此为右上角按钮的大致位置,请用 pyautogui.position() 精调
pyautogui.click()
你可以先运行:
pyautogui.position()
将鼠标移动到你截图中那个 “右上角翻页箭头按钮” 上,记录其坐标值。
⸻
📊 4. 记录状态切换与持续时间
from datetime import datetime
status_log = {}
run_records = []
def update_fan_status(fan_id, new_status):
now = datetime.now()
last_status, start_time = status_log.get(fan_id, (None, None))
if new_status != last_status:
if new_status == "ON":
status_log[fan_id] = ("ON", now)
elif new_status == "OFF" and start_time:
duration = (now - start_time).total_seconds() / 60
run_records.append({
"FanID": fan_id,
"StartTime": start_time,
"EndTime": now,
"Duration(min)": duration
})
status_log[fan_id] = ("OFF", None)
⸻
📦 5. 导出为 Excel
import pandas as pd
def export_to_excel():
df = pd.DataFrame(run_records)
df.to_excel("fan_log.xlsx", index=False)
⸻
🔁 6. 总循环(多页轮询)
def monitor_all_pages(total_pages=8):
for page in range(total_pages):
for idx, (x, y) in enumerate(fan_positions):
fan_id = f"P{page+1}-F{idx+1}"
status = check_fan_status(x, y)
update_fan_status(fan_id, status)
click_next_floor()
time.sleep(3) # 等页面刷新
⸻
1.2完整实现方案与下一步计划
⸻
✅ 项目目标概述
| 功能模块 | 内容 |
|---|---|
| ① 图像识别 | 自动识别屏幕上风机的状态(绿=开,灰=关) |
| ② 状态监控 | 定时识别各风机状态变化,记录开关时间 |
| ③ 楼层切换 | 自动点击右上角按钮,轮询8个楼层 |
| ④ 数据存储 | 记录每次风机开关的持续时间 |
| ⑤ 统计分析 | 按月/季度/年统计开机时长 |
| ⑥ 导出 Excel | 将记录导出为 .xlsx 报表 |
| ⑦ GUI 面板 | 提供可视化按钮与启动、查看状态等功能(可选) |
⸻
🛠️ 接下来的步骤安排
✅ Step 1:图像识别坐标 & 初始测试脚本
我们先生成: • 基于你图中页面识别的 48 个风机位置坐标; • 提供一个可运行的 .py 脚本,定时截图识别风机状态,并输出当前页风机状态列表。
⸻
✅ Step 2:状态变化记录逻辑
接下来我将实现以下功能: • 每个风机状态从“灰→绿→灰”算一次运行; • 记录开始时间、结束时间、持续分钟; • 保存在 CSV/Excel 中,并可定期汇总。
⸻
✅ Step 3:楼层轮询 & 自动点击
系统会: • 识别当前页风机; • 自动点击右上角按钮; • 继续识别下一页,直到全部页完成。
⸻
✅ Step 4:统计汇总与导出
将提供: • 月度、季度、年度统计汇总函数; • 每台风机的开机时长、频次、图表(可选); • 导出为 Excel 报表格式(EPPlus or pandas)。
⸻
✅ Step 5(可选):带 GUI 的监控工具
你可以拥有: • 图形界面带按钮启动监控; • 可视化状态显示(例如绿红灯标志); • 导出一键点击。
⸻
1.3生成一个完整可运行的 Python 脚本
实现:
✅ 图像识别风机状态 ✅ 每5分钟自动轮询识别所有页面(8页) ✅ 自动点击右上角切页按钮 ✅ 记录每台风机开启(绿色)持续时间 ✅ 导出运行记录为 Excel 表格
⸻
🧠 实现前提 • 界面排布为 6 行 × 8 列(共 48 台风机); • 每页风机位置一致; • 鼠标自动点击右上角箭头翻页(我默认其坐标为 (1840, 140),你可微调); • 状态判断基于中心像素是否为绿色。
⸻
📦 文件结构
fan_monitor/
├── fan_monitor.py # 主程序(轮询+识别+记录+导出)
├── fan_log.xlsx # 导出的运行日志
⸻
✅ 完整脚本(fan_monitor.py)
import pyautogui
import time
from datetime import datetime
from PIL import ImageGrab
import pandas as pd
import os
========== 配置部分 ==========
ROWS = 6
COLS = 8
PAGES = 8
X0, Y0 = 190, 270 # 第一个风机图标中心坐标(参考截图)
X_GAP = 172 # 横向间距
Y_GAP = 120 # 纵向间距
NEXT_BUTTON_POS = (1840, 140) # 翻页按钮坐标(右上角)
SCREEN_REGION = (0, 0, 1920, 1080)
CHECK_INTERVAL = 300 # 轮询间隔(秒)
========== 数据结构 ==========
status_log = {} # {fan_id: ("ON"/"OFF", start_time)}
run_records = [] # 运行时间段记录列表
def get_fan_positions():
positions = []
for row in range(ROWS):
for col in range(COLS):
x = X0 + col * X_GAP
y = Y0 + row * Y_GAP
positions.append((x, y))
return positions
def is_green(pixel):
r, g, b = pixel
return g > 180 and r < 100 and b < 100
def check_status(screenshot, pos):
pixel = screenshot.getpixel(pos)
return "ON" if is_green(pixel) else "OFF"
def update_status(fan_id, new_status):
now = datetime.now()
last_status, start_time = status_log.get(fan_id, (None, None))
if new_status != last_status:
if new_status == "ON":
status_log[fan_id] = ("ON", now)
elif new_status == "OFF" and start_time:
duration = (now - start_time).total_seconds() / 60
run_records.append({
"FanID": fan_id,
"StartTime": start_time,
"EndTime": now,
"Duration(min)": duration
})
status_log[fan_id] = ("OFF", None)
def click_next_page():
pyautogui.moveTo(*NEXT_BUTTON_POS)
pyautogui.click()
time.sleep(2) # 等待页面刷新
def monitor_once():
fan_positions = get_fan_positions()
for page in range(PAGES):
screenshot = ImageGrab.grab(SCREEN_REGION)
for idx, pos in enumerate(fan_positions):
fan_id = f"P{page+1}-F{idx+1}"
status = check_status(screenshot, pos)
update_status(fan_id, status)
if page < PAGES - 1:
click_next_page()
def export_log():
if not run_records:
return
df = pd.DataFrame(run_records)
os.makedirs("export", exist_ok=True)
df.to_excel(f"export/fan_log_{datetime.now().strftime('%Y%m%d_%H%M%S')}.xlsx", index=False)
def run_monitor():
print("启动风机监控...")
try:
while True:
print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] 轮询中...")
monitor_once()
export_log()
time.sleep(CHECK_INTERVAL)
except KeyboardInterrupt:
print("监控中断,导出记录...")
export_log()
if __name__ == "__main__":
run_monitor()
⸻
✅ 使用说明 1. 安装依赖(确保用 Python 3.9+):
pip install pyautogui pillow pandas openpyxl
- 运行脚本(记得先打开风机监控界面):
python fan_monitor.py
- 结果导出:
• 每轮运行后,会在 export/ 文件夹中生成 fan_log_*.xlsx 文件; • 文件包含每个风机的运行时间段及持续时间。
⸻
✅ 后续可加功能(可按需添加)
| 功能 | 实现方式 |
|---|---|
| GUI 可视化监控界面 | 使用 Tkinter or PyQt |
| 异常报警(连续运行超时) | 加阈值判断 |
| 分析图表(运行趋势) | 用 matplotlib 绘图 |
| 按月/季度/年统计 | 用 groupby 统计汇总 |
⸻
1.4为现有的脚本添加功能
✅ 统计每台风机的总运行时长(按月、季度、年) ✅ 自动在导出 Excel 中加入统计汇总页
⸻
✅ 修改步骤概览
🧩 目标效果: • 每轮导出日志时,自动新增一个 汇总 工作表; • 汇总包含每台风机在该时间段内的: • 月运行时长 • 季度运行时长 • 年运行时长(当前年度)
⸻
✅ 代码修改部分
替换原脚本中的 export_log() 函数为以下内容:
def export_log():
if not run_records:
return
df = pd.DataFrame(run_records)
df['StartTime'] = pd.to_datetime(df['StartTime'])
df['Year'] = df['StartTime'].dt.year
df['Month'] = df['StartTime'].dt.to_period('M')
df['Quarter'] = df['StartTime'].dt.to_period('Q')
# 分组统计总运行时长(分钟)
df_month = df.groupby(['FanID', 'Month'])['Duration(min)'].sum().reset_index()
df_quarter = df.groupby(['FanID', 'Quarter'])['Duration(min)'].sum().reset_index()
df_year = df.groupby(['FanID', 'Year'])['Duration(min)'].sum().reset_index()
# 创建工作簿
now = datetime.now().strftime('%Y%m%d_%H%M%S')
out_path = f"export/fan_log_{now}.xlsx"
with pd.ExcelWriter(out_path, engine='openpyxl') as writer:
df.to_excel(writer, sheet_name='运行记录', index=False)
df_month.to_excel(writer, sheet_name='月统计', index=False)
df_quarter.to_excel(writer, sheet_name='季度统计', index=False)
df_year.to_excel(writer, sheet_name='年度统计', index=False)
⸻
1.5最终生成 Excel 内容结构示例
📄 Sheet 1:运行记录
| FanID | StartTime | EndTime | Duration(min) |
|---|---|---|---|
| P1-F01 | 2025-07-01 10:00 | 2025-07-01 11:30 | 90 |
📄 Sheet 2:月统计
| FanID | Month | Duration(min) |
|---|---|---|
| P1-F01 | 2025-07 | 300 |
📄 Sheet 3:季度统计
| FanID | Quarter | Duration(min) |
|---|---|---|
| P1-F01 | 2025Q3 | 300 |
📄 Sheet 4:年度统计
| FanID | Year | Duration(min) |
|---|---|---|
| P1-F01 | 2025 | 300 |
⸻
✅ 下一步建议(可选扩展)
| 功能 | 描述 |
|---|---|
| 图表可视化(柱状/折线) | 用 matplotlib 或 openpyxl 绘图 |
| GUI 交互界面 | 启动/停止/查看运行状态按钮 |
| 开关日志分离按页保存 | 每页一个日志文件更易审计 |
| 自动定时启动 | 加入 Windows 任务计划或用 PyInstaller 打包服务 |
⸻
方案2:反编译
用dnspy反编译软件尝试对【touchvew】实现在原有系统上进行功能增添,看源程序界面是基于winform框架开发的:

安装dnspy进行软件反编译:

无法正常破解,方案2失效。
