Skip to content

Commit

Permalink
Investigated Issue #4
Browse files Browse the repository at this point in the history
There does not appear to be a way to get the bluetooth module into the correct mode. I have an outstanding request at robolink.
I did learn that setting the broadcast mode to mute returns it to the yellow state.
I also learned that making the mode active provides the additional messages I was missing.
Code around connecting has been reworked and should be more robust. More testing with multiple drones is required.
  • Loading branch information
Stephen Cerruti authored and e3-cerruti committed Jan 14, 2018
1 parent ee7907e commit 4715b05
Show file tree
Hide file tree
Showing 9 changed files with 323 additions and 107 deletions.
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
package org.jointheleague.jcodrone.protocol.information;
package org.jointheleague.jcodrone;

import org.jointheleague.jcodrone.protocol.InvalidDataSizeException;
import org.jointheleague.jcodrone.protocol.Serializable;
import org.jointheleague.jcodrone.protocol.link.LinkDiscoveredDevice;

import java.io.ByteArrayOutputStream;
import java.nio.ByteBuffer;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class Address implements Serializable {
private final byte[] address;
Expand All @@ -17,6 +21,26 @@ public static byte getSize() {
return 6;
}

public static Address parse(byte[] data) throws InvalidDataSizeException {
if (data.length != getSize()) {
throw new InvalidDataSizeException(getSize(), data.length);
}

ByteBuffer buffer = ByteBuffer.wrap(data);
byte[] address = new byte[getSize()];
buffer.get(address, 0, getSize());
return new Address(address);
}

public static Address parse(String address) {
byte[] bytes = Stream.of(address.split(":")).mapToInt(i -> Integer.parseInt(i, 16)).
collect(ByteArrayOutputStream::new, (baos, i) -> baos.write((byte) i),
(baos1, baos2) -> baos1.write(baos2.toByteArray(), 0, baos2.size()))
.toByteArray();

return new Address(bytes);
}

public byte getInstanceSize() {
return getSize();
}
Expand All @@ -28,15 +52,12 @@ public byte[] toArray() {
return buffer.array();
}

public static Address parse(byte[] data) throws InvalidDataSizeException {
if (data.length != getSize()) {
throw new InvalidDataSizeException(getSize(), data.length);
}

ByteBuffer buffer = ByteBuffer.wrap(data);
byte[] address = new byte[6];
buffer.get(address, 0, getSize());
return new Address(address);
public byte[] getAddress() {
return address;
}

@Override
public String toString() {
return LinkDiscoveredDevice.intStream(address).mapToObj(i -> String.format("%02X", 0x0FF & i)).collect(Collectors.joining(":"));
}
}
64 changes: 44 additions & 20 deletions src/main/java/org/jointheleague/jcodrone/CoDrone.java
Original file line number Diff line number Diff line change
Expand Up @@ -133,44 +133,57 @@ public void close() {
*
* @throws CoDroneNotFoundException Thrown if no drone is found. Check logs to determine what serial port was used.
*/
public void connect() throws CoDroneNotFoundException, MessageNotSentException {
connect(null, null, false);
public void connect() throws CoDroneNotFoundException, MessageNotSentException, InterruptedException {
connectPort(null);
link(null);
}

/**
* This connect method allows the connection to a specific drone over bluetooth via the controller connected
* to the specified serial por. Additionally the controller can be reset before the connection is attempted.
* The default connection method connects to the nearest drone connected to the last available serial port
* enumerated by the operating system.
*
* @param portName System name of the serial port connected to the controller.
* @param deviceName The name of the drone to connect to.
* @param resetSystem Resets the controller before attempting to connect to the drone.
* @throws CoDroneNotFoundException Thrown if the specified port or drone can not be found.
* @throws CoDroneNotFoundException Thrown if no drone is found. Check logs to determine what serial port was used.
*/
@SuppressWarnings("WeakerAccess")
public void connect(String portName, String deviceName, boolean resetSystem) throws CoDroneNotFoundException, MessageNotSentException {
public void connect(String deviceName) {
if (deviceName != null && !deviceName.isEmpty() && deviceName.length() != 12) {
throw new IllegalArgumentException(
String.format("Invalid device name length %s.", deviceName.length()));
}

connectPort(null);
}

/**
* The default connection method connects to the nearest drone connected to the last available serial port
* enumerated by the operating system.
*
* @throws CoDroneNotFoundException Thrown if no drone is found. Check logs to determine what serial port was used.
*/
public void connect(Address address) {
connectPort(null);
}

/**
* This connect method allows the connection to a specific drone over bluetooth via the controller connected
* to the specified serial port. Additionally the controller can be reset before the connection is attempted.
*
* @param portName System name of the serial port connected to the controller.
* @throws CoDroneNotFoundException Thrown if the specified port or drone can not be found.
*/
private void connectPort(String portName) {
if (comPort == null || !comPort.isOpen()) {
if (portName == null || portName.isEmpty()) {
open();
} else {
open(portName);
//Thread.sleep(100);
}
} else if (!portName.equalsIgnoreCase(comPort.getSystemPortName())) {
close();
open(portName);
//Thread.sleep(100);
}

// system reset
if (resetSystem) {
link.resetSystem();
}
}

private void link(String deviceName) throws MessageNotSentException, CoDroneNotFoundException, InterruptedException {
link.connect(deviceName);
}

Expand All @@ -197,6 +210,12 @@ void transfer(Header header, Serializable data) {

comPort.writeBytes(message.array(), message.capacity());
log.info("Sent: {}", DatatypeConverter.printHexBinary(message.array()));
// TODO: Remove this wait
try {
Thread.sleep(60);
} catch (InterruptedException e) {
log.warn("Sleep interrupted after sending command.");
}
}


Expand All @@ -209,7 +228,7 @@ void transfer(Header header, Serializable data) {
*
* @param type The command from the CommandType enumeration.
*/
public void sendCommand(CommandType type) throws MessageNotSentException {
public void sendCommand(CommandType type) {
sendCommand(type, (byte) 0);
}

Expand All @@ -222,7 +241,7 @@ public void sendCommand(CommandType type) throws MessageNotSentException {
*
* @param type The command from the CommandType enumeration.
*/
public void sendCommand(CommandType type, byte option) throws MessageNotSentException {
public void sendCommand(CommandType type, byte option) {
Command command = new Command(type, option);

sendMessage(command);
Expand Down Expand Up @@ -404,9 +423,10 @@ public void underAttack() throws MessageNotSentException {
Flight.underAttack(this);
}

public void flyDirect(DirectControl control) throws MessageNotSentException {
public void flyDirect(DirectControl control) {
Flight.flyDirect(this, control);
}

/**
* Sets a single light mode.
*
Expand Down Expand Up @@ -601,4 +621,8 @@ public TrimFlight getTrimFlight() {
public boolean isFlightMode() {
return (internals.getState() != null && internals.getState().isFlightMode());
}

public void requestLinkState() throws MessageNotSentException {
link.requestState();
}
}
Loading

0 comments on commit 4715b05

Please sign in to comment.