这是充电桩管理系统。运行起来会看到三类界面:
| 窗口 | 是什么 | 谁开 |
|---|---|---|
| 管理端 | 服务器 + 运营后台(写数据库、听 8888 端口) | 全组联调时 只允许一台电脑开 |
| 用户端 | 手机竖屏充电 App(底栏找桩 / 预约 / 充电 / 订单 / 我的) | 每个人的虚拟机都可以开,可以同时开很多个 |
| 运营大屏 | 浏览器里的 Vue 3 + ECharts 图表(Flask :5000,只读) |
任何人用浏览器打开即可(只看、不改数据) |
只在 Ubuntu 22.04 桌面 里运行。不要在 Windows 里双击 Qt 程序。
仓库里和呈现相关的目录:
| 目录 | 是什么 |
|---|---|
adminserver/ userclient/ common/ |
Qt 管理端 / 用户端 / 协议与地图 |
dashboard/ |
大屏:app.py(Flask)+ web/(Vue 3 源码)+ dist/(已构建,直接打开就能看) |
bigdata/ |
Hadoop / PySpark 分析(聚类、热力、电池风险)→ output/spark_report.json |
dataset/ |
原始表 04.数据集最终版/ + 扩样 CSV big/(约 22 万会话),给 Spark 读 |
database/ protocol/ ml/ docs/ |
表结构、报文、预测入口、说明文档 |
目录
- 三件不要忘
- 第一次准备
- 个人自己测(日常开发用这个)
- 计算机网络基础(联调必读)
- 一台当服务器、其他人当用户端
- 多管理端冲突:为什么、怎么处理
- 模块划分与接口
- 数据库设计
- 改代码与协作约定
- 打不开时
- 演示账号
- 运营大屏与大数据
答辩细拆(函数位置、五人分工):docs/大屏与智能分析答辩说明.md。
每人负责的文件表:docs/五人代码索引.md。
- 先开管理端,再开用户端。 管理端关了,用户端一定连不上。
- 演示号 不要点「注销」:
13800138000/123456。测注销请自己再注册一个号。 - 用户端「服务器地址」:
- 管理端也在 你这台 电脑 → 填
127.0.0.1:8888 - 管理端在 组里另一台 电脑 → 填那台管理端窗口 最底下 显示的
IP:8888
- 管理端也在 你这台 电脑 → 填
- 安装 Ubuntu 22.04(虚拟机即可)。
- 把整个
ChargeHub文件夹放进 Ubuntu(U 盘,或虚拟机共享文件夹,名字叫ChargeHub)。 - 打开「终端」,复制执行:
sudo apt update
sudo apt install -y build-essential qtbase5-dev qt5-qmake libqt5sql5-sqlite python3-flask python3-tk xdg-utils- 再编译一次(会弹出窗口):
# 共享文件夹名叫 ChargeHub 时:
bash /mnt/hgfs/ChargeHub/scripts/rebuild.sh
# 文件夹是拷进 Ubuntu 的:
cd 你的ChargeHub目录
bash scripts/rebuild.sh成品在主目录 ChargeHub-Linux。共享盘找不到时:
sudo mkdir -p /mnt/hgfs
sudo vmhgfs-fuse .host:/ /mnt/hgfs -o allow_other一个人改代码、验功能、交作业前自查,都走这一节。
整套程序都在你这一台 Ubuntu 虚拟机里,不连组员电脑,也不用改桥接、不用填局域网 IP。
和联调的差别(先记这一句):
| 个人自测(本节) | 全组联调(第 4 节) | |
|---|---|---|
| 开管理端 | 你自己开 | 全组只开一份(值班那台) |
| 用户端「服务器地址」 | 原样 127.0.0.1:8888 |
填值班机器底栏的 IP:8888 |
| 数据在哪 | 只在你这台虚拟机的库里 | 只在值班服务器的库里 |
自己测时开自己的管理端完全没问题。测完若要参加联调,先关掉自己的管理端,再按第 4 节连组里服务器。
第一次先编一次(改代码后再编一次):
bash scripts/rebuild.sh之后只双击这两个文件:
| 文件 | 打开什么 | 登录 |
|---|---|---|
ChargeHub/scripts/打开运营后台.bat |
管理端 | admin / 123456 |
ChargeHub/scripts/打开用户端.bat |
用户端 | 13800138000 / 123456,服务器 127.0.0.1:8888 |
用户端先点「连接」,连上后用顶栏切换 登录 / 注册。登录用演示号即可;注册须满足密码规则(6~20 位且含大小写字母和数字),成功后写入管理端数据库并自动登录。窗口是手机竖屏,底栏切换找桩 / 预约 / 充电 / 订单 / 我的。昵称、住址、评价、电站名称等可在窗口内用 Ctrl+空格 切换拼音(Linux ibus,不是任务栏的微软拼音);手机号和密码仍用英文数字。
大屏:管理端里 运营决策大屏 → 打开 Web 大屏,或浏览器打开 http://127.0.0.1:5000。页面是 Vue 3(<script setup>)+ ECharts,Flask 只读 SQLite 和 bigdata/output/spark_report.json,不会改订单/余额/桩状态。仓库已带 dashboard/dist,组员 不必先 npm install 也能看到和本地一样的图。改前端或重跑 Spark 见 第 11 节。
下面都在 你自己的 用户端 + 管理端上做。演示号不要点「注销」。
- 登录 / 注册
用户端能进首页;管理端「用户管理」里能看到13800138000。点「注册」页用新手机号注册(密码须含大小写字母和数字),管理端应出现该用户。 - 找桩
登录后会弹出位置授权。同意后优先用 Windows 定位(Wi-Fi/系统定位)。不准时会弹出地图:拖动查看周围,点击标定位置;也可随时点「地图选点」或填精确住址。点电站「位置 / 导航」可拖动预览图,并从该点导航到充电站。 - 预约 / 充电
选一根闲置桩:预约或直接开始充电。用户端充电页应有度数、金额在变;总价含固定 1 元起步价。 - 停止并结算
结束充电 → 待结算 → 结算。余额应减少;管理端「订单跟踪」应出现这条订单。 - 充值
个人中心模拟充值,余额增加;管理端能对上。 - 大屏
浏览器http://127.0.0.1:5000,营收/订单数应跟着刚才的结算变(刷新即可)。 - 管理端操作
试:冻结某个 自己新注册的号(不要冻演示号)、加电站或改电价、选中电站点「启用分时电价」、把闲置桩标故障再「远程重启 / 恢复」、在「订单跟踪」对卡住的单点强制结束 / 代结算、智能分析里「采纳选中调度建议」、打开「操作审计」。用户端用被冻号应无法登录。充电中把用户端关掉,约 60 秒后该桩应回到闲置,订单变待结算。充电中度数/金额除轮询外,服务端大约每 5 秒还会推一次PUSH_CHARGE。 - 注销(用新号)
再注册一个手机号,用该号测「注销账号」。注销后不能再登录、不能再用同一手机号注册。不要用 13800138000 测这一条。
测崩了、窗口关了:从 2.1 再开一遍即可。库在 ~/ChargeHub-Linux/admin/data/chargehub.db,一般不用手删。
- 源码改完并保存(Windows 里改的话,确认虚拟机共享盘已是最新文件)。
- Ubuntu 终端只跑:
bash /mnt/hgfs/ChargeHub/scripts/rebuild.sh(工程是拷进来的则:cd 工程目录 && bash scripts/rebuild.sh)
- 等两个窗口重新弹出,再走 2.1 登录、2.2 里你改过的那几条。
- 不要在共享盘上直接敲
make。只保存文件、不跑rebuild.sh,虚拟机里的程序还是旧的。
只想重新弹出窗口、没改代码:用 scripts/start.sh,或按 2.1 再双击 run.sh。
- 用户端服务器地址不要填组员的 IP(那是联调用法)。
- 不要同时再开第二份管理端(本机会提示已在运行或 8888 占用)。
- 不要把个人库和联调服务器混为一谈:你这边充的电,组员电脑上看不到,这是正常的。
- 测完要参加第 4 节联调:关掉自己的管理端和用户端,用户端改连值班服务器。
把电脑想成一栋楼,程序想成房间里的人。
每台连上网的电脑都有一个 IP,例如 192.168.1.8。
组员要找到「开着管理端的那台电脑」,靠的就是这个门牌号。
常见两种:
| 你看到的地址 | 白话 | 什么时候用 |
|---|---|---|
127.0.0.1 |
「我自己这台电脑」 | 用户端和管理端在 同一台 Ubuntu 里 |
192.168.x.x 或 10.x.x.x |
「局域网里别人也能敲的门牌」 | 用户端在 另一台 电脑 / 另一台虚拟机 |
千万不要 在别人的用户端里填 127.0.0.1:那会连到 他自己 的电脑,连不到你。
同一台电脑可以同时跑很多程序,靠端口区分:
| 端口 | 程序 | 谁来敲门 |
|---|---|---|
| 8888 | 管理端(ChargeHub 服务器) | 用户端程序(不要用浏览器打开) |
| 5000 | 运营大屏 Flask | 浏览器 输入 http://IP:5000 |
所以:
- 用户端登录页填:
192.168.1.8:8888(程序之间说话) - 浏览器大屏填:
http://192.168.1.8:5000(网页)
两套地址不要混。
要让 A 电脑的用户端连上 B 电脑的管理端,两台机器必须能互相「喊到」:
- 连 同一个 Wi-Fi,或
- 插在 同一间机房/同一个交换机 的网线
手机开热点也可以,但双方都要连这个热点。
一边连宿舍 Wi-Fi、一边连手机流量,一定连不上。
在用户端那台 Ubuntu 终端里测(把 IP 换成服务器底栏上的):
ping 192.168.1.8能通再开用户端。一直失败:Wi-Fi 不同,或虚拟机网络模式不对(见下)。
管理端如果跑在虚拟机里,虚拟机也有自己的 IP。
| 模式 | 像什么 | 组员能不能连 |
|---|---|---|
| NAT(默认常见) | 住酒店:对外只看到宿主机,虚拟机是内部分机 | 只有这台 Windows 自己 较容易访问;旁边同学的电脑通常进不去 |
| 桥接 Bridged | 虚拟机直接在 Wi-Fi 上有自己的门牌 | 同一 Wi-Fi 的同学可以连 |
联调时请把 当服务器的那台虚拟机 改成桥接:
- 虚拟机关机或先改网卡再开
- VMware:虚拟机 → 设置 → 网络适配器 → 桥接模式(Bridged)(勾选「复制物理网络连接状态」更好)
- 重新打开管理端,看窗口 最底下 的新 IP,以这一行为准
- 把新的
IP:8888发给组员
NAT 下的地址经常是 192.168.122.x 或 192.168.88.x,那是虚拟机内部网,不要 发给旁边物理机上的同学当服务器地址。
服务器那台 Ubuntu 若开了防火墙,需要放行两个端口:
sudo ufw allow 8888
sudo ufw allow 5000
sudo ufw reload没开 ufw 可以不管。
日常改功能、自己点一遍:请用 第 2 节,不要走本节。
本节只用于全组测 同一份数据(同一批用户、同一批订单)。
| 角色 | 几台 | 虚拟机里开什么 | 不要开什么 |
|---|---|---|---|
| 服务器电脑(事先说好谁当) | 只能 1 台 | 管理端 + 可选大屏 | 不要再在别人电脑上开第二份管理端 |
| 测试电脑(其余所有人) | 可以很多台 | 只开用户端 | 不要开管理端 |
| 任何人想「看运营数据」 | — | 浏览器打开 http://服务器IP:5000 |
这不是管理端,改不了用户冻结、加电站 |
队友 可以 在自己虚拟机里编译出管理端,也可以在 单人自测 时打开它(第 2 节)。
但是 一旦开始组内联调,其他人虚拟机里的管理端必须关掉,只留服务器那一台。
想操作「冻结用户、加电站、重启桩」:请到 服务器那台 电脑前操作,或让服务器同学开共享屏幕 / Ubuntu 远程桌面。
管理端没有「远程登录另一台管理端」的功能,因为管理端本身就是服务器。
- 虚拟机网络改成 桥接(第 3 节)。
- 只开管理端:
cd ~/ChargeHub-Linux/admin && ./run.sh登录 admin / 123456。
- 看窗口 最底部状态栏,类似:
用户端请填写 192.168.1.8:8888 数据库 /home/bit/ChargeHub-Linux/admin/data/chargehub.db
把 192.168.1.8:8888 发到群里(以你屏幕上的为准)。
- 建议同时开大屏(方便别人只看不改):
cd ~/ChargeHub-Linux/dashboard
CHARGEHUB_DB=$HOME/ChargeHub-Linux/admin/data/chargehub.db python3 app.py群里同步:大屏地址 http://192.168.1.8:5000。
- 联调期间不要关管理端窗口。
- 自己虚拟机里 不要 再双击
admin/run.sh。若已经开了,关掉。 - 打开用户端(自己编的或拷服务器的
ChargeHub-Linux/user整夹都可以):
cd ~/ChargeHub-Linux/user && ./run.sh- 「服务器地址」粘贴群里那串,例如
192.168.1.8:8888,不要用127.0.0.1:8888。 - 点「连接」,成功后再登录。可以注册自己的手机号,也可以商量着用演示号(演示号不要注销)。
- 充电、预约产生的订单,会出现在 服务器那台 的管理端和
http://服务器IP:5000大屏上。
- 全组只开着 一份 管理端
- 服务器虚拟机是 桥接
- 大家连 同一个 Wi-Fi
- 用户端地址与管理端底栏 完全一致(含
:8888) -
ping 服务器IP能通 - 管理端窗口没关
本项目里:管理端 = 服务器。它同时做三件事:
- 打开并 独占写入
data/chargehub.db - 在 8888 端口等待用户端
- 显示运营窗口
所以:
| 错误做法 | 实际后果 |
|---|---|
| 同一台 Ubuntu 开两个管理端 | 第二份会被文件锁拦住,或提示 8888 被占用 |
| 两台电脑各开一个管理端 | 两套库、两个 8888。用户端连谁,数据就在谁那里。看起来都能登录,但订单对不上、余额对不上 |
把 .db 放到共享盘让两台一起写 |
SQLite 不能当网上的共享数据库用,会损坏或锁死 |
联调时自己又开了管理端,用户端仍填 127.0.0.1 |
你在测自己的空库,不是组里的服务器 |
程序 不会 自动把两台管理端的数据合并。
- 群里指定 一名「值班服务器」,只他的虚拟机开管理端。
- 其他人虚拟机:只开用户端,地址填值班机器底栏 IP。
- 需要看后台:用浏览器开大屏;需要改后台:让值班同学操作或坐到那台电脑前。
- 换人当服务器:先 完全退出 旧管理端,再在新电脑上开管理端。注意:新电脑是 空库或自己的旧库,不会自动带着上一台的订单走。要延续同一份数据,请继续用原来那台,或拷贝
ChargeHub-Linux/admin/data/chargehub.db(必须在管理端 已关闭 后拷)。
改界面、改业务时,每个人在自己虚拟机开管理端 + 用户端(第 2 节)完全没问题,那是各测各的。
不要把「自己的管理端」和「值班服务器」混在一次联调里。
用户端 userclient 管理端 adminserver 大屏 / 预测
┌─────────────┐ TCP:8888 ┌──────────────────────┐ 只读db ┌──────────┐
│ UserWindow │ ─────────► │ TcpServer │ ◄───── │dashboard │
│ Client │ JSON帧 │ Dispatch → Database │ │ bigdata/ |
└─────────────┘ │ MainWindow(同进程) │ └──────────┘
└──────────────────────┘
源码目录对应关系:
| 目录 / 文件 | 职责 | 对外接口 | 协作时改哪里 |
|---|---|---|---|
common/protocol.* |
4 字节长度 + JSON 拆包组包 | Protocol::pack / append / nextPacket |
改帧格式必须用户端、管理端一起改 |
userclient/src/client.* |
TCP 客户端 | connectTo(ip,8888) request(type,data,token) |
只加请求,禁止 QSqlDatabase |
userclient/src/userwindow.* |
用户界面 | 按钮 → Client::request |
界面与交互 |
adminserver/src/tcpserver.* |
听 8888、多用户连接;断线 60s 释放桩 | 内部调用 Dispatch::handle / releaseStaleSession |
会话与超时 |
adminserver/src/dispatch.* |
装配与兼容门面 | handle(用户端);adminLogin / freezeUser 等(GUI) |
对外签名不要改 |
adminserver/src/services/ |
会话 / 充电 / 预约 / 电站 / 用户 / 评价 / 运营 / 分析 | 各领域函数;找桩 GPS 在 StationService |
加业务优先改对应服务 |
adminserver/src/transport/ |
路由、鉴权、幂等 | RequestDispatcher |
新 type 在 registerRoutes 注册 |
adminserver/src/database.* |
SQLite 唯一写入口 | query / one / execute / transaction |
改表要同步 schema.sql |
adminserver/src/mainwindow.* |
运营界面 | 直接调 Dispatch,不走 Socket | 后台页面 |
adminserver/src/chartwidget.* |
自绘图表 | setPoints / setBars / setSlices |
仅显示 |
dashboard/app.py |
Flask 只读大屏 | GET / GET /api/overview GET /api/analysis GET /api/bigdata |
有 dist/index.html 就提供 Vue 页;禁止 UPDATE 订单 |
dashboard/web/ |
Vue 3 + Vite + ECharts 源码 | 全部 .vue 用 <script setup> |
改完 npm run build,产物进 dashboard/dist |
dashboard/dist/ |
已构建的大屏静态页 | Flask 直接托管 | 组员克隆后即可打开,无需 Node |
bigdata/spark_analyze.py |
Hadoop + PySpark | GBT 负荷、KMeans 聚类、电池风险 | 只写 bigdata/output 与分析表 |
dataset/ |
Spark 用的 CSV | 04.数据集最终版/ 原始表;big/ 扩样 |
与本地大屏同一套数;详见 dataset/big/README.md |
ml/forecast.py |
预测入口 | 有 Spark 报告则导入,否则小时均值 | 不改余额、不改桩状态 |
database/schema.sql |
表结构说明 | 与 C++ 建表一致 | 改库先改此文件再改 C++ |
protocol/messages.md |
报文 type 列表 | 联调对照表 | 新增 type 必须更新此文件 |
用户端报文的 type、字段、错误码见 protocol/messages.md。
最终答辩介绍(怎么讲、演示怎么点、评委怎么问):docs/最终答辩-网络通信与外部接口.pdf。
从 IP/TCP 讲到本项目 Socket 与 HTTP:docs/Socket网络编程详解.pdf。逐文件技术对照:docs/网络通信与外部接口.pdf。
新增接口的步骤:
- 在
messages.md加一行 type - 在对应
services/里实现,并在Dispatch::registerRoutes注册 - 在
UserWindow里request(...)并处理responded
管理端 GUI 新增按钮:只调 Dispatch 的 C++ 方法,不要再发明一套 Socket。
文件位置(运行时): 服务器电脑
~/ChargeHub-Linux/admin/data/chargehub.db
谁能写: 只有 adminserver。用户端不准打开该文件。大屏只读。
设计分层:
- 账号层
admin运营账号;user车主(余额、状态:正常/冻结/注销)。注销只改状态留档,不删行。 - 资料层
user_avatar头像二进制(与 user 一对一)。 - 资源层
station电站;pile电桩(闲置/在用/故障)。站 1 对多 桩。 - 交易层
charge_order订单;recharge_log充值;reservation预约。 - 评价层
station_review/review_doc。 - 审计层
audit_log。 - 分析层
load_forecasthourly_loadfault_riskanalysis_alertdispatch_plananalysis_report(预测与大屏用,不参与扣费)。
关系简图:
admin
user ─── user_avatar
user ─── charge_order ─── pile ─── station
user ─── reservation ─── pile
user ─── recharge_log
user ─── station_review ─── station / pile
字段级说明以 database/schema.sql 为准(含 CHECK、外键、索引)。
C++ 启动时 CREATE IF NOT EXISTS 并给旧库补列,不以删除用户数据的方式「升级」。
联调时这份库只存在于 值班服务器 那台机器。别人电脑上的 chargehub.db 是另一份,互不影响。
改完源码后在 Ubuntu 执行:
bash /mnt/hgfs/ChargeHub/scripts/rebuild.sh不要在共享盘上直接 make。
| 类别 | 规则 | 例子 |
|---|---|---|
| 类 | 大驼峰 | MainWindow Dispatch |
| 函数 / 变量 | 小驼峰 | queryStations() userId_ |
| 源文件 / 目录 | 全小写、无下划线 | userwindow.cpp adminserver/ |
| 表字段 | SQL 下划线 | price_per_kwh |
| JSON | 小驼峰 | pileId radiusKm |
各模块文件头注释(@file / @brief)已写在对应 .h / .cpp,协作时先读文件头再改。
| 现象 | 先做什么 |
|---|---|
| 用户端连不上(本机自测) | 管理端开了吗?地址是不是 127.0.0.1:8888? |
| 用户端连不上(连组里服务器) | 别人是不是也开了管理端?你填的是不是 127.0.0.1?Wi-Fi 是否相同?虚拟机是否桥接?ping 通不通? |
| 提示已有管理端 / 8888 占用 | 关掉多余的管理端,全组只留一份 |
| 能登录但订单和别人不一样 | 你们连的不是同一台服务器(两套库) |
| 浏览器打不开大屏 | 在 dashboard/ 跑 python3 app.py;别人请用 http://服务器IP:5000 不要用 127.0.0.1。确认存在 dashboard/dist/index.html |
| 大屏 KPI 有数但热力/聚类是空的 | 需要 bigdata/output/spark_report.json。按第 11 节用 dataset/big 跑一遍 Spark |
双击 run.sh 没反应 |
还没编过,回到第 1 节 |
| 改代码没变化 | 必须再跑 rebuild.sh |
| 输入框打不出中文 | 在 ChargeHub 窗口里按 Ctrl+空格 开拼音(不要用 Windows 任务栏输入法)。仍不行则关掉两个窗口再双击 bat 重开 |
| 程序 | 账号 | 密码 | 注意 |
|---|---|---|---|
| 管理端 | admin |
123456 |
只在值班服务器上登录 |
| 用户端 | 13800138000 |
123456 |
不要用此号测注销 |
源码在 ChargeHub/,编好的程序在 ~/ChargeHub-Linux/(admin / user / dashboard)。发给同学当用户端时,拷 user 整夹。
大屏要和本地看起来一样,仓库里需要这三块(都已进 git,不含 node_modules):
| 路径 | 作用 |
|---|---|
dashboard/web/ |
Vue 3 源码(Composition API + <script setup>),顶栏切换 运营总览 / 行为分析 / 智能预测 / 用户分析 / 数据质量 / 风险调度 |
dashboard/dist/ |
npm run build 的产物,Flask 优先托管这里 |
dataset/ + bigdata/output/ |
Spark 输入 CSV、spark_report.json、多屏图表 dash_charts.json |
管理端开着的前提下:
cd ChargeHub/dashboard
CHARGEHUB_DB=$HOME/ChargeHub-Linux/admin/data/chargehub.db python3 app.py浏览器:http://127.0.0.1:5000。
GET /api/overview 读 SQLite 营收/订单;GET /api/bigdata 读 bigdata/output/spark_report.json(HDFS 没装时 Spark 本来就是读本地 dataset/big 算出来的)。
需要本机 Node 18+(只改 Qt / Flask / Spark 的人可以跳过):
cd ChargeHub/dashboard/web
npm install
npm run build构建结果写到 dashboard/dist/。再重启 python3 app.py。不要把 node_modules 提交进仓库。
步骤、算法说明见 bigdata/README.md。最短路径(HDFS 可选,没有则读 dataset/big):
cd ChargeHub/bigdata
python3 expand_dataset.py # 若 dataset/big 已在仓库里,可跳过
# 已安装 Spark 时:
bash scripts/run_spark_only.sh # 或 bash scripts/run_pipeline.sh输出覆盖 bigdata/output/spark_report.json。大屏刷新即可,不会改 charge_order / user.balance / pile.status。
原始表在 dataset/04.数据集最终版/,扩样规模见 dataset/big/README.md(默认约 22 万会话 + 8 万条遥测)。