咱們昨天已經將 E2E-Counter 和 E2E-CRC 完成了,接下來就是藉由它們來完善咱們的 IDD Features characteristic。
為了讓 IddFeatures
類別支援 E2E-Protection,在 IddFeatures._build_read_rsp()
裡須判斷 Config.is_e2e_protection_supported
是否為 True
,若是,則進行以下動作:
IDD Features 要回應的資料這樣就完成了,但還有一件事情沒處理:
對於這件事,咱們可以監聽 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
,讓它繼承 E2ETxMixin
和 IddFeatures
,然後覆寫 IddFeatures
的 _build_read_rsp()
:
IddFeatures._build_read_rsp()
取得已經建構好的資料咦?!不是說 _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: