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;
        }
    }

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

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

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

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • plc-300c语言编程,PLC初学者必备:7个PLC经典编程[通俗易懂]

    plc-300c语言编程,PLC初学者必备:7个PLC经典编程[通俗易懂]1、自锁(启保停)自锁需要并联一个线圈输出的常开触点,当启动后,并联的常开触点起到维持输出继续闭合的作用,就是自锁。我们最常用的启保停程序就是自锁。2、连锁和互锁(正反转)连锁就是用两个或多个信号控制一个输出,其实就是触点串联程序。互锁其实是连锁的扩展,利用一个程序行的输出信号作为其他程序行的连锁触点,相互之间进行运行控制,就是互锁。当两个或多个输出之间存在不能同时运行的情况时,就需要用到互锁,比…

  • datagrip2020激活码mac_通用破解码

    datagrip2020激活码mac_通用破解码,https://javaforall.cn/100143.html。详细ieda激活码不妨到全栈程序员必看教程网一起来了解一下吧!

  • linux ghost备份_pe备份linux系统

    linux ghost备份_pe备份linux系统Windows系统备份可以用ghost工具软件完成,Linux系统不能完全依赖于ghost工具,一则是ghost本身是有版权的软件,二则ghost只支持ext2、ext3文件系统的Linux分区,不支持reiserfs、xfs等比较高级的文件系统,ghost本身并不备份mbr,因此常造成恢复后的系统grub出错的问题。  linux本身自带有着优秀的备份工具,传统如:tar、cpio、dd,新的有

  • Protel 99SE详细安装教程(附安装包)[通俗易懂]

    Protel 99SE详细安装教程(附安装包)[通俗易懂]安装步骤:安装前先关闭杀毒软件和360卫士,注意安装路径不能有中文,安装包路径也不要有中文。安装前请断网。试装系统:win1064bit1.解压安装包。2.以管理员身份运行Protel99SE文件夹里的安装程序。3.点击下一步。4.name和company随便输入,打开SerialNO.txt,将serialNO输入到安装界面的code栏中。5.选择好安装目录(不要出现中…

  • 如何用python画一个心形图_python画心形名字

    如何用python画一个心形图_python画心形名字Python可以使用turtle库来画爱心。Turtle库是Python语言中一个很流行的绘制图像的函数库,想象一个小乌龟,在一个横轴为x、纵轴为y的坐标系原点,(0,0)位置开始,它根据一组函数指令的控制,在这个平面坐标系中移动,从而在它爬行的路径上绘制了图形。实现代码如下:fromturtleimport*pensize(1)pencolor(‘red’)fillcolor(‘pink…

  • pycharm 激活码 2021【2021.7最新】

    (pycharm 激活码 2021)JetBrains旗下有多款编译器工具(如:IntelliJ、WebStorm、PyCharm等)在各编程领域几乎都占据了垄断地位。建立在开源IntelliJ平台之上,过去15年以来,JetBrains一直在不断发展和完善这个平台。这个平台可以针对您的开发工作流进行微调并且能够提供…

发表回复

您的电子邮箱地址不会被公开。

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