cmd.cpp
Go to the documentation of this file.
00001 /*
00002         Aseba - an event-based framework for distributed robot control
00003         Copyright (C) 2007--2012:
00004                 Stephane Magnenat <stephane at magnenat dot net>
00005                 (http://stephane.magnenat.net)
00006                 and other contributors, see authors.txt for details
00007         
00008         This program is free software: you can redistribute it and/or modify
00009         it under the terms of the GNU Lesser General Public License as published
00010         by the Free Software Foundation, version 3 of the License.
00011         
00012         This program is distributed in the hope that it will be useful,
00013         but WITHOUT ANY WARRANTY; without even the implied warranty of
00014         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015         GNU Lesser General Public License for more details.
00016         
00017         You should have received a copy of the GNU Lesser General Public License
00018         along with this program. If not, see <http://www.gnu.org/licenses/>.
00019 */
00020 
00021 #include "../common/consts.h"
00022 #include "../msg/msg.h"
00023 #include "../utils/utils.h"
00024 #include "../utils/HexFile.h"
00025 #include "../utils/FormatableString.h"
00026 #include "../utils/BootloaderInterface.h"
00027 #include <dashel/dashel.h>
00028 #include "../transport/dashel_plugins/dashel-plugins.h"
00029 #include <iostream>
00030 #include <fstream>
00031 #include <vector>
00032 #include <iterator>
00033 #include <cassert>
00034 #include <cstring>
00035 #include <memory>
00036 
00037 namespace Aseba 
00038 {
00039         using namespace Dashel;
00040         using namespace std;
00041         
00043         void dumpCommandList(ostream &stream)
00044         {
00045                 stream << "* presence : broadcast presence message\n";
00046                 stream << "* usermsg: user message [type] [word0] ... [wordN]\n";
00047                 stream << "* rdpage : bootloader read page [dest] [page number]\n";
00048                 stream << "* rdpageusb : bootloader read page usb [dest] [page number]\n";
00049                 stream << "* whex : write hex file [dest] [file name] [reset]\n";
00050                 stream << "* rhex : read hex file [source] [file name]\n";
00051                 stream << "* eb: exit from bootloader, go back into user mode [dest]\n";
00052                 stream << "* sb: switch into bootloader: reboot node, then enter bootloader for a while [dest]\n";
00053                 stream << "* sleep: put the vm to sleep [dest]\n";
00054                 stream << "* wusb : write hex file to [dest] [file name] [reset]\n";
00055         }
00056         
00058         void dumpHelp(ostream &stream, const char *programName)
00059         {
00060                 stream << "Aseba cmd, send message over the aseba network, usage:\n";
00061                 stream << programName << " [-t target] [cmd destId (args)] ... [cmd destId (args)]\n";
00062                 stream << "where cmd is one af the following:\n";
00063                 dumpCommandList(stream);
00064                 stream << std::endl;
00065                 stream << "Other options:\n";
00066                 stream << "    -h, --help      : shows this help\n";
00067                 stream << "    -V, --version   : shows the version number\n";
00068                 stream << "Report bugs to: aseba-dev@gna.org" << std::endl;
00069         }
00070         
00072         void dumpVersion(std::ostream &stream)
00073         {
00074                 stream << "Aseba cmd " << ASEBA_VERSION << std::endl;
00075                 stream << "Aseba protocol " << ASEBA_PROTOCOL_VERSION << std::endl;
00076                 stream << "Licence LGPLv3: GNU LGPL version 3 <http://www.gnu.org/licenses/lgpl.html>\n";
00077         }
00078 
00080         void errorMissingArgument(const char *programName)
00081         {
00082                 cerr << "Error, missing argument.\n";
00083                 dumpHelp(cerr, programName);
00084                 exit(4);
00085         }
00086         
00088         void errorUnknownCommand(const char *cmd)
00089         {
00090                 cerr << "Error, unknown command " << cmd << endl;
00091                 cerr << "Known commands are:\n";
00092                 dumpCommandList(cerr);
00093                 exit(5);
00094         }
00095         
00097         void errorReadPage(int pageNumber)
00098         {
00099                 cerr << "Error, can't read page " << pageNumber << endl;
00100                 exit(6);
00101         }
00102         
00104         void errorOpenFile(const char *fileName)
00105         {
00106                 cerr << "Error, can't open file " << fileName << endl;
00107                 exit(7);
00108         }
00109         
00111         void errorServerDisconnected()
00112         {
00113                 cerr << "Server closed connection before command was completely sent." << endl;
00114                 exit(9);
00115         }
00116         
00118         void errorHexFile(const string &message)
00119         {
00120                 cerr << "HEX file error: " << message << endl;
00121                 exit(10);
00122         }
00123         
00125         void errorBootloader(const string& message)
00126         {
00127                 cerr << "Error while interfacing with bootloader: " << message << endl;
00128                 exit(9);
00129         }
00130 
00131         
00132         class CmdBootloaderInterface:public BootloaderInterface
00133         {
00134         public:
00135                 CmdBootloaderInterface(Stream* stream, int dest):
00136                         BootloaderInterface(stream, dest)
00137                 {}
00138         
00139         protected:
00140                 // reporting function
00141                 virtual void writePageStart(unsigned pageNumber, const uint8* data, bool simple)
00142                 {
00143                         cout << "Writing page " << pageNumber << "... ";
00144                         cout.flush();
00145                         //cout << "First data: " << hex << (int) data[0] << "," << hex << (int) data[1] << "," << hex << (int) data[2] << endl;
00146                 }
00147                 
00148                 virtual void writePageWaitAck()
00149                 {
00150                         cout << "Waiting ack ... ";
00151                         cout.flush();
00152                 }
00153                 
00154                 virtual void writePageSuccess()
00155                 {
00156                         cout << "Success" << endl;
00157                 }
00158                 
00159                 virtual void writePageFailure()
00160                 {
00161                         cout << "Failure" << endl;
00162                 }
00163                 
00164                 virtual void writeHexStart(const string &fileName, bool reset, bool simple)
00165                 {
00166                         cout << "Flashing " << fileName << endl;
00167                 }
00168                 
00169                 virtual void writeHexEnteringBootloader()
00170                 {
00171                         cout << "Entering bootloader" << endl;
00172                 }
00173                 
00174                 virtual void writeHexGotDescription(unsigned pagesCount)
00175                 {
00176                         cout << "In bootloader, about to write " << pagesCount << " pages" << endl;
00177                 }
00178                 
00179                 virtual void writeHexWritten()
00180                 {
00181                         cout << "Write completed" << endl;
00182                 }
00183                 
00184                 virtual void writeHexExitingBootloader()
00185                 {
00186                         cout << "Exiting bootloader" << endl;
00187                 }
00188                 
00189                 virtual void errorWritePageNonFatal(unsigned pageNumber)
00190                 {
00191                         cerr << "Warning, error while writing page " << pageNumber << ", continuing ..." << endl;
00192                 }
00193         };
00194         
00196         int processCommand(Stream* stream, int argc, char *argv[])
00197         {
00198                 const char *cmd = argv[0];
00199                 int argEaten = 0;
00200                 
00201                 if (strcmp(cmd, "presence") == 0)
00202                 {
00203                         GetDescription message;
00204                         message.serialize(stream);
00205                         stream->flush();
00206                 }
00207                 else if (strcmp(cmd, "usermsg") == 0)
00208                 {
00209                         // first arg is type, second is length
00210                         if (argc < 2)
00211                                 errorMissingArgument(argv[0]);
00212                         argEaten = argc;
00213                         uint16 type = atoi(argv[1]);
00214                         uint16 length = argc-2;
00215                         
00216                         UserMessage::DataVector data(length);
00217                         for (size_t i = 0; i < length; i++)
00218                                 data[i] = atoi(argv[i+2]);
00219                         
00220                         UserMessage message(type, data);
00221                         message.serialize(stream);
00222                         stream->flush();
00223                 }
00224                 else if (strcmp(cmd, "rdpage") == 0)
00225                 {
00226                         // first arg is dest, second is page number
00227                         if (argc < 3)
00228                                 errorMissingArgument(argv[0]);
00229                         argEaten = 2;
00230                         
00231                         CmdBootloaderInterface bootloader(stream, atoi(argv[1]));
00232                         
00233                         vector<uint8> data(bootloader.getPageSize());
00234                         if (bootloader.readPage(atoi(argv[2]), &data[0]))
00235                         {
00236                                 ofstream file("page.bin");
00237                                 if (file.good())
00238                                         copy(data.begin(), data.end(), ostream_iterator<uint8>(file));
00239                                 else
00240                                         errorOpenFile("page.bin");
00241                         }
00242                         else
00243                                 errorReadPage(atoi(argv[2]));
00244                 }
00245                 else if(strcmp(cmd, "rdpageusb") == 0)
00246                 {
00247                         if (argc < 3)
00248                                 errorMissingArgument(argv[0]);
00249                         argEaten = 2;
00250                         
00251                         CmdBootloaderInterface bootloader(stream, atoi(argv[1]));
00252                         vector <uint8> data(2048);
00253                         cout << "Page: " << atoi(argv[2]) << endl;
00254                         if(bootloader.readPageSimple(atoi(argv[2]), &data[0])) {
00255                                 ofstream file("page.bin");
00256                                 if(file.good())
00257                                         copy(data.begin(),data.end(),ostream_iterator<uint8>(file));
00258                                 else
00259                                         errorOpenFile("page.bin");
00260                         }
00261                         else
00262                                 errorReadPage(atoi(argv[2]));
00263                 }
00264                 else if (strcmp(cmd, "whex") == 0)
00265                 {
00266                         bool reset = 0;
00267                         // first arg is dest, second is file name
00268                         if (argc < 3)
00269                                 errorMissingArgument(argv[0]);
00270                         argEaten = 2;
00271                         
00272                         if (argc > 3 && !strcmp(argv[3], "reset")) 
00273                         {
00274                                 reset = 1;
00275                                 argEaten = 3;
00276                         }
00277 
00278                         // try to write hex file
00279                         try
00280                         {
00281                                 CmdBootloaderInterface bootloader(stream, atoi(argv[1]));
00282                                 bootloader.writeHex(argv[2], reset, false);
00283                         }
00284                         catch (HexFile::Error &e)
00285                         {
00286                                 errorHexFile(e.toString());
00287                         }
00288                 }
00289                 else if (strcmp(cmd,"wusb") == 0)
00290                 {
00291                         bool reset = 0;
00292                         if (argc < 3)
00293                                 errorMissingArgument(argv[0]);
00294                         argEaten = 2;
00295                         if(argc > 3 && !strcmp(argv[3], "reset"))
00296                         {
00297                                 reset = 1;
00298                                 argEaten = 3;
00299                         }
00300                         try
00301                         {
00302                                 CmdBootloaderInterface bootloader(stream, atoi(argv[1]));
00303                                 bootloader.writeHex(argv[2], reset, true);
00304                         }
00305                         catch (HexFile::Error &e)
00306                         {
00307                                 errorHexFile(e.toString());
00308                         }
00309                 }
00310                 else if (strcmp(cmd, "rhex") == 0)
00311                 {
00312                         // first arg is source, second is file name
00313                         if (argc < 3)
00314                                 errorMissingArgument(argv[0]);
00315                         argEaten = 2;
00316                         
00317                         // try to read hex file
00318                         try
00319                         {
00320                                 CmdBootloaderInterface bootloader(stream, atoi(argv[1]));
00321                                 bootloader.readHex(argv[2]);
00322                         }
00323                         catch (HexFile::Error &e)
00324                         {
00325                                 errorHexFile(e.toString());
00326                         }
00327                 }
00328                 else if (strcmp(cmd, "eb") == 0)
00329                 {
00330                         uint16 dest;
00331                         
00332                         if(argc < 2)
00333                                 errorMissingArgument(argv[0]);
00334                         argEaten = 1;
00335                         
00336                         dest = atoi(argv[1]);
00337                         
00338                         BootloaderReset msg(dest);
00339                         msg.serialize(stream);
00340                         stream->flush();
00341                         
00342                         // Wait ack from bootloader (mean we got out of it)
00343                         // Or bootloader description (mean we just entered it)
00344                         // WRONG; FIXME 
00345                         while (true)
00346                         {
00347                                 Message *message = Message::receive(stream);
00348                                 
00349                                 // handle ack
00350                                 BootloaderAck *ackMessage = dynamic_cast<BootloaderAck *>(message);
00351                                 if (ackMessage && (ackMessage->source == dest))
00352                                 {
00353                                         cout << "Device is now in user-code" << endl;
00354                                         delete message;
00355                                         break;
00356                                 }
00357                                 
00358                                 //BootloaderDescription * bMessage = dynamic_cast<BootloaderDescription *>(message);
00359                                 
00360                                 delete message;
00361                         }
00362                 }
00363                 else if (strcmp(cmd, "sb") == 0)
00364                 {
00365                         uint16 dest;
00366                         
00367                         if(argc < 2)
00368                                 errorMissingArgument(argv[0]);
00369                         argEaten = 1;
00370                         
00371                         dest = atoi(argv[1]);
00372                         
00373                         Reboot msg(dest);
00374                         msg.serialize(stream);
00375                         stream->flush();
00376                 }
00377                 else if (strcmp(cmd, "sleep") == 0)
00378                 {
00379                         uint16 dest;
00380                         if(argc < 2)
00381                                 errorMissingArgument(argv[0]);
00382                         argEaten = 1;
00383 
00384                         dest = atoi(argv[1]);
00385 
00386                         Sleep msg(dest);
00387                         msg.serialize(stream);
00388                         stream->flush();
00389                 } else 
00390                         errorUnknownCommand(cmd);
00391                 
00392                 return argEaten;
00393         }
00394 }
00395 
00396 int main(int argc, char *argv[])
00397 {
00398         Dashel::initPlugins();
00399         
00400         const char *target = ASEBA_DEFAULT_TARGET;
00401         int argCounter = 1;
00402         
00403         if (argc == 1)
00404         {
00405                 Aseba::dumpHelp(std::cout, argv[0]);
00406                 return 0;
00407         }
00408         
00409         while (argCounter < argc)
00410         {
00411                 const char *arg = argv[argCounter];
00412                 if (strcmp(arg, "-t") == 0)
00413                 {
00414                         if (++argCounter < argc)
00415                                 target = argv[argCounter];
00416                         else
00417                                 Aseba::errorMissingArgument(argv[0]);
00418                 }
00419                 else if ((strcmp(arg, "-h") == 0) || (strcmp(arg, "--help") == 0))
00420                 {
00421                         Aseba::dumpHelp(std::cout, argv[0]);
00422                         return 0;
00423                 }
00424                 else if ((strcmp(arg, "-V") == 0) || (strcmp(arg, "--version") == 0))
00425                 {
00426                         Aseba::dumpVersion(std::cout);
00427                         return 0;
00428                 }
00429                 else
00430                 {
00431                         Dashel::Hub client;
00432                         Dashel::Stream* stream = client.connect(target);
00433                         assert(stream);
00434                         
00435                         // process command
00436                         try
00437                         {
00438                                  argCounter += Aseba::processCommand(stream, argc - argCounter, &argv[argCounter]);
00439                                  stream->flush();
00440                         }
00441                         catch (Dashel::DashelException e)
00442                         {
00443                                 Aseba::errorServerDisconnected();
00444                         }
00445                         catch (Aseba::BootloaderInterface::Error e)
00446                         {
00447                                 Aseba::errorBootloader(e.what());
00448                         }
00449                 }
00450                 argCounter++;
00451         }
00452         return 0;
00453 }
00454 


aseba
Author(s): Stéphane Magnenat
autogenerated on Thu Jan 2 2014 11:17:16