Core: Cortex-M4
Microcontroller: stm32f407 (stm32f4 discovery board)
IP Stack: lwIP 1.4.1
I am using this microcontroller to control an automate and I want to send some information to a separate web server via a HTTP request in the form of:
http://192.168.1.3/api/xdevices.json?SetR=01
lwIP has a http server for the microprocessor, but I'm after the opposite (microcontroller is the client).
I am not sure what i'm doing wrong but after TCP_Connect it always goes to tcp_error handler :
#include "stm32f4xx.h"
/* Include my libraries here */
#include "defines.h"
#include "tm_stm32f4_delay.h"
#include "tm_stm32f4_disco.h"
#include "tm_stm32f4_usart.h"
#include "tm_stm32f4_ethernet.h"
#include "tm_stm32f4_watchdog.h"
#include <stdio.h>
#include <stdlib.h>
#include <lwip/tcp.h>
#include <tcp.h>
uint32_t tcp_send_packet(void);
void tcpErrorHandler(void *arg, err_t err);
err_t tcpSendCallback(void *arg, struct tcp_pcb *tpcb,u16_t len);
err_t connectCallback(void *arg, struct tcp_pcb *tpcb, err_t err);
struct tcp_pcb *testpcb;
first Function is tcp_new :
void tcp_setup(void)
{
uint32_t data = 0xdeadbeef;
/* create an ip */
struct ip_addr ip;
IP4_ADDR(&ip,192,168,1,4); //IP of my PHP server
/* create the control block */
testpcb = tcp_new(); //testpcb is a global struct tcp_pcb
// as defined by lwIP
/* dummy data to pass to callbacks*/
tcp_arg(testpcb, &data);
/* register callbacks with the pcb */
// tcp_recv(testpcb, tcpRecvCallback);
tcp_sent(testpcb, tcpSendCallback);
tcp_err(testpcb, tcpErrorHandler);
/* now connect */
tcp_connect(testpcb, &ip, 21, connectCallback);
TM_DISCO_LedOn(LED_ORANGE);
}
My Callbacks :
void tcpErrorHandler(void *arg, err_t err){
TM_DISCO_LedOn(LED_BLUE);
}
err_t tcpSendCallback(void *arg, struct tcp_pcb *tpcb,u16_t len)
{
TM_DISCO_LedOn(LED_RED);
}
err_t connectCallback(void *arg, struct tcp_pcb *tpcb, err_t err)
{
TM_DISCO_LedOn(LED_RED);
tcp_send_packet();
return 0;
}
my header :
uint32_t tcp_send_packet(void)
{
char *string = "SetR=01\r\n\r\n ";
uint32_t len = strlen(string);
/* push to buffer */
tcp_write(testpcb, string, strlen(string), TCP_WRITE_FLAG_COPY);
/* now send */
tcp_output(testpcb);
return 0;
}
void lwip_init();
Main function :
int main(void) {
/* Initialize system */
SystemInit();
lwip_init();
/* Initialize delay */
TM_DELAY_Init();
/* Initialize leds on board */
TM_DISCO_LedInit();
/* Initialize button */
TM_DISCO_ButtonInit();
while(1) {
tcp_setup();
} }
Clearly i'm forgetting something i just don't know what it is .( i'm using Keil arm)
thank you
Init LwIP with lwip_init
Call tcp_setup outside while loop only once not in while loop to setup only one TCP connection, not unlimited
In while loop, process LwIP incoming data periodically. Since you are using my (TM Tilen Majerle) ethernet wrapper for STM32F4, you should add these lines inside your while loop
/* Check if any packet received */
if (LwIP_CheckFrameReceived()) {
/* Process received ethernet packet */
LwIP_Pkt_Handle();
}
/* Handle periodic timers for LwIP */
LwIP_Periodic_Handle(EthernetLocalTime);
Or call TM_ETHERNET_Update function from your library. Your choice, it works the same.
In your case:
int main() {
....
lwip_init();
tcp_setup();
while (1) {
TM_ETHERNET_Update();
}
}
Related
Now,I am working with STM32F107+lwip.The aim is making a gateway which is used to exchange datas between ETHERNET and CAN. The UDP server is tested well.And now I want to increase the TCP server function,which can be permitted to establish 5 TCP connections.
My questions:
1 TCP connnection is tested ok,How to implement 5 TCP connections?
First,PC send data to STM32 by TCP connections. STM32 receives it and send it to CAN.Then,when STM32 receives datas from CAN ,it will send the datas to PC by all the TCP connections.Now,my idea is that typedef a structure,when STM32 received the data from PC,it will record the pcb,remote ip and remote port. And receiving data from CAN ,STM32 will send it through the recording data.The result is the data will be sent slowly when STM32 invokes the "tcp_write()" and "tcp_output"frequently.
So I wonder the solutions to implement multiple TCP connections.
#define TCP_WORKING 0xaa
#define TCP_FREE 0xa5
typedef struct Cmd_TCPData
{
unsigned char TCP_STATUS;
unsigned char cmd_flag;
unsigned short remote_port;
unsigned short data_len;
struct ip_addr remote_ip;
unsigned char *pData;
struct tcp_pcb *TCP_pcb;
}Cmd_TCPData;
Cmd_TCPData cmd_tcp;
Cmd_TCPData tcp_list[5];
static u8 TcpListNum;
void TCP_server_init(void)
{
struct tcp_pcb *pcb;
err_t err;
/*****************************************************/
pcb = tcp_new();
if (!pcb)
{
return ;
}
err = tcp_bind(pcb,IP_ADDR_ANY,devInfo.udpPort);
if(err != ERR_OK)
{
return ;
}
pcb = tcp_listen(pcb);
tcp_accept(pcb,tcp_server_accept);
}
static err_t tcp_server_accept(void *arg,struct tcp_pcb *pcb,err_t err)
{
tcp_setprio(pcb, TCP_PRIO_MIN);
tcp_recv(pcb,tcp_server_recv);
err = ERR_OK;
return err;
}
static err_t tcp_server_recv(void *arg, struct tcp_pcb *pcb,struct pbuf *p,err_t err)
{
struct pbuf *p_temp = p;
int nPos=0;
u8 searchtemp=0;
//TCP_pcbA=pcb;
while(tcp_list[searchtemp].TCP_STATUS==TCP_WORKING)
{
if(tcp_list[searchtemp].remote_ip.addr!= pcb->remote_ip.addr)
{
searchtemp++;
}
else
break;
if(searchtemp==5)
{
searchtemp=0;
break;
}
}
/******copy*******************/
tcp_list[searchtemp].TCP_pcb=pcb;
tcp_list[searchtemp].pData = TCPRecvBuf;
tcp_list[searchtemp].remote_port=pcb->remote_port;
tcp_list[searchtemp].remote_ip = pcb->remote_ip;
tcp_setprio(tcp_list[searchtemp].TCP_pcb, TCP_PRIO_MIN+searchtemp);
if(p_temp != NULL)
{
tcp_recved(pcb, p_temp->tot_len);
while(p_temp != NULL)
{
// tcp_write(pcb,p_temp->payload,p_temp->len,TCP_WRITE_FLAG_COPY);
// tcp_output(pcb);
memcpy(tcp_list[searchtemp].pData+nPos,p_temp->payload,p_temp->len);
nPos += p_temp->len;
p_temp = p_temp->next;
}
}
else
{
tcp_close(pcb);
}
tcp_list[searchtemp].data_len = nPos;
flash_led_tcp = 1;
tcp_list[searchtemp].TCP_STATUS= TCP_WORKING;
TcpListNum=searchtemp;
pbuf_free(p);
err = ERR_OK;
return err;
}
void send_tcp_data(u8_t *pPtr,u16_t data_len)
{
u8 x=0;
while(x<5)
{
if(tcp_list[x].TCP_STATUS==TCP_WORKING)
{
//TCP_pcbA->remote_port=tcp_list[x].remote_port;
//TCP_pcbA->remote_ip= tcp_list[x].remote_ip;
tcp_write(tcp_list[x].TCP_pcb,pPtr,data_len,TCP_WRITE_FLAG_COPY);
tcp_output(tcp_list[x].TCP_pcb);
}
OSTimeDlyHMSM(0, 0, 0, 250);//250ms
x++;
}
}
The tcp_server_accept() will contain the newly created connection. To this connection you can attach your context.
struct myclient_t
{
struct tcp_pcb *pcb;
/* all the variables uniqe for tracking this specific connection.. parser-state, receive/send buffers, statistics... */
int foo;
int bar;
};
static err_t tcp_server_accept(void *arg,struct tcp_pcb *pcb,err_t err)
{
err_t ret_err;
struct struct myclient_t *context = 0;
int i;
context = new_client();
if (!context )
{
return ERR_MEM;
}
context->pcb = pcb;
/* pass newly allocated es structure as argument to newpcb */
tcp_arg(newpcb, context); /* recv, sent, error and poll callbacks will have context their argument, which is uniqe for each connection */
/* initialize lwip tcp_recv callback function for newpcb */
tcp_recv(newpcb, tcp_server_recv
tcp_sent(newpcb, tcp_server_sent);
/* initialize lwip tcp_err callback function for newpcb */
tcp_err(newpcb, tcp_server_error);
/* initialize lwip tcp_poll callback function for newpcb */
tcp_poll(newpcb, tcp_server_poll, 1);
return ERR_OK;
}
I am new in ARM and try to create slave device on STM32F103x. Also I need Serial Wire debugging and FreeRTOS tasking.
I create new project by STM32CubeMX. There are options to "Use FreeRTOS functions" in NVIC configuration. But I did not find any documentation, references or demos about how to use that.
EDIT 1: So I make in such way for now:
#include <string.h>
#define MASTER_REQ_READ 0x44
#define MASTER_REQ_EXEC 0x34
#define CONN_Pin GPIO_PIN_13
#define CONN_GPIO_Port GPIOC
/* Recieve protocol struct from Main controller */
struct saatProtoExec {
uint8_t target;
uint8_t command;
} execCommand;
uint8_t execBufferSize = sizeof(execCommand);
int main(void)
{
/*******************************/
/* definition and creation of i2cWait */
osThreadDef(i2cWait, i2cWaitForData, osPriorityRealtime, 0, 128);
i2cWaitHandle = osThreadCreate(osThread(i2cWait), NULL);
osKernelStart();
/* We should never get here as control is now taken by the scheduler */
/* Infinite loop */
while (1)
{
}
}
/* i2cWaitForData function */
void i2cWaitForData(void const * argument)
{
/* Infinite loop */
for(;;)
{
while(HAL_I2C_Slave_Receive_IT(&hi2c1, (uint8_t*)&bTransferRequest, 1)!= HAL_OK)
{
vTaskDelay(1);
}
/* Wait for I2C to get ready */
while (HAL_I2C_GetState(&hi2c1) != HAL_I2C_STATE_READY)
{
vTaskDelay(1);
}
/* Got command from main controller */
if (bTransferRequest == MASTER_REQ_EXEC)
{
/* Recieve buffer */
uint8_t execRxBuffer[execBufferSize];
printf("EXEC BUFFER SIZE %d\n", execBufferSize);
/* Got data */
while(HAL_I2C_Slave_Receive_IT(&hi2c1, (uint8_t*)execRxBuffer, execBufferSize)!= HAL_OK);
/* Wait for I2C to get ready */
while (HAL_I2C_GetState(&hi2c1) != HAL_I2C_STATE_READY)
{
vTaskDelay(1);
}
/* Lets print recieved RAW data */
for (uint8_t k = 0; k < sizeof(execRxBuffer); k++){
printf("0x%X\n", execRxBuffer[k]);
}
/* Lets combine recieved data to owr struct */
memcpy(&execCommand, execRxBuffer, execBufferSize);
/* Lets print data from struct */
printf("TARGET: 0x%X\n", execCommand.target);
printf("COMMAND: %u\n", execCommand.command);
/* Flush Rx buffers */
Flush_Buffer((uint8_t*)execRxBuffer, execBufferSize);
/* Toggle LED2 */
HAL_GPIO_TogglePin(CONN_GPIO_Port, CONN_Pin);
}
osDelay(1);
}
}
It works fine in non-blocking mode, but anyway: is it correct to do this?
Or may be it would be right to use Semaphores?
I can recommend this user manual: Developing Applications on STM32Cube with RTOS.
It has a description about FreeRTOS regarding the following points:
Free RTOS source organizations
Porting FreeRTOS on STM32
FreeRTOS API
FreeRTOS memory management
FreeRTOS low power
FreeRTOS configuration
Also it has application examples of the main operating system features:
Thread creation example
Semaphores example (between threads, from ISR)
Mutexes example
Queues example
Timers example
Low power example
There is an example project provided about thread creation in the STM32CubeF1 package under:
\STM32Cube_FW_F1_V1.4.0\Projects\STM32F103RB-Nucleo\Applications\FreeRTOS\FreeRTOS_ThreadCreation
this example uses an STM32F103RB.
To check if my cc3000 Wifi Shield works, I download the Adafruit CC3000 Library and run the example in the library, which is 'buildtest'.
Here are the link of Adafruit and library.
https://learn.adafruit.com/adafruit-shield-compatibility/cc3000-wifi-shield
https://github.com/adafruit/Adafruit_CC3000_Library
But when I run 'buildtest', the only things I can see in Serial monitor are corrupt(or garbled) messages.
Here is the code of 'buildtest' in the library.
/***************************************************
This is an example for the Adafruit CC3000 Wifi Breakout & Shield
Designed specifically to work with the Adafruit WiFi products:
----> https://www.adafruit.com/products/1469
Adafruit invests time and resources providing this open source code,
please support Adafruit and open-source hardware by purchasing
products from Adafruit!
Written by Kevin Townsend & Limor Fried for Adafruit Industries.
BSD license, all text above must be included in any redistribution
****************************************************/
/*
This example does a full test of core connectivity:
* Initialization
* SSID Scan
* AP connection
* DHCP printout
* DNS lookup
* Ping
* Disconnect
It's a good idea to run this sketch when first setting up the
module.
*/
#include <Adafruit_CC3000.h>
#include <ccspi.h>
#include <SPI.h>
#include <string.h>
#include "utility/debug.h"
// These are the interrupt and control pins
#define ADAFRUIT_CC3000_IRQ 3 // MUST be an interrupt pin!
// These can be any two pins
#define ADAFRUIT_CC3000_VBAT 5
#define ADAFRUIT_CC3000_CS 10
// Use hardware SPI for the remaining pins
// On an UNO, SCK = 13, MISO = 12, and MOSI = 11
Adafruit_CC3000 cc3000 = Adafruit_CC3000(ADAFRUIT_CC3000_CS, ADAFRUIT_CC3000_IRQ, ADAFRUIT_CC3000_VBAT,
SPI_CLOCK_DIVIDER); // you can change this clock speed but DI
#define WLAN_SSID "myNetwork" // cannot be longer than 32 characters!
#define WLAN_PASS "myPassword"
// Security can be WLAN_SEC_UNSEC, WLAN_SEC_WEP, WLAN_SEC_WPA or WLAN_SEC_WPA2
#define WLAN_SECURITY WLAN_SEC_WPA2
/**************************************************************************/
/*!
#brief Sets up the HW and the CC3000 module (called automatically
on startup)
*/
/**************************************************************************/
void setup(void)
{
Serial.begin(115200);
Serial.println(F("Hello, CC3000!\n"));
displayDriverMode();
Serial.print("Free RAM: "); Serial.println(getFreeRam(), DEC);
/* Initialise the module */
Serial.println(F("\nInitialising the CC3000 ..."));
if (!cc3000.begin())
{
Serial.println(F("Unable to initialise the CC3000! Check your wiring?"));
while(1);
}
/* Optional: Update the Mac Address to a known value */
/*
uint8_t macAddress[6] = { 0x08, 0x00, 0x28, 0x01, 0x79, 0xB7 };
if (!cc3000.setMacAddress(macAddress))
{
Serial.println(F("Failed trying to update the MAC address"));
while(1);
}
*/
uint16_t firmware = checkFirmwareVersion();
if (firmware < 0x113) {
Serial.println(F("Wrong firmware version!"));
for(;;);
}
displayMACAddress();
/* Optional: Get the SSID list (not available in 'tiny' mode) */
#ifndef CC3000_TINY_DRIVER
listSSIDResults();
#endif
/* Delete any old connection data on the module */
Serial.println(F("\nDeleting old connection profiles"));
if (!cc3000.deleteProfiles()) {
Serial.println(F("Failed!"));
while(1);
}
/* Optional: Set a static IP address instead of using DHCP.
Note that the setStaticIPAddress function will save its state
in the CC3000's internal non-volatile memory and the details
will be used the next time the CC3000 connects to a network.
This means you only need to call the function once and the
CC3000 will remember the connection details. To switch back
to using DHCP, call the setDHCP() function (again only needs
to be called once).
*/
/*
uint32_t ipAddress = cc3000.IP2U32(192, 168, 1, 19);
uint32_t netMask = cc3000.IP2U32(255, 255, 255, 0);
uint32_t defaultGateway = cc3000.IP2U32(192, 168, 1, 1);
uint32_t dns = cc3000.IP2U32(8, 8, 4, 4);
if (!cc3000.setStaticIPAddress(ipAddress, netMask, defaultGateway, dns)) {
Serial.println(F("Failed to set static IP!"));
while(1);
}
*/
/* Optional: Revert back from static IP addres to use DHCP.
See note for setStaticIPAddress above, this only needs to be
called once and will be remembered afterwards by the CC3000.
*/
/*
if (!cc3000.setDHCP()) {
Serial.println(F("Failed to set DHCP!"));
while(1);
}
*/
/* Attempt to connect to an access point */
char *ssid = WLAN_SSID; /* Max 32 chars */
Serial.print(F("\nAttempting to connect to ")); Serial.println(ssid);
/* NOTE: Secure connections are not available in 'Tiny' mode!
By default connectToAP will retry indefinitely, however you can pass an
optional maximum number of retries (greater than zero) as the fourth parameter.
ALSO NOTE: By default connectToAP will retry forever until it can connect to
the access point. This means if the access point doesn't exist the call
will _never_ return! You can however put in an optional maximum retry count
by passing a 4th parameter to the connectToAP function below. This should
be a number of retries to make before giving up, for example 5 would retry
5 times and then fail if a connection couldn't be made.
*/
if (!cc3000.connectToAP(WLAN_SSID, WLAN_PASS, WLAN_SECURITY)) {
Serial.println(F("Failed!"));
while(1);
}
Serial.println(F("Connected!"));
/* Wait for DHCP to complete */
Serial.println(F("Request DHCP"));
while (!cc3000.checkDHCP())
{
delay(100); // ToDo: Insert a DHCP timeout!
}
/* Display the IP address DNS, Gateway, etc. */
while (! displayConnectionDetails()) {
delay(1000);
}
#ifndef CC3000_TINY_DRIVER
/* Try looking up www.adafruit.com */
uint32_t ip = 0;
Serial.print(F("www.adafruit.com -> "));
while (ip == 0) {
if (! cc3000.getHostByName("www.adafruit.com", &ip)) {
Serial.println(F("Couldn't resolve!"));
}
delay(500);
}
cc3000.printIPdotsRev(ip);
/* Do a quick ping test on adafruit.com */
Serial.print(F("\n\rPinging ")); cc3000.printIPdotsRev(ip); Serial.print("...");
uint8_t replies = cc3000.ping(ip, 5);
Serial.print(replies); Serial.println(F(" replies"));
if (replies)
Serial.println(F("Ping successful!"));
#endif
/* You need to make sure to clean up after yourself or the CC3000 can freak out */
/* the next time you try to connect ... */
Serial.println(F("\n\nClosing the connection"));
cc3000.disconnect();
}
void loop(void)
{
delay(1000);
}
/**************************************************************************/
/*!
#brief Displays the driver mode (tiny of normal), and the buffer
size if tiny mode is not being used
#note The buffer size and driver mode are defined in cc3000_common.h
*/
/**************************************************************************/
void displayDriverMode(void)
{
#ifdef CC3000_TINY_DRIVER
Serial.println(F("CC3000 is configure in 'Tiny' mode"));
#else
Serial.print(F("RX Buffer : "));
Serial.print(CC3000_RX_BUFFER_SIZE);
Serial.println(F(" bytes"));
Serial.print(F("TX Buffer : "));
Serial.print(CC3000_TX_BUFFER_SIZE);
Serial.println(F(" bytes"));
#endif
}
/**************************************************************************/
/*!
#brief Tries to read the CC3000's internal firmware patch ID
*/
/**************************************************************************/
uint16_t checkFirmwareVersion(void)
{
uint8_t major, minor;
uint16_t version;
#ifndef CC3000_TINY_DRIVER
if(!cc3000.getFirmwareVersion(&major, &minor))
{
Serial.println(F("Unable to retrieve the firmware version!\r\n"));
version = 0;
}
else
{
Serial.print(F("Firmware V. : "));
Serial.print(major); Serial.print(F(".")); Serial.println(minor);
version = major; version <<= 8; version |= minor;
}
#endif
return version;
}
/**************************************************************************/
/*!
#brief Tries to read the 6-byte MAC address of the CC3000 module
*/
/**************************************************************************/
void displayMACAddress(void)
{
uint8_t macAddress[6];
if(!cc3000.getMacAddress(macAddress))
{
Serial.println(F("Unable to retrieve MAC Address!\r\n"));
}
else
{
Serial.print(F("MAC Address : "));
cc3000.printHex((byte*)&macAddress, 6);
}
}
/**************************************************************************/
/*!
#brief Tries to read the IP address and other connection details
*/
/**************************************************************************/
bool displayConnectionDetails(void)
{
uint32_t ipAddress, netmask, gateway, dhcpserv, dnsserv;
if(!cc3000.getIPAddress(&ipAddress, &netmask, &gateway, &dhcpserv, &dnsserv))
{
Serial.println(F("Unable to retrieve the IP Address!\r\n"));
return false;
}
else
{
Serial.print(F("\nIP Addr: ")); cc3000.printIPdotsRev(ipAddress);
Serial.print(F("\nNetmask: ")); cc3000.printIPdotsRev(netmask);
Serial.print(F("\nGateway: ")); cc3000.printIPdotsRev(gateway);
Serial.print(F("\nDHCPsrv: ")); cc3000.printIPdotsRev(dhcpserv);
Serial.print(F("\nDNSserv: ")); cc3000.printIPdotsRev(dnsserv);
Serial.println();
return true;
}
}
/**************************************************************************/
/*!
#brief Begins an SSID scan and prints out all the visible networks
*/
/**************************************************************************/
void listSSIDResults(void)
{
uint32_t index;
uint8_t valid, rssi, sec;
char ssidname[33];
if (!cc3000.startSSIDscan(&index)) {
Serial.println(F("SSID scan failed!"));
return;
}
Serial.print(F("Networks found: ")); Serial.println(index);
Serial.println(F("================================================"));
while (index) {
index--;
valid = cc3000.getNextSSID(&rssi, &sec, ssidname);
Serial.print(F("SSID Name : ")); Serial.print(ssidname);
Serial.println();
Serial.print(F("RSSI : "));
Serial.println(rssi);
Serial.print(F("Security Mode: "));
Serial.println(sec);
Serial.println();
}
Serial.println(F("================================================"));
cc3000.stopSSIDscan();
}
Sorry, I know this is very long code, but I can't understand why I get the corrupt message.
I don't think this problem is related to the setting of WIFI(#define WLAN SSID or #define WLAN PASS).
Because... if you look at the 'void setup' function, you can see
Serial.println(F("Hello, CC3000!\n"));
so I should see this message(Hello CC3000) no matter what.
Even if I set the my WLAN SSID and WLAN PASS, same corrupt message appears.
I can not check whether my cc3000 work well because of this corrupt message.
How can I solve this problem??
It usually means that you are using the wrong baudrate. In your program listing you have this line
“Serial.begin(115200);”
This sets the default baudrate.
In the Arduino software-> Tools->Serial Monitor-> bottom right corner you will see the baudrate window. This needs to match the baudrate in your program otherwise you get rubbish displayed.
I created a webservices in ASP .NET, that i published on azure, with this function
public string GetObject(int id)
{
return ("it is a test !");
}
when i enter the right URL, it works.
But when i try to send the request with arduino (based on ethernetclient example), it does not work.
the arduino code :
#include "Arduino.h"
#include <SPI.h>
#include <WiFlyHQ.h>
#include <Ethernet.h>
#include <SoftwareSerial.h>
WiFly wifly;
char ssid[] = "myssid";
char password[] = "mypass";
void setup() {
Serial.begin(9600);
wifly.begin(&Serial, NULL);
if (!(wifly.setSSID(ssid))) {
Serial.println("Fail to set ssid");
}
/* if (!(wifly.setKey(password))) {
Serial.println("Fail to set passPhrase");
} */
if (!(wifly.setPassphrase(password))) {
Serial.println("Fail to set passPhrase");
}
wifly.enableDHCP();
if (wifly.join()) {
Serial.println("Joined wifi network");
} else {
Serial.println("Failed to join wifi network");
}
if (wifly.open(myurl.azurewebsites.net)) {
wifly.println("GET /api/object/123 HTTP/1.0");
wifly.println("");
}
else
Serial.println("Connection failed");
}
void loop() {
if (client.available()) {
char c = client.read();
Serial.print(c);
}
}
The connection to the ssid works. But it blocks on wifly.open(). But, if I put wifly.open("search.yahoo.com") and then wifly.write("GET /search?p=50+km+in+miles HTTP/1.0"), ALL WORKS !
Do you know why ?
Thanks for your help.
How does EthernetClient get connected with WiFly? I don't see any calls that connect them. I have done some playing with a WiFly module but I don't see how you use EthernetClient with it.
The WiFly module is the network connection and is accessed via serial. Wouldn't you need to make the request though it, handle the responses with serial processing?
So I've looked around and noticed some others having a similar problem to mine. However I have yet to find a solution. I've created a client and server in Unix (Cygwin) using UDP. When I try to use sendto() in order to send a message to the server from the client, the server doesn't seem to be receiving the the packet. I've done error checking and it seems like the client isn't having a problem sending the packet, yet still the server cannot receive it correctly. The server just seems to be dead for the most part. I'm using my machine to host the client and the server and I'm attempting to connect to the server on my home address (127.0.0.1) and a random port. Any suggestions at this point would be much appreciated.
Server Code:
#include <stdio.h> /* standard C i/o facilities */
#include <stdlib.h> /* needed for atoi() / atof() */
#include <unistd.h> /* Unix System Calls */
#include <sys/types.h> /* system data type definitions */
#include <sys/socket.h> /* socket specific definitions */
#include <netinet/in.h> /* INET constants and stuff */
#include <arpa/inet.h> /* IP address conversion stuff */
#include <string.h> /* String manipulation */
#include <time.h> /* Used to to measure process execution time */
/* Server main routine - this is an iterative server
1. create a socket
2. bind the socket and print out the port number assigned
3. do forever
get next connection
handle the connection
enddo
*/
int main(int argc, char **argv)
{
int sockfd;
struct sockaddr_in servaddr, cliaddr;
int n;
//Create UDP socket
if( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
perror("Problem creating socket\n");
exit(1);
}
//Setup the UDP server
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(0);
//Bind the UDP to the socket
if (bind(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr))<0)
{
perror("Error bind\n");
exit(1);
}
//Print the port for the UDP server
int length = sizeof( servaddr );
if (getsockname(sockfd, (struct sockaddr *) &servaddr, &length) < 0)
{
perror("Error getsockname\n");
exit(1);
}
printf("The Server passive socket port number is %d\n",ntohs(servaddr.sin_port));
//Send/Recv from client
char msg[100];
for(;;)
{
socklen_t len = sizeof(cliaddr);
if( recvfrom(sockfd, msg, 100, 0, (struct sockaddr*) &cliaddr, &len) < 0)
{
perror("Error on recv\n");
exit(1);
}
printf("Msg: %s\n", msg);
//read(sockfd, msg, 10);
//sendto(sockfd, msg, n, 0, (struct sockaddr*) &cliaddr, len);
}
close(sockfd);
return 0;
}
Client Code:
#include <stdio.h> /* standard C i/o facilities */
#include <stdlib.h> /* needed for atoi() */
#include <unistd.h> /* Unix System Calls */
#include <sys/types.h> /* system data type definitions */
#include <sys/socket.h> /* socket specific definitions */
#include <netinet/in.h> /* INET constants and stuff */
#include <arpa/inet.h> /* IP address conversion stuff */
#include <string.h>
/* client program:
The following must passed in on the command line:
name of the server (argv[1])
port number of the server (argv[2])
*/
int main( int argc, char **argv )
{
int sockfd;
struct sockaddr_in servaddr;
int n;
//Ensure we have full args
if (argc != 3)
{
printf("Usage: client <server name> <server port>\n");
exit(1);
}
//Setup the port number
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(atoi(argv[2]));
//Setup the client IP
//inet_pton(AF_INET, argv[1], &servaddr.sin_addr)) <= 0
if( inet_aton(argv[1], &servaddr.sin_addr) == 0)
{
perror("Error with server IP\n");
exit(1);
}
//Create socket
if( (sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
{
perror("Error on socket\n");
exit(1);
}
/*if (connect(sockfd,(struct sockaddr *) &servaddr, sizeof(servaddr)) < 0 )
{
printf("Problem connecting socket\n");
exit(1);
}*/
//Send msg
char msg[10] = "123456789";
for(;;)
{
socklen_t len = sizeof(servaddr);
if( (sendto(sockfd, msg, strlen(msg), 0, (struct sockaddr*) &servaddr, len)) < 0 )
{
perror("Error on sendto():\n");
exit(1);
}
//write(sockfd, msg, strlen(msg));
//n = recvfrom(sockfd, msg2, 10, 0, NULL, NULL);
//printf("Msg: %s\n", msg2);
}
close(sockfd);
return 0;
}
First, your sender just sends data as fast as it possibly can, whether or not anyone or anything is listening. That's not a good thing to do.
Second, your receiver passes msg through to a %s printf specifier. But %s is only for C-style strings, and msg is not a C-style string (nothing puts a zero byte on the end of it). You also throw the return value of recvfrom away, so you can't convert it into a string because you have no idea how many of its bytes are valid.
Third, your server is creating a SOCK_STREAM socket!