鸿蒙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通信模拟智能家居模拟案例
效果图 一、智能家居热潮下的鸿蒙契机 在当下科技飞速发展的时代,智能家居已如浪潮般席卷而来,深刻地改变着我们的生活方式。从能依据环境光线自动调节亮度的智能灯具,到可远程操控、精准控温的智能空调,再到实时监测健康数据的智…...
SQL-leetcode-197. 上升的温度
197. 上升的温度 表: Weather ---------------------- | Column Name | Type | ---------------------- | id | int | | recordDate | date | | temperature | int | ---------------------- id 是该表具有唯一值的列。 没有具有相同 recordDate 的不同行。 该表包…...
C++系列关键字static
文章目录 1.静态变量2.静态成员变量 1.静态变量 在C的,静态变量是一个非常有用的特性,它在程序执行期间只初始化一次,并在程序的整个执行期间都保持其值。 1.局部静态变量。定义在函数中,只初始化一次,不像普通的局部…...
使用Fn Connect之后,如何访问到其他程序页面?原来一直都可以!
前言 昨天小白讲过在飞牛上登录Fn Connect,就可以实现远程访问家里的NAS。 接着就有小伙伴咨询:如何远程访问到家里其他需要使用不同端口号才能访问到的软件,比如Jellyfin、Emby等。 这个小白在写文章的时候确实没有考虑到,因为…...
探索Composable Architecture:小众但高效的现代框架技术
近年来,随着应用规模和复杂性的不断提升,对开发效率和可维护性的要求也水涨船高。特别是在领域驱动设计 (DDD) 和反应式编程 (Reactive Programming) 的趋势影响下,一些小众但极具潜力的框架应运而生。本篇博客将深入探讨一种日益受到关注但尚…...
改投论文时如何重构
摘要: 不同期刊和会议对于论文的风格、页数限制等方面有一些差别, 论文在某个地方被拒, 改投别处时需要进行重构. 本贴描述重构的基本方案. 你的衣柜乱糟糟的, 如何清理呢? 方案 A. 把不喜欢的衣服一件件丢掉.方案 B. 把衣服全部丢出来, 然后再把喜欢的衣服一件件放进去. 对…...
P8打卡——YOLOv5-C3模块实现天气识别
🍨 本文为🔗365天深度学习训练营中的学习记录博客🍖 原作者:K同学啊 1.检查GPU import torch import torch.nn as nn import torchvision.transforms as transforms import torchvision from torchvision import transforms, dat…...
基于微信小程序的校园点餐平台的设计与实现(源码+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.…...
PyTorch快速入门教程【小土堆】之完整模型训练套路
视频地址完整的模型训练套路(一)_哔哩哔哩_bilibili import torch import torchvision from model import * from torch import nn from torch.utils.data import DataLoader# 准备数据集 train_data torchvision.datasets.CIFAR10(root"CIFAR10&…...
【AIGC】 ChatGPT实战教程:如何高效撰写学术论文引言
💥 欢迎来到我的博客!很高兴能在这里与您相遇! 首页:GPT-千鑫 – 热爱AI、热爱Python的天选打工人,活到老学到老!!!导航 - 人工智能系列:包含 OpenAI API Key教程, 50个…...
TTL 传输中过期问题定位
问题: 工作环境中有一个acap的环境,ac的wan口ip是192.168.186.195/24,ac上lan上有vlan205,其ip子接口地址192.168.205.1/24,ac采用非nat模式,而是路由模式,在上级路由器上有192.168.205.0/24指向…...
非docker方式部署openwebui过程记录
之前一直用docker方式部署openwebui,结果这东西三天两头升级,我这一升级拉取docker镜像硬盘空间嗖嗖的占用,受不了,今天改成了直接部署,以下是部署过程记录。 一、停止及删除没用的docker镜像占用的硬盘空间 docker s…...
大模型的prompt的应用二
下面总结一些在工作中比较实用的prompt应用。还可以到以下网站参考更多的prompt AI Prompts - WayToAGI 举个例子,让大模型写一份周报 # 角色:智能周报编写助手 ## 背景: 需要根据产品经理提供的简要周报框架,补充完整的周报内容。 ## 注意事项: 言简意赅,重点突…...
ubuntu 22.04安装ollama
1. 顺利的情况 按照官网的提示,执行下面的命令: curl -fsSL https://ollama.com/install.sh | sh如果网络畅通,github访问也没有问题,那就等待安装完成就行 2. 不顺利的情况 由于众所周知的情况,国内网络访问githu…...
从企业级 RAG 到 AI Assistant,阿里云 Elasticsearch AI 搜索技术实践
在过去一年中,基座大模型技术的快速迭代推动了 AI 搜索的演进,主要体现在以下几个方面: 1.搜索技术链路重构 基于大模型的全面重构正在重塑 AI 搜索的技术链路。从数据采集、文档解析、向量检索到查询分析、意图识别、排序模型和知识图谱等…...
Redis--高可用(主从复制、哨兵模式、分片集群)
高可用(主从复制、哨兵模式、分片集群) 高可用性Redis如何实现高可用架构?主从复制原理1. 全量同步2. 命令传播3. 增量同步 Redis Sentinel(哨兵模式)为什么要有哨兵模式?哨兵机制是如何工作的?…...
框架(Mybatis配置日志)
mybatis配置日志输出 先导入日志依赖 <dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.17</version></dependency> 编写log4j.properties配置文件 # Root logger option log4j.rootLogge…...
人工智能-Python上下文管理器-with
概念 Python提供了 with 语句的这种写法,既简单又安全,并且 with 语句执行完成以后自动调用关闭文件操作,即使出现异常也会自动调用关闭文件操作;其效果等价于try-except-finally with 拥有以下两个魔术方法 __enter__() 上文管理…...
每天40分玩转Django:Django类视图
Django类视图 一、知识要点概览表 类别知识点掌握程度要求基础视图View、TemplateView、RedirectView深入理解通用显示视图ListView、DetailView熟练应用通用编辑视图CreateView、UpdateView、DeleteView熟练应用Mixin机制ContextMixin、LoginRequiredMixin理解原理视图配置U…...
自动化测试之Pytest框架(万字详解)
Pytest测试框架 一、前言二、安装2.1 命令行安装2.2 验证安装 三、pytest设计测试用例注意点3.1 命名规范3.2 断言清晰3.3 fixture3.4 参数化设置3.5 测试隔离3.6 异常处理3.7 跳过或者预期失败3.8 mocking3.9 标记测试 四、以案例初入pytest4.1 第一个pytest测试4.2 多个测试分…...
MPNet:旋转机械轻量化故障诊断模型详解python代码复现
目录 一、问题背景与挑战 二、MPNet核心架构 2.1 多分支特征融合模块(MBFM) 2.2 残差注意力金字塔模块(RAPM) 2.2.1 空间金字塔注意力(SPA) 2.2.2 金字塔残差块(PRBlock) 2.3 分类器设计 三、关键技术突破 3.1 多尺度特征融合 3.2 轻量化设计策略 3.3 抗噪声…...
阿里云ACP云计算备考笔记 (5)——弹性伸缩
目录 第一章 概述 第二章 弹性伸缩简介 1、弹性伸缩 2、垂直伸缩 3、优势 4、应用场景 ① 无规律的业务量波动 ② 有规律的业务量波动 ③ 无明显业务量波动 ④ 混合型业务 ⑤ 消息通知 ⑥ 生命周期挂钩 ⑦ 自定义方式 ⑧ 滚的升级 5、使用限制 第三章 主要定义 …...
在 Nginx Stream 层“改写”MQTT ngx_stream_mqtt_filter_module
1、为什么要修改 CONNECT 报文? 多租户隔离:自动为接入设备追加租户前缀,后端按 ClientID 拆分队列。零代码鉴权:将入站用户名替换为 OAuth Access-Token,后端 Broker 统一校验。灰度发布:根据 IP/地理位写…...
MySQL中【正则表达式】用法
MySQL 中正则表达式通过 REGEXP 或 RLIKE 操作符实现(两者等价),用于在 WHERE 子句中进行复杂的字符串模式匹配。以下是核心用法和示例: 一、基础语法 SELECT column_name FROM table_name WHERE column_name REGEXP pattern; …...
OPenCV CUDA模块图像处理-----对图像执行 均值漂移滤波(Mean Shift Filtering)函数meanShiftFiltering()
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 在 GPU 上对图像执行 均值漂移滤波(Mean Shift Filtering),用于图像分割或平滑处理。 该函数将输入图像中的…...
如何在网页里填写 PDF 表格?
有时候,你可能希望用户能在你的网站上填写 PDF 表单。然而,这件事并不简单,因为 PDF 并不是一种原生的网页格式。虽然浏览器可以显示 PDF 文件,但原生并不支持编辑或填写它们。更糟的是,如果你想收集表单数据ÿ…...
Mysql8 忘记密码重置,以及问题解决
1.使用免密登录 找到配置MySQL文件,我的文件路径是/etc/mysql/my.cnf,有的人的是/etc/mysql/mysql.cnf 在里最后加入 skip-grant-tables重启MySQL服务 service mysql restartShutting down MySQL… SUCCESS! Starting MySQL… SUCCESS! 重启成功 2.登…...
【Nginx】使用 Nginx+Lua 实现基于 IP 的访问频率限制
使用 NginxLua 实现基于 IP 的访问频率限制 在高并发场景下,限制某个 IP 的访问频率是非常重要的,可以有效防止恶意攻击或错误配置导致的服务宕机。以下是一个详细的实现方案,使用 Nginx 和 Lua 脚本结合 Redis 来实现基于 IP 的访问频率限制…...
水泥厂自动化升级利器:Devicenet转Modbus rtu协议转换网关
在水泥厂的生产流程中,工业自动化网关起着至关重要的作用,尤其是JH-DVN-RTU疆鸿智能Devicenet转Modbus rtu协议转换网关,为水泥厂实现高效生产与精准控制提供了有力支持。 水泥厂设备众多,其中不少设备采用Devicenet协议。Devicen…...
大数据治理的常见方式
大数据治理的常见方式 大数据治理是确保数据质量、安全性和可用性的系统性方法,以下是几种常见的治理方式: 1. 数据质量管理 核心方法: 数据校验:建立数据校验规则(格式、范围、一致性等)数据清洗&…...
