Sensors
The Generic Sensor API: accelerometer, gyroscope, magnetometer, the two orientation sensors, gravity, linear acceleration and ambient light - each with its own sample rate and permission.
@inject Bit.Butil.Sensors sensorsMDN reference
Accelerometer and not
Magnetometer, and a device can ship neither. A Permissions-Policy on
the document can also block a sensor, which arrives on the error callback rather than as an
exception.
deviceorientation / devicemotion events. What these sensors add is an
explicit frequency, a per-sensor permission model, an error channel, and hardware the legacy
events never exposed: magnetometer, gravity and ambient light.
IsSupported reports whether the constructor exists. QueryPermission reports the permission state - it is a query only, since sensor permissions cannot be requested on their own; the prompt, where an engine has one, happens on the first Subscribe.
@inject Bit.Butil.Sensors sensors
var supported = await sensors.IsSupported(SensorType.Accelerometer);
PermissionState state = await sensors.QueryPermission(SensorType.Accelerometer);Starts a sensor and calls back on every reading. The eight sensors report different quantities, so a reading carries all of them and leaves the ones this sensor does not produce as null. Frequency is a hint the platform is free to ignore; MinIntervalMs is the rate limit that actually holds, applied in JS so a 60 Hz sensor does not spend 60 interop round-trips a second. Dispose the subscription to stop - a running sensor keeps hardware awake.
await using var subscription = await sensors.Subscribe(
SensorType.Accelerometer,
reading => Console.WriteLine($"{reading.X}, {reading.Y}, {reading.Z}"),
new SensorOptions { Frequency = 10, MinIntervalMs = 100 },
onError: message => Console.WriteLine(message));API reference
ValueTask<bool> IsSupported(SensorType type)ValueTask<PermissionState> QueryPermission(SensorType type)ValueTask<ButilSubscription> Subscribe(SensorType type, Action<SensorReading> onReading, SensorOptions? options = null, Action<string>? onError = null)ValueTask DisposeAsync()void InvokeSensorReading(Guid id, SensorReading reading)void InvokeSensorError(Guid id, string message)enum SensorType { Accelerometer, Gyroscope, Magnetometer, AbsoluteOrientation, RelativeOrientation, Gravity, LinearAcceleration, AmbientLight }class SensorOptions { double? Frequency; SensorReferenceFrame? ReferenceFrame; int MinIntervalMs = 100; }enum SensorReferenceFrame { Device, Screen }class SensorReading { string Type; double Timestamp; double? X; double? Y; double? Z; double[]? Quaternion; double? Illuminance; }