示例#1
0
        public async Task Run_Should_Output_Code_Results_When_Valid()
        {
            // arrange
            var input  = "test code";
            var output = "test output";
            var result = new CodeResult
            {
                Output    = output,
                State     = OutputState.Valid,
                Variables = Enumerable.Range(1, 2).Select(i => $"test-var-{i}").ToList(),
            };

            var console = new Mock <IConsole>();

            var expectedColPosition = 3;

            console
            .Setup(c => c.CursorLeft)
            .Returns(expectedColPosition);

            var expectedRowPosition = 6;

            console
            .Setup(c => c.CursorTop)
            .Returns(expectedRowPosition);

            var keyHandler    = new Mock <IConsoleKeyHandler>();
            var consoleWriter = new Mock <IConsoleWriter>();
            var replEngine    = new Mock <IReplEngine>();
            var loop          = new Mock <ILoop>();
            var consoleState  = new Mock <IConsoleState>();

            keyHandler
            .Setup(c => c.Process(consoleState.Object))
            .Returns(input);

            replEngine
            .Setup(r => r.Execute(input))
            .ReturnsAsync(result);

            loop
            .SetupSequence(l => l.Continue())
            .Returns(true)
            .Returns(false);

            var interactiveLoop = new InteractiveLoop(console.Object,
                                                      keyHandler.Object, consoleWriter.Object, replEngine.Object, loop.Object, consoleState.Object);

            // act
            await interactiveLoop.Run();

            // assert
            consoleState.VerifySet(c => c.ColPosition = expectedColPosition);
            consoleState.VerifySet(c => c.RowPosition = expectedRowPosition);

            consoleWriter.Verify(c => c.WriteOutput(output), Times.Once);
            consoleWriter.Verify(c => c.WriteError(output), Times.Never);

            consoleState.Verify(c => c.CompleteInput(result.Variables));
        }
示例#2
0
        private async Task <CodeResult> ExecuteInternally()
        {
            CodeResult result = null;

            // Preprocess this code
            if (!Flags.HasFlag(CodeFlags.IsPreProcessed))
            {
                result = await Interception.Intercept(this, InterceptionMode.Pre);

                Flags |= CodeFlags.IsPreProcessed;

                if (result != null)
                {
                    InternallyExecuted = true;
                    return(await OnCodeExecuted(result));
                }
            }

            // Attempt to process the code internally
            switch (Type)
            {
            case CodeType.GCode:
                result = await GCodes.Process(this);

                break;

            case CodeType.MCode:
                result = await MCodes.Process(this);

                break;

            case CodeType.TCode:
                result = await TCodes.Process(this);

                break;
            }

            if (result != null)
            {
                InternallyExecuted = true;
                return(await OnCodeExecuted(result));
            }

            // If the could not be interpreted, post-process it
            if (!Flags.HasFlag(CodeFlags.IsPostProcessed))
            {
                result = await Interception.Intercept(this, InterceptionMode.Post);

                Flags |= CodeFlags.IsPostProcessed;

                if (result != null)
                {
                    InternallyExecuted = true;
                    return(await OnCodeExecuted(result));
                }
            }

            // Code has not been interpreted yet
            return(null);
        }
示例#3
0
        public async Task Execute_Should_Continue_When_Not_Complete()
        {
            // arrange
            var codeLines = new List <string>
            {
                "var ",
                "foo =\"bar\";",
                "foo",
            };

            var inputCheck           = new Mock <IInputCheck>();
            var scriptOptionsBuilder = new Mock <IScriptOptionsBuilder>();
            var engine     = new ReplEngine(inputCheck.Object, scriptOptionsBuilder.Object);
            var builder    = new StringBuilder();
            var codeResult = new CodeResult();

            // act
            foreach (var line in codeLines)
            {
                builder.AppendLine(line);

                codeResult = await engine.Execute(builder.ToString());
            }

            // assert
            Assert.That(codeResult.Output, Is.EqualTo("bar"));
            Assert.That(codeResult.State, Is.EqualTo(OutputState.Valid));
        }
