Showing 4 changed files with 260 additions and 0 deletions
+123
BLE_iBeacon.ino
... ...
@@ -0,0 +1,123 @@
1
+/*
2
+   Based on Neil Kolban example for IDF: https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLE%20Tests/SampleScan.cpp
3
+   Ported to Arduino ESP32 by pcbreflux
4
+*/
5
+
6
+
7
+/*
8
+   Create a BLE server that will send periodic iBeacon frames.
9
+   The design of creating the BLE server is:
10
+   1. Create a BLE Server
11
+   2. Create advertising data
12
+   3. Start advertising.
13
+   4. wait
14
+   5. Stop advertising.
15
+   6. deep sleep
16
+
17
+*/
18
+#include <heltec.h>
19
+#include "sys/time.h"
20
+
21
+#include "BLEDevice.h"
22
+#include "BLEUtils.h"
23
+#include "BLEBeacon.h"
24
+#include "esp_bt_device.h"
25
+
26
+#include "beacon.h"
27
+#include "display.h"
28
+#include "button.h"
29
+
30
+BLEAdvertising *pAdvertising;
31
+
32
+
33
+//-----------------------------------------------------------------------------------
34
+
35
+
36
+void setBeacon() {
37
+  BLEBeacon oBeacon = BLEBeacon();
38
+  oBeacon.setManufacturerId(0x4C00); // fake Apple 0x004C LSB (ENDIAN_CHANGE_U16!)
39
+  oBeacon.setProximityUUID(BLEUUID(BEACON_UUID));
40
+  oBeacon.setMajor(0);
41
+  oBeacon.setMinor(0);
42
+  BLEAdvertisementData oAdvertisementData = BLEAdvertisementData();
43
+  BLEAdvertisementData oScanResponseData = BLEAdvertisementData();
44
+  oAdvertisementData.setFlags(0x04); // BR_EDR_NOT_SUPPORTED 0x04
45
+  oAdvertisementData.setCompleteServices(BLEUUID(BEACON_SERVICE_UUID));
46
+
47
+  memcpy(&advertising_data[AD_IDX_NAMESPACE], beacon_namespace, 10);
48
+  memcpy(&advertising_data[AD_IDX_INSTANCE], beacon_inst, 3);
49
+  advertising_data[AD_IDX_TYPE] = beacon_type;
50
+  advertising_data[AD_IDX_NUM] = beacon_num[0];
51
+  advertising_data[AD_IDX_NUM+1] = beacon_num[1];
52
+  std::string strServiceData = "";
53
+  strServiceData += (char)21;     // Len
54
+  strServiceData += (char)0x16;   // Fame Type
55
+  strServiceData += (char)0xaa;
56
+  strServiceData += (char)0xfe;
57
+  for(int i =0; i < ADVERT_SZ; i++ ) {
58
+    strServiceData += (char)advertising_data[i];     // Len
59
+  }
60
+  sprintf(instanceStr,"%02x%02x%02x%02x%02x%02x",
61
+    advertising_data[AD_IDX_INSTANCE_ALL+AD_SHIFT], advertising_data[AD_IDX_INSTANCE_ALL+AD_SHIFT+1],
62
+    advertising_data[AD_IDX_INSTANCE_ALL+AD_SHIFT+2], advertising_data[AD_IDX_INSTANCE_ALL+AD_SHIFT+3],
63
+    advertising_data[AD_IDX_INSTANCE_ALL+AD_SHIFT+4], advertising_data[AD_IDX_INSTANCE_ALL+AD_SHIFT+5]);
64
+  DisplayButtonStatus();
65
+  
66
+  uint8_t *ptr=(uint8_t*)strServiceData.c_str();
67
+  for(int i = 0; i < 36; i++ ) {
68
+    Serial.printf("%02x", ptr[i]);
69
+  }
70
+  Serial.println("");
71
+  oAdvertisementData.addData(strServiceData);
72
+  pAdvertising->setAdvertisementData(oAdvertisementData);
73
+  pAdvertising->setScanResponseData(oScanResponseData);
74
+}
75
+
76
+void setup() {
77
+  #ifdef _HELTEC_H_
78
+  Heltec.begin(true /*DisplayEnable Enable*/, false /*LoRa Enable*/, true /*Serial Enable*/, false /*LoRa use PABOOST*/, 0 /*LoRa RF working band*/);
79
+  Heltec.display->clear();
80
+  #endif //_HELTEC_H_
81
+  Serial.begin(115200);
82
+
83
+  
84
+
85
+  Serial.printf("------------------------------");
86
+
87
+  //BLE MAC Address will be new_mac + 2
88
+  esp_base_mac_addr_set(new_mac);
89
+  sprintf(macStr,"%02x:%02x:%02x:%02x:%02x:%02x", new_mac[0], new_mac[1], new_mac[2], new_mac[3], new_mac[4], new_mac[5]);
90
+
91
+  beaconTypeStr = "Init Safe";
92
+  
93
+  // Create the BLE Device
94
+  BLEDevice::init(BEACON_NAME);
95
+}
96
+
97
+void loop() {
98
+
99
+  //PRG Button
100
+  pollPrg();
101
+  
102
+  Serial.println("DeviceAddress: "+String(macStr));
103
+
104
+  // Create the BLE Server
105
+  pAdvertising = BLEDevice::getAdvertising();
106
+  BLEDevice::startAdvertising();
107
+  setBeacon();
108
+  // Start advertising
109
+  pAdvertising->addServiceUUID(BLEUUID(BEACON_SERVICE_UUID));
110
+
111
+  beacon_count++;
112
+  ad_running = 1;
113
+  DisplayButtonStatus();
114
+  pAdvertising->start();
115
+  Serial.println("Advertizing started type : "+beaconTypeStr);
116
+  delay(BEACON_ADV_DURATION);
117
+  pAdvertising->stop();
118
+  ad_running = 0;
119
+  DisplayButtonStatus();
120
+  Serial.println("Advertizing stopped.");
121
+
122
+  delay(BEACON_SLEEP_ADV);
123
+}
+53
beacon.h
... ...
@@ -0,0 +1,53 @@
1
+#ifndef _BEACON_H
2
+#define _BEACON_H
3
+
4
+#define BEACON_SLEEP_ADV 2000 //2s between uptime
5
+#define BEACON_ADV_DURATION 200 //200ms
6
+#define BEACON_UUID         "7c8a68a6-ddd0-11e9-8a34-2a2ae2dbcce4"
7
+#define BEACON_SERVICE_UUID "feaa"
8
+#define BEACON_NAME         "FakeESP"
9
+enum EN_BEACON_TYPE {
10
+  EN_BEACON_TYPE_entry = 0x01,
11
+  EN_BEACON_TYPE_exit = 0x02,
12
+  EN_BEACON_TYPE_hazard = 0x03,
13
+  EN_BEACON_TYPE_safe = 0x04,
14
+  EN_BEACON_TYPE_other = 0x05,
15
+  EN_BEACON_TYPE_num = 5
16
+};
17
+
18
+uint8_t beacon_type = EN_BEACON_TYPE_safe;
19
+String beaconTypeStr = "";
20
+
21
+// Fake MAC Address for BLE beacon
22
+uint8_t new_mac[8] = {0xAC, 0x23, 0x3F, 0xCA, 0xFE, 0x01};
23
+
24
+// Fake Complete Instance
25
+uint8_t advert_instance[7] = {0x54, 0x43, 0x4c, 0x03, 0x00, 0x00, 0x0a};
26
+// Fake Complete Namespace
27
+uint8_t beacon_namespace[10] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99};
28
+
29
+// Fake Partial Instance
30
+// 0x54434cXXYYYY
31
+// XX : Beacon Type
32
+// YY : Beacon Number
33
+uint8_t beacon_inst[3] = { 0x54, 0x43, 0x4c };//Instance ID on 3 bytes
34
+uint8_t beacon_num[2] = { 0x00, 0x0b };//11th beacon
35
+
36
+
37
+//#define ADVERT_SZ 22
38
+//char  advertising_data[ADVERT_SZ]={ 0x15, 0x16, 0xAA, 0xFE, 0x00, 0xE8, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0x54, 0x43, 0x4C, 0x04, 0x00, 0x0b };
39
+//#define AD_IDX_NAMESPACE 6
40
+//#define AD_IDX_INSTANCE 16
41
+//#define AD_IDX_TYPE 19
42
+//#define AD_IDX_NUM 20
43
+
44
+#define ADVERT_SZ 18
45
+char  advertising_data[ADVERT_SZ]={ 0x00, 0xE8, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0x54, 0x43, 0x4C, 0x04, 0x00, 0x0b };
46
+#define AD_IDX_NAMESPACE 2
47
+#define AD_IDX_INSTANCE_ALL 9
48
+#define AD_IDX_INSTANCE 12
49
+#define AD_IDX_TYPE 15
50
+#define AD_IDX_NUM 16
51
+#define AD_SHIFT 3 
52
+
53
+#endif //_BEACON_H
+48
button.h
... ...
@@ -0,0 +1,48 @@
1
+#ifndef _BUTTON_H
2
+#define _BUTTON_H
3
+
4
+#include "beacon.h"
5
+
6
+int buttonState = 0;         // variable for reading the pushbutton status
7
+const int BUTTON_PRG = 0;     // PRG Button
8
+const int ledPin =  13;      // the number of the LED pin
9
+
10
+void pollPrg() 
11
+{ 
12
+  buttonState = digitalRead(BUTTON_PRG);
13
+  if (buttonState == LOW) {
14
+    Serial.println("pollPrg: Call");
15
+    switch( beacon_type ) {
16
+    case EN_BEACON_TYPE_entry:
17
+      beacon_type = EN_BEACON_TYPE_hazard;
18
+      beaconTypeStr="Hazard";
19
+      break;
20
+    case EN_BEACON_TYPE_hazard:
21
+      beacon_type = EN_BEACON_TYPE_safe;
22
+      beaconTypeStr="Safe";
23
+      break;
24
+    case EN_BEACON_TYPE_safe:
25
+      beacon_type = EN_BEACON_TYPE_exit;
26
+      beaconTypeStr="Exit";
27
+      break;
28
+    case EN_BEACON_TYPE_exit:
29
+      beacon_type = EN_BEACON_TYPE_other;
30
+      beaconTypeStr="Other";
31
+      break;
32
+    case EN_BEACON_TYPE_other:
33
+      beacon_type = EN_BEACON_TYPE_entry;
34
+      beaconTypeStr="Entry";
35
+      break;
36
+    default:
37
+      beacon_type = EN_BEACON_TYPE_safe;
38
+      beaconTypeStr="Safe";
39
+      break;
40
+    }
41
+    Serial.println("Switching to "+beaconTypeStr);
42
+  }
43
+  DisplayButtonStatus();
44
+}
45
+
46
+#endif //_BUTTON_H
47
+
48
+    
+36
display.h
... ...
@@ -0,0 +1,36 @@
1
+#ifndef _DISPLAY_H
2
+#define _DISPLAY_H
3
+
4
+#include "beacon.h"
5
+
6
+// Display Constants
7
+#define LINE1 0
8
+#define LINE2 12
9
+#define LINE3 24
10
+#define LINE4 36
11
+#define LINE5 48
12
+#define LINEBOTTOM 54
13
+
14
+// Display String Variables for updating all screen at once
15
+//---------------------------------------------------------------------
16
+char instanceStr[12] = "";
17
+char macStr[18] = "";
18
+int ad_running = 0;
19
+uint32_t beacon_count = 0;
20
+
21
+//---------------------------------------------------------------------
22
+void DisplayButtonStatus() {
23
+  #ifdef _HELTEC_H_
24
+  Heltec.display->clear();
25
+  Heltec.display->drawString(0, LINE1, "MAC: "+String(macStr));
26
+  Heltec.display->drawString(0, LINE2, "I : "+String(instanceStr));
27
+  Heltec.display->drawString(0, LINE4, beaconTypeStr);
28
+  Heltec.display->drawString(0, LINEBOTTOM, "Cnt: "+String(beacon_count));
29
+  if( 1 == ad_running ) {
30
+    String running="X";
31
+    Heltec.display->drawString(120, LINEBOTTOM, running);
32
+  }
33
+  Heltec.display->display();
34
+  #endif //_HELTEC_H_
35
+}
36
+#endif //_DISPLAY_H