Skip to content

Virtual Devices

Zaber offers cloud-hosted simulations of Zaber devices for software testing purposes. Virtual Devices only support the Zaber ASCII protocol and do not offer all of the models or features of real devices, but they can be used to evaluate Zaber software or test the behavior of your custom motion control code using the Zaber Motion Library (ZML).

Controlling a Virtual Device using ZML is very similar to controlling a real device over the network; you just need one or two special identifiers and to make a different function call to establish the connection.

There are two way of accessing Virtual Devices: Free trial and paid subscription.

Option 1: Free Trial

You can create a temporary, fee-free Virtual Device by navigating your web browser to the Virtual Device page and selecting a device type to simulate. Once you click the Try it for free button you will be taken to the device viewer page. It will take a few minutes to create and start the simulation. Once it is running you will see a 3D model of the device you have chosen, and it is then ready for software connection. Free trial devices will automatically be deleted after four hours.

Copy the Virtual Device's Cloud ID from the box labeled Cloud ID at the top right of the display. You just need to click on the ID to copy it to the clipboard.

Virtual Device Cloud ID

Once you have the Cloud ID for the Virtual Device, you can connect to it as shown in the following example code. This is very similar to the TCP/IP network communication example except the function call to make the connection is different. In the example code replace Cloud ID here with the ID you copied from the viewer page.

from zaber_motion import Library
from zaber_motion.ascii import Connection

Library.enable_device_db_store()

with Connection.open_iot_unauthenticated("Cloud ID here") as connection:
    device_list = connection.detect_devices()
    print("Found {} devices".format(len(device_list)))

    # The rest of your program goes here
const { ascii: { Connection }, Library } = require('@zaber/motion');

async function main() {
  Library.enableDeviceDbStore();

  const connection = await Connection.openIotUnauthenticated('Cloud ID here');
  try {
      const deviceList = await connection.detectDevices();
      console.log(`Found ${deviceList.length} devices.`);

      // The rest of your program goes here
  } finally {
      // Close the connection to allow Node.js to exit
      await connection.close();
  }
}

main();
using System;
using Zaber.Motion;
using Zaber.Motion.Ascii;

namespace example
{
    class Program
    {
        static void Main(string[] args)
        {
            Library.EnableDeviceDbStore();

            using (var comm = Connection.OpenIotUnauthenticated("Cloud ID here"))
            {
                var deviceList = comm.DetectDevices();
                Console.WriteLine("Found {deviceList.Length} devices.");

                // The rest of your program goes here
            }
        }
    }
}
// package name may differ in your code
package example;

import zaber.motion.Library;
import zaber.motion.ascii.Axis;
import zaber.motion.ascii.Connection;
import zaber.motion.ascii.Device;

public class App
{
    public static void main(String[] args)
    {
        Library.enableDeviceDbStore();

        try (Connection connection = Connection.openIotUnauthenticated("Cloud ID here")) {
            Device[] deviceList = connection.detectDevices();
            System.out.println(String.format("Found %d devices.", deviceList.length));

            // The rest of your program goes here
        }
    }
}
import zaber.motion.Library;
import zaber.motion.ascii.Connection;

Library.enableDeviceDbStore();
try
    connection = Connection.openIotUnauthenticated('Cloud ID here');
    deviceList = connection.detectDevices();
    fprintf('Found %d devices.\n', deviceList.length);

    % The rest of your program goes here

catch exception
    disp(getReport(exception));
end
connection.close();
#include <zaber/motion/ascii.h>

using namespace zaber::motion;
using namespace zaber::motion::ascii;

int main() {
    Library::enableDeviceDbStore();

    Connection connection = Connection::openIotUnauthenticated("Cloud ID here");

    std::vector<Device> deviceList = connection.detectDevices();
    std::cout << "Found " << deviceList.size() << " devices." << std::endl;

    /* The rest of your program goes here */

    return 0;
}

Option 2: Paid Subscription

