charging-cabinet/tools/mock_redis.py
12451 06765f99db feat: H5 用户端 Taro 重写 + 前后端接口对齐修复
- 使用 Taro + React 重写 H5 用户端(替换旧的 React+Vite+H5 实现)
- 6 个页面:登录、首页、设备列表、设备详情、仓体详情、个人中心
- Zustand 状态管理 + API 层封装 11 个接口
- 后端 H5 路由:新增仪表盘/项目/设备/充电控制接口,组织数据隔离
- 扫码入口:/h5/{abstract_id} → 免认证查设备 + 登录后跳转
- 管理端:新增绑定码管理、二维码展示下载、设备绑定/替换 IMEI
- 产品落地页更新(hero-bg + logo 替换)
- 接口对齐修复:修正 action 路径/请求体,DashboardData 和 CabinetItem 字段匹配后端
- 布局兼容性:grid → flex,提升移动浏览器兼容性
- 移除旧 H5 项目 software/h5/
2026-07-03 02:45:00 +08:00

160 lines
4.7 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
"""
Redis 模拟数据填充工具
- 从数据库读取前10个设备
- 生成随机状态写入Redis设备级+板级+通道级)
- 300秒后自动过期与设备上报TTL一致
用法:
python tools/mock_redis.py # 填充模拟数据
python tools/mock_redis.py --clear # 清除所有模拟数据
"""
import sys
import json
import random
import redis
import pymysql
# Redis 配置
REDIS_HOST = "10.8.0.252"
REDIS_PORT = 6379
REDIS_PASSWORD = "Hbhyg731024@"
REDIS_DB = 5
# MySQL 配置
MYSQL_HOST = "10.8.0.252"
MYSQL_PORT = 3306
MYSQL_USER = "root"
MYSQL_PASSWORD = "Hbhyg731024@"
MYSQL_DB = "pms"
# 设备数量
DEVICE_COUNT = 10
# 通道状态: 0=空闲, 1=插入, 2=充电中, 3=充满, 4=故障
STATUS_IDLE = 0
STATUS_INSERTED = 1
STATUS_CHARGING = 2
STATUS_FULL = 3
STATUS_FAULT = 4
def get_devices():
"""从数据库获取前N个设备"""
conn = pymysql.connect(
host=MYSQL_HOST, port=MYSQL_PORT, user=MYSQL_USER,
password=MYSQL_PASSWORD, database=MYSQL_DB, charset="utf8mb4"
)
try:
with conn.cursor(pymysql.cursors.DictCursor) as cur:
cur.execute("""
SELECT c.imei, c.abstract_id, c.name,
(SELECT COUNT(*) FROM cabin_boards cb WHERE cb.cabinet_id = c.id) as board_count
FROM cabinets c ORDER BY c.id LIMIT %s
""", (DEVICE_COUNT,))
return cur.fetchall()
finally:
conn.close()
def gen_channel_hex(status: int) -> str:
"""生成单通道hex4字节=8个hex字符"""
# 字节1: bit0=在线 bit1=充电中 bit2=充满 bit3=故障
byte1 = 0x01 # 在线
if status == STATUS_CHARGING:
byte1 |= 0x02
elif status == STATUS_FULL:
byte1 |= 0x04
elif status == STATUS_FAULT:
byte1 |= 0x08
# 字节2-4: 随机(模拟电压电流等)
byte2 = random.randint(0x10, 0x60)
byte3 = random.randint(0x00, 0xFF)
byte4 = random.randint(0x00, 0xFF)
return f"{byte1:02x}{byte2:02x}{byte3:02x}{byte4:02x}"
def gen_board_status_hex(board_idx: int) -> str:
"""生成一块板6个通道的status_hex"""
parts = []
for ch in range(6):
# 随机分配状态,充电和故障少一些
r = random.random()
if r < 0.02:
status = STATUS_FAULT
elif r < 0.25:
status = STATUS_CHARGING
elif r < 0.32:
status = STATUS_FULL
elif r < 0.42:
status = STATUS_INSERTED
else:
status = STATUS_IDLE
parts.append(gen_channel_hex(status))
return "".join(parts)
def fill_mock_data():
"""填充模拟数据"""
r = redis.Redis(host=REDIS_HOST, port=REDIS_PORT, password=REDIS_PASSWORD, db=REDIS_DB, decode_responses=True)
devices = get_devices()
print(f"获取到 {len(devices)} 个设备")
for dev in devices:
imei = dev["imei"]
board_count = dev.get("board_count") or 6
device_key = f"device:{imei}"
# 设备级
r.hset(device_key, mapping={
"online": "1",
"rssi": str(random.randint(30, 95)),
"pow_fail_dc": random.choice(["0", "0", "0", "1"]), # 25%概率停电
"pow_fail_ac": "0",
})
r.expire(device_key, 300)
# 板级 + 通道级
for board_idx in range(1, board_count + 1):
board_key = f"{device_key}:board:{board_idx}"
status_hex = gen_board_status_hex(board_idx)
r.hset(board_key, mapping={"status_hex": status_hex})
# 解析6个通道
for ch in range(6):
ch_hex = status_hex[ch * 8 : (ch + 1) * 8]
byte1 = int(ch_hex[0:2], 16)
ch_key = f"{board_key}:ch:{ch}"
r.hset(ch_key, mapping={
"on": "1" if byte1 & 0x02 else "0",
"full": "1" if byte1 & 0x04 else "0",
"fault": "1" if byte1 & 0x08 else "0",
"hex": ch_hex,
})
name = dev.get("name") or imei
print(f"{name} ({imei}) — {board_count}")
print(f"\n完成!已填充 {len(devices)} 个设备300秒后自动过期")
def clear_mock_data():
"""清除所有模拟数据"""
r = redis.Redis(host=REDIS_HOST, port=REDIS_PORT, password=REDIS_PASSWORD, db=REDIS_DB, decode_responses=True)
devices = get_devices()
count = 0
for dev in devices:
imei = dev["imei"]
keys = r.keys(f"device:{imei}*")
if keys:
r.delete(*keys)
count += len(keys)
print(f"已清除 {count} 个 Redis key")
if __name__ == "__main__":
if "--clear" in sys.argv:
clear_mock_data()
else:
fill_mock_data()