Reid Carlberg

Connected Devices, salesforce.com & Other Adventures

Tessel Review & Salesforce REST API Example (with a smidge of OAuth2)

0
T-Rex-Salesforce1

TL;DR – I wrote a script on my new Tessel that posts images to Salesforce Chatter and learned a lot along the way. You can find the full Tessel Image Capture script over on Github and you can ask me about it on Twitter @ReidCarlberg. The screen cap above is an automatically captured picture of a 3D printed T-Rex Skull on Salesforce1.

Hello Tessel

The Tessel is a brand new hardware prototyping board that lets you code in Javascript rather than C. I first ran into it during their crowd funding campaign last year, and received my first unit last week. Since then I’ve had a chance to create my first simple app on the device, so today I’m going to share what I’ve learned so far. Tessel Review, Camera, ClimateTessel Review

If you’re already used to working with hardware prototyping boards, there’s a lot you’re going to like. There are plenty of analog, digital, I2C, SPI and serial ports to go around. You can use these ports to connect any old hardware you already know how to connect, or you can use one of their preconfigured modules. Pretty easy.

One thing that confused me since I first spied the prototype is the positioning of the interface ports. They’re bent at 90 degrees and so rather than facing up, they face out. (Note: in the picture above you can see that my C port is at a weird angle. Bent it somehow.) This design helps a board with a number of modules attached stay flat, which is particularly useful with something like the servo module where you’re going to connect a number of wires in. The GPIO port faces up as you would expect.

Basic interaction is super simple. You access all of the ports via standard Javascript syntax. For example, the blink app (“Hello World”, but for hardware), is just a few lines:

// Import the interface to Tessel hardware
var tessel = require('tessel');

// Set the led pins as outputs with initial states
// Truthy initial state sets the pin high
// Falsy sets it low.
var led1 = tessel.led[1].output(1);
var led2 = tessel.led[1].output(0);

setInterval(function () {
    console.log("I'm blinking! (Press CTRL + C to stop)");
    // Toggle the led states
    led1.toggle();
    led2.toggle();
}, 100);

You can run scripts from the CLI using the command "tessel run myScript.js".  Here's what running the blink.js example looks like.

$ tessel run blink.js
TESSEL! Connected to TM-00-04-f000da30-006a473e-34b02586.
WARN No package.json or node_modules found. Deploying just this file.
INFO Bundling directory /Users/reid.carlberg/Projects/tessel-blink (~428 bytes)
INFO Deploying bundle (4.50 KB)...
INFO Running script...
I'm blinking! (Press CTRL + C to stop)
I'm blinking! (Press CTRL + C to stop)
.....

And if you want the script to run headless, you simply use "tessel push myScript.js" and you're good to go.  The script will start automatically as soon as it has power.

The modules are pretty easy to use, and they all come with node libraries and sample code. When you want to use a module, you simply insert it into one of the ports, grab the library via NPM and get to work. Installing the camera module, for example, is as simple as typing "npm install camera-vc0706". T-Rex-Salesforce1 My Tessel Sample App

My sample use case is pretty simple: when something is close enough to the Tessel, snap a picture and upload it to Salesforce. In this example, I connected my own proximity detector and used Tessel camera and climate modules. tessel-camera-2 The first thing I wanted to do was connect to the Salesforce platform the way I usually do, with the excellent nforce library. Now, I've used it quite a bit, and have watched the npm install routine probably 100 times without really wondering about all of the components it requires. However, I couldn't take that same laissez faire attitude when working on the Tessel. Although it is designed to be Node.js compatible, it's still a limited device and larger, complex modules like nforce are too much for it to handle. This is not that big of a deal. In fact, it was a great excuse for me to get more familiar with some Node.js basics I'd managed to ignore until now, such as the HTTPS request object. Incidentally, before rolling my own OAuth2 and REST interactions, I also attempted to use the excellent request and restler libraries.  No luck!

The good news here is that rolling your own autonomous client / username & password flow OAuth2 is pretty easy. Setup your connected app in Salesforce (example), send a few parameters to the endpoint and voila! you have an authorization token.

function handleOauth() {
  log('handleOauth');
  var body = 'grant_type=password&client_id='+clientid+'&client_secret='+clientsecret+
    '&username='+sfuser+'&password='+sfpass
  var options = buildRequestOptions('/services/oauth2/token', body, 'application/x-www-form-urlencoded');
  options.hostname = 'login.salesforce.com';
  log(options);
  handleHttpsRequest(options, body, handleOauthCallback);
}

You can see I've built a few small routines to make this easier, but the main job is done in four lines of code. Add a callback to interpret the results, and I'm off.

Sending an Image to Chatter

The next step is capturing an image and sending it to Chatter. The good people at Tessel have made taking the picture extremely easy. The basic code looks something like:

