mirror of
https://github.com/arendst/Tasmota.git
synced 2025-07-22 18:26:30 +00:00
ESP32 preliminary support for Matter protocol, milestone 1 (commissioning) (#17871)
* ESP32 preliminary support for Matter protocol, milestone 1 (commissioning) * Fix case
This commit is contained in:
parent
e8056df1ad
commit
a483991ba3
@ -11,6 +11,7 @@ All notable changes to this project will be documented in this file.
|
||||
- support for SEN5X gas and air quality sensor by Tyeth Gundry (#17736)
|
||||
- Berry add ``mdns`` advanced features and query
|
||||
- ESP32 support for Biomine BioPDU 625x12 (#17857)
|
||||
- ESP32 preliminary support for Matter protocol, milestone 1 (commissioning)
|
||||
|
||||
### Breaking Changed
|
||||
- Berry energy_ctypes changed with new energy driver
|
||||
|
@ -65,6 +65,9 @@ be_extern_native_module(lv_tasmota);
|
||||
be_extern_native_module(haspmota);
|
||||
#endif // USE_LVGL_HASPMOTA
|
||||
#endif // USE_LVGL
|
||||
#ifdef USE_MATTER_DEVICE
|
||||
be_extern_native_module(matter);
|
||||
#endif // USE_MATTER_DEVICE
|
||||
|
||||
/* user-defined modules declare start */
|
||||
|
||||
@ -175,6 +178,9 @@ BERRY_LOCAL const bntvmodule* const be_module_table[] = {
|
||||
#ifdef USE_DISCOVERY
|
||||
&be_native_module(mdns),
|
||||
#endif // USE_DISCOVERY
|
||||
#ifdef USE_MATTER_DEVICE
|
||||
&be_native_module(matter),
|
||||
#endif // USE_MATTER_DEVICE
|
||||
#endif // TASMOTA
|
||||
/* user-defined modules register end */
|
||||
NULL /* do not remove */
|
||||
|
121
lib/libesp32/berry_matter/generate/Matter_generate_c.be
Normal file
121
lib/libesp32/berry_matter/generate/Matter_generate_c.be
Normal file
@ -0,0 +1,121 @@
|
||||
# ../../berry/berry -s -g Matter_generate_c.be
|
||||
#
|
||||
# generate C headers
|
||||
|
||||
import matter_clusters
|
||||
var c = matter_clusters
|
||||
|
||||
|
||||
#################################################################################
|
||||
# Simple insertion sort - sorts the list in place, and returns the list
|
||||
#################################################################################
|
||||
def sort(l) for i:1..size(l)-1 var k = l[i] var j = i while (j > 0) && (l[j-1] > k) l[j] = l[j-1] j -= 1 end l[j] = k end return l end
|
||||
|
||||
# keys to llist
|
||||
def k2l(m) var r=[] for k:m.keys() r.push(k) end return sort(r) end
|
||||
|
||||
var cl_keys = {}
|
||||
for cl:c
|
||||
for k:cl.keys()
|
||||
cl_keys[k] = true
|
||||
end
|
||||
end
|
||||
|
||||
var attr_ids = {}
|
||||
var attr_keys = {}
|
||||
var attr_types = {}
|
||||
for cl:c
|
||||
for attr:cl['attributes']
|
||||
attr_ids[attr['attributeId']] = true
|
||||
for k:attr.keys()
|
||||
attr_keys[k] = true
|
||||
end
|
||||
attr_types[attr['type']] = true
|
||||
end
|
||||
end
|
||||
|
||||
import string
|
||||
|
||||
# prepare file
|
||||
f=open("be_matter_clusters.h", "w")
|
||||
def fprint(*l)
|
||||
f.write(l.concat(" "))
|
||||
f.write("\n")
|
||||
end
|
||||
|
||||
# fprint("Cluster keys:",k2l(cl_keys))
|
||||
# fprint("Attribute ids:",k2l(attr_ids))
|
||||
# fprint("Attribute keys:",k2l(attr_keys))
|
||||
# fprint("Attribute types:",k2l(attr_types))
|
||||
|
||||
var cl_id_name = {}
|
||||
for cl:c
|
||||
cl_id_name[cl['clusterId']] = cl['clusterName']
|
||||
end
|
||||
var cl_ids = k2l(cl_id_name)
|
||||
|
||||
fprint("/*********************************************************************************\\")
|
||||
fprint("* Compact form for attributes and clusters")
|
||||
fprint("*")
|
||||
fprint("* Generated content, do not edit")
|
||||
fprint("\\*********************************************************************************/")
|
||||
fprint()
|
||||
fprint("typedef struct {")
|
||||
fprint(" uint16_t id;")
|
||||
fprint(" uint8_t type;")
|
||||
fprint(" uint8_t flags;")
|
||||
fprint(" const char* name;")
|
||||
fprint("} matter_attribute_t;")
|
||||
fprint()
|
||||
fprint("typedef struct {")
|
||||
fprint(" uint16_t id;")
|
||||
fprint(" const char* name;")
|
||||
fprint("} matter_command_t;")
|
||||
fprint()
|
||||
fprint("typedef struct {")
|
||||
fprint(" uint16_t id;")
|
||||
fprint(" const char* name;")
|
||||
fprint(" const matter_attribute_t* attributes;")
|
||||
fprint(" const matter_command_t* commands;")
|
||||
fprint("} matter_cluster_t;")
|
||||
fprint()
|
||||
for cl:cl_ids
|
||||
fprint(string.format("const matter_attribute_t matter_Attributes_%04X[] = {", cl))
|
||||
var attributes = c[cl_id_name[cl]]['attributes']
|
||||
var attr_id_name = {}
|
||||
for attr:attributes
|
||||
attr_id_name[attr['attributeId']] = attr['attributeName']
|
||||
end
|
||||
var attr_ids_local = k2l(attr_id_name)
|
||||
|
||||
for attr_id:attr_ids_local
|
||||
fprint(string.format(' { 0x%04X, %i, 0x%02X, "%s" },', attr_id, 0, 0, attributes[attr_id]['attributeName']))
|
||||
end
|
||||
fprint(' { 0xFFFF, 0, 0x00, NULL },')
|
||||
fprint("};")
|
||||
fprint()
|
||||
# commands
|
||||
fprint(string.format("const matter_command_t matter_Commands_%04X[] = {", cl))
|
||||
var commands = c[cl_id_name[cl]]['commands']
|
||||
var cmd_id_name = {}
|
||||
for cmd:commands
|
||||
cmd_id_name[cmd['commandId']] = cmd['commandName']
|
||||
end
|
||||
var cmd_ids_local = k2l(cmd_id_name)
|
||||
|
||||
for cmd_id:cmd_ids_local
|
||||
fprint(string.format(' { 0x%04X, "%s" },', cmd_id, commands[cmd_id]['commandName']))
|
||||
end
|
||||
fprint(' { 0xFFFF, NULL },')
|
||||
fprint("};")
|
||||
fprint()
|
||||
end
|
||||
|
||||
fprint("const matter_cluster_t matterAllClusters[] = {")
|
||||
for cl:cl_ids
|
||||
fprint(string.format(' { 0x%04X, "%s", matter_Attributes_%04X, matter_Commands_%04X },', cl, cl_id_name[cl], cl, cl))
|
||||
end
|
||||
fprint(' { 0xFFFF, NULL, NULL },')
|
||||
fprint("};")
|
||||
|
||||
f.close()
|
351
lib/libesp32/berry_matter/generate/be_matter_certs.h
Normal file
351
lib/libesp32/berry_matter/generate/be_matter_certs.h
Normal file
@ -0,0 +1,351 @@
|
||||
// Certificates and credentials from demo
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
const uint8_t kDevelopmentPAI_Cert_FFF1[463] = {
|
||||
0x30, 0x82, 0x01, 0xcb, 0x30, 0x82, 0x01, 0x71, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x08, 0x56, 0xad, 0x82, 0x22, 0xad, 0x94,
|
||||
0x5b, 0x64, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x30, 0x31, 0x18, 0x30, 0x16, 0x06,
|
||||
0x03, 0x55, 0x04, 0x03, 0x0c, 0x0f, 0x4d, 0x61, 0x74, 0x74, 0x65, 0x72, 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x50, 0x41, 0x41,
|
||||
0x31, 0x14, 0x30, 0x12, 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0xa2, 0x7c, 0x02, 0x01, 0x0c, 0x04, 0x46, 0x46, 0x46,
|
||||
0x31, 0x30, 0x20, 0x17, 0x0d, 0x32, 0x32, 0x30, 0x32, 0x30, 0x35, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x39,
|
||||
0x39, 0x39, 0x39, 0x31, 0x32, 0x33, 0x31, 0x32, 0x33, 0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x3d, 0x31, 0x25, 0x30, 0x23, 0x06,
|
||||
0x03, 0x55, 0x04, 0x03, 0x0c, 0x1c, 0x4d, 0x61, 0x74, 0x74, 0x65, 0x72, 0x20, 0x44, 0x65, 0x76, 0x20, 0x50, 0x41, 0x49, 0x20,
|
||||
0x30, 0x78, 0x46, 0x46, 0x46, 0x31, 0x20, 0x6e, 0x6f, 0x20, 0x50, 0x49, 0x44, 0x31, 0x14, 0x30, 0x12, 0x06, 0x0a, 0x2b, 0x06,
|
||||
0x01, 0x04, 0x01, 0x82, 0xa2, 0x7c, 0x02, 0x01, 0x0c, 0x04, 0x46, 0x46, 0x46, 0x31, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a,
|
||||
0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x41,
|
||||
0x9a, 0x93, 0x15, 0xc2, 0x17, 0x3e, 0x0c, 0x8c, 0x87, 0x6d, 0x03, 0xcc, 0xfc, 0x94, 0x48, 0x52, 0x64, 0x7f, 0x7f, 0xec, 0x5e,
|
||||
0x50, 0x82, 0xf4, 0x05, 0x99, 0x28, 0xec, 0xa8, 0x94, 0xc5, 0x94, 0x15, 0x13, 0x09, 0xac, 0x63, 0x1e, 0x4c, 0xb0, 0x33, 0x92,
|
||||
0xaf, 0x68, 0x4b, 0x0b, 0xaf, 0xb7, 0xe6, 0x5b, 0x3b, 0x81, 0x62, 0xc2, 0xf5, 0x2b, 0xf9, 0x31, 0xb8, 0xe7, 0x7a, 0xaa, 0x82,
|
||||
0xa3, 0x66, 0x30, 0x64, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff,
|
||||
0x02, 0x01, 0x00, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x1d,
|
||||
0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x63, 0x54, 0x0e, 0x47, 0xf6, 0x4b, 0x1c, 0x38, 0xd1, 0x38, 0x84, 0xa4,
|
||||
0x62, 0xd1, 0x6c, 0x19, 0x5d, 0x8f, 0xfb, 0x3c, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14,
|
||||
0x6a, 0xfd, 0x22, 0x77, 0x1f, 0x51, 0x1f, 0xec, 0xbf, 0x16, 0x41, 0x97, 0x67, 0x10, 0xdc, 0xdc, 0x31, 0xa1, 0x71, 0x7e, 0x30,
|
||||
0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, 0x30, 0x45, 0x02, 0x21, 0x00, 0xb2, 0xef,
|
||||
0x27, 0xf4, 0x9a, 0xe9, 0xb5, 0x0f, 0xb9, 0x1e, 0xea, 0xc9, 0x4c, 0x4d, 0x0b, 0xdb, 0xb8, 0xd7, 0x92, 0x9c, 0x6c, 0xb8, 0x8f,
|
||||
0xac, 0xe5, 0x29, 0x36, 0x8d, 0x12, 0x05, 0x4c, 0x0c, 0x02, 0x20, 0x65, 0x5d, 0xc9, 0x2b, 0x86, 0xbd, 0x90, 0x98, 0x82, 0xa6,
|
||||
0xc6, 0x21, 0x77, 0xb8, 0x25, 0xd7, 0xd0, 0x5e, 0xdb, 0xe7, 0xc2, 0x2f, 0x9f, 0xea, 0x71, 0x22, 0x0e, 0x7e, 0xa7, 0x03, 0xf8,
|
||||
0x91,
|
||||
};
|
||||
|
||||
const uint8_t kDevelopmentPAI_PublicKey_FFF1[65] = {
|
||||
0x04, 0x41, 0x9a, 0x93, 0x15, 0xc2, 0x17, 0x3e, 0x0c, 0x8c, 0x87, 0x6d, 0x03, 0xcc, 0xfc, 0x94, 0x48,
|
||||
0x52, 0x64, 0x7f, 0x7f, 0xec, 0x5e, 0x50, 0x82, 0xf4, 0x05, 0x99, 0x28, 0xec, 0xa8, 0x94, 0xc5, 0x94,
|
||||
0x15, 0x13, 0x09, 0xac, 0x63, 0x1e, 0x4c, 0xb0, 0x33, 0x92, 0xaf, 0x68, 0x4b, 0x0b, 0xaf, 0xb7, 0xe6,
|
||||
0x5b, 0x3b, 0x81, 0x62, 0xc2, 0xf5, 0x2b, 0xf9, 0x31, 0xb8, 0xe7, 0x7a, 0xaa, 0x82,
|
||||
};
|
||||
const uint8_t kDevelopmentPAI_PrivateKey_FFF1[32] = {
|
||||
0xc1, 0xab, 0x5f, 0xe2, 0x84, 0xb4, 0xc1, 0x89, 0x40, 0xa5, 0x31, 0x61, 0xf8, 0x06, 0x94, 0x40,
|
||||
0x50, 0xa1, 0x69, 0x7b, 0x71, 0x76, 0x1d, 0x38, 0x53, 0x37, 0xa8, 0xa3, 0xcd, 0x09, 0x5c, 0x34,
|
||||
};
|
||||
|
||||
/*
|
||||
Certificate:
|
||||
Data:
|
||||
Version: 3 (0x2)
|
||||
Serial Number:
|
||||
56:ad:82:22:ad:94:5b:64
|
||||
Signature Algorithm: ecdsa-with-SHA256
|
||||
Issuer: CN = Matter Test PAA, 1.3.6.1.4.1.37244.2.1 = FFF1
|
||||
Validity
|
||||
Not Before: Feb 5 00:00:00 2022 GMT
|
||||
Not After : Dec 31 23:59:59 9999 GMT
|
||||
Subject: CN = Matter Dev PAI 0xFFF1 no PID, 1.3.6.1.4.1.37244.2.1 = FFF1
|
||||
Subject Public Key Info:
|
||||
Public Key Algorithm: id-ecPublicKey
|
||||
Public-Key: (256 bit)
|
||||
pub:
|
||||
04:41:9a:93:15:c2:17:3e:0c:8c:87:6d:03:cc:fc:
|
||||
94:48:52:64:7f:7f:ec:5e:50:82:f4:05:99:28:ec:
|
||||
a8:94:c5:94:15:13:09:ac:63:1e:4c:b0:33:92:af:
|
||||
68:4b:0b:af:b7:e6:5b:3b:81:62:c2:f5:2b:f9:31:
|
||||
b8:e7:7a:aa:82
|
||||
ASN1 OID: prime256v1
|
||||
NIST CURVE: P-256
|
||||
X509v3 extensions:
|
||||
X509v3 Basic Constraints: critical
|
||||
CA:TRUE, pathlen:0
|
||||
X509v3 Key Usage: critical
|
||||
Certificate Sign, CRL Sign
|
||||
X509v3 Subject Key Identifier:
|
||||
63:54:0E:47:F6:4B:1C:38:D1:38:84:A4:62:D1:6C:19:5D:8F:FB:3C
|
||||
X509v3 Authority Key Identifier:
|
||||
keyid:6A:FD:22:77:1F:51:1F:EC:BF:16:41:97:67:10:DC:DC:31:A1:71:7E
|
||||
|
||||
Signature Algorithm: ecdsa-with-SHA256
|
||||
30:45:02:21:00:b2:ef:27:f4:9a:e9:b5:0f:b9:1e:ea:c9:4c:
|
||||
4d:0b:db:b8:d7:92:9c:6c:b8:8f:ac:e5:29:36:8d:12:05:4c:
|
||||
0c:02:20:65:5d:c9:2b:86:bd:90:98:82:a6:c6:21:77:b8:25:
|
||||
d7:d0:5e:db:e7:c2:2f:9f:ea:71:22:0e:7e:a7:03:f8:91
|
||||
*/
|
||||
|
||||
/*
|
||||
ASN.1
|
||||
|
||||
SEQUENCE (3 elem)
|
||||
SEQUENCE (8 elem)
|
||||
[0] (1 elem)
|
||||
INTEGER 2
|
||||
INTEGER (63 bit) 6245791343685426020
|
||||
SEQUENCE (1 elem)
|
||||
OBJECT IDENTIFIER 1.2.840.10045.4.3.2 ecdsaWithSHA256 (ANSI X9.62 ECDSA algorithm with SHA256)
|
||||
SEQUENCE (2 elem)
|
||||
SET (1 elem)
|
||||
SEQUENCE (2 elem)
|
||||
OBJECT IDENTIFIER 2.5.4.3 commonName (X.520 DN component)
|
||||
UTF8String Matter Test PAA
|
||||
SET (1 elem)
|
||||
SEQUENCE (2 elem)
|
||||
OBJECT IDENTIFIER 1.3.6.1.4.1.37244.2.1
|
||||
UTF8String FFF1
|
||||
SEQUENCE (2 elem)
|
||||
UTCTime 2022-02-05 00:00:00 UTC
|
||||
GeneralizedTime 9999-12-31 23:59:59 UTC
|
||||
SEQUENCE (2 elem)
|
||||
SET (1 elem)
|
||||
SEQUENCE (2 elem)
|
||||
OBJECT IDENTIFIER 2.5.4.3 commonName (X.520 DN component)
|
||||
UTF8String Matter Dev PAI 0xFFF1 no PID
|
||||
SET (1 elem)
|
||||
SEQUENCE (2 elem)
|
||||
OBJECT IDENTIFIER 1.3.6.1.4.1.37244.2.1
|
||||
UTF8String FFF1
|
||||
SEQUENCE (2 elem)
|
||||
SEQUENCE (2 elem)
|
||||
OBJECT IDENTIFIER 1.2.840.10045.2.1 ecPublicKey (ANSI X9.62 public key type)
|
||||
OBJECT IDENTIFIER 1.2.840.10045.3.1.7 prime256v1 (ANSI X9.62 named elliptic curve)
|
||||
BIT STRING (520 bit) 0000010001000001100110101001001100010101110000100001011100111110000011…
|
||||
[3] (1 elem)
|
||||
SEQUENCE (4 elem)
|
||||
SEQUENCE (3 elem)
|
||||
OBJECT IDENTIFIER 2.5.29.19 basicConstraints (X.509 extension)
|
||||
BOOLEAN true
|
||||
OCTET STRING (8 byte) 30060101FF020100
|
||||
SEQUENCE (2 elem)
|
||||
BOOLEAN true
|
||||
INTEGER 0
|
||||
SEQUENCE (3 elem)
|
||||
OBJECT IDENTIFIER 2.5.29.15 keyUsage (X.509 extension)
|
||||
BOOLEAN true
|
||||
OCTET STRING (4 byte) 03020106
|
||||
BIT STRING (7 bit) 0000011
|
||||
SEQUENCE (2 elem)
|
||||
OBJECT IDENTIFIER 2.5.29.14 subjectKeyIdentifier (X.509 extension)
|
||||
OCTET STRING (22 byte) 041463540E47F64B1C38D13884A462D16C195D8FFB3C
|
||||
OCTET STRING (20 byte) 63540E47F64B1C38D13884A462D16C195D8FFB3C
|
||||
SEQUENCE (2 elem)
|
||||
OBJECT IDENTIFIER 2.5.29.35 authorityKeyIdentifier (X.509 extension)
|
||||
OCTET STRING (24 byte) 301680146AFD22771F511FECBF1641976710DCDC31A1717E
|
||||
SEQUENCE (1 elem)
|
||||
[0] (20 byte) 6AFD22771F511FECBF1641976710DCDC31A1717E
|
||||
SEQUENCE (1 elem)
|
||||
Offset: 377
|
||||
Length: 2+10
|
||||
(constructed)
|
||||
Value:
|
||||
(1 elem)
|
||||
OBJECT IDENTIFIER 1.2.840.10045.4.3.2 ecdsaWithSHA256 (ANSI X9.62 ECDSA algorithm with SHA256)
|
||||
BIT STRING (568 bit) 0011000001000101000000100010000100000000101100101110111100100111111101…
|
||||
SEQUENCE (2 elem)
|
||||
INTEGER (256 bit) 8093423925895219711386938045632983408737245943652937189339272815747009…
|
||||
INTEGER (255 bit) 4584930290841753608947726397552150715869097421278636946745345682393985…
|
||||
*/
|
||||
|
||||
const uint8_t kDevelopmentDAC_Cert_FFF1_8000[493] = {
|
||||
0x30, 0x82, 0x01, 0xe9, 0x30, 0x82, 0x01, 0x8e, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x08, 0x23, 0x8a, 0x64, 0x7b, 0xbc, 0x4c,
|
||||
0x30, 0xdd, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x3d, 0x31, 0x25, 0x30, 0x23, 0x06,
|
||||
0x03, 0x55, 0x04, 0x03, 0x0c, 0x1c, 0x4d, 0x61, 0x74, 0x74, 0x65, 0x72, 0x20, 0x44, 0x65, 0x76, 0x20, 0x50, 0x41, 0x49, 0x20,
|
||||
0x30, 0x78, 0x46, 0x46, 0x46, 0x31, 0x20, 0x6e, 0x6f, 0x20, 0x50, 0x49, 0x44, 0x31, 0x14, 0x30, 0x12, 0x06, 0x0a, 0x2b, 0x06,
|
||||
0x01, 0x04, 0x01, 0x82, 0xa2, 0x7c, 0x02, 0x01, 0x0c, 0x04, 0x46, 0x46, 0x46, 0x31, 0x30, 0x20, 0x17, 0x0d, 0x32, 0x32, 0x30,
|
||||
0x32, 0x30, 0x35, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x39, 0x39, 0x39, 0x39, 0x31, 0x32, 0x33, 0x31, 0x32,
|
||||
0x33, 0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x53, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x1c, 0x4d, 0x61,
|
||||
0x74, 0x74, 0x65, 0x72, 0x20, 0x44, 0x65, 0x76, 0x20, 0x44, 0x41, 0x43, 0x20, 0x30, 0x78, 0x46, 0x46, 0x46, 0x31, 0x2f, 0x30,
|
||||
0x78, 0x38, 0x30, 0x30, 0x30, 0x31, 0x14, 0x30, 0x12, 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0xa2, 0x7c, 0x02, 0x01,
|
||||
0x0c, 0x04, 0x46, 0x46, 0x46, 0x31, 0x31, 0x14, 0x30, 0x12, 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0xa2, 0x7c, 0x02,
|
||||
0x02, 0x0c, 0x04, 0x38, 0x30, 0x30, 0x30, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06,
|
||||
0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x62, 0xdb, 0x16, 0xba, 0xde, 0xa3, 0x26, 0xa6,
|
||||
0xdb, 0x84, 0x81, 0x4a, 0x06, 0x3f, 0xc6, 0xc7, 0xe9, 0xe2, 0xb1, 0x01, 0xb7, 0x21, 0x64, 0x8e, 0xba, 0x4e, 0x5a, 0xc8, 0x40,
|
||||
0xf5, 0xda, 0x30, 0x1e, 0xe6, 0x18, 0x12, 0x4e, 0xb4, 0x18, 0x0e, 0x2f, 0xc3, 0xa2, 0x04, 0x7a, 0x56, 0x4b, 0xa9, 0xbc, 0xfa,
|
||||
0x0b, 0xf7, 0x1f, 0x60, 0xce, 0x89, 0x30, 0xf1, 0xe7, 0xf6, 0x6e, 0xc8, 0xd7, 0x28, 0xa3, 0x60, 0x30, 0x5e, 0x30, 0x0c, 0x06,
|
||||
0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x02, 0x30, 0x00, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff,
|
||||
0x04, 0x04, 0x03, 0x02, 0x07, 0x80, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xbc, 0xf7, 0xb0, 0x07,
|
||||
0x49, 0x70, 0x63, 0x60, 0x6a, 0x26, 0xbe, 0x4e, 0x08, 0x7c, 0x59, 0x56, 0x87, 0x74, 0x5a, 0x5a, 0x30, 0x1f, 0x06, 0x03, 0x55,
|
||||
0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x63, 0x54, 0x0e, 0x47, 0xf6, 0x4b, 0x1c, 0x38, 0xd1, 0x38, 0x84, 0xa4, 0x62,
|
||||
0xd1, 0x6c, 0x19, 0x5d, 0x8f, 0xfb, 0x3c, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x49,
|
||||
0x00, 0x30, 0x46, 0x02, 0x21, 0x00, 0x97, 0x97, 0x11, 0xec, 0x9e, 0x76, 0x18, 0xce, 0x41, 0x80, 0x11, 0x32, 0xc2, 0x50, 0xdb,
|
||||
0x70, 0x76, 0x74, 0x63, 0x0c, 0xd5, 0x8c, 0x12, 0xc6, 0xe2, 0x31, 0x5f, 0x08, 0xd0, 0x1e, 0xe1, 0x78, 0x02, 0x21, 0x00, 0xec,
|
||||
0xfc, 0x13, 0x06, 0xbd, 0x2a, 0x13, 0x3d, 0x12, 0x2a, 0x27, 0x86, 0x10, 0xea, 0x3d, 0xca, 0x47, 0xf0, 0x5c, 0x7a, 0x8b, 0x80,
|
||||
0x5f, 0xa7, 0x1c, 0x6f, 0xf4, 0x15, 0x38, 0xa8, 0x64, 0xc8,
|
||||
};
|
||||
|
||||
/*
|
||||
Decoded cert: openssl x509 -inform der -in DAC_Cert_FFF1_8000.der -text -noout
|
||||
|
||||
Certificate:
|
||||
Data:
|
||||
Version: 3 (0x2)
|
||||
Serial Number:
|
||||
23:8a:64:7b:bc:4c:30:dd
|
||||
Signature Algorithm: ecdsa-with-SHA256
|
||||
Issuer: CN = Matter Dev PAI 0xFFF1 no PID, 1.3.6.1.4.1.37244.2.1 = FFF1
|
||||
Validity
|
||||
Not Before: Feb 5 00:00:00 2022 GMT
|
||||
Not After : Dec 31 23:59:59 9999 GMT
|
||||
Subject: CN = Matter Dev DAC 0xFFF1/0x8000, 1.3.6.1.4.1.37244.2.1 = FFF1, 1.3.6.1.4.1.37244.2.2 = 8000
|
||||
Subject Public Key Info:
|
||||
Public Key Algorithm: id-ecPublicKey
|
||||
Public-Key: (256 bit)
|
||||
pub:
|
||||
04:62:db:16:ba:de:a3:26:a6:db:84:81:4a:06:3f:
|
||||
c6:c7:e9:e2:b1:01:b7:21:64:8e:ba:4e:5a:c8:40:
|
||||
f5:da:30:1e:e6:18:12:4e:b4:18:0e:2f:c3:a2:04:
|
||||
7a:56:4b:a9:bc:fa:0b:f7:1f:60:ce:89:30:f1:e7:
|
||||
f6:6e:c8:d7:28
|
||||
ASN1 OID: prime256v1
|
||||
NIST CURVE: P-256
|
||||
X509v3 extensions:
|
||||
X509v3 Basic Constraints: critical
|
||||
CA:FALSE
|
||||
X509v3 Key Usage: critical
|
||||
Digital Signature
|
||||
X509v3 Subject Key Identifier:
|
||||
BC:F7:B0:07:49:70:63:60:6A:26:BE:4E:08:7C:59:56:87:74:5A:5A
|
||||
X509v3 Authority Key Identifier:
|
||||
keyid:63:54:0E:47:F6:4B:1C:38:D1:38:84:A4:62:D1:6C:19:5D:8F:FB:3C
|
||||
|
||||
Signature Algorithm: ecdsa-with-SHA256
|
||||
30:46:02:21:00:97:97:11:ec:9e:76:18:ce:41:80:11:32:c2:
|
||||
50:db:70:76:74:63:0c:d5:8c:12:c6:e2:31:5f:08:d0:1e:e1:
|
||||
78:02:21:00:ec:fc:13:06:bd:2a:13:3d:12:2a:27:86:10:ea:
|
||||
3d:ca:47:f0:5c:7a:8b:80:5f:a7:1c:6f:f4:15:38:a8:64:c8
|
||||
|
||||
*/
|
||||
|
||||
/* Decoded ASN.1
|
||||
|
||||
SEQUENCE (3 elem)
|
||||
SEQUENCE (8 elem)
|
||||
[0] (1 elem)
|
||||
INTEGER 2
|
||||
INTEGER (62 bit) 2560969820716413149
|
||||
SEQUENCE (1 elem)
|
||||
OBJECT IDENTIFIER 1.2.840.10045.4.3.2 ecdsaWithSHA256 (ANSI X9.62 ECDSA algorithm with SHA256)
|
||||
SEQUENCE (2 elem)
|
||||
SET (1 elem)
|
||||
SEQUENCE (2 elem)
|
||||
OBJECT IDENTIFIER 2.5.4.3 commonName (X.520 DN component)
|
||||
UTF8String Matter Dev PAI 0xFFF1 no PID
|
||||
SET (1 elem)
|
||||
SEQUENCE (2 elem)
|
||||
OBJECT IDENTIFIER 1.3.6.1.4.1.37244.2.1
|
||||
UTF8String FFF1
|
||||
SEQUENCE (2 elem)
|
||||
UTCTime 2022-02-05 00:00:00 UTC
|
||||
GeneralizedTime 9999-12-31 23:59:59 UTC
|
||||
SEQUENCE (3 elem)
|
||||
SET (1 elem)
|
||||
SEQUENCE (2 elem)
|
||||
OBJECT IDENTIFIER 2.5.4.3 commonName (X.520 DN component)
|
||||
UTF8String Matter Dev DAC 0xFFF1/0x8000
|
||||
SET (1 elem)
|
||||
SEQUENCE (2 elem)
|
||||
OBJECT IDENTIFIER 1.3.6.1.4.1.37244.2.1
|
||||
UTF8String FFF1
|
||||
SET (1 elem)
|
||||
SEQUENCE (2 elem)
|
||||
OBJECT IDENTIFIER 1.3.6.1.4.1.37244.2.2
|
||||
UTF8String 8000
|
||||
SEQUENCE (2 elem)
|
||||
SEQUENCE (2 elem)
|
||||
OBJECT IDENTIFIER 1.2.840.10045.2.1 ecPublicKey (ANSI X9.62 public key type)
|
||||
OBJECT IDENTIFIER 1.2.840.10045.3.1.7 prime256v1 (ANSI X9.62 named elliptic curve)
|
||||
BIT STRING (520 bit) 0000010001100010110110110001011010111010110111101010001100100110101001…
|
||||
[3] (1 elem)
|
||||
SEQUENCE (4 elem)
|
||||
SEQUENCE (3 elem)
|
||||
OBJECT IDENTIFIER 2.5.29.19 basicConstraints (X.509 extension)
|
||||
BOOLEAN true
|
||||
OCTET STRING (2 byte) 3000
|
||||
SEQUENCE (0 elem)
|
||||
SEQUENCE (3 elem)
|
||||
OBJECT IDENTIFIER 2.5.29.15 keyUsage (X.509 extension)
|
||||
BOOLEAN true
|
||||
OCTET STRING (4 byte) 03020780
|
||||
BIT STRING (1 bit) 1
|
||||
SEQUENCE (2 elem)
|
||||
OBJECT IDENTIFIER 2.5.29.14 subjectKeyIdentifier (X.509 extension)
|
||||
OCTET STRING (22 byte) 0414BCF7B007497063606A26BE4E087C595687745A5A
|
||||
OCTET STRING (20 byte) BCF7B007497063606A26BE4E087C595687745A5A
|
||||
SEQUENCE (2 elem)
|
||||
OBJECT IDENTIFIER 2.5.29.35 authorityKeyIdentifier (X.509 extension)
|
||||
OCTET STRING (24 byte) 3016801463540E47F64B1C38D13884A462D16C195D8FFB3C
|
||||
SEQUENCE (1 elem)
|
||||
[0] (20 byte) 63540E47F64B1C38D13884A462D16C195D8FFB3C
|
||||
SEQUENCE (1 elem)
|
||||
OBJECT IDENTIFIER 1.2.840.10045.4.3.2 ecdsaWithSHA256 (ANSI X9.62 ECDSA algorithm with SHA256)
|
||||
BIT STRING (576 bit) 0011000001000110000000100010000100000000100101111001011100010001111011…
|
||||
SEQUENCE (2 elem)
|
||||
INTEGER (256 bit) 6856615775177799389454949658700013485116050405241433595512074226650010…
|
||||
INTEGER (256 bit) 1071912090408366213691559168363210336766445086127676108978024779974417…
|
||||
*/
|
||||
|
||||
const uint8_t kDevelopmentDAC_PublicKey_FFF1_8000[65] = {
|
||||
0x04, 0x62, 0xdb, 0x16, 0xba, 0xde, 0xa3, 0x26, 0xa6, 0xdb, 0x84, 0x81, 0x4a, 0x06, 0x3f, 0xc6, 0xc7,
|
||||
0xe9, 0xe2, 0xb1, 0x01, 0xb7, 0x21, 0x64, 0x8e, 0xba, 0x4e, 0x5a, 0xc8, 0x40, 0xf5, 0xda, 0x30, 0x1e,
|
||||
0xe6, 0x18, 0x12, 0x4e, 0xb4, 0x18, 0x0e, 0x2f, 0xc3, 0xa2, 0x04, 0x7a, 0x56, 0x4b, 0xa9, 0xbc, 0xfa,
|
||||
0x0b, 0xf7, 0x1f, 0x60, 0xce, 0x89, 0x30, 0xf1, 0xe7, 0xf6, 0x6e, 0xc8, 0xd7, 0x28,
|
||||
};
|
||||
|
||||
const uint8_t kDevelopmentDAC_PrivateKey_FFF1_8000[32] = {
|
||||
0xcc, 0xcf, 0x9d, 0xc7, 0x05, 0x0e, 0xf5, 0xd9, 0x0b, 0xe4, 0x57, 0x07, 0xb9, 0x0e, 0x1f, 0x87,
|
||||
0x5d, 0x59, 0xbe, 0x1f, 0xa9, 0x42, 0xe8, 0xed, 0x2e, 0x42, 0x72, 0x03, 0xf6, 0xc2, 0xee, 0x3d,
|
||||
};
|
||||
|
||||
/* CertificationDeclaration */
|
||||
//-> format_version = 1
|
||||
//-> vendor_id = 0xFFF1
|
||||
//-> product_id_array = [ 0x8000, 0x8001, 0x8002, 0x8003, 0x8004, 0x8005, 0x8006, 0x8007, 0x8008, 0x8009, 0x800A, 0x800B,
|
||||
// 0x800C, 0x800D, 0x800E, 0x800F, 0x8010, 0x8011, 0x8012, 0x8013, 0x8014, 0x8015, 0x8016, 0x8017, 0x8018, 0x8019, 0x801A,
|
||||
// 0x801B, 0x801C, 0x801D, 0x801E, 0x801F, 0x8020, 0x8021, 0x8022, 0x8023, 0x8024, 0x8025, 0x8026, 0x8027, 0x8028, 0x8029,
|
||||
// 0x802A, 0x802B, 0x802C, 0x802D, 0x802E, 0x802F, 0x8030, 0x8031, 0x8032, 0x8033, 0x8034, 0x8035, 0x8036, 0x8037, 0x8038,
|
||||
// 0x8039, 0x803A, 0x803B, 0x803C, 0x803D, 0x803E, 0x803F, 0x8040, 0x8041, 0x8042, 0x8043, 0x8044, 0x8045, 0x8046, 0x8047,
|
||||
// 0x8048, 0x8049, 0x804A, 0x804B, 0x804C, 0x804D, 0x804E, 0x804F, 0x8050, 0x8051, 0x8052, 0x8053, 0x8054, 0x8055, 0x8056,
|
||||
// 0x8057, 0x8058, 0x8059, 0x805A, 0x805B, 0x805C, 0x805D, 0x805E, 0x805F, 0x8060, 0x8061, 0x8062, 0x8063 ]
|
||||
//-> device_type_id = 0x0016
|
||||
//-> certificate_id = "CSA00000SWC00000-00"
|
||||
//-> security_level = 0
|
||||
//-> security_information = 0
|
||||
//-> version_number = 1
|
||||
//-> certification_type = 0
|
||||
//-> dac_origin_vendor_id is not present
|
||||
//-> dac_origin_product_id is not present
|
||||
const uint8_t kCdForAllExamples[539] = {
|
||||
0x30, 0x82, 0x02, 0x17, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02, 0xa0, 0x82, 0x02, 0x08, 0x30,
|
||||
0x82, 0x02, 0x04, 0x02, 0x01, 0x03, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02,
|
||||
0x01, 0x30, 0x82, 0x01, 0x70, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x82, 0x01, 0x61,
|
||||
0x04, 0x82, 0x01, 0x5d, 0x15, 0x24, 0x00, 0x01, 0x25, 0x01, 0xf1, 0xff, 0x36, 0x02, 0x05, 0x00, 0x80, 0x05, 0x01, 0x80,
|
||||
0x05, 0x02, 0x80, 0x05, 0x03, 0x80, 0x05, 0x04, 0x80, 0x05, 0x05, 0x80, 0x05, 0x06, 0x80, 0x05, 0x07, 0x80, 0x05, 0x08,
|
||||
0x80, 0x05, 0x09, 0x80, 0x05, 0x0a, 0x80, 0x05, 0x0b, 0x80, 0x05, 0x0c, 0x80, 0x05, 0x0d, 0x80, 0x05, 0x0e, 0x80, 0x05,
|
||||
0x0f, 0x80, 0x05, 0x10, 0x80, 0x05, 0x11, 0x80, 0x05, 0x12, 0x80, 0x05, 0x13, 0x80, 0x05, 0x14, 0x80, 0x05, 0x15, 0x80,
|
||||
0x05, 0x16, 0x80, 0x05, 0x17, 0x80, 0x05, 0x18, 0x80, 0x05, 0x19, 0x80, 0x05, 0x1a, 0x80, 0x05, 0x1b, 0x80, 0x05, 0x1c,
|
||||
0x80, 0x05, 0x1d, 0x80, 0x05, 0x1e, 0x80, 0x05, 0x1f, 0x80, 0x05, 0x20, 0x80, 0x05, 0x21, 0x80, 0x05, 0x22, 0x80, 0x05,
|
||||
0x23, 0x80, 0x05, 0x24, 0x80, 0x05, 0x25, 0x80, 0x05, 0x26, 0x80, 0x05, 0x27, 0x80, 0x05, 0x28, 0x80, 0x05, 0x29, 0x80,
|
||||
0x05, 0x2a, 0x80, 0x05, 0x2b, 0x80, 0x05, 0x2c, 0x80, 0x05, 0x2d, 0x80, 0x05, 0x2e, 0x80, 0x05, 0x2f, 0x80, 0x05, 0x30,
|
||||
0x80, 0x05, 0x31, 0x80, 0x05, 0x32, 0x80, 0x05, 0x33, 0x80, 0x05, 0x34, 0x80, 0x05, 0x35, 0x80, 0x05, 0x36, 0x80, 0x05,
|
||||
0x37, 0x80, 0x05, 0x38, 0x80, 0x05, 0x39, 0x80, 0x05, 0x3a, 0x80, 0x05, 0x3b, 0x80, 0x05, 0x3c, 0x80, 0x05, 0x3d, 0x80,
|
||||
0x05, 0x3e, 0x80, 0x05, 0x3f, 0x80, 0x05, 0x40, 0x80, 0x05, 0x41, 0x80, 0x05, 0x42, 0x80, 0x05, 0x43, 0x80, 0x05, 0x44,
|
||||
0x80, 0x05, 0x45, 0x80, 0x05, 0x46, 0x80, 0x05, 0x47, 0x80, 0x05, 0x48, 0x80, 0x05, 0x49, 0x80, 0x05, 0x4a, 0x80, 0x05,
|
||||
0x4b, 0x80, 0x05, 0x4c, 0x80, 0x05, 0x4d, 0x80, 0x05, 0x4e, 0x80, 0x05, 0x4f, 0x80, 0x05, 0x50, 0x80, 0x05, 0x51, 0x80,
|
||||
0x05, 0x52, 0x80, 0x05, 0x53, 0x80, 0x05, 0x54, 0x80, 0x05, 0x55, 0x80, 0x05, 0x56, 0x80, 0x05, 0x57, 0x80, 0x05, 0x58,
|
||||
0x80, 0x05, 0x59, 0x80, 0x05, 0x5a, 0x80, 0x05, 0x5b, 0x80, 0x05, 0x5c, 0x80, 0x05, 0x5d, 0x80, 0x05, 0x5e, 0x80, 0x05,
|
||||
0x5f, 0x80, 0x05, 0x60, 0x80, 0x05, 0x61, 0x80, 0x05, 0x62, 0x80, 0x05, 0x63, 0x80, 0x18, 0x24, 0x03, 0x16, 0x2c, 0x04,
|
||||
0x13, 0x43, 0x53, 0x41, 0x30, 0x30, 0x30, 0x30, 0x30, 0x53, 0x57, 0x43, 0x30, 0x30, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30,
|
||||
0x24, 0x05, 0x00, 0x24, 0x06, 0x00, 0x24, 0x07, 0x01, 0x24, 0x08, 0x00, 0x18, 0x31, 0x7c, 0x30, 0x7a, 0x02, 0x01, 0x03,
|
||||
0x80, 0x14, 0xfe, 0x34, 0x3f, 0x95, 0x99, 0x47, 0x76, 0x3b, 0x61, 0xee, 0x45, 0x39, 0x13, 0x13, 0x38, 0x49, 0x4f, 0xe6,
|
||||
0x7d, 0x8e, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x30, 0x0a, 0x06, 0x08, 0x2a,
|
||||
0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x04, 0x46, 0x30, 0x44, 0x02, 0x20, 0x4a, 0x12, 0xf8, 0xd4, 0x2f, 0x90, 0x23,
|
||||
0x5c, 0x05, 0xa7, 0x71, 0x21, 0xcb, 0xeb, 0xae, 0x15, 0xd5, 0x90, 0x14, 0x65, 0x58, 0xe9, 0xc9, 0xb4, 0x7a, 0x1a, 0x38,
|
||||
0xf7, 0xa3, 0x6a, 0x7d, 0xc5, 0x02, 0x20, 0x20, 0xa4, 0x74, 0x28, 0x97, 0xc3, 0x0a, 0xed, 0xa0, 0xa5, 0x6b, 0x36, 0xe1,
|
||||
0x4e, 0xbb, 0xc8, 0x5b, 0xbd, 0xb7, 0x44, 0x93, 0xf9, 0x93, 0x58, 0x1e, 0xb0, 0x44, 0x4e, 0xd6, 0xca, 0x94, 0x0b
|
||||
};
|
1572
lib/libesp32/berry_matter/generate/be_matter_clusters.h
Normal file
1572
lib/libesp32/berry_matter/generate/be_matter_clusters.h
Normal file
File diff suppressed because it is too large
Load Diff
29
lib/libesp32/berry_matter/generate/be_matter_opcodes.h
Normal file
29
lib/libesp32/berry_matter/generate/be_matter_opcodes.h
Normal file
@ -0,0 +1,29 @@
|
||||
/*********************************************************************************\
|
||||
* Compact form for attributes and clusters
|
||||
*
|
||||
* Generated content, do not edit
|
||||
\*********************************************************************************/
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct {
|
||||
uint16_t id;
|
||||
const char* name;
|
||||
} matter_opcode_t;
|
||||
|
||||
const matter_opcode_t matter_OpCodes[] = {
|
||||
{ 0x0000, "MsgCounterSyncReq" },
|
||||
{ 0x0001, "MsgCounterSyncRsp" },
|
||||
{ 0x0010, "MRP_Standalone_Acknowledgement" },
|
||||
{ 0x0020, "PBKDFParamRequest" },
|
||||
{ 0x0021, "PBKDFParamResponse" },
|
||||
{ 0x0022, "PASE_Pake1" },
|
||||
{ 0x0023, "PASE_Pake2" },
|
||||
{ 0x0024, "PASE_Pake3" },
|
||||
{ 0x0030, "CASE_Sigma1" },
|
||||
{ 0x0031, "CASE_Sigma2" },
|
||||
{ 0x0032, "CASE_Sigma3" },
|
||||
{ 0x0033, "CASE_Sigma2_Resume" },
|
||||
{ 0x0040, "StatusReport" },
|
||||
{ 0xFFFF, NULL },
|
||||
};
|
7425
lib/libesp32/berry_matter/generate/matter_clusters.be
Normal file
7425
lib/libesp32/berry_matter/generate/matter_clusters.be
Normal file
File diff suppressed because it is too large
Load Diff
17
lib/libesp32/berry_matter/library.json
Normal file
17
lib/libesp32/berry_matter/library.json
Normal file
@ -0,0 +1,17 @@
|
||||
{
|
||||
"name": "Berry Matter protocol implementation",
|
||||
"version": "0.1",
|
||||
"description": "Implementation of the Matter protocol specification in Berry for Tasmota, acting as an end-device over Wifi",
|
||||
"license": "MIT",
|
||||
"homepage": "https://github.com/arendst/Tasmota",
|
||||
"frameworks": "arduino",
|
||||
"platforms": "espressif32",
|
||||
"authors":
|
||||
{
|
||||
"name": "Stephan Hadinger",
|
||||
"maintainer": true
|
||||
},
|
||||
"build": {
|
||||
"flags": [ "-I$PROJECT_DIR/include", "-includetasmota_options.h" ]
|
||||
}
|
||||
}
|
2
lib/libesp32/berry_matter/path.be
Normal file
2
lib/libesp32/berry_matter/path.be
Normal file
@ -0,0 +1,2 @@
|
||||
# empty module
|
||||
# allows stand-alone `import path`
|
86
lib/libesp32/berry_matter/solidify_all.be
Executable file
86
lib/libesp32/berry_matter/solidify_all.be
Executable file
@ -0,0 +1,86 @@
|
||||
#! ../berry/berry -s -g
|
||||
#
|
||||
# Berry solidify files
|
||||
#
|
||||
# `../berry/berry -s -g`
|
||||
|
||||
import os
|
||||
import global
|
||||
import solidify
|
||||
import string
|
||||
import re
|
||||
|
||||
import sys
|
||||
sys.path().push('src/embedded') # allow to import from src/embedded
|
||||
|
||||
# globals that need to exist to make compilation succeed
|
||||
var globs = "path,ctypes_bytes_dyn,tasmota,ccronexpr,gpio,light,webclient,load,MD5,lv,light_state,udp,"
|
||||
"lv_clock,lv_clock_icon,lv_signal_arcs,lv_signal_bars,lv_wifi_arcs_icon,lv_wifi_arcs,"
|
||||
"lv_wifi_bars_icon,lv_wifi_bars,"
|
||||
"_lvgl,"
|
||||
"int64"
|
||||
|
||||
for g:string.split(globs, ",")
|
||||
global.(g) = nil
|
||||
end
|
||||
|
||||
var prefix_dir = "src/embedded/"
|
||||
var prefix_out = "src/solidify/"
|
||||
|
||||
def clean_directory(dir)
|
||||
var file_list = os.listdir(dir)
|
||||
for f : file_list
|
||||
if f[0] == '.' continue end # ignore files starting with `.`
|
||||
os.remove(dir + f)
|
||||
end
|
||||
end
|
||||
|
||||
var pattern = "#@\\s*solidify:([A-Za-z0-9_.,]+)"
|
||||
|
||||
def parse_file(fname, prefix_out)
|
||||
print("Parsing: ", fname)
|
||||
var f = open(prefix_dir + fname)
|
||||
var src = f.read()
|
||||
f.close()
|
||||
# try to compile
|
||||
var compiled = compile(src)
|
||||
compiled() # run the compile code to instanciate the classes and modules
|
||||
# output solidified
|
||||
var fname_h = string.split(fname, '.be')[0] + '.h' # take whatever is before the first '.be'
|
||||
var fout = open(prefix_out + "solidified_" + fname_h, "w")
|
||||
fout.write(string.format("/* Solidification of %s */\n", fname_h))
|
||||
fout.write("/********************************************************************\\\n")
|
||||
fout.write("* Generated code, don't edit *\n")
|
||||
fout.write("\\********************************************************************/\n")
|
||||
fout.write('#include "be_constobj.h"\n')
|
||||
|
||||
var directives = re.searchall(pattern, src)
|
||||
# print(directives)
|
||||
|
||||
for directive : directives
|
||||
var object_list = string.split(directive[1], ',')
|
||||
var object_name = object_list[0]
|
||||
var weak = (object_list.find('weak') != nil) # do we solidify with weak strings?
|
||||
var o = global
|
||||
var cl_name = nil
|
||||
var obj_name = nil
|
||||
for subname : string.split(object_name, '.')
|
||||
o = o.(subname)
|
||||
cl_name = obj_name
|
||||
obj_name = subname
|
||||
end
|
||||
solidify.dump(o, weak, fout, cl_name)
|
||||
end
|
||||
|
||||
fout.write("/********************************************************************/\n")
|
||||
fout.write("/* End of solidification */\n")
|
||||
fout.close()
|
||||
end
|
||||
|
||||
clean_directory(prefix_out)
|
||||
|
||||
var src_file_list = os.listdir(prefix_dir)
|
||||
for src_file : src_file_list
|
||||
if src_file[0] == '.' continue end
|
||||
parse_file(src_file, prefix_out)
|
||||
end
|
266
lib/libesp32/berry_matter/src/be_matter_counter.cpp
Normal file
266
lib/libesp32/berry_matter/src/be_matter_counter.cpp
Normal file
@ -0,0 +1,266 @@
|
||||
/*
|
||||
be_matter_counter.cpp - implements Matter counters for message replay prevention
|
||||
|
||||
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_Counter - Support for 32 bits counter with history window
|
||||
*
|
||||
* This is used in Matter to detect collision and replay of packets
|
||||
* See section "4.5. Message Counters"
|
||||
*******************************************************************/
|
||||
|
||||
#include <bitset>
|
||||
#include "be_constobj.h"
|
||||
#include "be_mapping.h"
|
||||
#include "be_mem.h"
|
||||
|
||||
#include "esp_random.h"
|
||||
|
||||
#define MESSAGE_COUNTER_WINDOW_SIZE 32
|
||||
|
||||
typedef struct {
|
||||
uint32_t counter; // value of the counter
|
||||
std::bitset<MESSAGE_COUNTER_WINDOW_SIZE> window;
|
||||
} matter_counter_t;
|
||||
|
||||
/*
|
||||
* Initialize a local message counter with random value between [1, 2^28]. This increases the difficulty of traffic analysis
|
||||
* attacks by making it harder to determine how long a particular session has been open. The initial counter is always 1 or
|
||||
* higher to guarantee first message is always greater than initial peer counter set to 0.
|
||||
*/
|
||||
|
||||
static void mc_randomize(matter_counter_t *c) {
|
||||
// pick a random one in range 0..2^28
|
||||
esp_fill_random(&c->counter, sizeof(c->counter));
|
||||
c->counter = c->counter & 0x0FFFFFFF; // keep only 28 bits
|
||||
if (c->counter == 0) { c->counter = 1; } // unfortunate event that the random generates `0`
|
||||
c->window.reset();
|
||||
}
|
||||
|
||||
// `Matter_Counter([counter:int]) -> instance(Matter_Counter)`
|
||||
//
|
||||
// Creates a new monotonic counter for sending or receiving
|
||||
// If value is `0` or absent, a random counter is generated in the range 1..2^28
|
||||
static void* mc_init(bvm *vm, int32_t val) {
|
||||
matter_counter_t *c = (matter_counter_t*)be_malloc(vm, sizeof(matter_counter_t));
|
||||
c->counter = val;
|
||||
c->window.reset(); // reset the window
|
||||
return c;
|
||||
}
|
||||
BE_FUNC_CTYPE_DECLARE(mc_init, "+_p", "@[i]")
|
||||
|
||||
static void mc_deinit(bvm *vm, matter_counter_t *c) {
|
||||
be_free(vm, c, sizeof(matter_counter_t));
|
||||
}
|
||||
BE_FUNC_CTYPE_DECLARE(mc_deinit, "", "@.")
|
||||
|
||||
static void mc_reset(matter_counter_t *c, int32_t val) {
|
||||
c->counter = val;
|
||||
c->window.reset();
|
||||
}
|
||||
BE_FUNC_CTYPE_DECLARE(mc_reset, "", ".[i]")
|
||||
|
||||
|
||||
int32_t mc_val(matter_counter_t *c) {
|
||||
return c->counter;
|
||||
}
|
||||
BE_FUNC_CTYPE_DECLARE(mc_val, "i", ".")
|
||||
|
||||
int32_t mc_next(matter_counter_t *c) {
|
||||
if (c->counter == 0) { mc_randomize(c); }
|
||||
c->counter++;
|
||||
c->window <<= 1;
|
||||
if (c->counter == 0) {
|
||||
c->counter++;
|
||||
c->window <<= 1;
|
||||
}
|
||||
return c->counter;
|
||||
}
|
||||
BE_FUNC_CTYPE_DECLARE(mc_next, "i", ".")
|
||||
|
||||
// validate if the value is acceptable
|
||||
//
|
||||
// strict_mode is used for encrypted messages: roll-over is not permitted
|
||||
// otherwise roll-over is permitted and counter in the past
|
||||
// (outside of window) is allowed
|
||||
//
|
||||
// return `true` if ok, `false` if rejected
|
||||
int32_t mc_validate(matter_counter_t *c, uint32_t new_val, bbool strict_mode) {
|
||||
if (new_val == c->counter) { return bfalse; } // simple case of a collision of the last message
|
||||
|
||||
if (c->counter == 0) { // first message received, accept any value
|
||||
c->counter = new_val;
|
||||
c->window.reset();
|
||||
return btrue;
|
||||
}
|
||||
|
||||
if (new_val > c->counter) { // counter is in the future, same handling for both modes
|
||||
if (new_val - c->counter > MESSAGE_COUNTER_WINDOW_SIZE) {
|
||||
c->window.reset(); // no index is in the window anymore, clear all
|
||||
} else {
|
||||
c->window <<= new_val - c->counter;
|
||||
c->window[new_val - c->counter - 1] = true; // mark previous val
|
||||
// adjust window
|
||||
}
|
||||
c->counter = new_val;
|
||||
return btrue;
|
||||
} else { // here: new_val < c->counter
|
||||
// are we in the window?
|
||||
uint32_t gap = c->counter - new_val;
|
||||
if (gap <= 32) {
|
||||
if (c->window[gap-1]) {
|
||||
return false; // reject because already seen
|
||||
} else {
|
||||
c->window[gap-1] = btrue;
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
// in the past and out of the window (we ignore roll-over to simplify)
|
||||
if (strict_mode) {
|
||||
return bfalse;
|
||||
} else {
|
||||
c->counter = new_val;
|
||||
c->window.reset();
|
||||
return btrue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
BE_FUNC_CTYPE_DECLARE(mc_validate, "b", ".ib")
|
||||
|
||||
|
||||
static int mc_tostring(bvm *vm) {
|
||||
be_getmember(vm, 1, "_p");
|
||||
matter_counter_t *c = (matter_counter_t*) be_tocomptr(vm, -1);
|
||||
if (c->counter != 0) {
|
||||
be_pushstring(vm, "[");
|
||||
|
||||
for (uint32_t i = MESSAGE_COUNTER_WINDOW_SIZE; i > 0; i--) {
|
||||
be_pushint(vm, c->window[i-1]);
|
||||
be_toescape(vm, -1, 'x'); /* escape string */
|
||||
be_strconcat(vm, -2);
|
||||
be_pop(vm, 1);
|
||||
}
|
||||
|
||||
be_pushstring(vm, "]");
|
||||
be_strconcat(vm, -2);
|
||||
be_pop(vm, 1);
|
||||
|
||||
be_pushint(vm, c->counter);
|
||||
be_toescape(vm, -1, 'x'); /* escape string */
|
||||
be_strconcat(vm, -2);
|
||||
be_pop(vm, 1);
|
||||
} else {
|
||||
be_pushstring(vm, "[]-");
|
||||
}
|
||||
|
||||
be_return(vm);
|
||||
}
|
||||
|
||||
#include "be_fixed_be_class_Matter_Counter.h"
|
||||
|
||||
/* @const_object_info_begin
|
||||
class be_class_Matter_Counter (scope: global, name: Matter_Counter) {
|
||||
_p, var
|
||||
init, ctype_func(mc_init)
|
||||
deinit, ctype_func(mc_deinit)
|
||||
reset, ctype_func(mc_reset)
|
||||
tostring, func(mc_tostring)
|
||||
|
||||
val, ctype_func(mc_val)
|
||||
next, ctype_func(mc_next)
|
||||
validate, ctype_func(mc_validate)
|
||||
}
|
||||
@const_object_info_end */
|
||||
|
||||
|
||||
/*
|
||||
|
||||
# Unit tests
|
||||
import matter
|
||||
var c = matter.Counter(100)
|
||||
assert(str(c) == '[00000000000000000000000000000000]100')
|
||||
assert(c.val() == 100)
|
||||
assert(c.next() == 101)
|
||||
assert(c.val() == 101)
|
||||
assert(str(c) == '[00000000000000000000000000000000]101')
|
||||
|
||||
c.reset(101)
|
||||
assert(!c.validate(101, true))
|
||||
assert(str(c) == '[00000000000000000000000000000000]101')
|
||||
|
||||
c.reset(101)
|
||||
assert(c.validate(100, true))
|
||||
assert(str(c) == '[00000000000000000000000000000001]101')
|
||||
assert(!c.validate(100, true))
|
||||
assert(str(c) == '[00000000000000000000000000000001]101')
|
||||
|
||||
c.reset(101)
|
||||
assert(c.validate(100, false))
|
||||
assert(str(c) == '[00000000000000000000000000000001]101')
|
||||
assert(!c.validate(100, false))
|
||||
assert(str(c) == '[00000000000000000000000000000001]101')
|
||||
|
||||
|
||||
c.reset(128)
|
||||
assert(c.validate(96, true))
|
||||
assert(str(c) == '[10000000000000000000000000000000]128')
|
||||
assert(!c.validate(95, true))
|
||||
assert(str(c) == '[10000000000000000000000000000000]128')
|
||||
|
||||
c.reset(128)
|
||||
assert(c.validate(96, false))
|
||||
assert(str(c) == '[10000000000000000000000000000000]128')
|
||||
assert(c.validate(95, false))
|
||||
assert(str(c) == '[00000000000000000000000000000000]95')
|
||||
|
||||
|
||||
c.reset(100)
|
||||
# set the context as in the documentation
|
||||
assert(c.validate(99, true))
|
||||
assert(c.validate(96, true))
|
||||
assert(c.validate(70, true))
|
||||
assert(str(c) == '[00100000000000000000000000001001]100')
|
||||
|
||||
assert(c.validate(97, true))
|
||||
assert(str(c) == '[00100000000000000000000000001101]100')
|
||||
|
||||
assert(!c.validate(100, true))
|
||||
assert(!c.validate(99, true))
|
||||
assert(!c.validate(97, true))
|
||||
assert(!c.validate(96, true))
|
||||
assert(!c.validate(70, true))
|
||||
assert(str(c) == '[00100000000000000000000000001101]100') # unchanged
|
||||
|
||||
assert(c.validate(101, true))
|
||||
assert(str(c) == '[01000000000000000000000000011011]101')
|
||||
|
||||
assert(c.validate(103, true))
|
||||
assert(str(c) == '[00000000000000000000000001101110]103')
|
||||
|
||||
assert(!c.validate(70, true))
|
||||
|
||||
assert(c.validate(200, true))
|
||||
assert(str(c) == '[00000000000000000000000000000000]200')
|
||||
|
||||
### counters for outgoing messages
|
||||
|
||||
c.reset()
|
||||
assert(c.val() == 0)
|
||||
|
||||
*/
|
270
lib/libesp32/berry_matter/src/be_matter_module.c
Normal file
270
lib/libesp32/berry_matter/src/be_matter_module.c
Normal file
@ -0,0 +1,270 @@
|
||||
/*
|
||||
be_matter_module.c - implements the high level `matter` Berry 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 "be_matter_qrcode_min_js.h"
|
||||
|
||||
// Matter logo
|
||||
static const uint8_t MATTER_LOGO[] =
|
||||
"<svg style='vertical-align:middle;' width='24' height='24' xmlns='http://www.w3.org/2000/svg' viewBox='100 100 240 240'>"
|
||||
"<defs><style>.cls-1{fill:none}.cls-2{fill:#FFFFFF;}</style></defs><rect class='cls-1' "
|
||||
"width='420' height='420'/><path class='cls-2' d='"
|
||||
"M167,156.88a71,71,0,0,0,32.1,14.73v-62.8l12.79-7.38,12.78,7.38v62.8a71.09,71.09,0,0,0,32.11-14.73"
|
||||
"L280,170.31a96.92,96.92,0,0,1-136.33,0Zm28.22,160.37A96.92,96.92,0,0,0,127,199.19v26.87a71.06,"
|
||||
"71.06,0,0,1,28.82,20.43l-54.39,31.4v14.77L114.22,300l54.38-31.4a71,71,0,0,1,3.29,35.17Zm101.5-"
|
||||
"118.06a96.93,96.93,0,0,0-68.16,118.06l23.27-13.44a71.1,71.1,0,0,1,3.29-35.17L309.46,300l12.78-"
|
||||
"7.38V277.89l-54.39-31.4a71.13,71.13,0,0,1,28.82-20.43Z'/></svg>";
|
||||
|
||||
extern const bclass be_class_Matter_Counter;
|
||||
extern const bclass be_class_Matter_Verhoeff;
|
||||
|
||||
#include "solidify/solidified_Matter_Module.h"
|
||||
|
||||
#include "../generate/be_matter_clusters.h"
|
||||
#include "../generate/be_matter_opcodes.h"
|
||||
|
||||
const char* matter_get_cluster_name(uint16_t cluster) {
|
||||
for (const matter_cluster_t * cl = matterAllClusters; cl->id != 0xFFFF; cl++) {
|
||||
if (cl->id == cluster) {
|
||||
return cl->name;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
BE_FUNC_CTYPE_DECLARE(matter_get_cluster_name, "s", "i")
|
||||
|
||||
const char* matter_get_opcode_name(uint16_t opcode) {
|
||||
for (const matter_opcode_t * op = matter_OpCodes; op->id != 0xFFFF; op++) {
|
||||
if (op->id == opcode) {
|
||||
return op->name;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
BE_FUNC_CTYPE_DECLARE(matter_get_opcode_name, "s", "i")
|
||||
|
||||
const char* matter_get_attribute_name(uint16_t cluster, uint16_t attribute) {
|
||||
for (const matter_cluster_t * cl = matterAllClusters; cl->id != 0xFFFF; cl++) {
|
||||
if (cl->id == cluster) {
|
||||
for (const matter_attribute_t * at = cl->attributes; at->id != 0xFFFF; at++) {
|
||||
if (at->id == attribute) {
|
||||
return at->name;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
BE_FUNC_CTYPE_DECLARE(matter_get_attribute_name, "s", "ii")
|
||||
|
||||
const char* matter_get_command_name(uint16_t cluster, uint16_t command) {
|
||||
for (const matter_cluster_t * cl = matterAllClusters; cl->id != 0xFFFF; cl++) {
|
||||
if (cl->id == cluster) {
|
||||
for (const matter_command_t * cmd = cl->commands; cmd->id != 0xFFFF; cmd++) {
|
||||
if (cmd->id == command) {
|
||||
return cmd->name;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
BE_FUNC_CTYPE_DECLARE(matter_get_command_name, "s", "ii")
|
||||
|
||||
#include "solidify/solidified_Matter_inspect.h"
|
||||
|
||||
extern const bclass be_class_Matter_TLV; // need to declare it upfront because of circular reference
|
||||
#include "solidify/solidified_Matter_TLV.h"
|
||||
#include "solidify/solidified_Matter_IM_Data.h"
|
||||
#include "solidify/solidified_Matter_UDPServer.h"
|
||||
#include "solidify/solidified_Matter_Session.h"
|
||||
#include "solidify/solidified_Matter_Commissioning_Data.h"
|
||||
#include "solidify/solidified_Matter_Commissioning.h"
|
||||
#include "solidify/solidified_Matter_Message.h"
|
||||
#include "solidify/solidified_Matter_MessageHandler.h"
|
||||
#include "solidify/solidified_Matter_IM.h"
|
||||
#include "solidify/solidified_Matter_Plugin.h"
|
||||
#include "solidify/solidified_Matter_Base38.h"
|
||||
#include "solidify/solidified_Matter_UI.h"
|
||||
#include "solidify/solidified_Matter_Device.h"
|
||||
|
||||
#include "../generate/be_matter_certs.h"
|
||||
|
||||
#include "solidify/solidified_Matter_Plugin_core.h"
|
||||
#include "solidify/solidified_Matter_Plugin_Relay.h"
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Get a bytes() object of the certificate DAC/PAI_Cert
|
||||
\*********************************************************************************************/
|
||||
static int matter_return_static_bytes(bvm *vm, const uint8* addr, size_t len) {
|
||||
be_getbuiltin(vm, "bytes");
|
||||
be_pushcomptr(vm, addr);
|
||||
be_pushint(vm, - len);
|
||||
be_call(vm, 2);
|
||||
be_pop(vm, 2);
|
||||
be_return(vm);
|
||||
}
|
||||
static int matter_PAI_Cert_FFF1(bvm *vm) { return matter_return_static_bytes(vm, kDevelopmentPAI_Cert_FFF1, sizeof(kDevelopmentPAI_Cert_FFF1)); }
|
||||
static int matter_PAI_Pub_FFF1(bvm *vm) { return matter_return_static_bytes(vm, kDevelopmentPAI_PublicKey_FFF1, sizeof(kDevelopmentPAI_PublicKey_FFF1)); }
|
||||
static int matter_PAI_Priv_FFF1(bvm *vm) { return matter_return_static_bytes(vm, kDevelopmentPAI_PrivateKey_FFF1, sizeof(kDevelopmentPAI_PrivateKey_FFF1)); }
|
||||
static int matter_DAC_Cert_FFF1_8000(bvm *vm) { return matter_return_static_bytes(vm, kDevelopmentDAC_Cert_FFF1_8000, sizeof(kDevelopmentDAC_Cert_FFF1_8000)); }
|
||||
static int matter_DAC_Pub_FFF1_8000(bvm *vm) { return matter_return_static_bytes(vm, kDevelopmentDAC_PublicKey_FFF1_8000, sizeof(kDevelopmentDAC_PublicKey_FFF1_8000)); }
|
||||
static int matter_DAC_Priv_FFF1_8000(bvm *vm) { return matter_return_static_bytes(vm, kDevelopmentDAC_PrivateKey_FFF1_8000, sizeof(kDevelopmentDAC_PrivateKey_FFF1_8000)); }
|
||||
static int matter_CD_FFF1_8000(bvm *vm) { return matter_return_static_bytes(vm, kCdForAllExamples, sizeof(kCdForAllExamples)); }
|
||||
|
||||
|
||||
#include "be_fixed_matter.h"
|
||||
|
||||
/* @const_object_info_begin
|
||||
|
||||
module matter (scope: global) {
|
||||
_LOGO, comptr(MATTER_LOGO)
|
||||
_QRCODE_MINJS, comptr(QRCODE_MINJS)
|
||||
MATTER_OPTION, int(151) // SetOption151 enables Matter
|
||||
|
||||
Verhoeff, class(be_class_Matter_Verhoeff)
|
||||
Counter, class(be_class_Matter_Counter)
|
||||
setmember, closure(matter_setmember_closure)
|
||||
member, closure(matter_member_closure)
|
||||
|
||||
get_cluster_name, ctype_func(matter_get_cluster_name)
|
||||
get_attribute_name, ctype_func(matter_get_attribute_name)
|
||||
get_command_name, ctype_func(matter_get_command_name)
|
||||
get_opcode_name, ctype_func(matter_get_opcode_name)
|
||||
TLV, class(be_class_Matter_TLV)
|
||||
sort, closure(matter_sort_closure)
|
||||
inspect, closure(matter_inspect_closure)
|
||||
|
||||
// Status codes
|
||||
SUCCESS, int(0x00)
|
||||
FAILURE, int(0x01)
|
||||
INVALID_SUBSCRIPTION, int(0x7D)
|
||||
UNSUPPORTED_ACCESS, int(0x7E)
|
||||
UNSUPPORTED_ENDPOINT, int(0x7F)
|
||||
INVALID_ACTION, int(0x80)
|
||||
UNSUPPORTED_COMMAND, int(0x81)
|
||||
INVALID_COMMAND, int(0x85)
|
||||
UNSUPPORTED_ATTRIBUTE, int(0x86)
|
||||
CONSTRAINT_ERROR, int(0x87)
|
||||
UNSUPPORTED_WRITE, int(0x88)
|
||||
RESOURCE_EXHAUSTED, int(0x89)
|
||||
NOT_FOUND, int(0x8B)
|
||||
UNREPORTABLE_ATTRIBUTE, int(0x8C)
|
||||
INVALID_DATA_TYPE, int(0x8D)
|
||||
UNSUPPORTED_READ, int(0x8F)
|
||||
DATA_VERSION_MISMATCH, int(0x92)
|
||||
TIMEOUT, int(0x94)
|
||||
UNSUPPORTED_NODE, int(0x9B)
|
||||
BUSY, int(0x9C)
|
||||
UNSUPPORTED_CLUSTER, int(0xC3)
|
||||
NO_UPSTREAM_SUBSCRIPTION, int(0xC5)
|
||||
NEEDS_TIMED_INTERACTION, int(0xC6)
|
||||
UNSUPPORTED_EVENT, int(0xC7)
|
||||
PATHS_EXHAUSTED, int(0xC8)
|
||||
TIMED_REQUEST_MISMATCH, int(0xC9)
|
||||
FAILSAFE_REQUIRED, int(0xCA)
|
||||
|
||||
// Matter_Data_IM classes
|
||||
AttributePathIB, class(be_class_Matter_AttributePathIB)
|
||||
ClusterPathIB, class(be_class_Matter_ClusterPathIB)
|
||||
DataVersionFilterIB, class(be_class_Matter_DataVersionFilterIB)
|
||||
AttributeDataIB, class(be_class_Matter_AttributeDataIB)
|
||||
AttributeReportIB, class(be_class_Matter_AttributeReportIB)
|
||||
EventFilterIB, class(be_class_Matter_EventFilterIB)
|
||||
EventPathIB, class(be_class_Matter_EventPathIB)
|
||||
EventDataIB, class(be_class_Matter_EventDataIB)
|
||||
EventReportIB, class(be_class_Matter_EventReportIB)
|
||||
CommandPathIB, class(be_class_Matter_CommandPathIB)
|
||||
CommandDataIB, class(be_class_Matter_CommandDataIB)
|
||||
InvokeResponseIB, class(be_class_Matter_InvokeResponseIB)
|
||||
CommandStatusIB, class(be_class_Matter_CommandStatusIB)
|
||||
EventStatusIB, class(be_class_Matter_EventStatusIB)
|
||||
AttributeStatusIB, class(be_class_Matter_AttributeStatusIB)
|
||||
StatusIB, class(be_class_Matter_StatusIB)
|
||||
StatusResponseMessage, class(be_class_Matter_StatusResponseMessage)
|
||||
ReadRequestMessage, class(be_class_Matter_ReadRequestMessage)
|
||||
ReportDataMessage, class(be_class_Matter_ReportDataMessage)
|
||||
SubscribeRequestMessage, class(be_class_Matter_SubscribeRequestMessage)
|
||||
SubscribeResponseMessage, class(be_class_Matter_SubscribeResponseMessage)
|
||||
WriteRequestMessage, class(be_class_Matter_WriteRequestMessage)
|
||||
WriteResponseMessage, class(be_class_Matter_WriteResponseMessage)
|
||||
TimedRequestMessage, class(be_class_Matter_TimedRequestMessage)
|
||||
InvokeRequestMessage, class(be_class_Matter_InvokeRequestMessage)
|
||||
InvokeResponseMessage, class(be_class_Matter_InvokeResponseMessage)
|
||||
|
||||
// Matter Commisioning messages
|
||||
PBKDFParamRequest, class(be_class_Matter_PBKDFParamRequest)
|
||||
PBKDFParamResponse, class(be_class_Matter_PBKDFParamResponse)
|
||||
Pake1, class(be_class_Matter_Pake1)
|
||||
Pake2, class(be_class_Matter_Pake2)
|
||||
Pake3, class(be_class_Matter_Pake3)
|
||||
Sigma1, class(be_class_Matter_Sigma1)
|
||||
Sigma2, class(be_class_Matter_Sigma2)
|
||||
Sigma2Resume, class(be_class_Matter_Sigma2Resume)
|
||||
Sigma3, class(be_class_Matter_Sigma3)
|
||||
|
||||
Commisioning_Context, class(be_class_Matter_Commisioning_Context)
|
||||
|
||||
// UDP Server
|
||||
UDPPacket_sent, class(be_class_Matter_UDPPacket_sent)
|
||||
UDPServer, class(be_class_Matter_UDPServer)
|
||||
|
||||
// Sessions
|
||||
Session, class(be_class_Matter_Session)
|
||||
Session_Store, class(be_class_Matter_Session_Store)
|
||||
|
||||
// Message Handler
|
||||
Frame, class(be_class_Matter_Frame)
|
||||
MessageHandler, class(be_class_Matter_MessageHandler)
|
||||
|
||||
// Interation Model
|
||||
Response_container, class(be_class_Matter_Response_container)
|
||||
IM, class(be_class_Matter_IM)
|
||||
Plugin_core, class(be_class_Matter_Plugin_core)
|
||||
UI, class(be_class_Matter_UI)
|
||||
|
||||
// Base38 for QR Code
|
||||
Base38, class(be_class_Matter_Base38)
|
||||
|
||||
// Matter Device core class
|
||||
Device, class(be_class_Matter_Device)
|
||||
|
||||
// credentials from example
|
||||
PAI_Cert_FFF1, func(matter_PAI_Cert_FFF1)
|
||||
PAI_Pub_FFF1, func(matter_PAI_Pub_FFF1)
|
||||
PAI_Priv_FFF1, func(matter_PAI_Priv_FFF1)
|
||||
DAC_Cert_FFF1_8000, func(matter_DAC_Cert_FFF1_8000)
|
||||
DAC_Pub_FFF1_8000, func(matter_DAC_Pub_FFF1_8000)
|
||||
DAC_Priv_FFF1_8000, func(matter_DAC_Priv_FFF1_8000)
|
||||
CD_FFF1_8000, func(matter_CD_FFF1_8000) // Certification Declaration
|
||||
|
||||
// Plugins
|
||||
Plugin_core, class(be_class_Matter_Plugin_core) // Generic behavior common to all devices
|
||||
Plugin_Relay, class(be_class_Matter_Plugin_Relay) // Relay behavior (OnOff)
|
||||
}
|
||||
|
||||
@const_object_info_end */
|
||||
|
45
lib/libesp32/berry_matter/src/be_matter_qrcode_min_js.h
Normal file
45
lib/libesp32/berry_matter/src/be_matter_qrcode_min_js.h
Normal file
File diff suppressed because one or more lines are too long
105
lib/libesp32/berry_matter/src/be_matter_verhoeff.cpp
Normal file
105
lib/libesp32/berry_matter/src/be_matter_verhoeff.cpp
Normal file
@ -0,0 +1,105 @@
|
||||
/*
|
||||
be_matter_verhoeff.cpp - implements the Verhoeff algorithm to compute a checksum digit for QR Code
|
||||
|
||||
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/>.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include "be_constobj.h"
|
||||
#include "be_mapping.h"
|
||||
|
||||
// code inspired from https://www.programmingalgorithms.com/algorithm/verhoeff-algorithm/c/
|
||||
|
||||
static const int8_t _multiplicationTable[10][10] = {
|
||||
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },
|
||||
{ 1, 2, 3, 4, 0, 6, 7, 8, 9, 5 },
|
||||
{ 2, 3, 4, 0, 1, 7, 8, 9, 5, 6 },
|
||||
{ 3, 4, 0, 1, 2, 8, 9, 5, 6, 7 },
|
||||
{ 4, 0, 1, 2, 3, 9, 5, 6, 7, 8 },
|
||||
{ 5, 9, 8, 7, 6, 0, 4, 3, 2, 1 },
|
||||
{ 6, 5, 9, 8, 7, 1, 0, 4, 3, 2 },
|
||||
{ 7, 6, 5, 9, 8, 2, 1, 0, 4, 3 },
|
||||
{ 8, 7, 6, 5, 9, 3, 2, 1, 0, 4 },
|
||||
{ 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }
|
||||
};
|
||||
|
||||
static const int8_t _permutationTable[10][10] = {
|
||||
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },
|
||||
{ 1, 5, 7, 6, 2, 8, 3, 0, 9, 4 },
|
||||
{ 5, 8, 0, 3, 7, 9, 6, 1, 4, 2 },
|
||||
{ 8, 9, 1, 6, 0, 4, 3, 5, 2, 7 },
|
||||
{ 9, 4, 5, 3, 1, 2, 6, 8, 7, 0 },
|
||||
{ 4, 2, 8, 6, 5, 7, 3, 9, 0, 1 },
|
||||
{ 2, 7, 9, 3, 8, 0, 6, 4, 1, 5 },
|
||||
{ 7, 0, 4, 6, 9, 1, 3, 2, 5, 8 }
|
||||
};
|
||||
|
||||
static const int8_t _inverseTable[10] = { 0, 4, 3, 2, 1, 5, 6, 7, 8, 9 };
|
||||
|
||||
static char ret_digit[] = "0"; // used as a placeholder to return a single digit string
|
||||
|
||||
const char* vh_checksum(const char* number) {
|
||||
int32_t c = 0;
|
||||
int32_t len = strlen(number);
|
||||
|
||||
for (int32_t i = 0; i < len; ++i) {
|
||||
int8_t digit = number[len - i - 1] - '0';
|
||||
if (digit < 0) { digit = 0; }
|
||||
if (digit > 9) { digit = 9; }
|
||||
c = _multiplicationTable[c][_permutationTable[((i + 1) % 8)][digit]];
|
||||
}
|
||||
|
||||
ret_digit[0] = _inverseTable[c] + '0';
|
||||
return ret_digit;
|
||||
}
|
||||
BE_FUNC_CTYPE_DECLARE(vh_checksum, "s", "s")
|
||||
|
||||
static bbool vh_validate(char* number) {
|
||||
int32_t c = 0;
|
||||
int32_t len = strlen(number);
|
||||
|
||||
for (int32_t i = 0; i < len; ++i) {
|
||||
int8_t digit = number[len - i - 1] - '0';
|
||||
if (digit < 0) { digit = 0; }
|
||||
if (digit > 9) { digit = 9; }
|
||||
c = _multiplicationTable[c][_permutationTable[(i % 8)][digit]];
|
||||
}
|
||||
return c == 0;
|
||||
}
|
||||
BE_FUNC_CTYPE_DECLARE(vh_validate, "b", "s")
|
||||
|
||||
#include "be_fixed_be_class_Matter_Verhoeff.h"
|
||||
|
||||
/* @const_object_info_begin
|
||||
class be_class_Matter_Verhoeff (scope: global, name: Matter_Verhoeff) {
|
||||
checksum, static_ctype_func(vh_checksum)
|
||||
validate, static_ctype_func(vh_validate)
|
||||
}
|
||||
@const_object_info_end */
|
||||
|
||||
|
||||
/*
|
||||
|
||||
# Unit tests
|
||||
import matter
|
||||
|
||||
assert(matter.Verhoeff.checksum("236") == "3")
|
||||
assert(matter.Verhoeff.validate("236"))
|
||||
assert(matter.Verhoeff.checksum("58564") == "9")
|
||||
assert(matter.Verhoeff.validate("585649"))
|
||||
|
||||
*/
|
8
lib/libesp32/berry_matter/src/berry_tasmota.h
Normal file
8
lib/libesp32/berry_matter/src/berry_tasmota.h
Normal file
@ -0,0 +1,8 @@
|
||||
// force include of module by including this file
|
||||
|
||||
#ifndef __BERRY_MATTER__
|
||||
#define __BERRY_MATTER__
|
||||
|
||||
|
||||
|
||||
#endif // __BERRY_MATTER__
|
71
lib/libesp32/berry_matter/src/embedded/Matter_Base38.be
Normal file
71
lib/libesp32/berry_matter/src/embedded/Matter_Base38.be
Normal file
@ -0,0 +1,71 @@
|
||||
#
|
||||
# Matter_Base38.be - suppport for Base38 encoding which is used in QR Codes
|
||||
#
|
||||
# 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/>.
|
||||
#
|
||||
|
||||
import matter
|
||||
|
||||
#@ solidify:Matter_Base38,weak
|
||||
|
||||
class Matter_Base38
|
||||
|
||||
static def encode(raw)
|
||||
# encodes b38 (mutates `b`)
|
||||
def b38_enc(v, l)
|
||||
import string
|
||||
var ENCODE = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-."
|
||||
var i = 0
|
||||
var ret = ""
|
||||
while i < l
|
||||
ret += ENCODE[v % 38]
|
||||
v = v / 38
|
||||
i += 1
|
||||
end
|
||||
return ret
|
||||
end
|
||||
|
||||
var idx = 0
|
||||
var sz = size(raw)
|
||||
var out = ""
|
||||
|
||||
while idx < sz
|
||||
var val
|
||||
if idx + 2 < sz
|
||||
# encode 3 bytes
|
||||
val = raw[idx] | (raw[idx+1] << 8) | (raw[idx+2] << 16)
|
||||
out += b38_enc(val, 5)
|
||||
idx += 3
|
||||
elif idx + 1 < sz
|
||||
# encode 2 bytes
|
||||
val = raw[idx] | (raw[idx+1] << 8)
|
||||
out += b38_enc(val, 4)
|
||||
idx += 2
|
||||
else
|
||||
# encode 1 byte
|
||||
val = raw[idx]
|
||||
out += b38_enc(val, 2)
|
||||
idx += 1
|
||||
end
|
||||
end
|
||||
return out
|
||||
end
|
||||
end
|
||||
matter.Base38 = Matter_Base38
|
||||
|
||||
#-
|
||||
|
||||
-#
|
632
lib/libesp32/berry_matter/src/embedded/Matter_Commissioning.be
Normal file
632
lib/libesp32/berry_matter/src/embedded/Matter_Commissioning.be
Normal file
@ -0,0 +1,632 @@
|
||||
#
|
||||
# Matter_Commissioning.be - suppport for Matter Commissioning process
|
||||
#
|
||||
# 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/>.
|
||||
#
|
||||
|
||||
import matter
|
||||
|
||||
#@ solidify:Matter_Commisioning_Context,weak
|
||||
|
||||
#################################################################################
|
||||
# Class Matter_Commisioning_Context
|
||||
#################################################################################
|
||||
class Matter_Commisioning_Context
|
||||
# static Matter_Context_Prefix = "Matter PAKE V1 Commissioning" # spec is wrong
|
||||
static var Matter_Context_Prefix = "CHIP PAKE V1 Commissioning" # from CHIP code
|
||||
static var SEKeys_Info = "SessionKeys"
|
||||
static var S2K_Info = "Sigma2"
|
||||
static var S3K_Info = "Sigma3"
|
||||
static var TBEData2_Nonce = "NCASE_Sigma2N"
|
||||
static var TBEData3_Nonce = "NCASE_Sigma3N"
|
||||
|
||||
var responder # reference to the caller, sending packets
|
||||
var device # root device object
|
||||
var spake
|
||||
var future_initiator_session_id
|
||||
var future_local_session_id
|
||||
# used by TT hash
|
||||
var PBKDFParamRequest, PBKDFParamResponse
|
||||
# PAKE
|
||||
var y # 32 bytes random known only by verifier
|
||||
var pA, pB, cA, cB
|
||||
var Ke
|
||||
# CASE
|
||||
var ResponderEph_priv, ResponderEph_pub
|
||||
var initiatorEph_pub
|
||||
# Session data
|
||||
var session_timestamp
|
||||
var I2RKey, R2IKey, AttestationChallenge
|
||||
# is commissioning window open
|
||||
var window_open
|
||||
|
||||
def init(responder)
|
||||
import crypto
|
||||
self.responder = responder
|
||||
self.device = responder.device
|
||||
# generate y once
|
||||
self.y = crypto.random(32)
|
||||
|
||||
self.window_open = true # auto-commissioning for now
|
||||
end
|
||||
|
||||
def process_incoming(msg, remote_ip, remote_port)
|
||||
#
|
||||
if !self.window_open
|
||||
tasmota.log("MTR: commissioning not open", 2)
|
||||
return false
|
||||
end
|
||||
|
||||
tasmota.log("MTR: received message " + matter.inspect(msg), 3)
|
||||
if msg.opcode == 0x20
|
||||
return self.parse_PBKDFParamRequest(msg, remote_ip, remote_port)
|
||||
elif msg.opcode == 0x22
|
||||
return self.parse_Pake1(msg, remote_ip, remote_port)
|
||||
elif msg.opcode == 0x24
|
||||
return self.parse_Pake3(msg, remote_ip, remote_port)
|
||||
elif msg.opcode == 0x30
|
||||
return self.parse_Sigma1(msg, remote_ip, remote_port)
|
||||
elif msg.opcode == 0x32
|
||||
return self.parse_Sigma3(msg, remote_ip, remote_port)
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
def parse_PBKDFParamRequest(msg, addr, port)
|
||||
import crypto
|
||||
# sanity checks
|
||||
if msg.opcode != 0x20 || msg.local_session_id != 0 || msg.protocol_id != 0
|
||||
raise "protocol_error", "invalid PBKDFParamRequest message"
|
||||
end
|
||||
var pbkdfparamreq = matter.PBKDFParamRequest().parse(msg.raw, msg.app_payload_idx)
|
||||
msg.session.set_mode(matter.Session.__PASE)
|
||||
|
||||
self.PBKDFParamRequest = msg.raw[msg.app_payload_idx..]
|
||||
|
||||
# sanity check for PBKDFParamRequest
|
||||
if pbkdfparamreq.passcodeId != 0 raise "protocol_error", "non-zero passcode id" end
|
||||
|
||||
# record the initiator_session_id
|
||||
self.future_initiator_session_id = pbkdfparamreq.initiator_session_id
|
||||
self.future_local_session_id = self.device.sessions.gen_local_session_id()
|
||||
|
||||
# prepare response
|
||||
var pbkdfparamresp = matter.PBKDFParamResponse()
|
||||
|
||||
pbkdfparamresp.initiatorRandom = pbkdfparamreq.initiatorRandom
|
||||
# generate 32 bytes random
|
||||
pbkdfparamresp.responderRandom = crypto.random(32)
|
||||
pbkdfparamresp.responderSessionId = self.future_local_session_id
|
||||
pbkdfparamresp.pbkdf_parameters_salt = self.device.salt
|
||||
pbkdfparamresp.pbkdf_parameters_iterations = self.device.iterations
|
||||
tasmota.log("MTR: pbkdfparamresp: " + str(matter.inspect(pbkdfparamresp)), 3)
|
||||
var pbkdfparamresp_raw = pbkdfparamresp.encode()
|
||||
tasmota.log("MTR: pbkdfparamresp_raw: " + pbkdfparamresp_raw.tohex(), 3)
|
||||
|
||||
self.PBKDFParamResponse = pbkdfparamresp_raw
|
||||
|
||||
var resp = msg.build_response(0x21 #-PBKDR Response-#, true)
|
||||
var raw = resp.encode(pbkdfparamresp_raw)
|
||||
|
||||
self.responder.send_response(raw, addr, port, resp.message_counter)
|
||||
end
|
||||
|
||||
def parse_Pake1(msg, addr, port)
|
||||
import crypto
|
||||
# sanity checks
|
||||
if msg.opcode != 0x22 || msg.local_session_id != 0 || msg.protocol_id != 0
|
||||
raise "protocol_error", "invalid Pake1 message"
|
||||
end
|
||||
var pake1 = matter.Pake1().parse(msg.raw, msg.app_payload_idx)
|
||||
|
||||
self.pA = pake1.pA
|
||||
tasmota.log("MTR: received pA=" + self.pA.tohex(), 3)
|
||||
|
||||
|
||||
tasmota.log("MTR: spake: " + matter.inspect(self.spake), 3)
|
||||
# instanciate SPAKE
|
||||
self.spake = crypto.SPAKE2P_Matter(self.device.w0, self.device.w1, self.device.L)
|
||||
# compute pB
|
||||
self.spake.compute_pB(self.y)
|
||||
self.pB = self.spake.pB
|
||||
tasmota.log("MTR: y=" + self.y.tohex(), 3)
|
||||
tasmota.log("MTR: pb=" + self.pB.tohex(), 3)
|
||||
|
||||
# compute ZV
|
||||
self.spake.compute_ZV_verifier(self.pA)
|
||||
tasmota.log("MTR: Z=" + self.spake.Z.tohex(), 3)
|
||||
tasmota.log("MTR: V=" + self.spake.V.tohex(), 3)
|
||||
|
||||
var context = crypto.SHA256()
|
||||
context.update(bytes().fromstring(self.Matter_Context_Prefix))
|
||||
context.update(self.PBKDFParamRequest)
|
||||
context.update(self.PBKDFParamResponse)
|
||||
var context_hash = context.out()
|
||||
|
||||
tasmota.log("MTR: Context=" + context_hash.tohex(), 3)
|
||||
|
||||
# add pA
|
||||
self.spake.pA = self.pA
|
||||
|
||||
self.spake.set_context(context_hash)
|
||||
self.spake.compute_TT_hash(true) # `true` to indicate it's Matter variant to SPAKE2+
|
||||
|
||||
tasmota.log("MTR: ------------------------------", 3)
|
||||
tasmota.log("MTR: Context = " + self.spake.Context.tohex(), 3)
|
||||
tasmota.log("MTR: A = " + self.spake.A.tohex(), 3)
|
||||
tasmota.log("MTR: B = " + self.spake.B.tohex(), 3)
|
||||
tasmota.log("MTR: M = " + self.spake.M.tohex(), 3)
|
||||
tasmota.log("MTR: N = " + self.spake.N.tohex(), 3)
|
||||
tasmota.log("MTR: pA = " + self.spake.pA.tohex(), 3)
|
||||
tasmota.log("MTR: pB = " + self.spake.pB.tohex(), 3)
|
||||
tasmota.log("MTR: Z = " + self.spake.Z.tohex(), 3)
|
||||
tasmota.log("MTR: V = " + self.spake.V.tohex(), 3)
|
||||
tasmota.log("MTR: w0 = " + self.spake.w0.tohex(), 3)
|
||||
tasmota.log("MTR: ------------------------------", 3)
|
||||
|
||||
tasmota.log("MTR: Kmain =" + self.spake.Kmain.tohex(), 3)
|
||||
|
||||
tasmota.log("MTR: KcA =" + self.spake.KcA.tohex(), 3)
|
||||
tasmota.log("MTR: KcB =" + self.spake.KcB.tohex(), 3)
|
||||
tasmota.log("MTR: K_shared=" + self.spake.K_shared.tohex(), 3)
|
||||
tasmota.log("MTR: Ke =" + self.spake.Ke.tohex(), 3)
|
||||
self.cB = self.spake.cB
|
||||
self.Ke = self.spake.Ke
|
||||
tasmota.log("MTR: cB=" + self.cB.tohex(), 3)
|
||||
|
||||
var pake2 = matter.Pake2()
|
||||
pake2.pB = self.pB
|
||||
pake2.cB = self.cB
|
||||
tasmota.log("MTR: pake2: " + matter.inspect(pake2), 3)
|
||||
var pake2_raw = pake2.encode()
|
||||
tasmota.log("MTR: pake2_raw: " + pake2_raw.tohex(), 3)
|
||||
|
||||
|
||||
# now package the response message
|
||||
var resp = msg.build_response(0x23 #-pake-2-#, true) # no reliable flag
|
||||
var raw = resp.encode(pake2_raw)
|
||||
|
||||
self.responder.send_response(raw, addr, port, resp.message_counter)
|
||||
end
|
||||
|
||||
def parse_Pake3(msg, addr, port)
|
||||
import crypto
|
||||
# sanity checks
|
||||
if msg.opcode != 0x24 || msg.local_session_id != 0 || msg.protocol_id != 0
|
||||
raise "protocol_error", "invalid Pake3 message"
|
||||
end
|
||||
var pake3 = matter.Pake3().parse(msg.raw, msg.app_payload_idx)
|
||||
|
||||
self.cA = pake3.cA
|
||||
tasmota.log("MTR: received cA=" + self.cA.tohex(), 3)
|
||||
|
||||
# check the value against computed
|
||||
if self.cA != self.spake.cA raise "protocol_error", "invalid cA received" end
|
||||
|
||||
# send PakeFinished and compute session key
|
||||
self.session_timestamp = tasmota.rtc()['utc']
|
||||
var session_keys = crypto.HKDF_SHA256().derive(self.Ke, bytes(), bytes().fromstring(self.SEKeys_Info), 48)
|
||||
self.I2RKey = session_keys[0..15]
|
||||
self.R2IKey = session_keys[16..31]
|
||||
self.AttestationChallenge = session_keys[32..47]
|
||||
|
||||
tasmota.log("MTR: ******************************", 3)
|
||||
tasmota.log("MTR: session_keys=" + session_keys.tohex(), 3)
|
||||
tasmota.log("MTR: I2RKey =" + self.I2RKey.tohex(), 3)
|
||||
tasmota.log("MTR: R2IKey =" + self.R2IKey.tohex(), 3)
|
||||
tasmota.log("MTR: AC =" + self.AttestationChallenge.tohex(), 3)
|
||||
tasmota.log("MTR: ******************************", 3)
|
||||
|
||||
# now package the response message
|
||||
var resp = msg.build_response(0x40 #-StatusReport-#, false) # no reliable flag
|
||||
|
||||
var status_raw = bytes()
|
||||
status_raw.add(0x00, 2) # GeneralCode = SUCCESS
|
||||
status_raw.add(0x0000, 4) # ProtocolID = 0 (PROTOCOL_ID_SECURE_CHANNEL)
|
||||
status_raw.add(0x0000, 4) # ProtocolCode = 0 (SESSION_ESTABLISHMENT_SUCCESS)
|
||||
|
||||
var raw = resp.encode(status_raw)
|
||||
|
||||
self.responder.send_response(raw, addr, port, nil)
|
||||
self.responder.add_session(self.future_local_session_id, self.future_initiator_session_id, self.I2RKey, self.R2IKey, self.AttestationChallenge, self.session_timestamp)
|
||||
end
|
||||
|
||||
def find_session_by_destination_id(destinationId, initiatorRandom)
|
||||
import crypto
|
||||
# Validate Sigma1 Destination ID, p.162
|
||||
# traverse all existing sessions
|
||||
tasmota.log("MTR: SEARCHING: destinationId=" + destinationId.tohex(), 3)
|
||||
for session:self.device.sessions.sessions
|
||||
if session.noc == nil || session.fabric == nil || session.deviceid == nil continue end
|
||||
# compute candidateDestinationId, Section 4.13.2.4.1, “Destination Identifier”
|
||||
var destinationMessage = initiatorRandom + session.get_ca_pub() + session.get_fabric() + session.get_deviceid()
|
||||
var key = session.get_ipk_group_key()
|
||||
tasmota.log("MTR: SIGMA1: destinationMessage=" + destinationMessage.tohex(), 3)
|
||||
tasmota.log("MTR: SIGMA1: key_ipk=" + key.tohex(), 3)
|
||||
var h = crypto.HMAC_SHA256(key)
|
||||
h.update(destinationMessage)
|
||||
var candidateDestinationId = h.out()
|
||||
tasmota.log("MTR: SIGMA1: candidateDestinationId=" + candidateDestinationId.tohex(), 3)
|
||||
if candidateDestinationId == destinationId
|
||||
return session
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
def parse_Sigma1(msg, addr, port)
|
||||
import crypto
|
||||
# sanity checks
|
||||
if msg.opcode != 0x30 || msg.local_session_id != 0 || msg.protocol_id != 0
|
||||
raise "protocol_error", "invalid Pake1 message"
|
||||
end
|
||||
var sigma1 = matter.Sigma1().parse(msg.raw, msg.app_payload_idx)
|
||||
|
||||
self.initiatorEph_pub = sigma1.initiatorEphPubKey
|
||||
|
||||
# find session
|
||||
var session = self.find_session_by_destination_id(sigma1.destinationId, sigma1.initiatorRandom)
|
||||
if session == nil raise "valuer_error", "StatusReport(GeneralCode: FAILURE, ProtocolId: SECURE_CHANNEL, ProtocolCode: NO_SHARED_TRUST_ROOTS)" end
|
||||
session.source_node_id = msg.source_node_id
|
||||
session.set_mode(matter.Session.__CASE)
|
||||
|
||||
if msg.session
|
||||
self.device.sessions.remove_session(msg.session) # drop the temporary session that was created
|
||||
end
|
||||
msg.session = session
|
||||
session._future_initiator_session_id = sigma1.initiator_session_id # update initiator_session_id
|
||||
session._future_local_session_id = self.device.sessions.gen_local_session_id()
|
||||
self.future_local_session_id = session._future_local_session_id
|
||||
|
||||
|
||||
# Check that it's a resumption
|
||||
if sigma1.resumptionID != nil && sigma1.initiatorResumeMIC != nil &&
|
||||
session.shared_secret != nil
|
||||
# Resumption p.169
|
||||
var s1rk_salt = sigma1.initiatorRandom + sigma1.resumptionID
|
||||
var s1rk_info = bytes().fromstring("Sigma1_Resume")
|
||||
var s1rk = crypto.HKDF_SHA256().derive(session.shared_secret, s1rk_salt, s1rk_info, 16)
|
||||
|
||||
var Resume1MIC_Nonce = bytes().fromstring("NCASE_SigmaR1")
|
||||
var encrypted = sigma1.initiatorResumeMIC[0..-17]
|
||||
var tag = sigma1.initiatorResumeMIC[-16..]
|
||||
var ec = crypto.AES_CCM(s1rk, Resume1MIC_Nonce, bytes(), size(encrypted), 16)
|
||||
var Resume1MICPayload = ec.decrypt(encrypted)
|
||||
var decrypted_tag = ec.tag()
|
||||
|
||||
tasmota.log("****************************************", 3)
|
||||
tasmota.log("MTR: * s1rk = " + s1rk.tohex(), 3)
|
||||
tasmota.log("MTR: * tag = " + tag.tohex(), 3)
|
||||
tasmota.log("MTR: * Resume1MICPayload = " + Resume1MICPayload.tohex(), 3)
|
||||
tasmota.log("MTR: * decrypted_tag = " + decrypted_tag.tohex(), 3)
|
||||
tasmota.log("****************************************", 3)
|
||||
if tag == decrypted_tag
|
||||
# Generate and Send Sigma2_Resume
|
||||
session.resumption_id = crypto.random(16) # generate a new resumption id
|
||||
|
||||
# compute S2RK
|
||||
var s2rk_info = bytes().fromstring("Sigma2_Resume") + session.resumption_id
|
||||
var s2rk_salt = sigma1.initiatorRandom + sigma1.resumptionID
|
||||
var s2rk = crypto.HKDF_SHA256().derive(session.shared_secret, s2rk_salt, s2rk_info, 16)
|
||||
|
||||
# compute Resume2MIC
|
||||
var aes = crypto.AES_CCM(s2rk, bytes().fromstring("NCASE_SigmaR2"), bytes(), 0, 16)
|
||||
var Resume2MIC = aes.tag()
|
||||
|
||||
var sigma2resume = matter.Sigma2Resume()
|
||||
sigma2resume.resumptionID = session.resumption_id
|
||||
sigma2resume.responderSessionID = session._future_local_session_id
|
||||
sigma2resume.sigma2ResumeMIC = Resume2MIC
|
||||
|
||||
# # compute session key, p.178
|
||||
var session_keys = crypto.HKDF_SHA256().derive(session.shared_secret #- input key -#,
|
||||
sigma1.initiatorRandom + sigma1.resumptionID #- salt -#,
|
||||
bytes().fromstring("SessionResumptionKeys") #- info -#,
|
||||
48)
|
||||
var i2r = session_keys[0..15]
|
||||
var r2i = session_keys[16..31]
|
||||
var ac = session_keys[32..47]
|
||||
var session_timestamp = tasmota.rtc()['utc']
|
||||
|
||||
tasmota.log("MTR: ******************************", 3)
|
||||
tasmota.log("MTR: I2RKey =" + i2r.tohex(), 3)
|
||||
tasmota.log("MTR: R2IKey =" + r2i.tohex(), 3)
|
||||
tasmota.log("MTR: AC =" + ac.tohex(), 3)
|
||||
tasmota.log("MTR: ******************************", 3)
|
||||
|
||||
var sigma2resume_raw = sigma2resume.encode()
|
||||
session._Msg1 = nil
|
||||
tasmota.log("MTR: sigma2resume_raw: " + sigma2resume_raw.tohex(), 3)
|
||||
|
||||
# now package the response message
|
||||
var resp = msg.build_response(0x33 #-sigma-2-resume-#, true)
|
||||
var raw = resp.encode(sigma2resume_raw)
|
||||
|
||||
self.responder.send_response(raw, addr, port, resp.message_counter)
|
||||
|
||||
session.close()
|
||||
session.set_keys(i2r, r2i, ac, session_timestamp)
|
||||
session.set_persist(true) # keep session on flash
|
||||
session.set_no_expiration() # never expire
|
||||
session.save()
|
||||
|
||||
return true
|
||||
else
|
||||
sigma1.resumptionID = nil
|
||||
# fall through normal sigma1 (non-resumption)
|
||||
end
|
||||
end
|
||||
|
||||
if sigma1.resumptionID == nil || sigma1.initiatorResumeMIC == nil
|
||||
# Compute Sigma2, p.162
|
||||
session.resumption_id = crypto.random(16)
|
||||
self.ResponderEph_priv = crypto.random(32)
|
||||
self.ResponderEph_pub = crypto.EC_P256().public_key(self.ResponderEph_priv)
|
||||
var responderRandom = crypto.random(32)
|
||||
|
||||
session.shared_secret = crypto.EC_P256().shared_key(self.ResponderEph_priv, sigma1.initiatorEphPubKey)
|
||||
|
||||
var sigma2_tbsdata = matter.TLV.Matter_TLV_struct()
|
||||
sigma2_tbsdata.add_TLV(1, matter.TLV.B2, session.get_noc())
|
||||
sigma2_tbsdata.add_TLV(2, matter.TLV.B2, session.get_icac())
|
||||
sigma2_tbsdata.add_TLV(3, matter.TLV.B2, self.ResponderEph_pub)
|
||||
sigma2_tbsdata.add_TLV(4, matter.TLV.B2, sigma1.initiatorEphPubKey)
|
||||
|
||||
var TBSData2Signature = crypto.EC_P256().ecdsa_sign_sha256(session.get_pk(), sigma2_tbsdata.encode())
|
||||
|
||||
var sigma2_tbedata = matter.TLV.Matter_TLV_struct()
|
||||
sigma2_tbedata.add_TLV(1, matter.TLV.B2, session.get_noc())
|
||||
sigma2_tbedata.add_TLV(2, matter.TLV.B2, session.get_icac())
|
||||
sigma2_tbedata.add_TLV(3, matter.TLV.B2, TBSData2Signature)
|
||||
sigma2_tbedata.add_TLV(4, matter.TLV.B2, session.resumption_id)
|
||||
|
||||
# compute TranscriptHash = Crypto_Hash(message = Msg1)
|
||||
tasmota.log("****************************************", 3)
|
||||
session._Msg1 = sigma1.Msg1
|
||||
tasmota.log("MTR: * MSG1 = " + session._Msg1.tohex(), 3)
|
||||
var TranscriptHash = crypto.SHA256().update(session._Msg1).out()
|
||||
|
||||
# Compute S2K, p.175
|
||||
var s2k_info = bytes().fromstring(self.S2K_Info)
|
||||
var s2k_salt = session.get_ipk_group_key() + responderRandom + self.ResponderEph_pub + TranscriptHash
|
||||
|
||||
var s2k = crypto.HKDF_SHA256().derive(session.shared_secret, s2k_salt, s2k_info, 16)
|
||||
tasmota.log("MTR: * SharedSecret = " + session.shared_secret.tohex(), 3)
|
||||
tasmota.log("MTR: * s2k_salt = " + s2k_salt.tohex(), 3)
|
||||
tasmota.log("MTR: * s2k = " + s2k.tohex(), 3)
|
||||
|
||||
var sigma2_tbedata_raw = sigma2_tbedata.encode()
|
||||
# // `AES_CCM.init(secret_key:bytes(16 or 32), iv:bytes(7..13), aad:bytes(), data_len:int, tag_len:int) -> instance`
|
||||
|
||||
var aes = crypto.AES_CCM(s2k, bytes().fromstring(self.TBEData2_Nonce), bytes(), size(sigma2_tbedata_raw), 16)
|
||||
var TBEData2Encrypted = aes.encrypt(sigma2_tbedata_raw) + aes.tag()
|
||||
tasmota.log("MTR: * TBEData2Enc = " + TBEData2Encrypted.tohex(), 3)
|
||||
tasmota.log("****************************************", 3)
|
||||
|
||||
var sigma2 = matter.Sigma2()
|
||||
sigma2.responderRandom = responderRandom
|
||||
sigma2.responderSessionId = self.future_local_session_id
|
||||
sigma2.responderEphPubKey = self.ResponderEph_pub
|
||||
sigma2.encrypted2 = TBEData2Encrypted
|
||||
tasmota.log("MTR: sigma2: " + matter.inspect(sigma2), 3)
|
||||
var sigma2_raw = sigma2.encode()
|
||||
session._Msg2 = sigma2_raw
|
||||
tasmota.log("MTR: sigma2_raw: " + sigma2_raw.tohex(), 3)
|
||||
|
||||
# now package the response message
|
||||
var resp = msg.build_response(0x31 #-sigma-2-#, true) # no reliable flag
|
||||
var raw = resp.encode(sigma2_raw)
|
||||
|
||||
self.responder.send_response(raw, addr, port, resp.message_counter)
|
||||
return true
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
def parse_Sigma3(msg, addr, port)
|
||||
import crypto
|
||||
# sanity checks
|
||||
if msg.opcode != 0x32 || msg.local_session_id != 0 || msg.protocol_id != 0
|
||||
raise "protocol_error", "invalid Pake1 message"
|
||||
end
|
||||
var session = msg.session
|
||||
var sigma3 = matter.Sigma3().parse(msg.raw, msg.app_payload_idx)
|
||||
|
||||
tasmota.log("****************************************", 3)
|
||||
# compute TranscriptHash = Crypto_Hash(message = Msg1 || Msg2)
|
||||
var TranscriptHash = crypto.SHA256().update(session._Msg1).update(session._Msg2).out()
|
||||
tasmota.log("MTR: * session = " + str(session), 3)
|
||||
tasmota.log("MTR: session.ipk_epoch_key " + str(session.ipk_epoch_key), 3)
|
||||
tasmota.log("MTR: session.fabric_compressed " + str(session.fabric_compressed), 3)
|
||||
tasmota.log("MTR: * ipk_group_key = " + session.get_ipk_group_key().tohex(), 3)
|
||||
tasmota.log("MTR: * TranscriptHash= " + TranscriptHash.tohex(), 3)
|
||||
|
||||
var s3k_info = bytes().fromstring(self.S3K_Info)
|
||||
var s3k = crypto.HKDF_SHA256().derive(session.shared_secret, session.get_ipk_group_key() + TranscriptHash, s3k_info, 16)
|
||||
|
||||
tasmota.log("****************************************", 3)
|
||||
# self.ipk_epoch_key == nil || self.fabric_compressed")
|
||||
tasmota.log("MTR: * s3k_salt = " + (session.get_ipk_group_key() + TranscriptHash).tohex(), 3)
|
||||
tasmota.log("MTR: * s3k = " + s3k.tohex(), 3)
|
||||
tasmota.log("****************************************", 3)
|
||||
|
||||
# decrypt
|
||||
var encrypted = sigma3.TBEData3Encrypted[0..-17]
|
||||
var tag = sigma3.TBEData3Encrypted[-16..]
|
||||
var ec = crypto.AES_CCM(s3k, bytes().fromstring(self.TBEData3_Nonce), bytes(), size(encrypted), 16)
|
||||
var TBEData3 = ec.decrypt(encrypted)
|
||||
var TBETag3 = ec.tag()
|
||||
tasmota.log("MTR: * TBEData3 = " + TBEData3.tohex(), 3)
|
||||
tasmota.log("MTR: * TBETag3 = " + TBETag3.tohex(), 3)
|
||||
tasmota.log("MTR: * tag_sent = " + tag.tohex(), 3)
|
||||
tasmota.log("****************************************", 3)
|
||||
|
||||
if TBETag3 != tag raise "value_error", "tag do not match" end
|
||||
|
||||
var TBEData3TLV = matter.TLV.parse(TBEData3)
|
||||
var initiatorNOC = TBEData3TLV.findsubval(1)
|
||||
var initiatorICAC = TBEData3TLV.findsubval(2)
|
||||
var ec_signature = TBEData3TLV.findsubval(3)
|
||||
# Success = Crypto_VerifyChain(certificates = [TBEData3.initiatorNOC, TBEData3.initiatorICAC, TrustedRCAC]), when TBEData3.initiatorICAC is present
|
||||
# TODO
|
||||
var initiatorNOCTLV = matter.TLV.parse(initiatorNOC)
|
||||
tasmota.log("MTR: initiatorNOCTLV = " + str(initiatorNOCTLV), 3)
|
||||
var initiatorNOCPubKey = initiatorNOCTLV.findsubval(9)
|
||||
var initiatorNOCListDN = initiatorNOCTLV.findsub(6)
|
||||
var initiatorFabricId = initiatorNOCListDN.findsubval(17)
|
||||
if type(initiatorFabricId) == 'int' initiatorFabricId = int64(initiatorFabricId) end
|
||||
session.peer_node_id = initiatorFabricId.tobytes()
|
||||
tasmota.log("MTR: initiatorFabricId="+str(session.peer_node_id), 3)
|
||||
|
||||
var sigma3_tbs = matter.TLV.Matter_TLV_struct()
|
||||
sigma3_tbs.add_TLV(1, matter.TLV.B1, initiatorNOC)
|
||||
sigma3_tbs.add_TLV(2, matter.TLV.B1, initiatorICAC)
|
||||
sigma3_tbs.add_TLV(3, matter.TLV.B1, self.initiatorEph_pub)
|
||||
sigma3_tbs.add_TLV(4, matter.TLV.B1, self.ResponderEph_pub)
|
||||
var sigma3_tbs_raw = sigma3_tbs.encode()
|
||||
|
||||
tasmota.log("MTR: * initiatorNOCPubKey = " + initiatorNOCPubKey.tohex(), 3)
|
||||
tasmota.log("MTR: * ec_signature = " + ec_signature.tohex(), 3)
|
||||
tasmota.log("****************************************", 3)
|
||||
|
||||
# `crypto.EC_P256().ecdsa_verify_sha256(public_key:bytes(65), message:bytes(), hash:bytes()) -> bool`
|
||||
var sigma3_tbs_valid = crypto.EC_P256().ecdsa_verify_sha256(initiatorNOCPubKey, sigma3_tbs_raw, ec_signature)
|
||||
|
||||
if !sigma3_tbs_valid raise "value_error", "sigma3_tbs does not have a valid signature" end
|
||||
|
||||
# All good, compute new keys
|
||||
tasmota.log("MTR: Sigma3 verified, computing new keys", 3)
|
||||
|
||||
TranscriptHash = crypto.SHA256().update(session._Msg1).update(session._Msg2).update(sigma3.Msg3).out()
|
||||
# we can now free _Msg1 and _Msg2
|
||||
session._Msg1 = nil
|
||||
session._Msg2 = nil
|
||||
|
||||
tasmota.log("MTR: ******************************", 3)
|
||||
tasmota.log("MTR: shared_secret =" + session.shared_secret.tohex(), 3)
|
||||
tasmota.log("MTR: ipk + hash =" + (session.get_ipk_group_key() + TranscriptHash).tohex(), 3)
|
||||
# compute session key
|
||||
var session_keys = crypto.HKDF_SHA256().derive(session.shared_secret #- input key -#,
|
||||
session.get_ipk_group_key() + TranscriptHash #- salt -#,
|
||||
bytes().fromstring(self.SEKeys_Info) #- info -#,
|
||||
48)
|
||||
var i2r = session_keys[0..15]
|
||||
var r2i = session_keys[16..31]
|
||||
var ac = session_keys[32..47]
|
||||
var session_timestamp = tasmota.rtc()['utc']
|
||||
|
||||
tasmota.log("MTR: ******************************", 3)
|
||||
tasmota.log("MTR: I2RKey =" + i2r.tohex(), 3)
|
||||
tasmota.log("MTR: R2IKey =" + r2i.tohex(), 3)
|
||||
tasmota.log("MTR: AC =" + ac.tohex(), 3)
|
||||
tasmota.log("MTR: ******************************", 3)
|
||||
|
||||
# Send success status report
|
||||
var resp = msg.build_response(0x40 #-StatusReport-#, true) # reliable flag
|
||||
|
||||
var status_raw = bytes()
|
||||
status_raw.add(0x00, 2) # GeneralCode = SUCCESS
|
||||
status_raw.add(0x0000, 4) # ProtocolID = 0 (PROTOCOL_ID_SECURE_CHANNEL)
|
||||
status_raw.add(0x0000, 4) # ProtocolCode = 0 (SESSION_ESTABLISHMENT_SUCCESS)
|
||||
|
||||
var raw = resp.encode(status_raw)
|
||||
|
||||
self.responder.send_response(raw, addr, port, resp.message_counter)
|
||||
|
||||
session.close()
|
||||
session.set_keys(i2r, r2i, ac, session_timestamp)
|
||||
session.set_persist(true) # keep session on flash
|
||||
session.set_no_expiration() # never expire
|
||||
session.save()
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
#############################################################
|
||||
# placeholder, nothing to run for now
|
||||
def every_second()
|
||||
end
|
||||
end
|
||||
matter.Commisioning_Context = Matter_Commisioning_Context
|
||||
|
||||
#-
|
||||
|
||||
# STEP 1
|
||||
PBKDF_PR = matter.PBKDFParamRequest().parse(bytes("15300120D2DAEE8760C9B1D1B25E0E2E4DD6ECA8AEF6193C0203761356FCB06BBEDD7D662502054C240300280435052501881325022C011818"))
|
||||
{'passcodeId': 0, 'initiatorRandom': bytes('D2DAEE8760C9B1D1B25E0E2E4DD6ECA8AEF6193C0203761356FCB06BBEDD7D66'),
|
||||
'hasPBKDFParameters': 0, 'SLEEPY_IDLE_INTERVAL': 5000, 'SLEEPY_ACTIVE_INTERVAL': 300, 'initiator_session_id': 19461}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# ##########################################################################################
|
||||
PBKDF_PR = matter.PBKDFParamRequest().parse(bytes("15300120D2DAEE8760C9B1D1B25E0E2E4DD6ECA8AEF6193C0203761356FCB06BBEDD7D662502054C240300280435052501881325022C011818"))
|
||||
print(matter.inspect(PBKDF_PR))
|
||||
{'passcodeId': 0, 'initiatorRandom': bytes('D2DAEE8760C9B1D1B25E0E2E4DD6ECA8AEF6193C0203761356FCB06BBEDD7D66'), 'hasPBKDFParameters': 0, 'SLEEPY_IDLE_INTERVAL': 5000, 'SLEEPY_ACTIVE_INTERVAL': 300, 'initiator_session_id': 19461}
|
||||
|
||||
var r = matter.PBKDFParamResponse()
|
||||
r.initiatorRandom = bytes("112233445566778899AABBCCDDEEFF00112233445566778899AABBCCDDEEFF00")
|
||||
r.responderRandom = bytes("112233445566778899AABBCCDDEEFF00112233445566778899AABBCCDDEEFF00")
|
||||
r.responderSessionId = 1234
|
||||
r.pbkdf_parameters_iterations = 1000
|
||||
r.pbkdf_parameters_salt = bytes("deadbeef11223344deadbeef11223344")
|
||||
r.SLEEPY_IDLE_INTERVAL = 100
|
||||
r.SLEEPY_ACTIVE_INTERVAL = 200
|
||||
|
||||
bytes('15300120112233445566778899AABBCCDDEEFF00112233445566778899AABBCCDDEEFF00300220112233445566778899AABBCCDDEEFF00112233445566778899AABBCCDDEEFF002503D20418')
|
||||
|
||||
|
||||
# ##########################################################################################
|
||||
var m = matter.Frame()
|
||||
m.decode(bytes("0400000006747A09347BFD880AC8128005205FC3000015300120D2DAEE8760C9B1D1B25E0E2E4DD6ECA8AEF6193C0203761356FCB06BBEDD7D662502054C240300280435052501881325022C011818"))
|
||||
|
||||
# 'opcode': 32
|
||||
# 'local_session_id': 0
|
||||
# 'protocol_id': 0
|
||||
|
||||
#{'dest_node_id_8': nil, 'flag_dsiz': 0, 'x_flag_r': 1, 'sec_c': 0, 'app_payload_idx': 22, 'sec_flags': 0,
|
||||
#'dest_node_id_2': nil, 'x_flag_sx': 0, 'sec_p': 0, 'message_counter': 159020038, 'x_flag_v': 0, 'flags': 4,
|
||||
#'vendor_id': nil, 'x_flag_i': 1, 'source_node_id': bytes('347BFD880AC81280'),
|
||||
#'ack_message_counter': nil, 'raw': bytes('0400000006747A09347BFD880AC8128005205FC3000015300120D2DAEE8760C9...'),
|
||||
#'exchange_id': 50015, 'opcode': 32, 'local_session_id': 0, 'x_flag_a': 0, 'flag_s': 1, 'x_flags': 5, 'sec_sesstype': 0,
|
||||
#'sec_extensions': nil, 'sec_mx': 0, 'protocol_id': 0}
|
||||
|
||||
0400000006747A09347BFD880AC8128005205FC3000015300120D2DAEE8760C9B1D1B25E0E2E4DD6ECA8AEF6193C0203761356FCB06BBEDD7D662502054C240300280435052501881325022C011818
|
||||
|
||||
12:09:05.561 MTR: sending packet to '192.168.2.109:5540' 050000000674C82B96B90B530000347BFD880AC8128000215FC3000015300120D2DAEE8760C9B1D1B25E0E2E4DD6ECA8AEF6193C0203761356FCB06BBEDD7D66300220AA981992DB666B51DEDC0DD67ED6ABBB29AB30E67452C8893166FBF5FD95601D2503010018
|
||||
|
||||
050000000674C82B96B90B530000347BFD880AC8128000215FC3000015300120D2DAEE8760C9B1D1B25E0E2E4DD6ECA8AEF6193C0203761356FCB06BBEDD7D66300220AA981992DB666B51DEDC0DD67ED6ABBB29AB30E67452C8893166FBF5FD95601D2503010018
|
||||
12:10:29.174 MTR: received message {
|
||||
'flag_s': 1, 'flag_dsiz': 1, 'x_flag_r': 1, 'x_flag_sx': 1, 'sec_mx': 0, 'sec_flags': 0,
|
||||
'dest_node_id_2': nil, 'sec_sesstype': 0, 'local_session_id': 0, 'ack_message_counter': -2014389550,
|
||||
'x_flag_v': 1, 'flags': 5, 'vendor_id': 8193, 'x_flag_i': 1, 'source_node_id': bytes('96B90B530000347B'),
|
||||
'app_payload_idx': 51590,
|
||||
'raw': bytes('050000000674C82B96B90B530000347BFD880AC8128000215FC3000015300120...'),
|
||||
'exchange_id': 0, 'opcode': 195, 'message_counter': 734557190, 'sec_p': 0, 'sec_c': 0,
|
||||
'protocol_id': 12309, 'dest_node_id_8': bytes('FD880AC812800021'),
|
||||
'sec_extensions': nil, 'x_flag_a': 1, 'x_flags': 95}
|
||||
|
||||
347BFD880AC81280
|
||||
|
||||
fe80::1bf1:bd1a:c5ff:818a
|
||||
b8:27:eb:8b:d2:59
|
||||
|
||||
{'mac': 'C8:2B:96:B9:0B:53', 'ip6local': 'fe80::ca2b:96ff:feb9:b53', 'ip': '192.168.1.116'}
|
||||
|
||||
-#
|
@ -0,0 +1,317 @@
|
||||
#
|
||||
# Matter_Commissioning_Data.be - suppport for Matter Commissioning messages structure
|
||||
#
|
||||
# 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/>.
|
||||
#
|
||||
|
||||
import matter
|
||||
|
||||
#@ solidify:Matter_PBKDFParamRequest,weak
|
||||
#@ solidify:Matter_PBKDFParamResponse,weak
|
||||
#@ solidify:Matter_Pake1,weak
|
||||
#@ solidify:Matter_Pake2,weak
|
||||
#@ solidify:Matter_Pake3,weak
|
||||
#@ solidify:Matter_Sigma1,weak
|
||||
#@ solidify:Matter_Sigma2,weak
|
||||
#@ solidify:Matter_Sigma2Resume,weak
|
||||
#@ solidify:Matter_Sigma3,weak
|
||||
|
||||
#################################################################################
|
||||
# class PBKDFParamRequest encaspulating pbkdfparamreq-struct (p. 151)
|
||||
#################################################################################
|
||||
class Matter_PBKDFParamRequest
|
||||
var initiatorRandom
|
||||
var initiator_session_id
|
||||
var passcodeId
|
||||
var hasPBKDFParameters
|
||||
var SLEEPY_IDLE_INTERVAL
|
||||
var SLEEPY_ACTIVE_INTERVAL
|
||||
|
||||
def parse(b, idx)
|
||||
if idx == nil idx = 0 end
|
||||
var val = matter.TLV.parse(b, idx)
|
||||
|
||||
self.initiatorRandom = val.getsubval(1)
|
||||
self.initiator_session_id = val.getsubval(2)
|
||||
self.passcodeId = val.getsubval(3)
|
||||
self.hasPBKDFParameters = val.getsubval(4)
|
||||
var initiatorSEDParams = val.findsub(5)
|
||||
if initiatorSEDParams != nil
|
||||
self.SLEEPY_IDLE_INTERVAL = initiatorSEDParams.findsubval(1)
|
||||
self.SLEEPY_ACTIVE_INTERVAL = initiatorSEDParams.findsubval(2)
|
||||
end
|
||||
return self
|
||||
end
|
||||
end
|
||||
matter.PBKDFParamRequest = Matter_PBKDFParamRequest
|
||||
|
||||
#################################################################################
|
||||
# class PBKDFParamResponse encaspulating pbkdfparamresp-struct (p. 153)
|
||||
#################################################################################
|
||||
class Matter_PBKDFParamResponse
|
||||
var initiatorRandom
|
||||
var responderRandom
|
||||
var responderSessionId
|
||||
var pbkdf_parameters_iterations
|
||||
var pbkdf_parameters_salt
|
||||
var SLEEPY_IDLE_INTERVAL
|
||||
var SLEEPY_ACTIVE_INTERVAL
|
||||
|
||||
def encode(b)
|
||||
var s = matter.TLV.Matter_TLV_struct()
|
||||
# initiatorRandom
|
||||
s.add_TLV(1, matter.TLV.B1, self.initiatorRandom)
|
||||
s.add_TLV(2, matter.TLV.B1, self.responderRandom)
|
||||
s.add_TLV(3, matter.TLV.U2, self.responderSessionId)
|
||||
var s_pbkdf = s.add_struct(4)
|
||||
s_pbkdf.add_TLV(1, matter.TLV.U4, self.pbkdf_parameters_iterations)
|
||||
s_pbkdf.add_TLV(2, matter.TLV.B1, self.pbkdf_parameters_salt)
|
||||
if self.SLEEPY_IDLE_INTERVAL != nil || self.SLEEPY_ACTIVE_INTERVAL != nil
|
||||
var s2 = s.add_struct(5)
|
||||
s2.add_TLV(1, matter.TLV.U4, self.SLEEPY_IDLE_INTERVAL)
|
||||
s2.add_TLV(2, matter.TLV.U4, self.SLEEPY_ACTIVE_INTERVAL)
|
||||
end
|
||||
return s.encode()
|
||||
end
|
||||
end
|
||||
matter.PBKDFParamResponse = Matter_PBKDFParamResponse
|
||||
|
||||
#################################################################################
|
||||
# class Pake1
|
||||
#################################################################################
|
||||
class Matter_Pake1
|
||||
var pA
|
||||
|
||||
def parse(b, idx)
|
||||
if idx == nil idx = 0 end
|
||||
var val = matter.TLV.parse(b, idx)
|
||||
tasmota.log("MTR: parsed TLV: " + str(val), 3)
|
||||
|
||||
self.pA = val.getsubval(1)
|
||||
return self
|
||||
end
|
||||
end
|
||||
matter.Pake1 = Matter_Pake1
|
||||
|
||||
#################################################################################
|
||||
# class Pake1
|
||||
#################################################################################
|
||||
class Matter_Pake2
|
||||
var pB # 65 bytes
|
||||
var cB # 32 bytes
|
||||
|
||||
def encode(b)
|
||||
var s = matter.TLV.Matter_TLV_struct()
|
||||
#
|
||||
s.add_TLV(1, matter.TLV.B1, self.pB)
|
||||
s.add_TLV(2, matter.TLV.B1, self.cB)
|
||||
return s.encode()
|
||||
end
|
||||
end
|
||||
matter.Pake2 = Matter_Pake2
|
||||
|
||||
# class Pake3
|
||||
class Matter_Pake3
|
||||
var cA
|
||||
|
||||
def parse(b, idx)
|
||||
if idx == nil idx = 0 end
|
||||
var val = matter.TLV.parse(b, idx)
|
||||
tasmota.log("MTR: parsed TLV: " + str(val), 3)
|
||||
|
||||
self.cA = val.getsubval(1)
|
||||
return self
|
||||
end
|
||||
end
|
||||
matter.Pake3 = Matter_Pake3
|
||||
|
||||
#################################################################################
|
||||
# class Sigma1, p.160
|
||||
#################################################################################
|
||||
class Matter_Sigma1
|
||||
var initiatorRandom # bytes(32)
|
||||
var initiator_session_id # U16
|
||||
var destinationId # bytes(32)
|
||||
var initiatorEphPubKey # bytes(65)
|
||||
# var initiatorSEDParams # (opt) sed-parameter-struct
|
||||
var SLEEPY_IDLE_INTERVAL
|
||||
var SLEEPY_ACTIVE_INTERVAL
|
||||
var resumptionID # (opt) bytes(16)
|
||||
var initiatorResumeMIC # (opt) bytes(16)
|
||||
var Msg1
|
||||
|
||||
def parse(b, idx)
|
||||
if idx == nil idx = 0 end
|
||||
var val = matter.TLV.parse(b, idx)
|
||||
self.Msg1 = b[idx..]
|
||||
tasmota.log("MTR: Sigma1 TLV=" + str(val), 3)
|
||||
|
||||
self.initiatorRandom = val.getsubval(1)
|
||||
self.initiator_session_id = val.getsubval(2)
|
||||
self.destinationId = val.getsubval(3)
|
||||
self.initiatorEphPubKey = val.getsubval(4)
|
||||
var initiatorSEDParams = val.findsub(5)
|
||||
if initiatorSEDParams != nil
|
||||
self.SLEEPY_IDLE_INTERVAL = initiatorSEDParams.findsubval(1)
|
||||
self.SLEEPY_ACTIVE_INTERVAL = initiatorSEDParams.findsubval(2)
|
||||
end
|
||||
var resumptionID = val.findsub(6)
|
||||
var initiatorResumeMIC = val.findsub(7)
|
||||
return self
|
||||
end
|
||||
end
|
||||
matter.Sigma1 = Matter_Sigma1
|
||||
|
||||
#################################################################################
|
||||
# class Sigma2
|
||||
#################################################################################
|
||||
class Matter_Sigma2
|
||||
var responderRandom # bytes(32)
|
||||
var responderSessionId # U16
|
||||
var responderEphPubKey # bytes(65)
|
||||
var encrypted2 # bytes()
|
||||
var SLEEPY_IDLE_INTERVAL
|
||||
var SLEEPY_ACTIVE_INTERVAL
|
||||
|
||||
def encode(b)
|
||||
var s = matter.TLV.Matter_TLV_struct()
|
||||
# initiatorRandom
|
||||
s.add_TLV(1, matter.TLV.B1, self.responderRandom)
|
||||
s.add_TLV(2, matter.TLV.U2, self.responderSessionId)
|
||||
s.add_TLV(3, matter.TLV.B1, self.responderEphPubKey)
|
||||
s.add_TLV(4, matter.TLV.B1, self.encrypted2)
|
||||
if self.SLEEPY_IDLE_INTERVAL != nil || self.SLEEPY_ACTIVE_INTERVAL != nil
|
||||
var s2 = s.add_struct(5)
|
||||
s2.add_TLV(1, matter.TLV.U4, self.SLEEPY_IDLE_INTERVAL)
|
||||
s2.add_TLV(2, matter.TLV.U4, self.SLEEPY_ACTIVE_INTERVAL)
|
||||
end
|
||||
return s.encode()
|
||||
end
|
||||
end
|
||||
matter.Sigma2 = Matter_Sigma2
|
||||
|
||||
#################################################################################
|
||||
# class Sigma2Resume, p.170
|
||||
#################################################################################
|
||||
class Matter_Sigma2Resume
|
||||
var resumptionID # bytes(16)
|
||||
var sigma2ResumeMIC # bytes(16)
|
||||
var responderSessionID # u16
|
||||
var SLEEPY_IDLE_INTERVAL
|
||||
var SLEEPY_ACTIVE_INTERVAL
|
||||
|
||||
def encode(b)
|
||||
var s = matter.TLV.Matter_TLV_struct()
|
||||
# initiatorRandom
|
||||
s.add_TLV(1, matter.TLV.B1, self.resumptionID)
|
||||
s.add_TLV(2, matter.TLV.B1, self.sigma2ResumeMIC)
|
||||
s.add_TLV(3, matter.TLV.B1, self.responderSessionID)
|
||||
if self.SLEEPY_IDLE_INTERVAL != nil || self.SLEEPY_ACTIVE_INTERVAL != nil
|
||||
var s2 = s.add_struct(4)
|
||||
s2.add_TLV(1, matter.TLV.U4, self.SLEEPY_IDLE_INTERVAL)
|
||||
s2.add_TLV(2, matter.TLV.U4, self.SLEEPY_ACTIVE_INTERVAL)
|
||||
end
|
||||
return s.encode()
|
||||
end
|
||||
end
|
||||
matter.Sigma2Resume = Matter_Sigma2Resume
|
||||
|
||||
#################################################################################
|
||||
# class Sigma3, p.160
|
||||
#################################################################################
|
||||
class Matter_Sigma3
|
||||
var TBEData3Encrypted # bytes()
|
||||
var Msg3
|
||||
|
||||
def parse(b, idx)
|
||||
if idx == nil idx = 0 end
|
||||
var val = matter.TLV.parse(b, idx)
|
||||
self.Msg3 = b[idx..]
|
||||
tasmota.log("MTR: Sigma3 TLV=" + str(val), 3)
|
||||
|
||||
self.TBEData3Encrypted = val.getsubval(1)
|
||||
return self
|
||||
end
|
||||
end
|
||||
matter.Sigma3 = Matter_Sigma3
|
||||
|
||||
|
||||
#-
|
||||
|
||||
# STEP 1
|
||||
PBKDF_PR = matter.PBKDFParamRequest().parse(bytes("15300120D2DAEE8760C9B1D1B25E0E2E4DD6ECA8AEF6193C0203761356FCB06BBEDD7D662502054C240300280435052501881325022C011818"))
|
||||
{'passcodeId': 0, 'initiatorRandom': bytes('D2DAEE8760C9B1D1B25E0E2E4DD6ECA8AEF6193C0203761356FCB06BBEDD7D66'),
|
||||
'hasPBKDFParameters': 0, 'SLEEPY_IDLE_INTERVAL': 5000, 'SLEEPY_ACTIVE_INTERVAL': 300, 'initiator_session_id': 19461}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# ##########################################################################################
|
||||
PBKDF_PR = matter.PBKDFParamRequest().parse(bytes("15300120D2DAEE8760C9B1D1B25E0E2E4DD6ECA8AEF6193C0203761356FCB06BBEDD7D662502054C240300280435052501881325022C011818"))
|
||||
print(matter.inspect(PBKDF_PR))
|
||||
{'passcodeId': 0, 'initiatorRandom': bytes('D2DAEE8760C9B1D1B25E0E2E4DD6ECA8AEF6193C0203761356FCB06BBEDD7D66'), 'hasPBKDFParameters': 0, 'SLEEPY_IDLE_INTERVAL': 5000, 'SLEEPY_ACTIVE_INTERVAL': 300, 'initiator_session_id': 19461}
|
||||
|
||||
var r = matter.PBKDFParamResponse()
|
||||
r.initiatorRandom = bytes("112233445566778899AABBCCDDEEFF00112233445566778899AABBCCDDEEFF00")
|
||||
r.responderRandom = bytes("112233445566778899AABBCCDDEEFF00112233445566778899AABBCCDDEEFF00")
|
||||
r.responderSessionId = 1234
|
||||
r.pbkdf_parameters_iterations = 1000
|
||||
r.pbkdf_parameters_salt = bytes("deadbeef11223344deadbeef11223344")
|
||||
r.SLEEPY_IDLE_INTERVAL = 100
|
||||
r.SLEEPY_ACTIVE_INTERVAL = 200
|
||||
|
||||
bytes('15300120112233445566778899AABBCCDDEEFF00112233445566778899AABBCCDDEEFF00300220112233445566778899AABBCCDDEEFF00112233445566778899AABBCCDDEEFF002503D20418')
|
||||
|
||||
|
||||
# ##########################################################################################
|
||||
var m = matter.Frame()
|
||||
m.decode(bytes("0400000006747A09347BFD880AC8128005205FC3000015300120D2DAEE8760C9B1D1B25E0E2E4DD6ECA8AEF6193C0203761356FCB06BBEDD7D662502054C240300280435052501881325022C011818"))
|
||||
|
||||
# 'opcode': 32
|
||||
# 'local_session_id': 0
|
||||
# 'protocol_id': 0
|
||||
|
||||
#{'dest_node_id_8': nil, 'flag_dsiz': 0, 'x_flag_r': 1, 'sec_c': 0, 'app_payload_idx': 22, 'sec_flags': 0,
|
||||
#'dest_node_id_2': nil, 'x_flag_sx': 0, 'sec_p': 0, 'message_counter': 159020038, 'x_flag_v': 0, 'flags': 4,
|
||||
#'vendor_id': nil, 'x_flag_i': 1, 'source_node_id': bytes('347BFD880AC81280'),
|
||||
#'ack_message_counter': nil, 'raw': bytes('0400000006747A09347BFD880AC8128005205FC3000015300120D2DAEE8760C9...'),
|
||||
#'exchange_id': 50015, 'opcode': 32, 'local_session_id': 0, 'x_flag_a': 0, 'flag_s': 1, 'x_flags': 5, 'sec_sesstype': 0,
|
||||
#'sec_extensions': nil, 'sec_mx': 0, 'protocol_id': 0}
|
||||
|
||||
0400000006747A09347BFD880AC8128005205FC3000015300120D2DAEE8760C9B1D1B25E0E2E4DD6ECA8AEF6193C0203761356FCB06BBEDD7D662502054C240300280435052501881325022C011818
|
||||
|
||||
12:09:05.561 MTR: sending packet to '192.168.2.109:5540' 050000000674C82B96B90B530000347BFD880AC8128000215FC3000015300120D2DAEE8760C9B1D1B25E0E2E4DD6ECA8AEF6193C0203761356FCB06BBEDD7D66300220AA981992DB666B51DEDC0DD67ED6ABBB29AB30E67452C8893166FBF5FD95601D2503010018
|
||||
|
||||
050000000674C82B96B90B530000347BFD880AC8128000215FC3000015300120D2DAEE8760C9B1D1B25E0E2E4DD6ECA8AEF6193C0203761356FCB06BBEDD7D66300220AA981992DB666B51DEDC0DD67ED6ABBB29AB30E67452C8893166FBF5FD95601D2503010018
|
||||
12:10:29.174 MTR: received message {
|
||||
'flag_s': 1, 'flag_dsiz': 1, 'x_flag_r': 1, 'x_flag_sx': 1, 'sec_mx': 0, 'sec_flags': 0,
|
||||
'dest_node_id_2': nil, 'sec_sesstype': 0, 'local_session_id': 0, 'ack_message_counter': -2014389550,
|
||||
'x_flag_v': 1, 'flags': 5, 'vendor_id': 8193, 'x_flag_i': 1, 'source_node_id': bytes('96B90B530000347B'),
|
||||
'app_payload_idx': 51590,
|
||||
'raw': bytes('050000000674C82B96B90B530000347BFD880AC8128000215FC3000015300120...'),
|
||||
'exchange_id': 0, 'opcode': 195, 'message_counter': 734557190, 'sec_p': 0, 'sec_c': 0,
|
||||
'protocol_id': 12309, 'dest_node_id_8': bytes('FD880AC812800021'),
|
||||
'sec_extensions': nil, 'x_flag_a': 1, 'x_flags': 95}
|
||||
|
||||
347BFD880AC81280
|
||||
|
||||
fe80::1bf1:bd1a:c5ff:818a
|
||||
b8:27:eb:8b:d2:59
|
||||
|
||||
{'mac': 'C8:2B:96:B9:0B:53', 'ip6local': 'fe80::ca2b:96ff:feb9:b53', 'ip': '192.168.1.116'}
|
||||
|
||||
-#
|
508
lib/libesp32/berry_matter/src/embedded/Matter_Device.be
Normal file
508
lib/libesp32/berry_matter/src/embedded/Matter_Device.be
Normal file
@ -0,0 +1,508 @@
|
||||
#
|
||||
# Matter_Device.be - implements a generic Matter device (commissionee)
|
||||
#
|
||||
# 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/>.
|
||||
#
|
||||
|
||||
#@ solidify:Matter_Device,weak
|
||||
|
||||
class Matter_Device
|
||||
static var UDP_PORT = 5540 # this is the default port for group multicast, we also use it for unicast
|
||||
static var PASSCODE_DEFAULT = 20202021
|
||||
static var PBKDF_ITERATIONS = 1000 # I don't see any reason to choose a different number
|
||||
static var VENDOR_ID = 0xFFF1
|
||||
static var PRODUCT_ID = 0x8000
|
||||
static var FILENAME = "_matter_device.json"
|
||||
var plugins # list of plugins
|
||||
var udp_server # `matter.UDPServer()` object
|
||||
var msg_handler # `matter.MessageHandler()` object
|
||||
var sessions # `matter.Session_Store()` objet
|
||||
var ui
|
||||
# information about the device
|
||||
var commissioning_instance_wifi # random instance name for commissioning
|
||||
var commissioning_instance_eth # random instance name for commissioning
|
||||
var hostname_wifi # MAC-derived hostname for commissioning
|
||||
var hostname_eth # MAC-derived hostname for commissioning
|
||||
var vendorid
|
||||
var productid
|
||||
var discriminator
|
||||
# context for PBKDF
|
||||
var passcode
|
||||
var iterations
|
||||
# PBKDF information used only during PASE (freed afterwards)
|
||||
var salt
|
||||
var w0, w1, L
|
||||
|
||||
#############################################################
|
||||
def init()
|
||||
import crypto
|
||||
import string
|
||||
if !tasmota.get_option(matter.MATTER_OPTION)
|
||||
matter.UI(self) # minimal UI
|
||||
return
|
||||
end # abort if SetOption 151 is not set
|
||||
|
||||
self.plugins = []
|
||||
self.vendorid = self.VENDOR_ID
|
||||
self.productid = self.PRODUCT_ID
|
||||
self.iterations = self.PBKDF_ITERATIONS
|
||||
self.load_param()
|
||||
self.commissioning_instance_wifi = crypto.random(8).tohex() # 16 characters random hostname
|
||||
self.commissioning_instance_eth = crypto.random(8).tohex() # 16 characters random hostname
|
||||
|
||||
self.sessions = matter.Session_Store()
|
||||
self.sessions.load()
|
||||
self.msg_handler = matter.MessageHandler(self)
|
||||
self.ui = matter.UI(self)
|
||||
|
||||
# add the default plugin
|
||||
self.plugins.push(matter.Plugin_core(self))
|
||||
|
||||
self.start_mdns_announce_hostnames()
|
||||
|
||||
if tasmota.wifi()['up']
|
||||
self.start_udp(self.UDP_PORT)
|
||||
else
|
||||
tasmota.add_rule("Wifi#Connected", def ()
|
||||
self.start_udp(self.UDP_PORT)
|
||||
tasmota.remove_rule("Wifi#Connected", "matter_device_udp")
|
||||
|
||||
end, self)
|
||||
end
|
||||
|
||||
if tasmota.eth()['up']
|
||||
self.start_udp(self.UDP_PORT)
|
||||
else
|
||||
tasmota.add_rule("Eth#Connected", def ()
|
||||
self.start_udp(self.UDP_PORT)
|
||||
tasmota.remove_rule("Eth#Connected", "matter_device_udp")
|
||||
end, self)
|
||||
end
|
||||
|
||||
self.start_basic_commissioning()
|
||||
|
||||
tasmota.add_driver(self)
|
||||
end
|
||||
|
||||
#############################################################
|
||||
# Start Basic Commissioning Window
|
||||
def start_basic_commissioning()
|
||||
# compute PBKDF
|
||||
self.compute_pbkdf(self.passcode)
|
||||
end
|
||||
|
||||
def finish_commissioning()
|
||||
end
|
||||
|
||||
#############################################################
|
||||
# Compute the PBKDF parameters for SPAKE2+
|
||||
#
|
||||
# iterations is set to 1000 which is large enough
|
||||
def compute_pbkdf(passcode_int)
|
||||
import crypto
|
||||
self.salt = crypto.random(16) # bytes("5350414B453250204B65792053616C74")
|
||||
var passcode = bytes().add(passcode_int, 4)
|
||||
|
||||
var tv = crypto.PBKDF2_HMAC_SHA256().derive(passcode, self.salt, self.iterations, 80)
|
||||
var w0s = tv[0..39]
|
||||
var w1s = tv[40..79]
|
||||
|
||||
self.w0 = crypto.EC_P256().mod(w0s)
|
||||
self.w1 = crypto.EC_P256().mod(w1s)
|
||||
self.L = crypto.EC_P256().public_key(self.w1)
|
||||
|
||||
tasmota.log("MTR: ******************************", 3)
|
||||
tasmota.log("MTR: salt = " + self.salt.tohex(), 3)
|
||||
tasmota.log("MTR: passcode = " + passcode.tohex(), 3)
|
||||
tasmota.log("MTR: w0 = " + self.w0.tohex(), 3)
|
||||
tasmota.log("MTR: w1 = " + self.w1.tohex(), 3)
|
||||
tasmota.log("MTR: L = " + self.L.tohex(), 3)
|
||||
tasmota.log("MTR: ******************************", 3)
|
||||
end
|
||||
|
||||
#############################################################
|
||||
# compute QR Code content
|
||||
def compute_qrcode_content()
|
||||
var raw = bytes().resize(11) # we don't use TLV Data so it's only 88 bits or 11 bytes
|
||||
# version is `000` dont touch
|
||||
raw.setbits(3, 16, self.vendorid)
|
||||
raw.setbits(19, 16, self.productid)
|
||||
# custom flow = 0 (offset=35, len=2)
|
||||
raw.setbits(37, 8, 0x04) # already on IP network
|
||||
raw.setbits(45, 12, self.discriminator & 0xFFF)
|
||||
raw.setbits(57, 27, self.passcode & 0x7FFFFFF)
|
||||
# padding (offset=84 len=4)
|
||||
return "MT:" + matter.Base38.encode(raw)
|
||||
end
|
||||
|
||||
|
||||
#############################################################
|
||||
# compute the 11 digits manual pairing code (wihout vendorid nor productid) p.223
|
||||
def compute_manual_pairing_code()
|
||||
import string
|
||||
var digit_1 = (self.discriminator & 0x0FFF) >> 10
|
||||
var digit_2_6 = ((self.discriminator & 0x0300) << 6) | (self.passcode & 0x3FFF)
|
||||
var digit_7_10 = (self.passcode >> 14)
|
||||
|
||||
var ret = string.format("%1i%05i%04i", digit_1, digit_2_6, digit_7_10)
|
||||
ret += matter.Verhoeff.checksum(ret)
|
||||
return ret
|
||||
end
|
||||
|
||||
#############################################################
|
||||
# dispatch every second click to sub-objects that need it
|
||||
def every_second()
|
||||
self.sessions.every_second()
|
||||
self.msg_handler.every_second()
|
||||
end
|
||||
|
||||
#############################################################
|
||||
def stop()
|
||||
if self.udp_server self.udp_server.stop() end
|
||||
end
|
||||
|
||||
#############################################################
|
||||
# callback when message is received
|
||||
def msg_received(raw, addr, port)
|
||||
return self.msg_handler.msg_received(raw, addr, port)
|
||||
end
|
||||
|
||||
def msg_send(raw, addr, port, id)
|
||||
return self.udp_server.send_response(raw, addr, port, id)
|
||||
end
|
||||
|
||||
def packet_ack(id)
|
||||
return self.udp_server.packet_ack(id)
|
||||
end
|
||||
|
||||
#############################################################
|
||||
# Start UDP Server
|
||||
def start_udp(port)
|
||||
if self.udp_server return end # already started
|
||||
if port == nil port = 5540 end
|
||||
tasmota.log("MTR: starting UDP server on port: " + str(port), 2)
|
||||
self.udp_server = matter.UDPServer("", port)
|
||||
self.udp_server.start(/ raw, addr, port -> self.msg_received(raw, addr, port))
|
||||
end
|
||||
|
||||
#############################################################
|
||||
# start_operational_dicovery
|
||||
#
|
||||
# Pass control to `device`
|
||||
def start_operational_dicovery_deferred(session)
|
||||
# defer to next click
|
||||
tasmota.set_timer(0, /-> self.start_operational_dicovery(session))
|
||||
end
|
||||
|
||||
#############################################################
|
||||
def start_commissioning_complete_deferred(session)
|
||||
# defer to next click
|
||||
tasmota.set_timer(0, /-> self.start_commissioning_complete(session))
|
||||
end
|
||||
|
||||
#############################################################
|
||||
# Start UDP mDNS announcements for commissioning
|
||||
#
|
||||
# eth is `true` if ethernet turned up, `false` is wifi turned up
|
||||
# def mdns_announce_commissioning()
|
||||
# var services = {
|
||||
# "VP":str(self.vendorid) + "+" + str(self.productid),
|
||||
# "D": self.discriminator,
|
||||
# "CM":1, # requires passcode
|
||||
# "T":0, # no support for TCP
|
||||
# "SII":5000, "SAI":300
|
||||
# }
|
||||
|
||||
# if self.self.hostname_eth
|
||||
# mdns.add_service("_matterc","_udp", 5540, services, self.commissioning_instance_eth, self.hostname_eth)
|
||||
# end
|
||||
# if self.self.hostname_wifi
|
||||
# mdns.add_service("_matter","_tcp", 5540, services, self.commissioning_instance_wifi, self.hostname_wifi)
|
||||
# end
|
||||
# end
|
||||
|
||||
#############################################################
|
||||
# Start Operational Discovery
|
||||
def start_operational_dicovery(session)
|
||||
import crypto
|
||||
import mdns
|
||||
import string
|
||||
|
||||
# clear any PBKDF information to free memory
|
||||
self.salt = nil
|
||||
self.w0 = nil
|
||||
self.w1 = nil
|
||||
self.L = nil
|
||||
|
||||
# save session as persistant
|
||||
session.set_no_expiration()
|
||||
session.set_persist(true)
|
||||
# close the PASE session, it will be re-opened with a CASE session
|
||||
session.close()
|
||||
self.sessions.save()
|
||||
|
||||
self.mdns_announce_op_discovery(session)
|
||||
end
|
||||
|
||||
#############################################################
|
||||
# Commissioning Complete
|
||||
#
|
||||
def start_commissioning_complete(session)
|
||||
tasmota.log("MTR: *** Commissioning complete ***", 2)
|
||||
end
|
||||
|
||||
#############################################################
|
||||
# read an attribute
|
||||
#
|
||||
def read_attribute(msg, endpoint, cluster, attribute)
|
||||
var idx = 0
|
||||
while idx < size(self.plugins)
|
||||
var plugin = self.plugins[idx]
|
||||
|
||||
var ret = plugin.read_attribute(msg, endpoint, cluster, attribute)
|
||||
if ret != nil
|
||||
return ret
|
||||
end
|
||||
|
||||
idx += 1
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
#############################################################
|
||||
# Persistance of Matter Device parameters
|
||||
#
|
||||
#############################################################
|
||||
#
|
||||
def save_param()
|
||||
import json
|
||||
var j = json.dump({'distinguish':self.discriminator, 'passcode':self.passcode})
|
||||
try
|
||||
import string
|
||||
var f = open(self.FILENAME, "w")
|
||||
f.write(j)
|
||||
f.close()
|
||||
return j
|
||||
except .. as e, m
|
||||
tasmota.log("MTR: Session_Store::save Exception:" + str(e) + "|" + str(m), 2)
|
||||
return j
|
||||
end
|
||||
end
|
||||
|
||||
#############################################################
|
||||
def load_param()
|
||||
import string
|
||||
import crypto
|
||||
try
|
||||
|
||||
var f = open(self.FILENAME)
|
||||
var s = f.read()
|
||||
f.close()
|
||||
|
||||
import json
|
||||
var j = json.load(s)
|
||||
|
||||
self.discriminator = j.find("distinguish")
|
||||
self.passcode = j.find("passcode")
|
||||
except .. as e, m
|
||||
if e != "io_error"
|
||||
tasmota.log("MTR: Session_Store::load Exception:" + str(e) + "|" + str(m), 2)
|
||||
end
|
||||
end
|
||||
|
||||
var dirty = false
|
||||
if self.discriminator == nil
|
||||
self.discriminator = crypto.random(2).get(0,2) & 0xFFF
|
||||
dirty = true
|
||||
end
|
||||
if self.passcode == nil
|
||||
self.passcode = self.PASSCODE_DEFAULT
|
||||
dirty = true
|
||||
end
|
||||
if dirty self.save_param() end
|
||||
end
|
||||
|
||||
|
||||
#############################################################
|
||||
# Matter plugin management
|
||||
#
|
||||
# Plugins allow to specify response to read/write attributes
|
||||
# and command invokes
|
||||
#############################################################
|
||||
def invoke_request(msg, val, ctx)
|
||||
var idx = 0
|
||||
while idx < size(self.plugins)
|
||||
var plugin = self.plugins[idx]
|
||||
|
||||
var ret = plugin.invoke_request(msg, val, ctx)
|
||||
if ret != nil || ctx.status != matter.UNSUPPORTED_COMMAND # default value
|
||||
return ret
|
||||
end
|
||||
|
||||
idx += 1
|
||||
end
|
||||
end
|
||||
|
||||
#############################################################
|
||||
# MDNS Configuration
|
||||
#############################################################
|
||||
# Start MDNS and announce hostnames for Wifi and ETH from MAC
|
||||
#
|
||||
# When the announce is active, `hostname_wifi` and `hostname_eth`
|
||||
# are defined
|
||||
def start_mdns_announce_hostnames()
|
||||
if tasmota.wifi()['up']
|
||||
self._start_mdns_announce(false)
|
||||
else
|
||||
tasmota.add_rule("Wifi#Connected", def ()
|
||||
self._start_mdns_announce(false)
|
||||
tasmota.remove_rule("Wifi#Connected", "matter_device_mdns")
|
||||
end, self)
|
||||
end
|
||||
|
||||
if tasmota.eth()['up']
|
||||
self._start_mdns_announce(true)
|
||||
else
|
||||
tasmota.add_rule("Eth#Connected", def ()
|
||||
self._start_mdns_announce(true)
|
||||
tasmota.remove_rule("Eth#Connected", "matter_device_mdns")
|
||||
end, self)
|
||||
end
|
||||
end
|
||||
|
||||
#############################################################
|
||||
# Start UDP mDNS announcements for commissioning
|
||||
#
|
||||
# eth is `true` if ethernet turned up, `false` is wifi turned up
|
||||
def _start_mdns_announce(is_eth)
|
||||
import mdns
|
||||
import string
|
||||
|
||||
mdns.start()
|
||||
|
||||
var services = {
|
||||
"VP":str(self.vendorid) + "+" + str(self.productid),
|
||||
"D": self.discriminator,
|
||||
"CM":1, # requires passcode
|
||||
"T":0, # no support for TCP
|
||||
"SII":5000, "SAI":300
|
||||
}
|
||||
|
||||
# mdns
|
||||
try
|
||||
if is_eth
|
||||
var eth = tasmota.eth()
|
||||
self.hostname_eth = string.replace(eth.find("mac"), ':', '')
|
||||
mdns.add_hostname(self.hostname_eth, eth.find('ip6local',''), eth.find('ip',''), eth.find('ip6',''))
|
||||
mdns.add_service("_matterc", "_udp", 5540, services, self.commissioning_instance_eth, self.hostname_eth)
|
||||
|
||||
tasmota.log(string.format("MTR: starting mDNS on %s '%s' ptr to `%s.local`", is_eth ? "eth" : "wifi",
|
||||
is_eth ? self.commissioning_instance_eth : self.commissioning_instance_wifi,
|
||||
is_eth ? self.hostname_eth : self.hostname_wifi), 2)
|
||||
|
||||
# `mdns.add_subtype(service:string, proto:string, instance:string, hostname:string, subtype:string) -> nil`
|
||||
var subtype = "_L" + str(self.discriminator & 0xFFF)
|
||||
tasmota.log("MTR: adding subtype: "+subtype, 3)
|
||||
mdns.add_subtype("_matterc", "_udp", self.commissioning_instance_eth, self.hostname_eth, subtype)
|
||||
subtype = "_S" + str((self.discriminator & 0xF00) >> 8)
|
||||
tasmota.log("MTR: adding subtype: "+subtype, 3)
|
||||
mdns.add_subtype("_matterc", "_udp", self.commissioning_instance_eth, self.hostname_eth, subtype)
|
||||
subtype = "_V" + str(self.vendorid)
|
||||
tasmota.log("MTR: adding subtype: "+subtype, 3)
|
||||
mdns.add_subtype("_matterc", "_udp", self.commissioning_instance_eth, self.hostname_eth, subtype)
|
||||
subtype = "_CM1"
|
||||
tasmota.log("MTR: adding subtype: "+subtype, 3)
|
||||
mdns.add_subtype("_matterc", "_udp", self.commissioning_instance_eth, self.hostname_eth, subtype)
|
||||
else
|
||||
var wifi = tasmota.wifi()
|
||||
self.hostname_wifi = string.replace(wifi.find("mac"), ':', '')
|
||||
mdns.add_hostname(self.hostname_wifi, wifi.find('ip6local',''), wifi.find('ip',''), wifi.find('ip6',''))
|
||||
mdns.add_service("_matter", "_tcp", 5540, services, self.commissioning_instance_wifi, self.hostname_wifi)
|
||||
|
||||
tasmota.log(string.format("MTR: starting mDNS on %s '%s' ptr to `%s.local`", is_eth ? "eth" : "wifi",
|
||||
is_eth ? self.commissioning_instance_eth : self.commissioning_instance_wifi,
|
||||
is_eth ? self.hostname_eth : self.hostname_wifi), 2)
|
||||
|
||||
# `mdns.add_subtype(service:string, proto:string, instance:string, hostname:string, subtype:string) -> nil`
|
||||
var subtype = "_L" + str(self.discriminator & 0xFFF)
|
||||
tasmota.log("MTR: adding subtype: "+subtype, 3)
|
||||
mdns.add_subtype("_matterc", "_udp", self.commissioning_instance_wifi, self.hostname_wifi, subtype)
|
||||
subtype = "_S" + str((self.discriminator & 0xF00) >> 8)
|
||||
tasmota.log("MTR: adding subtype: "+subtype, 3)
|
||||
mdns.add_subtype("_matterc", "_udp", self.commissioning_instance_wifi, self.hostname_wifi, subtype)
|
||||
subtype = "_V" + str(self.vendorid)
|
||||
tasmota.log("MTR: adding subtype: "+subtype, 3)
|
||||
mdns.add_subtype("_matterc", "_udp", self.commissioning_instance_wifi, self.hostname_wifi, subtype)
|
||||
subtype = "_CM1"
|
||||
tasmota.log("MTR: adding subtype: "+subtype, 3)
|
||||
mdns.add_subtype("_matterc", "_udp", self.commissioning_instance_wifi, self.hostname_wifi, subtype)
|
||||
end
|
||||
except .. as e, m
|
||||
tasmota.log("MTR: Exception" + str(e) + "|" + str(m), 2)
|
||||
end
|
||||
|
||||
self.mdns_announce_op_discovery_all_sessions()
|
||||
end
|
||||
|
||||
#############################################################
|
||||
# Start UDP mDNS announcements for commissioning for all persisted sessions
|
||||
def mdns_announce_op_discovery_all_sessions()
|
||||
for session: self.sessions.sessions
|
||||
if session.get_deviceid() && session.get_fabric()
|
||||
self.mdns_announce_op_discovery(session)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
#############################################################
|
||||
# Start UDP mDNS announcements for commissioning
|
||||
def mdns_announce_op_discovery(session)
|
||||
import mdns
|
||||
import string
|
||||
try
|
||||
var device_id = session.get_deviceid().copy().reverse()
|
||||
var k_fabric = session.get_fabric_compressed()
|
||||
var op_node = k_fabric.tohex() + "-" + device_id.tohex()
|
||||
tasmota.log("MTR: Operational Discovery node = " + op_node, 2)
|
||||
|
||||
# mdns
|
||||
if (tasmota.eth().find("up"))
|
||||
tasmota.log(string.format("MTR: adding mDNS on %s '%s' ptr to `%s.local`", "eth", op_node, self.hostname_eth), 3)
|
||||
mdns.add_service("_matter","_tcp", 5540, nil, op_node, self.hostname_eth)
|
||||
var subtype = "_I" + k_fabric.tohex()
|
||||
tasmota.log("MTR: adding subtype: "+subtype, 3)
|
||||
mdns.add_subtype("_matter", "_tcp", op_node, self.hostname_eth, subtype)
|
||||
end
|
||||
if (tasmota.wifi().find("up"))
|
||||
tasmota.log(string.format("MTR: adding mDNS on %s '%s' ptr to `%s.local`", "wifi", op_node, self.hostname_wifi), 3)
|
||||
mdns.add_service("_matter","_tcp", 5540, nil, op_node, self.hostname_wifi)
|
||||
var subtype = "_I" + k_fabric.tohex()
|
||||
tasmota.log("MTR: adding subtype: "+subtype, 3)
|
||||
mdns.add_subtype("_matter", "_tcp", op_node, self.hostname_wifi, subtype)
|
||||
end
|
||||
except .. as e, m
|
||||
tasmota.log("MTR: Exception" + str(e) + "|" + str(m), 2)
|
||||
end
|
||||
end
|
||||
end
|
||||
matter.Device = Matter_Device
|
||||
|
||||
#-
|
||||
import global
|
||||
global.matter_device = matter_device()
|
||||
return matter_device
|
||||
-#
|
326
lib/libesp32/berry_matter/src/embedded/Matter_IM.be
Normal file
326
lib/libesp32/berry_matter/src/embedded/Matter_IM.be
Normal file
@ -0,0 +1,326 @@
|
||||
#
|
||||
# Matter_IM.be - suppport for Matter Interaction Model
|
||||
#
|
||||
# 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/>.
|
||||
#
|
||||
|
||||
import matter
|
||||
|
||||
#@ solidify:Matter_Response_container,weak
|
||||
#@ solidify:Matter_IM,weak
|
||||
|
||||
#################################################################################
|
||||
# Matter_Response_container
|
||||
#
|
||||
# Used to store all the elements of the reponse to an attribute or command
|
||||
#################################################################################
|
||||
class Matter_Response_container
|
||||
var endpoint
|
||||
var cluster
|
||||
var attribute
|
||||
var command
|
||||
var status
|
||||
end
|
||||
matter.Response_container = Matter_Response_container
|
||||
|
||||
#################################################################################
|
||||
# Matter_IM class
|
||||
#################################################################################
|
||||
class Matter_IM
|
||||
var responder
|
||||
|
||||
def init(responder)
|
||||
self.responder = responder
|
||||
end
|
||||
|
||||
def process_incoming(msg, remote_ip, remote_port)
|
||||
# messages are always TLV, decode payload
|
||||
tasmota.log("MTR: received IM message " + matter.inspect(msg), 3)
|
||||
|
||||
var val = matter.TLV.parse(msg.raw, msg.app_payload_idx)
|
||||
|
||||
tasmota.log("MTR: IM TLV: " + str(val), 3)
|
||||
|
||||
var InteractionModelRevision = val.findsubval(0xFF)
|
||||
tasmota.log("MTR: InteractionModelRevision=" + (InteractionModelRevision != nil ? str(InteractionModelRevision) : "nil"), 3)
|
||||
|
||||
var opcode = msg.opcode
|
||||
if opcode == 0x01 # Status Response
|
||||
return self.process_status_response(msg, val, remote_ip, remote_port)
|
||||
elif opcode == 0x02 # Read Request
|
||||
return self.process_read_request(msg, val, remote_ip, remote_port)
|
||||
elif opcode == 0x03 # Subscribe Request
|
||||
return self.subscribe_request(msg, val, remote_ip, remote_port)
|
||||
elif opcode == 0x04 # Subscribe Response
|
||||
return self.subscribe_response(msg, val, remote_ip, remote_port)
|
||||
elif opcode == 0x05 # Report Data
|
||||
return self.report_data(msg, val, remote_ip, remote_port)
|
||||
elif opcode == 0x06 # Write Request
|
||||
return self.process_write_request(msg, val, remote_ip, remote_port)
|
||||
elif opcode == 0x07 # Write Response
|
||||
return self.process_write_response(msg, val, remote_ip, remote_port)
|
||||
elif opcode == 0x08 # Invoke Request
|
||||
return self.process_invoke_request(msg, val, remote_ip, remote_port)
|
||||
elif opcode == 0x09 # Invoke Response
|
||||
return self.process_invoke_response(msg, val, remote_ip, remote_port)
|
||||
elif opcode == 0x0A # Timed Request
|
||||
return self.process_timed_request(msg, val, remote_ip, remote_port)
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
#############################################################
|
||||
# process IM 0x01 Status Response
|
||||
#
|
||||
# val is the TLV structure
|
||||
# returns `true` if processed, `false` if silently ignored,
|
||||
# or raises an exception
|
||||
def process_status_response(msg, val, remote_ip, remote_port)
|
||||
import string
|
||||
var status = val.findsubval(0, 0xFF)
|
||||
tasmota.log(string.format("MTR: Status Response = 0x%02X", status), 3)
|
||||
return true
|
||||
end
|
||||
|
||||
#############################################################
|
||||
# process IM 0x02 Read Request
|
||||
#
|
||||
# val is the TLV structure
|
||||
# returns `true` if processed, `false` if silently ignored,
|
||||
# or raises an exception
|
||||
def process_read_request(msg, val, remote_ip, remote_port)
|
||||
# structure is `ReadRequestMessage` 10.6.2 p.558
|
||||
tasmota.log("MTR: IM:read_request processing start", 3)
|
||||
|
||||
var query = matter.ReadRequestMessage().from_TLV(val)
|
||||
if query.attributes_requests != nil
|
||||
# prepare the response
|
||||
var ret = matter.ReportDataMessage()
|
||||
ret.suppress_response = true
|
||||
ret.attribute_reports = []
|
||||
|
||||
# TODO - we need to implement Concrete path expansion here
|
||||
|
||||
for q:query.attributes_requests
|
||||
var attr_name = matter.get_attribute_name(q.cluster, q.attribute)
|
||||
tasmota.log("MTR: Read Attribute " + str(q) + (attr_name ? " (" + attr_name + ")" : ""), 2)
|
||||
var res = self.responder.device.read_attribute(msg, q.endpoint, q.cluster, q.attribute)
|
||||
if res != nil
|
||||
var a1 = matter.AttributeReportIB()
|
||||
# a1.attribute_status = matter.AttributeStatusIB()
|
||||
# a1.attribute_status.path = matter.AttributePathIB()
|
||||
# a1.attribute_status.status = matter.StatusIB()
|
||||
# a1.attribute_status.path.endpoint = 0
|
||||
# a1.attribute_status.path.cluster = q.cluster
|
||||
# a1.attribute_status.path.attribute = q.attribute
|
||||
# a1.attribute_status.status.status = matter.SUCCESS
|
||||
a1.attribute_data = matter.AttributeDataIB()
|
||||
a1.attribute_data.data_version = 1
|
||||
a1.attribute_data.path = matter.AttributePathIB()
|
||||
a1.attribute_data.path.endpoint = 0
|
||||
a1.attribute_data.path.cluster = q.cluster
|
||||
a1.attribute_data.path.attribute = q.attribute
|
||||
a1.attribute_data.data = res
|
||||
|
||||
ret.attribute_reports.push(a1)
|
||||
end
|
||||
end
|
||||
|
||||
tasmota.log("MTR: ReportDataMessage=" + str(ret), 3)
|
||||
tasmota.log("MTR: ReportDataMessageTLV=" + str(ret.to_TLV()), 3)
|
||||
|
||||
var resp = msg.build_response(0x05 #-Report Data-#, true)
|
||||
resp.encode(ret.to_TLV().encode()) # payload in cleartext
|
||||
resp.encrypt()
|
||||
|
||||
self.responder.send_response(resp.raw, remote_ip, remote_port, resp.message_counter)
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
#############################################################
|
||||
# process IM 0x08 Invoke Request
|
||||
#
|
||||
# val is the TLV structure
|
||||
# returns `true` if processed, `false` if silently ignored,
|
||||
# or raises an exception
|
||||
def process_invoke_request(msg, val, remote_ip, remote_port)
|
||||
import string
|
||||
# structure is `ReadRequestMessage` 10.6.2 p.558
|
||||
tasmota.log("MTR: IM:invoke_request processing start", 3)
|
||||
var ctx = matter.Response_container()
|
||||
|
||||
var query = matter.InvokeRequestMessage().from_TLV(val)
|
||||
if query.invoke_requests != nil
|
||||
# prepare the response
|
||||
var ret = matter.InvokeResponseMessage()
|
||||
ret.suppress_response = false
|
||||
ret.invoke_responses = []
|
||||
|
||||
for q:query.invoke_requests
|
||||
ctx.endpoint = q.command_path.endpoint
|
||||
ctx.cluster = q.command_path.cluster
|
||||
ctx.command = q.command_path.command
|
||||
ctx.status = matter.UNSUPPORTED_COMMAND #default error if returned `nil`
|
||||
|
||||
var cmd_name = matter.get_command_name(ctx.cluster, ctx.command)
|
||||
if cmd_name == nil cmd_name = string.format("0x%04X/0x02X", ctx.cluster, ctx.command) end
|
||||
tasmota.log(string.format("MTR: >Received_cmd %s from [%s]:%i", cmd_name, remote_ip, remote_port), 2)
|
||||
var res = self.responder.device.invoke_request(msg, q.command_fields, ctx)
|
||||
var a1 = matter.InvokeResponseIB()
|
||||
if res != nil
|
||||
a1.command = matter.CommandDataIB()
|
||||
a1.command.command_path = matter.CommandPathIB()
|
||||
a1.command.command_path.endpoint = ctx.endpoint
|
||||
a1.command.command_path.cluster = ctx.cluster
|
||||
a1.command.command_path.command = ctx.command
|
||||
a1.command.command_fields = res
|
||||
ret.invoke_responses.push(a1)
|
||||
|
||||
cmd_name = matter.get_command_name(ctx.cluster, ctx.command)
|
||||
if cmd_name == nil cmd_name = string.format("0x%04X/0x%02X", ctx.cluster, ctx.command) end
|
||||
tasmota.log(string.format("MTR: <Replied_cmd %s", cmd_name), 2)
|
||||
elif ctx.status != nil
|
||||
a1.status = matter.CommandStatusIB()
|
||||
a1.status.command_path = matter.CommandPathIB()
|
||||
a1.status.command_path.endpoint = ctx.endpoint
|
||||
a1.status.command_path.cluster = ctx.cluster
|
||||
a1.status.command_path.command = ctx.command
|
||||
a1.status.status = matter.StatusIB()
|
||||
a1.status.status.status = ctx.status
|
||||
ret.invoke_responses.push(a1)
|
||||
else
|
||||
# ignore if content is nil and status is undefined
|
||||
end
|
||||
end
|
||||
|
||||
tasmota.log("MTR: invoke_responses="+str(ret.invoke_responses), 3)
|
||||
if size(ret.invoke_responses) > 0
|
||||
tasmota.log("MTR: InvokeResponse=" + str(ret), 3)
|
||||
tasmota.log("MTR: InvokeResponseTLV=" + str(ret.to_TLV()), 3)
|
||||
|
||||
var resp = msg.build_response(0x09 #-Invoke Response-#, true)
|
||||
resp.encode(ret.to_TLV().encode()) # payload in cleartext
|
||||
resp.encrypt()
|
||||
|
||||
self.responder.send_response(resp.raw, remote_ip, remote_port, resp.message_counter)
|
||||
elif msg.x_flag_r # nothing to respond, check if we need a standalone ack
|
||||
var resp = msg.build_standalone_ack()
|
||||
resp.encode()
|
||||
resp.encrypt()
|
||||
# no ecnryption required for ACK
|
||||
self.responder.send_response(resp.raw, remote_ip, remote_port, resp.message_counter)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
#############################################################
|
||||
# process IM 0x03 Subscribe Request
|
||||
#
|
||||
def subscribe_request(msg, val, remote_ip, remote_port)
|
||||
import string
|
||||
var query = matter.SubscribeRequestMessage().from_TLV(val)
|
||||
tasmota.log("MTR: received SubscribeRequestMessage=" + str(query), 3)
|
||||
return false
|
||||
end
|
||||
|
||||
#############################################################
|
||||
# process IM 0x04 Subscribe Response
|
||||
#
|
||||
def subscribe_response(msg, val, remote_ip, remote_port)
|
||||
import string
|
||||
var query = matter.SubscribeResponseMessage().from_TLV(val)
|
||||
tasmota.log("MTR: received SubscribeResponsetMessage=" + str(query), 3)
|
||||
return false
|
||||
end
|
||||
|
||||
#############################################################
|
||||
# process IM 0x05 ReportData
|
||||
#
|
||||
def report_data(msg, val, remote_ip, remote_port)
|
||||
import string
|
||||
var query = matter.ReportDataMessage().from_TLV(val)
|
||||
tasmota.log("MTR: received ReportDataMessage=" + str(query), 3)
|
||||
return false
|
||||
end
|
||||
|
||||
#############################################################
|
||||
# process IM 0x06 Write Request
|
||||
#
|
||||
def process_write_request(msg, val, remote_ip, remote_port)
|
||||
import string
|
||||
var query = matter.WriteRequestMessage().from_TLV(val)
|
||||
tasmota.log("MTR: received WriteRequestMessage=" + str(query), 3)
|
||||
return false
|
||||
end
|
||||
|
||||
#############################################################
|
||||
# process IM 0x07 Write Response
|
||||
#
|
||||
def process_write_response(msg, val, remote_ip, remote_port)
|
||||
import string
|
||||
var query = matter.WriteResponseMessage().from_TLV(val)
|
||||
tasmota.log("MTR: received WriteResponseMessage=" + str(query), 3)
|
||||
return false
|
||||
end
|
||||
|
||||
#############################################################
|
||||
# process IM 0x09 Invoke Response
|
||||
#
|
||||
def process_invoke_response(msg, val, remote_ip, remote_port)
|
||||
import string
|
||||
var query = matter.InvokeResponseMessage().from_TLV(val)
|
||||
tasmota.log("MTR: received InvokeResponseMessage=" + str(query), 3)
|
||||
return false
|
||||
end
|
||||
|
||||
#############################################################
|
||||
# process IM 0x0A Timed Request
|
||||
#
|
||||
def process_timed_request(msg, val, remote_ip, remote_port)
|
||||
import string
|
||||
var query = matter.TimedRequestMessage().from_TLV(val)
|
||||
tasmota.log("MTR: received TimedRequestMessage=" + str(query), 3)
|
||||
|
||||
tasmota.log(string.format("MTR: >Received_IM TimedRequest=%i from [%s]:%i", query.timeout, remote_ip, remote_port), 2)
|
||||
|
||||
# Send success status report
|
||||
var sr = matter.StatusResponseMessage()
|
||||
sr.status = matter.SUCCESS
|
||||
var resp = msg.build_response(0x01 #-Status Response-#, true #-reliable-#)
|
||||
resp.encode(sr.to_TLV().encode()) # payload in cleartext
|
||||
resp.encrypt()
|
||||
self.responder.send_response(resp.raw, remote_ip, remote_port, resp.message_counter)
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
#############################################################
|
||||
# placeholder, nothing to run for now
|
||||
def every_second()
|
||||
end
|
||||
end
|
||||
matter.IM = Matter_IM
|
||||
|
||||
#-
|
||||
|
||||
# Unit tests
|
||||
|
||||
|
||||
-#
|
||||
|
946
lib/libesp32/berry_matter/src/embedded/Matter_IM_Data.be
Normal file
946
lib/libesp32/berry_matter/src/embedded/Matter_IM_Data.be
Normal file
@ -0,0 +1,946 @@
|
||||
#
|
||||
# Matter_IM_Data.be - suppport for Matter Interation Model messages structure
|
||||
#
|
||||
# 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/>.
|
||||
#
|
||||
|
||||
import matter
|
||||
|
||||
#@ solidify:Matter_IM_base,weak
|
||||
#@ solidify:Matter_IM_Message_base,weak
|
||||
|
||||
#@ solidify:matter.AttributePathIB,weak
|
||||
#@ solidify:matter.ClusterPathIB,weak
|
||||
#@ solidify:matter.DataVersionFilterIB,weak
|
||||
#@ solidify:matter.AttributeDataIB,weak
|
||||
#@ solidify:matter.AttributeReportIB,weak
|
||||
#@ solidify:matter.EventFilterIB,weak
|
||||
#@ solidify:matter.EventPathIB,weak
|
||||
#@ solidify:matter.EventDataIB,weak
|
||||
#@ solidify:matter.EventReportIB,weak
|
||||
#@ solidify:matter.CommandPathIB,weak
|
||||
#@ solidify:matter.CommandDataIB,weak
|
||||
#@ solidify:matter.InvokeResponseIB,weak
|
||||
#@ solidify:matter.CommandStatusIB,weak
|
||||
#@ solidify:matter.EventStatusIB,weak
|
||||
#@ solidify:matter.AttributeStatusIB,weak
|
||||
#@ solidify:matter.StatusIB,weak
|
||||
#@ solidify:matter.StatusResponseMessage,weak
|
||||
#@ solidify:matter.ReadRequestMessage,weak
|
||||
#@ solidify:matter.ReportDataMessage,weak
|
||||
#@ solidify:matter.SubscribeRequestMessage,weak
|
||||
#@ solidify:matter.SubscribeResponseMessage,weak
|
||||
#@ solidify:matter.WriteRequestMessage,weak
|
||||
#@ solidify:matter.WriteResponseMessage,weak
|
||||
#@ solidify:matter.TimedRequestMessage,weak
|
||||
#@ solidify:matter.InvokeRequestMessage,weak
|
||||
#@ solidify:matter.InvokeResponseMessage,weak
|
||||
|
||||
#################################################################################
|
||||
# Base class for all IM containers
|
||||
#################################################################################
|
||||
class Matter_IM_base
|
||||
def tostring()
|
||||
return "<" + classname(self) + ":" + matter.inspect(self) + ">"
|
||||
end
|
||||
|
||||
# arr: array (list) of TLV values
|
||||
# cl: class for the TLV decoder
|
||||
def from_TLV_array(arr, cl)
|
||||
if arr == nil return nil end
|
||||
var r = []
|
||||
for v:arr
|
||||
r.push(cl().from_TLV(v))
|
||||
end
|
||||
return r
|
||||
end
|
||||
|
||||
# add an array of objects to TLV
|
||||
# s: current container to add to
|
||||
# tag: tag for the array (inner items don't have tags)
|
||||
# arr: the array of objects supporting `to_TLV()`
|
||||
#
|
||||
# if arr is `nil`, nothing happens
|
||||
def to_TLV_array(s, tag, arr)
|
||||
if arr == nil return nil end
|
||||
var l = s.add_array(tag) # create the list container and add to the current container
|
||||
for v:arr
|
||||
l.add_obj(nil, v)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
#################################################################################
|
||||
# Matter_AttributePathIB class
|
||||
#################################################################################
|
||||
class Matter_AttributePathIB : Matter_IM_base
|
||||
var tag_compression # false if none
|
||||
var node # u64 as bytes
|
||||
var endpoint # u16
|
||||
var cluster # u32
|
||||
var attribute # u32
|
||||
var list_index # ?
|
||||
|
||||
def tostring()
|
||||
try
|
||||
import string
|
||||
var s = ""
|
||||
if self.node s += string.format("node=%s ", self.node) end
|
||||
s += (self.endpoint != nil ? string.format("[%02X]", self.endpoint) : "[**]")
|
||||
s += (self.cluster != nil ? string.format("%04X/", self.cluster) : "****/")
|
||||
s += (self.attribute != nil ? string.format("%04X", self.attribute) : "****")
|
||||
return s
|
||||
except .. as e, m
|
||||
return "Exception> " + str(e) + ", " + str(m)
|
||||
end
|
||||
end
|
||||
|
||||
# decode from TLV
|
||||
def from_TLV(val)
|
||||
if val == nil return nil end
|
||||
self.tag_compression = val.findsubval(0)
|
||||
self.node = val.findsubval(1)
|
||||
self.endpoint = val.findsubval(2)
|
||||
self.cluster = val.findsubval(3)
|
||||
self.attribute = val.findsubval(4)
|
||||
self.list_index = val.findsubval(5)
|
||||
return self
|
||||
end
|
||||
|
||||
def to_TLV()
|
||||
var TLV = matter.TLV
|
||||
var s = TLV.Matter_TLV_list()
|
||||
s.add_TLV(0, TLV.BOOL, self.tag_compression)
|
||||
s.add_TLV(1, TLV.U8, self.node)
|
||||
s.add_TLV(2, TLV.U2, self.endpoint)
|
||||
s.add_TLV(3, TLV.U4, self.cluster)
|
||||
s.add_TLV(4, TLV.U4, self.attribute)
|
||||
s.add_TLV(5, TLV.U2, self.list_index)
|
||||
return s
|
||||
end
|
||||
end
|
||||
matter.AttributePathIB = Matter_AttributePathIB
|
||||
|
||||
|
||||
#################################################################################
|
||||
# ClusterPathIB class
|
||||
#################################################################################
|
||||
class Matter_ClusterPathIB : Matter_IM_base
|
||||
var node # u64 as bytes
|
||||
var endpoint # u16
|
||||
var cluster # u32
|
||||
|
||||
# decode from TLV
|
||||
def from_TLV(val)
|
||||
if val == nil return nil end
|
||||
self.node = val.findsubval(0)
|
||||
self.endpoint = val.findsubval(1)
|
||||
self.cluster = val.findsubval(2)
|
||||
return self
|
||||
end
|
||||
|
||||
def to_TLV()
|
||||
var TLV = matter.TLV
|
||||
var s = TLV.Matter_TLV_list()
|
||||
s.add_TLV(0, TLV.U8, self.node)
|
||||
s.add_TLV(1, TLV.U2, self.endpoint)
|
||||
s.add_TLV(2, TLV.U4, self.cluster)
|
||||
return s
|
||||
end
|
||||
end
|
||||
matter.ClusterPathIB = Matter_ClusterPathIB
|
||||
|
||||
#################################################################################
|
||||
# DataVersionFilterIB class
|
||||
#################################################################################
|
||||
class Matter_DataVersionFilterIB : Matter_IM_base
|
||||
var path # false if none
|
||||
var data_version # u64 as bytes
|
||||
|
||||
# decode from TLV
|
||||
def from_TLV(val)
|
||||
if val == nil return nil end
|
||||
self.path = matter.ClusterPathIB().from_TLV(val.findsub(0))
|
||||
self.data_version = val.findsubval(1) # u32
|
||||
return self
|
||||
end
|
||||
|
||||
def to_TLV()
|
||||
var TLV = matter.TLV
|
||||
var s = TLV.Matter_TLV_struct()
|
||||
s.add_obj(0, self.path)
|
||||
s.add_TLV(1, TLV.U4, self.data_version)
|
||||
return s
|
||||
end
|
||||
end
|
||||
matter.DataVersionFilterIB = Matter_DataVersionFilterIB
|
||||
|
||||
#################################################################################
|
||||
# AttributeDataIB class
|
||||
#################################################################################
|
||||
class Matter_AttributeDataIB : Matter_IM_base
|
||||
var data_version # u32
|
||||
var path # AttributePathIB
|
||||
var data # any TLV
|
||||
|
||||
# decode from TLV
|
||||
def from_TLV(val)
|
||||
if val == nil return nil end
|
||||
self.data_version = val.findsubval(0) # u32
|
||||
self.path = matter.AttributePathIB().from_TLV(val.findsub(1))
|
||||
self.data = val.findsubval(2) # any
|
||||
return self
|
||||
end
|
||||
|
||||
def to_TLV()
|
||||
var TLV = matter.TLV
|
||||
var s = TLV.Matter_TLV_struct()
|
||||
s.add_TLV(0, TLV.U4, self.data_version)
|
||||
s.add_obj(1, self.path)
|
||||
s.add_obj(2, self.data)
|
||||
return s
|
||||
end
|
||||
end
|
||||
matter.AttributeDataIB = Matter_AttributeDataIB
|
||||
|
||||
#################################################################################
|
||||
# AttributeReportIB class
|
||||
#################################################################################
|
||||
class Matter_AttributeReportIB : Matter_IM_base
|
||||
var attribute_status # AttributeStatusIB
|
||||
var attribute_data # AttributeDataIB
|
||||
|
||||
# decode from TLV
|
||||
def from_TLV(val)
|
||||
if val == nil return nil end
|
||||
self.attribute_status = matter.AttributeStatusIB().from_TLV(val.findsub(0))
|
||||
self.attribute_data = matter.AttributeDataIB().from_TLV(val.findsub(1))
|
||||
return self
|
||||
end
|
||||
|
||||
def to_TLV()
|
||||
var TLV = matter.TLV
|
||||
var s = TLV.Matter_TLV_struct()
|
||||
s.add_obj(0, self.attribute_status)
|
||||
s.add_obj(1, self.attribute_data)
|
||||
return s
|
||||
end
|
||||
end
|
||||
matter.AttributeReportIB = Matter_AttributeReportIB
|
||||
|
||||
#################################################################################
|
||||
# EventFilterIB class
|
||||
#################################################################################
|
||||
class Matter_EventFilterIB : Matter_IM_base
|
||||
var node # u64
|
||||
var event_min # u64
|
||||
|
||||
# decode from TLV
|
||||
def from_TLV(val)
|
||||
if val == nil return nil end
|
||||
self.node = val.findsubval(0)
|
||||
self.event_min = val.findsubval(1)
|
||||
return self
|
||||
end
|
||||
|
||||
def to_TLV()
|
||||
var TLV = matter.TLV
|
||||
var s = TLV.Matter_TLV_struct()
|
||||
s.add_TLV(0, TLV.U8, self.node)
|
||||
s.add_TLV(1, TLV.U8, self.event_min)
|
||||
return s
|
||||
end
|
||||
end
|
||||
matter.EventFilterIB = Matter_EventFilterIB
|
||||
|
||||
#################################################################################
|
||||
# EventPathIB class
|
||||
#################################################################################
|
||||
class Matter_EventPathIB : Matter_IM_base
|
||||
var node # u64 as bytes
|
||||
var endpoint # u16
|
||||
var cluster # u32
|
||||
var event # u32
|
||||
var is_urgent # bool
|
||||
|
||||
# decode from TLV
|
||||
def from_TLV(val)
|
||||
if val == nil return nil end
|
||||
self.node = val.findsubval(0)
|
||||
self.endpoint = val.findsubval(1)
|
||||
self.cluster = val.findsubval(2)
|
||||
self.event = val.findsubval(3)
|
||||
self.is_urgent = val.findsubval(4)
|
||||
return self
|
||||
end
|
||||
|
||||
def to_TLV(s)
|
||||
var TLV = matter.TLV
|
||||
if s == nil s = TLV.Matter_TLV_list() end
|
||||
s.add_TLV(0, TLV.U8, self.node)
|
||||
s.add_TLV(1, TLV.U2, self.endpoint)
|
||||
s.add_TLV(2, TLV.U4, self.cluster)
|
||||
s.add_TLV(3, TLV.U4, self.event)
|
||||
s.add_TLV(4, TLV.BOOL, self.is_urgent)
|
||||
return s
|
||||
end
|
||||
end
|
||||
matter.EventPathIB = Matter_EventPathIB
|
||||
|
||||
|
||||
#################################################################################
|
||||
# EventDataIB class
|
||||
#################################################################################
|
||||
class Matter_EventDataIB : Matter_IM_base
|
||||
var path #
|
||||
var event_number # u64 as bytes
|
||||
var priority # u8
|
||||
# one of
|
||||
var epoch_timestamp # u64
|
||||
var system_timestamp # u64
|
||||
var delta_epoch_timestamp # u64
|
||||
var delta_system_timestamp # u64
|
||||
# data
|
||||
var data # any TLV
|
||||
|
||||
# decode from TLV
|
||||
def from_TLV(val)
|
||||
if val == nil return nil end
|
||||
self.path = matter.EventPathIB().from_TLV(val.findsub(0))
|
||||
self.event_number = val.findsubval(1) # u64
|
||||
self.priority = val.findsubval(2) # u64
|
||||
self.epoch_timestamp = val.findsubval(3) # u64
|
||||
self.system_timestamp = val.findsubval(4) # u64
|
||||
self.delta_epoch_timestamp = val.findsubval(5) # u64
|
||||
self.delta_system_timestamp = val.findsubval(6) # u64
|
||||
self.data = val.findsubval(7) # any
|
||||
return self
|
||||
end
|
||||
|
||||
def to_TLV(s)
|
||||
var TLV = matter.TLV
|
||||
if s == nil s = TLV.Matter_TLV_struct() end
|
||||
if self.path
|
||||
self.path.to_TLV(s.add_list(0))
|
||||
end
|
||||
s.add_TLV(1, TLV.U8, self.event_number)
|
||||
s.add_TLV(2, TLV.U1, self.priority)
|
||||
s.add_TLV(3, TLV.U8, self.epoch_timestamp)
|
||||
s.add_TLV(4, TLV.U8, self.system_timestamp)
|
||||
s.add_TLV(5, TLV.U8, self.delta_epoch_timestamp)
|
||||
s.add_TLV(6, TLV.U8, self.delta_system_timestamp)
|
||||
s.add_obj(7, self.data)
|
||||
return s
|
||||
end
|
||||
end
|
||||
matter.EventDataIB = Matter_EventDataIB
|
||||
|
||||
|
||||
#################################################################################
|
||||
# EventReportIB class
|
||||
#################################################################################
|
||||
class Matter_EventReportIB : Matter_IM_base
|
||||
var event_status # EventStatusIB
|
||||
var event_data # EventDataIB
|
||||
|
||||
# decode from TLV
|
||||
def from_TLV(val)
|
||||
if val == nil return nil end
|
||||
self.event_status = matter.EventStatusIB().from_TLV(val.findsub(0))
|
||||
self.event_data = matter.EventDataIB().from_TLV(val.findsub(1))
|
||||
return self
|
||||
end
|
||||
|
||||
def to_TLV()
|
||||
var TLV = matter.TLV
|
||||
var s = TLV.Matter_TLV_struct()
|
||||
s.add_obj(0, self.event_status)
|
||||
s.add_obj(1, self.event_data)
|
||||
return s
|
||||
end
|
||||
end
|
||||
matter.EventReportIB = Matter_EventReportIB
|
||||
|
||||
#################################################################################
|
||||
# CommandPathIB class
|
||||
#################################################################################
|
||||
class Matter_CommandPathIB : Matter_IM_base
|
||||
var endpoint # u16
|
||||
var cluster # u32
|
||||
var command # u32
|
||||
|
||||
# decode from TLV
|
||||
def from_TLV(val)
|
||||
if val == nil return nil end
|
||||
self.endpoint = val.findsubval(0)
|
||||
self.cluster = val.findsubval(1)
|
||||
self.command = val.findsubval(2)
|
||||
return self
|
||||
end
|
||||
|
||||
def to_TLV()
|
||||
var TLV = matter.TLV
|
||||
var s = TLV.Matter_TLV_list()
|
||||
s.add_TLV(0, TLV.U2, self.endpoint)
|
||||
s.add_TLV(1, TLV.U4, self.cluster)
|
||||
s.add_TLV(2, TLV.U4, self.command)
|
||||
return s
|
||||
end
|
||||
end
|
||||
matter.CommandPathIB = Matter_CommandPathIB
|
||||
|
||||
#################################################################################
|
||||
# CommandDataIB class
|
||||
#################################################################################
|
||||
class Matter_CommandDataIB : Matter_IM_base
|
||||
var command_path # CommandPathIB
|
||||
var command_fields # any
|
||||
|
||||
# decode from TLV
|
||||
def from_TLV(val)
|
||||
if val == nil return nil end
|
||||
self.command_path = matter.CommandPathIB().from_TLV(val.findsub(0))
|
||||
self.command_fields = val.findsub(1)
|
||||
return self
|
||||
end
|
||||
|
||||
def to_TLV()
|
||||
var TLV = matter.TLV
|
||||
var s = TLV.Matter_TLV_struct()
|
||||
s.add_obj(0, self.command_path)
|
||||
s.add_obj(1, self.command_fields)
|
||||
return s
|
||||
end
|
||||
end
|
||||
matter.CommandDataIB = Matter_CommandDataIB
|
||||
|
||||
|
||||
#################################################################################
|
||||
# InvokeResponseIB class
|
||||
#################################################################################
|
||||
class Matter_InvokeResponseIB : Matter_IM_base
|
||||
var command # CommandDataIB
|
||||
var status # CommandStatusIB
|
||||
|
||||
# decode from TLV
|
||||
def from_TLV(val)
|
||||
if val == nil return nil end
|
||||
self.command = matter.CommandDataIB().from_TLV(val.findsub(0))
|
||||
self.status = matter.CommandStatusIB().from_TLV(val.findsub(1))
|
||||
return self
|
||||
end
|
||||
|
||||
def to_TLV()
|
||||
var TLV = matter.TLV
|
||||
var s = TLV.Matter_TLV_struct()
|
||||
s.add_obj(0, self.command)
|
||||
s.add_obj(1, self.status)
|
||||
return s
|
||||
end
|
||||
end
|
||||
matter.InvokeResponseIB = Matter_InvokeResponseIB
|
||||
|
||||
|
||||
#################################################################################
|
||||
# CommandStatusIB class
|
||||
#################################################################################
|
||||
class Matter_CommandStatusIB : Matter_IM_base
|
||||
var command_path # CommandPathIB
|
||||
var status # StatusIB
|
||||
|
||||
# decode from TLV
|
||||
def from_TLV(val)
|
||||
if val == nil return nil end
|
||||
self.command_path = matter.CommandPathIB().from_TLV(val.findsub(0))
|
||||
self.status = matter.StatusIB().from_TLV(val.findsub(1))
|
||||
return self
|
||||
end
|
||||
|
||||
def to_TLV()
|
||||
var TLV = matter.TLV
|
||||
var s = TLV.Matter_TLV_struct()
|
||||
s.add_obj(0, self.command_path)
|
||||
s.add_obj(1, self.status)
|
||||
return s
|
||||
end
|
||||
end
|
||||
matter.CommandStatusIB = Matter_CommandStatusIB
|
||||
|
||||
#################################################################################
|
||||
# EventStatusIB class
|
||||
#################################################################################
|
||||
class Matter_EventStatusIB : Matter_IM_base
|
||||
var path # EventPathIB
|
||||
var status # StatusIB
|
||||
|
||||
# decode from TLV
|
||||
def from_TLV(val)
|
||||
if val == nil return nil end
|
||||
self.path = matter.EventPathIB().from_TLV(val.findsub(0))
|
||||
self.status = matter.StatusIB().from_TLV(val.findsub(1))
|
||||
return self
|
||||
end
|
||||
|
||||
def to_TLV()
|
||||
var TLV = matter.TLV
|
||||
var s = TLV.Matter_TLV_struct()
|
||||
s.add_obj(0, self.path)
|
||||
s.add_obj(1, self.status)
|
||||
return s
|
||||
end
|
||||
end
|
||||
matter.EventStatusIB = Matter_EventStatusIB
|
||||
|
||||
#################################################################################
|
||||
# AttributeStatusIB class
|
||||
#################################################################################
|
||||
class Matter_AttributeStatusIB : Matter_IM_base
|
||||
var path # AttributePathIB
|
||||
var status # StatusIB
|
||||
|
||||
# decode from TLV
|
||||
def from_TLV(val)
|
||||
if val == nil return nil end
|
||||
self.path = matter.AttributePathIB().from_TLV(val.findsub(0))
|
||||
self.status = matter.StatusIB().from_TLV(val.findsub(1))
|
||||
return self
|
||||
end
|
||||
|
||||
def to_TLV()
|
||||
var TLV = matter.TLV
|
||||
var s = TLV.Matter_TLV_struct()
|
||||
s.add_obj(0, self.path)
|
||||
s.add_obj(1, self.status)
|
||||
return s
|
||||
end
|
||||
end
|
||||
matter.AttributeStatusIB = Matter_AttributeStatusIB
|
||||
|
||||
#################################################################################
|
||||
# StatusIB class
|
||||
#################################################################################
|
||||
class Matter_StatusIB : Matter_IM_base
|
||||
var status # u16
|
||||
var cluster_status # u16
|
||||
|
||||
# decode from TLV
|
||||
def from_TLV(val)
|
||||
if val == nil return nil end
|
||||
self.status = val.findsubval(0)
|
||||
self.cluster_status = val.findsubval(1)
|
||||
return self
|
||||
end
|
||||
|
||||
def to_TLV()
|
||||
var TLV = matter.TLV
|
||||
var s = TLV.Matter_TLV_list()
|
||||
s.add_TLV(0, TLV.U2, self.status)
|
||||
s.add_TLV(1, TLV.U2, self.cluster_status)
|
||||
return s
|
||||
end
|
||||
end
|
||||
matter.StatusIB = Matter_StatusIB
|
||||
|
||||
#################################################################################
|
||||
#################################################################################
|
||||
# Matter_IM_Message_base class
|
||||
#
|
||||
# This is the superclass for all high-level messages
|
||||
#################################################################################
|
||||
#################################################################################
|
||||
class Matter_IM_Message_base : Matter_IM_base
|
||||
var InteractionModelRevision # 0xFF
|
||||
|
||||
def init()
|
||||
self.InteractionModelRevision = 1
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
#################################################################################
|
||||
# StatusResponseMessage class
|
||||
#################################################################################
|
||||
class Matter_StatusResponseMessage : Matter_IM_Message_base
|
||||
var status # u32
|
||||
|
||||
# decode from TLV
|
||||
def from_TLV(val)
|
||||
if val == nil return nil end
|
||||
self.status = val.findsubval(0)
|
||||
return self
|
||||
end
|
||||
|
||||
def to_TLV()
|
||||
var TLV = matter.TLV
|
||||
var s = TLV.Matter_TLV_struct()
|
||||
s.add_TLV(0, TLV.U4, self.status)
|
||||
s.add_TLV(0xFF, TLV.U1, self.InteractionModelRevision)
|
||||
return s
|
||||
end
|
||||
end
|
||||
matter.StatusResponseMessage = Matter_StatusResponseMessage
|
||||
|
||||
#################################################################################
|
||||
# ReadRequestMessage class
|
||||
#################################################################################
|
||||
class Matter_ReadRequestMessage : Matter_IM_Message_base
|
||||
var attributes_requests # array of AttributePathIB
|
||||
var event_requests # array of EventPathIB
|
||||
var event_filters # array of EventFilterIB
|
||||
var fabric_filtered # bool
|
||||
var data_version_filters # array of DataVersionFilterIB
|
||||
|
||||
# decode from TLV
|
||||
def from_TLV(val)
|
||||
if val == nil return nil end
|
||||
self.attributes_requests = self.from_TLV_array(val.findsubval(0), matter.AttributePathIB)
|
||||
self.event_requests = self.from_TLV_array(val.findsubval(1), matter.EventPathIB)
|
||||
self.event_filters = self.from_TLV_array(val.findsubval(2), matter.EventFilterIB)
|
||||
self.fabric_filtered = val.findsubval(3)
|
||||
self.data_version_filters = self.from_TLV_array(val.findsubval(4), matter.DataVersionFilterIB)
|
||||
return self
|
||||
end
|
||||
|
||||
def to_TLV()
|
||||
var TLV = matter.TLV
|
||||
var s = TLV.Matter_TLV_struct()
|
||||
self.to_TLV_array(s, 0, self.attributes_requests)
|
||||
self.to_TLV_array(s, 1, self.event_requests)
|
||||
self.to_TLV_array(s, 2, self.event_filters)
|
||||
s.add_TLV(3, TLV.BOOL, self.fabric_filtered)
|
||||
self.to_TLV_array(s, 4, self.data_version_filters)
|
||||
s.add_TLV(0xFF, TLV.U1, self.InteractionModelRevision)
|
||||
return s
|
||||
end
|
||||
end
|
||||
matter.ReadRequestMessage = Matter_ReadRequestMessage
|
||||
|
||||
#################################################################################
|
||||
# ReportDataMessage class
|
||||
#################################################################################
|
||||
class Matter_ReportDataMessage : Matter_IM_Message_base
|
||||
var subscription_id # u32
|
||||
var attribute_reports # array of AttributeReportIB
|
||||
var event_reports # array of EventReportIB
|
||||
var more_chunked_messages # bool
|
||||
var suppress_response # bool
|
||||
|
||||
# decode from TLV
|
||||
def from_TLV(val)
|
||||
if val == nil return nil end
|
||||
self.subscription_id = val.findsubval(0)
|
||||
self.attribute_reports = self.from_TLV_array(val.findsubval(1), matter.AttributeReportIB)
|
||||
self.event_reports = self.from_TLV_array(val.findsubval(2), matter.EventReportIB)
|
||||
self.more_chunked_messages = val.findsubval(3)
|
||||
self.suppress_response = val.findsubval(4)
|
||||
return self
|
||||
end
|
||||
|
||||
def to_TLV()
|
||||
var TLV = matter.TLV
|
||||
var s = TLV.Matter_TLV_struct()
|
||||
s.add_TLV(0, TLV.U4, self.subscription_id)
|
||||
self.to_TLV_array(s, 1, self.attribute_reports)
|
||||
self.to_TLV_array(s, 2, self.event_reports)
|
||||
s.add_TLV(3, TLV.BOOL, self.more_chunked_messages)
|
||||
s.add_TLV(4, TLV.BOOL, self.suppress_response)
|
||||
s.add_TLV(0xFF, TLV.U1, self.InteractionModelRevision)
|
||||
return s
|
||||
end
|
||||
end
|
||||
matter.ReportDataMessage = Matter_ReportDataMessage
|
||||
|
||||
#################################################################################
|
||||
# SubscribeRequestMessage class
|
||||
#################################################################################
|
||||
class Matter_SubscribeRequestMessage : Matter_IM_Message_base
|
||||
var keep_subscriptions # bool
|
||||
var min_interval_floor # u16
|
||||
var max_interval_ceiling # u16
|
||||
var attribute_requests # array of AttributePathIB
|
||||
var event_requests # array of EventPathIB
|
||||
var event_filters # array of EventFilterIB
|
||||
var fabric_filtered # bool
|
||||
var data_version_filters # array of DataVersionFilterIB
|
||||
|
||||
# decode from TLV
|
||||
def from_TLV(val)
|
||||
if val == nil return nil end
|
||||
self.keep_subscriptions = val.findsubval(0)
|
||||
self.min_interval_floor = val.findsubval(1)
|
||||
self.max_interval_ceiling = val.findsubval(2)
|
||||
self.attribute_requests = self.from_TLV_array(val.findsubval(3), matter.AttributePathIB)
|
||||
self.event_requests = self.from_TLV_array(val.findsubval(4), matter.EventPathIB)
|
||||
self.event_filters = self.from_TLV_array(val.findsubval(5), matter.EventFilterIB)
|
||||
self.fabric_filtered = val.findsubval(7)
|
||||
self.data_version_filters = self.from_TLV_array(val.findsubval(8), matter.DataVersionFilterIB)
|
||||
return self
|
||||
end
|
||||
|
||||
def to_TLV()
|
||||
var TLV = matter.TLV
|
||||
var s = TLV.Matter_TLV_struct()
|
||||
s.add_TLV(0, TLV.BOOL, self.keep_subscriptions)
|
||||
s.add_TLV(1, TLV.U2, self.min_interval_floor)
|
||||
s.add_TLV(2, TLV.U2, self.max_interval_ceiling)
|
||||
self.to_TLV_array(s, 3, self.attribute_requests)
|
||||
self.to_TLV_array(s, 4, self.event_requests)
|
||||
self.to_TLV_array(s, 5, self.event_filters)
|
||||
s.add_TLV(7, TLV.BOOL, self.fabric_filtered)
|
||||
self.to_TLV_array(s, 8, self.data_version_filters)
|
||||
s.add_TLV(0xFF, TLV.U1, self.InteractionModelRevision)
|
||||
return s
|
||||
end
|
||||
end
|
||||
matter.SubscribeRequestMessage = Matter_SubscribeRequestMessage
|
||||
|
||||
#################################################################################
|
||||
# SubscribeResponseMessage class
|
||||
#################################################################################
|
||||
class Matter_SubscribeResponseMessage : Matter_IM_Message_base
|
||||
var subscription_id # u32
|
||||
var max_interval # u16
|
||||
|
||||
# decode from TLV
|
||||
def from_TLV(val)
|
||||
if val == nil return nil end
|
||||
self.subscription_id = val.findsubval(0)
|
||||
self.max_interval = val.findsubval(2)
|
||||
return self
|
||||
end
|
||||
|
||||
def to_TLV()
|
||||
var TLV = matter.TLV
|
||||
var s = TLV.Matter_TLV_struct()
|
||||
s.add_TLV(0, TLV.U4, self.subscription_id)
|
||||
s.add_TLV(2, TLV.U2, self.max_interval)
|
||||
s.add_TLV(0xFF, TLV.U1, self.InteractionModelRevision)
|
||||
return s
|
||||
end
|
||||
end
|
||||
matter.SubscribeResponseMessage = Matter_SubscribeResponseMessage
|
||||
|
||||
#################################################################################
|
||||
# WriteRequestMessage class
|
||||
#################################################################################
|
||||
class Matter_WriteRequestMessage : Matter_IM_Message_base
|
||||
var suppress_response # bool
|
||||
var timed_request # bool
|
||||
var write_requests # array of AttributeDataIB
|
||||
var more_chunked_messages # bool
|
||||
|
||||
# decode from TLV
|
||||
def from_TLV(val)
|
||||
if val == nil return nil end
|
||||
self.suppress_response = val.findsubval(0)
|
||||
self.timed_request = val.findsubval(1)
|
||||
self.write_requests = self.from_TLV_array(val.findsubval(2), matter.AttributeDataIB)
|
||||
self.more_chunked_messages = val.findsubval(3)
|
||||
return self
|
||||
end
|
||||
|
||||
def to_TLV()
|
||||
var TLV = matter.TLV
|
||||
var s = TLV.Matter_TLV_struct()
|
||||
s.add_TLV(0, TLV.BOOL, self.suppress_response)
|
||||
s.add_TLV(1, TLV.BOOL, self.timed_request)
|
||||
self.to_TLV_array(s, 2, self.write_requests)
|
||||
s.add_TLV(3, TLV.BOOL, self.more_chunked_messages)
|
||||
s.add_TLV(0xFF, TLV.U1, self.InteractionModelRevision)
|
||||
return s
|
||||
end
|
||||
end
|
||||
matter.WriteRequestMessage = Matter_WriteRequestMessage
|
||||
|
||||
#################################################################################
|
||||
# WriteResponseMessage class
|
||||
#################################################################################
|
||||
class Matter_WriteResponseMessage : Matter_IM_Message_base
|
||||
var write_responses # array of AttributeStatusIB
|
||||
|
||||
# decode from TLV
|
||||
def from_TLV(val)
|
||||
if val == nil return nil end
|
||||
self.write_requests = self.from_TLV_array(val.findsubval(0), matter.AttributeStatusIB)
|
||||
return self
|
||||
end
|
||||
|
||||
def to_TLV()
|
||||
var TLV = matter.TLV
|
||||
var s = TLV.Matter_TLV_struct()
|
||||
self.to_TLV_array(s, 0, self.write_responses)
|
||||
s.add_TLV(0xFF, TLV.U1, self.InteractionModelRevision)
|
||||
return s
|
||||
end
|
||||
end
|
||||
matter.WriteResponseMessage = Matter_WriteResponseMessage
|
||||
|
||||
#################################################################################
|
||||
# TimedRequestMessage class
|
||||
#################################################################################
|
||||
class Matter_TimedRequestMessage : Matter_IM_Message_base
|
||||
var timeout # u16
|
||||
|
||||
# decode from TLV
|
||||
def from_TLV(val)
|
||||
if val == nil return nil end
|
||||
self.timeout = val.findsubval(0)
|
||||
return self
|
||||
end
|
||||
|
||||
def to_TLV()
|
||||
var TLV = matter.TLV
|
||||
var s = TLV.Matter_TLV_struct()
|
||||
s.add_TLV(0, TLV.U2, self.timeout)
|
||||
s.add_TLV(0xFF, TLV.U1, self.InteractionModelRevision)
|
||||
return s
|
||||
end
|
||||
end
|
||||
matter.TimedRequestMessage = Matter_TimedRequestMessage
|
||||
|
||||
#################################################################################
|
||||
# InvokeRequestMessage class
|
||||
#################################################################################
|
||||
class Matter_InvokeRequestMessage : Matter_IM_Message_base
|
||||
var suppress_response # bool
|
||||
var timed_request # bool
|
||||
var invoke_requests # array of CommandDataIB
|
||||
|
||||
# decode from TLV
|
||||
def from_TLV(val)
|
||||
if val == nil return nil end
|
||||
self.suppress_response = val.findsubval(0)
|
||||
self.timed_request = val.findsubval(1)
|
||||
self.invoke_requests = self.from_TLV_array(val.findsubval(2), matter.CommandDataIB)
|
||||
return self
|
||||
end
|
||||
|
||||
def to_TLV()
|
||||
var TLV = matter.TLV
|
||||
var s = TLV.Matter_TLV_struct()
|
||||
s.add_TLV(0, TLV.BOOL, self.suppress_response)
|
||||
s.add_TLV(1, TLV.BOOL, self.timed_request)
|
||||
self.to_TLV_array(s, 2, self.invoke_requests)
|
||||
s.add_TLV(0xFF, TLV.U1, self.InteractionModelRevision)
|
||||
return s
|
||||
end
|
||||
end
|
||||
matter.InvokeRequestMessage = Matter_InvokeRequestMessage
|
||||
|
||||
#################################################################################
|
||||
# InvokeResponseMessage class
|
||||
#################################################################################
|
||||
class Matter_InvokeResponseMessage : Matter_IM_Message_base
|
||||
var suppress_response # bool
|
||||
var invoke_responses # array of InvokeResponseIB
|
||||
|
||||
# decode from TLV
|
||||
def from_TLV(val)
|
||||
if val == nil return nil end
|
||||
self.suppress_response = val.findsubval(0)
|
||||
self.invoke_responses = self.from_TLV_array(val.findsubval(1), matter.InvokeResponseIB)
|
||||
return self
|
||||
end
|
||||
|
||||
def to_TLV()
|
||||
var TLV = matter.TLV
|
||||
var s = TLV.Matter_TLV_struct()
|
||||
s.add_TLV(0, TLV.BOOL, self.suppress_response)
|
||||
self.to_TLV_array(s, 1, self.invoke_responses)
|
||||
s.add_TLV(0xFF, TLV.U1, self.InteractionModelRevision)
|
||||
return s
|
||||
end
|
||||
end
|
||||
matter.InvokeResponseMessage = Matter_InvokeResponseMessage
|
||||
|
||||
|
||||
#-
|
||||
|
||||
# Unit tests
|
||||
|
||||
import matter
|
||||
|
||||
m = matter.TLV.parse(bytes("1724020024033024040018"))
|
||||
assert(m.tostring() == "[[2 = 0U, 3 = 48U, 4 = 0U]]")
|
||||
#a = matter.IM.AttributePathIB().from_TLV(m)
|
||||
a = matter.AttributePathIB().from_TLV(m)
|
||||
assert(str(a) == "[00]0030/0000")
|
||||
m = a.to_TLV()
|
||||
assert(m.tostring() == "[[2 = 0U, 3 = 48U, 4 = 0U]]")
|
||||
assert(m.encode() == bytes("1724020024033024040018"))
|
||||
|
||||
|
||||
# create DataVersionFilterIB from scratch
|
||||
c = matter.ClusterPathIB()
|
||||
c.endpoint = 1
|
||||
c.cluster = 32
|
||||
c.to_TLV()
|
||||
assert(str(c.to_TLV()) == "[[1 = 1U, 2 = 32U]]")
|
||||
|
||||
d = matter.DataVersionFilterIB()
|
||||
d.path = c
|
||||
d.data_version = 10
|
||||
assert(str(d.to_TLV()) == '{0 = [[1 = 1U, 2 = 32U]], 1 = 10U}')
|
||||
assert(d.to_TLV().encode() == bytes('1537002401012402201824010A18'))
|
||||
|
||||
# decode DataVersionFilterIB from scratch
|
||||
m = matter.TLV.parse(bytes("1537002401012402201824010A18"))
|
||||
assert(str(m) == '{0 = [[1 = 1U, 2 = 32U]], 1 = 10U}')
|
||||
|
||||
# ReadRequestMessage
|
||||
m = matter.TLV.parse(bytes("153600172403312504FCFF18172402002403302404001817240200240330240401181724020024033024040218172402002403302404031817240200240328240402181724020024032824040418172403312404031818280324FF0118"))
|
||||
assert(str(m) == "{0 = [[[3 = 49U, 4 = 65532U]], [[2 = 0U, 3 = 48U, 4 = 0U]], [[2 = 0U, 3 = 48U, 4 = 1U]], [[2 = 0U, 3 = 48U, 4 = 2U]], [[2 = 0U, 3 = 48U, 4 = 3U]], [[2 = 0U, 3 = 40U, 4 = 2U]], [[2 = 0U, 3 = 40U, 4 = 4U]], [[3 = 49U, 4 = 3U]]], 3 = false, 255 = 1U}")
|
||||
r = matter.ReadRequestMessage().from_TLV(m)
|
||||
assert(str(r) == "<Matter_ReadRequestMessage:{'attributes_requests': [[**]0031/FFFC, [00]0030/0000, [00]0030/0001, [00]0030/0002, [00]0030/0003, [00]0028/0002, [00]0028/0004, [**]0031/0003], 'data_version_filters': nil, 'event_filters': nil, 'event_requests': nil, 'fabric_filtered': false}>")
|
||||
t = r.to_TLV()
|
||||
assert(str(t) == "{0 = [[[3 = 49U, 4 = 65532U]], [[2 = 0U, 3 = 48U, 4 = 0U]], [[2 = 0U, 3 = 48U, 4 = 1U]], [[2 = 0U, 3 = 48U, 4 = 2U]], [[2 = 0U, 3 = 48U, 4 = 3U]], [[2 = 0U, 3 = 40U, 4 = 2U]], [[2 = 0U, 3 = 40U, 4 = 4U]], [[3 = 49U, 4 = 3U]]], 3 = false}")
|
||||
|
||||
|
||||
# ReportDataMessage
|
||||
r = matter.ReportDataMessage()
|
||||
r.subscription_id = 1
|
||||
r.attribute_reports = []
|
||||
a1 = matter.AttributeReportIB()
|
||||
a1.attribute_status = matter.AttributeStatusIB()
|
||||
a1.attribute_status.path = matter.AttributePathIB()
|
||||
a1.attribute_status.status = matter.StatusIB()
|
||||
a1.attribute_status.path.endpoint = 0
|
||||
a1.attribute_status.path.cluster = 0x0030
|
||||
a1.attribute_status.path.attribute = 0
|
||||
a1.attribute_status.status.status = 0
|
||||
a1.attribute_status.status.cluster_status = 0
|
||||
a1.attribute_data = matter.AttributeDataIB()
|
||||
a1.attribute_data.data_version = 1
|
||||
a1.attribute_data.path = matter.AttributePathIB()
|
||||
a1.attribute_data.path.endpoint = 0
|
||||
a1.attribute_data.path.cluster = 0x0030
|
||||
a1.attribute_data.path.attribute = 0
|
||||
a1.attribute_data.data = matter.TLV.create_TLV(matter.TLV.UTF1, "Tasmota")
|
||||
assert(str(a1.to_TLV()) == '{0 = {0 = [[2 = 0U, 3 = 48U, 4 = 0U]], 1 = [[0 = 0U, 1 = 0U]]}, 1 = {0 = 1U, 1 = [[2 = 0U, 3 = 48U, 4 = 0U]], 2 = "Tasmota"}}')
|
||||
r.attribute_reports.push(a1)
|
||||
#{0 = 1U, 1 = [{0 = {0 = [[2 = 0U, 3 = 48U, 4 = 0U]], 1 = [[0 = 0U, 1 = 0U]]}, 1 = {0 = 1U, 1 = [[2 = 0U, 3 = 48U, 4 = 0U]], 2 = "Tasmota"}}]}
|
||||
assert(r.to_TLV().encode() == bytes('1524000136011535003700240200240330240400183701240000240100181835012400013701240200240330240400182C02075461736D6F746118181818'))
|
||||
|
||||
|
||||
# <Matter_AttributeReportIB:{
|
||||
# 'attribute_data': <Matter_AttributeDataIB:{
|
||||
# 'data': nil, 'data_version': nil, 'path': nil}>,
|
||||
# 'attribute_status': <Matter_AttributeStatusIB:{
|
||||
# 'path': [00]0030/0000, 'status': <Matter_StatusIB:{
|
||||
# 'cluster_status': 0, 'status': 0}>}>}>
|
||||
|
||||
-#
|
||||
|
407
lib/libesp32/berry_matter/src/embedded/Matter_Message.be
Normal file
407
lib/libesp32/berry_matter/src/embedded/Matter_Message.be
Normal file
@ -0,0 +1,407 @@
|
||||
#
|
||||
# Matter_Message.be - suppport for Matter Message Packet/Frame structure, deconding, enconding, encryption & decryption
|
||||
#
|
||||
# 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/>.
|
||||
#
|
||||
|
||||
|
||||
import matter
|
||||
|
||||
#@ solidify:Matter_Frame,weak
|
||||
|
||||
# Matter frame format, see 4.4 (p. 107)
|
||||
class Matter_Frame
|
||||
# context information
|
||||
var message_handler # the message handler instance that decodes and generate responses
|
||||
var session # the session object associated, or `nil` if no session
|
||||
# content of the message
|
||||
var raw # raw bytes of the packet
|
||||
var payload_idx # index in raw for beginning of payload
|
||||
# Message header
|
||||
var flags
|
||||
var flag_s # Note: Matter booleans are 1/0 not true/false
|
||||
var flag_dsiz
|
||||
var local_session_id
|
||||
var sec_flags
|
||||
var sec_p
|
||||
var sec_c
|
||||
var sec_mx
|
||||
var sec_sesstype
|
||||
var message_counter
|
||||
var source_node_id
|
||||
var dest_node_id_2 # if 2 bytes
|
||||
var dest_node_id_8 # if 8 bytes
|
||||
# Message payload
|
||||
var x_flags
|
||||
var x_flag_v
|
||||
var x_flag_sx
|
||||
var x_flag_r
|
||||
var x_flag_a
|
||||
var x_flag_i
|
||||
var opcode
|
||||
var exchange_id
|
||||
var protocol_id
|
||||
var vendor_id # (opt)
|
||||
var ack_message_counter # (opt)
|
||||
var sec_extensions
|
||||
# var
|
||||
var app_payload_idx # index where the application payload starts
|
||||
|
||||
#############################################################
|
||||
# keep track of the message_handler object
|
||||
#
|
||||
def init(message_handler, raw)
|
||||
self.message_handler = message_handler
|
||||
self.raw = raw
|
||||
end
|
||||
|
||||
#############################################################
|
||||
# decode the header of the message and provide session
|
||||
# information if decryption is required
|
||||
#
|
||||
# returns `true` if ok, `false` if message needs to be ignored
|
||||
# or raises an exception if something went wrong
|
||||
def decode_header()
|
||||
var idx = 0
|
||||
var raw = self.raw
|
||||
# flags
|
||||
self.flags = raw.get(0, 1)
|
||||
if (self.flags & 0xF8) != 0x00 return false end # ignore if Matter version if not 1.0
|
||||
self.flag_s = raw.getbits(2, 1)
|
||||
self.flag_dsiz = raw.getbits(0, 2)
|
||||
if self.flag_dsiz == 3 return false end # ignore if dsiz is unknown
|
||||
|
||||
# security flagse
|
||||
self.sec_flags = raw.get(3, 1)
|
||||
self.sec_p = raw.getbits(3*8 + 7, 1)
|
||||
self.sec_c = raw.getbits(3*8 + 6, 1)
|
||||
self.sec_mx = raw.getbits(3*8 + 5, 1)
|
||||
self.sec_sesstype = raw.getbits(3*8, 2)
|
||||
if self.sec_sesstype > 1 return false end # ignore if session type is unknown
|
||||
|
||||
#
|
||||
self.local_session_id = raw.get(1, 2)
|
||||
self.message_counter = raw.get(4, 4)
|
||||
idx += 8
|
||||
# source node id?
|
||||
if self.flag_s
|
||||
self.source_node_id = raw[idx .. idx+7]
|
||||
idx += 8
|
||||
end
|
||||
# dest node id?
|
||||
if self.flag_dsiz == 1
|
||||
self.dest_node_id_8 = raw[idx .. idx+7]
|
||||
idx += 8
|
||||
elif self.flag_dsiz == 2
|
||||
self.dest_node_id_2 = raw.get(idx, 2)
|
||||
idx += 2
|
||||
end
|
||||
|
||||
# skip MX if any
|
||||
if self.sec_mx
|
||||
var sz = raw.get(idx, 2)
|
||||
idx += sz + 2 # ignore bytes
|
||||
end
|
||||
|
||||
self.payload_idx = idx
|
||||
return true
|
||||
end
|
||||
|
||||
#############################################################
|
||||
def decode_payload()
|
||||
var idx = self.payload_idx # retrieve index for payload
|
||||
var raw = self.raw
|
||||
|
||||
# Message paylod
|
||||
self.x_flags = raw.get(idx, 1)
|
||||
# flags
|
||||
self.x_flag_v = raw.getbits(idx*8 + 4, 1)
|
||||
self.x_flag_sx = raw.getbits(idx*8 + 3, 1)
|
||||
self.x_flag_r = raw.getbits(idx*8 + 2, 1)
|
||||
self.x_flag_a = raw.getbits(idx*8 + 1, 1)
|
||||
self.x_flag_i = raw.getbits(idx*8, 1)
|
||||
|
||||
self.opcode = raw.get(idx+1, 1)
|
||||
self.exchange_id = raw.get(idx+2, 2)
|
||||
self.protocol_id = raw.get(idx+4, 2)
|
||||
idx += 6
|
||||
|
||||
# optional protocol vendor id
|
||||
if self.x_flag_v
|
||||
self.vendor_id = raw.get(idx, 2)
|
||||
idx += 2
|
||||
end
|
||||
# optional Acknowledged Message Counter (32 bits)
|
||||
if self.x_flag_a
|
||||
self.ack_message_counter = raw.get(idx, 4)
|
||||
idx += 4
|
||||
end
|
||||
# optional secure extensions
|
||||
if self.x_flag_sx
|
||||
var sz = raw.get(idx, 2)
|
||||
idx += sz + 2 # skip
|
||||
end
|
||||
|
||||
self.app_payload_idx = idx
|
||||
return self
|
||||
end
|
||||
|
||||
#############################################################
|
||||
# Encode the packet as raw bytes
|
||||
#
|
||||
# If encryption is needed, it is done later
|
||||
#
|
||||
# Header is built from attributes
|
||||
# `payload` is a bytes() buffer for the app payload
|
||||
def encode(payload)
|
||||
var raw = bytes()
|
||||
# compute flags
|
||||
if self.flags == nil
|
||||
self.flags = 0x00
|
||||
if self.flag_s self.flags = self.flags | 0x04 end
|
||||
if self.flag_dsiz self.flags = self.flags | (self.flag_dsiz & 0x03) end
|
||||
end
|
||||
raw.add(self.flags, 1)
|
||||
# local_session_id (mandatory)
|
||||
raw.add(self.local_session_id ? self.local_session_id : 0, 2)
|
||||
# compute security flags
|
||||
if self.sec_flags == nil
|
||||
self.sec_flags = 0x00
|
||||
if self.sec_p self.sec_flags = self.sec_flags | 0x80 end
|
||||
if self.sec_c self.sec_flags = self.sec_flags | 0x40 end
|
||||
# if self.sec_mx self.sec_flags = self.sec_flags | 0x20 end # not supportedd
|
||||
if self.sec_sesstype self.sec_flags = self.sec_flags | (self.sec_sesstype & 0x03) end
|
||||
end
|
||||
raw.add(self.sec_flags, 1)
|
||||
#
|
||||
raw.add(self.message_counter, 4) # mandatory
|
||||
#
|
||||
if self.flag_s raw .. self.source_node_id end # 8 bytes
|
||||
if self.flag_dsiz == 0x01 raw .. self.dest_node_id_8 end # 8 bytes
|
||||
if self.flag_dsiz == 0x02 raw.add(self.dest_node_id_2, 2) end # 2 bytes
|
||||
# skip message extensions
|
||||
self.payload_idx = size(raw)
|
||||
# Message payload
|
||||
if self.x_flags == nil
|
||||
self.x_flags = 0x00
|
||||
if self.x_flag_v self.x_flags = self.x_flags | 0x10 end
|
||||
# if self.x_flag_sx self.x_flags = self.x_flags | 0x08 end # not implemented
|
||||
if self.x_flag_r self.x_flags = self.x_flags | 0x04 end
|
||||
if self.x_flag_a self.x_flags = self.x_flags | 0x02 end
|
||||
if self.x_flag_i self.x_flags = self.x_flags | 0x01 end
|
||||
end
|
||||
raw.add(self.x_flags, 1)
|
||||
# opcode (mandatory)
|
||||
raw.add(self.opcode, 1)
|
||||
raw.add(self.exchange_id, 2)
|
||||
raw.add(self.protocol_id, 2)
|
||||
if self.x_flag_a raw.add(self.ack_message_counter, 4) end
|
||||
# finally payload
|
||||
self.app_payload_idx = size(raw)
|
||||
if payload
|
||||
raw .. payload
|
||||
end
|
||||
|
||||
self.debug(raw)
|
||||
self.raw = raw
|
||||
return raw
|
||||
end
|
||||
|
||||
#############################################################
|
||||
# Generate a Standalone Acknowledgment
|
||||
# Uses `PROTOCOL_ID_SECURE_CHANNEL` no ecnryption required
|
||||
def build_standalone_ack()
|
||||
import string
|
||||
# send back response
|
||||
var resp = classof(self)(self.message_handler)
|
||||
|
||||
if self.flag_s
|
||||
resp.flag_dsiz = 0x01
|
||||
resp.dest_node_id_8 = self.source_node_id
|
||||
else
|
||||
resp.flag_dsiz = 0x00
|
||||
end
|
||||
resp.session = self.session # also copy the session object
|
||||
# message counter
|
||||
resp.message_counter = self.session.counter_snd.next()
|
||||
resp.local_session_id = self.session.initiator_session_id
|
||||
|
||||
resp.x_flag_i = 0 # not sent by initiator
|
||||
resp.opcode = 0x10 # MRP Standalone Acknowledgement
|
||||
resp.exchange_id = self.exchange_id
|
||||
resp.protocol_id = 0 # PROTOCOL_ID_SECURE_CHANNEL
|
||||
resp.x_flag_a = 1 # ACK of previous message
|
||||
resp.ack_message_counter = self.message_counter
|
||||
resp.x_flag_r = 0
|
||||
|
||||
tasmota.log(string.format("MTR: <Replied %s", matter.get_opcode_name(resp.opcode)), 2)
|
||||
return resp
|
||||
end
|
||||
|
||||
#############################################################
|
||||
# Generate response to message with default parameter
|
||||
# does not handle encryption which is done in a later step
|
||||
def build_response(opcode, reliable)
|
||||
import string
|
||||
# send back response
|
||||
var resp = classof(self)(self.message_handler)
|
||||
|
||||
if self.flag_s
|
||||
resp.flag_dsiz = 0x01
|
||||
resp.dest_node_id_8 = self.source_node_id
|
||||
else
|
||||
resp.flag_dsiz = 0x00
|
||||
end
|
||||
resp.session = self.session # also copy the session object
|
||||
# message counter
|
||||
# if self.session && self.session.initiator_session_id != 0
|
||||
if self.local_session_id != 0 && self.session && self.session.initiator_session_id != 0
|
||||
resp.message_counter = self.session.counter_snd.next()
|
||||
resp.local_session_id = self.session.initiator_session_id
|
||||
else
|
||||
resp.message_counter = self.session._counter_insecure_snd.next()
|
||||
resp.local_session_id = 0
|
||||
end
|
||||
|
||||
resp.x_flag_i = 0 # not sent by initiator
|
||||
resp.opcode = opcode
|
||||
resp.exchange_id = self.exchange_id
|
||||
resp.protocol_id = self.protocol_id
|
||||
if self.x_flag_r
|
||||
resp.x_flag_a = 1 # ACK of previous message
|
||||
resp.ack_message_counter = self.message_counter
|
||||
end
|
||||
resp.x_flag_r = reliable ? 1 : 0
|
||||
|
||||
if resp.local_session_id == 0
|
||||
var op_name = matter.get_opcode_name(resp.opcode)
|
||||
if !op_name op_name = string.format("0x%02X", resp.opcode) end
|
||||
tasmota.log(string.format("MTR: <Replied %s", op_name), 2)
|
||||
end
|
||||
return resp
|
||||
end
|
||||
|
||||
#############################################################
|
||||
# decrypt with I2S key
|
||||
# return cleartext or `nil` if failed
|
||||
def decrypt()
|
||||
import crypto
|
||||
var session = self.session
|
||||
var raw = self.raw
|
||||
# decrypt the message with `i2r` key
|
||||
var i2r = session.get_i2r()
|
||||
var mic = raw[-16..] # take last 16 bytes as signature
|
||||
# use AES_CCM
|
||||
var a = raw[0 .. self.payload_idx - 1]
|
||||
var p = raw[self.payload_idx .. -17]
|
||||
# recompute nonce
|
||||
var n = bytes()
|
||||
n.add(self.flags, 1)
|
||||
n.add(self.message_counter, 4)
|
||||
if self.source_node_id
|
||||
n .. source_node_id
|
||||
else
|
||||
if session.peer_node_id
|
||||
n .. session.peer_node_id
|
||||
end
|
||||
n.resize(13) # add zeros
|
||||
end
|
||||
|
||||
tasmota.log("MTR: ******************************", 3)
|
||||
tasmota.log("MTR: i2r =" + i2r.tohex(), 3)
|
||||
tasmota.log("MTR: p =" + p.tohex(), 3)
|
||||
tasmota.log("MTR: a =" + a.tohex(), 3)
|
||||
tasmota.log("MTR: n =" + n.tohex(), 3)
|
||||
tasmota.log("MTR: mic =" + mic.tohex(), 3)
|
||||
|
||||
# decrypt
|
||||
var aes = crypto.AES_CCM(i2r, n, a, size(p), 16)
|
||||
var cleartext = aes.decrypt(p)
|
||||
var tag = aes.tag()
|
||||
|
||||
tasmota.log("MTR: ******************************", 3)
|
||||
tasmota.log("MTR: cleartext =" + cleartext.tohex(), 3)
|
||||
tasmota.log("MTR: tag =" + tag.tohex(), 3)
|
||||
tasmota.log("MTR: ******************************", 3)
|
||||
|
||||
if tag != mic
|
||||
tasmota.log("MTR: rejected packet due to invalid MIC", 3)
|
||||
return nil
|
||||
end
|
||||
|
||||
return cleartext
|
||||
end
|
||||
|
||||
#############################################################
|
||||
# encrypt with R2I key
|
||||
# return true if ok
|
||||
# changes the raw buffer in-place
|
||||
def encrypt()
|
||||
import crypto
|
||||
var raw = self.raw
|
||||
var session = self.session
|
||||
|
||||
# encrypt the message with `i2r` key
|
||||
var r2i = session.get_r2i()
|
||||
|
||||
# use AES_CCM
|
||||
var a = raw[0 .. self.payload_idx - 1]
|
||||
var p = raw[self.payload_idx .. ]
|
||||
# recompute nonce
|
||||
var n = bytes()
|
||||
n.add(self.flags, 1)
|
||||
n.add(self.message_counter, 4)
|
||||
if session.get_mode() == session.__CASE && session.deviceid
|
||||
n .. session.deviceid
|
||||
end
|
||||
n.resize(13) # add zeros
|
||||
|
||||
tasmota.log("MTR: cleartext: " + self.raw.tohex(), 3)
|
||||
|
||||
tasmota.log("MTR: ******************************", 3)
|
||||
tasmota.log("MTR: r2i =" + r2i.tohex(), 3)
|
||||
tasmota.log("MTR: p =" + p.tohex(), 3)
|
||||
tasmota.log("MTR: a =" + a.tohex(), 3)
|
||||
tasmota.log("MTR: n =" + n.tohex(), 3)
|
||||
|
||||
# decrypt
|
||||
var aes = crypto.AES_CCM(r2i, n, a, size(p), 16)
|
||||
var ciphertext = aes.encrypt(p)
|
||||
var tag = aes.tag()
|
||||
|
||||
tasmota.log("MTR: ******************************", 3)
|
||||
tasmota.log("MTR: ciphertext =" + ciphertext.tohex(), 3)
|
||||
tasmota.log("MTR: tag =" + tag.tohex(), 3)
|
||||
tasmota.log("MTR: ******************************", 3)
|
||||
|
||||
# packet is good, put back content in raw
|
||||
self.raw.resize(self.payload_idx) # remove cleartext payload
|
||||
self.raw .. ciphertext # add ciphertext
|
||||
self.raw .. tag # add MIC
|
||||
|
||||
# tasmota.log("MTR: encrypted: " + self.raw.tohex(), 3)
|
||||
end
|
||||
|
||||
#############################################################
|
||||
# Decode a message we are about to send, to ease debug
|
||||
def debug(raw)
|
||||
var r = matter.Frame(self.message_handler, raw)
|
||||
r.decode_header()
|
||||
r.decode_payload()
|
||||
tasmota.log("MTR: sending decode: " + matter.inspect(r), 3)
|
||||
end
|
||||
end
|
||||
matter.Frame = Matter_Frame
|
171
lib/libesp32/berry_matter/src/embedded/Matter_MessageHandler.be
Normal file
171
lib/libesp32/berry_matter/src/embedded/Matter_MessageHandler.be
Normal file
@ -0,0 +1,171 @@
|
||||
#
|
||||
# Matter_MessageHandler.be - suppport for Matter Message handler, dispatches incoming messages and sends outgoing messages
|
||||
#
|
||||
# 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/>.
|
||||
#
|
||||
|
||||
import matter
|
||||
|
||||
#@ solidify:Matter_MessageHandler,weak
|
||||
|
||||
class Matter_MessageHandler
|
||||
# callback for sending messages
|
||||
var device # `tansport.msg_send(raw:bytes() [,...]) -> bool` true if succeeded
|
||||
|
||||
# handlers
|
||||
var commissioning
|
||||
var im # handler for Interaction Model
|
||||
# counters
|
||||
var counter_rcv # Global Unencrypted Message Counter incoming
|
||||
|
||||
#############################################################
|
||||
def init(device)
|
||||
self.device = device
|
||||
self.commissioning = matter.Commisioning_Context(self)
|
||||
self.im = matter.IM(self)
|
||||
self.counter_rcv = matter.Counter()
|
||||
end
|
||||
|
||||
#############################################################
|
||||
# Called when a message is received
|
||||
#
|
||||
# Find or create a session for the message
|
||||
# and dispacth to appropriate handler
|
||||
#
|
||||
def msg_received(raw, addr, port)
|
||||
import string
|
||||
try
|
||||
tasmota.log("MTR: MessageHandler::msg_received raw="+raw.tohex(), 4)
|
||||
var frame = matter.Frame(self, raw)
|
||||
|
||||
var ok = frame.decode_header()
|
||||
if !ok return false end
|
||||
|
||||
# do we need decryption?
|
||||
if frame.local_session_id == 0 && frame.sec_sesstype == 0
|
||||
#############################################################
|
||||
### unencrypted session, handled by commissioning
|
||||
var session = self.device.sessions.find_session_source_id_unsecure(frame.source_node_id, 90) # 90 seconds max
|
||||
tasmota.log("MTR: find session by source_node_id = " + str(frame.source_node_id) + "session_id = " + str(session.local_session_id), 3)
|
||||
frame.session = session
|
||||
|
||||
# check if it's a duplicate
|
||||
if !self.counter_rcv.validate(frame.message_counter, false)
|
||||
tasmota.log(string.format("MTR: rejected duplicate unencrypted message = %i ref = %i", frame.message_counter, self.counter_rcv.val()), 3)
|
||||
return false
|
||||
end
|
||||
|
||||
if !frame.decode_payload() return false end
|
||||
self.device.packet_ack(frame.ack_message_counter) # acknowledge packet
|
||||
if frame.opcode != 0x10 # don't show `MRP_Standalone_Acknowledgement`
|
||||
var op_name = matter.get_opcode_name(frame.opcode)
|
||||
if !op_name op_name = string.format("0x%02X", frame.opcode) end
|
||||
tasmota.log(string.format("MTR: >Received %s from [%s]:%i", op_name, addr, port), 2)
|
||||
end
|
||||
self.commissioning.process_incoming(frame, addr, port)
|
||||
return true
|
||||
else
|
||||
#############################################################
|
||||
# encrypted message
|
||||
tasmota.log(string.format("MTR: decode header: local_session_id=%i message_counter=%i", frame.local_session_id, frame.message_counter), 3)
|
||||
|
||||
var session = self.device.sessions.get_session_by_local_session_id(frame.local_session_id)
|
||||
if session == nil
|
||||
tasmota.log("MTR: unknown local_session_id "+str(frame.local_session_id), 3)
|
||||
tasmota.log("MTR: frame="+matter.inspect(frame), 3)
|
||||
return false
|
||||
end
|
||||
frame.session = session # keep a pointer of the session in the message
|
||||
|
||||
# check if it's a duplicate
|
||||
if !session.counter_rcv.validate(frame.message_counter, true)
|
||||
tasmota.log("MTR: rejected duplicate encrypted message = " + str(frame.message_counter) + " counter=" + str(session.counter_rcv.val()), 3)
|
||||
return false
|
||||
end
|
||||
|
||||
var cleartext = frame.decrypt()
|
||||
if !cleartext return false end
|
||||
|
||||
# packet is good, put back content in raw
|
||||
frame.raw = frame.raw[0 .. frame.payload_idx - 1] # remove encrypted payload
|
||||
frame.raw .. cleartext # add cleartext
|
||||
|
||||
# continue decoding
|
||||
tasmota.log(string.format("MTR: idx=%i clear=%s", frame.payload_idx, frame.raw.tohex()), 3)
|
||||
frame.decode_payload()
|
||||
tasmota.log("MTR: decrypted message: protocol_id:"+str(frame.protocol_id)+" opcode="+str(frame.opcode)+" exchange_id"+str(frame.exchange_id), 3)
|
||||
|
||||
self.device.packet_ack(frame.ack_message_counter) # acknowledge packet
|
||||
|
||||
# dispatch according to protocol_id
|
||||
var protocol_id = frame.protocol_id
|
||||
if protocol_id == 0x0000 # PROTOCOL_ID_SECURE_CHANNEL
|
||||
# it should not be encrypted
|
||||
tasmota.log("MTR: PROTOCOL_ID_SECURE_CHANNEL " + matter.inspect(frame), 3)
|
||||
# if frame.opcode == 0x10
|
||||
# end
|
||||
return true
|
||||
elif protocol_id == 0x0001 # PROTOCOL_ID_INTERACTION_MODEL
|
||||
# dispatch to IM Protocol Messages
|
||||
return self.im.process_incoming(frame, addr, port)
|
||||
|
||||
# -- PROTOCOL_ID_BDX is used for file transfer between devices, not used in Tasmota
|
||||
# elif protocol_id == 0x0002 # PROTOCOL_ID_BDX -- BDX not handled at all in Tasmota
|
||||
# tasmota.log("MTR: PROTOCOL_ID_BDX not yet handled", 2)
|
||||
# return false # ignore for now TODO
|
||||
# -- PROTOCOL_ID_USER_DIRECTED_COMMISSIONING is only used by devices, as a device we will not receive any
|
||||
# elif protocol_id == 0x0003 # PROTOCOL_ID_USER_DIRECTED_COMMISSIONING
|
||||
# tasmota.log("MTR: PROTOCOL_ID_USER_DIRECTED_COMMISSIONING not yet handled", 2)
|
||||
# return false # ignore for now TODO
|
||||
else
|
||||
tasmota.log("MTR: ignoring unhandled protocol_id:"+str(protocol_id), 3)
|
||||
return false
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
return true
|
||||
except .. as e, m
|
||||
tasmota.log("MTR: MessageHandler::msg_received exception: "+str(e)+";"+str(m))
|
||||
import debug
|
||||
debug.traceback()
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
#############################################################
|
||||
def send_response(raw, addr, port, id)
|
||||
self.device.msg_send(raw, addr, port, id)
|
||||
end
|
||||
|
||||
#############################################################
|
||||
def add_session(local_session_id, initiator_session_id, i2r, r2i, ac, session_timestamp)
|
||||
import string
|
||||
# create session object
|
||||
tasmota.log(string.format("MTR: add_session local_session_id=%i initiator_session_id=%i", local_session_id, initiator_session_id), 3)
|
||||
|
||||
var session = self.device.sessions.create_session(local_session_id, initiator_session_id)
|
||||
session.set_keys(i2r, r2i, ac, session_timestamp)
|
||||
end
|
||||
|
||||
#############################################################
|
||||
# placeholder, nothing to run for now
|
||||
def every_second()
|
||||
self.commissioning.every_second()
|
||||
self.im.every_second()
|
||||
end
|
||||
end
|
||||
matter.MessageHandler = Matter_MessageHandler
|
46
lib/libesp32/berry_matter/src/embedded/Matter_Module.be
Normal file
46
lib/libesp32/berry_matter/src/embedded/Matter_Module.be
Normal file
@ -0,0 +1,46 @@
|
||||
#
|
||||
# Matter_Module.be - implements the global `matter` module from a solidified module that can be dynamically enriched
|
||||
#
|
||||
# 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 module for extensibility
|
||||
#
|
||||
# this allows the module `matter` to be extended
|
||||
|
||||
var matter = module("matter")
|
||||
|
||||
def setmember(k, v)
|
||||
import global
|
||||
if !global.contains(".matter") global.(".matter") = {} end
|
||||
global.(".matter")[k] = v
|
||||
end
|
||||
|
||||
def member(k)
|
||||
import global
|
||||
import undefined
|
||||
|
||||
if global.contains(".matter") && global.(".matter").contains(k)
|
||||
return global.(".matter")[k]
|
||||
else
|
||||
return undefined
|
||||
end
|
||||
end
|
||||
|
||||
matter.setmember = setmember
|
||||
matter.member = member
|
||||
#@ solidify:matter.setmember,weak
|
||||
#@ solidify:matter.member,weak
|
88
lib/libesp32/berry_matter/src/embedded/Matter_Plugin.be
Normal file
88
lib/libesp32/berry_matter/src/embedded/Matter_Plugin.be
Normal file
@ -0,0 +1,88 @@
|
||||
#
|
||||
# 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
|
||||
var device
|
||||
var endpoints
|
||||
|
||||
#############################################################
|
||||
# Constructor
|
||||
def init(device)
|
||||
self.device = device
|
||||
self.endpoints = []
|
||||
end
|
||||
|
||||
#############################################################
|
||||
# Which endpoints does it handle (list of numbers)
|
||||
def get_endpoints()
|
||||
return self.endpoints
|
||||
end
|
||||
|
||||
#############################################################
|
||||
# read attribute
|
||||
def read_attribute(msg, endpoint, cluster, attribute)
|
||||
return nil
|
||||
end
|
||||
|
||||
#############################################################
|
||||
# read event
|
||||
# TODO
|
||||
def read_event(msg, endpoint, cluster, eventid)
|
||||
return nil
|
||||
end
|
||||
|
||||
#############################################################
|
||||
# subscribe attribute
|
||||
# TODO
|
||||
def subscribe_attribute(msg, endpoint, cluster, attribute)
|
||||
return nil
|
||||
end
|
||||
|
||||
#############################################################
|
||||
# subscribe event
|
||||
# TODO
|
||||
def subscribe_event(msg, endpoint, cluster, eventid)
|
||||
return nil
|
||||
end
|
||||
|
||||
#############################################################
|
||||
# write attribute
|
||||
def write_attribute(msg, endpoint, cluster, attribute)
|
||||
return nil
|
||||
end
|
||||
|
||||
#############################################################
|
||||
# invoke command
|
||||
def invoke_request(msg, val, ctx)
|
||||
return nil
|
||||
end
|
||||
|
||||
#############################################################
|
||||
# timed request
|
||||
# TODO - should we even support this?
|
||||
def timed_request(msg, val, ctx)
|
||||
return nil
|
||||
end
|
||||
end
|
||||
matter.Plugin = Matter_Plugin
|
@ -0,0 +1,52 @@
|
||||
#
|
||||
# Matter_Plugin_Relay.be - implements the behavior for a Relay (OnOff)
|
||||
#
|
||||
# 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 plug-in for core behavior
|
||||
|
||||
# dummy declaration for solidification
|
||||
class Matter_Plugin end
|
||||
|
||||
#@ solidify:Matter_Plugin_Relay,weak
|
||||
|
||||
class Matter_Plugin_Relay : Matter_Plugin
|
||||
#############################################################
|
||||
# Constructor
|
||||
def init(device)
|
||||
super(self).init(device)
|
||||
self.endpoints = [ 1 ]
|
||||
end
|
||||
|
||||
#############################################################
|
||||
# read an attribute
|
||||
#
|
||||
def read_attribute(msg, endpoint, cluster, attribute)
|
||||
# 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(msg, val, ctx)
|
||||
# no match found, return that the command is unsupported
|
||||
end
|
||||
end
|
||||
matter.Plugin_core = Matter_Plugin_core
|
||||
|
372
lib/libesp32/berry_matter/src/embedded/Matter_Plugin_core.be
Normal file
372
lib/libesp32/berry_matter/src/embedded/Matter_Plugin_core.be
Normal file
@ -0,0 +1,372 @@
|
||||
#
|
||||
# Matter_Plugin_core.be - implements the core features that a Matter device must implemment
|
||||
#
|
||||
# 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 plug-in for core behavior
|
||||
|
||||
# dummy declaration for solidification
|
||||
class Matter_Plugin end
|
||||
|
||||
#@ solidify:Matter_Plugin_core,weak
|
||||
|
||||
class Matter_Plugin_core : Matter_Plugin
|
||||
#############################################################
|
||||
# Constructor
|
||||
def init(device)
|
||||
super(self).init(device)
|
||||
self.endpoints = [ 0 ]
|
||||
end
|
||||
|
||||
#############################################################
|
||||
# read an attribute
|
||||
#
|
||||
def read_attribute(msg, endpoint, cluster, attribute)
|
||||
var TLV = matter.TLV
|
||||
|
||||
if cluster == 0x0030 # ========== GeneralCommissioning cluster 11.9 p.627 ==========
|
||||
|
||||
if attribute == 0x0000 # ---------- Breadcrumb ----------
|
||||
return TLV.create_TLV(TLV.U8, msg.session.breadcrumb)
|
||||
elif attribute == 0x0001 # ---------- BasicCommissioningInfo / BasicCommissioningInfo----------
|
||||
var bci = TLV.Matter_TLV_struct()
|
||||
bci.add_TLV(0, TLV.U2, 60) # FailSafeExpiryLengthSeconds
|
||||
bci.add_TLV(1, TLV.U2, 900) # MaxCumulativeFailsafeSeconds
|
||||
return bci
|
||||
elif attribute == 0x0002 # ---------- RegulatoryConfig / RegulatoryLocationType ----------
|
||||
return TLV.create_TLV(TLV.U1, 2) # 2 = IndoorOutdoor | esp-matter = 0
|
||||
elif attribute == 0x0003 # ---------- LocationCapability / RegulatoryLocationType----------
|
||||
return TLV.create_TLV(TLV.U1, 2) # 2 = IndoorOutdoor
|
||||
elif attribute == 0x0004 # ---------- SupportsConcurrentConnection / bool ----------
|
||||
return TLV.create_TLV(TLV.BOOL, false) # false - maybe can set to true
|
||||
end
|
||||
# ====================================================================================================
|
||||
elif cluster == 0x0032 # ========== Diagnostic Logs Cluster 11.10 p.637 ==========
|
||||
# no attributes
|
||||
|
||||
# ====================================================================================================
|
||||
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
|
||||
return nwi
|
||||
elif attribute == 0x0001 # ---------- RebootCount u16 ----------
|
||||
return TLV.create_TLV(TLV.U2, tasmota.cmd("Status 1")['StatusPRM']['BootCount'])
|
||||
elif attribute == 0x0002 # ---------- UpTime u16 ----------
|
||||
return TLV.create_TLV(TLV.U4, tasmota.cmd("Status 11")['StatusSTS']['UptimeSec'])
|
||||
# TODO add later other attributes
|
||||
elif attribute == 0x0008 # ---------- TestEventTriggersEnabled bool ----------
|
||||
return TLV.create_TLV(TLV.BOOL, false) # false - maybe can set to true
|
||||
end
|
||||
|
||||
# ====================================================================================================
|
||||
elif cluster == 0x0034 # ========== Software Diagnostics Cluster 11.12 p.654 ==========
|
||||
# no mandatory attributes - to be added later (maybe)
|
||||
|
||||
# ====================================================================================================
|
||||
elif cluster == 0x0038 # ========== Time Synchronization 11.16 p.689 ==========
|
||||
if attribute == 0x0000 # ---------- UTCTime / epoch_us ----------
|
||||
var epoch_us = int64(tasmota.rtc()['utc']) * int64(1000000)
|
||||
return TLV.create_TLV(TLV.U8, epoch_us) # TODO test the conversion of int64()
|
||||
elif attribute == 0x0001 # ---------- Granularity / enum ----------
|
||||
return TLV.create_TLV(TLV.U1, 3) # MillisecondsGranularity (NTP every hour, i.e. 36ms max drift)
|
||||
# TODO add some missing args
|
||||
elif attribute == 0x0007 # ---------- LocalTime / epoch_us ----------
|
||||
var epoch_us = int64(tasmota.rtc()['local']) * int64(1000000)
|
||||
return TLV.create_TLV(TLV.U8, epoch_us) # TODO test the conversion of int64()
|
||||
end
|
||||
|
||||
# ====================================================================================================
|
||||
elif cluster == 0x003E # ========== Node Operational Credentials Cluster 11.17 p.704 ==========
|
||||
|
||||
if attribute == 0x0000 # ---------- NOCs / list[NOCStruct] ----------
|
||||
# TODO
|
||||
elif attribute == 0x0001 # ---------- Fabrics / list[FabricDescriptorStruct] ----------
|
||||
# TODO
|
||||
elif attribute == 0x0002 # ---------- SupportedFabrics / u1 ----------
|
||||
return TLV.create_TLV(TLV.U1, 5) # Max 5 fabrics
|
||||
elif attribute == 0x0003 # ---------- CommissionedFabrics / u1 ----------
|
||||
return TLV.create_TLV(TLV.U1, 1) # TODO
|
||||
elif attribute == 0x0004 # ---------- TrustedRootCertificates / list[octstr] ----------
|
||||
# TODO
|
||||
elif attribute == 0x0005 # ---------- Current FabricIndex / u1 ----------
|
||||
# TODO
|
||||
end
|
||||
|
||||
# ====================================================================================================
|
||||
elif cluster == 0x003C # ========== Administrator Commissioning Cluster 11.18 p.725 ==========
|
||||
# TODO
|
||||
|
||||
# ====================================================================================================
|
||||
elif cluster == 0x0028 # ========== Basic Information Cluster cluster 11.1 p.565 ==========
|
||||
|
||||
if attribute == 0x0000 # ---------- DataModelRevision / u16 ----------
|
||||
return TLV.create_TLV(TLV.U2, 0)
|
||||
elif attribute == 0x0001 # ---------- VendorName / string ----------
|
||||
return TLV.create_TLV(TLV.UTF1, "Tasmota")
|
||||
elif attribute == 0x0002 # ---------- VendorID / vendor-id ----------
|
||||
return TLV.create_TLV(TLV.U2, self.device.vendorid) # Vendor ID reserved for development
|
||||
elif attribute == 0x0003 # ---------- ProductName / string ----------
|
||||
return TLV.create_TLV(TLV.UTF1, tasmota.cmd("DeviceName")['DeviceName'])
|
||||
elif attribute == 0x0004 # ---------- ProductID / u16 (opt) ----------
|
||||
return TLV.create_TLV(TLV.U2, 32768) # taken from esp-matter example
|
||||
elif attribute == 0x0005 # ---------- NodeLabel / string ----------
|
||||
return TLV.create_TLV(TLV.UTF1, tasmota.cmd("FriendlyName")['FriendlyName1'])
|
||||
elif attribute == 0x0006 # ---------- Location / string ----------
|
||||
return TLV.create_TLV(TLV.UTF1, "XX") # no location
|
||||
elif attribute == 0x0007 # ---------- HardwareVersion / u16 ----------
|
||||
return TLV.create_TLV(TLV.U2, 0)
|
||||
elif attribute == 0x0008 # ---------- HardwareVersionString / string ----------
|
||||
return TLV.create_TLV(TLV.UTF1, tasmota.cmd("Status 2")['StatusFWR']['Hardware'])
|
||||
elif attribute == 0x0009 # ---------- SoftwareVersion / u32 ----------
|
||||
return TLV.create_TLV(TLV.U2, 0)
|
||||
elif attribute == 0x000A # ---------- SoftwareVersionString / string ----------
|
||||
return TLV.create_TLV(TLV.UTF1, tasmota.cmd("Status 2")['StatusFWR']['Version'])
|
||||
end
|
||||
|
||||
# ====================================================================================================
|
||||
elif cluster == 0x003F # ========== Group Key Management Cluster 11.2 p.572 ==========
|
||||
# TODO
|
||||
|
||||
# ====================================================================================================
|
||||
elif cluster == 0x002B # ========== Localization Configuration Cluster 11.3 p.580 ==========
|
||||
|
||||
if attribute == 0x0000 # ---------- ActiveLocale / string ----------
|
||||
return TLV.create_TLV(TLV.UTF1, tasmota.locale())
|
||||
elif attribute == 0x0001 # ---------- SupportedLocales / list[string] ----------
|
||||
var locl = TLV.Matter_TLV_list()
|
||||
locl.add_TLV(nil, TLV.UTF1, tasmota.locale())
|
||||
return locl
|
||||
end
|
||||
|
||||
# ====================================================================================================
|
||||
elif cluster == 0x002C # ========== Time Format Localization Cluster 11.4 p.581 ==========
|
||||
|
||||
if attribute == 0x0000 # ---------- HourFormat / HourFormat ----------
|
||||
return TLV.create_TLV(TLV.U1, 1) # 1 = 24hr
|
||||
elif attribute == 0x0001 # ---------- ActiveCalendarType / CalendarType ----------
|
||||
return TLV.create_TLV(TLV.U1, 4) # 4 = Gregorian
|
||||
elif attribute == 0x0002 # ---------- SupportedCalendarTypes / list[CalendarType] ----------
|
||||
var callist = TLV.Matter_TLV_list()
|
||||
callist.add_TLV(nil, TLV.create_TLV(TLV.U1, 4))
|
||||
return callist
|
||||
end
|
||||
|
||||
# ====================================================================================================
|
||||
elif cluster == 0x0031 # ========== Network Commissioning Cluster cluster 11.8 p.606 ==========
|
||||
if attribute == 0x0003 # ---------- ConnectMaxTimeSeconds / uint8 ----------
|
||||
return TLV.create_TLV(TLV.U1, 30) # 30 - value taking from example in esp-matter
|
||||
elif attribute == 0xFFFC # ---------- FeatureMap / map32 ----------
|
||||
return TLV.create_TLV(TLV.U4, 0) # 15s ??? TOOD what should we put here?
|
||||
end
|
||||
end
|
||||
# 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(msg, val, ctx)
|
||||
import crypto
|
||||
var TLV = matter.TLV
|
||||
var cluster = ctx.cluster
|
||||
var command = ctx.command
|
||||
var session = msg.session
|
||||
if cluster == 0x0030 # ========== GeneralCommissioning cluster 11.9 p.627 ==========
|
||||
|
||||
if command == 0x0000 # ---------- ArmFailSafe ----------
|
||||
# create ArmFailSafeResponse
|
||||
# ID=1
|
||||
# 0=ErrorCode (OK=0)
|
||||
# 1=DebugText
|
||||
var ExpiryLengthSeconds = val.findsubval(0, 900)
|
||||
var Breadcrumb = val.findsubval(1, 0)
|
||||
session.breadcrumb = Breadcrumb
|
||||
|
||||
var afsr = TLV.Matter_TLV_struct()
|
||||
afsr.add_TLV(0, TLV.U1, 0) # ErrorCode = OK
|
||||
afsr.add_TLV(1, TLV.UTF1, "") # DebugText = ""
|
||||
ctx.command = 0x01 # ArmFailSafeResponse
|
||||
return afsr
|
||||
|
||||
elif command == 0x0002 # ---------- SetRegulatoryConfig ----------
|
||||
var NewRegulatoryConfig = val.findsubval(0) # RegulatoryLocationType Enum
|
||||
var CountryCode = val.findsubval(1, "XX")
|
||||
var Breadcrumb = val.findsubval(2, 0)
|
||||
session.breadcrumb = Breadcrumb
|
||||
# create SetRegulatoryConfigResponse
|
||||
# ID=1
|
||||
# 0=ErrorCode (OK=0)
|
||||
# 1=DebugText
|
||||
var srcr = TLV.Matter_TLV_struct()
|
||||
srcr.add_TLV(0, TLV.U1, 0) # ErrorCode = OK
|
||||
srcr.add_TLV(1, TLV.UTF1, "") # DebugText = ""
|
||||
ctx.command = 0x03 # SetRegulatoryConfigResponse
|
||||
return srcr
|
||||
|
||||
elif command == 0x0004 # ---------- CommissioningComplete p.636 ----------
|
||||
# no data
|
||||
session.breadcrumb = 0 # clear breadcrumb
|
||||
session.set_no_expiration()
|
||||
|
||||
# create CommissioningCompleteResponse
|
||||
# ID=1
|
||||
# 0=ErrorCode (OK=0)
|
||||
# 1=DebugText
|
||||
var ccr = TLV.Matter_TLV_struct()
|
||||
ccr.add_TLV(0, TLV.U1, 0) # ErrorCode = OK
|
||||
ccr.add_TLV(1, TLV.UTF1, "") # DebugText = ""
|
||||
ctx.command = 0x05 # CommissioningCompleteResponse
|
||||
|
||||
self.device.start_commissioning_complete_deferred(session)
|
||||
return ccr # trigger a standalone ack
|
||||
end
|
||||
|
||||
elif cluster == 0x003E # ========== Node Operational Credentials Cluster 11.17 p.704 ==========
|
||||
|
||||
if command == 0x0002 # ---------- CertificateChainRequest ----------
|
||||
var CertificateType = val.findsubval(0) # CertificateChainType Enum 1=DACCertificate 2=PAICertificate
|
||||
if CertificateType != 1 && CertificateType != 2
|
||||
ctx.status = matter.UNSUPPORTED_COMMAND
|
||||
return nil
|
||||
end
|
||||
# create CertificateChainResponse
|
||||
# ID=1
|
||||
# 0=Certificate (octstr)
|
||||
var ccr = TLV.Matter_TLV_struct()
|
||||
ccr.add_TLV(0, TLV.B2, CertificateType == 1 ? matter.DAC_Cert_FFF1_8000() : matter.PAI_Cert_FFF1()) # send DAC_Cert_FFF1_8000 or PAI_Cert_FFF1
|
||||
ctx.command = 0x03 # CertificateChainResponse
|
||||
return ccr
|
||||
|
||||
elif command == 0x0000 # ---------- AttestationRequest ----------
|
||||
var AttestationNonce = val.findsubval(0) # octstr
|
||||
if size(AttestationNonce) != 32 return nil end # check size on nonce
|
||||
ctx.command = 0x01 # AttestationResponse
|
||||
|
||||
# build Attestation Elements 11.17.5.4 p.707
|
||||
var att_elts = TLV.Matter_TLV_struct()
|
||||
att_elts.add_TLV(1, TLV.B2, matter.CD_FFF1_8000()) # certification_declaration
|
||||
att_elts.add_TLV(2, TLV.B1, AttestationNonce) # attestation_nonce
|
||||
att_elts.add_TLV(3, TLV.U4, tasmota.rtc()['utc']) # timestamp in epoch-s
|
||||
var attestation_message = att_elts.encode()
|
||||
|
||||
var ac = session.get_ac()
|
||||
var attestation_tbs = attestation_message + ac
|
||||
tasmota.log("MTR: attestation_tbs=" + attestation_tbs.tohex(), 3)
|
||||
|
||||
var attestation_signature = crypto.EC_P256().ecdsa_sign_sha256(matter.DAC_Priv_FFF1_8000(), attestation_tbs)
|
||||
|
||||
# create AttestationResponse
|
||||
# 0=AttestationElements (octstr max 900 bytes)
|
||||
# 1=AttestationSignature (octstr 64)
|
||||
var ar = TLV.Matter_TLV_struct()
|
||||
ar.add_TLV(0, TLV.B2, attestation_message) # AttestationElements
|
||||
ar.add_TLV(1, TLV.B1, attestation_signature) # AttestationElements
|
||||
ctx.command = 0x01 # AttestationResponse
|
||||
return ar
|
||||
|
||||
elif command == 0x0004 # ---------- CSRRequest ----------
|
||||
var CSRNonce = val.findsubval(0) # octstr 32
|
||||
if size(CSRNonce) != 32 return nil end # check size on nonce
|
||||
var IsForUpdateNOC = val.findsubval(1, false) # bool
|
||||
|
||||
var csr = session.gen_CSR()
|
||||
|
||||
var nocsr_elements = TLV.Matter_TLV_struct()
|
||||
nocsr_elements.add_TLV(1, TLV.B2, csr)
|
||||
nocsr_elements.add_TLV(2, TLV.B1, CSRNonce)
|
||||
var nocsr_elements_message = nocsr_elements.encode()
|
||||
# sign with attestation challenge
|
||||
var nocsr_tbs = nocsr_elements_message + session.get_ac()
|
||||
tasmota.log("MTR: nocsr_tbs=" + nocsr_tbs.tohex(), 3)
|
||||
var attestation_signature = crypto.EC_P256().ecdsa_sign_sha256(matter.DAC_Priv_FFF1_8000(), nocsr_tbs)
|
||||
|
||||
# create CSRResponse
|
||||
# 0=NOCSRElements (octstr max 900 bytes)
|
||||
# 1=AttestationSignature (octstr 64)
|
||||
var csrr = TLV.Matter_TLV_struct()
|
||||
csrr.add_TLV(0, TLV.B2, nocsr_elements_message) # AttestationElements
|
||||
csrr.add_TLV(1, TLV.B1, attestation_signature) # AttestationElements
|
||||
ctx.command = 0x05 # CSRResponse
|
||||
return csrr
|
||||
|
||||
elif command == 0x000B # ---------- AddTrustedRootCertificate ----------
|
||||
var RootCACertificate = val.findsubval(0) # octstr 400 max
|
||||
session.set_ca(RootCACertificate)
|
||||
tasmota.log("MTR: received ca_root="+RootCACertificate.tohex(), 3)
|
||||
ctx.status = matter.SUCCESS # OK
|
||||
return nil # trigger a standalone ack
|
||||
|
||||
elif command == 0x0006 # ---------- AddNOC ----------
|
||||
var NOCValue = val.findsubval(0) # octstr max 400
|
||||
var ICACValue = val.findsubval(1) # octstr max 400
|
||||
var IpkValue = val.findsubval(2) # octstr max 16
|
||||
var CaseAdminSubject = val.findsubval(3)
|
||||
var AdminVendorId = val.findsubval(4)
|
||||
|
||||
if session.get_ca() == nil
|
||||
tasmota.log("MTR: Error: AdNOC without CA", 2)
|
||||
return nil
|
||||
end
|
||||
|
||||
session.set_noc(NOCValue, ICACValue)
|
||||
session.set_ipk_epoch_key(IpkValue)
|
||||
session.admin_subject = CaseAdminSubject
|
||||
session.admin_vendor = AdminVendorId
|
||||
|
||||
# extract important information from NOC
|
||||
var noc_cert = matter.TLV.parse(NOCValue)
|
||||
var dnlist = noc_cert.findsub(6)
|
||||
var fabric = dnlist.findsubval(21)
|
||||
var deviceid = dnlist.findsubval(17)
|
||||
if !fabric || !deviceid
|
||||
tasmota.log("MTR: Error: no fabricid nor deviceid in NOC certificate", 2)
|
||||
return false
|
||||
end
|
||||
# convert fo bytes(8)
|
||||
if type(fabric) == 'int' fabric = int64(fabric).tobytes() else fabric = fabric.tobytes() end
|
||||
if type(deviceid) == 'int' deviceid = int64(deviceid).tobytes() else deviceid = deviceid.tobytes() end
|
||||
|
||||
var root_ca = matter.TLV.parse(session.get_ca()).findsubval(9) # extract public key from ca
|
||||
root_ca = root_ca[1..] # remove first byte as per Matter specification
|
||||
var info = bytes().fromstring("CompressedFabric") # as per spec, 4.3.2.2 p.99
|
||||
var hk = crypto.HKDF_SHA256()
|
||||
var fabric_rev = fabric.copy().reverse()
|
||||
var k_fabric = hk.derive(root_ca, fabric_rev, info, 8)
|
||||
session.set_fabric_device(fabric, deviceid, k_fabric)
|
||||
|
||||
# move to next step
|
||||
self.device.start_operational_dicovery_deferred(session)
|
||||
# create NOCResponse
|
||||
# 0=StatusCode
|
||||
# 1=FabricIndex (1-254) (opt)
|
||||
# 2=DebugText (opt)
|
||||
var nocr = TLV.Matter_TLV_struct()
|
||||
nocr.add_TLV(0, TLV.U1, matter.SUCCESS) # Status
|
||||
nocr.add_TLV(1, TLV.U1, 1) # fabric-index
|
||||
ctx.command = 0x08 # NOCResponse
|
||||
return nocr
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
matter.Plugin_core = Matter_Plugin_core
|
||||
|
574
lib/libesp32/berry_matter/src/embedded/Matter_Session.be
Normal file
574
lib/libesp32/berry_matter/src/embedded/Matter_Session.be
Normal file
@ -0,0 +1,574 @@
|
||||
#
|
||||
# Matter_Session.be - Support for Matter Sessions and Session Store
|
||||
#
|
||||
# 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/>.
|
||||
#
|
||||
|
||||
import matter
|
||||
|
||||
#@ solidify:Matter_Session,weak
|
||||
#@ solidify:Matter_Session_Store,weak
|
||||
|
||||
#################################################################################
|
||||
# Matter_Session class
|
||||
#
|
||||
# Session is refered by remote_session_id once a session is established
|
||||
# It can also be retrived by `source_node_id` when `local_session_id` is 0
|
||||
#
|
||||
# By convention, names starting with `_` are not persisted
|
||||
#################################################################################
|
||||
class Matter_Session
|
||||
static var __PASE = 1 # PASE authentication in progress
|
||||
static var __CASE = 2 # CASE authentication in progress
|
||||
var __store # reference back to session store
|
||||
# mode for Session. Can be PASE=1, CASE=2, Established=10 none=0
|
||||
var mode
|
||||
# sesions
|
||||
var local_session_id # id for the current local session, starts with 1
|
||||
var initiator_session_id # id used to respond to the initiator
|
||||
var session_timestamp # timestamp (UTC) when the session was created
|
||||
var source_node_id # source node if bytes(8) (opt, used only when session is not established)
|
||||
# session_ids when the session will be active
|
||||
var _future_initiator_session_id
|
||||
var _future_local_session_id
|
||||
# counters
|
||||
var counter_rcv # counter for incoming messages
|
||||
var counter_snd # counter for outgoing messages
|
||||
# non-session counters
|
||||
var _counter_insecure_rcv # counter for incoming messages
|
||||
var _counter_insecure_snd # counter for outgoing messages
|
||||
# encryption keys and challenges
|
||||
var i2rkey # key initiator to receiver (incoming)
|
||||
var r2ikey # key receiver to initiator (outgoing)
|
||||
var attestation_challenge # Attestation challenge
|
||||
var peer_node_id
|
||||
# breadcrumb
|
||||
var breadcrumb # breadcrumb attribute for this session
|
||||
# our own private key
|
||||
var no_private_key # private key of the device certificate (generated at commissioning)
|
||||
# NOC information
|
||||
var root_ca_certificate # root certificate of the initiator
|
||||
var noc # Node Operational Certificate in TLV Matter Certificate
|
||||
var icac # Initiator CA Certificate in TLV Matter Certificate
|
||||
var ipk_epoch_key # timestamp
|
||||
# CASE
|
||||
var resumption_id # bytes(16)
|
||||
var shared_secret # ECDH shared secret used in CASE
|
||||
# Information extracted from `noc`
|
||||
var fabric # fabric identifier as bytes(8) little endian
|
||||
var fabric_compressed # comrpessed fabric identifier, hashed with root_ca public key
|
||||
var deviceid # our own device id bytes(8) little endian
|
||||
# Admin info extracted from NOC/ICAC
|
||||
var admin_subject
|
||||
var admin_vendor
|
||||
# Previous CASE messages for Transcript hash
|
||||
var _Msg1, _Msg2
|
||||
# Expiration
|
||||
var _persist # do we persist this sessions or is it remporary
|
||||
var expiration # if not `nil` the entry is removed after this timestamp
|
||||
|
||||
# Group Key Derivation
|
||||
static var __GROUP_KEY = "GroupKey v1.0" # starting with double `_` means it's not writable
|
||||
|
||||
#############################################################
|
||||
def init(store, local_session_id, initiator_session_id)
|
||||
self.__store = store
|
||||
self.mode = 0
|
||||
self.local_session_id = local_session_id
|
||||
self.initiator_session_id = initiator_session_id
|
||||
self.counter_rcv = matter.Counter()
|
||||
self.counter_snd = matter.Counter()
|
||||
self._counter_insecure_rcv = matter.Counter()
|
||||
self._counter_insecure_snd = matter.Counter()
|
||||
self.breadcrumb = int64()
|
||||
end
|
||||
|
||||
#############################################################
|
||||
# Close the current PASE/CASE session to be re-negociated
|
||||
#
|
||||
def close()
|
||||
# close the PASE session, it will be re-opened with a CASE session
|
||||
var persist_save = self._persist
|
||||
self.local_session_id = self._future_local_session_id
|
||||
self.initiator_session_id = self._future_initiator_session_id
|
||||
self.source_node_id = nil
|
||||
self.counter_rcv.reset()
|
||||
self.counter_snd.reset()
|
||||
self.i2rkey = nil
|
||||
self.r2ikey = nil
|
||||
self.attestation_challenge = nil
|
||||
# clear any attribute starting with `_`
|
||||
import introspect
|
||||
for k : introspect.members(self)
|
||||
var v = introspect.get(self, k)
|
||||
if type(v) != 'function' && type(v) != 'instance' && k[0] == '_' && k[1] != '_'
|
||||
self.(k) = nil
|
||||
end
|
||||
end
|
||||
self._persist = persist_save
|
||||
# self._future_initiator_session_id = nil
|
||||
# self._future_local_session_id = nil
|
||||
end
|
||||
|
||||
#############################################################
|
||||
def set_mode(mode)
|
||||
self.mode = mode
|
||||
end
|
||||
def set_keys(i2r, r2i, ac, st)
|
||||
self.i2rkey = i2r
|
||||
self.r2ikey = r2i
|
||||
self.attestation_challenge = ac
|
||||
self.session_timestamp = st
|
||||
end
|
||||
def set_ca(ca)
|
||||
self.root_ca_certificate = ca
|
||||
end
|
||||
def set_noc(noc, icac)
|
||||
self.noc = noc
|
||||
self.icac = icac
|
||||
end
|
||||
def set_ipk_epoch_key(ipk_epoch_key)
|
||||
self.ipk_epoch_key = ipk_epoch_key
|
||||
end
|
||||
def set_fabric_device(fabric, deviceid, fc)
|
||||
self.fabric = fabric
|
||||
self.deviceid = deviceid
|
||||
self.fabric_compressed = fc
|
||||
self.__store.remove_redundant_session(self)
|
||||
end
|
||||
def set_persist(p)
|
||||
self._persist = bool(p)
|
||||
end
|
||||
|
||||
#############################################################
|
||||
def get_mode()
|
||||
return self.mode
|
||||
end
|
||||
def get_i2r()
|
||||
return self.i2rkey
|
||||
end
|
||||
def get_r2i()
|
||||
return self.r2ikey
|
||||
end
|
||||
def get_ac()
|
||||
return self.attestation_challenge
|
||||
end
|
||||
def get_ca()
|
||||
return self.root_ca_certificate
|
||||
end
|
||||
def get_ca_pub()
|
||||
if self.root_ca_certificate
|
||||
var m = matter.TLV.parse(self.root_ca_certificate)
|
||||
return m.findsubval(9)
|
||||
end
|
||||
end
|
||||
def get_noc() return self.noc end
|
||||
def get_icac() return self.icac end
|
||||
def get_ipk_epoch_key() return self.ipk_epoch_key end
|
||||
def get_fabric() return self.fabric end
|
||||
def get_deviceid() return self.deviceid end
|
||||
def get_fabric_compressed() return self.fabric_compressed end
|
||||
|
||||
#############################################################
|
||||
# Generate a private key (or retrieve it)
|
||||
def get_pk()
|
||||
if !self.no_private_key
|
||||
import crypto
|
||||
self.no_private_key = crypto.random(32)
|
||||
end
|
||||
return self.no_private_key
|
||||
end
|
||||
|
||||
#############################################################
|
||||
# Operational Group Key Derivation, 4.15.2, p.182
|
||||
def get_ipk_group_key()
|
||||
if self.ipk_epoch_key == nil || self.fabric_compressed == nil return nil end
|
||||
import crypto
|
||||
var hk = crypto.HKDF_SHA256()
|
||||
var info = bytes().fromstring(self.__GROUP_KEY)
|
||||
var hash = hk.derive(self.ipk_epoch_key, self.fabric_compressed, info, 16)
|
||||
return hash
|
||||
end
|
||||
|
||||
#############################################################
|
||||
# set absolute time for expiration
|
||||
def set_no_expiration()
|
||||
self.expiration = nil
|
||||
end
|
||||
|
||||
#############################################################
|
||||
# set absolute time for expiration
|
||||
def set_expire_time(t)
|
||||
self.expiration = int(t)
|
||||
end
|
||||
|
||||
#############################################################
|
||||
# set relative time in the future for expiration (in seconds)
|
||||
def set_expire_in_seconds(s, now)
|
||||
if s == nil return end
|
||||
if now == nil now = tasmota.rtc()['utc'] end
|
||||
self.set_expire_time(now + s)
|
||||
end
|
||||
|
||||
#############################################################
|
||||
# set relative time in the future for expiration (in seconds)
|
||||
# returns `true` if expiration date has been reached
|
||||
def has_expired(now)
|
||||
if now == nil now = tasmota.rtc()['utc'] end
|
||||
if self.expiration != nil
|
||||
return now >= self.expiration
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
#############################################################
|
||||
# to_json()
|
||||
#
|
||||
# convert a single entry as json
|
||||
# returns a JSON string
|
||||
#############################################################
|
||||
def tojson()
|
||||
import json
|
||||
import string
|
||||
import introspect
|
||||
|
||||
var keys = []
|
||||
for k : introspect.members(self)
|
||||
var v = introspect.get(self, k)
|
||||
if type(v) != 'function' && k[0] != '_' keys.push(k) end
|
||||
end
|
||||
keys = matter.sort(keys)
|
||||
|
||||
var r = []
|
||||
for k : keys
|
||||
var v = introspect.get(self, k)
|
||||
if v == nil continue end
|
||||
|
||||
if k == "counter_rcv" v = v.val()
|
||||
elif k == "counter_snd" v = v.val() + 256 # take a margin to avoid reusing the same counter
|
||||
end
|
||||
|
||||
if isinstance(v, bytes) v = "$$" + v.tob64() end # bytes
|
||||
# if isinstance(v, bytes) v = "0x" + v.tohex() end
|
||||
|
||||
# if type(v) == 'string' v = string.escape(v, true) end
|
||||
r.push(string.format("%s:%s", json.dump(str(k)), json.dump(v)))
|
||||
end
|
||||
return "{" + r.concat(",") + "}"
|
||||
end
|
||||
|
||||
#############################################################
|
||||
# fromjson()
|
||||
#
|
||||
# reads a map and load arguments
|
||||
# returns an new instance of session
|
||||
#############################################################
|
||||
static def fromjson(store, values)
|
||||
import string
|
||||
import introspect
|
||||
var self = matter.Session(store)
|
||||
|
||||
for k:values.keys()
|
||||
var v = values[k]
|
||||
if k == "counter_rcv" self.counter_rcv.reset(int(v))
|
||||
elif k == "counter_snd" self.counter_snd.reset(int(v))
|
||||
else
|
||||
# standard values
|
||||
if type(v) == 'string'
|
||||
if string.find(v, "0x") == 0 # treat as bytes
|
||||
introspect.set(self, k, bytes().fromhex(v[2..]))
|
||||
elif string.find(v, "$$") == 0 # treat as bytes
|
||||
introspect.set(self, k, bytes().fromb64(v[2..]))
|
||||
else
|
||||
introspect.set(self, k, v)
|
||||
end
|
||||
else
|
||||
introspect.set(self, k, v)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
#############################################################
|
||||
# Callback to Session store
|
||||
def save()
|
||||
self.__store.save()
|
||||
end
|
||||
|
||||
#############################################################
|
||||
def gen_CSR()
|
||||
# Create CSR
|
||||
# See 6.4.7. Node Operational Certificate Signing Request (NOCSR) p.302
|
||||
var pk = self.get_pk() # private key of device
|
||||
|
||||
# Example
|
||||
# 3081CA
|
||||
# 3070020100300E310C300A060355040A0C034353523059301306072A8648CE3D020106082A8648CE3D030107
|
||||
# PubKey=034200.043AEFB8D1F25813BE355920577971814827B24F2784A729297F88FBD998A59D29D439604678C42D2FA5DE4E9402C30376015E05DF0AD4A8737DCD4E6D03B11CF5
|
||||
# A000
|
||||
# 300C06082A8648CE3D0403020500
|
||||
# 034800
|
||||
# ECDSA=3045022054907C4F096B30EFEB56190E0F2AFAEE447991C927003185AD044D1A971BDEDD02210088FB7E44116FBD7DE5277890A3F3BC26ACC35441DF04FD0BBF02A369E751241D
|
||||
|
||||
import crypto
|
||||
var ec256 = crypto.EC_P256()
|
||||
var pub = ec256.public_key(pk)
|
||||
|
||||
var seg1 = bytes("3070020100300E310C300A060355040A0C034353523059301306072A8648CE3D020106082A8648CE3D030107034200")
|
||||
seg1 .. pub
|
||||
seg1 .. bytes("A000")
|
||||
var seg2 = bytes("300C06082A8648CE3D0403020500") # not mutable
|
||||
# compute signature in ECDSA format
|
||||
var sig = ec256.ecdsa_sign_sha256_asn1(pk, seg1)
|
||||
var seg3 = bytes(128)
|
||||
seg3.add(0x03, 1)
|
||||
seg3.add(size(sig)+1, 1)
|
||||
seg3.add(0x00, 1)
|
||||
seg3 .. sig
|
||||
# construct the global csr
|
||||
var seg_123_size = size(seg1) + size(seg2) + size(seg3)
|
||||
var csr = bytes(208)
|
||||
csr.add(0x30, 1)
|
||||
csr.add(0x81, 1)
|
||||
csr.add(seg_123_size & 0xFF, 1)
|
||||
csr .. seg1
|
||||
csr .. seg2
|
||||
csr .. seg3
|
||||
return csr
|
||||
end
|
||||
|
||||
end
|
||||
matter.Session = Matter_Session
|
||||
|
||||
|
||||
#################################################################################
|
||||
# Matter_Session_Store class
|
||||
#################################################################################
|
||||
class Matter_Session_Store
|
||||
var sessions
|
||||
static var FILENAME = "_matter_sessions.json"
|
||||
|
||||
#############################################################
|
||||
def init()
|
||||
self.sessions = []
|
||||
end
|
||||
|
||||
#############################################################
|
||||
# add session
|
||||
def create_session(local_session_id, initiator_session_id)
|
||||
var session = self.get_session_by_local_session_id(local_session_id)
|
||||
if session != nil self.remove_session(session) end
|
||||
session = matter.Session(self, local_session_id, initiator_session_id)
|
||||
self.sessions.push(session)
|
||||
return session
|
||||
end
|
||||
|
||||
#############################################################
|
||||
# add session
|
||||
def add_session(s, expires_in_seconds)
|
||||
if expires_in_seconds != nil
|
||||
s.set_expire_in_seconds(expires_in_seconds)
|
||||
end
|
||||
self.sessions.push(s)
|
||||
end
|
||||
|
||||
#############################################################
|
||||
def get_session_by_local_session_id(id)
|
||||
if id == nil return nil end
|
||||
var sz = size(self.sessions)
|
||||
var i = 0
|
||||
var sessions = self.sessions
|
||||
while i < sz
|
||||
if sessions[i].local_session_id == id return sessions[i] end
|
||||
i += 1
|
||||
end
|
||||
end
|
||||
|
||||
#############################################################
|
||||
def get_session_by_source_node_id(nodeid)
|
||||
if nodeid == nil return nil end
|
||||
var sz = size(self.sessions)
|
||||
var i = 0
|
||||
var sessions = self.sessions
|
||||
while i < sz
|
||||
if sessions[i].source_node_id == nodeid return sessions[i] end
|
||||
i += 1
|
||||
end
|
||||
end
|
||||
|
||||
#############################################################
|
||||
# Remove session by reference
|
||||
#
|
||||
def remove_session(s)
|
||||
var i = 0
|
||||
var sessions = self.sessions
|
||||
while i < size(self.sessions)
|
||||
if sessions[i] == s
|
||||
sessions.remove(i)
|
||||
else
|
||||
i += 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
#############################################################
|
||||
# Remove session by reference
|
||||
#
|
||||
# remove all other sessions that have the same:
|
||||
# fabric / deviceid / fc
|
||||
def remove_redundant_session(s)
|
||||
var i = 0
|
||||
var sessions = self.sessions
|
||||
while i < size(self.sessions)
|
||||
var session = sessions[i]
|
||||
if session != s && session.fabric == s.fabric && session.deviceid == s.deviceid #- && session.fabric_compressed == s.fabric_compressed -#
|
||||
sessions.remove(i)
|
||||
else
|
||||
i += 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
#############################################################
|
||||
# Generate a new local_session_id
|
||||
def gen_local_session_id()
|
||||
import crypto
|
||||
while true
|
||||
var candidate_local_session_id = crypto.random(2).get(0, 2)
|
||||
|
||||
if self.get_session_by_local_session_id(candidate_local_session_id) == nil
|
||||
return candidate_local_session_id
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
#############################################################
|
||||
# remove_expired
|
||||
#
|
||||
# Check is any session has expired
|
||||
def remove_expired()
|
||||
var dirty = false
|
||||
var i = 0
|
||||
var sessions = self.sessions
|
||||
while i < size(self.sessions)
|
||||
if sessions[i].has_expired()
|
||||
if sessions[i]._persist dirty = true end # do we need to save
|
||||
sessions.remove(i)
|
||||
else
|
||||
i += 1
|
||||
end
|
||||
end
|
||||
if dirty self.save() end
|
||||
end
|
||||
def every_second()
|
||||
self.remove_expired()
|
||||
end
|
||||
|
||||
#############################################################
|
||||
# find or create a session for unencrypted traffic
|
||||
# expires in `expire` seconds
|
||||
def find_session_source_id_unsecure(source_node_id, expire)
|
||||
var session = self.get_session_by_source_node_id(source_node_id)
|
||||
if session == nil
|
||||
session = matter.Session(self, 0, 0)
|
||||
session.source_node_id = source_node_id
|
||||
self.sessions.push(session)
|
||||
end
|
||||
session.set_expire_in_seconds(expire)
|
||||
return session
|
||||
end
|
||||
|
||||
#############################################################
|
||||
def save()
|
||||
import json
|
||||
self.remove_expired() # clean before saving
|
||||
|
||||
var j = []
|
||||
for v:self.sessions
|
||||
if v._persist
|
||||
j.push(v.tojson())
|
||||
end
|
||||
end
|
||||
var j_size = size(j)
|
||||
j = "[" + j.concat(",") + "]"
|
||||
|
||||
try
|
||||
import string
|
||||
var f = open(self.FILENAME, "w")
|
||||
f.write(j)
|
||||
f.close()
|
||||
tasmota.log(string.format("MTR: Saved %i session(s)", j_size), 2)
|
||||
return j
|
||||
except .. as e, m
|
||||
tasmota.log("MTR: Session_Store::save Exception:" + str(e) + "|" + str(m), 2)
|
||||
return j
|
||||
end
|
||||
end
|
||||
|
||||
#############################################################
|
||||
def load()
|
||||
import string
|
||||
try
|
||||
self.sessions = [] # remove any left-over
|
||||
var f = open(self.FILENAME)
|
||||
var s = f.read()
|
||||
f.close()
|
||||
|
||||
import json
|
||||
var j = json.load(s)
|
||||
s = nil
|
||||
tasmota.gc() # clean-up a potential long string
|
||||
|
||||
for v:j # iterate on values
|
||||
var session = matter.Session.fromjson(self, v)
|
||||
if session != nil
|
||||
self.add_session(session)
|
||||
end
|
||||
end
|
||||
|
||||
tasmota.log(string.format("MTR: Loaded %i session(s)", size(self.sessions)), 2)
|
||||
except .. as e, m
|
||||
if e != "io_error"
|
||||
tasmota.log("MTR: Session_Store::load Exception:" + str(e) + "|" + str(m), 2)
|
||||
end
|
||||
end
|
||||
self.remove_expired() # clean after load
|
||||
end
|
||||
end
|
||||
matter.Session_Store = Matter_Session_Store
|
||||
|
||||
#-
|
||||
|
||||
# Unit test
|
||||
var s = Matter_Session(1,2)
|
||||
s.counter_rcv.validate(0x100, false)
|
||||
s.counter_snd.validate(0x1000, false)
|
||||
s.source_node_id = bytes("1122334455667788")
|
||||
assert(s.tojson() == '{"breadcrumb":"0","counter_rcv":256,"counter_snd":4352,"initiator_session_id":2,"local_session_id":1,"source_node_id":"0x1122334455667788"}')
|
||||
|
||||
var ss = Matter_Session_Store()
|
||||
ss.add_session(s)
|
||||
var j = ss.save()
|
||||
assert(j == '{"1":{"breadcrumb":"0","counter_rcv":256,"counter_snd":4352,"initiator_session_id":2,"local_session_id":1,"source_node_id":"0x1122334455667788"}}')
|
||||
|
||||
|
||||
var ss = Matter_Session_Store()
|
||||
ss.load()
|
||||
|
||||
-#
|
874
lib/libesp32/berry_matter/src/embedded/Matter_TLV.be
Normal file
874
lib/libesp32/berry_matter/src/embedded/Matter_TLV.be
Normal file
@ -0,0 +1,874 @@
|
||||
#
|
||||
# Matter_TLV.be - implements the encoding and decoding of Matter TLV structures (Tag/Lenght/Value) Appendix A.
|
||||
#
|
||||
# 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/>.
|
||||
#
|
||||
|
||||
# Support for Matter Protocol: TLV encoding and decoding
|
||||
|
||||
import matter
|
||||
|
||||
#@ solidify:Matter_TLV.Matter_TLV_item,weak
|
||||
#@ solidify:Matter_TLV.Matter_TLV_list,weak
|
||||
#@ solidify:Matter_TLV.Matter_TLV_struct,weak
|
||||
#@ solidify:Matter_TLV.Matter_TLV_array,weak
|
||||
#@ solidify:Matter_TLV,weak
|
||||
|
||||
class Matter_TLV
|
||||
static var _type = [
|
||||
'i1', 'i2', 'i4', 'i8', 'u1', 'u2', 'u4', 'u8', # signed and unsigned 0x00-0x07
|
||||
'bool', 'bool', 'float', 'double', # 0x08-0x0B
|
||||
'UTF1', 'UTF2', 'UTF4', 'UTF8', # 0x0C-0x0F
|
||||
'b1', 'b2', 'b4', 'b8', # 0x10-0x13
|
||||
'null', 'struct', 'array', 'list', 'end' # 0x14-0x18
|
||||
# all other are reserved
|
||||
]
|
||||
|
||||
static var _len = [
|
||||
1, 2, 4, 8, 1, 2, 4, 8,
|
||||
0, 0, 4, 8,
|
||||
-1, -2, -4, -8,
|
||||
-1, -2, -4, -8,
|
||||
0, -99, -99, -99, 0
|
||||
]
|
||||
|
||||
# type values (enum like)
|
||||
static var I1 = 0x00
|
||||
static var I2 = 0x01
|
||||
static var I4 = 0x02
|
||||
static var I8 = 0x03
|
||||
static var U1 = 0x04
|
||||
static var U2 = 0x05
|
||||
static var U4 = 0x06
|
||||
static var U8 = 0x07
|
||||
static var BOOL = 0x08 # when encoding, use indifferentiate
|
||||
static var BFALSE = 0x08
|
||||
static var BTRUE = 0x09
|
||||
static var FLOAT = 0x0A
|
||||
static var DOUBLE = 0x0B
|
||||
static var UTF1 = 0x0C
|
||||
static var UTF2 = 0x0D
|
||||
static var UTF4 = 0x0E
|
||||
static var UTF8 = 0x0F
|
||||
static var B1 = 0x10
|
||||
static var B2 = 0x11
|
||||
static var B4 = 0x12
|
||||
static var B8 = 0x13
|
||||
static var NULL = 0x14
|
||||
static var STRUCT = 0x15
|
||||
static var ARRAY = 0x16
|
||||
static var LIST = 0x17
|
||||
static var EOC = 0x18
|
||||
|
||||
#################################################################################
|
||||
# Matter_TLV_item class
|
||||
#################################################################################
|
||||
static class Matter_TLV_item
|
||||
# we keep a shortcut reference to the Matter_TLV class
|
||||
static var TLV = Matter_TLV
|
||||
# parent tag to inherit vendor/profile/tag
|
||||
var parent
|
||||
var next_idx # next idx in buffer (when parsing)
|
||||
# tags
|
||||
var tag_vendor # 16 bit VendorID [opt]
|
||||
var tag_profile # 16 bit profile number [opt]
|
||||
var tag_number # 32 bit tag number
|
||||
var tag_sub # context specific tag 8 bit [opt]
|
||||
# type
|
||||
var typ # TLV type number, set at decoding, mandatory for encoding
|
||||
# value
|
||||
var val # multi-type: int, float, bool, bytes, map, list
|
||||
|
||||
#############################################################
|
||||
# constructor
|
||||
def init(parent)
|
||||
self.parent = parent
|
||||
end
|
||||
|
||||
#############################################################
|
||||
# neutral converter
|
||||
def to_TLV()
|
||||
return self
|
||||
end
|
||||
|
||||
#############################################################
|
||||
# create simple TLV
|
||||
static def create_TLV(t, value)
|
||||
if value != nil
|
||||
var v = _class() # parent is nil
|
||||
v.typ = t
|
||||
v.val = value
|
||||
return v
|
||||
end
|
||||
end
|
||||
|
||||
#############################################################
|
||||
# tostring
|
||||
#
|
||||
# We are trying to follow the official Matter way of printing TLV
|
||||
# Ex: '42U' or '1 = 42U' or '0xFFF1::0xDEED:0xAA55FEED = 42U'
|
||||
def tostring()
|
||||
import string
|
||||
# var s = "<instance: Matter_TLV_item("
|
||||
var s = ""
|
||||
try # any exception raised in `tostring()` causes a crash, so better catch it here
|
||||
|
||||
if self.tag_profile == -1
|
||||
s += "Matter::"
|
||||
if self.tag_number != nil s += string.format("0x%08X ", self.tag_number) end
|
||||
else
|
||||
if self.tag_vendor != nil s += string.format("0x%04X::", self.tag_vendor) end
|
||||
if self.tag_profile != nil s += string.format("0x%04X:", self.tag_profile) end
|
||||
if self.tag_number != nil s += string.format("0x%08X ", self.tag_number) end
|
||||
if self.tag_sub != nil s += string.format("%i ", self.tag_sub) end
|
||||
end
|
||||
|
||||
if size(s) > 0 s += "= " end
|
||||
|
||||
# print value
|
||||
if type(self.val) == 'int' s += string.format("%i", self.val)
|
||||
if self.typ >= self.TLV.U1 && self.typ <= self.TLV.U8 s += "U" end
|
||||
elif type(self.val) == 'bool' s += self.val ? "true" : "false"
|
||||
elif self.val == nil s += "null"
|
||||
elif type(self.val) == 'real' s += string.format("%g", self.val)
|
||||
elif type(self.val) == 'string' s += string.format('"%s"', self.val)
|
||||
elif isinstance(self.val, int64) s += self.val.tostring()
|
||||
if self.typ >= self.TLV.U1 && self.typ <= self.TLV.U8 s += "U" end
|
||||
elif type(self.val) == 'instance'
|
||||
s += string.format("%s", self.val.tohex())
|
||||
end
|
||||
|
||||
except .. as e, m
|
||||
return e + " " + m
|
||||
end
|
||||
return s
|
||||
end
|
||||
|
||||
#############################################################
|
||||
# parse a bytes() array from `idx`
|
||||
# args:
|
||||
# b: bytes() buffer
|
||||
# idx: starting index in the bytes() buffer
|
||||
# parent: (optional) the parent object to inherit tag values
|
||||
#
|
||||
# returns the next `idx` for the item following or `-1` if error
|
||||
# The next `idx` is also stored in `self.next_idx`
|
||||
def parse(b, idx)
|
||||
var item_type = self.typ
|
||||
# parse LV
|
||||
var TLV = self.TLV # cache value in register
|
||||
var item_len = TLV._len[item_type]
|
||||
|
||||
if item_len == 8 # i64 / u64 / double
|
||||
self.val = int64()
|
||||
self.val.frombytes(b, idx)
|
||||
idx += 8
|
||||
elif item_type == TLV.BFALSE || item_type == TLV.BTRUE # bool
|
||||
self.val = (item_type == TLV.BTRUE)
|
||||
elif item_type < TLV.U8 # i1/i2/i4 u1/u2/u4
|
||||
self.val = item_type <= TLV.I8 ? b.geti(idx, item_len) : b.get(idx, item_len)
|
||||
idx += item_len
|
||||
elif item_type == TLV.FLOAT # float
|
||||
self.val = b.getfloat(idx)
|
||||
idx += 4
|
||||
elif item_len >= -8 && item_len <= -1 # len prefix 1/2/4/8
|
||||
# TODO skip len == 8 for now
|
||||
var b_len = b.get(idx, -item_len)
|
||||
idx += -item_len
|
||||
self.val = b[idx .. idx + b_len - 1]
|
||||
idx += b_len
|
||||
if (item_type <= TLV.UTF8) self.val = self.val.asstring() end
|
||||
elif item_type == TLV.NULL # null
|
||||
# do nothing
|
||||
elif item_type == TLV.EOC
|
||||
tasmota.log("MTR: unexpected eoc", 3)
|
||||
else
|
||||
tasmota.log("MTR: unexpected type: " + str(item_type), 3)
|
||||
end
|
||||
self.next_idx = idx
|
||||
return idx
|
||||
end
|
||||
|
||||
#############################################################
|
||||
# encode TLV
|
||||
#
|
||||
# appends to the bytes() object
|
||||
def encode(b)
|
||||
var TLV = self.TLV
|
||||
if b == nil b = bytes() end # start new buffer if none passed
|
||||
|
||||
# special case for bool
|
||||
# we need to change the type according to the value
|
||||
if self.typ == TLV.BFALSE || self.typ == TLV.BTRUE
|
||||
self.typ = bool(self.val) ? TLV.BTRUE : TLV.BFALSE
|
||||
# try to compress ints
|
||||
elif self.typ >= TLV.I2 && self.typ <= TLV.I4
|
||||
var i = int(self.val)
|
||||
if i <= 127 && i >= -128 self.typ = TLV.I1
|
||||
elif i <= 32767 && i >= -32768 self.typ = TLV.I2
|
||||
end
|
||||
elif self.typ >= TLV.U2 && self.typ <= TLV.U4
|
||||
var i = int(self.val)
|
||||
if i <= 255 && i >= 0 self.typ = TLV.U1
|
||||
elif i <= 65535 && i >= 0 self.typ = TLV.U2
|
||||
end
|
||||
elif self.typ >= TLV.B1 && self.typ <= TLV.B8 # encode length as minimum possible
|
||||
if size(self.val) <= 255
|
||||
self.typ = TLV.B1
|
||||
elif size(self.val) <= 65535
|
||||
self.typ = TLV.B2
|
||||
else
|
||||
self.typ = TLV.B4 # B4 is unlikely, B8 is impossible
|
||||
end
|
||||
elif self.typ >= TLV.UTF1 && self.typ <= TLV.UTF8
|
||||
if size(self.val) <= 255
|
||||
self.typ = TLV.UTF1
|
||||
elif size(self.val) <= 65535
|
||||
self.typ = TLV.UTF2
|
||||
else
|
||||
self.typ = TLV.UTF4 # UTF4 is unlikely, UTF8 is impossible
|
||||
end
|
||||
end
|
||||
|
||||
# encode tag and type
|
||||
self._encode_tag(b)
|
||||
# encode value
|
||||
|
||||
if self.typ == TLV.I1 || self.typ == TLV.U1
|
||||
b.add(int(self.val), 1)
|
||||
elif self.typ == TLV.I2 || self.typ == TLV.U2
|
||||
b.add(int(self.val), 2)
|
||||
elif self.typ == TLV.I4 || self.typ == TLV.U4
|
||||
b.add(int(self.val), 4)
|
||||
elif self.typ == TLV.I8 || self.typ == TLV.U8
|
||||
var i64 = self.val
|
||||
if !isinstance(i64, int64)
|
||||
i64 = int64(int(self.val))
|
||||
end
|
||||
b .. i64.tobytes()
|
||||
elif self.typ == TLV.BFALSE || self.typ == TLV.BTRUE
|
||||
# push nothing
|
||||
elif self.typ == TLV.FLOAT
|
||||
var idx = size(b)
|
||||
b.add(0, 4)
|
||||
b.setfloat(idx, real(self.val))
|
||||
elif self.typ == TLV.DOUBLE
|
||||
raise "value_error", "Unsupported type TLV.DOUBLE"
|
||||
elif self.typ == TLV.UTF1
|
||||
if size(self.val) > 255 raise "value_error", "string too big" end
|
||||
b.add(size(self.val), 1)
|
||||
b..bytes().fromstring(str(self.val))
|
||||
elif self.typ == TLV.UTF2
|
||||
if size(self.val) > 65535 raise "value_error", "string too big" end
|
||||
b.add(size(self.val), 2)
|
||||
b..bytes().frostring(str(self.val))
|
||||
elif self.typ == TLV.B1
|
||||
if size(self.val) > 255 raise "value_error", "bytes too big" end
|
||||
b.add(size(self.val), 1)
|
||||
b..self.val
|
||||
elif self.typ == TLV.B2
|
||||
if size(self.val) > 65535 raise "value_error", "bytes too big" end
|
||||
b.add(size(self.val), 2)
|
||||
b..self.val
|
||||
elif self.typ == TLV.NULL
|
||||
# push nothing
|
||||
else
|
||||
raise "value_error", "unsupported type " + str(self.typ)
|
||||
end
|
||||
|
||||
return b
|
||||
end
|
||||
|
||||
#############################################################
|
||||
# internal_function
|
||||
# encode Tag+Type as the first bytes
|
||||
def _encode_tag(b)
|
||||
var tag_number = self.tag_number != nil ? self.tag_number : 0
|
||||
var tag_huge = (tag_number >= 65536) || (tag_number < 0)
|
||||
var tag_control = 0x00
|
||||
if self.tag_vendor != nil
|
||||
# full encoding
|
||||
if tag_huge
|
||||
b.add(0xE0 + self.typ, 1)
|
||||
b.add(self.tag_vendor, 2)
|
||||
b.add(self.tag_profile, 2)
|
||||
b.add(self.tag_number, 4)
|
||||
else
|
||||
b.add(0xC0 + self.typ, 1)
|
||||
b.add(self.tag_vendor, 2)
|
||||
b.add(self.tag_profile, 2)
|
||||
b.add(self.tag_number, 2)
|
||||
end
|
||||
elif self.tag_profile == -1 # Matter Common profile
|
||||
if tag_huge
|
||||
b.add(0x60 + self.typ, 1)
|
||||
b.add(self.tag_number, 4)
|
||||
else
|
||||
b.add(0x40 + self.typ, 1)
|
||||
b.add(self.tag_number, 2)
|
||||
end
|
||||
elif self.tag_profile != nil
|
||||
if tag_huge
|
||||
b.add(0xA0 + self.typ, 1)
|
||||
b.add(self.tag_number, 4)
|
||||
else
|
||||
b.add(0x80 + self.typ, 1)
|
||||
b.add(self.tag_number, 2)
|
||||
end
|
||||
elif self.tag_sub != nil
|
||||
b.add(0x20 + self.typ, 1)
|
||||
b.add(self.tag_sub, 1)
|
||||
else # anonymous tag
|
||||
b.add(0x00 + self.typ, 1)
|
||||
end
|
||||
end
|
||||
|
||||
#############################################################
|
||||
# Compare the value index with an element
|
||||
# returns:
|
||||
# 1 if self is strictly greater than k
|
||||
# 0 if equal or lower
|
||||
def _cmp_gt(k)
|
||||
# compare tag_vendor
|
||||
if self.tag_vendor != nil
|
||||
if k.tag_vendor == nil return 1 end
|
||||
if self.tag_vendor > k.tag_vendor return 1 end
|
||||
if self.tag_vendor == k.tag_vendor
|
||||
if self.tag_profile > k.tag_profile return 1 end
|
||||
end
|
||||
# continue to tag comparison
|
||||
end
|
||||
|
||||
# Matter common profile
|
||||
if self.tag_profile == -1
|
||||
if k.tag_profile == nil return 1 end
|
||||
elif self.tag_profile == nil
|
||||
if k.tag_profile == -1 return 0 end
|
||||
end
|
||||
|
||||
if self.tag_number != nil
|
||||
if k.tag_number == nil return 1 end
|
||||
if self.tag_number > k.tag_number return 1 end
|
||||
return 0
|
||||
end
|
||||
|
||||
if self.tag_sub != nil
|
||||
if k.tag_sub == nil return 1 end
|
||||
if self.tag_sub > k.tag_sub return 1 end
|
||||
end
|
||||
|
||||
return 0
|
||||
end
|
||||
|
||||
#################################################################################
|
||||
# Simple insertion sort - sorts the list in place, and returns the list
|
||||
#################################################################################
|
||||
static def sort(l)
|
||||
# insertion sort
|
||||
for i:1..size(l)-1
|
||||
var k = l[i]
|
||||
var j = i
|
||||
while (j > 0) && (l[j-1]._cmp_gt(k) > 0)
|
||||
l[j] = l[j-1]
|
||||
j -= 1
|
||||
end
|
||||
l[j] = k
|
||||
end
|
||||
return l
|
||||
end
|
||||
|
||||
#############################################################
|
||||
# set parent
|
||||
def set_parent(parent)
|
||||
self.parent = parent
|
||||
end
|
||||
|
||||
#############################################################
|
||||
# Setters for tags
|
||||
def set_fulltag(vendor, profile, tag)
|
||||
self.tag_vendor = int(vendor)
|
||||
self.tag_profile = int(profile)
|
||||
self.tag_number = int(tag)
|
||||
self.tag_sub = nil
|
||||
end
|
||||
# set context specific
|
||||
def set_anonymoustag()
|
||||
self.set_fulltag()
|
||||
end
|
||||
# set common profile
|
||||
def set_commonprofile()
|
||||
self.set_fulltag(nil, -1, nil)
|
||||
end
|
||||
# set context specific
|
||||
def set_contextspecific(n)
|
||||
self.set_fulltag()
|
||||
self.tag_sub = int(n)
|
||||
end
|
||||
end
|
||||
|
||||
# class Matter_TLV_array var _ end
|
||||
# class Matter_TLV_struct var _ end
|
||||
|
||||
static class Matter_TLV_list : Matter_TLV_item
|
||||
#################################################################################
|
||||
def init(parent)
|
||||
super(self).init(parent)
|
||||
self.typ = self.TLV.LIST
|
||||
self.val = []
|
||||
end
|
||||
|
||||
#################################################################################
|
||||
def tostring()
|
||||
return self.tostring_inner(false, "[[", "]]")
|
||||
end
|
||||
|
||||
def tostring_inner(sorted, pre, post)
|
||||
import string
|
||||
var s = ""
|
||||
try
|
||||
|
||||
if self.tag_profile == -1
|
||||
s += "Matter::"
|
||||
if self.tag_number != nil s += string.format("0x%08X ", self.tag_number) end
|
||||
else
|
||||
if self.tag_vendor != nil s += string.format("0x%04X::", self.tag_vendor) end
|
||||
if self.tag_profile != nil s += string.format("0x%04X:", self.tag_profile) end
|
||||
if self.tag_number != nil s += string.format("0x%08X ", self.tag_number) end
|
||||
if self.tag_sub != nil s += string.format("%i ", self.tag_sub) end
|
||||
end
|
||||
|
||||
if size(s) > 0 s += "= " end
|
||||
|
||||
s += pre
|
||||
|
||||
# sort values
|
||||
var val_list = self.val.copy()
|
||||
if sorted
|
||||
self.sort(val_list)
|
||||
end
|
||||
|
||||
s += val_list.concat(", ")
|
||||
|
||||
s += post
|
||||
|
||||
except .. as e, m
|
||||
return e + " " + m
|
||||
end
|
||||
return s
|
||||
end
|
||||
|
||||
#################################################################################
|
||||
def parse(b, idx)
|
||||
# iterate until end of struct
|
||||
while b[idx] != self.TLV.EOC
|
||||
# read next
|
||||
var item = self.TLV.parse(b, idx, self)
|
||||
idx = item.next_idx
|
||||
|
||||
self.val.push(item)
|
||||
end
|
||||
idx += 1
|
||||
|
||||
self.next_idx = idx
|
||||
return idx
|
||||
end
|
||||
|
||||
#############################################################
|
||||
# encode TLV
|
||||
#
|
||||
# appends to the bytes() object
|
||||
def _encode_inner(b, is_struct)
|
||||
if b == nil b = bytes() end
|
||||
# encode tag and type
|
||||
self._encode_tag(b)
|
||||
# sort values
|
||||
var val_list = self.val.copy()
|
||||
if is_struct
|
||||
self.sort(val_list)
|
||||
end
|
||||
|
||||
# output each one after the other
|
||||
for v : val_list
|
||||
v.encode(b)
|
||||
end
|
||||
|
||||
# add 'end of container'
|
||||
b.add(self.TLV.EOC, 1)
|
||||
|
||||
return b
|
||||
end
|
||||
|
||||
#############################################################
|
||||
def encode(b)
|
||||
return self._encode_inner(b, false)
|
||||
end
|
||||
|
||||
#############################################################
|
||||
# Getters
|
||||
#
|
||||
# get by index
|
||||
def item(n)
|
||||
return self.val[n]
|
||||
end
|
||||
def setitem(n, v)
|
||||
self.val[n] = v
|
||||
end
|
||||
def push(v)
|
||||
self.val.push(v)
|
||||
end
|
||||
def size()
|
||||
return size(self.val)
|
||||
end
|
||||
|
||||
#############################################################
|
||||
# get by sub-tag, return nil if not found
|
||||
def findsub(n, v)
|
||||
for k : self.val
|
||||
if k.tag_sub == n return k end
|
||||
end
|
||||
return v
|
||||
end
|
||||
def findsubval(n, v)
|
||||
var r = self.findsub(n)
|
||||
if r != nil return r.val end
|
||||
return v
|
||||
end
|
||||
def findsubtyp(n)
|
||||
var r = self.findsub(n)
|
||||
if r != nil return r.typ end
|
||||
return nil
|
||||
end
|
||||
def getsub(n)
|
||||
var v = self.findsub(n)
|
||||
if v == nil raise "value_error", "sub not found" end
|
||||
return v
|
||||
end
|
||||
def getsubval(n)
|
||||
return self.getsub(n).val
|
||||
end
|
||||
|
||||
#############################################################
|
||||
# adders
|
||||
def add_TLV(tag, t, value)
|
||||
if value != nil
|
||||
var v = self.TLV.Matter_TLV_item(self)
|
||||
v.tag_sub = tag
|
||||
v.typ = t
|
||||
v.val = value
|
||||
self.val.push(v)
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
# add on object that implements `to_TLV()` and adds to the current container
|
||||
#
|
||||
# obj can be `nil`, in such case nothing happens
|
||||
# returns `self` to allow calls to be chained
|
||||
def add_obj(tag, obj)
|
||||
if obj != nil
|
||||
var value = obj.to_TLV()
|
||||
value.tag_sub = tag
|
||||
self.val.push(value)
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
def add_list(tag)
|
||||
var s = self.TLV.Matter_TLV_list(self)
|
||||
s.tag_sub = tag
|
||||
self.val.push(s)
|
||||
return s
|
||||
end
|
||||
|
||||
def add_array(tag)
|
||||
var s = self.TLV.Matter_TLV_array(self)
|
||||
s.tag_sub = tag
|
||||
self.val.push(s)
|
||||
return s
|
||||
end
|
||||
|
||||
def add_struct(tag)
|
||||
var s = self.TLV.Matter_TLV_struct(self)
|
||||
s.tag_sub = tag
|
||||
self.val.push(s)
|
||||
return s
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
#################################################################################
|
||||
# Matter_TLV_struct class
|
||||
#################################################################################
|
||||
static class Matter_TLV_struct : Matter_TLV_list
|
||||
def init(parent)
|
||||
super(self).init(parent)
|
||||
self.typ = self.TLV.STRUCT
|
||||
self.val = []
|
||||
end
|
||||
|
||||
#############################################################
|
||||
def tostring()
|
||||
return self.tostring_inner(true, "{", "}")
|
||||
end
|
||||
|
||||
#############################################################
|
||||
# encode TLV
|
||||
#
|
||||
# appends to the bytes() object
|
||||
def encode(b)
|
||||
return self._encode_inner(b, true)
|
||||
end
|
||||
end
|
||||
|
||||
#################################################################################
|
||||
# Matter_TLV_array class
|
||||
#################################################################################
|
||||
static class Matter_TLV_array : Matter_TLV_list
|
||||
def init(parent)
|
||||
super(self).init(parent)
|
||||
self.typ = self.TLV.ARRAY
|
||||
self.val = []
|
||||
end
|
||||
|
||||
#############################################################
|
||||
def tostring()
|
||||
return self.tostring_inner(false, "[", "]")
|
||||
end
|
||||
|
||||
#############################################################
|
||||
def parse(b, idx)
|
||||
# iterate until end of struct
|
||||
while b[idx] != self.TLV.EOC
|
||||
# read next
|
||||
var item = self.TLV.parse(b, idx, self)
|
||||
idx = item.next_idx
|
||||
|
||||
# for arrays, all tags must be anonymous
|
||||
item.tag_vendor = nil
|
||||
item.tag_profile = nil
|
||||
item.tag_number = nil
|
||||
item.tag_sub = nil
|
||||
self.val.push(item)
|
||||
end
|
||||
idx += 1
|
||||
|
||||
self.next_idx = idx
|
||||
return idx
|
||||
end
|
||||
end
|
||||
|
||||
#################################################################################
|
||||
# bookkeeping
|
||||
#################################################################################
|
||||
# Matter_TLV.Matter_TLV_item = Matter_TLV_item
|
||||
# Matter_TLV.Matter_TLV_struct = Matter_TLV_struct
|
||||
# Matter_TLV.Matter_TLV_array = Matter_TLV_array
|
||||
# Matter_TLV.Matter_TLV_list = Matter_TLV_list
|
||||
|
||||
# parse a bytes() array from `idx`
|
||||
# args:
|
||||
# b: bytes() buffer
|
||||
# idx: starting index in the bytes() buffer
|
||||
# parent: (optional) the parent object to inherit tag values
|
||||
# returns the next `idx` for the item following or `-1` if error
|
||||
static def parse(b, idx, parent)
|
||||
var TLV = _class
|
||||
if idx == nil idx = 0 end
|
||||
# read type and tag_control
|
||||
var item_type = b[idx] & 0x1F # values 0x00 - 0x1F
|
||||
var item_tag_control = b[idx] & 0xE0 # values 0x20 - 0xE0
|
||||
idx += 1 # skip tag/type byte
|
||||
|
||||
if (item_type > TLV.EOC) raise "TLV_error", "invalid TLV type "+str(item_type) end
|
||||
|
||||
# ############################################################
|
||||
# instanciate TLV item or struct
|
||||
var item
|
||||
if item_type == TLV.STRUCT
|
||||
item = _class.Matter_TLV_struct(parent)
|
||||
elif item_type == TLV.ARRAY
|
||||
item = _class.Matter_TLV_array(parent)
|
||||
elif item_type == TLV.LIST
|
||||
item = _class.Matter_TLV_list(parent)
|
||||
else
|
||||
item = _class.Matter_TLV_item(parent)
|
||||
end
|
||||
item.typ = item_type # set type for item
|
||||
|
||||
# ############################################################
|
||||
# parse Tag and length
|
||||
# do we have a vendor?
|
||||
if item_tag_control == 0xC0 || item_tag_control == 0xE0
|
||||
item.tag_vendor = b.get(idx, 2)
|
||||
item.tag_profile = b.get(idx + 2, 2)
|
||||
idx += 4
|
||||
end
|
||||
# Common profile tags
|
||||
if item_tag_control == 0x40 || item_tag_control == 0x60
|
||||
item.tag_vendor = nil
|
||||
item.tag_profile = -1
|
||||
end
|
||||
# Tags
|
||||
if item_tag_control == 0x00
|
||||
# pass
|
||||
elif item_tag_control == 0x20
|
||||
# context specific tag
|
||||
item.tag_sub = b[idx]
|
||||
idx += 1
|
||||
elif item_tag_control == 0xC0 || item_tag_control == 0x80 || item_tag_control == 0x40
|
||||
item.tag_number = b.get(idx, 2)
|
||||
idx += 2
|
||||
else
|
||||
item.tag_number = b.get(idx, 4)
|
||||
idx += 4
|
||||
end
|
||||
|
||||
# ############################################################
|
||||
# parse Value
|
||||
idx = item.parse(b, idx)
|
||||
|
||||
return item
|
||||
end
|
||||
#############################################################
|
||||
# create simple TLV
|
||||
static def create_TLV(t, value)
|
||||
return _class.Matter_TLV_item.create_TLV(t, value)
|
||||
end
|
||||
end
|
||||
|
||||
# add to matter
|
||||
import matter
|
||||
matter.TLV = Matter_TLV
|
||||
|
||||
#-
|
||||
|
||||
# Test
|
||||
import matter
|
||||
|
||||
#load("Matter_TLV.be")
|
||||
|
||||
var m
|
||||
m = matter.TLV.parse(bytes("2502054C"))
|
||||
assert(m.tostring() == "2 = 19461U")
|
||||
assert(m.encode() == bytes("2502054C"))
|
||||
|
||||
m = matter.TLV.parse(bytes("0001"))
|
||||
assert(m.tostring() == "1")
|
||||
assert(m.encode() == bytes("0001"))
|
||||
|
||||
m = matter.TLV.parse(bytes("08"))
|
||||
assert(m.tostring() == "false")
|
||||
assert(m.encode() == bytes("08"))
|
||||
m = matter.TLV.parse(bytes("09"))
|
||||
assert(m.tostring() == "true")
|
||||
assert(m.encode() == bytes("09"))
|
||||
|
||||
m = matter.TLV.parse(bytes("01FFFF"))
|
||||
assert(m.tostring() == "-1")
|
||||
assert(m.encode() == bytes("00FF"))
|
||||
m = matter.TLV.parse(bytes("05FFFF"))
|
||||
assert(m.tostring() == "65535U")
|
||||
assert(m.encode() == bytes("05FFFF"))
|
||||
|
||||
m = matter.TLV.parse(bytes("0A0000C03F"))
|
||||
assert(m.tostring() == "1.5")
|
||||
assert(m.encode() == bytes("0A0000C03F"))
|
||||
|
||||
m = matter.TLV.parse(bytes("0C06466f6f626172"))
|
||||
assert(m.tostring() == '"Foobar"')
|
||||
assert(m.encode() == bytes("0C06466f6f626172"))
|
||||
|
||||
m = matter.TLV.parse(bytes("1006466f6f626172"))
|
||||
assert(m.tostring() == "466F6F626172")
|
||||
assert(m.encode() == bytes("1006466f6f626172"))
|
||||
|
||||
m = matter.TLV.parse(bytes("e4f1ffeddeedfe55aa2a"))
|
||||
assert(m.tostring() == "0xFFF1::0xDEED:0xAA55FEED = 42U")
|
||||
assert(m.encode() == bytes("e4f1ffeddeedfe55aa2a"))
|
||||
|
||||
|
||||
m = matter.TLV.parse(bytes("300120D2DAEE8760C9B1D1B25E0E2E4DD6ECA8AEF6193C0203761356FCB06BBEDD7D66"))
|
||||
assert(m.tostring() == "1 = D2DAEE8760C9B1D1B25E0E2E4DD6ECA8AEF6193C0203761356FCB06BBEDD7D66")
|
||||
assert(m.encode() == bytes("300120D2DAEE8760C9B1D1B25E0E2E4DD6ECA8AEF6193C0203761356FCB06BBEDD7D66"))
|
||||
|
||||
# context specific
|
||||
m = matter.TLV.parse(bytes("24012a"))
|
||||
assert(m.tostring() == "1 = 42U")
|
||||
assert(m.encode() == bytes("24012a"))
|
||||
|
||||
m = matter.TLV.parse(bytes("4401002a"))
|
||||
assert(m.tostring() == "Matter::0x00000001 = 42U")
|
||||
assert(m.encode() == bytes("4401002a"))
|
||||
|
||||
# int64
|
||||
m = matter.TLV.parse(bytes("030102000000000000"))
|
||||
assert(m.tostring() == "513")
|
||||
assert(m.encode() == bytes("030102000000000000"))
|
||||
|
||||
m = matter.TLV.parse(bytes("070102000000000000"))
|
||||
assert(m.tostring() == "513U")
|
||||
assert(m.encode() == bytes("070102000000000000"))
|
||||
|
||||
m = matter.TLV.parse(bytes("03FFFFFFFFFFFFFFFF"))
|
||||
assert(m.tostring() == "-1")
|
||||
assert(m.encode() == bytes("03FFFFFFFFFFFFFFFF"))
|
||||
|
||||
m = matter.TLV.parse(bytes("07FFFFFFFFFFFFFF7F"))
|
||||
assert(m.tostring() == "9223372036854775807U")
|
||||
assert(m.encode() == bytes("07FFFFFFFFFFFFFF7F"))
|
||||
|
||||
# structure
|
||||
m = matter.TLV.parse(bytes("1518"))
|
||||
assert(m.tostring() == "{}")
|
||||
assert(m.encode() == bytes("1518"))
|
||||
|
||||
m = matter.TLV.parse(bytes("15300120D2DAEE8760C9B1D1B25E0E2E4DD6ECA8AEF6193C0203761356FCB06BBEDD7D662502054C240300280418"))
|
||||
assert(m.tostring() == "{1 = D2DAEE8760C9B1D1B25E0E2E4DD6ECA8AEF6193C0203761356FCB06BBEDD7D66, 2 = 19461U, 3 = 0U, 4 = false}")
|
||||
assert(m.encode() == bytes("15300120D2DAEE8760C9B1D1B25E0E2E4DD6ECA8AEF6193C0203761356FCB06BBEDD7D662502054C240300280418"))
|
||||
|
||||
m = matter.TLV.parse(bytes("15300120D2DAEE8760C9B1D1B25E0E2E4DD6ECA8AEF6193C0203761356FCB06BBEDD7D662502054C240300280435052501881325022C011818"))
|
||||
assert(m.tostring() == "{1 = D2DAEE8760C9B1D1B25E0E2E4DD6ECA8AEF6193C0203761356FCB06BBEDD7D66, 2 = 19461U, 3 = 0U, 4 = false, 5 = {1 = 5000U, 2 = 300U}}")
|
||||
assert(m.encode() == bytes("15300120D2DAEE8760C9B1D1B25E0E2E4DD6ECA8AEF6193C0203761356FCB06BBEDD7D662502054C240300280435052501881325022C011818"))
|
||||
|
||||
# list
|
||||
m = matter.TLV.parse(bytes("1718"))
|
||||
assert(m.tostring() == "[[]]")
|
||||
assert(m.encode() == bytes("1718"))
|
||||
|
||||
m = matter.TLV.parse(bytes("17000120002a000200032000ef18"))
|
||||
assert(m.tostring() == "[[1, 0 = 42, 2, 3, 0 = -17]]")
|
||||
assert(m.encode() == bytes("17000120002a000200032000ef18"))
|
||||
|
||||
|
||||
# array
|
||||
m = matter.TLV.parse(bytes("1618"))
|
||||
assert(m.tostring() == "[]")
|
||||
assert(m.encode() == bytes("1618"))
|
||||
|
||||
m = matter.TLV.parse(bytes("160000000100020003000418"))
|
||||
assert(m.tostring() == "[0, 1, 2, 3, 4]")
|
||||
assert(m.encode() == bytes("160000000100020003000418"))
|
||||
|
||||
# mix
|
||||
m = matter.TLV.parse(bytes("16002a02f067fdff15180a33338f410c0648656c6c6f2118"))
|
||||
assert(m.tostring() == '[42, -170000, {}, 17.9, "Hello!"]')
|
||||
assert(m.encode() == bytes("16002a02f067fdff15180a33338f410c0648656c6c6f2118"))
|
||||
|
||||
m = matter.TLV.parse(bytes("153600172403312504FCFF18172402002403302404001817240200240330240401181724020024033024040218172402002403302404031817240200240328240402181724020024032824040418172403312404031818280324FF0118"))
|
||||
assert(m.tostring() == '{0 = [[[3 = 49U, 4 = 65532U]], [[2 = 0U, 3 = 48U, 4 = 0U]], [[2 = 0U, 3 = 48U, 4 = 1U]], [[2 = 0U, 3 = 48U, 4 = 2U]], [[2 = 0U, 3 = 48U, 4 = 3U]], [[2 = 0U, 3 = 40U, 4 = 2U]], [[2 = 0U, 3 = 40U, 4 = 4U]], [[3 = 49U, 4 = 3U]]], 3 = false, 255 = 1U}')
|
||||
assert(m.encode() == bytes("153600172403312504FCFF18172402002403302404001817240200240330240401181724020024033024040218172402002403302404031817240200240328240402181724020024032824040418172403312404031818280324FF0118"))
|
||||
|
||||
-#
|
187
lib/libesp32/berry_matter/src/embedded/Matter_UDPServer.be
Normal file
187
lib/libesp32/berry_matter/src/embedded/Matter_UDPServer.be
Normal file
@ -0,0 +1,187 @@
|
||||
#
|
||||
# Matter_UDPServer.be - implements IPv6 UDP communication for Matter
|
||||
#
|
||||
# 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_UDPServer class
|
||||
#
|
||||
# For receiving and outgoing messages on UDP
|
||||
#
|
||||
|
||||
import matter
|
||||
|
||||
#@ solidify:Matter_UDPPacket_sent,weak
|
||||
#@ solidify:Matter_UDPServer,weak
|
||||
|
||||
#################################################################################
|
||||
# Matter_UDPPacket_sent class
|
||||
#
|
||||
# A packet that needs to be resent if not acknowledged by the other party
|
||||
#################################################################################
|
||||
class Matter_UDPPacket_sent
|
||||
static var RETRY_MS = 500 # retry every 500 ms
|
||||
static var RETRIES = 4 # retry every 500 ms
|
||||
var raw # bytes() to be sent
|
||||
var addr # ip_address (string)
|
||||
var port # port (int)
|
||||
var msg_id # (int) message identifier that needs to be acknowledged
|
||||
var retries # how many retries are allowed, when `0` drop and log
|
||||
var next_try # timestamp (millis) when to try again
|
||||
|
||||
def init(raw, addr, port, id)
|
||||
self.raw = raw
|
||||
self.addr = addr
|
||||
self.port = port
|
||||
self.msg_id = id
|
||||
self.retries = self.RETRIES
|
||||
self.next_try = tasmota.millis() + self.RETRY_MS
|
||||
end
|
||||
|
||||
def send(udp_socket)
|
||||
import string
|
||||
var ok = udp_socket.send(self.addr ? self.addr : udp_socket.remote_ip, self.port ? self.port : udp_socket.remote_port, self.raw)
|
||||
if ok
|
||||
tasmota.log(string.format("MTR: sending packet to '[%s]:%i'", self.addr, self.port), 3)
|
||||
else
|
||||
tasmota.log(string.format("MTR: failed to send packet to '[%s]:%i'", self.addr, self.port), 2)
|
||||
end
|
||||
end
|
||||
end
|
||||
matter.UDPPacket_sent = Matter_UDPPacket_sent
|
||||
|
||||
#################################################################################
|
||||
# Matter_UDPServer class
|
||||
#
|
||||
#################################################################################
|
||||
class Matter_UDPServer
|
||||
static var MAX_PACKETS_READ = 4 # read at most 4 packets per tick
|
||||
var address, port # local address and port
|
||||
var listening # true if active
|
||||
var udp_socket
|
||||
var dispatch_cb # callback to call when a message is received
|
||||
var packets_sent # map of packets sent to be acknowledged
|
||||
|
||||
#############################################################
|
||||
def init(address, port)
|
||||
self.address = address ? address : ""
|
||||
self.port = port ? port : 5540
|
||||
self.listening = false
|
||||
self.packets_sent = {}
|
||||
end
|
||||
|
||||
#############################################################
|
||||
# start the server
|
||||
# raises an exception if something is wrong
|
||||
# registers as device handle
|
||||
#
|
||||
# `cb`: callback to call when a message is received
|
||||
def start(cb)
|
||||
if !self.listening
|
||||
self.udp_socket = udp()
|
||||
var ok = self.udp_socket.begin(self.address, self.port)
|
||||
if !ok raise "network_error", "could not open UDP server" end
|
||||
self.listening = true
|
||||
self.dispatch_cb = cb
|
||||
tasmota.add_driver(self)
|
||||
end
|
||||
end
|
||||
|
||||
#############################################################
|
||||
# stop the server
|
||||
# remove driver
|
||||
def stop()
|
||||
if self.listening
|
||||
self.udp_socket.stop()
|
||||
self.listening = false
|
||||
tasmota.remove_driver(self)
|
||||
end
|
||||
end
|
||||
|
||||
#############################################################
|
||||
def every_50ms()
|
||||
import string
|
||||
var packet_read = 0
|
||||
if self.udp_socket == nil return end
|
||||
var packet = self.udp_socket.read()
|
||||
while packet != nil
|
||||
# self.packet = packet
|
||||
packet_read += 1
|
||||
var from_addr = self.udp_socket.remote_ip
|
||||
var from_port = self.udp_socket.remote_port
|
||||
tasmota.log(string.format("MTR: UDP received from [%s]:%i", from_addr, from_port), 4)
|
||||
if self.dispatch_cb
|
||||
self.dispatch_cb(packet, from_addr, from_port)
|
||||
end
|
||||
# are we reading new packets?
|
||||
if packet_read < self.MAX_PACKETS_READ
|
||||
packet = self.udp_socket.read()
|
||||
else
|
||||
packet = nil
|
||||
end
|
||||
end
|
||||
self.resend_packets() # resend any packet
|
||||
end
|
||||
|
||||
#############################################################
|
||||
def resend_packets()
|
||||
for packet:self.packets_sent
|
||||
if tasmota.time_reached(packet.next_try)
|
||||
tasmota.log("MTR: resending packet id=" + str(packet.msg_id), 3)
|
||||
packet.send(self.udp_socket) # resend
|
||||
packet.retries -= 1
|
||||
if packet.retries <= 0
|
||||
self.packets_sent.remove(packet.msg_id)
|
||||
else
|
||||
packet.next_try = tasmota.millis() + packet.RETRY_MS
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
#############################################################
|
||||
# just received acknowledgment, remove packet from sender
|
||||
def packet_ack(id)
|
||||
if id == nil return end
|
||||
if self.packets_sent.contains(id)
|
||||
self.packets_sent.remove(id)
|
||||
tasmota.log("MTR: removed packet from sending list id=" + str(id), 3)
|
||||
end
|
||||
end
|
||||
|
||||
#############################################################
|
||||
def send_response(raw, addr, port, id)
|
||||
var packet = matter.UDPPacket_sent(raw, addr, port, id)
|
||||
packet.send(self.udp_socket) # send
|
||||
if id
|
||||
self.packets_sent[id] = packet
|
||||
end
|
||||
end
|
||||
|
||||
#############################################################
|
||||
# placeholder, nothing to run for now
|
||||
def every_second()
|
||||
end
|
||||
end
|
||||
matter.UDPServer = Matter_UDPServer
|
||||
|
||||
#-
|
||||
|
||||
import matter
|
||||
var udps = matter.UDPServer()
|
||||
udps.listen()
|
||||
|
||||
-#
|
259
lib/libesp32/berry_matter/src/embedded/Matter_UI.be
Normal file
259
lib/libesp32/berry_matter/src/embedded/Matter_UI.be
Normal file
@ -0,0 +1,259 @@
|
||||
#
|
||||
# Matter_UI.be - WebUI for Matter configuration in Tasmota
|
||||
#
|
||||
# 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 Web UI
|
||||
#
|
||||
#######################################################################
|
||||
|
||||
import matter
|
||||
|
||||
#@ solidify:Matter_UI,weak
|
||||
|
||||
#################################################################################
|
||||
# Partition_wizard_UI
|
||||
#
|
||||
# WebUI for the partition manager
|
||||
#################################################################################
|
||||
class Matter_UI
|
||||
var device
|
||||
|
||||
def init(device)
|
||||
self.device = device
|
||||
tasmota.add_driver(self)
|
||||
end
|
||||
|
||||
# ####################################################################################################
|
||||
# Init web handlers
|
||||
# ####################################################################################################
|
||||
# Displays a "Autoconf" button on the configuration page
|
||||
def web_add_config_button()
|
||||
import webserver
|
||||
# webserver.content_send("<p><form id=ac action='matterc' style='display: block;' method='get'><button>Configure Matter</button></form></p>")
|
||||
webserver.content_send("<p><form id=ac action='matterc' style='display: block;' method='get'><button>")
|
||||
webserver.content_send(matter._LOGO)
|
||||
webserver.content_send(" Configure Matter</button></form></p>")
|
||||
end
|
||||
|
||||
#- ---------------------------------------------------------------------- -#
|
||||
#- Show commissioning information and QR Code
|
||||
#
|
||||
# Returns true if Matter is enabled
|
||||
#- ---------------------------------------------------------------------- -#
|
||||
def show_enable(p)
|
||||
import webserver
|
||||
import string
|
||||
var matter_enabled = tasmota.get_option(matter.MATTER_OPTION)
|
||||
|
||||
webserver.content_send(string.format("<fieldset><legend><b> Matter %s </b></legend><p></p>",
|
||||
matter_enabled ? "Enabled" : "Disabled"))
|
||||
|
||||
webserver.content_send("<p style='width:320px;'>Matter support is experimental.</p>")
|
||||
|
||||
webserver.content_send("<form action='/matterc' method='post' onsubmit='return confirm(\"This will cause a restart.\");'>")
|
||||
webserver.content_send(string.format("<p></p><button name='%s' class='button bgrn'>", matter_enabled ? "disable" : "enable"))
|
||||
webserver.content_send(matter_enabled ? "Disable" : "Enable")
|
||||
webserver.content_send(" Matter</button></form></p>")
|
||||
|
||||
webserver.content_send("<p></p></fieldset><p></p>")
|
||||
|
||||
return matter_enabled
|
||||
end
|
||||
|
||||
#- ---------------------------------------------------------------------- -#
|
||||
#- Show commissioning information and QR Code
|
||||
#- ---------------------------------------------------------------------- -#
|
||||
def show_commissioning_info()
|
||||
import webserver
|
||||
import string
|
||||
|
||||
webserver.content_send("<fieldset><legend><b> Matter Passcode </b></legend><p></p>")
|
||||
|
||||
var pairing_code = self.device.compute_manual_pairing_code()
|
||||
webserver.content_send(string.format("<p>Manual pairing code:<br><b>%s-%s-%s</b></p><hr>", pairing_code[0..3], pairing_code[4..6], pairing_code[7..]))
|
||||
|
||||
var qr_text = self.device.compute_qrcode_content()
|
||||
webserver.content_send('<div id="qrcode"></div>')
|
||||
webserver.content_send(string.format('<script type="text/javascript"> new QRCode(document.getElementById("qrcode"), "%s");</script>', qr_text))
|
||||
webserver.content_send(string.format("<p>%s</p><hr>", qr_text))
|
||||
|
||||
webserver.content_send("<form action='/matterc' method='post' >")
|
||||
webserver.content_send("<p>Passcode:</p>")
|
||||
webserver.content_send(string.format("<input type='number' min='1' max='99999998' name='passcode' value='%i'>", self.device.passcode))
|
||||
webserver.content_send("<p>Distinguish id:</p>")
|
||||
webserver.content_send(string.format("<input type='number' min='0' max='2047' name='discriminator' value='%i'>", self.device.discriminator))
|
||||
webserver.content_send("<p></p><button name='passcode' class='button bgrn'>Change</button></form></p>")
|
||||
|
||||
|
||||
webserver.content_send("<p></p></fieldset><p></p>")
|
||||
|
||||
end
|
||||
|
||||
#- ---------------------------------------------------------------------- -#
|
||||
#- Show commissioning information and QR Code
|
||||
#- ---------------------------------------------------------------------- -#
|
||||
def show_session_info(p)
|
||||
import webserver
|
||||
import string
|
||||
|
||||
webserver.content_send("<fieldset><legend><b> Sessions </b></legend><p></p>")
|
||||
webserver.content_send("<p>Existing sessions:</p>")
|
||||
|
||||
if size(self.device.sessions.sessions) == 0
|
||||
webserver.content_send("<p><b>None</b></p>")
|
||||
else
|
||||
var i = 0
|
||||
var sz = size(self.device.sessions.sessions)
|
||||
while i < sz
|
||||
var s = self.device.sessions.sessions[i]
|
||||
if s.fabric
|
||||
webserver.content_send(string.format("<fieldset><legend><b> Session %i </b></legend><p></p>", s.local_session_id))
|
||||
if i != 0 webserver.content_send("<hr>") end
|
||||
var fabric_rev = s.fabric.copy().reverse()
|
||||
var deviceid_rev = s.deviceid.copy().reverse()
|
||||
webserver.content_send(string.format("Fabric: %s<br>", fabric_rev.tohex()))
|
||||
webserver.content_send(string.format("Device: %s<br> ", deviceid_rev.tohex()))
|
||||
|
||||
webserver.content_send("<form action='/matterc' method='post' ")
|
||||
webserver.content_send("onsubmit='return confirm(\"This will cause a restart.\");'>")
|
||||
webserver.content_send(string.format("<input name='del_session' type='hidden' value='%d'>", s.local_session_id))
|
||||
webserver.content_send("<button name='del' class='button bgrn'>Delete Session</button></form></p>")
|
||||
|
||||
webserver.content_send("<p></p></fieldset><p></p>")
|
||||
end
|
||||
i += 1
|
||||
end
|
||||
end
|
||||
|
||||
webserver.content_send("<p></p></fieldset><p></p>")
|
||||
|
||||
end
|
||||
|
||||
|
||||
#######################################################################
|
||||
# Serve qrcode.min.js static file
|
||||
#######################################################################
|
||||
def page_qrcode_min_js()
|
||||
import webserver
|
||||
|
||||
webserver.content_open(200, "text/javascript")
|
||||
webserver.content_send(matter._QRCODE_MINJS)
|
||||
end
|
||||
|
||||
#######################################################################
|
||||
# Display the complete page
|
||||
#######################################################################
|
||||
def page_part_mgr()
|
||||
import webserver
|
||||
import string
|
||||
|
||||
if !webserver.check_privileged_access() return nil end
|
||||
|
||||
webserver.content_start("Matter") #- title of the web page -#
|
||||
webserver.content_send_style() #- send standard Tasmota styles -#
|
||||
|
||||
webserver.content_send('<script type="text/javascript" src="qrcode.min.js"></script>')
|
||||
|
||||
if self.show_enable()
|
||||
self.show_commissioning_info()
|
||||
self.show_session_info()
|
||||
end
|
||||
webserver.content_button(webserver.BUTTON_CONFIGURATION)
|
||||
webserver.content_stop() #- end of web page -#
|
||||
end
|
||||
|
||||
#######################################################################
|
||||
# Web Controller, called by POST to `/part_wiz`
|
||||
#######################################################################
|
||||
def page_part_ctl()
|
||||
import webserver
|
||||
if !webserver.check_privileged_access() return nil end
|
||||
|
||||
import string
|
||||
import partition_core
|
||||
import persist
|
||||
|
||||
|
||||
#- check that the partition is valid -#
|
||||
var p = partition_core.Partition()
|
||||
|
||||
try
|
||||
|
||||
#---------------------------------------------------------------------#
|
||||
# Change Passcode and/or Passcode
|
||||
#---------------------------------------------------------------------#
|
||||
if webserver.has_arg("passcode") || webserver.has_arg("discriminator")
|
||||
if webserver.has_arg("passcode")
|
||||
self.device.passcode = int(webserver.arg("passcode"))
|
||||
end
|
||||
if webserver.has_arg("discriminator")
|
||||
self.device.discriminator = int(webserver.arg("discriminator"))
|
||||
end
|
||||
self.device.save_param()
|
||||
|
||||
#- and force restart -#
|
||||
webserver.redirect("/?rst=")
|
||||
|
||||
elif webserver.has_arg("enable")
|
||||
tasmota.cmd("SetOption" + str(matter.MATTER_OPTION) + " 1")
|
||||
#- and force restart -#
|
||||
webserver.redirect("/?rst=")
|
||||
|
||||
elif webserver.has_arg("disable")
|
||||
tasmota.cmd("SetOption" + str(matter.MATTER_OPTION) + " 0")
|
||||
#- and force restart -#
|
||||
webserver.redirect("/?rst=")
|
||||
|
||||
elif webserver.has_arg("del_session")
|
||||
var session = self.device.sessions.get_session_by_local_session_id(int(webserver.arg("del_session")))
|
||||
if session != nil
|
||||
self.device.sessions.remove_session(session)
|
||||
self.device.sessions.save()
|
||||
end
|
||||
|
||||
#- and force restart -#
|
||||
webserver.redirect("/?rst=")
|
||||
|
||||
end
|
||||
except .. as e, m
|
||||
tasmota.log(string.format("BRY: Exception> '%s' - %s", e, m), 2)
|
||||
#- display error page -#
|
||||
webserver.content_start("Parameter error") #- title of the web page -#
|
||||
webserver.content_send_style() #- send standard Tasmota styles -#
|
||||
|
||||
webserver.content_send(string.format("<p style='width:340px;'><b>Exception:</b><br>'%s'<br>%s</p>", e, m))
|
||||
|
||||
webserver.content_button(webserver.BUTTON_MANAGEMENT) #- button back to management page -#
|
||||
webserver.content_stop() #- end of web page -#
|
||||
end
|
||||
end
|
||||
|
||||
#- ---------------------------------------------------------------------- -#
|
||||
# respond to web_add_handler() event to register web listeners
|
||||
#- ---------------------------------------------------------------------- -#
|
||||
#- this is called at Tasmota start-up, as soon as Wifi/Eth is up and web server running -#
|
||||
def web_add_handler()
|
||||
import webserver
|
||||
#- we need to register a closure, not just a function, that captures the current instance -#
|
||||
webserver.on("/matterc", / -> self.page_part_mgr(), webserver.HTTP_GET)
|
||||
webserver.on("/matterc", / -> self.page_part_ctl(), webserver.HTTP_POST)
|
||||
webserver.on("/qrcode.min.js", / -> self.page_qrcode_min_js(), webserver.HTTP_GET)
|
||||
end
|
||||
end
|
||||
matter.UI = Matter_UI
|
64
lib/libesp32/berry_matter/src/embedded/Matter_inspect.be
Normal file
64
lib/libesp32/berry_matter/src/embedded/Matter_inspect.be
Normal file
@ -0,0 +1,64 @@
|
||||
#
|
||||
# Matter_inspect.be - implements a generic function to inspect an instance (for debugging only)
|
||||
#
|
||||
# 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/>.
|
||||
#
|
||||
|
||||
import matter
|
||||
|
||||
#@ solidify:matter.sort,weak
|
||||
def sort(l)
|
||||
# insertion sort
|
||||
for i:1..size(l)-1
|
||||
var k = l[i]
|
||||
var j = i
|
||||
while (j > 0) && (l[j-1] > k)
|
||||
l[j] = l[j-1]
|
||||
j -= 1
|
||||
end
|
||||
l[j] = k
|
||||
end
|
||||
return l
|
||||
end
|
||||
matter.sort = sort
|
||||
|
||||
#@ solidify:matter.inspect,weak
|
||||
# debug function
|
||||
def inspect(p)
|
||||
try
|
||||
import string
|
||||
import introspect
|
||||
|
||||
var keys = []
|
||||
for k : introspect.members(p)
|
||||
var v = introspect.get(p, k)
|
||||
if type(v) != 'function' keys.push(k) end
|
||||
end
|
||||
keys = matter.sort(keys)
|
||||
|
||||
var r = []
|
||||
for k : keys
|
||||
var v = introspect.get(p, k)
|
||||
# if type(v) == 'string' v = string.escape(v, true) end
|
||||
r.push(string.format("'%s': %s", str(k), str(v)))
|
||||
end
|
||||
|
||||
return "{" + r.concat(", ") + "}"
|
||||
except .. as e, m
|
||||
return "Exception:" + str(e) + "|" + str(m)
|
||||
end
|
||||
end
|
||||
matter.inspect = inspect
|
4
lib/libesp32/berry_matter/src/embedded/matter.be
Normal file
4
lib/libesp32/berry_matter/src/embedded/matter.be
Normal file
@ -0,0 +1,4 @@
|
||||
# placeholder for `import matter` not to fail when running solidification
|
||||
|
||||
var m = module("matter")
|
||||
return m
|
0
lib/libesp32/berry_matter/src/solidify/.keep
Normal file
0
lib/libesp32/berry_matter/src/solidify/.keep
Normal file
@ -0,0 +1,154 @@
|
||||
/* Solidification of Matter_Base38.h */
|
||||
/********************************************************************\
|
||||
* Generated code, don't edit *
|
||||
\********************************************************************/
|
||||
#include "be_constobj.h"
|
||||
|
||||
extern const bclass be_class_Matter_Base38;
|
||||
|
||||
/********************************************************************
|
||||
** Solidified function: encode
|
||||
********************************************************************/
|
||||
be_local_closure(Matter_Base38_encode, /* name */
|
||||
be_nested_proto(
|
||||
10, /* nstack */
|
||||
1, /* argc */
|
||||
4, /* varg */
|
||||
0, /* has upvals */
|
||||
NULL, /* no upvals */
|
||||
1, /* has sup protos */
|
||||
( &(const struct bproto*[ 1]) {
|
||||
be_nested_proto(
|
||||
7, /* nstack */
|
||||
2, /* argc */
|
||||
0, /* varg */
|
||||
0, /* has upvals */
|
||||
NULL, /* no upvals */
|
||||
0, /* has sup protos */
|
||||
NULL, /* no sub protos */
|
||||
1, /* has constants */
|
||||
( &(const bvalue[ 5]) { /* constants */
|
||||
/* K0 */ be_nested_str_weak(string),
|
||||
/* K1 */ be_nested_str_weak(0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_X2D_X2E),
|
||||
/* K2 */ be_const_int(0),
|
||||
/* K3 */ be_nested_str_weak(),
|
||||
/* K4 */ be_const_int(1),
|
||||
}),
|
||||
be_str_weak(b38_enc),
|
||||
&be_const_str_solidified,
|
||||
( &(const binstruction[15]) { /* code */
|
||||
0xA40A0000, // 0000 IMPORT R2 K0
|
||||
0x580C0001, // 0001 LDCONST R3 K1
|
||||
0x58100002, // 0002 LDCONST R4 K2
|
||||
0x58140003, // 0003 LDCONST R5 K3
|
||||
0x14180801, // 0004 LT R6 R4 R1
|
||||
0x781A0007, // 0005 JMPF R6 #000E
|
||||
0x541A0025, // 0006 LDINT R6 38
|
||||
0x10180006, // 0007 MOD R6 R0 R6
|
||||
0x94180606, // 0008 GETIDX R6 R3 R6
|
||||
0x00140A06, // 0009 ADD R5 R5 R6
|
||||
0x541A0025, // 000A LDINT R6 38
|
||||
0x0C000006, // 000B DIV R0 R0 R6
|
||||
0x00100904, // 000C ADD R4 R4 K4
|
||||
0x7001FFF5, // 000D JMP #0004
|
||||
0x80040A00, // 000E RET 1 R5
|
||||
})
|
||||
),
|
||||
}),
|
||||
1, /* has constants */
|
||||
( &(const bvalue[ 6]) { /* constants */
|
||||
/* K0 */ be_const_class(be_class_Matter_Base38),
|
||||
/* K1 */ be_const_int(0),
|
||||
/* K2 */ be_nested_str_weak(),
|
||||
/* K3 */ be_const_int(2),
|
||||
/* K4 */ be_const_int(1),
|
||||
/* K5 */ be_const_int(3),
|
||||
}),
|
||||
be_str_weak(encode),
|
||||
&be_const_str_solidified,
|
||||
( &(const binstruction[58]) { /* code */
|
||||
0x58040000, // 0000 LDCONST R1 K0
|
||||
0x84080000, // 0001 CLOSURE R2 P0
|
||||
0x580C0001, // 0002 LDCONST R3 K1
|
||||
0x6010000C, // 0003 GETGBL R4 G12
|
||||
0x5C140000, // 0004 MOVE R5 R0
|
||||
0x7C100200, // 0005 CALL R4 1
|
||||
0x58140002, // 0006 LDCONST R5 K2
|
||||
0x14180604, // 0007 LT R6 R3 R4
|
||||
0x781A002F, // 0008 JMPF R6 #0039
|
||||
0x4C180000, // 0009 LDNIL R6
|
||||
0x001C0703, // 000A ADD R7 R3 K3
|
||||
0x141C0E04, // 000B LT R7 R7 R4
|
||||
0x781E0012, // 000C JMPF R7 #0020
|
||||
0x941C0003, // 000D GETIDX R7 R0 R3
|
||||
0x00200704, // 000E ADD R8 R3 K4
|
||||
0x94200008, // 000F GETIDX R8 R0 R8
|
||||
0x54260007, // 0010 LDINT R9 8
|
||||
0x38201009, // 0011 SHL R8 R8 R9
|
||||
0x301C0E08, // 0012 OR R7 R7 R8
|
||||
0x00200703, // 0013 ADD R8 R3 K3
|
||||
0x94200008, // 0014 GETIDX R8 R0 R8
|
||||
0x5426000F, // 0015 LDINT R9 16
|
||||
0x38201009, // 0016 SHL R8 R8 R9
|
||||
0x301C0E08, // 0017 OR R7 R7 R8
|
||||
0x5C180E00, // 0018 MOVE R6 R7
|
||||
0x5C1C0400, // 0019 MOVE R7 R2
|
||||
0x5C200C00, // 001A MOVE R8 R6
|
||||
0x54260004, // 001B LDINT R9 5
|
||||
0x7C1C0400, // 001C CALL R7 2
|
||||
0x00140A07, // 001D ADD R5 R5 R7
|
||||
0x000C0705, // 001E ADD R3 R3 K5
|
||||
0x70020017, // 001F JMP #0038
|
||||
0x001C0704, // 0020 ADD R7 R3 K4
|
||||
0x141C0E04, // 0021 LT R7 R7 R4
|
||||
0x781E000D, // 0022 JMPF R7 #0031
|
||||
0x941C0003, // 0023 GETIDX R7 R0 R3
|
||||
0x00200704, // 0024 ADD R8 R3 K4
|
||||
0x94200008, // 0025 GETIDX R8 R0 R8
|
||||
0x54260007, // 0026 LDINT R9 8
|
||||
0x38201009, // 0027 SHL R8 R8 R9
|
||||
0x301C0E08, // 0028 OR R7 R7 R8
|
||||
0x5C180E00, // 0029 MOVE R6 R7
|
||||
0x5C1C0400, // 002A MOVE R7 R2
|
||||
0x5C200C00, // 002B MOVE R8 R6
|
||||
0x54260003, // 002C LDINT R9 4
|
||||
0x7C1C0400, // 002D CALL R7 2
|
||||
0x00140A07, // 002E ADD R5 R5 R7
|
||||
0x000C0703, // 002F ADD R3 R3 K3
|
||||
0x70020006, // 0030 JMP #0038
|
||||
0x94180003, // 0031 GETIDX R6 R0 R3
|
||||
0x5C1C0400, // 0032 MOVE R7 R2
|
||||
0x5C200C00, // 0033 MOVE R8 R6
|
||||
0x58240003, // 0034 LDCONST R9 K3
|
||||
0x7C1C0400, // 0035 CALL R7 2
|
||||
0x00140A07, // 0036 ADD R5 R5 R7
|
||||
0x000C0704, // 0037 ADD R3 R3 K4
|
||||
0x7001FFCD, // 0038 JMP #0007
|
||||
0x80040A00, // 0039 RET 1 R5
|
||||
})
|
||||
)
|
||||
);
|
||||
/*******************************************************************/
|
||||
|
||||
|
||||
/********************************************************************
|
||||
** Solidified class: Matter_Base38
|
||||
********************************************************************/
|
||||
be_local_class(Matter_Base38,
|
||||
0,
|
||||
NULL,
|
||||
be_nested_map(1,
|
||||
( (struct bmapnode*) &(const bmapnode[]) {
|
||||
{ be_const_key_weak(encode, -1), be_const_static_closure(Matter_Base38_encode_closure) },
|
||||
})),
|
||||
be_str_weak(Matter_Base38)
|
||||
);
|
||||
/*******************************************************************/
|
||||
|
||||
void be_load_Matter_Base38_class(bvm *vm) {
|
||||
be_pushntvclass(vm, &be_class_Matter_Base38);
|
||||
be_setglobal(vm, "Matter_Base38");
|
||||
be_pop(vm, 1);
|
||||
}
|
||||
/********************************************************************/
|
||||
/* End of solidification */
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,970 @@
|
||||
/* Solidification of Matter_Commissioning_Data.h */
|
||||
/********************************************************************\
|
||||
* Generated code, don't edit *
|
||||
\********************************************************************/
|
||||
#include "be_constobj.h"
|
||||
|
||||
extern const bclass be_class_Matter_PBKDFParamRequest;
|
||||
|
||||
/********************************************************************
|
||||
** Solidified function: parse
|
||||
********************************************************************/
|
||||
be_local_closure(Matter_PBKDFParamRequest_parse, /* name */
|
||||
be_nested_proto(
|
||||
8, /* nstack */
|
||||
3, /* argc */
|
||||
2, /* varg */
|
||||
0, /* has upvals */
|
||||
NULL, /* no upvals */
|
||||
0, /* has sup protos */
|
||||
NULL, /* no sub protos */
|
||||
1, /* has constants */
|
||||
( &(const bvalue[16]) { /* constants */
|
||||
/* K0 */ be_const_int(0),
|
||||
/* K1 */ be_nested_str_weak(matter),
|
||||
/* K2 */ be_nested_str_weak(TLV),
|
||||
/* K3 */ be_nested_str_weak(parse),
|
||||
/* K4 */ be_nested_str_weak(initiatorRandom),
|
||||
/* K5 */ be_nested_str_weak(getsubval),
|
||||
/* K6 */ be_const_int(1),
|
||||
/* K7 */ be_nested_str_weak(initiator_session_id),
|
||||
/* K8 */ be_const_int(2),
|
||||
/* K9 */ be_nested_str_weak(passcodeId),
|
||||
/* K10 */ be_const_int(3),
|
||||
/* K11 */ be_nested_str_weak(hasPBKDFParameters),
|
||||
/* K12 */ be_nested_str_weak(findsub),
|
||||
/* K13 */ be_nested_str_weak(SLEEPY_IDLE_INTERVAL),
|
||||
/* K14 */ be_nested_str_weak(findsubval),
|
||||
/* K15 */ be_nested_str_weak(SLEEPY_ACTIVE_INTERVAL),
|
||||
}),
|
||||
be_str_weak(parse),
|
||||
&be_const_str_solidified,
|
||||
( &(const binstruction[41]) { /* code */
|
||||
0x4C0C0000, // 0000 LDNIL R3
|
||||
0x1C0C0403, // 0001 EQ R3 R2 R3
|
||||
0x780E0000, // 0002 JMPF R3 #0004
|
||||
0x58080000, // 0003 LDCONST R2 K0
|
||||
0xB80E0200, // 0004 GETNGBL R3 K1
|
||||
0x880C0702, // 0005 GETMBR R3 R3 K2
|
||||
0x8C0C0703, // 0006 GETMET R3 R3 K3
|
||||
0x5C140200, // 0007 MOVE R5 R1
|
||||
0x5C180400, // 0008 MOVE R6 R2
|
||||
0x7C0C0600, // 0009 CALL R3 3
|
||||
0x8C100705, // 000A GETMET R4 R3 K5
|
||||
0x58180006, // 000B LDCONST R6 K6
|
||||
0x7C100400, // 000C CALL R4 2
|
||||
0x90020804, // 000D SETMBR R0 K4 R4
|
||||
0x8C100705, // 000E GETMET R4 R3 K5
|
||||
0x58180008, // 000F LDCONST R6 K8
|
||||
0x7C100400, // 0010 CALL R4 2
|
||||
0x90020E04, // 0011 SETMBR R0 K7 R4
|
||||
0x8C100705, // 0012 GETMET R4 R3 K5
|
||||
0x5818000A, // 0013 LDCONST R6 K10
|
||||
0x7C100400, // 0014 CALL R4 2
|
||||
0x90021204, // 0015 SETMBR R0 K9 R4
|
||||
0x8C100705, // 0016 GETMET R4 R3 K5
|
||||
0x541A0003, // 0017 LDINT R6 4
|
||||
0x7C100400, // 0018 CALL R4 2
|
||||
0x90021604, // 0019 SETMBR R0 K11 R4
|
||||
0x8C10070C, // 001A GETMET R4 R3 K12
|
||||
0x541A0004, // 001B LDINT R6 5
|
||||
0x7C100400, // 001C CALL R4 2
|
||||
0x4C140000, // 001D LDNIL R5
|
||||
0x20140805, // 001E NE R5 R4 R5
|
||||
0x78160007, // 001F JMPF R5 #0028
|
||||
0x8C14090E, // 0020 GETMET R5 R4 K14
|
||||
0x581C0006, // 0021 LDCONST R7 K6
|
||||
0x7C140400, // 0022 CALL R5 2
|
||||
0x90021A05, // 0023 SETMBR R0 K13 R5
|
||||
0x8C14090E, // 0024 GETMET R5 R4 K14
|
||||
0x581C0008, // 0025 LDCONST R7 K8
|
||||
0x7C140400, // 0026 CALL R5 2
|
||||
0x90021E05, // 0027 SETMBR R0 K15 R5
|
||||
0x80040000, // 0028 RET 1 R0
|
||||
})
|
||||
)
|
||||
);
|
||||
/*******************************************************************/
|
||||
|
||||
|
||||
/********************************************************************
|
||||
** Solidified class: Matter_PBKDFParamRequest
|
||||
********************************************************************/
|
||||
be_local_class(Matter_PBKDFParamRequest,
|
||||
6,
|
||||
NULL,
|
||||
be_nested_map(7,
|
||||
( (struct bmapnode*) &(const bmapnode[]) {
|
||||
{ be_const_key_weak(initiatorRandom, 6), be_const_var(0) },
|
||||
{ be_const_key_weak(passcodeId, -1), be_const_var(2) },
|
||||
{ be_const_key_weak(hasPBKDFParameters, -1), be_const_var(3) },
|
||||
{ be_const_key_weak(parse, -1), be_const_closure(Matter_PBKDFParamRequest_parse_closure) },
|
||||
{ be_const_key_weak(initiator_session_id, 0), be_const_var(1) },
|
||||
{ be_const_key_weak(SLEEPY_IDLE_INTERVAL, 3), be_const_var(4) },
|
||||
{ be_const_key_weak(SLEEPY_ACTIVE_INTERVAL, -1), be_const_var(5) },
|
||||
})),
|
||||
be_str_weak(Matter_PBKDFParamRequest)
|
||||
);
|
||||
/*******************************************************************/
|
||||
|
||||
void be_load_Matter_PBKDFParamRequest_class(bvm *vm) {
|
||||
be_pushntvclass(vm, &be_class_Matter_PBKDFParamRequest);
|
||||
be_setglobal(vm, "Matter_PBKDFParamRequest");
|
||||
be_pop(vm, 1);
|
||||
}
|
||||
|
||||
extern const bclass be_class_Matter_PBKDFParamResponse;
|
||||
|
||||
/********************************************************************
|
||||
** Solidified function: encode
|
||||
********************************************************************/
|
||||
be_local_closure(Matter_PBKDFParamResponse_encode, /* name */
|
||||
be_nested_proto(
|
||||
10, /* nstack */
|
||||
2, /* argc */
|
||||
2, /* varg */
|
||||
0, /* has upvals */
|
||||
NULL, /* no upvals */
|
||||
0, /* has sup protos */
|
||||
NULL, /* no sub protos */
|
||||
1, /* has constants */
|
||||
( &(const bvalue[19]) { /* constants */
|
||||
/* K0 */ be_nested_str_weak(matter),
|
||||
/* K1 */ be_nested_str_weak(TLV),
|
||||
/* K2 */ be_nested_str_weak(Matter_TLV_struct),
|
||||
/* K3 */ be_nested_str_weak(add_TLV),
|
||||
/* K4 */ be_const_int(1),
|
||||
/* K5 */ be_nested_str_weak(B1),
|
||||
/* K6 */ be_nested_str_weak(initiatorRandom),
|
||||
/* K7 */ be_const_int(2),
|
||||
/* K8 */ be_nested_str_weak(responderRandom),
|
||||
/* K9 */ be_const_int(3),
|
||||
/* K10 */ be_nested_str_weak(U2),
|
||||
/* K11 */ be_nested_str_weak(responderSessionId),
|
||||
/* K12 */ be_nested_str_weak(add_struct),
|
||||
/* K13 */ be_nested_str_weak(U4),
|
||||
/* K14 */ be_nested_str_weak(pbkdf_parameters_iterations),
|
||||
/* K15 */ be_nested_str_weak(pbkdf_parameters_salt),
|
||||
/* K16 */ be_nested_str_weak(SLEEPY_IDLE_INTERVAL),
|
||||
/* K17 */ be_nested_str_weak(SLEEPY_ACTIVE_INTERVAL),
|
||||
/* K18 */ be_nested_str_weak(encode),
|
||||
}),
|
||||
be_str_weak(encode),
|
||||
&be_const_str_solidified,
|
||||
( &(const binstruction[70]) { /* code */
|
||||
0xB80A0000, // 0000 GETNGBL R2 K0
|
||||
0x88080501, // 0001 GETMBR R2 R2 K1
|
||||
0x8C080502, // 0002 GETMET R2 R2 K2
|
||||
0x7C080200, // 0003 CALL R2 1
|
||||
0x8C0C0503, // 0004 GETMET R3 R2 K3
|
||||
0x58140004, // 0005 LDCONST R5 K4
|
||||
0xB81A0000, // 0006 GETNGBL R6 K0
|
||||
0x88180D01, // 0007 GETMBR R6 R6 K1
|
||||
0x88180D05, // 0008 GETMBR R6 R6 K5
|
||||
0x881C0106, // 0009 GETMBR R7 R0 K6
|
||||
0x7C0C0800, // 000A CALL R3 4
|
||||
0x8C0C0503, // 000B GETMET R3 R2 K3
|
||||
0x58140007, // 000C LDCONST R5 K7
|
||||
0xB81A0000, // 000D GETNGBL R6 K0
|
||||
0x88180D01, // 000E GETMBR R6 R6 K1
|
||||
0x88180D05, // 000F GETMBR R6 R6 K5
|
||||
0x881C0108, // 0010 GETMBR R7 R0 K8
|
||||
0x7C0C0800, // 0011 CALL R3 4
|
||||
0x8C0C0503, // 0012 GETMET R3 R2 K3
|
||||
0x58140009, // 0013 LDCONST R5 K9
|
||||
0xB81A0000, // 0014 GETNGBL R6 K0
|
||||
0x88180D01, // 0015 GETMBR R6 R6 K1
|
||||
0x88180D0A, // 0016 GETMBR R6 R6 K10
|
||||
0x881C010B, // 0017 GETMBR R7 R0 K11
|
||||
0x7C0C0800, // 0018 CALL R3 4
|
||||
0x8C0C050C, // 0019 GETMET R3 R2 K12
|
||||
0x54160003, // 001A LDINT R5 4
|
||||
0x7C0C0400, // 001B CALL R3 2
|
||||
0x8C100703, // 001C GETMET R4 R3 K3
|
||||
0x58180004, // 001D LDCONST R6 K4
|
||||
0xB81E0000, // 001E GETNGBL R7 K0
|
||||
0x881C0F01, // 001F GETMBR R7 R7 K1
|
||||
0x881C0F0D, // 0020 GETMBR R7 R7 K13
|
||||
0x8820010E, // 0021 GETMBR R8 R0 K14
|
||||
0x7C100800, // 0022 CALL R4 4
|
||||
0x8C100703, // 0023 GETMET R4 R3 K3
|
||||
0x58180007, // 0024 LDCONST R6 K7
|
||||
0xB81E0000, // 0025 GETNGBL R7 K0
|
||||
0x881C0F01, // 0026 GETMBR R7 R7 K1
|
||||
0x881C0F05, // 0027 GETMBR R7 R7 K5
|
||||
0x8820010F, // 0028 GETMBR R8 R0 K15
|
||||
0x7C100800, // 0029 CALL R4 4
|
||||
0x88100110, // 002A GETMBR R4 R0 K16
|
||||
0x4C140000, // 002B LDNIL R5
|
||||
0x20100805, // 002C NE R4 R4 R5
|
||||
0x74120003, // 002D JMPT R4 #0032
|
||||
0x88100111, // 002E GETMBR R4 R0 K17
|
||||
0x4C140000, // 002F LDNIL R5
|
||||
0x20100805, // 0030 NE R4 R4 R5
|
||||
0x78120010, // 0031 JMPF R4 #0043
|
||||
0x8C10050C, // 0032 GETMET R4 R2 K12
|
||||
0x541A0004, // 0033 LDINT R6 5
|
||||
0x7C100400, // 0034 CALL R4 2
|
||||
0x8C140903, // 0035 GETMET R5 R4 K3
|
||||
0x581C0004, // 0036 LDCONST R7 K4
|
||||
0xB8220000, // 0037 GETNGBL R8 K0
|
||||
0x88201101, // 0038 GETMBR R8 R8 K1
|
||||
0x8820110D, // 0039 GETMBR R8 R8 K13
|
||||
0x88240110, // 003A GETMBR R9 R0 K16
|
||||
0x7C140800, // 003B CALL R5 4
|
||||
0x8C140903, // 003C GETMET R5 R4 K3
|
||||
0x581C0007, // 003D LDCONST R7 K7
|
||||
0xB8220000, // 003E GETNGBL R8 K0
|
||||
0x88201101, // 003F GETMBR R8 R8 K1
|
||||
0x8820110D, // 0040 GETMBR R8 R8 K13
|
||||
0x88240111, // 0041 GETMBR R9 R0 K17
|
||||
0x7C140800, // 0042 CALL R5 4
|
||||
0x8C100512, // 0043 GETMET R4 R2 K18
|
||||
0x7C100200, // 0044 CALL R4 1
|
||||
0x80040800, // 0045 RET 1 R4
|
||||
})
|
||||
)
|
||||
);
|
||||
/*******************************************************************/
|
||||
|
||||
|
||||
/********************************************************************
|
||||
** Solidified class: Matter_PBKDFParamResponse
|
||||
********************************************************************/
|
||||
be_local_class(Matter_PBKDFParamResponse,
|
||||
7,
|
||||
NULL,
|
||||
be_nested_map(8,
|
||||
( (struct bmapnode*) &(const bmapnode[]) {
|
||||
{ be_const_key_weak(pbkdf_parameters_salt, -1), be_const_var(4) },
|
||||
{ be_const_key_weak(SLEEPY_IDLE_INTERVAL, -1), be_const_var(5) },
|
||||
{ be_const_key_weak(SLEEPY_ACTIVE_INTERVAL, 1), be_const_var(6) },
|
||||
{ be_const_key_weak(responderRandom, -1), be_const_var(1) },
|
||||
{ be_const_key_weak(pbkdf_parameters_iterations, -1), be_const_var(3) },
|
||||
{ be_const_key_weak(initiatorRandom, -1), be_const_var(0) },
|
||||
{ be_const_key_weak(responderSessionId, 3), be_const_var(2) },
|
||||
{ be_const_key_weak(encode, -1), be_const_closure(Matter_PBKDFParamResponse_encode_closure) },
|
||||
})),
|
||||
be_str_weak(Matter_PBKDFParamResponse)
|
||||
);
|
||||
/*******************************************************************/
|
||||
|
||||
void be_load_Matter_PBKDFParamResponse_class(bvm *vm) {
|
||||
be_pushntvclass(vm, &be_class_Matter_PBKDFParamResponse);
|
||||
be_setglobal(vm, "Matter_PBKDFParamResponse");
|
||||
be_pop(vm, 1);
|
||||
}
|
||||
|
||||
extern const bclass be_class_Matter_Pake1;
|
||||
|
||||
/********************************************************************
|
||||
** Solidified function: parse
|
||||
********************************************************************/
|
||||
be_local_closure(Matter_Pake1_parse, /* name */
|
||||
be_nested_proto(
|
||||
8, /* nstack */
|
||||
3, /* argc */
|
||||
2, /* varg */
|
||||
0, /* has upvals */
|
||||
NULL, /* no upvals */
|
||||
0, /* has sup protos */
|
||||
NULL, /* no sub protos */
|
||||
1, /* has constants */
|
||||
( &(const bvalue[11]) { /* constants */
|
||||
/* K0 */ be_const_int(0),
|
||||
/* K1 */ be_nested_str_weak(matter),
|
||||
/* K2 */ be_nested_str_weak(TLV),
|
||||
/* K3 */ be_nested_str_weak(parse),
|
||||
/* K4 */ be_nested_str_weak(tasmota),
|
||||
/* K5 */ be_nested_str_weak(log),
|
||||
/* K6 */ be_nested_str_weak(MTR_X3A_X20parsed_X20TLV_X3A_X20),
|
||||
/* K7 */ be_const_int(3),
|
||||
/* K8 */ be_nested_str_weak(pA),
|
||||
/* K9 */ be_nested_str_weak(getsubval),
|
||||
/* K10 */ be_const_int(1),
|
||||
}),
|
||||
be_str_weak(parse),
|
||||
&be_const_str_solidified,
|
||||
( &(const binstruction[23]) { /* code */
|
||||
0x4C0C0000, // 0000 LDNIL R3
|
||||
0x1C0C0403, // 0001 EQ R3 R2 R3
|
||||
0x780E0000, // 0002 JMPF R3 #0004
|
||||
0x58080000, // 0003 LDCONST R2 K0
|
||||
0xB80E0200, // 0004 GETNGBL R3 K1
|
||||
0x880C0702, // 0005 GETMBR R3 R3 K2
|
||||
0x8C0C0703, // 0006 GETMET R3 R3 K3
|
||||
0x5C140200, // 0007 MOVE R5 R1
|
||||
0x5C180400, // 0008 MOVE R6 R2
|
||||
0x7C0C0600, // 0009 CALL R3 3
|
||||
0xB8120800, // 000A GETNGBL R4 K4
|
||||
0x8C100905, // 000B GETMET R4 R4 K5
|
||||
0x60180008, // 000C GETGBL R6 G8
|
||||
0x5C1C0600, // 000D MOVE R7 R3
|
||||
0x7C180200, // 000E CALL R6 1
|
||||
0x001A0C06, // 000F ADD R6 K6 R6
|
||||
0x581C0007, // 0010 LDCONST R7 K7
|
||||
0x7C100600, // 0011 CALL R4 3
|
||||
0x8C100709, // 0012 GETMET R4 R3 K9
|
||||
0x5818000A, // 0013 LDCONST R6 K10
|
||||
0x7C100400, // 0014 CALL R4 2
|
||||
0x90021004, // 0015 SETMBR R0 K8 R4
|
||||
0x80040000, // 0016 RET 1 R0
|
||||
})
|
||||
)
|
||||
);
|
||||
/*******************************************************************/
|
||||
|
||||
|
||||
/********************************************************************
|
||||
** Solidified class: Matter_Pake1
|
||||
********************************************************************/
|
||||
be_local_class(Matter_Pake1,
|
||||
1,
|
||||
NULL,
|
||||
be_nested_map(2,
|
||||
( (struct bmapnode*) &(const bmapnode[]) {
|
||||
{ be_const_key_weak(pA, 1), be_const_var(0) },
|
||||
{ be_const_key_weak(parse, -1), be_const_closure(Matter_Pake1_parse_closure) },
|
||||
})),
|
||||
be_str_weak(Matter_Pake1)
|
||||
);
|
||||
/*******************************************************************/
|
||||
|
||||
void be_load_Matter_Pake1_class(bvm *vm) {
|
||||
be_pushntvclass(vm, &be_class_Matter_Pake1);
|
||||
be_setglobal(vm, "Matter_Pake1");
|
||||
be_pop(vm, 1);
|
||||
}
|
||||
|
||||
extern const bclass be_class_Matter_Pake2;
|
||||
|
||||
/********************************************************************
|
||||
** Solidified function: encode
|
||||
********************************************************************/
|
||||
be_local_closure(Matter_Pake2_encode, /* name */
|
||||
be_nested_proto(
|
||||
8, /* nstack */
|
||||
2, /* argc */
|
||||
2, /* varg */
|
||||
0, /* has upvals */
|
||||
NULL, /* no upvals */
|
||||
0, /* has sup protos */
|
||||
NULL, /* no sub protos */
|
||||
1, /* has constants */
|
||||
( &(const bvalue[10]) { /* constants */
|
||||
/* K0 */ be_nested_str_weak(matter),
|
||||
/* K1 */ be_nested_str_weak(TLV),
|
||||
/* K2 */ be_nested_str_weak(Matter_TLV_struct),
|
||||
/* K3 */ be_nested_str_weak(add_TLV),
|
||||
/* K4 */ be_const_int(1),
|
||||
/* K5 */ be_nested_str_weak(B1),
|
||||
/* K6 */ be_nested_str_weak(pB),
|
||||
/* K7 */ be_const_int(2),
|
||||
/* K8 */ be_nested_str_weak(cB),
|
||||
/* K9 */ be_nested_str_weak(encode),
|
||||
}),
|
||||
be_str_weak(encode),
|
||||
&be_const_str_solidified,
|
||||
( &(const binstruction[21]) { /* code */
|
||||
0xB80A0000, // 0000 GETNGBL R2 K0
|
||||
0x88080501, // 0001 GETMBR R2 R2 K1
|
||||
0x8C080502, // 0002 GETMET R2 R2 K2
|
||||
0x7C080200, // 0003 CALL R2 1
|
||||
0x8C0C0503, // 0004 GETMET R3 R2 K3
|
||||
0x58140004, // 0005 LDCONST R5 K4
|
||||
0xB81A0000, // 0006 GETNGBL R6 K0
|
||||
0x88180D01, // 0007 GETMBR R6 R6 K1
|
||||
0x88180D05, // 0008 GETMBR R6 R6 K5
|
||||
0x881C0106, // 0009 GETMBR R7 R0 K6
|
||||
0x7C0C0800, // 000A CALL R3 4
|
||||
0x8C0C0503, // 000B GETMET R3 R2 K3
|
||||
0x58140007, // 000C LDCONST R5 K7
|
||||
0xB81A0000, // 000D GETNGBL R6 K0
|
||||
0x88180D01, // 000E GETMBR R6 R6 K1
|
||||
0x88180D05, // 000F GETMBR R6 R6 K5
|
||||
0x881C0108, // 0010 GETMBR R7 R0 K8
|
||||
0x7C0C0800, // 0011 CALL R3 4
|
||||
0x8C0C0509, // 0012 GETMET R3 R2 K9
|
||||
0x7C0C0200, // 0013 CALL R3 1
|
||||
0x80040600, // 0014 RET 1 R3
|
||||
})
|
||||
)
|
||||
);
|
||||
/*******************************************************************/
|
||||
|
||||
|
||||
/********************************************************************
|
||||
** Solidified class: Matter_Pake2
|
||||
********************************************************************/
|
||||
be_local_class(Matter_Pake2,
|
||||
2,
|
||||
NULL,
|
||||
be_nested_map(3,
|
||||
( (struct bmapnode*) &(const bmapnode[]) {
|
||||
{ be_const_key_weak(encode, -1), be_const_closure(Matter_Pake2_encode_closure) },
|
||||
{ be_const_key_weak(cB, -1), be_const_var(1) },
|
||||
{ be_const_key_weak(pB, 0), be_const_var(0) },
|
||||
})),
|
||||
be_str_weak(Matter_Pake2)
|
||||
);
|
||||
/*******************************************************************/
|
||||
|
||||
void be_load_Matter_Pake2_class(bvm *vm) {
|
||||
be_pushntvclass(vm, &be_class_Matter_Pake2);
|
||||
be_setglobal(vm, "Matter_Pake2");
|
||||
be_pop(vm, 1);
|
||||
}
|
||||
|
||||
extern const bclass be_class_Matter_Pake3;
|
||||
|
||||
/********************************************************************
|
||||
** Solidified function: parse
|
||||
********************************************************************/
|
||||
be_local_closure(Matter_Pake3_parse, /* name */
|
||||
be_nested_proto(
|
||||
8, /* nstack */
|
||||
3, /* argc */
|
||||
2, /* varg */
|
||||
0, /* has upvals */
|
||||
NULL, /* no upvals */
|
||||
0, /* has sup protos */
|
||||
NULL, /* no sub protos */
|
||||
1, /* has constants */
|
||||
( &(const bvalue[11]) { /* constants */
|
||||
/* K0 */ be_const_int(0),
|
||||
/* K1 */ be_nested_str_weak(matter),
|
||||
/* K2 */ be_nested_str_weak(TLV),
|
||||
/* K3 */ be_nested_str_weak(parse),
|
||||
/* K4 */ be_nested_str_weak(tasmota),
|
||||
/* K5 */ be_nested_str_weak(log),
|
||||
/* K6 */ be_nested_str_weak(MTR_X3A_X20parsed_X20TLV_X3A_X20),
|
||||
/* K7 */ be_const_int(3),
|
||||
/* K8 */ be_nested_str_weak(cA),
|
||||
/* K9 */ be_nested_str_weak(getsubval),
|
||||
/* K10 */ be_const_int(1),
|
||||
}),
|
||||
be_str_weak(parse),
|
||||
&be_const_str_solidified,
|
||||
( &(const binstruction[23]) { /* code */
|
||||
0x4C0C0000, // 0000 LDNIL R3
|
||||
0x1C0C0403, // 0001 EQ R3 R2 R3
|
||||
0x780E0000, // 0002 JMPF R3 #0004
|
||||
0x58080000, // 0003 LDCONST R2 K0
|
||||
0xB80E0200, // 0004 GETNGBL R3 K1
|
||||
0x880C0702, // 0005 GETMBR R3 R3 K2
|
||||
0x8C0C0703, // 0006 GETMET R3 R3 K3
|
||||
0x5C140200, // 0007 MOVE R5 R1
|
||||
0x5C180400, // 0008 MOVE R6 R2
|
||||
0x7C0C0600, // 0009 CALL R3 3
|
||||
0xB8120800, // 000A GETNGBL R4 K4
|
||||
0x8C100905, // 000B GETMET R4 R4 K5
|
||||
0x60180008, // 000C GETGBL R6 G8
|
||||
0x5C1C0600, // 000D MOVE R7 R3
|
||||
0x7C180200, // 000E CALL R6 1
|
||||
0x001A0C06, // 000F ADD R6 K6 R6
|
||||
0x581C0007, // 0010 LDCONST R7 K7
|
||||
0x7C100600, // 0011 CALL R4 3
|
||||
0x8C100709, // 0012 GETMET R4 R3 K9
|
||||
0x5818000A, // 0013 LDCONST R6 K10
|
||||
0x7C100400, // 0014 CALL R4 2
|
||||
0x90021004, // 0015 SETMBR R0 K8 R4
|
||||
0x80040000, // 0016 RET 1 R0
|
||||
})
|
||||
)
|
||||
);
|
||||
/*******************************************************************/
|
||||
|
||||
|
||||
/********************************************************************
|
||||
** Solidified class: Matter_Pake3
|
||||
********************************************************************/
|
||||
be_local_class(Matter_Pake3,
|
||||
1,
|
||||
NULL,
|
||||
be_nested_map(2,
|
||||
( (struct bmapnode*) &(const bmapnode[]) {
|
||||
{ be_const_key_weak(parse, -1), be_const_closure(Matter_Pake3_parse_closure) },
|
||||
{ be_const_key_weak(cA, -1), be_const_var(0) },
|
||||
})),
|
||||
be_str_weak(Matter_Pake3)
|
||||
);
|
||||
/*******************************************************************/
|
||||
|
||||
void be_load_Matter_Pake3_class(bvm *vm) {
|
||||
be_pushntvclass(vm, &be_class_Matter_Pake3);
|
||||
be_setglobal(vm, "Matter_Pake3");
|
||||
be_pop(vm, 1);
|
||||
}
|
||||
|
||||
extern const bclass be_class_Matter_Sigma1;
|
||||
|
||||
/********************************************************************
|
||||
** Solidified function: parse
|
||||
********************************************************************/
|
||||
be_local_closure(Matter_Sigma1_parse, /* name */
|
||||
be_nested_proto(
|
||||
9, /* nstack */
|
||||
3, /* argc */
|
||||
2, /* varg */
|
||||
0, /* has upvals */
|
||||
NULL, /* no upvals */
|
||||
0, /* has sup protos */
|
||||
NULL, /* no sub protos */
|
||||
1, /* has constants */
|
||||
( &(const bvalue[21]) { /* constants */
|
||||
/* K0 */ be_const_int(0),
|
||||
/* K1 */ be_nested_str_weak(matter),
|
||||
/* K2 */ be_nested_str_weak(TLV),
|
||||
/* K3 */ be_nested_str_weak(parse),
|
||||
/* K4 */ be_nested_str_weak(Msg1),
|
||||
/* K5 */ be_const_int(2147483647),
|
||||
/* K6 */ be_nested_str_weak(tasmota),
|
||||
/* K7 */ be_nested_str_weak(log),
|
||||
/* K8 */ be_nested_str_weak(MTR_X3A_X20Sigma1_X20TLV_X3D),
|
||||
/* K9 */ be_const_int(3),
|
||||
/* K10 */ be_nested_str_weak(initiatorRandom),
|
||||
/* K11 */ be_nested_str_weak(getsubval),
|
||||
/* K12 */ be_const_int(1),
|
||||
/* K13 */ be_nested_str_weak(initiator_session_id),
|
||||
/* K14 */ be_const_int(2),
|
||||
/* K15 */ be_nested_str_weak(destinationId),
|
||||
/* K16 */ be_nested_str_weak(initiatorEphPubKey),
|
||||
/* K17 */ be_nested_str_weak(findsub),
|
||||
/* K18 */ be_nested_str_weak(SLEEPY_IDLE_INTERVAL),
|
||||
/* K19 */ be_nested_str_weak(findsubval),
|
||||
/* K20 */ be_nested_str_weak(SLEEPY_ACTIVE_INTERVAL),
|
||||
}),
|
||||
be_str_weak(parse),
|
||||
&be_const_str_solidified,
|
||||
( &(const binstruction[58]) { /* code */
|
||||
0x4C0C0000, // 0000 LDNIL R3
|
||||
0x1C0C0403, // 0001 EQ R3 R2 R3
|
||||
0x780E0000, // 0002 JMPF R3 #0004
|
||||
0x58080000, // 0003 LDCONST R2 K0
|
||||
0xB80E0200, // 0004 GETNGBL R3 K1
|
||||
0x880C0702, // 0005 GETMBR R3 R3 K2
|
||||
0x8C0C0703, // 0006 GETMET R3 R3 K3
|
||||
0x5C140200, // 0007 MOVE R5 R1
|
||||
0x5C180400, // 0008 MOVE R6 R2
|
||||
0x7C0C0600, // 0009 CALL R3 3
|
||||
0x40100505, // 000A CONNECT R4 R2 K5
|
||||
0x94100204, // 000B GETIDX R4 R1 R4
|
||||
0x90020804, // 000C SETMBR R0 K4 R4
|
||||
0xB8120C00, // 000D GETNGBL R4 K6
|
||||
0x8C100907, // 000E GETMET R4 R4 K7
|
||||
0x60180008, // 000F GETGBL R6 G8
|
||||
0x5C1C0600, // 0010 MOVE R7 R3
|
||||
0x7C180200, // 0011 CALL R6 1
|
||||
0x001A1006, // 0012 ADD R6 K8 R6
|
||||
0x581C0009, // 0013 LDCONST R7 K9
|
||||
0x7C100600, // 0014 CALL R4 3
|
||||
0x8C10070B, // 0015 GETMET R4 R3 K11
|
||||
0x5818000C, // 0016 LDCONST R6 K12
|
||||
0x7C100400, // 0017 CALL R4 2
|
||||
0x90021404, // 0018 SETMBR R0 K10 R4
|
||||
0x8C10070B, // 0019 GETMET R4 R3 K11
|
||||
0x5818000E, // 001A LDCONST R6 K14
|
||||
0x7C100400, // 001B CALL R4 2
|
||||
0x90021A04, // 001C SETMBR R0 K13 R4
|
||||
0x8C10070B, // 001D GETMET R4 R3 K11
|
||||
0x58180009, // 001E LDCONST R6 K9
|
||||
0x7C100400, // 001F CALL R4 2
|
||||
0x90021E04, // 0020 SETMBR R0 K15 R4
|
||||
0x8C10070B, // 0021 GETMET R4 R3 K11
|
||||
0x541A0003, // 0022 LDINT R6 4
|
||||
0x7C100400, // 0023 CALL R4 2
|
||||
0x90022004, // 0024 SETMBR R0 K16 R4
|
||||
0x8C100711, // 0025 GETMET R4 R3 K17
|
||||
0x541A0004, // 0026 LDINT R6 5
|
||||
0x7C100400, // 0027 CALL R4 2
|
||||
0x4C140000, // 0028 LDNIL R5
|
||||
0x20140805, // 0029 NE R5 R4 R5
|
||||
0x78160007, // 002A JMPF R5 #0033
|
||||
0x8C140913, // 002B GETMET R5 R4 K19
|
||||
0x581C000C, // 002C LDCONST R7 K12
|
||||
0x7C140400, // 002D CALL R5 2
|
||||
0x90022405, // 002E SETMBR R0 K18 R5
|
||||
0x8C140913, // 002F GETMET R5 R4 K19
|
||||
0x581C000E, // 0030 LDCONST R7 K14
|
||||
0x7C140400, // 0031 CALL R5 2
|
||||
0x90022805, // 0032 SETMBR R0 K20 R5
|
||||
0x8C140711, // 0033 GETMET R5 R3 K17
|
||||
0x541E0005, // 0034 LDINT R7 6
|
||||
0x7C140400, // 0035 CALL R5 2
|
||||
0x8C180711, // 0036 GETMET R6 R3 K17
|
||||
0x54220006, // 0037 LDINT R8 7
|
||||
0x7C180400, // 0038 CALL R6 2
|
||||
0x80040000, // 0039 RET 1 R0
|
||||
})
|
||||
)
|
||||
);
|
||||
/*******************************************************************/
|
||||
|
||||
|
||||
/********************************************************************
|
||||
** Solidified class: Matter_Sigma1
|
||||
********************************************************************/
|
||||
be_local_class(Matter_Sigma1,
|
||||
9,
|
||||
NULL,
|
||||
be_nested_map(10,
|
||||
( (struct bmapnode*) &(const bmapnode[]) {
|
||||
{ be_const_key_weak(SLEEPY_ACTIVE_INTERVAL, -1), be_const_var(5) },
|
||||
{ be_const_key_weak(Msg1, -1), be_const_var(8) },
|
||||
{ be_const_key_weak(parse, 6), be_const_closure(Matter_Sigma1_parse_closure) },
|
||||
{ be_const_key_weak(initiatorRandom, -1), be_const_var(0) },
|
||||
{ be_const_key_weak(SLEEPY_IDLE_INTERVAL, 7), be_const_var(4) },
|
||||
{ be_const_key_weak(initiatorEphPubKey, -1), be_const_var(3) },
|
||||
{ be_const_key_weak(initiatorResumeMIC, -1), be_const_var(7) },
|
||||
{ be_const_key_weak(resumptionID, -1), be_const_var(6) },
|
||||
{ be_const_key_weak(destinationId, -1), be_const_var(2) },
|
||||
{ be_const_key_weak(initiator_session_id, 1), be_const_var(1) },
|
||||
})),
|
||||
be_str_weak(Matter_Sigma1)
|
||||
);
|
||||
/*******************************************************************/
|
||||
|
||||
void be_load_Matter_Sigma1_class(bvm *vm) {
|
||||
be_pushntvclass(vm, &be_class_Matter_Sigma1);
|
||||
be_setglobal(vm, "Matter_Sigma1");
|
||||
be_pop(vm, 1);
|
||||
}
|
||||
|
||||
extern const bclass be_class_Matter_Sigma2;
|
||||
|
||||
/********************************************************************
|
||||
** Solidified function: encode
|
||||
********************************************************************/
|
||||
be_local_closure(Matter_Sigma2_encode, /* name */
|
||||
be_nested_proto(
|
||||
9, /* nstack */
|
||||
2, /* argc */
|
||||
2, /* varg */
|
||||
0, /* has upvals */
|
||||
NULL, /* no upvals */
|
||||
0, /* has sup protos */
|
||||
NULL, /* no sub protos */
|
||||
1, /* has constants */
|
||||
( &(const bvalue[18]) { /* constants */
|
||||
/* K0 */ be_nested_str_weak(matter),
|
||||
/* K1 */ be_nested_str_weak(TLV),
|
||||
/* K2 */ be_nested_str_weak(Matter_TLV_struct),
|
||||
/* K3 */ be_nested_str_weak(add_TLV),
|
||||
/* K4 */ be_const_int(1),
|
||||
/* K5 */ be_nested_str_weak(B1),
|
||||
/* K6 */ be_nested_str_weak(responderRandom),
|
||||
/* K7 */ be_const_int(2),
|
||||
/* K8 */ be_nested_str_weak(U2),
|
||||
/* K9 */ be_nested_str_weak(responderSessionId),
|
||||
/* K10 */ be_const_int(3),
|
||||
/* K11 */ be_nested_str_weak(responderEphPubKey),
|
||||
/* K12 */ be_nested_str_weak(encrypted2),
|
||||
/* K13 */ be_nested_str_weak(SLEEPY_IDLE_INTERVAL),
|
||||
/* K14 */ be_nested_str_weak(SLEEPY_ACTIVE_INTERVAL),
|
||||
/* K15 */ be_nested_str_weak(add_struct),
|
||||
/* K16 */ be_nested_str_weak(U4),
|
||||
/* K17 */ be_nested_str_weak(encode),
|
||||
}),
|
||||
be_str_weak(encode),
|
||||
&be_const_str_solidified,
|
||||
( &(const binstruction[60]) { /* code */
|
||||
0xB80A0000, // 0000 GETNGBL R2 K0
|
||||
0x88080501, // 0001 GETMBR R2 R2 K1
|
||||
0x8C080502, // 0002 GETMET R2 R2 K2
|
||||
0x7C080200, // 0003 CALL R2 1
|
||||
0x8C0C0503, // 0004 GETMET R3 R2 K3
|
||||
0x58140004, // 0005 LDCONST R5 K4
|
||||
0xB81A0000, // 0006 GETNGBL R6 K0
|
||||
0x88180D01, // 0007 GETMBR R6 R6 K1
|
||||
0x88180D05, // 0008 GETMBR R6 R6 K5
|
||||
0x881C0106, // 0009 GETMBR R7 R0 K6
|
||||
0x7C0C0800, // 000A CALL R3 4
|
||||
0x8C0C0503, // 000B GETMET R3 R2 K3
|
||||
0x58140007, // 000C LDCONST R5 K7
|
||||
0xB81A0000, // 000D GETNGBL R6 K0
|
||||
0x88180D01, // 000E GETMBR R6 R6 K1
|
||||
0x88180D08, // 000F GETMBR R6 R6 K8
|
||||
0x881C0109, // 0010 GETMBR R7 R0 K9
|
||||
0x7C0C0800, // 0011 CALL R3 4
|
||||
0x8C0C0503, // 0012 GETMET R3 R2 K3
|
||||
0x5814000A, // 0013 LDCONST R5 K10
|
||||
0xB81A0000, // 0014 GETNGBL R6 K0
|
||||
0x88180D01, // 0015 GETMBR R6 R6 K1
|
||||
0x88180D05, // 0016 GETMBR R6 R6 K5
|
||||
0x881C010B, // 0017 GETMBR R7 R0 K11
|
||||
0x7C0C0800, // 0018 CALL R3 4
|
||||
0x8C0C0503, // 0019 GETMET R3 R2 K3
|
||||
0x54160003, // 001A LDINT R5 4
|
||||
0xB81A0000, // 001B GETNGBL R6 K0
|
||||
0x88180D01, // 001C GETMBR R6 R6 K1
|
||||
0x88180D05, // 001D GETMBR R6 R6 K5
|
||||
0x881C010C, // 001E GETMBR R7 R0 K12
|
||||
0x7C0C0800, // 001F CALL R3 4
|
||||
0x880C010D, // 0020 GETMBR R3 R0 K13
|
||||
0x4C100000, // 0021 LDNIL R4
|
||||
0x200C0604, // 0022 NE R3 R3 R4
|
||||
0x740E0003, // 0023 JMPT R3 #0028
|
||||
0x880C010E, // 0024 GETMBR R3 R0 K14
|
||||
0x4C100000, // 0025 LDNIL R4
|
||||
0x200C0604, // 0026 NE R3 R3 R4
|
||||
0x780E0010, // 0027 JMPF R3 #0039
|
||||
0x8C0C050F, // 0028 GETMET R3 R2 K15
|
||||
0x54160004, // 0029 LDINT R5 5
|
||||
0x7C0C0400, // 002A CALL R3 2
|
||||
0x8C100703, // 002B GETMET R4 R3 K3
|
||||
0x58180004, // 002C LDCONST R6 K4
|
||||
0xB81E0000, // 002D GETNGBL R7 K0
|
||||
0x881C0F01, // 002E GETMBR R7 R7 K1
|
||||
0x881C0F10, // 002F GETMBR R7 R7 K16
|
||||
0x8820010D, // 0030 GETMBR R8 R0 K13
|
||||
0x7C100800, // 0031 CALL R4 4
|
||||
0x8C100703, // 0032 GETMET R4 R3 K3
|
||||
0x58180007, // 0033 LDCONST R6 K7
|
||||
0xB81E0000, // 0034 GETNGBL R7 K0
|
||||
0x881C0F01, // 0035 GETMBR R7 R7 K1
|
||||
0x881C0F10, // 0036 GETMBR R7 R7 K16
|
||||
0x8820010E, // 0037 GETMBR R8 R0 K14
|
||||
0x7C100800, // 0038 CALL R4 4
|
||||
0x8C0C0511, // 0039 GETMET R3 R2 K17
|
||||
0x7C0C0200, // 003A CALL R3 1
|
||||
0x80040600, // 003B RET 1 R3
|
||||
})
|
||||
)
|
||||
);
|
||||
/*******************************************************************/
|
||||
|
||||
|
||||
/********************************************************************
|
||||
** Solidified class: Matter_Sigma2
|
||||
********************************************************************/
|
||||
be_local_class(Matter_Sigma2,
|
||||
6,
|
||||
NULL,
|
||||
be_nested_map(7,
|
||||
( (struct bmapnode*) &(const bmapnode[]) {
|
||||
{ be_const_key_weak(encrypted2, -1), be_const_var(3) },
|
||||
{ be_const_key_weak(encode, -1), be_const_closure(Matter_Sigma2_encode_closure) },
|
||||
{ be_const_key_weak(responderSessionId, -1), be_const_var(1) },
|
||||
{ be_const_key_weak(SLEEPY_IDLE_INTERVAL, 6), be_const_var(4) },
|
||||
{ be_const_key_weak(SLEEPY_ACTIVE_INTERVAL, 0), be_const_var(5) },
|
||||
{ be_const_key_weak(responderRandom, 3), be_const_var(0) },
|
||||
{ be_const_key_weak(responderEphPubKey, -1), be_const_var(2) },
|
||||
})),
|
||||
be_str_weak(Matter_Sigma2)
|
||||
);
|
||||
/*******************************************************************/
|
||||
|
||||
void be_load_Matter_Sigma2_class(bvm *vm) {
|
||||
be_pushntvclass(vm, &be_class_Matter_Sigma2);
|
||||
be_setglobal(vm, "Matter_Sigma2");
|
||||
be_pop(vm, 1);
|
||||
}
|
||||
|
||||
extern const bclass be_class_Matter_Sigma2Resume;
|
||||
|
||||
/********************************************************************
|
||||
** Solidified function: encode
|
||||
********************************************************************/
|
||||
be_local_closure(Matter_Sigma2Resume_encode, /* name */
|
||||
be_nested_proto(
|
||||
9, /* nstack */
|
||||
2, /* argc */
|
||||
2, /* varg */
|
||||
0, /* has upvals */
|
||||
NULL, /* no upvals */
|
||||
0, /* has sup protos */
|
||||
NULL, /* no sub protos */
|
||||
1, /* has constants */
|
||||
( &(const bvalue[16]) { /* constants */
|
||||
/* K0 */ be_nested_str_weak(matter),
|
||||
/* K1 */ be_nested_str_weak(TLV),
|
||||
/* K2 */ be_nested_str_weak(Matter_TLV_struct),
|
||||
/* K3 */ be_nested_str_weak(add_TLV),
|
||||
/* K4 */ be_const_int(1),
|
||||
/* K5 */ be_nested_str_weak(B1),
|
||||
/* K6 */ be_nested_str_weak(resumptionID),
|
||||
/* K7 */ be_const_int(2),
|
||||
/* K8 */ be_nested_str_weak(sigma2ResumeMIC),
|
||||
/* K9 */ be_const_int(3),
|
||||
/* K10 */ be_nested_str_weak(responderSessionID),
|
||||
/* K11 */ be_nested_str_weak(SLEEPY_IDLE_INTERVAL),
|
||||
/* K12 */ be_nested_str_weak(SLEEPY_ACTIVE_INTERVAL),
|
||||
/* K13 */ be_nested_str_weak(add_struct),
|
||||
/* K14 */ be_nested_str_weak(U4),
|
||||
/* K15 */ be_nested_str_weak(encode),
|
||||
}),
|
||||
be_str_weak(encode),
|
||||
&be_const_str_solidified,
|
||||
( &(const binstruction[53]) { /* code */
|
||||
0xB80A0000, // 0000 GETNGBL R2 K0
|
||||
0x88080501, // 0001 GETMBR R2 R2 K1
|
||||
0x8C080502, // 0002 GETMET R2 R2 K2
|
||||
0x7C080200, // 0003 CALL R2 1
|
||||
0x8C0C0503, // 0004 GETMET R3 R2 K3
|
||||
0x58140004, // 0005 LDCONST R5 K4
|
||||
0xB81A0000, // 0006 GETNGBL R6 K0
|
||||
0x88180D01, // 0007 GETMBR R6 R6 K1
|
||||
0x88180D05, // 0008 GETMBR R6 R6 K5
|
||||
0x881C0106, // 0009 GETMBR R7 R0 K6
|
||||
0x7C0C0800, // 000A CALL R3 4
|
||||
0x8C0C0503, // 000B GETMET R3 R2 K3
|
||||
0x58140007, // 000C LDCONST R5 K7
|
||||
0xB81A0000, // 000D GETNGBL R6 K0
|
||||
0x88180D01, // 000E GETMBR R6 R6 K1
|
||||
0x88180D05, // 000F GETMBR R6 R6 K5
|
||||
0x881C0108, // 0010 GETMBR R7 R0 K8
|
||||
0x7C0C0800, // 0011 CALL R3 4
|
||||
0x8C0C0503, // 0012 GETMET R3 R2 K3
|
||||
0x58140009, // 0013 LDCONST R5 K9
|
||||
0xB81A0000, // 0014 GETNGBL R6 K0
|
||||
0x88180D01, // 0015 GETMBR R6 R6 K1
|
||||
0x88180D05, // 0016 GETMBR R6 R6 K5
|
||||
0x881C010A, // 0017 GETMBR R7 R0 K10
|
||||
0x7C0C0800, // 0018 CALL R3 4
|
||||
0x880C010B, // 0019 GETMBR R3 R0 K11
|
||||
0x4C100000, // 001A LDNIL R4
|
||||
0x200C0604, // 001B NE R3 R3 R4
|
||||
0x740E0003, // 001C JMPT R3 #0021
|
||||
0x880C010C, // 001D GETMBR R3 R0 K12
|
||||
0x4C100000, // 001E LDNIL R4
|
||||
0x200C0604, // 001F NE R3 R3 R4
|
||||
0x780E0010, // 0020 JMPF R3 #0032
|
||||
0x8C0C050D, // 0021 GETMET R3 R2 K13
|
||||
0x54160003, // 0022 LDINT R5 4
|
||||
0x7C0C0400, // 0023 CALL R3 2
|
||||
0x8C100703, // 0024 GETMET R4 R3 K3
|
||||
0x58180004, // 0025 LDCONST R6 K4
|
||||
0xB81E0000, // 0026 GETNGBL R7 K0
|
||||
0x881C0F01, // 0027 GETMBR R7 R7 K1
|
||||
0x881C0F0E, // 0028 GETMBR R7 R7 K14
|
||||
0x8820010B, // 0029 GETMBR R8 R0 K11
|
||||
0x7C100800, // 002A CALL R4 4
|
||||
0x8C100703, // 002B GETMET R4 R3 K3
|
||||
0x58180007, // 002C LDCONST R6 K7
|
||||
0xB81E0000, // 002D GETNGBL R7 K0
|
||||
0x881C0F01, // 002E GETMBR R7 R7 K1
|
||||
0x881C0F0E, // 002F GETMBR R7 R7 K14
|
||||
0x8820010C, // 0030 GETMBR R8 R0 K12
|
||||
0x7C100800, // 0031 CALL R4 4
|
||||
0x8C0C050F, // 0032 GETMET R3 R2 K15
|
||||
0x7C0C0200, // 0033 CALL R3 1
|
||||
0x80040600, // 0034 RET 1 R3
|
||||
})
|
||||
)
|
||||
);
|
||||
/*******************************************************************/
|
||||
|
||||
|
||||
/********************************************************************
|
||||
** Solidified class: Matter_Sigma2Resume
|
||||
********************************************************************/
|
||||
be_local_class(Matter_Sigma2Resume,
|
||||
5,
|
||||
NULL,
|
||||
be_nested_map(6,
|
||||
( (struct bmapnode*) &(const bmapnode[]) {
|
||||
{ be_const_key_weak(SLEEPY_IDLE_INTERVAL, 3), be_const_var(3) },
|
||||
{ be_const_key_weak(resumptionID, -1), be_const_var(0) },
|
||||
{ be_const_key_weak(sigma2ResumeMIC, -1), be_const_var(1) },
|
||||
{ be_const_key_weak(responderSessionID, 1), be_const_var(2) },
|
||||
{ be_const_key_weak(SLEEPY_ACTIVE_INTERVAL, -1), be_const_var(4) },
|
||||
{ be_const_key_weak(encode, -1), be_const_closure(Matter_Sigma2Resume_encode_closure) },
|
||||
})),
|
||||
be_str_weak(Matter_Sigma2Resume)
|
||||
);
|
||||
/*******************************************************************/
|
||||
|
||||
void be_load_Matter_Sigma2Resume_class(bvm *vm) {
|
||||
be_pushntvclass(vm, &be_class_Matter_Sigma2Resume);
|
||||
be_setglobal(vm, "Matter_Sigma2Resume");
|
||||
be_pop(vm, 1);
|
||||
}
|
||||
|
||||
extern const bclass be_class_Matter_Sigma3;
|
||||
|
||||
/********************************************************************
|
||||
** Solidified function: parse
|
||||
********************************************************************/
|
||||
be_local_closure(Matter_Sigma3_parse, /* name */
|
||||
be_nested_proto(
|
||||
8, /* nstack */
|
||||
3, /* argc */
|
||||
2, /* varg */
|
||||
0, /* has upvals */
|
||||
NULL, /* no upvals */
|
||||
0, /* has sup protos */
|
||||
NULL, /* no sub protos */
|
||||
1, /* has constants */
|
||||
( &(const bvalue[13]) { /* constants */
|
||||
/* K0 */ be_const_int(0),
|
||||
/* K1 */ be_nested_str_weak(matter),
|
||||
/* K2 */ be_nested_str_weak(TLV),
|
||||
/* K3 */ be_nested_str_weak(parse),
|
||||
/* K4 */ be_nested_str_weak(Msg3),
|
||||
/* K5 */ be_const_int(2147483647),
|
||||
/* K6 */ be_nested_str_weak(tasmota),
|
||||
/* K7 */ be_nested_str_weak(log),
|
||||
/* K8 */ be_nested_str_weak(MTR_X3A_X20Sigma3_X20TLV_X3D),
|
||||
/* K9 */ be_const_int(3),
|
||||
/* K10 */ be_nested_str_weak(TBEData3Encrypted),
|
||||
/* K11 */ be_nested_str_weak(getsubval),
|
||||
/* K12 */ be_const_int(1),
|
||||
}),
|
||||
be_str_weak(parse),
|
||||
&be_const_str_solidified,
|
||||
( &(const binstruction[26]) { /* code */
|
||||
0x4C0C0000, // 0000 LDNIL R3
|
||||
0x1C0C0403, // 0001 EQ R3 R2 R3
|
||||
0x780E0000, // 0002 JMPF R3 #0004
|
||||
0x58080000, // 0003 LDCONST R2 K0
|
||||
0xB80E0200, // 0004 GETNGBL R3 K1
|
||||
0x880C0702, // 0005 GETMBR R3 R3 K2
|
||||
0x8C0C0703, // 0006 GETMET R3 R3 K3
|
||||
0x5C140200, // 0007 MOVE R5 R1
|
||||
0x5C180400, // 0008 MOVE R6 R2
|
||||
0x7C0C0600, // 0009 CALL R3 3
|
||||
0x40100505, // 000A CONNECT R4 R2 K5
|
||||
0x94100204, // 000B GETIDX R4 R1 R4
|
||||
0x90020804, // 000C SETMBR R0 K4 R4
|
||||
0xB8120C00, // 000D GETNGBL R4 K6
|
||||
0x8C100907, // 000E GETMET R4 R4 K7
|
||||
0x60180008, // 000F GETGBL R6 G8
|
||||
0x5C1C0600, // 0010 MOVE R7 R3
|
||||
0x7C180200, // 0011 CALL R6 1
|
||||
0x001A1006, // 0012 ADD R6 K8 R6
|
||||
0x581C0009, // 0013 LDCONST R7 K9
|
||||
0x7C100600, // 0014 CALL R4 3
|
||||
0x8C10070B, // 0015 GETMET R4 R3 K11
|
||||
0x5818000C, // 0016 LDCONST R6 K12
|
||||
0x7C100400, // 0017 CALL R4 2
|
||||
0x90021404, // 0018 SETMBR R0 K10 R4
|
||||
0x80040000, // 0019 RET 1 R0
|
||||
})
|
||||
)
|
||||
);
|
||||
/*******************************************************************/
|
||||
|
||||
|
||||
/********************************************************************
|
||||
** Solidified class: Matter_Sigma3
|
||||
********************************************************************/
|
||||
be_local_class(Matter_Sigma3,
|
||||
2,
|
||||
NULL,
|
||||
be_nested_map(3,
|
||||
( (struct bmapnode*) &(const bmapnode[]) {
|
||||
{ be_const_key_weak(TBEData3Encrypted, 2), be_const_var(0) },
|
||||
{ be_const_key_weak(parse, -1), be_const_closure(Matter_Sigma3_parse_closure) },
|
||||
{ be_const_key_weak(Msg3, -1), be_const_var(1) },
|
||||
})),
|
||||
be_str_weak(Matter_Sigma3)
|
||||
);
|
||||
/*******************************************************************/
|
||||
|
||||
void be_load_Matter_Sigma3_class(bvm *vm) {
|
||||
be_pushntvclass(vm, &be_class_Matter_Sigma3);
|
||||
be_setglobal(vm, "Matter_Sigma3");
|
||||
be_pop(vm, 1);
|
||||
}
|
||||
/********************************************************************/
|
||||
/* End of solidification */
|
2136
lib/libesp32/berry_matter/src/solidify/solidified_Matter_Device.h
Normal file
2136
lib/libesp32/berry_matter/src/solidify/solidified_Matter_Device.h
Normal file
File diff suppressed because it is too large
Load Diff
1274
lib/libesp32/berry_matter/src/solidify/solidified_Matter_IM.h
Normal file
1274
lib/libesp32/berry_matter/src/solidify/solidified_Matter_IM.h
Normal file
File diff suppressed because it is too large
Load Diff
4020
lib/libesp32/berry_matter/src/solidify/solidified_Matter_IM_Data.h
Normal file
4020
lib/libesp32/berry_matter/src/solidify/solidified_Matter_IM_Data.h
Normal file
File diff suppressed because it is too large
Load Diff
1227
lib/libesp32/berry_matter/src/solidify/solidified_Matter_Message.h
Normal file
1227
lib/libesp32/berry_matter/src/solidify/solidified_Matter_Message.h
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,582 @@
|
||||
/* Solidification of Matter_MessageHandler.h */
|
||||
/********************************************************************\
|
||||
* Generated code, don't edit *
|
||||
\********************************************************************/
|
||||
#include "be_constobj.h"
|
||||
|
||||
extern const bclass be_class_Matter_MessageHandler;
|
||||
|
||||
/********************************************************************
|
||||
** Solidified function: send_response
|
||||
********************************************************************/
|
||||
be_local_closure(Matter_MessageHandler_send_response, /* name */
|
||||
be_nested_proto(
|
||||
11, /* nstack */
|
||||
5, /* argc */
|
||||
2, /* varg */
|
||||
0, /* has upvals */
|
||||
NULL, /* no upvals */
|
||||
0, /* has sup protos */
|
||||
NULL, /* no sub protos */
|
||||
1, /* has constants */
|
||||
( &(const bvalue[ 2]) { /* constants */
|
||||
/* K0 */ be_nested_str_weak(device),
|
||||
/* K1 */ be_nested_str_weak(msg_send),
|
||||
}),
|
||||
be_str_weak(send_response),
|
||||
&be_const_str_solidified,
|
||||
( &(const binstruction[ 8]) { /* code */
|
||||
0x88140100, // 0000 GETMBR R5 R0 K0
|
||||
0x8C140B01, // 0001 GETMET R5 R5 K1
|
||||
0x5C1C0200, // 0002 MOVE R7 R1
|
||||
0x5C200400, // 0003 MOVE R8 R2
|
||||
0x5C240600, // 0004 MOVE R9 R3
|
||||
0x5C280800, // 0005 MOVE R10 R4
|
||||
0x7C140A00, // 0006 CALL R5 5
|
||||
0x80000000, // 0007 RET 0
|
||||
})
|
||||
)
|
||||
);
|
||||
/*******************************************************************/
|
||||
|
||||
|
||||
/********************************************************************
|
||||
** Solidified function: msg_received
|
||||
********************************************************************/
|
||||
be_local_closure(Matter_MessageHandler_msg_received, /* name */
|
||||
be_nested_proto(
|
||||
17, /* nstack */
|
||||
4, /* argc */
|
||||
2, /* varg */
|
||||
0, /* has upvals */
|
||||
NULL, /* no upvals */
|
||||
0, /* has sup protos */
|
||||
NULL, /* no sub protos */
|
||||
1, /* has constants */
|
||||
( &(const bvalue[59]) { /* constants */
|
||||
/* K0 */ be_nested_str_weak(string),
|
||||
/* K1 */ be_nested_str_weak(tasmota),
|
||||
/* K2 */ be_nested_str_weak(log),
|
||||
/* K3 */ be_nested_str_weak(MTR_X3A_X20MessageHandler_X3A_X3Amsg_received_X20raw_X3D),
|
||||
/* K4 */ be_nested_str_weak(tohex),
|
||||
/* K5 */ be_nested_str_weak(matter),
|
||||
/* K6 */ be_nested_str_weak(Frame),
|
||||
/* K7 */ be_nested_str_weak(decode_header),
|
||||
/* K8 */ be_nested_str_weak(local_session_id),
|
||||
/* K9 */ be_const_int(0),
|
||||
/* K10 */ be_nested_str_weak(sec_sesstype),
|
||||
/* K11 */ be_nested_str_weak(device),
|
||||
/* K12 */ be_nested_str_weak(sessions),
|
||||
/* K13 */ be_nested_str_weak(find_session_source_id_unsecure),
|
||||
/* K14 */ be_nested_str_weak(source_node_id),
|
||||
/* K15 */ be_nested_str_weak(MTR_X3A_X20find_X20session_X20by_X20source_node_id_X20_X3D_X20),
|
||||
/* K16 */ be_nested_str_weak(session_id_X20_X3D_X20),
|
||||
/* K17 */ be_const_int(3),
|
||||
/* K18 */ be_nested_str_weak(session),
|
||||
/* K19 */ be_nested_str_weak(counter_rcv),
|
||||
/* K20 */ be_nested_str_weak(validate),
|
||||
/* K21 */ be_nested_str_weak(message_counter),
|
||||
/* K22 */ be_nested_str_weak(format),
|
||||
/* K23 */ be_nested_str_weak(MTR_X3A_X20rejected_X20duplicate_X20unencrypted_X20message_X20_X3D_X20_X25i_X20ref_X20_X3D_X20_X25i),
|
||||
/* K24 */ be_nested_str_weak(val),
|
||||
/* K25 */ be_nested_str_weak(decode_payload),
|
||||
/* K26 */ be_nested_str_weak(packet_ack),
|
||||
/* K27 */ be_nested_str_weak(ack_message_counter),
|
||||
/* K28 */ be_nested_str_weak(opcode),
|
||||
/* K29 */ be_nested_str_weak(get_opcode_name),
|
||||
/* K30 */ be_nested_str_weak(0x_X2502X),
|
||||
/* K31 */ be_nested_str_weak(MTR_X3A_X20_X3EReceived_X20_X20_X20_X20_X20_X20_X25s_X20from_X20_X5B_X25s_X5D_X3A_X25i),
|
||||
/* K32 */ be_const_int(2),
|
||||
/* K33 */ be_nested_str_weak(commissioning),
|
||||
/* K34 */ be_nested_str_weak(process_incoming),
|
||||
/* K35 */ be_nested_str_weak(MTR_X3A_X20decode_X20header_X3A_X20local_session_id_X3D_X25i_X20message_counter_X3D_X25i),
|
||||
/* K36 */ be_nested_str_weak(get_session_by_local_session_id),
|
||||
/* K37 */ be_nested_str_weak(MTR_X3A_X20unknown_X20local_session_id_X20),
|
||||
/* K38 */ be_nested_str_weak(MTR_X3A_X20frame_X3D),
|
||||
/* K39 */ be_nested_str_weak(inspect),
|
||||
/* K40 */ be_nested_str_weak(MTR_X3A_X20rejected_X20duplicate_X20encrypted_X20message_X20_X3D_X20),
|
||||
/* K41 */ be_nested_str_weak(_X20counter_X3D),
|
||||
/* K42 */ be_nested_str_weak(decrypt),
|
||||
/* K43 */ be_nested_str_weak(raw),
|
||||
/* K44 */ be_nested_str_weak(payload_idx),
|
||||
/* K45 */ be_const_int(1),
|
||||
/* K46 */ be_nested_str_weak(MTR_X3A_X20idx_X3D_X25i_X20clear_X3D_X25s),
|
||||
/* K47 */ be_nested_str_weak(MTR_X3A_X20decrypted_X20message_X3A_X20protocol_id_X3A),
|
||||
/* K48 */ be_nested_str_weak(protocol_id),
|
||||
/* K49 */ be_nested_str_weak(_X20opcode_X3D),
|
||||
/* K50 */ be_nested_str_weak(_X20exchange_id),
|
||||
/* K51 */ be_nested_str_weak(exchange_id),
|
||||
/* K52 */ be_nested_str_weak(MTR_X3A_X20PROTOCOL_ID_SECURE_CHANNEL_X20),
|
||||
/* K53 */ be_nested_str_weak(im),
|
||||
/* K54 */ be_nested_str_weak(MTR_X3A_X20ignoring_X20unhandled_X20protocol_id_X3A),
|
||||
/* K55 */ be_nested_str_weak(MTR_X3A_X20MessageHandler_X3A_X3Amsg_received_X20exception_X3A_X20),
|
||||
/* K56 */ be_nested_str_weak(_X3B),
|
||||
/* K57 */ be_nested_str_weak(debug),
|
||||
/* K58 */ be_nested_str_weak(traceback),
|
||||
}),
|
||||
be_str_weak(msg_received),
|
||||
&be_const_str_solidified,
|
||||
( &(const binstruction[289]) { /* code */
|
||||
0xA4120000, // 0000 IMPORT R4 K0
|
||||
0xA8020108, // 0001 EXBLK 0 #010B
|
||||
0xB8160200, // 0002 GETNGBL R5 K1
|
||||
0x8C140B02, // 0003 GETMET R5 R5 K2
|
||||
0x8C1C0304, // 0004 GETMET R7 R1 K4
|
||||
0x7C1C0200, // 0005 CALL R7 1
|
||||
0x001E0607, // 0006 ADD R7 K3 R7
|
||||
0x54220003, // 0007 LDINT R8 4
|
||||
0x7C140600, // 0008 CALL R5 3
|
||||
0xB8160A00, // 0009 GETNGBL R5 K5
|
||||
0x8C140B06, // 000A GETMET R5 R5 K6
|
||||
0x5C1C0000, // 000B MOVE R7 R0
|
||||
0x5C200200, // 000C MOVE R8 R1
|
||||
0x7C140600, // 000D CALL R5 3
|
||||
0x8C180B07, // 000E GETMET R6 R5 K7
|
||||
0x7C180200, // 000F CALL R6 1
|
||||
0x5C1C0C00, // 0010 MOVE R7 R6
|
||||
0x741E0002, // 0011 JMPT R7 #0015
|
||||
0x501C0000, // 0012 LDBOOL R7 0 0
|
||||
0xA8040001, // 0013 EXBLK 1 1
|
||||
0x80040E00, // 0014 RET 1 R7
|
||||
0x881C0B08, // 0015 GETMBR R7 R5 K8
|
||||
0x1C1C0F09, // 0016 EQ R7 R7 K9
|
||||
0x781E0057, // 0017 JMPF R7 #0070
|
||||
0x881C0B0A, // 0018 GETMBR R7 R5 K10
|
||||
0x1C1C0F09, // 0019 EQ R7 R7 K9
|
||||
0x781E0054, // 001A JMPF R7 #0070
|
||||
0x881C010B, // 001B GETMBR R7 R0 K11
|
||||
0x881C0F0C, // 001C GETMBR R7 R7 K12
|
||||
0x8C1C0F0D, // 001D GETMET R7 R7 K13
|
||||
0x88240B0E, // 001E GETMBR R9 R5 K14
|
||||
0x542A0059, // 001F LDINT R10 90
|
||||
0x7C1C0600, // 0020 CALL R7 3
|
||||
0xB8220200, // 0021 GETNGBL R8 K1
|
||||
0x8C201102, // 0022 GETMET R8 R8 K2
|
||||
0x60280008, // 0023 GETGBL R10 G8
|
||||
0x882C0B0E, // 0024 GETMBR R11 R5 K14
|
||||
0x7C280200, // 0025 CALL R10 1
|
||||
0x002A1E0A, // 0026 ADD R10 K15 R10
|
||||
0x00281510, // 0027 ADD R10 R10 K16
|
||||
0x602C0008, // 0028 GETGBL R11 G8
|
||||
0x88300F08, // 0029 GETMBR R12 R7 K8
|
||||
0x7C2C0200, // 002A CALL R11 1
|
||||
0x0028140B, // 002B ADD R10 R10 R11
|
||||
0x582C0011, // 002C LDCONST R11 K17
|
||||
0x7C200600, // 002D CALL R8 3
|
||||
0x90162407, // 002E SETMBR R5 K18 R7
|
||||
0x88200113, // 002F GETMBR R8 R0 K19
|
||||
0x8C201114, // 0030 GETMET R8 R8 K20
|
||||
0x88280B15, // 0031 GETMBR R10 R5 K21
|
||||
0x502C0000, // 0032 LDBOOL R11 0 0
|
||||
0x7C200600, // 0033 CALL R8 3
|
||||
0x7422000D, // 0034 JMPT R8 #0043
|
||||
0xB8220200, // 0035 GETNGBL R8 K1
|
||||
0x8C201102, // 0036 GETMET R8 R8 K2
|
||||
0x8C280916, // 0037 GETMET R10 R4 K22
|
||||
0x58300017, // 0038 LDCONST R12 K23
|
||||
0x88340B15, // 0039 GETMBR R13 R5 K21
|
||||
0x88380113, // 003A GETMBR R14 R0 K19
|
||||
0x8C381D18, // 003B GETMET R14 R14 K24
|
||||
0x7C380200, // 003C CALL R14 1
|
||||
0x7C280800, // 003D CALL R10 4
|
||||
0x582C0011, // 003E LDCONST R11 K17
|
||||
0x7C200600, // 003F CALL R8 3
|
||||
0x50200000, // 0040 LDBOOL R8 0 0
|
||||
0xA8040001, // 0041 EXBLK 1 1
|
||||
0x80041000, // 0042 RET 1 R8
|
||||
0x8C200B19, // 0043 GETMET R8 R5 K25
|
||||
0x7C200200, // 0044 CALL R8 1
|
||||
0x74220002, // 0045 JMPT R8 #0049
|
||||
0x50200000, // 0046 LDBOOL R8 0 0
|
||||
0xA8040001, // 0047 EXBLK 1 1
|
||||
0x80041000, // 0048 RET 1 R8
|
||||
0x8820010B, // 0049 GETMBR R8 R0 K11
|
||||
0x8C20111A, // 004A GETMET R8 R8 K26
|
||||
0x88280B1B, // 004B GETMBR R10 R5 K27
|
||||
0x7C200400, // 004C CALL R8 2
|
||||
0x88200B1C, // 004D GETMBR R8 R5 K28
|
||||
0x5426000F, // 004E LDINT R9 16
|
||||
0x20201009, // 004F NE R8 R8 R9
|
||||
0x78220014, // 0050 JMPF R8 #0066
|
||||
0xB8220A00, // 0051 GETNGBL R8 K5
|
||||
0x8C20111D, // 0052 GETMET R8 R8 K29
|
||||
0x88280B1C, // 0053 GETMBR R10 R5 K28
|
||||
0x7C200400, // 0054 CALL R8 2
|
||||
0x5C241000, // 0055 MOVE R9 R8
|
||||
0x74260004, // 0056 JMPT R9 #005C
|
||||
0x8C240916, // 0057 GETMET R9 R4 K22
|
||||
0x582C001E, // 0058 LDCONST R11 K30
|
||||
0x88300B1C, // 0059 GETMBR R12 R5 K28
|
||||
0x7C240600, // 005A CALL R9 3
|
||||
0x5C201200, // 005B MOVE R8 R9
|
||||
0xB8260200, // 005C GETNGBL R9 K1
|
||||
0x8C241302, // 005D GETMET R9 R9 K2
|
||||
0x8C2C0916, // 005E GETMET R11 R4 K22
|
||||
0x5834001F, // 005F LDCONST R13 K31
|
||||
0x5C381000, // 0060 MOVE R14 R8
|
||||
0x5C3C0400, // 0061 MOVE R15 R2
|
||||
0x5C400600, // 0062 MOVE R16 R3
|
||||
0x7C2C0A00, // 0063 CALL R11 5
|
||||
0x58300020, // 0064 LDCONST R12 K32
|
||||
0x7C240600, // 0065 CALL R9 3
|
||||
0x88200121, // 0066 GETMBR R8 R0 K33
|
||||
0x8C201122, // 0067 GETMET R8 R8 K34
|
||||
0x5C280A00, // 0068 MOVE R10 R5
|
||||
0x5C2C0400, // 0069 MOVE R11 R2
|
||||
0x5C300600, // 006A MOVE R12 R3
|
||||
0x7C200800, // 006B CALL R8 4
|
||||
0x50200200, // 006C LDBOOL R8 1 0
|
||||
0xA8040001, // 006D EXBLK 1 1
|
||||
0x80041000, // 006E RET 1 R8
|
||||
0x70020095, // 006F JMP #0106
|
||||
0xB81E0200, // 0070 GETNGBL R7 K1
|
||||
0x8C1C0F02, // 0071 GETMET R7 R7 K2
|
||||
0x8C240916, // 0072 GETMET R9 R4 K22
|
||||
0x582C0023, // 0073 LDCONST R11 K35
|
||||
0x88300B08, // 0074 GETMBR R12 R5 K8
|
||||
0x88340B15, // 0075 GETMBR R13 R5 K21
|
||||
0x7C240800, // 0076 CALL R9 4
|
||||
0x58280011, // 0077 LDCONST R10 K17
|
||||
0x7C1C0600, // 0078 CALL R7 3
|
||||
0x881C010B, // 0079 GETMBR R7 R0 K11
|
||||
0x881C0F0C, // 007A GETMBR R7 R7 K12
|
||||
0x8C1C0F24, // 007B GETMET R7 R7 K36
|
||||
0x88240B08, // 007C GETMBR R9 R5 K8
|
||||
0x7C1C0400, // 007D CALL R7 2
|
||||
0x4C200000, // 007E LDNIL R8
|
||||
0x1C200E08, // 007F EQ R8 R7 R8
|
||||
0x78220013, // 0080 JMPF R8 #0095
|
||||
0xB8220200, // 0081 GETNGBL R8 K1
|
||||
0x8C201102, // 0082 GETMET R8 R8 K2
|
||||
0x60280008, // 0083 GETGBL R10 G8
|
||||
0x882C0B08, // 0084 GETMBR R11 R5 K8
|
||||
0x7C280200, // 0085 CALL R10 1
|
||||
0x002A4A0A, // 0086 ADD R10 K37 R10
|
||||
0x582C0011, // 0087 LDCONST R11 K17
|
||||
0x7C200600, // 0088 CALL R8 3
|
||||
0xB8220200, // 0089 GETNGBL R8 K1
|
||||
0x8C201102, // 008A GETMET R8 R8 K2
|
||||
0xB82A0A00, // 008B GETNGBL R10 K5
|
||||
0x8C281527, // 008C GETMET R10 R10 K39
|
||||
0x5C300A00, // 008D MOVE R12 R5
|
||||
0x7C280400, // 008E CALL R10 2
|
||||
0x002A4C0A, // 008F ADD R10 K38 R10
|
||||
0x582C0011, // 0090 LDCONST R11 K17
|
||||
0x7C200600, // 0091 CALL R8 3
|
||||
0x50200000, // 0092 LDBOOL R8 0 0
|
||||
0xA8040001, // 0093 EXBLK 1 1
|
||||
0x80041000, // 0094 RET 1 R8
|
||||
0x90162407, // 0095 SETMBR R5 K18 R7
|
||||
0x88200F13, // 0096 GETMBR R8 R7 K19
|
||||
0x8C201114, // 0097 GETMET R8 R8 K20
|
||||
0x88280B15, // 0098 GETMBR R10 R5 K21
|
||||
0x502C0200, // 0099 LDBOOL R11 1 0
|
||||
0x7C200600, // 009A CALL R8 3
|
||||
0x74220011, // 009B JMPT R8 #00AE
|
||||
0xB8220200, // 009C GETNGBL R8 K1
|
||||
0x8C201102, // 009D GETMET R8 R8 K2
|
||||
0x60280008, // 009E GETGBL R10 G8
|
||||
0x882C0B15, // 009F GETMBR R11 R5 K21
|
||||
0x7C280200, // 00A0 CALL R10 1
|
||||
0x002A500A, // 00A1 ADD R10 K40 R10
|
||||
0x00281529, // 00A2 ADD R10 R10 K41
|
||||
0x602C0008, // 00A3 GETGBL R11 G8
|
||||
0x88300F13, // 00A4 GETMBR R12 R7 K19
|
||||
0x8C301918, // 00A5 GETMET R12 R12 K24
|
||||
0x7C300200, // 00A6 CALL R12 1
|
||||
0x7C2C0200, // 00A7 CALL R11 1
|
||||
0x0028140B, // 00A8 ADD R10 R10 R11
|
||||
0x582C0011, // 00A9 LDCONST R11 K17
|
||||
0x7C200600, // 00AA CALL R8 3
|
||||
0x50200000, // 00AB LDBOOL R8 0 0
|
||||
0xA8040001, // 00AC EXBLK 1 1
|
||||
0x80041000, // 00AD RET 1 R8
|
||||
0x8C200B2A, // 00AE GETMET R8 R5 K42
|
||||
0x7C200200, // 00AF CALL R8 1
|
||||
0x5C241000, // 00B0 MOVE R9 R8
|
||||
0x74260002, // 00B1 JMPT R9 #00B5
|
||||
0x50240000, // 00B2 LDBOOL R9 0 0
|
||||
0xA8040001, // 00B3 EXBLK 1 1
|
||||
0x80041200, // 00B4 RET 1 R9
|
||||
0x88240B2C, // 00B5 GETMBR R9 R5 K44
|
||||
0x0424132D, // 00B6 SUB R9 R9 K45
|
||||
0x40261209, // 00B7 CONNECT R9 K9 R9
|
||||
0x88280B2B, // 00B8 GETMBR R10 R5 K43
|
||||
0x94241409, // 00B9 GETIDX R9 R10 R9
|
||||
0x90165609, // 00BA SETMBR R5 K43 R9
|
||||
0x88240B2B, // 00BB GETMBR R9 R5 K43
|
||||
0x40241208, // 00BC CONNECT R9 R9 R8
|
||||
0xB8260200, // 00BD GETNGBL R9 K1
|
||||
0x8C241302, // 00BE GETMET R9 R9 K2
|
||||
0x8C2C0916, // 00BF GETMET R11 R4 K22
|
||||
0x5834002E, // 00C0 LDCONST R13 K46
|
||||
0x88380B2C, // 00C1 GETMBR R14 R5 K44
|
||||
0x883C0B2B, // 00C2 GETMBR R15 R5 K43
|
||||
0x8C3C1F04, // 00C3 GETMET R15 R15 K4
|
||||
0x7C3C0200, // 00C4 CALL R15 1
|
||||
0x7C2C0800, // 00C5 CALL R11 4
|
||||
0x58300011, // 00C6 LDCONST R12 K17
|
||||
0x7C240600, // 00C7 CALL R9 3
|
||||
0x8C240B19, // 00C8 GETMET R9 R5 K25
|
||||
0x7C240200, // 00C9 CALL R9 1
|
||||
0xB8260200, // 00CA GETNGBL R9 K1
|
||||
0x8C241302, // 00CB GETMET R9 R9 K2
|
||||
0x602C0008, // 00CC GETGBL R11 G8
|
||||
0x88300B30, // 00CD GETMBR R12 R5 K48
|
||||
0x7C2C0200, // 00CE CALL R11 1
|
||||
0x002E5E0B, // 00CF ADD R11 K47 R11
|
||||
0x002C1731, // 00D0 ADD R11 R11 K49
|
||||
0x60300008, // 00D1 GETGBL R12 G8
|
||||
0x88340B1C, // 00D2 GETMBR R13 R5 K28
|
||||
0x7C300200, // 00D3 CALL R12 1
|
||||
0x002C160C, // 00D4 ADD R11 R11 R12
|
||||
0x002C1732, // 00D5 ADD R11 R11 K50
|
||||
0x60300008, // 00D6 GETGBL R12 G8
|
||||
0x88340B33, // 00D7 GETMBR R13 R5 K51
|
||||
0x7C300200, // 00D8 CALL R12 1
|
||||
0x002C160C, // 00D9 ADD R11 R11 R12
|
||||
0x58300011, // 00DA LDCONST R12 K17
|
||||
0x7C240600, // 00DB CALL R9 3
|
||||
0x8824010B, // 00DC GETMBR R9 R0 K11
|
||||
0x8C24131A, // 00DD GETMET R9 R9 K26
|
||||
0x882C0B1B, // 00DE GETMBR R11 R5 K27
|
||||
0x7C240400, // 00DF CALL R9 2
|
||||
0x88240B30, // 00E0 GETMBR R9 R5 K48
|
||||
0x1C281309, // 00E1 EQ R10 R9 K9
|
||||
0x782A000C, // 00E2 JMPF R10 #00F0
|
||||
0xB82A0200, // 00E3 GETNGBL R10 K1
|
||||
0x8C281502, // 00E4 GETMET R10 R10 K2
|
||||
0xB8320A00, // 00E5 GETNGBL R12 K5
|
||||
0x8C301927, // 00E6 GETMET R12 R12 K39
|
||||
0x5C380A00, // 00E7 MOVE R14 R5
|
||||
0x7C300400, // 00E8 CALL R12 2
|
||||
0x0032680C, // 00E9 ADD R12 K52 R12
|
||||
0x58340011, // 00EA LDCONST R13 K17
|
||||
0x7C280600, // 00EB CALL R10 3
|
||||
0x50280200, // 00EC LDBOOL R10 1 0
|
||||
0xA8040001, // 00ED EXBLK 1 1
|
||||
0x80041400, // 00EE RET 1 R10
|
||||
0x70020015, // 00EF JMP #0106
|
||||
0x1C28132D, // 00F0 EQ R10 R9 K45
|
||||
0x782A0008, // 00F1 JMPF R10 #00FB
|
||||
0x88280135, // 00F2 GETMBR R10 R0 K53
|
||||
0x8C281522, // 00F3 GETMET R10 R10 K34
|
||||
0x5C300A00, // 00F4 MOVE R12 R5
|
||||
0x5C340400, // 00F5 MOVE R13 R2
|
||||
0x5C380600, // 00F6 MOVE R14 R3
|
||||
0x7C280800, // 00F7 CALL R10 4
|
||||
0xA8040001, // 00F8 EXBLK 1 1
|
||||
0x80041400, // 00F9 RET 1 R10
|
||||
0x7002000A, // 00FA JMP #0106
|
||||
0xB82A0200, // 00FB GETNGBL R10 K1
|
||||
0x8C281502, // 00FC GETMET R10 R10 K2
|
||||
0x60300008, // 00FD GETGBL R12 G8
|
||||
0x5C341200, // 00FE MOVE R13 R9
|
||||
0x7C300200, // 00FF CALL R12 1
|
||||
0x00326C0C, // 0100 ADD R12 K54 R12
|
||||
0x58340011, // 0101 LDCONST R13 K17
|
||||
0x7C280600, // 0102 CALL R10 3
|
||||
0x50280000, // 0103 LDBOOL R10 0 0
|
||||
0xA8040001, // 0104 EXBLK 1 1
|
||||
0x80041400, // 0105 RET 1 R10
|
||||
0x501C0200, // 0106 LDBOOL R7 1 0
|
||||
0xA8040001, // 0107 EXBLK 1 1
|
||||
0x80040E00, // 0108 RET 1 R7
|
||||
0xA8040001, // 0109 EXBLK 1 1
|
||||
0x70020014, // 010A JMP #0120
|
||||
0xAC140002, // 010B CATCH R5 0 2
|
||||
0x70020011, // 010C JMP #011F
|
||||
0xB81E0200, // 010D GETNGBL R7 K1
|
||||
0x8C1C0F02, // 010E GETMET R7 R7 K2
|
||||
0x60240008, // 010F GETGBL R9 G8
|
||||
0x5C280A00, // 0110 MOVE R10 R5
|
||||
0x7C240200, // 0111 CALL R9 1
|
||||
0x00266E09, // 0112 ADD R9 K55 R9
|
||||
0x00241338, // 0113 ADD R9 R9 K56
|
||||
0x60280008, // 0114 GETGBL R10 G8
|
||||
0x5C2C0C00, // 0115 MOVE R11 R6
|
||||
0x7C280200, // 0116 CALL R10 1
|
||||
0x0024120A, // 0117 ADD R9 R9 R10
|
||||
0x7C1C0400, // 0118 CALL R7 2
|
||||
0xA41E7200, // 0119 IMPORT R7 K57
|
||||
0x8C200F3A, // 011A GETMET R8 R7 K58
|
||||
0x7C200200, // 011B CALL R8 1
|
||||
0x50200000, // 011C LDBOOL R8 0 0
|
||||
0x80041000, // 011D RET 1 R8
|
||||
0x70020000, // 011E JMP #0120
|
||||
0xB0080000, // 011F RAISE 2 R0 R0
|
||||
0x80000000, // 0120 RET 0
|
||||
})
|
||||
)
|
||||
);
|
||||
/*******************************************************************/
|
||||
|
||||
|
||||
/********************************************************************
|
||||
** Solidified function: add_session
|
||||
********************************************************************/
|
||||
be_local_closure(Matter_MessageHandler_add_session, /* name */
|
||||
be_nested_proto(
|
||||
15, /* nstack */
|
||||
7, /* argc */
|
||||
2, /* varg */
|
||||
0, /* has upvals */
|
||||
NULL, /* no upvals */
|
||||
0, /* has sup protos */
|
||||
NULL, /* no sub protos */
|
||||
1, /* has constants */
|
||||
( &(const bvalue[10]) { /* constants */
|
||||
/* K0 */ be_nested_str_weak(string),
|
||||
/* K1 */ be_nested_str_weak(tasmota),
|
||||
/* K2 */ be_nested_str_weak(log),
|
||||
/* K3 */ be_nested_str_weak(format),
|
||||
/* K4 */ be_nested_str_weak(MTR_X3A_X20add_session_X20local_session_id_X3D_X25i_X20initiator_session_id_X3D_X25i),
|
||||
/* K5 */ be_const_int(3),
|
||||
/* K6 */ be_nested_str_weak(device),
|
||||
/* K7 */ be_nested_str_weak(sessions),
|
||||
/* K8 */ be_nested_str_weak(create_session),
|
||||
/* K9 */ be_nested_str_weak(set_keys),
|
||||
}),
|
||||
be_str_weak(add_session),
|
||||
&be_const_str_solidified,
|
||||
( &(const binstruction[23]) { /* code */
|
||||
0xA41E0000, // 0000 IMPORT R7 K0
|
||||
0xB8220200, // 0001 GETNGBL R8 K1
|
||||
0x8C201102, // 0002 GETMET R8 R8 K2
|
||||
0x8C280F03, // 0003 GETMET R10 R7 K3
|
||||
0x58300004, // 0004 LDCONST R12 K4
|
||||
0x5C340200, // 0005 MOVE R13 R1
|
||||
0x5C380400, // 0006 MOVE R14 R2
|
||||
0x7C280800, // 0007 CALL R10 4
|
||||
0x582C0005, // 0008 LDCONST R11 K5
|
||||
0x7C200600, // 0009 CALL R8 3
|
||||
0x88200106, // 000A GETMBR R8 R0 K6
|
||||
0x88201107, // 000B GETMBR R8 R8 K7
|
||||
0x8C201108, // 000C GETMET R8 R8 K8
|
||||
0x5C280200, // 000D MOVE R10 R1
|
||||
0x5C2C0400, // 000E MOVE R11 R2
|
||||
0x7C200600, // 000F CALL R8 3
|
||||
0x8C241109, // 0010 GETMET R9 R8 K9
|
||||
0x5C2C0600, // 0011 MOVE R11 R3
|
||||
0x5C300800, // 0012 MOVE R12 R4
|
||||
0x5C340A00, // 0013 MOVE R13 R5
|
||||
0x5C380C00, // 0014 MOVE R14 R6
|
||||
0x7C240A00, // 0015 CALL R9 5
|
||||
0x80000000, // 0016 RET 0
|
||||
})
|
||||
)
|
||||
);
|
||||
/*******************************************************************/
|
||||
|
||||
|
||||
/********************************************************************
|
||||
** Solidified function: init
|
||||
********************************************************************/
|
||||
be_local_closure(Matter_MessageHandler_init, /* name */
|
||||
be_nested_proto(
|
||||
5, /* nstack */
|
||||
2, /* argc */
|
||||
2, /* varg */
|
||||
0, /* has upvals */
|
||||
NULL, /* no upvals */
|
||||
0, /* has sup protos */
|
||||
NULL, /* no sub protos */
|
||||
1, /* has constants */
|
||||
( &(const bvalue[ 8]) { /* constants */
|
||||
/* K0 */ be_nested_str_weak(device),
|
||||
/* K1 */ be_nested_str_weak(commissioning),
|
||||
/* K2 */ be_nested_str_weak(matter),
|
||||
/* K3 */ be_nested_str_weak(Commisioning_Context),
|
||||
/* K4 */ be_nested_str_weak(im),
|
||||
/* K5 */ be_nested_str_weak(IM),
|
||||
/* K6 */ be_nested_str_weak(counter_rcv),
|
||||
/* K7 */ be_nested_str_weak(Counter),
|
||||
}),
|
||||
be_str_weak(init),
|
||||
&be_const_str_solidified,
|
||||
( &(const binstruction[16]) { /* code */
|
||||
0x90020001, // 0000 SETMBR R0 K0 R1
|
||||
0xB80A0400, // 0001 GETNGBL R2 K2
|
||||
0x8C080503, // 0002 GETMET R2 R2 K3
|
||||
0x5C100000, // 0003 MOVE R4 R0
|
||||
0x7C080400, // 0004 CALL R2 2
|
||||
0x90020202, // 0005 SETMBR R0 K1 R2
|
||||
0xB80A0400, // 0006 GETNGBL R2 K2
|
||||
0x8C080505, // 0007 GETMET R2 R2 K5
|
||||
0x5C100000, // 0008 MOVE R4 R0
|
||||
0x7C080400, // 0009 CALL R2 2
|
||||
0x90020802, // 000A SETMBR R0 K4 R2
|
||||
0xB80A0400, // 000B GETNGBL R2 K2
|
||||
0x8C080507, // 000C GETMET R2 R2 K7
|
||||
0x7C080200, // 000D CALL R2 1
|
||||
0x90020C02, // 000E SETMBR R0 K6 R2
|
||||
0x80000000, // 000F RET 0
|
||||
})
|
||||
)
|
||||
);
|
||||
/*******************************************************************/
|
||||
|
||||
|
||||
/********************************************************************
|
||||
** Solidified function: every_second
|
||||
********************************************************************/
|
||||
be_local_closure(Matter_MessageHandler_every_second, /* name */
|
||||
be_nested_proto(
|
||||
3, /* nstack */
|
||||
1, /* argc */
|
||||
2, /* varg */
|
||||
0, /* has upvals */
|
||||
NULL, /* no upvals */
|
||||
0, /* has sup protos */
|
||||
NULL, /* no sub protos */
|
||||
1, /* has constants */
|
||||
( &(const bvalue[ 3]) { /* constants */
|
||||
/* K0 */ be_nested_str_weak(commissioning),
|
||||
/* K1 */ be_nested_str_weak(every_second),
|
||||
/* K2 */ be_nested_str_weak(im),
|
||||
}),
|
||||
be_str_weak(every_second),
|
||||
&be_const_str_solidified,
|
||||
( &(const binstruction[ 7]) { /* code */
|
||||
0x88040100, // 0000 GETMBR R1 R0 K0
|
||||
0x8C040301, // 0001 GETMET R1 R1 K1
|
||||
0x7C040200, // 0002 CALL R1 1
|
||||
0x88040102, // 0003 GETMBR R1 R0 K2
|
||||
0x8C040301, // 0004 GETMET R1 R1 K1
|
||||
0x7C040200, // 0005 CALL R1 1
|
||||
0x80000000, // 0006 RET 0
|
||||
})
|
||||
)
|
||||
);
|
||||
/*******************************************************************/
|
||||
|
||||
|
||||
/********************************************************************
|
||||
** Solidified class: Matter_MessageHandler
|
||||
********************************************************************/
|
||||
be_local_class(Matter_MessageHandler,
|
||||
4,
|
||||
NULL,
|
||||
be_nested_map(9,
|
||||
( (struct bmapnode*) &(const bmapnode[]) {
|
||||
{ be_const_key_weak(every_second, -1), be_const_closure(Matter_MessageHandler_every_second_closure) },
|
||||
{ be_const_key_weak(msg_received, -1), be_const_closure(Matter_MessageHandler_msg_received_closure) },
|
||||
{ be_const_key_weak(counter_rcv, -1), be_const_var(3) },
|
||||
{ be_const_key_weak(commissioning, 0), be_const_var(1) },
|
||||
{ be_const_key_weak(device, 5), be_const_var(0) },
|
||||
{ be_const_key_weak(init, 8), be_const_closure(Matter_MessageHandler_init_closure) },
|
||||
{ be_const_key_weak(send_response, 4), be_const_closure(Matter_MessageHandler_send_response_closure) },
|
||||
{ be_const_key_weak(add_session, 2), be_const_closure(Matter_MessageHandler_add_session_closure) },
|
||||
{ be_const_key_weak(im, -1), be_const_var(2) },
|
||||
})),
|
||||
be_str_weak(Matter_MessageHandler)
|
||||
);
|
||||
/*******************************************************************/
|
||||
|
||||
void be_load_Matter_MessageHandler_class(bvm *vm) {
|
||||
be_pushntvclass(vm, &be_class_Matter_MessageHandler);
|
||||
be_setglobal(vm, "Matter_MessageHandler");
|
||||
be_pop(vm, 1);
|
||||
}
|
||||
/********************************************************************/
|
||||
/* End of solidification */
|
@ -0,0 +1,90 @@
|
||||
/* Solidification of Matter_Module.h */
|
||||
/********************************************************************\
|
||||
* Generated code, don't edit *
|
||||
\********************************************************************/
|
||||
#include "be_constobj.h"
|
||||
|
||||
/********************************************************************
|
||||
** Solidified function: setmember
|
||||
********************************************************************/
|
||||
be_local_closure(matter_setmember, /* name */
|
||||
be_nested_proto(
|
||||
6, /* nstack */
|
||||
2, /* argc */
|
||||
0, /* varg */
|
||||
0, /* has upvals */
|
||||
NULL, /* no upvals */
|
||||
0, /* has sup protos */
|
||||
NULL, /* no sub protos */
|
||||
1, /* has constants */
|
||||
( &(const bvalue[ 3]) { /* constants */
|
||||
/* K0 */ be_nested_str_weak(global),
|
||||
/* K1 */ be_nested_str_weak(contains),
|
||||
/* K2 */ be_nested_str_weak(_X2Ematter),
|
||||
}),
|
||||
be_str_weak(setmember),
|
||||
&be_const_str_solidified,
|
||||
( &(const binstruction[11]) { /* code */
|
||||
0xA40A0000, // 0000 IMPORT R2 K0
|
||||
0x8C0C0501, // 0001 GETMET R3 R2 K1
|
||||
0x58140002, // 0002 LDCONST R5 K2
|
||||
0x7C0C0400, // 0003 CALL R3 2
|
||||
0x740E0002, // 0004 JMPT R3 #0008
|
||||
0x600C0013, // 0005 GETGBL R3 G19
|
||||
0x7C0C0000, // 0006 CALL R3 0
|
||||
0x900A0403, // 0007 SETMBR R2 K2 R3
|
||||
0x880C0502, // 0008 GETMBR R3 R2 K2
|
||||
0x980C0001, // 0009 SETIDX R3 R0 R1
|
||||
0x80000000, // 000A RET 0
|
||||
})
|
||||
)
|
||||
);
|
||||
/*******************************************************************/
|
||||
|
||||
|
||||
/********************************************************************
|
||||
** Solidified function: member
|
||||
********************************************************************/
|
||||
be_local_closure(matter_member, /* name */
|
||||
be_nested_proto(
|
||||
6, /* nstack */
|
||||
1, /* argc */
|
||||
0, /* varg */
|
||||
0, /* has upvals */
|
||||
NULL, /* no upvals */
|
||||
0, /* has sup protos */
|
||||
NULL, /* no sub protos */
|
||||
1, /* has constants */
|
||||
( &(const bvalue[ 4]) { /* constants */
|
||||
/* K0 */ be_nested_str_weak(global),
|
||||
/* K1 */ be_nested_str_weak(undefined),
|
||||
/* K2 */ be_nested_str_weak(contains),
|
||||
/* K3 */ be_nested_str_weak(_X2Ematter),
|
||||
}),
|
||||
be_str_weak(member),
|
||||
&be_const_str_solidified,
|
||||
( &(const binstruction[17]) { /* code */
|
||||
0xA4060000, // 0000 IMPORT R1 K0
|
||||
0xA40A0200, // 0001 IMPORT R2 K1
|
||||
0x8C0C0302, // 0002 GETMET R3 R1 K2
|
||||
0x58140003, // 0003 LDCONST R5 K3
|
||||
0x7C0C0400, // 0004 CALL R3 2
|
||||
0x780E0008, // 0005 JMPF R3 #000F
|
||||
0x880C0303, // 0006 GETMBR R3 R1 K3
|
||||
0x8C0C0702, // 0007 GETMET R3 R3 K2
|
||||
0x5C140000, // 0008 MOVE R5 R0
|
||||
0x7C0C0400, // 0009 CALL R3 2
|
||||
0x780E0003, // 000A JMPF R3 #000F
|
||||
0x880C0303, // 000B GETMBR R3 R1 K3
|
||||
0x940C0600, // 000C GETIDX R3 R3 R0
|
||||
0x80040600, // 000D RET 1 R3
|
||||
0x70020000, // 000E JMP #0010
|
||||
0x80040400, // 000F RET 1 R2
|
||||
0x80000000, // 0010 RET 0
|
||||
})
|
||||
)
|
||||
);
|
||||
/*******************************************************************/
|
||||
|
||||
/********************************************************************/
|
||||
/* End of solidification */
|
@ -0,0 +1,272 @@
|
||||
/* Solidification of Matter_Plugin.h */
|
||||
/********************************************************************\
|
||||
* Generated code, don't edit *
|
||||
\********************************************************************/
|
||||
#include "be_constobj.h"
|
||||
|
||||
extern const bclass be_class_Matter_Plugin;
|
||||
|
||||
/********************************************************************
|
||||
** Solidified function: get_endpoints
|
||||
********************************************************************/
|
||||
be_local_closure(Matter_Plugin_get_endpoints, /* name */
|
||||
be_nested_proto(
|
||||
2, /* nstack */
|
||||
1, /* argc */
|
||||
2, /* varg */
|
||||
0, /* has upvals */
|
||||
NULL, /* no upvals */
|
||||
0, /* has sup protos */
|
||||
NULL, /* no sub protos */
|
||||
1, /* has constants */
|
||||
( &(const bvalue[ 1]) { /* constants */
|
||||
/* K0 */ be_nested_str_weak(endpoints),
|
||||
}),
|
||||
be_str_weak(get_endpoints),
|
||||
&be_const_str_solidified,
|
||||
( &(const binstruction[ 2]) { /* code */
|
||||
0x88040100, // 0000 GETMBR R1 R0 K0
|
||||
0x80040200, // 0001 RET 1 R1
|
||||
})
|
||||
)
|
||||
);
|
||||
/*******************************************************************/
|
||||
|
||||
|
||||
/********************************************************************
|
||||
** Solidified function: invoke_request
|
||||
********************************************************************/
|
||||
be_local_closure(Matter_Plugin_invoke_request, /* name */
|
||||
be_nested_proto(
|
||||
5, /* nstack */
|
||||
4, /* argc */
|
||||
2, /* varg */
|
||||
0, /* has upvals */
|
||||
NULL, /* no upvals */
|
||||
0, /* has sup protos */
|
||||
NULL, /* no sub protos */
|
||||
0, /* has constants */
|
||||
NULL, /* no const */
|
||||
be_str_weak(invoke_request),
|
||||
&be_const_str_solidified,
|
||||
( &(const binstruction[ 2]) { /* code */
|
||||
0x4C100000, // 0000 LDNIL R4
|
||||
0x80040800, // 0001 RET 1 R4
|
||||
})
|
||||
)
|
||||
);
|
||||
/*******************************************************************/
|
||||
|
||||
|
||||
/********************************************************************
|
||||
** Solidified function: init
|
||||
********************************************************************/
|
||||
be_local_closure(Matter_Plugin_init, /* name */
|
||||
be_nested_proto(
|
||||
3, /* nstack */
|
||||
2, /* argc */
|
||||
2, /* varg */
|
||||
0, /* has upvals */
|
||||
NULL, /* no upvals */
|
||||
0, /* has sup protos */
|
||||
NULL, /* no sub protos */
|
||||
1, /* has constants */
|
||||
( &(const bvalue[ 2]) { /* constants */
|
||||
/* K0 */ be_nested_str_weak(device),
|
||||
/* K1 */ be_nested_str_weak(endpoints),
|
||||
}),
|
||||
be_str_weak(init),
|
||||
&be_const_str_solidified,
|
||||
( &(const binstruction[ 5]) { /* code */
|
||||
0x90020001, // 0000 SETMBR R0 K0 R1
|
||||
0x60080012, // 0001 GETGBL R2 G18
|
||||
0x7C080000, // 0002 CALL R2 0
|
||||
0x90020202, // 0003 SETMBR R0 K1 R2
|
||||
0x80000000, // 0004 RET 0
|
||||
})
|
||||
)
|
||||
);
|
||||
/*******************************************************************/
|
||||
|
||||
|
||||
/********************************************************************
|
||||
** Solidified function: read_attribute
|
||||
********************************************************************/
|
||||
be_local_closure(Matter_Plugin_read_attribute, /* name */
|
||||
be_nested_proto(
|
||||
6, /* nstack */
|
||||
5, /* argc */
|
||||
2, /* varg */
|
||||
0, /* has upvals */
|
||||
NULL, /* no upvals */
|
||||
0, /* has sup protos */
|
||||
NULL, /* no sub protos */
|
||||
0, /* has constants */
|
||||
NULL, /* no const */
|
||||
be_str_weak(read_attribute),
|
||||
&be_const_str_solidified,
|
||||
( &(const binstruction[ 2]) { /* code */
|
||||
0x4C140000, // 0000 LDNIL R5
|
||||
0x80040A00, // 0001 RET 1 R5
|
||||
})
|
||||
)
|
||||
);
|
||||
/*******************************************************************/
|
||||
|
||||
|
||||
/********************************************************************
|
||||
** Solidified function: read_event
|
||||
********************************************************************/
|
||||
be_local_closure(Matter_Plugin_read_event, /* name */
|
||||
be_nested_proto(
|
||||
6, /* nstack */
|
||||
5, /* argc */
|
||||
2, /* varg */
|
||||
0, /* has upvals */
|
||||
NULL, /* no upvals */
|
||||
0, /* has sup protos */
|
||||
NULL, /* no sub protos */
|
||||
0, /* has constants */
|
||||
NULL, /* no const */
|
||||
be_str_weak(read_event),
|
||||
&be_const_str_solidified,
|
||||
( &(const binstruction[ 2]) { /* code */
|
||||
0x4C140000, // 0000 LDNIL R5
|
||||
0x80040A00, // 0001 RET 1 R5
|
||||
})
|
||||
)
|
||||
);
|
||||
/*******************************************************************/
|
||||
|
||||
|
||||
/********************************************************************
|
||||
** Solidified function: subscribe_attribute
|
||||
********************************************************************/
|
||||
be_local_closure(Matter_Plugin_subscribe_attribute, /* name */
|
||||
be_nested_proto(
|
||||
6, /* nstack */
|
||||
5, /* argc */
|
||||
2, /* varg */
|
||||
0, /* has upvals */
|
||||
NULL, /* no upvals */
|
||||
0, /* has sup protos */
|
||||
NULL, /* no sub protos */
|
||||
0, /* has constants */
|
||||
NULL, /* no const */
|
||||
be_str_weak(subscribe_attribute),
|
||||
&be_const_str_solidified,
|
||||
( &(const binstruction[ 2]) { /* code */
|
||||
0x4C140000, // 0000 LDNIL R5
|
||||
0x80040A00, // 0001 RET 1 R5
|
||||
})
|
||||
)
|
||||
);
|
||||
/*******************************************************************/
|
||||
|
||||
|
||||
/********************************************************************
|
||||
** Solidified function: subscribe_event
|
||||
********************************************************************/
|
||||
be_local_closure(Matter_Plugin_subscribe_event, /* name */
|
||||
be_nested_proto(
|
||||
6, /* nstack */
|
||||
5, /* argc */
|
||||
2, /* varg */
|
||||
0, /* has upvals */
|
||||
NULL, /* no upvals */
|
||||
0, /* has sup protos */
|
||||
NULL, /* no sub protos */
|
||||
0, /* has constants */
|
||||
NULL, /* no const */
|
||||
be_str_weak(subscribe_event),
|
||||
&be_const_str_solidified,
|
||||
( &(const binstruction[ 2]) { /* code */
|
||||
0x4C140000, // 0000 LDNIL R5
|
||||
0x80040A00, // 0001 RET 1 R5
|
||||
})
|
||||
)
|
||||
);
|
||||
/*******************************************************************/
|
||||
|
||||
|
||||
/********************************************************************
|
||||
** Solidified function: write_attribute
|
||||
********************************************************************/
|
||||
be_local_closure(Matter_Plugin_write_attribute, /* name */
|
||||
be_nested_proto(
|
||||
6, /* nstack */
|
||||
5, /* argc */
|
||||
2, /* varg */
|
||||
0, /* has upvals */
|
||||
NULL, /* no upvals */
|
||||
0, /* has sup protos */
|
||||
NULL, /* no sub protos */
|
||||
0, /* has constants */
|
||||
NULL, /* no const */
|
||||
be_str_weak(write_attribute),
|
||||
&be_const_str_solidified,
|
||||
( &(const binstruction[ 2]) { /* code */
|
||||
0x4C140000, // 0000 LDNIL R5
|
||||
0x80040A00, // 0001 RET 1 R5
|
||||
})
|
||||
)
|
||||
);
|
||||
/*******************************************************************/
|
||||
|
||||
|
||||
/********************************************************************
|
||||
** Solidified function: timed_request
|
||||
********************************************************************/
|
||||
be_local_closure(Matter_Plugin_timed_request, /* name */
|
||||
be_nested_proto(
|
||||
5, /* nstack */
|
||||
4, /* argc */
|
||||
2, /* varg */
|
||||
0, /* has upvals */
|
||||
NULL, /* no upvals */
|
||||
0, /* has sup protos */
|
||||
NULL, /* no sub protos */
|
||||
0, /* has constants */
|
||||
NULL, /* no const */
|
||||
be_str_weak(timed_request),
|
||||
&be_const_str_solidified,
|
||||
( &(const binstruction[ 2]) { /* code */
|
||||
0x4C100000, // 0000 LDNIL R4
|
||||
0x80040800, // 0001 RET 1 R4
|
||||
})
|
||||
)
|
||||
);
|
||||
/*******************************************************************/
|
||||
|
||||
|
||||
/********************************************************************
|
||||
** Solidified class: Matter_Plugin
|
||||
********************************************************************/
|
||||
be_local_class(Matter_Plugin,
|
||||
2,
|
||||
NULL,
|
||||
be_nested_map(11,
|
||||
( (struct bmapnode*) &(const bmapnode[]) {
|
||||
{ be_const_key_weak(get_endpoints, -1), be_const_closure(Matter_Plugin_get_endpoints_closure) },
|
||||
{ be_const_key_weak(endpoints, 7), be_const_var(1) },
|
||||
{ be_const_key_weak(timed_request, 8), be_const_closure(Matter_Plugin_timed_request_closure) },
|
||||
{ be_const_key_weak(read_attribute, -1), be_const_closure(Matter_Plugin_read_attribute_closure) },
|
||||
{ be_const_key_weak(read_event, -1), be_const_closure(Matter_Plugin_read_event_closure) },
|
||||
{ be_const_key_weak(device, -1), be_const_var(0) },
|
||||
{ be_const_key_weak(subscribe_attribute, -1), be_const_closure(Matter_Plugin_subscribe_attribute_closure) },
|
||||
{ be_const_key_weak(write_attribute, -1), be_const_closure(Matter_Plugin_write_attribute_closure) },
|
||||
{ be_const_key_weak(subscribe_event, -1), be_const_closure(Matter_Plugin_subscribe_event_closure) },
|
||||
{ be_const_key_weak(init, 2), be_const_closure(Matter_Plugin_init_closure) },
|
||||
{ be_const_key_weak(invoke_request, 1), be_const_closure(Matter_Plugin_invoke_request_closure) },
|
||||
})),
|
||||
be_str_weak(Matter_Plugin)
|
||||
);
|
||||
/*******************************************************************/
|
||||
|
||||
void be_load_Matter_Plugin_class(bvm *vm) {
|
||||
be_pushntvclass(vm, &be_class_Matter_Plugin);
|
||||
be_setglobal(vm, "Matter_Plugin");
|
||||
be_pop(vm, 1);
|
||||
}
|
||||
/********************************************************************/
|
||||
/* End of solidification */
|
@ -0,0 +1,118 @@
|
||||
/* Solidification of Matter_Plugin_Relay.h */
|
||||
/********************************************************************\
|
||||
* Generated code, don't edit *
|
||||
\********************************************************************/
|
||||
#include "be_constobj.h"
|
||||
|
||||
extern const bclass be_class_Matter_Plugin_Relay;
|
||||
|
||||
/********************************************************************
|
||||
** Solidified function: read_attribute
|
||||
********************************************************************/
|
||||
be_local_closure(Matter_Plugin_Relay_read_attribute, /* name */
|
||||
be_nested_proto(
|
||||
5, /* nstack */
|
||||
5, /* argc */
|
||||
2, /* varg */
|
||||
0, /* has upvals */
|
||||
NULL, /* no upvals */
|
||||
0, /* has sup protos */
|
||||
NULL, /* no sub protos */
|
||||
0, /* has constants */
|
||||
NULL, /* no const */
|
||||
be_str_weak(read_attribute),
|
||||
&be_const_str_solidified,
|
||||
( &(const binstruction[ 1]) { /* code */
|
||||
0x80000000, // 0000 RET 0
|
||||
})
|
||||
)
|
||||
);
|
||||
/*******************************************************************/
|
||||
|
||||
|
||||
/********************************************************************
|
||||
** Solidified function: init
|
||||
********************************************************************/
|
||||
be_local_closure(Matter_Plugin_Relay_init, /* name */
|
||||
be_nested_proto(
|
||||
5, /* nstack */
|
||||
2, /* argc */
|
||||
2, /* varg */
|
||||
0, /* has upvals */
|
||||
NULL, /* no upvals */
|
||||
0, /* has sup protos */
|
||||
NULL, /* no sub protos */
|
||||
1, /* has constants */
|
||||
( &(const bvalue[ 3]) { /* constants */
|
||||
/* K0 */ be_nested_str_weak(init),
|
||||
/* K1 */ be_nested_str_weak(endpoints),
|
||||
/* K2 */ be_const_int(1),
|
||||
}),
|
||||
be_str_weak(init),
|
||||
&be_const_str_solidified,
|
||||
( &(const binstruction[11]) { /* code */
|
||||
0x60080003, // 0000 GETGBL R2 G3
|
||||
0x5C0C0000, // 0001 MOVE R3 R0
|
||||
0x7C080200, // 0002 CALL R2 1
|
||||
0x8C080500, // 0003 GETMET R2 R2 K0
|
||||
0x5C100200, // 0004 MOVE R4 R1
|
||||
0x7C080400, // 0005 CALL R2 2
|
||||
0x60080012, // 0006 GETGBL R2 G18
|
||||
0x7C080000, // 0007 CALL R2 0
|
||||
0x400C0502, // 0008 CONNECT R3 R2 K2
|
||||
0x90020202, // 0009 SETMBR R0 K1 R2
|
||||
0x80000000, // 000A RET 0
|
||||
})
|
||||
)
|
||||
);
|
||||
/*******************************************************************/
|
||||
|
||||
|
||||
/********************************************************************
|
||||
** Solidified function: invoke_request
|
||||
********************************************************************/
|
||||
be_local_closure(Matter_Plugin_Relay_invoke_request, /* name */
|
||||
be_nested_proto(
|
||||
4, /* nstack */
|
||||
4, /* argc */
|
||||
2, /* varg */
|
||||
0, /* has upvals */
|
||||
NULL, /* no upvals */
|
||||
0, /* has sup protos */
|
||||
NULL, /* no sub protos */
|
||||
0, /* has constants */
|
||||
NULL, /* no const */
|
||||
be_str_weak(invoke_request),
|
||||
&be_const_str_solidified,
|
||||
( &(const binstruction[ 1]) { /* code */
|
||||
0x80000000, // 0000 RET 0
|
||||
})
|
||||
)
|
||||
);
|
||||
/*******************************************************************/
|
||||
|
||||
|
||||
/********************************************************************
|
||||
** Solidified class: Matter_Plugin_Relay
|
||||
********************************************************************/
|
||||
extern const bclass be_class_Matter_Plugin;
|
||||
be_local_class(Matter_Plugin_Relay,
|
||||
0,
|
||||
&be_class_Matter_Plugin,
|
||||
be_nested_map(3,
|
||||
( (struct bmapnode*) &(const bmapnode[]) {
|
||||
{ be_const_key_weak(read_attribute, 1), be_const_closure(Matter_Plugin_Relay_read_attribute_closure) },
|
||||
{ be_const_key_weak(init, -1), be_const_closure(Matter_Plugin_Relay_init_closure) },
|
||||
{ be_const_key_weak(invoke_request, -1), be_const_closure(Matter_Plugin_Relay_invoke_request_closure) },
|
||||
})),
|
||||
be_str_weak(Matter_Plugin_Relay)
|
||||
);
|
||||
/*******************************************************************/
|
||||
|
||||
void be_load_Matter_Plugin_Relay_class(bvm *vm) {
|
||||
be_pushntvclass(vm, &be_class_Matter_Plugin_Relay);
|
||||
be_setglobal(vm, "Matter_Plugin_Relay");
|
||||
be_pop(vm, 1);
|
||||
}
|
||||
/********************************************************************/
|
||||
/* End of solidification */
|
File diff suppressed because it is too large
Load Diff
2239
lib/libesp32/berry_matter/src/solidify/solidified_Matter_Session.h
Normal file
2239
lib/libesp32/berry_matter/src/solidify/solidified_Matter_Session.h
Normal file
File diff suppressed because it is too large
Load Diff
2909
lib/libesp32/berry_matter/src/solidify/solidified_Matter_TLV.h
Normal file
2909
lib/libesp32/berry_matter/src/solidify/solidified_Matter_TLV.h
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,626 @@
|
||||
/* Solidification of Matter_UDPServer.h */
|
||||
/********************************************************************\
|
||||
* Generated code, don't edit *
|
||||
\********************************************************************/
|
||||
#include "be_constobj.h"
|
||||
|
||||
extern const bclass be_class_Matter_UDPPacket_sent;
|
||||
|
||||
/********************************************************************
|
||||
** Solidified function: init
|
||||
********************************************************************/
|
||||
be_local_closure(Matter_UDPPacket_sent_init, /* name */
|
||||
be_nested_proto(
|
||||
7, /* nstack */
|
||||
5, /* argc */
|
||||
2, /* varg */
|
||||
0, /* has upvals */
|
||||
NULL, /* no upvals */
|
||||
0, /* has sup protos */
|
||||
NULL, /* no sub protos */
|
||||
1, /* has constants */
|
||||
( &(const bvalue[10]) { /* constants */
|
||||
/* K0 */ be_nested_str_weak(raw),
|
||||
/* K1 */ be_nested_str_weak(addr),
|
||||
/* K2 */ be_nested_str_weak(port),
|
||||
/* K3 */ be_nested_str_weak(msg_id),
|
||||
/* K4 */ be_nested_str_weak(retries),
|
||||
/* K5 */ be_nested_str_weak(RETRIES),
|
||||
/* K6 */ be_nested_str_weak(next_try),
|
||||
/* K7 */ be_nested_str_weak(tasmota),
|
||||
/* K8 */ be_nested_str_weak(millis),
|
||||
/* K9 */ be_nested_str_weak(RETRY_MS),
|
||||
}),
|
||||
be_str_weak(init),
|
||||
&be_const_str_solidified,
|
||||
( &(const binstruction[13]) { /* code */
|
||||
0x90020001, // 0000 SETMBR R0 K0 R1
|
||||
0x90020202, // 0001 SETMBR R0 K1 R2
|
||||
0x90020403, // 0002 SETMBR R0 K2 R3
|
||||
0x90020604, // 0003 SETMBR R0 K3 R4
|
||||
0x88140105, // 0004 GETMBR R5 R0 K5
|
||||
0x90020805, // 0005 SETMBR R0 K4 R5
|
||||
0xB8160E00, // 0006 GETNGBL R5 K7
|
||||
0x8C140B08, // 0007 GETMET R5 R5 K8
|
||||
0x7C140200, // 0008 CALL R5 1
|
||||
0x88180109, // 0009 GETMBR R6 R0 K9
|
||||
0x00140A06, // 000A ADD R5 R5 R6
|
||||
0x90020C05, // 000B SETMBR R0 K6 R5
|
||||
0x80000000, // 000C RET 0
|
||||
})
|
||||
)
|
||||
);
|
||||
/*******************************************************************/
|
||||
|
||||
|
||||
/********************************************************************
|
||||
** Solidified function: send
|
||||
********************************************************************/
|
||||
be_local_closure(Matter_UDPPacket_sent_send, /* name */
|
||||
be_nested_proto(
|
||||
11, /* nstack */
|
||||
2, /* argc */
|
||||
2, /* varg */
|
||||
0, /* has upvals */
|
||||
NULL, /* no upvals */
|
||||
0, /* has sup protos */
|
||||
NULL, /* no sub protos */
|
||||
1, /* has constants */
|
||||
( &(const bvalue[14]) { /* constants */
|
||||
/* K0 */ be_nested_str_weak(string),
|
||||
/* K1 */ be_nested_str_weak(send),
|
||||
/* K2 */ be_nested_str_weak(addr),
|
||||
/* K3 */ be_nested_str_weak(remote_ip),
|
||||
/* K4 */ be_nested_str_weak(port),
|
||||
/* K5 */ be_nested_str_weak(remote_port),
|
||||
/* K6 */ be_nested_str_weak(raw),
|
||||
/* K7 */ be_nested_str_weak(tasmota),
|
||||
/* K8 */ be_nested_str_weak(log),
|
||||
/* K9 */ be_nested_str_weak(format),
|
||||
/* K10 */ be_nested_str_weak(MTR_X3A_X20sending_X20packet_X20to_X20_X27_X5B_X25s_X5D_X3A_X25i_X27),
|
||||
/* K11 */ be_const_int(3),
|
||||
/* K12 */ be_nested_str_weak(MTR_X3A_X20failed_X20to_X20send_X20packet_X20to_X20_X27_X5B_X25s_X5D_X3A_X25i_X27),
|
||||
/* K13 */ be_const_int(2),
|
||||
}),
|
||||
be_str_weak(send),
|
||||
&be_const_str_solidified,
|
||||
( &(const binstruction[35]) { /* code */
|
||||
0xA40A0000, // 0000 IMPORT R2 K0
|
||||
0x8C0C0301, // 0001 GETMET R3 R1 K1
|
||||
0x88140102, // 0002 GETMBR R5 R0 K2
|
||||
0x78160001, // 0003 JMPF R5 #0006
|
||||
0x88140102, // 0004 GETMBR R5 R0 K2
|
||||
0x70020000, // 0005 JMP #0007
|
||||
0x88140303, // 0006 GETMBR R5 R1 K3
|
||||
0x88180104, // 0007 GETMBR R6 R0 K4
|
||||
0x781A0001, // 0008 JMPF R6 #000B
|
||||
0x88180104, // 0009 GETMBR R6 R0 K4
|
||||
0x70020000, // 000A JMP #000C
|
||||
0x88180305, // 000B GETMBR R6 R1 K5
|
||||
0x881C0106, // 000C GETMBR R7 R0 K6
|
||||
0x7C0C0800, // 000D CALL R3 4
|
||||
0x780E0009, // 000E JMPF R3 #0019
|
||||
0xB8120E00, // 000F GETNGBL R4 K7
|
||||
0x8C100908, // 0010 GETMET R4 R4 K8
|
||||
0x8C180509, // 0011 GETMET R6 R2 K9
|
||||
0x5820000A, // 0012 LDCONST R8 K10
|
||||
0x88240102, // 0013 GETMBR R9 R0 K2
|
||||
0x88280104, // 0014 GETMBR R10 R0 K4
|
||||
0x7C180800, // 0015 CALL R6 4
|
||||
0x581C000B, // 0016 LDCONST R7 K11
|
||||
0x7C100600, // 0017 CALL R4 3
|
||||
0x70020008, // 0018 JMP #0022
|
||||
0xB8120E00, // 0019 GETNGBL R4 K7
|
||||
0x8C100908, // 001A GETMET R4 R4 K8
|
||||
0x8C180509, // 001B GETMET R6 R2 K9
|
||||
0x5820000C, // 001C LDCONST R8 K12
|
||||
0x88240102, // 001D GETMBR R9 R0 K2
|
||||
0x88280104, // 001E GETMBR R10 R0 K4
|
||||
0x7C180800, // 001F CALL R6 4
|
||||
0x581C000D, // 0020 LDCONST R7 K13
|
||||
0x7C100600, // 0021 CALL R4 3
|
||||
0x80000000, // 0022 RET 0
|
||||
})
|
||||
)
|
||||
);
|
||||
/*******************************************************************/
|
||||
|
||||
|
||||
/********************************************************************
|
||||
** Solidified class: Matter_UDPPacket_sent
|
||||
********************************************************************/
|
||||
be_local_class(Matter_UDPPacket_sent,
|
||||
6,
|
||||
NULL,
|
||||
be_nested_map(10,
|
||||
( (struct bmapnode*) &(const bmapnode[]) {
|
||||
{ be_const_key_weak(RETRY_MS, 7), be_const_int(500) },
|
||||
{ be_const_key_weak(raw, 4), be_const_var(0) },
|
||||
{ be_const_key_weak(next_try, 9), be_const_var(5) },
|
||||
{ be_const_key_weak(retries, -1), be_const_var(4) },
|
||||
{ be_const_key_weak(send, 6), be_const_closure(Matter_UDPPacket_sent_send_closure) },
|
||||
{ be_const_key_weak(init, -1), be_const_closure(Matter_UDPPacket_sent_init_closure) },
|
||||
{ be_const_key_weak(RETRIES, -1), be_const_int(4) },
|
||||
{ be_const_key_weak(port, -1), be_const_var(2) },
|
||||
{ be_const_key_weak(addr, -1), be_const_var(1) },
|
||||
{ be_const_key_weak(msg_id, -1), be_const_var(3) },
|
||||
})),
|
||||
be_str_weak(Matter_UDPPacket_sent)
|
||||
);
|
||||
/*******************************************************************/
|
||||
|
||||
void be_load_Matter_UDPPacket_sent_class(bvm *vm) {
|
||||
be_pushntvclass(vm, &be_class_Matter_UDPPacket_sent);
|
||||
be_setglobal(vm, "Matter_UDPPacket_sent");
|
||||
be_pop(vm, 1);
|
||||
}
|
||||
|
||||
extern const bclass be_class_Matter_UDPServer;
|
||||
|
||||
/********************************************************************
|
||||
** Solidified function: init
|
||||
********************************************************************/
|
||||
be_local_closure(Matter_UDPServer_init, /* name */
|
||||
be_nested_proto(
|
||||
4, /* nstack */
|
||||
3, /* argc */
|
||||
2, /* varg */
|
||||
0, /* has upvals */
|
||||
NULL, /* no upvals */
|
||||
0, /* has sup protos */
|
||||
NULL, /* no sub protos */
|
||||
1, /* has constants */
|
||||
( &(const bvalue[ 5]) { /* constants */
|
||||
/* K0 */ be_nested_str_weak(address),
|
||||
/* K1 */ be_nested_str_weak(),
|
||||
/* K2 */ be_nested_str_weak(port),
|
||||
/* K3 */ be_nested_str_weak(listening),
|
||||
/* K4 */ be_nested_str_weak(packets_sent),
|
||||
}),
|
||||
be_str_weak(init),
|
||||
&be_const_str_solidified,
|
||||
( &(const binstruction[16]) { /* code */
|
||||
0x78060001, // 0000 JMPF R1 #0003
|
||||
0x5C0C0200, // 0001 MOVE R3 R1
|
||||
0x70020000, // 0002 JMP #0004
|
||||
0x580C0001, // 0003 LDCONST R3 K1
|
||||
0x90020003, // 0004 SETMBR R0 K0 R3
|
||||
0x780A0001, // 0005 JMPF R2 #0008
|
||||
0x5C0C0400, // 0006 MOVE R3 R2
|
||||
0x70020000, // 0007 JMP #0009
|
||||
0x540E15A3, // 0008 LDINT R3 5540
|
||||
0x90020403, // 0009 SETMBR R0 K2 R3
|
||||
0x500C0000, // 000A LDBOOL R3 0 0
|
||||
0x90020603, // 000B SETMBR R0 K3 R3
|
||||
0x600C0013, // 000C GETGBL R3 G19
|
||||
0x7C0C0000, // 000D CALL R3 0
|
||||
0x90020803, // 000E SETMBR R0 K4 R3
|
||||
0x80000000, // 000F RET 0
|
||||
})
|
||||
)
|
||||
);
|
||||
/*******************************************************************/
|
||||
|
||||
|
||||
/********************************************************************
|
||||
** Solidified function: every_second
|
||||
********************************************************************/
|
||||
be_local_closure(Matter_UDPServer_every_second, /* name */
|
||||
be_nested_proto(
|
||||
1, /* nstack */
|
||||
1, /* argc */
|
||||
2, /* varg */
|
||||
0, /* has upvals */
|
||||
NULL, /* no upvals */
|
||||
0, /* has sup protos */
|
||||
NULL, /* no sub protos */
|
||||
0, /* has constants */
|
||||
NULL, /* no const */
|
||||
be_str_weak(every_second),
|
||||
&be_const_str_solidified,
|
||||
( &(const binstruction[ 1]) { /* code */
|
||||
0x80000000, // 0000 RET 0
|
||||
})
|
||||
)
|
||||
);
|
||||
/*******************************************************************/
|
||||
|
||||
|
||||
/********************************************************************
|
||||
** Solidified function: stop
|
||||
********************************************************************/
|
||||
be_local_closure(Matter_UDPServer_stop, /* name */
|
||||
be_nested_proto(
|
||||
4, /* nstack */
|
||||
1, /* argc */
|
||||
2, /* varg */
|
||||
0, /* has upvals */
|
||||
NULL, /* no upvals */
|
||||
0, /* has sup protos */
|
||||
NULL, /* no sub protos */
|
||||
1, /* has constants */
|
||||
( &(const bvalue[ 5]) { /* constants */
|
||||
/* K0 */ be_nested_str_weak(listening),
|
||||
/* K1 */ be_nested_str_weak(udp_socket),
|
||||
/* K2 */ be_nested_str_weak(stop),
|
||||
/* K3 */ be_nested_str_weak(tasmota),
|
||||
/* K4 */ be_nested_str_weak(remove_driver),
|
||||
}),
|
||||
be_str_weak(stop),
|
||||
&be_const_str_solidified,
|
||||
( &(const binstruction[12]) { /* code */
|
||||
0x88040100, // 0000 GETMBR R1 R0 K0
|
||||
0x78060008, // 0001 JMPF R1 #000B
|
||||
0x88040101, // 0002 GETMBR R1 R0 K1
|
||||
0x8C040302, // 0003 GETMET R1 R1 K2
|
||||
0x7C040200, // 0004 CALL R1 1
|
||||
0x50040000, // 0005 LDBOOL R1 0 0
|
||||
0x90020001, // 0006 SETMBR R0 K0 R1
|
||||
0xB8060600, // 0007 GETNGBL R1 K3
|
||||
0x8C040304, // 0008 GETMET R1 R1 K4
|
||||
0x5C0C0000, // 0009 MOVE R3 R0
|
||||
0x7C040400, // 000A CALL R1 2
|
||||
0x80000000, // 000B RET 0
|
||||
})
|
||||
)
|
||||
);
|
||||
/*******************************************************************/
|
||||
|
||||
|
||||
/********************************************************************
|
||||
** Solidified function: every_50ms
|
||||
********************************************************************/
|
||||
be_local_closure(Matter_UDPServer_every_50ms, /* name */
|
||||
be_nested_proto(
|
||||
13, /* nstack */
|
||||
1, /* argc */
|
||||
2, /* varg */
|
||||
0, /* has upvals */
|
||||
NULL, /* no upvals */
|
||||
0, /* has sup protos */
|
||||
NULL, /* no sub protos */
|
||||
1, /* has constants */
|
||||
( &(const bvalue[14]) { /* constants */
|
||||
/* K0 */ be_nested_str_weak(string),
|
||||
/* K1 */ be_const_int(0),
|
||||
/* K2 */ be_nested_str_weak(udp_socket),
|
||||
/* K3 */ be_nested_str_weak(read),
|
||||
/* K4 */ be_const_int(1),
|
||||
/* K5 */ be_nested_str_weak(remote_ip),
|
||||
/* K6 */ be_nested_str_weak(remote_port),
|
||||
/* K7 */ be_nested_str_weak(tasmota),
|
||||
/* K8 */ be_nested_str_weak(log),
|
||||
/* K9 */ be_nested_str_weak(format),
|
||||
/* K10 */ be_nested_str_weak(MTR_X3A_X20UDP_X20received_X20from_X20_X5B_X25s_X5D_X3A_X25i),
|
||||
/* K11 */ be_nested_str_weak(dispatch_cb),
|
||||
/* K12 */ be_nested_str_weak(MAX_PACKETS_READ),
|
||||
/* K13 */ be_nested_str_weak(resend_packets),
|
||||
}),
|
||||
be_str_weak(every_50ms),
|
||||
&be_const_str_solidified,
|
||||
( &(const binstruction[47]) { /* code */
|
||||
0xA4060000, // 0000 IMPORT R1 K0
|
||||
0x58080001, // 0001 LDCONST R2 K1
|
||||
0x880C0102, // 0002 GETMBR R3 R0 K2
|
||||
0x4C100000, // 0003 LDNIL R4
|
||||
0x1C0C0604, // 0004 EQ R3 R3 R4
|
||||
0x780E0000, // 0005 JMPF R3 #0007
|
||||
0x80000600, // 0006 RET 0
|
||||
0x880C0102, // 0007 GETMBR R3 R0 K2
|
||||
0x8C0C0703, // 0008 GETMET R3 R3 K3
|
||||
0x7C0C0200, // 0009 CALL R3 1
|
||||
0x4C100000, // 000A LDNIL R4
|
||||
0x20100604, // 000B NE R4 R3 R4
|
||||
0x7812001E, // 000C JMPF R4 #002C
|
||||
0x00080504, // 000D ADD R2 R2 K4
|
||||
0x88100102, // 000E GETMBR R4 R0 K2
|
||||
0x88100905, // 000F GETMBR R4 R4 K5
|
||||
0x88140102, // 0010 GETMBR R5 R0 K2
|
||||
0x88140B06, // 0011 GETMBR R5 R5 K6
|
||||
0xB81A0E00, // 0012 GETNGBL R6 K7
|
||||
0x8C180D08, // 0013 GETMET R6 R6 K8
|
||||
0x8C200309, // 0014 GETMET R8 R1 K9
|
||||
0x5828000A, // 0015 LDCONST R10 K10
|
||||
0x5C2C0800, // 0016 MOVE R11 R4
|
||||
0x5C300A00, // 0017 MOVE R12 R5
|
||||
0x7C200800, // 0018 CALL R8 4
|
||||
0x54260003, // 0019 LDINT R9 4
|
||||
0x7C180600, // 001A CALL R6 3
|
||||
0x8818010B, // 001B GETMBR R6 R0 K11
|
||||
0x781A0004, // 001C JMPF R6 #0022
|
||||
0x8C18010B, // 001D GETMET R6 R0 K11
|
||||
0x5C200600, // 001E MOVE R8 R3
|
||||
0x5C240800, // 001F MOVE R9 R4
|
||||
0x5C280A00, // 0020 MOVE R10 R5
|
||||
0x7C180800, // 0021 CALL R6 4
|
||||
0x8818010C, // 0022 GETMBR R6 R0 K12
|
||||
0x14180406, // 0023 LT R6 R2 R6
|
||||
0x781A0004, // 0024 JMPF R6 #002A
|
||||
0x88180102, // 0025 GETMBR R6 R0 K2
|
||||
0x8C180D03, // 0026 GETMET R6 R6 K3
|
||||
0x7C180200, // 0027 CALL R6 1
|
||||
0x5C0C0C00, // 0028 MOVE R3 R6
|
||||
0x70020000, // 0029 JMP #002B
|
||||
0x4C0C0000, // 002A LDNIL R3
|
||||
0x7001FFDD, // 002B JMP #000A
|
||||
0x8C10010D, // 002C GETMET R4 R0 K13
|
||||
0x7C100200, // 002D CALL R4 1
|
||||
0x80000000, // 002E RET 0
|
||||
})
|
||||
)
|
||||
);
|
||||
/*******************************************************************/
|
||||
|
||||
|
||||
/********************************************************************
|
||||
** Solidified function: resend_packets
|
||||
********************************************************************/
|
||||
be_local_closure(Matter_UDPServer_resend_packets, /* name */
|
||||
be_nested_proto(
|
||||
7, /* nstack */
|
||||
1, /* argc */
|
||||
2, /* varg */
|
||||
0, /* has upvals */
|
||||
NULL, /* no upvals */
|
||||
0, /* has sup protos */
|
||||
NULL, /* no sub protos */
|
||||
1, /* has constants */
|
||||
( &(const bvalue[17]) { /* constants */
|
||||
/* K0 */ be_nested_str_weak(packets_sent),
|
||||
/* K1 */ be_nested_str_weak(tasmota),
|
||||
/* K2 */ be_nested_str_weak(time_reached),
|
||||
/* K3 */ be_nested_str_weak(next_try),
|
||||
/* K4 */ be_nested_str_weak(log),
|
||||
/* K5 */ be_nested_str_weak(MTR_X3A_X20resending_X20packet_X20id_X3D),
|
||||
/* K6 */ be_nested_str_weak(msg_id),
|
||||
/* K7 */ be_const_int(3),
|
||||
/* K8 */ be_nested_str_weak(send),
|
||||
/* K9 */ be_nested_str_weak(udp_socket),
|
||||
/* K10 */ be_nested_str_weak(retries),
|
||||
/* K11 */ be_const_int(1),
|
||||
/* K12 */ be_const_int(0),
|
||||
/* K13 */ be_nested_str_weak(remove),
|
||||
/* K14 */ be_nested_str_weak(millis),
|
||||
/* K15 */ be_nested_str_weak(RETRY_MS),
|
||||
/* K16 */ be_nested_str_weak(stop_iteration),
|
||||
}),
|
||||
be_str_weak(resend_packets),
|
||||
&be_const_str_solidified,
|
||||
( &(const binstruction[44]) { /* code */
|
||||
0x60040010, // 0000 GETGBL R1 G16
|
||||
0x88080100, // 0001 GETMBR R2 R0 K0
|
||||
0x7C040200, // 0002 CALL R1 1
|
||||
0xA8020023, // 0003 EXBLK 0 #0028
|
||||
0x5C080200, // 0004 MOVE R2 R1
|
||||
0x7C080000, // 0005 CALL R2 0
|
||||
0xB80E0200, // 0006 GETNGBL R3 K1
|
||||
0x8C0C0702, // 0007 GETMET R3 R3 K2
|
||||
0x88140503, // 0008 GETMBR R5 R2 K3
|
||||
0x7C0C0400, // 0009 CALL R3 2
|
||||
0x780E001B, // 000A JMPF R3 #0027
|
||||
0xB80E0200, // 000B GETNGBL R3 K1
|
||||
0x8C0C0704, // 000C GETMET R3 R3 K4
|
||||
0x60140008, // 000D GETGBL R5 G8
|
||||
0x88180506, // 000E GETMBR R6 R2 K6
|
||||
0x7C140200, // 000F CALL R5 1
|
||||
0x00160A05, // 0010 ADD R5 K5 R5
|
||||
0x58180007, // 0011 LDCONST R6 K7
|
||||
0x7C0C0600, // 0012 CALL R3 3
|
||||
0x8C0C0508, // 0013 GETMET R3 R2 K8
|
||||
0x88140109, // 0014 GETMBR R5 R0 K9
|
||||
0x7C0C0400, // 0015 CALL R3 2
|
||||
0x880C050A, // 0016 GETMBR R3 R2 K10
|
||||
0x040C070B, // 0017 SUB R3 R3 K11
|
||||
0x900A1403, // 0018 SETMBR R2 K10 R3
|
||||
0x880C050A, // 0019 GETMBR R3 R2 K10
|
||||
0x180C070C, // 001A LE R3 R3 K12
|
||||
0x780E0004, // 001B JMPF R3 #0021
|
||||
0x880C0100, // 001C GETMBR R3 R0 K0
|
||||
0x8C0C070D, // 001D GETMET R3 R3 K13
|
||||
0x88140506, // 001E GETMBR R5 R2 K6
|
||||
0x7C0C0400, // 001F CALL R3 2
|
||||
0x70020005, // 0020 JMP #0027
|
||||
0xB80E0200, // 0021 GETNGBL R3 K1
|
||||
0x8C0C070E, // 0022 GETMET R3 R3 K14
|
||||
0x7C0C0200, // 0023 CALL R3 1
|
||||
0x8810050F, // 0024 GETMBR R4 R2 K15
|
||||
0x000C0604, // 0025 ADD R3 R3 R4
|
||||
0x900A0603, // 0026 SETMBR R2 K3 R3
|
||||
0x7001FFDB, // 0027 JMP #0004
|
||||
0x58040010, // 0028 LDCONST R1 K16
|
||||
0xAC040200, // 0029 CATCH R1 1 0
|
||||
0xB0080000, // 002A RAISE 2 R0 R0
|
||||
0x80000000, // 002B RET 0
|
||||
})
|
||||
)
|
||||
);
|
||||
/*******************************************************************/
|
||||
|
||||
|
||||
/********************************************************************
|
||||
** Solidified function: start
|
||||
********************************************************************/
|
||||
be_local_closure(Matter_UDPServer_start, /* name */
|
||||
be_nested_proto(
|
||||
6, /* nstack */
|
||||
2, /* argc */
|
||||
2, /* varg */
|
||||
0, /* has upvals */
|
||||
NULL, /* no upvals */
|
||||
0, /* has sup protos */
|
||||
NULL, /* no sub protos */
|
||||
1, /* has constants */
|
||||
( &(const bvalue[11]) { /* constants */
|
||||
/* K0 */ be_nested_str_weak(listening),
|
||||
/* K1 */ be_nested_str_weak(udp_socket),
|
||||
/* K2 */ be_nested_str_weak(udp),
|
||||
/* K3 */ be_nested_str_weak(begin),
|
||||
/* K4 */ be_nested_str_weak(address),
|
||||
/* K5 */ be_nested_str_weak(port),
|
||||
/* K6 */ be_nested_str_weak(network_error),
|
||||
/* K7 */ be_nested_str_weak(could_X20not_X20open_X20UDP_X20server),
|
||||
/* K8 */ be_nested_str_weak(dispatch_cb),
|
||||
/* K9 */ be_nested_str_weak(tasmota),
|
||||
/* K10 */ be_nested_str_weak(add_driver),
|
||||
}),
|
||||
be_str_weak(start),
|
||||
&be_const_str_solidified,
|
||||
( &(const binstruction[21]) { /* code */
|
||||
0x88080100, // 0000 GETMBR R2 R0 K0
|
||||
0x740A0011, // 0001 JMPT R2 #0014
|
||||
0xB80A0400, // 0002 GETNGBL R2 K2
|
||||
0x7C080000, // 0003 CALL R2 0
|
||||
0x90020202, // 0004 SETMBR R0 K1 R2
|
||||
0x88080101, // 0005 GETMBR R2 R0 K1
|
||||
0x8C080503, // 0006 GETMET R2 R2 K3
|
||||
0x88100104, // 0007 GETMBR R4 R0 K4
|
||||
0x88140105, // 0008 GETMBR R5 R0 K5
|
||||
0x7C080600, // 0009 CALL R2 3
|
||||
0x5C0C0400, // 000A MOVE R3 R2
|
||||
0x740E0000, // 000B JMPT R3 #000D
|
||||
0xB0060D07, // 000C RAISE 1 K6 K7
|
||||
0x500C0200, // 000D LDBOOL R3 1 0
|
||||
0x90020003, // 000E SETMBR R0 K0 R3
|
||||
0x90021001, // 000F SETMBR R0 K8 R1
|
||||
0xB80E1200, // 0010 GETNGBL R3 K9
|
||||
0x8C0C070A, // 0011 GETMET R3 R3 K10
|
||||
0x5C140000, // 0012 MOVE R5 R0
|
||||
0x7C0C0400, // 0013 CALL R3 2
|
||||
0x80000000, // 0014 RET 0
|
||||
})
|
||||
)
|
||||
);
|
||||
/*******************************************************************/
|
||||
|
||||
|
||||
/********************************************************************
|
||||
** Solidified function: send_response
|
||||
********************************************************************/
|
||||
be_local_closure(Matter_UDPServer_send_response, /* name */
|
||||
be_nested_proto(
|
||||
11, /* nstack */
|
||||
5, /* argc */
|
||||
2, /* varg */
|
||||
0, /* has upvals */
|
||||
NULL, /* no upvals */
|
||||
0, /* has sup protos */
|
||||
NULL, /* no sub protos */
|
||||
1, /* has constants */
|
||||
( &(const bvalue[ 5]) { /* constants */
|
||||
/* K0 */ be_nested_str_weak(matter),
|
||||
/* K1 */ be_nested_str_weak(UDPPacket_sent),
|
||||
/* K2 */ be_nested_str_weak(send),
|
||||
/* K3 */ be_nested_str_weak(udp_socket),
|
||||
/* K4 */ be_nested_str_weak(packets_sent),
|
||||
}),
|
||||
be_str_weak(send_response),
|
||||
&be_const_str_solidified,
|
||||
( &(const binstruction[14]) { /* code */
|
||||
0xB8160000, // 0000 GETNGBL R5 K0
|
||||
0x8C140B01, // 0001 GETMET R5 R5 K1
|
||||
0x5C1C0200, // 0002 MOVE R7 R1
|
||||
0x5C200400, // 0003 MOVE R8 R2
|
||||
0x5C240600, // 0004 MOVE R9 R3
|
||||
0x5C280800, // 0005 MOVE R10 R4
|
||||
0x7C140A00, // 0006 CALL R5 5
|
||||
0x8C180B02, // 0007 GETMET R6 R5 K2
|
||||
0x88200103, // 0008 GETMBR R8 R0 K3
|
||||
0x7C180400, // 0009 CALL R6 2
|
||||
0x78120001, // 000A JMPF R4 #000D
|
||||
0x88180104, // 000B GETMBR R6 R0 K4
|
||||
0x98180805, // 000C SETIDX R6 R4 R5
|
||||
0x80000000, // 000D RET 0
|
||||
})
|
||||
)
|
||||
);
|
||||
/*******************************************************************/
|
||||
|
||||
|
||||
/********************************************************************
|
||||
** Solidified function: packet_ack
|
||||
********************************************************************/
|
||||
be_local_closure(Matter_UDPServer_packet_ack, /* name */
|
||||
be_nested_proto(
|
||||
6, /* nstack */
|
||||
2, /* argc */
|
||||
2, /* varg */
|
||||
0, /* has upvals */
|
||||
NULL, /* no upvals */
|
||||
0, /* has sup protos */
|
||||
NULL, /* no sub protos */
|
||||
1, /* has constants */
|
||||
( &(const bvalue[ 7]) { /* constants */
|
||||
/* K0 */ be_nested_str_weak(packets_sent),
|
||||
/* K1 */ be_nested_str_weak(contains),
|
||||
/* K2 */ be_nested_str_weak(remove),
|
||||
/* K3 */ be_nested_str_weak(tasmota),
|
||||
/* K4 */ be_nested_str_weak(log),
|
||||
/* K5 */ be_nested_str_weak(MTR_X3A_X20removed_X20packet_X20from_X20sending_X20list_X20id_X3D),
|
||||
/* K6 */ be_const_int(3),
|
||||
}),
|
||||
be_str_weak(packet_ack),
|
||||
&be_const_str_solidified,
|
||||
( &(const binstruction[22]) { /* code */
|
||||
0x4C080000, // 0000 LDNIL R2
|
||||
0x1C080202, // 0001 EQ R2 R1 R2
|
||||
0x780A0000, // 0002 JMPF R2 #0004
|
||||
0x80000400, // 0003 RET 0
|
||||
0x88080100, // 0004 GETMBR R2 R0 K0
|
||||
0x8C080501, // 0005 GETMET R2 R2 K1
|
||||
0x5C100200, // 0006 MOVE R4 R1
|
||||
0x7C080400, // 0007 CALL R2 2
|
||||
0x780A000B, // 0008 JMPF R2 #0015
|
||||
0x88080100, // 0009 GETMBR R2 R0 K0
|
||||
0x8C080502, // 000A GETMET R2 R2 K2
|
||||
0x5C100200, // 000B MOVE R4 R1
|
||||
0x7C080400, // 000C CALL R2 2
|
||||
0xB80A0600, // 000D GETNGBL R2 K3
|
||||
0x8C080504, // 000E GETMET R2 R2 K4
|
||||
0x60100008, // 000F GETGBL R4 G8
|
||||
0x5C140200, // 0010 MOVE R5 R1
|
||||
0x7C100200, // 0011 CALL R4 1
|
||||
0x00120A04, // 0012 ADD R4 K5 R4
|
||||
0x58140006, // 0013 LDCONST R5 K6
|
||||
0x7C080600, // 0014 CALL R2 3
|
||||
0x80000000, // 0015 RET 0
|
||||
})
|
||||
)
|
||||
);
|
||||
/*******************************************************************/
|
||||
|
||||
|
||||
/********************************************************************
|
||||
** Solidified class: Matter_UDPServer
|
||||
********************************************************************/
|
||||
be_local_class(Matter_UDPServer,
|
||||
6,
|
||||
NULL,
|
||||
be_nested_map(15,
|
||||
( (struct bmapnode*) &(const bmapnode[]) {
|
||||
{ be_const_key_weak(init, 1), be_const_closure(Matter_UDPServer_init_closure) },
|
||||
{ be_const_key_weak(every_second, -1), be_const_closure(Matter_UDPServer_every_second_closure) },
|
||||
{ be_const_key_weak(stop, -1), be_const_closure(Matter_UDPServer_stop_closure) },
|
||||
{ be_const_key_weak(udp_socket, -1), be_const_var(3) },
|
||||
{ be_const_key_weak(address, -1), be_const_var(0) },
|
||||
{ be_const_key_weak(dispatch_cb, -1), be_const_var(4) },
|
||||
{ be_const_key_weak(packet_ack, 7), be_const_closure(Matter_UDPServer_packet_ack_closure) },
|
||||
{ be_const_key_weak(MAX_PACKETS_READ, 13), be_const_int(4) },
|
||||
{ be_const_key_weak(every_50ms, 6), be_const_closure(Matter_UDPServer_every_50ms_closure) },
|
||||
{ be_const_key_weak(listening, -1), be_const_var(2) },
|
||||
{ be_const_key_weak(port, -1), be_const_var(1) },
|
||||
{ be_const_key_weak(start, -1), be_const_closure(Matter_UDPServer_start_closure) },
|
||||
{ be_const_key_weak(send_response, -1), be_const_closure(Matter_UDPServer_send_response_closure) },
|
||||
{ be_const_key_weak(resend_packets, -1), be_const_closure(Matter_UDPServer_resend_packets_closure) },
|
||||
{ be_const_key_weak(packets_sent, -1), be_const_var(5) },
|
||||
})),
|
||||
be_str_weak(Matter_UDPServer)
|
||||
);
|
||||
/*******************************************************************/
|
||||
|
||||
void be_load_Matter_UDPServer_class(bvm *vm) {
|
||||
be_pushntvclass(vm, &be_class_Matter_UDPServer);
|
||||
be_setglobal(vm, "Matter_UDPServer");
|
||||
be_pop(vm, 1);
|
||||
}
|
||||
/********************************************************************/
|
||||
/* End of solidification */
|
893
lib/libesp32/berry_matter/src/solidify/solidified_Matter_UI.h
Normal file
893
lib/libesp32/berry_matter/src/solidify/solidified_Matter_UI.h
Normal file
@ -0,0 +1,893 @@
|
||||
/* Solidification of Matter_UI.h */
|
||||
/********************************************************************\
|
||||
* Generated code, don't edit *
|
||||
\********************************************************************/
|
||||
#include "be_constobj.h"
|
||||
|
||||
extern const bclass be_class_Matter_UI;
|
||||
|
||||
/********************************************************************
|
||||
** Solidified function: show_commissioning_info
|
||||
********************************************************************/
|
||||
be_local_closure(Matter_UI_show_commissioning_info, /* name */
|
||||
be_nested_proto(
|
||||
12, /* nstack */
|
||||
1, /* argc */
|
||||
2, /* varg */
|
||||
0, /* has upvals */
|
||||
NULL, /* no upvals */
|
||||
0, /* has sup protos */
|
||||
NULL, /* no sub protos */
|
||||
1, /* has constants */
|
||||
( &(const bvalue[24]) { /* constants */
|
||||
/* K0 */ be_nested_str_weak(webserver),
|
||||
/* K1 */ be_nested_str_weak(string),
|
||||
/* K2 */ be_nested_str_weak(content_send),
|
||||
/* K3 */ be_nested_str_weak(_X3Cfieldset_X3E_X3Clegend_X3E_X3Cb_X3E_X26nbsp_X3BMatter_X20Passcode_X26nbsp_X3B_X3C_X2Fb_X3E_X3C_X2Flegend_X3E_X3Cp_X3E_X3C_X2Fp_X3E),
|
||||
/* K4 */ be_nested_str_weak(device),
|
||||
/* K5 */ be_nested_str_weak(compute_manual_pairing_code),
|
||||
/* K6 */ be_nested_str_weak(format),
|
||||
/* K7 */ be_nested_str_weak(_X3Cp_X3EManual_X20pairing_X20code_X3A_X3Cbr_X3E_X3Cb_X3E_X25s_X2D_X25s_X2D_X25s_X3C_X2Fb_X3E_X3C_X2Fp_X3E_X3Chr_X3E),
|
||||
/* K8 */ be_const_int(0),
|
||||
/* K9 */ be_const_int(3),
|
||||
/* K10 */ be_const_int(2147483647),
|
||||
/* K11 */ be_nested_str_weak(compute_qrcode_content),
|
||||
/* K12 */ be_nested_str_weak(_X3Cdiv_X20id_X3D_X22qrcode_X22_X3E_X3C_X2Fdiv_X3E),
|
||||
/* K13 */ be_nested_str_weak(_X3Cscript_X20type_X3D_X22text_X2Fjavascript_X22_X3E_X20new_X20QRCode_X28document_X2EgetElementById_X28_X22qrcode_X22_X29_X2C_X20_X22_X25s_X22_X29_X3B_X3C_X2Fscript_X3E),
|
||||
/* K14 */ be_nested_str_weak(_X3Cp_X3E_X25s_X3C_X2Fp_X3E_X3Chr_X3E),
|
||||
/* K15 */ be_nested_str_weak(_X3Cform_X20action_X3D_X27_X2Fmatterc_X27_X20method_X3D_X27post_X27_X20_X3E),
|
||||
/* K16 */ be_nested_str_weak(_X3Cp_X3EPasscode_X3A_X3C_X2Fp_X3E),
|
||||
/* K17 */ be_nested_str_weak(_X3Cinput_X20type_X3D_X27number_X27_X20min_X3D_X271_X27_X20max_X3D_X2799999998_X27_X20name_X3D_X27passcode_X27_X20value_X3D_X27_X25i_X27_X3E),
|
||||
/* K18 */ be_nested_str_weak(passcode),
|
||||
/* K19 */ be_nested_str_weak(_X3Cp_X3EDistinguish_X20id_X3A_X3C_X2Fp_X3E),
|
||||
/* K20 */ be_nested_str_weak(_X3Cinput_X20type_X3D_X27number_X27_X20min_X3D_X270_X27_X20max_X3D_X272047_X27_X20name_X3D_X27discriminator_X27_X20value_X3D_X27_X25i_X27_X3E),
|
||||
/* K21 */ be_nested_str_weak(discriminator),
|
||||
/* K22 */ be_nested_str_weak(_X3Cp_X3E_X3C_X2Fp_X3E_X3Cbutton_X20name_X3D_X27passcode_X27_X20class_X3D_X27button_X20bgrn_X27_X3EChange_X3C_X2Fbutton_X3E_X3C_X2Fform_X3E_X3C_X2Fp_X3E),
|
||||
/* K23 */ be_nested_str_weak(_X3Cp_X3E_X3C_X2Fp_X3E_X3C_X2Ffieldset_X3E_X3Cp_X3E_X3C_X2Fp_X3E),
|
||||
}),
|
||||
be_str_weak(show_commissioning_info),
|
||||
&be_const_str_solidified,
|
||||
( &(const binstruction[70]) { /* code */
|
||||
0xA4060000, // 0000 IMPORT R1 K0
|
||||
0xA40A0200, // 0001 IMPORT R2 K1
|
||||
0x8C0C0302, // 0002 GETMET R3 R1 K2
|
||||
0x58140003, // 0003 LDCONST R5 K3
|
||||
0x7C0C0400, // 0004 CALL R3 2
|
||||
0x880C0104, // 0005 GETMBR R3 R0 K4
|
||||
0x8C0C0705, // 0006 GETMET R3 R3 K5
|
||||
0x7C0C0200, // 0007 CALL R3 1
|
||||
0x8C100302, // 0008 GETMET R4 R1 K2
|
||||
0x8C180506, // 0009 GETMET R6 R2 K6
|
||||
0x58200007, // 000A LDCONST R8 K7
|
||||
0x40261109, // 000B CONNECT R9 K8 K9
|
||||
0x94240609, // 000C GETIDX R9 R3 R9
|
||||
0x542A0003, // 000D LDINT R10 4
|
||||
0x542E0005, // 000E LDINT R11 6
|
||||
0x4028140B, // 000F CONNECT R10 R10 R11
|
||||
0x9428060A, // 0010 GETIDX R10 R3 R10
|
||||
0x542E0006, // 0011 LDINT R11 7
|
||||
0x402C170A, // 0012 CONNECT R11 R11 K10
|
||||
0x942C060B, // 0013 GETIDX R11 R3 R11
|
||||
0x7C180A00, // 0014 CALL R6 5
|
||||
0x7C100400, // 0015 CALL R4 2
|
||||
0x88100104, // 0016 GETMBR R4 R0 K4
|
||||
0x8C10090B, // 0017 GETMET R4 R4 K11
|
||||
0x7C100200, // 0018 CALL R4 1
|
||||
0x8C140302, // 0019 GETMET R5 R1 K2
|
||||
0x581C000C, // 001A LDCONST R7 K12
|
||||
0x7C140400, // 001B CALL R5 2
|
||||
0x8C140302, // 001C GETMET R5 R1 K2
|
||||
0x8C1C0506, // 001D GETMET R7 R2 K6
|
||||
0x5824000D, // 001E LDCONST R9 K13
|
||||
0x5C280800, // 001F MOVE R10 R4
|
||||
0x7C1C0600, // 0020 CALL R7 3
|
||||
0x7C140400, // 0021 CALL R5 2
|
||||
0x8C140302, // 0022 GETMET R5 R1 K2
|
||||
0x8C1C0506, // 0023 GETMET R7 R2 K6
|
||||
0x5824000E, // 0024 LDCONST R9 K14
|
||||
0x5C280800, // 0025 MOVE R10 R4
|
||||
0x7C1C0600, // 0026 CALL R7 3
|
||||
0x7C140400, // 0027 CALL R5 2
|
||||
0x8C140302, // 0028 GETMET R5 R1 K2
|
||||
0x581C000F, // 0029 LDCONST R7 K15
|
||||
0x7C140400, // 002A CALL R5 2
|
||||
0x8C140302, // 002B GETMET R5 R1 K2
|
||||
0x581C0010, // 002C LDCONST R7 K16
|
||||
0x7C140400, // 002D CALL R5 2
|
||||
0x8C140302, // 002E GETMET R5 R1 K2
|
||||
0x8C1C0506, // 002F GETMET R7 R2 K6
|
||||
0x58240011, // 0030 LDCONST R9 K17
|
||||
0x88280104, // 0031 GETMBR R10 R0 K4
|
||||
0x88281512, // 0032 GETMBR R10 R10 K18
|
||||
0x7C1C0600, // 0033 CALL R7 3
|
||||
0x7C140400, // 0034 CALL R5 2
|
||||
0x8C140302, // 0035 GETMET R5 R1 K2
|
||||
0x581C0013, // 0036 LDCONST R7 K19
|
||||
0x7C140400, // 0037 CALL R5 2
|
||||
0x8C140302, // 0038 GETMET R5 R1 K2
|
||||
0x8C1C0506, // 0039 GETMET R7 R2 K6
|
||||
0x58240014, // 003A LDCONST R9 K20
|
||||
0x88280104, // 003B GETMBR R10 R0 K4
|
||||
0x88281515, // 003C GETMBR R10 R10 K21
|
||||
0x7C1C0600, // 003D CALL R7 3
|
||||
0x7C140400, // 003E CALL R5 2
|
||||
0x8C140302, // 003F GETMET R5 R1 K2
|
||||
0x581C0016, // 0040 LDCONST R7 K22
|
||||
0x7C140400, // 0041 CALL R5 2
|
||||
0x8C140302, // 0042 GETMET R5 R1 K2
|
||||
0x581C0017, // 0043 LDCONST R7 K23
|
||||
0x7C140400, // 0044 CALL R5 2
|
||||
0x80000000, // 0045 RET 0
|
||||
})
|
||||
)
|
||||
);
|
||||
/*******************************************************************/
|
||||
|
||||
|
||||
/********************************************************************
|
||||
** Solidified function: web_add_handler
|
||||
********************************************************************/
|
||||
be_local_closure(Matter_UI_web_add_handler, /* name */
|
||||
be_nested_proto(
|
||||
7, /* nstack */
|
||||
1, /* argc */
|
||||
2, /* varg */
|
||||
0, /* has upvals */
|
||||
NULL, /* no upvals */
|
||||
1, /* has sup protos */
|
||||
( &(const struct bproto*[ 3]) {
|
||||
be_nested_proto(
|
||||
2, /* nstack */
|
||||
0, /* argc */
|
||||
0, /* varg */
|
||||
1, /* has upvals */
|
||||
( &(const bupvaldesc[ 1]) { /* upvals */
|
||||
be_local_const_upval(1, 0),
|
||||
}),
|
||||
0, /* has sup protos */
|
||||
NULL, /* no sub protos */
|
||||
1, /* has constants */
|
||||
( &(const bvalue[ 1]) { /* constants */
|
||||
/* K0 */ be_nested_str_weak(page_part_mgr),
|
||||
}),
|
||||
be_str_weak(_X3Clambda_X3E),
|
||||
&be_const_str_solidified,
|
||||
( &(const binstruction[ 4]) { /* code */
|
||||
0x68000000, // 0000 GETUPV R0 U0
|
||||
0x8C000100, // 0001 GETMET R0 R0 K0
|
||||
0x7C000200, // 0002 CALL R0 1
|
||||
0x80040000, // 0003 RET 1 R0
|
||||
})
|
||||
),
|
||||
be_nested_proto(
|
||||
2, /* nstack */
|
||||
0, /* argc */
|
||||
0, /* varg */
|
||||
1, /* has upvals */
|
||||
( &(const bupvaldesc[ 1]) { /* upvals */
|
||||
be_local_const_upval(1, 0),
|
||||
}),
|
||||
0, /* has sup protos */
|
||||
NULL, /* no sub protos */
|
||||
1, /* has constants */
|
||||
( &(const bvalue[ 1]) { /* constants */
|
||||
/* K0 */ be_nested_str_weak(page_part_ctl),
|
||||
}),
|
||||
be_str_weak(_X3Clambda_X3E),
|
||||
&be_const_str_solidified,
|
||||
( &(const binstruction[ 4]) { /* code */
|
||||
0x68000000, // 0000 GETUPV R0 U0
|
||||
0x8C000100, // 0001 GETMET R0 R0 K0
|
||||
0x7C000200, // 0002 CALL R0 1
|
||||
0x80040000, // 0003 RET 1 R0
|
||||
})
|
||||
),
|
||||
be_nested_proto(
|
||||
2, /* nstack */
|
||||
0, /* argc */
|
||||
0, /* varg */
|
||||
1, /* has upvals */
|
||||
( &(const bupvaldesc[ 1]) { /* upvals */
|
||||
be_local_const_upval(1, 0),
|
||||
}),
|
||||
0, /* has sup protos */
|
||||
NULL, /* no sub protos */
|
||||
1, /* has constants */
|
||||
( &(const bvalue[ 1]) { /* constants */
|
||||
/* K0 */ be_nested_str_weak(page_qrcode_min_js),
|
||||
}),
|
||||
be_str_weak(_X3Clambda_X3E),
|
||||
&be_const_str_solidified,
|
||||
( &(const binstruction[ 4]) { /* code */
|
||||
0x68000000, // 0000 GETUPV R0 U0
|
||||
0x8C000100, // 0001 GETMET R0 R0 K0
|
||||
0x7C000200, // 0002 CALL R0 1
|
||||
0x80040000, // 0003 RET 1 R0
|
||||
})
|
||||
),
|
||||
}),
|
||||
1, /* has constants */
|
||||
( &(const bvalue[ 6]) { /* constants */
|
||||
/* K0 */ be_nested_str_weak(webserver),
|
||||
/* K1 */ be_nested_str_weak(on),
|
||||
/* K2 */ be_nested_str_weak(_X2Fmatterc),
|
||||
/* K3 */ be_nested_str_weak(HTTP_GET),
|
||||
/* K4 */ be_nested_str_weak(HTTP_POST),
|
||||
/* K5 */ be_nested_str_weak(_X2Fqrcode_X2Emin_X2Ejs),
|
||||
}),
|
||||
be_str_weak(web_add_handler),
|
||||
&be_const_str_solidified,
|
||||
( &(const binstruction[18]) { /* code */
|
||||
0xA4060000, // 0000 IMPORT R1 K0
|
||||
0x8C080301, // 0001 GETMET R2 R1 K1
|
||||
0x58100002, // 0002 LDCONST R4 K2
|
||||
0x84140000, // 0003 CLOSURE R5 P0
|
||||
0x88180303, // 0004 GETMBR R6 R1 K3
|
||||
0x7C080800, // 0005 CALL R2 4
|
||||
0x8C080301, // 0006 GETMET R2 R1 K1
|
||||
0x58100002, // 0007 LDCONST R4 K2
|
||||
0x84140001, // 0008 CLOSURE R5 P1
|
||||
0x88180304, // 0009 GETMBR R6 R1 K4
|
||||
0x7C080800, // 000A CALL R2 4
|
||||
0x8C080301, // 000B GETMET R2 R1 K1
|
||||
0x58100005, // 000C LDCONST R4 K5
|
||||
0x84140002, // 000D CLOSURE R5 P2
|
||||
0x88180303, // 000E GETMBR R6 R1 K3
|
||||
0x7C080800, // 000F CALL R2 4
|
||||
0xA0000000, // 0010 CLOSE R0
|
||||
0x80000000, // 0011 RET 0
|
||||
})
|
||||
)
|
||||
);
|
||||
/*******************************************************************/
|
||||
|
||||
|
||||
/********************************************************************
|
||||
** Solidified function: show_session_info
|
||||
********************************************************************/
|
||||
be_local_closure(Matter_UI_show_session_info, /* name */
|
||||
be_nested_proto(
|
||||
16, /* nstack */
|
||||
2, /* argc */
|
||||
2, /* varg */
|
||||
0, /* has upvals */
|
||||
NULL, /* no upvals */
|
||||
0, /* has sup protos */
|
||||
NULL, /* no sub protos */
|
||||
1, /* has constants */
|
||||
( &(const bvalue[26]) { /* constants */
|
||||
/* K0 */ be_nested_str_weak(webserver),
|
||||
/* K1 */ be_nested_str_weak(string),
|
||||
/* K2 */ be_nested_str_weak(content_send),
|
||||
/* K3 */ be_nested_str_weak(_X3Cfieldset_X3E_X3Clegend_X3E_X3Cb_X3E_X26nbsp_X3BSessions_X26nbsp_X3B_X3C_X2Fb_X3E_X3C_X2Flegend_X3E_X3Cp_X3E_X3C_X2Fp_X3E),
|
||||
/* K4 */ be_nested_str_weak(_X3Cp_X3EExisting_X20sessions_X3A_X3C_X2Fp_X3E),
|
||||
/* K5 */ be_nested_str_weak(device),
|
||||
/* K6 */ be_nested_str_weak(sessions),
|
||||
/* K7 */ be_const_int(0),
|
||||
/* K8 */ be_nested_str_weak(_X3Cp_X3E_X3Cb_X3ENone_X3C_X2Fb_X3E_X3C_X2Fp_X3E),
|
||||
/* K9 */ be_nested_str_weak(fabric),
|
||||
/* K10 */ be_nested_str_weak(format),
|
||||
/* K11 */ be_nested_str_weak(_X3Cfieldset_X3E_X3Clegend_X3E_X3Cb_X3E_X26nbsp_X3BSession_X20_X25i_X26nbsp_X3B_X3C_X2Fb_X3E_X3C_X2Flegend_X3E_X3Cp_X3E_X3C_X2Fp_X3E),
|
||||
/* K12 */ be_nested_str_weak(local_session_id),
|
||||
/* K13 */ be_nested_str_weak(_X3Chr_X3E),
|
||||
/* K14 */ be_nested_str_weak(copy),
|
||||
/* K15 */ be_nested_str_weak(reverse),
|
||||
/* K16 */ be_nested_str_weak(deviceid),
|
||||
/* K17 */ be_nested_str_weak(Fabric_X3A_X20_X25s_X3Cbr_X3E),
|
||||
/* K18 */ be_nested_str_weak(tohex),
|
||||
/* K19 */ be_nested_str_weak(Device_X3A_X20_X25s_X3Cbr_X3E_X26nbsp_X3B),
|
||||
/* K20 */ be_nested_str_weak(_X3Cform_X20action_X3D_X27_X2Fmatterc_X27_X20method_X3D_X27post_X27_X20),
|
||||
/* K21 */ be_nested_str_weak(onsubmit_X3D_X27return_X20confirm_X28_X22This_X20will_X20cause_X20a_X20restart_X2E_X22_X29_X3B_X27_X3E),
|
||||
/* K22 */ be_nested_str_weak(_X3Cinput_X20name_X3D_X27del_session_X27_X20type_X3D_X27hidden_X27_X20value_X3D_X27_X25d_X27_X3E),
|
||||
/* K23 */ be_nested_str_weak(_X3Cbutton_X20name_X3D_X27del_X27_X20class_X3D_X27button_X20bgrn_X27_X3EDelete_X20Session_X3C_X2Fbutton_X3E_X3C_X2Fform_X3E_X3C_X2Fp_X3E),
|
||||
/* K24 */ be_nested_str_weak(_X3Cp_X3E_X3C_X2Fp_X3E_X3C_X2Ffieldset_X3E_X3Cp_X3E_X3C_X2Fp_X3E),
|
||||
/* K25 */ be_const_int(1),
|
||||
}),
|
||||
be_str_weak(show_session_info),
|
||||
&be_const_str_solidified,
|
||||
( &(const binstruction[92]) { /* code */
|
||||
0xA40A0000, // 0000 IMPORT R2 K0
|
||||
0xA40E0200, // 0001 IMPORT R3 K1
|
||||
0x8C100502, // 0002 GETMET R4 R2 K2
|
||||
0x58180003, // 0003 LDCONST R6 K3
|
||||
0x7C100400, // 0004 CALL R4 2
|
||||
0x8C100502, // 0005 GETMET R4 R2 K2
|
||||
0x58180004, // 0006 LDCONST R6 K4
|
||||
0x7C100400, // 0007 CALL R4 2
|
||||
0x6010000C, // 0008 GETGBL R4 G12
|
||||
0x88140105, // 0009 GETMBR R5 R0 K5
|
||||
0x88140B06, // 000A GETMBR R5 R5 K6
|
||||
0x88140B06, // 000B GETMBR R5 R5 K6
|
||||
0x7C100200, // 000C CALL R4 1
|
||||
0x1C100907, // 000D EQ R4 R4 K7
|
||||
0x78120003, // 000E JMPF R4 #0013
|
||||
0x8C100502, // 000F GETMET R4 R2 K2
|
||||
0x58180008, // 0010 LDCONST R6 K8
|
||||
0x7C100400, // 0011 CALL R4 2
|
||||
0x70020044, // 0012 JMP #0058
|
||||
0x58100007, // 0013 LDCONST R4 K7
|
||||
0x6014000C, // 0014 GETGBL R5 G12
|
||||
0x88180105, // 0015 GETMBR R6 R0 K5
|
||||
0x88180D06, // 0016 GETMBR R6 R6 K6
|
||||
0x88180D06, // 0017 GETMBR R6 R6 K6
|
||||
0x7C140200, // 0018 CALL R5 1
|
||||
0x14180805, // 0019 LT R6 R4 R5
|
||||
0x781A003C, // 001A JMPF R6 #0058
|
||||
0x88180105, // 001B GETMBR R6 R0 K5
|
||||
0x88180D06, // 001C GETMBR R6 R6 K6
|
||||
0x88180D06, // 001D GETMBR R6 R6 K6
|
||||
0x94180C04, // 001E GETIDX R6 R6 R4
|
||||
0x881C0D09, // 001F GETMBR R7 R6 K9
|
||||
0x781E0034, // 0020 JMPF R7 #0056
|
||||
0x8C1C0502, // 0021 GETMET R7 R2 K2
|
||||
0x8C24070A, // 0022 GETMET R9 R3 K10
|
||||
0x582C000B, // 0023 LDCONST R11 K11
|
||||
0x88300D0C, // 0024 GETMBR R12 R6 K12
|
||||
0x7C240600, // 0025 CALL R9 3
|
||||
0x7C1C0400, // 0026 CALL R7 2
|
||||
0x201C0907, // 0027 NE R7 R4 K7
|
||||
0x781E0002, // 0028 JMPF R7 #002C
|
||||
0x8C1C0502, // 0029 GETMET R7 R2 K2
|
||||
0x5824000D, // 002A LDCONST R9 K13
|
||||
0x7C1C0400, // 002B CALL R7 2
|
||||
0x881C0D09, // 002C GETMBR R7 R6 K9
|
||||
0x8C1C0F0E, // 002D GETMET R7 R7 K14
|
||||
0x7C1C0200, // 002E CALL R7 1
|
||||
0x8C1C0F0F, // 002F GETMET R7 R7 K15
|
||||
0x7C1C0200, // 0030 CALL R7 1
|
||||
0x88200D10, // 0031 GETMBR R8 R6 K16
|
||||
0x8C20110E, // 0032 GETMET R8 R8 K14
|
||||
0x7C200200, // 0033 CALL R8 1
|
||||
0x8C20110F, // 0034 GETMET R8 R8 K15
|
||||
0x7C200200, // 0035 CALL R8 1
|
||||
0x8C240502, // 0036 GETMET R9 R2 K2
|
||||
0x8C2C070A, // 0037 GETMET R11 R3 K10
|
||||
0x58340011, // 0038 LDCONST R13 K17
|
||||
0x8C380F12, // 0039 GETMET R14 R7 K18
|
||||
0x7C380200, // 003A CALL R14 1
|
||||
0x7C2C0600, // 003B CALL R11 3
|
||||
0x7C240400, // 003C CALL R9 2
|
||||
0x8C240502, // 003D GETMET R9 R2 K2
|
||||
0x8C2C070A, // 003E GETMET R11 R3 K10
|
||||
0x58340013, // 003F LDCONST R13 K19
|
||||
0x8C381112, // 0040 GETMET R14 R8 K18
|
||||
0x7C380200, // 0041 CALL R14 1
|
||||
0x7C2C0600, // 0042 CALL R11 3
|
||||
0x7C240400, // 0043 CALL R9 2
|
||||
0x8C240502, // 0044 GETMET R9 R2 K2
|
||||
0x582C0014, // 0045 LDCONST R11 K20
|
||||
0x7C240400, // 0046 CALL R9 2
|
||||
0x8C240502, // 0047 GETMET R9 R2 K2
|
||||
0x582C0015, // 0048 LDCONST R11 K21
|
||||
0x7C240400, // 0049 CALL R9 2
|
||||
0x8C240502, // 004A GETMET R9 R2 K2
|
||||
0x8C2C070A, // 004B GETMET R11 R3 K10
|
||||
0x58340016, // 004C LDCONST R13 K22
|
||||
0x88380D0C, // 004D GETMBR R14 R6 K12
|
||||
0x7C2C0600, // 004E CALL R11 3
|
||||
0x7C240400, // 004F CALL R9 2
|
||||
0x8C240502, // 0050 GETMET R9 R2 K2
|
||||
0x582C0017, // 0051 LDCONST R11 K23
|
||||
0x7C240400, // 0052 CALL R9 2
|
||||
0x8C240502, // 0053 GETMET R9 R2 K2
|
||||
0x582C0018, // 0054 LDCONST R11 K24
|
||||
0x7C240400, // 0055 CALL R9 2
|
||||
0x00100919, // 0056 ADD R4 R4 K25
|
||||
0x7001FFC0, // 0057 JMP #0019
|
||||
0x8C100502, // 0058 GETMET R4 R2 K2
|
||||
0x58180018, // 0059 LDCONST R6 K24
|
||||
0x7C100400, // 005A CALL R4 2
|
||||
0x80000000, // 005B RET 0
|
||||
})
|
||||
)
|
||||
);
|
||||
/*******************************************************************/
|
||||
|
||||
|
||||
/********************************************************************
|
||||
** Solidified function: show_enable
|
||||
********************************************************************/
|
||||
be_local_closure(Matter_UI_show_enable, /* name */
|
||||
be_nested_proto(
|
||||
11, /* nstack */
|
||||
2, /* argc */
|
||||
2, /* varg */
|
||||
0, /* has upvals */
|
||||
NULL, /* no upvals */
|
||||
0, /* has sup protos */
|
||||
NULL, /* no sub protos */
|
||||
1, /* has constants */
|
||||
( &(const bvalue[20]) { /* constants */
|
||||
/* K0 */ be_nested_str_weak(webserver),
|
||||
/* K1 */ be_nested_str_weak(string),
|
||||
/* K2 */ be_nested_str_weak(tasmota),
|
||||
/* K3 */ be_nested_str_weak(get_option),
|
||||
/* K4 */ be_nested_str_weak(matter),
|
||||
/* K5 */ be_nested_str_weak(MATTER_OPTION),
|
||||
/* K6 */ be_nested_str_weak(content_send),
|
||||
/* K7 */ be_nested_str_weak(format),
|
||||
/* K8 */ be_nested_str_weak(_X3Cfieldset_X3E_X3Clegend_X3E_X3Cb_X3E_X26nbsp_X3BMatter_X20_X25s_X26nbsp_X3B_X3C_X2Fb_X3E_X3C_X2Flegend_X3E_X3Cp_X3E_X3C_X2Fp_X3E),
|
||||
/* K9 */ be_nested_str_weak(Enabled),
|
||||
/* K10 */ be_nested_str_weak(Disabled),
|
||||
/* K11 */ be_nested_str_weak(_X3Cp_X20style_X3D_X27width_X3A320px_X3B_X27_X3EMatter_X20support_X20is_X20experimental_X2E_X3C_X2Fp_X3E),
|
||||
/* K12 */ be_nested_str_weak(_X3Cform_X20action_X3D_X27_X2Fmatterc_X27_X20method_X3D_X27post_X27_X20onsubmit_X3D_X27return_X20confirm_X28_X22This_X20will_X20cause_X20a_X20restart_X2E_X22_X29_X3B_X27_X3E),
|
||||
/* K13 */ be_nested_str_weak(_X3Cp_X3E_X3C_X2Fp_X3E_X3Cbutton_X20name_X3D_X27_X25s_X27_X20class_X3D_X27button_X20bgrn_X27_X3E),
|
||||
/* K14 */ be_nested_str_weak(disable),
|
||||
/* K15 */ be_nested_str_weak(enable),
|
||||
/* K16 */ be_nested_str_weak(Disable),
|
||||
/* K17 */ be_nested_str_weak(Enable),
|
||||
/* K18 */ be_nested_str_weak(_X20Matter_X3C_X2Fbutton_X3E_X3C_X2Fform_X3E_X3C_X2Fp_X3E),
|
||||
/* K19 */ be_nested_str_weak(_X3Cp_X3E_X3C_X2Fp_X3E_X3C_X2Ffieldset_X3E_X3Cp_X3E_X3C_X2Fp_X3E),
|
||||
}),
|
||||
be_str_weak(show_enable),
|
||||
&be_const_str_solidified,
|
||||
( &(const binstruction[44]) { /* code */
|
||||
0xA40A0000, // 0000 IMPORT R2 K0
|
||||
0xA40E0200, // 0001 IMPORT R3 K1
|
||||
0xB8120400, // 0002 GETNGBL R4 K2
|
||||
0x8C100903, // 0003 GETMET R4 R4 K3
|
||||
0xB81A0800, // 0004 GETNGBL R6 K4
|
||||
0x88180D05, // 0005 GETMBR R6 R6 K5
|
||||
0x7C100400, // 0006 CALL R4 2
|
||||
0x8C140506, // 0007 GETMET R5 R2 K6
|
||||
0x8C1C0707, // 0008 GETMET R7 R3 K7
|
||||
0x58240008, // 0009 LDCONST R9 K8
|
||||
0x78120001, // 000A JMPF R4 #000D
|
||||
0x58280009, // 000B LDCONST R10 K9
|
||||
0x70020000, // 000C JMP #000E
|
||||
0x5828000A, // 000D LDCONST R10 K10
|
||||
0x7C1C0600, // 000E CALL R7 3
|
||||
0x7C140400, // 000F CALL R5 2
|
||||
0x8C140506, // 0010 GETMET R5 R2 K6
|
||||
0x581C000B, // 0011 LDCONST R7 K11
|
||||
0x7C140400, // 0012 CALL R5 2
|
||||
0x8C140506, // 0013 GETMET R5 R2 K6
|
||||
0x581C000C, // 0014 LDCONST R7 K12
|
||||
0x7C140400, // 0015 CALL R5 2
|
||||
0x8C140506, // 0016 GETMET R5 R2 K6
|
||||
0x8C1C0707, // 0017 GETMET R7 R3 K7
|
||||
0x5824000D, // 0018 LDCONST R9 K13
|
||||
0x78120001, // 0019 JMPF R4 #001C
|
||||
0x5828000E, // 001A LDCONST R10 K14
|
||||
0x70020000, // 001B JMP #001D
|
||||
0x5828000F, // 001C LDCONST R10 K15
|
||||
0x7C1C0600, // 001D CALL R7 3
|
||||
0x7C140400, // 001E CALL R5 2
|
||||
0x8C140506, // 001F GETMET R5 R2 K6
|
||||
0x78120001, // 0020 JMPF R4 #0023
|
||||
0x581C0010, // 0021 LDCONST R7 K16
|
||||
0x70020000, // 0022 JMP #0024
|
||||
0x581C0011, // 0023 LDCONST R7 K17
|
||||
0x7C140400, // 0024 CALL R5 2
|
||||
0x8C140506, // 0025 GETMET R5 R2 K6
|
||||
0x581C0012, // 0026 LDCONST R7 K18
|
||||
0x7C140400, // 0027 CALL R5 2
|
||||
0x8C140506, // 0028 GETMET R5 R2 K6
|
||||
0x581C0013, // 0029 LDCONST R7 K19
|
||||
0x7C140400, // 002A CALL R5 2
|
||||
0x80040800, // 002B RET 1 R4
|
||||
})
|
||||
)
|
||||
);
|
||||
/*******************************************************************/
|
||||
|
||||
|
||||
/********************************************************************
|
||||
** Solidified function: init
|
||||
********************************************************************/
|
||||
be_local_closure(Matter_UI_init, /* name */
|
||||
be_nested_proto(
|
||||
5, /* nstack */
|
||||
2, /* argc */
|
||||
2, /* varg */
|
||||
0, /* has upvals */
|
||||
NULL, /* no upvals */
|
||||
0, /* has sup protos */
|
||||
NULL, /* no sub protos */
|
||||
1, /* has constants */
|
||||
( &(const bvalue[ 3]) { /* constants */
|
||||
/* K0 */ be_nested_str_weak(device),
|
||||
/* K1 */ be_nested_str_weak(tasmota),
|
||||
/* K2 */ be_nested_str_weak(add_driver),
|
||||
}),
|
||||
be_str_weak(init),
|
||||
&be_const_str_solidified,
|
||||
( &(const binstruction[ 6]) { /* code */
|
||||
0x90020001, // 0000 SETMBR R0 K0 R1
|
||||
0xB80A0200, // 0001 GETNGBL R2 K1
|
||||
0x8C080502, // 0002 GETMET R2 R2 K2
|
||||
0x5C100000, // 0003 MOVE R4 R0
|
||||
0x7C080400, // 0004 CALL R2 2
|
||||
0x80000000, // 0005 RET 0
|
||||
})
|
||||
)
|
||||
);
|
||||
/*******************************************************************/
|
||||
|
||||
|
||||
/********************************************************************
|
||||
** Solidified function: page_part_ctl
|
||||
********************************************************************/
|
||||
be_local_closure(Matter_UI_page_part_ctl, /* name */
|
||||
be_nested_proto(
|
||||
15, /* nstack */
|
||||
1, /* argc */
|
||||
2, /* varg */
|
||||
0, /* has upvals */
|
||||
NULL, /* no upvals */
|
||||
0, /* has sup protos */
|
||||
NULL, /* no sub protos */
|
||||
1, /* has constants */
|
||||
( &(const bvalue[40]) { /* constants */
|
||||
/* K0 */ be_nested_str_weak(webserver),
|
||||
/* K1 */ be_nested_str_weak(check_privileged_access),
|
||||
/* K2 */ be_nested_str_weak(string),
|
||||
/* K3 */ be_nested_str_weak(partition_core),
|
||||
/* K4 */ be_nested_str_weak(persist),
|
||||
/* K5 */ be_nested_str_weak(Partition),
|
||||
/* K6 */ be_nested_str_weak(has_arg),
|
||||
/* K7 */ be_nested_str_weak(passcode),
|
||||
/* K8 */ be_nested_str_weak(discriminator),
|
||||
/* K9 */ be_nested_str_weak(device),
|
||||
/* K10 */ be_nested_str_weak(arg),
|
||||
/* K11 */ be_nested_str_weak(save_param),
|
||||
/* K12 */ be_nested_str_weak(redirect),
|
||||
/* K13 */ be_nested_str_weak(_X2F_X3Frst_X3D),
|
||||
/* K14 */ be_nested_str_weak(enable),
|
||||
/* K15 */ be_nested_str_weak(tasmota),
|
||||
/* K16 */ be_nested_str_weak(cmd),
|
||||
/* K17 */ be_nested_str_weak(SetOption),
|
||||
/* K18 */ be_nested_str_weak(matter),
|
||||
/* K19 */ be_nested_str_weak(MATTER_OPTION),
|
||||
/* K20 */ be_nested_str_weak(_X201),
|
||||
/* K21 */ be_nested_str_weak(disable),
|
||||
/* K22 */ be_nested_str_weak(_X200),
|
||||
/* K23 */ be_nested_str_weak(del_session),
|
||||
/* K24 */ be_nested_str_weak(sessions),
|
||||
/* K25 */ be_nested_str_weak(get_session_by_local_session_id),
|
||||
/* K26 */ be_nested_str_weak(remove_session),
|
||||
/* K27 */ be_nested_str_weak(save),
|
||||
/* K28 */ be_nested_str_weak(log),
|
||||
/* K29 */ be_nested_str_weak(format),
|
||||
/* K30 */ be_nested_str_weak(BRY_X3A_X20Exception_X3E_X20_X27_X25s_X27_X20_X2D_X20_X25s),
|
||||
/* K31 */ be_const_int(2),
|
||||
/* K32 */ be_nested_str_weak(content_start),
|
||||
/* K33 */ be_nested_str_weak(Parameter_X20error),
|
||||
/* K34 */ be_nested_str_weak(content_send_style),
|
||||
/* K35 */ be_nested_str_weak(content_send),
|
||||
/* K36 */ be_nested_str_weak(_X3Cp_X20style_X3D_X27width_X3A340px_X3B_X27_X3E_X3Cb_X3EException_X3A_X3C_X2Fb_X3E_X3Cbr_X3E_X27_X25s_X27_X3Cbr_X3E_X25s_X3C_X2Fp_X3E),
|
||||
/* K37 */ be_nested_str_weak(content_button),
|
||||
/* K38 */ be_nested_str_weak(BUTTON_MANAGEMENT),
|
||||
/* K39 */ be_nested_str_weak(content_stop),
|
||||
}),
|
||||
be_str_weak(page_part_ctl),
|
||||
&be_const_str_solidified,
|
||||
( &(const binstruction[144]) { /* code */
|
||||
0xA4060000, // 0000 IMPORT R1 K0
|
||||
0x8C080301, // 0001 GETMET R2 R1 K1
|
||||
0x7C080200, // 0002 CALL R2 1
|
||||
0x740A0001, // 0003 JMPT R2 #0006
|
||||
0x4C080000, // 0004 LDNIL R2
|
||||
0x80040400, // 0005 RET 1 R2
|
||||
0xA40A0400, // 0006 IMPORT R2 K2
|
||||
0xA40E0600, // 0007 IMPORT R3 K3
|
||||
0xA4120800, // 0008 IMPORT R4 K4
|
||||
0x8C140705, // 0009 GETMET R5 R3 K5
|
||||
0x7C140200, // 000A CALL R5 1
|
||||
0xA8020064, // 000B EXBLK 0 #0071
|
||||
0x8C180306, // 000C GETMET R6 R1 K6
|
||||
0x58200007, // 000D LDCONST R8 K7
|
||||
0x7C180400, // 000E CALL R6 2
|
||||
0x741A0003, // 000F JMPT R6 #0014
|
||||
0x8C180306, // 0010 GETMET R6 R1 K6
|
||||
0x58200008, // 0011 LDCONST R8 K8
|
||||
0x7C180400, // 0012 CALL R6 2
|
||||
0x781A001C, // 0013 JMPF R6 #0031
|
||||
0x8C180306, // 0014 GETMET R6 R1 K6
|
||||
0x58200007, // 0015 LDCONST R8 K7
|
||||
0x7C180400, // 0016 CALL R6 2
|
||||
0x781A0006, // 0017 JMPF R6 #001F
|
||||
0x88180109, // 0018 GETMBR R6 R0 K9
|
||||
0x601C0009, // 0019 GETGBL R7 G9
|
||||
0x8C20030A, // 001A GETMET R8 R1 K10
|
||||
0x58280007, // 001B LDCONST R10 K7
|
||||
0x7C200400, // 001C CALL R8 2
|
||||
0x7C1C0200, // 001D CALL R7 1
|
||||
0x901A0E07, // 001E SETMBR R6 K7 R7
|
||||
0x8C180306, // 001F GETMET R6 R1 K6
|
||||
0x58200008, // 0020 LDCONST R8 K8
|
||||
0x7C180400, // 0021 CALL R6 2
|
||||
0x781A0006, // 0022 JMPF R6 #002A
|
||||
0x88180109, // 0023 GETMBR R6 R0 K9
|
||||
0x601C0009, // 0024 GETGBL R7 G9
|
||||
0x8C20030A, // 0025 GETMET R8 R1 K10
|
||||
0x58280008, // 0026 LDCONST R10 K8
|
||||
0x7C200400, // 0027 CALL R8 2
|
||||
0x7C1C0200, // 0028 CALL R7 1
|
||||
0x901A1007, // 0029 SETMBR R6 K8 R7
|
||||
0x88180109, // 002A GETMBR R6 R0 K9
|
||||
0x8C180D0B, // 002B GETMET R6 R6 K11
|
||||
0x7C180200, // 002C CALL R6 1
|
||||
0x8C18030C, // 002D GETMET R6 R1 K12
|
||||
0x5820000D, // 002E LDCONST R8 K13
|
||||
0x7C180400, // 002F CALL R6 2
|
||||
0x7002003D, // 0030 JMP #006F
|
||||
0x8C180306, // 0031 GETMET R6 R1 K6
|
||||
0x5820000E, // 0032 LDCONST R8 K14
|
||||
0x7C180400, // 0033 CALL R6 2
|
||||
0x781A000C, // 0034 JMPF R6 #0042
|
||||
0xB81A1E00, // 0035 GETNGBL R6 K15
|
||||
0x8C180D10, // 0036 GETMET R6 R6 K16
|
||||
0x60200008, // 0037 GETGBL R8 G8
|
||||
0xB8262400, // 0038 GETNGBL R9 K18
|
||||
0x88241313, // 0039 GETMBR R9 R9 K19
|
||||
0x7C200200, // 003A CALL R8 1
|
||||
0x00222208, // 003B ADD R8 K17 R8
|
||||
0x00201114, // 003C ADD R8 R8 K20
|
||||
0x7C180400, // 003D CALL R6 2
|
||||
0x8C18030C, // 003E GETMET R6 R1 K12
|
||||
0x5820000D, // 003F LDCONST R8 K13
|
||||
0x7C180400, // 0040 CALL R6 2
|
||||
0x7002002C, // 0041 JMP #006F
|
||||
0x8C180306, // 0042 GETMET R6 R1 K6
|
||||
0x58200015, // 0043 LDCONST R8 K21
|
||||
0x7C180400, // 0044 CALL R6 2
|
||||
0x781A000C, // 0045 JMPF R6 #0053
|
||||
0xB81A1E00, // 0046 GETNGBL R6 K15
|
||||
0x8C180D10, // 0047 GETMET R6 R6 K16
|
||||
0x60200008, // 0048 GETGBL R8 G8
|
||||
0xB8262400, // 0049 GETNGBL R9 K18
|
||||
0x88241313, // 004A GETMBR R9 R9 K19
|
||||
0x7C200200, // 004B CALL R8 1
|
||||
0x00222208, // 004C ADD R8 K17 R8
|
||||
0x00201116, // 004D ADD R8 R8 K22
|
||||
0x7C180400, // 004E CALL R6 2
|
||||
0x8C18030C, // 004F GETMET R6 R1 K12
|
||||
0x5820000D, // 0050 LDCONST R8 K13
|
||||
0x7C180400, // 0051 CALL R6 2
|
||||
0x7002001B, // 0052 JMP #006F
|
||||
0x8C180306, // 0053 GETMET R6 R1 K6
|
||||
0x58200017, // 0054 LDCONST R8 K23
|
||||
0x7C180400, // 0055 CALL R6 2
|
||||
0x781A0017, // 0056 JMPF R6 #006F
|
||||
0x88180109, // 0057 GETMBR R6 R0 K9
|
||||
0x88180D18, // 0058 GETMBR R6 R6 K24
|
||||
0x8C180D19, // 0059 GETMET R6 R6 K25
|
||||
0x60200009, // 005A GETGBL R8 G9
|
||||
0x8C24030A, // 005B GETMET R9 R1 K10
|
||||
0x582C0017, // 005C LDCONST R11 K23
|
||||
0x7C240400, // 005D CALL R9 2
|
||||
0x7C200200, // 005E CALL R8 1
|
||||
0x7C180400, // 005F CALL R6 2
|
||||
0x4C1C0000, // 0060 LDNIL R7
|
||||
0x201C0C07, // 0061 NE R7 R6 R7
|
||||
0x781E0008, // 0062 JMPF R7 #006C
|
||||
0x881C0109, // 0063 GETMBR R7 R0 K9
|
||||
0x881C0F18, // 0064 GETMBR R7 R7 K24
|
||||
0x8C1C0F1A, // 0065 GETMET R7 R7 K26
|
||||
0x5C240C00, // 0066 MOVE R9 R6
|
||||
0x7C1C0400, // 0067 CALL R7 2
|
||||
0x881C0109, // 0068 GETMBR R7 R0 K9
|
||||
0x881C0F18, // 0069 GETMBR R7 R7 K24
|
||||
0x8C1C0F1B, // 006A GETMET R7 R7 K27
|
||||
0x7C1C0200, // 006B CALL R7 1
|
||||
0x8C1C030C, // 006C GETMET R7 R1 K12
|
||||
0x5824000D, // 006D LDCONST R9 K13
|
||||
0x7C1C0400, // 006E CALL R7 2
|
||||
0xA8040001, // 006F EXBLK 1 1
|
||||
0x7002001D, // 0070 JMP #008F
|
||||
0xAC180002, // 0071 CATCH R6 0 2
|
||||
0x7002001A, // 0072 JMP #008E
|
||||
0xB8221E00, // 0073 GETNGBL R8 K15
|
||||
0x8C20111C, // 0074 GETMET R8 R8 K28
|
||||
0x8C28051D, // 0075 GETMET R10 R2 K29
|
||||
0x5830001E, // 0076 LDCONST R12 K30
|
||||
0x5C340C00, // 0077 MOVE R13 R6
|
||||
0x5C380E00, // 0078 MOVE R14 R7
|
||||
0x7C280800, // 0079 CALL R10 4
|
||||
0x582C001F, // 007A LDCONST R11 K31
|
||||
0x7C200600, // 007B CALL R8 3
|
||||
0x8C200320, // 007C GETMET R8 R1 K32
|
||||
0x58280021, // 007D LDCONST R10 K33
|
||||
0x7C200400, // 007E CALL R8 2
|
||||
0x8C200322, // 007F GETMET R8 R1 K34
|
||||
0x7C200200, // 0080 CALL R8 1
|
||||
0x8C200323, // 0081 GETMET R8 R1 K35
|
||||
0x8C28051D, // 0082 GETMET R10 R2 K29
|
||||
0x58300024, // 0083 LDCONST R12 K36
|
||||
0x5C340C00, // 0084 MOVE R13 R6
|
||||
0x5C380E00, // 0085 MOVE R14 R7
|
||||
0x7C280800, // 0086 CALL R10 4
|
||||
0x7C200400, // 0087 CALL R8 2
|
||||
0x8C200325, // 0088 GETMET R8 R1 K37
|
||||
0x88280326, // 0089 GETMBR R10 R1 K38
|
||||
0x7C200400, // 008A CALL R8 2
|
||||
0x8C200327, // 008B GETMET R8 R1 K39
|
||||
0x7C200200, // 008C CALL R8 1
|
||||
0x70020000, // 008D JMP #008F
|
||||
0xB0080000, // 008E RAISE 2 R0 R0
|
||||
0x80000000, // 008F RET 0
|
||||
})
|
||||
)
|
||||
);
|
||||
/*******************************************************************/
|
||||
|
||||
|
||||
/********************************************************************
|
||||
** Solidified function: web_add_config_button
|
||||
********************************************************************/
|
||||
be_local_closure(Matter_UI_web_add_config_button, /* name */
|
||||
be_nested_proto(
|
||||
5, /* nstack */
|
||||
1, /* argc */
|
||||
2, /* varg */
|
||||
0, /* has upvals */
|
||||
NULL, /* no upvals */
|
||||
0, /* has sup protos */
|
||||
NULL, /* no sub protos */
|
||||
1, /* has constants */
|
||||
( &(const bvalue[ 6]) { /* constants */
|
||||
/* K0 */ be_nested_str_weak(webserver),
|
||||
/* K1 */ be_nested_str_weak(content_send),
|
||||
/* K2 */ be_nested_str_weak(_X3Cp_X3E_X3Cform_X20id_X3Dac_X20action_X3D_X27matterc_X27_X20style_X3D_X27display_X3A_X20block_X3B_X27_X20method_X3D_X27get_X27_X3E_X3Cbutton_X3E),
|
||||
/* K3 */ be_nested_str_weak(matter),
|
||||
/* K4 */ be_nested_str_weak(_LOGO),
|
||||
/* K5 */ be_nested_str_weak(_X20Configure_X20Matter_X3C_X2Fbutton_X3E_X3C_X2Fform_X3E_X3C_X2Fp_X3E),
|
||||
}),
|
||||
be_str_weak(web_add_config_button),
|
||||
&be_const_str_solidified,
|
||||
( &(const binstruction[12]) { /* code */
|
||||
0xA4060000, // 0000 IMPORT R1 K0
|
||||
0x8C080301, // 0001 GETMET R2 R1 K1
|
||||
0x58100002, // 0002 LDCONST R4 K2
|
||||
0x7C080400, // 0003 CALL R2 2
|
||||
0x8C080301, // 0004 GETMET R2 R1 K1
|
||||
0xB8120600, // 0005 GETNGBL R4 K3
|
||||
0x88100904, // 0006 GETMBR R4 R4 K4
|
||||
0x7C080400, // 0007 CALL R2 2
|
||||
0x8C080301, // 0008 GETMET R2 R1 K1
|
||||
0x58100005, // 0009 LDCONST R4 K5
|
||||
0x7C080400, // 000A CALL R2 2
|
||||
0x80000000, // 000B RET 0
|
||||
})
|
||||
)
|
||||
);
|
||||
/*******************************************************************/
|
||||
|
||||
|
||||
/********************************************************************
|
||||
** Solidified function: page_qrcode_min_js
|
||||
********************************************************************/
|
||||
be_local_closure(Matter_UI_page_qrcode_min_js, /* name */
|
||||
be_nested_proto(
|
||||
6, /* nstack */
|
||||
1, /* argc */
|
||||
2, /* varg */
|
||||
0, /* has upvals */
|
||||
NULL, /* no upvals */
|
||||
0, /* has sup protos */
|
||||
NULL, /* no sub protos */
|
||||
1, /* has constants */
|
||||
( &(const bvalue[ 6]) { /* constants */
|
||||
/* K0 */ be_nested_str_weak(webserver),
|
||||
/* K1 */ be_nested_str_weak(content_open),
|
||||
/* K2 */ be_nested_str_weak(text_X2Fjavascript),
|
||||
/* K3 */ be_nested_str_weak(content_send),
|
||||
/* K4 */ be_nested_str_weak(matter),
|
||||
/* K5 */ be_nested_str_weak(_QRCODE_MINJS),
|
||||
}),
|
||||
be_str_weak(page_qrcode_min_js),
|
||||
&be_const_str_solidified,
|
||||
( &(const binstruction[10]) { /* code */
|
||||
0xA4060000, // 0000 IMPORT R1 K0
|
||||
0x8C080301, // 0001 GETMET R2 R1 K1
|
||||
0x541200C7, // 0002 LDINT R4 200
|
||||
0x58140002, // 0003 LDCONST R5 K2
|
||||
0x7C080600, // 0004 CALL R2 3
|
||||
0x8C080303, // 0005 GETMET R2 R1 K3
|
||||
0xB8120800, // 0006 GETNGBL R4 K4
|
||||
0x88100905, // 0007 GETMBR R4 R4 K5
|
||||
0x7C080400, // 0008 CALL R2 2
|
||||
0x80000000, // 0009 RET 0
|
||||
})
|
||||
)
|
||||
);
|
||||
/*******************************************************************/
|
||||
|
||||
|
||||
/********************************************************************
|
||||
** Solidified function: page_part_mgr
|
||||
********************************************************************/
|
||||
be_local_closure(Matter_UI_page_part_mgr, /* name */
|
||||
be_nested_proto(
|
||||
6, /* nstack */
|
||||
1, /* argc */
|
||||
2, /* varg */
|
||||
0, /* has upvals */
|
||||
NULL, /* no upvals */
|
||||
0, /* has sup protos */
|
||||
NULL, /* no sub protos */
|
||||
1, /* has constants */
|
||||
( &(const bvalue[14]) { /* constants */
|
||||
/* K0 */ be_nested_str_weak(webserver),
|
||||
/* K1 */ be_nested_str_weak(string),
|
||||
/* K2 */ be_nested_str_weak(check_privileged_access),
|
||||
/* K3 */ be_nested_str_weak(content_start),
|
||||
/* K4 */ be_nested_str_weak(Matter),
|
||||
/* K5 */ be_nested_str_weak(content_send_style),
|
||||
/* K6 */ be_nested_str_weak(content_send),
|
||||
/* K7 */ be_nested_str_weak(_X3Cscript_X20type_X3D_X22text_X2Fjavascript_X22_X20src_X3D_X22qrcode_X2Emin_X2Ejs_X22_X3E_X3C_X2Fscript_X3E),
|
||||
/* K8 */ be_nested_str_weak(show_enable),
|
||||
/* K9 */ be_nested_str_weak(show_commissioning_info),
|
||||
/* K10 */ be_nested_str_weak(show_session_info),
|
||||
/* K11 */ be_nested_str_weak(content_button),
|
||||
/* K12 */ be_nested_str_weak(BUTTON_CONFIGURATION),
|
||||
/* K13 */ be_nested_str_weak(content_stop),
|
||||
}),
|
||||
be_str_weak(page_part_mgr),
|
||||
&be_const_str_solidified,
|
||||
( &(const binstruction[28]) { /* code */
|
||||
0xA4060000, // 0000 IMPORT R1 K0
|
||||
0xA40A0200, // 0001 IMPORT R2 K1
|
||||
0x8C0C0302, // 0002 GETMET R3 R1 K2
|
||||
0x7C0C0200, // 0003 CALL R3 1
|
||||
0x740E0001, // 0004 JMPT R3 #0007
|
||||
0x4C0C0000, // 0005 LDNIL R3
|
||||
0x80040600, // 0006 RET 1 R3
|
||||
0x8C0C0303, // 0007 GETMET R3 R1 K3
|
||||
0x58140004, // 0008 LDCONST R5 K4
|
||||
0x7C0C0400, // 0009 CALL R3 2
|
||||
0x8C0C0305, // 000A GETMET R3 R1 K5
|
||||
0x7C0C0200, // 000B CALL R3 1
|
||||
0x8C0C0306, // 000C GETMET R3 R1 K6
|
||||
0x58140007, // 000D LDCONST R5 K7
|
||||
0x7C0C0400, // 000E CALL R3 2
|
||||
0x8C0C0108, // 000F GETMET R3 R0 K8
|
||||
0x7C0C0200, // 0010 CALL R3 1
|
||||
0x780E0003, // 0011 JMPF R3 #0016
|
||||
0x8C0C0109, // 0012 GETMET R3 R0 K9
|
||||
0x7C0C0200, // 0013 CALL R3 1
|
||||
0x8C0C010A, // 0014 GETMET R3 R0 K10
|
||||
0x7C0C0200, // 0015 CALL R3 1
|
||||
0x8C0C030B, // 0016 GETMET R3 R1 K11
|
||||
0x8814030C, // 0017 GETMBR R5 R1 K12
|
||||
0x7C0C0400, // 0018 CALL R3 2
|
||||
0x8C0C030D, // 0019 GETMET R3 R1 K13
|
||||
0x7C0C0200, // 001A CALL R3 1
|
||||
0x80000000, // 001B RET 0
|
||||
})
|
||||
)
|
||||
);
|
||||
/*******************************************************************/
|
||||
|
||||
|
||||
/********************************************************************
|
||||
** Solidified class: Matter_UI
|
||||
********************************************************************/
|
||||
be_local_class(Matter_UI,
|
||||
1,
|
||||
NULL,
|
||||
be_nested_map(10,
|
||||
( (struct bmapnode*) &(const bmapnode[]) {
|
||||
{ be_const_key_weak(init, -1), be_const_closure(Matter_UI_init_closure) },
|
||||
{ be_const_key_weak(device, -1), be_const_var(0) },
|
||||
{ be_const_key_weak(web_add_handler, -1), be_const_closure(Matter_UI_web_add_handler_closure) },
|
||||
{ be_const_key_weak(page_part_ctl, -1), be_const_closure(Matter_UI_page_part_ctl_closure) },
|
||||
{ be_const_key_weak(show_enable, -1), be_const_closure(Matter_UI_show_enable_closure) },
|
||||
{ be_const_key_weak(show_commissioning_info, 7), be_const_closure(Matter_UI_show_commissioning_info_closure) },
|
||||
{ be_const_key_weak(show_session_info, 3), be_const_closure(Matter_UI_show_session_info_closure) },
|
||||
{ be_const_key_weak(web_add_config_button, 0), be_const_closure(Matter_UI_web_add_config_button_closure) },
|
||||
{ be_const_key_weak(page_qrcode_min_js, -1), be_const_closure(Matter_UI_page_qrcode_min_js_closure) },
|
||||
{ be_const_key_weak(page_part_mgr, -1), be_const_closure(Matter_UI_page_part_mgr_closure) },
|
||||
})),
|
||||
be_str_weak(Matter_UI)
|
||||
);
|
||||
/*******************************************************************/
|
||||
|
||||
void be_load_Matter_UI_class(bvm *vm) {
|
||||
be_pushntvclass(vm, &be_class_Matter_UI);
|
||||
be_setglobal(vm, "Matter_UI");
|
||||
be_pop(vm, 1);
|
||||
}
|
||||
/********************************************************************/
|
||||
/* End of solidification */
|
@ -0,0 +1,189 @@
|
||||
/* Solidification of Matter_inspect.h */
|
||||
/********************************************************************\
|
||||
* Generated code, don't edit *
|
||||
\********************************************************************/
|
||||
#include "be_constobj.h"
|
||||
|
||||
/********************************************************************
|
||||
** Solidified function: sort
|
||||
********************************************************************/
|
||||
be_local_closure(matter_sort, /* name */
|
||||
be_nested_proto(
|
||||
6, /* nstack */
|
||||
1, /* argc */
|
||||
0, /* varg */
|
||||
0, /* has upvals */
|
||||
NULL, /* no upvals */
|
||||
0, /* has sup protos */
|
||||
NULL, /* no sub protos */
|
||||
1, /* has constants */
|
||||
( &(const bvalue[ 3]) { /* constants */
|
||||
/* K0 */ be_const_int(1),
|
||||
/* K1 */ be_const_int(0),
|
||||
/* K2 */ be_nested_str_weak(stop_iteration),
|
||||
}),
|
||||
be_str_weak(sort),
|
||||
&be_const_str_solidified,
|
||||
( &(const binstruction[29]) { /* code */
|
||||
0x60040010, // 0000 GETGBL R1 G16
|
||||
0x6008000C, // 0001 GETGBL R2 G12
|
||||
0x5C0C0000, // 0002 MOVE R3 R0
|
||||
0x7C080200, // 0003 CALL R2 1
|
||||
0x04080500, // 0004 SUB R2 R2 K0
|
||||
0x400A0002, // 0005 CONNECT R2 K0 R2
|
||||
0x7C040200, // 0006 CALL R1 1
|
||||
0xA8020010, // 0007 EXBLK 0 #0019
|
||||
0x5C080200, // 0008 MOVE R2 R1
|
||||
0x7C080000, // 0009 CALL R2 0
|
||||
0x940C0002, // 000A GETIDX R3 R0 R2
|
||||
0x5C100400, // 000B MOVE R4 R2
|
||||
0x24140901, // 000C GT R5 R4 K1
|
||||
0x78160008, // 000D JMPF R5 #0017
|
||||
0x04140900, // 000E SUB R5 R4 K0
|
||||
0x94140005, // 000F GETIDX R5 R0 R5
|
||||
0x24140A03, // 0010 GT R5 R5 R3
|
||||
0x78160004, // 0011 JMPF R5 #0017
|
||||
0x04140900, // 0012 SUB R5 R4 K0
|
||||
0x94140005, // 0013 GETIDX R5 R0 R5
|
||||
0x98000805, // 0014 SETIDX R0 R4 R5
|
||||
0x04100900, // 0015 SUB R4 R4 K0
|
||||
0x7001FFF4, // 0016 JMP #000C
|
||||
0x98000803, // 0017 SETIDX R0 R4 R3
|
||||
0x7001FFEE, // 0018 JMP #0008
|
||||
0x58040002, // 0019 LDCONST R1 K2
|
||||
0xAC040200, // 001A CATCH R1 1 0
|
||||
0xB0080000, // 001B RAISE 2 R0 R0
|
||||
0x80040000, // 001C RET 1 R0
|
||||
})
|
||||
)
|
||||
);
|
||||
/*******************************************************************/
|
||||
|
||||
|
||||
/********************************************************************
|
||||
** Solidified function: inspect
|
||||
********************************************************************/
|
||||
be_local_closure(matter_inspect, /* name */
|
||||
be_nested_proto(
|
||||
16, /* nstack */
|
||||
1, /* argc */
|
||||
0, /* varg */
|
||||
0, /* has upvals */
|
||||
NULL, /* no upvals */
|
||||
0, /* has sup protos */
|
||||
NULL, /* no sub protos */
|
||||
1, /* has constants */
|
||||
( &(const bvalue[17]) { /* constants */
|
||||
/* K0 */ be_nested_str_weak(string),
|
||||
/* K1 */ be_nested_str_weak(introspect),
|
||||
/* K2 */ be_nested_str_weak(members),
|
||||
/* K3 */ be_nested_str_weak(get),
|
||||
/* K4 */ be_nested_str_weak(function),
|
||||
/* K5 */ be_nested_str_weak(push),
|
||||
/* K6 */ be_nested_str_weak(stop_iteration),
|
||||
/* K7 */ be_nested_str_weak(matter),
|
||||
/* K8 */ be_nested_str_weak(sort),
|
||||
/* K9 */ be_nested_str_weak(format),
|
||||
/* K10 */ be_nested_str_weak(_X27_X25s_X27_X3A_X20_X25s),
|
||||
/* K11 */ be_nested_str_weak(_X7B),
|
||||
/* K12 */ be_nested_str_weak(concat),
|
||||
/* K13 */ be_nested_str_weak(_X2C_X20),
|
||||
/* K14 */ be_nested_str_weak(_X7D),
|
||||
/* K15 */ be_nested_str_weak(Exception_X3A),
|
||||
/* K16 */ be_nested_str_weak(_X7C),
|
||||
}),
|
||||
be_str_weak(inspect),
|
||||
&be_const_str_solidified,
|
||||
( &(const binstruction[85]) { /* code */
|
||||
0xA8020044, // 0000 EXBLK 0 #0046
|
||||
0xA4060000, // 0001 IMPORT R1 K0
|
||||
0xA40A0200, // 0002 IMPORT R2 K1
|
||||
0x600C0012, // 0003 GETGBL R3 G18
|
||||
0x7C0C0000, // 0004 CALL R3 0
|
||||
0x60100010, // 0005 GETGBL R4 G16
|
||||
0x8C140502, // 0006 GETMET R5 R2 K2
|
||||
0x5C1C0000, // 0007 MOVE R7 R0
|
||||
0x7C140400, // 0008 CALL R5 2
|
||||
0x7C100200, // 0009 CALL R4 1
|
||||
0xA802000E, // 000A EXBLK 0 #001A
|
||||
0x5C140800, // 000B MOVE R5 R4
|
||||
0x7C140000, // 000C CALL R5 0
|
||||
0x8C180503, // 000D GETMET R6 R2 K3
|
||||
0x5C200000, // 000E MOVE R8 R0
|
||||
0x5C240A00, // 000F MOVE R9 R5
|
||||
0x7C180600, // 0010 CALL R6 3
|
||||
0x601C0004, // 0011 GETGBL R7 G4
|
||||
0x5C200C00, // 0012 MOVE R8 R6
|
||||
0x7C1C0200, // 0013 CALL R7 1
|
||||
0x201C0F04, // 0014 NE R7 R7 K4
|
||||
0x781E0002, // 0015 JMPF R7 #0019
|
||||
0x8C1C0705, // 0016 GETMET R7 R3 K5
|
||||
0x5C240A00, // 0017 MOVE R9 R5
|
||||
0x7C1C0400, // 0018 CALL R7 2
|
||||
0x7001FFF0, // 0019 JMP #000B
|
||||
0x58100006, // 001A LDCONST R4 K6
|
||||
0xAC100200, // 001B CATCH R4 1 0
|
||||
0xB0080000, // 001C RAISE 2 R0 R0
|
||||
0xB8120E00, // 001D GETNGBL R4 K7
|
||||
0x8C100908, // 001E GETMET R4 R4 K8
|
||||
0x5C180600, // 001F MOVE R6 R3
|
||||
0x7C100400, // 0020 CALL R4 2
|
||||
0x5C0C0800, // 0021 MOVE R3 R4
|
||||
0x60100012, // 0022 GETGBL R4 G18
|
||||
0x7C100000, // 0023 CALL R4 0
|
||||
0x60140010, // 0024 GETGBL R5 G16
|
||||
0x5C180600, // 0025 MOVE R6 R3
|
||||
0x7C140200, // 0026 CALL R5 1
|
||||
0xA8020011, // 0027 EXBLK 0 #003A
|
||||
0x5C180A00, // 0028 MOVE R6 R5
|
||||
0x7C180000, // 0029 CALL R6 0
|
||||
0x8C1C0503, // 002A GETMET R7 R2 K3
|
||||
0x5C240000, // 002B MOVE R9 R0
|
||||
0x5C280C00, // 002C MOVE R10 R6
|
||||
0x7C1C0600, // 002D CALL R7 3
|
||||
0x8C200905, // 002E GETMET R8 R4 K5
|
||||
0x8C280309, // 002F GETMET R10 R1 K9
|
||||
0x5830000A, // 0030 LDCONST R12 K10
|
||||
0x60340008, // 0031 GETGBL R13 G8
|
||||
0x5C380C00, // 0032 MOVE R14 R6
|
||||
0x7C340200, // 0033 CALL R13 1
|
||||
0x60380008, // 0034 GETGBL R14 G8
|
||||
0x5C3C0E00, // 0035 MOVE R15 R7
|
||||
0x7C380200, // 0036 CALL R14 1
|
||||
0x7C280800, // 0037 CALL R10 4
|
||||
0x7C200400, // 0038 CALL R8 2
|
||||
0x7001FFED, // 0039 JMP #0028
|
||||
0x58140006, // 003A LDCONST R5 K6
|
||||
0xAC140200, // 003B CATCH R5 1 0
|
||||
0xB0080000, // 003C RAISE 2 R0 R0
|
||||
0x8C14090C, // 003D GETMET R5 R4 K12
|
||||
0x581C000D, // 003E LDCONST R7 K13
|
||||
0x7C140400, // 003F CALL R5 2
|
||||
0x00161605, // 0040 ADD R5 K11 R5
|
||||
0x00140B0E, // 0041 ADD R5 R5 K14
|
||||
0xA8040001, // 0042 EXBLK 1 1
|
||||
0x80040A00, // 0043 RET 1 R5
|
||||
0xA8040001, // 0044 EXBLK 1 1
|
||||
0x7002000D, // 0045 JMP #0054
|
||||
0xAC040002, // 0046 CATCH R1 0 2
|
||||
0x7002000A, // 0047 JMP #0053
|
||||
0x600C0008, // 0048 GETGBL R3 G8
|
||||
0x5C100200, // 0049 MOVE R4 R1
|
||||
0x7C0C0200, // 004A CALL R3 1
|
||||
0x000E1E03, // 004B ADD R3 K15 R3
|
||||
0x000C0710, // 004C ADD R3 R3 K16
|
||||
0x60100008, // 004D GETGBL R4 G8
|
||||
0x5C140400, // 004E MOVE R5 R2
|
||||
0x7C100200, // 004F CALL R4 1
|
||||
0x000C0604, // 0050 ADD R3 R3 R4
|
||||
0x80040600, // 0051 RET 1 R3
|
||||
0x70020000, // 0052 JMP #0054
|
||||
0xB0080000, // 0053 RAISE 2 R0 R0
|
||||
0x80000000, // 0054 RET 0
|
||||
})
|
||||
)
|
||||
);
|
||||
/*******************************************************************/
|
||||
|
||||
/********************************************************************/
|
||||
/* End of solidification */
|
@ -0,0 +1,7 @@
|
||||
/* Solidification of matter.h */
|
||||
/********************************************************************\
|
||||
* Generated code, don't edit *
|
||||
\********************************************************************/
|
||||
#include "be_constobj.h"
|
||||
/********************************************************************/
|
||||
/* End of solidification */
|
@ -14,10 +14,11 @@ import sys
|
||||
sys.path().push('src/embedded') # allow to import from src/embedded
|
||||
|
||||
# globals that need to exist to make compilation succeed
|
||||
var globs = "path,ctypes_bytes_dyn,tasmota,ccronexpr,gpio,light,webclient,load,MD5,lv,light_state,"
|
||||
var globs = "path,ctypes_bytes_dyn,tasmota,ccronexpr,gpio,light,webclient,load,MD5,lv,light_state,udp,"
|
||||
"lv_clock,lv_clock_icon,lv_signal_arcs,lv_signal_bars,lv_wifi_arcs_icon,lv_wifi_arcs,"
|
||||
"lv_wifi_bars_icon,lv_wifi_bars,"
|
||||
"_lvgl"
|
||||
"_lvgl,"
|
||||
"int64"
|
||||
|
||||
for g:string.split(globs, ",")
|
||||
global.(g) = nil
|
||||
|
@ -138,7 +138,7 @@ autoconf_module.init = def (m)
|
||||
# ####################################################################################################
|
||||
# Init web handlers
|
||||
# ####################################################################################################
|
||||
# Displays a "Autocong" button on the configuration page
|
||||
# Displays a "Autoconf" button on the configuration page
|
||||
def web_add_config_button()
|
||||
import webserver
|
||||
webserver.content_send("<p><form id=ac action='ac' style='display: block;' method='get'><button>Auto-configuration</button></form></p>")
|
||||
|
@ -16,6 +16,6 @@ for filePath in fileList:
|
||||
# print("Deleting file : ", filePath)
|
||||
except:
|
||||
print("Error while deleting file : ", filePath)
|
||||
cmd = (env["PYTHONEXE"],join("tools","coc","coc"),"-o","generate","src","default",join("..","berry_tasmota","src"),join("..","berry_tasmota","src","solidify"),join("..","berry_mapping","src"),join("..","berry_int64","src"),join("..","..","libesp32_lvgl","lv_binding_berry","src"),join("..","..","libesp32_lvgl","lv_binding_berry","src","solidify"),join("..","..","libesp32_lvgl","lv_binding_berry","generate"),"-c",join("default","berry_conf.h"))
|
||||
cmd = (env["PYTHONEXE"],join("tools","coc","coc"),"-o","generate","src","default",join("..","berry_tasmota","src"),join("..","berry_matter","src","solidify"),join("..","berry_matter","src"),join("..","berry_tasmota","src","solidify"),join("..","berry_mapping","src"),join("..","berry_int64","src"),join("..","..","libesp32_lvgl","lv_binding_berry","src"),join("..","..","libesp32_lvgl","lv_binding_berry","src","solidify"),join("..","..","libesp32_lvgl","lv_binding_berry","generate"),"-c",join("default","berry_conf.h"))
|
||||
returncode = subprocess.call(cmd, shell=False)
|
||||
os.chdir(CURRENT_DIR)
|
||||
|
@ -88,6 +88,11 @@ const char berry_prog[] =
|
||||
"import debug "
|
||||
"import solidify "
|
||||
#endif
|
||||
|
||||
#ifdef USE_MATTER_DEVICE
|
||||
"import matter "
|
||||
"global.matter_device = matter.Device() "
|
||||
#endif
|
||||
;
|
||||
|
||||
#endif // USE_BERRY
|
||||
|
@ -24,6 +24,9 @@
|
||||
|
||||
#include <berry.h>
|
||||
#include "berry_tasmota.h"
|
||||
#ifdef USE_MATTER
|
||||
#include "berry_matter.h"
|
||||
#endif
|
||||
#include "be_vm.h"
|
||||
#include "ZipReadFS.h"
|
||||
#include "ccronexpr.h"
|
||||
|
Loading…
x
Reference in New Issue
Block a user