Skip to content

Commit

Permalink
Matter aggregator relocated to endpoint 1 for Google compatibility, m…
Browse files Browse the repository at this point in the history
…ay break existing associations (arendst#20654)
  • Loading branch information
s-hadinger authored and hawa-lc4 committed Feb 12, 2024
1 parent 545f5c4 commit eafdacc
Show file tree
Hide file tree
Showing 39 changed files with 6,878 additions and 6,511 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -12,6 +12,7 @@ All notable changes to this project will be documented in this file.
- Berry `introspect.contains` and `bytes.addfloat` (#20635)

### Breaking Changed
- Matter aggregator relocated to endpoint 1 for Google compatibility, may break existing associations

### Changed
- Library OneWire-Stickbreaker by TasmotaOneWire supporting Shelly Plus Add-On (#20580)
Expand Down
3 changes: 2 additions & 1 deletion lib/libesp32/berry_matter/src/be_matter_module.c
Expand Up @@ -285,7 +285,8 @@ module matter (scope: global, strings: weak) {
_STYLESHEET, comptr(MATTER_STYLESHEET)
_ADD_ENDPOINT_JS, comptr(MATTER_ADD_ENDPOINT_HINTS_JS)
MATTER_OPTION, int(151) // SetOption151 enables Matter
AGGREGATOR_ENDPOINT, int(0xFE) // for Alexa we need only 8 bits endpoints
AGGREGATOR_ENDPOINT, int(0x0001) // some controllers require aggregator to be endpoint 1
START_ENDPOINT, int(0x0002) // endpoint where to start devices
seconds_to_dhm, ctype_func(matter_seconds_to_dhm)
Verhoeff, class(be_class_Matter_Verhoeff)
Expand Down
12 changes: 12 additions & 0 deletions lib/libesp32/berry_matter/src/embedded/Matter_Fabric.be
Expand Up @@ -43,6 +43,7 @@ class Matter_Fabric : Matter_Expirable
var _store # reference back to session store
# timestamp
var created
var deleted # timestamp when the deletion of fabric was requested, and deferred
# fabric-index
var fabric_index # index number for fabrics, starts with `1`
var fabric_parent # index of the parent fabric, i.e. the fabric that triggered the provisioning (if nested)
Expand Down Expand Up @@ -76,6 +77,7 @@ class Matter_Fabric : Matter_Expirable
self._sessions = matter.Expirable_list()
self.fabric_label = ""
self.created = tasmota.rtc_utc()
# self.deleted = nil # no need to actually set to nil
# init group counters
self._counter_group_data_snd_impl = matter.Counter()
self._counter_group_ctrl_snd_impl = matter.Counter()
Expand Down Expand Up @@ -276,6 +278,16 @@ class Matter_Fabric : Matter_Expirable
return session
end

#############################################################
# Mark for deleteion in the near future
#
def mark_for_deletion()
self.deleted = tasmota.rtc_utc()
end
def is_marked_for_deletion()
return self.deleted != nil
end

#############################################################
# Fabric::tojson()
#
Expand Down
9 changes: 0 additions & 9 deletions lib/libesp32/berry_matter/src/embedded/Matter_Plugin_0.be
Expand Up @@ -38,7 +38,6 @@ class Matter_Plugin
# Configuration of the plugin: clusters and type
static var CLUSTERS = {
0x001D: [0,1,2,3,0xFFFC,0xFFFD], # Descriptor Cluster 9.5 p.453
0x0039: [0x11], # Bridged Device Basic Information 9.13 p.485
}
# Accepted Update commands for virtual devices
static var UPDATE_COMMANDS = []
Expand Down Expand Up @@ -266,14 +265,6 @@ class Matter_Plugin
return tlv_solo.set(TLV.U4, 1) # "Initial Release"
end

# ====================================================================================================
elif cluster == 0x0039 # ========== Bridged Device Basic Information 9.13 p.485 ==========

if attribute == 0x0011 # ---------- Reachable / bool ----------
return tlv_solo.set(TLV.BOOL, 1) # by default we are reachable
else
return super(self).read_attribute(session, ctx, tlv_solo) # rest is handled by 0x0028
end
else
return nil
end
Expand Down
Expand Up @@ -26,9 +26,10 @@ import matter
class Matter_Plugin_Aggregator : Matter_Plugin
static var TYPE = "aggregator" # name of the plug-in in json
static var DISPLAY_NAME = "Aggregator" # display name of the plug-in
# static var CLUSTERS = {
# # 0x001D: inherited # Descriptor Cluster 9.5 p.453
# }
static var CLUSTERS = matter.consolidate_clusters(_class, {
# 0x001D: inherited # Descriptor Cluster 9.5 p.453
0x0003: [0,1,0xFFFC,0xFFFD], # Identify 1.2 p.16
})
static var TYPES = { 0x000E: 1 } # Aggregator

#############################################################
Expand All @@ -39,14 +40,30 @@ class Matter_Plugin_Aggregator : Matter_Plugin
var cluster = ctx.cluster
var attribute = ctx.attribute

if cluster == 0x001D # ========== Descriptor Cluster 9.5 p.453 ==========
# ====================================================================================================
if cluster == 0x0003 # ========== Identify 1.2 p.16 ==========
if attribute == 0x0000 # ---------- IdentifyTime / u2 ----------
return tlv_solo.set(TLV.U2, 0) # no identification in progress
elif attribute == 0x0001 # ---------- IdentifyType / enum8 ----------
return tlv_solo.set(TLV.U1, 0) # IdentifyType = 0x00 None
elif attribute == 0xFFFC # ---------- FeatureMap / map32 ----------
return tlv_solo.set(TLV.U4, 0) # no features
elif attribute == 0xFFFD # ---------- ClusterRevision / u2 ----------
return tlv_solo.set(TLV.U4, 4) # "new data model format and notation"
end

elif cluster == 0x001D # ========== Descriptor Cluster 9.5 p.453 ==========
if attribute == 0x0002 # ---------- ClientList / list[cluster-id] ----------
var pl = TLV.Matter_TLV_array()
# from connectedhome reference implementation
pl.add_TLV(nil, TLV.U2, 0x001E) # Binding
return pl
# overwrite PartsList
if attribute == 0x0003 # ---------- PartsList / list[endpoint-no]----------
elif attribute == 0x0003 # ---------- PartsList / list[endpoint-no]----------
var pl = TLV.Matter_TLV_array()
var eps = self.device.get_active_endpoints(true)
for ep: eps
if ep < matter.AGGREGATOR_ENDPOINT
if ep != matter.AGGREGATOR_ENDPOINT
pl.add_TLV(nil, TLV.U2, ep) # add each endpoint
end
end
Expand All @@ -62,6 +79,39 @@ class Matter_Plugin_Aggregator : Matter_Plugin
# no match found, return that the attribute is unsupported
end

#############################################################
# Invoke a command
#
# returns a TLV object if successful, contains the response
# or an `int` to indicate a status
def invoke_request(session, val, ctx)
var TLV = matter.TLV
var cluster = ctx.cluster
var command = ctx.command

# ====================================================================================================
if cluster == 0x0003 # ========== Identify 1.2 p.16 ==========

if command == 0x0000 # ---------- Identify ----------
# ignore
return true
elif command == 0x0001 # ---------- IdentifyQuery ----------
# create IdentifyQueryResponse
# ID=1
# 0=Certificate (octstr)
var iqr = TLV.Matter_TLV_struct()
iqr.add_TLV(0, TLV.U2, 0) # Timeout
ctx.command = 0x00 # IdentifyQueryResponse
return iqr
elif command == 0x0040 # ---------- TriggerEffect ----------
# ignore
return true
end

else
return super(self).invoke_request(session, val, ctx)
end
end

end
matter.Plugin_Aggregator = Matter_Plugin_Aggregator

Expand Up @@ -119,8 +119,6 @@ class Matter_Plugin_Device : Matter_Plugin
return tlv_solo.set(TLV.BOOL, 1) # by default we are reachable
elif attribute == 0x0012 # ---------- UniqueID / string 32 max ----------
return tlv_solo.set(TLV.UTF1, tasmota.wifi().find("mac", ""))
else
return super(self).read_attribute(session, ctx, tlv_solo)
end

else
Expand Down
13 changes: 11 additions & 2 deletions lib/libesp32/berry_matter/src/embedded/Matter_Plugin_1_Root.be
Expand Up @@ -154,6 +154,7 @@ class Matter_Plugin_Root : Matter_Plugin
var nocl = TLV.Matter_TLV_array() # NOCs, p.711
var fabs = ctx.fabric_filtered ? [session.get_fabric()] : self.device.sessions.active_fabrics()
for loc_fabric: fabs
if loc_fabric.is_marked_for_deletion() continue end # fabric is scheduled for deletion
if loc_fabric == nil continue end
var nocs = nocl.add_struct(nil)
nocs.add_TLV(1, TLV.B2, loc_fabric.get_noc()) # NOC
Expand All @@ -166,6 +167,7 @@ class Matter_Plugin_Root : Matter_Plugin
var fabs = ctx.fabric_filtered ? [session.get_fabric()] : self.device.sessions.active_fabrics()
for loc_fabric: fabs
if loc_fabric == nil continue end
if loc_fabric.is_marked_for_deletion() continue end # fabric is scheduled for deletion
var root_ca_tlv = TLV.parse(loc_fabric.get_ca())
var fab = fabrics.add_struct(nil) # encoding see p.303
fab.add_TLV(1, TLV.B2, root_ca_tlv.findsubval(9)) # RootPublicKey
Expand Down Expand Up @@ -305,14 +307,20 @@ class Matter_Plugin_Root : Matter_Plugin

elif cluster == 0x001D # ========== Descriptor Cluster 9.5 p.453 ==========

# overwrite ClientList
if attribute == 0x0002 # ---------- ClientList / list[cluster-id] ----------
var pl = TLV.Matter_TLV_array()
# from connectedhome reference implementation
pl.add_TLV(nil, TLV.U2, 0x001F) # Access Control Cluster
return pl
# overwrite PartsList
if attribute == 0x0003 # ---------- PartsList / list[endpoint-no]----------
elif attribute == 0x0003 # ---------- PartsList / list[endpoint-no]----------
var pl = TLV.Matter_TLV_array()
var eps = self.device.get_active_endpoints(true)
var disable_bridge_mode = self.device.disable_bridge_mode
for ep: eps
# if bridge mode is disabled, don't announce Aggregatore (above 0xFF00)
if !disable_bridge_mode || ep < matter.AGGREGATOR_ENDPOINT
if !disable_bridge_mode || ep != matter.AGGREGATOR_ENDPOINT
pl.add_TLV(nil, TLV.U2, ep) # add each endpoint
end
end
Expand Down Expand Up @@ -572,6 +580,7 @@ class Matter_Plugin_Root : Matter_Plugin
if fab.get_fabric_index() == index
# tasmota.log("MTR: removing fabric " + fab.get_fabric_id().copy().reverse().tohex(), 2)
# defer actual removal to send a response
fab.mark_for_deletion() # this should not appear anymore in the list
tasmota.set_timer(2000, def () self.device.remove_fabric(fab) end)
return true # Ok
end
Expand Down
22 changes: 21 additions & 1 deletion lib/libesp32/berry_matter/src/embedded/Matter_zz_Device.be
Expand Up @@ -786,6 +786,7 @@ class Matter_Device
if self.plugins_config != nil
tasmota.log("MTR: load_config = " + str(self.plugins_config), 3)
self.adjust_next_ep()
self.check_config_ep()
self.plugins_persist = true
end
self.plugins_config_remotes = j.find("remotes", {})
Expand Down Expand Up @@ -1160,7 +1161,7 @@ class Matter_Device
var m = {}

# check if we have a light
var endpoint = 1
var endpoint = matter.START_ENDPOINT
var light_present = false

import light
Expand Down Expand Up @@ -1399,6 +1400,25 @@ class Matter_Device
self.attribute_updated(matter.AGGREGATOR_ENDPOINT, 0x001D, 0x0003, false)
end

#############################################################
# Check that all ep are valid, i.e. don't collied with root or aggregator
#
def check_config_ep()
# copy into list so we can change the map on the fly
var keys = []
for k: self.plugins_config.keys() k.push(int(k)) end
for ep: keys
if ep == 0
tasmota.log("MTR: invalid entry with ep '0'", 2)
self.plugins_config.remove(str(ep))
elif ep == matter.AGGREGATOR_ENDPOINT
tasmota.log(f"MTR: endpoint {ep} collides wit aggregator, relocating to {self.next_ep}", 2)
self.plugins_config[str(self.next_ep)] = self.plugins_config[str(ep)]
self.plugins_config.remove(str(ep))
end
end
end

#############################################################
# Adjust next_ep
#
Expand Down

0 comments on commit eafdacc

Please sign in to comment.