iT邦幫忙

2025 iThome 鐵人賽

DAY 5
0

相信各位看官對於目前 IDS server 裡散落各處的 hard-coding 一定看不過眼吧 ...
因此!今天本喵就試著把這些東西整理一番吧!

1. 管理設定值

目前在 IDS server 中,有以下幾項可能會因應需求而異的 hard-coding 設定值:

名稱或變數名 意義
_adv_interval_us 250000 廣播間距
_passkey 123456 BLE PIN
local_name IDS 🍭 廣播攜帶的 complete local name
IDD Features b'\x01\x02\x03' 回應 BLE read 要求的值

除了這些設定值散落在不同程式碼的問題外,即使將它們集中在某個檔案內,有些值理應是每台機器都不同的,比如 PIN 和 Complete Local Name。所以為了更好管理,咱們會建立一個可以讓使用者自行修改的設定檔,當伺服器啟動後會依據其設定來做相應的設定。

咱們先將設定值全歸在一個類別裡:

class Config:
    def __init__(self):
        self.local_name = "IDS 🍭"
        self.adv_interval_us = 250_000
        self.passkey = "123456"
        self.idd_features = b"\x01\x02\x03"

2. 儲存設定

為了讓使用者可以自行修改,設定檔的格式必須讓他人容易了解,因此咱們使用 JSON 來撰寫設定檔。為了將類別實體以 JSON 來儲存,需要將待儲存的資料轉成字典型式:

def to_dict(self):
    return {
        "local_name": self.local_name,
        "adv_interval_us": self.adv_interval_us,
        "passkey": self.passkey,
        "idd_features": tuple(self.idd_features),
    }

然後將 Config 實體傳入 json.dump():

def _build_config():
    c = config.Config()

    with open(config.CONFIG_PATH, "w", encoding="utf-8") as fp:
        # MicroPython 不支援這些命名參數
        json.dump(c.to_dict(), fp, ensure_ascii=False, indent=4)

可以得到如下內容的檔案:

{
    "local_name": "IDS 🍭",
    "adv_interval_us": 250000,
    "passkey": "123456",
    "idd_features": [
        1,
        2,
        3
    ]
}

要特別注意的是,_build_config() 是使用 Python 來執行,因為 MicroPython 的 json.dump() 不支援如 ensure_ascii 和 indent 等命名參數。若使用 MicroPython 來執行,會得到如下結果:

{"local_name": "IDS 🍭", "passkey": "123456", "idd_features": [1, 2, 3], "adv_interval_us": 250000}

所有都內容歸於一行,若以後設定愈來愈多,將不易於查看,所以才以 Python 製作良好風格的 JSON 檔。

3. 載入設定

首先讓系統讀入保存設定的 JSON 檔:

def get_config():
    # MicroPython 沒有 os.path.exists()
    if CONFIG_PATH in os.listdir():
        with open(CONFIG_PATH, encoding="utf-8") as fp:
            data = json.load(fp)

        return Config.from_dict(data)
    else:
        print("No configuration file")
        return Config()

然後由 Config 類別將其還原為實體:

@classmethod
def from_dict(cls, d):
    obj = cls()

    obj.local_name = d["local_name"]
    obj.adv_interval_us = d["adv_interval_us"]
    obj.passkey = d["passkey"]
    obj.idd_features = bytes(d["idd_features"])

    return obj

4. 重構 main.py

先宣告一個全域變數:

_config = config.get_config()

然後只是簡單地將先前在 main.py 裡的 hard-coding 替換為 _config 的成員變數。如由原本的:

# 發送廣播
adv_data = build_advertising_payload()
local_name = "IDS 🍭"
resp_data = build_scan_response_payload(local_name)
ble.gap_advertise(_adv_interval_us, adv_data, resp_data=resp_data)

變為:

# 發送廣播
adv_data = build_advertising_payload()
resp_data = build_scan_response_payload(_config.local_name)
ble.gap_advertise(_config.adv_interval_us, adv_data, resp_data=resp_data)

完整程式請參考 https://github.com/ArcticCatSD/ESP32_MicroPython_IDS/tree/main/05


上一篇
Day 04 - 整體架構 & logger & 字串拼接效能
下一篇
Day 06 - 封裝 BLE 相關功能 (1)
系列文
以MicroPython在ESP32上實作Insulin Delivery Service31
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言