Merge pull request #8318 from gemu2015/esp32-webcam

Esp32 webcam
This commit is contained in:
Theo Arends 2020-05-02 10:26:22 +02:00 committed by GitHub
commit 7169925a4e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
52 changed files with 15050 additions and 80 deletions

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,6 +28,9 @@
#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};
@ -44,8 +47,8 @@ inline uint32_t pin2chan(uint32_t pin) {
inline void analogWrite(uint8_t pin, int val)
{
uint32_t channel=pin2chan(pin);
ledcWrite(channel,val);
Serial.printf("write %d - %d\n",channel,val);
ledcWrite(channel+PWM_CHANNEL_OFFSET,val);
//Serial.printf("write %d - %d\n",channel,val);
}
inline void analogWriteFreq(uint32_t freq)
@ -57,8 +60,8 @@ inline void analogWriteRange(uint32_t range)
inline void analogAttach(uint32_t pin, uint32_t channel) {
pwm_channel[channel&7]=pin;
ledcAttachPin(pin,channel);
Serial.printf("attach %d - %d\n",channel,pin);
ledcAttachPin(pin,channel+PWM_CHANNEL_OFFSET);
//Serial.printf("attach %d - %d\n",channel,pin);
}
inline uint32_t pow2(uint32_t x) {
@ -74,7 +77,7 @@ 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,freq,range);
ledcSetup(cnt+PWM_CHANNEL_OFFSET,freq,range);
}
}
Serial.printf("freq - range %d - %d\n",freq,range);

View File

@ -666,6 +666,27 @@
#define D_SENSOR_HRXL_RX "HRXL Rx"
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
#define D_SENSOR_AS3935 "AS3935"
#define D_GPIO_WEBCAM_PWDN_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

@ -666,6 +666,27 @@
#define D_SENSOR_HRXL_RX "HRXL Rx"
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
#define D_SENSOR_AS3935 "AS3935"
#define D_GPIO_WEBCAM_PWDN_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

@ -666,6 +666,27 @@
#define D_SENSOR_HRXL_RX "HRXL Rx"
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
#define D_SENSOR_AS3935 "AS3935"
#define D_GPIO_WEBCAM_PWDN_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

@ -666,6 +666,27 @@
#define D_SENSOR_HRXL_RX "HRXL Rx"
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
#define D_SENSOR_AS3935 "AS3935"
#define D_GPIO_WEBCAM_PWDN_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

@ -666,6 +666,27 @@
#define D_SENSOR_HRXL_RX "HRXL Rx"
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
#define D_SENSOR_AS3935 "AS3935"
#define D_GPIO_WEBCAM_PWDN_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

@ -666,6 +666,27 @@
#define D_SENSOR_HRXL_RX "HRXL Rx"
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
#define D_SENSOR_AS3935 "AS3935"
#define D_GPIO_WEBCAM_PWDN_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

@ -666,6 +666,27 @@
#define D_SENSOR_HRXL_RX "HRXL Rx"
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
#define D_SENSOR_AS3935 "AS3935"
#define D_GPIO_WEBCAM_PWDN_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

@ -666,6 +666,27 @@
#define D_SENSOR_HRXL_RX "HRXL Rx"
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
#define D_SENSOR_AS3935 "AS3935"
#define D_GPIO_WEBCAM_PWDN_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

@ -666,6 +666,27 @@
#define D_SENSOR_HRXL_RX "HRXL Rx"
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
#define D_SENSOR_AS3935 "AS3935"
#define D_GPIO_WEBCAM_PWDN_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

@ -666,6 +666,27 @@
#define D_SENSOR_HRXL_RX "HRXL - RX"
#define D_SENSOR_ELECTRIQ_MOODL "MOODL - TX"
#define D_SENSOR_AS3935 "AS3935"
#define D_GPIO_WEBCAM_PWDN_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

@ -666,6 +666,27 @@
#define D_SENSOR_HRXL_RX "HRXL Rx"
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
#define D_SENSOR_AS3935 "AS3935"
#define D_GPIO_WEBCAM_PWDN_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

