一、概述
我会画电路板、写 C 程序;在 AI 编程的助力下,以近乎零代码的方式完成了设备端、服务端、Web 端、Windows 端与小程序端的全栈打通------串口数据上云、远程终端、虚拟串口等能力均可多端使用。

二、功能说明
2.1.PCB
串口:TTL/RS232
联网:WIFI/4G
调试:CH340

2.2.功能介绍
|------------|--------------------------------------------------------------|----------------------------|
| 功能 | 功能描述 | 应用场景 |
| 串口数据记录 | 设备实时将串口数据转到服务端,可通过小程序、WEB 查看。 | 远程日志记录、设备运行监控、故障回溯与排查 |
| 终端控制 | 通过 Web 端开启设备远程终端,实时发送指令、查看输出,支持远程操作与运维。 | 远程调试、远程开发管理、现场设备免到场维护 |
| 虚拟串口 | 将远程设备串口映射为本地虚拟 COM 口,通过 TCP/服务器与设备双向透传,本地工具可像访问物理串口一样访问远程串口。 | 数据采集、远程控制、上位机/调试工具远程连接设备串口 |
| 其他功能 | 远程升级、设备管理、用户管理、设备绑定 | IOT |
2.3.功能演示
2. 3.1 应用连接图
图片是 UTOOL串口通过TTL 链接了一个STM32H750 的一个开发板。
下面这套组合放在任何地方我都可以对这个STM32H750开发板进行调试。
尤其是设备需要在公司烤机的时候,随时可以远程查看板子运行的状态,比出差的时候,在路上,打开手机就可以看到这个板子的日志。

2. 3.2 小程序端查看串口数据
微信小程序,可看到UTOOL外挂串口设备的日志。日志是实时传输到云端的,随时可以看。

2. 3.3 WEB端查看串口数据
web端和小程序端功能差不多

2. 3.4 终端控制功能
WEB网页上新建一个终端控制页。在这个页面下可以给UTool 外接的串口设备进行控制,如shell 调试,配置交换机等
图片上演示的是外挂的一个STM32开发板,跑的rt_thread 系统。看到的是msh 指令

2. 3.5 虚拟串口功能演示
uCOM 创建虚拟串口,Xshell成功链接该串口并通信成功。如果串口设备是原配有上位机的,那种这种方案就 很实用了。远端回传个r

三、开源链接
3.1 MCU代码
码云utool_mcu
3.2 服务端代码
码云utool_server
3.3 虚拟串口windows客户端代码
码云utool_ucom
3.4 微信小程序代码
码云utool_wechat
3.5 原理图
硬件创社
3.6 PCB、BOM
硬件创社
四、开发过程记录
4.1、环境介绍
-
AI代码编辑器:cursor
-
coding模型: 复杂任务Claude Sonnet 4.5 + 简单任务 Auto
-
编译环境:MCU:CDK、 windows客户端:pyinstaller 、小程序:微信开发者工具.、服务端:无
-
PCB:AD19
4.1.1 cursor 安装与配置
这种教程网上多的很,这里只特别说明一下,C/C++开发。
C/C++开发需要装ms-vscode.cpptools:这个插件。
新版本的ms-vscode.cpptools 插件 不支持cursor
可以装这个版本。直接下载
https://github.com/microsoft/vscode-cpptools/releases/download/v1.17.2/cpptools-win64.vsix

安装方式:ctrl+shift+p 然后选从VSIX 安装。再选刚才下载的文件,就可以了,C代码可以跳转了。。

下面这个是装了插件后它让加入的C++配置文件

配置文件

编辑器中隐藏.i文件

4.2、电路图设计
电路是自己画的,就不多BB了
也有AI画图,试过效果都不太好
介绍一些硬件仿真平台:不用做板子、也可以搞开发

