Compare commits
2 Commits
8d5b663c78
...
7f8c320b5a
| Author | SHA1 | Date | |
|---|---|---|---|
|
7f8c320b5a
|
|||
|
316fbd7c60
|
144
src/BLEOTA.cpp
144
src/BLEOTA.cpp
@@ -1,24 +1,146 @@
|
|||||||
#include "BLEOTA.h"
|
#include "BLEOTA.h"
|
||||||
|
|
||||||
BLEOTAClass::BLEOTAClass(){
|
/*
|
||||||
_pVersionNumber = new BLECharacteristic(VERSION_NUMBER_UUID, BLECharacteristic::PROPERTY_READ);
|
MAIN CLASS
|
||||||
_pVersionNumberDescriptor = new BLEDescriptor(VERSION_NUMBER_DESCRIPTOR_UUID);
|
*/
|
||||||
|
|
||||||
|
BLEOTAClass::BLEOTAClass()
|
||||||
|
: pVersionNumber_(new BLECharacteristic(VERSION_NUMBER_UUID, BLECharacteristic::PROPERTY_READ)),
|
||||||
|
pVersionNumberDescriptor_(new BLEDescriptor(VERSION_NUMBER_DESCRIPTOR_UUID)),
|
||||||
|
pOTACommand_(new BLECharacteristic(OTA_COMMAND_UUID, BLECharacteristic::PROPERTY_NOTIFY | BLECharacteristic::PROPERTY_WRITE)),
|
||||||
|
pOTACommandDescriptor_(new BLEDescriptor(OTA_COMMAND_DESCRIPTOR_UUID)),
|
||||||
|
pOTAFile_(new BLECharacteristic(OTA_FILE_UUID, BLECharacteristic::PROPERTY_WRITE)),
|
||||||
|
pOTAFileDescriptor_(new BLEDescriptor(OTA_FILE_DESCRIPTOR_UUID)) {
|
||||||
|
cmdCallbacks_ = new OTACommandCallbacks(this);
|
||||||
|
fileCallbacks_ = new OTAFileCallbacks(this);
|
||||||
};
|
};
|
||||||
|
|
||||||
void BLEOTAClass::begin(BLEServer* server, char* versionNumber) {
|
void BLEOTAClass::begin(BLEServer* server, char* versionNumber) {
|
||||||
// set internal versionNumber
|
// set internal versionNumber
|
||||||
_vNum = versionNumber;
|
vNum_ = versionNumber;
|
||||||
// set internal server
|
// set internal server
|
||||||
_pServer = server;
|
pServer_ = server;
|
||||||
// create service
|
// create service
|
||||||
BLEService* otaService = _pServer->createService(OTA_SERVICE_UUID);
|
BLEService* otaService = pServer_->createService(OTA_SERVICE_UUID);
|
||||||
// version number property
|
|
||||||
otaService->addCharacteristic(_pVersionNumber);
|
pVersionNumber_->setValue(vNum_);
|
||||||
_pVersionNumber->setValue(_vNum);
|
pVersionNumberDescriptor_->setValue("Version Number");
|
||||||
_pVersionNumberDescriptor->setValue("Version Number");
|
pVersionNumber_->addDescriptor(pVersionNumberDescriptor_);
|
||||||
_pVersionNumber->addDescriptor(_pVersionNumberDescriptor);
|
|
||||||
|
otaService->addCharacteristic(pVersionNumber_);
|
||||||
|
pOTACommandDescriptor_->setValue("OTA Command");
|
||||||
|
pOTACommand_->addDescriptor(pOTACommandDescriptor_);
|
||||||
|
otaService->addCharacteristic(pOTACommand_);
|
||||||
|
|
||||||
|
pOTAFileDescriptor_->setValue("OTA File");
|
||||||
|
pOTAFile_->addDescriptor(pOTAFileDescriptor_);
|
||||||
|
otaService->addCharacteristic(pOTAFile_);
|
||||||
|
|
||||||
otaService->start();
|
otaService->start();
|
||||||
|
setOTAcommand(CMD_ON);
|
||||||
|
state_ = STAGE_READY;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BLEOTAClass::setOTAcommand(otaCommand cmd) {
|
||||||
|
uint8_t commandBuffer[1] = {};
|
||||||
|
commandBuffer[0] = cmd;
|
||||||
|
pOTACommand_->setValue(commandBuffer, 1);
|
||||||
|
pOTACommand_->notify();
|
||||||
|
currentCommand_ = cmd;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BLEOTAClass::loop() {
|
||||||
|
if (millis() - lastLoop_ > 2000) {
|
||||||
|
if (state_ == STAGE_ERROR && currentCommand_ != CMD_ERROR) {
|
||||||
|
setOTAcommand(CMD_ERROR);
|
||||||
|
}
|
||||||
|
if (state_ == STAGE_DONE) {
|
||||||
|
// reboot
|
||||||
|
ESP.restart();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
COMMAND CHARACTERISTIC CALLBACKS
|
||||||
|
*/
|
||||||
|
|
||||||
|
// so that the callback has access to the main class
|
||||||
|
BLEOTAClass::OTACommandCallbacks::OTACommandCallbacks(BLEOTAClass* pParent) : pParent_(pParent) {};
|
||||||
|
|
||||||
|
void BLEOTAClass::OTACommandCallbacks::onWrite(BLECharacteristic* pCharacteristic, esp_ble_gatts_cb_param_t* param) {
|
||||||
|
size_t cmdLength = pCharacteristic->getLength();
|
||||||
|
if (cmdLength > 4 && pParent_->state_ == STAGE_READY) {
|
||||||
|
// error
|
||||||
|
Serial.println("Error: command too long");
|
||||||
|
pParent_->state_ = STAGE_ERROR;
|
||||||
|
} else if (cmdLength > 1 && pParent_->state_ == STAGE_READY) {
|
||||||
|
// process file size
|
||||||
|
uint8_t* cmdBuffer = pCharacteristic->getData();
|
||||||
|
uint32_t cmd = ((uint32_t)cmdBuffer[0] << 24) |
|
||||||
|
((uint32_t)cmdBuffer[1] << 16) |
|
||||||
|
((uint32_t)cmdBuffer[2] << 8) | (uint32_t)cmdBuffer[3];
|
||||||
|
pParent_->fileSize_ = cmd;
|
||||||
|
// start update
|
||||||
|
if (!Update.begin(pParent_->fileSize_, U_FLASH)) {
|
||||||
|
// error
|
||||||
|
Serial.printf("Error: ");
|
||||||
|
Update.printError(Serial);
|
||||||
|
pParent_->state_ = STAGE_ERROR;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
pParent_->state_ = STAGE_FLASHING;
|
||||||
|
} else if (cmdLength == 0) {
|
||||||
|
// process cmd
|
||||||
|
uint8_t cmd = pCharacteristic->getData()[0];
|
||||||
|
if (cmd == otaCommand::CMD_AGREE) {
|
||||||
|
// process agree
|
||||||
|
if (!Update.end()) {
|
||||||
|
// error
|
||||||
|
Serial.println("Error: client and server ready, but Updater is not");
|
||||||
|
pParent_->state_ = STAGE_ERROR;
|
||||||
|
} else {
|
||||||
|
// reboot logic
|
||||||
|
pParent_->state_ = STAGE_DONE;
|
||||||
|
}
|
||||||
|
} else if (cmd == CMD_DISAGREE) {
|
||||||
|
// process disagree
|
||||||
|
// start over
|
||||||
|
Update.abort();
|
||||||
|
pParent_->fileProgress_ = 0;
|
||||||
|
} else {
|
||||||
|
Serial.println("Error: wrong command");
|
||||||
|
pParent_->state_ = STAGE_ERROR;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Serial.println("Error: command length");
|
||||||
|
pParent_->state_ = STAGE_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
FILE CHARACTERISTIC CALLBACKS
|
||||||
|
*/
|
||||||
|
|
||||||
|
// so that the callback has access to the main class
|
||||||
|
BLEOTAClass::OTAFileCallbacks::OTAFileCallbacks(BLEOTAClass* pParent) : pParent_(pParent) {};
|
||||||
|
|
||||||
|
void BLEOTAClass::OTAFileCallbacks::onWrite(BLECharacteristic* pCharacteristic, esp_ble_gatts_cb_param_t* param) {
|
||||||
|
size_t packetSize = pCharacteristic->getLength();
|
||||||
|
if (packetSize == 0) {
|
||||||
|
// problem
|
||||||
|
// output error
|
||||||
|
Serial.println("Error: no packet");
|
||||||
|
pParent_->state_ = STAGE_ERROR;
|
||||||
|
} else {
|
||||||
|
// write file to updater
|
||||||
|
uint8_t* filePacket = pCharacteristic->getData();
|
||||||
|
if (Update.write(filePacket, packetSize) != packetSize) {
|
||||||
|
Update.printError(Serial);
|
||||||
|
pParent_->state_ = STAGE_ERROR;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BLEOTAClass BLEota;
|
BLEOTAClass BLEota;
|
||||||
83
src/BLEOTA.h
83
src/BLEOTA.h
@@ -3,20 +3,81 @@
|
|||||||
|
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include <BLEServer.h>
|
#include <BLEServer.h>
|
||||||
|
#include <Update.h>
|
||||||
|
|
||||||
#define OTA_SERVICE_UUID "71a4438e-fd52-4b15-b3d2-ec0e3e56193b"
|
#define OTA_SERVICE_UUID "71a4438e-fd52-4b15-b3d2-ec0e3e561900"
|
||||||
#define VERSION_NUMBER_UUID "1978a3df-c009-4837-b295-57ef429dde8c"
|
|
||||||
#define VERSION_NUMBER_DESCRIPTOR_UUID "1e0c35d1-ba03-4f4d-a99c-bac7664d95ed"
|
#define VERSION_NUMBER_UUID "71a4438e-fd52-4b15-b3d2-ec0e3e561910"
|
||||||
|
#define VERSION_NUMBER_DESCRIPTOR_UUID "71a4438e-fd52-4b15-b3d2-ec0e3e561911"
|
||||||
|
|
||||||
|
#define OTA_COMMAND_UUID "71a4438e-fd52-4b15-b3d2-ec0e3e561920"
|
||||||
|
#define OTA_COMMAND_DESCRIPTOR_UUID "71a4438e-fd52-4b15-b3d2-ec0e3e561921"
|
||||||
|
|
||||||
|
#define OTA_FILE_UUID "71a4438e-fd52-4b15-b3d2-ec0e3e561930"
|
||||||
|
#define OTA_FILE_DESCRIPTOR_UUID "71a4438e-fd52-4b15-b3d2-ec0e3e561931"
|
||||||
|
|
||||||
class BLEOTAClass {
|
class BLEOTAClass {
|
||||||
public:
|
public:
|
||||||
BLEOTAClass();
|
BLEOTAClass();
|
||||||
void begin(BLEServer* server, char* versionNumber = "1.0.0");
|
void begin(BLEServer* server, char* versionNumber = "1.0.0");
|
||||||
private:
|
void loop();
|
||||||
BLEServer* _pServer;
|
|
||||||
char* _vNum;
|
typedef enum otaCommand {
|
||||||
BLECharacteristic* _pVersionNumber;
|
CMD_ON = 0x00,
|
||||||
BLEDescriptor* _pVersionNumberDescriptor;
|
CMD_READY = 0x01,
|
||||||
|
CMD_DONE = 0x02,
|
||||||
|
CMD_AGREE = 0x03,
|
||||||
|
CMD_DISAGREE = 0x04,
|
||||||
|
CMD_ERROR = 0x0F
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef enum otaStage {
|
||||||
|
STAGE_READY,
|
||||||
|
STAGE_FLASHING,
|
||||||
|
STAGE_DONE,
|
||||||
|
STAGE_ERROR
|
||||||
|
};
|
||||||
|
private:
|
||||||
|
|
||||||
|
void setOTAcommand(otaCommand cmd);
|
||||||
|
|
||||||
|
class OTACommandCallbacks : public BLECharacteristicCallbacks {
|
||||||
|
public:
|
||||||
|
OTACommandCallbacks(BLEOTAClass* pParent);
|
||||||
|
void onWrite(BLECharacteristic* pCharacteristic, esp_ble_gatts_cb_param_t* param) override;
|
||||||
|
private:
|
||||||
|
BLEOTAClass* pParent_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class OTAFileCallbacks : public BLECharacteristicCallbacks {
|
||||||
|
public:
|
||||||
|
OTAFileCallbacks(BLEOTAClass* pParent);
|
||||||
|
void onWrite(BLECharacteristic* pCharacteristic, esp_ble_gatts_cb_param_t* param) override;
|
||||||
|
private:
|
||||||
|
BLEOTAClass* pParent_;
|
||||||
|
};
|
||||||
|
|
||||||
|
BLEServer* pServer_;
|
||||||
|
char* vNum_;
|
||||||
|
|
||||||
|
BLECharacteristic* pVersionNumber_;
|
||||||
|
BLEDescriptor* pVersionNumberDescriptor_;
|
||||||
|
|
||||||
|
BLECharacteristic* pOTACommand_;
|
||||||
|
BLEDescriptor* pOTACommandDescriptor_;
|
||||||
|
OTACommandCallbacks* cmdCallbacks_;
|
||||||
|
otaCommand currentCommand_;
|
||||||
|
|
||||||
|
BLECharacteristic* pOTAFile_;
|
||||||
|
BLEDescriptor* pOTAFileDescriptor_;
|
||||||
|
OTAFileCallbacks* fileCallbacks_;
|
||||||
|
|
||||||
|
uint32_t fileSize_ = 0;
|
||||||
|
uint32_t fileProgress_ = 0;
|
||||||
|
|
||||||
|
otaStage state_ = otaStage::STAGE_READY;
|
||||||
|
|
||||||
|
unsigned long lastLoop_ = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern BLEOTAClass BLEota;
|
extern BLEOTAClass BLEota;
|
||||||
|
|||||||
Reference in New Issue
Block a user