Adding Machine Analytics Support to New Printers¶
This document is designed to assist printer manufacturers in the steps necessary to add native support for Authentise Machine Analytics to their printers. The goal is to allow the printer to be connected through a network to a computer that can harvest status information about the printer on an ongoing basis. This data can then be used to make high-level decisions around inventory management, capacity planning, and maintenance.
Authentise Machine Analytics harvests data from printers using a program called Echo. Echo speaks many protocols natively to accomodate different printers. Printers with built-in support for Echo communicate via HTTP over TCP/IP on port 80. The printer should start a web server internally after startup that is able to service HTTP requests on port 80. Data transferred via HTTP should be formatted as JSON.
GET /status/¶
There are two endpoints that the printer should support. The first is a status endpoint which responds to an HTTP request with the path /status/
. This endpoint returns the current status information of the printer. It should respond with all of the following properties contains within a JSON object
Property Name | Property Type | Description |
---|---|---|
current_build | object | An object containing information about the current build if any, otherwise ‘null’ |
current_build.estimated_end_time | string (ISO 8601 datetime in UTC timezone) | The date and time and timezone when the current build is estimated to complete |
current_build.id | string | A programmatically generated unique ID for the current build. This should ideally be a UUID |
current_build.name | string | The user-supplied name of the current build |
current_build.percent_completed | float | A number from 0.0 to 100.0 indicating the amount of the total material for the build has been consumed |
current_build.start_time | string (ISO 8601 datetime in UTC timezone) | The date and time and timezone when the current build started |
errors | array | An array of short strings that identify any error states for the printer |
errors.N.code | string | A short string meant to be a stable, machine-readable indicator of the type of error |
errors.N.detail | string (may be localized) | A long-form explanation of the error and possible remedies the user could use |
materials | array | An array of objects detailing the materials that are loaded into the printer |
materials.N.expiration | string (ISO8601 datetime in UTC timezone) | The date when the material will expire, if any. Otherwise ‘null’ |
materials.N.id | string | A unique identifier for this particular material type |
materials.N.quantity | float | The quantity of the material available in whatever units are supplied |
materials.N.units | string | The unit of measure used to determine quantity |
online_since | string (ISO 8601 datetime in UTC timezone) | The date and time and timezone when the printer came online |
sensors | array | An array of objects detailing current sensor states |
sensors.N.name | string | The name of the sensor |
sensors.N.taken | string (ISO 8601 datetime in UTC timezone) | The date, time, and timezone the sensore reading was recorded or taken |
sensors.N.units | string | The units used in the sensor |
sensors.N.value | string/float/boolean/integer | The value of the sensor |
status | string | The current status of the printer (printing, idle, warming, preparing, error, etc) |
current_build¶
The current build property should be set to null
if the printer is not currently printing or building any parts. Otherwise it should be set to an object with the following properties
current_build.estimated_end_time¶
The estimated_end_time
property should be a date and time when the machine currently estimates that the build should complete. No particular algorithm for estimation is implied or required and the estimate can be calculated to service each request or it can be calculated once and stored. For processes that require curing, cooldown or other “ramping-down” processes this estimate should include the time for ramp-down. The estimate should target the first moment when a technician could safely remove the completed build from the printer.
current_build.id¶
The id
property for the current build should be a globally unique identifier. In other words, the ID should not conflict between two printers of the same model installed in the same location. For this reason they should be automatically generated via software. It is strongly recommended that a standards-compliant UUID be used for this purpose. This value will be used to uniquely identify two build that happened on the same printer with the same parameters using the same input data that happened at different times.
current_build.name¶
The name
property should be the user-supplied name for the build. This value may be duplicated between builds on the same or different printers. The user should have been given some opportunity to control the name
at some point during the preparation of the build. If not, this value can be null
current_build.percent_completed¶
The percent_completed
value is designed to give the user a sense of how much material has been consumed towards completing the build. For some printers this value may be quite different from the estimated_end_time
. For example, if a particular printer tends to use most material in the initial stages of the print then the percent_completed
may be well over %50 when most than half the time remains between the start_time
and estimated_end_time
.
This property can be very useful for a technician to make decisions such as whether or not to fill supply hoppers or spools with additional raw materials or whether or not to abort a particular build part of the way through the process
current_build.start_time¶
This is the start date and time when the build was initiated. This is not the time when the user requested the build. It may not be the same time as when the first material was deposited for the build. It should be considered the first moment when the machine began the process of performing the build. For processes that require a warming period the time should begin when warming began.
errors¶
The errors array should contain zero or more items indicating errors the system may be having. If the printer is functioning well and has no errors this value should be []
rather than null
. This property contains an array so that a printer may report multiple simultaneous errors to a client. Each error should be a short JSON object which contains the following properties
errors.N.code¶
This is a machine-readable code that is meant to be a stable way to indicate an error type. For example, a motor could have failed on the printer. An appropriate code for this may be motor-failure
. This is a stable, meaningful value that is non-localized and generic. These values should not be translated into other languages.
errors.N.detail¶
This is a human-readable detailed message that is meant to assist users in understanding the detail of an error and what they might be able to do to solve the problem, if anything. For example, a motor could have failed on the printer. An appropriate code for this may be motor-failure
. An appropriate detail
value to go with that code could be Motor #5 has overheated. Wait one hour before proceeding to fully cool to avoid damage to the motor
. This information could also be translated into other languages.
materials¶
The materials
property contains information, if available, about the materials that are loaded and available to the printer. In situations where the printer cannot know about its own materials this property should be set to null
. In situations where the printer does know about its own materials but there are none loaded or available this value should be []
. This property is a list so that different printers that track or use varying amounts of materials can track as many materials as is appropriate for their process. Each element in the materials
array should be a JSON object with the following properties
materials.N.expiration¶
The date and time and timezone when the material is expected to expire. This may be a good-faith best estimate of an exact time or may set an amount of precision by setting other parts of the date and time to zero. For example, if expiration is expected to happen at some time in the month of October then value could be 2017-10-00T00:00:00.000+000
. If the material is not expected to expire or the expiration is unknown the value should be null
materials.N.id¶
A unique identifier for this material. This identifier should be shared between printers. In other words, if two printers both have exactly the same materials loaded in the same way then the values of the materials.N.id
properties should be the same for both. The identifier can include information about the material, such as titanium-6AL-4V
which indicates a particular alloy of Titanium, Aluminum and Vanadium. It can also be an opaque identifier such as a UUID or trademarked name.
materials.N.quantity¶
This should be the quantity of materials available in whatever units are supplied in the units
property. For that reason it should always be a floating point value. If the quantity is unknown or unknowable the value should be null
rather than 0
materials.N.units¶
The units of measure used to determine the quantity
of the material. For example, if the printer measures by unit volume the quantity
could be 1004
and the units
be milliliters
or cubic centimeters
. The quantity
could be 1.004
and the units
could be liters
. If the quantity is unknown or unknowable the value for units
should be null
online_since¶
This is the date and time and timezone of when the printer last came online. This is useful for measuring printer uptime and making determinations about scheduled maintenance
sensors¶
This is an array containing JSON objects which contain details about any sensors on the printer. If there are no sensors the value should be []
. Each object in this array should contain the following properties
sensors.N.name¶
The name of the sensor. This should be unique for the printer. For example, if there are 2 temperature sensors it could make sense to name them temperature1
and temperature2
. It may be better to disambiguate the sensor names with a description of the sensor’s purpose or location, like temperature-nozzle
and temperature-bed
.
sensors.N.taken¶
The date and time and timezone the sensor reading was taken. This could be set to the current date and time if the sensor reading is taken when the HTTP request is made to get the information. It could also be far in the past if the sensor reading is only taken periodically
sensors.N.units¶
The units used in the value returned by the value
property. For many types of sensors this should be obvious - temperature sensors would supply the temperature scale (degrees celsius
or degrees kelvin
). For sensors that simply indicate whethor or not a threshold has been crossed this should indicate how to interpret the boolean - is_tripped
would mean that a value
of true
indicates that the sensor has crossed the threshold.
sensors.N.value¶
This is the value of the sensor. This may be of any valid JSON type depending on the sensor. Temperature sensors may be floating point values in degrees. In that cause the units
property should indicate which temperature scale is in use (Celsius, Kelvin). The sensor may be a simple trigger sensor indicating a threshold has been crossed, in which case the value
could be the value true
. In that case the units
would be set to is_tripped
.
status¶
This indicates the printers general status. Manufacturers should be free to include their own statuses that are relevant to their build process, but should consider using some of the following standard statuses
Status | Description |
---|---|
offline | The printer has been disabled, perhaps for maintenance purposes, and is not able to take on new jobs and is not building |
error | The printer has some kind of failure and cannot continue building or take on new jobs |
idle | The printer is currently online and able to take on new jobs. It is not currently building anything |
preparing | The printer has a build and is preparing for the build in some way, but it has not yet started to consume material for the build |
building | The printer is currently building something |
finishing | The printer has a build and is finalizing the build in some way. It has fully consumed all materials for the build that will be consumed, but it is not yet ready for the completed build to be removed |
occupied | The printer has completed its previous build and would be idle, but the finished build needs to be removed first |
Examples¶
Here is an example of several requests to GET /status/
GET /status/
Content-Type: application/json
{
"current_build" : null,
"errors" : [],
"materials" : [{
"expiration" : "2017-12-31T00:00:00.000+000",
"id" : "PLA-green-3mm",
"quantity" : 15.7,
"units" : "meters",
},{
"expiration" : "2018-01-31T00:00:00.000+000",
"id" : "HIPS-natural-3mm",
"quantity" : 11.3,
"units" : "meters",
}],
"online_since" : "2017-10-03T04:45:32+000",
"sensors" : null,
"status" : "idle"
}
The request above shows a printer that is currently not building anything and has no errors. It has two types of materials loaded, nearly 16 meters of green PLA and 11 meters of HIPS in a natural tone. There are no sensors on this printer that report back. This is a relatively simple report that is common for some low-end FDM printers
GET /status/
Content-Type: application/json
{
"current_build" : {
"estimated_end_time": "2017-10-08T05:42:57+000",
"id" : "d142ce8d-3973-4d84-9c82-a35a31d1156d",
"name" : "iPhone case",
"percent_completed" : 0.0,
"start_time" : "2017-10-08T03:22:43+000",
},
"errors" : [],
"materials" : null,
"online_since" : "2017-10-03T04:45:32+000",
"sensors" : [{
"name" : "chamber temperature",
"taken" : "2017-10-08T03:22:44.536+000",
"units" : "C",
"value" : 267.3,
}],
"status" : "preparing",
}
This is a status report from a printer that is building an iPhone case. The printer has not yet started to apply materials to the build which we can tell because the percent_completed
property indicate no material has yet been consumed and the status
property indicates the printer is preparing
which means it has not yet started to consume material for the build. There is a single sensor reporting from this printer which indicates the chamber is at 267.3 degrees celsius. The build is estimated to complete a little over two hours after the build started.
GET /status/
Content-Type: application/json
{
"current_build" : {
"estimated_end_time": "2017-10-08T05:42:57+000",
"id" : "d142ce8d-3973-4d84-9c82-a35a31d1156d",
"name" : "iPhone case",
"percent_completed" : 12.7,
"start_time" : "2017-10-08T03:22:43+000",
},
"errors" : [{
"code" : "out-of-material",
"detail" : "The hopper has been emptied, please refill it"
},{
"code" : "build-envelope-below-temp",
"detail" : "The build envelope temperature has fallen below 300C"
}],
"materials" : null,
"online_since" : "2017-10-03T04:45:32+000",
"sensors" : [{
"name" : "chamber temperature",
"taken" : "2017-10-08T04:03:37.536+000",
"units" : "C",
"value" : 267.3
}],
"status" : "error"
}
This is the same printer as the previous example but taken a little later when the build has failed. This particular build has failed because it has run out of material. A technician then opened the build envelope door and caused the temperature to fall. The printer is dutifully reporting both error states and indicating through the status
property that the build is now in error and cannot proceed without intervention.
GET /history/¶
Beyond the immediate status of the printer, Echo requires information about the history of what the printer has done. This is very useful in situations where users add Echo to an existing installation and want historical data about how their printers have been used. The GET /history/
endpoint provides that historical information about prints. The endpoint returns an array of JSON objects. Ongoing builds should not be included in this list. Each object in the array should have the following properties
Name | Type | Description |
---|---|---|
end_time | string (ISO 8601 datetime in UTC timezone) | The date and time and timezone when the build completed |
id | string | A programmatically generated unique ID for the build. This should ideally be a UUID |
materials | list | A list of the materials used in the build |
materials.N.id | string | A unique identifier for this particular material type |
materials.N.quantity | float | The quantity of the material used in whatever units are supplied |
materials.N.units | string | The unit of measure used to determine quantity |
name | string | The user-supplied name of the build |
percent_completed | float | A number from 0.0 to 100.0 indicating the amount of the total material for the build that was consumed. |
start_time | string (ISO 8601 datetime in UTC timezone) | The date and time and timezone when the current build started |
status | string | The status of the build (completed, cancelled, failed) |
end_time¶
The date, time, and timezone when the build completed, failed or was cancelled. This should be formatted as an ISO 8601 datetime with timezone information
id¶
The id
property for the build should be a globally unique identifier. In other words, the ID should not conflict between two printers of the same model installed in the same location. For this reason they should be automatically generated via software. It is strongly recommended that a standards-compliant UUID be used for this purpose. This value will be used to uniquely identify two builds that happened on the same printer with the same parameters using the same input data that happened at different times.
materials¶
The materials
property contains information, if available, about the materials that were used in the build. In situations where the printer cannot know about its own materials this property should be set to null
. This property is a list so that different printers that track or use varying amounts of materials can track as many materials as is appropriate for their process. Each element in the materials
array should be a JSON object with the following properties
materials.N.id¶
A unique identifier for this material. This identifier should be shared between printers. In other words, if two printers both have exactly the same materials loaded in the same way then the values of the materials.N.id
properties should be the same for both. The identifier can include information about the material, such as titanium-6AL-4V
which indicates a particular alloy of Titanium, Aluminum and Vanadium. It can also be an opaque identifier such as a UUID or trademarked name.
materials.N.quantity¶
This should be the quantity of materials used for the build in whatever units are supplied in the units
property. For that reason it should always be a floating point value. If the quantity is unknown or unknowable the value should be null
rather than 0
materials.N.units¶
The units of measure used to determine the quantity
of the material. For example, if the printer measures by unit volume the quantity
could be 1004
and the units
be milliliters
or cubic centimeters
. The quantity
could be 1.004
and the units
could be liters
. If the quantity is unknown or unknowable the value for units
should be null
name¶
The name
property should be the user-supplied name for the build. This value may be duplicated between builds on the same or different printers. The user should have been given some opportunity to control the name
at some point during the preparation of the build. If not, this value can be null
percent_completed¶
The percent_completed
should indicate how much of the total expected material was consumed towards completing the build. This value should be expressed as a value between 0 and 100.0 that is the percentage of the material expected that was used.
start_time¶
This is the start date and time when the build was initiated. This is not the time when the user requested the build. It may not be the same time as when the first material was deposited for the build. It should be considered the first moment when the machine began the process of performing the build. For processes that require a warming period the time should begin when warming began.
status¶
This should be the final status of the build. Manufacturers may include additional status values that makes sense for their process, but should consider using one of the following statuses to be consistent with other printer manufacturers.
Value | Description |
---|---|
cancelled | The build was cancelled before completing at the users request |
completed | The build completed successfully and completely |
failed | The build failed for some reason. This may include unavailability of raw materials, mechanical failure, power outtage, etc. |
Examples¶
Here are some example requests to the /history/
endpoint
GET /history/
Content-Type: application/json
[{
"end_time" : "2017-10-04T08:15:33+000",
"id" : "c0ffea27-cd13-4743-9e8d-0336d5dd3e2b",
"materials" : null,
"name" : "iPhone case",
"percent_completed" : 100.0,
"start_time" : "2017-10-04T06:43:01+000",
"status" : "completed",
},{
"end_time" : "2017-10-04T03:12:03+000",
"id" : "757d2dfd-8fff-4f5e-8ff9-42c6bf2df0d1",
"materials" : null,
"name" : "iPhone case",
"percent_completed" : 37.1,
"start_time" : "2017-10-04T02:47:31+000",
"status" : "failed",
}]
This is a very short history report of a printer that attempted to print an iPhone case and failed after using up about 1/3 of the total materials it needed. The user then attempted to print the same job again and was successful after about an hour and a half. The printer does not track material usage or consumption and so has no information available about the materials used in the builds
GET /history/
Content-Type: application/json
[{
"end_time" : "2017-10-04T08:15:33+000",
"id" : "09dc80d8-223d-4148-a9e5-a25df984a686"
"materials" : [{
"id" : "234894f1-ef56-4df5-9386-64a6949e7319",
"quantity" : "57.8",
"units" : "cc",
}],
"name" : "coupon175",
"percent_completed" : 100.0,
"start_time" : "2017-10-04T06:43:01+000",
"status" : "completed",
},{
"end_time" : "2017-10-04T03:12:03+000",
"id" : "926c38d0-cd2e-49f3-94c0-d3abdd19632e"
"materials" : [{
"id" : "234894f1-ef56-4df5-9386-64a6949e7319",
"quantity" : "57.8",
"units" : "cc",
},{
"id" : "a6a72068-1676-4537-bc57-c36f8d46a6c0",
"quantity" : 44,
"units" : "magazines",
}],
"name" : "test14",
"percent_completed" : 58.352
"start_time" : "2017-10-04T02:47:31+000",
"status" : "cancelled",
}]
Here is a different historical report. In this the manufacturer does not supply meaningful material IDs, but rather just UUIDs for the materials. We can see that the same material was used for the first and second prints. The first print was cancelled at the users request as it was a little passed halfway complete. We can also see an example of material consumption tracking that uses a non-standard unit, “magazine”. This is for a printer that supplies materials as discrete packages and consumes those packages as part of the build.