系统运维

基于HarmonyOS控制Hi3861小车之信息通信

时间:2010-12-5 17:23:32  作者:IT科技类资讯   来源:IT科技  查看:  评论:0
内容摘要:想了解更多内容,请访问:和华为官方合作共建的鸿蒙技术社区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="前进"/> 

想了解更多内容,请访问:

和华为官方合作共建的源码下载鸿蒙技术社区

https://harmonyos.51cto.com

-->
copyright © 2025 powered by 益强资讯全景  滇ICP备2023006006号-31sitemap