Skip to content

Commit

Permalink
refactor sample
Browse files Browse the repository at this point in the history
  • Loading branch information
felipengeletrica committed May 28, 2024
1 parent a9746c1 commit fe370ea
Show file tree
Hide file tree
Showing 4 changed files with 219 additions and 11 deletions.
2 changes: 2 additions & 0 deletions examples/esp32-BLE/platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,5 @@ platform = espressif32
board = wemos_d1_mini32
framework = arduino
monitor_speed = 115200

lib_deps = bblanchon/ArduinoJson@^7.0.4
77 changes: 66 additions & 11 deletions examples/esp32-BLE/src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,31 @@
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>
#include <BLECharacteristic.h>
#include <BLEUUID.h>
#include <ArduinoJson.h>

/* CONSTANTS */
// Hardware Serial 2 pins
#define TIMER_INTERRUPT_US 1000000
#define SERVICE_UUID "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"
#define RXD2 6
#define TXD2 7
#define SIZE_BUFFER 2048
#define BUFFER_JSON SIZE_BUFFER
#define UUID \
String((uint32_t)ESP.getEfuseMac()) + \
String((uint32_t)(ESP.getEfuseMac() >> 32))
#define DEVICE_ID String("belfast_test")
/* VARIABLES */
uint64_t uptime = 0;
// Handle do timer
esp_timer_handle_t timer_handle;
BLEServer *pServer;
BLECharacteristic *pCharacteristic;
bool deviceConnected = false;

#define SERVICE_UUID "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"

