@ -222,13 +222,17 @@ void Wiz810MjDevice::setMac(byte b0, byte b1, byte b2, byte b3, byte b4, byte b5
class NetworkConnection { // Essentially a Socket wrapper
public:
NetworkConnection(uint16_t port); // TODO: Add UDP, TCP choice?
// TODO: Split into client/server connections? Subclass?
NetworkConnection(uint16_t port); // TODO: Add UDP, TCP choice? // For servers
NetworkConnection(); // For clients--is using the default constructor hide misuse? TODO: As above.
int listen();
int connect(uint8 * addr, uint16 port);
int isConnected();
int available();
int read();
void print(uint8_t);
void print(const char * text);
void close();
private:
@ -248,6 +252,14 @@ NetworkConnection::NetworkConnection(uint16_t port) {
socket(_socket, Sn_MR_TCP, port, 0);
}
NetworkConnection::NetworkConnection() {
/*
*/
NetworkConnection(0);
}
int NetworkConnection::listen() { // TODO: Make private or protected?
/*
@ -255,6 +267,21 @@ int NetworkConnection::listen() { // TODO: Make private or protected?
return !!::listen(_socket); // TODO: Use C++ namespaces for the driver functions?
}
int NetworkConnection::connect(uint8 * addr, uint16 port) { // TODO: Make private or protected?
/*
*/
// TODO: Accept bytes here for addr?
int result = 0;
result = !!::connect(_socket, addr, port); // TODO: Use C++ namespaces for the driver functions?
Serial.println(IINCHIP_READ(Sn_DPORT0(_socket)), HEX);
Serial.println(IINCHIP_READ(Sn_DPORT0(_socket) + 1), HEX);
return result;
}
int NetworkConnection::available() {
/*
@ -313,6 +340,7 @@ int NetworkConnection::isConnected() {
*/
// TODO: If we want the 'Network*' classes to be generic we
// would need to handle this differently:
//Serial.println(getSn_SR(_socket), HEX);
return (getSn_SR(_socket) == SOCK_ESTABLISHED);
}
@ -327,6 +355,15 @@ void NetworkConnection::print(uint8_t b) {
}
}
void NetworkConnection::print(const char * text) {
/*
*/
for (int idx = 0; idx < strlen(text); idx++) {
print(text[idx]);
Serial.print(text[idx]);
}
}
void NetworkConnection::close() {
/*
@ -350,6 +387,7 @@ class NetworkInterface {
NetworkInterface(Wiz810MjDevice& networkDevice);
NetworkConnection listen(uint16_t port);
NetworkConnection connect(byte b0, byte b1, byte b2, byte b3, uint16 port);
Wiz810MjDevice& device; // TODO: Make this a generic "network device" interface
};
@ -407,6 +445,27 @@ NetworkConnection NetworkInterface::listen(uint16_t port) {
return connection;
}
NetworkConnection NetworkInterface::connect(byte b0, byte b1, byte b2, byte b3, uint16 port) {
/*
*/
NetworkConnection connection = NetworkConnection(4000);
byte _scratchBuffer[4]; // TODO: Move this?
// TODO: Better?
_scratchBuffer[0] = b0;
_scratchBuffer[1] = b1;
_scratchBuffer[2] = b2;
_scratchBuffer[3] = b3;
if (!connection.connect(_scratchBuffer, port)) {
HANDLE_BAD_ERROR();
}
return connection;
}
// NetworkInterface Network = NetworkInterface(...); // TODO: Make this a global
/* ----------------------- */
@ -488,6 +547,148 @@ byte ip[6];
#define PIN_LED 2
//------
// Note: Probably not efficient or anything...
class StreamConnection {
public:
StreamConnection(NetworkConnection& connection);
int peekByte();
int readByte();
int skipSegment(const char * separators); // TODO: Return if separators found or not?
int readSegmentByte(const char * separators);
int debug;
int gobbleMatch(const char * separators, const char * target);
private:
NetworkConnection& _connection;
int _byteSeen;
};
StreamConnection::StreamConnection(NetworkConnection& connection) : _connection (connection) {
/*
*/
_byteSeen = -1;
debug = 0;
}
int StreamConnection::peekByte() {
/*
*/
if (_byteSeen < 0) {
if (_connection.available()) {
_byteSeen = _connection.read();
}
}
return _byteSeen;
}
int StreamConnection::readByte() {
/*
*/
int newByte = -1;
if (_byteSeen < 0) {
if (_connection.available()) {
newByte = _connection.read();
}
} else {
newByte = _byteSeen;
_byteSeen = -1;
}
if (debug == 1) {
Serial.print(newByte, BYTE);
}
return newByte;
}
int StreamConnection::readSegmentByte(const char * separators) {
/*
*/
// Blocks
while (peekByte() < 0) { // TODO: Time out?
delay(500);
}
if (!strchr(separators, peekByte())) {
return readByte();
}
return -1;
}
int StreamConnection::skipSegment(const char * separators) {
/*
*/
if (debug == 1) {
Serial.println("Start skipping non-separator");
}
do {
if (peekByte() < 0) {
return -1;
}
// Skip everything not a separator
} while (!strchr(separators, peekByte()) && readByte());
if (debug == 1) {
Serial.println("Finished skipping non-separator");
}
do {
/* // We can't return here or we get stuck above.
if (peekByte() < 0) {
return -1;
}*/
while (peekByte() < 0) {
delay(500); // TODO: Time out?
}
// Skip everything that *is* a separator
} while (strchr(separators, peekByte()) && readByte());
if (debug == 1) {
Serial.println("Finished skipping separator");
}
return 1;
}
int StreamConnection::gobbleMatch(const char * separators, const char * target) {
/*
*/
int idx = 0;
int byteRead = -1;
while ((byteRead = readSegmentByte(separators)) >=0) {
if (idx < strlen(target)) {
if (byteRead != target[idx]) {
break;
}
idx++;
} else {
break;
}
}
if ((byteRead == -1) && (idx == strlen(target))) { // Matched
while (skipSegment(separators) < 0) {
// Ummm, we ran outta data--this screws things up...
// TODO: Have a time out?
delay(500);
}
return 1;
}
return -1;
}
//------
void setup () {
Serial.begin(9600);
Serial.println("Setup enter...");
@ -503,6 +704,8 @@ void setup () {
Network.device.setIp(192,168,2,105);
Network.device.setMask(255,255,255,0);
Network.device.setGateway(192,168,2,101);
Serial.println("End W5100 configuration...");
pinMode(PIN_LED, OUTPUT);
@ -510,10 +713,204 @@ void setup () {
Serial.println("Setup exit...");
// Serial.println(((analogRead(2)*70)/630)/10+'0', BYTE);
/**/
Serial.println("Test sockets...");
#if
#if 1
#if 1 //b
NetworkConnection conn = Network.connect(209,177,146,34, 6667); // TODO: Better?
Serial.println("Waiting to connect...");
while (!conn.isConnected()) {
//Serial.print(!conn.isConnected());
delay(500);
}
Serial.println("Connected...");
int byteRead = -1;
int dataWait = 0;
StreamConnection stream = StreamConnection(conn);
conn.print("NICK Arduino\n");
conn.print("USER Arduino 0 0 Arduino\n");
byte buf[4] = {0, 0, 0, 0};
int state = 0;
while (conn.isConnected()) {
#if 1 //c
if (stream.peekByte() >= 0) {
// New line
//Serial.println("Process new line...");
if (stream.peekByte() != ':') {
// Skip local responses/messages entirely. TODO: Handle PINGs?
while (stream.skipSegment("\x0A\x0D") < 0) {
// Ummm, we ran outta data--this screws things up...
// TODO: Have a time out?
delay(500);
}
} else {
//Serial.println(state, HEX);
if (state == 0) {
// Skip sending servername // TODO: Check it's the main one?
while (stream.skipSegment(" ") < 0) {
// Ummm, we ran outta data--this screws things up...
// TODO: Have a time out?
delay(500);
}
for (int idx=0; idx < 3; idx++) {
while (stream.peekByte() < 0) { // TODO: Time out?
delay(500);
}
buf[idx] = stream.readByte();
//Serial.print(buf[idx], BYTE);
}
//Serial.print("//");
Serial.println((const char *) buf);
if (strcmp((const char *) buf, "376") == 0) { // End MOTD
state=1;
conn.print("JOIN #arduino\n");
//stream.debug = 1;
}
} else if (state == 1) {
//stream.debug = 1;
//Serial.println("Skip servername");
// Skip sending servername // TODO: Check it's the main one?
while (stream.skipSegment(" ") < 0) {
// Ummm, we ran outta data--this screws things up...
// TODO: Have a time out?
delay(500);
}
//stream.debug = 0;
/*
int idx = 0;
const char * PRIVMSG = "PRIVMSG";
//Serial.println("Checking for PRIVMSG.");
//stream.debug = 1;
while ((byteRead = stream.readSegmentByte(" ")) >=0) {
if (idx < strlen(PRIVMSG)) {
if (byteRead != PRIVMSG[idx]) {
break;
}
idx++;
} else {
break;
}
}
// stream.debug = 0;
//Serial.println("Finished check PRIVMSG, determining result.");
if ((byteRead == -1) && (idx == strlen(PRIVMSG))) { // Matched
//Serial.println("Matched.");
while (stream.skipSegment(" ") < 0) {
// Ummm, we ran outta data--this screws things up...
// TODO: Have a time out?
delay(500);
}
*/
if (stream.gobbleMatch(" ", "PRIVMSG") > 0) {
/* **
while ((byteRead = stream.readSegmentByte("\x0A\x0D")) >=0) {
Serial.print(byteRead, BYTE);
}
Serial.println("");
*/
Serial.println("Matched PRIV MSG");
if (stream.gobbleMatch(" :", "#arduino") > 0) { // We treat the ":" as a separator too--does this break?
Serial.println("Matched #arduino");
//Serial.println(stream.peekByte(), HEX);
//if (stream.gobbleMatch("\x0A\x0D", "arduino:") > 0) {
//if (stream.gobbleMatch(":", "Arduino") > 0) {
//Serial.println("Matched Arduino");
if ((stream.peekByte() == 'A') && (stream.gobbleMatch(":", "Arduino") > 0)) {
Serial.println("Matched something");
//conn.print("PRIVMSG #arduino :Huh, what? Was someone talking to me?\n");
conn.print("PRIVMSG #arduino :My current pot status is ");
conn.print(((analogRead(2)*70)/630)/10+'0');
conn.print("3%, man!\n");
}
}
} else {
//Serial.println("No match.");
}
} else {
while ((byteRead = stream.readSegmentByte("\x0A\x0D")) >=0) {
Serial.print(byteRead, BYTE);
}
Serial.println("");
}
//Serial.println("Skipping this:");
//stream.debug = 1;
while (stream.skipSegment("\x0A\x0D") < 0) {
// Ummm, we ran outta data--this screws things up...
// TODO: Have a time out?
delay(500);
}
//stream.debug = 0;
//Serial.println("\nFinish skipping.");
}
}
#else //c
if (conn.available()) {
byteRead = conn.read();
Serial.print(byteRead, BYTE);
if (byteRead == '\n') {
dataWait++;
Serial.println(dataWait, DEC);
}
if (dataWait==4) {
//conn.print("NICK Arduino\n");
//conn.print("USER Arduino Arduino Arduino Arduino\n");
dataWait++;
}
if (dataWait==67) {
conn.print("JOIN #arduino\n");
//conn.print("PRIVMSG #arduino :Hello, world!\n");
//delay(10000);
conn.print("QUIT\n");
dataWait++;
}
//conn.print(conn.read());
} else {
//dataWait++;
//Serial.print(dataWait, DEC);
}
#endif //c
}
Serial.println("");
conn.close();
#else //b
NetworkConnection conn = Network.listen(7);
Serial.println("Waiting for connection...");
@ -535,6 +932,7 @@ void setup () {
Serial.println("");
conn.close();
#endif //b
#else
// This uses the 1-argument constructor of EchoServer and supplies it with 7 for each instance.