Skip to content

Instantly share code, notes, and snippets.

@foofoodog
Last active August 29, 2015 14:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save foofoodog/590cff62be6cc54f34e1 to your computer and use it in GitHub Desktop.
Save foofoodog/590cff62be6cc54f34e1 to your computer and use it in GitHub Desktop.
Watch a folder for STL files, slice them, then upload the gcode to Octoprint
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
// csc 3dwatch.cs /r:System.Net.Http.dll
// Run this in a directory where there is a slic3r.ini and where STL or gcode files will be created.
namespace _3dwatch
{
class Program
{
static void Main()
{
Func<Processor> processor = () => new Processor();
var actions = new Dictionary<string, Action<string>>()
{
{".stl", (s) => processor().ProcessStl(s)},
{".gcode", (s) => processor().ProcessGcode(s)},
};
Watcher.Create(".", "*.*", actions).Wait();
}
}
public class Watcher
{
private readonly Dictionary<string, Action<string>> _actions;
private readonly FileSystemWatcher _fsw;
public static Task Create(string path, string mask, Dictionary<string, Action<string>> actions)
{
return (new Watcher(path, mask, actions)).Watch();
}
private Watcher(string path, string mask, Dictionary<string, Action<string>> actions)
{
_actions = actions;
_fsw = new FileSystemWatcher(path, mask)
{
EnableRaisingEvents = true,
InternalBufferSize = int.Parse(ConfigurationManager.AppSettings["FileSystemWatcher.InternalBufferSize"]),
};
_fsw.Created += fsw_Created;
}
private Task Watch()
{
return new Task(() => { while (true) _fsw.WaitForChanged(WatcherChangeTypes.Created); });
}
private void fsw_Created(object sender, FileSystemEventArgs e)
{
var action = _actions.FirstOrDefault(x => x.Key == Path.GetExtension(e.Name.ToLower()));
if (action.Key != null) action.Value(e.Name);
}
}
public class Processor
{
private const string CommandTemplate = "\"{0}\" --load {1}";
private static readonly Func<string, string> Config = (key) => ConfigurationManager.AppSettings[key];
public void ProcessStl(string name)
{
Console.WriteLine(name);
var arguments = string.Format(CommandTemplate, name, Config("slic3r.ini"));
var psi = new ProcessStartInfo(Config("slic3r.exe"), arguments)
{
RedirectStandardError = true,
RedirectStandardOutput = true,
UseShellExecute = false
};
try
{
var p = Process.Start(psi);
if (p != null) p.WaitForExit();
if (p.ExitCode != 0) Console.Write("slic3r: " + p.StandardError.ReadToEnd());
}
catch (Exception ex)
{
Console.WriteLine("slic3r choked processing {0}: {1}", name, ex.Message);
}
}
public async void ProcessGcode(string name)
{
var httpClient = new HttpClient();
var key = Config("octoprint.apikey");
if (!string.IsNullOrWhiteSpace(key)) httpClient.DefaultRequestHeaders.Add("X-Api-Key", key);
var form = new MultipartFormDataContent
{
{new StringContent(Config("octoprint.select")), "select"},
{new StringContent(Config("octoprint.print")), "print"},
};
// Devel branch has gotten finicky about content types.
foreach ( var content in form)
{
content.Headers.Remove("Content-Type");
}
var file = new ByteArrayContent(File.ReadAllBytes(name));
file.Headers.Add("Content-Type", "application/octet-stream");
form.Add(file, "file", name);
var response = await httpClient.PostAsync(Config("octoprint.address") + "files/" + Config("octoprint.location"), form);
Console.WriteLine(name + ":" + response.StatusCode);
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<appSettings>
<add key="slic3r.exe" value="c:\temp\slic3r-mswin-x64-1-1-7-stable\Slic3r\slic3r.exe"/>
<add key="slic3r.ini" value=".\slic3r.ini"/>
<add key="octoprint.apikey" value="2F91AC719336489CB8202B85B0118D08"/>
<add key="octoprint.address" value="http://simple/api/"/>
<add key="octoprint.select" value="false"/>
<add key="octoprint.print" value="false"/>
<add key="octoprint.location" value="local"/>
<add key="FileSystemWatcher.InternalBufferSize" value="8000000" />
</appSettings>
</configuration>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment