我是靠谱客的博主 善良黑米,最近开发中收集的这篇文章主要介绍打造自己的HelloDrone 无人机APP过程《1》目录摘要1.实例化无人机及地面站控制对象2.绑定服务3.增加连接点击事件及进行连接,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

目录

文章目录

  • 目录
  • 摘要
  • 1.实例化无人机及地面站控制对象
  • 2.绑定服务
  • 3.增加连接点击事件及进行连接

摘要

本节主要记录HelloDrone的连接过程及Mavlink协议解析过程。

1.实例化无人机及地面站控制对象

核心内容:

controlTower = new ControlTower(context);
drone = new Drone(context);

    @Override
    /**
     * 重写onCreate方法,在onStart方法之前启动
     */
    protected void onCreate(Bundle savedInstanceState) {
        //调用父类的onCreate
        super.onCreate(savedInstanceState);
        //设置主窗口显示信息
        setContentView(R.layout.activity_main);
        Log.i("lxw","+++++");

        //获取app文件名称
        final Context context = getApplicationContext();
        //创建控制
        controlTower = new ControlTower(context);
        //创建无人机实例
        drone = new Drone(context);
        //模式选择
        this.modeSelector = (Spinner) findViewById(R.id.modeSelect);
        //增加模式选择监听事件
        this.modeSelector.setOnItemSelectedListener(new Spinner.OnItemSelectedListener()
        {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id)
            {
                onFlightModeSelected(view);
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent)
            {
                // Do nothing
            }
        });

        final Button takePic = (Button) findViewById(R.id.take_photo_button);
        takePic.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                takePhoto();
            }
        });

        final Button toggleVideo = (Button) findViewById(R.id.toggle_video_recording);
        toggleVideo.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                toggleVideoRecording();
            }
        });

        videoView = (TextureView) findViewById(R.id.video_content);
        videoView.setSurfaceTextureListener(new TextureView.SurfaceTextureListener() {
            @Override
            public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
                alertUser("Video display is available.");
                startVideoStream.setEnabled(true);
                startVideoStreamUsingObserver.setEnabled(true);
            }

            @Override
            public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {

            }

            @Override
            public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
                startVideoStream.setEnabled(false);
                startVideoStreamUsingObserver.setEnabled(false);
                return true;
            }

            @Override
            public void onSurfaceTextureUpdated(SurfaceTexture surface) {

            }
        });

        startVideoStream = (Button) findViewById(R.id.start_video_stream);
        startVideoStream.setEnabled(false);
        startVideoStream.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                alertUser("Starting video stream.");
                startVideoStream(new Surface(videoView.getSurfaceTexture()));
            }
        });

        stopVideoStream = (Button) findViewById(R.id.stop_video_stream);
        stopVideoStream.setEnabled(false);
        stopVideoStream.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                alertUser("Stopping video stream.");
                stopVideoStream();
            }
        });

        startVideoStreamUsingObserver = (Button) findViewById(R.id.start_video_stream_using_observer);
        startVideoStreamUsingObserver.setEnabled(false);
        startVideoStreamUsingObserver.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                alertUser("Starting video stream using observer for video stream packets.");
                startVideoStreamForObserver();
            }
        });

        stopVideoStreamUsingObserver = (Button) findViewById(R.id.stop_video_stream_using_observer);
        stopVideoStreamUsingObserver.setEnabled(false);
        stopVideoStreamUsingObserver.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                alertUser("Stopping video stream using observer for video stream packets.");
                stopVideoStreamForObserver();
            }
        });

        // Initialize media codec manager to decode video stream packets.
        HandlerThread mediaCodecHandlerThread = new HandlerThread("MediaCodecHandlerThread");
        mediaCodecHandlerThread.start();
        Handler mediaCodecHandler = new Handler(mediaCodecHandlerThread.getLooper());
        mediaCodecManager = new MediaCodecManager(mediaCodecHandler);

        mainHandler = new Handler(getApplicationContext().getMainLooper());
    }

2.绑定服务

    @Override
    public void onStart()
    {
        Log.i("lxw","Hello Drone onStart启动");
        super.onStart();
        //执行连接任务
        Log.i(MAGTAG,"onStart");
        Log.i(MAGTAG,"this:"+this); //this:hello.MainActivity
        Log.i(MAGTAG,"this2:"+getApplicationContext()); //this2:hello.StarterApplication
        //执行控制器连接
        this.controlTower.connect(this,getApplicationContext());
        //更新模式类型
        updateVehicleModesForType(this.droneType);
        Log.i(MAGTAG,"connect");

    }

核心代码是:

this.controlTower.connect(this,getApplicationContext());

实现服务的绑定o3drServicesConnection

    public void connect(TowerListener listener,Context context) {
        boolean value;
        Log.i("LXW","AAA");
        //没有监听这,条件判断
        if (towerListener != null && (isServiceConnecting.get() || isTowerConnected()))
            return;
         //是空
        if (listener == null)
        {
            throw new IllegalArgumentException("ServiceListener argument cannot be null.");
        }
        Log.i("LXW","CCC");
        towerListener = listener;
        Log.i("LXW","DDD");
        if (!isTowerConnected() && !isServiceConnecting.get())
        {
            Intent serviceIntent = ApiAvailability.getInstance().getAvailableServicesInstance(context);
            //value1:Intent { act=com.o3dr.services.android.lib.model.IDroidPlannerServices
            // cmp=com.o3dr.sample.hellodrone/org.droidplanner.services.android.impl.api.DroidPlannerService }
            Log.i("LXW","value1:"+ApiAvailability.getInstance().getAvailableServicesInstance(context));
            value= this.context.bindService(serviceIntent, o3drServicesConnection, Context.BIND_AUTO_CREATE);
            //value2:true
            Log.i("LXW","value2:"+value);
            isServiceConnecting.set(value);
        }
        Log.i("LXW","EEE");
    }

绑定服务后,首先启动的是onCreate(),然后进行onBind()方法
在这里插入图片描述
我们需要在清单文件中声明服务
在这里插入图片描述
我们去看下DroidPlannerService的代码,发现他是继承Service的,这也满足了服务的要求。


/**
   DroneKit安卓后台服务实现。
 * DroneKit-Android background service implementation.
 */
public class DroidPlannerService extends Service {

        /**
     * Status bar notification id
     */
    private static final int FOREGROUND_ID = 101;

    /**
     * Set of actions to notify the local app's components of the service events.
     */
    public static final String ACTION_DRONE_CREATED = Utils.PACKAGE_NAME + ".ACTION_DRONE_CREATED";
    public static final String ACTION_DRONE_DESTROYED = Utils.PACKAGE_NAME + ".ACTION_DRONE_DESTROYED";
    public static final String ACTION_RELEASE_API_INSTANCE = Utils.PACKAGE_NAME + ".action.RELEASE_API_INSTANCE";
    public static final String EXTRA_API_INSTANCE_APP_ID = "extra_api_instance_app_id";

    /**
     * Used to broadcast service events.
     */
    private LocalBroadcastManager lbm;

    /**
     * Stores drone api instances per connected client. The client are denoted by their app id.
     */
    final ConcurrentHashMap<String, DroneApi> droneApiStore = new ConcurrentHashMap<>();

    /**
     * Caches drone managers per connection type.
     */
    final ConcurrentHashMap<ConnectionParameter, DroneManager> droneManagers = new ConcurrentHashMap<>();

    private DPServices dpServices;

    private CameraInfoLoader cameraInfoLoader;
    private List<CameraDetail> cachedCameraDetails;

    /**
     * Generate a drone api instance for the client denoted by the given app id.
     *
     * @param listener Used to retrieve api information.
     * @param appId    Application id of the connecting client.
     * @return a IDroneApi instance
     */
    DroneApi registerDroneApi(IApiListener listener, String appId) {
        if (listener == null)
            return null;

        DroneApi droneApi = new DroneApi(this, listener, appId);
        droneApiStore.put(appId, droneApi);
        lbm.sendBroadcast(new Intent(ACTION_DRONE_CREATED));
        updateForegroundNotification();
        return droneApi;
    }

    /**
     * Release the drone api instance attached to the given app id.
     *
     * @param appId Application id of the disconnecting client.
     */
    void releaseDroneApi(String appId) {
        if (appId == null)
            return;

        DroneApi droneApi = droneApiStore.remove(appId);
        if (droneApi != null) {
            Timber.d("Releasing drone api instance for " + appId);
            droneApi.destroy();
            lbm.sendBroadcast(new Intent(ACTION_DRONE_DESTROYED));
            updateForegroundNotification();
        }
    }

    /**
     * 使用给定的连接参数与车辆建立连接。
     * Establish a connection with a vehicle using the given connection parameter.
     *
     * @param connParams 用于连接到车辆的参数---Parameters used to connect to the vehicle.
     * @param appId      连接应用程序的客户端id---Application id of the connecting client.
     * @param listener   回调以接收无人机事件。Callback to receive drone events.
     * @return 一个DroneManager实例,充当连接的车辆和正在侦听的客户端之间的路由器。
     *       A DroneManager instance which acts as router between the connected vehicle and the listeneing client(s).
     */
    DroneManager connectDroneManager(ConnectionParameter connParams, String appId, DroneApi listener) {

        if (connParams == null || TextUtils.isEmpty(appId) || listener == null)
        {
            Log.i("lxw","connectDroneManager NULL");
            return null;
        }


        DroneManager droneMgr = droneManagers.get(connParams);
        Log.i("lxw","MYdroneMgr:"+droneMgr);
        if (droneMgr == null) {
            final DroneManager temp = DroneManager.generateDroneManager(getApplicationContext(), connParams, new Handler(Looper.getMainLooper()));
            Log.i("lxw","temp:"+temp);
            droneMgr = droneManagers.putIfAbsent(connParams, temp);
            Log.i("lxw","MYdroneMgr2:"+droneMgr);
            if(droneMgr == null){
                Log.i("lxw","Generating:");
                Timber.d("Generating new drone manager.");
                droneMgr = temp;
            }
            else{
                temp.destroy();
            }
        }

        Timber.d("Drone manager connection for " + appId);
        Log.i("lxw","Generating connect");
        //进行连接
        droneMgr.connect(appId, listener, connParams);
        return droneMgr;
    }

    /**
     * Disconnect the given client from the vehicle managed by the given drone manager.
     *
     * @param droneMgr   Handler for the connected vehicle.
     * @param clientInfo Info of the disconnecting client.
     */
    void disconnectDroneManager(DroneManager droneMgr, DroneApi.ClientInfo clientInfo) {
        if (droneMgr == null || clientInfo == null || TextUtils.isEmpty(clientInfo.appId))
            return;

        String appId = clientInfo.appId;
        Timber.d("Drone manager disconnection for " + appId);
        droneMgr.disconnect(clientInfo);
        if (droneMgr.getConnectedAppsCount() == 0) {
            Timber.d("Destroying drone manager.");
            droneMgr.destroy();
            droneManagers.remove(droneMgr.getConnectionParameter());
        }
    }

    /**
     * Retrieves the set of camera info provided by the app.
     *
     * @return a list of {@link CameraDetail} objects.
     */
    synchronized List<CameraDetail> getCameraDetails() {
        if (cachedCameraDetails == null) {
            List<String> cameraInfoNames = cameraInfoLoader.getCameraInfoList();

            List<CameraInfo> cameraInfos = new ArrayList<>(cameraInfoNames.size());
            for (String infoName : cameraInfoNames) {
                try {
                    cameraInfos.add(cameraInfoLoader.openFile(infoName));
                } catch (Exception e) {
                    Timber.e(e, e.getMessage());
                }
            }

            List<CameraDetail> cameraDetails = new ArrayList<>(cameraInfos.size());
            for (CameraInfo camInfo : cameraInfos) {
                cameraDetails.add(new CameraDetail(camInfo.name, camInfo.sensorWidth,
                        camInfo.sensorHeight, camInfo.sensorResolution, camInfo.focalLength,
                        camInfo.overlap, camInfo.sidelap, camInfo.isInLandscapeOrientation));
            }

            cachedCameraDetails = cameraDetails;
        }

        return cachedCameraDetails;
    }

    @Override
    //这里是不是返回null了
    public IBinder onBind(Intent intent) {
        Log.d("lxw","onBind service  " + intent);
        final String action = intent.getAction();
        if (IDroidPlannerServices.class.getName().equals(action))
        {
            // Return binder to ipc client-server interaction.
            return dpServices;
        } else
            {
            return null;
        }
    }

    @SuppressLint("NewApi")
    @Override
    public void onCreate() {
        super.onCreate();
        Log.d("lxw","Binding DroidPlannerService onCreate " );
        Timber.d("Creating DroneKit-Android.");

        final Context context = getApplicationContext();

        dpServices = new DPServices(this);
        lbm = LocalBroadcastManager.getInstance(context);
        this.cameraInfoLoader = new CameraInfoLoader(context);

        updateForegroundNotification();
    }

    @SuppressLint("NewApi")
    private void updateForegroundNotification() {
        final Context context = getApplicationContext();

        //Put the service in the foreground
        final NotificationCompat.Builder notifBuilder = new NotificationCompat.Builder(context)
                .setContentTitle("DroneKit-Android")
                .setPriority(NotificationCompat.PRIORITY_MIN)
                .setSmallIcon(R.drawable.ic_stat_notify);

        final int connectedCount = droneApiStore.size();
        if (connectedCount > 1) {
            notifBuilder.setContentText(connectedCount + " connected apps");
        }

        final Notification notification = notifBuilder.build();
        startForeground(FOREGROUND_ID, notification);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Timber.d("Destroying DroneKit-Android.");

        for (DroneApi droneApi : droneApiStore.values()) {
            droneApi.destroy();
        }
        droneApiStore.clear();

        for (DroneManager droneMgr : droneManagers.values()) {
            droneMgr.destroy();
        }
        droneManagers.clear();

        dpServices.destroy();

        stopForeground(true);

        //Disable this service. It'll be reenabled the next time its local client needs it.
        enableDroidPlannerService(getApplicationContext(), false);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i("lxw","MYintent:"+intent);
        if (intent != null) {
            final String action = intent.getAction();
            switch (action) {

                case ACTION_RELEASE_API_INSTANCE:
                    final String appId = intent.getStringExtra(EXTRA_API_INSTANCE_APP_ID);
                    releaseDroneApi(appId);
                    break;
            }
        }

        stopSelf();
        return START_NOT_STICKY;
    }

