mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge
synced 2024-11-09 19:49:30 +01:00
Pixoo: Decode alarms from device, support sending alarms
This is probably not quite right yet. Also we need to properly chunk incoming protocol messages before decoding them
This commit is contained in:
parent
275deb4d06
commit
198800e087
@ -61,6 +61,11 @@ public class PixooCoordinator extends AbstractBLEDeviceCoordinator {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getAlarmSlotCount(GBDevice device) {
|
||||||
|
return 10;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getDefaultIconResource() {
|
public int getDefaultIconResource() {
|
||||||
return R.drawable.ic_device_lovetoy;
|
return R.drawable.ic_device_lovetoy;
|
||||||
|
@ -31,19 +31,24 @@ import java.util.Arrays;
|
|||||||
|
|
||||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.btclassic.BtClassicIoThread;
|
import nodomain.freeyourgadget.gadgetbridge.service.btclassic.BtClassicIoThread;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.nothing.NothingProtocol;
|
||||||
|
|
||||||
public class PixooIOThread extends BtClassicIoThread {
|
public class PixooIOThread extends BtClassicIoThread {
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(PixooIOThread.class);
|
private static final Logger LOG = LoggerFactory.getLogger(PixooIOThread.class);
|
||||||
|
private final PixooProtocol mPixooProtocol;
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void initialize() {
|
protected void initialize() {
|
||||||
|
write(mPixooProtocol.encodeReqestAlarms());
|
||||||
|
|
||||||
setUpdateState(GBDevice.State.INITIALIZED);
|
setUpdateState(GBDevice.State.INITIALIZED);
|
||||||
}
|
}
|
||||||
|
|
||||||
public PixooIOThread(GBDevice device, Context context, PixooProtocol deviceProtocol,
|
public PixooIOThread(GBDevice device, Context context, PixooProtocol deviceProtocol,
|
||||||
PixooSupport PixooSupport, BluetoothAdapter bluetoothAdapter) {
|
PixooSupport PixooSupport, BluetoothAdapter bluetoothAdapter) {
|
||||||
super(device, context, deviceProtocol, PixooSupport, bluetoothAdapter);
|
super(device, context, deviceProtocol, PixooSupport, bluetoothAdapter);
|
||||||
|
mPixooProtocol = deviceProtocol;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -17,8 +17,12 @@
|
|||||||
|
|
||||||
package nodomain.freeyourgadget.gadgetbridge.service.devices.divoom;
|
package nodomain.freeyourgadget.gadgetbridge.service.devices.divoom;
|
||||||
|
|
||||||
|
import android.content.Intent;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
|
|
||||||
|
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.ArrayUtils;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
@ -26,17 +30,22 @@ import java.nio.ByteBuffer;
|
|||||||
import java.nio.ByteOrder;
|
import java.nio.ByteOrder;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import lineageos.weather.util.WeatherUtils;
|
import lineageos.weather.util.WeatherUtils;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.R;
|
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.activities.SettingsActivity;
|
import nodomain.freeyourgadget.gadgetbridge.activities.SettingsActivity;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst;
|
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.database.DBHelper;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEvent;
|
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEvent;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventVersionInfo;
|
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventVersionInfo;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.entities.Alarm;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.model.CallSpec;
|
import nodomain.freeyourgadget.gadgetbridge.model.CallSpec;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.model.DeviceService;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
|
import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.model.WeatherSpec;
|
import nodomain.freeyourgadget.gadgetbridge.model.WeatherSpec;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.BLETypeConversions;
|
import nodomain.freeyourgadget.gadgetbridge.service.btle.BLETypeConversions;
|
||||||
@ -64,10 +73,86 @@ public class PixooProtocol extends GBDeviceProtocol {
|
|||||||
|
|
||||||
ByteBuffer incoming = ByteBuffer.wrap(responseData);
|
ByteBuffer incoming = ByteBuffer.wrap(responseData);
|
||||||
incoming.order(ByteOrder.LITTLE_ENDIAN);
|
incoming.order(ByteOrder.LITTLE_ENDIAN);
|
||||||
|
if (incoming.get() != 0x01) {
|
||||||
|
LOG.warn("first byte not 0x01");
|
||||||
|
return devEvts.toArray(new GBDeviceEvent[0]);
|
||||||
|
}
|
||||||
|
int length = incoming.getShort() & 0xffff;
|
||||||
|
byte status = incoming.get(); // unsure
|
||||||
|
if (status != 0x04) {
|
||||||
|
LOG.warn("status byte not 0x04");
|
||||||
|
return devEvts.toArray(new GBDeviceEvent[0]);
|
||||||
|
}
|
||||||
|
byte endpoint = incoming.get(); // unsure
|
||||||
|
LOG.info("endpoint " + endpoint);
|
||||||
|
if (endpoint == 0x42) {
|
||||||
|
decodeAlarms(incoming);
|
||||||
|
}
|
||||||
return devEvts.toArray(new GBDeviceEvent[0]);
|
return devEvts.toArray(new GBDeviceEvent[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void decodeAlarms(ByteBuffer incoming) {
|
||||||
|
byte unknown = incoming.get();
|
||||||
|
if (unknown != 0x55) { // expected
|
||||||
|
LOG.warn("unexpected byte when decoding Alarms " + unknown);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Map of alarm position to Alarm, as returned by the band
|
||||||
|
final Map<Integer, nodomain.freeyourgadget.gadgetbridge.model.Alarm> payloadAlarms = new HashMap<>();
|
||||||
|
|
||||||
|
while (incoming.remaining() > 10) {
|
||||||
|
int position = incoming.get();
|
||||||
|
boolean enabled = incoming.get() == 1;
|
||||||
|
int hour = incoming.get();
|
||||||
|
int minute = incoming.get();
|
||||||
|
int repeatMask = incoming.get();
|
||||||
|
int unknown2 = incoming.getInt();
|
||||||
|
byte unknown3 = incoming.get(); // normally 0x01, on fresh alarms 0x32
|
||||||
|
final Alarm alarm = new nodomain.freeyourgadget.gadgetbridge.entities.Alarm();
|
||||||
|
alarm.setEnabled(enabled);
|
||||||
|
alarm.setPosition(position);
|
||||||
|
alarm.setHour(hour);
|
||||||
|
alarm.setMinute(minute);
|
||||||
|
alarm.setRepetition(repeatMask);
|
||||||
|
alarm.setUnused(unknown3 == 0x32 && !enabled);
|
||||||
|
payloadAlarms.put(position, alarm);
|
||||||
|
}
|
||||||
|
final List<nodomain.freeyourgadget.gadgetbridge.entities.Alarm> dbAlarms = DBHelper.getAlarms(getDevice());
|
||||||
|
int numUpdatedAlarms = 0;
|
||||||
|
|
||||||
|
for (nodomain.freeyourgadget.gadgetbridge.entities.Alarm alarm : dbAlarms) {
|
||||||
|
final int pos = alarm.getPosition();
|
||||||
|
final nodomain.freeyourgadget.gadgetbridge.model.Alarm updatedAlarm = payloadAlarms.get(pos);
|
||||||
|
final boolean alarmNeedsUpdate = updatedAlarm == null ||
|
||||||
|
alarm.getUnused() != updatedAlarm.getUnused() ||
|
||||||
|
alarm.getEnabled() != updatedAlarm.getEnabled() ||
|
||||||
|
alarm.getSmartWakeup() != updatedAlarm.getSmartWakeup() ||
|
||||||
|
alarm.getHour() != updatedAlarm.getHour() ||
|
||||||
|
alarm.getMinute() != updatedAlarm.getMinute() ||
|
||||||
|
alarm.getRepetition() != updatedAlarm.getRepetition();
|
||||||
|
|
||||||
|
if (alarmNeedsUpdate) {
|
||||||
|
numUpdatedAlarms++;
|
||||||
|
LOG.info("Updating alarm index={}, unused={}", pos, updatedAlarm == null);
|
||||||
|
alarm.setUnused(updatedAlarm == null);
|
||||||
|
if (updatedAlarm != null) {
|
||||||
|
alarm.setEnabled(updatedAlarm.getEnabled());
|
||||||
|
alarm.setUnused(updatedAlarm.getUnused());
|
||||||
|
alarm.setSmartWakeup(updatedAlarm.getSmartWakeup());
|
||||||
|
alarm.setHour(updatedAlarm.getHour());
|
||||||
|
alarm.setMinute(updatedAlarm.getMinute());
|
||||||
|
alarm.setRepetition(updatedAlarm.getRepetition());
|
||||||
|
}
|
||||||
|
DBHelper.store(alarm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (numUpdatedAlarms > 0) {
|
||||||
|
final Intent intent = new Intent(DeviceService.ACTION_SAVE_ALARMS);
|
||||||
|
LocalBroadcastManager.getInstance(GBApplication.getContext()).sendBroadcast(intent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public byte[] encodeSendConfiguration(String config) {
|
public byte[] encodeSendConfiguration(String config) {
|
||||||
SharedPreferences prefs = GBApplication.getDeviceSpecificSharedPrefs(getDevice().getAddress());
|
SharedPreferences prefs = GBApplication.getDeviceSpecificSharedPrefs(getDevice().getAddress());
|
||||||
@ -171,6 +256,26 @@ public class PixooProtocol extends GBDeviceProtocol {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] encodeSetAlarms(ArrayList<? extends nodomain.freeyourgadget.gadgetbridge.model.Alarm> alarms) {
|
||||||
|
byte[] complete_command = new byte[]{};
|
||||||
|
for (nodomain.freeyourgadget.gadgetbridge.model.Alarm alarm : alarms) {
|
||||||
|
byte[] cmd = new byte[]{
|
||||||
|
0x43,
|
||||||
|
(byte) alarm.getPosition(),
|
||||||
|
(byte) (alarm.getEnabled() && !alarm.getUnused() ? 1 : 0),
|
||||||
|
(byte) alarm.getHour(),
|
||||||
|
(byte) alarm.getMinute(),
|
||||||
|
(byte) alarm.getRepetition(),
|
||||||
|
0, 0, 0, 0,
|
||||||
|
(byte) (alarm.getUnused() ? 0x32 : 0x00)};
|
||||||
|
|
||||||
|
complete_command = ArrayUtils.addAll(complete_command, encodeProtocol(cmd));
|
||||||
|
}
|
||||||
|
return complete_command;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public byte[] encodeSendWeather(WeatherSpec weatherSpec) {
|
public byte[] encodeSendWeather(WeatherSpec weatherSpec) {
|
||||||
byte pixooWeatherCode = 0;
|
byte pixooWeatherCode = 0;
|
||||||
@ -238,6 +343,10 @@ public class PixooProtocol extends GBDeviceProtocol {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public byte[] encodeReqestAlarms() {
|
||||||
|
return encodeProtocol(new byte[]{0x42});
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public byte[] encodeTestNewFunction() {
|
public byte[] encodeTestNewFunction() {
|
||||||
//return encodeAudioModeCommand(1); // works
|
//return encodeAudioModeCommand(1); // works
|
||||||
@ -262,3 +371,4 @@ public class PixooProtocol extends GBDeviceProtocol {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,6 +20,7 @@ package nodomain.freeyourgadget.gadgetbridge.service.devices.divoom;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.serial.AbstractSerialDeviceSupport;
|
import nodomain.freeyourgadget.gadgetbridge.service.serial.AbstractSerialDeviceSupport;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.serial.GBDeviceIoThread;
|
import nodomain.freeyourgadget.gadgetbridge.service.serial.GBDeviceIoThread;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.serial.GBDeviceProtocol;
|
import nodomain.freeyourgadget.gadgetbridge.service.serial.GBDeviceProtocol;
|
||||||
|
@ -25,6 +25,7 @@ import java.util.UUID;
|
|||||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEvent;
|
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEvent;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventSendBytes;
|
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventSendBytes;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.EventHandler;
|
import nodomain.freeyourgadget.gadgetbridge.devices.EventHandler;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.model.Alarm;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.model.CalendarEventSpec;
|
import nodomain.freeyourgadget.gadgetbridge.model.CalendarEventSpec;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.model.CallSpec;
|
import nodomain.freeyourgadget.gadgetbridge.model.CallSpec;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.model.CannedMessagesSpec;
|
import nodomain.freeyourgadget.gadgetbridge.model.CannedMessagesSpec;
|
||||||
@ -286,6 +287,12 @@ public abstract class AbstractSerialDeviceSupport extends AbstractDeviceSupport
|
|||||||
sendToDevice(bytes);
|
sendToDevice(bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSetAlarms(ArrayList<? extends Alarm> alarms) {
|
||||||
|
byte[] bytes = gbDeviceProtocol.encodeSetAlarms(alarms);
|
||||||
|
sendToDevice(bytes);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSetReminders(ArrayList<? extends Reminder> reminders) {
|
public void onSetReminders(ArrayList<? extends Reminder> reminders) {
|
||||||
byte[] bytes = gbDeviceProtocol.encodeReminders(reminders);
|
byte[] bytes = gbDeviceProtocol.encodeReminders(reminders);
|
||||||
|
@ -24,6 +24,7 @@ import java.util.UUID;
|
|||||||
|
|
||||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEvent;
|
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEvent;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.model.Alarm;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.model.CalendarEventSpec;
|
import nodomain.freeyourgadget.gadgetbridge.model.CalendarEventSpec;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.model.CannedMessagesSpec;
|
import nodomain.freeyourgadget.gadgetbridge.model.CannedMessagesSpec;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
|
import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
|
||||||
@ -158,6 +159,10 @@ public abstract class GBDeviceProtocol {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public byte[] encodeSetAlarms(ArrayList<? extends Alarm> alarms) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
public byte[] encodeReminders(ArrayList<? extends Reminder> reminders) {
|
public byte[] encodeReminders(ArrayList<? extends Reminder> reminders) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user