├── 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 |
--------------------------------------------------------------------------------