EclipseCon 2013

Merging technologies to bring 3D printing status to the web

Justin Ribeiro
justin@stickmanventures.com


@justinribeiro +Justin Ribeiro justinribeiro

Slides: http://goo.gl/LMVBf

What's with the fancy numbers?

That's real time 3D printer status action.

Also available publicly: http://goo.gl/zQQrK

Those look like zero's to me.

Well, they'd be fancy numbers if the Intertubes were working.

Or the printer hadn't caught on fire. Who can tell which.

Let's all imagine numbers.

Pssft, everything talks to the Internet

  • In a perfect Internet Of Things (IOT) world, yes
  • But alas, with our 3D printers in question, no.
It's not getting an IP address

Let the integration challenge begin!

The goal is simple: real time printer status on the web.

This should be easy. Right?

What do we need

  • We need a messaging protocol + platform.
  • We need it to listen to many clients.
  • We need it to not kill the bot.
  • Has to work on mobile.

The messaging protocol: MQTT

Message Queuing Telemetry Transport, oh how we love you.

  • Extremely lightweight protocol
  • Works on limited processing power
  • Small code footprint
  • Lots and lots of implementations
    • Libs: C, Java, C#, PHP, Perl, Lua, Python, Arduino client ...
    • Brokers: Mosquitto, WebSphere MQ, RabbitMQ, Cosm ...

The broker: Mosquitto

More info on Mosquitto

  • Open source, v3.1 broker
  • SSL / TLS support
  • Pick a platform you like
    • Windows, Linux, Mac, Raspberry Pi, OpenWRT ...
  • Just want to test?

Hardware + Firmware = painful

  • Not all 3D printers are open source
  • Even with extra IO pins, firmware is tight and often overtasked
Alli fixing her robot

The next best thing: ReplicatorG

More info on ReplicatorG

  • Open source, written in Java
  • Works with a number of printers
  • We can use Eclipse Paho Java implementation to bring MQTT support
  • Add some Google GSON for good measure

Wiring up Paho is straightforward

No surprises, just works.


public class MqttCommunications implements MqttCallback {
	
	...

		public MqttCommunications() { ... }
	public void publish(String data, String sub) { ... }
	public void subscribe(String topic) { ... }
	public void connectionLost(Throwable cause) { ... }
	public void deliveryComplete(MqttDeliveryToken token) { ... }
	public void messageArrived(MqttTopic topic, MqttMessage message) throws Exception { ... }
	
	...
}					
					

Use Swing to implement our menu

Nothing fancy, just the facts ma'am.

But...where's the hook?

  • Transversing RepG takes patience
  • Work with what is there
  • Temper that message sending rate

public void updateBuildStatus(MachineProgressEvent event) {
	if (isBuilding) {
		...
		// JDR: Not ideal, work with what we've got 
		// otherwise things go south FAST
		if (!elapsed.equals(prepc)) {
		    String message = new BuildStatus(getLines, totallines, percentComplete, elapsed, remainingtime).toJson();
		    Base.broker.publish(message, "/build");
		    prepc = elapsed;
		}	
		...
	}
}			

Result: messages get to the broker

Whoo hooo, we're cooking now

Mosquitto_sub in action, showing messages from printer

The websocket server: pywebsocket

  • Can run standalone or as Apache extension module
  • Using python allows us to use Mosquitto's excellent Python MQTT lib
  • RepG implementation doesn't just publish, also listens

 def requestMachineInfo(self):
        # Hey...3D printer....tell me who you are
        self.client.publish(_TOPIC_BASE + "/get", "info", 1)
					

Like Paho, pywebsocket + Mosquitto python lib easy to wire

Don't forget the heartbeat


# client is still alive
if line == _HEARTBEAT:
	continue
	

Don't forget the clientid


self.clientid = ''.join(random.choice(string.ascii_letters + string.digits) for letter in xrange(23))

Dumping all that data onto the web

  • Web Socket support into today's browsers pretty solid
web socket support via CanIUse.com Source: CanIUse.com

I need more support!

Use Modernizr to test for support, load fallback as needed.


    	// Fallback in case client doesn't have web socket
    	if (!Modernizr.websockets) {
    		WEB_SOCKET_SWF_LOCATION = "/swf/WebSocketMain.swf";
    	}

Full list of cross browser polyfills

Firing up the web frontend

Web Socket + JavaScript + DOM = profit

Wiring up the JavaScript is straightforward


Mqtt.prototype = {
    connect: function(){
		var self = this;
        this.ws = new WebSocket(this.url);
       
        this.ws.onopen = function(event){
        	self.onOpen(event);
        };
        
        this.ws.onclose =  function(event){
        	self.onClose(event);
        };
        
        this.ws.onmessage =  function(event){
        	self.onMessage(event);
        };
        
        this.ws.onerror =  function(event){
        	self.onError(event);
        };
    }
    
    ...

DOM updates require finesse

If you hammer the DOM with updates, you could make it angry

Using Node.textContent doesn't trigger a reflow


domUpdateBuild: function(obj) {
	...
		document.getElementById("build-percentagecomplete").textContent = message.complete;
		document.getElementById("build-elapsed").textContent = message.elapsed;
		document.getElementById("build-remaining").textContent = message.remaining;
		document.getElementById("build-completelines").textContent = message.completelines;
		document.getElementById("build-totallines").textContent = message.totallines;
}

The pieces in place... Success!

All the numbers match, it's a good day

Let me have that code!

All my repo's are on GitHub

Leave me some feedback!

  1. Sign In: www.eclipsecon.org
  2. Select this session to evaluate
  3. Vote!

Rate me!

Don't like numbers?

Yell at me on one of those social networks.

Questions? Comments?

Justin you're crazy. Justin I don't understand. Justin something something.


Thank you!