Naos v1.x

From Alteeve Wiki
Revision as of 23:03, 23 January 2010 by Digimer (talk | contribs) (Created page with '{{na_header}} <source lang="c"> #include <Ethernet.h> // Arduino's enthernet library. #include <ctype.h> // Library for testing and character manipulation. #include <stdint.h> /…')
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

 Node Assassin :: Naos v1.x

#include <Ethernet.h>	// Arduino's enthernet library.
#include <ctype.h>	// Library for testing and character manipulation.
#include <stdint.h>	// Library for standard integer types (guarantees the size of an int).

// 00:X is a request for info where 'X' is the requested data. Currently '0' is only data type and returns the current state of all nodes.
// [01-99]:[0-1] Sends a command to set the state of node [01-99] to on [:1] or off [:0].

// MAC Address; Array of six bytes.
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xEF };
// Arduino IP, netmask and gateway.
byte ip[] = { 192, 168, 111, 66 };
// Netmask defaults to 255.255.255.0.
byte nm[] = { 255, 255, 255, 0 };
// Default gateway defaults to IP with the last octal set to 1.
byte dg[] = { 192, 168, 1, 1 };
// Laptop's IP address that I test connecting to.
byte remote[] = { 192, 168, 1, 154 };

// This is the port that I will listen on.
#define port 238

// Setup the server.
Server server = Server(port);

// My function prototypes.
void printError(char reading[]);

// Setup my digital out pins.
#define maxnode 5
#define firstnode 2

// Setup
void setup()
{
	// Setup the IP info.
	Ethernet.begin(mac, ip, dg, nm);
	
	// Print what comes in over telnet.
	Serial.begin(9600);
	Serial.println("Node Assassin: 'Ariel' now listening for orders.");
	
	// Iterator
	for (int i=firstnode; i<(firstnode+maxnode); i++)
	{
		// Set my pin 'i' to be output.
		pinMode(i, OUTPUT);
		// and set it initially to be low.
		digitalWrite(i, LOW);
	}
	
	// Start the server listening for connections.
	server.begin();
}

// And GO!
void loop()
{
	// Variables
	uint8_t node=0;		// The device I am working on.
	uint8_t state=0;	// The (new?) state of the pin.
	
	// Start the network library.
	Client client=server.available();
	if (client)
	{
		char reading[7];	// 4 chars (XX:Y) + '\n' or '\r\n' or <NUL>' + double-increment below
		int i=0;
		while (((reading[i]=client.read())!=-1)||(i<5))
		{
			i++;
		}
		// Double increment to make sure my test works even when I don't get an '\n' or '\r\n'.
		reading[i++]=0;
		reading[i]=0;
		
		// Parse the string.
		// Format: XX:Y where XX is the node to work on and Y is the new state
		// Make sure the string is formatted properly and print an error if not.
		if (reading[2] != ':')
		{
			// Error
			printError(reading);
			return;
		}
		if (!isdigit(reading[0]) || !isdigit(reading[1]) || !isdigit(reading[3]))
		{
			// Error
			printError(reading);
			return;
		}
		// Next two check the termination
		if ((reading[4] != 0) && (reading[4] != '\n') && (reading[4] != '\r'))
		{
			// Extraneous terminated string.
			printError(reading);
			return;
		}
		if ((reading[5] != 0) && (reading[5] != '\n') && (reading[5] != '\r'))
		{
			// Extraneous terminated string.
			printError(reading);
			return;
		}
		
		// Do the math to turn the node number into a binary value.
		node=reading[0]-'0';	// First digit convertion (ie: '1' (0x31)-'0' (0x30) = 0x01 = "0000 0001 (dec. 1)").
		node*=10;		// Shift to the first base-10 position.
		node+=reading[1]-'0';	// Now 'node' contains the binary version of the ASCII two-digit value read off of telnet.
		
		// Do the math to turn the state number into a binary value.
		state=reading[3]-'0';	// Now 'state' contains the binary version.
		
		// Check the node.
		if (node > 5)
		{
			// Node number can't be higher than '05' on this model.
			Serial.println("This fence only supports up to '05' nodes.");
			server.write("This fence only supports up to '05' nodes.\n");
		}
		if (state > 1)
		{
			// Node number can't be higher than '05' on this model.
			Serial.println("Invalid state received. Send 'XX:0' to kill a node, XX:1 to release a node");
			server.write("Invalid state received. Send 'XX:0' to kill a node, XX:1 to release a node\n");
		}
		
		// Check is this is an info request.
		// By putting 0 first, I can never accidentally set 'node' to '0' with an accidental single-equal.
		if (0 == node)
		{
			// Send states
			Serial.println("Node states: ");
			server.write("Node states: \n");
			
			// Make my maxnode an ASCII value so that I can print it by reversing the convertion to binary done earlier.
			char saynode[3];		// This is '3' because of 'first char' + 'second char' + terminating '0'.
			saynode[0]=(maxnode/10)+'0';	// Move from the 'tens' posiition into the '1' position and add '0' to get the ASCII value.
			saynode[1]=(maxnode%10)+'0';	// The modulous returns my real one position.
			saynode[2]=0;			// Null terminated.
			
			Serial.print("- Max Node: "); Serial.println(saynode);
			server.write("- Max Node: "); server.write(saynode); server.write("\n");
			for (int i=0; i<maxnode; i++)
			{
				// 'i' is the current, printable node number.
				saynode[0]=((i+1)/10)+'0';	// The '+1' makes the node 1-based instead of 0-based.
				saynode[1]=((i+1)%10)+'0';	// The modulous returns my real one position.
				
				char saystate = digitalRead(i+firstnode);	// i + pin offset.
				Serial.print("- Node "); Serial.print(saynode); Serial.print(": "); Serial.println((LOW == saystate) ? "Running" : "Fenced!" );
				server.write("- Node "); server.write(saynode); server.write(": "); server.write((LOW == saystate) ? "Running\n" : "Fenced!\n");
			}
			Serial.println("End Message.");
			server.write("End Message.\n");
			
			return;
		}
		
		// Subtract 1 from node to make it zero-based.
		node--;
		// Set the pin based on whether 'state' is '0' or not.
		digitalWrite(node+firstnode, (0 == state) ? HIGH : LOW);
		
		// This is what I am trying to concatenate and to print as a whole line.
		Serial.println(reading);
		server.write(reading);
	}
}

void printError(char reading[])
{
	// Print the message to the serial bus and the client.
	// I know this is dirty but it represents the one line string.
	Serial.print("Bad command: [" ); Serial.print(reading); Serial.println("]" );
	server.write("Bad command: [" ); server.write(reading); server.write("]\n" );
}

 

Input, advice, complaints and meanderings all welcome!
Digimer digimer@alteeve.ca https://alteeve.ca/w legal stuff:  
All info is provided "As-Is". Do not use anything here unless you are willing and able to take resposibility for your own actions. © 1997-2013
Naming credits go to Christopher Olah!
In memory of Kettle, Tonia, Josh, Leah and Harvey. In special memory of Hannah, Jack and Riley.