2017-03-10 14:53:19 +01:00
|
|
|
/* Copyright (C) 2015-2017 Andreas Shimokawa, Carsten Pfeiffer, Julien
|
|
|
|
Pivotto, Steffen Liebergeld
|
|
|
|
|
|
|
|
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
|
|
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
2015-08-18 01:26:15 +02:00
|
|
|
package nodomain.freeyourgadget.gadgetbridge.service.serial;
|
2015-04-14 01:24:03 +02:00
|
|
|
|
2015-05-18 20:56:19 +02:00
|
|
|
import java.util.UUID;
|
|
|
|
|
2015-06-23 11:54:33 +02:00
|
|
|
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEvent;
|
|
|
|
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventSendBytes;
|
2015-09-13 21:44:26 +02:00
|
|
|
import nodomain.freeyourgadget.gadgetbridge.devices.EventHandler;
|
2016-05-16 17:30:11 +02:00
|
|
|
import nodomain.freeyourgadget.gadgetbridge.model.CalendarEventSpec;
|
2016-04-04 20:08:34 +02:00
|
|
|
import nodomain.freeyourgadget.gadgetbridge.model.CallSpec;
|
2016-06-24 10:25:08 +02:00
|
|
|
import nodomain.freeyourgadget.gadgetbridge.model.CannedMessagesSpec;
|
2016-04-04 20:08:34 +02:00
|
|
|
import nodomain.freeyourgadget.gadgetbridge.model.MusicSpec;
|
2016-06-08 20:27:25 +02:00
|
|
|
import nodomain.freeyourgadget.gadgetbridge.model.MusicStateSpec;
|
2015-09-24 14:45:21 +02:00
|
|
|
import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
|
2016-12-31 15:56:05 +01:00
|
|
|
import nodomain.freeyourgadget.gadgetbridge.model.WeatherSpec;
|
2015-08-03 23:51:53 +02:00
|
|
|
import nodomain.freeyourgadget.gadgetbridge.service.AbstractDeviceSupport;
|
2015-04-14 01:24:03 +02:00
|
|
|
|
2015-08-02 00:12:21 +02:00
|
|
|
/**
|
2015-08-17 16:30:12 +02:00
|
|
|
* An abstract base class for devices speaking a serial protocol, like via
|
|
|
|
* an rfcomm bluetooth socket or a TCP socket.
|
2015-09-13 21:44:26 +02:00
|
|
|
* <p/>
|
2015-08-02 00:12:21 +02:00
|
|
|
* This class uses two helper classes to deal with that:
|
|
|
|
* - GBDeviceIoThread, which creates and maintains the actual socket connection and implements the transport layer
|
|
|
|
* - GBDeviceProtocol, which implements the encoding and decoding of messages, i.e. the actual device specific protocol
|
2015-09-13 21:44:26 +02:00
|
|
|
* <p/>
|
2015-08-02 00:12:21 +02:00
|
|
|
* Note that these two classes need to be implemented in a device specific way.
|
2015-09-13 21:44:26 +02:00
|
|
|
* <p/>
|
2015-08-02 00:12:21 +02:00
|
|
|
* This implementation implements all methods of {@link EventHandler}, calls the {@link GBDeviceProtocol device protocol}
|
|
|
|
* to create the device specific message for the respective events and sends them to the device via {@link #sendToDevice(byte[])}.
|
|
|
|
*/
|
2015-08-17 16:30:12 +02:00
|
|
|
public abstract class AbstractSerialDeviceSupport extends AbstractDeviceSupport {
|
2016-12-31 15:56:05 +01:00
|
|
|
private GBDeviceProtocol gbDeviceProtocol;
|
2016-04-03 18:30:20 +02:00
|
|
|
protected GBDeviceIoThread gbDeviceIOThread;
|
2015-04-14 01:24:03 +02:00
|
|
|
|
2015-08-02 00:12:21 +02:00
|
|
|
/**
|
|
|
|
* Factory method to create the device specific GBDeviceProtocol instance to be used.
|
|
|
|
*/
|
2015-04-14 01:24:03 +02:00
|
|
|
protected abstract GBDeviceProtocol createDeviceProtocol();
|
|
|
|
|
2015-08-02 00:12:21 +02:00
|
|
|
/**
|
|
|
|
* Factory method to create the device specific GBDeviceIoThread instance to be used.
|
|
|
|
*/
|
2015-04-14 01:24:03 +02:00
|
|
|
protected abstract GBDeviceIoThread createDeviceIOThread();
|
2015-04-14 10:29:09 +02:00
|
|
|
|
2015-04-14 01:39:00 +02:00
|
|
|
@Override
|
|
|
|
public void dispose() {
|
|
|
|
// currently only one thread allowed
|
|
|
|
if (gbDeviceIOThread != null) {
|
|
|
|
gbDeviceIOThread.quit();
|
2016-04-07 00:21:21 +02:00
|
|
|
gbDeviceIOThread.interrupt();
|
2015-04-14 01:39:00 +02:00
|
|
|
gbDeviceIOThread = null;
|
|
|
|
}
|
|
|
|
}
|
2015-04-14 10:29:09 +02:00
|
|
|
|
2015-08-02 00:12:21 +02:00
|
|
|
/**
|
|
|
|
* Lazily creates and returns the GBDeviceProtocol instance to be used.
|
|
|
|
*/
|
2016-12-31 15:56:05 +01:00
|
|
|
protected synchronized GBDeviceProtocol getDeviceProtocol() {
|
2015-04-14 01:24:03 +02:00
|
|
|
if (gbDeviceProtocol == null) {
|
|
|
|
gbDeviceProtocol = createDeviceProtocol();
|
|
|
|
}
|
|
|
|
return gbDeviceProtocol;
|
|
|
|
}
|
2015-04-14 10:29:09 +02:00
|
|
|
|
2015-08-02 00:12:21 +02:00
|
|
|
/**
|
|
|
|
* Lazily creates and returns the GBDeviceIoThread instance to be used.
|
|
|
|
*/
|
2015-04-14 01:24:03 +02:00
|
|
|
public synchronized GBDeviceIoThread getDeviceIOThread() {
|
|
|
|
if (gbDeviceIOThread == null) {
|
|
|
|
gbDeviceIOThread = createDeviceIOThread();
|
|
|
|
}
|
|
|
|
return gbDeviceIOThread;
|
|
|
|
}
|
2015-04-14 10:29:09 +02:00
|
|
|
|
2015-08-02 00:12:21 +02:00
|
|
|
/**
|
|
|
|
* Sends the given message to the device. This implementation delegates the
|
|
|
|
* writing to the {@link #getDeviceIOThread device io thread}
|
2015-09-13 21:44:26 +02:00
|
|
|
*
|
2015-08-02 00:12:21 +02:00
|
|
|
* @param bytes the message to send to the device
|
|
|
|
*/
|
2016-12-31 15:56:05 +01:00
|
|
|
private void sendToDevice(byte[] bytes) {
|
2015-04-14 01:39:00 +02:00
|
|
|
if (bytes != null && gbDeviceIOThread != null) {
|
2015-04-14 01:24:03 +02:00
|
|
|
gbDeviceIOThread.write(bytes);
|
|
|
|
}
|
|
|
|
}
|
2015-04-14 10:29:09 +02:00
|
|
|
|
2016-12-31 15:56:05 +01:00
|
|
|
private void handleGBDeviceEvent(GBDeviceEventSendBytes sendBytes) {
|
2015-05-22 20:20:33 +02:00
|
|
|
sendToDevice(sendBytes.encodedBytes);
|
|
|
|
}
|
|
|
|
|
2015-05-23 00:54:14 +02:00
|
|
|
@Override
|
2015-06-23 11:54:33 +02:00
|
|
|
public void evaluateGBDeviceEvent(GBDeviceEvent deviceEvent) {
|
2015-08-31 17:25:58 +02:00
|
|
|
if (deviceEvent instanceof GBDeviceEventSendBytes) {
|
|
|
|
handleGBDeviceEvent((GBDeviceEventSendBytes) deviceEvent);
|
|
|
|
return;
|
2015-05-22 20:20:33 +02:00
|
|
|
}
|
2015-06-23 11:54:33 +02:00
|
|
|
super.evaluateGBDeviceEvent(deviceEvent);
|
2015-05-22 20:20:33 +02:00
|
|
|
}
|
|
|
|
|
2015-04-14 01:24:03 +02:00
|
|
|
@Override
|
2015-09-24 14:45:21 +02:00
|
|
|
public void onNotification(NotificationSpec notificationSpec) {
|
|
|
|
byte[] bytes = gbDeviceProtocol.encodeNotification(notificationSpec);
|
2015-05-13 21:55:22 +02:00
|
|
|
sendToDevice(bytes);
|
|
|
|
}
|
|
|
|
|
2017-01-09 16:33:00 +01:00
|
|
|
@Override
|
|
|
|
public void onDeleteNotification(int id) {
|
|
|
|
byte[] bytes = gbDeviceProtocol.encodeDeleteNotification(id);
|
|
|
|
sendToDevice(bytes);
|
|
|
|
}
|
|
|
|
|
2015-04-14 01:24:03 +02:00
|
|
|
@Override
|
2015-08-21 00:58:18 +02:00
|
|
|
public void onSetTime() {
|
|
|
|
byte[] bytes = gbDeviceProtocol.encodeSetTime();
|
2015-04-14 01:24:03 +02:00
|
|
|
sendToDevice(bytes);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2016-04-04 20:08:34 +02:00
|
|
|
public void onSetCallState(CallSpec callSpec) {
|
|
|
|
byte[] bytes = gbDeviceProtocol.encodeSetCallState(callSpec.number, callSpec.name, callSpec.command);
|
2015-04-14 01:24:03 +02:00
|
|
|
sendToDevice(bytes);
|
|
|
|
}
|
|
|
|
|
2016-06-24 10:25:08 +02:00
|
|
|
@Override
|
|
|
|
public void onSetCannedMessages(CannedMessagesSpec cannedMessagesSpec) {
|
|
|
|
byte[] bytes = gbDeviceProtocol.encodeSetCannedMessages(cannedMessagesSpec);
|
|
|
|
sendToDevice(bytes);
|
|
|
|
}
|
|
|
|
|
2016-06-08 20:27:25 +02:00
|
|
|
@Override
|
|
|
|
public void onSetMusicState(MusicStateSpec stateSpec) {
|
|
|
|
byte[] bytes = gbDeviceProtocol.encodeSetMusicState(stateSpec.state, stateSpec.position, stateSpec.playRate, stateSpec.shuffle, stateSpec.repeat);
|
|
|
|
sendToDevice(bytes);
|
|
|
|
}
|
|
|
|
|
2015-04-14 01:24:03 +02:00
|
|
|
@Override
|
2016-04-04 20:08:34 +02:00
|
|
|
public void onSetMusicInfo(MusicSpec musicSpec) {
|
|
|
|
byte[] bytes = gbDeviceProtocol.encodeSetMusicInfo(musicSpec.artist, musicSpec.album, musicSpec.track, musicSpec.duration, musicSpec.trackCount, musicSpec.trackNr);
|
2015-04-14 01:24:03 +02:00
|
|
|
sendToDevice(bytes);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onAppInfoReq() {
|
|
|
|
byte[] bytes = gbDeviceProtocol.encodeAppInfoReq();
|
|
|
|
sendToDevice(bytes);
|
|
|
|
}
|
|
|
|
|
2015-05-18 22:20:01 +02:00
|
|
|
@Override
|
2015-09-13 21:44:26 +02:00
|
|
|
public void onAppStart(UUID uuid, boolean start) {
|
|
|
|
byte[] bytes = gbDeviceProtocol.encodeAppStart(uuid, start);
|
2015-05-18 22:20:01 +02:00
|
|
|
sendToDevice(bytes);
|
|
|
|
}
|
|
|
|
|
2015-04-14 01:24:03 +02:00
|
|
|
@Override
|
2015-05-18 20:56:19 +02:00
|
|
|
public void onAppDelete(UUID uuid) {
|
|
|
|
byte[] bytes = gbDeviceProtocol.encodeAppDelete(uuid);
|
2015-04-14 01:24:03 +02:00
|
|
|
sendToDevice(bytes);
|
|
|
|
}
|
|
|
|
|
2016-06-12 01:20:12 +02:00
|
|
|
@Override
|
|
|
|
public void onAppReorder(UUID[] uuids) {
|
|
|
|
byte[] bytes = gbDeviceProtocol.encodeAppReorder(uuids);
|
|
|
|
sendToDevice(bytes);
|
|
|
|
}
|
|
|
|
|
2015-06-06 00:40:16 +02:00
|
|
|
@Override
|
2015-06-06 19:39:04 +02:00
|
|
|
public void onFetchActivityData() {
|
2015-06-06 00:40:16 +02:00
|
|
|
byte[] bytes = gbDeviceProtocol.encodeSynchronizeActivityData();
|
|
|
|
sendToDevice(bytes);
|
|
|
|
}
|
|
|
|
|
2015-05-18 22:40:39 +02:00
|
|
|
@Override
|
2015-05-17 21:58:08 +02:00
|
|
|
public void onReboot() {
|
|
|
|
byte[] bytes = gbDeviceProtocol.encodeReboot();
|
|
|
|
sendToDevice(bytes);
|
|
|
|
}
|
2015-06-21 00:34:05 +02:00
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onFindDevice(boolean start) {
|
2015-06-21 20:59:36 +02:00
|
|
|
byte[] bytes = gbDeviceProtocol.encodeFindDevice(start);
|
2015-06-21 00:34:05 +02:00
|
|
|
sendToDevice(bytes);
|
|
|
|
}
|
2015-06-24 00:23:38 +02:00
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onScreenshotReq() {
|
|
|
|
byte[] bytes = gbDeviceProtocol.encodeScreenshotReq();
|
|
|
|
sendToDevice(bytes);
|
|
|
|
}
|
2015-09-02 08:00:26 +02:00
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onEnableRealtimeSteps(boolean enable) {
|
|
|
|
byte[] bytes = gbDeviceProtocol.encodeEnableRealtimeSteps(enable);
|
|
|
|
sendToDevice(bytes);
|
|
|
|
}
|
2016-04-03 22:38:06 +02:00
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onEnableHeartRateSleepSupport(boolean enable) {
|
|
|
|
byte[] bytes = gbDeviceProtocol.encodeEnableHeartRateSleepSupport(enable);
|
|
|
|
sendToDevice(bytes);
|
|
|
|
}
|
2016-04-12 23:12:15 +02:00
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onEnableRealtimeHeartRateMeasurement(boolean enable) {
|
|
|
|
byte[] bytes = gbDeviceProtocol.encodeEnableRealtimeHeartRateMeasurement(enable);
|
|
|
|
sendToDevice(bytes);
|
|
|
|
}
|
2016-05-16 23:37:40 +02:00
|
|
|
|
2016-05-16 17:30:11 +02:00
|
|
|
@Override
|
|
|
|
public void onAddCalendarEvent(CalendarEventSpec calendarEventSpec) {
|
|
|
|
byte[] bytes = gbDeviceProtocol.encodeAddCalendarEvent(calendarEventSpec);
|
|
|
|
sendToDevice(bytes);
|
|
|
|
}
|
2016-05-16 23:37:40 +02:00
|
|
|
|
|
|
|
@Override
|
2016-05-24 13:11:57 +02:00
|
|
|
public void onDeleteCalendarEvent(byte type, long id) {
|
2016-05-16 23:37:40 +02:00
|
|
|
byte[] bytes = gbDeviceProtocol.encodeDeleteCalendarEvent(type, id);
|
|
|
|
sendToDevice(bytes);
|
|
|
|
}
|
2016-10-11 23:06:59 +02:00
|
|
|
|
2016-11-13 20:47:24 +01:00
|
|
|
@Override
|
|
|
|
public void onSendConfiguration(String config) {
|
|
|
|
byte[] bytes = gbDeviceProtocol.encodeSendConfiguration(config);
|
|
|
|
sendToDevice(bytes);
|
|
|
|
}
|
|
|
|
|
2016-10-11 23:06:59 +02:00
|
|
|
@Override
|
|
|
|
public void onTestNewFunction() {
|
|
|
|
byte[] bytes = gbDeviceProtocol.encodeTestNewFunction();
|
|
|
|
sendToDevice(bytes);
|
|
|
|
}
|
2016-12-31 15:56:05 +01:00
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onSendWeather(WeatherSpec weatherSpec) {
|
|
|
|
byte[] bytes = gbDeviceProtocol.encodeSendWeather(weatherSpec);
|
|
|
|
sendToDevice(bytes);
|
|
|
|
}
|
2015-04-14 01:24:03 +02:00
|
|
|
}
|