Reuse machine configuration on many machines

If most of your machines use the same setup, you can use a fragment, like a cookie cutter, to configure the machines in the same way. Fragments are a way of sharing and managing machine configurations across multiple machines.

For example, if you have a fleet of rovers that uses the same hardware, you could use a fragment to configure the motors, base component, camera, and all other resources for all rovers. If some of the rovers have a slightly different configuration, you can overwrite the configuration for just those resources of those rovers. If one rover has an arm attached, you can add the rover configuration fragment (including the motors, camera, and base components), and then configure the arm on just that one rover.

Create a fragment

You must be an organization owner to create fragments for an organization.

1

In the Viam app, create a machine in any location.

2

Use the CONFIGURE tab to configure all the resources you want to use on your machines.

All available resources except triggers are supported in fragments. You can even configure other fragments inside a fragment.

3

Switch to JSON.

JSON subtab of the CONFIGURE tab
4

Copy the raw JSON configuration object.

5

Go to the FRAGMENTS tab and create a fragment.

Paste the copied JSON configuration into it.

Set your privacy settings in the menu bar. There are three options for this:

  • Public: Any user inside or outside of your organization will be able to view and use this fragment.
  • Private: No user outside of your organization will be able to view or use this fragment.
  • Unlisted: Any user inside or outside of your organization, with a direct link, will be able to view and use this fragment.

Click Save.

If you want to edit the fragment later, do it from this screen.

6

Delete the original configuration (optional).

Now that the configuration is saved as a fragment, you can delete each resource in the original config from your machine and replace the config with the fragment in the next step. By using the new fragment, this and every other machine you add the fragment to will use the exact same configuration.

Add the fragment to multiple machines

With your fragment created, you can add it to all machines that should have it.

In the following steps, you will see how to add a fragment manually. If you are working in a factory setting and need to set up devices before they reach the end user, you can also use fragments to provision your machines.

1

On your machine’s CONFIGURE tab, click the + button and select Insert fragment.

Search for your fragment and add it.

Click Save in the upper right corner of the screen.

2

Repeat step 1 for each of the machines that you want to configure in the same way.

If some of your machines have slight differences, you can still add the fragment and then add fragment overwrites in the next section.

Modify fragment settings on a machine

If some of your machines are similar but not identical, you can use a fragment with all of them and then overwrite parts of the configuration to customize it without modifying the upstream fragment.

For example, consider a fleet of rovers that all have the same motors, wheels, and base but a few rovers have a different camera than most. You can configure a fragment that has the motors, wheels, base on the rovers as well as the camera that is used on most rovers. For the rovers that have a different camera, you would then add the fragment and overwrite the camera configuration.

If you or a collaborator later modify fields within the upstream fragment, your modifications will still apply. For example if you changed the default camera configuration in the fragment to be a different camera model, your modified rovers would still overwrite the camera model set by the fragment.

1

On the CONFIGURE tab of the machine whose config you want to modify, make your edits just as you would edit a non-fragment resource.

You can click the {} button to switch to advanced view and see the changes.

Click Save.

You can modify fragment fields in your machine’s raw JSON config by using update operators. Viam supports all update operators except for $setOnInsert, $, $[], and $[<identifier>].

To configure fragment overwrites manually instead of using the builder UI:

  1. Navigate to your machine’s CONFIGURE tab.
  2. Switch to JSON mode.
  3. Add a top-level section called "fragment_mods" (alongside the other top-level sections like "components" and "fragments"):
  "fragment_mods": [
    {
      "fragment_id": "<YOUR FRAGMENT ID>",
      "mods": [
        {
          <INSERT YOUR MODS HERE>
        }
      ]
    }
  ],

This example assumes the fragment with ID abcd7ef8-fa88-1234-b9a1-123z987e55aa contains a motor configured with "name": "motor1".

{
  "components": [],
  "fragment_mods": [
    {
      "fragment_id": "abcd7ef8-fa88-1234-b9a1-123z987e55aa",
      "mods": [
        {
          "$set": {
            "components.motor1.attributes.max_rpm": 1818,
            "components.motor1.attributes.pins.a": 30,
            "components.motor1.attributes.board": "local"
          }
        },
        {
          "$unset": {
            "components.motor1.attributes.pins.pwm": 0
          }
        }
      ]
    }
  ],
  "fragments": ["abcd7ef8-fa88-1234-b9a1-123z987e55aa"]
}
  1. Edit the fragment_id value to match the ID of the fragment you want to modify, for example "12345678-1a2b-9b8a-abcd987654321".
  2. Add any update operators you’d like to apply to the fragment to the mods section. Click to view each example:
Change the name and attributes of a component

This example uses $set to make the following changes to the attributes of a motor named motor1:

  • Sets the max_rpm to 1818.
  • Changes the name of motor1 to my_motor. Note that this does not affect the other mods; you still use motor1 for them.
  • Sets the pin number for pin a to 30.
  • Sets the name of the board associated with this motor to local.
  • Sets the capture_frequency_hz in the service_config for the first capture method in the capture_methods array.
"fragment_mods": [
 {
   "fragment_id": "abcd7ef8-fa88-1234-b9a1-123z987e55aa",
   "mods": [
     {
       "$set": {
         "components.motor1.attributes.max_rpm": 1818,
         "components.motor1.name": "my_motor",
         "components.motor1.attributes.pins.a": 30,
         "components.motor1.attributes.board": "local",
         "components.motor1.service_configs.0.attributes.capture_methods.0.capture_frequency_hz": 0.25
        }
     }
   ]
 }
],
Remove an attribute

This example uses $unset to remove the pin number set for the pwm pin, so the motor no longer has a PWM pin set. In other words, it deletes the pwm pin field.