4.3、让AI提取电路图内容
把电路图转成PDF或者图片
最新版的Cursor是可以读PDF的,如果读不了PDF的可以用图片
下面是提示词,这个步骤的效果可以参考之前发的笔记
读取并总结电路图 整体框架 各模块详细说明 外设PIN脚表 写成文档
有些时候并不是越高级的模型越好,简单的任务尽量用auto。
如果用高级模型,一个是很贵、另外高级模型为了让你值回票价回给你很多AI幻觉,写一抹多,其实没什么卵用
cursor auto模型 处理简单任务,比较精准,没啥废话
4.4、MCU代码编写
4.4.1.下载W806 官方SDK
里面有W806 驱动、和demo以及一些库。如果是STM32的话。就用STM32CubeMX生成
w806 SDK下载地址:
4.4.2.MQTT协议代码准备
项目需要用到MQTT,MQTT协议栈也给AI准备一个,免得它给你搞个不熟悉的协议代码,不好排查故障
我这边用的是:mbed-mqtt
4.4.4. 其他驱动代码准备
嵌入式很多外设属于细分领域的,AI根本就找不到它的驱动代码,这种情况AI写出来的代码肯定是用不了的。
把厂家给的驱动准备好,或者去网上下载确保驱动是可以正常使用的
用AI写 EC800G-CN 模块****驱动代码
在项目中,用到了EC800G-CN 模块。我没有找到合适的4G 模块驱动代码 想把文档拿给AI让它帮你写一版驱动代码
1、以下是我给它的提示词
bash
根据模块文档帮我写一版驱动@utool_mcu/doc/Quectel_LTE_StandardU系列_AT命令手册_V1.1.pdf
模块型号EC800G-CN
写一个LTE.C 和 LTE.H 写到这个文件夹@utool_mcu/utool_mcu/driver
C代码风格,linux 风格
结合EC800G-CN 常规用法
本项目中用到的MCU是W806串口UATRT3
本项目中用4G模块连接云端服务器功能
4G模块供电 PA1 和LTE_PWR_KEY PA10 其他硬件相关去这个文档获取@utool_mcu/doc/utool_原理图文档.md
2、使用Cursor 的Plan 模式
像这种写第一版代码,模型尽量用高端一点的模型,
我这里任务比较简单就一个.c和.h,
使用Auto 更加经济 。

3、运行了Plan 模式后AI会做一个计划,仔细阅读计划。
如果没问题,可以直接点击Build 它开始写代码。
这个plan 模认是没下载下来的。
点击这个下载按钮,可以下载到工程目录下:.cursor\plan

4、修改计划
读了它的计划后 我发现它写的驱动太基础了。
和我预期的不太一样,我需要在Build之前对它这个计划进行纠正。
完了后开始build

5、来回拉扯
之后还修改了两次plan

6、build
paln 敲定后 点击 build,等两分钟,代码就写好了。

