This commit is contained in:
2025-11-28 18:26:32 -06:00
commit 8bb08d2819
21 changed files with 3309 additions and 0 deletions

102
include/BLE.cpp Normal file
View File

@@ -0,0 +1,102 @@
#include "BLE.hpp"
#include "NimBLEDevice.h"
#include "WiFi.hpp"
bool flag_scan_requested = false;
std::string SSID = "";
std::string password = "";
bool SSIDGiven = false;
bool passGiven = false;
std::string token = "";
bool tokenGiven = false;
// Global pointers to characteristics for notification support
NimBLECharacteristic* ssidListChar = nullptr;
NimBLECharacteristic* connectConfirmChar = nullptr;
NimBLEAdvertising* initBLE() {
NimBLEDevice::init("BlindMaster-C6");
// Optional: Boost power for better range (ESP32-C6 supports up to +20dBm)
NimBLEDevice::setPower(ESP_PWR_LVL_P9);
// Set security
NimBLEDevice::setSecurityAuth(false, false, true); // bonding=false, mitm=false, sc=true (Secure Connections)
NimBLEDevice::setSecurityIOCap(BLE_HS_IO_NO_INPUT_OUTPUT); // No input/output capability
NimBLEServer *pServer = NimBLEDevice::createServer();
pServer->setCallbacks(new MyServerCallbacks());
pServer->advertiseOnDisconnect(true); // Automatically restart advertising on disconnect
NimBLEService *pService = pServer->createService("181C");
// Create all characteristics with callbacks
MyCharCallbacks* charCallbacks = new MyCharCallbacks();
// 0x0000 - SSID List (READ + NOTIFY)
ssidListChar = pService->createCharacteristic(
"0000",
NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::NOTIFY
);
ssidListChar->createDescriptor("2902"); // Add BLE2902 descriptor for notifications
// 0x0001 - SSID (WRITE)
NimBLECharacteristic *ssidChar = pService->createCharacteristic(
"0001",
NIMBLE_PROPERTY::WRITE
);
ssidChar->setCallbacks(charCallbacks);
// 0x0002 - Password (WRITE)
NimBLECharacteristic *passChar = pService->createCharacteristic(
"0002",
NIMBLE_PROPERTY::WRITE
);
passChar->setCallbacks(charCallbacks);
// 0x0003 - Token (WRITE)
NimBLECharacteristic *tokenChar = pService->createCharacteristic(
"0003",
NIMBLE_PROPERTY::WRITE
);
tokenChar->setCallbacks(charCallbacks);
// 0x0004 - SSID Refresh (WRITE)
NimBLECharacteristic *ssidRefreshChar = pService->createCharacteristic(
"0004",
NIMBLE_PROPERTY::WRITE
);
ssidRefreshChar->setCallbacks(charCallbacks);
// 0x0005 - Connect Confirmation (READ + NOTIFY)
connectConfirmChar = pService->createCharacteristic(
"0005",
NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::NOTIFY
);
connectConfirmChar->createDescriptor("2902"); // Add BLE2902 descriptor for notifications
// Start
pService->start();
NimBLEAdvertising *pAdvertising = NimBLEDevice::getAdvertising();
pAdvertising->addServiceUUID("181C");
pAdvertising->setName("BlindMaster-C6");
pAdvertising->enableScanResponse(true);
pAdvertising->setPreferredParams(0x06, 0x12); // Connection interval preferences
pAdvertising->start();
printf("BLE Started. Waiting...\n");
flag_scan_requested = true;
return pAdvertising;
}
void BLEtick(NimBLEAdvertising* pAdvertising) {
if(flag_scan_requested) {
flag_scan_requested = false;
printf("Scanning WiFi...\n");
scanAndUpdateSSIDList();
}
}

77
include/BLE.hpp Normal file
View File