class MyServerCallbacks : public BLEServerCallbacks {
void onConnect(BLEServer *pServer) {
deviceConnected = true;
Expand All @@ -21,17 +38,27 @@ class MyServerCallbacks : public BLEServerCallbacks {
}
};


/**
* @brief Interrupt
*
* @param arg
*/
void timer_callback(void* arg) {
uptime++;
}

void setup() {
Serial.begin(115200);

BLEDevice::init("ESP32 BLE Example");
BLEDevice::init("ESP32 BLE Belfast");
pServer = BLEDevice::createServer();
pServer->setCallbacks(new MyServerCallbacks());

BLEService *pService = pServer->createService(SERVICE_UUID);
pCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID,
BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_WRITE
BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_WRITE | BLECharacteristic::PROPERTY_NOTIFY
);

pCharacteristic->addDescriptor(new BLE2902());
Expand All @@ -40,18 +67,46 @@ void setup() {
BLEAdvertising *pAdvertising = pServer->getAdvertising();
pAdvertising->start();

// Configuração do timer
esp_timer_create_args_t timer_args;
timer_args.callback = &timer_callback;
timer_args.arg = NULL;
timer_args.dispatch_method = ESP_TIMER_TASK;
timer_args.name = "periodic_timer";

// Criar e iniciar o timer
esp_timer_create(&timer_args, &timer_handle);
esp_timer_start_periodic(timer_handle, TIMER_INTERRUPT_US);

// Configurar MTU
BLEDevice::setMTU(SIZE_BUFFER);

Serial.println("START BLE SAMPLE");
}

void loop() {
if (deviceConnected) {
// Do something when device is connected
String dataToSend = "Hello, World!";
// Create JSON object
DynamicJsonDocument doc(BUFFER_JSON);

pCharacteristic->setValue(dataToSend.c_str());
pCharacteristic->notify();
// Fill JSON object with data
doc["device_id"] = DEVICE_ID;
doc["serial"] = UUID;
doc["protocol_id"] = "0.1.0";
doc["hw_ver"] = "hardware_version";
doc["fw_ver"] = "firmware_version";
doc["up_time"] = uptime;

Serial.println(dataToSend);
delay(1000);
// Convert JSON object to string
String jsonString;
serializeJson(doc, jsonString);

// Send JSON data via Serial
Serial.println(jsonString);

pCharacteristic->setValue(jsonString.c_str());
pCharacteristic->notify();
Serial.println(jsonString);
delay(100);
}
}
135 changes: 135 additions & 0 deletions src/interface/BLEConnectorToMQTT.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
import threading
import json
import datetime
from bluepy.btle import UUID, Peripheral, DefaultDelegate
from queue import Queue
from src.interface.mqtt_manager import MqttManager
import logging

# Configure logging
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(levelname)s %(message)s')
logger = logging.getLogger(__name__)

debug = False

# UUIDs
SERVICE_UUID = "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
CHARACTERISTIC_UUID = "beb5483e-36e1-4688-b7f5-ea07361b26a8"
# BLE BUFFER
BLE_BUFFER = 2048


class DelegateBT(DefaultDelegate):
def __init__(self, data_queue):
super().__init__()
self.data_queue = data_queue

def handleNotification(self, cHandle, data):
self.data_queue.put(data)


class BLEConnectorToMQTT(threading.Thread):
def __init__(self, device_name, server_mqtt, timeout):
threading.Thread.__init__(self)
self.device_name = device_name
self.service_uuid = SERVICE_UUID
self.characteristic_uuid = CHARACTERISTIC_UUID
self.mac_address = None
self.timeout = timeout

self.mqtt_manager = MqttManager(
username=server_mqtt['username'],
password=server_mqtt['password'],
server=server_mqtt['server'],
port=server_mqtt['port'],
client='client1',
subscribe_upstream=server_mqtt['subscribe-upstream'],
subscribe_downstream=server_mqtt['subscribe-downstream'],
on_message_callback=self.senddata
)

self.subscribe_upstream = server_mqtt['subscribe-upstream']
self.subscribe_downstream = server_mqtt['subscribe-downstream']
self.data_queue = Queue()

def run(self, mac_address):
self.mac_address = mac_address
self.mqtt_manager.run()
self._process = threading.Thread(target=self._process)
self._process.daemon = True
self._process.start()
self._data_processor = threading.Thread(target=self._process_data)
self._data_processor.daemon = True
self._data_processor.start()

def _process(self):
while True:
try:
logger.info("MAC: " + self.mac_address)
peripheral = Peripheral(self.mac_address)
peripheral.setDelegate(DelegateBT(self.data_queue))

# Set MTU size
peripheral.setMTU(BLE_BUFFER)

service = peripheral.getServiceByUUID(UUID(self.service_uuid))
characteristic = service.getCharacteristics(UUID(self.characteristic_uuid))[0]

# Enable notifications
peripheral.writeCharacteristic(characteristic.getHandle() + 1, b"\x01\x00", withResponse=True)

while True:
if peripheral.waitForNotifications(self.timeout):
continue
except Exception as e:
logger.error(f"Error in _process: {e}")
finally:
try:
peripheral.disconnect()
except Exception as e:
logger.error(f"Error disconnecting: {e}")

def _process_data(self):
while True:
data = self.data_queue.get()
self.handle_data(data)

def handle_data(self, data):
try:
# First verification json
if len(data) and "{" in data.decode() and ":" in data.decode():
try:
logger.debug(f'raw: {data}')
json_obj = json.loads(data.decode())
metadata = {"timestamp": str(datetime.datetime.now())}
payload = {"gateway_meta": metadata, "data": json_obj}
payload_dumps = json.dumps(payload)
self.mqtt_manager.publish(self.subscribe_upstream, payload_dumps)
if debug:
logger.debug(f'{payload_dumps} [{str(datetime.datetime.now())}]')
except json.JSONDecodeError:
logger.warning("Invalid json")
except Exception as error:
logger.exception(f"exception data: {error}")

def senddata(self, message_content):
try:
if self.serialstate():
try:
if isinstance(message_content, dict):
if 'raw' in message_content:
raw_value = message_content.get("raw")
self.s.write(raw_value.encode())
logger.info(f"Message RAW via serial: {raw_value}")
else:
message_json = json.dumps(message_content)
self.s.write(message_json.encode())
logger.info("Sent via serial: %s", message_content)
else:
logger.warning("message_content is not a dictionary.")
except Exception as error:
logger.exception("Error sending data via serial: %s", error)
else:
logger.warning("Serial connection is not open.")
except Exception as error:
logger.exception("Error sending data via serial: %s", error)
16 changes: 16 additions & 0 deletions src/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
from src.interface.SerialToMQTT import SerialToMQTT
from src.interface.BluetoothGpsAgrinavi import BluetoothGpsAgrinavi
from src.interface.BLEConnector import BLEConnector
from src.interface.BLEConnectorToMQTT import import BLEConnectorToMQTT

# endregion

Expand Down Expand Up @@ -100,6 +101,21 @@ def init_data_instances(datajson):
devs[index].run(
mac_address=devices[index]['mac-address']
)
elif "bluetooth-BLE-to-mqtt" == devices[index]['interface']:
server_mqtt = datajson["server_mqtt"]
if server_mqtt is None:
Exception("Server MQTT not configured")

devs.append(
BLEConnector(
device_name=devices[index]['description'],
server_mqtt=server_mqtt,
timeout=devices[index]['samplingSeconds'],
)
)
devs[index].run(
mac_address=devices[index]['address']
)
else:
Exception("Invalid device")
a = 1
Expand Down

0 comments on commit fe370ea

Please sign in to comment.