Skip to content

codetunez/mock-devices-de

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

43 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

mock-devices-de v10 (Docker Edition)

mock-devices is a simulation engine that manages and runs simulated devices that connect to an Azure Iot Hub. When hosted in the Azure IoT Edge runtime, the engine will simulate Edge modules too. The simulated devices and modules implement D2C/C2D scenarios i.e telemetry, twin and commands as supported by the Azure IoT Device SDK

Each configured device/module acts independently of other devices/modules running within the engine. Each has its own model (capabilities), configuration and connection details. Devices/modules running on the same simulation engine can be a mix of connection strings, DPS, SaS, Edge modules. The engine has additional scenarios like cloning, bulk, templates and acknowledgements. See internal help

The Docker edition is a Docker container of the running simulation engine. It exposes a REST endpoint for control and data plane operations. Use this edition to run the Edge modules configured in a mock-devices state file (and deploy as an Edge module) It is also useful where a headless simulation experience per state file is required. It is part of a suite of mock-devices tools

Other editions

  • The mock-devices edition of the tool is the single install UX + engine experience. It provides an interactive experience for running and controlling the simulation as well as managing the devices/modules. It can be used to create a state file which can be used to run any mock-devices engine of the same version

  • The mock-devices-edge edition is a Docker container configured as an Edge module that can be used to manage basic operations for running instances of mock-devices-de within the same Edge runtime. Clients can interact with the simulation engine using Twin Desired and Direct Commands making it an alternative to doing REST

  • The mdux edition is a Docker container build of the desktop edition. It is a fully functional UX + simulation engine mock-devices instance and is useful for dynamic module scenarios. It is feature limited to run inside containers with no access to file system. It can also be used as a "terminal" UX experience to see other running mock-devices engines connecting via IP or DNS

State file

See the desktop edition for details about the state file

Getting started

General - Get and run the public Docker Hub version

Install Docker and execute the following commands. Default port is 9000. The following example remaps to 8989

docker pull codetunez/mock-devices-de

docker run -p 8989:9000 codetunez/mock-devices-de

Developer - Build and run a local version

Clone this repo and from the command line

Node

Install and Build

npm ci && npm run build

node _dist/start.js

Docker

Building the container
docker build -t <namespace>/mock-devices-de .

Run the container (changing port)
docker run -p 8989:9000 -d <namespace>/mock-devices-de

Loading data and running the engine

Use a state file

Once the container is running, load a state file by using one generated by the desktop edition or by using APIs below

See running containers
docker ps

Load your state (or reload new state)
curl -d "@<state file>" -H "Content-Type: application/json" -X POST http://127.0.0.1:8989/api/state

Start all devices
curl http://127.0.0.1:8989/api/devices/start

See the console
docker logs -f <container id>

Stop all devices
curl http://127.0.0.1:8989/api/devices/stop

API

These docs do not have the complete updates for Plan mode, Edge modules, SSE, Simulation and changes to response payloads. Doc will incrementally update

mock-devices DE has several resource endpoints to manage the simulation

The following endpoints deal with the core of creating, running and updating devices as well as adding capabilities to send and receive data.

  • /api/device - CRUD for a device including start/stopping the device
  • /api/devices - Gets the list of current devices and starts/stops all devices

The following endpoints deal with the service state and the misc simulation variables

  • /api/state - Gets or sets the current state machine and simulation config
  • /api/simulation - Gets or sets the simulation configuration. All devices restart required

The following endpoint deals with reference data

  • /api/sensors - Gets a list of fake sensors that can be added to a device to send simulated data

Objects

state object

property type usage
devices array The list of device objects in the state machine
simulation object The current configuration for the simulation

EXAMPLE

{
    "devices" : []
    "simulation" : {}
}

POST

state object
<devices> curl -d "<state>" -H "Content-Type: application/json" -X POST http://127.0.0.1:8989/api/state
only simulation object
<devices> curl -d "<simulation>" -H "Content-Type: application/json" -X POST http://127.0.0.1:8989/api/simulation

GET

state object
<state> curl http://127.0.0.1:8989/api/state
only devices array
<devices> curl http://127.0.0.1:8989/api/devices
only simulation object
<simulation> curl http://127.0.0.1:8989/api/simulation

Transport - All Devices

GET

<devices> curl http://127.0.0.1:8989/api/devices/start
<devices> curl http://127.0.0.1:8989/api/devices/stop


