Controlling Vex from an Android device

Greetings!

So I’ve got an assignment to make an app to control Vex IQ from an android device (there’s actually more to it, but the connection to Vex is what I’m having trouble with). Here’s the scenario:

The phone’s paired with another device and advertising to your robot, and that’s where I ran into trouble. I’ve read your Smart Radio Developer Guide (SDK), but I still don’t quite understand the entire scenario.

There’s advert data:
// GAP - Advertisement data byte] advertData = {
// Flags; this sets the device to use limited discoverable
// mode (advertises for 30 seconds at a time) instead of general
// discoverable mode (advertises indefinitely)
0x02, // length of this data
0x01, // GAP_ADTYPE_FLAGS,
0x05, // DEFAULT_DISCOVERABLE_MODE | BREDR_NOT_SUPPORTED,
0x0B, // Length of the following data
//0xFF, // GAP_ADTYPE_MANUFACTURER_SPECIFIC,
-1, // GAP_ADTYPE_MANUFACTURER_SPECIFIC,
0x11, // VEX Company ID byte1
0x11, // VEX Company ID byte0
0x01, // MAJOR_VERSION of the radio firmware,
0x01, // MINOR_VERSION of the radio firmware,
0x06, // The following 32 bits are out SSN (Little Endian)
0x12, // Example SSN = 987654
0x0F,
0x00,
0x01, // MAJOR_VERSION of the peripheral’s software
0x05 // MINOR_VERSION of the peripheral’s software
};

Java’s bytes are always signed, therefore 0xFF will not compile. -1 should be the correct equivalent. Right?

Also, don’t worry, I’m changing the array to have correct vex_id values at runtime:

final byte] result = toByteArray(vexId);

advertData[9] = result[0];
advertData[10] = result[1];
advertData[11] = result[2];
advertData[12] = result[3];

Then there are three different UUID’s:

// JS_Data
static final String *UUID_STRING *= “08590F7E-DB05-467E-8757-72F6FAEB13B5”;
// Data_Brain_RX
static final String *UUID_STRING *= “08590F7E-DB05-467E-8757-72F6FAEB13F5”;
// Data_Brain_TX
static final String *UUID_STRING *= “08590F7E-DB05-467E-8757-72F6FAEB1306”;

To which one of these should I advertise the initial data? Should be JS_Data, right?

Everything is succesful, the advertisement went out. Now, what should happen at this point? Because nothing’s happening. Should I instantly send out another advertisement? What should the content of that be?

It would even be helpful if you could point me to the correct location in your iOS Objective-C samples.

Best wishes,
Niki

Hey Nikitah,

We have yet to develop an example for Smart Radio communications with an Android device. But I can point you to the IOS code that does what your are needing to do.

Since you talk about your Device advertising I assume you have an Android device with the BLE Peripheral feature enabled. So that’s good.

It looks like to setup your advertiser you need to use use the call:

AdvertisementData.Builder dataBuilder = new AdvertisementData.Builder();
dataBuilder.setManufacturerData(0x1111, advertisingBytes);

Where advertisingBytes should look like this: (you will still have to fill in your robot’s ID)

// GAP - Advertisement data
byte] advertisingBytes = {
0x01, // MAJOR_VERSION of the radio firmware,
0x02, // MINOR_VERSION of the radio firmware,
0x06, // The following 32 bits are out SSN (Little Endian)
0x12, // Example SSN = 987654
0x0F,
0x00,
0x01, // MAJOR_VERSION of the peripheral’s software
0x06 // MINOR_VERSION of the peripheral’s software
};

With this code your advertisement should be caught by the VEX IQ brain. But you will need to add the VEX joystick service and it’s characteristics to your GATT server in order for the brain to successfully connect. So all you should have to do now is build your Joystick service object and add the JS_Data and JS_Rate Characteristics to that service. The example of where we do this on IOS is in the VEXSmartLink.m file of the SDK. If you look at line 405 you can see where we setup our characteristics with the correct GUIDs and add them to our service(line 420).

From what I can see in the documentation for Android it should look something like this in Java:

BluetoothGattService vexControllerService = new BluetoothGattService(UUID.fromString(“08590F7E-DB05-467E-8757-72F6FAEB13A5”),BluetoothGattService.SERVICE_TYPE_PRIMARY);

BluetoothGattCharacteristic JS_DATA_Char = new BluetoothGattCharacteristic(UUID.fromString(“08590F7E-DB05-467E-8757-72F6FAEB13B5”), BluetoothGattCharacteristic.PROPERTY_READ | BluetoothGattCharacteristic.PROPERTY_NOTIFY | BluetoothGattCharacteristic.PROPERTY_INDICATE, BluetoothGattCharacteristic.PERMISSION_READ | BluetoothGattCharacteristic.PERMISSION_WRITE);

BluetoothGattCharacteristic JS_RATE_Char = new BluetoothGattCharacteristic(UUID.fromString(“08590F7E-DB05-467E-8757-72F6FAEB13C5”), BluetoothGattCharacteristic.PROPERTY_READ | BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE | BluetoothGattCharacteristic.PROPERTY_WRITE, BluetoothGattCharacteristic.PERMISSION_READ | BluetoothGattCharacteristic.PERMISSION_WRITE);

vexControllerService.addCharacteristic(JS_DATA_Char);
vexControllerService.addCharacteristic(JS_RATE_Char);
ble.addService(vexControllerService);

You will want to set all this up before you start advertising. Now if you connect to the GATT server callback you should get a callback when the brain connects and when it subscribes to indications on the JS_DATA characteristic. This is when you will know you are connected. (see line 502 in VEXSmartLink.m). Once the brain subscribes you will need to start sending BLE indications on this characteristic at least once every second or the brain will timeout and close it’s BLE connection. But of course you will want to send the data much faster than that if you want your controller app to be useful. One packet every 25ms is recommended.

Here is the data format for the message in C code (you will have to convert this into Java):

typedef struct //Warning: Keep these long word aligned (4 byte)
{
UInt8 j1_y :8; //0
UInt8 j1_x :8; //1
UInt8 j2_y :8; //2
UInt8 j2_x :8; //3
UInt8 buttons :8; //4
UInt8 battery :8; //5
UInt8 mainPwr :8; //6
UInt8 idletime :8; //7 (minutes)
UInt8 pwrOffDelay :8; //8
UInt8 contCount :8; //9 Add + 1 each message
UInt8 unused :8; //10
UInt8 unused1 :8; //11
UInt8 unused2 :8; //12
UInt8 unused3 :8; //13
} JoyStickRecord;

The only values you really care about are the joystick values (j1_y,j1_x,j2_y,j2_x) and the buttons value (see Global.h in the SDK for button constants).

All of this except for the joystick data message creation is done in the VEXSmartLink.m file in the SDK.

I hope this helps. Sorry for the lack of examples for Android. We hope to have an SDK for Android at some point.

Please let us know if you come across any other issues. And once you get it all working we would love to see pictures or videos of your project.

Thanks
Levi