Skip to content

A software device simulator that shows how to use the nRF Cloud APIs.

License

Notifications You must be signed in to change notification settings

nRFCloud/device-simulator-v2

Repository files navigation

nRF91 Device Simulator v2 npm version

Build Status semantic-release Commitizen friendly

This is a software device simulator that shows how to use the nRF Cloud APIs to create device certificates, onboard a device to your team, do Firmware Over-the-Air Updates (FOTA), and more. Although we call it a "simulator", this tool creates real, working IoT "soft devices" that run from your local machine.

Installation and CLI Help

git clone [email protected]:nRFCloud/device-simulator-v2.git 
cd device-simulator-v2
yarn
yarn build
node dist/cli.js --help

Or you can run it directly using npx:

npx @nrfcloud/device-simulator-v2 --help

Examples that follow use the node dist/cli.js command. If you want nicely formatted JSON output, you can pipe the output to jq after installing it.

Documentation

The nRF Cloud documentation is a good place to start if you are unfamiliar with the nRF Cloud APIs, types of devices and certificates, device onboarding, and other concepts mentioned in this simulator.

Basic Usage

You can create a new device, onboard it, and start sending sensor data all in one command, which is a typical way to use the simulator:

node dist/cli.js -k <api key> -s gps,acc,temp

Use of simulated sensors

The -s flag is optionally used to specify which sensors to simulate.

The acc option sends FLIP accelerometer messages, simulating the device being flipped right-side-up or upside-down. This was a feature of the Asset Tracker v1 firmware example that has been removed for the currently supported Asset Tracker v2.

Note

Including device in the list will generate a LOT of device info messages which may overrun your Web browser. Best not to run it more than a few seconds with it, or you can leave out device and run it long-term.

If you want to use different GPS data, replace the appropriate file in ./data/sensors or change the appropriate file path(s) in cli.ts. (There is some additional GPS data in this repo for routes around Portland, Oregon, USA.)

GPS data is based on NMEA sentences. If you want to make your own GPS data, go to https://nmeagen.org. The "Multi-point line" seems to work best. Lay some points and then click the "Generate NMEA file" button.

Create a new Firmware Over-the-Air (FOTA) job

  1. Open a new terminal window/tab.
  2. Set up the environment variables. Use the same DEVICE_ID that you specified or was generated.
  3. Upload a dummy firmware file as binary data.

Note

If you don't use -a to specify an app type, you won't be able to create an update.

curl -X POST $API_HOST/v1/firmwares -H "Authorization: Bearer $API_KEY" -H "Content-Type: application/zip" --data-binary @data/fota_app_fw.zip | jq

Note that you can also upload your firmware as a base64-encoded string:

export DATA_DIR=<absolute_path_to_the_data_folder>
export FILE=$(base64 $DATA_DIR/fota_app_fw.zip)
curl -X POST $API_HOST/v1/firmwares -H "Authorization: Bearer $API_KEY" -H "Content-Type: text/plain" -d $FILE | jq
  1. Set the BUNDLE_ID variable by calling the firmwares endpoint:
export BUNDLE_ID=$(curl $API_HOST/v1/firmwares -H "Authorization: Bearer $API_KEY" | jq -r '.items[0].bundleId')
  1. Enable the "APP" type of FOTA on the device (if not already enabled). (The other two types are "BOOT" and "MODEM", and you can set one or all of these in the array. However, uploading modem firmware is not allowed because this is controlled by Nordic Semiconductor personnel.) First you need to find the latest version of your device:
export DEVICE_VERSION=$(curl $API_HOST/v1/devices/$DEVICE_ID -H "Authorization: Bearer $API_KEY" | jq -r '.["$meta"].version')

You can now use this to set an If-Match header, which is required to prevent "lost updates":

curl -X PATCH $API_HOST/v1/devices/$DEVICE_ID/state -d '{ "reported": { "device": { "serviceInfo": { "fota_v2": ["APP"] } } } }' -H "Authorization: Bearer $API_KEY" -H "Content-Type: application/json" -H "If-Match: $DEVICE_VERSION"
  1. Create the FOTA job
export JOB_ID=$(curl -X POST $API_HOST/v1/fota-jobs -H "Authorization: Bearer $API_KEY" -H "Content-Type: application/json" -d '{ "deviceIdentifiers": ["'$DEVICE_ID'"], "bundleId": "'$BUNDLE_ID'" }' | jq -r '.jobId')
  1. View your FOTA job
curl $API_HOST/v1/fota-jobs/$JOB_ID -H "Authorization: Bearer $API_KEY" | jq
  1. Verify the job succeeded in the other tab where you ran node dist/cli.js. You should see a series of messages that walk through the firmware installation lifecycle:
************** <your_device_id> ***********
JOB ID: <your_job_id>
OLD STATUS: IN_PROGRESS (1)
NEW STATUS: SUCCEEDED (3)
MESSAGE: installation successful for "APP" firmware file from "<your_bundle_id_url>"
********************************************

If successful, you should see a message like this:

job "<your_job_id>" succeeded!

If you do not see this it's possible that a previously created job has not succeeded. This will block any newly created jobs from running. You can check this by using the GET /fota-jobs endpoint (as you did above) and then using DELETE $API_HOST/v1/fota-jobs/<your-jobId> for any previously created jobs that has a status other than SUCCEEDED.

  1. You can also verify the job succeeded by using the Device API:
curl $API_HOST/v1/fota-job-execution-statuses/$JOB_ID -H "Authorization: Bearer $API_KEY" | jq

or

curl $API_HOST/v1/fota-job-executions/$DEVICE_ID/$JOB_ID -H "Authorization: Bearer $API_KEY" | jq

Simulate a FOTA Job Execution Failure Scenario

If you want to test devices failing, stalling, or timing out you can add the -x flag with one of the following options:

Value Execution Path Description
0 QUEUED Simulates a device not being turned on
1 QUEUED --> REJECTED Simulates a device instantly rejecting a job
2 QUEUED --> DOWNLOADING Simulates a device hanging in the DOWNLOADING state
3 QUEUED --> DOWNLOADING --> IN_PROGRESS Simulates a device attempting to update, but is unable to respond
4 QUEUED --> DOWNLOADING --> IN_PROGRESS --> TIMED_OUT Simulates a device timing out while processing the update
5 QUEUED --> DOWNLOADING --> IN_PROGRESS --> FAILED Simulates a device failing to apply the update and keeping the existing firmware installed

Clean up (if desired)

curl -X DELETE $API_HOST/v1/fota-jobs/<your-jobId> -H "Authorization: Bearer $API_KEY"
curl -X DELETE $API_HOST/v1/firmwares/$BUNDLE_ID -H "Authorization: Bearer $API_KEY"
# $DEVICE_OWNERSHIP_CODE only needed if used a JITP device
curl -X DELETE $API_HOST/v1/devices/$DEVICE_ID -d $DEVICE_OWNERSHIP_CODE -H "Authorization: Bearer $API_KEY" -H "Content-Type: text/plain"

Publishing

To publish a new version to npm, follow this recipe:

# commit all files
git add .
git commit -am "<feat|bug|chore|refactor>: <commit message>"

# publish to npm. this will build, ask for a new version, and publish 
# to the npm repo if you run `yarn deploy:beta, it will deploy to the beta tag
yarn deploy[:beta]
# updates the version in the package.json, this line:
#  "version": "2.2.7",

# tag the new version
git tag v2.2.7

# push changes and new tag to github
git push origin HEAD
git push origin v2.2.7

About

A software device simulator that shows how to use the nRF Cloud APIs.

Resources

License

Stars

Watchers

Forks

Packages

No packages published