device object

The device object defines all of the device's or module's inputs/outputs and it's connection configuration.

property type usage
_id string Device id in IoT Hub or DeviceId + ModuleId
comms array The list of comm objects
configuration object The connection information of a device
plan array The list of plan objects (TBD)

To represent a module, format the id using <deviceId>moduleId

Example for device

{
    "_id: "a-device",
    "configuration" : { _type: 'dps'}
    "comms" : [],
    "plan" : []    
}

Example for module

{
    "_id: "<a-device>a-module",
    "configuration" : { _type: 'module'},
    "comms" : [],
    "plan" : []
}

POST
<device> curl -d "<configuration>" -H "Content-Type: application/json" -X POST http://127.0.0.1:8989/api/device/new

DELETE
<devices> curl -X DELETE http://127.0.0.1:8989/api/device/<device id>

PUT
can only update configuration
<device> curl -d "<configuration>" -H "Content-Type: application/json" -X POST http://127.0.0.1:8989/api/<device id>

GET
<device> curl http://127.0.0.1:8989/api/device/<device id>

Transport - This device only

GET
<device> curl http://127.0.0.1:8989/api/device/<device id>/start
<device> curl http://127.0.0.1:8989/api/device/<device id>/stop

configuration object

Defines the connection configuration of the device and the initial create profile. Changes here require device restart

property type usage
_kind string 'dps' | 'template' | 'hub' | 'module | 'edge'
deviceId string Device id in IoT Hub or DeviceId + ModuleId
scopeId string DPS scope ID
dpsPayload object JSON payload as supported by DPS/Hub build
sasKey string Device SaS key
isMasterKey boolean 'true' |'false'. If true, device id is ignored and issued during DPS registration
mockDeviceName string Friendly name used by the GUI
mockDeviceCount string? Device number to start from in bulk create
mockDeviceCountMax string? Device number to end on in bulk create
connectionString string? Uses Azure IoT Hub connection string if _kind is hub
planMode boolean Switch this device to use plan mode
modules array The list of _ids that are modules for the Edge device
{
 "_kind": "dps"
 "deviceId" : "any-device-id"
 "scopeId": "00SED0045",
 "dpsPayload": {},
 "sasKey": "3249cxvnkj43579fdsg+=DFS90832",
 "isMasterKey": false,
 "mockDeviceName": "My Device",
 "mockDeviceCount": 1,
 "mockDeviceCountMax": 1,
}

This object can only be updated with the device object POST and PUT API

comm object

A communication or comm object is used to define the type of input/output the device will do. There are 3 kinds of comm objects. Reported (send data), Desired (receive data) and Method (execute). The device does not have to be stopped to add or remove comm objects except methods

This is how to use the comm object to define a data send property

property type usage
_id string A unique id for this property. Needs to be unique for the simulation i.e. a GUID
_type string 'property' |'method'. Msg/Events and Twins are properties. Primarily used by the GUI
color string? Only used by GUI
enabled boolean Only honored when device is in a runloop. Updating a device will send value immediately
interface string Name the comm property. Not supported
string boolean true for values to be treated as strings i.e. text and dates. false for all other types i.e. object, arrays and booleans
value any The current value of the property. Update this to send a new value (PUT) for the device. Supports AUTO_* in a runloop
sdk string Determine how to send the device data. msg for SDK event/message API or twin for SDK Device Twin API
version number Readonly. Lifecycle count of Twin updates for this device (only for Desired fields)
mock object? See later
propertyObject object See later
type object See later
runloop object? See later

mock object

To use a mock sensor, assign a <sensor> to the mock property and change the mock value in the type object

GET
<sensors> curl http://127.0.0.1:8989/api/sensors
<sensor> curl http://127.0.0.1:8989/api/sensors/<type>

projectObject object

The propertyObject defines if the value field is literal or a JSON object. The latter is the second property in this object should must be stringified. Supports AUTO_*

property type usage
type string 'default' |'templated'
templated string JSON object (optional)

type object

The type defines how to comm object binds to the SDK

property type usage
mock any use false to switch off mock sensor. Value is a sensor when mock sensor is on
direction string 'd2c' |'c2d'. Used to bind the comm object to the SDK. Honors sdk type and sets up the property to be read/desired or send/reported

runloop object

