mirror of
https://github.com/esp8266/Arduino.git
synced 2025-04-19 23:22:16 +03:00
Migrate from astyle to clang-format (#8464)
This commit is contained in:
parent
46190b61f1
commit
19b7a29720
11
.github/workflows/pull-request.yml
vendored
11
.github/workflows/pull-request.yml
vendored
@ -238,11 +238,20 @@ jobs:
|
||||
python-version: '3.x'
|
||||
- name: Style check
|
||||
env:
|
||||
LLVM_SNAPSHOT_KEY: "6084F3CF814B57C1CF12EFD515CF4D18AF4F7421"
|
||||
TRAVIS_BUILD_DIR: ${{ github.workspace }}
|
||||
TRAVIS_TAG: ${{ github.ref }}
|
||||
run: |
|
||||
export GNUPGHOME=$(mktemp -d)
|
||||
gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$LLVM_SNAPSHOT_KEY"
|
||||
gpg --batch --armor --export "$LLVM_SNAPSHOT_KEY" | \
|
||||
sudo tee /etc/apt/trusted.gpg.d/llvm-snapshot.gpg.asc
|
||||
rm -r $GNUPGHOME
|
||||
echo "deb http://apt.llvm.org/focal/ llvm-toolchain-focal-13 main" | \
|
||||
sudo tee /etc/apt/sources.list.d/llvm.list
|
||||
sudo apt update
|
||||
sudo apt install astyle
|
||||
sudo apt install clang-format-13
|
||||
pip3 install pyyaml
|
||||
bash ./tests/ci/style_check.sh
|
||||
|
||||
|
||||
|
@ -23,7 +23,7 @@
|
||||
// these functions must exists as-is with "C" interface,
|
||||
// nonos-sdk calls them at boot time and later
|
||||
|
||||
#include <lwip/init.h> // LWIP_VERSION
|
||||
#include <lwip/init.h> // LWIP_VERSION
|
||||
|
||||
#include <lwip/netif.h>
|
||||
#include "LwipDhcpServer.h"
|
||||
@ -35,8 +35,7 @@ DhcpServer dhcpSoftAP(&netif_git[SOFTAP_IF]);
|
||||
|
||||
extern "C"
|
||||
{
|
||||
|
||||
void dhcps_start(struct ip_info *info, netif* apnetif)
|
||||
void dhcps_start(struct ip_info* info, netif* apnetif)
|
||||
{
|
||||
// apnetif is esp interface, replaced by lwip2's
|
||||
// netif_git[SOFTAP_IF] interface in constructor
|
||||
@ -61,4 +60,4 @@ extern "C"
|
||||
dhcpSoftAP.end();
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
} // extern "C"
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -31,12 +31,11 @@
|
||||
#ifndef __DHCPS_H__
|
||||
#define __DHCPS_H__
|
||||
|
||||
#include <lwip/init.h> // LWIP_VERSION
|
||||
#include <lwip/init.h> // LWIP_VERSION
|
||||
|
||||
class DhcpServer
|
||||
{
|
||||
public:
|
||||
|
||||
DhcpServer(netif* netif);
|
||||
~DhcpServer();
|
||||
|
||||
@ -53,72 +52,64 @@ public:
|
||||
|
||||
// legacy public C structure and API to eventually turn into C++
|
||||
|
||||
void init_dhcps_lease(uint32 ip);
|
||||
bool set_dhcps_lease(struct dhcps_lease *please);
|
||||
bool get_dhcps_lease(struct dhcps_lease *please);
|
||||
bool set_dhcps_offer_option(uint8 level, void* optarg);
|
||||
bool set_dhcps_lease_time(uint32 minute);
|
||||
bool reset_dhcps_lease_time(void);
|
||||
void init_dhcps_lease(uint32 ip);
|
||||
bool set_dhcps_lease(struct dhcps_lease* please);
|
||||
bool get_dhcps_lease(struct dhcps_lease* please);
|
||||
bool set_dhcps_offer_option(uint8 level, void* optarg);
|
||||
bool set_dhcps_lease_time(uint32 minute);
|
||||
bool reset_dhcps_lease_time(void);
|
||||
uint32 get_dhcps_lease_time(void);
|
||||
bool add_dhcps_lease(uint8 *macaddr);
|
||||
bool add_dhcps_lease(uint8* macaddr);
|
||||
|
||||
void dhcps_set_dns(int num, const ipv4_addr_t* dns);
|
||||
|
||||
protected:
|
||||
|
||||
// legacy C structure and API to eventually turn into C++
|
||||
|
||||
typedef struct _list_node
|
||||
{
|
||||
void *pnode;
|
||||
struct _list_node *pnext;
|
||||
void* pnode;
|
||||
struct _list_node* pnext;
|
||||
} list_node;
|
||||
|
||||
void node_insert_to_list(list_node **phead, list_node* pinsert);
|
||||
void node_remove_from_list(list_node **phead, list_node* pdelete);
|
||||
uint8_t* add_msg_type(uint8_t *optptr, uint8_t type);
|
||||
uint8_t* add_offer_options(uint8_t *optptr);
|
||||
uint8_t* add_end(uint8_t *optptr);
|
||||
void create_msg(struct dhcps_msg *m);
|
||||
void send_offer(struct dhcps_msg *m);
|
||||
void send_nak(struct dhcps_msg *m);
|
||||
void send_ack(struct dhcps_msg *m);
|
||||
uint8_t parse_options(uint8_t *optptr, sint16_t len);
|
||||
sint16_t parse_msg(struct dhcps_msg *m, u16_t len);
|
||||
static void S_handle_dhcp(void *arg,
|
||||
struct udp_pcb *pcb,
|
||||
struct pbuf *p,
|
||||
const ip_addr_t *addr,
|
||||
void node_insert_to_list(list_node** phead, list_node* pinsert);
|
||||
void node_remove_from_list(list_node** phead, list_node* pdelete);
|
||||
uint8_t* add_msg_type(uint8_t* optptr, uint8_t type);
|
||||
uint8_t* add_offer_options(uint8_t* optptr);
|
||||
uint8_t* add_end(uint8_t* optptr);
|
||||
void create_msg(struct dhcps_msg* m);
|
||||
void send_offer(struct dhcps_msg* m);
|
||||
void send_nak(struct dhcps_msg* m);
|
||||
void send_ack(struct dhcps_msg* m);
|
||||
uint8_t parse_options(uint8_t* optptr, sint16_t len);
|
||||
sint16_t parse_msg(struct dhcps_msg* m, u16_t len);
|
||||
static void S_handle_dhcp(void* arg, struct udp_pcb* pcb, struct pbuf* p, const ip_addr_t* addr,
|
||||
uint16_t port);
|
||||
void handle_dhcp(
|
||||
struct udp_pcb *pcb,
|
||||
struct pbuf *p,
|
||||
const ip_addr_t *addr,
|
||||
uint16_t port);
|
||||
void kill_oldest_dhcps_pool(void);
|
||||
void dhcps_coarse_tmr(void); // CURRENTLY NOT CALLED
|
||||
void dhcps_client_leave(u8 *bssid, struct ipv4_addr *ip, bool force);
|
||||
uint32 dhcps_client_update(u8 *bssid, struct ipv4_addr *ip);
|
||||
void handle_dhcp(struct udp_pcb* pcb, struct pbuf* p, const ip_addr_t* addr, uint16_t port);
|
||||
void kill_oldest_dhcps_pool(void);
|
||||
void dhcps_coarse_tmr(void); // CURRENTLY NOT CALLED
|
||||
void dhcps_client_leave(u8* bssid, struct ipv4_addr* ip, bool force);
|
||||
uint32 dhcps_client_update(u8* bssid, struct ipv4_addr* ip);
|
||||
|
||||
netif* _netif;
|
||||
|
||||
struct udp_pcb *pcb_dhcps;
|
||||
ip_addr_t broadcast_dhcps;
|
||||
struct udp_pcb* pcb_dhcps;
|
||||
ip_addr_t broadcast_dhcps;
|
||||
struct ipv4_addr server_address;
|
||||
struct ipv4_addr client_address;
|
||||
struct ipv4_addr dns_address;
|
||||
uint32 dhcps_lease_time;
|
||||
uint32 dhcps_lease_time;
|
||||
|
||||
struct dhcps_lease dhcps_lease;
|
||||
list_node *plist;
|
||||
uint8 offer;
|
||||
bool renew;
|
||||
list_node* plist;
|
||||
uint8 offer;
|
||||
bool renew;
|
||||
|
||||
static const uint32 magic_cookie;
|
||||
};
|
||||
|
||||
// SoftAP DHCP server always exists and is started on boot
|
||||
extern DhcpServer dhcpSoftAP;
|
||||
extern "C" int fw_has_started_softap_dhcps;
|
||||
extern "C" int fw_has_started_softap_dhcps;
|
||||
|
||||
#endif // __DHCPS_H__
|
||||
#endif // __DHCPS_H__
|
||||
|
@ -1,12 +1,13 @@
|
||||
|
||||
extern "C" {
|
||||
extern "C"
|
||||
{
|
||||
#include "lwip/err.h"
|
||||
#include "lwip/ip_addr.h"
|
||||
#include "lwip/dns.h"
|
||||
#include "lwip/dhcp.h"
|
||||
#include "lwip/init.h" // LWIP_VERSION_
|
||||
#include "lwip/init.h" // LWIP_VERSION_
|
||||
#if LWIP_IPV6
|
||||
#include "lwip/netif.h" // struct netif
|
||||
#include "lwip/netif.h" // struct netif
|
||||
#endif
|
||||
|
||||
#include <user_interface.h>
|
||||
@ -24,19 +25,23 @@ extern "C" {
|
||||
//
|
||||
// result stored into gateway/netmask/dns1
|
||||
|
||||
bool LwipIntf::ipAddressReorder(const IPAddress& local_ip, const IPAddress& arg1, const IPAddress& arg2, const IPAddress& arg3,
|
||||
IPAddress& gateway, IPAddress& netmask, IPAddress& dns1)
|
||||
bool LwipIntf::ipAddressReorder(const IPAddress& local_ip, const IPAddress& arg1,
|
||||
const IPAddress& arg2, const IPAddress& arg3, IPAddress& gateway,
|
||||
IPAddress& netmask, IPAddress& dns1)
|
||||
{
|
||||
//To allow compatibility, check first octet of 3rd arg. If 255, interpret as ESP order, otherwise Arduino order.
|
||||
// To allow compatibility, check first octet of 3rd arg. If 255, interpret as ESP order,
|
||||
// otherwise Arduino order.
|
||||
gateway = arg1;
|
||||
netmask = arg2;
|
||||
dns1 = arg3;
|
||||
dns1 = arg3;
|
||||
|
||||
if (netmask[0] != 255)
|
||||
{
|
||||
//octet is not 255 => interpret as Arduino order
|
||||
// octet is not 255 => interpret as Arduino order
|
||||
gateway = arg2;
|
||||
netmask = arg3[0] == 0 ? IPAddress(255, 255, 255, 0) : arg3; //arg order is arduino and 4th arg not given => assign it arduino default
|
||||
netmask = arg3[0] == 0 ? IPAddress(255, 255, 255, 0)
|
||||
: arg3; // arg order is arduino and 4th arg not given => assign it
|
||||
// arduino default
|
||||
dns1 = arg1;
|
||||
}
|
||||
|
||||
@ -46,7 +51,7 @@ bool LwipIntf::ipAddressReorder(const IPAddress& local_ip, const IPAddress& arg1
|
||||
return false;
|
||||
}
|
||||
|
||||
//ip and gateway must be in the same netmask
|
||||
// ip and gateway must be in the same netmask
|
||||
if (gateway.isSet() && (local_ip.v4() & netmask.v4()) != (gateway.v4() & netmask.v4()))
|
||||
{
|
||||
return false;
|
||||
@ -143,7 +148,6 @@ bool LwipIntf::hostname(const char* aHostname)
|
||||
// harmless for AP, also compatible with ethernet adapters (to come)
|
||||
for (netif* intf = netif_list; intf; intf = intf->next)
|
||||
{
|
||||
|
||||
// unconditionally update all known interfaces
|
||||
intf->hostname = wifi_station_get_hostname();
|
||||
|
||||
@ -162,4 +166,3 @@ bool LwipIntf::hostname(const char* aHostname)
|
||||
|
||||
return ret && compliant;
|
||||
}
|
||||
|
||||
|
@ -10,8 +10,7 @@
|
||||
class LwipIntf
|
||||
{
|
||||
public:
|
||||
|
||||
using CBType = std::function <void(netif*)>;
|
||||
using CBType = std::function<void(netif*)>;
|
||||
|
||||
static bool stateUpCB(LwipIntf::CBType&& cb);
|
||||
|
||||
@ -24,12 +23,12 @@ public:
|
||||
// arg3 | dns1 netmask
|
||||
//
|
||||
// result stored into gateway/netmask/dns1
|
||||
static
|
||||
bool ipAddressReorder(const IPAddress& local_ip, const IPAddress& arg1, const IPAddress& arg2, const IPAddress& arg3,
|
||||
IPAddress& gateway, IPAddress& netmask, IPAddress& dns1);
|
||||
static bool ipAddressReorder(const IPAddress& local_ip, const IPAddress& arg1,
|
||||
const IPAddress& arg2, const IPAddress& arg3, IPAddress& gateway,
|
||||
IPAddress& netmask, IPAddress& dns1);
|
||||
|
||||
String hostname();
|
||||
bool hostname(const String& aHostname)
|
||||
bool hostname(const String& aHostname)
|
||||
{
|
||||
return hostname(aHostname.c_str());
|
||||
}
|
||||
@ -42,8 +41,7 @@ public:
|
||||
const char* getHostname();
|
||||
|
||||
protected:
|
||||
|
||||
static bool stateChangeSysCB(LwipIntf::CBType&& cb);
|
||||
};
|
||||
|
||||
#endif // _LWIPINTF_H
|
||||
#endif // _LWIPINTF_H
|
||||
|
@ -5,8 +5,8 @@
|
||||
|
||||
#define NETIF_STATUS_CB_SIZE 3
|
||||
|
||||
static int netifStatusChangeListLength = 0;
|
||||
LwipIntf::CBType netifStatusChangeList [NETIF_STATUS_CB_SIZE];
|
||||
static int netifStatusChangeListLength = 0;
|
||||
LwipIntf::CBType netifStatusChangeList[NETIF_STATUS_CB_SIZE];
|
||||
|
||||
extern "C" void netif_status_changed(struct netif* netif)
|
||||
{
|
||||
@ -33,12 +33,14 @@ bool LwipIntf::stateChangeSysCB(LwipIntf::CBType&& cb)
|
||||
|
||||
bool LwipIntf::stateUpCB(LwipIntf::CBType&& cb)
|
||||
{
|
||||
return stateChangeSysCB([cb](netif * nif)
|
||||
{
|
||||
if (netif_is_up(nif))
|
||||
schedule_function([cb, nif]()
|
||||
return stateChangeSysCB(
|
||||
[cb](netif* nif)
|
||||
{
|
||||
cb(nif);
|
||||
if (netif_is_up(nif))
|
||||
schedule_function(
|
||||
[cb, nif]()
|
||||
{
|
||||
cb(nif);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -14,7 +14,7 @@
|
||||
#include <lwip/dns.h>
|
||||
#include <lwip/apps/sntp.h>
|
||||
|
||||
#include <user_interface.h> // wifi_get_macaddr()
|
||||
#include <user_interface.h> // wifi_get_macaddr()
|
||||
|
||||
#include "SPI.h"
|
||||
#include "Schedule.h"
|
||||
@ -25,41 +25,36 @@
|
||||
#define DEFAULT_MTU 1500
|
||||
#endif
|
||||
|
||||
template <class RawDev>
|
||||
template<class RawDev>
|
||||
class LwipIntfDev: public LwipIntf, public RawDev
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
LwipIntfDev(int8_t cs = SS, SPIClass& spi = SPI, int8_t intr = -1):
|
||||
RawDev(cs, spi, intr),
|
||||
_mtu(DEFAULT_MTU),
|
||||
_intrPin(intr),
|
||||
_started(false),
|
||||
_default(false)
|
||||
LwipIntfDev(int8_t cs = SS, SPIClass& spi = SPI, int8_t intr = -1) :
|
||||
RawDev(cs, spi, intr), _mtu(DEFAULT_MTU), _intrPin(intr), _started(false), _default(false)
|
||||
{
|
||||
memset(&_netif, 0, sizeof(_netif));
|
||||
}
|
||||
|
||||
boolean config(const IPAddress& local_ip, const IPAddress& arg1, const IPAddress& arg2, const IPAddress& arg3 = IPADDR_NONE, const IPAddress& dns2 = IPADDR_NONE);
|
||||
boolean config(const IPAddress& local_ip, const IPAddress& arg1, const IPAddress& arg2,
|
||||
const IPAddress& arg3 = IPADDR_NONE, const IPAddress& dns2 = IPADDR_NONE);
|
||||
|
||||
// default mac-address is inferred from esp8266's STA interface
|
||||
boolean begin(const uint8_t *macAddress = nullptr, const uint16_t mtu = DEFAULT_MTU);
|
||||
boolean begin(const uint8_t* macAddress = nullptr, const uint16_t mtu = DEFAULT_MTU);
|
||||
|
||||
const netif* getNetIf() const
|
||||
{
|
||||
return &_netif;
|
||||
}
|
||||
|
||||
IPAddress localIP() const
|
||||
IPAddress localIP() const
|
||||
{
|
||||
return IPAddress(ip4_addr_get_u32(ip_2_ip4(&_netif.ip_addr)));
|
||||
}
|
||||
IPAddress subnetMask() const
|
||||
IPAddress subnetMask() const
|
||||
{
|
||||
return IPAddress(ip4_addr_get_u32(ip_2_ip4(&_netif.netmask)));
|
||||
}
|
||||
IPAddress gatewayIP() const
|
||||
IPAddress gatewayIP() const
|
||||
{
|
||||
return IPAddress(ip4_addr_get_u32(ip_2_ip4(&_netif.gw)));
|
||||
}
|
||||
@ -77,12 +72,11 @@ public:
|
||||
wl_status_t status();
|
||||
|
||||
protected:
|
||||
|
||||
err_t netif_init();
|
||||
void netif_status_callback();
|
||||
|
||||
static err_t netif_init_s(netif* netif);
|
||||
static err_t linkoutput_s(netif *netif, struct pbuf *p);
|
||||
static err_t linkoutput_s(netif* netif, struct pbuf* p);
|
||||
static void netif_status_callback_s(netif* netif);
|
||||
|
||||
// called on a regular basis or on interrupt
|
||||
@ -90,18 +84,19 @@ protected:
|
||||
|
||||
// members
|
||||
|
||||
netif _netif;
|
||||
|
||||
uint16_t _mtu;
|
||||
int8_t _intrPin;
|
||||
uint8_t _macAddress[6];
|
||||
bool _started;
|
||||
bool _default;
|
||||
netif _netif;
|
||||
|
||||
uint16_t _mtu;
|
||||
int8_t _intrPin;
|
||||
uint8_t _macAddress[6];
|
||||
bool _started;
|
||||
bool _default;
|
||||
};
|
||||
|
||||
template <class RawDev>
|
||||
boolean LwipIntfDev<RawDev>::config(const IPAddress& localIP, const IPAddress& gateway, const IPAddress& netmask, const IPAddress& dns1, const IPAddress& dns2)
|
||||
template<class RawDev>
|
||||
boolean LwipIntfDev<RawDev>::config(const IPAddress& localIP, const IPAddress& gateway,
|
||||
const IPAddress& netmask, const IPAddress& dns1,
|
||||
const IPAddress& dns2)
|
||||
{
|
||||
if (_started)
|
||||
{
|
||||
@ -132,7 +127,7 @@ boolean LwipIntfDev<RawDev>::config(const IPAddress& localIP, const IPAddress& g
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class RawDev>
|
||||
template<class RawDev>
|
||||
boolean LwipIntfDev<RawDev>::begin(const uint8_t* macAddress, const uint16_t mtu)
|
||||
{
|
||||
if (mtu)
|
||||
@ -162,9 +157,9 @@ boolean LwipIntfDev<RawDev>::begin(const uint8_t* macAddress, const uint16_t mtu
|
||||
memset(_macAddress, 0, 6);
|
||||
_macAddress[0] = 0xEE;
|
||||
#endif
|
||||
_macAddress[3] += _netif.num; // alter base mac address
|
||||
_macAddress[0] &= 0xfe; // set as locally administered, unicast, per
|
||||
_macAddress[0] |= 0x02; // https://en.wikipedia.org/wiki/MAC_address#Universal_vs._local
|
||||
_macAddress[3] += _netif.num; // alter base mac address
|
||||
_macAddress[0] &= 0xfe; // set as locally administered, unicast, per
|
||||
_macAddress[0] |= 0x02; // https://en.wikipedia.org/wiki/MAC_address#Universal_vs._local
|
||||
}
|
||||
|
||||
if (!RawDev::begin(_macAddress))
|
||||
@ -183,7 +178,8 @@ boolean LwipIntfDev<RawDev>::begin(const uint8_t* macAddress, const uint16_t mtu
|
||||
ip_addr_copy(netmask, _netif.netmask);
|
||||
ip_addr_copy(gw, _netif.gw);
|
||||
|
||||
if (!netif_add(&_netif, ip_2_ip4(&ip_addr), ip_2_ip4(&netmask), ip_2_ip4(&gw), this, netif_init_s, ethernet_input))
|
||||
if (!netif_add(&_netif, ip_2_ip4(&ip_addr), ip_2_ip4(&netmask), ip_2_ip4(&gw), this,
|
||||
netif_init_s, ethernet_input))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -212,20 +208,24 @@ boolean LwipIntfDev<RawDev>::begin(const uint8_t* macAddress, const uint16_t mtu
|
||||
{
|
||||
if (RawDev::interruptIsPossible())
|
||||
{
|
||||
//attachInterrupt(_intrPin, [&]() { this->handlePackets(); }, FALLING);
|
||||
// attachInterrupt(_intrPin, [&]() { this->handlePackets(); }, FALLING);
|
||||
}
|
||||
else
|
||||
{
|
||||
::printf((PGM_P)F("lwIP_Intf: Interrupt not implemented yet, enabling transparent polling\r\n"));
|
||||
::printf((PGM_P)F(
|
||||
"lwIP_Intf: Interrupt not implemented yet, enabling transparent polling\r\n"));
|
||||
_intrPin = -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (_intrPin < 0 && !schedule_recurrent_function_us([&]()
|
||||
{
|
||||
this->handlePackets();
|
||||
return true;
|
||||
}, 100))
|
||||
if (_intrPin < 0
|
||||
&& !schedule_recurrent_function_us(
|
||||
[&]()
|
||||
{
|
||||
this->handlePackets();
|
||||
return true;
|
||||
},
|
||||
100))
|
||||
{
|
||||
netif_remove(&_netif);
|
||||
return false;
|
||||
@ -234,14 +234,14 @@ boolean LwipIntfDev<RawDev>::begin(const uint8_t* macAddress, const uint16_t mtu
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class RawDev>
|
||||
template<class RawDev>
|
||||
wl_status_t LwipIntfDev<RawDev>::status()
|
||||
{
|
||||
return _started ? (connected() ? WL_CONNECTED : WL_DISCONNECTED) : WL_NO_SHIELD;
|
||||
}
|
||||
|
||||
template <class RawDev>
|
||||
err_t LwipIntfDev<RawDev>::linkoutput_s(netif *netif, struct pbuf *pbuf)
|
||||
template<class RawDev>
|
||||
err_t LwipIntfDev<RawDev>::linkoutput_s(netif* netif, struct pbuf* pbuf)
|
||||
{
|
||||
LwipIntfDev* ths = (LwipIntfDev*)netif->state;
|
||||
|
||||
@ -255,37 +255,34 @@ err_t LwipIntfDev<RawDev>::linkoutput_s(netif *netif, struct pbuf *pbuf)
|
||||
#if PHY_HAS_CAPTURE
|
||||
if (phy_capture)
|
||||
{
|
||||
phy_capture(ths->_netif.num, (const char*)pbuf->payload, pbuf->len, /*out*/1, /*success*/len == pbuf->len);
|
||||
phy_capture(ths->_netif.num, (const char*)pbuf->payload, pbuf->len, /*out*/ 1,
|
||||
/*success*/ len == pbuf->len);
|
||||
}
|
||||
#endif
|
||||
|
||||
return len == pbuf->len ? ERR_OK : ERR_MEM;
|
||||
}
|
||||
|
||||
template <class RawDev>
|
||||
template<class RawDev>
|
||||
err_t LwipIntfDev<RawDev>::netif_init_s(struct netif* netif)
|
||||
{
|
||||
return ((LwipIntfDev*)netif->state)->netif_init();
|
||||
}
|
||||
|
||||
template <class RawDev>
|
||||
template<class RawDev>
|
||||
void LwipIntfDev<RawDev>::netif_status_callback_s(struct netif* netif)
|
||||
{
|
||||
((LwipIntfDev*)netif->state)->netif_status_callback();
|
||||
}
|
||||
|
||||
template <class RawDev>
|
||||
template<class RawDev>
|
||||
err_t LwipIntfDev<RawDev>::netif_init()
|
||||
{
|
||||
_netif.name[0] = 'e';
|
||||
_netif.name[1] = '0' + _netif.num;
|
||||
_netif.mtu = _mtu;
|
||||
_netif.name[0] = 'e';
|
||||
_netif.name[1] = '0' + _netif.num;
|
||||
_netif.mtu = _mtu;
|
||||
_netif.chksum_flags = NETIF_CHECKSUM_ENABLE_ALL;
|
||||
_netif.flags =
|
||||
NETIF_FLAG_ETHARP
|
||||
| NETIF_FLAG_IGMP
|
||||
| NETIF_FLAG_BROADCAST
|
||||
| NETIF_FLAG_LINK_UP;
|
||||
_netif.flags = NETIF_FLAG_ETHARP | NETIF_FLAG_IGMP | NETIF_FLAG_BROADCAST | NETIF_FLAG_LINK_UP;
|
||||
|
||||
// lwIP's doc: This function typically first resolves the hardware
|
||||
// address, then sends the packet. For ethernet physical layer, this is
|
||||
@ -301,7 +298,7 @@ err_t LwipIntfDev<RawDev>::netif_init()
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
template <class RawDev>
|
||||
template<class RawDev>
|
||||
void LwipIntfDev<RawDev>::netif_status_callback()
|
||||
{
|
||||
if (connected())
|
||||
@ -321,14 +318,14 @@ void LwipIntfDev<RawDev>::netif_status_callback()
|
||||
}
|
||||
}
|
||||
|
||||
template <class RawDev>
|
||||
template<class RawDev>
|
||||
err_t LwipIntfDev<RawDev>::handlePackets()
|
||||
{
|
||||
int pkt = 0;
|
||||
while (1)
|
||||
{
|
||||
if (++pkt == 10)
|
||||
// prevent starvation
|
||||
// prevent starvation
|
||||
{
|
||||
return ERR_OK;
|
||||
}
|
||||
@ -374,7 +371,8 @@ err_t LwipIntfDev<RawDev>::handlePackets()
|
||||
#if PHY_HAS_CAPTURE
|
||||
if (phy_capture)
|
||||
{
|
||||
phy_capture(_netif.num, (const char*)pbuf->payload, tot_len, /*out*/0, /*success*/err == ERR_OK);
|
||||
phy_capture(_netif.num, (const char*)pbuf->payload, tot_len, /*out*/ 0,
|
||||
/*success*/ err == ERR_OK);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -384,11 +382,10 @@ err_t LwipIntfDev<RawDev>::handlePackets()
|
||||
return err;
|
||||
}
|
||||
// (else) allocated pbuf is now lwIP's responsibility
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
template <class RawDev>
|
||||
template<class RawDev>
|
||||
void LwipIntfDev<RawDev>::setDefault()
|
||||
{
|
||||
_default = true;
|
||||
@ -398,4 +395,4 @@ void LwipIntfDev<RawDev>::setDefault()
|
||||
}
|
||||
}
|
||||
|
||||
#endif // _LWIPINTFDEV_H
|
||||
#endif // _LWIPINTFDEV_H
|
||||
|
@ -19,20 +19,17 @@
|
||||
parsing functions based on TextFinder library by Michael Margolis
|
||||
*/
|
||||
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <StreamDev.h>
|
||||
|
||||
size_t Stream::sendGeneric(Print* to,
|
||||
const ssize_t len,
|
||||
const int readUntilChar,
|
||||
size_t Stream::sendGeneric(Print* to, const ssize_t len, const int readUntilChar,
|
||||
const esp8266::polledTimeout::oneShotFastMs::timeType timeoutMs)
|
||||
{
|
||||
setReport(Report::Success);
|
||||
|
||||
if (len == 0)
|
||||
{
|
||||
return 0; // conveniently avoids timeout for no requested data
|
||||
return 0; // conveniently avoids timeout for no requested data
|
||||
}
|
||||
|
||||
// There are two timeouts:
|
||||
@ -57,14 +54,17 @@ size_t Stream::sendGeneric(Print* to,
|
||||
return SendGenericRegular(to, len, timeoutMs);
|
||||
}
|
||||
|
||||
|
||||
size_t Stream::SendGenericPeekBuffer(Print* to, const ssize_t len, const int readUntilChar, const esp8266::polledTimeout::oneShotFastMs::timeType timeoutMs)
|
||||
size_t
|
||||
Stream::SendGenericPeekBuffer(Print* to, const ssize_t len, const int readUntilChar,
|
||||
const esp8266::polledTimeout::oneShotFastMs::timeType timeoutMs)
|
||||
{
|
||||
// "neverExpires (default, impossible)" is translated to default timeout
|
||||
esp8266::polledTimeout::oneShotFastMs timedOut(timeoutMs >= esp8266::polledTimeout::oneShotFastMs::neverExpires ? getTimeout() : timeoutMs);
|
||||
esp8266::polledTimeout::oneShotFastMs timedOut(
|
||||
timeoutMs >= esp8266::polledTimeout::oneShotFastMs::neverExpires ? getTimeout()
|
||||
: timeoutMs);
|
||||
// len==-1 => maxLen=0 <=> until starvation
|
||||
const size_t maxLen = std::max((ssize_t)0, len);
|
||||
size_t written = 0;
|
||||
const size_t maxLen = std::max((ssize_t)0, len);
|
||||
size_t written = 0;
|
||||
|
||||
while (!maxLen || written < maxLen)
|
||||
{
|
||||
@ -90,13 +90,13 @@ size_t Stream::SendGenericPeekBuffer(Print* to, const ssize_t len, const int rea
|
||||
if (w)
|
||||
{
|
||||
const char* directbuf = peekBuffer();
|
||||
bool foundChar = false;
|
||||
bool foundChar = false;
|
||||
if (readUntilChar >= 0)
|
||||
{
|
||||
const char* last = (const char*)memchr(directbuf, readUntilChar, w);
|
||||
if (last)
|
||||
{
|
||||
w = std::min((size_t)(last - directbuf), w);
|
||||
w = std::min((size_t)(last - directbuf), w);
|
||||
foundChar = true;
|
||||
}
|
||||
}
|
||||
@ -104,7 +104,7 @@ size_t Stream::SendGenericPeekBuffer(Print* to, const ssize_t len, const int rea
|
||||
{
|
||||
peekConsume(w);
|
||||
written += w;
|
||||
timedOut.reset(); // something has been written
|
||||
timedOut.reset(); // something has been written
|
||||
}
|
||||
if (foundChar)
|
||||
{
|
||||
@ -145,16 +145,20 @@ size_t Stream::SendGenericPeekBuffer(Print* to, const ssize_t len, const int rea
|
||||
return written;
|
||||
}
|
||||
|
||||
size_t Stream::SendGenericRegularUntil(Print* to, const ssize_t len, const int readUntilChar, const esp8266::polledTimeout::oneShotFastMs::timeType timeoutMs)
|
||||
size_t
|
||||
Stream::SendGenericRegularUntil(Print* to, const ssize_t len, const int readUntilChar,
|
||||
const esp8266::polledTimeout::oneShotFastMs::timeType timeoutMs)
|
||||
{
|
||||
// regular Stream API
|
||||
// no other choice than reading byte by byte
|
||||
|
||||
// "neverExpires (default, impossible)" is translated to default timeout
|
||||
esp8266::polledTimeout::oneShotFastMs timedOut(timeoutMs >= esp8266::polledTimeout::oneShotFastMs::neverExpires ? getTimeout() : timeoutMs);
|
||||
esp8266::polledTimeout::oneShotFastMs timedOut(
|
||||
timeoutMs >= esp8266::polledTimeout::oneShotFastMs::neverExpires ? getTimeout()
|
||||
: timeoutMs);
|
||||
// len==-1 => maxLen=0 <=> until starvation
|
||||
const size_t maxLen = std::max((ssize_t)0, len);
|
||||
size_t written = 0;
|
||||
const size_t maxLen = std::max((ssize_t)0, len);
|
||||
size_t written = 0;
|
||||
|
||||
while (!maxLen || written < maxLen)
|
||||
{
|
||||
@ -186,7 +190,7 @@ size_t Stream::SendGenericRegularUntil(Print* to, const ssize_t len, const int r
|
||||
break;
|
||||
}
|
||||
written += 1;
|
||||
timedOut.reset(); // something has been written
|
||||
timedOut.reset(); // something has been written
|
||||
}
|
||||
|
||||
if (timedOut)
|
||||
@ -221,16 +225,19 @@ size_t Stream::SendGenericRegularUntil(Print* to, const ssize_t len, const int r
|
||||
return written;
|
||||
}
|
||||
|
||||
size_t Stream::SendGenericRegular(Print* to, const ssize_t len, const esp8266::polledTimeout::oneShotFastMs::timeType timeoutMs)
|
||||
size_t Stream::SendGenericRegular(Print* to, const ssize_t len,
|
||||
const esp8266::polledTimeout::oneShotFastMs::timeType timeoutMs)
|
||||
{
|
||||
// regular Stream API
|
||||
// use an intermediary buffer
|
||||
|
||||
// "neverExpires (default, impossible)" is translated to default timeout
|
||||
esp8266::polledTimeout::oneShotFastMs timedOut(timeoutMs >= esp8266::polledTimeout::oneShotFastMs::neverExpires ? getTimeout() : timeoutMs);
|
||||
esp8266::polledTimeout::oneShotFastMs timedOut(
|
||||
timeoutMs >= esp8266::polledTimeout::oneShotFastMs::neverExpires ? getTimeout()
|
||||
: timeoutMs);
|
||||
// len==-1 => maxLen=0 <=> until starvation
|
||||
const size_t maxLen = std::max((ssize_t)0, len);
|
||||
size_t written = 0;
|
||||
const size_t maxLen = std::max((ssize_t)0, len);
|
||||
size_t written = 0;
|
||||
|
||||
while (!maxLen || written < maxLen)
|
||||
{
|
||||
@ -243,7 +250,7 @@ size_t Stream::SendGenericRegular(Print* to, const ssize_t len, const esp8266::p
|
||||
|
||||
size_t w = to->availableForWrite();
|
||||
if (w == 0 && !to->outputCanTimeout())
|
||||
// no more data can be written, ever
|
||||
// no more data can be written, ever
|
||||
{
|
||||
break;
|
||||
}
|
||||
@ -256,7 +263,7 @@ size_t Stream::SendGenericRegular(Print* to, const ssize_t len, const esp8266::p
|
||||
w = std::min(w, (decltype(w))temporaryStackBufferSize);
|
||||
if (w)
|
||||
{
|
||||
char temp[w];
|
||||
char temp[w];
|
||||
ssize_t r = read(temp, w);
|
||||
if (r < 0)
|
||||
{
|
||||
@ -270,7 +277,7 @@ size_t Stream::SendGenericRegular(Print* to, const ssize_t len, const esp8266::p
|
||||
setReport(Report::WriteError);
|
||||
break;
|
||||
}
|
||||
timedOut.reset(); // something has been written
|
||||
timedOut.reset(); // something has been written
|
||||
}
|
||||
|
||||
if (timedOut)
|
||||
@ -305,19 +312,19 @@ size_t Stream::SendGenericRegular(Print* to, const ssize_t len, const esp8266::p
|
||||
return written;
|
||||
}
|
||||
|
||||
Stream& operator << (Stream& out, String& string)
|
||||
Stream& operator<<(Stream& out, String& string)
|
||||
{
|
||||
StreamConstPtr(string).sendAll(out);
|
||||
return out;
|
||||
}
|
||||
|
||||
Stream& operator << (Stream& out, StreamString& stream)
|
||||
Stream& operator<<(Stream& out, StreamString& stream)
|
||||
{
|
||||
stream.sendAll(out);
|
||||
return out;
|
||||
}
|
||||
|
||||
Stream& operator << (Stream& out, Stream& stream)
|
||||
Stream& operator<<(Stream& out, Stream& stream)
|
||||
{
|
||||
if (stream.streamRemaining() < 0)
|
||||
{
|
||||
@ -339,13 +346,13 @@ Stream& operator << (Stream& out, Stream& stream)
|
||||
return out;
|
||||
}
|
||||
|
||||
Stream& operator << (Stream& out, const char* text)
|
||||
Stream& operator<<(Stream& out, const char* text)
|
||||
{
|
||||
StreamConstPtr(text, strlen_P(text)).sendAll(out);
|
||||
return out;
|
||||
}
|
||||
|
||||
Stream& operator << (Stream& out, const __FlashStringHelper* text)
|
||||
Stream& operator<<(Stream& out, const __FlashStringHelper* text)
|
||||
{
|
||||
StreamConstPtr(text).sendAll(out);
|
||||
return out;
|
||||
|
@ -35,16 +35,9 @@
|
||||
class S2Stream: public Stream
|
||||
{
|
||||
public:
|
||||
S2Stream(String& string, int peekPointer = -1) : string(&string), peekPointer(peekPointer) { }
|
||||
|
||||
S2Stream(String& string, int peekPointer = -1):
|
||||
string(&string), peekPointer(peekPointer)
|
||||
{
|
||||
}
|
||||
|
||||
S2Stream(String* string, int peekPointer = -1):
|
||||
string(string), peekPointer(peekPointer)
|
||||
{
|
||||
}
|
||||
S2Stream(String* string, int peekPointer = -1) : string(string), peekPointer(peekPointer) { }
|
||||
|
||||
virtual int available() override
|
||||
{
|
||||
@ -207,18 +200,15 @@ public:
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
String* string;
|
||||
int peekPointer; // -1:String is consumed / >=0:resettable pointer
|
||||
int peekPointer; // -1:String is consumed / >=0:resettable pointer
|
||||
};
|
||||
|
||||
|
||||
// StreamString is a S2Stream holding the String
|
||||
|
||||
class StreamString: public String, public S2Stream
|
||||
{
|
||||
protected:
|
||||
|
||||
void resetpp()
|
||||
{
|
||||
if (peekPointer > 0)
|
||||
@ -228,55 +218,68 @@ protected:
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
StreamString(StreamString&& bro): String(bro), S2Stream(this) { }
|
||||
StreamString(const StreamString& bro): String(bro), S2Stream(this) { }
|
||||
StreamString(StreamString&& bro) : String(bro), S2Stream(this) { }
|
||||
StreamString(const StreamString& bro) : String(bro), S2Stream(this) { }
|
||||
|
||||
// duplicate String constructors and operator=:
|
||||
|
||||
StreamString(const char* text = nullptr): String(text), S2Stream(this) { }
|
||||
StreamString(const String& string): String(string), S2Stream(this) { }
|
||||
StreamString(const __FlashStringHelper *str): String(str), S2Stream(this) { }
|
||||
StreamString(String&& string): String(string), S2Stream(this) { }
|
||||
StreamString(const char* text = nullptr) : String(text), S2Stream(this) { }
|
||||
StreamString(const String& string) : String(string), S2Stream(this) { }
|
||||
StreamString(const __FlashStringHelper* str) : String(str), S2Stream(this) { }
|
||||
StreamString(String&& string) : String(string), S2Stream(this) { }
|
||||
|
||||
explicit StreamString(char c): String(c), S2Stream(this) { }
|
||||
explicit StreamString(unsigned char c, unsigned char base = 10): String(c, base), S2Stream(this) { }
|
||||
explicit StreamString(int i, unsigned char base = 10): String(i, base), S2Stream(this) { }
|
||||
explicit StreamString(unsigned int i, unsigned char base = 10): String(i, base), S2Stream(this) { }
|
||||
explicit StreamString(long l, unsigned char base = 10): String(l, base), S2Stream(this) { }
|
||||
explicit StreamString(unsigned long l, unsigned char base = 10): String(l, base), S2Stream(this) { }
|
||||
explicit StreamString(float f, unsigned char decimalPlaces = 2): String(f, decimalPlaces), S2Stream(this) { }
|
||||
explicit StreamString(double d, unsigned char decimalPlaces = 2): String(d, decimalPlaces), S2Stream(this) { }
|
||||
explicit StreamString(char c) : String(c), S2Stream(this) { }
|
||||
explicit StreamString(unsigned char c, unsigned char base = 10) :
|
||||
String(c, base), S2Stream(this)
|
||||
{
|
||||
}
|
||||
explicit StreamString(int i, unsigned char base = 10) : String(i, base), S2Stream(this) { }
|
||||
explicit StreamString(unsigned int i, unsigned char base = 10) : String(i, base), S2Stream(this)
|
||||
{
|
||||
}
|
||||
explicit StreamString(long l, unsigned char base = 10) : String(l, base), S2Stream(this) { }
|
||||
explicit StreamString(unsigned long l, unsigned char base = 10) :
|
||||
String(l, base), S2Stream(this)
|
||||
{
|
||||
}
|
||||
explicit StreamString(float f, unsigned char decimalPlaces = 2) :
|
||||
String(f, decimalPlaces), S2Stream(this)
|
||||
{
|
||||
}
|
||||
explicit StreamString(double d, unsigned char decimalPlaces = 2) :
|
||||
String(d, decimalPlaces), S2Stream(this)
|
||||
{
|
||||
}
|
||||
|
||||
StreamString& operator= (const StreamString& rhs)
|
||||
StreamString& operator=(const StreamString& rhs)
|
||||
{
|
||||
String::operator=(rhs);
|
||||
resetpp();
|
||||
return *this;
|
||||
}
|
||||
|
||||
StreamString& operator= (const String& rhs)
|
||||
StreamString& operator=(const String& rhs)
|
||||
{
|
||||
String::operator=(rhs);
|
||||
resetpp();
|
||||
return *this;
|
||||
}
|
||||
|
||||
StreamString& operator= (const char* cstr)
|
||||
StreamString& operator=(const char* cstr)
|
||||
{
|
||||
String::operator=(cstr);
|
||||
resetpp();
|
||||
return *this;
|
||||
}
|
||||
|
||||
StreamString& operator= (const __FlashStringHelper* str)
|
||||
StreamString& operator=(const __FlashStringHelper* str)
|
||||
{
|
||||
String::operator=(str);
|
||||
resetpp();
|
||||
return *this;
|
||||
}
|
||||
|
||||
StreamString& operator= (String&& rval)
|
||||
StreamString& operator=(String&& rval)
|
||||
{
|
||||
String::operator=(rval);
|
||||
resetpp();
|
||||
@ -284,4 +287,4 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
#endif // __STREAMSTRING_H
|
||||
#endif // __STREAMSTRING_H
|
||||
|
@ -24,9 +24,8 @@
|
||||
#include "wiring_private.h"
|
||||
#include "PolledTimeout.h"
|
||||
|
||||
|
||||
|
||||
extern "C" {
|
||||
extern "C"
|
||||
{
|
||||
#include "twi_util.h"
|
||||
#include "ets_sys.h"
|
||||
};
|
||||
@ -57,78 +56,113 @@ static inline __attribute__((always_inline)) bool SCL_READ(const int twi_scl)
|
||||
return (GPI & (1 << twi_scl)) != 0;
|
||||
}
|
||||
|
||||
|
||||
// Implement as a class to reduce code size by allowing access to many global variables with a single base pointer
|
||||
// Implement as a class to reduce code size by allowing access to many global variables with a
|
||||
// single base pointer
|
||||
class Twi
|
||||
{
|
||||
private:
|
||||
unsigned int preferred_si2c_clock = 100000;
|
||||
uint32_t twi_dcount = 18;
|
||||
unsigned char twi_sda = 0;
|
||||
unsigned char twi_scl = 0;
|
||||
unsigned char twi_addr = 0;
|
||||
uint32_t twi_clockStretchLimit = 0;
|
||||
unsigned int preferred_si2c_clock = 100000;
|
||||
uint32_t twi_dcount = 18;
|
||||
unsigned char twi_sda = 0;
|
||||
unsigned char twi_scl = 0;
|
||||
unsigned char twi_addr = 0;
|
||||
uint32_t twi_clockStretchLimit = 0;
|
||||
|
||||
// These are int-wide, even though they could all fit in a byte, to reduce code size and avoid any potential
|
||||
// issues about RmW on packed bytes. The int-wide variations of asm instructions are smaller than the equivalent
|
||||
// byte-wide ones, and since these emums are used everywhere, the difference adds up fast. There is only a single
|
||||
// instance of the class, though, so the extra 12 bytes of RAM used here saves a lot more IRAM.
|
||||
volatile enum { TWIPM_UNKNOWN = 0, TWIPM_IDLE, TWIPM_ADDRESSED, TWIPM_WAIT} twip_mode = TWIPM_IDLE;
|
||||
volatile enum { TWIP_UNKNOWN = 0, TWIP_IDLE, TWIP_START, TWIP_SEND_ACK, TWIP_WAIT_ACK, TWIP_WAIT_STOP, TWIP_SLA_W, TWIP_SLA_R, TWIP_REP_START, TWIP_READ, TWIP_STOP, TWIP_REC_ACK, TWIP_READ_ACK, TWIP_RWAIT_ACK, TWIP_WRITE, TWIP_BUS_ERR } twip_state = TWIP_IDLE;
|
||||
// These are int-wide, even though they could all fit in a byte, to reduce code size and avoid
|
||||
// any potential issues about RmW on packed bytes. The int-wide variations of asm instructions
|
||||
// are smaller than the equivalent byte-wide ones, and since these emums are used everywhere,
|
||||
// the difference adds up fast. There is only a single instance of the class, though, so the
|
||||
// extra 12 bytes of RAM used here saves a lot more IRAM.
|
||||
volatile enum {
|
||||
TWIPM_UNKNOWN = 0,
|
||||
TWIPM_IDLE,
|
||||
TWIPM_ADDRESSED,
|
||||
TWIPM_WAIT
|
||||
} twip_mode
|
||||
= TWIPM_IDLE;
|
||||
volatile enum {
|
||||
TWIP_UNKNOWN = 0,
|
||||
TWIP_IDLE,
|
||||
TWIP_START,
|
||||
TWIP_SEND_ACK,
|
||||
TWIP_WAIT_ACK,
|
||||
TWIP_WAIT_STOP,
|
||||
TWIP_SLA_W,
|
||||
TWIP_SLA_R,
|
||||
TWIP_REP_START,
|
||||
TWIP_READ,
|
||||
TWIP_STOP,
|
||||
TWIP_REC_ACK,
|
||||
TWIP_READ_ACK,
|
||||
TWIP_RWAIT_ACK,
|
||||
TWIP_WRITE,
|
||||
TWIP_BUS_ERR
|
||||
} twip_state
|
||||
= TWIP_IDLE;
|
||||
volatile int twip_status = TW_NO_INFO;
|
||||
volatile int bitCount = 0;
|
||||
volatile int bitCount = 0;
|
||||
|
||||
volatile uint8_t twi_data = 0x00;
|
||||
volatile int twi_ack = 0;
|
||||
volatile int twi_ack_rec = 0;
|
||||
volatile int twi_timeout_ms = 10;
|
||||
volatile uint8_t twi_data = 0x00;
|
||||
volatile int twi_ack = 0;
|
||||
volatile int twi_ack_rec = 0;
|
||||
volatile int twi_timeout_ms = 10;
|
||||
|
||||
volatile enum { TWI_READY = 0, TWI_MRX, TWI_MTX, TWI_SRX, TWI_STX } twi_state = TWI_READY;
|
||||
volatile uint8_t twi_error = 0xFF;
|
||||
volatile uint8_t twi_error = 0xFF;
|
||||
|
||||
uint8_t twi_txBuffer[TWI_BUFFER_LENGTH];
|
||||
volatile int twi_txBufferIndex = 0;
|
||||
uint8_t twi_txBuffer[TWI_BUFFER_LENGTH];
|
||||
volatile int twi_txBufferIndex = 0;
|
||||
volatile int twi_txBufferLength = 0;
|
||||
|
||||
uint8_t twi_rxBuffer[TWI_BUFFER_LENGTH];
|
||||
uint8_t twi_rxBuffer[TWI_BUFFER_LENGTH];
|
||||
volatile int twi_rxBufferIndex = 0;
|
||||
|
||||
void (*twi_onSlaveTransmit)(void);
|
||||
void (*twi_onSlaveReceive)(uint8_t*, size_t);
|
||||
|
||||
// ETS queue/timer interfaces
|
||||
enum { EVENTTASK_QUEUE_SIZE = 1, EVENTTASK_QUEUE_PRIO = 2 };
|
||||
enum { TWI_SIG_RANGE = 0x00000100, TWI_SIG_RX = 0x00000101, TWI_SIG_TX = 0x00000102 };
|
||||
enum
|
||||
{
|
||||
EVENTTASK_QUEUE_SIZE = 1,
|
||||
EVENTTASK_QUEUE_PRIO = 2
|
||||
};
|
||||
enum
|
||||
{
|
||||
TWI_SIG_RANGE = 0x00000100,
|
||||
TWI_SIG_RX = 0x00000101,
|
||||
TWI_SIG_TX = 0x00000102
|
||||
};
|
||||
ETSEvent eventTaskQueue[EVENTTASK_QUEUE_SIZE];
|
||||
ETSTimer timer;
|
||||
|
||||
// Event/IRQ callbacks, so they can't use "this" and need to be static
|
||||
static void IRAM_ATTR onSclChange(void);
|
||||
static void IRAM_ATTR onSdaChange(void);
|
||||
static void eventTask(ETSEvent *e);
|
||||
static void IRAM_ATTR onTimer(void *unused);
|
||||
static void eventTask(ETSEvent* e);
|
||||
static void IRAM_ATTR onTimer(void* unused);
|
||||
|
||||
// Allow not linking in the slave code if there is no call to setAddress
|
||||
bool _slaveEnabled = false;
|
||||
|
||||
// Internal use functions
|
||||
void IRAM_ATTR busywait(unsigned int v);
|
||||
bool write_start(void);
|
||||
bool write_stop(void);
|
||||
bool write_bit(bool bit);
|
||||
bool read_bit(void);
|
||||
bool write_byte(unsigned char byte);
|
||||
unsigned char read_byte(bool nack);
|
||||
bool write_start(void);
|
||||
bool write_stop(void);
|
||||
bool write_bit(bool bit);
|
||||
bool read_bit(void);
|
||||
bool write_byte(unsigned char byte);
|
||||
unsigned char read_byte(bool nack);
|
||||
void IRAM_ATTR onTwipEvent(uint8_t status);
|
||||
|
||||
// Handle the case where a slave needs to stretch the clock with a time-limited busy wait
|
||||
inline void WAIT_CLOCK_STRETCH()
|
||||
{
|
||||
esp8266::polledTimeout::oneShotFastUs timeout(twi_clockStretchLimit);
|
||||
esp8266::polledTimeout::oneShotFastUs timeout(twi_clockStretchLimit);
|
||||
esp8266::polledTimeout::periodicFastUs yieldTimeout(5000);
|
||||
while (!timeout && !SCL_READ(twi_scl)) // outer loop is stretch duration up to stretch limit
|
||||
while (!timeout
|
||||
&& !SCL_READ(twi_scl)) // outer loop is stretch duration up to stretch limit
|
||||
{
|
||||
if (yieldTimeout) // inner loop yields every 5ms
|
||||
if (yieldTimeout) // inner loop yields every 5ms
|
||||
{
|
||||
yield();
|
||||
}
|
||||
@ -139,19 +173,21 @@ private:
|
||||
void twi_scl_valley(void);
|
||||
|
||||
public:
|
||||
void setClock(unsigned int freq);
|
||||
void setClockStretchLimit(uint32_t limit);
|
||||
void init(unsigned char sda, unsigned char scl);
|
||||
void setAddress(uint8_t address);
|
||||
unsigned char writeTo(unsigned char address, unsigned char * buf, unsigned int len, unsigned char sendStop);
|
||||
unsigned char readFrom(unsigned char address, unsigned char* buf, unsigned int len, unsigned char sendStop);
|
||||
uint8_t status();
|
||||
uint8_t transmit(const uint8_t* data, uint8_t length);
|
||||
void attachSlaveRxEvent(void (*function)(uint8_t*, size_t));
|
||||
void attachSlaveTxEvent(void (*function)(void));
|
||||
void setClock(unsigned int freq);
|
||||
void setClockStretchLimit(uint32_t limit);
|
||||
void init(unsigned char sda, unsigned char scl);
|
||||
void setAddress(uint8_t address);
|
||||
unsigned char writeTo(unsigned char address, unsigned char* buf, unsigned int len,
|
||||
unsigned char sendStop);
|
||||
unsigned char readFrom(unsigned char address, unsigned char* buf, unsigned int len,
|
||||
unsigned char sendStop);
|
||||
uint8_t status();
|
||||
uint8_t transmit(const uint8_t* data, uint8_t length);
|
||||
void attachSlaveRxEvent(void (*function)(uint8_t*, size_t));
|
||||
void attachSlaveTxEvent(void (*function)(void));
|
||||
void IRAM_ATTR reply(uint8_t ack);
|
||||
void IRAM_ATTR releaseBus(void);
|
||||
void enableSlave();
|
||||
void enableSlave();
|
||||
};
|
||||
|
||||
static Twi twi;
|
||||
@ -176,7 +212,8 @@ void Twi::setClock(unsigned int freq)
|
||||
freq = 400000;
|
||||
}
|
||||
twi_dcount = (500000000 / freq); // half-cycle period in ns
|
||||
twi_dcount = (1000 * (twi_dcount - 1120)) / 62500; // (half cycle - overhead) / busywait loop time
|
||||
twi_dcount
|
||||
= (1000 * (twi_dcount - 1120)) / 62500; // (half cycle - overhead) / busywait loop time
|
||||
|
||||
#else
|
||||
|
||||
@ -185,7 +222,8 @@ void Twi::setClock(unsigned int freq)
|
||||
freq = 800000;
|
||||
}
|
||||
twi_dcount = (500000000 / freq); // half-cycle period in ns
|
||||
twi_dcount = (1000 * (twi_dcount - 560)) / 31250; // (half cycle - overhead) / busywait loop time
|
||||
twi_dcount
|
||||
= (1000 * (twi_dcount - 560)) / 31250; // (half cycle - overhead) / busywait loop time
|
||||
|
||||
#endif
|
||||
}
|
||||
@ -195,8 +233,6 @@ void Twi::setClockStretchLimit(uint32_t limit)
|
||||
twi_clockStretchLimit = limit;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Twi::init(unsigned char sda, unsigned char scl)
|
||||
{
|
||||
// set timer function
|
||||
@ -210,7 +246,7 @@ void Twi::init(unsigned char sda, unsigned char scl)
|
||||
pinMode(twi_sda, INPUT_PULLUP);
|
||||
pinMode(twi_scl, INPUT_PULLUP);
|
||||
twi_setClock(preferred_si2c_clock);
|
||||
twi_setClockStretchLimit(150000L); // default value is 150 mS
|
||||
twi_setClockStretchLimit(150000L); // default value is 150 mS
|
||||
}
|
||||
|
||||
void Twi::setAddress(uint8_t address)
|
||||
@ -234,7 +270,8 @@ void IRAM_ATTR Twi::busywait(unsigned int v)
|
||||
unsigned int i;
|
||||
for (i = 0; i < v; i++) // loop time is 5 machine cycles: 31.25ns @ 160MHz, 62.5ns @ 80MHz
|
||||
{
|
||||
__asm__ __volatile__("nop"); // minimum element to keep GCC from optimizing this function out.
|
||||
__asm__ __volatile__(
|
||||
"nop"); // minimum element to keep GCC from optimizing this function out.
|
||||
}
|
||||
}
|
||||
|
||||
@ -250,7 +287,8 @@ bool Twi::write_start(void)
|
||||
// A high-to-low transition on the SDA line while the SCL is high defines a START condition.
|
||||
SDA_LOW(twi_sda);
|
||||
busywait(twi_dcount);
|
||||
// An additional delay between the SCL line high-to-low transition and setting up the SDA line to prevent a STOP condition execute.
|
||||
// An additional delay between the SCL line high-to-low transition and setting up the SDA line
|
||||
// to prevent a STOP condition execute.
|
||||
SCL_LOW(twi_scl);
|
||||
busywait(twi_dcount);
|
||||
return true;
|
||||
@ -308,7 +346,7 @@ bool Twi::write_byte(unsigned char byte)
|
||||
write_bit(byte & 0x80);
|
||||
byte <<= 1;
|
||||
}
|
||||
return !read_bit();//NACK/ACK
|
||||
return !read_bit(); // NACK/ACK
|
||||
}
|
||||
|
||||
unsigned char Twi::read_byte(bool nack)
|
||||
@ -323,12 +361,13 @@ unsigned char Twi::read_byte(bool nack)
|
||||
return byte;
|
||||
}
|
||||
|
||||
unsigned char Twi::writeTo(unsigned char address, unsigned char * buf, unsigned int len, unsigned char sendStop)
|
||||
unsigned char Twi::writeTo(unsigned char address, unsigned char* buf, unsigned int len,
|
||||
unsigned char sendStop)
|
||||
{
|
||||
unsigned int i;
|
||||
if (!write_start())
|
||||
{
|
||||
return 4; //line busy
|
||||
return 4; // line busy
|
||||
}
|
||||
if (!write_byte(((address << 1) | 0) & 0xFF))
|
||||
{
|
||||
@ -336,7 +375,7 @@ unsigned char Twi::writeTo(unsigned char address, unsigned char * buf, unsigned
|
||||
{
|
||||
write_stop();
|
||||
}
|
||||
return 2; //received NACK on transmit of address
|
||||
return 2; // received NACK on transmit of address
|
||||
}
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
@ -346,7 +385,7 @@ unsigned char Twi::writeTo(unsigned char address, unsigned char * buf, unsigned
|
||||
{
|
||||
write_stop();
|
||||
}
|
||||
return 3;//received NACK on transmit of data
|
||||
return 3; // received NACK on transmit of data
|
||||
}
|
||||
}
|
||||
if (sendStop)
|
||||
@ -368,12 +407,13 @@ unsigned char Twi::writeTo(unsigned char address, unsigned char * buf, unsigned
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned char Twi::readFrom(unsigned char address, unsigned char* buf, unsigned int len, unsigned char sendStop)
|
||||
unsigned char Twi::readFrom(unsigned char address, unsigned char* buf, unsigned int len,
|
||||
unsigned char sendStop)
|
||||
{
|
||||
unsigned int i;
|
||||
if (!write_start())
|
||||
{
|
||||
return 4; //line busy
|
||||
return 4; // line busy
|
||||
}
|
||||
if (!write_byte(((address << 1) | 1) & 0xFF))
|
||||
{
|
||||
@ -381,7 +421,7 @@ unsigned char Twi::readFrom(unsigned char address, unsigned char* buf, unsigned
|
||||
{
|
||||
write_stop();
|
||||
}
|
||||
return 2;//received NACK on transmit of address
|
||||
return 2; // received NACK on transmit of address
|
||||
}
|
||||
for (i = 0; i < (len - 1); i++)
|
||||
{
|
||||
@ -420,21 +460,25 @@ uint8_t Twi::status()
|
||||
WAIT_CLOCK_STRETCH(); // wait for a slow slave to finish
|
||||
if (!SCL_READ(twi_scl))
|
||||
{
|
||||
return I2C_SCL_HELD_LOW; // SCL held low by another device, no procedure available to recover
|
||||
return I2C_SCL_HELD_LOW; // SCL held low by another device, no procedure available to
|
||||
// recover
|
||||
}
|
||||
|
||||
int clockCount = 20;
|
||||
while (!SDA_READ(twi_sda) && clockCount-- > 0) // if SDA low, read the bits slaves have to sent to a max
|
||||
while (!SDA_READ(twi_sda)
|
||||
&& clockCount-- > 0) // if SDA low, read the bits slaves have to sent to a max
|
||||
{
|
||||
read_bit();
|
||||
if (!SCL_READ(twi_scl))
|
||||
{
|
||||
return I2C_SCL_HELD_LOW_AFTER_READ; // I2C bus error. SCL held low beyond slave clock stretch time
|
||||
return I2C_SCL_HELD_LOW_AFTER_READ; // I2C bus error. SCL held low beyond slave clock
|
||||
// stretch time
|
||||
}
|
||||
}
|
||||
if (!SDA_READ(twi_sda))
|
||||
{
|
||||
return I2C_SDA_HELD_LOW; // I2C bus error. SDA line held low by slave/another_master after n bits.
|
||||
return I2C_SDA_HELD_LOW; // I2C bus error. SDA line held low by slave/another_master after
|
||||
// n bits.
|
||||
}
|
||||
|
||||
return I2C_OK;
|
||||
@ -476,58 +520,57 @@ void Twi::attachSlaveTxEvent(void (*function)(void))
|
||||
twi_onSlaveTransmit = function;
|
||||
}
|
||||
|
||||
// DO NOT INLINE, inlining reply() in combination with compiler optimizations causes function breakup into
|
||||
// parts and the IRAM_ATTR isn't propagated correctly to all parts, which of course causes crashes.
|
||||
// DO NOT INLINE, inlining reply() in combination with compiler optimizations causes function
|
||||
// breakup into parts and the IRAM_ATTR isn't propagated correctly to all parts, which of course
|
||||
// causes crashes.
|
||||
// TODO: test with gcc 9.x and if it still fails, disable optimization with -fdisable-ipa-fnsplit
|
||||
void IRAM_ATTR Twi::reply(uint8_t ack)
|
||||
{
|
||||
// transmit master read ready signal, with or without ack
|
||||
if (ack)
|
||||
{
|
||||
//TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWINT) | _BV(TWEA);
|
||||
SCL_HIGH(twi.twi_scl); // _BV(TWINT)
|
||||
twi_ack = 1; // _BV(TWEA)
|
||||
// TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWINT) | _BV(TWEA);
|
||||
SCL_HIGH(twi.twi_scl); // _BV(TWINT)
|
||||
twi_ack = 1; // _BV(TWEA)
|
||||
}
|
||||
else
|
||||
{
|
||||
//TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWINT);
|
||||
SCL_HIGH(twi.twi_scl); // _BV(TWINT)
|
||||
twi_ack = 0; // ~_BV(TWEA)
|
||||
// TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWINT);
|
||||
SCL_HIGH(twi.twi_scl); // _BV(TWINT)
|
||||
twi_ack = 0; // ~_BV(TWEA)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void IRAM_ATTR Twi::releaseBus(void)
|
||||
{
|
||||
// release bus
|
||||
//TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT);
|
||||
SCL_HIGH(twi.twi_scl); // _BV(TWINT)
|
||||
twi_ack = 1; // _BV(TWEA)
|
||||
// TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT);
|
||||
SCL_HIGH(twi.twi_scl); // _BV(TWINT)
|
||||
twi_ack = 1; // _BV(TWEA)
|
||||
SDA_HIGH(twi.twi_sda);
|
||||
|
||||
// update twi state
|
||||
twi_state = TWI_READY;
|
||||
}
|
||||
|
||||
|
||||
void IRAM_ATTR Twi::onTwipEvent(uint8_t status)
|
||||
{
|
||||
twip_status = status;
|
||||
switch (status)
|
||||
{
|
||||
// Slave Receiver
|
||||
case TW_SR_SLA_ACK: // addressed, returned ack
|
||||
case TW_SR_GCALL_ACK: // addressed generally, returned ack
|
||||
case TW_SR_ARB_LOST_SLA_ACK: // lost arbitration, returned ack
|
||||
case TW_SR_ARB_LOST_GCALL_ACK: // lost arbitration, returned ack
|
||||
case TW_SR_SLA_ACK: // addressed, returned ack
|
||||
case TW_SR_GCALL_ACK: // addressed generally, returned ack
|
||||
case TW_SR_ARB_LOST_SLA_ACK: // lost arbitration, returned ack
|
||||
case TW_SR_ARB_LOST_GCALL_ACK: // lost arbitration, returned ack
|
||||
// enter slave receiver mode
|
||||
twi_state = TWI_SRX;
|
||||
// indicate that rx buffer can be overwritten and ack
|
||||
twi_rxBufferIndex = 0;
|
||||
reply(1);
|
||||
break;
|
||||
case TW_SR_DATA_ACK: // data received, returned ack
|
||||
case TW_SR_GCALL_DATA_ACK: // data received generally, returned ack
|
||||
case TW_SR_DATA_ACK: // data received, returned ack
|
||||
case TW_SR_GCALL_DATA_ACK: // data received generally, returned ack
|
||||
// if there is still room in the rx buffer
|
||||
if (twi_rxBufferIndex < TWI_BUFFER_LENGTH)
|
||||
{
|
||||
@ -541,29 +584,29 @@ void IRAM_ATTR Twi::onTwipEvent(uint8_t status)
|
||||
reply(0);
|
||||
}
|
||||
break;
|
||||
case TW_SR_STOP: // stop or repeated start condition received
|
||||
case TW_SR_STOP: // stop or repeated start condition received
|
||||
// put a null char after data if there's room
|
||||
if (twi_rxBufferIndex < TWI_BUFFER_LENGTH)
|
||||
{
|
||||
twi_rxBuffer[twi_rxBufferIndex] = '\0';
|
||||
}
|
||||
// callback to user-defined callback over event task to allow for non-RAM-residing code
|
||||
//twi_rxBufferLock = true; // This may be necessary
|
||||
// twi_rxBufferLock = true; // This may be necessary
|
||||
ets_post(EVENTTASK_QUEUE_PRIO, TWI_SIG_RX, twi_rxBufferIndex);
|
||||
|
||||
// since we submit rx buffer to "wire" library, we can reset it
|
||||
twi_rxBufferIndex = 0;
|
||||
break;
|
||||
|
||||
case TW_SR_DATA_NACK: // data received, returned nack
|
||||
case TW_SR_GCALL_DATA_NACK: // data received generally, returned nack
|
||||
case TW_SR_DATA_NACK: // data received, returned nack
|
||||
case TW_SR_GCALL_DATA_NACK: // data received generally, returned nack
|
||||
// nack back at master
|
||||
reply(0);
|
||||
break;
|
||||
|
||||
// Slave Transmitter
|
||||
case TW_ST_SLA_ACK: // addressed, returned ack
|
||||
case TW_ST_ARB_LOST_SLA_ACK: // arbitration lost, returned ack
|
||||
case TW_ST_SLA_ACK: // addressed, returned ack
|
||||
case TW_ST_ARB_LOST_SLA_ACK: // arbitration lost, returned ack
|
||||
// enter slave transmitter mode
|
||||
twi_state = TWI_STX;
|
||||
// ready the tx buffer index for iteration
|
||||
@ -576,7 +619,7 @@ void IRAM_ATTR Twi::onTwipEvent(uint8_t status)
|
||||
ets_post(EVENTTASK_QUEUE_PRIO, TWI_SIG_TX, 0);
|
||||
break;
|
||||
|
||||
case TW_ST_DATA_ACK: // byte sent, ack returned
|
||||
case TW_ST_DATA_ACK: // byte sent, ack returned
|
||||
// copy data to output register
|
||||
twi_data = twi_txBuffer[twi_txBufferIndex++];
|
||||
|
||||
@ -602,33 +645,32 @@ void IRAM_ATTR Twi::onTwipEvent(uint8_t status)
|
||||
reply(0);
|
||||
}
|
||||
break;
|
||||
case TW_ST_DATA_NACK: // received nack, we are done
|
||||
case TW_ST_LAST_DATA: // received ack, but we are done already!
|
||||
case TW_ST_DATA_NACK: // received nack, we are done
|
||||
case TW_ST_LAST_DATA: // received ack, but we are done already!
|
||||
// leave slave receiver state
|
||||
releaseBus();
|
||||
break;
|
||||
|
||||
// All
|
||||
case TW_NO_INFO: // no state information
|
||||
case TW_NO_INFO: // no state information
|
||||
break;
|
||||
case TW_BUS_ERROR: // bus error, illegal stop/start
|
||||
case TW_BUS_ERROR: // bus error, illegal stop/start
|
||||
twi_error = TW_BUS_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void IRAM_ATTR Twi::onTimer(void *unused)
|
||||
void IRAM_ATTR Twi::onTimer(void* unused)
|
||||
{
|
||||
(void)unused;
|
||||
twi.releaseBus();
|
||||
twi.onTwipEvent(TW_BUS_ERROR);
|
||||
twi.twip_mode = TWIPM_WAIT;
|
||||
twi.twip_mode = TWIPM_WAIT;
|
||||
twi.twip_state = TWIP_BUS_ERR;
|
||||
}
|
||||
|
||||
void Twi::eventTask(ETSEvent *e)
|
||||
void Twi::eventTask(ETSEvent* e)
|
||||
{
|
||||
|
||||
if (e == NULL)
|
||||
{
|
||||
return;
|
||||
@ -643,7 +685,7 @@ void Twi::eventTask(ETSEvent *e)
|
||||
if (twi.twi_txBufferLength == 0)
|
||||
{
|
||||
twi.twi_txBufferLength = 1;
|
||||
twi.twi_txBuffer[0] = 0x00;
|
||||
twi.twi_txBuffer[0] = 0x00;
|
||||
}
|
||||
|
||||
// Initiate transmission
|
||||
@ -663,7 +705,7 @@ void Twi::eventTask(ETSEvent *e)
|
||||
// compared to the logical-or of all states with the same branch. This removes the need
|
||||
// for a large series of straight-line compares. The biggest win is when multiple states
|
||||
// all have the same branch (onSdaChange), but for others there is some benefit, still.
|
||||
#define S2M(x) (1<<(x))
|
||||
#define S2M(x) (1 << (x))
|
||||
// Shorthand for if the state is any of the or'd bitmask x
|
||||
#define IFSTATE(x) if (twip_state_mask & (x))
|
||||
|
||||
@ -677,7 +719,7 @@ void IRAM_ATTR Twi::onSclChange(void)
|
||||
sda = SDA_READ(twi.twi_sda);
|
||||
scl = SCL_READ(twi.twi_scl);
|
||||
|
||||
twi.twip_status = 0xF8; // reset TWI status
|
||||
twi.twip_status = 0xF8; // reset TWI status
|
||||
|
||||
int twip_state_mask = S2M(twi.twip_state);
|
||||
IFSTATE(S2M(TWIP_START) | S2M(TWIP_REP_START) | S2M(TWIP_SLA_W) | S2M(TWIP_READ))
|
||||
@ -752,13 +794,13 @@ void IRAM_ATTR Twi::onSclChange(void)
|
||||
}
|
||||
else
|
||||
{
|
||||
SCL_LOW(twi.twi_scl); // clock stretching
|
||||
SCL_LOW(twi.twi_scl); // clock stretching
|
||||
SDA_HIGH(twi.twi_sda);
|
||||
twi.twip_mode = TWIPM_ADDRESSED;
|
||||
if (!(twi.twi_data & 0x01))
|
||||
{
|
||||
twi.onTwipEvent(TW_SR_SLA_ACK);
|
||||
twi.bitCount = 8;
|
||||
twi.bitCount = 8;
|
||||
twi.twip_state = TWIP_SLA_W;
|
||||
}
|
||||
else
|
||||
@ -770,18 +812,18 @@ void IRAM_ATTR Twi::onSclChange(void)
|
||||
}
|
||||
else
|
||||
{
|
||||
SCL_LOW(twi.twi_scl); // clock stretching
|
||||
SCL_LOW(twi.twi_scl); // clock stretching
|
||||
SDA_HIGH(twi.twi_sda);
|
||||
if (!twi.twi_ack)
|
||||
{
|
||||
twi.onTwipEvent(TW_SR_DATA_NACK);
|
||||
twi.twip_mode = TWIPM_WAIT;
|
||||
twi.twip_mode = TWIPM_WAIT;
|
||||
twi.twip_state = TWIP_WAIT_STOP;
|
||||
}
|
||||
else
|
||||
{
|
||||
twi.onTwipEvent(TW_SR_DATA_ACK);
|
||||
twi.bitCount = 8;
|
||||
twi.bitCount = 8;
|
||||
twi.twip_state = TWIP_READ;
|
||||
}
|
||||
}
|
||||
@ -837,7 +879,7 @@ void IRAM_ATTR Twi::onSclChange(void)
|
||||
else
|
||||
{
|
||||
twi.twi_ack_rec = !sda;
|
||||
twi.twip_state = TWIP_RWAIT_ACK;
|
||||
twi.twip_state = TWIP_RWAIT_ACK;
|
||||
}
|
||||
}
|
||||
else IFSTATE(S2M(TWIP_RWAIT_ACK))
|
||||
@ -848,7 +890,7 @@ void IRAM_ATTR Twi::onSclChange(void)
|
||||
}
|
||||
else
|
||||
{
|
||||
SCL_LOW(twi.twi_scl); // clock stretching
|
||||
SCL_LOW(twi.twi_scl); // clock stretching
|
||||
if (twi.twi_ack && twi.twi_ack_rec)
|
||||
{
|
||||
twi.onTwipEvent(TW_ST_DATA_ACK);
|
||||
@ -858,7 +900,7 @@ void IRAM_ATTR Twi::onSclChange(void)
|
||||
{
|
||||
// we have no more data to send and/or the master doesn't want anymore
|
||||
twi.onTwipEvent(twi.twi_ack_rec ? TW_ST_LAST_DATA : TW_ST_DATA_NACK);
|
||||
twi.twip_mode = TWIPM_WAIT;
|
||||
twi.twip_mode = TWIPM_WAIT;
|
||||
twi.twip_state = TWIP_WAIT_STOP;
|
||||
}
|
||||
}
|
||||
@ -875,7 +917,7 @@ void IRAM_ATTR Twi::onSdaChange(void)
|
||||
scl = SCL_READ(twi.twi_scl);
|
||||
|
||||
int twip_state_mask = S2M(twi.twip_state);
|
||||
if (scl) /* !DATA */
|
||||
if (scl) /* !DATA */
|
||||
{
|
||||
IFSTATE(S2M(TWIP_IDLE))
|
||||
{
|
||||
@ -886,17 +928,19 @@ void IRAM_ATTR Twi::onSdaChange(void)
|
||||
else
|
||||
{
|
||||
// START
|
||||
twi.bitCount = 8;
|
||||
twi.bitCount = 8;
|
||||
twi.twip_state = TWIP_START;
|
||||
ets_timer_arm_new(&twi.timer, twi.twi_timeout_ms, false, true); // Once, ms
|
||||
ets_timer_arm_new(&twi.timer, twi.twi_timeout_ms, false, true); // Once, ms
|
||||
}
|
||||
}
|
||||
else IFSTATE(S2M(TWIP_START) | S2M(TWIP_REP_START) | S2M(TWIP_SEND_ACK) | S2M(TWIP_WAIT_ACK) | S2M(TWIP_SLA_R) | S2M(TWIP_REC_ACK) | S2M(TWIP_READ_ACK) | S2M(TWIP_RWAIT_ACK) | S2M(TWIP_WRITE))
|
||||
else IFSTATE(S2M(TWIP_START) | S2M(TWIP_REP_START) | S2M(TWIP_SEND_ACK) | S2M(TWIP_WAIT_ACK)
|
||||
| S2M(TWIP_SLA_R) | S2M(TWIP_REC_ACK) | S2M(TWIP_READ_ACK)
|
||||
| S2M(TWIP_RWAIT_ACK) | S2M(TWIP_WRITE))
|
||||
{
|
||||
// START or STOP
|
||||
SDA_HIGH(twi.twi_sda); // Should not be necessary
|
||||
SDA_HIGH(twi.twi_sda); // Should not be necessary
|
||||
twi.onTwipEvent(TW_BUS_ERROR);
|
||||
twi.twip_mode = TWIPM_WAIT;
|
||||
twi.twip_mode = TWIPM_WAIT;
|
||||
twi.twip_state = TWIP_BUS_ERR;
|
||||
}
|
||||
else IFSTATE(S2M(TWIP_WAIT_STOP) | S2M(TWIP_BUS_ERR))
|
||||
@ -904,10 +948,10 @@ void IRAM_ATTR Twi::onSdaChange(void)
|
||||
if (sda)
|
||||
{
|
||||
// STOP
|
||||
SCL_LOW(twi.twi_scl); // generates a low SCL pulse after STOP
|
||||
SCL_LOW(twi.twi_scl); // generates a low SCL pulse after STOP
|
||||
ets_timer_disarm(&twi.timer);
|
||||
twi.twip_state = TWIP_IDLE;
|
||||
twi.twip_mode = TWIPM_IDLE;
|
||||
twi.twip_mode = TWIPM_IDLE;
|
||||
SCL_HIGH(twi.twi_scl);
|
||||
}
|
||||
else
|
||||
@ -919,9 +963,9 @@ void IRAM_ATTR Twi::onSdaChange(void)
|
||||
}
|
||||
else
|
||||
{
|
||||
twi.bitCount = 8;
|
||||
twi.bitCount = 8;
|
||||
twi.twip_state = TWIP_REP_START;
|
||||
ets_timer_arm_new(&twi.timer, twi.twi_timeout_ms, false, true); // Once, ms
|
||||
ets_timer_arm_new(&twi.timer, twi.twi_timeout_ms, false, true); // Once, ms
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -932,28 +976,28 @@ void IRAM_ATTR Twi::onSdaChange(void)
|
||||
{
|
||||
// inside byte transfer - error
|
||||
twi.onTwipEvent(TW_BUS_ERROR);
|
||||
twi.twip_mode = TWIPM_WAIT;
|
||||
twi.twip_mode = TWIPM_WAIT;
|
||||
twi.twip_state = TWIP_BUS_ERR;
|
||||
}
|
||||
else
|
||||
{
|
||||
// during first bit in byte transfer - ok
|
||||
SCL_LOW(twi.twi_scl); // clock stretching
|
||||
SCL_LOW(twi.twi_scl); // clock stretching
|
||||
twi.onTwipEvent(TW_SR_STOP);
|
||||
if (sda)
|
||||
{
|
||||
// STOP
|
||||
ets_timer_disarm(&twi.timer);
|
||||
twi.twip_state = TWIP_IDLE;
|
||||
twi.twip_mode = TWIPM_IDLE;
|
||||
twi.twip_mode = TWIPM_IDLE;
|
||||
}
|
||||
else
|
||||
{
|
||||
// START
|
||||
twi.bitCount = 8;
|
||||
ets_timer_arm_new(&twi.timer, twi.twi_timeout_ms, false, true); // Once, ms
|
||||
ets_timer_arm_new(&twi.timer, twi.twi_timeout_ms, false, true); // Once, ms
|
||||
twi.twip_state = TWIP_REP_START;
|
||||
twi.twip_mode = TWIPM_IDLE;
|
||||
twi.twip_mode = TWIPM_IDLE;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -961,8 +1005,8 @@ void IRAM_ATTR Twi::onSdaChange(void)
|
||||
}
|
||||
|
||||
// C wrappers for the object, since API is exposed only as C
|
||||
extern "C" {
|
||||
|
||||
extern "C"
|
||||
{
|
||||
void twi_init(unsigned char sda, unsigned char scl)
|
||||
{
|
||||
return twi.init(sda, scl);
|
||||
@ -983,12 +1027,14 @@ extern "C" {
|
||||
twi.setClockStretchLimit(limit);
|
||||
}
|
||||
|
||||
uint8_t twi_writeTo(unsigned char address, unsigned char * buf, unsigned int len, unsigned char sendStop)
|
||||
uint8_t twi_writeTo(unsigned char address, unsigned char* buf, unsigned int len,
|
||||
unsigned char sendStop)
|
||||
{
|
||||
return twi.writeTo(address, buf, len, sendStop);
|
||||
}
|
||||
|
||||
uint8_t twi_readFrom(unsigned char address, unsigned char * buf, unsigned int len, unsigned char sendStop)
|
||||
uint8_t twi_readFrom(unsigned char address, unsigned char* buf, unsigned int len,
|
||||
unsigned char sendStop)
|
||||
{
|
||||
return twi.readFrom(address, buf, len, sendStop);
|
||||
}
|
||||
@ -998,7 +1044,7 @@ extern "C" {
|
||||
return twi.status();
|
||||
}
|
||||
|
||||
uint8_t twi_transmit(const uint8_t * buf, uint8_t len)
|
||||
uint8_t twi_transmit(const uint8_t* buf, uint8_t len)
|
||||
{
|
||||
return twi.transmit(buf, len);
|
||||
}
|
||||
@ -1027,5 +1073,4 @@ extern "C" {
|
||||
{
|
||||
twi.enableSlave();
|
||||
}
|
||||
|
||||
};
|
||||
|
@ -30,7 +30,7 @@ void __iamslow(const char* what)
|
||||
#endif
|
||||
|
||||
IRAM_ATTR
|
||||
void hexdump(const void *mem, uint32_t len, uint8_t cols)
|
||||
void hexdump(const void* mem, uint32_t len, uint8_t cols)
|
||||
{
|
||||
const char* src = (const char*)mem;
|
||||
os_printf("\n[HEXDUMP] Address: %p len: 0x%X (%d)", src, len, len);
|
||||
|
@ -5,44 +5,54 @@
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef DEBUG_ESP_CORE
|
||||
#define DEBUGV(fmt, ...) ::printf((PGM_P)PSTR(fmt), ## __VA_ARGS__)
|
||||
#define DEBUGV(fmt, ...) ::printf((PGM_P)PSTR(fmt), ##__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#ifndef DEBUGV
|
||||
#define DEBUGV(...) do { (void)0; } while (0)
|
||||
#define DEBUGV(...) \
|
||||
do \
|
||||
{ \
|
||||
(void)0; \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" void hexdump(const void *mem, uint32_t len, uint8_t cols = 16);
|
||||
extern "C" void hexdump(const void* mem, uint32_t len, uint8_t cols = 16);
|
||||
#else
|
||||
void hexdump(const void *mem, uint32_t len, uint8_t cols);
|
||||
void hexdump(const void* mem, uint32_t len, uint8_t cols);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
void __unhandled_exception(const char *str) __attribute__((noreturn));
|
||||
void __panic_func(const char* file, int line, const char* func) __attribute__((noreturn));
|
||||
void __unhandled_exception(const char* str) __attribute__((noreturn));
|
||||
void __panic_func(const char* file, int line, const char* func) __attribute__((noreturn));
|
||||
#define panic() __panic_func(PSTR(__FILE__), __LINE__, __func__)
|
||||
|
||||
#ifdef DEBUG_ESP_CORE
|
||||
extern void __iamslow(const char* what);
|
||||
#define IAMSLOW() \
|
||||
do { \
|
||||
static bool once = false; \
|
||||
if (!once) { \
|
||||
once = true; \
|
||||
__iamslow((PGM_P)FPSTR(__FUNCTION__)); \
|
||||
} \
|
||||
extern void __iamslow(const char* what);
|
||||
#define IAMSLOW() \
|
||||
do \
|
||||
{ \
|
||||
static bool once = false; \
|
||||
if (!once) \
|
||||
{ \
|
||||
once = true; \
|
||||
__iamslow((PGM_P)FPSTR(__FUNCTION__)); \
|
||||
} \
|
||||
} while (0)
|
||||
#else
|
||||
#define IAMSLOW() do { (void)0; } while (0)
|
||||
#define IAMSLOW() \
|
||||
do \
|
||||
{ \
|
||||
(void)0; \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif//ARD_DEBUG_H
|
||||
#endif // ARD_DEBUG_H
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
#ifndef STASSID
|
||||
#define STASSID "your-ssid"
|
||||
#define STAPSK "your-password"
|
||||
#define STAPSK "your-password"
|
||||
#endif
|
||||
|
||||
const char* ssid = STASSID;
|
||||
@ -39,7 +39,7 @@ void setup() {
|
||||
String type;
|
||||
if (ArduinoOTA.getCommand() == U_FLASH) {
|
||||
type = "sketch";
|
||||
} else { // U_FS
|
||||
} else { // U_FS
|
||||
type = "filesystem";
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
#ifndef STASSID
|
||||
#define STASSID "your-ssid"
|
||||
#define STAPSK "your-password"
|
||||
#define STAPSK "your-password"
|
||||
#endif
|
||||
|
||||
const char* ssid = STASSID;
|
||||
@ -14,7 +14,7 @@ const char* host = "OTA-LEDS";
|
||||
|
||||
int led_pin = 13;
|
||||
#define N_DIMMERS 3
|
||||
int dimmer_pin[] = {14, 5, 15};
|
||||
int dimmer_pin[] = { 14, 5, 15 };
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
@ -45,14 +45,14 @@ void setup() {
|
||||
}
|
||||
|
||||
ArduinoOTA.setHostname(host);
|
||||
ArduinoOTA.onStart([]() { // switch off all the PWMs during upgrade
|
||||
ArduinoOTA.onStart([]() { // switch off all the PWMs during upgrade
|
||||
for (int i = 0; i < N_DIMMERS; i++) {
|
||||
analogWrite(dimmer_pin[i], 0);
|
||||
}
|
||||
analogWrite(led_pin, 0);
|
||||
});
|
||||
|
||||
ArduinoOTA.onEnd([]() { // do a fancy thing with our board led at end
|
||||
ArduinoOTA.onEnd([]() { // do a fancy thing with our board led at end
|
||||
for (int i = 0; i < 30; i++) {
|
||||
analogWrite(led_pin, (i * 100) % 1001);
|
||||
delay(50);
|
||||
@ -67,7 +67,6 @@ void setup() {
|
||||
/* setup the OTA server */
|
||||
ArduinoOTA.begin();
|
||||
Serial.println("Ready");
|
||||
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
@ -20,7 +20,7 @@
|
||||
/* Set these to your desired softAP credentials. They are not configurable at runtime */
|
||||
#ifndef APSSID
|
||||
#define APSSID "ESP_ap"
|
||||
#define APPSK "12345678"
|
||||
#define APPSK "12345678"
|
||||
#endif
|
||||
|
||||
const char *softAP_ssid = APSSID;
|
||||
@ -62,7 +62,7 @@ void setup() {
|
||||
/* You can remove the password parameter if you want the AP to be open. */
|
||||
WiFi.softAPConfig(apIP, apIP, netMsk);
|
||||
WiFi.softAP(softAP_ssid, softAP_password);
|
||||
delay(500); // Without delay I've seen the IP address blank
|
||||
delay(500); // Without delay I've seen the IP address blank
|
||||
Serial.print("AP IP address: ");
|
||||
Serial.println(WiFi.softAPIP());
|
||||
|
||||
@ -74,13 +74,13 @@ void setup() {
|
||||
server.on("/", handleRoot);
|
||||
server.on("/wifi", handleWifi);
|
||||
server.on("/wifisave", handleWifiSave);
|
||||
server.on("/generate_204", handleRoot); //Android captive portal. Maybe not needed. Might be handled by notFound handler.
|
||||
server.on("/fwlink", handleRoot); //Microsoft captive portal. Maybe not needed. Might be handled by notFound handler.
|
||||
server.on("/generate_204", handleRoot); // Android captive portal. Maybe not needed. Might be handled by notFound handler.
|
||||
server.on("/fwlink", handleRoot); // Microsoft captive portal. Maybe not needed. Might be handled by notFound handler.
|
||||
server.onNotFound(handleNotFound);
|
||||
server.begin(); // Web server start
|
||||
server.begin(); // Web server start
|
||||
Serial.println("HTTP server started");
|
||||
loadCredentials(); // Load WLAN credentials from network
|
||||
connect = strlen(ssid) > 0; // Request WLAN connect if there is a SSID
|
||||
loadCredentials(); // Load WLAN credentials from network
|
||||
connect = strlen(ssid) > 0; // Request WLAN connect if there is a SSID
|
||||
}
|
||||
|
||||
void connectWifi() {
|
||||
@ -106,7 +106,7 @@ void loop() {
|
||||
/* Don't set retry time too low as retry interfere the softAP operation */
|
||||
connect = true;
|
||||
}
|
||||
if (status != s) { // WLAN status change
|
||||
if (status != s) { // WLAN status change
|
||||
Serial.print("Status: ");
|
||||
Serial.println(s);
|
||||
status = s;
|
||||
@ -130,13 +130,11 @@ void loop() {
|
||||
WiFi.disconnect();
|
||||
}
|
||||
}
|
||||
if (s == WL_CONNECTED) {
|
||||
MDNS.update();
|
||||
}
|
||||
if (s == WL_CONNECTED) { MDNS.update(); }
|
||||
}
|
||||
// Do work:
|
||||
//DNS
|
||||
// DNS
|
||||
dnsServer.processNextRequest();
|
||||
//HTTP
|
||||
// HTTP
|
||||
server.handleClient();
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/** Handle root or redirect to captive portal */
|
||||
void handleRoot() {
|
||||
if (captivePortal()) { // If caprive portal redirect instead of displaying the page.
|
||||
if (captivePortal()) { // If caprive portal redirect instead of displaying the page.
|
||||
return;
|
||||
}
|
||||
server.sendHeader("Cache-Control", "no-cache, no-store, must-revalidate");
|
||||
@ -8,8 +8,7 @@ void handleRoot() {
|
||||
server.sendHeader("Expires", "-1");
|
||||
|
||||
String Page;
|
||||
Page += F(
|
||||
"<!DOCTYPE html><html lang='en'><head>"
|
||||
Page += F("<!DOCTYPE html><html lang='en'><head>"
|
||||
"<meta name='viewport' content='width=device-width'>"
|
||||
"<title>CaptivePortal</title></head><body>"
|
||||
"<h1>HELLO WORLD!!</h1>");
|
||||
@ -18,8 +17,7 @@ void handleRoot() {
|
||||
} else {
|
||||
Page += String(F("<p>You are connected through the wifi network: ")) + ssid + F("</p>");
|
||||
}
|
||||
Page += F(
|
||||
"<p>You may want to <a href='/wifi'>config the wifi connection</a>.</p>"
|
||||
Page += F("<p>You may want to <a href='/wifi'>config the wifi connection</a>.</p>"
|
||||
"</body></html>");
|
||||
|
||||
server.send(200, "text/html", Page);
|
||||
@ -30,8 +28,8 @@ boolean captivePortal() {
|
||||
if (!isIp(server.hostHeader()) && server.hostHeader() != (String(myHostname) + ".local")) {
|
||||
Serial.println("Request redirected to captive portal");
|
||||
server.sendHeader("Location", String("http://") + toStringIp(server.client().localIP()), true);
|
||||
server.send(302, "text/plain", ""); // Empty content inhibits Content-length header so we have to close the socket ourselves.
|
||||
server.client().stop(); // Stop is needed because we sent no content length
|
||||
server.send(302, "text/plain", ""); // Empty content inhibits Content-length header so we have to close the socket ourselves.
|
||||
server.client().stop(); // Stop is needed because we sent no content length
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -44,8 +42,7 @@ void handleWifi() {
|
||||
server.sendHeader("Expires", "-1");
|
||||
|
||||
String Page;
|
||||
Page += F(
|
||||
"<!DOCTYPE html><html lang='en'><head>"
|
||||
Page += F("<!DOCTYPE html><html lang='en'><head>"
|
||||
"<meta name='viewport' content='width=device-width'>"
|
||||
"<title>CaptivePortal</title></head><body>"
|
||||
"<h1>Wifi config</h1>");
|
||||
@ -54,40 +51,31 @@ void handleWifi() {
|
||||
} else {
|
||||
Page += String(F("<p>You are connected through the wifi network: ")) + ssid + F("</p>");
|
||||
}
|
||||
Page +=
|
||||
String(F(
|
||||
"\r\n<br />"
|
||||
"<table><tr><th align='left'>SoftAP config</th></tr>"
|
||||
"<tr><td>SSID ")) +
|
||||
String(softAP_ssid) +
|
||||
F("</td></tr>"
|
||||
"<tr><td>IP ") +
|
||||
toStringIp(WiFi.softAPIP()) +
|
||||
F("</td></tr>"
|
||||
"</table>"
|
||||
"\r\n<br />"
|
||||
"<table><tr><th align='left'>WLAN config</th></tr>"
|
||||
"<tr><td>SSID ") +
|
||||
String(ssid) +
|
||||
F("</td></tr>"
|
||||
"<tr><td>IP ") +
|
||||
toStringIp(WiFi.localIP()) +
|
||||
F("</td></tr>"
|
||||
"</table>"
|
||||
"\r\n<br />"
|
||||
"<table><tr><th align='left'>WLAN list (refresh if any missing)</th></tr>");
|
||||
Page += String(F("\r\n<br />"
|
||||
"<table><tr><th align='left'>SoftAP config</th></tr>"
|
||||
"<tr><td>SSID "))
|
||||
+ String(softAP_ssid) + F("</td></tr>"
|
||||
"<tr><td>IP ")
|
||||
+ toStringIp(WiFi.softAPIP()) + F("</td></tr>"
|
||||
"</table>"
|
||||
"\r\n<br />"
|
||||
"<table><tr><th align='left'>WLAN config</th></tr>"
|
||||
"<tr><td>SSID ")
|
||||
+ String(ssid) + F("</td></tr>"
|
||||
"<tr><td>IP ")
|
||||
+ toStringIp(WiFi.localIP()) + F("</td></tr>"
|
||||
"</table>"
|
||||
"\r\n<br />"
|
||||
"<table><tr><th align='left'>WLAN list (refresh if any missing)</th></tr>");
|
||||
Serial.println("scan start");
|
||||
int n = WiFi.scanNetworks();
|
||||
Serial.println("scan done");
|
||||
if (n > 0) {
|
||||
for (int i = 0; i < n; i++) {
|
||||
Page += String(F("\r\n<tr><td>SSID ")) + WiFi.SSID(i) + ((WiFi.encryptionType(i) == ENC_TYPE_NONE) ? F(" ") : F(" *")) + F(" (") + WiFi.RSSI(i) + F(")</td></tr>");
|
||||
}
|
||||
for (int i = 0; i < n; i++) { Page += String(F("\r\n<tr><td>SSID ")) + WiFi.SSID(i) + ((WiFi.encryptionType(i) == ENC_TYPE_NONE) ? F(" ") : F(" *")) + F(" (") + WiFi.RSSI(i) + F(")</td></tr>"); }
|
||||
} else {
|
||||
Page += F("<tr><td>No WLAN found</td></tr>");
|
||||
}
|
||||
Page += F(
|
||||
"</table>"
|
||||
Page += F("</table>"
|
||||
"\r\n<br /><form method='POST' action='wifisave'><h4>Connect to network:</h4>"
|
||||
"<input type='text' placeholder='network' name='n'/>"
|
||||
"<br /><input type='password' placeholder='password' name='p'/>"
|
||||
@ -95,7 +83,7 @@ void handleWifi() {
|
||||
"<p>You may want to <a href='/'>return to the home page</a>.</p>"
|
||||
"</body></html>");
|
||||
server.send(200, "text/html", Page);
|
||||
server.client().stop(); // Stop is needed because we sent no content length
|
||||
server.client().stop(); // Stop is needed because we sent no content length
|
||||
}
|
||||
|
||||
/** Handle the WLAN save form and redirect to WLAN config page again */
|
||||
@ -107,14 +95,14 @@ void handleWifiSave() {
|
||||
server.sendHeader("Cache-Control", "no-cache, no-store, must-revalidate");
|
||||
server.sendHeader("Pragma", "no-cache");
|
||||
server.sendHeader("Expires", "-1");
|
||||
server.send(302, "text/plain", ""); // Empty content inhibits Content-length header so we have to close the socket ourselves.
|
||||
server.client().stop(); // Stop is needed because we sent no content length
|
||||
server.send(302, "text/plain", ""); // Empty content inhibits Content-length header so we have to close the socket ourselves.
|
||||
server.client().stop(); // Stop is needed because we sent no content length
|
||||
saveCredentials();
|
||||
connect = strlen(ssid) > 0; // Request WLAN connect with new credentials if there is a SSID
|
||||
connect = strlen(ssid) > 0; // Request WLAN connect with new credentials if there is a SSID
|
||||
}
|
||||
|
||||
void handleNotFound() {
|
||||
if (captivePortal()) { // If caprive portal redirect instead of displaying the error page.
|
||||
if (captivePortal()) { // If caprive portal redirect instead of displaying the error page.
|
||||
return;
|
||||
}
|
||||
String message = F("File Not Found\n\n");
|
||||
@ -126,9 +114,7 @@ void handleNotFound() {
|
||||
message += server.args();
|
||||
message += F("\n");
|
||||
|
||||
for (uint8_t i = 0; i < server.args(); i++) {
|
||||
message += String(F(" ")) + server.argName(i) + F(": ") + server.arg(i) + F("\n");
|
||||
}
|
||||
for (uint8_t i = 0; i < server.args(); i++) { message += String(F(" ")) + server.argName(i) + F(": ") + server.arg(i) + F("\n"); }
|
||||
server.sendHeader("Cache-Control", "no-cache, no-store, must-revalidate");
|
||||
server.sendHeader("Pragma", "no-cache");
|
||||
server.sendHeader("Expires", "-1");
|
||||
|
@ -2,9 +2,7 @@
|
||||
boolean isIp(String str) {
|
||||
for (size_t i = 0; i < str.length(); i++) {
|
||||
int c = str.charAt(i);
|
||||
if (c != '.' && (c < '0' || c > '9')) {
|
||||
return false;
|
||||
}
|
||||
if (c != '.' && (c < '0' || c > '9')) { return false; }
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -12,10 +10,7 @@ boolean isIp(String str) {
|
||||
/** IP to String? */
|
||||
String toStringIp(IPAddress ip) {
|
||||
String res = "";
|
||||
for (int i = 0; i < 3; i++) {
|
||||
res += String((ip >> (8 * i)) & 0xFF) + ".";
|
||||
}
|
||||
for (int i = 0; i < 3; i++) { res += String((ip >> (8 * i)) & 0xFF) + "."; }
|
||||
res += String(((ip >> 8 * 3)) & 0xFF);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -11,9 +11,7 @@
|
||||
void setup() {
|
||||
EEPROM.begin(512);
|
||||
// write a 0 to all 512 bytes of the EEPROM
|
||||
for (int i = 0; i < 512; i++) {
|
||||
EEPROM.write(i, 0);
|
||||
}
|
||||
for (int i = 0; i < 512; i++) { EEPROM.write(i, 0); }
|
||||
|
||||
// turn the LED on when we're done
|
||||
pinMode(13, OUTPUT);
|
||||
@ -21,5 +19,4 @@ void setup() {
|
||||
EEPROM.end();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
}
|
||||
void loop() {}
|
||||
|
@ -32,9 +32,7 @@ void loop() {
|
||||
|
||||
// there are only 512 bytes of EEPROM, from 0 to 511, so if we're
|
||||
// on address 512, wrap around to address 0
|
||||
if (address == 512) {
|
||||
address = 0;
|
||||
}
|
||||
if (address == 512) { address = 0; }
|
||||
|
||||
delay(500);
|
||||
}
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
#ifndef STASSID
|
||||
#define STASSID "your-ssid"
|
||||
#define STAPSK "your-password"
|
||||
#define STAPSK "your-password"
|
||||
#endif
|
||||
|
||||
const char* host = "esp8266-avrisp";
|
||||
@ -20,7 +20,7 @@ void setup() {
|
||||
Serial.begin(115200);
|
||||
Serial.println("");
|
||||
Serial.println("Arduino AVR-ISP over TCP");
|
||||
avrprog.setReset(false); // let the AVR run
|
||||
avrprog.setReset(false); // let the AVR run
|
||||
|
||||
WiFi.mode(WIFI_STA);
|
||||
WiFi.begin(ssid, pass);
|
||||
@ -51,17 +51,20 @@ void loop() {
|
||||
AVRISPState_t new_state = avrprog.update();
|
||||
if (last_state != new_state) {
|
||||
switch (new_state) {
|
||||
case AVRISP_STATE_IDLE: {
|
||||
case AVRISP_STATE_IDLE:
|
||||
{
|
||||
Serial.printf("[AVRISP] now idle\r\n");
|
||||
// Use the SPI bus for other purposes
|
||||
break;
|
||||
}
|
||||
case AVRISP_STATE_PENDING: {
|
||||
case AVRISP_STATE_PENDING:
|
||||
{
|
||||
Serial.printf("[AVRISP] connection pending\r\n");
|
||||
// Clean up your other purposes and prepare for programming mode
|
||||
break;
|
||||
}
|
||||
case AVRISP_STATE_ACTIVE: {
|
||||
case AVRISP_STATE_ACTIVE:
|
||||
{
|
||||
Serial.printf("[AVRISP] programming mode\r\n");
|
||||
// Stand by for completion
|
||||
break;
|
||||
@ -70,11 +73,7 @@ void loop() {
|
||||
last_state = new_state;
|
||||
}
|
||||
// Serve the client
|
||||
if (last_state != AVRISP_STATE_IDLE) {
|
||||
avrprog.serve();
|
||||
}
|
||||
if (last_state != AVRISP_STATE_IDLE) { avrprog.serve(); }
|
||||
|
||||
if (WiFi.status() == WL_CONNECTED) {
|
||||
MDNS.update();
|
||||
}
|
||||
if (WiFi.status() == WL_CONNECTED) { MDNS.update(); }
|
||||
}
|
||||
|
@ -33,7 +33,6 @@ void setup() {
|
||||
|
||||
WiFi.mode(WIFI_STA);
|
||||
WiFiMulti.addAP("SSID", "PASSWORD");
|
||||
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
@ -33,7 +33,6 @@ void setup() {
|
||||
|
||||
WiFi.mode(WIFI_STA);
|
||||
WiFiMulti.addAP("SSID", "PASSWORD");
|
||||
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
@ -14,7 +14,7 @@
|
||||
|
||||
#include <WiFiClientSecureBearSSL.h>
|
||||
// Fingerprint for demo URL, expires on June 2, 2021, needs to be updated well before this date
|
||||
const uint8_t fingerprint[20] = {0x40, 0xaf, 0x00, 0x6b, 0xec, 0x90, 0x22, 0x41, 0x8e, 0xa3, 0xad, 0xfa, 0x1a, 0xe8, 0x25, 0x41, 0x1d, 0x1a, 0x54, 0xb3};
|
||||
const uint8_t fingerprint[20] = { 0x40, 0xaf, 0x00, 0x6b, 0xec, 0x90, 0x22, 0x41, 0x8e, 0xa3, 0xad, 0xfa, 0x1a, 0xe8, 0x25, 0x41, 0x1d, 0x1a, 0x54, 0xb3 };
|
||||
|
||||
ESP8266WiFiMulti WiFiMulti;
|
||||
|
||||
@ -41,7 +41,7 @@ void loop() {
|
||||
// wait for WiFi connection
|
||||
if ((WiFiMulti.run() == WL_CONNECTED)) {
|
||||
|
||||
std::unique_ptr<BearSSL::WiFiClientSecure>client(new BearSSL::WiFiClientSecure);
|
||||
std::unique_ptr<BearSSL::WiFiClientSecure> client(new BearSSL::WiFiClientSecure);
|
||||
|
||||
client->setFingerprint(fingerprint);
|
||||
// Or, if you happy to ignore the SSL certificate, then use the following line instead:
|
||||
|
@ -13,36 +13,31 @@
|
||||
|
||||
#ifndef STASSID
|
||||
#define STASSID "your-ssid"
|
||||
#define STAPSK "your-password"
|
||||
#define STAPSK "your-password"
|
||||
#endif
|
||||
|
||||
const char* ssid = STASSID;
|
||||
const char* ssidPassword = STAPSK;
|
||||
|
||||
const char *username = "admin";
|
||||
const char *password = "admin";
|
||||
const char* username = "admin";
|
||||
const char* password = "admin";
|
||||
|
||||
const char *server = "http://httpbin.org";
|
||||
const char *uri = "/digest-auth/auth/admin/admin/MD5";
|
||||
const char* server = "http://httpbin.org";
|
||||
const char* uri = "/digest-auth/auth/admin/admin/MD5";
|
||||
|
||||
String exractParam(String& authReq, const String& param, const char delimit) {
|
||||
int _begin = authReq.indexOf(param);
|
||||
if (_begin == -1) {
|
||||
return "";
|
||||
}
|
||||
if (_begin == -1) { return ""; }
|
||||
return authReq.substring(_begin + param.length(), authReq.indexOf(delimit, _begin + param.length()));
|
||||
}
|
||||
|
||||
String getCNonce(const int len) {
|
||||
static const char alphanum[] =
|
||||
"0123456789"
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"abcdefghijklmnopqrstuvwxyz";
|
||||
static const char alphanum[] = "0123456789"
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"abcdefghijklmnopqrstuvwxyz";
|
||||
String s = "";
|
||||
|
||||
for (int i = 0; i < len; ++i) {
|
||||
s += alphanum[rand() % (sizeof(alphanum) - 1)];
|
||||
}
|
||||
for (int i = 0; i < len; ++i) { s += alphanum[rand() % (sizeof(alphanum) - 1)]; }
|
||||
|
||||
return s;
|
||||
}
|
||||
@ -73,8 +68,7 @@ String getDigestAuth(String& authReq, const String& username, const String& pass
|
||||
md5.calculate();
|
||||
String response = md5.toString();
|
||||
|
||||
String authorization = "Digest username=\"" + username + "\", realm=\"" + realm + "\", nonce=\"" + nonce +
|
||||
"\", uri=\"" + uri + "\", algorithm=\"MD5\", qop=auth, nc=" + String(nc) + ", cnonce=\"" + cNonce + "\", response=\"" + response + "\"";
|
||||
String authorization = "Digest username=\"" + username + "\", realm=\"" + realm + "\", nonce=\"" + nonce + "\", uri=\"" + uri + "\", algorithm=\"MD5\", qop=auth, nc=" + String(nc) + ", cnonce=\"" + cNonce + "\", response=\"" + response + "\"";
|
||||
Serial.println(authorization);
|
||||
|
||||
return authorization;
|
||||
@ -100,7 +94,7 @@ void setup() {
|
||||
|
||||
void loop() {
|
||||
WiFiClient client;
|
||||
HTTPClient http; //must be declared after WiFiClient for correct destruction order, because used by http.begin(client,...)
|
||||
HTTPClient http; // must be declared after WiFiClient for correct destruction order, because used by http.begin(client,...)
|
||||
|
||||
Serial.print("[HTTP] begin...\n");
|
||||
|
||||
@ -108,7 +102,7 @@ void loop() {
|
||||
http.begin(client, String(server) + String(uri));
|
||||
|
||||
|
||||
const char *keys[] = {"WWW-Authenticate"};
|
||||
const char* keys[] = { "WWW-Authenticate" };
|
||||
http.collectHeaders(keys, 1);
|
||||
|
||||
Serial.print("[HTTP] GET...\n");
|
||||
|
@ -20,7 +20,7 @@
|
||||
|
||||
#ifndef STASSID
|
||||
#define STASSID "your-ssid"
|
||||
#define STAPSK "your-password"
|
||||
#define STAPSK "your-password"
|
||||
#endif
|
||||
|
||||
void setup() {
|
||||
@ -40,7 +40,6 @@ void setup() {
|
||||
Serial.println("");
|
||||
Serial.print("Connected! IP address: ");
|
||||
Serial.println(WiFi.localIP());
|
||||
|
||||
}
|
||||
|
||||
void loop() {
|
||||
@ -52,7 +51,7 @@ void loop() {
|
||||
|
||||
Serial.print("[HTTP] begin...\n");
|
||||
// configure traged server and url
|
||||
http.begin(client, "http://" SERVER_IP "/postplain/"); //HTTP
|
||||
http.begin(client, "http://" SERVER_IP "/postplain/"); // HTTP
|
||||
http.addHeader("Content-Type", "application/json");
|
||||
|
||||
Serial.print("[HTTP] POST...\n");
|
||||
|
@ -13,7 +13,7 @@
|
||||
|
||||
#ifndef STASSID
|
||||
#define STASSID "your-ssid"
|
||||
#define STAPSK "your-password"
|
||||
#define STAPSK "your-password"
|
||||
#endif
|
||||
|
||||
ESP8266WiFiMulti WiFiMulti;
|
||||
@ -45,7 +45,7 @@ void setup() {
|
||||
|
||||
|
||||
http.begin(client, "http://jigsaw.w3.org/HTTP/connection.html");
|
||||
//http.begin(client, "jigsaw.w3.org", 80, "/HTTP/connection.html");
|
||||
// http.begin(client, "jigsaw.w3.org", 80, "/HTTP/connection.html");
|
||||
}
|
||||
|
||||
int pass = 0;
|
||||
@ -60,15 +60,13 @@ void loop() {
|
||||
Serial.printf("[HTTP] GET... code: %d\n", httpCode);
|
||||
|
||||
// file found at server
|
||||
if (httpCode == HTTP_CODE_OK) {
|
||||
http.writeToStream(&Serial);
|
||||
}
|
||||
if (httpCode == HTTP_CODE_OK) { http.writeToStream(&Serial); }
|
||||
} else {
|
||||
Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str());
|
||||
// Something went wrong with the connection, try to reconnect
|
||||
http.end();
|
||||
http.begin(client, "http://jigsaw.w3.org/HTTP/connection.html");
|
||||
//http.begin(client, "jigsaw.w3.org", 80, "/HTTP/connection.html");
|
||||
// http.begin(client, "jigsaw.w3.org", 80, "/HTTP/connection.html");
|
||||
}
|
||||
|
||||
if (pass == 10) {
|
||||
|
@ -31,7 +31,6 @@ void setup() {
|
||||
|
||||
WiFi.mode(WIFI_STA);
|
||||
WiFiMulti.addAP("SSID", "PASSWORD");
|
||||
|
||||
}
|
||||
|
||||
void loop() {
|
||||
@ -39,13 +38,13 @@ void loop() {
|
||||
if ((WiFiMulti.run() == WL_CONNECTED)) {
|
||||
|
||||
WiFiClient client;
|
||||
HTTPClient http; //must be declared after WiFiClient for correct destruction order, because used by http.begin(client,...)
|
||||
HTTPClient http; // must be declared after WiFiClient for correct destruction order, because used by http.begin(client,...)
|
||||
|
||||
Serial.print("[HTTP] begin...\n");
|
||||
|
||||
// configure server and url
|
||||
http.begin(client, "http://jigsaw.w3.org/HTTP/connection.html");
|
||||
//http.begin(client, "jigsaw.w3.org", 80, "/HTTP/connection.html");
|
||||
// http.begin(client, "jigsaw.w3.org", 80, "/HTTP/connection.html");
|
||||
|
||||
Serial.print("[HTTP] GET...\n");
|
||||
// start connection and send HTTP header
|
||||
@ -70,23 +69,19 @@ void loop() {
|
||||
// or "by hand"
|
||||
|
||||
// get tcp stream
|
||||
WiFiClient * stream = &client;
|
||||
WiFiClient* stream = &client;
|
||||
|
||||
// read all data from server
|
||||
while (http.connected() && (len > 0 || len == -1)) {
|
||||
// read up to 128 byte
|
||||
int c = stream->readBytes(buff, std::min((size_t)len, sizeof(buff)));
|
||||
Serial.printf("readBytes: %d\n", c);
|
||||
if (!c) {
|
||||
Serial.println("read timeout");
|
||||
}
|
||||
if (!c) { Serial.println("read timeout"); }
|
||||
|
||||
// write it to Serial
|
||||
Serial.write(buff, c);
|
||||
|
||||
if (len > 0) {
|
||||
len -= c;
|
||||
}
|
||||
if (len > 0) { len -= c; }
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -31,7 +31,6 @@ void setup() {
|
||||
|
||||
WiFi.mode(WIFI_STA);
|
||||
WiFiMulti.addAP("SSID", "PASSWORD");
|
||||
|
||||
}
|
||||
|
||||
void loop() {
|
||||
@ -43,14 +42,12 @@ void loop() {
|
||||
bool mfln = client->probeMaxFragmentLength("tls.mbed.org", 443, 1024);
|
||||
Serial.printf("\nConnecting to https://tls.mbed.org\n");
|
||||
Serial.printf("Maximum fragment Length negotiation supported: %s\n", mfln ? "yes" : "no");
|
||||
if (mfln) {
|
||||
client->setBufferSizes(1024, 1024);
|
||||
}
|
||||
if (mfln) { client->setBufferSizes(1024, 1024); }
|
||||
|
||||
Serial.print("[HTTPS] begin...\n");
|
||||
|
||||
// configure server and url
|
||||
const uint8_t fingerprint[20] = {0x15, 0x77, 0xdc, 0x04, 0x7c, 0x00, 0xf8, 0x70, 0x09, 0x34, 0x24, 0xf4, 0xd3, 0xa1, 0x7a, 0x6c, 0x1e, 0xa3, 0xe0, 0x2a};
|
||||
const uint8_t fingerprint[20] = { 0x15, 0x77, 0xdc, 0x04, 0x7c, 0x00, 0xf8, 0x70, 0x09, 0x34, 0x24, 0xf4, 0xd3, 0xa1, 0x7a, 0x6c, 0x1e, 0xa3, 0xe0, 0x2a };
|
||||
|
||||
client->setFingerprint(fingerprint);
|
||||
|
||||
@ -86,16 +83,13 @@ void loop() {
|
||||
// write it to Serial
|
||||
Serial.write(buff, c);
|
||||
|
||||
if (len > 0) {
|
||||
len -= c;
|
||||
}
|
||||
if (len > 0) { len -= c; }
|
||||
}
|
||||
delay(1);
|
||||
}
|
||||
|
||||
Serial.println();
|
||||
Serial.print("[HTTPS] connection closed or file end.\n");
|
||||
|
||||
}
|
||||
} else {
|
||||
Serial.printf("[HTTPS] GET... failed, error: %s\n", https.errorToString(httpCode).c_str());
|
||||
|
@ -21,7 +21,7 @@
|
||||
|
||||
#ifndef STASSID
|
||||
#define STASSID "your-ssid"
|
||||
#define STAPSK "your-password"
|
||||
#define STAPSK "your-password"
|
||||
#endif
|
||||
|
||||
const char* host = "esp8266-webupdate";
|
||||
@ -57,7 +57,7 @@ JfUvYadSYxh3nblvA4OL+iEZiW8NE3hbW6WPXxvS7Euge0uWMPc4uEcnsE0ZVG3m
|
||||
-----END CERTIFICATE-----
|
||||
)EOF";
|
||||
|
||||
static const char serverKey[] PROGMEM = R"EOF(
|
||||
static const char serverKey[] PROGMEM = R"EOF(
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEpQIBAAKCAQEA9UoHBtn4oNKXjRgIOQ/rLxK/iI0a8Q5mDxhfuwa9//FkftSI
|
||||
IFY8UhGk2YNJpnfKOyYWqbqwuJhIZJ2sEIWp2301OnavuGBrpKOgBJJljgH2l/4Z
|
||||
@ -88,8 +88,7 @@ gz5JWYhbD6c38khSzJb0pNXCo3EuYAVa36kDM96k1BtWuhRS10Q1VXk=
|
||||
)EOF";
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
void setup() {
|
||||
|
||||
Serial.begin(115200);
|
||||
Serial.println();
|
||||
@ -97,7 +96,7 @@ void setup()
|
||||
WiFi.mode(WIFI_AP_STA);
|
||||
WiFi.begin(ssid, password);
|
||||
|
||||
while(WiFi.waitForConnectResult() != WL_CONNECTED){
|
||||
while (WiFi.waitForConnectResult() != WL_CONNECTED) {
|
||||
WiFi.begin(ssid, password);
|
||||
Serial.println("WiFi failed, retrying.");
|
||||
}
|
||||
@ -111,13 +110,13 @@ void setup()
|
||||
httpServer.begin();
|
||||
|
||||
MDNS.addService("https", "tcp", 443);
|
||||
Serial.printf("BearSSLUpdateServer ready!\nOpen https://%s.local%s in "\
|
||||
"your browser and login with username '%s' and password "\
|
||||
"'%s'\n", host, update_path, update_username, update_password);
|
||||
Serial.printf("BearSSLUpdateServer ready!\nOpen https://%s.local%s in "
|
||||
"your browser and login with username '%s' and password "
|
||||
"'%s'\n",
|
||||
host, update_path, update_username, update_password);
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
void loop() {
|
||||
httpServer.handleClient();
|
||||
MDNS.update();
|
||||
}
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
#ifndef STASSID
|
||||
#define STASSID "your-ssid"
|
||||
#define STAPSK "your-password"
|
||||
#define STAPSK "your-password"
|
||||
#endif
|
||||
|
||||
const char* host = "esp8266-webupdate";
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
#ifndef STASSID
|
||||
#define STASSID "your-ssid"
|
||||
#define STAPSK "your-password"
|
||||
#define STAPSK "your-password"
|
||||
#endif
|
||||
|
||||
const char* host = "esp8266-webupdate";
|
||||
|
@ -62,7 +62,7 @@
|
||||
|
||||
#ifndef STASSID
|
||||
#define STASSID "your-ssid"
|
||||
#define STAPSK "your-password"
|
||||
#define STAPSK "your-password"
|
||||
#endif
|
||||
|
||||
const char* ssid = STASSID;
|
||||
|
2
libraries/ESP8266NetBIOS/examples/ESP_NBNST/ESP_NBNST.ino
Executable file → Normal file
2
libraries/ESP8266NetBIOS/examples/ESP_NBNST/ESP_NBNST.ino
Executable file → Normal file
@ -4,7 +4,7 @@
|
||||
|
||||
#ifndef STASSID
|
||||
#define STASSID "your-ssid"
|
||||
#define STAPSK "your-password"
|
||||
#define STAPSK "your-password"
|
||||
#endif
|
||||
|
||||
const char* ssid = STASSID;
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
#ifndef STASSID
|
||||
#define STASSID "your-ssid"
|
||||
#define STAPSK "your-password"
|
||||
#define STAPSK "your-password"
|
||||
#endif
|
||||
|
||||
const char* ssid = STASSID;
|
||||
@ -46,9 +46,7 @@ void setup() {
|
||||
Serial.printf("Ready!\n");
|
||||
} else {
|
||||
Serial.printf("WiFi Failed\n");
|
||||
while (1) {
|
||||
delay(100);
|
||||
}
|
||||
while (1) { delay(100); }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -35,7 +35,7 @@
|
||||
|
||||
#ifndef STASSID
|
||||
#define STASSID "your-ssid"
|
||||
#define STAPSK "your-password"
|
||||
#define STAPSK "your-password"
|
||||
#endif
|
||||
|
||||
const char *ssid = STASSID;
|
||||
@ -69,8 +69,7 @@ void handleRoot() {
|
||||
</body>\
|
||||
</html>",
|
||||
|
||||
hr, min % 60, sec % 60
|
||||
);
|
||||
hr, min % 60, sec % 60);
|
||||
server.send(200, "text/html", temp);
|
||||
digitalWrite(led, 0);
|
||||
}
|
||||
@ -86,9 +85,7 @@ void handleNotFound() {
|
||||
message += server.args();
|
||||
message += "\n";
|
||||
|
||||
for (uint8_t i = 0; i < server.args(); i++) {
|
||||
message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
|
||||
}
|
||||
for (uint8_t i = 0; i < server.args(); i++) { message += " " + server.argName(i) + ": " + server.arg(i) + "\n"; }
|
||||
|
||||
server.send(404, "text/plain", message);
|
||||
digitalWrite(led, 0);
|
||||
@ -133,9 +130,7 @@ void setup(void) {
|
||||
Serial.print("IP address: ");
|
||||
Serial.println(WiFi.localIP());
|
||||
|
||||
if (MDNS.begin("esp8266")) {
|
||||
Serial.println("MDNS responder started");
|
||||
}
|
||||
if (MDNS.begin("esp8266")) { Serial.println("MDNS responder started"); }
|
||||
|
||||
server.on("/", handleRoot);
|
||||
server.on("/test.svg", drawGraph);
|
||||
@ -151,4 +146,3 @@ void loop(void) {
|
||||
server.handleClient();
|
||||
MDNS.update();
|
||||
}
|
||||
|
||||
|
@ -72,7 +72,7 @@ SDFSConfig fileSystemConfig = SDFSConfig();
|
||||
|
||||
#ifndef STASSID
|
||||
#define STASSID "your-ssid"
|
||||
#define STAPSK "your-password"
|
||||
#define STAPSK "your-password"
|
||||
#endif
|
||||
|
||||
const char* ssid = STASSID;
|
||||
@ -122,15 +122,9 @@ void replyServerError(String msg) {
|
||||
*/
|
||||
String checkForUnsupportedPath(String filename) {
|
||||
String error = String();
|
||||
if (!filename.startsWith("/")) {
|
||||
error += F("!NO_LEADING_SLASH! ");
|
||||
}
|
||||
if (filename.indexOf("//") != -1) {
|
||||
error += F("!DOUBLE_SLASH! ");
|
||||
}
|
||||
if (filename.endsWith("/")) {
|
||||
error += F("!TRAILING_SLASH! ");
|
||||
}
|
||||
if (!filename.startsWith("/")) { error += F("!NO_LEADING_SLASH! "); }
|
||||
if (filename.indexOf("//") != -1) { error += F("!DOUBLE_SLASH! "); }
|
||||
if (filename.endsWith("/")) { error += F("!TRAILING_SLASH! "); }
|
||||
return error;
|
||||
}
|
||||
#endif
|
||||
@ -174,18 +168,12 @@ void handleStatus() {
|
||||
Also demonstrates the use of chunked responses.
|
||||
*/
|
||||
void handleFileList() {
|
||||
if (!fsOK) {
|
||||
return replyServerError(FPSTR(FS_INIT_ERROR));
|
||||
}
|
||||
if (!fsOK) { return replyServerError(FPSTR(FS_INIT_ERROR)); }
|
||||
|
||||
if (!server.hasArg("dir")) {
|
||||
return replyBadRequest(F("DIR ARG MISSING"));
|
||||
}
|
||||
if (!server.hasArg("dir")) { return replyBadRequest(F("DIR ARG MISSING")); }
|
||||
|
||||
String path = server.arg("dir");
|
||||
if (path != "/" && !fileSystem->exists(path)) {
|
||||
return replyBadRequest("BAD PATH");
|
||||
}
|
||||
if (path != "/" && !fileSystem->exists(path)) { return replyBadRequest("BAD PATH"); }
|
||||
|
||||
DBG_OUTPUT_PORT.println(String("handleFileList: ") + path);
|
||||
Dir dir = fileSystem->openDir(path);
|
||||
@ -253,9 +241,7 @@ bool handleFileRead(String path) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (path.endsWith("/")) {
|
||||
path += "index.htm";
|
||||
}
|
||||
if (path.endsWith("/")) { path += "index.htm"; }
|
||||
|
||||
String contentType;
|
||||
if (server.hasArg("download")) {
|
||||
@ -270,9 +256,7 @@ bool handleFileRead(String path) {
|
||||
}
|
||||
if (fileSystem->exists(path)) {
|
||||
File file = fileSystem->open(path, "r");
|
||||
if (server.streamFile(file, contentType) != file.size()) {
|
||||
DBG_OUTPUT_PORT.println("Sent less data than expected!");
|
||||
}
|
||||
if (server.streamFile(file, contentType) != file.size()) { DBG_OUTPUT_PORT.println("Sent less data than expected!"); }
|
||||
file.close();
|
||||
return true;
|
||||
}
|
||||
@ -309,27 +293,17 @@ String lastExistingParent(String path) {
|
||||
Move folder | parent of source folder, or remaining ancestor
|
||||
*/
|
||||
void handleFileCreate() {
|
||||
if (!fsOK) {
|
||||
return replyServerError(FPSTR(FS_INIT_ERROR));
|
||||
}
|
||||
if (!fsOK) { return replyServerError(FPSTR(FS_INIT_ERROR)); }
|
||||
|
||||
String path = server.arg("path");
|
||||
if (path.isEmpty()) {
|
||||
return replyBadRequest(F("PATH ARG MISSING"));
|
||||
}
|
||||
if (path.isEmpty()) { return replyBadRequest(F("PATH ARG MISSING")); }
|
||||
|
||||
#ifdef USE_SPIFFS
|
||||
if (checkForUnsupportedPath(path).length() > 0) {
|
||||
return replyServerError(F("INVALID FILENAME"));
|
||||
}
|
||||
if (checkForUnsupportedPath(path).length() > 0) { return replyServerError(F("INVALID FILENAME")); }
|
||||
#endif
|
||||
|
||||
if (path == "/") {
|
||||
return replyBadRequest("BAD PATH");
|
||||
}
|
||||
if (fileSystem->exists(path)) {
|
||||
return replyBadRequest(F("PATH FILE EXISTS"));
|
||||
}
|
||||
if (path == "/") { return replyBadRequest("BAD PATH"); }
|
||||
if (fileSystem->exists(path)) { return replyBadRequest(F("PATH FILE EXISTS")); }
|
||||
|
||||
String src = server.arg("src");
|
||||
if (src.isEmpty()) {
|
||||
@ -338,43 +312,29 @@ void handleFileCreate() {
|
||||
if (path.endsWith("/")) {
|
||||
// Create a folder
|
||||
path.remove(path.length() - 1);
|
||||
if (!fileSystem->mkdir(path)) {
|
||||
return replyServerError(F("MKDIR FAILED"));
|
||||
}
|
||||
if (!fileSystem->mkdir(path)) { return replyServerError(F("MKDIR FAILED")); }
|
||||
} else {
|
||||
// Create a file
|
||||
File file = fileSystem->open(path, "w");
|
||||
if (file) {
|
||||
file.write((const char *)0);
|
||||
file.write((const char*)0);
|
||||
file.close();
|
||||
} else {
|
||||
return replyServerError(F("CREATE FAILED"));
|
||||
}
|
||||
}
|
||||
if (path.lastIndexOf('/') > -1) {
|
||||
path = path.substring(0, path.lastIndexOf('/'));
|
||||
}
|
||||
if (path.lastIndexOf('/') > -1) { path = path.substring(0, path.lastIndexOf('/')); }
|
||||
replyOKWithMsg(path);
|
||||
} else {
|
||||
// Source specified: rename
|
||||
if (src == "/") {
|
||||
return replyBadRequest("BAD SRC");
|
||||
}
|
||||
if (!fileSystem->exists(src)) {
|
||||
return replyBadRequest(F("SRC FILE NOT FOUND"));
|
||||
}
|
||||
if (src == "/") { return replyBadRequest("BAD SRC"); }
|
||||
if (!fileSystem->exists(src)) { return replyBadRequest(F("SRC FILE NOT FOUND")); }
|
||||
|
||||
DBG_OUTPUT_PORT.println(String("handleFileCreate: ") + path + " from " + src);
|
||||
|
||||
if (path.endsWith("/")) {
|
||||
path.remove(path.length() - 1);
|
||||
}
|
||||
if (src.endsWith("/")) {
|
||||
src.remove(src.length() - 1);
|
||||
}
|
||||
if (!fileSystem->rename(src, path)) {
|
||||
return replyServerError(F("RENAME FAILED"));
|
||||
}
|
||||
if (path.endsWith("/")) { path.remove(path.length() - 1); }
|
||||
if (src.endsWith("/")) { src.remove(src.length() - 1); }
|
||||
if (!fileSystem->rename(src, path)) { return replyServerError(F("RENAME FAILED")); }
|
||||
replyOKWithMsg(lastExistingParent(src));
|
||||
}
|
||||
}
|
||||
@ -403,9 +363,7 @@ void deleteRecursive(String path) {
|
||||
// Otherwise delete its contents first
|
||||
Dir dir = fileSystem->openDir(path);
|
||||
|
||||
while (dir.next()) {
|
||||
deleteRecursive(path + '/' + dir.fileName());
|
||||
}
|
||||
while (dir.next()) { deleteRecursive(path + '/' + dir.fileName()); }
|
||||
|
||||
// Then delete the folder itself
|
||||
fileSystem->rmdir(path);
|
||||
@ -420,19 +378,13 @@ void deleteRecursive(String path) {
|
||||
Delete folder | parent of deleted folder, or remaining ancestor
|
||||
*/
|
||||
void handleFileDelete() {
|
||||
if (!fsOK) {
|
||||
return replyServerError(FPSTR(FS_INIT_ERROR));
|
||||
}
|
||||
if (!fsOK) { return replyServerError(FPSTR(FS_INIT_ERROR)); }
|
||||
|
||||
String path = server.arg(0);
|
||||
if (path.isEmpty() || path == "/") {
|
||||
return replyBadRequest("BAD PATH");
|
||||
}
|
||||
if (path.isEmpty() || path == "/") { return replyBadRequest("BAD PATH"); }
|
||||
|
||||
DBG_OUTPUT_PORT.println(String("handleFileDelete: ") + path);
|
||||
if (!fileSystem->exists(path)) {
|
||||
return replyNotFound(FPSTR(FILE_NOT_FOUND));
|
||||
}
|
||||
if (!fileSystem->exists(path)) { return replyNotFound(FPSTR(FILE_NOT_FOUND)); }
|
||||
deleteRecursive(path);
|
||||
|
||||
replyOKWithMsg(lastExistingParent(path));
|
||||
@ -442,37 +394,25 @@ void handleFileDelete() {
|
||||
Handle a file upload request
|
||||
*/
|
||||
void handleFileUpload() {
|
||||
if (!fsOK) {
|
||||
return replyServerError(FPSTR(FS_INIT_ERROR));
|
||||
}
|
||||
if (server.uri() != "/edit") {
|
||||
return;
|
||||
}
|
||||
if (!fsOK) { return replyServerError(FPSTR(FS_INIT_ERROR)); }
|
||||
if (server.uri() != "/edit") { return; }
|
||||
HTTPUpload& upload = server.upload();
|
||||
if (upload.status == UPLOAD_FILE_START) {
|
||||
String filename = upload.filename;
|
||||
// Make sure paths always start with "/"
|
||||
if (!filename.startsWith("/")) {
|
||||
filename = "/" + filename;
|
||||
}
|
||||
if (!filename.startsWith("/")) { filename = "/" + filename; }
|
||||
DBG_OUTPUT_PORT.println(String("handleFileUpload Name: ") + filename);
|
||||
uploadFile = fileSystem->open(filename, "w");
|
||||
if (!uploadFile) {
|
||||
return replyServerError(F("CREATE FAILED"));
|
||||
}
|
||||
if (!uploadFile) { return replyServerError(F("CREATE FAILED")); }
|
||||
DBG_OUTPUT_PORT.println(String("Upload: START, filename: ") + filename);
|
||||
} else if (upload.status == UPLOAD_FILE_WRITE) {
|
||||
if (uploadFile) {
|
||||
size_t bytesWritten = uploadFile.write(upload.buf, upload.currentSize);
|
||||
if (bytesWritten != upload.currentSize) {
|
||||
return replyServerError(F("WRITE FAILED"));
|
||||
}
|
||||
if (bytesWritten != upload.currentSize) { return replyServerError(F("WRITE FAILED")); }
|
||||
}
|
||||
DBG_OUTPUT_PORT.println(String("Upload: WRITE, Bytes: ") + upload.currentSize);
|
||||
} else if (upload.status == UPLOAD_FILE_END) {
|
||||
if (uploadFile) {
|
||||
uploadFile.close();
|
||||
}
|
||||
if (uploadFile) { uploadFile.close(); }
|
||||
DBG_OUTPUT_PORT.println(String("Upload: END, Size: ") + upload.totalSize);
|
||||
}
|
||||
}
|
||||
@ -484,15 +424,11 @@ void handleFileUpload() {
|
||||
and if it fails, return a 404 page with debug information
|
||||
*/
|
||||
void handleNotFound() {
|
||||
if (!fsOK) {
|
||||
return replyServerError(FPSTR(FS_INIT_ERROR));
|
||||
}
|
||||
if (!fsOK) { return replyServerError(FPSTR(FS_INIT_ERROR)); }
|
||||
|
||||
String uri = ESP8266WebServer::urlDecode(server.uri()); // required to read paths with blanks
|
||||
String uri = ESP8266WebServer::urlDecode(server.uri()); // required to read paths with blanks
|
||||
|
||||
if (handleFileRead(uri)) {
|
||||
return;
|
||||
}
|
||||
if (handleFileRead(uri)) { return; }
|
||||
|
||||
// Dump debug data
|
||||
String message;
|
||||
@ -526,9 +462,7 @@ void handleNotFound() {
|
||||
Otherwise, fails with a 404 page with debug information
|
||||
*/
|
||||
void handleGetEdit() {
|
||||
if (handleFileRead(F("/edit/index.htm"))) {
|
||||
return;
|
||||
}
|
||||
if (handleFileRead(F("/edit/index.htm"))) { return; }
|
||||
|
||||
#ifdef INCLUDE_FALLBACK_INDEX_HTM
|
||||
server.sendHeader(F("Content-Encoding"), "gzip");
|
||||
@ -536,7 +470,6 @@ void handleGetEdit() {
|
||||
#else
|
||||
replyNotFound(FPSTR(FILE_NOT_FOUND));
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void setup(void) {
|
||||
@ -562,9 +495,7 @@ void setup(void) {
|
||||
String error = checkForUnsupportedPath(dir.fileName());
|
||||
String fileInfo = dir.fileName() + (dir.isDirectory() ? " [DIR]" : String(" (") + dir.fileSize() + "b)");
|
||||
DBG_OUTPUT_PORT.println(error + fileInfo);
|
||||
if (error.length() > 0) {
|
||||
unsupportedFiles += error + fileInfo + '\n';
|
||||
}
|
||||
if (error.length() > 0) { unsupportedFiles += error + fileInfo + '\n'; }
|
||||
}
|
||||
DBG_OUTPUT_PORT.println();
|
||||
|
||||
@ -609,15 +540,15 @@ void setup(void) {
|
||||
server.on("/edit", HTTP_GET, handleGetEdit);
|
||||
|
||||
// Create file
|
||||
server.on("/edit", HTTP_PUT, handleFileCreate);
|
||||
server.on("/edit", HTTP_PUT, handleFileCreate);
|
||||
|
||||
// Delete file
|
||||
server.on("/edit", HTTP_DELETE, handleFileDelete);
|
||||
server.on("/edit", HTTP_DELETE, handleFileDelete);
|
||||
|
||||
// Upload file
|
||||
// - first callback is called after the request has ended with all parsed arguments
|
||||
// - second callback handles file upload at that location
|
||||
server.on("/edit", HTTP_POST, replyOK, handleFileUpload);
|
||||
server.on("/edit", HTTP_POST, replyOK, handleFileUpload);
|
||||
|
||||
// Default handler for all URIs not defined above
|
||||
// Use it to read files from filesystem
|
||||
|
@ -58,7 +58,7 @@ SDFSConfig fileSystemConfig = SDFSConfig();
|
||||
|
||||
#ifndef STASSID
|
||||
#define STASSID "your-ssid"
|
||||
#define STAPSK "your-password"
|
||||
#define STAPSK "your-password"
|
||||
#endif
|
||||
|
||||
// Indicate which digital I/Os should be displayed on the chart.
|
||||
@ -110,9 +110,7 @@ void replyServerError(String msg) {
|
||||
bool handleFileRead(String path) {
|
||||
DBG_OUTPUT_PORT.println(String("handleFileRead: ") + path);
|
||||
|
||||
if (path.endsWith("/")) {
|
||||
path += "index.htm";
|
||||
}
|
||||
if (path.endsWith("/")) { path += "index.htm"; }
|
||||
|
||||
String contentType = mime::getContentType(path);
|
||||
|
||||
@ -122,9 +120,7 @@ bool handleFileRead(String path) {
|
||||
}
|
||||
if (fileSystem->exists(path)) {
|
||||
File file = fileSystem->open(path, "r");
|
||||
if (server.streamFile(file, contentType) != file.size()) {
|
||||
DBG_OUTPUT_PORT.println("Sent less data than expected!");
|
||||
}
|
||||
if (server.streamFile(file, contentType) != file.size()) { DBG_OUTPUT_PORT.println("Sent less data than expected!"); }
|
||||
file.close();
|
||||
return true;
|
||||
}
|
||||
@ -139,11 +135,9 @@ bool handleFileRead(String path) {
|
||||
and if it fails, return a 404 page with debug information
|
||||
*/
|
||||
void handleNotFound() {
|
||||
String uri = ESP8266WebServer::urlDecode(server.uri()); // required to read paths with blanks
|
||||
String uri = ESP8266WebServer::urlDecode(server.uri()); // required to read paths with blanks
|
||||
|
||||
if (handleFileRead(uri)) {
|
||||
return;
|
||||
}
|
||||
if (handleFileRead(uri)) { return; }
|
||||
|
||||
// Dump debug data
|
||||
String message;
|
||||
@ -218,7 +212,7 @@ void setup(void) {
|
||||
////////////////////////////////
|
||||
// WEB SERVER INIT
|
||||
|
||||
//get heap status, analog input value and all GPIO statuses in one json call
|
||||
// get heap status, analog input value and all GPIO statuses in one json call
|
||||
server.on("/espData", HTTP_GET, []() {
|
||||
String json;
|
||||
json.reserve(88);
|
||||
@ -249,21 +243,18 @@ void setup(void) {
|
||||
DBG_OUTPUT_PORT.println(" 0 (OFF): outputs are off and hidden from chart");
|
||||
DBG_OUTPUT_PORT.println(" 1 (AUTO): outputs are rotated automatically every second");
|
||||
DBG_OUTPUT_PORT.println(" 2 (MANUAL): outputs can be toggled from the web page");
|
||||
|
||||
}
|
||||
|
||||
// Return default GPIO mask, that is all I/Os except SD card ones
|
||||
unsigned int defaultMask() {
|
||||
unsigned int mask = 0b11111111111111111;
|
||||
for (auto pin = 0; pin <= 16; pin++) {
|
||||
if (isFlashInterfacePin(pin)) {
|
||||
mask &= ~(1 << pin);
|
||||
}
|
||||
if (isFlashInterfacePin(pin)) { mask &= ~(1 << pin); }
|
||||
}
|
||||
return mask;
|
||||
}
|
||||
|
||||
int rgbMode = 1; // 0=off - 1=auto - 2=manual
|
||||
int rgbMode = 1; // 0=off - 1=auto - 2=manual
|
||||
int rgbValue = 0;
|
||||
esp8266::polledTimeout::periodicMs timeToChange(1000);
|
||||
bool modeChangeRequested = false;
|
||||
@ -278,28 +269,24 @@ void loop(void) {
|
||||
}
|
||||
|
||||
// see if one second has passed since last change, otherwise stop here
|
||||
if (!timeToChange) {
|
||||
return;
|
||||
}
|
||||
if (!timeToChange) { return; }
|
||||
|
||||
// see if a mode change was requested
|
||||
if (modeChangeRequested) {
|
||||
// increment mode (reset after 2)
|
||||
rgbMode++;
|
||||
if (rgbMode > 2) {
|
||||
rgbMode = 0;
|
||||
}
|
||||
if (rgbMode > 2) { rgbMode = 0; }
|
||||
|
||||
modeChangeRequested = false;
|
||||
}
|
||||
|
||||
// act according to mode
|
||||
switch (rgbMode) {
|
||||
case 0: // off
|
||||
case 0: // off
|
||||
gpioMask = defaultMask();
|
||||
gpioMask &= ~(1 << 12); // Hide GPIO 12
|
||||
gpioMask &= ~(1 << 13); // Hide GPIO 13
|
||||
gpioMask &= ~(1 << 15); // Hide GPIO 15
|
||||
gpioMask &= ~(1 << 12); // Hide GPIO 12
|
||||
gpioMask &= ~(1 << 13); // Hide GPIO 13
|
||||
gpioMask &= ~(1 << 15); // Hide GPIO 15
|
||||
|
||||
// reset outputs
|
||||
digitalWrite(12, 0);
|
||||
@ -307,14 +294,12 @@ void loop(void) {
|
||||
digitalWrite(15, 0);
|
||||
break;
|
||||
|
||||
case 1: // auto
|
||||
case 1: // auto
|
||||
gpioMask = defaultMask();
|
||||
|
||||
// increment value (reset after 7)
|
||||
rgbValue++;
|
||||
if (rgbValue > 7) {
|
||||
rgbValue = 0;
|
||||
}
|
||||
if (rgbValue > 7) { rgbValue = 0; }
|
||||
|
||||
// output new values
|
||||
digitalWrite(12, rgbValue & 0b001);
|
||||
@ -322,11 +307,10 @@ void loop(void) {
|
||||
digitalWrite(15, rgbValue & 0b100);
|
||||
break;
|
||||
|
||||
case 2: // manual
|
||||
case 2: // manual
|
||||
gpioMask = defaultMask();
|
||||
|
||||
// keep outputs unchanged
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
#ifndef STASSID
|
||||
#define STASSID "your-ssid"
|
||||
#define STAPSK "your-password"
|
||||
#define STAPSK "your-password"
|
||||
#endif
|
||||
|
||||
const char* ssid = STASSID;
|
||||
@ -31,9 +31,7 @@ void handleNotFound() {
|
||||
message += "\nArguments: ";
|
||||
message += server.args();
|
||||
message += "\n";
|
||||
for (uint8_t i = 0; i < server.args(); i++) {
|
||||
message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
|
||||
}
|
||||
for (uint8_t i = 0; i < server.args(); i++) { message += " " + server.argName(i) + ": " + server.arg(i) + "\n"; }
|
||||
server.send(404, "text/plain", message);
|
||||
digitalWrite(led, 0);
|
||||
}
|
||||
@ -57,9 +55,7 @@ void setup(void) {
|
||||
Serial.print("IP address: ");
|
||||
Serial.println(WiFi.localIP());
|
||||
|
||||
if (MDNS.begin("esp8266")) {
|
||||
Serial.println("MDNS responder started");
|
||||
}
|
||||
if (MDNS.begin("esp8266")) { Serial.println("MDNS responder started"); }
|
||||
|
||||
server.on("/", handleRoot);
|
||||
|
||||
@ -89,17 +85,17 @@ void setup(void) {
|
||||
/////////////////////////////////////////////////////////
|
||||
// Hook examples
|
||||
|
||||
server.addHook([](const String & method, const String & url, WiFiClient * client, ESP8266WebServer::ContentTypeFunction contentType) {
|
||||
(void)method; // GET, PUT, ...
|
||||
(void)url; // example: /root/myfile.html
|
||||
(void)client; // the webserver tcp client connection
|
||||
(void)contentType; // contentType(".html") => "text/html"
|
||||
server.addHook([](const String& method, const String& url, WiFiClient* client, ESP8266WebServer::ContentTypeFunction contentType) {
|
||||
(void)method; // GET, PUT, ...
|
||||
(void)url; // example: /root/myfile.html
|
||||
(void)client; // the webserver tcp client connection
|
||||
(void)contentType; // contentType(".html") => "text/html"
|
||||
Serial.printf("A useless web hook has passed\n");
|
||||
Serial.printf("(this hook is in 0x%08x area (401x=IRAM 402x=FLASH))\n", esp_get_program_counter());
|
||||
return ESP8266WebServer::CLIENT_REQUEST_CAN_CONTINUE;
|
||||
});
|
||||
|
||||
server.addHook([](const String&, const String & url, WiFiClient*, ESP8266WebServer::ContentTypeFunction) {
|
||||
server.addHook([](const String&, const String& url, WiFiClient*, ESP8266WebServer::ContentTypeFunction) {
|
||||
if (url.startsWith("/fail")) {
|
||||
Serial.printf("An always failing web hook has been triggered\n");
|
||||
return ESP8266WebServer::CLIENT_MUST_STOP;
|
||||
@ -107,7 +103,7 @@ void setup(void) {
|
||||
return ESP8266WebServer::CLIENT_REQUEST_CAN_CONTINUE;
|
||||
});
|
||||
|
||||
server.addHook([](const String&, const String & url, WiFiClient * client, ESP8266WebServer::ContentTypeFunction) {
|
||||
server.addHook([](const String&, const String& url, WiFiClient* client, ESP8266WebServer::ContentTypeFunction) {
|
||||
if (url.startsWith("/dump")) {
|
||||
Serial.printf("The dumper web hook is on the run\n");
|
||||
|
||||
@ -137,7 +133,7 @@ void setup(void) {
|
||||
// check the client connection: it should not immediately be closed
|
||||
// (make another '/dump' one to close the first)
|
||||
Serial.printf("\nTelling server to forget this connection\n");
|
||||
static WiFiClient forgetme = *client; // stop previous one if present and transfer client refcounter
|
||||
static WiFiClient forgetme = *client; // stop previous one if present and transfer client refcounter
|
||||
return ESP8266WebServer::CLIENT_IS_GIVEN;
|
||||
}
|
||||
return ESP8266WebServer::CLIENT_REQUEST_CAN_CONTINUE;
|
||||
|
@ -18,7 +18,7 @@
|
||||
|
||||
#ifndef STASSID
|
||||
#define STASSID "your-ssid"
|
||||
#define STAPSK "your-password"
|
||||
#define STAPSK "your-password"
|
||||
#endif
|
||||
|
||||
const char* ssid = STASSID;
|
||||
@ -50,7 +50,7 @@ JfUvYadSYxh3nblvA4OL+iEZiW8NE3hbW6WPXxvS7Euge0uWMPc4uEcnsE0ZVG3m
|
||||
-----END CERTIFICATE-----
|
||||
)EOF";
|
||||
|
||||
static const char serverKey[] PROGMEM = R"EOF(
|
||||
static const char serverKey[] PROGMEM = R"EOF(
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEpQIBAAKCAQEA9UoHBtn4oNKXjRgIOQ/rLxK/iI0a8Q5mDxhfuwa9//FkftSI
|
||||
IFY8UhGk2YNJpnfKOyYWqbqwuJhIZJ2sEIWp2301OnavuGBrpKOgBJJljgH2l/4Z
|
||||
@ -89,24 +89,22 @@ void handleRoot() {
|
||||
digitalWrite(led, 0);
|
||||
}
|
||||
|
||||
void handleNotFound(){
|
||||
void handleNotFound() {
|
||||
digitalWrite(led, 1);
|
||||
String message = "File Not Found\n\n";
|
||||
message += "URI: ";
|
||||
message += server.uri();
|
||||
message += "\nMethod: ";
|
||||
message += (server.method() == HTTP_GET)?"GET":"POST";
|
||||
message += (server.method() == HTTP_GET) ? "GET" : "POST";
|
||||
message += "\nArguments: ";
|
||||
message += server.args();
|
||||
message += "\n";
|
||||
for (uint8_t i=0; i<server.args(); i++){
|
||||
message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
|
||||
}
|
||||
for (uint8_t i = 0; i < server.args(); i++) { message += " " + server.argName(i) + ": " + server.arg(i) + "\n"; }
|
||||
server.send(404, "text/plain", message);
|
||||
digitalWrite(led, 0);
|
||||
}
|
||||
|
||||
void setup(void){
|
||||
void setup(void) {
|
||||
pinMode(led, OUTPUT);
|
||||
digitalWrite(led, 0);
|
||||
Serial.begin(115200);
|
||||
@ -127,9 +125,7 @@ void setup(void){
|
||||
Serial.print("IP address: ");
|
||||
Serial.println(WiFi.localIP());
|
||||
|
||||
if (MDNS.begin("esp8266")) {
|
||||
Serial.println("MDNS responder started");
|
||||
}
|
||||
if (MDNS.begin("esp8266")) { Serial.println("MDNS responder started"); }
|
||||
|
||||
server.getServer().setRSACert(new BearSSL::X509List(serverCert), new BearSSL::PrivateKey(serverKey));
|
||||
|
||||
@ -138,7 +134,7 @@ void setup(void){
|
||||
|
||||
server.on("/", handleRoot);
|
||||
|
||||
server.on("/inline", [](){
|
||||
server.on("/inline", []() {
|
||||
server.send(200, "text/plain", "this works as well");
|
||||
});
|
||||
|
||||
@ -152,17 +148,20 @@ extern "C" void stack_thunk_dump_stack();
|
||||
|
||||
void processKey(Print& out, int hotKey) {
|
||||
switch (hotKey) {
|
||||
case 'd': {
|
||||
case 'd':
|
||||
{
|
||||
HeapSelectDram ephemeral;
|
||||
umm_info(NULL, true);
|
||||
break;
|
||||
}
|
||||
case 'i': {
|
||||
case 'i':
|
||||
{
|
||||
HeapSelectIram ephemeral;
|
||||
umm_info(NULL, true);
|
||||
break;
|
||||
}
|
||||
case 'h': {
|
||||
case 'h':
|
||||
{
|
||||
{
|
||||
HeapSelectIram ephemeral;
|
||||
Serial.printf(PSTR("IRAM ESP.getFreeHeap: %u\n"), ESP.getFreeHeap());
|
||||
@ -185,10 +184,8 @@ void processKey(Print& out, int hotKey) {
|
||||
out.printf_P(PSTR("Restart, ESP.restart(); ...\r\n"));
|
||||
ESP.restart();
|
||||
break;
|
||||
case '\r':
|
||||
out.println();
|
||||
case '\n':
|
||||
break;
|
||||
case '\r': out.println();
|
||||
case '\n': break;
|
||||
case '?':
|
||||
out.println();
|
||||
out.println(F("Press a key + <enter>"));
|
||||
@ -211,7 +208,7 @@ void processKey(Print& out, int hotKey) {
|
||||
}
|
||||
|
||||
|
||||
void loop(void){
|
||||
void loop(void) {
|
||||
server.handleClient();
|
||||
MDNS.update();
|
||||
if (Serial.available() > 0) {
|
||||
|
@ -11,7 +11,7 @@
|
||||
|
||||
#ifndef STASSID
|
||||
#define STASSID "your-ssid"
|
||||
#define STAPSK "your-password"
|
||||
#define STAPSK "your-password"
|
||||
#endif
|
||||
|
||||
const char* ssid = STASSID;
|
||||
@ -39,13 +39,13 @@ void setup() {
|
||||
|
||||
server.on("/", []() {
|
||||
if (!server.authenticate(www_username, www_password))
|
||||
//Basic Auth Method with Custom realm and Failure Response
|
||||
//return server.requestAuthentication(BASIC_AUTH, www_realm, authFailResponse);
|
||||
//Digest Auth Method with realm="Login Required" and empty Failure Response
|
||||
//return server.requestAuthentication(DIGEST_AUTH);
|
||||
//Digest Auth Method with Custom realm and empty Failure Response
|
||||
//return server.requestAuthentication(DIGEST_AUTH, www_realm);
|
||||
//Digest Auth Method with Custom realm and Failure Response
|
||||
// Basic Auth Method with Custom realm and Failure Response
|
||||
// return server.requestAuthentication(BASIC_AUTH, www_realm, authFailResponse);
|
||||
// Digest Auth Method with realm="Login Required" and empty Failure Response
|
||||
// return server.requestAuthentication(DIGEST_AUTH);
|
||||
// Digest Auth Method with Custom realm and empty Failure Response
|
||||
// return server.requestAuthentication(DIGEST_AUTH, www_realm);
|
||||
// Digest Auth Method with Custom realm and Failure Response
|
||||
{
|
||||
return server.requestAuthentication(DIGEST_AUTH, www_realm, authFailResponse);
|
||||
}
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
#ifndef STASSID
|
||||
#define STASSID "your-ssid"
|
||||
#define STAPSK "your-password"
|
||||
#define STAPSK "your-password"
|
||||
#endif
|
||||
|
||||
const char* ssid = STASSID;
|
||||
|
@ -15,21 +15,21 @@
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <ESP8266WebServerSecure.h>
|
||||
|
||||
//Unfortunately it is not possible to have persistent WiFi credentials stored as anything but plain text. Obfuscation would be the only feasible barrier.
|
||||
// Unfortunately it is not possible to have persistent WiFi credentials stored as anything but plain text. Obfuscation would be the only feasible barrier.
|
||||
#ifndef STASSID
|
||||
#define STASSID "your-ssid"
|
||||
#define STAPSK "your-password"
|
||||
#define STAPSK "your-password"
|
||||
#endif
|
||||
|
||||
const char* ssid = STASSID;
|
||||
const char* wifi_pw = STAPSK;
|
||||
|
||||
const String file_credentials = R"(/credentials.txt)"; // LittleFS file name for the saved credentials
|
||||
const String change_creds = "changecreds"; // Address for a credential change
|
||||
const String file_credentials = R"(/credentials.txt)"; // LittleFS file name for the saved credentials
|
||||
const String change_creds = "changecreds"; // Address for a credential change
|
||||
|
||||
//The ESP8266WebServerSecure requires an encryption certificate and matching key.
|
||||
//These can generated with the bash script available in the ESP8266 Arduino repository.
|
||||
//These values can be used for testing but are available publicly so should not be used in production.
|
||||
// The ESP8266WebServerSecure requires an encryption certificate and matching key.
|
||||
// These can generated with the bash script available in the ESP8266 Arduino repository.
|
||||
// These values can be used for testing but are available publicly so should not be used in production.
|
||||
static const char serverCert[] PROGMEM = R"EOF(
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDSzCCAjMCCQD2ahcfZAwXxDANBgkqhkiG9w0BAQsFADCBiTELMAkGA1UEBhMC
|
||||
@ -52,7 +52,7 @@ JfUvYadSYxh3nblvA4OL+iEZiW8NE3hbW6WPXxvS7Euge0uWMPc4uEcnsE0ZVG3m
|
||||
5tAF1D5vAAwA8nfPysumlLsIjohJZo4lgnhB++AlOg==
|
||||
-----END CERTIFICATE-----
|
||||
)EOF";
|
||||
static const char serverKey[] PROGMEM = R"EOF(
|
||||
static const char serverKey[] PROGMEM = R"EOF(
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEpQIBAAKCAQEA9UoHBtn4oNKXjRgIOQ/rLxK/iI0a8Q5mDxhfuwa9//FkftSI
|
||||
IFY8UhGk2YNJpnfKOyYWqbqwuJhIZJ2sEIWp2301OnavuGBrpKOgBJJljgH2l/4Z
|
||||
@ -84,7 +84,7 @@ gz5JWYhbD6c38khSzJb0pNXCo3EuYAVa36kDM96k1BtWuhRS10Q1VXk=
|
||||
|
||||
ESP8266WebServerSecure server(443);
|
||||
|
||||
//These are temporary credentials that will only be used if none are found saved in LittleFS.
|
||||
// These are temporary credentials that will only be used if none are found saved in LittleFS.
|
||||
String login = "admin";
|
||||
const String realm = "global";
|
||||
String H1 = "";
|
||||
@ -93,16 +93,16 @@ String authentication_failed = "User authentication has failed.";
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
|
||||
//Initialize LittleFS to save credentials
|
||||
if(!LittleFS.begin()){
|
||||
Serial.println("LittleFS initialization error, programmer flash configured?");
|
||||
// Initialize LittleFS to save credentials
|
||||
if (!LittleFS.begin()) {
|
||||
Serial.println("LittleFS initialization error, programmer flash configured?");
|
||||
ESP.restart();
|
||||
}
|
||||
}
|
||||
|
||||
//Attempt to load credentials. If the file does not yet exist, they will be set to the default values above
|
||||
// Attempt to load credentials. If the file does not yet exist, they will be set to the default values above
|
||||
loadcredentials();
|
||||
|
||||
//Initialize wifi
|
||||
// Initialize wifi
|
||||
WiFi.mode(WIFI_STA);
|
||||
WiFi.begin(ssid, wifi_pw);
|
||||
if (WiFi.waitForConnectResult() != WL_CONNECTED) {
|
||||
@ -112,8 +112,8 @@ void setup() {
|
||||
}
|
||||
|
||||
server.getServer().setRSACert(new BearSSL::X509List(serverCert), new BearSSL::PrivateKey(serverKey));
|
||||
server.on("/",showcredentialpage); //for this simple example, just show a simple page for changing credentials at the root
|
||||
server.on("/" + change_creds,handlecredentialchange); //handles submission of credentials from the client
|
||||
server.on("/", showcredentialpage); // for this simple example, just show a simple page for changing credentials at the root
|
||||
server.on("/" + change_creds, handlecredentialchange); // handles submission of credentials from the client
|
||||
server.onNotFound(redirect);
|
||||
server.begin();
|
||||
|
||||
@ -127,49 +127,48 @@ void loop() {
|
||||
server.handleClient();
|
||||
}
|
||||
|
||||
//This function redirects home
|
||||
void redirect(){
|
||||
// This function redirects home
|
||||
void redirect() {
|
||||
String url = "https://" + WiFi.localIP().toString();
|
||||
Serial.println("Redirect called. Redirecting to " + url);
|
||||
server.sendHeader("Location", url, true);
|
||||
Serial.println("Header sent.");
|
||||
server.send( 302, "text/plain", ""); // Empty content inhibits Content-length header so we have to close the socket ourselves.
|
||||
server.send(302, "text/plain", ""); // Empty content inhibits Content-length header so we have to close the socket ourselves.
|
||||
Serial.println("Empty page sent.");
|
||||
server.client().stop(); // Stop is needed because we sent no content length
|
||||
server.client().stop(); // Stop is needed because we sent no content length
|
||||
Serial.println("Client stopped.");
|
||||
}
|
||||
|
||||
//This function checks whether the current session has been authenticated. If not, a request for credentials is sent.
|
||||
// This function checks whether the current session has been authenticated. If not, a request for credentials is sent.
|
||||
bool session_authenticated() {
|
||||
Serial.println("Checking authentication.");
|
||||
if (server.authenticateDigest(login,H1)) {
|
||||
if (server.authenticateDigest(login, H1)) {
|
||||
Serial.println("Authentication confirmed.");
|
||||
return true;
|
||||
} else {
|
||||
} else {
|
||||
Serial.println("Not authenticated. Requesting credentials.");
|
||||
server.requestAuthentication(DIGEST_AUTH,realm.c_str(),authentication_failed);
|
||||
server.requestAuthentication(DIGEST_AUTH, realm.c_str(), authentication_failed);
|
||||
redirect();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//This function sends a simple webpage for changing login credentials to the client
|
||||
void showcredentialpage(){
|
||||
// This function sends a simple webpage for changing login credentials to the client
|
||||
void showcredentialpage() {
|
||||
Serial.println("Show credential page called.");
|
||||
if(!session_authenticated()){
|
||||
return;
|
||||
}
|
||||
if (!session_authenticated()) { return; }
|
||||
|
||||
Serial.println("Forming credential modification page.");
|
||||
|
||||
String page;
|
||||
page = R"(<html>)";
|
||||
|
||||
page+=
|
||||
R"(
|
||||
page +=
|
||||
R"(
|
||||
<h2>Login Credentials</h2><br>
|
||||
|
||||
<form action=")" + change_creds + R"(" method="post">
|
||||
<form action=")"
|
||||
+ change_creds + R"(" method="post">
|
||||
Login:<br>
|
||||
<input type="text" name="login"><br>
|
||||
Password:<br>
|
||||
@ -178,8 +177,7 @@ void showcredentialpage(){
|
||||
<input type="password" name="password_duplicate"><br>
|
||||
<p><button type="submit" name="newcredentials">Change Credentials</button></p>
|
||||
</form><br>
|
||||
)"
|
||||
;
|
||||
)";
|
||||
|
||||
page += R"(</html>)";
|
||||
|
||||
@ -188,17 +186,16 @@ void showcredentialpage(){
|
||||
server.send(200, "text/html", page);
|
||||
}
|
||||
|
||||
//Saves credentials to LittleFS
|
||||
void savecredentials(String new_login, String new_password)
|
||||
{
|
||||
//Set global variables to new values
|
||||
login=new_login;
|
||||
H1=ESP8266WebServer::credentialHash(new_login,realm,new_password);
|
||||
// Saves credentials to LittleFS
|
||||
void savecredentials(String new_login, String new_password) {
|
||||
// Set global variables to new values
|
||||
login = new_login;
|
||||
H1 = ESP8266WebServer::credentialHash(new_login, realm, new_password);
|
||||
|
||||
//Save new values to LittleFS for loading on next reboot
|
||||
// Save new values to LittleFS for loading on next reboot
|
||||
Serial.println("Saving credentials.");
|
||||
File f=LittleFS.open(file_credentials,"w"); //open as a brand new file, discard old contents
|
||||
if(f){
|
||||
File f = LittleFS.open(file_credentials, "w"); // open as a brand new file, discard old contents
|
||||
if (f) {
|
||||
Serial.println("Modifying credentials in file system.");
|
||||
f.println(login);
|
||||
f.println(H1);
|
||||
@ -209,19 +206,18 @@ void savecredentials(String new_login, String new_password)
|
||||
Serial.println("Credentials saved.");
|
||||
}
|
||||
|
||||
//loads credentials from LittleFS
|
||||
void loadcredentials()
|
||||
{
|
||||
// loads credentials from LittleFS
|
||||
void loadcredentials() {
|
||||
Serial.println("Searching for credentials.");
|
||||
File f;
|
||||
f=LittleFS.open(file_credentials,"r");
|
||||
if(f){
|
||||
f = LittleFS.open(file_credentials, "r");
|
||||
if (f) {
|
||||
Serial.println("Loading credentials from file system.");
|
||||
String mod=f.readString(); //read the file to a String
|
||||
int index_1=mod.indexOf('\n',0); //locate the first line break
|
||||
int index_2=mod.indexOf('\n',index_1+1); //locate the second line break
|
||||
login=mod.substring(0,index_1-1); //get the first line (excluding the line break)
|
||||
H1=mod.substring(index_1+1,index_2-1); //get the second line (excluding the line break)
|
||||
String mod = f.readString(); // read the file to a String
|
||||
int index_1 = mod.indexOf('\n', 0); // locate the first line break
|
||||
int index_2 = mod.indexOf('\n', index_1 + 1); // locate the second line break
|
||||
login = mod.substring(0, index_1 - 1); // get the first line (excluding the line break)
|
||||
H1 = mod.substring(index_1 + 1, index_2 - 1); // get the second line (excluding the line break)
|
||||
f.close();
|
||||
} else {
|
||||
String default_login = "admin";
|
||||
@ -229,17 +225,15 @@ void loadcredentials()
|
||||
Serial.println("None found. Setting to default credentials.");
|
||||
Serial.println("user:" + default_login);
|
||||
Serial.println("password:" + default_password);
|
||||
login=default_login;
|
||||
H1=ESP8266WebServer::credentialHash(default_login,realm,default_password);
|
||||
login = default_login;
|
||||
H1 = ESP8266WebServer::credentialHash(default_login, realm, default_password);
|
||||
}
|
||||
}
|
||||
|
||||
//This function handles a credential change from a client.
|
||||
// This function handles a credential change from a client.
|
||||
void handlecredentialchange() {
|
||||
Serial.println("Handle credential change called.");
|
||||
if(!session_authenticated()){
|
||||
return;
|
||||
}
|
||||
if (!session_authenticated()) { return; }
|
||||
|
||||
Serial.println("Handling credential change request from client.");
|
||||
|
||||
@ -247,9 +241,9 @@ void handlecredentialchange() {
|
||||
String pw1 = server.arg("password");
|
||||
String pw2 = server.arg("password_duplicate");
|
||||
|
||||
if(login != "" && pw1 != "" && pw1 == pw2){
|
||||
if (login != "" && pw1 != "" && pw1 == pw2) {
|
||||
|
||||
savecredentials(login,pw1);
|
||||
savecredentials(login, pw1);
|
||||
server.send(200, "text/plain", "Credentials updated");
|
||||
redirect();
|
||||
} else {
|
||||
|
@ -8,7 +8,7 @@
|
||||
|
||||
#ifndef STASSID
|
||||
#define STASSID "your-ssid"
|
||||
#define STAPSK "your-password"
|
||||
#define STAPSK "your-password"
|
||||
#endif
|
||||
|
||||
const char *ssid = STASSID;
|
||||
@ -33,9 +33,7 @@ void setup(void) {
|
||||
Serial.print("IP address: ");
|
||||
Serial.println(WiFi.localIP());
|
||||
|
||||
if (MDNS.begin("esp8266")) {
|
||||
Serial.println("MDNS responder started");
|
||||
}
|
||||
if (MDNS.begin("esp8266")) { Serial.println("MDNS responder started"); }
|
||||
|
||||
server.on(F("/"), []() {
|
||||
server.send(200, "text/plain", "hello from esp8266!");
|
||||
|
@ -5,10 +5,10 @@
|
||||
|
||||
#ifndef STASSID
|
||||
#define STASSID "your-ssid"
|
||||
#define STAPSK "your-password"
|
||||
#define STAPSK "your-password"
|
||||
#endif
|
||||
|
||||
const char* ssid = STASSID;
|
||||
const char* ssid = STASSID;
|
||||
const char* password = STAPSK;
|
||||
|
||||
ESP8266WebServer server(80);
|
||||
@ -62,9 +62,7 @@ void handleForm() {
|
||||
} else {
|
||||
digitalWrite(led, 1);
|
||||
String message = "POST form was:\n";
|
||||
for (uint8_t i = 0; i < server.args(); i++) {
|
||||
message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
|
||||
}
|
||||
for (uint8_t i = 0; i < server.args(); i++) { message += " " + server.argName(i) + ": " + server.arg(i) + "\n"; }
|
||||
server.send(200, "text/plain", message);
|
||||
digitalWrite(led, 0);
|
||||
}
|
||||
@ -80,9 +78,7 @@ void handleNotFound() {
|
||||
message += "\nArguments: ";
|
||||
message += server.args();
|
||||
message += "\n";
|
||||
for (uint8_t i = 0; i < server.args(); i++) {
|
||||
message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
|
||||
}
|
||||
for (uint8_t i = 0; i < server.args(); i++) { message += " " + server.argName(i) + ": " + server.arg(i) + "\n"; }
|
||||
server.send(404, "text/plain", message);
|
||||
digitalWrite(led, 0);
|
||||
}
|
||||
@ -105,9 +101,7 @@ void setup(void) {
|
||||
Serial.print("IP address: ");
|
||||
Serial.println(WiFi.localIP());
|
||||
|
||||
if (MDNS.begin("esp8266")) {
|
||||
Serial.println("MDNS responder started");
|
||||
}
|
||||
if (MDNS.begin("esp8266")) { Serial.println("MDNS responder started"); }
|
||||
|
||||
server.on("/", handleRoot);
|
||||
|
||||
|
@ -42,11 +42,11 @@ extern "C" {
|
||||
|
||||
#ifndef STASSID
|
||||
#define STASSID "your-ssid"
|
||||
#define STAPSK "your-password"
|
||||
#define STAPSK "your-password"
|
||||
#endif
|
||||
|
||||
const char* ssid = STASSID;
|
||||
const char* password = STAPSK;
|
||||
const char *ssid = STASSID;
|
||||
const char *password = STAPSK;
|
||||
const unsigned int port = 80;
|
||||
|
||||
ESP8266WebServer server(port);
|
||||
@ -76,20 +76,16 @@ void handleNotFound() {
|
||||
message += "\nArguments: ";
|
||||
message += server.args();
|
||||
message += "\n";
|
||||
for (uint8_t i = 0; i < server.args(); i++) {
|
||||
message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
|
||||
}
|
||||
for (uint8_t i = 0; i < server.args(); i++) { message += " " + server.argName(i) + ": " + server.arg(i) + "\n"; }
|
||||
server.send(404, "text/plain", message);
|
||||
}
|
||||
|
||||
void SSEKeepAlive() {
|
||||
for (uint8_t i = 0; i < SSE_MAX_CHANNELS; i++) {
|
||||
if (!(subscription[i].clientIP)) {
|
||||
continue;
|
||||
}
|
||||
if (!(subscription[i].clientIP)) { continue; }
|
||||
if (subscription[i].client.connected()) {
|
||||
Serial.printf_P(PSTR("SSEKeepAlive - client is still listening on channel %d\n"), i);
|
||||
subscription[i].client.println(F("event: event\ndata: { \"TYPE\":\"KEEP-ALIVE\" }\n")); // Extra newline required by SSE standard
|
||||
subscription[i].client.println(F("event: event\ndata: { \"TYPE\":\"KEEP-ALIVE\" }\n")); // Extra newline required by SSE standard
|
||||
} else {
|
||||
Serial.printf_P(PSTR("SSEKeepAlive - client not listening on channel %d, remove subscription\n"), i);
|
||||
subscription[i].keepAliveTimer.detach();
|
||||
@ -106,15 +102,15 @@ void SSEKeepAlive() {
|
||||
void SSEHandler(uint8_t channel) {
|
||||
WiFiClient client = server.client();
|
||||
SSESubscription &s = subscription[channel];
|
||||
if (s.clientIP != client.remoteIP()) { // IP addresses don't match, reject this client
|
||||
if (s.clientIP != client.remoteIP()) { // IP addresses don't match, reject this client
|
||||
Serial.printf_P(PSTR("SSEHandler - unregistered client with IP %s tries to listen\n"), server.client().remoteIP().toString().c_str());
|
||||
return handleNotFound();
|
||||
}
|
||||
client.setNoDelay(true);
|
||||
client.setSync(true);
|
||||
Serial.printf_P(PSTR("SSEHandler - registered client with IP %s is listening\n"), IPAddress(s.clientIP).toString().c_str());
|
||||
s.client = client; // capture SSE server client connection
|
||||
server.setContentLength(CONTENT_LENGTH_UNKNOWN); // the payload can go on forever
|
||||
s.client = client; // capture SSE server client connection
|
||||
server.setContentLength(CONTENT_LENGTH_UNKNOWN); // the payload can go on forever
|
||||
server.sendContent_P(PSTR("HTTP/1.1 200 OK\nContent-Type: text/event-stream;\nConnection: keep-alive\nCache-Control: no-cache\nAccess-Control-Allow-Origin: *\n\n"));
|
||||
s.keepAliveTimer.attach_scheduled(30.0, SSEKeepAlive); // Refresh time every 30s for demo
|
||||
}
|
||||
@ -122,28 +118,20 @@ void SSEHandler(uint8_t channel) {
|
||||
void handleAll() {
|
||||
const char *uri = server.uri().c_str();
|
||||
const char *restEvents = PSTR("/rest/events/");
|
||||
if (strncmp_P(uri, restEvents, strlen_P(restEvents))) {
|
||||
return handleNotFound();
|
||||
}
|
||||
uri += strlen_P(restEvents); // Skip the "/rest/events/" and get to the channel number
|
||||
if (strncmp_P(uri, restEvents, strlen_P(restEvents))) { return handleNotFound(); }
|
||||
uri += strlen_P(restEvents); // Skip the "/rest/events/" and get to the channel number
|
||||
unsigned int channel = atoi(uri);
|
||||
if (channel < SSE_MAX_CHANNELS) {
|
||||
return SSEHandler(channel);
|
||||
}
|
||||
if (channel < SSE_MAX_CHANNELS) { return SSEHandler(channel); }
|
||||
handleNotFound();
|
||||
};
|
||||
|
||||
void SSEBroadcastState(const char *sensorName, unsigned short prevSensorValue, unsigned short sensorValue) {
|
||||
for (uint8_t i = 0; i < SSE_MAX_CHANNELS; i++) {
|
||||
if (!(subscription[i].clientIP)) {
|
||||
continue;
|
||||
}
|
||||
if (!(subscription[i].clientIP)) { continue; }
|
||||
String IPaddrstr = IPAddress(subscription[i].clientIP).toString();
|
||||
if (subscription[i].client.connected()) {
|
||||
Serial.printf_P(PSTR("broadcast status change to client IP %s on channel %d for %s with new state %d\n"),
|
||||
IPaddrstr.c_str(), i, sensorName, sensorValue);
|
||||
subscription[i].client.printf_P(PSTR("event: event\ndata: {\"TYPE\":\"STATE\", \"%s\":{\"state\":%d, \"prevState\":%d}}\n\n"),
|
||||
sensorName, sensorValue, prevSensorValue);
|
||||
Serial.printf_P(PSTR("broadcast status change to client IP %s on channel %d for %s with new state %d\n"), IPaddrstr.c_str(), i, sensorName, sensorValue);
|
||||
subscription[i].client.printf_P(PSTR("event: event\ndata: {\"TYPE\":\"STATE\", \"%s\":{\"state\":%d, \"prevState\":%d}}\n\n"), sensorName, sensorValue, prevSensorValue);
|
||||
} else {
|
||||
Serial.printf_P(PSTR("SSEBroadcastState - client %s registered on channel %d but not listening\n"), IPaddrstr.c_str(), i);
|
||||
}
|
||||
@ -152,7 +140,7 @@ void SSEBroadcastState(const char *sensorName, unsigned short prevSensorValue, u
|
||||
|
||||
// Simulate sensors
|
||||
void updateSensor(sensorType &sensor) {
|
||||
unsigned short newVal = (unsigned short)RANDOM_REG32; // (not so good) random value for the sensor
|
||||
unsigned short newVal = (unsigned short)RANDOM_REG32; // (not so good) random value for the sensor
|
||||
Serial.printf_P(PSTR("update sensor %s - previous state: %d, new state: %d\n"), sensor.name, sensor.value, newVal);
|
||||
if (sensor.value != newVal) {
|
||||
SSEBroadcastState(sensor.name, sensor.value, newVal); // only broadcast if state is different
|
||||
@ -167,7 +155,7 @@ void handleSubscribe() {
|
||||
}
|
||||
|
||||
uint8_t channel;
|
||||
IPAddress clientIP = server.client().remoteIP(); // get IP address of client
|
||||
IPAddress clientIP = server.client().remoteIP(); // get IP address of client
|
||||
String SSEurl = F("http://");
|
||||
SSEurl += WiFi.localIP().toString();
|
||||
SSEurl += F(":");
|
||||
@ -176,14 +164,12 @@ void handleSubscribe() {
|
||||
SSEurl += F("/rest/events/");
|
||||
|
||||
++subscriptionCount;
|
||||
for (channel = 0; channel < SSE_MAX_CHANNELS; channel++) // Find first free slot
|
||||
if (!subscription[channel].clientIP) {
|
||||
break;
|
||||
}
|
||||
subscription[channel] = {clientIP, server.client(), Ticker()};
|
||||
for (channel = 0; channel < SSE_MAX_CHANNELS; channel++) // Find first free slot
|
||||
if (!subscription[channel].clientIP) { break; }
|
||||
subscription[channel] = { clientIP, server.client(), Ticker() };
|
||||
SSEurl += channel;
|
||||
Serial.printf_P(PSTR("Allocated channel %d, on uri %s\n"), channel, SSEurl.substring(offset).c_str());
|
||||
//server.on(SSEurl.substring(offset), std::bind(SSEHandler, &(subscription[channel])));
|
||||
// server.on(SSEurl.substring(offset), std::bind(SSEHandler, &(subscription[channel])));
|
||||
Serial.printf_P(PSTR("subscription for client IP %s: event bus location: %s\n"), clientIP.toString().c_str(), SSEurl.c_str());
|
||||
server.send_P(200, "text/plain", SSEurl.c_str());
|
||||
}
|
||||
@ -200,16 +186,14 @@ void setup(void) {
|
||||
WiFi.mode(WIFI_STA);
|
||||
WiFi.begin(ssid, password);
|
||||
Serial.println("");
|
||||
while (WiFi.status() != WL_CONNECTED) { // Wait for connection
|
||||
while (WiFi.status() != WL_CONNECTED) { // Wait for connection
|
||||
delay(500);
|
||||
Serial.print(".");
|
||||
}
|
||||
Serial.printf_P(PSTR("\nConnected to %s with IP address: %s\n"), ssid, WiFi.localIP().toString().c_str());
|
||||
if (MDNS.begin("esp8266")) {
|
||||
Serial.println("MDNS responder started");
|
||||
}
|
||||
if (MDNS.begin("esp8266")) { Serial.println("MDNS responder started"); }
|
||||
|
||||
startServers(); // start web and SSE servers
|
||||
startServers(); // start web and SSE servers
|
||||
sensor[0].name = "sensorA";
|
||||
sensor[1].name = "sensorB";
|
||||
updateSensor(sensor[0]);
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
#ifndef STASSID
|
||||
#define STASSID "your-ssid"
|
||||
#define STAPSK "your-password"
|
||||
#define STAPSK "your-password"
|
||||
#endif
|
||||
|
||||
const char* ssid = STASSID;
|
||||
@ -12,7 +12,7 @@ const char* password = STAPSK;
|
||||
|
||||
ESP8266WebServer server(80);
|
||||
|
||||
//Check if header is present and correct
|
||||
// Check if header is present and correct
|
||||
bool is_authenticated() {
|
||||
Serial.println("Enter is_authenticated");
|
||||
if (server.hasHeader("Cookie")) {
|
||||
@ -28,7 +28,7 @@ bool is_authenticated() {
|
||||
return false;
|
||||
}
|
||||
|
||||
//login page, also called for disconnect
|
||||
// login page, also called for disconnect
|
||||
void handleLogin() {
|
||||
String msg;
|
||||
if (server.hasHeader("Cookie")) {
|
||||
@ -45,7 +45,7 @@ void handleLogin() {
|
||||
return;
|
||||
}
|
||||
if (server.hasArg("USERNAME") && server.hasArg("PASSWORD")) {
|
||||
if (server.arg("USERNAME") == "admin" && server.arg("PASSWORD") == "admin") {
|
||||
if (server.arg("USERNAME") == "admin" && server.arg("PASSWORD") == "admin") {
|
||||
server.sendHeader("Location", "/");
|
||||
server.sendHeader("Cache-Control", "no-cache");
|
||||
server.sendHeader("Set-Cookie", "ESPSESSIONID=1");
|
||||
@ -64,7 +64,7 @@ void handleLogin() {
|
||||
server.send(200, "text/html", content);
|
||||
}
|
||||
|
||||
//root page can be accessed only if authentication is ok
|
||||
// root page can be accessed only if authentication is ok
|
||||
void handleRoot() {
|
||||
Serial.println("Enter handleRoot");
|
||||
String header;
|
||||
@ -75,14 +75,12 @@ void handleRoot() {
|
||||
return;
|
||||
}
|
||||
String content = "<html><body><H2>hello, you successfully connected to esp8266!</H2><br>";
|
||||
if (server.hasHeader("User-Agent")) {
|
||||
content += "the user agent used is : " + server.header("User-Agent") + "<br><br>";
|
||||
}
|
||||
if (server.hasHeader("User-Agent")) { content += "the user agent used is : " + server.header("User-Agent") + "<br><br>"; }
|
||||
content += "You can access this page until you <a href=\"/login?DISCONNECT=YES\">disconnect</a></body></html>";
|
||||
server.send(200, "text/html", content);
|
||||
}
|
||||
|
||||
//no need authentication
|
||||
// no need authentication
|
||||
void handleNotFound() {
|
||||
String message = "File Not Found\n\n";
|
||||
message += "URI: ";
|
||||
@ -92,9 +90,7 @@ void handleNotFound() {
|
||||
message += "\nArguments: ";
|
||||
message += server.args();
|
||||
message += "\n";
|
||||
for (uint8_t i = 0; i < server.args(); i++) {
|
||||
message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
|
||||
}
|
||||
for (uint8_t i = 0; i < server.args(); i++) { message += " " + server.argName(i) + ": " + server.arg(i) + "\n"; }
|
||||
server.send(404, "text/plain", message);
|
||||
}
|
||||
|
||||
@ -123,7 +119,7 @@ void setup(void) {
|
||||
});
|
||||
|
||||
server.onNotFound(handleNotFound);
|
||||
//ask server to track these headers
|
||||
// ask server to track these headers
|
||||
server.collectHeaders("User-Agent", "Cookie");
|
||||
server.begin();
|
||||
Serial.println("HTTP server started");
|
||||
|
@ -9,10 +9,10 @@
|
||||
#include <Arduino.h>
|
||||
#include <ESP8266WebServer.h>
|
||||
|
||||
#include "secrets.h" // add WLAN Credentials in here.
|
||||
#include "secrets.h" // add WLAN Credentials in here.
|
||||
|
||||
#include <FS.h> // File System for Web Server Files
|
||||
#include <LittleFS.h> // This file system is used.
|
||||
#include <FS.h> // File System for Web Server Files
|
||||
#include <LittleFS.h> // This file system is used.
|
||||
|
||||
// mark parameters not used in example
|
||||
#define UNUSED __attribute__((unused))
|
||||
@ -41,13 +41,11 @@ void handleRedirect() {
|
||||
TRACE("Redirect...");
|
||||
String url = "/index.htm";
|
||||
|
||||
if (!LittleFS.exists(url)) {
|
||||
url = "/$update.htm";
|
||||
}
|
||||
if (!LittleFS.exists(url)) { url = "/$update.htm"; }
|
||||
|
||||
server.sendHeader("Location", url, true);
|
||||
server.send(302);
|
||||
} // handleRedirect()
|
||||
} // handleRedirect()
|
||||
|
||||
|
||||
// This function is called when the WebServer was requested to list all existing files in the filesystem.
|
||||
@ -58,20 +56,18 @@ void handleListFiles() {
|
||||
|
||||
result += "[\n";
|
||||
while (dir.next()) {
|
||||
if (result.length() > 4) {
|
||||
result += ",";
|
||||
}
|
||||
if (result.length() > 4) { result += ","; }
|
||||
result += " {";
|
||||
result += " \"name\": \"" + dir.fileName() + "\", ";
|
||||
result += " \"size\": " + String(dir.fileSize()) + ", ";
|
||||
result += " \"time\": " + String(dir.fileTime());
|
||||
result += " }\n";
|
||||
// jc.addProperty("size", dir.fileSize());
|
||||
} // while
|
||||
} // while
|
||||
result += "]";
|
||||
server.sendHeader("Cache-Control", "no-cache");
|
||||
server.send(200, "text/javascript; charset=utf-8", result);
|
||||
} // handleListFiles()
|
||||
} // handleListFiles()
|
||||
|
||||
|
||||
// This function is called when the sysInfo service was requested.
|
||||
@ -90,96 +86,84 @@ void handleSysInfo() {
|
||||
|
||||
server.sendHeader("Cache-Control", "no-cache");
|
||||
server.send(200, "text/javascript; charset=utf-8", result);
|
||||
} // handleSysInfo()
|
||||
} // handleSysInfo()
|
||||
|
||||
|
||||
// ===== Request Handler class used to answer more complex requests =====
|
||||
|
||||
// The FileServerHandler is registered to the web server to support DELETE and UPLOAD of files into the filesystem.
|
||||
class FileServerHandler : public RequestHandler {
|
||||
public:
|
||||
// @brief Construct a new File Server Handler object
|
||||
// @param fs The file system to be used.
|
||||
// @param path Path to the root folder in the file system that is used for serving static data down and upload.
|
||||
// @param cache_header Cache Header to be used in replies.
|
||||
FileServerHandler() {
|
||||
TRACE("FileServerHandler is registered\n");
|
||||
}
|
||||
public:
|
||||
// @brief Construct a new File Server Handler object
|
||||
// @param fs The file system to be used.
|
||||
// @param path Path to the root folder in the file system that is used for serving static data down and upload.
|
||||
// @param cache_header Cache Header to be used in replies.
|
||||
FileServerHandler() {
|
||||
TRACE("FileServerHandler is registered\n");
|
||||
}
|
||||
|
||||
|
||||
// @brief check incoming request. Can handle POST for uploads and DELETE.
|
||||
// @param requestMethod method of the http request line.
|
||||
// @param requestUri request ressource from the http request line.
|
||||
// @return true when method can be handled.
|
||||
bool canHandle(HTTPMethod requestMethod, const String UNUSED &_uri) override {
|
||||
return ((requestMethod == HTTP_POST) || (requestMethod == HTTP_DELETE));
|
||||
} // canHandle()
|
||||
// @brief check incoming request. Can handle POST for uploads and DELETE.
|
||||
// @param requestMethod method of the http request line.
|
||||
// @param requestUri request ressource from the http request line.
|
||||
// @return true when method can be handled.
|
||||
bool canHandle(HTTPMethod requestMethod, const String UNUSED &_uri) override {
|
||||
return ((requestMethod == HTTP_POST) || (requestMethod == HTTP_DELETE));
|
||||
} // canHandle()
|
||||
|
||||
|
||||
bool canUpload(const String &uri) override {
|
||||
// only allow upload on root fs level.
|
||||
return (uri == "/");
|
||||
} // canUpload()
|
||||
bool canUpload(const String &uri) override {
|
||||
// only allow upload on root fs level.
|
||||
return (uri == "/");
|
||||
} // canUpload()
|
||||
|
||||
|
||||
bool handle(ESP8266WebServer &server, HTTPMethod requestMethod, const String &requestUri) override {
|
||||
// ensure that filename starts with '/'
|
||||
String fName = requestUri;
|
||||
if (!fName.startsWith("/")) {
|
||||
fName = "/" + fName;
|
||||
}
|
||||
bool handle(ESP8266WebServer &server, HTTPMethod requestMethod, const String &requestUri) override {
|
||||
// ensure that filename starts with '/'
|
||||
String fName = requestUri;
|
||||
if (!fName.startsWith("/")) { fName = "/" + fName; }
|
||||
|
||||
if (requestMethod == HTTP_POST) {
|
||||
// all done in upload. no other forms.
|
||||
if (requestMethod == HTTP_POST) {
|
||||
// all done in upload. no other forms.
|
||||
|
||||
} else if (requestMethod == HTTP_DELETE) {
|
||||
if (LittleFS.exists(fName)) {
|
||||
LittleFS.remove(fName);
|
||||
}
|
||||
} // if
|
||||
} else if (requestMethod == HTTP_DELETE) {
|
||||
if (LittleFS.exists(fName)) { LittleFS.remove(fName); }
|
||||
} // if
|
||||
|
||||
server.send(200); // all done.
|
||||
return (true);
|
||||
} // handle()
|
||||
server.send(200); // all done.
|
||||
return (true);
|
||||
} // handle()
|
||||
|
||||
|
||||
// uploading process
|
||||
void upload(ESP8266WebServer UNUSED &server, const String UNUSED &_requestUri, HTTPUpload &upload) override {
|
||||
// ensure that filename starts with '/'
|
||||
String fName = upload.filename;
|
||||
if (!fName.startsWith("/")) {
|
||||
fName = "/" + fName;
|
||||
}
|
||||
// uploading process
|
||||
void upload(ESP8266WebServer UNUSED &server, const String UNUSED &_requestUri, HTTPUpload &upload) override {
|
||||
// ensure that filename starts with '/'
|
||||
String fName = upload.filename;
|
||||
if (!fName.startsWith("/")) { fName = "/" + fName; }
|
||||
|
||||
if (upload.status == UPLOAD_FILE_START) {
|
||||
// Open the file
|
||||
if (LittleFS.exists(fName)) {
|
||||
LittleFS.remove(fName);
|
||||
} // if
|
||||
_fsUploadFile = LittleFS.open(fName, "w");
|
||||
if (upload.status == UPLOAD_FILE_START) {
|
||||
// Open the file
|
||||
if (LittleFS.exists(fName)) { LittleFS.remove(fName); } // if
|
||||
_fsUploadFile = LittleFS.open(fName, "w");
|
||||
|
||||
} else if (upload.status == UPLOAD_FILE_WRITE) {
|
||||
// Write received bytes
|
||||
if (_fsUploadFile) {
|
||||
_fsUploadFile.write(upload.buf, upload.currentSize);
|
||||
}
|
||||
} else if (upload.status == UPLOAD_FILE_WRITE) {
|
||||
// Write received bytes
|
||||
if (_fsUploadFile) { _fsUploadFile.write(upload.buf, upload.currentSize); }
|
||||
|
||||
} else if (upload.status == UPLOAD_FILE_END) {
|
||||
// Close the file
|
||||
if (_fsUploadFile) {
|
||||
_fsUploadFile.close();
|
||||
}
|
||||
} // if
|
||||
} // upload()
|
||||
} else if (upload.status == UPLOAD_FILE_END) {
|
||||
// Close the file
|
||||
if (_fsUploadFile) { _fsUploadFile.close(); }
|
||||
} // if
|
||||
} // upload()
|
||||
|
||||
protected:
|
||||
File _fsUploadFile;
|
||||
protected:
|
||||
File _fsUploadFile;
|
||||
};
|
||||
|
||||
|
||||
// Setup everything to make the webserver work.
|
||||
void setup(void) {
|
||||
delay(3000); // wait for serial monitor to start completely.
|
||||
delay(3000); // wait for serial monitor to start completely.
|
||||
|
||||
// Use Serial port for some trace information from the example
|
||||
Serial.begin(115200);
|
||||
@ -250,12 +234,12 @@ void setup(void) {
|
||||
|
||||
server.begin();
|
||||
TRACE("hostname=%s\n", WiFi.getHostname());
|
||||
} // setup
|
||||
} // setup
|
||||
|
||||
|
||||
// run the server...
|
||||
void loop(void) {
|
||||
server.handleClient();
|
||||
} // loop()
|
||||
} // loop()
|
||||
|
||||
// end.
|
||||
|
@ -9,7 +9,7 @@
|
||||
|
||||
#ifndef STASSID
|
||||
#define STASSID "your-ssid"
|
||||
#define STAPSK "your-password"
|
||||
#define STAPSK "your-password"
|
||||
#endif
|
||||
|
||||
const char* host = "esp8266-webupdate";
|
||||
@ -31,34 +31,36 @@ void setup(void) {
|
||||
server.sendHeader("Connection", "close");
|
||||
server.send(200, "text/html", serverIndex);
|
||||
});
|
||||
server.on("/update", HTTP_POST, []() {
|
||||
server.sendHeader("Connection", "close");
|
||||
server.send(200, "text/plain", (Update.hasError()) ? "FAIL" : "OK");
|
||||
ESP.restart();
|
||||
}, []() {
|
||||
HTTPUpload& upload = server.upload();
|
||||
if (upload.status == UPLOAD_FILE_START) {
|
||||
Serial.setDebugOutput(true);
|
||||
WiFiUDP::stopAll();
|
||||
Serial.printf("Update: %s\n", upload.filename.c_str());
|
||||
uint32_t maxSketchSpace = (ESP.getFreeSketchSpace() - 0x1000) & 0xFFFFF000;
|
||||
if (!Update.begin(maxSketchSpace)) { //start with max available size
|
||||
Update.printError(Serial);
|
||||
server.on(
|
||||
"/update", HTTP_POST, []() {
|
||||
server.sendHeader("Connection", "close");
|
||||
server.send(200, "text/plain", (Update.hasError()) ? "FAIL" : "OK");
|
||||
ESP.restart();
|
||||
},
|
||||
[]() {
|
||||
HTTPUpload& upload = server.upload();
|
||||
if (upload.status == UPLOAD_FILE_START) {
|
||||
Serial.setDebugOutput(true);
|
||||
WiFiUDP::stopAll();
|
||||
Serial.printf("Update: %s\n", upload.filename.c_str());
|
||||
uint32_t maxSketchSpace = (ESP.getFreeSketchSpace() - 0x1000) & 0xFFFFF000;
|
||||
if (!Update.begin(maxSketchSpace)) { // start with max available size
|
||||
Update.printError(Serial);
|
||||
}
|
||||
} else if (upload.status == UPLOAD_FILE_WRITE) {
|
||||
if (Update.write(upload.buf, upload.currentSize) != upload.currentSize) {
|
||||
Update.printError(Serial);
|
||||
}
|
||||
} else if (upload.status == UPLOAD_FILE_END) {
|
||||
if (Update.end(true)) { // true to set the size to the current progress
|
||||
Serial.printf("Update Success: %u\nRebooting...\n", upload.totalSize);
|
||||
} else {
|
||||
Update.printError(Serial);
|
||||
}
|
||||
Serial.setDebugOutput(false);
|
||||
}
|
||||
} else if (upload.status == UPLOAD_FILE_WRITE) {
|
||||
if (Update.write(upload.buf, upload.currentSize) != upload.currentSize) {
|
||||
Update.printError(Serial);
|
||||
}
|
||||
} else if (upload.status == UPLOAD_FILE_END) {
|
||||
if (Update.end(true)) { //true to set the size to the current progress
|
||||
Serial.printf("Update Success: %u\nRebooting...\n", upload.totalSize);
|
||||
} else {
|
||||
Update.printError(Serial);
|
||||
}
|
||||
Serial.setDebugOutput(false);
|
||||
}
|
||||
yield();
|
||||
});
|
||||
yield();
|
||||
});
|
||||
server.begin();
|
||||
MDNS.addService("http", "tcp", 80);
|
||||
|
||||
|
@ -41,7 +41,7 @@
|
||||
|
||||
#ifndef STASSID
|
||||
#define STASSID "your-ssid"
|
||||
#define STAPSK "your-password"
|
||||
#define STAPSK "your-password"
|
||||
#endif
|
||||
|
||||
const char *ssid = STASSID;
|
||||
@ -72,9 +72,7 @@ void setClock() {
|
||||
|
||||
// Try and connect using a WiFiClientBearSSL to specified host:port and dump URL
|
||||
void fetchURL(BearSSL::WiFiClientSecure *client, const char *host, const uint16_t port, const char *path) {
|
||||
if (!path) {
|
||||
path = "/";
|
||||
}
|
||||
if (!path) { path = "/"; }
|
||||
|
||||
Serial.printf("Trying: %s:443...", host);
|
||||
client->connect(host, port);
|
||||
@ -94,11 +92,9 @@ void fetchURL(BearSSL::WiFiClientSecure *client, const char *host, const uint16_
|
||||
do {
|
||||
char tmp[32];
|
||||
memset(tmp, 0, 32);
|
||||
int rlen = client->read((uint8_t*)tmp, sizeof(tmp) - 1);
|
||||
int rlen = client->read((uint8_t *)tmp, sizeof(tmp) - 1);
|
||||
yield();
|
||||
if (rlen < 0) {
|
||||
break;
|
||||
}
|
||||
if (rlen < 0) { break; }
|
||||
// Only print out first line up to \r, then abort connection
|
||||
char *nl = strchr(tmp, '\r');
|
||||
if (nl) {
|
||||
@ -136,13 +132,13 @@ void setup() {
|
||||
Serial.println("IP address: ");
|
||||
Serial.println(WiFi.localIP());
|
||||
|
||||
setClock(); // Required for X.509 validation
|
||||
setClock(); // Required for X.509 validation
|
||||
|
||||
int numCerts = certStore.initCertStore(LittleFS, PSTR("/certs.idx"), PSTR("/certs.ar"));
|
||||
Serial.printf("Number of CA certs read: %d\n", numCerts);
|
||||
if (numCerts == 0) {
|
||||
Serial.printf("No certs found. Did you run certs-from-mozilla.py and upload the LittleFS directory before running?\n");
|
||||
return; // Can't connect to anything w/o certs!
|
||||
return; // Can't connect to anything w/o certs!
|
||||
}
|
||||
|
||||
BearSSL::WiFiClientSecure *bear = new BearSSL::WiFiClientSecure();
|
||||
@ -156,9 +152,7 @@ void setup() {
|
||||
void loop() {
|
||||
Serial.printf("\nPlease enter a website address (www.blah.com) to connect to: ");
|
||||
String site;
|
||||
do {
|
||||
site = Serial.readString();
|
||||
} while (site == "");
|
||||
do { site = Serial.readString(); } while (site == "");
|
||||
// Strip newline if present
|
||||
site.replace(String("\r"), emptyString);
|
||||
site.replace(String("\n"), emptyString);
|
||||
@ -170,4 +164,3 @@ void loop() {
|
||||
fetchURL(bear, site.c_str(), 443, "/");
|
||||
delete bear;
|
||||
}
|
||||
|
||||
|
@ -9,7 +9,7 @@
|
||||
|
||||
#ifndef STASSID
|
||||
#define STASSID "your-ssid"
|
||||
#define STAPSK "your-password"
|
||||
#define STAPSK "your-password"
|
||||
#endif
|
||||
|
||||
const char *ssid = STASSID;
|
||||
@ -22,13 +22,11 @@ void fetch(BearSSL::WiFiClientSecure *client) {
|
||||
oneShot timeout(5000);
|
||||
do {
|
||||
char tmp[32];
|
||||
int rlen = client->read((uint8_t*)tmp, sizeof(tmp) - 1);
|
||||
int rlen = client->read((uint8_t *)tmp, sizeof(tmp) - 1);
|
||||
yield();
|
||||
if (rlen < 0) {
|
||||
break;
|
||||
}
|
||||
if (rlen < 0) { break; }
|
||||
if (rlen == 0) {
|
||||
delay(10); // Give background processes some time
|
||||
delay(10); // Give background processes some time
|
||||
continue;
|
||||
}
|
||||
tmp[rlen] = '\0';
|
||||
@ -82,9 +80,7 @@ int fetchMaxFragmentLength() {
|
||||
bool mfln = client.probeMaxFragmentLength("tls.mbed.org", 443, 512);
|
||||
Serial.printf("\nConnecting to https://tls.mbed.org\n");
|
||||
Serial.printf("MFLN supported: %s\n", mfln ? "yes" : "no");
|
||||
if (mfln) {
|
||||
client.setBufferSizes(512, 512);
|
||||
}
|
||||
if (mfln) { client.setBufferSizes(512, 512); }
|
||||
client.connect("tls.mbed.org", 443);
|
||||
if (client.connected()) {
|
||||
Serial.printf("MFLN status: %s\n", client.getMFLNStatus() ? "true" : "false");
|
||||
|
@ -39,7 +39,7 @@
|
||||
|
||||
#ifndef STASSID
|
||||
#define STASSID "your-ssid"
|
||||
#define STAPSK "your-password"
|
||||
#define STAPSK "your-password"
|
||||
#endif
|
||||
|
||||
const char *ssid = STASSID;
|
||||
@ -138,11 +138,11 @@ GBEnkz4KpKv7TkHoW+j7F5EMcLcSrUIpyw==
|
||||
|
||||
#endif
|
||||
|
||||
#define CACHE_SIZE 5 // Number of sessions to cache.
|
||||
#define USE_CACHE // Enable SSL session caching.
|
||||
// Caching SSL sessions shortens the length of the SSL handshake.
|
||||
// You can see the performance improvement by looking at the
|
||||
// Network tab of the developer tools of your browser.
|
||||
#define CACHE_SIZE 5 // Number of sessions to cache.
|
||||
#define USE_CACHE // Enable SSL session caching.
|
||||
// Caching SSL sessions shortens the length of the SSL handshake.
|
||||
// You can see the performance improvement by looking at the
|
||||
// Network tab of the developer tools of your browser.
|
||||
//#define DYNAMIC_CACHE // Whether to dynamically allocate the cache.
|
||||
|
||||
#if defined(USE_CACHE) && defined(DYNAMIC_CACHE)
|
||||
@ -181,7 +181,7 @@ void setup() {
|
||||
#ifndef USE_EC
|
||||
server.setRSACert(serverCertList, serverPrivKey);
|
||||
#else
|
||||
server.setECCert(serverCertList, BR_KEYTYPE_KEYX|BR_KEYTYPE_SIGN, serverPrivKey);
|
||||
server.setECCert(serverCertList, BR_KEYTYPE_KEYX | BR_KEYTYPE_SIGN, serverPrivKey);
|
||||
#endif
|
||||
|
||||
// Set the server's cache
|
||||
@ -193,31 +193,28 @@ void setup() {
|
||||
server.begin();
|
||||
}
|
||||
|
||||
static const char *HTTP_RES =
|
||||
"HTTP/1.0 200 OK\r\n"
|
||||
"Connection: close\r\n"
|
||||
"Content-Length: 62\r\n"
|
||||
"Content-Type: text/html; charset=iso-8859-1\r\n"
|
||||
"\r\n"
|
||||
"<html>\r\n"
|
||||
"<body>\r\n"
|
||||
"<p>Hello from ESP8266!</p>\r\n"
|
||||
"</body>\r\n"
|
||||
"</html>\r\n";
|
||||
static const char *HTTP_RES = "HTTP/1.0 200 OK\r\n"
|
||||
"Connection: close\r\n"
|
||||
"Content-Length: 62\r\n"
|
||||
"Content-Type: text/html; charset=iso-8859-1\r\n"
|
||||
"\r\n"
|
||||
"<html>\r\n"
|
||||
"<body>\r\n"
|
||||
"<p>Hello from ESP8266!</p>\r\n"
|
||||
"</body>\r\n"
|
||||
"</html>\r\n";
|
||||
|
||||
void loop() {
|
||||
static int cnt;
|
||||
BearSSL::WiFiClientSecure incoming = server.accept();
|
||||
if (!incoming) {
|
||||
return;
|
||||
}
|
||||
Serial.printf("Incoming connection...%d\n",cnt++);
|
||||
|
||||
if (!incoming) { return; }
|
||||
Serial.printf("Incoming connection...%d\n", cnt++);
|
||||
|
||||
// Ugly way to wait for \r\n (i.e. end of HTTP request which we don't actually parse here)
|
||||
uint32_t timeout=millis() + 1000;
|
||||
uint32_t timeout = millis() + 1000;
|
||||
int lcwn = 0;
|
||||
for (;;) {
|
||||
unsigned char x=0;
|
||||
unsigned char x = 0;
|
||||
if ((millis() > timeout) || (incoming.available() && incoming.read(&x, 1) < 0)) {
|
||||
incoming.stop();
|
||||
Serial.printf("Connection error, closed\n");
|
||||
@ -228,14 +225,12 @@ void loop() {
|
||||
} else if (x == 0x0D) {
|
||||
continue;
|
||||
} else if (x == 0x0A) {
|
||||
if (lcwn) {
|
||||
break;
|
||||
}
|
||||
if (lcwn) { break; }
|
||||
lcwn = 1;
|
||||
} else
|
||||
lcwn = 0;
|
||||
}
|
||||
incoming.write((uint8_t*)HTTP_RES, strlen(HTTP_RES));
|
||||
incoming.write((uint8_t *)HTTP_RES, strlen(HTTP_RES));
|
||||
incoming.flush();
|
||||
incoming.stop();
|
||||
Serial.printf("Connection closed.\n");
|
||||
|
@ -67,7 +67,7 @@
|
||||
|
||||
#ifndef STASSID
|
||||
#define STASSID "your-ssid"
|
||||
#define STAPSK "your-password"
|
||||
#define STAPSK "your-password"
|
||||
#endif
|
||||
|
||||
const char *ssid = STASSID;
|
||||
@ -160,8 +160,7 @@ seoK24dHmt6tWmn/sbxX7Aa6TL/4mVlFoOgcaTJyVaY/BrY=
|
||||
// head of the app.
|
||||
|
||||
// Set time via NTP, as required for x.509 validation
|
||||
void setClock()
|
||||
{
|
||||
void setClock() {
|
||||
configTime(3 * 3600, 0, "pool.ntp.org", "time.nist.gov");
|
||||
|
||||
Serial.print("Waiting for NTP time sync: ");
|
||||
@ -199,7 +198,7 @@ void setup() {
|
||||
Serial.println("IP address: ");
|
||||
Serial.println(WiFi.localIP());
|
||||
|
||||
setClock(); // Required for X.509 validation
|
||||
setClock(); // Required for X.509 validation
|
||||
|
||||
// Attach the server private cert/key combo
|
||||
BearSSL::X509List *serverCertList = new BearSSL::X509List(server_cert);
|
||||
@ -214,30 +213,27 @@ void setup() {
|
||||
server.begin();
|
||||
}
|
||||
|
||||
static const char *HTTP_RES =
|
||||
"HTTP/1.0 200 OK\r\n"
|
||||
"Connection: close\r\n"
|
||||
"Content-Length: 59\r\n"
|
||||
"Content-Type: text/html; charset=iso-8859-1\r\n"
|
||||
"\r\n"
|
||||
"<html>\r\n"
|
||||
"<body>\r\n"
|
||||
"<p>Hello my friend!</p>\r\n"
|
||||
"</body>\r\n"
|
||||
"</html>\r\n";
|
||||
static const char *HTTP_RES = "HTTP/1.0 200 OK\r\n"
|
||||
"Connection: close\r\n"
|
||||
"Content-Length: 59\r\n"
|
||||
"Content-Type: text/html; charset=iso-8859-1\r\n"
|
||||
"\r\n"
|
||||
"<html>\r\n"
|
||||
"<body>\r\n"
|
||||
"<p>Hello my friend!</p>\r\n"
|
||||
"</body>\r\n"
|
||||
"</html>\r\n";
|
||||
|
||||
void loop() {
|
||||
BearSSL::WiFiClientSecure incoming = server.accept();
|
||||
if (!incoming) {
|
||||
return;
|
||||
}
|
||||
if (!incoming) { return; }
|
||||
Serial.println("Incoming connection...\n");
|
||||
|
||||
|
||||
// Ugly way to wait for \r\n (i.e. end of HTTP request which we don't actually parse here)
|
||||
uint32_t timeout=millis() + 1000;
|
||||
uint32_t timeout = millis() + 1000;
|
||||
int lcwn = 0;
|
||||
for (;;) {
|
||||
unsigned char x=0;
|
||||
unsigned char x = 0;
|
||||
if ((millis() > timeout) || (incoming.available() && incoming.read(&x, 1) < 0)) {
|
||||
incoming.stop();
|
||||
Serial.printf("Connection error, closed\n");
|
||||
@ -248,14 +244,12 @@ void loop() {
|
||||
} else if (x == 0x0D) {
|
||||
continue;
|
||||
} else if (x == 0x0A) {
|
||||
if (lcwn) {
|
||||
break;
|
||||
}
|
||||
if (lcwn) { break; }
|
||||
lcwn = 1;
|
||||
} else
|
||||
lcwn = 0;
|
||||
}
|
||||
incoming.write((uint8_t*)HTTP_RES, strlen(HTTP_RES));
|
||||
incoming.write((uint8_t *)HTTP_RES, strlen(HTTP_RES));
|
||||
incoming.flush();
|
||||
incoming.stop();
|
||||
Serial.printf("Connection closed.\n");
|
||||
|
@ -9,13 +9,13 @@
|
||||
|
||||
#ifndef STASSID
|
||||
#define STASSID "your-ssid"
|
||||
#define STAPSK "your-password"
|
||||
#define STAPSK "your-password"
|
||||
#endif
|
||||
|
||||
const char *ssid = STASSID;
|
||||
const char *pass = STAPSK;
|
||||
|
||||
const char * path = "/";
|
||||
const char *path = "/";
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
@ -53,9 +53,7 @@ void setup() {
|
||||
|
||||
// Try and connect using a WiFiClientBearSSL to specified host:port and dump HTTP response
|
||||
void fetchURL(BearSSL::WiFiClientSecure *client, const char *host, const uint16_t port, const char *path) {
|
||||
if (!path) {
|
||||
path = "/";
|
||||
}
|
||||
if (!path) { path = "/"; }
|
||||
|
||||
Serial.printf("Trying: %s:443...", host);
|
||||
client->connect(host, port);
|
||||
@ -75,11 +73,9 @@ void fetchURL(BearSSL::WiFiClientSecure *client, const char *host, const uint16_
|
||||
do {
|
||||
char tmp[32];
|
||||
memset(tmp, 0, 32);
|
||||
int rlen = client->read((uint8_t*)tmp, sizeof(tmp) - 1);
|
||||
int rlen = client->read((uint8_t *)tmp, sizeof(tmp) - 1);
|
||||
yield();
|
||||
if (rlen < 0) {
|
||||
break;
|
||||
}
|
||||
if (rlen < 0) { break; }
|
||||
// Only print out first line up to \r, then abort connection
|
||||
char *nl = strchr(tmp, '\r');
|
||||
if (nl) {
|
||||
@ -130,6 +126,5 @@ void loop() {
|
||||
finish = millis();
|
||||
Serial.printf("Total time: %dms\n", finish - start);
|
||||
|
||||
delay(10000); // Avoid DDOSing github
|
||||
delay(10000); // Avoid DDOSing github
|
||||
}
|
||||
|
||||
|
@ -12,13 +12,13 @@
|
||||
|
||||
#ifndef STASSID
|
||||
#define STASSID "your-ssid"
|
||||
#define STAPSK "your-password"
|
||||
#define STAPSK "your-password"
|
||||
#endif
|
||||
|
||||
const char *ssid = STASSID;
|
||||
const char *pass = STAPSK;
|
||||
|
||||
const char * path = "/";
|
||||
const char *path = "/";
|
||||
|
||||
// Set time via NTP, as required for x.509 validation
|
||||
void setClock() {
|
||||
@ -40,9 +40,7 @@ void setClock() {
|
||||
|
||||
// Try and connect using a WiFiClientBearSSL to specified host:port and dump HTTP response
|
||||
void fetchURL(BearSSL::WiFiClientSecure *client, const char *host, const uint16_t port, const char *path) {
|
||||
if (!path) {
|
||||
path = "/";
|
||||
}
|
||||
if (!path) { path = "/"; }
|
||||
|
||||
ESP.resetFreeContStack();
|
||||
uint32_t freeStackStart = ESP.getFreeContStack();
|
||||
@ -64,11 +62,9 @@ void fetchURL(BearSSL::WiFiClientSecure *client, const char *host, const uint16_
|
||||
do {
|
||||
char tmp[32];
|
||||
memset(tmp, 0, 32);
|
||||
int rlen = client->read((uint8_t*)tmp, sizeof(tmp) - 1);
|
||||
int rlen = client->read((uint8_t *)tmp, sizeof(tmp) - 1);
|
||||
yield();
|
||||
if (rlen < 0) {
|
||||
break;
|
||||
}
|
||||
if (rlen < 0) { break; }
|
||||
// Only print out first line up to \r, then abort connection
|
||||
char *nl = strchr(tmp, '\r');
|
||||
if (nl) {
|
||||
|
@ -17,7 +17,7 @@
|
||||
|
||||
#ifndef STASSID
|
||||
#define STASSID "your-ssid"
|
||||
#define STAPSK "your-password"
|
||||
#define STAPSK "your-password"
|
||||
#endif
|
||||
|
||||
const char* ssid = STASSID;
|
||||
@ -74,10 +74,7 @@ void setup() {
|
||||
Serial.print("Requesting URL: ");
|
||||
Serial.println(url);
|
||||
|
||||
client.print(String("GET ") + url + " HTTP/1.1\r\n" +
|
||||
"Host: " + github_host + "\r\n" +
|
||||
"User-Agent: BuildFailureDetectorESP8266\r\n" +
|
||||
"Connection: close\r\n\r\n");
|
||||
client.print(String("GET ") + url + " HTTP/1.1\r\n" + "Host: " + github_host + "\r\n" + "User-Agent: BuildFailureDetectorESP8266\r\n" + "Connection: close\r\n\r\n");
|
||||
|
||||
Serial.println("Request sent");
|
||||
while (client.connected()) {
|
||||
@ -100,5 +97,4 @@ void setup() {
|
||||
Serial.println("Closing connection");
|
||||
}
|
||||
|
||||
void loop() {
|
||||
}
|
||||
void loop() {}
|
||||
|
@ -23,12 +23,12 @@
|
||||
|
||||
#ifndef STASSID
|
||||
#define STASSID "your-ssid"
|
||||
#define STAPSK "your-password"
|
||||
#define STAPSK "your-password"
|
||||
#endif
|
||||
|
||||
#define FQDN F("www.google.com") // with both IPv4 & IPv6 addresses
|
||||
#define FQDN2 F("www.yahoo.com") // with both IPv4 & IPv6 addresses
|
||||
#define FQDN6 F("ipv6.google.com") // does not resolve in IPv4
|
||||
#define FQDN F("www.google.com") // with both IPv4 & IPv6 addresses
|
||||
#define FQDN2 F("www.yahoo.com") // with both IPv4 & IPv6 addresses
|
||||
#define FQDN6 F("ipv6.google.com") // does not resolve in IPv4
|
||||
#define STATUSDELAY_MS 10000
|
||||
#define TCP_PORT 23
|
||||
#define UDP_PORT 23
|
||||
@ -71,29 +71,17 @@ void status(Print& out) {
|
||||
|
||||
for (int i = 0; i < DNS_MAX_SERVERS; i++) {
|
||||
IPAddress dns = WiFi.dnsIP(i);
|
||||
if (dns.isSet()) {
|
||||
out.printf("dns%d: %s\n", i, dns.toString().c_str());
|
||||
}
|
||||
if (dns.isSet()) { out.printf("dns%d: %s\n", i, dns.toString().c_str()); }
|
||||
}
|
||||
|
||||
out.println(F("Try me at these addresses:"));
|
||||
out.println(F("(with 'telnet <addr> or 'nc -u <addr> 23')"));
|
||||
for (auto a : addrList) {
|
||||
out.printf("IF='%s' IPv6=%d local=%d hostname='%s' addr= %s",
|
||||
a.ifname().c_str(),
|
||||
a.isV6(),
|
||||
a.isLocal(),
|
||||
a.ifhostname(),
|
||||
a.toString().c_str());
|
||||
out.printf("IF='%s' IPv6=%d local=%d hostname='%s' addr= %s", a.ifname().c_str(), a.isV6(), a.isLocal(), a.ifhostname(), a.toString().c_str());
|
||||
|
||||
if (a.isLegacy()) {
|
||||
out.printf(" / mask:%s / gw:%s",
|
||||
a.netmask().toString().c_str(),
|
||||
a.gw().toString().c_str());
|
||||
}
|
||||
if (a.isLegacy()) { out.printf(" / mask:%s / gw:%s", a.netmask().toString().c_str(), a.gw().toString().c_str()); }
|
||||
|
||||
out.println();
|
||||
|
||||
}
|
||||
|
||||
// lwIP's dns client will ask for IPv4 first (by default)
|
||||
@ -101,8 +89,8 @@ void status(Print& out) {
|
||||
fqdn(out, FQDN);
|
||||
fqdn(out, FQDN6);
|
||||
#if LWIP_IPV4 && LWIP_IPV6
|
||||
fqdn_rt(out, FQDN, DNSResolveType::DNS_AddrType_IPv4_IPv6); // IPv4 before IPv6
|
||||
fqdn_rt(out, FQDN2, DNSResolveType::DNS_AddrType_IPv6_IPv4); // IPv6 before IPv4
|
||||
fqdn_rt(out, FQDN, DNSResolveType::DNS_AddrType_IPv4_IPv6); // IPv4 before IPv6
|
||||
fqdn_rt(out, FQDN2, DNSResolveType::DNS_AddrType_IPv6_IPv4); // IPv6 before IPv4
|
||||
#endif
|
||||
out.println(F("------------------------------"));
|
||||
}
|
||||
@ -125,7 +113,7 @@ void setup() {
|
||||
|
||||
status(Serial);
|
||||
|
||||
#if 0 // 0: legacy connecting loop - 1: wait for IPv6
|
||||
#if 0 // 0: legacy connecting loop - 1: wait for IPv6
|
||||
|
||||
// legacy loop (still valid with IPv4 only)
|
||||
|
||||
@ -146,11 +134,9 @@ void setup() {
|
||||
for (bool configured = false; !configured;) {
|
||||
for (auto addr : addrList)
|
||||
if ((configured = !addr.isLocal()
|
||||
// && addr.isV6() // uncomment when IPv6 is mandatory
|
||||
// && addr.ifnumber() == STATION_IF
|
||||
)) {
|
||||
break;
|
||||
}
|
||||
// && addr.isV6() // uncomment when IPv6 is mandatory
|
||||
// && addr.ifnumber() == STATION_IF
|
||||
)) { break; }
|
||||
Serial.print('.');
|
||||
delay(500);
|
||||
}
|
||||
@ -188,10 +174,8 @@ void loop() {
|
||||
udp.remoteIP().printTo(Serial);
|
||||
Serial.print(F(" :"));
|
||||
Serial.println(udp.remotePort());
|
||||
int c;
|
||||
while ((c = udp.read()) >= 0) {
|
||||
Serial.write(c);
|
||||
}
|
||||
int c;
|
||||
while ((c = udp.read()) >= 0) { Serial.write(c); }
|
||||
|
||||
// send a reply, to the IP address and port that sent us the packet we received
|
||||
udp.beginPacket(udp.remoteIP(), udp.remotePort());
|
||||
@ -200,8 +184,5 @@ void loop() {
|
||||
}
|
||||
|
||||
|
||||
if (showStatusOnSerialNow) {
|
||||
status(Serial);
|
||||
}
|
||||
|
||||
if (showStatusOnSerialNow) { status(Serial); }
|
||||
}
|
||||
|
@ -23,24 +23,24 @@
|
||||
|
||||
#ifndef STASSID
|
||||
#define STASSID "your-ssid"
|
||||
#define STAPSK "your-password"
|
||||
#define STAPSK "your-password"
|
||||
#endif
|
||||
|
||||
const char * ssid = STASSID; // your network SSID (name)
|
||||
const char * pass = STAPSK; // your network password
|
||||
const char* ssid = STASSID; // your network SSID (name)
|
||||
const char* pass = STAPSK; // your network password
|
||||
|
||||
|
||||
unsigned int localPort = 2390; // local port to listen for UDP packets
|
||||
unsigned int localPort = 2390; // local port to listen for UDP packets
|
||||
|
||||
/* Don't hardwire the IP address or we won't get the benefits of the pool.
|
||||
Lookup the IP address for the host name instead */
|
||||
//IPAddress timeServer(129, 6, 15, 28); // time.nist.gov NTP server
|
||||
IPAddress timeServerIP; // time.nist.gov NTP server address
|
||||
// IPAddress timeServer(129, 6, 15, 28); // time.nist.gov NTP server
|
||||
IPAddress timeServerIP; // time.nist.gov NTP server address
|
||||
const char* ntpServerName = "time.nist.gov";
|
||||
|
||||
const int NTP_PACKET_SIZE = 48; // NTP time stamp is in the first 48 bytes of the message
|
||||
const int NTP_PACKET_SIZE = 48; // NTP time stamp is in the first 48 bytes of the message
|
||||
|
||||
byte packetBuffer[ NTP_PACKET_SIZE]; //buffer to hold incoming and outgoing packets
|
||||
byte packetBuffer[NTP_PACKET_SIZE]; // buffer to hold incoming and outgoing packets
|
||||
|
||||
// A UDP instance to let us send and receive packets over UDP
|
||||
WiFiUDP udp;
|
||||
@ -73,10 +73,10 @@ void setup() {
|
||||
}
|
||||
|
||||
void loop() {
|
||||
//get a random server from the pool
|
||||
// get a random server from the pool
|
||||
WiFi.hostByName(ntpServerName, timeServerIP);
|
||||
|
||||
sendNTPpacket(timeServerIP); // send an NTP packet to a time server
|
||||
sendNTPpacket(timeServerIP); // send an NTP packet to a time server
|
||||
// wait to see if a reply is available
|
||||
delay(1000);
|
||||
|
||||
@ -87,10 +87,10 @@ void loop() {
|
||||
Serial.print("packet received, length=");
|
||||
Serial.println(cb);
|
||||
// We've received a packet, read the data from it
|
||||
udp.read(packetBuffer, NTP_PACKET_SIZE); // read the packet into the buffer
|
||||
udp.read(packetBuffer, NTP_PACKET_SIZE); // read the packet into the buffer
|
||||
|
||||
//the timestamp starts at byte 40 of the received packet and is four bytes,
|
||||
// or two words, long. First, esxtract the two words:
|
||||
// the timestamp starts at byte 40 of the received packet and is four bytes,
|
||||
// or two words, long. First, esxtract the two words:
|
||||
|
||||
unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
|
||||
unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]);
|
||||
@ -112,19 +112,19 @@ void loop() {
|
||||
|
||||
// print the hour, minute and second:
|
||||
Serial.print("The UTC time is "); // UTC is the time at Greenwich Meridian (GMT)
|
||||
Serial.print((epoch % 86400L) / 3600); // print the hour (86400 equals secs per day)
|
||||
Serial.print((epoch % 86400L) / 3600); // print the hour (86400 equals secs per day)
|
||||
Serial.print(':');
|
||||
if (((epoch % 3600) / 60) < 10) {
|
||||
// In the first 10 minutes of each hour, we'll want a leading '0'
|
||||
Serial.print('0');
|
||||
}
|
||||
Serial.print((epoch % 3600) / 60); // print the minute (3600 equals secs per minute)
|
||||
Serial.print((epoch % 3600) / 60); // print the minute (3600 equals secs per minute)
|
||||
Serial.print(':');
|
||||
if ((epoch % 60) < 10) {
|
||||
// In the first 10 seconds of each minute, we'll want a leading '0'
|
||||
Serial.print('0');
|
||||
}
|
||||
Serial.println(epoch % 60); // print the second
|
||||
Serial.println(epoch % 60); // print the second
|
||||
}
|
||||
// wait ten seconds before asking for the time again
|
||||
delay(10000);
|
||||
@ -137,19 +137,19 @@ void sendNTPpacket(IPAddress& address) {
|
||||
memset(packetBuffer, 0, NTP_PACKET_SIZE);
|
||||
// Initialize values needed to form NTP request
|
||||
// (see URL above for details on the packets)
|
||||
packetBuffer[0] = 0b11100011; // LI, Version, Mode
|
||||
packetBuffer[1] = 0; // Stratum, or type of clock
|
||||
packetBuffer[2] = 6; // Polling Interval
|
||||
packetBuffer[3] = 0xEC; // Peer Clock Precision
|
||||
packetBuffer[0] = 0b11100011; // LI, Version, Mode
|
||||
packetBuffer[1] = 0; // Stratum, or type of clock
|
||||
packetBuffer[2] = 6; // Polling Interval
|
||||
packetBuffer[3] = 0xEC; // Peer Clock Precision
|
||||
// 8 bytes of zero for Root Delay & Root Dispersion
|
||||
packetBuffer[12] = 49;
|
||||
packetBuffer[13] = 0x4E;
|
||||
packetBuffer[14] = 49;
|
||||
packetBuffer[15] = 52;
|
||||
packetBuffer[12] = 49;
|
||||
packetBuffer[13] = 0x4E;
|
||||
packetBuffer[14] = 49;
|
||||
packetBuffer[15] = 52;
|
||||
|
||||
// all NTP fields have been given values, now
|
||||
// you can send a packet requesting a timestamp:
|
||||
udp.beginPacket(address, 123); //NTP requests are to port 123
|
||||
udp.beginPacket(address, 123); // NTP requests are to port 123
|
||||
udp.write(packetBuffer, NTP_PACKET_SIZE);
|
||||
udp.endPacket();
|
||||
}
|
||||
|
@ -25,10 +25,10 @@
|
||||
|
||||
#ifndef STASSID
|
||||
#define STASSID "your-ssid"
|
||||
#define STAPSK "your-password"
|
||||
#define STAPSK "your-password"
|
||||
#endif
|
||||
|
||||
const char* ssid = STASSID;
|
||||
const char* ssid = STASSID;
|
||||
const char* password = STAPSK;
|
||||
|
||||
ArduinoWiFiServer server(2323);
|
||||
@ -60,13 +60,13 @@ void setup() {
|
||||
|
||||
void loop() {
|
||||
|
||||
WiFiClient client = server.available(); // returns first client which has data to read or a 'false' client
|
||||
if (client) { // client is true only if it is connected and has data to read
|
||||
String s = client.readStringUntil('\n'); // read the message incoming from one of the clients
|
||||
s.trim(); // trim eventual \r
|
||||
Serial.println(s); // print the message to Serial Monitor
|
||||
client.print("echo: "); // this is only for the sending client
|
||||
server.println(s); // send the message to all connected clients
|
||||
server.flush(); // flush the buffers
|
||||
WiFiClient client = server.available(); // returns first client which has data to read or a 'false' client
|
||||
if (client) { // client is true only if it is connected and has data to read
|
||||
String s = client.readStringUntil('\n'); // read the message incoming from one of the clients
|
||||
s.trim(); // trim eventual \r
|
||||
Serial.println(s); // print the message to Serial Monitor
|
||||
client.print("echo: "); // this is only for the sending client
|
||||
server.println(s); // send the message to all connected clients
|
||||
server.flush(); // flush the buffers
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,7 @@
|
||||
|
||||
#ifndef STASSID
|
||||
#define STASSID "mynetwork"
|
||||
#define STAPSK "mynetworkpassword"
|
||||
#define STAPSK "mynetworkpassword"
|
||||
#endif
|
||||
|
||||
#include <ESP8266WiFi.h>
|
||||
@ -30,7 +30,7 @@ void dump(int netif_idx, const char* data, size_t len, int out, int success) {
|
||||
// optional filter example: if (netDump_is_ARP(data))
|
||||
{
|
||||
netDump(Serial, data, len);
|
||||
//netDumpHex(Serial, data, len);
|
||||
// netDumpHex(Serial, data, len);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -51,19 +51,14 @@ void setup() {
|
||||
Serial.print('.');
|
||||
delay(500);
|
||||
}
|
||||
Serial.printf("\nSTA: %s (dns: %s / %s)\n",
|
||||
WiFi.localIP().toString().c_str(),
|
||||
WiFi.dnsIP(0).toString().c_str(),
|
||||
WiFi.dnsIP(1).toString().c_str());
|
||||
Serial.printf("\nSTA: %s (dns: %s / %s)\n", WiFi.localIP().toString().c_str(), WiFi.dnsIP(0).toString().c_str(), WiFi.dnsIP(1).toString().c_str());
|
||||
|
||||
// give DNS servers to AP side
|
||||
dhcpSoftAP.dhcps_set_dns(0, WiFi.dnsIP(0));
|
||||
dhcpSoftAP.dhcps_set_dns(1, WiFi.dnsIP(1));
|
||||
|
||||
WiFi.softAPConfig( // enable AP, with android-compatible google domain
|
||||
IPAddress(172, 217, 28, 254),
|
||||
IPAddress(172, 217, 28, 254),
|
||||
IPAddress(255, 255, 255, 0));
|
||||
IPAddress(172, 217, 28, 254), IPAddress(172, 217, 28, 254), IPAddress(255, 255, 255, 0));
|
||||
WiFi.softAP(STASSID "extender", STAPSK);
|
||||
Serial.printf("AP: %s\n", WiFi.softAPIP().toString().c_str());
|
||||
|
||||
@ -73,14 +68,10 @@ void setup() {
|
||||
if (ret == ERR_OK) {
|
||||
ret = ip_napt_enable_no(SOFTAP_IF, 1);
|
||||
Serial.printf("ip_napt_enable_no(SOFTAP_IF): ret=%d (OK=%d)\n", (int)ret, (int)ERR_OK);
|
||||
if (ret == ERR_OK) {
|
||||
Serial.printf("WiFi Network '%s' with same password is now NATed behind '%s'\n", STASSID "extender", STASSID);
|
||||
}
|
||||
if (ret == ERR_OK) { Serial.printf("WiFi Network '%s' with same password is now NATed behind '%s'\n", STASSID "extender", STASSID); }
|
||||
}
|
||||
Serial.printf("Heap after napt init: %d\n", ESP.getFreeHeap());
|
||||
if (ret != ERR_OK) {
|
||||
Serial.printf("NAPT initialization failed\n");
|
||||
}
|
||||
if (ret != ERR_OK) { Serial.printf("NAPT initialization failed\n"); }
|
||||
}
|
||||
|
||||
#else
|
||||
@ -92,6 +83,4 @@ void setup() {
|
||||
|
||||
#endif
|
||||
|
||||
void loop() {
|
||||
}
|
||||
|
||||
void loop() {}
|
||||
|
@ -20,14 +20,14 @@
|
||||
|
||||
#ifndef STASSID
|
||||
#define STASSID "your-ssid"
|
||||
#define STAPSK "your-password"
|
||||
#define STAPSK "your-password"
|
||||
#endif
|
||||
|
||||
unsigned int localPort = 8888; // local port to listen on
|
||||
unsigned int localPort = 8888; // local port to listen on
|
||||
|
||||
// buffers for receiving and sending data
|
||||
char packetBuffer[UDP_TX_PACKET_MAX_SIZE + 1]; //buffer to hold incoming packet,
|
||||
char ReplyBuffer[] = "acknowledged\r\n"; // a string to send back
|
||||
char packetBuffer[UDP_TX_PACKET_MAX_SIZE + 1]; // buffer to hold incoming packet,
|
||||
char ReplyBuffer[] = "acknowledged\r\n"; // a string to send back
|
||||
|
||||
WiFiUDP Udp;
|
||||
|
||||
@ -49,11 +49,7 @@ void loop() {
|
||||
// if there's data available, read a packet
|
||||
int packetSize = Udp.parsePacket();
|
||||
if (packetSize) {
|
||||
Serial.printf("Received packet of size %d from %s:%d\n (to %s:%d, free heap = %d B)\n",
|
||||
packetSize,
|
||||
Udp.remoteIP().toString().c_str(), Udp.remotePort(),
|
||||
Udp.destinationIP().toString().c_str(), Udp.localPort(),
|
||||
ESP.getFreeHeap());
|
||||
Serial.printf("Received packet of size %d from %s:%d\n (to %s:%d, free heap = %d B)\n", packetSize, Udp.remoteIP().toString().c_str(), Udp.remotePort(), Udp.destinationIP().toString().c_str(), Udp.localPort(), ESP.getFreeHeap());
|
||||
|
||||
// read the packet into packetBufffer
|
||||
int n = Udp.read(packetBuffer, UDP_TX_PACKET_MAX_SIZE);
|
||||
@ -66,11 +62,10 @@ void loop() {
|
||||
Udp.write(ReplyBuffer);
|
||||
Udp.endPacket();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
test (shell/netcat):
|
||||
--------------------
|
||||
nc -u 192.168.esp.address 8888
|
||||
nc -u 192.168.esp.address 8888
|
||||
*/
|
||||
|
@ -36,7 +36,7 @@
|
||||
|
||||
#ifndef APSSID
|
||||
#define APSSID "ESPap"
|
||||
#define APPSK "thereisnospoon"
|
||||
#define APPSK "thereisnospoon"
|
||||
#endif
|
||||
|
||||
/* Set these to your desired credentials. */
|
||||
|
@ -7,10 +7,10 @@
|
||||
|
||||
#ifndef STASSID
|
||||
#define STASSID "your-ssid"
|
||||
#define STAPSK "your-password"
|
||||
#define STAPSK "your-password"
|
||||
#endif
|
||||
|
||||
const char* ssid = STASSID;
|
||||
const char* ssid = STASSID;
|
||||
const char* password = STAPSK;
|
||||
|
||||
const char* host = "djxmmx.net";
|
||||
@ -61,9 +61,7 @@ void loop() {
|
||||
|
||||
// This will send a string to the server
|
||||
Serial.println("sending data to server");
|
||||
if (client.connected()) {
|
||||
client.println("hello from ESP8266");
|
||||
}
|
||||
if (client.connected()) { client.println("hello from ESP8266"); }
|
||||
|
||||
// wait for data to be available
|
||||
unsigned long timeout = millis();
|
||||
@ -90,7 +88,7 @@ void loop() {
|
||||
client.stop();
|
||||
|
||||
if (wait) {
|
||||
delay(300000); // execute once every 5 minutes, don't flood remote service
|
||||
delay(300000); // execute once every 5 minutes, don't flood remote service
|
||||
}
|
||||
wait = true;
|
||||
}
|
||||
|
@ -9,10 +9,10 @@
|
||||
|
||||
#ifndef STASSID
|
||||
#define STASSID "your-ssid"
|
||||
#define STAPSK "your-password"
|
||||
#define STAPSK "your-password"
|
||||
#endif
|
||||
|
||||
const char* ssid = STASSID;
|
||||
const char* ssid = STASSID;
|
||||
const char* password = STAPSK;
|
||||
|
||||
const char* host = "192.168.1.1";
|
||||
@ -64,7 +64,7 @@ void loop() {
|
||||
// This will send the request to the server
|
||||
client.println("hello from ESP8266");
|
||||
|
||||
//read back one line from server
|
||||
// read back one line from server
|
||||
Serial.println("receiving from remote server");
|
||||
String line = client.readStringUntil('\r');
|
||||
Serial.println(line);
|
||||
@ -75,4 +75,3 @@ void loop() {
|
||||
Serial.println("wait 5 sec...");
|
||||
delay(5000);
|
||||
}
|
||||
|
||||
|
@ -7,11 +7,11 @@
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <ESP8266mDNS.h>
|
||||
#include <PolledTimeout.h>
|
||||
#include <algorithm> // std::min
|
||||
#include <algorithm> // std::min
|
||||
|
||||
#ifndef STASSID
|
||||
#define STASSID "your-ssid"
|
||||
#define STAPSK "your-password"
|
||||
#define STAPSK "your-password"
|
||||
#endif
|
||||
|
||||
constexpr int port = 23;
|
||||
@ -19,12 +19,12 @@ constexpr int port = 23;
|
||||
WiFiServer server(port);
|
||||
WiFiClient client;
|
||||
|
||||
constexpr size_t sizes [] = { 0, 512, 384, 256, 128, 64, 16, 8, 4 };
|
||||
constexpr size_t sizes[] = { 0, 512, 384, 256, 128, 64, 16, 8, 4 };
|
||||
constexpr uint32_t breathMs = 200;
|
||||
esp8266::polledTimeout::oneShotFastMs enoughMs(breathMs);
|
||||
esp8266::polledTimeout::periodicFastMs test(2000);
|
||||
int t = 1; // test (1, 2 or 3, see below)
|
||||
int s = 0; // sizes[] index
|
||||
int t = 1; // test (1, 2 or 3, see below)
|
||||
int s = 0; // sizes[] index
|
||||
|
||||
void setup() {
|
||||
|
||||
@ -63,19 +63,13 @@ void loop() {
|
||||
static uint32_t cnt = 0;
|
||||
if (test && cnt) {
|
||||
Serial.printf("measured-block-size=%u min-free-stack=%u", tot / cnt, ESP.getFreeContStack());
|
||||
if (t == 2 && sizes[s]) {
|
||||
Serial.printf(" (blocks: at most %d bytes)", sizes[s]);
|
||||
}
|
||||
if (t == 3 && sizes[s]) {
|
||||
Serial.printf(" (blocks: exactly %d bytes)", sizes[s]);
|
||||
}
|
||||
if (t == 3 && !sizes[s]) {
|
||||
Serial.printf(" (blocks: any size)");
|
||||
}
|
||||
if (t == 2 && sizes[s]) { Serial.printf(" (blocks: at most %d bytes)", sizes[s]); }
|
||||
if (t == 3 && sizes[s]) { Serial.printf(" (blocks: exactly %d bytes)", sizes[s]); }
|
||||
if (t == 3 && !sizes[s]) { Serial.printf(" (blocks: any size)"); }
|
||||
Serial.printf("\n");
|
||||
}
|
||||
|
||||
//check if there are any new clients
|
||||
// check if there are any new clients
|
||||
if (server.hasClient()) {
|
||||
client = server.accept();
|
||||
Serial.println("New client");
|
||||
@ -84,10 +78,25 @@ void loop() {
|
||||
if (Serial.available()) {
|
||||
s = (s + 1) % (sizeof(sizes) / sizeof(sizes[0]));
|
||||
switch (Serial.read()) {
|
||||
case '1': if (t != 1) s = 0; t = 1; Serial.println("byte-by-byte (watch then press 2, 3 or 4)"); break;
|
||||
case '2': if (t != 2) s = 1; t = 2; Serial.printf("through buffer (watch then press 2 again, or 1, 3 or 4)\n"); break;
|
||||
case '3': if (t != 3) s = 0; t = 3; Serial.printf("direct access (sendAvailable - watch then press 3 again, or 1, 2 or 4)\n"); break;
|
||||
case '4': t = 4; Serial.printf("direct access (sendAll - close peer to stop, then press 1, 2 or 3 before restarting peer)\n"); break;
|
||||
case '1':
|
||||
if (t != 1) s = 0;
|
||||
t = 1;
|
||||
Serial.println("byte-by-byte (watch then press 2, 3 or 4)");
|
||||
break;
|
||||
case '2':
|
||||
if (t != 2) s = 1;
|
||||
t = 2;
|
||||
Serial.printf("through buffer (watch then press 2 again, or 1, 3 or 4)\n");
|
||||
break;
|
||||
case '3':
|
||||
if (t != 3) s = 0;
|
||||
t = 3;
|
||||
Serial.printf("direct access (sendAvailable - watch then press 3 again, or 1, 2 or 4)\n");
|
||||
break;
|
||||
case '4':
|
||||
t = 4;
|
||||
Serial.printf("direct access (sendAll - close peer to stop, then press 1, 2 or 3 before restarting peer)\n");
|
||||
break;
|
||||
}
|
||||
tot = cnt = 0;
|
||||
ESP.resetFreeContStack();
|
||||
@ -113,9 +122,7 @@ void loop() {
|
||||
uint8_t buf[maxTo];
|
||||
size_t tcp_got = client.read(buf, maxTo);
|
||||
size_t tcp_sent = client.write(buf, tcp_got);
|
||||
if (tcp_sent != maxTo) {
|
||||
Serial.printf("len mismatch: available:%zd tcp-read:%zd serial-write:%zd\n", maxTo, tcp_got, tcp_sent);
|
||||
}
|
||||
if (tcp_sent != maxTo) { Serial.printf("len mismatch: available:%zd tcp-read:%zd serial-write:%zd\n", maxTo, tcp_got, tcp_sent); }
|
||||
tot += tcp_sent;
|
||||
cnt++;
|
||||
}
|
||||
@ -141,7 +148,7 @@ void loop() {
|
||||
|
||||
else if (t == 4) {
|
||||
// stream to print, possibly with only one copy
|
||||
tot += client.sendAll(&client); // this one might not exit until peer close
|
||||
tot += client.sendAll(&client); // this one might not exit until peer close
|
||||
cnt++;
|
||||
|
||||
switch (client.getLastSendReport()) {
|
||||
@ -152,5 +159,4 @@ void loop() {
|
||||
case Stream::Report::ShortOperation: Serial.println("Stream::send: short transfer"); break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -18,10 +18,10 @@
|
||||
|
||||
#ifndef APSSID
|
||||
#define APSSID "esp8266"
|
||||
#define APPSK "esp8266"
|
||||
#define APPSK "esp8266"
|
||||
#endif
|
||||
|
||||
const char* ssid = APSSID;
|
||||
const char* ssid = APSSID;
|
||||
const char* password = APPSK;
|
||||
|
||||
WiFiEventHandler stationConnectedHandler;
|
||||
@ -98,7 +98,6 @@ void loop() {
|
||||
|
||||
String macToString(const unsigned char* mac) {
|
||||
char buf[20];
|
||||
snprintf(buf, sizeof(buf), "%02x:%02x:%02x:%02x:%02x:%02x",
|
||||
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
||||
snprintf(buf, sizeof(buf), "%02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
||||
return String(buf);
|
||||
}
|
||||
|
@ -11,7 +11,7 @@
|
||||
|
||||
#ifndef STASSID
|
||||
#define STASSID "your-ssid"
|
||||
#define STAPSK "your-password"
|
||||
#define STAPSK "your-password"
|
||||
#endif
|
||||
|
||||
const char* ssid = STASSID;
|
||||
@ -55,12 +55,10 @@ void setup() {
|
||||
void loop() {
|
||||
// Check if a client has connected
|
||||
WiFiClient client = server.accept();
|
||||
if (!client) {
|
||||
return;
|
||||
}
|
||||
if (!client) { return; }
|
||||
Serial.println(F("new client"));
|
||||
|
||||
client.setTimeout(5000); // default is 1000
|
||||
client.setTimeout(5000); // default is 1000
|
||||
|
||||
// Read the first line of the request
|
||||
String req = client.readStringUntil('\r');
|
||||
|
@ -40,15 +40,7 @@ void loop() {
|
||||
for (int8_t i = 0; i < scanResult; i++) {
|
||||
WiFi.getNetworkInfo(i, ssid, encryptionType, rssi, bssid, channel, hidden);
|
||||
|
||||
Serial.printf(PSTR(" %02d: [CH %02d] [%02X:%02X:%02X:%02X:%02X:%02X] %ddBm %c %c %s\n"),
|
||||
i,
|
||||
channel,
|
||||
bssid[0], bssid[1], bssid[2],
|
||||
bssid[3], bssid[4], bssid[5],
|
||||
rssi,
|
||||
(encryptionType == ENC_TYPE_NONE) ? ' ' : '*',
|
||||
hidden ? 'H' : 'V',
|
||||
ssid.c_str());
|
||||
Serial.printf(PSTR(" %02d: [CH %02d] [%02X:%02X:%02X:%02X:%02X:%02X] %ddBm %c %c %s\n"), i, channel, bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5], rssi, (encryptionType == ENC_TYPE_NONE) ? ' ' : '*', hidden ? 'H' : 'V', ssid.c_str());
|
||||
yield();
|
||||
}
|
||||
} else {
|
||||
|
@ -17,7 +17,7 @@
|
||||
#endif
|
||||
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <include/WiFiState.h> // WiFiState structure details
|
||||
#include <include/WiFiState.h> // WiFiState structure details
|
||||
|
||||
WiFiState state;
|
||||
|
||||
@ -26,7 +26,7 @@ const char* password = STAPSK;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(74880);
|
||||
//Serial.setDebugOutput(true); // If you need debug output
|
||||
// Serial.setDebugOutput(true); // If you need debug output
|
||||
Serial.println("Trying to resume WiFi connection...");
|
||||
|
||||
// May be necessary after deepSleep. Otherwise you may get "error: pll_cal exceeds 2ms!!!" when trying to connect
|
||||
@ -36,17 +36,14 @@ void setup() {
|
||||
// Here you can do whatever you need to do that doesn't need a WiFi connection.
|
||||
// ---
|
||||
|
||||
ESP.rtcUserMemoryRead(RTC_USER_DATA_SLOT_WIFI_STATE, reinterpret_cast<uint32_t *>(&state), sizeof(state));
|
||||
ESP.rtcUserMemoryRead(RTC_USER_DATA_SLOT_WIFI_STATE, reinterpret_cast<uint32_t*>(&state), sizeof(state));
|
||||
unsigned long start = millis();
|
||||
|
||||
if (!WiFi.resumeFromShutdown(state)
|
||||
|| (WiFi.waitForConnectResult(10000) != WL_CONNECTED)) {
|
||||
if (!WiFi.resumeFromShutdown(state) || (WiFi.waitForConnectResult(10000) != WL_CONNECTED)) {
|
||||
Serial.println("Cannot resume WiFi connection, connecting via begin...");
|
||||
WiFi.persistent(false);
|
||||
|
||||
if (!WiFi.mode(WIFI_STA)
|
||||
|| !WiFi.begin(ssid, password)
|
||||
|| (WiFi.waitForConnectResult(10000) != WL_CONNECTED)) {
|
||||
if (!WiFi.mode(WIFI_STA) || !WiFi.begin(ssid, password) || (WiFi.waitForConnectResult(10000) != WL_CONNECTED)) {
|
||||
WiFi.mode(WIFI_OFF);
|
||||
Serial.println("Cannot connect!");
|
||||
Serial.flush();
|
||||
@ -64,7 +61,7 @@ void setup() {
|
||||
// ---
|
||||
|
||||
WiFi.shutdown(state);
|
||||
ESP.rtcUserMemoryWrite(RTC_USER_DATA_SLOT_WIFI_STATE, reinterpret_cast<uint32_t *>(&state), sizeof(state));
|
||||
ESP.rtcUserMemoryWrite(RTC_USER_DATA_SLOT_WIFI_STATE, reinterpret_cast<uint32_t*>(&state), sizeof(state));
|
||||
|
||||
// ---
|
||||
// Here you can do whatever you need to do that doesn't need a WiFi connection anymore.
|
||||
|
@ -20,11 +20,11 @@
|
||||
*/
|
||||
#include <ESP8266WiFi.h>
|
||||
|
||||
#include <algorithm> // std::min
|
||||
#include <algorithm> // std::min
|
||||
|
||||
#ifndef STASSID
|
||||
#define STASSID "your-ssid"
|
||||
#define STAPSK "your-password"
|
||||
#define STAPSK "your-password"
|
||||
#endif
|
||||
|
||||
/*
|
||||
@ -64,9 +64,9 @@ SoftwareSerial* logger = nullptr;
|
||||
#define logger (&Serial1)
|
||||
#endif
|
||||
|
||||
#define STACK_PROTECTOR 512 // bytes
|
||||
#define STACK_PROTECTOR 512 // bytes
|
||||
|
||||
//how many clients should be able to telnet to this ESP8266
|
||||
// how many clients should be able to telnet to this ESP8266
|
||||
#define MAX_SRV_CLIENTS 2
|
||||
const char* ssid = STASSID;
|
||||
const char* password = STAPSK;
|
||||
@ -98,7 +98,7 @@ void setup() {
|
||||
logger->printf("Serial receive buffer size: %d bytes\n", RXBUFFERSIZE);
|
||||
|
||||
#if SERIAL_LOOPBACK
|
||||
USC0(0) |= (1 << UCLBE); // incomplete HardwareSerial API
|
||||
USC0(0) |= (1 << UCLBE); // incomplete HardwareSerial API
|
||||
logger->println("Serial Internal Loopback enabled");
|
||||
#endif
|
||||
|
||||
@ -114,7 +114,7 @@ void setup() {
|
||||
logger->print("connected, address=");
|
||||
logger->println(WiFi.localIP());
|
||||
|
||||
//start server
|
||||
// start server
|
||||
server.begin();
|
||||
server.setNoDelay(true);
|
||||
|
||||
@ -124,19 +124,19 @@ void setup() {
|
||||
}
|
||||
|
||||
void loop() {
|
||||
//check if there are any new clients
|
||||
// check if there are any new clients
|
||||
if (server.hasClient()) {
|
||||
//find free/disconnected spot
|
||||
// find free/disconnected spot
|
||||
int i;
|
||||
for (i = 0; i < MAX_SRV_CLIENTS; i++)
|
||||
if (!serverClients[i]) { // equivalent to !serverClients[i].connected()
|
||||
if (!serverClients[i]) { // equivalent to !serverClients[i].connected()
|
||||
serverClients[i] = server.accept();
|
||||
logger->print("New client: index ");
|
||||
logger->print(i);
|
||||
break;
|
||||
}
|
||||
|
||||
//no free/disconnected spot so reject
|
||||
// no free/disconnected spot so reject
|
||||
if (i == MAX_SRV_CLIENTS) {
|
||||
server.accept().println("busy");
|
||||
// hints: server.accept() is a WiFiClient with short-term scope
|
||||
@ -147,7 +147,7 @@ void loop() {
|
||||
}
|
||||
}
|
||||
|
||||
//check TCP clients for data
|
||||
// check TCP clients for data
|
||||
#if 1
|
||||
// Incredibly, this code is faster than the buffered one below - #4620 is needed
|
||||
// loopback/3000000baud average 348KB/s
|
||||
@ -165,9 +165,7 @@ void loop() {
|
||||
uint8_t buf[maxToSerial];
|
||||
size_t tcp_got = serverClients[i].read(buf, maxToSerial);
|
||||
size_t serial_sent = Serial.write(buf, tcp_got);
|
||||
if (serial_sent != maxToSerial) {
|
||||
logger->printf("len mismatch: available:%zd tcp-read:%zd serial-write:%zd\n", maxToSerial, tcp_got, serial_sent);
|
||||
}
|
||||
if (serial_sent != maxToSerial) { logger->printf("len mismatch: available:%zd tcp-read:%zd serial-write:%zd\n", maxToSerial, tcp_got, serial_sent); }
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -189,7 +187,7 @@ void loop() {
|
||||
}
|
||||
}
|
||||
|
||||
//check UART for data
|
||||
// check UART for data
|
||||
size_t len = std::min(Serial.available(), maxToTcp);
|
||||
len = std::min(len, (size_t)STACK_PROTECTOR);
|
||||
if (len) {
|
||||
@ -202,9 +200,7 @@ void loop() {
|
||||
// ensure write space is sufficient:
|
||||
if (serverClients[i].availableForWrite() >= serial_got) {
|
||||
size_t tcp_sent = serverClients[i].write(sbuf, serial_got);
|
||||
if (tcp_sent != len) {
|
||||
logger->printf("len mismatch: available:%zd serial-read:%zd tcp-write:%zd\n", len, serial_got, tcp_sent);
|
||||
}
|
||||
if (tcp_sent != len) { logger->printf("len mismatch: available:%zd serial-read:%zd tcp-write:%zd\n", len, serial_got, tcp_sent); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
#define ESP8266WIFIMESH_DISABLE_COMPATIBILITY // Excludes redundant compatibility code. TODO: Should be used for new code until the compatibility code is removed with release 3.0.0 of the Arduino core.
|
||||
#define ESP8266WIFIMESH_DISABLE_COMPATIBILITY // Excludes redundant compatibility code. TODO: Should be used for new code until the compatibility code is removed with release 3.0.0 of the Arduino core.
|
||||
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <EspnowMeshBackend.h>
|
||||
@ -19,26 +19,23 @@ namespace TypeCast = MeshTypeConversionFunctions;
|
||||
https://github.com/esp8266/Arduino/issues/1143
|
||||
https://arduino-esp8266.readthedocs.io/en/latest/PROGMEM.html
|
||||
*/
|
||||
constexpr char exampleMeshName[] PROGMEM = "MeshNode_"; // The name of the mesh network. Used as prefix for the node SSID and to find other network nodes in the example networkFilter and broadcastFilter functions below.
|
||||
constexpr char exampleWiFiPassword[] PROGMEM = "ChangeThisWiFiPassword_TODO"; // Note: " is an illegal character. The password has to be min 8 and max 64 characters long, otherwise an AP which uses it will not be found during scans.
|
||||
constexpr char exampleMeshName[] PROGMEM = "MeshNode_"; // The name of the mesh network. Used as prefix for the node SSID and to find other network nodes in the example networkFilter and broadcastFilter functions below.
|
||||
constexpr char exampleWiFiPassword[] PROGMEM = "ChangeThisWiFiPassword_TODO"; // Note: " is an illegal character. The password has to be min 8 and max 64 characters long, otherwise an AP which uses it will not be found during scans.
|
||||
|
||||
// A custom encryption key is required when using encrypted ESP-NOW transmissions. There is always a default Kok set, but it can be replaced if desired.
|
||||
// All ESP-NOW keys below must match in an encrypted connection pair for encrypted communication to be possible.
|
||||
// Note that it is also possible to use Strings as key seeds instead of arrays.
|
||||
uint8_t espnowEncryptedConnectionKey[16] = {0x33, 0x44, 0x33, 0x44, 0x33, 0x44, 0x33, 0x44, // This is the key for encrypting transmissions of encrypted connections.
|
||||
0x33, 0x44, 0x33, 0x44, 0x33, 0x44, 0x32, 0x11
|
||||
};
|
||||
uint8_t espnowEncryptionKok[16] = {0x22, 0x44, 0x33, 0x44, 0x33, 0x44, 0x33, 0x44, // This is the key for encrypting the encrypted connection key.
|
||||
0x33, 0x44, 0x33, 0x44, 0x33, 0x44, 0x32, 0x33
|
||||
};
|
||||
uint8_t espnowHashKey[16] = {0xEF, 0x44, 0x33, 0x0C, 0x33, 0x44, 0xFE, 0x44, // This is the secret key used for HMAC during encrypted connection requests.
|
||||
0x33, 0x44, 0x33, 0xB0, 0x33, 0x44, 0x32, 0xAD
|
||||
};
|
||||
uint8_t espnowEncryptedConnectionKey[16] = { 0x33, 0x44, 0x33, 0x44, 0x33, 0x44, 0x33, 0x44, // This is the key for encrypting transmissions of encrypted connections.
|
||||
0x33, 0x44, 0x33, 0x44, 0x33, 0x44, 0x32, 0x11 };
|
||||
uint8_t espnowEncryptionKok[16] = { 0x22, 0x44, 0x33, 0x44, 0x33, 0x44, 0x33, 0x44, // This is the key for encrypting the encrypted connection key.
|
||||
0x33, 0x44, 0x33, 0x44, 0x33, 0x44, 0x32, 0x33 };
|
||||
uint8_t espnowHashKey[16] = { 0xEF, 0x44, 0x33, 0x0C, 0x33, 0x44, 0xFE, 0x44, // This is the secret key used for HMAC during encrypted connection requests.
|
||||
0x33, 0x44, 0x33, 0xB0, 0x33, 0x44, 0x32, 0xAD };
|
||||
|
||||
unsigned int requestNumber = 0;
|
||||
unsigned int responseNumber = 0;
|
||||
|
||||
const char broadcastMetadataDelimiter = 23; // 23 = End-of-Transmission-Block (ETB) control character in ASCII
|
||||
const char broadcastMetadataDelimiter = 23; // 23 = End-of-Transmission-Block (ETB) control character in ASCII
|
||||
|
||||
String manageRequest(const String &request, MeshBackendBase &meshInstance);
|
||||
TransmissionStatusType manageResponse(const String &response, MeshBackendBase &meshInstance);
|
||||
@ -61,7 +58,7 @@ String manageRequest(const String &request, MeshBackendBase &meshInstance) {
|
||||
String transmissionEncrypted = espnowInstance->receivedEncryptedTransmission() ? F(", Encrypted transmission") : F(", Unencrypted transmission");
|
||||
Serial.print(String(F("ESP-NOW (")) + espnowInstance->getSenderMac() + transmissionEncrypted + F("): "));
|
||||
} else if (TcpIpMeshBackend *tcpIpInstance = TypeCast::meshBackendCast<TcpIpMeshBackend *>(&meshInstance)) {
|
||||
(void)tcpIpInstance; // This is useful to remove a "unused parameter" compiler warning. Does nothing else.
|
||||
(void)tcpIpInstance; // This is useful to remove a "unused parameter" compiler warning. Does nothing else.
|
||||
Serial.print(F("TCP/IP: "));
|
||||
} else {
|
||||
Serial.print(F("UNKNOWN!: "));
|
||||
@ -174,7 +171,7 @@ bool broadcastFilter(String &firstTransmission, EspnowMeshBackend &meshInstance)
|
||||
String targetMeshName = firstTransmission.substring(0, metadataEndIndex);
|
||||
|
||||
if (!targetMeshName.isEmpty() && meshInstance.getMeshName() != targetMeshName) {
|
||||
return false; // Broadcast is for another mesh network
|
||||
return false; // Broadcast is for another mesh network
|
||||
} else {
|
||||
// Remove metadata from message and mark as accepted broadcast.
|
||||
// Note that when you modify firstTransmission it is best to avoid using substring or other String methods that rely on null values for String length determination.
|
||||
@ -198,7 +195,7 @@ bool broadcastFilter(String &firstTransmission, EspnowMeshBackend &meshInstance)
|
||||
bool exampleTransmissionOutcomesUpdateHook(MeshBackendBase &meshInstance) {
|
||||
// Currently this is exactly the same as the default hook, but you can modify it to alter the behaviour of attemptTransmission.
|
||||
|
||||
(void)meshInstance; // This is useful to remove a "unused parameter" compiler warning. Does nothing else.
|
||||
(void)meshInstance; // This is useful to remove a "unused parameter" compiler warning. Does nothing else.
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -221,7 +218,7 @@ bool exampleTransmissionOutcomesUpdateHook(MeshBackendBase &meshInstance) {
|
||||
bool exampleResponseTransmittedHook(bool transmissionSuccessful, const String &response, const uint8_t *recipientMac, uint32_t responseIndex, EspnowMeshBackend &meshInstance) {
|
||||
// Currently this is exactly the same as the default hook, but you can modify it to alter the behaviour of sendEspnowResponses.
|
||||
|
||||
(void)transmissionSuccessful; // This is useful to remove a "unused parameter" compiler warning. Does nothing else.
|
||||
(void)transmissionSuccessful; // This is useful to remove a "unused parameter" compiler warning. Does nothing else.
|
||||
(void)response;
|
||||
(void)recipientMac;
|
||||
(void)responseIndex;
|
||||
@ -281,8 +278,8 @@ void setup() {
|
||||
// Uncomment the lines below to use automatic AEAD encryption/decryption of messages sent/received.
|
||||
// All nodes this node wishes to communicate with must then also use encrypted messages with the same getEspnowMessageEncryptionKey(), or messages will not be accepted.
|
||||
// Note that using AEAD encrypted messages will reduce the number of message bytes that can be transmitted.
|
||||
//espnowNode.setEspnowMessageEncryptionKey(F("ChangeThisKeySeed_TODO")); // The message encryption key should always be set manually. Otherwise a default key (all zeroes) is used.
|
||||
//espnowNode.setUseEncryptedMessages(true);
|
||||
// espnowNode.setEspnowMessageEncryptionKey(F("ChangeThisKeySeed_TODO")); // The message encryption key should always be set manually. Otherwise a default key (all zeroes) is used.
|
||||
// espnowNode.setUseEncryptedMessages(true);
|
||||
}
|
||||
|
||||
int32_t timeOfLastScan = -10000;
|
||||
@ -293,10 +290,10 @@ void loop() {
|
||||
// Note that depending on the amount of responses to send and their length, this method can take tens or even hundreds of milliseconds to complete.
|
||||
// More intense transmission activity and less frequent calls to performEspnowMaintenance will likely cause the method to take longer to complete, so plan accordingly.
|
||||
|
||||
//Should not be used inside responseHandler, requestHandler, networkFilter or broadcastFilter callbacks since performEspnowMaintenance() can alter the ESP-NOW state.
|
||||
// Should not be used inside responseHandler, requestHandler, networkFilter or broadcastFilter callbacks since performEspnowMaintenance() can alter the ESP-NOW state.
|
||||
EspnowMeshBackend::performEspnowMaintenance();
|
||||
|
||||
if (millis() - timeOfLastScan > 10000) { // Give other nodes some time to connect between data transfers.
|
||||
if (millis() - timeOfLastScan > 10000) { // Give other nodes some time to connect between data transfers.
|
||||
Serial.println(F("\nPerforming unencrypted ESP-NOW transmissions."));
|
||||
|
||||
uint32_t startTime = millis();
|
||||
@ -310,9 +307,7 @@ void loop() {
|
||||
espnowDelay(100);
|
||||
|
||||
// One way to check how attemptTransmission worked out
|
||||
if (espnowNode.latestTransmissionSuccessful()) {
|
||||
Serial.println(F("Transmission successful."));
|
||||
}
|
||||
if (espnowNode.latestTransmissionSuccessful()) { Serial.println(F("Transmission successful.")); }
|
||||
|
||||
// Another way to check how attemptTransmission worked out
|
||||
if (espnowNode.latestTransmissionOutcomes().empty()) {
|
||||
@ -343,20 +338,20 @@ void loop() {
|
||||
espnowNode.broadcast(broadcastMetadata + broadcastMessage);
|
||||
Serial.println(String(F("Broadcast to all mesh nodes done in ")) + String(millis() - startTime) + F(" ms."));
|
||||
|
||||
espnowDelay(100); // Wait for responses (broadcasts can receive an unlimited number of responses, other transmissions can only receive one response).
|
||||
espnowDelay(100); // Wait for responses (broadcasts can receive an unlimited number of responses, other transmissions can only receive one response).
|
||||
|
||||
// If you have a data array containing null values it is possible to transmit the raw data by making the array into a multiString as shown below.
|
||||
// You can use String::c_str() or String::begin() to retrieve the data array later.
|
||||
// Note that certain String methods such as String::substring use null values to determine String length, which means they will not work as normal with multiStrings.
|
||||
uint8_t dataArray[] = {0, '\'', 0, '\'', ' ', '(', 'n', 'u', 'l', 'l', ')', ' ', 'v', 'a', 'l', 'u', 'e'};
|
||||
uint8_t dataArray[] = { 0, '\'', 0, '\'', ' ', '(', 'n', 'u', 'l', 'l', ')', ' ', 'v', 'a', 'l', 'u', 'e' };
|
||||
String espnowMessage = TypeCast::uint8ArrayToMultiString(dataArray, sizeof dataArray) + F(" from ") + espnowNode.getMeshName() + espnowNode.getNodeID() + String('.');
|
||||
Serial.println(String(F("\nTransmitting: ")) + espnowMessage);
|
||||
espnowNode.attemptTransmission(espnowMessage, false);
|
||||
espnowDelay(100); // Wait for response.
|
||||
espnowDelay(100); // Wait for response.
|
||||
|
||||
Serial.println(F("\nPerforming encrypted ESP-NOW transmissions."));
|
||||
|
||||
uint8_t targetBSSID[6] {0};
|
||||
uint8_t targetBSSID[6]{ 0 };
|
||||
|
||||
// We can create encrypted connections to individual nodes so that all ESP-NOW communication with the node will be encrypted.
|
||||
if (espnowNode.constConnectionQueue()[0].getBSSID(targetBSSID) && espnowNode.requestEncryptedConnection(targetBSSID) == EncryptedConnectionStatus::CONNECTION_ESTABLISHED) {
|
||||
@ -369,7 +364,7 @@ void loop() {
|
||||
String espnowMessage = String(F("This message is encrypted only when received by node ")) + peerMac;
|
||||
Serial.println(String(F("\nTransmitting: ")) + espnowMessage);
|
||||
espnowNode.attemptTransmission(espnowMessage, false);
|
||||
espnowDelay(100); // Wait for response.
|
||||
espnowDelay(100); // Wait for response.
|
||||
|
||||
// A connection can be serialized and stored for later use.
|
||||
// Note that this saves the current state only, so if encrypted communication between the nodes happen after this, the stored state is invalid.
|
||||
@ -383,7 +378,7 @@ void loop() {
|
||||
espnowMessage = String(F("This message is no longer encrypted when received by node ")) + peerMac;
|
||||
Serial.println(String(F("\nTransmitting: ")) + espnowMessage);
|
||||
espnowNode.attemptTransmission(espnowMessage, false);
|
||||
espnowDelay(100); // Wait for response.
|
||||
espnowDelay(100); // Wait for response.
|
||||
Serial.println(F("Cannot read the encrypted response..."));
|
||||
|
||||
// Let's re-add our stored connection so we can communicate properly with targetBSSID again!
|
||||
@ -392,7 +387,7 @@ void loop() {
|
||||
espnowMessage = String(F("This message is once again encrypted when received by node ")) + peerMac;
|
||||
Serial.println(String(F("\nTransmitting: ")) + espnowMessage);
|
||||
espnowNode.attemptTransmission(espnowMessage, false);
|
||||
espnowDelay(100); // Wait for response.
|
||||
espnowDelay(100); // Wait for response.
|
||||
|
||||
Serial.println();
|
||||
// If we want to remove the encrypted connection on both nodes, we can do it like this.
|
||||
@ -403,7 +398,7 @@ void loop() {
|
||||
espnowMessage = String(F("This message is only received by node ")) + peerMac + F(". Transmitting in this way will not change the transmission state of the sender.");
|
||||
Serial.println(String(F("Transmitting: ")) + espnowMessage);
|
||||
espnowNode.attemptTransmission(espnowMessage, EspnowNetworkInfo(targetBSSID));
|
||||
espnowDelay(100); // Wait for response.
|
||||
espnowDelay(100); // Wait for response.
|
||||
|
||||
Serial.println();
|
||||
|
||||
@ -423,7 +418,7 @@ void loop() {
|
||||
espnowMessage = String(F("Due to encrypted connection expiration, this message is no longer encrypted when received by node ")) + peerMac;
|
||||
Serial.println(String(F("\nTransmitting: ")) + espnowMessage);
|
||||
espnowNode.attemptTransmission(espnowMessage, false);
|
||||
espnowDelay(100); // Wait for response.
|
||||
espnowDelay(100); // Wait for response.
|
||||
}
|
||||
|
||||
// Or if we prefer we can just let the library automatically create brief encrypted connections which are long enough to transmit an encrypted message.
|
||||
@ -432,9 +427,9 @@ void loop() {
|
||||
espnowMessage = F("This message is always encrypted, regardless of receiver.");
|
||||
Serial.println(String(F("\nTransmitting: ")) + espnowMessage);
|
||||
espnowNode.attemptAutoEncryptingTransmission(espnowMessage);
|
||||
espnowDelay(100); // Wait for response.
|
||||
espnowDelay(100); // Wait for response.
|
||||
} else {
|
||||
Serial.println(String(F("Ooops! Encrypted connection removal failed. Status: ")) + String(static_cast<int>(removalOutcome)));
|
||||
Serial.println(String(F("Ooops! Encrypted connection removal failed. Status: ")) + String(static_cast<int>(removalOutcome)));
|
||||
}
|
||||
|
||||
// Finally, should you ever want to stop other parties from sending unencrypted messages to the node
|
||||
@ -445,8 +440,7 @@ void loop() {
|
||||
}
|
||||
|
||||
// Our last request was sent to all nodes found, so time to create a new request.
|
||||
espnowNode.setMessage(String(F("Hello world request #")) + String(++requestNumber) + F(" from ")
|
||||
+ espnowNode.getMeshName() + espnowNode.getNodeID() + String('.'));
|
||||
espnowNode.setMessage(String(F("Hello world request #")) + String(++requestNumber) + F(" from ") + espnowNode.getMeshName() + espnowNode.getNodeID() + String('.'));
|
||||
}
|
||||
|
||||
Serial.println();
|
||||
|
@ -8,7 +8,7 @@
|
||||
Or "floodingMesh.getEspnowMeshBackend().setBroadcastTransmissionRedundancy(uint8_t redundancy)" (default 1) at the cost of longer transmission times.
|
||||
*/
|
||||
|
||||
#define ESP8266WIFIMESH_DISABLE_COMPATIBILITY // Excludes redundant compatibility code. TODO: Should be used for new code until the compatibility code is removed with release 3.0.0 of the Arduino core.
|
||||
#define ESP8266WIFIMESH_DISABLE_COMPATIBILITY // Excludes redundant compatibility code. TODO: Should be used for new code until the compatibility code is removed with release 3.0.0 of the Arduino core.
|
||||
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <TypeConversionFunctions.h>
|
||||
@ -28,18 +28,16 @@ namespace TypeCast = MeshTypeConversionFunctions;
|
||||
https://github.com/esp8266/Arduino/issues/1143
|
||||
https://arduino-esp8266.readthedocs.io/en/latest/PROGMEM.html
|
||||
*/
|
||||
constexpr char exampleMeshName[] PROGMEM = "MeshNode_"; // The name of the mesh network. Used as prefix for the node SSID and to find other network nodes in the example networkFilter and broadcastFilter functions below.
|
||||
constexpr char exampleWiFiPassword[] PROGMEM = "ChangeThisWiFiPassword_TODO"; // Note: " is an illegal character. The password has to be min 8 and max 64 characters long, otherwise an AP which uses it will not be found during scans.
|
||||
constexpr char exampleMeshName[] PROGMEM = "MeshNode_"; // The name of the mesh network. Used as prefix for the node SSID and to find other network nodes in the example networkFilter and broadcastFilter functions below.
|
||||
constexpr char exampleWiFiPassword[] PROGMEM = "ChangeThisWiFiPassword_TODO"; // Note: " is an illegal character. The password has to be min 8 and max 64 characters long, otherwise an AP which uses it will not be found during scans.
|
||||
|
||||
// A custom encryption key is required when using encrypted ESP-NOW transmissions. There is always a default Kok set, but it can be replaced if desired.
|
||||
// All ESP-NOW keys below must match in an encrypted connection pair for encrypted communication to be possible.
|
||||
// Note that it is also possible to use Strings as key seeds instead of arrays.
|
||||
uint8_t espnowEncryptedConnectionKey[16] = {0x33, 0x44, 0x33, 0x44, 0x33, 0x44, 0x33, 0x44, // This is the key for encrypting transmissions of encrypted connections.
|
||||
0x33, 0x44, 0x33, 0x44, 0x33, 0x44, 0x32, 0x11
|
||||
};
|
||||
uint8_t espnowHashKey[16] = {0xEF, 0x44, 0x33, 0x0C, 0x33, 0x44, 0xFE, 0x44, // This is the secret key used for HMAC during encrypted connection requests.
|
||||
0x33, 0x44, 0x33, 0xB0, 0x33, 0x44, 0x32, 0xAD
|
||||
};
|
||||
uint8_t espnowEncryptedConnectionKey[16] = { 0x33, 0x44, 0x33, 0x44, 0x33, 0x44, 0x33, 0x44, // This is the key for encrypting transmissions of encrypted connections.
|
||||
0x33, 0x44, 0x33, 0x44, 0x33, 0x44, 0x32, 0x11 };
|
||||
uint8_t espnowHashKey[16] = { 0xEF, 0x44, 0x33, 0x0C, 0x33, 0x44, 0xFE, 0x44, // This is the secret key used for HMAC during encrypted connection requests.
|
||||
0x33, 0x44, 0x33, 0xB0, 0x33, 0x44, 0x32, 0xAD };
|
||||
|
||||
bool meshMessageHandler(String &message, FloodingMesh &meshInstance);
|
||||
|
||||
@ -49,7 +47,7 @@ FloodingMesh floodingMesh = FloodingMesh(meshMessageHandler, FPSTR(exampleWiFiPa
|
||||
bool theOne = true;
|
||||
String theOneMac;
|
||||
|
||||
bool useLED = false; // Change this to true if you wish the onboard LED to mark The One.
|
||||
bool useLED = false; // Change this to true if you wish the onboard LED to mark The One.
|
||||
|
||||
/**
|
||||
Callback for when a message is received from the mesh network.
|
||||
@ -78,7 +76,7 @@ bool meshMessageHandler(String &message, FloodingMesh &meshInstance) {
|
||||
|
||||
if (useLED && !theOne) {
|
||||
bool ledState = message.charAt(1) == '1';
|
||||
digitalWrite(LED_BUILTIN, ledState); // Turn LED on/off (LED_BUILTIN is active low)
|
||||
digitalWrite(LED_BUILTIN, ledState); // Turn LED on/off (LED_BUILTIN is active low)
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -87,26 +85,22 @@ bool meshMessageHandler(String &message, FloodingMesh &meshInstance) {
|
||||
}
|
||||
} else if (delimiterIndex > 0) {
|
||||
if (meshInstance.getOriginMac() == theOneMac) {
|
||||
uint32_t totalBroadcasts = strtoul(message.c_str(), nullptr, 0); // strtoul stops reading input when an invalid character is discovered.
|
||||
uint32_t totalBroadcasts = strtoul(message.c_str(), nullptr, 0); // strtoul stops reading input when an invalid character is discovered.
|
||||
|
||||
// Static variables are only initialized once.
|
||||
static uint32_t firstBroadcast = totalBroadcasts;
|
||||
|
||||
if (totalBroadcasts - firstBroadcast >= 100) { // Wait a little to avoid start-up glitches
|
||||
static uint32_t missedBroadcasts = 1; // Starting at one to compensate for initial -1 below.
|
||||
if (totalBroadcasts - firstBroadcast >= 100) { // Wait a little to avoid start-up glitches
|
||||
static uint32_t missedBroadcasts = 1; // Starting at one to compensate for initial -1 below.
|
||||
static uint32_t previousTotalBroadcasts = totalBroadcasts;
|
||||
static uint32_t totalReceivedBroadcasts = 0;
|
||||
totalReceivedBroadcasts++;
|
||||
|
||||
missedBroadcasts += totalBroadcasts - previousTotalBroadcasts - 1; // We expect an increment by 1.
|
||||
missedBroadcasts += totalBroadcasts - previousTotalBroadcasts - 1; // We expect an increment by 1.
|
||||
previousTotalBroadcasts = totalBroadcasts;
|
||||
|
||||
if (totalReceivedBroadcasts % 50 == 0) {
|
||||
Serial.println(String(F("missed/total: ")) + String(missedBroadcasts) + '/' + String(totalReceivedBroadcasts));
|
||||
}
|
||||
if (totalReceivedBroadcasts % 500 == 0) {
|
||||
Serial.println(String(F("Benchmark message: ")) + message.substring(0, 100));
|
||||
}
|
||||
if (totalReceivedBroadcasts % 50 == 0) { Serial.println(String(F("missed/total: ")) + String(missedBroadcasts) + '/' + String(totalReceivedBroadcasts)); }
|
||||
if (totalReceivedBroadcasts % 500 == 0) { Serial.println(String(F("Benchmark message: ")) + message.substring(0, 100)); }
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -136,24 +130,24 @@ void setup() {
|
||||
Serial.println(F("Setting up mesh node..."));
|
||||
|
||||
floodingMesh.begin();
|
||||
floodingMesh.activateAP(); // Required to receive messages
|
||||
floodingMesh.activateAP(); // Required to receive messages
|
||||
|
||||
uint8_t apMacArray[6] {0};
|
||||
uint8_t apMacArray[6]{ 0 };
|
||||
theOneMac = TypeCast::macToString(WiFi.softAPmacAddress(apMacArray));
|
||||
|
||||
if (useLED) {
|
||||
pinMode(LED_BUILTIN, OUTPUT); // Initialize the LED_BUILTIN pin as an output
|
||||
digitalWrite(LED_BUILTIN, LOW); // Turn LED on (LED_BUILTIN is active low)
|
||||
pinMode(LED_BUILTIN, OUTPUT); // Initialize the LED_BUILTIN pin as an output
|
||||
digitalWrite(LED_BUILTIN, LOW); // Turn LED on (LED_BUILTIN is active low)
|
||||
}
|
||||
|
||||
// Uncomment the lines below to use automatic AEAD encryption/decryption of messages sent/received via broadcast() and encryptedBroadcast().
|
||||
// The main benefit of AEAD encryption is that it can be used with normal broadcasts (which are substantially faster than encryptedBroadcasts).
|
||||
// The main drawbacks are that AEAD only encrypts the message data (not transmission metadata), transfers less data per message and lacks replay attack protection.
|
||||
// When using AEAD, potential replay attacks must thus be handled manually.
|
||||
//floodingMesh.getEspnowMeshBackend().setEspnowMessageEncryptionKey(F("ChangeThisKeySeed_TODO")); // The message encryption key should always be set manually. Otherwise a default key (all zeroes) is used.
|
||||
//floodingMesh.getEspnowMeshBackend().setUseEncryptedMessages(true);
|
||||
// floodingMesh.getEspnowMeshBackend().setEspnowMessageEncryptionKey(F("ChangeThisKeySeed_TODO")); // The message encryption key should always be set manually. Otherwise a default key (all zeroes) is used.
|
||||
// floodingMesh.getEspnowMeshBackend().setUseEncryptedMessages(true);
|
||||
|
||||
floodingMeshDelay(5000); // Give some time for user to start the nodes
|
||||
floodingMeshDelay(5000); // Give some time for user to start the nodes
|
||||
}
|
||||
|
||||
int32_t timeOfLastProclamation = -10000;
|
||||
@ -177,7 +171,7 @@ void loop() {
|
||||
if (theOne) {
|
||||
if (millis() - timeOfLastProclamation > 10000) {
|
||||
uint32_t startTime = millis();
|
||||
ledState = ledState ^ bool(benchmarkCount); // Make other nodes' LEDs alternate between on and off once benchmarking begins.
|
||||
ledState = ledState ^ bool(benchmarkCount); // Make other nodes' LEDs alternate between on and off once benchmarking begins.
|
||||
|
||||
// Note: The maximum length of an unencrypted broadcast message is given by floodingMesh.maxUnencryptedMessageLength(). It is around 670 bytes by default.
|
||||
floodingMesh.broadcast(String(floodingMesh.metadataDelimiter()) + String(ledState) + theOneMac + F(" is The One."));
|
||||
@ -187,7 +181,7 @@ void loop() {
|
||||
floodingMeshDelay(20);
|
||||
}
|
||||
|
||||
if (millis() - loopStart > 23000) { // Start benchmarking the mesh once three proclamations have been made
|
||||
if (millis() - loopStart > 23000) { // Start benchmarking the mesh once three proclamations have been made
|
||||
uint32_t startTime = millis();
|
||||
floodingMesh.broadcast(String(benchmarkCount++) + String(floodingMesh.metadataDelimiter()) + F(": Not a spoon in sight."));
|
||||
Serial.println(String(F("Benchmark broadcast done in ")) + String(millis() - startTime) + F(" ms."));
|
||||
|
@ -1,4 +1,4 @@
|
||||
#define ESP8266WIFIMESH_DISABLE_COMPATIBILITY // Excludes redundant compatibility code. TODO: Should be used for new code until the compatibility code is removed with release 3.0.0 of the Arduino core.
|
||||
#define ESP8266WIFIMESH_DISABLE_COMPATIBILITY // Excludes redundant compatibility code. TODO: Should be used for new code until the compatibility code is removed with release 3.0.0 of the Arduino core.
|
||||
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <TcpIpMeshBackend.h>
|
||||
@ -20,7 +20,7 @@ namespace TypeCast = MeshTypeConversionFunctions;
|
||||
https://arduino-esp8266.readthedocs.io/en/latest/PROGMEM.html
|
||||
*/
|
||||
constexpr char exampleMeshName[] PROGMEM = "MeshNode_";
|
||||
constexpr char exampleWiFiPassword[] PROGMEM = "ChangeThisWiFiPassword_TODO"; // Note: " is an illegal character. The password has to be min 8 and max 64 characters long, otherwise an AP which uses it will not be found during scans.
|
||||
constexpr char exampleWiFiPassword[] PROGMEM = "ChangeThisWiFiPassword_TODO"; // Note: " is an illegal character. The password has to be min 8 and max 64 characters long, otherwise an AP which uses it will not be found during scans.
|
||||
|
||||
unsigned int requestNumber = 0;
|
||||
unsigned int responseNumber = 0;
|
||||
@ -45,7 +45,7 @@ String manageRequest(const String &request, MeshBackendBase &meshInstance) {
|
||||
String transmissionEncrypted = espnowInstance->receivedEncryptedTransmission() ? F(", Encrypted transmission") : F(", Unencrypted transmission");
|
||||
Serial.print(String(F("ESP-NOW (")) + espnowInstance->getSenderMac() + transmissionEncrypted + F("): "));
|
||||
} else if (TcpIpMeshBackend *tcpIpInstance = TypeCast::meshBackendCast<TcpIpMeshBackend *>(&meshInstance)) {
|
||||
(void)tcpIpInstance; // This is useful to remove a "unused parameter" compiler warning. Does nothing else.
|
||||
(void)tcpIpInstance; // This is useful to remove a "unused parameter" compiler warning. Does nothing else.
|
||||
Serial.print(F("TCP/IP: "));
|
||||
} else {
|
||||
Serial.print(F("UNKNOWN!: "));
|
||||
@ -145,8 +145,7 @@ bool exampleTransmissionOutcomesUpdateHook(MeshBackendBase &meshInstance) {
|
||||
if (TcpIpMeshBackend *tcpIpInstance = TypeCast::meshBackendCast<TcpIpMeshBackend *>(&meshInstance)) {
|
||||
if (tcpIpInstance->latestTransmissionOutcomes().back().transmissionStatus() == TransmissionStatusType::TRANSMISSION_COMPLETE) {
|
||||
// Our last request got a response, so time to create a new request.
|
||||
meshInstance.setMessage(String(F("Hello world request #")) + String(++requestNumber) + F(" from ")
|
||||
+ meshInstance.getMeshName() + meshInstance.getNodeID() + String('.'));
|
||||
meshInstance.setMessage(String(F("Hello world request #")) + String(++requestNumber) + F(" from ") + meshInstance.getMeshName() + meshInstance.getNodeID() + String('.'));
|
||||
}
|
||||
} else {
|
||||
Serial.println(F("Invalid mesh backend!"));
|
||||
@ -174,8 +173,8 @@ void setup() {
|
||||
|
||||
/* Initialise the mesh node */
|
||||
tcpIpNode.begin();
|
||||
tcpIpNode.activateAP(); // Each AP requires a separate server port.
|
||||
tcpIpNode.setStaticIP(IPAddress(192, 168, 4, 22)); // Activate static IP mode to speed up connection times.
|
||||
tcpIpNode.activateAP(); // Each AP requires a separate server port.
|
||||
tcpIpNode.setStaticIP(IPAddress(192, 168, 4, 22)); // Activate static IP mode to speed up connection times.
|
||||
|
||||
// Storing our message in the TcpIpMeshBackend instance is not required, but can be useful for organizing code, especially when using many TcpIpMeshBackend instances.
|
||||
// Note that calling the multi-recipient tcpIpNode.attemptTransmission will replace the stored message with whatever message is transmitted.
|
||||
@ -186,17 +185,15 @@ void setup() {
|
||||
|
||||
int32_t timeOfLastScan = -10000;
|
||||
void loop() {
|
||||
if (millis() - timeOfLastScan > 3000 // Give other nodes some time to connect between data transfers.
|
||||
|| (WiFi.status() != WL_CONNECTED && millis() - timeOfLastScan > 2000)) { // Scan for networks with two second intervals when not already connected.
|
||||
if (millis() - timeOfLastScan > 3000 // Give other nodes some time to connect between data transfers.
|
||||
|| (WiFi.status() != WL_CONNECTED && millis() - timeOfLastScan > 2000)) { // Scan for networks with two second intervals when not already connected.
|
||||
|
||||
// attemptTransmission(message, scan, scanAllWiFiChannels, concludingDisconnect, initialDisconnect = false)
|
||||
tcpIpNode.attemptTransmission(tcpIpNode.getMessage(), true, false, false);
|
||||
timeOfLastScan = millis();
|
||||
|
||||
// One way to check how attemptTransmission worked out
|
||||
if (tcpIpNode.latestTransmissionSuccessful()) {
|
||||
Serial.println(F("Transmission successful."));
|
||||
}
|
||||
if (tcpIpNode.latestTransmissionSuccessful()) { Serial.println(F("Transmission successful.")); }
|
||||
|
||||
// Another way to check how attemptTransmission worked out
|
||||
if (tcpIpNode.latestTransmissionOutcomes().empty()) {
|
||||
|
@ -15,7 +15,7 @@
|
||||
|
||||
#ifndef APSSID
|
||||
#define APSSID "APSSID"
|
||||
#define APPSK "APPSK"
|
||||
#define APPSK "APPSK"
|
||||
#endif
|
||||
|
||||
ESP8266WiFiMulti WiFiMulti;
|
||||
@ -37,8 +37,6 @@ void setup() {
|
||||
|
||||
WiFi.mode(WIFI_STA);
|
||||
WiFiMulti.addAP(APSSID, APPSK);
|
||||
|
||||
|
||||
}
|
||||
|
||||
void update_started() {
|
||||
@ -80,21 +78,14 @@ void loop() {
|
||||
|
||||
t_httpUpdate_return ret = ESPhttpUpdate.update(client, "http://server/file.bin");
|
||||
// Or:
|
||||
//t_httpUpdate_return ret = ESPhttpUpdate.update(client, "server", 80, "file.bin");
|
||||
// t_httpUpdate_return ret = ESPhttpUpdate.update(client, "server", 80, "file.bin");
|
||||
|
||||
switch (ret) {
|
||||
case HTTP_UPDATE_FAILED:
|
||||
Serial.printf("HTTP_UPDATE_FAILD Error (%d): %s\n", ESPhttpUpdate.getLastError(), ESPhttpUpdate.getLastErrorString().c_str());
|
||||
break;
|
||||
case HTTP_UPDATE_FAILED: Serial.printf("HTTP_UPDATE_FAILD Error (%d): %s\n", ESPhttpUpdate.getLastError(), ESPhttpUpdate.getLastErrorString().c_str()); break;
|
||||
|
||||
case HTTP_UPDATE_NO_UPDATES:
|
||||
Serial.println("HTTP_UPDATE_NO_UPDATES");
|
||||
break;
|
||||
case HTTP_UPDATE_NO_UPDATES: Serial.println("HTTP_UPDATE_NO_UPDATES"); break;
|
||||
|
||||
case HTTP_UPDATE_OK:
|
||||
Serial.println("HTTP_UPDATE_OK");
|
||||
break;
|
||||
case HTTP_UPDATE_OK: Serial.println("HTTP_UPDATE_OK"); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -17,7 +17,7 @@ ESP8266WiFiMulti WiFiMulti;
|
||||
|
||||
#ifndef APSSID
|
||||
#define APSSID "APSSID"
|
||||
#define APPSK "APPSK"
|
||||
#define APPSK "APPSK"
|
||||
#endif
|
||||
|
||||
void setup() {
|
||||
@ -37,7 +37,6 @@ void setup() {
|
||||
|
||||
WiFi.mode(WIFI_STA);
|
||||
WiFiMulti.addAP(APSSID, APPSK);
|
||||
|
||||
}
|
||||
|
||||
void loop() {
|
||||
@ -62,19 +61,12 @@ void loop() {
|
||||
ret = ESPhttpUpdate.update(client, "http://server/file.bin");
|
||||
|
||||
switch (ret) {
|
||||
case HTTP_UPDATE_FAILED:
|
||||
Serial.printf("HTTP_UPDATE_FAILED Error (%d): %s", ESPhttpUpdate.getLastError(), ESPhttpUpdate.getLastErrorString().c_str());
|
||||
break;
|
||||
case HTTP_UPDATE_FAILED: Serial.printf("HTTP_UPDATE_FAILED Error (%d): %s", ESPhttpUpdate.getLastError(), ESPhttpUpdate.getLastErrorString().c_str()); break;
|
||||
|
||||
case HTTP_UPDATE_NO_UPDATES:
|
||||
Serial.println("HTTP_UPDATE_NO_UPDATES");
|
||||
break;
|
||||
case HTTP_UPDATE_NO_UPDATES: Serial.println("HTTP_UPDATE_NO_UPDATES"); break;
|
||||
|
||||
case HTTP_UPDATE_OK:
|
||||
Serial.println("HTTP_UPDATE_OK");
|
||||
break;
|
||||
case HTTP_UPDATE_OK: Serial.println("HTTP_UPDATE_OK"); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -18,7 +18,7 @@
|
||||
|
||||
#ifndef APSSID
|
||||
#define APSSID "APSSID"
|
||||
#define APPSK "APPSK"
|
||||
#define APPSK "APPSK"
|
||||
#endif
|
||||
|
||||
ESP8266WiFiMulti WiFiMulti;
|
||||
@ -74,7 +74,7 @@ void setup() {
|
||||
Serial.println(numCerts);
|
||||
if (numCerts == 0) {
|
||||
Serial.println(F("No certs found. Did you run certs-from-mozill.py and upload the LittleFS directory before running?"));
|
||||
return; // Can't connect to anything w/o certs!
|
||||
return; // Can't connect to anything w/o certs!
|
||||
}
|
||||
}
|
||||
|
||||
@ -87,9 +87,7 @@ void loop() {
|
||||
BearSSL::WiFiClientSecure client;
|
||||
bool mfln = client.probeMaxFragmentLength("server", 443, 1024); // server must be the same as in ESPhttpUpdate.update()
|
||||
Serial.printf("MFLN supported: %s\n", mfln ? "yes" : "no");
|
||||
if (mfln) {
|
||||
client.setBufferSizes(1024, 1024);
|
||||
}
|
||||
if (mfln) { client.setBufferSizes(1024, 1024); }
|
||||
client.setCertStore(&certStore);
|
||||
|
||||
// The line below is optional. It can be used to blink the LED on the board during flashing
|
||||
@ -102,21 +100,15 @@ void loop() {
|
||||
|
||||
t_httpUpdate_return ret = ESPhttpUpdate.update(client, "https://server/file.bin");
|
||||
// Or:
|
||||
//t_httpUpdate_return ret = ESPhttpUpdate.update(client, "server", 443, "file.bin");
|
||||
// t_httpUpdate_return ret = ESPhttpUpdate.update(client, "server", 443, "file.bin");
|
||||
|
||||
|
||||
switch (ret) {
|
||||
case HTTP_UPDATE_FAILED:
|
||||
Serial.printf("HTTP_UPDATE_FAILED Error (%d): %s\n", ESPhttpUpdate.getLastError(), ESPhttpUpdate.getLastErrorString().c_str());
|
||||
break;
|
||||
case HTTP_UPDATE_FAILED: Serial.printf("HTTP_UPDATE_FAILED Error (%d): %s\n", ESPhttpUpdate.getLastError(), ESPhttpUpdate.getLastErrorString().c_str()); break;
|
||||
|
||||
case HTTP_UPDATE_NO_UPDATES:
|
||||
Serial.println("HTTP_UPDATE_NO_UPDATES");
|
||||
break;
|
||||
case HTTP_UPDATE_NO_UPDATES: Serial.println("HTTP_UPDATE_NO_UPDATES"); break;
|
||||
|
||||
case HTTP_UPDATE_OK:
|
||||
Serial.println("HTTP_UPDATE_OK");
|
||||
break;
|
||||
case HTTP_UPDATE_OK: Serial.println("HTTP_UPDATE_OK"); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -23,7 +23,7 @@
|
||||
|
||||
#ifndef STASSID
|
||||
#define STASSID "your-ssid"
|
||||
#define STAPSK "your-password"
|
||||
#define STAPSK "your-password"
|
||||
#endif
|
||||
|
||||
ESP8266WiFiMulti WiFiMulti;
|
||||
@ -73,11 +73,11 @@ void setup() {
|
||||
WiFi.mode(WIFI_STA);
|
||||
WiFiMulti.addAP(STASSID, STAPSK);
|
||||
|
||||
#if MANUAL_SIGNING
|
||||
#if MANUAL_SIGNING
|
||||
signPubKey = new BearSSL::PublicKey(pubkey);
|
||||
hash = new BearSSL::HashSHA256();
|
||||
sign = new BearSSL::SigningVerifier(signPubKey);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@ -87,10 +87,10 @@ void loop() {
|
||||
|
||||
WiFiClient client;
|
||||
|
||||
#if MANUAL_SIGNING
|
||||
#if MANUAL_SIGNING
|
||||
// Ensure all updates are signed appropriately. W/o this call, all will be accepted.
|
||||
Update.installSignature(hash, sign);
|
||||
#endif
|
||||
#endif
|
||||
// If the key files are present in the build directory, signing will be
|
||||
// enabled using them automatically
|
||||
|
||||
@ -99,19 +99,12 @@ void loop() {
|
||||
t_httpUpdate_return ret = ESPhttpUpdate.update(client, "http://192.168.1.8/esp8266.bin");
|
||||
|
||||
switch (ret) {
|
||||
case HTTP_UPDATE_FAILED:
|
||||
Serial.printf("HTTP_UPDATE_FAILED Error (%d): %s\n", ESPhttpUpdate.getLastError(), ESPhttpUpdate.getLastErrorString().c_str());
|
||||
break;
|
||||
case HTTP_UPDATE_FAILED: Serial.printf("HTTP_UPDATE_FAILED Error (%d): %s\n", ESPhttpUpdate.getLastError(), ESPhttpUpdate.getLastErrorString().c_str()); break;
|
||||
|
||||
case HTTP_UPDATE_NO_UPDATES:
|
||||
Serial.println("HTTP_UPDATE_NO_UPDATES");
|
||||
break;
|
||||
case HTTP_UPDATE_NO_UPDATES: Serial.println("HTTP_UPDATE_NO_UPDATES"); break;
|
||||
|
||||
case HTTP_UPDATE_OK:
|
||||
Serial.println("HTTP_UPDATE_OK");
|
||||
break;
|
||||
case HTTP_UPDATE_OK: Serial.println("HTTP_UPDATE_OK"); break;
|
||||
}
|
||||
}
|
||||
delay(10000);
|
||||
}
|
||||
|
||||
|
@ -43,39 +43,38 @@
|
||||
Global defines and vars
|
||||
*/
|
||||
|
||||
#define TIMEZONE_OFFSET 1 // CET
|
||||
#define DST_OFFSET 1 // CEST
|
||||
#define UPDATE_CYCLE (1 * 1000) // every second
|
||||
#define TIMEZONE_OFFSET 1 // CET
|
||||
#define DST_OFFSET 1 // CEST
|
||||
#define UPDATE_CYCLE (1 * 1000) // every second
|
||||
|
||||
#define SERVICE_PORT 80 // HTTP port
|
||||
#define SERVICE_PORT 80 // HTTP port
|
||||
|
||||
#ifndef STASSID
|
||||
#define STASSID "your-ssid"
|
||||
#define STAPSK "your-password"
|
||||
#define STAPSK "your-password"
|
||||
#endif
|
||||
|
||||
const char* ssid = STASSID;
|
||||
const char* password = STAPSK;
|
||||
const char* ssid = STASSID;
|
||||
const char* password = STAPSK;
|
||||
|
||||
char* pcHostDomain = 0; // Negotiated host domain
|
||||
bool bHostDomainConfirmed = false; // Flags the confirmation of the host domain
|
||||
MDNSResponder::hMDNSService hMDNSService = 0; // The handle of the clock service in the MDNS responder
|
||||
char* pcHostDomain = 0; // Negotiated host domain
|
||||
bool bHostDomainConfirmed = false; // Flags the confirmation of the host domain
|
||||
MDNSResponder::hMDNSService hMDNSService = 0; // The handle of the clock service in the MDNS responder
|
||||
|
||||
// HTTP server at port 'SERVICE_PORT' will respond to HTTP requests
|
||||
ESP8266WebServer server(SERVICE_PORT);
|
||||
ESP8266WebServer server(SERVICE_PORT);
|
||||
|
||||
/*
|
||||
getTimeString
|
||||
*/
|
||||
const char* getTimeString(void) {
|
||||
|
||||
static char acTimeString[32];
|
||||
static char acTimeString[32];
|
||||
time_t now = time(nullptr);
|
||||
ctime_r(&now, acTimeString);
|
||||
size_t stLength;
|
||||
while (((stLength = strlen(acTimeString))) &&
|
||||
('\n' == acTimeString[stLength - 1])) {
|
||||
acTimeString[stLength - 1] = 0; // Remove trailing line break...
|
||||
size_t stLength;
|
||||
while (((stLength = strlen(acTimeString))) && ('\n' == acTimeString[stLength - 1])) {
|
||||
acTimeString[stLength - 1] = 0; // Remove trailing line break...
|
||||
}
|
||||
return acTimeString;
|
||||
}
|
||||
@ -186,7 +185,8 @@ void handleHTTPRequest() {
|
||||
Serial.println("HTTP Request");
|
||||
|
||||
// Get current time
|
||||
time_t now = time(nullptr);;
|
||||
time_t now = time(nullptr);
|
||||
;
|
||||
struct tm timeinfo;
|
||||
gmtime_r(&now, &timeinfo);
|
||||
|
||||
@ -231,10 +231,9 @@ void setup(void) {
|
||||
// Setup MDNS responder
|
||||
MDNS.setHostProbeResultCallback(hostProbeResult);
|
||||
// Init the (currently empty) host domain string with 'esp8266'
|
||||
if ((!MDNSResponder::indexDomain(pcHostDomain, 0, "esp8266")) ||
|
||||
(!MDNS.begin(pcHostDomain))) {
|
||||
if ((!MDNSResponder::indexDomain(pcHostDomain, 0, "esp8266")) || (!MDNS.begin(pcHostDomain))) {
|
||||
Serial.println("Error setting up MDNS responder!");
|
||||
while (1) { // STOP
|
||||
while (1) { // STOP
|
||||
delay(1000);
|
||||
}
|
||||
}
|
||||
|
@ -39,26 +39,26 @@
|
||||
Global defines and vars
|
||||
*/
|
||||
|
||||
#define SERVICE_PORT 80 // HTTP port
|
||||
#define SERVICE_PORT 80 // HTTP port
|
||||
|
||||
#ifndef STASSID
|
||||
#define STASSID "your-ssid"
|
||||
#define STAPSK "your-password"
|
||||
#define STAPSK "your-password"
|
||||
#endif
|
||||
|
||||
const char* ssid = STASSID;
|
||||
const char* password = STAPSK;
|
||||
const char* ssid = STASSID;
|
||||
const char* password = STAPSK;
|
||||
|
||||
char* pcHostDomain = 0; // Negotiated host domain
|
||||
bool bHostDomainConfirmed = false; // Flags the confirmation of the host domain
|
||||
MDNSResponder::hMDNSService hMDNSService = 0; // The handle of the http service in the MDNS responder
|
||||
MDNSResponder::hMDNSServiceQuery hMDNSServiceQuery = 0; // The handle of the 'http.tcp' service query in the MDNS responder
|
||||
char* pcHostDomain = 0; // Negotiated host domain
|
||||
bool bHostDomainConfirmed = false; // Flags the confirmation of the host domain
|
||||
MDNSResponder::hMDNSService hMDNSService = 0; // The handle of the http service in the MDNS responder
|
||||
MDNSResponder::hMDNSServiceQuery hMDNSServiceQuery = 0; // The handle of the 'http.tcp' service query in the MDNS responder
|
||||
|
||||
const String cstrNoHTTPServices = "Currently no 'http.tcp' services in the local network!<br/>";
|
||||
String strHTTPServices = cstrNoHTTPServices;
|
||||
const String cstrNoHTTPServices = "Currently no 'http.tcp' services in the local network!<br/>";
|
||||
String strHTTPServices = cstrNoHTTPServices;
|
||||
|
||||
// HTTP server at port 'SERVICE_PORT' will respond to HTTP requests
|
||||
ESP8266WebServer server(SERVICE_PORT);
|
||||
ESP8266WebServer server(SERVICE_PORT);
|
||||
|
||||
|
||||
/*
|
||||
@ -80,26 +80,17 @@ bool setStationHostname(const char* p_pcHostname) {
|
||||
void MDNSServiceQueryCallback(MDNSResponder::MDNSServiceInfo serviceInfo, MDNSResponder::AnswerType answerType, bool p_bSetContent) {
|
||||
String answerInfo;
|
||||
switch (answerType) {
|
||||
case MDNSResponder::AnswerType::ServiceDomain :
|
||||
answerInfo = "ServiceDomain " + String(serviceInfo.serviceDomain());
|
||||
break;
|
||||
case MDNSResponder::AnswerType::HostDomainAndPort :
|
||||
answerInfo = "HostDomainAndPort " + String(serviceInfo.hostDomain()) + ":" + String(serviceInfo.hostPort());
|
||||
break;
|
||||
case MDNSResponder::AnswerType::IP4Address :
|
||||
case MDNSResponder::AnswerType::ServiceDomain: answerInfo = "ServiceDomain " + String(serviceInfo.serviceDomain()); break;
|
||||
case MDNSResponder::AnswerType::HostDomainAndPort: answerInfo = "HostDomainAndPort " + String(serviceInfo.hostDomain()) + ":" + String(serviceInfo.hostPort()); break;
|
||||
case MDNSResponder::AnswerType::IP4Address:
|
||||
answerInfo = "IP4Address ";
|
||||
for (IPAddress ip : serviceInfo.IP4Adresses()) {
|
||||
answerInfo += "- " + ip.toString();
|
||||
};
|
||||
for (IPAddress ip : serviceInfo.IP4Adresses()) { answerInfo += "- " + ip.toString(); };
|
||||
break;
|
||||
case MDNSResponder::AnswerType::Txt :
|
||||
case MDNSResponder::AnswerType::Txt:
|
||||
answerInfo = "TXT " + String(serviceInfo.strKeyValue());
|
||||
for (auto kv : serviceInfo.keyValues()) {
|
||||
answerInfo += "\nkv : " + String(kv.first) + " : " + String(kv.second);
|
||||
}
|
||||
for (auto kv : serviceInfo.keyValues()) { answerInfo += "\nkv : " + String(kv.first) + " : " + String(kv.second); }
|
||||
break;
|
||||
default :
|
||||
answerInfo = "Unknown Answertype";
|
||||
default: answerInfo = "Unknown Answertype";
|
||||
}
|
||||
Serial.printf("Answer %s %s\n", answerInfo.c_str(), p_bSetContent ? "Modified" : "Deleted");
|
||||
}
|
||||
@ -109,10 +100,8 @@ void MDNSServiceQueryCallback(MDNSResponder::MDNSServiceInfo serviceInfo, MDNSRe
|
||||
Probe result callback for Services
|
||||
*/
|
||||
|
||||
void serviceProbeResult(String p_pcServiceName,
|
||||
const MDNSResponder::hMDNSService p_hMDNSService,
|
||||
bool p_bProbeResult) {
|
||||
(void) p_hMDNSService;
|
||||
void serviceProbeResult(String p_pcServiceName, const MDNSResponder::hMDNSService p_hMDNSService, bool p_bProbeResult) {
|
||||
(void)p_hMDNSService;
|
||||
Serial.printf("MDNSServiceProbeResultCallback: Service %s probe %s\n", p_pcServiceName.c_str(), (p_bProbeResult ? "succeeded." : "failed!"));
|
||||
}
|
||||
|
||||
@ -186,7 +175,7 @@ void handleHTTPRequest() {
|
||||
s += WiFi.hostname() + ".local at " + WiFi.localIP().toString() + "</h3></head>";
|
||||
s += "<br/><h4>Local HTTP services are :</h4>";
|
||||
s += "<ol>";
|
||||
for (auto info : MDNS.answerInfo(hMDNSServiceQuery)) {
|
||||
for (auto info : MDNS.answerInfo(hMDNSServiceQuery)) {
|
||||
s += "<li>";
|
||||
s += info.serviceDomain();
|
||||
if (info.hostDomainAvailable()) {
|
||||
@ -196,15 +185,11 @@ void handleHTTPRequest() {
|
||||
}
|
||||
if (info.IP4AddressAvailable()) {
|
||||
s += "<br/>IP4:";
|
||||
for (auto ip : info.IP4Adresses()) {
|
||||
s += " " + ip.toString();
|
||||
}
|
||||
for (auto ip : info.IP4Adresses()) { s += " " + ip.toString(); }
|
||||
}
|
||||
if (info.txtAvailable()) {
|
||||
s += "<br/>TXT:<br/>";
|
||||
for (auto kv : info.keyValues()) {
|
||||
s += "\t" + String(kv.first) + " : " + String(kv.second) + "<br/>";
|
||||
}
|
||||
for (auto kv : info.keyValues()) { s += "\t" + String(kv.first) + " : " + String(kv.second) + "<br/>"; }
|
||||
}
|
||||
s += "</li>";
|
||||
}
|
||||
@ -245,10 +230,9 @@ void setup(void) {
|
||||
MDNS.setHostProbeResultCallback(hostProbeResult);
|
||||
|
||||
// Init the (currently empty) host domain string with 'esp8266'
|
||||
if ((!MDNSResponder::indexDomain(pcHostDomain, 0, "esp8266")) ||
|
||||
(!MDNS.begin(pcHostDomain))) {
|
||||
if ((!MDNSResponder::indexDomain(pcHostDomain, 0, "esp8266")) || (!MDNS.begin(pcHostDomain))) {
|
||||
Serial.println(" Error setting up MDNS responder!");
|
||||
while (1) { // STOP
|
||||
while (1) { // STOP
|
||||
delay(1000);
|
||||
}
|
||||
}
|
||||
@ -265,6 +249,3 @@ void loop(void) {
|
||||
// Allow MDNS processing
|
||||
MDNS.update();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -14,12 +14,12 @@
|
||||
|
||||
#ifndef APSSID
|
||||
#define APSSID "your-apssid"
|
||||
#define APPSK "your-password"
|
||||
#define APPSK "your-password"
|
||||
#endif
|
||||
|
||||
#ifndef STASSID
|
||||
#define STASSID "your-sta"
|
||||
#define STAPSK "your-password"
|
||||
#define STAPSK "your-password"
|
||||
#endif
|
||||
|
||||
// includes
|
||||
@ -35,15 +35,15 @@
|
||||
@brief mDNS and OTA Constants
|
||||
@{
|
||||
*/
|
||||
#define HOSTNAME "ESP8266-OTA-" ///< Hostname. The setup function adds the Chip ID at the end.
|
||||
#define HOSTNAME "ESP8266-OTA-" ///< Hostname. The setup function adds the Chip ID at the end.
|
||||
/// @}
|
||||
|
||||
/**
|
||||
@brief Default WiFi connection information.
|
||||
@{
|
||||
*/
|
||||
const char* ap_default_ssid = APSSID; ///< Default SSID.
|
||||
const char* ap_default_psk = APPSK; ///< Default PSK.
|
||||
const char *ap_default_ssid = APSSID; ///< Default SSID.
|
||||
const char *ap_default_psk = APPSK; ///< Default PSK.
|
||||
/// @}
|
||||
|
||||
/// Uncomment the next line for verbose output over UART.
|
||||
@ -81,9 +81,7 @@ bool loadConfig(String *ssid, String *pass) {
|
||||
if (pos == -1) {
|
||||
le = 1;
|
||||
pos = content.indexOf("\n");
|
||||
if (pos == -1) {
|
||||
pos = content.indexOf("\r");
|
||||
}
|
||||
if (pos == -1) { pos = content.indexOf("\r"); }
|
||||
}
|
||||
|
||||
// If there is no second line: Some information is missing.
|
||||
@ -110,7 +108,7 @@ bool loadConfig(String *ssid, String *pass) {
|
||||
#endif
|
||||
|
||||
return true;
|
||||
} // loadConfig
|
||||
} // loadConfig
|
||||
|
||||
|
||||
/**
|
||||
@ -135,7 +133,7 @@ bool saveConfig(String *ssid, String *pass) {
|
||||
configFile.close();
|
||||
|
||||
return true;
|
||||
} // saveConfig
|
||||
} // saveConfig
|
||||
|
||||
|
||||
/**
|
||||
@ -160,7 +158,7 @@ void setup() {
|
||||
|
||||
// Print hostname.
|
||||
Serial.println("Hostname: " + hostname);
|
||||
//Serial.println(WiFi.hostname());
|
||||
// Serial.println(WiFi.hostname());
|
||||
|
||||
|
||||
// Initialize file system.
|
||||
@ -170,7 +168,7 @@ void setup() {
|
||||
}
|
||||
|
||||
// Load wifi connection information.
|
||||
if (! loadConfig(&station_ssid, &station_psk)) {
|
||||
if (!loadConfig(&station_ssid, &station_psk)) {
|
||||
station_ssid = STASSID;
|
||||
station_psk = STAPSK;
|
||||
|
||||
@ -196,7 +194,7 @@ void setup() {
|
||||
Serial.println(WiFi.SSID());
|
||||
|
||||
// ... Uncomment this for debugging output.
|
||||
//WiFi.printDiag(Serial);
|
||||
// WiFi.printDiag(Serial);
|
||||
} else {
|
||||
// ... Begin with sdk config.
|
||||
WiFi.begin();
|
||||
@ -208,7 +206,7 @@ void setup() {
|
||||
unsigned long startTime = millis();
|
||||
while (WiFi.status() != WL_CONNECTED && millis() - startTime < 10000) {
|
||||
Serial.write('.');
|
||||
//Serial.print(WiFi.status());
|
||||
// Serial.print(WiFi.status());
|
||||
delay(500);
|
||||
}
|
||||
Serial.println();
|
||||
@ -245,4 +243,3 @@ void loop() {
|
||||
// Handle OTA server.
|
||||
ArduinoOTA.handle();
|
||||
}
|
||||
|
||||
|
@ -14,12 +14,12 @@
|
||||
|
||||
#ifndef STASSID
|
||||
#define STASSID "your-ssid"
|
||||
#define STAPSK "your-password"
|
||||
#define STAPSK "your-password"
|
||||
#endif
|
||||
|
||||
const char* ssid = STASSID;
|
||||
const char* ssid = STASSID;
|
||||
const char* password = STAPSK;
|
||||
char hostString[16] = {0};
|
||||
char hostString[16] = { 0 };
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
@ -43,14 +43,12 @@ void setup() {
|
||||
Serial.print("IP address: ");
|
||||
Serial.println(WiFi.localIP());
|
||||
|
||||
if (!MDNS.begin(hostString)) {
|
||||
Serial.println("Error setting up MDNS responder!");
|
||||
}
|
||||
if (!MDNS.begin(hostString)) { Serial.println("Error setting up MDNS responder!"); }
|
||||
Serial.println("mDNS responder started");
|
||||
MDNS.addService("esp", "tcp", 8080); // Announce esp tcp service on port 8080
|
||||
MDNS.addService("esp", "tcp", 8080); // Announce esp tcp service on port 8080
|
||||
|
||||
Serial.println("Sending mDNS query");
|
||||
int n = MDNS.queryService("esp", "tcp"); // Send out query for esp tcp services
|
||||
int n = MDNS.queryService("esp", "tcp"); // Send out query for esp tcp services
|
||||
Serial.println("mDNS query done");
|
||||
if (n == 0) {
|
||||
Serial.println("no services found");
|
||||
|
@ -22,7 +22,7 @@
|
||||
|
||||
#ifndef STASSID
|
||||
#define STASSID "your-ssid"
|
||||
#define STAPSK "your-password"
|
||||
#define STAPSK "your-password"
|
||||
#endif
|
||||
|
||||
const char* ssid = STASSID;
|
||||
@ -57,9 +57,7 @@ void setup(void) {
|
||||
// we send our IP address on the WiFi network
|
||||
if (!MDNS.begin("esp8266")) {
|
||||
Serial.println("Error setting up MDNS responder!");
|
||||
while (1) {
|
||||
delay(1000);
|
||||
}
|
||||
while (1) { delay(1000); }
|
||||
}
|
||||
Serial.println("mDNS responder started");
|
||||
|
||||
@ -77,16 +75,12 @@ void loop(void) {
|
||||
|
||||
// Check if a client has connected
|
||||
WiFiClient client = server.accept();
|
||||
if (!client) {
|
||||
return;
|
||||
}
|
||||
if (!client) { return; }
|
||||
Serial.println("");
|
||||
Serial.println("New client");
|
||||
|
||||
// Wait for data from client to become available
|
||||
while (client.connected() && !client.available()) {
|
||||
delay(1);
|
||||
}
|
||||
while (client.connected() && !client.available()) { delay(1); }
|
||||
|
||||
// Read the first line of HTTP request
|
||||
String req = client.readStringUntil('\r');
|
||||
@ -121,4 +115,3 @@ void loop(void) {
|
||||
|
||||
Serial.println("Done with client");
|
||||
}
|
||||
|
||||
|
@ -30,4 +30,3 @@
|
||||
#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_MDNS)
|
||||
MDNSResponder MDNS;
|
||||
#endif
|
||||
|
||||
|
@ -3,15 +3,19 @@
|
||||
This file is part of the esp8266 core for Arduino environment.
|
||||
|
||||
mDNS implementation, that supports many mDNS features like:
|
||||
- Presenting a DNS-SD service to interested observers, eg. a http server by presenting _http._tcp service
|
||||
- Support for multi-level compressed names in input; in output only a very simple one-leven full-name compression is implemented
|
||||
- Presenting a DNS-SD service to interested observers, eg. a http server by presenting
|
||||
_http._tcp service
|
||||
- Support for multi-level compressed names in input; in output only a very simple one-leven
|
||||
full-name compression is implemented
|
||||
- Probing host and service domains for uniqueness in the local network
|
||||
- Tiebreaking while probing is supported in a very minimalistic way (the 'higher' IP address wins the tiebreak)
|
||||
- Tiebreaking while probing is supported in a very minimalistic way (the 'higher' IP address
|
||||
wins the tiebreak)
|
||||
- Announcing available services after successful probing
|
||||
- Using fixed service TXT items or
|
||||
- Using dynamic service TXT items for presented services (via callback)
|
||||
- Remove services (and un-announcing them to the observers by sending goodbye-messages)
|
||||
- Static queries for DNS-SD services (creating a fixed answer set after a certain timeout period)
|
||||
- Static queries for DNS-SD services (creating a fixed answer set after a certain timeout
|
||||
period)
|
||||
- Dynamic queries for DNS-SD services with cached and updated answers and user notifications
|
||||
- Support for multi-homed client host domains
|
||||
|
||||
@ -41,13 +45,13 @@
|
||||
#ifndef __ESP8266MDNS_H
|
||||
#define __ESP8266MDNS_H
|
||||
|
||||
#include "LEAmDNS.h" // LEA
|
||||
#include "LEAmDNS.h" // LEA
|
||||
|
||||
#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_MDNS)
|
||||
// Maps the implementation to use to the global namespace type
|
||||
using MDNSResponder = esp8266::MDNSImplementation::MDNSResponder; // LEA
|
||||
using MDNSResponder = esp8266::MDNSImplementation::MDNSResponder; // LEA
|
||||
|
||||
extern MDNSResponder MDNS;
|
||||
#endif
|
||||
|
||||
#endif // __ESP8266MDNS_H
|
||||
#endif // __ESP8266MDNS_H
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -37,7 +37,7 @@ namespace MDNSImplementation
|
||||
|
||||
// Enable class debug functions
|
||||
#define ESP_8266_MDNS_INCLUDE
|
||||
//#define DEBUG_ESP_MDNS_RESPONDER
|
||||
//#define DEBUG_ESP_MDNS_RESPONDER
|
||||
|
||||
#if !defined(DEBUG_ESP_MDNS_RESPONDER) && defined(DEBUG_ESP_MDNS)
|
||||
#define DEBUG_ESP_MDNS_RESPONDER
|
||||
@ -48,8 +48,9 @@ namespace MDNSImplementation
|
||||
#endif
|
||||
|
||||
//
|
||||
// If ENABLE_ESP_MDNS_RESPONDER_PASSIV_MODE is defined, the mDNS responder ignores a successful probing
|
||||
// This allows to drive the responder in a environment, where 'update()' isn't called in the loop
|
||||
// If ENABLE_ESP_MDNS_RESPONDER_PASSIV_MODE is defined, the mDNS responder ignores a successful
|
||||
// probing This allows to drive the responder in a environment, where 'update()' isn't called in the
|
||||
// loop
|
||||
//#define ENABLE_ESP_MDNS_RESPONDER_PASSIV_MODE
|
||||
|
||||
// Enable/disable debug trace macros
|
||||
@ -62,7 +63,7 @@ namespace MDNSImplementation
|
||||
|
||||
#ifdef DEBUG_ESP_MDNS_RESPONDER
|
||||
#ifdef DEBUG_ESP_MDNS_INFO
|
||||
#define DEBUG_EX_INFO(A) A
|
||||
#define DEBUG_EX_INFO(A) A
|
||||
#else
|
||||
#define DEBUG_EX_INFO(A)
|
||||
#endif
|
||||
@ -72,12 +73,12 @@ namespace MDNSImplementation
|
||||
#define DEBUG_EX_ERR(A)
|
||||
#endif
|
||||
#ifdef DEBUG_ESP_MDNS_TX
|
||||
#define DEBUG_EX_TX(A) A
|
||||
#define DEBUG_EX_TX(A) A
|
||||
#else
|
||||
#define DEBUG_EX_TX(A)
|
||||
#endif
|
||||
#ifdef DEBUG_ESP_MDNS_RX
|
||||
#define DEBUG_EX_RX(A) A
|
||||
#define DEBUG_EX_RX(A) A
|
||||
#else
|
||||
#define DEBUG_EX_RX(A)
|
||||
#endif
|
||||
@ -88,19 +89,34 @@ namespace MDNSImplementation
|
||||
#define DEBUG_OUTPUT Serial
|
||||
#endif
|
||||
#else
|
||||
#define DEBUG_EX_INFO(A) do { (void)0; } while (0)
|
||||
#define DEBUG_EX_ERR(A) do { (void)0; } while (0)
|
||||
#define DEBUG_EX_TX(A) do { (void)0; } while (0)
|
||||
#define DEBUG_EX_RX(A) do { (void)0; } while (0)
|
||||
#define DEBUG_EX_INFO(A) \
|
||||
do \
|
||||
{ \
|
||||
(void)0; \
|
||||
} while (0)
|
||||
#define DEBUG_EX_ERR(A) \
|
||||
do \
|
||||
{ \
|
||||
(void)0; \
|
||||
} while (0)
|
||||
#define DEBUG_EX_TX(A) \
|
||||
do \
|
||||
{ \
|
||||
(void)0; \
|
||||
} while (0)
|
||||
#define DEBUG_EX_RX(A) \
|
||||
do \
|
||||
{ \
|
||||
(void)0; \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
/* already defined in lwIP ('lwip/prot/dns.h')
|
||||
#ifdef MDNS_IP4_SUPPORT
|
||||
#define DNS_MQUERY_IPV4_GROUP_INIT (IPAddress(224, 0, 0, 251)) // ip_addr_t v4group = DNS_MQUERY_IPV4_GROUP_INIT
|
||||
#endif
|
||||
#ifdef MDNS_IP6_SUPPORT
|
||||
#define DNS_MQUERY_IPV6_GROUP_INIT IPADDR6_INIT_HOST(0xFF020000,0,0,0xFB) // ip_addr_t v6group = DNS_MQUERY_IPV6_GROUP_INIT
|
||||
#endif*/
|
||||
#define DNS_MQUERY_IPV4_GROUP_INIT (IPAddress(224, 0, 0, 251)) // ip_addr_t
|
||||
v4group = DNS_MQUERY_IPV4_GROUP_INIT #endif #ifdef MDNS_IP6_SUPPORT #define
|
||||
DNS_MQUERY_IPV6_GROUP_INIT IPADDR6_INIT_HOST(0xFF020000,0,0,0xFB) // ip_addr_t v6group =
|
||||
DNS_MQUERY_IPV6_GROUP_INIT #endif*/
|
||||
//#define MDNS_MULTICAST_PORT 5353
|
||||
|
||||
/*
|
||||
@ -111,44 +127,44 @@ namespace MDNSImplementation
|
||||
|
||||
However, RFC 3171 seems to force 255 instead
|
||||
*/
|
||||
#define MDNS_MULTICAST_TTL 255/*1*/
|
||||
#define MDNS_MULTICAST_TTL 255 /*1*/
|
||||
|
||||
/*
|
||||
This is the MDNS record TTL
|
||||
Host level records are set to 2min (120s)
|
||||
service level records are set to 75min (4500s)
|
||||
*/
|
||||
#define MDNS_HOST_TTL 120
|
||||
#define MDNS_SERVICE_TTL 4500
|
||||
#define MDNS_HOST_TTL 120
|
||||
#define MDNS_SERVICE_TTL 4500
|
||||
|
||||
/*
|
||||
Compressed labels are flagged by the two topmost bits of the length byte being set
|
||||
*/
|
||||
#define MDNS_DOMAIN_COMPRESS_MARK 0xC0
|
||||
#define MDNS_DOMAIN_COMPRESS_MARK 0xC0
|
||||
/*
|
||||
Avoid endless recursion because of malformed compressed labels
|
||||
*/
|
||||
#define MDNS_DOMAIN_MAX_REDIRCTION 6
|
||||
#define MDNS_DOMAIN_MAX_REDIRCTION 6
|
||||
|
||||
/*
|
||||
Default service priority and weight in SRV answers
|
||||
*/
|
||||
#define MDNS_SRV_PRIORITY 0
|
||||
#define MDNS_SRV_WEIGHT 0
|
||||
#define MDNS_SRV_PRIORITY 0
|
||||
#define MDNS_SRV_WEIGHT 0
|
||||
|
||||
/*
|
||||
Delay between and number of probes for host and service domains
|
||||
Delay between and number of announces for host and service domains
|
||||
Delay between and number of service queries; the delay is multiplied by the resent number in '_checkServiceQueryCache'
|
||||
Delay between and number of service queries; the delay is multiplied by the resent number in
|
||||
'_checkServiceQueryCache'
|
||||
*/
|
||||
#define MDNS_PROBE_DELAY 250
|
||||
#define MDNS_PROBE_COUNT 3
|
||||
#define MDNS_ANNOUNCE_DELAY 1000
|
||||
#define MDNS_ANNOUNCE_COUNT 8
|
||||
#define MDNS_PROBE_DELAY 250
|
||||
#define MDNS_PROBE_COUNT 3
|
||||
#define MDNS_ANNOUNCE_DELAY 1000
|
||||
#define MDNS_ANNOUNCE_COUNT 8
|
||||
#define MDNS_DYNAMIC_QUERY_RESEND_COUNT 5
|
||||
#define MDNS_DYNAMIC_QUERY_RESEND_DELAY 5000
|
||||
|
||||
|
||||
/*
|
||||
Force host domain to use only lowercase letters
|
||||
*/
|
||||
@ -167,15 +183,14 @@ namespace MDNSImplementation
|
||||
#ifdef F
|
||||
#undef F
|
||||
#endif
|
||||
#define F(A) A
|
||||
#define F(A) A
|
||||
#endif
|
||||
|
||||
} // namespace MDNSImplementation
|
||||
} // namespace MDNSImplementation
|
||||
|
||||
} // namespace esp8266
|
||||
} // namespace esp8266
|
||||
|
||||
// Include the main header, so the submodlues only need to include this header
|
||||
#include "LEAmDNS.h"
|
||||
|
||||
|
||||
#endif // MDNS_PRIV_H
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -27,4 +27,4 @@
|
||||
|
||||
#include <lwip/prot/dns.h> // DNS_RRTYPE_xxx, DNS_MQUERY_PORT
|
||||
|
||||
#endif // MDNS_LWIPDEFS_H
|
||||
#endif // MDNS_LWIPDEFS_H
|
||||
|
@ -22,9 +22,7 @@ void loop() {
|
||||
sha1("test", &hash[0]);
|
||||
|
||||
Serial.print("SHA1:");
|
||||
for (uint16_t i = 0; i < 20; i++) {
|
||||
Serial.printf("%02x", hash[i]);
|
||||
}
|
||||
for (uint16_t i = 0; i < 20; i++) { Serial.printf("%02x", hash[i]); }
|
||||
Serial.println();
|
||||
|
||||
delay(1000);
|
||||
|
@ -15,13 +15,14 @@ void setup() {
|
||||
// on non-native USB ports
|
||||
Serial.begin(115200);
|
||||
while (!Serial) {
|
||||
; // wait for serial port to connect. Needed for native USB port only
|
||||
; // wait for serial port to connect. Needed for native USB port only
|
||||
}
|
||||
|
||||
// start I2S at 8 kHz with 24-bits per sample
|
||||
if (!I2S.begin(I2S_PHILIPS_MODE, 8000, 24)) {
|
||||
Serial.println("Failed to initialize I2S!");
|
||||
while (1); // do nothing
|
||||
while (1)
|
||||
; // do nothing
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -10,13 +10,13 @@
|
||||
|
||||
#include <I2S.h>
|
||||
|
||||
const int frequency = 440; // frequency of square wave in Hz
|
||||
const int amplitude = 500; // amplitude of square wave
|
||||
const int sampleRate = 8000; // sample rate in Hz
|
||||
const int frequency = 440; // frequency of square wave in Hz
|
||||
const int amplitude = 500; // amplitude of square wave
|
||||
const int sampleRate = 8000; // sample rate in Hz
|
||||
|
||||
const int halfWavelength = (sampleRate / frequency); // half wavelength of square wave
|
||||
const int halfWavelength = (sampleRate / frequency); // half wavelength of square wave
|
||||
|
||||
short sample = amplitude; // current sample value
|
||||
short sample = amplitude; // current sample value
|
||||
int count = 0;
|
||||
|
||||
void setup() {
|
||||
@ -26,7 +26,8 @@ void setup() {
|
||||
// start I2S at the sample rate with 16-bits per sample
|
||||
if (!I2S.begin(I2S_PHILIPS_MODE, sampleRate, 16)) {
|
||||
Serial.println("Failed to initialize I2S!");
|
||||
while (1); // do nothing
|
||||
while (1)
|
||||
; // do nothing
|
||||
}
|
||||
}
|
||||
|
||||
@ -43,4 +44,3 @@ void loop() {
|
||||
// increment the counter for the next sample
|
||||
count++;
|
||||
}
|
||||
|
||||
|
@ -9,7 +9,7 @@
|
||||
|
||||
#ifndef STASSID
|
||||
#define STASSID "your-ssid"
|
||||
#define STAPSK "your-password"
|
||||
#define STAPSK "your-password"
|
||||
#endif
|
||||
|
||||
const char *ssid = STASSID;
|
||||
@ -19,7 +19,7 @@ long timezone = 2;
|
||||
byte daysavetime = 1;
|
||||
|
||||
|
||||
void listDir(const char * dirname) {
|
||||
void listDir(const char *dirname) {
|
||||
Serial.printf("Listing directory: %s\n", dirname);
|
||||
|
||||
Dir root = LittleFS.openDir(dirname);
|
||||
@ -33,7 +33,7 @@ void listDir(const char * dirname) {
|
||||
time_t cr = file.getCreationTime();
|
||||
time_t lw = file.getLastWrite();
|
||||
file.close();
|
||||
struct tm * tmstruct = localtime(&cr);
|
||||
struct tm *tmstruct = localtime(&cr);
|
||||
Serial.printf(" CREATION: %d-%02d-%02d %02d:%02d:%02d\n", (tmstruct->tm_year) + 1900, (tmstruct->tm_mon) + 1, tmstruct->tm_mday, tmstruct->tm_hour, tmstruct->tm_min, tmstruct->tm_sec);
|
||||
tmstruct = localtime(&lw);
|
||||
Serial.printf(" LAST WRITE: %d-%02d-%02d %02d:%02d:%02d\n", (tmstruct->tm_year) + 1900, (tmstruct->tm_mon) + 1, tmstruct->tm_mday, tmstruct->tm_hour, tmstruct->tm_min, tmstruct->tm_sec);
|
||||
@ -41,7 +41,7 @@ void listDir(const char * dirname) {
|
||||
}
|
||||
|
||||
|
||||
void readFile(const char * path) {
|
||||
void readFile(const char *path) {
|
||||
Serial.printf("Reading file: %s\n", path);
|
||||
|
||||
File file = LittleFS.open(path, "r");
|
||||
@ -51,13 +51,11 @@ void readFile(const char * path) {
|
||||
}
|
||||
|
||||
Serial.print("Read from file: ");
|
||||
while (file.available()) {
|
||||
Serial.write(file.read());
|
||||
}
|
||||
while (file.available()) { Serial.write(file.read()); }
|
||||
file.close();
|
||||
}
|
||||
|
||||
void writeFile(const char * path, const char * message) {
|
||||
void writeFile(const char *path, const char *message) {
|
||||
Serial.printf("Writing file: %s\n", path);
|
||||
|
||||
File file = LittleFS.open(path, "w");
|
||||
@ -70,11 +68,11 @@ void writeFile(const char * path, const char * message) {
|
||||
} else {
|
||||
Serial.println("Write failed");
|
||||
}
|
||||
delay(2000); // Make sure the CREATE and LASTWRITE times are different
|
||||
delay(2000); // Make sure the CREATE and LASTWRITE times are different
|
||||
file.close();
|
||||
}
|
||||
|
||||
void appendFile(const char * path, const char * message) {
|
||||
void appendFile(const char *path, const char *message) {
|
||||
Serial.printf("Appending to file: %s\n", path);
|
||||
|
||||
File file = LittleFS.open(path, "a");
|
||||
@ -90,7 +88,7 @@ void appendFile(const char * path, const char * message) {
|
||||
file.close();
|
||||
}
|
||||
|
||||
void renameFile(const char * path1, const char * path2) {
|
||||
void renameFile(const char *path1, const char *path2) {
|
||||
Serial.printf("Renaming file %s to %s\n", path1, path2);
|
||||
if (LittleFS.rename(path1, path2)) {
|
||||
Serial.println("File renamed");
|
||||
@ -99,7 +97,7 @@ void renameFile(const char * path1, const char * path2) {
|
||||
}
|
||||
}
|
||||
|
||||
void deleteFile(const char * path) {
|
||||
void deleteFile(const char *path) {
|
||||
Serial.printf("Deleting file: %s\n", path);
|
||||
if (LittleFS.remove(path)) {
|
||||
Serial.println("File deleted");
|
||||
@ -127,7 +125,7 @@ void setup() {
|
||||
Serial.println(WiFi.localIP());
|
||||
Serial.println("Contacting Time Server");
|
||||
configTime(3600 * timezone, daysavetime * 3600, "time.nist.gov", "0.pool.ntp.org", "1.pool.ntp.org");
|
||||
struct tm tmstruct ;
|
||||
struct tm tmstruct;
|
||||
delay(2000);
|
||||
tmstruct.tm_year = 0;
|
||||
getLocalTime(&tmstruct, 5000);
|
||||
@ -158,9 +156,6 @@ void setup() {
|
||||
}
|
||||
readFile("/hello.txt");
|
||||
listDir("/");
|
||||
|
||||
|
||||
}
|
||||
|
||||
void loop() { }
|
||||
|
||||
void loop() {}
|
||||
|
@ -44,9 +44,7 @@ void DoTest(FS *fs) {
|
||||
}
|
||||
|
||||
uint8_t data[256];
|
||||
for (int i = 0; i < 256; i++) {
|
||||
data[i] = (uint8_t) i;
|
||||
}
|
||||
for (int i = 0; i < 256; i++) { data[i] = (uint8_t)i; }
|
||||
|
||||
Serial.printf("Creating %dKB file, may take a while...\n", TESTSIZEKB);
|
||||
unsigned long start = millis();
|
||||
@ -56,9 +54,7 @@ void DoTest(FS *fs) {
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < TESTSIZEKB; i++) {
|
||||
for (int j = 0; j < 4; j++) {
|
||||
f.write(data, 256);
|
||||
}
|
||||
for (int j = 0; j < 4; j++) { f.write(data, 256); }
|
||||
}
|
||||
f.close();
|
||||
unsigned long stop = millis();
|
||||
@ -72,9 +68,7 @@ void DoTest(FS *fs) {
|
||||
start = millis();
|
||||
f = fs->open("/testwrite.bin", "r");
|
||||
for (int i = 0; i < TESTSIZEKB; i++) {
|
||||
for (int j = 0; j < 4; j++) {
|
||||
f.read(data, 256);
|
||||
}
|
||||
for (int j = 0; j < 4; j++) { f.read(data, 256); }
|
||||
}
|
||||
f.close();
|
||||
stop = millis();
|
||||
@ -85,9 +79,7 @@ void DoTest(FS *fs) {
|
||||
f = fs->open("/testwrite.bin", "r");
|
||||
f.read();
|
||||
for (int i = 0; i < TESTSIZEKB; i++) {
|
||||
for (int j = 0; j < 4; j++) {
|
||||
f.read(data + 1, 256);
|
||||
}
|
||||
for (int j = 0; j < 4; j++) { f.read(data + 1, 256); }
|
||||
}
|
||||
f.close();
|
||||
stop = millis();
|
||||
@ -115,9 +107,7 @@ void DoTest(FS *fs) {
|
||||
Serial.printf("Writing 64K file in 1-byte chunks\n");
|
||||
start = millis();
|
||||
f = fs->open("/test1b.bin", "w");
|
||||
for (int i = 0; i < 65536; i++) {
|
||||
f.write((uint8_t*)&i, 1);
|
||||
}
|
||||
for (int i = 0; i < 65536; i++) { f.write((uint8_t *)&i, 1); }
|
||||
f.close();
|
||||
stop = millis();
|
||||
Serial.printf("==> Time to write 64KB in 1b chunks = %lu milliseconds = %s\n", stop - start, rate(start, stop, 65536));
|
||||
@ -127,7 +117,7 @@ void DoTest(FS *fs) {
|
||||
f = fs->open("/test1b.bin", "r");
|
||||
for (int i = 0; i < 65536; i++) {
|
||||
char c;
|
||||
f.read((uint8_t*)&c, 1);
|
||||
f.read((uint8_t *)&c, 1);
|
||||
}
|
||||
f.close();
|
||||
stop = millis();
|
||||
|
@ -12,7 +12,7 @@ using namespace NetCapture;
|
||||
|
||||
#ifndef STASSID
|
||||
#define STASSID "your-ssid"
|
||||
#define STAPSK "your-password"
|
||||
#define STAPSK "your-password"
|
||||
#endif
|
||||
|
||||
const char* ssid = STASSID;
|
||||
@ -20,43 +20,36 @@ const char* password = STAPSK;
|
||||
|
||||
Netdump nd;
|
||||
|
||||
//FS* filesystem = &SPIFFS;
|
||||
// FS* filesystem = &SPIFFS;
|
||||
FS* filesystem = &LittleFS;
|
||||
|
||||
ESP8266WebServer webServer(80); // Used for sending commands
|
||||
WiFiServer tcpServer(8000); // Used to show netcat option.
|
||||
File tracefile;
|
||||
ESP8266WebServer webServer(80); // Used for sending commands
|
||||
WiFiServer tcpServer(8000); // Used to show netcat option.
|
||||
File tracefile;
|
||||
|
||||
std::map<PacketType, int> packetCount;
|
||||
|
||||
enum class SerialOption : uint8_t {
|
||||
AllFull,
|
||||
LocalNone,
|
||||
HTTPChar
|
||||
};
|
||||
enum class SerialOption : uint8_t { AllFull,
|
||||
LocalNone,
|
||||
HTTPChar };
|
||||
|
||||
void startSerial(SerialOption option) {
|
||||
switch (option) {
|
||||
case SerialOption::AllFull : //All Packets, show packet summary.
|
||||
case SerialOption::AllFull: // All Packets, show packet summary.
|
||||
nd.printDump(Serial, Packet::PacketDetail::FULL);
|
||||
break;
|
||||
|
||||
case SerialOption::LocalNone : // Only local IP traffic, full details
|
||||
nd.printDump(Serial, Packet::PacketDetail::NONE,
|
||||
[](Packet n) {
|
||||
case SerialOption::LocalNone: // Only local IP traffic, full details
|
||||
nd.printDump(Serial, Packet::PacketDetail::NONE, [](Packet n) {
|
||||
return (n.hasIP(WiFi.localIP()));
|
||||
}
|
||||
);
|
||||
});
|
||||
break;
|
||||
case SerialOption::HTTPChar : // Only HTTP traffic, show packet content as chars
|
||||
nd.printDump(Serial, Packet::PacketDetail::CHAR,
|
||||
[](Packet n) {
|
||||
case SerialOption::HTTPChar: // Only HTTP traffic, show packet content as chars
|
||||
nd.printDump(Serial, Packet::PacketDetail::CHAR, [](Packet n) {
|
||||
return (n.isHTTP());
|
||||
}
|
||||
);
|
||||
});
|
||||
break;
|
||||
default :
|
||||
Serial.printf("No valid SerialOption provided\r\n");
|
||||
default: Serial.printf("No valid SerialOption provided\r\n");
|
||||
};
|
||||
}
|
||||
|
||||
@ -80,49 +73,39 @@ void setup(void) {
|
||||
|
||||
if (WiFi.waitForConnectResult() != WL_CONNECTED) {
|
||||
Serial.println("WiFi Failed, stopping sketch");
|
||||
while (1) {
|
||||
delay(1000);
|
||||
}
|
||||
while (1) { delay(1000); }
|
||||
}
|
||||
|
||||
if (!MDNS.begin("netdumphost")) {
|
||||
Serial.println("Error setting up MDNS responder!");
|
||||
}
|
||||
if (!MDNS.begin("netdumphost")) { Serial.println("Error setting up MDNS responder!"); }
|
||||
|
||||
filesystem->begin();
|
||||
|
||||
webServer.on("/list",
|
||||
[]() {
|
||||
webServer.on("/list", []() {
|
||||
Dir dir = filesystem->openDir("/");
|
||||
String d = "<h1>File list</h1>";
|
||||
while (dir.next()) {
|
||||
d.concat("<li>" + dir.fileName() + "</li>");
|
||||
}
|
||||
webServer.send(200, "text.html", d);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
webServer.on("/req",
|
||||
[]() {
|
||||
webServer.on("/req", []() {
|
||||
static int rq = 0;
|
||||
String a = "<h1>You are connected, Number of requests = " + String(rq++) + "</h1>";
|
||||
webServer.send(200, "text/html", a);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
webServer.on("/reset",
|
||||
[]() {
|
||||
webServer.on("/reset", []() {
|
||||
nd.reset();
|
||||
tracefile.close();
|
||||
tcpServer.close();
|
||||
webServer.send(200, "text.html", "<h1>Netdump session reset</h1>");
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
webServer.serveStatic("/", *filesystem, "/");
|
||||
webServer.begin();
|
||||
|
||||
startSerial(SerialOption::AllFull); // Serial output examples, use enum SerialOption for selection
|
||||
startSerial(SerialOption::AllFull); // Serial output examples, use enum SerialOption for selection
|
||||
|
||||
// startTcpDump(); // tcpdump option
|
||||
// startTracefile(); // output to SPIFFS or LittleFS
|
||||
@ -132,18 +115,18 @@ void setup(void) {
|
||||
nd.setCallback(
|
||||
[](Packet p)
|
||||
{
|
||||
Serial.printf("PKT : %s : ",p.sourceIP().toString().c_str());
|
||||
for ( auto pp : p.allPacketTypes())
|
||||
{
|
||||
Serial.printf("%s ",pp.toString().c_str());
|
||||
packetCount[pp]++;
|
||||
}
|
||||
Serial.printf("\r\n CNT ");
|
||||
for (auto pc : packetCount)
|
||||
{
|
||||
Serial.printf("%s %d ", pc.first.toString().c_str(),pc.second);
|
||||
}
|
||||
Serial.printf("\r\n");
|
||||
Serial.printf("PKT : %s : ",p.sourceIP().toString().c_str());
|
||||
for ( auto pp : p.allPacketTypes())
|
||||
{
|
||||
Serial.printf("%s ",pp.toString().c_str());
|
||||
packetCount[pp]++;
|
||||
}
|
||||
Serial.printf("\r\n CNT ");
|
||||
for (auto pc : packetCount)
|
||||
{
|
||||
Serial.printf("%s %d ", pc.first.toString().c_str(),pc.second);
|
||||
}
|
||||
Serial.printf("\r\n");
|
||||
}
|
||||
);
|
||||
*/
|
||||
@ -153,4 +136,3 @@ void loop(void) {
|
||||
webServer.handleClient();
|
||||
MDNS.update();
|
||||
}
|
||||
|
||||
|
@ -23,7 +23,6 @@
|
||||
#include <lwip/init.h>
|
||||
#include "Schedule.h"
|
||||
|
||||
|
||||
namespace NetCapture
|
||||
{
|
||||
|
||||
@ -69,24 +68,26 @@ void Netdump::reset()
|
||||
void Netdump::printDump(Print& out, Packet::PacketDetail ndd, const Filter nf)
|
||||
{
|
||||
out.printf_P(PSTR("netDump starting\r\n"));
|
||||
setCallback([&out, ndd, this](const Packet & ndp)
|
||||
{
|
||||
printDumpProcess(out, ndd, ndp);
|
||||
}, nf);
|
||||
setCallback(
|
||||
[&out, ndd, this](const Packet& ndp)
|
||||
{
|
||||
printDumpProcess(out, ndd, ndp);
|
||||
},
|
||||
nf);
|
||||
}
|
||||
|
||||
void Netdump::fileDump(File& outfile, const Filter nf)
|
||||
{
|
||||
|
||||
writePcapHeader(outfile);
|
||||
setCallback([&outfile, this](const Packet & ndp)
|
||||
{
|
||||
fileDumpProcess(outfile, ndp);
|
||||
}, nf);
|
||||
setCallback(
|
||||
[&outfile, this](const Packet& ndp)
|
||||
{
|
||||
fileDumpProcess(outfile, ndp);
|
||||
},
|
||||
nf);
|
||||
}
|
||||
bool Netdump::tcpDump(WiFiServer &tcpDumpServer, const Filter nf)
|
||||
bool Netdump::tcpDump(WiFiServer& tcpDumpServer, const Filter nf)
|
||||
{
|
||||
|
||||
if (!packetBuffer)
|
||||
{
|
||||
packetBuffer = new (std::nothrow) char[tcpBufferSize];
|
||||
@ -98,10 +99,11 @@ bool Netdump::tcpDump(WiFiServer &tcpDumpServer, const Filter nf)
|
||||
}
|
||||
bufferIndex = 0;
|
||||
|
||||
schedule_function([&tcpDumpServer, this, nf]()
|
||||
{
|
||||
tcpDumpLoop(tcpDumpServer, nf);
|
||||
});
|
||||
schedule_function(
|
||||
[&tcpDumpServer, this, nf]()
|
||||
{
|
||||
tcpDumpLoop(tcpDumpServer, nf);
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -109,7 +111,8 @@ void Netdump::capture(int netif_idx, const char* data, size_t len, int out, int
|
||||
{
|
||||
if (lwipCallback.execute(netif_idx, data, len, out, success) == 0)
|
||||
{
|
||||
phy_capture = nullptr; // No active callback/netdump instances, will be set again by new object.
|
||||
phy_capture
|
||||
= nullptr; // No active callback/netdump instances, will be set again by new object.
|
||||
}
|
||||
}
|
||||
|
||||
@ -118,7 +121,7 @@ void Netdump::netdumpCapture(int netif_idx, const char* data, size_t len, int ou
|
||||
if (netDumpCallback)
|
||||
{
|
||||
Packet np(millis(), netif_idx, data, len, out, success);
|
||||
if (netDumpFilter && !netDumpFilter(np))
|
||||
if (netDumpFilter && !netDumpFilter(np))
|
||||
{
|
||||
return;
|
||||
}
|
||||
@ -131,8 +134,8 @@ void Netdump::writePcapHeader(Stream& s) const
|
||||
uint32_t pcapHeader[6];
|
||||
pcapHeader[0] = 0xa1b2c3d4; // pcap magic number
|
||||
pcapHeader[1] = 0x00040002; // pcap major/minor version
|
||||
pcapHeader[2] = 0; // pcap UTC correction in seconds
|
||||
pcapHeader[3] = 0; // pcap time stamp accuracy
|
||||
pcapHeader[2] = 0; // pcap UTC correction in seconds
|
||||
pcapHeader[3] = 0; // pcap time stamp accuracy
|
||||
pcapHeader[4] = maxPcapLength; // pcap max packet length per record
|
||||
pcapHeader[5] = 1; // pacp data linkt type = ethernet
|
||||
s.write(reinterpret_cast<char*>(pcapHeader), 24);
|
||||
@ -145,7 +148,7 @@ void Netdump::printDumpProcess(Print& out, Packet::PacketDetail ndd, const Packe
|
||||
|
||||
void Netdump::fileDumpProcess(File& outfile, const Packet& np) const
|
||||
{
|
||||
size_t incl_len = np.getPacketSize() > maxPcapLength ? maxPcapLength : np.getPacketSize();
|
||||
size_t incl_len = np.getPacketSize() > maxPcapLength ? maxPcapLength : np.getPacketSize();
|
||||
uint32_t pcapHeader[4];
|
||||
|
||||
struct timeval tv;
|
||||
@ -154,7 +157,7 @@ void Netdump::fileDumpProcess(File& outfile, const Packet& np) const
|
||||
pcapHeader[1] = tv.tv_usec;
|
||||
pcapHeader[2] = incl_len;
|
||||
pcapHeader[3] = np.getPacketSize();
|
||||
outfile.write(reinterpret_cast<char*>(pcapHeader), 16); // pcap record header
|
||||
outfile.write(reinterpret_cast<char*>(pcapHeader), 16); // pcap record header
|
||||
|
||||
outfile.write(np.rawData(), incl_len);
|
||||
}
|
||||
@ -168,16 +171,16 @@ void Netdump::tcpDumpProcess(const Packet& np)
|
||||
}
|
||||
size_t incl_len = np.getPacketSize() > maxPcapLength ? maxPcapLength : np.getPacketSize();
|
||||
|
||||
if (bufferIndex + 16 + incl_len < tcpBufferSize) // only add if enough space available
|
||||
if (bufferIndex + 16 + incl_len < tcpBufferSize) // only add if enough space available
|
||||
{
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, nullptr);
|
||||
uint32_t* pcapHeader = reinterpret_cast<uint32_t*>(&packetBuffer[bufferIndex]);
|
||||
pcapHeader[0] = tv.tv_sec; // add pcap record header
|
||||
pcapHeader[1] = tv.tv_usec;
|
||||
pcapHeader[2] = incl_len;
|
||||
pcapHeader[3] = np.getPacketSize();
|
||||
bufferIndex += 16; // pcap header size
|
||||
pcapHeader[0] = tv.tv_sec; // add pcap record header
|
||||
pcapHeader[1] = tv.tv_usec;
|
||||
pcapHeader[2] = incl_len;
|
||||
pcapHeader[3] = np.getPacketSize();
|
||||
bufferIndex += 16; // pcap header size
|
||||
memcpy(&packetBuffer[bufferIndex], np.rawData(), incl_len);
|
||||
bufferIndex += incl_len;
|
||||
}
|
||||
@ -189,7 +192,7 @@ void Netdump::tcpDumpProcess(const Packet& np)
|
||||
}
|
||||
}
|
||||
|
||||
void Netdump::tcpDumpLoop(WiFiServer &tcpDumpServer, const Filter nf)
|
||||
void Netdump::tcpDumpLoop(WiFiServer& tcpDumpServer, const Filter nf)
|
||||
{
|
||||
if (tcpDumpServer.hasClient())
|
||||
{
|
||||
@ -199,10 +202,12 @@ void Netdump::tcpDumpLoop(WiFiServer &tcpDumpServer, const Filter nf)
|
||||
bufferIndex = 0;
|
||||
writePcapHeader(tcpDumpClient);
|
||||
|
||||
setCallback([this](const Packet & ndp)
|
||||
{
|
||||
tcpDumpProcess(ndp);
|
||||
}, nf);
|
||||
setCallback(
|
||||
[this](const Packet& ndp)
|
||||
{
|
||||
tcpDumpProcess(ndp);
|
||||
},
|
||||
nf);
|
||||
}
|
||||
if (!tcpDumpClient || !tcpDumpClient.connected())
|
||||
{
|
||||
@ -216,11 +221,12 @@ void Netdump::tcpDumpLoop(WiFiServer &tcpDumpServer, const Filter nf)
|
||||
|
||||
if (tcpDumpServer.status() != CLOSED)
|
||||
{
|
||||
schedule_function([&tcpDumpServer, this, nf]()
|
||||
{
|
||||
tcpDumpLoop(tcpDumpServer, nf);
|
||||
});
|
||||
schedule_function(
|
||||
[&tcpDumpServer, this, nf]()
|
||||
{
|
||||
tcpDumpLoop(tcpDumpServer, nf);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace NetCapture
|
||||
} // namespace NetCapture
|
||||
|
@ -38,9 +38,8 @@ using namespace experimental::CBListImplentation;
|
||||
class Netdump
|
||||
{
|
||||
public:
|
||||
|
||||
using Filter = std::function<bool(const Packet&)>;
|
||||
using Callback = std::function<void(const Packet&)>;
|
||||
using Filter = std::function<bool(const Packet&)>;
|
||||
using Callback = std::function<void(const Packet&)>;
|
||||
using LwipCallback = std::function<void(int, const char*, int, int, int)>;
|
||||
|
||||
Netdump();
|
||||
@ -53,15 +52,14 @@ public:
|
||||
|
||||
void printDump(Print& out, Packet::PacketDetail ndd, const Filter nf = nullptr);
|
||||
void fileDump(File& outfile, const Filter nf = nullptr);
|
||||
bool tcpDump(WiFiServer &tcpDumpServer, const Filter nf = nullptr);
|
||||
|
||||
bool tcpDump(WiFiServer& tcpDumpServer, const Filter nf = nullptr);
|
||||
|
||||
private:
|
||||
Callback netDumpCallback = nullptr;
|
||||
Filter netDumpFilter = nullptr;
|
||||
|
||||
static void capture(int netif_idx, const char* data, size_t len, int out, int success);
|
||||
static CallBackList<LwipCallback> lwipCallback;
|
||||
static CallBackList<LwipCallback> lwipCallback;
|
||||
CallBackList<LwipCallback>::CallBackHandler lwipHandler;
|
||||
|
||||
void netdumpCapture(int netif_idx, const char* data, size_t len, int out, int success);
|
||||
@ -69,19 +67,19 @@ private:
|
||||
void printDumpProcess(Print& out, Packet::PacketDetail ndd, const Packet& np) const;
|
||||
void fileDumpProcess(File& outfile, const Packet& np) const;
|
||||
void tcpDumpProcess(const Packet& np);
|
||||
void tcpDumpLoop(WiFiServer &tcpDumpServer, const Filter nf);
|
||||
void tcpDumpLoop(WiFiServer& tcpDumpServer, const Filter nf);
|
||||
|
||||
void writePcapHeader(Stream& s) const;
|
||||
|
||||
WiFiClient tcpDumpClient;
|
||||
char* packetBuffer = nullptr;
|
||||
int bufferIndex = 0;
|
||||
char* packetBuffer = nullptr;
|
||||
int bufferIndex = 0;
|
||||
|
||||
static constexpr int tcpBufferSize = 2048;
|
||||
static constexpr int maxPcapLength = 1024;
|
||||
static constexpr uint32_t pcapMagic = 0xa1b2c3d4;
|
||||
static constexpr int tcpBufferSize = 2048;
|
||||
static constexpr int maxPcapLength = 1024;
|
||||
static constexpr uint32_t pcapMagic = 0xa1b2c3d4;
|
||||
};
|
||||
|
||||
} // namespace NetCapture
|
||||
} // namespace NetCapture
|
||||
|
||||
#endif /* __NETDUMP_H */
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user