示例#4
0
            public static Cell Eval(Cell code, CodeResult cr, SchemeEnvironment env)
            {
                List <Cell> args = new List <Cell>();

                args.Add(code);
                args.Add(new Cell(env));

                Machine machine = new Machine(cr, args);

                try {
                    System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
                    sw.Start();
                    while (machine.Finished == false)
                    {
                        machine.Step();
                    }
                    StepsExecuted += machine.Steps;
                    sw.Stop();
                    Console.WriteLine("!Eval ran in {0}", sw.Elapsed);
                } catch (Exception e) {
                    Debug.WriteLine("Eval failed: {0}", e.Message);
                }

                return(machine.A);
            }
示例#5
0
        public CodeResult LogOut()
        {
            var jtiClaims = User.Claims.FirstOrDefault(item => item.Type == JwtRegisteredClaimNames.Jti);

            _cache.Set(jtiClaims.Value, jtiClaims.Value, TimeSpan.FromHours(2));  // 将token唯一标识存入缓存中, 用于判断当前Token已注销,即使token在有效期内

            return(CodeResult.Success());
        }
 /// <summary>
 /// Log and output a code result
 /// </summary>
 /// <param name="result">Code result</param>
 /// <returns>Asynchronous task</returns>
 public static async Task LogOutput(CodeResult result)
 {
     if (result != null)
     {
         foreach (Message msg in result)
         {
             await LogOutput(msg);
         }
     }
 }
示例#7
0
 /// <summary>
 /// Write messages including timestamp to the log file
 /// </summary>
 /// <param name="result">Message list</param>
 public static async Task Log(CodeResult result)
 {
     if (result != null)
     {
         foreach (Message msg in result)
         {
             LogLevel level = (msg.Type == MessageType.Success) ? LogLevel.Info : LogLevel.Warn;
             await Log(level, msg);
         }
     }
 }
示例#8
0
 public static CodeResult GetCodeResult(string filepath, string entry = "main")
 {
     filepath = Program.GetFilePath(filepath);
     if (!codeCache.ContainsKey(filepath))
     {
         string code = System.IO.File.ReadAllText(filepath);
         CellMachineAssembler assembler = new CellMachineAssembler(code, entry);
         CodeResult           cr        = CellMachineAssembler.Assemble(code, entry);
         codeCache.Add(filepath, cr);
     }
     return(codeCache[filepath]);
 }
示例#9
0
        /// <summary>
        /// Print the diagnostics
        /// </summary>
        /// <param name="result">Target to write to</param>
        /// <returns>Asynchronous task</returns>
        private static async Task Diagnostics(CodeResult result)
        {
            StringBuilder builder = new StringBuilder();

            builder.AppendLine("=== Duet Control Server ===");
            builder.AppendLine($"Duet Control Server v{Assembly.GetExecutingAssembly().GetName().Version}");
            await SPI.Interface.Diagnostics(builder);

            SPI.DataTransfer.Diagnostics(builder);
            await Print.Diagnostics(builder);

            result.Add(MessageType.Success, builder.ToString().TrimEnd());
        }
示例#10
0
            public override Cell Eval(Cell Arg, SchemeEnvironment Env)
            {
                CodeResult cr      = GetCodeResult("Eval.asm");
                Machine    machine = new Machine(cr, new Cell[] { Arg, new Cell(Env) });

                machine.DebugMode = useDebug;
                while (machine.Finished == false)
                {
                    machine.Step();
                }
                stepCounter += machine.Steps;
                return(Result = machine.A);
            }
示例#11
0
        /// <summary>
        /// Print the diagnostics
        /// </summary>
        /// <param name="result">Target to write to</param>
        /// <returns>Asynchronous task</returns>
        private static async Task Diagnostics(CodeResult result)
        {
            StringBuilder builder = new StringBuilder();

            builder.AppendLine("=== Duet Control Server ===");
            builder.AppendLine($"Duet Control Server v{Program.Version}");

            await SPI.Interface.Diagnostics(builder);

            SPI.DataTransfer.Diagnostics(builder);
            await FileExecution.Job.Diagnostics(builder);

            result.Add(MessageType.Success, builder.ToString().TrimEnd());
        }
