dummynode.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 #ifndef ASEBA_ASSERT
00022 #define ASEBA_ASSERT
00023 #endif
00024 
00025 #include "../../vm/vm.h"
00026 #include "../../vm/natives.h"
00027 #include "../../common/productids.h"
00028 #include "../../common/consts.h"
00029 #include "../../transport/buffer/vm-buffer.h"
00030 #include <dashel/dashel.h>
00031 #include <iostream>
00032 #include <sstream>
00033 #include <valarray>
00034 #include <cassert>
00035 #include <cstring>
00036 
00037 extern AsebaVMDescription nodeDescription;
00038 
00039 class AsebaNode: public Dashel::Hub
00040 {
00041 private:
00042         AsebaVMState vm;
00043         std::valarray<unsigned short> bytecode;
00044         std::valarray<signed short> stack;
00045         struct Variables
00046         {
00047                 sint16 id;
00048                 sint16 source;
00049                 sint16 args[32];
00050                 sint16 productId;
00051                 sint16 user[1024];
00052         } variables;
00053         char mutableName[12];
00054         
00055 public:
00056         // public because accessed from a glue function
00057         uint16 lastMessageSource;
00058         std::valarray<uint8> lastMessageData;
00059         // this must be public because of bindings to C functions
00060         Dashel::Stream* stream;
00061         
00062 public:
00063         
00064         AsebaNode()
00065         {
00066                 // setup variables
00067                 vm.nodeId = 1;
00068                 
00069                 bytecode.resize(512);
00070                 vm.bytecode = &bytecode[0];
00071                 vm.bytecodeSize = bytecode.size();
00072                 
00073                 stack.resize(64);
00074                 vm.stack = &stack[0];
00075                 vm.stackSize = stack.size();
00076                 
00077                 vm.variables = reinterpret_cast<sint16 *>(&variables);
00078                 vm.variablesSize = sizeof(variables) / sizeof(sint16);
00079         }
00080         
00081         void listen(int basePort, int deltaPort)
00082         {
00083                 const int port(basePort + deltaPort);
00084                 vm.nodeId = 1 + deltaPort;
00085                 strncpy(mutableName, "dummynode-0", 12);
00086                 mutableName[10] = '0' + deltaPort;
00087                 nodeDescription.name = mutableName;
00088                 
00089                 // connect network
00090                 try
00091                 {
00092                         std::ostringstream oss;
00093                         oss << "tcpin:port=" << port;
00094                         Dashel::Hub::connect(oss.str());
00095                 }
00096                 catch (Dashel::DashelException e)
00097                 {
00098                         std::cerr << "Cannot create listening port " << port << ": " << e.what() << std::endl;
00099                         abort();
00100                 }
00101                 
00102                 // init VM
00103                 AsebaVMInit(&vm);
00104         }
00105         
00106         virtual void connectionCreated(Dashel::Stream *stream)
00107         {
00108                 std::string targetName = stream->getTargetName();
00109                 if (targetName.substr(0, targetName.find_first_of(':')) == "tcp")
00110                 {
00111                         std::cerr << this << " : New client connected." << std::endl;
00112                         if (this->stream)
00113                         {
00114                                 closeStream(this->stream);
00115                                 std::cerr << this << " : Disconnected old client." << std::endl;
00116                         }
00117                         this->stream = stream;
00118                 }
00119         }
00120         
00121         virtual void connectionClosed(Dashel::Stream *stream, bool abnormal)
00122         {
00123                 this->stream = 0;
00124                 // clear breakpoints
00125                 vm.breakpointsCount = 0;
00126                 
00127                 if (abnormal)
00128                         std::cerr << this << " : Client has disconnected unexpectedly." << std::endl;
00129                 else
00130                         std::cerr << this << " : Client has disconnected properly." << std::endl;
00131         }
00132         
00133         virtual void incomingData(Dashel::Stream *stream)
00134         {
00135                 uint16 temp;
00136                 uint16 len;
00137                 
00138                 stream->read(&temp, 2);
00139                 len = bswap16(temp);
00140                 stream->read(&temp, 2);
00141                 lastMessageSource = bswap16(temp);
00142                 lastMessageData.resize(len+2);
00143                 stream->read(&lastMessageData[0], lastMessageData.size());
00144                 
00145                 AsebaProcessIncomingEvents(&vm);
00146         }
00147         
00148         virtual void applicationStep()
00149         {
00150                 // run VM
00151                 AsebaVMRun(&vm, 65535);
00152                 
00153                 // reschedule a periodic event if we are not in step by step
00154                 if (AsebaMaskIsClear(vm.flags, ASEBA_VM_STEP_BY_STEP_MASK) || AsebaMaskIsClear(vm.flags, ASEBA_VM_EVENT_ACTIVE_MASK))
00155                         AsebaVMSetupEvent(&vm, ASEBA_EVENT_LOCAL_EVENTS_START-0);
00156         }
00157 } node;
00158 
00159 // Implementation of aseba glue code
00160 
00161 extern "C" void AsebaPutVmToSleep(AsebaVMState *vm) 
00162 {
00163         std::cerr << "Received request to go into sleep" << std::endl;
00164 }
00165 
00166 extern "C" void AsebaSendBuffer(AsebaVMState *vm, const uint8* data, uint16 length)
00167 {
00168         Dashel::Stream* stream = node.stream;
00169         if (stream)
00170         {
00171                 try
00172                 {
00173                         uint16 temp;
00174                         temp = bswap16(length - 2);
00175                         stream->write(&temp, 2);
00176                         temp = bswap16(vm->nodeId);
00177                         stream->write(&temp, 2);
00178                         stream->write(data, length);
00179                         stream->flush();
00180                 }
00181                 catch (Dashel::DashelException e)
00182                 {
00183                         std::cerr << "Cannot write to socket: " << stream->getFailReason() << std::endl;
00184                 }
00185         }
00186 }
00187 
00188 extern "C" uint16 AsebaGetBuffer(AsebaVMState *vm, uint8* data, uint16 maxLength, uint16* source)
00189 {
00190         if (node.lastMessageData.size())
00191         {
00192                 *source = node.lastMessageSource;
00193                 memcpy(data, &node.lastMessageData[0], node.lastMessageData.size());
00194         }
00195         return node.lastMessageData.size();
00196 }
00197 
00198 extern AsebaVMDescription nodeDescription;
00199 
00200 extern "C" const AsebaVMDescription* AsebaGetVMDescription(AsebaVMState *vm)
00201 {
00202         return &nodeDescription;
00203 }
00204 
00205 static AsebaNativeFunctionPointer nativeFunctions[] =
00206 {
00207         ASEBA_NATIVES_STD_FUNCTIONS,
00208 };
00209 
00210 static const AsebaNativeFunctionDescription* nativeFunctionsDescriptions[] =
00211 {
00212         ASEBA_NATIVES_STD_DESCRIPTIONS,
00213         0
00214 };
00215 
00216 extern "C" const AsebaNativeFunctionDescription * const * AsebaGetNativeFunctionsDescriptions(AsebaVMState *vm)
00217 {
00218         return nativeFunctionsDescriptions;
00219 }
00220 
00221 extern "C" void AsebaNativeFunction(AsebaVMState *vm, uint16 id)
00222 {
00223         nativeFunctions[id](vm);
00224 }
00225 
00226 
00227 static const AsebaLocalEventDescription localEvents[] = {
00228         { "timer", "periodic timer at 50 Hz" },
00229         { NULL, NULL }
00230 };
00231 
00232 extern "C" const AsebaLocalEventDescription * AsebaGetLocalEventsDescriptions(AsebaVMState *vm)
00233 {
00234         return localEvents;
00235 }
00236 
00237 extern "C" void AsebaWriteBytecode(AsebaVMState *vm)
00238 {
00239         std::cerr << "Received request to write bytecode into flash" << std::endl;
00240 }
00241 
00242 extern "C" void AsebaResetIntoBootloader(AsebaVMState *vm)
00243 {
00244         std::cerr << "Received request to reset into bootloader" << std::endl;
00245 }
00246 
00247 extern "C" void AsebaAssert(AsebaVMState *vm, AsebaAssertReason reason)
00248 {
00249         std::cerr << "\nFatal error; exception: ";
00250         switch (reason)
00251         {
00252                 case ASEBA_ASSERT_UNKNOWN: std::cerr << "undefined"; break;
00253                 case ASEBA_ASSERT_UNKNOWN_BINARY_OPERATOR: std::cerr << "unknown binary operator"; break;
00254                 case ASEBA_ASSERT_UNKNOWN_BYTECODE: std::cerr << "unknown bytecode"; break;
00255                 case ASEBA_ASSERT_STACK_OVERFLOW: std::cerr << "stack overflow"; break;
00256                 case ASEBA_ASSERT_STACK_UNDERFLOW: std::cerr << "stack underflow"; break;
00257                 case ASEBA_ASSERT_OUT_OF_VARIABLES_BOUNDS: std::cerr << "out of variables bounds"; break;
00258                 case ASEBA_ASSERT_OUT_OF_BYTECODE_BOUNDS: std::cerr << "out of bytecode bounds"; break;
00259                 case ASEBA_ASSERT_STEP_OUT_OF_RUN: std::cerr << "step out of run"; break;
00260                 case ASEBA_ASSERT_BREAKPOINT_OUT_OF_BYTECODE_BOUNDS: std::cerr << "breakpoint out of bytecode bounds"; break;
00261                 default: std::cerr << "unknown exception"; break;
00262         }
00263         std::cerr << ".\npc = " << vm->pc << ", sp = " << vm->sp;
00264         abort();
00265         std::cerr << "\nResetting VM" << std::endl;
00266         AsebaVMInit(vm);
00267 }
00268 
00269 
00270 int main(int argc, char* argv[])
00271 {
00272         const int basePort = ASEBA_DEFAULT_PORT;
00273         int deltaPort = 0;
00274         if (argc > 1)
00275         {
00276                 deltaPort = atoi(argv[1]);
00277                 if (deltaPort < 0 || deltaPort >= 9)
00278                 {
00279                         std::cerr << "Usage: " << argv[0] << " [delta port, from 0 to 9]" << std::endl;
00280                         return 1;
00281                 }
00282         }
00283         node.listen(basePort, deltaPort);
00284         while (node.step(10))
00285         {
00286                 node.applicationStep();
00287         }
00288 }


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