1
0
mirror of https://codeberg.org/Freeyourgadget/Gadgetbridge synced 2024-11-29 13:26:50 +01:00

Bangle.js: refactoring

Extract handling of packet types with large code blocks.
Incidentally fixes "intent" packets launching a full calendar sync if
intents are disabled in GB settings.
This commit is contained in:
Richard de Boer 2023-05-31 21:33:44 +02:00
parent 4c7920133b
commit 8e270fcbf7
No known key found for this signature in database

View File

@ -525,7 +525,59 @@ public class BangleJSDeviceSupport extends AbstractBTLEDeviceSupport {
if (json.has("fw2")) if (json.has("fw2"))
getDevice().setFirmwareVersion2(json.getString("fw2")); getDevice().setFirmwareVersion2(json.getString("fw2"));
} break; } break;
case "status": { case "findPhone": {
boolean start = json.has("n") && json.getBoolean("n");
GBDeviceEventFindPhone deviceEventFindPhone = new GBDeviceEventFindPhone();
deviceEventFindPhone.event = start ? GBDeviceEventFindPhone.Event.START : GBDeviceEventFindPhone.Event.STOP;
evaluateGBDeviceEvent(deviceEventFindPhone);
} break;
case "music": {
GBDeviceEventMusicControl deviceEventMusicControl = new GBDeviceEventMusicControl();
deviceEventMusicControl.event = GBDeviceEventMusicControl.Event.valueOf(json.getString("n").toUpperCase());
evaluateGBDeviceEvent(deviceEventMusicControl);
} break;
case "call": {
GBDeviceEventCallControl deviceEventCallControl = new GBDeviceEventCallControl();
deviceEventCallControl.event = GBDeviceEventCallControl.Event.valueOf(json.getString("n").toUpperCase());
evaluateGBDeviceEvent(deviceEventCallControl);
} break;
case "status":
handleBatteryStatus(json);
break;
case "notify" :
handleNotificationControl(json);
break;
case "act":
handleActivity(json);
break;
case "http":
handleHttp(json);
break;
case "force_calendar_sync":
handleCalendarSync(json);
break;
case "intent":
handleIntent(json);
break;
case "gps_power": {
boolean status = json.getBoolean("status");
LOG.info("Got gps power status: " + status);
if (status) {
setupGPSUpdateTimer();
} else {
stopLocationUpdate();
}
} break;
default : {
LOG.info("UART RX JSON packet type '"+packetType+"' not understood.");
}
}
}
/**
* Handle "status" packets: battery info updates
*/
private void handleBatteryStatus(JSONObject json) throws JSONException {
GBDeviceEventBatteryInfo batteryInfo = new GBDeviceEventBatteryInfo(); GBDeviceEventBatteryInfo batteryInfo = new GBDeviceEventBatteryInfo();
batteryInfo.state = BatteryState.UNKNOWN; batteryInfo.state = BatteryState.UNKNOWN;
if (json.has("chg")) { if (json.has("chg")) {
@ -549,24 +601,12 @@ public class BangleJSDeviceSupport extends AbstractBTLEDeviceSupport {
if (json.has("volt")) if (json.has("volt"))
batteryInfo.voltage = (float) json.getDouble("volt"); batteryInfo.voltage = (float) json.getDouble("volt");
handleGBDeviceEvent(batteryInfo); handleGBDeviceEvent(batteryInfo);
} break; }
case "findPhone": {
boolean start = json.has("n") && json.getBoolean("n"); /**
GBDeviceEventFindPhone deviceEventFindPhone = new GBDeviceEventFindPhone(); * Handle "notify" packet, used to send notification control from device to GB
deviceEventFindPhone.event = start ? GBDeviceEventFindPhone.Event.START : GBDeviceEventFindPhone.Event.STOP; */
evaluateGBDeviceEvent(deviceEventFindPhone); private void handleNotificationControl(JSONObject json) throws JSONException {
} break;
case "music": {
GBDeviceEventMusicControl deviceEventMusicControl = new GBDeviceEventMusicControl();
deviceEventMusicControl.event = GBDeviceEventMusicControl.Event.valueOf(json.getString("n").toUpperCase());
evaluateGBDeviceEvent(deviceEventMusicControl);
} break;
case "call": {
GBDeviceEventCallControl deviceEventCallControl = new GBDeviceEventCallControl();
deviceEventCallControl.event = GBDeviceEventCallControl.Event.valueOf(json.getString("n").toUpperCase());
evaluateGBDeviceEvent(deviceEventCallControl);
} break;
case "notify" : {
GBDeviceEventNotificationControl deviceEvtNotificationControl = new GBDeviceEventNotificationControl(); GBDeviceEventNotificationControl deviceEvtNotificationControl = new GBDeviceEventNotificationControl();
// .title appears unused // .title appears unused
deviceEvtNotificationControl.event = GBDeviceEventNotificationControl.Event.valueOf(json.getString("n").toUpperCase()); deviceEvtNotificationControl.event = GBDeviceEventNotificationControl.Event.valueOf(json.getString("n").toUpperCase());
@ -584,8 +624,12 @@ public class BangleJSDeviceSupport extends AbstractBTLEDeviceSupport {
deviceEvtNotificationControl.handle = foundHandle; deviceEvtNotificationControl.handle = foundHandle;
} }
evaluateGBDeviceEvent(deviceEvtNotificationControl); evaluateGBDeviceEvent(deviceEvtNotificationControl);
} break; }
case "act": {
/**
* Handle "act" packet, used to send activity reports
*/
private void handleActivity(JSONObject json) throws JSONException {
BangleJSActivitySample sample = new BangleJSActivitySample(); BangleJSActivitySample sample = new BangleJSActivitySample();
sample.setTimestamp((int) (System.currentTimeMillis() / 1000L)); sample.setTimestamp((int) (System.currentTimeMillis() / 1000L));
int hrm = 0; int hrm = 0;
@ -626,9 +670,12 @@ public class BangleJSDeviceSupport extends AbstractBTLEDeviceSupport {
.putExtra(DeviceService.EXTRA_REALTIME_SAMPLE, sample); .putExtra(DeviceService.EXTRA_REALTIME_SAMPLE, sample);
LocalBroadcastManager.getInstance(getContext()).sendBroadcast(intent); LocalBroadcastManager.getInstance(getContext()).sendBroadcast(intent);
} }
} break; }
case "http": {
Prefs devicePrefs = new Prefs(GBApplication.getDeviceSpecificSharedPrefs(gbDevice.getAddress())); /**
* Handle "http" packet: make an HTTP request and return a "http" response
*/
private void handleHttp(JSONObject json) throws JSONException {
String _id = null; String _id = null;
try { try {
_id = json.getString("id"); _id = json.getString("id");
@ -636,7 +683,17 @@ public class BangleJSDeviceSupport extends AbstractBTLEDeviceSupport {
} }
final String id = _id; final String id = _id;
if (BuildConfig.INTERNET_ACCESS && devicePrefs.getBoolean(PREF_DEVICE_INTERNET_ACCESS, false)) { if (! BuildConfig.INTERNET_ACCESS) {
uartTxJSONError("http", "Internet access not enabled, check Gadgetbridge Device Settings", id);
return;
}
Prefs devicePrefs = new Prefs(GBApplication.getDeviceSpecificSharedPrefs(gbDevice.getAddress()));
if (! devicePrefs.getBoolean(PREF_DEVICE_INTERNET_ACCESS, false)) {
uartTxJSONError("http", "Internet access not enabled in this Gadgetbridge build", id);
return;
}
String url = json.getString("url"); String url = json.getString("url");
int method = Request.Method.GET; int method = Request.Method.GET;
@ -746,16 +803,71 @@ public class BangleJSDeviceSupport extends AbstractBTLEDeviceSupport {
}; };
RequestQueue queue = getRequestQueue(); RequestQueue queue = getRequestQueue();
queue.add(stringRequest); queue.add(stringRequest);
} else {
if (BuildConfig.INTERNET_ACCESS)
uartTxJSONError("http", "Internet access not enabled, check Gadgetbridge Device Settings",id);
else
uartTxJSONError("http", "Internet access not enabled in this Gadgetbridge build",id);
} }
} break;
case "intent": { /**
* Handle "force_calendar_sync" packet
*/
private void handleCalendarSync(JSONObject json) throws JSONException {
//if(!GBApplication.getPrefs().getBoolean("enable_calendar_sync", false)) return;
//pretty much like the updateEvents in CalendarReceiver, but would need a lot of libraries here
JSONArray ids = json.getJSONArray("ids");
ArrayList<Long> idsList = new ArrayList<>(ids.length());
try (DBHandler dbHandler = GBApplication.acquireDB()) {
DaoSession session = dbHandler.getDaoSession();
Long deviceId = DBHelper.getDevice(gbDevice, session).getId();
QueryBuilder<CalendarSyncState> qb = session.getCalendarSyncStateDao().queryBuilder();
//FIXME just use that and don't query every time?
List<CalendarSyncState> states = qb.where(
CalendarSyncStateDao.Properties.DeviceId.eq(deviceId)).build().list();
LOG.info("force_calendar_sync on banglejs: "+ ids.length() +" events on the device, "+ states.size() +" on our db");
for (int i = 0; i < ids.length(); i++) {
Long id = ids.getLong(i);
qb = session.getCalendarSyncStateDao().queryBuilder(); //is this needed again?
CalendarSyncState calendarSyncState = qb.where(
qb.and(CalendarSyncStateDao.Properties.DeviceId.eq(deviceId),
CalendarSyncStateDao.Properties.CalendarEntryId.eq(id))).build().unique();
if(calendarSyncState == null) {
onDeleteCalendarEvent((byte)0, id);
LOG.info("event id="+ id +" is on device id="+ deviceId +", removing it there");
} else {
//used for later, no need to check twice the ones that do not match
idsList.add(id);
}
}
//remove all elements not in ids from database (we don't have them)
for(CalendarSyncState calendarSyncState : states) {
long id = calendarSyncState.getCalendarEntryId();
if(!idsList.contains(id)) {
qb = session.getCalendarSyncStateDao().queryBuilder(); //is this needed again?
qb.where(qb.and(CalendarSyncStateDao.Properties.DeviceId.eq(deviceId),
CalendarSyncStateDao.Properties.CalendarEntryId.eq(id)))
.buildDelete().executeDeleteWithoutDetachingEntities();
LOG.info("event id="+ id +" is not on device id="+ deviceId +", removing from our db");
}
}
} catch (Exception e1) {
GB.toast("Database Error while forcefully syncing Calendar", Toast.LENGTH_SHORT, GB.ERROR, e1);
}
//force a syncCalendar now, send missing events
Context context = GBApplication.getContext();
Intent intent = new Intent("FORCE_CALENDAR_SYNC");
intent.setPackage(BuildConfig.APPLICATION_ID);
GBApplication.getContext().sendBroadcast(intent);
}
/**
* Handle "intent" packet: broadcast an Android intent
*/
private void handleIntent(JSONObject json) throws JSONException {
Prefs devicePrefs = new Prefs(GBApplication.getDeviceSpecificSharedPrefs(gbDevice.getAddress())); Prefs devicePrefs = new Prefs(GBApplication.getDeviceSpecificSharedPrefs(gbDevice.getAddress()));
if (devicePrefs.getBoolean(PREF_DEVICE_INTENTS, false)) { if (!devicePrefs.getBoolean(PREF_DEVICE_INTENTS, false)) {
uartTxJSONError("intent", "Android Intents not enabled, check Gadgetbridge Device Settings", null);
return;
}
String target = json.has("target") ? json.getString("target") : "broadcastreceiver"; String target = json.has("target") ? json.getString("target") : "broadcastreceiver";
Intent in = new Intent(); Intent in = new Intent();
if (json.has("action")) in.setAction(json.getString("action")); if (json.has("action")) in.setAction(json.getString("action"));
@ -815,71 +927,6 @@ public class BangleJSDeviceSupport extends AbstractBTLEDeviceSupport {
LOG.info("Targeting '"+target+"' isn't implemented or doesn't exist."); LOG.info("Targeting '"+target+"' isn't implemented or doesn't exist.");
GB.toast(getContext(), "Targeting '"+target+"' isn't implemented or it doesn't exist.", Toast.LENGTH_LONG, GB.INFO); GB.toast(getContext(), "Targeting '"+target+"' isn't implemented or it doesn't exist.", Toast.LENGTH_LONG, GB.INFO);
} }
} else {
uartTxJSONError("intent", "Android Intents not enabled, check Gadgetbridge Device Settings", null);
} break;
}
case "force_calendar_sync": {
//if(!GBApplication.getPrefs().getBoolean("enable_calendar_sync", false)) return;
//pretty much like the updateEvents in CalendarReceiver, but would need a lot of libraries here
JSONArray ids = json.getJSONArray("ids");
ArrayList<Long> idsList = new ArrayList<>(ids.length());
try (DBHandler dbHandler = GBApplication.acquireDB()) {
DaoSession session = dbHandler.getDaoSession();
Long deviceId = DBHelper.getDevice(gbDevice, session).getId();
QueryBuilder<CalendarSyncState> qb = session.getCalendarSyncStateDao().queryBuilder();
//FIXME just use that and don't query every time?
List<CalendarSyncState> states = qb.where(
CalendarSyncStateDao.Properties.DeviceId.eq(deviceId)).build().list();
LOG.info("force_calendar_sync on banglejs: "+ ids.length() +" events on the device, "+ states.size() +" on our db");
for (int i = 0; i < ids.length(); i++) {
Long id = ids.getLong(i);
qb = session.getCalendarSyncStateDao().queryBuilder(); //is this needed again?
CalendarSyncState calendarSyncState = qb.where(
qb.and(CalendarSyncStateDao.Properties.DeviceId.eq(deviceId),
CalendarSyncStateDao.Properties.CalendarEntryId.eq(id))).build().unique();
if(calendarSyncState == null) {
onDeleteCalendarEvent((byte)0, id);
LOG.info("event id="+ id +" is on device id="+ deviceId +", removing it there");
} else {
//used for later, no need to check twice the ones that do not match
idsList.add(id);
}
}
//remove all elements not in ids from database (we don't have them)
for(CalendarSyncState calendarSyncState : states) {
long id = calendarSyncState.getCalendarEntryId();
if(!idsList.contains(id)) {
qb = session.getCalendarSyncStateDao().queryBuilder(); //is this needed again?
qb.where(qb.and(CalendarSyncStateDao.Properties.DeviceId.eq(deviceId),
CalendarSyncStateDao.Properties.CalendarEntryId.eq(id)))
.buildDelete().executeDeleteWithoutDetachingEntities();
LOG.info("event id="+ id +" is not on device id="+ deviceId +", removing from our db");
}
}
} catch (Exception e1) {
GB.toast("Database Error while forcefully syncing Calendar", Toast.LENGTH_SHORT, GB.ERROR, e1);
}
//force a syncCalendar now, send missing events
Intent intent = new Intent("FORCE_CALENDAR_SYNC");
intent.setPackage(BuildConfig.APPLICATION_ID);
GBApplication.getContext().sendBroadcast(intent);
} break;
case "gps_power": {
boolean status = json.getBoolean("status");
LOG.info("Got gps power status: " + status);
if (status) {
setupGPSUpdateTimer();
} else {
stopLocationUpdate();
}
} break;
default : {
LOG.info("UART RX JSON packet type '"+packetType+"' not understood.");
}
}
} }
private Intent addIntentFlag(Intent intent, String flag) { private Intent addIntentFlag(Intent intent, String flag) {