1
0
mirror of https://codeberg.org/Freeyourgadget/Gadgetbridge synced 2024-10-19 01:39:39 +02:00

Pebble: JS basic implementation of transaction acknowledgment

JAVA side:
- first trivial handling of ACK/NACK message,
- fake the location age until an update mechanism is implemented,
- make the appmessage parsing more robust,
- comment the forecast mimicked reply as it was wrong and confusing for some watchfaces

JS side: first trivial handling of ACK/NACK message
This commit is contained in:
Daniele Gobbetti 2017-08-02 22:08:29 +02:00
parent 5939c244fb
commit aa28625d9f
2 changed files with 68 additions and 28 deletions

View File

@ -159,17 +159,33 @@ function gbPebble() {
if (document.getElementById("step2").style.display == 'block') { //intercept the values if (document.getElementById("step2").style.display == 'block') { //intercept the values
document.getElementById("jsondata").innerHTML=self.configurationValues; document.getElementById("jsondata").innerHTML=self.configurationValues;
} else { //pass them silently } else { //pass them silently
GBjs.sendAppMessage(JSON.stringify(dict)); var needsTransaction = false;
if (callbackAck != undefined || callbackNack != undefined) {
needsTransaction = true;
} }
var transactionId = GBjs.sendAppMessage(JSON.stringify(dict), needsTransaction);
if (needsTransaction) {
if (callbackAck != undefined) { if (callbackAck != undefined) {
callbackAck(); this.addEventListener("ACK"+transactionId, function(e) {
// console.log("ACK FOR " + JSON.stringify(e));
callbackAck(e);
self.removeEventListener("ACK"+transactionId);
self.removeEventListener("NACK"+transactionId);
});
}
if (callbackNack != undefined) {
this.addEventListener("NACK"+transactionId, function(e) {
// console.log("NACK FOR " + JSON.stringify(e));
callbackNack(e);
self.removeEventListener("ACK"+transactionId);
self.removeEventListener("NACK"+transactionId);
});
}
}
} }
} }
catch (e) { catch (e) {
GBjs.gbLog("sendAppMessage failed"); GBjs.gbLog("sendAppMessage failed");
if (callbackNack != undefined) {
callbackNack();
}
} }
} }

View File

