static int8_t on_request(int8_t cid, int8_t routeid, GSwifi::GSREQUESTSTATE state) { if ( (state == GSwifi::GSREQUESTSTATE_RECEIVED) && (! gs.validRequest()) && (! has_valid_pass) ) { HTTPLOG_PRINTLN("!E32"); gs.writeHead(cid, 400); gs.writeEnd(); ring_put( &commands, COMMAND_CLOSE ); ring_put( &commands, cid ); return -1; } switch (routeid) { case 0: // POST /messages return on_post_messages_request(cid, state); case 1: // POST /keys // when client requests for a new key, // we request server for one, and respond to client with the result from server return on_post_keys_request(cid, state); case 2: // GET /messages return on_get_messages_request(cid, state); case 3: // POST /wifi return on_post_wifi_request(cid, state); default: break; } return -1; }
static int8_t on_post_wifi_request(uint8_t cid, GSwifi::GSREQUESTSTATE state) { if (state == GSwifi::GSREQUESTSTATE_BODY_START) { keys.clear(); return 0; } while (! gs.bufferEmpty()) { char letter = gs.bufferGet(); keys.put( letter ); } if (state == GSwifi::GSREQUESTSTATE_RECEIVED) { int8_t result = keys.putDone(); if (result != 0) { keys.clear(); gs.writeHead(cid, 400); } else { keys.dump(); keys.save(); gs.writeHead(cid, 200); } gs.writeEnd(); ring_put( &commands, COMMAND_CLOSE ); ring_put( &commands, cid ); if (result == 0) { ring_put( &commands, COMMAND_SETREGDOMAIN ); ring_put( &commands, keys.regdomain ); ring_put( &commands, COMMAND_CONNECT ); } } }
// added by eqiglii 2015-12-13 int8_t irkit_httpclient_post_temperature_(uint8_t temperature) { // send http post request to LAN server char path[82]; sprintf(path, P("/proxy.php?url=https://irkitrestapi.appspot.com/_ah/api/southbound/v1/temperature?")); // added "?" by eqiglii 2016-06-13 char body[POST_TEMPERATURE_BODY_LENGTH+1+4]; // +4, due to change the two "&" to "%26", eqiglii, 2016-06-13 // char array[6]; // dtostrf(temperature,5, 2, array); // this function works, but takes too much memory KB // I know that the Arduino version of sprinf does not support floats, but we're sticking to INTs here so it is fine sprintf(body, "irkit_id=%s%ssignal_content=%2d%ssignal_name=%s", gs.hostname(),"%26", temperature,"%26", "temp"); // change the two "&" to "%26", eqiglii 2016-06-13 int8_t cid = gs.post(path, body, POST_TEMPERATURE_BODY_LENGTH, &on_post_messages_response,50 ); //int8_t cid = gs.post("/_ah/api/southbound/v1/temperature?", body, POST_TEMPERATURE_BODY_LENGTH, &on_post_messages_response,50 ); // this never worked out!!! eqiglii 2016-06-14, don't try any more!!! if (cid == polling_cid) { // we're polling on this cid, and our response handler is registered with this cid. // we already overwritten the response handler, so restart everything. // HTTPLOG_PRINTLN("!E30"); wifi_hardware_reset(); return -1; } return cid; }
static int8_t on_get_messages_response(int8_t cid, uint16_t status_code, GSwifi::GSREQUESTSTATE state) { HTTPLOG_PRINT(P("< G /m ")); HTTPLOG_PRINTLN(status_code); if (status_code != 200) { gs.bufferClear(); } switch (status_code) { case 200: while (! gs.bufferEmpty()) { char letter = gs.bufferGet(); parse_json( letter ); } if (state == GSwifi::GSREQUESTSTATE_RECEIVED) { // should not be WRITING here, should be XMITTING or IDLE (xmit finished) if (IrCtrl.state == IR_WRITING) { // prevent from locking in WRITING state forever IR_state( IR_IDLE ); } ring_put( &commands, COMMAND_CLOSE ); ring_put( &commands, cid ); if ((polling_cid == cid) || (polling_cid == CID_UNDEFINED)) { polling_cid = CID_UNDEFINED; ring_put( &commands, COMMAND_START_POLLING ); } // if polling_cid != cid // there's already an ongoing polling request, so request again when that one finishes } break; case HTTP_STATUSCODE_CLIENT_TIMEOUT: polling_cid = CID_UNDEFINED; ring_put( &commands, COMMAND_CLOSE ); ring_put( &commands, cid ); irkit_httpclient_start_polling( 5 ); break; case HTTP_STATUSCODE_DISCONNECT: polling_cid = CID_UNDEFINED; irkit_httpclient_start_polling( 5 ); break; // heroku responds with 503 if longer than 30sec, // or when deploy occurs case 503: default: if (state == GSwifi::GSREQUESTSTATE_RECEIVED) { ring_put( &commands, COMMAND_CLOSE ); ring_put( &commands, cid ); irkit_httpclient_start_polling( 5 ); } break; } return 0; }
int8_t irkit_httpclient_post_door() { #ifdef USE_INTERNET // devicekey=[0-9A-F]{32}&hostname=IRKit%%%% char body[POST_DOOR_BODY_LENGTH+1]; sprintf(body, "devicekey=%s&hostname=%s", keys.getKey(), gs.hostname()); return gs.post( "/d", body, POST_DOOR_BODY_LENGTH, &on_post_door_response, 50 ); #else on_post_door_response(CID_UNDEFINED, 200, GSwifi::GSREQUESTSTATE_RECEIVED); #endif }
int8_t irkit_httpclient_post_door() { // devicekey=[0-9A-F]{32}&hostname=IRKit%%%% // send http post request to LAN server char path[75]; sprintf(path, P("/proxy.php?url=https://irkitrestapi.appspot.com/_ah/api/southbound/v1/door?")); // path must end up with "?", by eqiglii 2016-06-13 char body[POST_DOOR_BODY_LENGTH+1+2]; // +2, due to change from "&" to "%26", eqiglii, 2016-06-13 sprintf(body, "devicekey=%s%shostname=%s", keys.getKey(),"%26",gs.hostname()); // in http url encoding, "&" must be replaced by "%26", by eqiglii 2016-06-13 Serial.println (body); // print log, added by eqiglii //return gs.post( "/d", body, POST_DOOR_BODY_LENGTH, &on_post_door_response, 50 ); //return gs.post( "/_ah/api/southbound/v1/door?", body, POST_DOOR_BODY_LENGTH, &on_post_door_response, 50 ); return gs.post(path, body, POST_DOOR_BODY_LENGTH, &on_post_door_response, 50 ); }
int8_t irkit_httpclient_post_keys() { // devicekey=[0-9A-F]{32} char body[POST_KEYS_BODY_LENGTH+1]; sprintf(body, "devicekey=%s", keys.getKey()); int8_t result = gs.post( "/k", body, POST_KEYS_BODY_LENGTH, &on_post_keys_response, 10 ); if ( result < 0 ) { gs.writeHead( post_keys_cid, 500 ); gs.writeEnd(); ring_put( &commands, COMMAND_CLOSE ); ring_put( &commands, post_keys_cid ); } }
int8_t irkit_httpclient_get_messages() { // /m?devicekey=C7363FDA0F06406AB11C29BA41272AE3&newer_than=4294967295 //char path[68]; //sprintf(path, P("/m?devicekey=%s&newer_than=%ld"), keys.getKey(), newest_message_id); char path[109]; // added 29 chars path,12 chars messageid sprintf(path, P("/_ah/api/southbound/v1/messages?devicekey=%s&newer_than=%ld"), keys.getKey(), newest_message_id); return gs.get(path, &on_get_messages_response, 50); }
int8_t irkit_httpclient_post_messages() { // post body is IR data, move devicekey parameter to query, for implementation simplicity // /p?devicekey=C7363FDA0F06406AB11C29BA41272AE3&freq=38 char path[54]; sprintf(path, P("/p?devicekey=%s&freq=%d"), keys.getKey(), IrCtrl.freq); return gs.postBinary( path, (const char*)sharedbuffer, IR_packedlength(), &on_post_messages_response, 10 ); }
static int8_t on_post_messages_request(int8_t cid, GSwifi::GSREQUESTSTATE state) { while (! gs.bufferEmpty()) { char letter = gs.bufferGet(); parse_json( letter ); } if (state == GSwifi::GSREQUESTSTATE_RECEIVED) { // should be xmitting or idle (xmit finished) if (IrCtrl.state == IR_WRITING) { HTTPLOG_PRINTLN("!E7"); // invalid json gs.writeHead(cid, 400); gs.writeEnd(); } else { gs.writeHead(cid, 200); gs.writeEnd(); } ring_put( &commands, COMMAND_CLOSE ); ring_put( &commands, cid ); #ifdef USE_INTERNET TIMER_START( suspend_polling_timer, SUSPEND_GET_MESSAGES_INTERVAL ); #endif } return 0; }
static int8_t on_post_door_response(int8_t cid, uint16_t status_code, GSwifi::GSREQUESTSTATE state) { HTTPLOG_PRINT(P("< P /d ")); HTTPLOG_PRINTLN(status_code); gs.bufferClear(); if (state != GSwifi::GSREQUESTSTATE_RECEIVED) { return 0; } switch (status_code) { case 200: keys.setKeyValid(true); // save only independent area, since sharedbuffer might be populated by IR or so. keys.save2(); IR_state( IR_IDLE ); ring_put( &commands, COMMAND_CLOSE ); ring_put( &commands, cid ); #ifdef USE_INTERNET ring_put( &commands, COMMAND_START_POLLING ); #endif on_irkit_ready(); break; #ifdef USE_INTERNET case 401: case HTTP_STATUSCODE_CLIENT_TIMEOUT: // keys have expired, we have to start listening for POST /wifi again keys.clear(); keys.save(); software_reset(); break; case 400: // must be program bug, happens when there's no hostname parameter case 408: case 503: // heroku responds with 503 if longer than 30sec default: // retry again on next loop ring_put( &commands, COMMAND_CLOSE ); ring_put( &commands, cid ); ring_put( &commands, COMMAND_POST_DOOR ); break; #endif } return 0; }
static int8_t on_get_messages_request(int8_t cid, GSwifi::GSREQUESTSTATE state) { if (state != GSwifi::GSREQUESTSTATE_RECEIVED) { return -1; } gs.writeHead(cid, 200); if ( (IrCtrl.len <= 0) || (IrCtrl.state != IR_RECVED_IDLE) ) { // if no data gs.writeEnd(); ring_put( &commands, COMMAND_CLOSE ); ring_put( &commands, cid ); return 0; } IR_state( IR_READING ); gs.write("{\"format\":\"raw\",\"freq\":"); // format fixed to "raw" for now gs.write(IrCtrl.freq); gs.write(",\"data\":["); for (uint16_t i=0; i<IrCtrl.len; i++) { gs.write( IR_get() ); if (i != IrCtrl.len - 1) { gs.write(","); } } gs.write("]}"); gs.writeEnd(); ring_put( &commands, COMMAND_CLOSE ); ring_put( &commands, cid ); IR_state( IR_IDLE ); #ifdef USE_INTERNET TIMER_START( suspend_polling_timer, SUSPEND_GET_MESSAGES_INTERVAL ); #endif return 0; }
static int8_t on_post_messages_response(int8_t cid, uint16_t status_code, GSwifi::GSREQUESTSTATE state) { HTTPLOG_PRINT(P("< P /m ")); HTTPLOG_PRINTLN(status_code); if (status_code != 200) { gs.bufferClear(); } if (state != GSwifi::GSREQUESTSTATE_RECEIVED) { return 0; } ring_put( &commands, COMMAND_CLOSE ); ring_put( &commands, cid ); return 0; }
int8_t irkit_httpclient_post_messages_() { // post body is IR data, move devicekey parameter to query, for implementation simplicity // /p?devicekey=C7363FDA0F06406AB11C29BA41272AE3&freq=38 char path[54]; sprintf(path, P("/p?devicekey=%s&freq=%d"), keys.getKey(), IrCtrl.freq); int8_t cid = gs.postBinary( path, (const char*)sharedbuffer, IR_packedlength(), &on_post_messages_response, 10 ); if (cid == polling_cid) { // we're polling on this cid, and our response handler is registered with this cid. // we already overwritten the response handler, so restart everything. // HTTPLOG_PRINTLN("!E30"); wifi_hardware_reset(); return -1; } return cid; }
void irkit_httpserver_register_handler() { gs.clearRoutes(); // 0 gs.registerRoute( GSwifi::GSMETHOD_POST, P("/messages") ); // 1 gs.registerRoute( GSwifi::GSMETHOD_POST, P("/keys") ); // 2 gs.registerRoute( GSwifi::GSMETHOD_GET, P("/messages") ); // 3 gs.registerRoute( GSwifi::GSMETHOD_POST, P("/wifi") ); gs.setRequestHandler( &on_request ); }
static void on_json_data( uint8_t key, uint32_t value, char *pass ) { if ( IrCtrl.state != IR_WRITING ) { return; } switch (key) { case IrJsonParserDataKeyId: newest_message_id = value; break; case IrJsonParserDataKeyFreq: IrCtrl.freq = value; break; case IrJsonParserDataKeyData: IR_put( value ); break; case IrJsonParserDataKeyPass: if (strncmp(pass, gs.password(), 10) == 0) { has_valid_pass = true; } default: break; } }
static int8_t on_post_keys_response(int8_t cid, uint16_t status_code, GSwifi::GSREQUESTSTATE state) { HTTPLOG_PRINT(P("< P /k ")); HTTPLOG_PRINTLN(status_code); if (status_code != 200) { gs.bufferClear(); } if (state != GSwifi::GSREQUESTSTATE_RECEIVED) { return 0; } gs.writeHead( post_keys_cid, status_code ); switch (status_code) { case 200: while (! gs.bufferEmpty()) { char letter = gs.bufferGet(); gs.write( letter ); } gs.writeEnd(); break; default: gs.writeEnd(); break; } ring_put( &commands, COMMAND_CLOSE ); ring_put( &commands, cid ); ring_put( &commands, COMMAND_CLOSE ); if (ring_isfull( &commands )) { HTTPLOG_PRINTLN("!E8"); return -1; } ring_put( &commands, post_keys_cid ); return 0; }
int8_t irkit_httpclient_get_messages() { // /m?devicekey=C7363FDA0F06406AB11C29BA41272AE3&newer_than=4294967295 char path[70]; sprintf(path, P("/m?devicekey=%s&newer_than=%ld"), keys.getKey(), newest_message_id); return gs.get(path, &on_get_messages_response, 50); }
int8_t irkit_httpclient_post_door() { // devicekey=[0-9A-F]{32}&hostname=IRKit%%%% char body[POST_DOOR_BODY_LENGTH+1]; sprintf(body, "devicekey=%s&hostname=%s", keys.getKey(), gs.hostname()); return gs.post( "/d", body, POST_DOOR_BODY_LENGTH, &on_post_door_response, 50 ); }