mirror of
https://github.com/esp8266/Arduino.git
synced 2025-04-21 10:26:06 +03:00
commit
5baed4061e
@ -45,13 +45,22 @@ typedef enum {
|
|||||||
#define cli() ets_intr_lock() // IRQ Disable
|
#define cli() ets_intr_lock() // IRQ Disable
|
||||||
#define sei() ets_intr_unlock() // IRQ Enable
|
#define sei() ets_intr_unlock() // IRQ Enable
|
||||||
|
|
||||||
enum WakeMode {
|
enum RFMode {
|
||||||
WAKE_RF_DEFAULT = 0, // RF_CAL or not after deep-sleep wake up, depends on init data byte 108.
|
RF_DEFAULT = 0, // RF_CAL or not after deep-sleep wake up, depends on init data byte 108.
|
||||||
WAKE_RFCAL = 1, // RF_CAL after deep-sleep wake up, there will be large current.
|
RF_CAL = 1, // RF_CAL after deep-sleep wake up, there will be large current.
|
||||||
WAKE_NO_RFCAL = 2, // no RF_CAL after deep-sleep wake up, there will only be small current.
|
RF_NO_CAL = 2, // no RF_CAL after deep-sleep wake up, there will only be small current.
|
||||||
WAKE_RF_DISABLED = 4 // disable RF after deep-sleep wake up, just like modem sleep, there will be the smallest current.
|
RF_DISABLED = 4 // disable RF after deep-sleep wake up, just like modem sleep, there will be the smallest current.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define RF_MODE(mode) extern "C" int __get_rf_mode() { return mode; }
|
||||||
|
|
||||||
|
// compatibility definitions
|
||||||
|
#define WakeMode RFMode
|
||||||
|
#define WAKE_RF_DEFAULT RF_DEFAULT
|
||||||
|
#define WAKE_RFCAL RF_CAL
|
||||||
|
#define WAKE_NO_RFCAL RF_NO_CAL
|
||||||
|
#define WAKE_RF_DISABLED RF_DISABLED
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
FM_QIO = 0x00,
|
FM_QIO = 0x00,
|
||||||
FM_QOUT = 0x01,
|
FM_QOUT = 0x01,
|
||||||
@ -72,7 +81,7 @@ class EspClass {
|
|||||||
void wdtDisable();
|
void wdtDisable();
|
||||||
void wdtFeed();
|
void wdtFeed();
|
||||||
|
|
||||||
void deepSleep(uint32_t time_us, WakeMode mode = WAKE_RF_DEFAULT);
|
void deepSleep(uint32_t time_us, RFMode mode = RF_DEFAULT);
|
||||||
|
|
||||||
void reset();
|
void reset();
|
||||||
void restart();
|
void restart();
|
||||||
|
@ -58,6 +58,14 @@ namespace std {
|
|||||||
void __throw_bad_function_call() {
|
void __throw_bad_function_call() {
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void __throw_length_error(char const*) {
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
void __throw_bad_alloc() {
|
||||||
|
abort();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: rebuild windows toolchain to make this unnecessary:
|
// TODO: rebuild windows toolchain to make this unnecessary:
|
||||||
|
@ -106,7 +106,7 @@ cont_resume:
|
|||||||
|
|
||||||
cont_norm:
|
cont_norm:
|
||||||
/* calculate pointer to cont_ctx.struct_start from sp */
|
/* calculate pointer to cont_ctx.struct_start from sp */
|
||||||
l32i a2, a1, 8
|
l32i a2, a1, 4
|
||||||
/* sp <- cont_ctx.sp_ret */
|
/* sp <- cont_ctx.sp_ret */
|
||||||
l32i a1, a2, 4
|
l32i a1, a2, 4
|
||||||
|
|
||||||
|
@ -33,6 +33,8 @@ typedef struct cont_ {
|
|||||||
unsigned* sp_yield;
|
unsigned* sp_yield;
|
||||||
|
|
||||||
unsigned* stack_end;
|
unsigned* stack_end;
|
||||||
|
unsigned unused1;
|
||||||
|
unsigned unused2;
|
||||||
unsigned stack_guard1;
|
unsigned stack_guard1;
|
||||||
|
|
||||||
unsigned stack[CONT_STACKSIZE / 4];
|
unsigned stack[CONT_STACKSIZE / 4];
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
void cont_init(cont_t* cont) {
|
void cont_init(cont_t* cont) {
|
||||||
cont->stack_guard1 = CONT_STACKGUARD;
|
cont->stack_guard1 = CONT_STACKGUARD;
|
||||||
cont->stack_guard2 = CONT_STACKGUARD;
|
cont->stack_guard2 = CONT_STACKGUARD;
|
||||||
cont->stack_end = cont->stack + (sizeof(cont->stack) / 4 - 1);
|
cont->stack_end = cont->stack + (sizeof(cont->stack) / 4);
|
||||||
cont->struct_start = (unsigned*) cont;
|
cont->struct_start = (unsigned*) cont;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,7 +59,7 @@ void preloop_update_frequency() {
|
|||||||
extern void (*__init_array_start)(void);
|
extern void (*__init_array_start)(void);
|
||||||
extern void (*__init_array_end)(void);
|
extern void (*__init_array_end)(void);
|
||||||
|
|
||||||
static cont_t g_cont;
|
cont_t g_cont __attribute__ ((aligned (16)));
|
||||||
static os_event_t g_loop_queue[LOOP_QUEUE_SIZE];
|
static os_event_t g_loop_queue[LOOP_QUEUE_SIZE];
|
||||||
|
|
||||||
static uint32_t g_micros_at_task_start;
|
static uint32_t g_micros_at_task_start;
|
||||||
@ -118,9 +118,15 @@ void init_done() {
|
|||||||
esp_schedule();
|
esp_schedule();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" int __get_rf_mode() __attribute__((weak));
|
||||||
|
extern "C" int __get_rf_mode()
|
||||||
|
{
|
||||||
|
return 0; // default mode
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
void user_rf_pre_init() {
|
void user_rf_pre_init() {
|
||||||
|
system_phy_set_rfoption(__get_rf_mode());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -129,9 +135,6 @@ void user_init(void) {
|
|||||||
uart_div_modify(0, UART_CLK_FREQ / (74480));
|
uart_div_modify(0, UART_CLK_FREQ / (74480));
|
||||||
|
|
||||||
system_rtc_mem_read(0, &resetInfo, sizeof(struct rst_info));
|
system_rtc_mem_read(0, &resetInfo, sizeof(struct rst_info));
|
||||||
if(resetInfo.reason == REASON_WDT_RST || resetInfo.reason == REASON_EXCEPTION_RST) {
|
|
||||||
os_printf("Last Reset:\n - flag=%d\n - Fatal exception (%d):\n - epc1=0x%08x,epc2=0x%08x,epc3=0x%08x,excvaddr=0x%08x,depc=0x%08x\n", resetInfo.reason, resetInfo.exccause, resetInfo.epc1, resetInfo.epc2, resetInfo.epc3, resetInfo.excvaddr, resetInfo.depc);
|
|
||||||
}
|
|
||||||
struct rst_info info = { 0 };
|
struct rst_info info = { 0 };
|
||||||
system_rtc_mem_write(0, &info, sizeof(struct rst_info));
|
system_rtc_mem_write(0, &info, sizeof(struct rst_info));
|
||||||
|
|
||||||
|
130
cores/esp8266/core_esp8266_postmortem.c
Normal file
130
cores/esp8266/core_esp8266_postmortem.c
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
/*
|
||||||
|
postmortem.c - output of debug info on sketch crash
|
||||||
|
Copyright (c) 2015 Ivan Grokhotkov. All rights reserved.
|
||||||
|
This file is part of the esp8266 core for Arduino environment.
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include "ets_sys.h"
|
||||||
|
#include "user_interface.h"
|
||||||
|
#include "esp8266_peri.h"
|
||||||
|
#include "cont.h"
|
||||||
|
|
||||||
|
extern void __real_system_restart_local();
|
||||||
|
extern cont_t g_cont;
|
||||||
|
|
||||||
|
static void uart0_write_char_d(char c);
|
||||||
|
static void print_stack(uint32_t start, uint32_t end);
|
||||||
|
static void print_pcs(uint32_t start, uint32_t end);
|
||||||
|
|
||||||
|
void __wrap_system_restart_local() {
|
||||||
|
register uint32_t sp asm("a1");
|
||||||
|
|
||||||
|
struct rst_info rst_info = {0};
|
||||||
|
system_rtc_mem_read(0, &rst_info, sizeof(rst_info));
|
||||||
|
if (rst_info.reason != REASON_SOFT_WDT_RST &&
|
||||||
|
rst_info.reason != REASON_EXCEPTION_RST &&
|
||||||
|
rst_info.reason != REASON_WDT_RST)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ets_install_putc1(&uart0_write_char_d);
|
||||||
|
|
||||||
|
if (rst_info.reason == REASON_EXCEPTION_RST) {
|
||||||
|
ets_printf("\nException (%d):\nepc1=0x%08x epc2=0x%08x epc3=0x%08x excvaddr=0x%08x depc=0x%08x\n",
|
||||||
|
rst_info.exccause, rst_info.epc1, rst_info.epc2, rst_info.epc3, rst_info.excvaddr, rst_info.depc);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t cont_stack_start = (uint32_t) &(g_cont.stack);
|
||||||
|
uint32_t cont_stack_end = (uint32_t) g_cont.stack_end;
|
||||||
|
uint32_t stack_end;
|
||||||
|
|
||||||
|
// amount of stack taken by interrupt or exception handler
|
||||||
|
// and everything up to __wrap_system_restart_local
|
||||||
|
// (determined empirically, might break)
|
||||||
|
uint32_t offset = 0;
|
||||||
|
if (rst_info.reason == REASON_SOFT_WDT_RST) {
|
||||||
|
offset = 0x1b0;
|
||||||
|
}
|
||||||
|
else if (rst_info.reason == REASON_EXCEPTION_RST) {
|
||||||
|
offset = 0x1a0;
|
||||||
|
}
|
||||||
|
else if (rst_info.reason == REASON_WDT_RST) {
|
||||||
|
offset = 0x10;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sp > cont_stack_start && sp < cont_stack_end) {
|
||||||
|
ets_printf("\nctx: cont \n");
|
||||||
|
stack_end = cont_stack_end;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ets_printf("\nctx: sys \n");
|
||||||
|
stack_end = 0x3fffffb0;
|
||||||
|
// it's actually 0x3ffffff0, but the stuff below ets_run
|
||||||
|
// is likely not really relevant to the crash
|
||||||
|
}
|
||||||
|
|
||||||
|
ets_printf("sp: %08x end: %08x offset: %04x\n", sp, stack_end, offset);
|
||||||
|
|
||||||
|
// print_pcs(sp + offset, stack_end);
|
||||||
|
print_stack(sp + offset, stack_end);
|
||||||
|
delayMicroseconds(10000);
|
||||||
|
__real_system_restart_local();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void print_stack(uint32_t start, uint32_t end) {
|
||||||
|
ets_printf("\n>>>stack>>>\n");
|
||||||
|
for (uint32_t pos = start; pos < end; pos += 0x10) {
|
||||||
|
uint32_t* values = (uint32_t*)(pos);
|
||||||
|
|
||||||
|
// rough indicator: stack frames usually have SP saved as the second word
|
||||||
|
bool looksLikeStackFrame = (values[2] == pos + 0x10);
|
||||||
|
|
||||||
|
ets_printf("%08x: %08x %08x %08x %08x %c\n",
|
||||||
|
pos, values[0], values[1], values[2], values[3], (looksLikeStackFrame)?'<':' ');
|
||||||
|
}
|
||||||
|
ets_printf("<<<stack<<<\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_pcs(uint32_t start, uint32_t end) {
|
||||||
|
uint32_t n = 0;
|
||||||
|
ets_printf("\n>>>pc>>>\n");
|
||||||
|
for (uint32_t pos = start; pos < end; pos += 16, ++n) {
|
||||||
|
uint32_t* sf = (uint32_t*) pos;
|
||||||
|
|
||||||
|
uint32_t pc_ret = sf[3];
|
||||||
|
uint32_t sp_ret = sf[2];
|
||||||
|
if (pc_ret < 0x40000000 || pc_ret > 0x40f00000 || sp_ret != pos + 16)
|
||||||
|
continue;
|
||||||
|
ets_printf("%08x\n", pc_ret);
|
||||||
|
}
|
||||||
|
ets_printf("<<<pc<<<\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void uart0_write_char_d(char c) {
|
||||||
|
while (((USS(0) >> USTXC) & 0xff) >= 0x7e) { }
|
||||||
|
|
||||||
|
if (c == '\n') {
|
||||||
|
USF(0) = '\r';
|
||||||
|
}
|
||||||
|
USF(0) = c;
|
||||||
|
}
|
@ -5,7 +5,10 @@
|
|||||||
// #define DEBUGV(...) ets_printf(__VA_ARGS__)
|
// #define DEBUGV(...) ets_printf(__VA_ARGS__)
|
||||||
#define DEBUGV(...)
|
#define DEBUGV(...)
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
void hexdump(uint8_t *mem, uint32_t len, uint8_t cols = 16);
|
void hexdump(uint8_t *mem, uint32_t len, uint8_t cols = 16);
|
||||||
|
#else
|
||||||
|
void hexdump(uint8_t *mem, uint32_t len, uint8_t cols);
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif//ARD_DEBUG_H
|
#endif//ARD_DEBUG_H
|
||||||
|
@ -36,6 +36,7 @@
|
|||||||
#include "osapi.h"
|
#include "osapi.h"
|
||||||
#include "mem.h"
|
#include "mem.h"
|
||||||
#include "user_interface.h"
|
#include "user_interface.h"
|
||||||
|
#include "debug.h"
|
||||||
|
|
||||||
void* malloc(size_t size) {
|
void* malloc(size_t size) {
|
||||||
size = ((size + 3) & ~((size_t)0x3));
|
size = ((size + 3) & ~((size_t)0x3));
|
||||||
@ -471,75 +472,7 @@ int isblank(int c) {
|
|||||||
static int errno_var = 0;
|
static int errno_var = 0;
|
||||||
|
|
||||||
int* ICACHE_FLASH_ATTR __errno(void) {
|
int* ICACHE_FLASH_ATTR __errno(void) {
|
||||||
os_printf("__errno is called last error: %d (not current)\n", errno_var);
|
DEBUGV("__errno is called last error: %d (not current)\n", errno_var);
|
||||||
return &errno_var;
|
return &errno_var;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ##########################################################################
|
|
||||||
// __ieee754 functions
|
|
||||||
// ##########################################################################
|
|
||||||
|
|
||||||
double ICACHE_FLASH_ATTR __ieee754_sinh(double x) {
|
|
||||||
return sinh(x);
|
|
||||||
}
|
|
||||||
|
|
||||||
double ICACHE_FLASH_ATTR __ieee754_hypot(double x, double y) {
|
|
||||||
return hypot(x, y);
|
|
||||||
}
|
|
||||||
|
|
||||||
float ICACHE_FLASH_ATTR __ieee754_hypotf(float x, float y) {
|
|
||||||
return hypotf(x, y);
|
|
||||||
}
|
|
||||||
|
|
||||||
float ICACHE_FLASH_ATTR __ieee754_logf(float x) {
|
|
||||||
return logf(x);
|
|
||||||
}
|
|
||||||
|
|
||||||
double ICACHE_FLASH_ATTR __ieee754_log10(double x) {
|
|
||||||
return log10(x);
|
|
||||||
}
|
|
||||||
|
|
||||||
double ICACHE_FLASH_ATTR __ieee754_exp(double x) {
|
|
||||||
return exp(x);
|
|
||||||
}
|
|
||||||
|
|
||||||
double ICACHE_FLASH_ATTR __ieee754_cosh(double x) {
|
|
||||||
return cosh(x);
|
|
||||||
}
|
|
||||||
|
|
||||||
float ICACHE_FLASH_ATTR __ieee754_expf(float x) {
|
|
||||||
return expf(x);
|
|
||||||
}
|
|
||||||
|
|
||||||
float ICACHE_FLASH_ATTR __ieee754_log10f(float x) {
|
|
||||||
return log10f(x);
|
|
||||||
}
|
|
||||||
|
|
||||||
double ICACHE_FLASH_ATTR __ieee754_atan2(double x, double y) {
|
|
||||||
return atan2(x, y);
|
|
||||||
}
|
|
||||||
|
|
||||||
float ICACHE_FLASH_ATTR __ieee754_sqrtf(float x) {
|
|
||||||
return sqrtf(x);
|
|
||||||
}
|
|
||||||
|
|
||||||
float ICACHE_FLASH_ATTR __ieee754_sinhf(float x) {
|
|
||||||
return sinhf(x);
|
|
||||||
}
|
|
||||||
|
|
||||||
double ICACHE_FLASH_ATTR __ieee754_log(double x) {
|
|
||||||
return log(x);
|
|
||||||
}
|
|
||||||
|
|
||||||
double ICACHE_FLASH_ATTR __ieee754_sqrt(double x) {
|
|
||||||
return sqrt(x);
|
|
||||||
}
|
|
||||||
|
|
||||||
float ICACHE_FLASH_ATTR __ieee754_coshf(float x) {
|
|
||||||
return coshf(x);
|
|
||||||
}
|
|
||||||
|
|
||||||
float ICACHE_FLASH_ATTR __ieee754_atan2f(float x, float y) {
|
|
||||||
return atan2f(x, y);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@ -55,9 +55,6 @@ void setup() {
|
|||||||
/* You can remove the password parameter if you want the AP to be open. */
|
/* You can remove the password parameter if you want the AP to be open. */
|
||||||
WiFi.softAP(ssid, password);
|
WiFi.softAP(ssid, password);
|
||||||
|
|
||||||
while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); }
|
|
||||||
|
|
||||||
Serial.println("done");
|
|
||||||
IPAddress myIP = WiFi.softAPIP();
|
IPAddress myIP = WiFi.softAPIP();
|
||||||
Serial.print("AP IP address: ");
|
Serial.print("AP IP address: ");
|
||||||
Serial.println(myIP);
|
Serial.println(myIP);
|
||||||
|
44
libraries/ESP8266WiFiMesh/examples/HelloMesh/HelloMesh.ino
Normal file
44
libraries/ESP8266WiFiMesh/examples/HelloMesh/HelloMesh.ino
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
#include <ESP8266WiFi.h>
|
||||||
|
#include <ESP8266WiFiMesh.h>
|
||||||
|
|
||||||
|
/* Create the mesh node object */
|
||||||
|
ESP8266WiFiMesh mesh_node = ESP8266WiFiMesh(ESP.getChipId(), manageRequest);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback for when other nodes send you data
|
||||||
|
*
|
||||||
|
* @request The string received from another node in the mesh
|
||||||
|
* @returns The string to send back to the other node
|
||||||
|
*/
|
||||||
|
String manageRequest(String request)
|
||||||
|
{
|
||||||
|
/* Print out received message */
|
||||||
|
Serial.print("received: ");
|
||||||
|
Serial.println(request);
|
||||||
|
|
||||||
|
/* return a string to send back */
|
||||||
|
return String("Hello world response.");
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
Serial.begin(115200);
|
||||||
|
delay(10);
|
||||||
|
|
||||||
|
Serial.println();
|
||||||
|
Serial.println();
|
||||||
|
Serial.println("Setting up mesh node...");
|
||||||
|
|
||||||
|
/* Initialise the mesh node */
|
||||||
|
mesh_node.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop()
|
||||||
|
{
|
||||||
|
/* Accept any incoming connections */
|
||||||
|
mesh_node.acceptRequest();
|
||||||
|
|
||||||
|
/* Scan for other nodes and send them a message */
|
||||||
|
mesh_node.attemptScan("Hello world request.");
|
||||||
|
delay(1000);
|
||||||
|
}
|
23
libraries/ESP8266WiFiMesh/keywords.txt
Normal file
23
libraries/ESP8266WiFiMesh/keywords.txt
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#######################################
|
||||||
|
# Syntax Coloring Map For ESP8266WiFiMesh
|
||||||
|
#######################################
|
||||||
|
|
||||||
|
#######################################
|
||||||
|
# Library (KEYWORD3)
|
||||||
|
#######################################
|
||||||
|
|
||||||
|
ESP8266WiFiMesh KEYWORD3
|
||||||
|
|
||||||
|
#######################################
|
||||||
|
# Datatypes (KEYWORD1)
|
||||||
|
#######################################
|
||||||
|
|
||||||
|
ESP8266WiFiMesh KEYWORD1
|
||||||
|
|
||||||
|
#######################################
|
||||||
|
# Methods and Functions (KEYWORD2)
|
||||||
|
#######################################
|
||||||
|
|
||||||
|
begin KEYWORD2
|
||||||
|
attemptScan KEYWORD2
|
||||||
|
acceptRequest KEYWORD2
|
9
libraries/ESP8266WiFiMesh/library.properties
Normal file
9
libraries/ESP8266WiFiMesh/library.properties
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
name=ESP8266WiFiMesh
|
||||||
|
version=1.0
|
||||||
|
author=Julian Fell
|
||||||
|
maintainer=
|
||||||
|
sentence=Mesh network library
|
||||||
|
paragraph=The library sets up a Mesh Node which acts as a router, creating a Mesh Network with other nodes.
|
||||||
|
category=Communication
|
||||||
|
url=
|
||||||
|
architectures=esp8266
|
168
libraries/ESP8266WiFiMesh/src/ESP8266WiFiMesh.cpp
Normal file
168
libraries/ESP8266WiFiMesh/src/ESP8266WiFiMesh.cpp
Normal file
@ -0,0 +1,168 @@
|
|||||||
|
/*
|
||||||
|
ESP8266WiFiMesh.cpp - Mesh network node
|
||||||
|
Sets up a Mesh Node which acts as a router, creating a Mesh Network with other nodes. All information
|
||||||
|
is passed in both directions, but it is up to the user what the data sent is and how it is dealt with.
|
||||||
|
|
||||||
|
Copyright (c) 2015 Julian Fell. All rights reserved.
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <ESP8266WiFi.h>
|
||||||
|
#include <WiFiClient.h>
|
||||||
|
#include <WiFiServer.h>
|
||||||
|
|
||||||
|
#include "ESP8266WiFiMesh.h"
|
||||||
|
|
||||||
|
#define SSID_PREFIX "Mesh_Node"
|
||||||
|
#define SERVER_IP_ADDR "192.168.4.1"
|
||||||
|
#define SERVER_PORT 4011
|
||||||
|
|
||||||
|
ESP8266WiFiMesh::ESP8266WiFiMesh(uint32_t chip_id, std::function<String(String)> handler)
|
||||||
|
: _server(SERVER_PORT)
|
||||||
|
{
|
||||||
|
_chip_id = chip_id;
|
||||||
|
_ssid = String( String( SSID_PREFIX ) + String( _chip_id ) );
|
||||||
|
_ssid_prefix = String( SSID_PREFIX );
|
||||||
|
_handler = handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ESP8266WiFiMesh::begin()
|
||||||
|
{
|
||||||
|
WiFi.mode(WIFI_AP_STA);
|
||||||
|
WiFi.softAP( _ssid.c_str() );
|
||||||
|
_server.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wait for a WiFiClient to connect
|
||||||
|
*
|
||||||
|
* @returns: True if the client is ready, false otherwise.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
bool ESP8266WiFiMesh::waitForClient(WiFiClient curr_client, int max_wait)
|
||||||
|
{
|
||||||
|
int wait = max_wait;
|
||||||
|
while(curr_client.connected() && !curr_client.available() && wait--)
|
||||||
|
delay(3);
|
||||||
|
|
||||||
|
/* Return false if the client isn't ready to communicate */
|
||||||
|
if (WiFi.status() == WL_DISCONNECTED || !curr_client.connected())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send the supplied message then read back the other node's response
|
||||||
|
* and pass that to the user-supplied handler.
|
||||||
|
*
|
||||||
|
* @target_ssid The name of the AP the other node has set up.
|
||||||
|
* @message The string to send to the node.
|
||||||
|
* @returns: True if the exchange was a succes, false otherwise.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
bool ESP8266WiFiMesh::exchangeInfo(String message, WiFiClient curr_client)
|
||||||
|
{
|
||||||
|
curr_client.println( message.c_str() );
|
||||||
|
|
||||||
|
if (!waitForClient(curr_client, 1000))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
String response = curr_client.readStringUntil('\r');
|
||||||
|
curr_client.readStringUntil('\n');
|
||||||
|
|
||||||
|
if (response.length() <= 2)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/* Pass data to user callback */
|
||||||
|
_handler(response);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Connect to the AP at ssid, send them a message then disconnect.
|
||||||
|
*
|
||||||
|
* @target_ssid The name of the AP the other node has set up.
|
||||||
|
* @message The string to send to the node.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void WiFiMesh::connectToNode(String target_ssid, String message)
|
||||||
|
{
|
||||||
|
WiFiClient curr_client;
|
||||||
|
WiFi.begin( target_ssid.c_str() );
|
||||||
|
|
||||||
|
int wait = 1500;
|
||||||
|
while((WiFi.status() == WL_DISCONNECTED) && wait--)
|
||||||
|
delay(3);
|
||||||
|
|
||||||
|
/* If the connection timed out */
|
||||||
|
if (WiFi.status() != 3)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Connect to the node's server */
|
||||||
|
if (!curr_client.connect(SERVER_IP_ADDR, SERVER_PORT))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!exchangeInfo(message, curr_client))
|
||||||
|
return;
|
||||||
|
|
||||||
|
curr_client.stop();
|
||||||
|
WiFi.disconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ESP8266WiFiMesh::attemptScan(String message)
|
||||||
|
{
|
||||||
|
/* Scan for APs */
|
||||||
|
int n = WiFi.scanNetworks();
|
||||||
|
|
||||||
|
for (int i = 0; i < n; ++i) {
|
||||||
|
String current_ssid = WiFi.SSID(i);
|
||||||
|
int index = current_ssid.indexOf( _ssid_prefix );
|
||||||
|
uint32_t target_chip_id = (current_ssid.substring(index + _ssid_prefix.length())).toInt();
|
||||||
|
|
||||||
|
/* Connect to any _suitable_ APs which contain _ssid_prefix */
|
||||||
|
if (index >= 0 && (target_chip_id < _chip_id)) {
|
||||||
|
|
||||||
|
WiFi.mode(WIFI_STA);
|
||||||
|
delay(100);
|
||||||
|
connectToNode(current_ssid, message);
|
||||||
|
WiFi.mode(WIFI_AP_STA);
|
||||||
|
delay(100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ESP8266WiFiMesh::acceptRequest()
|
||||||
|
{
|
||||||
|
while (true) {
|
||||||
|
_client = _server.available();
|
||||||
|
if (!_client)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (!waitForClient(_client, 1500)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read in request and pass it to the supplied handler */
|
||||||
|
String request = _client.readStringUntil('\r');
|
||||||
|
_client.readStringUntil('\n');
|
||||||
|
|
||||||
|
String response = _handler(request);
|
||||||
|
|
||||||
|
/* Send the response back to the client */
|
||||||
|
if (_client.connected())
|
||||||
|
_client.println(response);
|
||||||
|
}
|
||||||
|
}
|
75
libraries/ESP8266WiFiMesh/src/ESP8266WiFiMesh.h
Normal file
75
libraries/ESP8266WiFiMesh/src/ESP8266WiFiMesh.h
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
/*
|
||||||
|
ESP8266WiFiMesh.h - Mesh network node
|
||||||
|
Sets up a Mesh Node which acts as a router, creating a Mesh Network with other nodes. All information
|
||||||
|
is passed in both directions, but it is up to the user what the data sent is and how it is dealt with.
|
||||||
|
|
||||||
|
Copyright (c) 2015 Julian Fell. All rights reserved.
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __WIFIMESH_H__
|
||||||
|
#define __WIFIMESH_H__
|
||||||
|
|
||||||
|
#include <WiFiClient.h>
|
||||||
|
#include <WiFiServer.h>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
class ESP8266WiFiMesh {
|
||||||
|
|
||||||
|
private:
|
||||||
|
String _ssid;
|
||||||
|
String _ssid_prefix;
|
||||||
|
uint32_t _chip_id;
|
||||||
|
|
||||||
|
std::function<String(String)> _handler;
|
||||||
|
|
||||||
|
WiFiServer _server;
|
||||||
|
WiFiClient _client;
|
||||||
|
|
||||||
|
void connectToNode(String target_ssid, String message);
|
||||||
|
bool exchangeInfo(String message, WiFiClient curr_client);
|
||||||
|
bool waitForClient(WiFiClient curr_client, int max_wait);
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* WiFiMesh Constructor method. Creates a WiFi Mesh Node, ready to be initialised.
|
||||||
|
*
|
||||||
|
* @chip_id A unique identifier number for the node.
|
||||||
|
* @handler The callback handler for dealing with received messages. Takes a string as an argument which
|
||||||
|
* is the string received from another node and returns the string to send back.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
ESP8266WiFiMesh(uint32_t chip_id, std::function<String(String)> handler);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialises the node.
|
||||||
|
*/
|
||||||
|
void begin();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scan for other nodes, and exchange the chosen message with any that are found.
|
||||||
|
*
|
||||||
|
* @message The message to send to all other nodes.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void attemptScan(String message);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If any clients are connected, accept their requests and call the hander function for each one.
|
||||||
|
*/
|
||||||
|
void acceptRequest();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
@ -16,17 +16,17 @@ compiler.sdk.path={runtime.platform.path}/tools/sdk/
|
|||||||
compiler.cpreprocessor.flags=-D__ets__ -DICACHE_FLASH -U__STRICT_ANSI__ "-I{compiler.sdk.path}/include"
|
compiler.cpreprocessor.flags=-D__ets__ -DICACHE_FLASH -U__STRICT_ANSI__ "-I{compiler.sdk.path}/include"
|
||||||
|
|
||||||
compiler.c.cmd=xtensa-lx106-elf-gcc
|
compiler.c.cmd=xtensa-lx106-elf-gcc
|
||||||
compiler.c.flags=-c -Os -Wpointer-arith -Wno-implicit-function-declaration -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -mtext-section-literals -falign-functions=4 -MMD -std=c99 -pedantic
|
compiler.c.flags=-c -Os -g -Wpointer-arith -Wno-implicit-function-declaration -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -mtext-section-literals -falign-functions=4 -MMD -std=gnu99
|
||||||
|
|
||||||
compiler.S.cmd=xtensa-lx106-elf-gcc
|
compiler.S.cmd=xtensa-lx106-elf-gcc
|
||||||
compiler.S.flags=-c -g -x assembler-with-cpp -MMD
|
compiler.S.flags=-c -g -x assembler-with-cpp -MMD
|
||||||
|
|
||||||
compiler.c.elf.flags=-nostdlib -Wl,--no-check-sections -u call_user_start -Wl,-static "-L{compiler.sdk.path}/lib" "-L{compiler.sdk.path}/ld" "-T{build.flash_ld}"
|
compiler.c.elf.flags=-g -Os -nostdlib -Wl,--no-check-sections -u call_user_start -Wl,-static "-L{compiler.sdk.path}/lib" "-L{compiler.sdk.path}/ld" "-T{build.flash_ld}" -Wl,-wrap,system_restart_local
|
||||||
compiler.c.elf.cmd=xtensa-lx106-elf-gcc
|
compiler.c.elf.cmd=xtensa-lx106-elf-gcc
|
||||||
compiler.c.elf.libs=-lm -lgcc -lhal -lphy -lnet80211 -llwip -lwpa -lmain -lpp -lsmartconfig
|
compiler.c.elf.libs=-lm -lgcc -lhal -lphy -lnet80211 -llwip -lwpa -lmain -lpp -lsmartconfig
|
||||||
|
|
||||||
compiler.cpp.cmd=xtensa-lx106-elf-g++
|
compiler.cpp.cmd=xtensa-lx106-elf-g++
|
||||||
compiler.cpp.flags=-c -Os -mlongcalls -mtext-section-literals -fno-exceptions -fno-rtti -falign-functions=4 -std=c++11 -MMD -pedantic
|
compiler.cpp.flags=-c -Os -g -mlongcalls -mtext-section-literals -fno-exceptions -fno-rtti -falign-functions=4 -std=c++11 -MMD
|
||||||
|
|
||||||
compiler.as.cmd=xtensa-lx106-elf-as
|
compiler.as.cmd=xtensa-lx106-elf-as
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user