If you want multiple Virtual Devices that last as long as you need them, you can create an account at the Virtual Device site, then navigate to My Virtual Devices under the Virtual Device menu, and create devices from there. Then you can copy the Virtual Device IDs by clicking on them in your list of Virtual Devices.

Virtual Device Manager

Note that a Virtual Device must be in the Running state in order to connect to it with software. The switches in the left column control the state. You will be charged for time in the Running state.

If you are using Virtual Devices created within a paid account, you will also need to create an Access Token for yourself. An Access Token is a way for your ZML program to authenticate itself with your Virtual Device subscription account without having your username and password in the code.

To create an Access Token, sign in to your account. Then, under the menu with your username on it, select Access Tokens. Click the Create Access Token button and give a name to the token - this name is just a memory aid for you and has no significance to your programs. You can optionally set an expiry date, but normally you will leave this blank. Check the IoT scope checkbox, then click the Create Access Token button. You will be shown the value of the new token. IMPORTANT: Copy the token value to somewhere secure; this is the only time you will be able to see it, and it should be considered as important as a password. In the event that your token is leaked, you can revoke it but then you will have to update your programs that were using it to use a new token instead.

Once you have both an Access Token and the Cloud IDs for all the Virtual Devices you want to use, the following code snippet shows how to connect to the Virtual Devices. In each case substitute a Cloud ID where you see Cloud ID here, and substitute your Access Token's secret value (not its name) where you see Access Token here.

from zaber_motion import Library
from zaber_motion.ascii import Connection

Library.enable_device_db_store()

with Connection.open_iot_authenticated("Cloud ID here", "Access Token here") as connection:
    device_list = connection.detect_devices()
    print("Found {} devices".format(len(device_list)))

    # The rest of your program goes here
const { ascii: { Connection }, Library } = require('@zaber/motion');

async function main() {
  Library.enableDeviceDbStore();

  const connection = await Connection.openIotAuthenticated('Cloud ID here', 'Access Token here');
  try {
      const deviceList = await connection.detectDevices();
      console.log(`Found ${deviceList.length} devices.`);

      // The rest of your program goes here
  } finally {
      // Close the connection to allow Node.js to exit
      await connection.close();
  }
}

main();
using System;
using Zaber.Motion;
using Zaber.Motion.Ascii;

namespace example
{
    class Program
    {
        static void Main(string[] args)
        {
            Library.EnableDeviceDbStore();

            using (var comm = Connection.OpenIotAuthenticated("Cloud ID here", "Access Token here"))
            {
                var deviceList = comm.DetectDevices();
                Console.WriteLine("Found {deviceList.Length} devices.");

                // The rest of your program goes here
            }
        }
    }
}
// package name may differ in your code
package example;

import zaber.motion.Library;
import zaber.motion.ascii.Axis;
import zaber.motion.ascii.Connection;
import zaber.motion.ascii.Device;

public class App
{
    public static void main(String[] args)
    {
        Library.enableDeviceDbStore();

        try (Connection connection = Connection.openIotAuthenticated("Cloud ID here", "Access Token here")) {
            Device[] deviceList = connection.detectDevices();
            System.out.println(String.format("Found %d devices.", deviceList.length));

            // The rest of your program goes here
        }
    }
}
import zaber.motion.Library;
import zaber.motion.ascii.Connection;

Library.enableDeviceDbStore();
try
    connection = Connection.openIotAuthenticated('Cloud ID here', 'Access Token here');
    deviceList = connection.detectDevices();
    fprintf('Found %d devices.\n', deviceList.length);

    % The rest of your program goes here

catch exception
    disp(getReport(exception));
end
connection.close();
#include <zaber/motion/ascii.h>

using namespace zaber::motion;
using namespace zaber::motion::ascii;

int main() {
    Library::enableDeviceDbStore();

    Connection connection = Connection::openIotAuthenticated("Cloud ID here", "Access Token here");

    std::vector<Device> deviceList = connection.detectDevices();
    std::cout << "Found " << deviceList.size() << " devices." << std::endl;

    /* The rest of your program goes here */

    return 0;
}