@@ -0,0 +1,77 @@
#ifndef BLE_H
#define BLE_H
#include "NimBLEDevice.h"
extern bool flag_scan_requested;
extern std::string SSID;
extern std::string password;
extern bool SSIDGiven;
extern bool passGiven;
extern std::string token;
extern bool tokenGiven;
// Global pointers to characteristics for notification support
extern NimBLECharacteristic* ssidListChar;
extern NimBLECharacteristic* connectConfirmChar;
class MyServerCallbacks : public NimBLEServerCallbacks {
void onConnect(NimBLEServer* pServer, NimBLEConnInfo& connInfo) {
printf("Client connected\n");
};
void onDisconnect(NimBLEServer* pServer, NimBLEConnInfo& connInfo, int reason) {
printf("Client disconnected - reason: %d\n", reason);
// Advertising will restart automatically
}
};
class MyCharCallbacks : public NimBLECharacteristicCallbacks {
void onWrite(NimBLECharacteristic* pChar, NimBLEConnInfo& connInfo) {
std::string val = pChar->getValue();
std::string uuidStr = pChar->getUUID().toString();
printf("onWrite called! UUID: %s, Value length: %d\n", uuidStr.c_str(), val.length());
// Check which characteristic was written to
if (uuidStr.find("0001") != std::string::npos) {
// SSID characteristic
if (val.length() > 0) {
printf("Received SSID: %s\n", val.c_str());
SSID = val;
SSIDGiven = true;
}
}
else if (uuidStr.find("0002") != std::string::npos) {
// Password characteristic
if (val.length() > 0) {
printf("Received Password: %s\n", val.c_str());
passGiven = true;
password = val;
}
}
else if (uuidStr.find("0003") != std::string::npos) {
// Token characteristic
if (val.length() > 0) {
printf("Received Token: %s\n", val.c_str());
tokenGiven = true;
token = val;
}
}
else if (uuidStr.find("0004") != std::string::npos) {
// Refresh characteristic
printf("Refresh Requested\n");
flag_scan_requested = true;
}
else {
printf("Unknown UUID: %s\n", uuidStr.c_str());
}
}
};
NimBLEAdvertising* initBLE();
void BLEtick(NimBLEAdvertising* pAdvertising);
#endif

37
include/README Normal file
View File

@@ -0,0 +1,37 @@
This directory is intended for project header files.
A header file is a file containing C declarations and macro definitions
to be shared between several project source files. You request the use of a
header file in your project source file (C, C++, etc) located in `src` folder
by including it, with the C preprocessing directive `#include'.
```src/main.c
#include "header.h"
int main (void)
{
...
}
```
Including a header file produces the same results as copying the header file
into each source file that needs it. Such copying would be time-consuming
and error-prone. With a header file, the related declarations appear
in only one place. If they need to be changed, they can be changed in one
place, and programs that include the header file will automatically use the
new version when next recompiled. The header file eliminates the labor of
finding and changing all the copies as well as the risk that a failure to
find one copy will result in inconsistencies within a program.
In C, the convention is to give header files names that end with `.h'.
Read more about using header files in official GCC documentation:
* Include Syntax
* Include Operation
* Once-Only Headers
* Computed Includes
https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html

78
include/WiFi.cpp Normal file
View File

@@ -0,0 +1,78 @@
#include "WiFi.hpp"
#include "esp_wifi.h"
#include "esp_event.h"
#include "cJSON.h" // Native replacement for ArduinoJson
#include "BLE.hpp"
void init_wifi() {
// 1. Init Network Interface
ESP_ERROR_CHECK(esp_netif_init());
ESP_ERROR_CHECK(esp_event_loop_create_default());
esp_netif_create_default_wifi_sta();
// 2. Init WiFi Driver
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
// 3. Set Mode to Station (Client)
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
ESP_ERROR_CHECK(esp_wifi_start());
}
void scanAndUpdateSSIDList() {
printf("Starting WiFi Scan...\n");
// 1. Start Scan (Blocking Mode = true)
// In blocking mode, this function waits here until scan is done (~2 seconds)
wifi_scan_config_t scan_config = {
.ssid = NULL,
.bssid = NULL,
.channel = 0,
.show_hidden = false
};
esp_err_t err = esp_wifi_scan_start(&scan_config, true);
if (err != ESP_OK) {
printf("Scan failed!\n");
return;
}
// 2. Get the results
uint16_t ap_count = 0;
esp_wifi_scan_get_ap_num(&ap_count);
// Limit to 10 networks to save RAM/BLE MTU space
if (ap_count > 10) ap_count = 10;
wifi_ap_record_t *ap_list = (wifi_ap_record_t *)malloc(sizeof(wifi_ap_record_t) * ap_count);
ESP_ERROR_CHECK(esp_wifi_scan_get_ap_records(&ap_count, ap_list));
// 3. Build JSON using cJSON
cJSON *root = cJSON_CreateArray();
for (int i = 0; i < ap_count; i++) {
cJSON *item = cJSON_CreateObject();
// ESP-IDF stores SSID as uint8_t, cast to char*
cJSON_AddStringToObject(item, "ssid", (char *)ap_list[i].ssid);
cJSON_AddNumberToObject(item, "rssi", ap_list[i].rssi);
// Add encryption type if you want (optional)
cJSON_AddNumberToObject(item, "auth", ap_list[i].authmode);
cJSON_AddItemToArray(root, item);
}
// 4. Convert to String
char *json_string = cJSON_PrintUnformatted(root); // Compact JSON
printf("JSON: %s\n", json_string);
// 5. Update BLE
if (ssidListChar != nullptr) {
ssidListChar->setValue(std::string(json_string));
ssidListChar->notify();
}
// 6. Cleanup Memory (CRITICAL in C++)
free(ap_list);
cJSON_Delete(root); // This deletes all children (items) too
free(json_string); // cJSON_Print allocates memory, you must free it
}

7
include/WiFi.hpp Normal file
View File

@@ -0,0 +1,7 @@
#ifndef WIFI_H
#define WIFI_H
void init_wifi();
void scanAndUpdateSSIDList();
#endif

38
include/defines.h Normal file
View File

@@ -0,0 +1,38 @@
#ifndef DEFINES_H
#define DEFINES_H
#define ccwSpeed 6500
#define cwSpeed 3300
#define offSpeed 4900
#define ccwMax 10
#define cwMax 0
#define getMovingCW(port) ((movingCW & (1 << port)) >> port)
#define setMovingCW(port) (movingCW |= (1 << port))
#define clearMovingCW(port) (movingCW &= ~(1 << port))
#define getMovingCCW(port) ((movingCCW & (1 << port)) >> port)
#define setMovingCCW(port) (movingCCW |= (1 << port))
#define clearMovingCCW(port) (movingCCW &= ~(1 << port))
#define getCalibCW(port) ((calibCW & (1 << port)) >> port)
#define setCalibCW(port) (calibCW |= (1 << port))
#define clearCalibCW(port) (calibCW &= ~(1 << port))
#define getCalibCCW(port) ((calibCCW & (1 << port)) >> port)
#define setCalibCCW(port) (calibCCW |= (1 << port))
#define clearCalibCCW(port) (calibCCW &= ~(1 << port))
#define getCalibDone(port) ((calibDone & (1 << port)) >> port)
#define setCalibDone(port) (calibDone |= (1 << port))
#define clearCalibDone(port) (calibDone &= ~(1 << port))
#define getBlocked(port) ((blocked & (1 << port)) >> port)
#define setBlocked(port) (blocked |= (1 << port))
#define clearBlocked(port) (blocked &= ~(1 << port))
#define getPos10(port) ((movingCCW & (1 << (port + 4))) >> (port + 4))
#define setPos10(port) (movingCCW |= (1 << (port + 4)))
#define clearPos10(port) (movingCCW &= ~(1 << (port + 4)))
#define getPos0(port) ((movingCW & (1 << (port + 4))) >> (port + 4))
#define setPos0(port) (movingCW |= (1 << (port + 4)))
#define clearPos0(port) (movingCW &= ~(1 << (port + 4)))
#define prefNameCalibs "periph_info_"
#endif

30
include/pwm.c Normal file
View File

@@ -0,0 +1,30 @@
#include "driver/ledc.h"
#include "defines.h"
void init_servo_PWM(void) {
ledc_timer_config_t ledc_timer = {
.speed_mode = LEDC_LOW_SPEED_MODE,
.timer_num = LEDC_TIMER_0,
.duty_resolution = LEDC_TIMER_16_BIT,
.freq_hz = 50,
.clk_cfg = LEDC_AUTO_CLK
};
ESP_ERROR_CHECK(ledc_timer_config(&ledc_timer));
ledc_channel_config_t ledc_channel = {
.speed_mode = LEDC_LOW_SPEED_MODE,
.channel = LEDC_CHANNEL_0,
.timer_sel = LEDC_TIMER_0,
.intr_type = LEDC_INTR_DISABLE,
.gpio_num = 0, // Using pin D0 for servo.
.duty = offSpeed, // Start off
.hpoint = 0
};
ESP_ERROR_CHECK(ledc_channel_config(&ledc_channel));
}
void set_servo_speed(int channel, uint32_t duty) {
// duty input should be between 0 and 65535
ledc_set_duty(LEDC_LOW_SPEED_MODE, (ledc_channel_t)channel, duty);
ledc_update_duty(LEDC_LOW_SPEED_MODE, (ledc_channel_t)channel);
}

7
include/pwm.h Normal file
View File

@@ -0,0 +1,7 @@
#ifndef PWM_H
#define PWM_H
void init_servo_PWM(void);
void set_servo_speed(int channel, int speed);
#endif