Commit 63ec7654 authored by David Boddie's avatar David Boddie

Add documentation for the Proximity example

parent 045c68cb
......@@ -34,3 +34,6 @@
[submodule "Apps/Examples/Sensors/Ambient_Light/app"]
path = Apps/Examples/Sensors/Ambient_Light/app
url = https://source.puri.sm/Librem5/example-apps/ambient-light.git
[submodule "Apps/Examples/Sensors/Proximity/app"]
path = Apps/Examples/Sensors/Proximity/app
url = https://source.puri.sm/Librem5/example-apps/proximity.git
.. |main-file| replace:: ``proximity.in``
.. |executable| replace:: ``proximity``
.. |desktop-entry-in| replace:: ``com.example.proximity.desktop.in``
.. |desktop-entry| replace:: ``com.example.proximity.desktop``
.. |desktop-entry-ref| replace:: desktop entry file
.. |svg-file| replace:: ``com.example.proximity.svg``
.. include:: /Apps/Examples/common/Building_the_App.txt
.. |project| replace:: https://source.puri.sm/Librem5/example-apps
.. |repo| replace:: proximity.git
.. |project-repo| replace:: ``https://source.puri.sm/Librem5/example-apps/proximity.git``
.. include:: /Apps/Examples/common/Getting_the_App.txt
.. |manifest| replace:: ``com.example.proximity.json``
.. |manifest-path| replace:: app/com.example.proximity.json
.. |app-id| replace:: com.example.proximity
.. |extra-permissions-info| replace:: We also specify the ``--system-talk-name=net.hadess.SensorProxy`` permission to request access to the `iio-sensor-proxy`_ service, using the mechanism described in the :ref:`flatpak_app_permissions_guide` guide.
.. |meson-app-module| replace:: proximity
.. |extra-module-info| replace:: The application's module is usually the last in the list:
.. include:: ../../common/Packaging_the_App.txt
.. include:: /links.txt
.. _Sensors_Proximity_example_src:
Source Files
============
Most of the code for the application is included in a single ``main.py`` file which contains an ``Application`` class to manage the running of the application and a ``Window`` class to describe the user interface.
.. contents::
:local:
Much of the code is very similar to other examples and tutorials. We will focus on the parts that are specific to this example.
Relevant Modules
----------------
In addition to the usual modules for accessing command line arguments and GTK widgets, we use a custom ``sensor`` module to enable us to access the sensors.
.. literalinclude:: app/src/main.py
:language: python3
:start-at: import sys
:end-at: from gi.repository
The ``sensor`` module is described in more detail `below <Sensors_Proximity_example_proximity_>`_.
Setting up the Application
--------------------------
The application provides an ``Application`` class with the usual methods to set up the application and perform tasks when it is run. In the ``__init__`` method we set up the application title, ID and program name to ensure that it integrates into the environment:
.. literalinclude:: app/src/main.py
:language: python3
:start-at: class Application
:end-at: set_prgname
In the ``do_activate`` method, we create the application window and show it, but we also create a ``Proximity`` object from the ``sensor`` module:
.. literalinclude:: app/src/main.py
:language: python3
:start-at: def do_activate
:end-at: claim()
The ``Proximity`` object has a ``changed`` signal that we connect to the window's ``update_info`` method.
The ``do_shutdown`` method of the application is called just before the application exits. In this method we call the ``release`` method of the ``Proximity`` object to release the sensor for other applications:
.. literalinclude:: app/src/main.py
:language: python3
:start-at: def do_shutdown
:end-at: release()
Applications should usually only claim the sensor when required and release it as soon as possible.
Creating the User Interface
---------------------------
The ``Window`` class is used to display a simple user interface that updates when new sensor data is available. We begin by a `Gtk.Label`_ widget to show the status of the sensor:
.. literalinclude:: app/src/main.py
:language: python3
:start-at: class Window
:end-at: self.add
The label will be updated when the sensor's state changes due to the signal connection in the application's ``do_activate`` method.
Responding to Updates
---------------------
As described above, the application contains a ``Proximity`` object that will emit a ``changed`` signal when the sensor's state changes. When this occurs the ``update_info`` method is called:
.. literalinclude:: app/src/main.py
:language: python3
:start-at: def update_info
:end-at: Far
The signal delivers two values in the ``sensor`` and ``near`` parameters of the method. Since there is only one ``proximity`` object in use, we simply check the value of ``near`` to determine which string to show in the label.
The information provided by the ``changed`` signal is intended to be simple, so that the GUI part of the application only needs to include code to respond to proximity sensor changes. The ``Proximity`` class hides any complexity from the main application.
.. _Sensors_Proximity_example_proximity:
The Proximity Class
-------------------
The ``sensor`` module provides the ``Proximity`` class that is used to access sensor data, using the ``Gio`` module to communicate with a D-Bus service:
.. literalinclude:: app/src/sensor.py
:language: python3
:start-at: import gi
:end-at: gi.repository
Since the ``Proximity`` class needs to emit signals, the ``GObject`` class from the ``GObject`` module is also needed. The class is derived from ``GObject`` and declares the ``changed`` signal to inform the rest of the application about sensor changes:
.. literalinclude:: app/src/sensor.py
:language: python3
:start-at: class Proximity
:end-at: }
In the ``__init__`` method of the class, we call the base class's ``__init__`` method to properly initialize it, before creating a proxy object that communicates with the ``net.hadess.SensorProxy`` service on the system D-Bus:
.. literalinclude:: app/src/sensor.py
:language: python3
:start-at: def __init__
:end-at: self.properties_changed, None)
This proxy object emits the ``g-properties-changed`` signal when any of the properties exposed by the service change. We connect this signal to the ``properties_changed`` method in this class:
.. literalinclude:: app/src/sensor.py
:language: python3
:start-at: def properties_changed
:end-at: self.emit
In the ``properties_changed`` method, we respond to changes from the D-Bus service by reading the state of the proximity sensor and emitting the ``changed`` signal. This provides only the basic information to any methods that receive it, keeping the details of the D-Bus communication separate from other components.
We also provide the ``claim`` and ``release`` methods to allow the application to start and stop using the sensor. Each of these methods check for the presence of the proximity sensor by reading the `HasProximity <net.hadess.SensorProxy.HasProximity_>`_ property of the D-Bus service:
.. literalinclude:: app/src/sensor.py
:language: python3
:start-at: def claim
:end-at: None)
In the ``claim`` method, we call the `ClaimProximity <net.hadess.SensorProxy.ClaimProximity_>`_ method if the sensor is available.
.. literalinclude:: app/src/sensor.py
:language: python3
:start-at: def release
:end-at: None)
In the ``release`` method, we call the `ReleaseProximity <net.hadess.SensorProxy.ClaimProximity_>`_ method to release it for other applications.
Summary
-------
Handling sensor data involves requesting information from the ``net.hadess.SensorProxy`` service on the system D-Bus. We create a module containing the ``Proximity`` class to communicate with the service, allowing the main application to subscribe to sensor changes by connecting to a ``changed`` signal.
The ``Proximity`` class itself performs a few tasks to make this possible, but users of this class can simply
* connect its ``changed`` signal to a callback method,
* call its ``claim`` method to start receiving updates, and
* call its ``release`` method to stop receiving updates.
Applications do not need to provide an abstraction like this one, but it can make it easier to separate sensor-handling code from GUI code.
.. include:: /links.txt
.. _examples_Sensors_Proximity_summary:
Summary
=======
Applications can access the proximity sensor by using the `DBusProxy`_ class from the ``Gio`` module to talk to a D-Bus service. The API provided by the service can also be used to access other sensors.
It can be useful to wrap the communication code in a separate class and use its API from GUI code. This example includes a simple class that performs this task.
When distributed as a flatpak, the manifest needs to include the ``--system-talk-name=net.hadess.SensorProxy`` permission that allows the application to access the ``net.hadess.SensorProxy`` service on the system D-Bus.
.. include:: /links.txt
Subproject commit b9ee82302bf51c51fdeb4ff669a8c666c518a909
.. _examples_Sensors_Proximity:
Proximity
=========
This example demonstrates a way to read values from the proximity sensor. When run, the application shows whether objects are near to the proximity sensor.
.. image:: images/screenshot.png
:scale: 50%
:align: center
:alt: A screenshot of the application running in the phone environment
In :ref:`Sensors_Proximity_example_src` we focus on the parts of the application that handle access to the proximity sensor.
.. toctree::
:maxdepth: 1
Getting_the_App
Source_Code
Building_the_App
Packaging_the_App
Summary
.. include:: /links.txt
......@@ -24,6 +24,7 @@ information about the APIs used by applications.
Networking/NetworkState/index
Files/Pictures/index
Audio/Play_Sounds/index
Sensors/Proximity/index
General/Simple_Weather/index
General/Treasure/index
......
......@@ -150,6 +150,12 @@
.. _`net.hadess.SensorProxy.HasAmbientLight`: https://developer.gnome.org/iio-sensor-proxy/1.0/gdbus-net.hadess.SensorProxy.html#gdbus-property-net-hadess-SensorProxy.HasAmbientLight
.. _`net.hadess.SensorProxy.LightLevel`: https://developer.gnome.org/iio-sensor-proxy/1.0/gdbus-net.hadess.SensorProxy.html#gdbus-property-net-hadess-SensorProxy.LightLevel
.. _`net.hadess.SensorProxy.LightLevelUnit`: https://developer.gnome.org/iio-sensor-proxy/1.0/gdbus-net.hadess.SensorProxy.html#gdbus-property-net-hadess-SensorProxy.LightLevelUnit
.. _`net.hadess.SensorProxy.ClaimProximity`: https://developer.gnome.org/iio-sensor-proxy/1.0/gdbus-net.hadess.SensorProxy.html#gdbus-method-net-hadess-SensorProxy.ClaimProximity
.. _`net.hadess.SensorProxy.HasAmbientLight`: https://developer.gnome.org/iio-sensor-proxy/1.0/gdbus-net.hadess.SensorProxy.html#gdbus-property-net-hadess-SensorProxy.HasAmbientLight
.. _`net.hadess.SensorProxy.HasProximity`: https://developer.gnome.org/iio-sensor-proxy/1.0/gdbus-net.hadess.SensorProxy.html#gdbus-property-net-hadess-SensorProxy.HasProximity
.. _`net.hadess.SensorProxy.LightLevel`: https://developer.gnome.org/iio-sensor-proxy/1.0/gdbus-net.hadess.SensorProxy.html#gdbus-property-net-hadess-SensorProxy.LightLevel
.. _`net.hadess.SensorProxy.LightLevelUnit`: https://developer.gnome.org/iio-sensor-proxy/1.0/gdbus-net.hadess.SensorProxy.html#gdbus-property-net-hadess-SensorProxy.LightLevelUnit
.. _`net.hadess.SensorProxy.ReleaseProximity`: https://developer.gnome.org/iio-sensor-proxy/1.0/gdbus-net.hadess.SensorProxy.html#gdbus-method-net-hadess-SensorProxy.ReleaseProximity
.. _`net.hadess.SensorProxy.ReleaseLight`: https://developer.gnome.org/iio-sensor-proxy/1.0/gdbus-net.hadess.SensorProxy.html#gdbus-method-net-hadess-SensorProxy.ReleaseLight
.. _`Nightly GNOME Apps`: https://wiki.gnome.org/Apps/Nightly
.. _`Ninja`: https://ninja-build.org/
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment