当前位置: 首页 > news >正文

鸿蒙TCPSocket通信模拟智能家居模拟案例

效果图

 

一、智能家居热潮下的鸿蒙契机

在当下科技飞速发展的时代,智能家居已如浪潮般席卷而来,深刻地改变着我们的生活方式。从能依据环境光线自动调节亮度的智能灯具,到可远程操控、精准控温的智能空调,再到实时监测健康数据的智能穿戴设备,智能家居产品如繁星般点缀着现代家庭,让生活愈发便捷、舒适与高效。

据权威数据显示,全球智能家居市场规模正以惊人的速度逐年攀升。2023 年,全球拥有智能家居设备的家庭数量已高达 3.61 亿户,市场销售收入更是接近 1400 亿美元。在国内,智能家居行业同样蓬勃发展,营收规模从 2018 年的 1.87 万亿跃升至 2022 年的 2.33 万亿元。英国以 45.83% 的智能家居渗透率位居全球之首,美国也达到了 43.80%,尽管我国目前的渗透率仅为 16.63%,但随着技术的日益成熟与消费者需求的迅猛增长,未来的发展潜力不可限量。

在这股智能家居的热潮中,华为鸿蒙系统崭露头角,成为了众多消费者与开发者瞩目的焦点。鸿蒙系统凭借其独特的分布式架构设计理念,打破了设备之间的隔阂,让数据能够自由、高效地流通共享。想象一下,你只需通过手机,便能轻松掌控家中的智能灯泡、空调、安全监控系统等各类设备,实现无缝对接的智能化交互体验。更为惊艳的是,鸿蒙系统融入的人工智能技术,能深度学习用户的日常习惯,提前为你调整好设备状态。例如,它会记住你每晚十点关闭客厅灯光的习惯,久而久之,为你量身打造出一个专属的智能家居生态圈。

众多行业专家也对鸿蒙系统在智能家居领域的表现给予了高度评价。技术分析师李华指出:“华为鸿蒙系统的推出代表了中国科技公司在全球市场中的一次重要跃进,是人工智能与传统家居领域结合的典范。” 它不仅为智能家居带来了前所未有的技术进步,更为用户开启了全新的智能生活体验之门。

 二、鸿蒙系统与 TCPSocket 初相识

(一)鸿蒙系统架构精析

鸿蒙系统以其独特精妙的架构设计傲立科技潮头。从底层逐步向上剖析,内核层作为基石,犹如精密的发动机,掌控着硬件资源调配、进程精细调度、内存高效管理以及文件系统的稳健运作,为上层建筑筑牢根基,确保系统平稳、高效运行。系统服务层宛如万能工具库,涵盖电源管理、网络调配、安全护卫、图形渲染、音频处理等多样功能模块,为框架层与应用层输送源源不断的强大助力,大幅削减重复开发的繁琐工序。框架层恰似贴心向导,为开发者精心打造开发框架与便捷的 API 接口,降低开发门槛,提速开发进程,无论是 UI 界面的精美搭建,还是数据管理的有序组织,亦或是通信连接的顺畅保障,都能轻松驾驭。最上层的应用层,则是百花齐放的舞台,各类应用程序琳琅满目,满足用户多元需求。

这种分层架构的优势显著。模块化特性使得各层相对独立,恰似积木拼图,开发人员可聚焦某一层级深耕细作,维护升级时也能精准定位,互不干扰,极大提升开发效率与系统稳定性。可扩展性更是一绝,以智能家居开发为例,随着新设备、新功能不断涌现,各层能够灵活应变,轻松拓展,随时接纳智能门锁、空气净化器等新成员融入智能家居大家庭,为用户带来持续升级的智慧体验。安全性方面,层层设防,严格隔离,如坚固堡垒,从内核层的底层防护,到系统服务层的权限管控,再到框架层与应用层的数据加密,全方位守护用户隐私与系统安全,让用户无后顾之忧。

(二)TCPSocket 通信解密

在网络通信的浩瀚星空中,TCP 协议无疑是一颗最为耀眼的恒星。它遵循着一套严谨且精妙的规则,致力于在复杂多变、充满不确定性的网络环境中,搭建起一条稳固可靠的数据传输高速公路。

TCP 协议的工作原理好似一场精心编排的舞蹈。在数据传输的序曲奏响之前,双方必先通过三次握手来建立连接,这是确保通信顺畅的重要前奏。客户端率先发送带有 SYN 标志的同步报文段,向服务器热情 “打招呼”,表明自己的通信意愿;服务器收到后,迅速响应,回以 SYN + ACK 报文段,既确认客户端的请求,又发出自己的同步信号;客户端再发送 ACK 报文段,至此,双方确认彼此身份,连接正式建立,犹如两位舞者携手步入舞池,准备共舞。

进入数据传输阶段,TCP 为每个数据包精心标注序号,就像为信件编号一样,确保接收方能够按照正确顺序重组信息,避免乱序带来的混乱。同时,接收方每成功接收一个数据包,便会即刻发送 ACK 确认报文,告知发送方数据已安全 “着陆”。倘若发送方在预设的时间内未收到确认,便会敏锐察觉可能出现的丢包情况,迅速启动重传机制,补发丢失的数据包,犹如快递员发现包裹未送达,及时折返重新派送,确保信息不遗漏。

与 UDP 协议相比,TCP 的可靠性优势尽显。UDP 如同风一般自由随性,它是无连接的,数据发送后便 “不管不顾”,虽然传输效率颇高,能快速将数据送出,但在网络状况不佳时,极易出现丢包、乱序等问题,如同信件在风中飘散,难以保证完整送达。而 TCP 恰似忠诚的信使,凭借连接管理、确认应答、超时重传等一系列严谨机制,确保信件准确无误地递交到收件人手中,数据完整性与顺序性得到坚实保障。

在智能家居场景中,TCP 的可靠性更是不可或缺。以智能摄像头为例,它实时捕捉家中的画面,通过网络传输至用户手机端。若采用不可靠的 UDP 协议,画面可能出现卡顿、花屏甚至丢失关键信息等状况,让用户无法及时掌握家中动态,安防功能大打折扣;而 TCP 协议则能稳稳地传输每一帧画面,让用户清晰、流畅地查看家中实时情况,为家庭安全保驾护航。又如智能窗帘的控制指令传输,TCP 确保指令准确执行,避免窗帘开合失常,为用户营造舒适便捷的家居环境。

三、实战!模拟智能家居搭建全流程

(一)开发环境巧搭建

工欲善其事,必先利其器。在开启鸿蒙智能家居开发之旅前,精心搭建完备的开发环境至关重要。

硬件层面,鸿蒙开发板是关键所在。以润和 Hi3861 开发板为例,它凭借小巧灵活、功耗低微且性能稳定的特性备受青睐。其内置高性能处理器,能够快速、精准地处理各类智能家居指令,无论是控制灯光的细微亮度调节,还是空调的复杂温度调控,都能轻松应对。丰富的接口更是一绝,GPIO 接口可便捷连接各类传感器与执行器,像智能温湿度传感器、智能窗帘电机等,为智能家居设备的拓展提供了无限可能;Wi-Fi 模块确保设备稳定接入网络,实现远程通信与控制,让你即便身处千里之外,也能随心掌控家中设备。

软件方面,鸿蒙 SDK 与 DevEco Studio 堪称两大得力助手。鸿蒙 SDK 如同百宝箱,涵盖了丰富多样的开发工具、类库以及 API 接口,为开发者提供了全方位的开发支持。从基础的系统功能调用,到复杂的分布式通信实现,都能在其中找到对应的资源。DevEco Studio 则是基于 IntelliJ IDEA Community 开源版本精心打造的一站式集成开发环境(IDE)。它界面友好、操作便捷,为开发者提供了从工程模板创建、代码编写、调试测试,到最终应用发布的全流程服务。其智能代码提示功能,如同贴心助手,能在你编写代码时快速给出精准建议,大幅提升开发效率;强大的调试工具,能够帮助你迅速定位并解决代码中的问题,确保开发进程顺利推进。

(二)代码编写分步走

1. 界面设计展风貌

利用 ArkUI 进行交互界面设计,为用户打造便捷舒适的操控体验。想象一下,当你打开智能家居控制应用,映入眼帘的是布局合理、美观大方的操作界面。以下是部分关键代码示例:

客户端:

import { ToggleCom } from '../commons/component/toggleCom';
import { SWITCH } from '../commons/constant/switchCon';
import { tcpUtils } from '../commons/utils/tcpUtils';@Entry
@Component
struct TcpClientPage {//连接状态@State connectState: boolean = false;//客厅开关@State KTState: boolean = false;//卧室开关@State WSState: boolean = false;//卫生间开关@State CSState: boolean = false;@State@Watch('msgChange')msg: string = ''intervalID = -1@State WSD: boolean = false@State WSK: boolean = false@State WST: boolean = false@State WSC: boolean = false@State KTD: boolean = false@State KTK: boolean = false@State KTT: boolean = false@State KTC: boolean = false@State CSD: boolean = false@State CSR: boolean = false// 页面初始化aboutToAppear() {this.connectServer();}//连接服务器async connectServer() {// 绑定本地IPawait tcpUtils.bindLocalIP();// 连接服务器await tcpUtils.connectServer();// 监听连接状态this.connectState = tcpUtils.connectState;// 监听服务器消息this.intervalID = setInterval(() => {this.msgChange()}, 300)}msgChange() {if (tcpUtils.serverMessage.length > 0) {this.msg = tcpUtils.serverMessagethis.switchChange()this.totalChange()tcpUtils.serverMessage = ''}}switchChange() {switch (this.msg) {case SWITCH.WSD_ON:this.WSD = truethis.WSState = truebreakcase SWITCH.WSD_OFF:this.WSD = falsebreakcase SWITCH.WSK_ON:this.WSK = truethis.WSState = truebreakcase SWITCH.WSK_OFF:this.WSK = falsebreakcase SWITCH.WST_ON:this.WST = truethis.WSState = truebreakcase SWITCH.WST_OFF:this.WST = falsebreakcase SWITCH.WSC_ON:this.WSC = truethis.WSState = truebreakcase SWITCH.WSC_OFF:this.WSC = falsebreakcase SWITCH.KTD_ON:this.KTD = truethis.KTState = truebreakcase SWITCH.KTD_OFF:this.KTD = falsebreakcase SWITCH.KTK_ON:this.KTK = truethis.KTState = truebreakcase SWITCH.KTK_OFF:this.KTK = falsebreakcase SWITCH.KTT_ON:this.KTT = truethis.KTState = truebreakcase SWITCH.KTT_OFF:this.KTT = falsebreakcase SWITCH.KTC_ON:this.KTC = truethis.KTState = truebreakcase SWITCH.KTC_OFF:this.KTC = falsebreakcase SWITCH.CSD_ON:this.CSD = truethis.CSState = truebreakcase SWITCH.CSD_OFF:this.CSD = falsebreakcase SWITCH.CSR_ON:this.CSR = truethis.CSState = truebreakcase SWITCH.CSR_OFF:this.CSR = falsebreakdefault:break}}totalChange() {if (!this.WSD && !this.WSK && !this.WST && !this.WSC) {this.WSState = false}if (!this.KTD && !this.KTK && !this.KTT && !this.KTC) {this.KTState = false}if (!this.CSD && !this.CSR) {this.CSState = false}}build() {Column({ space: 20 }) {// 标题栏Row() {Text('智能家居控制面板').textAlign(TextAlign.Start).fontWeight(FontWeight.Bold).fontSize(25).fontColor('#ffb1a67c').width('60%')Row({ space: 5 }) {Text(this.connectState ? "在线" : "离线").textAlign(TextAlign.End).fontWeight(FontWeight.Bold).fontSize(20).fontColor(this.connectState ? Color.Green : Color.Gray).width(48)Text('').backgroundColor(this.connectState ? Color.Green : Color.Gray).width(12).height(12).borderRadius(6)}.justifyContent(FlexAlign.Center).border({color: Color.Black,width: 1.8,radius: 15}).width(80).height(30).onClick(() => {if (!this.connectState) {this.connectServer();} else {tcpUtils.connectClose();}this.connectState = !this.connectState;})}// 内容区ToggleCom({title: "卧室    总开关",txtOn: SWITCH.WS_ON,txtOff: SWITCH.WS_OFF,isSwitch: this.WSState,connectState: this.connectState,onSwitch: () => {this.WSState = !this.WSState;this.WSD = this.WSStatethis.WSK = this.WSStatethis.WST = this.WSStatethis.WSC = this.WSState}})Row({ space: 5 }) {ToggleCom({isSwitch: this.WSD,txtOn: SWITCH.WSD_ON,txtOff: SWITCH.WSD_OFF,connectState: this.connectState,onSwitch: () => {this.WSState = truethis.WSD =!this.WSD;this.totalChange()}})ToggleCom({isSwitch: this.WSK,txtOn: SWITCH.WSK_ON,txtOff: SWITCH.WSK_OFF,connectState: this.connectState,ImgOn: $r('app.media.air_on'),ImgOff: $r('app.media.air_off'),onSwitch: () => {this.WSState = truethis.WSK =!this.WSK;this.totalChange()}})}Row({ space: 5 }) {ToggleCom({isSwitch: this.WST,txtOn: SWITCH.WST_ON,txtOff: SWITCH.WST_OFF,connectState: this.connectState,ImgOn: $r('app.media.lamp_on'),ImgOff: $r('app.media.lamp_off'),onSwitch: () => {this.WSState = truethis.WST =!this.WST;this.totalChange()}})ToggleCom({isSwitch: this.WSC,txtOn: SWITCH.WSC_ON,txtOff: SWITCH.WSC_OFF,connectState: this.connectState,ImgOn: $r('app.media.curtain_on'),ImgOff: $r('app.media.curtain_off'),onSwitch: () => {this.WSState = truethis.WSC =!this.WSC;this.totalChange()}})}ToggleCom({title: "客厅    总开关",txtOn: SWITCH.KT_ON,txtOff: SWITCH.KT_OFF,isSwitch: this.KTState,connectState: this.connectState,onSwitch: () => {this.KTState = !this.KTState;this.KTD = this.KTStatethis.KTK = this.KTStatethis.KTT = this.KTStatethis.KTC = this.KTState}})Row({ space: 5 }) {ToggleCom({isSwitch: this.KTD,txtOn: SWITCH.KTD_ON,txtOff: SWITCH.KTD_OFF,connectState: this.connectState,onSwitch: () => {this.KTState = truethis.KTD =!this.KTD;this.totalChange()}})ToggleCom({isSwitch: this.KTK,txtOn: SWITCH.KTK_ON,txtOff: SWITCH.KTK_OFF,ImgOn: $r('app.media.air_on'),ImgOff: $r('app.media.air_off'),onSwitch: () => {this.KTState = truethis.KTK = !this.KTK;this.totalChange()}})}Row({ space: 5 }) {ToggleCom({isSwitch: this.KTT,txtOn: SWITCH.KTT_ON,txtOff: SWITCH.KTT_OFF,connectState: this.connectState,ImgOn: $r('app.media.tv_on'),ImgOff: $r('app.media.tv_off'),onSwitch: () => {this.KTState = truethis.KTT =!this.KTT;this.totalChange()}})ToggleCom({isSwitch: this.KTC,txtOn: SWITCH.KTC_ON,txtOff: SWITCH.KTC_OFF,connectState: this.connectState,ImgOn: $r('app.media.curtain_on'),ImgOff: $r('app.media.curtain_off'),onSwitch: () => {this.KTState = truethis.KTC =!this.KTC;this.totalChange()}})}ToggleCom({title: "卫生间   总开关",txtOn: SWITCH.CS_ON,txtOff: SWITCH.CS_OFF,isSwitch: this.CSState,connectState: this.connectState,onSwitch: () => {this.CSState = !this.CSState;this.CSD = this.CSStatethis.CSR = this.CSState}})Row({ space: 5 }) {ToggleCom({connectState: this.connectState,isSwitch: this.CSD,txtOn: SWITCH.CSD_ON,txtOff: SWITCH.CSD_OFF,onSwitch: () => {this.CSState = truethis.CSD =!this.CSD;this.totalChange()}})ToggleCom({isSwitch: this.CSR,txtOn: SWITCH.CSR_ON,txtOff: SWITCH.CSR_OFF,connectState: this.connectState,ImgOn: $r('app.media.water_on'),ImgOff: $r('app.media.water_off'),onSwitch: () => {this.CSState = truethis.CSR =!this.CSR;this.totalChange()}})}}.height('100%').width('100%').backgroundColor('#F4F3EF')}
}

