Twilio Sync for IoT and Programmable Wireless on a LinkIt ONE

Today we'll mix the lightweight messaging protocol MQTT with Twilio Sync for IoT, the Arduino IDE, and the Seeed Studio LinkIt ONE. We'll use the Twilio Device Manager to create a Device Fleet then show a LinkIt ONE to Sync connection. We'll do all of that using either Twilio's Programmable Wireless connectivity over GPRS, or through a friendly WiFi network.

Oh, and we almost forgot - we'll use this ultra-powerful enterprise grade setup to blink an LED. C'mon, we'll show you!

Sync for IoT is currently in Developer Preview, which means access is by invite only. If you'd like to try what you see in these docs, sign up for the developer preview and the team at Twilio will get you onboarded as soon as possible.

Sign Up For (or Sign Into) a Twilio Account

Either create a new Twilio account (you can sign up for a free Twilio trial), or sign into an existing Twilio account.

Once you are logged in, click this Twilio Device Manager link to go to the Sync for IoT console.

Purchase and Activate a Programmable Wireless SIM Card (Optional)

This code will work both over WiFi or with 2G/GPRS via Twilio's Programmable Wireless. To switch between the two, set WIFI_USED to true or false.  (More detail below).

If you are connecting with Programmable Wireless, here's the order of operations:

  • Navigate to the Programmable Wireless section of the console with your SIMs handy
  • If your SIM is already associated with your account, follow the instructions on the SIMs page (Click the plus '+' button)
  • If you have an unassociated SIM , follow the instructions in 'Starter SIMs'

Once your SIM is active, associated, and has a data plan, insert it into the LinkIt ONE. Only punch out the medium sized SIM (if you do accidentally punch out too much, friction should still hold it though). Note: the proper orientation is 'reversed' from most phones; the angled side should face out.

SIM Card Insertion LinkIt

If you haven't yet, attach the antennas as shown above.

A General Warning About 2G Development

While most of your code will be transferrable, it’s important to note: for new product development 2G isn’t a good choice.

American 2G networks are being deprecated. For new product development, we suggest researching 4G alternatives or discussing your idea with the Twilio Programmable Wireless team.

Deploy a Fleet of LinkIt ONE Things

A Device Fleet is a collection of devices, certificates or keys, and unique configurations inside Twilio Sync. While you can create many fleets, any individual fleet will always be isolated. That's perfect for a use case where you want to prevent the accidental interaction of your things.

For today though, a Default Fleet is already provisioned for you. Get started by navigating to it in the Device Management console:

Locating the default Ffleet in the Twilio Console

(Note you may also deploy a fleet through the REST API.)

Loading Code Samples...
Language
SDK Version:
  • 5.x
Response Format:
  • json
SDK Version:
  • 7.x
SDK Version:
  • 3.x
SDK Version:
  • 5.x
SDK Version:
  • 6.x
SDK Version:
  • 5.x
Format:
  • JSON
const accountSid = 'ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
const authToken = 'your_auth_token';
const Twilio = require('twilio').Twilio;

const client = new Twilio(accountSid, authToken);

client.preview.deployed_devices.fleets
  .create({
    friendlyName: 'My Fleet of Devices',
  })
  .then(response => {
    console.log(response);
  })
  .catch(error => {
    console.log(error);
  });
// Get the C# helper library from https://twilio.com/docs/libraries/csharp
using System;
using System.Collections.Generic;
using Twilio;
using Twilio.Rest.Preview.DeployedDevices;

public class Example
{
    public static void Main(string[] args)
    {
        // Get your Account SID and Auth Token from https://twilio.com/console
        const string accountSid = "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
        const string authToken = "your_auth_token";
        TwilioClient.Init(accountSid, authToken);

        var fleet = FleetResource.Create(
            friendlyName: "My Fleet of Devices"
        );

        Console.WriteLine(fleet.Sid);
    }
}
<?php
// Get the PHP helper library from https://twilio.com/docs/libraries/php
require_once '/path/to/vendor/autoload.php'; // Loads the library

use Twilio\Rest\Client;

// Get your Account SID and Auth Token from https://twilio.com/console
$accountSid = 'ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
$authToken = 'your_auth_token';
$client = new Client($accountSid, $authToken);

$fleet = $client->preview->deployedDevices->fleets->create(
  array(
    'friendlyName' => 'My Fleet of Devices'
  )
);

echo $fleet->sid;
# Get the Ruby helper library from https://twilio.com/docs/libraries/ruby
require 'twilio-ruby'

# Get your Account SID and Auth Token from https://twilio.com/console
account_sid = 'ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
auth_token = 'your_auth_token'
client = Twilio::REST::Client.new(account_sid, auth_token)

fleet = client.preview.deployed_devices.fleets.create(
  friendly_name: 'My Fleet of Devices'
)

puts fleet.sid
# Get the Python helper library from https://twilio.com/docs/libraries/python
from twilio.rest import Client

# Get your Account SID and Auth Token from https://twilio.com/console
account_sid = 'ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
auth_token = 'your_auth_token'
client = Client(account_sid, auth_token)

fleet = client.preview.deployed_devices.fleets.create(
    friendly_name='My Fleet of Devices')

print(fleet.sid)
// Get the Java helper library from https://twilio.com/docs/libraries/java
import com.twilio.Twilio;
import com.twilio.rest.preview.deployedDevices.Fleet;
import com.twilio.rest.preview.deployedDevices.FleetCreator;

public class Example {
    // Get your Account SID and Auth Token from https://twilio.com/console
    public static final String ACCOUNT_SID = "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
    public static final String AUTH_TOKEN = "your_auth_token";

    public static void main(String[] args) {
        Twilio.init(ACCOUNT_SID, AUTH_TOKEN);

        FleetCreator fleetCreator = new FleetCreator();
        Fleet fleet = fleetCreator
                .setFriendlyName("My Fleet of Devices")
                .create();

        System.out.println(fleet.getSid());
    }
}
curl -u 'ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX:your_auth_token' \
  -X POST https://preview.twilio.com/DeployedDevices/Fleets
{
  "sid": "FLXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  "friendly_name": null,
  "account_sid": "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  "default_deployment_sid": "DLXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  "date_created": "2017-08-14T15:25:45Z",
  "date_updated": "2017-08-14T15:25:45Z",
  "url": "https://preview.twilio.com/DeployedDevices/Fleets/FLXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  "links": {
    "certificates": "https://preview.twilio.com/DeployedDevices/Fleets/FLXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Certificates",
    "keys": "https://preview.twilio.com/DeployedDevices/Fleets/FLXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Keys",
    "devices": "https://preview.twilio.com/DeployedDevices/Fleets/FLXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Devices",
    "deployments": "https://preview.twilio.com/DeployedDevices/Fleets/FLXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Deployments"
  }
}
Using the API to create a Device Fleet in Sync for IoT.
Create a Device Fleet

Using the API to create a Device Fleet in Sync for IoT.

It's now time to work on the deployment.

Configure the New Fleet's Deployment

Twilio will automatically give you a default Deployment and configure it upon Fleet creation. The 'Default Deployment' field in your Fleet will look similar to the following screenshot:

A default deployment is automatically provisioned for each new Device Fleet.

Click the 'Configure the Deployment' link:

Every deployment is configured with a default Service Instance.

