diff --git a/index.bs b/index.bs index 36a3143..67f1ce6 100644 --- a/index.bs +++ b/index.bs @@ -562,6 +562,10 @@ This set is initially [=set/is empty|empty=]. A [=sensor=] has an associated latest reading [=ordered map|map=] which holds the latest available [=sensor readings=]. +User agent must invoke the [=Report Latest Reading Updated=] abstract operation +for every {{Sensor}} object from [=activated Sensor objects=] [=ordered set|set=] +any time a new [=sensor reading|reading=] is available. + Issue: does the [=latest reading=] map need to be tied to an origin? @@ -597,9 +601,7 @@ its associated [=sensor type=] does. A [=sensor=] has an associated reporting flag which is initially unset. -A [=sensor=] has an associated periodic reporting mode flag which is initially unset. - -A [=sensor=] has an associated current polling frequency which is initially `null`. +A [=sensor=] has an associated current sampling frequency which is initially `null`.

API

@@ -745,22 +747,24 @@ with the internal slots described in the following table: - \[[desiredPollingFrequency]] - The requested polling frequency. It is initially unset. + \[[desiredSamplingFrequency]] + The requested sampling frequency for the {{Sensor}} object. + It is initially unset. - \[[lastEventFiredAt]] - the high resolution timestamp of the latest [=sensor reading=] - that was sent to observers of the {{Sensor}} object, - expressed in milliseconds that passed since the [=time origin=]. - It is initially `null`. + \[[reading]] + A deep copy of the the latest [=sensor reading=] + for the {{Sensor}} object. + Initially, it contains [=map/entries=] with the same + [=map/keys=] as the [=map/entries=] in [=latest reading=] + [=ordered map|map=] and with all the [=map/values=] set to `null`. \[[waitingForUpdate]] - A boolean which indicates wether the observers have been updated - or whether the object is waiting for a new reading to do so. - It is initially `true`. + A boolean which indicates whether {{[[reading]]}} [=ordered map|map=] + needs to be updated after a new [=sensor reading=] was reported. + It is initially `false`. \[[identifyingParameters]] @@ -787,7 +791,7 @@ with the internal slots described in the following table: ### Sensor.timestamp ### {#sensor-timestamp} The getter of the {{Sensor/timestamp!!attribute}} attribute returns -[=latest reading=]["timestamp"]. +this.{{[[reading]]}}["timestamp"]. ### Sensor.start() ### {#sensor-start} @@ -805,7 +809,7 @@ The {{Sensor/start()}} method must run these steps or their [=equivalent=]: the [=Request Sensor Access=] abstract operation, passing it |sensor_instance| as argument. 1. If |permission_state| is "granted", - 1. Invoke [=Register a Sensor Object=] passing it |sensor_instance| as argument. + 1. Invoke [=Activate a Sensor Object=] passing it |sensor_instance| as argument. 1. Otherwise, if |permission_state| is "denied", 1. let |e| be the result of [=created|creating=] a "{{NotAllowedError!!exception}}" {{DOMException}}. @@ -819,15 +823,14 @@ The {{Sensor/start()}} method must run these steps or their [=equivalent=]: The {{Sensor/stop()}} method must run these steps or their [=equivalent=]: 1. If |sensor_instance|.{{[[state]]}} is "idle", then return. - 1. Set |sensor_instance|.{{[[state]]}} to "idle". 1. Run these sub-steps [=in parallel=]: - 1. Invoke [=Unregister a Sensor=] passing it |sensor_instance| as argument. + 1. Invoke [=Deactivate a Sensor Object=] passing it |sensor_instance| as argument. ### Sensor.onchange ### {#sensor-onchange} {{Sensor/onchange}} is an {{EventHandler}} which is called -whenever a new [=sensor reading|reading=] is available. +whenever this.{{[[reading]]}} is updated with the [=Update Reading=] abstract operation. Issue: Should this be renamed `onreading`? Should we instead add an `ondata` {{EventHandler}} for continuous data @@ -908,7 +911,7 @@ Gets the {{Error}} object passed to {{SensorErrorEventInit}}. 1. Let |sensor_instance| be a new {{Sensor}} object, 1. If [=sensor=] [=supports periodic reporting mode=] and |options|.{{frequency!!dict-member}} is [=present=], then - 1. Set |sensor_instance|.{{[[desiredPollingFrequency]]}} to |options|.{{frequency!!dict-member}}. + 1. Set |sensor_instance|.{{[[desiredSamplingFrequency]]}} to |options|.{{frequency!!dict-member}}. Note: there is not guarantee that the requested |options|.{{frequency!!dict-member}} can be respected. The actual [=frequency=] can be calculated using @@ -957,9 +960,9 @@ Gets the {{Error}} object passed to {{SensorErrorEventInit}}. -

