Difference between revisions of "U23 2007/MateCrew"

From C4 Wiki
Jump to: navigation, search
(LED-Dimmer)
(Serverdienst)
 
(9 intermediate revisions by 2 users not shown)
Line 1: Line 1:
==avr-portremote-server==
+
==avr-portremote==
 
Unser Hauptprojekt ist eine komplette Implementierung eines Dienstes auf dem Etherrape mit zugehörigem Client und eigens entwickeltem Protokoll zur Steuerung der IO Pins über die Netzwerkschnittstelle. Hierzu fassen wir ein Passwort, ein Kommando, den IO Port und einen Wert, der gesetzt/weggenommen werden soll, in unsere Protokollimplementierung.
 
Unser Hauptprojekt ist eine komplette Implementierung eines Dienstes auf dem Etherrape mit zugehörigem Client und eigens entwickeltem Protokoll zur Steuerung der IO Pins über die Netzwerkschnittstelle. Hierzu fassen wir ein Passwort, ein Kommando, den IO Port und einen Wert, der gesetzt/weggenommen werden soll, in unsere Protokollimplementierung.
  
Im folgenden die Implementierung des Clients:
+
Der Dienst basiert zur Zeit auf dem restructure branch der etherrape Firmware.
 +
 
 +
===Client===
  
 
   
 
   
Line 193: Line 195:
 
  if(connect(mysocket,(sockaddr*)&target,sizeof(target))<0)
 
  if(connect(mysocket,(sockaddr*)&target,sizeof(target))<0)
 
 
 
 
  err<<"failed to establish connection"<<endl;
+
  cerr<<"failed to establish connection"<<endl;
 
 
 
 
 
 
 
 
Line 229: Line 231:
 
  }
 
  }
  
 +
===Serverdienst===
 +
// fnord.h
 +
 +
void handle_fnord(void);
 +
void init_fnord(void);
 +
 +
#define FNORD_PORT 2324
 +
 +
#define NET_SET_PORT 3
 +
#define NET_GET_PORT 2
 +
#define NET_SUB_PORT 1
 +
#define NET_ADD_PORT 0
 +
 +
#define FNORD_PASS "fnord"
  
portremoted:
+
// fnord.c
 +
 
  #include <string.h>
 
  #include <string.h>
 
   
 
   
Line 236: Line 253:
 
  #include "../debug.h"
 
  #include "../debug.h"
 
  #include "fnord.h"
 
  #include "fnord.h"
 +
 +
const char* FNORD_KEY = "A";
 
   
 
   
 
  struct fnord_command{
 
  struct fnord_command{
 +
 
  /*
 
  /*
* stores all needed protocol data
+
stores all needed protocol data
*/
+
*/
  uint8_t ctype; //command type (set,unset,additive,substractive)
+
  uint8_t ioport; //ioport  (PORTA/C/D)
+
  uint8_t ctype;     //command type (set,unset,additive,substractive)
  uint8_t data;   //data (1 byte)
+
  uint8_t ioport;   //ioport  (PORTA/C/D)
 +
  uint8_t data;   //data (1 byte)
 
   
 
   
 
  } incoming_command;
 
  } incoming_command;
 
   
 
   
 
  void init_fnord(void){
 
  void init_fnord(void){
        // we listen on port 2324 (defined in fnord.h)
+
 +
// we listen on port 2324 (defined in fnord.h)
 
  uip_listen(HTONS(FNORD_PORT));
 
  uip_listen(HTONS(FNORD_PORT));
 +
debug_printf(">>> INITIALISING FNORD <<<\n\n");
 
   
 
   
 
  }
 
  }
 
   
 
   
 +
inline void net_set_ddr(void) {
 +
cfg.options.io_ddr[(incoming_command.ioport)] |= incoming_command.data;
 +
}
 
   
 
   
 
  void net_add_port(){
 
  void net_add_port(){
 
  /*
 
  /*
* add incoming value to PORTX
+
add incoming value to PORTX
*/
+
*/
  cfg.options.io_ddr[(incoming_command.ioport)] |= incoming_command.data;  
+
  net_set_ddr();
  cfg.options.io[(incoming_command.ioport)] |= incoming_command.data;  
+
  cfg.options.io[(incoming_command.ioport)] |= incoming_command.data;
 
   
 
   
 
  }
 
  }
