public virtual IEnumerator<ITask> SendFileHandler(CopyFileToBrick sendFile)
        {
            Fault faultResponse = null;
            bool fileExists = false;
            bool done = false;

            #region See if the file is already on the LEGO NXT.

            nxtcmd.LegoCommand cmd = new nxtcmd.LegoFindFirst(sendFile.Body.FileName);
            yield return Arbiter.Choice(_legoBrickPort.SendNxtCommand(cmd),
                delegate(nxtcmd.LegoResponse ok)
                {
                    nxtcmd.LegoResponseFindFirst ffResponse = nxtcmd.LegoResponse.Upcast<nxtcmd.LegoResponseFindFirst>(ok);
                    if (ffResponse.Success && (ffResponse.FileName == sendFile.Body.FileName))
                    {
                        fileExists = true;
                        bool fileMatches = (sendFile.Body.FileData != null && sendFile.Body.FileData.Length == ffResponse.FileSize);
                        if (!sendFile.Body.ReplaceExistingFile)
                        {
                            string msg = ((fileMatches) ? "A matching file" : "A different file with the same name") + " already exists on the LEGO NXT Brick.";
                            sendFile.ResponsePort.Post(Fault.FromException(new System.IO.IOException(msg)));
                            done = true;
                        }
                    }
                },
                delegate(Fault fault)
                {
                    sendFile.ResponsePort.Post(fault);
                    done = true;
                });

            #endregion

            if (done)
                yield break;

            if (fileExists)
            {
                #region Remove the existing file

                cmd = new nxtcmd.LegoDelete(sendFile.Body.FileName);
                yield return Arbiter.Choice(_legoBrickPort.SendNxtCommand(cmd),
                    EmptyHandler<nxtcmd.LegoResponse>,
                    delegate(Fault fault)
                    {
                        done = true;
                        sendFile.ResponsePort.Post(fault);
                    });
                #endregion
            }

            if (done)
                yield break;

            #region Upload the file to the Brick.

            byte[] fileData = sendFile.Body.FileData;
            string fileName = sendFile.Body.FileName;
            if (fileData != null)
            {
                int pgmLength = fileData.Length;
                int handle = -1;
                LogInfo(LogGroups.Console, "Downloading " + fileName + " to LEGO NXT.");

                PortSet<nxtcmd.LegoResponse, Fault> responsePort = new PortSet<nxtcmd.LegoResponse, Fault>();
                done = false;
                int trial = 0;
                while (trial < 5 && !done)
                {
                    nxtcmd.LegoOpenWriteLinear openWrite = new nxtcmd.LegoOpenWriteLinear(fileName, pgmLength);
                    responsePort = _legoBrickPort.SendNxtCommand(openWrite);
                    yield return Arbiter.Choice(
                        Arbiter.Receive<nxtcmd.LegoResponse>(false, responsePort,
                            delegate(nxtcmd.LegoResponse response)
                            {
                                nxtcmd.LegoResponseOpenWriteLinear responseOpenWriteLinear = new nxtcmd.LegoResponseOpenWriteLinear(response.CommandData);
                                if (response.ErrorCode == LegoErrorCode.Success || response.ErrorCode == LegoErrorCode.FileExists)
                                {
                                    handle = responseOpenWriteLinear.Handle;
                                    done = true;
                                }
                                else if (response.ErrorCode == LegoErrorCode.NoSpace)
                                {
                                    faultResponse = Fault.FromException(new System.IO.IOException("Out of space on LEGO NXT Brick.\nPlease remove one or more LEGO NXT programs on the NXT Brick."));
                                    trial = 999;
                                }
                                else
                                {
                                    faultResponse = Fault.FromException(new System.IO.IOException("Error preparing to upload " + fileName + " file to the LEGO NXT: " + response.ErrorCode.ToString()));
                                }
                            }),
                        Arbiter.Receive<Fault>(false, responsePort,
                            delegate(Fault fault)
                            {
                                faultResponse = fault;
                            }));

                    trial++;
                }

                if (!done)
                {
                    if (faultResponse == null)
                        faultResponse = Fault.FromException(new System.IO.IOException("Failed to create the new file"));
                    sendFile.ResponsePort.Post(faultResponse);
                    yield break;
                }

                done = false;
                trial = 0;
                while (trial < 5 && !done)
                {
                    nxtcmd.LegoWrite legoWrite = new nxtcmd.LegoWrite(handle, fileData);
                    responsePort = _legoBrickPort.SendNxtCommand(legoWrite);
                    yield return Arbiter.Choice(
                        Arbiter.Receive<nxtcmd.LegoResponse>(false, responsePort,
                            delegate(nxtcmd.LegoResponse response)
                            {
                                nxtcmd.LegoResponseWrite responseWrite = new nxtcmd.LegoResponseWrite(response.CommandData);
                                if (response.ErrorCode == LegoErrorCode.Success)
                                {
                                    if (pgmLength != responseWrite.BytesWritten)
                                        LogWarning(LogGroups.Console, "Warning: " + fileName + " file length on LEGO NXT does not match the PC.");
                                    done = true;
                                }
                                else
                                {
                                    faultResponse = Fault.FromException(new System.IO.IOException("Error sending " + fileName + " file to the LEGO NXT: " + response.ErrorCode.ToString()));
                                    LogError(faultResponse);
                                }
                            }),
                        Arbiter.Receive<Fault>(false, responsePort,
                            delegate(Fault fault)
                            {
                                faultResponse = fault;
                                LogError(LogGroups.Console, "Timed out sending " + fileName + " file to the LEGO NXT");
                            }));

                    trial++;
                }

                if (!done)
                {
                    if (faultResponse == null)
                        faultResponse = Fault.FromException(new System.IO.IOException("Failed to write to the new file,"));
                    sendFile.ResponsePort.Post(faultResponse);

                    yield break;
                }

                // Now Close the Write Buffer.
                done = false;

                nxtcmd.LegoClose legoClose = new nxtcmd.LegoClose(handle);
                legoClose.TryCount = 5;
                responsePort = _legoBrickPort.SendNxtCommand(legoClose);
                yield return Arbiter.Choice(
                    Arbiter.Receive<nxtcmd.LegoResponse>(false, responsePort,
                        delegate(nxtcmd.LegoResponse response)
                        {
                            if (response.ErrorCode == LegoErrorCode.Success)
                            {
                                sendFile.ResponsePort.Post(DefaultSubmitResponseType.Instance);
                                done = true;
                            }
                            else
                            {
                                faultResponse = Fault.FromException(new System.IO.IOException("Error closing " + fileName + " file on the LEGO NXT: " + response.ErrorCode.ToString()));
                                LogError(faultResponse);
                            }
                        }),
                    Arbiter.Receive<Fault>(false, responsePort,
                        delegate(Fault fault)
                        {
                            faultResponse = fault;
                            LogError(LogGroups.Console, "Timed out closing file during SendFile.");
                        }));

            }
            else
            {
                faultResponse = Fault.FromException(new ArgumentNullException("The source file was not provided"));
            }

            if (done)
                yield break;

            if (faultResponse == null)
                faultResponse = Fault.FromException(new System.IO.IOException("Failed to write to the new file,"));

            sendFile.ResponsePort.Post(faultResponse);

            #endregion

            yield break;
        }
