package com.codegy.aerlink.connection.characteristic;
import android.util.Log;
import java.util.Queue;
/**
* Created by Guiye on 12/10/16.
*/
public class CharacteristicSubscriberThread extends Thread {
private static final String LOG_TAG = CharacteristicSubscriberThread.class.getSimpleName();
public enum State {
ErrorConnecting,
ErrorSubscribing,
Connecting,
Discovering,
Subscribing,
Bonding,
Ready
}
private CharacteristicSubscriber subscriber;
private Queue<CharacteristicIdentifier> subscribeRequests;
private volatile boolean run = true;
private boolean wait = false;
private State state = State.Connecting;
private final Object lock = new Object();
public CharacteristicSubscriberThread(CharacteristicSubscriber subscriber) {
this.subscriber = subscriber;
}
@Override
public void run() {
while (run) {
try {
synchronized (lock) {
switch (state) {
case ErrorConnecting:
wait = true;
subscriber.onConnectionFailed();
while (wait) { lock.wait(); }
break;
case ErrorSubscribing:
wait = true;
subscriber.onSubscribingFailed();
while (wait) { lock.wait(); }
break;
case Connecting:
state = State.ErrorConnecting;
lock.wait(5000);
break;
case Discovering:
state = State.ErrorSubscribing;
lock.wait(2000);
break;
case Bonding:
state = State.ErrorSubscribing;
lock.wait(5000);
break;
case Subscribing:
Log.d(LOG_TAG, "Subscribe Requests: " + (subscribeRequests == null ? -1 :subscribeRequests.size()));
CharacteristicIdentifier characteristic = subscribeRequests.peek();
if (characteristic != null) {
subscriber.subscribeCharacteristic(characteristic);
state = State.ErrorSubscribing;
lock.wait(3000);
break;
}
else {
state = State.Ready;
}
case Ready:
run = false;
subscriber.onConnectionReady();
break;
}
}
}
catch (InterruptedException ignored) {}
}
}
/**
* Kill the thread, discards all characteristics in queue
*/
public void kill() {
run = false;
interrupt();
}
public void reset() {
state = State.Connecting;
subscribeRequests = null;
interrupt();
}
public void setConnecting() {
synchronized(lock) {
state = State.Connecting;
wait = false;
lock.notify();
}
}
public void setDiscovering() {
synchronized(lock) {
state = State.Discovering;
wait = false;
lock.notify();
}
}
public void setBonding() {
synchronized(lock) {
state = State.Bonding;
wait = false;
lock.notify();
}
}
public void setSubscribeRequests(Queue<CharacteristicIdentifier> subscribeRequests) {
synchronized(lock) {
this.subscribeRequests = subscribeRequests;
if (subscribeRequests.size() > 0) {
state = State.Subscribing;
}
else {
state = State.ErrorSubscribing;
}
wait = false;
lock.notify();
}
}
/**
* Remove current characteristic and keep going with the next one
*/
public void remove() {
synchronized(lock) {
Log.d(LOG_TAG, "Characteristic subscribed");
subscribeRequests.poll();
if (subscribeRequests.size() > 0) {
state = State.Subscribing;
}
else {
state = State.Ready;
}
wait = false;
lock.notify();
}
}
}