"fragment_mods": [
  {
    "fragment_id": "abcd7ef8-fa88-1234-b9a1-123z987e55aa",
    "mods": [
      {
       "$unset": {
         "components.motor1.attributes.pins.pwm": 0
       }
      }
    ]
  }
],
Modify dependencies

This example uses $set to assign a new list of dependencies to a component named rover_base2.

"fragment_mods": [
  {
    "fragment_id": "abcd7ef8-fa88-1234-b9a1-123z987e55aa",
    "mods": [
      {
       "$set": {
         "components.rover_base2.attributes.depends_on": ["local", "motor1"]
       }
      }
    ]
  }
],
Change motor pins from A and B to PWM and DIR

This example uses $rename to make the following changes to the attributes of a motor named motor1 in the fragment:

  • Retrieves the pin number for pin a and assigns that value to the PWM pin. Deletes the pins.a field.
  • Retrieves the pin number for pin b and assigns that value to the DIR pin. Deletes the pins.b field.

$rename is for changing an attribute’s key, not its value. If you want to change the name of a component (for example, motor1), use $set, as shown in the change the name of a component example.

"fragment_mods": [
 {
   "fragment_id": "abcd7ef8-fa88-1234-b9a1-123z987e55aa",
   "mods": [
     {
       "$rename": {
         "components.motor1.attributes.pins.a": "components.motor1.attributes.pins.pwm",
         "components.motor1.attributes.pins.b": "components.motor1.attributes.pins.dir"
       }
     }
   ]
 }
],
Change a camera path

This example uses $set to change the video path for a camera named camera-one in the fragment:

"fragment_mods": [
  {
    "fragment_id": "abcd7ef8-fa88-1234-b9a1-123z987e55aa",
    "mods": [
      {
        "$set": {
          "components.camera-one.attributes.video_path": "0x11100004a12345"
        }
      }
    ]
  }
],
Modify data sync settings

This example uses $set to change the sync interval for a data management service named data-management in the fragment:

"fragment_mods": [
  {
    "fragment_id": "abcd7ef8-fa88-1234-b9a1-123z987e55aa",
    "mods": [
      {
        "$set": {
          "services.data-management.attributes.sync_interval_mins": "0.5"
        }
      }
    ]
  }
],
Pin a module version

This example uses $set to set version update settings for a module named custom-sensor in the fragment:

"fragment_mods": [
  {
    "fragment_id": "abcd7ef8-fa88-1234-b9a1-123z987e55aa",
    "mods": [
      {
        "$set": {
          "modules.custom-sensor.version": "1.8.0"
        }
      }
    ]
  }
],

Here are the version options:

  • To update with new minor releases of the same major release branch, use "^<major version number>", for example "^1"
  • To update with new patch releases of the same minor release branch, use "~<minor version number>", for example "~1.8"
  • To always update with the latest release, use "latest"
  • To pin to a specific release, use "<version number>", for example "1.8.3"
Change a package version

This example uses $set to modify version update settings for the first package in the packages array from the fragment:

"fragment_mods": [
  {
    "fragment_id": "abcd7ef8-fa88-1234-b9a1-123z987e55aa",
    "mods": [
      {
        "$set": {
          "packages.0.version": "latest"
        }
      }
    ]
  }
],
Change the log level of a resource

This example uses $set to modify the log level from the fragment for a resource:

"fragment_mods": [
  {
    "fragment_id": "abcd7ef8-fa88-1234-b9a1-123z987e55aa",
    "mods": [
      {
        "$set": {
          "components.control.log_configuration.level": "debug"
        }
      }
    ]
  }
],

If the resource comes from a module, you must instead set the log_level attribute on the module itself:

"fragment_mods": [
  {
    "fragment_id": "abcd7ef8-fa88-1234-b9a1-123z987e55aa",
    "mods": [
      {
        "$set": {
          "modules.my-control-logic.log_level":  "debug"
        }
      }
    ]
  }
],
  1. Click Save in the upper right corner of the page to save your new configuration.
  2. To check that your mods are working, view your machine’s debug configuration. In Builder mode on the CONFIGURE tab, select the (Actions) menu to the right of your main part’s name in the left-hand panel and click the View debug configuration option to view the full configuration file.
2

After configuring fragment overwrites, check your machine’s LOGS tab.

If there are problems with overwrites to the fragment, the overwrites will not be partially applied and the configuration changes will not take effect until the configuration is fixed.

3
Reset to fragment

(Optional) Revert fragment modifications.

If you need to restore the original fragment, click the in the upper right corner of the card you modified, and click Revert changes. Now, the fragment will be identical to the upstream fragment.

Update a fragment

You and your collaborators can edit a fragment at any time. The Viam app automatically creates new versions of your fragment as you make changes. Fragments can only be deleted if no machines are using them.

If you’ve already deployed the fragment to one or more machines, the Viam app updates the configuration on each deployed machine that uses that fragment. You can see the number of machines using your fragment from the fragments page in the Viam app.

Create fragment tags

You can create tags to differentiate between versions of your fragment. For example, you may want to create a tag for stable and beta.

  1. Go to the FRAGMENTS tab and click on a fragment.
  2. Click on Versions in the menu bar.
  3. Click Add Tag.
  4. Select a version to pin the tag to. You can change this later.
  5. Type in a name for your tag.

Pin to a version or tag for a fragment

When you add a fragment to a machine you can choose to pin the version to use:

  • the latest version: Always update to the latest version of this fragment as soon as a new version becomes available. This is the default.
  • a specific version: Do not update to any other version.
  • a tag: Always use the version of this fragment with the selected tag. For example stable or beta.

Example fragments

For an example of a fragment that configures multiple components and services, see the Viam Rover fragment.

For an example of creating a fragment and using it to configure a fleet of machines, see the air quality fleet tutorial.