服务端:

import { ToggleCom } from '../commons/component/toggleCom';
import { SWITCH } from '../commons/constant/switchCon';
import { tcpUtils } from '../commons/utils/tcpUtils';@Entry
@Component
struct TcpServerPage {@State@Watch('msgChange')msg: string = ''intervalID = -1@State WSD: boolean = false@State WSK: boolean = false@State WST: boolean = false@State WSC: boolean = false@State KTD: boolean = false@State KTK: boolean = false@State KTT: boolean = false@State KTC: boolean = false@State CSD: boolean = false@State CSR: boolean = falseaboutToAppear() {tcpUtils.listenServer()this.intervalID = setInterval(() => {this.msgChange()}, 300)}msgChange() {if (tcpUtils.messageData.length > 0) {this.msg = tcpUtils.messageDatathis.switchChange()}}switchChange() {switch (this.msg) {case SWITCH.WS_ON:this.WSD = truethis.WSK = truethis.WST = truethis.WSC = truebreakcase SWITCH.WS_OFF:this.WSD = falsethis.WSK = falsethis.WST = falsethis.WSC = falsebreakcase SWITCH.KT_ON:this.KTD = truethis.KTK = truethis.KTT = truethis.KTC = truebreakcase SWITCH.KT_OFF:this.KTD = falsethis.KTK = falsethis.KTT = falsethis.KTC = falsebreakcase SWITCH.CS_ON:this.CSD = truethis.CSR = truebreakcase SWITCH.CS_OFF:this.CSD = falsethis.CSR = falsebreakcase SWITCH.WSD_ON:this.WSD = truebreakcase SWITCH.WSD_OFF:this.WSD = falsebreakcase SWITCH.WSK_ON:this.WSK = truebreakcase SWITCH.WSK_OFF:this.WSK = falsebreakcase SWITCH.WST_ON:this.WST = truebreakcase SWITCH.WST_OFF:this.WST = falsebreakcase SWITCH.WSC_ON:this.WSC = truebreakcase SWITCH.WSC_OFF:this.WSC = falsebreakcase SWITCH.KTD_ON:this.KTD = truebreakcase SWITCH.KTD_OFF:this.KTD = falsebreakcase SWITCH.KTK_ON:this.KTK = truebreakcase SWITCH.KTK_OFF:this.KTK = falsebreakcase SWITCH.KTT_ON:this.KTT = truebreakcase SWITCH.KTT_OFF:this.KTT = falsebreakcase SWITCH.KTC_ON:this.KTC = truebreakcase SWITCH.KTC_OFF:this.KTC = falsebreakcase SWITCH.CSD_ON:this.CSD = truebreakcase SWITCH.CSD_OFF:this.CSD = falsebreakcase SWITCH.CSR_ON:this.CSR = truebreakcase SWITCH.CSR_OFF:this.CSR = falsebreakdefault:break}}build() {Column({ space: 20 }) {// 标题栏Row() {Text('智能家居模拟家电').textAlign(TextAlign.Start).fontWeight(FontWeight.Bold).fontSize(25).fontColor('#ffb1a67c').width('60%')}// 内容区ToggleCom({title: "卧室 "})Row({ space: 5 }) {ToggleCom({isSwitch: this.WSD,txtOn: SWITCH.WSD_ON,txtOff: SWITCH.WSD_OFF,})ToggleCom({isSwitch: this.WSK,txtOn: SWITCH.WSK_ON,txtOff: SWITCH.WSK_OFF,ImgOn: $r('app.media.air_on'),ImgOff: $r('app.media.air_off')})}Row({ space: 5 }) {ToggleCom({isSwitch: this.WST,txtOn: SWITCH.WST_ON,txtOff: SWITCH.WST_OFF,ImgOn: $r('app.media.lamp_on'),ImgOff: $r('app.media.lamp_off')})ToggleCom({isSwitch: this.WSC,txtOn: SWITCH.WSC_ON,txtOff: SWITCH.WSC_OFF,ImgOn: $r('app.media.curtain_on'),ImgOff: $r('app.media.curtain_off')})}ToggleCom({title: "客厅",})Row({ space: 5 }) {ToggleCom({isSwitch: this.KTD,txtOn: SWITCH.KTD_ON,txtOff: SWITCH.KTD_OFF,})ToggleCom({isSwitch: this.KTK,txtOn: SWITCH.KTK_ON,txtOff: SWITCH.KTK_OFF,ImgOn: $r('app.media.air_on'),ImgOff: $r('app.media.air_off')})}Row({ space: 5 }) {ToggleCom({isSwitch: this.KTT,txtOn: SWITCH.KTT_ON,txtOff: SWITCH.KTT_OFF,ImgOn: $r('app.media.tv_on'),ImgOff: $r('app.media.tv_off')})ToggleCom({isSwitch: this.KTC,txtOn: SWITCH.KTC_ON,txtOff: SWITCH.KTC_OFF,ImgOn: $r('app.media.curtain_on'),ImgOff: $r('app.media.curtain_off')})}ToggleCom({title: "卫生间"})Row({ space: 5 }) {ToggleCom({isSwitch: this.CSD,txtOn: SWITCH.CSD_ON,txtOff: SWITCH.CSD_OFF,})ToggleCom({isSwitch: this.CSR,txtOn: SWITCH.CSR_ON,txtOff: SWITCH.CSR_OFF,ImgOn: $r('app.media.water_on'),ImgOff: $r('app.media.water_off')})}}.height('100%').width('100%').backgroundColor('#F4F3EF')}}

