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! }
void esp8266_module::wifi_esp8266_socket_close(unsigned int sid) { CSTRING cmd; if(get_socket_state(sid)) { cmd.format("+CIPCLOSE=%u", sid); if(wifi_send_cmd(cmd.c_str(), 45) & WIFI_CMD_STATE_OK) { if( (sid < WIFI_ESP8266_MAX_SOCKETS) && alloc_sockets[sid]) { pending_socket = alloc_sockets[sid]; for(int i=0; i< 500; i++) { wifi_sleep(10); if(pending_socket->sock_state == SOCKET_OPEN) { TRACE_WIFI("\r\nUnlinked %d", sid); break; } } pending_socket = NULL; } } } }
RES_CODE esp8266_module::wifi_echo_off(bool lowlevel, uint32_t indx) { RES_CODE res; res = RES_ERROR; for(int i=0; i < 3; i++) { rcv_hnd.close(); snd_hnd.close(); if(lowlevel) return RES_OK; tsk_sleep(50); if(rcv_hnd.tsk_open(drv_info->iface_driver_index, drv_info->iface_mode_stru[indx]) && snd_hnd.tsk_open(drv_info->iface_driver_index, drv_info->iface_mode_stru[indx]) ) { //wait until rx signals get stable tsk_sleep(50); //turn off echo if(wifi_send_cmd("E0", 1) & WIFI_CMD_STATE_OK) { res = RES_OK; break; } } } return res; }
void esp8266_module::wifi_process_tout(void) { CSocket* sock; HANDLE list; RES_CODE res; if(wifi_tout) { if(!--wifi_tout) { if(!used_sockets) { //--- deactivate the context? for(int i=0; i < 3; i++ ) { if(wifi_send_cmd("+CWQAP", 150) & WIFI_CMD_STATE_OK) { wifi_send_cmd("+CWJAP?", 50); break; } } wifi_on_disconnect(this); TRACELN1("WIFI OFF"); list = waiting_open; waiting_open = NULL; while(list) { sock = (CSocket*)list; list = sock->next; sock->res = RES_BUSY; res = wifi_sock_open(sock); if(res & FLG_SIGNALED) usr_HND_SET_STATUS(sock, res); } if(!used_sockets) wifi_drv_off(); } } } }
RES_CODE esp8266_module::wifi_sock_connect_url(CSocket* sock) { CSTRING cmd;; for(int try_cnt=0; sock && try_cnt <3; try_cnt++ ) { if(sock->sock_state & SOCKET_OPEN) { unsigned int sid = sock->sock_id; cmd.format("+CIPSTART=%u,\"%s\",\"%s\",%u", sid, (((sock_mode_t*)sock->mode.as_voidptr)->sock_type == IP_SOCKET_TCP)?"TCP":"UDP", sock->src.as_charptr, sock->dst.as_int); if (wifi_send_cmd(cmd.c_str(), 40) & WIFI_CMD_STATE_OK) { pending_socket = sock; for(int i=0; i<500; i++) { wifi_sleep(10); if(sock->sock_state == SOCKET_CONECTED) break; } pending_socket = NULL; received_size[sock->sock_id] = 0; if(sock->sock_state == SOCKET_CONECTED) { TRACE_WIFI("\r\nLink %d", sid); return RES_SIG_OK; } wifi_esp8266_socket_close(sid); } //Debug get_socket_state(sid); } else { wifi_net_error(NET_ERR_SOCK_CLOSED); return RES_SIG_ERROR; } } wifi_net_error(NET_ERR_SOCK_CONNECT); return RES_SIG_ERROR; }
unsigned int esp8266_module::get_socket_state(unsigned int sock_id) { RES_CODE res; const char* cmd = "+CIPSTATUS"; unsigned int sig=0; uint32_t index; bool found = false; cmd_state |= WIFI_CMD_STATE_ROW_STOP; res = wifi_send_cmd(cmd, 15); cmd_state &= ~WIFI_CMD_STATE_ROW_STOP; do { if(sig) { process_input(sig, cmd); res = cmd_state; } if (res >= WIFI_CMD_STATE_OK) break; if(res & WIFI_CMD_STATE_RETURNED) { cmd_state = res & ~WIFI_CMD_STATE_RETURNED; if(tmos_sscanf(buf, "+CIPSTATUS:%u", &index)) { if(index == sock_id) found = true; } row_start = 0; row_end = 0; } sig = tsk_resume_wait_signal(rcv_hnd.signal); } while(sig); if((cmd_state & WIFI_CMD_STATE_OK) && found ) return 1; return 0; }
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; }
RES_CODE esp8266_module::process_write(CSocket* sock) { unsigned size;//, newsize, id; // unsigned int start_size, write_size, sock_state; CSTRING cmd; unsigned char snd_pending; while(1) { size = sock->len; if(!size) { TRACELN1("WIFI: write OK"); return RES_SIG_OK; } if(size >1022) size = 1022; if(sock->sock_state != SOCKET_CONECTED) break; // Send command cmd.format("+CIPSEND=%u,%u", sock->sock_id, size); TRACELN("WIFI: WRITE %d?", size); cmd_state |= WIFI_CMD_STATE_HND; if(wifi_send_cmd(cmd.c_str(), 20) != WIFI_CMD_STATE_RETURNED) { wifi_net_error(NET_ERR_SOCK_WRITE); return RES_SIG_ERROR; } // Send data snd_pending = '>'; do { process_input(rcv_hnd.signal, cmd.c_str(), snd_pending); if ( cmd_state >= WIFI_CMD_STATE_HND ) { if ( cmd_state & WIFI_CMD_STATE_HND ) { unsigned int mytime; cmd_state &= ~WIFI_CMD_STATE_HND; snd_pending = 0; rcv_hnd.tsk_start_read(&received_ch, 1); mytime = CURRENT_TASK->time; tsk_sleep(55); // data sheet recomendation if( snd_hnd.tsk_write(sock->src.as_voidptr, size, WIFI_WRITE_TOT) != RES_OK) break; CURRENT_TASK->time = mytime; } else { if ( cmd_state >= WIFI_CMD_STATE_OK ) break; // command completed with OK, ERROR .. } } } while(tsk_resume_wait_signal(rcv_hnd.signal)); // wifi_on_blink_transfer(this, GPRS_TRANSFER_INDICATOR); //Check the result if(cmd_state & WIFI_CMD_STATE_OK) { TRACE1(" done!"); sock->src.as_byteptr += size; sock->len -= size; continue; } if (cmd_state & WIFI_CMD_STATE_CMES) { TRACE_ERROR("\r\nWIFI:%s write ERROR", sock->client.task->name); } break; } wifi_sleep(120); wifi_net_error(NET_ERR_SOCK_WRITE); return RES_SIG_ERROR; }
RES_CODE esp8266_module::wifi_drv_pwron(bool lowlevel) { RES_CODE res; WIFI_DRIVER_DATA * drv_data = drv_info->drv_data; bool changed = false; if(drv_data->wifi_flags_bad & WIFI_FLAG_SHUTDOWN) return wifi_error(NET_ERR_WIFI_SHUTDOWN); if( drv_data->wifi_flags_ok & WIFI_FLAG_ON) return RES_OK; TRACE1_WIFI_DEBUG("\r\nWIFI power"); drv_data->wifi_flags_ok = WIFI_STATE_OFF; do { res = wifi_echo_off(lowlevel, 0); if(lowlevel) return res; if(res != RES_OK) { res = wifi_echo_off(lowlevel, 1); if(res == RES_OK && !changed) { //try to switch baudrate CSTRING cmd; cmd.format("+CIOBAUD=%u", *(const uint32_t*)drv_info->iface_mode_stru[0]); if(wifi_send_cmd(cmd.c_str(), 2) & WIFI_CMD_STATE_OK) changed = true; } } else break; } while(changed); if(res == RES_OK) { // configure WiFi module wifi_send_cmd("+CWQAP", 3); // 1. Enable the module to act as “Station” res = wifi_send_cmd("+CWMODE=1", 5); if(WIFI_CMD_STATE_OK == res) { // 2.Enable multiple connections or not (1-multiple/ 0- Single // Note: This mode can only be changed after all connections are // disconnected. If server is started, reboot is required. res = wifi_send_cmd("+CIPMUX=1", 50); if(WIFI_CMD_STATE_OK == res) { //Reset (reset MT with resetting the SIM) drv_data->wifi_flags_ok = WIFI_FLAG_ON; drv_data->wifi_flags_bad &= ~WIFI_FLAG_ON; wifi_on_pwron(this); return NET_OK; } } } drv_data->wifi_error = NET_ERR_WIFI_ON; drv_data->wifi_flags_bad |= WIFI_FLAG_ON; return wifi_error(NET_ERR_WIFI); }
NET_CODE esp8266_module::wifi_esp8266_socket_open(CSocket* sock) { unsigned int sid; sock_mode_t* mode; RES_CODE res; const char* cmd = "+CIPSTATUS"; unsigned int sig=0; CSTRING msg_list("\r\n"); uint32_t index=1; cmd_state |= WIFI_CMD_STATE_ROW_STOP; res = wifi_send_cmd(cmd, 15); cmd_state &= ~WIFI_CMD_STATE_ROW_STOP; do { if(sig) { process_input(sig, cmd); res = cmd_state; } if (res >= WIFI_CMD_STATE_OK) break; if(res & WIFI_CMD_STATE_RETURNED) { cmd_state = res & ~WIFI_CMD_STATE_RETURNED; msg_list.appendf("%u:%s\r\n", index++, buf); row_start = 0; row_end = 0; } sig = tsk_resume_wait_signal(rcv_hnd.signal); } while(sig); // if(cmd_state & WIFI_CMD_STATE_OK) // TRACE1(msg_list.c_str()); mode = (sock_mode_t*)sock->mode.as_voidptr; if(mode ) { if ( (mode->sock_type == IP_SOCKET_UDP && mode->port) ||(mode->sock_type == IP_SOCKET_TCP) ) { for(sid=0; sid < WIFI_ESP8266_MAX_SOCKETS; sid++) { if(NULL == alloc_sockets[sid]) { sock->sock_id = sid; sock->sock_state = SOCKET_OPEN; alloc_sockets[sid] = sock; #if USE_GPRS_LISTEN if (mode->sock_type == IP_SOCKET_UDP) listen_ports[sid] = mode->port; accept_id[sid] = GPRS_LEON_MAX_SOCKETS; #endif used_sockets++; // msg_list.format("\r\nWIFI:%s sock open %d.", sock->client.task->name, sid); // TRACE1(msg_list.c_str()); return NET_OK; } } } } TRACE_WIFI_ERROR("\r\nWIFI:%s create socket ERROR", sock->client.task->name); return wifi_net_error(NET_ERR_SOCK_CREATE); }
NET_CODE esp8266_module::wifi_esp8266_init_net(CSocket * sock) { NET_CODE res; CSTRING cmd; wifi_AP_t AP; uint32_t sig = 0; bool found; res = wifi_send_cmd("+CIFSR", 50); for(int i =0; i < 5; i++) { found = false; cmd_state |= WIFI_CMD_STATE_ROW_STOP; res = wifi_send_cmd("+CWLAP", 15); cmd_state &= ~WIFI_CMD_STATE_ROW_STOP; do { if(sig) { process_input(sig, "+CWLAP"); res = cmd_state; } if (res >= WIFI_CMD_STATE_OK) break; if(res & WIFI_CMD_STATE_RETURNED) { cmd_state = res & ~WIFI_CMD_STATE_RETURNED; if(!found) { res = wifi_on_get_AP(this, sock, &AP); if(res == RES_OK) found = true; } row_start = 0; row_end = 0; } sig = tsk_resume_wait_signal(rcv_hnd.signal); } while(sig); if(cmd_state & WIFI_CMD_STATE_OK) { if(!found) res = NET_ERR_WIFI_NET_NAME; else res = NET_OK; break; } } if (res != NET_OK) return wifi_error(res); // If the wifi is already connected to a network different than the one // requested - return NET_IDLE - unavailable if (NET_OK == wifi_get_network_name(cmd)) { if (0 != strcmp(cmd.c_str(), AP.name.c_str())) { return NET_IDLE; } } cmd.format("+CWJAP=\"%s\",\"%s\"", AP.name.c_str(), AP.pass.c_str()); for(int i=0; i < 3; i++) { res = wifi_send_cmd(cmd.c_str(), 50); if (WIFI_CMD_STATE_OK == res) { res = wifi_send_cmd("+CIFSR", 50); if (WIFI_CMD_STATE_ROK == res) { connected_network_name = AP.name; return NET_OK; } break; } } return NET_ERR_WIFI_REGISTER; if (WIFI_CMD_STATE_OK == res) { res = wifi_send_cmd("+CIFSR", 50); if (WIFI_CMD_STATE_ROK == res) { connected_network_name = AP.name; wifi_send_cmd("+CIPSTART=\"TCP\",\"www.tmos-arm.com\",80", 50); //wifi_send_cmd("+CIPSTART=\"TCP\",\"192.168.147.100\",6112", 50); cmd.clear(); cmd.append("+CIPSEND="); cmd.appendf("%d", strlen(message) + 1); wifi_send_cmd(cmd.c_str(), 200); // make sure the handle is working if it is open while(rcv_hnd.res < FLG_BUSY) { process_input(0, NULL); } wifi_sleep(20); //(the recommended value is at least 20 ms) // make sure no URC is coming and the buf is empty if( cmd_state & WIFI_CMD_STATE_STARTED) { if (tsk_wait_signal(rcv_hnd.signal, 8192)) { do { process_input(rcv_hnd.signal, NULL); } while ( (cmd_state & WIFI_CMD_STATE_STARTED) && tsk_resume_wait_signal(rcv_hnd.signal) ); } } //start clean cmd_state &= (WIFI_CMD_STATE_ROW_STOP | WIFI_CMD_STATE_HND); row_start = row_end = 0; snd_hnd.tsk_write(message, strlen(message) + 1, WIFI_WRITE_TOT); return NET_OK; } } return wifi_net_error(res); }
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; }