From 5211540e033de8c1ae10b78cdbbacf499950820b Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Mon, 23 May 2022 15:38:06 +0100 Subject: [PATCH] Improve JSON stringification for Bangle.js - much more compact, and now handles non-ASCII chars correctly --- .../banglejs/BangleJSDeviceSupport.java | 89 ++++++++++++++----- 1 file changed, 66 insertions(+), 23 deletions(-) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/banglejs/BangleJSDeviceSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/banglejs/BangleJSDeviceSupport.java index 8ed215b49..e6fcefb90 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/banglejs/BangleJSDeviceSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/banglejs/BangleJSDeviceSupport.java @@ -231,9 +231,8 @@ public class BangleJSDeviceSupport extends AbstractBTLEDeviceSupport { /// Write a string of data, and chunk it up private void uartTx(TransactionBuilder builder, String str) { + byte[] bytes = str.getBytes(StandardCharsets.ISO_8859_1); LOG.info("UART TX: " + str); - byte[] bytes; - bytes = str.getBytes(StandardCharsets.ISO_8859_1); // FIXME: somehow this is still giving us UTF8 data when we put images in strings. Maybe JSON.stringify is converting to UTF-8? for (int i=0;i iter = jsonObj.keys(); - while (iter.hasNext()) { - String key = iter.next(); - Object v = jsonObj.get(key); - if (v instanceof Integer) { - // ... - } else // .. - if (iter.hasNext()) json+=","; + /// Converts an object to a JSON string. see jsonToString + private String jsonToStringInternal(Object v) { + if (v instanceof String) { + /* Convert a string, escaping chars we can't send over out UART connection */ + String s = (String)v; + String json = "\""; + for (int i=0;i0) json += ","; + Object o = null; + try { + o = a.get(i); + } catch (JSONException e) { + LOG.warn("jsonToString array error: " + e.getLocalizedMessage()); + } + json += jsonToStringInternal(o)); + } + return json+"]"; + } else if (v instanceof JSONObject) { + JSONObject obj = (JSONObject)v; + String json = "{"; + Iterator iter = obj.keys(); + while (iter.hasNext()) { + String key = iter.next(); + Object o = null; + try { + o = obj.get(key); + } catch (JSONException e) { + LOG.warn("jsonToString object error: " + e.getLocalizedMessage()); + } + json += key+":"+jsonToStringInternal(o); + if (iter.hasNext()) json+=","; + } + return json+"}"; + } else { // int/double/null + return v.toString(); } - return json+"}";*/ + } + + /// Convert a JSON object to a JSON String (NOT 100% JSON compliant) + public String jsonToString(JSONObject jsonObj) { + /* jsonObj.toString() works but breaks char codes>128 (encodes as UTF8?) and also uses + \u0000 when just \0 would do (and so on). + + So we do it manually, which can be more compact anyway. + This is JSON-ish, so not exactly as per JSON1 spec but good enough for Espruino. + */ + return jsonToStringInternal(jsonObj); } /// Write a JSON object of data @@ -291,10 +334,10 @@ public class BangleJSDeviceSupport extends AbstractBTLEDeviceSupport { private void handleUartRxLine(String line) { LOG.info("UART RX LINE: " + line); - + if (line.length()==0) return; if (">Uncaught ReferenceError: \"GB\" is not defined".equals(line)) GB.toast(getContext(), "Gadgetbridge plugin not installed on Bangle.js", Toast.LENGTH_LONG, GB.ERROR); - else if (line.length() > 0 && line.charAt(0)=='{') { + else if (line.charAt(0)=='{') { // JSON - we hope! try { JSONObject json = new JSONObject(line);