Hi Guys,
c.maglie suggested I should also discuss a proposed contribution to the Arduino Library here.
originally I opened a pull request at github: https://github.com/arduino/Arduino/pull/1240 (so the code you find the code there, look at commit 2ac4e2f the other commit normalizes the tab/space usage in the library)
What did I do?
I've extended the Ethernet
library to make it possible to work with it in a non blocking way, which makes it easier to combine the library with handeling other task (handeling buttons, updating a screen etc) while a DHCP lease happens, or a packet is sent.
I've added non blocking variants for:
Dhcp::*
Dns::getHostbyName
Ethernet::begin (DHCP version)
Ethernet::maintain
EthernetClient::connect(*)
I welcome comments on the api-style, not really glad with all the names, but what would you guys think? I also need to think about a non blocking send, since it now loops until enough memory is available, I could make a variant which actually returns the bytes it could send, but I still have to think if this is the best way to do this.
There are 2 commits in this pull request, the Ethernet library was a mix of 3 different indentation styles, so I looked at the other parts and made commit a2ca62d to first only fix the formatting of the code. Then there is a new commit which actually changes the code, commit 2ac4e2f . This is actually an import from the work I started in DavyLandman/NBEthernet where I found out that the existing Ethernet library was already half non blocking.
So when reviewing, make sure to select just the correct commit (2ac4e2f), else in the github summary will claim I changed almost everything..
Impact on the size is quite minimal (for example DnsWebClient
):
old: Binary sketch size: 13,474 bytes (of a 30,720 byte maximum)
new: Binary sketch size: 14,980 bytes (of a 30,720 byte maximum)
The increase is primarily due to keeping a blocking variant.
I've tried to add "documentation" to the .h
files where I added a new method. But this here is an example, which uses all the new asynchronous methods. A user can mix them:
EthernetClient client;
static uint32_t next_connect;
void setup() {
// start the serial library:
Serial.begin(9600);
Serial.println("Initializing Ethernet controller");
Ethernet.initialize(mac);
int result = 0;
do {
result = Ethernet.initialized();
} while (result == 0);
if (result == 2) {
Serial.println("Failed to configure Ethernet using DHCP");
while (true) ;
}
Serial.println("Got IP adress");
Serial.println(Ethernet.localIP());
next_connect = millis() + TIMEOUT;
}
static byte maintaining = 0; // DHCP maintain happening
static byte insession = 0; // a HTTP GET is in session
static byte waiting = 0; // waiting for the connection to be established
static uint16_t bytes_read;
// crapy state machine, for real applications, use something better ;-)
void loop() {
if (maintaining) {
int result = Ethernet.maintainFinished();
maintaining = result == 0;
if (!maintaining) {
if (result == 1) {
Serial.println("DHCP succeeded");
Serial.println("Got IP adress");
Serial.println(Ethernet.localIP());
}
if (result == 2) {
Serial.println("DHCP failed");
}
}
return;
}
else {
maintaining = Ethernet.maintainNeeded() != DHCP_CHECK_NONE;
if (maintaining) {
Serial.println();
Serial.println();
Serial.println("DHCP timeout, getting new one");
return;
}
}
if (!insession) {
if (!waiting && millis() >= next_connect) {
next_connect += TIMEOUT;
Serial.println("Starting a new connection");
if (!client.initializeConnection("www.google.com", 80)) {
Serial.println("initializing connection failed");
}
else {
waiting = 1;
}
}
if (waiting && client.connectionInitialized()) {
if (client.connectionInitialized() == 1) {
Serial.println("connected");
client.println("GET /arduino HTTP/1.0");
client.println();
waiting = 0;
insession = 1;
bytes_read = 0;
}
else {
waiting = 0;
Serial.println("something went wrong with getting a connection");
}
}
}
else {
// we have a connection, and the GET has been sent.
// lets consume the response
if (client.available() && bytes_read < READLIMIT) {
char c = client.read();
Serial.print(c);
bytes_read++;
}
else if (client.available() && bytes_read == READLIMIT) {
client.flush();
}
if (!client.connected()) {
Serial.println();
Serial.println("disconnecting.");
client.stop();
insession = 0;
waiting = 0;
}
}
}
Cheers,
Davy Landman