Code after the jump
Processing:
import processing.serial.*; //Device Codes final int DVC_LM33 = 0x01; final int DVC_ST11 = 0x02; final int DVC_ST15 = 0x03; final int DVC_DOORCONTACT = 0x04; final int DVC_FLIPSWITCH = 0x05; final int DVC_LIGHT = 0x06; final int DVC_MOTION = 0x07; final int DVC_2LINECHAR = 0x08; final int DVC_POWER30 = 0x08; final int DVC_POWER100 = 0x09; final int DVC_SMARTOUTLET = 0x10; final int DVC_RGBLIGHT = 0x11; //Command Codes final int CMD_GET_VERSION = 0x01; final int CMD_PING = 0x3E; final int CMD_PONG = 0xE3; final int CMD_ACK = 0x11; final int CMD_READ = 0xAA; final int CMD_WRITE = 0xBB; final int CMD_PORTTYPE = 0xCC; final int CMD_AUTOSENDSTART = 0xC1; final int CMD_AUTOSENDSTOP = 0xC2; final int CMD_ERROR = 0xFF; //shortcuts to important bytes //keeps from having to decode the whole thing to check simple parts final int PACKET_LENGTH = 0; final int PACKET_SETTINGS = 1; final int PACKET_FROM = 2; final int PACKET_TO = 4; final int PACKET_TTL = 4; final int PACKET_ID = 6; final int PACKET_COMMAND = 7; final int PACKET_PAYLOAD = 8; //an enum might be better here final int STATUS_CLEAR = 0; final int STATUS_RECEVING = 1; final int STATUS_RECEVIED = 2; final int STATUS_WAITING = 3; final int STATUS_READY = 4; final int STATUS_SENDING = 5; final int STATUS_SENT = 6; final int STATUS_ACK = 7; final int STATUS_SUCCESS = 8; final int OFFSET_PACKET = 10; final int OFFSET_HEADER = 8; final int OFFSET_FOOTER = 2; class DataPacketDecoded { int command, length, status = 0, settings, type, fromPort, toPort, id, ttl = 0, ptr = 0; int fromNode, toNode, checksum = 0; int[] payload = new int[56]; DataPacketDecoded(){ } } //simple data packet class DataPacket { int ptr = 0, status = 0, checksum = 0; int[] payload = new int[64]; DataPacket(){ } } class Payload { int length; int[] data = new int[56]; Payload() { } } //What should master ports be? final int NODE_ID = 0x02; final int PORT_A = DVC_LM33; final int PORT_B = DVC_LM33; final int PORT_C = DVC_LM33; final int PORT_D = DVC_LM33; final int PACKET_BUFFER = 10; final int PACKET_TIMEOUT = 100; DataPacket[] data = new DataPacket[PACKET_BUFFER]; DataPacket incomingPacket = new DataPacket(); //current incoming packet int checksum; int uniqueId = 0; int i; boolean sending = false; boolean receiving = false; long packetTimer; int bgcolor; // Background color int fgcolor; // Fill color Serial myPort; // The serial port PFont myFont; //build rf12 packet void build_incoming_packet(int byteIn) { //mark which port it is coming from println("count: "+incomingPacket.ptr + " byte: " + byteIn); if(incomingPacket.ptr == 0){ //Packet length if(byteIn <= 1) { println("RESENDING LAST"); //resend last sendingPacket.status = STATUS_SENDING; return; } if(byteIn == 255) { println("ACK SUCCESS"); sendingPacket.status = STATUS_SUCCESS; sending = false; //allow next packet to send //aknowledge return; } if (byteIn > 128) { myPort.clear(); myPort.write(0); return; } receiving = true; packetTimer = millis(); incomingPacket.payload[PACKET_LENGTH] = byteIn; incomingPacket.status = STATUS_RECEVING; checksum = 0; println("length: " + byteIn); } //checksum if(incomingPacket.ptr < (incomingPacket.payload[PACKET_LENGTH] - OFFSET_FOOTER)){ //add to check sum incomingPacket.payload[incomingPacket.ptr] = byteIn; checksum = _crc16_update(checksum, byteIn); incomingPacket.ptr++; return; } else if(incomingPacket.ptr == (incomingPacket.payload[PACKET_LENGTH] - OFFSET_FOOTER)){ //get first byte of checksum incomingPacket.checksum = byteIn; incomingPacket.ptr++; return; } else { //get second byte and check the checksum incomingPacket.checksum = (incomingPacket.checksum << 8) | (byteIn & 0xFF); if(checksum != incomingPacket.checksum) { println("processing checksum: " + checksum); println(" packet checksum: " + incomingPacket.checksum); println("Failed CRC Check"); myPort.clear(); myPort.write(int(0)); } else { println("processing checksum: " + checksum); println(" packet checksum: " + incomingPacket.checksum); println("Passed CRC Check"); incomingPacket.status=STATUS_RECEVIED; DataPacket packet = getNewPacket(); packet = incomingPacket; myPort.clear(); myPort.write(int(255)); println("SENT ACK"); //packet debug_incoming_packet(packet); // incomingPacket.payload; //incomingPacket = DataPacket; } //reset incoming packet incomingPacket = new DataPacket(); receiving = false; } } //determine where to send packet. how to expand when we have 4 serial ports? void process_stack(){ //sending = false; //only send one pack per cycle for(i=0;i//check for packets to send //check for packets to resend if ACKs are late //check for data packets that can be deleted from the stack } DataPacket sendingPacket; void process_packet(DataPacket packet){ switch (packet.status){ case STATUS_CLEAR: //println("CLEAR"); break; case STATUS_RECEVING: println("RECEVING"); break; case STATUS_RECEVIED: process_command(packet); packet.status = STATUS_CLEAR; println("RECEVIED"); break; case STATUS_WAITING: println("WAITING"); break; case STATUS_READY: //check for free port if(sending == false){ packet.status = STATUS_SENDING; sending = true; } //if reset pointer and set to send println("READY"); break; case STATUS_SENDING: //because of the above, only one packet will be changed to sending //if(get_node(packet,PACKET_FROM) < 30){ // send_packet_rf12(packet); //} else { send_packet_serial(packet); sendingPacket = packet; // } packet.status = STATUS_SENT; println("SENDING"); break; case STATUS_SENT: //if is a ack packet if(packet.payload[PACKET_SETTINGS] == 1){ packet.status = STATUS_ACK; //start packets ack timer } else { //packet.status = STATUS_SUCCESS; } println("SENT"); break; case STATUS_ACK: //if execeded timer resen //count resends if exceds max kill packet and add error println("ACK"); break; case STATUS_SUCCESS: //option to post status to screen packet.status = STATUS_CLEAR; println("SUCCESS"); break; } } long sendTimer; void setup() { size(600, 400); // Stage size //noStroke(); // No border on the next thing drawn myFont = createFont("Consolas", 14); textFont(myFont); for(i=0; i < PACKET_BUFFER; i++) { data[i] = new DataPacket(); } // Print a list of the serial ports, for debugging purposes: //println(PFont.list()); sendTimer = millis(); String portName = Serial.list()[1]; myPort = new Serial(this, portName, 115200); } void draw() { process_stack(); //process_stack(); //process_stack(); // process_stack(); // process_stack(); println("loop"); //delay(1000); //text("Hello",10,10); //text("Z", 10, 220); // Draw the shape if((millis() - sendTimer) > 2500){ DataPacket packet = build_udp_packet(0,0,1,0,CMD_PING,str_to_payload("Hello")); packet.status = STATUS_READY; sendTimer=millis(); } //send_packet_serial(packet); if(receiving == true) { if((millis() - packetTimer) > PACKET_TIMEOUT) { myPort.clear(); myPort.write(0); //tell the node to resend last incomingPacket = new DataPacket(); println("bad packet"); receiving = false; } } } void serialEvent(Serial myPort) { // read a byte from the serial port: int inByte = myPort.read(); build_incoming_packet(inByte); //print(inByte); //print(","); } //Done DataPacket getNewPacket() { for(i=0; i < PACKET_BUFFER; i++) { if(data[i].status == STATUS_CLEAR){ return data[i]; } } println("BUFFER FULL"); return new DataPacket(); } int get_node(DataPacket packet, int location) { int node; node = packet.payload[location]; node = node << 4; node = node | (packet.payload[location+1] >> 4); return node; } Payload get_payload(DataPacket packet) { Payload payload = new Payload(); payload.length = packet.payload[PACKET_LENGTH] - OFFSET_PACKET; for(i=0; i < payload.length; i++){ if(packet.payload[PACKET_SETTINGS] < 3) { //single packet TCP or UDP payload.data[i] = packet.payload[i+OFFSET_HEADER]; } else if(packet.payload[PACKET_SETTINGS] == 3) { //broadcast //todo } } return payload; } Payload str_to_payload(String string) { Payload payload = new Payload(); //println("Payload Length: "+ string.length()); for(i=0;i length();i++){ payload.data[i] = int(string.charAt(i)); } payload.length = string.length(); return payload; } void process_command(DataPacket packet) { switch (packet.payload[PACKET_COMMAND]) { case CMD_PING: DataPacket reply = build_udp_packet(NODE_ID, 1, 0, 0, CMD_PONG, get_payload(packet)); reply.status = STATUS_READY; //change status to ready to send break; //default: //send_packet(COMMAND_ERROR,NULL,0); // break; } } int _crc16_update(int crc, int a) { int i; crc ^= a; for (i = 0; i < 8; ++i){ if ((crc & 1) == 1){ crc = (crc >> 1) ^ 0xA001; }else{ crc = (crc >> 1); } } return crc & 0xFFFF; } int getId() { if(uniqueId == 255){ uniqueId = 0; } return uniqueId++; //what happens when this wraps? } int compressAddress(int node, int port) { node = node << 4; //make space port = port & 0x0F; return node | port; } DataPacket build_tcp_packet(int fromNode, int fromPlug, int toNode, int toPlug, int command, Payload payload) { DataPacket packet = getNewPacket(); //*packet.status = STATUS_READY; packet.status = STATUS_WAITING; packet.payload[PACKET_LENGTH] = payload.length + OFFSET_PACKET; //header 8 crc 2 packet.payload[PACKET_SETTINGS] = 1; int address = compressAddress(fromNode, fromPlug); packet.payload[PACKET_FROM] = (address >> 8) & 0xFF; packet.payload[PACKET_FROM+1] = address & 0xFF; address = compressAddress(toNode, toPlug); packet.payload[PACKET_TO ] = (address >> 8) & 0xFF; packet.payload[PACKET_TO+1] = address & 0xFF; packet.payload[PACKET_ID] = getId(); packet.payload[PACKET_COMMAND] = command; for(i=0;i < payload.length;i++){ packet.payload[PACKET_PAYLOAD+i] = payload.data[i]; } return packet; } /* * @return DataPacket * Pointer to the New DataPacket */ DataPacket build_udp_packet(int fromNode, int fromPlug, int toNode, int toPlug, int command, Payload payload) { DataPacket packet = getNewPacket(); //*packet.status = STATUS_READY; packet.status = STATUS_WAITING; packet.payload[PACKET_LENGTH] = payload.length + OFFSET_PACKET; //header 8 crc 2 packet.payload[PACKET_SETTINGS] = 2; int address = compressAddress(fromNode, fromPlug); packet.payload[PACKET_FROM] = (address >> 8) & 0xFF; packet.payload[PACKET_FROM+1] = address & 0xFF; address = compressAddress(toNode, toPlug); packet.payload[PACKET_TO ] = (address >> 8) & 0xFF; packet.payload[PACKET_TO+1] = address & 0xFF; packet.payload[PACKET_ID] = getId(); packet.payload[PACKET_COMMAND] = command; for(i=0;i < payload.length;i++){ packet.payload[PACKET_PAYLOAD+i] = payload.data[i]; } return packet; } /* uint8_t build_broadcast_packet(uint16_t fromNode, uint8_t fromPort, uint16_t toNode, uint8_t toPort, uint8_t payload[48], uint8_t length, uint8_t ttl ) { byte packetId = getNewPacketId(); data[packetId].sent = 0; return packetId; } */ boolean send_packet_serial(DataPacket packet) { int dataChecksum = 0; for(i=0; i < (packet.payload[PACKET_LENGTH]-2); i++){ dataChecksum = _crc16_update(dataChecksum, packet.payload[i]); myPort.write(packet.payload[i] & 0xFF); print(int((packet.payload[i] & 0xFF)) + ","); } print((dataChecksum >>8)&0xFF); print(","); print(dataChecksum & 0xFF); println(""); println("Packet Sent"); packet.status = 1; myPort.write((dataChecksum >> 8) & 0xFF); myPort.write(dataChecksum & 0xFF); return true; } /** * turns a packet into a decoded packet */ DataPacketDecoded decode_packet(DataPacket packet) { DataPacketDecoded decodedPacket = new DataPacketDecoded(); //Set Packet length decodedPacket.length = packet.payload[PACKET_LENGTH]; decodedPacket.status = packet.status; //settings decodedPacket.settings = packet.payload[PACKET_SETTINGS]; decodedPacket.type = packet.payload[PACKET_SETTINGS]; //right now these are the same things //From 12bit node id, 4 bit plug id decodedPacket.fromNode = packet.payload[PACKET_FROM]; decodedPacket.fromNode = decodedPacket.fromNode << 4; decodedPacket.fromNode = decodedPacket.fromNode | (packet.payload[PACKET_FROM+1] >> 4); decodedPacket.fromPort = packet.payload[PACKET_FROM+1] &0xF; //To 12bit node id, 4 bit plug id decodedPacket.toNode = packet.payload[PACKET_TO]; decodedPacket.toNode = decodedPacket.toNode << 4; decodedPacket.toNode = decodedPacket.toNode | (packet.payload[PACKET_TO+1] >> 4); decodedPacket.toPort = packet.payload[PACKET_TO+1] &0xF; //packet id decodedPacket.id = packet.payload[PACKET_ID]; //Command decodedPacket.command = packet.payload[PACKET_COMMAND]; decodedPacket.checksum = packet.checksum; decodedPacket.ptr = packet.payload[PACKET_LENGTH] - 10; for(i=PACKET_PAYLOAD; i < packet.payload[PACKET_LENGTH]; i++){ if(decodedPacket.type < 3) { //single packet TCP or UDP decodedPacket.payload[i-PACKET_PAYLOAD] = packet.payload[i]; } else if(decodedPacket.type == 3) { //broadcast //todo } } return decodedPacket; } void debug_incoming_packet(DataPacket packet) { background(0); //println("show packet info"); text("Packet Info",5,15); int x = 20; DataPacketDecoded packetDecoded = decode_packet(packet); text(" status: " + packetDecoded.status,10,x+=20); text(" length: " + packetDecoded.length,10,x+=20); text("settings: " + packetDecoded.settings,10,x+=20); text(" type: " + packetDecoded.type,10,x+=20); text("fromNode: " + packetDecoded.fromNode,10,x+=20); text("fromPort: " + packetDecoded.fromPort,10,x+=20); text(" toNode: " + packetDecoded.toNode,10,x+=20); text(" toPort: " + packetDecoded.toPort,10,x+=20); text(" ttl: " + packetDecoded.ttl,10,x+=20); text(" id: " + packetDecoded.id,10,x+=20); text(" command: " + packetDecoded.command,10,x+=20); String message = ""; String message2 = ""; for(i=0; i < packetDecoded.ptr; i++){ message += int(packetDecoded.payload[i]); message += ","; message2 += char(packetDecoded.payload[i]); } text(" payload: " + message,10,x+=20); text(" payload: " + message2,10,x+=20); text("checksum: " + packetDecoded.checksum,10,x+=20); text(" ptr: " + packetDecoded.ptr,10,x+=20);//*/ }
Arduino
Protocol.h
//Device Codes #define DVC_LM33 0x01 #define DVC_ST11 0x02 #define DVC_ST15 0x03 #define DVC_DOORCONTACT 0x04 #define DVC_FLIPSWITCH 0x05 #define DVC_LIGHT 0x06 #define DVC_MOTION 0x07 #define DVC_2LINECHAR 0x08 #define DVC_POWER30 0x08 #define DVC_POWER100 0x09 #define DVC_SMARTOUTLET 0x10 #define DVC_RGBLIGHT 0x11 //Command Codes #define CMD_GET_VERSION 0x01 #define CMD_PING 0x3E #define CMD_PONG 0xE3 #define CMD_ACK 0x11 #define CMD_READ 0xAA #define CMD_WRITE 0xBB #define CMD_PORTTYPE 0xCC #define CMD_AUTOSENDSTART 0xC1 #define CMD_AUTOSENDSTOP 0xC2 #define CMD_VALUE 0x02 #define CMD_ERROR 0xFF //@todo commands for different data types? //decoded packet struct typedef struct { uint8_t command; //if 255 = ready to send // 0 = resend last uint8_t length; uint8_t status; uint8_t settings; //01010101 //version //type direct or broadcast //ack //ttl //priority //multi uint8_t type; //1 single tcp, 2 single udp, 3 multipacket tcp uint16_t fromNode; uint8_t fromPlug; uint16_t toNode; //00 is base //xffff is broadcast uint8_t toPlug; uint8_t id; uint8_t ttl; uint8_t payload[48]; uint16_t checksum; uint8_t ptr; } DataPacketDecoded; //simple data packet typedef struct { uint8_t ptr; uint8_t port; uint8_t status; uint8_t payload[56]; uint16_t checksum; } DataPacket; //payload type typedef struct { uint8_t length; uint8_t data[56]; } Payload; typedef struct { long start; uint8_t waiting; uint8_t ptr; } ACKStatus; typedef struct { uint8_t type; uint8_t status; } Port; //shortcuts to important bytes //keeps from having to decode the whole thing to check simple parts #define PACKET_LENGTH 0 #define PACKET_SETTINGS 1 #define PACKET_FROM 2 #define PACKET_TO 4 #define PACKET_TTL 4 #define PACKET_ID 6 #define PACKET_COMMAND 7 #define PACKET_PAYLOAD 8 //an enum might be better here #define STATUS_CLEAR 0 #define STATUS_RECEVING 1 #define STATUS_RECEVIED 2 #define STATUS_WAITING 3 #define STATUS_READY 4 #define STATUS_SENDING 5 #define STATUS_SENT 6 #define STATUS_ACK 7 #define STATUS_SUCCESS 8 #define OFFSET_PACKET 10 #define OFFSET_HEADER 8 #define OFFSET_FOOTER 2
Basenode.pde
#includeh> //checksum functions #include "protocol.h" #define NODE_ID 0x02 #define PLUG_A DVC_LM33 #define PLUG_B DVC_LM33 #define PLUG_C DVC_LM33 #define PLUG_D DVC_LM33 #define PACKET_BUFFER 10 //can be adujsted based on availbe space //#define DEBUG 1; #define PACKET_TIMEOUT 100 #define PORTTYPE_SERIAL 0 #define PORTTYPE_RF12 1 #define PORT_COUNT 2 #define PORT_0 PORTTYPE_SERIAL #define PORT_1 PORTTYPE_RF12 //types //ACK //Single TCp //requires 2byte packet ID //Single UDP //Multi TCP //requires 2byte total ID, 2 byte Packet ID + byte current packet + byte total packets //multi packet //packet id //current packets //total packets // Port ports[] = {{PORTTYPE_SERIAL,STATUS_CLEAR}, {PORTTYPE_RF12,STATUS_CLEAR}}; //list attached ports //1 2 3 4 //rf12 DataPacket data[PACKET_BUFFER]; uint16_t checksum; byte uniqueId = 0; byte i; DataPacket incomingPacket; //current incoming packet //incomingPacket.ptr = 0; DataPacket *sendingPacket; boolean sending = false; boolean receiving = false; long packetTimer;; DataPacket *getNewPacket() { for(i=0; i < PACKET_BUFFER; i++) { if(data[i].status == STATUS_CLEAR){ return &data[i]; } } //Serial.println("all full"); return 0; } uint8_t getId() { return uniqueId++; //loops when it overflows } uint16_t compressAddress(uint16_t node, uint8_t port) { return (node << 4) | (port & 0x0F); } //byte m = 1; void send_packet_serial(DataPacket *packet) { uint16_t dataChecksum = 0; //cause a problem // m++; for(i=0; i < (packet->payload[PACKET_LENGTH]-OFFSET_FOOTER); i++){ dataChecksum = _crc16_update(dataChecksum, packet->payload[i]); //if((m == 3) && (i == 0)){ // Serial.print(packet->payload[0]-5,BYTE); // } else { Serial.print(packet->payload[i],BYTE); // } //Serial.print(","); } packet->checksum = dataChecksum; Serial.print(highByte(dataChecksum),BYTE); // Serial.print(","); Serial.print(lowByte(dataChecksum),BYTE); packet->status = STATUS_SENT; //Serial.println(""); } void send_packet_rf12(DataPacket *packet) { /** //check address only 0-30 allowed * @todo */ } void process_command(DataPacket *packet) { switch (packet->payload[PACKET_COMMAND]) { case CMD_PING: DataPacket *reply = build_udp_packet(NODE_ID, 1, 0, 0, CMD_PONG, get_payload(packet)); reply->status = STATUS_READY; //change status to ready to send break; //default: //send_packet(COMMAND_ERROR,NULL,0); // break; } } //build rf12 packet void build_incoming_packet(uint8_t byteIn) { //mark which port it is coming from if(incomingPacket.ptr == 0){ //Packet length if(byteIn == 0) { //resend last sendingPacket->status = STATUS_SENDING; return; } if(byteIn == 255) { sendingPacket->status = STATUS_SUCCESS; sending = false; //allow next packet to send //aknowledge return; } if (byteIn > 128) { //Serial.flush(); Serial.print(0,BYTE); return; } receiving = true; packetTimer = millis(); incomingPacket.payload[PACKET_LENGTH] = byteIn; incomingPacket.status = STATUS_RECEVING; checksum = 0; } //checksum if(incomingPacket.ptr < (incomingPacket.payload[PACKET_LENGTH] - OFFSET_FOOTER)){ //add to check sum incomingPacket.payload[incomingPacket.ptr] = byteIn; checksum = _crc16_update(checksum, byteIn); incomingPacket.ptr++; return; } else if(incomingPacket.ptr == (incomingPacket.payload[PACKET_LENGTH] - OFFSET_FOOTER)){ //get first byte of checksum incomingPacket.checksum = byteIn; incomingPacket.ptr++; return; } else { //get second byte and check the checksum incomingPacket.checksum = (incomingPacket.checksum << 8) | (byteIn & 0xFF); if(checksum != incomingPacket.checksum) { //Serial.println(checksum, DEC); //Serial.println(incomingPacket.checksum, DEC); DataPacket *p = build_udp_packet(NODE_ID, 1, 0, 0, CMD_ERROR, packet_to_payload(&incomingPacket)); p->status = STATUS_READY; Serial.flush(); Serial.print(1,BYTE); //tell the node to resend last } else { incomingPacket.status=STATUS_RECEVIED; DataPacket *packet = getNewPacket(); *packet = incomingPacket; //Serial.flush(); Serial.print(255,BYTE); //tell the node the packet was successful } //reset incomingPacket receiving = false; incomingPacket.status=STATUS_CLEAR; incomingPacket.ptr = 0; } } //determine where to send packet. how to expand when we have 4 serial ports? void process_stack(){ //sending = false; //only send one pack per cycle for(i=0;i //check for packets to send //check for packets to resend if ACKs are late //check for data packets that can be deleted from the stack } void process_packet(DataPacket *packet){ switch (packet->status){ case STATUS_CLEAR: #ifdef DEBUG Serial.println("CLEAR"); #endif break; case STATUS_RECEVING: #ifdef DEBUG Serial.println("RECEVING"); #endif break; case STATUS_RECEVIED: process_command(packet); packet->status = STATUS_CLEAR; #ifdef DEBUG Serial.println("RECEVIED"); #endif break; case STATUS_WAITING: #ifdef DEBUG Serial.println("WAITING"); #endif break; case STATUS_READY: //check for free port if(sending == false){ packet->status = STATUS_SENDING; sendingPacket = packet; sending = true; } //if reset pointer and set to send #ifdef DEBUG Serial.println("READY"); #endif break; case STATUS_SENDING: //because of the above, only one packet will be changed to sending //if(get_node(packet,PACKET_FROM) < 30){ // send_packet_rf12(packet); //} else { send_packet_serial(packet); // } packet->status = STATUS_SENT; #ifdef DEBUG Serial.println("SENDING"); #endif break; case STATUS_SENT: //if is a ack packet if(packet->payload[PACKET_SETTINGS] == 1){ packet->status = STATUS_ACK; //start packets ack timer } else { //packet->status = STATUS_SUCCESS; } #ifdef DEBUG sending = false; //allow next packet to send packet->status = STATUS_SUCCESS; Serial.println("SENT"); #endif break; case STATUS_ACK: //if execeded timer resen //count resends if exceds max kill packet and add error #ifdef DEBUG Serial.println("ACK"); #endif break; case STATUS_SUCCESS: //option to post status to screen packet->status = STATUS_CLEAR; #ifdef DEBUG Serial.println("SUCCESS"); #endif break; } } unsigned counter = 0; void setup() { Serial.begin(115200); //Serial.println("Ping:"); //Serial.print("nodeID: "); // Serial.println(NODE_ID,DEC); // int sendPacketId = build_udp_packet(NODE_ID, 1, 0, 0, CMD_PING, (byte*)"TEST TEST TEST", 1); // int sendPacketId2 = build_udp_packet(NODE_ID, 1, 0, 0, CMD_PONG, (byte*)"HA HA HA", 8); //send_packet_serial(sendPacketId); //Serial.println(""); /**/ //DataPacket *p = build_udp_packet(NODE_ID, 1, 0, 0, CMD_PONG, str_to_payload("TEEEST")); // send_packet_serial(p); // debug_packet(p); } void loop() { //byte message[1] = {uniqueId}; //message[15] = uniqueId; //int sendPacketId = build_udp_packet(NODE_ID, 1, 0, 0, CMD_PING, message, 1); // int sendPacketId2 = build_udp_packet(NODE_ID, 1, 0, 0, CMD_PONG, (byte*)"HA HA HA", 8); if(counter > 50000) { DataPacket *p = build_udp_packet(NODE_ID, 1, 0, 0, CMD_VALUE, str_to_payload("ha ha ha22222")); p->status = STATUS_READY; counter = 0; } counter++; process_stack(); //recieve timer //and send command to resend last int byteIn; if (Serial.available()>0) { byteIn = Serial.read(); build_incoming_packet(byteIn); } process_stack(); if(receiving == true) { if((millis() - packetTimer) > PACKET_TIMEOUT) { //Serial.flush(); Serial.print(2,BYTE); //tell the node to resend last //DataPacket *p = build_udp_packet(NODE_ID, 1, 0, 0, CMD_ERROR, packet_to_payload(&incomingPacket)); // p->status = STATUS_READY; receiving = false; } } //delay(5); } /*FINISHED*/ Payload *get_payload(DataPacket *packet) { Payload payload; payload.length = packet->payload[PACKET_LENGTH] - OFFSET_PACKET; for(i=0; i < payload.length; i++){ if(packet->payload[PACKET_SETTINGS] < 3) { //single packet TCP or UDP payload.data[i] = packet->payload[i+OFFSET_HEADER]; } else if(packet->payload[PACKET_SETTINGS] == 3) { //broadcast //todo } } return &payload; } Payload *packet_to_payload(DataPacket *packet) { Payload payload; payload.length = packet->payload[PACKET_LENGTH]; for(i=0; i < (payload.length - OFFSET_FOOTER); i++){ payload.data[i] = packet->payload[i]; } payload.data[payload.length - OFFSET_FOOTER] = highByte(packet->checksum); payload.data[payload.length - OFFSET_FOOTER + 1] = lowByte(packet->checksum); return &payload; } uint16_t get_node(DataPacket *packet, uint8_t location) { uint16_t node; node = packet->payload[location]; node = node << 4; node = node | (packet->payload[location+1] >> 4); return node; } Payload *str_to_payload(char string[]) { Payload payload; i=0; while(string[i] != 0){ payload.data[i] = byte(string[i]); i++; } payload.length = i; //Serial.print("sizeOf: "); // Serial.println(i,DEC); return &payload; } Payload *long_to_payload(long number) { Payload payload; i=(sizeof(number)-1); payload.length = i; while(i != 0){ payload.data[i] = number & 0xFF; number = number >> 8; i--; } return &payload; } Payload *uint16_to_payload(uint16_t number) { Payload payload; payload.length = 2; payload.data[0] = highByte(number); payload.data[1] = lowByte(number); return &payload; } DataPacket *build_tcp_packet(uint16_t fromNode, uint8_t fromPlug, uint16_t toNode, uint8_t toPlug, uint8_t command, Payload *payload) { DataPacket *packet = getNewPacket(); //*packet.status = STATUS_READY; packet->status = STATUS_WAITING; packet->payload[PACKET_LENGTH] = payload->length + OFFSET_PACKET; //header 8 crc 2 packet->payload[PACKET_SETTINGS] = 1; uint16_t address = compressAddress(fromNode, fromPlug); packet->payload[PACKET_FROM] = (address >> 8) & 0xFF; packet->payload[PACKET_FROM+1] = address & 0xFF; address = compressAddress(toNode, toPlug); packet->payload[PACKET_TO ] = (address >> 8) & 0xFF; packet->payload[PACKET_TO+1] = address & 0xFF; packet->payload[PACKET_ID] = getId(); packet->payload[PACKET_COMMAND] = command; for(i=0;i < payload->length;i++){ packet->payload[PACKET_PAYLOAD+i] = payload->data[i]; } return packet; } /* * @return DataPacket * Pointer to the New DataPacket */ DataPacket *build_udp_packet(uint16_t fromNode, uint8_t fromPlug, uint16_t toNode, uint8_t toPlug, uint8_t command, Payload *payload) { DataPacket *packet = getNewPacket(); //*packet.status = STATUS_READY; packet->status = STATUS_WAITING; packet->payload[PACKET_LENGTH] = payload->length + OFFSET_PACKET; //header 8 crc 2 packet->payload[PACKET_SETTINGS] = 2; uint16_t address = compressAddress(fromNode, fromPlug); packet->payload[PACKET_FROM] = (address >> 8) & 0xFF; packet->payload[PACKET_FROM+1] = address & 0xFF; address = compressAddress(toNode, toPlug); packet->payload[PACKET_TO ] = (address >> 8) & 0xFF; packet->payload[PACKET_TO+1] = address & 0xFF; packet->payload[PACKET_ID] = getId(); packet->payload[PACKET_COMMAND] = command; for(i=0;i < payload->length;i++){ packet->payload[PACKET_PAYLOAD+i] = payload->data[i]; } return packet; } DataPacket *build_broadcast_packet(uint16_t fromNode, uint8_t fromPlug, uint8_t ttl, Payload payload) { DataPacket *packet = getNewPacket(); packet->status = STATUS_WAITING; return packet; } /** * turns a packet into a decoded packet */ DataPacketDecoded decode_packet(DataPacket *packet) { DataPacketDecoded decodedPacket; decodedPacket.ttl = 0; //Set Packet length decodedPacket.length = packet->payload[PACKET_LENGTH]; decodedPacket.status = packet->status; //settings decodedPacket.settings = packet->payload[PACKET_SETTINGS]; decodedPacket.type = packet->payload[PACKET_SETTINGS]; //right now these are the same things //From 12bit node id, 4 bit plug id decodedPacket.fromNode = packet->payload[PACKET_FROM]; decodedPacket.fromNode = decodedPacket.fromNode << 4; decodedPacket.fromNode = decodedPacket.fromNode | (packet->payload[PACKET_FROM+1] >> 4); decodedPacket.fromPlug = packet->payload[PACKET_FROM+1] &0xF; //To 12bit node id, 4 bit plug id decodedPacket.toNode = packet->payload[PACKET_TO]; decodedPacket.toNode = decodedPacket.toNode << 4; decodedPacket.toNode = decodedPacket.toNode | (packet->payload[PACKET_TO+1] >> 4); decodedPacket.toPlug = packet->payload[PACKET_TO+1] &0xF; //packet id decodedPacket.id = packet->payload[PACKET_ID]; //Command decodedPacket.command = packet->payload[PACKET_COMMAND]; decodedPacket.ptr = packet->payload[PACKET_LENGTH] - OFFSET_PACKET; Payload *payload = get_payload(packet); for(i=0; i < payload->length; i++){ if(decodedPacket.type < 3) { //single packet TCP or UDP decodedPacket.payload[i] = payload->data[i]; } else if(decodedPacket.type == 3) { //broadcast //todo } } decodedPacket.checksum=packet->checksum; return decodedPacket; } void debug_packet(DataPacket *packet){ DataPacketDecoded sendPacketedDecoded = decode_packet(packet); Serial.print(" sent: "); Serial.println(sendPacketedDecoded.status,DEC); Serial.print(" length: "); Serial.println(sendPacketedDecoded.length,DEC); Serial.print("settings: "); Serial.println(sendPacketedDecoded.settings,DEC); Serial.print(" type: "); Serial.println(sendPacketedDecoded.type,DEC); Serial.print("fromNode: "); Serial.println(sendPacketedDecoded.fromNode,DEC); Serial.print("fromPlug: "); Serial.println(sendPacketedDecoded.fromPlug,DEC); Serial.print(" toNode: "); Serial.println(sendPacketedDecoded.toNode,DEC); Serial.print(" toPlug: "); Serial.println(sendPacketedDecoded.toPlug,DEC); Serial.print(" ttl: "); Serial.println(sendPacketedDecoded.ttl,DEC); Serial.print(" id: "); Serial.println(sendPacketedDecoded.id,DEC); Serial.print(" command: "); Serial.println(sendPacketedDecoded.command,DEC); Serial.print(" payload: "); for(i=0; i < sendPacketedDecoded.ptr; i++){ Serial.print(sendPacketedDecoded.payload[i],DEC); Serial.print(","); } Serial.print(" payload: "); for(i=0; i < sendPacketedDecoded.ptr; i++){ Serial.print(sendPacketedDecoded.payload[i],BYTE); Serial.print(","); } Serial.println(""); Serial.print("checksum: "); Serial.println(sendPacketedDecoded.checksum,DEC); Serial.print(" ptr: "); Serial.println(sendPacketedDecoded.ptr,DEC); }
No comments:
Post a Comment