@Override public void run() { logger.info("Response Parser Running"); if (!Main.LOGLEVEL.equals("OFF")) { Main.print("[+]Response Parser Thread Running..."); } while (RUN) { try { line = TinygDriver.jsonQueue.take(); if (line.equals("")) { continue; } if (line.startsWith("{")) { if (isTEXT_MODE()) { setTEXT_MODE(false); // This checks to see if we WERE in textmode. If we were we notify the user that we are // not longer and update the system state. setChanged(); message[0] = "TEXTMODE_REPORT"; message[1] = "[+]JSON Response Detected... Leaving Text mode.. Querying System State....\n"; notifyObservers(message); try { TinygDriver.getInstance().cmdManager.queryAllMachineSettings(); TinygDriver.getInstance().cmdManager.queryAllHardwareAxisSettings(); TinygDriver.getInstance().cmdManager.queryAllMotorSettings(); } catch (Exception ex) { logger.error( "Error leaving Text mode and querying Motor, Machine and Axis Settings."); } } parseJSON(line); // Take a line from the response queue when its ready and parse it. } else { // Text Mode Response if (!isTEXT_MODE()) { // We are just entering text mode and need to alert the user. // This will fire the every time user is entering text mode. setTEXT_MODE(true); setChanged(); message[0] = "TEXTMODE_REPORT"; message[1] = "[+]User has entered text mode. To exit type \"{\" and hit enter.\n"; notifyObservers(message); } setChanged(); message[0] = "TEXTMODE_REPORT"; message[1] = line + "\n"; notifyObservers(message); } } catch (InterruptedException | JSONException ex) { logger.error("[!]Error in responseParser run(): " + ex.getMessage()); } } }
public void applySettingStatusReport(JSONObject js) { /** * This breaks the mold a bit.. but its more efficient. This gets called off the top of * ParseJson if it has an "SR" in it. Sr's are called so often that instead of walking the * normal parsing tree.. this skips to the end */ try { Iterator ii = js.keySet().iterator(); // This is a special multi single value response object while (ii.hasNext()) { String key = ii.next().toString(); responseCommand rc = new responseCommand(MNEMONIC_GROUP_SYSTEM, key.toString(), js.get(key).toString()); TinygDriver.getInstance().machine.applyJsonStatusReport(rc); // _applySettings(rc.buildJsonObject(), rc.getSettingParent()); //we will // supply the parent object name for each key pair } setChanged(); message[0] = "STATUS_REPORT"; message[1] = null; notifyObservers(message); } catch (Exception ex) { logger.error("[!] Error in applySettingStatusReport(JsonOBject js) : " + ex.getMessage()); logger.error("[!]js.tostring " + js.toString()); setChanged(); message[0] = "STATUS_REPORT"; message[1] = null; notifyObservers(message); } }
private void parseFooter(JSONArray footerValues) { try { // Checking to see if we have a footer response // Status reports will not have a footer so this is for everything else responseFooter.setProtocolVersion(footerValues.getInt(FOOTER_ELEMENT_PROTOCOL_VERSION)); responseFooter.setStatusCode(footerValues.getInt(FOOTER_ELEMENT_STATUS_CODE)); responseFooter.setRxRecvd(footerValues.getInt(FOOTER_ELEMENT_RX_RECVD)); responseFooter.setCheckSum(footerValues.getInt(FOOTER_ELEMENT_STATUS_CODE)); // Out footer object is not populated int beforeBytesReturned = TinygDriver.getInstance().serialWriter.getBufferValue(); // Make sure we do not add bytes to a already full buffer if (beforeBytesReturned != TinygDriver.MAX_BUFFER) { TinygDriver.getInstance() .serialWriter .addBytesReturnedToBuffer(responseFooter.getRxRecvd()); int afterBytesReturned = TinygDriver.getInstance().serialWriter.getBufferValue(); logger.debug( "Returned " + responseFooter.getRxRecvd() + " to buffer... Buffer was " + beforeBytesReturned + " is now " + afterBytesReturned); TinygDriver.getInstance() .serialWriter .notifyAck(); // We let our serialWriter thread know we have added some space to the // buffer. // Lets tell the UI the new size of the buffer message[0] = "BUFFER_UPDATE"; message[1] = String.valueOf(afterBytesReturned); setChanged(); notifyObservers(message); } } catch (Exception ex) { logger.error("Error parsing json footer"); } }
public void applySettingMasterGroup(JSONObject js, String pg) throws Exception { if (pg.equals(MNEMONIC_GROUP_STATUS_REPORT)) { // This is a status report master object that came in through a response object. // meaning that the response was asked for like this {"sr":""} and returned like this. // {"r":{"sr":{"line":0,"posx":0.000,"posy":0.000,"posz":0.000,"posa":0.000,"vel":0.000,"unit":1,"momo":0,"stat":3},"f":[1,0,10,885]}} // Right now its parsed down to JUST the json object for the SR like so. // {"sr":{"line":0,"posx":0.000,"posy":0.000,"posz":0.000,"posa":0.000,"vel":0.000,"unit":1,"momo":0,"stat":3},"f":[1,0,10,885]} // so we can now just pass it to the applySettingStatusReport method. applySettingStatusReport(js); } else { if (js.keySet().size() > 1) { Iterator ii = js.keySet().iterator(); // This is a special multi single value response object while (ii.hasNext()) { String key = ii.next().toString(); if (key.equals("f")) { parseFooter( js.getJSONArray( "f")); // This is very important. We break out our response footer.. error // codes.. bytes availble in hardware buffer etc. } else { responseCommand rc = TinygDriver.getInstance().mneManager.lookupSingleGroupMaster(key, pg); if (rc == null) { // This happens when a new mnemonic has been added to the tinyG firmware // but not added to tgFX's MnemonicManger // This is the error case logger.error( "Mnemonic Lookup Failed in applySettingsMasterGroup. \n\tMake sure there are not new elements added to TinyG and not to the MnemonicManager Class.\n\tMNEMONIC FAILED: " + key); } else { // This is the normal case rc.setSettingValue(js.get(key).toString()); String parentGroup = rc.getSettingParent(); _applySettings( rc.buildJsonObject(), rc.getSettingParent()); // we will supply the parent object name for each key pai } } } } } }
public synchronized void parseJSON(String line) throws JSONException { // logger.info("Got Line: " + line + " from TinyG."); if (!Main.LOGLEVEL.equals("OFF")) { Main.print("-" + line); } final JSONObject js = new JSONObject(line); if (js.has("r") || (js.has("sr")) || (js.has("tgfx"))) { // tgfx is for messages like timeout connections Platform.runLater( new Runnable() { @Override public void run() { try { if (js.has("tgfx")) { // This is for when tgfx times out when trying to connect to TinyG. // tgFX puts a message in the response parser queue to be parsed here. setChanged(); message[0] = "TINYG_CONNECTION_TIMEOUT"; message[1] = (String) js.get("tgfx") + "\n"; notifyObservers(message); } else if (js.has("f")) { // The new version of TinyG's footer has a footer element in each response. // We parse it here parseFooter(js.getJSONArray("f")); if (js.has("r")) { applySetting(js.getJSONObject("r")); } else if (js.has("sr")) { applySettingStatusReport(js.getJSONObject("sr")); } } else { // This is where the old footer style is dealt with // These are the 2 types of responses we will get back. switch (js.keys().next().toString()) { case ("r"): applySetting(js.getJSONObject("r")); break; case ("sr"): applySettingStatusReport(js.getJSONObject("sr")); break; } } } catch (JSONException ex) { logger.error(ex); } } }); } else if (js.has("qr")) { TinygDriver.getInstance().qr.parse(js); } else if (js.has("er")) { applySetting(js); } }
private void _applySettings(JSONObject js, String pg) throws Exception { switch (pg) { case (MNEMONIC_GROUP_MOTOR_1): TinygDriver.getInstance() .machine .getMotorByNumber(MNEMONIC_GROUP_MOTOR_1) .applyJsonSystemSetting( js.getJSONObject(MNEMONIC_GROUP_MOTOR_1), MNEMONIC_GROUP_MOTOR_1); setChanged(); message[0] = "CMD_GET_MOTOR_SETTINGS"; message[1] = MNEMONIC_GROUP_MOTOR_1; notifyObservers(message); break; case (MNEMONIC_GROUP_MOTOR_2): TinygDriver.getInstance() .machine .getMotorByNumber(MNEMONIC_GROUP_MOTOR_2) .applyJsonSystemSetting( js.getJSONObject(MNEMONIC_GROUP_MOTOR_2), MNEMONIC_GROUP_MOTOR_2); setChanged(); message[0] = "CMD_GET_MOTOR_SETTINGS"; message[1] = MNEMONIC_GROUP_MOTOR_2; notifyObservers(message); break; case (MNEMONIC_GROUP_MOTOR_3): TinygDriver.getInstance() .machine .getMotorByNumber(MNEMONIC_GROUP_MOTOR_3) .applyJsonSystemSetting( js.getJSONObject(MNEMONIC_GROUP_MOTOR_3), MNEMONIC_GROUP_MOTOR_3); setChanged(); message[0] = "CMD_GET_MOTOR_SETTINGS"; message[1] = MNEMONIC_GROUP_MOTOR_3; notifyObservers(message); break; case (MNEMONIC_GROUP_MOTOR_4): TinygDriver.getInstance() .machine .getMotorByNumber(MNEMONIC_GROUP_MOTOR_4) .applyJsonSystemSetting( js.getJSONObject(MNEMONIC_GROUP_MOTOR_4), MNEMONIC_GROUP_MOTOR_4); setChanged(); message[0] = "CMD_GET_MOTOR_SETTINGS"; message[1] = MNEMONIC_GROUP_MOTOR_4; notifyObservers(message); break; case (MNEMONIC_GROUP_AXIS_X): TinygDriver.getInstance() .machine .getAxisByName(MNEMONIC_GROUP_AXIS_X) .applyJsonSystemSetting(js.getJSONObject(MNEMONIC_GROUP_AXIS_X), MNEMONIC_GROUP_AXIS_X); setChanged(); message[0] = "CMD_GET_AXIS_SETTINGS"; message[1] = MNEMONIC_GROUP_AXIS_X; notifyObservers(message); break; case (MNEMONIC_GROUP_AXIS_Y): TinygDriver.getInstance() .machine .getAxisByName(MNEMONIC_GROUP_AXIS_Y) .applyJsonSystemSetting(js.getJSONObject(MNEMONIC_GROUP_AXIS_Y), MNEMONIC_GROUP_AXIS_Y); setChanged(); message[0] = "CMD_GET_AXIS_SETTINGS"; message[1] = MNEMONIC_GROUP_AXIS_Y; notifyObservers(message); break; case (MNEMONIC_GROUP_AXIS_Z): TinygDriver.getInstance() .machine .getAxisByName(MNEMONIC_GROUP_AXIS_Z) .applyJsonSystemSetting(js.getJSONObject(MNEMONIC_GROUP_AXIS_Z), MNEMONIC_GROUP_AXIS_Z); setChanged(); message[0] = "CMD_GET_AXIS_SETTINGS"; message[1] = MNEMONIC_GROUP_AXIS_Z; notifyObservers(message); break; case (MNEMONIC_GROUP_AXIS_A): TinygDriver.getInstance() .machine .getAxisByName(MNEMONIC_GROUP_AXIS_A) .applyJsonSystemSetting(js.getJSONObject(MNEMONIC_GROUP_AXIS_A), MNEMONIC_GROUP_AXIS_A); setChanged(); message[0] = "CMD_GET_AXIS_SETTINGS"; message[1] = MNEMONIC_GROUP_AXIS_A; notifyObservers(message); break; case (MNEMONIC_GROUP_AXIS_B): TinygDriver.getInstance() .machine .getAxisByName(MNEMONIC_GROUP_AXIS_B) .applyJsonSystemSetting(js.getJSONObject(MNEMONIC_GROUP_AXIS_B), MNEMONIC_GROUP_AXIS_B); setChanged(); message[0] = "CMD_GET_AXIS_SETTINGS"; message[1] = MNEMONIC_GROUP_AXIS_B; notifyObservers(message); break; case (MNEMONIC_GROUP_AXIS_C): TinygDriver.getInstance() .machine .getAxisByName(MNEMONIC_GROUP_AXIS_C) .applyJsonSystemSetting(js.getJSONObject(MNEMONIC_GROUP_AXIS_C), MNEMONIC_GROUP_AXIS_C); setChanged(); message[0] = "CMD_GET_AXIS_SETTINGS"; message[1] = MNEMONIC_GROUP_AXIS_C; notifyObservers(message); break; case ("hom"): logger.info("HOME"); break; case ("msg"): // NOP break; case (MNEMONIC_GROUP_SYSTEM): TinygDriver.getInstance() .machine .applyJsonSystemSetting(js.getJSONObject(MNEMONIC_GROUP_SYSTEM), MNEMONIC_GROUP_SYSTEM); /** UNCOMMENT THIS BELOW WHEN WE HAVE MACHINE SETTINGS THAT NEED TO UPDATE THE GU */ message[0] = "MACHINE_UPDATE"; message[1] = null; setChanged(); notifyObservers(message); break; case (MNEMONIC_GROUP_STATUS_REPORT): logger.info("Status Report"); applySettingMasterGroup(js, MNEMONIC_GROUP_STATUS_REPORT); setChanged(); message[0] = "STATUS_REPORT"; message[1] = null; notifyObservers(message); break; case (MNEMONIC_GROUP_EMERGENCY_SHUTDOWN): Platform.runLater( new Runnable() { @Override public void run() { Main.postConsoleMessage("TinyG Alarm " + line); MonologFXButton btnYes = MonologFXButtonBuilder.create() .defaultButton(true) .icon("/testmonologfx/dialog_apply.png") .type(MonologFXButton.Type.YES) .build(); MonologFXButton btnNo = MonologFXButtonBuilder.create() .cancelButton(true) .icon("/testmonologfx/dialog_cancel.png") .type(MonologFXButton.Type.CANCEL) .build(); MonologFX mono = MonologFXBuilder.create() .titleText("Error Occured") .message( "You have triggered a limit switch. TinyG is now in DISABLED mode. \n" + "Manually back your machine off of its limit switches.\n Once done, if you would like to re-enable TinyG click yes.") .button(btnYes) .button(btnNo) .type(MonologFX.Type.ERROR) .build(); MonologFXButton.Type retval = mono.showDialog(); switch (retval) { case YES: logger.info("Clicked Yes"); try { TinygDriver.getInstance().priorityWrite((byte) 0x18); } catch (Exception ex) { logger.error(ex); } break; case CANCEL: logger.info("Clicked No"); Main.postConsoleMessage( "TinyG will remain in diabled mode until you power cycle or click the reset button."); break; } } }); default: // This is for single settings xfr, 1tr etc... // This is pretty ugly but it gets the key and the value. For single values. responseCommand rc = TinygDriver.getInstance().mneManager.lookupSingleGroup(pg); // String _parent = String.valueOf(parentGroup.charAt(0)); String newJs; // String _key = parentGroup; //I changed this to deal with the fb // mnemonic.. not sure if this works all over. rc.setSettingValue(String.valueOf(js.get(js.keys().next().toString()))); logger.info( "Single Key Value: Group:" + rc.getSettingParent() + " key:" + rc.getSettingKey() + " value:" + rc.getSettingValue()); if (rc.getSettingValue().equals((""))) { logger.info(rc.getSettingKey() + " value was null"); } else { this.applySetting( rc.buildJsonObject()); // We pass the new json object we created from the string above } } }
public void applySetting(JSONObject js) { try { if (js.length() == 0) { // This is a blank object we just return and move on } else if (js.keySet().size() > 1) { // If there are more than one object in the json response Iterator ii = js.keySet().iterator(); // This is a special multi single value response object while (ii.hasNext()) { String key = ii.next().toString(); switch (key) { case "f": parseFooter(js.getJSONArray("f")); // This is very important. // We break out our response footer.. error codes.. bytes availble in hardware buffer // etc. break; case "msg": message[0] = "TINYG_USER_MESSAGE"; message[1] = (String) js.get(key) + "\n"; logger.info("[+]TinyG Message Sent: " + js.get(key) + "\n"); setChanged(); notifyObservers(message); break; case "rx": TinygDriver.getInstance().serialWriter.setBuffer(js.getInt(key)); break; default: if (TinygDriver.getInstance().mneManager.isMasterGroupObject(key)) { // logger.info("Group Status Report Detected: " + key); applySettingMasterGroup(js.getJSONObject(key), key); continue; } responseCommand rc = TinygDriver.getInstance().mneManager.lookupSingleGroup(key); rc.setSettingValue(js.get(key).toString()); _applySettings( rc.buildJsonObject(), rc.getSettingParent()); // we will supply the parent object name for each key pair break; } } } else { /* This else follows: * Contains a single object in the JSON response */ if (js.keySet().contains("f")) { /** This is a single response footer object: Like So: {"f":[1,0,5,3330]} */ parseFooter(js.getJSONArray("f")); } else { /** * Contains a single object in the json response I am not sure this else is needed any * longer. */ _applySettings(js, js.keys().next().toString()); } } } catch (JSONException ex) { logger.error("[!] Error in applySetting(JsonOBject js) : " + ex.getMessage()); logger.error("[!]JSON String Was: " + js.toString()); logger.error("Error in Line: " + js); } catch (Exception ex) { logger.error("[!] Error in applySetting(JsonOBject js) : " + ex.getMessage()); logger.error(ex.getClass().toString()); } }