LOCAL char * ICACHE_FLASH_ATTR readUIntField(struct jsonparse_state *jparser, ALLOWED_FIELDS field, uint32_t *out, ALLOWED_FIELDS fields, ALLOWED_FIELDS *readedfields, unsigned int x) { if((fields & field) == 0) return UNEXPECTED; int value; jsonparse_next(jparser); if(jsonparse_next(jparser) != JSON_TYPE_ERROR) { if(x && jparser->vlen == 1 && jparser->json[jparser->vstart] == 'x' && (field & AF_CS)) { *out = x; *readedfields |= field; return 0; } const int res = strToUInt(&jparser->json[jparser->vstart], &value); if(!res) return NONINTEGER; *out = value; *readedfields |= field; } return 0; }
char * ICACHE_FLASH_ATTR parse_params_pins_set(const char *params, unsigned int paramslen, gpio_command_params *out, unsigned int all, unsigned int timeout, ALLOWED_FIELDS fields, ALLOWED_FIELDS *readedfields) { struct jsonparse_state jparser; if(paramslen) jsonparse_setup(&jparser, params, paramslen); else if(fields) return "No parameters specified"; int type; int pinnum; unsigned int pins_found = 0; unsigned int pinmask; *readedfields = 0; load_defaults(out, timeout); while (jparser.pos < jparser.len) { type = jsonparse_next(&jparser); if (type == JSON_TYPE_PAIR_NAME) { if(strcmp_value(&jparser, "mode") == 0) { if((fields & AF_UARTMODE) == 0 && (fields & AF_SPIMODE) == 0) return UNEXPECTED; jsonparse_next(&jparser); if(jsonparse_next(&jparser) != JSON_TYPE_ERROR) { int val; if(strcmp_value(&jparser, "disable") == 0 && (fields & AF_UARTMODE)) { *readedfields |= AF_UARTMODE; out->uart_speed = 0; continue; } int res = strToUInt(&jparser.json[jparser.vstart], &val); if(!res) return "Wrong mode integer value"; if(fields & AF_UARTMODE) { *readedfields |= AF_UARTMODE; out->uart_speed = val; if(res < jparser.vlen && jparser.json[jparser.vstart + res] == ' ') { while(res < jparser.vlen && jparser.json[jparser.vstart + res] == ' ') res++; if(res + 3 == jparser.vlen) { const unsigned char b = jparser.json[jparser.vstart + res] - '0'; const unsigned char p = jparser.json[jparser.vstart + res + 1]; const unsigned char s = jparser.json[jparser.vstart + res + 2] - '0'; if(b < 10 && s < 10) { out->uart_bits = b; out->uart_partity = p; out->uart_stopbits = s; } else { return "Wrong mode framing"; } } } } if(fields & AF_SPIMODE) { *readedfields |= AF_SPIMODE; out->spi_mode = val; } } continue; } else if(strcmp_value(&jparser, "count") == 0) { char * res = readUIntField(&jparser, AF_COUNT, &out->count, fields, readedfields, 0); if(res) return res; continue; } else if(strcmp_value(&jparser, "timeout") == 0) { char * res = readUIntField(&jparser, AF_TIMEOUT, &out->timeout, fields, readedfields, 0); if(res) return res; continue; } else if(strcmp_value(&jparser, "frequency") == 0) { if((fields & AF_PERIOD) == 0) return UNEXPECTED; float frequncy; jsonparse_next(&jparser); if(jsonparse_next(&jparser) != JSON_TYPE_ERROR) { const int res = strToFloat(&jparser.json[jparser.vstart], &frequncy); if(!res) return "Wrong frequency float value"; if(frequncy < 0.000499999f) out->periodus = 2000004000; else out->periodus = 1000000.0f / frequncy; *readedfields |= AF_PERIOD; } continue; } else if(strcmp_value(&jparser, "address") == 0) { if((fields & AF_ADDRESS) == 0) return UNEXPECTED; jsonparse_next(&jparser); if(jsonparse_next(&jparser) != JSON_TYPE_ERROR) { char c; int p; if(jparser.json[jparser.vstart] == '0' && jparser.json[jparser.vstart + 1] == 'x') p = 2; else p = 0; const int res = hexToByte(&jparser.json[jparser.vstart + p], &c); if(res != (jparser.vlen - p)) return "Address is wrong"; out->address = c; *readedfields |= AF_ADDRESS; } continue; } else if(strcmp_value(&jparser, "SDA") == 0) { char * res = readUIntField(&jparser, AF_SDA, &out->SDA, fields, readedfields, 0); if(res) return res; continue; } else if(strcmp_value(&jparser, "SCL") == 0) { char * res = readUIntField(&jparser, AF_SCL, &out->SCL, fields, readedfields, 0); if(res) return res; continue; } else if(strcmp_value(&jparser, "CS") == 0) { char * res = readUIntField(&jparser, AF_CS, &out->CS, fields, readedfields, ~(uint32_t)0U); if(res) return res; continue; } else if(strcmp_value(&jparser, "pin") == 0) { char * res = readUIntField(&jparser, AF_PIN, &out->pin, fields, readedfields, 0); if(res) return res; continue; } else if(strcmp_value(&jparser, "data") == 0) { if((fields & AF_DATA) == 0 || out->data_len) return UNEXPECTED; jsonparse_next(&jparser); if(jsonparse_next(&jparser) != JSON_TYPE_ERROR) { out->data_len = dhdata_decode(&jparser.json[jparser.vstart], jparser.vlen, out->data, sizeof(out->data)); if(out->data_len == 0) return "Data is broken"; *readedfields |= AF_DATA; } continue; } else if(strcmp_value(&jparser, "text") == 0) { if((fields & AF_TEXT_DATA) == 0 || out->data_len) return UNEXPECTED; jsonparse_next(&jparser); if(jsonparse_next(&jparser) != JSON_TYPE_ERROR) { if (jparser.vlen > sizeof(out->data) - 1) return "Text is too long"; os_memcpy(out->data, &jparser.json[jparser.vstart], jparser.vlen); out->data[jparser.vlen] = 0; out->data_len = jparser.vlen; *readedfields |= AF_TEXT_DATA; } continue; } else if(strcmp_value(&jparser, "all") == 0) { if(pins_found) return "Wrong argument"; pins_found = ~(unsigned int)0; pinmask = all; pinnum = -1; } else { const int res = strToUInt(&jparser.json[jparser.vstart], &pinnum); if(!res || pinnum < 0 || pinnum > DHGPIO_MAXGPIONUM || (pins_found & (1 << pinnum))) return "Wrong argument"; pins_found |= (1 << pinnum); pinmask = (1 << pinnum); } jsonparse_next(&jparser); if(jsonparse_next(&jparser) != JSON_TYPE_ERROR) { if(strcmp_value(&jparser, "x") == 0) continue; else if(strcmp_value(&jparser, "init") == 0) { if((fields & AF_INIT) == 0) return UNEXPECTED; out->pins_to_init |= pinmask; *readedfields |= AF_INIT; } else if(strcmp_value(&jparser, "pullup") == 0) { if((fields & AF_PULLUP) == 0) return UNEXPECTED; out->pins_to_pullup |= pinmask; *readedfields |= AF_PULLUP; } else if(strcmp_value(&jparser, "nopull") == 0) { if((fields & AF_NOPULLUP) == 0) return UNEXPECTED; out->pins_to_nopull |= pinmask; *readedfields |= AF_NOPULLUP; } else if(strcmp_value(&jparser, "disable") == 0) { if((fields & AF_VALUES) == 0 && (fields & AF_DISABLE) == 0) { return UNEXPECTED; } if (fields & AF_VALUES) { int i; if(pinnum > 0 ) out->pin_value[pinnum] = 0; else for(i = 0; i <= DHGPIO_MAXGPIONUM; i++) out->pin_value[i] = 0; out->pin_value_readed |= pinmask; *readedfields |= AF_VALUES; } if(fields & AF_DISABLE) { out->pins_to_disable |= pinmask; *readedfields |= AF_DISABLE; } } else if(strcmp_value(&jparser, "rising") == 0) { if((fields & AF_RISING)== 0) return UNEXPECTED; out->pins_to_rising |= pinmask; *readedfields |= AF_RISING; } else if(strcmp_value(&jparser, "falling") == 0) { if((fields & AF_FALLING) == 0) return UNEXPECTED; out->pins_to_falling |= pinmask; *readedfields |= AF_FALLING; } else if(strcmp_value(&jparser, "both") == 0) { if((fields & AF_BOTH) == 0) return UNEXPECTED; out->pins_to_both |= pinmask; *readedfields |= AF_BOTH; } else if(strcmp_value(&jparser, "read") == 0) { if((fields & AF_READ) == 0) return UNEXPECTED; out->pins_to_read |= pinmask; *readedfields |= AF_READ; } else if(strcmp_value(&jparser, "presence") == 0) { if((fields & AF_PRESENCE) == 0) return UNEXPECTED; out->pins_to_presence |= pinmask; *readedfields |= AF_PRESENCE; } else if((fields & AF_VALUES)) { // BE CAREFULL, all digits values have to be under this if int value, i; if(!strToUInt(&jparser.json[jparser.vstart], &value)) return NONINTEGER; if(pinnum > 0 ) out->pin_value[pinnum] = value; else for(i = 0; i <= DHGPIO_MAXGPIONUM; i++) out->pin_value[i] = value; out->pin_value_readed |= pinmask; *readedfields |= AF_VALUES; if(value == 1 && (fields & AF_SET)) { out->pins_to_set |= pinmask; *readedfields |= AF_SET; } else if(value == 0 && (fields & AF_CLEAR)) { out->pins_to_clear |= pinmask; *readedfields |= AF_CLEAR; } } else if(strcmp_value(&jparser, "1") == 0) { if((fields & AF_SET) == 0) return UNEXPECTED; out->pins_to_set |= pinmask; *readedfields |= AF_SET; } else if(strcmp_value(&jparser, "0") == 0) { if((fields & AF_CLEAR) == 0) return UNEXPECTED; out->pins_to_clear |= pinmask; *readedfields |= AF_CLEAR; } else { return "Unsupported action"; } } } else if(type == JSON_TYPE_ERROR) { return "Broken json"; } } return NULL; }
LOCAL void ICACHE_FLASH_ATTR receive_post(const char *data, unsigned short len, char * internal, unsigned int internalsize) { const unsigned int POST_BUF_SIZE = 2048; const char content_length[] = "Content-Length:"; const char sp[] = "\r\n\r\n"; if(mPostBuf == 0) { mPostBuf = (char*)os_malloc(POST_BUF_SIZE); if(mPostBuf == 0) { check_send_res(espconn_send(mCurrentPost, internal, internalsize)); mCurrentPost = 0; return; } } if(len > POST_BUF_SIZE - mPostBufPos) { check_send_res(espconn_send(mCurrentPost, internal, internalsize)); mCurrentPost = 0; return; } os_memcpy(&mPostBuf[mPostBufPos], data, len); mPostBufPos += len; const int to = (int)mPostBufPos - sizeof(content_length) + 1; int i; unsigned int cont_len; for(i = 0; i < to; i++) { if(os_strncmp(&mPostBuf[i], content_length, sizeof(content_length) - 1) == 0) { i += sizeof(content_length) - 1; while(mPostBuf[i] == ' ') i++; if(strToUInt(&mPostBuf[i], &cont_len)) { for(; i < mPostBufPos; i++) { if(os_strncmp(&mPostBuf[i], sp, sizeof(sp) - 1) == 0) { i += sizeof(sp) - 1; if(cont_len <= mPostBufPos - i) { dhdebug("POST len %u/%u", cont_len, mPostBufPos - i); char *res = dhap_post_parse(&mPostBuf[i], mPostBufPos - i); unsigned int rlen; if(res) { res = dhap_pages_error(res, &rlen); } else { if(dhsettings_commit() == 0) { res = internal; rlen = internalsize; } else { res = dhap_pages_ok(&rlen); if(res == 0) { dhdebug("Generate OK page fail"); res = internal; rlen = internalsize; } else { dhdebug("Configuration was written. Will be rebooted in %d ms", RECONFIGURE_DELAY_MS); os_timer_disarm(&mReconfigureTimer); os_timer_setfn(&mReconfigureTimer, (os_timer_func_t *)system_reconfigure, NULL); os_timer_arm(&mReconfigureTimer, RECONFIGURE_DELAY_MS, 0); mConfigured = 1; } } } dhdebug("Parse post, send result %u bytes", rlen); check_send_res(espconn_send(mCurrentPost, res, rlen)); mCurrentPost = 0; } return; } } } return; } } }