/*-------------------------------------- 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. */