コード例 #1
0
ファイル: wifi.c プロジェクト: jdrunner/smartee
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!
}
コード例 #2
0
ファイル: esp8266.cpp プロジェクト: miro-kostadinov/tmos
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;
			}
		}
	}
}
コード例 #3
0
ファイル: esp8266.cpp プロジェクト: miro-kostadinov/tmos
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;
}
コード例 #4
0
ファイル: esp8266.cpp プロジェクト: miro-kostadinov/tmos
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();
			}
		}
	}
}
コード例 #5
0
ファイル: esp8266.cpp プロジェクト: miro-kostadinov/tmos
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;
}
コード例 #6
0
ファイル: esp8266.cpp プロジェクト: miro-kostadinov/tmos
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;
}
コード例 #7
0
ファイル: monitor.c プロジェクト: jdrunner/smartee
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;
}
コード例 #8
0
ファイル: esp8266.cpp プロジェクト: miro-kostadinov/tmos
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;
}
コード例 #9
0
ファイル: esp8266.cpp プロジェクト: miro-kostadinov/tmos
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);
}
コード例 #10
0
ファイル: esp8266.cpp プロジェクト: miro-kostadinov/tmos
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);

}
コード例 #11
0
ファイル: esp8266.cpp プロジェクト: miro-kostadinov/tmos
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);
}
コード例 #12
0
ファイル: wifi.c プロジェクト: jdrunner/smartee
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;
}