diff options
Diffstat (limited to 'libraries/Ethernet')
19 files changed, 479 insertions, 141 deletions
diff --git a/libraries/Ethernet/Dhcp.cpp b/libraries/Ethernet/Dhcp.cpp index 62bbfeb..e4d27f7 100755 --- a/libraries/Ethernet/Dhcp.cpp +++ b/libraries/Ethernet/Dhcp.cpp @@ -11,13 +11,33 @@ int DhcpClass::beginWithDHCP(uint8_t *mac, unsigned long timeout, unsigned long responseTimeout)
{
- uint8_t dhcp_state = STATE_DHCP_START;
- uint8_t messageType = 0;
-
- // zero out _dhcpMacAddr, _dhcpSubnetMask, _dhcpGatewayIp, _dhcpLocalIp, _dhcpDhcpServerIp, _dhcpDnsServerIp
- memset(_dhcpMacAddr, 0, 26);
+ _dhcpLeaseTime=0;
+ _dhcpT1=0;
+ _dhcpT2=0;
+ _lastCheck=0;
+ _timeout = timeout;
+ _responseTimeout = responseTimeout;
+
+ // zero out _dhcpMacAddr
+ memset(_dhcpMacAddr, 0, 6);
+ reset_DHCP_lease();
memcpy((void*)_dhcpMacAddr, (void*)mac, 6);
+ _dhcp_state = STATE_DHCP_START;
+ return request_DHCP_lease();
+}
+
+void DhcpClass::reset_DHCP_lease(){
+ // zero out _dhcpSubnetMask, _dhcpGatewayIp, _dhcpLocalIp, _dhcpDhcpServerIp, _dhcpDnsServerIp
+ memset(_dhcpLocalIp, 0, 20);
+}
+
+//return:0 on error, 1 if request is sent and response is received
+int DhcpClass::request_DHCP_lease(){
+
+ uint8_t messageType = 0;
+
+
// Pick an initial transaction ID
_dhcpTransactionId = random(1UL, 2000UL);
@@ -35,55 +55,75 @@ int DhcpClass::beginWithDHCP(uint8_t *mac, unsigned long timeout, unsigned long unsigned long startTime = millis();
- while(dhcp_state != STATE_DHCP_LEASED)
+ while(_dhcp_state != STATE_DHCP_LEASED)
{
- if(dhcp_state == STATE_DHCP_START)
+ if(_dhcp_state == STATE_DHCP_START)
{
_dhcpTransactionId++;
send_DHCP_MESSAGE(DHCP_DISCOVER, ((millis() - startTime) / 1000));
- dhcp_state = STATE_DHCP_DISCOVER;
+ _dhcp_state = STATE_DHCP_DISCOVER;
+ }
+ else if(_dhcp_state == STATE_DHCP_REREQUEST){
+ _dhcpTransactionId++;
+ send_DHCP_MESSAGE(DHCP_REQUEST, ((millis() - startTime)/1000));
+ _dhcp_state = STATE_DHCP_REQUEST;
}
- else if(dhcp_state == STATE_DHCP_DISCOVER)
+ else if(_dhcp_state == STATE_DHCP_DISCOVER)
{
uint32_t respId;
- messageType = parseDHCPResponse(responseTimeout, respId);
+ messageType = parseDHCPResponse(_responseTimeout, respId);
if(messageType == DHCP_OFFER)
{
// We'll use the transaction ID that the offer came with,
// rather than the one we were up to
_dhcpTransactionId = respId;
send_DHCP_MESSAGE(DHCP_REQUEST, ((millis() - startTime) / 1000));
- dhcp_state = STATE_DHCP_REQUEST;
+ _dhcp_state = STATE_DHCP_REQUEST;
}
}
- else if(dhcp_state == STATE_DHCP_REQUEST)
+ else if(_dhcp_state == STATE_DHCP_REQUEST)
{
uint32_t respId;
- messageType = parseDHCPResponse(responseTimeout, respId);
+ messageType = parseDHCPResponse(_responseTimeout, respId);
if(messageType == DHCP_ACK)
{
- dhcp_state = STATE_DHCP_LEASED;
+ _dhcp_state = STATE_DHCP_LEASED;
result = 1;
+ //use default lease time if we didn't get it
+ if(_dhcpLeaseTime == 0){
+ _dhcpLeaseTime = DEFAULT_LEASE;
+ }
+ //calculate T1 & T2 if we didn't get it
+ if(_dhcpT1 == 0){
+ //T1 should be 50% of _dhcpLeaseTime
+ _dhcpT1 = _dhcpLeaseTime >> 1;
+ }
+ if(_dhcpT2 == 0){
+ //T2 should be 87.5% (7/8ths) of _dhcpLeaseTime
+ _dhcpT2 = _dhcpT1 << 1;
+ }
+ _renewInSec = _dhcpT1;
+ _rebindInSec = _dhcpT2;
}
else if(messageType == DHCP_NAK)
- dhcp_state = STATE_DHCP_START;
+ _dhcp_state = STATE_DHCP_START;
}
if(messageType == 255)
{
messageType = 0;
- dhcp_state = STATE_DHCP_START;
+ _dhcp_state = STATE_DHCP_START;
}
- if(result != 1 && ((millis() - startTime) > timeout))
+ if(result != 1 && ((millis() - startTime) > _timeout))
break;
}
// We're done with the socket now
_dhcpUdpSocket.stop();
_dhcpTransactionId++;
-
+
return result;
}
@@ -302,8 +342,26 @@ uint8_t DhcpClass::parseDHCPResponse(unsigned long responseTimeout, uint32_t& tr }
}
break;
-
+
+ case dhcpT1value :
+ opt_len = _dhcpUdpSocket.read();
+ _dhcpUdpSocket.read((uint8_t*)&_dhcpT1, sizeof(_dhcpT1));
+ _dhcpT1 = ntohl(_dhcpT1);
+ break;
+
+ case dhcpT2value :
+ opt_len = _dhcpUdpSocket.read();
+ _dhcpUdpSocket.read((uint8_t*)&_dhcpT2, sizeof(_dhcpT2));
+ _dhcpT2 = ntohl(_dhcpT2);
+ break;
+
case dhcpIPaddrLeaseTime :
+ opt_len = _dhcpUdpSocket.read();
+ _dhcpUdpSocket.read((uint8_t*)&_dhcpLeaseTime, sizeof(_dhcpLeaseTime));
+ _dhcpLeaseTime = ntohl(_dhcpLeaseTime);
+ _renewInSec = _dhcpLeaseTime;
+ break;
+
default :
opt_len = _dhcpUdpSocket.read();
// Skip over the rest of this option
@@ -322,6 +380,68 @@ uint8_t DhcpClass::parseDHCPResponse(unsigned long responseTimeout, uint32_t& tr return type;
}
+
+/*
+ returns:
+ 0/DHCP_CHECK_NONE: nothing happened
+ 1/DHCP_CHECK_RENEW_FAIL: renew failed
+ 2/DHCP_CHECK_RENEW_OK: renew success
+ 3/DHCP_CHECK_REBIND_FAIL: rebind fail
+ 4/DHCP_CHECK_REBIND_OK: rebind success
+*/
+int DhcpClass::checkLease(){
+ //this uses a signed / unsigned trick to deal with millis overflow
+ unsigned long now = millis();
+ signed long snow = (long)now;
+ int rc=DHCP_CHECK_NONE;
+ if (_lastCheck != 0){
+ signed long factor;
+ //calc how many ms past the timeout we are
+ factor = snow - (long)_secTimeout;
+ //if on or passed the timeout, reduce the counters
+ if ( factor >= 0 ){
+ //next timeout should be now plus 1000 ms minus parts of second in factor
+ _secTimeout = snow + 1000 - factor % 1000;
+ //how many seconds late are we, minimum 1
+ factor = factor / 1000 +1;
+
+ //reduce the counters by that mouch
+ //if we can assume that the cycle time (factor) is fairly constant
+ //and if the remainder is less than cycle time * 2
+ //do it early instead of late
+ if(_renewInSec < factor*2 )
+ _renewInSec = 0;
+ else
+ _renewInSec -= factor;
+
+ if(_rebindInSec < factor*2 )
+ _rebindInSec = 0;
+ else
+ _rebindInSec -= factor;
+ }
+
+ //if we have a lease but should renew, do it
+ if (_dhcp_state == STATE_DHCP_LEASED && _renewInSec <=0){
+ _dhcp_state = STATE_DHCP_REREQUEST;
+ rc = 1 + request_DHCP_lease();
+ }
+
+ //if we have a lease or is renewing but should bind, do it
+ if( (_dhcp_state == STATE_DHCP_LEASED || _dhcp_state == STATE_DHCP_START) && _rebindInSec <=0){
+ //this should basically restart completely
+ _dhcp_state = STATE_DHCP_START;
+ reset_DHCP_lease();
+ rc = 3 + request_DHCP_lease();
+ }
+ }
+ else{
+ _secTimeout = snow + 1000;
+ }
+
+ _lastCheck = now;
+ return rc;
+}
+
IPAddress DhcpClass::getLocalIp()
{
return IPAddress(_dhcpLocalIp);
diff --git a/libraries/Ethernet/Dhcp.h b/libraries/Ethernet/Dhcp.h index 149876d..4a47936 100755 --- a/libraries/Ethernet/Dhcp.h +++ b/libraries/Ethernet/Dhcp.h @@ -45,6 +45,13 @@ #define MAX_DHCP_OPT 16
#define HOST_NAME "WIZnet"
+#define DEFAULT_LEASE (900) //default lease time in seconds
+
+#define DHCP_CHECK_NONE (0)
+#define DHCP_CHECK_RENEW_FAIL (1)
+#define DHCP_CHECK_RENEW_OK (2)
+#define DHCP_CHECK_REBIND_FAIL (3)
+#define DHCP_CHECK_REBIND_OK (4)
enum
{
@@ -139,8 +146,19 @@ private: uint8_t _dhcpGatewayIp[4];
uint8_t _dhcpDhcpServerIp[4];
uint8_t _dhcpDnsServerIp[4];
+ uint32_t _dhcpLeaseTime;
+ uint32_t _dhcpT1, _dhcpT2;
+ signed long _renewInSec;
+ signed long _rebindInSec;
+ signed long _lastCheck;
+ unsigned long _timeout;
+ unsigned long _responseTimeout;
+ unsigned long _secTimeout;
+ uint8_t _dhcp_state;
EthernetUDP _dhcpUdpSocket;
+ int request_DHCP_lease();
+ void reset_DHCP_lease();
void presend_DHCP();
void send_DHCP_MESSAGE(uint8_t, uint16_t);
void printByte(char *, uint8_t);
@@ -154,6 +172,7 @@ public: IPAddress getDnsServerIp();
int beginWithDHCP(uint8_t *, unsigned long timeout = 60000, unsigned long responseTimeout = 4000);
+ int checkLease();
};
#endif
diff --git a/libraries/Ethernet/Ethernet.cpp b/libraries/Ethernet/Ethernet.cpp index c298f3d..5d28f71 100644 --- a/libraries/Ethernet/Ethernet.cpp +++ b/libraries/Ethernet/Ethernet.cpp @@ -10,7 +10,8 @@ uint16_t EthernetClass::_server_port[MAX_SOCK_NUM] = { int EthernetClass::begin(uint8_t *mac_address) { - DhcpClass dhcp; + _dhcp = new DhcpClass(); + // Initialise the basic info W5100.init(); @@ -18,15 +19,15 @@ int EthernetClass::begin(uint8_t *mac_address) W5100.setIPAddress(IPAddress(0,0,0,0).raw_address()); // Now try to get our config info from a DHCP server - int ret = dhcp.beginWithDHCP(mac_address); + int ret = _dhcp->beginWithDHCP(mac_address); if(ret == 1) { // We've successfully found a DHCP server and got our configuration info, so set things // accordingly - W5100.setIPAddress(dhcp.getLocalIp().raw_address()); - W5100.setGatewayIp(dhcp.getGatewayIp().raw_address()); - W5100.setSubnetMask(dhcp.getSubnetMask().raw_address()); - _dnsServerAddress = dhcp.getDnsServerIp(); + W5100.setIPAddress(_dhcp->getLocalIp().raw_address()); + W5100.setGatewayIp(_dhcp->getGatewayIp().raw_address()); + W5100.setSubnetMask(_dhcp->getSubnetMask().raw_address()); + _dnsServerAddress = _dhcp->getDnsServerIp(); } return ret; @@ -66,6 +67,31 @@ void EthernetClass::begin(uint8_t *mac, IPAddress local_ip, IPAddress dns_server _dnsServerAddress = dns_server; } +int EthernetClass::maintain(){ + int rc = DHCP_CHECK_NONE; + if(_dhcp != NULL){ + //we have a pointer to dhcp, use it + rc = _dhcp->checkLease(); + switch ( rc ){ + case DHCP_CHECK_NONE: + //nothing done + break; + case DHCP_CHECK_RENEW_OK: + case DHCP_CHECK_REBIND_OK: + //we might have got a new IP. + W5100.setIPAddress(_dhcp->getLocalIp().raw_address()); + W5100.setGatewayIp(_dhcp->getGatewayIp().raw_address()); + W5100.setSubnetMask(_dhcp->getSubnetMask().raw_address()); + _dnsServerAddress = _dhcp->getDnsServerIp(); + break; + default: + //this is actually a error, it will retry though + break; + } + } + return rc; +} + IPAddress EthernetClass::localIP() { IPAddress ret; diff --git a/libraries/Ethernet/Ethernet.h b/libraries/Ethernet/Ethernet.h index c916dda..2a07ff3 100644 --- a/libraries/Ethernet/Ethernet.h +++ b/libraries/Ethernet/Ethernet.h @@ -6,12 +6,14 @@ #include "IPAddress.h" #include "EthernetClient.h" #include "EthernetServer.h" +#include "Dhcp.h" #define MAX_SOCK_NUM 4 class EthernetClass { private: IPAddress _dnsServerAddress; + DhcpClass* _dhcp; public: static uint8_t _state[MAX_SOCK_NUM]; static uint16_t _server_port[MAX_SOCK_NUM]; @@ -23,6 +25,7 @@ public: void begin(uint8_t *mac_address, IPAddress local_ip, IPAddress dns_server); void begin(uint8_t *mac_address, IPAddress local_ip, IPAddress dns_server, IPAddress gateway); void begin(uint8_t *mac_address, IPAddress local_ip, IPAddress dns_server, IPAddress gateway, IPAddress subnet); + int maintain(); IPAddress localIP(); IPAddress subnetMask(); diff --git a/libraries/Ethernet/EthernetClient.cpp b/libraries/Ethernet/EthernetClient.cpp index a77a62b..9885efb 100644 --- a/libraries/Ethernet/EthernetClient.cpp +++ b/libraries/Ethernet/EthernetClient.cpp @@ -41,7 +41,7 @@ int EthernetClient::connect(IPAddress ip, uint16_t port) { for (int i = 0; i < MAX_SOCK_NUM; i++) { uint8_t s = W5100.readSnSR(i); - if (s == SnSR::CLOSED || s == SnSR::FIN_WAIT) { + if (s == SnSR::CLOSED || s == SnSR::FIN_WAIT || s == SnSR::CLOSE_WAIT) { _sock = i; break; } diff --git a/libraries/Ethernet/EthernetUdp.cpp b/libraries/Ethernet/EthernetUdp.cpp index 9c752fc..3760052 100644 --- a/libraries/Ethernet/EthernetUdp.cpp +++ b/libraries/Ethernet/EthernetUdp.cpp @@ -52,15 +52,16 @@ uint8_t EthernetUDP::begin(uint16_t port) { return 0; _port = port; + _remaining = 0; socket(_sock, SnMR::UDP, _port, 0); return 1; } -/* Is data available in rx buffer? Returns 0 if no, number of available bytes if yes. - * returned value includes 8 byte UDP header!*/ +/* return number of bytes available in the current packet, + will return zero if parsePacket hasn't been called yet */ int EthernetUDP::available() { - return W5100.getRXReceivedSize(_sock); + return _remaining; } /* Release any resources being used by this EthernetUDP instance */ @@ -116,11 +117,14 @@ size_t EthernetUDP::write(const uint8_t *buffer, size_t size) int EthernetUDP::parsePacket() { - if (available() > 0) + // discard any remaining bytes in the last packet + flush(); + + if (W5100.getRXReceivedSize(_sock) > 0) { //HACK - hand-parse the UDP packet using TCP recv method uint8_t tmpBuf[8]; - int ret =0; + int ret =0; //read 8 header bytes and get IP and port from it ret = recv(_sock,tmpBuf,8); if (ret > 0) @@ -128,8 +132,11 @@ int EthernetUDP::parsePacket() _remoteIP = tmpBuf; _remotePort = tmpBuf[4]; _remotePort = (_remotePort << 8) + tmpBuf[5]; + _remaining = tmpBuf[6]; + _remaining = (_remaining << 8) + tmpBuf[7]; + // When we get here, any remaining bytes are the data - ret = available(); + ret = _remaining; } return ret; } @@ -140,34 +147,58 @@ int EthernetUDP::parsePacket() int EthernetUDP::read() { uint8_t byte; - if (recv(_sock, &byte, 1) > 0) + + if ((_remaining > 0) && (recv(_sock, &byte, 1) > 0)) { // We read things without any problems + _remaining--; return byte; } + // If we get here, there's no data available return -1; } int EthernetUDP::read(unsigned char* buffer, size_t len) { - /* In the readPacket that copes with truncating packets, the buffer was - filled with this code. Not sure why it loops round reading out a byte - at a time. - int i; - for(i=0;i<(int)bufLen;i++) { - recv(_sock,tmpBuf,1); - buf[i]=tmpBuf[0]; + + if (_remaining > 0) + { + + int got; + + if (_remaining <= len) + { + // data should fit in the buffer + got = recv(_sock, buffer, _remaining); + } + else + { + // too much data for the buffer, + // grab as much as will fit + got = recv(_sock, buffer, len); + } + + if (got > 0) + { + _remaining -= got; + return got; + } + } - */ - return recv(_sock, buffer, len); + + // If we get here, there's no data available or recv failed + return -1; + } int EthernetUDP::peek() { uint8_t b; - // Unlike recv, peek doesn't check to see if there's any data available, so we must - if (!available()) + // Unlike recv, peek doesn't check to see if there's any data available, so we must. + // If the user hasn't called parsePacket yet then return nothing otherwise they + // may get the UDP header + if (!_remaining) return -1; ::peek(_sock, &b); return b; @@ -175,7 +206,11 @@ int EthernetUDP::peek() void EthernetUDP::flush() { - while (available()) + // could this fail (loop endlessly) if _remaining > 0 and recv in read fails? + // should only occur if recv fails after telling us the data is there, lets + // hope the w5100 always behaves :) + + while (_remaining) { read(); } diff --git a/libraries/Ethernet/EthernetUdp.h b/libraries/Ethernet/EthernetUdp.h index 9a2b653..8a6b7ab 100644 --- a/libraries/Ethernet/EthernetUdp.h +++ b/libraries/Ethernet/EthernetUdp.h @@ -48,6 +48,7 @@ private: IPAddress _remoteIP; // remote IP address for the incoming packet whilst it's being processed uint16_t _remotePort; // remote port for the incoming packet whilst it's being processed uint16_t _offset; // offset into the packet being sent + uint16_t _remaining; // remaining bytes of incoming packet yet to be processed public: EthernetUDP(); // Constructor diff --git a/libraries/Ethernet/examples/ChatServer/ChatServer.ino b/libraries/Ethernet/examples/ChatServer/ChatServer.ino index 9f819fd..d50e5a6 100644 --- a/libraries/Ethernet/examples/ChatServer/ChatServer.ino +++ b/libraries/Ethernet/examples/ChatServer/ChatServer.ino @@ -12,7 +12,7 @@ created 18 Dec 2009 by David A. Mellis - modified 10 August 2010 + modified 9 Apr 2012 by Tom Igoe */ @@ -23,41 +23,57 @@ // Enter a MAC address and IP address for your controller below. // The IP address will be dependent on your local network. // gateway and subnet are optional: -byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; +byte mac[] = { + 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; IPAddress ip(192,168,1, 177); IPAddress gateway(192,168,1, 1); IPAddress subnet(255, 255, 0, 0); + // telnet defaults to port 23 EthernetServer server(23); -boolean gotAMessage = false; // whether or not you got a message from the client yet +boolean alreadyConnected = false; // whether or not the client was connected previously void setup() { // initialize the ethernet device Ethernet.begin(mac, ip, gateway, subnet); // start listening for clients server.begin(); - // open the serial port + // Open serial communications and wait for port to open: Serial.begin(9600); + while (!Serial) { + ; // wait for serial port to connect. Needed for Leonardo only + } + + + Serial.print("Chat server address:"); + Serial.println(Ethernet.localIP()); } void loop() { // wait for a new client: EthernetClient client = server.available(); - + // when the client sends the first byte, say hello: if (client) { - if (!gotAMessage) { + if (!alreadyConnected) { + // clead out the input buffer: + client.flush(); Serial.println("We have a new client"); client.println("Hello, client!"); - gotAMessage = true; + alreadyConnected = true; + } + + if (client.available() > 0) { + // read the bytes incoming from the client: + char thisChar = client.read(); + // echo the bytes back to the client: + server.write(thisChar); + // echo the bytes to the server as well: + Serial.write(thisChar); } - - // read the bytes incoming from the client: - char thisChar = client.read(); - // echo the bytes back to the client: - server.write(thisChar); - // echo the bytes to the server as well: - Serial.print(thisChar); } } + + + diff --git a/libraries/Ethernet/examples/DhcpAddressPrinter/DhcpAddressPrinter.ino b/libraries/Ethernet/examples/DhcpAddressPrinter/DhcpAddressPrinter.ino index 630dd17..5eaaf24 100644 --- a/libraries/Ethernet/examples/DhcpAddressPrinter/DhcpAddressPrinter.ino +++ b/libraries/Ethernet/examples/DhcpAddressPrinter/DhcpAddressPrinter.ino @@ -9,6 +9,7 @@ * Ethernet shield attached to pins 10, 11, 12, 13 created 12 April 2011 + modified 9 Apr 2012 by Tom Igoe */ @@ -27,8 +28,13 @@ byte mac[] = { EthernetClient client; void setup() { - // start the serial library: + // Open serial communications and wait for port to open: Serial.begin(9600); + // this check is only needed on the Leonardo: + while (!Serial) { + ; // wait for serial port to connect. Needed for Leonardo only + } + // start the Ethernet connection: if (Ethernet.begin(mac) == 0) { Serial.println("Failed to configure Ethernet using DHCP"); diff --git a/libraries/Ethernet/examples/DhcpChatServer/DhcpChatServer.ino b/libraries/Ethernet/examples/DhcpChatServer/DhcpChatServer.ino index 5082054..09cbd43 100644 --- a/libraries/Ethernet/examples/DhcpChatServer/DhcpChatServer.ino +++ b/libraries/Ethernet/examples/DhcpChatServer/DhcpChatServer.ino @@ -12,6 +12,7 @@ * Ethernet shield attached to pins 10, 11, 12, 13 created 21 May 2011 + modified 9 Apr 2012 by Tom Igoe Based on ChatServer example by David A. Mellis @@ -34,8 +35,14 @@ EthernetServer server(23); boolean gotAMessage = false; // whether or not you got a message from the client yet void setup() { - // open the serial port + // Open serial communications and wait for port to open: Serial.begin(9600); + // this check is only needed on the Leonardo: + while (!Serial) { + ; // wait for serial port to connect. Needed for Leonardo only + } + + // start the Ethernet connection: Serial.println("Trying to get an IP address using DHCP"); if (Ethernet.begin(mac) == 0) { diff --git a/libraries/Ethernet/examples/DnsWebClient/DnsWebClient.ino b/libraries/Ethernet/examples/DnsWebClient/DnsWebClient.ino index 5c7a53a..c14abf4 100644 --- a/libraries/Ethernet/examples/DnsWebClient/DnsWebClient.ino +++ b/libraries/Ethernet/examples/DnsWebClient/DnsWebClient.ino @@ -9,7 +9,7 @@ created 18 Dec 2009 by David A. Mellis - modified 12 April 2011 + modified 9 Apr 2012 by Tom Igoe, based on work by Adrian McEwen */ @@ -28,8 +28,13 @@ char serverName[] = "www.google.com"; EthernetClient client; void setup() { - // start the serial library: + // Open serial communications and wait for port to open: Serial.begin(9600); + while (!Serial) { + ; // wait for serial port to connect. Needed for Leonardo only + } + + // start the Ethernet connection: if (Ethernet.begin(mac) == 0) { Serial.println("Failed to configure Ethernet using DHCP"); diff --git a/libraries/Ethernet/examples/PachubeClient/PachubeClient.ino b/libraries/Ethernet/examples/PachubeClient/PachubeClient.ino index a169443..dfd2d40 100644 --- a/libraries/Ethernet/examples/PachubeClient/PachubeClient.ino +++ b/libraries/Ethernet/examples/PachubeClient/PachubeClient.ino @@ -6,15 +6,20 @@ the Adafruit Ethernet shield, either one will work, as long as it's got a Wiznet Ethernet module on board. + This example has been updated to use version 2.0 of the Pachube.com API. + To make it work, create a feed with a datastream, and give it the ID + sensor1. Or change the code below to match your feed. + + Circuit: * Analog sensor attached to analog in 0 * Ethernet shield attached to pins 10, 11, 12, 13 created 15 March 2010 - updated 26 Oct 2011 - by Tom Igoe + modified 9 Apr 2012 + by Tom Igoe with input from Usman Haque and Joe Saavedra - http://www.tigoe.net/pcomp/code/category/arduinowiring/873 +http://arduino.cc/en/Tutorial/PachubeClient This code is in the public domain. */ @@ -22,6 +27,10 @@ #include <SPI.h> #include <Ethernet.h> +#define APIKEY "YOUR API KEY GOES HERE" // replace your pachube api key here +#define FEEDID 00000 // replace your feed ID +#define USERAGENT "My Project" // user agent is the project name + // assign a MAC address for the ethernet controller. // Newer Ethernet shields have a MAC address printed on a sticker on the shield // fill in your address here: @@ -34,26 +43,27 @@ IPAddress ip(10,0,1,20); // initialize the library instance: EthernetClient client; -long lastConnectionTime = 0; // last time you connected to the server, in milliseconds -boolean lastConnected = false; // state of the connection last time through the main loop -const int postingInterval = 10000; //delay between updates to Pachube.com +// if you don't want to use DNS (and reduce your sketch size) +// use the numeric IP instead of the name for the server: +IPAddress server(216,52,233,122); // numeric IP for api.pachube.com +//char server[] = "api.pachube.com"; // name address for pachube API + +unsigned long lastConnectionTime = 0; // last time you connected to the server, in milliseconds +boolean lastConnected = false; // state of the connection last time through the main loop +const unsigned long postingInterval = 10*1000; //delay between updates to Pachube.com void setup() { - // start serial port: + // Open serial communications and wait for port to open: Serial.begin(9600); - // start the Ethernet connection: - if (Ethernet.begin(mac) == 0) { - Serial.println("Failed to configure Ethernet using DHCP"); - // no point in carrying on, so do nothing forevermore: - for(;;) - ; + while (!Serial) { + ; // wait for serial port to connect. Needed for Leonardo only } - // give the ethernet module time to boot up: - delay(1000); - // start the Ethernet connection: + + + // start the Ethernet connection: if (Ethernet.begin(mac) == 0) { Serial.println("Failed to configure Ethernet using DHCP"); - // Configure manually: + // DHCP failed, so use a fixed IP address: Ethernet.begin(mac, ip); } } @@ -91,34 +101,43 @@ void loop() { // this method makes a HTTP connection to the server: void sendData(int thisData) { // if there's a successful connection: - if (client.connect("www.pachube.com", 80)) { + if (client.connect(server, 80)) { Serial.println("connecting..."); - // send the HTTP PUT request. - // fill in your feed address here: - client.print("PUT /api/YOUR_FEED_HERE.csv HTTP/1.1\n"); - client.print("Host: www.pachube.com\n"); - // fill in your Pachube API key here: - client.print("X-PachubeApiKey: YOUR_KEY_HERE\n"); + // send the HTTP PUT request: + client.print("PUT /v2/feeds/"); + client.print(FEEDID); + client.println(".csv HTTP/1.1"); + client.println("Host: api.pachube.com"); + client.print("X-PachubeApiKey: "); + client.println(APIKEY); + client.print("User-Agent: "); + client.println(USERAGENT); client.print("Content-Length: "); // calculate the length of the sensor reading in bytes: - int thisLength = getLength(thisData); - client.println(thisLength, DEC); + // 8 bytes for "sensor1," + number of digits of the data: + int thisLength = 8 + getLength(thisData); + client.println(thisLength); // last pieces of the HTTP PUT request: - client.print("Content-Type: text/csv\n"); - client.println("Connection: close\n"); + client.println("Content-Type: text/csv"); + client.println("Connection: close"); + client.println(); // here's the actual content of the PUT request: - client.println(thisData, DEC); - - // note the time that the connection was made: - lastConnectionTime = millis(); + client.print("sensor1,"); + client.println(thisData); + } else { // if you couldn't make a connection: Serial.println("connection failed"); + Serial.println(); + Serial.println("disconnecting."); + client.stop(); } + // note the time that the connection was made or attempted: + lastConnectionTime = millis(); } diff --git a/libraries/Ethernet/examples/PachubeClientString/PachubeClientString.ino b/libraries/Ethernet/examples/PachubeClientString/PachubeClientString.ino index 4a03100..2a96e9f 100644 --- a/libraries/Ethernet/examples/PachubeClientString/PachubeClientString.ino +++ b/libraries/Ethernet/examples/PachubeClientString/PachubeClientString.ino @@ -1,11 +1,15 @@ /* - Pachube sensor client with Strings + Cosm sensor client with Strings - This sketch connects an analog sensor to Pachube (http://www.pachube.com) + This sketch connects an analog sensor to Cosm (http://www.cosm.com) using a Wiznet Ethernet shield. You can use the Arduino Ethernet shield, or the Adafruit Ethernet shield, either one will work, as long as it's got a Wiznet Ethernet module on board. + This example has been updated to use version 2.0 of the Cosm.com API. + To make it work, create a feed with two datastreams, and give them the IDs + sensor1 and sensor2. Or change the code below to match your feed. + This example uses the String library, which is part of the Arduino core from version 0019. @@ -14,9 +18,10 @@ * Ethernet shield attached to pins 10, 11, 12, 13 created 15 March 2010 - updated 26 Oct 2011 - by Tom Igoe + modified 9 Apr 2012 + by Tom Igoe with input from Usman Haque and Joe Saavedra + http://arduino.cc/en/Tutorial/CosmClientString This code is in the public domain. */ @@ -24,10 +29,17 @@ #include <SPI.h> #include <Ethernet.h> + +/#define APIKEY "YOUR API KEY GOES HERE" // replace your Cosm api key here +#define FEEDID 00000 // replace your feed ID +#define USERAGENT "My Project" // user agent is the project name + + // assign a MAC address for the ethernet controller. // fill in your address here: -byte mac[] = { + byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED}; + // fill in an available IP address on your network here, // for manual configuration: IPAddress ip(10,0,1,20); @@ -35,19 +47,29 @@ IPAddress ip(10,0,1,20); // initialize the library instance: EthernetClient client; -long lastConnectionTime = 0; // last time you connected to the server, in milliseconds -boolean lastConnected = false; // state of the connection last time through the main loop -const int postingInterval = 10000; //delay between updates to Pachube.com +// if you don't want to use DNS (and reduce your sketch size) +// use the numeric IP instead of the name for the server: +IPAddress server(216,52,233,121); // numeric IP for api.cosm.com +//char server[] = "api.cosm.com"; // name address for Cosm API + +unsigned long lastConnectionTime = 0; // last time you connected to the server, in milliseconds +boolean lastConnected = false; // state of the connection last time through the main loop +const unsigned long postingInterval = 10*1000; //delay between updates to Cosm.com void setup() { - // start serial port: + // Open serial communications and wait for port to open: Serial.begin(9600); + while (!Serial) { + ; // wait for serial port to connect. Needed for Leonardo only + } + + // give the ethernet module time to boot up: delay(1000); // start the Ethernet connection: if (Ethernet.begin(mac) == 0) { Serial.println("Failed to configure Ethernet using DHCP"); - // Configure manually: + // DHCP failed, so use a fixed IP address: Ethernet.begin(mac, ip); } } @@ -56,13 +78,15 @@ void loop() { // read the analog sensor: int sensorReading = analogRead(A0); // convert the data to a String to send it: - String dataString = String(sensorReading); + + String dataString = "sensor1,"; + dataString += sensorReading; // you can append multiple readings to this String if your - // pachube feed is set up to handle multiple values: + // Cosm feed is set up to handle multiple values: int otherSensorReading = analogRead(A1); - dataString += ","; - dataString += String(otherSensorReading); + dataString += "\nsensor2,"; + dataString += otherSensorReading; // if there's incoming data from the net connection. // send it out the serial port. This is for debugging @@ -81,7 +105,7 @@ void loop() { } // if you're not connected, and ten seconds have passed since - // your last connection, then connect again and send data: + // your last connection, then connect again and send data: if(!client.connected() && (millis() - lastConnectionTime > postingInterval)) { sendData(dataString); } @@ -93,29 +117,36 @@ void loop() { // this method makes a HTTP connection to the server: void sendData(String thisData) { // if there's a successful connection: - if (client.connect("www.pachube.com", 80)) { + if (client.connect(server, 80)) { Serial.println("connecting..."); - // send the HTTP PUT request. - // fill in your feed address here: - client.print("PUT /api/YOUR_FEED_HERE.csv HTTP/1.1\n"); - client.print("Host: www.pachube.com\n"); - // fill in your Pachube API key here: - client.print("X-PachubeApiKey: YOUR_KEY_HERE\n"); + // send the HTTP PUT request: + client.print("PUT /v2/feeds/"); + client.print(FEEDID); + client.println(".csv HTTP/1.1"); + client.println("Host: api.cosm.com"); + client.print("X-CosmApiKey: "); + client.println(APIKEY); + client.print("User-Agent: "); + client.println(USERAGENT); client.print("Content-Length: "); - client.println(thisData.length(), DEC); + client.println(thisData.length()); // last pieces of the HTTP PUT request: - client.print("Content-Type: text/csv\n"); - client.println("Connection: close\n"); + client.println("Content-Type: text/csv"); + client.println("Connection: close"); + client.println(); // here's the actual content of the PUT request: client.println(thisData); - - // note the time that the connection was made: - lastConnectionTime = millis(); } else { // if you couldn't make a connection: Serial.println("connection failed"); + Serial.println(); + Serial.println("disconnecting."); + client.stop(); } + // note the time that the connection was made or attempted: + lastConnectionTime = millis(); } + diff --git a/libraries/Ethernet/examples/TelnetClient/TelnetClient.ino b/libraries/Ethernet/examples/TelnetClient/TelnetClient.ino index 5cf1ad8..3457125 100644 --- a/libraries/Ethernet/examples/TelnetClient/TelnetClient.ino +++ b/libraries/Ethernet/examples/TelnetClient/TelnetClient.ino @@ -13,6 +13,7 @@ * Ethernet shield attached to pins 10, 11, 12, 13 created 14 Sep 2010 + modified 9 Apr 2012 by Tom Igoe */ @@ -38,8 +39,13 @@ EthernetClient client; void setup() { // start the Ethernet connection: Ethernet.begin(mac, ip); - // start the serial library: + // Open serial communications and wait for port to open: Serial.begin(9600); + while (!Serial) { + ; // wait for serial port to connect. Needed for Leonardo only + } + + // give the Ethernet shield a second to initialize: delay(1000); Serial.println("connecting..."); diff --git a/libraries/Ethernet/examples/TwitterClient/TwitterClient.ino b/libraries/Ethernet/examples/TwitterClient/TwitterClient.ino index f113e17..3587d72 100644 --- a/libraries/Ethernet/examples/TwitterClient/TwitterClient.ino +++ b/libraries/Ethernet/examples/TwitterClient/TwitterClient.ino @@ -14,9 +14,10 @@ version 0019. Circuit: - * Ethernet shield attached to pins 10, 11, 12, 13 + * Ethernet shield attached to pins 10, 11, 12, 13 created 21 May 2011 + modified 9 Apr 2012 by Tom Igoe This code is in the public domain. @@ -35,12 +36,12 @@ IPAddress ip(192,168,1,20); // initialize the library instance: EthernetClient client; -const int requestInterval = 60000; // delay between requests +const unsigned long requestInterval = 60000; // delay between requests char serverName[] = "api.twitter.com"; // twitter URL boolean requested; // whether you've made a request since connecting -long lastAttemptTime = 0; // last time you connected to the server, in milliseconds +unsigned long lastAttemptTime = 0; // last time you connected to the server, in milliseconds String currentLine = ""; // string to hold the text from server String tweet = ""; // string to hold the tweet @@ -51,13 +52,22 @@ void setup() { currentLine.reserve(256); tweet.reserve(150); -// initialize serial: + // Open serial communications and wait for port to open: Serial.begin(9600); + while (!Serial) { + ; // wait for serial port to connect. Needed for Leonardo only + } + + // attempt a DHCP connection: + Serial.println("Attempting to get an IP address using DHCP:"); if (!Ethernet.begin(mac)) { // if DHCP fails, start with a hard-coded address: + Serial.println("failed to get an IP address using DHCP, trying manually"); Ethernet.begin(mac, ip); } + Serial.print("My address:"); + Serial.println(Ethernet.localIP()); // connect to Twitter: connectToServer(); } @@ -114,7 +124,7 @@ void connectToServer() { Serial.println("connecting to server..."); if (client.connect(serverName, 80)) { Serial.println("making HTTP request..."); - // make HTTP GET request to twitter: + // make HTTP GET request to twitter: client.println("GET /1/statuses/user_timeline.xml?screen_name=arduino&count=1 HTTP/1.1"); client.println("HOST: api.twitter.com"); client.println(); @@ -122,3 +132,4 @@ void connectToServer() { // note the time of this connect attempt: lastAttemptTime = millis(); } + diff --git a/libraries/Ethernet/examples/UdpNtpClient/UdpNtpClient.ino b/libraries/Ethernet/examples/UdpNtpClient/UdpNtpClient.ino index b4e24b8..93ffe39 100644 --- a/libraries/Ethernet/examples/UdpNtpClient/UdpNtpClient.ino +++ b/libraries/Ethernet/examples/UdpNtpClient/UdpNtpClient.ino @@ -9,7 +9,7 @@ created 4 Sep 2010 by Michael Margolis - modified 17 Sep 2010 + modified 9 Apr 2012 by Tom Igoe This code is in the public domain. @@ -38,7 +38,12 @@ EthernetUDP Udp; void setup() { + // Open serial communications and wait for port to open: Serial.begin(9600); + while (!Serial) { + ; // wait for serial port to connect. Needed for Leonardo only + } + // start Ethernet and UDP if (Ethernet.begin(mac) == 0) { diff --git a/libraries/Ethernet/examples/WebClient/WebClient.ino b/libraries/Ethernet/examples/WebClient/WebClient.ino index 1806854..5d5d7f2 100644 --- a/libraries/Ethernet/examples/WebClient/WebClient.ino +++ b/libraries/Ethernet/examples/WebClient/WebClient.ino @@ -8,6 +8,7 @@ * Ethernet shield attached to pins 10, 11, 12, 13 created 18 Dec 2009 + modified 9 Apr 2012 by David A. Mellis */ @@ -26,8 +27,12 @@ IPAddress server(173,194,33,104); // Google EthernetClient client; void setup() { - // start the serial library: + // Open serial communications and wait for port to open: Serial.begin(9600); + while (!Serial) { + ; // wait for serial port to connect. Needed for Leonardo only + } + // start the Ethernet connection: if (Ethernet.begin(mac) == 0) { Serial.println("Failed to configure Ethernet using DHCP"); diff --git a/libraries/Ethernet/examples/WebServer/WebServer.ino b/libraries/Ethernet/examples/WebServer/WebServer.ino index 6837f83..ce8dbb1 100644 --- a/libraries/Ethernet/examples/WebServer/WebServer.ino +++ b/libraries/Ethernet/examples/WebServer/WebServer.ino @@ -10,7 +10,7 @@ created 18 Dec 2009 by David A. Mellis - modified 4 Sep 2010 + modified 9 Apr 2012 by Tom Igoe */ @@ -20,7 +20,8 @@ // Enter a MAC address and IP address for your controller below. // The IP address will be dependent on your local network: -byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; +byte mac[] = { + 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; IPAddress ip(192,168,1, 177); // Initialize the Ethernet server library @@ -28,23 +29,33 @@ IPAddress ip(192,168,1, 177); // (port 80 is default for HTTP): EthernetServer server(80); -void setup() -{ +void setup() { + // Open serial communications and wait for port to open: + Serial.begin(9600); + while (!Serial) { + ; // wait for serial port to connect. Needed for Leonardo only + } + + // start the Ethernet connection and the server: Ethernet.begin(mac, ip); server.begin(); + Serial.print("server is at "); + Serial.println(Ethernet.localIP()); } -void loop() -{ + +void loop() { // listen for incoming clients EthernetClient client = server.available(); if (client) { + Serial.println("new client"); // an http request ends with a blank line boolean currentLineIsBlank = true; while (client.connected()) { if (client.available()) { char c = client.read(); + Serial.write(c); // if you've gotten to the end of the line (received a newline // character) and the line is blank, the http request has ended, // so you can send a reply @@ -52,16 +63,22 @@ void loop() // send a standard http response header client.println("HTTP/1.1 200 OK"); client.println("Content-Type: text/html"); + client.println("Connnection: close"); client.println(); - + client.println("<!DOCTYPE HTML>"); + client.println("<html>"); + // add a meta refresh tag, so the browser pulls again every 5 seconds: + client.println("<meta http-equiv=\"refresh\" content=\"5\">"); // output the value of each analog input pin for (int analogChannel = 0; analogChannel < 6; analogChannel++) { + int sensorReading = analogRead(analogChannel); client.print("analog input "); client.print(analogChannel); client.print(" is "); - client.print(analogRead(analogChannel)); - client.println("<br />"); + client.print(sensorReading); + client.println("<br />"); } + client.println("</html>"); break; } if (c == '\n') { @@ -78,5 +95,7 @@ void loop() delay(1); // close the connection: client.stop(); + Serial.println("client disonnected"); } } + diff --git a/libraries/Ethernet/utility/w5100.h b/libraries/Ethernet/utility/w5100.h index 153aedb..8dccd9f 100755 --- a/libraries/Ethernet/utility/w5100.h +++ b/libraries/Ethernet/utility/w5100.h @@ -327,7 +327,11 @@ private: inline static void initSS() { DDRB |= _BV(4); }; inline static void setSS() { PORTB &= ~_BV(4); }; inline static void resetSS() { PORTB |= _BV(4); }; -#elif defined(__AVR_ATmega32U4__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB162__) +#elif defined(__AVR_ATmega32U4__) + inline static void initSS() { DDRB |= _BV(6); }; + inline static void setSS() { PORTB &= ~_BV(6); }; + inline static void resetSS() { PORTB |= _BV(6); }; +#elif defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB162__) inline static void initSS() { DDRB |= _BV(0); }; inline static void setSS() { PORTB &= ~_BV(0); }; inline static void resetSS() { PORTB |= _BV(0); }; |