    /**
     * Toggles the DroidPlannerService component
     * @param context
     * @param enable
     */
    public static void enableDroidPlannerService(Context context, boolean enable){
        final ComponentName serviceComp = new ComponentName(context, DroidPlannerService.class);
        final int newState = enable ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
                : PackageManager.COMPONENT_ENABLED_STATE_DISABLED;

        context.getPackageManager().setComponentEnabledSetting(serviceComp, newState, PackageManager.DONT_KILL_APP);
    }

}

执行完onbind后,会返回
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
然后会执行

    /**
     * 创建连接服务
     */
    private final ServiceConnection o3drServicesConnection = new ServiceConnection() {

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            isServiceConnecting.set(false);
            Log.i("lxw","onServiceConnected");
            o3drServices = IDroidPlannerServices.Stub.asInterface(service);
            try {
                o3drServices.asBinder().linkToDeath(binderDeathRecipient, 0);
                Log.i("lxw","onServiceConnected try ");
                //通知连接
                notifyTowerConnected();
            } catch (RemoteException e) {
                //通知没有连接
                notifyTowerDisconnected();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.i("lxw","EEE777");
            isServiceConnecting.set(false);
            notifyTowerDisconnected();
        }
    };

核心函数:notifyTowerConnected()

    /**
     * 通知连接
     */
    void notifyTowerConnected()
    {
        Log.i("lxw","notifyTowerConnected");
        if (towerListener == null)
            return;
        //调用连接
        Log.i("lxw","onTower");
        towerListener.onTowerConnected();
    }

我们关注这个函数:towerListener.onTowerConnected();主要实现注册无人机和注册监听者。

    public void onTowerConnected() {
        //提示连接成功
        alertUser("DroneKit-Android Connected");
        this.controlTower.registerDrone(this.drone, this.handler);
        Log.i("lxw","onTowerConnected");
        this.drone.registerDroneListener(this);
        Log.i("lxw","registerDroneListener");
    }

3.增加连接点击事件及进行连接

在这里插入图片描述
MainActivity实现点击按钮事件

    public void onBtnConnectTap(View view)
    {
        //判断是否连接状态,如果是连接,点击的话,提示端口连接
        if (this.drone.isConnected())
        {
            Log.i("lxw","端开连接");
            this.drone.disconnect();
        } else
         {
            Log.i("lxw","进行连接");
            //Spinner提供了从一个数据集合中快速选择一项值的办法。默认情况下Spinner显示的是当前选择的值,
            // 点击Spinner会弹出一个包含所有可选值的dropdown菜单,从该菜单中可以为Spinner选择一个新值
            Spinner connectionSelector = (Spinner) findViewById(R.id.selectConnectionType);
            //获取到下拉框属性
            int selectedConnectionType = connectionSelector.getSelectedItemPosition();
            //判断现在的连接是不是USB连接,如果是的话进行usb连接,否则是udp连接
            //conntParams:ConnectionParameter{connectionType=0, paramsBundle=[extra_usb_baud_rate=115200]}
            ConnectionParameter connectionParams = selectedConnectionType == ConnectionType.TYPE_USB
                ? ConnectionParameter.newUsbConnection(null)
                : ConnectionParameter.newUdpConnection(null);

                Log.i("lxw","connectionParams:"+connectionParams);
            //内部类实现连接事件
            this.drone.connect(connectionParams, new LinkListener()
            {

                @Override
                public void onLinkStateUpdated(@NonNull LinkConnectionStatus connectionStatus)
                {
                    Log.i("lxw","connectionStatus:"+connectionStatus);
                }
            });
        }
    }

核心代码:匿名内部类实现连接事件

            //匿名内部类实现连接事件
            this.drone.connect(connectionParams, new LinkListener()
            {

                @Override
                public void onLinkStateUpdated(@NonNull LinkConnectionStatus connectionStatus)
                {
                    Log.i("lxw","connectionStatus:"+connectionStatus);
                }
            });
    public void connect(ConnectionParameter connParams, LinkListener linkListener) {
        Log.i("lxw","开始进行drone连接操作");
        //USB连接
        VehicleApi.getApi(this).connect(connParams);
        this.connectionParameter = connParams;
        this.linkListener = linkListener;
        Log.i("lxw","this.connectionParameter:"+this.connectionParameter);
        Log.i("lxw","this.linkListener:"+this.linkListener);
    }

继续研究核心代码:VehicleApi.getApi(this).connect(connParams);

    public void connect(ConnectionParameter parameter) {
        Bundle params = new Bundle();
        //params:Bundle[{}]
        Log.i("lxw","Bundle params:"+params);
        params.putParcelable(EXTRA_CONNECT_PARAMETER, parameter);
        Action connectAction = new Action(ACTION_CONNECT, params);
        //无人机执行异步操作
        //com.o3dr.services.android.lib.model.action.Action
        Log.i("lxw","Bundle connectAction:"+connectAction);
        drone.performAsyncAction(connectAction);
    }

分析:drone.performAsyncAction(connectAction);

    public boolean performAsyncAction(Action action) {
        //异步执行线程
        return performAsyncActionOnDroneThread(action, null);
    }

分析代码:performAsyncActionOnDroneThread

    public boolean performAsyncActionOnDroneThread(Action action, AbstractCommandListener listener) {
        //执行异步行为处理
        return performAsyncActionOnHandler(action, this.handler, listener);
    }

分析performAsyncActionOnHandler

    public boolean performAsyncActionOnHandler(Action action, Handler handler, AbstractCommandListener listener) {
        boolean value=false;
        Log.i("lxw","performAsyncActionOnHandler");
        final IDroneApi droneApi = droneApiRef.get();
        //org.droidplanner.services.android.impl.api.DroneApi
        Log.i("lxw","droneApi:"+droneApi);
        value=isStarted(droneApi);
        Log.i("lxw","isStarted value:"+value);
        if (value)
        {
            try {
                //执行行为
                Log.i("lxw","executeAsyncAction:");
                droneApi.executeAsyncAction(action, wrapListener(handler, listener));
                return true;
            } catch (RemoteException e)
            {
                Log.i("lxw","执行 RemoteException");
                Toast.makeText(getContext(), "异步执行2", Toast.LENGTH_LONG).show();
                handleRemoteException(e);
            }
        }
        Log.i("lxw","disconnect7");
        return false;
    }

核心关注代码:droneApi.executeAsyncAction(action, wrapListener(handler, listener));
在这里插入图片描述

    /**
     * 执行行为
     */
    public void executeAction(Action action, ICommandListener listener) throws RemoteException {
        //com.o3dr.services.android.lib.model.action.Action
        Log.i("lxw","executeAction action:"+action);
        if (action == null)
        {
            Log.i("lxw","action null:");
            return;
        }

        String type = action.getType();
        //type com.o3dr.services.android.action.CONNECT
        Log.i("lxw","type:"+type);
        if (type == null)
        {
            Log.i("lxw","type null:");
            return;
        }

        Bundle data = action.getData();
        Log.i("lxw","Bundle data:"+data);
        if (data != null) {
            Log.i("lxw","data not null:");
            data.setClassLoader(context.getClassLoader());
        }
        //获取设备
        Drone drone = getDrone();
        Log.i("lxw","drone1:"+drone);
        Log.i("lxw","mytype:"+type);
        switch (type) {
            // CONNECTION ACTIONS
            case ConnectionActions.ACTION_CONNECT:
                ConnectionParameter parameter = data.getParcelable(ConnectionActions.EXTRA_CONNECT_PARAMETER);
                Log.i("lxw","ConnectionActions:");
                //进行连接
                connect(parameter);
                break;

            case ConnectionActions.ACTION_DISCONNECT:
                disconnect();
                break;

            // CAMERA ACTIONS
            case CameraActions.ACTION_START_VIDEO_STREAM: {
                Surface videoSurface = data.getParcelable(CameraActions.EXTRA_VIDEO_DISPLAY);
                String videoTag = data.getString(CameraActions.EXTRA_VIDEO_TAG, "");

                Bundle videoProps = data.getBundle(CameraActions.EXTRA_VIDEO_PROPERTIES);
                if (videoProps == null) {
                    //Only case where it's null is when interacting with a deprecated client version.
                    //In this case, we assume that the client is attempting to start a solo stream, since that's
                    //the only api that was exposed.
                    videoProps = new Bundle();
                    videoProps.putInt(CameraActions.EXTRA_VIDEO_PROPS_UDP_PORT, VideoManager.ARTOO_UDP_PORT);
                }

                CommonApiUtils.startVideoStream(drone, videoProps, ownerId, videoTag, videoSurface, listener);
                break;
            }

            case ExperimentalActions.ACTION_START_VIDEO_STREAM_FOR_OBSERVER: {
                String videoTag = data.getString(CameraActions.EXTRA_VIDEO_TAG, "");
                CommonApiUtils.startVideoStreamForObserver(drone, ownerId, videoTag, listener);
                break;
            }

            case CameraActions.ACTION_STOP_VIDEO_STREAM: {
                String videoTag = data.getString(CameraActions.EXTRA_VIDEO_TAG, "");
                CommonApiUtils.stopVideoStream(drone, ownerId, videoTag, listener);
                break;
            }

            case ExperimentalActions.ACTION_STOP_VIDEO_STREAM_FOR_OBSERVER: {
                String videoTag = data.getString(CameraActions.EXTRA_VIDEO_TAG, "");
                CommonApiUtils.stopVideoStreamForObserver(drone, ownerId, videoTag, listener);
                break;
            }

            // MISSION ACTIONS
            case MissionActions.ACTION_BUILD_COMPLEX_MISSION_ITEM:
                if (drone instanceof MavLinkDrone || drone == null) {
                    CommonApiUtils.buildComplexMissionItem((MavLinkDrone) drone, data);
                } else {
                    CommonApiUtils.postErrorEvent(CommandExecutionError.COMMAND_UNSUPPORTED, listener);
                }
                break;

            case MissionActions.ACTION_SAVE_MISSION: {
                Mission mission = data.getParcelable(MissionActions.EXTRA_MISSION);
                Uri saveUri = data.getParcelable(MissionActions.EXTRA_SAVE_MISSION_URI);
                if (saveUri == null) {
                    CommonApiUtils.postErrorEvent(CommandExecutionError.COMMAND_FAILED, listener);
                } else {
                    MissionUtils.saveMission(context, mission, saveUri, listener);
                }
                break;
            }

            case MissionActions.ACTION_LOAD_MISSION: {
                Uri loadUri = data.getParcelable(MissionActions.EXTRA_LOAD_MISSION_URI);
                boolean setMission = data.getBoolean(MissionActions.EXTRA_SET_LOADED_MISSION, false);
                if (loadUri != null) {
                    Mission mission = MissionUtils.loadMission(context, loadUri);
                    if(mission != null){
                        // Going back to the caller.
                        data.putParcelable(MissionActions.EXTRA_MISSION, mission);

                        if(setMission){
                            Bundle params = new Bundle();
                            params.putParcelable(EXTRA_MISSION, mission);
                            params.putBoolean(EXTRA_PUSH_TO_DRONE, false);
                            executeAction(new Action(ACTION_SET_MISSION, params), listener);
                        }
                    }
                }
                break;
            }

            default:
                if (droneMgr != null) {
                    droneMgr.executeAsyncAction(clientInfo, action, listener);
                } else {
                    CommonApiUtils.postErrorEvent(CommandExecutionError.COMMAND_FAILED, listener);
                }
                break;
        }
    }

这里我们选择USB连接,重点执行的函数

在这里插入代码片


    /**
     * 执行连接任务
     * @param connParams
     */
    public void connect(ConnectionParameter connParams) {
        try {
            Log.i("lxw","connParams:"+connParams);
            //Validate the given connection parameter
            connParams = checkConnectionParameter(connParams);
            Log.i("lxw","connParams1:"+connParams);
            //Validate the current connection parameter for the drone
            ConnectionParameter currentConnParams = this.connectionParams == null
                ? this.connectionParams
                : checkConnectionParameter(this.connectionParams);
            Log.i("lxw","currentConnParams:"+currentConnParams);
            if (!connParams.equals(currentConnParams))
            {
                Log.i("lxw","droneMgr:"+droneMgr);
                if (this.droneMgr != null)
                {
                    Log.i("lxw","droneMgr is not null:");
                    LinkConnectionStatus connectionStatus = LinkConnectionStatus
                        .newFailedConnectionStatus(LinkConnectionStatus.ADDRESS_IN_USE,
                            "Connection already started with different connection parameters");
                    onConnectionStatus(connectionStatus);
                    return;
                }

                this.connectionParams = connParams;
                Log.i("lxw","this.connectionParams:"+this.connectionParams);
                //ownerId:com.o3dr.sample.hellodrone
                Log.i("lxw","ownerId:"+ownerId);
                //进行连接管理调用
                this.droneMgr = service.connectDroneManager(this.connectionParams, ownerId, this);
                Log.i("lxw","this.droneMgr:"+this.droneMgr);
                Log.i("lxw","bufdata:"+isEventsBufferingEnabled());
                if(isEventsBufferingEnabled())
                {
                    Log.i("lxw","isEventsBufferingEnabled:");
                    eventsBuffer.clear();
                    handler.postDelayed(eventsDispatcher, this.connectionParams.getEventsDispatchingPeriod());
                }
            }
        } catch (ConnectionException e)
        {
            Log.i("lxw","link connect:");
            LinkConnectionStatus connectionStatus = LinkConnectionStatus
                .newFailedConnectionStatus(LinkConnectionStatus.INVALID_CREDENTIALS, e.getMessage());
            onConnectionStatus(connectionStatus);
            disconnect();
        }
    }