Register a Sensor Object

+

Activate a Sensor Object

-
+
: input :: |sensor_instance|, a {{Sensor}} object. @@ -967,9 +970,12 @@ Gets the {{Error}} object passed to {{SensorErrorEventInit}}. :: None 1. Let |sensor| be the [=sensor=] associated with |sensor_instance|. - 1. Add |sensor_instance| to |sensor|'s set of [=activated Sensor objects=]. 1. Invoke the [=Set Sensor Settings=] abstract operation, passing it |sensor| as argument. + 1. Add |sensor_instance| to |sensor|'s set of [=activated Sensor objects=]. + 1. Set |sensor_instance|.{{[[state]]}} to "activated". + 1. [=Fire an event=] named "activate" at |sensor_instance|. + + based on |options| of each |sensor_instance| from |sensor|'s associated [=ordered set|set=] + of [=activated Sensor objects=].
-

Observe a Sensor

- -
+

Calculate Reporting Frequency

- Issue: This needs to be refactored in an abstract operation - that has access to the {{Sensor}} instance |sensor_instance| - that just got started. +
: input - :: |sensor|, a [=sensor=]. - : output - :: None - - - 1. If |sensor|'s |latest reading|["timestamp"] is not `null`, - invoke the [=update observers=] abstract operation passing it |sensor_instance| - and |latest reading|["timestamp"] as arguments. - 1. Otherwise, poll |sensor| immediately. - - Issue: How do we handle this for [=sensors=] that - do not provide values immediately? - Fire a dedicated event to signal brokenness? - - 1. If |sensor|'s [=periodic reporting mode flag=] is set, - 1. let |frequency| be the [=current polling frequency=], - capped by the upper and lower bounds of the underlying hardware. - - Issue: Should this max polling frequency be reflected in the {{Sensor}} interface? - E.g. Through a dedicated attribute? - - Issue: Does the max polling frequency affect the reporting frequency? - If so, should we advise the developer of this issue? - E.g. via a dedicated event? - 1. Poll |sensor| at |frequency|. - 1. Issue: Hook into the `requestAnimationFrame` framework [[HTML]] - to invoke the [=update latest reading=] abstract operation - with every new frame passing it |sensor| and - the latest [=sensor reading=] as arguments. - - Issue: Relying on `requestAnimationFrame` gives us a perfect point - to buffer readings > 60Hz and to pass them to together with every new frame. - That's a level 2 feature. - - Issue: Figure out how to handle sensors/platforms that push the data - rather than wait for it to be polled. - 1. If the [=periodic reporting mode flag=] is unset, - 1. the user-agent can decide on the best reporting strategy - for this particular |sensor| and [=sensor type=]. - - Issue: This needs to be defined better. -
- - -

Is Current Reporting Mode Periodic

- -
- - : input - :: |sensor|, a [=sensor=]. - : output - :: |result|, a boolean. - - 1. Let |result| be `false`. - 1. [=list/For each=] |sensor_instance| in |sensor|'s set of [=activated Sensor objects=]: - 1. if |sensor_instance|.{{[[desiredPollingFrequency]]}} is set, - 1. set |result| to `true`, then [=break=]. - 1. return |result|. -
- - -

Find the polling frequency of a Sensor

- -
- - : input - :: |sensor|, a [=sensor=]. + :: |sensor_instance|, a {{Sensor}} object. : output :: |frequency|, a [=frequency=]. - 1. Let |frequency| be `null`. - 1. [=set/For each=] |sensor_instance| in |sensor|'s set of [=activated Sensor objects=]: - 1. let |f| be |sensor_instance|.{{[[desiredPollingFrequency]]}}. - 1. if |f| is set and |f| is greater than |frequency|, - 1. set |frequency| to |f|. + 1. Let |f| be |sensor_instance|.{{[[desiredSamplingFrequency]]}}. + 1. if |f| is set, + 1. set |frequency| to |f| capped by the upper and lower [=sampling frequency=] + bounds for the associated [=sensor=]. + 1. Otherwise, + 1. user agent can assign |frequency| to an appropriate value. 1. return |frequency|.
-

Update latest reading

+

