#include "brick.h" #include <stdio.h> #include <stdlib.h> #include <time.h> #include <string> #include <windows.h> #include "error.h" #define MSG_SIZE 64 Brick::Brick(Connection *connection){ this->connection = connection; } void Brick::write_msg(string message, int inbox, bool reply){ unsigned char answer[NXT_BUFFER_SIZE]; unsigned char command[NXT_BUFFER_SIZE]; unsigned int i=0; unsigned int length=message.length(); if(length>57){ length = 57; } command[0]=length+5; //command length command[1]=0x00; if(reply){ command[2]=0x00; } else{ command[2]=0x80; } command[3]=0x09; if(inbox>9){ inbox=9; } command[4]=inbox; command[5]=length+1; while(i<length){ command[i+6]=message[i]; i++; } command[i+6]='\0'; connection->send(&command[0],length+7); if(reply){ connection->receive(&answer[0],5); if(answer[4]){ throw Nxt_exception::Nxt_exception("write_msg","Brick", 0x00FF & answer[4]); } } return; } string Brick::read_msg(int inbox, bool remove){ unsigned int i; unsigned char answer[NXT_BUFFER_SIZE+2]; unsigned char command[7]; command[0]=0x05; //command length command[1]=0x00; command[2]=0x00; command[3]=0x13; command[4]=10+inbox; command[5]=0x00; command[6]=remove; connection->send(&command[0],7); connection->receive(&answer[0],66); if(answer[4]){ throw Nxt_exception::Nxt_exception("read_msg","Brick", answer[4]); } i=7; string result; result.resize(59); while((answer[i]!='\0')){ result[i-7]=answer[i]; i++; } result[i-7]='\0'; //connection->flush(); return result; } void Brick::set_name(string name, bool reply){ unsigned char answer[NXT_BUFFER_SIZE]; unsigned char command[NXT_BUFFER_SIZE]; unsigned int length=name.length(); unsigned int i; if(length>15){ length=15; } command[0]=length+3; //command length command[1]=0x00; //start of message if(reply){ command[2] = 0x01; } else{ command[2] = 0x81; } command[3]=0x98; for(i=0; i<length ;i++){ command[i+4]=name[i]; } command[i+4]='\0'; connection->send(&command[0],length+5); Sleep(200); if(reply){ connection->receive(&answer[0],5); if(answer[4]){ throw Nxt_exception::Nxt_exception("set_name","Brick", 0x00FF & answer[4]); } } return; } void Brick::get_device_info(Device_info &info){ unsigned int i; unsigned char answer[NXT_BUFFER_SIZE]; unsigned char command[4]; command[0] = 0x02; command[1] = 0x00; command[2] = 0x01; command[3] = 0x9b; connection->send(&command[0],4); connection->receive(&answer[0],35); if(answer[4]){ throw Nxt_exception::Nxt_exception("get_device_info","Brick", 0x00FF & answer[4]); } info.name.resize(15); i=0; while(i<15){ info.name[i]=answer[i+5]; i++; } info.bt_address.resize(21); i=0; while(i<7){ sprintf(&info.bt_address[i*3], "%02X:", answer[i+20]); i++; } info.bt_address[20] = '\0'; //LEGO has not implemented Bluetooth strengh //bt_strength = ((0xff & answer[27]) | ( answer[28] << 8) | (answer[29] << 16) | (answer[30] << 24) ); info.flash_memory = ((0xff & answer[31]) | ( answer[32] << 8) | ( answer[33] << 16) | ( answer[34] << 24) ); return; } string Brick::get_name(){ this->get_device_info(this->info); return this->info.name; } void Brick::keep_alive(bool reply){ unsigned char answer[NXT_BUFFER_SIZE]; unsigned char command[4]; command[0]=0x02; //command length command[1]=0x00; if(reply){ command[2]=0x00; } else{ command[2]=0x80; } command[3]=0x0D; connection->send(&command[0],4); if(reply){ connection->receive(&answer[0],9); if(answer[4]){ throw Nxt_exception::Nxt_exception("keep_alive","Brick", 0x00FF & answer[4]); } } return; } void Brick::play_tone(unsigned int freq, unsigned int time, bool reply){ unsigned char answer[NXT_BUFFER_SIZE]; unsigned char command[8]; command[0]=0x06; //command length command[1]=0x00; if(reply){ command[2]=0x00; } else{ command[2]=0x80; } command[3]=0x03; command[4]=freq; command[5]=freq >>8; command[6]=time; command[7]=time >> 8; connection->send(&command[0],8); if(reply){ connection->receive(&answer[0],5); if(answer[4]){ throw Nxt_exception::Nxt_exception("play_tone","Brick", 0x00FF & answer[4]); } } return; } void Brick::beep(unsigned int time, bool reply){ play_tone(1000,time, reply); } void Brick::play_soundfile(string file, bool loop, bool reply){ unsigned char answer[NXT_BUFFER_SIZE]; unsigned char command[NXT_BUFFER_SIZE]; unsigned int length=file.length(); unsigned int i; if(length>19){ length=19; } command[0]=length+4; //command length command[1]=0x00; //start of message if(reply){ command[2]=0x00; } else{ command[2]=0x80; } command[3]=0x02; command[4]=loop; for(i=0; i<length ;i++){ command[i+5]=file[i]; } command[i+5]='\0'; connection->send(&command[0],length+6); if(reply){ connection->receive(&answer[0],5); if(answer[4]){ throw Nxt_exception::Nxt_exception("play_soundfile","Brick", 0x00FF & answer[4]); } } return; } void Brick::stop_soundplayback(bool reply){ unsigned char answer[NXT_BUFFER_SIZE]; unsigned char command[4]; command[0]=0x02; //command length command[1]=0x00; if(reply){ command[2]=0x00; } else{ command[2]=0x80; } command[3]=0x0C; connection->send(&command[0],4); if(reply){ connection->receive(&answer[0],5); if(answer[4]){ throw Nxt_exception::Nxt_exception("stop_soundplayback","Brick", 0x00FF & answer[4]); } } return; } void Brick::start_program(string file, bool reply){ unsigned char answer[NXT_BUFFER_SIZE]; unsigned char command[NXT_BUFFER_SIZE]; int length=file.length(); int i; if(length>19){ length=19; } command[0]=length+3; //command length command[1]=0x00; //start of message if(reply){ command[2]=0x00; } else{ command[2]=0x80; } command[3]=0x00; for(i=0; i<length ;i++){ command[i+4]=file[i]; } command[i+4]='\0'; connection->send(&command[0],length+5); if(reply){ connection->receive(&answer[0],5); if(answer[4]){ throw Nxt_exception::Nxt_exception("start_program","Brick", 0x00FF & answer[4]); } } return; } void Brick::stop_programs(bool reply){ unsigned char answer[NXT_BUFFER_SIZE]; unsigned char command[4]; command[0]=0x02; //command length command[1]=0x00; if(reply){ command[2]=0x00; } else{ command[2]=0x80; } command[3]=0x01; connection->send(&command[0],4); if(reply){ connection->receive(&answer[0],5); if(answer[4]){ throw Nxt_exception::Nxt_exception("stop_programs","Brick", 0x00FF & answer[4]); } } return; } string Brick::get_current_program(){ unsigned char answer[NXT_BUFFER_SIZE]; unsigned char command[4]; string temp; unsigned int i; command[0]=0x02; command[1]=0; command[2]=0x00; command[3]=0x11; connection->send(&command[0],4); connection->receive(&answer[0],25); if(answer[4]){ throw Nxt_exception::Nxt_exception("get_current_program","Brick", 0x00FF & answer[4]); } i=5; temp.resize(20); while(i<25){ temp[i-5]=answer[i]; i++; } temp[i-5]='\0'; return temp; } string Brick::get_bt_address(){ this->get_device_info(this->info); return this->info.bt_address; } void Brick::get_device_version(Device_version &version){ unsigned char answer[NXT_BUFFER_SIZE]; unsigned char command[4]; command[0]=0x02; //command length command[1]=0x00; command[2]=0x01; command[3]=0x88; connection->send(&command[0],4); connection->receive(&answer[0],9); if(answer[4]){ throw Nxt_exception::Nxt_exception("get_device_version","Brick", 0x00FF & answer[4]); } version.protocol.resize(10); version.protocol[0] = answer[6]+48; version.protocol[1] = '.'; sprintf(&version.protocol[2], "%d", answer[5]); version.firmware.resize(10); version.firmware[0]=answer[8]+48; version.firmware[1]='.'; sprintf(&version.firmware[2], "%02d", answer[7]); //Sleep(80); //For some reason it is not possible to recieve a system command and send a direct command without delay return; } string Brick::get_firmware_version(){ this->get_device_version(this->version); return this->version.firmware; } string Brick::get_protocol_version(){ this->get_device_version(this->version); return this->version.protocol; } unsigned int Brick::get_flash_memory(){ this->get_device_info(this->info); return this->info.flash_memory; } unsigned int Brick::get_battery_level(){ unsigned char answer[NXT_BUFFER_SIZE]; unsigned char command[4]; int mvolt; command[0]=0x02; //command length command[1]=0x00; command[2]=0x00; command[3]=0x0B; connection->send(&command[0],4); connection->receive(&answer[0],7); if(answer[4]){ throw Nxt_exception::Nxt_exception("battery_level","Brick", answer[4]); } mvolt = ((0xFF & answer[5]) | (answer[6] << 8)); //Sleep(80); //For some reason it is not possible to recieve a system command and send a direct command without delay return mvolt; } // LEGO skiped the implementation //unsigned int Brick::get_bt_strength(){} /* string Brick::get_bt_address(){ this->get_info(); return this->bt_address; } void Brick::delete_flash(bool reply){ char answer[NXT_BUFFER_SIZE]; char command[4]; command[0] = 0x02; command[1] = 0x00; if(reply){ command[2]=0x01; } else{ command[2]=0x81; } command[3] = 0xA0; connection->send(&command[0],4); if(reply){ Sleep(3000);//wait for NXT connection->receive(&answer[0],5); if(answer[4]){ throw Nxt_exception::Nxt_exception("delete_flash","Brick", 0x00FF & answer[4]); } } } void Brick::download_file(string pc_file, string nxt_file){ FILE *to; unsigned int i,file_size; char *data; NXT_file *from = new NXT_file(this->connection); if((to =fopen(pc_file.c_str(),"wb"))==NULL){ throw Nxt_exception::Nxt_exception("download_file","Brick", PC_FILE_ERROR); } file_size = from->open(nxt_file,READ); data =(char *) malloc(file_size*sizeof(char)); from->read(data,file_size); i=0; while(i<file_size){ fputc(data[i], to); i++; } free(data); fclose(to); from->close(); delete(from); return; } void Brick::delete_file(string file_name, bool reply){ unsigned int name_length; char command[24]; char answer[NXT_BUFFER_SIZE]; unsigned int i=0; name_length = file_name.length(); if(name_length > MAX_NAME_LENGTH){ file_name.erase(MAX_NAME_LENGTH+1); name_length=MAX_NAME_LENGTH; } command[0]=0x16; //command length command[1]=0x00; if(reply){ command[2]=0x01; } else{ command[2]=0x81; } command[3]=0x85; while(i<name_length){ command[i+4]=file_name[i]; i++; } while(i<MAX_NAME_LENGTH){ command[i+4]='\0'; i++; } connection->send(&command[0],24); if(reply){ connection->receive(&answer[0],25); if(answer[4]){ throw Nxt_exception::Nxt_exception("delete_file","Brick", 0x00FF & answer[4]); } } } void Brick::upload_file(string pc_file, string nxt_file){ FILE *from; unsigned int i,file_size; char *data; string file_ext; NXT_file *to = new NXT_file(this->connection); if((from =fopen(pc_file.c_str(),"rb"))==NULL){ throw Nxt_exception::Nxt_exception("upload_file","Brick", PC_FILE_ERROR); } fseek( from, 0L, SEEK_END ); file_size = ftell( from ); fseek( from, 0, SEEK_SET); file_ext = nxt_file.substr( nxt_file.find_last_of(".")+1); i=0; while(i<file_ext.length()){ file_ext[i] = std::tolower(file_ext[i]); i++; } if(file_ext == "ric" || file_ext == "rxe"){ to->open(nxt_file, WRITE_LINEAR, file_size); } else{ to->open(nxt_file,WRITE,file_size); } data = (char *) malloc(file_size * sizeof(char)); i=0; while(i<file_size){ data[i] = fgetc(from); i++; } to->write(data, file_size); free(data); fclose(from); to->close(); delete(to); return; } int Brick::get_first(string wild_card, file_info *info){ char answer[NXT_BUFFER_SIZE]; char command[24]; unsigned int i=0; unsigned int name_length = wild_card.length(); if(name_length > MAX_NAME_LENGTH){ wild_card.erase(MAX_NAME_LENGTH+1); name_length=MAX_NAME_LENGTH; } command[0]=0x16; //command length command[1]=0x00; command[2]=0x01; command[3]=0x86; while(i<name_length){ command[i+4]=wild_card[i]; i++; } while(i<MAX_NAME_LENGTH){ command[i+4]='\0'; i++; } connection->send(&command[0],24); connection->receive(&answer[0],30); if(answer[4]){ if(answer[4]!= (char) FILE_NOT_FOUND){ throw Nxt_exception::Nxt_exception("get_first","Brick", 0x00FF & answer[4]); } else{ return 0; } } info->handle = answer[5]; i=0; while(i<MAX_NAME_LENGTH){ info->name[i] = answer[6+i]; i++; } info->size = (0xFF & answer[26]) | ((0xFF & answer[27]) << 8)| ((0xFF & answer[28]) << 16)| ((0xFF & answer[29]) << 24); //close the handle command[0] = 0x03; command[1] = 0x00; command[2] = 0x01; command[3] = 0x84; command[4] = answer[5]; connection->send(&command[0],5); connection->receive(&answer[0],6); if(answer[4]){ if(answer[4] != (char) HANDLE_ALREADY_CLOSED){ throw Nxt_exception::Nxt_exception("get_first","Brick", 0x00FF & answer[4]); } } return 1; } int Brick::get_next(int handle, file_info *info){ char answer[NXT_BUFFER_SIZE]; char command[5]; unsigned int i=0; command[0] = 0x03; command[1] = 0x00; command[2] = 0x01; command[3] = 0x87; command[4] = handle; connection->send(&command[0],5); connection->receive(&answer[0],30); if(answer[4]){ if(answer[4]!= (char) FILE_NOT_FOUND){ throw Nxt_exception::Nxt_exception("get_next","Brick", 0x00FF & answer[4]); } else{ return 0; } } info->handle = answer[5]; i=0; while(i<MAX_NAME_LENGTH){ info->name[i] = answer[6+i]; i++; } info->size = (0xFF & answer[26]) | ((0xFF & answer[27]) << 8)| ((0xFF & answer[28]) << 16)| ((0xFF & answer[29]) << 24); //close the handle command[0] = 0x03; command[1] = 0x00; command[2] = 0x01; command[3] = 0x84; command[4] = answer[5]; connection->send(&command[0],5); connection->receive(&answer[0],6); if(answer[4]){ if(answer[4] != (char) HANDLE_ALREADY_CLOSED){ throw Nxt_exception::Nxt_exception("get_next","Brick", 0x00FF & answer[4]); } } return 1; } void Brick::get_file_list(string wild_card, file_list *list){ unsigned int idx; file_info temp; free(list->file); if(this->get_first(wild_card, &temp)){ list->file = (file_info*) malloc(sizeof(file_info)); list->file[0] = temp; list->length = 1; } else{ list->length = 0; return; } idx=0; while(this->get_next(list->file[idx].handle, &temp)){ list->file = (file_info *) realloc(list->file, (list->length+1)* sizeof(file_info)); list->file[idx+1] = temp; list->length++; idx++; } return; } */