 在上述代码中,通过Column和Row组件巧妙布局,将灯光、窗帘、空调等设备的控制按钮有序排列。@State装饰器用于绑定设备状态,使其能够实时响应变化并在界面上精准展示。每个按钮的onClick事件则为后续添加控制逻辑预留了接口,为实现设备的远程操控搭建了基础框架。

2. TCPSocket 通信代码实现

在鸿蒙系统中,借助@ohos.net.socket模块实现 TCPSocket 通信。核心代码如下:

客户端:

import { socket } from '@kit.NetworkKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { buf2S } from './buftoString';class TcpUtils {// 2. **创建连接:**创建一个 TCPSocket 连接,返回一个 TCPSocket 对象。tcpConnect: socket.TCPSocket = socket.constructTCPSocketInstance();localIp: string = '127.0.0.1';localPort: number = 4651serverIp: string = '127.0.0.1';serverPort: number = 8000bindState: string = "未绑定"connectState: boolean = falsesendMessage: string = ''serverMessage: string = ''canSend: boolean = false// 4. **绑定IP和端口:**绑定 IP 地址和端口,端口可以指定或由系统随机分配。async bindLocalIP() {// 绑定本地IP地址和端口。let ipAddress: socket.NetAddress = {address: this.localIp,port: this.localPort,// 1: IPv4, 2: IPv6family: 1}await this.tcpConnect.bind(ipAddress).then(() => {console.info('===bind success!===');this.bindState = "bind success!"}).catch((err: BusinessError) => {console.info('===bind failed!===', JSON.stringify(err));})}async connectServer() {let serverAddress: socket.NetAddress = {} as socket.NetAddress;serverAddress.address = this.serverIp;serverAddress.port = this.serverPort;serverAddress.family = 1await this.tcpConnect.connect({ address: serverAddress })//三次握手.then(() => {console.info('===connect success!=== ')this.canSend = truethis.connectState = true3. (**可选**)订阅 TCPSocket 相关的订阅事件。接收数据//收到消息时的处理this.tcpConnect.on("message", async (value: socket.SocketMessageInfo) => {let msg: string = buf2S.buf2String(value.message)console.info("===服务端:" + msg)this.serverMessage = msg})}).catch((err: BusinessError) => {console.info('===connect fail!===' + JSON.stringify(err))})}// 6. **通信:**  发送消息到服务端。sendData(message: string) {if (this.canSend) {this.tcpConnect.send({ data: message })//data的数据格式可以定制.then(async () => {console.info('===数据发送成功!===')}).catch(() => {console.info('===数据发送失败!===')})}}// 7. **断开连接:**Socket 连接使用完毕后,主动关闭。connectClose() {this.tcpConnect.close(() => {console.info('===closed!===')this.connectState = false})}
}export const tcpUtils = new TcpUtils()

服务端:

import { socket } from '@kit.NetworkKit';
import { BusinessError, emitter } from '@kit.BasicServicesKit';class SocketInfo {message: ArrayBuffer = new ArrayBuffer(1);remoteInfo: socket.SocketRemoteInfo = {} as socket.SocketRemoteInfo;
}class TcpUtils {tcpServer: socket.TCPSocketServer = socket.constructTCPSocketServerInstance();serverIp: string = '127.0.0.1'serverPort: number = 8000serverData: string = ''//接收到的消息messageData: string = "";private connectState: boolean = falseprivate tcpSocketConnection ?: socket.TCPSocketConnectionasync listenServer() {let ipAddress: socket.NetAddress = {address: this.serverIp,port: this.serverPort,}// 绑定IP:Port、监听并启动服务,接收客户端的连接请求this.tcpServer.listen(ipAddress).then(() => {console.info('===listen success===');this.tcpServer.on("connect", (tcpConnection: socket.TCPSocketConnection) => {console.info("===connect success====")this.connectState = truethis.tcpSocketConnection = tcpConnectiontcpConnection.on("message", (data: SocketInfo) => {console.info("====receive message====")let buffer = data.message;let dataView = new DataView(buffer);this.messageData = ""for (let i = 0; i < dataView.byteLength; ++i) {this.messageData += String.fromCharCode(dataView.getUint8(i));}console.log("===" + this.messageData)});// 订阅TCPSocketConnection相关的事件tcpConnection.on("close", () => {console.info("===断开连接===");});})}).catch((err: BusinessError) => {console.info('listen fail', JSON.stringify(err));});}async sendData(message: string) {if (this.connectState) { //连接成功才可发送数据// 服务端给连接的客户端发送信息let tcpSendOptions: socket.TCPSendOptions = {} as socket.TCPSendOptions;tcpSendOptions.data = messagethis.tcpSocketConnection?.send(tcpSendOptions).then(() => {console.info('===send success===');})}}
}export const tcpUtils = new TcpUtils()

 这段代码清晰地展现了 TCPSocket 通信的关键步骤。首先,通过constructTCPSocketInstance创建套接字实例,这是通信的起点。接着,使用bind方法绑定本地 IP 地址与端口,确保设备在网络中的标识唯一,如同为设备在网络世界中找到一个专属的 “停车位”。然后,connect方法用于与服务器建立连接,打通数据传输的通道。on方法实现接收消息的监听,一旦有数据从服务器传来,便能及时捕捉并处理。最后,send方法则用于向服务器发送数据,实现设备与服务器之间的双向通信。

3. 设备控制逻辑显神通

以控制智能灯光设备为例,结合 TCPSocket 通信实现设备控制逻辑。当用户在界面点击灯光 “打开” 按钮时,执行如下代码:

 totalChange() {if (!this.WSD && !this.WSK && !this.WST && !this.WSC) {this.WSState = false}if (!this.KTD && !this.KTK && !this.KTT && !this.KTC) {this.KTState = false}if (!this.CSD && !this.CSR) {this.CSState = false}}

在这段代码中,定义了一个名为 totalChange 的函数。这个函数的作用是根据各个子开关的状态来更新总开关的状态。具体来说,如果所有的卧室设备开关(WSD、WSK、WST、WSC)都处于关闭状态,那么卧室总开关(WSState)也会被设置为关闭状态。同样,如果所有的客厅设备开关(KTD、KTK、KTT、KTC)都处于关闭状态,那么客厅总开关(KTState)也会被设置为关闭状态。最后,如果窗帘开关(CSD)或窗帘复位开关(CSR)中有一个处于关闭状态,那么窗帘总开关(CSState)也会被设置为关闭状态。
这个函数的实现逻辑清晰,通过检查各个子开关的状态来决定总开关的状态。这种设计可以确保总开关的状态能够准确反映所有子开关的状态,从而实现对整个系统的有效控制

四、案例优化与拓展探索

(一)性能瓶颈巧突破

随着智能家居设备数量的不断增加,系统可能面临多设备连接下的延迟、卡顿等性能瓶颈。例如,当家中同时有多个智能设备频繁向服务器发送或接收数据时,网络带宽可能会出现拥堵,如同上下班高峰期的城市道路,数据传输受阻,导致控制指令延迟执行,用户体验大打折扣。

为优化性能,可从多方面入手。一方面,优化数据传输格式,采用精简高效的 JSON 或二进制格式替代冗长的数据格式,减少数据传输量,就像将货物精简打包后运输,提高传输效率;另一方面,合理设置缓冲区大小,根据设备实际需求动态调整,避免数据溢出或等待时间过长,确保数据传输平稳流畅。此外,引入数据缓存机制,对于频繁访问的数据如设备状态信息,存储在本地缓存中,下次请求时可直接从缓存读取,减少与服务器的交互次数,加快响应速度,如同在本地设立了一个小型数据仓库,随时满足快速取用的需求。

(二)功能拓展创无限

为使智能家居系统更加智能便捷,可进一步拓展功能。想象一下,清晨醒来,你无需动手操作手机,只需轻声说出 “打开卧室灯光,拉开窗帘”,智能系统便能精准识别你的语音指令,为你开启活力满满的一天;夜晚回家,一句 “开启观影模式”,灯光自动调暗,窗帘缓缓拉上,电视播放你喜爱的节目,让你瞬间放松身心。

要实现语音控制功能,可借助鸿蒙系统的语音识别与语义解析能力。通过集成语音识别引擎,将用户的语音指令转化为文本,再利用语义解析技术提取关键信息,与预设的控制指令匹配,最后通过 TCPSocket 通信发送给相应设备执行操作。例如,当识别到 “打开客厅灯” 的语音指令,解析后找到对应的灯光设备控制代码,发送开灯指令,灯光随即亮起。

场景模式的实现则需建立不同场景下设备状态的预设集合。以 “睡眠模式” 为例,系统将灯光亮度调至最暗、关闭不必要电器、设置空调适宜睡眠的温度等,用户一键切换场景,即可享受全方位的智能服务。这需要在代码层面精心设计场景切换逻辑,关联多个设备的控制指令,为用户打造个性化、沉浸式的智能家居体验。

五、项目复盘与未来展望

回顾整个项目历程,诸多难点犹如崎岖山路,考验着开发者的智慧与毅力。在鸿蒙系统学习初期,其独特的分布式架构与全新的开发理念,宛如神秘的知识迷宫,让人一时摸不着头脑。但随着深入钻研,如同拨云见日,逐步领悟到其精妙之处,为后续开发点亮了明灯。

TCPSocket 通信的实现过程也并非一帆风顺。不同设备间的网络适配问题频出,就像为性格各异的人挑选合身衣物,需反复调试参数,确保通信顺畅。在设备控制逻辑与界面交互的衔接环节,也常出现 “沟通不畅” 的状况,按钮点击后无响应或延迟响应,让人头疼不已。经过无数次的代码审查、逻辑梳理,才使得两者默契配合,实现流畅操控。

展望未来,鸿蒙在智能家居领域的前景一片光明。随着技术的持续升级,智能家居系统将愈发智能、便捷、人性化。想象一下,未来的智能家居系统能够依据你的情绪状态自动调节环境氛围,当你疲惫时,柔和的灯光、舒缓的音乐随即开启;借助更强大的人工智能算法,精准预测你的生活需求,提前准备好热水、调整室内温度;在安全防护层面,与智能安防系统深度融合,一旦有异常情况,立即联动报警并推送详细信息至你的手机。

鸿蒙系统将如同一颗闪耀的火种,点燃智能家居领域创新的燎原之火,引领我们迈向一个更加智能、美好的生活时代,让家真正成为温馨、舒适、智慧的港湾。

六、TCPSocket通信拓展

Socket 连接:主要是通过 Socket 进行数据传输,支持 TCP/UDP/Multicast/TLS 协议。
Socket:套接字,就是对网络中不同主机上的应用进程之间进行双向通信的端点的抽象。
TCP:传输控制协议(Transmission Control Protocol)。是一种面向连接的、可靠的、基于字节流的传输层通信协议。
UDP:用户数据报协议(User Datagram Protocol)。是一个简单的面向消息的传输层,不需要连接。
应用场景,如
客户端:应用通过 TCP/UDP Socket进行数据传输
服务端:应用通过 TCP Socket Server 进行数据传输.鸿蒙操作系统中,Socket 连接主要由 socket模块提供,模块提供了多种API供开发者调用。

TCP客户端

TCP客户端实现的流程:
1.导入库: import 需要的 socket 模块。
2.创建连接:创建一个 TCPSocket 连接,返回一个 TCPSocket 对象。
3.(可选)订阅 TCPSocket 相关的订阅事件。
4.绑定IP和端口: 绑定 『 地址和端口,端口可以指定或由系统随机分配。
5.连接服务器:连接到指定的 IP 地址和端口。
6.发送消息:发送数据。
7.断开连接: Socket连接使用完毕后,主动关闭。
涉及的API以及功能说明:

TCP服务端

1.import 需要的 socket 模块。
2.创建一个 TCPSocketServer 连接,返回一个 TCPSocketServer 对象。
3.绑定本地 IP 地址和端口,监听并接受与此套接字建立的客户端 TCPSocket 连接。
4.订阅 TCPSocketServer 的 connect 事件,用于监听客户端的连接状态。
5.客户端与服务端建立连接后,返回一个 TCPSocketConnection 对象,用于与客户端通信。
6.订阅 TCPSocketConnection 相关的事件,通过 TCPSocketConnection 向客户端发送数据。
7.主动关闭与客户端的连接。
8.取消 TCPSocketConnection 和 TCPSocketServer 相关事件的订阅。

本地模拟器做服务端 

IP端口映射

以管理员身份运行命令提示符

电脑IP和本地模拟器IP端口映射
在命令行输入以下代码

netsh interface portproxy add v4tov4 listenaddress=你的电脑的IP地址 listenport=8888 connectaddress=127.0.0.1 connectport=8000

不知道ip地址可以输入 ipconfig

显示映射结果

netsh interface portproxy show v4tov4

设置端口转发

首先启动本地模拟器
在进行端口转发前,一定要先启动本地模拟器,即 本地模拟器每次重启都需要重新设备端口转发

接下来需要配置鸿蒙模拟器端口转发,使用HDC命令操作,需要用到hdc.exe文件,该文件在OpenHarmony SDK目录下的\toolchains目录内部找到(每个人的路径不同),需要记住该目录。例如我的电脑上hdc.exe的路径:

 

进入toolchains目录,在命令行执行以下命令进行端口转发:
注意:本地模拟器每次重启都需要重新进行端口转发 

hdc.exe -t 127.0.0.1:5555 fport tcp:8000 tcp:8000

配置环境变量 (可能需要)
OHOS_HDC_SERVER_PORT

相关文章:

鸿蒙TCPSocket通信模拟智能家居模拟案例

效果图 一、智能家居热潮下的鸿蒙契机 在当下科技飞速发展的时代&#xff0c;智能家居已如浪潮般席卷而来&#xff0c;深刻地改变着我们的生活方式。从能依据环境光线自动调节亮度的智能灯具&#xff0c;到可远程操控、精准控温的智能空调&#xff0c;再到实时监测健康数据的智…...

【Spring Boot 实现 PDF 导出】

Spring Boot 实现 PDF 导出 在Spring Boot应用程序中实现PDF导出功能&#xff0c;可以选择多种库和技术栈。每种方法都有其优缺点&#xff0c;适用于不同的场景。以下是四种常见的方式&#xff1a;iText、Apache PDFBox、JasperReports 和 Thymeleaf Flying Saucer。我将详细…...

【Python】selenium结合js模拟鼠标点击、拦截弹窗、鼠标悬停方法汇总(使用 execute_script 执行点击的方法)

我们在写selenium获取网络信息的时候&#xff0c;有时候我们会受到对方浏览器的监控&#xff0c;对方通过分析用户行为模式&#xff0c;如点击、滚动、停留时间等&#xff0c;网站可以识别出异常行为&#xff0c;进而对Selenium爬虫进行限制。 这里我们可以加入JavaScript的使…...

leetcode hot 100 前k个高平元素

347. 前 K 个高频元素 已解答 中等 相关标签 相关企业 给你一个整数数组 nums 和一个整数 k &#xff0c;请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。 class Solution(object):def topKFrequent(self, nums, k):""":type nums: Lis…...

数据结构漫游记:静态双向链表

嘿&#xff0c;各位技术潮人&#xff01;好久不见甚是想念。生活就像一场奇妙冒险&#xff0c;而编程就是那把超酷的万能钥匙。此刻&#xff0c;阳光洒在键盘上&#xff0c;灵感在指尖跳跃&#xff0c;让我们抛开一切束缚&#xff0c;给平淡日子加点料&#xff0c;注入满满的pa…...

Object.defineProperty() 完整指南

Object.defineProperty() 完整指南 1. 基本概念 Object.defineProperty() 方法允许精确地添加或修改对象的属性。默认情况下&#xff0c;使用此方法添加的属性是不可修改的。 1.1 基本语法 Object.defineProperty(obj, prop, descriptor)参数说明&#xff1a; obj: 要定义…...

1Panel自建RustDesk服务器方案实现Windows远程macOS

文章目录 缘起RustDesk 基本信息实现原理中继服务器的配置建议 中继服务器自建指南准备服务器安装1Panel安装和配置 RustDesk 中继服务防火墙配置和安全组配置查看key下载&安装&配置客户端设置永久密码测试连接 macOS安装客户端提示finder写入失败hbbs和hbbr说明**hbbs…...

nginx学习之路-windows系统安装nginx

文章目录 1. 下载2. 启动3. 验证参考文档 1. 下载 官方下载地址&#xff1a;https://nginx.org/en/download.html 可以下载windows版本&#xff0c;如nginx-1.26.2.zip。解压后&#xff0c;加入系统变量。 2. 启动 可以使用命令行启动&#xff08;windows系统自带的cmd可能…...

Paimon_01_241020

1. 概述 1.1. 核心特点 统一批处理和流处理&#xff08;流和批同一套代码&#xff09;数据湖能力多种引擎平权变更日志生成丰富的表类型&#xff08;主键表、append-only&#xff0c;有序的流式读取来代替消息队列&#xff09;模式演化&#xff08;schema变更&#xff09; 1…...

人工智能:变革时代的核心驱动力

求各位观众老爷看一看 先声明一下&#xff0c;该内容由于篇幅过长&#xff0c;可能会有一些地方存在一些小问题请大家谅解 观众老爷们&#xff0c;点个免费的赞和关注呗&#xff0c;您们的支持就是我最大的动力~ 人工智能&#xff1a;变革时代的核心驱动力 一、引言 在当今…...

【机器学习】工业 4.0 下机器学习如何驱动智能制造升级

我的个人主页 我的领域&#xff1a;人工智能篇&#xff0c;希望能帮助到大家&#xff01;&#xff01;&#xff01;&#x1f44d;点赞 收藏❤ 随着科技的飞速发展&#xff0c;工业 4.0 浪潮正席卷全球制造业&#xff0c;而机器学习作为这一变革中的关键技术&#xff0c;正以前…...

数据分析-Excel

数据类型和函数初步 Excel中有文本类型和数值类型–但是无法用肉眼分辨出来isnumber来区分是否是数值类型text和value函数可以完成数值类型以及文本类型的转换单元格第一位输入’方式明确输入的是文本sum函数必须是数值类型 文本连接-and-or-not-if-mod-max函数 字符串的连接…...

Kubernetes第二天

1.pod运行一个容器 1.创建目录 mkdir -p /manifests/pod 2.编写pod资源清单文件 vim 01-myweb.yaml 说明&#xff1a; apiVersion:指的是Api的版本 metadata&#xff1a;资源的元数据 spec:用户期望的资源的运行状态 status&#xff1a;资源实际的运行状态 由于拉取远…...

【Java 学习】深度剖析Java多态:从向上转型到向下转型,解锁动态绑定的奥秘,让代码更优雅灵活

&#x1f4ac; 欢迎讨论&#xff1a;如对文章内容有疑问或见解&#xff0c;欢迎在评论区留言&#xff0c;我需要您的帮助&#xff01; &#x1f44d; 点赞、收藏与分享&#xff1a;如果这篇文章对您有所帮助&#xff0c;请不吝点赞、收藏或分享&#xff0c;谢谢您的支持&#x…...

Kerberos用户认证-数据安全-简单了解-230403

hadoop安全模式官方文档&#xff1a;https://hadoop.apache.org/docs/r2.7.2/hadoop-project-dist/hadoop-common/SecureMode.html kerberos是什么 kerberos是计算机网络认证协议&#xff0c;用来在非安全网络中&#xff0c;对个人通信以安全的手段进行身份认证。 概念&#…...

大中厂面试经验分享:如何使用消息队列(MQ)解决系统问题

在大中型互联网公司中&#xff0c;消息队列&#xff08;MQ&#xff09;作为一种关键的分布式系统组件&#xff0c;广泛应用于解决系统中的高并发、异步处理、解耦等问题。 在面试中&#xff0c;尤其是针对后端工程师或系统架构师的职位&#xff0c;面试官常常会通过询问消息队列…...

c#String和StringBuilder

目录 一&#xff0c;String 1&#xff0c;string的特点&#xff1a; 2&#xff0c;string常用方法 &#xff08;1&#xff09;Length &#xff08;2&#xff09;Substring() &#xff08;3&#xff09;ToUpper() &#xff08;4&#xff09;ToLower() &#xff08;5&…...

【人工智能机器学习基础篇】——深入详解强化学习之常用算法Q-Learning与策略梯度,掌握智能体与环境的交互机制

深入详解强化学习之常用算法&#xff1a;Q-Learning与策略梯度 强化学习&#xff08;Reinforcement Learning, RL&#xff09;作为机器学习的一个重要分支&#xff0c;近年来在多个领域取得了显著成果。从棋类游戏的人机对战到自主驾驶汽车&#xff0c;强化学习技术展示了其强大…...

jQuery学习笔记2

jQuery 属性操作 <body><a href"http://www.itcast.cn" title"都挺好">都挺好</a><input type"checkbox" name"" id"" checked /><div index"1" data-index"2">我是div&…...

发现API安全风险,F5随时随地保障应用和API安全

分析数据显示&#xff0c;目前超过90%的基于Web的网络攻击都以API端点为目标&#xff0c;试图利用更新且较少为人所知的漏洞&#xff0c;而这些漏洞通常是由安全团队未主动监控的API所暴露。现代企业需要一种动态防御策略&#xff0c;在风险升级成代价高昂、令人警惕且往往无法…...

移动端如何实现上拉加载

一、理解上拉加载的原理 上拉加载是一种在移动端很常见的交互方式&#xff0c;其原理是当用户在页面上向上滑动&#xff08;即滚动条接近底部&#xff09;时&#xff0c;触发一个加载更多数据的操作。这通常涉及到对滚动事件的监听以及判断滚动位置是否达到了触发加载的阈值。…...

the request was rejected because no multipart boundary was found

文章目录 1. 需求描述2. 报错信息3. 探索过程 1. 使用postman 排除后端错误2. 搜索网上的解决方法3. 解决方法 1. 需求描述 想要在前端上传一个PDF 发票&#xff0c;经过后端解析PDF之后&#xff0c;将想要的值自动回填到对应的输入框中 2. 报错信息 org.apache.tomcat.u…...

Android 自定义shell命令

模拟触摸、按键等操作&#xff0c;直接在命令行输入对应命令即可。命令行如何识别并操作此命令&#xff0c;执行操作的是shell程序&#xff0c;还是java程序&#xff1f;是不是可以添加自定义的命令&#xff1f; 以下在Android13的代码中分析input命令 Android系统中使用了一…...

HTML5滑块(Slider)

HTML5 的滑块&#xff08;Slider&#xff09;控件允许用户通过拖动滑块来选择数值。以下是如何实现一个简单的滑块组件的详细说明。 HTML5 滑块组件 1. 基本结构 使用 <input type"range"> 元素可以创建一个滑块。下面是基本实现的代码示例&#xff1a; <…...

《SwiftUI 实现点击按钮播放 MP3 音频》

功能介绍 点击按钮时&#xff0c;应用会播放名为 yinpin.mp3 的音频文件。使用 AVAudioPlayer 来加载和播放音频。 关键点&#xff1a; 按钮触发&#xff1a;点击按钮会调用 playAudio() 播放音频。音频加载&#xff1a;通过 Bundle.main.url(forResource:) 加载音频文件。播…...

表单元素(标签)有哪些?

HTML 中的表单元素&#xff08;标签&#xff09;用于收集用户输入的数据&#xff0c;常见的有以下几种&#xff1a; 文本输入框 <input type"text">&#xff1a;用于单行文本输入&#xff0c;如用户名、密码等。可以通过设置maxlength属性限制输入字符数&…...

大型ERP系统GL(总账管理)模块需求分析

主要介绍了GL系统的需求分析&#xff0c;包括系统概述、功能描述、帐薄管理、报表管理、期末处理、财务报表以及凭证的快速输入方式、可用性设计、保存、自动审核和打印等方面的内容。系统概述部分介绍了系统的功能结构和模块流程图。 功能描述部分详细描述了系统的基础资料和业…...

SQL常用语句(基础)大全

SQL语句的类型 1.DDL 1.库2.表 2.DML 1.插入数据 insert inot2.删除数据 delete / truncate3.修改数据 update set 3.DQL 1.无条件查询2.查询 什么开始 到什么结束3.指定条件查询 1.单个条件 ro in2.多个条件 and4.查询不为NULL值 is not null ,为NULL值 is null5.模糊查询 li…...

关于HarmonyOS Next中卡片的使用方法

关于Harmony OS中卡片的使用方法 在Harmony OS中&#xff0c;静态卡片是一种非常有用的组件&#xff0c;用于提供应用内功能组件的交互和信息展示。本文将详细介绍如何在Harmony OS中使用静态卡片以及相关的API接口。 1. 概述 静态卡片是Harmony OS中的一种交互组件&#xf…...

Retrofit和rxjava 实现窜行请求,并行请求,循环多次请求,递归请求,错误重试

在使用 Retrofit 和 RxJava 时&#xff0c;可以通过多种方式实现多次请求&#xff0c;比如串行请求、并行请求、依赖请求等。以下是一些常见的实现方式&#xff1a; 1. 串行请求&#xff08;依赖关系&#xff09; 一个请求的结果作为另一个请求的输入&#xff0c;可以用 flat…...

C# OpenCV机器视觉:目标跟踪

在一个阳光明媚的下午&#xff0c;阿强正在实验室里忙碌&#xff0c;突然他的同事小杨走了进来&#xff0c;脸上挂着一丝困惑。 “阿强&#xff0c;我的目标跟踪项目出了问题&#xff01;我想跟踪一个移动的物体&#xff0c;但总是跟丢&#xff01;”小杨一边说&#xff0c;一…...

LeetCode 191 位1的个数

计算正整数二进制表示中汉明重量的两种实现方式对比 在编程的世界里&#xff0c;我们常常会遇到一些有趣又实用的小问题&#xff0c;今天就来和大家分享一下如何计算一个正整数二进制表示中设置位&#xff08;也就是 1 的个数&#xff0c;专业术语叫汉明重量&#xff09;的问题…...

【软件测试面试】银行项目测试面试题+答案(二)

前言 面试题&#xff1a;贷款有哪几种形式? 贷款是指金融机构或其他信贷机构向借款人提供资金&#xff0c;并按照约定的条件和期限收取一定利息的行为。根据贷款的不同形式&#xff0c;贷款可以分为以下几种&#xff1a; 按照还款方式分&#xff1a;分期付款贷款、到期一次…...

分布式消息队列RocketMQ

一、RocketMQ概述 1.1 MQ 概述 MQ&#xff0c;Message Queue&#xff0c;是一种提供消息队列服务的中间件&#xff0c;也成为消息中间件&#xff0c;是一套提供了消息生产、存储、消费全过程API的软件系统。消息即数据 1.2 MQ 用途 MQ的用途总结起来可分为以下三点 限流削峰…...

Temporary failure resolving ‘security.ubuntu.com‘

apt-get update 的时候出现&#xff1a; Temporary failure resolving security.ubuntu.com Temporary failure resolving archive.ubuntu.com具体信息&#xff1a; > ERROR [devel 3/17] RUN bash ./install_base.sh 3.12.3 && rm install_base.sh …...

0基础跟德姆(dom)一起学AI 自然语言处理10-LSTM模型

1 LSTM介绍 LSTM&#xff08;Long Short-Term Memory&#xff09;也称长短时记忆结构, 它是传统RNN的变体, 与经典RNN相比能够有效捕捉长序列之间的语义关联, 缓解梯度消失或爆炸现象. 同时LSTM的结构更复杂, 它的核心结构可以分为四个部分去解析: 遗忘门输入门细胞状态输出门…...

设计模式 创建型 建造者模式(Builder Pattern)与 常见技术框架应用 解析

单例模式&#xff08;Singleton Pattern&#xff09;&#xff0c;又称生成器模式&#xff0c;是一种对象构建模式。它主要用于构建复杂对象&#xff0c;通过将复杂对象的构建过程与其表示分离&#xff0c;使得同样的构建过程可以创建出具有不同表示的对象。该模式的核心思想是将…...

cJson—json和XML比较

cJson—json和XML比较 前言1. 数据结构与表达能力2. 效率&#xff08;性能&#xff09;3. 存储占用与传输效率4. 开发难易程度5. 跨平台支持与兼容性6. 灵活性与扩展性7. 错误处理与验证**总结&#xff1a;JSON 与 XML 的优缺点对比选择建议 前言 在嵌入式设备开发中&#xff…...

【项目】智能BI洞察引擎 测试报告

目录 一、项目背景BI介绍问题分析项目背景 二、项目功能三、功能测试1、登录测试测试用例测试结果 2、注册测试测试用例测试结果出现的bug 3、上传文件测试测试用例测试结果 4、AI生成图表测试测试用例测试结果 5、分析数据页面测试&#xff08;异步&#xff09;测试用例测试结…...

基于SpringBoot的野生动物保护发展平台的设计与实现(源码+SQL+LW+部署讲解)

文章目录 摘 要1. 第1章 选题背景及研究意义1.1 选题背景1.2 研究意义1.3 论文结构安排 2. 第2章 相关开发技术2.1 前端技术2.2 后端技术2.3 数据库技术 3. 第3章 可行性及需求分析3.1 可行性分析3.2 系统需求分析 4. 第4章 系统概要设计4.1 系统功能模块设计4.2 数据库设计 5.…...

QEMU网络配置简介

本文简单介绍下qemu虚拟机网络的几种配置方式。 通过QEMU的支持&#xff0c;常见的可以实现以下4种网络形式&#xff1a; 基于网桥&#xff08;bridge&#xff09;的虚拟网络。基于NAT&#xff08;Network Addresss Translation&#xff09;的虚拟网络。QEMU内置的用户模式网…...

wps透视数据表

1、操作 首先选中你要的行字段表格 -> 插入 -> 透视数据表 -> 拖动行值&#xff08;部门&#xff09;到下方&#xff0c;拖动值&#xff08;包裹数量、运费&#xff09;到下方 2、删除 选中整个透视数据表 -> delete 如图&#xff1a;...

Modbus知识详解

Modbus知识详解 ## 1.什么是Modbus?**顾名思义**&#xff0c;它是一个Bus&#xff08;总线&#xff09;&#xff0c;即总线协议。比如串口协议、IIC协议、SPI都是通信协议。你接触到这种协议&#xff0c;相信你所处的行业是工业电子方面或者你的产品用于工业。好了&#xff0c…...

c++字节对齐

字节对齐&#xff08;Byte Alignment&#xff09;是指计算机存储器中数据存放的位置必须满足特定的地址要求&#xff0c;以提高内存访问效率。在许多计算机系统中&#xff0c;处理器在读取内存中的数据时&#xff0c;需要按照特定的边界进行访问&#xff0c;这种边界通常是2的幂…...

javaEE-文件内容的读写

目录 一.数据流 1.字节流 InputStream的方法&#xff1a; cloes() read() OutPutStream writer()方法 2.字符流 Reader: writer: 代码练习1: 代码练习2: 代码练习3: 一.数据流 java标准库对数据进行了封装,提供了一组类负责进行这些工作. 数据流分为两类:字节流和…...

SWM221系列芯片之电机应用及控制

经过对SWM221系列的强大性能及外设资源&#xff0c;TFTLCD彩屏显示及控制进行了整体介绍后&#xff0c;新迎来我们的电控篇---SWM221系列芯片之电机应用及控制。在微控制器市场面临性能、集成度与成本挑战的当下&#xff0c;SWM221系列芯片以其卓越性能与创新设计&#xff0c;受…...

Mongodb日志报错too many open files,导致mongod进程down

【解决方案】 &#xff08;1&#xff09;进入到服务器&#xff0c;执行&#xff1a; ulimit -a 查看&#xff1a;open files这一行的数量&#xff0c;如果查询到的结果是1000左右&#xff0c;那多半是服务器限制。 &#xff08;2&#xff09;在当前session窗口执行如下&…...

在 uni-app 中使用 wxml-to-canvas 的踩坑经验总结

在 uni-app 中使用 wxml-to-canvas 的踩坑经验总结 wxml-to-canvas 是一款非常强大的小程序工具&#xff0c;可以将 WXML 转换为 Canvas 绘图&#xff0c;用于生成海报、分享图片等。将其应用于 uni-app 项目中&#xff0c;可以为多端开发带来极大的便利&#xff0c;但也有一些…...

基本算法——回归

目录 创建工程 加载数据 分析属性 创建与评估回归模型 线性回归 回归树 评估 完整代码 结论 本节将通过分析能源效率数据集&#xff08;Tsanas和Xifara&#xff0c;2012&#xff09;学习基本的回归算法。我们将基 于建筑的结构特点&#xff08;比如表面、墙体与屋顶面…...

NestJS 性能优化:从应用到部署的最佳实践

在上一篇文章中&#xff0c;我们介绍了 NestJS 的微服务架构实现。本文将深入探讨 NestJS 应用的性能优化策略&#xff0c;从应用层到部署层面提供全方位的优化指南。 应用层优化 1. 路由优化 // src/modules/users/users.controller.ts import { Controller, Get, UseInter…...