Tasmota/lib/libesp32/berry_matter/src/embedded/Matter_Plugin.be
2023-04-05 22:09:42 +02:00

221 lines
7.1 KiB
Plaintext

#
# Matter_Plugin.be - generic superclass for all Matter plugins, used to define specific behaviors (light, switch, media...)
#
# Copyright (C) 2023 Stephan Hadinger & Theo Arends
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# Matter modules for extensibility
# template but not actually used
#@ solidify:Matter_Plugin,weak
class Matter_Plugin
static var CLUSTERS = {
0x001D: [0,1,2,3,0xFFFC,0xFFFD], # Descriptor Cluster 9.5 p.453
}
var device # reference to the `device` global object
var endpoint # current endpoint
var clusters # map from cluster to list of attributes, typically constructed from CLUSTERS hierachy
#############################################################
# MVC Model
#
# Model linking the plugin to the Tasmota behavior
#############################################################
#############################################################
# Constructor
#
def init(device, endpoint)
self.device = device
self.endpoint = endpoint
self.clusters = self.consolidate_clusters()
end
#############################################################
# Stub for updating shadow values (local copies of what we published to the Matter gateway)
def update_shadow()
end
#############################################################
# signal that an attribute has been changed
#
# If `endpoint` is `nil`, send to all endpoints
def attribute_updated(endpoint, cluster, attribute, fabric_specific)
if endpoint == nil endpoint = self.endpoint end
self.device.attribute_updated(endpoint, cluster, attribute, fabric_specific)
end
#############################################################
# consolidate_clusters
#
# Build a consolidated map of all the `CLUSTERS` static vars
# from the inheritance hierarchy
def consolidate_clusters()
def real_super(o) return super(o) end # enclose `super()` in a static function to disable special behavior for super in instances
var ret = {}
var o = self # start with self
while o != nil # when we rich highest class, `super()` returns `nil`
var CL = o.CLUSTERS
for k: CL.keys()
# check if key already exists
if !ret.contains(k) ret[k] = [] end
for attr: CL[k] # iterate on values
if ret[k].find(attr) == nil
ret[k].push(attr)
end
end
end
o = real_super(o)
end
return ret
end
#############################################################
# Which endpoints does it handle (list of numbers)
def get_endpoint()
return self.endpoint
end
def get_cluster_list(ep)
var ret = []
for k: self.clusters.keys()
ret.push(k)
end
return ret
end
def get_attribute_list(ep, cluster)
return self.clusters.find(cluster, [])
end
#############################################################
# Does it handle this endpoint and this cluster
def has(cluster, endpoint)
return self.clusters.contains(cluster) && self.endpoints.find(endpoint) != nil
end
#############################################################
# MVC Model
#
# View reading attributes
#############################################################
#############################################################
# read attribute
def read_attribute(session, ctx)
var TLV = matter.TLV
var cluster = ctx.cluster
var attribute = ctx.attribute
if cluster == 0x001D # ========== Descriptor Cluster 9.5 p.453 ==========
if attribute == 0x0000 # ---------- DeviceTypeList / list[DeviceTypeStruct] ----------
var dtl = TLV.Matter_TLV_array()
for dt: self.TYPES.keys()
var d1 = dtl.add_struct()
d1.add_TLV(0, TLV.U2, dt) # DeviceType
d1.add_TLV(1, TLV.U2, self.TYPES[dt]) # Revision
end
return dtl
elif attribute == 0x0001 # ---------- ServerList / list[cluster-id] ----------
var sl = TLV.Matter_TLV_array()
for cl: self.get_cluster_list()
sl.add_TLV(nil, TLV.U4, cl)
end
return sl
elif attribute == 0x0002 # ---------- ClientList / list[cluster-id] ----------
var cl = TLV.Matter_TLV_array()
return cl
elif attribute == 0x0003 # ---------- PartsList / list[endpoint-no]----------
var pl = TLV.Matter_TLV_array()
return pl
elif attribute == 0xFFFC # ---------- FeatureMap / map32 ----------
return TLV.create_TLV(TLV.U4, 0) #
elif attribute == 0xFFFD # ---------- ClusterRevision / u2 ----------
return TLV.create_TLV(TLV.U4, 1) # "Initial Release"
end
else
return nil
end
end
#############################################################
# read event
# TODO
def read_event(session, endpoint, cluster, eventid)
return nil
end
#############################################################
# subscribe attribute
# TODO
def subscribe_attribute(session, endpoint, cluster, attribute)
return nil
end
#############################################################
# subscribe event
# TODO
def subscribe_event(session, endpoint, cluster, eventid)
return nil
end
#############################################################
# MVC Model
#
# Controller write attributes
#############################################################
#############################################################
# write attribute
def write_attribute(session, ctx, write_data)
return nil
end
#############################################################
# MVC Model
#
# Controller invoke request
#############################################################
#############################################################
# invoke command
def invoke_request(session, val, ctx)
return nil
end
#############################################################
# timed request
# TODO - should we even support this?
def timed_request(session, val, ctx)
return nil
end
#############################################################
# parse sensor
#
# The device calls regularly `tasmota.read_sensors()` and converts
# it to json.
def parse_sensors(payload)
end
#############################################################
# every_second
def every_second()
self.update_shadow() # force reading value and sending subscriptions
end
end
matter.Plugin = Matter_Plugin