Wifi connection works, but not hard-wire to RC

I am able to get the autoConnection facility to connect when I am connected to the Anafi’s wifi but not when I am hard-wired directly into the RC (using the same code from the sample app). Any ideas on getting the RC connection working?

1 Like

Apologies, missed the bit about adding com.parrot.dronesdk as an external accessory protocol!

Hi, I have a similar problem. My observer for AutoConnection does not get called.

#################################

    this.groundSdk = GroundSdk.newSession(getApplicationContext(), savedInstanceState);

    this.refAutoConnection = getGroundSdk().getFacility(AutoConnection.class, obj -> {
        Log.i(TAG, "AutoConnection Status Change!");
        if(obj != null) {
            Log.i(TAG, "AutoConnection Status Change: " + obj.getStatus());
            DevelopmentFragment.sendMessageToLog("AutoConnection Status Change: " + obj.getStatus());

            if(obj.getRemoteControl() != null) {
                if(remoteControl == null) {
                    remoteControl = obj.getRemoteControl();
                    remoteControl.getState(remoteControlObserver);
                } else {
                    if(!remoteControl.getUid().equals(obj.getRemoteControl().getUid())) {
                        remoteControl = obj.getRemoteControl();
                        remoteControl.getState(remoteControlObserver);
                    }
                }
            }

            if(obj.getDrone() != null) {
                if(drone == null) {
                    drone = obj.getDrone();
                    drone.getState(droneObserver);
                } else {
                    if(!drone.getUid().equals(obj.getDrone().getUid())) {
                        drone = obj.getDrone();
                        drone.getState(droneObserver);
                    }
                }
            }

        }
    });

#################################
Here’s my Logcat output:

01-29 14:41:57.747 8029 8108 I arsdk.mux: Starting USB accessory MUX backend controller
01-29 14:41:57.818 8029 8029 I de.mindur.drone.BaseActivity: Starting AutoConnection: true
01-29 14:41:57.886 8029 8090 I Adreno : QUALCOMM build : 624c5bb, I109c45a694
01-29 14:41:57.886 8029 8090 I Adreno : Build Date : 05/22/18
01-29 14:41:57.886 8029 8090 I Adreno : OpenGL ES Shader Compiler Version: EV031.22.00.01_06
01-29 14:41:57.886 8029 8090 I Adreno : Local Branch :
01-29 14:41:57.886 8029 8090 I Adreno : Remote Branch :
01-29 14:41:57.886 8029 8090 I Adreno : Remote Branch :
01-29 14:41:57.886 8029 8090 I Adreno : Reconstruct Branch :
01-29 14:41:57.887 8029 8090 D vndksupport: Loading /vendor/lib64/hw/gralloc.msm8953.so from current namespace instead of sphal namespace.
01-29 14:41:57.891 8029 8090 I Adreno : PFP: 0x005ff087, ME: 0x005ff063
01-29 14:41:57.895 8029 8090 I zygote64: android::hardware::configstore::V1_0::ISurfaceFlingerConfigs::hasWideColorDisplay retrieved: 0
01-29 14:41:57.896 8029 8090 I OpenGLRenderer: Initialized EGL, version 1.4
01-29 14:41:57.896 8029 8090 D OpenGLRenderer: Swap behavior 2
01-29 14:41:58.042 8029 8029 I arsdk.mux: Trying to discover a plugged RC accessory
01-29 14:41:58.043 8029 8029 I arsdk.mux: Installing RC: UsbAccessory[mManufacturer=Parrot, mModel=Skycontroller 3, mDescription=Parrot Skycontroller 3, mVersion=1.6.1, mUri=https://play.google.com/store/apps/details?id=com.parrot.freeflight6, mSerial=PI040443AA8G068763]
01-29 14:41:58.043 8029 8108 I arsdk.mux: Opening RC accessory:UsbAccessory[mManufacturer=Parrot, mModel=Skycontroller 3, mDescription=Parrot Skycontroller 3, mVersion=1.6.1, mUri=https://play.google.com/store/apps/details?id=com.parrot.freeflight6, mSerial=PI040443AA8G068763]
01-29 14:41:58.044 8029 8108 I arsdk.mux: RC accessory opened [fd: 69]
01-29 14:41:58.045 8029 8108 I mux : mux ref: 2
01-29 14:41:58.045 8029 8108 I mux : Opening channel 0x00000003
01-29 14:41:58.045 8029 8108 I mux : mux ref: 3
01-29 14:41:58.045 8029 8108 I mux : Opening channel 0x00000002
01-29 14:41:58.046 8029 8108 I arsdkctrl: discovery ‘mux’: start
01-29 14:41:58.047 8029 8108 I mux : CHANNEL_CLOSE chanid=0x00000001 type=NORMAL
01-29 14:41:58.047 8029 8108 I arsdkctrl: discovery ‘mux’: add device name=‘Skycontroller 3’ id=‘PI040443AA8G068763’
01-29 14:41:58.048 8029 8108 I arsdk : Device added: 40683
01-29 14:41:58.082 8029 8090 D vndksupport: Loading /vendor/lib64/hw/android.hardware.graphics.mapper@2.0-impl.so from current namespace instead of sphal namespace.
01-29 14:41:58.082 8029 8090 D vndksupport: Loading /vendor/lib64/hw/gralloc.msm8953.so from current namespace instead of sphal namespace.
01-29 14:41:58.108 8029 8108 I mux : Opening channel 0x00000001
01-29 14:41:58.108 8029 8108 I mux : CHANNEL_OPEN chanid=0x00000001 type=NORMAL
01-29 14:41:58.122 8029 8108 I mux : mux ref: 4
01-29 14:41:58.133 8029 8029 I arsdkengine.ctrl: TCP proxy created [address: 127.0.0.1, port: 43189]

Can you explain what exactly you had to do to be able to connect the RC properly?

I can’t reconstruct how I solved this, but somehow it’s working now.

I don’t use the. auto connection stuff. Have you looked into the getDroneList and getRemoteList methods in the gsdk session object? You’ll get much more control over the discovery and connection process this way inside of an activity:

    private GroundSdk discoverySession = null;
    private DeviceListObserver deviceListObserver = new DeviceListObserver();
    private Ref<List<DroneListEntry>> droneListRef = null;
    private Ref<List<RemoteControlListEntry>> remoteListRef = null;
...
        // you'l likely want to handle this in onCreate
        discoverySession = GroundSdk.newSession(ctx, null);
...
        // you'll want to probably handle this in OnResume and OnPause
        deviceListObserver.addListener(ctx);
...
        if (droneListRef == null) {
            // noinspection unchecked
            droneListRef = discoverySession.getDroneList(it -> true, deviceListObserver);
        }
        if (remoteListRef == null) {
            // noinspection unchecked
            remoteListRef = discoverySession.getRemoteControlList(it -> true, deviceListObserver);
        }

and here’s a nifty observer class you can play with / build upon:

package xxxx;

import com.parrot.drone.groundsdk.Ref;
import com.parrot.drone.groundsdk.device.DroneListEntry;
import com.parrot.drone.groundsdk.device.RemoteControlListEntry;
import xxx.interfaces.DeviceListListener;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import androidx.annotation.Nullable;

import static xxx.logEvent;

@SuppressWarnings("unchecked")
public class DeviceListObserver implements Ref.Observer {
    private final String CLASS_NAME = this.getClass().getSimpleName();
    private final Collection<DeviceListListener> deviceListListeners = new ArrayList<>();

    @Override
    public synchronized void onChanged(@Nullable Object o) {
        if (o instanceof List) {
            final List deviceList = (List) o;

            if (deviceList.size() > 0) {
                if (deviceList.get(0) instanceof DroneListEntry) {
                    final List<DroneListEntry> droneList = (List<DroneListEntry>) deviceList;

                    for (DeviceListListener listener : deviceListListeners) {
                        listener.onDroneListChanged(droneList);
                    }
                    logEvent(CLASS_NAME, "drone list changed");
                } else {
                    final List<RemoteControlListEntry> remoteList = (List<RemoteControlListEntry>) deviceList;

                    for (DeviceListListener listener : deviceListListeners) {
                        listener.onRemoteListChanged(remoteList);
                    }
                    logEvent(CLASS_NAME, "remote list changed");
                }
            }
        }
    }

    public synchronized boolean addListener(final DeviceListListener listener) {
        return !deviceListListeners.contains(listener) && deviceListListeners.add(listener);
    }

    public synchronized boolean removeListener(final DeviceListListener listener) {
        return deviceListListeners.remove(listener);
    }
}

and the interface you’ll want to implement in your activity:

package xxx.interfaces;

import com.parrot.drone.groundsdk.device.DroneListEntry;
import com.parrot.drone.groundsdk.device.RemoteControlListEntry;

import java.util.List;

public interface DeviceListListener {
    void onDroneListChanged(final List<DroneListEntry> droneList);
    void onRemoteListChanged(final List<RemoteControlListEntry> remoteList);
}

Back in your activity you’ll want to have something like this:

    @Override
    public void onDroneListChanged(@NonNull List<DroneListEntry> droneList) {
        if (isRemoteConnected()) {
            for (DroneListEntry entry : droneList) {
                if (entry.getState().getConnectionState() == DeviceState.ConnectionState.CONNECTED) {
                        //
                        // the drone is already connected via a remote so just grab a reference to it via (session.getDrone())
                       //
                        return;
                }
            }
        } else {
            if (!isDroneConnected()) {
                for (DroneListEntry entry : droneList) {
                    final Drone drone = getDroneSession().getDrone(entry.getUid(), ctx);
                    if (drone == null) break;

                    if (drone.getState().getConnectionState() == DeviceState.ConnectionState.DISCONNECTED && drone.getState().canBeConnected()) {
                        //
                        // you probably want to connect to the drone here via drone.connect();.
                        //
                        return;
                    }

                    if (drone.getState().getConnectionState() == DeviceState.ConnectionState.CONNECTED) {
                       //
                       // apparently the drone is already connected, just grab a reference to it
                       //
                        return;
                    }
                }
            }
        }
    }

    @Override
    public void onRemoteListChanged(@NonNull List<RemoteControlListEntry> remoteList) {
        if (!isRemoteConnected()) {
            for (RemoteControlListEntry entry : remoteList) {
                final RemoteControl remote = getRemoteSession().getRemoteControl(entry.getUid(), ctx);
                if (remote == null) break;

                if (remote.getState().getConnectionState() == DeviceState.ConnectionState.DISCONNECTED && remote.getState().canBeConnected()) {
                    //
                    // you probably want to connect to the remote via remote.connect()
                    //
                    return;
                }

                if (remote.getState().getConnectionState() == DeviceState.ConnectionState.CONNECTED) {
                    //
                    // apparently the remote is already connected, just grab a reference to it
                    //
                    return;
                }
            }
        }
    }

oh, and don’t forget to release your Refs if you are in an unmanaged session:

        if (droneListRef != null) {
            droneListRef.close();
            droneListRef = null;
        }
        if (remoteListRef != null) {
            remoteListRef.close();
            remoteListRef = null;
        }