|
| 1 | +# Sending observed time in device payload |
| 2 | + |
| 3 | +## The `timeObserved` property |
| 4 | + |
| 5 | +Digital twins with telemetry in structured format will by default set the Time Observed |
| 6 | +property to the time the payload was received. |
| 7 | + |
| 8 | +You can override this with data from the payload by assigning the `timeObserved` property |
| 9 | +in the envelope mapping section of the digital twin adapter envelope. |
| 10 | + |
| 11 | +If a default adapter is used, the generated envelope will already contain a mapping: |
| 12 | + |
| 13 | +```json |
| 14 | +"envelopeMapping": { |
| 15 | + "timeObserved": "$.time" |
| 16 | +} |
| 17 | +``` |
| 18 | + |
| 19 | +This means that if a `time` field is present in the payload, it will be used as the |
| 20 | +observed time; if not, it will default to the received time. |
| 21 | + |
| 22 | +## Data format |
| 23 | + |
| 24 | +The `timeObserved` property is a POSIX time expressed in microseconds; that is: the |
| 25 | +number of microseconds that have elapsed since January 1, 1970 (midnight UTC/GMT), also |
| 26 | +known as Unix time or Epoch time. |
| 27 | + |
| 28 | +The following sample payload (from the [publish-mqtt](../../python/publish-mqtt/) |
| 29 | +example) will set the observed time to: Wednesday, September 10, 2025 13:47:05.226854 UTC: |
| 30 | + |
| 31 | +```json |
| 32 | +{ |
| 33 | + "time": 1757512025226854, |
| 34 | + "sht_temperature": 23.8, |
| 35 | + "qmp_temperature": 24.4, |
| 36 | + "humidity": 56.1, |
| 37 | + "pressure": 1012.2, |
| 38 | + "count": 1, |
| 39 | +} |
| 40 | +``` |
| 41 | + |
| 42 | +## Conversion |
| 43 | + |
| 44 | +If the device sends a date string (e.g. in ISO-8601 format), it must be converted to the |
| 45 | +above format in the envelope mapping. |
| 46 | + |
| 47 | +The IoT Platform mappings can be done with JsonPath or JQ expression. To facilitate the |
| 48 | +conversion of a date string to POSIX time format, the Platform provides an additional |
| 49 | +JQ function: `fromdateformat` |
| 50 | + |
| 51 | +To accept a payload in the following format: |
| 52 | + |
| 53 | +```json |
| 54 | +{ |
| 55 | + "iso_time": "2025-09-10T13:47:05.226854Z", |
| 56 | + "sht_temperature": 23.8, |
| 57 | + ... |
| 58 | +} |
| 59 | +``` |
| 60 | + |
| 61 | +we can use the following envelope mapping: |
| 62 | + |
| 63 | +```json |
| 64 | +"envelopeMapping": { |
| 65 | + "timeObserved": "${.iso_time | fromdateformat(\"yyyy-MM-dd'T'HH:mm:ss.SSSSSS'Z'\")}" |
| 66 | +} |
| 67 | +``` |
| 68 | + |
| 69 | +The patterns used for parsing are compatible with the [Java DateTimeFormatter](https://docs.oracle.com/en/java/javase/23/docs/api/java.base/java/time/format/DateTimeFormatter.html#patterns). |
| 70 | + |
| 71 | +Note that such conversion might fail if the payload field (`iso_time` in this case) is missing |
| 72 | +from the payload, as the function might not accept a null value. |
| 73 | +If the field is optional, null values should be handled in the expression. For example: |
| 74 | + |
| 75 | +```json |
| 76 | +"envelopeMapping": { |
| 77 | + "timeObserved": "${if .iso_time == null then null else .iso_time | fromdateformat(\"yyyy-MM-dd'T'HH:mm:ss.SSSSSS'Z'\") end}" |
| 78 | +} |
| 79 | +``` |
0 commit comments