Report Latest Reading Updated

-
+
: input - :: |sensor|, a [=sensor=]. - :: |reading|, a [=sensor reading=]. - :: |reading_timestamp|, the timestamp at which [=sensor=] was polled. - - Issue: The timestamp needs to be specified more precisely, - see [issue #155](https://github.com/w3c/sensors/issues/155). + :: |sensor_instance|, a {{Sensor}} object. : output :: None - 1. If |sensor|’s [=reporting flag=] is set, - 1. abort these steps. - 1. If |reading_timestamp| is equal [=latest reading=]["timestamp"], - 1. abort these steps. - 1. Set |sensor|’s [=reporting flag=]. - 1. [=map/Set=] [=latest reading=]["timestamp"] to |reading_timestamp|. - 1. [=map/For each=] |key| → |value| of [=latest reading=]. - 1. If |key| is "timestamp", [=continue=]. - 1. [=map/Set=] [=latest reading=][|key|] to the corresponding - value of |reading|. - - Issue: Maybe compare |value| with corresponding - value of |reading| to see if there's a change - that needs to be propagated. - 1. Unset |sensor|’s [=reporting flag=]. + 1. If |sensor_instance|.{{[[waitingForUpdate]]}} is `true`, + 1. Abort these steps. + 1. Set |sensor_instance|.{{[[waitingForUpdate]]}} to `true`. + 1. Let |lastReportedTimestamp| be |sensor_instance|.{{[[reading]]}}["timestamp"]. + 1. If |lastReportedTimestamp| is not set + 1. Invoke the [=Update Reading=] abstract operation, passing it |sensor_instance| as argument. + 1. Abort these steps. + 1. Let |reportingFrequency| be result of invoking the "Calculate Reporting Frequency" abstract operation. + 1. If |reportingFrequency| is not set + 1. Invoke the [=Update Reading=] abstract operation, passing it |sensor_instance| as argument. + 1. Abort these steps. + 1. Let |reportingInterval| be the result of 1 / |reportingFrequency|. + 1. Let |timestampDelta| be the result of [=latest reading=]["timestamp"] - |lastReportedTimestamp|. + 1. If |timestampDelta| is less than or equal to |reportingInterval| + 1. Invoke the [=Update Reading=] abstract operation, passing it |sensor_instance| as argument. + 1. Abort these steps. + 1. Let |deferUpdateTime| be the result of |reportingInterval| - |timestampDelta|. + 1. User agent must defer invoking of the [=Update Reading=] abstract operation for a period of time + equal to |deferUpdateTime|.
+

Update Reading

-

Update Observers

- -
+
: input :: |sensor_instance|, a {{Sensor}} object. - :: |timestamp|, a high resolution timestamp. : output :: None - 1. If |sensor_instance|.{{[[state]]}} is "activating": - 1. Set |sensor_instance|.{{[[state]]}} to "activated". - 1. [=Fire an event=] named "activate" at |sensor_instance|. - 1. If |sensor_instance|.{{[[waitingForUpdate]]}} is true, then - - Issue: Should we fire delayed readings? Or should we just drop readings instead? - - 1. Set |sensor_instance|.{{[[waitingForUpdate]]}} to `false`. - 1. [=Fire an event=] named "reading" at |sensor_instance|. - 1. Set |sensor_instance|.{{[[lastEventFiredAt]]}} to |timestamp|. - - Issue: Should these last steps be done from within a new task? + 1. [=map/For each=] |key| → |value| of [=latest reading=]. + 1. [=map/Set=] |sensor_instance|.{{[[reading]]}}[|key|] to the corresponding + value of [=latest reading=]. + 1. Set |sensor_instance|.{{[[waitingForUpdate]]}} to `false`. + 1. [=Fire an event=] named "change" at |sensor_instance|.
@@ -1212,8 +1114,9 @@ Gets the {{Error}} object passed to {{SensorErrorEventInit}}. :: |error|, an [=exception=]. : output :: None - - 1. Set |sensor_instance|.{{[[state]]}} to "idle". + 1. If |sensor_instance|.{{[[state]]}} is "activated", + 1. Invoke [=Deactivate a Sensor Object=] passing it |sensor_instance| as argument. + 1. Otherwise, set |sensor_instance|.{{[[state]]}} to "idle". 1. [=Fire an event=] named "error" at |sensor_instance| using {{SensorErrorEvent}} with its {{SensorErrorEvent/error!!attribute}} attribute initialized to |error|.