尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Vue3+SpringBoot全栈开发:从零构建蓝牙数据监控APP(含STM32端配置)

Vue3+SpringBoot全栈开发:从零构建蓝牙数据监控APP(含STM32端配置) Vue3SpringBoot全栈开发构建工业级蓝牙数据监控系统实战1. 项目架构设计与技术选型工业物联网场景下的设备监控系统需要兼顾实时性、稳定性和跨平台兼容性。我们采用以下技术栈构建完整的解决方案前端框架Vue3 TypeScript ViteUI组件库Element Plus管理后台 UniApp原生组件移动端后端服务Spring Boot 2.7 Spring Security数据持久化MySQL 8.0主存储 Redis 7.0缓存/会话嵌入式端STM32F103C8T6 HC-05蓝牙模块graph TD A[STM32传感器节点] --|蓝牙4.0| B(UniApp移动端) B --|HTTP/WebSocket| C[SpringBoot服务] C -- D[(MySQL)] C -- E[(Redis)] D -- F[管理后台]关键设计考量蓝牙通信选择HC-05模块而非BLE确保与老旧设备兼容采用EventBusWebSocket双通道保证数据实时性服务端使用JWTRBAC实现细粒度权限控制2. STM32端开发实战2.1 硬件环境搭建所需材料清单组件型号备注主控芯片STM32F103C8T6蓝色pill开发板蓝牙模块HC-05需进入AT模式配置传感器DHT11温湿度检测电源AMS11173.3V稳压接线示意图// 硬件接口定义 #define BT_TX PA9 // 蓝牙模块RX #define BT_RX PA10 // 蓝牙模块TX #define DHT_DATA PB12 // 传感器数据线2.2 数据采集与传输传感器数据采集核心代码void DHT11_Read(float *temp, float *humi) { uint8_t data[5] {0}; // 启动信号 GPIO_WriteBit(DHT_PORT, DHT_DATA, Bit_RESET); Delay_ms(18); GPIO_WriteBit(DHT_PORT, DHT_DATA, Bit_SET); // 等待响应 while(GPIO_ReadInputDataBit(DHT_PORT, DHT_DATA)); // 数据接收 for(int i0; i5; i) { for(int j0; j8; j) { while(!GPIO_ReadInputDataBit(DHT_PORT, DHT_DATA)); Delay_us(30); data[i] 1; if(GPIO_ReadInputDataBit(DHT_PORT, DHT_DATA)) data[i] | 1; while(GPIO_ReadInputDataBit(DHT_PORT, DHT_DATA)); } } *humi data[0] data[1]*0.1; *temp data[2] data[3]*0.1; }蓝牙数据传输协议设计字节含义示例值0起始符0xAA1-2温度值0x1A 0x033-4湿度值0x3C 0x005校验和0x596结束符0x553. 移动端开发关键实现3.1 蓝牙通信模块创建蓝牙服务封装类class BluetoothService { private static instance: BluetoothService; private deviceId: string ; private constructor() { this.initEventListeners(); } public static getInstance(): BluetoothService { if (!BluetoothService.instance) { BluetoothService.instance new BluetoothService(); } return BluetoothService.instance; } private initEventListeners() { uni.onBluetoothDeviceFound((res) { EventBus.emit(DEVICE_FOUND, res.devices); }); } public async scanDevices(): PromiseUniApp.BluetoothDevice[] { return new Promise((resolve) { const devices: UniApp.BluetoothDevice[] []; EventBus.on(DEVICE_FOUND, (foundDevices) { devices.push(...foundDevices); }); uni.startBluetoothDevicesDiscovery({ success: () { setTimeout(() { uni.stopBluetoothDevicesDiscovery(); resolve(devices); }, 5000); } }); }); } }3.2 实时数据可视化使用ECharts实现动态图表template view classchart-container ec-canvas refchart canvas-idbt-chart/ec-canvas /view /template script import * as echarts from /components/ec-canvas/echarts; export default { data() { return { chart: null, option: { dataset: { source: [] }, xAxis: { type: category }, yAxis: {}, series: [ { type: line, smooth: true }, { type: line, smooth: true } ] } } }, mounted() { this.initChart(); EventBus.on(BLUETOOTH_DATA, this.updateData); }, methods: { initChart() { this.chart echarts.init(this.$refs.chart, light); this.chart.setOption(this.option); }, updateData(payload) { const { temperature, humidity, timestamp } payload; this.option.dataset.source.push([timestamp, temperature, humidity]); if(this.option.dataset.source.length 50) { this.option.dataset.source.shift(); } this.chart.setOption(this.option); } } } /script4. 后端服务设计精要4.1 分布式架构设计SpringBootApplication EnableCaching EnableWebSocket public class MonitorApplication { public static void main(String[] args) { SpringApplication.run(MonitorApplication.class, args); } Bean public WebSocketHandlerAdapter handlerAdapter() { return new WebSocketHandlerAdapter(); } Bean public ServletServerContainerFactoryBean createWebSocketContainer() { ServletServerContainerFactoryBean container new ServletServerContainerFactoryBean(); container.setMaxTextMessageBufferSize(8192); container.setMaxBinaryMessageBufferSize(8192); return container; } }4.2 数据持久化优化JPA实体关系设计Entity Table(name sensor_data) DynamicUpdate public class SensorData { Id GeneratedValue(strategy GenerationType.IDENTITY) private Long id; Column(precision 5, scale 2) private BigDecimal temperature; Column(precision 5, scale 2) private BigDecimal humidity; Temporal(TemporalType.TIMESTAMP) private Date createTime; ManyToOne JoinColumn(name device_id) private Device device; } Entity Table(name devices) public class Device { Id private String macAddress; private String name; Enumerated(EnumType.STRING) private DeviceStatus status; OneToMany(mappedBy device) private ListSensorData dataRecords; }5. 性能优化与异常处理5.1 蓝牙连接稳定性方案重连机制实现class BluetoothReconnect { private maxRetries 3; private currentRetry 0; private timer: number | null null; constructor(private deviceId: string) {} public connect(): Promisevoid { return new Promise((resolve, reject) { uni.createBLEConnection({ deviceId: this.deviceId, success: () { this.reset(); resolve(); }, fail: (err) { this.handleRetry(err, resolve, reject); } }); }); } private handleRetry(err: any, resolve: Function, reject: Function) { if (this.currentRetry this.maxRetries) { this.currentRetry; this.timer setTimeout(() { this.connect().then(resolve).catch(reject); }, 2000 * this.currentRetry); } else { this.reset(); reject(new Error(连接失败: ${err.errMsg})); } } }5.2 服务端高并发处理配置Spring Boot异步处理Configuration EnableAsync public class AsyncConfig implements AsyncConfigurer { Override public Executor getAsyncExecutor() { ThreadPoolTaskExecutor executor new ThreadPoolTaskExecutor(); executor.setCorePoolSize(10); executor.setMaxPoolSize(50); executor.setQueueCapacity(1000); executor.setThreadNamePrefix(Async-); executor.initialize(); return executor; } } Service public class DataProcessingService { Async public void processIncomingData(DataPacket packet) { // 耗时数据处理逻辑 complexAnalysis(packet); saveToDatabase(packet); notifyWebClients(packet); } }6. 安全防护体系6.1 通信安全方案数据传输加密流程设备端生成AES-256密钥使用服务器RSA公钥加密AES密钥服务端用私钥解密获取AES密钥后续通信使用AES加密数据RestController RequestMapping(/api/auth) public class AuthController { PostMapping(/key-exchange) public ResponseEntityKeyResponse keyExchange(RequestBody KeyRequest request) { String encryptedKey request.getEncryptedKey(); String aesKey RSAUtil.decrypt(encryptedKey, privateKey); String sessionId UUID.randomUUID().toString(); redisTemplate.opsForValue().set( aes: sessionId, aesKey, 2, TimeUnit.HOURS ); return ResponseEntity.ok(new KeyResponse(sessionId)); } }6.2 权限控制实现动态权限注解Target(ElementType.METHOD) Retention(RetentionPolicy.RUNTIME) PreAuthorize(pms.check(${permission})) public interface RequiresPermission { String value(); } Service(pms) public class PermissionService { public boolean check(String permission) { Authentication auth SecurityContextHolder.getContext().getAuthentication(); UserDetails user (UserDetails) auth.getPrincipal(); return user.getAuthorities().stream() .anyMatch(g - g.getAuthority().equals(permission)); } }7. 部署与监控方案7.1 容器化部署Docker Compose配置示例version: 3.8 services: backend: build: ./server ports: - 8080:8080 environment: - SPRING_PROFILES_ACTIVEprod depends_on: - redis - mysql mysql: image: mysql:8.0 environment: MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASS} MYSQL_DATABASE: monitor volumes: - db_data:/var/lib/mysql redis: image: redis:7.0-alpine ports: - 6379:6379 prometheus: image: prom/prometheus ports: - 9090:9090 volumes: - ./monitoring/prometheus.yml:/etc/prometheus/prometheus.yml grafana: image: grafana/grafana ports: - 3000:3000 volumes: db_data:7.2 性能监控指标关键监控指标配置# prometheus.yml scrape_configs: - job_name: spring metrics_path: /actuator/prometheus static_configs: - targets: [backend:8080] labels: service: monitor-backend - job_name: redis static_configs: - targets: [redis:6379] - job_name: mysql static_configs: - targets: [mysql:3306]8. 项目演进路线技术演进路线图V1.0基础版单蓝牙设备连接基础数据展示本地用户系统V2.0增强版多设备组网支持数据异常预警OTA远程升级V3.0专业版边缘计算能力AI预测分析可视化规则引擎实际开发中发现蓝牙模块在工业环境下的抗干扰能力需要特别优化我们通过以下措施提升稳定性增加数据包校验重传机制采用自适应跳频算法实现信号强度动态监测添加设备心跳检测
返回列表