├── LINE_Beacon └── LINE_Beacon.ino └── README.md /LINE_Beacon/LINE_Beacon.ino: -------------------------------------------------------------------------------- 1 | #include "bt.h" 2 | #include "esp_gap_ble_api.h" 3 | 4 | static const uint8_t HWID[5] = {0xff, 0xff, 0xff, 0xff, 0xff};// ผูก Hardware ID 5 | static const uint8_t ADC_PIN = 35; // 電圧入力ピン 6 | static const float R1 = 4000.0; 7 | static const float R2 = 2000.0; 8 | 9 | static const uint16_t UUID_FOR_LINECORP = 0xFE6F; 10 | static const uint8_t MAX_SIMPLEBEACON_DEVICEMESSAGE_SIZE = 13; 11 | 12 | static uint8_t deviceMessageSize = 1; 13 | static uint8_t deviceMessage[MAX_SIMPLEBEACON_DEVICEMESSAGE_SIZE]; 14 | 15 | static const uint8_t MAX_BLE_ADVERTISING_DATA_SIZE = 31; 16 | static const uint16_t HCI_LE_Set_Advertising_Data = (0x08 << 10) | 0x0008; 17 | static const uint16_t HCI_LE_Set_Advertising_Enable = (0x08 << 10) | 0x000A; 18 | 19 | 20 | static void _dump(const char * title, uint8_t *data, size_t dataSize) { 21 | Serial.printf("%s [%d]:", title, dataSize); 22 | for (size_t i = 0; i < dataSize; i++) { 23 | Serial.printf(" %02x", data[i]); 24 | } 25 | Serial.println(); 26 | } 27 | 28 | static void putUint8(uint8_t** bufferPtr, uint8_t data) { 29 | *(*bufferPtr)++ = data; 30 | } 31 | 32 | static void putUint16LE(uint8_t** bufferPtr, uint16_t data) { 33 | *(*bufferPtr)++ = lowByte(data); 34 | *(*bufferPtr)++ = highByte(data); 35 | } 36 | 37 | static void putArray(uint8_t** bufferPtr, const void* data, size_t dataSize) { 38 | memcpy(*bufferPtr, data, dataSize); 39 | (*bufferPtr) += dataSize; 40 | } 41 | 42 | // HCIを使い、指定されたopCode、dataのコマンドをBluetooth Controllerに書き込みます 43 | static void executeBluetoothHCICommand(uint16_t opCode, const uint8_t * hciData, uint8_t hciDataSize) { 44 | uint8_t buf[5 + MAX_BLE_ADVERTISING_DATA_SIZE]; //uint8_t buf[4 + MAX_BLE_ADVERTISING_DATA_SIZE]; แก้ไขเพื่อแก้เรื่อง fix for Stack overflow 45 | uint8_t* bufPtr = buf; 46 | 47 | putUint8(&bufPtr, 1);// 1 = H4_TYPE_COMMAND 48 | putUint16LE(&bufPtr, opCode); 49 | putUint8(&bufPtr, hciDataSize); 50 | putArray(&bufPtr, hciData, hciDataSize); 51 | 52 | uint8_t bufSize = bufPtr - buf; 53 | 54 | while (!esp_vhci_host_check_send_available()); 55 | esp_vhci_host_send_packet(buf, bufSize); 56 | } 57 | 58 | static void updateSimpleBeaconDeviceMessage(char dm[], int dmsize) { 59 | memset(deviceMessage, 0x00, MAX_SIMPLEBEACON_DEVICEMESSAGE_SIZE); 60 | uint8_t* deviceMessagePtr = deviceMessage; 61 | 62 | 63 | 64 | const uint8_t voltageStringSize = dmsize - 1; 65 | char voltageString[voltageStringSize]; 66 | 67 | 68 | //snprintf(voltageString, voltageStringSize, "V=%f", dm); 69 | //putArray(&deviceMessagePtr, voltageString, voltageStringSize); 70 | putArray(&deviceMessagePtr, dm, voltageStringSize); 71 | //deviceMessageSize = deviceMessagePtr - deviceMessage; 72 | deviceMessageSize = 13; 73 | 74 | } 75 | 76 | 77 | static void updateAdvertisingData() { 78 | 79 | uint8_t data[MAX_BLE_ADVERTISING_DATA_SIZE]; 80 | uint8_t* dataPtr = data; 81 | 82 | { 83 | // flag 84 | putUint8(&dataPtr, 1 + 1); 85 | putUint8(&dataPtr, ESP_BLE_AD_TYPE_FLAG); 86 | putUint8(&dataPtr, ESP_BLE_ADV_FLAG_GEN_DISC | ESP_BLE_ADV_FLAG_BREDR_NOT_SPT); 87 | } 88 | { 89 | // complete list of service uuid 90 | putUint8(&dataPtr, 1 + 2); 91 | putUint8(&dataPtr, ESP_BLE_AD_TYPE_16SRV_CMPL); 92 | putUint16LE(&dataPtr, UUID_FOR_LINECORP); 93 | } 94 | { 95 | // simple beacon 96 | putUint8(&dataPtr, 1 + 9 + deviceMessageSize); 97 | putUint8(&dataPtr, ESP_BLE_AD_TYPE_SERVICE_DATA); 98 | putUint16LE(&dataPtr, UUID_FOR_LINECORP); 99 | putUint8(&dataPtr, 0x02); // frame type 100 | putArray(&dataPtr, HWID, 5); 101 | putUint8(&dataPtr, 0x7F); // measured txpower 102 | putArray(&dataPtr, deviceMessage, deviceMessageSize); 103 | } 104 | 105 | uint8_t dataSize = dataPtr - data; 106 | _dump("simple beacon", data, dataSize); 107 | 108 | uint8_t hciDataSize = 1 + MAX_BLE_ADVERTISING_DATA_SIZE; 109 | uint8_t hciData[hciDataSize]; 110 | 111 | hciData[0] = dataSize; 112 | memcpy(hciData + 1, data, dataSize); 113 | 114 | executeBluetoothHCICommand(HCI_LE_Set_Advertising_Data, hciData, hciDataSize); 115 | } 116 | 117 | static void enableBluetoothAdvertising() { 118 | uint8_t enable = 1; 119 | executeBluetoothHCICommand(HCI_LE_Set_Advertising_Enable, &enable, 1); 120 | } 121 | 122 | 123 | 124 | static void notifyHostSendAvailableHandler() { 125 | // _dump("notify_host_send_available", NULL, 0); 126 | } 127 | static int notifyHostRecvHandler(uint8_t *data, uint16_t len) { 128 | // _dump("notify_host_recv", data, len); 129 | return 0; 130 | } 131 | 132 | static esp_vhci_host_callback_t vhciHostCallback = { 133 | notifyHostSendAvailableHandler, 134 | notifyHostRecvHandler 135 | }; 136 | 137 | 138 | void setup() { 139 | Serial.begin(115200, SERIAL_8N1); 140 | 141 | // 互換性を考慮し、ESP32のデフォルト値で上書きする 142 | analogSetAttenuation(ADC_11db); 143 | analogReadResolution(12); 144 | 145 | // bluetoothを初期化 146 | btStart(); 147 | esp_vhci_host_register_callback(&vhciHostCallback); 148 | enableBluetoothAdvertising(); 149 | } 150 | 151 | void loop() { 152 | 153 | // 12bit幅(0...4095)で電圧を取得。4095が最大電圧(ADC_11dbなので3.9V)を表します 154 | uint16_t analog12bit = analogRead(ADC_PIN); 155 | 156 | // 分圧前の電源電圧を計算 157 | float voltage = analog12bit / 4095.0 * 3.9 * (R1 + R2) / R2; 158 | 159 | Serial.printf("analogRead: %d, voltage: %f", analog12bit, voltage); 160 | Serial.println(); 161 | 162 | char dm[] = "Hello World"; 163 | int dm_size = sizeof(dm) / sizeof(dm[0]);; 164 | Serial.println(dm_size); 165 | updateSimpleBeaconDeviceMessage(dm, dm_size); 166 | //updateSimpleBeaconDeviceMessage(voltage); 167 | updateAdvertisingData(); 168 | 169 | delay(5000); 170 | } 171 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # LINE_Simple_Beacon_ESP32 2 | Arduino code for LINE Simple Beacon work with ESP32 3 | 4 | ## Prerequisites 5 | * [Create a channel on the LINE Developers console](https://developers.line.me/en/docs/line-login/getting-started/) 6 | * [Install Arduino IDE](https://www.arduino.cc/en/main/software) 7 | 8 | ## Setup 9 | * Install ESP32s Boards Manager 10 | * Preferences > Additional Boards Manager URLs > add 11 | ``` 12 | 'https://dl.espressif.com/dl/package_esp32_index.json' 13 | ``` 14 | * Tools > Boards Manager > search 'esp32' > Install 15 | * [Issue LINE Simple Beacon Hardware ID](https://admin-official.line.me/beacon/register) 16 | 17 | 18 | 19 | 20 | ## Steps 21 | * Update Hardware ID 22 | * [Adjust the signal length](https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/bluetooth/controller_vhci.html?highlight=esp_ble_tx_power_set#_CPPv220esp_ble_tx_power_set20esp_ble_power_type_t17esp_power_level_t) 23 | ``` 24 | esp_ble_tx_power_set(ESP_BLE_PWR_TYPE_ADV, adjust the power level that you want); 25 | ``` 26 | * Power level 27 | * -12dbm ~ 5-10m 28 | * -9dbm ~ 10-12m 29 | * -6dbm ~ 13-18m 30 | * -3dbm ~ 30-40m 31 | * 0dbm ~ 50m 32 | * 3dbm ~ 80m 33 | * Upload the code to hardware 34 | 35 | ## Reference 36 | * https://github.com/godda/LINE_Simple_Beacon_ESP32 37 | * https://medium.com/@chawanwitpoolsri/line-beacon-from-esp32-node32-lite-72c0fc7dc646 38 | * https://engineering.linecorp.com/ja/blog/detail/149/ 39 | * https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/bluetooth/index.html 40 | --------------------------------------------------------------------------------