Uploading the firmware image
Tip: With a commercial account, you can have up to 1,000 firmware images at a time, instead of 10. See Choosing your account type for more information about the other benefits of commercial accounts and how to upgrade a free account to a commercial account.
In Portal: Uploading the firmware image
When you upload a new firmware image to Device Management, Device Management provides you with a URL to put in the manifests you send to deployed devices.
Devices use this URL to download the candidate firmware image.
To upload the firmware binary to Device Management and obtain the candidate image URL:
-
Log in to Device Management Portal for your region:
-
Select Firmware update > Images from the left menu.
-
Click the Upload image button.
-
Enter a name and a description for the image.
-
Toggle the Image file encryption switch to encrypt the image you are uploading.
-
Click the Choose file button and select the file.
-
Click the Upload firmware image button.
You can now find the new image on the Firmware image management screen.
Using the API: Uploading a small firmware image
If your image is smaller than 100 MiB (one hundred mebibytes) in total, upload your full firmware or delta update image using the POST v3/firmware-images/
API.
To encrypt the image, set datafile_encryption
to true
.
Using the API: Uploading a large firmware image
Device Management Update lets you upload large firmware images in multiple parts (chunks) where each request is less than or equal to 100 MiB (one hundred mebibytes). This is necessary if the final firmware image resource is greater than 100 MiB. You can do this using the Update Service APIs.
The minimum chunk size is 5 MiB (five mebibytes). If your firmware chunk size is under 5 MiB, the upload process will not fail until the last packet is sent. This is because firmware images are stored in an S3 bucket, and the S3 APIs don't send a message of failure until the last packet.
Summary of API interfaces
You can click on each operation to see the full API reference.
Operation | Explanation |
---|---|
POST /v3/firmware-images/upload-jobs |
Create a new upload job. |
GET /v3/firmware-images/upload-jobs |
List upload jobs. |
GET /v3/firmware-images/upload-jobs/{upload_job_id} |
View a specific upload job. |
DELETE /v3/firmware-images/upload-jobs/{upload_job_id} |
Delete an upload job. |
PUT /v3/firmware-images/upload-jobs/{upload_job_id} |
Update an upload job. |
GET /v3/firmware-images/upload-jobs/{upload_job_id}/chunks |
View metadata for uploaded chunks. |
POST /v3/firmware-images/upload-jobs/{upload_job_id}/chunks |
Append a chunk to an upload job, or mark an upload job as complete. |
GET /v3/firmware-images/upload-jobs/{upload_job_id}/chunks/{chunk_id} |
View metadata about a chunk. |
See the troubleshooting information on this page if you encounter any difficulty during an upload with multiple parts.
Creating an upload job
To create an upload job with multiple parts, use POST /v3/firmware-images/upload-jobs
with header Content-Type: application/json
:
{
"name": "<name>",
"description": "<description>"
}
The field name
must be unique for each account, and the field description
is optional. Both default to an empty string.
Note: The response bodies in this tutorial are for demonstration purposes only. Your response bodies will differ.
The POST
response consists of:
- A
201 Created
status. - A
Location
header containing the URI for the new firmware image upload job resource. - A
Content-Location
header containing the same URI. - A response body like:
{
"completed": false,
"created_at": "2018-08-31T10:49:41.736515Z",
"description": "<description>",
"etag": "2018-08-31T10:49:41.736515Z",
"firmware_image_id": "",
"id": "01658f9a586800000000000100100023",
"name": "<name>",
"object": "upload-job",
"status": "not_started",
"updated_at": "2018-08-31T10:49:41.736515Z",
}
The status is not_started
because you haven't yet uploaded any chunks for this job. The completed
field is false
until the upload job is finished.
The firmware_image_id
is empty because you haven't finished the upload. There is no corresponding firmware image resource until the job is complete.
Returning information on existing upload jobs
To see information on upload jobs, GET /v3/firmware-images/upload-jobs
, which returns a 200 OK
status and a response like:
{
"after": None,
"data": [
{
"completed": false,
"created_at": "2018-08-31T15:09:06.659124Z",
"description": "<description>",
"etag": "2018-08-31T15:09:06.659124Z",
"firmware_image_id": "",
"id": "01659087d8e300000000000100100015",
"name": "<name>",
"object": "upload-job",
"status": "in_progress",
"updated_at": "2018-08-31T15:09:06.659124Z"
},
{
"completed": false,
"created_at": "2018-08-31T15:09:06.663841Z",
"description": "<description>",
"etag": "2018-08-31T15:09:06.663841Z",
"firmware_image_id": "",
"id": "01659087d8e900000000000100100016",
"name": "<another name>",
"object": "upload-job",
"status": "not_started",
"updated_at": "2018-08-31T15:09:06.663841Z"
}
],
"has_more": False,
"limit": 50,
"object": "list",
"order": "ASC"
}
Uploading a new chunk
You must call the API each time you want to add a new chunk. The service appends data onto an existing upload.
Note: Because there is no way to specify chunk index, you can't upload chunks in parallel. Doing so results in a corrupted firmware image. Wait for a 201 Created
status before proceeding to the next chunk.
To do this, POST /v3/firmware-images/upload-jobs/{upload_job_id}/chunks
with headers:
Content-Type: binary/octet-stream
.Content-Length: <data-length>
.Content-MD5: <per-RFC1864>
.
The body must contain the binary data for the chunk.
The response consists of:
-
A
201 Created
status. -
A
Location
header containing the URI for the new firmware image upload chunk resource. -
A
Content-Location
header containing the same URI. -
JSON like:
{ "created_at": "2018-08-31T10:49:41.742352Z", "etag": "2018-08-31T10:49:41.742352Z", "hash": "e3237bc98b00f204e8800999ecff316e", "id": 1, "length": 14, "updated_at": "2018-08-31T10:49:41.742352Z" }
The id
is the chunk index, starting at 1
for the first chunk posted to the firmware image upload job and increasing by one with each uploaded chunk.
The length
reflects the number of bytes in the binary data. The binary data in a chunk must be at least 5MB, except for the last chunk of the sequence (and ignoring the zero-length chunk that finishes the upload).
The hash
field is the hexadecimal form of the Content-MD5
message integrity check.
Viewing metadata for all uploaded chunks
To view metadata for all uploaded chunks in a job, use GET /v3/firmware-images/upload-jobs/{upload_job_id}/chunks
, which returns a 200 OK
status and a response body like the one below.
This example shows two uploaded firmware image chunks. See Posting a chunk for more information on the various fields for each chunk below:
{
"after": None,
"data": [
{
"created_at": "2018-08-31T14:44:25.023959Z",
"etag": "2018-08-31T14:44:25.023959Z",
"hash": "e3237bc98b00f204e8800999ecff316e",
"id": 1,
"length": 14,
"updated_at": "2018-08-31T14:44:25.023959Z"
},
{
"created_at": "2018-08-31T14:44:25.033691Z",
"etag": "2018-08-31T14:44:25.033691Z",
"hash": "d41d8cd98f00b204e9800998ecf8427e",
"id": 2,
"length": 19,
"updated_at": "2018-08-31T14:44:25.033691Z"
}
],
"has_more": False,
"limit": 50,
"object": "list",
"order": "ASC"
}
Alternatively, if there are no chunks (either because you haven't uploaded any yet, or you completed an upload):
{
"after": None,
"data": [],
"has_more": False,
"limit": 50,
"object": "list",
"order": "ASC"
}
Viewing metadata for a specific chunk
To view metadata for a specific uploaded chunk, use GET /v3/firmware-images/upload-jobs/{upload_job_id}/chunks/{chunk_id}
:
{
"created_at": "2018-08-31T15:23:55.912834Z",
"etag": "2018-08-31T15:23:55.912834Z",
"hash": "d41d8cd98f00b204e9800998ecf8427e",
"id": 1,
"length": 14,
"updated_at": "2018-08-31T15:23:55.912834Z"
}
This returns a 200 OK
status.
Ending an upload with multiple parts
Sending a chunk with zero data length ends the upload job and creates a record of the firmware image (firmware_image_id
).
To do this, use POST /v3/firmware-images/upload-jobs/{upload_job_id}/chunks
with headers:
Content-Length: 0
.Content-MD5: <per-RFC1864>
.
Note: You still need to include headers when posting an empty response body.
This returns a 201 Created
response and Location
and Content-Location
headers as for any other chunk.
For example, if you upload four data chunks, then the POST
of a zero-length chunk returns JSON like:
{
"created_at": "2018-08-31T10:49:41.742352Z",
"etag": "2018-08-31T10:49:41.742352Z",
"hash": "d41d8cd98f00b204e9800998ecf8427e",
"id": 5,
"length": 0,
"updated_at": "2018-08-31T10:49:41.742352Z"
}
Note: You can't complete an upload that has no data. The first chunk uploaded can't be of length zero. Attempting this gives a 400 Bad Request
response. To delete an upload job, see Delete a firmware image upload job.
You can then view information about the completed firmware image upload job using GET /v3/firmware-images/upload-jobs/{upload_job_id}
, which returns JSON like:
{
"completed": true,
"created_at": "2018-08-31T10:49:41.736515Z",
"description": "<description>",
"etag": "2018-08-31T10:49:41.756045Z",
"firmware_image_id": "01658f9a587800000000000100100024",
"id": "01658f9a586800000000000100100023",
"name": "<name>",
"object": "upload-job",
"status": "completed",
"updated_at": "2018-08-31T10:49:41.756045Z"
}
View the newly created firmware image using GET /v3/firmware-images/{image_id}/
. For example, GET /v3/firmware-images/01658f9a587800000000000100100024
returns the data for the firmware image resource, with the location of the image in the datafile
field:
{
"completed:" true,
"created_at": "2018-08-31T10:49:41.751725Z",
"datafile": "http://example.com/00000000000000000000000000000001",
"datafile_checksum": "1234",
"datafile_size": 27,
"description": "<description>",
"etag": "2018-08-31T10:49:41.751725Z",
"id": "01658f9a587800000000000100100024",
"name": "<name>",
"object": "firmware-image",
"updated_at": "2018-08-31T10:49:41.755303Z"
}
Deleting a firmware image upload job
Deleting an upload job cancels any ongoing upload job and removes the upload job resource. You can't undo or continue the job after this.
To do this, use DELETE /v3/firmware-images/upload-jobs/{upload_job_id}
. The response is a 204 No Content
status and no response body.
Troubleshooting
Posting to a completed upload job
If you try to POST
to a firmware image upload job that has already finished (with status completed
), the result is a 400 Bad Request
.
409 Conflict
This conflict happens when you use POST /v3/firmware-images/upload-jobs
but already have either a /v3/firmware-images/:id
with the same name as given, or a /v3/firmware-images/upload-jobs/:id
with the same name as given.