示例#12
0
        public async Task Run_Should_Output_Error_Message_From_Result_When_Error_State()
        {
            // arrange
            var input  = "test invalid code";
            var output = "error output";
            var result = new CodeResult
            {
                Output    = output,
                State     = OutputState.Error,
                Variables = Enumerable.Range(1, 3).Select(i => $"test-var-{i}").ToList(),
            };

            var console       = new Mock <IConsole>();
            var keyHandler    = new Mock <IConsoleKeyHandler>();
            var consoleWriter = new Mock <IConsoleWriter>();
            var replEngine    = new Mock <IReplEngine>();
            var loop          = new Mock <ILoop>();
            var consoleState  = new Mock <IConsoleState>();

            keyHandler
            .Setup(c => c.Process(consoleState.Object))
            .Returns(input);

            replEngine
            .Setup(r => r.Execute(input))
            .ReturnsAsync(result);

            loop
            .SetupSequence(l => l.Continue())
            .Returns(true)
            .Returns(false);

            consoleState
            .Setup(c => c.Text)
            .Returns(new StringBuilder());

            var interactiveLoop = new InteractiveLoop(console.Object,
                                                      keyHandler.Object, consoleWriter.Object, replEngine.Object, loop.Object, consoleState.Object);

            // act
            await interactiveLoop.Run();

            // assert
            consoleState.VerifySet(c => c.TextRowPosition = 1, Times.Never, "should not increment");

            consoleWriter.Verify(c => c.WriteOutput(output), Times.Never);
            consoleWriter.Verify(c => c.WriteError(output), Times.Once);

            consoleState.Verify(c => c.CompleteInput(result.Variables));
        }
示例#13
0
        private async Task <CodeResult> OnCodeExecuted(CodeResult result)
        {
            // Process code result
            switch (Type)
            {
            case CodeType.GCode:
                result = await GCodes.CodeExecuted(this, result);

                break;

            case CodeType.MCode:
                result = await MCodes.CodeExecuted(this, result);

                break;

            case CodeType.TCode:
                result = await TCodes.CodeExecuted(this, result);

                break;
            }

            // RepRapFirmware generally prefixes error messages with the code itself.
            // Do this only for error messages that come either from a print or from a macro
            if (result != null && (Flags.HasFlag(CodeFlags.IsFromMacro) || Channel == CodeChannel.File))
            {
                foreach (Message msg in result)
                {
                    if (msg.Type == MessageType.Error)
                    {
                        msg.Content = ToShortString() + ": " + msg.Content;
                    }
                }
            }

            // Log warning+error replies if the code could be processed internally
            if (InternallyExecuted && !result.IsEmpty)
            {
                foreach (Message msg in result)
                {
                    if (msg.Type != MessageType.Success || Channel == CodeChannel.File)
                    {
                        await Utility.Logger.Log(msg);
                    }
                }
            }

            // Finished. Optionally an "Executed" interceptor could be called here, but that would only make sense if the code reply was included
            return(result);
        }
        private static List <SearchResult> GetQuickFixesFromCodeResult(CodeResult codeResult, string filePath, bool findReferences,
                                                                       string searchFilter, bool exactMatch)
        {
            var foundSymbols = new List <SearchResult>();

            if (!codeResult.Matches.TryGetValue("content", out IEnumerable <Hit> contentHitsEnum))
            {
                return(foundSymbols);
            }

            List <Hit> contentHits    = contentHitsEnum.ToList();
            int        lineOffsetWin  = 0;
            int        lineOffsetUnix = 0;
            int        lineNumber     = 0;

            foreach (string line in File.ReadLines(filePath))
            {
                foreach (Hit hit in contentHits.OrderBy(h => h.CharOffset))
                {
                    // Hit.CharOffset is calculated based on end-of-lines of the file stored by the service which can be different from local file end-of-lines.
                    // Try guessing what end-of-lines were used by the service and use the first match.
                    if (hit.CharOffset >= lineOffsetUnix && hit.CharOffset < lineOffsetUnix + line.Length)
                    {
                        if (ConsiderMatchCandidate(filePath, findReferences, searchFilter, exactMatch, hit, lineNumber, lineOffsetUnix, line, foundSymbols))
                        {
                            // Keep only a single match per line per hit - it is already clone enough
                            continue;
                        }
                    }

                    if (hit.CharOffset >= lineOffsetWin && hit.CharOffset < lineOffsetWin + line.Length)
                    {
                        ConsiderMatchCandidate(filePath, findReferences, searchFilter, exactMatch, hit, lineNumber, lineOffsetWin, line, foundSymbols);
                    }
                }

                if (foundSymbols.Count >= contentHits.Count)
                {
                    // Found matching symbols for all hits - can stop searching the file
                    break;
                }

                lineOffsetWin  += line.Length + 2;
                lineOffsetUnix += line.Length + 1;
                lineNumber++;
            }

            return(foundSymbols);
        }
示例#15
0
        private static unsafe CodeResult VirtualMachine__RunCodeHook(VirtualMachine *vm, OpCode *op, IntPtr a3, uint opLimit, IntPtr a5)
        {
            CodeResult result = VirtualMachine__RunCode(vm, op, a3, opLimit, a5);

            try
            {
                VirtualMachine__RunCodeCallback?.Invoke(vm, op, a3, opLimit, a5, result);
            }
            catch (Exception ex)
            {
                Trace.WriteLine($"Unhandled Exception in {nameof(Script)}.{nameof(VirtualMachine__RunCodeHook)}!");
                Trace.WriteLine(ex.ToString());
            }
            return(result);
        }
示例#16
0
        /// <summary>
        /// 获取支付二维码
        /// </summary>
        /// <param name="orderModel"></param>
        /// <returns></returns>
        public CodeResult WXPayRequest(OrderInfoEntity orderModel)
        {
            CodeResult result = new CodeResult();



            string parameterString = @"version=1.0&merid=26100794&mername=北京联友创新科技发展有限公司&merorderid="
                                     + orderModel.OrderCode + "&paymoney=" + orderModel.TotalAmount + "&productname=" +
                                     "&productdesc=&userid=" + orderModel.UserId + "&username="******"&email=&phone=&extra=&custom=";
            string md5 = MD5Hash.GetMD5String(parameterString);//md5校验值

            //发送支付请求

            try
            {
                string url = "";
                //微信支付
                if (orderModel.PayType == 1)
                {
                    url = ConfigHelper.GetAppConfigString("WXPayUrl") + @"?version=1.0&merid=26100794&mername=北京联友创新科技发展有限公司&merorderid="
                          + orderModel.OrderCode + "&paymoney=" + orderModel.TotalAmount + "&productname=" +
                          "&productdesc=&userid=" + orderModel.UserId + "&username="******"&email=&phone=&extra=&custom=&md5=" + md5;
                }
                //支付宝支付
                if (orderModel.PayType == 2)
                {
                    url = ConfigHelper.GetAppConfigString("ZFBPayUrl") + @"?version=1.0&merid=26100794&mername=北京联友创新科技发展有限公司&merorderid="
                          + orderModel.OrderCode + "&paymoney=" + orderModel.TotalAmount + "&productname=" +
                          "&productdesc=&userid=" + orderModel.UserId + "&username="******"&email=&phone=&extra=&custom=&md5=" + md5;
                }


                LogHelper.Info("url=" + url);
                result = HttpClientHelper.GetResponse <CodeResult>(url);
            }
            catch (Exception ex)
            {
                //LogHelper.WriteLog(typeof(WXPayBLL), "WXPayRequest", Engineer.ggg, orderModel, ex);

                LogHelper.WriteInfo(typeof(PayBll), ex.Message);
            }


            return(result);
        }
        /// <summary>
        /// Called by the <see cref="Code"/> class to intercept a code.
        /// This method goes through each connected interception channel and notifies the clients.
        /// </summary>
        /// <param name="code">Code to intercept</param>
        /// <param name="type">Type of the interception</param>
        /// <returns>null if not intercepted and a CodeResult otherwise</returns>
        public static async Task <CodeResult> Intercept(Code code, InterceptionMode type)
        {
            foreach (var pair in _interceptors)
            {
                if (code.SourceConnection != pair.Key.Connection.Id && pair.Value == type)
                {
                    CodeResult result = await pair.Key.Intercept(code);

                    if (result != null)
                    {
                        return(result);
                    }
                }
            }
            return(null);
        }
