欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  科技

打造自己的HelloDrone 无人机APP过程《1》

程序员文章站 2022-06-16 13:21:14
目录文章目录目录摘要1.实例化无人机及地面站控制对象2.绑定服务3.增加连接点击事件及进行连接摘要本节主要记录HelloDrone的连接过程及Mavlink协议解析过程。1.实例化无人机及地面站控制对象核心内容:controlTower = new ControlTower(context);drone = new Drone(context); @Override /** * 重写onCreate方法,在onStart方法之前启动 */ pro...

目录

摘要

本节主要记录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()方法
打造自己的HelloDrone 无人机APP过程《1》
我们需要在清单文件中声明服务
打造自己的HelloDrone 无人机APP过程《1》
我们去看下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后,会返回
打造自己的HelloDrone 无人机APP过程《1》
打造自己的HelloDrone 无人机APP过程《1》
打造自己的HelloDrone 无人机APP过程《1》
然后会执行

    /**
     * 创建连接服务
     */
    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.增加连接点击事件及进行连接

打造自己的HelloDrone 无人机APP过程《1》
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));
打造自己的HelloDrone 无人机APP过程《1》

    /**
     * 执行行为
     */
    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连接,重点执行的函数

打造自己的HelloDrone 无人机APP过程《1》


    /**
     * 执行连接任务
     * @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();
            }
        }
    };

我们这里重点还是关注接收
打造自己的HelloDrone 无人机APP过程《1》

核心处理: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);
            }
        }
    }

这里的代码有两部分比较重要:带应答和不应答的协议,我们这主要关注不带应答的协议。
打造自己的HelloDrone 无人机APP过程《1》
先调用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;
        }
    }

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

本文地址:https://blog.csdn.net/lixiaoweimashixiao/article/details/108851017

相关标签: android学习