Line 265: Line 291:
 
  void net_sub_port(){
 
  void net_sub_port(){
 
  /*
 
  /*
* substract incoming value from PORTX
+
substract incoming value from PORTX
*/
+
*/
 
  cfg.options.io[(incoming_command.ioport)] &= ~(incoming_command.data);  
 
  cfg.options.io[(incoming_command.ioport)] &= ~(incoming_command.data);  
 
   
 
   
Line 272: Line 298:
 
   
 
   
 
  void net_get_port(){
 
  void net_get_port(){
/*
+
  * return value of PORTX
+
/*
  */
+
return PORT information (PORT#, value)
 +
*/
 
  ((uint8_t *)uip_appdata)[0]=NET_GET_PORT;
 
  ((uint8_t *)uip_appdata)[0]=NET_GET_PORT;
 
  ((uint8_t *)uip_appdata)[1]=incoming_command.ioport;
 
  ((uint8_t *)uip_appdata)[1]=incoming_command.ioport;
Line 285: Line 312:
 
   
 
   
 
  void net_set_port(){
 
  void net_set_port(){
/*
+
  * write incoming value to PORTX
+
/*
  */
+
set PORTX to incoming value
 +
*/
 +
net_set_ddr();
 
  cfg.options.io[(incoming_command.ioport)] = incoming_command.data;
 
  cfg.options.io[(incoming_command.ioport)] = incoming_command.data;
 +
}
 +
 +
void decrypt(){
 +
 +
 +
//uint8_t size=strlen(FNORD_KEY);
 +
uint8_t size=1;
 +
 +
debug_printf("FNORD_KEY is: '%s'\n",FNORD_KEY);
 +
 +
for(uint8_t i=0;i<(uip_datalen()-1);i++){
 +
 +
((uint8_t *)uip_appdata)[i]^=FNORD_KEY[i%size];
 +
 +
}
 +
 
  }
 
  }
 
   
 
   
 
  void handle_fnord(void) {
 
  void handle_fnord(void) {
+
 +
/*
 +
handle incomming connection and data
 +
*/
 +
 
  uint8_t logged_in=0;
 
  uint8_t logged_in=0;
 
 
 
 
  if(uip_connected())
+
//has a new client connected?
  debug_print("New client connected\n");
+
  if(uip_connected()) {
 
+
  debug_printf("New client connected\n");
 +
  debug_printf("clientIP: %d.%d.%d.%d clientPORT: %u\n\n", LO8(uip_conn->ripaddr[0]),
 +
HI8(uip_conn->ripaddr[0]),
 +
LO8(uip_conn->ripaddr[1]),
 +
  HI8(uip_conn->ripaddr[1]),
 +
  HTONS(uip_conn->rport));
 +
}
 +
 +
//do we have new data in buffer?
 
  if(uip_newdata()) {
 
  if(uip_newdata()) {
  ((uint8_t *)uip_appdata)[uip_datalen()] = 0;
+
debug_printf("new data in buffer, initialising decryption\n");
 +
debug_printf("before decryption: '%s' \n",(uint8_t *)uip_appdata);
 +
decrypt(); //call decrypt function
 +
debug_printf("after decryption:  '%s' \n\n",(uint8_t *)uip_appdata);
 +
 +
  ((uint8_t *)uip_appdata)[uip_datalen()] = 0; //prevent overflows
 
 
 
 
 
+
  //password hard coded in fnord.h
  uint8_t offset=0;
+
  uint8_t offset;
 
  char password[uip_len];
 
  char password[uip_len];
 
 
 
 
  for(offset;((uint8_t *)uip_appdata)[offset]!=' ' && offset<uip_len;offset++){
+
//parse password out of incoming data
 +
  for(offset=0;((uint8_t *)uip_appdata)[offset]!=' ' && offset<uip_len;offset++){
 
  password[offset]=((uint8_t *)uip_appdata)[offset];
 
  password[offset]=((uint8_t *)uip_appdata)[offset];
 
  }
 
  }
Line 313: Line 376:
 
  debug_printf("Password is: '%s', user entered: '%s' \n",FNORD_PASS,password);
 
  debug_printf("Password is: '%s', user entered: '%s' \n",FNORD_PASS,password);
 
 
 
 
 +
//check password
 
  if(!(strcmp(password,FNORD_PASS)))
 
  if(!(strcmp(password,FNORD_PASS)))
 
  logged_in=1;
 
  logged_in=1;
 
  else
 
  else
 
  logged_in=0;
 
  logged_in=0;
+
 
  if(logged_in){
 
  if(logged_in){
  debug_print("Password correct, logged in!\n\n");
+
  debug_printf("Password correct, logged in!\n\n");
 
+
 +
  // write incoming data (command,port,data) into structure
 
  incoming_command.ctype=((uint8_t *)uip_appdata)[++offset];
 
  incoming_command.ctype=((uint8_t *)uip_appdata)[++offset];
 
  incoming_command.ioport=((uint8_t *)uip_appdata)[++offset];
 
  incoming_command.ioport=((uint8_t *)uip_appdata)[++offset];
 
  incoming_command.data=((uint8_t *)uip_appdata)[++offset];
 
  incoming_command.data=((uint8_t *)uip_appdata)[++offset];
 
 
 
 
  debug_print("New data recieved:\n");
+
  debug_printf("New data recieved:\n");
 
  debug_printf("ctype: %i\n",incoming_command.ctype);
 
  debug_printf("ctype: %i\n",incoming_command.ctype);
 
  debug_printf("ioport: %i\n",incoming_command.ioport);
 
  debug_printf("ioport: %i\n",incoming_command.ioport);
 
  debug_printf("data: %i\n\n\n",incoming_command.data);
 
  debug_printf("data: %i\n\n\n",incoming_command.data);
 
 
 
 
 +
//choose the right operation (command)
 
  switch(incoming_command.ctype){
 
  switch(incoming_command.ctype){
 
  case NET_ADD_PORT: net_add_port();
 
  case NET_ADD_PORT: net_add_port();
Line 342: Line 408:
 
  }
 
  }
 
  else
 
  else
  debug_print("Incorrect password!\n\n\n");
+
  debug_printf("Incorrect password!\n\n\n");
 
  }
 
  }
 
 
  }
 
  }
  

Latest revision as of 20:01, 28 June 2007

avr-portremote

Unser Hauptprojekt ist eine komplette Implementierung eines Dienstes auf dem Etherrape mit zugehörigem Client und eigens entwickeltem Protokoll zur Steuerung der IO Pins über die Netzwerkschnittstelle. Hierzu fassen wir ein Passwort, ein Kommando, den IO Port und einen Wert, der gesetzt/weggenommen werden soll, in unsere Protokollimplementierung.

Der Dienst basiert zur Zeit auf dem restructure branch der etherrape Firmware.

Client

/* Der Client hat 2 Modi:
// 1. Interactive: Einlesen der benötigten Werte durch einzelne Abfragen (benötigt nur Ip-Adresse und Port)
// 2. Automatic: Einlesen aller Werte über Argumente (benötigt Ip-Adresse,Port,Passwort,Kommando,IO Port Nr.,Wert)
*/

#include <iostream>
#include <string>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <math.h>

#define MAX_COMMANDS 4
#define MAX_PORTS 3
//#define DEBUG 	// setzen fuer debug ausgaben
#define MAX_ARGS 7

#define GET_MODE 2

using namespace std;

char * command_types[MAX_COMMANDS]={"additive","substractive","get","set"};
char * port_types[MAX_PORTS]={"DDRA","DDRC","DDRD"};


struct remote_command{
/*{{{*/	
	string password;
	unsigned int command_type;
	unsigned int ioport;
	unsigned int value;

/*}}}*/

} user_command;

void list_commands(){
/*{{{*/
	for(int i=0;i<MAX_COMMANDS;i++)

		cout<<"["<<i<<"]"<<"\t "<<command_types[i]<<endl;
/*}}}*/
}


void list_ports(){
/*{{{*/
	for(int i=0;i<MAX_PORTS;i++)

		cout<<"["<<i<<"]"<<"\t "<<port_types[i]<<endl;
/*}}}*/
}

void interactive(){

	unsigned int input;

	cout<<"Please insert your password: ";
	cin>>user_command.password;

	do{

		list_commands();
		cout<<"Please specify a command: ";
	 	cin>>user_command.command_type; 

	}while(user_command.command_type < 0 || user_command.command_type > MAX_COMMANDS);
	
	if( user_command.command_type!= GET_MODE){ 

		do{
	  		list_ports();					
			cout<<"Please specify a port: ";
			cin>>user_command.ioport;

		}while(user_command.ioport < 0 || user_command.ioport > MAX_PORTS);
 		
  	
		do{
			cout<<"Please specify the value in hex: 0x";
			cin>>hex>>user_command.value;
			#ifdef DEBUG
			cout<<endl<<"der value ist: "<<user_command.value<<endl;
			#endif
			if(user_command.value>255)		
				cout<<"Value "<<user_command.value<<" too high!!!"<<endl<<"Please try again!"<<endl;
		
		}while(user_command.value>255);
	} 

	else{
		user_command.ioport=user_command.value=0;
	}

}

void make_request(string& request,char* pw=0,char* com=0,char* ioport=0,int dec_val=0){
/*{{{*/	
		request= ( (pw!=NULL) ? pw : user_command.password ) ;
		request+=" ";
		request+=( (pw!=NULL) ? ( (unsigned char)atoi(com) ) : ( (char)(user_command.command_type) ) );
		request+=( (pw!=NULL) ? ( (unsigned char)(atoi(ioport)) ):(char)(user_command.ioport));
		request+=( (pw!=NULL) ? ( (unsigned char)(unsigned int)dec_val) : (char)(int)(user_command.value));
	
		#ifndef DEBUG
		cout<<"hier gecastet auf void: "<<(int)&(user_command.value)<<endl;
		#endif

/*}}}*/
}

void write_output(char* buf){
/*{{{*/
	cout<<"Command: "<<command_types[(int)(unsigned char)(buf[0])] 
     	   		 <<endl<<"Port: "<<(int)(unsigned char)(buf[1])
     	   		 <<endl<<"Wert: "<<(int)(unsigned char)(buf[2]);

/*}}}*/
}

int main(int argc,char* argv[]){

	sockaddr_in target;
	int mysocket=socket(AF_INET,SOCK_STREAM,0);
       string request;
	char buf[64]; 

	if(argc < 3){
	
		cout<<"usage: "<<argv[0]<<" {target-ip} {target-port} [password command ioport value]"<<endl;
		exit(1);
	
	}
	
	if(argc < 4 ){
		
		interactive();
		make_request(request);
		
	}
	
	else{ 

		int dec_val=0;
	
		if(argc < MAX_ARGS){ 

			cout<<"Too few arguments for a command!!!"<<endl;
			exit(1); 

		}	
		
	        else{		
		
			#ifdef DEBUG
			cout<<"VALUE IST: "<<argv[6];
			#endif
		
			sscanf(argv[6],"%x",&dec_val);	
			make_request(request,argv[3],argv[4],argv[5],dec_val);
		
		}
	}
	
		
	#ifdef DEBUG
	/*{{{*/	
		cout<<"request is: "<<request<<endl;
		cout<<"length of request:  "<<request.length()<<endl;
		cout<<"values: "<<endl;
		
		for(unsigned int i=0;i<=request.length();i++){
		
			cout<<"position: "<<i<<" int wert: "<<(int)request[i]<<" zeichen: "<<request[i]<<endl;
		
		}
	/*}}}*/
	#endif	 

	target.sin_family=AF_INET;
	target.sin_port=htons(atoi(argv[2]));
	target.sin_addr.s_addr=inet_addr(argv[1]);
	 

	// establish connection
	if(connect(mysocket,(sockaddr*)&target,sizeof(target))<0)
		
		cerr<<"failed to establish connection"<<endl;
	
	
	cout<<"connection established"<<endl;
	 

	//send command to etherrape	
	if(write(mysocket,(void*)request.c_str(),request.length() + 1) < 0)
		
		cerr<<"failed to write data"<<endl;



 	
 	// etherrape will send us the port status 
 	if(user_command.command_type== GET_MODE ){
  	
  	  	if(read(mysocket,(void*)buf,strlen(buf)-1)>=1){
  			
 			write_output(buf);
 		
 		}
 
 		else{ 
 
 			cerr<<"failed to read data"<<endl;
 		
 		}
 	
 	} 

	close(mysocket);
	
	return 0;
}

Serverdienst

// fnord.h

void handle_fnord(void);
void init_fnord(void);

#define FNORD_PORT 2324

#define NET_SET_PORT 3
#define NET_GET_PORT 2
#define NET_SUB_PORT 1 
#define NET_ADD_PORT 0

#define FNORD_PASS "fnord"
// fnord.c

#include <string.h>

#include "../uip/uip.h"
#include "../debug.h"
#include "fnord.h"

const char* FNORD_KEY = "A";

struct fnord_command{

	/*
		stores all needed protocol data
	*/

	uint8_t ctype;     //command type (set,unset,additive,substractive)
	uint8_t ioport;	   //ioport  (PORTA/C/D)
	uint8_t data;	   //data (1 byte)

} incoming_command;

void init_fnord(void){
	
	// we listen on port 2324 (defined in fnord.h)
	uip_listen(HTONS(FNORD_PORT));
	debug_printf(">>> INITIALISING FNORD <<<\n\n");

}

inline void net_set_ddr(void) {
	cfg.options.io_ddr[(incoming_command.ioport)] |= incoming_command.data;
}

void net_add_port(){
	/*
		add incoming value to PORTX
	*/
	net_set_ddr();
	cfg.options.io[(incoming_command.ioport)] |= incoming_command.data;

}

void net_sub_port(){
	/*
		substract incoming value from PORTX
	*/
	cfg.options.io[(incoming_command.ioport)] &= ~(incoming_command.data); 

}

void net_get_port(){
	
	/*
		return PORT information (PORT#, value)
	*/
	((uint8_t *)uip_appdata)[0]=NET_GET_PORT;
	((uint8_t *)uip_appdata)[1]=incoming_command.ioport;
	((uint8_t *)uip_appdata)[2]=cfg.options.io[(incoming_command.ioport)];
	((uint8_t *)uip_appdata)[3]='\0';
	
	uip_send(uip_appdata,4);

}

void net_set_port(){

	/*
		set PORTX to incoming value
	*/
	net_set_ddr();
	cfg.options.io[(incoming_command.ioport)] = incoming_command.data;
}

void decrypt(){
	
	
	//uint8_t size=strlen(FNORD_KEY);
	uint8_t size=1;

	debug_printf("FNORD_KEY is: '%s'\n",FNORD_KEY);

	for(uint8_t i=0;i<(uip_datalen()-1);i++){
	
		((uint8_t *)uip_appdata)[i]^=FNORD_KEY[i%size];	
	
	}
	
}

void handle_fnord(void) {
	
	/*
		handle incomming connection and data
	*/
	
	uint8_t logged_in=0;
	
	//has a new client connected?
	if(uip_connected()) {
		debug_printf("New client connected\n");
		debug_printf("clientIP: %d.%d.%d.%d clientPORT: %u\n\n", LO8(uip_conn->ripaddr[0]),
	 								 HI8(uip_conn->ripaddr[0]),
									 LO8(uip_conn->ripaddr[1]),
						  			 HI8(uip_conn->ripaddr[1]),
						  			 HTONS(uip_conn->rport));
	}

	//do we have new data in buffer?
	if(uip_newdata()) {
		debug_printf("new data in buffer, initialising decryption\n");
		debug_printf("before decryption: '%s' \n",(uint8_t *)uip_appdata);
		decrypt(); //call decrypt function
		debug_printf("after decryption:  '%s' \n\n",(uint8_t *)uip_appdata);

		((uint8_t *)uip_appdata)[uip_datalen()] = 0; //prevent overflows
		
		//password hard coded in fnord.h
		uint8_t offset;
		char password[uip_len];
		
		//parse password out of incoming data
		for(offset=0;((uint8_t *)uip_appdata)[offset]!=' ' && offset<uip_len;offset++){
				password[offset]=((uint8_t *)uip_appdata)[offset];	
		}
		
		password[offset]='\0';
		
		debug_printf("Password is: '%s', user entered: '%s' \n",FNORD_PASS,password);
		
		//check password
		if(!(strcmp(password,FNORD_PASS)))
			logged_in=1;
		else
			logged_in=0;
		
		if(logged_in){
			debug_printf("Password correct, logged in!\n\n");
		
			// write incoming data (command,port,data) into structure	
			incoming_command.ctype=((uint8_t *)uip_appdata)[++offset];
			incoming_command.ioport=((uint8_t *)uip_appdata)[++offset];
			incoming_command.data=((uint8_t *)uip_appdata)[++offset];
			
			debug_printf("New data recieved:\n");
			debug_printf("ctype: %i\n",incoming_command.ctype);
			debug_printf("ioport: %i\n",incoming_command.ioport);
			debug_printf("data: %i\n\n\n",incoming_command.data);
			
			//choose the right operation (command)
			switch(incoming_command.ctype){
				case NET_ADD_PORT: net_add_port();
					  break;
				case NET_SUB_PORT: net_sub_port();
					  break;
				case NET_GET_PORT: net_get_port(); 	
					  break;
				case NET_SET_PORT: net_set_port();
					  break;
			}
		}
		else
			debug_printf("Incorrect password!\n\n\n");
	}
}

LED-Dimmer

Für unseren Dimmer für LEDs benutzen wir insgesamt 3 Funktionen:

  • Die Main mit einer Endlosschleife für ewiges hell und dunkel Dimmen durch Aufruf von den andern Beiden Funktionen
  • Die Funktion my_wait(uint32_t time), welche einfach wartet
  • Die Funktion dim(uint8_t ratio), welche für den schnellen Ein-/Ausschaltvorgang der LEDs zuständig ist

Die Main:

 #include <avr/io.h>

 #define F_CPU 2000000000L
 #include <util/delay.h>

 void my_wait(uint32_t);
 void dim(uint8_t); 
 int main(){	
   DDRA=0xff;
 
   // LED ausschalten
   PORTA=0;
   uint16_t i=0;    
   PORTA|=0x02;
 
   //Die Endlosschleife
   for(;;){
     for(i=0;i<0xfff;i++){
 
       // ein bisschen warten
       my_wait(1);
 
       // ein- und ausschalten
       // je größer i wird desto größer wird auch der Quotient der an bla übergeben wird
       // dadurch verändert sich auch der zeitliche Abstand zwischen dem Ein- und Ausschalten
       // wodurch die LED wiederum heller oder dunkler erscheint
       dim(i/0xf);		
     }
   }
   PORTA|=0x03;	
   return 0;
 }

Die Wait:

 void my_wait(uint32_t time)
 {	
   uint32_t i=0;
   for(i;i<(time);i++)
 
   //vordefinierte Funktion welche einen Leerlauf in Dauer von n Milisekunden auslöst
   _delay_ms(1);
 }

Die Dim:

 void dim(uint8_t ratio){
   uint32_t i=0;	
 
   // LED anschalten
   PORTA|=0x01;
   for(i;i<ratio;i++){}
 
   // LED ausschalten
   PORTA&=~0x01;
   for(i=ratio;i<255;i++){}
 }

Project

Im Großen und Ganzen ist alles Lauffähig. Beim nächsten Termin werden TODO Liste und Programmtests in Angriff genommen, sodass wir eventuell noch ein Projekt durchführen können.

TODO

  • Verschlüsselte Passwortübergabe
  • Ablegen des Passwortes im Flash (momentan hart Codiert)
  • Retransmitting ?

Team

  • scout
  • F3lix
  • Toby