1
0
mirror of https://github.com/bdring/Grbl_Esp32.git synced 2025-09-01 18:32:37 +02:00

Changed BT settings to yaml style config.

Fixed a bug in the Pin ISR
Fixed a few bugs in the Pin unit tests & added ISR test case
This commit is contained in:
Stefan de Bruijn
2021-05-25 11:02:51 +02:00
parent 8efe02e565
commit a6f7f5ef0e
20 changed files with 209 additions and 162 deletions

View File

@@ -23,7 +23,7 @@ Global
{11C8A44F-A303-4885-B5AD-5B65F7FE41C0}.Release|x64.Build.0 = Release|x64
{11C8A44F-A303-4885-B5AD-5B65F7FE41C0}.Release|x86.ActiveCfg = Release|Win32
{11C8A44F-A303-4885-B5AD-5B65F7FE41C0}.Release|x86.Build.0 = Release|Win32
{33ECE513-60D1-4949-A4A9-C95D353C2CF0}.Debug|x64.ActiveCfg = Debug|x64
{33ECE513-60D1-4949-A4A9-C95D353C2CF0}.Debug|x64.ActiveCfg = Debug|Win32
{33ECE513-60D1-4949-A4A9-C95D353C2CF0}.Debug|x86.ActiveCfg = Debug|Win32
{33ECE513-60D1-4949-A4A9-C95D353C2CF0}.Debug|x86.Build.0 = Debug|Win32
{33ECE513-60D1-4949-A4A9-C95D353C2CF0}.Release|x64.ActiveCfg = Release|x64

View File

@@ -102,9 +102,7 @@ const int MAX_N_AXIS = 6;
#define ENABLE_WIFI //enable wifi
#if defined(ENABLE_WIFI) || defined(ENABLE_BLUETOOTH)
#define WIFI_OR_BLUETOOTH
#endif
#define ENABLE_HTTP //enable HTTP and all related services
#define ENABLE_OTA //enable OTA
@@ -153,6 +151,8 @@ const int DEFAULT_RADIO_MODE = ESP_WIFI_AP;
# endif //CONNECT_TO_SSID
#else
# undef ENABLE_NOTIFICATIONS
// TODO FIXME!
# ifdef ENABLE_BLUETOOTH
const int DEFAULT_RADIO_MODE = ESP_BT;
# else

View File

