PageRenderTime 52ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/src/modules/mindstorm/src/brick.cpp

https://bitbucket.org/hagish/love-kinect-mindstorm
C++ | 676 lines | 368 code | 36 blank | 272 comment | 37 complexity | f3c2e78a27829eebefa8da07215442d8 MD5 | raw file
  1. #include "brick.h"
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <time.h>
  5. #include <string>
  6. //#include <windows.h>
  7. #include "error.h"
  8. #include "core.h"
  9. using namespace std;
  10. using namespace nxt;
  11. #define MSG_SIZE 64
  12. Brick::Brick(Connection *connection){
  13. this->connection = connection;
  14. }
  15. void Brick::write_msg(string message, int inbox, bool reply){
  16. unsigned char answer[NXT_BUFFER_SIZE];
  17. unsigned char command[NXT_BUFFER_SIZE];
  18. unsigned int i=0;
  19. unsigned int length=message.length();
  20. if(length>57){
  21. length = 57;
  22. }
  23. command[0]=length+5; //command length
  24. command[1]=0x00;
  25. if(reply){
  26. command[2]=0x00;
  27. }
  28. else{
  29. command[2]=0x80;
  30. }
  31. command[3]=0x09;
  32. if(inbox>9){
  33. inbox=9;
  34. }
  35. command[4]=inbox;
  36. command[5]=length+1;
  37. while(i<length){
  38. command[i+6]=message[i];
  39. i++;
  40. }
  41. command[i+6]='\0';
  42. connection->send(&command[0],length+7);
  43. if(reply){
  44. connection->receive(&answer[0],5);
  45. if(answer[4]){
  46. throw Nxt_exception("write_msg","Brick", 0x00FF & answer[4]);
  47. }
  48. }
  49. return;
  50. }
  51. string Brick::read_msg(int inbox, bool remove){
  52. unsigned int i;
  53. unsigned char answer[NXT_BUFFER_SIZE+2];
  54. unsigned char command[7];
  55. command[0]=0x05; //command length
  56. command[1]=0x00;
  57. command[2]=0x00;
  58. command[3]=0x13;
  59. command[4]=10+inbox;
  60. command[5]=0x00;
  61. command[6]=remove;
  62. connection->send(&command[0],7);
  63. connection->receive(&answer[0],66);
  64. if(answer[4]){
  65. throw Nxt_exception("read_msg","Brick", answer[4]);
  66. }
  67. i=7;
  68. string result;
  69. result.resize(59);
  70. while((answer[i]!='\0')){
  71. result[i-7]=answer[i];
  72. i++;
  73. }
  74. result[i-7]='\0';
  75. //connection->flush();
  76. return result;
  77. }
  78. void Brick::set_name(string name, bool reply){
  79. unsigned char answer[NXT_BUFFER_SIZE];
  80. unsigned char command[NXT_BUFFER_SIZE];
  81. unsigned int length=name.length();
  82. unsigned int i;
  83. if(length>15){
  84. length=15;
  85. }
  86. command[0]=length+3; //command length
  87. command[1]=0x00;
  88. //start of message
  89. if(reply){
  90. command[2] = 0x01;
  91. }
  92. else{
  93. command[2] = 0x81;
  94. }
  95. command[3]=0x98;
  96. for(i=0; i<length ;i++){
  97. command[i+4]=name[i];
  98. }
  99. command[i+4]='\0';
  100. connection->send(&command[0],length+5);
  101. _sleep(200);
  102. if(reply){
  103. connection->receive(&answer[0],5);
  104. if(answer[4]){
  105. throw Nxt_exception("set_name","Brick", 0x00FF & answer[4]);
  106. }
  107. }
  108. return;
  109. }
  110. void Brick::get_device_info(Device_info &info){
  111. unsigned int i;
  112. unsigned char answer[NXT_BUFFER_SIZE];
  113. unsigned char command[4];
  114. command[0] = 0x02;
  115. command[1] = 0x00;
  116. command[2] = 0x01;
  117. command[3] = 0x9b;
  118. connection->send(&command[0],4);
  119. connection->receive(&answer[0],35);
  120. if(answer[4]){
  121. throw Nxt_exception("get_device_info","Brick", 0x00FF & answer[4]);
  122. }
  123. info.name.resize(15);
  124. i=0;
  125. while(i<15){
  126. info.name[i]=answer[i+5];
  127. i++;
  128. }
  129. info.bt_address.resize(21);
  130. i=0;
  131. while(i<7){
  132. sprintf(&info.bt_address[i*3], "%02X:", answer[i+20]);
  133. i++;
  134. }
  135. info.bt_address[20] = '\0';
  136. //LEGO has not implemented Bluetooth strengh
  137. //bt_strength = ((0xff & answer[27]) | ( answer[28] << 8) | (answer[29] << 16) | (answer[30] << 24) );
  138. info.flash_memory = ((0xff & answer[31]) | ( answer[32] << 8) | ( answer[33] << 16) | ( answer[34] << 24) );
  139. return;
  140. }
  141. string Brick::get_name(){
  142. this->get_device_info(this->info);
  143. return this->info.name;
  144. }
  145. void Brick::keep_alive(bool reply){
  146. unsigned char answer[NXT_BUFFER_SIZE];
  147. unsigned char command[4];
  148. command[0]=0x02; //command length
  149. command[1]=0x00;
  150. if(reply){
  151. command[2]=0x00;
  152. }
  153. else{
  154. command[2]=0x80;
  155. }
  156. command[3]=0x0D;
  157. connection->send(&command[0],4);
  158. if(reply){
  159. connection->receive(&answer[0],9);
  160. if(answer[4]){
  161. throw Nxt_exception("keep_alive","Brick", 0x00FF & answer[4]);
  162. }
  163. }
  164. return;
  165. }
  166. void Brick::play_tone(unsigned int freq, unsigned int time, bool reply){
  167. unsigned char answer[NXT_BUFFER_SIZE];
  168. unsigned char command[8];
  169. command[0]=0x06; //command length
  170. command[1]=0x00;
  171. if(reply){
  172. command[2]=0x00;
  173. }
  174. else{
  175. command[2]=0x80;
  176. }
  177. command[3]=0x03;
  178. command[4]=freq;
  179. command[5]=freq >>8;
  180. command[6]=time;
  181. command[7]=time >> 8;
  182. connection->send(&command[0],8);
  183. if(reply){
  184. connection->receive(&answer[0],5);
  185. if(answer[4]){
  186. throw Nxt_exception("play_tone","Brick", 0x00FF & answer[4]);
  187. }
  188. }
  189. return;
  190. }
  191. void Brick::beep(unsigned int time, bool reply){
  192. play_tone(1000,time, reply);
  193. }
  194. void Brick::play_soundfile(string file, bool loop, bool reply){
  195. unsigned char answer[NXT_BUFFER_SIZE];
  196. unsigned char command[NXT_BUFFER_SIZE];
  197. unsigned int length=file.length();
  198. unsigned int i;
  199. if(length>19){
  200. length=19;
  201. }
  202. command[0]=length+4; //command length
  203. command[1]=0x00;
  204. //start of message
  205. if(reply){
  206. command[2]=0x00;
  207. }
  208. else{
  209. command[2]=0x80;
  210. }
  211. command[3]=0x02;
  212. command[4]=loop;
  213. for(i=0; i<length ;i++){
  214. command[i+5]=file[i];
  215. }
  216. command[i+5]='\0';
  217. connection->send(&command[0],length+6);
  218. if(reply){
  219. connection->receive(&answer[0],5);
  220. if(answer[4]){
  221. throw Nxt_exception("play_soundfile","Brick", 0x00FF & answer[4]);
  222. }
  223. }
  224. return;
  225. }
  226. void Brick::stop_soundplayback(bool reply){
  227. unsigned char answer[NXT_BUFFER_SIZE];
  228. unsigned char command[4];
  229. command[0]=0x02; //command length
  230. command[1]=0x00;
  231. if(reply){
  232. command[2]=0x00;
  233. }
  234. else{
  235. command[2]=0x80;
  236. }
  237. command[3]=0x0C;
  238. connection->send(&command[0],4);
  239. if(reply){
  240. connection->receive(&answer[0],5);
  241. if(answer[4]){
  242. throw Nxt_exception("stop_soundplayback","Brick", 0x00FF & answer[4]);
  243. }
  244. }
  245. return;
  246. }
  247. void Brick::start_program(string file, bool reply){
  248. unsigned char answer[NXT_BUFFER_SIZE];
  249. unsigned char command[NXT_BUFFER_SIZE];
  250. int length=file.length();
  251. int i;
  252. if(length>19){
  253. length=19;
  254. }
  255. command[0]=length+3; //command length
  256. command[1]=0x00;
  257. //start of message
  258. if(reply){
  259. command[2]=0x00;
  260. }
  261. else{
  262. command[2]=0x80;
  263. }
  264. command[3]=0x00;
  265. for(i=0; i<length ;i++){
  266. command[i+4]=file[i];
  267. }
  268. command[i+4]='\0';
  269. connection->send(&command[0],length+5);
  270. if(reply){
  271. connection->receive(&answer[0],5);
  272. if(answer[4]){
  273. throw Nxt_exception("start_program","Brick", 0x00FF & answer[4]);
  274. }
  275. }
  276. return;
  277. }
  278. void Brick::stop_programs(bool reply){
  279. unsigned char answer[NXT_BUFFER_SIZE];
  280. unsigned char command[4];
  281. command[0]=0x02; //command length
  282. command[1]=0x00;
  283. if(reply){
  284. command[2]=0x00;
  285. }
  286. else{
  287. command[2]=0x80;
  288. }
  289. command[3]=0x01;
  290. connection->send(&command[0],4);
  291. if(reply){
  292. connection->receive(&answer[0],5);
  293. if(answer[4]){
  294. throw Nxt_exception("stop_programs","Brick", 0x00FF & answer[4]);
  295. }
  296. }
  297. return;
  298. }
  299. string Brick::get_current_program(){
  300. unsigned char answer[NXT_BUFFER_SIZE];
  301. unsigned char command[4];
  302. string temp;
  303. unsigned int i;
  304. command[0]=0x02;
  305. command[1]=0;
  306. command[2]=0x00;
  307. command[3]=0x11;
  308. connection->send(&command[0],4);
  309. connection->receive(&answer[0],25);
  310. if(answer[4]){
  311. throw Nxt_exception("get_current_program","Brick", 0x00FF & answer[4]);
  312. }
  313. i=5;
  314. temp.resize(20);
  315. while(i<25){
  316. temp[i-5]=answer[i];
  317. i++;
  318. }
  319. temp[i-5]='\0';
  320. return temp;
  321. }
  322. string Brick::get_bt_address(){
  323. this->get_device_info(this->info);
  324. return this->info.bt_address;
  325. }
  326. void Brick::get_device_version(Device_version &version){
  327. unsigned char answer[NXT_BUFFER_SIZE];
  328. unsigned char command[4];
  329. command[0]=0x02; //command length
  330. command[1]=0x00;
  331. command[2]=0x01;
  332. command[3]=0x88;
  333. connection->send(&command[0],4);
  334. connection->receive(&answer[0],9);
  335. if(answer[4]){
  336. throw Nxt_exception("get_device_version","Brick", 0x00FF & answer[4]);
  337. }
  338. version.protocol.resize(10);
  339. version.protocol[0] = answer[6]+48;
  340. version.protocol[1] = '.';
  341. sprintf(&version.protocol[2], "%d", answer[5]);
  342. version.firmware.resize(10);
  343. version.firmware[0]=answer[8]+48;
  344. version.firmware[1]='.';
  345. sprintf(&version.firmware[2], "%02d", answer[7]);
  346. //Sleep(80); //For some reason it is not possible to recieve a system command and send a direct command without delay
  347. return;
  348. }
  349. string Brick::get_firmware_version(){
  350. this->get_device_version(this->version);
  351. return this->version.firmware;
  352. }
  353. string Brick::get_protocol_version(){
  354. this->get_device_version(this->version);
  355. return this->version.protocol;
  356. }
  357. unsigned int Brick::get_flash_memory(){
  358. this->get_device_info(this->info);
  359. return this->info.flash_memory;
  360. }
  361. unsigned int Brick::get_battery_level(){
  362. unsigned char answer[NXT_BUFFER_SIZE];
  363. unsigned char command[4];
  364. int mvolt;
  365. command[0]=0x02; //command length
  366. command[1]=0x00;
  367. command[2]=0x00;
  368. command[3]=0x0B;
  369. connection->send(&command[0],4);
  370. connection->receive(&answer[0],7);
  371. if(answer[4]){
  372. throw Nxt_exception("battery_level","Brick", answer[4]);
  373. }
  374. mvolt = ((0xFF & answer[5]) | (answer[6] << 8));
  375. //Sleep(80); //For some reason it is not possible to recieve a system command and send a direct command without delay
  376. return mvolt;
  377. }
  378. // LEGO skiped the implementation
  379. //unsigned int Brick::get_bt_strength(){}
  380. /*
  381. string Brick::get_bt_address(){
  382. this->get_info();
  383. return this->bt_address;
  384. }
  385. void Brick::delete_flash(bool reply){
  386. char answer[NXT_BUFFER_SIZE];
  387. char command[4];
  388. command[0] = 0x02;
  389. command[1] = 0x00;
  390. if(reply){
  391. command[2]=0x01;
  392. }
  393. else{
  394. command[2]=0x81;
  395. }
  396. command[3] = 0xA0;
  397. connection->send(&command[0],4);
  398. if(reply){
  399. Sleep(3000);//wait for NXT
  400. connection->receive(&answer[0],5);
  401. if(answer[4]){
  402. throw Nxt_exception("delete_flash","Brick", 0x00FF & answer[4]);
  403. }
  404. }
  405. }
  406. void Brick::download_file(string pc_file, string nxt_file){
  407. FILE *to;
  408. unsigned int i,file_size;
  409. char *data;
  410. NXT_file *from = new NXT_file(this->connection);
  411. if((to =fopen(pc_file.c_str(),"wb"))==NULL){
  412. throw Nxt_exception("download_file","Brick", PC_FILE_ERROR);
  413. }
  414. file_size = from->open(nxt_file,READ);
  415. data =(char *) malloc(file_size*sizeof(char));
  416. from->read(data,file_size);
  417. i=0;
  418. while(i<file_size){
  419. fputc(data[i], to);
  420. i++;
  421. }
  422. free(data);
  423. fclose(to);
  424. from->close();
  425. delete(from);
  426. return;
  427. }
  428. void Brick::delete_file(string file_name, bool reply){
  429. unsigned int name_length;
  430. char command[24];
  431. char answer[NXT_BUFFER_SIZE];
  432. unsigned int i=0;
  433. name_length = file_name.length();
  434. if(name_length > MAX_NAME_LENGTH){
  435. file_name.erase(MAX_NAME_LENGTH+1);
  436. name_length=MAX_NAME_LENGTH;
  437. }
  438. command[0]=0x16; //command length
  439. command[1]=0x00;
  440. if(reply){
  441. command[2]=0x01;
  442. }
  443. else{
  444. command[2]=0x81;
  445. }
  446. command[3]=0x85;
  447. while(i<name_length){
  448. command[i+4]=file_name[i];
  449. i++;
  450. }
  451. while(i<MAX_NAME_LENGTH){
  452. command[i+4]='\0';
  453. i++;
  454. }
  455. connection->send(&command[0],24);
  456. if(reply){
  457. connection->receive(&answer[0],25);
  458. if(answer[4]){
  459. throw Nxt_exception("delete_file","Brick", 0x00FF & answer[4]);
  460. }
  461. }
  462. }
  463. void Brick::upload_file(string pc_file, string nxt_file){
  464. FILE *from;
  465. unsigned int i,file_size;
  466. char *data;
  467. string file_ext;
  468. NXT_file *to = new NXT_file(this->connection);
  469. if((from =fopen(pc_file.c_str(),"rb"))==NULL){
  470. throw Nxt_exception("upload_file","Brick", PC_FILE_ERROR);
  471. }
  472. fseek( from, 0L, SEEK_END );
  473. file_size = ftell( from );
  474. fseek( from, 0, SEEK_SET);
  475. file_ext = nxt_file.substr( nxt_file.find_last_of(".")+1);
  476. i=0;
  477. while(i<file_ext.length()){
  478. file_ext[i] = std::tolower(file_ext[i]);
  479. i++;
  480. }
  481. if(file_ext == "ric" || file_ext == "rxe"){
  482. to->open(nxt_file, WRITE_LINEAR, file_size);
  483. }
  484. else{
  485. to->open(nxt_file,WRITE,file_size);
  486. }
  487. data = (char *) malloc(file_size * sizeof(char));
  488. i=0;
  489. while(i<file_size){
  490. data[i] = fgetc(from);
  491. i++;
  492. }
  493. to->write(data, file_size);
  494. free(data);
  495. fclose(from);
  496. to->close();
  497. delete(to);
  498. return;
  499. }
  500. int Brick::get_first(string wild_card, file_info *info){
  501. char answer[NXT_BUFFER_SIZE];
  502. char command[24];
  503. unsigned int i=0;
  504. unsigned int name_length = wild_card.length();
  505. if(name_length > MAX_NAME_LENGTH){
  506. wild_card.erase(MAX_NAME_LENGTH+1);
  507. name_length=MAX_NAME_LENGTH;
  508. }
  509. command[0]=0x16; //command length
  510. command[1]=0x00;
  511. command[2]=0x01;
  512. command[3]=0x86;
  513. while(i<name_length){
  514. command[i+4]=wild_card[i];
  515. i++;
  516. }
  517. while(i<MAX_NAME_LENGTH){
  518. command[i+4]='\0';
  519. i++;
  520. }
  521. connection->send(&command[0],24);
  522. connection->receive(&answer[0],30);
  523. if(answer[4]){
  524. if(answer[4]!= (char) FILE_NOT_FOUND){
  525. throw Nxt_exception("get_first","Brick", 0x00FF & answer[4]);
  526. }
  527. else{
  528. return 0;
  529. }
  530. }
  531. info->handle = answer[5];
  532. i=0;
  533. while(i<MAX_NAME_LENGTH){
  534. info->name[i] = answer[6+i];
  535. i++;
  536. }
  537. info->size = (0xFF & answer[26]) | ((0xFF & answer[27]) << 8)| ((0xFF & answer[28]) << 16)| ((0xFF & answer[29]) << 24);
  538. //close the handle
  539. command[0] = 0x03;
  540. command[1] = 0x00;
  541. command[2] = 0x01;
  542. command[3] = 0x84;
  543. command[4] = answer[5];
  544. connection->send(&command[0],5);
  545. connection->receive(&answer[0],6);
  546. if(answer[4]){
  547. if(answer[4] != (char) HANDLE_ALREADY_CLOSED){
  548. throw Nxt_exception("get_first","Brick", 0x00FF & answer[4]);
  549. }
  550. }
  551. return 1;
  552. }
  553. int Brick::get_next(int handle, file_info *info){
  554. char answer[NXT_BUFFER_SIZE];
  555. char command[5];
  556. unsigned int i=0;
  557. command[0] = 0x03;
  558. command[1] = 0x00;
  559. command[2] = 0x01;
  560. command[3] = 0x87;
  561. command[4] = handle;
  562. connection->send(&command[0],5);
  563. connection->receive(&answer[0],30);
  564. if(answer[4]){
  565. if(answer[4]!= (char) FILE_NOT_FOUND){
  566. throw Nxt_exception("get_next","Brick", 0x00FF & answer[4]);
  567. }
  568. else{
  569. return 0;
  570. }
  571. }
  572. info->handle = answer[5];
  573. i=0;
  574. while(i<MAX_NAME_LENGTH){
  575. info->name[i] = answer[6+i];
  576. i++;
  577. }
  578. info->size = (0xFF & answer[26]) | ((0xFF & answer[27]) << 8)| ((0xFF & answer[28]) << 16)| ((0xFF & answer[29]) << 24);
  579. //close the handle
  580. command[0] = 0x03;
  581. command[1] = 0x00;
  582. command[2] = 0x01;
  583. command[3] = 0x84;
  584. command[4] = answer[5];
  585. connection->send(&command[0],5);
  586. connection->receive(&answer[0],6);
  587. if(answer[4]){
  588. if(answer[4] != (char) HANDLE_ALREADY_CLOSED){
  589. throw Nxt_exception("get_next","Brick", 0x00FF & answer[4]);
  590. }
  591. }
  592. return 1;
  593. }
  594. void Brick::get_file_list(string wild_card, file_list *list){
  595. unsigned int idx;
  596. file_info temp;
  597. free(list->file);
  598. if(this->get_first(wild_card, &temp)){
  599. list->file = (file_info*) malloc(sizeof(file_info));
  600. list->file[0] = temp;
  601. list->length = 1;
  602. }
  603. else{
  604. list->length = 0;
  605. return;
  606. }
  607. idx=0;
  608. while(this->get_next(list->file[idx].handle, &temp)){
  609. list->file = (file_info *) realloc(list->file, (list->length+1)* sizeof(file_info));
  610. list->file[idx+1] = temp;
  611. list->length++;
  612. idx++;
  613. }
  614. return;
  615. }
  616. */