├── .gitattributes
├── .gitignore
├── .travis.yml
├── Examples
├── Examples.csproj
└── Program.cs
├── GCodeNet.sln
├── GCodeNet
├── Base
│ ├── CRC.cs
│ ├── Command.cs
│ ├── CommandAttribute.cs
│ ├── CommandBase.cs
│ ├── CommandMapping.cs
│ ├── CommandType.cs
│ ├── GCodeTokenizer.cs
│ ├── ParameterType.cs
│ └── ParameterTypeAttribute.cs
├── CommandCollection.cs
├── Commands
│ ├── G
│ │ ├── ControlledArcMoveClockwise.cs
│ │ ├── ControlledArcMoveCounterClockwise.cs
│ │ ├── Dwell.cs
│ │ ├── LinearMove.cs
│ │ ├── MoveToOrigin.cs
│ │ ├── RapidLinearMove.cs
│ │ ├── SetAbsolutePositioning.cs
│ │ ├── SetPosition.cs
│ │ ├── SetRelativePositioning.cs
│ │ ├── SetUnitsToInches.cs
│ │ └── SetUnitsToMillimeters.cs
│ └── M
│ │ ├── DisplayMessage.cs
│ │ ├── FanOff.cs
│ │ ├── FanOn.cs
│ │ ├── SetExtruderTemperature.cs
│ │ ├── SetExtruderTemperatureAndWait.cs
│ │ ├── SetExtruderToAbsolute.cs
│ │ └── StopIdleHold.cs
├── ExportFileOptions.cs
├── GCodeFile.cs
├── GCodeFileLine.cs
├── GCodeFileOptions.cs
├── GCodeNet.csproj
└── Reflection
│ ├── CommandReflection.cs
│ └── CommandReflectionData.cs
├── README.md
└── UnitTests
├── BoolType.cs
├── ByteType.cs
├── CommandTest.cs
├── DecimalType.cs
├── DoubleType.cs
├── EnumType.cs
├── GCodeFileTest.cs
├── IntType.cs
├── M117.cs
├── MappedCommand.cs
└── UnitTests.csproj
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
4 | # Custom for Visual Studio
5 | *.cs diff=csharp
6 |
7 | # Standard to msysgit
8 | *.doc diff=astextplain
9 | *.DOC diff=astextplain
10 | *.docx diff=astextplain
11 | *.DOCX diff=astextplain
12 | *.dot diff=astextplain
13 | *.DOT diff=astextplain
14 | *.pdf diff=astextplain
15 | *.PDF diff=astextplain
16 | *.rtf diff=astextplain
17 | *.RTF diff=astextplain
18 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.userosscache
8 | *.sln.docstates
9 |
10 | # User-specific files (MonoDevelop/Xamarin Studio)
11 | *.userprefs
12 |
13 | # Build results
14 | [Dd]ebug/
15 | [Dd]ebugPublic/
16 | [Rr]elease/
17 | [Rr]eleases/
18 | x64/
19 | x86/
20 | bld/
21 | [Bb]in/
22 | [Oo]bj/
23 | [Ll]og/
24 |
25 | # Visual Studio 2015 cache/options directory
26 | .vs/
27 | # Uncomment if you have tasks that create the project's static files in wwwroot
28 | #wwwroot/
29 |
30 | # MSTest test Results
31 | [Tt]est[Rr]esult*/
32 | [Bb]uild[Ll]og.*
33 |
34 | # NUNIT
35 | *.VisualState.xml
36 | TestResult.xml
37 |
38 | # Build Results of an ATL Project
39 | [Dd]ebugPS/
40 | [Rr]eleasePS/
41 | dlldata.c
42 |
43 | # DNX
44 | project.lock.json
45 | project.fragment.lock.json
46 | artifacts/
47 |
48 | *_i.c
49 | *_p.c
50 | *_i.h
51 | *.ilk
52 | *.meta
53 | *.obj
54 | *.pch
55 | *.pdb
56 | *.pgc
57 | *.pgd
58 | *.rsp
59 | *.sbr
60 | *.tlb
61 | *.tli
62 | *.tlh
63 | *.tmp
64 | *.tmp_proj
65 | *.log
66 | *.vspscc
67 | *.vssscc
68 | .builds
69 | *.pidb
70 | *.svclog
71 | *.scc
72 |
73 | # Chutzpah Test files
74 | _Chutzpah*
75 |
76 | # Visual C++ cache files
77 | ipch/
78 | *.aps
79 | *.ncb
80 | *.opendb
81 | *.opensdf
82 | *.sdf
83 | *.cachefile
84 | *.VC.db
85 | *.VC.VC.opendb
86 |
87 | # Visual Studio profiler
88 | *.psess
89 | *.vsp
90 | *.vspx
91 | *.sap
92 |
93 | # TFS 2012 Local Workspace
94 | $tf/
95 |
96 | # Guidance Automation Toolkit
97 | *.gpState
98 |
99 | # ReSharper is a .NET coding add-in
100 | _ReSharper*/
101 | *.[Rr]e[Ss]harper
102 | *.DotSettings.user
103 |
104 | # JustCode is a .NET coding add-in
105 | .JustCode
106 |
107 | # TeamCity is a build add-in
108 | _TeamCity*
109 |
110 | # DotCover is a Code Coverage Tool
111 | *.dotCover
112 |
113 | # NCrunch
114 | _NCrunch_*
115 | .*crunch*.local.xml
116 | nCrunchTemp_*
117 |
118 | # MightyMoose
119 | *.mm.*
120 | AutoTest.Net/
121 |
122 | # Web workbench (sass)
123 | .sass-cache/
124 |
125 | # Installshield output folder
126 | [Ee]xpress/
127 |
128 | # DocProject is a documentation generator add-in
129 | DocProject/buildhelp/
130 | DocProject/Help/*.HxT
131 | DocProject/Help/*.HxC
132 | DocProject/Help/*.hhc
133 | DocProject/Help/*.hhk
134 | DocProject/Help/*.hhp
135 | DocProject/Help/Html2
136 | DocProject/Help/html
137 |
138 | # Click-Once directory
139 | publish/
140 |
141 | # Publish Web Output
142 | *.[Pp]ublish.xml
143 | *.azurePubxml
144 | # TODO: Comment the next line if you want to checkin your web deploy settings
145 | # but database connection strings (with potential passwords) will be unencrypted
146 | *.pubxml
147 | *.publishproj
148 |
149 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
150 | # checkin your Azure Web App publish settings, but sensitive information contained
151 | # in these scripts will be unencrypted
152 | PublishScripts/
153 |
154 | # NuGet Packages
155 | *.nupkg
156 | # The packages folder can be ignored because of Package Restore
157 | **/packages/*
158 | # except build/, which is used as an MSBuild target.
159 | !**/packages/build/
160 | # Uncomment if necessary however generally it will be regenerated when needed
161 | #!**/packages/repositories.config
162 | # NuGet v3's project.json files produces more ignoreable files
163 | *.nuget.props
164 | *.nuget.targets
165 |
166 | # Microsoft Azure Build Output
167 | csx/
168 | *.build.csdef
169 |
170 | # Microsoft Azure Emulator
171 | ecf/
172 | rcf/
173 |
174 | # Windows Store app package directories and files
175 | AppPackages/
176 | BundleArtifacts/
177 | Package.StoreAssociation.xml
178 | _pkginfo.txt
179 |
180 | # Visual Studio cache files
181 | # files ending in .cache can be ignored
182 | *.[Cc]ache
183 | # but keep track of directories ending in .cache
184 | !*.[Cc]ache/
185 |
186 | # Others
187 | ClientBin/
188 | ~$*
189 | *~
190 | *.dbmdl
191 | *.dbproj.schemaview
192 | *.pfx
193 | *.publishsettings
194 | node_modules/
195 | orleans.codegen.cs
196 |
197 | # Since there are multiple workflows, uncomment next line to ignore bower_components
198 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
199 | #bower_components/
200 |
201 | # RIA/Silverlight projects
202 | Generated_Code/
203 |
204 | # Backup & report files from converting an old project file
205 | # to a newer Visual Studio version. Backup files are not needed,
206 | # because we have git ;-)
207 | _UpgradeReport_Files/
208 | Backup*/
209 | UpgradeLog*.XML
210 | UpgradeLog*.htm
211 |
212 | # SQL Server files
213 | *.mdf
214 | *.ldf
215 |
216 | # Business Intelligence projects
217 | *.rdl.data
218 | *.bim.layout
219 | *.bim_*.settings
220 |
221 | # Microsoft Fakes
222 | FakesAssemblies/
223 |
224 | # GhostDoc plugin setting file
225 | *.GhostDoc.xml
226 |
227 | # Node.js Tools for Visual Studio
228 | .ntvs_analysis.dat
229 |
230 | # Visual Studio 6 build log
231 | *.plg
232 |
233 | # Visual Studio 6 workspace options file
234 | *.opt
235 |
236 | # Visual Studio LightSwitch build output
237 | **/*.HTMLClient/GeneratedArtifacts
238 | **/*.DesktopClient/GeneratedArtifacts
239 | **/*.DesktopClient/ModelManifest.xml
240 | **/*.Server/GeneratedArtifacts
241 | **/*.Server/ModelManifest.xml
242 | _Pvt_Extensions
243 |
244 | # Paket dependency manager
245 | .paket/paket.exe
246 | paket-files/
247 |
248 | # FAKE - F# Make
249 | .fake/
250 |
251 | # JetBrains Rider
252 | .idea/
253 | *.sln.iml
254 |
255 | # CodeRush
256 | .cr/
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: csharp
2 | solution: GCodeNet.sln
3 | install:
4 | - nuget restore GCodeNet.sln
5 | - nuget install NUnit.Console -Version 3.5.0 -OutputDirectory testrunner
6 | script:
7 | - xbuild /p:Configuration=Release GCodeNet.sln
8 | - mono ./testrunner/NUnit.ConsoleRunner.3.5.0/tools/nunit3-console.exe ./UnitTests/bin/Release/TestProject.dll
--------------------------------------------------------------------------------
/Examples/Examples.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | netcoreapp2.1
4 | Exe
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Examples/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using GCodeNet;
3 | using GCodeNet.Commands;
4 |
5 | namespace Examples
6 | {
7 | class Program
8 | {
9 | static void Main(string[] args)
10 | {
11 | CreateGCodeCommand();
12 | CreateCommandFromGCode();
13 | GCodeFromMappedCommand();
14 | MappedCommandFromGCode();
15 |
16 | Console.ReadLine();
17 | }
18 |
19 | static void CreateGCodeCommand()
20 | {
21 | //Create a G1 command (Rapid Linear Movement)
22 | var cmd = new Command(CommandType.G, 1);
23 | cmd.SetParameterValue(ParameterType.X, 10);
24 | cmd.SetParameterValue(ParameterType.Y, 20);
25 |
26 | //Convert to GCode
27 | Console.WriteLine(cmd.ToGCode()); //Output: "G1 X10 Y20"
28 |
29 | //Convert to GCode with the CRC
30 | Console.WriteLine(cmd.ToGCode(addCrc: true)); //Output: "G1 X10 Y20*116"
31 |
32 | //Convert to GCode with the CRC and a line number
33 | Console.WriteLine(cmd.ToGCode(addCrc: true, lineNumber: 4)); //Output: "N4 G1 X10 Y20*46"
34 | }
35 |
36 | static void CreateCommandFromGCode()
37 | {
38 | var cmd = Command.Parse("G1 X10 Y20");
39 |
40 | Console.WriteLine(cmd.CommandType); //Output: "G"
41 | Console.WriteLine(cmd.CommandSubType); //Output: "1"
42 | Console.WriteLine(cmd.GetParameterValue(ParameterType.X)); //Output: "10"
43 | Console.WriteLine(cmd.GetParameterValue(ParameterType.Y)); //Output: "20"
44 | }
45 |
46 | static void GCodeFromMappedCommand()
47 | {
48 | var cmd = new RapidLinearMove();
49 | cmd.MoveX = 10;
50 | cmd.MoveY = 20;
51 |
52 | Console.WriteLine(cmd.CommandType); //Output: "G"
53 | Console.WriteLine(cmd.CommandSubType); //Output: "1"
54 | Console.WriteLine(cmd.GetParameterValue(ParameterType.X)); //Output: "10"
55 | Console.WriteLine(cmd.GetParameterValue(ParameterType.Y)); //Output: "20"
56 |
57 | Console.WriteLine(cmd.ToGCode()); //Output: "G1 X10 Y20 S0"
58 | }
59 |
60 | static void MappedCommandFromGCode()
61 | {
62 | var cmd = CommandMapping.Parse("G1 X10 Y20") as RapidLinearMove;
63 |
64 | Console.WriteLine(cmd.CommandType); //Output: "G"
65 | Console.WriteLine(cmd.CommandSubType); //Output: "1"
66 | Console.WriteLine(cmd.MoveX); //Output: "10"
67 | Console.WriteLine(cmd.MoveY); //Output: "20"
68 | Console.WriteLine(cmd.ToGCode()); //Output: "G1 X10 Y20 S0"
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/GCodeNet.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 14
4 | VisualStudioVersion = 14.0.25420.1
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GCodeNet", "GCodeNet\GCodeNet.csproj", "{12E6988E-D61B-4D15-AE53-6478EA04939F}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTests", "UnitTests\UnitTests.csproj", "{50B99882-A4CE-48B7-BC65-F730824CF5F8}"
9 | EndProject
10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Examples", "Examples\Examples.csproj", "{BE7EB1B0-A70B-43A9-AE03-CC84643C8D15}"
11 | EndProject
12 | Global
13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
14 | Debug|Any CPU = Debug|Any CPU
15 | Release|Any CPU = Release|Any CPU
16 | EndGlobalSection
17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
18 | {12E6988E-D61B-4D15-AE53-6478EA04939F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
19 | {12E6988E-D61B-4D15-AE53-6478EA04939F}.Debug|Any CPU.Build.0 = Debug|Any CPU
20 | {12E6988E-D61B-4D15-AE53-6478EA04939F}.Release|Any CPU.ActiveCfg = Release|Any CPU
21 | {12E6988E-D61B-4D15-AE53-6478EA04939F}.Release|Any CPU.Build.0 = Release|Any CPU
22 | {50B99882-A4CE-48B7-BC65-F730824CF5F8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
23 | {50B99882-A4CE-48B7-BC65-F730824CF5F8}.Debug|Any CPU.Build.0 = Debug|Any CPU
24 | {50B99882-A4CE-48B7-BC65-F730824CF5F8}.Release|Any CPU.ActiveCfg = Release|Any CPU
25 | {50B99882-A4CE-48B7-BC65-F730824CF5F8}.Release|Any CPU.Build.0 = Release|Any CPU
26 | {BE7EB1B0-A70B-43A9-AE03-CC84643C8D15}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
27 | {BE7EB1B0-A70B-43A9-AE03-CC84643C8D15}.Debug|Any CPU.Build.0 = Debug|Any CPU
28 | {BE7EB1B0-A70B-43A9-AE03-CC84643C8D15}.Release|Any CPU.ActiveCfg = Release|Any CPU
29 | {BE7EB1B0-A70B-43A9-AE03-CC84643C8D15}.Release|Any CPU.Build.0 = Release|Any CPU
30 | EndGlobalSection
31 | GlobalSection(SolutionProperties) = preSolution
32 | HideSolutionNode = FALSE
33 | EndGlobalSection
34 | EndGlobal
35 |
--------------------------------------------------------------------------------
/GCodeNet/Base/CRC.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 |
6 | namespace GCodeNet
7 | {
8 | public static class CRC
9 | {
10 | public static byte Calculate(string line)
11 | {
12 | var bytes = Encoding.UTF8.GetBytes(line);
13 | int cs = 0;
14 | for (int i = 0; i < bytes.Length; i++)
15 | {
16 | cs = cs ^ bytes[i];
17 | }
18 | cs = cs & 0xff;
19 | return (byte)cs;
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/GCodeNet/Base/Command.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 |
6 | namespace GCodeNet
7 | {
8 | public class Command : CommandBase
9 | {
10 | Dictionary parameters = new Dictionary();
11 |
12 | private Command() { }
13 |
14 | public Command(CommandType type, int subType)
15 | {
16 | this.CommandType = type;
17 | this.CommandSubType = subType;
18 | }
19 |
20 | public override IEnumerable GetParameters()
21 | {
22 | return parameters.Keys.ToArray();
23 | }
24 |
25 | public override object GetParameterValue(ParameterType parameter)
26 | {
27 | if (parameters.ContainsKey(parameter))
28 | {
29 | return parameters[parameter];
30 | }
31 | return null;
32 | }
33 |
34 | public override bool HasParameter(ParameterType parameter)
35 | {
36 | return parameters.ContainsKey(parameter);
37 | }
38 |
39 | public override void RemoveParameter(ParameterType parameter)
40 | {
41 | parameters.Remove(parameter);
42 | }
43 |
44 | public override void SetParameterValue(ParameterType parameter, object value)
45 | {
46 | parameters[parameter] = value;
47 | }
48 |
49 | public static Command Parse(string gcode)
50 | {
51 | var tokenizer = new GCodeTokenizer(gcode);
52 | var commands = tokenizer.GetCommandTokens().ToArray();
53 | if (commands.Length != 1)
54 | {
55 | throw new Exception("gcode may only contain a single command");
56 | }
57 | return FromTokens(commands[0]);
58 | }
59 |
60 | public static Command FromTokens(params string[] tokens)
61 | {
62 | var obj = new Command();
63 | obj.SetTokens(tokens);
64 | return obj;
65 | }
66 |
67 | public override string ToString()
68 | {
69 | return this.ToGCode();
70 | }
71 |
72 | public override void ClearAllParameters()
73 | {
74 | parameters.Clear();
75 | }
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/GCodeNet/Base/CommandAttribute.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace GCodeNet
4 | {
5 | [AttributeUsage(AttributeTargets.Class)]
6 | public class CommandAttribute : Attribute
7 | {
8 | public CommandType CommandType { get; private set; }
9 | public int CommandSubType { get; private set; }
10 |
11 | public CommandAttribute(CommandType commandType, int commandSubType)
12 | {
13 | this.CommandType = commandType;
14 | this.CommandSubType = commandSubType;
15 | }
16 | }
17 | }
--------------------------------------------------------------------------------
/GCodeNet/Base/CommandBase.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Text;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Collections;
6 |
7 | namespace GCodeNet
8 | {
9 | public abstract class CommandBase : IDictionary
10 | {
11 | public CommandType CommandType { get; set; }
12 | public int CommandSubType { get; set; }
13 |
14 | public abstract IEnumerable GetParameters();
15 | public abstract bool HasParameter(ParameterType parameter);
16 | public abstract object GetParameterValue(ParameterType parameter);
17 | public abstract void SetParameterValue(ParameterType parameter, object value);
18 | public abstract void RemoveParameter(ParameterType parameter);
19 | public abstract void ClearAllParameters();
20 |
21 | internal void SetTokens(string[] tokens)
22 | {
23 | this.CommandType = (CommandType)Enum.Parse(typeof(CommandType), tokens[0]);
24 | this.CommandSubType = int.Parse(tokens[1]);
25 |
26 | int i = 2;
27 | while (i < tokens.Length)
28 | {
29 | var paramType = (ParameterType)Enum.Parse(typeof(ParameterType), tokens[i++]);
30 | object value = null;
31 | if (tokens.Length > i && !char.IsLetter(tokens[i][0]))
32 | {
33 | if (tokens[i][0] == '"')
34 | {
35 | value = tokens[i++].Trim('"');
36 | }
37 | else
38 | {
39 | value = decimal.Parse(tokens[i++]);
40 | }
41 | }
42 | this.SetParameterValue(paramType, value);
43 | }
44 | }
45 |
46 | public static CommandBase Parse(string gcode, bool useMappedCommands = true)
47 | {
48 | var tokenizer = new GCodeTokenizer(gcode);
49 | var commands = tokenizer.GetCommandTokens().ToArray();
50 | if (commands.Length != 1)
51 | {
52 | throw new Exception("gcode may only contain a single command");
53 | }
54 | return FromTokens(commands[0], useMappedCommands);
55 | }
56 |
57 | public static CommandBase FromTokens(string[] tokens, bool useMappedCommands = true)
58 | {
59 | if (useMappedCommands)
60 | {
61 | var commandLetter = (CommandType)Enum.Parse(typeof(CommandType), tokens[0]);
62 | int commandNumber = int.Parse(tokens[1]);
63 | var type = CommandReflection.GetCommandObjectType(commandLetter, commandNumber);
64 | if (type != null)
65 | {
66 | return CommandMapping.FromTokens(tokens);
67 | }
68 | }
69 | return Command.FromTokens(tokens);
70 | }
71 |
72 | public virtual string ToGCode(bool addCrc = false, int lineNumber = -1)
73 | {
74 | StringBuilder sb = new StringBuilder();
75 |
76 | if (lineNumber > -1)
77 | {
78 | if (this.CommandType == CommandType.N)
79 | {
80 | throw new Exception("Can't add a line number on a line number command type");
81 | }
82 | sb.Append("N" + lineNumber + " ");
83 | }
84 | sb.Append(this.CommandType);
85 | sb.Append(this.CommandSubType);
86 | foreach (var param in this.GetParameters())
87 | {
88 | sb.Append(" " + param);
89 | var val = this.GetParameterValue(param);
90 | if (val != null)
91 | {
92 | sb.Append(val);
93 | }
94 | }
95 | if (addCrc)
96 | {
97 | sb.Append("*" + CRC.Calculate(sb.ToString()));
98 | }
99 | return sb.ToString();
100 | }
101 |
102 | public ICollection Keys
103 | {
104 | get
105 | {
106 | return (ICollection)GetParameters();
107 | }
108 | }
109 |
110 | public ICollection