分析代码:this.droneMgr = service.connectDroneManager(this.connectionParams, ownerId, this);

    /**
     * 使用给定的连接参数与车辆建立连接。
     * Establish a connection with a vehicle using the given connection parameter.
     *
     * @param connParams 用于连接到车辆的参数---Parameters used to connect to the vehicle.
     * @param appId      连接应用程序的客户端id---Application id of the connecting client.
     * @param listener   回调以接收无人机事件。Callback to receive drone events.
     * @return 一个DroneManager实例,充当连接的车辆和正在侦听的客户端之间的路由器。
     *       A DroneManager instance which acts as router between the connected vehicle and the listeneing client(s).
     */
    DroneManager connectDroneManager(ConnectionParameter connParams, String appId, DroneApi listener) {

        if (connParams == null || TextUtils.isEmpty(appId) || listener == null)
        {
            Log.i("lxw","connectDroneManager NULL");
            return null;
        }


        DroneManager droneMgr = droneManagers.get(connParams);
        Log.i("lxw","MYdroneMgr:"+droneMgr);
        if (droneMgr == null) {
            final DroneManager temp = DroneManager.generateDroneManager(getApplicationContext(), connParams, new Handler(Looper.getMainLooper()));
            Log.i("lxw","temp:"+temp);
            droneMgr = droneManagers.putIfAbsent(connParams, temp);
            Log.i("lxw","MYdroneMgr2:"+droneMgr);
            if(droneMgr == null){
                Log.i("lxw","Generating:");
                Timber.d("Generating new drone manager.");
                droneMgr = temp;
            }
            else{
                temp.destroy();
            }
        }

        Timber.d("Drone manager connection for " + appId);
        Log.i("lxw","Generating connect");
        //进行连接
        droneMgr.connect(appId, listener, connParams);
        return droneMgr;
    }

分析代码:droneMgr.connect(appId, listener, connParams);

    public synchronized void connect(String appId, DroneApi listener, ConnectionParameter connParams) {
        //org.droidplanner.services.android.impl.api.DroneApi
        Log.i("lxw","listener:"+listener);
        Log.i("lxw","listener2:"+TextUtils.isEmpty(appId));
        if (listener == null || TextUtils.isEmpty(appId)) {
            Log.i("lxw","listener return:");
            return;
        }

        connectedApps.put(appId, listener);
        //开始连接
        Log.i("lxw","doConnect:");
        doConnect(appId, listener, connParams);
    }

分析:doConnect(appId, listener, connParams);

    protected void doConnect(String appId, DroneApi listener, ConnectionParameter connParams) {
        Log.i("lxw"," MavlinkDrone Manager doConnect:");
        if (mavClient.isDisconnected()) {
            Timber.i("Opening connection for %s", appId);
            mavClient.openConnection();
            Log.i("lxw"," mavClientdoConnect:1");
        } else {
            if (isConnected()) {
                listener.onDroneEvent(DroneInterfaces.DroneEventsType.CONNECTED, drone);
                if (!drone.isConnectionAlive())
                    listener.onDroneEvent(DroneInterfaces.DroneEventsType.HEARTBEAT_TIMEOUT, drone);
            }
            Log.i("lxw"," mavClientdoConnect:2");
        }

        mavClient.registerForTLogLogging(appId, connParams.getTLogLoggingUri());
        Log.i("lxw"," updateDroneStreamRate:");
        updateDroneStreamRate(connParams);
    }

重点关注: mavClient.openConnection();

    public synchronized void openConnection()
    {
        if(isConnected() || isConnecting())
        {
            Log.i("lxw"," openConnection:1");
            return;
        }


        final String tag = toString();

        //创建Mavlink----Create the mavlink connection
        final int connectionType = connParams.getConnectionType();
        final Bundle paramsBundle = connParams.getParamsBundle();
        Log.i("lxw"," connectionType:"+connectionType); //0
        Log.i("lxw"," paramsBundle:"+paramsBundle); //波特率
        Log.i("lxw"," mavlinkConn:"+mavlinkConn); //UsbConnection
        if(mavlinkConn == null) {
            switch (connectionType) {
                //USB类型
                case ConnectionType.TYPE_USB:  //0
                    final int baudRate = paramsBundle.getInt(ConnectionType.EXTRA_USB_BAUD_RATE,
                            ConnectionType.DEFAULT_USB_BAUD_RATE);
                    mavlinkConn = new UsbConnection(context, baudRate);
                    Log.i("lxw"," mavlinkConn:6"+mavlinkConn);
                    Timber.i("Connecting over usb.");
                    break;
                //蓝牙类型
                case ConnectionType.TYPE_BLUETOOTH:
                    //Retrieve the bluetooth address to connect to
                    final String bluetoothAddress = paramsBundle.getString(ConnectionType.EXTRA_BLUETOOTH_ADDRESS);
                    mavlinkConn = new BluetoothConnection(context, bluetoothAddress);
                    Timber.i("Connecting over bluetooth.");
                    break;
                //TCP类型
                case ConnectionType.TYPE_TCP:
                    //Retrieve the server ip and port
                    final String tcpServerIp = paramsBundle.getString(ConnectionType.EXTRA_TCP_SERVER_IP);
                    final int tcpServerPort = paramsBundle.getInt(ConnectionType
                            .EXTRA_TCP_SERVER_PORT, ConnectionType.DEFAULT_TCP_SERVER_PORT);
                    mavlinkConn = new AndroidTcpConnection(context, tcpServerIp, tcpServerPort, new WifiConnectionHandler(context));
                    Timber.i("Connecting over tcp.");
                    break;
                //UDP类型
                case ConnectionType.TYPE_UDP:
                    final int udpServerPort = paramsBundle
                            .getInt(ConnectionType.EXTRA_UDP_SERVER_PORT, ConnectionType.DEFAULT_UDP_SERVER_PORT);
                    mavlinkConn = new AndroidUdpConnection(context, udpServerPort, new WifiConnectionHandler(context));
                    Timber.i("Connecting over udp.");
                    break;
                //SOLO类型
                case ConnectionType.TYPE_SOLO: {
                    Timber.i("Creating solo connection");
                    final String soloLinkId = paramsBundle.getString(ConnectionType.EXTRA_SOLO_LINK_ID, null);
                    final String linkPassword = paramsBundle.getString(ConnectionType.EXTRA_SOLO_LINK_PASSWORD, null);
                    mavlinkConn = new SoloConnection(context, soloLinkId, linkPassword);
                    break;
                }

                default:
                    Timber.e("Unrecognized connection type: %s", connectionType);
                    return;
            }
        }
        Log.i("lxw"," mavlinkConn:7");
        Log.i("lxw"," mConnectionListener:"+mConnectionListener);
        mavlinkConn.addMavLinkConnectionListener(tag, mConnectionListener);

        //Check if we need to ping a server to receive UDP data stream.
        if (connectionType == ConnectionType.TYPE_UDP)
        {
            final String pingIpAddress = paramsBundle.getString(ConnectionType.EXTRA_UDP_PING_RECEIVER_IP);
            if (!TextUtils.isEmpty(pingIpAddress)) {
                try {
                    final InetAddress resolvedAddress = InetAddress.getByName(pingIpAddress);

                    final int pingPort = paramsBundle.getInt(ConnectionType.EXTRA_UDP_PING_RECEIVER_PORT);
                    final long pingPeriod = paramsBundle.getLong(ConnectionType.EXTRA_UDP_PING_PERIOD,
                            ConnectionType.DEFAULT_UDP_PING_PERIOD);
                    final byte[] pingPayload = paramsBundle.getByteArray(ConnectionType.EXTRA_UDP_PING_PAYLOAD);

                    ((AndroidUdpConnection) mavlinkConn).addPingTarget(resolvedAddress, pingPort, pingPeriod, pingPayload);

                } catch (UnknownHostException e) {
                    Timber.e(e, "Unable to resolve UDP ping server ip address.");
                }
            }
        }
        Log.i("lxw"," mavlinkConn:888");
        if (mavlinkConn.getConnectionStatus() == MavLinkConnection.MAVLINK_DISCONNECTED)
        {
            Log.i("lxw"," 开始执行Mavlink 连接");
            mavlinkConn.connect(null);
        }
    }

