Skip to content

Commit

Permalink
Merge pull request #9 from nRF24/add-camel-case
Browse files Browse the repository at this point in the history
Add camel case API
  • Loading branch information
TMRh20 authored Jun 21, 2022
2 parents c843c7d + 90eafc1 commit ff659b5
Show file tree
Hide file tree
Showing 20 changed files with 755 additions and 312 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ jobs:
path: ${{ github.workspace }}/docs/_build/html

- name: upload to github pages
if: github.event_name != 'pull_request'
if: github.event_name != 'pull_request' && github.ref == 'refs/heads/main'
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
Expand Down
121 changes: 73 additions & 48 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -113,84 +113,109 @@ same version of CPython, CPU architecture, and C standard lib.
rm -r _skbuild/
3. To install a built wheel, simply pass the wheel's path and file name to ``pip install``:

.. code-block:: bash
python -m pip install dist/pyrf24-MAJOR.MINOR.PATCH-cp3X-cp3X-linux_ARCH.whl
Where the following would be replaced accordingly:

- ``MAJOR.MINOR.PATCH`` is the current version of the pyrf24 package
- ``cp3X`` is the version of python used to build the wheel (ie ``cp39`` for CPython 3.9)
The second occurrence of ``cp3X`` describes the CPython ABI compatibility.
- ``ARCH`` is the architecture type of the CPU. This corresponds to the compiler used.
On Raspberry Pi OS (32 bit), this will be ``armv7l``.

Differences in API
~~~~~~~~~~~~~~~~~~

This package intentionally adheres to `PEP8 <https://pep8.org/>`_ standards as much as possible.
This means that class members' names use snake casing (eg. ``get_dynamic_payload_size()``)
instead of using the C++ conventional camel casing (eg. ``getDynamicPayloadSize()``). However,
the older python wrappers provided with each C++ library (RF24, RF24Network, & RF24Mesh) had used
camel casing. So, the API provided by this package exposes both snake cased and camel cased
versions of the API. The camel cased API is not documented to avoid duplicate and
complicated documentation.

.. code-block:: py
radio.print_details() # documented
# can also be invoked as
radio.printDetails() # not documented
Some of the C++ functions that do not accept arguments are wrapped as a class property. But, the C++
style functions are still exposed. For example:

.. code-block:: py
radio.listen = False
# is equivalent to
radio.stopListening() # not documented
radio.listen = True
# is equivalent to
radio.startListening() # not documented
Python Type Hints
-----------------

This package is designed to only function on Linux devices. But, it is possible to install this
package on non-Linux devices to get the stub files which help auto-completion and type checking
in various development environments.

Documentation
~~~~~~~~~~~~~

Before submitting contributions, you should make sure that any documentation changes builds
successfully. This can be done locally.

Documentation Dependencies
--------------------------
successfully. This can be done locally but **on Linux only**. The documentation of API requires
this package (& all its latest changes) be installed.

This package's documentation is built with the python package Sphinx and the sphinx-immaterial theme.
It also uses the dot tool provided by the graphviz software to generate graphs.

Install Graphviz
****************

