Serial over BLE (#15)

added flag in config to enable using bluetooth low energy (BLE) which allows pairing with iOS devices (e.g. APRS.fi app).
pull/23/head
Matthew Patrick 2021-06-07 23:33:40 -06:00 zatwierdzone przez GitHub
rodzic f7028c690b
commit 1df9f4f87a
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
7 zmienionych plików z 290 dodań i 15 usunięć

177
ble_serial.cpp 100644
Wyświetl plik

@ -0,0 +1,177 @@
// Copyright 2019 Ian Archbell / oddWires
//
// 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 "ble_serial.h"
class BLESerialServerCallbacks: public BLEServerCallbacks {
friend class BLESerial;
BLESerial* bleSerial;
void onConnect(BLEServer* pServer) {
// do anything needed on connection
delay(1000); // wait for connection to complete or messages can be lost
};
void onDisconnect(BLEServer* pServer) {
pServer->startAdvertising(); // restart advertising
Serial.println("Started advertising");
}
};
class BLESerialCharacteristicCallbacks: public BLECharacteristicCallbacks {
friend class BLESerial;
BLESerial* bleSerial;
void onWrite(BLECharacteristic *pCharacteristic) {
bleSerial->receiveBuffer = bleSerial->receiveBuffer + pCharacteristic->getValue();
}
};
// Constructor
BLESerial::BLESerial()
{
// create instance
receiveBuffer = "";
}
// Destructor
BLESerial::~BLESerial(void)
{
// clean up
}
// Begin bluetooth serial
bool BLESerial::begin(char* localName)
{
// Create the BLE Device
BLEDevice::init(localName);
// Create the BLE Server
pServer = BLEDevice::createServer();
if (pServer == nullptr)
return false;
BLESerialServerCallbacks* bleSerialServerCallbacks = new BLESerialServerCallbacks();
bleSerialServerCallbacks->bleSerial = this;
pServer->setCallbacks(bleSerialServerCallbacks);
// Create the BLE Service
pService = pServer->createService(SERVICE_UUID);
if (pService == nullptr)
return false;
// Create a BLE Characteristic
pTxCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID_TX,
BLECharacteristic::PROPERTY_NOTIFY
);
if (pTxCharacteristic == nullptr)
return false;
pTxCharacteristic->addDescriptor(new BLE2902());
BLECharacteristic * pRxCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID_RX,
BLECharacteristic::PROPERTY_WRITE
);
if (pRxCharacteristic == nullptr)
return false;
BLESerialCharacteristicCallbacks* bleSerialCharacteristicCallbacks = new BLESerialCharacteristicCallbacks();
bleSerialCharacteristicCallbacks->bleSerial = this;
pRxCharacteristic->setCallbacks(bleSerialCharacteristicCallbacks);
// Start the service
pService->start();
Serial.println("starting service");
// Start advertising
pServer->getAdvertising()->addServiceUUID(pService->getUUID());
pServer->getAdvertising()->start();
Serial.println("Waiting a client connection to notify...");
return true;
}
int BLESerial::available(void)
{
// reply with data available
return receiveBuffer.length();
}
int BLESerial::peek(void)
{
// return first character available
// but don't remove it from the buffer
if ((receiveBuffer.length() > 0)){
uint8_t c = receiveBuffer[0];
return c;
}
else
return -1;
}
bool BLESerial::connected(void)
{
// true if connected
if (pServer->getConnectedCount() > 0)
return true;
else
return false;
}
int BLESerial::read(void)
{
// read a character
if ((receiveBuffer.length() > 0)){
uint8_t c = receiveBuffer[0];
receiveBuffer.erase(0,1); // remove it from the buffer
return c;
}
else
return -1;
}
size_t BLESerial::write(uint8_t c)
{
// write a character
uint8_t _c = c;
pTxCharacteristic->setValue(&_c, 1);
pTxCharacteristic->notify();
delay(10); // bluetooth stack will go into congestion, if too many packets are sent
return 1;
}
size_t BLESerial::write(const uint8_t *buffer, size_t size)
{
// write a buffer
for(int i=0; i < size; i++){
write(buffer[i]);
}
return size;
}
void BLESerial::flush()
{
// remove buffered data
receiveBuffer.clear();
}
void BLESerial::end()
{
// close connection
}

61
ble_serial.h 100644
Wyświetl plik

@ -0,0 +1,61 @@
// Copyright 2019 Ian Archbell / oddWires
//
// 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 _BLE_SERIAL_H_
#define _BLE_SERIAL_H_
#include "Arduino.h"
#include "Stream.h"
#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>
#define SERVICE_UUID "00000001-ba2a-46c9-ae49-01b0961f68bb" // KISS service UUID
#define CHARACTERISTIC_UUID_TX "00000003-ba2a-46c9-ae49-01b0961f68bb"
#define CHARACTERISTIC_UUID_RX "00000002-ba2a-46c9-ae49-01b0961f68bb"
class BLESerial: public Stream
{
public:
BLESerial(void);
~BLESerial(void);
bool begin(char* localName="loraprs");
int available(void);
int peek(void);
bool connected(void);
int read(void);
size_t write(uint8_t c);
size_t write(const uint8_t *buffer, size_t size);
void flush();
void end(void);
private:
String local_name;
BLEServer *pServer = NULL;
BLEService *pService;
BLECharacteristic * pTxCharacteristic;
bool deviceConnected = false;
uint8_t txValue = 0;
std::string receiveBuffer;
friend class BLESerialServerCallbacks;
friend class BLESerialCharacteristicCallbacks;
};
#endif

Wyświetl plik

@ -29,6 +29,7 @@
#define CFG_LORA_ENABLE_CRC true // set to false for speech data
#define CFG_BT_NAME "loraprs"
#define CFG_USE_BLE true // set to true to use bluetooth low energy (for ios devices)
#define CFG_APRS_LOGIN "NOCALL-10"
#define CFG_APRS_PASS "12345"

Wyświetl plik

@ -47,6 +47,7 @@ void initializeConfig(LoraPrs::Config &cfg) {
// bluetooth device name
cfg.BtName = CFG_BT_NAME;
cfg.useBLE = CFG_USE_BLE;
// server mode wifi paramaters
cfg.WifiSsid = CFG_WIFI_SSID;

Wyświetl plik

@ -26,7 +26,7 @@ struct Config
// bluetooth
String BtName; // bluetooth device name for the client, set to empty string to disable bluetooth in server mode
bool useBLE; // bluetooth device presents as BLE rather than serial bluetooth e.g. for iOS devices
// wifi
String WifiSsid; // wifi access point name
String WifiKey; // wifi access point key

Wyświetl plik

@ -8,6 +8,7 @@ Service::Service()
, csmaSlotTime_(CfgCsmaSlotTimeMs)
, csmaSlotTimePrev_(0)
, serialBt_()
, serialBLE_()
{
}
@ -140,14 +141,25 @@ void Service::setupLora(long loraFreq, long bw, int sf, int cr, int pwr, int syn
void Service::setupBt(const String &btName)
{
Serial.print("BT init " + btName + "...");
if (serialBt_.begin(btName)) {
Serial.println("ok");
if (config_.useBLE) {
Serial.print("BLE init " + btName + "...");
if (serialBLE_.begin()) {
Serial.println("ok");
}
else {
Serial.println("failed");
}
}
else
{
Serial.println("failed");
else {
Serial.print("BT init " + btName + "...");
if (serialBt_.begin(btName)) {
Serial.println("ok");
}
else {
Serial.println("failed");
}
}
}
@ -389,22 +401,43 @@ void Service::onRigTxEnd()
void Service::onSerialTx(byte b)
{
serialBt_.write(b);
if (config_.useBLE) {
serialBLE_.write(b);
}
else {
serialBt_.write(b);
}
}
bool Service::onSerialRxHasData()
{
return serialBt_.available();
if (config_.useBLE) {
return serialBLE_.available();
}
else {
return serialBt_.available();
}
}
bool Service::onSerialRx(byte *b)
{
int rxResult = serialBt_.read();
if (rxResult == -1) {
return false;
if (config_.useBLE) {
int rxResult = serialBLE_.read();
if (rxResult == -1) {
return false;
}
*b = (byte)rxResult;
return true;
}
else {
int rxResult = serialBt_.read();
if (rxResult == -1) {
return false;
}
*b = (byte)rxResult;
return true;
}
*b = (byte)rxResult;
return true;
}
void Service::onControlCommand(Cmd cmd, byte value)

Wyświetl plik

@ -8,6 +8,7 @@
#include <endian.h>
#include "BluetoothSerial.h"
#include "ble_serial.h"
#include "ax25_payload.h"
#include "kiss_processor.h"
#include "loraprs_config.h"
@ -107,6 +108,7 @@ private:
// peripherals
BluetoothSerial serialBt_;
BLESerial serialBLE_;
WiFiClient aprsisConn_;
};