您现在的位置是:亿华云 > 应用开发
基于HarmonyOS控制Hi3861小车之信息通信
亿华云2025-10-02 23:18:04【应用开发】3人已围观
简介想了解更多内容,请访问:和华为官方合作共建的鸿蒙技术社区https://harmonyos.51cto.com引言在鸿蒙应用实际开发中,经常会遇到App与IOT设备间的通信,本节主要详细讲述一下通信关
想了解更多内容,基于请访问:
和华为官方合作共建的小信息鸿蒙技术社区
https://harmonyos.51cto.com
引言
在鸿蒙应用实际开发中,经常会遇到App与IOT设备间的通信通信,本节主要详细讲述一下通信关键技术,基于考虑到TCP/UDP协议的小信息特性,两者间通过UDP进行通信是通信一种必然的选择,UDP一种无连接的基于协议,具有资源消耗小,小信息处理速度快的通信优点,了解UDP是基于怎么通信的,这对于每一个HarmonyOS开发者也是小信息需要了解的重点知识。
核心类
DatagramSocket、通信DatagramPacket、基于EventHandler,小信息下面分别简单介绍下:
1.DatagramSocket:
构造器DatagramSocket(int port,通信 InetAddress laddr):创建一个DatagramSocket实例,并将该对象绑定到指定IP地址、指定端口。主要方法receive(DatagramPacket p):从该DatagramSocket中接收数据报,send(DatagramPacket p):以该DatagramSocket对象向外发送数据报。
2.DatagramPacket:
构造器DatagramPacket(byte[] buf, int length, InetAddress addr, int port):以一个包含数据的源码库数组来创建DatagramPacket对象,创建该DatagramPacket对象时还指定了IP地址和端口--这就决定了该数据报的目的地。
3.EventHandler:
是HarmonyOS用于处理线程间通信的一种机制,可以通过EventRunner创建新线程,将耗时的操作放到新线程上执行。这样既不阻塞原来的线程,任务又可以得到合理的处理。比如:主线程使用EventHandler创建子线程,子线程做耗时的下载图片操作,下载完成后,子线程通过EventHandler通知主线程,主线程再更新UI。
功能介绍
通过App Demo控制小车运动(前进、后退、左转、右转、停止),主要通过UDP数据包发送命令,来说明它们间是怎么通信的,它们间控制命令以json格式发送。源码下载
如:
"mode": "CarControl",//控制命令分类 "cmd": "forward"//具体命令 }。开发指南
1、创建UDP协议的发送命令对象
private UdpManager() { try { mGpsDatagramSocket = new DatagramSocket(); } catch (SocketException e) { e.printStackTrace(); } }2、将要发送的数据封装成DatagramPacket对象发送
DatagramPacket sRequest = new DatagramPacket(mInfoArray, mInfoArray.length, InetAddress.getByName(getIp()), PORT); // 开始发送 mGpsDatagramSocket.send(sRequest);3、构造发送的命令
public void sendMessage(String info) { Gson gson = new Gson(); WifiCommand messageInfo = new WifiCommand(); messageInfo.setCmd(info); //控制类型 messageInfo.setMode(); //转换成json String resultJson = gson.toJson(messageInfo); // 创建发送命令SendMessageRunnable对象 mSendMessageRunnable = new SendMessageRunnable(); mSendMessageRunnable.setInfoArray(resultJson.getBytes(StandardCharsets.UTF_8)); // 启动发送命令线程 mEventHandler.postTask(mSendMessageRunnable); if ("stop".equals(info) || "tripod_on".equals(info) || "tripod_off".equals(info)){ HiLog.info(label, "info = " + info); } else { // 启动发送Gps请求线程和接收信息线程 startReceive(); startSendGpsMessage(); } HiLog.info(label, "sendMessage = " + resultJson); }实现效果

附上主要源代码
1. MainAbilitySlice
public class MainAbilitySlice extends AbilitySlice implements Component.ClickedListener{ private Button iTurnUp,iTurnDown,iTurnLeft,iTurnRight,iTurnRun; private UdpManager udpManager; @Override public void onStart(Intent intent) { super.onStart(intent); super.setUIContent(ResourceTable.Layout_ability_main); initComponent(); // 初始化WiFi控制对象 udpManager = UdpManager.getInstance(this); } private void initComponent(){ iTurnUp = (Button) findComponentById(ResourceTable.Id_i_up); iTurnUp.setClickedListener(this); iTurnDown = (Button) findComponentById(ResourceTable.Id_i_down); iTurnDown.setClickedListener(this); iTurnLeft = (Button) findComponentById(ResourceTable.Id_i_left); iTurnLeft.setClickedListener(this); iTurnRight = (Button) findComponentById(ResourceTable.Id_i_right); iTurnRight.setClickedListener(this); iTurnRun = (Button) findComponentById(ResourceTable.Id_i_run); iTurnRun.setClickedListener(this);2. UdpManager
/** * UDP连接类 */ public class UdpManager { private static final HiLogLabel label = new HiLogLabel(HiLog.LOG_APP, 0x00134, "UdpManager"); private static final int PORT = 48100; private static final int GET_MESSAGE = 1; private static UdpManager sUdpManager; private static Context sContext; private UdpReceiveCallback mReceiveInformationCallback; private ReceiveMessageRunnable mReceiveMessageRunnable; private SendGpsMessageRunnable mSendGpsMessageRunnable; private SendMessageRunnable mSendMessageRunnable; private DatagramSocket mGpsDatagramSocket; private static String ip = "192.168.0.1"; /** * 控制是否还需要接收信息控制器 */ private boolean flag = false; private final EventHandler mEventHandler = new EventHandler(EventRunner.create()) { @Override protected void processEvent(InnerEvent event) { super.processEvent(event); if (event.eventId == GET_MESSAGE) { if (mReceiveInformationCallback != null) { mReceiveInformationCallback.getMessage(event.object); } } } }; private final EventHandler mReceiveEventHandler = new EventHandler(EventRunner.create()) { }; private final EventHandler mSendGpsEventHandler = new EventHandler(EventRunner.create()) { }; /** * UdpManager的单例 * * @return UdpManager单例对象 */ public static UdpManager getInstance(Context context) { if (sUdpManager == null) { sUdpManager = new UdpManager(); sContext = context; } return sUdpManager; } /** * 构造函数 */ private UdpManager() { // 创建UDP协议的发送命令对象 try { mGpsDatagramSocket = new DatagramSocket(); } catch (SocketException e) { e.printStackTrace(); } } /** * 注册接收信息的回调函数 * * @param callback 接收信息回调函数 */ public void registerCallback(UdpReceiveCallback callback) { mReceiveInformationCallback = callback; } /** * 对外提供的发送命令方法 * * @param info 需要发送的命令 */ public void sendMessage(String info) { Gson gson = new Gson(); UdpCommand messageInfo = new UdpCommand(); // 传进来的控制命令 messageInfo.setCmd(info); //控制类型 messageInfo.setMode(); //转换成json String resultJson = gson.toJson(messageInfo); // 创建发送命令SendMessageRunnable对象 mSendMessageRunnable = new SendMessageRunnable(); mSendMessageRunnable.setInfoArray(resultJson.getBytes(StandardCharsets.UTF_8)); // 启动发送命令线程 mEventHandler.postTask(mSendMessageRunnable); // 启动发送Gps请求线程和接收信息线程 if ("stop".equals(info)) { HiLog.info(label, "info = " + info); } else { // 启动发送Gps请求线程和接收信息线程 startReceive(); startSendGpsMessage(); } HiLog.info(label, "sendMessage = " + resultJson); } public String getIp() { return ip; } public void setIp(String mIp) { this.ip = mIp; } /** * 内部类,用作发送命令 */ private class SendMessageRunnable implements Runnable { private byte[] mInfoArray; void setInfoArray(byte[] infoArray) { mInfoArray = infoArray; } @Override public void run() { HiLog.info(label, "发送线程 = " + Thread.currentThread().getName()); // 发送数据 try { // 延时发送50毫秒,因为如果不延时会将小车卡死 Thread.sleep(50); // 将要发送的数据封装成DatagramPacket对象 DatagramPacket sRequest = new DatagramPacket(mInfoArray, mInfoArray.length, InetAddress.getByName(getIp()), PORT); // 开始发送 mGpsDatagramSocket.send(sRequest); } catch (IOException | InterruptedException e) { e.printStackTrace(); HiLog.info(label, "sendMessage error"); } } } /** * 内部类,用作接收命令 */ private class ReceiveMessageRunnable implements Runnable { @Override public void run() { try { while (flag) { byte[] buf = new byte[1024]; DatagramPacket receiveDatagramPacket = new DatagramPacket(buf, buf.length); if (mGpsDatagramSocket != null && !mGpsDatagramSocket.isClosed()) { HiLog.info(label, "接收线程开始阻塞" + Thread.currentThread().getName()); // 接收返回数据,会阻塞线程 mGpsDatagramSocket.receive(receiveDatagramPacket); // 将得到的数据转成json String json = new String(receiveDatagramPacket.getData(), StandardCharsets.UTF_8); json = json.substring(json.indexOf("{ "), json.lastIndexOf("}")+1); HiLog.info(label, "receiveMessage json = " + json); // 将对象发送给需要接收返回值的地方 mEventHandler.sendEvent(InnerEvent.get(GET_MESSAGE, json)); } } } catch (IOException e) { e.printStackTrace(); HiLog.error(label, "receiveMessage error"); } } } /** * 内部类,用作发送请求Gps命令 */ private class SendGpsMessageRunnable implements Runnable { @Override public void run() { Gson gson = new Gson(); UdpCommand messageInfo = new UdpCommand(); // 传进来的控制命令 messageInfo.setCmd("getinfo"); //控制类型 messageInfo.setMode(); //转换成json String resultJson = gson.toJson(messageInfo); byte[] infoArray = resultJson.getBytes(StandardCharsets.UTF_8); try { // 将要发送的数据封装成DatagramPacket对象 DatagramPacket sRequest = new DatagramPacket(infoArray, infoArray.length, InetAddress.getByName(getIp()), PORT); // 开始发送 mGpsDatagramSocket.send(sRequest); // 启动获取Gps命令线程 mSendGpsEventHandler.postTask(mSendGpsMessageRunnable, 2000); HiLog.info(label, "发送gps"); } catch (IOException e) { e.printStackTrace(); } } } /** * 启动接收消息 */ private void startReceive() { if (!flag) { flag = true; // 创建接收命令ReceiveMessageRunnable对象 mReceiveMessageRunnable = new ReceiveMessageRunnable(); // 启动接收命令线程 mReceiveEventHandler.postTask(mReceiveMessageRunnable); HiLog.info(label, "开启接收线程"); } } /** * 开始获取gps点 */ private void startSendGpsMessage() { // 创建发送Gps命令SendGpsMessageRunnable对象 if (mSendGpsMessageRunnable == null) { mSendGpsMessageRunnable = new SendGpsMessageRunnable(); } // 启动获取Gps命令线程 mSendGpsEventHandler.postTask(mSendGpsMessageRunnable); HiLog.info(label, "开启发送gps请求线程"); }3. UdpCommand
class UdpCommand { // 控制命令:forward,back,left,right private String cmd; // 控制类型 private String mode; public String getCmd() { return cmd; } void setCmd(String cmd) { this.cmd = cmd; } public String getMode() { return mode; } void setMode() { this.mode = "CarControl"; } }4. UdpReceiveCallback
/** * 接收小车返回数据的回调函数 */ public interface UdpReceiveCallback { void getMessage(Object value); }5. xml布局文件
<?xml version="1.0" encoding="utf-8"?> <DirectionalLayout xmlns:ohos="http://schemas.huawei.com/res/ohos" ohos:height="match_parent" ohos:width="match_parent" ohos:alignment="center" ohos:orientation="vertical"> <DirectionalLayout ohos:height="70vp" ohos:width="match_parent" ohos:orientation="horizontal" ohos:layout_alignment="center" ohos:top_margin="10vp" > <Button ohos:id="$+id:i_up" ohos:height="50vp" ohos:width="120vp" ohos:background_element="#FF9F9F9F" ohos:left_margin="60vp" ohos:text_size="25fp" ohos:text="前进"/>想了解更多内容,请访问:
和华为官方合作共建的云南idc服务商鸿蒙技术社区
https://harmonyos.51cto.com
很赞哦!(4234)