示例#18
0
        /// <summary>
        /// Start an arbitrary G/M/T-code and get the task that is resolved when RRF finishes its execution.
        /// This is an internal alternative to the <see cref="CodeFlags.Asynchronous"/> flag.
        /// </summary>
        /// <returns>Asynchronous task</returns>
        public Task <CodeResult> Enqueue()
        {
            CodeResult result = InternallyExecuted ? null : ExecuteInternally().Result;

            if (result != null)
            {
                return(Task.FromResult(result));
            }

            if (Type != CodeType.Comment)
            {
                Task <CodeResult> codeTask = Interface.ProcessCode(this);
                return(codeTask.ContinueWith((task) => OnCodeExecuted(task.Result).Result));
            }
            return(OnCodeExecuted(result));
        }
        /// <summary>
        /// Converts simple G/M/T-codes to a regular Code instances, executes them and returns the result as text
        /// </summary>
        /// <returns>G-code result as text</returns>
        public override async Task <string> Execute()
        {
            IList <Code> codes;
            Queue <Task <CodeResult> > codeTasks = new Queue <Task <CodeResult> >();

            CodeResult result = new CodeResult();

            try
            {
                codes = Commands.Code.ParseMultiple(Code);
                foreach (Code code in codes)
                {
                    // M122 always goes to the Daemon channel so we (hopefully) get a low-latency response
                    code.Channel          = (code.Type == CodeType.MCode && code.MajorNumber == 122) ? DuetAPI.CodeChannel.Daemon : Channel;
                    code.SourceConnection = SourceConnection;

                    codeTasks.Enqueue(code.Enqueue());
                }
            }
            catch (CodeParserException e)
            {
                return($"Error: {e.Message}]\n");
            }

            while (codeTasks.TryDequeue(out Task <CodeResult> task))
            {
                Code code = codes[0];
                codes.RemoveAt(0);

                try
                {
                    CodeResult codeResult = await task;
                    if (codeResult != null && !codeResult.IsEmpty)
                    {
                        result.AddRange(codeResult);
                    }
                }
                catch (AggregateException ae)
                {
                    // FIXME: Should this terminate the code(s) being executed?
                    Console.WriteLine($"[err] {code} -> {ae.InnerException.Message}");
                }
            }

            return(result.ToString());
        }
示例#20
0
        private static unsafe CodeResult VirtualMachine__RunCodeHook(VirtualMachine *vm, OpCode *op, IntPtr a3, uint opLimit, IntPtr a5)
        {
            //string value = vm->TryGetOpCodeFunctionName(op, out string name) ? name : null;
            //if (value != null) Trace.WriteLine($"[RunCode] {name} Start");
            CodeResult result = VirtualMachine__RunCode(vm, op, a3, opLimit, a5);

            try
            {
                VirtualMachine__RunCodeCallback?.Invoke(vm, op, a3, opLimit, a5, result);
                //if (value != null) Trace.WriteLine($"[RunCode] {name} End");
            }
            catch (Exception ex)
            {
                Trace.WriteLine($"Unhandled Exception in {nameof(Script)}.{nameof(VirtualMachine__RunCodeHook)}!");
                Trace.WriteLine(ex.ToString());
            }
            return(result);
        }
 public void OnException(ExceptionContext context)
 {
     if (context.Exception is CodeException codeException)
     {
         context.Result = new ObjectResult(
             CodeResult.FromCodeException(codeException));
     }
     else
     {
         context.Result = new ObjectResult(
             CodeResult.FromCode(DefaultExceptionCode, context.Exception.Message, context.Exception.Data))
         {
             StatusCode = DefaultExceptionHttpStatusCode
         };
         context.ExceptionHandled = true;
     }
     context.ExceptionHandled = true;
 }
