From b919ffa74b603e6adc2445bf754d86dca69960c0 Mon Sep 17 00:00:00 2001 From: brentru Date: Tue, 19 Feb 2019 17:00:05 -0500 Subject: [PATCH 01/48] add files from pyportal board --- .gitignore | 12 + .pylintrc | 433 +++++++++++++++++++++++++++++ .readthedocs.yml | 3 + .travis.yml | 48 ++++ CODE_OF_CONDUCT.md | 127 +++++++++ LICENSE | 4 +- README.rst | 128 +++++++++ adafruit_io.py | 256 +++++++++++++++++ docs/_static/favicon.ico | Bin 0 -> 4414 bytes docs/api.rst | 8 + docs/conf.py | 160 +++++++++++ docs/examples.rst | 8 + docs/index.rst | 51 ++++ examples/adafruit_io_simpletest.py | 53 ++++ requirements.txt | 2 + setup.py | 65 +++++ 16 files changed, 1356 insertions(+), 2 deletions(-) create mode 100644 .gitignore create mode 100644 .pylintrc create mode 100644 .readthedocs.yml create mode 100644 .travis.yml create mode 100644 CODE_OF_CONDUCT.md create mode 100644 README.rst create mode 100644 adafruit_io.py create mode 100644 docs/_static/favicon.ico create mode 100644 docs/api.rst create mode 100644 docs/conf.py create mode 100644 docs/examples.rst create mode 100644 docs/index.rst create mode 100644 examples/adafruit_io_simpletest.py create mode 100644 requirements.txt create mode 100644 setup.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..55f127b --- /dev/null +++ b/.gitignore @@ -0,0 +1,12 @@ +*.mpy +.idea +__pycache__ +_build +*.pyc +.env +build* +bundles +*.DS_Store +.eggs +dist +**/*.egg-info \ No newline at end of file diff --git a/.pylintrc b/.pylintrc new file mode 100644 index 0000000..039eaec --- /dev/null +++ b/.pylintrc @@ -0,0 +1,433 @@ +[MASTER] + +# A comma-separated list of package or module names from where C extensions may +# be loaded. Extensions are loading into the active Python interpreter and may +# run arbitrary code +extension-pkg-whitelist= + +# Add files or directories to the blacklist. They should be base names, not +# paths. +ignore=CVS + +# Add files or directories matching the regex patterns to the blacklist. The +# regex matches against base names, not paths. +ignore-patterns= + +# Python code to execute, usually for sys.path manipulation such as +# pygtk.require(). +#init-hook= + +# Use multiple processes to speed up Pylint. +# jobs=1 +jobs=2 + +# List of plugins (as comma separated values of python modules names) to load, +# usually to register additional checkers. +load-plugins= + +# Pickle collected data for later comparisons. +persistent=yes + +# Specify a configuration file. +#rcfile= + +# Allow loading of arbitrary C extensions. Extensions are imported into the +# active Python interpreter and may run arbitrary code. +unsafe-load-any-extension=no + + +[MESSAGES CONTROL] + +# Only show warnings with the listed confidence levels. Leave empty to show +# all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED +confidence= + +# Disable the message, report, category or checker with the given id(s). You +# can either give multiple identifiers separated by comma (,) or put this +# option multiple times (only on the command line, not in the configuration +# file where it should appear only once).You can also use "--disable=all" to +# disable everything first and then reenable specific checks. For example, if +# you want to run only the similarities checker, you can use "--disable=all +# --enable=similarities". If you want to run only the classes checker, but have +# no Warning level messages displayed, use"--disable=all --enable=classes +# --disable=W" +# disable=import-error,print-statement,parameter-unpacking,unpacking-in-except,old-raise-syntax,backtick,long-suffix,old-ne-operator,old-octal-literal,import-star-module-level,raw-checker-failed,bad-inline-option,locally-disabled,locally-enabled,file-ignored,suppressed-message,useless-suppression,deprecated-pragma,apply-builtin,basestring-builtin,buffer-builtin,cmp-builtin,coerce-builtin,execfile-builtin,file-builtin,long-builtin,raw_input-builtin,reduce-builtin,standarderror-builtin,unicode-builtin,xrange-builtin,coerce-method,delslice-method,getslice-method,setslice-method,no-absolute-import,old-division,dict-iter-method,dict-view-method,next-method-called,metaclass-assignment,indexing-exception,raising-string,reload-builtin,oct-method,hex-method,nonzero-method,cmp-method,input-builtin,round-builtin,intern-builtin,unichr-builtin,map-builtin-not-iterating,zip-builtin-not-iterating,range-builtin-not-iterating,filter-builtin-not-iterating,using-cmp-argument,eq-without-hash,div-method,idiv-method,rdiv-method,exception-message-attribute,invalid-str-codec,sys-max-int,bad-python3-import,deprecated-string-function,deprecated-str-translate-call +disable=print-statement,parameter-unpacking,unpacking-in-except,old-raise-syntax,backtick,long-suffix,old-ne-operator,old-octal-literal,import-star-module-level,raw-checker-failed,bad-inline-option,locally-disabled,locally-enabled,file-ignored,suppressed-message,useless-suppression,deprecated-pragma,apply-builtin,basestring-builtin,buffer-builtin,cmp-builtin,coerce-builtin,execfile-builtin,file-builtin,long-builtin,raw_input-builtin,reduce-builtin,standarderror-builtin,unicode-builtin,xrange-builtin,coerce-method,delslice-method,getslice-method,setslice-method,no-absolute-import,old-division,dict-iter-method,dict-view-method,next-method-called,metaclass-assignment,indexing-exception,raising-string,reload-builtin,oct-method,hex-method,nonzero-method,cmp-method,input-builtin,round-builtin,intern-builtin,unichr-builtin,map-builtin-not-iterating,zip-builtin-not-iterating,range-builtin-not-iterating,filter-builtin-not-iterating,using-cmp-argument,eq-without-hash,div-method,idiv-method,rdiv-method,exception-message-attribute,invalid-str-codec,sys-max-int,bad-python3-import,deprecated-string-function,deprecated-str-translate-call,import-error + +# Enable the message, report, category or checker with the given id(s). You can +# either give multiple identifier separated by comma (,) or put this option +# multiple time (only on the command line, not in the configuration file where +# it should appear only once). See also the "--disable" option for examples. +enable= + + +[REPORTS] + +# Python expression which should return a note less than 10 (10 is the highest +# note). You have access to the variables errors warning, statement which +# respectively contain the number of errors / warnings messages and the total +# number of statements analyzed. This is used by the global evaluation report +# (RP0004). +evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10) + +# Template used to display messages. This is a python new-style format string +# used to format the message information. See doc for all details +#msg-template= + +# Set the output format. Available formats are text, parseable, colorized, json +# and msvs (visual studio).You can also give a reporter class, eg +# mypackage.mymodule.MyReporterClass. +output-format=text + +# Tells whether to display a full report or only the messages +reports=no + +# Activate the evaluation score. +score=yes + + +[REFACTORING] + +# Maximum number of nested blocks for function / method body +max-nested-blocks=5 + + +[LOGGING] + +# Logging modules to check that the string format arguments are in logging +# function parameter format +logging-modules=logging + + +[SPELLING] + +# Spelling dictionary name. Available dictionaries: none. To make it working +# install python-enchant package. +spelling-dict= + +# List of comma separated words that should not be checked. +spelling-ignore-words= + +# A path to a file that contains private dictionary; one word per line. +spelling-private-dict-file= + +# Tells whether to store unknown words to indicated private dictionary in +# --spelling-private-dict-file option instead of raising a message. +spelling-store-unknown-words=no + + +[MISCELLANEOUS] + +# List of note tags to take in consideration, separated by a comma. +# notes=FIXME,XXX,TODO +notes=FIXME,XXX + + +[TYPECHECK] + +# List of decorators that produce context managers, such as +# contextlib.contextmanager. Add to this list to register other decorators that +# produce valid context managers. +contextmanager-decorators=contextlib.contextmanager + +# List of members which are set dynamically and missed by pylint inference +# system, and so shouldn't trigger E1101 when accessed. Python regular +# expressions are accepted. +generated-members= + +# Tells whether missing members accessed in mixin class should be ignored. A +# mixin class is detected if its name ends with "mixin" (case insensitive). +ignore-mixin-members=yes + +# This flag controls whether pylint should warn about no-member and similar +# checks whenever an opaque object is returned when inferring. The inference +# can return multiple potential results while evaluating a Python object, but +# some branches might not be evaluated, which results in partial inference. In +# that case, it might be useful to still emit no-member and other checks for +# the rest of the inferred objects. +ignore-on-opaque-inference=yes + +# List of class names for which member attributes should not be checked (useful +# for classes with dynamically set attributes). This supports the use of +# qualified names. +ignored-classes=optparse.Values,thread._local,_thread._local + +# List of module names for which member attributes should not be checked +# (useful for modules/projects where namespaces are manipulated during runtime +# and thus existing member attributes cannot be deduced by static analysis. It +# supports qualified module names, as well as Unix pattern matching. +ignored-modules=board + +# Show a hint with possible names when a member name was not found. The aspect +# of finding the hint is based on edit distance. +missing-member-hint=yes + +# The minimum edit distance a name should have in order to be considered a +# similar match for a missing member name. +missing-member-hint-distance=1 + +# The total number of similar names that should be taken in consideration when +# showing a hint for a missing member. +missing-member-max-choices=1 + + +[VARIABLES] + +# List of additional names supposed to be defined in builtins. Remember that +# you should avoid to define new builtins when possible. +additional-builtins= + +# Tells whether unused global variables should be treated as a violation. +allow-global-unused-variables=yes + +# List of strings which can identify a callback function by name. A callback +# name must start or end with one of those strings. +callbacks=cb_,_cb + +# A regular expression matching the name of dummy variables (i.e. expectedly +# not used). +dummy-variables-rgx=_+$|(_[a-zA-Z0-9_]*[a-zA-Z0-9]+?$)|dummy|^ignored_|^unused_ + +# Argument names that match this expression will be ignored. Default to name +# with leading underscore +ignored-argument-names=_.*|^ignored_|^unused_ + +# Tells whether we should check for unused import in __init__ files. +init-import=no + +# List of qualified module names which can have objects that can redefine +# builtins. +redefining-builtins-modules=six.moves,future.builtins + + +[FORMAT] + +# Expected format of line ending, e.g. empty (any line ending), LF or CRLF. +# expected-line-ending-format= +expected-line-ending-format=LF + +# Regexp for a line that is allowed to be longer than the limit. +ignore-long-lines=^\s*(# )??$ + +# Number of spaces of indent required inside a hanging or continued line. +indent-after-paren=4 + +# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1 +# tab). +indent-string=' ' + +# Maximum number of characters on a single line. +max-line-length=100 + +# Maximum number of lines in a module +max-module-lines=1000 + +# List of optional constructs for which whitespace checking is disabled. `dict- +# separator` is used to allow tabulation in dicts, etc.: {1 : 1,\n222: 2}. +# `trailing-comma` allows a space between comma and closing bracket: (a, ). +# `empty-line` allows space-only lines. +no-space-check=trailing-comma,dict-separator + +# Allow the body of a class to be on the same line as the declaration if body +# contains single statement. +single-line-class-stmt=no + +# Allow the body of an if to be on the same line as the test if there is no +# else. +single-line-if-stmt=no + + +[SIMILARITIES] + +# Ignore comments when computing similarities. +ignore-comments=yes + +# Ignore docstrings when computing similarities. +ignore-docstrings=yes + +# Ignore imports when computing similarities. +ignore-imports=no + +# Minimum lines number of a similarity. +min-similarity-lines=4 + + +[BASIC] + +# Naming hint for argument names +argument-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ + +# Regular expression matching correct argument names +argument-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ + +# Naming hint for attribute names +attr-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ + +# Regular expression matching correct attribute names +attr-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ + +# Bad variable names which should always be refused, separated by a comma +bad-names=foo,bar,baz,toto,tutu,tata + +# Naming hint for class attribute names +class-attribute-name-hint=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$ + +# Regular expression matching correct class attribute names +class-attribute-rgx=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$ + +# Naming hint for class names +# class-name-hint=[A-Z_][a-zA-Z0-9]+$ +class-name-hint=[A-Z_][a-zA-Z0-9_]+$ + +# Regular expression matching correct class names +# class-rgx=[A-Z_][a-zA-Z0-9]+$ +class-rgx=[A-Z_][a-zA-Z0-9_]+$ + +# Naming hint for constant names +const-name-hint=(([A-Z_][A-Z0-9_]*)|(__.*__))$ + +# Regular expression matching correct constant names +const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$ + +# Minimum line length for functions/classes that require docstrings, shorter +# ones are exempt. +docstring-min-length=-1 + +# Naming hint for function names +function-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ + +# Regular expression matching correct function names +function-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ + +# Good variable names which should always be accepted, separated by a comma +# good-names=i,j,k,ex,Run,_ +good-names=r,g,b,w,i,j,k,n,x,y,z,ex,ok,Run,_ + +# Include a hint for the correct naming format with invalid-name +include-naming-hint=no + +# Naming hint for inline iteration names +inlinevar-name-hint=[A-Za-z_][A-Za-z0-9_]*$ + +# Regular expression matching correct inline iteration names +inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$ + +# Naming hint for method names +method-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ + +# Regular expression matching correct method names +method-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ + +# Naming hint for module names +module-name-hint=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ + +# Regular expression matching correct module names +module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ + +# Colon-delimited sets of names that determine each other's naming style when +# the name regexes allow several styles. +name-group= + +# Regular expression which should only match function or class names that do +# not require a docstring. +no-docstring-rgx=^_ + +# List of decorators that produce properties, such as abc.abstractproperty. Add +# to this list to register other decorators that produce valid properties. +property-classes=abc.abstractproperty + +# Naming hint for variable names +variable-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ + +# Regular expression matching correct variable names +variable-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ + + +[IMPORTS] + +# Allow wildcard imports from modules that define __all__. +allow-wildcard-with-all=no + +# Analyse import fallback blocks. This can be used to support both Python 2 and +# 3 compatible code, which means that the block might have code that exists +# only in one or another interpreter, leading to false positives when analysed. +analyse-fallback-blocks=no + +# Deprecated modules which should not be used, separated by a comma +deprecated-modules=optparse,tkinter.tix + +# Create a graph of external dependencies in the given file (report RP0402 must +# not be disabled) +ext-import-graph= + +# Create a graph of every (i.e. internal and external) dependencies in the +# given file (report RP0402 must not be disabled) +import-graph= + +# Create a graph of internal dependencies in the given file (report RP0402 must +# not be disabled) +int-import-graph= + +# Force import order to recognize a module as part of the standard +# compatibility libraries. +known-standard-library= + +# Force import order to recognize a module as part of a third party library. +known-third-party=enchant + + +[CLASSES] + +# List of method names used to declare (i.e. assign) instance attributes. +defining-attr-methods=__init__,__new__,setUp + +# List of member names, which should be excluded from the protected access +# warning. +exclude-protected=_asdict,_fields,_replace,_source,_make + +# List of valid names for the first argument in a class method. +valid-classmethod-first-arg=cls + +# List of valid names for the first argument in a metaclass class method. +valid-metaclass-classmethod-first-arg=mcs + + +[DESIGN] + +# Maximum number of arguments for function / method +max-args=5 + +# Maximum number of attributes for a class (see R0902). +# max-attributes=7 +max-attributes=11 + +# Maximum number of boolean expressions in a if statement +max-bool-expr=5 + +# Maximum number of branch for function / method body +max-branches=12 + +# Maximum number of locals for function / method body +max-locals=15 + +# Maximum number of parents for a class (see R0901). +max-parents=7 + +# Maximum number of public methods for a class (see R0904). +max-public-methods=20 + +# Maximum number of return / yield for function / method body +max-returns=6 + +# Maximum number of statements in function / method body +max-statements=50 + +# Minimum number of public methods for a class (see R0903). +min-public-methods=1 + + +[EXCEPTIONS] + +# Exceptions that will emit a warning when being caught. Defaults to +# "Exception" +overgeneral-exceptions=Exception diff --git a/.readthedocs.yml b/.readthedocs.yml new file mode 100644 index 0000000..f4243ad --- /dev/null +++ b/.readthedocs.yml @@ -0,0 +1,3 @@ +python: + version: 3 +requirements_file: requirements.txt diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..bb2998d --- /dev/null +++ b/.travis.yml @@ -0,0 +1,48 @@ +# This is a common .travis.yml for generating library release zip files for +# CircuitPython library releases using circuitpython-build-tools. +# See https://github.com/adafruit/circuitpython-build-tools for detailed setup +# instructions. + +dist: xenial +language: python +python: + - "3.6" + +cache: + pip: true + +# TODO: if deployment to PyPi is desired, change 'DEPLOY_PYPI' to "true", +# or remove the env block entirely and remove the condition in the +# deploy block. +env: + - DEPLOY_PYPI="false" + +deploy: + - provider: releases + api_key: "$GITHUB_TOKEN" + file_glob: true + file: "$TRAVIS_BUILD_DIR/bundles/*" + skip_cleanup: true + overwrite: true + on: + tags: true + # TODO: Use 'travis encrypt --com -r adafruit/' to generate + # the encrypted password for adafruit-travis. Paste result below. + - provider: pypi + user: adafruit-travis + password: + secure: #-- PASTE ENCRYPTED PASSWORD HERE --# + on: + tags: true + condition: $DEPLOY_PYPI = "true" + +install: + - pip install -r requirements.txt + - pip install circuitpython-build-tools Sphinx sphinx-rtd-theme + - pip install --force-reinstall pylint==1.9.2 + +script: + - pylint adafruit_adafruit_io.py + - ([[ ! -d "examples" ]] || pylint --disable=missing-docstring,invalid-name,bad-whitespace examples/*.py) + - circuitpython-build-bundles --filename_prefix adafruit-circuitpython-adafruit_io --library_location . + - cd docs && sphinx-build -E -W -b html . _build/html && cd .. diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..8ee6e44 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,127 @@ +# Adafruit Community Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and leaders pledge to making participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, gender identity and expression, level or type of +experience, education, socio-economic status, nationality, personal appearance, +race, religion, or sexual identity and orientation. + +## Our Standards + +We are committed to providing a friendly, safe and welcoming environment for +all. + +Examples of behavior that contributes to creating a positive environment +include: + +* Be kind and courteous to others +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Collaborating with other community members +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and sexual attention or advances +* The use of inappropriate images, including in a community member's avatar +* The use of inappropriate language, including in a community member's nickname +* Any spamming, flaming, baiting or other attention-stealing behavior +* Excessive or unwelcome helping; answering outside the scope of the question + asked +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic + address, without explicit permission +* Other conduct which could reasonably be considered inappropriate + +The goal of the standards and moderation guidelines outlined here is to build +and maintain a respectful community. We ask that you don’t just aim to be +"technically unimpeachable", but rather try to be your best self. + +We value many things beyond technical expertise, including collaboration and +supporting others within our community. Providing a positive experience for +other community members can have a much more significant impact than simply +providing the correct answer. + +## Our Responsibilities + +Project leaders are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project leaders have the right and responsibility to remove, edit, or +reject messages, comments, commits, code, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any community member for other behaviors that they deem +inappropriate, threatening, offensive, or harmful. + +## Moderation + +Instances of behaviors that violate the Adafruit Community Code of Conduct +may be reported by any member of the community. Community members are +encouraged to report these situations, including situations they witness +involving other community members. + +You may report in the following ways: + +In any situation, you may send an email to . + +On the Adafruit Discord, you may send an open message from any channel +to all Community Helpers by tagging @community helpers. You may also send an +open message from any channel, or a direct message to @kattni#1507, +@tannewt#4653, @Dan Halbert#1614, @cater#2442, @sommersoft#0222, or +@Andon#8175. + +Email and direct message reports will be kept confidential. + +In situations on Discord where the issue is particularly egregious, possibly +illegal, requires immediate action, or violates the Discord terms of service, +you should also report the message directly to Discord. + +These are the steps for upholding our community’s standards of conduct. + +1. Any member of the community may report any situation that violates the +Adafruit Community Code of Conduct. All reports will be reviewed and +investigated. +2. If the behavior is an egregious violation, the community member who +committed the violation may be banned immediately, without warning. +3. Otherwise, moderators will first respond to such behavior with a warning. +4. Moderators follow a soft "three strikes" policy - the community member may +be given another chance, if they are receptive to the warning and change their +behavior. +5. If the community member is unreceptive or unreasonable when warned by a +moderator, or the warning goes unheeded, they may be banned for a first or +second offense. Repeated offenses will result in the community member being +banned. + +## Scope + +This Code of Conduct and the enforcement policies listed above apply to all +Adafruit Community venues. This includes but is not limited to any community +spaces (both public and private), the entire Adafruit Discord server, and +Adafruit GitHub repositories. Examples of Adafruit Community spaces include +but are not limited to meet-ups, audio chats on the Adafruit Discord, or +interaction at a conference. + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. As a community +member, you are representing our community, and are expected to behave +accordingly. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], +version 1.4, available at +, +and the [Rust Code of Conduct](https://www.rust-lang.org/en-US/conduct.html). + +For other projects adopting the Adafruit Community Code of +Conduct, please contact the maintainers of those projects for enforcement. +If you wish to use this code of conduct for your own project, consider +explicitly mentioning your moderation policy or making a copy with your +own moderation policy so as to avoid confusion. diff --git a/LICENSE b/LICENSE index 5739aaa..d4fbf1d 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ -MIT License +The MIT License (MIT) -Copyright (c) 2019 Adafruit Industries +Copyright (c) 2019 Brent Rubell for Adafruit Industries Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.rst b/README.rst new file mode 100644 index 0000000..4260731 --- /dev/null +++ b/README.rst @@ -0,0 +1,128 @@ +Introduction +============ + +.. image:: https://readthedocs.org/projects/adafruit-circuitpython-adafruit_io/badge/?version=latest + :target: https://circuitpython.readthedocs.io/projects/adafruit_io/en/latest/ + :alt: Documentation Status + +.. image:: https://img.shields.io/discord/327254708534116352.svg + :target: https://discord.gg/nBQh6qu + :alt: Discord + +.. image:: https://travis-ci.com/adafruit/Adafruit_CircuitPython_Adafruit_IO.svg?branch=master + :target: https://travis-ci.com/adafruit/Adafruit_CircuitPython_Adafruit_IO + :alt: Build Status + +CircuitPython wrapper library for communicating with `Adafruit IO `_. + + +Dependencies +============= +This driver depends on: + +* `Adafruit CircuitPython `_ + +Please ensure all dependencies are available on the CircuitPython filesystem. +This is easily achieved by downloading +`the Adafruit library and driver bundle `_. + +Installing from PyPI +-------------------- +.. note:: This library is not available on PyPI yet. Install documentation is included + as a standard element. Stay tuned for PyPI availability! +.. todo:: Remove the above note if PyPI version is/will be available at time of release. + If the library is not planned for PyPI, remove the entire 'Installing from PyPI' section. +On supported GNU/Linux systems like the Raspberry Pi, you can install the driver locally `from +PyPI `_. To install for current user: + +.. code-block:: shell + + pip3 install adafruit-circuitpython-adafruit_io + +To install system-wide (this may be required in some cases): + +.. code-block:: shell + + sudo pip3 install adafruit-circuitpython-adafruit_io + +To install in a virtual environment in your current project: + +.. code-block:: shell + + mkdir project-name && cd project-name + python3 -m venv .env + source .env/bin/activate + pip3 install adafruit-circuitpython-adafruit_io + +Usage Example +============= + +Create an Adafruit IO Client object +.. code-block:: python + aio = adafruit_io.Client(ADAFRUIT_IO_USER, ADAFRUIT_IO_KEY, wifi) + +Sending `data` to an Adafruit IO feed +.. code-block:: python + aio.send_data(my_adafruit_io_feed, data) + +Receiving `data` from an Adafruit IO feed +.. code-block:: python + data = aio.receive_data(my_adafruit_io_feed) + + +Contributing +============ + +Contributions are welcome! Please read our `Code of Conduct +`_ +before contributing to help this project stay welcoming. + +Building locally +================ + +Zip release files +----------------- + +To build this library locally you'll need to install the +`circuitpython-build-tools `_ package. + +.. code-block:: shell + + python3 -m venv .env + source .env/bin/activate + pip install circuitpython-build-tools + +Once installed, make sure you are in the virtual environment: + +.. code-block:: shell + + source .env/bin/activate + +Then run the build: + +.. code-block:: shell + + circuitpython-build-bundles --filename_prefix adafruit-circuitpython-adafruit_io --library_location . + +Sphinx documentation +----------------------- + +Sphinx is used to build the documentation based on rST files and comments in the code. First, +install dependencies (feel free to reuse the virtual environment from above): + +.. code-block:: shell + + python3 -m venv .env + source .env/bin/activate + pip install Sphinx sphinx-rtd-theme + +Now, once you have the virtual environment activated: + +.. code-block:: shell + + cd docs + sphinx-build -E -W -b html . _build/html + +This will output the documentation to ``docs/_build/html``. Open the index.html in your browser to +view them. It will also (due to -W) error out on any warning like Travis will. This is a good way to +locally verify it will pass. diff --git a/adafruit_io.py b/adafruit_io.py new file mode 100644 index 0000000..5ea3f4c --- /dev/null +++ b/adafruit_io.py @@ -0,0 +1,256 @@ +# The MIT License (MIT) +# +# Copyright (c) 2019 Brent Rubell for Adafruit Industries +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +""" +`adafruit_io` +================================================================================ + +A CircuitPython/Python library for communicating with Adafruit IO + + +* Author(s): Brent Rubell for Adafruit Industries + +Implementation Notes +-------------------- + +**Hardware:** + +**Software and Dependencies:** + +* Adafruit CircuitPython firmware for the supported boards: + https://github.com/adafruit/circuitpython/releases + +* Adafruit's ESP32SPI library: https://github.com/adafruit/Adafruit_CircuitPython_ESP32SPI +""" + +# imports + +__version__ = "0.0.0-auto.0" +__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_Adafruit_IO.git" + +class AdafruitIO_ThrottleError(Exception): + """Adafruit IO request error class for Throttle Errors""" + def __init__(self): + super(AdafruitIO_ThrottleError, self).__init__("Number of Adafruit IO Requests exceeded! \ + Please try again in 30 seconds..") + +class AdafruitIO_RequestError(Exception): + """Base Adafruit IO request error class""" + def __init__(self, response): + response_content = response.json() + error = response_content['error'] + super(AdafruitIO_RequestError, self).__init__("Adafruit IO Error {0}: {1}" + .format(response.status_code, error)) + +class Client(): + """ + TODO: Add Class DOCSTRING here! + """ + def __init__(self, username, key, wifi_manager, api_version='v2'): + """ + Adafruit IO API REST Client + :param str username: Adafruit IO Username + :param str key: Adafruit IO Key, from `settings.py` + :param wifi_manager: ESP32WiFiManager Object + :param str api_version: Adafruit IO REST API Version + """ + self.api_version = api_version + self.url = 'https://io.adafruit.com/api' + self.username = username + self.key = key + if wifi_manager: + self.wifi = wifi_manager + else: + raise TypeError("This library requires a WiFiManager object.") + self.http_headers = [{bytes("X-AIO-KEY", "utf-8"):bytes(self.key, "utf-8"), + bytes("Content-Type", "utf-8"):bytes('application/json', "utf-8")}, + {bytes("X-AIO-KEY", "utf-8"):bytes(self.key, "utf-8")}] + + # TODO: Convert these two methods to functions? + def _compose_path(self, path): + return "{0}/{1}/{2}/{3}".format(self.url, self.api_version, self.username, path) + + def _create_data(self, data, latitude, longitude, elevation, timestamp): + return {'value':data, 'lat':latitude, 'lon':longitude, + 'ele':elevation, 'created_at':timestamp} + + def _handle_error(self, response): + if response.status_code == 429: + raise AdafruitIO_ThrottleError + elif response.status_code == 400: + raise AdafruitIO_RequestError(response) + elif response.status_code >= 400: + raise AdafruitIO_RequestError(response) + # no error? do nothing + + # HTTP Requests + def _post(self, path, packet): + """ + Send data to Adafruit IO + :param str path: Formatted Adafruit IO URL + :param json packet: JSON data to send to Adafruit IO + """ + response = self.wifi.post( + path, + json=packet, + headers=self.http_headers[0]) + self._handle_error(response) + return response.json() + response.close() + + def _get(self, path): + """ + Get data from Adafruit IO + :param str path: Formatted Adafruit IO URL + """ + response = self.wifi.get( + path, + headers=self.http_headers[1]) + self._handle_error(response) + return response.json() + response.close() + + def _delete(self, path): + """ + Delete data from Adafruit IO. + :param str path: Formatted Adafruit IO URL + """ + response = self.wifi.delete( + path, + headers=self.http_headers[0]) + self._handle_error(response) + return response.json() + response.close() + + # Data + def send_data(self, feed_key, data, lat=None, lon=None, ele=None, created_at=None): + """ + Sends value data to an Adafruit IO feed. + :param data: Data to send to an Adafruit IO feed + :param str feed_key: Specified Adafruit IO feed + :param int lat: Optional latitude + :param int lon: Optional longitude + :param int ele: Optional elevation + :param string created_at: Optional date/time string + """ + path = self._compose_path("feeds/{0}/data".format(feed_key)) + packet = self._create_data(data, lat, lon, ele, created_at) + self._post(path, packet) + + def receive_data(self, feed_key): + """ + Return the most recent value for the specified feed. + :param string feed_key: Name/Key/ID of Adafruit IO feed. + """ + path = self._compose_path("feeds/{0}/data/last".format(feed_key)) + return self._get(path) + + def delete_data(self, feed_key, data_id): + """ + Delete an existing Data point from a feed. + :param string feed: Feed Key + :param string data_id: Data point to delete + """ + path = self._compose_path("feeds/{0}/data/{0}".format(feed_key, data_id)) + return self._delete(path) + + # Groups + def get_all_groups(self): + """ + Returns information about the user's groups. + """ + path = self._compose_path("groups") + return self._get(path) + + def add_feed_to_group(self, group_key, feed_key): + """ + Adds an existing feed to a group + :param str group_key: Group + :param str feed_key: Feed to add to the group + """ + path = self._compose_path("groups/{0}/add".format(group_key)) + packet = {'feed_key':feed_key} + return self._post(path, packet) + + def create_new_group(self, group_key, group_description): + """ + Creates a new Adafruit IO Group. + :param str group_key: Adafruit IO Group Key + :param str group_description: Brief summary about the group + """ + path = self._compose_path("groups") + packet = {'name':group_key, 'description':group_description} + return self._post(path, packet) + + def delete_group(self, group_key): + """ + Deletes an existing group. + :param str group_key: Adafruit IO Group Key + """ + path = self._compose_path("groups/{0}".format(group_key)) + return self._delete(path) + + def get_group(self, group_key): + """ + Returns Group based on Group Key + :param str group_key: Adafruit IO Group Key + """ + path = self._compose_path("groups/{0}".format(group_key)) + return self._get(path) + + # Feeds + def get_feed(self, feed_key, detailed=False): + """ + Returns feed record + :param str key: Feed Key + :param bool detailed: Returns a more detailed feed record + """ + if detailed: + path = self._compose_path("feeds/{0}/details".format(feed_key)) + else: + path = self._compose_path("feeds/{0}".format(feed_key)) + return self._get(path) + + def get_all_feeds(self): + """ + Returns information about the user's feeds. The response includes + the latest value of each feed, and other metadata about each feed. + """ + path = self._compose_path("feeds") + return self._get(path) + + def create_new_feed(self, feed_key, feed_desc, feed_license): + """ + TODO: Add Docstring + """ + path = self._compose_path("feeds") + packet = packet = {'name':feed_key, + 'description':feed_desc, + 'license':feed_license} + return self._post(path, packet) + + def delete_feed(self, feed_key): + """ + Deletes an existing feed. + :param str feed_key: Valid feed key + """ + path = self._compose_path("feeds/{0}".format(feed_key)) + return self._delete(path) diff --git a/docs/_static/favicon.ico b/docs/_static/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..5aca98376a1f7e593ebd9cf41a808512c2135635 GIT binary patch literal 4414 zcmd^BX;4#F6n=SG-XmlONeGrD5E6J{RVh+e928U#MG!$jWvO+UsvWh`x&VqGNx*en zx=qox7Dqv{kPwo%fZC$dDwVpRtz{HzTkSs8QhG0)%Y=-3@Kt!4ag|JcIo?$-F|?bXVS9UDUyev>MVZQ(H8K4#;BQW-t2CPorj8^KJrMX}QK zp+e<;4ldpXz~=)2GxNy811&)gt-}Q*yVQpsxr@VMoA##{)$1~=bZ1MmjeFw?uT(`8 z^g=09<=zW%r%buwN%iHtuKSg|+r7HkT0PYN*_u9k1;^Ss-Z!RBfJ?Un4w(awqp2b3 z%+myoFis_lTlCrGx2z$0BQdh+7?!JK#9K9@Z!VrG zNj6gK5r(b4?YDOLw|DPRoN7bdP{(>GEG41YcN~4r_SUHU2hgVtUwZG@s%edC;k7Sn zC)RvEnlq~raE2mY2ko64^m1KQL}3riixh?#J{o)IT+K-RdHae2eRX91-+g!y`8^># z-zI0ir>P%Xon)!@xp-BK2bDYUB9k613NRrY6%lVjbFcQc*pRqiK~8xtkNPLxt}e?&QsTB}^!39t_%Qb)~Ukn0O%iC;zt z<&A-y;3h++)>c1br`5VFM~5(83!HKx$L+my8sW_c#@x*|*vB1yU)_dt3vH;2hqPWx zAl^6@?ipx&U7pf`a*>Yq6C85nb+B=Fnn+(id$W#WB^uHAcZVG`qg;rWB}ubvi(Y>D z$ei>REw$#xp0SHAd^|1hq&9HJ=jKK8^zTH~nk)G?yUcmTh9vUM6Y0LMw4(gYVY$D$ zGl&WY&H<)BbJ&3sYbKjx1j^=3-0Q#f^}(aP1?8^`&FUWMp|rmtpK)bLQ1Zo?^s4jqK=Lfg*9&geMGVQ z#^-*!V`fG@;H&{M9S8%+;|h&Qrxym0Ar>WT4BCVLR8cGXF=JmEYN(sNT(9vl+S|%g z8r7nXQ(95i^`=+XHo|){$vf2$?=`F$^&wFlYXyXg$B{a>$-Fp+V}+D;9k=~Xl~?C4 zAB-;RKXdUzBJE{V&d&%R>aEfFe;vxqI$0@hwVM}gFeQR@j}a>DDxR+n+-*6|_)k%% z*mSpDV|=5I9!&VC&9tD%fcVygWZV!iIo2qFtm#!*(s|@ZT33*Ad;+<|3^+yrp*;oH zBSYLV(H1zTU?2WjrCQoQW)Z>J2a=dTriuvezBmu16`tM2fm7Q@d4^iqII-xFpwHGI zn9CL}QE*1vdj2PX{PIuqOe5dracsciH6OlAZATvE8rj6ykqdIjal2 z0S0S~PwHb-5?OQ-tU-^KTG@XNrEVSvo|HIP?H;7ZhYeZkhSqh-{reE!5di;1zk$#Y zCe7rOnlzFYJ6Z#Hm$GoidKB=2HBCwm`BbZVeZY4ukmG%1uz7p2URs6c9j-Gjj^oQV zsdDb3@k2e`C$1I5ML5U0Qs0C1GAp^?!*`=|Nm(vWz3j*j*8ucum2;r0^-6Aca=Gv) zc%}&;!+_*S2tlnnJnz0EKeRmw-Y!@9ob!XQBwiv}^u9MkaXHvM=!<3YX;+2#5Cj5pp?FEK750S3BgeSDtaE^ zXUM@xoV6yBFKfzvY20V&Lr0yC + CircuitPython Reference Documentation + CircuitPython Support Forum + Discord Chat + Adafruit Learning System + Adafruit Blog + Adafruit Store + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` diff --git a/examples/adafruit_io_simpletest.py b/examples/adafruit_io_simpletest.py new file mode 100644 index 0000000..a408136 --- /dev/null +++ b/examples/adafruit_io_simpletest.py @@ -0,0 +1,53 @@ +""" +Send data to Adafruit IO, and retrieve it. +""" +import time +import board +import busio +import adafruit_io +from digitalio import DigitalInOut, Direction + +# ESP32 SPI +import microcontroller +from adafruit_esp32spi import adafruit_esp32spi +from adafruit_esp32spi import adafruit_esp32spi_wifimanager + +# Get wifi details and more from a settings.py file +try: + from settings import settings +except ImportError: + print("WiFi settings are kept in settings.py, please add them there!") + raise + +# PyPortal ESP32 Setup +esp32_cs = DigitalInOut(microcontroller.pin.PB14) # PB14 +esp32_ready = DigitalInOut(microcontroller.pin.PB16) +esp32_gpio0 = DigitalInOut(microcontroller.pin.PB15) +esp32_reset = DigitalInOut(microcontroller.pin.PB17) +spi = busio.SPI(board.SCK, board.MOSI, board.MISO) +esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset) +wifi = adafruit_esp32spi_wifimanager.ESPSPI_WiFiManager(esp, settings, board.NEOPIXEL) + +# Adafruit IO Setup +ADAFRUIT_IO_USER = 'YOUR_ADAFRUIT_IO_USERNAME' +ADAFRUIT_IO_KEY = 'YOUR_ADAFRUIT_IO_PASSWORD' +ADAFRUIT_IO_FEED = 'testfeed' +aio = adafruit_io.Client(ADAFRUIT_IO_USER, ADAFRUIT_IO_KEY, wifi) + +counter = 0 +while True: + try: + data = counter + print('Sending {0} to Adafruit IO...'.format(data)) + aio.send_data(ADAFRUIT_IO_FEED, data) + print('Data sent!') + + print('Receiving Feed {0}...'.format(ADAFRUIT_IO_FEED)) + data = aio.receive_data(ADAFRUIT_IO_FEED) + print('Feed Value:', data['value']) + + counter = counter + 1 + except (ValueError, RuntimeError) as e: + print("Failed to get data, retrying\n", e) + continue + response = None \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..377afe7 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ +Adafruit-Blinka +Adafruit_CircuitPython_ESP32SPI diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..5991328 --- /dev/null +++ b/setup.py @@ -0,0 +1,65 @@ +"""A setuptools based setup module. + +See: +https://packaging.python.org/en/latest/distributing.html +https://github.com/pypa/sampleproject +""" + +from setuptools import setup, find_packages +# To use a consistent encoding +from codecs import open +from os import path + +here = path.abspath(path.dirname(__file__)) + +# Get the long description from the README file +with open(path.join(here, 'README.rst'), encoding='utf-8') as f: + long_description = f.read() + +setup( + name='adafruit-circuitpython-adafruit_io', + + use_scm_version=True, + setup_requires=['setuptools_scm'], + + description='Adafruit IO for CircuitPython', + long_description=long_description, + long_description_content_type='text/x-rst', + + # The project's main homepage. + url='https://github.com/adafruit/Adafruit_CircuitPython_Adafruit_IO', + + # Author details + author='Adafruit Industries', + author_email='circuitpython@adafruit.com', + + install_requires=[ + 'Adafruit-Blinka', + 'Adafruit_CircuitPython_ESP32SPI' + ], + + # Choose your license + license='MIT', + + # See https://pypi.python.org/pypi?%3Aaction=list_classifiers + classifiers=[ + 'Development Status :: 3 - Alpha', + 'Intended Audience :: Developers', + 'Topic :: Software Development :: Libraries', + 'Topic :: System :: Hardware', + 'License :: OSI Approved :: MIT License', + 'Programming Language :: Python :: 3', + 'Programming Language :: Python :: 3.4', + 'Programming Language :: Python :: 3.5', + ], + + # What does your project relate to? + keywords='adafruit blinka circuitpython micropython adafruit_io adafruit-io rest api iot ' + 'wifi', + + # You can just specify the packages manually here if your project is + # simple. Or you can use find_packages(). + # TODO: IF LIBRARY FILES ARE A PACKAGE FOLDER, + # CHANGE `py_modules=['...']` TO `packages=['...']` + py_modules=['adafruit_adafruit_io'], +) From e4aea3d0413cfe8c37b09fa3db54b27f25b805ec Mon Sep 17 00:00:00 2001 From: brentru Date: Tue, 19 Feb 2019 17:01:39 -0500 Subject: [PATCH 02/48] update readme to highlight esp32spi dep --- README.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/README.rst b/README.rst index 4260731..7af94b9 100644 --- a/README.rst +++ b/README.rst @@ -21,6 +21,7 @@ Dependencies This driver depends on: * `Adafruit CircuitPython `_ +* `Adafruit CircuitPython ESP32SPI `_ Please ensure all dependencies are available on the CircuitPython filesystem. This is easily achieved by downloading From a0f4a4c108b4d2cc660572813016d818d9842077 Mon Sep 17 00:00:00 2001 From: brentru Date: Thu, 21 Feb 2019 11:14:24 -0500 Subject: [PATCH 03/48] remove two _all functions due to bug in ESP32SPI, change client to HTTPClient, add some docstrings --- adafruit_io.py | 68 +++++++++++++++++++------------------------------- 1 file changed, 25 insertions(+), 43 deletions(-) diff --git a/adafruit_io.py b/adafruit_io.py index 5ea3f4c..1a37abe 100644 --- a/adafruit_io.py +++ b/adafruit_io.py @@ -31,14 +31,13 @@ Implementation Notes -------------------- -**Hardware:** - **Software and Dependencies:** * Adafruit CircuitPython firmware for the supported boards: - https://github.com/adafruit/circuitpython/releases + https://github.com/adafruit/circuitpython/releases -* Adafruit's ESP32SPI library: https://github.com/adafruit/Adafruit_CircuitPython_ESP32SPI +* Adafruit's ESP32SPI library: + https://github.com/adafruit/Adafruit_CircuitPython_ESP32SPI """ # imports @@ -57,13 +56,9 @@ class AdafruitIO_RequestError(Exception): def __init__(self, response): response_content = response.json() error = response_content['error'] - super(AdafruitIO_RequestError, self).__init__("Adafruit IO Error {0}: {1}" - .format(response.status_code, error)) + super(AdafruitIO_RequestError, self).__init__("Adafruit IO Error {0}: {1}".format(response.status_code, error)) -class Client(): - """ - TODO: Add Class DOCSTRING here! - """ +class HTTPClient(object): def __init__(self, username, key, wifi_manager, api_version='v2'): """ Adafruit IO API REST Client @@ -80,17 +75,16 @@ def __init__(self, username, key, wifi_manager, api_version='v2'): self.wifi = wifi_manager else: raise TypeError("This library requires a WiFiManager object.") - self.http_headers = [{bytes("X-AIO-KEY", "utf-8"):bytes(self.key, "utf-8"), - bytes("Content-Type", "utf-8"):bytes('application/json', "utf-8")}, - {bytes("X-AIO-KEY", "utf-8"):bytes(self.key, "utf-8")}] + self.http_headers = [{bytes("X-AIO-KEY","utf-8"):bytes(self.key,"utf-8"), + bytes("Content-Type","utf-8"):bytes('application/json',"utf-8")}, + {bytes("X-AIO-KEY","utf-8"):bytes(self.key,"utf-8")}] - # TODO: Convert these two methods to functions? def _compose_path(self, path): return "{0}/{1}/{2}/{3}".format(self.url, self.api_version, self.username, path) - + def _create_data(self, data, latitude, longitude, elevation, timestamp): return {'value':data, 'lat':latitude, 'lon':longitude, - 'ele':elevation, 'created_at':timestamp} + 'ele':elevation, 'created_at':timestamp} def _handle_error(self, response): if response.status_code == 429: @@ -110,8 +104,8 @@ def _post(self, path, packet): """ response = self.wifi.post( path, - json=packet, - headers=self.http_headers[0]) + json = packet, + headers = self.http_headers[0]) self._handle_error(response) return response.json() response.close() @@ -127,7 +121,7 @@ def _get(self, path): self._handle_error(response) return response.json() response.close() - + def _delete(self, path): """ Delete data from Adafruit IO. @@ -135,17 +129,17 @@ def _delete(self, path): """ response = self.wifi.delete( path, - headers=self.http_headers[0]) + headers = self.http_headers[0]) self._handle_error(response) return response.json() response.close() - # Data + # Data def send_data(self, feed_key, data, lat=None, lon=None, ele=None, created_at=None): """ Sends value data to an Adafruit IO feed. - :param data: Data to send to an Adafruit IO feed :param str feed_key: Specified Adafruit IO feed + :param data: Data to send to an Adafruit IO feed :param int lat: Optional latitude :param int lon: Optional longitude :param int ele: Optional elevation @@ -173,13 +167,6 @@ def delete_data(self, feed_key, data_id): return self._delete(path) # Groups - def get_all_groups(self): - """ - Returns information about the user's groups. - """ - path = self._compose_path("groups") - return self._get(path) - def add_feed_to_group(self, group_key, feed_key): """ Adds an existing feed to a group @@ -219,8 +206,8 @@ def get_group(self, group_key): # Feeds def get_feed(self, feed_key, detailed=False): """ - Returns feed record - :param str key: Feed Key + Returns feed based on the feed key + :param str feed_key: Feed Key :param bool detailed: Returns a more detailed feed record """ if detailed: @@ -229,22 +216,17 @@ def get_feed(self, feed_key, detailed=False): path = self._compose_path("feeds/{0}".format(feed_key)) return self._get(path) - def get_all_feeds(self): - """ - Returns information about the user's feeds. The response includes - the latest value of each feed, and other metadata about each feed. - """ - path = self._compose_path("feeds") - return self._get(path) - def create_new_feed(self, feed_key, feed_desc, feed_license): """ - TODO: Add Docstring + Creates a new feed. + :param str feed_key: Feed key + :param str feed_desc: Description of feed + :param str feed_license: Feed License """ path = self._compose_path("feeds") packet = packet = {'name':feed_key, - 'description':feed_desc, - 'license':feed_license} + 'description':feed_desc, + 'license':feed_license} return self._post(path, packet) def delete_feed(self, feed_key): @@ -253,4 +235,4 @@ def delete_feed(self, feed_key): :param str feed_key: Valid feed key """ path = self._compose_path("feeds/{0}".format(feed_key)) - return self._delete(path) + return self._delete(path) \ No newline at end of file From 1f58eb887d79bd2f4e6d68c2b670d8beff2c53bb Mon Sep 17 00:00:00 2001 From: brentru Date: Thu, 21 Feb 2019 11:59:10 -0500 Subject: [PATCH 04/48] add example for send/receive data to a feed --- examples/adafruit_io_simpletest_data.py | 58 +++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 examples/adafruit_io_simpletest_data.py diff --git a/examples/adafruit_io_simpletest_data.py b/examples/adafruit_io_simpletest_data.py new file mode 100644 index 0000000..539d5fb --- /dev/null +++ b/examples/adafruit_io_simpletest_data.py @@ -0,0 +1,58 @@ +""" +Sending data to Adafruit IO and receiving it. +""" +import time +import board +import busio +from random import randint +from digitalio import DigitalInOut, Direction + +# ESP32 SPI +import microcontroller +from adafruit_esp32spi import adafruit_esp32spi, adafruit_esp32spi_wifimanager + +# Import Adafruit IO REST Client +from Adafruit_IO import RESTClient + +# Get wifi details and more from a settings.py file +try: + from settings import settings +except ImportError: + print("WiFi settings are kept in settings.py, please add them there!") + raise + +# PyPortal ESP32 Setup +esp32_cs = DigitalInOut(microcontroller.pin.PB14) +esp32_ready = DigitalInOut(microcontroller.pin.PB16) +esp32_gpio0 = DigitalInOut(microcontroller.pin.PB15) +esp32_reset = DigitalInOut(microcontroller.pin.PB17) +spi = busio.SPI(board.SCK, board.MOSI, board.MISO) +esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset) +wifi = adafruit_esp32spi_wifimanager.ESPSPI_WiFiManager(esp, settings, board.NEOPIXEL) + +# Set your Adafruit IO Username and Key in settings.py +# (visit io.adafruit.com if you need to create an account, +# or if you need your Adafruit IO key.) +ADAFRUIT_IO_USER = settings['adafruit_io_user'] +ADAFRUIT_IO_KEY = settings['adafruit_io_key'] + +# Create an instance of the Adafruit IO RESTClient +io = RESTClient(ADAFRUIT_IO_USER, ADAFRUIT_IO_KEY, wifi) + +try: + # Get the 'temperature' feed from Adafruit IO + temperature_feed = io.get_feed('temperature') +except AdafruitIO_RequestError: + # If no 'temperature' feed exists, create one + temperature_feed = io.create_new_feed('temperature') + +# Send random integer values to the feed +random_value = randint(0, 50) +print('Sending {0} to temperature feed...'.format(random_value)) +io.send_data(temperature_feed['key'], random_value) +print('Data sent!') + +# Retrieve data value from the feed +print('Retrieving data from temperature feed...') +received_data = io.receive_data(temperature_feed['key']) +print('Data from temperature feed: ', received_data['value']) From 010b43b32c296934c3852cbdbea54223a43fe243 Mon Sep 17 00:00:00 2001 From: brentru Date: Thu, 21 Feb 2019 12:10:14 -0500 Subject: [PATCH 05/48] add feed interaction example, update data example --- examples/adafruit_io_simpletest_data.py | 3 +- examples/adafruit_io_simpletest_feeds.py | 54 ++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 2 deletions(-) create mode 100644 examples/adafruit_io_simpletest_feeds.py diff --git a/examples/adafruit_io_simpletest_data.py b/examples/adafruit_io_simpletest_data.py index 539d5fb..90c4eb9 100644 --- a/examples/adafruit_io_simpletest_data.py +++ b/examples/adafruit_io_simpletest_data.py @@ -1,7 +1,6 @@ """ Sending data to Adafruit IO and receiving it. """ -import time import board import busio from random import randint @@ -36,7 +35,7 @@ ADAFRUIT_IO_USER = settings['adafruit_io_user'] ADAFRUIT_IO_KEY = settings['adafruit_io_key'] -# Create an instance of the Adafruit IO RESTClient +# Create an instance of the Adafruit IO REST client io = RESTClient(ADAFRUIT_IO_USER, ADAFRUIT_IO_KEY, wifi) try: diff --git a/examples/adafruit_io_simpletest_feeds.py b/examples/adafruit_io_simpletest_feeds.py new file mode 100644 index 0000000..2b1db05 --- /dev/null +++ b/examples/adafruit_io_simpletest_feeds.py @@ -0,0 +1,54 @@ +""" +Example of interacting with Adafruit IO feeds +""" +import time +import board +import busio +from digitalio import DigitalInOut, Direction + +# ESP32 SPI +import microcontroller +from adafruit_esp32spi import adafruit_esp32spi, adafruit_esp32spi_wifimanager + +# Import Adafruit IO REST Client +from Adafruit_IO import RESTClient + +# Get wifi details and more from a settings.py file +try: + from settings import settings +except ImportError: + print("WiFi settings are kept in settings.py, please add them there!") + raise + +# PyPortal ESP32 Setup +esp32_cs = DigitalInOut(microcontroller.pin.PB14) +esp32_ready = DigitalInOut(microcontroller.pin.PB16) +esp32_gpio0 = DigitalInOut(microcontroller.pin.PB15) +esp32_reset = DigitalInOut(microcontroller.pin.PB17) +spi = busio.SPI(board.SCK, board.MOSI, board.MISO) +esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset) +wifi = adafruit_esp32spi_wifimanager.ESPSPI_WiFiManager(esp, settings, board.NEOPIXEL) + +# Set your Adafruit IO Username and Key in settings.py +# (visit io.adafruit.com if you need to create an account, +# or if you need your Adafruit IO key.) +ADAFRUIT_IO_USER = settings['adafruit_io_user'] +ADAFRUIT_IO_KEY = settings['adafruit_io_key'] + +# Create an instance of the Adafruit IO REST client +io = RESTClient(ADAFRUIT_IO_USER, ADAFRUIT_IO_KEY, wifi) + +# Create a new 'circuitpython' feed with a description +print('Creating new Adafruit IO feed...') +feed = io.create_new_feed('circuitpython', 'a Adafruit IO CircuitPython feed') +print(feed) + +# List a specified feed +print('Retrieving new Adafruit IO feed...') +specified_feed = io.get_feed('circuitpython') +print(specified_feed) + +# Delete a specified feed by feed key +print('Deleting feed...') +io.delete_feed(specified_feed['key']) +print('Feed deleted!') \ No newline at end of file From c01873fdff0c5bf0fa1583187eec65ff97fd4440 Mon Sep 17 00:00:00 2001 From: brentru Date: Thu, 21 Feb 2019 12:26:53 -0500 Subject: [PATCH 06/48] add location metadata example --- examples/adafruit_io_simpletest_location.py | 60 +++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 examples/adafruit_io_simpletest_location.py diff --git a/examples/adafruit_io_simpletest_location.py b/examples/adafruit_io_simpletest_location.py new file mode 100644 index 0000000..b0e8a56 --- /dev/null +++ b/examples/adafruit_io_simpletest_location.py @@ -0,0 +1,60 @@ +""" +Example of attaching location +metadata to data sent to Adafruit IO. +""" +import board +import busio +from random import randint +from digitalio import DigitalInOut, Direction + +# ESP32 SPI +import microcontroller +from adafruit_esp32spi import adafruit_esp32spi, adafruit_esp32spi_wifimanager + +# Import Adafruit IO REST Client +from Adafruit_IO import RESTClient + +# Get wifi details and more from a settings.py file +try: + from settings import settings +except ImportError: + print("WiFi settings are kept in settings.py, please add them there!") + raise + +# PyPortal ESP32 Setup +esp32_cs = DigitalInOut(microcontroller.pin.PB14) +esp32_ready = DigitalInOut(microcontroller.pin.PB16) +esp32_gpio0 = DigitalInOut(microcontroller.pin.PB15) +esp32_reset = DigitalInOut(microcontroller.pin.PB17) +spi = busio.SPI(board.SCK, board.MOSI, board.MISO) +esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset) +wifi = adafruit_esp32spi_wifimanager.ESPSPI_WiFiManager(esp, settings, board.NEOPIXEL) + +# Set your Adafruit IO Username and Key in settings.py +# (visit io.adafruit.com if you need to create an account, +# or if you need your Adafruit IO key.) +ADAFRUIT_IO_USER = settings['adafruit_io_user'] +ADAFRUIT_IO_KEY = settings['adafruit_io_key'] + +# Create an instance of the Adafruit IO REST client +io = RESTClient(ADAFRUIT_IO_USER, ADAFRUIT_IO_KEY, wifi) + +try: + # Get the 'location' feed from Adafruit IO + location_feed = io.get_feed('location') +except AdafruitIO_RequestError: + # If no 'location' feed exists, create one + location_feed = io.create_new_feed('location') + +# Set data +data_value = 42 + +# Set up the Top-Secret Adafruit HQ Location Coordinate metadata +lat = 40.726190 +lon = -74.005334 +ele = 6 + +# Send data and location metadata to the 'location' feed +print('Sending data and location metadata to IO...') +io.send_data(location_feed['key'], data_value, lat, lon, ele) +print('Data sent!') From 350736a924a523a5491200f451d2c680b9be839b Mon Sep 17 00:00:00 2001 From: brentru Date: Thu, 21 Feb 2019 12:46:22 -0500 Subject: [PATCH 07/48] add adt7410 example, add error classes to examples --- examples/adafruit_io_simpletest_data.py | 2 +- examples/adafruit_io_simpletest_feeds.py | 2 +- examples/adafruit_io_simpletest_location.py | 2 +- .../adafruit_io_simpletest_temperature.py | 67 +++++++++++++++++++ 4 files changed, 70 insertions(+), 3 deletions(-) create mode 100644 examples/adafruit_io_simpletest_temperature.py diff --git a/examples/adafruit_io_simpletest_data.py b/examples/adafruit_io_simpletest_data.py index 90c4eb9..b1ad87e 100644 --- a/examples/adafruit_io_simpletest_data.py +++ b/examples/adafruit_io_simpletest_data.py @@ -11,7 +11,7 @@ from adafruit_esp32spi import adafruit_esp32spi, adafruit_esp32spi_wifimanager # Import Adafruit IO REST Client -from Adafruit_IO import RESTClient +from Adafruit_IO import RESTClient, AdafruitIO_RequestError, AdafruitIO_ThrottleError # Get wifi details and more from a settings.py file try: diff --git a/examples/adafruit_io_simpletest_feeds.py b/examples/adafruit_io_simpletest_feeds.py index 2b1db05..b0d0f4b 100644 --- a/examples/adafruit_io_simpletest_feeds.py +++ b/examples/adafruit_io_simpletest_feeds.py @@ -11,7 +11,7 @@ from adafruit_esp32spi import adafruit_esp32spi, adafruit_esp32spi_wifimanager # Import Adafruit IO REST Client -from Adafruit_IO import RESTClient +from Adafruit_IO import RESTClient, AdafruitIO_RequestError, AdafruitIO_ThrottleError # Get wifi details and more from a settings.py file try: diff --git a/examples/adafruit_io_simpletest_location.py b/examples/adafruit_io_simpletest_location.py index b0e8a56..85bd30a 100644 --- a/examples/adafruit_io_simpletest_location.py +++ b/examples/adafruit_io_simpletest_location.py @@ -12,7 +12,7 @@ from adafruit_esp32spi import adafruit_esp32spi, adafruit_esp32spi_wifimanager # Import Adafruit IO REST Client -from Adafruit_IO import RESTClient +from Adafruit_IO import RESTClient, AdafruitIO_RequestError, AdafruitIO_ThrottleError # Get wifi details and more from a settings.py file try: diff --git a/examples/adafruit_io_simpletest_temperature.py b/examples/adafruit_io_simpletest_temperature.py new file mode 100644 index 0000000..b516529 --- /dev/null +++ b/examples/adafruit_io_simpletest_temperature.py @@ -0,0 +1,67 @@ +""" +Example of sending temperature +values to an Adafruit IO feed. + +Dependencies: + * CircuitPython_ADT7410 + https://github.com/adafruit/Adafruit_CircuitPython_ADT7410 +""" +import board +import microcontroller +import busio +import time +from digitalio import DigitalInOut, Direction + +# ESP32 SPI +from adafruit_esp32spi import adafruit_esp32spi, adafruit_esp32spi_wifimanager + +# Import Adafruit IO REST Client +from Adafruit_IO import RESTClient, AdafruitIO_RequestError, AdafruitIO_ThrottleError + +# Import ADT7410 Library +import adafruit_adt7410 + +# Get wifi details and more from a settings.py file +try: + from settings import settings +except ImportError: + print("WiFi settings are kept in settings.py, please add them there!") + raise + +# PyPortal ESP32 Setup +esp32_cs = DigitalInOut(microcontroller.pin.PB14) +esp32_ready = DigitalInOut(microcontroller.pin.PB16) +esp32_gpio0 = DigitalInOut(microcontroller.pin.PB15) +esp32_reset = DigitalInOut(microcontroller.pin.PB17) +spi = busio.SPI(board.SCK, board.MOSI, board.MISO) +esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset) +wifi = adafruit_esp32spi_wifimanager.ESPSPI_WiFiManager(esp, settings, board.NEOPIXEL) + +# Set your Adafruit IO Username and Key in settings.py +# (visit io.adafruit.com if you need to create an account, +# or if you need your Adafruit IO key.) +ADAFRUIT_IO_USER = settings['adafruit_io_user'] +ADAFRUIT_IO_KEY = settings['adafruit_io_key'] + +# Create an instance of the Adafruit IO REST client +io = RESTClient(ADAFRUIT_IO_USER, ADAFRUIT_IO_KEY, wifi) + +try: + # Get the 'temperature' feed from Adafruit IO + temperature_feed = io.get_feed('temperature') +except AdafruitIO_RequestError: + # If no 'temperature' feed exists, create one + temperature_feed = io.create_new_feed('temperature') + +# Set up ADT7410 sensor +i2c_bus = busio.I2C(board.SCL, board.SDA) +adt = adafruit_adt7410.ADT7410(i2c_bus, address=0x48) +adt.high_resolution = True + +while True: + temperature = adt.temperature + print('Current Temperature is {0}C'.format(adt.temperature)) + print('Sending to Adafruit IO...') + io.send_data(temperature_feed['key'], temperature) + print('Data sent!') + time.sleep(0.5) \ No newline at end of file From 5c32764b3307c51501d61f40219b3dad522c109c Mon Sep 17 00:00:00 2001 From: brentru Date: Thu, 21 Feb 2019 12:49:41 -0500 Subject: [PATCH 08/48] send only 2 prec. points of temperature data --- examples/adafruit_io_simpletest_temperature.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/examples/adafruit_io_simpletest_temperature.py b/examples/adafruit_io_simpletest_temperature.py index b516529..0ad1463 100644 --- a/examples/adafruit_io_simpletest_temperature.py +++ b/examples/adafruit_io_simpletest_temperature.py @@ -60,7 +60,10 @@ while True: temperature = adt.temperature - print('Current Temperature is {0}C'.format(adt.temperature)) + # set temperature value to two precision points + temperature = '%0.2f'%(temperature) + + print('Current Temperature: {0}*C'.format(temperature)) print('Sending to Adafruit IO...') io.send_data(temperature_feed['key'], temperature) print('Data sent!') From 598a9e567ed18a64861a0d1ec50b2e6a642e3275 Mon Sep 17 00:00:00 2001 From: brentru Date: Thu, 21 Feb 2019 13:38:03 -0500 Subject: [PATCH 09/48] add digital out example --- .../adafruit_io_simpletest_digital_out.py | 66 +++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 examples/adafruit_io_simpletest_digital_out.py diff --git a/examples/adafruit_io_simpletest_digital_out.py b/examples/adafruit_io_simpletest_digital_out.py new file mode 100644 index 0000000..0897483 --- /dev/null +++ b/examples/adafruit_io_simpletest_digital_out.py @@ -0,0 +1,66 @@ +""" +Example of turning on and off a LED +from an Adafruit IO Dashboard. +""" +import board +import microcontroller +import busio +import time +from digitalio import DigitalInOut, Direction + +# ESP32 SPI +from adafruit_esp32spi import adafruit_esp32spi, adafruit_esp32spi_wifimanager + +# Import Adafruit IO REST Client +from Adafruit_IO import RESTClient, AdafruitIO_RequestError, AdafruitIO_ThrottleError + +# Get wifi details and more from a settings.py file +try: + from settings import settings +except ImportError: + print("WiFi settings are kept in settings.py, please add them there!") + raise + +# PyPortal ESP32 Setup +esp32_cs = DigitalInOut(microcontroller.pin.PB14) +esp32_ready = DigitalInOut(microcontroller.pin.PB16) +esp32_gpio0 = DigitalInOut(microcontroller.pin.PB15) +esp32_reset = DigitalInOut(microcontroller.pin.PB17) +spi = busio.SPI(board.SCK, board.MOSI, board.MISO) +esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset) +wifi = adafruit_esp32spi_wifimanager.ESPSPI_WiFiManager(esp, settings, board.NEOPIXEL) + +# Set your Adafruit IO Username and Key in settings.py +# (visit io.adafruit.com if you need to create an account, +# or if you need your Adafruit IO key.) +ADAFRUIT_IO_USER = settings['adafruit_io_user'] +ADAFRUIT_IO_KEY = settings['adafruit_io_key'] + +# Create an instance of the Adafruit IO REST client +io = RESTClient(ADAFRUIT_IO_USER, ADAFRUIT_IO_KEY, wifi) + +try: + # Get the 'digital' feed from Adafruit IO + digital_feed = io.get_feed('digital') +except AdafruitIO_RequestError: + # If no 'digital' feed exists, create one + digital_feed = io.create_new_feed('digital') + +# Set up LED +LED = DigitalInOut(board.D13) +LED.direction = Direction.OUTPUT + +while True: + # Get data from 'digital' feed + feed_data = io.receive_data(digital_feed['key']) + + # Check if data is ON or OFF + if int(feed_data['value'] == 1): + print('received <- ON\n') + elif int(feed_data['value'] == 0): + print('received <= OFF\n') + + # Set the LED to the feed value + LED.value = int(feed_data['value']) + + time.sleep(0.5) \ No newline at end of file From 07a5003ad13ee8676203c58ba7b8b7a01ae34ce8 Mon Sep 17 00:00:00 2001 From: brentru Date: Thu, 21 Feb 2019 13:41:20 -0500 Subject: [PATCH 10/48] update to RESTClient --- adafruit_io.py | 2 +- examples/adafruit_io_simpletest.py | 53 ------------------- .../adafruit_io_simpletest_digital_out.py | 2 +- 3 files changed, 2 insertions(+), 55 deletions(-) delete mode 100644 examples/adafruit_io_simpletest.py diff --git a/adafruit_io.py b/adafruit_io.py index 1a37abe..4117964 100644 --- a/adafruit_io.py +++ b/adafruit_io.py @@ -58,7 +58,7 @@ def __init__(self, response): error = response_content['error'] super(AdafruitIO_RequestError, self).__init__("Adafruit IO Error {0}: {1}".format(response.status_code, error)) -class HTTPClient(object): +class RESTClient(object): def __init__(self, username, key, wifi_manager, api_version='v2'): """ Adafruit IO API REST Client diff --git a/examples/adafruit_io_simpletest.py b/examples/adafruit_io_simpletest.py deleted file mode 100644 index a408136..0000000 --- a/examples/adafruit_io_simpletest.py +++ /dev/null @@ -1,53 +0,0 @@ -""" -Send data to Adafruit IO, and retrieve it. -""" -import time -import board -import busio -import adafruit_io -from digitalio import DigitalInOut, Direction - -# ESP32 SPI -import microcontroller -from adafruit_esp32spi import adafruit_esp32spi -from adafruit_esp32spi import adafruit_esp32spi_wifimanager - -# Get wifi details and more from a settings.py file -try: - from settings import settings -except ImportError: - print("WiFi settings are kept in settings.py, please add them there!") - raise - -# PyPortal ESP32 Setup -esp32_cs = DigitalInOut(microcontroller.pin.PB14) # PB14 -esp32_ready = DigitalInOut(microcontroller.pin.PB16) -esp32_gpio0 = DigitalInOut(microcontroller.pin.PB15) -esp32_reset = DigitalInOut(microcontroller.pin.PB17) -spi = busio.SPI(board.SCK, board.MOSI, board.MISO) -esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset) -wifi = adafruit_esp32spi_wifimanager.ESPSPI_WiFiManager(esp, settings, board.NEOPIXEL) - -# Adafruit IO Setup -ADAFRUIT_IO_USER = 'YOUR_ADAFRUIT_IO_USERNAME' -ADAFRUIT_IO_KEY = 'YOUR_ADAFRUIT_IO_PASSWORD' -ADAFRUIT_IO_FEED = 'testfeed' -aio = adafruit_io.Client(ADAFRUIT_IO_USER, ADAFRUIT_IO_KEY, wifi) - -counter = 0 -while True: - try: - data = counter - print('Sending {0} to Adafruit IO...'.format(data)) - aio.send_data(ADAFRUIT_IO_FEED, data) - print('Data sent!') - - print('Receiving Feed {0}...'.format(ADAFRUIT_IO_FEED)) - data = aio.receive_data(ADAFRUIT_IO_FEED) - print('Feed Value:', data['value']) - - counter = counter + 1 - except (ValueError, RuntimeError) as e: - print("Failed to get data, retrying\n", e) - continue - response = None \ No newline at end of file diff --git a/examples/adafruit_io_simpletest_digital_out.py b/examples/adafruit_io_simpletest_digital_out.py index 0897483..7f00e9b 100644 --- a/examples/adafruit_io_simpletest_digital_out.py +++ b/examples/adafruit_io_simpletest_digital_out.py @@ -63,4 +63,4 @@ # Set the LED to the feed value LED.value = int(feed_data['value']) - time.sleep(0.5) \ No newline at end of file + time.sleep(0.5) From 1eaa19eb765fda3b0a53cd5c3bcd1c4565fcec74 Mon Sep 17 00:00:00 2001 From: brentru Date: Thu, 21 Feb 2019 13:43:11 -0500 Subject: [PATCH 11/48] feed desc and license are optional kwargs --- adafruit_io.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/adafruit_io.py b/adafruit_io.py index 4117964..a5d2323 100644 --- a/adafruit_io.py +++ b/adafruit_io.py @@ -216,12 +216,12 @@ def get_feed(self, feed_key, detailed=False): path = self._compose_path("feeds/{0}".format(feed_key)) return self._get(path) - def create_new_feed(self, feed_key, feed_desc, feed_license): + def create_new_feed(self, feed_key, feed_desc=None, feed_license=None): """ Creates a new feed. :param str feed_key: Feed key - :param str feed_desc: Description of feed - :param str feed_license: Feed License + :param str feed_desc: Optional description of feed + :param str feed_license: Optional feed License """ path = self._compose_path("feeds") packet = packet = {'name':feed_key, From da296487eebe83bafa6fd4bd94cadcbcf44d9077 Mon Sep 17 00:00:00 2001 From: brentru Date: Thu, 21 Feb 2019 13:46:17 -0500 Subject: [PATCH 12/48] pylint examples --- examples/adafruit_io_simpletest_data.py | 6 +++--- examples/adafruit_io_simpletest_digital_out.py | 4 ++-- examples/adafruit_io_simpletest_feeds.py | 7 +++---- examples/adafruit_io_simpletest_location.py | 5 ++--- examples/adafruit_io_simpletest_temperature.py | 6 +++--- 5 files changed, 13 insertions(+), 15 deletions(-) diff --git a/examples/adafruit_io_simpletest_data.py b/examples/adafruit_io_simpletest_data.py index b1ad87e..7e35571 100644 --- a/examples/adafruit_io_simpletest_data.py +++ b/examples/adafruit_io_simpletest_data.py @@ -1,17 +1,17 @@ """ Sending data to Adafruit IO and receiving it. """ +from random import randint import board import busio -from random import randint -from digitalio import DigitalInOut, Direction +from digitalio import DigitalInOut # ESP32 SPI import microcontroller from adafruit_esp32spi import adafruit_esp32spi, adafruit_esp32spi_wifimanager # Import Adafruit IO REST Client -from Adafruit_IO import RESTClient, AdafruitIO_RequestError, AdafruitIO_ThrottleError +from Adafruit_IO import RESTClient, AdafruitIO_RequestError # Get wifi details and more from a settings.py file try: diff --git a/examples/adafruit_io_simpletest_digital_out.py b/examples/adafruit_io_simpletest_digital_out.py index 7f00e9b..2c91384 100644 --- a/examples/adafruit_io_simpletest_digital_out.py +++ b/examples/adafruit_io_simpletest_digital_out.py @@ -2,17 +2,17 @@ Example of turning on and off a LED from an Adafruit IO Dashboard. """ +import time import board import microcontroller import busio -import time from digitalio import DigitalInOut, Direction # ESP32 SPI from adafruit_esp32spi import adafruit_esp32spi, adafruit_esp32spi_wifimanager # Import Adafruit IO REST Client -from Adafruit_IO import RESTClient, AdafruitIO_RequestError, AdafruitIO_ThrottleError +from Adafruit_IO import RESTClient, AdafruitIO_RequestError # Get wifi details and more from a settings.py file try: diff --git a/examples/adafruit_io_simpletest_feeds.py b/examples/adafruit_io_simpletest_feeds.py index b0d0f4b..6b5fef7 100644 --- a/examples/adafruit_io_simpletest_feeds.py +++ b/examples/adafruit_io_simpletest_feeds.py @@ -1,17 +1,16 @@ """ Example of interacting with Adafruit IO feeds """ -import time import board import busio -from digitalio import DigitalInOut, Direction +from digitalio import DigitalInOut # ESP32 SPI import microcontroller from adafruit_esp32spi import adafruit_esp32spi, adafruit_esp32spi_wifimanager # Import Adafruit IO REST Client -from Adafruit_IO import RESTClient, AdafruitIO_RequestError, AdafruitIO_ThrottleError +from Adafruit_IO import RESTClient # Get wifi details and more from a settings.py file try: @@ -51,4 +50,4 @@ # Delete a specified feed by feed key print('Deleting feed...') io.delete_feed(specified_feed['key']) -print('Feed deleted!') \ No newline at end of file +print('Feed deleted!') diff --git a/examples/adafruit_io_simpletest_location.py b/examples/adafruit_io_simpletest_location.py index 85bd30a..ea3a427 100644 --- a/examples/adafruit_io_simpletest_location.py +++ b/examples/adafruit_io_simpletest_location.py @@ -4,15 +4,14 @@ """ import board import busio -from random import randint -from digitalio import DigitalInOut, Direction +from digitalio import DigitalInOut # ESP32 SPI import microcontroller from adafruit_esp32spi import adafruit_esp32spi, adafruit_esp32spi_wifimanager # Import Adafruit IO REST Client -from Adafruit_IO import RESTClient, AdafruitIO_RequestError, AdafruitIO_ThrottleError +from Adafruit_IO import RESTClient, AdafruitIO_RequestError # Get wifi details and more from a settings.py file try: diff --git a/examples/adafruit_io_simpletest_temperature.py b/examples/adafruit_io_simpletest_temperature.py index 0ad1463..7ca6908 100644 --- a/examples/adafruit_io_simpletest_temperature.py +++ b/examples/adafruit_io_simpletest_temperature.py @@ -6,17 +6,17 @@ * CircuitPython_ADT7410 https://github.com/adafruit/Adafruit_CircuitPython_ADT7410 """ +import time import board import microcontroller import busio -import time -from digitalio import DigitalInOut, Direction +from digitalio import DigitalInOut # ESP32 SPI from adafruit_esp32spi import adafruit_esp32spi, adafruit_esp32spi_wifimanager # Import Adafruit IO REST Client -from Adafruit_IO import RESTClient, AdafruitIO_RequestError, AdafruitIO_ThrottleError +from Adafruit_IO import RESTClient, AdafruitIO_RequestError # Import ADT7410 Library import adafruit_adt7410 From e800ab90f424518b4136bc6d4c36f78929ba3f61 Mon Sep 17 00:00:00 2001 From: brentru Date: Thu, 21 Feb 2019 13:52:43 -0500 Subject: [PATCH 13/48] pylint adafruit_io.py --- adafruit_io.py | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/adafruit_io.py b/adafruit_io.py index a5d2323..ea830f3 100644 --- a/adafruit_io.py +++ b/adafruit_io.py @@ -36,7 +36,7 @@ * Adafruit CircuitPython firmware for the supported boards: https://github.com/adafruit/circuitpython/releases -* Adafruit's ESP32SPI library: +* Adafruit's ESP32SPI library: https://github.com/adafruit/Adafruit_CircuitPython_ESP32SPI """ @@ -56,9 +56,10 @@ class AdafruitIO_RequestError(Exception): def __init__(self, response): response_content = response.json() error = response_content['error'] - super(AdafruitIO_RequestError, self).__init__("Adafruit IO Error {0}: {1}".format(response.status_code, error)) + super(AdafruitIO_RequestError, self).__init__("Adafruit IO Error {0}: {1}" + .format(response.status_code, error)) -class RESTClient(object): +class RESTClient(): def __init__(self, username, key, wifi_manager, api_version='v2'): """ Adafruit IO API REST Client @@ -75,16 +76,16 @@ def __init__(self, username, key, wifi_manager, api_version='v2'): self.wifi = wifi_manager else: raise TypeError("This library requires a WiFiManager object.") - self.http_headers = [{bytes("X-AIO-KEY","utf-8"):bytes(self.key,"utf-8"), - bytes("Content-Type","utf-8"):bytes('application/json',"utf-8")}, - {bytes("X-AIO-KEY","utf-8"):bytes(self.key,"utf-8")}] + self.http_headers = [{bytes("X-AIO-KEY", "utf-8"):bytes(self.key, "utf-8"), + bytes("Content-Type", "utf-8"):bytes('application/json', "utf-8")}, + {bytes("X-AIO-KEY", "utf-8"):bytes(self.key, "utf-8")}] def _compose_path(self, path): return "{0}/{1}/{2}/{3}".format(self.url, self.api_version, self.username, path) - + def _create_data(self, data, latitude, longitude, elevation, timestamp): return {'value':data, 'lat':latitude, 'lon':longitude, - 'ele':elevation, 'created_at':timestamp} + 'ele':elevation, 'created_at':timestamp} def _handle_error(self, response): if response.status_code == 429: @@ -104,8 +105,8 @@ def _post(self, path, packet): """ response = self.wifi.post( path, - json = packet, - headers = self.http_headers[0]) + json=packet, + headers=self.http_headers[0]) self._handle_error(response) return response.json() response.close() @@ -121,7 +122,7 @@ def _get(self, path): self._handle_error(response) return response.json() response.close() - + def _delete(self, path): """ Delete data from Adafruit IO. @@ -129,12 +130,12 @@ def _delete(self, path): """ response = self.wifi.delete( path, - headers = self.http_headers[0]) + headers=self.http_headers[0]) self._handle_error(response) return response.json() response.close() - # Data + # Data def send_data(self, feed_key, data, lat=None, lon=None, ele=None, created_at=None): """ Sends value data to an Adafruit IO feed. @@ -225,8 +226,8 @@ def create_new_feed(self, feed_key, feed_desc=None, feed_license=None): """ path = self._compose_path("feeds") packet = packet = {'name':feed_key, - 'description':feed_desc, - 'license':feed_license} + 'description':feed_desc, + 'license':feed_license} return self._post(path, packet) def delete_feed(self, feed_key): @@ -235,4 +236,4 @@ def delete_feed(self, feed_key): :param str feed_key: Valid feed key """ path = self._compose_path("feeds/{0}".format(feed_key)) - return self._delete(path) \ No newline at end of file + return self._delete(path) From 337392ef89ecd4fd8e6e88553d323cd2e81e0ad9 Mon Sep 17 00:00:00 2001 From: brentru Date: Thu, 21 Feb 2019 14:38:35 -0500 Subject: [PATCH 14/48] modify create_data to accept a list of metadata --- adafruit_io.py | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/adafruit_io.py b/adafruit_io.py index ea830f3..498c125 100644 --- a/adafruit_io.py +++ b/adafruit_io.py @@ -60,12 +60,15 @@ def __init__(self, response): .format(response.status_code, error)) class RESTClient(): + """ + REST Client for interacting with the Adafruit IO API. + """ def __init__(self, username, key, wifi_manager, api_version='v2'): """ - Adafruit IO API REST Client + Creates an instance of the Adafruit IO REST Client :param str username: Adafruit IO Username - :param str key: Adafruit IO Key, from `settings.py` - :param wifi_manager: ESP32WiFiManager Object + :param str key: Adafruit IO Key + :param wifi_manager: WiFiManager Object :param str api_version: Adafruit IO REST API Version """ self.api_version = api_version @@ -83,9 +86,9 @@ def __init__(self, username, key, wifi_manager, api_version='v2'): def _compose_path(self, path): return "{0}/{1}/{2}/{3}".format(self.url, self.api_version, self.username, path) - def _create_data(self, data, latitude, longitude, elevation, timestamp): - return {'value':data, 'lat':latitude, 'lon':longitude, - 'ele':elevation, 'created_at':timestamp} + def _create_data(self, data, metadata): + return {'value':data, 'lat':metadata[0], 'lon':metadata[1], + 'ele':metadata[2], 'created_at':metadata[3]} def _handle_error(self, response): if response.status_code == 429: @@ -109,7 +112,6 @@ def _post(self, path, packet): headers=self.http_headers[0]) self._handle_error(response) return response.json() - response.close() def _get(self, path): """ @@ -121,7 +123,6 @@ def _get(self, path): headers=self.http_headers[1]) self._handle_error(response) return response.json() - response.close() def _delete(self, path): """ @@ -133,7 +134,6 @@ def _delete(self, path): headers=self.http_headers[0]) self._handle_error(response) return response.json() - response.close() # Data def send_data(self, feed_key, data, lat=None, lon=None, ele=None, created_at=None): @@ -147,7 +147,8 @@ def send_data(self, feed_key, data, lat=None, lon=None, ele=None, created_at=Non :param string created_at: Optional date/time string """ path = self._compose_path("feeds/{0}/data".format(feed_key)) - packet = self._create_data(data, lat, lon, ele, created_at) + metadata = [lat, lon, ele, created_at] + packet = self._create_data(data, metadata) self._post(path, packet) def receive_data(self, feed_key): From ceb81366c5b2bfade3ca084131bb8e10767538bd Mon Sep 17 00:00:00 2001 From: brentru Date: Thu, 21 Feb 2019 15:12:55 -0500 Subject: [PATCH 15/48] add dict metadata to send_data and create_data --- adafruit_io.py | 28 +++++++++---------- ....py => adafruit_io_simpletest_metadata.py} | 15 +++++----- .../adafruit_io_simpletest_temperature.py | 2 +- 3 files changed, 22 insertions(+), 23 deletions(-) rename examples/{adafruit_io_simpletest_location.py => adafruit_io_simpletest_metadata.py} (85%) diff --git a/adafruit_io.py b/adafruit_io.py index 498c125..f86b5b5 100644 --- a/adafruit_io.py +++ b/adafruit_io.py @@ -83,14 +83,13 @@ def __init__(self, username, key, wifi_manager, api_version='v2'): bytes("Content-Type", "utf-8"):bytes('application/json', "utf-8")}, {bytes("X-AIO-KEY", "utf-8"):bytes(self.key, "utf-8")}] - def _compose_path(self, path): - return "{0}/{1}/{2}/{3}".format(self.url, self.api_version, self.username, path) - - def _create_data(self, data, metadata): - return {'value':data, 'lat':metadata[0], 'lon':metadata[1], - 'ele':metadata[2], 'created_at':metadata[3]} + @staticmethod + def _create_data(data, metadata): + return {'value':data, 'lat':metadata['lat'], 'lon':metadata['lon'], + 'ele':metadata['ele'], 'created_at':metadata['created_at']} - def _handle_error(self, response): + @staticmethod + def _handle_error(response): if response.status_code == 429: raise AdafruitIO_ThrottleError elif response.status_code == 400: @@ -99,6 +98,9 @@ def _handle_error(self, response): raise AdafruitIO_RequestError(response) # no error? do nothing + def _compose_path(self, path): + return "{0}/{1}/{2}/{3}".format(self.url, self.api_version, self.username, path) + # HTTP Requests def _post(self, path, packet): """ @@ -136,18 +138,14 @@ def _delete(self, path): return response.json() # Data - def send_data(self, feed_key, data, lat=None, lon=None, ele=None, created_at=None): + def send_data(self, feed_key, data, metadata=None): """ Sends value data to an Adafruit IO feed. :param str feed_key: Specified Adafruit IO feed - :param data: Data to send to an Adafruit IO feed - :param int lat: Optional latitude - :param int lon: Optional longitude - :param int ele: Optional elevation - :param string created_at: Optional date/time string + :param str data: Data to send to an Adafruit IO feed + :param dict metadata: Metadata associated with the data being sent """ path = self._compose_path("feeds/{0}/data".format(feed_key)) - metadata = [lat, lon, ele, created_at] packet = self._create_data(data, metadata) self._post(path, packet) @@ -165,7 +163,7 @@ def delete_data(self, feed_key, data_id): :param string feed: Feed Key :param string data_id: Data point to delete """ - path = self._compose_path("feeds/{0}/data/{0}".format(feed_key, data_id)) + path = self._compose_path("feeds/{0}/data/{1}".format(feed_key, data_id)) return self._delete(path) # Groups diff --git a/examples/adafruit_io_simpletest_location.py b/examples/adafruit_io_simpletest_metadata.py similarity index 85% rename from examples/adafruit_io_simpletest_location.py rename to examples/adafruit_io_simpletest_metadata.py index ea3a427..5c03cbf 100644 --- a/examples/adafruit_io_simpletest_location.py +++ b/examples/adafruit_io_simpletest_metadata.py @@ -1,6 +1,6 @@ """ -Example of attaching location -metadata to data sent to Adafruit IO. +Example of attaching metadata +to data sent to Adafruit IO. """ import board import busio @@ -48,12 +48,13 @@ # Set data data_value = 42 -# Set up the Top-Secret Adafruit HQ Location Coordinate metadata -lat = 40.726190 -lon = -74.005334 -ele = 6 +# Set up metadata associated with data_value +metadata = {'lat': 40.726190, + 'lon': -74.005334, + 'ele': -6, + 'created_at': None} # Send data and location metadata to the 'location' feed print('Sending data and location metadata to IO...') -io.send_data(location_feed['key'], data_value, lat, lon, ele) +io.send_data(location_feed['key'], data_value, metadata) print('Data sent!') diff --git a/examples/adafruit_io_simpletest_temperature.py b/examples/adafruit_io_simpletest_temperature.py index 7ca6908..8a5dc08 100644 --- a/examples/adafruit_io_simpletest_temperature.py +++ b/examples/adafruit_io_simpletest_temperature.py @@ -67,4 +67,4 @@ print('Sending to Adafruit IO...') io.send_data(temperature_feed['key'], temperature) print('Data sent!') - time.sleep(0.5) \ No newline at end of file + time.sleep(0.5) From 03396c0f513a4f9527a6b15419b56320f7723288 Mon Sep 17 00:00:00 2001 From: brentru Date: Thu, 21 Feb 2019 15:15:50 -0500 Subject: [PATCH 16/48] s/packet/payload --- adafruit_io.py | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/adafruit_io.py b/adafruit_io.py index f86b5b5..4ae6d26 100644 --- a/adafruit_io.py +++ b/adafruit_io.py @@ -102,15 +102,15 @@ def _compose_path(self, path): return "{0}/{1}/{2}/{3}".format(self.url, self.api_version, self.username, path) # HTTP Requests - def _post(self, path, packet): + def _post(self, path, payload): """ Send data to Adafruit IO :param str path: Formatted Adafruit IO URL - :param json packet: JSON data to send to Adafruit IO + :param json payload: JSON data to send to Adafruit IO """ response = self.wifi.post( path, - json=packet, + json=payload, headers=self.http_headers[0]) self._handle_error(response) return response.json() @@ -146,8 +146,8 @@ def send_data(self, feed_key, data, metadata=None): :param dict metadata: Metadata associated with the data being sent """ path = self._compose_path("feeds/{0}/data".format(feed_key)) - packet = self._create_data(data, metadata) - self._post(path, packet) + payload = self._create_data(data, metadata) + self._post(path, payload) def receive_data(self, feed_key): """ @@ -174,8 +174,8 @@ def add_feed_to_group(self, group_key, feed_key): :param str feed_key: Feed to add to the group """ path = self._compose_path("groups/{0}/add".format(group_key)) - packet = {'feed_key':feed_key} - return self._post(path, packet) + payload = {'feed_key':feed_key} + return self._post(path, payload) def create_new_group(self, group_key, group_description): """ @@ -184,8 +184,8 @@ def create_new_group(self, group_key, group_description): :param str group_description: Brief summary about the group """ path = self._compose_path("groups") - packet = {'name':group_key, 'description':group_description} - return self._post(path, packet) + payload = {'name':group_key, 'description':group_description} + return self._post(path, payload) def delete_group(self, group_key): """ @@ -224,10 +224,10 @@ def create_new_feed(self, feed_key, feed_desc=None, feed_license=None): :param str feed_license: Optional feed License """ path = self._compose_path("feeds") - packet = packet = {'name':feed_key, - 'description':feed_desc, - 'license':feed_license} - return self._post(path, packet) + payload = {'name':feed_key, + 'description':feed_desc, + 'license':feed_license} + return self._post(path, payload) def delete_feed(self, feed_key): """ From af518a2e2c2b1b395778a4b6f1bdfffbffb7b9f8 Mon Sep 17 00:00:00 2001 From: brentru Date: Thu, 21 Feb 2019 16:12:35 -0500 Subject: [PATCH 17/48] update readme, setup, lib --- README.rst | 43 ++++++++++++------------------------------- adafruit_io.py | 34 ++++++++++++++-------------------- setup.py | 6 ++---- 3 files changed, 28 insertions(+), 55 deletions(-) diff --git a/README.rst b/README.rst index 7af94b9..f1b1fd2 100644 --- a/README.rst +++ b/README.rst @@ -27,49 +27,30 @@ Please ensure all dependencies are available on the CircuitPython filesystem. This is easily achieved by downloading `the Adafruit library and driver bundle `_. -Installing from PyPI --------------------- -.. note:: This library is not available on PyPI yet. Install documentation is included - as a standard element. Stay tuned for PyPI availability! -.. todo:: Remove the above note if PyPI version is/will be available at time of release. - If the library is not planned for PyPI, remove the entire 'Installing from PyPI' section. -On supported GNU/Linux systems like the Raspberry Pi, you can install the driver locally `from -PyPI `_. To install for current user: - -.. code-block:: shell - - pip3 install adafruit-circuitpython-adafruit_io - -To install system-wide (this may be required in some cases): - -.. code-block:: shell - - sudo pip3 install adafruit-circuitpython-adafruit_io - -To install in a virtual environment in your current project: - -.. code-block:: shell - - mkdir project-name && cd project-name - python3 -m venv .env - source .env/bin/activate - pip3 install adafruit-circuitpython-adafruit_io - Usage Example ============= Create an Adafruit IO Client object .. code-block:: python - aio = adafruit_io.Client(ADAFRUIT_IO_USER, ADAFRUIT_IO_KEY, wifi) + io = RESTClient(ADAFRUIT_IO_USER, ADAFRUIT_IO_KEY, wifi) Sending `data` to an Adafruit IO feed .. code-block:: python - aio.send_data(my_adafruit_io_feed, data) + io.send_data(feed, data) Receiving `data` from an Adafruit IO feed .. code-block:: python - data = aio.receive_data(my_adafruit_io_feed) + data = io.receive_data(feed) + +Creating a new feed named `circuitpython` with a description +.. code-block:: python + feed = io.create_new_feed('circuitpython', 'an Adafruit IO CircuitPython feed') + +Listing the record of a specified feed: +.. code-block:: python + feed = io.get_feed('circuitpython') +More usage examples are included in the `examples folder of this repository<`_ Contributing ============ diff --git a/adafruit_io.py b/adafruit_io.py index 4ae6d26..acb6df6 100644 --- a/adafruit_io.py +++ b/adafruit_io.py @@ -25,7 +25,6 @@ A CircuitPython/Python library for communicating with Adafruit IO - * Author(s): Brent Rubell for Adafruit Industries Implementation Notes @@ -40,19 +39,17 @@ https://github.com/adafruit/Adafruit_CircuitPython_ESP32SPI """ -# imports - __version__ = "0.0.0-auto.0" __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_Adafruit_IO.git" class AdafruitIO_ThrottleError(Exception): - """Adafruit IO request error class for Throttle Errors""" + """Adafruit IO request error class for rate-limiting""" def __init__(self): super(AdafruitIO_ThrottleError, self).__init__("Number of Adafruit IO Requests exceeded! \ Please try again in 30 seconds..") class AdafruitIO_RequestError(Exception): - """Base Adafruit IO request error class""" + """Adafruit IO request error class""" def __init__(self, response): response_content = response.json() error = response_content['error'] @@ -63,18 +60,15 @@ class RESTClient(): """ REST Client for interacting with the Adafruit IO API. """ - def __init__(self, username, key, wifi_manager, api_version='v2'): - """ - Creates an instance of the Adafruit IO REST Client - :param str username: Adafruit IO Username - :param str key: Adafruit IO Key - :param wifi_manager: WiFiManager Object - :param str api_version: Adafruit IO REST API Version - """ - self.api_version = api_version - self.url = 'https://io.adafruit.com/api' - self.username = username - self.key = key + def __init__(self, adafruit_io_username, adafruit_io_key, wifi_manager): + """ + Creates an instance of the Adafruit IO REST Client. + :param str adafruit_io_username: Adafruit IO Username + :param str adafruit_io_key: Adafruit IO Key + :param wifi_manager: WiFiManager object from adafruit_esp32spi_wifimanager + """ + self.username = adafruit_io_username + self.key = adafruit_io_key if wifi_manager: self.wifi = wifi_manager else: @@ -96,10 +90,9 @@ def _handle_error(response): raise AdafruitIO_RequestError(response) elif response.status_code >= 400: raise AdafruitIO_RequestError(response) - # no error? do nothing def _compose_path(self, path): - return "{0}/{1}/{2}/{3}".format(self.url, self.api_version, self.username, path) + return "{0}/{1}/{2}/{3}".format('https://io.adafruit.com/api', 'v2', self.username, path) # HTTP Requests def _post(self, path, payload): @@ -184,7 +177,8 @@ def create_new_group(self, group_key, group_description): :param str group_description: Brief summary about the group """ path = self._compose_path("groups") - payload = {'name':group_key, 'description':group_description} + payload = {'name':group_key, + 'description':group_description} return self._post(path, payload) def delete_group(self, group_key): diff --git a/setup.py b/setup.py index 5991328..88e6d11 100644 --- a/setup.py +++ b/setup.py @@ -17,7 +17,7 @@ long_description = f.read() setup( - name='adafruit-circuitpython-adafruit_io', + name='adafruit-circuitpython-adafruitio', use_scm_version=True, setup_requires=['setuptools_scm'], @@ -27,7 +27,7 @@ long_description_content_type='text/x-rst', # The project's main homepage. - url='https://github.com/adafruit/Adafruit_CircuitPython_Adafruit_IO', + url='https://github.com/adafruit/Adafruit_CircuitPython_AdafruitIO', # Author details author='Adafruit Industries', @@ -59,7 +59,5 @@ # You can just specify the packages manually here if your project is # simple. Or you can use find_packages(). - # TODO: IF LIBRARY FILES ARE A PACKAGE FOLDER, - # CHANGE `py_modules=['...']` TO `packages=['...']` py_modules=['adafruit_adafruit_io'], ) From d3762a1ca47edaa23cd8c7d0516fc47b39111dac Mon Sep 17 00:00:00 2001 From: brentru Date: Thu, 21 Feb 2019 16:32:35 -0500 Subject: [PATCH 18/48] switch to esp32spi_settings.py --- examples/adafruit_io_simpletest_data.py | 10 +++++----- examples/adafruit_io_simpletest_digital_out.py | 6 +++--- examples/adafruit_io_simpletest_feeds.py | 6 +++--- examples/adafruit_io_simpletest_metadata.py | 6 +++--- examples/adafruit_io_simpletest_temperature.py | 6 +++--- 5 files changed, 17 insertions(+), 17 deletions(-) diff --git a/examples/adafruit_io_simpletest_data.py b/examples/adafruit_io_simpletest_data.py index 7e35571..c9717d4 100644 --- a/examples/adafruit_io_simpletest_data.py +++ b/examples/adafruit_io_simpletest_data.py @@ -13,11 +13,11 @@ # Import Adafruit IO REST Client from Adafruit_IO import RESTClient, AdafruitIO_RequestError -# Get wifi details and more from a settings.py file +# Get wifi details and more from a esp32spi_settings.py file try: - from settings import settings + from esp32spi_settings import settings except ImportError: - print("WiFi settings are kept in settings.py, please add them there!") + print("WiFi settings are kept in esp32spi_settings.py, please add them there!") raise # PyPortal ESP32 Setup @@ -32,8 +32,8 @@ # Set your Adafruit IO Username and Key in settings.py # (visit io.adafruit.com if you need to create an account, # or if you need your Adafruit IO key.) -ADAFRUIT_IO_USER = settings['adafruit_io_user'] -ADAFRUIT_IO_KEY = settings['adafruit_io_key'] +ADAFRUIT_IO_USER = esp32spi_settings['adafruit_io_user'] +ADAFRUIT_IO_KEY = esp32spi_settings['adafruit_io_key'] # Create an instance of the Adafruit IO REST client io = RESTClient(ADAFRUIT_IO_USER, ADAFRUIT_IO_KEY, wifi) diff --git a/examples/adafruit_io_simpletest_digital_out.py b/examples/adafruit_io_simpletest_digital_out.py index 2c91384..131365e 100644 --- a/examples/adafruit_io_simpletest_digital_out.py +++ b/examples/adafruit_io_simpletest_digital_out.py @@ -14,11 +14,11 @@ # Import Adafruit IO REST Client from Adafruit_IO import RESTClient, AdafruitIO_RequestError -# Get wifi details and more from a settings.py file +# Get wifi details and more from a esp32spi_settings.py file try: - from settings import settings + from esp32spi_settings import settings except ImportError: - print("WiFi settings are kept in settings.py, please add them there!") + print("WiFi settings are kept in esp32spi_settings.py, please add them there!") raise # PyPortal ESP32 Setup diff --git a/examples/adafruit_io_simpletest_feeds.py b/examples/adafruit_io_simpletest_feeds.py index 6b5fef7..0371ce8 100644 --- a/examples/adafruit_io_simpletest_feeds.py +++ b/examples/adafruit_io_simpletest_feeds.py @@ -12,11 +12,11 @@ # Import Adafruit IO REST Client from Adafruit_IO import RESTClient -# Get wifi details and more from a settings.py file +# Get wifi details and more from a esp32spi_settings.py file try: - from settings import settings + from esp32spi_settings import settings except ImportError: - print("WiFi settings are kept in settings.py, please add them there!") + print("WiFi settings are kept in esp32spi_settings.py, please add them there!") raise # PyPortal ESP32 Setup diff --git a/examples/adafruit_io_simpletest_metadata.py b/examples/adafruit_io_simpletest_metadata.py index 5c03cbf..eb82f10 100644 --- a/examples/adafruit_io_simpletest_metadata.py +++ b/examples/adafruit_io_simpletest_metadata.py @@ -13,11 +13,11 @@ # Import Adafruit IO REST Client from Adafruit_IO import RESTClient, AdafruitIO_RequestError -# Get wifi details and more from a settings.py file +# Get wifi details and more from a esp32spi_settings.py file try: - from settings import settings + from esp32spi_settings import settings except ImportError: - print("WiFi settings are kept in settings.py, please add them there!") + print("WiFi settings are kept in esp32spi_settings.py, please add them there!") raise # PyPortal ESP32 Setup diff --git a/examples/adafruit_io_simpletest_temperature.py b/examples/adafruit_io_simpletest_temperature.py index 8a5dc08..3903ce8 100644 --- a/examples/adafruit_io_simpletest_temperature.py +++ b/examples/adafruit_io_simpletest_temperature.py @@ -21,11 +21,11 @@ # Import ADT7410 Library import adafruit_adt7410 -# Get wifi details and more from a settings.py file +# Get wifi details and more from a esp32spi_settings.py file try: - from settings import settings + from esp32spi_settings import settings except ImportError: - print("WiFi settings are kept in settings.py, please add them there!") + print("WiFi settings are kept in esp32spi_settings.py, please add them there!") raise # PyPortal ESP32 Setup From d73c29589ca3b2d42fd409e78b345c323e2a1c18 Mon Sep 17 00:00:00 2001 From: brentru Date: Thu, 21 Feb 2019 16:37:59 -0500 Subject: [PATCH 19/48] wifi_settings.py, agnostic of SPI or AT library --- examples/adafruit_io_simpletest_data.py | 10 +++++----- examples/adafruit_io_simpletest_digital_out.py | 6 +++--- examples/adafruit_io_simpletest_feeds.py | 6 +++--- examples/adafruit_io_simpletest_metadata.py | 6 +++--- examples/adafruit_io_simpletest_temperature.py | 6 +++--- 5 files changed, 17 insertions(+), 17 deletions(-) diff --git a/examples/adafruit_io_simpletest_data.py b/examples/adafruit_io_simpletest_data.py index c9717d4..5022955 100644 --- a/examples/adafruit_io_simpletest_data.py +++ b/examples/adafruit_io_simpletest_data.py @@ -13,11 +13,11 @@ # Import Adafruit IO REST Client from Adafruit_IO import RESTClient, AdafruitIO_RequestError -# Get wifi details and more from a esp32spi_settings.py file +# Get wifi details and more from a wifi_settings.py.py file try: - from esp32spi_settings import settings + from wifi_settings.py import settings except ImportError: - print("WiFi settings are kept in esp32spi_settings.py, please add them there!") + print("WiFi settings are kept in wifi_settings.py.py, please add them there!") raise # PyPortal ESP32 Setup @@ -32,8 +32,8 @@ # Set your Adafruit IO Username and Key in settings.py # (visit io.adafruit.com if you need to create an account, # or if you need your Adafruit IO key.) -ADAFRUIT_IO_USER = esp32spi_settings['adafruit_io_user'] -ADAFRUIT_IO_KEY = esp32spi_settings['adafruit_io_key'] +ADAFRUIT_IO_USER = settings['adafruit_io_user'] +ADAFRUIT_IO_KEY = settings['adafruit_io_key'] # Create an instance of the Adafruit IO REST client io = RESTClient(ADAFRUIT_IO_USER, ADAFRUIT_IO_KEY, wifi) diff --git a/examples/adafruit_io_simpletest_digital_out.py b/examples/adafruit_io_simpletest_digital_out.py index 131365e..d43a41a 100644 --- a/examples/adafruit_io_simpletest_digital_out.py +++ b/examples/adafruit_io_simpletest_digital_out.py @@ -14,11 +14,11 @@ # Import Adafruit IO REST Client from Adafruit_IO import RESTClient, AdafruitIO_RequestError -# Get wifi details and more from a esp32spi_settings.py file +# Get wifi details and more from a wifi_settings.py.py file try: - from esp32spi_settings import settings + from wifi_settings.py import settings except ImportError: - print("WiFi settings are kept in esp32spi_settings.py, please add them there!") + print("WiFi settings are kept in wifi_settings.py.py, please add them there!") raise # PyPortal ESP32 Setup diff --git a/examples/adafruit_io_simpletest_feeds.py b/examples/adafruit_io_simpletest_feeds.py index 0371ce8..f00da83 100644 --- a/examples/adafruit_io_simpletest_feeds.py +++ b/examples/adafruit_io_simpletest_feeds.py @@ -12,11 +12,11 @@ # Import Adafruit IO REST Client from Adafruit_IO import RESTClient -# Get wifi details and more from a esp32spi_settings.py file +# Get wifi details and more from a wifi_settings.py.py file try: - from esp32spi_settings import settings + from wifi_settings.py import settings except ImportError: - print("WiFi settings are kept in esp32spi_settings.py, please add them there!") + print("WiFi settings are kept in wifi_settings.py.py, please add them there!") raise # PyPortal ESP32 Setup diff --git a/examples/adafruit_io_simpletest_metadata.py b/examples/adafruit_io_simpletest_metadata.py index eb82f10..e7fa97d 100644 --- a/examples/adafruit_io_simpletest_metadata.py +++ b/examples/adafruit_io_simpletest_metadata.py @@ -13,11 +13,11 @@ # Import Adafruit IO REST Client from Adafruit_IO import RESTClient, AdafruitIO_RequestError -# Get wifi details and more from a esp32spi_settings.py file +# Get wifi details and more from a wifi_settings.py.py file try: - from esp32spi_settings import settings + from wifi_settings.py import settings except ImportError: - print("WiFi settings are kept in esp32spi_settings.py, please add them there!") + print("WiFi settings are kept in wifi_settings.py.py, please add them there!") raise # PyPortal ESP32 Setup diff --git a/examples/adafruit_io_simpletest_temperature.py b/examples/adafruit_io_simpletest_temperature.py index 3903ce8..e7eb66e 100644 --- a/examples/adafruit_io_simpletest_temperature.py +++ b/examples/adafruit_io_simpletest_temperature.py @@ -21,11 +21,11 @@ # Import ADT7410 Library import adafruit_adt7410 -# Get wifi details and more from a esp32spi_settings.py file +# Get wifi details and more from a wifi_settings.py.py file try: - from esp32spi_settings import settings + from wifi_settings.py import settings except ImportError: - print("WiFi settings are kept in esp32spi_settings.py, please add them there!") + print("WiFi settings are kept in wifi_settings.py.py, please add them there!") raise # PyPortal ESP32 Setup From 34d7c92653f2f4d764ac760d0623ade47ff537f6 Mon Sep 17 00:00:00 2001 From: brentru Date: Thu, 21 Feb 2019 16:47:53 -0500 Subject: [PATCH 20/48] remove gpio defs, not used in the examples --- examples/adafruit_io_simpletest_data.py | 1 - examples/adafruit_io_simpletest_digital_out.py | 1 - examples/adafruit_io_simpletest_feeds.py | 1 - examples/adafruit_io_simpletest_metadata.py | 1 - examples/adafruit_io_simpletest_temperature.py | 1 - 5 files changed, 5 deletions(-) diff --git a/examples/adafruit_io_simpletest_data.py b/examples/adafruit_io_simpletest_data.py index 5022955..38eb7e7 100644 --- a/examples/adafruit_io_simpletest_data.py +++ b/examples/adafruit_io_simpletest_data.py @@ -23,7 +23,6 @@ # PyPortal ESP32 Setup esp32_cs = DigitalInOut(microcontroller.pin.PB14) esp32_ready = DigitalInOut(microcontroller.pin.PB16) -esp32_gpio0 = DigitalInOut(microcontroller.pin.PB15) esp32_reset = DigitalInOut(microcontroller.pin.PB17) spi = busio.SPI(board.SCK, board.MOSI, board.MISO) esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset) diff --git a/examples/adafruit_io_simpletest_digital_out.py b/examples/adafruit_io_simpletest_digital_out.py index d43a41a..4ce3baf 100644 --- a/examples/adafruit_io_simpletest_digital_out.py +++ b/examples/adafruit_io_simpletest_digital_out.py @@ -24,7 +24,6 @@ # PyPortal ESP32 Setup esp32_cs = DigitalInOut(microcontroller.pin.PB14) esp32_ready = DigitalInOut(microcontroller.pin.PB16) -esp32_gpio0 = DigitalInOut(microcontroller.pin.PB15) esp32_reset = DigitalInOut(microcontroller.pin.PB17) spi = busio.SPI(board.SCK, board.MOSI, board.MISO) esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset) diff --git a/examples/adafruit_io_simpletest_feeds.py b/examples/adafruit_io_simpletest_feeds.py index f00da83..fd97109 100644 --- a/examples/adafruit_io_simpletest_feeds.py +++ b/examples/adafruit_io_simpletest_feeds.py @@ -22,7 +22,6 @@ # PyPortal ESP32 Setup esp32_cs = DigitalInOut(microcontroller.pin.PB14) esp32_ready = DigitalInOut(microcontroller.pin.PB16) -esp32_gpio0 = DigitalInOut(microcontroller.pin.PB15) esp32_reset = DigitalInOut(microcontroller.pin.PB17) spi = busio.SPI(board.SCK, board.MOSI, board.MISO) esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset) diff --git a/examples/adafruit_io_simpletest_metadata.py b/examples/adafruit_io_simpletest_metadata.py index e7fa97d..de059d3 100644 --- a/examples/adafruit_io_simpletest_metadata.py +++ b/examples/adafruit_io_simpletest_metadata.py @@ -23,7 +23,6 @@ # PyPortal ESP32 Setup esp32_cs = DigitalInOut(microcontroller.pin.PB14) esp32_ready = DigitalInOut(microcontroller.pin.PB16) -esp32_gpio0 = DigitalInOut(microcontroller.pin.PB15) esp32_reset = DigitalInOut(microcontroller.pin.PB17) spi = busio.SPI(board.SCK, board.MOSI, board.MISO) esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset) diff --git a/examples/adafruit_io_simpletest_temperature.py b/examples/adafruit_io_simpletest_temperature.py index e7eb66e..c9eb5bc 100644 --- a/examples/adafruit_io_simpletest_temperature.py +++ b/examples/adafruit_io_simpletest_temperature.py @@ -31,7 +31,6 @@ # PyPortal ESP32 Setup esp32_cs = DigitalInOut(microcontroller.pin.PB14) esp32_ready = DigitalInOut(microcontroller.pin.PB16) -esp32_gpio0 = DigitalInOut(microcontroller.pin.PB15) esp32_reset = DigitalInOut(microcontroller.pin.PB17) spi = busio.SPI(board.SCK, board.MOSI, board.MISO) esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset) From b4966c813d31e0e8e7c5b287e08726c40ca42d74 Mon Sep 17 00:00:00 2001 From: brentru Date: Thu, 21 Feb 2019 16:54:35 -0500 Subject: [PATCH 21/48] handle data without associated metadata in _create_data --- adafruit_io.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/adafruit_io.py b/adafruit_io.py index acb6df6..e5f716b 100644 --- a/adafruit_io.py +++ b/adafruit_io.py @@ -79,8 +79,10 @@ def __init__(self, adafruit_io_username, adafruit_io_key, wifi_manager): @staticmethod def _create_data(data, metadata): - return {'value':data, 'lat':metadata['lat'], 'lon':metadata['lon'], - 'ele':metadata['ele'], 'created_at':metadata['created_at']} + if metadata is not None: + return {'value':data, 'lat':metadata['lat'], 'lon':metadata['lon'], + 'ele':metadata['ele'], 'created_at':metadata['created_at']} + return {'value':data} @staticmethod def _handle_error(response): @@ -177,8 +179,7 @@ def create_new_group(self, group_key, group_description): :param str group_description: Brief summary about the group """ path = self._compose_path("groups") - payload = {'name':group_key, - 'description':group_description} + payload = {'name':group_key, 'description':group_description} return self._post(path, payload) def delete_group(self, group_key): From 1416ca30f1602ada4ccc1405cb67134ecedc4ef3 Mon Sep 17 00:00:00 2001 From: brentru Date: Thu, 21 Feb 2019 17:01:23 -0500 Subject: [PATCH 22/48] removing incorrect .py after settings --- examples/adafruit_io_simpletest_data.py | 2 +- examples/adafruit_io_simpletest_digital_out.py | 4 ++-- examples/adafruit_io_simpletest_feeds.py | 4 ++-- examples/adafruit_io_simpletest_metadata.py | 4 ++-- examples/adafruit_io_simpletest_temperature.py | 4 ++-- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/examples/adafruit_io_simpletest_data.py b/examples/adafruit_io_simpletest_data.py index 38eb7e7..89803ba 100644 --- a/examples/adafruit_io_simpletest_data.py +++ b/examples/adafruit_io_simpletest_data.py @@ -28,7 +28,7 @@ esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset) wifi = adafruit_esp32spi_wifimanager.ESPSPI_WiFiManager(esp, settings, board.NEOPIXEL) -# Set your Adafruit IO Username and Key in settings.py +# Set your Adafruit IO Username and Key in wifi_settings.py # (visit io.adafruit.com if you need to create an account, # or if you need your Adafruit IO key.) ADAFRUIT_IO_USER = settings['adafruit_io_user'] diff --git a/examples/adafruit_io_simpletest_digital_out.py b/examples/adafruit_io_simpletest_digital_out.py index 4ce3baf..df3b491 100644 --- a/examples/adafruit_io_simpletest_digital_out.py +++ b/examples/adafruit_io_simpletest_digital_out.py @@ -16,7 +16,7 @@ # Get wifi details and more from a wifi_settings.py.py file try: - from wifi_settings.py import settings + from wifi_settings import settings except ImportError: print("WiFi settings are kept in wifi_settings.py.py, please add them there!") raise @@ -29,7 +29,7 @@ esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset) wifi = adafruit_esp32spi_wifimanager.ESPSPI_WiFiManager(esp, settings, board.NEOPIXEL) -# Set your Adafruit IO Username and Key in settings.py +# Set your Adafruit IO Username and Key in wifi_settings.py # (visit io.adafruit.com if you need to create an account, # or if you need your Adafruit IO key.) ADAFRUIT_IO_USER = settings['adafruit_io_user'] diff --git a/examples/adafruit_io_simpletest_feeds.py b/examples/adafruit_io_simpletest_feeds.py index fd97109..84567d0 100644 --- a/examples/adafruit_io_simpletest_feeds.py +++ b/examples/adafruit_io_simpletest_feeds.py @@ -14,7 +14,7 @@ # Get wifi details and more from a wifi_settings.py.py file try: - from wifi_settings.py import settings + from wifi_settings import settings except ImportError: print("WiFi settings are kept in wifi_settings.py.py, please add them there!") raise @@ -27,7 +27,7 @@ esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset) wifi = adafruit_esp32spi_wifimanager.ESPSPI_WiFiManager(esp, settings, board.NEOPIXEL) -# Set your Adafruit IO Username and Key in settings.py +# Set your Adafruit IO Username and Key in wifi_settings.py # (visit io.adafruit.com if you need to create an account, # or if you need your Adafruit IO key.) ADAFRUIT_IO_USER = settings['adafruit_io_user'] diff --git a/examples/adafruit_io_simpletest_metadata.py b/examples/adafruit_io_simpletest_metadata.py index de059d3..1e1b888 100644 --- a/examples/adafruit_io_simpletest_metadata.py +++ b/examples/adafruit_io_simpletest_metadata.py @@ -15,7 +15,7 @@ # Get wifi details and more from a wifi_settings.py.py file try: - from wifi_settings.py import settings + from wifi_settings import settings except ImportError: print("WiFi settings are kept in wifi_settings.py.py, please add them there!") raise @@ -28,7 +28,7 @@ esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset) wifi = adafruit_esp32spi_wifimanager.ESPSPI_WiFiManager(esp, settings, board.NEOPIXEL) -# Set your Adafruit IO Username and Key in settings.py +# Set your Adafruit IO Username and Key in wifi_settings.py # (visit io.adafruit.com if you need to create an account, # or if you need your Adafruit IO key.) ADAFRUIT_IO_USER = settings['adafruit_io_user'] diff --git a/examples/adafruit_io_simpletest_temperature.py b/examples/adafruit_io_simpletest_temperature.py index c9eb5bc..99a9794 100644 --- a/examples/adafruit_io_simpletest_temperature.py +++ b/examples/adafruit_io_simpletest_temperature.py @@ -23,7 +23,7 @@ # Get wifi details and more from a wifi_settings.py.py file try: - from wifi_settings.py import settings + from wifi_settings import settings except ImportError: print("WiFi settings are kept in wifi_settings.py.py, please add them there!") raise @@ -36,7 +36,7 @@ esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset) wifi = adafruit_esp32spi_wifimanager.ESPSPI_WiFiManager(esp, settings, board.NEOPIXEL) -# Set your Adafruit IO Username and Key in settings.py +# Set your Adafruit IO Username and Key in wifi_settings.py # (visit io.adafruit.com if you need to create an account, # or if you need your Adafruit IO key.) ADAFRUIT_IO_USER = settings['adafruit_io_user'] From 91202c81caead6bcf46f3eb186b043f57d59c1df Mon Sep 17 00:00:00 2001 From: brentru Date: Thu, 21 Feb 2019 17:03:44 -0500 Subject: [PATCH 23/48] dont print feed until rx --- examples/adafruit_io_simpletest_data.py | 2 +- examples/adafruit_io_simpletest_feeds.py | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/examples/adafruit_io_simpletest_data.py b/examples/adafruit_io_simpletest_data.py index 89803ba..c0f1017 100644 --- a/examples/adafruit_io_simpletest_data.py +++ b/examples/adafruit_io_simpletest_data.py @@ -15,7 +15,7 @@ # Get wifi details and more from a wifi_settings.py.py file try: - from wifi_settings.py import settings + from wifi_settings import settings except ImportError: print("WiFi settings are kept in wifi_settings.py.py, please add them there!") raise diff --git a/examples/adafruit_io_simpletest_feeds.py b/examples/adafruit_io_simpletest_feeds.py index 84567d0..c1887c1 100644 --- a/examples/adafruit_io_simpletest_feeds.py +++ b/examples/adafruit_io_simpletest_feeds.py @@ -39,7 +39,6 @@ # Create a new 'circuitpython' feed with a description print('Creating new Adafruit IO feed...') feed = io.create_new_feed('circuitpython', 'a Adafruit IO CircuitPython feed') -print(feed) # List a specified feed print('Retrieving new Adafruit IO feed...') From fba0837ad4cda30249bf429ec2c49741da045d4b Mon Sep 17 00:00:00 2001 From: brentru Date: Thu, 21 Feb 2019 17:16:29 -0500 Subject: [PATCH 24/48] fix example for digitalio --- examples/adafruit_io_simpletest_digital_out.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/examples/adafruit_io_simpletest_digital_out.py b/examples/adafruit_io_simpletest_digital_out.py index df3b491..a3c1e8b 100644 --- a/examples/adafruit_io_simpletest_digital_out.py +++ b/examples/adafruit_io_simpletest_digital_out.py @@ -51,15 +51,16 @@ while True: # Get data from 'digital' feed + print('getting data from IO...') feed_data = io.receive_data(digital_feed['key']) # Check if data is ON or OFF - if int(feed_data['value'] == 1): + if int(feed_data['value']) == 1: print('received <- ON\n') - elif int(feed_data['value'] == 0): + elif int(feed_data['value']) == 0: print('received <= OFF\n') # Set the LED to the feed value LED.value = int(feed_data['value']) - time.sleep(0.5) + time.sleep(5) From e6119448e022a4ae67d9599690414684e3b7810e Mon Sep 17 00:00:00 2001 From: brentru Date: Thu, 21 Feb 2019 17:26:53 -0500 Subject: [PATCH 25/48] docs! --- docs/api.rst | 2 +- docs/conf.py | 7 ------- docs/examples.rst | 4 ++-- docs/index.rst | 5 ----- 4 files changed, 3 insertions(+), 15 deletions(-) diff --git a/docs/api.rst b/docs/api.rst index 5fa718a..61d9704 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -4,5 +4,5 @@ .. If your library file(s) are nested in a directory (e.g. /adafruit_foo/foo.py) .. use this format as the module name: "adafruit_foo.foo" -.. automodule:: adafruit_adafruit_io +.. automodule:: adafruit_adafruitio :members: diff --git a/docs/conf.py b/docs/conf.py index 65d9a24..e3d0d23 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -16,13 +16,6 @@ 'sphinx.ext.todo', ] -# TODO: Please Read! -# Uncomment the below if you use native CircuitPython modules such as -# digitalio, micropython and busio. List the modules you use. Without it, the -# autodoc module docs will fail to generate with a warning. -# autodoc_mock_imports = ["digitalio", "busio"] - - intersphinx_mapping = {'python': ('https://docs.python.org/3.4', None),'CircuitPython': ('https://circuitpython.readthedocs.io/en/latest/', None)} # Add any paths that contain templates here, relative to this directory. diff --git a/docs/examples.rst b/docs/examples.rst index 1f35d94..db69245 100644 --- a/docs/examples.rst +++ b/docs/examples.rst @@ -3,6 +3,6 @@ Simple test Ensure your device works with this simple test. -.. literalinclude:: ../examples/adafruit_io_simpletest.py - :caption: examples/adafruit_io_simpletest.py +.. literalinclude:: ../examples/adafruit_io_simpletest_data.py + :caption: examples/adafruit_io_simpletest_data.py :linenos: diff --git a/docs/index.rst b/docs/index.rst index 083e2d1..cac5a94 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -23,15 +23,10 @@ Table of Contents .. toctree:: :caption: Tutorials -.. todo:: Add any Learn guide links here. If there are none, then simply delete this todo and leave - the toctree above for use later. .. toctree:: :caption: Related Products -.. todo:: Add any product links here. If there are none, then simply delete this todo and leave - the toctree above for use later. - .. toctree:: :caption: Other Links From 3afc51d14acfe619d53bf56180ffb2068ad84e41 Mon Sep 17 00:00:00 2001 From: brentru Date: Thu, 21 Feb 2019 17:33:20 -0500 Subject: [PATCH 26/48] add non-pyportal esp32 spi pins as default --- examples/adafruit_io_simpletest_data.py | 10 ++++++++++ examples/adafruit_io_simpletest_digital_out.py | 10 ++++++++++ examples/adafruit_io_simpletest_feeds.py | 10 ++++++++++ examples/adafruit_io_simpletest_metadata.py | 10 ++++++++++ examples/adafruit_io_simpletest_temperature.py | 10 ++++++++++ 5 files changed, 50 insertions(+) diff --git a/examples/adafruit_io_simpletest_data.py b/examples/adafruit_io_simpletest_data.py index c0f1017..8674afb 100644 --- a/examples/adafruit_io_simpletest_data.py +++ b/examples/adafruit_io_simpletest_data.py @@ -20,6 +20,15 @@ print("WiFi settings are kept in wifi_settings.py.py, please add them there!") raise +# ESP32 Setup +esp32_cs = DigitalInOut(board.D9) +esp32_ready = DigitalInOut(board.D10) +esp32_reset = DigitalInOut(board.D5) +spi = busio.SPI(board.SCK, board.MOSI, board.MISO) +esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset) +wifi = adafruit_esp32spi_wifimanager.ESPSPI_WiFiManager(esp, settings, board.NEOPIXEL) + +""" # PyPortal ESP32 Setup esp32_cs = DigitalInOut(microcontroller.pin.PB14) esp32_ready = DigitalInOut(microcontroller.pin.PB16) @@ -27,6 +36,7 @@ spi = busio.SPI(board.SCK, board.MOSI, board.MISO) esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset) wifi = adafruit_esp32spi_wifimanager.ESPSPI_WiFiManager(esp, settings, board.NEOPIXEL) +""" # Set your Adafruit IO Username and Key in wifi_settings.py # (visit io.adafruit.com if you need to create an account, diff --git a/examples/adafruit_io_simpletest_digital_out.py b/examples/adafruit_io_simpletest_digital_out.py index a3c1e8b..8d377aa 100644 --- a/examples/adafruit_io_simpletest_digital_out.py +++ b/examples/adafruit_io_simpletest_digital_out.py @@ -21,6 +21,15 @@ print("WiFi settings are kept in wifi_settings.py.py, please add them there!") raise +# ESP32 Setup +esp32_cs = DigitalInOut(board.D9) +esp32_ready = DigitalInOut(board.D10) +esp32_reset = DigitalInOut(board.D5) +spi = busio.SPI(board.SCK, board.MOSI, board.MISO) +esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset) +wifi = adafruit_esp32spi_wifimanager.ESPSPI_WiFiManager(esp, settings, board.NEOPIXEL) + +""" # PyPortal ESP32 Setup esp32_cs = DigitalInOut(microcontroller.pin.PB14) esp32_ready = DigitalInOut(microcontroller.pin.PB16) @@ -28,6 +37,7 @@ spi = busio.SPI(board.SCK, board.MOSI, board.MISO) esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset) wifi = adafruit_esp32spi_wifimanager.ESPSPI_WiFiManager(esp, settings, board.NEOPIXEL) +""" # Set your Adafruit IO Username and Key in wifi_settings.py # (visit io.adafruit.com if you need to create an account, diff --git a/examples/adafruit_io_simpletest_feeds.py b/examples/adafruit_io_simpletest_feeds.py index c1887c1..2e78b85 100644 --- a/examples/adafruit_io_simpletest_feeds.py +++ b/examples/adafruit_io_simpletest_feeds.py @@ -19,6 +19,15 @@ print("WiFi settings are kept in wifi_settings.py.py, please add them there!") raise +# ESP32 Setup +esp32_cs = DigitalInOut(board.D9) +esp32_ready = DigitalInOut(board.D10) +esp32_reset = DigitalInOut(board.D5) +spi = busio.SPI(board.SCK, board.MOSI, board.MISO) +esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset) +wifi = adafruit_esp32spi_wifimanager.ESPSPI_WiFiManager(esp, settings, board.NEOPIXEL) + +""" # PyPortal ESP32 Setup esp32_cs = DigitalInOut(microcontroller.pin.PB14) esp32_ready = DigitalInOut(microcontroller.pin.PB16) @@ -26,6 +35,7 @@ spi = busio.SPI(board.SCK, board.MOSI, board.MISO) esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset) wifi = adafruit_esp32spi_wifimanager.ESPSPI_WiFiManager(esp, settings, board.NEOPIXEL) +""" # Set your Adafruit IO Username and Key in wifi_settings.py # (visit io.adafruit.com if you need to create an account, diff --git a/examples/adafruit_io_simpletest_metadata.py b/examples/adafruit_io_simpletest_metadata.py index 1e1b888..444975b 100644 --- a/examples/adafruit_io_simpletest_metadata.py +++ b/examples/adafruit_io_simpletest_metadata.py @@ -20,6 +20,15 @@ print("WiFi settings are kept in wifi_settings.py.py, please add them there!") raise +# ESP32 Setup +esp32_cs = DigitalInOut(board.D9) +esp32_ready = DigitalInOut(board.D10) +esp32_reset = DigitalInOut(board.D5) +spi = busio.SPI(board.SCK, board.MOSI, board.MISO) +esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset) +wifi = adafruit_esp32spi_wifimanager.ESPSPI_WiFiManager(esp, settings, board.NEOPIXEL) + +""" # PyPortal ESP32 Setup esp32_cs = DigitalInOut(microcontroller.pin.PB14) esp32_ready = DigitalInOut(microcontroller.pin.PB16) @@ -27,6 +36,7 @@ spi = busio.SPI(board.SCK, board.MOSI, board.MISO) esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset) wifi = adafruit_esp32spi_wifimanager.ESPSPI_WiFiManager(esp, settings, board.NEOPIXEL) +""" # Set your Adafruit IO Username and Key in wifi_settings.py # (visit io.adafruit.com if you need to create an account, diff --git a/examples/adafruit_io_simpletest_temperature.py b/examples/adafruit_io_simpletest_temperature.py index 99a9794..299a5a3 100644 --- a/examples/adafruit_io_simpletest_temperature.py +++ b/examples/adafruit_io_simpletest_temperature.py @@ -28,6 +28,15 @@ print("WiFi settings are kept in wifi_settings.py.py, please add them there!") raise +# ESP32 Setup +esp32_cs = DigitalInOut(board.D9) +esp32_ready = DigitalInOut(board.D10) +esp32_reset = DigitalInOut(board.D5) +spi = busio.SPI(board.SCK, board.MOSI, board.MISO) +esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset) +wifi = adafruit_esp32spi_wifimanager.ESPSPI_WiFiManager(esp, settings, board.NEOPIXEL) + +""" # PyPortal ESP32 Setup esp32_cs = DigitalInOut(microcontroller.pin.PB14) esp32_ready = DigitalInOut(microcontroller.pin.PB16) @@ -35,6 +44,7 @@ spi = busio.SPI(board.SCK, board.MOSI, board.MISO) esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset) wifi = adafruit_esp32spi_wifimanager.ESPSPI_WiFiManager(esp, settings, board.NEOPIXEL) +""" # Set your Adafruit IO Username and Key in wifi_settings.py # (visit io.adafruit.com if you need to create an account, From 7bff616e4164686df83f4efce57ec94b8faa6d4f Mon Sep 17 00:00:00 2001 From: brentru Date: Thu, 21 Feb 2019 17:38:19 -0500 Subject: [PATCH 27/48] remove unused microcontroller import, move to pyportal setup comment --- examples/adafruit_io_simpletest_data.py | 2 +- examples/adafruit_io_simpletest_digital_out.py | 2 +- examples/adafruit_io_simpletest_feeds.py | 2 +- examples/adafruit_io_simpletest_metadata.py | 2 +- examples/adafruit_io_simpletest_temperature.py | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/adafruit_io_simpletest_data.py b/examples/adafruit_io_simpletest_data.py index 8674afb..8b1e508 100644 --- a/examples/adafruit_io_simpletest_data.py +++ b/examples/adafruit_io_simpletest_data.py @@ -7,7 +7,6 @@ from digitalio import DigitalInOut # ESP32 SPI -import microcontroller from adafruit_esp32spi import adafruit_esp32spi, adafruit_esp32spi_wifimanager # Import Adafruit IO REST Client @@ -30,6 +29,7 @@ """ # PyPortal ESP32 Setup +import microcontroller esp32_cs = DigitalInOut(microcontroller.pin.PB14) esp32_ready = DigitalInOut(microcontroller.pin.PB16) esp32_reset = DigitalInOut(microcontroller.pin.PB17) diff --git a/examples/adafruit_io_simpletest_digital_out.py b/examples/adafruit_io_simpletest_digital_out.py index 8d377aa..d7e0967 100644 --- a/examples/adafruit_io_simpletest_digital_out.py +++ b/examples/adafruit_io_simpletest_digital_out.py @@ -4,7 +4,6 @@ """ import time import board -import microcontroller import busio from digitalio import DigitalInOut, Direction @@ -31,6 +30,7 @@ """ # PyPortal ESP32 Setup +import microcontroller esp32_cs = DigitalInOut(microcontroller.pin.PB14) esp32_ready = DigitalInOut(microcontroller.pin.PB16) esp32_reset = DigitalInOut(microcontroller.pin.PB17) diff --git a/examples/adafruit_io_simpletest_feeds.py b/examples/adafruit_io_simpletest_feeds.py index 2e78b85..16e4ff7 100644 --- a/examples/adafruit_io_simpletest_feeds.py +++ b/examples/adafruit_io_simpletest_feeds.py @@ -6,7 +6,6 @@ from digitalio import DigitalInOut # ESP32 SPI -import microcontroller from adafruit_esp32spi import adafruit_esp32spi, adafruit_esp32spi_wifimanager # Import Adafruit IO REST Client @@ -29,6 +28,7 @@ """ # PyPortal ESP32 Setup +import microcontroller esp32_cs = DigitalInOut(microcontroller.pin.PB14) esp32_ready = DigitalInOut(microcontroller.pin.PB16) esp32_reset = DigitalInOut(microcontroller.pin.PB17) diff --git a/examples/adafruit_io_simpletest_metadata.py b/examples/adafruit_io_simpletest_metadata.py index 444975b..a1ff570 100644 --- a/examples/adafruit_io_simpletest_metadata.py +++ b/examples/adafruit_io_simpletest_metadata.py @@ -7,7 +7,6 @@ from digitalio import DigitalInOut # ESP32 SPI -import microcontroller from adafruit_esp32spi import adafruit_esp32spi, adafruit_esp32spi_wifimanager # Import Adafruit IO REST Client @@ -30,6 +29,7 @@ """ # PyPortal ESP32 Setup +import microcontroller esp32_cs = DigitalInOut(microcontroller.pin.PB14) esp32_ready = DigitalInOut(microcontroller.pin.PB16) esp32_reset = DigitalInOut(microcontroller.pin.PB17) diff --git a/examples/adafruit_io_simpletest_temperature.py b/examples/adafruit_io_simpletest_temperature.py index 299a5a3..734af95 100644 --- a/examples/adafruit_io_simpletest_temperature.py +++ b/examples/adafruit_io_simpletest_temperature.py @@ -8,7 +8,6 @@ """ import time import board -import microcontroller import busio from digitalio import DigitalInOut @@ -38,6 +37,7 @@ """ # PyPortal ESP32 Setup +import microcontroller esp32_cs = DigitalInOut(microcontroller.pin.PB14) esp32_ready = DigitalInOut(microcontroller.pin.PB16) esp32_reset = DigitalInOut(microcontroller.pin.PB17) From a212cc69a1aa7ffd99d56c2ac3c109b2a53c12b4 Mon Sep 17 00:00:00 2001 From: brentru Date: Thu, 21 Feb 2019 17:40:37 -0500 Subject: [PATCH 28/48] fix travis sphinx --- docs/api.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/api.rst b/docs/api.rst index 61d9704..219297b 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -4,5 +4,5 @@ .. If your library file(s) are nested in a directory (e.g. /adafruit_foo/foo.py) .. use this format as the module name: "adafruit_foo.foo" -.. automodule:: adafruit_adafruitio +.. automodule:: adafruit_io :members: From f5e76095edca60f892262001612d204884297aeb Mon Sep 17 00:00:00 2001 From: brentru Date: Thu, 21 Feb 2019 17:43:15 -0500 Subject: [PATCH 29/48] fix readme for sphinx --- README.rst | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/README.rst b/README.rst index f1b1fd2..92f12bc 100644 --- a/README.rst +++ b/README.rst @@ -32,25 +32,23 @@ Usage Example Create an Adafruit IO Client object .. code-block:: python - io = RESTClient(ADAFRUIT_IO_USER, ADAFRUIT_IO_KEY, wifi) +io = RESTClient(ADAFRUIT_IO_USER, ADAFRUIT_IO_KEY, wifi) -Sending `data` to an Adafruit IO feed +Sending data to an Adafruit IO feed .. code-block:: python - io.send_data(feed, data) +io.send_data(feed, data) -Receiving `data` from an Adafruit IO feed +Receiving data from an Adafruit IO feed .. code-block:: python - data = io.receive_data(feed) +data = io.receive_data(feed) -Creating a new feed named `circuitpython` with a description +Creating a new feed named circuitpython with a description .. code-block:: python - feed = io.create_new_feed('circuitpython', 'an Adafruit IO CircuitPython feed') +feed = io.create_new_feed('circuitpython', 'an Adafruit IO CircuitPython feed') Listing the record of a specified feed: .. code-block:: python - feed = io.get_feed('circuitpython') - -More usage examples are included in the `examples folder of this repository<`_ +feed = io.get_feed('circuitpython') Contributing ============ From 41a074c23a8f47fb2bf7d16bb23eaf4d70eb40a3 Mon Sep 17 00:00:00 2001 From: brentru Date: Thu, 21 Feb 2019 17:48:35 -0500 Subject: [PATCH 30/48] pylint the right file --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index bb2998d..9f4601c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -42,7 +42,7 @@ install: - pip install --force-reinstall pylint==1.9.2 script: - - pylint adafruit_adafruit_io.py + - pylint adafruit_io.py - ([[ ! -d "examples" ]] || pylint --disable=missing-docstring,invalid-name,bad-whitespace examples/*.py) - circuitpython-build-bundles --filename_prefix adafruit-circuitpython-adafruit_io --library_location . - cd docs && sphinx-build -E -W -b html . _build/html && cd .. From fa98981b120dfc42b0fe4e982c060c3ab33adc5b Mon Sep 17 00:00:00 2001 From: brentru Date: Fri, 22 Feb 2019 10:43:08 -0500 Subject: [PATCH 31/48] add Adafruit IO Connected Service: Weather --- adafruit_io.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/adafruit_io.py b/adafruit_io.py index e5f716b..d4aaf69 100644 --- a/adafruit_io.py +++ b/adafruit_io.py @@ -231,3 +231,13 @@ def delete_feed(self, feed_key): """ path = self._compose_path("feeds/{0}".format(feed_key)) return self._delete(path) + + # Adafruit IO Connected Services + def receive_weather(self, weather_id): + """ + Adafruit IO Weather Forecast Service + NOTE: This service is avaliable to Adafruit IO Plus subscribers only. + :param int weather_id: ID for retrieving a specified weather record. + """ + path = self._compose_path("integrations/weather/{0}".format(weather_id)) + return self._get(path) From 3ced1e38ceba70272920cba0bd4fb247a0150ddd Mon Sep 17 00:00:00 2001 From: brentru Date: Fri, 22 Feb 2019 10:48:43 -0500 Subject: [PATCH 32/48] Add Adafruit IO Connected Service: Random Data --- adafruit_io.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/adafruit_io.py b/adafruit_io.py index d4aaf69..0a8d6a2 100644 --- a/adafruit_io.py +++ b/adafruit_io.py @@ -235,9 +235,18 @@ def delete_feed(self, feed_key): # Adafruit IO Connected Services def receive_weather(self, weather_id): """ - Adafruit IO Weather Forecast Service + Get data from the Adafruit IO Weather Forecast Service NOTE: This service is avaliable to Adafruit IO Plus subscribers only. :param int weather_id: ID for retrieving a specified weather record. """ path = self._compose_path("integrations/weather/{0}".format(weather_id)) return self._get(path) + + def receive_random_data(self, generator_id): + """ + Get data from the Adafruit IO Random Data Stream Service + :param int generator_id: Specified randomizer record + """ + path = self._compose_path("integrations/words/{0}".format(generator_id)) + return self._get(path) + \ No newline at end of file From 119c818c1108123d674501d5906ecb6f454b61ef Mon Sep 17 00:00:00 2001 From: brentru Date: Fri, 22 Feb 2019 11:37:32 -0500 Subject: [PATCH 33/48] add example for accessing weather service --- examples/adafruit_io_simpletest_weather.py | 70 ++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 examples/adafruit_io_simpletest_weather.py diff --git a/examples/adafruit_io_simpletest_weather.py b/examples/adafruit_io_simpletest_weather.py new file mode 100644 index 0000000..4d3c6b6 --- /dev/null +++ b/examples/adafruit_io_simpletest_weather.py @@ -0,0 +1,70 @@ +""" +Example of getting weather +from the Adafruit IO Weather Service +NOTE: This example is for Adafruit IO +Plus subscribers only. +""" +import board +import busio +from digitalio import DigitalInOut + +# ESP32 SPI +from adafruit_esp32spi import adafruit_esp32spi, adafruit_esp32spi_wifimanager + +# Import Adafruit IO REST Client +from Adafruit_IO import RESTClient + +# Get wifi details and more from a wifi_settings.py.py file +try: + from wifi_settings import settings +except ImportError: + print("WiFi settings are kept in wifi_settings.py.py, please add them there!") + raise + + +# ESP32 Setup +esp32_cs = DigitalInOut(board.D9) +esp32_ready = DigitalInOut(board.D10) +esp32_reset = DigitalInOut(board.D5) +spi = busio.SPI(board.SCK, board.MOSI, board.MISO) +esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset) +wifi = adafruit_esp32spi_wifimanager.ESPSPI_WiFiManager(esp, settings, board.NEOPIXEL) + +""" +# PyPortal ESP32 Setup +import microcontroller +esp32_cs = DigitalInOut(microcontroller.pin.PB14) +esp32_ready = DigitalInOut(microcontroller.pin.PB16) +esp32_reset = DigitalInOut(microcontroller.pin.PB17) +spi = busio.SPI(board.SCK, board.MOSI, board.MISO) +esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset) +wifi = adafruit_esp32spi_wifimanager.ESPSPI_WiFiManager(esp, settings, board.NEOPIXEL) +""" + +# Set your Adafruit IO Username and Key in wifi_settings.py +# (visit io.adafruit.com if you need to create an account, +# or if you need your Adafruit IO key.) +ADAFRUIT_IO_USER = settings['adafruit_io_user'] +ADAFRUIT_IO_KEY = settings['adafruit_io_key'] + +# Create an instance of the Adafruit IO REST client +io = RESTClient(ADAFRUIT_IO_USER, ADAFRUIT_IO_KEY, wifi) + +# Weather Location ID +location_id = 2127 + +print('Getting weather record from IO...') +# Get the specified weather record with current weather +# and all available forecast information. +forecast = io.receive_weather(location_id) + +# Get today's forecast +current_forecast = forecast['current'] +print('It is {0} and {1}*F.'.format(current_forecast['summary'], current_forecast['temperature'])) +print('with a humidity of {0}%'.format(current_forecast['humidity'])) + +# Get tomorrow's forecast +tom_forecast = forecast['forecast_days_1'] +print('\nTomorrow has a low of {0}*F and a high of {1}*F.'.format( + tom_forecast['temperatureLow'], tom_forecast['temperatureHigh'])) +print('with a humidity of {0}%'.format(tom_forecast['humidity'])) From c197393f8e919bcf627f39869463db8b4da01e18 Mon Sep 17 00:00:00 2001 From: brentru Date: Fri, 22 Feb 2019 11:55:11 -0500 Subject: [PATCH 34/48] add Adafruit IO Connected Service: Time --- adafruit_io.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/adafruit_io.py b/adafruit_io.py index 0a8d6a2..acdd864 100644 --- a/adafruit_io.py +++ b/adafruit_io.py @@ -249,4 +249,11 @@ def receive_random_data(self, generator_id): """ path = self._compose_path("integrations/words/{0}".format(generator_id)) return self._get(path) - \ No newline at end of file + + def receive_time(self, time_type): + """ + Returns the current time from the Adafruit IO Server + :param string time_type: Type of time to be returned: `millis`, `seconds`, `ISO-8601` + """ + path = 'https://io.adafruit.com/api/v2/time/{0}'.format(time_type) + return self._get(path) From 2754bd0a09d7872b08b0ac2100dd82cfd5145f0d Mon Sep 17 00:00:00 2001 From: brentru Date: Fri, 22 Feb 2019 12:06:45 -0500 Subject: [PATCH 35/48] add example for fetching random data from the randomizer service --- examples/adafruit_io_simpletest_randomizer.py | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 examples/adafruit_io_simpletest_randomizer.py diff --git a/examples/adafruit_io_simpletest_randomizer.py b/examples/adafruit_io_simpletest_randomizer.py new file mode 100644 index 0000000..b5685db --- /dev/null +++ b/examples/adafruit_io_simpletest_randomizer.py @@ -0,0 +1,60 @@ +""" +Example of using Adafruit IO's +random data service. +""" +import time +import board +import busio +from digitalio import DigitalInOut + +# ESP32 SPI +from adafruit_esp32spi import adafruit_esp32spi, adafruit_esp32spi_wifimanager + +# Import Adafruit IO REST Client +from Adafruit_IO import RESTClient + +# Get wifi details and more from a wifi_settings.py.py file +try: + from wifi_settings import settings +except ImportError: + print("WiFi settings are kept in wifi_settings.py.py, please add them there!") + raise + +# ESP32 Setup +esp32_cs = DigitalInOut(board.D9) +esp32_ready = DigitalInOut(board.D10) +esp32_reset = DigitalInOut(board.D5) +spi = busio.SPI(board.SCK, board.MOSI, board.MISO) +esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset) +wifi = adafruit_esp32spi_wifimanager.ESPSPI_WiFiManager(esp, settings, board.NEOPIXEL) + +""" +# PyPortal ESP32 Setup +import microcontroller +esp32_cs = DigitalInOut(microcontroller.pin.PB14) +esp32_ready = DigitalInOut(microcontroller.pin.PB16) +esp32_reset = DigitalInOut(microcontroller.pin.PB17) +spi = busio.SPI(board.SCK, board.MOSI, board.MISO) +esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset) +wifi = adafruit_esp32spi_wifimanager.ESPSPI_WiFiManager(esp, settings, board.NEOPIXEL) +""" + +# Set your Adafruit IO Username and Key in wifi_settings.py +# (visit io.adafruit.com if you need to create an account, +# or if you need your Adafruit IO key.) +ADAFRUIT_IO_USER = settings['adafruit_io_user'] +ADAFRUIT_IO_KEY = settings['adafruit_io_key'] + +# Create an instance of the Adafruit IO REST client +io = RESTClient(ADAFRUIT_IO_USER, ADAFRUIT_IO_KEY, wifi) + +# Random Data ID +random_data_id = 1234 + +while True: + print('Fetching random data from Adafruit IO...') + random_data = io.receive_random_data(random_data_id) + print('Random Data: ', random_data['value']) + print('Data Seed: ', random_data['seed']) + print('Waiting 1 minute to fetch new randomized data...') + time.sleep(60) From 349234d33f89d72af49b9db81e9801386a087e37 Mon Sep 17 00:00:00 2001 From: brentru Date: Fri, 22 Feb 2019 12:08:28 -0500 Subject: [PATCH 36/48] make sphinx happy with docstring fix --- adafruit_io.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/adafruit_io.py b/adafruit_io.py index acdd864..a5b433d 100644 --- a/adafruit_io.py +++ b/adafruit_io.py @@ -253,7 +253,7 @@ def receive_random_data(self, generator_id): def receive_time(self, time_type): """ Returns the current time from the Adafruit IO Server - :param string time_type: Type of time to be returned: `millis`, `seconds`, `ISO-8601` + :param string time_type: Type of time to be returned: millis, seconds, or ISO-8601 """ path = 'https://io.adafruit.com/api/v2/time/{0}'.format(time_type) return self._get(path) From 8ce7fa4bea4a23ce886cafb1dec16a3047f580d6 Mon Sep 17 00:00:00 2001 From: brentru Date: Fri, 22 Feb 2019 13:07:40 -0500 Subject: [PATCH 37/48] import error handling within adafruit_io.py --- adafruit_io.py => adafruit_io/adafruit_io.py | 17 +------- adafruit_io/adafruit_io_errors.py | 41 ++++++++++++++++++++ 2 files changed, 43 insertions(+), 15 deletions(-) rename adafruit_io.py => adafruit_io/adafruit_io.py (92%) mode change 100644 => 100755 create mode 100755 adafruit_io/adafruit_io_errors.py diff --git a/adafruit_io.py b/adafruit_io/adafruit_io.py old mode 100644 new mode 100755 similarity index 92% rename from adafruit_io.py rename to adafruit_io/adafruit_io.py index a5b433d..53f9c7d --- a/adafruit_io.py +++ b/adafruit_io/adafruit_io.py @@ -38,24 +38,11 @@ * Adafruit's ESP32SPI library: https://github.com/adafruit/Adafruit_CircuitPython_ESP32SPI """ +from adafruit_io.adafruit_io_errors import AdafruitIO_RequestError, AdafruitIO_ThrottleError __version__ = "0.0.0-auto.0" __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_Adafruit_IO.git" -class AdafruitIO_ThrottleError(Exception): - """Adafruit IO request error class for rate-limiting""" - def __init__(self): - super(AdafruitIO_ThrottleError, self).__init__("Number of Adafruit IO Requests exceeded! \ - Please try again in 30 seconds..") - -class AdafruitIO_RequestError(Exception): - """Adafruit IO request error class""" - def __init__(self, response): - response_content = response.json() - error = response_content['error'] - super(AdafruitIO_RequestError, self).__init__("Adafruit IO Error {0}: {1}" - .format(response.status_code, error)) - class RESTClient(): """ REST Client for interacting with the Adafruit IO API. @@ -91,7 +78,7 @@ def _handle_error(response): elif response.status_code == 400: raise AdafruitIO_RequestError(response) elif response.status_code >= 400: - raise AdafruitIO_RequestError(response) + raise adafruit_io.adafruit_io_errors.AdafruitIO_RequestError(response) def _compose_path(self, path): return "{0}/{1}/{2}/{3}".format('https://io.adafruit.com/api', 'v2', self.username, path) diff --git a/adafruit_io/adafruit_io_errors.py b/adafruit_io/adafruit_io_errors.py new file mode 100755 index 0000000..9e9ecea --- /dev/null +++ b/adafruit_io/adafruit_io_errors.py @@ -0,0 +1,41 @@ +# The MIT License (MIT) +# +# Copyright (c) 2019 Brent Rubell for Adafruit +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +""" +`adafruit_io_errors.py` +====================================================== +CircuitPython Adafruit IO Error Classes +* Author(s): Brent Rubell +""" + +class AdafruitIO_ThrottleError(Exception): + """Adafruit IO request error class for rate-limiting""" + def __init__(self): + super(AdafruitIO_ThrottleError, self).__init__("Number of Adafruit IO Requests exceeded! \ + Please try again in 30 seconds..") + +class AdafruitIO_RequestError(Exception): + """Adafruit IO request error class""" + def __init__(self, response): + response_content = response.json() + error = response_content['error'] + super(AdafruitIO_RequestError, self).__init__("Adafruit IO Error {0}: {1}" + .format(response.status_code, error)) From f274d1ca859971872245a4f0e413a9d96b82b75b Mon Sep 17 00:00:00 2001 From: brentru Date: Fri, 22 Feb 2019 13:08:25 -0500 Subject: [PATCH 38/48] add empty __init__.py for pylint --- adafruit_io/__init__.py | 1 + 1 file changed, 1 insertion(+) create mode 100644 adafruit_io/__init__.py diff --git a/adafruit_io/__init__.py b/adafruit_io/__init__.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/adafruit_io/__init__.py @@ -0,0 +1 @@ + From b88e8853463328334cceaf06e8ab0016b88a3446 Mon Sep 17 00:00:00 2001 From: brentru Date: Fri, 22 Feb 2019 13:37:10 -0500 Subject: [PATCH 39/48] update examples for new file structure --- adafruit_io/__init__.py | 1 - adafruit_io/adafruit_io.py | 2 +- examples/adafruit_io_simpletest_data.py | 2 +- examples/adafruit_io_simpletest_digital_out.py | 2 +- examples/adafruit_io_simpletest_feeds.py | 2 +- examples/adafruit_io_simpletest_metadata.py | 2 +- examples/adafruit_io_simpletest_randomizer.py | 2 +- examples/adafruit_io_simpletest_temperature.py | 2 +- examples/adafruit_io_simpletest_weather.py | 2 +- 9 files changed, 8 insertions(+), 9 deletions(-) diff --git a/adafruit_io/__init__.py b/adafruit_io/__init__.py index 8b13789..e69de29 100644 --- a/adafruit_io/__init__.py +++ b/adafruit_io/__init__.py @@ -1 +0,0 @@ - diff --git a/adafruit_io/adafruit_io.py b/adafruit_io/adafruit_io.py index 53f9c7d..56e70f5 100755 --- a/adafruit_io/adafruit_io.py +++ b/adafruit_io/adafruit_io.py @@ -78,7 +78,7 @@ def _handle_error(response): elif response.status_code == 400: raise AdafruitIO_RequestError(response) elif response.status_code >= 400: - raise adafruit_io.adafruit_io_errors.AdafruitIO_RequestError(response) + raise AdafruitIO_RequestError(response) def _compose_path(self, path): return "{0}/{1}/{2}/{3}".format('https://io.adafruit.com/api', 'v2', self.username, path) diff --git a/examples/adafruit_io_simpletest_data.py b/examples/adafruit_io_simpletest_data.py index 8b1e508..a8b437f 100644 --- a/examples/adafruit_io_simpletest_data.py +++ b/examples/adafruit_io_simpletest_data.py @@ -10,7 +10,7 @@ from adafruit_esp32spi import adafruit_esp32spi, adafruit_esp32spi_wifimanager # Import Adafruit IO REST Client -from Adafruit_IO import RESTClient, AdafruitIO_RequestError +from adafruit_io.adafruit_io import RESTClient # Get wifi details and more from a wifi_settings.py.py file try: diff --git a/examples/adafruit_io_simpletest_digital_out.py b/examples/adafruit_io_simpletest_digital_out.py index d7e0967..8549129 100644 --- a/examples/adafruit_io_simpletest_digital_out.py +++ b/examples/adafruit_io_simpletest_digital_out.py @@ -11,7 +11,7 @@ from adafruit_esp32spi import adafruit_esp32spi, adafruit_esp32spi_wifimanager # Import Adafruit IO REST Client -from Adafruit_IO import RESTClient, AdafruitIO_RequestError +from adafruit_io.adafruit_io import RESTClient # Get wifi details and more from a wifi_settings.py.py file try: diff --git a/examples/adafruit_io_simpletest_feeds.py b/examples/adafruit_io_simpletest_feeds.py index 16e4ff7..1f997f7 100644 --- a/examples/adafruit_io_simpletest_feeds.py +++ b/examples/adafruit_io_simpletest_feeds.py @@ -9,7 +9,7 @@ from adafruit_esp32spi import adafruit_esp32spi, adafruit_esp32spi_wifimanager # Import Adafruit IO REST Client -from Adafruit_IO import RESTClient +from adafruit_io.adafruit_io import RESTClient # Get wifi details and more from a wifi_settings.py.py file try: diff --git a/examples/adafruit_io_simpletest_metadata.py b/examples/adafruit_io_simpletest_metadata.py index a1ff570..c62d46f 100644 --- a/examples/adafruit_io_simpletest_metadata.py +++ b/examples/adafruit_io_simpletest_metadata.py @@ -10,7 +10,7 @@ from adafruit_esp32spi import adafruit_esp32spi, adafruit_esp32spi_wifimanager # Import Adafruit IO REST Client -from Adafruit_IO import RESTClient, AdafruitIO_RequestError +from adafruit_io.adafruit_io import RESTClient # Get wifi details and more from a wifi_settings.py.py file try: diff --git a/examples/adafruit_io_simpletest_randomizer.py b/examples/adafruit_io_simpletest_randomizer.py index b5685db..8045107 100644 --- a/examples/adafruit_io_simpletest_randomizer.py +++ b/examples/adafruit_io_simpletest_randomizer.py @@ -11,7 +11,7 @@ from adafruit_esp32spi import adafruit_esp32spi, adafruit_esp32spi_wifimanager # Import Adafruit IO REST Client -from Adafruit_IO import RESTClient +from adafruit_io.adafruit_io import RESTClient # Get wifi details and more from a wifi_settings.py.py file try: diff --git a/examples/adafruit_io_simpletest_temperature.py b/examples/adafruit_io_simpletest_temperature.py index 734af95..c1ab867 100644 --- a/examples/adafruit_io_simpletest_temperature.py +++ b/examples/adafruit_io_simpletest_temperature.py @@ -15,7 +15,7 @@ from adafruit_esp32spi import adafruit_esp32spi, adafruit_esp32spi_wifimanager # Import Adafruit IO REST Client -from Adafruit_IO import RESTClient, AdafruitIO_RequestError +from adafruit_io.adafruit_io import RESTClient # Import ADT7410 Library import adafruit_adt7410 diff --git a/examples/adafruit_io_simpletest_weather.py b/examples/adafruit_io_simpletest_weather.py index 4d3c6b6..6db1905 100644 --- a/examples/adafruit_io_simpletest_weather.py +++ b/examples/adafruit_io_simpletest_weather.py @@ -12,7 +12,7 @@ from adafruit_esp32spi import adafruit_esp32spi, adafruit_esp32spi_wifimanager # Import Adafruit IO REST Client -from Adafruit_IO import RESTClient +from adafruit_io.adafruit_io import RESTClient # Get wifi details and more from a wifi_settings.py.py file try: From 71506d5bfdf2df88231f18fc69c21b80f77dcfec Mon Sep 17 00:00:00 2001 From: brentru Date: Fri, 22 Feb 2019 13:51:32 -0500 Subject: [PATCH 40/48] import requesterror for handling undef'd feed creation --- examples/adafruit_io_simpletest_data.py | 2 +- examples/adafruit_io_simpletest_digital_out.py | 2 +- examples/adafruit_io_simpletest_metadata.py | 2 +- examples/adafruit_io_simpletest_temperature.py | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/adafruit_io_simpletest_data.py b/examples/adafruit_io_simpletest_data.py index a8b437f..bb84cc0 100644 --- a/examples/adafruit_io_simpletest_data.py +++ b/examples/adafruit_io_simpletest_data.py @@ -10,7 +10,7 @@ from adafruit_esp32spi import adafruit_esp32spi, adafruit_esp32spi_wifimanager # Import Adafruit IO REST Client -from adafruit_io.adafruit_io import RESTClient +from adafruit_io.adafruit_io import RESTClient, AdafruitIO_RequestError # Get wifi details and more from a wifi_settings.py.py file try: diff --git a/examples/adafruit_io_simpletest_digital_out.py b/examples/adafruit_io_simpletest_digital_out.py index 8549129..8e0350c 100644 --- a/examples/adafruit_io_simpletest_digital_out.py +++ b/examples/adafruit_io_simpletest_digital_out.py @@ -11,7 +11,7 @@ from adafruit_esp32spi import adafruit_esp32spi, adafruit_esp32spi_wifimanager # Import Adafruit IO REST Client -from adafruit_io.adafruit_io import RESTClient +from adafruit_io.adafruit_io import RESTClient, AdafruitIO_RequestError # Get wifi details and more from a wifi_settings.py.py file try: diff --git a/examples/adafruit_io_simpletest_metadata.py b/examples/adafruit_io_simpletest_metadata.py index c62d46f..746684a 100644 --- a/examples/adafruit_io_simpletest_metadata.py +++ b/examples/adafruit_io_simpletest_metadata.py @@ -10,7 +10,7 @@ from adafruit_esp32spi import adafruit_esp32spi, adafruit_esp32spi_wifimanager # Import Adafruit IO REST Client -from adafruit_io.adafruit_io import RESTClient +from adafruit_io.adafruit_io import RESTClient, AdafruitIO_RequestError # Get wifi details and more from a wifi_settings.py.py file try: diff --git a/examples/adafruit_io_simpletest_temperature.py b/examples/adafruit_io_simpletest_temperature.py index c1ab867..91d4dc8 100644 --- a/examples/adafruit_io_simpletest_temperature.py +++ b/examples/adafruit_io_simpletest_temperature.py @@ -15,7 +15,7 @@ from adafruit_esp32spi import adafruit_esp32spi, adafruit_esp32spi_wifimanager # Import Adafruit IO REST Client -from adafruit_io.adafruit_io import RESTClient +from adafruit_io.adafruit_io import RESTClient, AdafruitIO_RequestError # Import ADT7410 Library import adafruit_adt7410 From 63622c75601ddfc568963ec86fcaf953d9a8a14c Mon Sep 17 00:00:00 2001 From: brentru Date: Fri, 22 Feb 2019 13:58:23 -0500 Subject: [PATCH 41/48] fix sphinx api doc issue --- docs/api.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/api.rst b/docs/api.rst index 219297b..4705ac0 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -1,4 +1,5 @@ - +API +------------ .. If you created a package, create one automodule per module in the package. .. If your library file(s) are nested in a directory (e.g. /adafruit_foo/foo.py) From 1398d59f8d805df16dda952b701f7e6f523ca2e1 Mon Sep 17 00:00:00 2001 From: brentru Date: Fri, 22 Feb 2019 14:06:22 -0500 Subject: [PATCH 42/48] pylint the folder instead of adafruit_io.py --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 9f4601c..82b0663 100644 --- a/.travis.yml +++ b/.travis.yml @@ -42,7 +42,7 @@ install: - pip install --force-reinstall pylint==1.9.2 script: - - pylint adafruit_io.py + - pylint adafruitio/*.py - ([[ ! -d "examples" ]] || pylint --disable=missing-docstring,invalid-name,bad-whitespace examples/*.py) - circuitpython-build-bundles --filename_prefix adafruit-circuitpython-adafruit_io --library_location . - cd docs && sphinx-build -E -W -b html . _build/html && cd .. From 9b95cc7336304e2ba914576dd13586021d5e164e Mon Sep 17 00:00:00 2001 From: brentru Date: Fri, 22 Feb 2019 14:29:23 -0500 Subject: [PATCH 43/48] fix travis path --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 82b0663..4c0ccb6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -42,7 +42,7 @@ install: - pip install --force-reinstall pylint==1.9.2 script: - - pylint adafruitio/*.py + - pylint adafruit_io/*.py - ([[ ! -d "examples" ]] || pylint --disable=missing-docstring,invalid-name,bad-whitespace examples/*.py) - circuitpython-build-bundles --filename_prefix adafruit-circuitpython-adafruit_io --library_location . - cd docs && sphinx-build -E -W -b html . _build/html && cd .. From 427051cea49390b60d7bbe21cf3950e1cdbeb46f Mon Sep 17 00:00:00 2001 From: brentru Date: Fri, 22 Feb 2019 14:35:27 -0500 Subject: [PATCH 44/48] add instructions for obtaining the weather service ID into the example --- examples/adafruit_io_simpletest_weather.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/examples/adafruit_io_simpletest_weather.py b/examples/adafruit_io_simpletest_weather.py index 6db1905..ff091bb 100644 --- a/examples/adafruit_io_simpletest_weather.py +++ b/examples/adafruit_io_simpletest_weather.py @@ -51,7 +51,10 @@ io = RESTClient(ADAFRUIT_IO_USER, ADAFRUIT_IO_KEY, wifi) # Weather Location ID -location_id = 2127 +# (to obtain this value, visit +# https://io.adafruit.com/services/weather +# and copy over the location ID) +location_id = 1234 print('Getting weather record from IO...') # Get the specified weather record with current weather From a6c421b3f003cf1552a19b09e3e296cb72f5f699 Mon Sep 17 00:00:00 2001 From: brentru Date: Fri, 22 Feb 2019 14:48:59 -0500 Subject: [PATCH 45/48] add random service URL into example --- examples/adafruit_io_simpletest_randomizer.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/examples/adafruit_io_simpletest_randomizer.py b/examples/adafruit_io_simpletest_randomizer.py index 8045107..6da5741 100644 --- a/examples/adafruit_io_simpletest_randomizer.py +++ b/examples/adafruit_io_simpletest_randomizer.py @@ -49,6 +49,9 @@ io = RESTClient(ADAFRUIT_IO_USER, ADAFRUIT_IO_KEY, wifi) # Random Data ID +# (to obtain this value, visit +# https://io.adafruit.com/services/words +# and copy over the location ID) random_data_id = 1234 while True: From 31efdf8d2ea97d2bcfb09437cf06302341cc3c95 Mon Sep 17 00:00:00 2001 From: brentru Date: Fri, 22 Feb 2019 15:10:20 -0500 Subject: [PATCH 46/48] update docstrings --- adafruit_io/adafruit_io.py | 50 ++++++++++++++++++++++---------------- 1 file changed, 29 insertions(+), 21 deletions(-) diff --git a/adafruit_io/adafruit_io.py b/adafruit_io/adafruit_io.py index 56e70f5..f67e8b2 100755 --- a/adafruit_io/adafruit_io.py +++ b/adafruit_io/adafruit_io.py @@ -23,7 +23,7 @@ `adafruit_io` ================================================================================ -A CircuitPython/Python library for communicating with Adafruit IO +A CircuitPython/Python library for communicating with Adafruit IO over WiFi * Author(s): Brent Rubell for Adafruit Industries @@ -66,6 +66,8 @@ def __init__(self, adafruit_io_username, adafruit_io_key, wifi_manager): @staticmethod def _create_data(data, metadata): + """Creates JSON data payload + """ if metadata is not None: return {'value':data, 'lat':metadata['lat'], 'lon':metadata['lon'], 'ele':metadata['ele'], 'created_at':metadata['created_at']} @@ -73,6 +75,9 @@ def _create_data(data, metadata): @staticmethod def _handle_error(response): + """Checks HTTP status codes + and raises errors. + """ if response.status_code == 429: raise AdafruitIO_ThrottleError elif response.status_code == 400: @@ -81,13 +86,16 @@ def _handle_error(response): raise AdafruitIO_RequestError(response) def _compose_path(self, path): + """Composes a valid API request path. + :param str path: Adafruit IO API URL path. + """ return "{0}/{1}/{2}/{3}".format('https://io.adafruit.com/api', 'v2', self.username, path) # HTTP Requests def _post(self, path, payload): """ - Send data to Adafruit IO - :param str path: Formatted Adafruit IO URL + POST data to Adafruit IO + :param str path: Formatted Adafruit IO URL from _compose_path :param json payload: JSON data to send to Adafruit IO """ response = self.wifi.post( @@ -99,8 +107,8 @@ def _post(self, path, payload): def _get(self, path): """ - Get data from Adafruit IO - :param str path: Formatted Adafruit IO URL + GET data from Adafruit IO + :param str path: Formatted Adafruit IO URL from _compose_path """ response = self.wifi.get( path, @@ -110,8 +118,8 @@ def _get(self, path): def _delete(self, path): """ - Delete data from Adafruit IO. - :param str path: Formatted Adafruit IO URL + DELETE data from Adafruit IO. + :param str path: Formatted Adafruit IO URL from _compose_path """ response = self.wifi.delete( path, @@ -122,10 +130,10 @@ def _delete(self, path): # Data def send_data(self, feed_key, data, metadata=None): """ - Sends value data to an Adafruit IO feed. - :param str feed_key: Specified Adafruit IO feed - :param str data: Data to send to an Adafruit IO feed - :param dict metadata: Metadata associated with the data being sent + Sends value data to a specified Adafruit IO feed. + :param str feed_key: Adafruit IO feed key + :param str data: Data to send to the Adafruit IO feed + :param dict metadata: Optional metadata associated with the data """ path = self._compose_path("feeds/{0}/data".format(feed_key)) payload = self._create_data(data, metadata) @@ -134,16 +142,16 @@ def send_data(self, feed_key, data, metadata=None): def receive_data(self, feed_key): """ Return the most recent value for the specified feed. - :param string feed_key: Name/Key/ID of Adafruit IO feed. + :param string feed_key: Adafruit IO feed key """ path = self._compose_path("feeds/{0}/data/last".format(feed_key)) return self._get(path) def delete_data(self, feed_key, data_id): """ - Delete an existing Data point from a feed. - :param string feed: Feed Key - :param string data_id: Data point to delete + Deletes an existing Data point from a feed. + :param string feed: Adafruit IO feed key + :param string data_id: Data point to delete from the feed """ path = self._compose_path("feeds/{0}/data/{1}".format(feed_key, data_id)) return self._delete(path) @@ -188,9 +196,9 @@ def get_group(self, group_key): # Feeds def get_feed(self, feed_key, detailed=False): """ - Returns feed based on the feed key - :param str feed_key: Feed Key - :param bool detailed: Returns a more detailed feed record + Returns an Adafruit IO feed based on the feed key + :param str feed_key: Adafruit IO Feed Key + :param bool detailed: Returns a more verbose feed record """ if detailed: path = self._compose_path("feeds/{0}/details".format(feed_key)) @@ -200,10 +208,10 @@ def get_feed(self, feed_key, detailed=False): def create_new_feed(self, feed_key, feed_desc=None, feed_license=None): """ - Creates a new feed. - :param str feed_key: Feed key + Creates a new Adafruit IO feed. + :param str feed_key: Adafruit IO Feed Key :param str feed_desc: Optional description of feed - :param str feed_license: Optional feed License + :param str feed_license: Optional feed license """ path = self._compose_path("feeds") payload = {'name':feed_key, From 2c1f65e62e99140c2783d7f14243905d2b79518d Mon Sep 17 00:00:00 2001 From: brentru Date: Fri, 22 Feb 2019 16:10:10 -0500 Subject: [PATCH 47/48] fix bug when getting ISO8601 datetime from server --- adafruit_io/adafruit_io.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/adafruit_io/adafruit_io.py b/adafruit_io/adafruit_io.py index f67e8b2..524b3dd 100755 --- a/adafruit_io/adafruit_io.py +++ b/adafruit_io/adafruit_io.py @@ -105,15 +105,18 @@ def _post(self, path, payload): self._handle_error(response) return response.json() - def _get(self, path): + def _get(self, path, return_text=False): """ GET data from Adafruit IO :param str path: Formatted Adafruit IO URL from _compose_path + :param bool return_text: Returns text instead of json """ response = self.wifi.get( path, headers=self.http_headers[1]) self._handle_error(response) + if return_text: + return response.text return response.json() def _delete(self, path): @@ -251,4 +254,4 @@ def receive_time(self, time_type): :param string time_type: Type of time to be returned: millis, seconds, or ISO-8601 """ path = 'https://io.adafruit.com/api/v2/time/{0}'.format(time_type) - return self._get(path) + return self._get(path, return_text=True) From d8ebe4c30b9dab741b6998d338422820940b45ae Mon Sep 17 00:00:00 2001 From: brentru Date: Fri, 22 Feb 2019 16:39:26 -0500 Subject: [PATCH 48/48] add example for using the groups api --- examples/adafruit_io_simpletest_groups.py | 63 +++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 examples/adafruit_io_simpletest_groups.py diff --git a/examples/adafruit_io_simpletest_groups.py b/examples/adafruit_io_simpletest_groups.py new file mode 100644 index 0000000..f6b3752 --- /dev/null +++ b/examples/adafruit_io_simpletest_groups.py @@ -0,0 +1,63 @@ +""" +Example of performing group operations +""" +import board +import busio +from digitalio import DigitalInOut + +# ESP32 SPI +from adafruit_esp32spi import adafruit_esp32spi, adafruit_esp32spi_wifimanager + +# Import Adafruit IO REST Client +from adafruit_io.adafruit_io import RESTClient + +# Get wifi details and more from a wifi_settings.py.py file +try: + from wifi_settings import settings +except ImportError: + print("WiFi settings are kept in wifi_settings.py.py, please add them there!") + raise + + +# ESP32 Setup +esp32_cs = DigitalInOut(board.D9) +esp32_ready = DigitalInOut(board.D10) +esp32_reset = DigitalInOut(board.D5) +spi = busio.SPI(board.SCK, board.MOSI, board.MISO) +esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset) +wifi = adafruit_esp32spi_wifimanager.ESPSPI_WiFiManager(esp, settings, board.NEOPIXEL) + +""" +# PyPortal ESP32 Setup +import microcontroller +esp32_cs = DigitalInOut(microcontroller.pin.PB14) +esp32_ready = DigitalInOut(microcontroller.pin.PB16) +esp32_reset = DigitalInOut(microcontroller.pin.PB17) +spi = busio.SPI(board.SCK, board.MOSI, board.MISO) +esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset) +wifi = adafruit_esp32spi_wifimanager.ESPSPI_WiFiManager(esp, settings, board.NEOPIXEL) +""" + +# Set your Adafruit IO Username and Key in wifi_settings.py +# (visit io.adafruit.com if you need to create an account, +# or if you need your Adafruit IO key.) +ADAFRUIT_IO_USER = settings['adafruit_io_user'] +ADAFRUIT_IO_KEY = settings['adafruit_io_key'] + +# Create an instance of the Adafruit IO REST client +io = RESTClient(ADAFRUIT_IO_USER, ADAFRUIT_IO_KEY, wifi) + +# Create a new group +print('Creating a new Adafruit IO Group...') +sensor_group = io.create_new_group('envsensors', 'a group of environmental sensors') + +# Add the 'temperature' feed to the group +print('Adding feed temperature to group...') +io.add_feed_to_group(sensor_group['key'], 'temperature') + +# Get info from the group +print(sensor_group) + +# Delete the group +print('Deleting group...') +io.delete_group('envsensors')