重点函数:执行mavlink相关mavlinkConn.connect(null);

    public void connect(Bundle extras) {
        Log.i("lxw"," mavlinkConn:999");
        if (mConnectionStatus.compareAndSet(MAVLINK_DISCONNECTED, MAVLINK_CONNECTING)) {
            extrasHolder.set(extras);
            mLogger.logInfo(TAG, "Starting connection thread.");
            Log.i("lxw"," mavlink连接任务创建");
            mConnectThread = new Thread(mConnectingTask, "MavLinkConnection-Connecting Thread");
            //启动连接
            mConnectThread.start();
            //报告链接状态
            reportConnecting();
        }
    }
    /**
     * 启动连接进程。Start the connection process.
     */
    private final Runnable mConnectingTask = new Runnable() {
        @Override
        public void run() {
            // Load the connection specific preferences
            loadPreferences();
            // Open the connection
            try {
                Log.i("lxw"," 开始执行打开openConnection run");
                openConnection(extrasHolder.get());
                Log.i("lxw"," mavlinkConn:111");
            } catch (IOException e) {
                Log.i("lxw"," mavlinkConn:2222");
                // Ignore errors while shutting down
                if (mConnectionStatus.get() != MAVLINK_DISCONNECTED) {
                    reportIOException(e);

                    mLogger.logErr(TAG, e);
                }

                disconnect();
            }

            mLogger.logInfo(TAG, "Exiting connecting thread.");
        }
    };

继续看代码:openConnection(extrasHolder.get());

    @Override
    protected void openConnection(Bundle connectionExtras) throws IOException {
        boolean id_device;
        Log.i("lxw"," mUsbConnection:"+mUsbConnection);
        if (mUsbConnection != null) {
            try {
                Log.i("lxw"," BBB123");
                mUsbConnection.openUsbConnection(connectionExtras);
                Log.d(TAG, "Reusing previous usb connection.");
                return;
            } catch (IOException e) {
                Log.i("lxw"," BBB456");
                Log.e(TAG, "Previous usb connection is not usable.", e);
                mUsbConnection = null;
            }
        }
        id_device=isFTDIdevice(context);
        Log.i("lxw","id_device:"+id_device);
        if (id_device)
        {
            final UsbConnectionImpl tmp = new UsbFTDIConnection(context, this, mBaudRate);
            try {
                tmp.openUsbConnection(connectionExtras);

                // If the call above is successful, 'mUsbConnection' will be set.
                mUsbConnection = tmp;
                Log.d(TAG, "Using FTDI usb connection.");
            } catch (IOException e) {
                Log.d(TAG, "Unable to open a ftdi usb connection. Falling back to the open "
                    + "usb-library.", e);
            }
        }

        // Fallback
        if (mUsbConnection == null) {
            Log.i("lxw"," KKK");
            Log.i("lxw"," BT:"+mBaudRate);
            Log.i("lxw"," BT2:"+context);
            final UsbConnectionImpl tmp = new UsbCDCConnection(context, this, mBaudRate);
            Log.i("lxw"," BT3:"+tmp);
            // If an error happens here, let it propagate up the call chain since this is the fallback.
            tmp.openUsbConnection(connectionExtras);
            Log.i("lxw"," BT5:");
            mUsbConnection = tmp;
            Log.i("lxw"," BT6:"+mUsbConnection);
            Log.d(TAG, "Using open-source usb connection.");
        }
    }

继续看代码:tmp.openUsbConnection(connectionExtras);

    protected void openUsbConnection(Bundle extras) throws IOException {
        Log.i("lxw"," cdc");
        extrasHolder.set(extras);
        registerUsbPermissionBroadcastReceiver();

        // Get UsbManager from Android.
        UsbManager manager = (UsbManager) mContext.getSystemService(Context.USB_SERVICE);

        //Get the list of available devices
        List<UsbDevice> availableDevices = UsbSerialProber.getAvailableSupportedDevices(manager);
        Log.i("lxw"," availableDevices:"+availableDevices);
        if (availableDevices.isEmpty())
        {
            Log.i("lxw"," CDC NULL");
            Log.d(TAG, "No Devices found");
            throw new IOException("No Devices found");
        }

        //Pick the first device
        UsbDevice device = availableDevices.get(0);
        if (manager.hasPermission(device))
        {
            openUsbDevice(device, extras);
        } else {
            removeWatchdog();

            scheduler = Executors.newSingleThreadScheduledExecutor();
            scheduler.schedule(permissionWatchdog, 15, TimeUnit.SECONDS);
            Log.d(TAG, "Requesting permission to access usb device " + device.getDeviceName());
            manager.requestPermission(device, usbPermissionIntent);
        }
    }

继续看代码:openUsbDevice(device, extras);

    private void openUsbDevice(UsbDevice device, Bundle extras) throws IOException {
        //从Android获取UsbManager。--- Get UsbManager from Android.
        UsbManager manager = (UsbManager) mContext.getSystemService(Context.USB_SERVICE);

        //找到第一个可用的驱动程序。--- Find the first available driver.
        final UsbSerialDriver serialDriver = UsbSerialProber.openUsbDevice(manager, device);

        if (serialDriver == null) {
            Log.d(TAG, "No Devices found");
            throw new IOException("No Devices found");
        } else {
            Log.d(TAG, "Opening using Baud rate " + mBaudRate);
            try {
                serialDriver.open();
                serialDriver.setParameters(mBaudRate, 8, UsbSerialDriver.STOPBITS_1, UsbSerialDriver.PARITY_NONE);

                serialDriverRef.set(serialDriver);

                onUsbConnectionOpened(extras);
            } catch (IOException e)
            {
                Log.e(TAG, "Error setting up device: " + e.getMessage(), e);
                try {
                    serialDriver.close();
                } catch (IOException e2) {
                    // Ignore.
                }
            }
        }
    }

