예제 #1
0
        public static byte[] ReadEV3File(String fullname)
        {
            try
            {
                lock (sync)
                {
                    // if not already done, memorize the start time and fire up the communication
                    MemorizeStartTime();
                    EstablishConnection();

                    // prepare the pinger packet to keep the remote-controll target alive during large file transfer
                    ByteCodeBuffer c = new ByteCodeBuffer();
                    c.OP(0x3A);           // Move32_32
                    c.CONST(42);          // move this value
                    c.GLOBVAR(0);         // to global variable 0-3
                    c.OP(0x7E);           // Memory_Write
                    c.CONST(1);           // program slot 1 = user slot
                    c.CONST(0);           // write to global variables
                    c.CONST(0);           // to global variable 0
                    c.CONST(4);           // write 4 bytes
                    c.GLOBVAR(0);         // take the prepared value 42

                    // finally execute the command
                    return(con.ReadEV3File(fullname, c));
                }
            }
            catch (Exception)
            {   // no connection or other severe error - must terminate immediately
                System.Environment.Exit(1);
            }
            return(null);
        }
예제 #2
0
        // must be called while holding a lock on sync
        private static void EstablishConnection()
        {
            // the first action also involves passing some SystemCommands and DirectCommands
            if (con == null)
            {
                // try to start up connection (when failing, an exception is thrown)
                con = ConnectionFinder.CreateConnection(false, true);

                String filename = "/tmp/EV3-Basic Session.rbf";

                // download the watchdog program as a file to the brick
                con.CreateEV3File(filename, HexDumpToBytes(EV3Communication.Properties.Resources.WatchDog));

                // before loading the watchdog program, check if there is no other program running
                ByteCodeBuffer c = new ByteCodeBuffer();
                c.OP(0x0C);            // opProgram_Info
                c.CONST(0x16);         // CMD: GET_STATUS = 0x16
                c.CONST(1);            // program slot 1 = user slot
                c.GLOBVAR(8);

                // load and start it
                c.OP(0xC0);       // opFILE
                c.CONST(0x08);    // CMD: LOAD_IMAGE = 0x08
                c.CONST(1);       // slot 1 = user program slot
                c.STRING(filename);
                c.GLOBVAR(0);
                c.GLOBVAR(4);
                c.OP(0x03);       // opPROGRAM_START
                c.CONST(1);       // slot 1 = user program slot
                c.GLOBVAR(0);
                c.GLOBVAR(4);
                c.CONST(0);

                // after starting, check if indeed running now
                c.OP(0x0C);            // opProgram_Info
                c.CONST(0x16);         // CMD: GET_STATUS = 0x16
                c.CONST(1);            // program slot 1 = user slot
                c.GLOBVAR(9);

                // as additional startup-action, reset the hardware (sensors and motors)
                c.OP(0x99);            // opInput_Device (CMD, …)
                c.CONST(0x0A);         // CLR_ALL = 0x0A
                c.CONST(-1);           // LAYER – Specify chain layer number [0-3] (-1 = All)

                byte[] response = con.DirectCommand(c, 10, 0);
                if (response == null || response[8] != 0x0040 || response[9] == 0x0040)
                {
                    throw new Exception("Could not start EV3 remote client on device");
                }

                // set up local ping thread to periodically send a command to the watchdog
                // program to keep it alive (and check if the brick is still operating)
                (new System.Threading.Thread(runpings)).Start();
            }
        }
예제 #3
0
        public byte[] DirectCommand(ByteCodeBuffer bytecodes, int globalbytes, int localbytes)
        {
            // increase message counter (neccesary to check if request and respond match)
            messagecounter++;

            byte[] sendpacket = new byte[2 + 1 + 2 + bytecodes.Length];
            sendpacket[0] = (byte)(messagecounter & 0xff);
            sendpacket[1] = (byte)((messagecounter >> 8) & 0xff);
            sendpacket[2] = 0x00;   // DIRECT_COMMAND_REPLY
            sendpacket[3] = (byte)(globalbytes & 0xff);
            sendpacket[4] = (byte)(((globalbytes >> 8) & 0x3) + (localbytes << 2));
            bytecodes.CopyTo(sendpacket, 5);
            SendPacket(sendpacket);

            for (; ;)
            {
                byte[] packet = ReceivePacket();

                if (packet.Length < 3)
                {
                    throw new Exception("Reply has no message counter");
                }
                // wait until reply arrives that has a counter that matches the command
                ushort ctr = (ushort)(packet[0] + (packet[1] << 8));
                //         Console.WriteLine("Expected counter: "+messagecounter+ " received counter: " + ctr);
                if (ctr != messagecounter)
                {
                    continue;
                }
                // check if the direct command caused an error
                if (packet[2] == 0x04)
                {
                    return(null);
                }

                // check if problems with received packet
                if (packet[2] != 0x02)
                {
                    throw new Exception("Reply is not of correct type");
                }
                if (packet.Length != globalbytes + 3)
                {
                    throw new Exception("Reply size unexpected: " + packet.Length + " instead of " + (globalbytes + 3));
                }

                // extract data
                byte[] replydata = new byte[packet.Length - 3];
                System.Array.Copy(packet, 3, replydata, 0, packet.Length - 3);
                return(replydata);
            }
        }
