Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Matter aggregator relocated to endpoint 1 for Google compatibility, may break existing associations #20654

Merged
merged 1 commit into from Feb 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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