7、review 代码
以下是它写的代码,可以评估下写的怎么样
站在我的角度上去看。代码真的是写的又快有好
我加到项目后。代码直接一把过。
代码一把过的时候真的是非常少,很多时候都需要来回拉扯好几遍。
cpp
/*
* LTE.h - EC800G-CN LTE modem driver (W806 UART3 + GPIO)
*
* Hardware: LTE_EN=PA1, LTE_PWR_KEY=PA10, UART3=PA5(TX)/PA6(RX).
* Uses W806 platform drivers only (platform/drivers/uart, gpio, gpio_afsel).
*/
#ifndef LTE_H
#define LTE_H
#include <stddef.h>
#include <stdint.h>
/* W806 pin and UART types for macro definitions */
#include "wm_io.h"
#include "wm_uart.h"
/* Pin and UART (match schematic) */
#define LTE_GPIO_EN WM_IO_PA_01 /* LTE_EN, power enable */
#define LTE_GPIO_PWR_KEY WM_IO_PA_10 /* LTE_PWR_KEY, power-on sequence */
#define LTE_UART_ID TLS_UART_3
#define LTE_UART_TX_PIN WM_IO_PA_05
#define LTE_UART_RX_PIN WM_IO_PA_06
#define LTE_DEFAULT_BAUD 115200
/* Error codes (Linux-style, negative) */
#define LTE_OK 0
#define LTE_ERR_TIMEOUT (-1)
#define LTE_ERR_IO (-2)
#define LTE_ERR_PARAM (-3)
#define LTE_ERR_STATE (-4) /* e.g. not connected for send */
#define LTE_ERR_NOMEM (-5)
/* Default PDP context id for data (used by QIOPEN etc.) */
#define LTE_PDP_CID 1
/* Max single QISEND length (Quectel typical) */
#define LTE_SEND_CHUNK 1460
/*
* Hardware and low-level
*/
int lte_hw_init(void);
int lte_power_on(void);
int lte_power_off(void);
int lte_uart_init(uint32_t baudrate);
int lte_at_send(const char *cmd);
int lte_at_send_buf(const void *buf, size_t len);
int lte_at_wait_response(char *buf, size_t size, int timeout_ms);
int lte_deinit(void);
/*
* Network ready (PDP)
*/
int lte_network_ready(const char *apn, int timeout_ms);
int lte_check_sim(void);
int lte_set_pdp_context(int cid, const char *apn);
int lte_activate_pdp(int cid);
int lte_get_signal_csq(int *rssi, int *ber);
/*
* Application: connect to server and send/recv
*/
int lte_server_connect(const char *host, uint16_t port);
int lte_server_send(const void *data, size_t len);
int lte_server_disconnect(void);
int lte_server_recv(void *buf, size_t size, int timeout_ms);
#endif /* LTE_H */
cpp
LTE.c
/*
* LTE.c - EC800G-CN LTE modem driver (W806 UART3 + GPIO)
*
* Uses only RTOS_W806_SDK_OTA/platform drivers: wm_uart, wm_gpio, wm_gpio_afsel.
*/
#include "LTE.h"
#include <string.h>
#include <stdio.h>
#include "wm_uart.h"
#include "wm_gpio.h"
#include "wm_gpio_afsel.h"
#include "wm_pmu.h"
#include "wm_osal.h"
#include "wm_mem.h"
#include "wm_type_def.h"
/* Power and PWR_KEY timing (plan: 2s stable, 800ms key low) */
#define LTE_POWER_STABLE_TICKS (2 * HZ)
#define LTE_PWR_KEY_LOW_TICKS (800 * HZ / 1000)
#define LTE_PWR_KEY_RELEASE_MS 50
#define LTE_AT_READY_TIMEOUT_MS 15000
#define LTE_POWERED_DOWN_TIMEOUT_MS (65 * 1000)
static uint8_t lte_uart_inited;
static uint8_t lte_server_connected; /* 1 = TCP connected */
/* UART RX callback: driver already stores data in its ring; we just need it registered */
static s16 lte_uart_rx_cb(u16 len, void *priv_data)
{
(void)len;
(void)priv_data;
return 0;
}
/* Delay in ms using OS ticks (HZ ticks per second) */
static void lte_delay_ms(int ms)
{
if (ms <= 0)
return;
tls_os_time_delay((u32)((unsigned)ms * HZ / 1000));
}
/* Read one line (up to and including \r or \n) from UART into buf, null-terminated. Returns length. */
static int lte_rx_getline(char *buf, size_t size, int timeout_ms)
{
size_t i = 0;
if (size == 0)
return LTE_ERR_PARAM;
while (i < size - 1) {
while (tls_uart_try_read(LTE_UART_ID, 1) != 1) {
lte_delay_ms(10);
timeout_ms -= 10;
if (timeout_ms <= 0)
return LTE_ERR_TIMEOUT;
}
uint8_t c;
int n = tls_uart_read(LTE_UART_ID, &c, 1);
if (n != 1)
continue;
if (c == '\r' || c == '\n') {
buf[i] = '\0';
return (int)i;
}
buf[i++] = (char)c;
}
buf[i] = '\0';
return (int)i;
}
/* Flush UART RX (discard all in driver buffer) */
static void lte_rx_flush(void)
{
uint8_t c;
while (tls_uart_try_read(LTE_UART_ID, 1) == 1)
tls_uart_read(LTE_UART_ID, &c, 1);
}
int lte_hw_init(void)
{
tls_gpio_cfg(LTE_GPIO_EN, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_FLOATING);
tls_gpio_cfg(LTE_GPIO_PWR_KEY, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_FLOATING);
tls_gpio_write(LTE_GPIO_EN, 0);
tls_gpio_write(LTE_GPIO_PWR_KEY, 1); /* released = high */
return LTE_OK;
}
int lte_power_on(void)
{
tls_gpio_write(LTE_GPIO_EN, 1);
tls_os_time_delay(LTE_POWER_STABLE_TICKS);
tls_gpio_write(LTE_GPIO_PWR_KEY, 0);
tls_os_time_delay(LTE_PWR_KEY_LOW_TICKS);
tls_gpio_write(LTE_GPIO_PWR_KEY, 1);
lte_delay_ms(LTE_PWR_KEY_RELEASE_MS);
/* Wait for module AT ready (need UART first - caller should lte_uart_init then poll AT) */
return LTE_OK;
}
int lte_power_off(void)
{
if (!lte_uart_inited)
return LTE_ERR_STATE;
lte_at_send("AT+QPOWD");
/* Wait POWERED DOWN or timeout 65s */
int timeout_ms = LTE_POWERED_DOWN_TIMEOUT_MS;
char line[128];
while (timeout_ms > 0) {
int r = lte_at_wait_response(line, sizeof(line), 1000);
if (r >= 0 && strstr(line, "POWERED DOWN") != NULL)
break;
timeout_ms -= 1000;
}
lte_delay_ms(1000);
tls_gpio_write(LTE_GPIO_EN, 0);
lte_server_connected = 0;
return LTE_OK;
}
int lte_uart_init(uint32_t baudrate)
{
tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_UART3);
wm_uart3_tx_config(LTE_UART_TX_PIN);
wm_uart3_rx_config(LTE_UART_RX_PIN);
tls_uart_options_t opt;
opt.baudrate = baudrate ? baudrate : LTE_DEFAULT_BAUD;
opt.charlength = TLS_UART_CHSIZE_8BIT;
opt.flow_ctrl = TLS_UART_FLOW_CTRL_NONE;
opt.paritytype = TLS_UART_PMODE_DISABLED;
opt.stopbits = TLS_UART_ONE_STOPBITS;
if (tls_uart_port_init(LTE_UART_ID, &opt, 0) != WM_SUCCESS)
return LTE_ERR_IO;
tls_uart_rx_callback_register(LTE_UART_ID, lte_uart_rx_cb, NULL);
lte_uart_inited = 1;
lte_server_connected = 0;
return LTE_OK;
}
int lte_at_send(const char *cmd)
{
if (!lte_uart_inited || !cmd)
return LTE_ERR_PARAM;
size_t len = strlen(cmd);
char *buf = (char *)tls_mem_alloc(len + 4);
if (!buf)
return LTE_ERR_NOMEM;
memcpy(buf, cmd, len);
buf[len++] = '\r';
buf[len++] = '\n';
buf[len] = '\0';
int r = tls_uart_write(LTE_UART_ID, buf, (u16)len) == WM_SUCCESS ? LTE_OK : LTE_ERR_IO;
tls_mem_free(buf);
return r;
}
int lte_at_send_buf(const void *buf, size_t len)
{
if (!lte_uart_inited || !buf)
return LTE_ERR_PARAM;
if (tls_uart_write(LTE_UART_ID, (char *)buf, (u16)len) != WM_SUCCESS)
return LTE_ERR_IO;
return (int)len;
}
int lte_at_wait_response(char *buf, size_t size, int timeout_ms)
{
if (!buf || size == 0)
return LTE_ERR_PARAM;
return lte_rx_getline(buf, size, timeout_ms);
}
int lte_deinit(void)
{
lte_uart_inited = 0;
lte_server_connected = 0;
/* UART port is not de-initialized by SDK API; just stop using it */
return LTE_OK;
}
/* Check SIM READY */
int lte_check_sim(void)
{
if (lte_at_send("AT+CPIN?") != LTE_OK)
return LTE_ERR_IO;
char line[128];
int r = lte_at_wait_response(line, sizeof(line), 2000);
if (r < 0)
return r;
if (strstr(line, "READY") != NULL)
return LTE_OK;
return LTE_ERR_IO;
}
int lte_set_pdp_context(int cid, const char *apn)
{
char cmd[96];
snprintf(cmd, sizeof(cmd), "AT+CGDCONT=%d,\"IP\",\"%s\"", cid, apn ? apn : "");
return lte_at_send(cmd) == LTE_OK ? LTE_OK : LTE_ERR_IO;
}
int lte_activate_pdp(int cid)
{
char cmd[32];
snprintf(cmd, sizeof(cmd), "AT+CGACT=1,%d", cid);
if (lte_at_send(cmd) != LTE_OK)
return LTE_ERR_IO;
char line[128];
int r = lte_at_wait_response(line, sizeof(line), 15000);
if (r < 0)
return r;
if (strstr(line, "OK") != NULL)
return LTE_OK;
return LTE_ERR_IO;
}
int lte_network_ready(const char *apn, int timeout_ms)
{
if (lte_at_send("ATE0") != LTE_OK)
return LTE_ERR_IO;
{
char drain[64];
lte_at_wait_response(drain, sizeof(drain), 500); /* drain */
}
if (lte_check_sim() != LTE_OK)
return LTE_ERR_IO;
if (lte_set_pdp_context(LTE_PDP_CID, apn) != LTE_OK)
return LTE_ERR_IO;
if (lte_activate_pdp(LTE_PDP_CID) != LTE_OK)
return LTE_ERR_IO;
return LTE_OK;
}
int lte_get_signal_csq(int *rssi, int *ber)
{
if (lte_at_send("AT+CSQ") != LTE_OK)
return LTE_ERR_IO;
char line[64];
if (lte_at_wait_response(line, sizeof(line), 2000) < 0)
return LTE_ERR_TIMEOUT;
{
int r = 0, b = 0;
if (sscanf(line, "+CSQ: %d,%d", &r, &b) >= 1) {
if (rssi)
*rssi = r;
if (ber)
*ber = b;
return LTE_OK;
}
}
return LTE_ERR_IO;
}
/* TCP: Quectel QIOPEN/QISEND/QICLOSE (EC800 series) */
int lte_server_connect(const char *host, uint16_t port)
{
if (!host || lte_server_connected)
return LTE_ERR_PARAM;
char cmd[128];
snprintf(cmd, sizeof(cmd), "AT+QIOPEN=1,0,\"TCP\",\"%s\",%u", host, (unsigned)port);
if (lte_at_send(cmd) != LTE_OK)
return LTE_ERR_IO;
char line[128];
int r = lte_at_wait_response(line, sizeof(line), 75000);
if (r < 0)
return r;
if (strstr(line, "OK") != NULL || strstr(line, "+QIOPEN: 0,0") != NULL)
lte_server_connected = 1;
else
return LTE_ERR_IO;
return LTE_OK;
}
int lte_server_send(const void *data, size_t len)
{
if (!lte_server_connected || !data)
return LTE_ERR_PARAM;
const uint8_t *p = (const uint8_t *)data;
int sent = 0;
while (len) {
size_t chunk = len > LTE_SEND_CHUNK ? LTE_SEND_CHUNK : len;
char cmd[32];
snprintf(cmd, sizeof(cmd), "AT+QISEND=0,%u", (unsigned)chunk);
if (lte_at_send(cmd) != LTE_OK)
return LTE_ERR_IO;
char line[64];
if (lte_at_wait_response(line, sizeof(line), 5000) < 0)
return LTE_ERR_TIMEOUT;
if (strstr(line, ">") == NULL)
return LTE_ERR_IO;
if (tls_uart_write(LTE_UART_ID, (char *)p, (u16)chunk) != WM_SUCCESS)
return LTE_ERR_IO;
p += chunk;
len -= chunk;
sent += (int)chunk;
lte_at_wait_response(line, sizeof(line), 5000);
}
return sent;
}
int lte_server_disconnect(void)
{
if (!lte_server_connected)
return LTE_OK;
lte_at_send("AT+QICLOSE=0");
lte_server_connected = 0;
return LTE_OK;
}
int lte_server_recv(void *buf, size_t size, int timeout_ms)
{
if (!lte_server_connected || !buf || size == 0)
return LTE_ERR_PARAM;
/* Poll for data in UART buffer (from +QIURC "recv" or module response) */
int t = timeout_ms;
while (t > 0) {
int avail = tls_uart_try_read(LTE_UART_ID, (int32_t)size);
if (avail > 0) {
int n = tls_uart_read(LTE_UART_ID, (u8 *)buf, (u16)(avail > (int)size ? size : (size_t)avail));
return n >= 0 ? n : LTE_ERR_IO;
}
lte_delay_ms(20);
t -= 20;
}
return LTE_ERR_TIMEOUT;
}
8、提交代码
代码接受后,可以将代码提交GIT

9、最后给大家看看,这个.C和.H花了多少钱。
登录cursor的后台可以看到每个Agent 的token花费。
统计下花费了1.09美元换算成人名币是7块钱左右。
两杯蜜雪冰城。。你们觉得划算吗。
我用的是auto 便宜的模型,在加上我的pro账号20刀一个月,
auto 是无限量使用,几乎等于不要钱
(明面上是无限量,可token 上了一个亿后,老是会卡住,等于是限量)。
如果用claud code 4.5 的话。估计是5美元左右。愿意花5美元买一个.c和.吗

4.4.4.写MCU端代码生成提示词
为了得到相对确定的结果,写的提示词一定要详细。
当然,如果也可以写简单的大需求,剩下的交给AI幻觉。
甚至功能都可以让AI给你定义。
bash
1.WM_SDK_W806 是W806官方SDK,WM_SDK_W806\tools这个路径是demo工程
2.mbed-mqtt-master是mqtt代码
3.utool_原理图pdf.pdf 是电路图
4.utool_原理图文档.md 是电路图解析文档
5.utool_mcu 项目代码全写到这个文件夹
6.不能修改SDK 和MQTT协议栈的代码,只能调用,用到的代码或者文件都需要拷贝到utool_mcu
7.项目结构清晰方便维护
8.代码风格,Linux 内核风格
9.UATRT0 是调试端口,代码下载,日志输出端口
10.日志 选 ulog
分等级ERROR、WORING、DEBUG。
日志可根据等级查找。
可设置等级选择输出等级,
日志输出在控制台里根据等级显示不同颜色
日志需要打印文件名称(不是路径)和行号
11.UATRT0 通过串口配置设备信息DeviceID、Secret、ProductKey
DeviceID:sc22430984,Secret:QNVKFuC07aPI+VYRyk3ZLg==,ProductKey:9rZJxganPKJRO2UY5AhBHA==...
可通过UATRT0 配置服务器地址和端口号
12.UATRT2是接外设的是,本项目核心功能就是
UATRT2的数据传通过WIFI/4G传到服务端存起来、通过WEB端和小程序端查看
通过 Web 端开启设备远程终端,实时发送指令、查看输出,支持远程操作与运维,通过UATRT2透传给外接设备
将远程设备串口映射为本地虚拟 COM 口,通过 TCP/服务器与设备双向透传,本地工具可像访问物理串口一样访问远程串口(串口3外接的设备)
UATRT2的波特率可设置
以上通讯都通过MQTT,每个功能要定义不同的TOPIC
13.UATRT4 外接的是 蓝牙WIFI模块
通过蓝牙连接小程序配网:WIFI名、WIFI密码,配网流程协议需要写成文档,供给小程序开发用
通过WIFI链接服务器
14.UATRT3外接的是4G模块
根据文档写4G模块的驱动 Quectel_LTE_StandardU系列_AT命令手册_V1.1
通过4G模块联网
15.WIFI联网还是4G联网通过启动时候通过配置区分
16.在线升级功能,通过MQTT实现对板子的在线升级功能。IAP功能调用wm_fwup.c 功能参考 uart_ota.c
17.通过MQTT实现,板子参数的修改
18.MQTT相关TOPIC实现后。需要编写文档,以供后续服务端和WEB端小程序端等开发
19.参数管理,参数存到FLASH里面
串口3的波特率设置
DeviceID、Secret、ProductKey
服务器数据,IP + 端口
WIFI还是4G
4.4.3.使用plan模式进行第一版设计
TODO
4.5.服务端端设计TODO
bash
1.MQTT服务:对接MCU MQTT相关协议文档完成相关功能
2.小程序服务:对接小程序API文档,完成小程序需要的相关功能
3.windows端服务:对接windows端文档,完成windows端需要的相关功能
4.web端:
5.以上各个服务独立运行。
6.设备管理、用户管理属于公共接口
7.
8.一键部署脚本
requirements.txt Python 依赖版本要固定,Python版本也要固定
install.bat 创建虚拟环境搭建运行环境
start.bat 将项目打包成EXE
小程序端是必须要HTTPS的,SSL证书我已经下载并放到了SSL文件夹里面utool.icu_nginx.zip。install.bat的时候一并自动安装
分为开发环境和生产环境。生产环境在阿里云服务器。测试环境是本地windows电脑,写两套脚本
4.6.web端设计TODO
bash
1.首页是项目介绍,内容先留白,项目做完了再完善
2.用户登录、用户注册功能
3.不通用户登录有不同的权限,管理员是最高权限
4.用户管理页面,可对用户账号信息进行编辑;增加用户、删除用户、修改绑定信息、修改
5.固件管理,上传、删除固件功能
6.设备管理,删除设备,编辑设计,查看设备、批量新加设备、导入导出设备,新加设备需要给到设备信息
DeviceID:sc22430984,Secret:QNVKFuC07aPI+VYRyk3ZLg==,ProductKey:9rZJxganPKJRO2UY5AhBHA==...
7.设备详情页,查看和管理存储的设备数据、进入终端控制界面、固件升级
8.固件升级页,选择要升级的固件,进行升级。
9.终端页的功能参考workbench设计
10.普通用户登录只能看到设备管理页,无固件管理和用户管理页
11.个人中心
4.7.小程序端设计TODO
bash
1. 打开小程序,进入登录页面
注册新账号或使用已有账号登录
登录后自动进入设备列表页面
2. 绑定设备
在设备列表页点击"添加设备"
输入设备ID或扫描设备二维码
确认绑定后设备将显示在列表中
3. 查看设备
在设备列表中选择设备
进入设备详情页
点击"查看设备记录"进入设备记录页面
可选择查看设备串口传上来的数据
4. 管理设备
长按设备列表中的设备可进行管理
可选择重命名或解绑设备
设备详情页也提供设备管理功能
也可以对设备进行固件升级
可以上传设备照片,管理设备
5. 个人设置
在"我的"页面可查看个人信息
换头像
可修改密码
可退出登录
6.编写对接文档,方便服务端开发
4.8.windows 端设计TODO
bash
1.需要账号登陆
2.登陆后可以看到该账号下绑定的设备列表(对接服务器)
3.双击设备,可创建指定设备的虚拟串口
4.创建串口窗可配置串口号波特率等
5.设备连接进度显示,不弹窗,直接在设备列表的后方显示
6.右键选择设备,可删除虚拟串口,可进行数据监控
7.python 写 windows 客户端
8.为了避开签名,用户会预装com0com.直接调用。预装路径固定
9.新建虚拟串口对时,隐藏一个串口用来链接TCP服务器,这个串口命名不限制。另外一个串口名称需要和配置界面一致
9.日志,程序启动时根据时间戳创建日志,日志分等级方便调试分析
10.编写对接API文档,以便于服务端功能的开发
11.写个打包脚本。这个是打包脚本的参考代码
requirements.txt 是需要安装的库,版本必须是确定的
setup.bat 创建虚拟环境搭建运行环境
build.bat 将项目打包成EXE
run.bat 调试时,让python代码运行在虚拟环境里面
clean.bat 保存或者提交代码时清理过程文件和缓存文件