2024-01-10 18:54:00 +01:00
|
|
|
/* Copyright (C) 2015-2024 Andreas Shimokawa, Arjan Schrijver, Carsten
|
|
|
|
Pfeiffer, Daniel Dakhno, Daniele Gobbetti, José Rebelo, Petr Vaněk, Taavi
|
|
|
|
Eomäe, Uwe Hermann
|
2017-03-10 14:53:19 +01:00
|
|
|
|
|
|
|
This file is part of Gadgetbridge.
|
|
|
|
|
|
|
|
Gadgetbridge is free software: you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU Affero General Public License as published
|
|
|
|
by the Free Software Foundation, either version 3 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
Gadgetbridge is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU Affero General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU Affero General Public License
|
2024-01-10 18:54:00 +01:00
|
|
|
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
2015-08-03 23:09:49 +02:00
|
|
|
package nodomain.freeyourgadget.gadgetbridge.impl;
|
2015-03-21 18:18:07 +01:00
|
|
|
|
2021-10-16 22:40:30 +02:00
|
|
|
import static nodomain.freeyourgadget.gadgetbridge.model.BatteryState.UNKNOWN;
|
|
|
|
|
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-05-12 06:28:11 +02:00
|
|
|
|
2020-06-12 22:49:16 +02:00
|
|
|
import androidx.annotation.NonNull;
|
|
|
|
import androidx.annotation.Nullable;
|
|
|
|
import androidx.localbroadcastmanager.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
|
|
|
|
2016-03-16 00:14:38 +01:00
|
|
|
import java.util.ArrayList;
|
2016-03-25 23:54:42 +01:00
|
|
|
import java.util.Collections;
|
2018-07-28 17:23:58 +02:00
|
|
|
import java.util.HashMap;
|
2016-03-16 00:14:38 +01:00
|
|
|
import java.util.List;
|
|
|
|
|
2015-08-03 23:09:49 +02:00
|
|
|
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
|
|
|
import nodomain.freeyourgadget.gadgetbridge.R;
|
2023-09-27 23:11:02 +02:00
|
|
|
import nodomain.freeyourgadget.gadgetbridge.devices.DeviceCoordinator;
|
2015-09-24 14:45:21 +02:00
|
|
|
import nodomain.freeyourgadget.gadgetbridge.model.BatteryState;
|
|
|
|
import nodomain.freeyourgadget.gadgetbridge.model.DeviceType;
|
2016-03-16 00:14:38 +01:00
|
|
|
import nodomain.freeyourgadget.gadgetbridge.model.GenericItem;
|
|
|
|
import nodomain.freeyourgadget.gadgetbridge.model.ItemWithDetails;
|
2015-08-03 23:09:49 +02:00
|
|
|
|
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;
|
2021-10-31 17:36:04 +01:00
|
|
|
public static final short BATTERY_ICON_DEFAULT = -1;
|
|
|
|
public static final short BATTERY_LABEL_DEFAULT = -1;
|
2015-08-19 17:36:53 +02:00
|
|
|
private static final short BATTERY_THRESHOLD_PERCENT = 10;
|
2015-05-05 00:48:02 +02:00
|
|
|
public static final String EXTRA_DEVICE = "device";
|
2021-06-23 20:54:16 +02:00
|
|
|
public static final String EXTRA_UUID = "extraUUID";
|
2022-09-23 02:57:08 +02:00
|
|
|
public static final String EXTRA_UPDATE_SUBJECT = "EXTRA_UPDATE_SUBJECT";
|
2016-03-16 00:14:38 +01:00
|
|
|
private static final String DEVINFO_HW_VER = "HW: ";
|
|
|
|
private static final String DEVINFO_FW_VER = "FW: ";
|
2021-06-02 17:12:59 +02:00
|
|
|
private static final String DEVINFO_FW2_VER = "FW2: ";
|
2016-05-28 11:32:36 +02:00
|
|
|
private static final String DEVINFO_ADDR = "ADDR: ";
|
2016-11-27 09:49:28 +01:00
|
|
|
private static final String DEVINFO_ADDR2 = "ADDR2: ";
|
2021-10-31 17:36:04 +01:00
|
|
|
public static final String BATTERY_INDEX = "battery_index";
|
2016-07-11 00:28:15 +02:00
|
|
|
private String mName;
|
2020-06-12 18:04:53 +02:00
|
|
|
private String mAlias;
|
2022-06-23 23:12:08 +02:00
|
|
|
private String parentFolder;
|
2015-04-20 11:58:59 +02:00
|
|
|
private final String mAddress;
|
2016-11-27 09:49:28 +01:00
|
|
|
private String mVolatileAddress;
|
2015-05-05 00:48:02 +02:00
|
|
|
private final DeviceType mDeviceType;
|
2016-06-14 20:13:08 +02:00
|
|
|
private String mFirmwareVersion;
|
|
|
|
private String mFirmwareVersion2;
|
2016-08-26 20:57:59 +02:00
|
|
|
private String mModel;
|
2015-04-20 11:58:59 +02:00
|
|
|
private State mState = State.NOT_CONNECTED;
|
2021-10-16 22:40:30 +02:00
|
|
|
|
|
|
|
// multiple battery support: at this point we support up to three batteries
|
|
|
|
private int[] mBatteryLevel = {BATTERY_UNKNOWN, BATTERY_UNKNOWN, BATTERY_UNKNOWN};
|
|
|
|
private float[] mBatteryVoltage = {BATTERY_UNKNOWN, BATTERY_UNKNOWN, BATTERY_UNKNOWN};
|
2015-08-19 17:36:53 +02:00
|
|
|
private short mBatteryThresholdPercent = BATTERY_THRESHOLD_PERCENT;
|
2021-10-16 22:40:30 +02:00
|
|
|
private BatteryState[] mBatteryState = {UNKNOWN, UNKNOWN, UNKNOWN};
|
2021-10-31 17:36:04 +01:00
|
|
|
private int[] mBatteryIcons = {BATTERY_ICON_DEFAULT, BATTERY_ICON_DEFAULT, BATTERY_ICON_DEFAULT};
|
|
|
|
private int[] mBatteryLabels = {BATTERY_LABEL_DEFAULT, BATTERY_LABEL_DEFAULT, BATTERY_LABEL_DEFAULT};
|
2021-10-16 22:40:30 +02:00
|
|
|
|
2015-05-05 00:48:02 +02:00
|
|
|
private short mRssi = RSSI_UNKNOWN;
|
2015-06-06 00:40:16 +02:00
|
|
|
private String mBusyTask;
|
2016-03-16 00:14:38 +01:00
|
|
|
private List<ItemWithDetails> mDeviceInfos;
|
2018-07-28 17:23:58 +02:00
|
|
|
private HashMap<String, Object> mExtraInfos;
|
2015-04-19 22:20:47 +02:00
|
|
|
|
2019-10-11 03:46:42 +02:00
|
|
|
private int mNotificationIconConnected = R.drawable.ic_notification;
|
|
|
|
private int mNotificationIconDisconnected = R.drawable.ic_notification_disconnected;
|
|
|
|
private int mNotificationIconLowBattery = R.drawable.ic_notification_low_battery;
|
|
|
|
|
2022-09-29 00:42:15 +02:00
|
|
|
public static enum DeviceUpdateSubject {
|
2022-09-23 02:57:08 +02:00
|
|
|
UNKNOWN,
|
|
|
|
NOTHING,
|
2022-09-25 01:27:26 +02:00
|
|
|
CONNECTION_STATE,
|
|
|
|
DEVICE_STATE,
|
2022-09-23 02:57:08 +02:00
|
|
|
}
|
|
|
|
|
2022-06-23 23:12:08 +02:00
|
|
|
public GBDevice(String address, String name, String alias, String parentFolder, DeviceType deviceType) {
|
|
|
|
this(address, null, name, alias, parentFolder, deviceType);
|
2016-11-27 09:49:28 +01:00
|
|
|
}
|
|
|
|
|
2022-06-23 23:12:08 +02:00
|
|
|
public GBDevice(String address, String address2, String name, String alias, String parentFolder, DeviceType deviceType) {
|
2015-04-20 11:58:59 +02:00
|
|
|
mAddress = address;
|
2016-11-27 09:49:28 +01:00
|
|
|
mVolatileAddress = address2;
|
2016-07-05 21:03:30 +02:00
|
|
|
mName = (name != null) ? name : mAddress;
|
2020-06-12 18:04:53 +02:00
|
|
|
mAlias = alias;
|
2015-05-05 00:48:02 +02:00
|
|
|
mDeviceType = deviceType;
|
2022-06-23 23:12:08 +02:00
|
|
|
this.parentFolder = parentFolder;
|
2015-04-20 23:25:46 +02:00
|
|
|
validate();
|
2015-04-20 11:58:59 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
private GBDevice(Parcel in) {
|
|
|
|
mName = in.readString();
|
2020-06-12 18:04:53 +02:00
|
|
|
mAlias = in.readString();
|
2022-06-23 23:12:08 +02:00
|
|
|
parentFolder = in.readString();
|
2015-04-20 11:58:59 +02:00
|
|
|
mAddress = in.readString();
|
2016-11-27 09:49:28 +01:00
|
|
|
mVolatileAddress = 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();
|
2016-06-14 20:13:08 +02:00
|
|
|
mFirmwareVersion2 = in.readString();
|
2016-08-26 20:57:59 +02:00
|
|
|
mModel = in.readString();
|
2015-04-20 11:58:59 +02:00
|
|
|
mState = State.values()[in.readInt()];
|
2021-10-16 22:40:30 +02:00
|
|
|
mBatteryLevel = in.createIntArray();
|
|
|
|
mBatteryVoltage = in.createFloatArray();
|
2015-08-28 13:53:16 +02:00
|
|
|
mBatteryThresholdPercent = (short) in.readInt();
|
2021-10-16 22:40:30 +02:00
|
|
|
mBatteryState = ordinalsToEnums(in.createIntArray());
|
2021-10-31 17:36:04 +01:00
|
|
|
mBatteryIcons = in.createIntArray();
|
|
|
|
mBatteryLabels = in.createIntArray();
|
2015-05-05 00:48:02 +02:00
|
|
|
mRssi = (short) in.readInt();
|
2015-06-06 00:40:16 +02:00
|
|
|
mBusyTask = in.readString();
|
2016-03-16 00:14:38 +01:00
|
|
|
mDeviceInfos = in.readArrayList(getClass().getClassLoader());
|
2018-07-28 17:23:58 +02:00
|
|
|
mExtraInfos = (HashMap) in.readSerializable();
|
2019-10-11 03:46:42 +02:00
|
|
|
mNotificationIconConnected = in.readInt();
|
|
|
|
mNotificationIconDisconnected = in.readInt();
|
|
|
|
mNotificationIconLowBattery = in.readInt();
|
2015-06-06 00:40:16 +02:00
|
|
|
|
2015-04-20 23:25:46 +02:00
|
|
|
validate();
|
|
|
|
}
|
|
|
|
|
2022-06-23 23:12:08 +02:00
|
|
|
public void copyFromDevice(GBDevice device){
|
|
|
|
if(!device.mAddress.equals(mAddress)){
|
|
|
|
throw new RuntimeException("Cannot copy from device with other address");
|
|
|
|
}
|
|
|
|
|
|
|
|
mName = device.mName;
|
|
|
|
mAlias = device.mAlias;
|
|
|
|
parentFolder = device.parentFolder;
|
|
|
|
mVolatileAddress = device.mVolatileAddress;
|
|
|
|
mFirmwareVersion = device.mFirmwareVersion;
|
|
|
|
mFirmwareVersion2 = device.mFirmwareVersion2;
|
|
|
|
mModel = device.mModel;
|
|
|
|
mState = device.mState;
|
|
|
|
mBatteryLevel = device.mBatteryLevel;
|
|
|
|
mBatteryVoltage = device.mBatteryVoltage;
|
|
|
|
mBatteryThresholdPercent = device.mBatteryThresholdPercent;
|
|
|
|
mBatteryState = device.mBatteryState;
|
|
|
|
mBatteryIcons = device.mBatteryIcons;
|
|
|
|
mBatteryLabels = device.mBatteryLabels;
|
|
|
|
mRssi = device.mRssi;
|
|
|
|
mBusyTask = device.mBusyTask;
|
|
|
|
mDeviceInfos = device.mDeviceInfos;
|
|
|
|
mExtraInfos = device.mExtraInfos;
|
|
|
|
mNotificationIconConnected = device.mNotificationIconConnected;
|
|
|
|
mNotificationIconDisconnected = device.mNotificationIconDisconnected;
|
|
|
|
mNotificationIconLowBattery = device.mNotificationIconLowBattery;
|
|
|
|
}
|
|
|
|
|
2015-04-20 23:25:46 +02:00
|
|
|
@Override
|
|
|
|
public void writeToParcel(Parcel dest, int flags) {
|
|
|
|
dest.writeString(mName);
|
2020-06-12 18:04:53 +02:00
|
|
|
dest.writeString(mAlias);
|
2022-06-23 23:12:08 +02:00
|
|
|
dest.writeString(parentFolder);
|
2015-04-20 23:25:46 +02:00
|
|
|
dest.writeString(mAddress);
|
2016-11-27 09:49:28 +01:00
|
|
|
dest.writeString(mVolatileAddress);
|
2015-05-05 00:48:02 +02:00
|
|
|
dest.writeInt(mDeviceType.ordinal());
|
2015-04-20 23:25:46 +02:00
|
|
|
dest.writeString(mFirmwareVersion);
|
2016-06-14 20:13:08 +02:00
|
|
|
dest.writeString(mFirmwareVersion2);
|
2016-08-26 20:57:59 +02:00
|
|
|
dest.writeString(mModel);
|
2015-04-20 23:25:46 +02:00
|
|
|
dest.writeInt(mState.ordinal());
|
2021-10-16 22:40:30 +02:00
|
|
|
dest.writeIntArray(mBatteryLevel);
|
|
|
|
dest.writeFloatArray(mBatteryVoltage);
|
2015-08-28 13:53:16 +02:00
|
|
|
dest.writeInt(mBatteryThresholdPercent);
|
2021-10-16 22:40:30 +02:00
|
|
|
dest.writeIntArray(enumsToOrdinals(mBatteryState));
|
2021-10-31 17:36:04 +01:00
|
|
|
dest.writeIntArray(mBatteryIcons);
|
|
|
|
dest.writeIntArray(mBatteryLabels);
|
2015-05-05 00:48:02 +02:00
|
|
|
dest.writeInt(mRssi);
|
2015-06-06 00:40:16 +02:00
|
|
|
dest.writeString(mBusyTask);
|
2016-03-16 00:14:38 +01:00
|
|
|
dest.writeList(mDeviceInfos);
|
2018-07-28 17:23:58 +02:00
|
|
|
dest.writeSerializable(mExtraInfos);
|
2019-10-11 03:46:42 +02:00
|
|
|
dest.writeInt(mNotificationIconConnected);
|
|
|
|
dest.writeInt(mNotificationIconDisconnected);
|
|
|
|
dest.writeInt(mNotificationIconLowBattery);
|
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
|
|
|
}
|
|
|
|
|
2021-10-16 22:40:30 +02:00
|
|
|
private int[] enumsToOrdinals(BatteryState[] arrayEnum) {
|
|
|
|
int[] ordinals = new int[arrayEnum.length];
|
|
|
|
for (int i = 0; i < arrayEnum.length; i++) {
|
|
|
|
ordinals[i] = arrayEnum[i].ordinal();
|
|
|
|
}
|
|
|
|
return ordinals;
|
|
|
|
}
|
|
|
|
|
|
|
|
private BatteryState[] ordinalsToEnums(int[] arrayInt){
|
|
|
|
BatteryState[] enums = new BatteryState[arrayInt.length];
|
|
|
|
for(int i = 0; i<arrayInt.length; i++){
|
|
|
|
enums[i]=BatteryState.values()[arrayInt[i]];
|
|
|
|
}
|
|
|
|
return enums;
|
|
|
|
}
|
|
|
|
|
2022-06-23 23:12:08 +02:00
|
|
|
public String getParentFolder() {
|
|
|
|
return parentFolder;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setParentFolder(String parentFolder) {
|
|
|
|
this.parentFolder = parentFolder;
|
|
|
|
}
|
2020-06-12 22:49:16 +02: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
|
|
|
}
|
|
|
|
|
2020-06-12 18:04:53 +02:00
|
|
|
public String getAlias() {
|
|
|
|
return mAlias;
|
|
|
|
}
|
|
|
|
|
2020-06-12 22:49:16 +02:00
|
|
|
public String getAliasOrName() {
|
|
|
|
if (mAlias != null && !mAlias.equals("")) {
|
|
|
|
return mAlias;
|
|
|
|
}
|
|
|
|
return mName;
|
|
|
|
}
|
|
|
|
|
2016-07-11 00:28:15 +02:00
|
|
|
public void setName(String name) {
|
|
|
|
if (name == null) {
|
|
|
|
LOG.warn("Ignoring setting of GBDevice name to null for " + this);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
mName = name;
|
|
|
|
}
|
|
|
|
|
2020-06-12 22:38:37 +02:00
|
|
|
public void setAlias(String alias) {
|
|
|
|
mAlias = alias;
|
|
|
|
}
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2016-11-27 09:49:28 +01:00
|
|
|
public String getVolatileAddress() {
|
|
|
|
return mVolatileAddress;
|
|
|
|
}
|
|
|
|
|
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
|
|
|
}
|
2016-06-14 20:13:08 +02:00
|
|
|
public String getFirmwareVersion2() {
|
|
|
|
return mFirmwareVersion2;
|
|
|
|
}
|
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
|
|
|
}
|
|
|
|
|
2016-09-11 21:15:36 +02:00
|
|
|
/**
|
2017-08-29 23:12:28 +02:00
|
|
|
* Sets the second firmware version (HR or GPS or other component)
|
2016-09-11 21:15:36 +02:00
|
|
|
* @param firmwareVersion2
|
|
|
|
*/
|
2016-06-14 20:13:08 +02:00
|
|
|
public void setFirmwareVersion2(String firmwareVersion2) {
|
|
|
|
mFirmwareVersion2 = firmwareVersion2;
|
|
|
|
}
|
|
|
|
|
2016-11-27 09:49:28 +01:00
|
|
|
public void setVolatileAddress(String volatileAddress) {
|
|
|
|
mVolatileAddress = volatileAddress;
|
|
|
|
}
|
|
|
|
|
2016-08-26 20:57:59 +02:00
|
|
|
/**
|
|
|
|
* Returns the specific model/hardware revision of this device.
|
|
|
|
* This information is not always available, typically only when the device is initialized
|
|
|
|
* @return the model/hardware revision of this device
|
|
|
|
* @see #getType()
|
|
|
|
*/
|
|
|
|
@Nullable
|
|
|
|
public String getModel() {
|
|
|
|
return mModel;
|
2015-04-20 12:48:32 +02:00
|
|
|
}
|
|
|
|
|
2016-08-26 20:57:59 +02:00
|
|
|
public void setModel(String model) {
|
|
|
|
mModel = model;
|
2015-04-20 12:48:32 +02:00
|
|
|
}
|
|
|
|
|
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() {
|
2024-02-26 01:01:46 +01:00
|
|
|
return mState.equalsOrHigherThan(State.INITIALIZED);
|
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;
|
|
|
|
}
|
|
|
|
|
2019-10-11 03:46:42 +02:00
|
|
|
public int getNotificationIconConnected() {
|
|
|
|
return mNotificationIconConnected;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setNotificationIconConnected(int mNotificationIconConnected) {
|
|
|
|
this.mNotificationIconConnected = mNotificationIconConnected;
|
|
|
|
}
|
|
|
|
|
|
|
|
public int getNotificationIconDisconnected() {
|
|
|
|
return mNotificationIconDisconnected;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setNotificationIconDisconnected(int notificationIconDisconnected) {
|
|
|
|
this.mNotificationIconDisconnected = notificationIconDisconnected;
|
|
|
|
}
|
|
|
|
|
|
|
|
public int getNotificationIconLowBattery() {
|
|
|
|
return mNotificationIconLowBattery;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setNotificationIconLowBattery(int mNotificationIconLowBattery) {
|
|
|
|
this.mNotificationIconLowBattery = mNotificationIconLowBattery;
|
|
|
|
}
|
|
|
|
|
2015-06-06 00:40:16 +02:00
|
|
|
/**
|
|
|
|
* 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-09-09 23:39:57 +02:00
|
|
|
LOG.info("Mark device as busy: " + task);
|
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
|
|
|
}
|
|
|
|
|
2018-02-19 18:27:48 +01:00
|
|
|
public int getStateOrdinal() {
|
|
|
|
return mState.ordinal();
|
|
|
|
}
|
|
|
|
|
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() {
|
2021-10-31 17:36:04 +01:00
|
|
|
|
2021-10-16 22:40:30 +02:00
|
|
|
setBatteryLevel(BATTERY_UNKNOWN, 0);
|
|
|
|
setBatteryLevel(BATTERY_UNKNOWN, 1);
|
|
|
|
setBatteryLevel(BATTERY_UNKNOWN, 2);
|
|
|
|
setBatteryState(UNKNOWN, 0);
|
|
|
|
setBatteryState(UNKNOWN, 1);
|
|
|
|
setBatteryState(UNKNOWN, 2);
|
2015-05-10 00:05:29 +02:00
|
|
|
setFirmwareVersion(null);
|
2016-09-11 12:23:14 +02:00
|
|
|
setFirmwareVersion2(null);
|
2015-05-10 00:05:29 +02:00
|
|
|
setRssi(RSSI_UNKNOWN);
|
2018-09-28 16:50:11 +02:00
|
|
|
resetExtraInfos();
|
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() {
|
2016-07-05 23:35:20 +02:00
|
|
|
return getStateString(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2016-12-01 20:18:36 +01:00
|
|
|
* for simplicity the user won't see all internal states, just connecting -> connected
|
2016-07-05 23:35:20 +02:00
|
|
|
* instead of connecting->connected->initializing->initialized
|
|
|
|
* Set simple to true to get this behavior.
|
|
|
|
*/
|
|
|
|
private String getStateString(boolean simple) {
|
2024-02-14 03:25:26 +01:00
|
|
|
try{
|
|
|
|
// TODO: not sure if this is really neccessary...
|
|
|
|
if(simple){
|
|
|
|
return GBApplication.getContext().getString(mState.getSimpleStringId());
|
|
|
|
}
|
|
|
|
return GBApplication.getContext().getString(mState.getStringId());
|
|
|
|
}catch (Exception e){}
|
|
|
|
|
2024-02-12 23:30:32 +01:00
|
|
|
return GBApplication.getContext().getString(R.string.unknown_state);
|
2015-03-22 23:38:51 +01:00
|
|
|
}
|
|
|
|
|
2016-08-26 20:57:59 +02:00
|
|
|
/**
|
|
|
|
* Returns the general type of this device. For more detailed information,
|
|
|
|
* soo #getModel()
|
|
|
|
* @return the general type of this device
|
|
|
|
*/
|
|
|
|
@NonNull
|
2015-05-05 00:48:02 +02:00
|
|
|
public DeviceType getType() {
|
|
|
|
return mDeviceType;
|
|
|
|
}
|
|
|
|
|
2023-09-27 23:11:02 +02:00
|
|
|
@NonNull
|
|
|
|
public DeviceCoordinator getDeviceCoordinator(){
|
|
|
|
return mDeviceType.getDeviceCoordinator();
|
|
|
|
}
|
|
|
|
|
2015-05-05 00:48:02 +02:00
|
|
|
public void setRssi(short rssi) {
|
|
|
|
if (rssi < 0) {
|
2018-03-22 22:47:40 +01: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) {
|
2022-09-29 00:42:15 +02:00
|
|
|
sendDeviceUpdateIntent(context, DeviceUpdateSubject.UNKNOWN);
|
2022-09-23 02:57:08 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: this doesn't really belong here
|
2022-09-29 00:42:15 +02:00
|
|
|
public void sendDeviceUpdateIntent(Context context, DeviceUpdateSubject subject) {
|
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);
|
2022-09-23 02:57:08 +02:00
|
|
|
deviceUpdateIntent.putExtra(EXTRA_UPDATE_SUBJECT, subject);
|
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
|
|
|
|
2018-07-28 17:23:58 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the extra info value if it is set, null otherwise
|
|
|
|
* @param key the extra info key
|
|
|
|
* @return the extra info value if set, null otherwise
|
|
|
|
*/
|
|
|
|
public Object getExtraInfo(String key) {
|
|
|
|
if (mExtraInfos == null) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
return mExtraInfos.get(key);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Sets an extra info value, overwriting the current one, if any
|
|
|
|
* @param key the extra info key
|
|
|
|
* @param info the extra info value
|
|
|
|
*/
|
|
|
|
public void setExtraInfo(String key, Object info) {
|
|
|
|
if (mExtraInfos == null) {
|
|
|
|
mExtraInfos = new HashMap<>();
|
|
|
|
}
|
|
|
|
|
|
|
|
mExtraInfos.put(key, info);
|
|
|
|
}
|
|
|
|
|
2018-09-28 16:50:11 +02:00
|
|
|
/**
|
|
|
|
* Deletes all the extra infos
|
|
|
|
*/
|
|
|
|
public void resetExtraInfos() {
|
|
|
|
mExtraInfos = null;
|
|
|
|
}
|
|
|
|
|
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
|
|
|
*/
|
2021-10-16 22:40:30 +02:00
|
|
|
public int getBatteryLevel() {
|
|
|
|
return getBatteryLevel(0);
|
2015-04-19 22:20:47 +02:00
|
|
|
}
|
|
|
|
|
2021-10-16 22:40:30 +02:00
|
|
|
public int getBatteryLevel(int index) {
|
|
|
|
return mBatteryLevel[index];
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void setBatteryLevel(int batteryLevel) {
|
|
|
|
setBatteryLevel(batteryLevel, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setBatteryLevel(int batteryLevel, int index) {
|
2015-05-25 23:14:02 +02:00
|
|
|
if ((batteryLevel >= 0 && batteryLevel <= 100) || batteryLevel == BATTERY_UNKNOWN) {
|
2021-10-16 22:40:30 +02:00
|
|
|
mBatteryLevel[index] = batteryLevel;
|
2015-04-19 22:20:47 +02:00
|
|
|
} 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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-28 17:23:58 +02:00
|
|
|
public void setBatteryVoltage(float batteryVoltage) {
|
2021-10-16 22:40:30 +02:00
|
|
|
setBatteryVoltage(batteryVoltage, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void setBatteryVoltage(float batteryVoltage, int index) {
|
2018-07-28 17:23:58 +02:00
|
|
|
if (batteryVoltage >= 0 || batteryVoltage == BATTERY_UNKNOWN) {
|
2021-10-16 22:40:30 +02:00
|
|
|
mBatteryVoltage[index] = batteryVoltage;
|
2018-07-28 17:23:58 +02:00
|
|
|
} else {
|
|
|
|
LOG.error("Battery voltage must be > 0: " + batteryVoltage);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Voltage greater than zero (unit: Volt), or -1 if unknown
|
|
|
|
*
|
|
|
|
* @return the battery voltage, or -1 if unknown
|
|
|
|
*/
|
|
|
|
public float getBatteryVoltage() {
|
2021-10-16 22:40:30 +02:00
|
|
|
return getBatteryVoltage(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
public float getBatteryVoltage(int index) {
|
|
|
|
return mBatteryVoltage[index];
|
2018-07-28 17:23:58 +02:00
|
|
|
}
|
|
|
|
|
2015-08-21 08:41:57 +02:00
|
|
|
public BatteryState getBatteryState() {
|
2021-10-16 22:40:30 +02:00
|
|
|
return getBatteryState(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
public BatteryState getBatteryState(int index) {
|
|
|
|
return mBatteryState[index];
|
2015-04-19 22:20:47 +02:00
|
|
|
}
|
|
|
|
|
2015-08-21 08:41:57 +02:00
|
|
|
public void setBatteryState(BatteryState mBatteryState) {
|
2021-10-16 22:40:30 +02:00
|
|
|
setBatteryState(mBatteryState, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setBatteryState(BatteryState mBatteryState, int index) {
|
|
|
|
this.mBatteryState[index] = mBatteryState;
|
2015-04-19 22:20:47 +02:00
|
|
|
}
|
2015-04-20 11:58:59 +02:00
|
|
|
|
2015-08-19 17:36:53 +02:00
|
|
|
public short getBatteryThresholdPercent() {
|
|
|
|
return mBatteryThresholdPercent;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setBatteryThresholdPercent(short batteryThresholdPercent) {
|
|
|
|
this.mBatteryThresholdPercent = batteryThresholdPercent;
|
|
|
|
}
|
|
|
|
|
2021-10-31 17:36:04 +01:00
|
|
|
public int getBatteryIcon(int index) {
|
|
|
|
return this.mBatteryIcons[index];
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setBatteryIcon(int icon, int index) {
|
|
|
|
this.mBatteryIcons[index] = icon;
|
|
|
|
}
|
|
|
|
|
|
|
|
public int getBatteryLabel(int index) {
|
|
|
|
return this.mBatteryLabels[index];
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setBatteryLabel(int label, int index) {
|
|
|
|
this.mBatteryLabels[index] = label;
|
|
|
|
}
|
|
|
|
|
2023-09-27 23:11:02 +02:00
|
|
|
public int getEnabledDisabledIconResource(){
|
|
|
|
return isInitialized() ?
|
|
|
|
getDeviceCoordinator().getDefaultIconResource() :
|
|
|
|
getDeviceCoordinator().getDisabledIconResource();
|
|
|
|
}
|
|
|
|
|
2015-07-10 21:35:28 +02:00
|
|
|
@Override
|
|
|
|
public String toString() {
|
2016-07-05 23:35:20 +02:00
|
|
|
return "Device " + getName() + ", " + getAddress() + ", " + getStateString(false);
|
2015-07-10 21:35:28 +02:00
|
|
|
}
|
|
|
|
|
2015-12-28 00:16:00 +01:00
|
|
|
/**
|
|
|
|
* Returns a shortened form of the device's address, in order to form a
|
|
|
|
* unique name in companion with #getName().
|
|
|
|
*/
|
|
|
|
@NonNull
|
|
|
|
public String getShortAddress() {
|
|
|
|
String address = getAddress();
|
|
|
|
if (address != null) {
|
|
|
|
if (address.length() > 5) {
|
|
|
|
return address.substring(address.length() - 5);
|
|
|
|
}
|
|
|
|
return address;
|
|
|
|
}
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
|
2016-03-16 00:14:38 +01:00
|
|
|
public boolean hasDeviceInfos() {
|
|
|
|
return getDeviceInfos().size() > 0;
|
|
|
|
}
|
|
|
|
|
2016-05-13 23:47:47 +02:00
|
|
|
public ItemWithDetails getDeviceInfo(String name) {
|
|
|
|
for (ItemWithDetails item : getDeviceInfos()) {
|
|
|
|
if (name.equals(item.getName())) {
|
|
|
|
return item;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2016-03-16 00:14:38 +01:00
|
|
|
public List<ItemWithDetails> getDeviceInfos() {
|
|
|
|
List<ItemWithDetails> result = new ArrayList<>();
|
|
|
|
if (mDeviceInfos != null) {
|
|
|
|
result.addAll(mDeviceInfos);
|
|
|
|
}
|
2016-08-26 20:57:59 +02:00
|
|
|
if (mModel != null) {
|
|
|
|
result.add(new GenericItem(DEVINFO_HW_VER, mModel));
|
2016-03-16 00:14:38 +01:00
|
|
|
}
|
|
|
|
if (mFirmwareVersion != null) {
|
|
|
|
result.add(new GenericItem(DEVINFO_FW_VER, mFirmwareVersion));
|
|
|
|
}
|
2016-09-11 21:15:36 +02:00
|
|
|
if (mFirmwareVersion2 != null) {
|
2021-06-02 17:12:59 +02:00
|
|
|
result.add(new GenericItem(DEVINFO_FW2_VER, mFirmwareVersion2));
|
2016-09-11 21:15:36 +02:00
|
|
|
}
|
2016-05-28 11:32:36 +02:00
|
|
|
if (mAddress != null) {
|
|
|
|
result.add(new GenericItem(DEVINFO_ADDR, mAddress));
|
|
|
|
}
|
2016-11-27 09:49:28 +01:00
|
|
|
if (mVolatileAddress != null) {
|
|
|
|
result.add(new GenericItem(DEVINFO_ADDR2, mVolatileAddress));
|
|
|
|
}
|
2016-03-25 23:54:42 +01:00
|
|
|
Collections.sort(result);
|
2016-03-16 00:14:38 +01:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setDeviceInfos(List<ItemWithDetails> deviceInfos) {
|
|
|
|
this.mDeviceInfos = deviceInfos;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void addDeviceInfo(ItemWithDetails info) {
|
|
|
|
if (mDeviceInfos == null) {
|
|
|
|
mDeviceInfos = new ArrayList<>();
|
|
|
|
} else {
|
|
|
|
int index = mDeviceInfos.indexOf(info);
|
|
|
|
if (index >= 0) {
|
|
|
|
mDeviceInfos.set(index, info); // replace item with new one
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
mDeviceInfos.add(info);
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean removeDeviceInfo(ItemWithDetails info) {
|
|
|
|
if (mDeviceInfos == null) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return mDeviceInfos.remove(info);
|
|
|
|
}
|
|
|
|
|
2015-04-20 11:58:59 +02:00
|
|
|
public enum State {
|
2024-02-14 03:25:26 +01:00
|
|
|
NOT_CONNECTED(R.string.not_connected),
|
|
|
|
WAITING_FOR_RECONNECT(R.string.waiting_for_reconnect),
|
|
|
|
WAITING_FOR_SCAN(R.string.device_state_waiting_scan),
|
|
|
|
CONNECTING(R.string.connecting),
|
|
|
|
CONNECTED(R.string.connected, R.string.connecting),
|
|
|
|
INITIALIZING(R.string.initializing, R.string.connecting),
|
|
|
|
AUTHENTICATION_REQUIRED(R.string.authentication_required), // some kind of pairing is required by the device
|
|
|
|
AUTHENTICATING(R.string.authenticating), // some kind of pairing is requested by the device
|
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.
|
|
|
|
*/
|
2024-02-14 03:25:26 +01:00
|
|
|
INITIALIZED(R.string.initialized, R.string.connected);
|
|
|
|
|
|
|
|
|
|
|
|
private int stringId, simpleStringId;
|
|
|
|
|
|
|
|
State(int stringId, int simpleStringId) {
|
|
|
|
this.stringId = stringId;
|
|
|
|
this.simpleStringId = simpleStringId;
|
|
|
|
}
|
|
|
|
|
|
|
|
State(int stringId) {
|
|
|
|
this(stringId, stringId);
|
|
|
|
}
|
|
|
|
|
|
|
|
public int getStringId() {
|
|
|
|
return stringId;
|
|
|
|
}
|
|
|
|
|
|
|
|
public int getSimpleStringId() {
|
|
|
|
return simpleStringId;
|
|
|
|
}
|
2024-02-26 01:01:46 +01:00
|
|
|
|
|
|
|
boolean equalsOrHigherThan(State otherState){
|
|
|
|
return ordinal() >= otherState.ordinal();
|
|
|
|
}
|
2015-04-20 11:58:59 +02:00
|
|
|
}
|
2015-03-21 18:18:07 +01:00
|
|
|
}
|