@@ -99,10 +99,11 @@ void grbl_init() {
WebUI::wifi_config.begin();
#endif
#ifdef ENABLE_BLUETOOTH
if (config->_comms->_bluetoothConfig != nullptr) {
grbl_msg_sendf(CLIENT_SERIAL, MsgLevel::Info, "Initializing Bluetooth...");
WebUI::bt_config.begin();
#endif
config->_comms->_bluetoothConfig->begin();
}
WebUI::inputBuffer.begin();
} catch (const AssertionFailed& ex) {
// This means something is terribly broken:

View File

@@ -69,10 +69,6 @@ const char* const GRBL_VERSION_BUILD = "20210326";
// Do not guard this because it is needed for local files too
#include "SDCard.h"
#ifdef ENABLE_BLUETOOTH
# include "WebUI/BTConfig.h"
#endif
#ifdef ENABLE_WIFI
# include "WebUI/WifiConfig.h"
# ifdef ENABLE_HTTP

View File

@@ -23,6 +23,7 @@
#include "Configuration/HandlerBase.h"
#include "Configuration/Configurable.h"
#include "CoolantControl.h"
#include "WebUI/BTConfig.h"
#include "Probe.h"
// TODO FIXME: Split this file up into several files, perhaps put it in some folder and namespace Machine?
@@ -200,17 +201,6 @@ public:
~SPIBus() = default;
};
class BluetoothConfig : public Configuration::Configurable {
public:
BluetoothConfig() = default;
String _name = "grbl_esp32";
void validate() const override { Assert(_name.length() > 0, "Bluetooth must have a name if it's configured"); }
void handle(Configuration::HandlerBase& handler) override { handler.handle("_name", _name); }
};
class WifiConfig : public Configuration::Configurable {
public:
WifiConfig() = default;
@@ -327,7 +317,7 @@ public:
String _hostname = "grblesp";
BluetoothConfig* _bluetoothConfig = nullptr;
WebUI::BTConfig* _bluetoothConfig = nullptr;
WifiAPConfig* _apConfig = nullptr;
WifiSTAConfig* _staConfig = nullptr;

View File

@@ -37,7 +37,7 @@ class Pin {
// Helper for handling callbacks and mapping them to the proper class:
template <typename ThisType, void (ThisType::*Callback)()>
struct InterruptCallbackHelper {
static void IRAM_ATTR callback(void* ptr) { static_cast<ThisType*>(ptr)->*Callback(); }
static void IRAM_ATTR callback(void* ptr) { (static_cast<ThisType*>(ptr)->*Callback)(); }
};
// Helper for handling callbacks and mapping them to the proper class. This one is just meant
@@ -68,6 +68,8 @@ public:
static const bool On = true;
static const bool Off = false;
inline static Pin create(const char* str) { return create(StringRange(str)); }
static Pin create(const StringRange& str);
static Pin create(const String& str);
static bool validate(const String& str);

View File

@@ -37,9 +37,6 @@ void settings_restore(uint8_t restore_flag) {
if (restore_flag & SettingsRestore::Wifi) {
# ifdef ENABLE_WIFI
WebUI::wifi_config.reset_settings();
# endif
# ifdef ENABLE_BLUETOOTH
WebUI::bt_config.reset_settings();
# endif
}
#endif

View File

@@ -528,9 +528,9 @@ void report_build_info(const char* line, uint8_t client) {
#ifdef ALLOW_FEED_OVERRIDE_DURING_PROBE_CYCLES
grbl_send(client, "A");
#endif
#ifdef ENABLE_BLUETOOTH
if (config->_comms->_bluetoothConfig != nullptr) {
grbl_send(client, "B");
#endif
}
#ifdef ENABLE_SD_CARD
grbl_send(client, "S");
#endif
@@ -562,9 +562,9 @@ void report_build_info(const char* line, uint8_t client) {
#if defined(ENABLE_WIFI)
grbl_send(client, (char*)WebUI::wifi_config.info());
#endif
#if defined(ENABLE_BLUETOOTH)
grbl_send(client, (char*)WebUI::bt_config.info());
#endif
if (config->_comms->_bluetoothConfig != nullptr) {
grbl_send(client, config->_comms->_bluetoothConfig->info().c_str());
}
}
// Prints the character string line Grbl has received from the user, which has been pre-parsed,
@@ -609,12 +609,10 @@ void report_realtime_status(uint8_t client) {
bufsize = WebUI::telnet_server.get_rx_buffer_available();
}
# endif //ENABLE_WIFI && ENABLE_TELNET
# if defined(ENABLE_BLUETOOTH)
if (client == CLIENT_BT) {
if (config->_comms->_bluetoothConfig != nullptr && client == CLIENT_BT) {
//TODO FIXME
bufsize = 512 - WebUI::SerialBT.available();
}
# endif //ENABLE_BLUETOOTH
if (client == CLIENT_SERIAL) {
bufsize = client_get_rx_buffer_available(CLIENT_SERIAL);
}

View File

@@ -56,6 +56,7 @@
*/
#include "Grbl.h"
#include "MachineConfig.h"
#include <atomic>
portMUX_TYPE myMutex = portMUX_INITIALIZER_UNLOCKED;
@@ -124,14 +125,14 @@ static uint8_t getClientChar(uint8_t* data) {
return CLIENT_INPUT;
}
//currently is wifi or BT but better to prepare both can be live
#ifdef ENABLE_BLUETOOTH
if (config->_comms->_bluetoothConfig != nullptr) {
if (WebUI::SerialBT.hasClient()) {
if ((res = WebUI::SerialBT.read()) != -1) {
*data = res;
return CLIENT_BT;
}
}
#endif
}
#if defined(ENABLE_WIFI) && defined(ENABLE_HTTP) && defined(ENABLE_SERIAL2SOCKET_IN)
if (WebUI::Serial2Socket.available()) {
*data = WebUI::Serial2Socket.read();
@@ -180,9 +181,9 @@ void clientCheckTask(void* pvParameters) {
#ifdef ENABLE_WIFI
WebUI::wifi_config.handle();
#endif
#ifdef ENABLE_BLUETOOTH
WebUI::bt_config.handle();
#endif
if (config->_comms->_bluetoothConfig != nullptr) {
config->_comms->_bluetoothConfig->handle();
}
#if defined(ENABLE_WIFI) && defined(ENABLE_HTTP) && defined(ENABLE_SERIAL2SOCKET_IN)
WebUI::Serial2Socket.handle_flush();
#endif
@@ -331,12 +332,12 @@ void client_write(uint8_t client, const char* text) {
if (client == CLIENT_INPUT) {
return;
}
#ifdef ENABLE_BLUETOOTH
if (config->_comms->_bluetoothConfig != nullptr) {
if (WebUI::SerialBT.hasClient() && (client == CLIENT_BT || client == CLIENT_ALL)) {
WebUI::SerialBT.print(text);
//delay(10); // possible fix for dropped characters
}
#endif
}
#if defined(ENABLE_WIFI) && defined(ENABLE_HTTP) && defined(ENABLE_SERIAL2SOCKET_OUT)
if (client == CLIENT_WEBUI || client == CLIENT_ALL) {
WebUI::Serial2Socket.write((const uint8_t*)text, strlen(text));

View File

@@ -81,9 +81,6 @@ public:
const char* begin() const { return start_; }
const char* end() const { return end_; }
#ifndef ESP32
std::string str() const { return std::string(begin(), end()); }
#else
String str() const {
// TODO: Check if we can eliminate this function. I'm pretty sure we can.
auto len = length();
@@ -94,5 +91,4 @@ public:
delete[] buf;
return tmp;
}
#endif
};

View File

@@ -19,48 +19,44 @@
*/
#include "../Grbl.h"
#include "../MachineConfig.h"
#ifdef ENABLE_BLUETOOTH
# include <BluetoothSerial.h>
#include "BTConfig.h"
extern "C" {
const uint8_t* esp_bt_dev_get_address(void);
}
namespace WebUI {
BTConfig bt_config;
BluetoothSerial SerialBT;
# ifdef __cplusplus
extern "C" {
# endif
const uint8_t* esp_bt_dev_get_address(void);
# ifdef __cplusplus
}
# endif
String BTConfig::_btname = "";
String BTConfig::_btclient = "";
BTConfig* BTConfig::instance = nullptr;
BTConfig::BTConfig() {}
static void my_spp_cb(esp_spp_cb_event_t event, esp_spp_cb_param_t* param) {
void BTConfig::my_spp_cb(esp_spp_cb_event_t event, esp_spp_cb_param_t* param) {
auto inst = instance;
switch (event) {
case ESP_SPP_SRV_OPEN_EVT: { //Server connection open
char str[18];
str[17] = '\0';
uint8_t* addr = param->srv_open.rem_bda;
sprintf(str, "%02X:%02X:%02X:%02X:%02X:%02X", addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
BTConfig::_btclient = str;
inst->_btclient = str;
grbl_sendf(CLIENT_ALL, "[MSG:BT Connected with %s]\r\n", str);
} break;
case ESP_SPP_CLOSE_EVT: //Client connection closed
grbl_send(CLIENT_ALL, "[MSG:BT Disconnected]\r\n");
BTConfig::_btclient = "";
inst->_btclient = "";
break;
default:
break;
}
}
const char* BTConfig::info() {
static String result;
String BTConfig::info() {
String result;
String tmp;
result = "[MSG:";
if (Is_BT_on()) {
@@ -78,7 +74,7 @@ namespace WebUI {
result += "No BT";
}
result += "]\r\n";
return result.c_str();
return result;
}
/**
* Check if BlueTooth string is valid
@@ -103,7 +99,7 @@ namespace WebUI {
const char* BTConfig::device_address() {
const uint8_t* point = esp_bt_dev_get_address();
static char str[18];
char* str = _deviceAddrBuffer;
str[17] = '\0';
sprintf(
str, "%02X:%02X:%02X:%02X:%02X:%02X", (int)point[0], (int)point[1], (int)point[2], (int)point[3], (int)point[4], (int)point[5]);
@@ -114,9 +110,11 @@ namespace WebUI {
* begin WiFi setup
*/
void BTConfig::begin() {
instance = this;
//stop active services
end();
_btname = bt_name->get();
if (wifi_radio_mode->get() == ESP_BT) {
if (!SerialBT.begin(_btname)) {
report_status_message(Error::BtFailBegin, CLIENT_ALL);
@@ -138,7 +136,6 @@ namespace WebUI {
* Reset ESP
*/
void BTConfig::reset_settings() {
bt_name->setDefault();
wifi_radio_mode->setDefault();
grbl_send(CLIENT_ALL, "[MSG:BT reset done]\r\n");
}
@@ -146,7 +143,7 @@ namespace WebUI {
/**
* Check if BT is on and working
*/
bool BTConfig::Is_BT_on() { return btStarted(); }
bool BTConfig::Is_BT_on() const { return btStarted(); }
/**
* Handle not critical actions that must be done in sync environement
@@ -158,4 +155,3 @@ namespace WebUI {
BTConfig::~BTConfig() { end(); }
}
#endif // ENABLE_BLUETOOTH

View File

@@ -4,6 +4,8 @@
BTConfig.h - Bluetooth functions class
Copyright (c) 2014 Luc Lebosse. All rights reserved.
Copyright (c) 2021 Stefan de Bruijn. Changed to a class based structure,
fixed multiple bugs with static and added configuration.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -19,42 +21,50 @@
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#if !defined(CONFIG_BT_ENABLED) || !defined(CONFIG_BLUEDROID_ENABLED)
# error Bluetooth is not enabled! Please run `make menuconfig` to and enable it
#endif
//defaults values
const char* const DEFAULT_BT_NAME = "btgrblesp";
#include <BluetoothSerial.h>
#include "../Configuration/Configurable.h"
namespace WebUI {
extern BluetoothSerial SerialBT;
class BTConfig {
//boundaries
public:
class BTConfig : public Configuration::Configurable {
private:
static BTConfig* instance; // BT Callback does not support passing parameters. Sigh.
String _btclient = "";
String _btname = "btgrblesp";
char _deviceAddrBuffer[18];
static const int MAX_BTNAME_LENGTH = 32;
static const int MIN_BTNAME_LENGTH = 1;
static void my_spp_cb(esp_spp_cb_event_t event, esp_spp_cb_param_t* param);
//boundaries
public:
BTConfig();
static const char* info();
static bool isBTnameValid(const char* hostname);
static String BTname() { return _btname; }
static const char* device_address();
static void begin();
static void end();
static void handle();
static void reset_settings();
static bool Is_BT_on();
static String _btclient;
void validate() const override {
Assert(_btname.length() > 0, "Bluetooth must have a name if it's configured");
Assert(_btname.length() >= MIN_BTNAME_LENGTH && _btname.length() <= MAX_BTNAME_LENGTH,
"Bluetooth name must be between %d and %d characters long",
MIN_BTNAME_LENGTH,
MAX_BTNAME_LENGTH);
}
void handle(Configuration::HandlerBase& handler) override { handler.handle("_name", _btname); }
String info();
bool isBTnameValid(const char* hostname);
const String& BTname() const { return _btname; }
const String& client_name() const { return _btclient; }
const char* device_address();
void begin();
void end();
void handle();
void reset_settings();
bool Is_BT_on() const;
~BTConfig();
private:
static String _btname;
};
extern BTConfig bt_config;
}

View File

@@ -29,6 +29,7 @@
// - https://www.electronicshub.org/send-an-email-using-esp8266/
#include "../Grbl.h"
#include "../MachineConfig.h"
#ifdef ENABLE_NOTIFICATIONS
# include "NotificationsService.h"

View File

@@ -19,6 +19,7 @@
*/
#include "../Grbl.h"
#include "../MachineConfig.h"
#if defined(ENABLE_WIFI) && defined(ENABLE_TELNET)

View File

@@ -19,6 +19,7 @@
*/
#include "../Grbl.h"
#include "../MachineConfig.h"
#if defined(ENABLE_WIFI) && defined(ENABLE_HTTP)
@@ -484,7 +485,8 @@ namespace WebUI {
} else {
espresponse->flush();
}
if(espresponse) delete(espresponse);
if (espresponse)
delete (espresponse);
} else { //execute GCODE
if (auth_level == AuthenticationLevel::LEVEL_GUEST) {
_webserver->send(401, "text/plain", "Authentication failed!\n");

View File

@@ -79,16 +79,10 @@ namespace WebUI {
{ "STA", ESP_WIFI_STA },
{ "AP", ESP_WIFI_AP },
# endif
# ifdef ENABLE_BLUETOOTH
{ "BT", ESP_BT },
# endif
};
#endif
#ifdef ENABLE_BLUETOOTH
StringSetting* bt_name;
#endif
#ifdef ENABLE_NOTIFICATIONS
enum_opt_t notificationOptions = {
{ "NONE", 0 },
@@ -562,27 +556,28 @@ namespace WebUI {
break;
}
#endif // ENABLE_WIFI
#ifdef ENABLE_BLUETOOTH
if (config->_comms->_bluetoothConfig != nullptr) {
auto bt_config = config->_comms->_bluetoothConfig;
webPrint("Current BT Mode: ");
if (bt_config.Is_BT_on()) {
if (bt_config->Is_BT_on()) {
webPrintln("On");
webPrint("BT Name: ");
webPrint(bt_config.BTname());
webPrint(bt_config->BTname());
webPrint("(");
webPrint(bt_config.device_address());
webPrint(bt_config->device_address());
webPrintln(")");
webPrint("Status: ");
if (SerialBT.hasClient()) {
webPrintln("Connected with ", bt_config._btclient);
webPrintln("Connected with ", bt_config->client_name());
} else {
webPrintln("Not connected");
}
} else {
webPrintln("Off");
}
#endif
}
#ifdef ENABLE_NOTIFICATIONS
webPrint("Notifications: ");
webPrint(notificationsservice.started() ? "Enabled" : "Disabled");
@@ -910,11 +905,11 @@ namespace WebUI {
on = true;
}
#endif
#if defined(ENABLE_BLUETOOTH)
if (bt_config.Is_BT_on()) {
if (config->_comms->_bluetoothConfig != nullptr && config->_comms->_bluetoothConfig->Is_BT_on()) {
on = true;
}
#endif
webPrintln(on ? "ON" : "OFF");
return Error::Ok;
}
@@ -935,11 +930,12 @@ namespace WebUI {
wifi_config.StopWiFi();
}
#endif
#if defined(ENABLE_BLUETOOTH)
if (bt_config.Is_BT_on()) {
bt_config.end();
if (config->_comms->_bluetoothConfig != nullptr) {
if (config->_comms->_bluetoothConfig->Is_BT_on()) {
config->_comms->_bluetoothConfig->end();
}
#endif
}
//if On start proper service
if (!on) {
webPrintln("[MSG: Radio is Off]");
@@ -959,13 +955,13 @@ namespace WebUI {
return Error::Ok;
# endif
case ESP_BT:
# if !defined(ENABLE_BLUETOOTH)
if (config->_comms->_bluetoothConfig == nullptr) {
webPrintln("Bluetooth is not enabled!");
return Error::BtFailBegin;
# else
bt_config.begin();
} else {
config->_comms->_bluetoothConfig->begin();
return Error::Ok;
# endif
}
default:
webPrintln("[MSG: Radio is Off]");
return Error::Ok;
@@ -1143,17 +1139,6 @@ namespace WebUI {
MAX_LOCAL_PASSWORD_LENGTH,
&COMMANDS::isLocalPasswordValid);
#endif
#ifdef ENABLE_BLUETOOTH
bt_name = new StringSetting("Bluetooth name",
WEBSET,
WA,
"ESP140",
"Bluetooth/Name",
DEFAULT_BT_NAME,
WebUI::BTConfig::MIN_BTNAME_LENGTH,
WebUI::BTConfig::MAX_BTNAME_LENGTH,
(bool (*)(char*))BTConfig::isBTnameValid);
#endif
#ifdef WIFI_OR_BLUETOOTH
// user+ to get, admin to set

View File

@@ -48,10 +48,6 @@ namespace WebUI {
extern EnumSetting* wifi_radio_mode;
#endif
#ifdef ENABLE_BLUETOOTH
extern StringSetting* bt_name;
#endif
#ifdef ENABLE_AUTHENTICATION
extern StringSetting* user_password;
extern StringSetting* admin_password;

View File

@@ -19,6 +19,7 @@
*/
#include "../Grbl.h"
#include "../MachineConfig.h"
#ifdef ENABLE_WIFI

View File

@@ -19,6 +19,7 @@
*/
#include "../Grbl.h"
#include "../MachineConfig.h"
#ifdef ENABLE_WIFI

View File

@@ -285,4 +285,77 @@ namespace Pins {
Assert(true == GPIONative::read(16));
Assert(true == GPIONative::read(17));
}
class GPIOISR {
int hitCount;
void HandleISR() { ++hitCount; }
public:
GPIOISR(int deltaRising, int deltaFalling, int mode) {
GPIONative::initialize();
PinLookup::ResetAllPins();
Pin gpio16 = Pin::create("gpio.16");
Pin gpio17 = Pin::create("gpio.17");
gpio16.setAttr(Pin::Attr::Input | Pin::Attr::ISR);
gpio17.setAttr(Pin::Attr::Output);
hitCount = 0;
int expected = 0;
gpio16.attachInterrupt<GPIOISR, &GPIOISR::HandleISR>(this, mode);
// Two ways to set I/O:
// 1. using on/off
// 2. external source (e.g. set softwareio pin value)
//
// We read as well, because that shouldn't modify the state.
//
// NOTE: Hysteresis tells us that we get changes a lot during a small
// window in time. Unfortunately, it's practically impossible to test
// because it bounces all over the place... TODO FIXME, some mechanism
// to cope with that.
for (int i = 0; i < 10; ++i) {
if (deltaRising) {
auto oldCount = hitCount;
gpio17.on();
delay(1);
auto newCount = hitCount;
Assert(oldCount < newCount, "Expected rise after set state");
} else {
gpio17.on();
}
if (deltaFalling) {
auto oldCount = hitCount;
gpio17.off();
delay(1);
auto newCount = hitCount;
Assert(oldCount < newCount, "Expected rise after set state");
} else {
gpio17.off();
}
}
// Detach interrupt. Regardless of what we do, it shouldn't change hitcount anymore.
gpio16.detachInterrupt();
auto oldCount = hitCount;
gpio17.on();
gpio17.off();
delay(1);
auto newCount = hitCount;
Assert(oldCount == newCount, "ISR hitcount error");
}
};
Test(GPIO, ISRRisingPinClass) { GPIOISR isr(1, 0, RISING); }
Test(GPIO, ISRFallingPinClass) { GPIOISR isr(0, 1, FALLING); }
Test(GPIO, ISRChangePinClass) { GPIOISR isr(1, 1, CHANGE); }
}