Community Tip - When posting, your subject should be specific and summarize your question. Here are some additional tips on asking a great question. X
The past few years has seen a tremendous explosion in the numbers of devices with Internet connectivity, and the Axeda product has continued to evolve to meet the requirements of these devices, which are often memory and CPU constrained. Beginning with the Axeda Platform 6.6 release, the Axeda Adaptive Machine Messaging Protocol (AMMP) has been available that allows any device that can make an HTTP GET/POST request to send data to the Axeda Machine Cloud. AMMP uses standard, JSON messages sent inside HTTP requests.
How to get AMMP
AMMP is a separately available product that can be added to an Axeda installation. Customers should discuss with their Account Managers to get access to the Axeda AMMP product offering. AMMP is a device codec that requires the installation of the Axeda AnyDevice Codec Server (ACS) component. This configuration presents a new endpoint for customer installations - an https://example.axeda.com instance will have an ACS instance available at https://example-connect.axeda.com. Self-hosted customers can create their own hosting/URL infrastructure, but this is the default available to Axeda On-Demand Center customers.
How to set up assets to talk AMMP
Before you can start deploying devices to talk AMMP to an Axeda instance, a Model Communication Profile must be created for any Model that is expected to communicate with the AMMP protocol. This is required in order to configure the proper egress mechanism so that the device can get access to messages waiting for it on the Axeda Platform. Attached to this document is a file called AMMP_CreateCommProfile.groovy.zip. This file contains a Groovy-based script that is copied into the Platform as a Custom Object, and then executed via Scripto - this is needed to be run for each device Model that requires access via AMMP.
First Requests
Since all requests are via HTTP, it is useful to acquire a client that can perform REST API requests. One highly recommended client is Postman (available in Chrome and standalone versions).
The first time a device connects to the Axeda Machine Cloud it should send a registration message. A registration message must contain a model and serial number and can optionally include a ping rate. The ping rate is how often the server should expect to hear from the device. The server will mark a device as off-line if it does not get a message before a configurable number ping times pass. A device should also send a registration message whenever it powers up.
Using Postman, select POST from the drop down next to the URL. Enter the URL as shown below to register a new device.
https://example-connect.axeda.com/ammp/assets/1 (Customers should use their own instances in the following examples)
Click Headers to add a header named 'Content-Type' with value of 'application/json':
Click the Body button and enter the line below. The "mn" field below should be an already registered and configured model.
{ "id": { "mn" : "ExampleModel", "sn" : "ExampleDevice-001", "tn" : 0 }, "pingRate": 60 }
Click the Send button - an HTTP 200 OK response should be the expected result. Logging into the platform and searching for 'ExampleDevice-001' should show that it is registered
Now that a device has been registered is is now possible to send live information to the Axeda Machine Cloud.
Sending information is also done with a POST to a URL. Instead of the asset's resource, we will be sending to the data resource. Using Postman, the HTTP POST request will be structured like follows:
http://example-connect.axeda.com/ammp/data/1/ExampleModel!ExampleDevice-001
Change the body as follows:
{"alarms":[{"name":"over_temp","description":"freezer hot" }]}
Click on the 'Send' button and after the response returns, the alarm can be seen in the Asset Status Page in the Axeda Machine Cloud.
Four different types of information can be sent to the data resource and any or all can be included in one POST message. All four types can have an optional time and priority field. If no time is specified, the time on the server at arrival will be added.
Alarm
Field Name | Purpose | Expected Data Type | Required? | Format, Range | Default Value | Default Behavior |
name | Identify the alarm | String | Yes | Length: 0 <= N <= ? Valid String Characters | ||
description | Describe the alarm | String | No | Length: 0 <= N <= ? | None | |
severity | Describe the severity | Integer | No | Range: 0 <= N <= 1000 | 0 | |
cause | Identify the cause | String | No | Length: 0 <= N <= ? | None | |
reason | Describe the cause | String | No | Length: 0 <= N <= ? | None | |
time | Time when the alarm occurred | No | ISO-8601 or Unix Epoch | None | Use server time if <Default Value> | |
priority | How much priority the server should give to processing | No | 1 <= N <= 100 | 1 |
Alarm Example JSON
{
"alarms": [
{
"name": "RadiationLeak",
"description": "A radiation leak has been detected",
"severity": 1000,
"cause": "CoolantPipeBurst",
"reason": "The main coolant pipe exploded",
"time": 1364443200000,
"priority": 100
}
]
}
Once alarms reach the Axeda Machine Cloud, they will be in the "Started" state. Once an alarm is received, it can be "Acknowledged", "Escalated", or "Closed".
Event
Field Name | Purpose | Expected Data Type | Required? | Format, Range | Default Value | Default Behavior |
name | Identify the event | String | Yes | Length: 0 <= N <=? Valid String Characters | ||
description | Describe the event | String | No | Length: 0 <= N <= ? | None | |
time | Time when the event occurred | Integer (Epoch Timestamp) String (ISO-8601) | No | ISO-8601 or Unix Epoch | None | Use server time if <Default Value> |
priority | How much priority the server should give to processing | Integer | No | 1 <= N <= 100 | 1 |
Event Example JSON
{
"events": [
{
"name": "RadiationLeak",
"description": "A radiation leak has been detected",
"time": 1364443200000,
"priority": 100
}
]
}
Mobile Location
Field Name | Purpose | Expected Data Type | Required? | Format, Range | Default Value | Default Behavior |
latitude | Latitude | Float | Yes | -90 <= N <= +90 | ||
longitude | Longitude | Float | Yes | -180 <= N <= +180 | ||
altitude | Altitude/Elevation | Float | No | Unbounded | ||
time | Time when the event occurred | Integer (Epoch Timestamp) String (ISO-8601 Timestamp) | No | ISO-8601 or Unix Epoch | None | Use server time if <Default Value> |
priority | How much priority the server should give to processing | Integer | No | 1 <= N <= 100 | 1 |
Location Example JSON
{
"locations": [
{
"latitude": 42.034061,
"longitude": -71.237472,
"altitude": 0.0,
"time": 1364443200000,
"priority": 100
}
]
}
Note: The platform records the history of all the mobile locations a device has reported. This has implications for the positions displayed in the Asset Status Map Charting components.
Data Item Set
Field Name | Purpose | Expected Data Type | Required? | Format, Range | Default Value | Default Behavior |
dataItems | A collection of key/value pairs | Object<String, JSON Type> | Yes | Unbounded | ||
time | Time when the data items were sampled | Integer (Epoch Timestamp) String (ISO-8601 Timestamp) | No | ISO-8601 or Unix Epoch | None | Use server time if <Default Value> |
priority | How much priority the server should give to processing | Integer | No | 1 <= N <= 100 | 1 |
Data Item Set Example JSON
{ "data" :[
{
"dataItems": {
"CurrentSong": "Comfortably Numb",
"PreviousSong": "Rain When I Die",
"NextSong": "Whole Lotta Love",
"FreeMemory": 1237.24,
"DebugModeEnabled": true
},
"time": 1364443200000, "priority": 100
},
{ "dataItems":{
"bar":"camp",
"pot1":23.3
},
"time": 1364443234000, "priority": 100 }
]}
Data Items are sent as sets that share a common recording time and priority. Data Item values follow JSON representation standards and can be: string, numeric, or Boolean.
Below is an example message showing all four information types that can be sent:
{
"alarms": [
{
"name": "RadiationLeak",
"description": "A radiation leak has been detected",
"time": 1364443200000
}
],
"events": [
{
"name": "Foo",
"description": "A Foo occurred"
}
],
"data":[
{
"dataItems":{
"bar":"camp",
"pot1":23.3},
"time": 1364443200000
}
],
"locations": [
{
"latitude": 32.00,
"longitude": -78.00
}
]
}
Polling
Axeda AMMP is designed to provide a minimalist communication protocol between devices. As such each request has egress items returned in the HTTP response body, no matter the type of data sent as the request body. This is so that extra requests to retrieve egress do not have to be made. But if a device has no updates to make, it is still able to make periodic polling requests to the Codec Server to get any egress items available to it.
This request is simply a REST request of HTTP POST to the example URL: https://example-connect.axeda.com/ammp/assets/1/ExampleModel!ExampleDevice-001 with an empty request body.
Next steps and caveats
Keep in mind that egress data can be returned in ANY HTTP response body. If a device has a programming error or a power failure occurs before the request is processed, then it is possible that request can be lost - permanently. The Axeda Platform does not replay egress items once it has been delivered to the device. Additional logical facilities are available on the Axeda Platform to be able to provide replay/retry communications to the device.
Bibliography