var camera = require('camera-vc0706').use(tessel.port['A'], { resolution: 'qvga' }); 
camera.takePicture(function(err, image) {
if (err) {
   log('error taking image', err);
} else {
   //do something with the image
   base64content = image.toString('base64');
}

On the Chatter side of the fence, if you can send an octet-stream directly to the Chatter API, you can use a single call and post a message and the picture at the same time.  In theory, the image buffer should work in here, but I couldn't get it to work on either the Tessel or my MBP.  I ended up taking a note from @Metadaddy and an example from @CCoenraets, and did a 3 step process after base64 encoding the buffer object. Step 1, insert a ContentVersion object. Step 2, lookup the ContentVersion and get the ContentDocumentId. Step 3, insert a FeedItem that references the ContentDocumentId.  The final Chatter code looks like this:

  var body =  {
      attachment: {
          attachmentType: "ExistingContent",
          contentDocumentId: contentVersion.ContentDocumentId
      },
      body: {
          messageSegments: [{
                type: 'Text',
                text: 'Here is a current picture. \nClimate: '  + currentClimateText
              }]
      }
  };
  body = JSON.stringify(body);
  var chatterOptions = buildRequestOptions('/services/data/v30.0/chatter/feeds/record/me/feed-items', body, 'application/json');
  handleHttpsRequest(chatterOptions, body, handleChatterCallback);  

The other option for inserting the picture is to create a custom ApexREST web service. This is a good option if you want to minimize API calls, but it adds the extra complexity of creating that bit of Apex. Fortunately, that bit of Apex is easy to create.  In fact, I had created something similar for the Share Wonder project I did a while back.  Share Wonder, however, inserted the data into an Attachment object rather than a ContentVersion object. Before I wrote the ContentVersion code myself, I search a bit and it turns out that Maxim Fesenko over at Cloud Catamaran had written a blog called File Upload to Chatter Using the ConnectAPI just a few days ago.

My slightly modified version of the code from that blog post looks like this:

/*
 * Totally copied from 
 * http://cloudcatamaran.com/2014/04/file-upload-to-chatter-with-using-connectapi-class/
 */

@RestResource(urlMapping='/TesselImage')
global class PostHelper{
  @HttpPost
    global static ConnectApi.FeedItem post(String text, String imageName, String imageBase64) {
        ConnectApi.MessageBodyInput v_messageInput = new ConnectApi.MessageBodyInput();
        v_messageInput.messageSegments = new List();
         
        ConnectApi.TextSegmentInput v_textSegment = new ConnectApi.TextSegmentInput();
        v_textSegment.text = text;
         
        v_messageInput.messageSegments.add(v_textSegment);
         
        ConnectApi.FeedItemInput v_input = new ConnectApi.FeedItemInput();
        v_input.body = v_messageInput;

        ConnectApi.NewFileAttachmentInput v_fileIn = new ConnectApi.NewFileAttachmentInput();
        v_fileIn.title = 'title of file';
        v_fileIn.description = 'description of file';
         
        v_input.attachment = v_fileIn;
         
        ConnectApi.BinaryInput v_feedBinary = new ConnectApi.BinaryInput(EncodingUtil.base64Decode(imageBase64), 'image/jpg', imageName);
        
        System.debug('***Just about to insert');
        ConnectApi.FeedItem v_feedItem = ConnectApi.ChatterFeeds.postFeedItem(null, ConnectApi.FeedType.Record, 'me', v_input, v_feedBinary);
        System.debug('***Inserted');
        System.debug(v_feedItem);
        
        return v_feedItem;
    }
}

And if you'd like to install it in your org, here's an unmanaged package which yes of course includes full test coverage.

Tessel Lessons Learned

I learned a lot going through this sample app.  Some of my key takeaways.

* Base64 encoding takes quite a while. A qqvga image (160 x 120) encodes in about 20 seconds. A larger qvga (320 x 240) takes about 2 minutes. A vga image (640 x 480) takes more like 20 minutes.

* System intensive actions like base64 encoding will block other actions you have setup on an interval.  Once the encoding is done, all of the blocked actions will fire.

* Yes, the Tessel uses Javascript, but it's still a constrained device. You should expect complex, memory intensive operations to be tricky. Every platform has constraints. The Arduino, for example, doesn't handle JSON parsing well. Just because you can use Javascript on the Tessel, you shouldn't assume you can use Javascript exactly as you might on more powerful platforms.

* The wifi is a bit tricky. Setup is dead easy -- "tessel wifi -n MyNetwork -p MyPassword" -- but the Tessel doesn't have a huge antenna, and reception isn't the greatest. I found areas of my house that work great for a larger device but not for the Tessel. They actually have a tutorial on how to add an antenna.

Finally, I would like to point out that the crew over at Technical Humans have been super responsive and helpful.

In the End...

In the end, I think the Tessel is a super interesting iteration on the hardware prototyping platform. Coding hardware using Javascript - even if it's a little different than other places you use Javascript -  is very interesting. I hope a lot of people buy one of these boards, because I definitely want to see what the future holds for this extremely interesting team.

Internet of Things: Six Requirements for Your First Project

1

The Internet of Things, the Internet of Everything, the Industrial Internet — whatever you call it, connected devices are a fantastic gift to any business that wants to get closer to their customers. The pattern captures people’s imaginations and many of the predictions feel like magic, but IoT solutions are hard to get right. If you’re trying to decide on your first project, you probably have a lot of questions. Here are six critical things to keep in mind as you move forward.

#1 Pick a Great Use Case

There are a lot of fun IoT use cases around the Internet. Many of them don’t matter. In the interest of keeping good relations with the rest of the world, I’m going to call out something I did as a fantastic example of a trivial exercise: the Coffee Copter, detailed in the video below. As you pour a cup of coffee, a quadcopter takes off. As you empty the cup, the quadcopter lands.

Now, as fun as that was, it was an execise in can you do something, and these days can is the wrong question. You need to be asking yourself should questions. Should I connect a coffee urn and a quadcopter? No.

But there are lot of areas where the answer is yes.

Should you make healthcare equipment more reliable? Should you make it easier to monitor radiation in a nuclear accident zone? Should you help people save money on energy by helping them monitor and manage their use?

The answer to all of these is a clear yes.

One of my favorite examples in this department is New England BioLabs. NEB sells supplies to medical researchers. As part of their sales process, they stock these supplies in a freezer at their customer’s location. Now, it used to be that they had a hard time knowing the right supplies to stock, validating that supplies were kept at the right temperature, and tracking the researchers that used a specific item. NEB solved this by transforming their freezers into connected devices and now they know the researchers, they know the supplies and they know the temperature history for each item.

I’m sure we can all agree that medical research is a worthy cause. But not everyone is a healthcare researcher, so you have to find a similar problem in your business. You need to start by identifying the target outcomes your customers are looking for, and then come up with ways to help them achieve those outcomes more reliably. When you do this, you deliver additional value and build better relationships.

These outcome oriented use cases are what matter, and you should start with them.

#2 Create a Great User Experience

Once you decide on the right use case, you have to create a user experience that delights your customers.

Internet of things demands great User Experience

(source & thanks @RossBelmont).

User experience, UX, determines how people engage with your solution, and there’s no one UX for every product. Your UX goal should be two fold. First, if possible, your new solution should fit into what customers already know how to do. Second, it should reduce the friction of what they have to do to realize the value it delivers. Great UX not only disappears into the environment, it makes the environment better.

Carlberg-Reid-Salesforce-Practical-IoT-Now_pptx

The current generation of fitness wearables is interesting example of good UX. Fitbit, for example, has no buttons. All you have to do is put it on and the technology does everything else in the background. Now, on the down side, the user also has to tap the device from time to time. It’s easy to get the hang of, but I wouldn’t call it natural, and it still requires a local gateway rather than being able to magically talk directly to the cloud. There’s no great way around that right now, it’s a constraint that the technology hasn’t eliminated yet. But the first wearable that includes some sort of background connectivity will have a tremendous advantage.

#3 Community & Collaboration

I’m not talking about the network of connected toasters or refrigerators complaining to each other about being out of milk. I’m talking about actual people. People value interacting with other people in context of things they care about. In fact, they value it so much, if you don’t create a destination for the community that pops up around your product, your customers will probably create one on their own.

There are three main types of communities to be thinking about.

photo-8The first is a data-centric community. Runkeeper has created an excellent example of a data-centric community. Data-centric communities take the output of the device and interact around it. In Runkeeper’s case, this is a leader board comparing the number of activities between you and your friends (yes, that’s me at the bottom). Most fitness wearables have data-centric communities as a core part of the product.

The second type of community is product-centric. Product-centric communities are more about how to use things, news from the company, tips and tricks, etc. PrintrBot has an excellent product-centric community. Interestingly, it’s not operated by the company itself. Customers created their own informal community. Today the company has an official one as well, but the original continues to thrive.

Philips_Puts_Customers_at_the_Center_of_Their_Company_-_YouTube

The third type is transaction-centric. Say you manufacture MRI machines, and you connect those MRI machines to an enterprise backend like salesforce.com. When the MRI machines have actionable data, that data gets posted to Chatter, and all of the people who have a legitimate interest in it can collaborate around that particular post. MRI techs, doctors, hospital staff, biomed technicians, and external contractors can create a short lived, ad hoc community around that transaction.  (The screenshot above is from this video, a couple of minutes in.)

#4 Developer Experience

Open Source has shown time and again that remix is often more valuable than the original. And although I won’t presume to say you should open source your core IP behind whatever connected solution you land on, I think its critical you have an easy to understand, well documented and powerful API that developers can harness.

Automatic__An_Auto_Accessory_to_Make_You_a_Smarter_Driver

A great example of a good out of the box Developer Experience (DX) is Automatic, the car tracking company. With Automatic, you pair an OBD-II device with your phone and track driving patterns. Automatic launched with an API out of the box, and they exposed their API using a number of standards. For example, it has a REST API and handles authentication via OAuth2. This definitely sets them up for developer success, and people are doing great things.  (Note that Automatic’s API is still in beta.  That’s fine.)

Like the community, the funny thing is that if you don’t deliver an API out of the box, chances are good someone else will attempt to. Take the example of Kickstarter success LiFX. It took a year for them create and ship bulbs to their backers, and they did so without an official API. However, an unofficial API showed up on Github in days. Now the challenge here is that an unofficial one is OK, but people don’t have a lot of confidence in it. Meanwhile the Philips Hue, their competitor, has had a reasonably good API for quite a while.

This all begs the question of Nest.  Nest doesn’t have a public API yet which probably makes you wonder if you really need one.  My opinion is that most of the time yes you will need one.  Nest has proven to be a successful exception.  There may be more exceptions, but I suspect not many.

#5 The Right Amount of Data

In order to succeed, your IoT solution needs to gather enough data to create accurate, actionable insights for your users. Is this Big Data? Yes, but your users don’t want and can’t handle big data. They want the processed results.

How do you handle big data if you don’t already understand it? The right thing to do is partner with a company who already has the expertise, of which there are an increasing number. Companies like Etherios, 2lementry and Axeda, just to name a few. Can you develop it yourself? Sure, but see the above discussion about can versus should.

Processed data is where the action is. A typical IoT value chain has a number of components, all of which are easy to get lost in, but processed data, that someone can act on, will drive the success or failure of your product. User experience plays a critical role here as well, although it’s a different set of users: internal users. If your use case involves helping customers achieve better outcomes from their purchase, and it should, then the processed data needs to sit very close to the customer data so people can take quick action on it.

Learning what data is valuable will take some trial and error, and the data that’s valuable today will be different that the data which matters tomorrow.  You need to figure this out for your customers.

#6 Non-Technical Integration

Connected devices open up new and interesting future possibilities, but they have to play well in the current world with all of it’s existing requirements. A good case in point is government regulation.

Brivo Labs is a great example of a company that understands the impact of regulatory requirements on IoT solutions. Brivo Labs is an access management company that’s a spin off of a well established commercial security access control company with a deep understanding of regional building codes. This kind of knowledge is absolutely key to working effectively with existing markets, and they’ve used this to create a number of interesting products, including an iBeacon enabled app that works with Salesforce Identity called Rändivoo.

Nest experienced an interesting result of regulatory requirements when they found a problem with their smoke detectors. They started to fix it and then received a demand for a recall from the Consumer Product Safety Commission - six weeks after their own disclosure and initial action. This kind of interaction can be very distracting for a business, especially when it’s not planned for, but the reality is that even the most leading edge companies are still subject to it.

Recalled_Nest_Protect_Smoke_Alarm_Will_Return_To_Sale_In_Weeks___TechCrunch

Source. Note that as of this writing, Nest Protects were not available on the Nest website.  This letter from Nest CEO describes the situation.

Now is the Time to Jump In!

I hope this list is helpful.  The Internet of Things is an architectural style that will drive really interesting innovation in the coming years.  There’s a lot of detail around creating an IoT solution, but you shouldn’t let that stop you from jumping in. Now is a great time.  Companies are increasingly turning to connected customer experiences as a way of delivering what all customers really want: better outcomes.

If you’re looking for more ideas and inspiration, you should take a look at the ever growing list of artifacts created by some of the leading thinkers in the space.  I recommend the videos from ThingMonk, ThingsCon and SolidCon as a great place to start.

I’d love your feedback on this or any other article.

Code Coverage, 3D Printers vs. Quadcopters & Apex4Admins

0

The excellent Code Coverage podcast features me today.  I was really honored when Matt and Steven invited me and am really excited to hear who they’ve got lined up next.

During the show, Matt & Steven asked me to pick a favorite connected device hack.  I talked about the quadcopter hack, which I indeed loved. This episode was recorded a few weeks ago, when I hadn’t yet had the chance to control 3D printers with Salesforce1.  I would now say this is my favorite project, surpassing even the quadcopters.

The thing I hope people get out of this, especially people who are new to Salesforce1 and development in general, is how good of time this is to kickstart your career.  As I was listening to our conversation, I found myself reflecting on the amount of money I’ve spent on developer tooling over the years, and how valuable the free developer edition really is.  Literally anyone can get one, get started, and build an extremely lucrative career, for free.  It’s a matter of putting in the effort.

If you’re brand new and want to go down this path but don’t know where to start, you should check out the excellent Apex4Admins. They’ll get you started right.  I’ve included the first of three Apex4Admins episodes here because I think it’s so good.

Thanks again Matt & Steven.  Keep up the great work!

 

Internet of Things: 5 Easy Steps to Understanding Our I Dream of Jeannie Future

0
jeannie

The Internet of Things — IoT for short — is the new black, but most people still can’t explain what it is or why the average person, developer or CEO should care.  Let me break it down in 5 easy to understand steps.

#1 Nobody Wants Your Product

I want to start off by setting the stage with a very simple fact: nobody wants your product. I don’t care if you make smart phones, cars, houses, bathroom scales, pens, pencils or chairs.  A priori no one wants your product.

This is confusing.  We often conflate the effects of marketing and advertising with inherent desire and generally that inherent desire just isn’t there.  Now, if your products are food staples, or maybe art, I’d open that up for discussion but once you get beyond those basics – once you get into the very specific realm of, for example, prepared sandwich cookies, desire isn’t natural, it’s manufactured.

#2 People Want Outcomes

People want outcomes.  Smart phones provide connectedness. Cars provide safe transit from point A to B. Houses help us feel safe.

Products and outcomes are different.  Sometimes it’s difficult to remember that they’re different while caught up in the day to day world of making things and selling them, but that’s why people buy products.

They want outcomes.

It’s always important to ask, what are people getting out of this product? Why are they buying it.  It’s the why that matters.

#3 Technology Enables Better Outcomes

I’ve been in technology most of my career.  The reason I like technology is simple: technology enables better outcomes.  The has been true for a long time, since long before we called it “technology” (a term that joined us in the 17th century) and long before there was a tech industry (coined in the 20th century).

Think about Gutenberg’s printing press (from the 15th century). Gutenberg’s printing press was the quad-copter drone of it’s day. It made “printing” a thing. Before Gutenberg, creating new books meant copying by hand.  For centuries, control of the printing presses conferred a huge amount of power.

Computing power is the same. It started with mainframes, went to PCs, then the Internet and now everyone carries a wildly connected supercomputer in their pocket that fundamentally creates better outcomes for them every day.

Importantly, these better outcomes still require a device, an intermediary, something that separates the user from the computing power.

#4 IoT Breaks Computing Power’s Fourth Wall

The fourth wall is a metaphor describing the relationship between the performers and the audience in a theater. The fourth wall keeps the actors on the stage, safely separated from the audience in their seats. Breaking the fourth wall, a concept that started in the 19th century, is all about engaging observers in the performance.

IoT, as a technical architecture, is fundamentally about eliminating computing power’s fourth wall. IoT embeds computing power among the diverse devices a user might rely on to improve outcomes and reduces the intentionality required for a user to engage it.

IoT is a great marketing term right now as well, which means it’s sometimes used out of context. That’s OK. Marketing terms, even those lacking precision, can be useful organizing principals that help people talk about similar ideas in a similar way.

#5 All Estimates of IoT’s Impact are Too Small

You’ve probably heard 75 billion devices and $14 trillion in revenue opportunities. These are huge numbers — mind boggling — which is great — but kind of insignificant when you switch your default mindset to assume every thing you come into contact with every day will soon have incredibly rich computing and communication capabilities.

Think a decade out, or two decades out, when the standards are agreed on and the technology stack is mature.  Suddenly, I Dream of Jeannie is the new normal.  But instead of Barbara Eden crossing her arms and nodding her head, it will be you, conducting the technology embedded everywhere around you, without thinking about it.

Sensors, robotics and technology we’re not even talking about yet will turn I Dream of Jeannie into brilliant speculative fiction instead of a quality sitcom.

IoT is the organizing metaphor that will help us get there.

…And We’re Just Getting Started

I hope this paints a clearer picture of IoT.  This architectural style is just getting started and people are thinking about it in many different ways.  It doesn’t matter that we don’t agree on all of it yet, or that we don’t have all of the technology worked out.  That will happen.

And it’s going to be a lot of fun!

3D Printer Management Goes Mobile with Salesforce1

1

Full confession: when you look up “3D Printer Newbie” in the OED, you’ll see a picture of me.  I am early on this particular learning curve but as enamored of it as most people who start down this path. This of course means I must somehow connect it to my primary area of interest, Salesforce. That is what I’m going to talk about today.

This post has six parts. 3D Printer Fundamentals, Introducing OctoPrint, The Salesforce Side of the House, Code Review, Practical Applications and Things That Went Wrong Along the Way.  But let’s start with a demo!

(Yes, that bonus soundtrack you hear in the far background is in fact my child.)

3D Printer Fundamentals

My work here was done with a couple of PrintrBot Simple Metal printers I picked up online. They’re not the most advanced printer on the market — if anything, they’re a minimalist interpretation of the form — but they are pretty sweet and at $599 the price is certainly right.

PrintrBot-Simple-Metal-Anatomy-453D printers are what’s referred to as “additive manufacturing.”  This means they start with nothing and add something to create their output. Most 3D printers on the market extrude thin layers of plastic over and over again, and these devices share a few common attributes.  First, since they work in three dimensions, they must be able to move a printhead in three dimensions.  I’ve labeled these as the X, Y and Z axises above so you can see which parts of the PrintrBot move. Second, they have a micro-controller that moves the printhead and regulates temperature and a bed that holds the results.  Finally, they all have a feed that moves plastic filament into a hot end where it melts and is extruded on to the bed.  For filament, I used 1.75mm wide PLA (plant based and compostable).  Layers are about 0.3mm thick, and come out of a 0.4mm hot end nozzle at 190° C.

Controlling a 3D printer is a cooperative effort between the onboard micro-controller and host software. The host software feeds printing instructions to the micro-controller which in turn provides operating details back to the host software.  The most important of these operating details is the temperature of the hot-end.  Probably the most common host software you will hear about is Repetier, and it’s definitely a great way to go. However, it’s not the only way to go and I ended up using another one for this project, which I’ll get to in a second.

Now, this is most of the picture, but you still need to tell the host software what you want to print. A 3D print generally starts off as a 3D design in some kind of CAD program.  There are a bunch of these you can choose from.  SketchUp is popular and free for non-commercial use, TinkerCAD is an online web-app that does it, and there are a bunch of others.  Once you have a 3D design, you need to convert it to something your 3D printer can understand.  Slic3r is the tool of choice for that. It converts 3D designs into a “gcode” file that contains actual instructions your printer can use.  If you want to use someone else’s design to start, checkout the good people at Thingiverse.  They have a lot of designs you can download and use for free.

octoprint

Introducing OctoPrint

Probably the best part of my job is poking my head into a new-to-me corner of the technology world and discovering an unexpected gem. OctoPrint is that gem. OctoPrint is 3D printer host software delivered as a web-app. It’s open source, written in Python, optionally runs on a Raspberry Pi and the devel branch has a pretty sweet API.

If you’ve read any of my earlier posts about controlling quadcopters, Philips Hues or DIY wireless sensor networks, you probably know what happens next.

If you guessed:

3D-Printer-OctoPrint-Salesforce1-NodeJS-Raspberry-Pi_2You are correct.  The basic setup is pretty simple.  I install the OctoPrint friendly Rasbian distro OctoPi (yes, it’s as easy as they make it look — completely awesome, too) on a Raspberry Pi I have sitting around.  I then added Node JS to it and created some familiar looking JS to talk to Salesforce via the Streaming API. OctoPrint talks to the PrintrBot Simple by way of a USB cable, so nothing special there. Also, in case you’re curious, I opted to have a single Pi control a single PrintrBot, so the setup in the video requires two units.

(Incidentally, I wanted to mix this architecture up this time, but was stymied.  See “Things That Went Wrong Along the Way” below for details on that.)3D-Printer-Salesforce

The Salesforce Side of the House

Let’s start with the data model.  It’s pretty easy, but a little different than the ones I’ve used before.

Historically, I’ve used a single message object.  The OctoPrint API is pretty rich, though, and has a variety of requirements (some commands are GETS and others are POSTS with bodies requiring a JSON object, for example), so I added an additional object to store API Command Templates.  The UI simply lists the available commands, and then creates a printer message based on the template.

Schema_Builder___salesforce_com_-_Developer_Edition

I really like this approach because it let’s me add new API commands as data, not metadata, so it’s super easy to add functionality and update the system as OctoPrint changes without having to deploy code.  (I can’t remember who, but I think I’m stealing this idea from someone.  Sam maybe?  I hate it when I can’t remember, so ping me if it’s you.)

Notice I don’t have a Printer object here. I do have one in the code, but it only holds names. It should be a relationship on the Printer Message object, but I didn’t get around to it.

The rest of the app is plain old Visualforce and Apex.  I’m not using any of the modern JS frameworks (Angular JS, etc), and I haven’t gone out of my way to optimize queries etc.  As you can see in the YouTube above, it performs pretty well.  The longest delay is doing the asynchronous round trip all the way back from the PrintrBot.

(Full confession: Christophe talked me into adding a little padding around the page so the Bootstrap based CSS didn’t extend completely end to end.  He was right.)

Code Review

As I said, the code on the Salesforce side of the house is pretty basic.  You can see it on the Github repo and yes there’s a link to an unmanaged package there too.  Literally all I’m doing is inserting an object based on a template contained in another object. The code that’s doing the interface is pretty similar the the quadcopter code, but it has a couple of twists.  The full gist is here.

In the likely event you don’t want to parse through the code pasted below, the simple flow is:

  1. On Salesforce1, create a Printer Message using a little step-by-step process governed by a controller in Apex (here).
  2. Wait for messages on the Streaming API, send them to handleOctoPrintCall and store the message’s original SFDC ID (below).
  3. Determine if we need a GET or a POST, create the outbound request and send it to OctoPrint. OctoPrint then sends it to the printer.  Note that OctoPrint and this script are running on the same Raspberry Pi.
  4. When the results come back, get the original message ID, and update the original request using a custom Apex REST service (here).

That’s is.

function handleOctoPrintCall(command, body) {
	var options;
  if (body == null) {
    console.log("body is null");
    options = {
	    url: OctoPrintURL + command,
	    headers: {
           	'X-Api-Key': OctoPrintApiKey
    	    }
	   };
   } else {
      console.log("body isn't null");
     options = {
      url: OctoPrintURL + command,
      method: "POST",
      body: body,
      headers: {
            'X-Api-Key': OctoPrintApiKey,
            'Content-Type': 'application/json'
          }
      };
 
   }
 
	request(options, callback);
}
 
function callback(error, response, body) {
  console.log("callback from printer");
  console.log(body);
  console.log("end callback from printer");
  
  if (!error && response.statusCode == 200) {
    console.log(body);
    sendPrinterResponse(body);
  } else if (!error && response.statusCode == 204) {
    console.log("Empty Body (204)");
    sendPrinterResponse( JSON.stringify({ "result" : "OK" }) );
  }
 
}
 
function sendPrinterResponse(body) {
 
  var newBody = {
    originalId : lastMessageId,
    responseJson : body
  };
 
  var options = {
      url: orgOauth.instance_url + '/services/apexrest/PrinterResponse',
      method: "POST",
      body: JSON.stringify(newBody),
      headers: {
            'Authorization': 'OAuth ' + orgOauth.access_token,
            "Content-Type": 'application/json'
          }
    };  
 
  request(options, printerResponseCallback);  
 
}
 
function printerResponseCallback(error, response, body) {
  console.log('printerResponseCallback');
  lastMessageId = '';
  if (!error) {
    console.log("success");
    console.log(body); 
  } else { 
    console.log("error");
    console.log(error);
  }
}

The other bits of code in the gist are relatively mundane -- a heartbeat so I know the system is alive, OAuth magic with salesforce (thanks Kevin et al!)

Practical Applications

The most frequent question people ask me when I tie together a few interesting bits of technology is simple: why? That's a great question, and sometimes I'm doing it just to demonstrate that it's possible. 3D printing and Salesforce is different.

One practical (but abstract) application  of an integration like this is to check asset utilization.  The more expensive, specialized equipment you have, the more likely you are to care about it's utilization.  In general, the more you utilize these assets, the better.  The classic example here is Southwest Airlines and their drive to turn their planes around very quickly. The more often their planes are flying, the more money they're making.  All of these assets and this data should be surfaced through whatever interface your team is likely to use in service of this goal.

More concretely, let's say you have a 3D printer farm at your company, and you use those printers to create parts.  Maybe these are R&D parts, maybe they're spare parts, maybe they're promotional chochkies.  Having something to spawn jobs and monitor progress is a good thing.  More than that, having a source of engineered, iterated on and blessed 3D designs means that users are more likely to get the results they want.  A central resource like the one I've shown here is a step in the right direction.

If you take this idea one level further, let's saying you have a very interesting service scenario where a piece of equipment reports a system fault automatically.  That fault is then diagnosed as needing a unique spare part, which is 3D printed and then automatically delivered by, for example, a quadcopter.  That's some next generation stuff right there.

There are more ideas, but you get my general train of thought here.

Three-Quarter-T-Rex-Skull

Things That Went Wrong Along the Way

Lots of things went wrong and didn't work.

  1. Most irritatingly, I accidentally aborted printing this super-cool T-Rex skull.  Totally blaming Seligman but it's my fault for wanting to show him another project.  ProTip: think before you unplug that USB. Hours of printing and meters of filament down the drain.
  2. I wanted to get out of the Streaming API pattern and connected OctoPrint directly to the Internet.  No reason that shouldn't work, except my attempts at using VyperVPN and No-Ip to get that going failed, failed and failed again.  Killed a whole day.  Someone better at networking could do it. The Streaming API is dead easy because I don't have to worry about open a port on my network, etc.
  3. Turns out 3D printers are relatively hard to get.  I somehow caught a window where I could buy these on Amazon.  The first two that arrived were all busted up like someone had dropped them off a pretty tall conveyor, but replacements were only a couple days away.  Lots of places advertise filament and printers and neglect to mention a 6 week lead time and even on Amazon these are now a 2-4 week delivery item.
  4. At one point, I jammed the feed on the printer so bad I had to call in backup.  Gory details over on their forum. Turned into a great excuse to take apart the printer though and I always like that.
  5. The PrintrBot Simple intro video made some mention of the various kinds of surface treatments you could use to enhance your printing.  The standard is blue painters tape--it works like a charm!  I also tried some beige masking tape I had lying around the house, since The blue stuff was a Home Depot away, and it was an unmitigated disaster.

Wrap Up

Over all, I end where I started: this stuff is super cool.  But it's also still pretty new and not very polished yet.  If you jump in now, you'll need to be patient and interested in tinkering.  And if you are those things -- WOW.  You're going to love it!

IoT, the Maker Movement and Evangelism

0

Paul Wallbank was kind enough to film a conversation he and I had earlier this month.

Control Your Quadcopter Drone Fleet with Salesforce1

8

Let’s say — hypothetically —  your VP of Drone Fleet Operations just asked you to help her handle drone management, route planning, payload optimization and more. What do you do? Well, there’s a few approaches to tackling the problem. Approach #1 is all about controlling drones using the Salesforce1 Mobile app. That’s what I’m going to talk about today. Note that all of this is done with a free Developer Edition and a little code.

Although I won’t cover it here, there’s also a mildly entertaining yet entirely impractical YouTube artifact documenting my adventures at ThingMonk where together with the excellent Darach Ennis we were able to launch a quadcopter using a coffeepot.

Equipment & Architecture

Let’s start by looking at the equipment you’ll need. The first thing is a quadcopter or two.  I used the Parrot AR Drone 2.0 available at pretty much every retailer worth their weight in salt. The Parrot is great for a lot of reasons, but first and foremost is that it has a great API. Where you have an API, great things are possible, right? Now, the Parrot is also a toy, so you production minded folks will probably want to upgrade to something more robust.

ardrone

The way the AR Drone works out of the box is that it creates a WiFi hotspot. You then connect your controlling device to that AR Drone hotspot and operate it. Parrot sets you up with an app that runs on either an iOS or Android device. I’ve controlled them from both platforms and it works great. The default AR Drone configuration requires one controller per drone, and it requires that controller to be on the WiFi network provided by the drone. If you have two drones, they are isolated from each other by their network connections and there’s no interaction.  

ardrone.standardconfig

In order for this to work with Salesforce, and in order to control multiple drones at the same time, we have to somehow unify these devices, which using the out of the box configuration means the controller needs to bridge multiple networks. My goto local interface box is typically the Raspberry Pi, and, fortunately, the Raspberry Pi is capable of supporting multiple network interfaces, which means it can also handle multiple network addresses. There are a few ways you could configure this, but I chose to use a single Raspberry Pi as a bridge between Salesforce and two other Raspberry Pi’s which connect to the AR Drones.  It looks a little like this:

ARDRone.Salesforce.v2

Now all you need is an app to handle the interface to the AR Drone. There are a lot of great ways to do this, and for this example I have used CylonJS and their ARDrone driver.  (You might remember Cylon JS from the Dreamforce Connected Device Lab.  They do tons of great stuff in the robotics world and have cool libraries for JavaScript, Ruby and Go.)

Control via the Streaming API Pattern

My first approach on this project is to use the familiar Streaming API  Pattern. (See Controlling Philips Hue from Salesforce1 for another example, or get started with a really simple streaming API example.) The Drone Gateway connects to Salesforce, listens to a Streaming API Push Topic and then forwards those instructions to a device as soon as they’re received.

On the Salesforce side of the house, we have to create a simple way to generate listenable data. This is easier than it sounds. The first thing we want is an sObject to store the data in. I’m re-using an existing object pattern I’ve used for other message driven work, I call it “Drone Message.”  The two key pieces of data it stores are the Address and Message. You can see in the screen capture that this one is setting the “land” message to “D2″.

Drone_Message__DRONE-00143___salesforce_com_-_Developer_Edition-2

You can of course use the default UI to create the records, but that then requires you to know addresses and message codes. Since code handles those kind of details better than my brain does, I created a simple Apex class to create these records.

public class DroneController{
    public void droneOneTakeoff() {
        insertMessage('D1','takeoff');
    }

    public void droneOneLand() {
        insertMessage('D1','land');
    }

    public void droneTwoTakeoff() {
		insertMessage('D2', 'takeoff');        
    }

    public void droneTwoLand() {
        insertMessage('D2', 'land');
    }

    public void insertMessage(String address, String message) {
        Drone_Message__c m = new Drone_Message__c();
        m.Address__c = address;
        m.Message__c = message;
        insert m;
    }

}

And now all I need is a little Visualforce code to extend this out to the UI layer. Note that this Visualforce page is tied to the Apex code above using the controller attribute.

<apex:page controller="DroneController" standardStylesheets="false" showHeader="false">
<style>
h1 {
font-family: sans-serif;
}

.large {
font-family: sans-serif;
font-size: 18pt;
}
</style>
<h1>Drone Controller</h1>
<apex:form >
<h1>Drone 1</h1>
<p><apex:commandButton action="{!droneOneTakeoff}" value="Takeoff" styleClass="large" />&nbsp;&nbsp;
<apex:commandButton action="{!droneOneLand}" value="Land" styleClass="large"/></p>

<h1>Drone 2</h1>
<p><apex:commandButton action="{!droneTwoTakeoff}" value="Takeoff" styleClass="large"/>&nbsp;&nbsp;
<apex:commandButton action="{!droneTwoLand}" value="Land" styleClass="large" /></p>

</apex:form>
</apex:page>

Now you need to make this Visualforce page available for mobile apps, create a tab for it and finally customize your mobile navigation options.  These are all just a few clicks, so check out the links if you've never done it before -- pretty easy. Out in the world of humans, this renders as a very simple page, the same one that you saw in the video clip above.

DroneControllerInterface-one

Now that we have a quick and easy way to create listenable messages, let's take a quick look at the Drone Gateway that's doing this listening. This is a pattern I've re-used a few times, so you might be familiar with it. The gateway authenticates, begins listening to a Streaming API Push Topic, and then handles whatever it receives.  I chose to write this in Node.js and the code is pretty simple. The connect to Salesforce is detailed in the Philips Hue article, so I'll just show you how it handles the message. Note the "address" and "message" arguments.

function handleMessage(address, message) {
	console.log("address: " + address);
	console.log("message: " + message);
	if (address == 'D1') {
		if (message == 'takeoff') {
			console.log("in d1 takeoff");
			handleRequest("http://10.0.0.2:1337/start");
		} else if (message == 'land') {
			console.log("in d1 land");
			handleRequest("http://10.0.0.2:1337/stop");
		}
	} else if (address == "D2") {
                if (message == 'takeoff') {
                        console.log("in d2 takeoff");
			handleRequest("http://10.0.0.3:1337/start");
                } else if (message == 'land') {
                        console.log("in d2 land");
			handleRequest("http://10.0.0.3:1337/stop");
                }		
	}
}

Now, you will have no doubt noticed that the above code is doing nothing more than making a call to a webserver. When I was testing, I decided that an http based interface would also be fun, so I created a small server that simply responds to two URLs: start and stop. You can see that these map to the CylonJS commands for "takeoff" and "land".

http.createServer(function(req,res) {
	if (req.url == "/start") {
		console.log("ready to start");
		copter1.connections['ardrone'].takeoff();
	} else if (req.url == "/stop") {
		console.log("ready to stop");
		copter1.connections['ardrone'].land();
	}
	res.writeHead(200, {'Content-Type': 'text/plain'});
	res.end('Executed');
}).listen(1337, "10.0.0.2");

And there you have it. The start to finish message flow now looks like this:

  1. User presses takeoff on their mobile device.
  2. Salesforce1 inserts a Drone Message object for takeoff.
  3. Streaming API picks up the new records, forwards to listeners.
  4. The Node.js based Drone Gateway catches the new record, and sends it to the right address.
  5. The Node.js based Drone Server sends the specific command to the AR Drone.

Code notes and links:

My command center for the video shoot looks a bit more complicated, but it follows the diagrams above.  Note the three Raspberry Pi's and two network hubs on the lower left.

Control-Multiple-AR-Drones-from-Salesforce1.jpg

Wrap Up

As you can see from the video, it's pretty easy to get the drones to follow some simple instructions. The primary challenge with this method is the inherent lag between when an instruction is issued and when it gets to the drone.  This lag depends on a huge number of factors -- Internet connection, gateway device performance, Streaming API performance, etc -- but the end result is the same.  A drone moving at 5-6 meters per second will be in a completely different place by the time it responds to a delayed command.

An interesting experiment that raises a lot of questions for me.  First and foremost, what is the best way to spread device intelligence out among the components of a system?  Which is to say, what kind of work should Salesforce play in this kind of complicated interaction?  My overall feeling is that this, while interesting, is lower level than truly practical today.

Follow

Get every new post delivered to your Inbox.

Join 4,369 other followers

%d bloggers like this: