Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add bluetooth connection disconnect handling #74

Merged
25 changes: 17 additions & 8 deletions lib/M5ez/src/M5ez.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -419,7 +419,7 @@ size_t ezCanvas::write(const uint8_t *buffer, size_t size) {
return size;
}

uint16_t ezCanvas::loop() {
uint16_t ezCanvas::loop(void *private_data) {
if (_next_scroll && millis() >= _next_scroll) {
ez.setFont(_font);
uint8_t h = ez.fontHeight();
Expand Down Expand Up @@ -554,6 +554,10 @@ void ezButtons::show(String buttons) {
}
}

String ezButtons::get() {
return (_btn_a_s + "#" + _btn_b_s + "#" + _btn_c_s);
}

void ezButtons::clear(bool wipe /* = true */) {
if (wipe && (_lower_button_row || _upper_button_row)) {
M5.Lcd.fillRect(0, ez.canvas.bottom() + 1, TFT_H - ez.canvas.bottom() - 1, TFT_W,
Expand Down Expand Up @@ -887,7 +891,7 @@ void ezBacklight::activity() {
_last_activity = millis();
}

uint16_t ezBacklight::loop() {
uint16_t ezBacklight::loop(void *private_data) {
if (!_backlight_off && _inactivity) {
if (millis() > _last_activity + 30000 * _inactivity) {
_backlight_off = true;
Expand Down Expand Up @@ -1008,7 +1012,7 @@ void ezClock::menu() {
}
}

uint16_t ezClock::loop() {
uint16_t ezClock::loop(void *private_data) {
ezt::events();
if (_starting && timeStatus() != timeNotSet) {
_starting = false;
Expand Down Expand Up @@ -1562,7 +1566,7 @@ void ezWifi::_askAdd() {
}
}

uint16_t ezWifi::loop() {
uint16_t ezWifi::loop(void *private_data) {
if (millis() > _widget_time + ez.theme->signal_interval) {
ez.header.draw("wifi");
_widget_time = millis();
Expand Down Expand Up @@ -2109,7 +2113,7 @@ void ezBattery::menu() {
}
}

uint16_t ezBattery::loop() {
uint16_t ezBattery::loop(void *private_data) {
if (!_on)
return 0;
ez.header.draw("battery");
Expand Down Expand Up @@ -2232,7 +2236,7 @@ void M5ez::yield() {
M5.update();
for (uint8_t n = 0; n < _events.size(); n++) {
if (millis() > _events[n].when) {
uint16_t r = (_events[n].function)();
uint16_t r = (_events[n].function)(_events[n].private_data);
if (r) {
_events[n].when = millis() + r - 1;
} else {
Expand All @@ -2246,14 +2250,17 @@ void M5ez::yield() {
#endif
}

void M5ez::addEvent(uint16_t (*function)(), uint32_t when /* = 1 */) {
void M5ez::addEvent(uint16_t (*function)(void *private_data),
void *private_data,
uint32_t when /* = 1 */) {
event_t n;
n.function = function;
n.private_data = private_data;
n.when = millis() + when - 1;
_events.push_back(n);
}

void M5ez::removeEvent(uint16_t (*function)()) {
void M5ez::removeEvent(uint16_t (*function)(void *private_data)) {
uint8_t n = 0;
while (n < _events.size()) {
if (_events[n].function == function) {
Expand Down Expand Up @@ -3467,6 +3474,8 @@ ezProgressBar::ezProgressBar(String header /* = "" */,
bar_color = ez.theme->progressbar_color;
_bar_color = bar_color;
ez.screen.clear();
M5.Lcd.fillRect(0, 0, TFT_W, TFT_H, ez.screen.background());

if (header != "")
ez.header.show(header);
ez.buttons.show(buttons);
Expand Down
20 changes: 12 additions & 8 deletions lib/M5ez/src/M5ez.h
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ class ezCanvas: public Print {
uint8_t c); // These three are used to inherint print and println from Print class
virtual size_t write(const char *str);
virtual size_t write(const uint8_t *buffer, size_t size);
static uint16_t loop();
static uint16_t loop(void *private_data);

private:
static std::vector<print_t> _printed;
Expand Down Expand Up @@ -321,6 +321,7 @@ class ezButtons {
public:
static void begin();
static void show(String buttons);
static String get();
static void clear(bool wipe = true);
static void releaseWait();
static String poll();
Expand Down Expand Up @@ -501,7 +502,7 @@ class ezBacklight {
static void menu();
static void inactivity(uint8_t half_minutes);
static void activity();
static uint16_t loop();
static uint16_t loop(void *private_data);

private:
static uint8_t _brightness;
Expand All @@ -526,7 +527,7 @@ class ezClock {
static void begin();
static void restart();
static void menu();
static uint16_t loop();
static uint16_t loop(void *private_data);
static void clear();
static void draw(uint16_t x, uint16_t w);
static bool waitForSync(const uint16_t timeout = 0);
Expand Down Expand Up @@ -599,7 +600,7 @@ class ezWifi {
static void readFlash();
static void writeFlash();
static void menu();
static uint16_t loop();
static uint16_t loop(void *private_data);
static bool update(String url, const char *root_cert, ezProgressBar *pb = NULL);
static String updateError();

Expand Down Expand Up @@ -678,7 +679,7 @@ class ezBattery {
static void readFlash();
static void writeFlash();
static void menu();
static uint16_t loop();
static uint16_t loop(void *private_data);
static uint8_t getTransformedBatteryLevel();
static uint16_t getBatteryBarColor(uint8_t batteryLevel);

Expand All @@ -698,7 +699,8 @@ class ezBattery {
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

struct event_t {
uint16_t (*function)();
uint16_t (*function)(void *);
void *private_data;
uint32_t when;
};
class M5ez {
Expand Down Expand Up @@ -742,8 +744,10 @@ class M5ez {

static void yield();

static void addEvent(uint16_t (*function)(), uint32_t when = 1);
static void removeEvent(uint16_t (*function)());
static void addEvent(uint16_t (*function)(void *),
void *private_data = nullptr,
uint32_t when = 1);
static void removeEvent(uint16_t (*function)(void *private_data));
static void redraw();

// ez.msgBox
Expand Down
4 changes: 4 additions & 0 deletions lib/furble/Device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -180,4 +180,8 @@ void Device::getUUID128(uuid128_t *uuid) {
}
}

bool Device::isConnected(void) {
return m_Client->isConnected();
}

} // namespace Furble
5 changes: 5 additions & 0 deletions lib/furble/Device.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,11 @@ class Device {
*/
virtual void updateGeoData(gps_t &gps, timesync_t &timesync) = 0;

/**
* Checks if the client is still connected.
*/
bool isConnected(void);

const char *getName(void);
void save(void);
void remove(void);
Expand Down
2 changes: 2 additions & 0 deletions lib/furble/Fujifilm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ bool Fujifilm::connect(NimBLEClient *pClient, ezProgressBar &progress_bar) {
if (m_Configured) {
break;
}
progress_bar.value(50.0f + (((float)i / 5000.0f) * 10.0f));
delay(100);
}

Expand All @@ -224,6 +225,7 @@ bool Fujifilm::connect(NimBLEClient *pClient, ezProgressBar &progress_bar) {
m_GeoRequested = false;
break;
}
progress_bar.value(90.0f + (((float)i / 5000.0f) * 10.0f));
delay(100);
}

Expand Down
86 changes: 68 additions & 18 deletions src/furble.ino
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ static const uint8_t GPS_HEADER_POSITION = CURRENT_POSITION + 1;
static bool gps_enable = false;
static bool gps_has_fix = false;

struct FurbleCtx {
Furble::Device *device;
bool reconnected;
};

/**
* BLE Advertisement callback.
*/
Expand All @@ -38,7 +43,7 @@ class AdvertisedCallback: public NimBLEAdvertisedDeviceCallbacks {
/**
* GPS serial event service handler.
*/
static uint16_t service_grove_gps(void) {
static uint16_t service_grove_gps(void *private_data) {
if (!gps_enable) {
return GPS_SERVICE_MS;
}
Expand Down Expand Up @@ -112,7 +117,7 @@ static void current_draw_widget(uint16_t x, uint16_t y) {
M5.Lcd.drawString(s, x + ez.theme->header_hmargin, ez.theme->header_tmargin + 2);
}

static uint16_t current_service(void) {
static uint16_t current_service(void *private_data) {
ez.header.draw("current");
return 1000;
}
Expand All @@ -139,16 +144,22 @@ static void trigger(Furble::Device *device, int counter) {
device->shutterRelease();
}

static void remote_interval(Furble::Device *device) {
static void remote_interval(FurbleCtx *fctx) {
Furble::Device *device = fctx->device;
int i = 0;
int j = 1;

ez.msgBox("Interval Release", "", "Stop", false);
trigger(device, j);

while (true) {
while (device->isConnected()) {
i++;

if (fctx->reconnected) {
ez.msgBox("Interval Release", String(j), "Stop", false);
fctx->reconnected = false;
}

M5.update();

if (M5.BtnB.wasReleased()) {
Expand Down Expand Up @@ -200,7 +211,8 @@ static void show_shutter_control(bool shutter_locked, unsigned long lock_start_m
}
}

static void remote_control(Furble::Device *device) {
static void remote_control(FurbleCtx *fctx) {
Furble::Device *device = fctx->device;
static unsigned long shutter_lock_start_ms = 0;
static bool shutter_lock = false;

Expand All @@ -213,6 +225,11 @@ static void remote_control(Furble::Device *device) {

update_geodata(device);

if (fctx->reconnected) {
show_shutter_control(shutter_lock, shutter_lock_start_ms);
fctx->reconnected = false;
}

if (M5.BtnPWR.wasClicked() || M5.BtnC.wasPressed()) {
if (shutter_lock) {
// ensure shutter is released on exit
Expand Down Expand Up @@ -268,7 +285,7 @@ static void remote_control(Furble::Device *device) {

ez.yield();
delay(50);
} while (true);
} while (device->isConnected());
}

/**
Expand All @@ -291,7 +308,36 @@ static void do_saved(void) {
menu_connect(false);
}

static void menu_remote(Furble::Device *device) {
uint16_t disconnectDetect(void *private_data) {
FurbleCtx *fctx = (FurbleCtx *)private_data;
Furble::Device *device = fctx->device;

if (device->isConnected())
return 500;

String buttons = ez.buttons.get();
String header = ez.header.title();

NimBLEClient *pClient = NimBLEDevice::createClient();
ezProgressBar progress_bar(FURBLE_STR, "Reconnecting ...", "");
if (device->connect(pClient, progress_bar)) {
ez.screen.clear();
ez.header.show(header);
ez.buttons.show(buttons);

fctx->reconnected = true;

ez.redraw();
return 500;
}

ez.screen.clear();
// no recovery, restart device
esp_restart();
return 0;
}

static void menu_remote(FurbleCtx *fctx) {
ez.backlight.inactivity(NEVER);
ezMenu submenu(FURBLE_STR " - Connected");
submenu.buttons("OK#down");
Expand All @@ -300,19 +346,23 @@ static void menu_remote(Furble::Device *device) {
submenu.addItem("Disconnect");
submenu.downOnLast("first");

ez.addEvent(disconnectDetect, fctx, 500);

do {
submenu.runOnce();

if (submenu.pickName() == "Shutter") {
remote_control(device);
remote_control(fctx);
}

if (submenu.pickName() == "Interval") {
remote_interval(device);
remote_interval(fctx);
}
} while (submenu.pickName() != "Disconnect");

device->disconnect();
ez.removeEvent(disconnectDetect);

fctx->device->disconnect();
ez.backlight.inactivity(USER_SET);
}

Expand All @@ -329,21 +379,21 @@ static void menu_connect(bool save) {
if (i == 0)
return;

Furble::Device *device = connect_list[i - 1];
FurbleCtx fctx = {connect_list[i - 1], false};

update_geodata(device);
update_geodata(fctx.device);

NimBLEClient *pClient = NimBLEDevice::createClient();
ezProgressBar progress_bar(FURBLE_STR, "Connecting ...", "");
if (device->connect(pClient, progress_bar)) {
if (fctx.device->connect(pClient, progress_bar)) {
if (save) {
device->save();
fctx.device->save();
}
menu_remote(device);
menu_remote(&fctx);
}
}

static void menu_delete() {
static void menu_delete(void) {
std::vector<Furble::Device *> devices;
ezMenu submenu(FURBLE_STR " - Delete");
submenu.buttons("OK#down");
Expand Down Expand Up @@ -394,8 +444,8 @@ void setup() {
uint8_t width = 4 * M5.Lcd.textWidth("5") + ez.theme->header_hmargin * 2;
ez.header.insert(CURRENT_POSITION, "current", width, current_draw_widget);
ez.header.insert(GPS_HEADER_POSITION, "gps", ez.theme->header_height * 0.8, gps_draw_widget);
ez.addEvent(service_grove_gps, millis() + 500);
ez.addEvent(current_service, millis() + 500);
ez.addEvent(service_grove_gps, nullptr, millis() + 500);
ez.addEvent(current_service, nullptr, millis() + 500);

NimBLEDevice::init(FURBLE_STR);
NimBLEDevice::setSecurityAuth(true, true, true);
Expand Down