void nv_read_parameter_int(uint32_t* val) { nvObj_t *nv = nv_reset_nv_list(); for (uint16_t i = 0; i < nv_index_max(); i++) { if (cfgArray[i].target == val) { nv->index = i; break; } } strncpy_P(nv->token, cfgArray[nv->index].token, TOKEN_LEN); read_persistent_value(nv); nv_set(nv); }
void nv_save_parameter_flt(float* val) { nvObj_t *nv = nv_reset_nv_list(); for (uint16_t i = 0; i < nv_index_max(); i++) { if (cfgArray[i].target == val) { nv->index = i; break; } } nv->value = *val; strncpy_P(nv->token, cfgArray[nv->index].token, TOKEN_LEN); nv_set(nv); nv_persist(nv); }
static stat_t _probing_error_exit(int8_t axis) { // Generate the warning message. Since the error exit returns via the probing callback // - and not the main controller - it requires its own display processing nv_reset_nv_list(); if (axis == -2) { nv_add_conditional_message((const char *)"Probing error - invalid probe destination"); } else { char msg[NV_MESSAGE_LEN]; sprintf_P(msg, PSTR("Probing error - %c axis cannot move during probing"), cm_get_axis_char(axis)); nv_add_conditional_message(msg); } nv_print_list(STAT_PROBE_CYCLE_FAILED, TEXT_INLINE_VALUES, JSON_RESPONSE_FORMAT); // clean up and exit _probe_restore_settings(); return (STAT_PROBE_CYCLE_FAILED); }
static stat_t _homing_error_exit(int8_t axis, stat_t status) { // Generate the warning message. Since the error exit returns via the homing callback // - and not the main controller - it requires its own display processing nv_reset_nv_list(); if (axis == -2) { nv_add_conditional_message((const char_t *)"Homing error - Bad or no axis(es) specified");; } else { char message[NV_MESSAGE_LEN]; sprintf_P(message, PSTR("Homing error - %c axis settings misconfigured"), cm_get_axis_char(axis)); nv_add_conditional_message((char_t *)message); } nv_print_list(STAT_HOMING_CYCLE_FAILED, TEXT_INLINE_VALUES, JSON_RESPONSE_FORMAT); _homing_finalize_exit(axis); return (STAT_HOMING_CYCLE_FAILED); // homing state remains HOMING_NOT_HOMED }
static stat_t _json_parser_kernal(char *str) { stat_t status; int8_t depth; nvObj_t *nv = nv_reset_nv_list(); // get a fresh nvObj list char group[GROUP_LEN+1] = {""}; // group identifier - starts as NUL int8_t i = NV_BODY_LEN; ritorno(_normalize_json_string(str, JSON_OUTPUT_STRING_MAX)); // return if error // parse the JSON command into the nv body do { if (--i == 0) { return (STAT_JSON_TOO_MANY_PAIRS); } // length error // if ((status = _get_nv_pair_strict(nv, &str, &depth)) > STAT_EAGAIN) { // erred out if ((status = _get_nv_pair(nv, &str, &depth)) > STAT_EAGAIN) { // erred out return (status); } // propagate the group from previous NV pair (if relevant) if (group[0] != NUL) { strncpy(nv->group, group, GROUP_LEN); // copy the parent's group to this child } // validate the token and get the index if ((nv->index = nv_get_index(nv->group, nv->token)) == NO_MATCH) { nv->valuetype = TYPE_NULL; return (STAT_UNRECOGNIZED_NAME); } if ((nv_index_is_group(nv->index)) && (nv_group_is_prefixed(nv->token))) { strncpy(group, nv->token, GROUP_LEN); // record the group ID } if ((nv = nv->nx) == NULL) return (STAT_JSON_TOO_MANY_PAIRS);// Not supposed to encounter a NULL } while (status != STAT_OK); // breaks when parsing is complete // execute the command nv = nv_body; if (nv->valuetype == TYPE_NULL){ // means GET the value ritorno(nv_get(nv)); // ritorno returns w/status on any errors } else { cm_parse_clear(*nv->stringp); // parse Gcode and clear alarms if M30 or M2 is found ritorno(cm_is_alarmed()); // return error status if in alarm, shutdown or panic ritorno(nv_set(nv)); // set value or call a function (e.g. gcode) nv_persist(nv); } return (STAT_OK); // only successful commands exit through this point }
/****************************************************************************** * text_parser() - update a config setting from a text block (text mode) * _text_parser_kernal() - helper for above * * Use cases handled: * - $xfr=1200 set a parameter (strict separators)) * - $xfr 1200 set a parameter (relaxed separators) * - $xfr display a parameter * - $x display a group * - ? generate a status report (multiline format) */ stat_t text_parser(char_t *str) { nvObj_t *nv = nv_reset_nv_list(); // returns first object in the body stat_t status = STAT_OK; // trap special displays if (str[0] == '?') { // handle status report case sr_run_text_status_report(); return (STAT_OK); } if (str[0] == 'H') { // print help screens help_general((nvObj_t *)NULL); return (STAT_OK); } // pre-process the command if ((str[0] == '$') && (str[1] == NUL)) { // treat a lone $ as a sys request strcat(str,"sys"); } // parse and execute the command (only processes 1 command per line) ritorno(_text_parser_kernal(str, nv)); // run the parser to decode the command if ((nv->valuetype == TYPE_NULL) || (nv->valuetype == TYPE_PARENT)) { if (nv_get(nv) == STAT_COMPLETE){ // populate value, group values, or run uber-group displays return (STAT_OK); // return for uber-group displays so they don't print twice } } else { // process SET and RUN commands if (cm.machine_state == MACHINE_ALARM) return (STAT_MACHINE_ALARMED); status = nv_set(nv); // set (or run) single value if (status == STAT_OK) { nv_persist(nv); // conditionally persist depending on flags in array } } nv_print_list(status, TEXT_MULTILINE_FORMATTED, JSON_RESPONSE_FORMAT); // print the results return (status); }
void json_print_response(uint8_t status) { #ifdef __SILENCE_JSON_RESPONSES return; #endif if (js.json_verbosity == JV_SILENT) { // silent means no responses return; } if (js.json_verbosity == JV_EXCEPTIONS) { // cutout for JV_EXCEPTIONS mode if (status == STAT_OK) { if (cm.machine_state != MACHINE_INITIALIZING) { // always do full echo during startup return; } } } // Body processing nvObj_t *nv = nv_body; if (status == STAT_JSON_SYNTAX_ERROR) { nv_reset_nv_list(); nv_add_string((const char *)"err", escape_string(cs.bufp, cs.saved_buf)); } else if (cm.machine_state != MACHINE_INITIALIZING) { // always do full echo during startup uint8_t nv_type; do { if ((nv_type = nv_get_type(nv)) == NV_TYPE_NULL) break; if (nv_type == NV_TYPE_GCODE) { if (js.echo_json_gcode_block == false) { // kill command echo if not enabled nv->valuetype = TYPE_EMPTY; } //++++ } else if (nv_type == NV_TYPE_CONFIG) { // kill config echo if not enabled //fix me if (js.echo_json_configs == false) { // nv->valuetype = TYPE_EMPTY; // } } else if (nv_type == NV_TYPE_MESSAGE) { // kill message echo if not enabled if (js.echo_json_messages == false) { nv->valuetype = TYPE_EMPTY; } } else if (nv_type == NV_TYPE_LINENUM) { // kill line number echo if not enabled if ((js.echo_json_linenum == false) || (fp_ZERO(nv->value))) { // do not report line# 0 nv->valuetype = TYPE_EMPTY; } } } while ((nv = nv->nx) != NULL); } // Footer processing while(nv->valuetype != TYPE_EMPTY) { // find a free nvObj at end of the list... if ((nv = nv->nx) == NULL) { // oops! No free nvObj! rpt_exception(STAT_JSON_TOO_LONG, "json_print"); // report this as an exception return; } } char footer_string[NV_FOOTER_LEN]; // in xio.cpp:xio.readline the CR||LF read from the host is not appended to the string. // to ensure that the correct number of bytes are reported back to the host we add a +1 to // cs.linelen so that the number of bytes received matches the number of bytes reported sprintf((char *)footer_string, "%d,%d,%d", 1, status, cs.linelen + 1); cs.linelen = 0; // reset linelen so it's only reported once // if (xio.enable_window_mode) { // 2 footer styles are supported... // sprintf((char *)footer_string, "%d,%d,%d", 2, status, xio_get_window_slots()); //...windowing // } else { // sprintf((char *)footer_string, "%d,%d,%d", 1, status, cs.linelen); //...streaming // cs.linelen = 0; // reset linelen so it's only reported once // } nv_copy_string(nv, footer_string); // link string to nv object nv->depth = 0; // footer 'f' is a peer to response 'r' (hard wired to 0) nv->valuetype = TYPE_ARRAY; // declare it as an array strcpy(nv->token, "f"); // set it to Footer nv->nx = NULL; // terminate the list // serialize the JSON response and print it if there were no errors if (json_serialize(nv_header, cs.out_buf, sizeof(cs.out_buf)) >= 0) { fprintf(stderr, "%s", cs.out_buf); } }
/************************************************************************************ * config_init() - called once on hard reset * * Performs one of 2 actions: * (1) if persistence is set up or out-of-rev load RAM and NVM with settings.h defaults * (2) if persistence is set up and at current config version use NVM data for config * * You can assume the cfg struct has been zeroed by a hard reset. * Do not clear it as the version and build numbers have already been set by tg_init() * * NOTE: Config assertions are handled from the controller */ void config_init() { nvObj_t *nv = nv_reset_nv_list(); char *P_str_axis[3] = {"x","y", "z"}; config_init_assertions(); #ifdef __ARM // ++++ The following code is offered until persistence is implemented. // ++++ Then you can use the AVR code (or something like it) cfg.comm_mode = JSON_MODE; // initial value until EEPROM is read _set_defa(nv); #endif #ifdef __AVR cm_set_units_mode(MILLIMETERS); // must do inits in millimeter mode nv->index = 0; // this will read the first record in NVM read_persistent_value(nv); if (nv->value != cs.fw_build) { // case (1) NVM is not setup or not in revision // if (fp_NE(nv->value, cs.fw_build)) { _set_defa(nv); } else { // case (2) NVM is setup and in revision rpt_print_loading_configs_message(); for (nv->index=0; nv_index_is_single(nv->index); nv->index++) { if (GET_TABLE_BYTE(flags) & F_INITIALIZE) { strncpy_P(nv->token, cfgArray[nv->index].token, TOKEN_LEN); // read the token from the array read_persistent_value(nv); nv_set(nv); } } sr_init_status_report(); } #endif #ifdef __RX // ++++ The following code is offered until persistence is implemented. // ++++ Then you can use the AVR code (or something like it) cm_set_units_mode(MILLIMETERS); // must do inits in millimeter mode nv->index = 0; // this will read the first record in NVM spiffs_DIR sf_dir; struct spiffs_dirent e; struct spiffs_dirent *pe = &e; spiffs_file *fd = &uspiffs[0].f; spiffs *fs = &uspiffs[0].gSPIFFS; R_FlashDataAreaAccess(0xFFFF,0xFFFF); checkifParFlashed = (char *)(0x00100000); if (SPIFFS_opendir(fs, "/", &sf_dir) == NULL) { } pe = SPIFFS_readdir(&sf_dir, pe); *fd = SPIFFS_open(fs, "config.met", SPIFFS_RDWR | SPIFFS_DIRECT, 0); SPIFFS_close(fs, *fd); if (*fd == SPIFFS_ERR_NOT_FOUND && strcmp(checkifParFlashed,checkParPhrase)) { // case (1) NVM is not setup or not in revision *fd = SPIFFS_open(fs, "config.met", SPIFFS_CREAT | SPIFFS_RDWR | SPIFFS_DIRECT, 0); SPIFFS_close(fs, *fd); R_FlashEraseRange(0x00100000,0x20); R_FlashWrite(0x00100000,(uint32_t)checkParPhrase, 0x20); _set_defa(nv); } else { // case (2) NVM is setup and in revision rpt_print_loading_configs_message(); for (nv->index=0; nv_index_is_single(nv->index); nv->index++) { if (GET_TABLE_BYTE(flags) & F_INITIALIZE) { strncpy_P(nv->token, cfgArray[nv->index].token, TOKEN_LEN); // read the token from the array read_persistent_value(nv); nv_set(nv); } } sr_init_status_report(); } z_step_pulse = (M1_TRAVEL_PER_REV*M1_STEP_ANGLE)/(360*M1_MICROSTEPS); #endif }