Twilio also automatically created a new Sync Service Instance. An instance is similar to an isolated database. When you make updates on Sync primitives (such as the Document type we're using here), they are stored only in this Sync instance.

As before, you can create a Deployment with the API.

Loading Code Samples...
Language
SDK Version:
  • 5.x
Response Format:
  • json
SDK Version:
  • 7.x
SDK Version:
  • 3.x
SDK Version:
  • 5.x
SDK Version:
  • 6.x
SDK Version:
  • 5.x
Format:
  • JSON
const accountSid = 'ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
const authToken = 'your_auth_token';
const Twilio = require('twilio').Twilio;

const client = new Twilio(accountSid, authToken);
const fleet = client.preview.deployed_devices.fleets(
  'FLXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
);

fleet
  .deployments('FLXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX')
  .update({
    friendlyName: 'My New Device Deployment',
    syncServiceSid: 'ISXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
  })
  .then(response => {
    console.log(response);
  })
  .catch(error => {
    console.log(error);
  });
// Get the C# helper library from https://twilio.com/docs/libraries/csharp
using System;
using System.Collections.Generic;
using Twilio;
using Twilio.Rest.Preview.DeployedDevices;

public class Example
{
    public static void Main(string[] args)
    {
        // Get your Account SID and Auth Token from https://twilio.com/console
        const string accountSid = "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
        const string authToken = "your_auth_token";
        TwilioClient.Init(accountSid, authToken);

        const string deploymentSid = "DLXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
        var deployment = DeploymentResource.Update(
            deploymentSid,
            friendlyName: "My New Device Deployment");

        Console.WriteLine(deploymentSid.FriendlyName);
    }
}
<?php
// Get the PHP helper library from https://twilio.com/docs/libraries/php
require_once '/path/to/vendor/autoload.php'; // Loads the library

use Twilio\Rest\Client;

// Get your Account SID and Auth Token from https://twilio.com/console
$accountSid = 'ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
$authToken = 'your_auth_token';
$client = new Client($accountSid, $authToken);

$deploymentSid = 'DLXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
$deployment = $client->preview->deployedDevices->deployments($deploymentSid)->update(
  array(
    'friendlyName' => 'My New Device Deployment'
  )
);

echo $deployment->friendlyName;
# Get the Ruby helper library from https://twilio.com/docs/libraries/ruby
require 'twilio-ruby'

# Get your Account SID and Auth Token from https://twilio.com/console
account_sid = 'ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
auth_token = 'your_auth_token'
client = Twilio::REST::Client.new(account_sid, auth_token)

deployment_sid = 'DLXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
deployment = client.preview.deployed_devices
                   .deployments(deployment_sid)
                   .update(friendly_name: 'My New Device Deployment')

puts deployment.friendly_name
# Get the Python helper library from https://twilio.com/docs/libraries/python
from twilio.rest import Client

# Get your Account SID and Auth Token from https://twilio.com/console
account_sid = 'ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
auth_token = 'your_auth_token'
client = Client(account_sid, auth_token)

fleet_sid = 'FLXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
deployment_sid = 'DLXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
deployment = client.preview\
                   .deployed_devices\
                   .fleets(fleet_sid)\
                   .deployments(sid=deployment_sid)\
                   .update(friendly_name='My New Device Deployment')

print(deployment.friendly_name)
// Get the Java helper library from https://twilio.com/docs/libraries/java
import com.twilio.Twilio;
import com.twilio.rest.preview.deployedDevices.Deployment;
import com.twilio.rest.preview.deployedDevices.DeploymentUpdater;

public class Example {
    // Get your Account SID and Auth Token from https://twilio.com/console
    public static final String ACCOUNT_SID = "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
    public static final String AUTH_TOKEN = "your_auth_token";

    public static void main(String[] args) {
        Twilio.init(ACCOUNT_SID, AUTH_TOKEN);

        String deploymentSid = "DLXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";

        Deployment deployment = new DeploymentUpdater(deploymentSid)
                .setFriendlyName("My New Device Deployment")
                .update();

        System.out.println(deployment.getFriendlyName());
    }
}
curl -u 'ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX:your_auth_token' \
  -X POST https://preview.twilio.com/DeployedDevices/Fleets/FLXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Deployments/DLXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX \
  -d 'FriendlyName=My New Device Deployment' \
  -d 'SyncServiceSid=ISXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
{
  "sid": "DLXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  "friendly_name": "My New Device Deployment",
  "fleet_sid": "FLXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  "account_sid": "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  "sync_service_sid": "ISXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  "date_created": "2017-08-14T15:44:05Z",
  "date_updated": "2017-08-14T15:55:25Z",
  "url": "https://preview.twilio.com/DeployedDevices/Fleets/FLXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Deployments/DLXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
}
Update a Device Deployment

Once you've got the Deployment handled (and an instance pointer), it's time to create a Device Certificate for authentication.

Create a LinkIt ONE Device and Device Certificate

For Sync for IoT, a Device refers to a particular piece of hardware managed through the Device Manager. When your hardware connects to Sync, Twilio identifies it either through a key or certificate. The LinkIt is a powerful board and can handle certificate based authentication; we strongly encourage you to use certificate credentialing wherever you can.

Click the 'Devices' link on the left sidebar from inside your Fleet. Enter a Unique and Friendly name for the LinkIt ONE then hit the 'Create' button.

Create a New ESP8266 Device in Deployed Devices

You can also create a Device through the API.

Loading Code Samples...
Language
SDK Version:
  • 5.x
Response Format:
  • json
SDK Version:
  • 7.x
SDK Version:
  • 3.x
SDK Version:
  • 5.x
SDK Version:
  • 6.x
SDK Version:
  • 5.x
Format:
  • JSON
// Get the Node helper library from https://twilio.com/docs/libraries/node
const fs = require('fs');
const Twilio = require('twilio').Twilio;

// Get your Account SID and Auth Token from https://twilio.com/console
const accountSid = 'ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
const authToken = 'your_auth_token';
const client = new Twilio(accountSid, authToken);

const fleetSid = 'FLXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
const fleetService = client.preview.deployed_devices.fleets(fleetSid);

fleetService.devices
  .create({
    friendlyName: 'My Device #1',
  })
  .then(response => {
    console.log(response);
  })
  .catch(error => {
    console.log(error);
  });
// Get the C# helper library from https://twilio.com/docs/libraries/csharp
using System;
using System.Collections.Generic;
using Twilio;
using Twilio.Rest.Preview.DeployedDevices.Fleet

public class Example
{
    public static void Main(string[] args)
    {
        // Get your Account SID and Auth Token from https://twilio.com/console
        const string accountSid = "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
        const string authToken = "your_auth_token";
        TwilioClient.Init(accountSid, authToken);

        var device = DeviceResource.Create(
            pathFleetSid: "FLXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
            friendlyName: "My Device #1"
        );

        Console.WriteLine(device.Sid);
    }
}
<?php
// Get the PHP helper library from https://twilio.com/docs/libraries/php
require_once '/path/to/vendor/autoload.php'; // Loads the library

use Twilio\Rest\Client;

// Get your Account SID and Auth Token from https://twilio.com/console
$accountSid = 'ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
$authToken = 'your_auth_token';
$client = new Client($sid, $token);

$fleetSid = 'FLXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
$fleetService = $client->preview->deployedDevices->fleets($fleetSid);

$device = $fleetService->devices->create([
    'friendlyName' => 'My Device #1'
]);

echo $device->sid;
# Get the Ruby helper library from https://twilio.com/docs/libraries/ruby
require 'twilio-ruby'

# Get your Account SID and Auth Token from https://twilio.com/console
account_sid = 'ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
auth_token = 'your_auth_token'
client = Twilio::REST::Client.new(account_sid, auth_token)

fleet_sid = 'FLXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
fleet_service = client.preview.deployed_devices.fleets(fleet_sid)

device = fleet_service.devices.create(
  friendly_name: 'My Device #1'
)

puts device.sid
# Get the Python helper library from https://twilio.com/docs/libraries/python
from twilio.rest import Client

# Get your Account SID and Auth Token from https://twilio.com/console
account_sid = 'ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
auth_token = 'your_auth_token'
client = Client(account_sid, auth_token)

fleet_sid = 'FLXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
fleet_service = client.preview.deployed_devices.fleets(fleet_sid)

device = fleet_service.devices.create(friendly_name='My Device #1')

print(device.sid)
// Get the Java helper library from https://twilio.com/docs/libraries/java
import com.twilio.Twilio;
import com.twilio.base.ResourceSet;
import com.twilio.rest.preview.deployedDevices.fleet;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;

public class Example {
    // Get your Account SID and Auth Token from https://twilio.com/console
    public static final String ACCOUNT_SID = "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
    public static final String AUTH_TOKEN = "your_auth_token";

    public static void main(String[] args) {
        Twilio.init(ACCOUNT_SID, AUTH_TOKEN);

        Device device = DeviceCreator("FLXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
            .setFriendlyName("My Device #1")
            .create();

        System.out.println(device.getSid());
    }
}
curl -u 'ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX:your_auth_token' \
  -X POST https://preview.twilio.com/DeployedDevices/Fleets/FLXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Devices \
  -d 'FriendlyName=My Device #1'
{
  "sid": "THXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  "friendly_name": "My Device #1",
  "unique_name": null,
  "fleet_sid": "FLXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  "account_sid": "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  "deployment_sid": "DLXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  "identity": null,
  "enabled": true,
  "date_created": "2017-08-14T19:19:30Z",
  "date_updated": "2017-08-14T19:19:30Z",
  "date_authenticated": null,
  "url": "https://preview.twilio.com/DeployedDevices/Fleets/FLXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Devices/THXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
}
Create a Device

 While still in your device, click the 'Certificate' link in the left sidebar then the red plus sign (+) and create a new Device Certificate. As you are clicking from inside the device, it will automatically associate this Certificate with the LinkIt. 

Enter a name then check the 'Self-signed certificate' box. Finally, hit the 'Create' button to create your certificate.

Sync Certificate and Key Download for ESP32

In the success screen (similar to the above), download both the Certificate and Private key, and copy the key decryption password to a safe place. Note: this is your last chance to do this!  If you miss this step you'll have to create a new certificate!

  • Also, download Twilio's root certificate (naming it root.crt) which you'll use to verify you are talking to Twilio:

Root Certificate for LinkIt ONE Sync

Optionally, you can create device certificates with the API as well.

Loading Code Samples...
Language
SDK Version:
  • 5.x
Response Format:
  • json
SDK Version:
  • 7.x
SDK Version:
  • 3.x
SDK Version:
  • 5.x
SDK Version:
  • 6.x
SDK Version:
  • 5.x
Format:
  • JSON
// Get the Node helper library from https://twilio.com/docs/libraries/node
const fs = require('fs');
const Twilio = require('twilio').Twilio;

// Get your Account SID and Auth Token from https://twilio.com/console
const accountSid = 'ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
const authToken = 'your_auth_token';
const client = new Twilio(accountSid, authToken);

const fleetSid = 'FLXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
const fleetService = client.preview.deployed_devices.fleets(fleetSid);

fleetService.certificates
  .create({
    deviceSid: 'THXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
    friendlyName: 'Woody',
    certificateData: fs.readFileSync('/path/to/certificate.pem'),
  })
  .then(response => {
    console.log(response);
  })
  .catch(error => {
    console.log(error);
  });
// Get the C# helper library from https://twilio.com/docs/libraries/csharp
using System;
using System.Collections.Generic;
using Twilio;
using Twilio.Rest.Preview.DeployedDevices.Fleet

public class Example
{
    public static void Main(string[] args)
    {
        // Get your Account SID and Auth Token from https://twilio.com/console
        const string accountSid = "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
        const string authToken = "your_auth_token";
        TwilioClient.Init(accountSid, authToken);

        const string certificatePath = @"C:\path\to\certificate.pem";
        var certificate = CertificateResource.Create(
            pathFleetSid: "FLXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
            deviceSid: "THXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
            friendlyName: "Woody",
            certificateData: System.IO.File.ReadAllText(certificatePath)
        );

        Console.WriteLine(certificate.Sid);
    }
}
<?php
// Get the PHP helper library from https://twilio.com/docs/libraries/php
require_once '/path/to/vendor/autoload.php'; // Loads the library

use Twilio\Rest\Client;

// Get your Account SID and Auth Token from https://twilio.com/console
$accountSid = 'ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
$authToken = 'your_auth_token';
$client = new Client($sid, $token);

$fleetSid = 'FLXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
$fleetService = $client->preview->deployedDevices->fleets($fleetSid);

$certificateContent = file_get_contents('/path/to/certificate.pem');
$certificate = $fleetService->create($certificateContent, [
    'deviceSid' => 'THXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
    'friendlyName' => 'Woody',
]);

echo $certificate->sid;
# Get the Ruby helper library from https://twilio.com/docs/libraries/ruby
require 'twilio-ruby'

# Get your Account SID and Auth Token from https://twilio.com/console
account_sid = 'ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
auth_token = 'your_auth_token'
client = Twilio::REST::Client.new(account_sid, auth_token)

fleet_sid = 'FLXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
fleet_service = client.preview.deployed_devices.fleets(fleet_sid)

certificate = fleet_service.certificates.create(
  device_sid: 'THXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
  friendly_name: 'Woody',
  certificate_data: IO.read('/path/to/certificate.pem')
)

puts certificate.sid
# Get the Python helper library from https://twilio.com/docs/libraries/python
from pathlib import Path
from twilio.rest import Client

# Get your Account SID and Auth Token from https://twilio.com/console
account_sid = 'ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
auth_token = 'your_auth_token'
client = Client(account_sid, auth_token)

fleet_sid = 'FLXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
fleet_service = client.preview.deployed_devices.fleets(fleet_sid)

certificate = fleet_service.certificates.create({
    'device_sid': 'THXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
    'friendly_name': 'Woody',
    'certificate_data': Path('/path/to/certificate.pem').read_text(),
})

print(certificate.sid)
// Get the Java helper library from https://twilio.com/docs/libraries/java
import com.twilio.Twilio;
import com.twilio.base.ResourceSet;
import com.twilio.rest.preview.deployedDevices.fleet;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;

public class Example {
    // Get your Account SID and Auth Token from https://twilio.com/console
    public static final String ACCOUNT_SID = "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
    public static final String AUTH_TOKEN = "your_auth_token";

    public static void main(String[] args) {
        Twilio.init(ACCOUNT_SID, AUTH_TOKEN);

        CertificateCreator certificateCreator = CertificateCreator(
            "FLXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
            new String(Files.readAllBytes(Paths.get("/path/to/certificate.pem")))
        );

        Certificate certificate = certificateCreator
            .setFriendlyName("Woody")
            .setDeviceSid("THXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX")
            .create();

        System.out.println(certificate.getSid());
    }
}
curl -u 'ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX:your_auth_token' \
  -X POST https://preview.twilio.com/DeployedDevices/Fleets/FLXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Certificates \
  -d 'DeviceSid=THXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' \
  -d 'FriendlyName=Woody' \
  --data-urlencode CertificateData@cert-file.pem
{
  "sid": "CYXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  "friendly_name": null,
  "fleet_sid": "FLXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  "account_sid": "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  "device_sid": "THXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  "thumbprint": "<supplied_certificate_fingerprint>",
  "date_created": "2017-08-14T18:23:12Z",
  "date_updated": "2017-08-14T18:23:12Z",
  "url": "https://preview.twilio.com/DeployedDevices/Fleets/FLXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Certificates/CYXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
}
Create a Certificate

On the LinkIt, you will be copying the root certificate, client certificate, and a decrypted client key to the root filesystem. Save those in a safe place for now, we'll go over those steps in detail.

Create a Sync Document

A Document is the simplest type of object in Sync (perfect for, say, tracking LED status!). You will have to create a document before you connect your LinkIt ONE to Sync. The Document name will map directly to a topic name in MQTT, where you will subscribe on the LinkIt. Be sure to name your Document 'BoardLED' (follow our capitalization).

Loading Code Samples...
Language
SDK Version:
  • 5.x
Response Format:
  • json
SDK Version:
  • 7.x
SDK Version:
  • 3.x
SDK Version:
  • 5.x
SDK Version:
  • 6.x
SDK Version:
  • 5.x
Format:
  • JSON
const accountSid = 'ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
const authToken = 'your_auth_token';
const Twilio = require('twilio').Twilio;

const client = new Twilio(accountSid, authToken);
const service = client.sync.services('default');

service.documents
  .create({
    uniqueName: 'BoardLED',
    data: { led: 'OFF' },
  })
  .then(response => {
    console.log(response);
  })
  .catch(error => {
    console.log(error);
  });
// Download the twilio-csharp library from twilio.com/docs/libraries/csharp
using System;
using Twilio;
using Twilio.Rest.Sync.V1.Service;

public class Example
{
    public static void Main(string[] args)
    {
        // Find your Account SID and Auth Token at twilio.com/console
        const string accountSid = "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
        const string authToken = "your_auth_token";
        const string serviceSid = "default";

        TwilioClient.Init(accountSid, authToken);

        var data = new
        {
            led = "OFF"
        };

        var doc = DocumentResource.Create(serviceSid,
                                          "BoardLED",
                                          data);

        Console.WriteLine(doc.Sid);
    }
}
<?php
// NOTE: This example uses the next generation Twilio helper library - for more
// information on how to download and install this version, visit
// https://www.twilio.com/docs/libraries/php
require_once 'vendor/autoload.php';

use Twilio\Rest\Client;

// Your Account SID from www.twilio.com/console
$sid = "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
// Your Auth Token from www.twilio.com/console
$token = "your_auth_token";

$client = new Client($sid, $token);

$data = array(
    'led' => "OFF"
);

$doc = $client->sync
    ->services("default")
    ->documents->create(
        array(
            'uniqueName' => "BoardLED",
            'data' => $data
        )
    );

echo $doc->sid, PHP_EOL;
require 'twilio-ruby'

# Initialize the client
account_sid = 'ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
auth_token = 'your_auth_token'
client = Twilio::REST::Client.new(account_sid, auth_token)

# Retrieve the service
service = client.sync.v1.services('default')

data = [
  '"led": "OFF"'
]

# Create the Document, data can be any JSON
response = service.documents.create(
  unique_name: 'BoardLED',
  data: "{#{data.join(',')}}"
)

puts response
# Download the Python helper library from twilio.com/docs/python/install
from twilio.rest import Client

# Your Account Sid and Auth Token from twilio.com/user/account
account_sid = "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
auth_token = "your_auth_token"
client = Client(account_sid, auth_token)

data = {
    'led': "OFF"
}

document = client.sync \
    .services("default") \
    .documents \
    .create(unique_name="BoardLED", data=data)

print(document.sid)
// Install the Java helper library from twilio.com/docs/java/install
import java.util.HashMap;
import java.util.Map;

import com.twilio.Twilio;
import com.twilio.rest.sync.v1.service.Document;

public class Example {
  // Find your Account Sid and Token at twilio.com/user/account
  public static final String ACCOUNT_SID = "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
  public static final String AUTH_TOKEN = "your_auth_token";

  public static void main(String[] args) {
    Twilio.init(ACCOUNT_SID, AUTH_TOKEN);

    Map<String, Object> data = new HashMap<>();
    data.put("led", "OFF");

    Document document = Document
        .creator("default")
        .setUniqueName("BoardLED")
        .setData(data)
        .create();

    System.out.println(document.getSid());
  }
}
curl -X POST https://sync.twilio.com/v1/Services/default/Documents \
 -d 'UniqueName=BoardLED' \
 -d 'Data={"led":"OFF"}'  \
 -u 'ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX:your_auth_token'
{
  "unique_name": "BoardLED",
  "url": "https://sync.twilio.com/v1/Services/ISXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Documents/ETXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  "created_by": "system",
  "account_sid": "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  "date_created": "2017-09-06T20:53:38Z",
  "date_updated": "2017-09-06T20:53:38Z",
  "sid": "ETXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  "service_sid": "ISXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  "data": {
    "led": "OFF"
  },
  "revision": "0",
  "links": {
    "permissions": "https://sync.twilio.com/v1/Services/ISXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Documents/ETXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Permissions"
  }
}
Use the Sync Service SID from the 'Configure Deployment' Screen, as Shown Above.
Create a Sync Document

Use the Sync Service SID from the 'Configure Deployment' Screen, as Shown Above.

We create a new document BoardLED, and initialize led key to value OFF.

Prerequisites to Use a LinkIt ONE with Sync

You can grab all of our LinkIt code quickly from Github.

For this guide's development, we used a LinkIt ONE with the Arduino IDE. The canonical guide for getting the LinkIt on the Arduino IDE can be found here on MediaTek's site.  Note that you will likely have to install the serial port driver as well; be sure to do that before attempting the steps.

We also have a blog post detailing the steps to get the LinkIt ONE working with the Arduino IDE if you are still stuck.

Install Using the Library Manager

Once you are inside the Arduino IDE, install one library from the Library Manager (menus: 'Sketch' -> 'Include Library' -> 'Library Manager' on a Mac):

  • ArduinoJSON (by Benoit Blanchon - GitHub)

This library and future updates are installed and managed directly inside the IDE.

Install Using a ZIP File

You also need to install MediaTek's aws_mbedtls_mqtt library (Github here).

  1. Download the aws_mbedtls_mqrtt library as a ZIP File (click here for the master branch ZIP)
  2. Inside of Arduino, surf to the 'Add ZIP Library' link.  For Mac, this is found in the 'Sketch' -> 'Library' submenu
  3. Find the ZIP file and install it

Add All Our Code to the Arduino IDE

Note that there are three files in this package; copy the .ino file as well as SyncLinkItHelper.cpp and SyncLinkItHelper.hpp. As you're only adding two additional files, once you have the sketch open you can also create named tabs and paste the contents inside.

Add Your Credentials to the LinkIt's File System

Above, you created a device certificate for the LinkIt ONE and downloaded an encrypted key and certificate.  You also downloaded a Root Certificate.  (You didn't?  Here is the link again: Root Certificate for LinkIt ONE Sync ).

  • Set your LinkIt ONE to 'MASS STORAGE' Mode.  The outer switch points to 'MS' (similar to updating firmware.)
  • You should see a USB disk appear in your filesystem.  Copy 'root.crt' to it.
  • Rename the CYxxxxxx.pem file to 'client.crt' and copy it to the LinkIt's root file system.
  • The CYxxxx.key file needs to be decrypted before copying to the LinkIt.  On *NIX, this is done with:
    openssl rsa -in  CYxxxxxxxxxx.key -out CYxxxxxxxxxx.key.decrypted​
    

    (Use the password tyou saved from the certificate screen)

  • Rename the decrypted file to 'client.key' and copy it to the root filesystem of the LinkIt.
  • Unplug the LinkIt ONE, switch the outer switch back to 'UART', then plug the LinkIt back into a USB port.

Choose to Connect Over GPRS or WiFi

First, modify the WIFI_USED boolean to choose GPRS (false) or WiFi (true).

Loading Code Samples...
Language
/*
 * Subscribe to a Twilio Sync Deployed Devices Document using a LinkIt ONE
 * over WiFi or Twilio Wireless with GPRS.

 * This code owes much thanks to MediaTek Labs, who have a skeleton up here:
 * 
 * https://github.com/MediaTek-Labs/aws_mbedtls_mqtt
 *
 * You'll need to install it to run our code.
 * 
 * License: This code, MIT, AWS Code: Apache (http://aws.amazon.com/apache2.0)
 */
#include <ArduinoJson.h>
#include <LTask.h>
#include <LWiFi.h>
#include <LWiFiClient.h>
#include <LGPRS.h>
#include "SyncLinkItHelper.hpp"

/* CONFIGURATION:
 *  
 * This should point at the ROOT Certificate, CLIENT Certificate,
 * and unencrypted CLIENT Key.  You can unencrypt it with (*NIX):
 *
 * openssl rsa -in  CYxxxxxxxxxx.key -out client.key
 * 
 * Name the three files root.crt, root.crt, and client.key
 * 
 * Then, flip the outer switch to 'MS' and upload the three to
 * the LinkIt's root directory.
 */
String           SYNC_ROOT_CA_FILENAME        = "root.crt";
String           SYNC_CERTIFICATE_FILENAME    = "client.crt";
String           SYNC_PRIVATE_KEY_FILENAME    = "client.key";

/* Should we use WiFi or GPRS?  'true' for WiFi, 'false' for GPRS */
boolean          WIFI_USED                    = true;

/* 
 *  Optional Settings.  
 *  You probably do not need to change these unless you change the Doc name. 
 */
const String twilio_topic                     = "sync/docs/BoardLED";
const int mqtt_tls_port                       = 8883;
String SYNC_MQTT_HOST                         = "mqtt-sync.us1.twilio.com";
String SYNC_MQTT_CLIENT_ID                    = "LinkIt_ONE";
const uint8_t LED_BUILTIN                     = 13;

/* Friendly WiFi Network details go here.  Auth choices:
 * LWIFI_OPEN, LWIFI_WPA, LWIFI_WEP
 */
#define WIFI_AP "YOUR_SSID"
#define WIFI_PASSWORD "WIFI_PASSWORD"
#define WIFI_AUTH LWIFI_WPA

/* 
 *  Twilio GPRS Settings here - you should not have to change these to 
 *  use a Twilio Programmable Wireless SIM Card.  Make sure your card 
 *  is registered, provisioned, and activated if you have issues.
 */
#define GPRS_APN "wireless.twilio.com"
#define GPRS_USERNAME NULL
#define GPRS_PASSWORD NULL

typedef int32_t mqtt_callback(MQTTCallbackParams);

// Global Twilio Lambda helper
void disconnect_function();
SyncLinkItHelper helper(
        mqtt_tls_port,
        SYNC_MQTT_HOST,
        SYNC_MQTT_CLIENT_ID,
        SYNC_ROOT_CA_FILENAME,
        SYNC_CERTIFICATE_FILENAME,
        SYNC_PRIVATE_KEY_FILENAME,
        WIFI_USED,
        disconnect_function
);

struct MQTTSub {
        char* topic;
        mqtt_callback* callback; 
};

/* 
 * Our Sync message handling callback.  This is passed as a callback function
 * when we subscribe to the Document, and will handle any incoming messages
 * on that topic (e.g., LED ON or OFF)
 */
int32_t handle_callback(MQTTCallbackParams params)
{     
        MQTTMessageParams message = params.MessageParams;

        char msg[message.PayloadLen+1];
        memcpy (msg,message.pPayload,message.PayloadLen);
        StaticJsonBuffer<maxMQTTpackageSize> jsonBuffer;

        Serial.print("Incoming message from Twilio:");
        Serial.println(msg);
        
        JsonObject& root = jsonBuffer.parseObject(msg);
        String led           = root["led"];
        if (led == "ON") {
                digitalWrite(LED_BUILTIN, HIGH);
        } else {
                digitalWrite(LED_BUILTIN, LOW);          
        }

        return 0;
}

/* 
 *  Main setup function.
 *  
 *  Here we connect to either GPRS or WiFi, then Deployed Devices.  We then 
 *  subscribe to the Document and listen for updates.
 */
void setup()
{
        LTask.begin();
        pinMode(LED_BUILTIN, OUTPUT);
        
        Serial.begin(115200);
        while(!Serial) {
                // Busy wait on Serial Monitor connection.
                delay(100);
        }

  
        if (WIFI_USED){
                LWiFi.begin();
                Serial.println("Connecting to AP");
                Serial.flush();
                while (!LWiFi.connect(
                                WIFI_AP, 
                                LWiFiLoginInfo(WIFI_AUTH, WIFI_PASSWORD)
                      )
                ) {
                        Serial.print(".");
                        Serial.flush();
                        delay(500);
                }
        } else {  
                Serial.println("Connecting to GPRS");
                Serial.flush();
                while (!LGPRS.attachGPRS(
                                GPRS_APN, 
                                GPRS_USERNAME, 
                                GPRS_PASSWORD
                      )
                ) {
                        Serial.println(".");
                        Serial.flush();
                        delay(500);
                }
        }

        Serial.println("Connected to the internet!");
        VMINT port = mqtt_tls_port;
        CONNECT_PORT = port;
        
        LTask.remoteCall(&__wifi_dns, (void*)SYNC_MQTT_HOST.c_str());
        LTask.remoteCall(&__bearer_open, NULL);
        LTask.remoteCall(&__mqtt_start, NULL);

        MQTTSub sub_struct;
        sub_struct.topic = const_cast<char*>(twilio_topic.c_str());
        sub_struct.callback = handle_callback;
        
        LTask.remoteCall(&__sub_mqtt, (void*)&sub_struct);
}

/*  
 *   Every time through the main loop we will spin up a new thread on the 
 *   LinkIt to perform our watchdog tasks in the background.  Insert everything
 *   you want to perform over and over again until infinity (or power 
 *   loss!) here.
*/
boolean main_thread(void* user_data) 
{
        Serial.flush();
        helper.handle_requests();
        delay(1000);

        // Example on how to publish to a Sync Document
        // (uncomment lines between the /* */)
        /*
        static uint32_t counter = 0;
        ++counter;
        if (counter == 10) {
                Serial.println("Sending message to Twilio.");
                helper.publish_to_topic(twilio_topic.c_str(), "{\"msg\":\"Ahoy!\",\"led\":\"ON\"}\0");
                counter = 0;
        }
        */
}

/*
 * This example creates a new thread which calls main_thread() every 3 seconds.
 */
void loop() 
{
        Serial.flush();
        LTask.remoteCall(main_thread, NULL);
        delay(3000);
}

/* 
 *  Trampolines/thunks are the easiest way to pass these class methods.  
 *  We don't have std::bind() or boost::bind()!
 */
inline boolean __bearer_open(void* ctx) 
{ return helper.bearer_open(ctx); }

inline boolean __mqtt_start(void* ctx)  
{ return helper.start_mqtt(ctx); }

inline boolean __wifi_dns(void* ctx)    
{ return helper.wifiResolveDomainName(ctx); }

inline boolean __sub_mqtt(void *ctx)   
{ 
        MQTTSub* sub_struct = (MQTTSub*)ctx; char* topic = sub_struct->topic;
        mqtt_callback* callback = sub_struct->callback;
        helper.subscribe_to_topic(topic, callback);
        return true;
}

/* MQTT Disconnect callback function */
void disconnect_function() 
{
        Serial.println("Oh no, we disconnected!"); while(1);
}

/* Workaround to remove a Macro from mbedtls */
#ifdef connect
#undef connect
#endif
If you aren't using GPRS, edit the WiFi SSID and password to connect to a friendly network.
Optionally Add Your WiFi Credentials to the LinkIt Code

If you aren't using GPRS, edit the WiFi SSID and password to connect to a friendly network.

If you choose GPRS with Twilio Programmable Wireless, everything  should be good to go assuming you have a working SIM card inserted. You don't need to change and of the GPRS_* variables, but double check your status in the Programmable Wireless console.

If you choose WiFi, also edit the WIFI_AP and WIFI_PASSWORD variables with your WiFi network's SSID and password, respectively. If you are not using WPA security, also edit WIFI_AUTH.

Burn the Code to the LinkIt and Toggle the LED

We're getting close now - it's time to upload everything to the board.

Edits done, compile and upload the code to the LinkIt ONE. Open the Arduino Serial Monitor (the menu 'Tools' -> 'Serial Monitor'). You should see some signs of life assuming you followed the steps above.

But wait - that's not the demo!  Let's blink that onboard LED.  

Set 'led' to 'ON' in the Document you created above.

Loading Code Samples...
Language
SDK Version:
  • 5.x
Response Format:
  • json
SDK Version:
  • 7.x
SDK Version:
  • 3.x
SDK Version:
  • 5.x
SDK Version:
  • 6.x
SDK Version:
  • 5.x
Format:
  • JSON
const accountSid = 'ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
const authToken = 'your_auth_token';
const Twilio = require('twilio').Twilio;

const client = new Twilio(accountSid, authToken);
const service = client.sync.services('default');

service
  .documents('BoardLED')
  .update({
    data: { led: 'ON' },
  })
  .then(response => {
    console.log(response);
  })
  .catch(error => {
    console.log(error);
  });
// Download the twilio-csharp library from twilio.com/docs/libraries/csharp
using System;
using Twilio;
using Twilio.Rest.Sync.V1.Service;

public class Example
{
    public static void Main(string[] args)
    {
        // Find your Account SID and Auth Token at twilio.com/console
        const string accountSid = "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
        const string authToken = "your_auth_token";
        const string serviceSid = "default";

        TwilioClient.Init(accountSid, authToken);

        var data = new
        {
            led = "ON"
        };

        var doc = DocumentResource.Update(serviceSid,
                                          "BoardLED",
                                          data);

        Console.WriteLine(doc.Data);
    }
}
<?php
// NOTE: This example uses the next generation Twilio helper library - for more
// information on how to download and install this version, visit
// https://www.twilio.com/docs/libraries/php
require_once 'vendor/autoload.php';

use Twilio\Rest\Client;

// Your Account SID from www.twilio.com/console
$sid = "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
// Your Auth Token from www.twilio.com/console
$token = "your_auth_token";

$client = new Client($sid, $token);

$data = array(
    'led' => "ON"
);

$doc = $client->sync
    ->services("default")
    ->documents("BoardLED")->update(
        array(
            'led' => $data
        )
    );

print_r($doc->data);
echo PHP_EOL;
require 'twilio-ruby'

# Initialize the client
account_sid = 'ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
auth_token = 'your_auth_token'
client = Twilio::REST::Client.new(account_sid, auth_token)

# Retreive the service
service = client.sync.v1.services('default')

# Update the Document, data can be any JSON
response = service.documents('BoardLED').update(
  data: '{ "led": "ON" }'
)

puts response
# Download the Python helper library from twilio.com/docs/python/install
from twilio.rest import Client

# Your Account Sid and Auth Token from twilio.com/user/account
account_sid = "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
auth_token = "your_auth_token"
client = Client(account_sid, auth_token)

new_data = {
    'led': "ON"
}

document = client.sync \
    .services("default") \
    .documents("BoardLED") \
    .update(data=new_data)

print(document.data)
// Install the Java helper library from twilio.com/docs/java/install
import java.util.HashMap;
import java.util.Map;

import com.twilio.Twilio;
import com.twilio.rest.sync.v1.service.Document;

public class Example {
  // Find your Account Sid and Token at twilio.com/user/account
  public static final String ACCOUNT_SID = "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
  public static final String AUTH_TOKEN = "your_auth_token";

  public static final String SERVICE_SID = "default";

  public static void main(String[] args) {
    Twilio.init(ACCOUNT_SID, AUTH_TOKEN);

    Map<String, Object> data = new HashMap<>();
    data.put("led", "ON");

    Document document = Document.updater(SERVICE_SID, "BoardLED", data).update();

    System.out.println(document.getData());
  }
}
curl -X POST https://sync.twilio.com/v1/Services/default/Documents/BoardLED \
 -d 'Data={"led":"ON"}'  \
 -u 'ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX:your_auth_token'
{
  "unique_name": "BoardLED",
  "url": "https://sync.twilio.com/v1/Services/ISXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Documents/ETXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  "created_by": "system",
  "account_sid": "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  "date_created": "2017-09-06T20:53:38Z",
  "date_updated": "2017-09-06T20:55:21Z",
  "sid": "ETXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  "service_sid": "ISXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  "data": {
    "led": "ON"
  },
  "revision": "1",
  "links": {
    "permissions": "https://sync.twilio.com/v1/Services/ISXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Documents/ETXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Permissions"
  }
}
Update a BoardLED Document

You should quickly see three signs your API Request went through:

  • Sync lets you know the command was successful
  • The onboard LED will light
  • The LinkIt ONE will give you a success message over serial

LinkIt ONE Blinking Over Sync

Sending Updates Back to Sync from the LinkIt

If you look in the main_thread(void* user_data) function in the .ino file, there are commented lines which would send updates back from the LinkIt to the document. Remove the comment block to send a msg back to Sync periodically.

Loading Code Samples...
Language
/*
 * Subscribe to a Twilio Sync Deployed Devices Document using a LinkIt ONE
 * over WiFi or Twilio Wireless with GPRS.

 * This code owes much thanks to MediaTek Labs, who have a skeleton up here:
 * 
 * https://github.com/MediaTek-Labs/aws_mbedtls_mqtt
 *
 * You'll need to install it to run our code.
 * 
 * License: This code, MIT, AWS Code: Apache (http://aws.amazon.com/apache2.0)
 */
#include <ArduinoJson.h>
#include <LTask.h>
#include <LWiFi.h>
#include <LWiFiClient.h>
#include <LGPRS.h>
#include "SyncLinkItHelper.hpp"

/* CONFIGURATION:
 *  
 * This should point at the ROOT Certificate, CLIENT Certificate,
 * and unencrypted CLIENT Key.  You can unencrypt it with (*NIX):
 *
 * openssl rsa -in  CYxxxxxxxxxx.key -out client.key
 * 
 * Name the three files root.crt, root.crt, and client.key
 * 
 * Then, flip the outer switch to 'MS' and upload the three to
 * the LinkIt's root directory.
 */
String           SYNC_ROOT_CA_FILENAME        = "root.crt";
String           SYNC_CERTIFICATE_FILENAME    = "client.crt";
String           SYNC_PRIVATE_KEY_FILENAME    = "client.key";

/* Should we use WiFi or GPRS?  'true' for WiFi, 'false' for GPRS */
boolean          WIFI_USED                    = true;

/* 
 *  Optional Settings.  
 *  You probably do not need to change these unless you change the Doc name. 
 */
const String twilio_topic                     = "sync/docs/BoardLED";
const int mqtt_tls_port                       = 8883;
String SYNC_MQTT_HOST                         = "mqtt-sync.us1.twilio.com";
String SYNC_MQTT_CLIENT_ID                    = "LinkIt_ONE";
const uint8_t LED_BUILTIN                     = 13;

/* Friendly WiFi Network details go here.  Auth choices:
 * LWIFI_OPEN, LWIFI_WPA, LWIFI_WEP
 */
#define WIFI_AP "YOUR_SSID"
#define WIFI_PASSWORD "WIFI_PASSWORD"
#define WIFI_AUTH LWIFI_WPA

/* 
 *  Twilio GPRS Settings here - you should not have to change these to 
 *  use a Twilio Programmable Wireless SIM Card.  Make sure your card 
 *  is registered, provisioned, and activated if you have issues.
 */
#define GPRS_APN "wireless.twilio.com"
#define GPRS_USERNAME NULL
#define GPRS_PASSWORD NULL

typedef int32_t mqtt_callback(MQTTCallbackParams);

// Global Twilio Lambda helper
void disconnect_function();
SyncLinkItHelper helper(
        mqtt_tls_port,
        SYNC_MQTT_HOST,
        SYNC_MQTT_CLIENT_ID,
        SYNC_ROOT_CA_FILENAME,
        SYNC_CERTIFICATE_FILENAME,
        SYNC_PRIVATE_KEY_FILENAME,
        WIFI_USED,
        disconnect_function
);

struct MQTTSub {
        char* topic;
        mqtt_callback* callback; 
};

/* 
 * Our Sync message handling callback.  This is passed as a callback function
 * when we subscribe to the Document, and will handle any incoming messages
 * on that topic (e.g., LED ON or OFF)
 */
int32_t handle_callback(MQTTCallbackParams params)
{     
        MQTTMessageParams message = params.MessageParams;

        char msg[message.PayloadLen+1];
        memcpy (msg,message.pPayload,message.PayloadLen);
        StaticJsonBuffer<maxMQTTpackageSize> jsonBuffer;

        Serial.print("Incoming message from Twilio:");
        Serial.println(msg);
        
        JsonObject& root = jsonBuffer.parseObject(msg);
        String led           = root["led"];
        if (led == "ON") {
                digitalWrite(LED_BUILTIN, HIGH);
        } else {
                digitalWrite(LED_BUILTIN, LOW);          
        }

        return 0;
}

/* 
 *  Main setup function.
 *  
 *  Here we connect to either GPRS or WiFi, then Deployed Devices.  We then 
 *  subscribe to the Document and listen for updates.
 */
void setup()
{
        LTask.begin();
        pinMode(LED_BUILTIN, OUTPUT);
        
        Serial.begin(115200);
        while(!Serial) {
                // Busy wait on Serial Monitor connection.
                delay(100);
        }

  
        if (WIFI_USED){
                LWiFi.begin();
                Serial.println("Connecting to AP");
                Serial.flush();
                while (!LWiFi.connect(
                                WIFI_AP, 
                                LWiFiLoginInfo(WIFI_AUTH, WIFI_PASSWORD)
                      )
                ) {
                        Serial.print(".");
                        Serial.flush();
                        delay(500);
                }
        } else {  
                Serial.println("Connecting to GPRS");
                Serial.flush();
                while (!LGPRS.attachGPRS(
                                GPRS_APN, 
                                GPRS_USERNAME, 
                                GPRS_PASSWORD
                      )
                ) {
                        Serial.println(".");
                        Serial.flush();
                        delay(500);
                }
        }

        Serial.println("Connected to the internet!");
        VMINT port = mqtt_tls_port;
        CONNECT_PORT = port;
        
        LTask.remoteCall(&__wifi_dns, (void*)SYNC_MQTT_HOST.c_str());
        LTask.remoteCall(&__bearer_open, NULL);
        LTask.remoteCall(&__mqtt_start, NULL);

        MQTTSub sub_struct;
        sub_struct.topic = const_cast<char*>(twilio_topic.c_str());
        sub_struct.callback = handle_callback;
        
        LTask.remoteCall(&__sub_mqtt, (void*)&sub_struct);
}

/*  
 *   Every time through the main loop we will spin up a new thread on the 
 *   LinkIt to perform our watchdog tasks in the background.  Insert everything
 *   you want to perform over and over again until infinity (or power 
 *   loss!) here.
*/
boolean main_thread(void* user_data) 
{
        Serial.flush();
        helper.handle_requests();
        delay(1000);

        // Example on how to publish to a Sync Document
        // (uncomment lines between the /* */)
        /*
        static uint32_t counter = 0;
        ++counter;
        if (counter == 10) {
                Serial.println("Sending message to Twilio.");
                helper.publish_to_topic(twilio_topic.c_str(), "{\"msg\":\"Ahoy!\",\"led\":\"ON\"}\0");
                counter = 0;
        }
        */
}

/*
 * This example creates a new thread which calls main_thread() every 3 seconds.
 */
void loop() 
{
        Serial.flush();
        LTask.remoteCall(main_thread, NULL);
        delay(3000);
}

/* 
 *  Trampolines/thunks are the easiest way to pass these class methods.  
 *  We don't have std::bind() or boost::bind()!
 */
inline boolean __bearer_open(void* ctx) 
{ return helper.bearer_open(ctx); }

inline boolean __mqtt_start(void* ctx)  
{ return helper.start_mqtt(ctx); }

inline boolean __wifi_dns(void* ctx)    
{ return helper.wifiResolveDomainName(ctx); }

inline boolean __sub_mqtt(void *ctx)   
{ 
        MQTTSub* sub_struct = (MQTTSub*)ctx; char* topic = sub_struct->topic;
        mqtt_callback* callback = sub_struct->callback;
        helper.subscribe_to_topic(topic, callback);
        return true;
}

/* MQTT Disconnect callback function */
void disconnect_function() 
{
        Serial.println("Oh no, we disconnected!"); while(1);
}

/* Workaround to remove a Macro from mbedtls */
#ifdef connect
#undef connect
#endif
Comment out these lines to periodically update the BoardLED Document from the LinkIt ONE.
Optionally Send Data Back to Sync

Comment out these lines to periodically update the BoardLED Document from the LinkIt ONE.

Whatever you send back to Sync should be in JSON format.  You can either generate JSON through the ArduinoJSON library or craft it inline like we've done here.

Link(It)ing Your Internet of Things

Very simple, right? Blinky lights, Sync Documents, powerful infrastructure - and zero wires!

While we know that your application isn't just blinking that single LED, the infrastructure you now have in place is ready for wherever you want to take it. You can scale out to many more devices or build up a backend dashboard or... well, the or is on you.  

Let us know where your imagination and your business takes you - we'll be watching for your tweets on Twitter!

Need some help?

We all do sometimes; code is hard. Get help now from our support team, or lean on the wisdom of the crowd browsing the Twilio tag on Stack Overflow.

1 / 1
Loading Code Samples...
SDK Version:
  • 5.x
Response Format:
  • json
SDK Version:
  • 7.x
SDK Version:
  • 3.x
SDK Version:
  • 5.x
SDK Version:
  • 6.x
SDK Version:
  • 5.x
Format:
  • JSON
const accountSid = 'ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
const authToken = 'your_auth_token';
const Twilio = require('twilio').Twilio;

const client = new Twilio(accountSid, authToken);

client.preview.deployed_devices.fleets
  .create({
    friendlyName: 'My Fleet of Devices',
  })
  .then(response => {
    console.log(response);
  })
  .catch(error => {
    console.log(error);
  });
// Get the C# helper library from https://twilio.com/docs/libraries/csharp
using System;
using System.Collections.Generic;
using Twilio;
using Twilio.Rest.Preview.DeployedDevices;

public class Example
{
    public static void Main(string[] args)
    {
        // Get your Account SID and Auth Token from https://twilio.com/console
        const string accountSid = "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
        const string authToken = "your_auth_token";
        TwilioClient.Init(accountSid, authToken);

        var fleet = FleetResource.Create(
            friendlyName: "My Fleet of Devices"
        );

        Console.WriteLine(fleet.Sid);
    }
}
<?php
// Get the PHP helper library from https://twilio.com/docs/libraries/php
require_once '/path/to/vendor/autoload.php'; // Loads the library

use Twilio\Rest\Client;

// Get your Account SID and Auth Token from https://twilio.com/console
$accountSid = 'ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
$authToken = 'your_auth_token';
$client = new Client($accountSid, $authToken);

$fleet = $client->preview->deployedDevices->fleets->create(
  array(
    'friendlyName' => 'My Fleet of Devices'
  )
);

echo $fleet->sid;
# Get the Ruby helper library from https://twilio.com/docs/libraries/ruby
require 'twilio-ruby'

# Get your Account SID and Auth Token from https://twilio.com/console
account_sid = 'ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
auth_token = 'your_auth_token'
client = Twilio::REST::Client.new(account_sid, auth_token)

fleet = client.preview.deployed_devices.fleets.create(
  friendly_name: 'My Fleet of Devices'
)

puts fleet.sid
# Get the Python helper library from https://twilio.com/docs/libraries/python
from twilio.rest import Client

# Get your Account SID and Auth Token from https://twilio.com/console
account_sid = 'ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
auth_token = 'your_auth_token'
client = Client(account_sid, auth_token)

fleet = client.preview.deployed_devices.fleets.create(
    friendly_name='My Fleet of Devices')

print(fleet.sid)
// Get the Java helper library from https://twilio.com/docs/libraries/java
import com.twilio.Twilio;
import com.twilio.rest.preview.deployedDevices.Fleet;
import com.twilio.rest.preview.deployedDevices.FleetCreator;

public class Example {
    // Get your Account SID and Auth Token from https://twilio.com/console
    public static final String ACCOUNT_SID = "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
    public static final String AUTH_TOKEN = "your_auth_token";

    public static void main(String[] args) {
        Twilio.init(ACCOUNT_SID, AUTH_TOKEN);

        FleetCreator fleetCreator = new FleetCreator();
        Fleet fleet = fleetCreator
                .setFriendlyName("My Fleet of Devices")
                .create();

        System.out.println(fleet.getSid());
    }
}
curl -u 'ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX:your_auth_token' \
  -X POST https://preview.twilio.com/DeployedDevices/Fleets
{
  "sid": "FLXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  "friendly_name": null,
  "account_sid": "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  "default_deployment_sid": "DLXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  "date_created": "2017-08-14T15:25:45Z",
  "date_updated": "2017-08-14T15:25:45Z",
  "url": "https://preview.twilio.com/DeployedDevices/Fleets/FLXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  "links": {
    "certificates": "https://preview.twilio.com/DeployedDevices/Fleets/FLXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Certificates",
    "keys": "https://preview.twilio.com/DeployedDevices/Fleets/FLXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Keys",
    "devices": "https://preview.twilio.com/DeployedDevices/Fleets/FLXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Devices",
    "deployments": "https://preview.twilio.com/DeployedDevices/Fleets/FLXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Deployments"
  }
}
SDK Version:
  • 5.x
Response Format:
  • json
SDK Version:
  • 7.x
SDK Version:
  • 3.x
SDK Version:
  • 5.x
SDK Version:
  • 6.x
SDK Version:
  • 5.x
Format:
  • JSON
const accountSid = 'ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
const authToken = 'your_auth_token';
const Twilio = require('twilio').Twilio;

const client = new Twilio(accountSid, authToken);
const fleet = client.preview.deployed_devices.fleets(
  'FLXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
);

fleet
  .deployments('FLXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX')
  .update({
    friendlyName: 'My New Device Deployment',
    syncServiceSid: 'ISXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
  })
  .then(response => {
    console.log(response);
  })
  .catch(error => {
    console.log(error);
  });
// Get the C# helper library from https://twilio.com/docs/libraries/csharp
using System;
using System.Collections.Generic;
using Twilio;
using Twilio.Rest.Preview.DeployedDevices;

public class Example
{
    public static void Main(string[] args)
    {
        // Get your Account SID and Auth Token from https://twilio.com/console
        const string accountSid = "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
        const string authToken = "your_auth_token";
        TwilioClient.Init(accountSid, authToken);

        const string deploymentSid = "DLXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
        var deployment = DeploymentResource.Update(
            deploymentSid,
            friendlyName: "My New Device Deployment");

        Console.WriteLine(deploymentSid.FriendlyName);
    }
}
<?php
// Get the PHP helper library from https://twilio.com/docs/libraries/php
require_once '/path/to/vendor/autoload.php'; // Loads the library

use Twilio\Rest\Client;

// Get your Account SID and Auth Token from https://twilio.com/console
$accountSid = 'ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
$authToken = 'your_auth_token';
$client = new Client($accountSid, $authToken);

$deploymentSid = 'DLXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
$deployment = $client->preview->deployedDevices->deployments($deploymentSid)->update(
  array(
    'friendlyName' => 'My New Device Deployment'
  )
);

echo $deployment->friendlyName;
# Get the Ruby helper library from https://twilio.com/docs/libraries/ruby
require 'twilio-ruby'

# Get your Account SID and Auth Token from https://twilio.com/console
account_sid = 'ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
auth_token = 'your_auth_token'
client = Twilio::REST::Client.new(account_sid, auth_token)

deployment_sid = 'DLXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
deployment = client.preview.deployed_devices
                   .deployments(deployment_sid)
                   .update(friendly_name: 'My New Device Deployment')

puts deployment.friendly_name
# Get the Python helper library from https://twilio.com/docs/libraries/python
from twilio.rest import Client

# Get your Account SID and Auth Token from https://twilio.com/console
account_sid = 'ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
auth_token = 'your_auth_token'
client = Client(account_sid, auth_token)

fleet_sid = 'FLXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
deployment_sid = 'DLXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
deployment = client.preview\
                   .deployed_devices\
                   .fleets(fleet_sid)\
                   .deployments(sid=deployment_sid)\
                   .update(friendly_name='My New Device Deployment')

print(deployment.friendly_name)
// Get the Java helper library from https://twilio.com/docs/libraries/java
import com.twilio.Twilio;
import com.twilio.rest.preview.deployedDevices.Deployment;
import com.twilio.rest.preview.deployedDevices.DeploymentUpdater;

public class Example {
    // Get your Account SID and Auth Token from https://twilio.com/console
    public static final String ACCOUNT_SID = "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
    public static final String AUTH_TOKEN = "your_auth_token";

    public static void main(String[] args) {
        Twilio.init(ACCOUNT_SID, AUTH_TOKEN);

        String deploymentSid = "DLXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";

        Deployment deployment = new DeploymentUpdater(deploymentSid)
                .setFriendlyName("My New Device Deployment")
                .update();

        System.out.println(deployment.getFriendlyName());
    }
}
curl -u 'ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX:your_auth_token' \
  -X POST https://preview.twilio.com/DeployedDevices/Fleets/FLXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Deployments/DLXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX \
  -d 'FriendlyName=My New Device Deployment' \
  -d 'SyncServiceSid=ISXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
{
  "sid": "DLXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  "friendly_name": "My New Device Deployment",
  "fleet_sid": "FLXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  "account_sid": "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  "sync_service_sid": "ISXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  "date_created": "2017-08-14T15:44:05Z",
  "date_updated": "2017-08-14T15:55:25Z",
  "url": "https://preview.twilio.com/DeployedDevices/Fleets/FLXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Deployments/DLXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
}
SDK Version:
  • 5.x
Response Format:
  • json
SDK Version:
  • 7.x
SDK Version:
  • 3.x
SDK Version:
  • 5.x
SDK Version:
  • 6.x
SDK Version:
  • 5.x
Format:
  • JSON
// Get the Node helper library from https://twilio.com/docs/libraries/node
const fs = require('fs');
const Twilio = require('twilio').Twilio;

// Get your Account SID and Auth Token from https://twilio.com/console
const accountSid = 'ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
const authToken = 'your_auth_token';
const client = new Twilio(accountSid, authToken);

const fleetSid = 'FLXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
const fleetService = client.preview.deployed_devices.fleets(fleetSid);

fleetService.devices
  .create({
    friendlyName: 'My Device #1',
  })
  .then(response => {
    console.log(response);
  })
  .catch(error => {
    console.log(error);
  });
// Get the C# helper library from https://twilio.com/docs/libraries/csharp
using System;
using System.Collections.Generic;
using Twilio;
using Twilio.Rest.Preview.DeployedDevices.Fleet

public class Example
{
    public static void Main(string[] args)
    {
        // Get your Account SID and Auth Token from https://twilio.com/console
        const string accountSid = "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
        const string authToken = "your_auth_token";
        TwilioClient.Init(accountSid, authToken);

        var device = DeviceResource.Create(
            pathFleetSid: "FLXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
            friendlyName: "My Device #1"
        );

        Console.WriteLine(device.Sid);
    }
}
<?php
// Get the PHP helper library from https://twilio.com/docs/libraries/php
require_once '/path/to/vendor/autoload.php'; // Loads the library

use Twilio\Rest\Client;

// Get your Account SID and Auth Token from https://twilio.com/console
$accountSid = 'ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
$authToken = 'your_auth_token';
$client = new Client($sid, $token);

$fleetSid = 'FLXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
$fleetService = $client->preview->deployedDevices->fleets($fleetSid);

$device = $fleetService->devices->create([
    'friendlyName' => 'My Device #1'
]);

echo $device->sid;
# Get the Ruby helper library from https://twilio.com/docs/libraries/ruby
require 'twilio-ruby'

# Get your Account SID and Auth Token from https://twilio.com/console
account_sid = 'ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
auth_token = 'your_auth_token'
client = Twilio::REST::Client.new(account_sid, auth_token)

fleet_sid = 'FLXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
fleet_service = client.preview.deployed_devices.fleets(fleet_sid)

device = fleet_service.devices.create(
  friendly_name: 'My Device #1'
)

puts device.sid
# Get the Python helper library from https://twilio.com/docs/libraries/python
from twilio.rest import Client

# Get your Account SID and Auth Token from https://twilio.com/console
account_sid = 'ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
auth_token = 'your_auth_token'
client = Client(account_sid, auth_token)

fleet_sid = 'FLXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
fleet_service = client.preview.deployed_devices.fleets(fleet_sid)

device = fleet_service.devices.create(friendly_name='My Device #1')

print(device.sid)
// Get the Java helper library from https://twilio.com/docs/libraries/java
import com.twilio.Twilio;
import com.twilio.base.ResourceSet;
import com.twilio.rest.preview.deployedDevices.fleet;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;

public class Example {
    // Get your Account SID and Auth Token from https://twilio.com/console
    public static final String ACCOUNT_SID = "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
    public static final String AUTH_TOKEN = "your_auth_token";

    public static void main(String[] args) {
        Twilio.init(ACCOUNT_SID, AUTH_TOKEN);

        Device device = DeviceCreator("FLXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
            .setFriendlyName("My Device #1")
            .create();

        System.out.println(device.getSid());
    }
}
curl -u 'ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX:your_auth_token' \
  -X POST https://preview.twilio.com/DeployedDevices/Fleets/FLXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Devices \
  -d 'FriendlyName=My Device #1'
{
  "sid": "THXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  "friendly_name": "My Device #1",
  "unique_name": null,
  "fleet_sid": "FLXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  "account_sid": "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  "deployment_sid": "DLXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  "identity": null,
  "enabled": true,
  "date_created": "2017-08-14T19:19:30Z",
  "date_updated": "2017-08-14T19:19:30Z",
  "date_authenticated": null,
  "url": "https://preview.twilio.com/DeployedDevices/Fleets/FLXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Devices/THXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
}
SDK Version:
  • 5.x
Response Format:
  • json
SDK Version:
  • 7.x
SDK Version:
  • 3.x
SDK Version:
  • 5.x
SDK Version:
  • 6.x
SDK Version:
  • 5.x
Format:
  • JSON
// Get the Node helper library from https://twilio.com/docs/libraries/node
const fs = require('fs');
const Twilio = require('twilio').Twilio;

// Get your Account SID and Auth Token from https://twilio.com/console
const accountSid = 'ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
const authToken = 'your_auth_token';
const client = new Twilio(accountSid, authToken);

const fleetSid = 'FLXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
const fleetService = client.preview.deployed_devices.fleets(fleetSid);

fleetService.certificates
  .create({
    deviceSid: 'THXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
    friendlyName: 'Woody',
    certificateData: fs.readFileSync('/path/to/certificate.pem'),
  })
  .then(response => {
    console.log(response);
  })
  .catch(error => {
    console.log(error);
  });
// Get the C# helper library from https://twilio.com/docs/libraries/csharp
using System;
using System.Collections.Generic;
using Twilio;
using Twilio.Rest.Preview.DeployedDevices.Fleet

public class Example
{
    public static void Main(string[] args)
    {
        // Get your Account SID and Auth Token from https://twilio.com/console
        const string accountSid = "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
        const string authToken = "your_auth_token";
        TwilioClient.Init(accountSid, authToken);

        const string certificatePath = @"C:\path\to\certificate.pem";
        var certificate = CertificateResource.Create(
            pathFleetSid: "FLXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
            deviceSid: "THXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
            friendlyName: "Woody",
            certificateData: System.IO.File.ReadAllText(certificatePath)
        );

        Console.WriteLine(certificate.Sid);
    }
}
<?php
// Get the PHP helper library from https://twilio.com/docs/libraries/php
require_once '/path/to/vendor/autoload.php'; // Loads the library

use Twilio\Rest\Client;

// Get your Account SID and Auth Token from https://twilio.com/console
$accountSid = 'ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
$authToken = 'your_auth_token';
$client = new Client($sid, $token);

$fleetSid = 'FLXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
$fleetService = $client->preview->deployedDevices->fleets($fleetSid);

$certificateContent = file_get_contents('/path/to/certificate.pem');
$certificate = $fleetService->create($certificateContent, [
    'deviceSid' => 'THXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
    'friendlyName' => 'Woody',
]);

echo $certificate->sid;
# Get the Ruby helper library from https://twilio.com/docs/libraries/ruby
require 'twilio-ruby'

# Get your Account SID and Auth Token from https://twilio.com/console
account_sid = 'ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
auth_token = 'your_auth_token'
client = Twilio::REST::Client.new(account_sid, auth_token)

fleet_sid = 'FLXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
fleet_service = client.preview.deployed_devices.fleets(fleet_sid)

certificate = fleet_service.certificates.create(
  device_sid: 'THXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
  friendly_name: 'Woody',
  certificate_data: IO.read('/path/to/certificate.pem')
)

puts certificate.sid
# Get the Python helper library from https://twilio.com/docs/libraries/python
from pathlib import Path
from twilio.rest import Client

# Get your Account SID and Auth Token from https://twilio.com/console
account_sid = 'ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
auth_token = 'your_auth_token'
client = Client(account_sid, auth_token)

fleet_sid = 'FLXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
fleet_service = client.preview.deployed_devices.fleets(fleet_sid)

certificate = fleet_service.certificates.create({
    'device_sid': 'THXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
    'friendly_name': 'Woody',
    'certificate_data': Path('/path/to/certificate.pem').read_text(),
})

print(certificate.sid)
// Get the Java helper library from https://twilio.com/docs/libraries/java
import com.twilio.Twilio;
import com.twilio.base.ResourceSet;
import com.twilio.rest.preview.deployedDevices.fleet;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;

public class Example {
    // Get your Account SID and Auth Token from https://twilio.com/console
    public static final String ACCOUNT_SID = "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
    public static final String AUTH_TOKEN = "your_auth_token";

    public static void main(String[] args) {
        Twilio.init(ACCOUNT_SID, AUTH_TOKEN);

        CertificateCreator certificateCreator = CertificateCreator(
            "FLXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
            new String(Files.readAllBytes(Paths.get("/path/to/certificate.pem")))
        );

        Certificate certificate = certificateCreator
            .setFriendlyName("Woody")
            .setDeviceSid("THXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX")
            .create();

        System.out.println(certificate.getSid());
    }
}
curl -u 'ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX:your_auth_token' \
  -X POST https://preview.twilio.com/DeployedDevices/Fleets/FLXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Certificates \
  -d 'DeviceSid=THXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' \
  -d 'FriendlyName=Woody' \
  --data-urlencode CertificateData@cert-file.pem
{
  "sid": "CYXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  "friendly_name": null,
  "fleet_sid": "FLXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  "account_sid": "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  "device_sid": "THXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  "thumbprint": "<supplied_certificate_fingerprint>",
  "date_created": "2017-08-14T18:23:12Z",
  "date_updated": "2017-08-14T18:23:12Z",
  "url": "https://preview.twilio.com/DeployedDevices/Fleets/FLXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Certificates/CYXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
}
SDK Version:
  • 5.x
Response Format:
  • json
SDK Version:
  • 7.x
SDK Version:
  • 3.x
SDK Version:
  • 5.x
SDK Version:
  • 6.x
SDK Version:
  • 5.x
Format:
  • JSON
const accountSid = 'ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
const authToken = 'your_auth_token';
const Twilio = require('twilio').Twilio;

const client = new Twilio(accountSid, authToken);
const service = client.sync.services('default');

service.documents
  .create({
    uniqueName: 'BoardLED',
    data: { led: 'OFF' },
  })
  .then(response => {
    console.log(response);
  })
  .catch(error => {
    console.log(error);
  });
// Download the twilio-csharp library from twilio.com/docs/libraries/csharp
using System;
using Twilio;
using Twilio.Rest.Sync.V1.Service;

public class Example
{
    public static void Main(string[] args)
    {
        // Find your Account SID and Auth Token at twilio.com/console
        const string accountSid = "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
        const string authToken = "your_auth_token";
        const string serviceSid = "default";

        TwilioClient.Init(accountSid, authToken);

        var data = new
        {
            led = "OFF"
        };

        var doc = DocumentResource.Create(serviceSid,
                                          "BoardLED",
                                          data);

        Console.WriteLine(doc.Sid);
    }
}
<?php
// NOTE: This example uses the next generation Twilio helper library - for more
// information on how to download and install this version, visit
// https://www.twilio.com/docs/libraries/php
require_once 'vendor/autoload.php';

use Twilio\Rest\Client;

// Your Account SID from www.twilio.com/console
$sid = "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
// Your Auth Token from www.twilio.com/console
$token = "your_auth_token";

$client = new Client($sid, $token);

$data = array(
    'led' => "OFF"
);

$doc = $client->sync
    ->services("default")
    ->documents->create(
        array(
            'uniqueName' => "BoardLED",
            'data' => $data
        )
    );

echo $doc->sid, PHP_EOL;
require 'twilio-ruby'

# Initialize the client
account_sid = 'ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
auth_token = 'your_auth_token'
client = Twilio::REST::Client.new(account_sid, auth_token)

# Retrieve the service
service = client.sync.v1.services('default')

data = [
  '"led": "OFF"'
]

# Create the Document, data can be any JSON
response = service.documents.create(
  unique_name: 'BoardLED',
  data: "{#{data.join(',')}}"
)

puts response
# Download the Python helper library from twilio.com/docs/python/install
from twilio.rest import Client

# Your Account Sid and Auth Token from twilio.com/user/account
account_sid = "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
auth_token = "your_auth_token"
client = Client(account_sid, auth_token)

data = {
    'led': "OFF"
}

document = client.sync \
    .services("default") \
    .documents \
    .create(unique_name="BoardLED", data=data)

print(document.sid)
// Install the Java helper library from twilio.com/docs/java/install
import java.util.HashMap;
import java.util.Map;

import com.twilio.Twilio;
import com.twilio.rest.sync.v1.service.Document;

public class Example {
  // Find your Account Sid and Token at twilio.com/user/account
  public static final String ACCOUNT_SID = "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
  public static final String AUTH_TOKEN = "your_auth_token";

  public static void main(String[] args) {
    Twilio.init(ACCOUNT_SID, AUTH_TOKEN);

    Map<String, Object> data = new HashMap<>();
    data.put("led", "OFF");

    Document document = Document
        .creator("default")
        .setUniqueName("BoardLED")
        .setData(data)
        .create();

    System.out.println(document.getSid());
  }
}
curl -X POST https://sync.twilio.com/v1/Services/default/Documents \
 -d 'UniqueName=BoardLED' \
 -d 'Data={"led":"OFF"}'  \
 -u 'ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX:your_auth_token'
{
  "unique_name": "BoardLED",
  "url": "https://sync.twilio.com/v1/Services/ISXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Documents/ETXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  "created_by": "system",
  "account_sid": "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  "date_created": "2017-09-06T20:53:38Z",
  "date_updated": "2017-09-06T20:53:38Z",
  "sid": "ETXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  "service_sid": "ISXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  "data": {
    "led": "OFF"
  },
  "revision": "0",
  "links": {
    "permissions": "https://sync.twilio.com/v1/Services/ISXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Documents/ETXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Permissions"
  }
}
/*
 * Subscribe to a Twilio Sync Deployed Devices Document using a LinkIt ONE
 * over WiFi or Twilio Wireless with GPRS.

 * This code owes much thanks to MediaTek Labs, who have a skeleton up here:
 * 
 * https://github.com/MediaTek-Labs/aws_mbedtls_mqtt
 *
 * You'll need to install it to run our code.
 * 
 * License: This code, MIT, AWS Code: Apache (http://aws.amazon.com/apache2.0)
 */
#include <ArduinoJson.h>
#include <LTask.h>
#include <LWiFi.h>
#include <LWiFiClient.h>
#include <LGPRS.h>
#include "SyncLinkItHelper.hpp"

/* CONFIGURATION:
 *  
 * This should point at the ROOT Certificate, CLIENT Certificate,
 * and unencrypted CLIENT Key.  You can unencrypt it with (*NIX):
 *
 * openssl rsa -in  CYxxxxxxxxxx.key -out client.key
 * 
 * Name the three files root.crt, root.crt, and client.key
 * 
 * Then, flip the outer switch to 'MS' and upload the three to
 * the LinkIt's root directory.
 */
String           SYNC_ROOT_CA_FILENAME        = "root.crt";
String           SYNC_CERTIFICATE_FILENAME    = "client.crt";
String           SYNC_PRIVATE_KEY_FILENAME    = "client.key";

/* Should we use WiFi or GPRS?  'true' for WiFi, 'false' for GPRS */
boolean          WIFI_USED                    = true;

/* 
 *  Optional Settings.  
 *  You probably do not need to change these unless you change the Doc name. 
 */
const String twilio_topic                     = "sync/docs/BoardLED";
const int mqtt_tls_port                       = 8883;
String SYNC_MQTT_HOST                         = "mqtt-sync.us1.twilio.com";
String SYNC_MQTT_CLIENT_ID                    = "LinkIt_ONE";
const uint8_t LED_BUILTIN                     = 13;

/* Friendly WiFi Network details go here.  Auth choices:
 * LWIFI_OPEN, LWIFI_WPA, LWIFI_WEP
 */
#define WIFI_AP "YOUR_SSID"
#define WIFI_PASSWORD "WIFI_PASSWORD"
#define WIFI_AUTH LWIFI_WPA

/* 
 *  Twilio GPRS Settings here - you should not have to change these to 
 *  use a Twilio Programmable Wireless SIM Card.  Make sure your card 
 *  is registered, provisioned, and activated if you have issues.
 */
#define GPRS_APN "wireless.twilio.com"
#define GPRS_USERNAME NULL
#define GPRS_PASSWORD NULL

typedef int32_t mqtt_callback(MQTTCallbackParams);

// Global Twilio Lambda helper
void disconnect_function();
SyncLinkItHelper helper(
        mqtt_tls_port,
        SYNC_MQTT_HOST,
        SYNC_MQTT_CLIENT_ID,
        SYNC_ROOT_CA_FILENAME,
        SYNC_CERTIFICATE_FILENAME,
        SYNC_PRIVATE_KEY_FILENAME,
        WIFI_USED,
        disconnect_function
);

struct MQTTSub {
        char* topic;
        mqtt_callback* callback; 
};

/* 
 * Our Sync message handling callback.  This is passed as a callback function
 * when we subscribe to the Document, and will handle any incoming messages
 * on that topic (e.g., LED ON or OFF)
 */
int32_t handle_callback(MQTTCallbackParams params)
{     
        MQTTMessageParams message = params.MessageParams;

        char msg[message.PayloadLen+1];
        memcpy (msg,message.pPayload,message.PayloadLen);
        StaticJsonBuffer<maxMQTTpackageSize> jsonBuffer;

        Serial.print("Incoming message from Twilio:");
        Serial.println(msg);
        
        JsonObject& root = jsonBuffer.parseObject(msg);
        String led           = root["led"];
        if (led == "ON") {
                digitalWrite(LED_BUILTIN, HIGH);
        } else {
                digitalWrite(LED_BUILTIN, LOW);          
        }

        return 0;
}

/* 
 *  Main setup function.
 *  
 *  Here we connect to either GPRS or WiFi, then Deployed Devices.  We then 
 *  subscribe to the Document and listen for updates.
 */
void setup()
{
        LTask.begin();
        pinMode(LED_BUILTIN, OUTPUT);
        
        Serial.begin(115200);
        while(!Serial) {
                // Busy wait on Serial Monitor connection.
                delay(100);
        }

  
        if (WIFI_USED){
                LWiFi.begin();
                Serial.println("Connecting to AP");
                Serial.flush();
                while (!LWiFi.connect(
                                WIFI_AP, 
                                LWiFiLoginInfo(WIFI_AUTH, WIFI_PASSWORD)
                      )
                ) {
                        Serial.print(".");
                        Serial.flush();
                        delay(500);
                }
        } else {  
                Serial.println("Connecting to GPRS");
                Serial.flush();
                while (!LGPRS.attachGPRS(
                                GPRS_APN, 
                                GPRS_USERNAME, 
                                GPRS_PASSWORD
                      )
                ) {
                        Serial.println(".");
                        Serial.flush();
                        delay(500);
                }
        }

        Serial.println("Connected to the internet!");
        VMINT port = mqtt_tls_port;
        CONNECT_PORT = port;
        
        LTask.remoteCall(&__wifi_dns, (void*)SYNC_MQTT_HOST.c_str());
        LTask.remoteCall(&__bearer_open, NULL);
        LTask.remoteCall(&__mqtt_start, NULL);

        MQTTSub sub_struct;
        sub_struct.topic = const_cast<char*>(twilio_topic.c_str());
        sub_struct.callback = handle_callback;
        
        LTask.remoteCall(&__sub_mqtt, (void*)&sub_struct);
}

/*  
 *   Every time through the main loop we will spin up a new thread on the 
 *   LinkIt to perform our watchdog tasks in the background.  Insert everything
 *   you want to perform over and over again until infinity (or power 
 *   loss!) here.
*/
boolean main_thread(void* user_data) 
{
        Serial.flush();
        helper.handle_requests();
        delay(1000);

        // Example on how to publish to a Sync Document
        // (uncomment lines between the /* */)
        /*
        static uint32_t counter = 0;
        ++counter;
        if (counter == 10) {
                Serial.println("Sending message to Twilio.");
                helper.publish_to_topic(twilio_topic.c_str(), "{\"msg\":\"Ahoy!\",\"led\":\"ON\"}\0");
                counter = 0;
        }
        */
}

/*
 * This example creates a new thread which calls main_thread() every 3 seconds.
 */
void loop() 
{
        Serial.flush();
        LTask.remoteCall(main_thread, NULL);
        delay(3000);
}

/* 
 *  Trampolines/thunks are the easiest way to pass these class methods.  
 *  We don't have std::bind() or boost::bind()!
 */
inline boolean __bearer_open(void* ctx) 
{ return helper.bearer_open(ctx); }

inline boolean __mqtt_start(void* ctx)  
{ return helper.start_mqtt(ctx); }

inline boolean __wifi_dns(void* ctx)    
{ return helper.wifiResolveDomainName(ctx); }

inline boolean __sub_mqtt(void *ctx)   
{ 
        MQTTSub* sub_struct = (MQTTSub*)ctx; char* topic = sub_struct->topic;
        mqtt_callback* callback = sub_struct->callback;
        helper.subscribe_to_topic(topic, callback);
        return true;
}

/* MQTT Disconnect callback function */
void disconnect_function() 
{
        Serial.println("Oh no, we disconnected!"); while(1);
}

/* Workaround to remove a Macro from mbedtls */
#ifdef connect
#undef connect
#endif
SDK Version:
  • 5.x
Response Format:
  • json
SDK Version:
  • 7.x
SDK Version:
  • 3.x
SDK Version:
  • 5.x
SDK Version:
  • 6.x
SDK Version:
  • 5.x
Format:
  • JSON
const accountSid = 'ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
const authToken = 'your_auth_token';
const Twilio = require('twilio').Twilio;

const client = new Twilio(accountSid, authToken);
const service = client.sync.services('default');

service
  .documents('BoardLED')
  .update({
    data: { led: 'ON' },
  })
  .then(response => {
    console.log(response);
  })
  .catch(error => {
    console.log(error);
  });
// Download the twilio-csharp library from twilio.com/docs/libraries/csharp
using System;
using Twilio;
using Twilio.Rest.Sync.V1.Service;

public class Example
{
    public static void Main(string[] args)
    {
        // Find your Account SID and Auth Token at twilio.com/console
        const string accountSid = "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
        const string authToken = "your_auth_token";
        const string serviceSid = "default";

        TwilioClient.Init(accountSid, authToken);

        var data = new
        {
            led = "ON"
        };

        var doc = DocumentResource.Update(serviceSid,
                                          "BoardLED",
                                          data);

        Console.WriteLine(doc.Data);
    }
}
<?php
// NOTE: This example uses the next generation Twilio helper library - for more
// information on how to download and install this version, visit
// https://www.twilio.com/docs/libraries/php
require_once 'vendor/autoload.php';

use Twilio\Rest\Client;

// Your Account SID from www.twilio.com/console
$sid = "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
// Your Auth Token from www.twilio.com/console
$token = "your_auth_token";

$client = new Client($sid, $token);

$data = array(
    'led' => "ON"
);

$doc = $client->sync
    ->services("default")
    ->documents("BoardLED")->update(
        array(
            'led' => $data
        )
    );

print_r($doc->data);
echo PHP_EOL;
require 'twilio-ruby'

# Initialize the client
account_sid = 'ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
auth_token = 'your_auth_token'
client = Twilio::REST::Client.new(account_sid, auth_token)

# Retreive the service
service = client.sync.v1.services('default')

# Update the Document, data can be any JSON
response = service.documents('BoardLED').update(
  data: '{ "led": "ON" }'
)

puts response
# Download the Python helper library from twilio.com/docs/python/install
from twilio.rest import Client

# Your Account Sid and Auth Token from twilio.com/user/account
account_sid = "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
auth_token = "your_auth_token"
client = Client(account_sid, auth_token)

new_data = {
    'led': "ON"
}

document = client.sync \
    .services("default") \
    .documents("BoardLED") \
    .update(data=new_data)

print(document.data)
// Install the Java helper library from twilio.com/docs/java/install
import java.util.HashMap;
import java.util.Map;

import com.twilio.Twilio;
import com.twilio.rest.sync.v1.service.Document;

public class Example {
  // Find your Account Sid and Token at twilio.com/user/account
  public static final String ACCOUNT_SID = "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
  public static final String AUTH_TOKEN = "your_auth_token";

  public static final String SERVICE_SID = "default";

  public static void main(String[] args) {
    Twilio.init(ACCOUNT_SID, AUTH_TOKEN);

    Map<String, Object> data = new HashMap<>();
    data.put("led", "ON");

    Document document = Document.updater(SERVICE_SID, "BoardLED", data).update();

    System.out.println(document.getData());
  }
}
curl -X POST https://sync.twilio.com/v1/Services/default/Documents/BoardLED \
 -d 'Data={"led":"ON"}'  \
 -u 'ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX:your_auth_token'
{
  "unique_name": "BoardLED",
  "url": "https://sync.twilio.com/v1/Services/ISXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Documents/ETXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  "created_by": "system",
  "account_sid": "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  "date_created": "2017-09-06T20:53:38Z",
  "date_updated": "2017-09-06T20:55:21Z",
  "sid": "ETXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  "service_sid": "ISXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  "data": {
    "led": "ON"
  },
  "revision": "1",
  "links": {
    "permissions": "https://sync.twilio.com/v1/Services/ISXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Documents/ETXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Permissions"
  }
}
/*
 * Subscribe to a Twilio Sync Deployed Devices Document using a LinkIt ONE
 * over WiFi or Twilio Wireless with GPRS.

 * This code owes much thanks to MediaTek Labs, who have a skeleton up here:
 * 
 * https://github.com/MediaTek-Labs/aws_mbedtls_mqtt
 *
 * You'll need to install it to run our code.
 * 
 * License: This code, MIT, AWS Code: Apache (http://aws.amazon.com/apache2.0)
 */
#include <ArduinoJson.h>
#include <LTask.h>
#include <LWiFi.h>
#include <LWiFiClient.h>
#include <LGPRS.h>
#include "SyncLinkItHelper.hpp"

/* CONFIGURATION:
 *  
 * This should point at the ROOT Certificate, CLIENT Certificate,
 * and unencrypted CLIENT Key.  You can unencrypt it with (*NIX):
 *
 * openssl rsa -in  CYxxxxxxxxxx.key -out client.key
 * 
 * Name the three files root.crt, root.crt, and client.key
 * 
 * Then, flip the outer switch to 'MS' and upload the three to
 * the LinkIt's root directory.
 */
String           SYNC_ROOT_CA_FILENAME        = "root.crt";
String           SYNC_CERTIFICATE_FILENAME    = "client.crt";
String           SYNC_PRIVATE_KEY_FILENAME    = "client.key";

/* Should we use WiFi or GPRS?  'true' for WiFi, 'false' for GPRS */
boolean          WIFI_USED                    = true;

/* 
 *  Optional Settings.  
 *  You probably do not need to change these unless you change the Doc name. 
 */
const String twilio_topic                     = "sync/docs/BoardLED";
const int mqtt_tls_port                       = 8883;
String SYNC_MQTT_HOST                         = "mqtt-sync.us1.twilio.com";
String SYNC_MQTT_CLIENT_ID                    = "LinkIt_ONE";
const uint8_t LED_BUILTIN                     = 13;

/* Friendly WiFi Network details go here.  Auth choices:
 * LWIFI_OPEN, LWIFI_WPA, LWIFI_WEP
 */
#define WIFI_AP "YOUR_SSID"
#define WIFI_PASSWORD "WIFI_PASSWORD"
#define WIFI_AUTH LWIFI_WPA

/* 
 *  Twilio GPRS Settings here - you should not have to change these to 
 *  use a Twilio Programmable Wireless SIM Card.  Make sure your card 
 *  is registered, provisioned, and activated if you have issues.
 */
#define GPRS_APN "wireless.twilio.com"
#define GPRS_USERNAME NULL
#define GPRS_PASSWORD NULL

typedef int32_t mqtt_callback(MQTTCallbackParams);

// Global Twilio Lambda helper
void disconnect_function();
SyncLinkItHelper helper(
        mqtt_tls_port,
        SYNC_MQTT_HOST,
        SYNC_MQTT_CLIENT_ID,
        SYNC_ROOT_CA_FILENAME,
        SYNC_CERTIFICATE_FILENAME,
        SYNC_PRIVATE_KEY_FILENAME,
        WIFI_USED,
        disconnect_function
);

struct MQTTSub {
        char* topic;
        mqtt_callback* callback; 
};

/* 
 * Our Sync message handling callback.  This is passed as a callback function
 * when we subscribe to the Document, and will handle any incoming messages
 * on that topic (e.g., LED ON or OFF)
 */
int32_t handle_callback(MQTTCallbackParams params)
{     
        MQTTMessageParams message = params.MessageParams;

        char msg[message.PayloadLen+1];
        memcpy (msg,message.pPayload,message.PayloadLen);
        StaticJsonBuffer<maxMQTTpackageSize> jsonBuffer;

        Serial.print("Incoming message from Twilio:");
        Serial.println(msg);
        
        JsonObject& root = jsonBuffer.parseObject(msg);
        String led           = root["led"];
        if (led == "ON") {
                digitalWrite(LED_BUILTIN, HIGH);
        } else {
                digitalWrite(LED_BUILTIN, LOW);          
        }

        return 0;
}

/* 
 *  Main setup function.
 *  
 *  Here we connect to either GPRS or WiFi, then Deployed Devices.  We then 
 *  subscribe to the Document and listen for updates.
 */
void setup()
{
        LTask.begin();
        pinMode(LED_BUILTIN, OUTPUT);
        
        Serial.begin(115200);
        while(!Serial) {
                // Busy wait on Serial Monitor connection.
                delay(100);
        }

  
        if (WIFI_USED){
                LWiFi.begin();
                Serial.println("Connecting to AP");
                Serial.flush();
                while (!LWiFi.connect(
                                WIFI_AP, 
                                LWiFiLoginInfo(WIFI_AUTH, WIFI_PASSWORD)
                      )
                ) {
                        Serial.print(".");
                        Serial.flush();
                        delay(500);
                }
        } else {  
                Serial.println("Connecting to GPRS");
                Serial.flush();
                while (!LGPRS.attachGPRS(
                                GPRS_APN, 
                                GPRS_USERNAME, 
                                GPRS_PASSWORD
                      )
                ) {
                        Serial.println(".");
                        Serial.flush();
                        delay(500);
                }
        }

        Serial.println("Connected to the internet!");
        VMINT port = mqtt_tls_port;
        CONNECT_PORT = port;
        
        LTask.remoteCall(&__wifi_dns, (void*)SYNC_MQTT_HOST.c_str());
        LTask.remoteCall(&__bearer_open, NULL);
        LTask.remoteCall(&__mqtt_start, NULL);

        MQTTSub sub_struct;
        sub_struct.topic = const_cast<char*>(twilio_topic.c_str());
        sub_struct.callback = handle_callback;
        
        LTask.remoteCall(&__sub_mqtt, (void*)&sub_struct);
}

/*  
 *   Every time through the main loop we will spin up a new thread on the 
 *   LinkIt to perform our watchdog tasks in the background.  Insert everything
 *   you want to perform over and over again until infinity (or power 
 *   loss!) here.
*/
boolean main_thread(void* user_data) 
{
        Serial.flush();
        helper.handle_requests();
        delay(1000);

        // Example on how to publish to a Sync Document
        // (uncomment lines between the /* */)
        /*
        static uint32_t counter = 0;
        ++counter;
        if (counter == 10) {
                Serial.println("Sending message to Twilio.");
                helper.publish_to_topic(twilio_topic.c_str(), "{\"msg\":\"Ahoy!\",\"led\":\"ON\"}\0");
                counter = 0;
        }
        */
}

/*
 * This example creates a new thread which calls main_thread() every 3 seconds.
 */
void loop() 
{
        Serial.flush();
        LTask.remoteCall(main_thread, NULL);
        delay(3000);
}

/* 
 *  Trampolines/thunks are the easiest way to pass these class methods.  
 *  We don't have std::bind() or boost::bind()!
 */
inline boolean __bearer_open(void* ctx) 
{ return helper.bearer_open(ctx); }

inline boolean __mqtt_start(void* ctx)  
{ return helper.start_mqtt(ctx); }

inline boolean __wifi_dns(void* ctx)    
{ return helper.wifiResolveDomainName(ctx); }

inline boolean __sub_mqtt(void *ctx)   
{ 
        MQTTSub* sub_struct = (MQTTSub*)ctx; char* topic = sub_struct->topic;
        mqtt_callback* callback = sub_struct->callback;
        helper.subscribe_to_topic(topic, callback);
        return true;
}

/* MQTT Disconnect callback function */
void disconnect_function() 
{
        Serial.println("Oh no, we disconnected!"); while(1);
}

/* Workaround to remove a Macro from mbedtls */
#ifdef connect
#undef connect
#endif