# ESP32 BLE - Beacon Locating
**Repository Path**: walkline/esp32-ble-beacon_locating
## Basic Information
- **Project Name**: ESP32 BLE - Beacon Locating
- **Description**: 信标定位测试
- **Primary Language**: Python
- **License**: MIT
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 4
- **Forks**: 1
- **Created**: 2021-08-03
- **Last Updated**: 2025-05-08
## Categories & Tags
**Categories**: hardware
**Tags**: MicroPython, iBeacon
## README
ESP32 BLE - Beacon Locating

### 项目介绍
使用开发板进行信标定位功能测试
### 获取完整项目
因为项目中使用了子模块 [MicroPython BLE Library](https://gitee.com/walkline/micropython-ble-library) 和 [MicroPython Beacon Library](https://gitee.com/walkline/micropython-beacon-library),所以要获取完整项目代码需要如下操作
#### 克隆方式
```bash
$ git clone --recursive https://gitee.com/walkline/esp32-ble-beacon_locating.git
```
#### 下载压缩文件方式
```bash
$ cd esp32-ble-beacon_locating
$ git submodule update --init --recursive
```
> 由于项目结构相对复杂,向开发板上传文件会有一定难度,所以推荐使用 [ab 工具](https://gitee.com/walkline/a-batch-tool) 进行批量上传
#### 不用获取完整项目方式
如果烧录`firmware/`目录下提供固件,那么固件里已经集成了上述两个子模块,就可以使用普通方式获取项目了
### 使用开发板测试代码
这里使用了一块`esp32 开发板`和一块`esp32c3 32s开发板`进行测试
#### 上传代码
* 使用集成了子模块的固件
```bash
$ ab abc-nolib
```
* 使用官方固件
```bash
$ ab
```
* 不使用`ab`工具
```bash
# 使用相关软件上传完整项目代码
drivers/button.py
libs/ble/ble/
libs/beacon/beacon/
utils.py
config.py
main.py
```
#### 进入`信标模式`
第一次上传代码之后重新上电进入`扫描模式`,这时按住开发板上的`BOOT`按键超过 3 秒会重新上电,并进入`信标模式`,此时开发板上的 Led 常亮
使用`ab`工具进入`repl`模式
```bash
$ ab --repl
```
查看完整输出内容
```bash
activating ble...
W (4841) BTDM_INIT: esp_bt_controller_mem_release not implemented, return OK
I (4841) BTDM_INIT: BT controller compile version [501d88d]
I (4851) coexist: coexist rom version 9387209
I (4851) phy_init: phy_version 500,985899c,Apr 19 2021,16:05:08
I (4971) system_api: Base MAC address is not set
I (4971) system_api: read default base MAC address from EFUSE
I (4971) BTDM_INIT: Bluetooth MAC: 7c:df:a1:c2:a3:0e
GAP procedure initiated: stop advertising.
ble activated
advertising...
GAP procedure initiated: advertise; disc_mode=2 adv_channel_map=7 own_addr_type=0 adv_filter_policy=0 adv_itvl_min=160 adv_itvl_max=160
>>>
```
#### 进入`扫描模式`
开发板上的 Led 常亮代表当前为`信标模式`,这时按住开发板上的`BOOT`按键超过 3 秒会重新上电,并进入`扫描模式`,此时开发板上的 Led 熄灭
完整输出内容
```bash
activating ble...
I (32694) BTDM_INIT: BT controller compile version [1342a48]
I (32694) system_api: Base MAC address is not set
I (32694) system_api: read default base MAC address from EFUSE
I (32704) phy_init: phy_version 4670,719f9f6,Feb 18 2021,17:07:07
ble activated
scanning...
GAP procedure initiated: discovery; own_addr_type=0 filter_policy=0 passive=1 limited=0 filter_duplicates=0 duration=forever
```
#### 查看数据
使用两块开发板分别进入`信标模式`和`扫描模式`,并查看`扫描模式`开发板的输出内容
```bash
[7C:DF:A1:C2:A3:0E] rssi: -54, dis: 1.584893
[7C:DF:A1:C2:A3:0E] rssi: -60, dis: 3.162278
[7C:DF:A1:C2:A3:0E] rssi: -53, dis: 1.412538
[7C:DF:A1:C2:A3:0E] rssi: -55, dis: 1.778279
[7C:DF:A1:C2:A3:0E] rssi: -57, dis: 2.238721
[7C:DF:A1:C2:A3:0E] rssi: -53, dis: 1.412538
[7C:DF:A1:C2:A3:0E] rssi: -54, dis: 1.584893
```
> `dis`代表两块开发板通过参数计算所得的距离,单位:米
> 还可以使用一个`扫描模式`对应多个`信标模式`开发板的方式进行数据查看
### 附录
#### 安信可 ESP32C3 开发板针脚
##### 板载元器件
| Led1 (R) | Led1 (G) | Led1 (B) | Led2 | Led3 | Key2 |
| :-: | :-: | :-: | :-: | :-: | :-: |
| IO3 | IO4 | IO5 | IO18 | IO19 | IO9 |
##### 可用 GPIO
| | 编号 |
| :-: | :- |
| 12F | 0, 1, 2, 3, 4, 5, 8, 9, 10, 18, 19, 20, 21 |
| 13 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 18, 19, 20, 21 |
| 13U | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 18, 19, 20, 21 |
| 32S | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 14, 15, 16, 17, 18, 19, 20, 21 |
#### `libs/`子模块折腾记录
由于最近刚刚掌握了`git submodule`的使用方法,而且这个项目非常适合使用子模块,所以为此特意进行了一番研究(还特意搞了一个`ab`工具出来。。。)
##### Round 1
一上来直接想当然的就这样添加了一个子模块
```bash
$ git submodule add https://gitee.com/walkline/micropython-ble-library ble-lib/ble
```
结果是`import`不支持带`-`号的路径 凸-_-凸
##### Round 2
经过一番思考,最终将子模块路径定为`libs/ble`和`libs/beacon`,然后为了兼容 [不用获取完整项目方式](#不用获取完整项目方式) 使用了如下的骚操作
```python
try:
from ble.tools import BLETools # 首先尝试从固件中导入模块
from ble.beacon.client.ibeacon import iBeacon
except:
from libs.ble.ble.tools import BLETools # 如果失败了就从用户分区导入
from libs.beacon.ble.beacon.client.ibeacon import iBeacon
```
看似没问题啊?那就赶紧尝试一下吧!
找了块板子,特意刷了不带`ble`模块的固件,使用`ab`工具上传文件,打开`Thonny`,输入代码
```python
>>> from libs.ble.ble.tools import BLETools
Traceback (most recent call last):
File "", line 1, in
File "libs/ble/ble/__init__.py", line 2, in
File "libs/ble/ble/tools.py", line 8, in
ImportError: no module named 'ble'
>>>
```
惊喜不?`tools.py`第 8 行代码如下
```python
from ble.const import BLEConst
```
##### Round 3
难到还要去改`libs/`下的代码?没有通用性啊!
最后根据`包导入顺序`这个思路找到`sys.path`这个列表,先看一下详情
```python
>>> import sys
>>> help(sys)
object is of type module
__name__ -- sys
path -- ['', '/lib']
argv -- []
version -- 3.4.0
version_info -- (3, 4, 0)
implementation -- (name='micropython', version=(1, 12, 0), mpy=10757)
platform -- esp32
byteorder -- little
maxsize -- 2147483647
exit --
stdin --
stdout --
stderr --
modules -- {'flashbdev': }
print_exception --
>>>
```
[查看文档](https://docs.micropython.org/en/latest/library/usys.html#usys.path) 得知,这里的`sys.path`就是导入模块时的搜索路径,默认是``和`/lib`(据说`PyBoard`还有`0:/lib`和`1:/flash`等不同分区下的路径,这里不做考虑),既然是个列表那就可以自己添加路径了,所以尝试了如下方法
```python
>>> import sys
>>> sys.path.append('libs/ble')
>>> sys.path.append('libs/beacon')
>>> from ble.tools import BLETools
>>>
```
貌似成功了?重启设备再来一次!
```python
>>> import sys
>>> sys.path.append('libs/ble')
>>> sys.path.append('libs/beacon')
>>> from ble.tools import BLETools
>>> from ble.beacon.client.ibeacon import iBeacon
Traceback (most recent call last):
File "", line 1, in
ImportError: no module named 'ble.beacon'
>>>
```
##### Round 4
着实迷惑了一阵啊!!!
这个问题的关键就是`sys.path`里增加路径增加的顺序,先增加了`libs/ble`,然后`import ble.beacon`的时候命中了`libs/ble/ble`这个路径,在这个路径下肯定是找不到`beacon`的,尝试如下
```python
>>> import sys
>>> sys.path.append('libs/beacon') # 颠倒了顺序
>>> sys.path.append('libs/ble')
>>> from ble.beacon.client.ibeacon import iBeacon
Traceback (most recent call last):
File "", line 1, in
File "libs/beacon/ble/beacon/client/ibeacon/iBeacon.py", line 11, in
ImportError: no module named 'ble.const'
>>>
```
倒是印证了前边的猜测,可是怎么解决呢?
##### Round 5
可用但不合理的方法,是一次性导入模块中的全部文件
假设`libs/ble/ble/__init__.py`中有如下代码
```python
from .const import *
from .tools import *
from .characteristics import *
from .descriptors import *
from .profile import *
from .services import *
```
那么我们可以做如下的尝试
```python
>>> import sys
>>> sys.path.append('libs/ble')
>>> from ble import *
>>> sys.path.remove('libs/ble')
>>> sys.path.append('libs/beacon')
>>> from ble.beacon.client.ibeacon import iBeacon
>>>
```
几乎完美啊!除了一次性导入了这么多模块
```python
>>> print('\n'.join(sys.modules))
ble.characteristics.__characteristic
ble.beacon.client.ibeacon.iBeacon
ble.profile
ble.descriptors.descriptors
ble.beacon.client
ble.descriptors.__descriptor
flashbdev
ble.descriptors
ble.characteristics
ble.characteristics.characteristics
ble.beacon.client.ibeacon
ble.services
ble.services.__service
ble.const
ble.tools
ble
ble.services.services
ble.beacon
```
##### Round Final
最终的解决方案是,给 [MicroPython Beacon Library](https://gitee.com/walkline/micropython-beacon-library/tree/libs/) 新开了一个`libs`分支,调整目录结构,去掉了最外层的`ble`目录并修改几个文件中的导入路径,然后尝试如下
```python
>>> import sys
>>> sys.path.append('libs/ble')
>>> sys.path.append('libs/beacon')
>>> from ble.tools import BLETools
>>> from beacon.client.ibeacon import iBeacon
>>>
>>> print('\n'.join(sys.modules))
flashbdev
beacon
beacon.client.ibeacon
ble.tools
beacon.client.ibeacon.iBeacon
ble.const
ble
beacon.client
>>>
```
至此完美解决
### 合作交流
* 联系邮箱:
* QQ 交流群:
* 走线物联:163271910
* 扇贝物联:31324057