Example #2
0
        public virtual IEnumerator <ITask> SendFileHandler(CopyFileToBrick sendFile)
        {
            Fault faultResponse = null;
            bool  fileExists    = false;
            bool  done          = false;

            #region See if the file is already on the LEGO NXT.

            nxtcmd.LegoCommand cmd = new nxtcmd.LegoFindFirst(sendFile.Body.FileName);
            yield return(Arbiter.Choice(_legoBrickPort.SendNxtCommand(cmd),
                                        delegate(nxtcmd.LegoResponse ok)
            {
                nxtcmd.LegoResponseFindFirst ffResponse = nxtcmd.LegoResponse.Upcast <nxtcmd.LegoResponseFindFirst>(ok);
                if (ffResponse.Success && (ffResponse.FileName == sendFile.Body.FileName))
                {
                    fileExists = true;
                    bool fileMatches = (sendFile.Body.FileData != null && sendFile.Body.FileData.Length == ffResponse.FileSize);
                    if (!sendFile.Body.ReplaceExistingFile)
                    {
                        string msg = ((fileMatches) ? "A matching file" : "A different file with the same name") + " already exists on the LEGO NXT Brick.";
                        sendFile.ResponsePort.Post(Fault.FromException(new System.IO.IOException(msg)));
                        done = true;
                    }
                }
            },
                                        delegate(Fault fault)
            {
                sendFile.ResponsePort.Post(fault);
                done = true;
            }));

            #endregion

            if (done)
            {
                yield break;
            }

            if (fileExists)
            {
                #region Remove the existing file

                cmd = new nxtcmd.LegoDelete(sendFile.Body.FileName);
                yield return(Arbiter.Choice(_legoBrickPort.SendNxtCommand(cmd),
                                            EmptyHandler <nxtcmd.LegoResponse>,
                                            delegate(Fault fault)
                {
                    done = true;
                    sendFile.ResponsePort.Post(fault);
                }));

                #endregion
            }

            if (done)
            {
                yield break;
            }


            #region Upload the file to the Brick.

            byte[] fileData = sendFile.Body.FileData;
            string fileName = sendFile.Body.FileName;
            if (fileData != null)
            {
                int pgmLength = fileData.Length;
                int handle    = -1;
                LogInfo(LogGroups.Console, "Downloading " + fileName + " to LEGO NXT.");

                PortSet <nxtcmd.LegoResponse, Fault> responsePort = new PortSet <nxtcmd.LegoResponse, Fault>();
                done = false;
                int trial = 0;
                while (trial < 5 && !done)
                {
                    nxtcmd.LegoOpenWriteLinear openWrite = new nxtcmd.LegoOpenWriteLinear(fileName, pgmLength);
                    responsePort = _legoBrickPort.SendNxtCommand(openWrite);
                    yield return(Arbiter.Choice(
                                     Arbiter.Receive <nxtcmd.LegoResponse>(false, responsePort,
                                                                           delegate(nxtcmd.LegoResponse response)
                    {
                        nxtcmd.LegoResponseOpenWriteLinear responseOpenWriteLinear = new nxtcmd.LegoResponseOpenWriteLinear(response.CommandData);
                        if (response.ErrorCode == LegoErrorCode.Success || response.ErrorCode == LegoErrorCode.FileExists)
                        {
                            handle = responseOpenWriteLinear.Handle;
                            done = true;
                        }
                        else if (response.ErrorCode == LegoErrorCode.NoSpace)
                        {
                            faultResponse = Fault.FromException(new System.IO.IOException("Out of space on LEGO NXT Brick.\nPlease remove one or more LEGO NXT programs on the NXT Brick."));
                            trial = 999;
                        }
                        else
                        {
                            faultResponse = Fault.FromException(new System.IO.IOException("Error preparing to upload " + fileName + " file to the LEGO NXT: " + response.ErrorCode.ToString()));
                        }
                    }),
                                     Arbiter.Receive <Fault>(false, responsePort,
                                                             delegate(Fault fault)
                    {
                        faultResponse = fault;
                    })));

                    trial++;
                }

                if (!done)
                {
                    if (faultResponse == null)
                    {
                        faultResponse = Fault.FromException(new System.IO.IOException("Failed to create the new file"));
                    }
                    sendFile.ResponsePort.Post(faultResponse);
                    yield break;
                }

                done  = false;
                trial = 0;
                while (trial < 5 && !done)
                {
                    nxtcmd.LegoWrite legoWrite = new nxtcmd.LegoWrite(handle, fileData);
                    responsePort = _legoBrickPort.SendNxtCommand(legoWrite);
                    yield return(Arbiter.Choice(
                                     Arbiter.Receive <nxtcmd.LegoResponse>(false, responsePort,
                                                                           delegate(nxtcmd.LegoResponse response)
                    {
                        nxtcmd.LegoResponseWrite responseWrite = new nxtcmd.LegoResponseWrite(response.CommandData);
                        if (response.ErrorCode == LegoErrorCode.Success)
                        {
                            if (pgmLength != responseWrite.BytesWritten)
                            {
                                LogWarning(LogGroups.Console, "Warning: " + fileName + " file length on LEGO NXT does not match the PC.");
                            }
                            done = true;
                        }
                        else
                        {
                            faultResponse = Fault.FromException(new System.IO.IOException("Error sending " + fileName + " file to the LEGO NXT: " + response.ErrorCode.ToString()));
                            LogError(faultResponse);
                        }
                    }),
                                     Arbiter.Receive <Fault>(false, responsePort,
                                                             delegate(Fault fault)
                    {
                        faultResponse = fault;
                        LogError(LogGroups.Console, "Timed out sending " + fileName + " file to the LEGO NXT");
                    })));

                    trial++;
                }

                if (!done)
                {
                    if (faultResponse == null)
                    {
                        faultResponse = Fault.FromException(new System.IO.IOException("Failed to write to the new file,"));
                    }
                    sendFile.ResponsePort.Post(faultResponse);

                    yield break;
                }


                // Now Close the Write Buffer.
                done = false;

                nxtcmd.LegoClose legoClose = new nxtcmd.LegoClose(handle);
                legoClose.TryCount = 5;
                responsePort       = _legoBrickPort.SendNxtCommand(legoClose);
                yield return(Arbiter.Choice(
                                 Arbiter.Receive <nxtcmd.LegoResponse>(false, responsePort,
                                                                       delegate(nxtcmd.LegoResponse response)
                {
                    if (response.ErrorCode == LegoErrorCode.Success)
                    {
                        sendFile.ResponsePort.Post(DefaultSubmitResponseType.Instance);
                        done = true;
                    }
                    else
                    {
                        faultResponse = Fault.FromException(new System.IO.IOException("Error closing " + fileName + " file on the LEGO NXT: " + response.ErrorCode.ToString()));
                        LogError(faultResponse);
                    }
                }),
                                 Arbiter.Receive <Fault>(false, responsePort,
                                                         delegate(Fault fault)
                {
                    faultResponse = fault;
                    LogError(LogGroups.Console, "Timed out closing file during SendFile.");
                })));
            }
            else
            {
                faultResponse = Fault.FromException(new ArgumentNullException("The source file was not provided"));
            }

            if (done)
            {
                yield break;
            }

            if (faultResponse == null)
            {
                faultResponse = Fault.FromException(new System.IO.IOException("Failed to write to the new file,"));
            }

            sendFile.ResponsePort.Post(faultResponse);

            #endregion

            yield break;
        }