Proximity and Ambient Light Sensor

The Librem 5 development board has a proximity sensor (PS) and ambient light sensor (ALS) provided by the VCNL4040M3OE-H5 module. At a low level, these sensors can be accessed programmatically via messages sent to the relevant addresses on the appropriate I2C bus. Applications will typically receive sensor information by accessing the appropriate system D-Bus interface.

This guide provides a basic overview of the commands that can be used to obtain ambient light and proximity information from the device; first via the D-Bus interface, then using the I2C bus.

D-Bus Interface

The sensors are exposed to applications via the net.hadess.SensorProxy service on the system D-Bus. This is provided by the iio-sensor-proxy service.

Information from the sensors can be obtained by querying the interface provided by the D-Bus service, calling methods to access devices and reading their properties.

Preparations

If the iio-sensor-proxy daemon is not already running, start it from the command line in the following way:

systemctl start iio-sensor-proxy

Check that it is running with this command:

systemctl status iio-sensor-proxy

This should include useful information to help diagnose problems if the service does not start.

Introspecting the D-Bus Object

It is useful to get an overview of the properties and methods that the service exposes via D-Bus. Use the gdbus tool from the command line to discover these:

gdbus introspect --system --dest net.hadess.SensorProxy \
                          --object-path /net/hadess/SensorProxy

Monitor the Sensor

It can be useful to quickly check that the sensors are working by running the monitor-sensor tool, as shown in this shell output:

purism@pureos:-$ monitor-sensor
    Waiting for iio-sensor-proxy to appear
+++ iio-sensor-proxy appeared
=== Has accelerometer (orientation: bottom-up)
=== Has ambient light sensor (value: 0.000000, unit: lux)
=== No proximity sensor

The tool outputs information from all sensors. By filtering the output from monitor-sensor you can see changes to the sensor you are interested in.

purism@pureos:~$ monitor-sensor | grep Light
    Light changed: 1.440000 (lux)
    Light changed: 1.800000 (lux)
    Light changed: 16.560000 (lux)
    Light changed: 8.040000 (lux)
    Light changed: 1.440000 (lux)
    Light changed: 3.240000 (lux)
    Light changed: 0.000000 (lux)

This provides verification that the sensor is reporting changes via the D-Bus interface.

Reading the Ambient Light Level

Using the gdbus tool again, first check that the ambient light sensor is available to be read:

gdbus call --system --dest net.hadess.SensorProxy \
                    --object-path /net/hadess/SensorProxy \
                    --method org.freedesktop.DBus.Properties.Get \
                             net.hadess.SensorProxy HasAmbientLight

If it returns (<true>,) then you can claim the sensor:

gdbus call --system --dest net.hadess.SensorProxy \
                    --object-path /net/hadess/SensorProxy \
                    --method net.hadess.SensorProxy.ClaimLight

This will cause the LightLevel property to be updated:

gdbus call --system --dest net.hadess.SensorProxy \
                    --object-path /net/hadess/SensorProxy \
                    --method org.freedesktop.DBus.Properties.Get \
                    net.hadess.SensorProxy LightLevel

Finally, release the sensor to stop the service from polling the device:

gdbus call --system --dest net.hadess.SensorProxy \
                    --object-path /net/hadess/SensorProxy \
                    --method net.hadess.SensorProxy.ReleaseLight

This can also be performed using the Gio.DBusProxy class – see the GNOME API Reference for further information.

Reading the Proximity

Note

Support for the proximity sensor is currently not in the mainline kernel.

Check that the proximity sensor light is available to be read:

gdbus call --system --dest net.hadess.SensorProxy \
                    --object-path /net/hadess/SensorProxy \
                    --method org.freedesktop.DBus.Properties.Get \
                             net.hadess.SensorProxy HasProximity

If it returns (<true>,) then you can claim the sensor:

gdbus call --system --dest net.hadess.SensorProxy \
                    --object-path /net/hadess/SensorProxy \
                    --method net.hadess.SensorProxy.ClaimProximity

This will cause the ProximityNear property to be updated:

gdbus call --system --dest net.hadess.SensorProxy \
                    --object-path /net/hadess/SensorProxy \
                    --method org.freedesktop.DBus.Properties.Get \
                    net.hadess.SensorProxy ProximityNear

Finally, release the sensor to stop the service from polling the device:

gdbus call --system --dest net.hadess.SensorProxy \
                    --object-path /net/hadess/SensorProxy \
                    --method net.hadess.SensorProxy.ReleaseProximity

This can also be performed using the Gio.DBusProxy class – see the GNOME API Reference for further information.