mirror of
https://github.com/letscontrolit/ESPEasy.git
synced 2026-07-28 12:17:05 +00:00
Compare commits
62
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
acecff4108 | ||
|
|
cf4d28eb4f | ||
|
|
e648a20fd0 | ||
|
|
692fb248ce | ||
|
|
5a87397ee0 | ||
|
|
99ba09b024 | ||
|
|
f68516d5bb | ||
|
|
8102a0096d | ||
|
|
96ecf9bf29 | ||
|
|
ef1e371514 | ||
|
|
45d67292a3 | ||
|
|
b5662baad4 | ||
|
|
12c3e5f81f | ||
|
|
dececf24ee | ||
|
|
3fb6dec382 | ||
|
|
cef962c5f1 | ||
|
|
cca2335070 | ||
|
|
ffd0d26ed3 | ||
|
|
f787a9a9a6 | ||
|
|
a0ae104794 | ||
|
|
2b78810457 | ||
|
|
43081c3ac8 | ||
|
|
33281c08c2 | ||
|
|
461aee26ad | ||
|
|
2b0b14b2e8 | ||
|
|
b7404666b1 | ||
|
|
da25aa87dd | ||
|
|
10a1e634e2 | ||
|
|
83f86449b9 | ||
|
|
eee337d3e3 | ||
|
|
c549ecd329 | ||
|
|
d9e682668d | ||
|
|
e38072ac24 | ||
|
|
6aebeba5dc | ||
|
|
da01c8f469 | ||
|
|
b3b68856f0 | ||
|
|
bec5cb5334 | ||
|
|
bda6011390 | ||
|
|
f3fdb93a52 | ||
|
|
200b060b15 | ||
|
|
ff41cb2f94 | ||
|
|
c134eb6d13 | ||
|
|
f9e2a211e1 | ||
|
|
bd3d3f66f4 | ||
|
|
3bad683211 | ||
|
|
68f6e913a2 | ||
|
|
96420faa2f | ||
|
|
8eea77e4ed | ||
|
|
3d1f723787 | ||
|
|
5d459003e4 | ||
|
|
ad208c357c | ||
|
|
b1c777e6fd | ||
|
|
f5ab15c255 | ||
|
|
001ec6dcd2 | ||
|
|
15e5edccd8 | ||
|
|
651353cc99 | ||
|
|
85f97551c5 | ||
|
|
6a158f68f5 | ||
|
|
1933714de5 | ||
|
|
e6fdd3380a | ||
|
|
639685ea0d | ||
|
|
867209de6d |
@@ -22,3 +22,5 @@ test/output_export.cpp
|
||||
.vscode/.browse.c_cpp.db*
|
||||
.vscode/c_cpp_properties.json
|
||||
.vscode/launch.json
|
||||
|
||||
docs/build/
|
||||
|
||||
+2
-1
@@ -22,9 +22,10 @@ addons:
|
||||
|
||||
|
||||
install:
|
||||
- pip install -U platformio
|
||||
- pip install -U platformio sphinx recommonmark sphinx_bootstrap_theme
|
||||
|
||||
script:
|
||||
- bash ./preflight.sh # make sure input files are OK before wasting time with prereqs
|
||||
# - cppcheck --enable=warning src/*.ino -q --force -I src --include=src/ESPEasy.ino --error-exitcode=1
|
||||
# - ./memanalyzer.py ~/.platformio/packages/toolchain-xtensa/bin/xtensa-lx106-elf-objdump
|
||||
- PLATFORMIO_BUILD_FLAGS="-D CONTINUOUS_INTEGRATION" platformio run
|
||||
|
||||
@@ -41,4 +41,6 @@ ESPEasy_mega-20180102_dev_ESP8285_1024.bin | ESP8285 with 1Mb flash | Stabl
|
||||
|
||||
Details and discussion are on the Experimental forum: https://www.letscontrolit.com/forum/viewforum.php?f=18
|
||||
|
||||
Automated builds of the (new) documentation can be found at [ESPEasy.readthedocs.io](https://espeasy.readthedocs.io/en/latest/)
|
||||
|
||||
We're also on IRC: #ESPEasy @freenode
|
||||
|
||||
+5
-1
@@ -36,9 +36,13 @@ done
|
||||
|
||||
#create a source structure that is the same as the original ESPEasy project (and works with the howto on the wiki)
|
||||
rm -rf dist/Source 2>/dev/null
|
||||
mkdir dist/Source
|
||||
rm -rf dist/Docs 2>/dev/null
|
||||
|
||||
mkdir -p dist/Source
|
||||
mkdir -p dist/Docs
|
||||
cp -r lib dist/Source/
|
||||
cp -r src dist/Source/
|
||||
cp -r docs/build/ dist/Docs/
|
||||
cp platformio.ini dist/Source/
|
||||
|
||||
cd dist
|
||||
|
||||
Vendored
+116
@@ -1,3 +1,119 @@
|
||||
-------------------------------------------------
|
||||
Changes in release mega-20181010 (since mega-20181009)
|
||||
-------------------------------------------------
|
||||
|
||||
Release date: Wed Oct 10 04:00:09 CEST 2018
|
||||
|
||||
Plebs (1):
|
||||
Update src/_P019_PCF8574.ino
|
||||
|
||||
|
||||
-------------------------------------------------
|
||||
Changes in release mega-20181009 (since mega-20181008)
|
||||
-------------------------------------------------
|
||||
|
||||
Release date: Tue Oct 9 04:00:18 CEST 2018
|
||||
|
||||
TD-er (7):
|
||||
[Docs] Add favicon to documentation
|
||||
[Docs] Add Travis check for documentation and stop build for docs only
|
||||
[Docs] Run Travic documentation check before compiling project
|
||||
[Docs] Disable travis_terminate for now
|
||||
[JSON] Replace \n and \r in text fields
|
||||
[LWIP1.4] Move back to LWIP1.4
|
||||
[StringConverter] Some optimisations to reduce memory allocation
|
||||
|
||||
|
||||
-------------------------------------------------
|
||||
Changes in release mega-20181008 (since mega-20181007)
|
||||
-------------------------------------------------
|
||||
|
||||
Release date: Mon Oct 8 04:00:09 CEST 2018
|
||||
|
||||
Gijs Noorlander (1):
|
||||
Added link to ReadTheDocs
|
||||
|
||||
Grovkillen (1):
|
||||
[Sphinx] added extension "sphinx.ext.imgconverter"
|
||||
|
||||
TD-er (3):
|
||||
[Sphinx] Initial setup for Sphinx documentation
|
||||
[Docs] First ESPEasy documentation (Controllers)
|
||||
[Docs] Added some directory structure and template
|
||||
|
||||
|
||||
-------------------------------------------------
|
||||
Changes in release mega-20181007 (since mega-20181006)
|
||||
-------------------------------------------------
|
||||
|
||||
Release date: Sun Oct 7 04:00:09 CEST 2018
|
||||
|
||||
Max (2):
|
||||
Force slash to be converted in htmlEscape
|
||||
Fix XSS-Vulnerabilites on wifi configuration pages
|
||||
|
||||
Plebs (3):
|
||||
Add three new TOGGLE commands
|
||||
fixed float to int conversion
|
||||
added "mcpgpiotoggle" command
|
||||
|
||||
TD-er (3):
|
||||
[ESP32] Allow Wrover dev kit to be used for PIO debug
|
||||
[Stack] Move Arduino 'cont' stack into user RAM
|
||||
[SPIFFS] Make sure to close open files on SPIFFS
|
||||
|
||||
|
||||
-------------------------------------------------
|
||||
Changes in release mega-20181006 (since mega-20181004)
|
||||
-------------------------------------------------
|
||||
|
||||
Release date: Sat Oct 6 04:00:13 CEST 2018
|
||||
|
||||
TD-er (3):
|
||||
[Stack] Increase stack to 5k and reduce stack allocations in rules
|
||||
[WiFi] Add delay to connection attempts in ControllerSettings
|
||||
[Build flags] Remove NO_EXTRA_4K_HEAP
|
||||
|
||||
|
||||
-------------------------------------------------
|
||||
Changes in release mega-20181004 (since mega-20181003)
|
||||
-------------------------------------------------
|
||||
|
||||
Release date: Thu Oct 4 04:00:08 CEST 2018
|
||||
|
||||
Bartlomiej Zimon (1):
|
||||
- partial fix for #1723
|
||||
|
||||
JojoS (1):
|
||||
added error checking and logging
|
||||
|
||||
JojoS62 (5):
|
||||
added float calculation for time to distance conversion
|
||||
added more settings: unit, filtertype and size
|
||||
max distance depends on measurement unit
|
||||
code clean up
|
||||
fixed 'unused variable' warning
|
||||
|
||||
TD-er (3):
|
||||
[sendHttp] #1830 Set timeout and early exit on timeout reached
|
||||
[WiFiClient] Set timeout and make it configurable for controllers
|
||||
[Core 2.4.1] Move back to core 2.4.1 from 2.4.2
|
||||
|
||||
Thomas (1):
|
||||
Update _P075_Nextion.ino (#1)
|
||||
|
||||
|
||||
-------------------------------------------------
|
||||
Changes in release mega-20181003 (since mega-20181002)
|
||||
-------------------------------------------------
|
||||
|
||||
Release date: Wed Oct 3 04:00:18 CEST 2018
|
||||
|
||||
David Conran (2):
|
||||
Acknowledge credit & origin of code used in IRTX
|
||||
Acknowledge credit & origin of code used in _P016IR.ino
|
||||
|
||||
|
||||
-------------------------------------------------
|
||||
Changes in release mega-20181002 (since mega-20181001)
|
||||
-------------------------------------------------
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
# Minimal makefile for Sphinx documentation
|
||||
#
|
||||
|
||||
# You can set these variables from the command line.
|
||||
SPHINXOPTS =
|
||||
SPHINXBUILD = sphinx-build
|
||||
SOURCEDIR = source
|
||||
BUILDDIR = build
|
||||
|
||||
# Put it first so that "make" without argument is like "make help".
|
||||
help:
|
||||
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
||||
|
||||
.PHONY: help Makefile
|
||||
|
||||
# Catch-all target: route all unknown targets to Sphinx using the new
|
||||
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
|
||||
%: Makefile
|
||||
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
||||
@@ -0,0 +1,35 @@
|
||||
@ECHO OFF
|
||||
|
||||
pushd %~dp0
|
||||
|
||||
REM Command file for Sphinx documentation
|
||||
|
||||
if "%SPHINXBUILD%" == "" (
|
||||
set SPHINXBUILD=sphinx-build
|
||||
)
|
||||
set SOURCEDIR=source
|
||||
set BUILDDIR=build
|
||||
|
||||
if "%1" == "" goto help
|
||||
|
||||
%SPHINXBUILD% >NUL 2>NUL
|
||||
if errorlevel 9009 (
|
||||
echo.
|
||||
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
|
||||
echo.installed, then set the SPHINXBUILD environment variable to point
|
||||
echo.to the full path of the 'sphinx-build' executable. Alternatively you
|
||||
echo.may add the Sphinx directory to PATH.
|
||||
echo.
|
||||
echo.If you don't have Sphinx installed, grab it from
|
||||
echo.http://sphinx-doc.org/
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
|
||||
goto end
|
||||
|
||||
:help
|
||||
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
|
||||
|
||||
:end
|
||||
popd
|
||||
@@ -0,0 +1,3 @@
|
||||
recommonmark
|
||||
Sphinx
|
||||
sphinx-bootstrap-theme
|
||||
@@ -0,0 +1,65 @@
|
||||
Controller
|
||||
**********
|
||||
|
||||
A controller is a component to enable a plugin to send data elsewhere.
|
||||
|
||||
- Up-to 3 controllers can be active in ESPEasy.
|
||||
- Per plugin up-to 3 active controllers can be selected.
|
||||
- For some controllers an additional parameter can be given.
|
||||
|
||||
For example, Domoticz needs an 'IDX' value to identify the configured entry in
|
||||
Domoticz for which new data is sent.
|
||||
|
||||
Controller Parameters
|
||||
=====================
|
||||
|
||||
Generic fields
|
||||
--------------
|
||||
|
||||
- **Protocol** - The type of controller (e.g. ThingSpeak/OpenHAB MQTT/etc.)
|
||||
- **Locate Controller** - Selection between hostname/IP
|
||||
- **Controller Hostname/IP** - The address to reach the selected service
|
||||
- **Controller Port** - TCP/UDP Port number (0...65536)
|
||||
- **Enabled** - Whether or not the controller is active.
|
||||
|
||||
Send queue parameters
|
||||
---------------------
|
||||
|
||||
Controllers have a queue to keep unsent messages.
|
||||
This queue is used to handle message bursts and also store messages which are recorded
|
||||
before WiFi connection is made or during lost connection.
|
||||
|
||||
- **Minimum Send Interval** - Minimum time between two messages in msec.
|
||||
- **Max Queue Depth** - Maximum length of the buffer queue to keep unsent messages.
|
||||
- **Max Retries** - Maximum number of retries to send a message.
|
||||
- **Full Queue Action** - How to handle when queue is full, ignore new or delete oldest message.
|
||||
- **Client Timeout** - Timeout in msec for an network connection used by the controller.
|
||||
|
||||
|
||||
Sample ThingSpeak configuration
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Some controllers, like ThingSpeak, need a specific configuration.
|
||||
ThingSpeak only allows a message every 15 seconds for the free accounts.
|
||||
|
||||
- **Minimum Send Interval** - 15000 msec
|
||||
- **Max Queue Depth** - 1 (only report the last value)
|
||||
- **Max Retries** - 2
|
||||
- **Full Queue Action** - Delete Oldest
|
||||
- **Client Timeout** - 500 msec (server is online, so timeout must be a bit longer)
|
||||
|
||||
|
||||
Controller user credentials
|
||||
---------------------------
|
||||
|
||||
- **Controller User** - User name (optional)
|
||||
- **Controller Password** - Password (optional)
|
||||
|
||||
MQTT related settings
|
||||
---------------------
|
||||
|
||||
- **Controller Subscribe** - Subscribe to the given topic.
|
||||
- **Controller Publish** - Publish to the given topic.
|
||||
- **Controller lwl topic** - Topic to which LWT (Last Will Testament) messages should be sent.
|
||||
- **LWT Connect Message** - Connection established message.
|
||||
- **LWT Disconnect Message** - Connection lost message (sent to broker during connect and published by broker when connection is lost)
|
||||
@@ -0,0 +1,2 @@
|
||||
About Us
|
||||
********
|
||||
@@ -0,0 +1,2 @@
|
||||
ESPEasy Function Blocks
|
||||
***********************
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 2.1 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
@@ -0,0 +1,35 @@
|
||||
Documentation
|
||||
*************
|
||||
|
||||
For documentation we use Sphinx and this will be read by ReadTheDocs.
|
||||
We use the `Sphinx Bootstrap Theme <https://github.com/ryan-roemer/sphinx-bootstrap-theme>`_
|
||||
|
||||
This documentation is included in the GitHub repository.
|
||||
It allows us to create documentation per version of ESPEasy.
|
||||
|
||||
See also the `ESPEasy wiki <https://www.letscontrolit.com/wiki/index.php/ESPEasy>`_
|
||||
for more documentation which has not been moved here.
|
||||
|
||||
Needed Python packages::
|
||||
|
||||
pip install sphinx recommonmark sphinx_bootstrap_theme
|
||||
|
||||
PlatformIO with Atom
|
||||
====================
|
||||
|
||||
With the ESPEasy project open in Atom, open the PIO terminal in Atom.
|
||||
|
||||
Install dependencies::
|
||||
|
||||
cd docs
|
||||
pip install ... (see needed Python packages above)
|
||||
|
||||
Build on Windows::
|
||||
|
||||
cd docs
|
||||
.\make.bat html
|
||||
|
||||
Build on Linux/Mac::
|
||||
|
||||
cd docs
|
||||
./make html
|
||||
@@ -0,0 +1,2 @@
|
||||
Plugins
|
||||
*******
|
||||
@@ -0,0 +1,2 @@
|
||||
Command Reference
|
||||
*****************
|
||||
@@ -0,0 +1,2 @@
|
||||
System Variables
|
||||
****************
|
||||
@@ -0,0 +1,2 @@
|
||||
Rules
|
||||
*****
|
||||
@@ -0,0 +1,286 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Configuration file for the Sphinx documentation builder.
|
||||
#
|
||||
# This file does only contain a selection of the most common options. For a
|
||||
# full list see the documentation:
|
||||
# http://www.sphinx-doc.org/en/master/config
|
||||
|
||||
# -- Path setup --------------------------------------------------------------
|
||||
|
||||
# If extensions (or modules to document with autodoc) are in another directory,
|
||||
# add these directories to sys.path here. If the directory is relative to the
|
||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
#
|
||||
# import os
|
||||
# import sys
|
||||
# sys.path.insert(0, os.path.abspath('.'))
|
||||
from recommonmark.parser import CommonMarkParser
|
||||
import sphinx_bootstrap_theme
|
||||
|
||||
|
||||
# -- Project information -----------------------------------------------------
|
||||
|
||||
project = u'ESPEasy'
|
||||
copyright = u'2018, ESPEasy'
|
||||
author = u'Many'
|
||||
|
||||
# The short X.Y version
|
||||
version = u''
|
||||
# The full version, including alpha/beta/rc tags
|
||||
release = u'2.1b1'
|
||||
|
||||
|
||||
# -- General configuration ---------------------------------------------------
|
||||
|
||||
# If your documentation needs a minimal Sphinx version, state it here.
|
||||
#
|
||||
# needs_sphinx = '1.0'
|
||||
|
||||
# Add any Sphinx extension module names here, as strings. They can be
|
||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||
# ones.
|
||||
extensions = [
|
||||
'sphinx.ext.autodoc',
|
||||
'sphinx.ext.intersphinx',
|
||||
'sphinx.ext.todo',
|
||||
'sphinx.ext.imgmath',
|
||||
'sphinx.ext.imgconverter',
|
||||
]
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ['_templates']
|
||||
|
||||
source_parsers = {
|
||||
'.md': CommonMarkParser,
|
||||
}
|
||||
|
||||
# The suffix(es) of source filenames.
|
||||
# You can specify multiple suffix as a list of string:
|
||||
#
|
||||
source_suffix = ['.rst', '.md']
|
||||
#source_suffix = '.rst'
|
||||
|
||||
# The master toctree document.
|
||||
master_doc = 'index'
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
#
|
||||
# This is also used if you do content translation via gettext catalogs.
|
||||
# Usually you set "language" from the command line for these cases.
|
||||
language = None
|
||||
|
||||
# List of patterns, relative to source directory, that match files and
|
||||
# directories to ignore when looking for source files.
|
||||
# This pattern also affects html_static_path and html_extra_path.
|
||||
exclude_patterns = []
|
||||
|
||||
# The name of the Pygments (syntax highlighting) style to use.
|
||||
pygments_style = None
|
||||
|
||||
|
||||
# -- Options for HTML output -------------------------------------------------
|
||||
html_logo = 'ESPEasy/espeasy_logo.png'
|
||||
html_favicon = 'ESPEasy/favicon.ico'
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
#
|
||||
#html_theme = 'sphinx_rtd_theme'
|
||||
html_theme = 'bootstrap'
|
||||
html_theme_path = sphinx_bootstrap_theme.get_html_theme_path()
|
||||
|
||||
# Theme options are theme-specific and customize the look and feel of a theme
|
||||
# further. For a list of options available for each theme, see the
|
||||
# documentation.
|
||||
#
|
||||
# html_theme_options = {}
|
||||
#html_theme_options = {
|
||||
# 'canonical_url': '',
|
||||
# 'analytics_id': '',
|
||||
# 'logo_only': False,
|
||||
# 'display_version': True,
|
||||
# 'prev_next_buttons_location': 'bottom',
|
||||
# 'style_external_links': False,
|
||||
# # Toc options
|
||||
# 'collapse_navigation': True,
|
||||
# 'sticky_navigation': True,
|
||||
# 'navigation_depth': 4,
|
||||
# 'includehidden': True,
|
||||
# 'titles_only': False
|
||||
#}
|
||||
|
||||
html_theme_options = {
|
||||
# Navigation bar title. (Default: ``project`` value)
|
||||
'navbar_title': "ESPEasy",
|
||||
|
||||
# Tab name for entire site. (Default: "Site")
|
||||
'navbar_site_name': "Site",
|
||||
|
||||
# A list of tuples containing pages or urls to link to.
|
||||
# Valid tuples should be in the following forms:
|
||||
# (name, page) # a link to a page
|
||||
# (name, "/aa/bb", 1) # a link to an arbitrary relative url
|
||||
# (name, "http://example.com", True) # arbitrary absolute url
|
||||
# Note the "1" or "True" value above as the third argument to indicate
|
||||
# an arbitrary url.
|
||||
'navbar_links': [
|
||||
("Rules", "rules"),
|
||||
("Forum", "https://www.letscontrolit.com/forum/viewforum.php?f=1", True),
|
||||
],
|
||||
|
||||
# Render the next and previous page links in navbar. (Default: true)
|
||||
'navbar_sidebarrel': True,
|
||||
|
||||
# Render the current pages TOC in the navbar. (Default: true)
|
||||
'navbar_pagenav': True,
|
||||
|
||||
# Tab name for the current pages TOC. (Default: "Page")
|
||||
'navbar_pagenav_name': "Page",
|
||||
|
||||
# Global TOC depth for "site" navbar tab. (Default: 1)
|
||||
# Switching to -1 shows all levels.
|
||||
'globaltoc_depth': 2,
|
||||
|
||||
# Include hidden TOCs in Site navbar?
|
||||
#
|
||||
# Note: If this is "false", you cannot have mixed ``:hidden:`` and
|
||||
# non-hidden ``toctree`` directives in the same page, or else the build
|
||||
# will break.
|
||||
#
|
||||
# Values: "true" (default) or "false"
|
||||
'globaltoc_includehidden': "true",
|
||||
|
||||
# HTML navbar class (Default: "navbar") to attach to <div> element.
|
||||
# For black navbar, do "navbar navbar-inverse"
|
||||
'navbar_class': "navbar navbar-inverse",
|
||||
|
||||
# Fix navigation bar to top of page?
|
||||
# Values: "true" (default) or "false"
|
||||
'navbar_fixed_top': "true",
|
||||
|
||||
# Location of link to source.
|
||||
# Options are "nav" (default), "footer" or anything else to exclude.
|
||||
'source_link_position': "none",
|
||||
|
||||
# Bootswatch (http://bootswatch.com/) theme.
|
||||
#
|
||||
# Options are nothing (default) or the name of a valid theme
|
||||
# such as "cosmo" or "sandstone".
|
||||
#
|
||||
# The set of valid themes depend on the version of Bootstrap
|
||||
# that's used (the next config option).
|
||||
#
|
||||
# Currently, the supported themes are:
|
||||
# - Bootstrap 2: https://bootswatch.com/2
|
||||
# - Bootstrap 3: https://bootswatch.com/3
|
||||
'bootswatch_theme': "cerulean",
|
||||
|
||||
# Choose Bootstrap version.
|
||||
# Values: "3" (default) or "2" (in quotes)
|
||||
'bootstrap_version': "3",
|
||||
}
|
||||
|
||||
# Add any paths that contain custom static files (such as style sheets) here,
|
||||
# relative to this directory. They are copied after the builtin static files,
|
||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||
html_static_path = ['_static']
|
||||
|
||||
# Custom sidebar templates, must be a dictionary that maps document names
|
||||
# to template names.
|
||||
#
|
||||
# The default sidebars (for documents that don't match any pattern) are
|
||||
# defined by theme itself. Builtin themes are using these templates by
|
||||
# default: ``['localtoc.html', 'relations.html', 'sourcelink.html',
|
||||
# 'searchbox.html']``.
|
||||
#
|
||||
# html_sidebars = {}
|
||||
|
||||
|
||||
# -- Options for HTMLHelp output ---------------------------------------------
|
||||
|
||||
# Output file base name for HTML help builder.
|
||||
htmlhelp_basename = 'ESPEasydoc'
|
||||
|
||||
|
||||
# -- Options for LaTeX output ------------------------------------------------
|
||||
|
||||
latex_elements = {
|
||||
# The paper size ('letterpaper' or 'a4paper').
|
||||
#
|
||||
# 'papersize': 'letterpaper',
|
||||
|
||||
# The font size ('10pt', '11pt' or '12pt').
|
||||
#
|
||||
# 'pointsize': '10pt',
|
||||
|
||||
# Additional stuff for the LaTeX preamble.
|
||||
#
|
||||
# 'preamble': '',
|
||||
|
||||
# Latex figure (float) alignment
|
||||
#
|
||||
# 'figure_align': 'htbp',
|
||||
}
|
||||
|
||||
# Grouping the document tree into LaTeX files. List of tuples
|
||||
# (source start file, target name, title,
|
||||
# author, documentclass [howto, manual, or own class]).
|
||||
latex_documents = [
|
||||
(master_doc, 'ESPEasy.tex', u'ESPEasy Documentation',
|
||||
u'Many', 'manual'),
|
||||
]
|
||||
|
||||
|
||||
# -- Options for manual page output ------------------------------------------
|
||||
|
||||
# One entry per manual page. List of tuples
|
||||
# (source start file, name, description, authors, manual section).
|
||||
man_pages = [
|
||||
(master_doc, 'espeasy', u'ESPEasy Documentation',
|
||||
[author], 1)
|
||||
]
|
||||
|
||||
|
||||
# -- Options for Texinfo output ----------------------------------------------
|
||||
|
||||
# Grouping the document tree into Texinfo files. List of tuples
|
||||
# (source start file, target name, title, author,
|
||||
# dir menu entry, description, category)
|
||||
texinfo_documents = [
|
||||
(master_doc, 'ESPEasy', u'ESPEasy Documentation',
|
||||
author, 'ESPEasy', 'ESP82xx/ESP32 firmware to connect people with any level of experience to system automation.',
|
||||
'Miscellaneous'),
|
||||
]
|
||||
|
||||
|
||||
# -- Options for Epub output -------------------------------------------------
|
||||
|
||||
# Bibliographic Dublin Core info.
|
||||
epub_title = project
|
||||
|
||||
# The unique identifier of the text. This can be a ISBN number
|
||||
# or the project homepage.
|
||||
#
|
||||
# epub_identifier = ''
|
||||
|
||||
# A unique identification for the text.
|
||||
#
|
||||
# epub_uid = ''
|
||||
|
||||
# A list of files that should not be packed into the epub file.
|
||||
epub_exclude_files = ['search.html']
|
||||
|
||||
|
||||
# -- Extension configuration -------------------------------------------------
|
||||
|
||||
# -- Options for intersphinx extension ---------------------------------------
|
||||
|
||||
# Example configuration for intersphinx: refer to the Python standard library.
|
||||
intersphinx_mapping = {'https://docs.python.org/': None}
|
||||
|
||||
# -- Options for todo extension ----------------------------------------------
|
||||
|
||||
# If true, `todo` and `todoList` produce output, else they produce nothing.
|
||||
todo_include_todos = True
|
||||
@@ -0,0 +1,38 @@
|
||||
.. ESPEasy documentation master file, created by
|
||||
sphinx-quickstart on Sat Oct 06 22:34:34 2018.
|
||||
You can adapt this file completely to your liking, but it should at least
|
||||
contain the root `toctree` directive.
|
||||
|
||||
Welcome to ESPEasy's documentation!
|
||||
===================================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:caption: Table of Contents
|
||||
|
||||
ESPEasy/AboutUs.rst
|
||||
ESPEasy/FunctionBlocks.rst
|
||||
Controller/Controller.rst
|
||||
Plugin/Plugin.rst
|
||||
Rules/Rules.rst
|
||||
|
||||
.. raw:: latex
|
||||
|
||||
\appendix
|
||||
|
||||
|
||||
.. toctree::
|
||||
:caption: Appendix
|
||||
|
||||
Participate/Documentation.rst
|
||||
Reference/Command.rst
|
||||
Reference/SystemVariable.rst
|
||||
|
||||
|
||||
|
||||
Indices and tables
|
||||
==================
|
||||
|
||||
* :ref:`genindex`
|
||||
* :ref:`modindex`
|
||||
* :ref:`search`
|
||||
@@ -6,12 +6,13 @@
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
#include "NewPingESP8266.h"
|
||||
|
||||
//#include "ESPEasy-Globals.h"
|
||||
// ---------------------------------------------------------------------------
|
||||
// NewPingESP8266 constructor
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
NewPingESP8266::NewPingESP8266(uint32_t trigger_pin, uint32_t echo_pin, unsigned int max_cm_distance) {
|
||||
_errorState = STATUS_SENSOR_READY;
|
||||
#if DO_BITWISE == true
|
||||
_triggerBit = digitalPinToBitMask(trigger_pin); // Get the port register bitmask for the trigger pin.
|
||||
_echoBit = digitalPinToBitMask(echo_pin); // Get the port register bitmask for the echo pin.
|
||||
@@ -58,7 +59,10 @@ unsigned int NewPingESP8266::ping(unsigned int max_cm_distance) {
|
||||
while (!digitalRead(_echoPin)) // Wait for the ping echo.
|
||||
#endif
|
||||
{
|
||||
if (micros() > _max_time) return NO_ECHO; // Stop the loop and return NO_ECHO (false) if we're beyond the set maximum distance.
|
||||
if ((_max_cm_distance > 0) && (micros() > _max_time)) {
|
||||
_errorState = STATUS_MAX_DISTANCE_EXCEEDED;
|
||||
return NO_ECHO; // Stop the loop and return NO_ECHO (false) if we're beyond the set maximum distance.
|
||||
}
|
||||
}
|
||||
#else
|
||||
#if DO_BITWISE == true
|
||||
@@ -67,10 +71,14 @@ unsigned int NewPingESP8266::ping(unsigned int max_cm_distance) {
|
||||
while (digitalRead(_echoPin)) // Wait for the ping echo.
|
||||
#endif
|
||||
{
|
||||
if (micros() > _max_time) return NO_ECHO; // Stop the loop and return NO_ECHO (false) if we're beyond the set maximum distance.
|
||||
if ((_max_cm_distance > 0) && (micros() > _max_time)) {
|
||||
_errorState = STATUS_MAX_DISTANCE_EXCEEDED;
|
||||
return NO_ECHO; // Stop the loop and return NO_ECHO (false) if we're beyond the set maximum distance.
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
_errorState = STATUS_MEASUREMENT_VALID;
|
||||
return (micros() - (_max_time - _maxEchoTime) - PING_OVERHEAD); // Calculate ping time, include overhead.
|
||||
}
|
||||
|
||||
@@ -144,15 +152,39 @@ boolean NewPingESP8266::ping_trigger() {
|
||||
#endif
|
||||
|
||||
#if URM37_ENABLED == true
|
||||
if (!(*_echoInput & _echoBit)) return false; // Previous ping hasn't finished, abort.
|
||||
if (!(*_echoInput & _echoBit)) { // Previous ping hasn't finished, abort.{
|
||||
_errorState = STATUS_ECHO_STATE_ERROR;
|
||||
return false;
|
||||
}
|
||||
_max_time = micros() + _maxEchoTime + MAX_SENSOR_DELAY; // Maximum time we'll wait for ping to start (most sensors are <450uS, the SRF06 can take up to 34,300uS!)
|
||||
while (*_echoInput & _echoBit) // Wait for ping to start.
|
||||
if (micros() > _max_time) return false; // Took too long to start, abort.
|
||||
{
|
||||
if (millis() > (start + 50)) {
|
||||
_errorState = STATUS_ECHO_START_TIMEOUT_50ms;
|
||||
return false;
|
||||
}
|
||||
if ((_max_cm_distance > 0) && (micros() > _max_time)) { // check max. distance if != 0 cm
|
||||
_errorState = STATUS_ECHO_START_TIMEOUT_DISTANCE;
|
||||
return false; // echo too late, max distance exceeded
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (*_echoInput & _echoBit) return false; // Previous ping hasn't finished, abort.
|
||||
if (*_echoInput & _echoBit) { // Previous ping hasn't finished, abort.
|
||||
_errorState = STATUS_ECHO_STATE_ERROR;
|
||||
return false;
|
||||
}
|
||||
_max_time = micros() + _maxEchoTime + MAX_SENSOR_DELAY; // Maximum time we'll wait for ping to start (most sensors are <450uS, the SRF06 can take up to 34,300uS!)
|
||||
while (!(*_echoInput & _echoBit)) // Wait for ping to start.
|
||||
if (micros() > _max_time) return false; // Took too long to start, abort.
|
||||
{
|
||||
if (millis() > (start + 50)) {
|
||||
_errorState = STATUS_ECHO_START_TIMEOUT_50ms;
|
||||
return false;
|
||||
}
|
||||
if ((_max_cm_distance > 0) && (micros() > _max_time)) { // check max. distance if != 0 cm
|
||||
_errorState = STATUS_ECHO_START_TIMEOUT_DISTANCE;
|
||||
return false; // echo too late, max distance exceeded
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
#if ONE_PIN_ENABLED == true
|
||||
@@ -170,30 +202,51 @@ boolean NewPingESP8266::ping_trigger() {
|
||||
#endif
|
||||
|
||||
#if URM37_ENABLED == true
|
||||
if (!digitalRead(_echoPin)) return false; // Previous ping hasn't finished, abort.
|
||||
if (!digitalRead(_echoPin)) {
|
||||
_errorState = STATUS_ECHO_STATE_ERROR;
|
||||
return false; // Previous ping hasn't finished, abort.
|
||||
}
|
||||
_max_time = micros() + _maxEchoTime + MAX_SENSOR_DELAY; // Maximum time we'll wait for ping to start (most sensors are <450uS, the SRF06 can take up to 34,300uS!)
|
||||
while (digitalRead(_echoPin)) // Wait for ping to start.
|
||||
{
|
||||
if (millis() > (start + 50)) return false;
|
||||
if (micros() > _max_time) return false; // Took too long to start, abort.
|
||||
if (millis() > (start + 50)) {
|
||||
_errorState = STATUS_ECHO_START_TIMEOUT_50ms;
|
||||
return false;
|
||||
}
|
||||
if ((_max_cm_distance > 0) && (micros() > _max_time)) { // check max. distance if != 0 cm
|
||||
_errorState = STATUS_ECHO_START_TIMEOUT_DISTANCE;
|
||||
return false; // echo too late, max distance exceeded
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (digitalRead(_echoPin)) return false; // Previous ping hasn't finished, abort.
|
||||
if (digitalRead(_echoPin)) {
|
||||
_errorState = STATUS_ECHO_STATE_ERROR;
|
||||
return false; // Previous ping hasn't finished, abort.
|
||||
}
|
||||
_max_time = micros() + _maxEchoTime + MAX_SENSOR_DELAY; // Maximum time we'll wait for ping to start (most sensors are <450uS, the SRF06 can take up to 34,300uS!)
|
||||
while (!digitalRead(_echoPin)) // Wait for ping to start.
|
||||
{
|
||||
if (millis() > (start + 50)) return false;
|
||||
if (micros() > _max_time) return false; // Took too long to start, abort.
|
||||
if (millis() > (start + 50)) {
|
||||
_errorState = STATUS_ECHO_START_TIMEOUT_50ms;
|
||||
return false;
|
||||
}
|
||||
if ((_max_cm_distance > 0) && (micros() > _max_time)) { // check max. distance if != 0 cm
|
||||
_errorState = STATUS_ECHO_START_TIMEOUT_DISTANCE;
|
||||
return false; // echo too late, max distance exceeded
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
_max_time = micros() + _maxEchoTime; // Ping started, set the time-out.
|
||||
_errorState = STATUS_ECHO_TRIGGERED;
|
||||
|
||||
return true; // Ping started successfully.
|
||||
}
|
||||
|
||||
|
||||
void NewPingESP8266::set_max_distance(unsigned int max_cm_distance) {
|
||||
_max_cm_distance = max_cm_distance;
|
||||
#if ROUNDING_ENABLED == false
|
||||
_maxEchoTime = min(max_cm_distance + 1, (unsigned int) MAX_SENSOR_DISTANCE + 1) * US_ROUNDTRIP_CM; // Calculate the maximum distance in uS (no rounding).
|
||||
#else
|
||||
@@ -222,3 +275,12 @@ unsigned int NewPingESP8266::convert_in(unsigned int echoTime) {
|
||||
return NewPingESP8266Convert(echoTime, US_ROUNDTRIP_IN); // Convert uS to inches.
|
||||
#endif
|
||||
}
|
||||
|
||||
float NewPingESP8266::convert_cm_F(unsigned int echoTime) {
|
||||
return ((float)echoTime / US_ROUNDTRIP_CM); // Convert uS to centimeters (no rounding).
|
||||
}
|
||||
|
||||
|
||||
float NewPingESP8266::convert_in_F(unsigned int echoTime) {
|
||||
return ((float)echoTime / US_ROUNDTRIP_IN); // Convert uS to inches (no rounding).
|
||||
}
|
||||
|
||||
@@ -194,15 +194,29 @@
|
||||
|
||||
class NewPingESP8266 {
|
||||
public:
|
||||
enum errorState {
|
||||
STATUS_SENSOR_READY, // no error, no measruement started
|
||||
STATUS_MEASUREMENT_VALID, // no errors
|
||||
STATUS_ECHO_TRIGGERED, // echo triggered, intermediate state
|
||||
STATUS_MAX_DISTANCE_EXCEEDED, // echo too late, maximum distance exceeded
|
||||
STATUS_ECHO_START_TIMEOUT_50ms, // no echo start signal after 50 ms
|
||||
STATUS_ECHO_START_TIMEOUT_DISTANCE, // no echo start signal after max. distance
|
||||
STATUS_ECHO_STATE_ERROR // echopin level not low after triggered
|
||||
};
|
||||
|
||||
NewPingESP8266(uint32_t trigger_pin, uint32_t echo_pin, unsigned int max_cm_distance = MAX_SENSOR_DISTANCE);
|
||||
~NewPingESP8266() { };
|
||||
unsigned int ping(unsigned int max_cm_distance = 0);
|
||||
unsigned long ping_cm(unsigned int max_cm_distance = 0);
|
||||
unsigned long ping_in(unsigned int max_cm_distance = 0);
|
||||
unsigned long ping_median(uint32_t it = 5, unsigned int max_cm_distance = 0);
|
||||
static unsigned int convert_cm(unsigned int echoTime);
|
||||
static unsigned int convert_in(unsigned int echoTime);
|
||||
static float convert_cm_F(unsigned int echoTime);
|
||||
static float convert_in_F(unsigned int echoTime);
|
||||
|
||||
unsigned int getMaxEchoTime() { return _maxEchoTime; }
|
||||
unsigned int getMaxEchoTime() { return _maxEchoTime; };
|
||||
errorState getErrorState() { return _errorState; };
|
||||
private:
|
||||
boolean ping_trigger();
|
||||
void set_max_distance(unsigned int max_cm_distance);
|
||||
@@ -218,6 +232,8 @@ class NewPingESP8266 {
|
||||
#endif
|
||||
unsigned int _maxEchoTime;
|
||||
unsigned long _max_time;
|
||||
errorState _errorState;
|
||||
unsigned int _max_cm_distance;
|
||||
};
|
||||
|
||||
|
||||
|
||||
+31
-10
@@ -106,7 +106,9 @@ monitor_speed = 115200
|
||||
; -DVTABLES_IN_IRAM
|
||||
; NO_EXTRA_4K_HEAP - this forces the default NONOS-SDK user's heap location
|
||||
; Default currently overlaps cont stack (Arduino) with sys stack (System)
|
||||
; to save up-to 4 kB of heap.
|
||||
; to save up-to 4 kB of heap. (starting core_2.4.2)
|
||||
; ESP8266_DISABLE_EXTRA4K - Calls disable_extra4k_at_link_time() from setup
|
||||
; to force the linker keep user's stack in user ram.
|
||||
; CONT_STACKSIZE to set the 'cont' (Arduino) stack size. Default = 4096
|
||||
|
||||
[common]
|
||||
@@ -115,7 +117,7 @@ build_unflags =
|
||||
build_flags = -D BUILD_GIT='"${sysenv.TRAVIS_TAG}"'
|
||||
-D NDEBUG
|
||||
-lstdc++ -lsupc++
|
||||
-DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY
|
||||
-DPIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH
|
||||
-DVTABLES_IN_FLASH
|
||||
|
||||
|
||||
@@ -126,20 +128,20 @@ lib_archive = false
|
||||
upload_speed = 460800
|
||||
framework = arduino
|
||||
board = esp12e
|
||||
platform = ${core_2_4_2.platform}
|
||||
platform = ${core_2_4_1.platform}
|
||||
monitor_speed = 115200
|
||||
|
||||
[normal]
|
||||
platform = ${common.platform}
|
||||
build_flags = -DNO_EXTRA_4K_HEAP -DCONT_STACKSIZE=5120
|
||||
build_flags =
|
||||
|
||||
[testing]
|
||||
platform = ${core_2_4_2.platform}
|
||||
build_flags = -DNO_EXTRA_4K_HEAP -DPLUGIN_BUILD_TESTING
|
||||
platform = ${core_2_4_1.platform}
|
||||
build_flags = -DPLUGIN_BUILD_TESTING
|
||||
|
||||
[dev]
|
||||
platform = ${core_2_4_2.platform}
|
||||
build_flags = -DNO_EXTRA_4K_HEAP -DPLUGIN_BUILD_DEV
|
||||
platform = ${core_2_4_1.platform}
|
||||
build_flags = -DPLUGIN_BUILD_DEV
|
||||
|
||||
[ir]
|
||||
lib_ignore = ESP32_ping, ESP32WebServer
|
||||
@@ -167,7 +169,7 @@ board_build.flash_mode = ${esp8266_1M.board_build.flash_mode}
|
||||
board_build.f_cpu = ${esp8266_1M.board_build.f_cpu}
|
||||
build_unflags = ${common.build_unflags}
|
||||
build_flags = ${common.build_flags} -Wl,-Tesp8266.flash.1m128.ld
|
||||
platform = ${core_2_4_2.platform}
|
||||
platform = ${core_2_4_1.platform}
|
||||
|
||||
[Sonoff_8285]
|
||||
board_upload.maximum_size = ${esp8285_1M.board_upload.maximum_size}
|
||||
@@ -176,7 +178,7 @@ board_build.f_cpu = ${esp8285_1M.board_build.f_cpu}
|
||||
board = ${esp8285_1M.board}
|
||||
build_unflags = ${esp8285_1M.build_unflags}
|
||||
build_flags = ${esp8285_1M.build_flags}
|
||||
platform = ${core_2_4_2.platform}
|
||||
platform = ${core_2_4_1.platform}
|
||||
|
||||
[espWroom2M]
|
||||
board_build.flash_mode = dout
|
||||
@@ -202,6 +204,25 @@ build_flags = ${common.build_flags} -Wl,-Tesp8266.flash.4m1m.ld
|
||||
; Will probably not work, not tested and guaranteed to take a few hours time of some ;
|
||||
; still trying to build the version without reading this warning. ;
|
||||
; *********************************************************************
|
||||
[env:esp-wrover-kit_test_1M8_partition]
|
||||
platform = ${core_esp32.platform}
|
||||
board = esp-wrover-kit
|
||||
build_unflags = ${core_esp32.build_unflags}
|
||||
build_flags = ${core_esp32.build_flags} -DPLUGIN_SET_TEST_ESP32
|
||||
lib_deps = ${core_esp32.lib_deps}
|
||||
lib_ignore = ${core_esp32.lib_ignore}
|
||||
lib_ldf_mode = ${common.lib_ldf_mode}
|
||||
lib_archive = ${common.lib_archive}
|
||||
framework = ${common.framework}
|
||||
upload_speed = ${common.upload_speed}
|
||||
upload_protocol = ftdi
|
||||
debug_tool = ftdi
|
||||
monitor_speed = ${common.monitor_speed}
|
||||
board_build.partitions = esp32_partition_app1810k_spiffs316k.csv
|
||||
board_upload.maximum_size = 1900544
|
||||
debug_extra_cmds = break Misc.ino:3011
|
||||
|
||||
|
||||
[env:esp32dev]
|
||||
platform = ${core_esp32.platform}
|
||||
board = esp32dev
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Check for documentation only changes.
|
||||
# Source: https://github.com/dev-id/Magic-Spoiler/blob/8111a06ab6682e020169991d5e2aa4fa503d787f/preflight.sh
|
||||
|
||||
set -e
|
||||
MAIN_BRANCH="mega"
|
||||
MD=".md$"
|
||||
DOCS="^docs/"
|
||||
|
||||
CHANGED_FILES=`git diff --name-only ${MAIN_BRANCH}...${TRAVIS_COMMIT}`
|
||||
ONLY_READMES=True
|
||||
DOCUMENTATION_CHANGED=False
|
||||
|
||||
for CHANGED_FILE in $CHANGED_FILES; do
|
||||
if ! [[ $CHANGED_FILE =~ $MD || $CHANGED_FILE =~ $DOCS ]]; then
|
||||
ONLY_READMES=False
|
||||
# break
|
||||
else
|
||||
DOCUMENTATION_CHANGED=True
|
||||
fi
|
||||
done
|
||||
|
||||
#if [[ $ONLY_READMES == True ]]; then
|
||||
# echo "Only documentation files found, exiting."
|
||||
# travis_terminate 0
|
||||
# exit 1
|
||||
#else
|
||||
# echo "Non-documentation files found, continuing with build."
|
||||
#fi
|
||||
|
||||
if [[ $DOCUMENTATION_CHANGED == True ]]; then
|
||||
echo "Generate documentation."
|
||||
cd docs
|
||||
make html
|
||||
fi
|
||||
+2
-1
@@ -131,7 +131,8 @@ String doExecuteCommand(const char * cmd, struct EventStruct *event, const char*
|
||||
COMMAND_CASE("taskclear" , Command_Task_Clear); // Tasks.h
|
||||
COMMAND_CASE("taskclearall" , Command_Task_ClearAll); // Tasks.h
|
||||
COMMAND_CASE("taskrun" , Command_Task_Run); // Tasks.h
|
||||
COMMAND_CASE("taskvalueset" , Command_Task_ValueSet); // Tasks.h
|
||||
COMMAND_CASE("taskvalueset" , Command_Task_ValueSet); // Tasks.h
|
||||
COMMAND_CASE("taskvaluetoggle" , Command_Task_ValueToggle); // Tasks.h
|
||||
COMMAND_CASE("taskvaluesetandrun" , Command_Task_ValueSetAndRun); // Tasks.h
|
||||
COMMAND_CASE("timerpause" , Command_Timer_Pause); // Timers.h
|
||||
COMMAND_CASE("timerresume" , Command_Timer_Resume); // Timers.h
|
||||
|
||||
@@ -30,6 +30,15 @@ String Command_Task_ValueSet(struct EventStruct *event, const char* Line)
|
||||
return return_command_success();
|
||||
}
|
||||
|
||||
String Command_Task_ValueToggle(struct EventStruct *event, const char* Line)
|
||||
{
|
||||
const int result = round(UserVar[(VARS_PER_TASK * (event->Par1 - 1)) + event->Par2 - 1]);
|
||||
if (result == 0 || result == 1) {
|
||||
UserVar[(VARS_PER_TASK * (event->Par1 - 1)) + event->Par2 - 1] = !result;
|
||||
}
|
||||
return return_command_success();
|
||||
}
|
||||
|
||||
String Command_Task_ValueSetAndRun(struct EventStruct *event, const char* Line)
|
||||
{
|
||||
char TmpStr1[INPUT_COMMAND_SIZE];
|
||||
|
||||
@@ -141,6 +141,7 @@ bool MQTTConnect(int controller_idx)
|
||||
updateMQTTclient_connected();
|
||||
}
|
||||
mqtt = WiFiClient(); // workaround see: https://github.com/esp8266/Arduino/issues/4497#issuecomment-373023864
|
||||
mqtt.setTimeout(ControllerSettings.ClientTimeout);
|
||||
if (ControllerSettings.UseDNS) {
|
||||
MQTTclient.setServer(ControllerSettings.getHost().c_str(), ControllerSettings.Port);
|
||||
} else {
|
||||
|
||||
+15
-5
@@ -191,6 +191,8 @@
|
||||
|
||||
#define MAX_FLASHWRITES_PER_DAY 100 // per 24 hour window
|
||||
#define INPUT_COMMAND_SIZE 240 // Affects maximum command length in rules and other commands
|
||||
// FIXME TD-er: INPUT_COMMAND_SIZE is also used in commands where simply a check for valid parameter is needed
|
||||
// and some may need less memory. (which is stack allocated)
|
||||
|
||||
#define NODE_TYPE_ID_ESP_EASY_STD 1
|
||||
#define NODE_TYPE_ID_ESP_EASYM_STD 17
|
||||
@@ -226,6 +228,9 @@
|
||||
// N.B. Retries without a connection to wifi do not count as retry.
|
||||
#define CONTROLLER_DELAY_QUEUE_RETRY_MAX 10
|
||||
#define CONTROLLER_DELAY_QUEUE_RETRY_DFLT 10
|
||||
// Timeout of the client in msec.
|
||||
#define CONTROLLER_CLIENTTIMEOUT_MAX 1000
|
||||
#define CONTROLLER_CLIENTTIMEOUT_DFLT 100
|
||||
|
||||
|
||||
#define PLUGIN_INIT_ALL 1
|
||||
@@ -895,7 +900,7 @@ SettingsStruct& Settings = *SettingsStruct_ptr;
|
||||
struct ControllerSettingsStruct
|
||||
{
|
||||
ControllerSettingsStruct() : UseDNS(false), Port(0),
|
||||
MinimalTimeBetweenMessages(100), MaxQueueDepth(10), MaxRetry(10), DeleteOldest(false) {
|
||||
MinimalTimeBetweenMessages(100), MaxQueueDepth(10), MaxRetry(10), DeleteOldest(false), ClientTimeout(100) {
|
||||
for (byte i = 0; i < 4; ++i) {
|
||||
IP[i] = 0;
|
||||
}
|
||||
@@ -919,13 +924,16 @@ struct ControllerSettingsStruct
|
||||
unsigned int MaxQueueDepth;
|
||||
unsigned int MaxRetry;
|
||||
boolean DeleteOldest; // Action to perform when buffer full, delete oldest, or ignore newest.
|
||||
unsigned int ClientTimeout;
|
||||
|
||||
void validate() {
|
||||
if (Port > 65535) Port = 0;
|
||||
if (MinimalTimeBetweenMessages < 1) MinimalTimeBetweenMessages = 100;
|
||||
if (MinimalTimeBetweenMessages > 3600000) MinimalTimeBetweenMessages = 100;
|
||||
if (MaxQueueDepth > 25) MaxQueueDepth = 10;
|
||||
if (MaxRetry > 10) MaxRetry = 10;
|
||||
if (MinimalTimeBetweenMessages < 1 || MinimalTimeBetweenMessages > CONTROLLER_DELAY_QUEUE_DELAY_MAX)
|
||||
MinimalTimeBetweenMessages = CONTROLLER_DELAY_QUEUE_DELAY_DFLT;
|
||||
if (MaxQueueDepth > CONTROLLER_DELAY_QUEUE_DEPTH_MAX) MaxQueueDepth = CONTROLLER_DELAY_QUEUE_DEPTH_DFLT;
|
||||
if (MaxRetry > CONTROLLER_DELAY_QUEUE_RETRY_MAX) MaxRetry = CONTROLLER_DELAY_QUEUE_RETRY_MAX;
|
||||
if (ClientTimeout < 10 || ClientTimeout > CONTROLLER_CLIENTTIMEOUT_MAX)
|
||||
ClientTimeout = CONTROLLER_CLIENTTIMEOUT_DFLT;
|
||||
}
|
||||
|
||||
IPAddress getIP() const {
|
||||
@@ -949,6 +957,7 @@ struct ControllerSettingsStruct
|
||||
if (!WiFiConnected(10)) {
|
||||
return false; // Not connected, so no use in wasting time to connect to a host.
|
||||
}
|
||||
delay(1); // Make sure the Watchdog will not trigger a reset.
|
||||
if (quick && ipSet()) return true;
|
||||
if (UseDNS) {
|
||||
if (!updateIPcache()) {
|
||||
@@ -1487,6 +1496,7 @@ unsigned long connectionFailures = 0;
|
||||
unsigned long wdcounter = 0;
|
||||
unsigned long timerAPoff = 0;
|
||||
unsigned long timerAwakeFromDeepSleep = 0;
|
||||
unsigned long last_system_event_run = 0;
|
||||
|
||||
#if FEATURE_ADC_VCC
|
||||
float vcc = -1.0;
|
||||
|
||||
@@ -106,6 +106,9 @@ int firstEnabledBlynkController() {
|
||||
\*********************************************************************************************/
|
||||
void setup()
|
||||
{
|
||||
#ifdef ESP8266_DISABLE_EXTRA4K
|
||||
disable_extra4k_at_link_time();
|
||||
#endif
|
||||
WiFi.persistent(false); // Do not use SDK storage of SSID/WPA parameters
|
||||
WiFi.setAutoReconnect(false);
|
||||
setWifiMode(WIFI_OFF);
|
||||
|
||||
+41
-23
@@ -113,7 +113,7 @@ void fileSystemCheck()
|
||||
{
|
||||
ResetFactory();
|
||||
}
|
||||
f.close();
|
||||
if (f) f.close();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -518,13 +518,15 @@ String InitFile(const char* fname, int datasize)
|
||||
FLASH_GUARD();
|
||||
|
||||
fs::File f = SPIFFS.open(fname, "w");
|
||||
SPIFFS_CHECK(f, fname);
|
||||
if (f) {
|
||||
SPIFFS_CHECK(f, fname);
|
||||
|
||||
for (int x = 0; x < datasize ; x++)
|
||||
{
|
||||
SPIFFS_CHECK(f.write(0), fname);
|
||||
for (int x = 0; x < datasize ; x++)
|
||||
{
|
||||
SPIFFS_CHECK(f.write(0), fname);
|
||||
}
|
||||
f.close();
|
||||
}
|
||||
f.close();
|
||||
|
||||
//OK
|
||||
return String();
|
||||
@@ -556,19 +558,27 @@ String SaveToFile(char* fname, int index, byte* memAddress, int datasize)
|
||||
FLASH_GUARD();
|
||||
|
||||
fs::File f = SPIFFS.open(fname, "r+");
|
||||
SPIFFS_CHECK(f, fname);
|
||||
if (f) {
|
||||
SPIFFS_CHECK(f, fname);
|
||||
|
||||
SPIFFS_CHECK(f.seek(index, fs::SeekSet), fname);
|
||||
byte *pointerToByteToSave = memAddress;
|
||||
for (int x = 0; x < datasize ; x++)
|
||||
{
|
||||
SPIFFS_CHECK(f.write(*pointerToByteToSave), fname);
|
||||
pointerToByteToSave++;
|
||||
SPIFFS_CHECK(f.seek(index, fs::SeekSet), fname);
|
||||
byte *pointerToByteToSave = memAddress;
|
||||
for (int x = 0; x < datasize ; x++)
|
||||
{
|
||||
SPIFFS_CHECK(f.write(*pointerToByteToSave), fname);
|
||||
pointerToByteToSave++;
|
||||
}
|
||||
f.close();
|
||||
String log = F("FILE : Saved ");
|
||||
log=log+fname;
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
} else {
|
||||
String log = F("SaveToFile: ");
|
||||
log += fname;
|
||||
log += F(" ERROR, Cannot save to file");
|
||||
addLog(LOG_LEVEL_ERROR, log);
|
||||
return log;
|
||||
}
|
||||
f.close();
|
||||
String log = F("FILE : Saved ");
|
||||
log=log+fname;
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
|
||||
//OK
|
||||
return String();
|
||||
@@ -591,14 +601,22 @@ String ClearInFile(char* fname, int index, int datasize)
|
||||
FLASH_GUARD();
|
||||
|
||||
fs::File f = SPIFFS.open(fname, "r+");
|
||||
SPIFFS_CHECK(f, fname);
|
||||
if (f) {
|
||||
SPIFFS_CHECK(f, fname);
|
||||
|
||||
SPIFFS_CHECK(f.seek(index, fs::SeekSet), fname);
|
||||
for (int x = 0; x < datasize ; x++)
|
||||
{
|
||||
SPIFFS_CHECK(f.write(0), fname);
|
||||
SPIFFS_CHECK(f.seek(index, fs::SeekSet), fname);
|
||||
for (int x = 0; x < datasize ; x++)
|
||||
{
|
||||
SPIFFS_CHECK(f.write(0), fname);
|
||||
}
|
||||
f.close();
|
||||
} else {
|
||||
String log = F("ClearInFile: ");
|
||||
log += fname;
|
||||
log += F(" ERROR, Cannot save to file");
|
||||
addLog(LOG_LEVEL_ERROR, log);
|
||||
return log;
|
||||
}
|
||||
f.close();
|
||||
|
||||
//OK
|
||||
return String();
|
||||
|
||||
@@ -678,6 +678,7 @@ void WifiScan()
|
||||
|
||||
String formatScanResult(int i, const String& separator) {
|
||||
String result = WiFi.SSID(i);
|
||||
htmlEscape(result);
|
||||
#ifndef ESP32
|
||||
if (WiFi.isHidden(i)) {
|
||||
result += F("#Hidden#");
|
||||
|
||||
+16
-19
@@ -445,23 +445,19 @@ void delayBackground(unsigned long delay)
|
||||
void parseCommandString(struct EventStruct *event, const String& string)
|
||||
{
|
||||
checkRAM(F("parseCommandString"));
|
||||
char command[INPUT_COMMAND_SIZE];
|
||||
command[0] = 0;
|
||||
char TmpStr1[INPUT_COMMAND_SIZE];
|
||||
TmpStr1[0] = 0;
|
||||
|
||||
string.toCharArray(command, INPUT_COMMAND_SIZE);
|
||||
event->Par1 = 0;
|
||||
event->Par2 = 0;
|
||||
event->Par3 = 0;
|
||||
event->Par4 = 0;
|
||||
event->Par5 = 0;
|
||||
|
||||
if (GetArgv(command, TmpStr1, 2)) event->Par1 = CalculateParam(TmpStr1);
|
||||
if (GetArgv(command, TmpStr1, 3)) event->Par2 = CalculateParam(TmpStr1);
|
||||
if (GetArgv(command, TmpStr1, 4)) event->Par3 = CalculateParam(TmpStr1);
|
||||
if (GetArgv(command, TmpStr1, 5)) event->Par4 = CalculateParam(TmpStr1);
|
||||
if (GetArgv(command, TmpStr1, 6)) event->Par5 = CalculateParam(TmpStr1);
|
||||
if (GetArgv(string.c_str(), TmpStr1, 2)) { event->Par1 = CalculateParam(TmpStr1); }
|
||||
if (GetArgv(string.c_str(), TmpStr1, 3)) { event->Par2 = CalculateParam(TmpStr1); }
|
||||
if (GetArgv(string.c_str(), TmpStr1, 4)) { event->Par3 = CalculateParam(TmpStr1); }
|
||||
if (GetArgv(string.c_str(), TmpStr1, 5)) { event->Par4 = CalculateParam(TmpStr1); }
|
||||
if (GetArgv(string.c_str(), TmpStr1, 6)) { event->Par5 = CalculateParam(TmpStr1); }
|
||||
}
|
||||
|
||||
/********************************************************************************************\
|
||||
@@ -572,15 +568,18 @@ boolean GetArgv(const char *string, char *argv, unsigned int argc) {
|
||||
|
||||
boolean GetArgv(const char *string, char *argv, unsigned int argv_size, unsigned int argc)
|
||||
{
|
||||
size_t string_len = strlen(string);
|
||||
unsigned int string_pos = 0, argv_pos = 0, argc_pos = 0;
|
||||
char c, d;
|
||||
boolean parenthesis = false;
|
||||
char matching_parenthesis = '"';
|
||||
|
||||
while (string_pos < strlen(string))
|
||||
while (string_pos < string_len)
|
||||
{
|
||||
c = string[string_pos];
|
||||
d = string[string_pos + 1];
|
||||
d = 0;
|
||||
if ((string_pos + 1) < string_len)
|
||||
d = string[string_pos + 1];
|
||||
|
||||
if (!parenthesis && c == ' ' && d == ' ') {}
|
||||
else if (!parenthesis && c == ' ' && d == ',') {}
|
||||
@@ -2208,7 +2207,7 @@ void rulesProcessing(String& event)
|
||||
/********************************************************************************************\
|
||||
Rules processing
|
||||
\*********************************************************************************************/
|
||||
String rulesProcessingFile(String fileName, String& event)
|
||||
String rulesProcessingFile(const String& fileName, String& event)
|
||||
{
|
||||
checkRAM(F("rulesProcessingFile"));
|
||||
if (Settings.SerialLogLevel == LOG_LEVEL_DEBUG_DEV){
|
||||
@@ -2271,6 +2270,7 @@ String rulesProcessingFile(String fileName, String& event)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (f) f.close();
|
||||
|
||||
nestingLevel--;
|
||||
checkRAM(F("rulesProcessingFile2"));
|
||||
@@ -2504,19 +2504,16 @@ void processMatchedRule(
|
||||
{
|
||||
String tmpString = event.substring(equalsPos + 1);
|
||||
|
||||
char command[INPUT_COMMAND_SIZE];
|
||||
command[0] = 0;
|
||||
char tmpParam[INPUT_COMMAND_SIZE];
|
||||
tmpParam[0] = 0;
|
||||
tmpString.toCharArray(command, INPUT_COMMAND_SIZE);
|
||||
|
||||
if (GetArgv(command,tmpParam,1)) {
|
||||
if (GetArgv(tmpString.c_str(),tmpParam,1)) {
|
||||
action.replace(F("%eventvalue%"), tmpParam); // for compatibility issues
|
||||
action.replace(F("%eventvalue1%"), tmpParam); // substitute %eventvalue1% in actions with the actual value from the event
|
||||
}
|
||||
if (GetArgv(command,tmpParam,2)) action.replace(F("%eventvalue2%"), tmpParam); // substitute %eventvalue2% in actions with the actual value from the event
|
||||
if (GetArgv(command,tmpParam,3)) action.replace(F("%eventvalue3%"), tmpParam); // substitute %eventvalue3% in actions with the actual value from the event
|
||||
if (GetArgv(command,tmpParam,4)) action.replace(F("%eventvalue4%"), tmpParam); // substitute %eventvalue4% in actions with the actual value from the event
|
||||
if (GetArgv(tmpString.c_str(),tmpParam,2)) action.replace(F("%eventvalue2%"), tmpParam); // substitute %eventvalue2% in actions with the actual value from the event
|
||||
if (GetArgv(tmpString.c_str(),tmpParam,3)) action.replace(F("%eventvalue3%"), tmpParam); // substitute %eventvalue3% in actions with the actual value from the event
|
||||
if (GetArgv(tmpString.c_str(),tmpParam,4)) action.replace(F("%eventvalue4%"), tmpParam); // substitute %eventvalue4% in actions with the actual value from the event
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+8
-1
@@ -41,19 +41,26 @@ unsigned long getMixedId(unsigned long timerType, unsigned long id) {
|
||||
\*********************************************************************************************/
|
||||
void handle_schedule() {
|
||||
unsigned long timer;
|
||||
const unsigned long mixed_id = msecTimerHandler.getNextId(timer);
|
||||
unsigned long mixed_id = 0;
|
||||
if (timePassedSince(last_system_event_run) < 500) {
|
||||
// Make sure system event queue will be looked at every now and then.
|
||||
mixed_id = msecTimerHandler.getNextId(timer);
|
||||
}
|
||||
if (mixed_id == 0) {
|
||||
// No id ready to run right now.
|
||||
// Events are not that important to run immediately.
|
||||
// Make sure normal scheduled jobs run at higher priority.
|
||||
backgroundtasks();
|
||||
process_system_event_queue();
|
||||
last_system_event_run = millis();
|
||||
return;
|
||||
}
|
||||
const unsigned long timerType = (mixed_id >> TIMER_ID_SHIFT);
|
||||
const unsigned long mask = (1 << TIMER_ID_SHIFT) -1;
|
||||
const unsigned long id = mixed_id & mask;
|
||||
|
||||
yield(); // See: https://github.com/letscontrolit/ESPEasy/issues/1818#issuecomment-425351328
|
||||
|
||||
switch (timerType) {
|
||||
case CONST_INTERVAL_TIMER:
|
||||
process_interval_timer(id, timer);
|
||||
|
||||
+62
-28
@@ -131,7 +131,7 @@ String toString(float value, byte decimals)
|
||||
|
||||
String toString(WiFiMode_t mode)
|
||||
{
|
||||
String result = F("Undefinited");
|
||||
String result = F("Undefined");
|
||||
switch (mode)
|
||||
{
|
||||
case WIFI_OFF:
|
||||
@@ -165,11 +165,13 @@ String doFormatUserVar(byte TaskIndex, byte rel_index, bool mustCheck, bool& isv
|
||||
const byte DeviceIndex = getDeviceIndex(Settings.TaskDeviceNumber[TaskIndex]);
|
||||
if (Device[DeviceIndex].ValueCount <= rel_index) {
|
||||
isvalid = false;
|
||||
String log = F("No sensor value for TaskIndex: ");
|
||||
log += TaskIndex;
|
||||
log += F(" varnumber: ");
|
||||
log += rel_index;
|
||||
addLog(LOG_LEVEL_ERROR, log);
|
||||
if (loglevelActiveFor(LOG_LEVEL_ERROR)) {
|
||||
String log = F("No sensor value for TaskIndex: ");
|
||||
log += TaskIndex;
|
||||
log += F(" varnumber: ");
|
||||
log += rel_index;
|
||||
addLog(LOG_LEVEL_ERROR, log);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
if (Device[DeviceIndex].VType == SENSOR_TYPE_LONG) {
|
||||
@@ -178,11 +180,13 @@ String doFormatUserVar(byte TaskIndex, byte rel_index, bool mustCheck, bool& isv
|
||||
float f(UserVar[BaseVarIndex + rel_index]);
|
||||
if (mustCheck && !isValidFloat(f)) {
|
||||
isvalid = false;
|
||||
String log = F("Invalid float value for TaskIndex: ");
|
||||
log += TaskIndex;
|
||||
log += F(" varnumber: ");
|
||||
log += rel_index;
|
||||
addLog(LOG_LEVEL_DEBUG, log);
|
||||
if (loglevelActiveFor(LOG_LEVEL_DEBUG)) {
|
||||
String log = F("Invalid float value for TaskIndex: ");
|
||||
log += TaskIndex;
|
||||
log += F(" varnumber: ");
|
||||
log += rel_index;
|
||||
addLog(LOG_LEVEL_DEBUG, log);
|
||||
}
|
||||
f = 0;
|
||||
}
|
||||
return toString(f, ExtraTaskSettings.TaskDeviceValueDecimals[rel_index]);
|
||||
@@ -210,13 +214,11 @@ String formatUserVar(struct EventStruct *event, byte rel_index, bool& isvalid)
|
||||
/*********************************************************************************************\
|
||||
Wrap a string with given pre- and postfix string.
|
||||
\*********************************************************************************************/
|
||||
String wrap_String(const String& string, const String& wrap) {
|
||||
String result;
|
||||
result.reserve(string.length() + 2* wrap.length());
|
||||
result = wrap;
|
||||
|
||||
void wrap_String(const String& string, const String& wrap, String& result) {
|
||||
result += wrap;
|
||||
result += string;
|
||||
result += wrap;
|
||||
return result;
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
@@ -225,19 +227,25 @@ String wrap_String(const String& string, const String& wrap) {
|
||||
String to_json_object_value(const String& object, const String& value) {
|
||||
String result;
|
||||
result.reserve(object.length() + value.length() + 6);
|
||||
result = wrap_String(object, F("\""));
|
||||
wrap_String(object, F("\""), result);
|
||||
result += F(":");
|
||||
if (value.length() == 0 || !isFloat(value)) {
|
||||
if (value.indexOf('\n') == -1 && value.indexOf('"') == -1 && value.indexOf(F("Pragma")) == -1) {
|
||||
result += wrap_String(value, F("\""));
|
||||
} else {
|
||||
if (value.length() == 0) {
|
||||
// Empty string
|
||||
result += F("\"\"");
|
||||
} else if (!isFloat(value)) {
|
||||
// Is not a numerical value, thus wrap with quotes
|
||||
if (value.indexOf('\n') != -1 || value.indexOf('\r') != -1 || value.indexOf('"') != -1) {
|
||||
// Must replace characters, so make a deepcopy
|
||||
String tmpValue(value);
|
||||
tmpValue.replace('\n', '^');
|
||||
tmpValue.replace('\r', '^');
|
||||
tmpValue.replace('"', '\'');
|
||||
tmpValue.replace(F("Pragma"), F("Bugje!"));
|
||||
result += wrap_String(tmpValue, F("\""));
|
||||
wrap_String(tmpValue, F("\""), result);
|
||||
} else {
|
||||
wrap_String(value, F("\""), result);
|
||||
}
|
||||
} else {
|
||||
// It is a numerical
|
||||
result += value;
|
||||
}
|
||||
return result;
|
||||
@@ -373,8 +381,32 @@ void htmlEscape(String & html)
|
||||
html.replace("'", F("'"));
|
||||
html.replace("<", F("<"));
|
||||
html.replace(">", F(">"));
|
||||
html.replace("/", F("/"));
|
||||
}
|
||||
|
||||
void htmlStrongEscape(String & html)
|
||||
{
|
||||
String escaped;
|
||||
escaped.reserve(html.length());
|
||||
for (unsigned i = 0; i < html.length(); ++i)
|
||||
{
|
||||
if ((html[i] >= 'a' && html[i] <= 'z') || (html[i] >= 'A' && html[i] <= 'Z') || (html[i] >= '0' && html[i] <= '9'))
|
||||
{
|
||||
escaped += html[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
char s [4];
|
||||
sprintf(s, "%03d", static_cast<int>(html[i]));
|
||||
escaped += "&#";
|
||||
escaped += s;
|
||||
escaped += ";";
|
||||
}
|
||||
}
|
||||
html = escaped;
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************************************\
|
||||
replace other system variables like %sysname%, %systime%, %ip%
|
||||
\*********************************************************************************************/
|
||||
@@ -546,11 +578,13 @@ String getReplacementString(const String& format, String& s) {
|
||||
int startpos = s.indexOf(format);
|
||||
int endpos = s.indexOf('%', startpos + 1);
|
||||
String R = s.substring(startpos, endpos + 1);
|
||||
String log = F("ReplacementString SunTime: ");
|
||||
log += R;
|
||||
log += F(" offset: ");
|
||||
log += getSecOffset(R);
|
||||
addLog(LOG_LEVEL_DEBUG, log);
|
||||
if (loglevelActiveFor(LOG_LEVEL_DEBUG)) {
|
||||
String log = F("ReplacementString SunTime: ");
|
||||
log += R;
|
||||
log += F(" offset: ");
|
||||
log += getSecOffset(R);
|
||||
addLog(LOG_LEVEL_DEBUG, log);
|
||||
}
|
||||
return R;
|
||||
}
|
||||
|
||||
|
||||
+18
-4
@@ -1183,6 +1183,7 @@ void handle_controllers() {
|
||||
const int maxqueuedepth = getFormItemInt(F("maxqueuedepth"), 10);
|
||||
const int maxretry = getFormItemInt(F("maxretry"), 10);
|
||||
String deleteoldest = WebServer.arg(F("deleteoldest"));
|
||||
const int clienttimeout = getFormItemInt(F("clienttimeout"), CONTROLLER_CLIENTTIMEOUT_DFLT);
|
||||
|
||||
|
||||
//submitted data
|
||||
@@ -1201,7 +1202,8 @@ void handle_controllers() {
|
||||
//reset (some) default-settings
|
||||
byte ProtocolIndex = getProtocolIndex(Settings.Protocol[controllerindex]);
|
||||
ControllerSettings.Port = Protocol[ProtocolIndex].defaultPort;
|
||||
ControllerSettings.MinimalTimeBetweenMessages = 100;
|
||||
ControllerSettings.MinimalTimeBetweenMessages = CONTROLLER_DELAY_QUEUE_DELAY_DFLT;
|
||||
ControllerSettings.ClientTimeout = CONTROLLER_CLIENTTIMEOUT_DFLT;
|
||||
// ControllerSettings.MaxQueueDepth = 0;
|
||||
if (Protocol[ProtocolIndex].usesTemplate)
|
||||
CPlugin_ptr[ProtocolIndex](CPLUGIN_PROTOCOL_TEMPLATE, &TempEvent, dummyString);
|
||||
@@ -1266,6 +1268,7 @@ void handle_controllers() {
|
||||
ControllerSettings.MaxQueueDepth = maxqueuedepth;
|
||||
ControllerSettings.MaxRetry = maxretry;
|
||||
ControllerSettings.DeleteOldest = deleteoldest.toInt();
|
||||
ControllerSettings.ClientTimeout = clienttimeout;
|
||||
|
||||
|
||||
CPlugin_ptr[ProtocolIndex](CPLUGIN_INIT, &TempEvent, dummyString);
|
||||
@@ -1373,6 +1376,8 @@ void handle_controllers() {
|
||||
addFormNumericBox( F("Max Queue Depth"), F("maxqueuedepth"), ControllerSettings.MaxQueueDepth, 1, CONTROLLER_DELAY_QUEUE_DEPTH_MAX);
|
||||
addFormNumericBox( F("Max Retries"), F("maxretry"), ControllerSettings.MaxRetry, 1, CONTROLLER_DELAY_QUEUE_RETRY_MAX);
|
||||
addFormSelector(F("Full Queue Action"), F("deleteoldest"), 2, options_delete_oldest, NULL, NULL, choice_delete_oldest, true);
|
||||
addFormNumericBox( F("Client Timeout"), F("clienttimeout"), ControllerSettings.ClientTimeout, 10, CONTROLLER_CLIENTTIMEOUT_MAX);
|
||||
addUnit(F("ms"));
|
||||
|
||||
|
||||
if (Protocol[ProtocolIndex].usesAccount)
|
||||
@@ -3660,6 +3665,7 @@ void handle_control() {
|
||||
}
|
||||
else if (command.equalsIgnoreCase(F("taskrun")) ||
|
||||
command.equalsIgnoreCase(F("taskvalueset")) ||
|
||||
command.equalsIgnoreCase(F("taskvaluetoggle")) ||
|
||||
command.equalsIgnoreCase(F("rules"))) {
|
||||
addLog(LOG_LEVEL_INFO,String(F("HTTP : ")) + webrequest);
|
||||
ExecuteCommand(VALUE_SOURCE_HTTP,webrequest.c_str());
|
||||
@@ -4201,6 +4207,7 @@ void handle_download()
|
||||
|
||||
WebServer.sendHeader(F("Content-Disposition"), str);
|
||||
WebServer.streamFile(dataFile, F("application/octet-stream"));
|
||||
dataFile.close();
|
||||
}
|
||||
|
||||
|
||||
@@ -4624,7 +4631,10 @@ void handle_filelist() {
|
||||
TXBuffer += F("</a>");
|
||||
fs::File f = dir.openFile("r");
|
||||
html_TD();
|
||||
TXBuffer += f.size();
|
||||
if (f) {
|
||||
TXBuffer += f.size();
|
||||
f.close();
|
||||
}
|
||||
if (count >= endIdx)
|
||||
{
|
||||
break;
|
||||
@@ -4982,7 +4992,11 @@ void handle_setup() {
|
||||
{
|
||||
html_TR_TD(); TXBuffer += F("<label class='container2'>");
|
||||
TXBuffer += F("<input type='radio' name='ssid' value='");
|
||||
TXBuffer += WiFi.SSID(i);
|
||||
{
|
||||
String escapeBuffer = WiFi.SSID(i);
|
||||
htmlStrongEscape(escapeBuffer);
|
||||
TXBuffer += escapeBuffer;
|
||||
}
|
||||
TXBuffer += F("'");
|
||||
if (WiFi.SSID(i) == ssid)
|
||||
TXBuffer += F(" checked ");
|
||||
@@ -5121,7 +5135,7 @@ void handle_rules() {
|
||||
log += F(" Create new file: ");
|
||||
log += fileName;
|
||||
fs::File f = SPIFFS.open(fileName, "w");
|
||||
f.close();
|
||||
if (f) f.close();
|
||||
}
|
||||
}
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
|
||||
@@ -382,7 +382,7 @@ bool safeReadStringUntil(Stream &input, String &str, char terminator, unsigned i
|
||||
int c;
|
||||
const unsigned long start = millis();
|
||||
const unsigned long timer = start + timeout;
|
||||
unsigned long backgroundtasks_timer = start + 100;
|
||||
unsigned long backgroundtasks_timer = start + 10;
|
||||
str = "";
|
||||
|
||||
do {
|
||||
@@ -405,7 +405,7 @@ bool safeReadStringUntil(Stream &input, String &str, char terminator, unsigned i
|
||||
}
|
||||
// We must run the backgroundtasks every now and then.
|
||||
if (timeOutReached(backgroundtasks_timer)) {
|
||||
backgroundtasks_timer += 100;
|
||||
backgroundtasks_timer += 10;
|
||||
backgroundtasks();
|
||||
} else {
|
||||
yield();
|
||||
@@ -584,6 +584,7 @@ bool count_connection_results(bool success, const String& prefix, int controller
|
||||
}
|
||||
|
||||
bool try_connect_host(int controller_number, WiFiUDP& client, ControllerSettingsStruct& ControllerSettings) {
|
||||
client.setTimeout(ControllerSettings.ClientTimeout);
|
||||
log_connecting_to(F("UDP : "), controller_number, ControllerSettings);
|
||||
bool success = ControllerSettings.beginPacket(client) != 0;
|
||||
return count_connection_results(
|
||||
@@ -593,6 +594,7 @@ bool try_connect_host(int controller_number, WiFiUDP& client, ControllerSettings
|
||||
|
||||
bool try_connect_host(int controller_number, WiFiClient& client, ControllerSettingsStruct& ControllerSettings) {
|
||||
// Use WiFiClient class to create TCP connections
|
||||
client.setTimeout(ControllerSettings.ClientTimeout);
|
||||
log_connecting_to(F("HTTP : "), controller_number, ControllerSettings);
|
||||
bool success = ControllerSettings.connectToHost(client);
|
||||
return count_connection_results(
|
||||
@@ -613,8 +615,10 @@ bool send_via_http(const String& logIdentifier, WiFiClient& client, const String
|
||||
client.print(postStr);
|
||||
|
||||
unsigned long timer = millis() + 200;
|
||||
while (!client.available() && !timeOutReached(timer))
|
||||
while (!client.available()) {
|
||||
if (timeOutReached(timer)) return false;
|
||||
delay(1);
|
||||
}
|
||||
|
||||
// Read all the lines of the reply from server and print them to Serial
|
||||
while (client_available(client) && !success) {
|
||||
|
||||
@@ -73,6 +73,7 @@ boolean NPlugin_001_send(const NotificationSettingsStruct& notificationsettings,
|
||||
|
||||
// Use WiFiClient class to create TCP connections
|
||||
WiFiClient client;
|
||||
client.setTimeout(CONTROLLER_CLIENTTIMEOUT_DFLT);
|
||||
String aHost = notificationsettings.Server;
|
||||
addLog(LOG_LEVEL_DEBUG, String(F("EMAIL: Connecting to ")) + aHost + notificationsettings.Port);
|
||||
if (client.connect(aHost.c_str(), notificationsettings.Port) != 1) {
|
||||
|
||||
@@ -257,6 +257,22 @@ boolean Plugin_001(byte function, struct EventStruct *event, String& string)
|
||||
}
|
||||
}
|
||||
|
||||
if (command == F("gpiotoggle"))
|
||||
{
|
||||
success = true;
|
||||
byte mode;
|
||||
uint16_t currentState;
|
||||
|
||||
getPinState(PLUGIN_ID_001, event->Par1, &mode, ¤tState);
|
||||
if (mode == PIN_MODE_OUTPUT || mode == PIN_MODE_UNDEFINED) { //toggle only output pins
|
||||
digitalWrite(event->Par1, !currentState);
|
||||
setPinState(PLUGIN_ID_001, event->Par1, PIN_MODE_OUTPUT, !currentState);
|
||||
log = String(F("SW : Toggle GPIO ")) + String(event->Par1) + String(F(" Set to ")) + String(!currentState);
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
SendStatus(event->Source, getPinStateJSON(SEARCH_PIN_STATE, PLUGIN_ID_001, event->Par1, log, 0));
|
||||
}
|
||||
}
|
||||
|
||||
if (command == F("pwm"))
|
||||
{
|
||||
success = true;
|
||||
|
||||
@@ -90,7 +90,7 @@ boolean Plugin_004(byte function, struct EventStruct * event, String& string)
|
||||
resolutionChoice = Plugin_004_DS_getResolution(savedAddress);
|
||||
else
|
||||
resolutionChoice = 9;
|
||||
String resultsOptions[4] = { "9", "10", "11", "12" };
|
||||
String resultsOptions[4] = { F("9"), F("10"), F("11"), F("12") };
|
||||
int resultsOptionValues[4] = { 9, 10, 11, 12 };
|
||||
addFormSelector(F("Device Resolution"), F("plugin_004_res"), 4, resultsOptions, resultsOptionValues, resolutionChoice);
|
||||
addHtml(F(" Bit"));
|
||||
@@ -105,7 +105,6 @@ boolean Plugin_004(byte function, struct EventStruct * event, String& string)
|
||||
|
||||
// save the address for selected device and store into extra tasksettings
|
||||
Plugin_004_DallasPin = Settings.TaskDevicePin1[event->TaskIndex];
|
||||
// byte devCount =
|
||||
if (Plugin_004_DallasPin != -1){
|
||||
Plugin_004_DS_scan(getFormItemInt(F("plugin_004_dev")), addr);
|
||||
for (byte x = 0; x < 8; x++)
|
||||
@@ -124,11 +123,12 @@ boolean Plugin_004(byte function, struct EventStruct * event, String& string)
|
||||
{
|
||||
if (x != 0)
|
||||
string += "-";
|
||||
// string += String(ExtraTaskSettings.TaskDevicePluginConfigLong[x], HEX);
|
||||
string += String(ExtraTaskSettings.TaskDevicePluginConfigLong[x], HEX);
|
||||
}
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_INIT:
|
||||
{
|
||||
Plugin_004_DallasPin = Settings.TaskDevicePin1[event->TaskIndex];
|
||||
@@ -169,7 +169,7 @@ boolean Plugin_004(byte function, struct EventStruct * event, String& string)
|
||||
for (byte x = 0; x < 8; x++)
|
||||
{
|
||||
if (x != 0)
|
||||
log += "-";
|
||||
log += '-';
|
||||
log += String(ExtraTaskSettings.TaskDevicePluginConfigLong[x], HEX);
|
||||
}
|
||||
|
||||
|
||||
@@ -124,6 +124,22 @@ boolean Plugin_009(byte function, struct EventStruct *event, String& string)
|
||||
SendStatus(event->Source, getPinStateJSON(SEARCH_PIN_STATE, PLUGIN_ID_009, event->Par1, log, 0));
|
||||
}
|
||||
|
||||
if (command == F("mcpgpiotoggle"))
|
||||
{
|
||||
success = true;
|
||||
byte mode;
|
||||
uint16_t currentState;
|
||||
|
||||
getPinState(PLUGIN_ID_009, event->Par1, &mode, ¤tState);
|
||||
if (mode == PIN_MODE_OUTPUT || mode == PIN_MODE_UNDEFINED) {
|
||||
setPinState(PLUGIN_ID_009, event->Par1, PIN_MODE_OUTPUT, !currentState);
|
||||
Plugin_009_Write(event->Par1, !currentState);
|
||||
log = String(F("MCP : Toggle GPIO ")) + String(event->Par1) + String(F(" Set to ")) + String(!currentState);
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
SendStatus(event->Source, getPinStateJSON(SEARCH_PIN_STATE, PLUGIN_ID_009, event->Par1, log, 0));
|
||||
}
|
||||
}
|
||||
|
||||
if (command == F("mcppulse"))
|
||||
{
|
||||
success = true;
|
||||
|
||||
+198
-40
@@ -10,9 +10,21 @@
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <map>
|
||||
//#include <shared_ptr>
|
||||
#include <NewPingESP8266.h>
|
||||
|
||||
// PlugIn specific defines
|
||||
// operatingMode
|
||||
#define OPMODE_VALUE (0)
|
||||
#define OPMODE_STATE (1)
|
||||
|
||||
// measuringUnit
|
||||
#define UNIT_CM (0)
|
||||
#define UNIT_INCH (1)
|
||||
|
||||
// filterType
|
||||
#define FILTER_NONE (0)
|
||||
#define FILTER_MEDIAN (1)
|
||||
|
||||
// map of sensors
|
||||
std::map<unsigned int, std::shared_ptr<NewPingESP8266> > P_013_sensordefs;
|
||||
|
||||
@@ -36,6 +48,7 @@ boolean Plugin_013(byte function, struct EventStruct *event, String& string)
|
||||
Device[deviceCount].SendDataOption = true;
|
||||
Device[deviceCount].TimerOption = true;
|
||||
Device[deviceCount].GlobalSyncOption = true;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -54,20 +67,51 @@ boolean Plugin_013(byte function, struct EventStruct *event, String& string)
|
||||
|
||||
case PLUGIN_WEBFORM_LOAD:
|
||||
{
|
||||
byte choice = Settings.TaskDevicePluginConfig[event->TaskIndex][0];
|
||||
String options[2];
|
||||
options[0] = F("Value");
|
||||
options[1] = F("State");
|
||||
int optionValues[2] = { 1, 2 };
|
||||
addFormSelector(F("Mode"), F("plugin_013_mode"), 2, options, optionValues, choice);
|
||||
int16_t operatingMode = Settings.TaskDevicePluginConfig[event->TaskIndex][0];
|
||||
int16_t threshold = Settings.TaskDevicePluginConfig[event->TaskIndex][1];
|
||||
int16_t max_distance = Settings.TaskDevicePluginConfig[event->TaskIndex][2];
|
||||
int16_t measuringUnit = Settings.TaskDevicePluginConfig[event->TaskIndex][3];
|
||||
int16_t filterType = Settings.TaskDevicePluginConfig[event->TaskIndex][4];
|
||||
int16_t filterSize = Settings.TaskDevicePluginConfig[event->TaskIndex][5];
|
||||
|
||||
if (Settings.TaskDevicePluginConfig[event->TaskIndex][0] == 2)
|
||||
{
|
||||
addFormNumericBox(F("Threshold"), F("plugin_013_threshold"), Settings.TaskDevicePluginConfig[event->TaskIndex][1]);
|
||||
addUnit(F("cm"));
|
||||
// default filtersize = 5
|
||||
if (filterSize == 0) {
|
||||
filterSize = 5;
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][5] = filterSize;
|
||||
}
|
||||
addFormNumericBox(F("Max Distance"), F("plugin_013_max_distance"), Settings.TaskDevicePluginConfig[event->TaskIndex][2], 0, 500);
|
||||
addUnit(F("cm"));
|
||||
|
||||
|
||||
String strUnit = (measuringUnit == UNIT_CM) ? F("cm") : F("inch");
|
||||
|
||||
String optionsOpMode[2];
|
||||
int optionValuesOpMode[2] = { 0, 1 };
|
||||
optionsOpMode[0] = F("Value");
|
||||
optionsOpMode[1] = F("State");
|
||||
addFormSelector(F("Mode"), F("plugin_013_mode"), 2, optionsOpMode, optionValuesOpMode, operatingMode);
|
||||
|
||||
if (operatingMode == OPMODE_STATE)
|
||||
{
|
||||
addFormNumericBox(F("Threshold"), F("plugin_013_threshold"), threshold);
|
||||
addUnit(strUnit);
|
||||
}
|
||||
addFormNumericBox(F("Max Distance"), F("plugin_013_max_distance"), max_distance, 0, 500);
|
||||
addUnit(strUnit);
|
||||
|
||||
String optionsUnit[2];
|
||||
int optionValuesUnit[2] = { 0, 1 };
|
||||
optionsUnit[0] = F("Metric");
|
||||
optionsUnit[1] = F("Imperial");
|
||||
addFormSelector(F("Unit"), F("plugin_013_Unit"), 2, optionsUnit, optionValuesUnit, measuringUnit);
|
||||
|
||||
String optionsFilter[2];
|
||||
int optionValuesFilter[2] = { 0, 1 };
|
||||
optionsFilter[0] = F("None");
|
||||
optionsFilter[1] = F("Median");
|
||||
addFormSelector(F("Filter"), F("plugin_013_FilterType"), 2, optionsFilter, optionValuesFilter, filterType);
|
||||
|
||||
// enable filtersize option if filter is used,
|
||||
if (filterType != FILTER_NONE)
|
||||
addFormNumericBox(F("Filter size"), F("plugin_013_FilterSize"), filterSize, 2, 20);
|
||||
|
||||
success = true;
|
||||
break;
|
||||
@@ -75,34 +119,60 @@ boolean Plugin_013(byte function, struct EventStruct *event, String& string)
|
||||
|
||||
case PLUGIN_WEBFORM_SAVE:
|
||||
{
|
||||
int16_t operatingMode = Settings.TaskDevicePluginConfig[event->TaskIndex][0];
|
||||
int16_t filterType = Settings.TaskDevicePluginConfig[event->TaskIndex][4];
|
||||
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][0] = getFormItemInt(F("plugin_013_mode"));
|
||||
if (Settings.TaskDevicePluginConfig[event->TaskIndex][0] == 2)
|
||||
{
|
||||
if (operatingMode == OPMODE_STATE)
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][1] = getFormItemInt(F("plugin_013_threshold"));
|
||||
}
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][2] = getFormItemInt(F("plugin_013_max_distance"));
|
||||
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][3] = getFormItemInt(F("plugin_013_Unit"));
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][4] = getFormItemInt(F("plugin_013_FilterType"));
|
||||
if (filterType != FILTER_NONE)
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][5] = getFormItemInt(F("plugin_013_FilterSize"));
|
||||
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_INIT:
|
||||
{
|
||||
byte Plugin_013_TRIG_Pin = Settings.TaskDevicePin1[event->TaskIndex];
|
||||
byte Plugin_013_IRQ_Pin = Settings.TaskDevicePin2[event->TaskIndex];
|
||||
int16_t max_cm_distance = Settings.TaskDevicePluginConfig[event->TaskIndex][2];
|
||||
int16_t max_distance = Settings.TaskDevicePluginConfig[event->TaskIndex][2];
|
||||
int16_t measuringUnit = Settings.TaskDevicePluginConfig[event->TaskIndex][3];
|
||||
int16_t filterType = Settings.TaskDevicePluginConfig[event->TaskIndex][4];
|
||||
int16_t filterSize = Settings.TaskDevicePluginConfig[event->TaskIndex][5];
|
||||
|
||||
int8_t Plugin_013_TRIG_Pin = Settings.TaskDevicePin1[event->TaskIndex];
|
||||
int8_t Plugin_013_IRQ_Pin = Settings.TaskDevicePin2[event->TaskIndex];
|
||||
int16_t max_distance_cm = (measuringUnit == UNIT_CM) ? max_distance : (float)max_distance * 2.54f;
|
||||
|
||||
// create sensor instance and add to std::map
|
||||
P_013_sensordefs.erase(event->TaskIndex);
|
||||
P_013_sensordefs[event->TaskIndex] =
|
||||
std::shared_ptr<NewPingESP8266> (new NewPingESP8266(Plugin_013_TRIG_Pin, Plugin_013_IRQ_Pin, max_cm_distance));
|
||||
std::shared_ptr<NewPingESP8266> (new NewPingESP8266(Plugin_013_TRIG_Pin, Plugin_013_IRQ_Pin, max_distance_cm));
|
||||
|
||||
String log = F("ULTRASONIC : TaskNr: ");
|
||||
log += event->TaskIndex +1;
|
||||
log += F(" TrigPin: ");
|
||||
log += Plugin_013_TRIG_Pin;
|
||||
log += F(" IRQ_Pin: ");
|
||||
log += Plugin_013_IRQ_Pin;
|
||||
log += F(" max dist cm: ");
|
||||
log += max_cm_distance;
|
||||
log += F(" max dist ");
|
||||
log += (measuringUnit == UNIT_CM) ? F("[cm]: ") : F("[inch]: ");
|
||||
log += max_distance;
|
||||
log += F(" max echo: ");
|
||||
log += P_013_sensordefs[event->TaskIndex]->getMaxEchoTime();
|
||||
log += F(" Filter: ");
|
||||
if (filterType == FILTER_NONE)
|
||||
log += F("none");
|
||||
else
|
||||
if (filterType == FILTER_MEDIAN) {
|
||||
log += F("Median size: ");
|
||||
log += filterSize;
|
||||
}
|
||||
else
|
||||
log += F("invalid!");
|
||||
log += F(" nr_tasks: ");
|
||||
log += P_013_sensordefs.size();
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
@@ -120,7 +190,6 @@ boolean Plugin_013(byte function, struct EventStruct *event, String& string)
|
||||
log += F(" usec, ");
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
|
||||
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
@@ -133,39 +202,48 @@ boolean Plugin_013(byte function, struct EventStruct *event, String& string)
|
||||
|
||||
case PLUGIN_READ: // If we select value mode, read and send the value based on global timer
|
||||
{
|
||||
if (Settings.TaskDevicePluginConfig[event->TaskIndex][0] == 1)
|
||||
int16_t operatingMode = Settings.TaskDevicePluginConfig[event->TaskIndex][0];
|
||||
int16_t measuringUnit = Settings.TaskDevicePluginConfig[event->TaskIndex][3];
|
||||
|
||||
if (operatingMode == OPMODE_VALUE)
|
||||
{
|
||||
float value = Plugin_013_read(event->TaskIndex);
|
||||
String log = F("ULTRASONIC : TaskNr: ");
|
||||
log += event->TaskIndex +1;
|
||||
log += F(" Distance: ");
|
||||
if (value > 0)
|
||||
UserVar[event->BaseVarIndex] = value;
|
||||
log += UserVar[event->BaseVarIndex];
|
||||
log += (measuringUnit == UNIT_CM) ? F(" cm ") : F(" inch ");
|
||||
if (value == NO_ECHO)
|
||||
{
|
||||
UserVar[event->BaseVarIndex] = value;
|
||||
log += UserVar[event->BaseVarIndex];
|
||||
success = true;
|
||||
log += F(" Error: ");
|
||||
log += Plugin_013_getErrorStatusString(event->TaskIndex);
|
||||
}
|
||||
else
|
||||
log += F("No reading!");
|
||||
|
||||
addLog(LOG_LEVEL_INFO,log);
|
||||
addLog(LOG_LEVEL_INFO,log);
|
||||
}
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_TEN_PER_SECOND: // If we select state mode, do more frequent checks and send only state changes
|
||||
{
|
||||
if (Settings.TaskDevicePluginConfig[event->TaskIndex][0] == 2)
|
||||
int16_t operatingMode = Settings.TaskDevicePluginConfig[event->TaskIndex][0];
|
||||
int16_t threshold = Settings.TaskDevicePluginConfig[event->TaskIndex][1];
|
||||
|
||||
if (operatingMode == OPMODE_STATE)
|
||||
{
|
||||
byte state = 0;
|
||||
float value = Plugin_013_read(event->TaskIndex);
|
||||
if (value > 0)
|
||||
if (value != NO_ECHO)
|
||||
{
|
||||
if (value < Settings.TaskDevicePluginConfig[event->TaskIndex][1])
|
||||
if (value < threshold)
|
||||
state = 1;
|
||||
if (state != switchstate[event->TaskIndex])
|
||||
{
|
||||
String log = F("ULTRASONIC : State ");
|
||||
String log = F("ULTRASONIC : TaskNr: ");
|
||||
log += event->TaskIndex +1;
|
||||
log += F(" state: ");
|
||||
log += state;
|
||||
addLog(LOG_LEVEL_INFO,log);
|
||||
switchstate[event->TaskIndex] = state;
|
||||
@@ -174,6 +252,14 @@ boolean Plugin_013(byte function, struct EventStruct *event, String& string)
|
||||
sendData(event);
|
||||
}
|
||||
}
|
||||
else {
|
||||
String log = F("ULTRASONIC : TaskNr: ");
|
||||
log += event->TaskIndex +1;
|
||||
log += F(" Error: ");
|
||||
log += Plugin_013_getErrorStatusString(event->TaskIndex);
|
||||
addLog(LOG_LEVEL_INFO,log);
|
||||
}
|
||||
|
||||
}
|
||||
success = true;
|
||||
break;
|
||||
@@ -186,10 +272,82 @@ boolean Plugin_013(byte function, struct EventStruct *event, String& string)
|
||||
float Plugin_013_read(unsigned int taskIndex)
|
||||
/*********************************************************************/
|
||||
{
|
||||
if (P_013_sensordefs.count(taskIndex) == 0) return 0;
|
||||
delay(1);
|
||||
float distance = (P_013_sensordefs[taskIndex])->ping_cm();
|
||||
delay(1);
|
||||
return distance;
|
||||
if (P_013_sensordefs.count(taskIndex) == 0)
|
||||
return 0;
|
||||
|
||||
int16_t max_distance = Settings.TaskDevicePluginConfig[taskIndex][2];
|
||||
int16_t measuringUnit = Settings.TaskDevicePluginConfig[taskIndex][3];
|
||||
int16_t filterType = Settings.TaskDevicePluginConfig[taskIndex][4];
|
||||
int16_t filterSize = Settings.TaskDevicePluginConfig[taskIndex][5];
|
||||
int16_t max_distance_cm = (measuringUnit == UNIT_CM) ? max_distance : (float)max_distance * 2.54f;
|
||||
|
||||
unsigned int echoTime = 0;
|
||||
|
||||
switch (filterType) {
|
||||
case FILTER_NONE:
|
||||
echoTime = (P_013_sensordefs[taskIndex])->ping();
|
||||
break;
|
||||
case FILTER_MEDIAN:
|
||||
echoTime = (P_013_sensordefs[taskIndex])->ping_median(filterSize, max_distance_cm);
|
||||
break;
|
||||
default:
|
||||
addLog(LOG_LEVEL_INFO, F("invalid Filter Type setting!"));
|
||||
}
|
||||
|
||||
if (measuringUnit == UNIT_CM)
|
||||
return NewPingESP8266::convert_cm_F(echoTime);
|
||||
else
|
||||
return NewPingESP8266::convert_in_F(echoTime);
|
||||
}
|
||||
|
||||
/*********************************************************************/
|
||||
String Plugin_013_getErrorStatusString(unsigned int taskIndex)
|
||||
/*********************************************************************/
|
||||
{
|
||||
if (P_013_sensordefs.count(taskIndex) == 0)
|
||||
return String(F("invalid taskindex"));
|
||||
|
||||
switch ((P_013_sensordefs[taskIndex])->getErrorState()) {
|
||||
case NewPingESP8266::STATUS_SENSOR_READY: {
|
||||
return String(F("Sensor ready"));
|
||||
break;
|
||||
}
|
||||
|
||||
case NewPingESP8266::STATUS_MEASUREMENT_VALID: {
|
||||
return String(F("no error, measurement valid"));
|
||||
break;
|
||||
}
|
||||
|
||||
case NewPingESP8266::STATUS_ECHO_TRIGGERED: {
|
||||
return String(F("Echo triggered, waiting for Echo end"));
|
||||
break;
|
||||
}
|
||||
|
||||
case NewPingESP8266::STATUS_ECHO_STATE_ERROR: {
|
||||
return String(F("Echo pulse error, Echopin not low on trigger"));
|
||||
break;
|
||||
}
|
||||
|
||||
case NewPingESP8266::STATUS_ECHO_START_TIMEOUT_50ms: {
|
||||
return String(F("Echo timeout error, no echo start whithin 50 ms"));
|
||||
break;
|
||||
}
|
||||
|
||||
case NewPingESP8266::STATUS_ECHO_START_TIMEOUT_DISTANCE: {
|
||||
return String(F("Echo timeout error, no echo start whithin time for max. distance"));
|
||||
break;
|
||||
}
|
||||
|
||||
case NewPingESP8266::STATUS_MAX_DISTANCE_EXCEEDED: {
|
||||
return String(F("Echo too late, maximum distance exceeded"));
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
return String(F("unknown error"));
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
#endif // USES_P013
|
||||
|
||||
@@ -41,6 +41,9 @@ decode_results results;
|
||||
#define PLUGIN_NAME_016 "Communication - TSOP4838"
|
||||
#define PLUGIN_VALUENAME1_016 "IR"
|
||||
|
||||
// A lot of the following code has been taken directly (with permission) from the IRrecvDumpV2.ino example code
|
||||
// of the IRremoteESP8266 library. (https://github.com/markszabo/IRremoteESP8266)
|
||||
|
||||
// ==================== start of TUNEABLE PARAMETERS ====================
|
||||
// As this program is a special purpose capture/decoder, let us use a larger
|
||||
// than normal buffer so we can handle Air Conditioner remote codes.
|
||||
|
||||
+35
-6
@@ -11,7 +11,7 @@
|
||||
boolean Plugin_019(byte function, struct EventStruct *event, String& string)
|
||||
{
|
||||
boolean success = false;
|
||||
static byte switchstate[TASKS_MAX];
|
||||
static boolean switchstate[TASKS_MAX];
|
||||
|
||||
switch (function)
|
||||
{
|
||||
@@ -23,7 +23,7 @@ boolean Plugin_019(byte function, struct EventStruct *event, String& string)
|
||||
Device[deviceCount].VType = SENSOR_TYPE_SWITCH;
|
||||
Device[deviceCount].Ports = 8;
|
||||
Device[deviceCount].PullUpOption = false;
|
||||
Device[deviceCount].InverseLogicOption = false;
|
||||
Device[deviceCount].InverseLogicOption = true;
|
||||
Device[deviceCount].FormulaOption = false;
|
||||
Device[deviceCount].ValueCount = 1;
|
||||
Device[deviceCount].SendDataOption = true;
|
||||
@@ -66,10 +66,17 @@ boolean Plugin_019(byte function, struct EventStruct *event, String& string)
|
||||
// read and store current state to prevent switching at boot time
|
||||
switchstate[event->TaskIndex] = Plugin_019_Read(Settings.TaskDevicePort[event->TaskIndex]);
|
||||
|
||||
// if boot state must be send, inverse default state
|
||||
if (Settings.TaskDevicePluginConfig[event->TaskIndex][0])
|
||||
switchstate[event->TaskIndex] = !switchstate[event->TaskIndex];
|
||||
if (Settings.TaskDevicePin1Inversed[event->TaskIndex]){
|
||||
UserVar[event->BaseVarIndex] = !switchstate[event->TaskIndex];
|
||||
} else {
|
||||
UserVar[event->BaseVarIndex] = switchstate[event->TaskIndex];
|
||||
}
|
||||
|
||||
// if boot state must be send, inverse default state
|
||||
// this is done to force the trigger in PLUGIN_TEN_PER_SECOND
|
||||
if (Settings.TaskDevicePluginConfig[event->TaskIndex][0]) {
|
||||
switchstate[event->TaskIndex] = !switchstate[event->TaskIndex];
|
||||
}
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
@@ -85,7 +92,13 @@ boolean Plugin_019(byte function, struct EventStruct *event, String& string)
|
||||
log += state;
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
switchstate[event->TaskIndex] = state;
|
||||
UserVar[event->BaseVarIndex] = state;
|
||||
|
||||
if (Settings.TaskDevicePin1Inversed[event->TaskIndex]){
|
||||
UserVar[event->BaseVarIndex] = !switchstate[event->TaskIndex];
|
||||
} else {
|
||||
UserVar[event->BaseVarIndex] = switchstate[event->TaskIndex];
|
||||
}
|
||||
|
||||
event->sensorType = SENSOR_TYPE_SWITCH;
|
||||
sendData(event);
|
||||
}
|
||||
@@ -128,6 +141,22 @@ boolean Plugin_019(byte function, struct EventStruct *event, String& string)
|
||||
SendStatus(event->Source, getPinStateJSON(SEARCH_PIN_STATE, PLUGIN_ID_019, event->Par1, log, 0));
|
||||
}
|
||||
|
||||
if (command == F("pcfgpiotoggle"))
|
||||
{
|
||||
success = true;
|
||||
byte mode;
|
||||
uint16_t currentState;
|
||||
|
||||
getPinState(PLUGIN_ID_019, event->Par1, &mode, ¤tState);
|
||||
if (mode == PIN_MODE_OUTPUT || mode == PIN_MODE_UNDEFINED) {
|
||||
setPinState(PLUGIN_ID_019, event->Par1, PIN_MODE_OUTPUT, !currentState);
|
||||
Plugin_019_Write(event->Par1, !currentState);
|
||||
log = String(F("PCF : Toggle GPIO ")) + String(event->Par1) + String(F(" Set to ")) + String(!currentState);
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
SendStatus(event->Source, getPinStateJSON(SEARCH_PIN_STATE, PLUGIN_ID_019, event->Par1, log, 0));
|
||||
}
|
||||
}
|
||||
|
||||
if (command == F("pcfpulse"))
|
||||
{
|
||||
success = true;
|
||||
|
||||
+3
-1
@@ -274,6 +274,8 @@ boolean Plugin_035(byte function, struct EventStruct *event, String& string)
|
||||
return success;
|
||||
}
|
||||
|
||||
// A lot of the following code has been taken directly (with permission) from the IRMQTTServer.ino example code
|
||||
// of the IRremoteESP8266 library. (https://github.com/markszabo/IRremoteESP8266)
|
||||
|
||||
// Parse an Air Conditioner A/C Hex String/code and send it.
|
||||
// Args:
|
||||
@@ -615,4 +617,4 @@ uint16_t countValuesInStr(const String str, char sep) {
|
||||
// }
|
||||
// return result;
|
||||
//}
|
||||
#endif // USES_P035
|
||||
#endif // USES_P035
|
||||
|
||||
@@ -41,6 +41,7 @@ void Plugin_037_try_connect() {
|
||||
if (MQTTclient_037_connected) return;
|
||||
// workaround see: https://github.com/esp8266/Arduino/issues/4497#issuecomment-373023864
|
||||
espclient_037 = WiFiClient();
|
||||
espclient_037.setTimeout(CONTROLLER_CLIENTTIMEOUT_DFLT);
|
||||
|
||||
if (MQTTclient_037 == NULL) {
|
||||
MQTTclient_037 = new PubSubClient(espclient_037);
|
||||
@@ -69,6 +70,7 @@ void Plugin_037_update_connect_status() {
|
||||
if (!connected) {
|
||||
// workaround see: https://github.com/esp8266/Arduino/issues/4497#issuecomment-373023864
|
||||
espclient_037 = WiFiClient();
|
||||
espclient_037.setTimeout(CONTROLLER_CLIENTTIMEOUT_DFLT);
|
||||
++reconnectCount;
|
||||
addLog(LOG_LEVEL_ERROR, F("IMPT : MQTT 037 Connection lost"));
|
||||
}
|
||||
|
||||
+84
-42
@@ -3,10 +3,15 @@
|
||||
//################################### Plugin 075: Nextion <info@sensorio.cz> ###########################
|
||||
//################################### Created on the work of majklovec ###########################
|
||||
//################################### Revisions by BertB and ThomasB ###########################
|
||||
//################################### Last Revision: Aug-03-2018 (TB) ###########################
|
||||
//################################### Last Revision: Oct-03-2018 (TB) ###########################
|
||||
//#######################################################################################################
|
||||
//
|
||||
// Updated: Aug-03-2018, ThomasB.
|
||||
// Updated: Oct-03-2018, ThomasB.
|
||||
// Added DEBUG_LOG define to reduce info log messages and prevent serial log flooding.
|
||||
// Added SendStatus() to post log message on browser to acknowledge HTTP write.
|
||||
// Added reserve() to minimize string memory allocations.
|
||||
//
|
||||
// Aug-03-2018 change log summary:
|
||||
// This updated Nextion Plugin introduces hardware (UART) serial as an alternative to SoftSerial.
|
||||
// Hardware serial offers more reliable communication with the Nextion display.
|
||||
// Created on the experimental Serial.swap() work of BertB.
|
||||
@@ -19,6 +24,9 @@
|
||||
// Defines start here
|
||||
// *****************************************************************************************************
|
||||
|
||||
//#define DEBUG_LOG // Enable this to include additional info messages in log output.
|
||||
|
||||
|
||||
// Plug-In defines
|
||||
#define PLUGIN_075
|
||||
#define PLUGIN_ID_075 75
|
||||
@@ -241,7 +249,9 @@ boolean Plugin_075(byte function, struct EventStruct *event, String& string)
|
||||
SoftSerial = NULL;
|
||||
}
|
||||
|
||||
String log = F("NEXTION075 : serial pin config RX:");
|
||||
String log;
|
||||
log.reserve(80); // Prevent re-allocation
|
||||
log = F("NEXTION075 : serial pin config RX:");
|
||||
log += rxPin;
|
||||
log += F(", TX:");
|
||||
log += txPin;
|
||||
@@ -313,6 +323,7 @@ boolean Plugin_075(byte function, struct EventStruct *event, String& string)
|
||||
RssiIndex = UcTmpString.indexOf(F("RSSIBAR")); // RSSI bargraph Keyword found, wifi value in dBm.
|
||||
if(RssiIndex >= 0) {
|
||||
int barVal;
|
||||
newString.reserve(Lenlines+10); // Prevent re-allocation
|
||||
newString = tmpString.substring(0, RssiIndex);
|
||||
int nbars = WiFi.RSSI();
|
||||
if (nbars < -100 || nbars >= 0)
|
||||
@@ -345,31 +356,38 @@ boolean Plugin_075(byte function, struct EventStruct *event, String& string)
|
||||
}
|
||||
|
||||
sendCommand(newString.c_str(), HwSerial);
|
||||
|
||||
String log = F("NEXTION075 : Cmd Statement Line-");
|
||||
log += String(x+1);
|
||||
log += F(" Sent: ");
|
||||
log += newString;
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
#ifdef DEBUG_LOG
|
||||
String log;
|
||||
log.reserve(Lenlines+50); // Prevent re-allocation
|
||||
log = F("NEXTION075 : Cmd Statement Line-");
|
||||
log += String(x+1);
|
||||
log += F(" Sent: ");
|
||||
log += newString;
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// At Interval timer, send idx & value data only if user enabled "values" interval mode.
|
||||
if(IncludeValues) {
|
||||
/*
|
||||
String log = F("NEXTION075: Interval values data enabled, resending idx=");
|
||||
log += String(UserVar[event->BaseVarIndex]);
|
||||
log += F(", value=");
|
||||
log += String(UserVar[event->BaseVarIndex+1]);
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
*/
|
||||
#ifdef DEBUG_LOG
|
||||
String log;
|
||||
log.reserve(120); // Prevent re-allocation
|
||||
log = F("NEXTION075: Interval values data enabled, resending idx=");
|
||||
log += String(UserVar[event->BaseVarIndex]);
|
||||
log += F(", value=");
|
||||
log += String(UserVar[event->BaseVarIndex+1]);
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
#endif
|
||||
|
||||
success = true;
|
||||
}
|
||||
else {
|
||||
/*
|
||||
String log = F("NEXTION075: Interval values data disabled, idx & value not resent");
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
*/
|
||||
#ifdef DEBUG_LOG
|
||||
String log = F("NEXTION075: Interval values data disabled, idx & value not resent");
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
#endif
|
||||
|
||||
success = false;
|
||||
}
|
||||
|
||||
@@ -386,6 +404,8 @@ boolean Plugin_075(byte function, struct EventStruct *event, String& string)
|
||||
|
||||
// Enable addLog() code below to help debug plugin write problems.
|
||||
/*
|
||||
String log;
|
||||
log.reserve(140); // Prevent re-allocation
|
||||
String log = F("Nextion arg0: ");
|
||||
log += tmpString;
|
||||
log += F(", TaskDeviceName: ");
|
||||
@@ -401,11 +421,14 @@ boolean Plugin_075(byte function, struct EventStruct *event, String& string)
|
||||
tmpString = string.substring(argIndex + 1);
|
||||
sendCommand(tmpString.c_str(), HwSerial);
|
||||
|
||||
String log = F("NEXTION075 : WRITE, ");
|
||||
log += F("Command is ");
|
||||
log += (tmpString.c_str());
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
|
||||
String log;
|
||||
log.reserve(110); // Prevent re-allocation
|
||||
log = F("NEXTION075 : WRITE = ");
|
||||
log += tmpString;
|
||||
#ifdef DEBUG_LOG
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
#endif
|
||||
SendStatus(event->Source, log); // Reply (echo) to sender. This will print message on browser.
|
||||
success = true; // Set true only if plugin found a command to execute.
|
||||
}
|
||||
break;
|
||||
@@ -439,7 +462,6 @@ boolean Plugin_075(byte function, struct EventStruct *event, String& string)
|
||||
uint16_t i;
|
||||
uint8_t c;
|
||||
uint8_t charCount;
|
||||
String log;
|
||||
String Vidx;
|
||||
String Nvalue;
|
||||
String Svalue;
|
||||
@@ -447,7 +469,7 @@ boolean Plugin_075(byte function, struct EventStruct *event, String& string)
|
||||
char __buffer[RXBUFFSZ+1]; // Staging buffer.
|
||||
|
||||
if(rxPin < 0) {
|
||||
String log = F("NEXTION075 : Missing RxD Pin Number, aborted serial receive");
|
||||
String log = F("NEXTION075 : Missing RxD Pin, aborted serial receive");
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
break;
|
||||
}
|
||||
@@ -455,6 +477,8 @@ boolean Plugin_075(byte function, struct EventStruct *event, String& string)
|
||||
if(HwSerial == UARTSERIAL) {
|
||||
charCount = Serial.available(); // Prime the Hardware Serial engine.
|
||||
if(charCount >= RXBUFFWARN) { // ESP8266 has 128 byte circular Rx buffer.
|
||||
String log;
|
||||
log.reserve(70); // Prevent re-allocation
|
||||
log = F("NEXTION075 : RxD UART Buffer capacity warning,");
|
||||
log += String(charCount);
|
||||
log += F(" bytes");
|
||||
@@ -465,6 +489,8 @@ boolean Plugin_075(byte function, struct EventStruct *event, String& string)
|
||||
if(SoftSerial == NULL) break; // SoftSerial missing, exit.
|
||||
charCount = SoftSerial->available(); // Prime the Soft Serial engine.
|
||||
if(charCount >= RXBUFFWARN) {
|
||||
String log;
|
||||
log.reserve(70); // Prevent re-allocation
|
||||
log = F("NEXTION075 : RxD SoftSerial Buffer capacity warning, ");
|
||||
log += String(charCount);
|
||||
log += F(" bytes");
|
||||
@@ -495,13 +521,17 @@ boolean Plugin_075(byte function, struct EventStruct *event, String& string)
|
||||
UserVar[event->BaseVarIndex + 1] = __buffer[3];
|
||||
sendData(event);
|
||||
|
||||
log = F("NEXTION075 : code: ");
|
||||
log += __buffer[1];
|
||||
log += ",";
|
||||
log += __buffer[2];
|
||||
log += ",";
|
||||
log += __buffer[3];
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
#ifdef DEBUG_LOG
|
||||
String log;
|
||||
log.reserve(70); // Prevent re-allocation
|
||||
log = F("NEXTION075 : code: ");
|
||||
log += __buffer[1];
|
||||
log += ",";
|
||||
log += __buffer[2];
|
||||
log += ",";
|
||||
log += __buffer[3];
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -534,9 +564,14 @@ boolean Plugin_075(byte function, struct EventStruct *event, String& string)
|
||||
__buffer[i] = 0x00;
|
||||
|
||||
String tmpString = __buffer;
|
||||
log = F("NEXTION075 : code: ");
|
||||
log += tmpString;
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
String log;
|
||||
log.reserve(50); // Prevent re-allocation
|
||||
log = F("NEXTION075 : Code = ");
|
||||
log += tmpString;
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
#endif
|
||||
|
||||
int argIndex = tmpString.indexOf(F(",i"));
|
||||
int argEnd = tmpString.indexOf(',', argIndex + 1);
|
||||
@@ -568,14 +603,21 @@ boolean Plugin_075(byte function, struct EventStruct *event, String& string)
|
||||
UserVar[event->BaseVarIndex+1] = Svalue.toFloat();
|
||||
sendData(event);
|
||||
|
||||
log = F("NEXTION075 : Pipe Command Sent: ");
|
||||
log += __buffer;
|
||||
log += UserVar[event->BaseVarIndex];
|
||||
#ifdef DEBUG_LOG
|
||||
String log;
|
||||
log.reserve(80); // Prevent re-allocation
|
||||
log = F("NEXTION075 : Pipe Command Sent: ");
|
||||
log += __buffer;
|
||||
log += UserVar[event->BaseVarIndex];
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
log = F("NEXTION075 : Unknown Pipe Command, skipped");
|
||||
#ifdef DEBUG_LOG
|
||||
String log = F("NEXTION075 : Unknown Pipe Command, skipped");
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
#endif
|
||||
}
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
}
|
||||
}
|
||||
if(HwSerial == UARTSERIAL) charCount = Serial.available();
|
||||
|
||||
Reference in New Issue
Block a user