@ -123,22 +123,31 @@ public class WebViewSingleton {
public static void appMessage(GBDeviceEventAppMessage message) { public static void appMessage(GBDeviceEventAppMessage message) {
final String jsEvent;
if (webViewSingleton.instance == null) { if (webViewSingleton.instance == null) {
LOG.warn("WEBVIEW is not initialized, cannot send appMessages to it"); LOG.warn("WEBVIEW is not initialized, cannot send appMessages to it");
return; return;
} }
if (!message.appUUID.equals(currentRunningUUID)) {
LOG.info("WEBVIEW ignoring message for app that is not currently running: " + message.appUUID + " message: " + message.message + " type: " + message.type);
// return; //TODO: ignoring would be the right thing to do here, but sometimes appUUID is apparently wrong
}
// TODO: handle ACK and NACK types with ids // TODO: handle ACK and NACK types with ids
if (message.type != GBDeviceEventAppMessage.TYPE_APPMESSAGE) { if (message.type != GBDeviceEventAppMessage.TYPE_APPMESSAGE) {
return; jsEvent = (GBDeviceEventAppMessage.TYPE_NACK == GBDeviceEventAppMessage.TYPE_APPMESSAGE) ? "NACK" + message.id : "ACK" + message.id;
LOG.debug("WEBVIEW received ACK/NACK:" + message.message + " for uuid: " + message.appUUID + " ID: " + message.id);
} else {
jsEvent = "appmessage";
} }
final String appMessage = parseIncomingAppMessage(message.message, message.appUUID); final String appMessage = parseIncomingAppMessage(message.message, message.appUUID);
LOG.debug("to WEBVIEW: " + appMessage); LOG.debug("to WEBVIEW: event: " + jsEvent + " message: " + appMessage);
new Handler(webViewSingleton.mainLooper).post(new Runnable() { new Handler(webViewSingleton.mainLooper).post(new Runnable() {
@Override @Override
public void run() { public void run() {
webViewSingleton.instance.evaluateJavascript("Pebble.evaluate('appmessage',[" + appMessage + "]);", new ValueCallback<String>() { webViewSingleton.instance.evaluateJavascript("Pebble.evaluate('" + jsEvent + "',[" + appMessage + "]);", new ValueCallback<String>() {
@Override @Override
public void onReceiveValue(String s) { public void onReceiveValue(String s) {
//TODO: the message should be acked here instead of in PebbleIoThread //TODO: the message should be acked here instead of in PebbleIoThread
@ -192,6 +201,7 @@ public class WebViewSingleton {
Location lastKnownLocation = locationManager.getLastKnownLocation(provider); Location lastKnownLocation = locationManager.getLastKnownLocation(provider);
if (lastKnownLocation != null) { if (lastKnownLocation != null) {
this.timestamp = lastKnownLocation.getTime(); this.timestamp = lastKnownLocation.getTime();
this.timestamp = System.currentTimeMillis() - 1000; //TODO: request updating the location and don't fake its age
this.latitude = (float) lastKnownLocation.getLatitude(); this.latitude = (float) lastKnownLocation.getLatitude();
this.longitude = (float) lastKnownLocation.getLongitude(); this.longitude = (float) lastKnownLocation.getLongitude();
@ -260,20 +270,20 @@ public class WebViewSingleton {
resp.put("cod", 200); resp.put("cod", 200);
resp.put("coord", coordObject(currentPosition)); resp.put("coord", coordObject(currentPosition));
resp.put("sys", sysObject(currentPosition)); resp.put("sys", sysObject(currentPosition));
} else if ("/data/2.5/forecast".equals(type) && Weather.getInstance().getWeather2().reconstructedForecast != null) { //this is wrong, as we only have daily data. Unfortunately it looks like daily forecasts cannot be reconstructed // } else if ("/data/2.5/forecast".equals(type) && Weather.getInstance().getWeather2().reconstructedForecast != null) { //this is wrong, as we only have daily data. Unfortunately it looks like daily forecasts cannot be reconstructed
resp = new JSONObject(Weather.getInstance().getWeather2().reconstructedForecast.toString()); // resp = new JSONObject(Weather.getInstance().getWeather2().reconstructedForecast.toString());
//
JSONObject city = resp.getJSONObject("city"); // JSONObject city = resp.getJSONObject("city");
city.put("coord", coordObject(currentPosition)); // city.put("coord", coordObject(currentPosition));
//
JSONArray list = resp.getJSONArray("list"); // JSONArray list = resp.getJSONArray("list");
for (int i = 0, size = list.length(); i < size; i++) { // for (int i = 0, size = list.length(); i < size; i++) {
JSONObject item = list.getJSONObject(i); // JSONObject item = list.getJSONObject(i);
JSONObject main = item.getJSONObject("main"); // JSONObject main = item.getJSONObject("main");
convertTemps(main, units); //caller might want different units // convertTemps(main, units); //caller might want different units
} // }
//
resp.put("cod", 200); // resp.put("cod", 200);
} else { } else {
LOG.warn("WEBVIEW - cannot mimick request of type " + type + " (unsupported or lack of data)"); LOG.warn("WEBVIEW - cannot mimick request of type " + type + " (unsupported or lack of data)");
return null; return null;
@ -393,6 +403,10 @@ public class WebViewSingleton {
JSONObject knownKeys = getAppConfigurationKeys(uuid); JSONObject knownKeys = getAppConfigurationKeys(uuid);
SparseArray<String> appKeysMap = new SparseArray<>(); SparseArray<String> appKeysMap = new SparseArray<>();
if (knownKeys == null) {
return "{}";
}
String inKey, outKey; String inKey, outKey;
//knownKeys contains "name"->"index", we need to reverse that //knownKeys contains "name"->"index", we need to reverse that
for (Iterator<String> key = knownKeys.keys(); key.hasNext(); ) { for (Iterator<String> key = knownKeys.keys(); key.hasNext(); ) {
@ -423,7 +437,7 @@ public class WebViewSingleton {
} }
jsAppMessage.put("payload", outgoing); jsAppMessage.put("payload", outgoing);
} catch (JSONException e) { } catch (Exception e) {
LOG.warn(e.getMessage()); LOG.warn(e.getMessage());
} }
return jsAppMessage.toString(); return jsAppMessage.toString();
@ -433,11 +447,13 @@ public class WebViewSingleton {
UUID mUuid; UUID mUuid;
GBDevice device; GBDevice device;
Integer lastTransaction;
private JSInterface(GBDevice device, UUID mUuid) { private JSInterface(GBDevice device, UUID mUuid) {
LOG.debug("Creating JS interface for UUID: " + mUuid.toString()); LOG.debug("Creating JS interface for UUID: " + mUuid.toString());
this.device = device; this.device = device;
this.mUuid = mUuid; this.mUuid = mUuid;
this.lastTransaction = 0;
} }
@ -451,8 +467,9 @@ public class WebViewSingleton {
} }
@JavascriptInterface @JavascriptInterface
public void sendAppMessage(String msg) { public String sendAppMessage(String msg, String needsTransactionMsg) {
LOG.debug("from WEBVIEW: " + msg); boolean needsTransaction = "true".equals(needsTransactionMsg);
LOG.debug("from WEBVIEW: " + msg + " needs a transaction: " + needsTransaction);
JSONObject knownKeys = getAppConfigurationKeys(this.mUuid); JSONObject knownKeys = getAppConfigurationKeys(this.mUuid);
try { try {
@ -486,11 +503,18 @@ public class WebViewSingleton {
} }
LOG.info("WEBVIEW message to pebble: " + out.toString()); LOG.info("WEBVIEW message to pebble: " + out.toString());
GBApplication.deviceService().onAppConfiguration(this.mUuid, out.toString(), null); // TODO: insert local id for transaction if (needsTransaction) {
this.lastTransaction++;
GBApplication.deviceService().onAppConfiguration(this.mUuid, out.toString(), this.lastTransaction);
return this.lastTransaction.toString();
} else {
GBApplication.deviceService().onAppConfiguration(this.mUuid, out.toString(), null);
}
} catch (JSONException e) { } catch (JSONException e) {
LOG.warn(e.getMessage()); LOG.warn(e.getMessage());
} }
return null;
} }
@JavascriptInterface @JavascriptInterface