On Windows, installing Graphviz library is done differently. Check out the
`Graphviz downloads page <https://graphviz.org/download/>`_. Be sure that the ``graphviz/bin``
directory is in the ``PATH`` environment variable (there's an option in the installer for this).
After Graphviz is installed, reboot the PC so the updated ``PATH`` environment variable takes affect.
1. Install Graphviz

On Linux, just run:
.. code-block:: shell
.. code-block:: shell
sudo apt-get install graphviz
sudo apt-get install graphviz
2. Installing Sphinx necessities

Installing Sphinx necessities
*****************************
.. note::
If you installed sphinx using ``apt``, then it is likely out-of-date and will override any virtual
python environments installation of Sphinx. Simply uninstall sphinx (using ``apt``) will remedy
this problem.

.. note::
If you installed sphinx using ``apt``, then it is likely out-of-date and will override any virtual
python environments installation of Sphinx. Simply uninstall sphinx (using ``apt``) will remedy
this problem.

.. code-block:: bash
.. code-block:: bash
python -m pip install -r docs/requirements.txt
python -m pip install -r docs/requirements.txt
.. important::
If pip outputs a warning about your ``path/to/Python/Python3x/Scripts`` folder not
added to your OS environment variable ``PATH``, then you will likely get an error message like
``sphinx-build command not found`` when building the documentation. For more information on
installing sphinx, see the
`official Sphinx install instructions
<https://www.sphinx-doc.org/en/master/usage/installation.html>`_.
.. important::
If pip outputs a warning about your ``path/to/Python/Python3x/Scripts`` folder not
added to your OS environment variable ``PATH``, then you will likely get an error message like
``sphinx-build command not found`` when building the documentation. For more information on
installing sphinx, see the
`official Sphinx install instructions
<https://www.sphinx-doc.org/en/master/usage/installation.html>`_.

.. warning::
This documentation's theme requires Sphinx v4.0+. So, it is not recommended to install
sphinx from ``apt`` on Linux because the version distributed with the OS's PPA repository
may not be the most recent version of Sphinx.
.. warning::
This documentation's theme requires Sphinx v4.0+. So, it is not recommended to install
sphinx from ``apt`` on Linux because the version distributed with the OS's PPA repository
may not be the most recent version of Sphinx.

Building the Documentation
--------------------------
3. Building the Documentation

To build the documentation locally, the pyrf24 package needs to be installed first. Then run:
To build the documentation locally, the pyrf24 package needs to be installed first. Then run:

.. code-block:: bash
.. code-block:: bash
cd docs
sphinx-build -E -W . _build
cd docs
sphinx-build -E -W . _build
The ``docs/_build`` folder should now contain the html files that would be hosted on deployment.
Direct your internet browser to the html files in this folder to make sure your changes have been
rendered correctly.
The ``docs/_build`` folder should now contain the html files that would be hosted on deployment.
Direct your internet browser to the html files in this folder to make sure your changes have been
rendered correctly.

.. note::
The flags ``-E`` and ``-W`` will ensure the docs fail to build on any error or warning
(just like it does when deploying the docs online).
.. note::
The flags ``-E`` and ``-W`` will ensure the docs fail to build on any error or warning
(just like it does when deploying the docs online).
Binary file added docs/_static/Logo_large.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed docs/_static/Logo_large.png
Binary file not shown.
2 changes: 1 addition & 1 deletion docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@
html_favicon = "_static/new_favicon.ico"

# project logo
html_logo = "_static/Logo_large.png"
html_logo = "_static/Logo_large.jpg"

# split site index page into 2 pages:
# 1 with only alphabet-like links to partial lists, 1 with full listing
Expand Down
5 changes: 5 additions & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
.. include:: ../README.rst

.. toctree::
:hidden:

self

.. toctree::
:hidden:

examples

.. toctree::
:hidden:
:caption: API Reference

rf24_api
Expand All @@ -16,6 +20,7 @@
rf24_mesh_api

.. toctree::
:hidden:

topology

Expand Down
31 changes: 6 additions & 25 deletions docs/rf24_api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,33 +4,14 @@ RF24 API
Enum classes
------------

.. class:: pyrf24.rf24.rf24_crclength_e
.. autoclass:: pyrf24.rf24.rf24_crclength_e
:members: RF24_CRC_DISABLED, RF24_CRC_8, RF24_CRC_16

.. csv-table::
:header: "length (enum value)", description
.. autoclass:: pyrf24.rf24.rf24_datarate_e
:members: RF24_1MBPS, RF24_2MBPS, RF24_250KBPS

"RF24_CRC_DISABLED (0)", "to disable using CRC checksums"
"RF24_CRC_8 (1)", "to use 8-bit checksums"
"RF24_CRC_16 (2)", "to use 16-bit checksums"

.. class:: pyrf24.rf24.rf24_datarate_e

.. csv-table::
:header: "speed (enum value)", description

"RF24_1MBPS (0)", "for 1 Mbps"
"RF24_2MBPS (1)", "for 2 Mbps"
"RF24_250KBPS (2)", "for 250 kbps"

.. class:: pyrf24.rf24.rf24_pa_dbm_e

.. csv-table::
:header: "level (enum value)", "nRF24L01 description", "Si24R1 description when LNA enabled", "Si24R1 description when LNA disabled"

"RF24_PA_MIN (0)", "-18 dBm", "-6 dBm", "-12 dBm"
"RF24_PA_LOW (1)", "-12 dBm", "-0 dBm", "-4 dBm"
"RF24_PA_HIGH (2)", "-6 dBm", "3 dBm", "1 dBm"
"RF24_PA_MAX (3)", "0 dBm", "7 dBm", "4 dBm"
.. autoclass:: pyrf24.rf24.rf24_pa_dbm_e
:members: RF24_PA_MIN, RF24_PA_LOW, RF24_PA_HIGH, RF24_PA_MAX

RF24 class
----------
Expand Down
7 changes: 7 additions & 0 deletions docs/rf24_mesh_api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,13 @@ Advanced RF24Mesh API
AddrListStruct class
--------------------

The properties of this class are read-only because they can only be set by the master node upon
successful connection to a child node.

.. hint::
The `AddrListStruct` class supports the python "magic method" :py:func:`repr()`. So, you can
easily pass an instantiated `AddrListStruct` object to the :py:func:`print()` function.

.. autoclass:: pyrf24.rf24_mesh.AddrListStruct
:members:

Expand Down
11 changes: 10 additions & 1 deletion docs/rf24_network_api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,19 @@ External Systems or Applications
RF24NetworkHeader class
-----------------------

.. hint::
The `RF24NetworkHeader` class supports the python "magic method" :py:func:`repr()`. So, you can
easily pass an instantiated `RF24NetworkHeader` object to the :py:func:`print()` function.

.. autoclass:: pyrf24.rf24_network.RF24NetworkHeader
:members:
:members: to_node, type, from_node, id, reserved, to_string
:special-members: __init__

.. property:: next_id
:classmethod:

The next sequential identifying number used for the next created header's `id`.

Constants
----------

Expand Down
26 changes: 18 additions & 8 deletions examples/mesh_example.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
"""
Simplest RF24Mesh example that transmits a time stamp (in milliseconds) 1 per second.
"""
import sys
import time
import struct
from pyrf24 import RF24, RF24Network, RF24Mesh
from pyrf24 import RF24, RF24Network, RF24Mesh, MESH_DEFAULT_ADDRESS

start = time.monotonic()

Expand All @@ -21,9 +22,16 @@ def millis():
mesh.node_id = 4
print("starting nodeID", mesh.node_id)
if not mesh.begin():
# if mesh.begin() returns false for a master node,
# then radio.begin() returned false.
raise OSError("Radio hardware not responding.")
if radio.is_chip_connected:
try:
print("Could not connect to network.\nConnecting to mesh...")
while mesh.renew_address() == MESH_DEFAULT_ADDRESS:
print("Could not connect to network.\nConnecting to mesh...")
except KeyboardInterrupt:
radio.power = False
sys.exit()
else:
raise OSError("Radio hardware not responding or could not connect to mesh.")
radio.print_pretty_details()

TIMER = 0
Expand All @@ -39,14 +47,16 @@ def millis():
if not mesh.write(struct.pack("L", TIMER), ord("M")):
# If a write fails, check connectivity to the mesh network
if not mesh.check_connection():
# The address could be refreshed per a specified timeframe
# The address could be refreshed per a specified time frame
# or only when sequential writes fail, etc.
print("Renewing Address")
mesh.renew_address()
print("Send fail. Renewing Address...")
while mesh.renew_address() == MESH_DEFAULT_ADDRESS:
print("Renewing Address...")
else:
print("Send fail, Test OK")
else:
print("Send OK:", TIMER)
time.sleep(0.001) # delay 1 ms
except KeyboardInterrupt:
radio.power = False # power radio down before exiting
print("powering down radio and exiting.")
radio.power = False
7 changes: 5 additions & 2 deletions examples/mesh_example_master.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@
mesh = RF24Mesh(radio, network)
mesh.node_id = 0
if not mesh.begin():
raise OSError("failed to initialize radio or could not connect to mesh")
# if mesh.begin() returns false for a master node,
# then radio.begin() returned false.
raise OSError("Radio hardware not responding.")
radio.print_pretty_details()

try:
Expand All @@ -22,4 +24,5 @@
header, payload = network.read()
print(f"Received message {header.to_string()}")
except KeyboardInterrupt:
radio.power = False # power radio down before exiting
print("powering down radio and exiting.")
radio.power = False
5 changes: 3 additions & 2 deletions examples/network_helloworld_rx.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,9 @@
print("payload length ", len(payload))
millis, packet_count = struct.unpack("<LL", payload[:EXPECTED_SIZE])
print(
f"Received payload {packet_count} at {millis}",
f"Received payload {packet_count} at (origin's timestamp) {millis}.",
f"Header details {header.to_string()}",
)
except KeyboardInterrupt:
radio.power = False # power radio down before exiting
print("powering down radio and exiting.")
radio.power = False
5 changes: 3 additions & 2 deletions examples/network_helloworld_tx.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
PACKETS_SENT += 1
payload = struct.pack("<LL", now, PACKETS_SENT)
ok = network.write(RF24NetworkHeader(OTHER_NODE), payload)
print("Sending...", ("ok" if ok else "failed"))
print(f"Sending {PACKETS_SENT}...", ("ok" if ok else "failed"))
except KeyboardInterrupt:
radio.power = False # power radio down before exiting
print("powering down radio and exiting.")
radio.power = False
4 changes: 2 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
if IS_LINUX:
from skbuild import setup
else:
from distutils.core import setup
from distutils.core import setup # pylint: disable=deprecated-module


long_description = "" # pylint: disable=invalid-name
Expand All @@ -33,7 +33,7 @@ def exclude_rf24_utility_folder(cmake_manifest):
"zip_safe": False,
"license": "GNU General Public License v2 (GPLv2)",
"classifiers": [
"Development Status :: 3 - Alpha", # TODO change this when ready
"Development Status :: 3 - Beta", # TODO change this when ready
"Intended Audience :: Developers",
"Topic :: Software Development :: Libraries",
"Topic :: System :: Hardware",
Expand Down
Loading

0 comments on commit ff659b5

Please sign in to comment.