Use the runloop object to send the value on a timed loop.

property type usage
include boolean false to not include this property in a runloop
unit string 'secs' |'mins'
value integer Honors unit

EXAMPLE

{
    "_id": "b07f4260-df7d-4d79-8f2d-02cf9d8c5b1f",
    "_type": "property",
    "name": "d2cProperty_1d57",
    "color": "#333333",
    "enabled": false,
    "interface": "(single interface only)",
    "string": false,
    "value": 0,
    "sdk": "msg",
    "propertyObject": {
        "type": "default"
    },
    "version": 0,
    "type": {
        "mock": false,
        "direction": "d2c"
    },
    "runloop": {
        "include": false,
        "unit": "secs",
        "value": 15
    }
}

POST
create the comm with defaults
<device> curl -d "{type:'d2c'}" -H "Content-Type: application/json" -X POST http://127.0.0.1:8989/api/device/<device id>/property/new
create the default mock sensor and assign to comm
<device> curl -X POST http://127.0.0.1:8989/api/device/<device id>/property/<property id>/mock/new

PUT
<device> curl -d "{comm}" -H "Content-Type: application/json" -X POST http://127.0.0.1:8989/api/device/<device id>/property/<property id>

DELETE
<devices> curl -X DELETE http://127.0.0.1:8989/api/device/<device id>/property/<property id>

GET
<devices> curl http://127.0.0.1:8989/api/device/<device id>/property/<property id>

This is how to use the comm object to define a data receive property

runloop not required

EXAMPLE

{
    "_id": "61cdc84c-20e8-4066-9e39-22a3868719bf",
    "_type": "property",
    "enabled": true,
    "name": "c2dProperty_a8e3",
    "color": "#383a1e",
    "interface": "(single interface only)",
    "string": false,
    "value": 0,
    "sdk": "twin",
    "propertyObject": {
        "type": "default"
    },
    "version": 0,
    "type": {
        "mock": false,
        "direction": "c2d"
    }
}

POST
create the comm with defaults
<device> curl -d "{type:'c2d'}" -H "Content-Type: application/json" -X POST http://127.0.0.1:8989/api/device/<device id>/property/new\

PUT
update comm and not value
<device> curl -d "{comm}" -H "Content-Type: application/json" -X POST http://127.0.0.1:8989/api/device/<device id>/property/<property id>
update comm and value
<device> curl -d "{comm}" -H "Content-Type: application/json" -X POST http://127.0.0.1:8989/api/device/<device id>/property/<property id>/value

DELETE
<devices> curl -X DELETE http://127.0.0.1:8989/api/device/<device id>/property/<property id>

GET
<devices> curl http://127.0.0.1:8989/api/device/<device id>/property/<property id>

This is how to use the comm object to define a method property

property type usage
_id string A unique id for this property. Needs to be unique for the simulation i.e. a GUID
_type string 'property' |'method'. Msg/Events and Twins are properties. Primarily used by the GUI
color string? Only used by GUI
enabled boolean Only honored when device is in a runloop. Updating a device will send value immediately
interface string Name the comm property. Not supported
status integer HTTP status code
receivedParams string The parameters sent to the device from the caller
asProperty boolean Send the result as a reported Twin reported as well
payload string The result JSON

EXAMPLE

{
    "_id": "27dfec16-128a-4cf8-bbba-89263c51f4d3",
    "_type": "method",
    "enabled": true,
    "name": "method47a2",
    "color": "#3a1e1e",
    "interface": "(single interface only)",
    "status": 200,
    "receivedParams": null,
    "asProperty": false,
    "payload": "{\n  \"result\": \"OK\"\n}"
}

POST
create the comm with defaults
<device> curl -X POST http://127.0.0.1:8989/api/device/<device id>/method/new

PUT
<device> curl -d "{comm}" -H "Content-Type: application/json" -X POST http://127.0.0.1:8989/api/device/<device id>/method/<method id>

DELETE
<devices> curl -X DELETE http://127.0.0.1:8989/api/device/<device id>/method/<method id>

GET
<devices> curl http://127.0.0.1:8989/api/device/<device id>/<method>/<method id>

Sample device object JSON

{
    "comms": [
        {
            "_id": "b07f4260-df7d-4d79-8f2d-02cf9d8c5b1f",
            "_type": "property",
            "name": "d2cProperty_1d57",
            "color": "#333333",
            "enabled": false,
            "interface": "(single interface only)",
            "string": false,
            "value": 0,
            "sdk": "msg",
            "propertyObject": {
                "type": "default"
            },
            "version": 0,
            "type": {
                "mock": true,
                "direction": "d2c"
            },
            "runloop": {
                "include": true,
                "unit": "secs",
                "value": 15
            },
            "mock": {
                "_id": "2400337d-46dd-4885-857f-306bf4761e75",
                "_hasState": false,
                "_type": "random",
                "_value": 0,
                "variance": 3,
                "init": 0,
                "_resx": {
                    "init": "Initial",
                    "variance": "Length"
                }
            }
        },
        {
            "_id": "61cdc84c-20e8-4066-9e39-22a3868719bf",
            "_type": "property",
            "enabled": true,
            "name": "c2dProperty_a8e3",
            "color": "#383a1e",
            "interface": "(single interface only)",
            "string": false,
            "value": 0,
            "sdk": "twin",
            "propertyObject": {
                "type": "default"
            },
            "version": 0,
            "type": {
                "mock": false,
                "direction": "c2d"
            }
        },
        {
            "_id": "27dfec16-128a-4cf8-bbba-89263c51f4d3",
            "_type": "method",
            "enabled": true,
            "name": "method47a2",
            "color": "#3a1e1e",
            "interface": "(single interface only)",
            "status": 200,
            "receivedParams": null,
            "asProperty": false,
            "payload": "{\n  \"result\": \"OK\"\n}"
        }
    ],
    "configuration": {
        "_kind": "dps",
        "deviceId": "any-device-id",
        "scopeId": "00SED0045",
        "dpsPayload": {},
        "sasKey": "3249cxvnkj43579fdsg+=DFS90832",
        "isMasterKey": false,
        "mockDeviceName": "My Device",
    },
    "_id": "any-device-id",
    "running": false
}

Macros and AUTO values

AUTO values are macros that are replaced with real (random) values when the device sends its data. They can be used in value fields and complex payloads (for sending random data on the leaf nodes) Replace AUTO string with a static value if the feature is not required.

Complex values must be authored using JSON so use the macro as a string (see examples). When using AUTOs, the property's type will be replaced. See the following.

  • AUTO_STRING - Use a random word from 'random-words' library
  • AUTO_BOOLEAN - Use a random true or false
  • AUTO_INTEGER - Use a random number
  • AUTO_LONG - Use a random number
  • AUTO_DOUBLE - Use a random number with precision
  • AUTO_FLOAT - Use a random number with precision
  • AUTO_DATE - Use now() ISO 8601 format
  • AUTO_DATETIME - Use now() ISO 8601 format
  • AUTO_TIME - Use now() ISO 8601 format
  • AUTO_DURATION - Use now() ISO 8601 format
  • AUTO_GEOPOINT - Use a random lat/long object
  • AUTO_VECTOR - Use a random x,y,z
  • AUTO_MAP - Use empty HashMap
  • AUTO_ENUM/* - Use a random Enum value (See below)
  • AUTO_VALUE - Use the last user supplied or mock sensor value. Honors String setting.

Enum support is possible by extending the macro to include the list of values. Values can only be integers or strings. Enums use the JavaScript style arrays i.e. [1,0] or ['foo','bar'] Append this to the end of an Enum AUTO like ...

AUTO_ENUM/['foo','bar']

The default geo location is London, UK. This can be changed in the Simulation object

Complex Examples A JSON with AUTO values and statics

{
  "complexObject": {
    "nestedObj": {
      "nestedObj": {
        "param3": "AUTO_BOOLEAN"
      },
      "param1": "AUTO_INTEGER",
      "param2": "Hello World!"
    },
    "param1": "AUTO_VALUE",
    "param2": "AUTO_STRING",
    "param3": true
  }
}

An X,Y,Z object

{
  "x": "AUTO_INTEGER",
  "y": "AUTO_INTEGER",
  "z": 150
}

An Array

['AUTO_INTEGER', 5, 'AUTO_DOUBLE', 999]

A Map - Needs static keys (Beta)

{
  "map": {
    "mapKey1": "AUTO_STRING",
    "mapKey2": "AUTO_STRING",
    "mapKey3": "AUTO_STRING"
  }
}

About

mock-device DE (Docker Edition)

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published