drone无人机app下载苹果版_drone无人机教程视频

drone无人机app下载苹果版_drone无人机教程视频目录文章目录目录摘要1.实例化无人机及地面站控制对象2.绑定服务3.增加连接点击事件及进行连接摘要本节主要记录HelloDrone的连接过程及Mavlink协议解析过程。1.实例化无人机及地面站控制对象核心内容:controlTower=newControlTower(context);drone=newDrone(context);@Override/***重写onCreate方法,在onStart方法之前启动*/pro

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

目录

摘要

本节主要记录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;
        }
    }

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

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/170568.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • Python环境配置及项目建立

    Python环境配置及项目建立一、安装PythonPython比较稳定的两个版本是Python3.5和Python2.7,我用的是Python2.7,下载地址是:https://www.python.org/downloa

    2022年7月5日
    21
  • CFileDialog类应用详解

    CFileDialog类应用详解原文地址 http blog csdn net bxwang1 article details 构造函数原型 CFileDialog BOOLbOpenFil nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp LPCTSTRlpszD NULL nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp LPCTSTRlpszF NULL nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp D

    2025年11月9日
    7
  • 亚马逊跨境电商ERP_跨境电商铺货模式和精品模式

    亚马逊跨境电商ERP_跨境电商铺货模式和精品模式所谓跨境电商ERP,简单来说就是提高效率的工具,节省时间不用去做重复的事情跨境电商ERP系统:亚马逊erp,对接亚马逊、wish、ebay、速卖通、shopify、shopee虾皮、lazada等跨境电商平台。跨境电商ERP源码,跨境电商erp系统源码:亚马逊erp源码、wisherp源码、ebayerp源码、速卖通erp源码、shopifyerp源码、shopee虾皮erp源码、lazada来赞达erp源码。对接亚马逊、wish、ebay、速卖通、shopify、shopee虾皮、lazada等.

    2025年11月29日
    6
  • Week04-面向对象设计与继承

    Week04-面向对象设计与继承

    2022年3月7日
    37
  • C语言模拟银行家算法

    C语言模拟银行家算法银行家算法需求:一个程序对资源的最大需求量不超过系统的最大资源程序可以分多次申请资源,但是申请资源的总量不能超过最大需求量当系统现有资源不能满足程序的需求时,可以推迟分配资源,但是总能满足程序对资源的需求当程序获得了全部的资源后,要在有限的时间内归还资源系统的安全/不安全状态:在程序申请资源时,当系统的拥有的资源不能满足程序剩余所需的全部资源时,则处于不安全状态C代码实现:头文件的导入和预定义#include<stdio.h>#include<stdli

    2022年7月22日
    6
  • accept函数的用法_requestscope用法

    accept函数的用法_requestscope用法这是在学《Windows网络编程(第二版)》第六章时制作的一个例子由于书中没有给出简洁的例子,本人在学这里时就费了很多时间。现在把完成的代码贴出来,供大家参考。下面包括了主程序部分,工作线程在(2)中贴出,由于代码太长。本程序在VS2003编译器编译运行。在6.0下可能需要稍加修改。#include#include#include#include    //微软扩展的类库

    2022年9月29日
    2

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号