Ejemplo n.º 1
0
        public static IEnumerable <DuetAPI.Commands.Code> Parse(string code)
        {
            yield return(new DuetAPI.Commands.Code(code));

            byte[] codeBytes = Encoding.UTF8.GetBytes(code);
            using MemoryStream memoryStream = new MemoryStream(codeBytes);
            using StreamReader reader       = new StreamReader(memoryStream);
            CodeParserBuffer buffer = new CodeParserBuffer(128, true);

            DuetAPI.Commands.Code codeObj = new DuetAPI.Commands.Code();
            DuetAPI.Commands.Code.ParseAsync(reader, codeObj, buffer).Wait();
            yield return(codeObj);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Parse codes from the given input string asynchronously
        /// </summary>
        /// <returns>Parsed G/M/T-codes</returns>
        public async IAsyncEnumerable <Code> ParseAsync()
        {
            using MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(Code));
            using StreamReader reader = new StreamReader(stream);
            CodeParserBuffer buffer = new CodeParserBuffer((int)stream.Length, Code.Contains('\n'));

            while (buffer.GetPosition(reader) < stream.Length)
            {
                Code code = new Code()
                {
                    Channel    = Channel,
                    Connection = Connection
                };

                if (await DuetAPI.Commands.Code.ParseAsync(reader, code, buffer))
                {
                    yield return(code);
                }
            }
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Try to extract thumbnails from a given file
        /// </summary>
        /// <param name="reader">Stream reader to read from</param>
        /// <param name="codeParserBuffer">Read buffer</param>
        /// <param name="parsedFileInfo">File information</param>
        /// <param name="code">Code instance to reuse</param>
        /// <returns>Asynchronous task</returns>
        public static async Task ProcessAsync(StreamReader reader, CodeParserBuffer codeParserBuffer, ParsedFileInfo parsedFileInfo, Code code)
        {
            _logger.Info($"Processing Image {parsedFileInfo.FileName}");
            StringBuilder imageBuffer = new();

            code.Reset();

            //Keep reading the data from the file
            while (codeParserBuffer.GetPosition(reader) < reader.BaseStream.Length)
            {
                Program.CancellationToken.ThrowIfCancellationRequested();
                if (!await DuetAPI.Commands.Code.ParseAsync(reader, code, codeParserBuffer))
                {
                    continue;
                }

                //Icon data goes until the first line of executable code.
                if (code.Type == CodeType.Comment)
                {
                    imageBuffer.Append(code.Comment.Trim());
                    code.Reset();
                }
                else
                {
                    try
                    {
                        ParsedThumbnail thumbnail = ReadImage(imageBuffer.ToString());
                        parsedFileInfo.Thumbnails.Add(thumbnail);
                        _logger.Error("Icon Thumbnails Found");
                    }
                    catch
                    {
                        //throw it away
                    }
                    return;
                }
            }
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Extract thumbnails generated by Prusa Slicer from a file
        /// </summary>
        /// <param name="reader">Stream reader to read from</param>
        /// <param name="codeParserBuffer">Parser buffer</param>
        /// <param name="parsedFileInfo">File information</param>
        /// <param name="code">Code to reuse while parsing</param>
        /// <returns>Asynchronous task</returns>
        public static async Task ProcessAsync(StreamReader reader, CodeParserBuffer codeParserBuffer, ParsedFileInfo parsedFileInfo, Code code)
        {
            StringBuilder encodedImage = new();

            //Read the image header info that is currently in the code
            string[] thumbnailTokens = code.Comment.Trim().Split(' ');

            //Stop processing since the thumbnail may be corrupt.
            if (thumbnailTokens.Length != 4)
            {
                throw new ImageProcessingException();
            }
            string[] dimensions = thumbnailTokens[2].Split('x');
            if (dimensions.Length != 2)
            {
                throw new ImageProcessingException();
            }

            ParsedThumbnail thumbnail = new()
            {
                Width  = int.Parse(dimensions[0]),
                Height = int.Parse(dimensions[1])
            };

            int encodedLength = int.Parse(thumbnailTokens[3]);

            encodedImage.Clear();
            code.Reset();


            //Keep reading the data from the file
            while (codeParserBuffer.GetPosition(reader) < reader.BaseStream.Length)
            {
                Program.CancellationToken.ThrowIfCancellationRequested();
                if (!await Code.ParseAsync(reader, code, codeParserBuffer))
                {
                    continue;
                }



                if (code.Type != CodeType.Comment)
                {
                    return;
                }

                if (string.IsNullOrEmpty(code.Comment))
                {
                    code.Reset();
                    continue;
                }

                if (code.Comment.Contains("thumbnail begin", StringComparison.InvariantCultureIgnoreCase))
                {
                    //Exit if we find another start tag before ending the previous image
                    throw new ImageProcessingException();
                }
                else if (code.Comment.Contains("thumbnail end", StringComparison.InvariantCultureIgnoreCase))
                {
                    if (encodedImage.Length == encodedLength)
                    {
                        thumbnail.EncodedImage = "data:image/png;base64," + encodedImage.ToString();
                        parsedFileInfo.Thumbnails.Add(thumbnail);
                        return;
                    }
                }
                else
                {
                    encodedImage.Append(code.Comment.Trim());
                }
                code.Reset();
            }
        }
    }
Ejemplo n.º 5
0
        public async Task ParseAsync()
        {
            string codeString = "G53 G1 X0 Y5 F3000 G0 X5 Y10";

            byte[] codeBytes = Encoding.UTF8.GetBytes(codeString);
            using (MemoryStream memoryStream = new MemoryStream(codeBytes))
            {
                using StreamReader reader = new StreamReader(memoryStream);
                CodeParserBuffer      buffer = new CodeParserBuffer(128, true);
                DuetAPI.Commands.Code code   = new DuetAPI.Commands.Code()
                {
                    LineNumber = 1
                };

                await DuetAPI.Commands.Code.ParseAsync(reader, code, buffer);

                Assert.AreEqual(CodeType.GCode, code.Type);
                Assert.AreEqual(1, code.MajorNumber);
                Assert.AreEqual(CodeFlags.EnforceAbsolutePosition, code.Flags);
                Assert.AreEqual(1, code.LineNumber);
                Assert.AreEqual(3, code.Parameters.Count);
                Assert.AreEqual(0, (int)code.Parameter('X'));
                Assert.AreEqual(5, (int)code.Parameter('Y'));
                Assert.AreEqual(3000, (int)code.Parameter('F'));

                code.Reset();
                await DuetAPI.Commands.Code.ParseAsync(reader, code, buffer);

                Assert.AreEqual(CodeType.GCode, code.Type);
                Assert.AreEqual(0, code.MajorNumber);
                Assert.AreEqual(CodeFlags.EnforceAbsolutePosition | CodeFlags.IsLastCode, code.Flags);
                Assert.AreEqual(1, code.LineNumber);
                Assert.AreEqual(2, code.Parameters.Count);
                Assert.AreEqual(5, (int)code.Parameter('X'));
                Assert.AreEqual(10, (int)code.Parameter('Y'));
            }

            codeString = "G1 X1 Y5 F3000\nG1 X5 F300\nG0 Y40";
            codeBytes  = Encoding.UTF8.GetBytes(codeString);
            using (MemoryStream memoryStream = new MemoryStream(codeBytes))
            {
                using StreamReader reader = new StreamReader(memoryStream);
                CodeParserBuffer buffer = new CodeParserBuffer(128, true);

                DuetAPI.Commands.Code code = new DuetAPI.Commands.Code()
                {
                    LineNumber = 0
                };
                await DuetAPI.Commands.Code.ParseAsync(reader, code, buffer);

                code.Reset();
                await DuetAPI.Commands.Code.ParseAsync(reader, code, buffer);

                code.Reset();
                await DuetAPI.Commands.Code.ParseAsync(reader, code, buffer);

                Assert.AreEqual(CodeType.GCode, code.Type);
                Assert.AreEqual(0, code.MajorNumber);
                Assert.AreEqual(3, code.LineNumber);
            }

            codeString = "G1 X1 Y5 F3000\n  G53 G1 X5 F300\n    G53 G0 Y40 G1 Z50\n  G4 S3\nG1 Z3";
            codeBytes  = Encoding.UTF8.GetBytes(codeString);
            using (MemoryStream memoryStream = new MemoryStream(codeBytes))
            {
                using StreamReader reader = new StreamReader(memoryStream);
                CodeParserBuffer buffer = new CodeParserBuffer(128, true);

                DuetAPI.Commands.Code code = new DuetAPI.Commands.Code()
                {
                    LineNumber = 0
                };
                await DuetAPI.Commands.Code.ParseAsync(reader, code, buffer);

                Assert.AreEqual(CodeFlags.IsLastCode, code.Flags);
                Assert.AreEqual(0, code.Indent);
                Assert.AreEqual(1, code.LineNumber);

                code.Reset();
                await DuetAPI.Commands.Code.ParseAsync(reader, code, buffer);

                Assert.AreEqual(CodeFlags.EnforceAbsolutePosition | CodeFlags.IsLastCode, code.Flags);
                Assert.AreEqual(2, code.Indent);
                Assert.AreEqual(2, code.LineNumber);

                code.Reset();
                await DuetAPI.Commands.Code.ParseAsync(reader, code, buffer);

                Assert.AreEqual(CodeFlags.EnforceAbsolutePosition, code.Flags);
                Assert.AreEqual(4, code.Indent);
                Assert.AreEqual(3, code.LineNumber);

                code.Reset();
                await DuetAPI.Commands.Code.ParseAsync(reader, code, buffer);

                Assert.AreEqual(CodeFlags.EnforceAbsolutePosition | CodeFlags.IsLastCode, code.Flags);
                Assert.AreEqual(4, code.Indent);
                Assert.AreEqual(3, code.LineNumber);

                code.Reset();
                await DuetAPI.Commands.Code.ParseAsync(reader, code, buffer);

                Assert.AreEqual(CodeFlags.IsLastCode, code.Flags);
                Assert.AreEqual(2, code.Indent);
                Assert.AreEqual(4, code.LineNumber);

                code.Reset();
                await DuetAPI.Commands.Code.ParseAsync(reader, code, buffer);

                Assert.AreEqual(CodeFlags.IsLastCode, code.Flags);
                Assert.AreEqual(0, code.Indent);
                Assert.AreEqual(5, code.LineNumber);
            }

            codeString = "M291 P\"Please go to <a href=\"\"https://www.duet3d.com/StartHere\"\" target=\"\"_blank\"\">this</a> page for further instructions on how to set it up.\" R\"Welcome to your new Duet 3!\" S1 T0";
            codeBytes  = Encoding.UTF8.GetBytes(codeString);
            using (MemoryStream memoryStream = new MemoryStream(codeBytes))
            {
                using StreamReader reader = new StreamReader(memoryStream);
                CodeParserBuffer buffer = new CodeParserBuffer(128, true);

                DuetAPI.Commands.Code code = new DuetAPI.Commands.Code();
                await DuetAPI.Commands.Code.ParseAsync(reader, code, buffer);

                Assert.AreEqual(CodeType.MCode, code.Type);
                Assert.AreEqual(291, code.MajorNumber);
                Assert.AreEqual("Please go to <a href=\"https://www.duet3d.com/StartHere\" target=\"_blank\">this</a> page for further instructions on how to set it up.", (string)code.Parameter('P'));
                Assert.AreEqual("Welcome to your new Duet 3!", (string)code.Parameter('R'));
                Assert.AreEqual(1, (int)code.Parameter('S'));
                Assert.AreEqual(0, (int)code.Parameter('T'));
            }
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Parse the header of a G-code file
        /// </summary>
        /// <param name="reader">Stream reader</param>
        /// <param name="partialFileInfo">G-code file information</param>
        /// <returns>Asynchronous task</returns>
        private static async Task ParseHeader(StreamReader reader, ParsedFileInfo partialFileInfo)
        {
            Code             code             = new Code();
            CodeParserBuffer codeParserBuffer = new CodeParserBuffer(Settings.FileBufferSize, true);

            bool inRelativeMode = false, lastCodeHadInfo = false, gotNewInfo = false;
            long fileReadLimit = Math.Min(Settings.FileInfoReadLimitHeader + Settings.FileBufferSize, reader.BaseStream.Length);

            while (codeParserBuffer.GetPosition(reader) < fileReadLimit)
            {
                Program.CancellationToken.ThrowIfCancellationRequested();
                if (!await DuetAPI.Commands.Code.ParseAsync(reader, code, codeParserBuffer))
                {
                    continue;
                }

                if (code.Type == CodeType.GCode && partialFileInfo.FirstLayerHeight == 0)
                {
                    if (code.MajorNumber == 91)
                    {
                        // G91 code (relative positioning)
                        inRelativeMode = true;
                        gotNewInfo     = true;
                    }
                    else if (inRelativeMode)
                    {
                        // G90 (absolute positioning)
                        inRelativeMode = (code.MajorNumber != 90);
                        gotNewInfo     = true;
                    }
                    else if (code.MajorNumber == 0 || code.MajorNumber == 1)
                    {
                        // G0/G1 is a move, see if there is a Z parameter present
                        CodeParameter zParam = code.Parameter('Z');
                        if (zParam != null)
                        {
                            float z = zParam;
                            if (z <= Settings.MaxLayerHeight)
                            {
                                partialFileInfo.FirstLayerHeight = z;
                                gotNewInfo = true;
                            }
                        }
                    }
                }
                else if (!string.IsNullOrWhiteSpace(code.Comment))
                {
                    gotNewInfo |= (partialFileInfo.LayerHeight == 0) && FindLayerHeight(code.Comment, ref partialFileInfo);
                    gotNewInfo |= FindFilamentUsed(code.Comment, ref partialFileInfo);
                    gotNewInfo |= string.IsNullOrEmpty(partialFileInfo.GeneratedBy) && FindGeneratedBy(code.Comment, ref partialFileInfo);
                    gotNewInfo |= (partialFileInfo.PrintTime == null) && FindPrintTime(code.Comment, ref partialFileInfo);
                    gotNewInfo |= (partialFileInfo.SimulatedTime == null) && FindSimulatedTime(code.Comment, ref partialFileInfo);
                }

                // Is the file info complete?
                if (!gotNewInfo && !lastCodeHadInfo && IsFileInfoComplete(partialFileInfo))
                {
                    break;
                }
                lastCodeHadInfo = gotNewInfo;
                code.Reset();
            }
        }
Ejemplo n.º 7
0
        /// <summary>
        /// Parse the file for thumbnails
        /// </summary>
        /// <param name="reader">Stream reader</param>
        /// <param name="partialFileInfo">G-code file information</param>
        /// <returns>Asynchronous task</returns>
        /// <remarks>
        /// This functionality should be moved to ParseHeader in the long term
        /// </remarks>
        private static async Task ParseThumbnails(StreamReader reader, ParsedFileInfo parsedFileInfo)
        {
            Code             code             = new Code();
            CodeParserBuffer codeParserBuffer = new CodeParserBuffer(Settings.FileBufferSize, true);
            bool             imageFound       = false;
            int           encodedLength       = 0;
            StringBuilder encodedImage        = new StringBuilder();

            reader.BaseStream.Seek(0, SeekOrigin.Begin);
            ParsedThumbnail thumbnail = null;

            while (codeParserBuffer.GetPosition(reader) < reader.BaseStream.Length)
            {
                Program.CancellationToken.ThrowIfCancellationRequested();
                if (!await DuetAPI.Commands.Code.ParseAsync(reader, code, codeParserBuffer))
                {
                    continue;
                }

                if (code.Type != CodeType.Comment)
                {
                    return;
                }

                if (string.IsNullOrEmpty(code.Comment))
                {
                    code.Reset();
                    continue;
                }

                if (code.Comment.Contains("thumbnail begin", StringComparison.InvariantCultureIgnoreCase))
                {
                    //Exit if we find another start tag before ending the previous image
                    if (imageFound)
                    {
                        return;
                    }
                    string[] thumbnailTokens = code.Comment.Trim().Split(' ');
                    //Stop processing since the thumbnail may be corrupt.
                    if (thumbnailTokens.Length != 4)
                    {
                        return;
                    }
                    string[] dimensions = thumbnailTokens[2].Split('x');
                    if (dimensions.Length != 2)
                    {
                        continue;
                    }
                    imageFound = true;

                    thumbnail = new ParsedThumbnail
                    {
                        Width  = int.Parse(dimensions[0]),
                        Height = int.Parse(dimensions[1])
                    };

                    encodedLength = int.Parse(thumbnailTokens[3]);
                    encodedImage.Clear();
                    code.Reset();
                    continue;
                }
                else if (code.Comment.Contains("thumbnail end", StringComparison.InvariantCultureIgnoreCase))
                {
                    if (encodedImage.Length == encodedLength)
                    {
                        thumbnail.EncodedImage = "data:image/png;base64," + encodedImage.ToString();
                        parsedFileInfo.Thumbnails.Add(thumbnail);
                    }
                    thumbnail  = null;
                    imageFound = false;
                }
                else if (imageFound)
                {
                    encodedImage.Append(code.Comment.Trim());
                }
                code.Reset();
            }
        }