iT邦幫忙

2025 iThome 鐵人賽

DAY 12
0
Software Development

以MicroPython在ESP32上實作Insulin Delivery Service系列 第 12

Day 12 - 為 IDD Features 加上 E2E-Protection

  • 分享至 

  • xImage
  •  

咱們昨天已經將 E2E-Counter 和 E2E-CRC 完成了,接下來就是藉由它們來完善咱們的 IDD Features characteristic。

為了讓 IddFeatures 類別支援 E2E-Protection,在 IddFeatures._build_read_rsp() 裡須判斷 Config.is_e2e_protection_supported 是否為 True,若是,則進行以下動作:

  1. 取得 IDD Features 專屬的 E2E-Counter 的值
  2. 依序將除 E2E-CRC 欄位以外的所有欄位納入 CRC 的計算
  3. 更新 E2E-Counter
  4. 將 E2E-Counter 和 E2E-CRC 放入待傳送緩衝區裡

IDD Features 要回應的資料這樣就完成了,但還有一件事情沒處理:

  • 每次連線,傳送的 E2E-Counter 都由 1 開始

對於這件事,咱們可以監聽 BLE 的連接或斷線事件,當事件發生後,便重設 E2E-Counter。

這些行為的實作都很直觀、簡單,可是每次一有新的 characteristic,都要記得撰寫相同的程式碼,實在讓人覺得瑣碎、麻煩,就算複製貼上,也難保不會出錯。為了遵循「懶惰是程式設計師的美德」的信念,咱們來製作一個專門處理傳輸用的 E2E-Protection 的類別吧:

class E2ETxMixin:
    def __init__(self):
        self._tx_counter = ble.e2e.TxCounter()
        ble.stack.register_irq_handler(self._isr_e2e_tx_mixin)

    def _after_build_tx_data(self):
        self._tx_counter.inc_counter()

    def _isr_e2e_tx_mixin(self, event, data):
        if event == _IRQ_CENTRAL_DISCONNECT:
            self._tx_counter.reset()

咱們讓 E2ETxMixin 類別在以下情境自動處理 E2E-Counter 的更新:

  • 取得資料後:_after_build_tx_data()
  • 連線中斷後:_isr_e2e_tx_mixin()

還記得在 ReadMixin 類別裡,咱們留了一個沒做任何事的成員方法 _after_build_tx_data() 嗎?而現在,在 E2ETxMixin 類別裡也有這個同名方法,只是它不再無所事事,而是專職於遞增 E2E-Counter。

那要怎麼藉由 E2ETxMixin 來增加 IddFeatures 類別的 E2E-Protection 支援呢?當時咱們讓 IddFeatures 繼承 ReadMixin,但卻沒有覆寫它的 _after_build_tx_data(),而現在就是它發揮作用的時候了:

class E2EIddFeatures(ble.mixin.E2ETxMixin, IddFeatures):
    def __init__(self, config: config.Config):
        ble.mixin.E2ETxMixin.__init__(self)
        IddFeatures.__init__(self, config)

    def _build_read_rsp(self, buf: memoryview) -> int:
        data_len = super()._build_read_rsp(buf)
        buf[2] = self._tx_counter.value
        ble.e2e.Crc.fill_crc(buf, 0, data_len)
        return data_len

咱們新創一個類別 E2EIddFeatures,讓它繼承 E2ETxMixinIddFeatures,然後覆寫 IddFeatures_build_read_rsp()

  1. IddFeatures._build_read_rsp() 取得已經建構好的資料
  2. 然後更新 E2E-Counter 和 E2E-CRC 兩個欄位

咦?!不是說 _after_build_tx_data() 要發揮作用嗎?怎麼 E2EIddFeatures 類別沒有覆寫 _after_build_tx_data()?這是因為 E2EIddFeatures 繼承了 E2ETxMixin,而 E2ETxMixin 已經把 _after_build_tx_data() 寫好了,所以 E2EIddFeatures 就可以直接使用它了~

最後是更新 ble/server.py 的 IdsServer._build_ids()

def _build_ids(self) -> ble.stack.Service:

    self._ids = ble.stack.Service(_IDS_UUID)

    if _config.is_e2e_protection_supported:
        features = ble.ids.features.E2EIddFeatures(_config)
    else:
        features = ble.ids.features.IddFeatures(_config)

    self._ids.add_char(features)

    return self._ids

至此,咱們的 IDD Features characteristic 便算是正式完成了~
看官可以藉由修改 config.json 的 idd_features_flags 來開關 E2E-Protection:

  • 偶數:關閉 E2E-Protection
  • 奇數:啟用 E2E-Protection

上一篇
Day 11 - E2E-Protection
下一篇
Day 13 - IDD Status Changed (1) 之 Indicate
系列文
以MicroPython在ESP32上實作Insulin Delivery Service31
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言