Code after the jump
Arduino Code
//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 65 #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_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 sent; 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 fromPort; uint16_t toNode; //00 is base //xffff is broadcast uint8_t toPort; 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 sent; uint8_t payload[56]; uint16_t checksum; } DataPacket; //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 //send_test_packet.pde #includeh> //checksum functions #include "protocol.h" #define NODE_ID 0x02 #define PORT_A DVC_LM33 #define PORT_B DVC_LM33 #define PORT_C DVC_LM33 #define PORT_D DVC_LM33 #define PACKET_BUFFER 4 //can be adujsted based on availbe space #define debug 1; //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 // DataPacket data[PACKET_BUFFER]; DataPacketDecoded dataDecoded[2]; byte dataPtr = 0; uint16_t checksum; byte dataId = 0; byte packetIds = 0; byte uniqueId = 0; byte i; DataPacket incomingPacket; //current incoming packet //incomingPacket.ptr = 0; byte getNewPacketId() { for(i=0; i < PACKET_BUFFER; i++) { if(data[i].payload[PACKET_SETTINGS] == 0){ return i; } } } byte getId() { return uniqueId++; //what happens when this overflows? } uint16_t compressAddress(uint16_t node, uint8_t port) { return (node << 4) | (port & 0x0F); } boolean send_packet_serial(uint8_t packetId) { uint16_t dataChecksum = 0; for(i=0; i < (data[packetId].payload[PACKET_LENGTH]-2); i++){ dataChecksum = _crc16_update(dataChecksum, data[packetId].payload[i]); Serial.print(data[packetId].payload[i],BYTE); // Serial.print(","); } data[packetId].status = 1; data[packetId].checksum = dataChecksum; //Serial.println(""); // Serial.print("checksum: "); //Serial.print(dataChecksum,BYTE); //Serial.print("checksum: "); Serial.print(highByte(dataChecksum),BYTE); // Serial.print(","); Serial.print(lowByte(dataChecksum),BYTE);//*/ } uint8_t build_tcp_packet(uint16_t fromNode, uint8_t fromPort, uint16_t toNode, uint8_t toPort, uint8_t command, uint8_t payload[48], uint8_t length) { byte packetId = getNewPacketId(); data[packetId].status = 0; data[packetId].payload[PACKET_LENGTH] = length + 10; //header 8 crc 2 data[packetId].payload[PACKET_SETTINGS] = 1; uint16_t address = compressAddress(fromNode, fromPort); data[packetId].payload[PACKET_FROM] = highByte(address); data[packetId].payload[PACKET_FROM+1] = lowByte(address); address = compressAddress(toNode, toPort); data[packetId].payload[PACKET_TO ] = highByte(address); data[packetId].payload[PACKET_TO+1] = lowByte(address); data[packetId].payload[PACKET_ID] = getId(); data[packetId].payload[PACKET_COMMAND] = command; for(i=0;i < length;i++){ data[packetId].payload[PACKET_PAYLOAD+i] = payload[i]; } return packetId; } byte build_udp_packet(uint16_t fromNode, uint8_t fromPort, uint16_t toNode, uint8_t toPort, uint8_t command, uint8_t payload[48], uint8_t length) { byte packetId = getNewPacketId(); data[packetId].status = 0; data[packetId].payload[PACKET_LENGTH] = length + 10; data[packetId].payload[PACKET_SETTINGS] = 2; uint16_t address = compressAddress(fromNode, fromPort); data[packetId].payload[PACKET_FROM] = highByte(address); data[packetId].payload[PACKET_FROM+1] = lowByte(address); address = compressAddress(toNode, toPort); data[packetId].payload[PACKET_TO ] = highByte(address); data[packetId].payload[PACKET_TO+1] = lowByte(address); data[packetId].payload[PACKET_ID] = getId(); data[packetId].payload[PACKET_COMMAND] = command; for(i=0;i < length;i++){ data[packetId].payload[PACKET_PAYLOAD+i] = payload[i]; } return packetId; } 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].status = 0; return packetId; } void process_command(DataPacketDecoded packet) { switch (packet.command) { case CMD_PING: //replyPacket.payload = packet.payload; //replyPacket.command = CMD_PONG; //replyPacket.fromNode = NODE_ID; //send_packet(packet); break; default: //send_packet(COMMAND_ERROR,NULL,0); break; } } /** * 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.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.ptr = packet.payload[PACKET_LENGTH] - 8; for(i=PACKET_PAYLOAD; i < (packet.payload[PACKET_LENGTH] - 2); 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 } } decodedPacket.checksum=packet.checksum; return decodedPacket; } void build_incoming_packet(uint8_t bIn) { if(incomingPacket.ptr == 0){ //Packet length if(bIn == 0) { //resend last return; } if(bIn == 255) { //aknowledge //delete packet from que //reset last pointer return; } if (bIn > 128) { //stop sending current packet //flush return; } incomingPacket.payload[PACKET_LENGTH] = bIn; uint16_t temp; checksum = 0; } //checksum if(incomingPacket.ptr < incomingPacket.payload[PACKET_LENGTH]){ //add to check sum incomingPacket.payload[incomingPacket.ptr] = bIn; checksum = _crc16_update(checksum, bIn); } else if(incomingPacket.ptr == incomingPacket.payload[PACKET_LENGTH]){ //get first byte of checksum incomingPacket.checksum = bIn; } else { //get second byte and check the checksum incomingPacket.checksum = (incomingPacket.checksum << 8) | bIn; if(checksum != incomingPacket.checksum) { //Serial.println(checksum, DEC); //Serial.println(incomingPacket.checksum, DEC); //Serial.println("Failed CRC Check"); incomingPacket.ptr=0; } else { i = getNewPacketId(); data[i] = incomingPacket; incomingPacket.ptr=0; } } incomingPacket.ptr++; } void setup() { Serial.begin(115200); } void loop() { byte message[1] = {uniqueId}; int sendPacketId = build_udp_packet(NODE_ID, 1, 0, 0, CMD_PING, message, 1); send_packet_serial(sendPacketId); delay(2000); }
Processing Code
//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 = 65; 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; 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() { } } //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; 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() { return uniqueId++; //what happens when this wraps? } int compressAddress(int node, int port) { node = node << 4; //make space port = port & 0x0F; return node | port; } import processing.serial.*; //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; DataPacket data[]; int dataPtr = 0; int checksum; int dataId = 0; int packetIds = 0; int uniqueId = 0; int i; DataPacket incomingPacket = new DataPacket(); //current incoming packet int bgcolor; // Background color int fgcolor; // Fill color Serial myPort; // The serial port int[] serialInArray = new int[3]; // Where we'll put what we receive int serialCount = 0; // A count of how many bytes we receive boolean firstContact = false; // Whether we've heard from the microcontroller PFont myFont; void setup() { size(400, 400); // Stage size //noStroke(); // No border on the next thing drawn myFont = createFont("Consolas", 14); textFont(myFont); // Print a list of the serial ports, for debugging purposes: //println(PFont.list()); String portName = Serial.list()[1]; myPort = new Serial(this, portName, 115200); } void draw() { //text("Hello",10,10); //text("Z", 10, 220); // Draw the shape } void serialEvent(Serial myPort) { // read a byte from the serial port: int inByte = myPort.read(); build_incoming_packet(inByte); } //#include//checksum functions 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); } packet.status = 1; myPort.write(dataChecksum & 0xFFFF); return true; } DataPacket build_tcp_packet(int fromNode, int fromPort, int toNode, int toPort, int command, int payload[]) { DataPacket packet = new DataPacket(); //packet.payload[PACKET_LENGTH] = length + 8; packet.payload[PACKET_SETTINGS] = 1; int address = compressAddress(fromNode, fromPort); packet.payload[PACKET_FROM] = (address >> 8) & 0xFF; packet.payload[PACKET_FROM+1] = address & 0xFF; address = compressAddress(toNode, toPort); 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[i]; } return packet; } DataPacket build_udp_packet(int fromNode, int fromPort, int toNode, int toPort, int command, int payload[]) { DataPacket packet = new DataPacket(); //packet.payload[PACKET_LENGTH] = length + 8; packet.payload[PACKET_SETTINGS] = 2; int address = compressAddress(fromNode, fromPort); packet.payload[PACKET_FROM] = (char)(address >> 8) & 0xFF; packet.payload[PACKET_FROM+1] = (char)address & 0xFF; address = compressAddress(toNode, toPort); packet.payload[PACKET_TO ] = (char)(address >> 8) & 0xFF; packet.payload[PACKET_TO+1] = (char)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[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; } */ void process_command(DataPacketDecoded packet) { switch (packet.command) { case CMD_PING: //replyPacket.payload = packet.payload; //replyPacket.command = CMD_PONG; //replyPacket.fromNode = NODE_ID; //send_packet(packet); break; default: //send_packet(COMMAND_ERROR,NULL,0); break; } } /** * 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 build_incoming_packet(int bIn) { //add timout to reset if packets get jamed println("count: "+incomingPacket.ptr + " byte: " + bIn); if(incomingPacket.ptr == 0){ //Packet length if(bIn == 0) { //resend last return; } if(bIn == 255) { //aknowledge //delete packet from que //reset last pointer return; } if (bIn > 66) { //stop sending current packet //flush return; } incomingPacket.payload[PACKET_LENGTH] = bIn; println("length: "+bIn); checksum = 0; } //checksum if(incomingPacket.ptr < (incomingPacket.payload[PACKET_LENGTH]-2)){ //add to check sum incomingPacket.payload[incomingPacket.ptr] = bIn; checksum = _crc16_update(checksum, bIn); } else if(incomingPacket.ptr == (incomingPacket.payload[PACKET_LENGTH]-2)){ //get first byte of checksum incomingPacket.checksum = bIn; } else { //get second byte and check the checksum incomingPacket.checksum = (incomingPacket.checksum << 8) | (bIn & 0xFF); if(checksum != incomingPacket.checksum) { println("processing checksum: " + checksum); println(" packet checksum: " + incomingPacket.checksum); println("Failed CRC Check"); } else { println("processing checksum: " + checksum); println(" packet checksum: " + incomingPacket.checksum); println("Passed CRC Check"); debug_incoming_packet(incomingPacket); //check packet address, if it matches, process command, if not add to queue to resend to other nodes //i = getNewPacketId(); //data[i] = incomingPacket; //process_command(incomingPacket); //incomingPacket = DataPacket; } //reset incoming packet incomingPacket = new DataPacket(); return; } incomingPacket.ptr++; } 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 = ""; for(i=0; i < packetDecoded.ptr; i++){ message += int(packetDecoded.payload[i]); //message += char(packetDecoded.payload[i]); } text(" payload: " + message,10,x+=20); text("checksum: " + packetDecoded.checksum,10,x+=20); text(" ptr: " + packetDecoded.ptr,10,x+=20);//*/ }
No comments:
Post a Comment