add config to build enviro board API docs with Sphinx and add docs in
.py files

Change-Id: I00e3eda6d4516a3cd368c66c69b811e7869c680e
diff --git a/python/coral-cloudiot/coral/cloudiot/core.py b/python/coral-cloudiot/coral/cloudiot/core.py
index 6897427..46f76dd 100644
--- a/python/coral-cloudiot/coral/cloudiot/core.py
+++ b/python/coral-cloudiot/coral/cloudiot/core.py
@@ -13,10 +13,6 @@
 # limitations under the License.
 
 """Python Library for connecting to Google Cloud IoT Core via MQTT, using JWT.
-This library connects to Google Cloud IoT Core via MQTT, using a JWT for device
-authentication. After connection, publish_message can be used to provide an
-arbitrary message to a cloud project. Configuration must be done using a
-configuration file.
 """
 
 import argparse
@@ -36,7 +32,20 @@
 
 
 class CloudIot:
+    """
+    Manages a connection to Google Cloud IoT Core via MQTT, using a JWT for device
+    authentication.
+
+    You must configure a connection by specifying a Clout IoT configuration file (.ini). Then
+    you can use :meth:`publish_message` to send an arbitrary message to your cloud project.
+    """
     def __init__(self, config_file, config_section='DEFAULT'):
+        """
+        Args:
+            config_file (str): Path to your Cloud IoT configuration file (.ini).
+            config_section (str): The section name in the .ini file where the Cloud IoT Core config
+                can be read. By default, it reads from the "[DEFAULT]" section.
+        """
         self._config = configparser.ConfigParser()
         self._config.read(config_file)
 
@@ -110,9 +119,22 @@
             self._token_thread.join()
 
     def enabled(self):
+        """
+        Checks whether or not Clout Iot Core is enabled, as per the config file's "Enabled" boolean.
+
+        Returns:
+            True if Cloud Iot Core is enabled, False if it's disabled.
+        """
         return self._enabled
 
     def publish_message(self, message):
+        """
+        Sends an arbitrary message to the Cloud Iot Core service.
+
+        Args:
+            message (obj): The message to send. It can be any message that's serializable into a
+                JSON message using :func:`json.dumps` (such as a dictionary or string).
+        """
         if not self._enabled:
             return
 
@@ -137,6 +159,13 @@
             self._client.loop_stop()
 
     def register_message_callbacks(self, callbacks):
+        """
+        Specifies functions to call upon various MQTT pub-sub messages.
+
+        Args:
+            callbacks (dict): A mapping of callback names from `paho.mqtt.client callbacks
+                <https://pypi.org/project/paho-mqtt/#callbacks>`_ to your own function names.
+        """
         if 'on_connect' in callbacks:
             self._client.on_connect = callbacks['on_connect']
         if 'on_disconnect' in callbacks:
diff --git a/python/coral-enviro/coral/enviro/board.py b/python/coral-enviro/coral/enviro/board.py
index 38431b1..e876b5c 100644
--- a/python/coral-enviro/coral/enviro/board.py
+++ b/python/coral-enviro/coral/enviro/board.py
@@ -47,6 +47,9 @@
         return None
 
 class EnviroBoard():
+    """
+    An interface for all input and output modules on the Environmental Sensor Board.
+    """
     def __init__(self):
         # Obtain the full sysfs path of the IIO devices.
         self._hdc2010 = _get_path('hdc20x0')
@@ -59,6 +62,9 @@
 
     @property
     def temperature(self):
+        """
+        Gets the current temperature, in Celsius.
+        """
         temperature = _read_sysfs(self._hdc2010 + '/in_temp_input')
         if temperature is not None:
             return temperature
@@ -70,20 +76,49 @@
 
     @property
     def humidity(self):
+        """
+        Gets the current relative humidity, in percentage.
+        """
         return _read_sysfs(self._hdc2010 + '/in_humidityrelative_input')
 
     @property
     def ambient_light(self):
+        """
+        Gets the ambient light, in lux.
+        """
         return _read_sysfs(self._opt3002 + '/in_illuminance_input')
 
     @property
     def pressure(self):
+        """
+        Gets the current atmospheric pressure, in kPa.
+        """
         return _read_sysfs(self._bmp280 + '/in_pressure_input')
 
     @property
     def grove_analog(self):
+        """
+        Gets a raw value from a device connected to the board's analog Grove connector.
+
+        .. note::
+            ADC is set to +/- 6V range, independent of supply voltage (selected by jumper).
+        """
         return _read_sysfs(self._tla2021 + '/in_voltage0_raw')
 
     @property
     def display(self):
+        """
+        Gets an instance of :class:`luma.core.device.device` representing the board's OLED display.
+
+        For example, you can write to the display using :class:`luma.core.render.canvas`
+        as follows::
+
+            enviro = EnviroBoard()
+
+            update_display(enviro.display, "Hello world")
+
+            def update_display(display, msg):
+                with canvas(display) as draw:
+                    draw.text((0, 0), msg, fill='white')
+        """
         return self._display
diff --git a/python/docs/README.md b/python/docs/README.md
new file mode 100644
index 0000000..15ce545
--- /dev/null
+++ b/python/docs/README.md
@@ -0,0 +1,26 @@
+This directory holds the source files required to build the Environmental Sensor Board reference with Sphinx.
+
+Building it requires that you install Sphinx and other Python dependencies:
+
+    # We require Python3, so if that's not your default, first start a virtual environment:
+    python3 -m venv ~/.my_venvs/coraldocs
+    source ~/.my_venvs/coraldocs/bin/activate
+
+    # Navigate to the coral-cloud/python/ directory in your terminal for these commands...
+
+    # Install the doc build dependencies:
+    pip install -r docs/requirements.txt
+
+    # Build the docs for local viewing (in "read the docs" style):
+    sphinx-build -b html docs/ docs/_build/html -D html_theme="sphinx_rtd_theme" -D html_file_suffix=".html" -D html_link_suffix=".html"
+
+    # Build the docs for the coral website (with .md files)
+    sphinx-build -b html docs/ docs/_build/html
+
+    # Clean the output for a fresh build:
+    rm -rf docs/_build
+
+The results are output in `coral-cloud/python/docs/_build/html/`.
+
+For more information about the syntax in these RST files, see the [reStructuredText documentation](
+http://www.sphinx-doc.org/en/master/usage/restructuredtext/index.html).
\ No newline at end of file
diff --git a/python/docs/conf.py b/python/docs/conf.py
new file mode 100644
index 0000000..f48e533
--- /dev/null
+++ b/python/docs/conf.py
@@ -0,0 +1,242 @@
+# Copyright 2019 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# -*- coding: utf-8 -*-
+#
+# Configuration file for the Sphinx documentation builder.
+#
+# This file does only contain a selection of the most common options. For a
+# full list see the documentation:
+# http://www.sphinx-doc.org/en/master/config
+
+# -- Path setup --------------------------------------------------------------
+
+# If extensions (or modules to document with autodoc) are in another directory,
+# add these directories to sys.path here. If the directory is relative to the
+# documentation root, use os.path.abspath to make it absolute, like shown here.
+#
+import os
+import sys
+
+from unittest.mock import MagicMock
+
+sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', 'coral-cloudiot'))
+sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', 'coral-enviro'))
+
+# Mock modules not needed for docs
+
+sys.modules.update((module, MagicMock()) for module in (
+    'jwt',
+    'paho',
+    'paho.mqtt',
+    'paho.mqtt.client',
+    'luma',
+    'luma.oled',
+    'luma.oled.device',
+    'luma.core',
+    'luma.core.interface',
+    'luma.core.interface.serial',
+    'cryptoauthlib',
+    'cryptography',
+    'cryptography.exceptions',
+    'cryptography.hazmat',
+    'cryptography.hazmat.primitives',
+    'cryptography.hazmat.primitives.asymmetric'))
+
+# -- Project information -----------------------------------------------------
+
+project = 'Coral Environmental Sensor Board API'
+copyright = '2019, Google LLC'
+author = 'Google LLC'
+
+# The short X.Y version
+version = '1.0'
+# The full version, including alpha/beta/rc tags
+release = ''
+
+
+# -- General configuration ---------------------------------------------------
+
+# If your documentation needs a minimal Sphinx version, state it here.
+#
+# needs_sphinx = '1.0'
+
+# Add any Sphinx extension module names here, as strings. They can be
+# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
+# ones.
+extensions = [
+    'sphinx.ext.autodoc',
+    'sphinx.ext.intersphinx', # Enables linking to other libs like Pillow
+    'sphinx.ext.coverage',
+    'sphinx.ext.napoleon', # Converts Google-style code comments to RST
+]
+
+# Autodoc configurations
+autoclass_content = 'both'
+
+# Intersfphinx config; Controls external linking to other python libraries
+intersphinx_mapping = {
+    'python': ('https://docs.python.org/', None),
+    'PIL': ('https://pillow.readthedocs.io/en/stable/', None),
+    'luma': ('https://luma-core.readthedocs.io/en/latest/', None)
+}
+
+# Disable rtype return values; output return type inline with description
+napoleon_use_rtype = False
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['_templates']
+
+source_parsers = {
+    '.md': 'recommonmark.parser.CommonMarkParser',
+}
+
+# The suffix(es) of source filenames.
+# You can specify multiple suffix as a list of string:
+#
+# source_suffix = ['.rst', '.md']
+source_suffix = ['.rst', '.md']
+
+# The master toctree document.
+master_doc = 'index'
+
+# The language for content autogenerated by Sphinx. Refer to documentation
+# for a list of supported languages.
+#
+# This is also used if you do content translation via gettext catalogs.
+# Usually you set "language" from the command line for these cases.
+language = None
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+# This pattern also affects html_static_path and html_extra_path.
+exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store', 'README*']
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = None
+
+
+# -- Options for HTML output -------------------------------------------------
+
+# The theme to use for HTML and HTML Help pages.  See the documentation for
+# a list of builtin themes.
+#
+html_theme = "coral_theme"
+html_theme_path = ["."]
+html_file_suffix = ".md"
+html_link_suffix = "/"
+
+# Left nav header
+# html_logo = '_static/images/aiy-logo-white.svg'
+
+# Theme options are theme-specific and customize the look and feel of a theme
+# further.  For a list of options available for each theme, see the
+# documentation.
+#
+# html_theme_options = {}
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = ['_static']
+
+# Add our custom stylesheet. By default, Sphinx looks for this in _static/.
+def setup(app):
+    app.add_stylesheet('custom.css')
+
+# Custom sidebar templates, must be a dictionary that maps document names
+# to template names.
+#
+# The default sidebars (for documents that don't match any pattern) are
+# defined by theme itself.  Builtin themes are using these templates by
+# default: ``['localtoc.html', 'relations.html', 'sourcelink.html',
+# 'searchbox.html']``.
+#
+# html_sidebars = {}
+
+
+# -- Options for HTMLHelp output ---------------------------------------------
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'EnviroBoardAPI'
+
+
+# -- Options for LaTeX output ------------------------------------------------
+
+latex_elements = {
+    # The paper size ('letterpaper' or 'a4paper').
+    #
+    # 'papersize': 'letterpaper',
+
+    # The font size ('10pt', '11pt' or '12pt').
+    #
+    # 'pointsize': '10pt',
+
+    # Additional stuff for the LaTeX preamble.
+    #
+    # 'preamble': '',
+
+    # Latex figure (float) alignment
+    #
+    # 'figure_align': 'htbp',
+}
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title,
+#  author, documentclass [howto, manual, or own class]).
+latex_documents = [
+    (master_doc, 'EdgeTPUAPI.tex', 'Coral Environmental Sensor Board API Reference',
+     'Google LLC', 'manual'),
+]
+
+
+# -- Options for manual page output ------------------------------------------
+
+# One entry per manual page. List of tuples
+# (source start file, name, description, authors, manual section).
+man_pages = [
+    (master_doc, 'edgetpuapi', 'Coral Environmental Sensor Board API Reference',
+     [author], 1)
+]
+
+
+# -- Options for Texinfo output ----------------------------------------------
+
+# Grouping the document tree into Texinfo files. List of tuples
+# (source start file, target name, title, author,
+#  dir menu entry, description, category)
+texinfo_documents = [
+    (master_doc, 'EdgeTPUAPI', 'Coral Environmental Sensor Board API Reference',
+     author, 'EdgeTPUAPI', 'One line description of project.',
+     'Miscellaneous'),
+]
+
+
+# -- Options for Epub output -------------------------------------------------
+
+# Bibliographic Dublin Core info.
+epub_title = project
+
+# The unique identifier of the text. This can be a ISBN number
+# or the project homepage.
+#
+# epub_identifier = ''
+
+# A unique identification for the text.
+#
+# epub_uid = ''
+
+# A list of files that should not be packed into the epub file.
+epub_exclude_files = ['search.html']
+
diff --git a/python/docs/coral.cloudiot.core.rst b/python/docs/coral.cloudiot.core.rst
new file mode 100644
index 0000000..a114c8e
--- /dev/null
+++ b/python/docs/coral.cloudiot.core.rst
@@ -0,0 +1,7 @@
+coral.cloudiot.core
+===================
+
+.. autoclass:: coral.cloudiot.core.CloudIot
+    :members:
+    :undoc-members:
+    :inherited-members:
\ No newline at end of file
diff --git a/python/docs/coral.enviro.board.rst b/python/docs/coral.enviro.board.rst
new file mode 100644
index 0000000..0d3fa4e
--- /dev/null
+++ b/python/docs/coral.enviro.board.rst
@@ -0,0 +1,8 @@
+coral.enviro.board
+==================
+
+.. autoclass:: coral.enviro.board.EnviroBoard
+    :members:
+    :undoc-members:
+    :inherited-members:
+    :member-order: bysource
\ No newline at end of file
diff --git a/python/docs/coral_theme/layout.html b/python/docs/coral_theme/layout.html
new file mode 100644
index 0000000..5e74d1b
--- /dev/null
+++ b/python/docs/coral_theme/layout.html
@@ -0,0 +1,7 @@
+----
+Title: {{ title|striptags|e }}
+----
+
+<div class="sphinx-reference">
+{% block body %}{% endblock %}
+</div>
\ No newline at end of file
diff --git a/python/docs/coral_theme/search.html b/python/docs/coral_theme/search.html
new file mode 100644
index 0000000..53cce44
--- /dev/null
+++ b/python/docs/coral_theme/search.html
@@ -0,0 +1 @@
+{{ toctree() }}
\ No newline at end of file
diff --git a/python/docs/coral_theme/theme.conf b/python/docs/coral_theme/theme.conf
new file mode 100644
index 0000000..aa1d70a
--- /dev/null
+++ b/python/docs/coral_theme/theme.conf
@@ -0,0 +1,12 @@
+[theme]
+inherit = basic
+stylesheet = none
+pygments_style = none
+sidebars = localtoc.html, relations.html, sourcelink.html, searchbox.html
+file_suffix = md
+
+[options]
+nosidebar = false
+sidebarwidth = 230
+body_min_width = 450
+body_max_width = 800
\ No newline at end of file
diff --git a/python/docs/index.rst b/python/docs/index.rst
new file mode 100644
index 0000000..cc3f251
--- /dev/null
+++ b/python/docs/index.rst
@@ -0,0 +1,17 @@
+Coral Environmental Sensor Board API reference
+==============================================
+
+This is the API reference for the Coral Environmental Sensor Board library.
+
+.. toctree::
+   :maxdepth: 1
+
+   coral.enviro.board
+   coral.cloudiot.core
+
+
+API indices
+-----------
+
+* :ref:`Full index <genindex>`
+* :ref:`Module index <modindex>`
diff --git a/python/docs/requirements.txt b/python/docs/requirements.txt
new file mode 100644
index 0000000..d934244
--- /dev/null
+++ b/python/docs/requirements.txt
@@ -0,0 +1,4 @@
+# Python packages required to build the docs
+sphinx
+sphinx_rtd_theme
+recommonmark
\ No newline at end of file