继续onUsbConnectionOpened(extras);

       protected void onUsbConnectionOpened(Bundle extras) {
            parentConnection.onConnectionOpened(extras);
        }
    /**
     * 打开设备,执行mManagerTask任务
     * @param extras
     */
    protected void onConnectionOpened(Bundle extras) {
        if (mConnectionStatus.compareAndSet(MAVLINK_CONNECTING, MAVLINK_CONNECTED)) {
            extrasHolder.set(extras);
            mLogger.logInfo(TAG, "Starting manager thread.");
            Log.i("lxw"," mManagerTask主要处理mavlink信息");
            mTaskThread = new Thread(mManagerTask, "MavLinkConnection-Manager Thread");
            mTaskThread.start();
        }
    }

匿名内部类实现最终mavlink协议处理相关

    private final Runnable mManagerTask = new Runnable() {

        @Override
        public void run() {
            Thread sendingThread = null;
            Thread loggingThread = null;

            try {
                final long connectionTime = System.currentTimeMillis();
                mConnectionTime.set(connectionTime);
                reportConnect(connectionTime);

                // Launch the 'Sending' thread
                mLogger.logInfo(TAG, "Starting sender thread.");
                Log.i("lxw"," Starting new thread.");
                sendingThread = new Thread(mSendingTask, "MavLinkConnection-Sending Thread");
                sendingThread.start();

                //Launch the 'Logging' thread
                mLogger.logInfo(TAG, "Starting logging thread.");
                Log.i("lxw"," Starting sender thread.");
                loggingThread = new Thread(mLoggingTask, "MavLinkConnection-Logging Thread");
                loggingThread.start();
                //协议解析
                final Parser parser = new Parser();
                //com.MAVLink.Parser
                Log.i("lxw"," parser:"+parser);
                //服务解析状态
                parser.stats.resetStats();
                //创建解析数据数组
                final byte[] readBuffer = new byte[READ_BUFFER_SIZE];

                while (mConnectionStatus.get() == MAVLINK_CONNECTED)
                {
                    //读取bufferSize
                    int bufferSize = readDataBlock(readBuffer);
                    //bufferSize=
                    Log.i("lxw"," bufferSize:"+bufferSize);
                    handleData(parser, bufferSize, readBuffer);
                }
            } catch (IOException e) {
                // Ignore errors while shutting down
                if (mConnectionStatus.get() != MAVLINK_DISCONNECTED) {
                    reportIOException(e);
                    mLogger.logErr(TAG, e);
                }
            } finally {
                if (sendingThread != null && sendingThread.isAlive()) {
                    sendingThread.interrupt();
                }

                if (loggingThread != null && loggingThread.isAlive()) {
                    loggingThread.interrupt();
                }

                disconnect();
                mLogger.logInfo(TAG, "Exiting manager thread.");
            }
        }

        /**
         * 开始进行数据处理
         * @param parser
         * @param bufferSize
         * @param buffer
         */
        private void handleData(Parser parser, int bufferSize, byte[] buffer) {
            if (bufferSize < 1) {
                return;
            }

            for (int i = 0; i < bufferSize; i++)
            {
                //解析包
                MAVLinkPacket receivedPacket = parser.mavlink_parse_char(buffer[i] & 0x00ff);
                if (receivedPacket != null)
                {
                    queueToLog(receivedPacket);
                    Log.i("lxw"," 开始报告解析:");
                    reportReceivedPacket(receivedPacket);
                }
            }
        }
    };

其中比较重要的APP往外界发送的内容:
其中比较重要的APP往外界发送的内容:
其中比较重要的APP往外界发送的内容:

    private final Runnable mSendingTask = new Runnable() {
        @Override
        public void run() {
            try {
                while (mConnectionStatus.get() == MAVLINK_CONNECTED) {
                    byte[] buffer = mPacketsToSend.take();

                    try {
                        sendBuffer(buffer);
                        queueToLog(buffer);
                    } catch (IOException e) {
                        reportIOException(e);
                        mLogger.logErr(TAG, e);
                    }
                }
            } catch (InterruptedException e) {
                mLogger.logVerbose(TAG, e.getMessage());
            } finally {
                disconnect();
            }
        }
    };

我们这里重点还是关注接收
在这里插入图片描述

核心处理:handleData(parser, bufferSize, readBuffer);
核心处理:handleData(parser, bufferSize, readBuffer);
核心处理:handleData(parser, bufferSize, readBuffer);

        private void handleData(Parser parser, int bufferSize, byte[] buffer) {
            if (bufferSize < 1) {
                return;
            }

            for (int i = 0; i < bufferSize; i++)
            {
                //解析包
                MAVLinkPacket receivedPacket = parser.mavlink_parse_char(buffer[i] & 0x00ff);
                if (receivedPacket != null)
                {
                    queueToLog(receivedPacket);
                    Log.i("lxw"," 开始报告解析:");
                    reportReceivedPacket(receivedPacket);
                }
            }
        }
    private void reportReceivedPacket(MAVLinkPacket packet)
    {
        //监听者是否非空
        if (mListeners.isEmpty())
        {
            return;
        }

        for (MavLinkConnectionListener listener : mListeners.values())
        {
            Log.i("lxw"," onReceivePacket:");
            //接收数据处理
            listener.onReceivePacket(packet);
        }
    }
        public void onReceivePacket(final MAVLinkPacket packet) {
            Log.i("lxw"," notifyReceivedData:");
            listener.notifyReceivedData(packet);
            Log.i("lxw"," receivedMsg END:");
        }
    public void notifyReceivedData(MAVLinkPacket packet) {

        MAVLinkMessage receivedMsg = packet.unpack();
        Log.i("lxw"," receivedMsg:"+receivedMsg);
        if (receivedMsg == null)
            return;
        Log.i("lxw"," MSGID:"+receivedMsg.msgid);
        if (receivedMsg.msgid == msg_command_ack.MAVLINK_MSG_ID_COMMAND_ACK)
        {
            Log.i("lxw"," command ack:");
            msg_command_ack commandAck = (msg_command_ack) receivedMsg;
            handleCommandAck(commandAck);
        } else
         {
             Log.i("lxw"," Handler receiveData :");
            this.mavLinkMsgHandler.receiveData(receivedMsg);
            if (this.drone != null)
            {
                Log.i("lxw"," 核心处理mavlink信息:");
                this.drone.onMavLinkMessageReceived(receivedMsg);
            }
        }

        if (!connectedApps.isEmpty())
        {
            Log.i("lxw"," spp :"+connectedApps.values());
            //org.droidplanner.services.android.impl.api.DroneApi
            for (DroneApi droneEventsListener : connectedApps.values())
            {
                droneEventsListener.onReceivedMavLinkMessage(receivedMsg);
            }
        }
    }