@ -666,6 +666,27 @@
#define D_SENSOR_HRXL_RX "HRXL Rx"
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
#define D_SENSOR_AS3935 "AS3935"
#define D_GPIO_WEBCAM_PWDN_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

@ -666,6 +666,27 @@
#define D_SENSOR_HRXL_RX "HRXL Rx"
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
#define D_SENSOR_AS3935 "AS3935"
#define D_GPIO_WEBCAM_PWDN_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

@ -666,6 +666,27 @@
#define D_SENSOR_HRXL_RX "HRXL Rx"
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
#define D_SENSOR_AS3935 "AS3935"
#define D_GPIO_WEBCAM_PWDN_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

@ -666,6 +666,27 @@
#define D_SENSOR_HRXL_RX "HRXL Rx"
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
#define D_SENSOR_AS3935 "AS3935"
#define D_GPIO_WEBCAM_PWDN_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

@ -666,6 +666,27 @@
#define D_SENSOR_HRXL_RX "HRXL Rx"
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
#define D_SENSOR_AS3935 "AS3935"
#define D_GPIO_WEBCAM_PWDN_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

@ -666,6 +666,27 @@
#define D_SENSOR_HRXL_RX "HRXL Rx"
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
#define D_SENSOR_AS3935 "AS3935"
#define D_GPIO_WEBCAM_PWDN_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

@ -666,6 +666,27 @@
#define D_SENSOR_HRXL_RX "HRXL Rx"
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
#define D_SENSOR_AS3935 "AS3935"
#define D_GPIO_WEBCAM_PWDN_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

@ -666,6 +666,27 @@
#define D_SENSOR_HRXL_RX "HRXL Rx"
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
#define D_SENSOR_AS3935 "AS3935"
#define D_GPIO_WEBCAM_PWDN_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

@ -666,6 +666,27 @@
#define D_SENSOR_HRXL_RX "HRXL Rx"
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
#define D_SENSOR_AS3935 "AS3935"
#define D_GPIO_WEBCAM_PWDN_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

@ -666,6 +666,27 @@
#define D_SENSOR_HRXL_RX "HRXL Rx"
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
#define D_SENSOR_AS3935 "AS3935"
#define D_GPIO_WEBCAM_PWDN_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

@ -666,6 +666,27 @@
#define D_SENSOR_HRXL_RX "HRXL Rx"
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
#define D_SENSOR_AS3935 "AS3935"
#define D_GPIO_WEBCAM_PWDN_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

@ -666,6 +666,27 @@
#define D_SENSOR_HRXL_RX "HRXL Rx"
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
#define D_SENSOR_AS3935 "AS3935"
#define D_GPIO_WEBCAM_PWDN_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

@ -197,6 +197,28 @@ enum UserSelectablePins {
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 {
@ -287,6 +309,27 @@ const char kSensorNames[] PROGMEM =
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 =
@ -589,6 +632,29 @@ const uint16_t kGpioNiceList[] PROGMEM = {
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
};
//********************************************************************************************

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,6 +1663,13 @@ chknext:
}
if (!strncmp(vname,"pn[",3)) {
GetNumericResult(vname+3,OPER_EQU,&fvar,0);
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
@ -1790,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;
@ -1902,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;
@ -2722,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;
@ -2763,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)) {
@ -3274,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 =
@ -3297,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;
@ -3311,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;
}
@ -3320,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) {
@ -3334,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();
@ -3429,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);
@ -3449,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;
@ -3518,6 +3720,7 @@ void HandleScriptTextareaConfiguration(void) {
}
}
void HandleScriptConfiguration(void) {
if (!HttpCheckPriviledgedAccess()) { return; }
@ -3619,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
@ -4278,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.
@ -4292,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;
@ -4313,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;
@ -4557,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];
@ -4584,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)
@ -4749,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++;
@ -4765,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];
@ -4796,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++;
@ -4807,7 +5022,8 @@ uint8_t msect=Run_Scripter(">m",-2,0);
}
}
} else {
client->println("*");
//client->println("*");
func((char*)"*");
}
}
#endif
@ -4868,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;
@ -4915,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();
}
@ -4934,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;
}
@ -5001,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);
@ -5028,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

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