示例#22
0
        /// <summary>
        /// React to an executed M-code before its result is returend
        /// </summary>
        /// <param name="code">Code processed by RepRapFirmware</param>
        /// <param name="result">Result that it generated</param>
        /// <returns>Result to output</returns>
        /// <remarks>This method shall be used only to update values that are time-critical. Others are supposed to be updated via the object model</remarks>
        public static async Task <CodeResult> CodeExecuted(Code code, CodeResult result)
        {
            if (!result.IsSuccessful)
            {
                return(result);
            }

            switch (code.MajorNumber)
            {
            // Resume print
            case 24:
                if (Print.IsPaused)
                {
                    // Resume sending file instructions to the firmware
                    Print.Resume();
                }
                break;

            // Absolute extrusion
            case 82:
                using (await Model.Provider.AccessReadWriteAsync())
                {
                    Model.Provider.Get.Channels[code.Channel].RelativeExtrusion = false;
                }
                break;

            // Relative extrusion
            case 83:
                using (await Model.Provider.AccessReadWriteAsync())
                {
                    Model.Provider.Get.Channels[code.Channel].RelativeExtrusion = false;
                }
                break;

            // Diagnostics
            case 122:
                if (code.GetUnprecedentedString() != "DSF")
                {
                    await Diagnostics(result);
                }
                break;
            }
            return(result);
        }
