在 HarmonyOS 3.0 和 OpenHarmony 3.2 的支持下,TCP-socket 通信 API 已經穩定可控,今天我們做一個控制應用來控制小車。
效果演示:
設計思路
運行環境:HarmonyOS 3.0,OpenHarmony 3.2
①按鍵說明
如下:
轉向控制:左右滑動搖桿,實現轉向,上下滑動搖桿,實現速度控制
動力控制:上下滑動搖桿,實現前進后退
本機 IP 地址展示
對端 IP 地址輸入
鏈接,斷開按鍵,主動進行 TCP 連接請求與斷開
②控制指令
本遙控器以狀態指令為驅動,每觸發一種狀態僅發送一次指令,對端在未接收到新指令的情況下一直保持當前指令狀態。
前進狀態:“1”
后退狀態:“2”
左轉狀態:“3”
右轉狀態:“4”
停止狀態:“0”
頁面設計
在搖桿的拖動設計中,主要運用 ontouchmove,ontouchend,ontouchstart 實現。 通過手指坐標來確定搖桿組件的 top 和 left 值,通過設定方向閾值來判斷是否開始發送指令,通過打印回調數據來設置參數。
hml:
{{local_ip}}
CSS:
.container{ display:flex; flex-direction:column; justify-content:center; align-items:center; left:0px; top:0px; width:100%; height:100%; } .title{ font-size:40px; text-align:center; width:100%; height:40%; margin:10px; } .yaogan{ position:absolute; top:100px; left:50px; width:200px; height:200px; background-image:url("./common/RadialJoy_Area.png"); background-size:100%; background-repeat:no-repeat; z-index:-1; } .controller{ width:100px; height:100px; top:150px; left:100px; background-image:url("./common/RadialJoy_Area.png"); background-size:100%; background-repeat:no-repeat; position:absolute; z-index:1; } .forward{ position:absolute; left:550px; width:100px; height:100px; background-size:100%; z-index:-1; } .ip_input{ font-size:18px; left:30px; width:200px; height:50px; margin-top:25px; background-color:#ff2c7a87; /*background-imagenone*/ /*background-size:100%;*/ /*background-repeat:no-repeat;*/ } .btn{ width:100px; height:30px; left:30px; margin-top:5px; background-color:#ff93f0fd; /*background-imagenone*/ /*background-size:150%;*/ /*background-repeat:no-repeat;*/ } .ip_local{ font-size:20px; width:200px; height:50px; left:30px; color:#ff3850ef; margin-top:20px; background-image:url("./common/images/bg2.png"); background-size:100%; background-repeat:no-repeat; }
業務邏輯
①參數調試
我們前面為搖桿組件設置了 ontouch 事件,那么如何設計 Top 或者 left 值來判斷什么時候可以開始發送指令呢?
搖桿既不可太過靈敏也不可以太過遲鈍,我們可以通過打印觸摸事件返回的參數來進行調參。
exportdefault{ touchstartfunc(msg){ console.info(`ontouchstart,pointis:${msg.touches[0].globalX}`); console.info(`ontouchstart,pointis:${msg.touches[0].globalY}`); console.info(`ontouchstart,datais:${msg.target.dataSet.a}`); } }②觸摸控制 根據前文提到的狀態控制機制,我們應該在 ontouchmove 中進行判斷,當上滑到某一閾值的時候開始發送前進指令,當松手時即 ontouchend 時我們應該立即發送停止指令。 即滑動中判斷并發送指令,停止則立馬發送停止信息。具體的閾值參數根據個人考慮進行調試設置。
importpromptfrom'@ohos.prompt'; importwififrom'@ohos.wifi'; importsocketfrom'@ohos.net.socket'; importdisplayfrom'@ohos.display'; varpromise; exportdefault{ data:{ title:"", x:150, y:100, forward_x:150, msg:"forward", forward_image:"Button_normal", TGA:"YZJ", command:"1", local_ip:"", remote_ip:"", speed_mode:1, speed:10, tcp:socket.constructTCPSocketInstance(), pre_cmd:'0', cur_cmd:'0' }, onInit(){ this.title=this.$t('strings.world'); this.getIpAddress(); this.creatScoket(); }, send_cmd(cmd){ if(cmd!=this.cur_cmd){ this.cur_cmd=cmd; this.sendMessage(cmd); } }, onMoveStart(e){ console.info("開始移動"+JSON.stringify(e)); }, toSpeed_mode(){ if(this.speed_mode==0) this.speed_mode=1; elseif(this.speed_mode==1) this.speed_mode=0; }, onMove(e){ //圓心是(100,250) if(this.speed_mode==0){ console.info(JSON.stringify(e)) letnx=e.touches[0].globalY-50; this.x=nx; } elseif(this.speed_mode==1){ console.info(JSON.stringify(e)) letny=e.touches[0].globalX-50; this.y=ny; if(ny>=110){ this.msg="trun_right" console.info("YZJ:正在向右轉") this.command="4"; this.send_cmd(this.command); } elseif(ny<=90){ ????????????????this.msg="trun_left" ????????????????console.info("YZJ:正在向做左轉") ????????????????this.command="3"; ????????????????this.send_cmd(this.command); ????????????} ????????} ????}, ????onMoveEnd(){ ????????this.x=150; ????????this.y=100; ????????this.msg="stop" ????????this.command='0'; ????????this.send_cmd(this.command); ????}, ????onForwardstart(e){ ????????this.forward_image="Button_active"; ????????this.forward_x=e.touches[0].globalY-50 ????}, ????onForward(e){ ????????if(?e.touches[0].globalY-50<=140){ ????????????console.info("正在前進") ????????????this.msg="forward" ????????????this.command="1" ????????????this.send_cmd(this.command); ????????????if(e.touches[0].globalY-50<100){ ????????????????this.forward_x=100 ????????????} ????????????else ????????????this.forward_x=e.touches[0].globalY-50 ????????} ????????else?if(e.touches[0].globalY-50>165){ console.info("正在后退") this.msg="backoff" this.command="2" this.send_cmd(this.command); if(e.touches[0].globalY-50>200){ this.forward_x=200 } else this.forward_x=e.touches[0].globalY-50 } }, onForwardend(){ this.forward_x=150; console.info("停止前進") this.msg="stop" this.forward_image="Button_normal" this.command="0" this.send_cmd(this.command); }, //創建udpSocket默認端口10006 creatScoket:asyncfunction(){ this.tcp.bind({address:this.local_ip,port:8888,family:1},err=>{ if(err){ console.log('YZJ---bindfail'); return; } console.log('YZJ---bindsuccess'); }) //監聽收到的信息打印到屏幕上 this.tcp.on('message',value=>{ letbuffer=value.message; letdataView=newDataView(buffer); letstr=""; for(leti=0;i{ console.log('YZJ---sendsuccess'); }).catch(err=>{ console.log('YZJ---sendfail'); }); }, onConnect:asyncfunction(){ promise=this.tcp.connect({address:{address:"192.168.1.1",port:8888,family:1},timeout:6000}); promise.then(()=>{ prompt.showToast({ message:"連接成功!" }) console.log('YZJ---connectsuccess'); this.tcp.setExtraOptions({ keepAlive:true, OOBInline:true, TCPNoDelay:true, socketLinger:{on:true,linger:10}, receiveBufferSize:1000, sendBufferSize:1000, reuseAddress:true, socketTimeout:3000, },err=>{ if(err){ console.log('YZJ---setExtraOptionsfail'); return; } console.log('YZJ---setExtraOptionssuccess'); }); }).catch(err=>{ console.log('YZJ---connectfail'); prompt.showToast({ message:"連接失敗!" }) }); }, onDisconnect(){ this.tcp.close() prompt.showToast({ message:"斷開鏈接!" }) }, onDestroy(){ this.tcp.close() prompt.showToast({ message:"斷開鏈接!" }) }, //獲取本機ip地址 getIpAddress(){ letip=wifi.getIpInfo().ipAddress; this.local_ip=(ip>>24&0xFF)+"."+((ip>>16)&0xFF)+"."+((ip>>8)&0xFF)+"."+(ip&0xFF); }, get_remote_ip(e){ this.remote_ip=e.value } }③TCP 通過輸入框獲取對端 IP 地址,點擊鏈接按鍵時觸發 connect 方法請求連接,連接成功彈出對話框"連接成功"。 展示本機 IP 地址。 應用或者頁面銷毀時應關閉連接,否則會占據對端該端口,導致下次連接失敗。 根據狀態驅動指令控制,由于 ontouchmove 是一直在觸發的,也就是判斷是一直在進行的,當我們保持搖桿前進狀態的時候,注意要判斷指令狀態是否更新了?如果指令未變,那么就不再發送指令。只有指令變化的時候才會發送一次指令。 只有連接成功后,才能夠發送信息。
tcp 設置參數:
|參數|描述| |-|-| |keepAlive|是否保持連接。默認為false。| |OOBInline|是否為OOB內聯。默認為false。| |TCPNoDelay|TCPSocket連接是否無時延。默認為false。| |receiveBufferSize|接收緩沖區大小(單位:Byte)| |sendBufferSize|發送緩沖區大小(單位:Byte)| |reuseAddress|是否重用地址。默認為false| |socketTimeout|套接字超時時間,單位毫秒(ms)|建議開啟 HarmonyOS 工程,開發完畢后可同步安裝到 OpenHarmony 設備,反之則會變得麻煩一些。
④申請權限
"reqPermissions":[ { "name":"ohos.permission.GET_WIFI_INFO" }, { "name":"ohos.permission.GET_NETWORK_INFO" }, { "name":"ohos.permission.INTERNET" }, { "name":"ohos.permission.SET_NETWORK_INFO" }, { "name":"ohos.permission.ACCELEROMETER" } ]
結語
本次分享的應用需要南北向開發配合食用,同時需要 HarmonyOS 3.0 設備或者 OpenHarmony 3.2 設備。 HarmonyOS 2.0 設備可考慮采用 JS/JAVA 混合開發,JAVA 側實現 Socket 通信,可參考我往期博客。 下一期,我將會分享如何配置 HarmonyOS 3.0 設備的碰一碰拉起應用配置。
審核編輯:湯梓紅
-
遙控器
+關注
關注
18文章
829瀏覽量
65972 -
HarmonyOS
+關注
關注
79文章
1967瀏覽量
30017 -
OpenHarmony
+關注
關注
25文章
3660瀏覽量
16152
原文標題:為鴻蒙小車做一個遙控器
文章出處:【微信號:gh_834c4b3d87fe,微信公眾號:OpenHarmony技術社區】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論