Recipes

A recipe is a JSON formatted file that provides a structured way to define the operational setup of the data logger. It is a set of instructions for a logger to execute encapsulating frequently used data logger operations to provision a data logger, or a custom system. The recipe has the ability to configure settings, update operating systems, file management commands [copy, move, delete, rename], format drives, set run options for a program, and more. Recipes are flexible and could be used for a wide variety of data logger configuration tasks or just to combine multiple data logger command and control operations into one file. Recipes provide a convenient way to automate deployment and make data logger setup more efficient and less error-prone.

They are especially useful for onboarding devices to specific environments. For example, a recipe can configure a data logger to connect to Campbell Cloud, setting communication parameters and authentication credentials—all in a single step.

Recipe Format

Recipes are defined in JSON and consist of several key components that tell the data logger what to do and how to do it.

Recipe Components

  • name (required) A human-readable name for the recipe.

  • version (required) A version identifier for the recipe.

  • id (Optional) An identifier stored with the recipe metadata for tracking.

  • function (Optional) How the recipe is applied: "onboard", "startup", or "run". With "run" the recipe is retained as the data logger’s active program recipe — its signature and metadata are stored and its program is set to run — so it persists and is re-applied across restarts. (Loading any new recipe resets the previously stored recipe properties.)

  • metadata (Object, Optional) Mostly free-form metadata for tracking or documentation. One key is read by the data logger: cert_exp_timestamp (an ISO-8601 timestamp) is used to track certificate expiration.

  • reboot (Boolean, Optional) When true the data logger restarts once at the end of the recipe, after every operation has been applied, and only if the recipe succeeded. It is a recipe-level directive rather than an operation because a reboot has no meaningful position in the operation sequence — it is always the final action. Use it to force a clean restart into a fresh state, for example from an onboard recipe that would not otherwise reboot (a recipe delivered by the recipe command already restarts on success; setting/settingDefaults/program/editConst operations also reboot on their own when a change requires it). A plain restart; data tables are preserved.

  • operations (Array of Objects) A list of operations the data logger should execute. These are saved and may be retried if interrupted. Each operation includes:
    • name — The operation identifier

    • data (Object) — Parameters required for the operation

Important

Values inside an operation’s data object (settings, variables, constants, file parameters) must be strings — the data logger converts each string to the appropriate type. Top-level fields such as metadata may contain nested objects or arrays (e.g. specialization_tags).

Generic Recipe Template

{
    "name": "<recipe_name>",
    "version": "<recipe_version>",
    "metadata": {
        "<key>": "<value>",
        "specialization_tags": ["<tag1>", "<tag2>"]
    },
    "reboot": false,
    "operations": [
        {
            "name": "<operation_name>",
            "data": {
                "<parameter_key_1>": "<parameter_value_1>",
                "<parameter_key_2>": "<parameter_value_2>"
            }
        }
        // Additional main operations
    ]
}

Examples

Onboarding to an MQTT environment

This recipe configures a data logger to onboard to an MQTT cloud service that requires mutual TLS authentication.

{
    "name": "Cloud9_OnBoard",
    "version": "1.1.1",
    "metadata": {
        "cert_exp_timestamp": "2025-06-03T18:28:08Z"
    },
    "operations": [
        {
            "name": "setting",
            "data": {
                "TLSConnections": "2",
                "MQTTEnable": "1",
                "MQTTEndpoint": "dashboard.oncloud9.io",
                "MQTTKeepAlive": "43200",
                "MQTTPortNumber": "8883",
                "MQTTCleanSession": "1",
                "MQTTStateInterval": "1",
                "MQTTStatusInterval": "1",
                "MQTTWillMessage": "Gone Fishin' ABCD-EFGH-1234",
                "MQTTWillQoS": "0",
                "MQTTWillRetain": "0",
                "MQTTWillTopic": "cs/v2/last/",
                "MQTTBaseTopic": "cs/v2/",
                "MQTTClientID": "ABCD-EFGH-1234",
                "TLSCertificate": "-----BEGIN CERTIFICATE-----<Client Cert>----END CERTIFICATE-----",
                "TLSPrivateKey": "-----BEGIN PRIVATE KEY-----<Client Private Key>-----END PRIVATE KEY-----",
                "TLSRootCA": "-----BEGIN CERTIFICATE-----<Certificate Authority>-----END CERTIFICATE-----"
            }
        }
    ]
}

CRBasic Program Recipe

This recipe downloads and runs a CRBasic program.

{
    "name": "ClimaVUE 50",
    "version": "0.0.1",
    "metadata": {},
    "operations": [
        {
            "name": "program",
            "data": {
                "url": "https://s3.us-west-2.amazonaws.com/..."
            }
        }
    ]
}

Operation List

The data logger supports the following operations:

Program Operations

This operation is intended for downloading either a program or an operating system, not generic files. When the data logger detects a program operation, it will attempt to run the specified file. If the file is a CRBasic program: the Run Now and Run on Power Up options will be set to true. If the file is an operating system: the data logger will install the downloaded OS.

Properties

  • "url": {string} The web address of the server from which the program should be retrieved. Required unless source is supplied.

  • "fileName": {string} (optional) The desired name for the program on the data logger. If the name has no drive prefix it is placed on CPU:. If omitted, the CRBasic program is saved as CPU:recipe.crb.

  • "size": {string} (optional) Expected size in bytes of the downloaded file. If provided, the download is rejected unless the file size matches.

  • "source": {string} (optional) The program text itself, embedded in the recipe instead of downloaded. When present, url is not used.

  • "language": {string} (optional) Source language when using source. Only CRBasic ("crbasic") is supported; any other value is rejected.

{
    "name": "program",
    "data": {
        "url": "https://DataThings.com/programs/main.crb",
        "fileName" : "main.crb"
    }
}

Embed CRBasic Program

{
    "name": "program",
    "data": {
        "source": "< long crbasic string >",
        "language": "crbasic",
        "fileName": "CPU:main_program.CRB"
    }
}

OS Operations

Downloads and installs an operating system. The "data" object is handed to the same handler as the command-and-control OS command, so it accepts the same fields. At minimum supply a "url"; optional fields include "version" (skip the update if it exactly matches the running version) and the "pre_url" / "post_url" URL segments. See the OS command documentation for the full field list.

Properties

  • "minVersion": {string} (optional) A dotted-decimal version (e.g. "1.4.0"). The OS update is skipped when this version is less than or equal to the data logger’s current version — i.e. the update only proceeds when it moves the device forward. Trailing components default to zero, so "1.4" is treated as "1.4.0". (Also available on the command-and-control OS command.)

  • "manifest_url": {string} (optional) Instead of inlining the download descriptor (url / pre_url / post_url / size / chksum32) in the recipe, the data logger fetches it from this URL with an HTTP GET. The response must be the same JSON object that would otherwise be supplied inline in data; it is used as the OS download descriptor. If the fetch or the parse fails, the OS operation fails.

{
    "name": "OS",
    "data": {
        "url": "https://DataThings.com/Operating_Systems/CR350.1.8.0.obj",
        "minVersion": "1.8.0"
    }
}

When the OS is delivered in chunks, "url" is a list of segments and the full URL for each chunk is composed as <pre_url><url><post_url>. Use "pre_url" and "post_url" to avoid repeating the common parts in every list entry:

{
    "name": "OS",
    "data": {
        "pre_url": "https://DataThings.com/Operating_Systems/",
        "url": [
            "CR350.1.8.0_0",
            "CR350.1.8.0_1",
            "CR350.1.8.0_2"
        ],
        "post_url": ".obj",
        "minVersion": "1.8.0"
    }
}

Setting Operations

Configures data logger settings. The "data" object is a flat map where each key is a setting name (e.g. "PakBusAddress") or its numeric setting ID, and each value is the value to apply. There are two forms:

  • "name": "setting" — applies the listed settings, leaving all others unchanged.

  • "name": "settingDefaults" — resets the device to factory defaults first, then applies the listed settings on top.

Properties

  • "<setting name or ID>": {string} The value to apply. All values must be strings.

Only the settings listed in data are written; every other setting keeps its current value (or, for settingDefaults, its factory default). The settings are applied in a single edit session and committed together — if any committed setting requires a restart, the data logger reboots to apply it.

Set Settings

{
    "name": "setting",
    "data": {
        "PakBusAddress": "12",
        "StationName": "Rufus"
    }
}

Set Settings From Defaults

The settingDefaults operation first resets the entire device configuration to its factory defaults, then applies the settings listed in data on top of that baseline. The reset and the overrides happen in a single edit session and result in a single reboot, so the device ends up at “factory defaults, plus exactly these values” regardless of its prior configuration.

{
    "name": "settingDefaults",
    "data": {
        "PakBusAddress": "12",
        "StationName": "Rufus"
    }
}

data may be empty ({}) to reset the device to factory defaults with no overrides:

{
    "name": "settingDefaults",
    "data": {}
}

Note

This is a full factory reset of all settings before the overrides are applied — including network/cloud connectivity settings not listed in data. Make sure any settings required for the device to remain reachable (MQTT, IP, cellular, etc.) are included in data.

File Operations

The file operation performs file-system and program-control actions, selected by the "action" key. Supported actions: create, download, upload, list, checksum, run, stop, load, format, delete, copy, and move (rename is a move).

The download, upload, list, and checksum actions behave exactly as the matching fileControl commands; in a recipe they simply run silently (no command response is published).

Where an action takes a target file, it accepts either "path" (a full DRIVE:file path) or "fileName" with an optional "drive" (defaulting to CPU). The run and stop actions reboot the data logger to apply the change.

Format Drive

{
    "name": "file",
    "data": {
        "action": "format",
        "drive": "USR"
    }
}

Note

