@riddix/hamh 2.0.34 → 2.0.35
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +21 -11
- package/dist/backend/cli.js +777 -422
- package/dist/backend/cli.js.map +4 -4
- package/dist/frontend/assets/index-CpNOwL9y.js +499 -0
- package/dist/frontend/index.html +1 -1
- package/package.json +4 -4
- package/dist/frontend/assets/index-ranhrLWH.js +0 -499
package/dist/backend/cli.js
CHANGED
|
@@ -9825,12 +9825,12 @@ var init_StandardCrypto = __esm({
|
|
|
9825
9825
|
implementationName = "JS";
|
|
9826
9826
|
#crypto;
|
|
9827
9827
|
#subtle;
|
|
9828
|
-
constructor(
|
|
9829
|
-
const { subtle } =
|
|
9830
|
-
assertInterface("crypto",
|
|
9828
|
+
constructor(crypto8 = globalThis.crypto) {
|
|
9829
|
+
const { subtle } = crypto8;
|
|
9830
|
+
assertInterface("crypto", crypto8, requiredCryptoMethods);
|
|
9831
9831
|
assertInterface("crypto.subtle", subtle, requiredSubtleMethods);
|
|
9832
9832
|
super();
|
|
9833
|
-
this.#crypto =
|
|
9833
|
+
this.#crypto = crypto8;
|
|
9834
9834
|
this.#subtle = subtle;
|
|
9835
9835
|
}
|
|
9836
9836
|
get subtle() {
|
|
@@ -10013,9 +10013,9 @@ var init_StandardCrypto = __esm({
|
|
|
10013
10013
|
}
|
|
10014
10014
|
};
|
|
10015
10015
|
if ("crypto" in globalThis && globalThis.crypto?.subtle) {
|
|
10016
|
-
const
|
|
10017
|
-
Environment.default.set(Entropy,
|
|
10018
|
-
Environment.default.set(Crypto,
|
|
10016
|
+
const crypto8 = new StandardCrypto();
|
|
10017
|
+
Environment.default.set(Entropy, crypto8);
|
|
10018
|
+
Environment.default.set(Crypto, crypto8);
|
|
10019
10019
|
}
|
|
10020
10020
|
}
|
|
10021
10021
|
});
|
|
@@ -10025,9 +10025,9 @@ function MockCrypto(index = 128, implementation = StandardCrypto) {
|
|
|
10025
10025
|
if (index < 0 || index > 255) {
|
|
10026
10026
|
throw new ImplementationError(`Index for stable crypto must be 0-255`);
|
|
10027
10027
|
}
|
|
10028
|
-
const
|
|
10029
|
-
const { randomBytes: randomBytes2, createKeyPair } =
|
|
10030
|
-
Object.defineProperties(
|
|
10028
|
+
const crypto8 = new implementation();
|
|
10029
|
+
const { randomBytes: randomBytes2, createKeyPair } = crypto8;
|
|
10030
|
+
Object.defineProperties(crypto8, {
|
|
10031
10031
|
index: {
|
|
10032
10032
|
get() {
|
|
10033
10033
|
return index;
|
|
@@ -10038,12 +10038,12 @@ function MockCrypto(index = 128, implementation = StandardCrypto) {
|
|
|
10038
10038
|
},
|
|
10039
10039
|
entropic: {
|
|
10040
10040
|
get() {
|
|
10041
|
-
return
|
|
10041
|
+
return crypto8.randomBytes === randomBytes2;
|
|
10042
10042
|
},
|
|
10043
10043
|
set(entropic) {
|
|
10044
10044
|
if (entropic) {
|
|
10045
|
-
|
|
10046
|
-
|
|
10045
|
+
crypto8.randomBytes = randomBytes2;
|
|
10046
|
+
crypto8.createKeyPair = createKeyPair;
|
|
10047
10047
|
} else {
|
|
10048
10048
|
disableEntropy();
|
|
10049
10049
|
}
|
|
@@ -10051,15 +10051,15 @@ function MockCrypto(index = 128, implementation = StandardCrypto) {
|
|
|
10051
10051
|
}
|
|
10052
10052
|
});
|
|
10053
10053
|
disableEntropy();
|
|
10054
|
-
return
|
|
10054
|
+
return crypto8;
|
|
10055
10055
|
function disableEntropy() {
|
|
10056
|
-
|
|
10056
|
+
crypto8.randomBytes = function getRandomDataNONENTROPIC(length) {
|
|
10057
10057
|
const result = new Uint8Array(length);
|
|
10058
10058
|
result.fill(index);
|
|
10059
10059
|
return result;
|
|
10060
10060
|
};
|
|
10061
|
-
|
|
10062
|
-
const privateBits = ec.mapHashToField(Bytes.of(
|
|
10061
|
+
crypto8.createKeyPair = function getRandomDataNONENTROPIC() {
|
|
10062
|
+
const privateBits = ec.mapHashToField(Bytes.of(crypto8.randomBytes(48)), ec.p256.Point.CURVE().n);
|
|
10063
10063
|
return Key({
|
|
10064
10064
|
kty: KeyType.EC,
|
|
10065
10065
|
crv: CurveType.p256,
|
|
@@ -10092,9 +10092,9 @@ var init_NodeJsStyleCrypto = __esm({
|
|
|
10092
10092
|
NodeJsStyleCrypto = class extends Crypto {
|
|
10093
10093
|
implementationName = "Node.js";
|
|
10094
10094
|
#crypto;
|
|
10095
|
-
constructor(
|
|
10095
|
+
constructor(crypto8) {
|
|
10096
10096
|
super();
|
|
10097
|
-
this.#crypto =
|
|
10097
|
+
this.#crypto = crypto8;
|
|
10098
10098
|
}
|
|
10099
10099
|
encrypt(key, data, nonce, aad) {
|
|
10100
10100
|
const cipher = this.#crypto.createCipheriv(CRYPTO_ENCRYPT_ALGORITHM, Bytes.of(key), Bytes.of(nonce), {
|
|
@@ -10368,29 +10368,29 @@ var init_Spake2p = __esm({
|
|
|
10368
10368
|
#context;
|
|
10369
10369
|
#random;
|
|
10370
10370
|
#w0;
|
|
10371
|
-
static async computeW0W1(
|
|
10371
|
+
static async computeW0W1(crypto8, { iterations, salt }, pin) {
|
|
10372
10372
|
const pinWriter = new DataWriter(Endian.Little);
|
|
10373
10373
|
pinWriter.writeUInt32(pin);
|
|
10374
10374
|
const ws2 = Bytes.of(
|
|
10375
|
-
await
|
|
10375
|
+
await crypto8.createPbkdf2Key(pinWriter.toByteArray(), salt, iterations, CRYPTO_W_SIZE_BYTES * 2)
|
|
10376
10376
|
);
|
|
10377
10377
|
const curve = Point2.CURVE();
|
|
10378
10378
|
const w0 = mod2(bytesToNumberBE(ws2.slice(0, 40)), curve.n);
|
|
10379
10379
|
const w1 = mod2(bytesToNumberBE(ws2.slice(40, 80)), curve.n);
|
|
10380
10380
|
return { w0, w1 };
|
|
10381
10381
|
}
|
|
10382
|
-
static async computeW0L(
|
|
10383
|
-
const { w0, w1 } = await this.computeW0W1(
|
|
10382
|
+
static async computeW0L(crypto8, pbkdfParameters, pin) {
|
|
10383
|
+
const { w0, w1 } = await this.computeW0W1(crypto8, pbkdfParameters, pin);
|
|
10384
10384
|
const L = Point2.BASE.multiply(w1).toBytes(false);
|
|
10385
10385
|
return { w0, L };
|
|
10386
10386
|
}
|
|
10387
|
-
static create(
|
|
10387
|
+
static create(crypto8, context, w0) {
|
|
10388
10388
|
const curve = Point2.CURVE();
|
|
10389
|
-
const random =
|
|
10390
|
-
return new _Spake2p(
|
|
10389
|
+
const random = crypto8.randomBigInt(32, curve.p);
|
|
10390
|
+
return new _Spake2p(crypto8, context, random, w0);
|
|
10391
10391
|
}
|
|
10392
|
-
constructor(
|
|
10393
|
-
this.#crypto =
|
|
10392
|
+
constructor(crypto8, context, random, w0) {
|
|
10393
|
+
this.#crypto = crypto8;
|
|
10394
10394
|
this.#context = context;
|
|
10395
10395
|
this.#random = random;
|
|
10396
10396
|
this.#w0 = w0;
|
|
@@ -10521,10 +10521,10 @@ var init_X509 = __esm({
|
|
|
10521
10521
|
init_Pem();
|
|
10522
10522
|
init_X962();
|
|
10523
10523
|
((X5092) => {
|
|
10524
|
-
async function sign(
|
|
10524
|
+
async function sign(crypto8, key, cert) {
|
|
10525
10525
|
return {
|
|
10526
10526
|
...cert,
|
|
10527
|
-
signature: (await
|
|
10527
|
+
signature: (await crypto8.signEcdsa(key, certificateToDer(cert))).der
|
|
10528
10528
|
};
|
|
10529
10529
|
}
|
|
10530
10530
|
X5092.sign = sign;
|
|
@@ -46460,9 +46460,9 @@ var init_NodeId = __esm({
|
|
|
46460
46460
|
return hex.fixed(nodeId3, 16);
|
|
46461
46461
|
}
|
|
46462
46462
|
NodeId2.strOf = strOf;
|
|
46463
|
-
NodeId2.randomOperationalNodeId = (
|
|
46463
|
+
NodeId2.randomOperationalNodeId = (crypto8) => {
|
|
46464
46464
|
while (true) {
|
|
46465
|
-
const randomBigInt =
|
|
46465
|
+
const randomBigInt = crypto8.randomBigInt(8);
|
|
46466
46466
|
if (randomBigInt >= OPERATIONAL_NODE_MIN && randomBigInt <= OPERATIONAL_NODE_MAX) {
|
|
46467
46467
|
return NodeId2(randomBigInt);
|
|
46468
46468
|
}
|
|
@@ -88338,11 +88338,11 @@ var init_GlobalFabricId = __esm({
|
|
|
88338
88338
|
return hex.fixed(id, 16);
|
|
88339
88339
|
}
|
|
88340
88340
|
GlobalFabricId2.strOf = strOf;
|
|
88341
|
-
async function compute(
|
|
88341
|
+
async function compute(crypto8, id, caKey) {
|
|
88342
88342
|
const saltWriter = new DataWriter();
|
|
88343
88343
|
saltWriter.writeUInt64(id);
|
|
88344
88344
|
return GlobalFabricId2(
|
|
88345
|
-
await
|
|
88345
|
+
await crypto8.createHkdfKey(
|
|
88346
88346
|
Bytes.of(caKey).slice(1),
|
|
88347
88347
|
saltWriter.toByteArray(),
|
|
88348
88348
|
COMPRESSED_FABRIC_ID_INFO,
|
|
@@ -90621,8 +90621,8 @@ var init_Certificate = __esm({
|
|
|
90621
90621
|
* Sign the certificate using the provided crypto and key.
|
|
90622
90622
|
* It throws a CertificateError if the certificate is already signed.
|
|
90623
90623
|
*/
|
|
90624
|
-
async sign(
|
|
90625
|
-
this.signature = await
|
|
90624
|
+
async sign(crypto8, key) {
|
|
90625
|
+
this.signature = await crypto8.signEcdsa(key, this.asUnsignedDer());
|
|
90626
90626
|
}
|
|
90627
90627
|
/**
|
|
90628
90628
|
* Serialize as signed DER.
|
|
@@ -90684,7 +90684,7 @@ var init_Certificate = __esm({
|
|
|
90684
90684
|
}
|
|
90685
90685
|
};
|
|
90686
90686
|
((Certificate2) => {
|
|
90687
|
-
async function createCertificateSigningRequest(
|
|
90687
|
+
async function createCertificateSigningRequest(crypto8, key) {
|
|
90688
90688
|
const request = {
|
|
90689
90689
|
version: 0,
|
|
90690
90690
|
subject: { organization: X520.OrganisationName("CSR") },
|
|
@@ -90694,7 +90694,7 @@ var init_Certificate = __esm({
|
|
|
90694
90694
|
return DerCodec.encode({
|
|
90695
90695
|
request,
|
|
90696
90696
|
signAlgorithm: X962.EcdsaWithSHA256,
|
|
90697
|
-
signature: DerBitString((await
|
|
90697
|
+
signature: DerBitString((await crypto8.signEcdsa(key, DerCodec.encode(request))).der)
|
|
90698
90698
|
});
|
|
90699
90699
|
}
|
|
90700
90700
|
Certificate2.createCertificateSigningRequest = createCertificateSigningRequest;
|
|
@@ -90973,7 +90973,7 @@ var init_Certificate = __esm({
|
|
|
90973
90973
|
};
|
|
90974
90974
|
}
|
|
90975
90975
|
Certificate2.parseAsn1Certificate = parseAsn1Certificate;
|
|
90976
|
-
async function getPublicKeyFromCsr(
|
|
90976
|
+
async function getPublicKeyFromCsr(crypto8, encodedCsr) {
|
|
90977
90977
|
const { _elements: rootElements } = DerCodec.decode(encodedCsr);
|
|
90978
90978
|
if (rootElements?.length !== 3) {
|
|
90979
90979
|
throw new CertificateError("Invalid CSR data");
|
|
@@ -91011,7 +91011,7 @@ var init_Certificate = __esm({
|
|
|
91011
91011
|
if (signatureAlgorithmBytes === void 0 || !Bytes.areEqual(X962.EcdsaWithSHA256._objectId._bytes, signatureAlgorithmBytes)) {
|
|
91012
91012
|
throw new CertificateError("Unsupported signature algorithm in CSR");
|
|
91013
91013
|
}
|
|
91014
|
-
await
|
|
91014
|
+
await crypto8.verifyEcdsa(
|
|
91015
91015
|
PublicKey(publicKey),
|
|
91016
91016
|
DerCodec.encode(requestNode),
|
|
91017
91017
|
new EcdsaSignature(signatureNode._bytes, "der")
|
|
@@ -91240,7 +91240,7 @@ var init_Icac = __esm({
|
|
|
91240
91240
|
* Verify requirements a Matter Intermediate CA certificate must fulfill.
|
|
91241
91241
|
* Rules for this are listed in @see {@link MatterSpecification.v12.Core} §6.5.x
|
|
91242
91242
|
*/
|
|
91243
|
-
async verify(
|
|
91243
|
+
async verify(crypto8, root) {
|
|
91244
91244
|
this.generalVerify();
|
|
91245
91245
|
const {
|
|
91246
91246
|
subject,
|
|
@@ -91316,7 +91316,7 @@ var init_Icac = __esm({
|
|
|
91316
91316
|
`Ica certificate authorityKeyIdentifier must be equal to root cert subjectKeyIdentifier.`
|
|
91317
91317
|
);
|
|
91318
91318
|
}
|
|
91319
|
-
await
|
|
91319
|
+
await crypto8.verifyEcdsa(PublicKey(root.cert.ellipticCurvePublicKey), this.asUnsignedDer(), this.signature);
|
|
91320
91320
|
}
|
|
91321
91321
|
};
|
|
91322
91322
|
}
|
|
@@ -91367,7 +91367,7 @@ var init_Noc = __esm({
|
|
|
91367
91367
|
* Verify requirements a Matter Node Operational certificate must fulfill.
|
|
91368
91368
|
* Rules for this are listed in @see {@link MatterSpecification.v12.Core} §6.5.x
|
|
91369
91369
|
*/
|
|
91370
|
-
async verify(
|
|
91370
|
+
async verify(crypto8, root, ica) {
|
|
91371
91371
|
this.generalVerify();
|
|
91372
91372
|
const {
|
|
91373
91373
|
subject,
|
|
@@ -91452,7 +91452,7 @@ var init_Noc = __esm({
|
|
|
91452
91452
|
`Noc certificate authorityKeyIdentifier must be equal to Root/Ica subjectKeyIdentifier.`
|
|
91453
91453
|
);
|
|
91454
91454
|
}
|
|
91455
|
-
await
|
|
91455
|
+
await crypto8.verifyEcdsa(PublicKey(issuer.cert.ellipticCurvePublicKey), this.asUnsignedDer(), this.signature);
|
|
91456
91456
|
}
|
|
91457
91457
|
};
|
|
91458
91458
|
}
|
|
@@ -93037,10 +93037,10 @@ var init_MessageCounter = __esm({
|
|
|
93037
93037
|
* counter is not allowed to rollover and the callback is called before a rollover would happen. Optionally provide
|
|
93038
93038
|
* a number of messages before the rollover callback is called (Default 1000).
|
|
93039
93039
|
*/
|
|
93040
|
-
constructor(
|
|
93040
|
+
constructor(crypto8, onRollover, rolloverInfoDifference = ROLLOVER_INFO_DIFFERENCE) {
|
|
93041
93041
|
this.onRollover = onRollover;
|
|
93042
93042
|
this.rolloverInfoDifference = rolloverInfoDifference;
|
|
93043
|
-
this.messageCounter = (
|
|
93043
|
+
this.messageCounter = (crypto8.randomUint32 >>> 4) + 1;
|
|
93044
93044
|
}
|
|
93045
93045
|
messageCounter;
|
|
93046
93046
|
async getIncrementedCounter() {
|
|
@@ -93058,8 +93058,8 @@ var init_MessageCounter = __esm({
|
|
|
93058
93058
|
}
|
|
93059
93059
|
};
|
|
93060
93060
|
PersistedMessageCounter = class _PersistedMessageCounter extends MessageCounter {
|
|
93061
|
-
constructor(
|
|
93062
|
-
super(
|
|
93061
|
+
constructor(crypto8, storageContext, storageKey, aboutToRolloverCallback, rolloverInfoDifference = ROLLOVER_INFO_DIFFERENCE) {
|
|
93062
|
+
super(crypto8, aboutToRolloverCallback, rolloverInfoDifference);
|
|
93063
93063
|
this.storageContext = storageContext;
|
|
93064
93064
|
this.storageKey = storageKey;
|
|
93065
93065
|
this.#construction = Construction(this, async () => {
|
|
@@ -93078,10 +93078,10 @@ var init_MessageCounter = __esm({
|
|
|
93078
93078
|
get construction() {
|
|
93079
93079
|
return this.#construction;
|
|
93080
93080
|
}
|
|
93081
|
-
static async create(
|
|
93081
|
+
static async create(crypto8, storageContext, storageKey, aboutToRolloverCallback, rolloverInfoDifference = ROLLOVER_INFO_DIFFERENCE) {
|
|
93082
93082
|
return asyncNew(
|
|
93083
93083
|
_PersistedMessageCounter,
|
|
93084
|
-
|
|
93084
|
+
crypto8,
|
|
93085
93085
|
storageContext,
|
|
93086
93086
|
storageKey,
|
|
93087
93087
|
aboutToRolloverCallback,
|
|
@@ -93994,7 +93994,7 @@ var init_NodeSession = __esm({
|
|
|
93994
93994
|
}
|
|
93995
93995
|
constructor(config10) {
|
|
93996
93996
|
const {
|
|
93997
|
-
crypto:
|
|
93997
|
+
crypto: crypto8,
|
|
93998
93998
|
manager,
|
|
93999
93999
|
id,
|
|
94000
94000
|
fabric,
|
|
@@ -94012,14 +94012,14 @@ var init_NodeSession = __esm({
|
|
|
94012
94012
|
setActiveTimestamp: true,
|
|
94013
94013
|
// We always set the active timestamp for Secure sessions
|
|
94014
94014
|
// Can be changed to a PersistedMessageCounter if we implement session storage
|
|
94015
|
-
messageCounter: new MessageCounter(
|
|
94015
|
+
messageCounter: new MessageCounter(crypto8, async () => {
|
|
94016
94016
|
await this.initiateClose(async () => {
|
|
94017
94017
|
await this.closeSubscriptions(true);
|
|
94018
94018
|
});
|
|
94019
94019
|
}),
|
|
94020
94020
|
messageReceptionState: new MessageReceptionStateEncryptedWithoutRollover(0)
|
|
94021
94021
|
});
|
|
94022
|
-
this.#crypto =
|
|
94022
|
+
this.#crypto = crypto8;
|
|
94023
94023
|
this.#id = id;
|
|
94024
94024
|
this.#fabric = fabric;
|
|
94025
94025
|
this.#peerNodeId = peerNodeId;
|
|
@@ -94468,22 +94468,22 @@ var init_CaseClient = __esm({
|
|
|
94468
94468
|
}
|
|
94469
94469
|
}
|
|
94470
94470
|
async #doPair(messenger, exchange, fabric, peerNodeId, caseAuthenticatedTags) {
|
|
94471
|
-
const { crypto:
|
|
94472
|
-
const initiatorRandom =
|
|
94471
|
+
const { crypto: crypto8 } = fabric;
|
|
94472
|
+
const initiatorRandom = crypto8.randomBytes(32);
|
|
94473
94473
|
const initiatorSessionId = await this.#sessions.getNextAvailableSessionId();
|
|
94474
94474
|
const { operationalIdentityProtectionKey, operationalCert: localNoc, intermediateCACert: localIcac } = fabric;
|
|
94475
|
-
const localKey = await
|
|
94475
|
+
const localKey = await crypto8.createKeyPair();
|
|
94476
94476
|
let sigma1Bytes;
|
|
94477
94477
|
let resumed = false;
|
|
94478
94478
|
let resumptionRecord = this.#sessions.findResumptionRecordByAddress(fabric.addressOf(peerNodeId));
|
|
94479
94479
|
if (resumptionRecord !== void 0) {
|
|
94480
94480
|
const { sharedSecret, resumptionId } = resumptionRecord;
|
|
94481
|
-
const resumeKey = await
|
|
94481
|
+
const resumeKey = await crypto8.createHkdfKey(
|
|
94482
94482
|
sharedSecret,
|
|
94483
94483
|
Bytes.concat(initiatorRandom, resumptionId),
|
|
94484
94484
|
KDFSR1_KEY_INFO
|
|
94485
94485
|
);
|
|
94486
|
-
const initiatorResumeMic =
|
|
94486
|
+
const initiatorResumeMic = crypto8.encrypt(resumeKey, new Uint8Array(0), RESUME1_MIC_NONCE);
|
|
94487
94487
|
sigma1Bytes = await messenger.sendSigma1({
|
|
94488
94488
|
initiatorSessionId,
|
|
94489
94489
|
destinationId: await fabric.currentDestinationIdFor(peerNodeId, initiatorRandom),
|
|
@@ -94518,8 +94518,8 @@ var init_CaseClient = __esm({
|
|
|
94518
94518
|
...resumptionSessionParams ?? {}
|
|
94519
94519
|
};
|
|
94520
94520
|
const resumeSalt = Bytes.concat(initiatorRandom, resumptionId);
|
|
94521
|
-
const resumeKey = await
|
|
94522
|
-
|
|
94521
|
+
const resumeKey = await crypto8.createHkdfKey(sharedSecret, resumeSalt, KDFSR2_KEY_INFO);
|
|
94522
|
+
crypto8.decrypt(resumeKey, resumeMic, RESUME2_MIC_NONCE);
|
|
94523
94523
|
const secureSessionSalt = Bytes.concat(initiatorRandom, resumptionRecord.resumptionId);
|
|
94524
94524
|
secureSession = await this.#sessions.createSecureSession({
|
|
94525
94525
|
channel: exchange.channel.channel,
|
|
@@ -94563,15 +94563,15 @@ var init_CaseClient = __esm({
|
|
|
94563
94563
|
...exchange.session.parameters,
|
|
94564
94564
|
...responderSessionParams ?? {}
|
|
94565
94565
|
};
|
|
94566
|
-
const sharedSecret = await
|
|
94566
|
+
const sharedSecret = await crypto8.generateDhSecret(localKey, PublicKey(peerKey));
|
|
94567
94567
|
const sigma2Salt = Bytes.concat(
|
|
94568
94568
|
operationalIdentityProtectionKey,
|
|
94569
94569
|
responderRandom,
|
|
94570
94570
|
peerKey,
|
|
94571
|
-
await
|
|
94571
|
+
await crypto8.computeHash(sigma1Bytes)
|
|
94572
94572
|
);
|
|
94573
|
-
const sigma2Key = await
|
|
94574
|
-
const peerEncryptedData =
|
|
94573
|
+
const sigma2Key = await crypto8.createHkdfKey(sharedSecret, sigma2Salt, KDFSR2_INFO);
|
|
94574
|
+
const peerEncryptedData = crypto8.decrypt(sigma2Key, peerEncrypted, TBE_DATA2_NONCE);
|
|
94575
94575
|
const {
|
|
94576
94576
|
responderNoc: peerNoc,
|
|
94577
94577
|
responderIcac: peerIcac,
|
|
@@ -94588,7 +94588,7 @@ var init_CaseClient = __esm({
|
|
|
94588
94588
|
ellipticCurvePublicKey: peerPublicKey,
|
|
94589
94589
|
subject: { fabricId: peerFabricIdNOCert, nodeId: peerNodeIdNOCert }
|
|
94590
94590
|
} = Noc.fromTlv(peerNoc).cert;
|
|
94591
|
-
await
|
|
94591
|
+
await crypto8.verifyEcdsa(PublicKey(peerPublicKey), peerSignatureData, new EcdsaSignature(peerSignature));
|
|
94592
94592
|
if (peerNodeIdNOCert !== peerNodeId) {
|
|
94593
94593
|
throw new UnexpectedDataError(
|
|
94594
94594
|
`The node ID in the peer certificate ${peerNodeIdNOCert} doesn't match the expected peer node ID ${peerNodeId}`
|
|
@@ -94612,9 +94612,9 @@ var init_CaseClient = __esm({
|
|
|
94612
94612
|
await fabric.verifyCredentials(peerNoc, peerIcac);
|
|
94613
94613
|
const sigma3Salt = Bytes.concat(
|
|
94614
94614
|
operationalIdentityProtectionKey,
|
|
94615
|
-
await
|
|
94615
|
+
await crypto8.computeHash([sigma1Bytes, sigma2Bytes])
|
|
94616
94616
|
);
|
|
94617
|
-
const sigma3Key = await
|
|
94617
|
+
const sigma3Key = await crypto8.createHkdfKey(sharedSecret, sigma3Salt, KDFSR3_INFO);
|
|
94618
94618
|
const signatureData = TlvSignedData.encode({
|
|
94619
94619
|
responderNoc: localNoc,
|
|
94620
94620
|
responderIcac: localIcac,
|
|
@@ -94627,13 +94627,13 @@ var init_CaseClient = __esm({
|
|
|
94627
94627
|
responderIcac: localIcac,
|
|
94628
94628
|
signature: signature.bytes
|
|
94629
94629
|
});
|
|
94630
|
-
const encrypted =
|
|
94630
|
+
const encrypted = crypto8.encrypt(sigma3Key, encryptedData, TBE_DATA3_NONCE);
|
|
94631
94631
|
const sigma3Bytes = await messenger.sendSigma3({ encrypted });
|
|
94632
94632
|
await messenger.waitForSuccess("Sigma3-Success");
|
|
94633
94633
|
const sessionCaseAuthenticatedTags = caseAuthenticatedTags ?? resumptionRecord?.caseAuthenticatedTags;
|
|
94634
94634
|
const secureSessionSalt = Bytes.concat(
|
|
94635
94635
|
operationalIdentityProtectionKey,
|
|
94636
|
-
await
|
|
94636
|
+
await crypto8.computeHash([sigma1Bytes, sigma2Bytes, sigma3Bytes])
|
|
94637
94637
|
);
|
|
94638
94638
|
secureSession = await this.#sessions.createSecureSession({
|
|
94639
94639
|
channel: exchange.channel.channel,
|
|
@@ -94711,7 +94711,7 @@ var init_Rcac = __esm({
|
|
|
94711
94711
|
* Verify requirements a Matter Root certificate must fulfill.
|
|
94712
94712
|
* Rules for this are listed in @see {@link MatterSpecification.v12.Core} §6.5.x
|
|
94713
94713
|
*/
|
|
94714
|
-
async verify(
|
|
94714
|
+
async verify(crypto8) {
|
|
94715
94715
|
this.generalVerify();
|
|
94716
94716
|
const { subject, extensions } = this.cert;
|
|
94717
94717
|
const { fabricId: fabricId3, rcacId } = subject;
|
|
@@ -94768,7 +94768,7 @@ var init_Rcac = __esm({
|
|
|
94768
94768
|
`Root certificate authorityKeyIdentifier must be equal to subjectKeyIdentifier.`
|
|
94769
94769
|
);
|
|
94770
94770
|
}
|
|
94771
|
-
await
|
|
94771
|
+
await crypto8.verifyEcdsa(PublicKey(this.cert.ellipticCurvePublicKey), this.asUnsignedDer(), this.signature);
|
|
94772
94772
|
}
|
|
94773
94773
|
};
|
|
94774
94774
|
}
|
|
@@ -94903,8 +94903,8 @@ var init_KeySets = __esm({
|
|
|
94903
94903
|
};
|
|
94904
94904
|
}
|
|
94905
94905
|
/** Calculates a group session id based on the operational group key. */
|
|
94906
|
-
async sessionIdFromKey(
|
|
94907
|
-
const groupKeyHash = await
|
|
94906
|
+
async sessionIdFromKey(crypto8, operationalGroupKey) {
|
|
94907
|
+
const groupKeyHash = await crypto8.createHkdfKey(operationalGroupKey, new Uint8Array(), GROUP_KEY_INFO, 2);
|
|
94908
94908
|
return new DataReader(groupKeyHash).readUInt16();
|
|
94909
94909
|
}
|
|
94910
94910
|
/**
|
|
@@ -94957,8 +94957,8 @@ var init_MessagingState = __esm({
|
|
|
94957
94957
|
#messageDataReceptionState = /* @__PURE__ */ new Map();
|
|
94958
94958
|
#crypto;
|
|
94959
94959
|
#storage;
|
|
94960
|
-
constructor(
|
|
94961
|
-
this.#crypto =
|
|
94960
|
+
constructor(crypto8, storage2) {
|
|
94961
|
+
this.#crypto = crypto8;
|
|
94962
94962
|
if (storage2 !== void 0) {
|
|
94963
94963
|
this.#storage = storage2;
|
|
94964
94964
|
}
|
|
@@ -95491,8 +95491,8 @@ var init_Fabric = __esm({
|
|
|
95491
95491
|
* Certain derived fields that require async crypto operations to compute must be supplied here. Use {@link create}
|
|
95492
95492
|
* to populate these fields automatically.
|
|
95493
95493
|
*/
|
|
95494
|
-
constructor(
|
|
95495
|
-
this.#crypto =
|
|
95494
|
+
constructor(crypto8, config10) {
|
|
95495
|
+
this.#crypto = crypto8;
|
|
95496
95496
|
this.fabricIndex = config10.fabricIndex;
|
|
95497
95497
|
this.fabricId = config10.fabricId;
|
|
95498
95498
|
this.nodeId = config10.nodeId;
|
|
@@ -95521,20 +95521,20 @@ var init_Fabric = __esm({
|
|
|
95521
95521
|
*
|
|
95522
95522
|
* This async creation path populates derived fields that require async crypto operations to compute.
|
|
95523
95523
|
*/
|
|
95524
|
-
static async create(
|
|
95524
|
+
static async create(crypto8, config10) {
|
|
95525
95525
|
let { globalId, operationalIdentityProtectionKey } = config10;
|
|
95526
95526
|
if (globalId === void 0) {
|
|
95527
95527
|
const caKey = config10.rootPublicKey ?? Rcac.publicKeyOfTlv(config10.rootCert);
|
|
95528
|
-
globalId = await GlobalFabricId.compute(
|
|
95528
|
+
globalId = await GlobalFabricId.compute(crypto8, config10.fabricId, caKey);
|
|
95529
95529
|
}
|
|
95530
95530
|
if (operationalIdentityProtectionKey === void 0) {
|
|
95531
|
-
operationalIdentityProtectionKey = await
|
|
95531
|
+
operationalIdentityProtectionKey = await crypto8.createHkdfKey(
|
|
95532
95532
|
config10.identityProtectionKey,
|
|
95533
95533
|
Bytes.fromBigInt(globalId, 8),
|
|
95534
95534
|
GROUP_SECURITY_INFO
|
|
95535
95535
|
);
|
|
95536
95536
|
}
|
|
95537
|
-
return new _Fabric(
|
|
95537
|
+
return new _Fabric(crypto8, {
|
|
95538
95538
|
...config10,
|
|
95539
95539
|
globalId,
|
|
95540
95540
|
operationalIdentityProtectionKey
|
|
@@ -95791,12 +95791,12 @@ var init_Fabric = __esm({
|
|
|
95791
95791
|
#vvsc;
|
|
95792
95792
|
#fabricIndex;
|
|
95793
95793
|
#label = "";
|
|
95794
|
-
constructor(
|
|
95795
|
-
this.#crypto =
|
|
95794
|
+
constructor(crypto8, key) {
|
|
95795
|
+
this.#crypto = crypto8;
|
|
95796
95796
|
this.#keyPair = key;
|
|
95797
95797
|
}
|
|
95798
|
-
static async create(
|
|
95799
|
-
return new _FabricBuilder(
|
|
95798
|
+
static async create(crypto8) {
|
|
95799
|
+
return new _FabricBuilder(crypto8, await crypto8.createKeyPair());
|
|
95800
95800
|
}
|
|
95801
95801
|
get publicKey() {
|
|
95802
95802
|
return this.#keyPair.publicKey;
|
|
@@ -95955,8 +95955,8 @@ var init_FabricManager = __esm({
|
|
|
95955
95955
|
failsafeClosed: Observable()
|
|
95956
95956
|
};
|
|
95957
95957
|
#construction;
|
|
95958
|
-
constructor(
|
|
95959
|
-
this.#crypto =
|
|
95958
|
+
constructor(crypto8, storage2) {
|
|
95959
|
+
this.#crypto = crypto8;
|
|
95960
95960
|
this.#storage = storage2;
|
|
95961
95961
|
let construct;
|
|
95962
95962
|
if (this.#storage === void 0) {
|
|
@@ -95969,7 +95969,7 @@ var init_FabricManager = __esm({
|
|
|
95969
95969
|
}
|
|
95970
95970
|
const fabrics = await this.#storage.get("fabrics", []);
|
|
95971
95971
|
for (const fabricConfig of fabrics) {
|
|
95972
|
-
this.#addNewFabric(await Fabric.create(
|
|
95972
|
+
this.#addNewFabric(await Fabric.create(crypto8, fabricConfig));
|
|
95973
95973
|
}
|
|
95974
95974
|
this.#nextFabricIndex = await this.#storage.get("nextFabricIndex", this.#nextFabricIndex);
|
|
95975
95975
|
this.#initializationDone = true;
|
|
@@ -96265,14 +96265,14 @@ var init_CaseServer = __esm({
|
|
|
96265
96265
|
return false;
|
|
96266
96266
|
}
|
|
96267
96267
|
const { sharedSecret, fabric, peerNodeId, caseAuthenticatedTags } = cx.resumptionRecord;
|
|
96268
|
-
const { crypto:
|
|
96269
|
-
const peerResumeKey = await
|
|
96268
|
+
const { crypto: crypto8 } = this.#fabrics;
|
|
96269
|
+
const peerResumeKey = await crypto8.createHkdfKey(
|
|
96270
96270
|
sharedSecret,
|
|
96271
96271
|
Bytes.concat(cx.peerRandom, cx.peerResumptionId),
|
|
96272
96272
|
KDFSR1_KEY_INFO
|
|
96273
96273
|
);
|
|
96274
96274
|
try {
|
|
96275
|
-
|
|
96275
|
+
crypto8.decrypt(peerResumeKey, cx.peerResumeMic, RESUME1_MIC_NONCE);
|
|
96276
96276
|
} catch (e) {
|
|
96277
96277
|
CryptoDecryptError.accept(e);
|
|
96278
96278
|
cx.peerResumptionId = cx.peerResumeMic = void 0;
|
|
@@ -96296,8 +96296,8 @@ var init_CaseServer = __esm({
|
|
|
96296
96296
|
// Session establishment could still fail, so add session ourselves to the manager
|
|
96297
96297
|
});
|
|
96298
96298
|
const resumeSalt = Bytes.concat(cx.peerRandom, cx.localResumptionId);
|
|
96299
|
-
const resumeKey = await
|
|
96300
|
-
const resumeMic =
|
|
96299
|
+
const resumeKey = await crypto8.createHkdfKey(sharedSecret, resumeSalt, KDFSR2_KEY_INFO);
|
|
96300
|
+
const resumeMic = crypto8.encrypt(resumeKey, new Uint8Array(0), RESUME2_MIC_NONCE);
|
|
96301
96301
|
try {
|
|
96302
96302
|
const responderSessionParams = this.#sessions.sessionParameters;
|
|
96303
96303
|
await cx.messenger.sendSigma2Resume({
|
|
@@ -96326,20 +96326,20 @@ var init_CaseServer = __esm({
|
|
|
96326
96326
|
) {
|
|
96327
96327
|
return false;
|
|
96328
96328
|
}
|
|
96329
|
-
const { crypto:
|
|
96330
|
-
const responderRandom =
|
|
96329
|
+
const { crypto: crypto8 } = this.#fabrics;
|
|
96330
|
+
const responderRandom = crypto8.randomBytes(32);
|
|
96331
96331
|
const fabric = await this.#fabrics.findFabricFromDestinationId(cx.destinationId, cx.peerRandom);
|
|
96332
96332
|
const { operationalCert: nodeOpCert, intermediateCACert, operationalIdentityProtectionKey } = fabric;
|
|
96333
|
-
const key = await
|
|
96333
|
+
const key = await crypto8.createKeyPair();
|
|
96334
96334
|
const responderEcdhPublicKey = key.publicBits;
|
|
96335
|
-
const sharedSecret = await
|
|
96335
|
+
const sharedSecret = await crypto8.generateDhSecret(key, PublicKey(cx.peerEcdhPublicKey));
|
|
96336
96336
|
const sigma2Salt = Bytes.concat(
|
|
96337
96337
|
operationalIdentityProtectionKey,
|
|
96338
96338
|
responderRandom,
|
|
96339
96339
|
responderEcdhPublicKey,
|
|
96340
|
-
await
|
|
96340
|
+
await crypto8.computeHash(cx.bytes)
|
|
96341
96341
|
);
|
|
96342
|
-
const sigma2Key = await
|
|
96342
|
+
const sigma2Key = await crypto8.createHkdfKey(sharedSecret, sigma2Salt, KDFSR2_INFO);
|
|
96343
96343
|
const signatureData = TlvSignedData.encode({
|
|
96344
96344
|
responderNoc: nodeOpCert,
|
|
96345
96345
|
responderIcac: intermediateCACert,
|
|
@@ -96353,7 +96353,7 @@ var init_CaseServer = __esm({
|
|
|
96353
96353
|
signature: signature.bytes,
|
|
96354
96354
|
resumptionId: cx.localResumptionId
|
|
96355
96355
|
});
|
|
96356
|
-
const encrypted =
|
|
96356
|
+
const encrypted = crypto8.encrypt(sigma2Key, encryptedData, TBE_DATA2_NONCE);
|
|
96357
96357
|
const responderSessionId = await this.#sessions.getNextAvailableSessionId();
|
|
96358
96358
|
const sigma2Bytes = await cx.messenger.sendSigma2({
|
|
96359
96359
|
responderRandom,
|
|
@@ -96369,10 +96369,10 @@ var init_CaseServer = __esm({
|
|
|
96369
96369
|
} = await cx.messenger.readSigma3();
|
|
96370
96370
|
const sigma3Salt = Bytes.concat(
|
|
96371
96371
|
operationalIdentityProtectionKey,
|
|
96372
|
-
await
|
|
96372
|
+
await crypto8.computeHash([cx.bytes, sigma2Bytes])
|
|
96373
96373
|
);
|
|
96374
|
-
const sigma3Key = await
|
|
96375
|
-
const peerDecryptedData =
|
|
96374
|
+
const sigma3Key = await crypto8.createHkdfKey(sharedSecret, sigma3Salt, KDFSR3_INFO);
|
|
96375
|
+
const peerDecryptedData = crypto8.decrypt(sigma3Key, peerEncrypted, TBE_DATA3_NONCE);
|
|
96376
96376
|
const {
|
|
96377
96377
|
responderNoc: peerNewOpCert,
|
|
96378
96378
|
responderIcac: peerIntermediateCACert,
|
|
@@ -96392,10 +96392,10 @@ var init_CaseServer = __esm({
|
|
|
96392
96392
|
if (fabric.fabricId !== peerFabricId) {
|
|
96393
96393
|
throw new UnexpectedDataError(`Fabric ID mismatch: ${fabric.fabricId} !== ${peerFabricId}`);
|
|
96394
96394
|
}
|
|
96395
|
-
await
|
|
96395
|
+
await crypto8.verifyEcdsa(PublicKey(peerPublicKey), peerSignatureData, new EcdsaSignature(peerSignature));
|
|
96396
96396
|
const secureSessionSalt = Bytes.concat(
|
|
96397
96397
|
operationalIdentityProtectionKey,
|
|
96398
|
-
await
|
|
96398
|
+
await crypto8.computeHash([cx.bytes, sigma2Bytes, sigma3Bytes])
|
|
96399
96399
|
);
|
|
96400
96400
|
const secureSession = await this.#sessions.createSecureSession({
|
|
96401
96401
|
channel,
|
|
@@ -96440,8 +96440,8 @@ var init_CaseServer = __esm({
|
|
|
96440
96440
|
peerSessionParams;
|
|
96441
96441
|
resumptionRecord;
|
|
96442
96442
|
#localResumptionId;
|
|
96443
|
-
constructor(
|
|
96444
|
-
this.crypto =
|
|
96443
|
+
constructor(crypto8, messenger, bytes, sigma1, resumptionRecord) {
|
|
96444
|
+
this.crypto = crypto8;
|
|
96445
96445
|
this.messenger = messenger;
|
|
96446
96446
|
this.bytes = bytes;
|
|
96447
96447
|
this.peerSessionId = sigma1.initiatorSessionId;
|
|
@@ -96937,25 +96937,25 @@ var init_PaseClient = __esm({
|
|
|
96937
96937
|
constructor(sessions) {
|
|
96938
96938
|
this.#sessions = sessions;
|
|
96939
96939
|
}
|
|
96940
|
-
static async generatePakePasscodeVerifier(
|
|
96941
|
-
const { w0, L } = await Spake2p.computeW0L(
|
|
96940
|
+
static async generatePakePasscodeVerifier(crypto8, setupPinCode, pbkdfParameters) {
|
|
96941
|
+
const { w0, L } = await Spake2p.computeW0L(crypto8, pbkdfParameters, setupPinCode);
|
|
96942
96942
|
return Bytes.concat(numberToBytesBE3(w0, 32), L);
|
|
96943
96943
|
}
|
|
96944
|
-
static generateRandomPasscode(
|
|
96944
|
+
static generateRandomPasscode(crypto8) {
|
|
96945
96945
|
let passcode;
|
|
96946
|
-
passcode =
|
|
96946
|
+
passcode = crypto8.randomUint32 % 99999998 + 1;
|
|
96947
96947
|
if (CommissioningOptions.FORBIDDEN_PASSCODES.includes(passcode)) {
|
|
96948
96948
|
passcode += 1;
|
|
96949
96949
|
}
|
|
96950
96950
|
return passcode;
|
|
96951
96951
|
}
|
|
96952
|
-
static generateRandomDiscriminator(
|
|
96953
|
-
return
|
|
96952
|
+
static generateRandomDiscriminator(crypto8) {
|
|
96953
|
+
return crypto8.randomUint16 % 4096;
|
|
96954
96954
|
}
|
|
96955
96955
|
async pair(initiatorSessionParams, exchange, channel, setupPin) {
|
|
96956
96956
|
const messenger = new PaseClientMessenger(exchange);
|
|
96957
|
-
const { crypto:
|
|
96958
|
-
const initiatorRandom =
|
|
96957
|
+
const { crypto: crypto8 } = this.#sessions;
|
|
96958
|
+
const initiatorRandom = crypto8.randomBytes(32);
|
|
96959
96959
|
const initiatorSessionId = await this.#sessions.getNextAvailableSessionId();
|
|
96960
96960
|
const requestPayload = await messenger.sendPbkdfParamRequest({
|
|
96961
96961
|
initiatorRandom,
|
|
@@ -96979,10 +96979,10 @@ var init_PaseClient = __esm({
|
|
|
96979
96979
|
...exchange.session.parameters,
|
|
96980
96980
|
...responderSessionParams ?? {}
|
|
96981
96981
|
};
|
|
96982
|
-
const { w0, w1 } = await Spake2p.computeW0W1(
|
|
96982
|
+
const { w0, w1 } = await Spake2p.computeW0W1(crypto8, pbkdfParameters, setupPin);
|
|
96983
96983
|
const spake2p = Spake2p.create(
|
|
96984
|
-
|
|
96985
|
-
await
|
|
96984
|
+
crypto8,
|
|
96985
|
+
await crypto8.computeHash([SPAKE_CONTEXT, requestPayload, responsePayload]),
|
|
96986
96986
|
w0
|
|
96987
96987
|
);
|
|
96988
96988
|
const X = spake2p.computeX();
|
|
@@ -97093,7 +97093,7 @@ var init_PaseServer = __esm({
|
|
|
97093
97093
|
}
|
|
97094
97094
|
}
|
|
97095
97095
|
}
|
|
97096
|
-
async handlePairingRequest(
|
|
97096
|
+
async handlePairingRequest(crypto8, channel) {
|
|
97097
97097
|
const messenger = this.#pairingMessenger;
|
|
97098
97098
|
logger40.info("Received pairing request", Mark.INBOUND, Diagnostic.via(messenger.channelName));
|
|
97099
97099
|
this.#pairingTimer = Time.getTimer(
|
|
@@ -97115,7 +97115,7 @@ var init_PaseServer = __esm({
|
|
|
97115
97115
|
throw new UnexpectedDataError(`Unsupported passcode ID ${passcodeId}.`);
|
|
97116
97116
|
}
|
|
97117
97117
|
const responderSessionId = await this.sessions.getNextAvailableSessionId();
|
|
97118
|
-
const responderRandom =
|
|
97118
|
+
const responderRandom = crypto8.randomBytes(32);
|
|
97119
97119
|
const responderSessionParams = this.sessions.sessionParameters;
|
|
97120
97120
|
if (initiatorSessionParams !== void 0) {
|
|
97121
97121
|
messenger.channel.session.timingParameters = initiatorSessionParams;
|
|
@@ -97128,8 +97128,8 @@ var init_PaseServer = __esm({
|
|
|
97128
97128
|
responderSessionParams
|
|
97129
97129
|
});
|
|
97130
97130
|
const spake2p = Spake2p.create(
|
|
97131
|
-
|
|
97132
|
-
await
|
|
97131
|
+
crypto8,
|
|
97132
|
+
await crypto8.computeHash([SPAKE_CONTEXT, requestPayload, responsePayload]),
|
|
97133
97133
|
this.w0
|
|
97134
97134
|
);
|
|
97135
97135
|
const { x: X } = await messenger.readPasePake1();
|
|
@@ -97197,14 +97197,14 @@ var init_UnsecuredSession = __esm({
|
|
|
97197
97197
|
supportsMRP = true;
|
|
97198
97198
|
type = SessionType.Unicast;
|
|
97199
97199
|
constructor(config10) {
|
|
97200
|
-
const { crypto:
|
|
97200
|
+
const { crypto: crypto8, initiatorNodeId, isInitiator } = config10;
|
|
97201
97201
|
super({
|
|
97202
97202
|
...config10,
|
|
97203
97203
|
setActiveTimestamp: !isInitiator,
|
|
97204
97204
|
// When we are the initiator we assume the node is in idle mode
|
|
97205
97205
|
messageReceptionState: new MessageReceptionStateUnencryptedWithRollover()
|
|
97206
97206
|
});
|
|
97207
|
-
this.#initiatorNodeId = initiatorNodeId ?? NodeId.randomOperationalNodeId(
|
|
97207
|
+
this.#initiatorNodeId = initiatorNodeId ?? NodeId.randomOperationalNodeId(crypto8);
|
|
97208
97208
|
}
|
|
97209
97209
|
get isSecure() {
|
|
97210
97210
|
return false;
|
|
@@ -97291,11 +97291,11 @@ var init_SessionManager = __esm({
|
|
|
97291
97291
|
constructor(context) {
|
|
97292
97292
|
this.#context = context;
|
|
97293
97293
|
const {
|
|
97294
|
-
fabrics: { crypto:
|
|
97294
|
+
fabrics: { crypto: crypto8 }
|
|
97295
97295
|
} = context;
|
|
97296
97296
|
this.#sessionParameters = SessionParameters({ ...SessionParameters.defaults, ...context.parameters });
|
|
97297
|
-
this.#nextSessionId =
|
|
97298
|
-
this.#globalUnencryptedMessageCounter = new MessageCounter(
|
|
97297
|
+
this.#nextSessionId = crypto8.randomUint16;
|
|
97298
|
+
this.#globalUnencryptedMessageCounter = new MessageCounter(crypto8);
|
|
97299
97299
|
this.#observers.on(context.fabrics.events.deleting, async (fabric) => {
|
|
97300
97300
|
await this.deleteResumptionRecordsForFabric(fabric);
|
|
97301
97301
|
});
|
|
@@ -100871,18 +100871,18 @@ var init_ProtocolMocks = __esm({
|
|
|
100871
100871
|
init_MessageExchange();
|
|
100872
100872
|
((ProtocolMocks2) => {
|
|
100873
100873
|
class Fabric2 extends Fabric {
|
|
100874
|
-
constructor(config10,
|
|
100875
|
-
if (!
|
|
100876
|
-
|
|
100877
|
-
if (!(
|
|
100878
|
-
|
|
100874
|
+
constructor(config10, crypto8) {
|
|
100875
|
+
if (!crypto8) {
|
|
100876
|
+
crypto8 = Environment.default.maybeGet(Crypto);
|
|
100877
|
+
if (!(crypto8 instanceof MockCrypto)) {
|
|
100878
|
+
crypto8 = MockCrypto();
|
|
100879
100879
|
}
|
|
100880
100880
|
}
|
|
100881
|
-
const keyPair = config10?.keyPair ??
|
|
100881
|
+
const keyPair = config10?.keyPair ?? crypto8.createKeyPair();
|
|
100882
100882
|
if (MaybePromise.is(keyPair)) {
|
|
100883
100883
|
throw new ImplementationError("Must provide key pair with async crypto");
|
|
100884
100884
|
}
|
|
100885
|
-
super(
|
|
100885
|
+
super(crypto8, {
|
|
100886
100886
|
...Fabric2.defaults,
|
|
100887
100887
|
...config10,
|
|
100888
100888
|
keyPair
|
|
@@ -100912,7 +100912,7 @@ var init_ProtocolMocks = __esm({
|
|
|
100912
100912
|
constructor(config10) {
|
|
100913
100913
|
const index = config10?.index ?? 1;
|
|
100914
100914
|
const fabricIndex = config10?.fabricIndex ?? 1;
|
|
100915
|
-
const
|
|
100915
|
+
const crypto8 = config10?.crypto ?? Environment.default.get(Crypto);
|
|
100916
100916
|
const fabric = config10 && "fabric" in config10 ? config10.fabric : new Fabric2({ fabricIndex });
|
|
100917
100917
|
const maxPayloadSize = config10?.maxPayloadSize;
|
|
100918
100918
|
let channel;
|
|
@@ -100931,7 +100931,7 @@ var init_ProtocolMocks = __esm({
|
|
|
100931
100931
|
encryptKey: Bytes.empty,
|
|
100932
100932
|
isInitiator: true,
|
|
100933
100933
|
...config10,
|
|
100934
|
-
crypto:
|
|
100934
|
+
crypto: crypto8,
|
|
100935
100935
|
fabric
|
|
100936
100936
|
};
|
|
100937
100937
|
delete fullConfig.channel;
|
|
@@ -100940,11 +100940,11 @@ var init_ProtocolMocks = __esm({
|
|
|
100940
100940
|
this.lifetime = Lifetime.mock;
|
|
100941
100941
|
}
|
|
100942
100942
|
static async create(config10) {
|
|
100943
|
-
const
|
|
100943
|
+
const crypto8 = config10?.crypto ?? config10?.manager?.crypto ?? Environment.default.get(Crypto);
|
|
100944
100944
|
const index = config10?.index ?? 1;
|
|
100945
100945
|
return NodeSession.create.call(this, {
|
|
100946
100946
|
id: index,
|
|
100947
|
-
crypto:
|
|
100947
|
+
crypto: crypto8,
|
|
100948
100948
|
peerNodeId: NodeId(0),
|
|
100949
100949
|
peerSessionId: index,
|
|
100950
100950
|
sharedSecret: Bytes.empty,
|
|
@@ -106671,9 +106671,9 @@ var init_MdnsAdvertiser = __esm({
|
|
|
106671
106671
|
init_CommissionerMdnsAdvertisement();
|
|
106672
106672
|
init_OperationalMdnsAdvertisement();
|
|
106673
106673
|
MdnsAdvertiser = class _MdnsAdvertiser extends Advertiser {
|
|
106674
|
-
constructor(
|
|
106674
|
+
constructor(crypto8, server, options) {
|
|
106675
106675
|
super(options?.lifetime);
|
|
106676
|
-
this.crypto =
|
|
106676
|
+
this.crypto = crypto8;
|
|
106677
106677
|
this.server = server;
|
|
106678
106678
|
this.port = options?.port ?? STANDARD_MATTER_PORT;
|
|
106679
106679
|
this.omitPrivateDetails = options?.omitPrivateDetails ?? false;
|
|
@@ -108118,8 +108118,8 @@ var init_AttestationCertificates = __esm({
|
|
|
108118
108118
|
* Sign the certificate using the provided crypto and key.
|
|
108119
108119
|
* If the certificate is already signed, it throws a CertificateError.
|
|
108120
108120
|
*/
|
|
108121
|
-
async sign(
|
|
108122
|
-
this.signature = await
|
|
108121
|
+
async sign(crypto8, key) {
|
|
108122
|
+
this.signature = await crypto8.signEcdsa(key, this.asUnsignedDer());
|
|
108123
108123
|
}
|
|
108124
108124
|
};
|
|
108125
108125
|
Paa = class _Paa extends AttestationBaseCertificate {
|
|
@@ -108168,17 +108168,17 @@ var init_AttestationCertificateManager = __esm({
|
|
|
108168
108168
|
#paiCertId = BigInt(1);
|
|
108169
108169
|
#paiCertBytes;
|
|
108170
108170
|
#nextCertificateId = 2;
|
|
108171
|
-
constructor(
|
|
108172
|
-
this.#crypto =
|
|
108171
|
+
constructor(crypto8, vendorId3, paiKeyPair, paiKeyIdentifier) {
|
|
108172
|
+
this.#crypto = crypto8;
|
|
108173
108173
|
this.#vendorId = vendorId3;
|
|
108174
108174
|
this.#paiKeyPair = paiKeyPair;
|
|
108175
108175
|
this.#paiKeyIdentifier = paiKeyIdentifier;
|
|
108176
108176
|
this.#paiCertBytes = this.generatePAICert(vendorId3);
|
|
108177
108177
|
}
|
|
108178
|
-
static async create(
|
|
108179
|
-
const key = await
|
|
108180
|
-
const identifier = Bytes.of(await
|
|
108181
|
-
return new _AttestationCertificateManager(
|
|
108178
|
+
static async create(crypto8, vendorId3) {
|
|
108179
|
+
const key = await crypto8.createKeyPair();
|
|
108180
|
+
const identifier = Bytes.of(await crypto8.computeHash(key.publicKey));
|
|
108181
|
+
return new _AttestationCertificateManager(crypto8, vendorId3, key, identifier.slice(0, 20));
|
|
108182
108182
|
}
|
|
108183
108183
|
getPAICert() {
|
|
108184
108184
|
return this.#paiCertBytes;
|
|
@@ -108324,11 +108324,11 @@ var init_CertificateAuthority = __esm({
|
|
|
108324
108324
|
get construction() {
|
|
108325
108325
|
return this.#construction;
|
|
108326
108326
|
}
|
|
108327
|
-
static async create(
|
|
108328
|
-
return asyncNew(_CertificateAuthority,
|
|
108327
|
+
static async create(crypto8, options, generateIntermediateCert) {
|
|
108328
|
+
return asyncNew(_CertificateAuthority, crypto8, options, generateIntermediateCert);
|
|
108329
108329
|
}
|
|
108330
|
-
constructor(
|
|
108331
|
-
this.#crypto =
|
|
108330
|
+
constructor(crypto8, options, generateIntermediateCert) {
|
|
108331
|
+
this.#crypto = crypto8;
|
|
108332
108332
|
this.#construction = Construction(this, async () => {
|
|
108333
108333
|
if (typeof options === "boolean") {
|
|
108334
108334
|
generateIntermediateCert = options;
|
|
@@ -108610,7 +108610,7 @@ var init_CertificationDeclaration = __esm({
|
|
|
108610
108610
|
* Generator which is the main usage for the class from outside.
|
|
108611
108611
|
* It constructs the class with the relevant details and returns a signed ASN.1 DER version of the CD.
|
|
108612
108612
|
*/
|
|
108613
|
-
static generate(
|
|
108613
|
+
static generate(crypto8, vendorId3, productId, provisional = false) {
|
|
108614
108614
|
const cd = new _CertificationDeclaration(
|
|
108615
108615
|
{
|
|
108616
108616
|
formatVersion: 1,
|
|
@@ -108626,7 +108626,7 @@ var init_CertificationDeclaration = __esm({
|
|
|
108626
108626
|
},
|
|
108627
108627
|
TestCMS_SignerSubjectKeyIdentifier
|
|
108628
108628
|
);
|
|
108629
|
-
return cd.asSignedAsn1(
|
|
108629
|
+
return cd.asSignedAsn1(crypto8, PrivateKey(TestCMS_SignerPrivateKey));
|
|
108630
108630
|
}
|
|
108631
108631
|
constructor(content, subjectKeyIdentifier) {
|
|
108632
108632
|
this.#eContent = CertificationDeclaration.TlvDc.encode(content);
|
|
@@ -108635,7 +108635,7 @@ var init_CertificationDeclaration = __esm({
|
|
|
108635
108635
|
/**
|
|
108636
108636
|
* Returns the signed certificate in ASN.1 DER format.
|
|
108637
108637
|
*/
|
|
108638
|
-
async asSignedAsn1(
|
|
108638
|
+
async asSignedAsn1(crypto8, privateKey) {
|
|
108639
108639
|
const cert = {
|
|
108640
108640
|
version: 3,
|
|
108641
108641
|
digestAlgorithm: [Shs.SHA256_CMS],
|
|
@@ -108646,7 +108646,7 @@ var init_CertificationDeclaration = __esm({
|
|
|
108646
108646
|
subjectKeyIdentifier: ContextTaggedBytes(0, this.#subjectKeyIdentifier),
|
|
108647
108647
|
digestAlgorithm: Shs.SHA256_CMS,
|
|
108648
108648
|
signatureAlgorithm: X962.EcdsaWithSHA256,
|
|
108649
|
-
signature: (await
|
|
108649
|
+
signature: (await crypto8.signEcdsa(privateKey, this.#eContent)).der
|
|
108650
108650
|
}
|
|
108651
108651
|
]
|
|
108652
108652
|
};
|
|
@@ -108684,8 +108684,8 @@ var init_DeviceCertification = __esm({
|
|
|
108684
108684
|
get declaration() {
|
|
108685
108685
|
return this.#assertInitialized().declaration;
|
|
108686
108686
|
}
|
|
108687
|
-
constructor(
|
|
108688
|
-
this.#crypto =
|
|
108687
|
+
constructor(crypto8, config10, product) {
|
|
108688
|
+
this.#crypto = crypto8;
|
|
108689
108689
|
let configProvider;
|
|
108690
108690
|
if (typeof config10 === "function") {
|
|
108691
108691
|
configProvider = config10;
|
|
@@ -108696,13 +108696,13 @@ var init_DeviceCertification = __esm({
|
|
|
108696
108696
|
if (product === void 0) {
|
|
108697
108697
|
throw new ImplementationError(`Cannot generate device certification without product information`);
|
|
108698
108698
|
}
|
|
108699
|
-
const paa = await AttestationCertificateManager.create(
|
|
108699
|
+
const paa = await AttestationCertificateManager.create(crypto8, product.vendorId);
|
|
108700
108700
|
const { keyPair: dacKeyPair, dac } = await paa.getDACert(product.productId);
|
|
108701
108701
|
return {
|
|
108702
108702
|
privateKey: PrivateKey(dacKeyPair.privateKey),
|
|
108703
108703
|
certificate: dac,
|
|
108704
108704
|
intermediateCertificate: await paa.getPAICert(),
|
|
108705
|
-
declaration: await CertificationDeclaration2.generate(
|
|
108705
|
+
declaration: await CertificationDeclaration2.generate(crypto8, product.vendorId, product.productId)
|
|
108706
108706
|
};
|
|
108707
108707
|
};
|
|
108708
108708
|
}
|
|
@@ -109493,8 +109493,8 @@ var init_OtaImageReader = __esm({
|
|
|
109493
109493
|
return reader.#headerData;
|
|
109494
109494
|
}
|
|
109495
109495
|
/** Read and validate the full OTA image file from the stream and returns the header data on success. */
|
|
109496
|
-
static async file(streamReader,
|
|
109497
|
-
const reader = new _OtaImageReader(streamReader,
|
|
109496
|
+
static async file(streamReader, crypto8, expectedTotalSize, options) {
|
|
109497
|
+
const reader = new _OtaImageReader(streamReader, crypto8);
|
|
109498
109498
|
if (options?.checksumType !== void 0) {
|
|
109499
109499
|
reader.#fullFileChecksumType = options.checksumType;
|
|
109500
109500
|
}
|
|
@@ -109528,8 +109528,8 @@ var init_OtaImageReader = __esm({
|
|
|
109528
109528
|
* Read and validate OTA file, extracting payload to a writable stream.
|
|
109529
109529
|
* Returns the header information after successful validation and extraction.
|
|
109530
109530
|
*/
|
|
109531
|
-
static async extractPayload(streamReader, payloadWriter,
|
|
109532
|
-
const reader = new _OtaImageReader(streamReader,
|
|
109531
|
+
static async extractPayload(streamReader, payloadWriter, crypto8, expectedTotalSize) {
|
|
109532
|
+
const reader = new _OtaImageReader(streamReader, crypto8);
|
|
109533
109533
|
const { remainingData } = await reader.#processHeader(false);
|
|
109534
109534
|
if (reader.#headerData === void 0) {
|
|
109535
109535
|
throw new InternalError("OTA header not read");
|
|
@@ -109545,9 +109545,9 @@ var init_OtaImageReader = __esm({
|
|
|
109545
109545
|
}
|
|
109546
109546
|
return reader.#headerData;
|
|
109547
109547
|
}
|
|
109548
|
-
constructor(streamReader,
|
|
109548
|
+
constructor(streamReader, crypto8) {
|
|
109549
109549
|
this.#streamReader = streamReader;
|
|
109550
|
-
this.#crypto =
|
|
109550
|
+
this.#crypto = crypto8;
|
|
109551
109551
|
}
|
|
109552
109552
|
get totalSize() {
|
|
109553
109553
|
return this.#totalSize;
|
|
@@ -125833,8 +125833,8 @@ var init_VendorIdVerification = __esm({
|
|
|
125833
125833
|
}
|
|
125834
125834
|
VendorIdVerification2.dataToSign = dataToSign;
|
|
125835
125835
|
async function verify(node, options) {
|
|
125836
|
-
const
|
|
125837
|
-
const clientChallenge =
|
|
125836
|
+
const crypto8 = node.env.get(Crypto);
|
|
125837
|
+
const clientChallenge = crypto8.randomBytes(32);
|
|
125838
125838
|
const {
|
|
125839
125839
|
fabric: { fabricIndex }
|
|
125840
125840
|
} = options;
|
|
@@ -125857,7 +125857,7 @@ var init_VendorIdVerification = __esm({
|
|
|
125857
125857
|
return void 0;
|
|
125858
125858
|
}
|
|
125859
125859
|
const { noc, rcac, fabric } = options;
|
|
125860
|
-
return await verifyData(
|
|
125860
|
+
return await verifyData(crypto8, {
|
|
125861
125861
|
clientChallenge,
|
|
125862
125862
|
attChallenge: session.attestationChallengeKey,
|
|
125863
125863
|
signVerificationResponse,
|
|
@@ -125867,7 +125867,7 @@ var init_VendorIdVerification = __esm({
|
|
|
125867
125867
|
});
|
|
125868
125868
|
}
|
|
125869
125869
|
VendorIdVerification2.verify = verify;
|
|
125870
|
-
async function verifyData(
|
|
125870
|
+
async function verifyData(crypto8, options) {
|
|
125871
125871
|
const {
|
|
125872
125872
|
clientChallenge,
|
|
125873
125873
|
attChallenge,
|
|
@@ -125893,14 +125893,14 @@ var init_VendorIdVerification = __esm({
|
|
|
125893
125893
|
}
|
|
125894
125894
|
}).signatureData;
|
|
125895
125895
|
try {
|
|
125896
|
-
await
|
|
125896
|
+
await crypto8.verifyEcdsa(PublicKey(rootPublicKey), tbs, new EcdsaSignature(signature));
|
|
125897
125897
|
const rootCert = Rcac.fromTlv(rcac);
|
|
125898
125898
|
const nocCert = Noc.fromTlv(noc);
|
|
125899
125899
|
const icaCert = icac ? Icac.fromTlv(icac) : void 0;
|
|
125900
125900
|
if (icaCert !== void 0) {
|
|
125901
|
-
await icaCert.verify(
|
|
125901
|
+
await icaCert.verify(crypto8, rootCert);
|
|
125902
125902
|
}
|
|
125903
|
-
await nocCert.verify(
|
|
125903
|
+
await nocCert.verify(crypto8, rootCert, icaCert);
|
|
125904
125904
|
} catch (error) {
|
|
125905
125905
|
CryptoError.accept(error);
|
|
125906
125906
|
logger103.error("Could not verify VendorId", error);
|
|
@@ -125930,13 +125930,13 @@ var init_VendorIdVerification = __esm({
|
|
|
125930
125930
|
`VVSC SubjectKeyIdentifier does not match signerSkid in VID Verification Statement`
|
|
125931
125931
|
);
|
|
125932
125932
|
}
|
|
125933
|
-
await vvscCert.verify(
|
|
125933
|
+
await vvscCert.verify(crypto8);
|
|
125934
125934
|
const ourStatement = createStatementBytes({
|
|
125935
125935
|
version: vidStatementVersion,
|
|
125936
125936
|
fabricBindingMessage: tbs,
|
|
125937
125937
|
signerSkid
|
|
125938
125938
|
});
|
|
125939
|
-
await
|
|
125939
|
+
await crypto8.verifyEcdsa(
|
|
125940
125940
|
PublicKey(ellipticCurvePublicKey),
|
|
125941
125941
|
ourStatement,
|
|
125942
125942
|
new EcdsaSignature(vidStatementSignature)
|
|
@@ -130205,8 +130205,8 @@ var init_OtaSoftwareUpdateProviderServer = __esm({
|
|
|
130205
130205
|
// the usual bdx session timeout is 5 minutes, so let's use this
|
|
130206
130206
|
};
|
|
130207
130207
|
}
|
|
130208
|
-
const
|
|
130209
|
-
const updateToken =
|
|
130208
|
+
const crypto8 = this.env.get(Crypto);
|
|
130209
|
+
const updateToken = crypto8.randomBytes(OTA_UPDATE_TOKEN_LENGTH_BYTES);
|
|
130210
130210
|
if (consentRequired && !request.requestorCanConsent) {
|
|
130211
130211
|
this.#updateInProgressDetails(peerAddress, updateToken, OtaUpdateStatus.WaitForConsent, newSoftwareVersion);
|
|
130212
130212
|
const { consentState, delayTime = Seconds(120) } = await this.requestUserConsentForUpdate(
|
|
@@ -132681,8 +132681,8 @@ var init_OtaSoftwareUpdateRequestorServer = __esm({
|
|
|
132681
132681
|
try {
|
|
132682
132682
|
const blob = await this.downloadLocation.openBlob();
|
|
132683
132683
|
totalSize = blob.size;
|
|
132684
|
-
const
|
|
132685
|
-
const header = await OtaImageReader.file(blob.stream().getReader(),
|
|
132684
|
+
const crypto8 = this.env.get(Crypto);
|
|
132685
|
+
const header = await OtaImageReader.file(blob.stream().getReader(), crypto8);
|
|
132686
132686
|
const { softwareVersion: otaFileSoftwareVersion } = header;
|
|
132687
132687
|
if (newSoftwareVersion === void 0) {
|
|
132688
132688
|
const { softwareVersion: currentSoftwareVersion } = this.#basicInformationState();
|
|
@@ -141853,9 +141853,9 @@ var init_ServerNetworkRuntime = __esm({
|
|
|
141853
141853
|
lifetime: this.construction,
|
|
141854
141854
|
...this.owner.state.commissioning.mdns
|
|
141855
141855
|
};
|
|
141856
|
-
const
|
|
141856
|
+
const crypto8 = this.owner.env.get(Crypto);
|
|
141857
141857
|
const { server } = this.#services.get(MdnsService);
|
|
141858
|
-
this.#mdnsAdvertiser = new MdnsAdvertiser(
|
|
141858
|
+
this.#mdnsAdvertiser = new MdnsAdvertiser(crypto8, server, { ...options, port });
|
|
141859
141859
|
}
|
|
141860
141860
|
return this.#mdnsAdvertiser;
|
|
141861
141861
|
}
|
|
@@ -145421,14 +145421,14 @@ function rootDirOf(env) {
|
|
|
145421
145421
|
function configureCrypto(env) {
|
|
145422
145422
|
Boot.init(() => {
|
|
145423
145423
|
if (env.vars.boolean("nodejs.crypto")) {
|
|
145424
|
-
let
|
|
145424
|
+
let crypto8;
|
|
145425
145425
|
if (!isBunjs()) {
|
|
145426
|
-
|
|
145426
|
+
crypto8 = new NodeJsCrypto();
|
|
145427
145427
|
} else {
|
|
145428
|
-
|
|
145428
|
+
crypto8 = new StandardCrypto(global.crypto);
|
|
145429
145429
|
}
|
|
145430
|
-
env.set(Entropy,
|
|
145431
|
-
env.set(Crypto,
|
|
145430
|
+
env.set(Entropy, crypto8);
|
|
145431
|
+
env.set(Crypto, crypto8);
|
|
145432
145432
|
return;
|
|
145433
145433
|
}
|
|
145434
145434
|
if (Environment.default.has(Entropy)) {
|
|
@@ -146411,6 +146411,7 @@ var init_vacuum = __esm({
|
|
|
146411
146411
|
VacuumDeviceFeature2[VacuumDeviceFeature2["MAP"] = 2048] = "MAP";
|
|
146412
146412
|
VacuumDeviceFeature2[VacuumDeviceFeature2["STATE"] = 4096] = "STATE";
|
|
146413
146413
|
VacuumDeviceFeature2[VacuumDeviceFeature2["START"] = 8192] = "START";
|
|
146414
|
+
VacuumDeviceFeature2[VacuumDeviceFeature2["CLEAN_AREA"] = 16384] = "CLEAN_AREA";
|
|
146414
146415
|
})(VacuumDeviceFeature || (VacuumDeviceFeature = {}));
|
|
146415
146416
|
(function(VacuumFanSpeed2) {
|
|
146416
146417
|
VacuumFanSpeed2["off"] = "off";
|
|
@@ -147773,7 +147774,8 @@ WARNING: ${includeIdentity ? "This backup contains sensitive Matter identity dat
|
|
|
147773
147774
|
powerEntity: config10.powerEntity,
|
|
147774
147775
|
energyEntity: config10.energyEntity,
|
|
147775
147776
|
suctionLevelEntity: config10.suctionLevelEntity,
|
|
147776
|
-
mopIntensityEntity: config10.mopIntensityEntity
|
|
147777
|
+
mopIntensityEntity: config10.mopIntensityEntity,
|
|
147778
|
+
valetudoIdentifier: config10.valetudoIdentifier
|
|
147777
147779
|
});
|
|
147778
147780
|
mappingsRestored++;
|
|
147779
147781
|
}
|
|
@@ -148668,7 +148670,8 @@ function entityMappingApi(mappingStorage) {
|
|
|
148668
148670
|
suctionLevelEntity: body.suctionLevelEntity,
|
|
148669
148671
|
mopIntensityEntity: body.mopIntensityEntity,
|
|
148670
148672
|
customServiceAreas: body.customServiceAreas,
|
|
148671
|
-
customFanSpeedTags: body.customFanSpeedTags
|
|
148673
|
+
customFanSpeedTags: body.customFanSpeedTags,
|
|
148674
|
+
valetudoIdentifier: body.valetudoIdentifier
|
|
148672
148675
|
};
|
|
148673
148676
|
const config10 = await mappingStorage.setMapping(request);
|
|
148674
148677
|
res.status(200).json(config10);
|
|
@@ -149128,7 +149131,8 @@ function configToProfileEntry(config10) {
|
|
|
149128
149131
|
suctionLevelEntity: config10.suctionLevelEntity,
|
|
149129
149132
|
mopIntensityEntity: config10.mopIntensityEntity,
|
|
149130
149133
|
customServiceAreas: config10.customServiceAreas,
|
|
149131
|
-
customFanSpeedTags: config10.customFanSpeedTags
|
|
149134
|
+
customFanSpeedTags: config10.customFanSpeedTags,
|
|
149135
|
+
valetudoIdentifier: config10.valetudoIdentifier
|
|
149132
149136
|
};
|
|
149133
149137
|
}
|
|
149134
149138
|
function mappingProfileApi(mappingStorage) {
|
|
@@ -149246,7 +149250,8 @@ function mappingProfileApi(mappingStorage) {
|
|
|
149246
149250
|
suctionLevelEntity: entry.suctionLevelEntity,
|
|
149247
149251
|
mopIntensityEntity: entry.mopIntensityEntity,
|
|
149248
149252
|
customServiceAreas: entry.customServiceAreas,
|
|
149249
|
-
customFanSpeedTags: entry.customFanSpeedTags
|
|
149253
|
+
customFanSpeedTags: entry.customFanSpeedTags,
|
|
149254
|
+
valetudoIdentifier: entry.valetudoIdentifier
|
|
149250
149255
|
});
|
|
149251
149256
|
applied++;
|
|
149252
149257
|
} catch (e) {
|
|
@@ -149283,6 +149288,9 @@ function testMatchers(matchers, device, entity, mode = "any", entityState, label
|
|
|
149283
149288
|
);
|
|
149284
149289
|
}
|
|
149285
149290
|
function testMatcher(matcher, device, entity, entityState, labels) {
|
|
149291
|
+
if (matcher.value == null) {
|
|
149292
|
+
return false;
|
|
149293
|
+
}
|
|
149286
149294
|
switch (matcher.type) {
|
|
149287
149295
|
case "domain":
|
|
149288
149296
|
return entity.entity_id.split(".")[0] === matcher.value;
|
|
@@ -151983,6 +151991,7 @@ var BridgeService = class extends Service {
|
|
|
151983
151991
|
for (const bridge of this.bridges) {
|
|
151984
151992
|
try {
|
|
151985
151993
|
await bridge.refreshDevices();
|
|
151994
|
+
this.onBridgeChanged?.(bridge.id);
|
|
151986
151995
|
} catch (e) {
|
|
151987
151996
|
this.log.error(`Failed to refresh bridge ${bridge.id}:`, e);
|
|
151988
151997
|
}
|
|
@@ -152273,7 +152282,7 @@ var HomeAssistantRegistry = class extends Service {
|
|
|
152273
152282
|
try {
|
|
152274
152283
|
const changed = await this.reload();
|
|
152275
152284
|
if (changed) {
|
|
152276
|
-
onRefresh();
|
|
152285
|
+
await onRefresh();
|
|
152277
152286
|
}
|
|
152278
152287
|
} catch (e) {
|
|
152279
152288
|
logger145.warn("Failed to refresh registry, will retry next interval:", e);
|
|
@@ -152317,14 +152326,20 @@ var HomeAssistantRegistry = class extends Service {
|
|
|
152317
152326
|
const hash2 = createHash("md5");
|
|
152318
152327
|
for (const e of entityRegistry) {
|
|
152319
152328
|
hash2.update(
|
|
152320
|
-
`${e.entity_id}\0${e.device_id ?? ""}\0${e.disabled_by ?? ""}\0${e.hidden_by ?? ""}
|
|
152329
|
+
`${e.entity_id}\0${e.device_id ?? ""}\0${e.disabled_by ?? ""}\0${e.hidden_by ?? ""}\0${e.area_id ?? ""}\0${(e.labels ?? []).join(",")}\0${e.platform ?? ""}\0${e.entity_category ?? ""}
|
|
152321
152330
|
`
|
|
152322
152331
|
);
|
|
152323
152332
|
}
|
|
152324
|
-
for (const s of statesList)
|
|
152325
|
-
|
|
152326
|
-
for (const d of deviceRegistry) hash2.update(`${d.id}
|
|
152333
|
+
for (const s of statesList) {
|
|
152334
|
+
hash2.update(`${s.entity_id}\0${s.attributes?.device_class ?? ""}
|
|
152327
152335
|
`);
|
|
152336
|
+
}
|
|
152337
|
+
for (const d of deviceRegistry) {
|
|
152338
|
+
hash2.update(
|
|
152339
|
+
`${d.id}\0${(d.labels ?? []).join(",")}\0${d.area_id ?? ""}\0${d.name_by_user ?? ""}\0${d.name ?? ""}\0${d.model ?? ""}
|
|
152340
|
+
`
|
|
152341
|
+
);
|
|
152342
|
+
}
|
|
152328
152343
|
for (const l of labels) hash2.update(`${l.label_id}
|
|
152329
152344
|
`);
|
|
152330
152345
|
for (const a of areas) hash2.update(`${a.area_id}\0${a.name}
|
|
@@ -152670,9 +152685,10 @@ var EntityMappingStorage = class extends Service {
|
|
|
152670
152685
|
customServiceAreas: request.customServiceAreas?.filter(
|
|
152671
152686
|
(a) => a.name?.trim() && a.service?.trim()
|
|
152672
152687
|
) ?? void 0,
|
|
152673
|
-
customFanSpeedTags: request.customFanSpeedTags && Object.keys(request.customFanSpeedTags).length > 0 ? request.customFanSpeedTags : void 0
|
|
152688
|
+
customFanSpeedTags: request.customFanSpeedTags && Object.keys(request.customFanSpeedTags).length > 0 ? request.customFanSpeedTags : void 0,
|
|
152689
|
+
valetudoIdentifier: request.valetudoIdentifier?.trim() || void 0
|
|
152674
152690
|
};
|
|
152675
|
-
if (!config10.matterDeviceType && !config10.customName && config10.disabled !== true && !config10.filterLifeEntity && !config10.cleaningModeEntity && !config10.humidityEntity && !config10.batteryEntity && !config10.roomEntities && !config10.disableLockPin && !config10.powerEntity && !config10.energyEntity && !config10.pressureEntity && !config10.suctionLevelEntity && !config10.mopIntensityEntity && (!config10.customServiceAreas || config10.customServiceAreas.length === 0) && (!config10.customFanSpeedTags || Object.keys(config10.customFanSpeedTags).length === 0)) {
|
|
152691
|
+
if (!config10.matterDeviceType && !config10.customName && config10.disabled !== true && !config10.filterLifeEntity && !config10.cleaningModeEntity && !config10.humidityEntity && !config10.batteryEntity && !config10.roomEntities && !config10.disableLockPin && !config10.powerEntity && !config10.energyEntity && !config10.pressureEntity && !config10.suctionLevelEntity && !config10.mopIntensityEntity && (!config10.customServiceAreas || config10.customServiceAreas.length === 0) && (!config10.customFanSpeedTags || Object.keys(config10.customFanSpeedTags).length === 0) && !config10.valetudoIdentifier) {
|
|
152676
152692
|
bridgeMap.delete(request.entityId);
|
|
152677
152693
|
} else {
|
|
152678
152694
|
bridgeMap.set(request.entityId, config10);
|
|
@@ -159413,6 +159429,7 @@ var DimmablePlugInUnitDeviceDefinition = MutableEndpoint({
|
|
|
159413
159429
|
)
|
|
159414
159430
|
});
|
|
159415
159431
|
Object.freeze(DimmablePlugInUnitDeviceDefinition);
|
|
159432
|
+
var DimmablePlugInUnitDevice = DimmablePlugInUnitDeviceDefinition;
|
|
159416
159433
|
|
|
159417
159434
|
// ../../node_modules/.pnpm/@matter+node@0.16.10/node_modules/@matter/node/dist/esm/devices/dimmer-switch.js
|
|
159418
159435
|
init_IdentifyServer();
|
|
@@ -164692,10 +164709,6 @@ import * as path12 from "node:path";
|
|
|
164692
164709
|
// src/plugins/plugin-device-factory.ts
|
|
164693
164710
|
init_esm();
|
|
164694
164711
|
|
|
164695
|
-
// src/matter/behaviors/basic-information-server.ts
|
|
164696
|
-
init_esm7();
|
|
164697
|
-
import crypto4 from "node:crypto";
|
|
164698
|
-
|
|
164699
164712
|
// ../../node_modules/.pnpm/@matter+main@0.16.10/node_modules/@matter/main/dist/esm/behaviors.js
|
|
164700
164713
|
init_nodejs();
|
|
164701
164714
|
|
|
@@ -165653,6 +165666,65 @@ init_window_covering();
|
|
|
165653
165666
|
init_ClientBehavior();
|
|
165654
165667
|
var WindowCoveringClientConstructor = ClientBehavior(WindowCovering3.Complete);
|
|
165655
165668
|
|
|
165669
|
+
// src/matter/behaviors/identify-server.ts
|
|
165670
|
+
var IdentifyServer2 = class extends IdentifyServer {
|
|
165671
|
+
};
|
|
165672
|
+
|
|
165673
|
+
// src/matter/endpoints/validate-endpoint-type.ts
|
|
165674
|
+
init_esm();
|
|
165675
|
+
init_esm7();
|
|
165676
|
+
var logger158 = Logger.get("EndpointValidation");
|
|
165677
|
+
function toCamelCase(name) {
|
|
165678
|
+
return name.charAt(0).toLowerCase() + name.slice(1);
|
|
165679
|
+
}
|
|
165680
|
+
function validateEndpointType(endpointType, entityId) {
|
|
165681
|
+
const deviceTypeModel = Matter.deviceTypes.find(
|
|
165682
|
+
(dt) => dt.id === endpointType.deviceType
|
|
165683
|
+
);
|
|
165684
|
+
if (!deviceTypeModel) {
|
|
165685
|
+
return void 0;
|
|
165686
|
+
}
|
|
165687
|
+
const serverClusterReqs = deviceTypeModel.requirements.filter(
|
|
165688
|
+
(r) => r.element === "serverCluster"
|
|
165689
|
+
);
|
|
165690
|
+
const behaviorKeys = new Set(Object.keys(endpointType.behaviors));
|
|
165691
|
+
const missingMandatory = [];
|
|
165692
|
+
const availableOptional = [];
|
|
165693
|
+
const presentClusters = [];
|
|
165694
|
+
for (const req of serverClusterReqs) {
|
|
165695
|
+
const key = toCamelCase(req.name);
|
|
165696
|
+
if (behaviorKeys.has(key)) {
|
|
165697
|
+
presentClusters.push(req.name);
|
|
165698
|
+
} else if (req.isMandatory) {
|
|
165699
|
+
missingMandatory.push(req.name);
|
|
165700
|
+
} else {
|
|
165701
|
+
availableOptional.push(req.name);
|
|
165702
|
+
}
|
|
165703
|
+
}
|
|
165704
|
+
const prefix = entityId ? `[${entityId}] ` : "";
|
|
165705
|
+
if (missingMandatory.length > 0) {
|
|
165706
|
+
logger158.warn(
|
|
165707
|
+
`${prefix}${deviceTypeModel.name} (0x${endpointType.deviceType.toString(16)}): missing mandatory clusters: ${missingMandatory.join(", ")}`
|
|
165708
|
+
);
|
|
165709
|
+
}
|
|
165710
|
+
if (availableOptional.length > 0) {
|
|
165711
|
+
logger158.debug(
|
|
165712
|
+
`${prefix}${deviceTypeModel.name} (0x${endpointType.deviceType.toString(16)}): optional clusters not used: ${availableOptional.join(", ")}`
|
|
165713
|
+
);
|
|
165714
|
+
}
|
|
165715
|
+
return {
|
|
165716
|
+
deviceTypeName: deviceTypeModel.name,
|
|
165717
|
+
deviceTypeId: endpointType.deviceType,
|
|
165718
|
+
missingMandatory,
|
|
165719
|
+
availableOptional,
|
|
165720
|
+
presentClusters
|
|
165721
|
+
};
|
|
165722
|
+
}
|
|
165723
|
+
|
|
165724
|
+
// src/plugins/plugin-basic-information-server.ts
|
|
165725
|
+
init_esm7();
|
|
165726
|
+
import crypto4 from "node:crypto";
|
|
165727
|
+
|
|
165656
165728
|
// src/services/bridges/bridge-data-provider.ts
|
|
165657
165729
|
init_service();
|
|
165658
165730
|
import { values as values2 } from "lodash-es";
|
|
@@ -165741,7 +165813,7 @@ var BridgeDataProvider = class extends Service {
|
|
|
165741
165813
|
|
|
165742
165814
|
// src/utils/apply-patch-state.ts
|
|
165743
165815
|
init_esm();
|
|
165744
|
-
var
|
|
165816
|
+
var logger159 = Logger.get("ApplyPatchState");
|
|
165745
165817
|
function applyPatchState(state, patch, options) {
|
|
165746
165818
|
return applyPatch(state, patch, options?.force);
|
|
165747
165819
|
}
|
|
@@ -165768,23 +165840,23 @@ function applyPatch(state, patch, force = false) {
|
|
|
165768
165840
|
if (errorMessage.includes(
|
|
165769
165841
|
"Endpoint storage inaccessible because endpoint is not a node and is not owned by another endpoint"
|
|
165770
165842
|
)) {
|
|
165771
|
-
|
|
165843
|
+
logger159.debug(
|
|
165772
165844
|
`Suppressed endpoint storage error, patch not applied: ${JSON.stringify(actualPatch)}`
|
|
165773
165845
|
);
|
|
165774
165846
|
return actualPatch;
|
|
165775
165847
|
}
|
|
165776
165848
|
if (errorMessage.includes("synchronous-transaction-conflict")) {
|
|
165777
|
-
|
|
165849
|
+
logger159.warn(
|
|
165778
165850
|
`Transaction conflict, state update DROPPED: ${JSON.stringify(actualPatch)}`
|
|
165779
165851
|
);
|
|
165780
165852
|
return actualPatch;
|
|
165781
165853
|
}
|
|
165782
165854
|
failedKeys.push(key);
|
|
165783
|
-
|
|
165855
|
+
logger159.warn(`Failed to set property '${key}': ${errorMessage}`);
|
|
165784
165856
|
}
|
|
165785
165857
|
}
|
|
165786
165858
|
if (failedKeys.length > 0) {
|
|
165787
|
-
|
|
165859
|
+
logger159.warn(
|
|
165788
165860
|
`${failedKeys.length} properties failed to update: [${failedKeys.join(", ")}]`
|
|
165789
165861
|
);
|
|
165790
165862
|
}
|
|
@@ -165807,56 +165879,6 @@ function deepEqual(a, b) {
|
|
|
165807
165879
|
return a === b;
|
|
165808
165880
|
}
|
|
165809
165881
|
|
|
165810
|
-
// src/matter/behaviors/basic-information-server.ts
|
|
165811
|
-
init_home_assistant_entity_behavior();
|
|
165812
|
-
var BasicInformationServer2 = class extends BridgedDeviceBasicInformationServer {
|
|
165813
|
-
async initialize() {
|
|
165814
|
-
await super.initialize();
|
|
165815
|
-
const homeAssistant = await this.agent.load(HomeAssistantEntityBehavior);
|
|
165816
|
-
this.update(homeAssistant.entity);
|
|
165817
|
-
this.reactTo(homeAssistant.onChange, this.update);
|
|
165818
|
-
}
|
|
165819
|
-
update(entity) {
|
|
165820
|
-
if (!entity.state) {
|
|
165821
|
-
return;
|
|
165822
|
-
}
|
|
165823
|
-
const { basicInformation } = this.env.get(BridgeDataProvider);
|
|
165824
|
-
const homeAssistant = this.agent.get(HomeAssistantEntityBehavior);
|
|
165825
|
-
const device = entity.deviceRegistry;
|
|
165826
|
-
applyPatchState(this.state, {
|
|
165827
|
-
vendorId: VendorId(basicInformation.vendorId),
|
|
165828
|
-
vendorName: ellipse(32, device?.manufacturer) ?? hash(32, basicInformation.vendorName),
|
|
165829
|
-
productName: ellipse(32, device?.model_id) ?? ellipse(32, device?.model) ?? hash(32, basicInformation.productName),
|
|
165830
|
-
productLabel: ellipse(64, device?.model) ?? hash(64, basicInformation.productLabel),
|
|
165831
|
-
hardwareVersion: basicInformation.hardwareVersion,
|
|
165832
|
-
softwareVersion: basicInformation.softwareVersion,
|
|
165833
|
-
hardwareVersionString: ellipse(64, device?.hw_version),
|
|
165834
|
-
softwareVersionString: ellipse(64, device?.sw_version),
|
|
165835
|
-
nodeLabel: ellipse(32, homeAssistant.state.customName) ?? ellipse(32, entity.state?.attributes?.friendly_name) ?? ellipse(32, entity.entity_id),
|
|
165836
|
-
reachable: entity.state?.state != null && entity.state.state !== "unavailable",
|
|
165837
|
-
// The device serial number is available in `device?.serial_number`, but
|
|
165838
|
-
// we're keeping it as the entity ID for now to avoid breaking existing
|
|
165839
|
-
// deployments.
|
|
165840
|
-
serialNumber: hash(32, entity.entity_id),
|
|
165841
|
-
// UniqueId helps controllers (especially Alexa) identify devices across
|
|
165842
|
-
// multiple fabric connections. Using MD5 hash of entity_id for stability.
|
|
165843
|
-
uniqueId: crypto4.createHash("md5").update(entity.entity_id).digest("hex").substring(0, 32)
|
|
165844
|
-
});
|
|
165845
|
-
}
|
|
165846
|
-
};
|
|
165847
|
-
function ellipse(maxLength, value) {
|
|
165848
|
-
return trimToLength(value, maxLength, "...");
|
|
165849
|
-
}
|
|
165850
|
-
function hash(maxLength, value) {
|
|
165851
|
-
const hashLength = 4;
|
|
165852
|
-
const suffix = crypto4.createHash("md5").update(value ?? "").digest("hex").substring(0, hashLength);
|
|
165853
|
-
return trimToLength(value, maxLength, suffix);
|
|
165854
|
-
}
|
|
165855
|
-
|
|
165856
|
-
// src/matter/behaviors/identify-server.ts
|
|
165857
|
-
var IdentifyServer2 = class extends IdentifyServer {
|
|
165858
|
-
};
|
|
165859
|
-
|
|
165860
165882
|
// src/plugins/plugin-behavior.ts
|
|
165861
165883
|
init_esm7();
|
|
165862
165884
|
var PluginDeviceBehavior = class extends Behavior {
|
|
@@ -165880,72 +165902,142 @@ var PluginDeviceBehavior = class extends Behavior {
|
|
|
165880
165902
|
PluginDeviceBehavior2.Events = Events2;
|
|
165881
165903
|
})(PluginDeviceBehavior || (PluginDeviceBehavior = {}));
|
|
165882
165904
|
|
|
165905
|
+
// src/plugins/plugin-basic-information-server.ts
|
|
165906
|
+
var PluginBasicInformationServer = class extends BridgedDeviceBasicInformationServer {
|
|
165907
|
+
async initialize() {
|
|
165908
|
+
await super.initialize();
|
|
165909
|
+
const pluginDevice = this.agent.get(PluginDeviceBehavior);
|
|
165910
|
+
const device = pluginDevice.device;
|
|
165911
|
+
const { basicInformation } = this.env.get(BridgeDataProvider);
|
|
165912
|
+
applyPatchState(this.state, {
|
|
165913
|
+
vendorId: VendorId(basicInformation.vendorId),
|
|
165914
|
+
vendorName: truncate(32, pluginDevice.pluginName),
|
|
165915
|
+
productName: truncate(32, device.deviceType),
|
|
165916
|
+
nodeLabel: truncate(32, device.name),
|
|
165917
|
+
serialNumber: crypto4.createHash("md5").update(`plugin_${device.id}`).digest("hex").substring(0, 32),
|
|
165918
|
+
uniqueId: crypto4.createHash("md5").update(`plugin_${device.id}`).digest("hex").substring(0, 32),
|
|
165919
|
+
reachable: true
|
|
165920
|
+
});
|
|
165921
|
+
}
|
|
165922
|
+
};
|
|
165923
|
+
function truncate(maxLength, value) {
|
|
165924
|
+
if (value.length <= maxLength) return value;
|
|
165925
|
+
return `${value.substring(0, maxLength - 3)}...`;
|
|
165926
|
+
}
|
|
165927
|
+
|
|
165883
165928
|
// src/plugins/plugin-device-factory.ts
|
|
165884
|
-
var
|
|
165929
|
+
var logger160 = Logger.get("PluginDeviceFactory");
|
|
165885
165930
|
var deviceTypeMap = {
|
|
165886
165931
|
on_off_light: () => OnOffLightDevice.with(
|
|
165887
165932
|
IdentifyServer2,
|
|
165888
|
-
|
|
165933
|
+
PluginBasicInformationServer,
|
|
165889
165934
|
PluginDeviceBehavior
|
|
165890
165935
|
),
|
|
165891
165936
|
dimmable_light: () => DimmableLightDevice.with(
|
|
165892
165937
|
IdentifyServer2,
|
|
165893
|
-
|
|
165938
|
+
PluginBasicInformationServer,
|
|
165939
|
+
PluginDeviceBehavior
|
|
165940
|
+
),
|
|
165941
|
+
color_temperature_light: () => ColorTemperatureLightDevice.with(
|
|
165942
|
+
IdentifyServer2,
|
|
165943
|
+
PluginBasicInformationServer,
|
|
165944
|
+
PluginDeviceBehavior
|
|
165945
|
+
),
|
|
165946
|
+
extended_color_light: () => ExtendedColorLightDevice.with(
|
|
165947
|
+
IdentifyServer2,
|
|
165948
|
+
PluginBasicInformationServer,
|
|
165894
165949
|
PluginDeviceBehavior
|
|
165895
165950
|
),
|
|
165896
165951
|
on_off_plugin_unit: () => OnOffPlugInUnitDevice.with(
|
|
165897
165952
|
IdentifyServer2,
|
|
165898
|
-
|
|
165953
|
+
PluginBasicInformationServer,
|
|
165954
|
+
PluginDeviceBehavior
|
|
165955
|
+
),
|
|
165956
|
+
dimmable_plug_in_unit: () => DimmablePlugInUnitDevice.with(
|
|
165957
|
+
IdentifyServer2,
|
|
165958
|
+
PluginBasicInformationServer,
|
|
165899
165959
|
PluginDeviceBehavior
|
|
165900
165960
|
),
|
|
165901
165961
|
temperature_sensor: () => TemperatureSensorDevice.with(
|
|
165902
165962
|
IdentifyServer2,
|
|
165903
|
-
|
|
165963
|
+
PluginBasicInformationServer,
|
|
165904
165964
|
PluginDeviceBehavior
|
|
165905
165965
|
),
|
|
165906
165966
|
humidity_sensor: () => HumiditySensorDevice.with(
|
|
165907
165967
|
IdentifyServer2,
|
|
165908
|
-
|
|
165968
|
+
PluginBasicInformationServer,
|
|
165969
|
+
PluginDeviceBehavior
|
|
165970
|
+
),
|
|
165971
|
+
pressure_sensor: () => PressureSensorDevice.with(
|
|
165972
|
+
IdentifyServer2,
|
|
165973
|
+
PluginBasicInformationServer,
|
|
165974
|
+
PluginDeviceBehavior
|
|
165975
|
+
),
|
|
165976
|
+
flow_sensor: () => FlowSensorDevice.with(
|
|
165977
|
+
IdentifyServer2,
|
|
165978
|
+
PluginBasicInformationServer,
|
|
165909
165979
|
PluginDeviceBehavior
|
|
165910
165980
|
),
|
|
165911
165981
|
light_sensor: () => LightSensorDevice.with(
|
|
165912
165982
|
IdentifyServer2,
|
|
165913
|
-
|
|
165983
|
+
PluginBasicInformationServer,
|
|
165914
165984
|
PluginDeviceBehavior
|
|
165915
165985
|
),
|
|
165916
165986
|
occupancy_sensor: () => OccupancySensorDevice.with(
|
|
165917
165987
|
IdentifyServer2,
|
|
165918
|
-
|
|
165988
|
+
PluginBasicInformationServer,
|
|
165919
165989
|
PluginDeviceBehavior
|
|
165920
165990
|
),
|
|
165921
165991
|
contact_sensor: () => ContactSensorDevice.with(
|
|
165922
165992
|
IdentifyServer2,
|
|
165923
|
-
|
|
165993
|
+
PluginBasicInformationServer,
|
|
165994
|
+
PluginDeviceBehavior
|
|
165995
|
+
),
|
|
165996
|
+
air_quality_sensor: () => AirQualitySensorDevice.with(
|
|
165997
|
+
IdentifyServer2,
|
|
165998
|
+
PluginBasicInformationServer,
|
|
165924
165999
|
PluginDeviceBehavior
|
|
165925
166000
|
),
|
|
165926
166001
|
thermostat: () => ThermostatDevice.with(
|
|
165927
166002
|
IdentifyServer2,
|
|
165928
|
-
|
|
166003
|
+
PluginBasicInformationServer,
|
|
165929
166004
|
PluginDeviceBehavior
|
|
165930
166005
|
),
|
|
165931
166006
|
door_lock: () => DoorLockDevice.with(
|
|
165932
166007
|
IdentifyServer2,
|
|
165933
|
-
|
|
166008
|
+
PluginBasicInformationServer,
|
|
165934
166009
|
PluginDeviceBehavior
|
|
165935
166010
|
),
|
|
165936
166011
|
fan: () => FanDevice.with(
|
|
165937
166012
|
IdentifyServer2,
|
|
165938
|
-
|
|
166013
|
+
PluginBasicInformationServer,
|
|
166014
|
+
PluginDeviceBehavior
|
|
166015
|
+
),
|
|
166016
|
+
window_covering: () => WindowCoveringDevice.with(
|
|
166017
|
+
IdentifyServer2,
|
|
166018
|
+
PluginBasicInformationServer,
|
|
166019
|
+
PluginDeviceBehavior
|
|
166020
|
+
),
|
|
166021
|
+
generic_switch: () => GenericSwitchDevice.with(
|
|
166022
|
+
IdentifyServer2,
|
|
166023
|
+
PluginBasicInformationServer,
|
|
166024
|
+
PluginDeviceBehavior
|
|
166025
|
+
),
|
|
166026
|
+
water_leak_detector: () => WaterLeakDetectorDevice.with(
|
|
166027
|
+
IdentifyServer2,
|
|
166028
|
+
PluginBasicInformationServer,
|
|
165939
166029
|
PluginDeviceBehavior
|
|
165940
166030
|
)
|
|
165941
166031
|
};
|
|
165942
166032
|
function createPluginEndpointType(deviceType) {
|
|
165943
166033
|
const factory = deviceTypeMap[deviceType];
|
|
165944
166034
|
if (!factory) {
|
|
165945
|
-
|
|
166035
|
+
logger160.warn(`Unsupported plugin device type: "${deviceType}"`);
|
|
165946
166036
|
return void 0;
|
|
165947
166037
|
}
|
|
165948
|
-
|
|
166038
|
+
const endpoint = factory();
|
|
166039
|
+
validateEndpointType(endpoint, `plugin:${deviceType}`);
|
|
166040
|
+
return endpoint;
|
|
165949
166041
|
}
|
|
165950
166042
|
function getSupportedPluginDeviceTypes() {
|
|
165951
166043
|
return Object.keys(deviceTypeMap);
|
|
@@ -165955,11 +166047,13 @@ function getSupportedPluginDeviceTypes() {
|
|
|
165955
166047
|
init_esm();
|
|
165956
166048
|
import * as fs10 from "node:fs";
|
|
165957
166049
|
import * as path11 from "node:path";
|
|
165958
|
-
var
|
|
166050
|
+
var logger161 = Logger.get("PluginStorage");
|
|
166051
|
+
var SAVE_DEBOUNCE_MS = 500;
|
|
165959
166052
|
var FilePluginStorage = class {
|
|
165960
166053
|
data = {};
|
|
165961
166054
|
dirty = false;
|
|
165962
166055
|
filePath;
|
|
166056
|
+
saveTimer;
|
|
165963
166057
|
constructor(storageDir, pluginName) {
|
|
165964
166058
|
const safePluginName = pluginName.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
165965
166059
|
this.filePath = path11.join(storageDir, `plugin-${safePluginName}.json`);
|
|
@@ -165972,12 +166066,12 @@ var FilePluginStorage = class {
|
|
|
165972
166066
|
async set(key, value) {
|
|
165973
166067
|
this.data[key] = value;
|
|
165974
166068
|
this.dirty = true;
|
|
165975
|
-
this.
|
|
166069
|
+
this.scheduleSave();
|
|
165976
166070
|
}
|
|
165977
166071
|
async delete(key) {
|
|
165978
166072
|
delete this.data[key];
|
|
165979
166073
|
this.dirty = true;
|
|
165980
|
-
this.
|
|
166074
|
+
this.scheduleSave();
|
|
165981
166075
|
}
|
|
165982
166076
|
async keys() {
|
|
165983
166077
|
return Object.keys(this.data);
|
|
@@ -165989,12 +166083,20 @@ var FilePluginStorage = class {
|
|
|
165989
166083
|
this.data = JSON.parse(raw);
|
|
165990
166084
|
}
|
|
165991
166085
|
} catch (e) {
|
|
165992
|
-
|
|
166086
|
+
logger161.warn(`Failed to load plugin storage from ${this.filePath}:`, e);
|
|
165993
166087
|
this.data = {};
|
|
165994
166088
|
}
|
|
165995
166089
|
}
|
|
166090
|
+
scheduleSave() {
|
|
166091
|
+
if (this.saveTimer) clearTimeout(this.saveTimer);
|
|
166092
|
+
this.saveTimer = setTimeout(() => this.save(), SAVE_DEBOUNCE_MS);
|
|
166093
|
+
}
|
|
165996
166094
|
save() {
|
|
165997
166095
|
if (!this.dirty) return;
|
|
166096
|
+
if (this.saveTimer) {
|
|
166097
|
+
clearTimeout(this.saveTimer);
|
|
166098
|
+
this.saveTimer = void 0;
|
|
166099
|
+
}
|
|
165998
166100
|
try {
|
|
165999
166101
|
const dir = path11.dirname(this.filePath);
|
|
166000
166102
|
if (!fs10.existsSync(dir)) {
|
|
@@ -166003,14 +166105,17 @@ var FilePluginStorage = class {
|
|
|
166003
166105
|
fs10.writeFileSync(this.filePath, JSON.stringify(this.data, null, 2));
|
|
166004
166106
|
this.dirty = false;
|
|
166005
166107
|
} catch (e) {
|
|
166006
|
-
|
|
166108
|
+
logger161.warn(`Failed to save plugin storage to ${this.filePath}:`, e);
|
|
166007
166109
|
}
|
|
166008
166110
|
}
|
|
166111
|
+
flush() {
|
|
166112
|
+
this.save();
|
|
166113
|
+
}
|
|
166009
166114
|
};
|
|
166010
166115
|
|
|
166011
166116
|
// src/plugins/safe-plugin-runner.ts
|
|
166012
166117
|
init_esm();
|
|
166013
|
-
var
|
|
166118
|
+
var logger162 = Logger.get("SafePluginRunner");
|
|
166014
166119
|
var DEFAULT_TIMEOUT_MS = 1e4;
|
|
166015
166120
|
var CIRCUIT_BREAKER_THRESHOLD = 3;
|
|
166016
166121
|
var SafePluginRunner = class {
|
|
@@ -166043,7 +166148,7 @@ var SafePluginRunner = class {
|
|
|
166043
166148
|
async run(pluginName, operation, fn, timeoutMs = DEFAULT_TIMEOUT_MS) {
|
|
166044
166149
|
const state = this.getState(pluginName);
|
|
166045
166150
|
if (state.disabled) {
|
|
166046
|
-
|
|
166151
|
+
logger162.debug(
|
|
166047
166152
|
`Plugin "${pluginName}" is disabled (circuit breaker open), skipping ${operation}`
|
|
166048
166153
|
);
|
|
166049
166154
|
return void 0;
|
|
@@ -166061,13 +166166,13 @@ var SafePluginRunner = class {
|
|
|
166061
166166
|
timeout.clear();
|
|
166062
166167
|
state.failures++;
|
|
166063
166168
|
state.lastError = error instanceof Error ? error.message : String(error);
|
|
166064
|
-
|
|
166169
|
+
logger162.error(
|
|
166065
166170
|
`Plugin "${pluginName}" failed during ${operation} (failure ${state.failures}/${CIRCUIT_BREAKER_THRESHOLD}): ${state.lastError}`
|
|
166066
166171
|
);
|
|
166067
166172
|
if (state.failures >= CIRCUIT_BREAKER_THRESHOLD) {
|
|
166068
166173
|
state.disabled = true;
|
|
166069
166174
|
state.disabledAt = Date.now();
|
|
166070
|
-
|
|
166175
|
+
logger162.error(
|
|
166071
166176
|
`Plugin "${pluginName}" DISABLED after ${CIRCUIT_BREAKER_THRESHOLD} consecutive failures. Last error: ${state.lastError}`
|
|
166072
166177
|
);
|
|
166073
166178
|
}
|
|
@@ -166089,13 +166194,13 @@ var SafePluginRunner = class {
|
|
|
166089
166194
|
} catch (error) {
|
|
166090
166195
|
state.failures++;
|
|
166091
166196
|
state.lastError = error instanceof Error ? error.message : String(error);
|
|
166092
|
-
|
|
166197
|
+
logger162.error(
|
|
166093
166198
|
`Plugin "${pluginName}" failed during ${operation} (sync, failure ${state.failures}/${CIRCUIT_BREAKER_THRESHOLD}): ${state.lastError}`
|
|
166094
166199
|
);
|
|
166095
166200
|
if (state.failures >= CIRCUIT_BREAKER_THRESHOLD) {
|
|
166096
166201
|
state.disabled = true;
|
|
166097
166202
|
state.disabledAt = Date.now();
|
|
166098
|
-
|
|
166203
|
+
logger162.error(
|
|
166099
166204
|
`Plugin "${pluginName}" DISABLED after ${CIRCUIT_BREAKER_THRESHOLD} consecutive failures.`
|
|
166100
166205
|
);
|
|
166101
166206
|
}
|
|
@@ -166121,12 +166226,16 @@ var SafePluginRunner = class {
|
|
|
166121
166226
|
};
|
|
166122
166227
|
|
|
166123
166228
|
// src/plugins/plugin-manager.ts
|
|
166124
|
-
var
|
|
166229
|
+
var logger163 = Logger.get("PluginManager");
|
|
166230
|
+
var PLUGIN_API_VERSION = 1;
|
|
166231
|
+
var MAX_PLUGIN_DEVICE_ID_LENGTH = 100;
|
|
166125
166232
|
function validatePluginDevice(device) {
|
|
166126
166233
|
if (!device || typeof device !== "object") return "device must be an object";
|
|
166127
166234
|
const d = device;
|
|
166128
166235
|
if (!d.id || typeof d.id !== "string")
|
|
166129
166236
|
return "device.id must be a non-empty string";
|
|
166237
|
+
if (d.id.length > MAX_PLUGIN_DEVICE_ID_LENGTH)
|
|
166238
|
+
return `device.id too long (${d.id.length} chars, max ${MAX_PLUGIN_DEVICE_ID_LENGTH})`;
|
|
166130
166239
|
if (!d.name || typeof d.name !== "string")
|
|
166131
166240
|
return "device.name must be a non-empty string";
|
|
166132
166241
|
if (!d.deviceType || typeof d.deviceType !== "string")
|
|
@@ -166193,6 +166302,11 @@ var PluginManager = class {
|
|
|
166193
166302
|
if (!manifest.main || typeof manifest.main !== "string") {
|
|
166194
166303
|
throw new Error(`Plugin at ${packagePath} package.json missing "main"`);
|
|
166195
166304
|
}
|
|
166305
|
+
if (manifest.hamhPluginApiVersion != null && manifest.hamhPluginApiVersion !== PLUGIN_API_VERSION) {
|
|
166306
|
+
logger163.warn(
|
|
166307
|
+
`Plugin "${manifest.name}" declares API version ${manifest.hamhPluginApiVersion}, current is ${PLUGIN_API_VERSION}. It may not work correctly.`
|
|
166308
|
+
);
|
|
166309
|
+
}
|
|
166196
166310
|
const module = await this.runner.run(
|
|
166197
166311
|
manifest.name,
|
|
166198
166312
|
"import",
|
|
@@ -166220,7 +166334,7 @@ var PluginManager = class {
|
|
|
166220
166334
|
};
|
|
166221
166335
|
await this.register(plugin, metadata);
|
|
166222
166336
|
} catch (e) {
|
|
166223
|
-
|
|
166337
|
+
logger163.error(`Failed to load external plugin from ${packagePath}:`, e);
|
|
166224
166338
|
throw e;
|
|
166225
166339
|
}
|
|
166226
166340
|
}
|
|
@@ -166281,7 +166395,7 @@ var PluginManager = class {
|
|
|
166281
166395
|
devices,
|
|
166282
166396
|
started: false
|
|
166283
166397
|
});
|
|
166284
|
-
|
|
166398
|
+
logger163.info(
|
|
166285
166399
|
`Registered plugin: ${plugin.name} v${plugin.version} (${metadata.source})`
|
|
166286
166400
|
);
|
|
166287
166401
|
}
|
|
@@ -166292,13 +166406,13 @@ var PluginManager = class {
|
|
|
166292
166406
|
for (const [name, instance] of this.instances) {
|
|
166293
166407
|
if (!instance.metadata.enabled) continue;
|
|
166294
166408
|
if (this.runner.isDisabled(name)) {
|
|
166295
|
-
|
|
166409
|
+
logger163.warn(
|
|
166296
166410
|
`Plugin "${name}" is disabled (circuit breaker), skipping start`
|
|
166297
166411
|
);
|
|
166298
166412
|
instance.metadata.enabled = false;
|
|
166299
166413
|
continue;
|
|
166300
166414
|
}
|
|
166301
|
-
|
|
166415
|
+
logger163.info(`Starting plugin: ${name}`);
|
|
166302
166416
|
await this.runner.run(
|
|
166303
166417
|
name,
|
|
166304
166418
|
"onStart",
|
|
@@ -166341,8 +166455,12 @@ var PluginManager = class {
|
|
|
166341
166455
|
() => instance.plugin.onShutdown(reason)
|
|
166342
166456
|
);
|
|
166343
166457
|
}
|
|
166458
|
+
const storage2 = instance.context.storage;
|
|
166459
|
+
if (storage2 instanceof FilePluginStorage) {
|
|
166460
|
+
storage2.flush();
|
|
166461
|
+
}
|
|
166344
166462
|
instance.started = false;
|
|
166345
|
-
|
|
166463
|
+
logger163.info(`Plugin "${name}" shut down`);
|
|
166346
166464
|
}
|
|
166347
166465
|
this.instances.clear();
|
|
166348
166466
|
}
|
|
@@ -167304,13 +167422,61 @@ function testBit(value, bitValue) {
|
|
|
167304
167422
|
return !!(value & bitValue);
|
|
167305
167423
|
}
|
|
167306
167424
|
|
|
167425
|
+
// src/matter/behaviors/basic-information-server.ts
|
|
167426
|
+
init_esm7();
|
|
167427
|
+
import crypto6 from "node:crypto";
|
|
167428
|
+
init_home_assistant_entity_behavior();
|
|
167429
|
+
var BasicInformationServer2 = class extends BridgedDeviceBasicInformationServer {
|
|
167430
|
+
async initialize() {
|
|
167431
|
+
await super.initialize();
|
|
167432
|
+
const homeAssistant = await this.agent.load(HomeAssistantEntityBehavior);
|
|
167433
|
+
this.update(homeAssistant.entity);
|
|
167434
|
+
this.reactTo(homeAssistant.onChange, this.update);
|
|
167435
|
+
}
|
|
167436
|
+
update(entity) {
|
|
167437
|
+
if (!entity.state) {
|
|
167438
|
+
return;
|
|
167439
|
+
}
|
|
167440
|
+
const { basicInformation } = this.env.get(BridgeDataProvider);
|
|
167441
|
+
const homeAssistant = this.agent.get(HomeAssistantEntityBehavior);
|
|
167442
|
+
const device = entity.deviceRegistry;
|
|
167443
|
+
applyPatchState(this.state, {
|
|
167444
|
+
vendorId: VendorId(basicInformation.vendorId),
|
|
167445
|
+
vendorName: ellipse(32, device?.manufacturer) ?? hash(32, basicInformation.vendorName),
|
|
167446
|
+
productName: ellipse(32, device?.model_id) ?? ellipse(32, device?.model) ?? hash(32, basicInformation.productName),
|
|
167447
|
+
productLabel: ellipse(64, device?.model) ?? hash(64, basicInformation.productLabel),
|
|
167448
|
+
hardwareVersion: basicInformation.hardwareVersion,
|
|
167449
|
+
softwareVersion: basicInformation.softwareVersion,
|
|
167450
|
+
hardwareVersionString: ellipse(64, device?.hw_version),
|
|
167451
|
+
softwareVersionString: ellipse(64, device?.sw_version),
|
|
167452
|
+
nodeLabel: ellipse(32, homeAssistant.state.customName) ?? ellipse(32, entity.state?.attributes?.friendly_name) ?? ellipse(32, entity.entity_id),
|
|
167453
|
+
reachable: entity.state?.state != null && entity.state.state !== "unavailable",
|
|
167454
|
+
// The device serial number is available in `device?.serial_number`, but
|
|
167455
|
+
// we're keeping it as the entity ID for now to avoid breaking existing
|
|
167456
|
+
// deployments.
|
|
167457
|
+
serialNumber: hash(32, entity.entity_id),
|
|
167458
|
+
// UniqueId helps controllers (especially Alexa) identify devices across
|
|
167459
|
+
// multiple fabric connections. Using MD5 hash of entity_id for stability.
|
|
167460
|
+
uniqueId: crypto6.createHash("md5").update(entity.entity_id).digest("hex").substring(0, 32)
|
|
167461
|
+
});
|
|
167462
|
+
}
|
|
167463
|
+
};
|
|
167464
|
+
function ellipse(maxLength, value) {
|
|
167465
|
+
return trimToLength(value, maxLength, "...");
|
|
167466
|
+
}
|
|
167467
|
+
function hash(maxLength, value) {
|
|
167468
|
+
const hashLength = 4;
|
|
167469
|
+
const suffix = crypto6.createHash("md5").update(value ?? "").digest("hex").substring(0, hashLength);
|
|
167470
|
+
return trimToLength(value, maxLength, suffix);
|
|
167471
|
+
}
|
|
167472
|
+
|
|
167307
167473
|
// src/matter/endpoints/composed/composed-air-purifier-endpoint.ts
|
|
167308
167474
|
init_home_assistant_entity_behavior();
|
|
167309
167475
|
|
|
167310
167476
|
// src/matter/behaviors/humidity-measurement-server.ts
|
|
167311
167477
|
init_esm();
|
|
167312
167478
|
init_home_assistant_entity_behavior();
|
|
167313
|
-
var
|
|
167479
|
+
var logger164 = Logger.get("HumidityMeasurementServer");
|
|
167314
167480
|
var HumidityMeasurementServerBase = class extends RelativeHumidityMeasurementServer {
|
|
167315
167481
|
async initialize() {
|
|
167316
167482
|
await super.initialize();
|
|
@@ -167323,7 +167489,7 @@ var HumidityMeasurementServerBase = class extends RelativeHumidityMeasurementSer
|
|
|
167323
167489
|
return;
|
|
167324
167490
|
}
|
|
167325
167491
|
const humidity = this.getHumidity(this.state.config, entity.state);
|
|
167326
|
-
|
|
167492
|
+
logger164.debug(
|
|
167327
167493
|
`Humidity ${entity.state.entity_id} raw=${entity.state.state} measuredValue=${humidity}`
|
|
167328
167494
|
);
|
|
167329
167495
|
applyPatchState(this.state, {
|
|
@@ -167359,7 +167525,7 @@ init_clusters();
|
|
|
167359
167525
|
|
|
167360
167526
|
// src/matter/behaviors/power-source-server.ts
|
|
167361
167527
|
init_home_assistant_entity_behavior();
|
|
167362
|
-
var
|
|
167528
|
+
var logger165 = Logger.get("PowerSourceServer");
|
|
167363
167529
|
var FeaturedBase = PowerSourceServer.with("Battery", "Rechargeable");
|
|
167364
167530
|
var PowerSourceServerBase = class extends FeaturedBase {
|
|
167365
167531
|
async initialize() {
|
|
@@ -167371,17 +167537,17 @@ var PowerSourceServerBase = class extends FeaturedBase {
|
|
|
167371
167537
|
applyPatchState(this.state, {
|
|
167372
167538
|
endpointList: [endpointNumber]
|
|
167373
167539
|
});
|
|
167374
|
-
|
|
167540
|
+
logger165.debug(
|
|
167375
167541
|
`[${entityId}] PowerSource initialized with endpointList=[${endpointNumber}]`
|
|
167376
167542
|
);
|
|
167377
167543
|
} else {
|
|
167378
|
-
|
|
167544
|
+
logger165.warn(
|
|
167379
167545
|
`[${entityId}] PowerSource endpoint number is null during initialize - endpointList will be empty!`
|
|
167380
167546
|
);
|
|
167381
167547
|
}
|
|
167382
167548
|
const batteryEntity = homeAssistant.state.mapping?.batteryEntity;
|
|
167383
167549
|
if (batteryEntity) {
|
|
167384
|
-
|
|
167550
|
+
logger165.debug(
|
|
167385
167551
|
`[${entityId}] PowerSource using mapped battery entity: ${batteryEntity}`
|
|
167386
167552
|
);
|
|
167387
167553
|
}
|
|
@@ -167688,7 +167854,7 @@ var OPTIMISTIC_TOLERANCE = 5;
|
|
|
167688
167854
|
function notifyLightTurnedOn(entityId) {
|
|
167689
167855
|
lastTurnOnTimestamps.set(entityId, Date.now());
|
|
167690
167856
|
}
|
|
167691
|
-
var
|
|
167857
|
+
var logger166 = Logger.get("LevelControlServer");
|
|
167692
167858
|
var FeaturedBase3 = LevelControlServer.with("OnOff", "Lighting");
|
|
167693
167859
|
var LevelControlServerBase = class extends FeaturedBase3 {
|
|
167694
167860
|
pendingTransitionTime;
|
|
@@ -167703,12 +167869,12 @@ var LevelControlServerBase = class extends FeaturedBase3 {
|
|
|
167703
167869
|
this.state.maxLevel = 254;
|
|
167704
167870
|
}
|
|
167705
167871
|
this.state.onLevel = null;
|
|
167706
|
-
|
|
167872
|
+
logger166.debug(`initialize: calling super.initialize()`);
|
|
167707
167873
|
try {
|
|
167708
167874
|
await super.initialize();
|
|
167709
|
-
|
|
167875
|
+
logger166.debug(`initialize: super.initialize() completed successfully`);
|
|
167710
167876
|
} catch (error) {
|
|
167711
|
-
|
|
167877
|
+
logger166.error(`initialize: super.initialize() FAILED:`, error);
|
|
167712
167878
|
throw error;
|
|
167713
167879
|
}
|
|
167714
167880
|
const homeAssistant = await this.agent.load(HomeAssistantEntityBehavior);
|
|
@@ -167784,7 +167950,7 @@ var LevelControlServerBase = class extends FeaturedBase3 {
|
|
|
167784
167950
|
const timeSinceTurnOn = lastTurnOn ? Date.now() - lastTurnOn : Infinity;
|
|
167785
167951
|
const isMaxBrightness = level >= this.maxLevel;
|
|
167786
167952
|
if (isMaxBrightness && timeSinceTurnOn < 200) {
|
|
167787
|
-
|
|
167953
|
+
logger166.debug(
|
|
167788
167954
|
`[${entityId}] Ignoring moveToLevel(${level}) - Alexa brightness reset detected (${timeSinceTurnOn}ms after turn-on)`
|
|
167789
167955
|
);
|
|
167790
167956
|
return;
|
|
@@ -167827,7 +167993,7 @@ function LevelControlServer2(config10) {
|
|
|
167827
167993
|
}
|
|
167828
167994
|
|
|
167829
167995
|
// src/matter/behaviors/on-off-server.ts
|
|
167830
|
-
var
|
|
167996
|
+
var logger167 = Logger.get("OnOffServer");
|
|
167831
167997
|
var optimisticOnOffState = /* @__PURE__ */ new Map();
|
|
167832
167998
|
var OPTIMISTIC_TIMEOUT_MS2 = 3e3;
|
|
167833
167999
|
var OnOffServerBase = class extends OnOffServer {
|
|
@@ -167865,7 +168031,7 @@ var OnOffServerBase = class extends OnOffServer {
|
|
|
167865
168031
|
const action = turnOn?.(void 0, this.agent) ?? {
|
|
167866
168032
|
action: "homeassistant.turn_on"
|
|
167867
168033
|
};
|
|
167868
|
-
|
|
168034
|
+
logger167.info(`[${homeAssistant.entityId}] Turning ON -> ${action.action}`);
|
|
167869
168035
|
notifyLightTurnedOn(homeAssistant.entityId);
|
|
167870
168036
|
applyPatchState(this.state, { onOff: true });
|
|
167871
168037
|
optimisticOnOffState.set(homeAssistant.entityId, {
|
|
@@ -167887,7 +168053,7 @@ var OnOffServerBase = class extends OnOffServer {
|
|
|
167887
168053
|
const action = turnOff?.(void 0, this.agent) ?? {
|
|
167888
168054
|
action: "homeassistant.turn_off"
|
|
167889
168055
|
};
|
|
167890
|
-
|
|
168056
|
+
logger167.info(`[${homeAssistant.entityId}] Turning OFF -> ${action.action}`);
|
|
167891
168057
|
applyPatchState(this.state, { onOff: false });
|
|
167892
168058
|
optimisticOnOffState.set(homeAssistant.entityId, {
|
|
167893
168059
|
expectedOnOff: false,
|
|
@@ -167897,6 +168063,7 @@ var OnOffServerBase = class extends OnOffServer {
|
|
|
167897
168063
|
}
|
|
167898
168064
|
autoReset() {
|
|
167899
168065
|
const homeAssistant = this.agent.get(HomeAssistantEntityBehavior);
|
|
168066
|
+
optimisticOnOffState.delete(homeAssistant.entityId);
|
|
167900
168067
|
this.update(homeAssistant.entity);
|
|
167901
168068
|
}
|
|
167902
168069
|
};
|
|
@@ -167917,7 +168084,7 @@ function setOptimisticOnOff(entityId, expectedOnOff) {
|
|
|
167917
168084
|
}
|
|
167918
168085
|
|
|
167919
168086
|
// src/matter/behaviors/fan-control-server.ts
|
|
167920
|
-
var
|
|
168087
|
+
var logger168 = Logger.get("FanControlServer");
|
|
167921
168088
|
var defaultStepSize = 33.33;
|
|
167922
168089
|
var minSpeedMax = 3;
|
|
167923
168090
|
var maxSpeedMax = 100;
|
|
@@ -168276,7 +168443,7 @@ var FanControlServerBase = class extends FeaturedBase4 {
|
|
|
168276
168443
|
const entityId = this.agent.get(HomeAssistantEntityBehavior).entity.entity_id;
|
|
168277
168444
|
setOptimisticOnOff(entityId, on);
|
|
168278
168445
|
} catch (e) {
|
|
168279
|
-
|
|
168446
|
+
logger168.debug(
|
|
168280
168447
|
`syncOnOff(${on}) failed: ${e instanceof Error ? e.message : String(e)}`
|
|
168281
168448
|
);
|
|
168282
168449
|
}
|
|
@@ -168364,7 +168531,7 @@ var FanOnOffServer = OnOffServer2({
|
|
|
168364
168531
|
});
|
|
168365
168532
|
|
|
168366
168533
|
// src/matter/endpoints/composed/composed-air-purifier-endpoint.ts
|
|
168367
|
-
var
|
|
168534
|
+
var logger169 = Logger.get("ComposedAirPurifierEndpoint");
|
|
168368
168535
|
function createTemperatureConfig(temperatureEntityId) {
|
|
168369
168536
|
return {
|
|
168370
168537
|
getValue(_entity, agent) {
|
|
@@ -168522,7 +168689,7 @@ var ComposedAirPurifierEndpoint = class _ComposedAirPurifierEndpoint extends End
|
|
|
168522
168689
|
config10.humidityEntityId ? "+Hum" : "",
|
|
168523
168690
|
config10.batteryEntityId ? "+Bat" : ""
|
|
168524
168691
|
].filter(Boolean).join("");
|
|
168525
|
-
|
|
168692
|
+
logger169.info(`Created air purifier ${primaryEntityId}: ${clusterLabels}`);
|
|
168526
168693
|
return endpoint;
|
|
168527
168694
|
}
|
|
168528
168695
|
constructor(type, entityId, id, trackedEntityIds, mappedEntityIds) {
|
|
@@ -168618,7 +168785,7 @@ init_home_assistant_entity_behavior();
|
|
|
168618
168785
|
// src/matter/behaviors/pressure-measurement-server.ts
|
|
168619
168786
|
init_esm();
|
|
168620
168787
|
init_home_assistant_entity_behavior();
|
|
168621
|
-
var
|
|
168788
|
+
var logger170 = Logger.get("PressureMeasurementServer");
|
|
168622
168789
|
var MIN_PRESSURE = 300;
|
|
168623
168790
|
var MAX_PRESSURE = 1100;
|
|
168624
168791
|
var PressureMeasurementServerBase = class extends PressureMeasurementServer {
|
|
@@ -168646,7 +168813,7 @@ var PressureMeasurementServerBase = class extends PressureMeasurementServer {
|
|
|
168646
168813
|
}
|
|
168647
168814
|
const rounded = Math.round(value);
|
|
168648
168815
|
if (rounded < MIN_PRESSURE || rounded > MAX_PRESSURE) {
|
|
168649
|
-
|
|
168816
|
+
logger170.warn(
|
|
168650
168817
|
`Pressure value ${rounded} (raw: ${value}) for ${entity.entity_id} is outside valid range [${MIN_PRESSURE}-${MAX_PRESSURE}], ignoring`
|
|
168651
168818
|
);
|
|
168652
168819
|
return null;
|
|
@@ -168665,7 +168832,7 @@ function PressureMeasurementServer2(config10) {
|
|
|
168665
168832
|
}
|
|
168666
168833
|
|
|
168667
168834
|
// src/matter/endpoints/composed/composed-sensor-endpoint.ts
|
|
168668
|
-
var
|
|
168835
|
+
var logger171 = Logger.get("ComposedSensorEndpoint");
|
|
168669
168836
|
var temperatureConfig = {
|
|
168670
168837
|
getValue(entity, agent) {
|
|
168671
168838
|
const fallbackUnit = agent.env.get(HomeAssistantConfig).unitSystem.temperature;
|
|
@@ -168829,7 +168996,7 @@ var ComposedSensorEndpoint = class _ComposedSensorEndpoint extends Endpoint {
|
|
|
168829
168996
|
if (config10.pressureEntityId && pressSub) {
|
|
168830
168997
|
endpoint.subEndpoints.set(config10.pressureEntityId, pressSub);
|
|
168831
168998
|
}
|
|
168832
|
-
|
|
168999
|
+
logger171.info(
|
|
168833
169000
|
`Created composed sensor ${primaryEntityId} with ${parts.length} sub-endpoint(s): T${humSub ? "+H" : ""}${pressSub ? "+P" : ""}${config10.batteryEntityId ? "+Bat" : ""}`
|
|
168834
169001
|
);
|
|
168835
169002
|
return endpoint;
|
|
@@ -168897,57 +169064,6 @@ var ComposedSensorEndpoint = class _ComposedSensorEndpoint extends Endpoint {
|
|
|
168897
169064
|
}
|
|
168898
169065
|
};
|
|
168899
169066
|
|
|
168900
|
-
// src/matter/endpoints/validate-endpoint-type.ts
|
|
168901
|
-
init_esm();
|
|
168902
|
-
init_esm7();
|
|
168903
|
-
var logger171 = Logger.get("EndpointValidation");
|
|
168904
|
-
function toCamelCase(name) {
|
|
168905
|
-
return name.charAt(0).toLowerCase() + name.slice(1);
|
|
168906
|
-
}
|
|
168907
|
-
function validateEndpointType(endpointType, entityId) {
|
|
168908
|
-
const deviceTypeModel = Matter.deviceTypes.find(
|
|
168909
|
-
(dt) => dt.id === endpointType.deviceType
|
|
168910
|
-
);
|
|
168911
|
-
if (!deviceTypeModel) {
|
|
168912
|
-
return void 0;
|
|
168913
|
-
}
|
|
168914
|
-
const serverClusterReqs = deviceTypeModel.requirements.filter(
|
|
168915
|
-
(r) => r.element === "serverCluster"
|
|
168916
|
-
);
|
|
168917
|
-
const behaviorKeys = new Set(Object.keys(endpointType.behaviors));
|
|
168918
|
-
const missingMandatory = [];
|
|
168919
|
-
const availableOptional = [];
|
|
168920
|
-
const presentClusters = [];
|
|
168921
|
-
for (const req of serverClusterReqs) {
|
|
168922
|
-
const key = toCamelCase(req.name);
|
|
168923
|
-
if (behaviorKeys.has(key)) {
|
|
168924
|
-
presentClusters.push(req.name);
|
|
168925
|
-
} else if (req.isMandatory) {
|
|
168926
|
-
missingMandatory.push(req.name);
|
|
168927
|
-
} else {
|
|
168928
|
-
availableOptional.push(req.name);
|
|
168929
|
-
}
|
|
168930
|
-
}
|
|
168931
|
-
const prefix = entityId ? `[${entityId}] ` : "";
|
|
168932
|
-
if (missingMandatory.length > 0) {
|
|
168933
|
-
logger171.warn(
|
|
168934
|
-
`${prefix}${deviceTypeModel.name} (0x${endpointType.deviceType.toString(16)}): missing mandatory clusters: ${missingMandatory.join(", ")}`
|
|
168935
|
-
);
|
|
168936
|
-
}
|
|
168937
|
-
if (availableOptional.length > 0) {
|
|
168938
|
-
logger171.debug(
|
|
168939
|
-
`${prefix}${deviceTypeModel.name} (0x${endpointType.deviceType.toString(16)}): optional clusters not used: ${availableOptional.join(", ")}`
|
|
168940
|
-
);
|
|
168941
|
-
}
|
|
168942
|
-
return {
|
|
168943
|
-
deviceTypeName: deviceTypeModel.name,
|
|
168944
|
-
deviceTypeId: endpointType.deviceType,
|
|
168945
|
-
missingMandatory,
|
|
168946
|
-
availableOptional,
|
|
168947
|
-
presentClusters
|
|
168948
|
-
};
|
|
168949
|
-
}
|
|
168950
|
-
|
|
168951
169067
|
// src/matter/endpoints/legacy/air-purifier/index.ts
|
|
168952
169068
|
init_dist();
|
|
168953
169069
|
init_home_assistant_entity_behavior();
|
|
@@ -169208,10 +169324,6 @@ function AutomationDevice(homeAssistantEntity) {
|
|
|
169208
169324
|
return AutomationDeviceType.set({ homeAssistantEntity });
|
|
169209
169325
|
}
|
|
169210
169326
|
|
|
169211
|
-
// src/matter/endpoints/legacy/binary-sensor/index.ts
|
|
169212
|
-
init_dist();
|
|
169213
|
-
init_esm();
|
|
169214
|
-
|
|
169215
169327
|
// ../../node_modules/.pnpm/@matter+main@0.16.10/node_modules/@matter/main/dist/esm/forwards/behaviors/boolean-state.js
|
|
169216
169328
|
init_nodejs();
|
|
169217
169329
|
|
|
@@ -169281,6 +169393,10 @@ var ContactSensorWithBatteryType = ContactSensorDevice.with(
|
|
|
169281
169393
|
})
|
|
169282
169394
|
);
|
|
169283
169395
|
|
|
169396
|
+
// src/matter/endpoints/legacy/binary-sensor/index.ts
|
|
169397
|
+
init_dist();
|
|
169398
|
+
init_esm();
|
|
169399
|
+
|
|
169284
169400
|
// src/matter/endpoints/legacy/binary-sensor/motion-sensor.ts
|
|
169285
169401
|
init_home_assistant_entity_behavior();
|
|
169286
169402
|
|
|
@@ -173339,12 +173455,11 @@ function SceneDevice(homeAssistantEntity) {
|
|
|
173339
173455
|
// src/matter/endpoints/legacy/script/index.ts
|
|
173340
173456
|
init_home_assistant_entity_behavior();
|
|
173341
173457
|
var ScriptOnOffServer = OnOffServer2({
|
|
173458
|
+
isOn: () => false,
|
|
173342
173459
|
turnOn: () => ({
|
|
173343
173460
|
action: "script.turn_on"
|
|
173344
173461
|
}),
|
|
173345
|
-
turnOff:
|
|
173346
|
-
action: "script.turn_off"
|
|
173347
|
-
})
|
|
173462
|
+
turnOff: null
|
|
173348
173463
|
});
|
|
173349
173464
|
var ScriptDeviceType = OnOffPlugInUnitDevice.with(
|
|
173350
173465
|
BasicInformationServer2,
|
|
@@ -175076,6 +175191,16 @@ function SensorDevice(homeAssistantEntity) {
|
|
|
175076
175191
|
return void 0;
|
|
175077
175192
|
}
|
|
175078
175193
|
|
|
175194
|
+
// src/matter/endpoints/legacy/switch/dimmable-plugin-unit.ts
|
|
175195
|
+
init_home_assistant_entity_behavior();
|
|
175196
|
+
var DimmablePlugInUnitType = DimmablePlugInUnitDevice.with(
|
|
175197
|
+
IdentifyServer2,
|
|
175198
|
+
BasicInformationServer2,
|
|
175199
|
+
HomeAssistantEntityBehavior,
|
|
175200
|
+
LightOnOffServer,
|
|
175201
|
+
LightLevelControlServer
|
|
175202
|
+
);
|
|
175203
|
+
|
|
175079
175204
|
// src/matter/endpoints/legacy/switch/index.ts
|
|
175080
175205
|
init_home_assistant_entity_behavior();
|
|
175081
175206
|
var SwitchOnOffServer = OnOffServer2();
|
|
@@ -175703,9 +175828,51 @@ function createCustomServiceAreaServer(customAreas) {
|
|
|
175703
175828
|
currentArea: null
|
|
175704
175829
|
});
|
|
175705
175830
|
}
|
|
175831
|
+
function createCleanAreaServiceAreaServer(cleanAreaRooms) {
|
|
175832
|
+
const supportedAreas = cleanAreaRooms.map((room) => ({
|
|
175833
|
+
areaId: room.areaId,
|
|
175834
|
+
mapId: null,
|
|
175835
|
+
areaInfo: {
|
|
175836
|
+
locationInfo: {
|
|
175837
|
+
locationName: room.name,
|
|
175838
|
+
floorNumber: null,
|
|
175839
|
+
areaType: null
|
|
175840
|
+
},
|
|
175841
|
+
landmarkInfo: null
|
|
175842
|
+
}
|
|
175843
|
+
}));
|
|
175844
|
+
logger190.info(
|
|
175845
|
+
`Using ${cleanAreaRooms.length} HA areas via CLEAN_AREA: ${cleanAreaRooms.map((r) => r.name).join(", ")}`
|
|
175846
|
+
);
|
|
175847
|
+
return ServiceAreaServer2({
|
|
175848
|
+
supportedAreas,
|
|
175849
|
+
selectedAreas: [],
|
|
175850
|
+
currentArea: null
|
|
175851
|
+
});
|
|
175852
|
+
}
|
|
175706
175853
|
|
|
175707
175854
|
// src/matter/endpoints/legacy/vacuum/behaviors/vacuum-rvc-run-mode-server.ts
|
|
175708
175855
|
var logger191 = Logger.get("VacuumRvcRunModeServer");
|
|
175856
|
+
function buildValetudoSegmentAction(vacuumEntityId, segmentIds, valetudoIdentifier) {
|
|
175857
|
+
const identifier = valetudoIdentifier || vacuumEntityId.replace(/^vacuum\.valetudo_/, "");
|
|
175858
|
+
const topic = `valetudo/${identifier}/MapSegmentationCapability/clean/set`;
|
|
175859
|
+
logger191.info(
|
|
175860
|
+
`Valetudo: mqtt.publish to ${topic}, segments: ${segmentIds.join(", ")}`
|
|
175861
|
+
);
|
|
175862
|
+
return {
|
|
175863
|
+
action: "mqtt.publish",
|
|
175864
|
+
target: false,
|
|
175865
|
+
data: {
|
|
175866
|
+
topic,
|
|
175867
|
+
payload: JSON.stringify({
|
|
175868
|
+
action: "start_segment_action",
|
|
175869
|
+
segment_ids: segmentIds.map(String),
|
|
175870
|
+
iterations: 1,
|
|
175871
|
+
customOrder: true
|
|
175872
|
+
})
|
|
175873
|
+
}
|
|
175874
|
+
};
|
|
175875
|
+
}
|
|
175709
175876
|
function buildSupportedModes2(attributes7, includeUnnamedRooms = false, customAreas) {
|
|
175710
175877
|
const modes = [
|
|
175711
175878
|
{
|
|
@@ -175774,6 +175941,16 @@ function handleCustomServiceAreas(selectedAreas, customAreas, homeAssistant, ser
|
|
|
175774
175941
|
data: first.data
|
|
175775
175942
|
};
|
|
175776
175943
|
}
|
|
175944
|
+
function resolveCleanAreaIds(selectedAreas, cleanAreaRooms) {
|
|
175945
|
+
const haAreaIds = [];
|
|
175946
|
+
for (const areaId of selectedAreas) {
|
|
175947
|
+
const room = cleanAreaRooms.find((r) => r.areaId === areaId);
|
|
175948
|
+
if (room) {
|
|
175949
|
+
haAreaIds.push(room.haAreaId);
|
|
175950
|
+
}
|
|
175951
|
+
}
|
|
175952
|
+
return haAreaIds;
|
|
175953
|
+
}
|
|
175777
175954
|
var vacuumRvcRunModeConfig = {
|
|
175778
175955
|
getCurrentMode: (entity) => {
|
|
175779
175956
|
const state = entity.state;
|
|
@@ -175812,6 +175989,20 @@ var vacuumRvcRunModeConfig = {
|
|
|
175812
175989
|
serviceArea
|
|
175813
175990
|
);
|
|
175814
175991
|
}
|
|
175992
|
+
const cleanAreaRooms = homeAssistant.state.mapping?.cleanAreaRooms;
|
|
175993
|
+
if (cleanAreaRooms && cleanAreaRooms.length > 0) {
|
|
175994
|
+
const haAreaIds = resolveCleanAreaIds(selectedAreas, cleanAreaRooms);
|
|
175995
|
+
serviceArea.state.selectedAreas = [];
|
|
175996
|
+
if (haAreaIds.length > 0) {
|
|
175997
|
+
logger191.info(
|
|
175998
|
+
`CLEAN_AREA: cleaning HA areas: ${haAreaIds.join(", ")}`
|
|
175999
|
+
);
|
|
176000
|
+
return {
|
|
176001
|
+
action: "vacuum.clean_area",
|
|
176002
|
+
data: { cleaning_area_id: haAreaIds }
|
|
176003
|
+
};
|
|
176004
|
+
}
|
|
176005
|
+
}
|
|
175815
176006
|
const roomEntities = homeAssistant.state.mapping?.roomEntities;
|
|
175816
176007
|
if (roomEntities && roomEntities.length > 0) {
|
|
175817
176008
|
const buttonEntityIds = [];
|
|
@@ -175840,6 +176031,15 @@ var vacuumRvcRunModeConfig = {
|
|
|
175840
176031
|
};
|
|
175841
176032
|
}
|
|
175842
176033
|
}
|
|
176034
|
+
const vacuumEntityId = homeAssistant.entityId;
|
|
176035
|
+
if (vacuumEntityId.startsWith("vacuum.valetudo_")) {
|
|
176036
|
+
serviceArea.state.selectedAreas = [];
|
|
176037
|
+
return buildValetudoSegmentAction(
|
|
176038
|
+
vacuumEntityId,
|
|
176039
|
+
selectedAreas,
|
|
176040
|
+
homeAssistant.state.mapping?.valetudoIdentifier
|
|
176041
|
+
);
|
|
176042
|
+
}
|
|
175843
176043
|
const rooms = parseVacuumRooms(attributes7);
|
|
175844
176044
|
const roomIds = [];
|
|
175845
176045
|
let targetMapName;
|
|
@@ -175857,25 +176057,6 @@ var vacuumRvcRunModeConfig = {
|
|
|
175857
176057
|
`Starting cleaning with selected areas: ${roomIds.join(", ")}`
|
|
175858
176058
|
);
|
|
175859
176059
|
serviceArea.state.selectedAreas = [];
|
|
175860
|
-
const vacuumEntityId = homeAssistant.entityId;
|
|
175861
|
-
if (vacuumEntityId.startsWith("vacuum.valetudo_")) {
|
|
175862
|
-
const identifier = vacuumEntityId.replace(/^vacuum\.valetudo_/, "");
|
|
175863
|
-
logger191.info(
|
|
175864
|
-
`Valetudo vacuum: Using mqtt.publish segment_cleanup for rooms: ${roomIds.join(", ")}`
|
|
175865
|
-
);
|
|
175866
|
-
return {
|
|
175867
|
-
action: "mqtt.publish",
|
|
175868
|
-
target: false,
|
|
175869
|
-
data: {
|
|
175870
|
-
topic: `valetudo/${identifier}/MapSegmentationCapability/clean/set`,
|
|
175871
|
-
payload: JSON.stringify({
|
|
175872
|
-
segment_ids: roomIds.map(String),
|
|
175873
|
-
iterations: 1,
|
|
175874
|
-
customOrder: true
|
|
175875
|
-
})
|
|
175876
|
-
}
|
|
175877
|
-
};
|
|
175878
|
-
}
|
|
175879
176060
|
if (isDreameVacuum(attributes7)) {
|
|
175880
176061
|
if (targetMapName) {
|
|
175881
176062
|
const vacName = vacuumEntityId.replace("vacuum.", "");
|
|
@@ -175945,6 +176126,23 @@ var vacuumRvcRunModeConfig = {
|
|
|
175945
176126
|
const entity = homeAssistant.entity;
|
|
175946
176127
|
const attributes7 = entity.state.attributes;
|
|
175947
176128
|
logger191.info(`cleanRoom called: roomMode=${roomMode}`);
|
|
176129
|
+
const cleanAreaRooms = homeAssistant.state.mapping?.cleanAreaRooms;
|
|
176130
|
+
if (cleanAreaRooms && cleanAreaRooms.length > 0) {
|
|
176131
|
+
const sorted = [...cleanAreaRooms].sort(
|
|
176132
|
+
(a, b) => a.name.localeCompare(b.name)
|
|
176133
|
+
);
|
|
176134
|
+
const areaIndex = roomMode - ROOM_MODE_BASE2 - 1;
|
|
176135
|
+
if (areaIndex >= 0 && areaIndex < sorted.length) {
|
|
176136
|
+
const area = sorted[areaIndex];
|
|
176137
|
+
logger191.info(
|
|
176138
|
+
`cleanRoom: CLEAN_AREA "${area.name}" \u2192 vacuum.clean_area(${area.haAreaId})`
|
|
176139
|
+
);
|
|
176140
|
+
return {
|
|
176141
|
+
action: "vacuum.clean_area",
|
|
176142
|
+
data: { cleaning_area_id: [area.haAreaId] }
|
|
176143
|
+
};
|
|
176144
|
+
}
|
|
176145
|
+
}
|
|
175948
176146
|
const customAreas = homeAssistant.state.mapping?.customServiceAreas;
|
|
175949
176147
|
if (customAreas && customAreas.length > 0) {
|
|
175950
176148
|
const sorted = [...customAreas].sort(
|
|
@@ -175963,6 +176161,15 @@ var vacuumRvcRunModeConfig = {
|
|
|
175963
176161
|
};
|
|
175964
176162
|
}
|
|
175965
176163
|
}
|
|
176164
|
+
const vacuumEntityId = entity.entity_id;
|
|
176165
|
+
if (vacuumEntityId.startsWith("vacuum.valetudo_")) {
|
|
176166
|
+
const segmentId = getRoomIdFromMode(roomMode);
|
|
176167
|
+
return buildValetudoSegmentAction(
|
|
176168
|
+
vacuumEntityId,
|
|
176169
|
+
[segmentId],
|
|
176170
|
+
homeAssistant.state.mapping?.valetudoIdentifier
|
|
176171
|
+
);
|
|
176172
|
+
}
|
|
175966
176173
|
const rooms = parseVacuumRooms(attributes7);
|
|
175967
176174
|
const numericIdFromMode = getRoomIdFromMode(roomMode);
|
|
175968
176175
|
logger191.info(
|
|
@@ -175971,25 +176178,6 @@ var vacuumRvcRunModeConfig = {
|
|
|
175971
176178
|
const room = rooms.find((r) => getRoomModeValue(r) === roomMode);
|
|
175972
176179
|
if (room) {
|
|
175973
176180
|
const commandId3 = room.originalId ?? room.id;
|
|
175974
|
-
const vacuumEntityId = entity.entity_id;
|
|
175975
|
-
if (vacuumEntityId.startsWith("vacuum.valetudo_")) {
|
|
175976
|
-
const identifier = vacuumEntityId.replace(/^vacuum\.valetudo_/, "");
|
|
175977
|
-
logger191.info(
|
|
175978
|
-
`Valetudo vacuum: Using mqtt.publish segment_cleanup for room ${room.name} (id: ${commandId3})`
|
|
175979
|
-
);
|
|
175980
|
-
return {
|
|
175981
|
-
action: "mqtt.publish",
|
|
175982
|
-
target: false,
|
|
175983
|
-
data: {
|
|
175984
|
-
topic: `valetudo/${identifier}/MapSegmentationCapability/clean/set`,
|
|
175985
|
-
payload: JSON.stringify({
|
|
175986
|
-
segment_ids: [String(commandId3)],
|
|
175987
|
-
iterations: 1,
|
|
175988
|
-
customOrder: true
|
|
175989
|
-
})
|
|
175990
|
-
}
|
|
175991
|
-
};
|
|
175992
|
-
}
|
|
175993
176181
|
if (isDreameVacuum(attributes7)) {
|
|
175994
176182
|
if (room.mapName) {
|
|
175995
176183
|
const vacuumName = vacuumEntityId.replace("vacuum.", "");
|
|
@@ -176080,6 +176268,39 @@ function createVacuumRvcRunModeServer(attributes7, includeUnnamedRooms = false,
|
|
|
176080
176268
|
currentMode: 0 /* Idle */
|
|
176081
176269
|
});
|
|
176082
176270
|
}
|
|
176271
|
+
function createCleanAreaRvcRunModeServer(cleanAreaRooms) {
|
|
176272
|
+
const modes = [
|
|
176273
|
+
{
|
|
176274
|
+
label: "Idle",
|
|
176275
|
+
mode: 0 /* Idle */,
|
|
176276
|
+
modeTags: [{ value: RvcRunMode3.ModeTag.Idle }]
|
|
176277
|
+
},
|
|
176278
|
+
{
|
|
176279
|
+
label: "Cleaning",
|
|
176280
|
+
mode: 1 /* Cleaning */,
|
|
176281
|
+
modeTags: [{ value: RvcRunMode3.ModeTag.Cleaning }]
|
|
176282
|
+
}
|
|
176283
|
+
];
|
|
176284
|
+
const sorted = [...cleanAreaRooms].sort(
|
|
176285
|
+
(a, b) => a.name.localeCompare(b.name)
|
|
176286
|
+
);
|
|
176287
|
+
for (let i = 0; i < sorted.length; i++) {
|
|
176288
|
+
const modeValue = ROOM_MODE_BASE2 + i + 1;
|
|
176289
|
+
if (modeValue > 255) continue;
|
|
176290
|
+
modes.push({
|
|
176291
|
+
label: sorted[i].name,
|
|
176292
|
+
mode: modeValue,
|
|
176293
|
+
modeTags: [{ value: RvcRunMode3.ModeTag.Cleaning }]
|
|
176294
|
+
});
|
|
176295
|
+
}
|
|
176296
|
+
logger191.info(
|
|
176297
|
+
`Creating CLEAN_AREA RvcRunModeServer with ${cleanAreaRooms.length} HA areas, ${modes.length} total modes`
|
|
176298
|
+
);
|
|
176299
|
+
return RvcRunModeServer2(vacuumRvcRunModeConfig, {
|
|
176300
|
+
supportedModes: modes,
|
|
176301
|
+
currentMode: 0 /* Idle */
|
|
176302
|
+
});
|
|
176303
|
+
}
|
|
176083
176304
|
var VacuumRvcRunModeServer = RvcRunModeServer2(vacuumRvcRunModeConfig);
|
|
176084
176305
|
|
|
176085
176306
|
// src/matter/endpoints/legacy/vacuum/behaviors/vacuum-on-off-server.ts
|
|
@@ -176105,10 +176326,14 @@ var VacuumPowerSourceServer = PowerSourceServer2({
|
|
|
176105
176326
|
}
|
|
176106
176327
|
const attributes7 = entity.attributes;
|
|
176107
176328
|
const batteryLevel = attributes7.battery_level ?? attributes7.battery;
|
|
176108
|
-
if (batteryLevel == null
|
|
176329
|
+
if (batteryLevel == null) {
|
|
176109
176330
|
return null;
|
|
176110
176331
|
}
|
|
176111
|
-
|
|
176332
|
+
if (typeof batteryLevel === "number") {
|
|
176333
|
+
return batteryLevel;
|
|
176334
|
+
}
|
|
176335
|
+
const parsed = Number.parseFloat(String(batteryLevel));
|
|
176336
|
+
return Number.isNaN(parsed) ? null : parsed;
|
|
176112
176337
|
},
|
|
176113
176338
|
isCharging(entity) {
|
|
176114
176339
|
const state = entity.state;
|
|
@@ -177077,8 +177302,9 @@ function VacuumDevice(homeAssistantEntity, includeOnOff = false, cleaningModeOpt
|
|
|
177077
177302
|
logger196.info(
|
|
177078
177303
|
`Creating vacuum endpoint for ${entityId}, mapping: ${JSON.stringify(homeAssistantEntity.mapping ?? "none")}`
|
|
177079
177304
|
);
|
|
177305
|
+
const cleanAreaRooms = homeAssistantEntity.mapping?.cleanAreaRooms;
|
|
177080
177306
|
let device = VacuumEndpointType.with(
|
|
177081
|
-
createVacuumRvcRunModeServer(
|
|
177307
|
+
cleanAreaRooms && cleanAreaRooms.length > 0 ? createCleanAreaRvcRunModeServer(cleanAreaRooms) : createVacuumRvcRunModeServer(
|
|
177082
177308
|
attributes7,
|
|
177083
177309
|
false,
|
|
177084
177310
|
customAreas && customAreas.length > 0 ? customAreas : void 0
|
|
@@ -177092,9 +177318,14 @@ function VacuumDevice(homeAssistantEntity, includeOnOff = false, cleaningModeOpt
|
|
|
177092
177318
|
const roomEntities = homeAssistantEntity.mapping?.roomEntities;
|
|
177093
177319
|
const rooms = parseVacuumRooms(attributes7);
|
|
177094
177320
|
logger196.info(
|
|
177095
|
-
`${entityId}: customAreas=${customAreas?.length ?? 0}, roomEntities=${JSON.stringify(roomEntities ?? [])}, parsedRooms=${rooms.length}`
|
|
177321
|
+
`${entityId}: customAreas=${customAreas?.length ?? 0}, roomEntities=${JSON.stringify(roomEntities ?? [])}, parsedRooms=${rooms.length}, cleanAreaRooms=${cleanAreaRooms?.length ?? 0}`
|
|
177096
177322
|
);
|
|
177097
|
-
if (
|
|
177323
|
+
if (cleanAreaRooms && cleanAreaRooms.length > 0) {
|
|
177324
|
+
logger196.info(
|
|
177325
|
+
`${entityId}: Adding ServiceArea (${cleanAreaRooms.length} HA areas via CLEAN_AREA)`
|
|
177326
|
+
);
|
|
177327
|
+
device = device.with(createCleanAreaServiceAreaServer(cleanAreaRooms));
|
|
177328
|
+
} else if (customAreas && customAreas.length > 0) {
|
|
177098
177329
|
logger196.info(
|
|
177099
177330
|
`${entityId}: Adding ServiceArea (${customAreas.length} custom areas)`
|
|
177100
177331
|
);
|
|
@@ -177415,6 +177646,9 @@ var matterDeviceTypeFactories = {
|
|
|
177415
177646
|
}
|
|
177416
177647
|
return SwitchDevice(ha);
|
|
177417
177648
|
},
|
|
177649
|
+
dimmable_plugin_unit: (ha) => DimmablePlugInUnitType.set({
|
|
177650
|
+
homeAssistantEntity: { entity: ha.entity, customName: ha.customName }
|
|
177651
|
+
}),
|
|
177418
177652
|
on_off_switch: SwitchDevice,
|
|
177419
177653
|
door_lock: LockDevice,
|
|
177420
177654
|
window_covering: CoverDevice,
|
|
@@ -177470,9 +177704,15 @@ var matterDeviceTypeFactories = {
|
|
|
177470
177704
|
electrical_sensor: (ha) => ElectricalSensorType.set({
|
|
177471
177705
|
homeAssistantEntity: { entity: ha.entity, customName: ha.customName }
|
|
177472
177706
|
}),
|
|
177707
|
+
contact_sensor: (ha) => ContactSensorType.set({
|
|
177708
|
+
homeAssistantEntity: { entity: ha.entity, customName: ha.customName }
|
|
177709
|
+
}),
|
|
177473
177710
|
motion_sensor: (ha) => MotionSensorType.set({
|
|
177474
177711
|
homeAssistantEntity: { entity: ha.entity, customName: ha.customName }
|
|
177475
177712
|
}),
|
|
177713
|
+
occupancy_sensor: (ha) => OccupancySensorType.set({
|
|
177714
|
+
homeAssistantEntity: { entity: ha.entity, customName: ha.customName }
|
|
177715
|
+
}),
|
|
177476
177716
|
mode_select: SelectDevice,
|
|
177477
177717
|
water_valve: ValveDevice,
|
|
177478
177718
|
pump: PumpEndpoint,
|
|
@@ -177653,8 +177893,23 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
|
|
|
177653
177893
|
`Auto-assigned mopIntensity ${vacuumEntities.mopIntensityEntity} to ${entityId}`
|
|
177654
177894
|
);
|
|
177655
177895
|
}
|
|
177896
|
+
const supportedFeatures = state.attributes.supported_features ?? 0;
|
|
177897
|
+
const cleanAreaRooms = await registry2.resolveCleanAreaRooms(
|
|
177898
|
+
entityId,
|
|
177899
|
+
supportedFeatures
|
|
177900
|
+
);
|
|
177901
|
+
if (cleanAreaRooms.length > 0) {
|
|
177902
|
+
effectiveMapping = {
|
|
177903
|
+
...effectiveMapping,
|
|
177904
|
+
entityId: effectiveMapping?.entityId ?? entityId,
|
|
177905
|
+
cleanAreaRooms
|
|
177906
|
+
};
|
|
177907
|
+
logger198.debug(
|
|
177908
|
+
`Using ${cleanAreaRooms.length} HA areas via CLEAN_AREA for ${entityId}`
|
|
177909
|
+
);
|
|
177910
|
+
}
|
|
177656
177911
|
const vacAttrs = state.attributes;
|
|
177657
|
-
if (!vacAttrs.rooms && !vacAttrs.segments && !vacAttrs.room_mapping) {
|
|
177912
|
+
if (cleanAreaRooms.length === 0 && !vacAttrs.rooms && !vacAttrs.segments && !vacAttrs.room_mapping) {
|
|
177658
177913
|
const valetudoRooms = registry2.findValetudoMapSegments(
|
|
177659
177914
|
entity.device_id
|
|
177660
177915
|
);
|
|
@@ -177776,6 +178031,7 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
|
|
|
177776
178031
|
this.flushUpdate = debounce4(this.flushPendingUpdate.bind(this), 50);
|
|
177777
178032
|
}
|
|
177778
178033
|
lastState;
|
|
178034
|
+
pendingMappedChange = false;
|
|
177779
178035
|
flushUpdate;
|
|
177780
178036
|
async delete() {
|
|
177781
178037
|
this.flushUpdate.clear();
|
|
@@ -177788,6 +178044,7 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
|
|
|
177788
178044
|
return;
|
|
177789
178045
|
}
|
|
177790
178046
|
if (mappedChanged) {
|
|
178047
|
+
this.pendingMappedChange = true;
|
|
177791
178048
|
logger198.debug(
|
|
177792
178049
|
`Mapped entity change detected for ${this.entityId}, forcing update`
|
|
177793
178050
|
);
|
|
@@ -177806,8 +178063,13 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
|
|
|
177806
178063
|
}
|
|
177807
178064
|
try {
|
|
177808
178065
|
const current = this.stateOf(HomeAssistantEntityBehavior).entity;
|
|
178066
|
+
let effectiveState = state;
|
|
178067
|
+
if (this.pendingMappedChange) {
|
|
178068
|
+
this.pendingMappedChange = false;
|
|
178069
|
+
effectiveState = { ...state, last_updated: (/* @__PURE__ */ new Date()).toISOString() };
|
|
178070
|
+
}
|
|
177809
178071
|
await this.setStateOf(HomeAssistantEntityBehavior, {
|
|
177810
|
-
entity: { ...current, state }
|
|
178072
|
+
entity: { ...current, state: effectiveState }
|
|
177811
178073
|
});
|
|
177812
178074
|
} catch (error) {
|
|
177813
178075
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
@@ -177826,7 +178088,7 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
|
|
|
177826
178088
|
|
|
177827
178089
|
// src/services/home-assistant/api/subscribe-entities.ts
|
|
177828
178090
|
init_esm();
|
|
177829
|
-
import
|
|
178091
|
+
import crypto7 from "node:crypto";
|
|
177830
178092
|
import {
|
|
177831
178093
|
getCollection
|
|
177832
178094
|
} from "home-assistant-js-websocket";
|
|
@@ -177910,7 +178172,7 @@ var subscribeUpdates = (conn, store, entityIds) => {
|
|
|
177910
178172
|
});
|
|
177911
178173
|
};
|
|
177912
178174
|
function createEntitiesHash(entityIds) {
|
|
177913
|
-
return
|
|
178175
|
+
return crypto7.createHash("sha256").update(entityIds.join(",")).digest("hex").substring(0, 16);
|
|
177914
178176
|
}
|
|
177915
178177
|
var entitiesColl = (conn, entityIds) => {
|
|
177916
178178
|
if (atLeastHaVersion(conn.haVersion, 2022, 4, 0)) {
|
|
@@ -178843,6 +179105,54 @@ var BridgeRegistry = class _BridgeRegistry {
|
|
|
178843
179105
|
return [];
|
|
178844
179106
|
}
|
|
178845
179107
|
}
|
|
179108
|
+
static cleanAreaLogger = Logger.get("CleanAreaRooms");
|
|
179109
|
+
/**
|
|
179110
|
+
* Resolve HA areas mapped to vacuum segments via HA 2026.3 CLEAN_AREA.
|
|
179111
|
+
* Fetches the full entity registry entry (including options.vacuum.area_mapping)
|
|
179112
|
+
* and resolves HA area names from the area registry.
|
|
179113
|
+
* Returns CleanAreaRoom[] sorted alphabetically, or empty array if
|
|
179114
|
+
* CLEAN_AREA is not supported or no area_mapping is configured.
|
|
179115
|
+
*/
|
|
179116
|
+
async resolveCleanAreaRooms(entityId, supportedFeatures) {
|
|
179117
|
+
if (!this.client) return [];
|
|
179118
|
+
if (!(supportedFeatures & VacuumDeviceFeature.CLEAN_AREA)) return [];
|
|
179119
|
+
try {
|
|
179120
|
+
const entry = await this.client.connection.sendMessagePromise({
|
|
179121
|
+
type: "config/entity_registry/get",
|
|
179122
|
+
entity_id: entityId
|
|
179123
|
+
});
|
|
179124
|
+
const vacuumOptions = entry?.options?.vacuum;
|
|
179125
|
+
const areaMapping = vacuumOptions?.area_mapping;
|
|
179126
|
+
if (!areaMapping || Object.keys(areaMapping).length === 0) {
|
|
179127
|
+
_BridgeRegistry.cleanAreaLogger.debug(
|
|
179128
|
+
`${entityId}: CLEAN_AREA supported but no area_mapping configured`
|
|
179129
|
+
);
|
|
179130
|
+
return [];
|
|
179131
|
+
}
|
|
179132
|
+
const rooms = [];
|
|
179133
|
+
for (const haAreaId of Object.keys(areaMapping)) {
|
|
179134
|
+
const areaName = this.registry.areas.get(haAreaId) ?? haAreaId;
|
|
179135
|
+
rooms.push({
|
|
179136
|
+
areaId: hashAreaId(haAreaId),
|
|
179137
|
+
haAreaId,
|
|
179138
|
+
name: areaName
|
|
179139
|
+
});
|
|
179140
|
+
}
|
|
179141
|
+
rooms.sort((a, b) => a.name.localeCompare(b.name));
|
|
179142
|
+
if (rooms.length > 0) {
|
|
179143
|
+
_BridgeRegistry.cleanAreaLogger.info(
|
|
179144
|
+
`${entityId}: Resolved ${rooms.length} HA areas via CLEAN_AREA mapping`
|
|
179145
|
+
);
|
|
179146
|
+
}
|
|
179147
|
+
return rooms;
|
|
179148
|
+
} catch (error) {
|
|
179149
|
+
const msg = error instanceof Error ? error.message : typeof error === "object" && error !== null ? JSON.stringify(error) : String(error);
|
|
179150
|
+
_BridgeRegistry.cleanAreaLogger.warn(
|
|
179151
|
+
`${entityId}: Failed to resolve CLEAN_AREA mapping: ${msg}`
|
|
179152
|
+
);
|
|
179153
|
+
return [];
|
|
179154
|
+
}
|
|
179155
|
+
}
|
|
178846
179156
|
/**
|
|
178847
179157
|
* Find a pressure sensor entity that belongs to the same HA device.
|
|
178848
179158
|
* Returns the entity_id of the pressure sensor, or undefined if none found.
|
|
@@ -179073,6 +179383,15 @@ var BridgeRegistry = class _BridgeRegistry {
|
|
|
179073
179383
|
return true;
|
|
179074
179384
|
}
|
|
179075
179385
|
};
|
|
179386
|
+
function hashAreaId(areaId) {
|
|
179387
|
+
let hash2 = 0;
|
|
179388
|
+
for (let i = 0; i < areaId.length; i++) {
|
|
179389
|
+
const char = areaId.charCodeAt(i);
|
|
179390
|
+
hash2 = (hash2 << 5) - hash2 + char;
|
|
179391
|
+
hash2 |= 0;
|
|
179392
|
+
}
|
|
179393
|
+
return Math.abs(hash2);
|
|
179394
|
+
}
|
|
179076
179395
|
|
|
179077
179396
|
// src/services/bridges/server-mode-bridge.ts
|
|
179078
179397
|
init_dist();
|
|
@@ -179448,17 +179767,24 @@ function ServerModeVacuumDevice(homeAssistantEntity, includeOnOff = false, clean
|
|
|
179448
179767
|
return void 0;
|
|
179449
179768
|
}
|
|
179450
179769
|
const attributes7 = homeAssistantEntity.entity.state.attributes;
|
|
179770
|
+
const cleanAreaRooms = homeAssistantEntity.mapping?.cleanAreaRooms;
|
|
179771
|
+
const customAreas = homeAssistantEntity.mapping?.customServiceAreas;
|
|
179451
179772
|
let device = ServerModeVacuumEndpointType.with(
|
|
179452
|
-
createVacuumRvcRunModeServer(
|
|
179773
|
+
cleanAreaRooms && cleanAreaRooms.length > 0 ? createCleanAreaRvcRunModeServer(cleanAreaRooms) : createVacuumRvcRunModeServer(
|
|
179774
|
+
attributes7,
|
|
179775
|
+
false,
|
|
179776
|
+
customAreas && customAreas.length > 0 ? customAreas : void 0
|
|
179777
|
+
)
|
|
179453
179778
|
).set({ homeAssistantEntity });
|
|
179454
179779
|
if (includeOnOff) {
|
|
179455
179780
|
device = device.with(VacuumOnOffServer);
|
|
179456
179781
|
}
|
|
179457
179782
|
device = device.with(VacuumPowerSourceServer);
|
|
179458
|
-
const customAreas = homeAssistantEntity.mapping?.customServiceAreas;
|
|
179459
179783
|
const roomEntities = homeAssistantEntity.mapping?.roomEntities;
|
|
179460
179784
|
const rooms = parseVacuumRooms(attributes7);
|
|
179461
|
-
if (
|
|
179785
|
+
if (cleanAreaRooms && cleanAreaRooms.length > 0) {
|
|
179786
|
+
device = device.with(createCleanAreaServiceAreaServer(cleanAreaRooms));
|
|
179787
|
+
} else if (customAreas && customAreas.length > 0) {
|
|
179462
179788
|
device = device.with(createCustomServiceAreaServer(customAreas));
|
|
179463
179789
|
} else if (rooms.length > 0 || roomEntities && roomEntities.length > 0) {
|
|
179464
179790
|
device = device.with(
|
|
@@ -179518,9 +179844,16 @@ var ServerModeVacuumEndpoint = class _ServerModeVacuumEndpoint extends EntityEnd
|
|
|
179518
179844
|
registry2.markBatteryEntityUsed(batteryEntityId);
|
|
179519
179845
|
logger201.info(`${entityId}: Auto-assigned battery ${batteryEntityId}`);
|
|
179520
179846
|
} else {
|
|
179521
|
-
|
|
179522
|
-
|
|
179523
|
-
|
|
179847
|
+
const attrs = state.attributes;
|
|
179848
|
+
if (attrs.battery_level != null || attrs.battery != null) {
|
|
179849
|
+
logger201.info(
|
|
179850
|
+
`${entityId}: No battery entity found, using battery attribute from vacuum state`
|
|
179851
|
+
);
|
|
179852
|
+
} else {
|
|
179853
|
+
logger201.warn(
|
|
179854
|
+
`${entityId}: No battery entity found for device ${entity.device_id}`
|
|
179855
|
+
);
|
|
179856
|
+
}
|
|
179524
179857
|
}
|
|
179525
179858
|
}
|
|
179526
179859
|
const vacuumEntities = registry2.findVacuumSelectEntities(
|
|
@@ -179556,8 +179889,23 @@ var ServerModeVacuumEndpoint = class _ServerModeVacuumEndpoint extends EntityEnd
|
|
|
179556
179889
|
`${entityId}: Auto-assigned mopIntensity ${vacuumEntities.mopIntensityEntity}`
|
|
179557
179890
|
);
|
|
179558
179891
|
}
|
|
179892
|
+
const supportedFeatures = state.attributes.supported_features ?? 0;
|
|
179893
|
+
const cleanAreaRooms = await registry2.resolveCleanAreaRooms(
|
|
179894
|
+
entityId,
|
|
179895
|
+
supportedFeatures
|
|
179896
|
+
);
|
|
179897
|
+
if (cleanAreaRooms.length > 0) {
|
|
179898
|
+
effectiveMapping = {
|
|
179899
|
+
...effectiveMapping,
|
|
179900
|
+
entityId: effectiveMapping?.entityId ?? entityId,
|
|
179901
|
+
cleanAreaRooms
|
|
179902
|
+
};
|
|
179903
|
+
logger201.info(
|
|
179904
|
+
`${entityId}: Using ${cleanAreaRooms.length} HA areas via CLEAN_AREA`
|
|
179905
|
+
);
|
|
179906
|
+
}
|
|
179559
179907
|
const vacAttrs = state.attributes;
|
|
179560
|
-
if (!vacAttrs.rooms && !vacAttrs.segments && !vacAttrs.room_mapping) {
|
|
179908
|
+
if (cleanAreaRooms.length === 0 && !vacAttrs.rooms && !vacAttrs.segments && !vacAttrs.room_mapping) {
|
|
179561
179909
|
const valetudoRooms = registry2.findValetudoMapSegments(
|
|
179562
179910
|
entity.device_id
|
|
179563
179911
|
);
|
|
@@ -179643,6 +179991,7 @@ var ServerModeVacuumEndpoint = class _ServerModeVacuumEndpoint extends EntityEnd
|
|
|
179643
179991
|
);
|
|
179644
179992
|
}
|
|
179645
179993
|
lastState;
|
|
179994
|
+
pendingMappedChange = false;
|
|
179646
179995
|
flushUpdate;
|
|
179647
179996
|
constructor(type, entityId, customName, mappedEntityIds) {
|
|
179648
179997
|
super(type, entityId, customName, mappedEntityIds);
|
|
@@ -179659,6 +180008,7 @@ var ServerModeVacuumEndpoint = class _ServerModeVacuumEndpoint extends EntityEnd
|
|
|
179659
180008
|
return;
|
|
179660
180009
|
}
|
|
179661
180010
|
if (mappedChanged) {
|
|
180011
|
+
this.pendingMappedChange = true;
|
|
179662
180012
|
logger201.debug(
|
|
179663
180013
|
`Mapped entity change detected for ${this.entityId}, forcing update`
|
|
179664
180014
|
);
|
|
@@ -179677,8 +180027,13 @@ var ServerModeVacuumEndpoint = class _ServerModeVacuumEndpoint extends EntityEnd
|
|
|
179677
180027
|
}
|
|
179678
180028
|
try {
|
|
179679
180029
|
const current = this.stateOf(HomeAssistantEntityBehavior).entity;
|
|
180030
|
+
let effectiveState = state;
|
|
180031
|
+
if (this.pendingMappedChange) {
|
|
180032
|
+
this.pendingMappedChange = false;
|
|
180033
|
+
effectiveState = { ...state, last_updated: (/* @__PURE__ */ new Date()).toISOString() };
|
|
180034
|
+
}
|
|
179680
180035
|
await this.setStateOf(HomeAssistantEntityBehavior, {
|
|
179681
|
-
entity: { ...current, state }
|
|
180036
|
+
entity: { ...current, state: effectiveState }
|
|
179682
180037
|
});
|
|
179683
180038
|
} catch (error) {
|
|
179684
180039
|
if (error instanceof TransactionDestroyedError || error instanceof DestroyedDependencyError) {
|