commit 6ae01a08097812a75e1724f6ab9e963c09252f2c Author: dj99k Date: Wed Jul 22 23:42:16 2026 +0900 2026-07-22 BLE UART1(GPIO20(TX), GPIO21(RX)) ---> CSC Check ---> SEND BLE ---> Adroid BLE 수신. diff --git a/BLE_Uart1_CSC_Notify.ino b/BLE_Uart1_CSC_Notify.ino new file mode 100644 index 0000000..11289e3 --- /dev/null +++ b/BLE_Uart1_CSC_Notify.ino @@ -0,0 +1,217 @@ +/*-------------------------------------- +2026-07-22 PAYLOAD + +----------------------------------------*/ + +#include +#include +#include +#include + +#define LED_PIN1 8 // 수신 데이터에 따라 제어할 LED ESP32-C3 +#define LED_PIN2 7 // BLE 연결 상태 표시 LED + +BLEServer *pServer = NULL; +BLECharacteristic *pTxCharacteristic; // ESP32 -> Central (Notify) +BLECharacteristic *pRxCharacteristic; // Central -> ESP32 (Write) + +bool deviceConnected = false; +bool oldDeviceConnected = false; + +// Nordic UART UUID 세트 +#define SERVICE_UUID "6E400001-B5A3-F393-E0A9-E50E24DCCA9E" +#define CHARACTERISTIC_UUID_RX "6E400002-B5A3-F393-E0A9-E50E24DCCA9E" +#define CHARACTERISTIC_UUID_TX "6E400003-B5A3-F393-E0A9-E50E24DCCA9E" + +// UART1 객체 생성 (USB CDC 대신 GPIO20/21 사용) +HardwareSerial MySerial(1); + + +// --- CSC 계산 관련 함수 --- +char nibbleToAscii(uint8_t nibble) { + return (nibble < 10) ? ('0' + nibble) : ('A' + (nibble - 10)); +} + +String calcChecksum(String data) { + uint32_t sum = 0; + for (int i = 0; i < data.length(); i++) { + sum += (uint8_t)data[i]; + } + uint8_t oneByte = sum & 0xFF; + + char csc[3]; + csc[0] = nibbleToAscii((oneByte >> 4) & 0x0F); + csc[1] = nibbleToAscii(oneByte & 0x0F); + csc[2] = '\0'; + + return String(csc); +} + +String verifyPacket(String cmd, String len, String payload, String recvCsc) { + String body = cmd + len + payload; + String calcCsc = calcChecksum(body); + return (calcCsc == recvCsc) ? "True" : "Fault"; +} + +// --- BLE 서버 콜백 --- +class MyServerCallbacks : public BLEServerCallbacks { + void onConnect(BLEServer* pServer) { + deviceConnected = true; + }; + void onDisconnect(BLEServer* pServer) { + deviceConnected = false; + } +}; + +// --- BLE RX 콜백 --- +class MyCallbacks : public BLECharacteristicCallbacks { + void onWrite(BLECharacteristic *pCharacteristic) { + String rxValue = pCharacteristic->getValue(); + if (rxValue.length() > 0) { + Serial.print("BLE Rx: "); + Serial.println(rxValue); + + // UART1로 에코 + MySerial.print("Echo to UART: "); + MySerial.println(rxValue); + + digitalWrite(LED_PIN1, HIGH); // test LED + delay(500); + digitalWrite(LED_PIN1, LOW); + } + } +}; + +void setup() { + Serial.begin(115200); //USB to Serial Port + // while (!Serial) { ; } + // UART1 초기화 (GPIO20=RX, GPIO21=TX) + MySerial.begin(115200, SERIAL_8N1, 20, 21); + + // LED 핀 설정 + pinMode(LED_PIN1, OUTPUT); + pinMode(LED_PIN2, OUTPUT); + digitalWrite(LED_PIN1, HIGH); + digitalWrite(LED_PIN2, HIGH); + + // BLE 초기화 + BLEDevice::init("MMS UART"); + pServer = BLEDevice::createServer(); + pServer->setCallbacks(new MyServerCallbacks()); + + BLEService *pService = pServer->createService(SERVICE_UUID); + + pTxCharacteristic = pService->createCharacteristic( + CHARACTERISTIC_UUID_TX, + BLECharacteristic::PROPERTY_NOTIFY + ); + pTxCharacteristic->addDescriptor(new BLE2902()); + + pRxCharacteristic = pService->createCharacteristic( + CHARACTERISTIC_UUID_RX, + BLECharacteristic::PROPERTY_WRITE + ); + pRxCharacteristic->setCallbacks(new MyCallbacks()); + + pService->start(); + pServer->getAdvertising()->start(); + Serial.println("Waiting a client connection to notify..."); +} + +void loop() { + if (deviceConnected) { + digitalWrite(LED_PIN2, LOW); + + // UART1에서 들어온 데이터를 BLE로 전송 + if (MySerial.available() > 0) { + String uartData = MySerial.readStringUntil('\n'); + uartData.trim(); + + if (uartData.length() > 7) { + Serial.print("UART Rx(BLE SEND): "); + Serial.println(uartData); + + // 파싱: CMD(1) + LEN(4) + PAYLOAD + CSC(2) + String cmd = uartData.substring(0, 1); + String len = uartData.substring(1, 5); + String payload = uartData.substring(5, uartData.length() - 2); + String recvCsc = uartData.substring(uartData.length() - 2); + + Serial.print("CMD: "); Serial.println(cmd); + Serial.print("LEN: "); Serial.println(len); + Serial.print("PAYLOAD: "); Serial.println(payload); + Serial.print("Recv CSC: "); Serial.println(recvCsc); + + String result = verifyPacket(cmd, len, payload, recvCsc); + Serial.print("CSC Verify Result: "); + Serial.println(result); + + if (result == "True") { + // LED ON + digitalWrite(LED_PIN1, HIGH); + + // BLE Notify 전송 (True일 때만) + pTxCharacteristic->setValue(uartData.c_str()); + pTxCharacteristic->notify(); + Serial.println("Sent to BLE (Notify)."); + + delay(500); + digitalWrite(LED_PIN1, LOW); + } else { + // Fault일 경우 데이터 버림, LED OFF + Serial.println("Fault detected, data discarded."); + digitalWrite(LED_PIN1, HIGH); + delay(100); + digitalWrite(LED_PIN1, LOW); + delay(100); + digitalWrite(LED_PIN1, HIGH); + delay(100); + digitalWrite(LED_PIN1, LOW); + } + } + } + } else { + digitalWrite(LED_PIN2, HIGH); + } + + if (!deviceConnected && oldDeviceConnected) { + delay(500); + pServer->startAdvertising(); + Serial.println("start advertising"); + oldDeviceConnected = deviceConnected; + } + + if (deviceConnected && !oldDeviceConnected) { + digitalWrite(LED_PIN1, HIGH); + delay(500); + digitalWrite(LED_PIN1, LOW); + delay(500); + digitalWrite(LED_PIN1, HIGH); + delay(500); + digitalWrite(LED_PIN1, LOW); + oldDeviceConnected = deviceConnected; + } + + delay(10); +} + + +/* +방금 올려주신 BLE/UART 브리지 코드에 UART 수신 데이터 CSC 검증을 그대로 적용한 버전을 준비했습니다. +이제 시리얼로 입력된 패킷을 구조로 파싱하고, CSC가 맞으면 "True", 틀리면 "Fault"를 출력하며 LED1 상태도 반영합니다. + CSC 계산 함수(calcChecksum)와 검증 함수(verifyPacket) 추가. + loop()에서 UART 수신 시 패킷을 파싱하고 CSC 검증 수행. + 결과 "True"/"Fault"를 시리얼 출력. + LED1은 "True"일 때 ON, "Fault"일 때 OFF. + BLE Notify는 원본 UART 데이터를 그대로 전송. + + +Fault 일떄는 데이터를 버리고, 다음 데이터 수신하여 true이면 ble로 전송하도록 할 것 + -> CSC 검증 후 "Fault"일 경우: + BLE 전송 하지 않음. + 데이터 버림. + LED1 OFF. + "True"일 경우: + BLE Notify 전송. + LED1 ON. +*/ \ No newline at end of file