mirror of
https://github.com/arendst/Tasmota.git
synced 2025-07-24 11:16:34 +00:00
Merge branch 'development' into pre-release
This commit is contained in:
commit
e2da3e432e
7
.github/PULL_REQUEST_TEMPLATE.md
vendored
7
.github/PULL_REQUEST_TEMPLATE.md
vendored
@ -6,7 +6,8 @@
|
||||
- [ ] The pull request is done against the latest dev branch
|
||||
- [ ] Only relevant files were touched
|
||||
- [ ] Only one feature/fix was added per PR.
|
||||
- [ ] The code change is tested and works on core Tasmota_core
|
||||
- [ ] The code change is tested and works on core ESP32
|
||||
- [ ] The code change pass travis tests. **Your PR cannot be merged unless tests pass**
|
||||
- [ ] The code change is tested and works on core ESP8266 V.2.7.0
|
||||
- [ ] The code change is tested and works on core ESP32 V.1.12.0
|
||||
- [ ] I accept the [CLA](https://github.com/arendst/Tasmota/blob/development/CONTRIBUTING.md#contributor-license-agreement-cla).
|
||||
|
||||
_NOTE: The code change must pass CI tests. **Your PR cannot be merged unless tests pass**_
|
||||
|
441
.github/workflows/CI_github.yml
vendored
Normal file
441
.github/workflows/CI_github.yml
vendored
Normal file
@ -0,0 +1,441 @@
|
||||
name: Tasmota CI
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
tasmota:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v1
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -U platformio
|
||||
platformio upgrade --dev
|
||||
platformio update
|
||||
- name: Run PlatformIO
|
||||
run: platformio run -e tasmota
|
||||
|
||||
tasmota-minimal:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v1
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -U platformio
|
||||
platformio upgrade --dev
|
||||
platformio update
|
||||
- name: Run PlatformIO
|
||||
run: platformio run -e tasmota-minimal
|
||||
|
||||
tasmota-lite:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v1
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -U platformio
|
||||
platformio upgrade --dev
|
||||
platformio update
|
||||
- name: Run PlatformIO
|
||||
run: platformio run -e tasmota-lite
|
||||
|
||||
tasmota-knx:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v1
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -U platformio
|
||||
platformio upgrade --dev
|
||||
platformio update
|
||||
- name: Run PlatformIO
|
||||
run: platformio run -e tasmota-knx
|
||||
|
||||
tasmota-sensors:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v1
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -U platformio
|
||||
platformio upgrade --dev
|
||||
platformio update
|
||||
- name: Run PlatformIO
|
||||
run: platformio run -e tasmota-sensors
|
||||
|
||||
|
||||
tasmota-display:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v1
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -U platformio
|
||||
platformio upgrade --dev
|
||||
platformio update
|
||||
- name: Run PlatformIO
|
||||
run: platformio run -e tasmota-display
|
||||
|
||||
tasmota-ir:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v1
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -U platformio
|
||||
platformio upgrade --dev
|
||||
platformio update
|
||||
- name: Run PlatformIO
|
||||
run: platformio run -e tasmota-ir
|
||||
|
||||
tasmota-BG:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v1
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -U platformio
|
||||
platformio upgrade --dev
|
||||
platformio update
|
||||
- name: Run PlatformIO
|
||||
run: platformio run -e tasmota-BG
|
||||
|
||||
tasmota-BR:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v1
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -U platformio
|
||||
platformio upgrade --dev
|
||||
platformio update
|
||||
- name: Run PlatformIO
|
||||
run: platformio run -e tasmota-BR
|
||||
|
||||
tasmota-CN:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v1
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -U platformio
|
||||
platformio upgrade --dev
|
||||
platformio update
|
||||
- name: Run PlatformIO
|
||||
run: platformio run -e tasmota-CN
|
||||
|
||||
tasmota-CZ:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v1
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -U platformio
|
||||
platformio upgrade --dev
|
||||
platformio update
|
||||
- name: Run PlatformIO
|
||||
run: platformio run -e tasmota-CZ
|
||||
|
||||
tasmota-DE:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v1
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -U platformio
|
||||
platformio upgrade --dev
|
||||
platformio update
|
||||
- name: Run PlatformIO
|
||||
run: platformio run -e tasmota-DE
|
||||
|
||||
tasmota-ES:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v1
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -U platformio
|
||||
platformio upgrade --dev
|
||||
platformio update
|
||||
- name: Run PlatformIO
|
||||
run: platformio run -e tasmota-ES
|
||||
|
||||
|
||||
tasmota-FR:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v1
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -U platformio
|
||||
platformio upgrade --dev
|
||||
platformio update
|
||||
- name: Run PlatformIO
|
||||
run: platformio run -e tasmota-FR
|
||||
|
||||
tasmota-GR:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v1
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -U platformio
|
||||
platformio upgrade --dev
|
||||
platformio update
|
||||
- name: Run PlatformIO
|
||||
run: platformio run -e tasmota-GR
|
||||
|
||||
tasmota-HE:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v1
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -U platformio
|
||||
platformio upgrade --dev
|
||||
platformio update
|
||||
- name: Run PlatformIO
|
||||
run: platformio run -e tasmota-HE
|
||||
|
||||
tasmota-HU:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v1
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -U platformio
|
||||
platformio upgrade --dev
|
||||
platformio update
|
||||
- name: Run PlatformIO
|
||||
run: platformio run -e tasmota-HU
|
||||
|
||||
tasmota-IT:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v1
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -U platformio
|
||||
platformio upgrade --dev
|
||||
platformio update
|
||||
- name: Run PlatformIO
|
||||
run: platformio run -e tasmota-IT
|
||||
|
||||
tasmota-KO:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v1
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -U platformio
|
||||
platformio upgrade --dev
|
||||
platformio update
|
||||
- name: Run PlatformIO
|
||||
run: platformio run -e tasmota-KO
|
||||
|
||||
tasmota-NL:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v1
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -U platformio
|
||||
platformio upgrade --dev
|
||||
platformio update
|
||||
- name: Run PlatformIO
|
||||
run: platformio run -e tasmota-NL
|
||||
|
||||
tasmota-PL:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v1
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -U platformio
|
||||
platformio upgrade --dev
|
||||
platformio update
|
||||
- name: Run PlatformIO
|
||||
run: platformio run -e tasmota-PL
|
||||
|
||||
tasmota-PT:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v1
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -U platformio
|
||||
platformio upgrade --dev
|
||||
platformio update
|
||||
- name: Run PlatformIO
|
||||
run: platformio run -e tasmota-PT
|
||||
|
||||
tasmota-RO:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v1
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -U platformio
|
||||
platformio upgrade --dev
|
||||
platformio update
|
||||
- name: Run PlatformIO
|
||||
run: platformio run -e tasmota-RO
|
||||
|
||||
tasmota-RU:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v1
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -U platformio
|
||||
platformio upgrade --dev
|
||||
platformio update
|
||||
- name: Run PlatformIO
|
||||
run: platformio run -e tasmota-RU
|
||||
|
||||
tasmota-SE:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v1
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -U platformio
|
||||
platformio upgrade --dev
|
||||
platformio update
|
||||
- name: Run PlatformIO
|
||||
run: platformio run -e tasmota-SE
|
||||
|
||||
tasmota-SK:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v1
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -U platformio
|
||||
platformio upgrade --dev
|
||||
platformio update
|
||||
- name: Run PlatformIO
|
||||
run: platformio run -e tasmota-SK
|
||||
|
||||
tasmota-TR:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v1
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -U platformio
|
||||
platformio upgrade --dev
|
||||
platformio update
|
||||
- name: Run PlatformIO
|
||||
run: platformio run -e tasmota-TR
|
||||
|
||||
tasmota-TW:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v1
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -U platformio
|
||||
platformio upgrade --dev
|
||||
platformio update
|
||||
- name: Run PlatformIO
|
||||
run: platformio run -e tasmota-TW
|
||||
|
||||
tasmota-UK:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v1
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -U platformio
|
||||
platformio upgrade --dev
|
||||
platformio update
|
||||
- name: Run PlatformIO
|
||||
run: platformio run -e tasmota-UK
|
22
.github/workflows/CI_github_ESP32.yml
vendored
Normal file
22
.github/workflows/CI_github_ESP32.yml
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
name: Tasmota ESP32 CI
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
tasmota32:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v1
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -U platformio
|
||||
platformio upgrade --dev
|
||||
platformio update
|
||||
- name: Run PlatformIO
|
||||
run: |
|
||||
cp platformio_override_sample.ini platformio_override.ini
|
||||
platformio run -e tasmota32
|
||||
|
@ -22,7 +22,8 @@ In addition to the [release webpage](https://github.com/arendst/Tasmota/releases
|
||||
|
||||
[](https://github.com/arendst/Tasmota)
|
||||
[](http://thehackbox.org/tasmota/)
|
||||
[](https://travis-ci.org/arendst/Tasmota)
|
||||

|
||||

|
||||
|
||||
See [tasmota/CHANGELOG.md](tasmota/CHANGELOG.md) for detailed change information.
|
||||
|
||||
|
@ -96,3 +96,4 @@ The following binary downloads have been compiled with ESP8266/Arduino library c
|
||||
- Add console command history (#7483, #8015)
|
||||
- Add quick wifi reconnect using saved AP parameters when ``SetOption56 0`` (#3189)
|
||||
- Add more accuracy to GPS NTP server (#8088)
|
||||
- Add experimental basic support for Tasmota on ESP32 based on work by Jörg Schüler-Maroldt
|
||||
|
21
libesp32/ESP32-Mail-Client/LICENSE
Executable file
21
libesp32/ESP32-Mail-Client/LICENSE
Executable file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 mobizt
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
2138
libesp32/ESP32-Mail-Client/README.md
Executable file
2138
libesp32/ESP32-Mail-Client/README.md
Executable file
File diff suppressed because it is too large
Load Diff
278
libesp32/ESP32-Mail-Client/examples/Receive_email/Receive_email.ino
Executable file
278
libesp32/ESP32-Mail-Client/examples/Receive_email/Receive_email.ino
Executable file
@ -0,0 +1,278 @@
|
||||
/*
|
||||
* Created by K. Suwatchai (Mobizt)
|
||||
*
|
||||
* Email: k_suwatchai@hotmail.com
|
||||
*
|
||||
* Github: https://github.com/mobizt
|
||||
*
|
||||
* Copyright (c) 2019 mobizt
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
//To use send Email for Gmail to port 465 (SSL), less secure app option should be enabled. https://myaccount.google.com/lesssecureapps?pli=1
|
||||
|
||||
//To receive Email for Gmail, IMAP option should be enabled. https://support.google.com/mail/answer/7126229?hl=en
|
||||
|
||||
/*
|
||||
===========================================================================================================================
|
||||
To prevent stack overrun in case of you want to download email attachments in IMAP readMail,
|
||||
increase the stack size in app_main() in esp32 main.cpp will help by change the stack size from 8192 to any more value
|
||||
as following
|
||||
|
||||
xTaskCreatePinnedToCore(loopTask, "loopTask", 8192, NULL, 1, &loopTaskHandle, ARDUINO_RUNNING_CORE);
|
||||
to
|
||||
xTaskCreatePinnedToCore(loopTask, "loopTask", 16384, NULL, 1, &loopTaskHandle, ARDUINO_RUNNING_CORE);
|
||||
|
||||
For Arduino, file esp32's main.cpp is at C:\Users\USER_NAME\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.1\cores\esp32\main.cpp
|
||||
And for platformIO, that file is at C:\Users\USER_NAME\.platformio\packages\framework-arduinoespressif32\cores\esp32\main.cpp
|
||||
===========================================================================================================================
|
||||
|
||||
*/
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "ESP32_MailClient.h"
|
||||
#include "SD.h"
|
||||
|
||||
#define WIFI_SSID "YOUR_WIFI_SSID"
|
||||
#define WIFI_PASSWORD "YOUR_WIFI_PASSWORD"
|
||||
|
||||
|
||||
|
||||
//The Email Reading data object contains config and data that received
|
||||
IMAPData imapData;
|
||||
|
||||
//Callback function to get the Email reading status
|
||||
void readCallback(ReadStatus info);
|
||||
|
||||
//List all files in SD card
|
||||
void printDirectory(File &dir, int depth);
|
||||
|
||||
void readEmail();
|
||||
|
||||
unsigned long lastTime = 0;
|
||||
|
||||
void setup()
|
||||
{
|
||||
|
||||
Serial.begin(115200);
|
||||
Serial.println();
|
||||
|
||||
Serial.print("Connecting to AP");
|
||||
|
||||
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
|
||||
while (WiFi.status() != WL_CONNECTED)
|
||||
{
|
||||
Serial.print(".");
|
||||
delay(200);
|
||||
}
|
||||
|
||||
Serial.println("");
|
||||
Serial.println("WiFi connected.");
|
||||
Serial.println("IP address: ");
|
||||
Serial.println(WiFi.localIP());
|
||||
|
||||
Serial.println();
|
||||
|
||||
MailClient.sdBegin();
|
||||
//MailClient.sdBegin(14,2,15,13); //SCK, MISO, MOSI,SS for TTGO T8 v1.7 or 1.8
|
||||
|
||||
File dir = SD.open("/");
|
||||
|
||||
printDirectory(dir, 0);
|
||||
|
||||
Serial.println();
|
||||
|
||||
imapData.setLogin("imap.gmail.com", 993, "YOUR_EMAIL_ACCOUNT@gmail.com", "YOUR_EMAIL_PASSWORD");
|
||||
imapData.setFolder("INBOX");
|
||||
|
||||
//Clear fetch UID
|
||||
//If fetch UID was set, no search is perform.
|
||||
imapData.setFetchUID("");
|
||||
|
||||
//imapData.setSearchCriteria("UID SINCE 10-Feb-2019");
|
||||
//imapData.setSearchCriteria("UID 700:*");
|
||||
//imapData.setSearchCriteria("UID SEARCH NOT SEEN");
|
||||
//imapData.setSearchCriteria("UID SEARCH UNSEEN");
|
||||
imapData.setSearchCriteria("UID SEARCH ALL");
|
||||
|
||||
//To fetch or read one message UID = 320
|
||||
//imapData.setFechUID("320");
|
||||
|
||||
//Set SD folder to save download messages and attachments
|
||||
imapData.setSaveFilePath("/email_data");
|
||||
|
||||
//Save attachament
|
||||
imapData.setDownloadAttachment(true);
|
||||
|
||||
//Set fetch/search result to return html message
|
||||
imapData.setHTMLMessage(true);
|
||||
|
||||
//Set fetch/search result to return text message
|
||||
imapData.setTextMessage(true);
|
||||
|
||||
//Set to save html message in SD card with decoded content.
|
||||
imapData.saveHTMLMessage(true, true);
|
||||
|
||||
//Set to save text message in SD card with decoded content.
|
||||
imapData.saveTextMessage(true, true);
|
||||
|
||||
//Set the maximum result when search criteria was set.
|
||||
imapData.setSearchLimit(10);
|
||||
|
||||
//Set the sort order of returning message upon most recent received email.
|
||||
imapData.setRecentSort(true);
|
||||
|
||||
//Set the return tex/html message size in byte.
|
||||
imapData.setMessageBufferSize(200);
|
||||
|
||||
//Set the maximum attachment size 5 MB (each file)
|
||||
imapData.setAttachmentSizeLimit(1024 * 1024 * 5);
|
||||
|
||||
//Set the Email receive callback function.
|
||||
imapData.setReadCallback(readCallback);
|
||||
|
||||
//Set to get attachment downloading progress status.
|
||||
imapData.setDownloadReport(true);
|
||||
|
||||
//Set the storage types to save download attachments or messages (SD is default)
|
||||
//imapData.setFileStorageType(MailClientStorageType::SPIFFS)
|
||||
imapData.setFileStorageType(MailClientStorageType::SD);
|
||||
|
||||
MailClient.readMail(imapData);
|
||||
}
|
||||
|
||||
void readEmail()
|
||||
{
|
||||
|
||||
Serial.println();
|
||||
Serial.println("Read Email...");
|
||||
|
||||
imapData.setFetchUID("10");
|
||||
imapData.setSearchCriteria("");
|
||||
MailClient.readMail(imapData);
|
||||
|
||||
imapData.setFetchUID("11");
|
||||
imapData.setSearchCriteria("");
|
||||
MailClient.readMail(imapData);
|
||||
|
||||
imapData.setFetchUID("12");
|
||||
imapData.setSearchCriteria("");
|
||||
MailClient.readMail(imapData);
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
|
||||
if (millis() - lastTime > 1000 * 60 * 3)
|
||||
{
|
||||
|
||||
lastTime = millis();
|
||||
Serial.println(ESP.getFreeHeap());
|
||||
|
||||
readEmail();
|
||||
}
|
||||
}
|
||||
|
||||
//Callback function to get the Email reading status
|
||||
void readCallback(ReadStatus msg)
|
||||
{
|
||||
//Print the current status
|
||||
Serial.println("INFO: " + msg.info());
|
||||
|
||||
if (msg.status() != "")
|
||||
Serial.println("STATUS: " + msg.status());
|
||||
|
||||
//Show the result when reading finished
|
||||
if (msg.success())
|
||||
{
|
||||
|
||||
for (int i = 0; i < imapData.availableMessages(); i++)
|
||||
{
|
||||
Serial.println("=================");
|
||||
|
||||
//Search result number which varied upon search crieria
|
||||
Serial.println("Messsage Number: " + imapData.getNumber(i));
|
||||
|
||||
//UID only available when assigned UID keyword in setSearchCriteria
|
||||
//e.g. imapData.setSearchCriteria("UID SEARCH ALL");
|
||||
Serial.println("Messsage UID: " + imapData.getUID(i));
|
||||
Serial.println("Messsage ID: " + imapData.getMessageID(i));
|
||||
Serial.println("Accept Language: " + imapData.getAcceptLanguage(i));
|
||||
Serial.println("Content Language: " + imapData.getContentLanguage(i));
|
||||
Serial.println("From: " + imapData.getFrom(i));
|
||||
Serial.println("From Charset: " + imapData.getFromCharset(i));
|
||||
Serial.println("To: " + imapData.getTo(i));
|
||||
Serial.println("To Charset: " + imapData.getToCharset(i));
|
||||
Serial.println("CC: " + imapData.getCC(i));
|
||||
Serial.println("CC Charset: " + imapData.getCCCharset(i));
|
||||
Serial.println("Date: " + imapData.getDate(i));
|
||||
Serial.println("Subject: " + imapData.getSubject(i));
|
||||
Serial.println("Subject Charset: " + imapData.getSubjectCharset(i));
|
||||
|
||||
//If setHeaderOnly to false;
|
||||
if (!imapData.isHeaderOnly())
|
||||
{
|
||||
Serial.println("Text Message: " + imapData.getTextMessage(i));
|
||||
Serial.println("Text Message Charset: " + imapData.getTextMessgaeCharset(i));
|
||||
Serial.println("HTML Message: " + imapData.getHTMLMessage(i));
|
||||
Serial.println("HTML Message Charset: " + imapData.getHTMLMessgaeCharset(i));
|
||||
if (imapData.isFetchMessageFailed(i))
|
||||
Serial.println("Fetch Error: " + imapData.getFetchMessageFailedReason(i));
|
||||
|
||||
if (imapData.isDownloadMessageFailed(i))
|
||||
Serial.println("Save Content Error: " + imapData.getDownloadMessageFailedReason(i));
|
||||
|
||||
if (imapData.getAttachmentCount(i) > 0)
|
||||
{
|
||||
|
||||
Serial.println("**************");
|
||||
Serial.println("Attachment: " + String(imapData.getAttachmentCount(i)) + " file(s)");
|
||||
|
||||
for (int j = 0; j < imapData.getAttachmentCount(i); j++)
|
||||
{
|
||||
Serial.println("File Index: " + String(j + 1));
|
||||
Serial.println("Filename: " + imapData.getAttachmentFileName(i, j));
|
||||
Serial.println("Name: " + imapData.getAttachmentName(i, j));
|
||||
Serial.println("Size: " + String(imapData.getAttachmentFileSize(i, j)));
|
||||
Serial.println("Type: " + imapData.getAttachmentType(i, j));
|
||||
Serial.println("Creation Date: " + imapData.getAttachmentCreationDate(i, j));
|
||||
if (imapData.isDownloadAttachmentFailed(i, j))
|
||||
Serial.println("Download Attachment Error: " + imapData.getDownloadAttachmentFailedReason(i, j));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Serial.println();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//List all files in SD card
|
||||
void printDirectory(File &dir, int depth)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
File entry = dir.openNextFile();
|
||||
if (!entry)
|
||||
break;
|
||||
|
||||
for (uint8_t i = 0; i < depth; i++)
|
||||
Serial.print("| ");
|
||||
|
||||
std::string name = entry.name();
|
||||
if (entry.isDirectory())
|
||||
{
|
||||
Serial.print("+----" + String(name.substr(name.find_last_of("/\\") + 1).c_str()) + "\r\n");
|
||||
printDirectory(entry, depth + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.print("+--" + String(name.substr(name.find_last_of("/\\") + 1).c_str()));
|
||||
Serial.print("\t\t\t(");
|
||||
Serial.print(entry.size(), DEC);
|
||||
Serial.println(")");
|
||||
}
|
||||
entry.close();
|
||||
}
|
||||
}
|
180
libesp32/ESP32-Mail-Client/examples/Send_email/Send_email.ino
Executable file
180
libesp32/ESP32-Mail-Client/examples/Send_email/Send_email.ino
Executable file
@ -0,0 +1,180 @@
|
||||
|
||||
|
||||
/*
|
||||
* Created by K. Suwatchai (Mobizt)
|
||||
*
|
||||
* Email: k_suwatchai@hotmail.com
|
||||
*
|
||||
* Github: https://github.com/mobizt
|
||||
*
|
||||
* Copyright (c) 2019 mobizt
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
//To use send Email for Gmail to port 465 (SSL), less secure app option should be enabled. https://myaccount.google.com/lesssecureapps?pli=1
|
||||
|
||||
//To receive Email for Gmail, IMAP option should be enabled. https://support.google.com/mail/answer/7126229?hl=en
|
||||
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "ESP32_MailClient.h"
|
||||
#include "SD.h"
|
||||
|
||||
//For demo only
|
||||
#include "image.h"
|
||||
|
||||
#define WIFI_SSID "YOUR_WIFI_SSID"
|
||||
#define WIFI_PASSWORD "YOUR_WIFI_PASSWORD"
|
||||
|
||||
|
||||
//The Email Sending data object contains config and data to send
|
||||
SMTPData smtpData;
|
||||
|
||||
//Callback function to get the Email sending status
|
||||
void sendCallback(SendStatus info);
|
||||
|
||||
void setup()
|
||||
{
|
||||
|
||||
Serial.begin(115200);
|
||||
Serial.println();
|
||||
|
||||
Serial.print("Connecting to AP");
|
||||
|
||||
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
|
||||
while (WiFi.status() != WL_CONNECTED)
|
||||
{
|
||||
Serial.print(".");
|
||||
delay(200);
|
||||
}
|
||||
|
||||
Serial.println("");
|
||||
Serial.println("WiFi connected.");
|
||||
Serial.println("IP address: ");
|
||||
Serial.println(WiFi.localIP());
|
||||
Serial.println();
|
||||
|
||||
|
||||
Serial.println("Mounting SD Card...");
|
||||
|
||||
if (SD.begin()) // MailClient.sdBegin(14,2,15,13) for TTGO T8 v1.7 or 1.8
|
||||
{
|
||||
|
||||
Serial.println("Preparing attach file...");
|
||||
|
||||
File file = SD.open("/text_file.txt", FILE_WRITE);
|
||||
file.print("Hello World!\r\nHello World!");
|
||||
file.close();
|
||||
|
||||
file = SD.open("/binary_file.dat", FILE_WRITE);
|
||||
|
||||
static uint8_t buf[512];
|
||||
|
||||
buf[0] = 'H';
|
||||
buf[1] = 'E';
|
||||
buf[2] = 'A';
|
||||
buf[3] = 'D';
|
||||
file.write(buf, 4);
|
||||
|
||||
size_t i;
|
||||
memset(buf, 0xff, 512);
|
||||
for (i = 0; i < 2048; i++)
|
||||
{
|
||||
file.write(buf, 512);
|
||||
}
|
||||
|
||||
buf[0] = 'T';
|
||||
buf[1] = 'A';
|
||||
buf[2] = 'I';
|
||||
buf[3] = 'L';
|
||||
file.write(buf, 4);
|
||||
|
||||
file.close();
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println("SD Card Monting Failed");
|
||||
}
|
||||
|
||||
Serial.println();
|
||||
|
||||
|
||||
Serial.println("Sending email...");
|
||||
|
||||
//Set the Email host, port, account and password
|
||||
smtpData.setLogin("outlook.office365.com", 587, "YOUR_EMAIL_ACCOUNT@outlook.com", "YOUR_EMAIL_PASSWORD");
|
||||
|
||||
//For library version 1.2.0 and later which STARTTLS protocol was supported,the STARTTLS will be
|
||||
//enabled automatically when port 587 was used, or enable it manually using setSTARTTLS function.
|
||||
//smtpData.setSTARTTLS(true);
|
||||
|
||||
//Set the sender name and Email
|
||||
smtpData.setSender("ESP32", "SOME_EMAIL_ACCOUNT@SOME_EMAIL.com");
|
||||
|
||||
//Set Email priority or importance High, Normal, Low or 1 to 5 (1 is highest)
|
||||
smtpData.setPriority("High");
|
||||
|
||||
//Set the subject
|
||||
smtpData.setSubject("ESP32 SMTP Mail Sending Test");
|
||||
|
||||
//Set the message - normal text or html format
|
||||
smtpData.setMessage("<div style=\"color:#ff0000;font-size:20px;\">Hello World! - From ESP32</div>", true);
|
||||
|
||||
//Add recipients, can add more than one recipient
|
||||
smtpData.addRecipient("SOME_RECIPIENT@SOME_MAIL.com");
|
||||
|
||||
|
||||
|
||||
//Add attachments, can add the file or binary data from flash memory, file in SD card
|
||||
//Data from internal memory
|
||||
smtpData.addAttachData("firebase_logo.png", "image/png", (uint8_t *)dummyImageData, sizeof dummyImageData);
|
||||
|
||||
//Add attach files from SD card
|
||||
//Comment these two lines, if no SD card connected
|
||||
//Two files that previousely created.
|
||||
smtpData.addAttachFile("/binary_file.dat");
|
||||
smtpData.addAttachFile("/text_file.txt");
|
||||
|
||||
|
||||
//Add some custom header to message
|
||||
//See https://tools.ietf.org/html/rfc822
|
||||
//These header fields can be read from raw or source of message when it received)
|
||||
smtpData.addCustomMessageHeader("Date: Sat, 10 Aug 2019 21:39:56 -0700 (PDT)");
|
||||
//Be careful when set Message-ID, it should be unique, otherwise message will not store
|
||||
//smtpData.addCustomMessageHeader("Message-ID: <abcde.fghij@gmail.com>");
|
||||
|
||||
//Set the storage types to read the attach files (SD is default)
|
||||
//smtpData.setFileStorageType(MailClientStorageType::SPIFFS);
|
||||
smtpData.setFileStorageType(MailClientStorageType::SD);
|
||||
|
||||
|
||||
|
||||
smtpData.setSendCallback(sendCallback);
|
||||
|
||||
//Start sending Email, can be set callback function to track the status
|
||||
if (!MailClient.sendMail(smtpData))
|
||||
Serial.println("Error sending Email, " + MailClient.smtpErrorReason());
|
||||
|
||||
//Clear all data from Email object to free memory
|
||||
smtpData.empty();
|
||||
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
}
|
||||
|
||||
//Callback function to get the Email sending status
|
||||
void sendCallback(SendStatus msg)
|
||||
{
|
||||
//Print the current status
|
||||
Serial.println(msg.info());
|
||||
|
||||
//Do something when complete
|
||||
if (msg.success())
|
||||
{
|
||||
Serial.println("----------------");
|
||||
}
|
||||
}
|
||||
|
1074
libesp32/ESP32-Mail-Client/examples/Send_email/image.h
Executable file
1074
libesp32/ESP32-Mail-Client/examples/Send_email/image.h
Executable file
File diff suppressed because it is too large
Load Diff
70
libesp32/ESP32-Mail-Client/examples/Set_flag/Set_flag.ino
Executable file
70
libesp32/ESP32-Mail-Client/examples/Set_flag/Set_flag.ino
Executable file
@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Created by K. Suwatchai (Mobizt)
|
||||
*
|
||||
* Email: k_suwatchai@hotmail.com
|
||||
*
|
||||
* Github: https://github.com/mobizt
|
||||
*
|
||||
* Copyright (c) 2019 mobizt
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "ESP32_MailClient.h"
|
||||
|
||||
#define WIFI_SSID "YOUR_WIFI_SSID"
|
||||
#define WIFI_PASSWORD "YOUR_WIFI_PASSWORD"
|
||||
|
||||
//The Email Reading data object contains config and data that received
|
||||
IMAPData imapData;
|
||||
|
||||
void readEmail();
|
||||
|
||||
unsigned long lastTime = 0;
|
||||
|
||||
void setup()
|
||||
{
|
||||
|
||||
Serial.begin(115200);
|
||||
Serial.println();
|
||||
|
||||
Serial.print("Connecting to AP");
|
||||
|
||||
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
|
||||
while (WiFi.status() != WL_CONNECTED)
|
||||
{
|
||||
Serial.print(".");
|
||||
delay(200);
|
||||
}
|
||||
|
||||
Serial.println("");
|
||||
Serial.println("WiFi connected.");
|
||||
Serial.println("IP address: ");
|
||||
Serial.println(WiFi.localIP());
|
||||
|
||||
Serial.println();
|
||||
|
||||
Serial.println();
|
||||
|
||||
imapData.setLogin("imap.gmail.com", 993, "YOUR_EMAIL_ACCOUNT@gmail.com", "YOUR_EMAIL_PASSWORD");
|
||||
imapData.setFolder("INBOX");
|
||||
imapData.setDebug(true);
|
||||
|
||||
//Set \Seen and \Answered to flags for message with UID 100
|
||||
MailClient.setFlag(imapData, 100, "\\Seen \\Answered");
|
||||
|
||||
//Add \Seen and \Answered to flags for message with UID 100
|
||||
//MailClient.addFlag(imapData, 100, "\\Seen \\Answered");
|
||||
|
||||
//Remove \Seen and \Answered from flags for message with UID 100
|
||||
//MailClient.removeFlag(imapData, 100, "\\Seen \\Answered");
|
||||
}
|
||||
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
|
||||
}
|
||||
|
136
libesp32/ESP32-Mail-Client/examples/Time/Time.ino
Executable file
136
libesp32/ESP32-Mail-Client/examples/Time/Time.ino
Executable file
@ -0,0 +1,136 @@
|
||||
/*
|
||||
* Created by K. Suwatchai (Mobizt)
|
||||
*
|
||||
* Email: k_suwatchai@hotmail.com
|
||||
*
|
||||
* Github: https://github.com/mobizt
|
||||
*
|
||||
* Copyright (c) 2019 mobizt
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "ESP32_MailClient.h"
|
||||
|
||||
#define WIFI_SSID "YOUR_WIFI_SSID"
|
||||
#define WIFI_PASSWORD "YOUR_WIFI_PASSWORD"
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
|
||||
Serial.begin(115200);
|
||||
Serial.println();
|
||||
|
||||
Serial.print("Connecting to AP");
|
||||
|
||||
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
|
||||
while (WiFi.status() != WL_CONNECTED)
|
||||
{
|
||||
Serial.print(".");
|
||||
delay(200);
|
||||
}
|
||||
|
||||
Serial.println("");
|
||||
Serial.println("WiFi connected.");
|
||||
Serial.println("IP address: ");
|
||||
Serial.println(WiFi.localIP());
|
||||
|
||||
Serial.println();
|
||||
|
||||
//Set Clock
|
||||
//GMT offset (3 Hrs), Daylight offset (0 Hrs)
|
||||
MailClient.Time.setClock(3, 0);
|
||||
|
||||
Serial.println("Number of Days This Year (since January): " + String(MailClient.Time.getNumberOfDayThisYear()));
|
||||
Serial.println("Day of Week Number: " + String(MailClient.Time.getDayOfWeek()));
|
||||
Serial.println("Day of Week String: : " + String(MailClient.Time.getDayOfWeekString()));
|
||||
Serial.println("Total seconds today: : " + String(MailClient.Time.getCurrentSecond()));
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
|
||||
if (!MailClient.Time.clockReady)
|
||||
return;
|
||||
|
||||
//Print out current date and time
|
||||
int d = MailClient.Time.getDay();
|
||||
int m = MailClient.Time.getMonth();
|
||||
int y = MailClient.Time.getYear();
|
||||
int hr = MailClient.Time.getHour();
|
||||
int min = MailClient.Time.getMin();
|
||||
int sec = MailClient.Time.getSec();
|
||||
Serial.print("Current Time (GMT+3): ");
|
||||
Serial.print(d);
|
||||
Serial.print("/");
|
||||
Serial.print(m);
|
||||
Serial.print("/");
|
||||
Serial.print(y);
|
||||
Serial.print(" ");
|
||||
Serial.print(hr);
|
||||
Serial.print(":");
|
||||
Serial.print(min);
|
||||
Serial.print(":");
|
||||
Serial.println(sec);
|
||||
|
||||
uint32_t todayFromMidnightTimestamp = MailClient.Time.getTimestamp(y, m, d, 0, 0, 0);
|
||||
uint32_t currentTimestamp = MailClient.Time.getUnixTime();
|
||||
uint32_t totalSecondsFromMidnight = currentTimestamp - todayFromMidnightTimestamp;
|
||||
|
||||
//Assumed we countdown until 15:00:00 everyday
|
||||
uint8_t targetSec = 0;
|
||||
uint8_t targetMin = 0;
|
||||
uint8_t targetHr = 15;
|
||||
uint32_t targetSecondsFromMidnight = targetHr * 60 * 60 + targetMin * 60 + targetSec;
|
||||
|
||||
if (targetSecondsFromMidnight >= totalSecondsFromMidnight)
|
||||
{
|
||||
uint32_t diffSeconds = targetSecondsFromMidnight - totalSecondsFromMidnight;
|
||||
int remainYrs, remainMonths, remainDays, remainHr, remainMin, remainSec;
|
||||
MailClient.Time.getTimeFromSec(diffSeconds, remainYrs, remainMonths, remainDays, remainHr, remainMin, remainSec);
|
||||
Serial.print("Everyday countdown until 15:00:00 is ");
|
||||
Serial.print(remainHr);
|
||||
Serial.print(" Hr, ");
|
||||
Serial.print(remainMin);
|
||||
Serial.print(" Min and ");
|
||||
Serial.print(remainSec);
|
||||
Serial.println(" Sec to go.");
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println("Everyday countdown until 15:00:00 was passed.");
|
||||
}
|
||||
|
||||
//Assumed we countdown until 18/12/2019 8:30:45
|
||||
uint32_t targetTimestamp = MailClient.Time.getTimestamp(2019, 12, 18, 8, 30, 45);
|
||||
if (targetTimestamp >= currentTimestamp)
|
||||
{
|
||||
uint32_t diffSeconds = targetTimestamp - currentTimestamp;
|
||||
int remainYrs, remainMonths, remainDays, remainHr, remainMin, remainSec;
|
||||
MailClient.Time.getTimeFromSec(diffSeconds, remainYrs, remainMonths, remainDays, remainHr, remainMin, remainSec);
|
||||
Serial.print("One time countdown until 18/12/2019 8:30:45 is ");
|
||||
Serial.print(remainYrs);
|
||||
Serial.print(" Years, ");
|
||||
Serial.print(remainMonths);
|
||||
Serial.print(" Months, ");
|
||||
Serial.print(remainDays);
|
||||
Serial.print(" Days, ");
|
||||
Serial.print(remainHr);
|
||||
Serial.print(" Hr, ");
|
||||
Serial.print(remainMin);
|
||||
Serial.print(" Min and ");
|
||||
Serial.print(remainSec);
|
||||
Serial.println(" Sec to go.");
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println("One time countdown until 18/12/2019 8:30:45 was finished.");
|
||||
}
|
||||
Serial.println();
|
||||
|
||||
delay(1000);
|
||||
}
|
||||
|
166
libesp32/ESP32-Mail-Client/keywords.txt
Executable file
166
libesp32/ESP32-Mail-Client/keywords.txt
Executable file
@ -0,0 +1,166 @@
|
||||
#######################################
|
||||
# Syntax Coloring Map ESP32-Mail-Client
|
||||
#######################################
|
||||
|
||||
#######################################
|
||||
# Classes (KEYWORD1)
|
||||
#######################################
|
||||
|
||||
IMAPData KEYWORD1
|
||||
SMTPData KEYWORD1
|
||||
attachmentData KEYWORD1
|
||||
SendStatus KEYWORD1
|
||||
messageBodyData KEYWORD1
|
||||
DownloadProgress KEYWORD1
|
||||
MessageData KEYWORD1
|
||||
|
||||
TIME KEYWORD1
|
||||
|
||||
|
||||
##################################
|
||||
# Methods and Functions (KEYWORD2)
|
||||
##################################
|
||||
|
||||
sendMail KEYWORD2
|
||||
readMail KEYWORD2
|
||||
smtpErrorReason KEYWORD2
|
||||
imapErrorReason KEYWORD2
|
||||
sdBegin KEYWORD2
|
||||
setFlag KEYWORD2
|
||||
addFlag KEYWORD2
|
||||
removeFlag KEYWORD2
|
||||
|
||||
|
||||
setClock KEYWORD2
|
||||
getUnixTime KEYWORD2
|
||||
getTimestamp KEYWORD2
|
||||
getYear KEYWORD2
|
||||
getMonth KEYWORD2
|
||||
getDay KEYWORD2
|
||||
getDayOfWeek KEYWORD2
|
||||
getDayOfWeekString KEYWORD2
|
||||
getHour KEYWORD2
|
||||
getMin KEYWORD2
|
||||
getSec KEYWORD2
|
||||
getNumberOfDayThisYear KEYWORD2
|
||||
getTotalDays KEYWORD2
|
||||
dayofweek KEYWORD2
|
||||
getCurrentSecond KEYWORD2
|
||||
getCurrentTimestamp KEYWORD2
|
||||
getTimeFromSec KEYWORD2
|
||||
|
||||
#########################################
|
||||
# Methods for IMAP Data object (KEYWORD2)
|
||||
#########################################
|
||||
|
||||
setLogin KEYWORD2
|
||||
setSTARTTLS KEYWORD2
|
||||
setDebug KEYWORD2
|
||||
setFolder KEYWORD2
|
||||
setMessageBufferSize KEYWORD2
|
||||
setAttachmentSizeLimit KEYWORD2
|
||||
setSearchCriteria KEYWORD2
|
||||
setSaveFilePath KEYWORD2
|
||||
setFechUID KEYWORD2
|
||||
setDownloadAttachment KEYWORD2
|
||||
setHTMLMessage KEYWORD2
|
||||
setTextMessage KEYWORD2
|
||||
setSearchLimit KEYWORD2
|
||||
setRecentSort KEYWORD2
|
||||
setReadCallback KEYWORD2
|
||||
setDownloadReport KEYWORD2
|
||||
isHeaderOnly KEYWORD2
|
||||
getFrom KEYWORD2
|
||||
getFromCharset KEYWORD2
|
||||
getTo KEYWORD2
|
||||
getToCharset KEYWORD2
|
||||
getCC KEYWORD2
|
||||
getCCCharset KEYWORD2
|
||||
getSubject KEYWORD2
|
||||
getSubjectCharset KEYWORD2
|
||||
getHTMLMessage KEYWORD2
|
||||
getTextMessage KEYWORD2
|
||||
getHTMLMessgaeCharset KEYWORD2
|
||||
getTextMessgaeCharset KEYWORD2
|
||||
getDate KEYWORD2
|
||||
getUID KEYWORD2
|
||||
getNumber KEYWORD2
|
||||
getMessageID KEYWORD2
|
||||
getAcceptLanguage KEYWORD2
|
||||
getContentLanguage KEYWORD2
|
||||
isFetchMessageFailed KEYWORD2
|
||||
getFetchMessageFailedReason KEYWORD2
|
||||
isDownloadAttachmentFailed KEYWORD2
|
||||
getDownloadAttachmentFailedReason KEYWORD2
|
||||
isDownloadMessageFailed KEYWORD2
|
||||
getDownloadMessageFailedReason KEYWORD2
|
||||
saveHTMLMessage KEYWORD2
|
||||
saveTextMessage KEYWORD2
|
||||
getFolderCount KEYWORD2
|
||||
getFolder KEYWORD2
|
||||
getFlagCount KEYWORD2
|
||||
getFlag KEYWORD2
|
||||
totalMessages KEYWORD2
|
||||
searchCount KEYWORD2
|
||||
availableMessages KEYWORD2
|
||||
getAttachmentCount KEYWORD2
|
||||
getAttachmentFileName KEYWORD2
|
||||
getAttachmentName KEYWORD2
|
||||
getAttachmentFileSize KEYWORD2
|
||||
getAttachmentCreationDate KEYWORD2
|
||||
getAttachmentType KEYWORD2
|
||||
empty KEYWORD2
|
||||
clearMessageData KEYWORD2
|
||||
|
||||
#########################################
|
||||
# Methods for SMTP Data object (KEYWORD2)
|
||||
#########################################
|
||||
|
||||
setSender KEYWORD2
|
||||
getFromName KEYWORD2
|
||||
getSenderEmail KEYWORD2
|
||||
setPriority KEYWORD2
|
||||
getPriority KEYWORD2
|
||||
addRecipient KEYWORD2
|
||||
removeRecipient KEYWORD2
|
||||
clearRecipient KEYWORD2
|
||||
getRecipient KEYWORD2
|
||||
recipientCount KEYWORD2
|
||||
setSubject KEYWORD2
|
||||
getSubject KEYWORD2
|
||||
setMessage KEYWORD2
|
||||
getMessage KEYWORD2
|
||||
htmlFormat KEYWORD2
|
||||
addCC KEYWORD2
|
||||
removeCC KEYWORD2
|
||||
clearCC KEYWORD2
|
||||
getCC KEYWORD2
|
||||
ccCount KEYWORD2
|
||||
addBCC KEYWORD2
|
||||
removeBCC KEYWORD2
|
||||
clearBCC KEYWORD2
|
||||
getBCC KEYWORD2
|
||||
bccCount KEYWORD2
|
||||
addAttachData KEYWORD2
|
||||
removeAttachData KEYWORD2
|
||||
attachDataCount KEYWORD2
|
||||
addAttachFile KEYWORD2
|
||||
removeAttachFile KEYWORD2
|
||||
clearAttachData KEYWORD2
|
||||
clearAttachFile KEYWORD2
|
||||
clearAttachment KEYWORD2
|
||||
attachFileCount KEYWORD2
|
||||
setSendCallback KEYWORD2
|
||||
|
||||
|
||||
############################################################
|
||||
# Functions for ReadStatus and SendStatus classes (KEYWORD2)
|
||||
############################################################
|
||||
|
||||
SendStatus KEYWORD2
|
||||
info KEYWORD2
|
||||
success KEYWORD2
|
||||
ReadStatus KEYWORD2
|
||||
status KEYWORD2
|
||||
|
||||
clockReady KEYWORD3
|
17
libesp32/ESP32-Mail-Client/library.properties
Executable file
17
libesp32/ESP32-Mail-Client/library.properties
Executable file
@ -0,0 +1,17 @@
|
||||
name=ESP32 Mail Client
|
||||
|
||||
version=2.1.4
|
||||
|
||||
author=Mobizt
|
||||
|
||||
maintainer=Mobizt <k_suwatchai@hotmail.com.com>
|
||||
|
||||
sentence=Mail Client Arduino Library for ESP32
|
||||
|
||||
paragraph=This library allows ESP32 to send Email with/without attachment and receive Email with/without attachment download through SMTP and IMAP servers.
|
||||
|
||||
category=Communication
|
||||
|
||||
url=https://github.com/mobizt/ESP32-Mail-Client
|
||||
|
||||
architectures=esp32
|
BIN
libesp32/ESP32-Mail-Client/media/images/esp32-mail.jpg
Executable file
BIN
libesp32/ESP32-Mail-Client/media/images/esp32-mail.jpg
Executable file
Binary file not shown.
After Width: | Height: | Size: 10 KiB |
BIN
libesp32/ESP32-Mail-Client/media/images/esp32-mail.png
Executable file
BIN
libesp32/ESP32-Mail-Client/media/images/esp32-mail.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
200
libesp32/ESP32-Mail-Client/src/ESP32MailHTTPClient.cpp
Executable file
200
libesp32/ESP32-Mail-Client/src/ESP32MailHTTPClient.cpp
Executable file
@ -0,0 +1,200 @@
|
||||
/*
|
||||
* Customized version of ESP32 HTTPClient Library.
|
||||
* Allow custom header and payload with STARTTLS support
|
||||
*
|
||||
* v 1.0.0
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
* Copyright (c) 2019 K. Suwatchai (Mobizt)
|
||||
*
|
||||
* HTTPClient Arduino library for ESP32
|
||||
*
|
||||
* Copyright (c) 2015 Markus Sattler. All rights reserved.
|
||||
* This file is part of the HTTPClient for Arduino.
|
||||
* Port to ESP32 by Evandro Luis Copercini (2017),
|
||||
* changed fingerprints to CA verification.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ESP32MailHTTPClient_CPP
|
||||
#define ESP32MailHTTPClient_CPP
|
||||
|
||||
#ifdef ESP32
|
||||
|
||||
#include "ESP32MailHTTPClient.h"
|
||||
|
||||
class TransportTraits
|
||||
{
|
||||
public:
|
||||
virtual ~TransportTraits() {}
|
||||
|
||||
virtual std::unique_ptr<WiFiClient> create()
|
||||
{
|
||||
return std::unique_ptr<WiFiClient>(new WiFiClient());
|
||||
}
|
||||
|
||||
virtual bool
|
||||
verify(WiFiClient &client, const char *host, bool starttls, DebugMsgCallback cb)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class TLSTraits : public TransportTraits
|
||||
{
|
||||
public:
|
||||
TLSTraits(const char *CAcert, const char *clicert = nullptr, const char *clikey = nullptr) : _cacert(CAcert), _clicert(clicert), _clikey(clikey) {}
|
||||
|
||||
std::unique_ptr<WiFiClient> create() override
|
||||
{
|
||||
return std::unique_ptr<WiFiClient>(new WiFiClientSecureESP32());
|
||||
}
|
||||
|
||||
bool verify(WiFiClient &client, const char *host, bool starttls, DebugMsgCallback cb) override
|
||||
{
|
||||
WiFiClientSecureESP32 &wcs = static_cast<WiFiClientSecureESP32 &>(client);
|
||||
wcs.setCACert(_cacert);
|
||||
wcs.setCertificate(_clicert);
|
||||
wcs.setPrivateKey(_clikey);
|
||||
wcs.setSTARTTLS(starttls);
|
||||
wcs.setDebugCB(cb);
|
||||
return true;
|
||||
}
|
||||
|
||||
protected:
|
||||
const char *_cacert;
|
||||
const char *_clicert;
|
||||
const char *_clikey;
|
||||
};
|
||||
|
||||
ESP32MailHTTPClient::ESP32MailHTTPClient() {}
|
||||
|
||||
ESP32MailHTTPClient::~ESP32MailHTTPClient()
|
||||
{
|
||||
if (_client)
|
||||
_client->stop();
|
||||
}
|
||||
|
||||
bool ESP32MailHTTPClient::begin(const char *host, uint16_t port, const char *uri, const char *CAcert)
|
||||
{
|
||||
transportTraits.reset(nullptr);
|
||||
|
||||
_host = host;
|
||||
_port = port;
|
||||
_uri = uri;
|
||||
transportTraits = TransportTraitsPtr(new TLSTraits(CAcert));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ESP32MailHTTPClient::connected()
|
||||
{
|
||||
if (_client)
|
||||
return ((_client->available() > 0) || _client->connected());
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ESP32MailHTTPClient::sendHeader(const char *header)
|
||||
{
|
||||
if (!connected())
|
||||
return false;
|
||||
return (_client->write(header, strlen(header)) == strlen(header));
|
||||
}
|
||||
|
||||
int ESP32MailHTTPClient::sendRequest(const char *header, const char *payload)
|
||||
{
|
||||
size_t size = strlen(payload);
|
||||
if (strlen(header) > 0)
|
||||
{
|
||||
if (!connect())
|
||||
return HTTPC_ERROR_CONNECTION_REFUSED;
|
||||
if (!sendHeader(header))
|
||||
return HTTPC_ERROR_SEND_HEADER_FAILED;
|
||||
}
|
||||
if (size > 0)
|
||||
if (_client->write(&payload[0], size) != size)
|
||||
return HTTPC_ERROR_SEND_PAYLOAD_FAILED;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
WiFiClient *ESP32MailHTTPClient::getStreamPtr(void)
|
||||
{
|
||||
if (connected())
|
||||
return _client.get();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool ESP32MailHTTPClient::connect(void)
|
||||
{
|
||||
if (connected())
|
||||
{
|
||||
while (_client->available() > 0)
|
||||
_client->read();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!transportTraits)
|
||||
return false;
|
||||
|
||||
_client = transportTraits->create();
|
||||
|
||||
if (!transportTraits->verify(*_client, _host.c_str(), false, _debugCallback))
|
||||
{
|
||||
_client->stop();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!_client->connect(_host.c_str(), _port))
|
||||
return false;
|
||||
|
||||
return connected();
|
||||
}
|
||||
|
||||
bool ESP32MailHTTPClient::connect(bool starttls)
|
||||
{
|
||||
if (connected())
|
||||
{
|
||||
while (_client->available() > 0)
|
||||
_client->read();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!transportTraits)
|
||||
return false;
|
||||
|
||||
_client = transportTraits->create();
|
||||
|
||||
if (!transportTraits->verify(*_client, _host.c_str(), starttls, _debugCallback))
|
||||
{
|
||||
_client->stop();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!_client->connect(_host.c_str(), _port))
|
||||
return false;
|
||||
|
||||
return connected();
|
||||
}
|
||||
|
||||
void ESP32MailHTTPClient::setDebugCallback(DebugMsgCallback cb)
|
||||
{
|
||||
_debugCallback = std::move(cb);
|
||||
}
|
||||
|
||||
#endif //ESP32
|
||||
|
||||
#endif //ESP32MailHTTPClient_CPP
|
107
libesp32/ESP32-Mail-Client/src/ESP32MailHTTPClient.h
Executable file
107
libesp32/ESP32-Mail-Client/src/ESP32MailHTTPClient.h
Executable file
@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Customized version of ESP32 HTTPClient Library.
|
||||
* Allow custom header and payload with STARTTLS support
|
||||
*
|
||||
* v 1.0.0
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
* Copyright (c) 2019 K. Suwatchai (Mobizt)
|
||||
*
|
||||
* HTTPClient Arduino library for ESP32
|
||||
*
|
||||
* Copyright (c) 2015 Markus Sattler. All rights reserved.
|
||||
* This file is part of the HTTPClient for Arduino.
|
||||
* Port to ESP32 by Evandro Luis Copercini (2017),
|
||||
* changed fingerprints to CA verification.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ESP32MailHTTPClient_H
|
||||
#define ESP32MailHTTPClient_H
|
||||
|
||||
#ifdef ESP32
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <HTTPClient.h>
|
||||
|
||||
#include <WiFiClient.h>
|
||||
#include "WiFiClientSecureESP32.h"
|
||||
|
||||
class ESP32MailHTTPClient : public HTTPClient
|
||||
{
|
||||
public:
|
||||
ESP32MailHTTPClient();
|
||||
~ESP32MailHTTPClient();
|
||||
|
||||
/**
|
||||
* Initialization of new http connection.
|
||||
* \param host - Host name without protocols.
|
||||
* \param port - Server's port.
|
||||
* \param uri - The URI of resource.
|
||||
* \param CAcert - The Base64 encode root certificate string
|
||||
* \return True as default.
|
||||
* If no certificate string provided, use (const char*)NULL to CAcert param
|
||||
*/
|
||||
bool begin(const char *host, uint16_t port, const char *uri, const char *CAcert);
|
||||
|
||||
/**
|
||||
* Check the http connection status.
|
||||
* \return True if connected.
|
||||
*/
|
||||
bool connected();
|
||||
|
||||
/**
|
||||
* Establish http connection if header provided and send it, send payload if provided.
|
||||
* \param header - The header string (constant chars array).
|
||||
* \param payload - The payload string (constant chars array), optional.
|
||||
* \return http status code, Return zero if new http connection and header and/or payload sent
|
||||
* with no error or no header and payload provided. If obly payload provided, no new http connection was established.
|
||||
*/
|
||||
int sendRequest(const char *header, const char *payload);
|
||||
|
||||
/**
|
||||
* Send extra header without making new http connection (if sendRequest has been called)
|
||||
* \param header - The header string (constant chars array).
|
||||
* \return True if header sending success.
|
||||
* Need to call sendRequest with header first.
|
||||
*/
|
||||
bool sendHeader(const char *header);
|
||||
|
||||
/**
|
||||
* Get the WiFi client pointer.
|
||||
* \return WiFi client pointer.
|
||||
*/
|
||||
WiFiClient *getStreamPtr(void);
|
||||
|
||||
uint16_t tcpTimeout = HTTPCLIENT_DEFAULT_TCP_TIMEOUT;
|
||||
bool connect(void);
|
||||
bool connect(bool starttls);
|
||||
void setDebugCallback(DebugMsgCallback cb);
|
||||
|
||||
protected:
|
||||
TransportTraitsPtr transportTraits;
|
||||
std::unique_ptr<WiFiClient> _client;
|
||||
DebugMsgCallback _debugCallback = NULL;
|
||||
|
||||
std::string _host = "";
|
||||
std::string _uri = "";
|
||||
uint16_t _port = 0;
|
||||
};
|
||||
|
||||
#endif //ESP32
|
||||
|
||||
#endif //ESP32MailHTTPClient_H
|
191
libesp32/ESP32-Mail-Client/src/ESP32TimeHelper.cpp
Executable file
191
libesp32/ESP32-Mail-Client/src/ESP32TimeHelper.cpp
Executable file
@ -0,0 +1,191 @@
|
||||
/*
|
||||
* ESP32 Internet Time Helper Arduino Library v 1.0.1
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
* Copyright (c) 2019 K. Suwatchai (Mobizt)
|
||||
*
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person returning a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef ESP32TimeHelper_CPP
|
||||
#define ESP32TimeHelper_CPP
|
||||
|
||||
#ifdef ESP32
|
||||
|
||||
#include "ESP32TimeHelper.h"
|
||||
|
||||
ESP32TimeHelper::ESP32TimeHelper()
|
||||
{
|
||||
}
|
||||
uint32_t ESP32TimeHelper::getUnixTime()
|
||||
{
|
||||
uint32_t utime = (msec_time_diff + millis()) / 1000;
|
||||
return utime;
|
||||
}
|
||||
|
||||
time_t ESP32TimeHelper::getTimestamp(int year, int mon, int date, int hour, int mins, int sec)
|
||||
{
|
||||
struct tm timeinfo;
|
||||
timeinfo.tm_year = year - 1900;
|
||||
timeinfo.tm_mon = mon - 1;
|
||||
timeinfo.tm_mday = date;
|
||||
timeinfo.tm_hour = hour;
|
||||
timeinfo.tm_min = mins;
|
||||
timeinfo.tm_sec = sec;
|
||||
time_t ts = mktime(&timeinfo);
|
||||
return ts;
|
||||
}
|
||||
|
||||
bool ESP32TimeHelper::setClock(float gmtOffset, float daylightOffset)
|
||||
{
|
||||
TZ = gmtOffset;
|
||||
DST_MN = daylightOffset;
|
||||
configTime((TZ)*3600, (DST_MN)*60, "pool.ntp.org", "time.nist.gov", NULL);
|
||||
|
||||
now = time(nullptr);
|
||||
int cnt = 0;
|
||||
while (now < 8 * 3600 * 2 && cnt < 20)
|
||||
{
|
||||
delay(50);
|
||||
now = time(nullptr);
|
||||
cnt++;
|
||||
}
|
||||
|
||||
uint64_t tmp = now;
|
||||
tmp = tmp * 1000;
|
||||
msec_time_diff = tmp - millis();
|
||||
|
||||
getLocalTime(&timeinfo);
|
||||
|
||||
clockReady = now > 8 * 3600 * 2;
|
||||
return clockReady;
|
||||
}
|
||||
|
||||
int ESP32TimeHelper::getYear()
|
||||
{
|
||||
getLocalTime(&timeinfo);
|
||||
return timeinfo.tm_year + 1900;
|
||||
}
|
||||
int ESP32TimeHelper::getMonth()
|
||||
{
|
||||
getLocalTime(&timeinfo);
|
||||
return timeinfo.tm_mon + 1;
|
||||
}
|
||||
int ESP32TimeHelper::getDay()
|
||||
{
|
||||
getLocalTime(&timeinfo);
|
||||
return timeinfo.tm_mday;
|
||||
}
|
||||
|
||||
int ESP32TimeHelper::getDayOfWeek()
|
||||
{
|
||||
getLocalTime(&timeinfo);
|
||||
return timeinfo.tm_wday;
|
||||
}
|
||||
String ESP32TimeHelper::getDayOfWeekString()
|
||||
{
|
||||
getLocalTime(&timeinfo);
|
||||
return dow[timeinfo.tm_wday];
|
||||
}
|
||||
|
||||
int ESP32TimeHelper::getHour()
|
||||
{
|
||||
getLocalTime(&timeinfo);
|
||||
return timeinfo.tm_hour;
|
||||
}
|
||||
|
||||
int ESP32TimeHelper::getMin()
|
||||
{
|
||||
getLocalTime(&timeinfo);
|
||||
return timeinfo.tm_min;
|
||||
}
|
||||
int ESP32TimeHelper::getSec()
|
||||
{
|
||||
getLocalTime(&timeinfo);
|
||||
return timeinfo.tm_sec;
|
||||
}
|
||||
int ESP32TimeHelper::getNumberOfDayThisYear()
|
||||
{
|
||||
getLocalTime(&timeinfo);
|
||||
return timeinfo.tm_yday + 1;
|
||||
}
|
||||
|
||||
int ESP32TimeHelper::totalDays(int y, int m, int d)
|
||||
{
|
||||
static char daytab[2][13] =
|
||||
{
|
||||
{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
|
||||
{0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}};
|
||||
int daystotal = d;
|
||||
for (int year = 1; year <= y; year++)
|
||||
{
|
||||
int max_month = (year < y ? 12 : m - 1);
|
||||
int leap = (year % 4 == 0);
|
||||
if (year % 100 == 0 && year % 400 != 0)
|
||||
leap = 0;
|
||||
for (int month = 1; month <= max_month; month++)
|
||||
{
|
||||
daystotal += daytab[leap][month];
|
||||
}
|
||||
}
|
||||
return daystotal;
|
||||
}
|
||||
int ESP32TimeHelper::getTotalDays(int year, int month, int day)
|
||||
{
|
||||
return totalDays(year, month, day) - totalDays(1970, 1, 1);
|
||||
}
|
||||
|
||||
int ESP32TimeHelper::dayofWeek(int year, int month, int day) /* 1 <= m <= 12, y > 1752 (in the U.K.) */
|
||||
{
|
||||
static int t[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4};
|
||||
year -= month < 3;
|
||||
return (year + year / 4 - year / 100 + year / 400 + t[month - 1] + day) % 7;
|
||||
}
|
||||
|
||||
int ESP32TimeHelper::getCurrentSecond()
|
||||
{
|
||||
return (timeinfo.tm_hour * 3600) + (timeinfo.tm_min * 60) + timeinfo.tm_sec;
|
||||
}
|
||||
uint64_t ESP32TimeHelper::getCurrentTimestamp()
|
||||
{
|
||||
return now;
|
||||
}
|
||||
void ESP32TimeHelper::getTimeFromSec(int secCount, int &yrs, int &months, int &days, int &hr, int &min, int &sec)
|
||||
{
|
||||
int _yrs = secCount / (365 * 24 * 3600);
|
||||
secCount = secCount - _yrs * (365 * 24 * 3600);
|
||||
yrs = _yrs;
|
||||
int _months = secCount / (30* 24 * 3600);
|
||||
secCount = secCount - _months * (30 * 24 * 3600);
|
||||
months = _months;
|
||||
int _days = secCount / (24 * 3600);
|
||||
secCount = secCount - _days * (24 * 3600);
|
||||
days = _days;
|
||||
int _hr = secCount / 3600;
|
||||
secCount = secCount - _hr * 3600;
|
||||
hr = _hr;
|
||||
int _min = secCount / 60;
|
||||
secCount = secCount - _min * 60;
|
||||
min = _min;
|
||||
sec = secCount;
|
||||
}
|
||||
|
||||
#endif //ESP32
|
||||
|
||||
#endif //ESP32TimeHelper_CPP
|
73
libesp32/ESP32-Mail-Client/src/ESP32TimeHelper.h
Executable file
73
libesp32/ESP32-Mail-Client/src/ESP32TimeHelper.h
Executable file
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* ESP32 Internet Time Helper Arduino Library v 1.0.1
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
* Copyright (c) 2019 K. Suwatchai (Mobizt)
|
||||
*
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person returning a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef ESP32TimeHelper_H
|
||||
#define ESP32TimeHelper_H
|
||||
|
||||
#ifdef ESP32
|
||||
|
||||
|
||||
#include <time.h>
|
||||
#include <Arduino.h>
|
||||
#include <WiFi.h>
|
||||
|
||||
class ESP32TimeHelper
|
||||
{
|
||||
public:
|
||||
ESP32TimeHelper();
|
||||
bool clockReady = false;
|
||||
bool setClock(float gmtOffset, float daylightOffset);
|
||||
uint32_t getUnixTime();
|
||||
time_t getTimestamp(int year, int mon, int date, int hour, int mins, int sec);
|
||||
int getYear();
|
||||
int getMonth();
|
||||
int getDay();
|
||||
int getDayOfWeek();
|
||||
String getDayOfWeekString();
|
||||
int getHour();
|
||||
int getMin();
|
||||
int getSec();
|
||||
int getNumberOfDayThisYear();
|
||||
int getTotalDays(int year, int month, int day);
|
||||
int dayofWeek(int year, int month, int day);
|
||||
int getCurrentSecond();
|
||||
uint64_t getCurrentTimestamp();
|
||||
void getTimeFromSec(int secCount, int &yrs, int &months, int &days, int &hr, int &min, int &sec);
|
||||
|
||||
private:
|
||||
time_t now;
|
||||
uint64_t msec_time_diff = 0;
|
||||
struct tm timeinfo;
|
||||
float TZ = 0.0;
|
||||
float DST_MN = 0.0;
|
||||
|
||||
bool setClock();
|
||||
int totalDays(int y, int m, int d);
|
||||
const char *dow[20] = {"sunday", "monday", "tuesday", "wednesday", "thurseday", "friday", "saturday"};
|
||||
};
|
||||
|
||||
#endif //ESP32
|
||||
|
||||
#endif //ESP32TimeHelper_H
|
4875
libesp32/ESP32-Mail-Client/src/ESP32_MailClient.cpp
Executable file
4875
libesp32/ESP32-Mail-Client/src/ESP32_MailClient.cpp
Executable file
File diff suppressed because it is too large
Load Diff
1908
libesp32/ESP32-Mail-Client/src/ESP32_MailClient.h
Executable file
1908
libesp32/ESP32-Mail-Client/src/ESP32_MailClient.h
Executable file
File diff suppressed because it is too large
Load Diff
240
libesp32/ESP32-Mail-Client/src/RFC2047.cpp
Executable file
240
libesp32/ESP32-Mail-Client/src/RFC2047.cpp
Executable file
@ -0,0 +1,240 @@
|
||||
#ifndef RFC2047_CPP
|
||||
#define RFC2047_CPP
|
||||
|
||||
#ifdef ESP32
|
||||
|
||||
#include "RFC2047.h"
|
||||
|
||||
RFC2047::RFC2047(){}
|
||||
|
||||
|
||||
void RFC2047::rfc2047Decode(char *d, const char *s, size_t dlen){
|
||||
|
||||
const char *p, *q;
|
||||
size_t n;
|
||||
int found_encoded = 0;
|
||||
|
||||
dlen--; /* save room for the terminal nul */
|
||||
|
||||
while (*s && dlen > 0)
|
||||
{
|
||||
if ((p = strstr (s, "=?")) == NULL ||
|
||||
(q = strchr (p + 2, '?')) == NULL ||
|
||||
(q = strchr (q + 1, '?')) == NULL ||
|
||||
(q = strstr (q + 1, "?=")) == NULL)
|
||||
{
|
||||
/* no encoded words */
|
||||
if (d != s)
|
||||
strfcpy (d, s, dlen + 1);
|
||||
return;
|
||||
}
|
||||
|
||||
if (p != s)
|
||||
{
|
||||
n = (size_t) (p - s);
|
||||
/* ignore spaces between encoded words */
|
||||
if (!found_encoded || strspn (s, " \t\r\n") != n)
|
||||
{
|
||||
if (n > dlen)
|
||||
n = dlen;
|
||||
if (d != s)
|
||||
memcpy (d, s, n);
|
||||
d += n;
|
||||
dlen -= n;
|
||||
}
|
||||
}
|
||||
|
||||
rfc2047DecodeWord (d, p, dlen);
|
||||
found_encoded = 1;
|
||||
s = q + 2;
|
||||
n = strlen (d);
|
||||
dlen -= n;
|
||||
d += n;
|
||||
}
|
||||
*d = 0;
|
||||
|
||||
}
|
||||
|
||||
void RFC2047::rfc2047DecodeWord(char *d, const char *s, size_t dlen){
|
||||
|
||||
char *p = safe_strdup (s);
|
||||
char *pp = p;
|
||||
char *pd = d;
|
||||
size_t len = dlen;
|
||||
int enc = 0, filter = 0, count = 0, c1, c2, c3, c4;
|
||||
|
||||
while ((pp = strtok (pp, "?")) != NULL)
|
||||
{
|
||||
count++;
|
||||
switch (count)
|
||||
{
|
||||
case 2:
|
||||
if (strcasecmp (pp, Charset) != 0)
|
||||
{
|
||||
filter = 1;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
if (toupper (*pp) == 'Q')
|
||||
enc = ENCQUOTEDPRINTABLE;
|
||||
else if (toupper (*pp) == 'B')
|
||||
enc = ENCBASE64;
|
||||
else
|
||||
return;
|
||||
break;
|
||||
case 4:
|
||||
if (enc == ENCQUOTEDPRINTABLE)
|
||||
{
|
||||
while (*pp && len > 0)
|
||||
{
|
||||
if (*pp == '_')
|
||||
{
|
||||
*pd++ = ' ';
|
||||
len--;
|
||||
}
|
||||
else if (*pp == '=')
|
||||
{
|
||||
*pd++ = (hexval(pp[1]) << 4) | hexval(pp[2]);
|
||||
len--;
|
||||
pp += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
*pd++ = *pp;
|
||||
len--;
|
||||
}
|
||||
pp++;
|
||||
}
|
||||
*pd = 0;
|
||||
}
|
||||
else if (enc == ENCBASE64)
|
||||
{
|
||||
while (*pp && len > 0)
|
||||
{
|
||||
c1 = base64val(pp[0]);
|
||||
c2 = base64val(pp[1]);
|
||||
*pd++ = (c1 << 2) | ((c2 >> 4) & 0x3);
|
||||
if (--len == 0) break;
|
||||
|
||||
if (pp[2] == '=') break;
|
||||
|
||||
c3 = base64val(pp[2]);
|
||||
*pd++ = ((c2 & 0xf) << 4) | ((c3 >> 2) & 0xf);
|
||||
if (--len == 0)
|
||||
break;
|
||||
|
||||
if (pp[3] == '=')
|
||||
break;
|
||||
|
||||
c4 = base64val(pp[3]);
|
||||
*pd++ = ((c3 & 0x3) << 6) | c4;
|
||||
if (--len == 0)
|
||||
break;
|
||||
|
||||
pp += 4;
|
||||
}
|
||||
*pd = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
pp = 0;
|
||||
}
|
||||
safe_free (&p);
|
||||
if (filter)
|
||||
{
|
||||
|
||||
pd = d;
|
||||
while (*pd)
|
||||
{
|
||||
if (!IsPrint (*pd))
|
||||
*pd = '?';
|
||||
pd++;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void *RFC2047::safe_calloc (size_t nmemb, size_t size)
|
||||
{
|
||||
void *p;
|
||||
|
||||
if (!nmemb || !size)
|
||||
return NULL;
|
||||
if (!(p = calloc (nmemb, size)))
|
||||
{
|
||||
//out of memory
|
||||
return NULL;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
void *RFC2047::safe_malloc (unsigned int siz)
|
||||
{
|
||||
void *p;
|
||||
|
||||
if (siz == 0)
|
||||
return 0;
|
||||
if ((p = (void *) malloc (siz)) == 0)
|
||||
{
|
||||
//out of memory
|
||||
return NULL;
|
||||
}
|
||||
return (p);
|
||||
}
|
||||
|
||||
void RFC2047::safe_realloc (void **p, size_t siz)
|
||||
{
|
||||
void *r;
|
||||
|
||||
if (siz == 0)
|
||||
{
|
||||
if (*p)
|
||||
{
|
||||
free (*p);
|
||||
*p = NULL;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (*p)
|
||||
r = (void *) realloc (*p, siz);
|
||||
else
|
||||
{
|
||||
r = (void *) malloc (siz);
|
||||
}
|
||||
|
||||
if (!r)
|
||||
{
|
||||
//out of memory
|
||||
return;
|
||||
}
|
||||
|
||||
*p = r;
|
||||
}
|
||||
|
||||
void RFC2047::safe_free (void *ptr)
|
||||
{
|
||||
void **p = (void **)ptr;
|
||||
if (*p)
|
||||
{
|
||||
free (*p);
|
||||
*p = 0;
|
||||
}
|
||||
}
|
||||
|
||||
char *RFC2047::safe_strdup (const char *s)
|
||||
{
|
||||
char *p;
|
||||
size_t l;
|
||||
|
||||
if (!s || !*s) return 0;
|
||||
l = strlen (s) + 1;
|
||||
p = (char *)safe_malloc (l);
|
||||
memcpy (p, s, l);
|
||||
return (p);
|
||||
}
|
||||
|
||||
#endif //ESP32
|
||||
|
||||
#endif //RFC2047_CPP
|
70
libesp32/ESP32-Mail-Client/src/RFC2047.h
Executable file
70
libesp32/ESP32-Mail-Client/src/RFC2047.h
Executable file
@ -0,0 +1,70 @@
|
||||
|
||||
#ifndef RFC2047_H
|
||||
#define RFC2047_H
|
||||
|
||||
#ifdef ESP32
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
|
||||
#define strfcpy(A,B,C) strncpy(A,B,C), *(A+(C)-1)=0
|
||||
|
||||
enum
|
||||
{
|
||||
ENCOTHER,
|
||||
ENC7BIT,
|
||||
ENC8BIT,
|
||||
ENCQUOTEDPRINTABLE,
|
||||
ENCBASE64,
|
||||
ENCBINARY
|
||||
};
|
||||
|
||||
__attribute__((used)) static const char *Charset = "utf-8";
|
||||
|
||||
__attribute__((used)) static int Index_hex[128] = {
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
|
||||
-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
|
||||
|
||||
__attribute__((used)) static int Index_64[128] = {
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
|
||||
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
|
||||
-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
|
||||
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
|
||||
-1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
|
||||
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1};
|
||||
|
||||
#define IsPrint(c) (isprint((unsigned char)(c)) || \
|
||||
((unsigned char)(c) >= 0xa0))
|
||||
|
||||
#define hexval(c) Index_hex[(unsigned int)(c)]
|
||||
#define base64val(c) Index_64[(unsigned int)(c)]
|
||||
|
||||
class RFC2047{
|
||||
|
||||
public:
|
||||
RFC2047();
|
||||
void rfc2047Decode(char *d, const char *s, size_t dlen);
|
||||
|
||||
|
||||
private:
|
||||
void rfc2047DecodeWord(char *d, const char *s, size_t dlen);
|
||||
void *safe_calloc (size_t nmemb, size_t size);
|
||||
void *safe_malloc (unsigned int siz);
|
||||
void safe_realloc (void **p, size_t siz);
|
||||
void safe_free (void *ptr);
|
||||
char *safe_strdup (const char *s);
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif //ESP32
|
||||
|
||||
#endif //RFC2047_H
|
397
libesp32/ESP32-Mail-Client/src/WiFiClientSecureESP32.cpp
Executable file
397
libesp32/ESP32-Mail-Client/src/WiFiClientSecureESP32.cpp
Executable file
@ -0,0 +1,397 @@
|
||||
/*
|
||||
*Customized WiFiClientSecure.cpp to support STARTTLS protocol, version 1.0.1
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
* Copyright (c) 2019 K. Suwatchai (Mobizt)
|
||||
*
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
WiFiClientSecureESP32.cpp - Client Secure class for ESP32
|
||||
Copyright (c) 2016 Hristo Gochkov All right reserved.
|
||||
Additions Copyright (C) 2017 Evandro Luis Copercini.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef WiFiClientSecureESP32_CPP
|
||||
#define WiFiClientSecureESP32_CPP
|
||||
|
||||
#ifdef ESP32
|
||||
|
||||
#include "WiFiClientSecureESP32.h"
|
||||
#include <lwip/sockets.h>
|
||||
#include <lwip/netdb.h>
|
||||
#include <errno.h>
|
||||
|
||||
#undef connect
|
||||
#undef write
|
||||
#undef read
|
||||
|
||||
|
||||
WiFiClientSecureESP32::WiFiClientSecureESP32()
|
||||
{
|
||||
_connected = false;
|
||||
|
||||
sslclient = new sslclient_context32;
|
||||
ssl_init(sslclient);
|
||||
sslclient->socket = -1;
|
||||
sslclient->handshake_timeout = 120000;
|
||||
_CA_cert = NULL;
|
||||
_cert = NULL;
|
||||
_private_key = NULL;
|
||||
_pskIdent = NULL;
|
||||
_psKey = NULL;
|
||||
next = NULL;
|
||||
}
|
||||
|
||||
|
||||
WiFiClientSecureESP32::WiFiClientSecureESP32(int sock)
|
||||
{
|
||||
_connected = false;
|
||||
_timeout = 0;
|
||||
|
||||
sslclient = new sslclient_context32;
|
||||
ssl_init(sslclient);
|
||||
sslclient->socket = sock;
|
||||
sslclient->handshake_timeout = 120000;
|
||||
|
||||
if (sock >= 0) {
|
||||
_connected = true;
|
||||
}
|
||||
|
||||
_CA_cert = NULL;
|
||||
_cert = NULL;
|
||||
_private_key = NULL;
|
||||
_pskIdent = NULL;
|
||||
_psKey = NULL;
|
||||
next = NULL;
|
||||
}
|
||||
|
||||
WiFiClientSecureESP32::WiFiClientSecureESP32(bool starttls)
|
||||
{
|
||||
_connected = false;
|
||||
|
||||
sslclient = new sslclient_context32;
|
||||
ssl_init(sslclient);
|
||||
sslclient->socket = -1;
|
||||
sslclient->handshake_timeout = 120000;
|
||||
sslclient->starttls = true;
|
||||
_CA_cert = NULL;
|
||||
_cert = NULL;
|
||||
_private_key = NULL;
|
||||
_pskIdent = NULL;
|
||||
_psKey = NULL;
|
||||
next = NULL;
|
||||
}
|
||||
|
||||
WiFiClientSecureESP32::~WiFiClientSecureESP32()
|
||||
{
|
||||
stop();
|
||||
delete sslclient;
|
||||
}
|
||||
|
||||
WiFiClientSecureESP32 &WiFiClientSecureESP32::operator=(const WiFiClientSecureESP32 &other)
|
||||
{
|
||||
stop();
|
||||
sslclient->socket = other.sslclient->socket;
|
||||
_connected = other._connected;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void WiFiClientSecureESP32::stop()
|
||||
{
|
||||
if (sslclient->socket >= 0) {
|
||||
close(sslclient->socket);
|
||||
sslclient->socket = -1;
|
||||
_connected = false;
|
||||
_peek = -1;
|
||||
}
|
||||
stop_ssl_socket(sslclient, _CA_cert, _cert, _private_key);
|
||||
}
|
||||
|
||||
int WiFiClientSecureESP32::connect(IPAddress ip, uint16_t port)
|
||||
{
|
||||
if (_pskIdent && _psKey)
|
||||
return connect(ip, port, _pskIdent, _psKey);
|
||||
return connect(ip, port, _CA_cert, _cert, _private_key);
|
||||
}
|
||||
|
||||
int WiFiClientSecureESP32::connect(IPAddress ip, uint16_t port, int32_t timeout){
|
||||
_timeout = timeout;
|
||||
return connect(ip, port);
|
||||
}
|
||||
|
||||
int WiFiClientSecureESP32::connect(const char *host, uint16_t port)
|
||||
{
|
||||
if (_pskIdent && _psKey)
|
||||
return connect(host, port, _pskIdent, _psKey);
|
||||
return connect(host, port, _CA_cert, _cert, _private_key);
|
||||
}
|
||||
|
||||
int WiFiClientSecureESP32::connect(const char *host, uint16_t port, int32_t timeout){
|
||||
_timeout = timeout;
|
||||
return connect(host, port);
|
||||
}
|
||||
|
||||
int WiFiClientSecureESP32::connect(IPAddress ip, uint16_t port, const char *_CA_cert, const char *_cert, const char *_private_key)
|
||||
{
|
||||
return connect(ip.toString().c_str(), port, _CA_cert, _cert, _private_key);
|
||||
}
|
||||
|
||||
int WiFiClientSecureESP32::connect(const char *host, uint16_t port, const char *_CA_cert, const char *_cert, const char *_private_key)
|
||||
{
|
||||
if(_timeout > 0){
|
||||
sslclient->handshake_timeout = _timeout;
|
||||
}
|
||||
int ret = start_ssl_client(sslclient, host, port, _timeout, _CA_cert, _cert, _private_key, NULL, NULL);
|
||||
_lastError = ret;
|
||||
if (ret < 0) {
|
||||
log_e("start_ssl_client: %d", ret);
|
||||
stop();
|
||||
return 0;
|
||||
}
|
||||
_connected = true;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int WiFiClientSecureESP32::connect(IPAddress ip, uint16_t port, const char *pskIdent, const char *psKey) {
|
||||
return connect(ip.toString().c_str(), port,_pskIdent, _psKey);
|
||||
}
|
||||
|
||||
int WiFiClientSecureESP32::connect(const char *host, uint16_t port, const char *pskIdent, const char *psKey) {
|
||||
log_v("start_ssl_client with PSK");
|
||||
if(_timeout > 0){
|
||||
sslclient->handshake_timeout = _timeout;
|
||||
}
|
||||
int ret = start_ssl_client(sslclient, host, port, _timeout, NULL, NULL, NULL, _pskIdent, _psKey);
|
||||
_lastError = ret;
|
||||
if (ret < 0) {
|
||||
log_e("start_ssl_client: %d", ret);
|
||||
stop();
|
||||
return 0;
|
||||
}
|
||||
_connected = true;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int WiFiClientSecureESP32::peek(){
|
||||
if(_peek >= 0){
|
||||
return _peek;
|
||||
}
|
||||
_peek = timedRead();
|
||||
return _peek;
|
||||
}
|
||||
|
||||
size_t WiFiClientSecureESP32::write(uint8_t data)
|
||||
{
|
||||
return write(&data, 1);
|
||||
}
|
||||
|
||||
int WiFiClientSecureESP32::read()
|
||||
{
|
||||
uint8_t data = -1;
|
||||
int res = read(&data, 1);
|
||||
if (res < 0) {
|
||||
return res;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
size_t WiFiClientSecureESP32::write(const uint8_t *buf, size_t size)
|
||||
{
|
||||
if (!_connected) {
|
||||
return 0;
|
||||
}
|
||||
int res = send_ssl_data(sslclient, buf, size);
|
||||
if (res < 0) {
|
||||
stop();
|
||||
res = 0;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
int WiFiClientSecureESP32::read(uint8_t *buf, size_t size)
|
||||
{
|
||||
int peeked = 0;
|
||||
int avail = available();
|
||||
if ((!buf && size) || avail <= 0) {
|
||||
return -1;
|
||||
}
|
||||
if(!size){
|
||||
return 0;
|
||||
}
|
||||
if(_peek >= 0){
|
||||
buf[0] = _peek;
|
||||
_peek = -1;
|
||||
size--;
|
||||
avail--;
|
||||
if(!size || !avail){
|
||||
return 1;
|
||||
}
|
||||
buf++;
|
||||
peeked = 1;
|
||||
}
|
||||
|
||||
int res = get_ssl_receive(sslclient, buf, size);
|
||||
if (res < 0) {
|
||||
stop();
|
||||
return peeked?peeked:res;
|
||||
}
|
||||
return res + peeked;
|
||||
}
|
||||
|
||||
int WiFiClientSecureESP32::available()
|
||||
{
|
||||
int peeked = (_peek >= 0);
|
||||
if (!_connected) {
|
||||
return peeked;
|
||||
}
|
||||
int res = data_to_read(sslclient);
|
||||
if (res < 0) {
|
||||
stop();
|
||||
return peeked?peeked:res;
|
||||
}
|
||||
return res+peeked;
|
||||
}
|
||||
|
||||
uint8_t WiFiClientSecureESP32::connected()
|
||||
{
|
||||
uint8_t dummy = 0;
|
||||
read(&dummy, 0);
|
||||
|
||||
return _connected;
|
||||
}
|
||||
|
||||
void WiFiClientSecureESP32::setCACert (const char *rootCA)
|
||||
{
|
||||
_CA_cert = rootCA;
|
||||
}
|
||||
|
||||
void WiFiClientSecureESP32::setCertificate (const char *client_ca)
|
||||
{
|
||||
_cert = client_ca;
|
||||
}
|
||||
|
||||
void WiFiClientSecureESP32::setPrivateKey (const char *private_key)
|
||||
{
|
||||
_private_key = private_key;
|
||||
}
|
||||
|
||||
void WiFiClientSecureESP32::setPreSharedKey(const char *pskIdent, const char *psKey) {
|
||||
_pskIdent = pskIdent;
|
||||
_psKey = psKey;
|
||||
}
|
||||
|
||||
bool WiFiClientSecureESP32::verify(const char* fp, const char* domain_name)
|
||||
{
|
||||
if (!sslclient)
|
||||
return false;
|
||||
|
||||
return verify_ssl_fingerprint(sslclient, fp, domain_name);
|
||||
}
|
||||
|
||||
char *WiFiClientSecureESP32::_streamLoad(Stream& stream, size_t size) {
|
||||
static char *dest = nullptr;
|
||||
if(dest) {
|
||||
free(dest);
|
||||
}
|
||||
dest = (char*)malloc(size);
|
||||
if (!dest) {
|
||||
return nullptr;
|
||||
}
|
||||
if (size != stream.readBytes(dest, size)) {
|
||||
free(dest);
|
||||
dest = nullptr;
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
|
||||
bool WiFiClientSecureESP32::loadCACert(Stream& stream, size_t size) {
|
||||
char *dest = _streamLoad(stream, size);
|
||||
bool ret = false;
|
||||
if (dest) {
|
||||
setCACert(dest);
|
||||
ret = true;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool WiFiClientSecureESP32::loadCertificate(Stream& stream, size_t size) {
|
||||
char *dest = _streamLoad(stream, size);
|
||||
bool ret = false;
|
||||
if (dest) {
|
||||
setCertificate(dest);
|
||||
ret = true;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool WiFiClientSecureESP32::loadPrivateKey(Stream& stream, size_t size) {
|
||||
char *dest = _streamLoad(stream, size);
|
||||
bool ret = false;
|
||||
if (dest) {
|
||||
setPrivateKey(dest);
|
||||
ret = true;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int WiFiClientSecureESP32::lastError(char *buf, const size_t size)
|
||||
{
|
||||
if (!_lastError) {
|
||||
return 0;
|
||||
}
|
||||
char error_buf[100];
|
||||
mbedtls_strerror(_lastError, error_buf, 100);
|
||||
snprintf(buf, size, "%s", error_buf);
|
||||
return _lastError;
|
||||
}
|
||||
|
||||
void WiFiClientSecureESP32::setHandshakeTimeout(unsigned long handshake_timeout)
|
||||
{
|
||||
sslclient->handshake_timeout = handshake_timeout * 1000;
|
||||
}
|
||||
|
||||
void WiFiClientSecureESP32::setSTARTTLS(bool starttls)
|
||||
{
|
||||
sslclient->starttls = starttls;
|
||||
}
|
||||
|
||||
void WiFiClientSecureESP32::setDebugCB(DebugMsgCallback cb)
|
||||
{
|
||||
sslclient->_debugCallback = std::move(cb);
|
||||
}
|
||||
|
||||
#endif //ESP32
|
||||
|
||||
#endif //WiFiClientSecureESP32_CPP
|
145
libesp32/ESP32-Mail-Client/src/WiFiClientSecureESP32.h
Executable file
145
libesp32/ESP32-Mail-Client/src/WiFiClientSecureESP32.h
Executable file
@ -0,0 +1,145 @@
|
||||
|
||||
/*
|
||||
*Customized WiFiClientSecure.h to support STARTTLS protocol, version 1.0.1
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
* Copyright (c) 2019 K. Suwatchai (Mobizt)
|
||||
*
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
WiFiClientSecureESP32.h - Base class that provides Client SSL to ESP32
|
||||
Copyright (c) 2011 Adrian McEwen. All right reserved.
|
||||
Additions Copyright (C) 2017 Evandro Luis Copercini.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef WiFiClientSecureESP32_H
|
||||
#define WiFiClientSecureESP32_H
|
||||
|
||||
#ifdef ESP32
|
||||
|
||||
#include "Arduino.h"
|
||||
#include "IPAddress.h"
|
||||
#include <WiFi.h>
|
||||
#include "ssl_client32.h"
|
||||
|
||||
typedef void (*DebugMsgCallback)(const char* msg);
|
||||
|
||||
class WiFiClientSecureESP32 : public WiFiClient
|
||||
{
|
||||
protected:
|
||||
sslclient_context32 *sslclient;
|
||||
|
||||
int _lastError = 0;
|
||||
int _peek = -1;
|
||||
int _timeout = 0;
|
||||
const char *_CA_cert;
|
||||
const char *_cert;
|
||||
const char *_private_key;
|
||||
const char *_pskIdent; // identity for PSK cipher suites
|
||||
const char *_psKey; // key in hex for PSK cipher suites
|
||||
DebugMsgCallback _debugCallback = NULL;
|
||||
|
||||
public:
|
||||
WiFiClientSecureESP32 *next;
|
||||
WiFiClientSecureESP32();
|
||||
WiFiClientSecureESP32(int socket);
|
||||
WiFiClientSecureESP32(bool starttls);
|
||||
~WiFiClientSecureESP32();
|
||||
int connect(IPAddress ip, uint16_t port);
|
||||
int connect(IPAddress ip, uint16_t port, int32_t timeout);
|
||||
int connect(const char *host, uint16_t port);
|
||||
int connect(const char *host, uint16_t port, int32_t timeout);
|
||||
int connect(IPAddress ip, uint16_t port, const char *rootCABuff, const char *cli_cert, const char *cli_key);
|
||||
int connect(const char *host, uint16_t port, const char *rootCABuff, const char *cli_cert, const char *cli_key);
|
||||
int connect(IPAddress ip, uint16_t port, const char *pskIdent, const char *psKey);
|
||||
int connect(const char *host, uint16_t port, const char *pskIdent, const char *psKey);
|
||||
int peek();
|
||||
size_t write(uint8_t data);
|
||||
size_t write(const uint8_t *buf, size_t size);
|
||||
int available();
|
||||
int read();
|
||||
int read(uint8_t *buf, size_t size);
|
||||
void flush() {}
|
||||
void stop();
|
||||
uint8_t connected();
|
||||
int lastError(char *buf, const size_t size);
|
||||
void setPreSharedKey(const char *pskIdent, const char *psKey); // psKey in Hex
|
||||
void setCACert(const char *rootCA);
|
||||
void setCertificate(const char *client_ca);
|
||||
void setPrivateKey (const char *private_key);
|
||||
bool loadCACert(Stream& stream, size_t size);
|
||||
bool loadCertificate(Stream& stream, size_t size);
|
||||
bool loadPrivateKey(Stream& stream, size_t size);
|
||||
bool verify(const char* fingerprint, const char* domain_name);
|
||||
void setHandshakeTimeout(unsigned long handshake_timeout);
|
||||
void setSTARTTLS(bool starttls);
|
||||
void setDebugCB(DebugMsgCallback cb);
|
||||
|
||||
operator bool()
|
||||
{
|
||||
return connected();
|
||||
}
|
||||
WiFiClientSecureESP32 &operator=(const WiFiClientSecureESP32 &other);
|
||||
bool operator==(const bool value)
|
||||
{
|
||||
return bool() == value;
|
||||
}
|
||||
bool operator!=(const bool value)
|
||||
{
|
||||
return bool() != value;
|
||||
}
|
||||
bool operator==(const WiFiClientSecureESP32 &);
|
||||
bool operator!=(const WiFiClientSecureESP32 &rhs)
|
||||
{
|
||||
return !this->operator==(rhs);
|
||||
};
|
||||
|
||||
int socket()
|
||||
{
|
||||
return sslclient->socket = -1;
|
||||
}
|
||||
|
||||
private:
|
||||
char *_streamLoad(Stream& stream, size_t size);
|
||||
|
||||
//friend class WiFiServer;
|
||||
using Print::write;
|
||||
};
|
||||
|
||||
#endif //ESP32
|
||||
|
||||
#endif //WiFiClientSecureESP32_H
|
||||
|
||||
|
853
libesp32/ESP32-Mail-Client/src/ssl_client32.cpp
Executable file
853
libesp32/ESP32-Mail-Client/src/ssl_client32.cpp
Executable file
@ -0,0 +1,853 @@
|
||||
/*
|
||||
*Customized ssl_client.cpp to support STARTTLS protocol, version 1.0.3
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
* Copyright (c) 2019 K. Suwatchai (Mobizt)
|
||||
*
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/* Provide SSL/TLS functions to ESP32 with Arduino IDE
|
||||
*
|
||||
* Adapted from the ssl_client1 example of mbedtls.
|
||||
*
|
||||
* Original Copyright (C) 2006-2015, ARM Limited, All Rights Reserved, Apache 2.0 License.
|
||||
* Additions Copyright (C) 2017 Evandro Luis Copercini, Apache 2.0 License.
|
||||
*/
|
||||
|
||||
#ifndef SSL_CLIENT32_CPP
|
||||
#define SSL_CLIENT32_CPP
|
||||
|
||||
#ifdef ESP32
|
||||
|
||||
#include "Arduino.h"
|
||||
#include <esp32-hal-log.h>
|
||||
#include <lwip/err.h>
|
||||
#include <lwip/sockets.h>
|
||||
#include <lwip/sys.h>
|
||||
#include <lwip/netdb.h>
|
||||
#include <mbedtls/sha256.h>
|
||||
#include <mbedtls/oid.h>
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include "ssl_client32.h"
|
||||
#include "WiFi.h"
|
||||
|
||||
const char *pers32 = "esp32-tls";
|
||||
|
||||
static int handle_error(int err)
|
||||
{
|
||||
if (err == -30848)
|
||||
{
|
||||
return err;
|
||||
}
|
||||
#ifdef MBEDTLS_ERROR_C
|
||||
char error_buf[100];
|
||||
mbedtls_strerror(err, error_buf, 100);
|
||||
log_e("%s", error_buf);
|
||||
#endif
|
||||
log_e("MbedTLS message code: %d", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
void ssl_init(sslclient_context32 *ssl_client)
|
||||
{
|
||||
mbedtls_ssl_init(&ssl_client->ssl_ctx);
|
||||
mbedtls_ssl_config_init(&ssl_client->ssl_conf);
|
||||
mbedtls_ctr_drbg_init(&ssl_client->drbg_ctx);
|
||||
mbedtls_net_init(&ssl_client->server_fd);
|
||||
}
|
||||
|
||||
int start_ssl_client(sslclient_context32 *ssl_client, const char *host, uint32_t port, int timeout, const char *rootCABuff, const char *cli_cert, const char *cli_key, const char *pskIdent, const char *psKey)
|
||||
{
|
||||
char buf[512];
|
||||
int ret, flags;
|
||||
int enable = 1;
|
||||
|
||||
if (ssl_client->_debugCallback)
|
||||
ESP32SSLClientDebugInfo(ESP32_SSL_CLIENT_STR_2, ssl_client);
|
||||
|
||||
log_v("Free internal heap before TLS %u", ESP.getFreeHeap());
|
||||
|
||||
log_v("Starting socket");
|
||||
ssl_client->socket = -1;
|
||||
|
||||
ssl_client->socket = lwip_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
if (ssl_client->socket < 0)
|
||||
{
|
||||
if (ssl_client->_debugCallback)
|
||||
ESP32SSLClientDebugInfo(ESP32_SSL_CLIENT_STR_3, ssl_client);
|
||||
log_e("ERROR opening socket");
|
||||
return ssl_client->socket;
|
||||
}
|
||||
|
||||
IPAddress srv((uint32_t)0);
|
||||
if (!WiFiGenericClass::hostByName(host, srv))
|
||||
{
|
||||
if (ssl_client->_debugCallback)
|
||||
ESP32SSLClientDebugInfo(ESP32_SSL_CLIENT_STR_4, ssl_client);
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct sockaddr_in serv_addr;
|
||||
memset(&serv_addr, 0, sizeof(serv_addr));
|
||||
serv_addr.sin_family = AF_INET;
|
||||
serv_addr.sin_addr.s_addr = srv;
|
||||
serv_addr.sin_port = htons(port);
|
||||
|
||||
if (ssl_client->_debugCallback)
|
||||
ESP32SSLClientDebugInfo(ESP32_SSL_CLIENT_STR_5, ssl_client);
|
||||
|
||||
if (lwip_connect(ssl_client->socket, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) == 0)
|
||||
{
|
||||
if (timeout <= 0)
|
||||
{
|
||||
timeout = 30000;
|
||||
}
|
||||
lwip_setsockopt(ssl_client->socket, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
|
||||
lwip_setsockopt(ssl_client->socket, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout));
|
||||
lwip_setsockopt(ssl_client->socket, IPPROTO_TCP, TCP_NODELAY, &enable, sizeof(enable));
|
||||
lwip_setsockopt(ssl_client->socket, SOL_SOCKET, SO_KEEPALIVE, &enable, sizeof(enable));
|
||||
|
||||
if (ssl_client->_debugCallback)
|
||||
ESP32SSLClientDebugInfo(ESP32_SSL_CLIENT_STR_6, ssl_client);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ssl_client->_debugCallback)
|
||||
ESP32SSLClientDebugInfo(ESP32_SSL_CLIENT_STR_7, ssl_client);
|
||||
log_e("Connect to Server failed!");
|
||||
return -1;
|
||||
}
|
||||
|
||||
fcntl(ssl_client->socket, F_SETFL, fcntl(ssl_client->socket, F_GETFL, 0) | O_NONBLOCK);
|
||||
|
||||
if (ssl_client->starttls && (port == 25 || port == 587 || port == 143))
|
||||
{
|
||||
|
||||
if (ssl_client->_debugCallback)
|
||||
ESP32SSLClientDebugInfo(ESP32_SSL_CLIENT_STR_8, ssl_client);
|
||||
|
||||
if ((ret = starttlsHandshake(ssl_client, port)) != 0)
|
||||
{
|
||||
log_e("STARTTLS failed!");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (ssl_client->_debugCallback)
|
||||
ESP32SSLClientDebugInfo(ESP32_SSL_CLIENT_STR_9, ssl_client);
|
||||
|
||||
log_v("Seeding the random number generator");
|
||||
mbedtls_entropy_init(&ssl_client->entropy_ctx);
|
||||
|
||||
ret = mbedtls_ctr_drbg_seed(&ssl_client->drbg_ctx, mbedtls_entropy_func,
|
||||
&ssl_client->entropy_ctx, (const unsigned char *)pers32, strlen(pers32));
|
||||
if (ret < 0)
|
||||
{
|
||||
if (ssl_client->_debugCallback)
|
||||
{
|
||||
char *error_buf = new char[100];
|
||||
memset(buf, 0, 512);
|
||||
strcpy_P(buf, ESP32_SSL_CLIENT_STR_1);
|
||||
mbedtls_strerror(ret, error_buf, 100);
|
||||
strcat(buf, error_buf);
|
||||
ssl_client->_debugCallback(buf);
|
||||
delete[] error_buf;
|
||||
}
|
||||
|
||||
return handle_error(ret);
|
||||
}
|
||||
|
||||
if (ssl_client->_debugCallback)
|
||||
ESP32SSLClientDebugInfo(ESP32_SSL_CLIENT_STR_10, ssl_client);
|
||||
|
||||
log_v("Setting up the SSL/TLS structure...");
|
||||
|
||||
if ((ret = mbedtls_ssl_config_defaults(&ssl_client->ssl_conf,
|
||||
MBEDTLS_SSL_IS_CLIENT,
|
||||
MBEDTLS_SSL_TRANSPORT_STREAM,
|
||||
MBEDTLS_SSL_PRESET_DEFAULT)) != 0)
|
||||
{
|
||||
if (ssl_client->_debugCallback)
|
||||
{
|
||||
char *error_buf = new char[100];
|
||||
memset(buf, 0, 512);
|
||||
strcpy_P(buf, ESP32_SSL_CLIENT_STR_1);
|
||||
mbedtls_strerror(ret, error_buf, 100);
|
||||
strcat(buf, error_buf);
|
||||
ssl_client->_debugCallback(buf);
|
||||
delete[] error_buf;
|
||||
}
|
||||
return handle_error(ret);
|
||||
}
|
||||
|
||||
// MBEDTLS_SSL_VERIFY_REQUIRED if a CA certificate is defined on Arduino IDE and
|
||||
// MBEDTLS_SSL_VERIFY_NONE if not.
|
||||
|
||||
if (rootCABuff != NULL)
|
||||
{
|
||||
if (ssl_client->_debugCallback)
|
||||
ESP32SSLClientDebugInfo(ESP32_SSL_CLIENT_STR_11, ssl_client);
|
||||
log_v("Loading CA cert");
|
||||
mbedtls_x509_crt_init(&ssl_client->ca_cert);
|
||||
mbedtls_ssl_conf_authmode(&ssl_client->ssl_conf, MBEDTLS_SSL_VERIFY_REQUIRED);
|
||||
ret = mbedtls_x509_crt_parse(&ssl_client->ca_cert, (const unsigned char *)rootCABuff, strlen(rootCABuff) + 1);
|
||||
mbedtls_ssl_conf_ca_chain(&ssl_client->ssl_conf, &ssl_client->ca_cert, NULL);
|
||||
//mbedtls_ssl_conf_verify(&ssl_client->ssl_ctx, my_verify, NULL );
|
||||
if (ret < 0)
|
||||
{
|
||||
if (ssl_client->_debugCallback)
|
||||
{
|
||||
char *error_buf = new char[100];
|
||||
memset(buf, 0, 512);
|
||||
strcpy_P(buf, ESP32_SSL_CLIENT_STR_1);
|
||||
mbedtls_strerror(ret, error_buf, 100);
|
||||
strcat(buf, error_buf);
|
||||
ssl_client->_debugCallback(buf);
|
||||
delete[] error_buf;
|
||||
}
|
||||
return handle_error(ret);
|
||||
}
|
||||
}
|
||||
else if (pskIdent != NULL && psKey != NULL)
|
||||
{
|
||||
if (ssl_client->_debugCallback)
|
||||
ESP32SSLClientDebugInfo(ESP32_SSL_CLIENT_STR_12, ssl_client);
|
||||
log_v("Setting up PSK");
|
||||
// convert PSK from hex to binary
|
||||
if ((strlen(psKey) & 1) != 0 || strlen(psKey) > 2 * MBEDTLS_PSK_MAX_LEN)
|
||||
{
|
||||
if (ssl_client->_debugCallback)
|
||||
ESP32SSLClientDebugInfo(ESP32_SSL_CLIENT_STR_13, ssl_client);
|
||||
log_e("pre-shared key not valid hex or too long");
|
||||
return -1;
|
||||
}
|
||||
unsigned char psk[MBEDTLS_PSK_MAX_LEN];
|
||||
size_t psk_len = strlen(psKey) / 2;
|
||||
for (int j = 0; j < strlen(psKey); j += 2)
|
||||
{
|
||||
char c = psKey[j];
|
||||
if (c >= '0' && c <= '9')
|
||||
c -= '0';
|
||||
else if (c >= 'A' && c <= 'F')
|
||||
c -= 'A' - 10;
|
||||
else if (c >= 'a' && c <= 'f')
|
||||
c -= 'a' - 10;
|
||||
else
|
||||
return -1;
|
||||
psk[j / 2] = c << 4;
|
||||
c = psKey[j + 1];
|
||||
if (c >= '0' && c <= '9')
|
||||
c -= '0';
|
||||
else if (c >= 'A' && c <= 'F')
|
||||
c -= 'A' - 10;
|
||||
else if (c >= 'a' && c <= 'f')
|
||||
c -= 'a' - 10;
|
||||
else
|
||||
return -1;
|
||||
psk[j / 2] |= c;
|
||||
}
|
||||
// set mbedtls config
|
||||
if (ssl_client->_debugCallback)
|
||||
ESP32SSLClientDebugInfo(ESP32_SSL_CLIENT_STR_14, ssl_client);
|
||||
ret = mbedtls_ssl_conf_psk(&ssl_client->ssl_conf, psk, psk_len,
|
||||
(const unsigned char *)pskIdent, strlen(pskIdent));
|
||||
if (ret != 0)
|
||||
{
|
||||
if (ssl_client->_debugCallback)
|
||||
{
|
||||
char *error_buf = new char[100];
|
||||
memset(buf, 0, 512);
|
||||
strcpy_P(buf, ESP32_SSL_CLIENT_STR_1);
|
||||
mbedtls_strerror(ret, error_buf, 100);
|
||||
strcat(buf, error_buf);
|
||||
ssl_client->_debugCallback(buf);
|
||||
delete[] error_buf;
|
||||
}
|
||||
log_e("mbedtls_ssl_conf_psk returned %d", ret);
|
||||
return handle_error(ret);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
mbedtls_ssl_conf_authmode(&ssl_client->ssl_conf, MBEDTLS_SSL_VERIFY_NONE);
|
||||
log_i("WARNING: Use certificates for a more secure communication!");
|
||||
}
|
||||
|
||||
if (cli_cert != NULL && cli_key != NULL)
|
||||
{
|
||||
|
||||
mbedtls_x509_crt_init(&ssl_client->client_cert);
|
||||
mbedtls_pk_init(&ssl_client->client_key);
|
||||
|
||||
if (ssl_client->_debugCallback)
|
||||
ESP32SSLClientDebugInfo(ESP32_SSL_CLIENT_STR_15, ssl_client);
|
||||
|
||||
log_v("Loading CRT cert");
|
||||
|
||||
ret = mbedtls_x509_crt_parse(&ssl_client->client_cert, (const unsigned char *)cli_cert, strlen(cli_cert) + 1);
|
||||
if (ret < 0)
|
||||
{
|
||||
if (ssl_client->_debugCallback)
|
||||
{
|
||||
char *error_buf = new char[100];
|
||||
memset(buf, 0, 512);
|
||||
strcpy_P(buf, ESP32_SSL_CLIENT_STR_1);
|
||||
mbedtls_strerror(ret, error_buf, 100);
|
||||
strcat(buf, error_buf);
|
||||
ssl_client->_debugCallback(buf);
|
||||
delete[] error_buf;
|
||||
}
|
||||
return handle_error(ret);
|
||||
}
|
||||
|
||||
if (ssl_client->_debugCallback)
|
||||
ESP32SSLClientDebugInfo(ESP32_SSL_CLIENT_STR_16, ssl_client);
|
||||
|
||||
log_v("Loading private key");
|
||||
ret = mbedtls_pk_parse_key(&ssl_client->client_key, (const unsigned char *)cli_key, strlen(cli_key) + 1, NULL, 0);
|
||||
|
||||
if (ret != 0)
|
||||
{
|
||||
return handle_error(ret);
|
||||
}
|
||||
|
||||
mbedtls_ssl_conf_own_cert(&ssl_client->ssl_conf, &ssl_client->client_cert, &ssl_client->client_key);
|
||||
}
|
||||
|
||||
if (ssl_client->_debugCallback)
|
||||
ESP32SSLClientDebugInfo(ESP32_SSL_CLIENT_STR_17, ssl_client);
|
||||
|
||||
log_v("Setting hostname for TLS session...");
|
||||
|
||||
// Hostname set here should match CN in server certificate
|
||||
if ((ret = mbedtls_ssl_set_hostname(&ssl_client->ssl_ctx, host)) != 0)
|
||||
{
|
||||
if (ssl_client->_debugCallback)
|
||||
{
|
||||
char *error_buf = new char[100];
|
||||
memset(buf, 0, 512);
|
||||
strcpy_P(buf, ESP32_SSL_CLIENT_STR_1);
|
||||
mbedtls_strerror(ret, error_buf, 100);
|
||||
strcat(buf, error_buf);
|
||||
ssl_client->_debugCallback(buf);
|
||||
delete[] error_buf;
|
||||
}
|
||||
return handle_error(ret);
|
||||
}
|
||||
|
||||
mbedtls_ssl_conf_rng(&ssl_client->ssl_conf, mbedtls_ctr_drbg_random, &ssl_client->drbg_ctx);
|
||||
|
||||
if ((ret = mbedtls_ssl_setup(&ssl_client->ssl_ctx, &ssl_client->ssl_conf)) != 0)
|
||||
{
|
||||
if (ssl_client->_debugCallback)
|
||||
{
|
||||
char *error_buf = new char[100];
|
||||
memset(buf, 0, 512);
|
||||
strcpy_P(buf, ESP32_SSL_CLIENT_STR_1);
|
||||
mbedtls_strerror(ret, error_buf, 100);
|
||||
strcat(buf, error_buf);
|
||||
ssl_client->_debugCallback(buf);
|
||||
delete[] error_buf;
|
||||
}
|
||||
|
||||
return handle_error(ret);
|
||||
}
|
||||
|
||||
mbedtls_ssl_set_bio(&ssl_client->ssl_ctx, &ssl_client->socket, mbedtls_net_send, mbedtls_net_recv, NULL);
|
||||
|
||||
if (ssl_client->_debugCallback)
|
||||
ESP32SSLClientDebugInfo(ESP32_SSL_CLIENT_STR_18, ssl_client);
|
||||
|
||||
log_v("Performing the SSL/TLS handshake...");
|
||||
unsigned long handshake_start_time = millis();
|
||||
while ((ret = mbedtls_ssl_handshake(&ssl_client->ssl_ctx)) != 0)
|
||||
{
|
||||
if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE)
|
||||
{
|
||||
if (ssl_client->_debugCallback)
|
||||
{
|
||||
char *error_buf = new char[100];
|
||||
memset(buf, 0, 512);
|
||||
strcpy_P(buf, ESP32_SSL_CLIENT_STR_1);
|
||||
mbedtls_strerror(ret, error_buf, 100);
|
||||
strcat(buf, error_buf);
|
||||
ssl_client->_debugCallback(buf);
|
||||
delete[] error_buf;
|
||||
}
|
||||
return handle_error(ret);
|
||||
}
|
||||
if ((millis() - handshake_start_time) > ssl_client->handshake_timeout)
|
||||
return -1;
|
||||
vTaskDelay(10 / portTICK_PERIOD_MS);
|
||||
}
|
||||
|
||||
if (cli_cert != NULL && cli_key != NULL)
|
||||
{
|
||||
log_d("Protocol is %s Ciphersuite is %s", mbedtls_ssl_get_version(&ssl_client->ssl_ctx), mbedtls_ssl_get_ciphersuite(&ssl_client->ssl_ctx));
|
||||
if ((ret = mbedtls_ssl_get_record_expansion(&ssl_client->ssl_ctx)) >= 0)
|
||||
{
|
||||
|
||||
log_d("Record expansion is %d", ret);
|
||||
}
|
||||
else
|
||||
{
|
||||
log_w("Record expansion is unknown (compression)");
|
||||
}
|
||||
}
|
||||
|
||||
if (ssl_client->_debugCallback)
|
||||
ESP32SSLClientDebugInfo(ESP32_SSL_CLIENT_STR_19, ssl_client);
|
||||
|
||||
log_v("Verifying peer X.509 certificate...");
|
||||
|
||||
if ((flags = mbedtls_ssl_get_verify_result(&ssl_client->ssl_ctx)) != 0)
|
||||
{
|
||||
bzero(buf, sizeof(buf));
|
||||
mbedtls_x509_crt_verify_info(buf, sizeof(buf), " ! ", flags);
|
||||
if (ssl_client->_debugCallback)
|
||||
ESP32SSLClientDebugInfo(ESP32_SSL_CLIENT_STR_20, ssl_client);
|
||||
log_e("Failed to verify peer certificate! verification info: %s", buf);
|
||||
stop_ssl_socket(ssl_client, rootCABuff, cli_cert, cli_key); //It's not safe continue.
|
||||
return handle_error(ret);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ssl_client->_debugCallback)
|
||||
ESP32SSLClientDebugInfo(ESP32_SSL_CLIENT_STR_21, ssl_client);
|
||||
log_v("Certificate verified.");
|
||||
}
|
||||
|
||||
if (rootCABuff != NULL)
|
||||
{
|
||||
mbedtls_x509_crt_free(&ssl_client->ca_cert);
|
||||
}
|
||||
|
||||
if (cli_cert != NULL)
|
||||
{
|
||||
mbedtls_x509_crt_free(&ssl_client->client_cert);
|
||||
}
|
||||
|
||||
if (cli_key != NULL)
|
||||
{
|
||||
mbedtls_pk_free(&ssl_client->client_key);
|
||||
}
|
||||
|
||||
log_v("Free internal heap after TLS %u", ESP.getFreeHeap());
|
||||
|
||||
return ssl_client->socket;
|
||||
}
|
||||
|
||||
void stop_ssl_socket(sslclient_context32 *ssl_client, const char *rootCABuff, const char *cli_cert, const char *cli_key)
|
||||
{
|
||||
if (ssl_client->_debugCallback)
|
||||
ESP32SSLClientDebugInfo(ESP32_SSL_CLIENT_STR_22, ssl_client);
|
||||
log_v("Cleaning SSL connection.");
|
||||
|
||||
if (ssl_client->socket >= 0)
|
||||
{
|
||||
close(ssl_client->socket);
|
||||
ssl_client->socket = -1;
|
||||
}
|
||||
|
||||
mbedtls_ssl_free(&ssl_client->ssl_ctx);
|
||||
mbedtls_ssl_config_free(&ssl_client->ssl_conf);
|
||||
mbedtls_ctr_drbg_free(&ssl_client->drbg_ctx);
|
||||
mbedtls_entropy_free(&ssl_client->entropy_ctx);
|
||||
}
|
||||
|
||||
int data_to_read(sslclient_context32 *ssl_client)
|
||||
{
|
||||
int ret, res;
|
||||
ret = mbedtls_ssl_read(&ssl_client->ssl_ctx, NULL, 0);
|
||||
//log_e("RET: %i",ret); //for low level debug
|
||||
res = mbedtls_ssl_get_bytes_avail(&ssl_client->ssl_ctx);
|
||||
//log_e("RES: %i",res); //for low level debug
|
||||
if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE && ret < 0)
|
||||
{
|
||||
if (ssl_client->_debugCallback)
|
||||
{
|
||||
char *buf = new char[512];
|
||||
char *error_buf = new char[100];
|
||||
memset(buf, 0, 512);
|
||||
strcpy_P(buf, ESP32_SSL_CLIENT_STR_1);
|
||||
mbedtls_strerror(ret, error_buf, 100);
|
||||
strcat(buf, error_buf);
|
||||
ssl_client->_debugCallback(buf);
|
||||
delete[] error_buf;
|
||||
delete[] buf;
|
||||
}
|
||||
return handle_error(ret);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int send_ssl_data(sslclient_context32 *ssl_client, const uint8_t *data, uint16_t len)
|
||||
{
|
||||
|
||||
log_v("Writing HTTP request..."); //for low level debug
|
||||
int ret = -1;
|
||||
|
||||
while ((ret = mbedtls_ssl_write(&ssl_client->ssl_ctx, data, len)) <= 0)
|
||||
{
|
||||
if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE)
|
||||
{
|
||||
return handle_error(ret);
|
||||
}
|
||||
}
|
||||
|
||||
len = ret;
|
||||
//log_v("%d bytes written", len); //for low level debug
|
||||
return ret;
|
||||
}
|
||||
|
||||
int get_ssl_receive(sslclient_context32 *ssl_client, uint8_t *data, int length)
|
||||
{
|
||||
|
||||
//log_d( "Reading HTTP response..."); //for low level debug
|
||||
int ret = -1;
|
||||
|
||||
ret = mbedtls_ssl_read(&ssl_client->ssl_ctx, data, length);
|
||||
|
||||
//log_v( "%d bytes read", ret); //for low level debug
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool parseHexNibble(char pb, uint8_t *res)
|
||||
{
|
||||
if (pb >= '0' && pb <= '9')
|
||||
{
|
||||
*res = (uint8_t)(pb - '0');
|
||||
return true;
|
||||
}
|
||||
else if (pb >= 'a' && pb <= 'f')
|
||||
{
|
||||
*res = (uint8_t)(pb - 'a' + 10);
|
||||
return true;
|
||||
}
|
||||
else if (pb >= 'A' && pb <= 'F')
|
||||
{
|
||||
*res = (uint8_t)(pb - 'A' + 10);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Compare a name from certificate and domain name, return true if they match
|
||||
static bool matchName(const std::string &name, const std::string &domainName)
|
||||
{
|
||||
size_t wildcardPos = name.find('*');
|
||||
if (wildcardPos == std::string::npos)
|
||||
{
|
||||
// Not a wildcard, expect an exact match
|
||||
return name == domainName;
|
||||
}
|
||||
|
||||
size_t firstDotPos = name.find('.');
|
||||
if (wildcardPos > firstDotPos)
|
||||
{
|
||||
// Wildcard is not part of leftmost component of domain name
|
||||
// Do not attempt to match (rfc6125 6.4.3.1)
|
||||
return false;
|
||||
}
|
||||
if (wildcardPos != 0 || firstDotPos != 1)
|
||||
{
|
||||
// Matching of wildcards such as baz*.example.com and b*z.example.com
|
||||
// is optional. Maybe implement this in the future?
|
||||
return false;
|
||||
}
|
||||
size_t domainNameFirstDotPos = domainName.find('.');
|
||||
if (domainNameFirstDotPos == std::string::npos)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return domainName.substr(domainNameFirstDotPos) == name.substr(firstDotPos);
|
||||
}
|
||||
|
||||
// Verifies certificate provided by the peer to match specified SHA256 fingerprint
|
||||
bool verify_ssl_fingerprint(sslclient_context32 *ssl_client, const char *fp, const char *domain_name)
|
||||
{
|
||||
// Convert hex string to byte array
|
||||
uint8_t fingerprint_local[32];
|
||||
int len = strlen(fp);
|
||||
int pos = 0;
|
||||
for (size_t i = 0; i < sizeof(fingerprint_local); ++i)
|
||||
{
|
||||
while (pos < len && ((fp[pos] == ' ') || (fp[pos] == ':')))
|
||||
{
|
||||
++pos;
|
||||
}
|
||||
if (pos > len - 2)
|
||||
{
|
||||
if (ssl_client->_debugCallback)
|
||||
ESP32SSLClientDebugInfo(ESP32_SSL_CLIENT_STR_23, ssl_client);
|
||||
log_d("pos:%d len:%d fingerprint too short", pos, len);
|
||||
return false;
|
||||
}
|
||||
uint8_t high, low;
|
||||
if (!parseHexNibble(fp[pos], &high) || !parseHexNibble(fp[pos + 1], &low))
|
||||
{
|
||||
if (ssl_client->_debugCallback)
|
||||
ESP32SSLClientDebugInfo(ESP32_SSL_CLIENT_STR_24, ssl_client);
|
||||
log_d("pos:%d len:%d invalid hex sequence: %c%c", pos, len, fp[pos], fp[pos + 1]);
|
||||
return false;
|
||||
}
|
||||
pos += 2;
|
||||
fingerprint_local[i] = low | (high << 4);
|
||||
}
|
||||
|
||||
// Get certificate provided by the peer
|
||||
const mbedtls_x509_crt *crt = mbedtls_ssl_get_peer_cert(&ssl_client->ssl_ctx);
|
||||
|
||||
if (!crt)
|
||||
{
|
||||
if (ssl_client->_debugCallback)
|
||||
ESP32SSLClientDebugInfo(ESP32_SSL_CLIENT_STR_25, ssl_client);
|
||||
log_d("could not fetch peer certificate");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Calculate certificate's SHA256 fingerprint
|
||||
uint8_t fingerprint_remote[32];
|
||||
mbedtls_sha256_context sha256_ctx;
|
||||
mbedtls_sha256_init(&sha256_ctx);
|
||||
mbedtls_sha256_starts(&sha256_ctx, false);
|
||||
mbedtls_sha256_update(&sha256_ctx, crt->raw.p, crt->raw.len);
|
||||
mbedtls_sha256_finish(&sha256_ctx, fingerprint_remote);
|
||||
|
||||
// Check if fingerprints match
|
||||
if (memcmp(fingerprint_local, fingerprint_remote, 32))
|
||||
{
|
||||
if (ssl_client->_debugCallback)
|
||||
ESP32SSLClientDebugInfo(ESP32_SSL_CLIENT_STR_26, ssl_client);
|
||||
log_d("fingerprint doesn't match");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Additionally check if certificate has domain name if provided
|
||||
if (domain_name)
|
||||
return verify_ssl_dn(ssl_client, domain_name);
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
// Checks if peer certificate has specified domain in CN or SANs
|
||||
bool verify_ssl_dn(sslclient_context32 *ssl_client, const char *domain_name)
|
||||
{
|
||||
log_d("domain name: '%s'", (domain_name) ? domain_name : "(null)");
|
||||
std::string domain_name_str(domain_name);
|
||||
std::transform(domain_name_str.begin(), domain_name_str.end(), domain_name_str.begin(), ::tolower);
|
||||
|
||||
// Get certificate provided by the peer
|
||||
const mbedtls_x509_crt *crt = mbedtls_ssl_get_peer_cert(&ssl_client->ssl_ctx);
|
||||
|
||||
// Check for domain name in SANs
|
||||
const mbedtls_x509_sequence *san = &crt->subject_alt_names;
|
||||
while (san != nullptr)
|
||||
{
|
||||
std::string san_str((const char *)san->buf.p, san->buf.len);
|
||||
std::transform(san_str.begin(), san_str.end(), san_str.begin(), ::tolower);
|
||||
|
||||
if (matchName(san_str, domain_name_str))
|
||||
return true;
|
||||
|
||||
log_d("SAN '%s': no match", san_str.c_str());
|
||||
|
||||
// Fetch next SAN
|
||||
san = san->next;
|
||||
}
|
||||
|
||||
// Check for domain name in CN
|
||||
const mbedtls_asn1_named_data *common_name = &crt->subject;
|
||||
while (common_name != nullptr)
|
||||
{
|
||||
// While iterating through DN objects, check for CN object
|
||||
if (!MBEDTLS_OID_CMP(MBEDTLS_OID_AT_CN, &common_name->oid))
|
||||
{
|
||||
std::string common_name_str((const char *)common_name->val.p, common_name->val.len);
|
||||
|
||||
if (matchName(common_name_str, domain_name_str))
|
||||
return true;
|
||||
|
||||
log_d("CN '%s': not match", common_name_str.c_str());
|
||||
}
|
||||
|
||||
// Fetch next DN object
|
||||
common_name = common_name->next;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int starttlsHandshake(sslclient_context32 *ssl_client, int port)
|
||||
{
|
||||
|
||||
int ret = 0;
|
||||
size_t msgLen = 100;
|
||||
size_t bufLen = 512;
|
||||
char *buf = new char[bufLen];
|
||||
char *hMsg = new char[msgLen];
|
||||
|
||||
fd_set readset;
|
||||
fd_set writeset;
|
||||
fd_set errset;
|
||||
|
||||
struct timeval tv;
|
||||
|
||||
FD_ZERO(&readset);
|
||||
FD_SET(ssl_client->socket, &readset);
|
||||
FD_ZERO(&writeset);
|
||||
FD_SET(ssl_client->socket, &writeset);
|
||||
|
||||
FD_ZERO(&errset);
|
||||
FD_SET(ssl_client->socket, &errset);
|
||||
|
||||
tv.tv_sec = 1;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
ret = lwip_select(ssl_client->socket, &readset, &writeset, &errset, &tv);
|
||||
if (ret < 0)
|
||||
{
|
||||
if (ssl_client->_debugCallback)
|
||||
ESP32SSLClientDebugInfo(ESP32_SSL_CLIENT_STR_27, ssl_client);
|
||||
|
||||
goto starttls_exit;
|
||||
}
|
||||
|
||||
ret = read(ssl_client->socket, buf, bufLen);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
if (ssl_client->_debugCallback)
|
||||
ESP32SSLClientDebugInfo(ESP32_SSL_CLIENT_STR_28, ssl_client);
|
||||
goto starttls_exit;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ssl_client->_debugCallback)
|
||||
ssl_client->_debugCallback(buf);
|
||||
}
|
||||
|
||||
if (port == 587 || port == 25)
|
||||
{
|
||||
|
||||
memset(hMsg, 0, msgLen);
|
||||
strcpy_P(hMsg, ESP32_SSL_CLIENT_STR_29);
|
||||
if (ssl_client->_debugCallback)
|
||||
ESP32SSLClientDebugInfo(ESP32_SSL_CLIENT_STR_30, ssl_client);
|
||||
ret = lwip_write(ssl_client->socket, hMsg, strlen(hMsg));
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
if (ssl_client->_debugCallback)
|
||||
ESP32SSLClientDebugInfo(ESP32_SSL_CLIENT_STR_31, ssl_client);
|
||||
goto starttls_exit;
|
||||
}
|
||||
|
||||
ret = lwip_select(ssl_client->socket, &readset, &writeset, &errset, &tv);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
if (ssl_client->_debugCallback)
|
||||
ESP32SSLClientDebugInfo(ESP32_SSL_CLIENT_STR_32, ssl_client);
|
||||
goto starttls_exit;
|
||||
}
|
||||
|
||||
memset(buf, 0, bufLen);
|
||||
ret = lwip_read(ssl_client->socket, buf, bufLen);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
if (ssl_client->_debugCallback)
|
||||
ESP32SSLClientDebugInfo(ESP32_SSL_CLIENT_STR_33, ssl_client);
|
||||
goto starttls_exit;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ssl_client->_debugCallback)
|
||||
ssl_client->_debugCallback(buf);
|
||||
}
|
||||
}
|
||||
|
||||
memset(hMsg, 0, msgLen);
|
||||
strcpy_P(hMsg, ESP32_SSL_CLIENT_STR_34);
|
||||
if (ssl_client->_debugCallback)
|
||||
ESP32SSLClientDebugInfo(ESP32_SSL_CLIENT_STR_35, ssl_client);
|
||||
ret = lwip_write(ssl_client->socket, hMsg, strlen(hMsg));
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
if (ssl_client->_debugCallback)
|
||||
ESP32SSLClientDebugInfo(ESP32_SSL_CLIENT_STR_36, ssl_client);
|
||||
goto starttls_exit;
|
||||
}
|
||||
|
||||
ret = lwip_select(ssl_client->socket, &readset, &writeset, &errset, &tv);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
if (ssl_client->_debugCallback)
|
||||
ESP32SSLClientDebugInfo(ESP32_SSL_CLIENT_STR_37, ssl_client);
|
||||
goto starttls_exit;
|
||||
}
|
||||
|
||||
memset(buf, 0, bufLen);
|
||||
ret = lwip_read(ssl_client->socket, buf, bufLen);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
if (ssl_client->_debugCallback)
|
||||
ESP32SSLClientDebugInfo(ESP32_SSL_CLIENT_STR_38, ssl_client);
|
||||
goto starttls_exit;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ssl_client->_debugCallback)
|
||||
ssl_client->_debugCallback(buf);
|
||||
}
|
||||
|
||||
delete[] buf;
|
||||
delete[] hMsg;
|
||||
|
||||
return 0;
|
||||
|
||||
starttls_exit:
|
||||
|
||||
delete[] buf;
|
||||
delete[] hMsg;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void ESP32SSLClientDebugInfo(PGM_P info, sslclient_context32 *ssl_client)
|
||||
{
|
||||
size_t dbgInfoLen = strlen_P(info) + 1;
|
||||
char *dbgInfo = new char[dbgInfoLen];
|
||||
memset(dbgInfo, 0, dbgInfoLen);
|
||||
strcpy_P(dbgInfo, info);
|
||||
ssl_client->_debugCallback(dbgInfo);
|
||||
delete[] dbgInfo;
|
||||
}
|
||||
|
||||
#endif //ESP32
|
||||
|
||||
#endif //SSL_CLIENT32_CPP
|
116
libesp32/ESP32-Mail-Client/src/ssl_client32.h
Executable file
116
libesp32/ESP32-Mail-Client/src/ssl_client32.h
Executable file
@ -0,0 +1,116 @@
|
||||
/*
|
||||
*Customized ssl_client.h to support STARTTLS protocol, version 1.0.3
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
* Copyright (c) 2019 K. Suwatchai (Mobizt)
|
||||
*
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/* Provide SSL/TLS functions to ESP32 with Arduino IDE
|
||||
* by Evandro Copercini - 2017 - Apache 2.0 License
|
||||
*/
|
||||
|
||||
#ifndef SSL_CLIENT32_H
|
||||
#define SSL_CLIENT32_H
|
||||
|
||||
#ifdef ESP32
|
||||
|
||||
#include "mbedtls/platform.h"
|
||||
#include "mbedtls/net.h"
|
||||
#include "mbedtls/debug.h"
|
||||
#include "mbedtls/ssl.h"
|
||||
#include "mbedtls/entropy.h"
|
||||
#include "mbedtls/ctr_drbg.h"
|
||||
#include "mbedtls/error.h"
|
||||
|
||||
static const char ESP32_SSL_CLIENT_STR_1[] PROGMEM = "ERROR: ";
|
||||
static const char ESP32_SSL_CLIENT_STR_2[] PROGMEM = "INFO: starting socket";
|
||||
static const char ESP32_SSL_CLIENT_STR_3[] PROGMEM = "ERROR: opening socket";
|
||||
static const char ESP32_SSL_CLIENT_STR_4[] PROGMEM = "ERROR: could not get ip from host";
|
||||
static const char ESP32_SSL_CLIENT_STR_5[] PROGMEM = "INFO: connecting to Server...";
|
||||
static const char ESP32_SSL_CLIENT_STR_6[] PROGMEM = "INFO: server connected";
|
||||
static const char ESP32_SSL_CLIENT_STR_7[] PROGMEM = "ERROR: connect to Server failed!";
|
||||
static const char ESP32_SSL_CLIENT_STR_8[] PROGMEM = "INFO: begin STARTTLS handshake";
|
||||
static const char ESP32_SSL_CLIENT_STR_9[] PROGMEM = "INFO: seeding the random number generator";
|
||||
static const char ESP32_SSL_CLIENT_STR_10[] PROGMEM = "INFO: setting up the SSL/TLS structure...";
|
||||
static const char ESP32_SSL_CLIENT_STR_11[] PROGMEM = "INFO: loading CA cert";
|
||||
static const char ESP32_SSL_CLIENT_STR_12[] PROGMEM = "INFO: setting up PSK";
|
||||
static const char ESP32_SSL_CLIENT_STR_13[] PROGMEM = "ERROR: pre-shared key not valid hex or too long";
|
||||
static const char ESP32_SSL_CLIENT_STR_14[] PROGMEM = "INFO: set mbedtls config";
|
||||
static const char ESP32_SSL_CLIENT_STR_15[] PROGMEM = "INFO: loading CRT cert";
|
||||
static const char ESP32_SSL_CLIENT_STR_16[] PROGMEM = "INFO: loading private key";
|
||||
static const char ESP32_SSL_CLIENT_STR_17[] PROGMEM = "INFO: setting hostname for TLS session...";
|
||||
static const char ESP32_SSL_CLIENT_STR_18[] PROGMEM = "INFO: performing the SSL/TLS handshake...";
|
||||
static const char ESP32_SSL_CLIENT_STR_19[] PROGMEM = "INFO: verifying peer X.509 certificate...";
|
||||
static const char ESP32_SSL_CLIENT_STR_20[] PROGMEM = "ERROR: failed to verify peer certificate!";
|
||||
static const char ESP32_SSL_CLIENT_STR_21[] PROGMEM = "INFO: certificate verified";
|
||||
static const char ESP32_SSL_CLIENT_STR_22[] PROGMEM = "INFO: cleaning SSL connection";
|
||||
static const char ESP32_SSL_CLIENT_STR_23[] PROGMEM = "ERROR: fingerprint too short";
|
||||
static const char ESP32_SSL_CLIENT_STR_24[] PROGMEM = "ERROR: invalid hex sequence";
|
||||
static const char ESP32_SSL_CLIENT_STR_25[] PROGMEM = "ERROR: could not fetch peer certificate";
|
||||
static const char ESP32_SSL_CLIENT_STR_26[] PROGMEM = "ERROR: fingerprint doesn't match";
|
||||
static const char ESP32_SSL_CLIENT_STR_27[] PROGMEM = "ERROR: waiting incoming data failed!";
|
||||
static const char ESP32_SSL_CLIENT_STR_28[] PROGMEM = "ERROR: reading incoming data failed!";
|
||||
static const char ESP32_SSL_CLIENT_STR_29[] PROGMEM = "EHLO DUDE\r\n";
|
||||
static const char ESP32_SSL_CLIENT_STR_30[] PROGMEM = "INFO: send SMTP command extended HELO";
|
||||
static const char ESP32_SSL_CLIENT_STR_31[] PROGMEM = "ERROR: send SMTP command failed!";
|
||||
static const char ESP32_SSL_CLIENT_STR_32[] PROGMEM = "ERROR: waiting incoming data failed!";
|
||||
static const char ESP32_SSL_CLIENT_STR_33[] PROGMEM = "ERROR: reading incoming data failed!";
|
||||
static const char ESP32_SSL_CLIENT_STR_34[] PROGMEM = "STARTTLS\r\n";
|
||||
static const char ESP32_SSL_CLIENT_STR_35[] PROGMEM = "INFO: send STARTTLS protocol command";
|
||||
static const char ESP32_SSL_CLIENT_STR_36[] PROGMEM = "ERROR: send STARTTLS protocol command failed!";
|
||||
static const char ESP32_SSL_CLIENT_STR_37[] PROGMEM = "ERROR: waiting incoming data failed!";
|
||||
static const char ESP32_SSL_CLIENT_STR_38[] PROGMEM = "ERROR: reading incoming data failed!";
|
||||
|
||||
typedef void (*DebugMsgCallback)(const char *msg);
|
||||
|
||||
typedef struct sslclient_context32 {
|
||||
int socket;
|
||||
bool starttls;
|
||||
mbedtls_ssl_context ssl_ctx;
|
||||
mbedtls_ssl_config ssl_conf;
|
||||
mbedtls_net_context server_fd;
|
||||
|
||||
mbedtls_ctr_drbg_context drbg_ctx;
|
||||
mbedtls_entropy_context entropy_ctx;
|
||||
|
||||
mbedtls_x509_crt ca_cert;
|
||||
mbedtls_x509_crt client_cert;
|
||||
mbedtls_pk_context client_key;
|
||||
DebugMsgCallback _debugCallback;
|
||||
|
||||
unsigned long handshake_timeout;
|
||||
} sslclient_context32;
|
||||
|
||||
|
||||
void ssl_init(sslclient_context32 *ssl_client);
|
||||
int start_ssl_client(sslclient_context32 *ssl_client, const char *host, uint32_t port, int timeout, const char *rootCABuff, const char *cli_cert, const char *cli_key, const char *pskIdent, const char *psKey);
|
||||
void stop_ssl_socket(sslclient_context32 *ssl_client, const char *rootCABuff, const char *cli_cert, const char *cli_key);
|
||||
int data_to_read(sslclient_context32 *ssl_client);
|
||||
int send_ssl_data(sslclient_context32 *ssl_client, const uint8_t *data, uint16_t len);
|
||||
int get_ssl_receive(sslclient_context32 *ssl_client, uint8_t *data, int length);
|
||||
bool verify_ssl_fingerprint(sslclient_context32 *ssl_client, const char* fp, const char* domain_name);
|
||||
bool verify_ssl_dn(sslclient_context32 *ssl_client, const char* domain_name);
|
||||
int starttlsHandshake(sslclient_context32 *ssl_client, int port);
|
||||
void ESP32SSLClientDebugInfo(PGM_P info, sslclient_context32 *ssl_client);
|
||||
|
||||
#endif //ESP32
|
||||
|
||||
#endif //SSL_CLIENT32_H
|
@ -28,9 +28,27 @@
|
||||
|
||||
#include <Esp.h>
|
||||
|
||||
|
||||
// webcam uses channel 0, so we offset standard PWM
|
||||
#define PWM_CHANNEL_OFFSET 2
|
||||
// Analog
|
||||
|
||||
uint8_t pwm_channel[8]={99,99,99,99,99,99,99,99};
|
||||
|
||||
inline uint32_t pin2chan(uint32_t pin) {
|
||||
for (uint32_t cnt=0;cnt<8;cnt++) {
|
||||
if ((pwm_channel[cnt]<99) && (pwm_channel[cnt]==pin)) {
|
||||
return cnt;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline void analogWrite(uint8_t pin, int val)
|
||||
{
|
||||
uint32_t channel=pin2chan(pin);
|
||||
ledcWrite(channel+PWM_CHANNEL_OFFSET,val);
|
||||
//Serial.printf("write %d - %d\n",channel,val);
|
||||
}
|
||||
|
||||
inline void analogWriteFreq(uint32_t freq)
|
||||
@ -40,6 +58,31 @@ inline void analogWriteRange(uint32_t range)
|
||||
{
|
||||
}
|
||||
|
||||
inline void analogAttach(uint32_t pin, uint32_t channel) {
|
||||
pwm_channel[channel&7]=pin;
|
||||
ledcAttachPin(pin,channel+PWM_CHANNEL_OFFSET);
|
||||
//Serial.printf("attach %d - %d\n",channel,pin);
|
||||
}
|
||||
|
||||
inline uint32_t pow2(uint32_t x) {
|
||||
uint32_t power = 1,bits=0;
|
||||
while (power < x) {
|
||||
power*=2;
|
||||
bits++;
|
||||
}
|
||||
return bits-1;
|
||||
}
|
||||
// input range is in full range, ledc needs bits
|
||||
inline void analogWriteFreqRange(uint32_t channel,uint32_t freq, uint32_t irange) {
|
||||
uint32_t range=pow2(irange);
|
||||
for (uint32_t cnt=0;cnt<8;cnt++) {
|
||||
if (pwm_channel[cnt]<99) {
|
||||
ledcSetup(cnt+PWM_CHANNEL_OFFSET,freq,range);
|
||||
}
|
||||
}
|
||||
//Serial.printf("freq - range %d - %d\n",freq,range);
|
||||
}
|
||||
|
||||
#define INPUT_PULLDOWN_16 INPUT_PULLUP
|
||||
|
||||
typedef double real64_t;
|
||||
@ -57,7 +100,7 @@ typedef double real64_t;
|
||||
// Serial minimal type to hold the config
|
||||
typedef int SerConfu8;
|
||||
typedef int SerialConfig;
|
||||
#define analogWrite(a, b)
|
||||
//#define analogWrite(a, b)
|
||||
|
||||
//
|
||||
// WS2812
|
||||
|
@ -18,7 +18,7 @@ extra_configs = platformio_tasmota_env.ini
|
||||
default_envs =
|
||||
; *** Uncomment by deleting ";" in the line(s) below to select version(s)
|
||||
; tasmota
|
||||
; tasmota-ircustom ; alternative to 'tasmota' with full IR protocols activated, you will need to disable some features to keep code not too big
|
||||
; tasmota-ircustom
|
||||
; tasmota-minimal
|
||||
; tasmota-lite
|
||||
; tasmota-knx
|
||||
@ -112,9 +112,9 @@ platform_packages = ${tasmota_core.platform_packages}
|
||||
build_flags = ${tasmota_core.build_flags}
|
||||
|
||||
[tasmota_core]
|
||||
; *** Esp8266 Arduino core version Tasmota
|
||||
platform = espressif8266@2.4.0
|
||||
platform_packages = framework-arduinoespressif8266 @ https://github.com/esp8266/Arduino.git#36e047e908cfa6eafaaf824988070b49f2c2ff2a
|
||||
; *** Esp8266 Arduino core 2.7.0
|
||||
platform = espressif8266@2.5.0
|
||||
platform_packages = framework-arduinoespressif8266 @ https://github.com/tasmota/Arduino/releases/download/2.7.0/esp8266-2.7.0.zip
|
||||
build_flags = ${esp82xx_defaults.build_flags}
|
||||
-DBEARSSL_SSL_BASIC
|
||||
; NONOSDK22x_190703 = 2.2.2-dev(38a443e)
|
||||
|
@ -70,68 +70,20 @@ extra_scripts = ${scripts_defaults.extra_scripts}
|
||||
; pio/http-uploader.py
|
||||
|
||||
[core_active]
|
||||
; Select one core set for platform and build_flags
|
||||
; Activate only (one set) if you want to override the standard core defined in platformio.ini !!!
|
||||
|
||||
;platform = ${core_2_6_3.platform}
|
||||
;platform_packages = ${core_2_6_3.platform_packages}
|
||||
;build_flags = ${core_2_6_3.build_flags}
|
||||
|
||||
platform = ${tasmota_feature_stage.platform}
|
||||
platform_packages = ${tasmota_feature_stage.platform_packages}
|
||||
build_flags = ${tasmota_feature_stage.build_flags}
|
||||
;platform = ${tasmota_stage.platform}
|
||||
;platform_packages = ${tasmota_stage.platform_packages}
|
||||
;build_flags = ${tasmota_stage.build_flags}
|
||||
|
||||
;platform = ${core_stage.platform}
|
||||
;platform_packages = ${core_stage.platform_packages}
|
||||
;build_flags = ${core_stage.build_flags}
|
||||
|
||||
|
||||
[core_2_6_3]
|
||||
; *** Esp8266 core for Arduino version 2.6.3
|
||||
platform = espressif8266@2.4.0
|
||||
platform_packages =
|
||||
build_flags = ${esp82xx_defaults.build_flags}
|
||||
-DBEARSSL_SSL_BASIC
|
||||
; NONOSDK221
|
||||
; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK221
|
||||
; NONOSDK22x_190313
|
||||
; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190313
|
||||
; NONOSDK22x_190703 = 2.2.1+100-dev(38a443e) (Tasmota default) (Firmware 2K smaller than NONOSDK22x_191105)
|
||||
-DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190703
|
||||
; NONOSDK22x_191024 = 2.2.1+111-dev(5ab15d1)
|
||||
; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191024
|
||||
; NONOSDK22x_191105 = 2.2.1+113-dev(bb83b9b)
|
||||
; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191105
|
||||
; NONOSDK3V0 (known issues)
|
||||
; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK3
|
||||
; lwIP 1.4
|
||||
; -DPIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH
|
||||
; lwIP 2 - Low Memory
|
||||
; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY
|
||||
; lwIP 2 - Higher Bandwidth
|
||||
; -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH
|
||||
; lwIP 2 - Higher Bandwidth Low Memory no Features
|
||||
; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY_LOW_FLASH
|
||||
; lwIP 2 - Higher Bandwidth no Features (Tasmota default)
|
||||
-DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH_LOW_FLASH
|
||||
; lwIP 2 - Higher Bandwidth IPv6 (use ONLY if you need IPv6, experimental!)
|
||||
; -DPIO_FRAMEWORK_ARDUINO_LWIP2_IPV6_HIGHER_BANDWIDTH
|
||||
; VTABLES in Flash (Tasmota default)
|
||||
-DVTABLES_IN_FLASH
|
||||
; VTABLES in Heap
|
||||
; -DVTABLES_IN_DRAM
|
||||
; VTABLES in IRAM
|
||||
; -DVTABLES_IN_IRAM
|
||||
; enable one option set -> No exception recommended
|
||||
; No exception code in firmware
|
||||
-fno-exceptions
|
||||
-lstdc++
|
||||
; Exception code in firmware /needs much space! 90k
|
||||
; -fexceptions
|
||||
; -lstdc++-exc
|
||||
|
||||
[tasmota_feature_stage]
|
||||
; *** Esp8266 core for Arduino version Tasmota feature stage
|
||||
platform = espressif8266@2.4.0
|
||||
[tasmota_stage]
|
||||
; *** Esp8266 core for Arduino version Tasmota stage
|
||||
platform = espressif8266@2.5.0
|
||||
platform_packages = framework-arduinoespressif8266 @ https://github.com/esp8266/Arduino.git#36e047e908cfa6eafaaf824988070b49f2c2ff2a
|
||||
build_flags = ${esp82xx_defaults.build_flags}
|
||||
-DBEARSSL_SSL_BASIC
|
||||
@ -174,8 +126,8 @@ build_flags = ${esp82xx_defaults.build_flags}
|
||||
; -lstdc++-exc
|
||||
|
||||
[core_stage]
|
||||
; *** Esp8266 core for Arduino version latest beta
|
||||
platform = espressif8266@2.4.0
|
||||
; *** Esp8266 core for Arduino version latest development version
|
||||
platform = espressif8266@2.5.0
|
||||
platform_packages = framework-arduinoespressif8266 @ https://github.com/esp8266/Arduino.git
|
||||
build_flags = ${esp82xx_defaults.build_flags}
|
||||
-DBEARSSL_SSL_BASIC
|
||||
|
@ -2,10 +2,15 @@
|
||||
|
||||
## Released
|
||||
|
||||
### 8.3.0 20200507
|
||||
### 8.3.0 20200514
|
||||
|
||||
- Release Fred
|
||||
|
||||
### 8.2.0.6 20200501
|
||||
|
||||
- Add experimental basic support for Tasmota on ESP32 based on work by Jörg Schüler-Maroldt
|
||||
- Change PWM updated to latest Arduino Core #7213
|
||||
|
||||
### 8.2.0.5 20200425
|
||||
|
||||
- Breaking Change Device Groups multicast address and port (#8270)
|
||||
|
@ -5,23 +5,23 @@
|
||||
Copyright (c) 2018 Earle F. Philhower, III. All rights reserved.
|
||||
|
||||
The core idea is to have a programmable waveform generator with a unique
|
||||
high and low period (defined in microseconds or CPU clock cycles). TIMER1 is
|
||||
set to 1-shot mode and is always loaded with the time until the next edge
|
||||
of any live waveforms.
|
||||
high and low period (defined in microseconds or CPU clock cycles). TIMER1
|
||||
is set to 1-shot mode and is always loaded with the time until the next
|
||||
edge of any live waveforms.
|
||||
|
||||
Up to one waveform generator per pin supported.
|
||||
|
||||
Each waveform generator is synchronized to the ESP clock cycle counter, not the
|
||||
timer. This allows for removing interrupt jitter and delay as the counter
|
||||
always increments once per 80MHz clock. Changes to a waveform are
|
||||
Each waveform generator is synchronized to the ESP clock cycle counter, not
|
||||
the timer. This allows for removing interrupt jitter and delay as the
|
||||
counter always increments once per 80MHz clock. Changes to a waveform are
|
||||
contiguous and only take effect on the next waveform transition,
|
||||
allowing for smooth transitions.
|
||||
|
||||
This replaces older tone(), analogWrite(), and the Servo classes.
|
||||
|
||||
Everywhere in the code where "cycles" is used, it means ESP.getCycleCount()
|
||||
clock cycle count, or an interval measured in CPU clock cycles, but not TIMER1
|
||||
cycles (which may be 2 CPU clock cycles @ 160MHz).
|
||||
clock cycle count, or an interval measured in CPU clock cycles, but not
|
||||
TIMER1 cycles (which may be 2 CPU clock cycles @ 160MHz).
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
@ -65,60 +65,62 @@ typedef struct {
|
||||
uint32_t expiryCycle; // For time-limited waveform, the cycle when this waveform must stop
|
||||
uint32_t timeHighCycles; // Currently running waveform period
|
||||
uint32_t timeLowCycles; //
|
||||
uint32_t desiredHighCycles; // Currently running waveform period
|
||||
uint32_t desiredLowCycles; //
|
||||
uint32_t gotoTimeHighCycles; // Copied over on the next period to preserve phase
|
||||
uint32_t gotoTimeLowCycles; //
|
||||
uint32_t lastEdge; //
|
||||
} Waveform;
|
||||
|
||||
static Waveform waveform[17]; // State of all possible pins
|
||||
static volatile uint32_t waveformState = 0; // Is the pin high or low, updated in NMI so no access outside the NMI code
|
||||
static volatile uint32_t waveformEnabled = 0; // Is it actively running, updated in NMI so no access outside the NMI code
|
||||
class WVFState {
|
||||
public:
|
||||
Waveform waveform[17]; // State of all possible pins
|
||||
uint32_t waveformState = 0; // Is the pin high or low, updated in NMI so no access outside the NMI code
|
||||
uint32_t waveformEnabled = 0; // Is it actively running, updated in NMI so no access outside the NMI code
|
||||
|
||||
// Enable lock-free by only allowing updates to waveformState and waveformEnabled from IRQ service routine
|
||||
static volatile uint32_t waveformToEnable = 0; // Message to the NMI handler to start a waveform on a inactive pin
|
||||
static volatile uint32_t waveformToDisable = 0; // Message to the NMI handler to disable a pin from waveform generation
|
||||
// Enable lock-free by only allowing updates to waveformState and waveformEnabled from IRQ service routine
|
||||
uint32_t waveformToEnable = 0; // Message to the NMI handler to start a waveform on a inactive pin
|
||||
uint32_t waveformToDisable = 0; // Message to the NMI handler to disable a pin from waveform generation
|
||||
|
||||
volatile int32_t waveformToChange = -1;
|
||||
volatile uint32_t waveformNewHigh = 0;
|
||||
volatile uint32_t waveformNewLow = 0;
|
||||
int32_t waveformToChange = -1;
|
||||
uint32_t waveformNewHigh = 0;
|
||||
uint32_t waveformNewLow = 0;
|
||||
|
||||
static uint32_t (*timer1CB)() = NULL;
|
||||
uint32_t (*timer1CB)() = NULL;
|
||||
|
||||
// Optimize the NMI inner loop by keeping track of the min and max GPIO that we
|
||||
// are generating. In the common case (1 PWM) these may be the same pin and
|
||||
// we can avoid looking at the other pins.
|
||||
int startPin = 0;
|
||||
int endPin = 0;
|
||||
};
|
||||
static WVFState wvfState;
|
||||
|
||||
|
||||
// Ensure everything is read/written to RAM
|
||||
#define MEMBARRIER() { __asm__ volatile("" ::: "memory"); }
|
||||
|
||||
// Non-speed critical bits
|
||||
#pragma GCC optimize ("Os")
|
||||
|
||||
static inline ICACHE_RAM_ATTR uint32_t GetCycleCount() {
|
||||
uint32_t ccount;
|
||||
__asm__ __volatile__("esync; rsr %0,ccount":"=a"(ccount));
|
||||
return ccount;
|
||||
}
|
||||
|
||||
// Interrupt on/off control
|
||||
static ICACHE_RAM_ATTR void timer1Interrupt();
|
||||
static bool timerRunning = false;
|
||||
|
||||
static void initTimer() {
|
||||
timer1_disable();
|
||||
ETS_FRC_TIMER1_INTR_ATTACH(NULL, NULL);
|
||||
ETS_FRC_TIMER1_NMI_INTR_ATTACH(timer1Interrupt);
|
||||
timer1_enable(TIM_DIV1, TIM_EDGE, TIM_SINGLE);
|
||||
timerRunning = true;
|
||||
if (!timerRunning) {
|
||||
timer1_disable();
|
||||
ETS_FRC_TIMER1_INTR_ATTACH(NULL, NULL);
|
||||
ETS_FRC_TIMER1_NMI_INTR_ATTACH(timer1Interrupt);
|
||||
timer1_enable(TIM_DIV1, TIM_EDGE, TIM_SINGLE);
|
||||
timerRunning = true;
|
||||
timer1_write(microsecondsToClockCycles(10));
|
||||
}
|
||||
}
|
||||
|
||||
static void ICACHE_RAM_ATTR deinitTimer() {
|
||||
ETS_FRC_TIMER1_NMI_INTR_ATTACH(NULL);
|
||||
timer1_disable();
|
||||
timer1_isr_init();
|
||||
timerRunning = false;
|
||||
}
|
||||
|
||||
// Set a callback. Pass in NULL to stop it
|
||||
void setTimer1Callback(uint32_t (*fn)()) {
|
||||
timer1CB = fn;
|
||||
if (!timerRunning && fn) {
|
||||
initTimer();
|
||||
timer1_write(microsecondsToClockCycles(1)); // Cause an interrupt post-haste
|
||||
} else if (timerRunning && !fn && !waveformEnabled) {
|
||||
deinitTimer();
|
||||
static ICACHE_RAM_ATTR void forceTimerInterrupt() {
|
||||
if (T1L > microsecondsToClockCycles(10)) {
|
||||
T1L = microsecondsToClockCycles(10);
|
||||
}
|
||||
}
|
||||
|
||||
@ -135,24 +137,31 @@ void setTimer1Callback(uint32_t (*fn)()) {
|
||||
|
||||
constexpr int maxPWMs = 8;
|
||||
|
||||
// PWM edge definition
|
||||
typedef struct {
|
||||
unsigned int pin : 8;
|
||||
unsigned int delta : 24;
|
||||
} PWMEntry;
|
||||
|
||||
// PWM machine state
|
||||
typedef struct {
|
||||
uint32_t mask; // Bitmask of active pins
|
||||
uint8_t cnt; // How many entries
|
||||
uint8_t idx; // Where the state machine is along the list
|
||||
PWMEntry edge[maxPWMs + 1]; // Include space for terminal element
|
||||
uint32_t cnt; // How many entries
|
||||
uint32_t idx; // Where the state machine is along the list
|
||||
uint8_t pin[maxPWMs + 1];
|
||||
uint32_t delta[maxPWMs + 1];
|
||||
uint32_t nextServiceCycle; // Clock cycle for next step
|
||||
} PWMState;
|
||||
|
||||
static PWMState pwmState;
|
||||
static volatile PWMState *pwmUpdate = nullptr; // Set by main code, cleared by ISR
|
||||
static uint32_t pwmPeriod = (1000000L * system_get_cpu_freq()) / 1000;
|
||||
static PWMState *pwmUpdate = nullptr; // Set by main code, cleared by ISR
|
||||
static uint32_t pwmPeriod = microsecondsToClockCycles(1000000UL) / 1000;
|
||||
|
||||
|
||||
|
||||
static ICACHE_RAM_ATTR void disableIdleTimer() {
|
||||
if (timerRunning && !wvfState.waveformEnabled && !pwmState.cnt && !wvfState.timer1CB) {
|
||||
ETS_FRC_TIMER1_NMI_INTR_ATTACH(NULL);
|
||||
timer1_disable();
|
||||
timer1_isr_init();
|
||||
timerRunning = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Called when analogWriteFreq() changed to update the PWM total period
|
||||
void _setPWMPeriodCC(uint32_t cc) {
|
||||
@ -168,111 +177,118 @@ void _setPWMPeriodCC(uint32_t cc) {
|
||||
PWMState p; // The working copy since we can't edit the one in use
|
||||
p = pwmState;
|
||||
uint32_t ttl = 0;
|
||||
for (auto i = 0; i < p.cnt; i++) {
|
||||
uint64_t val64p16 = ((uint64_t)p.edge[i].delta) << 16;
|
||||
for (uint32_t i = 0; i < p.cnt; i++) {
|
||||
uint64_t val64p16 = ((uint64_t)p.delta[i]) << 16;
|
||||
uint64_t newVal64p32 = val64p16 * ratio64p16;
|
||||
p.edge[i].delta = newVal64p32 >> 32;
|
||||
ttl += p.edge[i].delta;
|
||||
p.delta[i] = newVal64p32 >> 32;
|
||||
ttl += p.delta[i];
|
||||
}
|
||||
p.edge[p.cnt].delta = cc - ttl; // Final cleanup exactly cc total cycles
|
||||
p.delta[p.cnt] = cc - ttl; // Final cleanup exactly cc total cycles
|
||||
// Update and wait for mailbox to be emptied
|
||||
pwmUpdate = &p;
|
||||
MEMBARRIER();
|
||||
forceTimerInterrupt();
|
||||
while (pwmUpdate) {
|
||||
delay(0);
|
||||
// No mem barrier. The external function call guarantees it's re-read
|
||||
}
|
||||
}
|
||||
pwmPeriod = cc;
|
||||
}
|
||||
|
||||
// Helper routine to remove an entry from the state machine
|
||||
static void _removePWMEntry(int pin, PWMState *p) {
|
||||
if (!((1<<pin) & p->mask)) {
|
||||
return;
|
||||
}
|
||||
static ICACHE_RAM_ATTR void _removePWMEntry(int pin, PWMState *p) {
|
||||
uint32_t i;
|
||||
|
||||
// Find the pin to pull out...
|
||||
for (i = 0; p->pin[i] != pin; i++) { /* no-op */ }
|
||||
auto delta = p->delta[i];
|
||||
|
||||
int delta = 0;
|
||||
int i;
|
||||
for (i=0; i < p->cnt; i++) {
|
||||
if (p->edge[i].pin == pin) {
|
||||
delta = p->edge[i].delta;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Add the removed previous pin delta to preserve absolute position
|
||||
p->edge[i+1].delta += delta;
|
||||
// Move everything back one and clean up
|
||||
p->delta[i+1] += delta;
|
||||
|
||||
// Move everything back one
|
||||
for (i++; i <= p->cnt; i++) {
|
||||
p->edge[i-1] = p->edge[i];
|
||||
p->pin[i-1] = p->pin[i];
|
||||
p->delta[i-1] = p->delta[i];
|
||||
}
|
||||
// Remove the pin from the active list
|
||||
p->mask &= ~(1<<pin);
|
||||
p->cnt--;
|
||||
}
|
||||
|
||||
// Called by analogWrite(0/100%) to disable PWM on a specific pin
|
||||
bool _stopPWM(int pin) {
|
||||
ICACHE_RAM_ATTR bool _stopPWM(int pin) {
|
||||
if (!((1<<pin) & pwmState.mask)) {
|
||||
return false; // Pin not actually active
|
||||
}
|
||||
|
||||
|
||||
PWMState p; // The working copy since we can't edit the one in use
|
||||
p = pwmState;
|
||||
_removePWMEntry(pin, &p);
|
||||
|
||||
// Update and wait for mailbox to be emptied
|
||||
pwmUpdate = &p;
|
||||
MEMBARRIER();
|
||||
forceTimerInterrupt();
|
||||
while (pwmUpdate) {
|
||||
delay(0);
|
||||
}
|
||||
// Possibly shut doen the timer completely if we're done
|
||||
if (!waveformEnabled && !pwmState.cnt && !timer1CB) {
|
||||
deinitTimer();
|
||||
MEMBARRIER();
|
||||
/* Busy wait, could be in ISR */
|
||||
}
|
||||
// Possibly shut down the timer completely if we're done
|
||||
disableIdleTimer();
|
||||
return true;
|
||||
}
|
||||
|
||||
// Called by analogWrite(1...99%) to set the PWM duty in clock cycles
|
||||
bool _setPWM(int pin, uint32_t cc) {
|
||||
stopWaveform(pin);
|
||||
PWMState p; // Working copy
|
||||
p = pwmState;
|
||||
// Get rid of any entries for this pin
|
||||
_removePWMEntry(pin, &p);
|
||||
if ((1<<pin) & p.mask) {
|
||||
_removePWMEntry(pin, &p);
|
||||
}
|
||||
// And add it to the list, in order
|
||||
if (p.cnt >= maxPWMs) {
|
||||
return false; // No space left
|
||||
} else if (p.cnt == 0) {
|
||||
// Starting up from scratch, special case 1st element and PWM period
|
||||
p.edge[0].pin = pin;
|
||||
p.edge[0].delta = cc;
|
||||
p.edge[1].pin = 0xff;
|
||||
p.edge[1].delta = pwmPeriod - cc;
|
||||
p.pin[0] = pin;
|
||||
p.delta[0] = cc;
|
||||
p.pin[1] = 0xff;
|
||||
p.delta[1] = pwmPeriod - cc;
|
||||
p.cnt = 1;
|
||||
p.mask = 1<<pin;
|
||||
} else {
|
||||
uint32_t ttl=0;
|
||||
uint32_t i;
|
||||
// Skip along until we're at the spot to insert
|
||||
for (i=0; (i <= p.cnt) && (ttl + p.edge[i].delta < cc); i++) {
|
||||
ttl += p.edge[i].delta;
|
||||
for (i=0; (i <= p.cnt) && (ttl + p.delta[i] < cc); i++) {
|
||||
ttl += p.delta[i];
|
||||
}
|
||||
// Shift everything out by one to make space for new edge
|
||||
memmove(&p.edge[i + 1], &p.edge[i], (1 + p.cnt - i) * sizeof(p.edge[0]));
|
||||
memmove(&p.pin[i + 1], &p.pin[i], (1 + p.cnt - i) * sizeof(p.pin[0]));
|
||||
memmove(&p.delta[i + 1], &p.delta[i], (1 + p.cnt - i) * sizeof(p.delta[0]));
|
||||
int off = cc - ttl; // The delta from the last edge to the one we're inserting
|
||||
p.edge[i].pin = pin;
|
||||
p.edge[i].delta = off; // Add the delta to this new pin
|
||||
p.edge[i + 1].delta -= off; // And subtract it from the follower to keep sum(deltas) constant
|
||||
p.pin[i] = pin;
|
||||
p.delta[i] = off; // Add the delta to this new pin
|
||||
p.delta[i + 1] -= off; // And subtract it from the follower to keep sum(deltas) constant
|
||||
p.cnt++;
|
||||
p.mask |= 1<<pin;
|
||||
}
|
||||
|
||||
// Set mailbox and wait for ISR to copy it over
|
||||
pwmUpdate = &p;
|
||||
if (!timerRunning) {
|
||||
initTimer();
|
||||
timer1_write(microsecondsToClockCycles(10));
|
||||
MEMBARRIER();
|
||||
initTimer();
|
||||
forceTimerInterrupt();
|
||||
while (pwmUpdate) {
|
||||
delay(0);
|
||||
}
|
||||
while (pwmUpdate) { delay(0); }
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// Start up a waveform on a pin, or change the current one. Will change to the new
|
||||
// waveform smoothly on next low->high transition. For immediate change, stopWaveform()
|
||||
// first, then it will immediately begin.
|
||||
@ -284,44 +300,59 @@ int startWaveformClockCycles(uint8_t pin, uint32_t timeHighCycles, uint32_t time
|
||||
if ((pin > 16) || isFlashInterfacePin(pin)) {
|
||||
return false;
|
||||
}
|
||||
Waveform *wave = &waveform[pin];
|
||||
wave->expiryCycle = runTimeCycles ? GetCycleCount() + runTimeCycles : 0;
|
||||
Waveform *wave = &wvfState.waveform[pin];
|
||||
wave->expiryCycle = runTimeCycles ? ESP.getCycleCount() + runTimeCycles : 0;
|
||||
if (runTimeCycles && !wave->expiryCycle) {
|
||||
wave->expiryCycle = 1; // expiryCycle==0 means no timeout, so avoid setting it
|
||||
}
|
||||
|
||||
_stopPWM(pin); // Make sure there's no PWM live here
|
||||
|
||||
uint32_t mask = 1<<pin;
|
||||
if (waveformEnabled & mask) {
|
||||
waveformNewHigh = timeHighCycles;
|
||||
waveformNewLow = timeLowCycles;
|
||||
waveformToChange = pin;
|
||||
while (waveformToChange >= 0) {
|
||||
MEMBARRIER();
|
||||
if (wvfState.waveformEnabled & mask) {
|
||||
wvfState.waveformNewHigh = timeHighCycles;
|
||||
wvfState.waveformNewLow = timeLowCycles;
|
||||
MEMBARRIER();
|
||||
wvfState.waveformToChange = pin;
|
||||
while (wvfState.waveformToChange >= 0) {
|
||||
delay(0); // Wait for waveform to update
|
||||
// No mem barrier here, the call to a global function implies global state updated
|
||||
}
|
||||
} else { // if (!(waveformEnabled & mask)) {
|
||||
} else { // if (!(wvfState.waveformEnabled & mask)) {
|
||||
wave->timeHighCycles = timeHighCycles;
|
||||
wave->timeLowCycles = timeLowCycles;
|
||||
wave->desiredHighCycles = wave->timeHighCycles;
|
||||
wave->desiredLowCycles = wave->timeLowCycles;
|
||||
wave->lastEdge = 0;
|
||||
wave->gotoTimeHighCycles = wave->timeHighCycles;
|
||||
wave->gotoTimeLowCycles = wave->timeLowCycles; // Actually set the pin high or low in the IRQ service to guarantee times
|
||||
wave->nextServiceCycle = GetCycleCount() + microsecondsToClockCycles(1);
|
||||
waveformToEnable |= mask;
|
||||
if (!timerRunning) {
|
||||
initTimer();
|
||||
timer1_write(microsecondsToClockCycles(10));
|
||||
} else {
|
||||
// Ensure timely service....
|
||||
if (T1L > microsecondsToClockCycles(10)) {
|
||||
timer1_write(microsecondsToClockCycles(10));
|
||||
}
|
||||
}
|
||||
while (waveformToEnable) {
|
||||
wave->nextServiceCycle = ESP.getCycleCount() + microsecondsToClockCycles(1);
|
||||
wvfState.waveformToEnable |= mask;
|
||||
MEMBARRIER();
|
||||
initTimer();
|
||||
forceTimerInterrupt();
|
||||
while (wvfState.waveformToEnable) {
|
||||
delay(0); // Wait for waveform to update
|
||||
// No mem barrier here, the call to a global function implies global state updated
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// Set a callback. Pass in NULL to stop it
|
||||
void setTimer1Callback(uint32_t (*fn)()) {
|
||||
wvfState.timer1CB = fn;
|
||||
if (fn) {
|
||||
initTimer();
|
||||
forceTimerInterrupt();
|
||||
}
|
||||
disableIdleTimer();
|
||||
}
|
||||
|
||||
|
||||
// Speed critical bits
|
||||
#pragma GCC optimize ("O2")
|
||||
// Normally would not want two copies like this, but due to different
|
||||
@ -349,76 +380,87 @@ int ICACHE_RAM_ATTR stopWaveform(uint8_t pin) {
|
||||
}
|
||||
// If user sends in a pin >16 but <32, this will always point to a 0 bit
|
||||
// If they send >=32, then the shift will result in 0 and it will also return false
|
||||
uint32_t mask = 1<<pin;
|
||||
if (!(waveformEnabled & mask)) {
|
||||
return false; // It's not running, nothing to do here
|
||||
}
|
||||
waveformToDisable |= mask;
|
||||
// Ensure timely service....
|
||||
if (T1L > microsecondsToClockCycles(10)) {
|
||||
timer1_write(microsecondsToClockCycles(10));
|
||||
}
|
||||
while (waveformToDisable) {
|
||||
/* no-op */ // Can't delay() since stopWaveform may be called from an IRQ
|
||||
}
|
||||
if (!waveformEnabled && !pwmState.cnt && !timer1CB) {
|
||||
deinitTimer();
|
||||
if (wvfState.waveformEnabled & (1UL << pin)) {
|
||||
wvfState.waveformToDisable = 1UL << pin;
|
||||
forceTimerInterrupt();
|
||||
while (wvfState.waveformToDisable) {
|
||||
MEMBARRIER(); // If it wasn't written yet, it has to be by now
|
||||
/* no-op */ // Can't delay() since stopWaveform may be called from an IRQ
|
||||
}
|
||||
}
|
||||
disableIdleTimer();
|
||||
return true;
|
||||
}
|
||||
|
||||
// The SDK and hardware take some time to actually get to our NMI code, so
|
||||
// decrement the next IRQ's timer value by a bit so we can actually catch the
|
||||
// real CPU cycle counter we want for the waveforms.
|
||||
|
||||
// The SDK also sometimes is running at a different speed the the Arduino core
|
||||
// so the ESP cycle counter is actually running at a variable speed.
|
||||
// adjust(x) takes care of adjusting a delta clock cycle amount accordingly.
|
||||
#if F_CPU == 80000000
|
||||
#define DELTAIRQ (microsecondsToClockCycles(3))
|
||||
#define adjust(x) ((x) << (turbo ? 1 : 0))
|
||||
#else
|
||||
#define DELTAIRQ (microsecondsToClockCycles(2))
|
||||
#define adjust(x) ((x) >> (turbo ? 0 : 1))
|
||||
#endif
|
||||
|
||||
#define ENABLE_ADJUST // Adjust takes 36 bytes
|
||||
#define ENABLE_FEEDBACK // Feedback costs 68 bytes
|
||||
#define ENABLE_PWM // PWM takes 160 bytes
|
||||
|
||||
#ifndef ENABLE_ADJUST
|
||||
#undef adjust
|
||||
#define adjust(x) (x)
|
||||
#endif
|
||||
|
||||
|
||||
static ICACHE_RAM_ATTR void timer1Interrupt() {
|
||||
// Optimize the NMI inner loop by keeping track of the min and max GPIO that we
|
||||
// are generating. In the common case (1 PWM) these may be the same pin and
|
||||
// we can avoid looking at the other pins.
|
||||
static int startPin = 0;
|
||||
static int endPin = 0;
|
||||
// Flag if the core is at 160 MHz, for use by adjust()
|
||||
bool turbo = (*(uint32_t*)0x3FF00014) & 1 ? true : false;
|
||||
|
||||
uint32_t nextEventCycles = microsecondsToClockCycles(MAXIRQUS);
|
||||
uint32_t timeoutCycle = GetCycleCountIRQ() + microsecondsToClockCycles(14);
|
||||
|
||||
if (waveformToEnable || waveformToDisable) {
|
||||
if (wvfState.waveformToEnable || wvfState.waveformToDisable) {
|
||||
// Handle enable/disable requests from main app
|
||||
waveformEnabled = (waveformEnabled & ~waveformToDisable) | waveformToEnable; // Set the requested waveforms on/off
|
||||
waveformState &= ~waveformToEnable; // And clear the state of any just started
|
||||
waveformToEnable = 0;
|
||||
waveformToDisable = 0;
|
||||
wvfState.waveformEnabled = (wvfState.waveformEnabled & ~wvfState.waveformToDisable) | wvfState.waveformToEnable; // Set the requested waveforms on/off
|
||||
wvfState.waveformState &= ~wvfState.waveformToEnable; // And clear the state of any just started
|
||||
wvfState.waveformToEnable = 0;
|
||||
wvfState.waveformToDisable = 0;
|
||||
// No mem barrier. Globals must be written to RAM on ISR exit.
|
||||
// Find the first GPIO being generated by checking GCC's find-first-set (returns 1 + the bit of the first 1 in an int32_t)
|
||||
startPin = __builtin_ffs(waveformEnabled) - 1;
|
||||
wvfState.startPin = __builtin_ffs(wvfState.waveformEnabled) - 1;
|
||||
// Find the last bit by subtracting off GCC's count-leading-zeros (no offset in this one)
|
||||
endPin = 32 - __builtin_clz(waveformEnabled);
|
||||
wvfState.endPin = 32 - __builtin_clz(wvfState.waveformEnabled);
|
||||
#ifdef ENABLE_PWM
|
||||
} else if (!pwmState.cnt && pwmUpdate) {
|
||||
// Start up the PWM generator by copying from the mailbox
|
||||
pwmState = *(PWMState*)pwmUpdate;
|
||||
pwmUpdate = nullptr;
|
||||
pwmState.cnt = 1;
|
||||
pwmState.idx = 1; // Ensure copy this cycle, cause it to start at t=0
|
||||
pwmState.nextServiceCycle = GetCycleCountIRQ(); // Do it this loop!
|
||||
pwmState.idx = pwmState.cnt; // Cause it to start at t=0
|
||||
} else if (waveformToChange >=0) {
|
||||
waveform[waveformToChange].gotoTimeHighCycles = waveformNewHigh;
|
||||
waveform[waveformToChange].gotoTimeLowCycles = waveformNewLow;
|
||||
waveformToChange = -1;
|
||||
// No need for mem barrier here. Global must be written by IRQ exit
|
||||
#endif
|
||||
} else if (wvfState.waveformToChange >= 0) {
|
||||
wvfState.waveform[wvfState.waveformToChange].gotoTimeHighCycles = wvfState.waveformNewHigh;
|
||||
wvfState.waveform[wvfState.waveformToChange].gotoTimeLowCycles = wvfState.waveformNewLow;
|
||||
wvfState.waveformToChange = -1;
|
||||
// No need for memory barrier here. The global has to be written before exit the ISR.
|
||||
}
|
||||
|
||||
bool done = false;
|
||||
if (waveformEnabled || pwmState.cnt) {
|
||||
if (wvfState.waveformEnabled || pwmState.cnt) {
|
||||
do {
|
||||
nextEventCycles = microsecondsToClockCycles(MAXIRQUS);
|
||||
|
||||
|
||||
#ifdef ENABLE_PWM
|
||||
// PWM state machine implementation
|
||||
if (pwmState.cnt) {
|
||||
uint32_t now = GetCycleCountIRQ();
|
||||
uint32_t now = GetCycleCountIRQ();
|
||||
int32_t cyclesToGo = pwmState.nextServiceCycle - now;
|
||||
if (cyclesToGo <= 10) {
|
||||
if (cyclesToGo < 0) {
|
||||
if (pwmState.idx == pwmState.cnt) { // Start of pulses, possibly copy new
|
||||
if (pwmUpdate) {
|
||||
// Do the memory copy from temp to global and clear mailbox
|
||||
@ -427,39 +469,39 @@ static ICACHE_RAM_ATTR void timer1Interrupt() {
|
||||
}
|
||||
GPOS = pwmState.mask; // Set all active pins high
|
||||
// GPIO16 isn't the same as the others
|
||||
if (pwmState.mask & 0x100) {
|
||||
GP16O |= 1;
|
||||
if (pwmState.mask & (1<<16)) {
|
||||
GP16O = 1;
|
||||
}
|
||||
pwmState.idx = 0;
|
||||
} else {
|
||||
do {
|
||||
// Drop the pin at this edge
|
||||
GPOC = 1<<pwmState.edge[pwmState.idx].pin;
|
||||
GPOC = 1<<pwmState.pin[pwmState.idx];
|
||||
// GPIO16 still needs manual work
|
||||
if (pwmState.edge[pwmState.idx].pin == 16) {
|
||||
GP16O &= ~1;
|
||||
if (pwmState.pin[pwmState.idx] == 16) {
|
||||
GP16O = 0;
|
||||
}
|
||||
pwmState.idx++;
|
||||
// Any other pins at this same PWM value will have delta==0, drop them too.
|
||||
} while (pwmState.edge[pwmState.idx].delta == 0);
|
||||
} while (pwmState.delta[pwmState.idx] == 0);
|
||||
}
|
||||
// Preserve duty cycle over PWM period by using now+xxx instead of += delta
|
||||
pwmState.nextServiceCycle = now + pwmState.edge[pwmState.idx].delta;
|
||||
cyclesToGo = pwmState.nextServiceCycle - now;
|
||||
if (cyclesToGo<0) cyclesToGo=0;
|
||||
cyclesToGo = adjust(pwmState.delta[pwmState.idx]);
|
||||
pwmState.nextServiceCycle = GetCycleCountIRQ() + cyclesToGo;
|
||||
}
|
||||
nextEventCycles = min_u32(nextEventCycles, cyclesToGo);
|
||||
}
|
||||
#endif
|
||||
|
||||
for (int i = startPin; i <= endPin; i++) {
|
||||
for (auto i = wvfState.startPin; i <= wvfState.endPin; i++) {
|
||||
uint32_t mask = 1<<i;
|
||||
|
||||
// If it's not on, ignore!
|
||||
if (!(waveformEnabled & mask)) {
|
||||
if (!(wvfState.waveformEnabled & mask)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Waveform *wave = &waveform[i];
|
||||
Waveform *wave = &wvfState.waveform[i];
|
||||
uint32_t now = GetCycleCountIRQ();
|
||||
|
||||
// Disable any waveforms that are done
|
||||
@ -467,9 +509,9 @@ static ICACHE_RAM_ATTR void timer1Interrupt() {
|
||||
int32_t expiryToGo = wave->expiryCycle - now;
|
||||
if (expiryToGo < 0) {
|
||||
// Done, remove!
|
||||
waveformEnabled &= ~mask;
|
||||
wvfState.waveformEnabled &= ~mask;
|
||||
if (i == 16) {
|
||||
GP16O &= ~1;
|
||||
GP16O = 0;
|
||||
} else {
|
||||
ClearGPIO(mask);
|
||||
}
|
||||
@ -480,27 +522,58 @@ static ICACHE_RAM_ATTR void timer1Interrupt() {
|
||||
// Check for toggles
|
||||
int32_t cyclesToGo = wave->nextServiceCycle - now;
|
||||
if (cyclesToGo < 0) {
|
||||
waveformState ^= mask;
|
||||
if (waveformState & mask) {
|
||||
uint32_t nextEdgeCycles;
|
||||
uint32_t desired = 0;
|
||||
uint32_t *timeToUpdate;
|
||||
wvfState.waveformState ^= mask;
|
||||
if (wvfState.waveformState & mask) {
|
||||
if (i == 16) {
|
||||
GP16O |= 1; // GPIO16 write slow as it's RMW
|
||||
GP16O = 1; // GPIO16 write slow as it's RMW
|
||||
} else {
|
||||
SetGPIO(mask);
|
||||
}
|
||||
wave->nextServiceCycle = now + wave->timeHighCycles;
|
||||
nextEventCycles = min_u32(nextEventCycles, wave->timeHighCycles);
|
||||
if (wave->gotoTimeHighCycles) {
|
||||
// Copy over next full-cycle timings
|
||||
wave->timeHighCycles = wave->gotoTimeHighCycles;
|
||||
wave->desiredHighCycles = wave->gotoTimeHighCycles;
|
||||
wave->timeLowCycles = wave->gotoTimeLowCycles;
|
||||
wave->desiredLowCycles = wave->gotoTimeLowCycles;
|
||||
wave->gotoTimeHighCycles = 0;
|
||||
} else {
|
||||
#ifdef ENABLE_FEEDBACK
|
||||
if (wave->lastEdge) {
|
||||
desired = wave->desiredLowCycles;
|
||||
timeToUpdate = &wave->timeLowCycles;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
nextEdgeCycles = wave->timeHighCycles;
|
||||
} else {
|
||||
if (i == 16) {
|
||||
GP16O &= ~1; // GPIO16 write slow as it's RMW
|
||||
GP16O = 0; // GPIO16 write slow as it's RMW
|
||||
} else {
|
||||
ClearGPIO(mask);
|
||||
}
|
||||
wave->nextServiceCycle = now + wave->timeLowCycles;
|
||||
nextEventCycles = min_u32(nextEventCycles, wave->timeLowCycles);
|
||||
// Copy over next full-cycle timings
|
||||
wave->timeHighCycles = wave->gotoTimeHighCycles;
|
||||
wave->timeLowCycles = wave->gotoTimeLowCycles;
|
||||
#ifdef ENABLE_FEEDBACK
|
||||
desired = wave->desiredHighCycles;
|
||||
timeToUpdate = &wave->timeHighCycles;
|
||||
#endif
|
||||
nextEdgeCycles = wave->timeLowCycles;
|
||||
}
|
||||
#ifdef ENABLE_FEEDBACK
|
||||
if (desired) {
|
||||
desired = adjust(desired);
|
||||
int32_t err = desired - (now - wave->lastEdge);
|
||||
if (abs(err) < desired) { // If we've lost > the entire phase, ignore this error signal
|
||||
err /= 2;
|
||||
*timeToUpdate += err;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
nextEdgeCycles = adjust(nextEdgeCycles);
|
||||
wave->nextServiceCycle = now + nextEdgeCycles;
|
||||
nextEventCycles = min_u32(nextEventCycles, nextEdgeCycles);
|
||||
wave->lastEdge = now;
|
||||
} else {
|
||||
uint32_t deltaCycles = wave->nextServiceCycle - now;
|
||||
nextEventCycles = min_u32(nextEventCycles, deltaCycles);
|
||||
@ -513,10 +586,10 @@ static ICACHE_RAM_ATTR void timer1Interrupt() {
|
||||
int32_t cyclesLeftTimeout = timeoutCycle - now;
|
||||
done = (cycleDeltaNextEvent < 0) || (cyclesLeftTimeout < 0);
|
||||
} while (!done);
|
||||
} // if (waveformEnabled)
|
||||
} // if (wvfState.waveformEnabled)
|
||||
|
||||
if (timer1CB) {
|
||||
nextEventCycles = min_u32(nextEventCycles, timer1CB());
|
||||
if (wvfState.timer1CB) {
|
||||
nextEventCycles = min_u32(nextEventCycles, wvfState.timer1CB());
|
||||
}
|
||||
|
||||
if (nextEventCycles < microsecondsToClockCycles(5)) {
|
||||
@ -525,11 +598,7 @@ static ICACHE_RAM_ATTR void timer1Interrupt() {
|
||||
nextEventCycles -= DELTAIRQ;
|
||||
|
||||
// Do it here instead of global function to save time and because we know it's edge-IRQ
|
||||
#if F_CPU == 160000000
|
||||
T1L = nextEventCycles >> 1; // Already know we're in range by MAXIRQUS
|
||||
#else
|
||||
T1L = nextEventCycles; // Already know we're in range by MAXIRQUS
|
||||
#endif
|
||||
T1L = nextEventCycles >> (turbo ? 1 : 0);
|
||||
TEIE |= TEIE1; // Edge int enable
|
||||
}
|
||||
|
||||
|
@ -47,8 +47,8 @@ extern void __analogWriteRange(uint32_t range) {
|
||||
extern void __analogWriteFreq(uint32_t freq) {
|
||||
if (freq < 100) {
|
||||
analogFreq = 100;
|
||||
} else if (freq > 40000) {
|
||||
analogFreq = 40000;
|
||||
} else if (freq > 60000) {
|
||||
analogFreq = 60000;
|
||||
} else {
|
||||
analogFreq = freq;
|
||||
}
|
||||
|
@ -666,6 +666,27 @@
|
||||
#define D_SENSOR_HRXL_RX "HRXL Rx"
|
||||
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
|
||||
#define D_SENSOR_AS3935 "AS3935"
|
||||
#define D_GPIO_WEBCAM_PWDN "CAM_PWDN"
|
||||
#define D_GPIO_WEBCAM_RESET "CAM_RESET"
|
||||
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK"
|
||||
#define D_GPIO_WEBCAM_SIOD "CAM_SIOD"
|
||||
#define D_GPIO_WEBCAM_SIOC "CAM_SIOC"
|
||||
#define D_GPIO_WEBCAM_Y9 "CAM_Y9"
|
||||
#define D_GPIO_WEBCAM_Y8 "CAM_Y8"
|
||||
#define D_GPIO_WEBCAM_Y7 "CAM_Y7"
|
||||
#define D_GPIO_WEBCAM_Y6 "CAM_Y6"
|
||||
#define D_GPIO_WEBCAM_Y5 "CAM_Y5"
|
||||
#define D_GPIO_WEBCAM_Y4 "CAM_Y4"
|
||||
#define D_GPIO_WEBCAM_Y3 "CAM_Y3"
|
||||
#define D_GPIO_WEBCAM_Y2 "CAM_Y2"
|
||||
#define D_GPIO_WEBCAM_VSYNC "CAM_VSYNC"
|
||||
#define D_GPIO_WEBCAM_HREF "CAM_HREF"
|
||||
#define D_GPIO_WEBCAM_PCLK "CAM_PCLK"
|
||||
#define D_GPIO_WEBCAM_PSCLK "CAM_PSCLK"
|
||||
#define D_GPIO_WEBCAM_HSD1 "CAM_HSD1"
|
||||
#define D_GPIO_WEBCAM_HSD2 "CAM_HSD2"
|
||||
#define D_GPIO_WEBCAM_HSD3 "CAM_HSD3"
|
||||
#define D_GPIO_WEBCAM_PSRCS "CAM_PSRCS"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
@ -666,6 +666,27 @@
|
||||
#define D_SENSOR_HRXL_RX "HRXL Rx"
|
||||
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
|
||||
#define D_SENSOR_AS3935 "AS3935"
|
||||
#define D_GPIO_WEBCAM_PWDN "CAM_PWDN"
|
||||
#define D_GPIO_WEBCAM_RESET "CAM_RESET"
|
||||
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK"
|
||||
#define D_GPIO_WEBCAM_SIOD "CAM_SIOD"
|
||||
#define D_GPIO_WEBCAM_SIOC "CAM_SIOC"
|
||||
#define D_GPIO_WEBCAM_Y9 "CAM_Y9"
|
||||
#define D_GPIO_WEBCAM_Y8 "CAM_Y8"
|
||||
#define D_GPIO_WEBCAM_Y7 "CAM_Y7"
|
||||
#define D_GPIO_WEBCAM_Y6 "CAM_Y6"
|
||||
#define D_GPIO_WEBCAM_Y5 "CAM_Y5"
|
||||
#define D_GPIO_WEBCAM_Y4 "CAM_Y4"
|
||||
#define D_GPIO_WEBCAM_Y3 "CAM_Y3"
|
||||
#define D_GPIO_WEBCAM_Y2 "CAM_Y2"
|
||||
#define D_GPIO_WEBCAM_VSYNC "CAM_VSYNC"
|
||||
#define D_GPIO_WEBCAM_HREF "CAM_HREF"
|
||||
#define D_GPIO_WEBCAM_PCLK "CAM_PCLK"
|
||||
#define D_GPIO_WEBCAM_PSCLK "CAM_PSCLK"
|
||||
#define D_GPIO_WEBCAM_HSD1 "CAM_HSD1"
|
||||
#define D_GPIO_WEBCAM_HSD2 "CAM_HSD2"
|
||||
#define D_GPIO_WEBCAM_HSD3 "CAM_HSD3"
|
||||
#define D_GPIO_WEBCAM_PSRCS "CAM_PSRCS"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
@ -666,6 +666,27 @@
|
||||
#define D_SENSOR_HRXL_RX "HRXL Rx"
|
||||
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
|
||||
#define D_SENSOR_AS3935 "AS3935"
|
||||
#define D_GPIO_WEBCAM_PWDN "CAM_PWDN"
|
||||
#define D_GPIO_WEBCAM_RESET "CAM_RESET"
|
||||
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK"
|
||||
#define D_GPIO_WEBCAM_SIOD "CAM_SIOD"
|
||||
#define D_GPIO_WEBCAM_SIOC "CAM_SIOC"
|
||||
#define D_GPIO_WEBCAM_Y9 "CAM_Y9"
|
||||
#define D_GPIO_WEBCAM_Y8 "CAM_Y8"
|
||||
#define D_GPIO_WEBCAM_Y7 "CAM_Y7"
|
||||
#define D_GPIO_WEBCAM_Y6 "CAM_Y6"
|
||||
#define D_GPIO_WEBCAM_Y5 "CAM_Y5"
|
||||
#define D_GPIO_WEBCAM_Y4 "CAM_Y4"
|
||||
#define D_GPIO_WEBCAM_Y3 "CAM_Y3"
|
||||
#define D_GPIO_WEBCAM_Y2 "CAM_Y2"
|
||||
#define D_GPIO_WEBCAM_VSYNC "CAM_VSYNC"
|
||||
#define D_GPIO_WEBCAM_HREF "CAM_HREF"
|
||||
#define D_GPIO_WEBCAM_PCLK "CAM_PCLK"
|
||||
#define D_GPIO_WEBCAM_PSCLK "CAM_PSCLK"
|
||||
#define D_GPIO_WEBCAM_HSD1 "CAM_HSD1"
|
||||
#define D_GPIO_WEBCAM_HSD2 "CAM_HSD2"
|
||||
#define D_GPIO_WEBCAM_HSD3 "CAM_HSD3"
|
||||
#define D_GPIO_WEBCAM_PSRCS "CAM_PSRCS"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
@ -666,6 +666,27 @@
|
||||
#define D_SENSOR_HRXL_RX "HRXL Rx"
|
||||
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
|
||||
#define D_SENSOR_AS3935 "AS3935"
|
||||
#define D_GPIO_WEBCAM_PWDN "CAM_PWDN"
|
||||
#define D_GPIO_WEBCAM_RESET "CAM_RESET"
|
||||
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK"
|
||||
#define D_GPIO_WEBCAM_SIOD "CAM_SIOD"
|
||||
#define D_GPIO_WEBCAM_SIOC "CAM_SIOC"
|
||||
#define D_GPIO_WEBCAM_Y9 "CAM_Y9"
|
||||
#define D_GPIO_WEBCAM_Y8 "CAM_Y8"
|
||||
#define D_GPIO_WEBCAM_Y7 "CAM_Y7"
|
||||
#define D_GPIO_WEBCAM_Y6 "CAM_Y6"
|
||||
#define D_GPIO_WEBCAM_Y5 "CAM_Y5"
|
||||
#define D_GPIO_WEBCAM_Y4 "CAM_Y4"
|
||||
#define D_GPIO_WEBCAM_Y3 "CAM_Y3"
|
||||
#define D_GPIO_WEBCAM_Y2 "CAM_Y2"
|
||||
#define D_GPIO_WEBCAM_VSYNC "CAM_VSYNC"
|
||||
#define D_GPIO_WEBCAM_HREF "CAM_HREF"
|
||||
#define D_GPIO_WEBCAM_PCLK "CAM_PCLK"
|
||||
#define D_GPIO_WEBCAM_PSCLK "CAM_PSCLK"
|
||||
#define D_GPIO_WEBCAM_HSD1 "CAM_HSD1"
|
||||
#define D_GPIO_WEBCAM_HSD2 "CAM_HSD2"
|
||||
#define D_GPIO_WEBCAM_HSD3 "CAM_HSD3"
|
||||
#define D_GPIO_WEBCAM_PSRCS "CAM_PSRCS"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
@ -666,6 +666,27 @@
|
||||
#define D_SENSOR_HRXL_RX "HRXL Rx"
|
||||
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
|
||||
#define D_SENSOR_AS3935 "AS3935"
|
||||
#define D_GPIO_WEBCAM_PWDN "CAM_PWDN"
|
||||
#define D_GPIO_WEBCAM_RESET "CAM_RESET"
|
||||
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK"
|
||||
#define D_GPIO_WEBCAM_SIOD "CAM_SIOD"
|
||||
#define D_GPIO_WEBCAM_SIOC "CAM_SIOC"
|
||||
#define D_GPIO_WEBCAM_Y9 "CAM_Y9"
|
||||
#define D_GPIO_WEBCAM_Y8 "CAM_Y8"
|
||||
#define D_GPIO_WEBCAM_Y7 "CAM_Y7"
|
||||
#define D_GPIO_WEBCAM_Y6 "CAM_Y6"
|
||||
#define D_GPIO_WEBCAM_Y5 "CAM_Y5"
|
||||
#define D_GPIO_WEBCAM_Y4 "CAM_Y4"
|
||||
#define D_GPIO_WEBCAM_Y3 "CAM_Y3"
|
||||
#define D_GPIO_WEBCAM_Y2 "CAM_Y2"
|
||||
#define D_GPIO_WEBCAM_VSYNC "CAM_VSYNC"
|
||||
#define D_GPIO_WEBCAM_HREF "CAM_HREF"
|
||||
#define D_GPIO_WEBCAM_PCLK "CAM_PCLK"
|
||||
#define D_GPIO_WEBCAM_PSCLK "CAM_PSCLK"
|
||||
#define D_GPIO_WEBCAM_HSD1 "CAM_HSD1"
|
||||
#define D_GPIO_WEBCAM_HSD2 "CAM_HSD2"
|
||||
#define D_GPIO_WEBCAM_HSD3 "CAM_HSD3"
|
||||
#define D_GPIO_WEBCAM_PSRCS "CAM_PSRCS"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
@ -666,6 +666,27 @@
|
||||
#define D_SENSOR_HRXL_RX "HRXL Rx"
|
||||
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
|
||||
#define D_SENSOR_AS3935 "AS3935"
|
||||
#define D_GPIO_WEBCAM_PWDN "CAM_PWDN"
|
||||
#define D_GPIO_WEBCAM_RESET "CAM_RESET"
|
||||
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK"
|
||||
#define D_GPIO_WEBCAM_SIOD "CAM_SIOD"
|
||||
#define D_GPIO_WEBCAM_SIOC "CAM_SIOC"
|
||||
#define D_GPIO_WEBCAM_Y9 "CAM_Y9"
|
||||
#define D_GPIO_WEBCAM_Y8 "CAM_Y8"
|
||||
#define D_GPIO_WEBCAM_Y7 "CAM_Y7"
|
||||
#define D_GPIO_WEBCAM_Y6 "CAM_Y6"
|
||||
#define D_GPIO_WEBCAM_Y5 "CAM_Y5"
|
||||
#define D_GPIO_WEBCAM_Y4 "CAM_Y4"
|
||||
#define D_GPIO_WEBCAM_Y3 "CAM_Y3"
|
||||
#define D_GPIO_WEBCAM_Y2 "CAM_Y2"
|
||||
#define D_GPIO_WEBCAM_VSYNC "CAM_VSYNC"
|
||||
#define D_GPIO_WEBCAM_HREF "CAM_HREF"
|
||||
#define D_GPIO_WEBCAM_PCLK "CAM_PCLK"
|
||||
#define D_GPIO_WEBCAM_PSCLK "CAM_PSCLK"
|
||||
#define D_GPIO_WEBCAM_HSD1 "CAM_HSD1"
|
||||
#define D_GPIO_WEBCAM_HSD2 "CAM_HSD2"
|
||||
#define D_GPIO_WEBCAM_HSD3 "CAM_HSD3"
|
||||
#define D_GPIO_WEBCAM_PSRCS "CAM_PSRCS"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
@ -666,6 +666,27 @@
|
||||
#define D_SENSOR_HRXL_RX "HRXL Rx"
|
||||
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
|
||||
#define D_SENSOR_AS3935 "AS3935"
|
||||
#define D_GPIO_WEBCAM_PWDN "CAM_PWDN"
|
||||
#define D_GPIO_WEBCAM_RESET "CAM_RESET"
|
||||
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK"
|
||||
#define D_GPIO_WEBCAM_SIOD "CAM_SIOD"
|
||||
#define D_GPIO_WEBCAM_SIOC "CAM_SIOC"
|
||||
#define D_GPIO_WEBCAM_Y9 "CAM_Y9"
|
||||
#define D_GPIO_WEBCAM_Y8 "CAM_Y8"
|
||||
#define D_GPIO_WEBCAM_Y7 "CAM_Y7"
|
||||
#define D_GPIO_WEBCAM_Y6 "CAM_Y6"
|
||||
#define D_GPIO_WEBCAM_Y5 "CAM_Y5"
|
||||
#define D_GPIO_WEBCAM_Y4 "CAM_Y4"
|
||||
#define D_GPIO_WEBCAM_Y3 "CAM_Y3"
|
||||
#define D_GPIO_WEBCAM_Y2 "CAM_Y2"
|
||||
#define D_GPIO_WEBCAM_VSYNC "CAM_VSYNC"
|
||||
#define D_GPIO_WEBCAM_HREF "CAM_HREF"
|
||||
#define D_GPIO_WEBCAM_PCLK "CAM_PCLK"
|
||||
#define D_GPIO_WEBCAM_PSCLK "CAM_PSCLK"
|
||||
#define D_GPIO_WEBCAM_HSD1 "CAM_HSD1"
|
||||
#define D_GPIO_WEBCAM_HSD2 "CAM_HSD2"
|
||||
#define D_GPIO_WEBCAM_HSD3 "CAM_HSD3"
|
||||
#define D_GPIO_WEBCAM_PSRCS "CAM_PSRCS"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
@ -666,6 +666,27 @@
|
||||
#define D_SENSOR_HRXL_RX "HRXL Rx"
|
||||
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
|
||||
#define D_SENSOR_AS3935 "AS3935"
|
||||
#define D_GPIO_WEBCAM_PWDN "CAM_PWDN"
|
||||
#define D_GPIO_WEBCAM_RESET "CAM_RESET"
|
||||
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK"
|
||||
#define D_GPIO_WEBCAM_SIOD "CAM_SIOD"
|
||||
#define D_GPIO_WEBCAM_SIOC "CAM_SIOC"
|
||||
#define D_GPIO_WEBCAM_Y9 "CAM_Y9"
|
||||
#define D_GPIO_WEBCAM_Y8 "CAM_Y8"
|
||||
#define D_GPIO_WEBCAM_Y7 "CAM_Y7"
|
||||
#define D_GPIO_WEBCAM_Y6 "CAM_Y6"
|
||||
#define D_GPIO_WEBCAM_Y5 "CAM_Y5"
|
||||
#define D_GPIO_WEBCAM_Y4 "CAM_Y4"
|
||||
#define D_GPIO_WEBCAM_Y3 "CAM_Y3"
|
||||
#define D_GPIO_WEBCAM_Y2 "CAM_Y2"
|
||||
#define D_GPIO_WEBCAM_VSYNC "CAM_VSYNC"
|
||||
#define D_GPIO_WEBCAM_HREF "CAM_HREF"
|
||||
#define D_GPIO_WEBCAM_PCLK "CAM_PCLK"
|
||||
#define D_GPIO_WEBCAM_PSCLK "CAM_PSCLK"
|
||||
#define D_GPIO_WEBCAM_HSD1 "CAM_HSD1"
|
||||
#define D_GPIO_WEBCAM_HSD2 "CAM_HSD2"
|
||||
#define D_GPIO_WEBCAM_HSD3 "CAM_HSD3"
|
||||
#define D_GPIO_WEBCAM_PSRCS "CAM_PSRCS"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
@ -666,6 +666,27 @@
|
||||
#define D_SENSOR_HRXL_RX "HRXL Rx"
|
||||
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
|
||||
#define D_SENSOR_AS3935 "AS3935"
|
||||
#define D_GPIO_WEBCAM_PWDN "CAM_PWDN"
|
||||
#define D_GPIO_WEBCAM_RESET "CAM_RESET"
|
||||
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK"
|
||||
#define D_GPIO_WEBCAM_SIOD "CAM_SIOD"
|
||||
#define D_GPIO_WEBCAM_SIOC "CAM_SIOC"
|
||||
#define D_GPIO_WEBCAM_Y9 "CAM_Y9"
|
||||
#define D_GPIO_WEBCAM_Y8 "CAM_Y8"
|
||||
#define D_GPIO_WEBCAM_Y7 "CAM_Y7"
|
||||
#define D_GPIO_WEBCAM_Y6 "CAM_Y6"
|
||||
#define D_GPIO_WEBCAM_Y5 "CAM_Y5"
|
||||
#define D_GPIO_WEBCAM_Y4 "CAM_Y4"
|
||||
#define D_GPIO_WEBCAM_Y3 "CAM_Y3"
|
||||
#define D_GPIO_WEBCAM_Y2 "CAM_Y2"
|
||||
#define D_GPIO_WEBCAM_VSYNC "CAM_VSYNC"
|
||||
#define D_GPIO_WEBCAM_HREF "CAM_HREF"
|
||||
#define D_GPIO_WEBCAM_PCLK "CAM_PCLK"
|
||||
#define D_GPIO_WEBCAM_PSCLK "CAM_PSCLK"
|
||||
#define D_GPIO_WEBCAM_HSD1 "CAM_HSD1"
|
||||
#define D_GPIO_WEBCAM_HSD2 "CAM_HSD2"
|
||||
#define D_GPIO_WEBCAM_HSD3 "CAM_HSD3"
|
||||
#define D_GPIO_WEBCAM_PSRCS "CAM_PSRCS"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
@ -666,6 +666,27 @@
|
||||
#define D_SENSOR_HRXL_RX "HRXL - RX"
|
||||
#define D_SENSOR_ELECTRIQ_MOODL "MOODL - TX"
|
||||
#define D_SENSOR_AS3935 "AS3935"
|
||||
#define D_GPIO_WEBCAM_PWDN "CAM_PWDN"
|
||||
#define D_GPIO_WEBCAM_RESET "CAM_RESET"
|
||||
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK"
|
||||
#define D_GPIO_WEBCAM_SIOD "CAM_SIOD"
|
||||
#define D_GPIO_WEBCAM_SIOC "CAM_SIOC"
|
||||
#define D_GPIO_WEBCAM_Y9 "CAM_Y9"
|
||||
#define D_GPIO_WEBCAM_Y8 "CAM_Y8"
|
||||
#define D_GPIO_WEBCAM_Y7 "CAM_Y7"
|
||||
#define D_GPIO_WEBCAM_Y6 "CAM_Y6"
|
||||
#define D_GPIO_WEBCAM_Y5 "CAM_Y5"
|
||||
#define D_GPIO_WEBCAM_Y4 "CAM_Y4"
|
||||
#define D_GPIO_WEBCAM_Y3 "CAM_Y3"
|
||||
#define D_GPIO_WEBCAM_Y2 "CAM_Y2"
|
||||
#define D_GPIO_WEBCAM_VSYNC "CAM_VSYNC"
|
||||
#define D_GPIO_WEBCAM_HREF "CAM_HREF"
|
||||
#define D_GPIO_WEBCAM_PCLK "CAM_PCLK"
|
||||
#define D_GPIO_WEBCAM_PSCLK "CAM_PSCLK"
|
||||
#define D_GPIO_WEBCAM_HSD1 "CAM_HSD1"
|
||||
#define D_GPIO_WEBCAM_HSD2 "CAM_HSD2"
|
||||
#define D_GPIO_WEBCAM_HSD3 "CAM_HSD3"
|
||||
#define D_GPIO_WEBCAM_PSRCS "CAM_PSRCS"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
@ -666,6 +666,27 @@
|
||||
#define D_SENSOR_HRXL_RX "HRXL Rx"
|
||||
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
|
||||
#define D_SENSOR_AS3935 "AS3935"
|
||||
#define D_GPIO_WEBCAM_PWDN "CAM_PWDN"
|
||||
#define D_GPIO_WEBCAM_RESET "CAM_RESET"
|
||||
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK"
|
||||
#define D_GPIO_WEBCAM_SIOD "CAM_SIOD"
|
||||
#define D_GPIO_WEBCAM_SIOC "CAM_SIOC"
|
||||
#define D_GPIO_WEBCAM_Y9 "CAM_Y9"
|
||||
#define D_GPIO_WEBCAM_Y8 "CAM_Y8"
|
||||
#define D_GPIO_WEBCAM_Y7 "CAM_Y7"
|
||||
#define D_GPIO_WEBCAM_Y6 "CAM_Y6"
|
||||
#define D_GPIO_WEBCAM_Y5 "CAM_Y5"
|
||||
#define D_GPIO_WEBCAM_Y4 "CAM_Y4"
|
||||
#define D_GPIO_WEBCAM_Y3 "CAM_Y3"
|
||||
#define D_GPIO_WEBCAM_Y2 "CAM_Y2"
|
||||
#define D_GPIO_WEBCAM_VSYNC "CAM_VSYNC"
|
||||
#define D_GPIO_WEBCAM_HREF "CAM_HREF"
|
||||
#define D_GPIO_WEBCAM_PCLK "CAM_PCLK"
|
||||
#define D_GPIO_WEBCAM_PSCLK "CAM_PSCLK"
|
||||
#define D_GPIO_WEBCAM_HSD1 "CAM_HSD1"
|
||||
#define D_GPIO_WEBCAM_HSD2 "CAM_HSD2"
|
||||
#define D_GPIO_WEBCAM_HSD3 "CAM_HSD3"
|
||||
#define D_GPIO_WEBCAM_PSRCS "CAM_PSRCS"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
@ -666,6 +666,27 @@
|
||||
#define D_SENSOR_HRXL_RX "HRXL Rx"
|
||||
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
|
||||
#define D_SENSOR_AS3935 "AS3935"
|
||||
#define D_GPIO_WEBCAM_PWDN "CAM_PWDN"
|
||||
#define D_GPIO_WEBCAM_RESET "CAM_RESET"
|
||||
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK"
|
||||
#define D_GPIO_WEBCAM_SIOD "CAM_SIOD"
|
||||
#define D_GPIO_WEBCAM_SIOC "CAM_SIOC"
|
||||
#define D_GPIO_WEBCAM_Y9 "CAM_Y9"
|
||||
#define D_GPIO_WEBCAM_Y8 "CAM_Y8"
|
||||
#define D_GPIO_WEBCAM_Y7 "CAM_Y7"
|
||||
#define D_GPIO_WEBCAM_Y6 "CAM_Y6"
|
||||
#define D_GPIO_WEBCAM_Y5 "CAM_Y5"
|
||||
#define D_GPIO_WEBCAM_Y4 "CAM_Y4"
|
||||
#define D_GPIO_WEBCAM_Y3 "CAM_Y3"
|
||||
#define D_GPIO_WEBCAM_Y2 "CAM_Y2"
|
||||
#define D_GPIO_WEBCAM_VSYNC "CAM_VSYNC"
|
||||
#define D_GPIO_WEBCAM_HREF "CAM_HREF"
|
||||
#define D_GPIO_WEBCAM_PCLK "CAM_PCLK"
|
||||
#define D_GPIO_WEBCAM_PSCLK "CAM_PSCLK"
|
||||
#define D_GPIO_WEBCAM_HSD1 "CAM_HSD1"
|
||||
#define D_GPIO_WEBCAM_HSD2 "CAM_HSD2"
|
||||
#define D_GPIO_WEBCAM_HSD3 "CAM_HSD3"
|
||||
#define D_GPIO_WEBCAM_PSRCS "CAM_PSRCS"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
@ -666,6 +666,27 @@
|
||||
#define D_SENSOR_HRXL_RX "HRXL Rx"
|
||||
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
|
||||
#define D_SENSOR_AS3935 "AS3935"
|
||||
#define D_GPIO_WEBCAM_PWDN "CAM_PWDN"
|
||||
#define D_GPIO_WEBCAM_RESET "CAM_RESET"
|
||||
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK"
|
||||
#define D_GPIO_WEBCAM_SIOD "CAM_SIOD"
|
||||
#define D_GPIO_WEBCAM_SIOC "CAM_SIOC"
|
||||
#define D_GPIO_WEBCAM_Y9 "CAM_Y9"
|
||||
#define D_GPIO_WEBCAM_Y8 "CAM_Y8"
|
||||
#define D_GPIO_WEBCAM_Y7 "CAM_Y7"
|
||||
#define D_GPIO_WEBCAM_Y6 "CAM_Y6"
|
||||
#define D_GPIO_WEBCAM_Y5 "CAM_Y5"
|
||||
#define D_GPIO_WEBCAM_Y4 "CAM_Y4"
|
||||
#define D_GPIO_WEBCAM_Y3 "CAM_Y3"
|
||||
#define D_GPIO_WEBCAM_Y2 "CAM_Y2"
|
||||
#define D_GPIO_WEBCAM_VSYNC "CAM_VSYNC"
|
||||
#define D_GPIO_WEBCAM_HREF "CAM_HREF"
|
||||
#define D_GPIO_WEBCAM_PCLK "CAM_PCLK"
|
||||
#define D_GPIO_WEBCAM_PSCLK "CAM_PSCLK"
|
||||
#define D_GPIO_WEBCAM_HSD1 "CAM_HSD1"
|
||||
#define D_GPIO_WEBCAM_HSD2 "CAM_HSD2"
|
||||
#define D_GPIO_WEBCAM_HSD3 "CAM_HSD3"
|
||||
#define D_GPIO_WEBCAM_PSRCS "CAM_PSRCS"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
@ -666,6 +666,27 @@
|
||||
#define D_SENSOR_HRXL_RX "HRXL Rx"
|
||||
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
|
||||
#define D_SENSOR_AS3935 "AS3935"
|
||||
#define D_GPIO_WEBCAM_PWDN "CAM_PWDN"
|
||||
#define D_GPIO_WEBCAM_RESET "CAM_RESET"
|
||||
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK"
|
||||
#define D_GPIO_WEBCAM_SIOD "CAM_SIOD"
|
||||
#define D_GPIO_WEBCAM_SIOC "CAM_SIOC"
|
||||
#define D_GPIO_WEBCAM_Y9 "CAM_Y9"
|
||||
#define D_GPIO_WEBCAM_Y8 "CAM_Y8"
|
||||
#define D_GPIO_WEBCAM_Y7 "CAM_Y7"
|
||||
#define D_GPIO_WEBCAM_Y6 "CAM_Y6"
|
||||
#define D_GPIO_WEBCAM_Y5 "CAM_Y5"
|
||||
#define D_GPIO_WEBCAM_Y4 "CAM_Y4"
|
||||
#define D_GPIO_WEBCAM_Y3 "CAM_Y3"
|
||||
#define D_GPIO_WEBCAM_Y2 "CAM_Y2"
|
||||
#define D_GPIO_WEBCAM_VSYNC "CAM_VSYNC"
|
||||
#define D_GPIO_WEBCAM_HREF "CAM_HREF"
|
||||
#define D_GPIO_WEBCAM_PCLK "CAM_PCLK"
|
||||
#define D_GPIO_WEBCAM_PSCLK "CAM_PSCLK"
|
||||
#define D_GPIO_WEBCAM_HSD1 "CAM_HSD1"
|
||||
#define D_GPIO_WEBCAM_HSD2 "CAM_HSD2"
|
||||
#define D_GPIO_WEBCAM_HSD3 "CAM_HSD3"
|
||||
#define D_GPIO_WEBCAM_PSRCS "CAM_PSRCS"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
@ -666,6 +666,27 @@
|
||||
#define D_SENSOR_HRXL_RX "HRXL Rx"
|
||||
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
|
||||
#define D_SENSOR_AS3935 "AS3935"
|
||||
#define D_GPIO_WEBCAM_PWDN "CAM_PWDN"
|
||||
#define D_GPIO_WEBCAM_RESET "CAM_RESET"
|
||||
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK"
|
||||
#define D_GPIO_WEBCAM_SIOD "CAM_SIOD"
|
||||
#define D_GPIO_WEBCAM_SIOC "CAM_SIOC"
|
||||
#define D_GPIO_WEBCAM_Y9 "CAM_Y9"
|
||||
#define D_GPIO_WEBCAM_Y8 "CAM_Y8"
|
||||
#define D_GPIO_WEBCAM_Y7 "CAM_Y7"
|
||||
#define D_GPIO_WEBCAM_Y6 "CAM_Y6"
|
||||
#define D_GPIO_WEBCAM_Y5 "CAM_Y5"
|
||||
#define D_GPIO_WEBCAM_Y4 "CAM_Y4"
|
||||
#define D_GPIO_WEBCAM_Y3 "CAM_Y3"
|
||||
#define D_GPIO_WEBCAM_Y2 "CAM_Y2"
|
||||
#define D_GPIO_WEBCAM_VSYNC "CAM_VSYNC"
|
||||
#define D_GPIO_WEBCAM_HREF "CAM_HREF"
|
||||
#define D_GPIO_WEBCAM_PCLK "CAM_PCLK"
|
||||
#define D_GPIO_WEBCAM_PSCLK "CAM_PSCLK"
|
||||
#define D_GPIO_WEBCAM_HSD1 "CAM_HSD1"
|
||||
#define D_GPIO_WEBCAM_HSD2 "CAM_HSD2"
|
||||
#define D_GPIO_WEBCAM_HSD3 "CAM_HSD3"
|
||||
#define D_GPIO_WEBCAM_PSRCS "CAM_PSRCS"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
@ -666,6 +666,27 @@
|
||||
#define D_SENSOR_HRXL_RX "HRXL Rx"
|
||||
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
|
||||
#define D_SENSOR_AS3935 "AS3935"
|
||||
#define D_GPIO_WEBCAM_PWDN "CAM_PWDN"
|
||||
#define D_GPIO_WEBCAM_RESET "CAM_RESET"
|
||||
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK"
|
||||
#define D_GPIO_WEBCAM_SIOD "CAM_SIOD"
|
||||
#define D_GPIO_WEBCAM_SIOC "CAM_SIOC"
|
||||
#define D_GPIO_WEBCAM_Y9 "CAM_Y9"
|
||||
#define D_GPIO_WEBCAM_Y8 "CAM_Y8"
|
||||
#define D_GPIO_WEBCAM_Y7 "CAM_Y7"
|
||||
#define D_GPIO_WEBCAM_Y6 "CAM_Y6"
|
||||
#define D_GPIO_WEBCAM_Y5 "CAM_Y5"
|
||||
#define D_GPIO_WEBCAM_Y4 "CAM_Y4"
|
||||
#define D_GPIO_WEBCAM_Y3 "CAM_Y3"
|
||||
#define D_GPIO_WEBCAM_Y2 "CAM_Y2"
|
||||
#define D_GPIO_WEBCAM_VSYNC "CAM_VSYNC"
|
||||
#define D_GPIO_WEBCAM_HREF "CAM_HREF"
|
||||
#define D_GPIO_WEBCAM_PCLK "CAM_PCLK"
|
||||
#define D_GPIO_WEBCAM_PSCLK "CAM_PSCLK"
|
||||
#define D_GPIO_WEBCAM_HSD1 "CAM_HSD1"
|
||||
#define D_GPIO_WEBCAM_HSD2 "CAM_HSD2"
|
||||
#define D_GPIO_WEBCAM_HSD3 "CAM_HSD3"
|
||||
#define D_GPIO_WEBCAM_PSRCS "CAM_PSRCS"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
@ -666,6 +666,27 @@
|
||||
#define D_SENSOR_HRXL_RX "HRXL Rx"
|
||||
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
|
||||
#define D_SENSOR_AS3935 "AS3935"
|
||||
#define D_GPIO_WEBCAM_PWDN "CAM_PWDN"
|
||||
#define D_GPIO_WEBCAM_RESET "CAM_RESET"
|
||||
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK"
|
||||
#define D_GPIO_WEBCAM_SIOD "CAM_SIOD"
|
||||
#define D_GPIO_WEBCAM_SIOC "CAM_SIOC"
|
||||
#define D_GPIO_WEBCAM_Y9 "CAM_Y9"
|
||||
#define D_GPIO_WEBCAM_Y8 "CAM_Y8"
|
||||
#define D_GPIO_WEBCAM_Y7 "CAM_Y7"
|
||||
#define D_GPIO_WEBCAM_Y6 "CAM_Y6"
|
||||
#define D_GPIO_WEBCAM_Y5 "CAM_Y5"
|
||||
#define D_GPIO_WEBCAM_Y4 "CAM_Y4"
|
||||
#define D_GPIO_WEBCAM_Y3 "CAM_Y3"
|
||||
#define D_GPIO_WEBCAM_Y2 "CAM_Y2"
|
||||
#define D_GPIO_WEBCAM_VSYNC "CAM_VSYNC"
|
||||
#define D_GPIO_WEBCAM_HREF "CAM_HREF"
|
||||
#define D_GPIO_WEBCAM_PCLK "CAM_PCLK"
|
||||
#define D_GPIO_WEBCAM_PSCLK "CAM_PSCLK"
|
||||
#define D_GPIO_WEBCAM_HSD1 "CAM_HSD1"
|
||||
#define D_GPIO_WEBCAM_HSD2 "CAM_HSD2"
|
||||
#define D_GPIO_WEBCAM_HSD3 "CAM_HSD3"
|
||||
#define D_GPIO_WEBCAM_PSRCS "CAM_PSRCS"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "А"
|
||||
|
@ -666,6 +666,27 @@
|
||||
#define D_SENSOR_HRXL_RX "HRXL Rx"
|
||||
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
|
||||
#define D_SENSOR_AS3935 "AS3935"
|
||||
#define D_GPIO_WEBCAM_PWDN "CAM_PWDN"
|
||||
#define D_GPIO_WEBCAM_RESET "CAM_RESET"
|
||||
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK"
|
||||
#define D_GPIO_WEBCAM_SIOD "CAM_SIOD"
|
||||
#define D_GPIO_WEBCAM_SIOC "CAM_SIOC"
|
||||
#define D_GPIO_WEBCAM_Y9 "CAM_Y9"
|
||||
#define D_GPIO_WEBCAM_Y8 "CAM_Y8"
|
||||
#define D_GPIO_WEBCAM_Y7 "CAM_Y7"
|
||||
#define D_GPIO_WEBCAM_Y6 "CAM_Y6"
|
||||
#define D_GPIO_WEBCAM_Y5 "CAM_Y5"
|
||||
#define D_GPIO_WEBCAM_Y4 "CAM_Y4"
|
||||
#define D_GPIO_WEBCAM_Y3 "CAM_Y3"
|
||||
#define D_GPIO_WEBCAM_Y2 "CAM_Y2"
|
||||
#define D_GPIO_WEBCAM_VSYNC "CAM_VSYNC"
|
||||
#define D_GPIO_WEBCAM_HREF "CAM_HREF"
|
||||
#define D_GPIO_WEBCAM_PCLK "CAM_PCLK"
|
||||
#define D_GPIO_WEBCAM_PSCLK "CAM_PSCLK"
|
||||
#define D_GPIO_WEBCAM_HSD1 "CAM_HSD1"
|
||||
#define D_GPIO_WEBCAM_HSD2 "CAM_HSD2"
|
||||
#define D_GPIO_WEBCAM_HSD3 "CAM_HSD3"
|
||||
#define D_GPIO_WEBCAM_PSRCS "CAM_PSRCS"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
@ -666,6 +666,27 @@
|
||||
#define D_SENSOR_HRXL_RX "HRXL Rx"
|
||||
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
|
||||
#define D_SENSOR_AS3935 "AS3935"
|
||||
#define D_GPIO_WEBCAM_PWDN "CAM_PWDN"
|
||||
#define D_GPIO_WEBCAM_RESET "CAM_RESET"
|
||||
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK"
|
||||
#define D_GPIO_WEBCAM_SIOD "CAM_SIOD"
|
||||
#define D_GPIO_WEBCAM_SIOC "CAM_SIOC"
|
||||
#define D_GPIO_WEBCAM_Y9 "CAM_Y9"
|
||||
#define D_GPIO_WEBCAM_Y8 "CAM_Y8"
|
||||
#define D_GPIO_WEBCAM_Y7 "CAM_Y7"
|
||||
#define D_GPIO_WEBCAM_Y6 "CAM_Y6"
|
||||
#define D_GPIO_WEBCAM_Y5 "CAM_Y5"
|
||||
#define D_GPIO_WEBCAM_Y4 "CAM_Y4"
|
||||
#define D_GPIO_WEBCAM_Y3 "CAM_Y3"
|
||||
#define D_GPIO_WEBCAM_Y2 "CAM_Y2"
|
||||
#define D_GPIO_WEBCAM_VSYNC "CAM_VSYNC"
|
||||
#define D_GPIO_WEBCAM_HREF "CAM_HREF"
|
||||
#define D_GPIO_WEBCAM_PCLK "CAM_PCLK"
|
||||
#define D_GPIO_WEBCAM_PSCLK "CAM_PSCLK"
|
||||
#define D_GPIO_WEBCAM_HSD1 "CAM_HSD1"
|
||||
#define D_GPIO_WEBCAM_HSD2 "CAM_HSD2"
|
||||
#define D_GPIO_WEBCAM_HSD3 "CAM_HSD3"
|
||||
#define D_GPIO_WEBCAM_PSRCS "CAM_PSRCS"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
@ -666,6 +666,27 @@
|
||||
#define D_SENSOR_HRXL_RX "HRXL Rx"
|
||||
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
|
||||
#define D_SENSOR_AS3935 "AS3935"
|
||||
#define D_GPIO_WEBCAM_PWDN "CAM_PWDN"
|
||||
#define D_GPIO_WEBCAM_RESET "CAM_RESET"
|
||||
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK"
|
||||
#define D_GPIO_WEBCAM_SIOD "CAM_SIOD"
|
||||
#define D_GPIO_WEBCAM_SIOC "CAM_SIOC"
|
||||
#define D_GPIO_WEBCAM_Y9 "CAM_Y9"
|
||||
#define D_GPIO_WEBCAM_Y8 "CAM_Y8"
|
||||
#define D_GPIO_WEBCAM_Y7 "CAM_Y7"
|
||||
#define D_GPIO_WEBCAM_Y6 "CAM_Y6"
|
||||
#define D_GPIO_WEBCAM_Y5 "CAM_Y5"
|
||||
#define D_GPIO_WEBCAM_Y4 "CAM_Y4"
|
||||
#define D_GPIO_WEBCAM_Y3 "CAM_Y3"
|
||||
#define D_GPIO_WEBCAM_Y2 "CAM_Y2"
|
||||
#define D_GPIO_WEBCAM_VSYNC "CAM_VSYNC"
|
||||
#define D_GPIO_WEBCAM_HREF "CAM_HREF"
|
||||
#define D_GPIO_WEBCAM_PCLK "CAM_PCLK"
|
||||
#define D_GPIO_WEBCAM_PSCLK "CAM_PSCLK"
|
||||
#define D_GPIO_WEBCAM_HSD1 "CAM_HSD1"
|
||||
#define D_GPIO_WEBCAM_HSD2 "CAM_HSD2"
|
||||
#define D_GPIO_WEBCAM_HSD3 "CAM_HSD3"
|
||||
#define D_GPIO_WEBCAM_PSRCS "CAM_PSRCS"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
@ -666,6 +666,27 @@
|
||||
#define D_SENSOR_HRXL_RX "HRXL Rx"
|
||||
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
|
||||
#define D_SENSOR_AS3935 "AS3935"
|
||||
#define D_GPIO_WEBCAM_PWDN "CAM_PWDN"
|
||||
#define D_GPIO_WEBCAM_RESET "CAM_RESET"
|
||||
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK"
|
||||
#define D_GPIO_WEBCAM_SIOD "CAM_SIOD"
|
||||
#define D_GPIO_WEBCAM_SIOC "CAM_SIOC"
|
||||
#define D_GPIO_WEBCAM_Y9 "CAM_Y9"
|
||||
#define D_GPIO_WEBCAM_Y8 "CAM_Y8"
|
||||
#define D_GPIO_WEBCAM_Y7 "CAM_Y7"
|
||||
#define D_GPIO_WEBCAM_Y6 "CAM_Y6"
|
||||
#define D_GPIO_WEBCAM_Y5 "CAM_Y5"
|
||||
#define D_GPIO_WEBCAM_Y4 "CAM_Y4"
|
||||
#define D_GPIO_WEBCAM_Y3 "CAM_Y3"
|
||||
#define D_GPIO_WEBCAM_Y2 "CAM_Y2"
|
||||
#define D_GPIO_WEBCAM_VSYNC "CAM_VSYNC"
|
||||
#define D_GPIO_WEBCAM_HREF "CAM_HREF"
|
||||
#define D_GPIO_WEBCAM_PCLK "CAM_PCLK"
|
||||
#define D_GPIO_WEBCAM_PSCLK "CAM_PSCLK"
|
||||
#define D_GPIO_WEBCAM_HSD1 "CAM_HSD1"
|
||||
#define D_GPIO_WEBCAM_HSD2 "CAM_HSD2"
|
||||
#define D_GPIO_WEBCAM_HSD3 "CAM_HSD3"
|
||||
#define D_GPIO_WEBCAM_PSRCS "CAM_PSRCS"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "А"
|
||||
|
@ -666,6 +666,27 @@
|
||||
#define D_SENSOR_HRXL_RX "HRXL Rx"
|
||||
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
|
||||
#define D_SENSOR_AS3935 "AS3935"
|
||||
#define D_GPIO_WEBCAM_PWDN "CAM_PWDN"
|
||||
#define D_GPIO_WEBCAM_RESET "CAM_RESET"
|
||||
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK"
|
||||
#define D_GPIO_WEBCAM_SIOD "CAM_SIOD"
|
||||
#define D_GPIO_WEBCAM_SIOC "CAM_SIOC"
|
||||
#define D_GPIO_WEBCAM_Y9 "CAM_Y9"
|
||||
#define D_GPIO_WEBCAM_Y8 "CAM_Y8"
|
||||
#define D_GPIO_WEBCAM_Y7 "CAM_Y7"
|
||||
#define D_GPIO_WEBCAM_Y6 "CAM_Y6"
|
||||
#define D_GPIO_WEBCAM_Y5 "CAM_Y5"
|
||||
#define D_GPIO_WEBCAM_Y4 "CAM_Y4"
|
||||
#define D_GPIO_WEBCAM_Y3 "CAM_Y3"
|
||||
#define D_GPIO_WEBCAM_Y2 "CAM_Y2"
|
||||
#define D_GPIO_WEBCAM_VSYNC "CAM_VSYNC"
|
||||
#define D_GPIO_WEBCAM_HREF "CAM_HREF"
|
||||
#define D_GPIO_WEBCAM_PCLK "CAM_PCLK"
|
||||
#define D_GPIO_WEBCAM_PSCLK "CAM_PSCLK"
|
||||
#define D_GPIO_WEBCAM_HSD1 "CAM_HSD1"
|
||||
#define D_GPIO_WEBCAM_HSD2 "CAM_HSD2"
|
||||
#define D_GPIO_WEBCAM_HSD3 "CAM_HSD3"
|
||||
#define D_GPIO_WEBCAM_PSRCS "CAM_PSRCS"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "安"
|
||||
|
@ -666,6 +666,27 @@
|
||||
#define D_SENSOR_HRXL_RX "HRXL Rx"
|
||||
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
|
||||
#define D_SENSOR_AS3935 "AS3935"
|
||||
#define D_GPIO_WEBCAM_PWDN "CAM_PWDN"
|
||||
#define D_GPIO_WEBCAM_RESET "CAM_RESET"
|
||||
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK"
|
||||
#define D_GPIO_WEBCAM_SIOD "CAM_SIOD"
|
||||
#define D_GPIO_WEBCAM_SIOC "CAM_SIOC"
|
||||
#define D_GPIO_WEBCAM_Y9 "CAM_Y9"
|
||||
#define D_GPIO_WEBCAM_Y8 "CAM_Y8"
|
||||
#define D_GPIO_WEBCAM_Y7 "CAM_Y7"
|
||||
#define D_GPIO_WEBCAM_Y6 "CAM_Y6"
|
||||
#define D_GPIO_WEBCAM_Y5 "CAM_Y5"
|
||||
#define D_GPIO_WEBCAM_Y4 "CAM_Y4"
|
||||
#define D_GPIO_WEBCAM_Y3 "CAM_Y3"
|
||||
#define D_GPIO_WEBCAM_Y2 "CAM_Y2"
|
||||
#define D_GPIO_WEBCAM_VSYNC "CAM_VSYNC"
|
||||
#define D_GPIO_WEBCAM_HREF "CAM_HREF"
|
||||
#define D_GPIO_WEBCAM_PCLK "CAM_PCLK"
|
||||
#define D_GPIO_WEBCAM_PSCLK "CAM_PSCLK"
|
||||
#define D_GPIO_WEBCAM_HSD1 "CAM_HSD1"
|
||||
#define D_GPIO_WEBCAM_HSD2 "CAM_HSD2"
|
||||
#define D_GPIO_WEBCAM_HSD3 "CAM_HSD3"
|
||||
#define D_GPIO_WEBCAM_PSRCS "CAM_PSRCS"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "安"
|
||||
|
@ -41,6 +41,7 @@ class SendEmail
|
||||
public:
|
||||
SendEmail(const String& host, const int port, const String& user, const String& passwd, const int timeout, const int auth_used);
|
||||
bool send(const String& from, const String& to, const String& subject, const char *msg);
|
||||
void send_message_txt(char *msg);
|
||||
~SendEmail() {client->stop(); delete client;}
|
||||
};
|
||||
|
||||
|
@ -1,5 +1,7 @@
|
||||
#ifdef USE_SENDMAIL
|
||||
|
||||
#ifndef USE_ESP32MAIL
|
||||
|
||||
#include "sendemail.h"
|
||||
|
||||
// enable serial debugging
|
||||
@ -26,6 +28,8 @@
|
||||
#define SEND_MAIL_MINRAM 12*1024
|
||||
#endif
|
||||
|
||||
void script_send_email_body(void(*func)(char *));
|
||||
|
||||
#define xPSTR(a) a
|
||||
|
||||
uint16_t SendMail(char *buffer) {
|
||||
@ -47,7 +51,7 @@ uint16_t SendMail(char *buffer) {
|
||||
|
||||
|
||||
// return if not enough memory
|
||||
uint16_t mem=ESP_getFreeHeap();
|
||||
uint16_t mem=ESP.getFreeHeap();
|
||||
if (mem<SEND_MAIL_MINRAM) {
|
||||
return 4;
|
||||
}
|
||||
@ -174,13 +178,15 @@ exit:
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef ESP8266
|
||||
void script_send_email_body(BearSSL::WiFiClientSecure_light *client);
|
||||
WiFiClient *g_client;
|
||||
SendEmail::SendEmail(const String& host, const int port, const String& user, const String& passwd, const int timeout, const int auth_used) :
|
||||
host(host), port(port), user(user), passwd(passwd), timeout(timeout), ssl(ssl), auth_used(auth_used), client(new BearSSL::WiFiClientSecure_light(1024,1024)) {
|
||||
}
|
||||
#else
|
||||
void script_send_email_body(WiFiClient *client);
|
||||
WiFiClient *g_client;
|
||||
SendEmail::SendEmail(const String& host, const int port, const String& user, const String& passwd, const int timeout, const int auth_used) :
|
||||
host(host), port(port), user(user), passwd(passwd), timeout(timeout), ssl(ssl), auth_used(auth_used), client(new WiFiClientSecure()) {
|
||||
}
|
||||
@ -346,7 +352,8 @@ String buffer;
|
||||
|
||||
#ifdef USE_SCRIPT
|
||||
if (*msg=='*' && *(msg+1)==0) {
|
||||
script_send_email_body(client);
|
||||
g_client=client;
|
||||
script_send_email_body(xsend_message_txt);
|
||||
} else {
|
||||
client->println(msg);
|
||||
}
|
||||
@ -370,5 +377,289 @@ exit:
|
||||
return status;
|
||||
}
|
||||
|
||||
void xsend_message_txt(char *msg) {
|
||||
g_client->println(msg);
|
||||
}
|
||||
#else
|
||||
|
||||
/*
|
||||
* Created by K. Suwatchai (Mobizt)
|
||||
*
|
||||
* Email: k_suwatchai@hotmail.com
|
||||
*
|
||||
* Github: https://github.com/mobizt
|
||||
*
|
||||
* Copyright (c) 2019 mobizt
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
//To use send Email for Gmail to port 465 (SSL), less secure app option should be enabled. https://myaccount.google.com/lesssecureapps?pli=1
|
||||
|
||||
//To receive Email for Gmail, IMAP option should be enabled. https://support.google.com/mail/answer/7126229?hl=en
|
||||
|
||||
#include "ESP32_MailClient.h"
|
||||
#include "SD.h"
|
||||
|
||||
//For demo only
|
||||
//#include "image.h"
|
||||
|
||||
#ifndef SEND_MAIL32_MINRAM
|
||||
#define SEND_MAIL32_MINRAM 30*1024
|
||||
#endif
|
||||
|
||||
void script_send_email_body(void(*func)(char *));
|
||||
|
||||
#define xPSTR(a) a
|
||||
//The Email Sending data object contains config and data to send
|
||||
SMTPData smtpData;
|
||||
|
||||
//Callback function to get the Email sending status
|
||||
//void sendCallback(SendStatus info);
|
||||
//#define DEBUG_EMAIL_PORT
|
||||
|
||||
uint16_t SendMail(char *buffer) {
|
||||
char *params,*oparams;
|
||||
const char *mserv;
|
||||
uint16_t port;
|
||||
const char *user;
|
||||
const char *pstr;
|
||||
const char *passwd;
|
||||
const char *from;
|
||||
const char *to;
|
||||
const char *subject;
|
||||
const char *cmd;
|
||||
uint16_t status=1;
|
||||
uint16_t blen;
|
||||
char *endcmd;
|
||||
|
||||
// return if not enough memory
|
||||
uint32_t mem=ESP.getFreeHeap();
|
||||
AddLog_P2(LOG_LEVEL_INFO, PSTR("heap: %d"),mem);
|
||||
if (mem<SEND_MAIL32_MINRAM) {
|
||||
return 4;
|
||||
}
|
||||
|
||||
while (*buffer==' ') buffer++;
|
||||
|
||||
if (*buffer!='[') {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
buffer++;
|
||||
|
||||
endcmd=strchr(buffer,']');
|
||||
if (!endcmd) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
// copy params
|
||||
blen=(uint32_t)endcmd-(uint32_t)buffer;
|
||||
oparams=(char*)calloc(blen+2,1);
|
||||
if (!oparams) return 4;
|
||||
params=oparams;
|
||||
strncpy(oparams,buffer,blen+2);
|
||||
oparams[blen]=0;
|
||||
|
||||
cmd=endcmd+1;
|
||||
|
||||
#ifdef DEBUG_EMAIL_PORT
|
||||
AddLog_P2(LOG_LEVEL_INFO, PSTR("mailsize: %d"),blen);
|
||||
#endif
|
||||
|
||||
mserv=strtok(params,":");
|
||||
if (!mserv) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
// port
|
||||
pstr=strtok(NULL,":");
|
||||
if (!pstr) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
#ifdef EMAIL_PORT
|
||||
if (*pstr=='*') {
|
||||
port=EMAIL_PORT;
|
||||
} else {
|
||||
port=atoi(pstr);
|
||||
}
|
||||
#else
|
||||
port=atoi(pstr);
|
||||
#endif
|
||||
|
||||
user=strtok(NULL,":");
|
||||
if (!user) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
passwd=strtok(NULL,":");
|
||||
if (!passwd) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
from=strtok(NULL,":");
|
||||
if (!from) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
to=strtok(NULL,":");
|
||||
if (!to) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
subject=strtok(NULL,"]");
|
||||
if (!subject) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
|
||||
#ifdef EMAIL_USER
|
||||
if (*user=='*') {
|
||||
user=xPSTR(EMAIL_USER);
|
||||
}
|
||||
#endif
|
||||
#ifdef EMAIL_PASSWORD
|
||||
if (*passwd=='*') {
|
||||
passwd=xPSTR(EMAIL_PASSWORD);
|
||||
}
|
||||
#endif
|
||||
#ifdef EMAIL_SERVER
|
||||
if (*mserv=='*') {
|
||||
mserv=xPSTR(EMAIL_SERVER);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_EMAIL_PORT
|
||||
AddLog_P2(LOG_LEVEL_INFO, PSTR("%s - %d - %s - %s"),mserv,port,user,passwd);
|
||||
#endif
|
||||
|
||||
#ifdef EMAIL_FROM
|
||||
if (*from=='*') {
|
||||
from=xPSTR(EMAIL_FROM);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_EMAIL_PORT
|
||||
AddLog_P2(LOG_LEVEL_INFO, PSTR("%s - %s - %s - %s"),from,to,subject,cmd);
|
||||
#endif
|
||||
|
||||
smtpData.setDebug(true);
|
||||
|
||||
//Set the Email host, port, account and password
|
||||
smtpData.setLogin(mserv, port, user, passwd);
|
||||
|
||||
//For library version 1.2.0 and later which STARTTLS protocol was supported,the STARTTLS will be
|
||||
//enabled automatically when port 587 was used, or enable it manually using setSTARTTLS function.
|
||||
//smtpData.setSTARTTLS(true);
|
||||
|
||||
//Set the sender name and Email
|
||||
smtpData.setSender("ESP32",from);
|
||||
|
||||
//Set Email priority or importance High, Normal, Low or 1 to 5 (1 is highest)
|
||||
smtpData.setPriority("High");
|
||||
|
||||
//Set the subject
|
||||
smtpData.setSubject(subject);
|
||||
|
||||
#ifdef USE_SCRIPT
|
||||
if (*cmd=='*' && *(cmd+1)==0) {
|
||||
smtpData.clrMessage(true);
|
||||
script_send_email_body(send_message_txt);
|
||||
} else {
|
||||
smtpData.setMessage(cmd, true);
|
||||
}
|
||||
#else
|
||||
//Set the message - normal text or html format
|
||||
smtpData.setMessage(cmd, true);
|
||||
#endif
|
||||
|
||||
|
||||
//Add recipients, can add more than one recipient
|
||||
smtpData.addRecipient(to);
|
||||
|
||||
//Add attachments, can add the file or binary data from flash memory, file in SD card
|
||||
//Data from internal memory
|
||||
//smtpData.addAttachData("firebase_logo.png", "image/png", (uint8_t *)dummyImageData, sizeof dummyImageData);
|
||||
|
||||
//Add attach files from SD card
|
||||
//Comment these two lines, if no SD card connected
|
||||
//Two files that previousely created.
|
||||
//smtpData.addAttachFile("/binary_file.dat");
|
||||
//smtpData.addAttachFile("/text_file.txt");
|
||||
|
||||
|
||||
//Add some custom header to message
|
||||
//See https://tools.ietf.org/html/rfc822
|
||||
//These header fields can be read from raw or source of message when it received)
|
||||
//smtpData.addCustomMessageHeader("Date: Sat, 10 Aug 2019 21:39:56 -0700 (PDT)");
|
||||
//Be careful when set Message-ID, it should be unique, otherwise message will not store
|
||||
//smtpData.addCustomMessageHeader("Message-ID: <abcde.fghij@gmail.com>");
|
||||
|
||||
//Set the storage types to read the attach files (SD is default)
|
||||
//smtpData.setFileStorageType(MailClientStorageType::SPIFFS);
|
||||
#if defined (USE_SCRIPT) && defined(USE_SCRIPT_FATFS)
|
||||
smtpData.setFileStorageType(MailClientStorageType::SD);
|
||||
#endif
|
||||
//smtpData.setSendCallback(sendCallback);
|
||||
|
||||
//Start sending Email, can be set callback function to track the status
|
||||
if (!MailClient.sendMail(smtpData)) {
|
||||
//Serial.println("Error sending Email, " + MailClient.smtpErrorReason());
|
||||
AddLog_P2(LOG_LEVEL_INFO, PSTR("Error sending Email, %s"), MailClient.smtpErrorReason());
|
||||
|
||||
} else {
|
||||
status=0;
|
||||
}
|
||||
//Clear all data from Email object to free memory
|
||||
smtpData.empty();
|
||||
|
||||
exit:
|
||||
if (oparams) free(oparams);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
void send_message_txt(char *txt) {
|
||||
if (*txt=='&') {
|
||||
txt++;
|
||||
smtpData.addAttachFile(txt);
|
||||
} else if (*txt=='$') {
|
||||
txt++;
|
||||
#if defined(ESP32) && defined(USE_WEBCAM)
|
||||
uint32_t cnt;
|
||||
uint8_t *buff;
|
||||
uint32_t len,picmax;
|
||||
picmax=get_picstore(-1,0);
|
||||
cnt=*txt&7;
|
||||
if (cnt<1 || cnt>picmax) cnt=1;
|
||||
len=get_picstore(cnt-1,&buff);
|
||||
if (len) {
|
||||
char str[12];
|
||||
sprintf(str,"img_%1d.jpg",cnt+1);
|
||||
smtpData.addAttachData(str, "image/jpg",buff,len);
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
smtpData.addMessage(txt);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
//Callback function to get the Email sending status
|
||||
void sendCallback(SendStatus msg)
|
||||
{
|
||||
//Print the current status
|
||||
Serial.println(msg.info());
|
||||
|
||||
//Do something when complete
|
||||
if (msg.success())
|
||||
{
|
||||
Serial.println("----------------");
|
||||
}
|
||||
}
|
||||
*/
|
||||
#endif
|
||||
|
||||
|
||||
#endif // USE_SENDMAIL
|
||||
|
@ -358,8 +358,17 @@ struct {
|
||||
SysBitfield3 flag3; // 3A0
|
||||
uint8_t switchmode[MAX_SWITCHES]; // 3A4 (6.0.0b - moved from 0x4CA)
|
||||
|
||||
#ifdef ESP8266
|
||||
char ex_friendlyname[4][33]; // 3AC
|
||||
char ex_switch_topic[33]; // 430
|
||||
#else // ESP32
|
||||
myio my_gp; // 3AC - 2 x 40 bytes (ESP32)
|
||||
mytmplt user_template; // 3FC - 2 x 37 bytes (ESP32)
|
||||
|
||||
uint8_t free_esp32_446[10]; // 446
|
||||
|
||||
uint8_t esp32_webcam_resolution; // 450
|
||||
#endif // ESP8266 - ESP32
|
||||
|
||||
char serial_delimiter; // 451
|
||||
uint8_t seriallog_level; // 452
|
||||
@ -403,14 +412,7 @@ struct {
|
||||
uint32_t ip_address[4]; // 544
|
||||
unsigned long energy_kWhtotal; // 554
|
||||
|
||||
#ifdef ESP8266
|
||||
char ex_mqtt_fulltopic[100]; // 558
|
||||
#else // ESP32
|
||||
myio my_gp; // 558 - 40 bytes (ESP32)
|
||||
mytmplt user_template; // 580 - 37 bytes (ESP32)
|
||||
|
||||
uint8_t free_esp32_5a5[23]; // 5A5
|
||||
#endif // ESP8266 - ESP32
|
||||
|
||||
SysBitfield2 flag2; // 5BC
|
||||
unsigned long pulse_counter[MAX_COUNTERS]; // 5C0
|
||||
|
@ -346,6 +346,7 @@ void SettingsSaveAll(void)
|
||||
|
||||
void UpdateQuickPowerCycle(bool update)
|
||||
{
|
||||
#ifndef FIRMWARE_MINIMAL
|
||||
if (Settings.flag3.fast_power_cycle_disable) { return; } // SetOption65 - Disable fast power cycle detection for device reset
|
||||
|
||||
uint32_t pc_register;
|
||||
@ -353,9 +354,9 @@ void UpdateQuickPowerCycle(bool update)
|
||||
|
||||
#ifdef ESP8266
|
||||
ESP.flashRead(pc_location * SPI_FLASH_SEC_SIZE, (uint32*)&pc_register, sizeof(pc_register));
|
||||
#else
|
||||
#else // ESP32
|
||||
QPCRead(&pc_register, sizeof(pc_register));
|
||||
#endif
|
||||
#endif // ESP8266 - ESP32
|
||||
if (update && ((pc_register & 0xFFFFFFF0) == 0xFFA55AB0)) {
|
||||
uint32_t counter = ((pc_register & 0xF) << 1) & 0xF;
|
||||
if (0 == counter) { // 4 power cycles in a row
|
||||
@ -365,9 +366,9 @@ void UpdateQuickPowerCycle(bool update)
|
||||
pc_register = 0xFFA55AB0 | counter;
|
||||
#ifdef ESP8266
|
||||
ESP.flashWrite(pc_location * SPI_FLASH_SEC_SIZE, (uint32*)&pc_register, sizeof(pc_register));
|
||||
#else
|
||||
#else // ESP32
|
||||
QPCWrite(&pc_register, sizeof(pc_register));
|
||||
#endif
|
||||
#endif // ESP8266 - ESP32
|
||||
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("QPC: Flag %02X"), counter);
|
||||
}
|
||||
}
|
||||
@ -378,11 +379,12 @@ void UpdateQuickPowerCycle(bool update)
|
||||
if (ESP.flashEraseSector(pc_location)) {
|
||||
ESP.flashWrite(pc_location * SPI_FLASH_SEC_SIZE, (uint32*)&pc_register, sizeof(pc_register));
|
||||
}
|
||||
#else
|
||||
#else // ESP32
|
||||
QPCWrite(&pc_register, sizeof(pc_register));
|
||||
#endif
|
||||
#endif // ESP8266 - ESP32
|
||||
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("QPC: Reset"));
|
||||
}
|
||||
#endif // FIRMWARE_MINIMAL
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
@ -405,9 +407,9 @@ bool SettingsUpdateText(uint32_t index, const char* replace_me)
|
||||
}
|
||||
|
||||
// Make a copy first in case we use source from Settings.text
|
||||
uint32_t replace_len = strlen(replace_me);
|
||||
uint32_t replace_len = strlen_P(replace_me);
|
||||
char replace[replace_len +1];
|
||||
memcpy(replace, replace_me, sizeof(replace));
|
||||
memcpy_P(replace, replace_me, sizeof(replace));
|
||||
|
||||
uint32_t start_pos = 0;
|
||||
uint32_t end_pos = 0;
|
||||
@ -742,11 +744,11 @@ void SettingsDefaultSet2(void)
|
||||
Settings.module = MODULE;
|
||||
ModuleDefault(WEMOS);
|
||||
// for (uint32_t i = 0; i < ARRAY_SIZE(Settings.my_gp.io); i++) { Settings.my_gp.io[i] = GPIO_NONE; }
|
||||
SettingsUpdateText(SET_FRIENDLYNAME1, FRIENDLY_NAME);
|
||||
SettingsUpdateText(SET_FRIENDLYNAME2, FRIENDLY_NAME"2");
|
||||
SettingsUpdateText(SET_FRIENDLYNAME3, FRIENDLY_NAME"3");
|
||||
SettingsUpdateText(SET_FRIENDLYNAME4, FRIENDLY_NAME"4");
|
||||
SettingsUpdateText(SET_OTAURL, OTA_URL);
|
||||
SettingsUpdateText(SET_FRIENDLYNAME1, PSTR(FRIENDLY_NAME));
|
||||
SettingsUpdateText(SET_FRIENDLYNAME2, PSTR(FRIENDLY_NAME"2"));
|
||||
SettingsUpdateText(SET_FRIENDLYNAME3, PSTR(FRIENDLY_NAME"3"));
|
||||
SettingsUpdateText(SET_FRIENDLYNAME4, PSTR(FRIENDLY_NAME"4"));
|
||||
SettingsUpdateText(SET_OTAURL, PSTR(OTA_URL));
|
||||
|
||||
// Power
|
||||
Settings.flag.save_state = SAVE_STATE;
|
||||
@ -777,14 +779,14 @@ void SettingsDefaultSet2(void)
|
||||
ParseIp(&Settings.ip_address[3], WIFI_DNS);
|
||||
Settings.sta_config = WIFI_CONFIG_TOOL;
|
||||
// Settings.sta_active = 0;
|
||||
SettingsUpdateText(SET_STASSID1, STA_SSID1);
|
||||
SettingsUpdateText(SET_STASSID2, STA_SSID2);
|
||||
SettingsUpdateText(SET_STAPWD1, STA_PASS1);
|
||||
SettingsUpdateText(SET_STAPWD2, STA_PASS2);
|
||||
SettingsUpdateText(SET_STASSID1, PSTR(STA_SSID1));
|
||||
SettingsUpdateText(SET_STASSID2, PSTR(STA_SSID2));
|
||||
SettingsUpdateText(SET_STAPWD1, PSTR(STA_PASS1));
|
||||
SettingsUpdateText(SET_STAPWD2, PSTR(STA_PASS2));
|
||||
SettingsUpdateText(SET_HOSTNAME, WIFI_HOSTNAME);
|
||||
|
||||
// Syslog
|
||||
SettingsUpdateText(SET_SYSLOG_HOST, SYS_LOG_HOST);
|
||||
SettingsUpdateText(SET_SYSLOG_HOST, PSTR(SYS_LOG_HOST));
|
||||
Settings.syslog_port = SYS_LOG_PORT;
|
||||
Settings.syslog_level = SYS_LOG_LEVEL;
|
||||
|
||||
@ -794,8 +796,8 @@ void SettingsDefaultSet2(void)
|
||||
Settings.flag3.mdns_enabled = MDNS_ENABLED;
|
||||
Settings.webserver = WEB_SERVER;
|
||||
Settings.weblog_level = WEB_LOG_LEVEL;
|
||||
SettingsUpdateText(SET_WEBPWD, WEB_PASSWORD);
|
||||
SettingsUpdateText(SET_CORS, CORS_DOMAIN);
|
||||
SettingsUpdateText(SET_WEBPWD, PSTR(WEB_PASSWORD));
|
||||
SettingsUpdateText(SET_CORS, PSTR(CORS_DOMAIN));
|
||||
|
||||
// Button
|
||||
Settings.flag.button_restrict = KEY_DISABLE_MULTIPRESS;
|
||||
@ -839,13 +841,13 @@ void SettingsDefaultSet2(void)
|
||||
SettingsUpdateText(SET_STATE_TXT2, MQTT_STATUS_ON);
|
||||
SettingsUpdateText(SET_STATE_TXT3, MQTT_CMND_TOGGLE);
|
||||
SettingsUpdateText(SET_STATE_TXT4, MQTT_CMND_HOLD);
|
||||
char fingerprint[60];
|
||||
strlcpy(fingerprint, MQTT_FINGERPRINT1, sizeof(fingerprint));
|
||||
char fingerprint[64];
|
||||
strncpy_P(fingerprint, PSTR(MQTT_FINGERPRINT1), sizeof(fingerprint));
|
||||
char *p = fingerprint;
|
||||
for (uint32_t i = 0; i < 20; i++) {
|
||||
Settings.mqtt_fingerprint[0][i] = strtol(p, &p, 16);
|
||||
}
|
||||
strlcpy(fingerprint, MQTT_FINGERPRINT2, sizeof(fingerprint));
|
||||
strncpy_P(fingerprint, PSTR(MQTT_FINGERPRINT2), sizeof(fingerprint));
|
||||
p = fingerprint;
|
||||
for (uint32_t i = 0; i < 20; i++) {
|
||||
Settings.mqtt_fingerprint[1][i] = strtol(p, &p, 16);
|
||||
@ -1008,9 +1010,9 @@ void SettingsDefaultSet2(void)
|
||||
Settings.timezone = APP_TIMEZONE / 60;
|
||||
Settings.timezone_minutes = abs(APP_TIMEZONE % 60);
|
||||
}
|
||||
SettingsUpdateText(SET_NTPSERVER1, NTP_SERVER1);
|
||||
SettingsUpdateText(SET_NTPSERVER2, NTP_SERVER2);
|
||||
SettingsUpdateText(SET_NTPSERVER3, NTP_SERVER3);
|
||||
SettingsUpdateText(SET_NTPSERVER1, PSTR(NTP_SERVER1));
|
||||
SettingsUpdateText(SET_NTPSERVER2, PSTR(NTP_SERVER2));
|
||||
SettingsUpdateText(SET_NTPSERVER3, PSTR(NTP_SERVER3));
|
||||
for (uint32_t i = 0; i < MAX_NTP_SERVERS; i++) {
|
||||
SettingsUpdateText(SET_NTPSERVER1 +i, ReplaceCommaWithDot(SettingsText(SET_NTPSERVER1 +i)));
|
||||
}
|
||||
@ -1386,6 +1388,13 @@ void SettingsDelta(void)
|
||||
#endif // ESP32
|
||||
}
|
||||
|
||||
if (Settings.version < 0x08020006) {
|
||||
#ifdef ESP32
|
||||
Settings.module = WEMOS;
|
||||
ModuleDefault(WEMOS);
|
||||
#endif // ESP32
|
||||
}
|
||||
|
||||
Settings.version = VERSION;
|
||||
SettingsSave(1);
|
||||
}
|
||||
|
@ -1079,21 +1079,17 @@ uint32_t Pin(uint32_t gpio, uint32_t index) ICACHE_RAM_ATTR;
|
||||
|
||||
uint32_t Pin(uint32_t gpio, uint32_t index = 0);
|
||||
uint32_t Pin(uint32_t gpio, uint32_t index) {
|
||||
#ifdef LEGACY_GPIO_ARRAY
|
||||
return pin[gpio + index]; // Pin number configured for gpio or 99 if not used
|
||||
#else
|
||||
//#ifdef ESP8266
|
||||
#ifdef ESP8266
|
||||
uint16_t real_gpio = gpio + index;
|
||||
//#else
|
||||
// uint16_t real_gpio = (gpio << 5) + index;
|
||||
//endif
|
||||
for (uint32_t i = 0; i < ARRAY_SIZE(pin); i++) {
|
||||
if (pin[i] == real_gpio) {
|
||||
#else // ESP32
|
||||
uint16_t real_gpio = (gpio << 5) + index;
|
||||
#endif // ESP8266 - ESP32
|
||||
for (uint32_t i = 0; i < ARRAY_SIZE(gpio_pin); i++) {
|
||||
if (gpio_pin[i] == real_gpio) {
|
||||
return i; // Pin number configured for gpio
|
||||
}
|
||||
}
|
||||
return 99; // No pin used for gpio
|
||||
#endif
|
||||
}
|
||||
|
||||
boolean PinUsed(uint32_t gpio, uint32_t index = 0);
|
||||
@ -1102,21 +1098,9 @@ boolean PinUsed(uint32_t gpio, uint32_t index) {
|
||||
}
|
||||
|
||||
void SetPin(uint32_t lpin, uint32_t gpio) {
|
||||
#ifdef LEGACY_GPIO_ARRAY
|
||||
pin[gpio] = lpin;
|
||||
#else
|
||||
pin[lpin] = gpio;
|
||||
#endif
|
||||
gpio_pin[lpin] = gpio;
|
||||
}
|
||||
|
||||
#ifdef LEGACY_GPIO_ARRAY
|
||||
void InitAllPins(void) {
|
||||
for (uint32_t i = 0; i < ARRAY_SIZE(pin); i++) {
|
||||
SetPin(99, i);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void DigitalWrite(uint32_t gpio_pin, uint32_t index, uint32_t state)
|
||||
{
|
||||
if (PinUsed(gpio_pin, index)) {
|
||||
@ -1164,13 +1148,13 @@ String ModuleName(void)
|
||||
|
||||
void ModuleGpios(myio *gp)
|
||||
{
|
||||
//#ifdef ESP8266
|
||||
#ifdef ESP8266
|
||||
uint8_t *dest = (uint8_t *)gp;
|
||||
uint8_t src[ARRAY_SIZE(Settings.user_template.gp.io)];
|
||||
//#else
|
||||
// uint16_t *dest = (uint16_t *)gp;
|
||||
// uint16_t src[ARRAY_SIZE(Settings.user_template.gp.io)];
|
||||
//#endif
|
||||
#else // ESP32
|
||||
uint16_t *dest = (uint16_t *)gp;
|
||||
uint16_t src[ARRAY_SIZE(Settings.user_template.gp.io)];
|
||||
#endif // ESP8266 - ESP32
|
||||
|
||||
memset(dest, GPIO_NONE, sizeof(myio));
|
||||
if (USER_MODULE == Settings.module) {
|
||||
@ -1202,24 +1186,15 @@ gpio_flag ModuleFlag(void)
|
||||
{
|
||||
gpio_flag flag;
|
||||
|
||||
#ifdef ESP8266
|
||||
if (USER_MODULE == Settings.module) {
|
||||
flag = Settings.user_template.flag;
|
||||
} else {
|
||||
#ifdef ESP8266
|
||||
memcpy_P(&flag, &kModules[Settings.module].flag, sizeof(gpio_flag));
|
||||
}
|
||||
#else // ESP32
|
||||
if (USER_MODULE == Settings.module) {
|
||||
/*
|
||||
gpio_flag gpio_adc0;
|
||||
memcpy_P(&gpio_adc0, &Settings.user_template.gp + ADC0_PIN - MIN_FLASH_PINS, sizeof(gpio_flag));
|
||||
flag = Settings.user_template.flag.data + gpio_adc0.data;
|
||||
*/
|
||||
memcpy_P(&flag, &Settings.user_template.gp + ADC0_PIN - MIN_FLASH_PINS, sizeof(gpio_flag));
|
||||
} else {
|
||||
memcpy_P(&flag, &kModules.gp + ADC0_PIN - MIN_FLASH_PINS, sizeof(gpio_flag));
|
||||
}
|
||||
memcpy_P(&flag, &kModules.flag, sizeof(gpio_flag));
|
||||
#endif // ESP8266 - ESP32
|
||||
}
|
||||
|
||||
return flag;
|
||||
}
|
||||
@ -1247,7 +1222,7 @@ bool FlashPin(uint32_t pin)
|
||||
return (((pin > 5) && (pin < 9)) || (11 == pin));
|
||||
}
|
||||
|
||||
uint8_t ValidPin(uint32_t pin, uint32_t gpio)
|
||||
uint32_t ValidPin(uint32_t pin, uint32_t gpio)
|
||||
{
|
||||
if (FlashPin(pin)) {
|
||||
return GPIO_NONE; // Disable flash pins GPIO6, GPIO7, GPIO8 and GPIO11
|
||||
@ -1265,21 +1240,27 @@ uint8_t ValidPin(uint32_t pin, uint32_t gpio)
|
||||
|
||||
bool ValidGPIO(uint32_t pin, uint32_t gpio)
|
||||
{
|
||||
#ifdef ESP8266
|
||||
return (GPIO_USER == ValidPin(pin, gpio)); // Only allow GPIO_USER pins
|
||||
#else // ESP32
|
||||
return (GPIO_USER == ValidPin(pin, gpio >> 5)); // Only allow GPIO_USER pins
|
||||
#endif // ESP8266 - ESP32
|
||||
}
|
||||
|
||||
#ifdef ESP8266
|
||||
bool ValidAdc(void)
|
||||
{
|
||||
gpio_flag flag = ModuleFlag();
|
||||
uint32_t template_adc0 = flag.data &15;
|
||||
return (ADC0_USER == template_adc0);
|
||||
}
|
||||
#endif // ESP8266
|
||||
|
||||
//#ifdef ESP8266
|
||||
#ifdef ESP8266
|
||||
bool GetUsedInModule(uint32_t val, uint8_t *arr)
|
||||
//#else
|
||||
//bool GetUsedInModule(uint32_t val, uint16_t *arr)
|
||||
//#endif
|
||||
#else // ESP32
|
||||
bool GetUsedInModule(uint32_t val, uint16_t *arr)
|
||||
#endif // ESP8266 - ESP32
|
||||
{
|
||||
int offset = 0;
|
||||
|
||||
@ -1349,7 +1330,7 @@ bool JsonTemplate(const char* dataBuf)
|
||||
#ifdef ESP8266
|
||||
StaticJsonBuffer<400> jb; // 331 from https://arduinojson.org/v5/assistant/
|
||||
#else
|
||||
StaticJsonBuffer<800> jb; // 654 from https://arduinojson.org/v5/assistant/
|
||||
StaticJsonBuffer<999> jb; // 654 from https://arduinojson.org/v5/assistant/
|
||||
#endif
|
||||
JsonObject& obj = jb.parseObject(dataBuf);
|
||||
if (!obj.success()) { return false; }
|
||||
@ -1365,11 +1346,11 @@ bool JsonTemplate(const char* dataBuf)
|
||||
}
|
||||
}
|
||||
if (obj[D_JSON_FLAG].success()) {
|
||||
uint8_t flag = obj[D_JSON_FLAG] | 0;
|
||||
uint32_t flag = obj[D_JSON_FLAG] | 0;
|
||||
memcpy(&Settings.user_template.flag, &flag, sizeof(gpio_flag));
|
||||
}
|
||||
if (obj[D_JSON_BASE].success()) {
|
||||
uint8_t base = obj[D_JSON_BASE];
|
||||
uint32_t base = obj[D_JSON_BASE];
|
||||
if ((0 == base) || !ValidTemplateModule(base -1)) { base = 18; }
|
||||
Settings.user_template_base = base -1; // Default WEMOS
|
||||
}
|
||||
@ -1868,3 +1849,16 @@ void AddLogMissed(const char *sensor, uint32_t misses)
|
||||
{
|
||||
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SNS: %s missed %d"), sensor, SENSOR_MAX_MISS - misses);
|
||||
}
|
||||
|
||||
void AddLogBufferSize(uint32_t loglevel, uint8_t *buffer, uint32_t count, uint32_t size) {
|
||||
snprintf_P(log_data, sizeof(log_data), PSTR("DMP:"));
|
||||
for (uint32_t i = 0; i < count; i++) {
|
||||
if (1 == size) { // uint8_t
|
||||
snprintf_P(log_data, sizeof(log_data), PSTR("%s %02X"), log_data, *(buffer));
|
||||
} else { // uint16_t
|
||||
snprintf_P(log_data, sizeof(log_data), PSTR("%s %02X%02X"), log_data, *(buffer +1), *(buffer));
|
||||
}
|
||||
buffer += size;
|
||||
}
|
||||
AddLog(loglevel);
|
||||
}
|
||||
|
@ -659,7 +659,7 @@ void CmndUpgrade(void)
|
||||
void CmndOtaUrl(void)
|
||||
{
|
||||
if (XdrvMailbox.data_len > 0) {
|
||||
SettingsUpdateText(SET_OTAURL, (SC_DEFAULT == Shortcut()) ? OTA_URL : XdrvMailbox.data);
|
||||
SettingsUpdateText(SET_OTAURL, (SC_DEFAULT == Shortcut()) ? PSTR(OTA_URL) : XdrvMailbox.data);
|
||||
}
|
||||
ResponseCmndChar(SettingsText(SET_OTAURL));
|
||||
}
|
||||
@ -1045,11 +1045,22 @@ void CmndGpio(void)
|
||||
if (XdrvMailbox.index < ARRAY_SIZE(Settings.my_gp.io)) {
|
||||
myio cmodule;
|
||||
ModuleGpios(&cmodule);
|
||||
if (ValidGPIO(XdrvMailbox.index, cmodule.io[XdrvMailbox.index]) && (XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < GPIO_SENSOR_END)) {
|
||||
if (ValidGPIO(XdrvMailbox.index, cmodule.io[XdrvMailbox.index]) && (XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < AGPIO(GPIO_SENSOR_END))) {
|
||||
bool present = false;
|
||||
for (uint32_t i = 0; i < sizeof(kGpioNiceList); i++) {
|
||||
for (uint32_t i = 0; i < ARRAY_SIZE(kGpioNiceList); i++) {
|
||||
#ifdef ESP8266
|
||||
uint32_t midx = pgm_read_byte(kGpioNiceList + i);
|
||||
if (midx == XdrvMailbox.payload) { present = true; }
|
||||
if (midx == XdrvMailbox.payload) {
|
||||
present = true;
|
||||
break;
|
||||
}
|
||||
#else // ESP32
|
||||
uint32_t midx = pgm_read_word(kGpioNiceList + i);
|
||||
if ((XdrvMailbox.payload >= (midx & 0xFFE0)) && (XdrvMailbox.payload < midx)) {
|
||||
present = true;
|
||||
break;
|
||||
}
|
||||
#endif // ESP8266 - ESP32
|
||||
}
|
||||
if (present) {
|
||||
for (uint32_t i = 0; i < ARRAY_SIZE(Settings.my_gp.io); i++) {
|
||||
@ -1064,25 +1075,38 @@ void CmndGpio(void)
|
||||
Response_P(PSTR("{"));
|
||||
bool jsflg = false;
|
||||
for (uint32_t i = 0; i < ARRAY_SIZE(Settings.my_gp.io); i++) {
|
||||
if (ValidGPIO(i, cmodule.io[i]) || ((GPIO_USER == XdrvMailbox.payload) && !FlashPin(i))) {
|
||||
if (ValidGPIO(i, cmodule.io[i]) || ((AGPIO(GPIO_USER) == XdrvMailbox.payload) && !FlashPin(i))) {
|
||||
if (jsflg) { ResponseAppend_P(PSTR(",")); }
|
||||
jsflg = true;
|
||||
uint8_t sensor_type = Settings.my_gp.io[i];
|
||||
uint32_t sensor_type = Settings.my_gp.io[i];
|
||||
if (!ValidGPIO(i, cmodule.io[i])) {
|
||||
sensor_type = cmodule.io[i];
|
||||
if (GPIO_USER == sensor_type) { // A user GPIO equals a not connected (=GPIO_NONE) GPIO here
|
||||
if (AGPIO(GPIO_USER) == sensor_type) { // A user GPIO equals a not connected (=GPIO_NONE) GPIO here
|
||||
sensor_type = GPIO_NONE;
|
||||
}
|
||||
}
|
||||
uint8_t sensor_name_idx = sensor_type;
|
||||
char sindex[4] = { 0 };
|
||||
#ifdef ESP8266
|
||||
uint32_t sensor_name_idx = sensor_type;
|
||||
#else // ESP32
|
||||
uint32_t sensor_name_idx = sensor_type >> 5;
|
||||
uint32_t nice_list_search = sensor_type & 0xFFE0;
|
||||
for (uint32_t j = 0; j < ARRAY_SIZE(kGpioNiceList); j++) {
|
||||
uint32_t nls_idx = pgm_read_word(kGpioNiceList + j);
|
||||
if (((nls_idx & 0xFFE0) == nice_list_search) && ((nls_idx & 0x001F) > 0)) {
|
||||
snprintf_P(sindex, sizeof(sindex), PSTR("%d"), (sensor_type & 0x001F) +1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif // ESP8266 - ESP32
|
||||
const char *sensor_names = kSensorNames;
|
||||
if (sensor_type > GPIO_FIX_START) {
|
||||
sensor_name_idx = sensor_type - GPIO_FIX_START -1;
|
||||
if (sensor_name_idx > GPIO_FIX_START) {
|
||||
sensor_name_idx = sensor_name_idx - GPIO_FIX_START -1;
|
||||
sensor_names = kSensorNamesFixed;
|
||||
}
|
||||
char stemp1[TOPSZ];
|
||||
ResponseAppend_P(PSTR("\"" D_CMND_GPIO "%d\":{\"%d\":\"%s\"}"),
|
||||
i, sensor_type, GetTextIndexed(stemp1, sizeof(stemp1), sensor_name_idx, sensor_names));
|
||||
ResponseAppend_P(PSTR("\"" D_CMND_GPIO "%d\":{\"%d\":\"%s%s\"}"),
|
||||
i, sensor_type, GetTextIndexed(stemp1, sizeof(stemp1), sensor_name_idx, sensor_names), sindex);
|
||||
}
|
||||
}
|
||||
if (jsflg) {
|
||||
@ -1099,8 +1123,14 @@ void CmndGpios(void)
|
||||
ModuleGpios(&cmodule);
|
||||
uint32_t lines = 1;
|
||||
bool jsflg = false;
|
||||
for (uint32_t i = 0; i < sizeof(kGpioNiceList); i++) {
|
||||
for (uint32_t i = 0; i < ARRAY_SIZE(kGpioNiceList); i++) {
|
||||
#ifdef ESP8266
|
||||
uint32_t midx = pgm_read_byte(kGpioNiceList + i);
|
||||
uint32_t ridx = midx;
|
||||
#else // ESP32
|
||||
uint32_t ridx = pgm_read_word(kGpioNiceList + i) & 0xFFE0;
|
||||
uint32_t midx = ridx >> 5;
|
||||
#endif // ESP8266 - ESP32
|
||||
if ((XdrvMailbox.payload != 255) && GetUsedInModule(midx, cmodule.io)) { continue; }
|
||||
if (!jsflg) {
|
||||
Response_P(PSTR("{\"" D_CMND_GPIOS "%d\":{"), lines);
|
||||
@ -1109,7 +1139,7 @@ void CmndGpios(void)
|
||||
}
|
||||
jsflg = true;
|
||||
char stemp1[TOPSZ];
|
||||
if ((ResponseAppend_P(PSTR("\"%d\":\"%s\""), midx, GetTextIndexed(stemp1, sizeof(stemp1), midx, kSensorNames)) > (LOGSZ - TOPSZ)) || (i == sizeof(kGpioNiceList) -1)) {
|
||||
if ((ResponseAppend_P(PSTR("\"%d\":\"%s\""), ridx, GetTextIndexed(stemp1, sizeof(stemp1), midx, kSensorNames)) > (LOGSZ - TOPSZ)) || (i == ARRAY_SIZE(kGpioNiceList) -1)) {
|
||||
ResponseJsonEndEnd();
|
||||
MqttPublishPrefixTopic_P(RESULT_OR_STAT, UpperCase(XdrvMailbox.command, XdrvMailbox.command));
|
||||
jsflg = false;
|
||||
@ -1181,7 +1211,11 @@ void CmndPwmfrequency(void)
|
||||
{
|
||||
if ((1 == XdrvMailbox.payload) || ((XdrvMailbox.payload >= PWM_MIN) && (XdrvMailbox.payload <= PWM_MAX))) {
|
||||
Settings.pwm_frequency = (1 == XdrvMailbox.payload) ? PWM_FREQ : XdrvMailbox.payload;
|
||||
#ifdef ESP8266
|
||||
analogWriteFreq(Settings.pwm_frequency); // Default is 1000 (core_esp8266_wiring_pwm.c)
|
||||
#else
|
||||
analogWriteFreqRange(0,Settings.pwm_frequency,Settings.pwm_range);
|
||||
#endif
|
||||
}
|
||||
ResponseCmndNumber(Settings.pwm_frequency);
|
||||
}
|
||||
@ -1195,7 +1229,11 @@ void CmndPwmrange(void)
|
||||
Settings.pwm_value[i] = Settings.pwm_range;
|
||||
}
|
||||
}
|
||||
#ifdef ESP8266
|
||||
analogWriteRange(Settings.pwm_range); // Default is 1023 (Arduino.h)
|
||||
#else
|
||||
analogWriteFreqRange(0,Settings.pwm_frequency,Settings.pwm_range);
|
||||
#endif
|
||||
}
|
||||
ResponseCmndNumber(Settings.pwm_range);
|
||||
}
|
||||
@ -1356,7 +1394,7 @@ void CmndNtpServer(void)
|
||||
uint32_t ntp_server = SET_NTPSERVER1 + XdrvMailbox.index -1;
|
||||
if (XdrvMailbox.data_len > 0) {
|
||||
SettingsUpdateText(ntp_server,
|
||||
(SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? (1 == XdrvMailbox.index) ? NTP_SERVER1 : (2 == XdrvMailbox.index) ? NTP_SERVER2 : NTP_SERVER3 : XdrvMailbox.data);
|
||||
(SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? (1 == XdrvMailbox.index) ? PSTR(NTP_SERVER1) : (2 == XdrvMailbox.index) ? PSTR(NTP_SERVER2) : PSTR(NTP_SERVER3) : XdrvMailbox.data);
|
||||
SettingsUpdateText(ntp_server, ReplaceCommaWithDot(SettingsText(ntp_server)));
|
||||
// restart_flag = 2; // Issue #3890
|
||||
ntp_force_sync = true;
|
||||
@ -1564,7 +1602,7 @@ void CmndReset(void)
|
||||
switch (XdrvMailbox.payload) {
|
||||
case 1:
|
||||
restart_flag = 211;
|
||||
ResponseCmndChar(D_JSON_RESET_AND_RESTARTING);
|
||||
ResponseCmndChar(PSTR(D_JSON_RESET_AND_RESTARTING));
|
||||
break;
|
||||
case 2 ... 6:
|
||||
restart_flag = 210 + XdrvMailbox.payload;
|
||||
@ -1576,7 +1614,7 @@ void CmndReset(void)
|
||||
ResponseCmndDone();
|
||||
break;
|
||||
default:
|
||||
ResponseCmndChar(D_JSON_ONE_TO_RESET);
|
||||
ResponseCmndChar(PSTR(D_JSON_ONE_TO_RESET));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1353,24 +1353,25 @@ void GpioInit(void)
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < ARRAY_SIZE(Settings.user_template.gp.io); i++) {
|
||||
if ((Settings.user_template.gp.io[i] >= GPIO_SENSOR_END) && (Settings.user_template.gp.io[i] < GPIO_USER)) {
|
||||
Settings.user_template.gp.io[i] = GPIO_USER; // Fix not supported sensor ids in template
|
||||
if ((Settings.user_template.gp.io[i] >= AGPIO(GPIO_SENSOR_END)) && (Settings.user_template.gp.io[i] < AGPIO(GPIO_USER))) {
|
||||
Settings.user_template.gp.io[i] = AGPIO(GPIO_USER); // Fix not supported sensor ids in template
|
||||
}
|
||||
}
|
||||
|
||||
myio def_gp;
|
||||
ModuleGpios(&def_gp);
|
||||
for (uint32_t i = 0; i < ARRAY_SIZE(Settings.my_gp.io); i++) {
|
||||
if ((Settings.my_gp.io[i] >= GPIO_SENSOR_END) && (Settings.my_gp.io[i] < GPIO_USER)) {
|
||||
if ((Settings.my_gp.io[i] >= AGPIO(GPIO_SENSOR_END)) && (Settings.my_gp.io[i] < AGPIO(GPIO_USER))) {
|
||||
Settings.my_gp.io[i] = GPIO_NONE; // Fix not supported sensor ids in module
|
||||
}
|
||||
else if (Settings.my_gp.io[i] > GPIO_NONE) {
|
||||
my_module.io[i] = Settings.my_gp.io[i]; // Set User selected Module sensors
|
||||
}
|
||||
if ((def_gp.io[i] > GPIO_NONE) && (def_gp.io[i] < GPIO_USER)) {
|
||||
if ((def_gp.io[i] > GPIO_NONE) && (def_gp.io[i] < AGPIO(GPIO_USER))) {
|
||||
my_module.io[i] = def_gp.io[i]; // Force Template override
|
||||
}
|
||||
}
|
||||
#ifdef ESP8266
|
||||
if ((Settings.my_adc0 >= ADC0_END) && (Settings.my_adc0 < ADC0_USER)) {
|
||||
Settings.my_adc0 = ADC0_NONE; // Fix not supported sensor ids in module
|
||||
}
|
||||
@ -1382,10 +1383,8 @@ void GpioInit(void)
|
||||
if ((template_adc0 > ADC0_NONE) && (template_adc0 < ADC0_USER)) {
|
||||
my_adc0 = template_adc0; // Force Template override
|
||||
}
|
||||
|
||||
#ifdef LEGACY_GPIO_ARRAY
|
||||
InitAllPins();
|
||||
#endif
|
||||
|
||||
for (uint32_t i = 0; i < ARRAY_SIZE(my_module.io); i++) {
|
||||
uint32_t mpin = ValidPin(i, my_module.io[i]);
|
||||
|
||||
@ -1395,38 +1394,38 @@ void GpioInit(void)
|
||||
XdrvMailbox.index = mpin;
|
||||
XdrvMailbox.payload = i;
|
||||
|
||||
if ((mpin >= GPIO_SWT1_NP) && (mpin < (GPIO_SWT1_NP + MAX_SWITCHES))) {
|
||||
SwitchPullupFlag(mpin - GPIO_SWT1_NP);
|
||||
mpin -= (GPIO_SWT1_NP - GPIO_SWT1);
|
||||
if ((mpin >= AGPIO(GPIO_SWT1_NP)) && (mpin < (AGPIO(GPIO_SWT1_NP) + MAX_SWITCHES))) {
|
||||
SwitchPullupFlag(mpin - AGPIO(GPIO_SWT1_NP));
|
||||
mpin -= (AGPIO(GPIO_SWT1_NP) - AGPIO(GPIO_SWT1));
|
||||
}
|
||||
else if ((mpin >= GPIO_KEY1_NP) && (mpin < (GPIO_KEY1_NP + MAX_KEYS))) {
|
||||
ButtonPullupFlag(mpin - GPIO_KEY1_NP); // 0 .. 3
|
||||
mpin -= (GPIO_KEY1_NP - GPIO_KEY1);
|
||||
else if ((mpin >= AGPIO(GPIO_KEY1_NP)) && (mpin < (AGPIO(GPIO_KEY1_NP) + MAX_KEYS))) {
|
||||
ButtonPullupFlag(mpin - AGPIO(GPIO_KEY1_NP)); // 0 .. 3
|
||||
mpin -= (AGPIO(GPIO_KEY1_NP) - AGPIO(GPIO_KEY1));
|
||||
}
|
||||
else if ((mpin >= GPIO_KEY1_INV) && (mpin < (GPIO_KEY1_INV + MAX_KEYS))) {
|
||||
ButtonInvertFlag(mpin - GPIO_KEY1_INV); // 0 .. 3
|
||||
mpin -= (GPIO_KEY1_INV - GPIO_KEY1);
|
||||
else if ((mpin >= AGPIO(GPIO_KEY1_INV)) && (mpin < (AGPIO(GPIO_KEY1_INV) + MAX_KEYS))) {
|
||||
ButtonInvertFlag(mpin - AGPIO(GPIO_KEY1_INV)); // 0 .. 3
|
||||
mpin -= (AGPIO(GPIO_KEY1_INV) - AGPIO(GPIO_KEY1));
|
||||
}
|
||||
else if ((mpin >= GPIO_KEY1_INV_NP) && (mpin < (GPIO_KEY1_INV_NP + MAX_KEYS))) {
|
||||
ButtonPullupFlag(mpin - GPIO_KEY1_INV_NP); // 0 .. 3
|
||||
ButtonInvertFlag(mpin - GPIO_KEY1_INV_NP); // 0 .. 3
|
||||
mpin -= (GPIO_KEY1_INV_NP - GPIO_KEY1);
|
||||
else if ((mpin >= AGPIO(GPIO_KEY1_INV_NP)) && (mpin < (AGPIO(GPIO_KEY1_INV_NP) + MAX_KEYS))) {
|
||||
ButtonPullupFlag(mpin - AGPIO(GPIO_KEY1_INV_NP)); // 0 .. 3
|
||||
ButtonInvertFlag(mpin - AGPIO(GPIO_KEY1_INV_NP)); // 0 .. 3
|
||||
mpin -= (AGPIO(GPIO_KEY1_INV_NP) - AGPIO(GPIO_KEY1));
|
||||
}
|
||||
else if ((mpin >= GPIO_REL1_INV) && (mpin < (GPIO_REL1_INV + MAX_RELAYS))) {
|
||||
bitSet(rel_inverted, mpin - GPIO_REL1_INV);
|
||||
mpin -= (GPIO_REL1_INV - GPIO_REL1);
|
||||
else if ((mpin >= AGPIO(GPIO_REL1_INV)) && (mpin < (AGPIO(GPIO_REL1_INV) + MAX_RELAYS))) {
|
||||
bitSet(rel_inverted, mpin - AGPIO(GPIO_REL1_INV));
|
||||
mpin -= (AGPIO(GPIO_REL1_INV) - AGPIO(GPIO_REL1));
|
||||
}
|
||||
else if ((mpin >= GPIO_LED1_INV) && (mpin < (GPIO_LED1_INV + MAX_LEDS))) {
|
||||
bitSet(led_inverted, mpin - GPIO_LED1_INV);
|
||||
mpin -= (GPIO_LED1_INV - GPIO_LED1);
|
||||
else if ((mpin >= AGPIO(GPIO_LED1_INV)) && (mpin < (AGPIO(GPIO_LED1_INV) + MAX_LEDS))) {
|
||||
bitSet(led_inverted, mpin - AGPIO(GPIO_LED1_INV));
|
||||
mpin -= (AGPIO(GPIO_LED1_INV) - AGPIO(GPIO_LED1));
|
||||
}
|
||||
else if (mpin == GPIO_LEDLNK_INV) {
|
||||
else if (mpin == AGPIO(GPIO_LEDLNK_INV)) {
|
||||
ledlnk_inverted = 1;
|
||||
mpin -= (GPIO_LEDLNK_INV - GPIO_LEDLNK);
|
||||
mpin -= (AGPIO(GPIO_LEDLNK_INV) - AGPIO(GPIO_LEDLNK));
|
||||
}
|
||||
else if ((mpin >= GPIO_PWM1_INV) && (mpin < (GPIO_PWM1_INV + MAX_PWMS))) {
|
||||
bitSet(pwm_inverted, mpin - GPIO_PWM1_INV);
|
||||
mpin -= (GPIO_PWM1_INV - GPIO_PWM1);
|
||||
else if ((mpin >= AGPIO(GPIO_PWM1_INV)) && (mpin < (AGPIO(GPIO_PWM1_INV) + MAX_PWMS))) {
|
||||
bitSet(pwm_inverted, mpin - AGPIO(GPIO_PWM1_INV));
|
||||
mpin -= (AGPIO(GPIO_PWM1_INV) - AGPIO(GPIO_PWM1));
|
||||
}
|
||||
else if (XdrvCall(FUNC_PIN_STATE)) {
|
||||
mpin = XdrvMailbox.index;
|
||||
@ -1438,13 +1437,10 @@ void GpioInit(void)
|
||||
if (mpin) { SetPin(i, mpin); } // Anything above GPIO_NONE and below GPIO_SENSOR_END
|
||||
}
|
||||
|
||||
#ifndef LEGACY_GPIO_ARRAY
|
||||
AddLogBuffer(LOG_LEVEL_DEBUG, (uint8_t*)pin, ARRAY_SIZE(pin));
|
||||
#endif
|
||||
// AddLogBufferSize(LOG_LEVEL_DEBUG, (uint8_t*)gpio_pin, ARRAY_SIZE(gpio_pin), sizeof(gpio_pin[0]));
|
||||
|
||||
#ifdef ESP8266
|
||||
if ((2 == Pin(GPIO_TXD)) || (H801 == my_module_type)) { Serial.set_tx(2); }
|
||||
#endif // ESP8266
|
||||
|
||||
analogWriteRange(Settings.pwm_range); // Default is 1023 (Arduino.h)
|
||||
analogWriteFreq(Settings.pwm_frequency); // Default is 1000 (core_esp8266_wiring_pwm.c)
|
||||
@ -1452,11 +1448,6 @@ void GpioInit(void)
|
||||
#ifdef USE_SPI
|
||||
spi_flg = (((PinUsed(GPIO_SPI_CS) && (Pin(GPIO_SPI_CS) > 14)) || (Pin(GPIO_SPI_CS) < 12)) || ((PinUsed(GPIO_SPI_DC) && (Pin(GPIO_SPI_DC) > 14)) || (Pin(GPIO_SPI_DC) < 12)));
|
||||
if (spi_flg) {
|
||||
#ifdef LEGACY_GPIO_ARRAY
|
||||
for (uint32_t i = 0; i < GPIO_MAX; i++) {
|
||||
if ((Pin(i) >= 12) && (Pin(i) <=14)) { SetPin(99, i); }
|
||||
}
|
||||
#endif
|
||||
my_module.io[12] = GPIO_SPI_MISO;
|
||||
SetPin(12, GPIO_SPI_MISO);
|
||||
my_module.io[13] = GPIO_SPI_MOSI;
|
||||
@ -1466,6 +1457,14 @@ void GpioInit(void)
|
||||
}
|
||||
soft_spi_flg = (PinUsed(GPIO_SSPI_CS) && PinUsed(GPIO_SSPI_SCLK) && (PinUsed(GPIO_SSPI_MOSI) || PinUsed(GPIO_SSPI_MISO)));
|
||||
#endif // USE_SPI
|
||||
#else // ESP32
|
||||
analogWriteFreqRange(0, Settings.pwm_frequency, Settings.pwm_range);
|
||||
|
||||
#ifdef USE_SPI
|
||||
spi_flg = (PinUsed(GPIO_SPI_CLK) && (PinUsed(GPIO_SPI_MOSI) || PinUsed(GPIO_SPI_MISO)));
|
||||
soft_spi_flg = (PinUsed(GPIO_SSPI_SCLK) && (PinUsed(GPIO_SSPI_MOSI) || PinUsed(GPIO_SSPI_MISO)));
|
||||
#endif // USE_SPI
|
||||
#endif // ESP8266 - ESP32
|
||||
|
||||
// Set any non-used GPIO to INPUT - Related to resetPins() in support_legacy_cores.ino
|
||||
// Doing it here solves relay toggles at restart.
|
||||
@ -1514,6 +1513,11 @@ void GpioInit(void)
|
||||
for (uint32_t i = 0; i < MAX_PWMS; i++) { // Basic PWM control only
|
||||
if (PinUsed(GPIO_PWM1, i)) {
|
||||
pinMode(Pin(GPIO_PWM1, i), OUTPUT);
|
||||
#ifdef ESP32
|
||||
analogAttach(Pin(GPIO_PWM1, i),i);
|
||||
analogWriteFreqRange(i,Settings.pwm_frequency,Settings.pwm_range);
|
||||
#endif
|
||||
|
||||
if (light_type) {
|
||||
// force PWM GPIOs to low or high mode, see #7165
|
||||
analogWrite(Pin(GPIO_PWM1, i), bitRead(pwm_inverted, i) ? Settings.pwm_range : 0);
|
||||
@ -1541,10 +1545,7 @@ void GpioInit(void)
|
||||
if (PinUsed(GPIO_LED1, i)) {
|
||||
#ifdef USE_ARILUX_RF
|
||||
if ((3 == i) && (leds_present < 2) && !PinUsed(GPIO_ARIRFSEL)) {
|
||||
SetPin(Pin(GPIO_LED4), GPIO_ARIRFSEL); // Legacy support where LED4 was Arilux RF enable
|
||||
#ifdef LEGACY_GPIO_ARRAY
|
||||
SetPin(99, GPIO_LED4);
|
||||
#endif
|
||||
SetPin(Pin(GPIO_LED1, i), GPIO_ARIRFSEL); // Legacy support where LED4 was Arilux RF enable
|
||||
} else {
|
||||
#endif
|
||||
pinMode(Pin(GPIO_LED1, i), OUTPUT);
|
||||
|
@ -41,14 +41,8 @@
|
||||
* Power Type
|
||||
\*********************************************************************************************/
|
||||
|
||||
//#ifdef ESP8266
|
||||
typedef unsigned long power_t; // Power (Relay) type
|
||||
const uint32_t POWER_MASK = 0xffffffffUL; // Power (Relay) full mask
|
||||
//#endif // ESP8266
|
||||
//#ifdef ESP32
|
||||
//typedef uint64_t power_t; // Power (Relay) type
|
||||
//const uint64_t POWER_MASK = 0xffffffffffffffffull; // Power (Relay) full mask
|
||||
//#endif // ESP32
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Constants
|
||||
|
@ -118,9 +118,11 @@ uint16_t tele_period = 9999; // Tele period timer
|
||||
uint16_t blink_counter = 0; // Number of blink cycles
|
||||
uint16_t seriallog_timer = 0; // Timer to disable Seriallog
|
||||
uint16_t syslog_timer = 0; // Timer to re-enable syslog_level
|
||||
//#ifdef ESP32
|
||||
//uint16_t pin[MAX_GPIO_PIN] = { 0 }; // Possible pin configurations
|
||||
//#endif
|
||||
|
||||
#ifdef ESP32
|
||||
uint16_t gpio_pin[MAX_GPIO_PIN] = { 0 }; // GPIO functions indexed by pin number
|
||||
#endif // ESP32
|
||||
|
||||
int16_t save_data_counter; // Counter and flag for config save to Flash
|
||||
RulesBitfield rules_flag; // Rule state flags (16 bits)
|
||||
uint8_t mqtt_cmnd_blocked = 0; // Ignore flag for publish command
|
||||
@ -129,13 +131,11 @@ uint8_t state_250mS = 0; // State 250msecond per second flag
|
||||
uint8_t latching_relay_pulse = 0; // Latching relay pulse timer
|
||||
uint8_t ssleep; // Current copy of Settings.sleep
|
||||
uint8_t blinkspeed = 1; // LED blink rate
|
||||
//#ifdef ESP8266
|
||||
#ifdef LEGACY_GPIO_ARRAY
|
||||
uint8_t pin[GPIO_MAX]; // Possible pin configurations
|
||||
#else
|
||||
uint8_t pin[MAX_GPIO_PIN] = { 0 }; // Possible pin configurations
|
||||
#endif
|
||||
//#endif
|
||||
|
||||
#ifdef ESP8266
|
||||
uint8_t gpio_pin[MAX_GPIO_PIN] = { 0 }; // GPIO functions indexed by pin number
|
||||
#endif // ESP8266 - ESP32
|
||||
|
||||
uint8_t active_device = 1; // Active device in ExecuteCommandPower
|
||||
uint8_t leds_present = 0; // Max number of LED supported
|
||||
uint8_t led_inverted = 0; // LED inverted flag (1 = (0 = On, 1 = Off))
|
||||
@ -151,7 +151,7 @@ uint8_t devices_present = 0; // Max number of devices supported
|
||||
uint8_t seriallog_level; // Current copy of Settings.seriallog_level
|
||||
uint8_t syslog_level; // Current copy of Settings.syslog_level
|
||||
uint8_t my_module_type; // Current copy of Settings.module or user template type
|
||||
uint8_t my_adc0; // Active copy of Module ADC0
|
||||
uint8_t my_adc0 = 0; // Active copy of Module ADC0
|
||||
uint8_t last_source = 0; // Last command source
|
||||
uint8_t shutters_present = 0; // Number of actual define shutters
|
||||
uint8_t prepped_loglevel = 0; // Delayed log level message
|
||||
@ -272,16 +272,17 @@ void setup(void)
|
||||
for (uint32_t i = 0; i < ARRAY_SIZE(Settings.my_gp.io); i++) {
|
||||
Settings.my_gp.io[i] = GPIO_NONE; // Reset user defined GPIO disabling sensors
|
||||
}
|
||||
#ifdef ESP8266
|
||||
Settings.my_adc0 = ADC0_NONE; // Reset user defined ADC0 disabling sensors
|
||||
#endif
|
||||
}
|
||||
if (RtcReboot.fast_reboot_count > Settings.param[P_BOOT_LOOP_OFFSET] +4) { // Restarted 6 times
|
||||
#ifdef ESP8266
|
||||
Settings.module = SONOFF_BASIC; // Reset module to Sonoff Basic
|
||||
// Settings.last_module = SONOFF_BASIC;
|
||||
#endif // ESP8266
|
||||
#ifdef ESP32
|
||||
#else // ESP32
|
||||
Settings.module = WEMOS; // Reset module to Wemos
|
||||
#endif // ESP32
|
||||
#endif // ESP8266 - ESP32
|
||||
}
|
||||
AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION D_LOG_SOME_SETTINGS_RESET " (%d)"), RtcReboot.fast_reboot_count);
|
||||
}
|
||||
|
@ -53,12 +53,6 @@ extern "C" void resetPins();
|
||||
* Mandatory defines satisfying disabled defines
|
||||
\*********************************************************************************************/
|
||||
|
||||
//#define LEGACY_GPIO_ARRAY
|
||||
|
||||
#ifndef MODULE
|
||||
#define MODULE SONOFF_BASIC // [Module] Select default model
|
||||
#endif
|
||||
|
||||
#ifdef USE_EMULATION_HUE
|
||||
#define USE_EMULATION
|
||||
#endif
|
||||
@ -280,6 +274,10 @@ const char kWebColors[] PROGMEM =
|
||||
|
||||
#ifdef ESP8266
|
||||
|
||||
#ifndef MODULE
|
||||
#define MODULE SONOFF_BASIC // [Module] Select default model
|
||||
#endif
|
||||
|
||||
#ifndef ARDUINO_ESP8266_RELEASE
|
||||
#define ARDUINO_CORE_RELEASE "STAGE"
|
||||
#else
|
||||
@ -290,6 +288,10 @@ const char kWebColors[] PROGMEM =
|
||||
|
||||
#ifdef ESP32
|
||||
|
||||
#ifndef MODULE
|
||||
#define MODULE WEMOS // [Module] Select default model
|
||||
#endif
|
||||
|
||||
#ifndef ARDUINO_ESP32_RELEASE
|
||||
#define ARDUINO_CORE_RELEASE "STAGE"
|
||||
#else
|
||||
@ -297,7 +299,7 @@ const char kWebColors[] PROGMEM =
|
||||
#endif // ARDUINO_ESP32_RELEASE
|
||||
|
||||
#undef USE_HM10 // Disable support for HM-10 as a BLE-bridge as an alternative is using the internal ESP32 BLE
|
||||
#undef USE_KEELOQ // Disable support for Jarolift rollers by Keeloq algorithm ss it's library cc1101 is not compatible with ESP32
|
||||
#undef USE_KEELOQ // Disable support for Jarolift rollers by Keeloq algorithm as it's library cc1101 is not compatible with ESP32
|
||||
#undef USE_DISPLAY_ILI9488 // Disable as it's library JaretBurkett_ILI9488-gemu-1.0 is not compatible with ESP32
|
||||
#undef USE_DISPLAY_SSD1351 // Disable as it's library Adafruit_SSD1351_gemu-1.0 is not compatible with ESP32
|
||||
|
||||
@ -324,6 +326,12 @@ const char kWebColors[] PROGMEM =
|
||||
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
|
||||
#endif
|
||||
|
||||
#ifdef ESP8266
|
||||
#define AGPIO(x) (x)
|
||||
#else // ESP32
|
||||
#define AGPIO(x) (x<<5)
|
||||
#endif // ESP8266 - ESP32
|
||||
|
||||
#ifdef USE_DEVICE_GROUPS
|
||||
#define SendDeviceGroupMessage(DEVICE_INDEX, REQUEST_TYPE, ...) _SendDeviceGroupMessage(DEVICE_INDEX, REQUEST_TYPE, __VA_ARGS__, 0)
|
||||
#define SendLocalDeviceGroupMessage(REQUEST_TYPE, ...) _SendDeviceGroupMessage(0, REQUEST_TYPE, __VA_ARGS__, 0)
|
||||
|
@ -20,6 +20,8 @@
|
||||
#ifndef _TASMOTA_TEMPLATE_H_
|
||||
#define _TASMOTA_TEMPLATE_H_
|
||||
|
||||
#ifdef ESP8266
|
||||
|
||||
// User selectable GPIO functionality
|
||||
// ATTENTION: Only add at the end of this list just before GPIO_SENSOR_END
|
||||
// Then add the same name(s) in a nice location in array kGpioNiceList
|
||||
@ -699,31 +701,14 @@ const char kAdc0Names[] PROGMEM =
|
||||
|
||||
/********************************************************************************************/
|
||||
|
||||
#ifdef ESP8266
|
||||
|
||||
#define MAX_GPIO_PIN 17 // Number of supported GPIO
|
||||
#define MIN_FLASH_PINS 4 // Number of flash chip pins unusable for configuration (GPIO6, 7, 8 and 11)
|
||||
#define MAX_USER_PINS 13 // MAX_GPIO_PIN - MIN_FLASH_PINS
|
||||
#define ADC0_PIN 17 // Pin number of ADC0
|
||||
#define WEMOS_MODULE 17 // Wemos module
|
||||
|
||||
const char PINS_WEMOS[] PROGMEM = "D3TXD4RXD2D1flashcFLFLolD6D7D5D8D0A0";
|
||||
|
||||
#else // ESP32
|
||||
|
||||
// esp32 has more pins
|
||||
#define USER_MODULE 255
|
||||
#define MAX_GPIO_PIN 40 // Number of supported GPIO
|
||||
#define MIN_FLASH_PINS 4 // Number of flash chip pins unusable for configuration (GPIO6, 7, 8 and 11)
|
||||
#define ADC0_PIN 33 // Pin number of ADC0
|
||||
#define WEMOS_MODULE 0 // Wemos module
|
||||
|
||||
// 0 1 2 3 4 5 6 7 8 9101112131415161718192021222324252627282930313233343536373839
|
||||
const char PINS_WEMOS[] PROGMEM = "IOTXIORXIOIOflashcFLFLolIOIOIOIOIOIOIOIOIOIOIOIOIOIOIOIOIOIOIOIOIOIOA6A7A0IoIoA3";
|
||||
|
||||
#endif // ESP8266
|
||||
|
||||
#define MAX_USER_PINS MAX_GPIO_PIN-MIN_FLASH_PINS
|
||||
|
||||
/********************************************************************************************/
|
||||
|
||||
typedef struct MYIO {
|
||||
@ -758,10 +743,8 @@ typedef struct MYTMPLT {
|
||||
} mytmplt;
|
||||
|
||||
/********************************************************************************************/
|
||||
|
||||
#ifdef ESP8266
|
||||
|
||||
// Supported hardware modules
|
||||
|
||||
enum SupportedModules {
|
||||
SONOFF_BASIC, SONOFF_RF, SONOFF_SV, SONOFF_TH, SONOFF_DUAL, SONOFF_POW, SONOFF_4CH, SONOFF_S2X, SLAMPHER, SONOFF_TOUCH,
|
||||
SONOFF_LED, CH1, CH4, MOTOR, ELECTRODRAGON, EXS_RELAY, WION, WEMOS, SONOFF_DEV, H801,
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
tasmota_template_ESP32.h - template settings for Tasmota
|
||||
tasmota_template_ESP32.h - ESP32 template settings for Tasmota
|
||||
|
||||
Copyright (C) 2020 Theo Arends
|
||||
|
||||
@ -42,12 +42,556 @@
|
||||
#undef USE_TUYA_MCU
|
||||
#undef USE_PS_16_DZ
|
||||
|
||||
enum UserSelectablePins {
|
||||
GPIO_NONE, // Not used
|
||||
GPIO_KEY1, GPIO_KEY1_NP, GPIO_KEY1_INV, GPIO_KEY1_INV_NP, // 4 x Button
|
||||
GPIO_SWT1, GPIO_SWT1_NP, // 8 x User connected external switches
|
||||
GPIO_REL1, GPIO_REL1_INV, // 8 x Relays
|
||||
GPIO_LED1, GPIO_LED1_INV, // 4 x Leds
|
||||
GPIO_CNTR1, GPIO_CNTR1_NP, // 4 x Counter
|
||||
GPIO_PWM1, GPIO_PWM1_INV, // 5 x PWM
|
||||
GPIO_BUZZER, GPIO_BUZZER_INV, // Buzzer
|
||||
GPIO_LEDLNK, GPIO_LEDLNK_INV, // Link led
|
||||
GPIO_I2C_SCL, GPIO_I2C_SDA, // Software I2C
|
||||
GPIO_SPI_MISO, GPIO_SPI_MOSI, GPIO_SPI_CLK, GPIO_SPI_CS, GPIO_SPI_DC, // Hardware SPI
|
||||
GPIO_SSPI_MISO, GPIO_SSPI_MOSI, GPIO_SSPI_SCLK, GPIO_SSPI_CS, GPIO_SSPI_DC, // Software SPI
|
||||
GPIO_BACKLIGHT, // Display backlight control
|
||||
GPIO_OLED_RESET, // OLED Display Reset
|
||||
GPIO_IRSEND, GPIO_IRRECV, // IR interface
|
||||
GPIO_RFSEND, GPIO_RFRECV, // RF interface
|
||||
GPIO_DHT11, GPIO_DHT22, GPIO_SI7021, GPIO_DHT11_OUT, // DHT11, DHT21, DHT22, AM2301, AM2302, AM2321
|
||||
GPIO_DSB, GPIO_DSB_OUT, // DS18B20 or DS18S20
|
||||
GPIO_WS2812, // WS2812 Led string
|
||||
GPIO_MHZ_TXD, GPIO_MHZ_RXD, // MH-Z19 Serial interface
|
||||
GPIO_PZEM0XX_TX, GPIO_PZEM004_RX, GPIO_PZEM016_RX, GPIO_PZEM017_RX, // PZEM Serial Modbus interface
|
||||
GPIO_SAIR_TX, GPIO_SAIR_RX, // SenseAir Serial interface
|
||||
GPIO_PMS5003_TX, GPIO_PMS5003_RX, // Plantower PMS5003 Serial interface
|
||||
GPIO_SDS0X1_TX, GPIO_SDS0X1_RX, // Nova Fitness SDS011 Serial interface
|
||||
GPIO_SBR_TX, GPIO_SBR_RX, // Serial Bridge Serial interface
|
||||
GPIO_SR04_TRIG, GPIO_SR04_ECHO, // SR04 interface
|
||||
GPIO_SDM120_TX, GPIO_SDM120_RX, // SDM120 Serial interface
|
||||
GPIO_SDM630_TX, GPIO_SDM630_RX, // SDM630 Serial interface
|
||||
GPIO_TM16CLK, GPIO_TM16DIO, GPIO_TM16STB, // TM1638 interface
|
||||
GPIO_MP3_DFR562, // RB-DFR-562, DFPlayer Mini MP3 Player
|
||||
GPIO_HX711_SCK, GPIO_HX711_DAT, // HX711 Load Cell interface
|
||||
GPIO_TX2X_TXD_BLACK, // TX20/TX23 Transmission Pin
|
||||
GPIO_TUYA_TX, GPIO_TUYA_RX, // Tuya Serial interface
|
||||
GPIO_MGC3130_XFER, GPIO_MGC3130_RESET, // MGC3130 interface
|
||||
GPIO_RF_SENSOR, // Rf receiver with sensor decoding
|
||||
GPIO_AZ_TXD, GPIO_AZ_RXD, // AZ-Instrument 7798 Serial interface
|
||||
GPIO_MAX31855CS, GPIO_MAX31855CLK, GPIO_MAX31855DO, // MAX31855 Serial interface
|
||||
GPIO_NRG_SEL, GPIO_NRG_SEL_INV, GPIO_NRG_CF1, GPIO_HLW_CF, GPIO_HJL_CF, // HLW8012/HJL-01/BL0937 energy monitoring
|
||||
GPIO_MCP39F5_TX, GPIO_MCP39F5_RX, GPIO_MCP39F5_RST, // MCP39F501 Energy monitoring (Shelly2)
|
||||
GPIO_PN532_TXD, GPIO_PN532_RXD, // PN532 NFC Serial interface
|
||||
GPIO_SM16716_CLK, GPIO_SM16716_DAT, GPIO_SM16716_SEL, // SM16716 SELECT
|
||||
GPIO_DI, GPIO_DCKI, // my92x1 PWM controller
|
||||
GPIO_CSE7766_TX, GPIO_CSE7766_RX, // CSE7766 Serial interface (S31 and Pow R2)
|
||||
GPIO_ARIRFRCV, GPIO_ARIRFSEL, // Arilux RF Receive input
|
||||
GPIO_TXD, GPIO_RXD, // Serial interface
|
||||
GPIO_ROT1A, GPIO_ROT1B, GPIO_ROT2A, GPIO_ROT2B, // Rotary switch
|
||||
GPIO_HRE_CLOCK, GPIO_HRE_DATA, // HR-E Water Meter
|
||||
GPIO_ADE7953_IRQ, // ADE7953 IRQ
|
||||
GPIO_SOLAXX1_TX, GPIO_SOLAXX1_RX, // Solax Inverter Serial interface
|
||||
GPIO_ZIGBEE_TX, GPIO_ZIGBEE_RX, // Zigbee Serial interface
|
||||
GPIO_RDM6300_RX, // RDM6300 RX
|
||||
GPIO_IBEACON_TX, GPIO_IBEACON_RX, // HM17 IBEACON Serial interface
|
||||
GPIO_A4988_DIR, GPIO_A4988_STP, GPIO_A4988_ENA, // A4988 interface
|
||||
GPIO_A4988_MS1, GPIO_A4988_MS2, GPIO_A4988_MS3, // A4988 microstep
|
||||
GPIO_DDS2382_TX, GPIO_DDS2382_RX, // DDS2382 Serial interface
|
||||
GPIO_DDSU666_TX, GPIO_DDSU666_RX, // DDSU666 Serial interface
|
||||
GPIO_SM2135_CLK, GPIO_SM2135_DAT, // SM2135 PWM controller
|
||||
GPIO_DEEPSLEEP, // Kill switch for deepsleep
|
||||
GPIO_EXS_ENABLE, // EXS MCU Enable
|
||||
GPIO_TASMOTASLAVE_TXD, GPIO_TASMOTASLAVE_RXD, // Slave Serial interface
|
||||
GPIO_TASMOTASLAVE_RST, GPIO_TASMOTASLAVE_RST_INV, // Slave Reset
|
||||
GPIO_HPMA_RX, GPIO_HPMA_TX, // Honeywell HPMA115S0 Serial interface
|
||||
GPIO_GPS_RX, GPIO_GPS_TX, // GPS Serial interface
|
||||
GPIO_HM10_RX, GPIO_HM10_TX, // HM10-BLE-Mijia-bridge Serial interface
|
||||
GPIO_LE01MR_RX, GPIO_LE01MR_TX, // F&F LE-01MR energy meter
|
||||
GPIO_CC1101_GDO0, GPIO_CC1101_GDO2, // CC1101 Serial interface
|
||||
GPIO_HRXL_RX, // Data from MaxBotix HRXL sonar range sensor
|
||||
GPIO_ELECTRIQ_MOODL_TX, // ElectriQ iQ-wifiMOODL Serial TX
|
||||
GPIO_AS3935,
|
||||
ADC0_INPUT, // Analog input
|
||||
ADC0_TEMP, // Analog Thermistor
|
||||
ADC0_LIGHT, // Analog Light sensor
|
||||
ADC0_BUTTON, ADC0_BUTTON_INV, // Analog Button
|
||||
ADC0_RANGE, // Analog Range
|
||||
ADC0_CT_POWER, // ANalog Current
|
||||
GPIO_WEBCAM_PWDN, GPIO_WEBCAM_RESET, GPIO_WEBCAM_XCLK, GPIO_WEBCAM_SIOD, GPIO_WEBCAM_SIOC, // Webcam
|
||||
GPIO_WEBCAM_Y9, GPIO_WEBCAM_Y8, GPIO_WEBCAM_Y7, GPIO_WEBCAM_Y6,
|
||||
GPIO_WEBCAM_Y5, GPIO_WEBCAM_Y4, GPIO_WEBCAM_Y3, GPIO_WEBCAM_Y2,
|
||||
GPIO_WEBCAM_VSYNC, GPIO_WEBCAM_HREF, GPIO_WEBCAM_PCLK, GPIO_WEBCAM_PSCLK,
|
||||
GPIO_WEBCAM_HSD1, GPIO_WEBCAM_HSD2, GPIO_WEBCAM_HSD3, GPIO_WEBCAM_PSRCS,
|
||||
GPIO_SENSOR_END };
|
||||
|
||||
enum ProgramSelectablePins {
|
||||
// GPIO_FIX_START = 254,
|
||||
GPIO_FIX_START = 2046,
|
||||
GPIO_USER, // User configurable needs to be 2047
|
||||
GPIO_MAX };
|
||||
|
||||
// Text in webpage Module Parameters and commands GPIOS and GPIO
|
||||
const char kSensorNames[] PROGMEM =
|
||||
D_SENSOR_NONE "|"
|
||||
D_SENSOR_BUTTON "|" D_SENSOR_BUTTON "n|" D_SENSOR_BUTTON "i|" D_SENSOR_BUTTON "in|"
|
||||
D_SENSOR_SWITCH "|" D_SENSOR_SWITCH "n|"
|
||||
D_SENSOR_RELAY "|" D_SENSOR_RELAY "i|"
|
||||
D_SENSOR_LED "|" D_SENSOR_LED "i|"
|
||||
D_SENSOR_COUNTER "|" D_SENSOR_COUNTER "n|"
|
||||
D_SENSOR_PWM "|" D_SENSOR_PWM "i|"
|
||||
D_SENSOR_BUZZER "|" D_SENSOR_BUZZER "i|"
|
||||
D_SENSOR_LED_LINK "|" D_SENSOR_LED_LINK "i|"
|
||||
D_SENSOR_I2C_SCL "|" D_SENSOR_I2C_SDA "|"
|
||||
D_SENSOR_SPI_MISO "|" D_SENSOR_SPI_MOSI "|" D_SENSOR_SPI_CLK "|" D_SENSOR_SPI_CS "|" D_SENSOR_SPI_DC "|"
|
||||
D_SENSOR_SSPI_MISO "|" D_SENSOR_SSPI_MOSI "|" D_SENSOR_SSPI_SCLK "|" D_SENSOR_SSPI_CS "|" D_SENSOR_SSPI_DC "|"
|
||||
D_SENSOR_BACKLIGHT "|" D_SENSOR_OLED_RESET "|"
|
||||
D_SENSOR_IRSEND "|" D_SENSOR_IRRECV "|"
|
||||
D_SENSOR_RFSEND "|" D_SENSOR_RFRECV "|"
|
||||
D_SENSOR_DHT11 "|" D_SENSOR_AM2301 "|" D_SENSOR_SI7021 "|" D_SENSOR_DHT11 "o|"
|
||||
D_SENSOR_DS18X20 "|" D_SENSOR_DS18X20 "o|"
|
||||
D_SENSOR_WS2812 "|"
|
||||
D_SENSOR_MHZ_TX "|" D_SENSOR_MHZ_RX "|"
|
||||
D_SENSOR_PZEM0XX_TX "|" D_SENSOR_PZEM004_RX "|" D_SENSOR_PZEM016_RX "|" D_SENSOR_PZEM017_RX "|"
|
||||
D_SENSOR_SAIR_TX "|" D_SENSOR_SAIR_RX "|"
|
||||
D_SENSOR_PMS5003_TX "|" D_SENSOR_PMS5003_RX "|"
|
||||
D_SENSOR_SDS0X1_TX "|" D_SENSOR_SDS0X1_RX "|"
|
||||
D_SENSOR_SBR_TX "|" D_SENSOR_SBR_RX "|"
|
||||
D_SENSOR_SR04_TRIG "|" D_SENSOR_SR04_ECHO "|"
|
||||
D_SENSOR_SDM120_TX "|" D_SENSOR_SDM120_RX "|"
|
||||
D_SENSOR_SDM630_TX "|" D_SENSOR_SDM630_RX "|"
|
||||
D_SENSOR_TM1638_CLK "|" D_SENSOR_TM1638_DIO "|" D_SENSOR_TM1638_STB "|"
|
||||
D_SENSOR_DFR562 "|"
|
||||
D_SENSOR_HX711_SCK "|" D_SENSOR_HX711_DAT "|"
|
||||
D_SENSOR_TX2X_TX "|"
|
||||
D_SENSOR_TUYA_TX "|" D_SENSOR_TUYA_RX "|"
|
||||
D_SENSOR_MGC3130_XFER "|" D_SENSOR_MGC3130_RESET "|"
|
||||
D_SENSOR_RF_SENSOR "|"
|
||||
D_SENSOR_AZ_TX "|" D_SENSOR_AZ_RX "|"
|
||||
D_SENSOR_MAX31855_CS "|" D_SENSOR_MAX31855_CLK "|" D_SENSOR_MAX31855_DO "|"
|
||||
D_SENSOR_NRG_SEL "|" D_SENSOR_NRG_SEL "i|" D_SENSOR_NRG_CF1 "|" D_SENSOR_HLW_CF "|" D_SENSOR_HJL_CF "|"
|
||||
D_SENSOR_MCP39F5_TX "|" D_SENSOR_MCP39F5_RX "|" D_SENSOR_MCP39F5_RST "|"
|
||||
D_SENSOR_PN532_TX "|" D_SENSOR_PN532_RX "|"
|
||||
D_SENSOR_SM16716_CLK "|" D_SENSOR_SM16716_DAT "|" D_SENSOR_SM16716_POWER "|"
|
||||
D_SENSOR_MY92X1_DI "|" D_SENSOR_MY92X1_DCKI "|"
|
||||
D_SENSOR_CSE7766_TX "|" D_SENSOR_CSE7766_RX "|"
|
||||
D_SENSOR_ARIRFRCV "|" D_SENSOR_ARIRFSEL "|"
|
||||
D_SENSOR_TXD "|" D_SENSOR_RXD "|"
|
||||
D_SENSOR_ROTARY "1a|" D_SENSOR_ROTARY "1b|" D_SENSOR_ROTARY "2a|" D_SENSOR_ROTARY "2b|"
|
||||
D_SENSOR_HRE_CLOCK "|" D_SENSOR_HRE_DATA "|"
|
||||
D_SENSOR_ADE7953_IRQ "|"
|
||||
D_SENSOR_SOLAXX1_TX "|" D_SENSOR_SOLAXX1_RX "|"
|
||||
D_SENSOR_ZIGBEE_TXD "|" D_SENSOR_ZIGBEE_RXD "|"
|
||||
D_SENSOR_RDM6300_RX "|"
|
||||
D_SENSOR_IBEACON_TX "|" D_SENSOR_IBEACON_RX "|"
|
||||
D_SENSOR_A4988_DIR "|" D_SENSOR_A4988_STP "|" D_SENSOR_A4988_ENA "|" D_SENSOR_A4988_MS1 "|" D_SENSOR_A4988_MS2 "|" D_SENSOR_A4988_MS3 "|"
|
||||
D_SENSOR_DDS2382_TX "|" D_SENSOR_DDS2382_RX "|"
|
||||
D_SENSOR_DDSU666_TX "|" D_SENSOR_DDSU666_RX "|"
|
||||
D_SENSOR_SM2135_CLK "|" D_SENSOR_SM2135_DAT "|"
|
||||
D_SENSOR_DEEPSLEEP "|" D_SENSOR_EXS_ENABLE "|"
|
||||
D_SENSOR_SLAVE_TX "|" D_SENSOR_SLAVE_RX "|" D_SENSOR_SLAVE_RESET "|" D_SENSOR_SLAVE_RESET "i|"
|
||||
D_SENSOR_HPMA_RX "|" D_SENSOR_HPMA_TX "|"
|
||||
D_SENSOR_GPS_RX "|" D_SENSOR_GPS_TX "|"
|
||||
D_SENSOR_HM10_RX "|" D_SENSOR_HM10_TX "|"
|
||||
D_SENSOR_LE01MR_RX "|" D_SENSOR_LE01MR_TX "|"
|
||||
D_SENSOR_CC1101_GDO0 "|" D_SENSOR_CC1101_GDO2 "|"
|
||||
D_SENSOR_HRXL_RX "|"
|
||||
D_SENSOR_ELECTRIQ_MOODL "|"
|
||||
D_SENSOR_AS3935 "|"
|
||||
D_ANALOG_INPUT "|"
|
||||
D_TEMPERATURE "|" D_LIGHT "|"
|
||||
D_SENSOR_BUTTON "|" D_SENSOR_BUTTON "i|"
|
||||
D_RANGE "|"
|
||||
D_CT_POWER "|"
|
||||
D_GPIO_WEBCAM_PWDN "|" D_GPIO_WEBCAM_RESET "|" D_GPIO_WEBCAM_XCLK "|" D_GPIO_WEBCAM_SIOD "|" D_GPIO_WEBCAM_SIOC "|"
|
||||
D_GPIO_WEBCAM_Y9 "|" D_GPIO_WEBCAM_Y8 "|" D_GPIO_WEBCAM_Y7 "|" D_GPIO_WEBCAM_Y6 "|"
|
||||
D_GPIO_WEBCAM_Y5 "|" D_GPIO_WEBCAM_Y4 "|" D_GPIO_WEBCAM_Y3 "|" D_GPIO_WEBCAM_Y2 "|"
|
||||
D_GPIO_WEBCAM_VSYNC "|" D_GPIO_WEBCAM_HREF "|" D_GPIO_WEBCAM_PCLK "|" D_GPIO_WEBCAM_PSCLK "|"
|
||||
D_GPIO_WEBCAM_HSD1 "|" D_GPIO_WEBCAM_HSD2 "|" D_GPIO_WEBCAM_HSD3 "|" D_GPIO_WEBCAM_PSRCS
|
||||
;
|
||||
|
||||
const char kSensorNamesFixed[] PROGMEM =
|
||||
D_SENSOR_USER;
|
||||
|
||||
const uint16_t kGpioNiceList[] PROGMEM = {
|
||||
GPIO_NONE, // Not used
|
||||
AGPIO(GPIO_KEY1) + MAX_KEYS, // Buttons
|
||||
AGPIO(GPIO_KEY1_NP) + MAX_KEYS,
|
||||
AGPIO(GPIO_KEY1_INV) + MAX_KEYS,
|
||||
AGPIO(GPIO_KEY1_INV_NP) + MAX_KEYS,
|
||||
AGPIO(GPIO_SWT1) + MAX_SWITCHES, // User connected external switches
|
||||
AGPIO(GPIO_SWT1_NP) + MAX_SWITCHES,
|
||||
AGPIO(GPIO_REL1) + MAX_RELAYS, // Relays
|
||||
AGPIO(GPIO_REL1_INV) + MAX_RELAYS,
|
||||
AGPIO(GPIO_LED1) + MAX_LEDS, // Leds
|
||||
AGPIO(GPIO_LED1_INV) + MAX_LEDS,
|
||||
#ifdef USE_COUNTER
|
||||
AGPIO(GPIO_CNTR1) + MAX_COUNTERS, // Counters
|
||||
AGPIO(GPIO_CNTR1_NP) + MAX_COUNTERS,
|
||||
#endif
|
||||
AGPIO(GPIO_PWM1) + MAX_PWMS, // RGB Red or C Cold White
|
||||
AGPIO(GPIO_PWM1_INV) + MAX_PWMS,
|
||||
#ifdef USE_BUZZER
|
||||
AGPIO(GPIO_BUZZER), // Buzzer
|
||||
AGPIO(GPIO_BUZZER_INV), // Inverted buzzer
|
||||
#endif
|
||||
AGPIO(GPIO_LEDLNK), // Link led
|
||||
AGPIO(GPIO_LEDLNK_INV), // Inverted link led
|
||||
#ifdef USE_I2C
|
||||
AGPIO(GPIO_I2C_SCL), // I2C SCL
|
||||
AGPIO(GPIO_I2C_SDA), // I2C SDA
|
||||
#endif
|
||||
#ifdef USE_SPI
|
||||
AGPIO(GPIO_SPI_MISO), // SPI MISO
|
||||
AGPIO(GPIO_SPI_MOSI), // SPI MOSI
|
||||
AGPIO(GPIO_SPI_CLK), // SPI Clk
|
||||
AGPIO(GPIO_SPI_CS), // SPI Chip Select
|
||||
AGPIO(GPIO_SPI_DC), // SPI Data Direction
|
||||
AGPIO(GPIO_SSPI_MISO), // Software SPI Master Input Slave Output
|
||||
AGPIO(GPIO_SSPI_MOSI), // Software SPI Master Output Slave Input
|
||||
AGPIO(GPIO_SSPI_SCLK), // Software SPI Serial Clock
|
||||
AGPIO(GPIO_SSPI_CS), // Software SPI Chip Select
|
||||
AGPIO(GPIO_SSPI_DC), // Software SPI Data or Command
|
||||
#endif
|
||||
#ifdef USE_DISPLAY
|
||||
AGPIO(GPIO_BACKLIGHT), // Display backlight control
|
||||
AGPIO(GPIO_OLED_RESET), // OLED Display Reset
|
||||
#endif
|
||||
|
||||
AGPIO(GPIO_TXD), // Serial interface
|
||||
AGPIO(GPIO_RXD), // Serial interface
|
||||
|
||||
#ifdef USE_DHT
|
||||
AGPIO(GPIO_DHT11), // DHT11
|
||||
AGPIO(GPIO_DHT22), // DHT21, DHT22, AM2301, AM2302, AM2321
|
||||
AGPIO(GPIO_SI7021), // iTead SI7021
|
||||
AGPIO(GPIO_DHT11_OUT), // Pseudo Single wire DHT11, DHT21, DHT22, AM2301, AM2302, AM2321
|
||||
#endif
|
||||
#ifdef USE_DS18x20
|
||||
AGPIO(GPIO_DSB), // Single wire DS18B20 or DS18S20
|
||||
AGPIO(GPIO_DSB_OUT), // Pseudo Single wire DS18B20 or DS18S20
|
||||
#endif
|
||||
|
||||
// Light
|
||||
#ifdef USE_LIGHT
|
||||
#ifdef USE_WS2812
|
||||
AGPIO(GPIO_WS2812), // WS2812 Led string
|
||||
#endif
|
||||
#ifdef USE_ARILUX_RF
|
||||
AGPIO(GPIO_ARIRFRCV), // AriLux RF Receive input
|
||||
AGPIO(GPIO_ARIRFSEL), // Arilux RF Receive input selected
|
||||
#endif
|
||||
#ifdef USE_MY92X1
|
||||
AGPIO(GPIO_DI), // my92x1 PWM input
|
||||
AGPIO(GPIO_DCKI), // my92x1 CLK input
|
||||
#endif // USE_MY92X1
|
||||
#ifdef USE_SM16716
|
||||
AGPIO(GPIO_SM16716_CLK), // SM16716 CLOCK
|
||||
AGPIO(GPIO_SM16716_DAT), // SM16716 DATA
|
||||
AGPIO(GPIO_SM16716_SEL), // SM16716 SELECT
|
||||
#endif // USE_SM16716
|
||||
#ifdef USE_SM2135
|
||||
AGPIO(GPIO_SM2135_CLK), // SM2135 CLOCK
|
||||
AGPIO(GPIO_SM2135_DAT), // SM2135 DATA
|
||||
#endif // USE_SM2135
|
||||
#ifdef USE_TUYA_MCU
|
||||
AGPIO(GPIO_TUYA_TX), // Tuya Serial interface
|
||||
AGPIO(GPIO_TUYA_RX), // Tuya Serial interface
|
||||
#endif
|
||||
#ifdef USE_EXS_DIMMER
|
||||
AGPIO(GPIO_EXS_ENABLE), // EXS MCU Enable
|
||||
#endif
|
||||
#ifdef USE_ELECTRIQ_MOODL
|
||||
AGPIO(GPIO_ELECTRIQ_MOODL_TX),
|
||||
#endif
|
||||
#endif // USE_LIGHT
|
||||
|
||||
#if defined(USE_IR_REMOTE) || defined(USE_IR_REMOTE_FULL)
|
||||
AGPIO(GPIO_IRSEND), // IR remote
|
||||
#if defined(USE_IR_RECEIVE) || defined(USE_IR_REMOTE_FULL)
|
||||
AGPIO(GPIO_IRRECV), // IR receiver
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef USE_RC_SWITCH
|
||||
AGPIO(GPIO_RFSEND), // RF transmitter
|
||||
AGPIO(GPIO_RFRECV), // RF receiver
|
||||
#endif
|
||||
#ifdef USE_RF_SENSOR
|
||||
AGPIO(GPIO_RF_SENSOR), // Rf receiver with sensor decoding
|
||||
#endif
|
||||
#ifdef USE_SR04
|
||||
AGPIO(GPIO_SR04_TRIG), // SR04 Tri/TXgger pin
|
||||
AGPIO(GPIO_SR04_ECHO), // SR04 Ech/RXo pin
|
||||
#endif
|
||||
#ifdef USE_TM1638
|
||||
AGPIO(GPIO_TM16CLK), // TM1638 Clock
|
||||
AGPIO(GPIO_TM16DIO), // TM1638 Data I/O
|
||||
AGPIO(GPIO_TM16STB), // TM1638 Strobe
|
||||
#endif
|
||||
#ifdef USE_HX711
|
||||
AGPIO(GPIO_HX711_SCK), // HX711 Load Cell clock
|
||||
AGPIO(GPIO_HX711_DAT), // HX711 Load Cell data
|
||||
#endif
|
||||
|
||||
// Energy sensors
|
||||
#ifdef USE_ENERGY_SENSOR
|
||||
#ifdef USE_HLW8012
|
||||
AGPIO(GPIO_NRG_SEL), // HLW8012/HLJ-01 Sel output (1 = Voltage)
|
||||
AGPIO(GPIO_NRG_SEL_INV), // HLW8012/HLJ-01 Sel output (0 = Voltage)
|
||||
AGPIO(GPIO_NRG_CF1), // HLW8012/HLJ-01 CF1 voltage / current
|
||||
AGPIO(GPIO_HLW_CF), // HLW8012 CF power
|
||||
AGPIO(GPIO_HJL_CF), // HJL-01/BL0937 CF power
|
||||
#endif
|
||||
#if defined(USE_I2C) && defined(USE_ADE7953)
|
||||
AGPIO(GPIO_ADE7953_IRQ), // ADE7953 IRQ
|
||||
#endif
|
||||
#ifdef USE_CSE7766
|
||||
AGPIO(GPIO_CSE7766_TX), // CSE7766 Serial interface (S31 and Pow R2)
|
||||
AGPIO(GPIO_CSE7766_RX), // CSE7766 Serial interface (S31 and Pow R2)
|
||||
#endif
|
||||
#ifdef USE_MCP39F501
|
||||
AGPIO(GPIO_MCP39F5_TX), // MCP39F501 Serial interface (Shelly2)
|
||||
AGPIO(GPIO_MCP39F5_RX), // MCP39F501 Serial interface (Shelly2)
|
||||
AGPIO(GPIO_MCP39F5_RST), // MCP39F501 Reset (Shelly2)
|
||||
#endif
|
||||
#if defined(USE_PZEM004T) || defined(USE_PZEM_AC) || defined(USE_PZEM_DC)
|
||||
AGPIO(GPIO_PZEM0XX_TX), // PZEM0XX Serial interface
|
||||
#endif
|
||||
#ifdef USE_PZEM004T
|
||||
AGPIO(GPIO_PZEM004_RX), // PZEM004T Serial interface
|
||||
#endif
|
||||
#ifdef USE_PZEM_AC
|
||||
AGPIO(GPIO_PZEM016_RX), // PZEM-014,016 Serial Modbus interface
|
||||
#endif
|
||||
#ifdef USE_PZEM_DC
|
||||
AGPIO(GPIO_PZEM017_RX), // PZEM-003,017 Serial Modbus interface
|
||||
#endif
|
||||
#ifdef USE_SDM120
|
||||
AGPIO(GPIO_SDM120_TX), // SDM120 Serial interface
|
||||
AGPIO(GPIO_SDM120_RX), // SDM120 Serial interface
|
||||
#endif
|
||||
#ifdef USE_SDM630
|
||||
AGPIO(GPIO_SDM630_TX), // SDM630 Serial interface
|
||||
AGPIO(GPIO_SDM630_RX), // SDM630 Serial interface
|
||||
#endif
|
||||
#ifdef USE_DDS2382
|
||||
AGPIO(GPIO_DDS2382_TX), // DDS2382 Serial interface
|
||||
AGPIO(GPIO_DDS2382_RX), // DDS2382 Serial interface
|
||||
#endif
|
||||
#ifdef USE_DDSU666
|
||||
AGPIO(GPIO_DDSU666_TX), // DDSU666 Serial interface
|
||||
AGPIO(GPIO_DDSU666_RX), // DDSU666 Serial interface
|
||||
#endif // USE_DDSU666
|
||||
#ifdef USE_SOLAX_X1
|
||||
AGPIO(GPIO_SOLAXX1_TX), // Solax Inverter tx pin
|
||||
AGPIO(GPIO_SOLAXX1_RX), // Solax Inverter rx pin
|
||||
#endif // USE_SOLAX_X1
|
||||
#ifdef USE_LE01MR
|
||||
AGPIO(GPIO_LE01MR_RX), // F7F LE-01MR energy meter rx pin
|
||||
AGPIO(GPIO_LE01MR_TX), // F7F LE-01MR energy meter tx pin
|
||||
#endif // IFDEF:USE_LE01MR
|
||||
#endif // USE_ENERGY_SENSOR
|
||||
|
||||
// Serial
|
||||
#ifdef USE_SERIAL_BRIDGE
|
||||
AGPIO(GPIO_SBR_TX), // Serial Bridge Serial interface
|
||||
AGPIO(GPIO_SBR_RX), // Serial Bridge Serial interface
|
||||
#endif
|
||||
#ifdef USE_ZIGBEE
|
||||
AGPIO(GPIO_ZIGBEE_TX), // Zigbee Serial interface
|
||||
AGPIO(GPIO_ZIGBEE_RX), // Zigbee Serial interface
|
||||
#endif
|
||||
#ifdef USE_MHZ19
|
||||
AGPIO(GPIO_MHZ_TXD), // MH-Z19 Serial interface
|
||||
AGPIO(GPIO_MHZ_RXD), // MH-Z19 Serial interface
|
||||
#endif
|
||||
#ifdef USE_SENSEAIR
|
||||
AGPIO(GPIO_SAIR_TX), // SenseAir Serial interface
|
||||
AGPIO(GPIO_SAIR_RX), // SenseAir Serial interface
|
||||
#endif
|
||||
#ifdef USE_NOVA_SDS
|
||||
AGPIO(GPIO_SDS0X1_TX), // Nova Fitness SDS011 Serial interface
|
||||
AGPIO(GPIO_SDS0X1_RX), // Nova Fitness SDS011 Serial interface
|
||||
#endif
|
||||
#ifdef USE_HPMA
|
||||
AGPIO(GPIO_HPMA_TX), // Honeywell HPMA115S0 Serial interface
|
||||
AGPIO(GPIO_HPMA_RX), // Honeywell HPMA115S0 Serial interface
|
||||
#endif
|
||||
#ifdef USE_PMS5003
|
||||
AGPIO(GPIO_PMS5003_TX), // Plantower PMS5003 Serial interface
|
||||
AGPIO(GPIO_PMS5003_RX), // Plantower PMS5003 Serial interface
|
||||
#endif
|
||||
#if defined(USE_TX20_WIND_SENSOR) || defined(USE_TX23_WIND_SENSOR)
|
||||
AGPIO(GPIO_TX2X_TXD_BLACK), // TX20/TX23 Transmission Pin
|
||||
#endif
|
||||
#ifdef USE_MP3_PLAYER
|
||||
AGPIO(GPIO_MP3_DFR562), // RB-DFR-562, DFPlayer Mini MP3 Player Serial interface
|
||||
#endif
|
||||
#ifdef USE_AZ7798
|
||||
AGPIO(GPIO_AZ_TXD), // AZ-Instrument 7798 CO2 datalogger Serial interface
|
||||
AGPIO(GPIO_AZ_RXD), // AZ-Instrument 7798 CO2 datalogger Serial interface
|
||||
#endif
|
||||
#ifdef USE_PN532_HSU
|
||||
AGPIO(GPIO_PN532_TXD), // PN532 HSU Tx
|
||||
AGPIO(GPIO_PN532_RXD), // PN532 HSU Rx
|
||||
#endif
|
||||
#ifdef USE_TASMOTA_SLAVE
|
||||
AGPIO(GPIO_TASMOTASLAVE_TXD), // Tasmota Slave TX
|
||||
AGPIO(GPIO_TASMOTASLAVE_RXD), // Tasmota Slave RX
|
||||
AGPIO(GPIO_TASMOTASLAVE_RST), // Tasmota Slave Reset
|
||||
AGPIO(GPIO_TASMOTASLAVE_RST_INV), // Tasmota Slave Reset Inverted
|
||||
#endif
|
||||
#ifdef USE_RDM6300
|
||||
AGPIO(GPIO_RDM6300_RX),
|
||||
#endif
|
||||
#ifdef USE_IBEACON
|
||||
AGPIO(GPIO_IBEACON_RX),
|
||||
AGPIO(GPIO_IBEACON_TX),
|
||||
#endif
|
||||
#ifdef USE_GPS
|
||||
AGPIO(GPIO_GPS_RX), // GPS serial interface
|
||||
AGPIO(GPIO_GPS_TX), // GPS serial interface
|
||||
#endif
|
||||
#ifdef USE_HM10
|
||||
AGPIO(GPIO_HM10_RX), // GPS serial interface
|
||||
AGPIO(GPIO_HM10_TX), // GPS serial interface
|
||||
#endif
|
||||
|
||||
#ifdef USE_MGC3130
|
||||
AGPIO(GPIO_MGC3130_XFER),
|
||||
AGPIO(GPIO_MGC3130_RESET),
|
||||
#endif
|
||||
#ifdef USE_MAX31855
|
||||
AGPIO(GPIO_MAX31855CS), // MAX31855 Serial interface
|
||||
AGPIO(GPIO_MAX31855CLK), // MAX31855 Serial interface
|
||||
AGPIO(GPIO_MAX31855DO), // MAX31855 Serial interface
|
||||
#endif
|
||||
#ifdef ROTARY_V1
|
||||
AGPIO(GPIO_ROT1A), // Rotary switch1 A Pin
|
||||
AGPIO(GPIO_ROT1B), // Rotary switch1 B Pin
|
||||
AGPIO(GPIO_ROT2A), // Rotary switch2 A Pin
|
||||
AGPIO(GPIO_ROT2B), // Rotary switch2 B Pin
|
||||
#endif
|
||||
#ifdef USE_HRE
|
||||
AGPIO(GPIO_HRE_CLOCK),
|
||||
AGPIO(GPIO_HRE_DATA),
|
||||
#endif
|
||||
#ifdef USE_A4988_STEPPER
|
||||
AGPIO(GPIO_A4988_DIR), // A4988 direction pin
|
||||
AGPIO(GPIO_A4988_STP), // A4988 step pin
|
||||
// folowing are not mandatory
|
||||
AGPIO(GPIO_A4988_ENA), // A4988 enabled pin
|
||||
AGPIO(GPIO_A4988_MS1), // A4988 microstep pin1
|
||||
AGPIO(GPIO_A4988_MS2), // A4988 microstep pin2
|
||||
AGPIO(GPIO_A4988_MS3), // A4988 microstep pin3
|
||||
#endif
|
||||
#ifdef USE_DEEPSLEEP
|
||||
AGPIO(GPIO_DEEPSLEEP),
|
||||
#endif
|
||||
#ifdef USE_KEELOQ
|
||||
AGPIO(GPIO_CC1101_GDO0), // CC1101 pin for RX
|
||||
AGPIO(GPIO_CC1101_GDO2), // CC1101 pin for RX
|
||||
#endif
|
||||
#ifdef USE_HRXL
|
||||
AGPIO(GPIO_HRXL_RX),
|
||||
#endif
|
||||
#ifdef USE_AS3935
|
||||
AGPIO(GPIO_AS3935),
|
||||
#endif
|
||||
/*
|
||||
#ifndef USE_ADC_VCC
|
||||
AGPIO(ADC0_INPUT), // Analog input
|
||||
AGPIO(ADC0_TEMP), // Thermistor
|
||||
AGPIO(ADC0_LIGHT), // Light sensor
|
||||
AGPIO(ADC0_BUTTON), // Button
|
||||
AGPIO(ADC0_BUTTON_INV),
|
||||
AGPIO(ADC0_RANGE), // Range
|
||||
AGPIO(ADC0_CT_POWER), // Current
|
||||
#endif
|
||||
*/
|
||||
#ifdef USE_WEBCAM
|
||||
AGPIO(GPIO_WEBCAM_PWDN),
|
||||
AGPIO(GPIO_WEBCAM_RESET),
|
||||
AGPIO(GPIO_WEBCAM_XCLK),
|
||||
AGPIO(GPIO_WEBCAM_SIOD),
|
||||
AGPIO(GPIO_WEBCAM_SIOC),
|
||||
AGPIO(GPIO_WEBCAM_Y9),
|
||||
AGPIO(GPIO_WEBCAM_Y8),
|
||||
AGPIO(GPIO_WEBCAM_Y7),
|
||||
AGPIO(GPIO_WEBCAM_Y6),
|
||||
AGPIO(GPIO_WEBCAM_Y5),
|
||||
AGPIO(GPIO_WEBCAM_Y4),
|
||||
AGPIO(GPIO_WEBCAM_Y3),
|
||||
AGPIO(GPIO_WEBCAM_Y2),
|
||||
AGPIO(GPIO_WEBCAM_VSYNC),
|
||||
AGPIO(GPIO_WEBCAM_HREF),
|
||||
AGPIO(GPIO_WEBCAM_PCLK),
|
||||
AGPIO(GPIO_WEBCAM_PSCLK),
|
||||
AGPIO(GPIO_WEBCAM_HSD1),
|
||||
AGPIO(GPIO_WEBCAM_HSD2),
|
||||
AGPIO(GPIO_WEBCAM_HSD3),
|
||||
AGPIO(GPIO_WEBCAM_PSRCS),
|
||||
#endif
|
||||
};
|
||||
|
||||
//********************************************************************************************
|
||||
|
||||
#define MAX_GPIO_PIN 40 // Number of supported GPIO
|
||||
#define MIN_FLASH_PINS 4 // Number of flash chip pins unusable for configuration (GPIO6, 7, 8 and 11)
|
||||
#define MAX_USER_PINS 36 // MAX_GPIO_PIN - MIN_FLASH_PINS
|
||||
#define WEMOS_MODULE 0 // Wemos module
|
||||
|
||||
// 0 1 2 3 4 5 6 7 8 9101112131415161718192021222324252627282930313233343536373839
|
||||
const char PINS_WEMOS[] PROGMEM = "IOTXIORXIOIOflashcFLFLolIOIOIOIOIOIOIOIOIOIOIOIOIOIOIOIOIOIOIOIOIOIOA6A7A0IoIoA3";
|
||||
|
||||
//********************************************************************************************
|
||||
|
||||
typedef struct MYIO {
|
||||
uint16_t io[MAX_GPIO_PIN];
|
||||
} myio; // 40 * 2 = 80 bytes
|
||||
|
||||
typedef struct MYCFGIO {
|
||||
uint16_t io[MAX_USER_PINS];
|
||||
} mycfgio; // 36 * 2 = 72 bytes
|
||||
|
||||
#define GPIO_FLAG_USED 0 // Currently no flags used
|
||||
|
||||
typedef union {
|
||||
uint16_t data;
|
||||
struct {
|
||||
uint16_t spare00 : 1;
|
||||
uint16_t spare01 : 1;
|
||||
uint16_t spare02 : 1;
|
||||
uint16_t spare03 : 1;
|
||||
uint16_t spare04 : 1;
|
||||
uint16_t spare05 : 1;
|
||||
uint16_t spare06 : 1;
|
||||
uint16_t spare07 : 1;
|
||||
uint16_t spare08 : 1;
|
||||
uint16_t spare09 : 1;
|
||||
uint16_t spare10 : 1;
|
||||
uint16_t spare11 : 1;
|
||||
uint16_t spare12 : 1;
|
||||
uint16_t spare13 : 1;
|
||||
uint16_t spare14 : 1;
|
||||
uint16_t spare15 : 1;
|
||||
};
|
||||
} gpio_flag; // 2 bytes
|
||||
|
||||
typedef struct MYTMPLT {
|
||||
mycfgio gp; // 72 bytes
|
||||
gpio_flag flag; // 2 bytes
|
||||
} mytmplt; // 74 bytes
|
||||
|
||||
/********************************************************************************************/
|
||||
// Supported hardware modules
|
||||
enum SupportedModules {
|
||||
WEMOS, ESP32_CAM_AITHINKER,
|
||||
MAXMODULE};
|
||||
|
||||
#define USER_MODULE 255
|
||||
|
||||
const char kModuleNames[] PROGMEM =
|
||||
"ESP32-DevKit|ESP32 Cam AiThinker";
|
||||
|
||||
@ -58,48 +602,48 @@ const uint8_t kModuleNiceList[MAXMODULE] PROGMEM = {
|
||||
};
|
||||
|
||||
const mytmplt kModules PROGMEM =
|
||||
{ // WEMOS - Espressif ESP32-DevKitC - Any ESP32 device like WeMos and NodeMCU hardware (ESP32)
|
||||
GPIO_USER, //0 (I)O GPIO0, ADC2_CH1, TOUCH1, RTC_GPIO11, CLK_OUT1, EMAC_TX_CLK
|
||||
GPIO_USER, //1 IO TXD0 GPIO1, U0TXD, CLK_OUT3, EMAC_RXD2
|
||||
GPIO_USER, //2 IO GPIO2, ADC2_CH2, TOUCH2, RTC_GPIO12, HSPIWP, HS2_DATA0, SD_DATA0
|
||||
GPIO_USER, //3 IO RXD0 GPIO3, U0RXD, CLK_OUT2
|
||||
GPIO_USER, //4 IO GPIO4, ADC2_CH0, TOUCH0, RTC_GPIO10, HSPIHD, HS2_DATA1, SD_DATA1, EMAC_TX_ER
|
||||
GPIO_USER, //5 IO GPIO5, VSPICS0, HS1_DATA6, EMAC_RX_CLK
|
||||
//6 IO GPIO6, Flash CLK
|
||||
//7 IO GPIO7, Flash D0
|
||||
//8 IO GPIO8, Flash D1
|
||||
GPIO_USER, //9 IO GPIO9, Flash D2, U1RXD
|
||||
GPIO_USER, //10 IO GPIO10, Flash D3, U1TXD
|
||||
//11 IO GPIO11, Flash CMD
|
||||
GPIO_USER, //12 (I)O GPIO12, ADC2_CH5, TOUCH5, RTC_GPIO15, MTDI, HSPIQ, HS2_DATA2, SD_DATA2, EMAC_TXD3 (If driven High, flash voltage (VDD_SDIO) is 1.8V not default 3.3V. Has internal pull-down, so unconnected = Low = 3.3V. May prevent flashing and/or booting if 3.3V flash is connected and pulled high. See ESP32 datasheet for more details.)
|
||||
GPIO_USER, //13 IO GPIO13, ADC2_CH4, TOUCH4, RTC_GPIO14, MTCK, HSPID, HS2_DATA3, SD_DATA3, EMAC_RX_ER
|
||||
GPIO_USER, //14 IO GPIO14, ADC2_CH6, TOUCH6, RTC_GPIO16, MTMS, HSPICLK, HS2_CLK, SD_CLK, EMAC_TXD2
|
||||
GPIO_USER, //15 (I)O GPIO15, ADC2_CH3, TOUCH3, MTDO, HSPICS0, RTC_GPIO13, HS2_CMD, SD_CMD, EMAC_RXD3 (If driven Low, silences boot messages from normal boot. Has internal pull-up, so unconnected = High = normal output.)
|
||||
GPIO_USER, //16 IO GPIO16, HS1_DATA4, U2RXD, EMAC_CLK_OUT
|
||||
GPIO_USER, //17 IO GPIO17, HS1_DATA5, U2TXD, EMAC_CLK_OUT_180
|
||||
GPIO_USER, //18 IO GPIO18, VSPICLK, HS1_DATA7
|
||||
GPIO_USER, //19 IO GPIO19, VSPIQ, U0CTS, EMAC_TXD0
|
||||
0, //20
|
||||
GPIO_USER, //21 IO GPIO21, VSPIHD, EMAC_TX_EN
|
||||
GPIO_USER, //22 IO LED GPIO22, VSPIWP, U0RTS, EMAC_TXD1
|
||||
GPIO_USER, //23 IO GPIO23, VSPID, HS1_STROBE
|
||||
0, //24
|
||||
GPIO_USER, //25 IO GPIO25, DAC_1, ADC2_CH8, RTC_GPIO6, EMAC_RXD0
|
||||
GPIO_USER, //26 IO GPIO26, DAC_2, ADC2_CH9, RTC_GPIO7, EMAC_RXD1
|
||||
GPIO_USER, //27 IO GPIO27, ADC2_CH7, TOUCH7, RTC_GPIO17, EMAC_RX_DV
|
||||
0, //28
|
||||
0, //29
|
||||
0, //30
|
||||
0, //31
|
||||
GPIO_USER, //32 IO GPIO32, XTAL_32K_P (32.768 kHz crystal oscillator input), ADC1_CH4, TOUCH9, RTC_GPIO9
|
||||
GPIO_USER, //33 IO GPIO33, XTAL_32K_N (32.768 kHz crystal oscillator output), ADC1_CH5, TOUCH8, RTC_GPIO8
|
||||
GPIO_USER, //34 I NO PULLUP GPIO34, ADC1_CH6, RTC_GPIO4
|
||||
GPIO_USER, //35 I NO PULLUP GPIO35, ADC1_CH7, RTC_GPIO5
|
||||
GPIO_USER, //36 I NO PULLUP GPIO36, SENSOR_VP, ADC_H, ADC1_CH0, RTC_GPIO0
|
||||
0, //37 NO PULLUP
|
||||
0, //38 NO PULLUP
|
||||
GPIO_USER, //39 I NO PULLUP GPIO39, SENSOR_VN, ADC1_CH3, ADC_H, RTC_GPIO3
|
||||
0 // Flag
|
||||
{ // WEMOS - Espressif ESP32-DevKitC - Any ESP32 device like WeMos and NodeMCU hardware (ESP32)
|
||||
AGPIO(GPIO_USER), // 0 (I)O GPIO0, ADC2_CH1, TOUCH1, RTC_GPIO11, CLK_OUT1, EMAC_TX_CLK
|
||||
AGPIO(GPIO_USER), // 1 IO TXD0 GPIO1, U0TXD, CLK_OUT3, EMAC_RXD2
|
||||
AGPIO(GPIO_USER), // 2 IO GPIO2, ADC2_CH2, TOUCH2, RTC_GPIO12, HSPIWP, HS2_DATA0, SD_DATA0
|
||||
AGPIO(GPIO_USER), // 3 IO RXD0 GPIO3, U0RXD, CLK_OUT2
|
||||
AGPIO(GPIO_USER), // 4 IO GPIO4, ADC2_CH0, TOUCH0, RTC_GPIO10, HSPIHD, HS2_DATA1, SD_DATA1, EMAC_TX_ER
|
||||
AGPIO(GPIO_USER), // 5 IO GPIO5, VSPICS0, HS1_DATA6, EMAC_RX_CLK
|
||||
// 6 IO GPIO6, Flash CLK
|
||||
// 7 IO GPIO7, Flash D0
|
||||
// 8 IO GPIO8, Flash D1
|
||||
AGPIO(GPIO_USER), // 9 IO GPIO9, Flash D2, U1RXD
|
||||
AGPIO(GPIO_USER), // 10 IO GPIO10, Flash D3, U1TXD
|
||||
// 11 IO GPIO11, Flash CMD
|
||||
AGPIO(GPIO_USER), // 12 (I)O GPIO12, ADC2_CH5, TOUCH5, RTC_GPIO15, MTDI, HSPIQ, HS2_DATA2, SD_DATA2, EMAC_TXD3 (If driven High, flash voltage (VDD_SDIO) is 1.8V not default 3.3V. Has internal pull-down, so unconnected = Low = 3.3V. May prevent flashing and/or booting if 3.3V flash is connected and pulled high. See ESP32 datasheet for more details.)
|
||||
AGPIO(GPIO_USER), // 13 IO GPIO13, ADC2_CH4, TOUCH4, RTC_GPIO14, MTCK, HSPID, HS2_DATA3, SD_DATA3, EMAC_RX_ER
|
||||
AGPIO(GPIO_USER), // 14 IO GPIO14, ADC2_CH6, TOUCH6, RTC_GPIO16, MTMS, HSPICLK, HS2_CLK, SD_CLK, EMAC_TXD2
|
||||
AGPIO(GPIO_USER), // 15 (I)O GPIO15, ADC2_CH3, TOUCH3, MTDO, HSPICS0, RTC_GPIO13, HS2_CMD, SD_CMD, EMAC_RXD3 (If driven Low, silences boot messages from normal boot. Has internal pull-up, so unconnected = High = normal output.)
|
||||
AGPIO(GPIO_USER), // 16 IO GPIO16, HS1_DATA4, U2RXD, EMAC_CLK_OUT
|
||||
AGPIO(GPIO_USER), // 17 IO GPIO17, HS1_DATA5, U2TXD, EMAC_CLK_OUT_180
|
||||
AGPIO(GPIO_USER), // 18 IO GPIO18, VSPICLK, HS1_DATA7
|
||||
AGPIO(GPIO_USER), // 19 IO GPIO19, VSPIQ, U0CTS, EMAC_TXD0
|
||||
0, // 20
|
||||
AGPIO(GPIO_USER), // 21 IO GPIO21, VSPIHD, EMAC_TX_EN
|
||||
AGPIO(GPIO_USER), // 22 IO LED GPIO22, VSPIWP, U0RTS, EMAC_TXD1
|
||||
AGPIO(GPIO_USER), // 23 IO GPIO23, VSPID, HS1_STROBE
|
||||
0, // 24
|
||||
AGPIO(GPIO_USER), // 25 IO GPIO25, DAC_1, ADC2_CH8, RTC_GPIO6, EMAC_RXD0
|
||||
AGPIO(GPIO_USER), // 26 IO GPIO26, DAC_2, ADC2_CH9, RTC_GPIO7, EMAC_RXD1
|
||||
AGPIO(GPIO_USER), // 27 IO GPIO27, ADC2_CH7, TOUCH7, RTC_GPIO17, EMAC_RX_DV
|
||||
0, // 28
|
||||
0, // 29
|
||||
0, // 30
|
||||
0, // 31
|
||||
AGPIO(GPIO_USER), // 32 IO GPIO32, XTAL_32K_P (32.768 kHz crystal oscillator input), ADC1_CH4, TOUCH9, RTC_GPIO9
|
||||
AGPIO(GPIO_USER), // 33 IO GPIO33, XTAL_32K_N (32.768 kHz crystal oscillator output), ADC1_CH5, TOUCH8, RTC_GPIO8
|
||||
AGPIO(GPIO_USER), // 34 I NO PULLUP GPIO34, ADC1_CH6, RTC_GPIO4
|
||||
AGPIO(GPIO_USER), // 35 I NO PULLUP GPIO35, ADC1_CH7, RTC_GPIO5
|
||||
AGPIO(GPIO_USER), // 36 I NO PULLUP GPIO36, SENSOR_VP, ADC_H, ADC1_CH0, RTC_GPIO0
|
||||
0, // 37 NO PULLUP
|
||||
0, // 38 NO PULLUP
|
||||
AGPIO(GPIO_USER), // 39 I NO PULLUP GPIO39, SENSOR_VN, ADC1_CH3, ADC_H, RTC_GPIO3
|
||||
0 // Flag
|
||||
};
|
||||
|
||||
#endif // ESP32
|
||||
|
@ -231,12 +231,38 @@ const char HTTP_MODULE_TEMPLATE_REPLACE[] PROGMEM =
|
||||
"}2%d'>%s (%d}3"; // }2 and }3 are used in below os.replace
|
||||
|
||||
const char HTTP_SCRIPT_MODULE_TEMPLATE[] PROGMEM =
|
||||
#ifdef ESP8266
|
||||
"var os;"
|
||||
"function sk(s,g){" // s = value, g = id and name
|
||||
"var o=os.replace(/}2/g,\"<option value='\").replace(/}3/g,\")</option>\");"
|
||||
"eb('g'+g).innerHTML=o;"
|
||||
"eb('g'+g).value=s;"
|
||||
"}";
|
||||
#else // ESP32
|
||||
"var os,hs;"
|
||||
"function ce(i,q){" // Create index select
|
||||
"var o=document.createElement('option');"
|
||||
"o.textContent=i;"
|
||||
"q.appendChild(o);"
|
||||
"}"
|
||||
"function ot(g,s){" // g = id and name, s = value
|
||||
"var p,l,t=qs('#h'+g),u=s&0x001f;"
|
||||
"l=t.options.length;" // Remove current options
|
||||
"for(i=l;i;i--){p=t.options[i-1].parentNode;p.removeChild(t.options[i-1]);}"
|
||||
"s>>=5;" // Add options
|
||||
"for(i=1;i<=hs[s];i++){ce((i<10)?(' '+i):i,t);}"
|
||||
"eb('h'+g).value=u+1;" // Set selected value
|
||||
"t.style.visibility=(hs[s]>0)?'':'hidden';"
|
||||
"}"
|
||||
"function sk(s,g){" // s = value, g = id and name
|
||||
"var o=os.replace(/}2/g,\"<option value='\").replace(/}3/g,\")</option>\");"
|
||||
"eb('g'+g).innerHTML=o;"
|
||||
"eb('g'+g).value=(g<99)?s&0xffe0:s;"
|
||||
"if(g<99){ot(g,s);}"
|
||||
"}";
|
||||
#endif // ESP8266 - ESP32
|
||||
|
||||
const char HTTP_SCRIPT_TEMPLATE[] PROGMEM =
|
||||
"function ld(u,f){"
|
||||
"var x=new XMLHttpRequest();"
|
||||
"x.onreadystatechange=function(){"
|
||||
@ -246,9 +272,7 @@ const char HTTP_SCRIPT_MODULE_TEMPLATE[] PROGMEM =
|
||||
"};"
|
||||
"x.open('GET',u,true);"
|
||||
"x.send();"
|
||||
"}";
|
||||
|
||||
const char HTTP_SCRIPT_TEMPLATE[] PROGMEM =
|
||||
"}"
|
||||
"var c;" // Need a global for BASE
|
||||
"function x1(b){"
|
||||
"var i,j,g,k,o;"
|
||||
@ -260,7 +284,6 @@ const char HTTP_SCRIPT_TEMPLATE[] PROGMEM =
|
||||
"g=o.shift().split(',');" // GPIO - Array separator
|
||||
"os=\""; // }2'0'>None (0)}3}2'17'>Button1 (17)}3...
|
||||
const char HTTP_SCRIPT_TEMPLATE2[] PROGMEM =
|
||||
"\";"
|
||||
"j=0;"
|
||||
"for(i=0;i<" STR(MAX_USER_PINS) ";i++){" // Supports 13 GPIOs
|
||||
"if(6==i){j=9;}"
|
||||
@ -268,12 +291,12 @@ const char HTTP_SCRIPT_TEMPLATE2[] PROGMEM =
|
||||
"sk(g[i],j);" // Set GPIO
|
||||
"j++;"
|
||||
"}"
|
||||
"g=o.shift();" // FLAG
|
||||
"os=\""; // }2'0'>None (0)}3}2'17'>Analog (17)}3...
|
||||
"g=o.shift();"; // FLAG
|
||||
const char HTTP_SCRIPT_TEMPLATE3[] PROGMEM =
|
||||
"\";"
|
||||
"sk(g&15," STR(ADC0_PIN) ");" // Set ADC0
|
||||
"g>>=4;"
|
||||
"g>>=4;";
|
||||
const char HTTP_SCRIPT_TEMPLATE4[] PROGMEM =
|
||||
"for(i=0;i<" STR(GPIO_FLAG_USED) ";i++){"
|
||||
"p=(g>>i)&1;"
|
||||
"eb('c'+i).checked=p;" // Set FLAG checkboxes
|
||||
@ -288,10 +311,9 @@ const char HTTP_SCRIPT_TEMPLATE3[] PROGMEM =
|
||||
"var a='tp?t='+t;"
|
||||
"ld(a,x1);" // ?t related to WebGetArg("t", stemp, sizeof(stemp));
|
||||
"}"
|
||||
|
||||
"function sl(){"
|
||||
"os=\""; // }2'0'>Sonoff Basic (1)}3...
|
||||
const char HTTP_SCRIPT_TEMPLATE4[] PROGMEM =
|
||||
const char HTTP_SCRIPT_TEMPLATE5[] PROGMEM =
|
||||
"\";"
|
||||
"sk(" STR(WEMOS_MODULE) ",99);" // 17 = WEMOS
|
||||
"st(" STR(USER_MODULE) ");"
|
||||
@ -1065,7 +1087,7 @@ void HandleRoot(void)
|
||||
|
||||
WSContentSend_P(HTTP_MSG_SLIDER_GRADIENT, // Hue
|
||||
"b", // b - Unique HTML id
|
||||
"#800", "#f00 5%,#ff0 20%,#0f0 35%,#0ff 50%,#00f 65%,#f0f 80%,#f00 95%,#800", // Hue colors
|
||||
"#800", PSTR("#f00 5%,#ff0 20%,#0f0 35%,#0ff 50%,#00f 65%,#f0f 80%,#f00 95%,#800"), // Hue colors
|
||||
2, // sl2 - Unique range HTML id - Used as source for Saturation end color
|
||||
1, 359, // Range valid Hue
|
||||
hue,
|
||||
@ -1429,14 +1451,53 @@ void HandleTemplateConfiguration(void)
|
||||
WSContentSend_P(HTTP_SCRIPT_MODULE_TEMPLATE);
|
||||
|
||||
WSContentSend_P(HTTP_SCRIPT_TEMPLATE);
|
||||
for (uint32_t i = 0; i < sizeof(kGpioNiceList); i++) { // GPIO: }2'0'>None (0)}3}2'17'>Button1 (17)}3...
|
||||
for (uint32_t i = 0; i < ARRAY_SIZE(kGpioNiceList); i++) { // GPIO: }2'0'>None (0)}3}2'17'>Button1 (17)}3...
|
||||
if (1 == i) {
|
||||
WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE, GPIO_USER, D_SENSOR_USER, GPIO_USER); // }2'255'>User (255)}3
|
||||
WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE, AGPIO(GPIO_USER), D_SENSOR_USER, AGPIO(GPIO_USER)); // }2'255'>User (255)}3
|
||||
}
|
||||
#ifdef ESP8266
|
||||
uint32_t midx = pgm_read_byte(kGpioNiceList + i);
|
||||
WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE, midx, GetTextIndexed(stemp, sizeof(stemp), midx, kSensorNames), midx);
|
||||
uint32_t ridx = midx;
|
||||
#else // ESP32
|
||||
uint32_t ridx = pgm_read_word(kGpioNiceList + i) & 0xFFE0;
|
||||
uint32_t midx = ridx >> 5;
|
||||
#endif // ESP8266 - ESP32
|
||||
WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE, ridx, GetTextIndexed(stemp, sizeof(stemp), midx, kSensorNames), ridx);
|
||||
}
|
||||
WSContentSend_P(PSTR("\";"));
|
||||
|
||||
#ifdef ESP32
|
||||
WSContentSend_P(PSTR("hs=["));
|
||||
bool first_done = false;
|
||||
/*
|
||||
for (uint32_t i = 0; i < ARRAY_SIZE(kGpioNiceList); i++) {
|
||||
uint32_t midx = pgm_read_word(kGpioNiceList + i) & 0x001F;
|
||||
if (first_done) { WSContentSend_P(PSTR(",")); }
|
||||
WSContentSend_P(PSTR("%d"), midx);
|
||||
first_done = true;
|
||||
}
|
||||
*/
|
||||
uint32_t j = 0;
|
||||
for (uint32_t i = 0; i < GPIO_SENSOR_END; i++) {
|
||||
uint32_t midx = pgm_read_word(kGpioNiceList + j);
|
||||
if ((midx >> 5) != i) {
|
||||
midx = 0;
|
||||
} else {
|
||||
midx &= 0x001F;
|
||||
j++;
|
||||
}
|
||||
if (first_done) { WSContentSend_P(PSTR(",")); }
|
||||
WSContentSend_P(PSTR("%d"), midx);
|
||||
first_done = true;
|
||||
}
|
||||
|
||||
WSContentSend_P(PSTR("];"));
|
||||
#endif // ESP32
|
||||
|
||||
WSContentSend_P(HTTP_SCRIPT_TEMPLATE2);
|
||||
|
||||
#ifdef ESP8266
|
||||
WSContentSend_P(PSTR("os=\""));
|
||||
for (uint32_t i = 0; i < ADC0_END; i++) { // FLAG: }2'0'>None (0)}3}2'17'>Analog (17)}3...
|
||||
if (1 == i) {
|
||||
WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE, ADC0_USER, D_SENSOR_USER, ADC0_USER); // }2'15'>User (15)}3
|
||||
@ -1444,11 +1505,14 @@ void HandleTemplateConfiguration(void)
|
||||
WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE, i, GetTextIndexed(stemp, sizeof(stemp), i, kAdc0Names), i);
|
||||
}
|
||||
WSContentSend_P(HTTP_SCRIPT_TEMPLATE3);
|
||||
#endif
|
||||
|
||||
WSContentSend_P(HTTP_SCRIPT_TEMPLATE4);
|
||||
for (uint32_t i = 0; i < sizeof(kModuleNiceList); i++) { // "}2'%d'>%s (%d)}3" - "}2'0'>Sonoff Basic (1)}3"
|
||||
uint32_t midx = pgm_read_byte(kModuleNiceList + i);
|
||||
WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE, midx, AnyModuleName(midx).c_str(), midx +1);
|
||||
}
|
||||
WSContentSend_P(HTTP_SCRIPT_TEMPLATE4);
|
||||
WSContentSend_P(HTTP_SCRIPT_TEMPLATE5);
|
||||
|
||||
WSContentSendStyle();
|
||||
WSContentSend_P(HTTP_FORM_TEMPLATE);
|
||||
@ -1460,18 +1524,30 @@ void HandleTemplateConfiguration(void)
|
||||
WSContentSend_P(HTTP_TABLE100);
|
||||
for (uint32_t i = 0; i < MAX_GPIO_PIN; i++) {
|
||||
if (!FlashPin(i)) {
|
||||
#ifdef ESP8266
|
||||
WSContentSend_P(PSTR("<tr><td><b><font color='#%06x'>" D_GPIO "%d</font></b></td><td%s><select id='g%d'></select></td></tr>"),
|
||||
((9==i)||(10==i)) ? WebColor(COL_TEXT_WARNING) : WebColor(COL_TEXT), i, (0==i) ? " style='width:200px'" : "", i);
|
||||
#else // ESP32
|
||||
WSContentSend_P(PSTR("<tr><td><b><font color='#%06x'>" D_GPIO "%d</font></b></td><td%s><select id='g%d' onchange='ot(%d,this.value)'></select></td>"),
|
||||
((9==i)||(10==i)) ? WebColor(COL_TEXT_WARNING) : WebColor(COL_TEXT), i, (0==i) ? " style='width:150px'" : "", i, i);
|
||||
WSContentSend_P(PSTR("<td style='width:50px'><select id='h%d'></select></td></tr>"), i);
|
||||
#endif // ESP8266
|
||||
}
|
||||
}
|
||||
#ifdef ESP8266
|
||||
WSContentSend_P(PSTR("<tr><td><b><font color='#%06x'>" D_ADC "0</font></b></td><td><select id='g17'></select></td></tr>"), WebColor(COL_TEXT));
|
||||
#endif
|
||||
WSContentSend_P(PSTR("</table>"));
|
||||
|
||||
gpio_flag flag = ModuleFlag();
|
||||
#ifdef ESP8266
|
||||
if (flag.data > ADC0_USER) {
|
||||
#else // ESP32
|
||||
if (flag.data) {
|
||||
#endif // ESP32
|
||||
WSContentSend_P(HTTP_FORM_TEMPLATE_FLAG);
|
||||
}
|
||||
|
||||
WSContentSend_P(HTTP_FORM_END);
|
||||
WSContentSpaceButton(BUTTON_CONFIGURATION);
|
||||
WSContentStop();
|
||||
@ -1492,13 +1568,25 @@ void TemplateSaveSettings(void)
|
||||
if (8 == i) { j = 12; }
|
||||
snprintf_P(webindex, sizeof(webindex), PSTR("g%d"), j);
|
||||
WebGetArg(webindex, tmp, sizeof(tmp)); // GPIO
|
||||
uint8_t gpio = atoi(tmp);
|
||||
uint32_t gpio = atoi(tmp);
|
||||
#ifdef ESP32
|
||||
char tmp2[8]; // WebGetArg numbers only
|
||||
char webindex2[5]; // WebGetArg name
|
||||
snprintf_P(webindex2, sizeof(webindex2), PSTR("h%d"), j);
|
||||
WebGetArg(webindex2, tmp2, sizeof(tmp2));
|
||||
uint32_t value2 = (!strlen(tmp2)) ? 0 : atoi(tmp2) -1;
|
||||
gpio += value2;
|
||||
#endif // ESP32
|
||||
snprintf_P(svalue, sizeof(svalue), PSTR("%s%s%d"), svalue, (i>0)?",":"", gpio);
|
||||
j++;
|
||||
}
|
||||
|
||||
#ifdef ESP8266
|
||||
WebGetArg("g" STR(ADC0_PIN), tmp, sizeof(tmp)); // FLAG - ADC0
|
||||
uint32_t flag = atoi(tmp);
|
||||
#else // ESP32
|
||||
uint32_t flag = 0;
|
||||
#endif // ESP32
|
||||
for (uint32_t i = 0; i < GPIO_FLAG_USED; i++) {
|
||||
snprintf_P(webindex, sizeof(webindex), PSTR("c%d"), i);
|
||||
uint32_t state = Webserver->hasArg(webindex) << i +4; // FLAG
|
||||
@ -1546,18 +1634,55 @@ void HandleModuleConfiguration(void)
|
||||
WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE, midx, AnyModuleName(midx).c_str(), vidx);
|
||||
}
|
||||
WSContentSend_P(PSTR("\";sk(%d,99);os=\""), Settings.module);
|
||||
for (uint32_t i = 0; i < sizeof(kGpioNiceList); i++) {
|
||||
for (uint32_t i = 0; i < ARRAY_SIZE(kGpioNiceList); i++) {
|
||||
#ifdef ESP8266
|
||||
midx = pgm_read_byte(kGpioNiceList + i);
|
||||
uint32_t ridx = midx;
|
||||
#else // ESP32
|
||||
uint32_t ridx = pgm_read_word(kGpioNiceList + i) & 0xFFE0;
|
||||
midx = ridx >> 5;
|
||||
#endif // ESP8266 - ESP32
|
||||
if (!GetUsedInModule(midx, cmodule.io)) {
|
||||
WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE, midx, GetTextIndexed(stemp, sizeof(stemp), midx, kSensorNames), midx);
|
||||
WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE, ridx, GetTextIndexed(stemp, sizeof(stemp), midx, kSensorNames), ridx);
|
||||
}
|
||||
}
|
||||
WSContentSend_P(PSTR("\";"));
|
||||
|
||||
#ifdef ESP32
|
||||
WSContentSend_P(PSTR("hs=["));
|
||||
bool first_done = false;
|
||||
/*
|
||||
for (uint32_t i = 0; i < ARRAY_SIZE(kGpioNiceList); i++) {
|
||||
midx = pgm_read_word(kGpioNiceList + i) & 0x001F;
|
||||
if (first_done) { WSContentSend_P(PSTR(",")); }
|
||||
WSContentSend_P(PSTR("%d"), midx);
|
||||
first_done = true;
|
||||
}
|
||||
*/
|
||||
uint32_t j = 0;
|
||||
for (uint32_t i = 0; i < GPIO_SENSOR_END; i++) {
|
||||
midx = pgm_read_word(kGpioNiceList + j);
|
||||
if ((midx >> 5) != i) {
|
||||
midx = 0;
|
||||
} else {
|
||||
midx &= 0x001F;
|
||||
j++;
|
||||
}
|
||||
if (first_done) { WSContentSend_P(PSTR(",")); }
|
||||
WSContentSend_P(PSTR("%d"), midx);
|
||||
first_done = true;
|
||||
}
|
||||
|
||||
WSContentSend_P(PSTR("];"));
|
||||
#endif // ESP32
|
||||
|
||||
for (uint32_t i = 0; i < ARRAY_SIZE(cmodule.io); i++) {
|
||||
if (ValidGPIO(i, cmodule.io[i])) {
|
||||
WSContentSend_P(PSTR("sk(%d,%d);"), my_module.io[i], i); // g0 - g16
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ESP8266
|
||||
#ifndef USE_ADC_VCC
|
||||
WSContentSend_P(PSTR("os=\""));
|
||||
for (uint32_t j = 0; j < ADC0_END; j++) {
|
||||
@ -1565,6 +1690,8 @@ void HandleModuleConfiguration(void)
|
||||
}
|
||||
WSContentSend_P(PSTR("\";sk(%d," STR(ADC0_PIN) ");"), Settings.my_adc0);
|
||||
#endif // USE_ADC_VCC
|
||||
#endif // ESP8266 - ESP32
|
||||
|
||||
WSContentSend_P(PSTR("}wl(sl);"));
|
||||
|
||||
WSContentSendStyle();
|
||||
@ -1578,8 +1705,9 @@ void HandleModuleConfiguration(void)
|
||||
WSContentSend_P(PSTR("<tr><td style='width:190px'>%s <b>" D_GPIO "%d</b> %s</td><td style='width:176px'><select id='g%d'></select></td></tr>"),
|
||||
(WEMOS==my_module_type)?stemp:"", i, (0==i)? D_SENSOR_BUTTON "1":(1==i)? D_SERIAL_OUT :(3==i)? D_SERIAL_IN :((9==i)||(10==i))? sesp8285 :(12==i)? D_SENSOR_RELAY "1":(13==i)? D_SENSOR_LED "1i":(14==i)? D_SENSOR :"", i);
|
||||
#else // ESP32
|
||||
WSContentSend_P(PSTR("<tr><td style='width:140px'>%s <b>" D_GPIO "%d</b></td><td style='width:176px'><select id='g%d'></select></td></tr>"),
|
||||
(WEMOS==my_module_type)?stemp:"", i, i);
|
||||
WSContentSend_P(PSTR("<tr><td style='width:116px'>%s <b>" D_GPIO "%d</b></td><td style='width:150px'><select id='g%d' onchange='ot(%d,this.value)'></select></td>"),
|
||||
(WEMOS==my_module_type)?stemp:"", i, i, i);
|
||||
WSContentSend_P(PSTR("<td style='width:50px'><select id='h%d'></select></td></tr>"), i);
|
||||
#endif // ESP8266
|
||||
}
|
||||
}
|
||||
@ -1616,23 +1744,22 @@ void ModuleSaveSettings(void)
|
||||
if (ValidGPIO(i, cmodule.io[i])) {
|
||||
snprintf_P(webindex, sizeof(webindex), PSTR("g%d"), i);
|
||||
WebGetArg(webindex, tmp, sizeof(tmp));
|
||||
uint8_t value = (!strlen(tmp)) ? 0 : atoi(tmp);
|
||||
#ifdef ESP8266
|
||||
Settings.my_gp.io[i] = value;
|
||||
#else // ESP32
|
||||
if (i == ADC0_PIN) {
|
||||
Settings.my_adc0 = value;
|
||||
} else {
|
||||
Settings.my_gp.io[i] = value;
|
||||
}
|
||||
uint32_t value = (!strlen(tmp)) ? 0 : atoi(tmp);
|
||||
#ifdef ESP32
|
||||
char tmp2[8]; // WebGetArg numbers only
|
||||
char webindex2[5]; // WebGetArg name
|
||||
snprintf_P(webindex2, sizeof(webindex2), PSTR("h%d"), i);
|
||||
WebGetArg(webindex2, tmp2, sizeof(tmp2));
|
||||
uint32_t value2 = (!strlen(tmp2)) ? 0 : atoi(tmp2) -1;
|
||||
value += value2;
|
||||
#endif // ESP8266 - ESP32
|
||||
Settings.my_gp.io[i] = value;
|
||||
gpios += F(", " D_GPIO ); gpios += String(i); gpios += F(" "); gpios += String(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef ESP8266
|
||||
#ifndef USE_ADC_VCC
|
||||
// WebGetArg("g17", tmp, sizeof(tmp));
|
||||
WebGetArg("g" STR(ADC0_PIN), tmp, sizeof(tmp));
|
||||
Settings.my_adc0 = (!strlen(tmp)) ? 0 : atoi(tmp);
|
||||
gpios += F(", " D_ADC "0 "); gpios += String(Settings.my_adc0);
|
||||
|
@ -481,11 +481,11 @@ void CmndRfKey(void)
|
||||
SnfBridge.learn_active = 0;
|
||||
if (2 == XdrvMailbox.payload) { // Learn RF data
|
||||
SonoffBridgeLearn(XdrvMailbox.index);
|
||||
ResponseCmndIdxChar(D_JSON_START_LEARNING);
|
||||
ResponseCmndIdxChar(PSTR(D_JSON_START_LEARNING));
|
||||
}
|
||||
else if (3 == XdrvMailbox.payload) { // Unlearn RF data
|
||||
Settings.rf_code[XdrvMailbox.index][0] = 0; // Reset sync_time MSB
|
||||
ResponseCmndIdxChar(D_JSON_SET_TO_DEFAULT);
|
||||
ResponseCmndIdxChar(PSTR(D_JSON_SET_TO_DEFAULT));
|
||||
}
|
||||
else if (4 == XdrvMailbox.payload) { // Save RF data provided by RFSync, RfLow, RfHigh and last RfCode
|
||||
for (uint32_t i = 0; i < 6; i++) {
|
||||
@ -494,7 +494,7 @@ void CmndRfKey(void)
|
||||
Settings.rf_code[XdrvMailbox.index][6] = (SnfBridge.last_send_code >> 16) & 0xff;
|
||||
Settings.rf_code[XdrvMailbox.index][7] = (SnfBridge.last_send_code >> 8) & 0xff;
|
||||
Settings.rf_code[XdrvMailbox.index][8] = SnfBridge.last_send_code & 0xff;
|
||||
ResponseCmndIdxChar(D_JSON_SAVED);
|
||||
ResponseCmndIdxChar(PSTR(D_JSON_SAVED));
|
||||
} else if (5 == XdrvMailbox.payload) { // Show default or learned RF data
|
||||
uint8_t key = XdrvMailbox.index;
|
||||
uint8_t index = (0 == Settings.rf_code[key][0]) ? 0 : key; // Use default if sync_time MSB = 0
|
||||
@ -513,10 +513,10 @@ void CmndRfKey(void)
|
||||
} else {
|
||||
if ((1 == XdrvMailbox.payload) || (0 == Settings.rf_code[XdrvMailbox.index][0])) { // Test sync_time MSB
|
||||
SonoffBridgeSend(0, XdrvMailbox.index); // Send default RF data
|
||||
ResponseCmndIdxChar(D_JSON_DEFAULT_SENT);
|
||||
ResponseCmndIdxChar(PSTR(D_JSON_DEFAULT_SENT));
|
||||
} else {
|
||||
SonoffBridgeSend(XdrvMailbox.index, 0); // Send learned RF data
|
||||
ResponseCmndIdxChar(D_JSON_LEARNED_SENT);
|
||||
ResponseCmndIdxChar(PSTR(D_JSON_LEARNED_SENT));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -62,6 +62,7 @@ keywords if then else endif, or, and are better readable for beginners (others m
|
||||
#define MAX_SCRIPT_SIZE MAX_RULE_SIZE*MAX_RULE_SETS
|
||||
|
||||
|
||||
|
||||
uint32_t EncodeLightId(uint8_t relay_id);
|
||||
uint32_t DecodeLightId(uint32_t hue_id);
|
||||
|
||||
@ -69,6 +70,8 @@ uint32_t DecodeLightId(uint32_t hue_id);
|
||||
|
||||
#include "FS.h"
|
||||
#include "SPIFFS.h"
|
||||
|
||||
|
||||
void SaveFile(const char *name,const uint8_t *buf,uint32_t len) {
|
||||
File file = SPIFFS.open(name, FILE_WRITE);
|
||||
if (!file) return;
|
||||
@ -102,14 +105,36 @@ enum {SCRIPT_LOGLEVEL=1,SCRIPT_TELEPERIOD};
|
||||
|
||||
#ifdef USE_SCRIPT_FATFS
|
||||
#include <SPI.h>
|
||||
|
||||
//#define USE_MMC
|
||||
|
||||
#ifdef USE_MMC
|
||||
#include <SD_MMC.h>
|
||||
#undef FS_USED
|
||||
#define FS_USED SD_MMC
|
||||
#else
|
||||
#include <SD.h>
|
||||
#undef FS_USED
|
||||
#define FS_USED SD
|
||||
#endif
|
||||
|
||||
#ifndef ESP32
|
||||
#undef FILE_WRITE
|
||||
#define FILE_WRITE (sdfat::O_READ | sdfat::O_WRITE | sdfat::O_CREAT)
|
||||
#define FILE_APPEND (sdfat::O_READ | sdfat::O_WRITE | sdfat::O_CREAT | sdfat::O_APPEND)
|
||||
#endif
|
||||
|
||||
#ifndef FAT_SCRIPT_SIZE
|
||||
#define FAT_SCRIPT_SIZE 4096
|
||||
#endif
|
||||
#ifdef ESP32
|
||||
#undef FAT_SCRIPT_NAME
|
||||
#define FAT_SCRIPT_NAME "/script.txt"
|
||||
#else
|
||||
#undef FAT_SCRIPT_NAME
|
||||
#define FAT_SCRIPT_NAME "script.txt"
|
||||
#if USE_LONG_FILE_NAMES==1
|
||||
#warning ("FATFS long filenames not supported");
|
||||
#endif
|
||||
|
||||
#if USE_STANDARD_SPI_LIBRARY==0
|
||||
#warning ("FATFS standard spi should be used");
|
||||
#endif
|
||||
@ -266,7 +291,6 @@ void RulesTeleperiod(void) {
|
||||
#define EEP_SCRIPT_SIZE 4095
|
||||
#endif
|
||||
|
||||
|
||||
static Eeprom24C128_256 eeprom(EEPROM_ADDRESS);
|
||||
// eeprom.writeBytes(address, length, buffer);
|
||||
#define EEP_WRITE(A,B,C) eeprom.writeBytes(A,B,(uint8_t*)C);
|
||||
@ -588,7 +612,11 @@ char *script;
|
||||
|
||||
#ifdef USE_SCRIPT_FATFS
|
||||
if (!glob_script_mem.script_sd_found) {
|
||||
if (SD.begin(USE_SCRIPT_FATFS)) {
|
||||
#ifdef USE_MMC
|
||||
if (FS_USED.begin()) {
|
||||
#else
|
||||
if (FS_USED.begin(USE_SCRIPT_FATFS)) {
|
||||
#endif
|
||||
glob_script_mem.script_sd_found=1;
|
||||
} else {
|
||||
glob_script_mem.script_sd_found=0;
|
||||
@ -1166,20 +1194,36 @@ chknext:
|
||||
goto exit;
|
||||
}
|
||||
break;
|
||||
#ifdef USE_SCRIPT_FATFS
|
||||
case 'f':
|
||||
#ifdef USE_SCRIPT_FATFS
|
||||
if (!strncmp(vname,"fo(",3)) {
|
||||
lp+=3;
|
||||
char str[SCRIPT_MAXSSIZE];
|
||||
lp=GetStringResult(lp,OPER_EQU,str,0);
|
||||
while (*lp==' ') lp++;
|
||||
lp=GetNumericResult(lp,OPER_EQU,&fvar,0);
|
||||
uint8_t mode=fvar;
|
||||
uint8_t mode=0;
|
||||
if ((*lp=='r') || (*lp=='w') || (*lp=='a')) {
|
||||
switch (*lp) {
|
||||
case 'r':
|
||||
mode=0;
|
||||
break;
|
||||
case 'w':
|
||||
mode=1;
|
||||
break;
|
||||
case 'a':
|
||||
mode=2;
|
||||
break;
|
||||
}
|
||||
lp++;
|
||||
} else {
|
||||
lp=GetNumericResult(lp,OPER_EQU,&fvar,0);
|
||||
mode=fvar;
|
||||
}
|
||||
fvar=-1;
|
||||
for (uint8_t cnt=0;cnt<SFS_MAX;cnt++) {
|
||||
if (!glob_script_mem.file_flags[cnt].is_open) {
|
||||
if (mode==0) {
|
||||
glob_script_mem.files[cnt]=SD.open(str,FILE_READ);
|
||||
glob_script_mem.files[cnt]=FS_USED.open(str,FILE_READ);
|
||||
if (glob_script_mem.files[cnt].isDirectory()) {
|
||||
glob_script_mem.files[cnt].rewindDirectory();
|
||||
glob_script_mem.file_flags[cnt].is_dir=1;
|
||||
@ -1187,7 +1231,13 @@ chknext:
|
||||
glob_script_mem.file_flags[cnt].is_dir=0;
|
||||
}
|
||||
}
|
||||
else glob_script_mem.files[cnt]=SD.open(str,FILE_WRITE);
|
||||
else {
|
||||
if (mode==1) {
|
||||
glob_script_mem.files[cnt]=FS_USED.open(str,FILE_WRITE);
|
||||
} else {
|
||||
glob_script_mem.files[cnt]=FS_USED.open(str,FILE_APPEND);
|
||||
}
|
||||
}
|
||||
if (glob_script_mem.files[cnt]) {
|
||||
fvar=cnt;
|
||||
glob_script_mem.file_flags[cnt].is_open=1;
|
||||
@ -1275,7 +1325,13 @@ chknext:
|
||||
File entry=glob_script_mem.files[find].openNextFile();
|
||||
if (entry) {
|
||||
if (!reject((char*)entry.name())) {
|
||||
strcpy(str,entry.name());
|
||||
char *ep=(char*)entry.name();
|
||||
if (*ep=='/') ep++;
|
||||
char *lcp = strrchr(ep,'/');
|
||||
if (lcp) {
|
||||
ep=lcp+1;
|
||||
}
|
||||
strcpy(str,ep);
|
||||
entry.close();
|
||||
break;
|
||||
}
|
||||
@ -1313,18 +1369,47 @@ chknext:
|
||||
lp+=3;
|
||||
char str[glob_script_mem.max_ssize+1];
|
||||
lp=GetStringResult(lp,OPER_EQU,str,0);
|
||||
SD.remove(str);
|
||||
FS_USED.remove(str);
|
||||
lp++;
|
||||
len=0;
|
||||
goto exit;
|
||||
}
|
||||
#if defined(ESP32) && defined(USE_WEBCAM)
|
||||
if (!strncmp(vname,"fwp(",4)) {
|
||||
lp+=4;
|
||||
lp=GetNumericResult(lp,OPER_EQU,&fvar,0);
|
||||
while (*lp==' ') lp++;
|
||||
float fvar1;
|
||||
lp=GetNumericResult(lp,OPER_EQU,&fvar1,0);
|
||||
uint8_t ind=fvar1;
|
||||
if (ind>=SFS_MAX) ind=SFS_MAX-1;
|
||||
if (glob_script_mem.file_flags[ind].is_open) {
|
||||
uint8_t *buff;
|
||||
float maxps=get_picstore(-1,0);
|
||||
if (fvar<1 || fvar>maxps) fvar=1;
|
||||
uint32_t len=get_picstore(fvar-1, &buff);
|
||||
if (len) {
|
||||
//glob_script_mem.files[ind].seek(0,SeekEnd);
|
||||
fvar=glob_script_mem.files[ind].write(buff,len);
|
||||
} else {
|
||||
fvar=0;
|
||||
}
|
||||
//AddLog_P2(LOG_LEVEL_INFO, PSTR("picture save: %d"), len);
|
||||
} else {
|
||||
fvar=0;
|
||||
}
|
||||
lp++;
|
||||
len=0;
|
||||
goto exit;
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_SCRIPT_FATFS_EXT
|
||||
if (!strncmp(vname,"fe(",3)) {
|
||||
lp+=3;
|
||||
char str[glob_script_mem.max_ssize+1];
|
||||
lp=GetStringResult(lp,OPER_EQU,str,0);
|
||||
// execute script
|
||||
File ef=SD.open(str);
|
||||
File ef=FS_USED.open(str);
|
||||
if (ef) {
|
||||
uint16_t fsiz=ef.size();
|
||||
if (fsiz<2048) {
|
||||
@ -1346,7 +1431,7 @@ chknext:
|
||||
lp+=4;
|
||||
char str[glob_script_mem.max_ssize+1];
|
||||
lp=GetStringResult(lp,OPER_EQU,str,0);
|
||||
fvar=SD.mkdir(str);
|
||||
fvar=FS_USED.mkdir(str);
|
||||
lp++;
|
||||
len=0;
|
||||
goto exit;
|
||||
@ -1355,7 +1440,7 @@ chknext:
|
||||
lp+=4;
|
||||
char str[glob_script_mem.max_ssize+1];
|
||||
lp=GetStringResult(lp,OPER_EQU,str,0);
|
||||
fvar=SD.rmdir(str);
|
||||
fvar=FS_USED.rmdir(str);
|
||||
lp++;
|
||||
len=0;
|
||||
goto exit;
|
||||
@ -1364,13 +1449,13 @@ chknext:
|
||||
lp+=3;
|
||||
char str[glob_script_mem.max_ssize+1];
|
||||
lp=GetStringResult(lp,OPER_EQU,str,0);
|
||||
if (SD.exists(str)) fvar=1;
|
||||
if (FS_USED.exists(str)) fvar=1;
|
||||
else fvar=0;
|
||||
lp++;
|
||||
len=0;
|
||||
goto exit;
|
||||
}
|
||||
#endif
|
||||
#endif // USE_SCRIPT_FATFS_EXT
|
||||
if (!strncmp(vname,"fl1(",4) || !strncmp(vname,"fl2(",4) ) {
|
||||
uint8_t lknum=*(lp+2)&3;
|
||||
lp+=4;
|
||||
@ -1388,9 +1473,16 @@ chknext:
|
||||
//card_init();
|
||||
goto exit;
|
||||
}
|
||||
break;
|
||||
|
||||
#endif //USE_SCRIPT_FATFS
|
||||
if (!strncmp(vname,"freq",4)) {
|
||||
#ifdef ESP32
|
||||
fvar=getCpuFrequencyMhz();
|
||||
#else
|
||||
fvar=ESP.getCpuFreqMHz();
|
||||
#endif
|
||||
goto exit;
|
||||
}
|
||||
break;
|
||||
case 'g':
|
||||
if (!strncmp(vname,"gtmp",4)) {
|
||||
fvar=global_temperature;
|
||||
@ -1472,6 +1564,10 @@ chknext:
|
||||
}
|
||||
break;
|
||||
case 'l':
|
||||
if (!strncmp(vname,"lip",3)) {
|
||||
if (sp) strlcpy(sp,(const char*)WiFi.localIP().toString().c_str(),glob_script_mem.max_ssize);
|
||||
goto strexit;
|
||||
}
|
||||
if (!strncmp(vname,"loglvl",6)) {
|
||||
fvar=glob_script_mem.script_loglevel;
|
||||
tind->index=SCRIPT_LOGLEVEL;
|
||||
@ -1573,7 +1669,14 @@ chknext:
|
||||
}
|
||||
if (!strncmp(vname,"pn[",3)) {
|
||||
GetNumericResult(vname+3,OPER_EQU,&fvar,0);
|
||||
// fvar=pin[(uint8_t)fvar];
|
||||
fvar=Pin(fvar);
|
||||
// skip ] bracket
|
||||
len++;
|
||||
goto exit;
|
||||
}
|
||||
if (!strncmp(vname,"pn[",3)) {
|
||||
GetNumericResult(vname+3,OPER_EQU,&fvar,0);
|
||||
// fvar=pin_gpio[(uint8_t)fvar];
|
||||
fvar=Pin(fvar);
|
||||
// skip ] bracket
|
||||
len++;
|
||||
@ -1582,9 +1685,9 @@ chknext:
|
||||
if (!strncmp(vname,"pd[",3)) {
|
||||
GetNumericResult(vname+3,OPER_EQU,&fvar,0);
|
||||
uint8_t gpiopin=fvar;
|
||||
#ifdef LEGACY_GPIO_ARRAY
|
||||
for (uint8_t i=0;i<GPIO_SENSOR_END;i++) { // Theo/Gemu: This needs to change when pin[] becomes real pin array
|
||||
// if (pin[i]==gpiopin) {
|
||||
/*
|
||||
for (uint8_t i=0;i<GPIO_SENSOR_END;i++) {
|
||||
// if (pin_gpio[i]==gpiopin) {
|
||||
if (Pin(i)==gpiopin) {
|
||||
fvar=i;
|
||||
// skip ] bracket
|
||||
@ -1592,14 +1695,13 @@ chknext:
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if ((gpiopin < ARRAY_SIZE(pin)) && (pin[gpiopin] > 0)) {
|
||||
fvar = pin[gpiopin];
|
||||
*/
|
||||
if ((gpiopin < ARRAY_SIZE(gpio_pin)) && (gpio_pin[gpiopin] > 0)) {
|
||||
fvar = gpio_pin[gpiopin];
|
||||
// skip ] bracket
|
||||
len++;
|
||||
goto exit;
|
||||
}
|
||||
#endif
|
||||
fvar=999;
|
||||
goto exit;
|
||||
}
|
||||
@ -1791,7 +1893,7 @@ chknext:
|
||||
goto exit;
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_SML_SCRIPT_CMD
|
||||
#if defined(USE_SML_M) && defined (USE_SML_SCRIPT_CMD)
|
||||
if (!strncmp(vname,"sml(",4)) {
|
||||
lp+=4;
|
||||
float fvar1;
|
||||
@ -1903,6 +2005,67 @@ chknext:
|
||||
break;
|
||||
|
||||
case 'w':
|
||||
#if defined(ESP32) && defined(USE_WEBCAM)
|
||||
if (!strncmp(vname,"wc(",3)) {
|
||||
lp+=3;
|
||||
float fvar1;
|
||||
lp=GetNumericResult(lp,OPER_EQU,&fvar1,0);
|
||||
SCRIPT_SKIP_SPACES
|
||||
switch ((uint32)fvar1) {
|
||||
case 0:
|
||||
{ float fvar2;
|
||||
lp=GetNumericResult(lp,OPER_EQU,&fvar2,0);
|
||||
fvar=wc_setup(fvar2);
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
{ float fvar2;
|
||||
lp=GetNumericResult(lp,OPER_EQU,&fvar2,0);
|
||||
fvar=wc_get_frame(fvar2);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
{ float fvar2,fvar3;
|
||||
lp=GetNumericResult(lp,OPER_EQU,&fvar2,0);
|
||||
SCRIPT_SKIP_SPACES
|
||||
lp=GetNumericResult(lp,OPER_EQU,&fvar3,0);
|
||||
fvar=wc_set_options(fvar2,fvar3);
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
fvar=wc_get_width();
|
||||
break;
|
||||
case 4:
|
||||
fvar=wc_get_height();
|
||||
break;
|
||||
case 5:
|
||||
{ float fvar2;
|
||||
lp=GetNumericResult(lp,OPER_EQU,&fvar2,0);
|
||||
fvar=wc_set_streamserver(fvar2);
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
{ float fvar2;
|
||||
lp=GetNumericResult(lp,OPER_EQU,&fvar2,0);
|
||||
fvar=wc_set_motion_detect(fvar2);
|
||||
}
|
||||
break;
|
||||
#ifdef USE_FACE_DETECT
|
||||
case 7:
|
||||
{ float fvar2;
|
||||
lp=GetNumericResult(lp,OPER_EQU,&fvar2,0);
|
||||
fvar=wc_set_face_detect(fvar2);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
fvar=0;
|
||||
}
|
||||
lp++;
|
||||
len=0;
|
||||
goto exit;
|
||||
}
|
||||
#endif
|
||||
if (!strncmp(vname,"wday",4)) {
|
||||
fvar=RtcTime.day_of_week;
|
||||
goto exit;
|
||||
@ -2723,9 +2886,29 @@ int16_t Run_Scripter(const char *type, int8_t tlen, char *js) {
|
||||
lp=GetNumericResult(lp,OPER_EQU,&fvar,0);
|
||||
int8_t pinnr=fvar;
|
||||
SCRIPT_SKIP_SPACES
|
||||
lp=GetNumericResult(lp,OPER_EQU,&fvar,0);
|
||||
int8_t mode=fvar;
|
||||
pinMode(pinnr,mode&3);
|
||||
uint8_t mode=0;
|
||||
if ((*lp=='I') || (*lp=='O') || (*lp=='P')) {
|
||||
switch (*lp) {
|
||||
case 'I':
|
||||
mode=0;
|
||||
break;
|
||||
case 'O':
|
||||
mode=1;
|
||||
break;
|
||||
case 'P':
|
||||
mode=2;
|
||||
break;
|
||||
}
|
||||
lp++;
|
||||
} else {
|
||||
lp=GetNumericResult(lp,OPER_EQU,&fvar,0);
|
||||
mode=fvar;
|
||||
}
|
||||
uint8_t pm=0;
|
||||
if (mode==0) pm=INPUT;
|
||||
if (mode==1) pm=OUTPUT;
|
||||
if (mode==2) pm=INPUT_PULLUP;
|
||||
pinMode(pinnr,pm);
|
||||
goto next_line;
|
||||
} else if (!strncmp(lp,"spin(",5)) {
|
||||
lp+=5;
|
||||
@ -2764,6 +2947,21 @@ int16_t Run_Scripter(const char *type, int8_t tlen, char *js) {
|
||||
goto next_line;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
#ifdef ESP32
|
||||
else if (!strncmp(lp,"beep(",5)) {
|
||||
lp+=5;
|
||||
lp=GetNumericResult(lp,OPER_EQU,&fvar,0);
|
||||
if (fvar<0) {
|
||||
ledcSetup(7,500,10);
|
||||
ledcAttachPin(-fvar,7);
|
||||
ledcWriteTone(7,0);
|
||||
} else {
|
||||
ledcWriteTone(7,fvar);
|
||||
}
|
||||
lp++;
|
||||
goto next_line;
|
||||
}
|
||||
#endif
|
||||
|
||||
else if (!strncmp(lp,"=>",2) || !strncmp(lp,"->",2) || !strncmp(lp,"+>",2) || !strncmp(lp,"print",5)) {
|
||||
@ -3275,7 +3473,7 @@ const char HTTP_FORM_FILE_UPGb[] PROGMEM =
|
||||
const char HTTP_FORM_SDC_DIRa[] PROGMEM =
|
||||
"<div style='text-align:left'>";
|
||||
const char HTTP_FORM_SDC_DIRb[] PROGMEM =
|
||||
"<pre><a href='%s' file='%s'>%s</a> %d</pre>";
|
||||
"<pre><a href='%s' file='%s'>%s</a> %s : %8d</pre>";
|
||||
const char HTTP_FORM_SDC_DIRd[] PROGMEM =
|
||||
"<pre><a href='%s' file='%s'>%s</a></pre>";
|
||||
const char HTTP_FORM_SDC_DIRc[] PROGMEM =
|
||||
@ -3298,6 +3496,7 @@ const char HTTP_FORM_SDC_HREF[] PROGMEM =
|
||||
|
||||
uint8_t reject(char *name) {
|
||||
|
||||
while (*name=='/') name++;
|
||||
if (*name=='_') return 1;
|
||||
if (*name=='.') return 1;
|
||||
|
||||
@ -3312,6 +3511,8 @@ uint8_t reject(char *name) {
|
||||
if (!strcasecmp(name,"FSEVEN~1")) return 1;
|
||||
if (!strcasecmp(name,"SYSTEM~1")) return 1;
|
||||
#endif
|
||||
|
||||
if (!strncasecmp(name,"System Volume",13)) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -3321,7 +3522,7 @@ void ListDir(char *path, uint8_t depth) {
|
||||
char format[12];
|
||||
sprintf(format,"%%-%ds",24-depth);
|
||||
|
||||
File dir=SD.open(path);
|
||||
File dir=FS_USED.open(path);
|
||||
if (dir) {
|
||||
dir.rewindDirectory();
|
||||
if (strlen(path)>1) {
|
||||
@ -3335,35 +3536,48 @@ void ListDir(char *path, uint8_t depth) {
|
||||
}
|
||||
WSContentSend_P(HTTP_FORM_SDC_DIRd,npath,path,"..");
|
||||
}
|
||||
char *ep;
|
||||
while (true) {
|
||||
File entry=dir.openNextFile();
|
||||
if (!entry) {
|
||||
break;
|
||||
}
|
||||
// esp32 returns path here, shorten to filename
|
||||
ep=(char*)entry.name();
|
||||
if (*ep=='/') ep++;
|
||||
char *lcp = strrchr(ep,'/');
|
||||
if (lcp) {
|
||||
ep=lcp+1;
|
||||
}
|
||||
//AddLog_P2(LOG_LEVEL_INFO, PSTR("entry: %s"),ep);
|
||||
time_t tm=entry.getLastWrite();
|
||||
char tstr[24];
|
||||
strftime(tstr, 22, "%d-%m-%Y - %H:%M:%S ", localtime(&tm));
|
||||
|
||||
char *pp=path;
|
||||
if (!*(pp+1)) pp++;
|
||||
char *cp=name;
|
||||
// osx formatted disks contain a lot of stuff we dont want
|
||||
if (reject((char*)entry.name())) goto fclose;
|
||||
if (reject((char*)ep)) goto fclose;
|
||||
|
||||
for (uint8_t cnt=0;cnt<depth;cnt++) {
|
||||
*cp++='-';
|
||||
}
|
||||
// unfortunately no time date info in class File
|
||||
sprintf(cp,format,entry.name());
|
||||
|
||||
sprintf(cp,format,ep);
|
||||
if (entry.isDirectory()) {
|
||||
snprintf_P(npath,sizeof(npath),HTTP_FORM_SDC_HREF,WiFi.localIP().toString().c_str(),pp,entry.name());
|
||||
WSContentSend_P(HTTP_FORM_SDC_DIRd,npath,entry.name(),name);
|
||||
snprintf_P(npath,sizeof(npath),HTTP_FORM_SDC_HREF,WiFi.localIP().toString().c_str(),pp,ep);
|
||||
WSContentSend_P(HTTP_FORM_SDC_DIRd,npath,ep,name);
|
||||
uint8_t plen=strlen(path);
|
||||
if (plen>1) {
|
||||
strcat(path,"/");
|
||||
}
|
||||
strcat(path,entry.name());
|
||||
strcat(path,ep);
|
||||
ListDir(path,depth+4);
|
||||
path[plen]=0;
|
||||
} else {
|
||||
snprintf_P(npath,sizeof(npath),HTTP_FORM_SDC_HREF,WiFi.localIP().toString().c_str(),pp,entry.name());
|
||||
WSContentSend_P(HTTP_FORM_SDC_DIRb,npath,entry.name(),name,entry.size());
|
||||
snprintf_P(npath,sizeof(npath),HTTP_FORM_SDC_HREF,WiFi.localIP().toString().c_str(),pp,ep);
|
||||
WSContentSend_P(HTTP_FORM_SDC_DIRb,npath,ep,name,tstr,entry.size());
|
||||
}
|
||||
fclose:
|
||||
entry.close();
|
||||
@ -3430,8 +3644,8 @@ void script_upload(void) {
|
||||
if (upload.status == UPLOAD_FILE_START) {
|
||||
char npath[48];
|
||||
sprintf(npath,"%s/%s",path,upload.filename.c_str());
|
||||
SD.remove(npath);
|
||||
upload_file=SD.open(npath,FILE_WRITE);
|
||||
FS_USED.remove(npath);
|
||||
upload_file=FS_USED.open(npath,FILE_WRITE);
|
||||
if (!upload_file) Web.upload_error=1;
|
||||
} else if(upload.status == UPLOAD_FILE_WRITE) {
|
||||
if (upload_file) upload_file.write(upload.buf,upload.currentSize);
|
||||
@ -3450,12 +3664,12 @@ uint8_t DownloadFile(char *file) {
|
||||
File download_file;
|
||||
WiFiClient download_Client;
|
||||
|
||||
if (!SD.exists(file)) {
|
||||
if (!FS_USED.exists(file)) {
|
||||
AddLog_P(LOG_LEVEL_INFO,PSTR("file not found"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
download_file=SD.open(file,FILE_READ);
|
||||
download_file=FS_USED.open(file,FILE_READ);
|
||||
if (!download_file) {
|
||||
AddLog_P(LOG_LEVEL_INFO,PSTR("could not open file"));
|
||||
return 0;
|
||||
@ -3519,6 +3733,7 @@ void HandleScriptTextareaConfiguration(void) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void HandleScriptConfiguration(void) {
|
||||
|
||||
if (!HttpCheckPriviledgedAccess()) { return; }
|
||||
@ -3620,19 +3835,17 @@ void ScriptSaveSettings(void) {
|
||||
|
||||
strlcpy(glob_script_mem.script_ram,str.c_str(), glob_script_mem.script_size);
|
||||
|
||||
#ifdef USE_24C256
|
||||
#ifndef USE_SCRIPT_FATFS
|
||||
#if defined(USE_24C256) && !defined(USE_SCRIPT_FATFS)
|
||||
if (glob_script_mem.flags&1) {
|
||||
EEP_WRITE(0,EEP_SCRIPT_SIZE,glob_script_mem.script_ram);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef USE_SCRIPT_FATFS
|
||||
#if !defined(USE_24C256) && defined(USE_SCRIPT_FATFS)
|
||||
if (glob_script_mem.flags&1) {
|
||||
SD.remove(FAT_SCRIPT_NAME);
|
||||
File file=SD.open(FAT_SCRIPT_NAME,FILE_WRITE);
|
||||
file.write(glob_script_mem.script_ram,FAT_SCRIPT_SIZE);
|
||||
FS_USED.remove(FAT_SCRIPT_NAME);
|
||||
File file=FS_USED.open(FAT_SCRIPT_NAME,FILE_WRITE);
|
||||
file.write((const uint8_t*)glob_script_mem.script_ram,FAT_SCRIPT_SIZE);
|
||||
file.close();
|
||||
}
|
||||
#endif
|
||||
@ -4279,6 +4492,14 @@ void dateTime(uint16_t* date, uint16_t* time) {
|
||||
|
||||
|
||||
#ifdef SUPPORT_MQTT_EVENT
|
||||
|
||||
#ifndef MQTT_EVENT_MSIZE
|
||||
#define MQTT_EVENT_MSIZE 256
|
||||
#endif
|
||||
#ifndef MQTT_EVENT_JSIZE
|
||||
#define MQTT_EVENT_JSIZE 400
|
||||
#endif
|
||||
|
||||
/********************************************************************************************/
|
||||
/*
|
||||
* Script: Process received MQTT message.
|
||||
@ -4293,8 +4514,8 @@ bool ScriptMqttData(void)
|
||||
{
|
||||
bool serviced = false;
|
||||
//toLog(">>> 1");
|
||||
toLog(XdrvMailbox.data);
|
||||
if (XdrvMailbox.data_len < 1 || XdrvMailbox.data_len > 256) {
|
||||
//toLog(XdrvMailbox.data);
|
||||
if (XdrvMailbox.data_len < 1 || XdrvMailbox.data_len > MQTT_EVENT_MSIZE) {
|
||||
return false;
|
||||
}
|
||||
String sTopic = XdrvMailbox.topic;
|
||||
@ -4314,7 +4535,7 @@ bool ScriptMqttData(void)
|
||||
if (event_item.Key.length() == 0) { //If did not specify Key
|
||||
value = sData;
|
||||
} else { //If specified Key, need to parse Key/Value from JSON data
|
||||
StaticJsonBuffer<400> jsonBuf;
|
||||
StaticJsonBuffer<MQTT_EVENT_JSIZE> jsonBuf;
|
||||
JsonObject& jsonData = jsonBuf.parseObject(sData);
|
||||
String key1 = event_item.Key;
|
||||
String key2;
|
||||
@ -4558,7 +4779,7 @@ uint32_t cnt;
|
||||
nbuf[cnt]=0;
|
||||
}
|
||||
|
||||
void ScriptWebShow(void) {
|
||||
void ScriptWebShow(char mc) {
|
||||
uint8_t web_script=Run_Scripter(">W",-2,0);
|
||||
if (web_script==99) {
|
||||
char line[128];
|
||||
@ -4585,12 +4806,16 @@ void ScriptWebShow(void) {
|
||||
cp++;
|
||||
}
|
||||
char *lin=line;
|
||||
if (!mc && (*lin!='&')) {
|
||||
|
||||
if (*lin=='@') {
|
||||
lin++;
|
||||
optflg=1;
|
||||
} else {
|
||||
optflg=0;
|
||||
}
|
||||
|
||||
|
||||
// check for input elements
|
||||
if (!strncmp(lin,"sl(",3)) {
|
||||
// insert slider sl(min max var left mid right)
|
||||
@ -4750,6 +4975,12 @@ void ScriptWebShow(void) {
|
||||
WSContentSend_PD(PSTR("{s}%s{e}"),tmp);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (*lin==mc) {
|
||||
Replace_Cmd_Vars(lin+1,tmp,sizeof(tmp));
|
||||
WSContentSend_PD(PSTR("%s"),tmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (*lp==SCRIPT_EOL) {
|
||||
lp++;
|
||||
@ -4766,12 +4997,7 @@ void ScriptWebShow(void) {
|
||||
|
||||
#ifdef USE_SENDMAIL
|
||||
|
||||
#ifdef ESP8266
|
||||
void script_send_email_body(BearSSL::WiFiClientSecure_light *client) {
|
||||
#else
|
||||
void script_send_email_body(WiFiClient *client) {
|
||||
#endif
|
||||
|
||||
void script_send_email_body(void(*func)(char *)) {
|
||||
uint8_t msect=Run_Scripter(">m",-2,0);
|
||||
if (msect==99) {
|
||||
char line[128];
|
||||
@ -4797,7 +5023,8 @@ uint8_t msect=Run_Scripter(">m",-2,0);
|
||||
cp++;
|
||||
}
|
||||
Replace_Cmd_Vars(line,tmp,sizeof(tmp));
|
||||
client->println(tmp);
|
||||
//client->println(tmp);
|
||||
func(tmp);
|
||||
}
|
||||
if (*lp==SCRIPT_EOL) {
|
||||
lp++;
|
||||
@ -4808,7 +5035,8 @@ uint8_t msect=Run_Scripter(">m",-2,0);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
client->println("*");
|
||||
//client->println("*");
|
||||
func((char*)"*");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -4869,14 +5097,8 @@ bool Xdrv10(uint8_t function)
|
||||
|
||||
switch (function) {
|
||||
case FUNC_PRE_INIT:
|
||||
/*
|
||||
#ifdef USE_WEBCAM
|
||||
if (Settings.module==ESP32_CAM_AITHINKER) {
|
||||
webcam_setup();
|
||||
}
|
||||
#endif
|
||||
*/
|
||||
// set defaults to rules memory
|
||||
//bitWrite(Settings.rule_enabled,0,0);
|
||||
glob_script_mem.script_ram=Settings.rules[0];
|
||||
glob_script_mem.script_size=MAX_SCRIPT_SIZE;
|
||||
glob_script_mem.flags=0;
|
||||
@ -4916,15 +5138,29 @@ bool Xdrv10(uint8_t function)
|
||||
#endif
|
||||
|
||||
#ifdef USE_SCRIPT_FATFS
|
||||
if (SD.begin(USE_SCRIPT_FATFS)) {
|
||||
|
||||
#ifdef USE_MMC
|
||||
if (FS_USED.begin()) {
|
||||
#else
|
||||
|
||||
#ifdef ESP32
|
||||
if (PinUsed(GPIO_SPI_MOSI) && PinUsed(GPIO_SPI_MISO) && PinUsed(GPIO_SPI_CLK)) {
|
||||
SPI.begin(Pin(GPIO_SPI_CLK),Pin(GPIO_SPI_MISO),Pin(GPIO_SPI_MOSI), -1);
|
||||
}
|
||||
#endif
|
||||
if (FS_USED.begin(USE_SCRIPT_FATFS)) {
|
||||
#endif
|
||||
|
||||
//FS_USED.dateTimeCallback(dateTime);
|
||||
|
||||
glob_script_mem.script_sd_found=1;
|
||||
char *script;
|
||||
script=(char*)calloc(FAT_SCRIPT_SIZE+4,1);
|
||||
if (!script) break;
|
||||
glob_script_mem.script_ram=script;
|
||||
glob_script_mem.script_size=FAT_SCRIPT_SIZE;
|
||||
if (SD.exists(FAT_SCRIPT_NAME)) {
|
||||
File file=SD.open(FAT_SCRIPT_NAME,FILE_READ);
|
||||
if (FS_USED.exists(FAT_SCRIPT_NAME)) {
|
||||
File file=FS_USED.open(FAT_SCRIPT_NAME,FILE_READ);
|
||||
file.read((uint8_t*)script,FAT_SCRIPT_SIZE);
|
||||
file.close();
|
||||
}
|
||||
@ -4935,11 +5171,6 @@ bool Xdrv10(uint8_t function)
|
||||
|
||||
glob_script_mem.flags=1;
|
||||
|
||||
#if defined(ARDUINO_ESP8266_RELEASE_2_3_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_2)
|
||||
// for unkonwn reasons is not defined in 2.52
|
||||
SdFile::dateTimeCallback(dateTime);
|
||||
#endif
|
||||
|
||||
} else {
|
||||
glob_script_mem.script_sd_found=0;
|
||||
}
|
||||
@ -5002,6 +5233,11 @@ bool Xdrv10(uint8_t function)
|
||||
case FUNC_WEB_ADD_BUTTON:
|
||||
WSContentSend_P(HTTP_BTN_MENU_RULES);
|
||||
break;
|
||||
#ifdef USE_SCRIPT_WEB_DISPLAY
|
||||
case FUNC_WEB_ADD_MAIN_BUTTON:
|
||||
ScriptWebShow('&');
|
||||
break;
|
||||
#endif // USE_SCRIPT_WEB_DISPLAY
|
||||
case FUNC_WEB_ADD_HANDLER:
|
||||
Webserver->on("/" WEB_HANDLE_SCRIPT, HandleScriptConfiguration);
|
||||
Webserver->on("/ta",HTTP_POST, HandleScriptTextareaConfiguration);
|
||||
@ -5029,7 +5265,7 @@ bool Xdrv10(uint8_t function)
|
||||
#ifdef USE_SCRIPT_WEB_DISPLAY
|
||||
case FUNC_WEB_SENSOR:
|
||||
if (bitRead(Settings.rule_enabled, 0)) {
|
||||
ScriptWebShow();
|
||||
ScriptWebShow(0);
|
||||
}
|
||||
break;
|
||||
#endif //USE_SCRIPT_WEB_DISPLAY
|
||||
|
@ -473,19 +473,19 @@ void KNX_INIT(void)
|
||||
{
|
||||
device_param[i].show = true;
|
||||
}
|
||||
for (uint32_t i = GPIO_SWT1; i < GPIO_SWT4 + 1; ++i)
|
||||
for (uint32_t i = GPIO_SWT1; i < GPIO_SWT1 + 4; ++i)
|
||||
{
|
||||
if (GetUsedInModule(i, my_module.io)) { device_param[i - GPIO_SWT1 + 8].show = true; }
|
||||
}
|
||||
for (uint32_t i = GPIO_KEY1; i < GPIO_KEY4 + 1; ++i)
|
||||
for (uint32_t i = GPIO_KEY1; i < GPIO_KEY1 + 4; ++i)
|
||||
{
|
||||
if (GetUsedInModule(i, my_module.io)) { device_param[i - GPIO_KEY1 + 8].show = true; }
|
||||
}
|
||||
for (uint32_t i = GPIO_SWT1_NP; i < GPIO_SWT4_NP + 1; ++i)
|
||||
for (uint32_t i = GPIO_SWT1_NP; i < GPIO_SWT1_NP + 4; ++i)
|
||||
{
|
||||
if (GetUsedInModule(i, my_module.io)) { device_param[i - GPIO_SWT1_NP + 8].show = true; }
|
||||
}
|
||||
for (uint32_t i = GPIO_KEY1_NP; i < GPIO_KEY4_NP + 1; ++i)
|
||||
for (uint32_t i = GPIO_KEY1_NP; i < GPIO_KEY1_NP + 4; ++i)
|
||||
{
|
||||
if (GetUsedInModule(i, my_module.io)) { device_param[i - GPIO_KEY1_NP + 8].show = true; }
|
||||
}
|
||||
|
@ -259,10 +259,10 @@ bool Xdrv21(uint8_t function)
|
||||
if (devices_present && (EMUL_WEMO == Settings.flag2.emulation)) {
|
||||
switch (function) {
|
||||
case FUNC_WEB_ADD_HANDLER:
|
||||
Webserver->on("/upnp/control/basicevent1", HTTP_POST, HandleUpnpEvent);
|
||||
Webserver->on("/eventservice.xml", HandleUpnpService);
|
||||
Webserver->on("/metainfoservice.xml", HandleUpnpMetaService);
|
||||
Webserver->on("/setup.xml", HandleUpnpSetupWemo);
|
||||
Webserver->on(F("/upnp/control/basicevent1"), HTTP_POST, HandleUpnpEvent);
|
||||
Webserver->on(F("/eventservice.xml"), HandleUpnpService);
|
||||
Webserver->on(F("/metainfoservice.xml"), HandleUpnpMetaService);
|
||||
Webserver->on(F("/setup.xml"), HandleUpnpSetupWemo);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -444,12 +444,9 @@ void TasmotaSlave_Init(void)
|
||||
if (TasmotaSlave_Serial->hardwareSerial()) {
|
||||
ClaimSerial();
|
||||
}
|
||||
TasmotaSlave_Serial->setTimeout(50);
|
||||
TasmotaSlave_Serial->setTimeout(100); // Theo 20200502 - increase from 50
|
||||
if (PinUsed(GPIO_TASMOTASLAVE_RST_INV)) {
|
||||
SetPin(Pin(GPIO_TASMOTASLAVE_RST_INV), GPIO_TASMOTASLAVE_RST);
|
||||
#ifdef LEGACY_GPIO_ARRAY
|
||||
SetPin(99, GPIO_TASMOTASLAVE_RST_INV);
|
||||
#endif
|
||||
TSlave.inverted = HIGH;
|
||||
}
|
||||
pinMode(Pin(GPIO_TASMOTASLAVE_RST), OUTPUT);
|
||||
@ -459,11 +456,14 @@ void TasmotaSlave_Init(void)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (TSlave.SerialEnabled) { // All go for hardware now we need to detect features if there are any
|
||||
if (TSlave.SerialEnabled) { // All go for hardware now we need to detect features if there are any
|
||||
TasmotaSlave_sendCmnd(CMND_FEATURES, 0);
|
||||
char buffer[32];
|
||||
char buffer[32] = { 0 };
|
||||
TasmotaSlave_Serial->readBytesUntil(char(PARAM_DATA_START), buffer, sizeof(buffer));
|
||||
uint8_t len = TasmotaSlave_Serial->readBytesUntil(char(PARAM_DATA_END), buffer, sizeof(buffer));
|
||||
|
||||
if (len) { AddLogBuffer(LOG_LEVEL_DEBUG_MORE, (uint8_t*)buffer, len); } // Theo 20200502 - DMP: 99 17 34 01 02 00 00 00
|
||||
|
||||
memcpy(&TSlaveSettings, &buffer, sizeof(TSlaveSettings));
|
||||
if (20191129 == TSlaveSettings.features_version) {
|
||||
TSlave.type = true;
|
||||
@ -497,6 +497,9 @@ void TasmotaSlave_sendCmnd(uint8_t cmnd, uint8_t param)
|
||||
buffer[0] = CMND_START;
|
||||
memcpy(&buffer[1], &TSlaveCommand, sizeof(TSlaveCommand));
|
||||
buffer[sizeof(TSlaveCommand)+1] = CMND_END;
|
||||
|
||||
TasmotaSlave_Serial->flush(); // Theo 20200502
|
||||
|
||||
for (uint8_t ca = 0; ca < sizeof(buffer); ca++) {
|
||||
TasmotaSlave_Serial->write(buffer[ca]);
|
||||
}
|
||||
|
@ -17,6 +17,7 @@
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef USE_LIGHT
|
||||
#ifdef USE_SONOFF_D1
|
||||
/*********************************************************************************************\
|
||||
* Sonoff D1 dimmer 433
|
||||
@ -196,3 +197,4 @@ bool Xdrv37(uint8_t function)
|
||||
}
|
||||
|
||||
#endif // USE_SONOFF_D1
|
||||
#endif // USE_LIGHT
|
||||
|
887
tasmota/xdrv_39_webcam.ino
Normal file
887
tasmota/xdrv_39_webcam.ino
Normal file
@ -0,0 +1,887 @@
|
||||
/*
|
||||
xdrv_39_webcam.ino - ESP32 webcam support for Tasmota
|
||||
|
||||
Copyright (C) 2020 Gerhard Mutz and Theo Arends
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef ESP32
|
||||
#ifdef USE_WEBCAM
|
||||
/*********************************************************************************************\
|
||||
* ESP32 webcam based on example in Arduino-ESP32 library
|
||||
*
|
||||
* Template as used on ESP32-CAM WiFi + bluetooth Camera Module Development Board ESP32 With Camera Module OV2640 Geekcreit for Arduino
|
||||
* {"NAME":"AITHINKER CAM No SPI","GPIO":[4992,65504,65504,65504,5472,5312,65504,65504,5504,5536,65504,65504,5568,5440,5280,5248,0,5216,5408,5376,0,5344,5024,5056,0,0,0,0,4928,65504,5120,5088,5184,0,0,5152],"FLAG":0,"BASE":1}
|
||||
* Template with SPI configured. This needs define USE_SPI
|
||||
* {"NAME":"AITHINKER CAM","GPIO":[4992,65504,672,65504,5472,5312,65504,65504,5504,5536,736,704,5568,5440,5280,5248,0,5216,5408,5376,0,5344,5024,5056,0,0,0,0,4928,65504,5120,5088,5184,0,0,5152],"FLAG":0,"BASE":1}
|
||||
*
|
||||
* Command: Webcam <number>
|
||||
* 0 = Stop streaming
|
||||
* 1 = FRAMESIZE_QQVGA2 (128x160)
|
||||
* 2 = FRAMESIZE_QCIF (176x144)
|
||||
* 3 = FRAMESIZE_HQVGA (240x176)
|
||||
* 4 = FRAMESIZE_QVGA (320x240)
|
||||
* 5 = FRAMESIZE_CIF (400x296)
|
||||
* 6 = FRAMESIZE_VGA (640x480)
|
||||
* 7 = FRAMESIZE_SVGA (800x600)
|
||||
* 8 = FRAMESIZE_XGA (1024x768)
|
||||
* 9 = FRAMESIZE_SXGA (1280x1024)
|
||||
* 10 = FRAMESIZE_UXGA (1600x1200)
|
||||
*
|
||||
* Only boards with PSRAM should be used. To enable PSRAM board should be se set to esp32cam in common32 of platform_override.ini
|
||||
* board = esp32cam
|
||||
* To speed up cam processing cpu frequency should be better set to 240Mhz in common32 of platform_override.ini
|
||||
* board_build.f_cpu = 240000000L
|
||||
\*********************************************************************************************/
|
||||
|
||||
#define XDRV_39 39
|
||||
|
||||
#define CAMERA_MODEL_AI_THINKER
|
||||
|
||||
//#define USE_TEMPLATE
|
||||
|
||||
#define WC_LOGLEVEL LOG_LEVEL_INFO
|
||||
#include "fb_gfx.h"
|
||||
#include "fd_forward.h"
|
||||
#include "fr_forward.h"
|
||||
|
||||
#define PWDN_GPIO_NUM 32
|
||||
#define RESET_GPIO_NUM -1
|
||||
#define XCLK_GPIO_NUM 0
|
||||
#define SIOD_GPIO_NUM 26
|
||||
#define SIOC_GPIO_NUM 27
|
||||
|
||||
#define Y9_GPIO_NUM 35
|
||||
#define Y8_GPIO_NUM 34
|
||||
#define Y7_GPIO_NUM 39
|
||||
#define Y6_GPIO_NUM 36
|
||||
#define Y5_GPIO_NUM 21
|
||||
#define Y4_GPIO_NUM 19
|
||||
#define Y3_GPIO_NUM 18
|
||||
#define Y2_GPIO_NUM 5
|
||||
#define VSYNC_GPIO_NUM 25
|
||||
#define HREF_GPIO_NUM 23
|
||||
#define PCLK_GPIO_NUM 22
|
||||
|
||||
|
||||
#include "esp_camera.h"
|
||||
#include "sensor.h"
|
||||
|
||||
uint8_t wc_up;
|
||||
uint16_t wc_width;
|
||||
uint16_t wc_height;
|
||||
uint8_t wc_stream_active;
|
||||
#ifdef USE_FACE_DETECT
|
||||
uint8_t faces;
|
||||
uint16_t face_detect_time;
|
||||
#endif
|
||||
|
||||
uint32_t wc_setup(int32_t fsiz) {
|
||||
if (fsiz > 10) { fsiz = 10; }
|
||||
|
||||
wc_stream_active = 0;
|
||||
|
||||
if (fsiz < 0) {
|
||||
esp_camera_deinit();
|
||||
wc_up = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (wc_up) {
|
||||
esp_camera_deinit();
|
||||
AddLog_P2(WC_LOGLEVEL, PSTR("CAM: deinit"));
|
||||
//return wc_up;
|
||||
}
|
||||
|
||||
//esp_log_level_set("*", ESP_LOG_VERBOSE);
|
||||
|
||||
camera_config_t config;
|
||||
config.ledc_channel = LEDC_CHANNEL_0;
|
||||
config.ledc_timer = LEDC_TIMER_0;
|
||||
config.xclk_freq_hz = 20000000;
|
||||
config.pixel_format = PIXFORMAT_JPEG;
|
||||
// config.pixel_format = PIXFORMAT_GRAYSCALE;
|
||||
// config.pixel_format = PIXFORMAT_RGB565;
|
||||
|
||||
#ifndef USE_TEMPLATE
|
||||
config.pin_d0 = Y2_GPIO_NUM;
|
||||
config.pin_d1 = Y3_GPIO_NUM;
|
||||
config.pin_d2 = Y4_GPIO_NUM;
|
||||
config.pin_d3 = Y5_GPIO_NUM;
|
||||
config.pin_d4 = Y6_GPIO_NUM;
|
||||
config.pin_d5 = Y7_GPIO_NUM;
|
||||
config.pin_d6 = Y8_GPIO_NUM;
|
||||
config.pin_d7 = Y9_GPIO_NUM;
|
||||
config.pin_xclk = XCLK_GPIO_NUM;
|
||||
config.pin_pclk = PCLK_GPIO_NUM;
|
||||
config.pin_vsync = VSYNC_GPIO_NUM;
|
||||
config.pin_href = HREF_GPIO_NUM;
|
||||
config.pin_sscb_sda = SIOD_GPIO_NUM;
|
||||
config.pin_sscb_scl = SIOC_GPIO_NUM;
|
||||
config.pin_pwdn = PWDN_GPIO_NUM;
|
||||
config.pin_reset = RESET_GPIO_NUM;
|
||||
#else
|
||||
if (PinUsed(GPIO_WEBCAM_Y2) && PinUsed(GPIO_WEBCAM_Y3) && PinUsed(GPIO_WEBCAM_Y4) && PinUsed(GPIO_WEBCAM_Y5)\
|
||||
&& PinUsed(GPIO_WEBCAM_Y6) && PinUsed(GPIO_WEBCAM_Y7) && PinUsed(GPIO_WEBCAM_Y8) && PinUsed(GPIO_WEBCAM_Y9)\
|
||||
&& PinUsed(GPIO_WEBCAM_XCLK) && PinUsed(GPIO_WEBCAM_PCLK) && PinUsed(GPIO_WEBCAM_VSYNC) && PinUsed(GPIO_WEBCAM_HREF)\
|
||||
&& PinUsed(GPIO_WEBCAM_SIOD) && PinUsed(GPIO_WEBCAM_SIOC)) {
|
||||
config.pin_d0 = Pin(GPIO_WEBCAM_Y2); //Y2_GPIO_NUM;
|
||||
config.pin_d1 = Pin(GPIO_WEBCAM_Y3); //Y3_GPIO_NUM;
|
||||
config.pin_d2 = Pin(GPIO_WEBCAM_Y4); //Y4_GPIO_NUM;
|
||||
config.pin_d3 = Pin(GPIO_WEBCAM_Y5); //Y5_GPIO_NUM;
|
||||
config.pin_d4 = Pin(GPIO_WEBCAM_Y6); //Y6_GPIO_NUM;
|
||||
config.pin_d5 = Pin(GPIO_WEBCAM_Y7); //Y7_GPIO_NUM;
|
||||
config.pin_d6 = Pin(GPIO_WEBCAM_Y8); //Y8_GPIO_NUM;
|
||||
config.pin_d7 = Pin(GPIO_WEBCAM_Y9); //Y9_GPIO_NUM;
|
||||
config.pin_xclk = Pin(GPIO_WEBCAM_XCLK); //XCLK_GPIO_NUM;
|
||||
config.pin_pclk = Pin(GPIO_WEBCAM_PCLK); //PCLK_GPIO_NUM;
|
||||
config.pin_vsync = Pin(GPIO_WEBCAM_VSYNC); //VSYNC_GPIO_NUM;
|
||||
config.pin_href = Pin(GPIO_WEBCAM_HREF); //HREF_GPIO_NUM;
|
||||
config.pin_sscb_sda = Pin(GPIO_WEBCAM_SIOD); //SIOD_GPIO_NUM;
|
||||
config.pin_sscb_scl = Pin(GPIO_WEBCAM_SIOC); //SIOC_GPIO_NUM;
|
||||
int16_t xpin;
|
||||
xpin = Pin(GPIO_WEBCAM_PWDN);
|
||||
if (99 == xpin) { xpin = -1; }
|
||||
config.pin_pwdn = xpin; //PWDN_GPIO_NUM;
|
||||
xpin = Pin(GPIO_WEBCAM_RESET);
|
||||
if (99 == xpin) { xpin=-1; }
|
||||
config.pin_reset = xpin; //RESET_GPIO_NUM;
|
||||
} else {
|
||||
// defaults to AI THINKER
|
||||
config.pin_d0 = Y2_GPIO_NUM;
|
||||
config.pin_d1 = Y3_GPIO_NUM;
|
||||
config.pin_d2 = Y4_GPIO_NUM;
|
||||
config.pin_d3 = Y5_GPIO_NUM;
|
||||
config.pin_d4 = Y6_GPIO_NUM;
|
||||
config.pin_d5 = Y7_GPIO_NUM;
|
||||
config.pin_d6 = Y8_GPIO_NUM;
|
||||
config.pin_d7 = Y9_GPIO_NUM;
|
||||
config.pin_xclk = XCLK_GPIO_NUM;
|
||||
config.pin_pclk = PCLK_GPIO_NUM;
|
||||
config.pin_vsync = VSYNC_GPIO_NUM;
|
||||
config.pin_href = HREF_GPIO_NUM;
|
||||
config.pin_sscb_sda = SIOD_GPIO_NUM;
|
||||
config.pin_sscb_scl = SIOC_GPIO_NUM;
|
||||
config.pin_pwdn = PWDN_GPIO_NUM;
|
||||
config.pin_reset = RESET_GPIO_NUM;
|
||||
}
|
||||
#endif
|
||||
|
||||
//ESP.getPsramSize()
|
||||
|
||||
//esp_log_level_set("*", ESP_LOG_INFO);
|
||||
|
||||
|
||||
// if PSRAM IC present, init with UXGA resolution and higher JPEG quality
|
||||
// for larger pre-allocated frame buffer.
|
||||
|
||||
bool psram = psramFound();
|
||||
if (psram) {
|
||||
config.frame_size = FRAMESIZE_UXGA;
|
||||
config.jpeg_quality = 10;
|
||||
config.fb_count = 2;
|
||||
AddLog_P2(WC_LOGLEVEL, PSTR("CAM: PSRAM found"));
|
||||
} else {
|
||||
config.frame_size = FRAMESIZE_VGA;
|
||||
config.jpeg_quality = 12;
|
||||
config.fb_count = 1;
|
||||
AddLog_P2(WC_LOGLEVEL, PSTR("CAM: PSRAM not found"));
|
||||
}
|
||||
|
||||
// stupid workaround camera diver eats up static ram should prefer PSRAM
|
||||
// so we steal static ram to force driver to alloc PSRAM
|
||||
//ESP.getMaxAllocHeap()
|
||||
|
||||
// void *x=malloc(70000);
|
||||
void *x = 0;
|
||||
esp_err_t err = esp_camera_init(&config);
|
||||
if (x) { free(x); }
|
||||
|
||||
if (err != ESP_OK) {
|
||||
AddLog_P2(WC_LOGLEVEL, PSTR("CAM: Init failed with error 0x%x"), err);
|
||||
return 0;
|
||||
}
|
||||
|
||||
sensor_t * wc_s = esp_camera_sensor_get();
|
||||
// initial sensors are flipped vertically and colors are a bit saturated
|
||||
if (OV3660_PID == wc_s->id.PID) {
|
||||
wc_s->set_vflip(wc_s, 1); // flip it back
|
||||
wc_s->set_brightness(wc_s, 1); // up the brightness just a bit
|
||||
wc_s->set_saturation(wc_s, -2); // lower the saturation
|
||||
}
|
||||
// drop down frame size for higher initial frame rate
|
||||
wc_s->set_framesize(wc_s, (framesize_t)fsiz);
|
||||
|
||||
camera_fb_t *wc_fb = esp_camera_fb_get();
|
||||
wc_width = wc_fb->width;
|
||||
wc_height = wc_fb->height;
|
||||
esp_camera_fb_return(wc_fb);
|
||||
|
||||
|
||||
#ifdef USE_FACE_DETECT
|
||||
fd_init();
|
||||
#endif
|
||||
|
||||
AddLog_P2(WC_LOGLEVEL, PSTR("CAM: Initialized"));
|
||||
|
||||
wc_up = 1;
|
||||
if (psram) { wc_up=2; }
|
||||
|
||||
return wc_up;
|
||||
}
|
||||
|
||||
int32_t wc_set_options(uint32_t sel, int32_t value) {
|
||||
int32_t res = 0;
|
||||
sensor_t *s = esp_camera_sensor_get();
|
||||
if (!s) { return -99; }
|
||||
|
||||
switch (sel) {
|
||||
case 0:
|
||||
if (value >= 0) { s->set_framesize(s, (framesize_t)value); }
|
||||
res = s->status.framesize;
|
||||
break;
|
||||
case 1:
|
||||
if (value >= 0) { s->set_special_effect(s, value); }
|
||||
res = s->status.special_effect;
|
||||
break;
|
||||
case 2:
|
||||
if (value >= 0) { s->set_vflip(s, value); }
|
||||
res = s->status.vflip;
|
||||
break;
|
||||
case 3:
|
||||
if (value >= 0) { s->set_hmirror(s, value); }
|
||||
res = s->status.hmirror;
|
||||
break;
|
||||
case 4:
|
||||
if (value >= -4) { s->set_contrast(s, value); }
|
||||
res = s->status.contrast;
|
||||
break;
|
||||
case 5:
|
||||
if (value >= -4) { s->set_brightness(s, value); }
|
||||
res = s->status.brightness;
|
||||
break;
|
||||
case 6:
|
||||
if (value >= -4) { s->set_saturation(s,value); }
|
||||
res = s->status.saturation;
|
||||
break;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
uint32_t wc_get_width(void) {
|
||||
camera_fb_t *wc_fb = esp_camera_fb_get();
|
||||
if (!wc_fb) { return 0; }
|
||||
wc_width = wc_fb->width;
|
||||
esp_camera_fb_return(wc_fb);
|
||||
return wc_width;
|
||||
}
|
||||
|
||||
uint32_t wc_get_height(void) {
|
||||
camera_fb_t *wc_fb = esp_camera_fb_get();
|
||||
if (!wc_fb) { return 0; }
|
||||
wc_height = wc_fb->height;
|
||||
esp_camera_fb_return(wc_fb);
|
||||
return wc_height;
|
||||
}
|
||||
|
||||
#ifndef MAX_PICSTORE
|
||||
#define MAX_PICSTORE 4
|
||||
#endif
|
||||
struct PICSTORE {
|
||||
uint8_t *buff;
|
||||
uint32_t len;
|
||||
};
|
||||
|
||||
struct PICSTORE picstore[MAX_PICSTORE];
|
||||
|
||||
#ifdef COPYFRAME
|
||||
struct PICSTORE tmp_picstore;
|
||||
#endif
|
||||
|
||||
uint32_t get_picstore(int32_t num, uint8_t **buff) {
|
||||
if (num<0) { return MAX_PICSTORE; }
|
||||
*buff = picstore[num].buff;
|
||||
return picstore[num].len;
|
||||
}
|
||||
|
||||
uint32_t wc_get_jpeg(uint8_t **buff) {
|
||||
size_t _jpg_buf_len = 0;
|
||||
uint8_t * _jpg_buf = NULL;
|
||||
camera_fb_t *wc_fb;
|
||||
wc_fb = esp_camera_fb_get();
|
||||
if (!wc_fb) { return 0; }
|
||||
if (wc_fb->format != PIXFORMAT_JPEG) {
|
||||
bool jpeg_converted = frame2jpg(wc_fb, 80, &_jpg_buf, &_jpg_buf_len);
|
||||
if (!jpeg_converted) {
|
||||
_jpg_buf_len = wc_fb->len;
|
||||
_jpg_buf = wc_fb->buf;
|
||||
}
|
||||
} else {
|
||||
_jpg_buf_len = wc_fb->len;
|
||||
_jpg_buf = wc_fb->buf;
|
||||
}
|
||||
esp_camera_fb_return(wc_fb);
|
||||
*buff = _jpg_buf;
|
||||
return _jpg_buf_len;
|
||||
}
|
||||
|
||||
uint32_t wc_get_frame(int32_t bnum) {
|
||||
size_t _jpg_buf_len = 0;
|
||||
uint8_t * _jpg_buf = NULL;
|
||||
camera_fb_t *wc_fb = 0;
|
||||
bool jpeg_converted = false;
|
||||
|
||||
if (bnum < 0) {
|
||||
if (bnum < -MAX_PICSTORE) { bnum=-1; }
|
||||
bnum = -bnum;
|
||||
bnum--;
|
||||
if (picstore[bnum].buff) { free(picstore[bnum].buff); }
|
||||
picstore[bnum].len = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef COPYFRAME
|
||||
if (bnum & 0x10) {
|
||||
bnum &= 0xf;
|
||||
_jpg_buf = tmp_picstore.buff;
|
||||
_jpg_buf_len = tmp_picstore.len;
|
||||
if (!_jpg_buf_len) { return 0; }
|
||||
goto pcopy;
|
||||
}
|
||||
#endif
|
||||
|
||||
wc_fb = esp_camera_fb_get();
|
||||
if (!wc_fb) {
|
||||
AddLog_P2(WC_LOGLEVEL, PSTR("CAM: Can't get frame"));
|
||||
return 0;
|
||||
}
|
||||
if (!bnum) {
|
||||
wc_width = wc_fb->width;
|
||||
wc_height = wc_fb->height;
|
||||
esp_camera_fb_return(wc_fb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (wc_fb->format != PIXFORMAT_JPEG) {
|
||||
jpeg_converted = frame2jpg(wc_fb, 80, &_jpg_buf, &_jpg_buf_len);
|
||||
if (!jpeg_converted){
|
||||
//Serial.println("JPEG compression failed");
|
||||
_jpg_buf_len = wc_fb->len;
|
||||
_jpg_buf = wc_fb->buf;
|
||||
}
|
||||
} else {
|
||||
_jpg_buf_len = wc_fb->len;
|
||||
_jpg_buf = wc_fb->buf;
|
||||
}
|
||||
|
||||
pcopy:
|
||||
if ((bnum < 1) || (bnum > MAX_PICSTORE)) { bnum = 1; }
|
||||
bnum--;
|
||||
if (picstore[bnum].buff) { free(picstore[bnum].buff); }
|
||||
picstore[bnum].buff = (uint8_t *)heap_caps_malloc(_jpg_buf_len+4, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
|
||||
if (picstore[bnum].buff) {
|
||||
memcpy(picstore[bnum].buff, _jpg_buf, _jpg_buf_len);
|
||||
picstore[bnum].len = _jpg_buf_len;
|
||||
} else {
|
||||
AddLog_P2(WC_LOGLEVEL, PSTR("CAM: Can't allocate picstore"));
|
||||
picstore[bnum].len = 0;
|
||||
}
|
||||
if (wc_fb) { esp_camera_fb_return(wc_fb); }
|
||||
if (jpeg_converted) { free(_jpg_buf); }
|
||||
if (!picstore[bnum].buff) { return 0; }
|
||||
|
||||
return _jpg_buf_len;
|
||||
}
|
||||
|
||||
bool HttpCheckPriviledgedAccess(bool);
|
||||
extern ESP8266WebServer *Webserver;
|
||||
|
||||
void HandleImage(void) {
|
||||
if (!HttpCheckPriviledgedAccess(true)) { return; }
|
||||
|
||||
uint32_t bnum = Webserver->arg(F("p")).toInt();
|
||||
if ((bnum < 0) || (bnum > MAX_PICSTORE)) { bnum= 1; }
|
||||
WiFiClient client = Webserver->client();
|
||||
String response = "HTTP/1.1 200 OK\r\n";
|
||||
response += "Content-disposition: inline; filename=cap.jpg\r\n";
|
||||
response += "Content-type: image/jpeg\r\n\r\n";
|
||||
Webserver->sendContent(response);
|
||||
|
||||
if (!bnum) {
|
||||
uint8_t *buff;
|
||||
uint32_t len;
|
||||
len = wc_get_jpeg(&buff);
|
||||
if (len) {
|
||||
client.write(buff,len);
|
||||
free(buff);
|
||||
}
|
||||
} else {
|
||||
bnum--;
|
||||
if (!picstore[bnum].len) {
|
||||
AddLog_P2(WC_LOGLEVEL, PSTR("CAM: No image #: %d"), bnum);
|
||||
return;
|
||||
}
|
||||
client.write((char *)picstore[bnum].buff, picstore[bnum].len);
|
||||
}
|
||||
|
||||
AddLog_P2(WC_LOGLEVEL, PSTR("CAM: Sending image #: %d"), bnum+1);
|
||||
}
|
||||
|
||||
ESP8266WebServer *CamServer;
|
||||
#define BOUNDARY "e8b8c539-047d-4777-a985-fbba6edff11e"
|
||||
|
||||
WiFiClient client;
|
||||
|
||||
void handleMjpeg(void) {
|
||||
AddLog_P2(WC_LOGLEVEL, PSTR("CAM: Handle camserver"));
|
||||
//if (!wc_stream_active) {
|
||||
wc_stream_active = 1;
|
||||
client = CamServer->client();
|
||||
AddLog_P2(WC_LOGLEVEL, PSTR("CAM: Create client"));
|
||||
//}
|
||||
}
|
||||
|
||||
#ifdef USE_FACE_DETECT
|
||||
|
||||
static mtmn_config_t mtmn_config = {0};
|
||||
|
||||
void fd_init(void) {
|
||||
mtmn_config.type = FAST;
|
||||
mtmn_config.min_face = 80;
|
||||
mtmn_config.pyramid = 0.707;
|
||||
mtmn_config.pyramid_times = 4;
|
||||
mtmn_config.p_threshold.score = 0.6;
|
||||
mtmn_config.p_threshold.nms = 0.7;
|
||||
mtmn_config.p_threshold.candidate_number = 20;
|
||||
mtmn_config.r_threshold.score = 0.7;
|
||||
mtmn_config.r_threshold.nms = 0.7;
|
||||
mtmn_config.r_threshold.candidate_number = 10;
|
||||
mtmn_config.o_threshold.score = 0.7;
|
||||
mtmn_config.o_threshold.nms = 0.7;
|
||||
mtmn_config.o_threshold.candidate_number = 1;
|
||||
}
|
||||
|
||||
#define FACE_COLOR_WHITE 0x00FFFFFF
|
||||
#define FACE_COLOR_BLACK 0x00000000
|
||||
#define FACE_COLOR_RED 0x000000FF
|
||||
#define FACE_COLOR_GREEN 0x0000FF00
|
||||
#define FACE_COLOR_BLUE 0x00FF0000
|
||||
#define FACE_COLOR_YELLOW (FACE_COLOR_RED | FACE_COLOR_GREEN)
|
||||
#define FACE_COLOR_CYAN (FACE_COLOR_BLUE | FACE_COLOR_GREEN)
|
||||
#define FACE_COLOR_PURPLE (FACE_COLOR_BLUE | FACE_COLOR_RED)
|
||||
void draw_face_boxes(dl_matrix3du_t *image_matrix, box_array_t *boxes, int face_id);
|
||||
|
||||
/*
|
||||
void draw_face_boxes(dl_matrix3du_t *image_matrix, box_array_t *boxes, int face_id) {
|
||||
int x, y, w, h, i;
|
||||
uint32_t color = FACE_COLOR_YELLOW;
|
||||
if(face_id < 0){
|
||||
color = FACE_COLOR_RED;
|
||||
} else if(face_id > 0){
|
||||
color = FACE_COLOR_GREEN;
|
||||
}
|
||||
fb_data_t fb;
|
||||
fb.width = image_matrix->w;
|
||||
fb.height = image_matrix->h;
|
||||
fb.data = image_matrix->item;
|
||||
fb.bytes_per_pixel = 3;
|
||||
fb.format = FB_BGR888;
|
||||
for (i = 0; i < boxes->len; i++){
|
||||
// rectangle box
|
||||
x = (int)boxes->box[i].box_p[0];
|
||||
y = (int)boxes->box[i].box_p[1];
|
||||
w = (int)boxes->box[i].box_p[2] - x + 1;
|
||||
h = (int)boxes->box[i].box_p[3] - y + 1;
|
||||
fb_gfx_drawFastHLine(&fb, x, y, w, color);
|
||||
fb_gfx_drawFastHLine(&fb, x, y+h-1, w, color);
|
||||
fb_gfx_drawFastVLine(&fb, x, y, h, color);
|
||||
fb_gfx_drawFastVLine(&fb, x+w-1, y, h, color);
|
||||
#if 0
|
||||
// landmark
|
||||
int x0, y0, j;
|
||||
for (j = 0; j < 10; j+=2) {
|
||||
x0 = (int)boxes->landmark[i].landmark_p[j];
|
||||
y0 = (int)boxes->landmark[i].landmark_p[j+1];
|
||||
fb_gfx_fillRect(&fb, x0, y0, 3, 3, color);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
#define DL_SPIRAM_SUPPORT
|
||||
|
||||
uint32_t wc_set_face_detect(int32_t value) {
|
||||
if (value >= 0) { face_detect_time = value; }
|
||||
return faces;
|
||||
}
|
||||
|
||||
uint32_t face_ltime;
|
||||
|
||||
uint32_t detect_face(void);
|
||||
|
||||
uint32_t detect_face(void) {
|
||||
dl_matrix3du_t *image_matrix;
|
||||
size_t out_len, out_width, out_height;
|
||||
uint8_t * out_buf;
|
||||
bool s;
|
||||
bool detected = false;
|
||||
int face_id = 0;
|
||||
camera_fb_t *fb;
|
||||
|
||||
if ((millis() - face_ltime) > face_detect_time) {
|
||||
face_ltime = millis();
|
||||
fb = esp_camera_fb_get();
|
||||
if (!fb) { return ESP_FAIL; }
|
||||
|
||||
image_matrix = dl_matrix3du_alloc(1, fb->width, fb->height, 3);
|
||||
if (!image_matrix) {
|
||||
AddLog_P2(WC_LOGLEVEL, PSTR("CAM: dl_matrix3du_alloc failed"));
|
||||
esp_camera_fb_return(fb);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
out_buf = image_matrix->item;
|
||||
//out_len = fb->width * fb->height * 3;
|
||||
//out_width = fb->width;
|
||||
//out_height = fb->height;
|
||||
|
||||
s = fmt2rgb888(fb->buf, fb->len, fb->format, out_buf);
|
||||
esp_camera_fb_return(fb);
|
||||
if (!s){
|
||||
dl_matrix3du_free(image_matrix);
|
||||
AddLog_P2(WC_LOGLEVEL, PSTR("CAM: to rgb888 failed"));
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
box_array_t *net_boxes = face_detect(image_matrix, &mtmn_config);
|
||||
if (net_boxes){
|
||||
detected = true;
|
||||
faces = net_boxes->len;
|
||||
//if(recognition_enabled){
|
||||
// face_id = run_face_recognition(image_matrix, net_boxes);
|
||||
//}
|
||||
//draw_face_boxes(image_matrix, net_boxes, face_id);
|
||||
free(net_boxes->score);
|
||||
free(net_boxes->box);
|
||||
free(net_boxes->landmark);
|
||||
free(net_boxes);
|
||||
} else {
|
||||
faces = 0;
|
||||
}
|
||||
dl_matrix3du_free(image_matrix);
|
||||
//Serial.printf("face detected: %d",faces);
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void handleMjpeg_task(void) {
|
||||
camera_fb_t *wc_fb;
|
||||
size_t _jpg_buf_len = 0;
|
||||
uint8_t * _jpg_buf = NULL;
|
||||
|
||||
//WiFiClient client = CamServer->client();
|
||||
uint32_t tlen;
|
||||
bool jpeg_converted = false;
|
||||
|
||||
if (!client.connected()) {
|
||||
wc_stream_active = 0;
|
||||
AddLog_P2(WC_LOGLEVEL, PSTR("CAM: Client fail"));
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (1 == wc_stream_active) {
|
||||
client.flush();
|
||||
client.setTimeout(3);
|
||||
AddLog_P2(WC_LOGLEVEL, PSTR("CAM: Start stream"));
|
||||
client.print("HTTP/1.1 200 OK\r\n"
|
||||
"Content-Type: multipart/x-mixed-replace;boundary=" BOUNDARY "\r\n"
|
||||
"\r\n");
|
||||
wc_stream_active = 2;
|
||||
} else {
|
||||
wc_fb = esp_camera_fb_get();
|
||||
if (!wc_fb) {
|
||||
wc_stream_active = 0;
|
||||
AddLog_P2(WC_LOGLEVEL, PSTR("CAM: Frame fail"));
|
||||
goto exit;
|
||||
}
|
||||
|
||||
|
||||
if (wc_fb->format != PIXFORMAT_JPEG) {
|
||||
jpeg_converted = frame2jpg(wc_fb, 80, &_jpg_buf, &_jpg_buf_len);
|
||||
if (!jpeg_converted){
|
||||
AddLog_P2(WC_LOGLEVEL, PSTR("CAM: JPEG compression failed"));
|
||||
_jpg_buf_len = wc_fb->len;
|
||||
_jpg_buf = wc_fb->buf;
|
||||
}
|
||||
} else {
|
||||
_jpg_buf_len = wc_fb->len;
|
||||
_jpg_buf = wc_fb->buf;
|
||||
}
|
||||
|
||||
client.printf("Content-Type: image/jpeg\r\n"
|
||||
"Content-Length: %d\r\n"
|
||||
"\r\n", static_cast<int>(_jpg_buf_len));
|
||||
tlen = client.write(_jpg_buf, _jpg_buf_len);
|
||||
/*
|
||||
if (tlen!=_jpg_buf_len) {
|
||||
esp_camera_fb_return(wc_fb);
|
||||
wc_stream_active=0;
|
||||
AddLog_P2(WC_LOGLEVEL, PSTR("CAM: Send fail"));
|
||||
}*/
|
||||
client.print("\r\n--" BOUNDARY "\r\n");
|
||||
|
||||
#ifdef COPYFRAME
|
||||
if (tmp_picstore.buff) { free(tmp_picstore.buff); }
|
||||
tmp_picstore.buff = (uint8_t *)heap_caps_malloc(_jpg_buf_len+4, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
|
||||
if (tmp_picstore.buff) {
|
||||
memcpy(tmp_picstore.buff, _jpg_buf, _jpg_buf_len);
|
||||
tmp_picstore.len = _jpg_buf_len;
|
||||
} else {
|
||||
tmp_picstore.len = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (jpeg_converted) { free(_jpg_buf); }
|
||||
esp_camera_fb_return(wc_fb);
|
||||
//AddLog_P2(WC_LOGLEVEL, PSTR("CAM: send frame"));
|
||||
|
||||
exit:
|
||||
if (!wc_stream_active) {
|
||||
AddLog_P2(WC_LOGLEVEL, PSTR("CAM: Stream exit"));
|
||||
client.flush();
|
||||
client.stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CamHandleRoot(void) {
|
||||
//CamServer->redirect("http://" + String(ip) + ":81/cam.mjpeg");
|
||||
CamServer->sendHeader("Location", WiFi.localIP().toString() + ":81/cam.mjpeg");
|
||||
CamServer->send(302, "", "");
|
||||
AddLog_P2(WC_LOGLEVEL, PSTR("CAM: root called"));
|
||||
}
|
||||
|
||||
uint16_t motion_detect;
|
||||
uint32_t motion_ltime;
|
||||
uint32_t motion_trigger;
|
||||
uint32_t motion_brightness;
|
||||
uint8_t *last_motion_buffer;
|
||||
|
||||
uint32_t wc_set_motion_detect(int32_t value) {
|
||||
if (value >= 0) { motion_detect = value; }
|
||||
if (-1 == value) {
|
||||
return motion_trigger;
|
||||
} else {
|
||||
return motion_brightness;
|
||||
}
|
||||
}
|
||||
|
||||
// optional motion detector
|
||||
void detect_motion(void) {
|
||||
camera_fb_t *wc_fb;
|
||||
uint8_t *out_buf = 0;
|
||||
|
||||
if ((millis()-motion_ltime) > motion_detect) {
|
||||
motion_ltime = millis();
|
||||
wc_fb = esp_camera_fb_get();
|
||||
if (!wc_fb) { return; }
|
||||
|
||||
if (!last_motion_buffer) {
|
||||
last_motion_buffer=(uint8_t *)heap_caps_malloc((wc_fb->width*wc_fb->height)+4, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
|
||||
}
|
||||
if (last_motion_buffer) {
|
||||
if (PIXFORMAT_JPEG == wc_fb->format) {
|
||||
out_buf = (uint8_t *)heap_caps_malloc((wc_fb->width*wc_fb->height*3)+4, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
|
||||
if (out_buf) {
|
||||
fmt2rgb888(wc_fb->buf, wc_fb->len, wc_fb->format, out_buf);
|
||||
uint32_t x, y;
|
||||
uint8_t *pxi = out_buf;
|
||||
uint8_t *pxr = last_motion_buffer;
|
||||
// convert to bw
|
||||
uint64_t accu = 0;
|
||||
uint64_t bright = 0;
|
||||
for (y = 0; y < wc_fb->height; y++) {
|
||||
for (x = 0; x < wc_fb->width; x++) {
|
||||
int32_t gray = (pxi[0] + pxi[1] + pxi[2]) / 3;
|
||||
int32_t lgray = pxr[0];
|
||||
pxr[0] = gray;
|
||||
pxi += 3;
|
||||
pxr++;
|
||||
accu += abs(gray - lgray);
|
||||
bright += gray;
|
||||
}
|
||||
}
|
||||
motion_trigger = accu / ((wc_fb->height * wc_fb->width) / 100);
|
||||
motion_brightness = bright / ((wc_fb->height * wc_fb->width) / 100);
|
||||
free(out_buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
esp_camera_fb_return(wc_fb);
|
||||
}
|
||||
}
|
||||
|
||||
void wc_show_stream(void) {
|
||||
if (CamServer) {
|
||||
WSContentSend_P(PSTR("<p></p><center><img src='http://%s:81/stream' alt='Webcam stream' style='width:99%%;'></center><p></p>"),
|
||||
WiFi.localIP().toString().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t wc_set_streamserver(uint32_t flag) {
|
||||
if (global_state.wifi_down) { return 0; }
|
||||
|
||||
wc_stream_active = 0;
|
||||
|
||||
if (flag) {
|
||||
if (!CamServer) {
|
||||
CamServer = new ESP8266WebServer(81);
|
||||
CamServer->on("/", CamHandleRoot);
|
||||
CamServer->on("/cam.mjpeg", handleMjpeg);
|
||||
CamServer->on("/cam.jpg", handleMjpeg);
|
||||
CamServer->on("/stream", handleMjpeg);
|
||||
AddLog_P2(WC_LOGLEVEL, PSTR("CAM: Stream init"));
|
||||
CamServer->begin();
|
||||
}
|
||||
} else {
|
||||
if (CamServer) {
|
||||
CamServer->stop();
|
||||
delete CamServer;
|
||||
CamServer = NULL;
|
||||
AddLog_P2(WC_LOGLEVEL, PSTR("CAM: Stream exit"));
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void WcStreamControl(uint32_t resolution) {
|
||||
wc_set_streamserver(resolution);
|
||||
/*if (0 == resolution) {
|
||||
resolution=-1;
|
||||
}*/
|
||||
wc_setup(resolution);
|
||||
}
|
||||
|
||||
void wc_loop(void) {
|
||||
if (CamServer) { CamServer->handleClient(); }
|
||||
if (wc_stream_active) { handleMjpeg_task(); }
|
||||
if (motion_detect) { detect_motion(); }
|
||||
#ifdef USE_FACE_DETECT
|
||||
if (face_detect_time) { detect_face(); }
|
||||
#endif
|
||||
}
|
||||
|
||||
void wc_pic_setup(void) {
|
||||
Webserver->on("/wc.jpg", HandleImage);
|
||||
Webserver->on("/wc.mjpeg", HandleImage);
|
||||
}
|
||||
|
||||
/*
|
||||
typedef enum {
|
||||
// FRAMESIZE_96x96, // 96x96
|
||||
FRAMESIZE_QQVGA, // 160x120 0
|
||||
FRAMESIZE_QQVGA2, // 128x160 1
|
||||
FRAMESIZE_QCIF, // 176x144 2
|
||||
FRAMESIZE_HQVGA, // 240x176 3
|
||||
|
||||
// FRAMESIZE_240x240, // 240x240 3
|
||||
|
||||
FRAMESIZE_QVGA, // 320x240 4
|
||||
FRAMESIZE_CIF, // 400x296 5
|
||||
FRAMESIZE_VGA, // 640x480 6
|
||||
FRAMESIZE_SVGA, // 800x600 7
|
||||
FRAMESIZE_XGA, // 1024x768 8
|
||||
FRAMESIZE_SXGA, // 1280x1024 9
|
||||
FRAMESIZE_UXGA, // 1600x1200 10
|
||||
|
||||
|
||||
FRAMESIZE_QXGA, // 2048*1536
|
||||
FRAMESIZE_INVALID
|
||||
} framesize_t;
|
||||
|
||||
flash led = gpio4
|
||||
red led = gpio 33
|
||||
*/
|
||||
|
||||
void WcInit(void) {
|
||||
if (Settings.esp32_webcam_resolution > 10) {
|
||||
Settings.esp32_webcam_resolution = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Commands
|
||||
\*********************************************************************************************/
|
||||
|
||||
#define D_CMND_WEBCAM "Webcam"
|
||||
|
||||
const char kWCCommands[] PROGMEM = "|" // no prefix
|
||||
D_CMND_WEBCAM
|
||||
;
|
||||
|
||||
void (* const WCCommand[])(void) PROGMEM = {
|
||||
&CmndWebcam,
|
||||
};
|
||||
|
||||
void CmndWebcam(void) {
|
||||
uint32_t flag = 0;
|
||||
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 10)) {
|
||||
Settings.esp32_webcam_resolution=XdrvMailbox.payload;
|
||||
WcStreamControl(Settings.esp32_webcam_resolution);
|
||||
}
|
||||
if (CamServer) { flag = 1; }
|
||||
Response_P(PSTR("{\"" D_CMND_WEBCAM "\":{\"Streaming\":\"%s\"}"),GetStateText(flag));
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Interface
|
||||
\*********************************************************************************************/
|
||||
|
||||
bool Xdrv39(uint8_t function) {
|
||||
bool result = false;
|
||||
|
||||
switch (function) {
|
||||
case FUNC_LOOP:
|
||||
wc_loop();
|
||||
break;
|
||||
case FUNC_WEB_ADD_HANDLER:
|
||||
wc_pic_setup();
|
||||
break;
|
||||
case FUNC_WEB_ADD_MAIN_BUTTON:
|
||||
//if (Settings.esp32_webcam_resolution) {
|
||||
#ifndef USE_SCRIPT
|
||||
WcStreamControl(Settings.esp32_webcam_resolution);
|
||||
delay(50); // Give the webcam webserver some time to prepare the stream
|
||||
wc_show_stream();
|
||||
#endif
|
||||
//}
|
||||
break;
|
||||
case FUNC_COMMAND:
|
||||
result = DecodeCommand(kWCCommands, WCCommand);
|
||||
break;
|
||||
case FUNC_PRE_INIT:
|
||||
WcInit();
|
||||
break;
|
||||
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif // USE_WEBCAM
|
||||
#endif // ESP32
|
@ -250,9 +250,6 @@ void HlwDrvInit(void)
|
||||
Hlw.model_type = 0; // HLW8012
|
||||
if (PinUsed(GPIO_HJL_CF)) {
|
||||
SetPin(Pin(GPIO_HJL_CF), GPIO_HLW_CF);
|
||||
#ifdef LEGACY_GPIO_ARRAY
|
||||
SetPin(99, GPIO_HJL_CF);
|
||||
#endif
|
||||
Hlw.model_type = 1; // HJL-01/BL0937
|
||||
}
|
||||
|
||||
@ -261,9 +258,6 @@ void HlwDrvInit(void)
|
||||
Hlw.ui_flag = true; // Voltage on high
|
||||
if (PinUsed(GPIO_NRG_SEL_INV)) {
|
||||
SetPin(Pin(GPIO_NRG_SEL_INV), GPIO_NRG_SEL);
|
||||
#ifdef LEGACY_GPIO_ARRAY
|
||||
SetPin(99, GPIO_NRG_SEL_INV);
|
||||
#endif
|
||||
Hlw.ui_flag = false; // Voltage on low
|
||||
}
|
||||
|
||||
|
@ -317,11 +317,18 @@ void AdcShow(bool json)
|
||||
\*********************************************************************************************/
|
||||
|
||||
const char kAdcCommands[] PROGMEM = "|" // No prefix
|
||||
D_CMND_ADC "|" D_CMND_ADCS "|" D_CMND_ADCPARAM;
|
||||
#ifdef ESP8266
|
||||
D_CMND_ADC "|" D_CMND_ADCS "|"
|
||||
#endif // ESP8266
|
||||
D_CMND_ADCPARAM;
|
||||
|
||||
void (* const AdcCommand[])(void) PROGMEM = {
|
||||
&CmndAdc, &CmndAdcs, &CmndAdcParam };
|
||||
#ifdef ESP8266
|
||||
&CmndAdc, &CmndAdcs,
|
||||
#endif // ESP8266
|
||||
&CmndAdcParam };
|
||||
|
||||
#ifdef ESP8266
|
||||
void CmndAdc(void)
|
||||
{
|
||||
if (ValidAdc() && (XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < ADC0_END)) {
|
||||
@ -346,6 +353,7 @@ void CmndAdcs(void)
|
||||
}
|
||||
ResponseJsonEndEnd();
|
||||
}
|
||||
#endif // ESP8266
|
||||
|
||||
void CmndAdcParam(void)
|
||||
{
|
||||
|
@ -64,8 +64,8 @@
|
||||
|
||||
// TODO() : Move to my_user_config.h file
|
||||
#define USE_APDS9960_GESTURE // Enable Gesture feature (+2k code)
|
||||
#define USE_APDS9960_PROXIMITY // Enable Proximity feature (Not use)
|
||||
#define USE_APDS9960_COLOR // Enable Color feature (Not use)
|
||||
#define USE_APDS9960_PROXIMITY // Enable Proximity feature (>50 code)
|
||||
#define USE_APDS9960_COLOR // Enable Color feature (+0.8k code)
|
||||
|
||||
|
||||
/* Gesture parameters */
|
||||
@ -96,16 +96,19 @@ const char APDS9960_TAG[] PROGMEM = "APDS9960"; // Only one actualy
|
||||
#ifdef USE_WEBSERVER
|
||||
|
||||
#ifdef USE_APDS9960_GESTURE
|
||||
|
||||
const char HTTP_SNS_GESTURE[] PROGMEM = "{s}%s " D_GESTURE "{m}%s{e}";
|
||||
|
||||
#endif // USE_APDS9960_GESTURE
|
||||
|
||||
#ifdef USE_APDS9960_COLOR
|
||||
const char HTTP_SNS_COLOR_RED[] PROGMEM = "{s}%s " D_COLOR_RED "{m}%u{e}";
|
||||
const char HTTP_SNS_COLOR_GREEN[] PROGMEM = "{s}%s " D_COLOR_GREEN "{m}%u{e}";
|
||||
const char HTTP_SNS_COLOR_BLUE[] PROGMEM = "{s}%s " D_COLOR_BLUE "{m}%u{e}";
|
||||
const char HTTP_SNS_CCT[] PROGMEM = "{s}%s " D_CCT "{m}%u " D_UNIT_KELVIN "{e}";
|
||||
#endif // USE_APDS9960_COLOR
|
||||
|
||||
#ifdef USE_APDS9960_PROXIMITY
|
||||
const char HTTP_SNS_PROXIMITY[] PROGMEM = "{s}%s " D_PROXIMITY "{m}%u{e}";
|
||||
#endif // USE_APDS9960_PROXIMITY
|
||||
|
||||
#endif // USE_WEBSERVER
|
||||
|
||||
@ -321,6 +324,7 @@ typedef struct gesture_type {
|
||||
|
||||
#endif // USE_APDS9960_GESTURE
|
||||
|
||||
#if defined(USE_APDS9960_COLOR) || defined(USE_APDS9960_PROXIMITY)
|
||||
typedef struct color_data_type {
|
||||
uint16_t a; // measured ambient
|
||||
uint16_t r; // Red
|
||||
@ -331,21 +335,21 @@ typedef struct color_data_type {
|
||||
uint16_t cct; // calculated color temperature
|
||||
uint16_t lux; // calculated illuminance - atm only from rgb
|
||||
} color_data_t;
|
||||
#endif // USE_APDS9960_COLOR || USE_APDS9960_PROXIMITY
|
||||
|
||||
/******************************************************************************\
|
||||
* Globals
|
||||
\******************************************************************************/
|
||||
|
||||
#ifdef USE_APDS9960_GESTURE
|
||||
|
||||
gesture_data_t gesture_data;
|
||||
gesture_t gesture;
|
||||
|
||||
#endif // USE_APDS9960_GESTURE
|
||||
char currentGesture[6];
|
||||
#endif // USE_APDS9960_GESTURE
|
||||
|
||||
|
||||
#if defined(USE_APDS9960_COLOR) || defined(USE_APDS9960_PROXIMITY)
|
||||
color_data_t color_data;
|
||||
#endif // USE_APDS9960_COLOR || USE_APDS9960_PROXIMITY
|
||||
|
||||
volatile uint8_t recovery_loop_counter = 0; // count number of stateloops to switch the sensor off, if needed
|
||||
bool APDS9960_overload = false;
|
||||
@ -357,6 +361,7 @@ uint8_t gesture_mode = 1;
|
||||
* Helper functions
|
||||
\******************************************************************************/
|
||||
|
||||
#ifdef USE_APDS9960_COLOR
|
||||
/**
|
||||
* Taken from the Adafruit-library
|
||||
* @brief Converts the raw R/G/B values to color temperature in degrees
|
||||
@ -388,6 +393,7 @@ void calculateColorTemperature(void) {
|
||||
|
||||
return;
|
||||
}
|
||||
#endif // USE_APDS9960_COLOR
|
||||
|
||||
/******************************************************************************\
|
||||
* Getters and setters for register values
|
||||
@ -1249,7 +1255,6 @@ bool APDS9960_init(void) {
|
||||
|
||||
/* Set default values for gesture sense registers */
|
||||
#ifdef USE_APDS9960_GESTURE
|
||||
|
||||
setGestureEnterThresh(DEFAULT_GPENTH);
|
||||
setGestureExitThresh(DEFAULT_GEXTH);
|
||||
|
||||
@ -1267,7 +1272,6 @@ bool APDS9960_init(void) {
|
||||
I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GCONF3, DEFAULT_GCONF3);
|
||||
|
||||
setGestureIntEnable(DEFAULT_GIEN);
|
||||
|
||||
#endif // USE_APDS9960_GESTURE
|
||||
|
||||
disablePower(); // go to sleep
|
||||
@ -1543,6 +1547,7 @@ inline void disablePower(void) {
|
||||
* Ambient light and color sensor controls
|
||||
\******************************************************************************/
|
||||
|
||||
#if defined(USE_APDS9960_COLOR) || defined(USE_APDS9960_PROXIMITY)
|
||||
/**
|
||||
* @brief Reads the ARGB-Data and fills color_data
|
||||
*/
|
||||
@ -1553,6 +1558,38 @@ inline void readAllColorAndProximityData(void) {
|
||||
}
|
||||
}
|
||||
|
||||
void APDS9960_adjustATime(void) { // not really used atm
|
||||
// readAllColorAndProximityData();
|
||||
I2cValidRead16LE(&color_data.a, APDS9960_I2C_ADDR, APDS9960_CDATAL);
|
||||
// disablePower();
|
||||
|
||||
if (color_data.a < (uint16_t)20) {
|
||||
APDS9960_aTime = 0x40;
|
||||
} else if (color_data.a < (uint16_t)40) {
|
||||
APDS9960_aTime = 0x80;
|
||||
} else if (color_data.a < (uint16_t)50) {
|
||||
APDS9960_aTime = DEFAULT_ATIME;
|
||||
} else if (color_data.a < (uint16_t)70) {
|
||||
APDS9960_aTime = 0xc0;
|
||||
}
|
||||
|
||||
if (color_data.a < 200) {
|
||||
APDS9960_aTime = 0xe9;
|
||||
}
|
||||
/* if (color_data.a < 10000){
|
||||
APDS9960_aTime = 0xF0;
|
||||
}*/
|
||||
else {
|
||||
APDS9960_aTime = 0xff;
|
||||
}
|
||||
|
||||
// disableLightSensor();
|
||||
I2cWrite8(APDS9960_I2C_ADDR, APDS9960_ATIME, APDS9960_aTime);
|
||||
enablePower();
|
||||
enableLightSensor();
|
||||
delay(20);
|
||||
}
|
||||
#endif // USE_APDS9960_COLOR || USE_APDS9960_PROXIMITY
|
||||
|
||||
/******************************************************************************\
|
||||
* High-level gesture controls
|
||||
@ -1754,42 +1791,6 @@ void handleGesture(void) {
|
||||
}
|
||||
}
|
||||
|
||||
#endif // USE_APDS9960_GESTURE
|
||||
|
||||
void APDS9960_adjustATime(void) { // not really used atm
|
||||
// readAllColorAndProximityData();
|
||||
I2cValidRead16LE(&color_data.a, APDS9960_I2C_ADDR, APDS9960_CDATAL);
|
||||
// disablePower();
|
||||
|
||||
if (color_data.a < (uint16_t)20) {
|
||||
APDS9960_aTime = 0x40;
|
||||
} else if (color_data.a < (uint16_t)40) {
|
||||
APDS9960_aTime = 0x80;
|
||||
} else if (color_data.a < (uint16_t)50) {
|
||||
APDS9960_aTime = DEFAULT_ATIME;
|
||||
} else if (color_data.a < (uint16_t)70) {
|
||||
APDS9960_aTime = 0xc0;
|
||||
}
|
||||
|
||||
if (color_data.a < 200) {
|
||||
APDS9960_aTime = 0xe9;
|
||||
}
|
||||
/* if (color_data.a < 10000){
|
||||
APDS9960_aTime = 0xF0;
|
||||
}*/
|
||||
else {
|
||||
APDS9960_aTime = 0xff;
|
||||
}
|
||||
|
||||
// disableLightSensor();
|
||||
I2cWrite8(APDS9960_I2C_ADDR, APDS9960_ATIME, APDS9960_aTime);
|
||||
enablePower();
|
||||
enableLightSensor();
|
||||
delay(20);
|
||||
}
|
||||
|
||||
#ifdef USE_APDS9960_GESTURE
|
||||
|
||||
void APDS9960_loop(void) {
|
||||
if (recovery_loop_counter > 0) {
|
||||
recovery_loop_counter -= 1;
|
||||
@ -1845,7 +1846,9 @@ void APDS9960_detect(void) {
|
||||
APDS9960_type = 0;
|
||||
}
|
||||
|
||||
#ifdef USE_APDS9960_GESTURE
|
||||
currentGesture[0] = '\0';
|
||||
#endif // USE_APDS9960_GESTURE
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
@ -1856,6 +1859,8 @@ void APDS9960_show(bool json) {
|
||||
if (!APDS9960_type) { return; }
|
||||
|
||||
if (!gesture_mode && !APDS9960_overload) {
|
||||
|
||||
#if defined(USE_APDS9960_COLOR) || defined(USE_APDS9960_PROXIMITY)
|
||||
uint16_t ambient;
|
||||
|
||||
readAllColorAndProximityData();
|
||||
@ -1865,8 +1870,11 @@ void APDS9960_show(bool json) {
|
||||
I2cWrite8(APDS9960_I2C_ADDR, APDS9960_ATIME, DEFAULT_ATIME); // reset to default
|
||||
enableLightSensor();*/
|
||||
|
||||
#ifdef USE_APDS9960_COLOR
|
||||
calculateColorTemperature(); // and calculate Lux
|
||||
#endif // USE_APDS9960_COLOR
|
||||
if (json) {
|
||||
#if defined(USE_APDS9960_COLOR) && defined(USE_APDS9960_PROXIMITY)
|
||||
ResponseAppend_P(PSTR(",\"%s\":{\"Red\":%u,\"Green\":%u,\"Blue\":%u,\"" D_JSON_ILLUMINANCE "\":%u,\"CCT\":%u,\"Proximity\":%u}"),
|
||||
APDS9960_TAG,
|
||||
color_data.r,
|
||||
@ -1875,16 +1883,44 @@ void APDS9960_show(bool json) {
|
||||
ambient,
|
||||
color_data.cct,
|
||||
color_data.p);
|
||||
#else
|
||||
|
||||
#ifdef USE_APDS9960_COLOR
|
||||
ResponseAppend_P(PSTR(",\"%s\":{\"Red\":%u,\"Green\":%u,\"Blue\":%u,\"" D_JSON_ILLUMINANCE "\":%u,\"CCT\":%u}"),
|
||||
APDS9960_TAG,
|
||||
color_data.r,
|
||||
color_data.g,
|
||||
color_data.b,
|
||||
ambient,
|
||||
color_data.cct);
|
||||
#endif // USE_APDS9960_COLOR
|
||||
|
||||
#ifdef USE_APDS9960_PROXIMITY
|
||||
ResponseAppend_P(PSTR(",\"%s\":{\"Proximity\":%u}"),
|
||||
APDS9960_TAG,
|
||||
color_data.p);
|
||||
#endif // USE_APDS9960_PROXIMITY
|
||||
|
||||
#endif // USE_APDS9960_COLOR && USE_APDS9960_PROXIMITY
|
||||
#ifdef USE_WEBSERVER
|
||||
} else {
|
||||
|
||||
#ifdef USE_APDS9960_COLOR
|
||||
WSContentSend_PD(HTTP_SNS_COLOR_RED, APDS9960_TAG, color_data.r);
|
||||
WSContentSend_PD(HTTP_SNS_COLOR_GREEN, APDS9960_TAG, color_data.g);
|
||||
WSContentSend_PD(HTTP_SNS_COLOR_BLUE, APDS9960_TAG, color_data.b);
|
||||
WSContentSend_PD(HTTP_SNS_ILLUMINANCE, APDS9960_TAG, ambient);
|
||||
WSContentSend_PD(HTTP_SNS_CCT, APDS9960_TAG, color_data.cct);
|
||||
#endif // USE_APDS9960_COLOR
|
||||
|
||||
#ifdef USE_APDS9960_PROXIMITY
|
||||
WSContentSend_PD(HTTP_SNS_PROXIMITY, APDS9960_TAG, color_data.p);
|
||||
#endif // USE_APDS9960_PROXIMITY
|
||||
|
||||
#endif // USE_WEBSERVER
|
||||
}
|
||||
#endif // USE_APDS9960_COLOR || USE_APDS9960_PROXIMITY
|
||||
|
||||
#ifdef USE_APDS9960_GESTURE
|
||||
} else {
|
||||
if (currentGesture[0] != '\0') {
|
||||
@ -1898,6 +1934,7 @@ void APDS9960_show(bool json) {
|
||||
}
|
||||
}
|
||||
#endif // USE_APDS9960_GESTURE
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1831,18 +1831,17 @@ uint8_t *script_meter;
|
||||
#endif
|
||||
|
||||
bool Gpio_used(uint8_t gpiopin) {
|
||||
#ifdef LEGACY_GPIO_ARRAY
|
||||
for (uint16_t i=0;i<GPIO_SENSOR_END;i++) { // Theo/Gemu: This needs to change when pin[] has becomes real pin array
|
||||
// if (pin[i]==gpiopin) {
|
||||
/*
|
||||
for (uint16_t i=0;i<GPIO_SENSOR_END;i++) {
|
||||
// if (pin_gpio[i]==gpiopin) {
|
||||
if (Pin(i)==gpiopin) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if ((gpiopin < ARRAY_SIZE(pin)) && (pin[gpiopin] > 0)) {
|
||||
*/
|
||||
if ((gpiopin < ARRAY_SIZE(gpio_pin)) && (gpio_pin[gpiopin] > 0)) {
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -548,14 +548,14 @@ void AS3935EverySecond() {
|
||||
as3935_sensor.mqtt_irq = 0;
|
||||
// start http times
|
||||
as3935_sensor.http_count_start = 1;
|
||||
as3935_sensor.http_count = 0;
|
||||
as3935_sensor.icount++; // Int counter
|
||||
as3935_sensor.detected = false;
|
||||
}
|
||||
|
||||
if (as3935_sensor.http_count_start) as3935_sensor.http_count++;
|
||||
// clear Http
|
||||
if (as3935_sensor.http_count == as3935_sensor.http_timer) {
|
||||
as3935_sensor.http_count = 0;
|
||||
if (as3935_sensor.http_count > as3935_sensor.http_timer) {
|
||||
as3935_sensor.http_count_start = 0;
|
||||
as3935_sensor.http_intensity = 0;
|
||||
as3935_sensor.http_distance = 0;
|
||||
|
Loading…
x
Reference in New Issue
Block a user