int wifi_send_ip(void){ int TX_BUF_SIZE = LG_BUF_SIZE; int PAYLOAD_BUF_SIZE = LG_BUF_SIZE; int r; char *tx_buf,*payload_buf; tx_buf = core_malloc(TX_BUF_SIZE); payload_buf = core_malloc(PAYLOAD_BUF_SIZE); snprintf(payload_buf,PAYLOAD_BUF_SIZE, "{\"serial_number\":\"%s\",\"ip_addr\":\"%s\"}", wemo_config.serial_number,wemo_config.ip_addr); snprintf(tx_buf,TX_BUF_SIZE, "POST /config/plugs/update HTTP/1.1\r\n" "User-Agent: WemoPlug\r\n" "Host: NILM\r\nAccept:*/*\r\n" "Connection: keep-alive\r\n" "Content-Type: application/json\r\n" "Content-Length: %d\r\n" "\r\n%s", strlen(payload_buf),payload_buf); //send the packet! r = wifi_transmit(wemo_config.nilm_ip_addr,80,tx_buf); core_free(tx_buf); core_free(payload_buf); return r; }
int wifi_transmit(char *url, int port, char *data){ int BUF_SIZE = MD_BUF_SIZE; char *cmd; char *buf; int r; //allocate memory cmd = core_malloc(BUF_SIZE); buf = core_malloc(BUF_SIZE); //sometimes the port stays open, so check for both //conditions char *success_str = "4,CONNECT"; char *connected_str = "ALREAY CONNECT"; //sic //open a TCP connection on channel 4 snprintf(cmd,BUF_SIZE,"AT+CIPSTART=4,\"TCP\",\"%s\",%d", url,port); wifi_send_cmd(cmd,"4,CONNECT",buf,100,5); //check if we are able to connect to the NILM if(strstr(buf,"ERROR\r\nUnlink")==buf){ printf("can't connect to NILM\n"); core_free(cmd); core_free(buf); return TX_BAD_DEST_IP; } //if we are still connected, close and reopen socket if(strstr(buf,connected_str)==buf){ wifi_send_cmd("AT+CIPCLOSE=4","Unlink",buf,100,1); //now try again wifi_send_cmd(cmd,"Linked",buf,100,2); } //check for successful link if(strstr(buf,success_str)!=buf){ printf("error, setting up link\n"); core_free(cmd); core_free(buf); return TX_ERROR; } //send the data if((r=wifi_send_txt(4,data))!=0){ printf("error transmitting data: %d\n",data_tx_status); core_free(cmd); core_free(buf); return r; } //connection is closed *after* we receive the server's response //this is processed by the core and we discard the response //wifi_send_cmd("AT+CIPCLOSE=4","Unlink",buf,100,1); core_free(cmd); core_free(buf); return r; //success! }
//////////////////// //callback function void core_get_nilm_ip_addr_cb(char* data){ //find the IP address in the response //expect 4 octets enclosed by double brackets: [[x.x.x.]] int a1,a2,a3,a4; char *buf, *resp_data; int BUF_SIZE = MD_BUF_SIZE; buf = core_malloc(BUF_SIZE); resp_data = strrchr(data,'\n'); if(sscanf(resp_data,"\n<<%d.%d.%d.%d>>",&a1,&a2,&a3,&a4)!=4){ printf("error, bad address from manager\n"); core_free(buf); return; } //save the IP to our config snprintf(buf,BUF_SIZE,"%d.%d.%d.%d",a1,a2,a3,a4); memset(wemo_config.nilm_ip_addr,0x0,MAX_CONFIG_LEN); strcpy(wemo_config.nilm_ip_addr,buf); //save the new config fs_write_config(); //now send our IP to our NILM wifi_send_ip(); //free the memory core_free(buf); }
//*** Private method that actually sends data ***// int wifi_send_data(int ch, const uint8_t* data, int size){ int cmd_buf_size = MD_BUF_SIZE; char *cmd; int timeout = 7; //wait 7 seconds to transmit the data //allocate memory cmd = core_malloc(cmd_buf_size); snprintf(cmd,cmd_buf_size,"AT+CIPSEND=%d,%d\r\n",ch,size); data_tx_status=TX_PENDING; rx_wait=true; resp_buf_idx = 0; memset(resp_buf,0x0,RESP_BUF_SIZE); memset(wifi_rx_buf,0x0,WIFI_RX_BUF_SIZE); //to make debugging easier wifi_rx_buf_idx=0; usart_serial_write_packet(WIFI_UART,(uint8_t*)cmd,strlen(cmd)); delay_ms(250); //wait for module to be ready to accept data usart_serial_write_packet(WIFI_UART,(uint8_t*)data,size); //now wait for the data to be sent while(timeout>0){ //start the timer tc_start(TC0, 0); //when timer expires, return what we have in the buffer rx_wait=true; //reset the wait flag while(rx_wait && data_tx_status!=TX_SUCCESS); tc_stop(TC0,0); //the success flag is set *before* we receive the server's response //core_process_wifi_data receives the response but discards it if(data_tx_status==TX_SUCCESS){ data_tx_status=TX_IDLE; rx_wait = false; //free memory core_free(cmd); return TX_SUCCESS; } timeout--; } //check if this is a timeout error if(strlen((char*)resp_buf)==0){ printf("timeout error\n"); core_log("timeout error"); data_tx_status = TX_TIMEOUT; } //an error occured, see if it is due to a module reset else if(strcmp((char*)resp_buf,"\r\nready\r\n")==0){ //module reset itself!!! printf("detected module reset\n"); core_log("module reset"); data_tx_status = TX_ERR_MODULE_RESET; } else { data_tx_status=TX_ERROR; core_log("TX error:"); core_log((char*)resp_buf); data_tx_status = TX_ERROR; } //free memory core_free(cmd); return data_tx_status; }
static void* operator new(size_t size,const std::nothrow_t& )throw() { try { return core_malloc(size); } catch (std::exception &) { return NULL; } }
int mon_log(int argc, char **argv){ FIL fil; int line_buf_size = MD_BUF_SIZE; char *line_buf; FRESULT fr; if(argc!=2){ printf("specify [read] or [erase]\n"); return -1; } if(strcmp(argv[1],"read")==0){ //allocate the line buffer line_buf = core_malloc(line_buf_size); //print the log out to STDOUT fr = f_open(&fil, LOG_FILE, FA_READ); if(fr){ printf("error reading log: %d\n",(int)fr); core_free(line_buf); return -1; } while(f_gets(line_buf, line_buf_size, &fil)){ printf("%s",line_buf); } f_close(&fil); core_free(line_buf); return 0; } else if(strcmp(argv[1],"erase")==0){ fr = f_open(&fil, LOG_FILE, FA_WRITE); if(fr){ printf("error erasing log: %d\n", (int)fr); return -1; } f_lseek(&fil,0); f_truncate(&fil); f_close(&fil); if(wemo_config.echo) printf("erased log\n"); return 0; } else{ printf("specify [read] or [erase]\n"); return -1; } //shouldn't get here return 0; }
/////////////////// // core_get_nilm_ip_addr // Request the NILM IP address from the // manager, this allows us to operate in // DHCP environments because the manager URL // can be resolved by DNS to a static IP // void core_get_nilm_ip_addr(void){ int BUF_SIZE=MD_BUF_SIZE; char *buf; //allocate memory buf=core_malloc(BUF_SIZE); snprintf(buf,BUF_SIZE, "GET /nilms/get_ip?serial_number=%s HTTP/1.1\r\n" "User-Agent: WemoPlug\r\n" "Host: %s\r\n" "Accept:*/*\r\n\r\n", wemo_config.serial_number,wemo_config.mgr_url); wifi_transmit(wemo_config.mgr_url,80,buf); tx_callback = &core_get_nilm_ip_addr_cb; //free memory core_free(buf); }
int wifi_send_raw(int ch, const uint8_t* data, int size){ int BUFFER_SIZE=1000; int i=0; int r; char *tx_buf; tx_buf = core_malloc(MD_BUF_SIZE); for(i=0;i<size;i+=BUFFER_SIZE){ if(i+BUFFER_SIZE<size) r=wifi_send_data(ch,&data[i],BUFFER_SIZE); else r=wifi_send_data(ch,&data[i],size-i); if(r!=TX_SUCCESS){ //exit early core_free(tx_buf); return r; //fail! } } core_free(tx_buf); return r; }
void core_transmit_power_packet_http(power_pkt *wemo_pkt){ int r, i, j; int TX_BUF_SIZE = XL_BUF_SIZE; int PAYLOAD_BUF_SIZE = XL_BUF_SIZE; int DATA_BUF_SIZE = MD_BUF_SIZE; char *tx_buf, *payload_buf; char *bufs[7]; int32_t *srcs[7] = {wemo_pkt->vrms, wemo_pkt->irms, wemo_pkt->pavg, wemo_pkt->watts, wemo_pkt->pf, wemo_pkt->freq, wemo_pkt->kwh}; char *buf; int32_t *src; //make sure all the data is present if(wemo_pkt->status != POWER_PKT_READY){ printf("Error, packet is not ready to tx!\n"); return; } //now we are filling up the POST request wemo_pkt->status = POWER_PKT_TX_IN_PROG; //allocate memory for the POST request tx_buf = core_malloc(TX_BUF_SIZE); payload_buf = core_malloc(DATA_BUF_SIZE); //print out the data arrays as strings for(j=0;j<7;j++){ src = srcs[j]; buf = core_malloc(DATA_BUF_SIZE); bufs[j] = buf; for(i=0;i<PKT_SIZE;i++){ snprintf(buf+strlen(buf),DATA_BUF_SIZE,"%li",src[i]); if(i<(PKT_SIZE-1)) snprintf(buf+strlen(buf),DATA_BUF_SIZE,", "); } } //stick them in a json format snprintf(payload_buf,PAYLOAD_BUF_SIZE, "{\"plug\":\"%s\",\"ip\":\"%s\",\"time\":\"%s\"," "\"vrms\":[%s],\"irms\":[%s],\"watts\":[%s],\"pavg\":[%s]," "\"pf\":[%s],\"freq\":[%s],\"kwh\":[%s]}", wemo_config.serial_number,wemo_config.ip_addr,wemo_pkt->timestamp, bufs[0],bufs[1],bufs[2],bufs[3],bufs[4],bufs[5],bufs[6]); snprintf(tx_buf,TX_BUF_SIZE, "POST /config/plugs/log HTTP/1.1\r\n" "User-Agent: WemoPlug\r\n" "Host: NILM\r\nAccept:*/*\r\n" "Connection: keep-alive\r\n" "Content-Type: application/json\r\n" "Content-Length: %d\r\n" "\r\n%s", strlen(payload_buf),payload_buf); //send the packet! r = wifi_transmit(wemo_config.nilm_ip_addr,80,tx_buf); switch(r){ case TX_SUCCESS: wemo_pkt->status = POWER_PKT_EMPTY; break; case TX_BAD_DEST_IP: //if we can't find NILM, get its IP from the manager wemo_pkt->status = POWER_PKT_EMPTY; //just dump the packet core_get_nilm_ip_addr(); break; case TX_ERR_MODULE_RESET: wifi_init(); //re-initialize WiFi on reset error case TX_ERROR: //just fall through and register the failure case TX_TIMEOUT: default: wemo_pkt->status = POWER_PKT_TX_FAIL; } //free memory core_free(tx_buf); core_free(payload_buf); for(j=0;j<7;j++){ core_free(bufs[j]); } }
void core_process_wifi_data(void){ int BUF_SIZE=XL_BUF_SIZE; char *buf; int chan_num, data_size, r; unsigned int red,green,blue, blink; unsigned int yr,mo,dt,dw,hr,mn,sc; int time_buf_size = MD_BUF_SIZE; char *time_buf; //match against the data if(strlen(wifi_rx_buf)>BUF_SIZE){ printf("can't process rx'd packet, too large\n"); core_log("can't process rx'd packet, too large"); return; } //allocate memory buf = core_malloc(BUF_SIZE); r=sscanf(wifi_rx_buf,"\r\n+IPD,%d,%d:%s", &chan_num, &data_size, buf); if(r!=3){ printf("rx'd corrupt data, ignoring\n"); core_log("rx'd corrupt data, ignoring\n"); //free memory core_free(buf); return; } if(wemo_config.debug_level>DEBUG_INFO) printf("Got [%d] bytes on channel [%d]\n", data_size, chan_num); //discard responses from the NILM to power logging packets, but keep the response //if another core function has requested some data, this is done with the callback //function. The requesting core function registers a callback and this function calls //it and then resets the callback to NULL if(chan_num==4){ //close the socket wifi_send_cmd("AT+CIPCLOSE=4","Unlink",buf,BUF_SIZE,1); //execute the callback if(tx_callback!=NULL){ (*tx_callback)(wifi_rx_buf); tx_callback=NULL; } //clear the server buffer memset(wifi_rx_buf,0x0,WIFI_RX_BUF_SIZE); //free memory core_free(buf); return; } /////////////////// //this data must be inbound to the server port, process the command // // RELAY ON if(strcmp(buf,"relay_on")==0){ gpio_set_pin_high(RELAY_PIN); printf("relay ON\n"); //return "OK" to indicate success wifi_send_txt(0,"OK"); } // RELAY OFF else if(strcmp(buf,"relay_off")==0){ gpio_set_pin_low(RELAY_PIN); printf("relay OFF\n"); //return "OK" to indicate success wifi_send_txt(0,"OK"); } // LED SET else if(strstr(buf,"set_led")==buf){ if(sscanf(buf,"set_led_%u_%u_%u_%u.",&red,&green,&blue,&blink)!=4){ core_log("corrupt led_set request"); } else { rgb_led_set(red,green,blue,blink); if(wemo_config.echo) printf("set led: [%u, %u, %u, %u]\n",red,green,blue,blink); wifi_send_txt(0,"OK"); } } // RTC SET else if(strstr(buf,"set_rtc")==buf){ if(sscanf(buf,"set_rtc_%u_%u_%u_%u_%u_%u_%u.", &yr,&mo,&dt,&dw,&hr,&mn,&sc)!=7){ core_log("corrupt rtc_set request"); } else { if(i2c_rtc_set_time(sc,mn,hr,dw,dt,mo,yr)!=0) printf("error setting RTC\n"); else{ time_buf = membag_alloc(time_buf_size); if(time_buf==NULL) core_panic(); rtc_get_time_str(time_buf,time_buf_size); if(wemo_config.echo) printf("wifi set rtc to: %s\n",time_buf); core_log("wifi set rtc"); membag_free(time_buf); wifi_send_txt(0,"OK"); } } } // SEND DATA else if(strcmp(buf,"send_data")==0){ if(tx_pkt->status!=POWER_PKT_READY){ r = wifi_send_txt(chan_num,"error: no data"); if(r==TX_ERR_MODULE_RESET) while(wifi_init()!=0); //fail!!! anger!!!! reset the module } else { //send the data r=wifi_send_raw(chan_num,(uint8_t*)tx_pkt,sizeof(*tx_pkt)); if(r==TX_ERR_MODULE_RESET){ while(wifi_init()!=0); //fail!! anger!!! reset the module } else { //clear out the packet so we can start again memset(tx_pkt,0,sizeof(*tx_pkt)); tx_pkt->status=POWER_PKT_EMPTY; if(wemo_config.debug_level>=DEBUG_INFO) printf("sent data\n"); } } } else{ printf("unknown command: %s\n",buf); wifi_send_txt(chan_num,"error: unknown command"); //free memory core_free(buf); return; } //clear the server buffer memset(wifi_rx_buf,0x0,WIFI_RX_BUF_SIZE); //free the memory core_free(buf); return; }
int mon_config(int argc, char **argv){ int i; bool b_tmp_echo; //override echo setting for config printout char *conf_buf; int CONF_BUF_SIZE = MD_BUF_SIZE; //array of gettable configs and their values #define GETTABLE_CONFIG_SIZE 7 char *gettable_configs[GETTABLE_CONFIG_SIZE]= { "wifi_ssid","mgr_url","serial_number", "ip_addr","nilm_id","nilm_ip","standalone"}; char *gettable_config_vals[GETTABLE_CONFIG_SIZE] = { wemo_config.wifi_ssid, wemo_config.mgr_url, wemo_config.serial_number, wemo_config.ip_addr, wemo_config.nilm_id, wemo_config.nilm_ip_addr, wemo_config.str_standalone}; //array of settable configs and their values #define SETTABLE_CONFIG_SIZE 7 char *settable_configs[SETTABLE_CONFIG_SIZE]= { "wifi_ssid","wifi_pwd","mgr_url","serial_number", "nilm_id","standalone","nilm_ip"}; char *settable_config_vals[SETTABLE_CONFIG_SIZE] = { wemo_config.wifi_ssid, wemo_config.wifi_pwd, wemo_config.mgr_url, wemo_config.serial_number, wemo_config.nilm_id, wemo_config.str_standalone, wemo_config.nilm_ip_addr}; if(argc<2){ printf("wrong number of args to config\n"); return -1; } //--- request to get a config ---- if(strcmp(argv[1],"get")==0){ if(argc!=3){ printf("specify a config to read\n"); return -1; } //find the matching config for(i=0;i<GETTABLE_CONFIG_SIZE;i++){ if(strstr(argv[2],gettable_configs[i])==argv[2]){ //override the echo setting b_tmp_echo = wemo_config.echo; wemo_config.echo = true; printf(gettable_config_vals[i]); printf("\n"); //reset the echo setting wemo_config.echo = b_tmp_echo; return 0; } } //couldn't find config printf("Error, config [%s] is not available\n",argv[2]); return -1; } //--- request to set a config ---- if(strcmp(argv[1],"set")==0){ if(argc<3){ //clear the specified config printf("specify a config and the value"); } //allocate memory conf_buf=core_malloc(CONF_BUF_SIZE); //read in the whole config, might have whitespace for(i=3;i<argc;i++){ if(strlen(conf_buf)>0){ //insert whitespace btwn "args" strcat(conf_buf," "); } if((strlen(argv[i])+strlen(conf_buf))>CONF_BUF_SIZE){ printf("requested value is too large to store\n"); return -1; } strcat(conf_buf,argv[i]); } //find the matching config for(i=0;i<SETTABLE_CONFIG_SIZE;i++){ if(strstr(argv[2],settable_configs[i])==argv[2]){ if(strlen(conf_buf)>MAX_CONFIG_LEN){ printf("requested value is too large to store\n"); return -1; } //clear out the existing config memset(settable_config_vals[i],0x0,MAX_CONFIG_LEN); //save the config to the config struct memcpy(settable_config_vals[i],conf_buf,strlen(conf_buf)); printf("Set [%s] to [%s]\n",argv[2],settable_config_vals[i]); //save the new config fs_write_config(); } } } return 0; }
static void * operator new[](size_t size) { return core_malloc(size); }
int wifi_init(void){ uint32_t BUF_SIZE = MD_BUF_SIZE; uint8_t tmp; //dummy var for flushing UART int r; //return value from wifi_send_cmd (length of resp) char *buf; char *tx_buf; //allocate static buffers if they are not NULL if(resp_buf==NULL){ resp_buf=core_malloc(RESP_BUF_SIZE); } if(resp_complete_buf==NULL){ resp_complete_buf=core_malloc(RESP_COMPLETE_BUF_SIZE); } if(wifi_rx_buf==NULL){ wifi_rx_buf = core_malloc(WIFI_RX_BUF_SIZE); } //if we are standalone, don't do anything if(wemo_config.standalone){ printf("warning: wifi_init called in standalone mode\n"); return 0; } //initialize the memory buf = core_malloc(BUF_SIZE); tx_buf = core_malloc(BUF_SIZE); //set up the UART static usart_serial_options_t usart_options = { .baudrate = WIFI_UART_BAUDRATE, .charlength = WIFI_UART_CHAR_LENGTH, .paritytype = WIFI_UART_PARITY, .stopbits = WIFI_UART_STOP_BITS }; gpio_configure_pin(PIO_PA9_IDX, (PIO_PERIPH_A | PIO_DEFAULT)); gpio_configure_pin(PIO_PA10_IDX, (PIO_PERIPH_A | PIO_DEFAULT)); pmc_enable_periph_clk(ID_WIFI_UART); sysclk_enable_peripheral_clock(ID_WIFI_UART); usart_serial_init(WIFI_UART,&usart_options); //flush any existing data while(usart_serial_is_rx_ready(WIFI_UART)){ usart_serial_getchar(WIFI_UART,&tmp); } // Trigger from timer 0 pmc_enable_periph_clk(ID_TC0); tc_init(TC0, 0, // channel 0 TC_CMR_TCCLKS_TIMER_CLOCK5 // source clock (CLOCK5 = Slow Clock) | TC_CMR_CPCTRG // up mode with automatic reset on RC match | TC_CMR_WAVE // waveform mode | TC_CMR_ACPA_CLEAR // RA compare effect: clear | TC_CMR_ACPC_SET // RC compare effect: set ); TC0->TC_CHANNEL[0].TC_RA = 0; // doesn't matter TC0->TC_CHANNEL[0].TC_RC = 64000; // sets frequency: 32kHz/32000 = 1 Hz NVIC_ClearPendingIRQ(TC0_IRQn); NVIC_SetPriority(TC0_IRQn,1);//high priority NVIC_EnableIRQ(TC0_IRQn); tc_enable_interrupt(TC0, 0, TC_IER_CPCS); //reset the module if(wifi_send_cmd("AT+RST","ready",buf,BUF_SIZE,8)==0){ printf("Error reseting ESP8266\n"); //free memory core_free(buf); core_free(tx_buf); return -1; } //set to mode STA if(wifi_send_cmd("AT+CWMODE=1","OK",buf,BUF_SIZE,8)==0){ printf("Error setting ESP8266 mode\n"); core_free(buf); core_free(tx_buf); return 0; } //try to join the specified network snprintf(tx_buf,BUF_SIZE,"AT+CWJAP=\"%s\",\"%s\"", wemo_config.wifi_ssid,wemo_config.wifi_pwd); if((r=wifi_send_cmd(tx_buf,"OK",buf,BUF_SIZE,10))==0){ printf("no response to CWJAP\n"); //free memory core_free(buf); core_free(tx_buf); return -1; } //check for errors if( (r<1) || (strcmp(&buf[r-1],"OK")!=0)){ snprintf(tx_buf,BUF_SIZE,"failed to join network [%s]: [%s]\n",wemo_config.wifi_ssid, buf); printf(tx_buf); core_log(tx_buf); //free memory core_free(buf); core_free(tx_buf); return -1; } //see if we have an IP address wifi_send_cmd("AT+CIFSR","OK",buf,BUF_SIZE,5); if(strstr(buf,"ERROR")==buf){ printf("error getting IP address\n"); //free the memory core_free(tx_buf); core_free(buf); return -1; } //try to parse the response into an IP address //expect 4 octets but *not* 0.0.0.0 int a1,a2,a3,a4; if(!(sscanf(buf,"+CIFSR:STAIP,\"%d.%d.%d.%d\"",&a1,&a2,&a3,&a4)==4 && a1!=0)){ printf("error, bad address: %s\n",buf); //free the memory core_free(tx_buf); core_free(buf); return -1; } //save the IP to our config snprintf(buf,BUF_SIZE,"%d.%d.%d.%d",a1,a2,a3,a4); memset(wemo_config.ip_addr,0x0,MAX_CONFIG_LEN); strcpy(wemo_config.ip_addr,buf); //set the mode to multiple connection wifi_send_cmd("AT+CIPMUX=1","OK",buf,BUF_SIZE,2); //start a server on port 1336 wifi_send_cmd("AT+CIPSERVER=1,1336","OK",buf,BUF_SIZE,2); //if we know the NILM IP address, send it our IP if(strlen(wemo_config.nilm_ip_addr)!=0){ if(wifi_send_ip()==TX_ERR_MODULE_RESET){ return TX_ERR_MODULE_RESET; } } else { //get the NILM IP address from the manager //once we know the NILM address we send it ours core_get_nilm_ip_addr(); } //log the event snprintf(buf,BUF_SIZE,"Joined [%s] with IP [%s]", wemo_config.wifi_ssid,wemo_config.ip_addr); printf("\n%s\n",buf); core_log(buf); //free the memory core_free(tx_buf); core_free(buf); return 0; }