示例#23
0
        /// <summary>
        /// Converts a simple G/M/T-code to a regular Code instance, executes it and returns its result as text
        /// </summary>
        /// <returns>G-code result as text</returns>
        public override async Task <string> Execute()
        {
            Code code = new Code(Code)
            {
                Channel          = Channel,
                SourceConnection = SourceConnection
            };

            // Send diagnostics request always over the Daemon channel.
            // This way, diagnotics can be output even if a code is blocking everything else
            if (code.Type == CodeType.MCode && code.MajorNumber == 122)
            {
                code.Channel = DuetAPI.CodeChannel.Daemon;
            }

            CodeResult result = await code.Execute();

            return((result != null) ? result.ToString() : "");
        }
 public void OnResultExecuting(ResultExecutingContext context)
 {
     if (context.Result is ObjectResult obj && obj.Value is not CodeResult)
     {
         if (IsSuccessCode(obj))
         {
             context.Result = new ObjectResult(CodeResult.FromData(SuccessCode, SuccessMessage, obj.Value))
             {
                 StatusCode = obj.StatusCode
             };
         }
         else
         {
             context.Result = new ObjectResult(CodeResult.FromData($"{obj.StatusCode}", obj.Value?.ToString(), obj.Value))
             {
                 StatusCode = obj.StatusCode
             };
         }
     }
示例#25
0
        /// <summary>
        /// Run an arbitrary G/M/T-code and wait for it to finish
        /// </summary>
        /// <returns>Code result instance</returns>
        public override async Task <CodeResult> Execute()
        {
            // Attempt to process the code internally
            CodeResult result = InternallyExecuted ? null : await ExecuteInternally();

            if (result != null)
            {
                return(result);
            }

            // Send it to RepRapFirmware unless it is a comment
            if (Type != CodeType.Comment)
            {
                if (Flags.HasFlag(CodeFlags.Asynchronous))
                {
                    // Enqueue the code for execution by RRF and return no result
                    Task <CodeResult> codeTask = Interface.ProcessCode(this);
                    _ = Task.Run(async() =>
                    {
                        try
                        {
                            CodeResult res = await codeTask;
                            res            = await OnCodeExecuted(res);
                            await Model.Provider.Output(res);
                        }
                        catch (AggregateException ae)
                        {
                            Console.WriteLine($"[err] {this} -> {ae.InnerException.Message}");
                        }
                    });
                    return(null);
                }
                else
                {
                    // Wait for the code to complete
                    result = await Interface.ProcessCode(this);
                }
            }

            return(await OnCodeExecuted(result));
        }
        /// <summary>
        /// Converts simple G/M/T-codes to a regular Code instances, executes them and returns the result as text
        /// </summary>
        /// <returns>Code result as text</returns>
        /// <exception cref="OperationCanceledException">Code has been cancelled</exception>
        public override async Task <string> Execute()
        {
            CodeResult result = new CodeResult();

            try
            {
                List <Code> codes = Commands.Code.ParseMultiple(Code);
                foreach (Code code in codes)
                {
                    // M112, M122, and M999 always go to the Daemon channel so we (hopefully) get a low-latency response
                    if (code.Type == CodeType.MCode && (code.MajorNumber == 112 || code.MajorNumber == 122 || code.MajorNumber == 999))
                    {
                        code.Channel = DuetAPI.CodeChannel.Daemon;
                        code.Flags  |= CodeFlags.IsPrioritized;
                    }
                    else
                    {
                        code.Channel = Channel;
                    }

                    // Execute the code and append the result
                    CodeResult codeResult = await code.Execute();

                    result.AddRange(codeResult);
                }
            }
            catch (CodeParserException e)
            {
                // Report parsing errors as an error message
                result = new CodeResult(DuetAPI.MessageType.Error, e.Message);
            }
            catch (OperationCanceledException)
            {
                // Report this code as cancelled
                result.Add(DuetAPI.MessageType.Error, "Code has been cancelled");
            }

            return(result.ToString());
        }
示例#27
0
        /// <summary>
        /// React to an executed T-code before its result is returend
        /// </summary>
        /// <param name="code">Code processed by RepRapFirmware</param>
        /// <param name="result">Result that it generated</param>
        /// <returns>Result to output</returns>
        public static async Task <CodeResult> CodeExecuted(Code code, CodeResult result)
        {
            if (!code.MajorNumber.HasValue || !result.IsSuccessful)
            {
                return(result);
            }

            // Set new tool number
            using (await Model.Provider.AccessReadWriteAsync())
            {
                if (Model.Provider.Get.Tools.Any(tool => tool.Number == code.MajorNumber))
                {
                    // Make sure the chosen tool actually exists
                    Model.Provider.Get.State.CurrentTool = code.MajorNumber.Value;
                }
                else
                {
                    // Deselect the current tool if it does not exist
                    Model.Provider.Get.State.CurrentTool = -1;
                }
            }

            return(result);
        }
示例#28
0
        private static async Task RunPrint()
        {
            BaseFile file = _file;

            // Process the job file
            Queue <Code> codes = new Queue <Code>();
            Queue <Task <CodeResult> > codeTasks = new Queue <Task <CodeResult> >();

            do
            {
                // Has the file been paused? If so, rewind to the pause position
                bool paused = false;
                using (await _lock.LockAsync())
                {
                    if (!file.IsFinished && IsPaused)
                    {
                        file.Position = _pausePosition;
                        paused        = true;
                    }
                }

                // Wait for print to resume
                if (paused)
                {
                    codes.Clear();
                    codeTasks.Clear();

                    await _resumeEvent.WaitAsync(Program.CancelSource.Token);
                }

                // Fill up the code buffer
                Code code;
                while (codeTasks.Count == 0 || codeTasks.Count < Settings.BufferedPrintCodes)
                {
                    code = file.ReadCode();
                    if (code == null)
                    {
                        break;
                    }

                    // The trick here is that Code.Enqueue runs synchronously and returns a
                    // task instance that completes when a code result is available...
                    codes.Enqueue(code);
                    codeTasks.Enqueue(code.Enqueue());
                }

                // Is there anything to do?
                if (codes.TryDequeue(out code))
                {
                    // Keep track of the next file position so we know where to resume in case the print is paused while a macro is being performed
                    if (codes.TryPeek(out Code nextCode))
                    {
                        LastFilePosition = nextCode.FilePosition;
                    }
                    else
                    {
                        LastFilePosition = file.Position;
                    }

                    // Process the next code
                    try
                    {
                        CodeResult result = await codeTasks.Dequeue();

                        await Utility.Logger.LogOutput(result);
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine($"[err] {code} -> {e}");
                    }
                }
                else
                {
                    // No more codes available - print must have finished
                    break;
                }
            } while (!Program.CancelSource.IsCancellationRequested);

            Console.WriteLine("[info] DCS has finished printing");

            // Update the last print filename
            using (await Model.Provider.AccessReadWriteAsync())
            {
                Model.Provider.Get.Job.LastFileName = await FilePath.ToVirtualAsync(file.FileName);

                // FIXME: Add support for simulation
            }

            // Notify the controller that the print has stopped
            SPI.Communication.PrintStoppedReason stopReason = !file.IsAborted ? SPI.Communication.PrintStoppedReason.NormalCompletion
                : (IsPaused ? SPI.Communication.PrintStoppedReason.UserCancelled : SPI.Communication.PrintStoppedReason.Abort);
            SPI.Interface.SetPrintStopped(stopReason);

            // Invalidate the file being printed
            _file            = null;
            LastFilePosition = null;
        }
示例#29
0
        /// <summary>
        /// React to an executed G-code before its result is returend
        /// </summary>
        /// <param name="code">Code processed by RepRapFirmware</param>
        /// <param name="result">Result that it generated</param>
        /// <returns>Result to output</returns>
        /// <remarks>This method shall be used only to update values that are time-critical. Others are supposed to be updated via the object model</remarks>
        public static async Task <CodeResult> CodeExecuted(Code code, CodeResult result)
        {
            if (!result.IsSuccessful)
            {
                return(result);
            }

            switch (code.MajorNumber)
            {
            // Rapid/Regular positioning
            case 0:
            case 1:
                CodeParameter feedrate = code.Parameter('F');
                if (feedrate != null)
                {
                    using (await Model.Provider.AccessReadWriteAsync())
                    {
                        if (Model.Provider.Get.Channels[code.Channel].UsingInches)
                        {
                            Model.Provider.Get.Channels[code.Channel].Feedrate = feedrate / 25.4F;
                        }
                        else
                        {
                            Model.Provider.Get.Channels[code.Channel].Feedrate = feedrate;
                        }
                    }
                }
                break;

            // Use inches
            case 20:
                using (await Model.Provider.AccessReadWriteAsync())
                {
                    Model.Provider.Get.Channels[code.Channel].UsingInches = true;
                }
                break;

            // Use millimetres
            case 21:
                using (await Model.Provider.AccessReadWriteAsync())
                {
                    Model.Provider.Get.Channels[code.Channel].UsingInches = false;
                }
                break;

            // Save heightmap
            case 29:
                if (code.Parameter('S', 0) == 0)
                {
                    string file = code.Parameter('P', "heightmap.csv");

                    try
                    {
                        Heightmap map = await SPI.Interface.GetHeightmap();

                        await map.Save(await FilePath.ToPhysicalAsync(file, "sys"));

                        result.Add(DuetAPI.MessageType.Success, $"Height map saved to file {file}");
                    }
                    catch (AggregateException ae)
                    {
                        result.Add(DuetAPI.MessageType.Error, $"Failed to save height map to file {file}: {ae.InnerException.Message}");
                    }
                }
                break;

            // Absolute positioning
            case 90:
                using (await Model.Provider.AccessReadWriteAsync())
                {
                    Model.Provider.Get.Channels[code.Channel].RelativePositioning = false;
                }
                break;

            // Relative positioning
            case 91:
                using (await Model.Provider.AccessReadWriteAsync())
                {
                    Model.Provider.Get.Channels[code.Channel].RelativePositioning = true;
                }
                break;
            }
            return(result);
        }
示例#30
0
        private async Task Process()
        {
            // Attempt to process the code internally first
            if (!InternallyProcessed && await ProcessInternally())
            {
                return;
            }

            // Comments are resolved in DCS
            if (Type == CodeType.Comment)
            {
                Result = new CodeResult();
                return;
            }

            // Send the code to RepRapFirmware
            if (Flags.HasFlag(CodeFlags.Asynchronous))
            {
                // Enqueue the code for execution by RRF and return no result
                Task <CodeResult> codeTask = Interface.ProcessCode(this);
                _ = Task.Run(async() =>
                {
                    try
                    {
                        // Process this code via RRF asynchronously
                        Result = await codeTask;
                        await Model.Provider.Output(Result);
                    }
                    catch (OperationCanceledException)
                    {
                        // Deal with cancelled codes
                        await CodeExecuted();
                        Console.WriteLine($"[info] Cancelled {this}");
                        throw;
                    }
                    catch (Exception e)
                    {
                        // Deal with exeptions of asynchronous codes
                        if (e is AggregateException ae)
                        {
                            e = ae.InnerException;
                        }
                        Console.WriteLine($"[err] Failed to execute {this} asynchronously: {e}");
                    }
                    finally
                    {
                        // Always interpret the result of this code
                        await CodeExecuted();
                        Console.WriteLine($"[info] Completed {this} asynchronously");
                    }
                });

                // Start the next code
                StartNextCode();
            }
            else
            {
                // RepRapFirmware buffers a number of codes so a new code can be started before the last one has finished
                StartNextCode();

                // Wait for the code to complete
                Result = await Interface.ProcessCode(this);
            }
        }