这里的代码有两部分比较重要:带应答和不应答的协议,我们这主要关注不带应答的协议。
在这里插入图片描述
先调用Ardupilot中的方法:

    public void onMavLinkMessageReceived(MAVLinkMessage message) {
        Log.i("lxw","ardupilot message.sysid :"+message.sysid );

        if ((message.sysid != this.getSysid()) && !isMavLinkMessageException(message)) {
            // Reject Messages that are not for the system id
            return;
        }

        // Filter Components IDs to be specifically the IDs that can be processed
        int compId = message.compid;
        if (compId != AUTOPILOT_COMPONENT_ID
                && compId != ARTOO_COMPONENT_ID
                && compId != SiK_RADIO_FIXED_COMPID ){
            return;
        }

        if (!getParameterManager().processMessage(message)) {

            getWaypointManager().processMessage(message);
            getCalibrationSetup().processMessage(message);

            switch (message.msgid) {

                case msg_statustext.MAVLINK_MSG_ID_STATUSTEXT:
                    // These are any warnings sent from APM:Copter with
                    // gcs_send_text_P()
                    // This includes important thing like arm fails, prearm fails, low
                    // battery, etc.
                    // also less important things like "erasing logs" and
                    // "calibrating barometer"
                    msg_statustext msg_statustext = (msg_statustext) message;
                    processStatusText(msg_statustext);
                    break;

                case msg_vfr_hud.MAVLINK_MSG_ID_VFR_HUD:
                    processVfrHud((msg_vfr_hud) message);
                    break;

                case msg_raw_imu.MAVLINK_MSG_ID_RAW_IMU:
                    msg_raw_imu msg_imu = (msg_raw_imu) message;
                    mag.newData(msg_imu);
                    break;

                case msg_radio.MAVLINK_MSG_ID_RADIO:
                    msg_radio m_radio = (msg_radio) message;
                    processSignalUpdate(m_radio.rxerrors, m_radio.fixed, m_radio.rssi,
                            m_radio.remrssi, m_radio.txbuf, m_radio.noise, m_radio.remnoise);
                    break;

                case msg_rc_channels_raw.MAVLINK_MSG_ID_RC_CHANNELS_RAW:
                    rc.setRcInputValues((msg_rc_channels_raw) message);
                    break;

                case msg_servo_output_raw.MAVLINK_MSG_ID_SERVO_OUTPUT_RAW:
                    rc.setRcOutputValues((msg_servo_output_raw) message);
                    break;

                case msg_camera_feedback.MAVLINK_MSG_ID_CAMERA_FEEDBACK:
                    getCamera().newImageLocation((msg_camera_feedback) message);
                    break;

                case msg_mount_status.MAVLINK_MSG_ID_MOUNT_STATUS:
                    processMountStatus((msg_mount_status) message);
                    break;

                case msg_named_value_int.MAVLINK_MSG_ID_NAMED_VALUE_INT:
                    processNamedValueInt((msg_named_value_int) message);
                    break;

                //*************** Magnetometer calibration messages handling *************//
                case msg_mag_cal_progress.MAVLINK_MSG_ID_MAG_CAL_PROGRESS:
                case msg_mag_cal_report.MAVLINK_MSG_ID_MAG_CAL_REPORT:
                    getMagnetometerCalibration().processCalibrationMessage(message);
                    break;

                default:
                    break;
            }
        }
        Log.i("lxw","super message.sysid :"+message.sysid );
        //这里实现调用父类的方法
        super.onMavLinkMessageReceived(message);
    }
    public void onMavLinkMessageReceived(MAVLinkMessage message) {
        Log.i("lxw","message.sysid :"+message.sysid );
        if ( (message.sysid != this.getSysid()) && !isMavLinkMessageException(message) )
        {
            // Reject messages that are not for this drone's system id
            return;
        }

        onHeartbeat(message);

        switch (message.msgid) {
            case msg_radio_status.MAVLINK_MSG_ID_RADIO_STATUS:
                msg_radio_status m_radio_status = (msg_radio_status) message;
                processSignalUpdate(m_radio_status.rxerrors, m_radio_status.fixed, m_radio_status.rssi,
                        m_radio_status.remrssi, m_radio_status.txbuf, m_radio_status.noise, m_radio_status.remnoise);
                break;

            case msg_attitude.MAVLINK_MSG_ID_ATTITUDE:
                msg_attitude m_att = (msg_attitude) message;
                processAttitude(m_att);
                break;

            case msg_heartbeat.MAVLINK_MSG_ID_HEARTBEAT:
                msg_heartbeat msg_heart = (msg_heartbeat) message;
                processHeartbeat(msg_heart);
                break;

            case msg_vibration.MAVLINK_MSG_ID_VIBRATION:
                msg_vibration vibrationMsg = (msg_vibration) message;
                processVibrationMessage(vibrationMsg);
                break;

            //*************** EKF State handling ******************//
            case msg_ekf_status_report.MAVLINK_MSG_ID_EKF_STATUS_REPORT:
                processEfkStatus((msg_ekf_status_report) message);
                break;

            case msg_sys_status.MAVLINK_MSG_ID_SYS_STATUS:
                msg_sys_status m_sys = (msg_sys_status) message;
                processSysStatus(m_sys);
                break;

            case msg_global_position_int.MAVLINK_MSG_ID_GLOBAL_POSITION_INT:
                processGlobalPositionInt((msg_global_position_int) message);
                break;

            case msg_gps_raw_int.MAVLINK_MSG_ID_GPS_RAW_INT:
                processGpsState((msg_gps_raw_int) message);
                break;

            case msg_mission_item.MAVLINK_MSG_ID_MISSION_ITEM:
                processHomeUpdate((msg_mission_item) message);
                break;

            case msg_mission_current.MAVLINK_MSG_ID_MISSION_CURRENT:
                missionStats.setWpno(((msg_mission_current) message).seq);
                break;

            case msg_mission_item_reached.MAVLINK_MSG_ID_MISSION_ITEM_REACHED:
                missionStats.setLastReachedWaypointNumber(((msg_mission_item_reached) message).seq);
                break;

            case msg_nav_controller_output.MAVLINK_MSG_ID_NAV_CONTROLLER_OUTPUT:
                msg_nav_controller_output m_nav = (msg_nav_controller_output) message;
                setDisttowpAndSpeedAltErrors(m_nav.wp_dist, m_nav.alt_error, m_nav.aspd_error);
                break;
        }
    }

整体协议处理流程就是这样,后续会细致分析。

最后

以上就是善良黑米为你收集整理的打造自己的HelloDrone 无人机APP过程《1》目录摘要1.实例化无人机及地面站控制对象2.绑定服务3.增加连接点击事件及进行连接的全部内容,希望文章能够帮你解决打造自己的HelloDrone 无人机APP过程《1》目录摘要1.实例化无人机及地面站控制对象2.绑定服务3.增加连接点击事件及进行连接所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(43)

评论列表共有 0 条评论

立即
投稿
返回
顶部