0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

为鸿蒙小车做一个遥控器

OpenHarmony技术社区 来源:OST开源开发者 2022-12-26 09:56 次阅读

HarmonyOS 3.0 和 OpenHarmony 3.2 的支持下,TCP-socket 通信 API 已经稳定可控,今天我们做一个控制应用来控制小车。

效果演示:

b0d57e74-8468-11ed-bfe3-dac502259ad0.gif

设计思路

运行环境:HarmonyOS 3.0,OpenHarmony 3.2

b12540a8-8468-11ed-bfe3-dac502259ad0.png

①按键说明

如下:

转向控制:左右滑动摇杆,实现转向,上下滑动摇杆,实现速度控制

动力控制:上下滑动摇杆,实现前进后退

本机 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< dataView.byteLength; ++i) {
                str += String.fromCharCode(dataView.getUint8(i))
            }
            this.title =str;
        });
    },
    sendMessage: async function(cmd){
       //发送信息
//                let promise1 = this.tcp.connect({ address: {address: this.remote_ip, port: 10006, family: 1} , timeout: 6000});
        let promise2 = this.tcp.send({
            data:cmd
        });
        promise2.then(() =>{
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 是一直在触发的,也就是判断是一直在进行的,当我们保持摇杆前进状态的时候,注意要判断指令状态是否更新了?如果指令未变,那么就不再发送指令。只有指令变化的时候才会发送一次指令。 只有连接成功后,才能够发送信息。 b13bb496-8468-11ed-bfe3-dac502259ad0.png

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 设备的碰一碰拉起应用配置。

审核编辑:汤梓红

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

原文标题:为鸿蒙小车做一个遥控器

文章出处:【微信号:gh_834c4b3d87fe,微信公众号:OpenHarmony技术社区】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    玩具车 wifi遥控器

    现在有辆玩具小车,可以用安卓手机或苹果连接(wifi)来进行控制,我想做一个玩具车遥控器来控制,有没有可以实现的,有偿!
    发表于 05-22 22:50

    【NanoPi2申请】基于Linux or 安卓的遥控小车

    申请理由:其实我是想用它来学opencv的些东西,或许那样写不是好的选择,做一个遥控小车
    发表于 12-02 16:10

    做一个用单片机控制的遥控器

    本人菜鸟,想要做一个用单片机来控制的遥控器,但不知道需要什么部件和工具,求大神指导。
    发表于 10-07 14:06

    最近做了遥控小车 前进后退都没有问题 但是有时候不按遥控器后 车子自己会转 怎么破?

    最近做了遥控小车 前进后退都没有问题 但是有时候不按遥控器后 车子自己会转 怎么破
    发表于 05-10 22:19

    遥控器单片机是51的,小车芯片是飞思卡尔的,请问如何修好这个遥控器 急急急

    接手前人的活,用摇杆控制小车运动 无线模块是zigbee,现在遥控器坏了 没有原来的电路图 遥控器单片机是51的,小车芯片是飞思卡尔的,请问如何修好这个
    发表于 05-05 20:03

    遥控器通信原理简介

    目录. 遥控器通信原理简介二. SBUS信号解析1. SBUS信号简介2. STM32F7解析SBUS信号三. 通信任务实现. 遥控器通信原理简介要实现
    发表于 08-19 08:53

    如何做一个无线遥控小车

    如何做一个无线遥控小车
    发表于 12-17 06:58

    如何做一个遥控器控制的计算

    基于arduino uno r3/ Mega2560,做一个遥控器控制的计算。。。。。目录. 实验材料:(ง •_•)ง...
    发表于 02-15 07:42

    如何做一个相机红外遥控器

    如何做一个相机红外遥控器
    发表于 02-15 07:04

    如何设计智能遥控器的电路?

      智能遥控器种可以通过红外线或蓝牙等无线技术来控制家电的设备,以下是设计智能遥控器的电路需要考虑的些方面:  电源管理:智能遥控器
    发表于 04-21 11:03

    请问能用单片机加上红外做一个空调遥控器吗?

    能用单片机加上红外做一个空调遥控器吗?该怎么实现?
    发表于 11-07 06:28

    空调遥控器维修资料下载

    空调遥控器坏了怎么办?空调遥控器哪里修?空调遥控器哪里买?空调遥控器多少钱
    发表于 05-13 10:13 18次下载
    空调<b class='flag-5'>遥控器</b>维修资料下载

    文弄懂无线遥控器

    相信大家对于无线遥控器都有着自己的认知,认为无线遥控器就是我们家用的电视啊、空调啊的遥控器吗?是的,这些当然是无线遥控种,它们属于红外
    发表于 11-14 09:18 9021次阅读

    如何构建简单的基于红外的车门遥控器

    在这篇文章中,我们将学习如何构建简单但万无失的基于红外的遥控器,该遥控器可用于通过个人遥控
    的头像 发表于 04-02 10:37 1243次阅读
    如何构建<b class='flag-5'>一</b><b class='flag-5'>个</b>简单的基于红外的车门<b class='flag-5'>遥控器</b>

    使用红外发射模块自制空调遥控器

    我们家里的空调、电视等,它们的遥控器都是通过红外信号来控制的。其实,我们可以自己用红外发射模块来做一个遥控器
    的头像 发表于 05-23 15:43 3591次阅读
    使用红外发射模块自制空调<b class='flag-5'>遥控器</b>