kopia lustrzana https://github.com/sh123/esp32_loraprs
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
rodzic
f7028c690b
commit
1df9f4f87a
|
@ -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
|
||||
}
|
|
@ -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
|
1
config.h
1
config.h
|
@ -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"
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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_;
|
||||
};
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue