# 04-25 Refactor BLE Scan and HTTP
The program is a monolith, where BLE and HTTP code are heavily interlinked. The program runs on a single thread and does not manage tasks well. This leads to memory allocation issues and fatal errors.
# Problems
# WifiClientSecure uses too much memory
WifiClientSecure doesnt work work when invoked from the onDeviceDiscovery() callback. The good news though is that this time the issue is different. The mbedTLS module of the WifiClientSecure uses a lot of memory for the ssl encrypted tcp stream. The heap size of the ESP32 is 160kb and mbedTLS uses 70kb of that at runtime.. When the BLE Scanner is still in memory, there is not a lot of space left in the heap.
Here is the verbose version of the core debugging output:

The HttpManager tries to default initialize a new WifiClientSecure object and then fails. It does not cause a fatal error but it just catches an exception.
After figuring this out, I switched to plain HTTP without SSL and encountered the follow-up problem:
# Program crashes on non-secured WifiClient calls
When using unencrypted TCP, the program causes the following fatal error:
Device found: 24:6f:28:7a:48:2e
storing measurements
attempting post COMMENT BY MARK: CALL TO HttpManager::POST()
E (10132) task_wdt: Task watchdog got triggered. The following tasks did not reset the watchdog in time:
E (10132) task_wdt: - IDLE0 (CPU 0)
E (10132) task_wdt: Tasks currently running:
E (10132) task_wdt: CPU 0: Btc_task COMMENT BY MARK: Bluetooth stack running
E (10132) task_wdt: CPU 1: IDLE1 COMMENT BY MARK: Second core is idle
E (10132) task_wdt: Aborting.
abort() was called at PC 0x400e01db on core 0
The program crashes before it can potentially encounter memory issues because the task watchdog interrupts the program shortly after the call to the HttpManager. Here is a description of what the TWDT prevents:
"The TWDT is responsible for detecting instances of tasks running without yielding for a prolonged period. his is a symptom of CPU starvation and is usually caused by a higher priority task looping without yielding to a lower-priority task thus starving the lower priority task from CPU time. This can be an indicator of poorly written code that spinloops on a peripheral, or a task that is stuck in an infinite loop." Link to source
The Scanner is not stopped on device discovery. Sequence does not destroy scanner object or interrupt scanner instance and it continues to use CPU cycles.
# Solutions
# Try to allocate more RAM to the app
It appears that only 320 kb seems of the available 520kb are being allocated to my program. Perhaps there is a way to allocate more resources to it, same as when I did the storage issue in here. Something like this function would maybe work to get more heap space for the program at runtime.
# Create FreeRTOS tasks
In this document, it becomes clear that there is a lot of room for optimizations in my code. To fully take advantage of the DRAM pool, I can create tasks that have their own heaps. The ESP32 is a dual core system. Currently I only use a single core for my program. In the debug log down below of my program, it is clear that the second core (cpu 1) is sitting idle while the Bluetooth task is doing all the work.
E (10132) task_wdt: - IDLE0 (CPU 0)
E (10132) task_wdt: Tasks currently running:
E (10132) task_wdt: CPU 0: Btc_task
E (10132) task_wdt: CPU 1: IDLE1
Using tasks I can assign the BLE functionality to core 0 and move the measurement processing and uploading threads to core 1. This should actually even allow for uninterrupted measurement collection that I wanted to approximate by using async http. Tasks would make concurrency like this fully possible.
# Fully switch to BLE connections instead of relying on Scanner callbacks
Consider my current algorithm:
The scanner is loaded into RAM and then on device discovery it tells the measurentWebservice to manage uploading of a result. The measurementWebservice is responsible for locally persisting the scan results. The BLE Scan task runs indefinetely and has the measurementWebservice, HttpManager and all their objects in the same stack and heap. This is really stupid for reasons stated above in detail (One task can only use 160Kb of at least 320Kb available DRAM). The measurementWebservice is tied to the scanner because it holds the private data member that stores the upload queue. It calls its own store member function when scanResults
These are my proposed changes:
The main difference to the existing algorithm is that I separate the logical parts of the program. The BLE part of the program is not bound to the HTTP part of the program. They are distinct and separate in code and in runtime memory.
Objects can be destroyed when the program no longer needs them (Scanner object should not be involved in the http upload process). As soon as the Scanner stops, the scan results can be deleted and the the scanner object destroyed. This frees up DRAM for the SSL client.
# Switch to RPi
If it becomes evident that the hardware is bottlenecking my project on the BLE Client side, I can always switch to a raspberry pi. It probably wouldnt be incredibly hard to switch, since the C++ headers can be modified to use the interfaces of raspbian.