2015-08-03 23:09:49 +02:00
|
|
|
package nodomain.freeyourgadget.gadgetbridge.impl;
|
2015-03-21 18:18:07 +01:00
|
|
|
|
2015-04-13 01:01:52 +02:00
|
|
|
import android.content.Context;
|
|
|
|
import android.content.Intent;
|
2015-04-20 11:58:59 +02:00
|
|
|
import android.os.Parcel;
|
|
|
|
import android.os.Parcelable;
|
2015-04-13 01:01:52 +02:00
|
|
|
import android.support.v4.content.LocalBroadcastManager;
|
2015-05-12 06:28:11 +02:00
|
|
|
|
|
|
|
import org.slf4j.Logger;
|
|
|
|
import org.slf4j.LoggerFactory;
|
2015-04-13 01:01:52 +02:00
|
|
|
|
2015-08-03 23:09:49 +02:00
|
|
|
import nodomain.freeyourgadget.gadgetbridge.model.DeviceType;
|
|
|
|
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
|
|
|
import nodomain.freeyourgadget.gadgetbridge.R;
|
|
|
|
|
2015-04-20 11:58:59 +02:00
|
|
|
public class GBDevice implements Parcelable {
|
2015-04-19 14:34:18 +02:00
|
|
|
public static final String ACTION_DEVICE_CHANGED
|
2015-07-18 23:38:59 +02:00
|
|
|
= "nodomain.freeyourgadget.gadgetbridge.gbdevice.action.device_changed";
|
2015-04-20 22:43:47 +02:00
|
|
|
public static final Creator<GBDevice> CREATOR = new Creator<GBDevice>() {
|
2015-04-20 11:58:59 +02:00
|
|
|
@Override
|
|
|
|
public GBDevice createFromParcel(Parcel source) {
|
|
|
|
return new GBDevice(source);
|
|
|
|
}
|
2015-03-22 23:38:51 +01:00
|
|
|
|
2015-04-20 11:58:59 +02:00
|
|
|
@Override
|
|
|
|
public GBDevice[] newArray(int size) {
|
|
|
|
return new GBDevice[size];
|
|
|
|
}
|
|
|
|
};
|
2015-05-12 06:28:11 +02:00
|
|
|
private static final Logger LOG = LoggerFactory.getLogger(GBDevice.class);
|
2015-05-05 00:48:02 +02:00
|
|
|
public static final short RSSI_UNKNOWN = 0;
|
2015-05-10 00:05:29 +02:00
|
|
|
public static final short BATTERY_UNKNOWN = -1;
|
2015-05-05 00:48:02 +02:00
|
|
|
public static final String EXTRA_DEVICE = "device";
|
2015-04-20 11:58:59 +02:00
|
|
|
private final String mName;
|
|
|
|
private final String mAddress;
|
2015-05-05 00:48:02 +02:00
|
|
|
private final DeviceType mDeviceType;
|
2015-04-20 11:58:59 +02:00
|
|
|
private String mFirmwareVersion = null;
|
2015-04-20 12:48:32 +02:00
|
|
|
private String mHardwareVersion = null;
|
2015-04-20 11:58:59 +02:00
|
|
|
private State mState = State.NOT_CONNECTED;
|
2015-05-10 00:05:29 +02:00
|
|
|
private short mBatteryLevel = BATTERY_UNKNOWN;
|
2015-04-19 22:20:47 +02:00
|
|
|
private String mBatteryState;
|
2015-05-05 00:48:02 +02:00
|
|
|
private short mRssi = RSSI_UNKNOWN;
|
2015-06-06 00:40:16 +02:00
|
|
|
private String mBusyTask;
|
2015-04-19 22:20:47 +02:00
|
|
|
|
2015-05-05 00:48:02 +02:00
|
|
|
public GBDevice(String address, String name, DeviceType deviceType) {
|
2015-04-20 11:58:59 +02:00
|
|
|
mAddress = address;
|
|
|
|
mName = name;
|
2015-05-05 00:48:02 +02:00
|
|
|
mDeviceType = deviceType;
|
2015-04-20 23:25:46 +02:00
|
|
|
validate();
|
2015-04-20 11:58:59 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
private GBDevice(Parcel in) {
|
|
|
|
mName = in.readString();
|
|
|
|
mAddress = in.readString();
|
2015-05-05 00:48:02 +02:00
|
|
|
mDeviceType = DeviceType.values()[in.readInt()];
|
2015-04-20 11:58:59 +02:00
|
|
|
mFirmwareVersion = in.readString();
|
2015-04-20 12:48:32 +02:00
|
|
|
mHardwareVersion = in.readString();
|
2015-04-20 11:58:59 +02:00
|
|
|
mState = State.values()[in.readInt()];
|
|
|
|
mBatteryLevel = (short) in.readInt();
|
|
|
|
mBatteryState = in.readString();
|
2015-05-05 00:48:02 +02:00
|
|
|
mRssi = (short) in.readInt();
|
2015-06-06 00:40:16 +02:00
|
|
|
mBusyTask = in.readString();
|
|
|
|
|
2015-04-20 23:25:46 +02:00
|
|
|
validate();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void writeToParcel(Parcel dest, int flags) {
|
|
|
|
dest.writeString(mName);
|
|
|
|
dest.writeString(mAddress);
|
2015-05-05 00:48:02 +02:00
|
|
|
dest.writeInt(mDeviceType.ordinal());
|
2015-04-20 23:25:46 +02:00
|
|
|
dest.writeString(mFirmwareVersion);
|
|
|
|
dest.writeString(mHardwareVersion);
|
|
|
|
dest.writeInt(mState.ordinal());
|
|
|
|
dest.writeInt(mBatteryLevel);
|
|
|
|
dest.writeString(mBatteryState);
|
2015-05-05 00:48:02 +02:00
|
|
|
dest.writeInt(mRssi);
|
2015-06-06 00:40:16 +02:00
|
|
|
dest.writeString(mBusyTask);
|
2015-04-20 23:25:46 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
private void validate() {
|
|
|
|
if (getAddress() == null) {
|
|
|
|
throw new IllegalArgumentException("address must not be null");
|
|
|
|
}
|
2015-03-22 00:34:54 +01:00
|
|
|
}
|
|
|
|
|
2015-03-21 18:18:07 +01:00
|
|
|
public String getName() {
|
2015-04-20 11:58:59 +02:00
|
|
|
return mName;
|
2015-03-21 18:18:07 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
public String getAddress() {
|
2015-04-20 11:58:59 +02:00
|
|
|
return mAddress;
|
2015-03-21 18:18:07 +01:00
|
|
|
}
|
|
|
|
|
2015-03-22 23:38:51 +01:00
|
|
|
public String getFirmwareVersion() {
|
2015-04-20 11:58:59 +02:00
|
|
|
return mFirmwareVersion;
|
2015-03-22 23:38:51 +01:00
|
|
|
}
|
|
|
|
|
2015-03-31 23:34:19 +02:00
|
|
|
public void setFirmwareVersion(String firmwareVersion) {
|
2015-04-20 11:58:59 +02:00
|
|
|
mFirmwareVersion = firmwareVersion;
|
2015-03-31 23:34:19 +02:00
|
|
|
}
|
|
|
|
|
2015-04-20 12:48:32 +02:00
|
|
|
public String getHardwareVersion() {
|
|
|
|
return mHardwareVersion;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setHardwareVersion(String hardwareVersion) {
|
|
|
|
mHardwareVersion = hardwareVersion;
|
|
|
|
}
|
|
|
|
|
2015-04-19 02:37:29 +02:00
|
|
|
public boolean isConnected() {
|
2015-04-20 11:58:59 +02:00
|
|
|
return mState.ordinal() >= State.CONNECTED.ordinal();
|
2015-04-19 02:37:29 +02:00
|
|
|
}
|
2015-04-19 11:28:03 +02:00
|
|
|
|
2015-05-28 00:26:41 +02:00
|
|
|
public boolean isInitializing() {
|
|
|
|
return mState == State.INITIALIZING;
|
|
|
|
}
|
|
|
|
|
2015-04-19 02:37:29 +02:00
|
|
|
public boolean isInitialized() {
|
2015-04-20 11:58:59 +02:00
|
|
|
return mState.ordinal() >= State.INITIALIZED.ordinal();
|
2015-04-19 02:37:29 +02:00
|
|
|
}
|
2015-04-19 11:28:03 +02:00
|
|
|
|
2015-04-20 10:50:30 +02:00
|
|
|
public boolean isConnecting() {
|
2015-04-20 11:58:59 +02:00
|
|
|
return mState == State.CONNECTING;
|
2015-04-20 10:50:30 +02:00
|
|
|
}
|
|
|
|
|
2015-06-06 00:40:16 +02:00
|
|
|
public boolean isBusy() {
|
|
|
|
return mBusyTask != null;
|
|
|
|
}
|
|
|
|
|
|
|
|
public String getBusyTask() {
|
|
|
|
return mBusyTask;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Marks the device as busy, performing a certain task. While busy, no other operations will
|
|
|
|
* be performed on the device.
|
2015-06-13 00:32:48 +02:00
|
|
|
* <p/>
|
2015-06-06 00:40:16 +02:00
|
|
|
* Note that nested busy tasks are not supported, every single call to #setBusyTask()
|
|
|
|
* or unsetBusy() has an effect.
|
2015-06-13 00:32:48 +02:00
|
|
|
*
|
2015-06-06 00:40:16 +02:00
|
|
|
* @param task a textual name of the task to be performed, possibly displayed to the user
|
|
|
|
*/
|
|
|
|
public void setBusyTask(String task) {
|
|
|
|
if (task == null) {
|
|
|
|
throw new IllegalArgumentException("busy task must not be null");
|
|
|
|
}
|
|
|
|
if (mBusyTask != null) {
|
|
|
|
LOG.warn("Attempt to mark device as busy with: " + task + ", but is already busy with: " + mBusyTask);
|
|
|
|
}
|
2015-07-04 22:22:59 +02:00
|
|
|
LOG.info("Mark device as busy: " + mBusyTask);
|
2015-06-06 00:40:16 +02:00
|
|
|
mBusyTask = task;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Marks the device as not busy anymore.
|
|
|
|
*/
|
|
|
|
public void unsetBusyTask() {
|
|
|
|
if (mBusyTask == null) {
|
|
|
|
LOG.error("Attempt to mark device as not busy anymore, but was not busy before.");
|
2015-07-04 22:22:59 +02:00
|
|
|
return;
|
2015-06-06 00:40:16 +02:00
|
|
|
}
|
2015-07-04 22:22:59 +02:00
|
|
|
LOG.info("Mark device as NOT busy anymore: " + mBusyTask);
|
2015-06-06 00:40:16 +02:00
|
|
|
mBusyTask = null;
|
|
|
|
}
|
|
|
|
|
2015-03-22 23:38:51 +01:00
|
|
|
public State getState() {
|
2015-04-20 11:58:59 +02:00
|
|
|
return mState;
|
2015-03-22 23:38:51 +01:00
|
|
|
}
|
|
|
|
|
2015-03-31 23:34:19 +02:00
|
|
|
public void setState(State state) {
|
2015-04-20 11:58:59 +02:00
|
|
|
mState = state;
|
2015-05-28 00:26:41 +02:00
|
|
|
if (state.ordinal() <= State.CONNECTED.ordinal()) {
|
|
|
|
unsetDynamicState();
|
|
|
|
}
|
2015-05-10 00:05:29 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
private void unsetDynamicState() {
|
|
|
|
setBatteryLevel(BATTERY_UNKNOWN);
|
|
|
|
setBatteryState(null);
|
|
|
|
setFirmwareVersion(null);
|
|
|
|
setRssi(RSSI_UNKNOWN);
|
2015-06-06 23:13:26 +02:00
|
|
|
if (mBusyTask != null) {
|
|
|
|
unsetBusyTask();
|
|
|
|
}
|
2015-03-31 23:34:19 +02:00
|
|
|
}
|
|
|
|
|
2015-05-05 11:16:57 +02:00
|
|
|
public String getStateString() {
|
2015-04-20 11:58:59 +02:00
|
|
|
switch (mState) {
|
2015-03-22 23:38:51 +01:00
|
|
|
case NOT_CONNECTED:
|
2015-05-01 01:26:12 +02:00
|
|
|
return GBApplication.getContext().getString(R.string.not_connected);
|
2015-03-22 23:38:51 +01:00
|
|
|
case CONNECTING:
|
2015-05-01 01:26:12 +02:00
|
|
|
return GBApplication.getContext().getString(R.string.connecting);
|
2015-03-22 23:38:51 +01:00
|
|
|
case CONNECTED:
|
2015-05-01 01:26:12 +02:00
|
|
|
return GBApplication.getContext().getString(R.string.connected);
|
2015-05-28 00:26:41 +02:00
|
|
|
case INITIALIZING:
|
|
|
|
return GBApplication.getContext().getString(R.string.initializing);
|
2015-04-19 15:21:15 +02:00
|
|
|
case INITIALIZED:
|
2015-05-01 01:26:12 +02:00
|
|
|
return GBApplication.getContext().getString(R.string.initialized);
|
2015-03-22 23:38:51 +01:00
|
|
|
}
|
2015-05-01 01:26:12 +02:00
|
|
|
return GBApplication.getContext().getString(R.string.unknown_state);
|
2015-03-22 23:38:51 +01:00
|
|
|
}
|
|
|
|
|
2015-05-05 11:16:57 +02:00
|
|
|
|
2015-03-22 23:38:51 +01:00
|
|
|
public String getInfoString() {
|
2015-04-20 11:58:59 +02:00
|
|
|
if (mFirmwareVersion != null) {
|
2015-04-20 12:48:32 +02:00
|
|
|
if (mHardwareVersion != null) {
|
2015-05-05 11:16:57 +02:00
|
|
|
return GBApplication.getContext().getString(R.string.connectionstate_hw_fw, mHardwareVersion, mFirmwareVersion);
|
2015-04-20 12:48:32 +02:00
|
|
|
}
|
2015-05-05 11:16:57 +02:00
|
|
|
return GBApplication.getContext().getString(R.string.connectionstate_fw, mFirmwareVersion);
|
2015-03-22 00:34:54 +01:00
|
|
|
} else {
|
2015-05-05 11:16:57 +02:00
|
|
|
return "";
|
2015-03-22 00:34:54 +01:00
|
|
|
}
|
2015-03-21 18:18:07 +01:00
|
|
|
}
|
2015-03-31 23:34:19 +02:00
|
|
|
|
2015-05-05 00:48:02 +02:00
|
|
|
public DeviceType getType() {
|
|
|
|
return mDeviceType;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setRssi(short rssi) {
|
|
|
|
if (rssi < 0) {
|
2015-05-12 06:28:11 +02:00
|
|
|
LOG.warn("illegal rssi value " + rssi + ", setting to RSSI_UNKNOWN");
|
2015-05-05 00:48:02 +02:00
|
|
|
mRssi = RSSI_UNKNOWN;
|
|
|
|
} else {
|
|
|
|
mRssi = rssi;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the device specific signal strength value, or #RSSI_UNKNOWN
|
|
|
|
*/
|
|
|
|
public short getRssi() {
|
|
|
|
return mRssi;
|
2015-03-31 23:34:19 +02:00
|
|
|
}
|
|
|
|
|
2015-04-19 02:37:29 +02:00
|
|
|
// TODO: this doesn't really belong here
|
2015-04-13 01:01:52 +02:00
|
|
|
public void sendDeviceUpdateIntent(Context context) {
|
2015-04-19 14:34:18 +02:00
|
|
|
Intent deviceUpdateIntent = new Intent(ACTION_DEVICE_CHANGED);
|
2015-05-05 00:48:02 +02:00
|
|
|
deviceUpdateIntent.putExtra(EXTRA_DEVICE, this);
|
2015-04-13 01:01:52 +02:00
|
|
|
LocalBroadcastManager.getInstance(context).sendBroadcast(deviceUpdateIntent);
|
|
|
|
}
|
2015-04-13 11:22:03 +02:00
|
|
|
|
2015-04-20 11:58:59 +02:00
|
|
|
@Override
|
|
|
|
public int describeContents() {
|
|
|
|
return 0;
|
2015-03-31 23:34:19 +02:00
|
|
|
}
|
|
|
|
|
2015-04-20 11:58:59 +02:00
|
|
|
@Override
|
|
|
|
public boolean equals(Object obj) {
|
|
|
|
if (obj == this) {
|
|
|
|
return true;
|
|
|
|
}
|
2015-07-10 21:35:28 +02:00
|
|
|
if (!(obj instanceof GBDevice)) {
|
|
|
|
return false;
|
|
|
|
}
|
2015-04-20 11:58:59 +02:00
|
|
|
if (((GBDevice) obj).getAddress().equals(this.mAddress)) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2015-04-20 23:25:46 +02:00
|
|
|
public int hashCode() {
|
|
|
|
return mAddress.hashCode() ^ 37;
|
2015-03-31 23:34:19 +02:00
|
|
|
}
|
2015-04-19 22:20:47 +02:00
|
|
|
|
|
|
|
/**
|
2015-05-10 00:05:29 +02:00
|
|
|
* Ranges from 0-100 (percent), or -1 if unknown
|
2015-04-20 11:58:59 +02:00
|
|
|
*
|
2015-05-10 00:05:29 +02:00
|
|
|
* @return the battery level in range 0-100, or -1 if unknown
|
2015-04-19 22:20:47 +02:00
|
|
|
*/
|
|
|
|
public short getBatteryLevel() {
|
|
|
|
return mBatteryLevel;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setBatteryLevel(short batteryLevel) {
|
2015-05-25 23:14:02 +02:00
|
|
|
if ((batteryLevel >= 0 && batteryLevel <= 100) || batteryLevel == BATTERY_UNKNOWN) {
|
2015-04-19 22:20:47 +02:00
|
|
|
mBatteryLevel = batteryLevel;
|
|
|
|
} else {
|
2015-05-12 06:28:11 +02:00
|
|
|
LOG.error("Battery level musts be within range 0-100: " + batteryLevel);
|
2015-04-19 22:20:47 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns a string representation of the battery state.
|
|
|
|
*/
|
|
|
|
public String getBatteryState() {
|
2015-05-01 01:26:12 +02:00
|
|
|
return mBatteryState != null ? mBatteryState : GBApplication.getContext().getString(R.string._unknown_);
|
2015-04-19 22:20:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
public void setBatteryState(String batteryState) {
|
|
|
|
mBatteryState = batteryState;
|
|
|
|
}
|
2015-04-20 11:58:59 +02:00
|
|
|
|
2015-07-10 21:35:28 +02:00
|
|
|
@Override
|
|
|
|
public String toString() {
|
|
|
|
return "Device " + getName() + ", " + getAddress() + ", " + getStateString();
|
|
|
|
}
|
|
|
|
|
2015-04-20 11:58:59 +02:00
|
|
|
public enum State {
|
|
|
|
// Note: the order is important!
|
|
|
|
NOT_CONNECTED,
|
|
|
|
CONNECTING,
|
|
|
|
CONNECTED,
|
2015-05-28 00:26:41 +02:00
|
|
|
INITIALIZING,
|
2015-08-14 23:37:47 +02:00
|
|
|
/**
|
|
|
|
* Means that the device is connected AND all the necessary initialization steps
|
|
|
|
* have been performed. At the very least, this means that basic information like
|
|
|
|
* device name, firmware version, hardware revision (as applicable) is available
|
|
|
|
* in the GBDevice.
|
|
|
|
*/
|
2015-04-20 11:58:59 +02:00
|
|
|
INITIALIZED
|
|
|
|
}
|
2015-03-21 18:18:07 +01:00
|
|
|
}
|