Recipes are stored on the CPU: drive, so formatting CPU would normally erase the running recipe (and the copy used to resume it if interrupted). When a recipe contains a format operation, the data logger keeps the recipe in memory for the duration of the run and automatically rewrites it after the format if the file is missing. The remaining operations and interrupted-recipe resume therefore continue to work even after a CPU format.

Move File

{
    "name": "file",
    "data": {
        "action": "move",
        "source": "CRD:file.txt",
        "destination": "USR:file.txt"
    }
}

Rename File

{
    "name": "file",
    "data": {
        "action": "move",
        "source": "CRD:file.txt",
        "destination": "CRD:renamed_file.txt"
    }
}

Set Run Options

Sets the program to run and reboots. "runOnPowerUp" (default true) controls whether the program also runs on power-up, and "deleteTables" (default false) clears existing data tables on the reboot.

{
    "name": "file",
    "data": {
        "action": "run",
        "path": "CPU:main_program.CRB",
        "runOnPowerUp": "true",
        "deleteTables": "true"
    }
}

Stop Program

Stops the running program and reboots. Honors "runOnPowerUp" and "deleteTables" as above.

{
    "name": "file",
    "data": {
        "action": "stop"
    }
}

Create File

Writes a file from inline data supplied in "source". Text files are written verbatim; binary files are supplied base64-encoded together with "encoding": "base64".

Properties

  • "source": {string} The file contents to write. For "encoding": "base64" this is the base64-encoded binary; otherwise it is written verbatim as text.

  • "encoding": {string} (optional) "base64" to decode "source" from base64 and write the resulting raw bytes — use this to create binary files. Omit (or "none") to write "source" verbatim.

  • "chksum32": {string} (optional) A CRC-32 of the intended contents (the decoded bytes when base64 is used), as a decimal (or 0x-prefixed hex) string. If the target file already exists and its CRC-32 matches, the file is left untouched and creation is skipped. Uses the same checksum as the OS operation.

{
    "name": "file",
    "data": {
        "action": "create",
        "path": "CPU:notes.txt",
        "source": "file contents",
        "chksum32": "3735928559"
    }
}

Binary file, supplied base64-encoded:

{
    "name": "file",
    "data": {
        "action": "create",
        "path": "CPU:blob.bin",
        "encoding": "base64",
        "source": "SGVsbG8sIHdvcmxkIQ=="
    }
}

Download File

Fetches a file over HTTP(S) and saves it to the logger — the general-purpose file downloader. (To download and run a program, or download and install an operating system, use the program / OS operations above instead.)

{
    "name": "file",
    "data": {
        "action": "download",
        "url": "https://example.com/files/cal.dat",
        "path": "CPU:cal.dat"
    }
}

Copy File

{
    "name": "file",
    "data": {
        "action": "copy",
        "source": "CRD:file.txt",
        "destination": "USR:file.txt"
    }
}

Delete File

{
    "name": "file",
    "data": {
        "action": "delete",
        "path": "CPU:file.CRB"
    }
}

Load OS From Drive

{
    "name": "file",
    "data": {
        "action": "load",
        "path": "CPU:CR350.1.8.0.obj"
    }
}

EditConst Operations

Sets one or more constants in the running CRBasic program’s ConstTable and triggers a recompile. This is the recipe-embedded form of the editConst command and uses the same underlying handler (JSON_const_set).

The operation is identified by "name": "editConst". The "data" object is a flat map of constant name → value, where every value must be a string (the logger casts each string to the constant’s declared type when it rewrites the program). Only the constants listed are changed; all others keep their current values, and every key must name an existing constant or the operation fails. Each value may be at most 79 characters.

Unlike the command-and-control form, the recipe form does not honor the cmd / tranID / apply keys — those are command-and-control specific. After the constants are applied successfully the logger reboots to recompile.

{
    "name": "editConst",
    "data": {
        "THRESHOLD": "10.5",
        "SENSOR_ID": "99",
        "STATION_NAME": "North 40"
    }
}

Set Variables

Sets one or more variables in the running CRBasic program. The "data" object is a flat map of variable name → value, using the same handler as the command-and-control variable / setVar commands. Values must be strings; the data logger converts each string to the variable’s type when it is applied.

Properties

  • "<variable name>": {string} The value to assign.

Variable access and examples:

  • "variable_name": "12.3" — Public variable

  • "Public.variable_name": "12.3" — Public variable with explicit scope

  • "variable_name(2)": "2.013" — Array element of a public variable

  • "StructureName.variable_name": "12.3" — Variable inside a structure

  • "StructureName.variable_name(2)": "12.3" — Array element of a variable inside a structure

  • "trigger_event": "true" — Boolean variables

Every key must name a variable that exists in the running program; if any assignment fails (unknown variable, array index out of bounds, etc.) the operation fails.

{
    "name": "variable",
    "data": {
        "bale_count": "20",
        "field_name": "north_40",
        "farmall.pto_engaged": "False",
        "farmall.engine_rpm": "1780.0"
    }
}

Recipe and WEB.OBJ.GZ

A Recipe can be included in a WEB.OBJ.GZ for a powerful automated deployment solution