Merge branch 'development' into new-windmeter-sensor

This commit is contained in:
Matteo Albinola 2020-05-02 15:10:56 +02:00
commit 691e1e9653
153 changed files with 17007 additions and 838 deletions

View File

@ -8,5 +8,5 @@
- [ ] 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 pass CI tests. **Your PR cannot be merged unless tests pass**
- [ ] I accept the [CLA](https://github.com/arendst/Tasmota/blob/development/CONTRIBUTING.md#contributor-license-agreement-cla).

441
.github/workflows/CI_github.yml vendored Normal file
View 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

View File

@ -22,7 +22,7 @@ In addition to the [release webpage](https://github.com/arendst/Tasmota/releases
[![Dev Version](https://img.shields.io/badge/development%20version-v8.2.x.x-blue.svg)](https://github.com/arendst/Tasmota)
[![Download Dev](https://img.shields.io/badge/download-development-yellow.svg)](http://thehackbox.org/tasmota/)
[![Build Status](https://img.shields.io/travis/arendst/Tasmota.svg)](https://travis-ci.org/arendst/Tasmota)
![Tasmota CI](https://github.com/arendst/Tasmota/workflows/Tasmota%20CI/badge.svg)
See [tasmota/CHANGELOG.md](tasmota/CHANGELOG.md) for detailed change information.

View File

@ -61,7 +61,7 @@ The following binary downloads have been compiled with ESP8266/Arduino library c
- Change light scheme 2,3,4 cycle time speed from 24,48,72,... seconds to 4,6,12,24,36,48,... seconds (#8034)
- Change remove floating point libs from IRAM
- Change remove MQTT Info messages on restart for DeepSleep Wake (#8044)
- Change IRremoteESP8266 library updated to v2.7.5
- Change IRremoteESP8266 library updated to v2.7.6
- Fix possible Relay toggle on (OTA) restart
- Fix PWM flickering during wifi connection (#8046)
- Fix Zigbee sending wrong Sat value with Hue emulation
@ -78,6 +78,7 @@ The following binary downloads have been compiled with ESP8266/Arduino library c
- Add command ``SetOption73 1`` for button decoupling and send multi-press and hold MQTT messages by Federico Leoni (#8235)
- Add command ``SetOption90 1`` to disable non-json MQTT messages (#8044)
- Add command ``SetOption91 1`` to enable fading at startup / power on
- Add command ``SetOption92 1`` to set PWM Mode from regular PWM to ColorTemp control (Xiaomi Philips ...)
- Add command ``Sensor10 0/1/2`` to control BH1750 resolution - 0 = High (default), 1 = High2, 2 = Low (#8016)
- Add command ``Sensor10 31..254`` to control BH1750 measurement time which defaults to 69 (#8016)
- Add command ``Sensor18 0..32000`` to control PMS5003 sensor interval to extend lifetime by Gene Ruebsamen (#8128)
@ -95,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

View 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.

File diff suppressed because it is too large Load Diff

View 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();
}
}

View 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("----------------");
}
}

File diff suppressed because it is too large Load Diff

View 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()
{
}

View 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);
}

View 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

View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View 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

View 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

View 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

View 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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View 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

View 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

View 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

View 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

View 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

View 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

View File

@ -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

View File

@ -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
; *** Esp8266 Arduino core 2.7.0
platform = espressif8266@2.4.0
platform_packages = framework-arduinoespressif8266 @ https://github.com/esp8266/Arduino.git#36e047e908cfa6eafaaf824988070b49f2c2ff2a
platform_packages = framework-arduinoespressif8266 @ https://github.com/esp8266/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)

View File

@ -70,67 +70,19 @@ 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
[tasmota_stage]
; *** Esp8266 core for Arduino version Tasmota stage
platform = espressif8266@2.4.0
platform_packages = framework-arduinoespressif8266 @ https://github.com/esp8266/Arduino.git#36e047e908cfa6eafaaf824988070b49f2c2ff2a
build_flags = ${esp82xx_defaults.build_flags}
@ -174,7 +126,7 @@ build_flags = ${esp82xx_defaults.build_flags}
; -lstdc++-exc
[core_stage]
; *** Esp8266 core for Arduino version latest beta
; *** Esp8266 core for Arduino version latest development version
platform = espressif8266@2.4.0
platform_packages = framework-arduinoespressif8266 @ https://github.com/esp8266/Arduino.git
build_flags = ${esp82xx_defaults.build_flags}

View File

@ -1,5 +1,9 @@
## Unreleased (development)
### 8.2.0.6 20200501
- Add experimental basic support for Tasmota on ESP32 based on work by Jörg Schüler-Maroldt
### 8.2.0.5 20200425
- Breaking Change Device Groups multicast address and port (#8270)
@ -12,6 +16,7 @@
- Fix Zigbee DimmerUp/DimmerDown malformed
- Add config version tag
- Add command ``SetOption73 1`` for button decoupling and send multi-press and hold MQTT messages by Federico Leoni (#8235)
- Add command ``SetOption92 1`` to set PWM Mode from regular PWM to ColorTemp control (Xiaomi Philips ...)
- Add command ``SO`` as shortcut for command ``SetOption``
### 8.2.0.3 20200329

View File

@ -667,6 +667,27 @@
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
#define D_SENSOR_AS3935 "AS3935"
#define D_SENSOR_WINDMETER_SPEED "WindMeter Speed"
#define D_GPIO_WEBCAM_PWDN_GPIO_NUM "CAM_PWDN"
#define D_GPIO_WEBCAM_RESET_GPIO_NUM "CAM_RESET"
#define D_GPIO_WEBCAM_XCLK_GPIO_NUM "CAM_XCLK"
#define D_GPIO_WEBCAM_SIOD_GPIO_NUM "CAM_SIOD"
#define D_GPIO_WEBCAM_SIOC_GPIO_NUM "CAM_SIOC"
#define D_GPIO_WEBCAM_Y9_GPIO_NUM "CAM_Y9"
#define D_GPIO_WEBCAM_Y8_GPIO_NUM "CAM_Y8"
#define D_GPIO_WEBCAM_Y7_GPIO_NUM "CAM_Y7"
#define D_GPIO_WEBCAM_Y6_GPIO_NUM "CAM_Y6"
#define D_GPIO_WEBCAM_Y5_GPIO_NUM "CAM_Y5"
#define D_GPIO_WEBCAM_Y4_GPIO_NUM "CAM_Y4"
#define D_GPIO_WEBCAM_Y3_GPIO_NUM "CAM_Y3"
#define D_GPIO_WEBCAM_Y2_GPIO_NUM "CAM_Y2"
#define D_GPIO_WEBCAM_VSYNC_GPIO_NUM "CAM_VSYNC"
#define D_GPIO_WEBCAM_HREF_GPIO_NUM "CAM_HREF"
#define D_GPIO_WEBCAM_PCLK_GPIO_NUM "CAM_PCLK"
#define D_GPIO_WEBCAM_PSCLK_GPIO_NUM "CAM_PSCLK"
#define D_GPIO_WEBCAM_HSD1_GPIO_NUM "CAM_HSD1"
#define D_GPIO_WEBCAM_HSD2_GPIO_NUM "CAM_HSD2"
#define D_GPIO_WEBCAM_HSD3_GPIO_NUM "CAM_HSD3"
#define D_GPIO_WEBCAM_PSRCS_GPIO_NUM "CAM_PSRCS"
// Units
#define D_UNIT_AMPERE "A"

View File

@ -667,6 +667,27 @@
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
#define D_SENSOR_AS3935 "AS3935"
#define D_SENSOR_WINDMETER_SPEED "WindMeter Speed"
#define D_GPIO_WEBCAM_PWDN_GPIO_NUM "CAM_PWDN"
#define D_GPIO_WEBCAM_RESET_GPIO_NUM "CAM_RESET"
#define D_GPIO_WEBCAM_XCLK_GPIO_NUM "CAM_XCLK"
#define D_GPIO_WEBCAM_SIOD_GPIO_NUM "CAM_SIOD"
#define D_GPIO_WEBCAM_SIOC_GPIO_NUM "CAM_SIOC"
#define D_GPIO_WEBCAM_Y9_GPIO_NUM "CAM_Y9"
#define D_GPIO_WEBCAM_Y8_GPIO_NUM "CAM_Y8"
#define D_GPIO_WEBCAM_Y7_GPIO_NUM "CAM_Y7"
#define D_GPIO_WEBCAM_Y6_GPIO_NUM "CAM_Y6"
#define D_GPIO_WEBCAM_Y5_GPIO_NUM "CAM_Y5"
#define D_GPIO_WEBCAM_Y4_GPIO_NUM "CAM_Y4"
#define D_GPIO_WEBCAM_Y3_GPIO_NUM "CAM_Y3"
#define D_GPIO_WEBCAM_Y2_GPIO_NUM "CAM_Y2"
#define D_GPIO_WEBCAM_VSYNC_GPIO_NUM "CAM_VSYNC"
#define D_GPIO_WEBCAM_HREF_GPIO_NUM "CAM_HREF"
#define D_GPIO_WEBCAM_PCLK_GPIO_NUM "CAM_PCLK"
#define D_GPIO_WEBCAM_PSCLK_GPIO_NUM "CAM_PSCLK"
#define D_GPIO_WEBCAM_HSD1_GPIO_NUM "CAM_HSD1"
#define D_GPIO_WEBCAM_HSD2_GPIO_NUM "CAM_HSD2"
#define D_GPIO_WEBCAM_HSD3_GPIO_NUM "CAM_HSD3"
#define D_GPIO_WEBCAM_PSRCS_GPIO_NUM "CAM_PSRCS"
// Units
#define D_UNIT_AMPERE "A"

View File

@ -667,6 +667,27 @@
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
#define D_SENSOR_AS3935 "AS3935"
#define D_SENSOR_WINDMETER_SPEED "WindMeter Speed"
#define D_GPIO_WEBCAM_PWDN_GPIO_NUM "CAM_PWDN"
#define D_GPIO_WEBCAM_RESET_GPIO_NUM "CAM_RESET"
#define D_GPIO_WEBCAM_XCLK_GPIO_NUM "CAM_XCLK"
#define D_GPIO_WEBCAM_SIOD_GPIO_NUM "CAM_SIOD"
#define D_GPIO_WEBCAM_SIOC_GPIO_NUM "CAM_SIOC"
#define D_GPIO_WEBCAM_Y9_GPIO_NUM "CAM_Y9"
#define D_GPIO_WEBCAM_Y8_GPIO_NUM "CAM_Y8"
#define D_GPIO_WEBCAM_Y7_GPIO_NUM "CAM_Y7"
#define D_GPIO_WEBCAM_Y6_GPIO_NUM "CAM_Y6"
#define D_GPIO_WEBCAM_Y5_GPIO_NUM "CAM_Y5"
#define D_GPIO_WEBCAM_Y4_GPIO_NUM "CAM_Y4"
#define D_GPIO_WEBCAM_Y3_GPIO_NUM "CAM_Y3"
#define D_GPIO_WEBCAM_Y2_GPIO_NUM "CAM_Y2"
#define D_GPIO_WEBCAM_VSYNC_GPIO_NUM "CAM_VSYNC"
#define D_GPIO_WEBCAM_HREF_GPIO_NUM "CAM_HREF"
#define D_GPIO_WEBCAM_PCLK_GPIO_NUM "CAM_PCLK"
#define D_GPIO_WEBCAM_PSCLK_GPIO_NUM "CAM_PSCLK"
#define D_GPIO_WEBCAM_HSD1_GPIO_NUM "CAM_HSD1"
#define D_GPIO_WEBCAM_HSD2_GPIO_NUM "CAM_HSD2"
#define D_GPIO_WEBCAM_HSD3_GPIO_NUM "CAM_HSD3"
#define D_GPIO_WEBCAM_PSRCS_GPIO_NUM "CAM_PSRCS"
// Units
#define D_UNIT_AMPERE "A"

View File

@ -667,6 +667,27 @@
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
#define D_SENSOR_AS3935 "AS3935"
#define D_SENSOR_WINDMETER_SPEED "WindMeter Speed"
#define D_GPIO_WEBCAM_PWDN_GPIO_NUM "CAM_PWDN"
#define D_GPIO_WEBCAM_RESET_GPIO_NUM "CAM_RESET"
#define D_GPIO_WEBCAM_XCLK_GPIO_NUM "CAM_XCLK"
#define D_GPIO_WEBCAM_SIOD_GPIO_NUM "CAM_SIOD"
#define D_GPIO_WEBCAM_SIOC_GPIO_NUM "CAM_SIOC"
#define D_GPIO_WEBCAM_Y9_GPIO_NUM "CAM_Y9"
#define D_GPIO_WEBCAM_Y8_GPIO_NUM "CAM_Y8"
#define D_GPIO_WEBCAM_Y7_GPIO_NUM "CAM_Y7"
#define D_GPIO_WEBCAM_Y6_GPIO_NUM "CAM_Y6"
#define D_GPIO_WEBCAM_Y5_GPIO_NUM "CAM_Y5"
#define D_GPIO_WEBCAM_Y4_GPIO_NUM "CAM_Y4"
#define D_GPIO_WEBCAM_Y3_GPIO_NUM "CAM_Y3"
#define D_GPIO_WEBCAM_Y2_GPIO_NUM "CAM_Y2"
#define D_GPIO_WEBCAM_VSYNC_GPIO_NUM "CAM_VSYNC"
#define D_GPIO_WEBCAM_HREF_GPIO_NUM "CAM_HREF"
#define D_GPIO_WEBCAM_PCLK_GPIO_NUM "CAM_PCLK"
#define D_GPIO_WEBCAM_PSCLK_GPIO_NUM "CAM_PSCLK"
#define D_GPIO_WEBCAM_HSD1_GPIO_NUM "CAM_HSD1"
#define D_GPIO_WEBCAM_HSD2_GPIO_NUM "CAM_HSD2"
#define D_GPIO_WEBCAM_HSD3_GPIO_NUM "CAM_HSD3"
#define D_GPIO_WEBCAM_PSRCS_GPIO_NUM "CAM_PSRCS"
// Units
#define D_UNIT_AMPERE "A"

View File

@ -667,6 +667,27 @@
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
#define D_SENSOR_AS3935 "AS3935"
#define D_SENSOR_WINDMETER_SPEED "WindMeter Speed"
#define D_GPIO_WEBCAM_PWDN_GPIO_NUM "CAM_PWDN"
#define D_GPIO_WEBCAM_RESET_GPIO_NUM "CAM_RESET"
#define D_GPIO_WEBCAM_XCLK_GPIO_NUM "CAM_XCLK"
#define D_GPIO_WEBCAM_SIOD_GPIO_NUM "CAM_SIOD"
#define D_GPIO_WEBCAM_SIOC_GPIO_NUM "CAM_SIOC"
#define D_GPIO_WEBCAM_Y9_GPIO_NUM "CAM_Y9"
#define D_GPIO_WEBCAM_Y8_GPIO_NUM "CAM_Y8"
#define D_GPIO_WEBCAM_Y7_GPIO_NUM "CAM_Y7"
#define D_GPIO_WEBCAM_Y6_GPIO_NUM "CAM_Y6"
#define D_GPIO_WEBCAM_Y5_GPIO_NUM "CAM_Y5"
#define D_GPIO_WEBCAM_Y4_GPIO_NUM "CAM_Y4"
#define D_GPIO_WEBCAM_Y3_GPIO_NUM "CAM_Y3"
#define D_GPIO_WEBCAM_Y2_GPIO_NUM "CAM_Y2"
#define D_GPIO_WEBCAM_VSYNC_GPIO_NUM "CAM_VSYNC"
#define D_GPIO_WEBCAM_HREF_GPIO_NUM "CAM_HREF"
#define D_GPIO_WEBCAM_PCLK_GPIO_NUM "CAM_PCLK"
#define D_GPIO_WEBCAM_PSCLK_GPIO_NUM "CAM_PSCLK"
#define D_GPIO_WEBCAM_HSD1_GPIO_NUM "CAM_HSD1"
#define D_GPIO_WEBCAM_HSD2_GPIO_NUM "CAM_HSD2"
#define D_GPIO_WEBCAM_HSD3_GPIO_NUM "CAM_HSD3"
#define D_GPIO_WEBCAM_PSRCS_GPIO_NUM "CAM_PSRCS"
// Units
#define D_UNIT_AMPERE "A"

View File

@ -667,6 +667,27 @@
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
#define D_SENSOR_AS3935 "AS3935"
#define D_SENSOR_WINDMETER_SPEED "WindMeter Speed"
#define D_GPIO_WEBCAM_PWDN_GPIO_NUM "CAM_PWDN"
#define D_GPIO_WEBCAM_RESET_GPIO_NUM "CAM_RESET"
#define D_GPIO_WEBCAM_XCLK_GPIO_NUM "CAM_XCLK"
#define D_GPIO_WEBCAM_SIOD_GPIO_NUM "CAM_SIOD"
#define D_GPIO_WEBCAM_SIOC_GPIO_NUM "CAM_SIOC"
#define D_GPIO_WEBCAM_Y9_GPIO_NUM "CAM_Y9"
#define D_GPIO_WEBCAM_Y8_GPIO_NUM "CAM_Y8"
#define D_GPIO_WEBCAM_Y7_GPIO_NUM "CAM_Y7"
#define D_GPIO_WEBCAM_Y6_GPIO_NUM "CAM_Y6"
#define D_GPIO_WEBCAM_Y5_GPIO_NUM "CAM_Y5"
#define D_GPIO_WEBCAM_Y4_GPIO_NUM "CAM_Y4"
#define D_GPIO_WEBCAM_Y3_GPIO_NUM "CAM_Y3"
#define D_GPIO_WEBCAM_Y2_GPIO_NUM "CAM_Y2"
#define D_GPIO_WEBCAM_VSYNC_GPIO_NUM "CAM_VSYNC"
#define D_GPIO_WEBCAM_HREF_GPIO_NUM "CAM_HREF"
#define D_GPIO_WEBCAM_PCLK_GPIO_NUM "CAM_PCLK"
#define D_GPIO_WEBCAM_PSCLK_GPIO_NUM "CAM_PSCLK"
#define D_GPIO_WEBCAM_HSD1_GPIO_NUM "CAM_HSD1"
#define D_GPIO_WEBCAM_HSD2_GPIO_NUM "CAM_HSD2"
#define D_GPIO_WEBCAM_HSD3_GPIO_NUM "CAM_HSD3"
#define D_GPIO_WEBCAM_PSRCS_GPIO_NUM "CAM_PSRCS"
// Units
#define D_UNIT_AMPERE "A"

View File

@ -667,6 +667,27 @@
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
#define D_SENSOR_AS3935 "AS3935"
#define D_SENSOR_WINDMETER_SPEED "WindMeter Speed"
#define D_GPIO_WEBCAM_PWDN_GPIO_NUM "CAM_PWDN"
#define D_GPIO_WEBCAM_RESET_GPIO_NUM "CAM_RESET"
#define D_GPIO_WEBCAM_XCLK_GPIO_NUM "CAM_XCLK"
#define D_GPIO_WEBCAM_SIOD_GPIO_NUM "CAM_SIOD"
#define D_GPIO_WEBCAM_SIOC_GPIO_NUM "CAM_SIOC"
#define D_GPIO_WEBCAM_Y9_GPIO_NUM "CAM_Y9"
#define D_GPIO_WEBCAM_Y8_GPIO_NUM "CAM_Y8"
#define D_GPIO_WEBCAM_Y7_GPIO_NUM "CAM_Y7"
#define D_GPIO_WEBCAM_Y6_GPIO_NUM "CAM_Y6"
#define D_GPIO_WEBCAM_Y5_GPIO_NUM "CAM_Y5"
#define D_GPIO_WEBCAM_Y4_GPIO_NUM "CAM_Y4"
#define D_GPIO_WEBCAM_Y3_GPIO_NUM "CAM_Y3"
#define D_GPIO_WEBCAM_Y2_GPIO_NUM "CAM_Y2"
#define D_GPIO_WEBCAM_VSYNC_GPIO_NUM "CAM_VSYNC"
#define D_GPIO_WEBCAM_HREF_GPIO_NUM "CAM_HREF"
#define D_GPIO_WEBCAM_PCLK_GPIO_NUM "CAM_PCLK"
#define D_GPIO_WEBCAM_PSCLK_GPIO_NUM "CAM_PSCLK"
#define D_GPIO_WEBCAM_HSD1_GPIO_NUM "CAM_HSD1"
#define D_GPIO_WEBCAM_HSD2_GPIO_NUM "CAM_HSD2"
#define D_GPIO_WEBCAM_HSD3_GPIO_NUM "CAM_HSD3"
#define D_GPIO_WEBCAM_PSRCS_GPIO_NUM "CAM_PSRCS"
// Units
#define D_UNIT_AMPERE "A"

View File

@ -667,6 +667,27 @@
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
#define D_SENSOR_AS3935 "AS3935"
#define D_SENSOR_WINDMETER_SPEED "WindMeter Speed"
#define D_GPIO_WEBCAM_PWDN_GPIO_NUM "CAM_PWDN"
#define D_GPIO_WEBCAM_RESET_GPIO_NUM "CAM_RESET"
#define D_GPIO_WEBCAM_XCLK_GPIO_NUM "CAM_XCLK"
#define D_GPIO_WEBCAM_SIOD_GPIO_NUM "CAM_SIOD"
#define D_GPIO_WEBCAM_SIOC_GPIO_NUM "CAM_SIOC"
#define D_GPIO_WEBCAM_Y9_GPIO_NUM "CAM_Y9"
#define D_GPIO_WEBCAM_Y8_GPIO_NUM "CAM_Y8"
#define D_GPIO_WEBCAM_Y7_GPIO_NUM "CAM_Y7"
#define D_GPIO_WEBCAM_Y6_GPIO_NUM "CAM_Y6"
#define D_GPIO_WEBCAM_Y5_GPIO_NUM "CAM_Y5"
#define D_GPIO_WEBCAM_Y4_GPIO_NUM "CAM_Y4"
#define D_GPIO_WEBCAM_Y3_GPIO_NUM "CAM_Y3"
#define D_GPIO_WEBCAM_Y2_GPIO_NUM "CAM_Y2"
#define D_GPIO_WEBCAM_VSYNC_GPIO_NUM "CAM_VSYNC"
#define D_GPIO_WEBCAM_HREF_GPIO_NUM "CAM_HREF"
#define D_GPIO_WEBCAM_PCLK_GPIO_NUM "CAM_PCLK"
#define D_GPIO_WEBCAM_PSCLK_GPIO_NUM "CAM_PSCLK"
#define D_GPIO_WEBCAM_HSD1_GPIO_NUM "CAM_HSD1"
#define D_GPIO_WEBCAM_HSD2_GPIO_NUM "CAM_HSD2"
#define D_GPIO_WEBCAM_HSD3_GPIO_NUM "CAM_HSD3"
#define D_GPIO_WEBCAM_PSRCS_GPIO_NUM "CAM_PSRCS"
// Units
#define D_UNIT_AMPERE "A"

View File

@ -667,6 +667,27 @@
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
#define D_SENSOR_AS3935 "AS3935"
#define D_SENSOR_WINDMETER_SPEED "WindMeter Speed"
#define D_GPIO_WEBCAM_PWDN_GPIO_NUM "CAM_PWDN"
#define D_GPIO_WEBCAM_RESET_GPIO_NUM "CAM_RESET"
#define D_GPIO_WEBCAM_XCLK_GPIO_NUM "CAM_XCLK"
#define D_GPIO_WEBCAM_SIOD_GPIO_NUM "CAM_SIOD"
#define D_GPIO_WEBCAM_SIOC_GPIO_NUM "CAM_SIOC"
#define D_GPIO_WEBCAM_Y9_GPIO_NUM "CAM_Y9"
#define D_GPIO_WEBCAM_Y8_GPIO_NUM "CAM_Y8"
#define D_GPIO_WEBCAM_Y7_GPIO_NUM "CAM_Y7"
#define D_GPIO_WEBCAM_Y6_GPIO_NUM "CAM_Y6"
#define D_GPIO_WEBCAM_Y5_GPIO_NUM "CAM_Y5"
#define D_GPIO_WEBCAM_Y4_GPIO_NUM "CAM_Y4"
#define D_GPIO_WEBCAM_Y3_GPIO_NUM "CAM_Y3"
#define D_GPIO_WEBCAM_Y2_GPIO_NUM "CAM_Y2"
#define D_GPIO_WEBCAM_VSYNC_GPIO_NUM "CAM_VSYNC"
#define D_GPIO_WEBCAM_HREF_GPIO_NUM "CAM_HREF"
#define D_GPIO_WEBCAM_PCLK_GPIO_NUM "CAM_PCLK"
#define D_GPIO_WEBCAM_PSCLK_GPIO_NUM "CAM_PSCLK"
#define D_GPIO_WEBCAM_HSD1_GPIO_NUM "CAM_HSD1"
#define D_GPIO_WEBCAM_HSD2_GPIO_NUM "CAM_HSD2"
#define D_GPIO_WEBCAM_HSD3_GPIO_NUM "CAM_HSD3"
#define D_GPIO_WEBCAM_PSRCS_GPIO_NUM "CAM_PSRCS"
// Units
#define D_UNIT_AMPERE "A"

View File

@ -667,6 +667,27 @@
#define D_SENSOR_ELECTRIQ_MOODL "MOODL - TX"
#define D_SENSOR_AS3935 "AS3935"
#define D_SENSOR_WINDMETER_SPEED "WindMeter Speed"
#define D_GPIO_WEBCAM_PWDN_GPIO_NUM "CAM_PWDN"
#define D_GPIO_WEBCAM_RESET_GPIO_NUM "CAM_RESET"
#define D_GPIO_WEBCAM_XCLK_GPIO_NUM "CAM_XCLK"
#define D_GPIO_WEBCAM_SIOD_GPIO_NUM "CAM_SIOD"
#define D_GPIO_WEBCAM_SIOC_GPIO_NUM "CAM_SIOC"
#define D_GPIO_WEBCAM_Y9_GPIO_NUM "CAM_Y9"
#define D_GPIO_WEBCAM_Y8_GPIO_NUM "CAM_Y8"
#define D_GPIO_WEBCAM_Y7_GPIO_NUM "CAM_Y7"
#define D_GPIO_WEBCAM_Y6_GPIO_NUM "CAM_Y6"
#define D_GPIO_WEBCAM_Y5_GPIO_NUM "CAM_Y5"
#define D_GPIO_WEBCAM_Y4_GPIO_NUM "CAM_Y4"
#define D_GPIO_WEBCAM_Y3_GPIO_NUM "CAM_Y3"
#define D_GPIO_WEBCAM_Y2_GPIO_NUM "CAM_Y2"
#define D_GPIO_WEBCAM_VSYNC_GPIO_NUM "CAM_VSYNC"
#define D_GPIO_WEBCAM_HREF_GPIO_NUM "CAM_HREF"
#define D_GPIO_WEBCAM_PCLK_GPIO_NUM "CAM_PCLK"
#define D_GPIO_WEBCAM_PSCLK_GPIO_NUM "CAM_PSCLK"
#define D_GPIO_WEBCAM_HSD1_GPIO_NUM "CAM_HSD1"
#define D_GPIO_WEBCAM_HSD2_GPIO_NUM "CAM_HSD2"
#define D_GPIO_WEBCAM_HSD3_GPIO_NUM "CAM_HSD3"
#define D_GPIO_WEBCAM_PSRCS_GPIO_NUM "CAM_PSRCS"
// Units
#define D_UNIT_AMPERE "A"

View File

@ -667,6 +667,27 @@
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
#define D_SENSOR_AS3935 "AS3935"
#define D_SENSOR_WINDMETER_SPEED "WindMeter Speed"
#define D_GPIO_WEBCAM_PWDN_GPIO_NUM "CAM_PWDN"
#define D_GPIO_WEBCAM_RESET_GPIO_NUM "CAM_RESET"
#define D_GPIO_WEBCAM_XCLK_GPIO_NUM "CAM_XCLK"
#define D_GPIO_WEBCAM_SIOD_GPIO_NUM "CAM_SIOD"
#define D_GPIO_WEBCAM_SIOC_GPIO_NUM "CAM_SIOC"
#define D_GPIO_WEBCAM_Y9_GPIO_NUM "CAM_Y9"
#define D_GPIO_WEBCAM_Y8_GPIO_NUM "CAM_Y8"
#define D_GPIO_WEBCAM_Y7_GPIO_NUM "CAM_Y7"
#define D_GPIO_WEBCAM_Y6_GPIO_NUM "CAM_Y6"
#define D_GPIO_WEBCAM_Y5_GPIO_NUM "CAM_Y5"
#define D_GPIO_WEBCAM_Y4_GPIO_NUM "CAM_Y4"
#define D_GPIO_WEBCAM_Y3_GPIO_NUM "CAM_Y3"
#define D_GPIO_WEBCAM_Y2_GPIO_NUM "CAM_Y2"
#define D_GPIO_WEBCAM_VSYNC_GPIO_NUM "CAM_VSYNC"
#define D_GPIO_WEBCAM_HREF_GPIO_NUM "CAM_HREF"
#define D_GPIO_WEBCAM_PCLK_GPIO_NUM "CAM_PCLK"
#define D_GPIO_WEBCAM_PSCLK_GPIO_NUM "CAM_PSCLK"
#define D_GPIO_WEBCAM_HSD1_GPIO_NUM "CAM_HSD1"
#define D_GPIO_WEBCAM_HSD2_GPIO_NUM "CAM_HSD2"
#define D_GPIO_WEBCAM_HSD3_GPIO_NUM "CAM_HSD3"
#define D_GPIO_WEBCAM_PSRCS_GPIO_NUM "CAM_PSRCS"
// Units
#define D_UNIT_AMPERE "A"

View File

@ -667,6 +667,27 @@
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
#define D_SENSOR_AS3935 "AS3935"
#define D_SENSOR_WINDMETER_SPEED "WindMeter Speed"
#define D_GPIO_WEBCAM_PWDN_GPIO_NUM "CAM_PWDN"
#define D_GPIO_WEBCAM_RESET_GPIO_NUM "CAM_RESET"
#define D_GPIO_WEBCAM_XCLK_GPIO_NUM "CAM_XCLK"
#define D_GPIO_WEBCAM_SIOD_GPIO_NUM "CAM_SIOD"
#define D_GPIO_WEBCAM_SIOC_GPIO_NUM "CAM_SIOC"
#define D_GPIO_WEBCAM_Y9_GPIO_NUM "CAM_Y9"
#define D_GPIO_WEBCAM_Y8_GPIO_NUM "CAM_Y8"
#define D_GPIO_WEBCAM_Y7_GPIO_NUM "CAM_Y7"
#define D_GPIO_WEBCAM_Y6_GPIO_NUM "CAM_Y6"
#define D_GPIO_WEBCAM_Y5_GPIO_NUM "CAM_Y5"
#define D_GPIO_WEBCAM_Y4_GPIO_NUM "CAM_Y4"
#define D_GPIO_WEBCAM_Y3_GPIO_NUM "CAM_Y3"
#define D_GPIO_WEBCAM_Y2_GPIO_NUM "CAM_Y2"
#define D_GPIO_WEBCAM_VSYNC_GPIO_NUM "CAM_VSYNC"
#define D_GPIO_WEBCAM_HREF_GPIO_NUM "CAM_HREF"
#define D_GPIO_WEBCAM_PCLK_GPIO_NUM "CAM_PCLK"
#define D_GPIO_WEBCAM_PSCLK_GPIO_NUM "CAM_PSCLK"
#define D_GPIO_WEBCAM_HSD1_GPIO_NUM "CAM_HSD1"
#define D_GPIO_WEBCAM_HSD2_GPIO_NUM "CAM_HSD2"
#define D_GPIO_WEBCAM_HSD3_GPIO_NUM "CAM_HSD3"
#define D_GPIO_WEBCAM_PSRCS_GPIO_NUM "CAM_PSRCS"
// Units
#define D_UNIT_AMPERE "A"

View File

@ -667,6 +667,27 @@
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
#define D_SENSOR_AS3935 "AS3935"
#define D_SENSOR_WINDMETER_SPEED "WindMeter Speed"
#define D_GPIO_WEBCAM_PWDN_GPIO_NUM "CAM_PWDN"
#define D_GPIO_WEBCAM_RESET_GPIO_NUM "CAM_RESET"
#define D_GPIO_WEBCAM_XCLK_GPIO_NUM "CAM_XCLK"
#define D_GPIO_WEBCAM_SIOD_GPIO_NUM "CAM_SIOD"
#define D_GPIO_WEBCAM_SIOC_GPIO_NUM "CAM_SIOC"
#define D_GPIO_WEBCAM_Y9_GPIO_NUM "CAM_Y9"
#define D_GPIO_WEBCAM_Y8_GPIO_NUM "CAM_Y8"
#define D_GPIO_WEBCAM_Y7_GPIO_NUM "CAM_Y7"
#define D_GPIO_WEBCAM_Y6_GPIO_NUM "CAM_Y6"
#define D_GPIO_WEBCAM_Y5_GPIO_NUM "CAM_Y5"
#define D_GPIO_WEBCAM_Y4_GPIO_NUM "CAM_Y4"
#define D_GPIO_WEBCAM_Y3_GPIO_NUM "CAM_Y3"
#define D_GPIO_WEBCAM_Y2_GPIO_NUM "CAM_Y2"
#define D_GPIO_WEBCAM_VSYNC_GPIO_NUM "CAM_VSYNC"
#define D_GPIO_WEBCAM_HREF_GPIO_NUM "CAM_HREF"
#define D_GPIO_WEBCAM_PCLK_GPIO_NUM "CAM_PCLK"
#define D_GPIO_WEBCAM_PSCLK_GPIO_NUM "CAM_PSCLK"
#define D_GPIO_WEBCAM_HSD1_GPIO_NUM "CAM_HSD1"
#define D_GPIO_WEBCAM_HSD2_GPIO_NUM "CAM_HSD2"
#define D_GPIO_WEBCAM_HSD3_GPIO_NUM "CAM_HSD3"
#define D_GPIO_WEBCAM_PSRCS_GPIO_NUM "CAM_PSRCS"
// Units
#define D_UNIT_AMPERE "A"

View File

@ -667,6 +667,27 @@
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
#define D_SENSOR_AS3935 "AS3935"
#define D_SENSOR_WINDMETER_SPEED "WindMeter Speed"
#define D_GPIO_WEBCAM_PWDN_GPIO_NUM "CAM_PWDN"
#define D_GPIO_WEBCAM_RESET_GPIO_NUM "CAM_RESET"
#define D_GPIO_WEBCAM_XCLK_GPIO_NUM "CAM_XCLK"
#define D_GPIO_WEBCAM_SIOD_GPIO_NUM "CAM_SIOD"
#define D_GPIO_WEBCAM_SIOC_GPIO_NUM "CAM_SIOC"
#define D_GPIO_WEBCAM_Y9_GPIO_NUM "CAM_Y9"
#define D_GPIO_WEBCAM_Y8_GPIO_NUM "CAM_Y8"
#define D_GPIO_WEBCAM_Y7_GPIO_NUM "CAM_Y7"
#define D_GPIO_WEBCAM_Y6_GPIO_NUM "CAM_Y6"
#define D_GPIO_WEBCAM_Y5_GPIO_NUM "CAM_Y5"
#define D_GPIO_WEBCAM_Y4_GPIO_NUM "CAM_Y4"
#define D_GPIO_WEBCAM_Y3_GPIO_NUM "CAM_Y3"
#define D_GPIO_WEBCAM_Y2_GPIO_NUM "CAM_Y2"
#define D_GPIO_WEBCAM_VSYNC_GPIO_NUM "CAM_VSYNC"
#define D_GPIO_WEBCAM_HREF_GPIO_NUM "CAM_HREF"
#define D_GPIO_WEBCAM_PCLK_GPIO_NUM "CAM_PCLK"
#define D_GPIO_WEBCAM_PSCLK_GPIO_NUM "CAM_PSCLK"
#define D_GPIO_WEBCAM_HSD1_GPIO_NUM "CAM_HSD1"
#define D_GPIO_WEBCAM_HSD2_GPIO_NUM "CAM_HSD2"
#define D_GPIO_WEBCAM_HSD3_GPIO_NUM "CAM_HSD3"
#define D_GPIO_WEBCAM_PSRCS_GPIO_NUM "CAM_PSRCS"
// Units
#define D_UNIT_AMPERE "A"

View File

@ -667,6 +667,27 @@
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
#define D_SENSOR_AS3935 "AS3935"
#define D_SENSOR_WINDMETER_SPEED "WindMeter Speed"
#define D_GPIO_WEBCAM_PWDN_GPIO_NUM "CAM_PWDN"
#define D_GPIO_WEBCAM_RESET_GPIO_NUM "CAM_RESET"
#define D_GPIO_WEBCAM_XCLK_GPIO_NUM "CAM_XCLK"
#define D_GPIO_WEBCAM_SIOD_GPIO_NUM "CAM_SIOD"
#define D_GPIO_WEBCAM_SIOC_GPIO_NUM "CAM_SIOC"
#define D_GPIO_WEBCAM_Y9_GPIO_NUM "CAM_Y9"
#define D_GPIO_WEBCAM_Y8_GPIO_NUM "CAM_Y8"
#define D_GPIO_WEBCAM_Y7_GPIO_NUM "CAM_Y7"
#define D_GPIO_WEBCAM_Y6_GPIO_NUM "CAM_Y6"
#define D_GPIO_WEBCAM_Y5_GPIO_NUM "CAM_Y5"
#define D_GPIO_WEBCAM_Y4_GPIO_NUM "CAM_Y4"
#define D_GPIO_WEBCAM_Y3_GPIO_NUM "CAM_Y3"
#define D_GPIO_WEBCAM_Y2_GPIO_NUM "CAM_Y2"
#define D_GPIO_WEBCAM_VSYNC_GPIO_NUM "CAM_VSYNC"
#define D_GPIO_WEBCAM_HREF_GPIO_NUM "CAM_HREF"
#define D_GPIO_WEBCAM_PCLK_GPIO_NUM "CAM_PCLK"
#define D_GPIO_WEBCAM_PSCLK_GPIO_NUM "CAM_PSCLK"
#define D_GPIO_WEBCAM_HSD1_GPIO_NUM "CAM_HSD1"
#define D_GPIO_WEBCAM_HSD2_GPIO_NUM "CAM_HSD2"
#define D_GPIO_WEBCAM_HSD3_GPIO_NUM "CAM_HSD3"
#define D_GPIO_WEBCAM_PSRCS_GPIO_NUM "CAM_PSRCS"
// Units
#define D_UNIT_AMPERE "A"

View File

@ -667,6 +667,27 @@
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
#define D_SENSOR_AS3935 "AS3935"
#define D_SENSOR_WINDMETER_SPEED "WindMeter Speed"
#define D_GPIO_WEBCAM_PWDN_GPIO_NUM "CAM_PWDN"
#define D_GPIO_WEBCAM_RESET_GPIO_NUM "CAM_RESET"
#define D_GPIO_WEBCAM_XCLK_GPIO_NUM "CAM_XCLK"
#define D_GPIO_WEBCAM_SIOD_GPIO_NUM "CAM_SIOD"
#define D_GPIO_WEBCAM_SIOC_GPIO_NUM "CAM_SIOC"
#define D_GPIO_WEBCAM_Y9_GPIO_NUM "CAM_Y9"
#define D_GPIO_WEBCAM_Y8_GPIO_NUM "CAM_Y8"
#define D_GPIO_WEBCAM_Y7_GPIO_NUM "CAM_Y7"
#define D_GPIO_WEBCAM_Y6_GPIO_NUM "CAM_Y6"
#define D_GPIO_WEBCAM_Y5_GPIO_NUM "CAM_Y5"
#define D_GPIO_WEBCAM_Y4_GPIO_NUM "CAM_Y4"
#define D_GPIO_WEBCAM_Y3_GPIO_NUM "CAM_Y3"
#define D_GPIO_WEBCAM_Y2_GPIO_NUM "CAM_Y2"
#define D_GPIO_WEBCAM_VSYNC_GPIO_NUM "CAM_VSYNC"
#define D_GPIO_WEBCAM_HREF_GPIO_NUM "CAM_HREF"
#define D_GPIO_WEBCAM_PCLK_GPIO_NUM "CAM_PCLK"
#define D_GPIO_WEBCAM_PSCLK_GPIO_NUM "CAM_PSCLK"
#define D_GPIO_WEBCAM_HSD1_GPIO_NUM "CAM_HSD1"
#define D_GPIO_WEBCAM_HSD2_GPIO_NUM "CAM_HSD2"
#define D_GPIO_WEBCAM_HSD3_GPIO_NUM "CAM_HSD3"
#define D_GPIO_WEBCAM_PSRCS_GPIO_NUM "CAM_PSRCS"
// Units
#define D_UNIT_AMPERE "A"

View File

@ -667,6 +667,27 @@
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
#define D_SENSOR_AS3935 "AS3935"
#define D_SENSOR_WINDMETER_SPEED "WindMeter Speed"
#define D_GPIO_WEBCAM_PWDN_GPIO_NUM "CAM_PWDN"
#define D_GPIO_WEBCAM_RESET_GPIO_NUM "CAM_RESET"
#define D_GPIO_WEBCAM_XCLK_GPIO_NUM "CAM_XCLK"
#define D_GPIO_WEBCAM_SIOD_GPIO_NUM "CAM_SIOD"
#define D_GPIO_WEBCAM_SIOC_GPIO_NUM "CAM_SIOC"
#define D_GPIO_WEBCAM_Y9_GPIO_NUM "CAM_Y9"
#define D_GPIO_WEBCAM_Y8_GPIO_NUM "CAM_Y8"
#define D_GPIO_WEBCAM_Y7_GPIO_NUM "CAM_Y7"
#define D_GPIO_WEBCAM_Y6_GPIO_NUM "CAM_Y6"
#define D_GPIO_WEBCAM_Y5_GPIO_NUM "CAM_Y5"
#define D_GPIO_WEBCAM_Y4_GPIO_NUM "CAM_Y4"
#define D_GPIO_WEBCAM_Y3_GPIO_NUM "CAM_Y3"
#define D_GPIO_WEBCAM_Y2_GPIO_NUM "CAM_Y2"
#define D_GPIO_WEBCAM_VSYNC_GPIO_NUM "CAM_VSYNC"
#define D_GPIO_WEBCAM_HREF_GPIO_NUM "CAM_HREF"
#define D_GPIO_WEBCAM_PCLK_GPIO_NUM "CAM_PCLK"
#define D_GPIO_WEBCAM_PSCLK_GPIO_NUM "CAM_PSCLK"
#define D_GPIO_WEBCAM_HSD1_GPIO_NUM "CAM_HSD1"
#define D_GPIO_WEBCAM_HSD2_GPIO_NUM "CAM_HSD2"
#define D_GPIO_WEBCAM_HSD3_GPIO_NUM "CAM_HSD3"
#define D_GPIO_WEBCAM_PSRCS_GPIO_NUM "CAM_PSRCS"
// Units
#define D_UNIT_AMPERE "А"

View File

@ -667,6 +667,27 @@
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
#define D_SENSOR_AS3935 "AS3935"
#define D_SENSOR_WINDMETER_SPEED "WindMeter Speed"
#define D_GPIO_WEBCAM_PWDN_GPIO_NUM "CAM_PWDN"
#define D_GPIO_WEBCAM_RESET_GPIO_NUM "CAM_RESET"
#define D_GPIO_WEBCAM_XCLK_GPIO_NUM "CAM_XCLK"
#define D_GPIO_WEBCAM_SIOD_GPIO_NUM "CAM_SIOD"
#define D_GPIO_WEBCAM_SIOC_GPIO_NUM "CAM_SIOC"
#define D_GPIO_WEBCAM_Y9_GPIO_NUM "CAM_Y9"
#define D_GPIO_WEBCAM_Y8_GPIO_NUM "CAM_Y8"
#define D_GPIO_WEBCAM_Y7_GPIO_NUM "CAM_Y7"
#define D_GPIO_WEBCAM_Y6_GPIO_NUM "CAM_Y6"
#define D_GPIO_WEBCAM_Y5_GPIO_NUM "CAM_Y5"
#define D_GPIO_WEBCAM_Y4_GPIO_NUM "CAM_Y4"
#define D_GPIO_WEBCAM_Y3_GPIO_NUM "CAM_Y3"
#define D_GPIO_WEBCAM_Y2_GPIO_NUM "CAM_Y2"
#define D_GPIO_WEBCAM_VSYNC_GPIO_NUM "CAM_VSYNC"
#define D_GPIO_WEBCAM_HREF_GPIO_NUM "CAM_HREF"
#define D_GPIO_WEBCAM_PCLK_GPIO_NUM "CAM_PCLK"
#define D_GPIO_WEBCAM_PSCLK_GPIO_NUM "CAM_PSCLK"
#define D_GPIO_WEBCAM_HSD1_GPIO_NUM "CAM_HSD1"
#define D_GPIO_WEBCAM_HSD2_GPIO_NUM "CAM_HSD2"
#define D_GPIO_WEBCAM_HSD3_GPIO_NUM "CAM_HSD3"
#define D_GPIO_WEBCAM_PSRCS_GPIO_NUM "CAM_PSRCS"
// Units
#define D_UNIT_AMPERE "A"

View File

@ -667,6 +667,27 @@
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
#define D_SENSOR_AS3935 "AS3935"
#define D_SENSOR_WINDMETER_SPEED "WindMeter Speed"
#define D_GPIO_WEBCAM_PWDN_GPIO_NUM "CAM_PWDN"
#define D_GPIO_WEBCAM_RESET_GPIO_NUM "CAM_RESET"
#define D_GPIO_WEBCAM_XCLK_GPIO_NUM "CAM_XCLK"
#define D_GPIO_WEBCAM_SIOD_GPIO_NUM "CAM_SIOD"
#define D_GPIO_WEBCAM_SIOC_GPIO_NUM "CAM_SIOC"
#define D_GPIO_WEBCAM_Y9_GPIO_NUM "CAM_Y9"
#define D_GPIO_WEBCAM_Y8_GPIO_NUM "CAM_Y8"
#define D_GPIO_WEBCAM_Y7_GPIO_NUM "CAM_Y7"
#define D_GPIO_WEBCAM_Y6_GPIO_NUM "CAM_Y6"
#define D_GPIO_WEBCAM_Y5_GPIO_NUM "CAM_Y5"
#define D_GPIO_WEBCAM_Y4_GPIO_NUM "CAM_Y4"
#define D_GPIO_WEBCAM_Y3_GPIO_NUM "CAM_Y3"
#define D_GPIO_WEBCAM_Y2_GPIO_NUM "CAM_Y2"
#define D_GPIO_WEBCAM_VSYNC_GPIO_NUM "CAM_VSYNC"
#define D_GPIO_WEBCAM_HREF_GPIO_NUM "CAM_HREF"
#define D_GPIO_WEBCAM_PCLK_GPIO_NUM "CAM_PCLK"
#define D_GPIO_WEBCAM_PSCLK_GPIO_NUM "CAM_PSCLK"
#define D_GPIO_WEBCAM_HSD1_GPIO_NUM "CAM_HSD1"
#define D_GPIO_WEBCAM_HSD2_GPIO_NUM "CAM_HSD2"
#define D_GPIO_WEBCAM_HSD3_GPIO_NUM "CAM_HSD3"
#define D_GPIO_WEBCAM_PSRCS_GPIO_NUM "CAM_PSRCS"
// Units
#define D_UNIT_AMPERE "A"

View File

@ -667,6 +667,27 @@
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
#define D_SENSOR_AS3935 "AS3935"
#define D_SENSOR_WINDMETER_SPEED "WindMeter Speed"
#define D_GPIO_WEBCAM_PWDN_GPIO_NUM "CAM_PWDN"
#define D_GPIO_WEBCAM_RESET_GPIO_NUM "CAM_RESET"
#define D_GPIO_WEBCAM_XCLK_GPIO_NUM "CAM_XCLK"
#define D_GPIO_WEBCAM_SIOD_GPIO_NUM "CAM_SIOD"
#define D_GPIO_WEBCAM_SIOC_GPIO_NUM "CAM_SIOC"
#define D_GPIO_WEBCAM_Y9_GPIO_NUM "CAM_Y9"
#define D_GPIO_WEBCAM_Y8_GPIO_NUM "CAM_Y8"
#define D_GPIO_WEBCAM_Y7_GPIO_NUM "CAM_Y7"
#define D_GPIO_WEBCAM_Y6_GPIO_NUM "CAM_Y6"
#define D_GPIO_WEBCAM_Y5_GPIO_NUM "CAM_Y5"
#define D_GPIO_WEBCAM_Y4_GPIO_NUM "CAM_Y4"
#define D_GPIO_WEBCAM_Y3_GPIO_NUM "CAM_Y3"
#define D_GPIO_WEBCAM_Y2_GPIO_NUM "CAM_Y2"
#define D_GPIO_WEBCAM_VSYNC_GPIO_NUM "CAM_VSYNC"
#define D_GPIO_WEBCAM_HREF_GPIO_NUM "CAM_HREF"
#define D_GPIO_WEBCAM_PCLK_GPIO_NUM "CAM_PCLK"
#define D_GPIO_WEBCAM_PSCLK_GPIO_NUM "CAM_PSCLK"
#define D_GPIO_WEBCAM_HSD1_GPIO_NUM "CAM_HSD1"
#define D_GPIO_WEBCAM_HSD2_GPIO_NUM "CAM_HSD2"
#define D_GPIO_WEBCAM_HSD3_GPIO_NUM "CAM_HSD3"
#define D_GPIO_WEBCAM_PSRCS_GPIO_NUM "CAM_PSRCS"
// Units
#define D_UNIT_AMPERE "A"

View File

@ -667,6 +667,27 @@
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
#define D_SENSOR_AS3935 "AS3935"
#define D_SENSOR_WINDMETER_SPEED "WindMeter Speed"
#define D_GPIO_WEBCAM_PWDN_GPIO_NUM "CAM_PWDN"
#define D_GPIO_WEBCAM_RESET_GPIO_NUM "CAM_RESET"
#define D_GPIO_WEBCAM_XCLK_GPIO_NUM "CAM_XCLK"
#define D_GPIO_WEBCAM_SIOD_GPIO_NUM "CAM_SIOD"
#define D_GPIO_WEBCAM_SIOC_GPIO_NUM "CAM_SIOC"
#define D_GPIO_WEBCAM_Y9_GPIO_NUM "CAM_Y9"
#define D_GPIO_WEBCAM_Y8_GPIO_NUM "CAM_Y8"
#define D_GPIO_WEBCAM_Y7_GPIO_NUM "CAM_Y7"
#define D_GPIO_WEBCAM_Y6_GPIO_NUM "CAM_Y6"
#define D_GPIO_WEBCAM_Y5_GPIO_NUM "CAM_Y5"
#define D_GPIO_WEBCAM_Y4_GPIO_NUM "CAM_Y4"
#define D_GPIO_WEBCAM_Y3_GPIO_NUM "CAM_Y3"
#define D_GPIO_WEBCAM_Y2_GPIO_NUM "CAM_Y2"
#define D_GPIO_WEBCAM_VSYNC_GPIO_NUM "CAM_VSYNC"
#define D_GPIO_WEBCAM_HREF_GPIO_NUM "CAM_HREF"
#define D_GPIO_WEBCAM_PCLK_GPIO_NUM "CAM_PCLK"
#define D_GPIO_WEBCAM_PSCLK_GPIO_NUM "CAM_PSCLK"
#define D_GPIO_WEBCAM_HSD1_GPIO_NUM "CAM_HSD1"
#define D_GPIO_WEBCAM_HSD2_GPIO_NUM "CAM_HSD2"
#define D_GPIO_WEBCAM_HSD3_GPIO_NUM "CAM_HSD3"
#define D_GPIO_WEBCAM_PSRCS_GPIO_NUM "CAM_PSRCS"
// Units
#define D_UNIT_AMPERE "А"

View File

@ -667,6 +667,27 @@
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
#define D_SENSOR_AS3935 "AS3935"
#define D_SENSOR_WINDMETER_SPEED "WindMeter Speed"
#define D_GPIO_WEBCAM_PWDN_GPIO_NUM "CAM_PWDN"
#define D_GPIO_WEBCAM_RESET_GPIO_NUM "CAM_RESET"
#define D_GPIO_WEBCAM_XCLK_GPIO_NUM "CAM_XCLK"
#define D_GPIO_WEBCAM_SIOD_GPIO_NUM "CAM_SIOD"
#define D_GPIO_WEBCAM_SIOC_GPIO_NUM "CAM_SIOC"
#define D_GPIO_WEBCAM_Y9_GPIO_NUM "CAM_Y9"
#define D_GPIO_WEBCAM_Y8_GPIO_NUM "CAM_Y8"
#define D_GPIO_WEBCAM_Y7_GPIO_NUM "CAM_Y7"
#define D_GPIO_WEBCAM_Y6_GPIO_NUM "CAM_Y6"
#define D_GPIO_WEBCAM_Y5_GPIO_NUM "CAM_Y5"
#define D_GPIO_WEBCAM_Y4_GPIO_NUM "CAM_Y4"
#define D_GPIO_WEBCAM_Y3_GPIO_NUM "CAM_Y3"
#define D_GPIO_WEBCAM_Y2_GPIO_NUM "CAM_Y2"
#define D_GPIO_WEBCAM_VSYNC_GPIO_NUM "CAM_VSYNC"
#define D_GPIO_WEBCAM_HREF_GPIO_NUM "CAM_HREF"
#define D_GPIO_WEBCAM_PCLK_GPIO_NUM "CAM_PCLK"
#define D_GPIO_WEBCAM_PSCLK_GPIO_NUM "CAM_PSCLK"
#define D_GPIO_WEBCAM_HSD1_GPIO_NUM "CAM_HSD1"
#define D_GPIO_WEBCAM_HSD2_GPIO_NUM "CAM_HSD2"
#define D_GPIO_WEBCAM_HSD3_GPIO_NUM "CAM_HSD3"
#define D_GPIO_WEBCAM_PSRCS_GPIO_NUM "CAM_PSRCS"
// Units
#define D_UNIT_AMPERE "安"

View File

@ -667,6 +667,27 @@
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
#define D_SENSOR_AS3935 "AS3935"
#define D_SENSOR_WINDMETER_SPEED "WindMeter Speed"
#define D_GPIO_WEBCAM_PWDN_GPIO_NUM "CAM_PWDN"
#define D_GPIO_WEBCAM_RESET_GPIO_NUM "CAM_RESET"
#define D_GPIO_WEBCAM_XCLK_GPIO_NUM "CAM_XCLK"
#define D_GPIO_WEBCAM_SIOD_GPIO_NUM "CAM_SIOD"
#define D_GPIO_WEBCAM_SIOC_GPIO_NUM "CAM_SIOC"
#define D_GPIO_WEBCAM_Y9_GPIO_NUM "CAM_Y9"
#define D_GPIO_WEBCAM_Y8_GPIO_NUM "CAM_Y8"
#define D_GPIO_WEBCAM_Y7_GPIO_NUM "CAM_Y7"
#define D_GPIO_WEBCAM_Y6_GPIO_NUM "CAM_Y6"
#define D_GPIO_WEBCAM_Y5_GPIO_NUM "CAM_Y5"
#define D_GPIO_WEBCAM_Y4_GPIO_NUM "CAM_Y4"
#define D_GPIO_WEBCAM_Y3_GPIO_NUM "CAM_Y3"
#define D_GPIO_WEBCAM_Y2_GPIO_NUM "CAM_Y2"
#define D_GPIO_WEBCAM_VSYNC_GPIO_NUM "CAM_VSYNC"
#define D_GPIO_WEBCAM_HREF_GPIO_NUM "CAM_HREF"
#define D_GPIO_WEBCAM_PCLK_GPIO_NUM "CAM_PCLK"
#define D_GPIO_WEBCAM_PSCLK_GPIO_NUM "CAM_PSCLK"
#define D_GPIO_WEBCAM_HSD1_GPIO_NUM "CAM_HSD1"
#define D_GPIO_WEBCAM_HSD2_GPIO_NUM "CAM_HSD2"
#define D_GPIO_WEBCAM_HSD3_GPIO_NUM "CAM_HSD3"
#define D_GPIO_WEBCAM_PSRCS_GPIO_NUM "CAM_PSRCS"
// Units
#define D_UNIT_AMPERE "安"

View File

@ -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;}
};

View File

@ -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

View File

@ -111,7 +111,7 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu
uint32_t zigbee_distinct_topics : 1; // bit 7 (v8.1.0.10) - SetOption89 - Distinct MQTT topics per device for Zigbee (#7835)
uint32_t only_json_message : 1; // bit 8 (v8.2.0.3) - SetOption90 - Disable non-json MQTT response
uint32_t fade_at_startup : 1; // bit 9 (v8.2.0.3) - SetOption91 - Enable light fading at start/power on
uint32_t pwm_ct_mode : 1; // bit 10 () - SetOption92 - Set PWM Mode from regular PWM to ColorTemp control (Xiaomi Philips ...)
uint32_t pwm_ct_mode : 1; // bit 10 (v8.2.0.4) - SetOption92 - Set PWM Mode from regular PWM to ColorTemp control (Xiaomi Philips ...)
uint32_t spare11 : 1;
uint32_t spare12 : 1;
uint32_t spare13 : 1;
@ -358,8 +358,15 @@ 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[11]; // 446
#endif // ESP8266 - ESP32
char serial_delimiter; // 451
uint8_t seriallog_level; // 452
@ -403,14 +410,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

View File

@ -1386,6 +1386,13 @@ void SettingsDelta(void)
#endif // ESP32
}
if (Settings.version < 0x08020006) {
#ifdef ESP32
Settings.module = WEMOS;
ModuleDefault(WEMOS);
#endif // ESP32
}
Settings.version = VERSION;
SettingsSave(1);
}

View File

@ -1073,37 +1073,38 @@ int ResponseJsonEndEnd(void)
* GPIO Module and Template management
\*********************************************************************************************/
#ifndef ARDUINO_ESP8266_RELEASE_2_3_0 // Fix core 2.5.x ISR not in IRAM Exception
uint32_t Pin(uint32_t gpio, uint32_t index) ICACHE_RAM_ATTR;
#endif
uint32_t Pin(uint32_t gpio, uint32_t index = 0);
uint32_t Pin(uint32_t gpio, uint32_t index) {
//#ifdef ESP8266
return pin[gpio + index]; // Pin number configured for gpio or 99 if not used
/*
#else
#ifdef ESP8266
uint16_t real_gpio = gpio + index;
#else // ESP32
uint16_t real_gpio = (gpio << 5) + index;
for (uint32_t i = 0; i < ARRAY_SIZE(pin); i++) {
if (pin[i] == real_gpio) {
#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);
boolean PinUsed(uint32_t gpio, uint32_t index) {
return (Pin(gpio, index) < 99);
}
void SetPin(uint32_t lpin, uint32_t gpio) {
//#ifdef ESP8266
pin[gpio] = lpin;
/*
#else
pin[lpin] = gpio;
#endif
*/
gpio_pin[lpin] = gpio;
}
void DigitalWrite(uint32_t gpio_pin, uint32_t state)
void DigitalWrite(uint32_t gpio_pin, uint32_t index, uint32_t state)
{
if (Pin(gpio_pin) < 99) {
digitalWrite(Pin(gpio_pin), state &1);
if (PinUsed(gpio_pin, index)) {
digitalWrite(Pin(gpio_pin, index), state &1);
}
}
@ -1147,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) {
@ -1185,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;
}
@ -1230,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
@ -1248,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;
@ -1332,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; }
@ -1348,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
}
@ -1851,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);
}

View File

@ -60,7 +60,7 @@ void ButtonInit(void)
{
Button.present = 0;
for (uint32_t i = 0; i < MAX_KEYS; i++) {
if (Pin(GPIO_KEY1, i) < 99) {
if (PinUsed(GPIO_KEY1, i)) {
Button.present++;
pinMode(Pin(GPIO_KEY1, i), bitRead(Button.no_pullup_mask, i) ? INPUT : ((16 == Pin(GPIO_KEY1, i)) ? INPUT_PULLDOWN_16 : INPUT_PULLUP));
}
@ -135,7 +135,7 @@ void ButtonHandler(void)
}
else
#endif // ESP8266
if (Pin(GPIO_KEY1, button_index) < 99) {
if (PinUsed(GPIO_KEY1, button_index)) {
button_present = 1;
button = (digitalRead(Pin(GPIO_KEY1, button_index)) != bitRead(Button.inverted_mask, button_index));
}

View File

@ -60,7 +60,7 @@ void ButtonInit(void)
{
Button.present = 0;
for (uint32_t i = 0; i < MAX_KEYS; i++) {
if (Pin(GPIO_KEY1, i) < 99) {
if (PinUsed(GPIO_KEY1, i)) {
Button.present++;
pinMode(Pin(GPIO_KEY1, i), bitRead(Button.no_pullup_mask, i) ? INPUT : ((16 == Pin(GPIO_KEY1, i)) ? INPUT_PULLDOWN_16 : INPUT_PULLUP));
}
@ -132,7 +132,7 @@ void ButtonHandler(void)
}
else
#endif // ESP8266
if (Pin(GPIO_KEY1, button_index) < 99) {
if (PinUsed(GPIO_KEY1, button_index)) {
button_present = 1;
button = (digitalRead(Pin(GPIO_KEY1, button_index)) != bitRead(Button.inverted_mask, button_index));
}
@ -266,7 +266,7 @@ void ButtonHandler(void)
} else {
SendKey(KEY_BUTTON, button_index +1, Button.press_counter[button_index] +9); // 2,3,4 and 5 press send just the key value (11,12,13 and 14) for rules
if (0 == button_index) { // BUTTON1 can toggle up to 5 relays if present. If a relay is not present will send out the key value (2,11,12,13 and 14) for rules
if ((Button.press_counter[button_index] > 1 && Pin(GPIO_REL1, Button.press_counter[button_index]-1) < 99) && Button.press_counter[button_index] <= MAX_RELAY_BUTTON1) {
if ((Button.press_counter[button_index] > 1 && PinUsed(GPIO_REL1, Button.press_counter[button_index]-1)) && Button.press_counter[button_index] <= MAX_RELAY_BUTTON1) {
ExecuteCommandPower(button_index + Button.press_counter[button_index], POWER_TOGGLE, SRC_BUTTON); // Execute Toggle command internally
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DBG: Relay%d found on GPIO%d"), Button.press_counter[button_index], Pin(GPIO_REL1, Button.press_counter[button_index]-1));
}

View File

@ -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;
@ -1167,7 +1197,7 @@ void CmndTemplate(void)
void CmndPwm(void)
{
if (pwm_present && (XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_PWMS)) {
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= Settings.pwm_range) && (Pin(GPIO_PWM1, XdrvMailbox.index -1) < 99)) {
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= Settings.pwm_range) && PinUsed(GPIO_PWM1, XdrvMailbox.index -1)) {
Settings.pwm_value[XdrvMailbox.index -1] = XdrvMailbox.payload;
analogWrite(Pin(GPIO_PWM1, XdrvMailbox.index -1), bitRead(pwm_inverted, XdrvMailbox.index -1) ? Settings.pwm_range - XdrvMailbox.payload : XdrvMailbox.payload);
}
@ -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);
}
@ -1694,7 +1732,7 @@ void CmndAltitude(void)
void CmndLedPower(void)
{
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_LEDS)) {
if (99 == Pin(GPIO_LEDLNK)) { XdrvMailbox.index = 1; }
if (!PinUsed(GPIO_LEDLNK)) { XdrvMailbox.index = 1; }
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 2)) {
Settings.ledstate &= 8; // Disable power control
uint32_t mask = 1 << (XdrvMailbox.index -1); // Led to control
@ -1713,14 +1751,14 @@ void CmndLedPower(void)
break;
}
blinks = 0;
if (99 == Pin(GPIO_LEDLNK)) {
if (!PinUsed(GPIO_LEDLNK)) {
SetLedPower(Settings.ledstate &8);
} else {
SetLedPowerIdx(XdrvMailbox.index -1, (led_power & mask));
}
}
bool state = bitRead(led_power, XdrvMailbox.index -1);
if (99 == Pin(GPIO_LEDLNK)) {
if (!PinUsed(GPIO_LEDLNK)) {
state = bitRead(Settings.ledstate, 3);
}
ResponseCmndIdxChar(GetStateText(state));

View File

@ -80,7 +80,7 @@ bool RotaryButtonPressed(void)
void RotaryInit(void)
{
Rotary.present = 0;
if ((Pin(GPIO_ROT1A) < 99) && (Pin(GPIO_ROT1B) < 99)) {
if (PinUsed(GPIO_ROT1A) && PinUsed(GPIO_ROT1B)) {
Rotary.present++;
pinMode(Pin(GPIO_ROT1A), INPUT_PULLUP);
pinMode(Pin(GPIO_ROT1B), INPUT_PULLUP);

View File

@ -86,7 +86,7 @@ void SwitchProbe(void)
uint8_t force_low = (Settings.switch_debounce % 50) &2; // 52, 102, 152 etc
for (uint32_t i = 0; i < MAX_SWITCHES; i++) {
if (Pin(GPIO_SWT1, i) < 99) {
if (PinUsed(GPIO_SWT1, i)) {
// Olimex user_switch2.c code to fix 50Hz induced pulses
if (1 == digitalRead(Pin(GPIO_SWT1, i))) {
@ -127,7 +127,7 @@ void SwitchInit(void)
Switch.present = 0;
for (uint32_t i = 0; i < MAX_SWITCHES; i++) {
Switch.last_state[i] = 1; // Init global to virtual switch state;
if (Pin(GPIO_SWT1, i) < 99) {
if (PinUsed(GPIO_SWT1, i)) {
Switch.present++;
pinMode(Pin(GPIO_SWT1, i), bitRead(Switch.no_pullup_mask, i) ? INPUT : ((16 == Pin(GPIO_SWT1, i)) ? INPUT_PULLDOWN_16 : INPUT_PULLUP));
Switch.last_state[i] = digitalRead(Pin(GPIO_SWT1, i)); // Set global now so doesn't change the saved power state on first switch check
@ -148,7 +148,7 @@ void SwitchHandler(uint8_t mode)
uint16_t loops_per_second = 1000 / Settings.switch_debounce;
for (uint32_t i = 0; i < MAX_SWITCHES; i++) {
if ((Pin(GPIO_SWT1, i) < 99) || (mode)) {
if (PinUsed(GPIO_SWT1, i) || (mode)) {
uint8_t button = Switch.virtual_state[i];
uint8_t switchflag = POWER_TOGGLE +1;

View File

@ -166,7 +166,7 @@ void SetLatchingRelay(power_t lpower, uint32_t state)
for (uint32_t i = 0; i < devices_present; i++) {
uint32_t port = (i << 1) + ((latching_power >> i) &1);
DigitalWrite(GPIO_REL1 +port, bitRead(rel_inverted, port) ? !state : state);
DigitalWrite(GPIO_REL1, port, bitRead(rel_inverted, port) ? !state : state);
}
}
@ -228,7 +228,7 @@ void SetDevicePower(power_t rpower, uint32_t source)
for (uint32_t i = 0; i < devices_present; i++) {
power_t state = rpower &1;
if (i < MAX_RELAYS) {
DigitalWrite(GPIO_REL1 +i, bitRead(rel_inverted, i) ? !state : state);
DigitalWrite(GPIO_REL1, i, bitRead(rel_inverted, i) ? !state : state);
}
rpower >>= 1;
}
@ -325,7 +325,7 @@ void SetPowerOnState(void)
// Issue #526 and #909
for (uint32_t i = 0; i < devices_present; i++) {
if (!Settings.flag3.no_power_feedback) { // SetOption63 - Don't scan relay power state at restart - #5594 and #5663
if ((i < MAX_RELAYS) && (Pin(GPIO_REL1, i) < 99)) {
if ((i < MAX_RELAYS) && PinUsed(GPIO_REL1, i)) {
bitWrite(power, i, digitalRead(Pin(GPIO_REL1, i)) ^ bitRead(rel_inverted, i));
}
}
@ -338,12 +338,12 @@ void SetPowerOnState(void)
void SetLedPowerIdx(uint32_t led, uint32_t state)
{
if ((99 == Pin(GPIO_LEDLNK)) && (0 == led)) { // Legacy - LED1 is link led only if LED2 is present
if (Pin(GPIO_LED1, 1) < 99) {
if (!PinUsed(GPIO_LEDLNK) && (0 == led)) { // Legacy - LED1 is link led only if LED2 is present
if (PinUsed(GPIO_LED1, 1)) {
led = 1;
}
}
if (Pin(GPIO_LED1, led) < 99) {
if (PinUsed(GPIO_LED1, led)) {
uint32_t mask = 1 << led;
if (state) {
state = 1;
@ -351,7 +351,7 @@ void SetLedPowerIdx(uint32_t led, uint32_t state)
} else {
led_power &= (0xFF ^ mask);
}
DigitalWrite(Pin(GPIO_LED1, led), bitRead(led_inverted, led) ? !state : state);
DigitalWrite(GPIO_LED1, led, bitRead(led_inverted, led) ? !state : state);
}
#ifdef USE_BUZZER
if (led == 0) {
@ -362,7 +362,7 @@ void SetLedPowerIdx(uint32_t led, uint32_t state)
void SetLedPower(uint32_t state)
{
if (99 == Pin(GPIO_LEDLNK)) { // Legacy - Only use LED1 and/or LED2
if (!PinUsed(GPIO_LEDLNK)) { // Legacy - Only use LED1 and/or LED2
SetLedPowerIdx(0, state);
} else {
power_t mask = 1;
@ -608,7 +608,7 @@ void MqttShowPWMState(void)
ResponseAppend_P(PSTR("\"" D_CMND_PWM "\":{"));
bool first = true;
for (uint32_t i = 0; i < MAX_PWMS; i++) {
if (Pin(GPIO_PWM1, i) < 99) {
if (PinUsed(GPIO_PWM1, i)) {
ResponseAppend_P(PSTR("%s\"" D_CMND_PWM "%d\":%d"), first ? "" : ",", i+1, Settings.pwm_value[i]);
first = false;
}
@ -703,9 +703,9 @@ bool MqttShowSensor(void)
int json_data_start = strlen(mqtt_data);
for (uint32_t i = 0; i < MAX_SWITCHES; i++) {
#ifdef USE_TM1638
if ((Pin(GPIO_SWT1, i) < 99) || ((Pin(GPIO_TM16CLK) < 99) && (Pin(GPIO_TM16DIO) < 99) && (Pin(GPIO_TM16STB) < 99))) {
if (PinUsed(GPIO_SWT1, i) || (PinUsed(GPIO_TM16CLK) && PinUsed(GPIO_TM16DIO) && PinUsed(GPIO_TM16STB))) {
#else
if (Pin(GPIO_SWT1, i) < 99) {
if (PinUsed(GPIO_SWT1, i)) {
#endif // USE_TM1638
ResponseAppend_P(PSTR(",\"" D_JSON_SWITCH "%d\":\"%s\""), i +1, GetStateText(SwitchState(i)));
}
@ -913,7 +913,7 @@ void Every250mSeconds(void)
if (200 == blinks) blinks = 0; // Disable blink
}
}
if (Settings.ledstate &1 && (Pin(GPIO_LEDLNK) < 99 || !(blinks || restart_flag || ota_state_flag)) ) {
if (Settings.ledstate &1 && (PinUsed(GPIO_LEDLNK) || !(blinks || restart_flag || ota_state_flag)) ) {
bool tstate = power & Settings.ledmask;
#ifdef ESP8266
if ((SONOFF_TOUCH == my_module_type) || (SONOFF_T11 == my_module_type) || (SONOFF_T12 == my_module_type) || (SONOFF_T13 == my_module_type)) {
@ -1320,7 +1320,7 @@ void SerialInput(void)
void ResetPwm(void)
{
for (uint32_t i = 0; i < MAX_PWMS; i++) { // Basic PWM control only
if (Pin(GPIO_PWM1, i) < 99) {
if (PinUsed(GPIO_PWM1, i)) {
analogWrite(Pin(GPIO_PWM1, i), bitRead(pwm_inverted, i) ? Settings.pwm_range : 0);
// analogWrite(Pin(GPIO_PWM1, i), bitRead(pwm_inverted, i) ? Settings.pwm_range - Settings.pwm_value[i] : Settings.pwm_value[i]);
}
@ -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,51 +1383,49 @@ void GpioInit(void)
if ((template_adc0 > ADC0_NONE) && (template_adc0 < ADC0_USER)) {
my_adc0 = template_adc0; // Force Template override
}
#endif
for (uint32_t i = 0; i < GPIO_MAX; i++) {
SetPin(99, i);
}
for (uint32_t i = 0; i < ARRAY_SIZE(my_module.io); i++) {
uint32_t mpin = ValidPin(i, my_module.io[i]);
DEBUG_CORE_LOG(PSTR("INI: gpio pin %d, mpin %d"), i, mpin);
if (mpin) {
if (mpin) { // Above GPIO_NONE
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;
@ -1435,22 +1434,25 @@ void GpioInit(void)
mpin = XdrvMailbox.index;
};
}
if (mpin) { SetPin(i, mpin); }
if (mpin) { SetPin(i, mpin); } // Anything above GPIO_NONE and below GPIO_SENSOR_END
}
// 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
#ifdef ESP8266
analogWriteRange(Settings.pwm_range); // Default is 1023 (Arduino.h)
analogWriteFreq(Settings.pwm_frequency); // Default is 1000 (core_esp8266_wiring_pwm.c)
#else
analogWriteFreqRange(0,Settings.pwm_frequency,Settings.pwm_range);
#endif
#ifdef USE_SPI
spi_flg = ((((Pin(GPIO_SPI_CS) < 99) && (Pin(GPIO_SPI_CS) > 14)) || (Pin(GPIO_SPI_CS) < 12)) || (((Pin(GPIO_SPI_DC) < 99) && (Pin(GPIO_SPI_DC) > 14)) || (Pin(GPIO_SPI_DC) < 12)));
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) {
for (uint32_t i = 0; i < GPIO_MAX; i++) {
if ((Pin(i) >= 12) && (Pin(i) <=14)) { SetPin(99, i); }
}
my_module.io[12] = GPIO_SPI_MISO;
SetPin(12, GPIO_SPI_MISO);
my_module.io[13] = GPIO_SPI_MOSI;
@ -1458,7 +1460,7 @@ void GpioInit(void)
my_module.io[14] = GPIO_SPI_CLK;
SetPin(14, GPIO_SPI_CLK);
}
soft_spi_flg = ((Pin(GPIO_SSPI_CS) < 99) && (Pin(GPIO_SSPI_SCLK) < 99) && ((Pin(GPIO_SSPI_MOSI) < 99) || (Pin(GPIO_SSPI_MOSI) < 99)));
soft_spi_flg = (PinUsed(GPIO_SSPI_CS) && PinUsed(GPIO_SSPI_SCLK) && (PinUsed(GPIO_SSPI_MOSI) || PinUsed(GPIO_SSPI_MISO)));
#endif // USE_SPI
// Set any non-used GPIO to INPUT - Related to resetPins() in support_legacy_cores.ino
@ -1474,7 +1476,7 @@ void GpioInit(void)
}
#ifdef USE_I2C
i2c_flg = ((Pin(GPIO_I2C_SCL) < 99) && (Pin(GPIO_I2C_SDA) < 99));
i2c_flg = (PinUsed(GPIO_I2C_SCL) && PinUsed(GPIO_I2C_SDA));
if (i2c_flg) {
Wire.begin(Pin(GPIO_I2C_SDA), Pin(GPIO_I2C_SCL));
}
@ -1506,8 +1508,13 @@ void GpioInit(void)
#endif // ESP8266
for (uint32_t i = 0; i < MAX_PWMS; i++) { // Basic PWM control only
if (Pin(GPIO_PWM1, i) < 99) {
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);
@ -1519,7 +1526,7 @@ void GpioInit(void)
}
for (uint32_t i = 0; i < MAX_RELAYS; i++) {
if (Pin(GPIO_REL1, i) < 99) {
if (PinUsed(GPIO_REL1, i)) {
pinMode(Pin(GPIO_REL1, i), OUTPUT);
devices_present++;
#ifdef ESP8266
@ -1532,11 +1539,10 @@ void GpioInit(void)
}
for (uint32_t i = 0; i < MAX_LEDS; i++) {
if (Pin(GPIO_LED1, i) < 99) {
if (PinUsed(GPIO_LED1, i)) {
#ifdef USE_ARILUX_RF
if ((3 == i) && (leds_present < 2) && (99 == Pin(GPIO_ARIRFSEL))) {
if ((3 == i) && (leds_present < 2) && !PinUsed(GPIO_ARIRFSEL)) {
SetPin(Pin(GPIO_LED4), GPIO_ARIRFSEL); // Legacy support where LED4 was Arilux RF enable
SetPin(99, GPIO_LED4);
} else {
#endif
pinMode(Pin(GPIO_LED1, i), OUTPUT);
@ -1547,13 +1553,13 @@ void GpioInit(void)
#endif
}
}
if (Pin(GPIO_LEDLNK) < 99) {
if (PinUsed(GPIO_LEDLNK)) {
pinMode(Pin(GPIO_LEDLNK), OUTPUT);
digitalWrite(Pin(GPIO_LEDLNK), ledlnk_inverted);
}
#ifdef USE_PWM_DIMMER
if (PWM_DIMMER == my_module_type && Pin(GPIO_REL1) < 99) { devices_present--; }
if (PWM_DIMMER == my_module_type && PinUsed(GPIO_REL1)) { devices_present--; }
#endif // USE_PWM_DIMMER
ButtonInit();

View File

@ -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

View File

@ -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]; // 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,9 +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
uint8_t pin[GPIO_MAX]; // Possible pin configurations
//#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))
@ -147,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
@ -268,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);
}

View File

@ -53,10 +53,6 @@ extern "C" void resetPins();
* Mandatory defines satisfying disabled defines
\*********************************************************************************************/
#ifndef MODULE
#define MODULE SONOFF_BASIC // [Module] Select default model
#endif
#ifdef USE_EMULATION_HUE
#define USE_EMULATION
#endif
@ -278,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
@ -288,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
@ -295,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
@ -322,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)

View File

@ -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
@ -704,31 +706,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 {
@ -763,10 +748,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,

View File

@ -42,12 +42,678 @@
#undef USE_TUYA_MCU
#undef USE_PS_16_DZ
enum UserSelectablePins {
GPIO_NONE, // Not used
GPIO_KEY1, // 4 x Button usually connected to GPIO0
GPIO_KEY1_NP,
GPIO_KEY1_INV,
GPIO_KEY1_INV_NP,
GPIO_SWT1, // 8 x User connected external switches
GPIO_SWT1_NP,
GPIO_REL1, // 8 x Relays
GPIO_REL1_INV,
GPIO_LED1, // 4 x Leds
GPIO_LED1_INV,
GPIO_CNTR1, // 4 x Counter
GPIO_CNTR1_NP,
GPIO_PWM1, // 5 x PWM
GPIO_PWM1_INV,
GPIO_BUZZER, // Buzzer
GPIO_BUZZER_INV, // Inverted buzzer
GPIO_LEDLNK, // Link led
GPIO_LEDLNK_INV, // Inverted link led
GPIO_I2C_SCL, // I2C SCL
GPIO_I2C_SDA, // I2C SDA
GPIO_SPI_MISO, // SPI MISO
GPIO_SPI_MOSI, // SPI MOSI
GPIO_SPI_CLK, // SPI Clk
GPIO_SPI_CS, // SPI Chip Select
GPIO_SPI_DC, // SPI Data Direction
GPIO_SSPI_MISO, // Software SPI Master Input Slave Output
GPIO_SSPI_MOSI, // Software SPI Master Output Slave Input
GPIO_SSPI_SCLK, // Software SPI Serial Clock
GPIO_SSPI_CS, // Software SPI Chip Select
GPIO_SSPI_DC, // Software SPI Data or Command
GPIO_BACKLIGHT, // Display backlight control
GPIO_OLED_RESET, // OLED Display Reset
GPIO_IRSEND, // IR remote
GPIO_IRRECV, // IR receiver
GPIO_RFSEND, // RF transmitter
GPIO_RFRECV, // RF receiver
GPIO_DHT11, // DHT11
GPIO_DHT22, // DHT21, DHT22, AM2301, AM2302, AM2321
GPIO_SI7021, // iTead SI7021
GPIO_DHT11_OUT, // Pseudo Single wire DHT11, DHT21, DHT22, AM2301, AM2302, AM2321
GPIO_DSB, // Single wire DS18B20 or DS18S20
GPIO_DSB_OUT, // Pseudo Single wire DS18B20 or DS18S20
GPIO_WS2812, // WS2812 Led string
GPIO_MHZ_TXD, // MH-Z19 Serial interface
GPIO_MHZ_RXD, // MH-Z19 Serial interface
GPIO_PZEM0XX_TX, // PZEM0XX Serial interface
GPIO_PZEM004_RX, // PZEM004T Serial interface
GPIO_PZEM016_RX, // PZEM-014,016 Serial Modbus interface
GPIO_PZEM017_RX, // PZEM-003,017 Serial Modbus interface
GPIO_SAIR_TX, // SenseAir Serial interface
GPIO_SAIR_RX, // SenseAir Serial interface
GPIO_PMS5003_TX, // Plantower PMS5003 Serial interface
GPIO_PMS5003_RX, // Plantower PMS5003 Serial interface
GPIO_SDS0X1_TX, // Nova Fitness SDS011 Serial interface
GPIO_SDS0X1_RX, // Nova Fitness SDS011 Serial interface
GPIO_SBR_TX, // Serial Bridge Serial interface
GPIO_SBR_RX, // Serial Bridge Serial interface
GPIO_SR04_TRIG, // SR04 Trigger/TX pin
GPIO_SR04_ECHO, // SR04 Echo/RX pin
GPIO_SDM120_TX, // SDM120 Serial interface
GPIO_SDM120_RX, // SDM120 Serial interface
GPIO_SDM630_TX, // SDM630 Serial interface
GPIO_SDM630_RX, // SDM630 Serial interface
GPIO_TM16CLK, // TM1638 Clock
GPIO_TM16DIO, // TM1638 Data I/O
GPIO_TM16STB, // TM1638 Strobe
GPIO_MP3_DFR562, // RB-DFR-562, DFPlayer Mini MP3 Player
GPIO_HX711_SCK, // HX711 Load Cell clock
GPIO_HX711_DAT, // HX711 Load Cell data
GPIO_TX2X_TXD_BLACK, // TX20/TX23 Transmission Pin
GPIO_TUYA_TX, // Tuya Serial interface
GPIO_TUYA_RX, // Tuya Serial interface
GPIO_MGC3130_XFER, // MGC3130 Transfer
GPIO_MGC3130_RESET, // MGC3130 Reset
GPIO_RF_SENSOR, // Rf receiver with sensor decoding
GPIO_AZ_TXD, // AZ-Instrument 7798 Serial interface
GPIO_AZ_RXD, // AZ-Instrument 7798 Serial interface
GPIO_MAX31855CS, // MAX31855 Serial interface
GPIO_MAX31855CLK, // MAX31855 Serial interface
GPIO_MAX31855DO, // MAX31855 Serial interface
GPIO_NRG_SEL, // HLW8012/HLJ-01 Sel output (1 = Voltage)
GPIO_NRG_SEL_INV, // HLW8012/HLJ-01 Sel output (0 = Voltage)
GPIO_NRG_CF1, // HLW8012/HLJ-01 CF1 voltage / current
GPIO_HLW_CF, // HLW8012 CF power
GPIO_HJL_CF, // HJL-01/BL0937 CF power
GPIO_MCP39F5_TX, // MCP39F501 Serial interface (Shelly2)
GPIO_MCP39F5_RX, // MCP39F501 Serial interface (Shelly2)
GPIO_MCP39F5_RST, // MCP39F501 Reset (Shelly2)
GPIO_PN532_TXD, // PN532 NFC Serial Tx
GPIO_PN532_RXD, // PN532 NFC Serial Rx
GPIO_SM16716_CLK, // SM16716 CLOCK
GPIO_SM16716_DAT, // SM16716 DATA
GPIO_SM16716_SEL, // SM16716 SELECT
GPIO_DI, // my92x1 PWM input
GPIO_DCKI, // my92x1 CLK input
GPIO_CSE7766_TX, // CSE7766 Serial interface (S31 and Pow R2) - Not used anymore 20200121
GPIO_CSE7766_RX, // CSE7766 Serial interface (S31 and Pow R2)
GPIO_ARIRFRCV, // AriLux RF Receive input
GPIO_TXD, // Serial interface
GPIO_RXD, // Serial interface
GPIO_ROT1A, // Rotary switch1 A Pin
GPIO_ROT1B, // Rotary switch1 B Pin
GPIO_ROT2A, // Rotary switch2 A Pin
GPIO_ROT2B, // Rotary switch2 B Pin
GPIO_HRE_CLOCK, // Clock/Power line for HR-E Water Meter
GPIO_HRE_DATA, // Data line for HR-E Water Meter
GPIO_ADE7953_IRQ, // ADE7953 IRQ
GPIO_ARIRFSEL, // Arilux RF Receive input selected
GPIO_SOLAXX1_TX, // Solax Inverter tx pin
GPIO_SOLAXX1_RX, // Solax Inverter rx pin
GPIO_ZIGBEE_TX, // Zigbee Serial interface
GPIO_ZIGBEE_RX, // Zigbee Serial interface
GPIO_RDM6300_RX, // RDM6300 RX
GPIO_IBEACON_TX, // HM17 IBEACON TX
GPIO_IBEACON_RX, // HM17 IBEACON RX
GPIO_A4988_DIR, // A4988 direction pin
GPIO_A4988_STP, // A4988 step pin
GPIO_A4988_ENA, // A4988 enabled pin
GPIO_A4988_MS1, // A4988 microstep pin1
GPIO_A4988_MS2, // A4988 microstep pin2
GPIO_A4988_MS3, // A4988 microstep pin3
GPIO_DDS2382_TX, // DDS2382 Serial interface
GPIO_DDS2382_RX, // DDS2382 Serial interface
GPIO_DDSU666_TX, // DDSU666 Serial interface
GPIO_DDSU666_RX, // DDSU666 Serial interface
GPIO_SM2135_CLK, // SM2135 Clk
GPIO_SM2135_DAT, // SM2135 Dat
GPIO_DEEPSLEEP, // Kill switch for deepsleep
GPIO_EXS_ENABLE, // EXS MCU Enable
GPIO_TASMOTASLAVE_TXD, // Slave TX
GPIO_TASMOTASLAVE_RXD, // Slave RX
GPIO_TASMOTASLAVE_RST, // Slave Reset Pin
GPIO_TASMOTASLAVE_RST_INV, // Slave Reset Inverted
GPIO_HPMA_RX, // Honeywell HPMA115S0 Serial interface
GPIO_HPMA_TX, // Honeywell HPMA115S0 Serial interface
GPIO_GPS_RX, // GPS serial interface
GPIO_GPS_TX, // GPS serial interface
GPIO_HM10_RX, // HM10-BLE-Mijia-bridge serial interface
GPIO_HM10_TX, // HM10-BLE-Mijia-bridge serial interface
GPIO_LE01MR_RX, // F&F LE-01MR energy meter
GPIO_LE01MR_TX, // F&F LE-01MR energy meter
GPIO_CC1101_GDO0, // CC1101 pin for RX
GPIO_CC1101_GDO2, // CC1101 pin for RX
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, // Thermistor
ADC0_LIGHT, // Light sensor
ADC0_BUTTON, // Button
ADC0_BUTTON_INV,
ADC0_RANGE, // Range
ADC0_CT_POWER, // Current
// webcam interface
GPIO_WEBCAM_PWDN_GPIO_NUM,
GPIO_WEBCAM_RESET_GPIO_NUM,
GPIO_WEBCAM_XCLK_GPIO_NUM,
GPIO_WEBCAM_SIOD_GPIO_NUM,
GPIO_WEBCAM_SIOC_GPIO_NUM,
GPIO_WEBCAM_Y9_GPIO_NUM,
GPIO_WEBCAM_Y8_GPIO_NUM,
GPIO_WEBCAM_Y7_GPIO_NUM,
GPIO_WEBCAM_Y6_GPIO_NUM,
GPIO_WEBCAM_Y5_GPIO_NUM,
GPIO_WEBCAM_Y4_GPIO_NUM,
GPIO_WEBCAM_Y3_GPIO_NUM,
GPIO_WEBCAM_Y2_GPIO_NUM,
GPIO_WEBCAM_VSYNC_GPIO_NUM,
GPIO_WEBCAM_HREF_GPIO_NUM,
GPIO_WEBCAM_PCLK_GPIO_NUM,
GPIO_WEBCAM_PSCLK_GPIO_NUM,
GPIO_WEBCAM_HSD1_GPIO_NUM,
GPIO_WEBCAM_HSD2_GPIO_NUM,
GPIO_WEBCAM_HSD3_GPIO_NUM,
GPIO_WEBCAM_PSRCS_GPIO_NUM,
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_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_ARIRFSEL "|"
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_GPIO_NUM "|"
D_GPIO_WEBCAM_RESET_GPIO_NUM "|"
D_GPIO_WEBCAM_XCLK_GPIO_NUM "|"
D_GPIO_WEBCAM_SIOD_GPIO_NUM "|"
D_GPIO_WEBCAM_SIOC_GPIO_NUM "|"
D_GPIO_WEBCAM_Y9_GPIO_NUM "|"
D_GPIO_WEBCAM_Y8_GPIO_NUM "|"
D_GPIO_WEBCAM_Y7_GPIO_NUM "|"
D_GPIO_WEBCAM_Y6_GPIO_NUM "|"
D_GPIO_WEBCAM_Y5_GPIO_NUM "|"
D_GPIO_WEBCAM_Y4_GPIO_NUM "|"
D_GPIO_WEBCAM_Y3_GPIO_NUM "|"
D_GPIO_WEBCAM_Y2_GPIO_NUM "|"
D_GPIO_WEBCAM_VSYNC_GPIO_NUM "|"
D_GPIO_WEBCAM_HREF_GPIO_NUM "|"
D_GPIO_WEBCAM_PCLK_GPIO_NUM "|"
D_GPIO_WEBCAM_PSCLK_GPIO_NUM "|"
D_GPIO_WEBCAM_HSD1_GPIO_NUM "|"
D_GPIO_WEBCAM_HSD2_GPIO_NUM "|"
D_GPIO_WEBCAM_HSD3_GPIO_NUM "|"
D_GPIO_WEBCAM_PSRCS_GPIO_NUM
;
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
*/
#if defined(ESP32) && defined(USE_WEBCAM)
AGPIO(GPIO_WEBCAM_PWDN_GPIO_NUM),
AGPIO(GPIO_WEBCAM_RESET_GPIO_NUM),
AGPIO(GPIO_WEBCAM_XCLK_GPIO_NUM),
AGPIO(GPIO_WEBCAM_SIOD_GPIO_NUM),
AGPIO(GPIO_WEBCAM_SIOC_GPIO_NUM),
AGPIO(GPIO_WEBCAM_Y9_GPIO_NUM),
AGPIO(GPIO_WEBCAM_Y8_GPIO_NUM),
AGPIO(GPIO_WEBCAM_Y7_GPIO_NUM),
AGPIO(GPIO_WEBCAM_Y6_GPIO_NUM),
AGPIO(GPIO_WEBCAM_Y5_GPIO_NUM),
AGPIO(GPIO_WEBCAM_Y4_GPIO_NUM),
AGPIO(GPIO_WEBCAM_Y3_GPIO_NUM),
AGPIO(GPIO_WEBCAM_Y2_GPIO_NUM),
AGPIO(GPIO_WEBCAM_VSYNC_GPIO_NUM),
AGPIO(GPIO_WEBCAM_HREF_GPIO_NUM),
AGPIO(GPIO_WEBCAM_PCLK_GPIO_NUM),
AGPIO(GPIO_WEBCAM_PSCLK_GPIO_NUM),
AGPIO(GPIO_WEBCAM_HSD1_GPIO_NUM),
AGPIO(GPIO_WEBCAM_HSD2_GPIO_NUM),
AGPIO(GPIO_WEBCAM_HSD3_GPIO_NUM),
AGPIO(GPIO_WEBCAM_PSRCS_GPIO_NUM),
#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 +724,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

View File

@ -20,7 +20,7 @@
#ifndef _TASMOTA_VERSION_H_
#define _TASMOTA_VERSION_H_
const uint32_t VERSION = 0x08020005;
const uint32_t VERSION = 0x08020006;
// Lowest compatible version
const uint32_t VERSION_COMPATIBLE = 0x07010006;

View File

@ -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) ");"
@ -1429,14 +1451,37 @@ 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;
}
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 +1489,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 +1508,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 +1552,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 +1618,39 @@ 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;
}
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 +1658,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 +1673,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 +1712,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);

View File

@ -1244,7 +1244,7 @@ bool LightModuleInit(void)
if (Settings.flag.pwm_control) { // SetOption15 - Switch between commands PWM or COLOR/DIMMER/CT/CHANNEL
for (uint32_t i = 0; i < MAX_PWMS; i++) {
if (Pin(GPIO_PWM1, i) < 99) { light_type++; } // Use Dimmer/Color control for all PWM as SetOption15 = 1
if (PinUsed(GPIO_PWM1, i)) { light_type++; } // Use Dimmer/Color control for all PWM as SetOption15 = 1
}
}
@ -1347,12 +1347,12 @@ void LightInit(void)
if (light_type < LT_PWM6) { // PWM
for (uint32_t i = 0; i < light_type; i++) {
Settings.pwm_value[i] = 0; // Disable direct PWM control
if (Pin(GPIO_PWM1, i) < 99) {
if (PinUsed(GPIO_PWM1, i)) {
pinMode(Pin(GPIO_PWM1, i), OUTPUT);
}
}
if (Pin(GPIO_ARIRFRCV) < 99) {
if (Pin(GPIO_ARIRFSEL) < 99) {
if (PinUsed(GPIO_ARIRFRCV)) {
if (PinUsed(GPIO_ARIRFSEL)) {
pinMode(Pin(GPIO_ARIRFSEL), OUTPUT);
digitalWrite(Pin(GPIO_ARIRFSEL), 1); // Turn off RF
}
@ -1702,17 +1702,19 @@ void LightCycleColor(int8_t direction)
#ifdef USE_LIGHT_PALETTE
if (Light.palette_count) {
if (0 == direction) {
Light.wheel = random(Light.palette_count);
}
else {
Light.wheel += direction;
if (Light.wheel >= Light.palette_count) {
Light.wheel = 0;
if (direction < 0) Light.wheel = Light.palette_count - 1;
if (!Light.fade_running) {
if (0 == direction) {
Light.wheel = random(Light.palette_count);
}
else {
Light.wheel += direction;
if (Light.wheel >= Light.palette_count) {
Light.wheel = 0;
if (direction < 0) Light.wheel = Light.palette_count - 1;
}
}
LightSetPaletteEntry();
}
LightSetPaletteEntry();
return;
}
#endif // USE_LIGHT_PALETTE
@ -2133,7 +2135,7 @@ void LightSetOutputs(const uint16_t *cur_col_10) {
// now apply the actual PWM values, adjusted and remapped 10-bits range
if (light_type < LT_PWM6) { // only for direct PWM lights, not for Tuya, Armtronix...
for (uint32_t i = 0; i < (Light.subtype - Light.pwm_offset); i++) {
if (Pin(GPIO_PWM1, i) < 99) {
if (PinUsed(GPIO_PWM1, i)) {
//AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION "Cur_Col%d 10 bits %d"), i, cur_col_10[i]);
uint16_t cur_col = cur_col_10[i + Light.pwm_offset];
if (!isChannelCT(i)) { // if CT don't use pwm_min and pwm_max
@ -2232,27 +2234,21 @@ void calcGammaBulbs(uint16_t cur_col_10[5]) {
}
#ifdef USE_DEVICE_GROUPS
void LightSendDeviceGroupStatus(bool force)
void LightSendDeviceGroupStatus(bool status)
{
static uint8_t last_channels[LST_MAX];
static uint8_t channels_sequence = 0;
static uint8_t last_bri;
uint8_t bri = light_state.getBri();
bool send_bri_update = (force || bri != last_bri);
bool send_bri_update = (status || bri != last_bri);
if (Light.subtype > LST_SINGLE && !Light.devgrp_no_channels_out) {
uint8_t channels[LST_MAX + 1];
light_state.getChannels(channels);
if (force || memcmp(last_channels, channels, LST_MAX)
#ifdef USE_LIGHT_PALETTE
|| (Settings.light_scheme && Light.palette_count)
#endif // USE_LIGHT_PALETTE
) {
memcpy(last_channels, channels, LST_MAX);
channels[LST_MAX] = ++channels_sequence;
SendLocalDeviceGroupMessage((send_bri_update ? DGR_MSGTYP_PARTIAL_UPDATE : DGR_MSGTYP_UPDATE), DGR_ITEM_LIGHT_CHANNELS, channels);
static uint8_t channels[LST_MAX + 1] = { 0, 0, 0, 0, 0, 0 };
if (status) {
light_state.getChannels(channels);
}
else {
memcpy(channels, Light.new_color, LST_MAX);
channels[LST_MAX]++;
}
SendLocalDeviceGroupMessage((send_bri_update ? DGR_MSGTYP_PARTIAL_UPDATE : DGR_MSGTYP_UPDATE), DGR_ITEM_LIGHT_CHANNELS, channels);
}
if (send_bri_update) {
last_bri = bri;

View File

@ -279,28 +279,28 @@ bool Xdrv05(uint8_t function)
{
bool result = false;
if ((Pin(GPIO_IRSEND) < 99) || (Pin(GPIO_IRRECV) < 99)) {
if (PinUsed(GPIO_IRSEND) || PinUsed(GPIO_IRRECV)) {
switch (function) {
case FUNC_PRE_INIT:
if (Pin(GPIO_IRSEND) < 99) {
if (PinUsed(GPIO_IRSEND)) {
IrSendInit();
}
#ifdef USE_IR_RECEIVE
if (Pin(GPIO_IRRECV) < 99) {
if (PinUsed(GPIO_IRRECV)) {
IrReceiveInit();
}
#endif // USE_IR_RECEIVE
break;
case FUNC_EVERY_50_MSECOND:
#ifdef USE_IR_RECEIVE
if (Pin(GPIO_IRRECV) < 99) {
if (PinUsed(GPIO_IRRECV)) {
IrReceiveCheck(); // check if there's anything on IR side
}
#endif // USE_IR_RECEIVE
irsend_active = false; // re-enable IR reception
break;
case FUNC_COMMAND:
if (Pin(GPIO_IRSEND) < 99) {
if (PinUsed(GPIO_IRSEND)) {
result = DecodeCommand(kIrRemoteCommands, IrRemoteCommand);
}
break;

View File

@ -635,24 +635,24 @@ bool Xdrv05(uint8_t function)
{
bool result = false;
if ((Pin(GPIO_IRSEND) < 99) || (Pin(GPIO_IRRECV) < 99)) {
if (PinUsed(GPIO_IRSEND) || PinUsed(GPIO_IRRECV)) {
switch (function) {
case FUNC_PRE_INIT:
if (Pin(GPIO_IRSEND) < 99) {
if (PinUsed(GPIO_IRSEND)) {
IrSendInit();
}
if (Pin(GPIO_IRRECV) < 99) {
if (PinUsed(GPIO_IRRECV)) {
IrReceiveInit();
}
break;
case FUNC_EVERY_50_MSECOND:
if (Pin(GPIO_IRRECV) < 99) {
if (PinUsed(GPIO_IRRECV)) {
IrReceiveCheck(); // check if there's anything on IR side
}
irsend_active = false; // re-enable IR reception
break;
case FUNC_COMMAND:
if (Pin(GPIO_IRSEND) < 99) {
if (PinUsed(GPIO_IRSEND)) {
result = DecodeCommand(kIrRemoteCommands, IrRemoteCommand);
}
break;

View File

@ -576,7 +576,7 @@ void HandleDomoticzConfiguration(void)
i +1, i, Settings.domoticz_relay_idx[i],
i +1, i, Settings.domoticz_key_idx[i]);
}
if (Pin(GPIO_SWT1, i) < 99) {
if (PinUsed(GPIO_SWT1, i)) {
WSContentSend_P(HTTP_FORM_DOMOTICZ_SWITCH,
i +1, i, Settings.domoticz_switch_idx[i]);
}

View File

@ -87,7 +87,7 @@ void SerialBridgeInput(void)
void SerialBridgeInit(void)
{
serial_bridge_active = false;
if ((Pin(GPIO_SBR_RX) < 99) && (Pin(GPIO_SBR_TX) < 99)) {
if (PinUsed(GPIO_SBR_RX) && PinUsed(GPIO_SBR_TX)) {
SerialBridgeSerial = new TasmotaSerial(Pin(GPIO_SBR_RX), Pin(GPIO_SBR_TX));
if (SerialBridgeSerial->begin(Settings.sbaudrate * 300)) { // Baud rate is stored div 300 so it fits into 16 bits
if (SerialBridgeSerial->hardwareSerial()) {

View File

@ -580,9 +580,9 @@ void RulesEvery50ms(void)
// Boot time SWITCHES Status
for (uint32_t i = 0; i < MAX_SWITCHES; i++) {
#ifdef USE_TM1638
if ((Pin(GPIO_SWT1, i) < 99) || ((Pin(GPIO_TM16CLK) < 99) && (Pin(GPIO_TM16DIO) < 99) && (Pin(GPIO_TM16STB) < 99))) {
if (PinUsed(GPIO_SWT1, i) || (PinUsed(GPIO_TM16CLK) && PinUsed(GPIO_TM16DIO) && PinUsed(GPIO_TM16STB))) {
#else
if (Pin(GPIO_SWT1, i) < 99) {
if (PinUsed(GPIO_SWT1, i)) {
#endif // USE_TM1638
snprintf_P(json_event, sizeof(json_event), PSTR("{\"" D_JSON_SWITCH "%d\":{\"Boot\":%d}}"), i +1, (SwitchState(i)));
RulesProcessEvent(json_event);

View File

@ -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);
@ -102,14 +103,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 +289,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 +610,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 +1192,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 +1229,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 +1323,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 +1367,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 +1429,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 +1438,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 +1447,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 +1471,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;
@ -1573,7 +1663,15 @@ 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++;
goto exit;
@ -1581,14 +1679,23 @@ chknext:
if (!strncmp(vname,"pd[",3)) {
GetNumericResult(vname+3,OPER_EQU,&fvar,0);
uint8_t gpiopin=fvar;
/*
for (uint8_t i=0;i<GPIO_SENSOR_END;i++) {
if (pin[i]==gpiopin) {
// if (pin_gpio[i]==gpiopin) {
if (Pin(i)==gpiopin) {
fvar=i;
// skip ] bracket
len++;
goto exit;
}
}
*/
if ((gpiopin < ARRAY_SIZE(gpio_pin)) && (gpio_pin[gpiopin] > 0)) {
fvar = gpio_pin[gpiopin];
// skip ] bracket
len++;
goto exit;
}
fvar=999;
goto exit;
}
@ -1780,7 +1887,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;
@ -1892,6 +1999,60 @@ 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;
default:
fvar=0;
}
lp++;
len=0;
goto exit;
}
#endif
if (!strncmp(vname,"wday",4)) {
fvar=RtcTime.day_of_week;
goto exit;
@ -2712,9 +2873,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;
@ -2753,6 +2934,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)) {
@ -3264,7 +3460,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 =
@ -3287,6 +3483,7 @@ const char HTTP_FORM_SDC_HREF[] PROGMEM =
uint8_t reject(char *name) {
while (*name=='/') name++;
if (*name=='_') return 1;
if (*name=='.') return 1;
@ -3301,6 +3498,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;
}
@ -3310,7 +3509,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) {
@ -3324,35 +3523,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();
@ -3419,8 +3631,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);
@ -3439,12 +3651,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;
@ -3508,6 +3720,7 @@ void HandleScriptTextareaConfiguration(void) {
}
}
void HandleScriptConfiguration(void) {
if (!HttpCheckPriviledgedAccess()) { return; }
@ -3609,19 +3822,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
@ -4268,6 +4479,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.
@ -4282,8 +4501,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;
@ -4303,7 +4522,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;
@ -4547,7 +4766,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];
@ -4574,12 +4793,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)
@ -4739,6 +4962,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++;
@ -4755,12 +4984,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];
@ -4786,7 +5010,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++;
@ -4797,7 +5022,8 @@ uint8_t msect=Run_Scripter(">m",-2,0);
}
}
} else {
client->println("*");
//client->println("*");
func((char*)"*");
}
}
#endif
@ -4858,14 +5084,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;
@ -4905,15 +5125,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();
}
@ -4924,11 +5158,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;
}
@ -4991,6 +5220,10 @@ bool Xdrv10(uint8_t function)
case FUNC_WEB_ADD_BUTTON:
WSContentSend_P(HTTP_BTN_MENU_RULES);
break;
case FUNC_WEB_ADD_MAIN_BUTTON:
ScriptWebShow('&');
break;
case FUNC_WEB_ADD_HANDLER:
Webserver->on("/" WEB_HANDLE_SCRIPT, HandleScriptConfiguration);
Webserver->on("/ta",HTTP_POST, HandleScriptTextareaConfiguration);
@ -5018,7 +5251,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

View File

@ -370,7 +370,7 @@ void HAssAnnounceSwitches(void)
uint8_t hold = 0;
uint8_t pir = 0;
if (Pin(GPIO_SWT1, switch_index) < 99) { switch_present = 1; }
if (PinUsed(GPIO_SWT1, switch_index)) { switch_present = 1; }
if (KeyTopicActive(1) && strcmp(SettingsText(SET_MQTT_SWITCH_TOPIC), mqtt_topic)) // Enable Discovery for Switches only if Switchtopic is set to a custom name
{
@ -451,7 +451,7 @@ void HAssAnnounceButtons(void)
} else
#endif
{
if (Pin(GPIO_KEY1, button_index) < 99) {
if (PinUsed(GPIO_KEY1, button_index)) {
button_present = 1;
}
}

View File

@ -232,7 +232,7 @@ bool Xdrv14(uint8_t function)
{
bool result = false;
if (Pin(GPIO_MP3_DFR562) < 99) {
if (PinUsed(GPIO_MP3_DFR562)) {
switch (function) {
case FUNC_PRE_INIT:
MP3PlayerInit(); // init and start communication

View File

@ -596,7 +596,7 @@ void TuyaNormalPowerModePacketProcess(void)
bool TuyaModuleSelected(void)
{
if (!(Pin(GPIO_TUYA_RX) < 99) || !(Pin(GPIO_TUYA_TX) < 99)) { // fallback to hardware-serial if not explicitly selected
if (!PinUsed(GPIO_TUYA_RX) || !PinUsed(GPIO_TUYA_TX)) { // fallback to hardware-serial if not explicitly selected
SetPin(1, GPIO_TUYA_TX);
SetPin(3, GPIO_TUYA_RX);
Settings.my_gp.io[1] = GPIO_TUYA_TX;

View File

@ -81,10 +81,10 @@ void RfReceiveCheck(void)
void RfInit(void)
{
if (Pin(GPIO_RFSEND) < 99) {
if (PinUsed(GPIO_RFSEND)) {
mySwitch.enableTransmit(Pin(GPIO_RFSEND));
}
if (Pin(GPIO_RFRECV) < 99) {
if (PinUsed(GPIO_RFRECV)) {
pinMode( Pin(GPIO_RFRECV), INPUT);
mySwitch.enableReceive(Pin(GPIO_RFRECV));
}
@ -170,15 +170,15 @@ bool Xdrv17(uint8_t function)
{
bool result = false;
if ((Pin(GPIO_RFSEND) < 99) || (Pin(GPIO_RFRECV) < 99)) {
if (PinUsed(GPIO_RFSEND) || PinUsed(GPIO_RFRECV)) {
switch (function) {
case FUNC_EVERY_50_MSECOND:
if (Pin(GPIO_RFRECV) < 99) {
if (PinUsed(GPIO_RFRECV)) {
RfReceiveCheck();
}
break;
case FUNC_COMMAND:
if (Pin(GPIO_RFSEND) < 99) {
if (PinUsed(GPIO_RFSEND)) {
result = DecodeCommand(kRfSendCommands, RfSendCommand);
}
break;

View File

@ -162,7 +162,7 @@ void ZigbeeInit(void)
// AddLog_P2(LOG_LEVEL_INFO, PSTR("ZigbeeInit Mem1 = %d"), ESP_getFreeHeap());
zigbee.active = false;
if ((Pin(GPIO_ZIGBEE_RX) < 99) && (Pin(GPIO_ZIGBEE_TX) < 99)) {
if (PinUsed(GPIO_ZIGBEE_RX) && PinUsed(GPIO_ZIGBEE_TX)) {
AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_ZIGBEE "GPIOs Rx:%d Tx:%d"), Pin(GPIO_ZIGBEE_RX), Pin(GPIO_ZIGBEE_TX));
// if seriallog_level is 0, we allow GPIO 13/15 to switch to Hardware Serial
ZigbeeSerial = new TasmotaSerial(Pin(GPIO_ZIGBEE_RX), Pin(GPIO_ZIGBEE_TX), seriallog_level ? 1 : 2, 0, 256); // set a receive buffer of 256 bytes

View File

@ -41,7 +41,7 @@ struct BUZZER {
void BuzzerOff(void)
{
DigitalWrite(GPIO_BUZZER, Buzzer.inverted); // Buzzer Off
DigitalWrite(GPIO_BUZZER, 0, Buzzer.inverted); // Buzzer Off
}
//void BuzzerBeep(uint32_t count = 1, uint32_t on = 1, uint32_t off = 1, uint32_t tune = 0, uint32_t mode = 0);
@ -81,7 +81,7 @@ void BuzzerSetStateToLed(uint32_t state)
{
if (Buzzer.enable && (2 == Buzzer.mode)) {
Buzzer.state = (state != 0);
DigitalWrite(GPIO_BUZZER, (Buzzer.inverted) ? !Buzzer.state : Buzzer.state);
DigitalWrite(GPIO_BUZZER, 0, (Buzzer.inverted) ? !Buzzer.state : Buzzer.state);
}
}
@ -111,7 +111,7 @@ bool BuzzerPinState(void)
void BuzzerInit(void)
{
if (Pin(GPIO_BUZZER) < 99) {
if (PinUsed(GPIO_BUZZER)) {
pinMode(Pin(GPIO_BUZZER), OUTPUT);
BuzzerOff();
} else {
@ -140,7 +140,7 @@ void BuzzerEvery100mSec(void)
Buzzer.duration = Buzzer.set[Buzzer.state];
}
}
DigitalWrite(GPIO_BUZZER, (Buzzer.inverted) ? !Buzzer.state : Buzzer.state);
DigitalWrite(GPIO_BUZZER, 0, (Buzzer.inverted) ? !Buzzer.state : Buzzer.state);
} else {
Buzzer.enable = false;
}

View File

@ -93,7 +93,7 @@ void CmndDoTurn(void) {
}
void CmndSetMIS(void) {
if ((Pin(GPIO_A4988_MS1) < 99) && (Pin(GPIO_A4988_MS2) < 99) && (Pin(GPIO_A4988_MS3) < 99) && (XdrvMailbox.data_len > 0)) {
if (PinUsed(GPIO_A4988_MS1) && PinUsed(GPIO_A4988_MS2) && PinUsed(GPIO_A4988_MS3) && (XdrvMailbox.data_len > 0)) {
short newMIS = strtoul(XdrvMailbox.data,nullptr,10);
myA4988->setMIS(newMIS);
ResponseCmndDone();
@ -122,7 +122,7 @@ void CmndSetRPM(void) {
bool Xdrv25(uint8_t function)
{
bool result = false;
if ((Pin(GPIO_A4988_DIR) < 99) && (Pin(GPIO_A4988_STP) < 99)) {
if (PinUsed(GPIO_A4988_DIR) && PinUsed(GPIO_A4988_STP)) {
switch (function) {
case FUNC_INIT:
A4988Init();

View File

@ -147,7 +147,7 @@ void AriluxRfHandler(void)
void AriluxRfInit(void)
{
if ((Pin(GPIO_ARIRFRCV) < 99) && (Pin(GPIO_ARIRFSEL) < 99)) {
if (PinUsed(GPIO_ARIRFRCV) && PinUsed(GPIO_ARIRFSEL)) {
if (Settings.last_module != Settings.module) {
Settings.rf_code[1][6] = 0;
Settings.rf_code[1][7] = 0;
@ -162,7 +162,7 @@ void AriluxRfInit(void)
void AriluxRfDisable(void)
{
if ((Pin(GPIO_ARIRFRCV) < 99) && (Pin(GPIO_ARIRFSEL) < 99)) {
if (PinUsed(GPIO_ARIRFRCV) && PinUsed(GPIO_ARIRFSEL)) {
detachInterrupt(Pin(GPIO_ARIRFRCV));
digitalWrite(Pin(GPIO_ARIRFSEL), 1); // Turn off RF
}
@ -178,7 +178,7 @@ bool Xdrv26(uint8_t function)
switch (function) {
case FUNC_EVERY_50_MSECOND:
if (Pin(GPIO_ARIRFRCV) < 99) { AriluxRfHandler(); }
if (PinUsed(GPIO_ARIRFRCV)) { AriluxRfHandler(); }
break;
case FUNC_EVERY_SECOND:
if (10 == uptime) { AriluxRfInit(); } // Needs rest before enabling RF interrupts

View File

@ -201,7 +201,7 @@ void ShutterInit(void)
}
} else {
Shutter.mode = SHT_OFF_ON__OPEN_CLOSE;
if ((Pin(GPIO_PWM1, i) < 99) && (Pin(GPIO_CNTR1, i) < 99)) {
if (PinUsed(GPIO_PWM1, i) && PinUsed(GPIO_CNTR1, i)) {
Shutter.mode = SHT_OFF_ON__OPEN_CLOSE_STEPPER;
Shutter.pwm_frequency[i] = 0;
Shutter.accelerator[i] = 0;

View File

@ -54,7 +54,7 @@ bool DeepSleepEnabled(void)
return false; // Disabled
}
if (Pin(GPIO_DEEPSLEEP) < 99) {
if (PinUsed(GPIO_DEEPSLEEP)) {
pinMode(Pin(GPIO_DEEPSLEEP), INPUT_PULLUP);
return (digitalRead(Pin(GPIO_DEEPSLEEP))); // Disable DeepSleep if user holds pin GPIO_DEEPSLEEP low
}

View File

@ -437,17 +437,16 @@ void TasmotaSlave_Init(void)
return;
}
if (!TSlave.SerialEnabled) {
if ((Pin(GPIO_TASMOTASLAVE_RXD) < 99) && (Pin(GPIO_TASMOTASLAVE_TXD) < 99) &&
((Pin(GPIO_TASMOTASLAVE_RST) < 99) || (Pin(GPIO_TASMOTASLAVE_RST_INV) < 99))) {
if (PinUsed(GPIO_TASMOTASLAVE_RXD) && PinUsed(GPIO_TASMOTASLAVE_TXD) &&
(PinUsed(GPIO_TASMOTASLAVE_RST) || PinUsed(GPIO_TASMOTASLAVE_RST_INV))) {
TasmotaSlave_Serial = new TasmotaSerial(Pin(GPIO_TASMOTASLAVE_RXD), Pin(GPIO_TASMOTASLAVE_TXD), 1, 0, 200);
if (TasmotaSlave_Serial->begin(USE_TASMOTA_SLAVE_SERIAL_SPEED)) {
if (TasmotaSlave_Serial->hardwareSerial()) {
ClaimSerial();
}
TasmotaSlave_Serial->setTimeout(50);
if (Pin(GPIO_TASMOTASLAVE_RST_INV) < 99) {
if (PinUsed(GPIO_TASMOTASLAVE_RST_INV)) {
SetPin(Pin(GPIO_TASMOTASLAVE_RST_INV), GPIO_TASMOTASLAVE_RST);
SetPin(99, GPIO_TASMOTASLAVE_RST_INV);
TSlave.inverted = HIGH;
}
pinMode(Pin(GPIO_TASMOTASLAVE_RST), OUTPUT);

View File

@ -73,7 +73,7 @@ bool NRF24initRadio()
bool NRF24Detect(void)
{
if ((Pin(GPIO_SPI_CS)<99) && (Pin(GPIO_SPI_DC)<99)){
if (PinUsed(GPIO_SPI_CS) && PinUsed(GPIO_SPI_DC)) {
SPI.pins(SCK,MOSI,MISO,-1);
if(NRF24initRadio()){
NRF24.chipType = 32; // SPACE

View File

@ -94,7 +94,7 @@ void PWMModulePreInit(void)
PWMDimmerSetPoweredOffLed();
// The relay initializes to on. If the power is supposed to be off, turn the relay off.
if (!power && Pin(GPIO_REL1) < 99) digitalWrite(Pin(GPIO_REL1), bitRead(rel_inverted, 0) ? 1 : 0);
if (!power && PinUsed(GPIO_REL1)) digitalWrite(Pin(GPIO_REL1), bitRead(rel_inverted, 0) ? 1 : 0);
#ifdef USE_PWM_DIMMER_REMOTE
// If remote device mode is enabled, set the device group count to the number of buttons
@ -104,7 +104,7 @@ void PWMModulePreInit(void)
device_group_count = 0;
for (uint32_t button_index = 0; button_index < MAX_KEYS; button_index++) {
if (Pin(GPIO_KEY1, button_index) < 99) device_group_count++;
if (PinUsed(GPIO_KEY1, button_index)) device_group_count++;
}
remote_pwm_dimmer_count = device_group_count - 1;
@ -156,7 +156,7 @@ void PWMDimmerSetBrightnessLeds(int32_t operation)
void PWMDimmerSetPoweredOffLed(void)
{
// Set the powered-off LED state.
if (Pin(GPIO_LEDLNK) < 99) {
if (PinUsed(GPIO_LEDLNK)) {
bool power_off_led_on = !power && Settings.flag4.powered_off_led;
if (ledlnk_inverted) power_off_led_on ^= 1;
digitalWrite(Pin(GPIO_LEDLNK), power_off_led_on);
@ -165,7 +165,7 @@ void PWMDimmerSetPoweredOffLed(void)
void PWMDimmerSetPower(void)
{
DigitalWrite(GPIO_REL1, bitRead(rel_inverted, 0) ? !power : power);
DigitalWrite(GPIO_REL1, 0, bitRead(rel_inverted, 0) ? !power : power);
PWMDimmerSetBrightnessLeds(0);
PWMDimmerSetPoweredOffLed();
}

View File

@ -266,7 +266,7 @@ void KeeloqInit()
\*********************************************************************************************/
bool Xdrv36(uint8_t function)
{
if ((99 == Pin(GPIO_CC1101_GDO0)) || (99 == Pin(GPIO_CC1101_GDO2))) { return false; }
if (!PinUsed(GPIO_CC1101_GDO0) || !PinUsed(GPIO_CC1101_GDO2)) { return false; }
bool result = false;

648
tasmota/xdrv_39_webcam.ino Normal file
View File

@ -0,0 +1,648 @@
#if defined(ESP32) && defined(USE_WEBCAM)
#define XDRV_39 39
#define CAMERA_MODEL_AI_THINKER
//#define USE_TEMPLATE
#define WC_LOGLEVEL LOG_LEVEL_INFO
#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;
uint32_t wc_setup(int32_t fsiz) {
bool psram;
if (fsiz>10) fsiz=10;
wc_stream_active=0;
if (fsiz<0) {
esp_camera_deinit();
return 0;
}
if (wc_up) {
esp_camera_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_GPIO_NUM) && PinUsed(GPIO_WEBCAM_Y3_GPIO_NUM) && PinUsed(GPIO_WEBCAM_Y4_GPIO_NUM) && PinUsed(GPIO_WEBCAM_Y5_GPIO_NUM)\
&& PinUsed(GPIO_WEBCAM_Y6_GPIO_NUM) && PinUsed(GPIO_WEBCAM_Y7_GPIO_NUM) && PinUsed(GPIO_WEBCAM_Y8_GPIO_NUM) && PinUsed(GPIO_WEBCAM_Y9_GPIO_NUM)\
&& PinUsed(GPIO_WEBCAM_XCLK_GPIO_NUM) && PinUsed(GPIO_WEBCAM_PCLK_GPIO_NUM) && PinUsed(GPIO_WEBCAM_VSYNC_GPIO_NUM) && PinUsed(GPIO_WEBCAM_HREF_GPIO_NUM)\
&& PinUsed(GPIO_WEBCAM_SIOD_GPIO_NUM) && PinUsed(GPIO_WEBCAM_SIOC_GPIO_NUM)) {
config.pin_d0 = Pin(GPIO_WEBCAM_Y2_GPIO_NUM); //Y2_GPIO_NUM;
config.pin_d1 = Pin(GPIO_WEBCAM_Y3_GPIO_NUM); //Y3_GPIO_NUM;
config.pin_d2 = Pin(GPIO_WEBCAM_Y4_GPIO_NUM); //Y4_GPIO_NUM;
config.pin_d3 = Pin(GPIO_WEBCAM_Y5_GPIO_NUM); //Y5_GPIO_NUM;
config.pin_d4 = Pin(GPIO_WEBCAM_Y6_GPIO_NUM); //Y6_GPIO_NUM;
config.pin_d5 = Pin(GPIO_WEBCAM_Y7_GPIO_NUM); //Y7_GPIO_NUM;
config.pin_d6 = Pin(GPIO_WEBCAM_Y8_GPIO_NUM); //Y8_GPIO_NUM;
config.pin_d7 = Pin(GPIO_WEBCAM_Y9_GPIO_NUM); //Y9_GPIO_NUM;
config.pin_xclk = Pin(GPIO_WEBCAM_XCLK_GPIO_NUM); //XCLK_GPIO_NUM;
config.pin_pclk = Pin(GPIO_WEBCAM_PCLK_GPIO_NUM); //PCLK_GPIO_NUM;
config.pin_vsync = Pin(GPIO_WEBCAM_VSYNC_GPIO_NUM); //VSYNC_GPIO_NUM;
config.pin_href = Pin(GPIO_WEBCAM_HREF_GPIO_NUM); //HREF_GPIO_NUM;
config.pin_sscb_sda = Pin(GPIO_WEBCAM_SIOD_GPIO_NUM); //SIOD_GPIO_NUM;
config.pin_sscb_scl = Pin(GPIO_WEBCAM_SIOC_GPIO_NUM); //SIOC_GPIO_NUM;
int16_t xpin;
xpin=Pin(GPIO_WEBCAM_PWDN_GPIO_NUM);
if (xpin==99) xpin=-1;
config.pin_pwdn = xpin; //PWDN_GPIO_NUM;
xpin=Pin(GPIO_WEBCAM_RESET_GPIO_NUM);
if (xpin==99) 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.
psram=psramFound();
if (psram) {
config.frame_size = FRAMESIZE_UXGA;
config.jpeg_quality = 10;
config.fb_count = 2;
AddLog_P(WC_LOGLEVEL,"PSRAM found!");
} else {
config.frame_size = FRAMESIZE_VGA;
config.jpeg_quality = 12;
config.fb_count = 1;
AddLog_P(WC_LOGLEVEL,"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,"Camera 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 (wc_s->id.PID == OV3660_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);
AddLog_P(WC_LOGLEVEL,"Camera successfully 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_P(WC_LOGLEVEL, "cant 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_P(WC_LOGLEVEL, "cant 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("no image #: %d"), bnum);
return;
}
client.write((char *)picstore[bnum].buff, picstore[bnum].len);
}
AddLog_P2(WC_LOGLEVEL, PSTR("sending image #: %d"), bnum+1);
}
ESP8266WebServer *CamServer;
#define BOUNDARY "e8b8c539-047d-4777-a985-fbba6edff11e"
WiFiClient client;
void handleMjpeg(void) {
AddLog_P(WC_LOGLEVEL, "handle camserver");
//if (!wc_stream_active) {
wc_stream_active=1;
client = CamServer->client();
AddLog_P(WC_LOGLEVEL, "create client");
//}
}
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_P(WC_LOGLEVEL,"client fail");
goto exit;
}
if (wc_stream_active==1) {
client.flush();
client.setTimeout(3);
AddLog_P(WC_LOGLEVEL, "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_P(WC_LOGLEVEL, "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_P(WC_LOGLEVEL, "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_P(WC_LOGLEVEL, "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_P(WC_LOGLEVEL, "send frame");
exit:
if (!wc_stream_active) {
AddLog_P(WC_LOGLEVEL, "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, "", "");
Serial.printf("WC 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 (value==-1) {
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 (wc_fb->format==PIXFORMAT_JPEG) {
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);
}
}
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_P(WC_LOGLEVEL, "cam stream init");
CamServer->begin();
}
} else {
if (CamServer) {
CamServer->stop();
delete CamServer;
CamServer=NULL;
AddLog_P(WC_LOGLEVEL, "cam stream exit");
}
}
return 0;
}
void wc_loop(void) {
if (CamServer) CamServer->handleClient();
if (wc_stream_active) handleMjpeg_task();
if (motion_detect) detect_motion();
}
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
*/
/*********************************************************************************************\
* 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;
}
return result;
}
#endif

View File

@ -71,8 +71,8 @@ void SSD1306InitDriver(void)
}
uint8_t reset_pin = -1;
if (pin[GPIO_OLED_RESET] < 99) {
reset_pin = pin[GPIO_OLED_RESET];
if (PinUsed(GPIO_OLED_RESET)) {
reset_pin = Pin(GPIO_OLED_RESET);
}
// allocate screen buffer

View File

@ -90,7 +90,7 @@ void Ili9341InitDriver(void)
if (Settings.display_height != ILI9341_TFTHEIGHT) {
Settings.display_height = ILI9341_TFTHEIGHT;
}
tft = new Adafruit_ILI9341(pin[GPIO_SPI_CS], pin[GPIO_SPI_DC]);
tft = new Adafruit_ILI9341(Pin(GPIO_SPI_CS), Pin(GPIO_SPI_DC));
tft->begin();
#ifdef USE_DISPLAY_MODES1TO5
@ -128,9 +128,9 @@ void Ili9341DisplayOnOff(uint8_t on)
{
// tft->showDisplay(on);
// tft->invertDisplay(on);
if (pin[GPIO_BACKLIGHT] < 99) {
pinMode(pin[GPIO_BACKLIGHT], OUTPUT);
digitalWrite(pin[GPIO_BACKLIGHT], on);
if (PinUsed(GPIO_BACKLIGHT)) {
pinMode(Pin(GPIO_BACKLIGHT), OUTPUT);
digitalWrite(Pin(GPIO_BACKLIGHT), on);
}
}

View File

@ -67,13 +67,13 @@ void EpdInitDriver29()
epd = new Epd(EPD_WIDTH,EPD_HEIGHT);
// whiten display with full update, takes 3 seconds
if ((pin[GPIO_SPI_CS] < 99) && (pin[GPIO_SPI_CLK] < 99) && (pin[GPIO_SPI_MOSI] < 99)) {
epd->Begin(pin[GPIO_SPI_CS],pin[GPIO_SPI_MOSI],pin[GPIO_SPI_CLK]);
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("EPD: HardSPI CS %d, CLK %d, MOSI %d"),pin[GPIO_SPI_CS], pin[GPIO_SPI_CLK], pin[GPIO_SPI_MOSI]);
if (PinUsed(GPIO_SPI_CS) && PinUsed(GPIO_SPI_CLK) && PinUsed(GPIO_SPI_MOSI)) {
epd->Begin(Pin(GPIO_SPI_CS),Pin(GPIO_SPI_MOSI),Pin(GPIO_SPI_CLK));
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("EPD: HardSPI CS %d, CLK %d, MOSI %d"),Pin(GPIO_SPI_CS), Pin(GPIO_SPI_CLK), Pin(GPIO_SPI_MOSI));
}
else if ((pin[GPIO_SSPI_CS] < 99) && (pin[GPIO_SSPI_SCLK] < 99) && (pin[GPIO_SSPI_MOSI] < 99)) {
epd->Begin(pin[GPIO_SSPI_CS],pin[GPIO_SSPI_MOSI],pin[GPIO_SSPI_SCLK]);
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("EPD: SoftSPI CS %d, CLK %d, MOSI %d"),pin[GPIO_SSPI_CS], pin[GPIO_SSPI_SCLK], pin[GPIO_SSPI_MOSI]);
else if (PinUsed(GPIO_SSPI_CS) && PinUsed(GPIO_SSPI_SCLK) && PinUsed(GPIO_SSPI_MOSI)) {
epd->Begin(Pin(GPIO_SSPI_CS),Pin(GPIO_SSPI_MOSI),Pin(GPIO_SSPI_SCLK));
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("EPD: SoftSPI CS %d, CLK %d, MOSI %d"),Pin(GPIO_SSPI_CS), Pin(GPIO_SSPI_SCLK), Pin(GPIO_SSPI_MOSI));
} else {
free(buffer);
return;

View File

@ -65,15 +65,15 @@ void EpdInitDriver42()
epd42 = new Epd42(EPD_WIDTH42,EPD_HEIGHT42);
#ifdef USE_SPI
if ((pin[GPIO_SSPI_CS]<99) && (pin[GPIO_SSPI_MOSI]<99) && (pin[GPIO_SSPI_SCLK]<99)) {
epd42->Begin(pin[GPIO_SSPI_CS],pin[GPIO_SSPI_MOSI],pin[GPIO_SSPI_SCLK]);
if (PinUsed(GPIO_SSPI_CS) && PinUsed(GPIO_SSPI_MOSI) && PinUsed(GPIO_SSPI_SCLK)) {
epd42->Begin(Pin(GPIO_SSPI_CS),Pin(GPIO_SSPI_MOSI),Pin(GPIO_SSPI_SCLK));
} else {
free(buffer);
return;
}
#else
if ((pin[GPIO_SPI_CS]<99) && (pin[GPIO_SPI_MOSI]<99) && (pin[GPIO_SPI_CLK]<99)) {
epd42->Begin(pin[GPIO_SPI_CS],pin[GPIO_SPI_MOSI],pin[GPIO_SPI_CLK]);
if (PinUsed(GPIO_SPI_CS) && PinUsed(GPIO_SPI_MOSI) && PinUsed(GPIO_SPI_CLK)) {
epd42->Begin(Pin(GPIO_SPI_CS),Pin(GPIO_SPI_MOSI),Pin(GPIO_SPI_CLK));
} else {
free(buffer);
return;

View File

@ -80,16 +80,16 @@ void ILI9488_InitDriver()
bg_color = ILI9488_BLACK;
uint8_t bppin=BACKPLANE_PIN;
if (pin[GPIO_BACKLIGHT]<99) {
bppin=pin[GPIO_BACKLIGHT];
if (PinUsed(GPIO_BACKLIGHT)) {
bppin=Pin(GPIO_BACKLIGHT);
}
// init renderer
if ((pin[GPIO_SSPI_CS]<99) && (pin[GPIO_SSPI_MOSI]<99) && (pin[GPIO_SSPI_SCLK]<99)){
ili9488 = new ILI9488(pin[GPIO_SSPI_CS],pin[GPIO_SSPI_MOSI],pin[GPIO_SSPI_SCLK],bppin);
if (PinUsed(GPIO_SSPI_CS) && PinUsed(GPIO_SSPI_MOSI) && PinUsed(GPIO_SSPI_SCLK)) {
ili9488 = new ILI9488(Pin(GPIO_SSPI_CS),Pin(GPIO_SSPI_MOSI),Pin(GPIO_SSPI_SCLK),bppin);
} else {
if ((pin[GPIO_SPI_CS]<99) && (pin[GPIO_SPI_MOSI]<99) && (pin[GPIO_SPI_CLK]<99)) {
ili9488 = new ILI9488(pin[GPIO_SPI_CS],pin[GPIO_SPI_MOSI],pin[GPIO_SPI_CLK],bppin);
if (PinUsed(GPIO_SPI_CS) && PinUsed(GPIO_SPI_MOSI) && PinUsed(GPIO_SPI_CLK)) {
ili9488 = new ILI9488(Pin(GPIO_SPI_CS),Pin(GPIO_SPI_MOSI),Pin(GPIO_SPI_CLK),bppin);
} else {
return;
}

Some files were not shown because too many files have changed in this diff Show More