예제 #4
0
        public static byte[] DirectCommand(ByteCodeBuffer bytecodes, int globalbytes, int localbytes)
        {
            try
            {
                lock (sync)
                {
                    // if not already done, memorize the start time and fire up the communication
                    MemorizeStartTime();
                    EstablishConnection();

                    // if requested to only queue the command, and the queue is not too full, and there is no expected response
                    if (queue_active && globalbytes == 0 && queue.Length + bytecodes.Length < 900)         // prevent to exceed 1024 bytes in single transmission
                    {
                        bytecodes.CopyTo(queue);
                        queue_locals = Math.Max(queue_locals, localbytes);
                        queue_active = false;
                        return(new byte[0]);
                    }
                    else
                    {
                        queue_active = false;   // remove queue-status in any case
                    }

                    // if there is data in the queue, try to merge it with the new command
                    if (queue.Length > 0)
                    {
                        // when total length is not too big, can send together with new command
                        if (queue.Length + bytecodes.Length < 900)
                        {
                            bytecodes.CopyTo(queue);
                            byte[] response = con.DirectCommand(queue, globalbytes, Math.Max(localbytes, queue_locals));
                            queue.Clear();
                            queue_locals = 0;
                            return(response);
                        }
                        // if can not be merged, send queued commands seperately
                        con.DirectCommand(queue, 0, queue_locals);
                        queue.Clear();
                        queue_locals = 0;
                    }

                    // finally execute the command
                    return(con.DirectCommand(bytecodes, globalbytes, localbytes));
                }
            }
            catch (Exception)
            {   // no connection - must terminate immediately
                System.Environment.Exit(1);
            }
            return(null);
        }
예제 #5
0
        // Periodically modify a flag in the global variables of program slot 1.
        // The program in slot 1 is a watchdog program that will notice when this "pings" no longer
        // arrive and will stop itself and shut down motors and sensors gracefully.
        // On the other side, the pinger will monitor if the watchdog is still running (could have
        // been stopped manually by the user) and if so, terminates the Basic program also.
        private static void runpings()
        {
            ByteCodeBuffer c = new ByteCodeBuffer();

            c.OP(0x3A);           // Move32_32
            c.CONST(42);          // move this value
            c.GLOBVAR(0);         // to gloval variable 0-3

            c.OP(0x7E);           // Memory_Write
            c.CONST(1);           // program slot 1 = user slot
            c.CONST(0);           // write to global variables
            c.CONST(0);           // to global variable 0
            c.CONST(4);           // write 4 bytes
            c.GLOBVAR(0);         // take the prepared value 42

            c.OP(0x0C);           // opProgram_Info
            c.CONST(0x16);        // CMD: GET_STATUS = 0x16
            c.CONST(1);           // program slot 1 = user slot
            c.GLOBVAR(0);

            for (; ;)
            {
                lock (sync)
                {
                    byte[] packet = null;
                    try
                    {
                        packet = con.DirectCommand(c, 4, 0);
                    }
                    catch (Exception e)
                    {
                        throw e;
                    }
                    // detected communication error or watchdog progam is no longer running
                    if (packet == null || packet.Length <= 0 || packet[0] == 0x40)
                    {
                        System.Environment.Exit(1);
                    }
                }
                System.Threading.Thread.Sleep(500);
            }
        }
예제 #6
0
 private static EV3Connection TestConnection(EV3Connection con)
 {
     try
     {
         // perform a tiny direct command to check if communication works
         ByteCodeBuffer c = new ByteCodeBuffer();
         c.OP(0x30);           // Move8_8
         c.CONST(74);
         c.GLOBVAR(0);
         byte[] response = con.DirectCommand(c, 1, 0);
         if (response == null || response.Length != 1 || response[0] != 74)
         {
             throw new Exception("Test DirectCommand delivers wrong result");
         }
         return(con);
     }
     catch (Exception e)
     {
         con.Close();
         throw e;
     }
 }
예제 #7
0
        public byte[] ReadEV3File(String fullname, ByteCodeBuffer pingercommand = null)
        {
            long nextping  = DateTime.Now.Ticks + 500;
            int  chunksize = 900;

            // start the transfer
            BinaryBuffer b = new BinaryBuffer();

            b.Append16(0);                     // transfer no content right now
            b.AppendZeroTerminated(fullname);

            byte[] response = SystemCommand(BEGIN_UPLOAD, b);

            if (response == null)
            {
                throw new Exception("No response to BEGIN_UPLOAD");
            }
            if (response.Length < 6)
            {
                throw new Exception("Response too short for BEGIN_UPLOAD");
            }
            if (response[0] != SUCCESS && response[0] != END_OF_FILE)
            {
                throw new Exception("Unexpected status at BEGIN_UPLOAD: " + response[0]);
            }

            int len    = ((int)response[1]) + (((int)response[2]) << 8) + (((int)response[3]) << 16) + (((int)response[4]) << 24);
            int handle = response[5] & 0xff;

//    Console.WriteLine("Start uploading file of size: " + len + ". handle=" + handle);

            byte[] buffer = new byte[len];
            int    pos    = 0;

            // transfer bytes in small chunks
            while (pos < len)
            {
                int transfernow = Math.Min(len - pos, chunksize);
                b.Clear();
                b.Append8(handle);
                b.Append16(transfernow);

                response = SystemCommand(CONTINUE_UPLOAD, b);

                if (response == null)
                {
                    throw new Exception("No response to CONTINUE_UPLOAD");
                }
                if (response.Length < 2 + transfernow)
                {
                    throw new Exception("Response too short for CONTINUE_UPLOAD");
                }
                if (response[0] != SUCCESS && response[0] != END_OF_FILE)
                {
                    throw new Exception("Unexpected status at CONTINUE_UPLOAD: " + response[0]);
                }

                for (int i = 0; i < transfernow; i++)
                {
                    buffer[pos + i] = response[2 + i];
                }
                pos += transfernow;

                // check if it is necessary to send intermediary pings to the watchdog program
                if (pingercommand != null && DateTime.Now.Ticks > nextping)
                {
                    DirectCommand(pingercommand, 4, 0);
                    nextping = DateTime.Now.Ticks + 500;
                }
            }

            return(buffer);
        }