forked from espressif/arduino-esp32
Major IDF and Arduino Update
WiFi and BlueTooth can now be started and stopped at will. basic functions added to esp32-hal to start and stop the BT radio SimpleBLE class added to show the most basic functionality Example to show how to switch between BT, WiFi or Both
This commit is contained in:
@ -0,0 +1,47 @@
|
||||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Sketch shows how SimpleBLE to advertise the name of the device and change it on button press
|
||||
// Usefull if you want to advertise some short message
|
||||
// Button is attached between GPIO 0 and GND and modes are switched with each press
|
||||
|
||||
#include "SimpleBLE.h"
|
||||
SimpleBLE ble;
|
||||
|
||||
void onButton(){
|
||||
String out = "BLE32 at: ";
|
||||
out += String(millis() / 1000);
|
||||
Serial.println(out);
|
||||
ble.begin(out);
|
||||
}
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
Serial.setDebugOutput(true);
|
||||
pinMode(0, INPUT_PULLUP);
|
||||
Serial.print("ESP32 SDK: ");
|
||||
Serial.println(ESP.getSdkVersion());
|
||||
ble.begin("ESP32 SimpleBLE");
|
||||
Serial.println("Press the button to change the device name");
|
||||
}
|
||||
|
||||
void loop() {
|
||||
static uint8_t lastPinState = 1;
|
||||
uint8_t pinState = digitalRead(0);
|
||||
if(!pinState && lastPinState){
|
||||
onButton();
|
||||
}
|
||||
lastPinState = pinState;
|
||||
while(Serial.available()) Serial.write(Serial.read());
|
||||
}
|
9
libraries/SimpleBLE/library.properties
Normal file
9
libraries/SimpleBLE/library.properties
Normal file
@ -0,0 +1,9 @@
|
||||
name=SimpleBLE
|
||||
version=1.0
|
||||
author=Hristo Gochkov
|
||||
maintainer=Hristo Gochkov <hristo@espressif.com>
|
||||
sentence=Provides really simple BLE advertizer with just on and off
|
||||
paragraph=
|
||||
category=Communication
|
||||
url=
|
||||
architectures=esp32
|
338
libraries/SimpleBLE/src/SimpleBLE.cpp
Normal file
338
libraries/SimpleBLE/src/SimpleBLE.cpp
Normal file
@ -0,0 +1,338 @@
|
||||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "SimpleBLE.h"
|
||||
#include "esp32-hal-log.h"
|
||||
|
||||
/* HCI Command opcode group field(OGF) */
|
||||
#define HCI_GRP_HOST_CONT_BASEBAND_CMDS (0x03 << 10) /* 0x0C00 */
|
||||
#define HCI_GRP_BLE_CMDS (0x08 << 10)
|
||||
|
||||
/* HCI Command opcode command field(OCF) */
|
||||
#define HCI_RESET (0x0003 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
|
||||
#define HCI_BLE_WRITE_ADV_ENABLE (0x000A | HCI_GRP_BLE_CMDS)
|
||||
#define HCI_BLE_WRITE_ADV_PARAMS (0x0006 | HCI_GRP_BLE_CMDS)
|
||||
#define HCI_BLE_WRITE_ADV_DATA (0x0008 | HCI_GRP_BLE_CMDS)
|
||||
|
||||
#define HCI_H4_CMD_PREAMBLE_SIZE (4)
|
||||
#define HCIC_PARAM_SIZE_WRITE_ADV_ENABLE (1)
|
||||
#define HCIC_PARAM_SIZE_BLE_WRITE_ADV_PARAMS (15)
|
||||
#define HCIC_PARAM_SIZE_BLE_WRITE_ADV_DATA (31)
|
||||
|
||||
/* EIR/AD data type definitions */
|
||||
#define BT_DATA_FLAGS 0x01 /* AD flags */
|
||||
#define BT_DATA_UUID16_SOME 0x02 /* 16-bit UUID, more available */
|
||||
#define BT_DATA_UUID16_ALL 0x03 /* 16-bit UUID, all listed */
|
||||
#define BT_DATA_UUID32_SOME 0x04 /* 32-bit UUID, more available */
|
||||
#define BT_DATA_UUID32_ALL 0x05 /* 32-bit UUID, all listed */
|
||||
#define BT_DATA_UUID128_SOME 0x06 /* 128-bit UUID, more available */
|
||||
#define BT_DATA_UUID128_ALL 0x07 /* 128-bit UUID, all listed */
|
||||
#define BT_DATA_NAME_SHORTENED 0x08 /* Shortened name */
|
||||
#define BT_DATA_NAME_COMPLETE 0x09 /* Complete name */
|
||||
#define BT_DATA_TX_POWER 0x0a /* Tx Power */
|
||||
#define BT_DATA_SOLICIT16 0x14 /* Solicit UUIDs, 16-bit */
|
||||
#define BT_DATA_SOLICIT128 0x15 /* Solicit UUIDs, 128-bit */
|
||||
#define BT_DATA_SVC_DATA16 0x16 /* Service data, 16-bit UUID */
|
||||
#define BT_DATA_GAP_APPEARANCE 0x19 /* GAP appearance */
|
||||
#define BT_DATA_SOLICIT32 0x1f /* Solicit UUIDs, 32-bit */
|
||||
#define BT_DATA_SVC_DATA32 0x20 /* Service data, 32-bit UUID */
|
||||
#define BT_DATA_SVC_DATA128 0x21 /* Service data, 128-bit UUID */
|
||||
#define BT_DATA_MANUFACTURER_DATA 0xff /* Manufacturer Specific Data */
|
||||
|
||||
|
||||
/* Advertising types */
|
||||
#define BLE_GAP_ADV_TYPE_ADV_IND 0x00
|
||||
#define BLE_GAP_ADV_TYPE_ADV_DIRECT_IND 0x01
|
||||
#define BLE_GAP_ADV_TYPE_ADV_SCAN_IND 0x02
|
||||
#define BLE_GAP_ADV_TYPE_ADV_NONCONN_IND 0x03
|
||||
|
||||
|
||||
/* Advertising Discovery Flags */
|
||||
#define BLE_GAP_ADV_FLAG_LE_LIMITED_DISC_MODE (0x01)
|
||||
#define BLE_GAP_ADV_FLAG_LE_GENERAL_DISC_MODE (0x02)
|
||||
#define BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED (0x04)
|
||||
#define BLE_GAP_ADV_FLAG_LE_BR_EDR_CONTROLLER (0x08)
|
||||
#define BLE_GAP_ADV_FLAG_LE_BR_EDR_HOST (0x10)
|
||||
#define BLE_GAP_ADV_FLAGS_LE_ONLY_LIMITED_DISC_MODE (BLE_GAP_ADV_FLAG_LE_LIMITED_DISC_MODE | BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED)
|
||||
#define BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE (BLE_GAP_ADV_FLAG_LE_GENERAL_DISC_MODE | BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED)
|
||||
|
||||
|
||||
/* Advertising Filter Policies */
|
||||
#define BLE_GAP_ADV_FP_ANY 0x00
|
||||
#define BLE_GAP_ADV_FP_FILTER_SCANREQ 0x01
|
||||
#define BLE_GAP_ADV_FP_FILTER_CONNREQ 0x02
|
||||
#define BLE_GAP_ADV_FP_FILTER_BOTH 0x03
|
||||
|
||||
|
||||
/* Advertising Device Address Types */
|
||||
#define BLE_GAP_ADDR_TYPE_PUBLIC 0x00
|
||||
#define BLE_GAP_ADDR_TYPE_RANDOM_STATIC 0x01
|
||||
#define BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE 0x02
|
||||
#define BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE 0x03
|
||||
|
||||
|
||||
/* GAP Advertising Channel Maps */
|
||||
#define GAP_ADVCHAN_37 0x01
|
||||
#define GAP_ADVCHAN_38 0x02
|
||||
#define GAP_ADVCHAN_39 0x04
|
||||
#define GAP_ADVCHAN_ALL GAP_ADVCHAN_37 | GAP_ADVCHAN_38 | GAP_ADVCHAN_39
|
||||
|
||||
|
||||
/* GAP Filter Policies */
|
||||
#define BLE_GAP_ADV_FP_ANY 0x00
|
||||
#define BLE_GAP_ADV_FP_FILTER_SCANREQ 0x01
|
||||
#define BLE_GAP_ADV_FP_FILTER_CONNREQ 0x02
|
||||
#define BLE_GAP_ADV_FP_FILTER_BOTH 0x03
|
||||
|
||||
#define BD_ADDR_LEN (6) /* Device address length */
|
||||
|
||||
|
||||
/*
|
||||
* BLE System
|
||||
*
|
||||
* */
|
||||
|
||||
/* HCI H4 message type definitions */
|
||||
enum {
|
||||
H4_TYPE_COMMAND = 1,
|
||||
H4_TYPE_ACL = 2,
|
||||
H4_TYPE_SCO = 3,
|
||||
H4_TYPE_EVENT = 4
|
||||
};
|
||||
|
||||
volatile bool _vhci_host_send_available = false;
|
||||
volatile bool _vhci_host_command_running = false;
|
||||
static uint16_t _vhci_host_command = 0x0000;
|
||||
static uint8_t _vhci_host_command_result = 0x00;
|
||||
|
||||
//controller is ready to receive command
|
||||
static void _on_tx_ready(void)
|
||||
{
|
||||
_vhci_host_send_available = true;
|
||||
}
|
||||
/*
|
||||
static void _dump_buf(const char * txt, uint8_t *data, uint16_t len){
|
||||
log_printf("%s[%u]:", txt, len);
|
||||
for (uint16_t i=0; i<len; i++)
|
||||
log_printf(" %02x", data[i]);
|
||||
log_printf("\n");
|
||||
}
|
||||
*/
|
||||
//controller has a packet
|
||||
static int _on_rx_data(uint8_t *data, uint16_t len)
|
||||
{
|
||||
if(len == 7 && *data == 0x04){
|
||||
//baseband response
|
||||
uint16_t cmd = (((uint16_t)data[5] << 8) | data[4]);
|
||||
uint8_t res = data[6];
|
||||
if(_vhci_host_command_running && _vhci_host_command == cmd){
|
||||
//_dump_buf("BLE: res", data, len);
|
||||
_vhci_host_command_result = res;
|
||||
_vhci_host_command_running = false;
|
||||
return 0;
|
||||
} else if(cmd == 0){
|
||||
log_e("error %u", res);
|
||||
}
|
||||
}
|
||||
|
||||
//_dump_buf("BLE: rx", data, len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static esp_vhci_host_callback_t vhci_host_cb = {
|
||||
_on_tx_ready,
|
||||
_on_rx_data
|
||||
};
|
||||
|
||||
static bool _esp_ble_start()
|
||||
{
|
||||
if(btStart()){
|
||||
esp_vhci_host_register_callback(&vhci_host_cb);
|
||||
uint8_t i = 0;
|
||||
while(!esp_vhci_host_check_send_available() && i++ < 100){
|
||||
delay(10);
|
||||
}
|
||||
if(i >= 100){
|
||||
log_e("esp_vhci_host_check_send_available failed");
|
||||
return false;
|
||||
}
|
||||
_vhci_host_send_available = true;
|
||||
} else
|
||||
log_e("BT Failed");
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _esp_ble_stop()
|
||||
{
|
||||
if(btStarted()){
|
||||
_vhci_host_send_available = false;
|
||||
btStop();
|
||||
esp_vhci_host_register_callback(NULL);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//public
|
||||
|
||||
static uint8_t ble_send_cmd(uint16_t cmd, uint8_t * data, uint8_t len){
|
||||
static uint8_t buf[36];
|
||||
if(len > 32){
|
||||
//too much data
|
||||
return 2;
|
||||
}
|
||||
uint16_t i = 0;
|
||||
while(!_vhci_host_send_available && i++ < 1000){
|
||||
delay(1);
|
||||
}
|
||||
if(i >= 1000){
|
||||
log_e("_vhci_host_send_available failed");
|
||||
return 1;
|
||||
}
|
||||
uint8_t outlen = len + HCI_H4_CMD_PREAMBLE_SIZE;
|
||||
buf[0] = H4_TYPE_COMMAND;
|
||||
buf[1] = (uint8_t)(cmd & 0xFF);
|
||||
buf[2] = (uint8_t)(cmd >> 8);
|
||||
buf[3] = len;
|
||||
if(len){
|
||||
memcpy(buf+4, data, len);
|
||||
}
|
||||
_vhci_host_send_available = false;
|
||||
_vhci_host_command_running = true;
|
||||
_vhci_host_command = cmd;
|
||||
|
||||
//log_printf("BLE: cmd: 0x%04X, data[%u]:", cmd, len);
|
||||
//for (uint16_t i=0; i<len; i++) log_printf(" %02x", buf[i+4]);
|
||||
//log_printf("\n");
|
||||
|
||||
esp_vhci_host_send_packet(buf, outlen);
|
||||
while(_vhci_host_command_running);
|
||||
int res = _vhci_host_command_result;
|
||||
//log_printf("BLE: cmd: 0x%04X, res: %u\n", cmd, res);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* BLE Arduino
|
||||
*
|
||||
* */
|
||||
|
||||
enum {
|
||||
UNIT_0_625_MS = 625, /* Number of microseconds in 0.625 milliseconds. */
|
||||
UNIT_1_25_MS = 1250, /* Number of microseconds in 1.25 milliseconds. */
|
||||
UNIT_10_MS = 10000 /* Number of microseconds in 10 milliseconds. */
|
||||
};
|
||||
|
||||
/* BLE Advertising parameters struct */
|
||||
typedef struct ble_gap_adv_params_s {
|
||||
uint8_t type;
|
||||
uint8_t own_addr_type;
|
||||
uint8_t addr_type;
|
||||
uint8_t addr[BD_ADDR_LEN];
|
||||
uint8_t fp; // filter policy
|
||||
uint16_t interval_min; // minimum advertising interval between 0x0020 and 0x4000 in 0.625 ms units (20ms to 10.24s)
|
||||
uint16_t interval_max;
|
||||
uint8_t chn_map;
|
||||
} ble_adv_params_t;
|
||||
|
||||
#define MSEC_TO_UNITS(TIME, RESOLUTION) (((TIME) * 1000) / (RESOLUTION))
|
||||
#define UINT16_TO_STREAM(p, u16) {*(p)++ = (uint8_t)(u16); *(p)++ = (uint8_t)((u16) >> 8);}
|
||||
#define UINT8_TO_STREAM(p, u8) {*(p)++ = (uint8_t)(u8);}
|
||||
#define BDADDR_TO_STREAM(p, a) {int i; for (i = 0; i < BD_ADDR_LEN; i++) *(p)++ = (uint8_t) a[BD_ADDR_LEN - 1 - i];}
|
||||
#define ARRAY_TO_STREAM(p, a, len) {int i; for (i = 0; i < len; i++) *(p)++ = (uint8_t) a[i];}
|
||||
|
||||
SimpleBLE::SimpleBLE()
|
||||
{
|
||||
uint8_t peerAddr[BD_ADDR_LEN] = {0x80, 0x81, 0x82, 0x83, 0x84, 0x85};
|
||||
_ble_adv_param = (ble_adv_params_t*)malloc(sizeof(ble_adv_params_t));
|
||||
memset(_ble_adv_param, 0x00, sizeof(ble_adv_params_t));
|
||||
_ble_adv_param->type = BLE_GAP_ADV_TYPE_ADV_NONCONN_IND;//not connectable
|
||||
_ble_adv_param->chn_map = GAP_ADVCHAN_ALL; // 37, 38, 39 channels
|
||||
_ble_adv_param->fp = 0;//any
|
||||
_ble_adv_param->interval_min = 512;
|
||||
_ble_adv_param->interval_max = 1024;
|
||||
_ble_adv_param->addr_type = 0;//public
|
||||
memcpy(_ble_adv_param->addr, peerAddr, BD_ADDR_LEN);
|
||||
local_name = "esp32";
|
||||
}
|
||||
|
||||
SimpleBLE::~SimpleBLE(void)
|
||||
{
|
||||
free(_ble_adv_param);
|
||||
_esp_ble_stop();
|
||||
}
|
||||
|
||||
bool SimpleBLE::begin(String localName)
|
||||
{
|
||||
if(!_esp_ble_start()){
|
||||
return false;
|
||||
}
|
||||
ble_send_cmd(HCI_RESET, NULL, 0);
|
||||
if(localName.length()){
|
||||
local_name = localName;
|
||||
}
|
||||
_ble_send_adv_param();
|
||||
_ble_send_adv_data();
|
||||
|
||||
uint8_t adv_enable = 1;
|
||||
ble_send_cmd(HCI_BLE_WRITE_ADV_ENABLE, &adv_enable, HCIC_PARAM_SIZE_WRITE_ADV_ENABLE);
|
||||
return true;
|
||||
}
|
||||
|
||||
void SimpleBLE::end()
|
||||
{
|
||||
uint8_t adv_enable = 0;
|
||||
ble_send_cmd(HCI_BLE_WRITE_ADV_ENABLE, &adv_enable, HCIC_PARAM_SIZE_WRITE_ADV_ENABLE);
|
||||
ble_send_cmd(HCI_RESET, NULL, 0);
|
||||
_esp_ble_stop();
|
||||
}
|
||||
|
||||
void SimpleBLE::_ble_send_adv_param(void)
|
||||
{
|
||||
uint8_t dbuf[HCIC_PARAM_SIZE_BLE_WRITE_ADV_PARAMS];
|
||||
uint8_t *buf = dbuf;
|
||||
UINT16_TO_STREAM (buf, _ble_adv_param->interval_min);
|
||||
UINT16_TO_STREAM (buf, _ble_adv_param->interval_max);
|
||||
UINT8_TO_STREAM (buf, _ble_adv_param->type);
|
||||
UINT8_TO_STREAM (buf, _ble_adv_param->own_addr_type);
|
||||
UINT8_TO_STREAM (buf, _ble_adv_param->addr_type);
|
||||
ARRAY_TO_STREAM (buf, _ble_adv_param->addr, BD_ADDR_LEN);
|
||||
UINT8_TO_STREAM (buf, _ble_adv_param->chn_map);
|
||||
UINT8_TO_STREAM (buf, _ble_adv_param->fp);
|
||||
ble_send_cmd(HCI_BLE_WRITE_ADV_PARAMS, dbuf, HCIC_PARAM_SIZE_BLE_WRITE_ADV_PARAMS);
|
||||
}
|
||||
|
||||
void SimpleBLE::_ble_send_adv_data(void)
|
||||
{
|
||||
uint8_t adv_data[HCIC_PARAM_SIZE_BLE_WRITE_ADV_DATA + 1] = {
|
||||
0x03, 0x02, BT_DATA_FLAGS, BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE
|
||||
};
|
||||
//zerofill the buffer
|
||||
memset(adv_data+4, 0x00, HCIC_PARAM_SIZE_BLE_WRITE_ADV_DATA-4);
|
||||
uint8_t adv_data_len = 4;
|
||||
|
||||
// Advertising data device local name
|
||||
uint8_t name_len = (uint8_t) local_name.length();
|
||||
adv_data[adv_data_len++] = name_len + 1;
|
||||
adv_data[adv_data_len++] = BT_DATA_NAME_COMPLETE;
|
||||
for (int i=0; i<name_len; i++) {
|
||||
adv_data[adv_data_len++] = (uint8_t) local_name.charAt(i);
|
||||
}
|
||||
//send data
|
||||
adv_data[0] = adv_data_len - 1;
|
||||
ble_send_cmd(HCI_BLE_WRITE_ADV_DATA, (uint8_t *)adv_data, HCIC_PARAM_SIZE_BLE_WRITE_ADV_DATA + 1);
|
||||
}
|
63
libraries/SimpleBLE/src/SimpleBLE.h
Normal file
63
libraries/SimpleBLE/src/SimpleBLE.h
Normal file
@ -0,0 +1,63 @@
|
||||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef _SIMPLE_BLE_H_
|
||||
#define _SIMPLE_BLE_H_
|
||||
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "bt.h"
|
||||
|
||||
#include "Arduino.h"
|
||||
|
||||
struct ble_gap_adv_params_s;
|
||||
|
||||
class SimpleBLE {
|
||||
public:
|
||||
|
||||
SimpleBLE(void);
|
||||
~SimpleBLE(void);
|
||||
|
||||
/**
|
||||
* Start BLE Advertising
|
||||
*
|
||||
* @param[in] localName local name to advertise
|
||||
*
|
||||
* @return true on success
|
||||
*
|
||||
*/
|
||||
bool begin(String localName=String());
|
||||
|
||||
/**
|
||||
* Stop BLE Advertising
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
void end(void);
|
||||
|
||||
private:
|
||||
struct ble_gap_adv_params_s * _ble_adv_param;
|
||||
String local_name;
|
||||
void _ble_send_adv_param(void);
|
||||
void _ble_send_adv_data(void);
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
#endif
|
@ -0,0 +1,128 @@
|
||||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Sketch shows how to switch between WiFi and BlueTooth or use both
|
||||
// Button is attached between GPIO 0 and GND and modes are switched with each press
|
||||
|
||||
#include "WiFi.h"
|
||||
#define STA_SSID "your-ssid"
|
||||
#define STA_PASS "your-pass"
|
||||
#define AP_SSID "esp32"
|
||||
|
||||
enum { STEP_BTON, STEP_BTOFF, STEP_STA, STEP_AP, STEP_AP_STA, STEP_OFF, STEP_BT_STA, STEP_END };
|
||||
|
||||
void onButton(){
|
||||
static uint32_t step = STEP_BTON;
|
||||
switch(step){
|
||||
case STEP_BTON://BT Only
|
||||
Serial.println("** Starting BT");
|
||||
btStart();
|
||||
break;
|
||||
case STEP_BTOFF://All Off
|
||||
Serial.println("** Stopping BT");
|
||||
btStop();
|
||||
break;
|
||||
case STEP_STA://STA Only
|
||||
Serial.println("** Starting STA");
|
||||
WiFi.begin(STA_SSID, STA_PASS);
|
||||
break;
|
||||
case STEP_AP://AP Only
|
||||
Serial.println("** Stopping STA");
|
||||
WiFi.mode(WIFI_AP);
|
||||
Serial.println("** Starting AP");
|
||||
WiFi.softAP(AP_SSID);
|
||||
break;
|
||||
case STEP_AP_STA://AP+STA
|
||||
Serial.println("** Starting STA");
|
||||
WiFi.begin(STA_SSID, STA_PASS);
|
||||
break;
|
||||
case STEP_OFF://All Off
|
||||
Serial.println("** Stopping WiFi");
|
||||
WiFi.mode(WIFI_OFF);
|
||||
break;
|
||||
case STEP_BT_STA://BT+STA
|
||||
Serial.println("** Starting STA+BT");
|
||||
WiFi.begin(STA_SSID, STA_PASS);
|
||||
btStart();
|
||||
break;
|
||||
case STEP_END://All Off
|
||||
Serial.println("** Stopping WiFi+BT");
|
||||
WiFi.mode(WIFI_OFF);
|
||||
btStop();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if(step == STEP_END){
|
||||
step = STEP_BTON;
|
||||
} else {
|
||||
step++;
|
||||
}
|
||||
//little debounce
|
||||
delay(100);
|
||||
}
|
||||
|
||||
void WiFiEvent(WiFiEvent_t event){
|
||||
switch(event) {
|
||||
case SYSTEM_EVENT_AP_START:
|
||||
Serial.println("AP Started");
|
||||
WiFi.softAPsetHostname(AP_SSID);
|
||||
break;
|
||||
case SYSTEM_EVENT_AP_STOP:
|
||||
Serial.println("AP Stopped");
|
||||
break;
|
||||
case SYSTEM_EVENT_STA_START:
|
||||
Serial.println("STA Started");
|
||||
WiFi.setHostname(AP_SSID);
|
||||
break;
|
||||
case SYSTEM_EVENT_STA_CONNECTED:
|
||||
Serial.println("STA Connected");
|
||||
WiFi.enableIpV6();
|
||||
break;
|
||||
case SYSTEM_EVENT_AP_STA_GOT_IP6:
|
||||
Serial.print("STA IPv6: ");
|
||||
Serial.println(WiFi.localIPv6());
|
||||
break;
|
||||
case SYSTEM_EVENT_STA_GOT_IP:
|
||||
Serial.print("STA IPv4: ");
|
||||
Serial.println(WiFi.localIP());
|
||||
break;
|
||||
case SYSTEM_EVENT_STA_DISCONNECTED:
|
||||
Serial.println("STA Disconnected");
|
||||
break;
|
||||
case SYSTEM_EVENT_STA_STOP:
|
||||
Serial.println("STA Stopped");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
pinMode(0, INPUT_PULLUP);
|
||||
WiFi.onEvent(WiFiEvent);
|
||||
Serial.print("ESP32 SDK: ");
|
||||
Serial.println(ESP.getSdkVersion());
|
||||
Serial.println("Press the button to select the next mode");
|
||||
}
|
||||
|
||||
void loop() {
|
||||
static uint8_t lastPinState = 1;
|
||||
uint8_t pinState = digitalRead(0);
|
||||
if(!pinState && lastPinState){
|
||||
onButton();
|
||||
}
|
||||
lastPinState = pinState;
|
||||
}
|
@ -42,76 +42,72 @@ extern "C" {
|
||||
#include "lwip/dns.h"
|
||||
#include "esp_ipc.h"
|
||||
|
||||
#include "esp32-hal-log.h"
|
||||
|
||||
/**
|
||||
* Boot and start WiFi
|
||||
* This method get's called on boot if you use any of the WiFi methods.
|
||||
* If you do not link to this library, WiFi will not be started.
|
||||
* */
|
||||
static bool _esp_wifi_initalized = false;
|
||||
extern void initWiFi()
|
||||
{
|
||||
#if !CONFIG_ESP32_PHY_AUTO_INIT
|
||||
arduino_phy_init();
|
||||
#endif
|
||||
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
|
||||
tcpip_adapter_init();
|
||||
esp_event_loop_init(&WiFiGenericClass::_eventCallback, NULL);
|
||||
esp_wifi_init(&cfg);
|
||||
esp_wifi_set_storage(WIFI_STORAGE_FLASH);
|
||||
_esp_wifi_initalized = true;
|
||||
}
|
||||
|
||||
} //extern "C"
|
||||
|
||||
#include "esp32-hal-log.h"
|
||||
|
||||
#undef min
|
||||
#undef max
|
||||
#include <vector>
|
||||
|
||||
static bool _esp_wifi_start()
|
||||
{
|
||||
static bool started = false;
|
||||
esp_err_t err;
|
||||
|
||||
if(!_esp_wifi_initalized){
|
||||
initWiFi();
|
||||
if(!_esp_wifi_initalized){
|
||||
log_w("not initialized");
|
||||
static bool wifiLowLevelInit(){
|
||||
static bool lowLevelInitDone = false;
|
||||
if(!lowLevelInitDone){
|
||||
tcpip_adapter_init();
|
||||
esp_event_loop_init(&WiFiGenericClass::_eventCallback, NULL);
|
||||
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
|
||||
esp_err_t err = esp_wifi_init(&cfg);
|
||||
if(err){
|
||||
log_e("esp_wifi_init %d", err);
|
||||
return false;
|
||||
}
|
||||
esp_wifi_set_storage(WIFI_STORAGE_FLASH);
|
||||
esp_wifi_set_mode(WIFI_MODE_NULL);
|
||||
lowLevelInitDone = true;
|
||||
}
|
||||
if(started){
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool wifiLowLevelDeinit(){
|
||||
//deinit not working yet!
|
||||
//esp_wifi_deinit();
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _esp_wifi_started = false;
|
||||
|
||||
static bool espWiFiStart(){
|
||||
if(_esp_wifi_started){
|
||||
return true;
|
||||
}
|
||||
started = true;
|
||||
err = esp_wifi_start();
|
||||
if (err != ESP_OK) {
|
||||
log_e("%d", err);
|
||||
if(!wifiLowLevelInit()){
|
||||
return false;
|
||||
}
|
||||
#if CONFIG_AUTOCONNECT_WIFI
|
||||
wifi_mode_t mode = WIFI_MODE_NULL;
|
||||
bool auto_connect = false;
|
||||
|
||||
err = esp_wifi_get_mode(&mode);
|
||||
esp_err_t err = esp_wifi_start();
|
||||
if (err != ESP_OK) {
|
||||
log_e("esp_wifi_get_mode: %d", err);
|
||||
log_e("esp_wifi_start %d", err);
|
||||
wifiLowLevelDeinit();
|
||||
return false;
|
||||
}
|
||||
|
||||
err = esp_wifi_get_auto_connect(&auto_connect);
|
||||
if ((mode == WIFI_MODE_STA || mode == WIFI_MODE_APSTA) && auto_connect) {
|
||||
err = esp_wifi_connect();
|
||||
if (err != ESP_OK) {
|
||||
log_e("esp_wifi_connect: %d", err);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
_esp_wifi_started = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool espWiFiStop(){
|
||||
esp_err_t err;
|
||||
if(!_esp_wifi_started){
|
||||
return true;
|
||||
}
|
||||
err = esp_wifi_stop();
|
||||
if(err){
|
||||
log_e("Could not stop WiFi! %u", err);
|
||||
return false;
|
||||
}
|
||||
_esp_wifi_started = false;
|
||||
return wifiLowLevelDeinit();
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------------------------
|
||||
// ------------------------------------------------- Generic WiFi function -----------------------------------------------
|
||||
// -----------------------------------------------------------------------------------------------------------------------
|
||||
@ -246,7 +242,16 @@ bool WiFiGenericClass::mode(wifi_mode_t m)
|
||||
if(cm == m) {
|
||||
return true;
|
||||
}
|
||||
return esp_wifi_set_mode(m) == ESP_OK;
|
||||
esp_err_t err;
|
||||
err = esp_wifi_set_mode(m);
|
||||
if(err){
|
||||
log_e("Could not set mode! %u", err);
|
||||
return false;
|
||||
}
|
||||
if(m){
|
||||
return espWiFiStart();
|
||||
}
|
||||
return espWiFiStop();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -255,10 +260,10 @@ bool WiFiGenericClass::mode(wifi_mode_t m)
|
||||
*/
|
||||
wifi_mode_t WiFiGenericClass::getMode()
|
||||
{
|
||||
uint8_t mode;
|
||||
if(!_esp_wifi_start()){
|
||||
if(!wifiLowLevelInit()){
|
||||
return WIFI_MODE_MAX;
|
||||
}
|
||||
uint8_t mode;
|
||||
esp_wifi_get_mode((wifi_mode_t*)&mode);
|
||||
return (wifi_mode_t)mode;
|
||||
}
|
||||
|
Reference in New Issue
Block a user