mirror of
https://github.com/letscontrolit/ESPEasy.git
synced 2026-07-27 19:57:38 +00:00
[P089] Add support for ESP32
This commit is contained in:
@@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
@@ -0,0 +1,41 @@
|
||||
# ESPping
|
||||
Let the ESP32/ESP8266 ping a remote machine.
|
||||
|
||||
With this library an ESP32/ESP8266 can ping a remote machine and know if it's reachable.
|
||||
It provide some basic measurements on ping messages (avg response time).
|
||||
|
||||
thanks to Daniele Colanardi and Marian Craciunescu
|
||||
|
||||
## Usage
|
||||
|
||||
First, include the library in your sketch along with WiFi library:
|
||||
|
||||
```Arduino
|
||||
#include <ESPping.h>
|
||||
```
|
||||
|
||||
Next, simply call the `Ping.ping()` function
|
||||
|
||||
```Arduino
|
||||
IPAddress ip (192, 168, 0, 1); // The remote ip to ping
|
||||
bool ret = Ping.ping(ip);
|
||||
```
|
||||
|
||||
`ret` will be true if the remote responded to pings, false if not reachable.
|
||||
The library supports hostname too, just pass a string instead of the ip address:
|
||||
|
||||
```Arduino
|
||||
bool ret = Ping.ping("www.google.com");
|
||||
```
|
||||
|
||||
Additionally, the function accept a second integer parameter `count` that specify how many pings has to be sent:
|
||||
|
||||
```Arduino
|
||||
bool ret = Ping.ping(ip_or_host, 10);
|
||||
```
|
||||
|
||||
After `Ping.ping()` has been called, the average response time (in milliseconds) can be retrieved with
|
||||
|
||||
```Arduino
|
||||
float avg_time_ms = Ping.averageTime();
|
||||
```
|
||||
@@ -0,0 +1,61 @@
|
||||
/******************************************************
|
||||
test Ping
|
||||
******************************************************/
|
||||
|
||||
#include <ESPping.h>
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
delay(100);
|
||||
|
||||
WiFi.begin("ssid","password");
|
||||
|
||||
// attente connexion
|
||||
Serial.print("\nConnection");
|
||||
while (WiFi.status() != WL_CONNECTED)
|
||||
{
|
||||
delay(500);
|
||||
Serial.print(".");
|
||||
}
|
||||
Serial.print("\nConnection OK, IP: ");
|
||||
Serial.print(WiFi.localIP());
|
||||
Serial.print(" Gateway: ");
|
||||
Serial.println(WiFi.gatewayIP());
|
||||
Serial.println("You can try to ping me ;-)");
|
||||
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
|
||||
// Ping IP
|
||||
const IPAddress remote_ip(9,9,9,9);
|
||||
Serial.print(remote_ip);
|
||||
if (Ping.ping(remote_ip) > 0){
|
||||
Serial.printf(" response time : %d/%.2f/%d ms\n", Ping.minTime(), Ping.averageTime(), Ping.maxTime());
|
||||
} else {
|
||||
Serial.println(" Error !");
|
||||
}
|
||||
delay(1000);
|
||||
|
||||
// Ping Host
|
||||
const char* remote_host = "quad9.net";
|
||||
Serial.print(remote_host);
|
||||
if (Ping.ping(remote_host) > 0){
|
||||
Serial.printf(" response time : %d/%.2f/%d ms\n", Ping.minTime(), Ping.averageTime(), Ping.maxTime());
|
||||
} else {
|
||||
Serial.println(" Ping Error !");
|
||||
}
|
||||
delay(1000);
|
||||
|
||||
// Ping local IP
|
||||
Serial.print(WiFi.gatewayIP());
|
||||
if (Ping.ping(WiFi.gatewayIP()) > 0){
|
||||
Serial.printf(" response time : %d/%.2f/%d ms\n", Ping.minTime(), Ping.averageTime(), Ping.maxTime());
|
||||
} else {
|
||||
Serial.println(" Ping Error !");
|
||||
}
|
||||
delay(1000);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
#######################################
|
||||
# Syntax Coloring Map For ESPping
|
||||
#######################################
|
||||
|
||||
#######################################
|
||||
# Library (KEYWORD3)
|
||||
#######################################
|
||||
|
||||
ESPping KEYWORD3
|
||||
|
||||
#######################################
|
||||
# Class (KEYWORD1)
|
||||
#######################################
|
||||
|
||||
Ping KEYWORD1
|
||||
|
||||
#######################################
|
||||
# Methods and Functions (KEYWORD2)
|
||||
#######################################
|
||||
|
||||
ping KEYWORD2
|
||||
minTime KEYWORD2
|
||||
averageTime KEYWORD2
|
||||
maxTime KEYWORD2
|
||||
|
||||
#######################################
|
||||
# Constants (LITERAL1)
|
||||
#######################################
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
name=ESPping
|
||||
version=1.0.5
|
||||
author=dvarrel, Daniele Colanardi, Marian Craciunescu
|
||||
maintainer=dvarrel
|
||||
sentence=Let the ESP32/ESP8266 ping a remote machine.
|
||||
paragraph=With this library an ESP32/ESP8266 can ping a remote machine and know if reachable. It provide some basic measurements on ping messages (avg response time).
|
||||
category=Communication
|
||||
url=https://github.com/dvarrel/ESPping.git
|
||||
architectures=esp8266,esp32
|
||||
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
ESP8266Ping - Ping library for ESP8266
|
||||
Copyright (c) 2015 Daniele Colanardi. All rights reserved.
|
||||
|
||||
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
|
||||
*/
|
||||
#include "ESPping.h"
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef ESP8266
|
||||
extern "C" void esp_schedule();
|
||||
extern "C" void esp_yield();
|
||||
#endif
|
||||
#ifdef ESP32
|
||||
extern "C" void esp_schedule(void) {};
|
||||
extern "C" void esp_yield(void) {};
|
||||
#endif
|
||||
|
||||
PingClass::PingClass() {}
|
||||
|
||||
bool PingClass::ping(IPAddress dest, int16_t count) {
|
||||
_expected_count = count;
|
||||
_errors = 0;
|
||||
_success = 0;
|
||||
|
||||
_min_time = INT_MAX;
|
||||
_avg_time = 0.0f;
|
||||
_max_time = 0;
|
||||
|
||||
|
||||
memset(&_options, 0, sizeof(struct ping_option));
|
||||
|
||||
// Repeat count (how many time send a ping message to destination)
|
||||
_options.count = count;
|
||||
// Time interval between two ping (seconds??)
|
||||
_options.coarse_time = 1;
|
||||
// Destination machine
|
||||
_options.ip = dest;
|
||||
|
||||
// Callbacks
|
||||
_options.recv_function = reinterpret_cast<ping_recv_function>(&PingClass::_ping_recv_cb);
|
||||
_options.sent_function = NULL; //reinterpret_cast<ping_sent_function>(&_ping_sent_cb);
|
||||
|
||||
// Let's go!
|
||||
if(ping_start(&_options)) {
|
||||
#ifdef ESP8266
|
||||
//wait until finished
|
||||
while((_success + _errors) < _expected_count){
|
||||
delay(1);
|
||||
esp_yield();
|
||||
};
|
||||
#else
|
||||
// Suspend till the process end
|
||||
esp_yield();
|
||||
#endif
|
||||
}
|
||||
return (_success > 0);
|
||||
}
|
||||
|
||||
bool PingClass::ping(const char* host, int16_t count) {
|
||||
IPAddress remote_addr;
|
||||
|
||||
if (WiFi.hostByName(host, remote_addr))
|
||||
return ping(remote_addr, count);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
float PingClass::averageTime() {
|
||||
return _avg_time;
|
||||
}
|
||||
|
||||
float PingClass::minTime() {
|
||||
return _min_time;
|
||||
}
|
||||
|
||||
float PingClass::maxTime() {
|
||||
return _max_time;
|
||||
}
|
||||
|
||||
void PingClass::_ping_recv_cb(void *opt, void *resp) {
|
||||
// Cast the parameters to get some usable info
|
||||
ping_resp* ping_resp = reinterpret_cast<struct ping_resp*>(resp);
|
||||
//ping_option* ping_opt = reinterpret_cast<struct ping_option*>(opt);
|
||||
|
||||
// Error or success?
|
||||
#ifdef ESP8266
|
||||
if (ping_resp->ping_err == -1)
|
||||
_errors++;
|
||||
else {
|
||||
_success++;
|
||||
_avg_time += ping_resp->resp_time;
|
||||
if(ping_resp->resp_time < _min_time)
|
||||
_min_time = ping_resp->resp_time;
|
||||
if(ping_resp->resp_time > _max_time)
|
||||
_max_time = ping_resp->resp_time;
|
||||
|
||||
}
|
||||
#else
|
||||
_errors = ping_resp->ping_err;
|
||||
_success = _expected_count - _errors;
|
||||
_avg_time = ping_resp->resp_time;
|
||||
#endif
|
||||
|
||||
// Some debug info
|
||||
DEBUG_PING(
|
||||
"DEBUG: ping reply"
|
||||
"\ttotal_count = %d"
|
||||
"\tresp_time = %d"
|
||||
"\tseqno = %d"
|
||||
"\ttimeout_count = %d"
|
||||
"\tbytes = %d"
|
||||
"\ttotal_bytes = %d"
|
||||
"\ttotal_time = %d"
|
||||
"\tping_err = %d \n",
|
||||
(int)ping_resp->total_count, (int)ping_resp->resp_time, (int)ping_resp->seqno,
|
||||
(int)ping_resp->timeout_count, (int)ping_resp->bytes, (int)ping_resp->total_bytes,
|
||||
(int)ping_resp->total_time, (int)ping_resp->ping_err
|
||||
);
|
||||
|
||||
// Is it time to end?
|
||||
// Don't using seqno because it does not increase on error
|
||||
#ifdef ESP8266
|
||||
if (_success + _errors == _expected_count ) {
|
||||
_avg_time = _success > 0 ? _avg_time / _success : 0;
|
||||
#else
|
||||
if (ping_resp->total_count== _expected_count) {
|
||||
|
||||
#endif
|
||||
|
||||
DEBUG_PING("success %d errors %d\n", _success, _errors);
|
||||
DEBUG_PING("Resp times min %d, avg %.2f, max %d ms\n", _min_time, _avg_time, _max_time);
|
||||
|
||||
#ifdef ESP32
|
||||
// Done, return to main functiom
|
||||
esp_schedule();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
byte PingClass::_expected_count = 0;
|
||||
byte PingClass::_errors = 0;
|
||||
byte PingClass::_success = 0;
|
||||
float PingClass::_avg_time = 0;
|
||||
float PingClass::_min_time = std::numeric_limits<float>::max();
|
||||
float PingClass::_max_time = 0;
|
||||
|
||||
PingClass Ping;
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
ESP32Ping - Ping library for ESP32 or ESP8266
|
||||
Copyright (c) 2018 Marian Craciunescu. All rights reserved.
|
||||
|
||||
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 ESPping_H
|
||||
#define ESPping_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <Arduino.h>
|
||||
#ifdef ESP32
|
||||
#include <WiFi.h>
|
||||
#include <ping32.h>
|
||||
extern "C" {
|
||||
void esp_schedule(void);
|
||||
void esp_yield(void);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ESP8266
|
||||
#include <ESP8266WiFi.h>
|
||||
extern "C" {
|
||||
#include <ping.h>
|
||||
}
|
||||
#endif
|
||||
|
||||
//#define ENABLE_DEBUG_PING 0
|
||||
#ifdef ENABLE_DEBUG_PING
|
||||
#define DEBUG_PING(...) Serial.printf(__VA_ARGS__)
|
||||
#else
|
||||
#define DEBUG_PING(...)
|
||||
#endif
|
||||
|
||||
class PingClass {
|
||||
public:
|
||||
PingClass();
|
||||
|
||||
bool ping(IPAddress dest, int16_t count = 5);
|
||||
bool ping(const char* host, int16_t count = 5);
|
||||
|
||||
float averageTime();
|
||||
float minTime();
|
||||
float maxTime();
|
||||
|
||||
protected:
|
||||
static void _ping_sent_cb(void *opt, void *pdata);
|
||||
static void _ping_recv_cb(void *opt, void *pdata);
|
||||
|
||||
IPAddress _dest;
|
||||
ping_option _options;
|
||||
|
||||
static byte _expected_count, _errors, _success;
|
||||
static float _min_time, _max_time;
|
||||
static float _avg_time;
|
||||
};
|
||||
|
||||
extern PingClass Ping;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,384 @@
|
||||
/*
|
||||
* ESP32 Ping library
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software
|
||||
* and its documentation for any purpose and without fee is hereby
|
||||
* granted, provided that the above copyright notice appear in all
|
||||
* copies and that both that the copyright notice and this
|
||||
* permission notice and warranty disclaimer appear in supporting
|
||||
* documentation, and that the name of the author not be used in
|
||||
* advertising or publicity pertaining to distribution of the
|
||||
* software without specific, written prior permission.
|
||||
*
|
||||
* The author disclaim all warranties with regard to this
|
||||
* software, including all implied warranties of merchantability
|
||||
* and fitness. In no event shall the author be liable for any
|
||||
* special, indirect or consequential damages or any damages
|
||||
* whatsoever resulting from loss of use, data or profits, whether
|
||||
* in an action of contract, negligence or other tortious action,
|
||||
* arising out of or in connection with the use or performance of
|
||||
* this software.
|
||||
*
|
||||
* --------------------------------------------------------------------------------
|
||||
* Ping Library is based on the following source code:
|
||||
*
|
||||
* Lua RTOS, ping utility
|
||||
*
|
||||
*
|
||||
* Author: Jaume Oliv� (jolive@iberoxarxa.com / jolive@whitecatboard.org)
|
||||
*
|
||||
* --------------------------------------------------------------------------------
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
*/
|
||||
#ifdef ESP32
|
||||
#include <Arduino.h>
|
||||
|
||||
#include <math.h>
|
||||
#include <float.h>
|
||||
#include <signal.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "ping32.h"
|
||||
|
||||
#include "lwip/inet_chksum.h"
|
||||
#include "lwip/ip.h"
|
||||
#include "lwip/ip4.h"
|
||||
#include "lwip/err.h"
|
||||
#include "lwip/icmp.h"
|
||||
#include "lwip/sockets.h"
|
||||
#include "lwip/sys.h"
|
||||
#include "lwip/netdb.h"
|
||||
#include "lwip/dns.h"
|
||||
|
||||
static uint16_t ping_seq_num;
|
||||
static uint8_t stopped = 0;
|
||||
|
||||
/*
|
||||
* Statistics
|
||||
*/
|
||||
static uint32_t transmitted = 0;
|
||||
static uint32_t received = 0;
|
||||
static float min_time = 0;
|
||||
static float max_time = 0;
|
||||
static float mean_time = 0;
|
||||
static float last_mean_time = 0;
|
||||
static float var_time = 0;
|
||||
|
||||
#define PING_ID 0xAFAF
|
||||
|
||||
#ifndef PING_DEFAULT_COUNT
|
||||
#define PING_DEFAULT_COUNT 10
|
||||
#endif
|
||||
#ifndef PING_DEFAULT_INTERVAL
|
||||
#define PING_DEFAULT_INTERVAL 1
|
||||
#endif
|
||||
#ifndef PING_DEFAULT_SIZE
|
||||
#define PING_DEFAULT_SIZE 32
|
||||
#endif
|
||||
#ifndef PING_DEFAULT_TIMEOUT
|
||||
#define PING_DEFAULT_TIMEOUT 1
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Helper functions
|
||||
*
|
||||
*/
|
||||
static void ping_prepare_echo(struct icmp_echo_hdr *iecho, uint16_t len) {
|
||||
size_t i;
|
||||
size_t data_len = len - sizeof(struct icmp_echo_hdr);
|
||||
|
||||
ICMPH_TYPE_SET(iecho, ICMP_ECHO);
|
||||
ICMPH_CODE_SET(iecho, 0);
|
||||
iecho->chksum = 0;
|
||||
iecho->id = PING_ID;
|
||||
iecho->seqno = htons(++ping_seq_num);
|
||||
|
||||
/* fill the additional data buffer with some data */
|
||||
for (i = 0; i < data_len; i++) {
|
||||
((char*)iecho)[sizeof(struct icmp_echo_hdr) + i] = (char)i;
|
||||
}
|
||||
|
||||
iecho->chksum = inet_chksum(iecho, len);
|
||||
}
|
||||
|
||||
static err_t ping_send(int s, ip4_addr_t *addr, int size) {
|
||||
struct icmp_echo_hdr *iecho;
|
||||
struct sockaddr_in to;
|
||||
size_t ping_size = sizeof(struct icmp_echo_hdr) + size;
|
||||
int err;
|
||||
|
||||
iecho = (struct icmp_echo_hdr *)mem_malloc((mem_size_t)ping_size);
|
||||
if (!iecho) {
|
||||
mem_free(iecho);
|
||||
return ERR_MEM;
|
||||
}
|
||||
|
||||
ping_prepare_echo(iecho, (uint16_t)ping_size);
|
||||
|
||||
to.sin_len = sizeof(to);
|
||||
to.sin_family = AF_INET;
|
||||
inet_addr_from_ip4addr(&to.sin_addr, addr);
|
||||
|
||||
if ((err = sendto(s, iecho, ping_size, 0, (struct sockaddr*)&to, sizeof(to)))) {
|
||||
transmitted++;
|
||||
}
|
||||
mem_free(iecho);
|
||||
return (err ? ERR_OK : ERR_VAL);
|
||||
}
|
||||
|
||||
static void ping_recv(int s) {
|
||||
char buf[64];
|
||||
int fromlen, len;
|
||||
struct sockaddr_in from;
|
||||
struct ip_hdr *iphdr;
|
||||
struct icmp_echo_hdr *iecho = NULL;
|
||||
char ipa[16];
|
||||
struct timeval begin;
|
||||
struct timeval end;
|
||||
uint64_t micros_begin;
|
||||
uint64_t micros_end;
|
||||
float elapsed;
|
||||
|
||||
// Register begin time
|
||||
gettimeofday(&begin, NULL);
|
||||
|
||||
// Send
|
||||
while ((len = recvfrom(s, buf, sizeof(buf), 0, (struct sockaddr*)&from, (socklen_t*)&fromlen)) > 0) {
|
||||
if (len >= (int)(sizeof(struct ip_hdr) + sizeof(struct icmp_echo_hdr))) {
|
||||
// Register end time
|
||||
gettimeofday(&end, NULL);
|
||||
|
||||
/// Get from IP address
|
||||
ip4_addr_t fromaddr;
|
||||
inet_addr_to_ip4addr(&fromaddr, &from.sin_addr);
|
||||
|
||||
strcpy(ipa, inet_ntoa(fromaddr));
|
||||
|
||||
// Get echo
|
||||
iphdr = (struct ip_hdr *)buf;
|
||||
iecho = (struct icmp_echo_hdr *)(buf + (IPH_HL(iphdr) * 4));
|
||||
|
||||
// Print ....
|
||||
if ((iecho->id == PING_ID) && (iecho->seqno == htons(ping_seq_num))) {
|
||||
received++;
|
||||
|
||||
// Get elapsed time in milliseconds
|
||||
micros_begin = begin.tv_sec * 1000000;
|
||||
micros_begin += begin.tv_usec;
|
||||
|
||||
micros_end = end.tv_sec * 1000000;
|
||||
micros_end += end.tv_usec;
|
||||
|
||||
elapsed = (float)(micros_end - micros_begin) / (float)1000.0;
|
||||
|
||||
// Update statistics
|
||||
// Mean and variance are computed in an incremental way
|
||||
if (elapsed < min_time) {
|
||||
min_time = elapsed;
|
||||
}
|
||||
|
||||
if (elapsed > max_time) {
|
||||
max_time = elapsed;
|
||||
}
|
||||
|
||||
last_mean_time = mean_time;
|
||||
mean_time = (((received - 1) * mean_time) + elapsed) / received;
|
||||
|
||||
if (received > 1) {
|
||||
var_time = var_time + ((elapsed - last_mean_time) * (elapsed - mean_time));
|
||||
}
|
||||
|
||||
// Print ...
|
||||
log_d("%d bytes from %s: icmp_seq=%d time=%.3f ms", len, ipa,
|
||||
ntohs(iecho->seqno), elapsed
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
else {
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (len < 0) {
|
||||
log_d("Request timeout for icmp_seq %d", ping_seq_num);
|
||||
}
|
||||
}
|
||||
/*
|
||||
static void stop_action(int i) {
|
||||
signal(i, SIG_DFL);
|
||||
|
||||
stopped = 1;
|
||||
}
|
||||
*/
|
||||
/*
|
||||
* Operation functions
|
||||
*
|
||||
*/
|
||||
void ping(const char *name, int16_t count, int interval, int size, int timeout) {
|
||||
// Resolve name
|
||||
hostent * target = gethostbyname(name);
|
||||
IPAddress adr = *target->h_addr_list[0];
|
||||
if (target->h_length == 0) {
|
||||
// TODO: error not found target?????
|
||||
return;
|
||||
}
|
||||
ping_start(adr, count, interval, size, timeout);
|
||||
}
|
||||
|
||||
bool ping_start(struct ping_option *ping_o) {
|
||||
|
||||
|
||||
return ping_start(ping_o->ip,ping_o->count,0,0,0,ping_o);
|
||||
|
||||
}
|
||||
bool ping_start(IPAddress adr, int16_t count=0, int interval=0, int size=0, int timeout=0, struct ping_option *ping_o) {
|
||||
// driver_error_t *error;
|
||||
struct sockaddr_in address;
|
||||
ip4_addr_t ping_target;
|
||||
int s;
|
||||
// Get default values if argument are not provided
|
||||
if (count == 0) {
|
||||
count = PING_DEFAULT_COUNT;
|
||||
}
|
||||
|
||||
if (interval == 0) {
|
||||
interval = PING_DEFAULT_INTERVAL;
|
||||
}
|
||||
|
||||
if (size == 0) {
|
||||
size = PING_DEFAULT_SIZE;
|
||||
}
|
||||
|
||||
if (timeout == 0) {
|
||||
timeout = PING_DEFAULT_TIMEOUT;
|
||||
}
|
||||
|
||||
// Create socket
|
||||
if ((s = socket(AF_INET, SOCK_RAW, IP_PROTO_ICMP)) < 0) {
|
||||
// TODO: error
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
address.sin_addr.s_addr = adr;
|
||||
ping_target.addr = address.sin_addr.s_addr;
|
||||
|
||||
// Setup socket
|
||||
struct timeval tout;
|
||||
|
||||
// Timeout
|
||||
tout.tv_sec = timeout;
|
||||
tout.tv_usec = 0;
|
||||
|
||||
if (setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &tout, sizeof(tout)) < 0) {
|
||||
closesocket(s);
|
||||
// TODO: error
|
||||
return false;
|
||||
}
|
||||
|
||||
stopped = 0;
|
||||
transmitted = 0;
|
||||
received = 0;
|
||||
min_time = 1.E+9;// FLT_MAX;
|
||||
max_time = 0.0;
|
||||
mean_time = 0.0;
|
||||
var_time = 0.0;
|
||||
|
||||
// Register signal for stop ping
|
||||
//signal(SIGINT, stop_action);
|
||||
|
||||
// Begin ping ...
|
||||
char ipa[16];
|
||||
|
||||
strcpy(ipa, inet_ntoa(ping_target));
|
||||
log_i("PING %s: %d data bytes", ipa, size);
|
||||
|
||||
ping_seq_num = 0;
|
||||
|
||||
unsigned long ping_started_time = millis();
|
||||
while ((ping_seq_num < count) && (!stopped)) {
|
||||
if (ping_send(s, &ping_target, size) == ERR_OK) {
|
||||
ping_recv(s);
|
||||
}
|
||||
if(ping_seq_num < count){
|
||||
delay( interval*1000L);
|
||||
}
|
||||
}
|
||||
|
||||
closesocket(s);
|
||||
|
||||
log_i("%d packets transmitted, %d packets received, %.1f%% packet loss",
|
||||
transmitted,
|
||||
received,
|
||||
((((float)transmitted - (float)received) / (float)transmitted) * 100.0)
|
||||
);
|
||||
|
||||
|
||||
if (ping_o) {
|
||||
ping_resp pingresp;
|
||||
log_i("round-trip min/avg/max/stddev = %.3f/%.3f/%.3f/%.3f ms", min_time, mean_time, max_time, sqrt(var_time / received));
|
||||
pingresp.total_count = count; //Number of pings
|
||||
pingresp.resp_time = mean_time; //Average time for the pings
|
||||
pingresp.seqno = 0; //not relevant
|
||||
pingresp.timeout_count = transmitted - received; //number of pings which failed
|
||||
pingresp.bytes = size; //number of bytes received for 1 ping
|
||||
pingresp.total_bytes = size * count; //number of bytes for all pings
|
||||
pingresp.total_time = (millis() - ping_started_time) / 1000.0; //Time consumed for all pings; it takes into account also timeout pings
|
||||
pingresp.ping_err = transmitted - received; //number of pings failed
|
||||
// Call the callback function
|
||||
ping_o->recv_function(ping_o, &pingresp);
|
||||
}
|
||||
|
||||
// Return true if at least one ping had a successfull "pong"
|
||||
return (received > 0);
|
||||
}
|
||||
|
||||
bool ping_regist_recv(struct ping_option *ping_opt, ping_recv_function ping_recv)
|
||||
{
|
||||
if (ping_opt == NULL)
|
||||
return false;
|
||||
|
||||
ping_opt->recv_function = ping_recv;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ping_regist_sent(struct ping_option *ping_opt, ping_sent_function ping_sent)
|
||||
{
|
||||
if (ping_opt == NULL)
|
||||
return false;
|
||||
|
||||
ping_opt->sent_function = ping_sent;
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,37 @@
|
||||
#ifdef ESP32
|
||||
|
||||
#ifndef PING32_H
|
||||
#define PING32_H
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <stdint.h>
|
||||
|
||||
typedef void(*ping_recv_function)(void* arg, void *pdata);
|
||||
typedef void(*ping_sent_function)(void* arg, void *pdata);
|
||||
|
||||
struct ping_option {
|
||||
int16_t count;
|
||||
uint32_t ip;
|
||||
uint32_t coarse_time;
|
||||
ping_recv_function recv_function;
|
||||
ping_sent_function sent_function;
|
||||
void* reverse;
|
||||
};
|
||||
|
||||
struct ping_resp {
|
||||
uint32_t total_count;
|
||||
float resp_time;
|
||||
uint32_t seqno;
|
||||
uint32_t timeout_count;
|
||||
uint32_t bytes;
|
||||
uint32_t total_bytes;
|
||||
float total_time;
|
||||
int8_t ping_err;
|
||||
};
|
||||
|
||||
bool ping_start(struct ping_option *ping_opt);
|
||||
void ping(const char *name, int16_t count, int interval, int size, int timeout);
|
||||
bool ping_start(IPAddress adr, int16_t count, int interval, int size, int timeout, struct ping_option *ping_o = NULL);
|
||||
|
||||
#endif
|
||||
#endif // PING_H
|
||||
+53
-4
@@ -1,5 +1,5 @@
|
||||
#include "_Plugin_Helper.h"
|
||||
#if defined(USES_P089) && defined(ESP8266)
|
||||
#ifdef USES_P089
|
||||
|
||||
# include "src/PluginStructs/P089_data_struct.h"
|
||||
|
||||
@@ -19,6 +19,8 @@
|
||||
Maintainer: Denys Fedoryshchenko, denys AT nuclearcat.com
|
||||
*/
|
||||
/** Changelog:
|
||||
* 2025-08-14 tonhuisman: Add code to plugin to use dvarrel/ESPping library that works for ESP32.
|
||||
* ESP32 handles the ping in an independent RTOS task, to make it non-blocking.
|
||||
* 2025-01-12 tonhuisman: Add support for MQTT AutoDiscovery (not supported for Ping)
|
||||
* 2023-03-19 tonhuisman: Show hostname in GPIO column of Devices page
|
||||
* 2023-03-14 tonhuisman: Change command handling to not require the taskname as the second argument if no 3rd argument is given.
|
||||
@@ -30,6 +32,7 @@
|
||||
# define PLUGIN_089
|
||||
# define PLUGIN_NAME_089 "Communication - Ping"
|
||||
# define PLUGIN_VALUENAME1_089 "Fails"
|
||||
# define PLUGIN_VALUENAME2_089 "Avg_ms"
|
||||
|
||||
|
||||
boolean Plugin_089(uint8_t function, struct EventStruct *event, String& string)
|
||||
@@ -60,14 +63,34 @@ boolean Plugin_089(uint8_t function, struct EventStruct *event, String& string)
|
||||
case PLUGIN_GET_DEVICEVALUENAMES:
|
||||
{
|
||||
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_089));
|
||||
# ifdef ESP32
|
||||
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[1], PSTR(PLUGIN_VALUENAME2_089));
|
||||
# endif // ifdef ESP32
|
||||
break;
|
||||
}
|
||||
|
||||
# ifdef ESP32
|
||||
case PLUGIN_GET_DEVICEVALUECOUNT:
|
||||
{
|
||||
int vCount = P089_VALUE_COUNT;
|
||||
|
||||
if (0 == vCount) {
|
||||
vCount = 1;
|
||||
}
|
||||
event->Par1 = vCount;
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
# endif // ifdef ESP32
|
||||
|
||||
# if FEATURE_MQTT_DISCOVER
|
||||
case PLUGIN_GET_DISCOVERY_VTYPES:
|
||||
{
|
||||
event->Par1 = static_cast<int>(Sensor_VType::SENSOR_TYPE_NONE); // Not yet supported
|
||||
success = true;
|
||||
# ifdef ESP32
|
||||
event->Par2 = static_cast<int>(Sensor_VType::SENSOR_TYPE_DURATION);
|
||||
# endif // ifdef ESP32
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
# endif // if FEATURE_MQTT_DISCOVER
|
||||
@@ -92,12 +115,35 @@ boolean Plugin_089(uint8_t function, struct EventStruct *event, String& string)
|
||||
char hostname[PLUGIN_089_HOSTNAME_SIZE]{};
|
||||
LoadCustomTaskSettings(event->TaskIndex, (uint8_t *)&hostname, PLUGIN_089_HOSTNAME_SIZE);
|
||||
addFormTextBox(F("Hostname"), F("host"), hostname, PLUGIN_089_HOSTNAME_SIZE - 2);
|
||||
|
||||
# ifdef ESP32
|
||||
|
||||
if (P089_PING_COUNT < 1) {
|
||||
P089_PING_COUNT = 5;
|
||||
}
|
||||
addFormNumericBox(F("Ping count"), F("pcount"), P089_PING_COUNT, 1, 100);
|
||||
|
||||
const __FlashStringHelper*countOptions[] = {
|
||||
F("Fails"),
|
||||
F("Fails, Avg_ms"),
|
||||
};
|
||||
const int countValues[] = { 1, 2 };
|
||||
FormSelectorOptions selector(2, countOptions, countValues);
|
||||
selector.reloadonchange = true;
|
||||
selector.addFormSelector(F("Available Values"), F("pvals"), P089_VALUE_COUNT);
|
||||
# endif // ifdef ESP32
|
||||
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_WEBFORM_SAVE:
|
||||
{
|
||||
# ifdef ESP32
|
||||
P089_PING_COUNT = getFormItemInt(F("pcount"), 5);
|
||||
P089_VALUE_COUNT = getFormItemInt(F("pvals"), 1);
|
||||
# endif // ifdef ESP32
|
||||
|
||||
char hostname[PLUGIN_089_HOSTNAME_SIZE]{};
|
||||
|
||||
// Reset "Fails" if settings updated
|
||||
@@ -112,6 +158,9 @@ boolean Plugin_089(uint8_t function, struct EventStruct *event, String& string)
|
||||
{
|
||||
success = initPluginTaskData(event->TaskIndex, new (std::nothrow) P089_data_struct());
|
||||
UserVar.setFloat(event->TaskIndex, 0, 0);
|
||||
# ifdef ESP32
|
||||
UserVar.setFloat(event->TaskIndex, 1, 0);
|
||||
# endif // ifdef ESP32
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -120,7 +169,7 @@ boolean Plugin_089(uint8_t function, struct EventStruct *event, String& string)
|
||||
P089_data_struct *P089_taskdata =
|
||||
static_cast<P089_data_struct *>(getPluginTaskData(event->TaskIndex));
|
||||
|
||||
if (nullptr == P089_taskdata) {
|
||||
if ((nullptr == P089_taskdata) || !P089_taskdata->isInitialized()) {
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -165,4 +214,4 @@ boolean Plugin_089(uint8_t function, struct EventStruct *event, String& string)
|
||||
return success;
|
||||
}
|
||||
|
||||
#endif // if defined(USES_P089) && defined(ESP8266)
|
||||
#endif // ifdef USES_P089
|
||||
|
||||
@@ -1753,6 +1753,9 @@ To create/register a plugin, you have to :
|
||||
#ifndef USES_P085
|
||||
#define USES_P085 // AcuDC24x
|
||||
#endif
|
||||
#ifndef USES_P089
|
||||
#define USES_P089 // Ping
|
||||
#endif
|
||||
#ifndef USES_P093
|
||||
#define USES_P093 // Mitsubishi Heat Pump
|
||||
#endif
|
||||
@@ -1977,6 +1980,9 @@ To create/register a plugin, you have to :
|
||||
#ifndef USES_P083
|
||||
#define USES_P083 // SGP30
|
||||
#endif
|
||||
#ifndef USES_P089
|
||||
#define USES_P089 // Ping
|
||||
#endif
|
||||
#ifndef USES_P090
|
||||
#define USES_P090 // CCS811
|
||||
#endif
|
||||
@@ -2094,6 +2100,9 @@ To create/register a plugin, you have to :
|
||||
#ifndef USES_P070
|
||||
#define USES_P070 // NeoPixel_Clock
|
||||
#endif
|
||||
#ifndef USES_P089
|
||||
#define USES_P089 // Ping
|
||||
#endif
|
||||
#ifndef USES_P128
|
||||
#define USES_P128 // NeoPixelBusFX
|
||||
#endif
|
||||
@@ -2326,6 +2335,9 @@ To create/register a plugin, you have to :
|
||||
#ifndef USES_P088
|
||||
#define USES_P088 // ToniA IR plugin
|
||||
#endif
|
||||
#ifndef USES_P089
|
||||
#define USES_P089 // Ping
|
||||
#endif
|
||||
#ifndef USES_P094
|
||||
#define USES_P094 // CUL Reader
|
||||
#endif
|
||||
|
||||
@@ -371,11 +371,7 @@ constexpr /*pluginID_t*/ uint8_t DeviceIndex_to_Plugin_id[] PROGMEM =
|
||||
#endif // ifdef USES_P088
|
||||
|
||||
#ifdef USES_P089
|
||||
# ifdef ESP8266
|
||||
|
||||
// FIXME TD-er: Support Ping plugin for ESP32
|
||||
89,
|
||||
# endif // ifdef ESP8266
|
||||
#endif // ifdef USES_P089
|
||||
|
||||
#ifdef USES_P090
|
||||
@@ -1404,11 +1400,7 @@ constexpr const Plugin_ptr_t PROGMEM Plugin_ptr[] =
|
||||
#endif // ifdef USES_P088
|
||||
|
||||
#ifdef USES_P089
|
||||
# ifdef ESP8266
|
||||
|
||||
// FIXME TD-er: Support Ping plugin for ESP32
|
||||
&Plugin_089,
|
||||
# endif // ifdef ESP8266
|
||||
#endif // ifdef USES_P089
|
||||
|
||||
#ifdef USES_P090
|
||||
|
||||
@@ -390,10 +390,7 @@ void PluginInit(bool priorityOnly = false);
|
||||
#endif
|
||||
|
||||
#ifdef USES_P089
|
||||
#ifdef ESP8266
|
||||
// FIXME TD-er: Support Ping plugin for ESP32
|
||||
ADDPLUGIN_H(089)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef USES_P090
|
||||
|
||||
@@ -1,13 +1,114 @@
|
||||
#include "../PluginStructs/P089_data_struct.h"
|
||||
|
||||
#if defined(USES_P089) && defined(ESP8266)
|
||||
#ifdef USES_P089
|
||||
|
||||
|
||||
#include "../Helpers/Networking.h"
|
||||
# include "../Helpers/Networking.h"
|
||||
|
||||
#include "../Helpers/_Plugin_init.h"
|
||||
# include "../Helpers/_Plugin_init.h"
|
||||
|
||||
# ifdef ESP32
|
||||
P089_data_struct::P089_data_struct() {
|
||||
espPing = new (std::nothrow) PingClass();
|
||||
_ping_task_data.initialized = isInitialized();
|
||||
}
|
||||
|
||||
P089_data_struct::~P089_data_struct() {
|
||||
if (_ping_task_data.taskHandle) {
|
||||
vTaskDelete(_ping_task_data.taskHandle);
|
||||
}
|
||||
delete espPing;
|
||||
}
|
||||
|
||||
void P089_execute_ping_task(void *parameter)
|
||||
{
|
||||
P089_ping_task_data*ping_task_data = static_cast<P089_ping_task_data *>(parameter);
|
||||
|
||||
if ((ping_task_data->status == P089_status::Working) && (nullptr != ping_task_data->espPing)) {
|
||||
// Blocking operation
|
||||
ping_task_data->result = ping_task_data->espPing->ping(ping_task_data->pingIp, ping_task_data->count);
|
||||
|
||||
// Results are in
|
||||
ping_task_data->avgTime = ping_task_data->espPing->averageTime();
|
||||
ping_task_data->status = P089_status::Ready;
|
||||
}
|
||||
|
||||
ping_task_data->taskHandle = NULL;
|
||||
vTaskDelete(ping_task_data->taskHandle);
|
||||
}
|
||||
|
||||
bool P089_data_struct::send_ping(struct EventStruct *event) {
|
||||
/* This ping lost for sure */
|
||||
if (!isInitialized() || !NetworkConnected()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!_ping_task_data.initialized) {
|
||||
// addLog(LOG_LEVEL_ERROR, F("PING : Not initialized."));
|
||||
return true; // Not (yet?) initialized
|
||||
}
|
||||
|
||||
if (_ping_task_data.status == P089_status::Working) {
|
||||
// addLog(LOG_LEVEL_INFO, F("PING : Still working."));
|
||||
return false; // Busy, but not a failure
|
||||
}
|
||||
|
||||
if (_ping_task_data.status == P089_status::Ready) {
|
||||
if (_ping_task_data.result) {
|
||||
addLog(LOG_LEVEL_INFO, strformat(F("PING : Successfully pinged %s (%s) count: %d avg: %.03f ms"),
|
||||
_ping_task_data.hostname.c_str(),
|
||||
_ping_task_data.pingIp.toString().c_str(),
|
||||
_ping_task_data.count,
|
||||
_ping_task_data.avgTime));
|
||||
} else {
|
||||
addLog(LOG_LEVEL_ERROR, strformat(F("PING : Error pinging %s (%s)"),
|
||||
_ping_task_data.hostname.c_str(),
|
||||
_ping_task_data.pingIp.toString().c_str()));
|
||||
}
|
||||
UserVar.setFloat(event->TaskIndex, 1, _ping_task_data.avgTime); // Set always, even when not specifically enabled
|
||||
|
||||
_ping_task_data.status = P089_status::Initial; // Ready for new work
|
||||
return !_ping_task_data.result; // Inverted result to report back!
|
||||
}
|
||||
|
||||
IPAddress ip;
|
||||
char hostname[PLUGIN_089_HOSTNAME_SIZE]{};
|
||||
|
||||
LoadCustomTaskSettings(event->TaskIndex, (uint8_t *)&hostname, PLUGIN_089_HOSTNAME_SIZE);
|
||||
|
||||
/* This one lost as well, DNS dead? */
|
||||
if (!resolveHostByName(hostname, ip)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
int16_t pingCount = P089_PING_COUNT;
|
||||
|
||||
if ((pingCount < 1) || (pingCount > 100)) {
|
||||
pingCount = 5;
|
||||
}
|
||||
|
||||
_ping_task_data.status = P089_status::Working;
|
||||
_ping_task_data.count = pingCount;
|
||||
_ping_task_data.pingIp = ip;
|
||||
_ping_task_data.hostname = hostname; // Bring all data to the task
|
||||
_ping_task_data.espPing = espPing;
|
||||
|
||||
xTaskCreatePinnedToCore(
|
||||
P089_execute_ping_task, // Function that should be called
|
||||
"PingClass.ping()", // Name of the task (for debugging)
|
||||
4000, // Stack size (bytes)
|
||||
&_ping_task_data, // Parameter to pass
|
||||
1, // Task priority
|
||||
&_ping_task_data.taskHandle, // Task handle
|
||||
xPortGetCoreID() // Core you want to run the task on (0 or 1)
|
||||
);
|
||||
|
||||
return false; // Started work, not a failure
|
||||
}
|
||||
|
||||
# endif // ifdef ESP32
|
||||
|
||||
# ifdef ESP8266
|
||||
P089_data_struct::P089_data_struct() {
|
||||
destIPAddress.addr = 0;
|
||||
idseq = 0;
|
||||
@@ -159,4 +260,5 @@ uint8_t PingReceiver(void *origin, struct raw_pcb *pcb, struct pbuf *packetBuffe
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif // if defined(USES_P089) && defined(ESP8266)
|
||||
# endif // ifdef ESP8266
|
||||
#endif // ifdef USES_P089
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#define PLUGINSTRUCTS_P089_DATA_STRUCT_H
|
||||
|
||||
#include "../../_Plugin_Helper.h"
|
||||
#if defined(USES_P089) && defined(ESP8266)
|
||||
#ifdef USES_P089
|
||||
|
||||
|
||||
# define PLUGIN_ID_089 89
|
||||
@@ -12,16 +12,64 @@
|
||||
|
||||
# define ICMP_PAYLOAD_LEN 32
|
||||
|
||||
# ifdef ESP32
|
||||
# define P089_PING_COUNT PCONFIG(0)
|
||||
# define P089_VALUE_COUNT PCONFIG(1)
|
||||
|
||||
# include <ESPping.h>
|
||||
|
||||
enum class P089_status : uint8_t {
|
||||
Initial = 0,
|
||||
Working = 1,
|
||||
Ready = 2,
|
||||
};
|
||||
|
||||
struct P089_ping_task_data {
|
||||
bool initialized{};
|
||||
P089_status status = P089_status::Initial;
|
||||
IPAddress pingIp;
|
||||
String hostname;
|
||||
bool result{};
|
||||
uint16_t count{};
|
||||
float avgTime{};
|
||||
PingClass *espPing = nullptr;
|
||||
|
||||
// This is C-code, so not set to nullptr, but to NULL
|
||||
TaskHandle_t taskHandle = NULL;
|
||||
};
|
||||
|
||||
struct P089_data_struct : public PluginTaskData_base {
|
||||
public:
|
||||
|
||||
P089_data_struct();
|
||||
|
||||
virtual ~P089_data_struct();
|
||||
|
||||
bool isInitialized() const {
|
||||
return nullptr != espPing;
|
||||
}
|
||||
|
||||
bool send_ping(struct EventStruct *event);
|
||||
|
||||
private:
|
||||
|
||||
PingClass *espPing = nullptr;
|
||||
P089_ping_task_data _ping_task_data;
|
||||
};
|
||||
# endif // ifdef ESP32
|
||||
|
||||
# ifdef ESP8266
|
||||
|
||||
extern "C"
|
||||
{
|
||||
# include <lwip/raw.h>
|
||||
# include <lwip/icmp.h> // needed for icmp packet definitions
|
||||
# include <lwip/inet_chksum.h> // needed for inet_chksum()
|
||||
# include <lwip/sys.h> // needed for sys_now()
|
||||
# include <lwip/netif.h>
|
||||
# include <lwip/raw.h>
|
||||
# include <lwip/icmp.h> // needed for icmp packet definitions
|
||||
# include <lwip/inet_chksum.h> // needed for inet_chksum()
|
||||
# include <lwip/sys.h> // needed for sys_now()
|
||||
# include <lwip/netif.h>
|
||||
}
|
||||
|
||||
# include "src/ESPEasyCore/ESPEasyNetwork.h"
|
||||
# include "src/ESPEasyCore/ESPEasyNetwork.h"
|
||||
|
||||
|
||||
struct P089_icmp_pcb {
|
||||
@@ -39,6 +87,10 @@ public:
|
||||
|
||||
bool send_ping(struct EventStruct *event);
|
||||
|
||||
bool isInitialized() const {
|
||||
return nullptr != P089_data;
|
||||
}
|
||||
|
||||
struct P089_icmp_pcb *P089_data = nullptr;
|
||||
ip_addr_t destIPAddress;
|
||||
uint32_t idseq;
|
||||
@@ -50,6 +102,6 @@ uint8_t PingReceiver(void *origin,
|
||||
struct pbuf *packetBuffer,
|
||||
const ip_addr_t *addr);
|
||||
|
||||
|
||||
#endif // if defined(USES_P089) && defined(ESP8266)
|
||||
# endif // ifdef ESP8266
|
||||
#endif // ifdef USES_P089
|
||||
#endif // ifndef PLUGINSTRUCTS_P089_DATA_STRUCT_H
|
||||
|
||||
Reference in New Issue
Block a user