Matter fully implement attribute 0030/0000 (#17885)

This commit is contained in:
s-hadinger 2023-02-05 15:11:51 +01:00 committed by GitHub
parent 8bc03bbc06
commit 9126417836
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 755 additions and 461 deletions

View File

@ -479,7 +479,7 @@ int be_call_c_func(bvm *vm, const void * func, const char * return_type, const c
case 'c': be_pushcomptr(vm, (void*) ret); break;
case 's': if (ret) {be_pushstring(vm, (const char*) ret);} else {be_pushnil(vm);} break; // push `nil` if no string
case '$': if (ret) {be_pushstring(vm, (const char*) ret); free((void*)ret);} else {be_pushnil(vm);} break;
case '&': be_pushbytes(vm, (void*) ret, return_len); break;
case '&': if (ret) {be_pushbytes(vm, (void*) ret, return_len);} else {be_pushnil(vm);} break;
default: be_raise(vm, "internal_error", "Unsupported return type"); break;
}
be_return(vm);

View File

@ -0,0 +1,47 @@
/*
be_matter_misc.c - misc functions for `matter` module
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 global module
*
*******************************************************************/
#include "be_constobj.h"
#include "be_mapping.h"
#include "IPAddress.h"
static uint8_t ip_bytes[16] = {};
// Convert an IP address from string to raw bytes
extern "C" const void* matter_get_ip_bytes(const char* ip_str, size_t* ret_len) {
IPAddress ip;
if (ip.fromString(ip_str)) {
if (ip.isV4()) {
uint32_t ip_32 = ip;
memcpy(ip_bytes, &ip_32, 4);
*ret_len = 4;
} else {
memcpy(ip_bytes, ip.raw6(), 16);
*ret_len = 16;
}
return ip_bytes;
} else {
*ret_len = 0;
return nullptr;
}
}

View File

@ -94,6 +94,11 @@ const char* matter_get_command_name(uint16_t cluster, uint16_t command) {
}
BE_FUNC_CTYPE_DECLARE(matter_get_command_name, "s", "ii")
// Convert an IP address from string to raw bytes
extern const void* matter_get_ip_bytes(const char* ip_str, size_t* ret_len);
BE_FUNC_CTYPE_DECLARE(matter_get_ip_bytes, "&", "s")
#include "solidify/solidified_Matter_inspect.h"
extern const bclass be_class_Matter_TLV; // need to declare it upfront because of circular reference
@ -149,6 +154,7 @@ module matter (scope: global) {
Counter, class(be_class_Matter_Counter)
setmember, closure(matter_setmember_closure)
member, closure(matter_member_closure)
get_ip_bytes, ctype_func(matter_get_ip_bytes)
get_cluster_name, ctype_func(matter_get_cluster_name)
get_attribute_name, ctype_func(matter_get_attribute_name)

View File

@ -36,6 +36,7 @@ class Matter_Plugin_core : Matter_Plugin
# read an attribute
#
def read_attribute(msg, endpoint, cluster, attribute)
import string
var TLV = matter.TLV
if cluster == 0x0030 # ========== GeneralCommissioning cluster 11.9 p.627 ==========
@ -62,7 +63,41 @@ class Matter_Plugin_core : Matter_Plugin
elif cluster == 0x0033 # ========== General Diagnostics Cluster 11.11 p.642 ==========
if attribute == 0x0000 # ---------- NetworkInterfaces ----------
var nwi = TLV.Matter_TLV_list() # TODO list network interfaces, empty list for now
var nwi = TLV.Matter_TLV_array() # list network interfaces, empty list for now, p.647
var tas_eth = tasmota.eth()
if (tas_eth['up'])
var eth = nwi.add_struct(nil)
eth.add_TLV(0, TLV.UTF1, 'ethernet') # Name
eth.add_TLV(1, TLV.BOOL, 1) # IsOperational
eth.add_TLV(2, TLV.BOOL, 1) # OffPremiseServicesReachableIPv4
eth.add_TLV(3, TLV.NULL, nil) # OffPremiseServicesReachableIPv6
var mac = bytes().fromhex(string.replace(tas_eth.find("mac", ""), ":", ""))
eth.add_TLV(4, TLV.B1, mac) # HardwareAddress
var ip4 = eth.add_array(5) # IPv4Addresses
ip4.add_TLV(nil, TLV.B1, matter.get_ip_bytes(tas_eth.find("ip", "")))
var ip6 = eth.add_array(6) # IPv6Addresses
ip6.add_TLV(nil, TLV.B1, matter.get_ip_bytes(tas_eth.find("ip6local", "")))
ip6.add_TLV(nil, TLV.B1, matter.get_ip_bytes(tas_eth.find("ip6", "")))
eth.add_TLV(7, TLV.U1, 2) # InterfaceType, p646
end
var tas_wif = tasmota.wifi()
if (tas_wif['up'])
var wif = nwi.add_struct(nil)
wif.add_TLV(0, TLV.UTF1, 'wifi') # Name
wif.add_TLV(1, TLV.BOOL, 1) # IsOperational
wif.add_TLV(2, TLV.BOOL, 1) # OffPremiseServicesReachableIPv4
wif.add_TLV(3, TLV.NULL, nil) # OffPremiseServicesReachableIPv6
var mac = bytes().fromhex(string.replace(tas_wif.find("mac", ""), ":", ""))
wif.add_TLV(4, TLV.B1, mac) # HardwareAddress
var ip4 = wif.add_array(5) # IPv4Addresses
ip4.add_TLV(nil, TLV.B1, matter.get_ip_bytes(tas_wif.find("ip", "")))
var ip6 = wif.add_array(6) # IPv6Addresses
ip6.add_TLV(nil, TLV.B1, matter.get_ip_bytes(tas_wif.find("ip6local", "")))
ip6.add_TLV(nil, TLV.B1, matter.get_ip_bytes(tas_wif.find("ip6", "")))
wif.add_TLV(7, TLV.U1, 1) # InterfaceType, p646
end
return nwi
elif attribute == 0x0001 # ---------- RebootCount u16 ----------
return TLV.create_TLV(TLV.U2, tasmota.cmd("Status 1")['StatusPRM']['BootCount'])

View File

@ -563,7 +563,7 @@ class Matter_TLV
#############################################################
# adders
def add_TLV(tag, t, value)
if value != nil
if value != nil || t == matter.TLV.NULL
var v = self.TLV.Matter_TLV_item(self)
v.tag_sub = tag
v.typ = t

View File

@ -2198,32 +2198,39 @@ be_local_closure(Matter_TLV_list_add_TLV, /* name */
0, /* has sup protos */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 6]) { /* constants */
/* K0 */ be_nested_str_weak(TLV),
/* K1 */ be_nested_str_weak(Matter_TLV_item),
/* K2 */ be_nested_str_weak(tag_sub),
/* K3 */ be_nested_str_weak(typ),
/* K4 */ be_nested_str_weak(val),
/* K5 */ be_nested_str_weak(push),
( &(const bvalue[ 8]) { /* constants */
/* K0 */ be_nested_str_weak(matter),
/* K1 */ be_nested_str_weak(TLV),
/* K2 */ be_nested_str_weak(NULL),
/* K3 */ be_nested_str_weak(Matter_TLV_item),
/* K4 */ be_nested_str_weak(tag_sub),
/* K5 */ be_nested_str_weak(typ),
/* K6 */ be_nested_str_weak(val),
/* K7 */ be_nested_str_weak(push),
}),
be_str_weak(add_TLV),
&be_const_str_solidified,
( &(const binstruction[15]) { /* code */
( &(const binstruction[20]) { /* code */
0x4C100000, // 0000 LDNIL R4
0x20100604, // 0001 NE R4 R3 R4
0x7812000A, // 0002 JMPF R4 #000E
0x88100100, // 0003 GETMBR R4 R0 K0
0x8C100901, // 0004 GETMET R4 R4 K1
0x5C180000, // 0005 MOVE R6 R0
0x7C100400, // 0006 CALL R4 2
0x90120401, // 0007 SETMBR R4 K2 R1
0x90120602, // 0008 SETMBR R4 K3 R2
0x90120803, // 0009 SETMBR R4 K4 R3
0x88140104, // 000A GETMBR R5 R0 K4
0x8C140B05, // 000B GETMET R5 R5 K5
0x5C1C0800, // 000C MOVE R7 R4
0x7C140400, // 000D CALL R5 2
0x80040000, // 000E RET 1 R0
0x74120004, // 0002 JMPT R4 #0008
0xB8120000, // 0003 GETNGBL R4 K0
0x88100901, // 0004 GETMBR R4 R4 K1
0x88100902, // 0005 GETMBR R4 R4 K2
0x1C100404, // 0006 EQ R4 R2 R4
0x7812000A, // 0007 JMPF R4 #0013
0x88100101, // 0008 GETMBR R4 R0 K1
0x8C100903, // 0009 GETMET R4 R4 K3
0x5C180000, // 000A MOVE R6 R0
0x7C100400, // 000B CALL R4 2
0x90120801, // 000C SETMBR R4 K4 R1
0x90120A02, // 000D SETMBR R4 K5 R2
0x90120C03, // 000E SETMBR R4 K6 R3
0x88140106, // 000F GETMBR R5 R0 K6
0x8C140B07, // 0010 GETMET R5 R5 K7
0x5C1C0800, // 0011 MOVE R7 R4
0x7C140400, // 0012 CALL R5 2
0x80040000, // 0013 RET 1 R0
})
)
);