@riddix/hamh 2.1.0-alpha.856 → 2.1.0-alpha.857
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/dist/backend/cli.js
CHANGED
|
@@ -133515,7 +133515,8 @@ WARNING: ${includeIdentity ? "This backup contains sensitive Matter identity dat
|
|
|
133515
133515
|
fanRestoreSpeedOnPowerOn: config8.fanRestoreSpeedOnPowerOn,
|
|
133516
133516
|
composedEntities: config8.composedEntities,
|
|
133517
133517
|
disableMomentaryFlip: config8.disableMomentaryFlip,
|
|
133518
|
-
vacuumAscendingRoomOrder: config8.vacuumAscendingRoomOrder
|
|
133518
|
+
vacuumAscendingRoomOrder: config8.vacuumAscendingRoomOrder,
|
|
133519
|
+
vacuumRoomSwitches: config8.vacuumRoomSwitches
|
|
133519
133520
|
});
|
|
133520
133521
|
mappingsRestored++;
|
|
133521
133522
|
}
|
|
@@ -133681,7 +133682,8 @@ WARNING: ${includeIdentity ? "This backup contains sensitive Matter identity dat
|
|
|
133681
133682
|
fanWindPresets: config8.fanWindPresets,
|
|
133682
133683
|
composedEntities: config8.composedEntities,
|
|
133683
133684
|
disableMomentaryFlip: config8.disableMomentaryFlip,
|
|
133684
|
-
vacuumAscendingRoomOrder: config8.vacuumAscendingRoomOrder
|
|
133685
|
+
vacuumAscendingRoomOrder: config8.vacuumAscendingRoomOrder,
|
|
133686
|
+
vacuumRoomSwitches: config8.vacuumRoomSwitches
|
|
133685
133687
|
});
|
|
133686
133688
|
mappingsRestored++;
|
|
133687
133689
|
}
|
|
@@ -134533,6 +134535,7 @@ function entityMappingApi(mappingStorage, identityStorage) {
|
|
|
134533
134535
|
currentRoomEntity: body.currentRoomEntity,
|
|
134534
134536
|
cleanedAreaEntity: body.cleanedAreaEntity,
|
|
134535
134537
|
vacuumAscendingRoomOrder: body.vacuumAscendingRoomOrder,
|
|
134538
|
+
vacuumRoomSwitches: body.vacuumRoomSwitches,
|
|
134536
134539
|
disableCustomAreaRoomModes: body.disableCustomAreaRoomModes,
|
|
134537
134540
|
valetudoIdentifier: body.valetudoIdentifier,
|
|
134538
134541
|
coverSwapOpenClose: body.coverSwapOpenClose,
|
|
@@ -135045,7 +135048,8 @@ function configToProfileEntry(config8) {
|
|
|
135045
135048
|
climateExposeFan: config8.climateExposeFan,
|
|
135046
135049
|
climateAutoMode: config8.climateAutoMode,
|
|
135047
135050
|
disableMomentaryFlip: config8.disableMomentaryFlip,
|
|
135048
|
-
vacuumAscendingRoomOrder: config8.vacuumAscendingRoomOrder
|
|
135051
|
+
vacuumAscendingRoomOrder: config8.vacuumAscendingRoomOrder,
|
|
135052
|
+
vacuumRoomSwitches: config8.vacuumRoomSwitches
|
|
135049
135053
|
};
|
|
135050
135054
|
}
|
|
135051
135055
|
function mappingProfileApi(mappingStorage) {
|
|
@@ -135189,7 +135193,8 @@ function mappingProfileApi(mappingStorage) {
|
|
|
135189
135193
|
climateExposeFan: entry.climateExposeFan,
|
|
135190
135194
|
climateAutoMode: entry.climateAutoMode,
|
|
135191
135195
|
disableMomentaryFlip: entry.disableMomentaryFlip,
|
|
135192
|
-
vacuumAscendingRoomOrder: entry.vacuumAscendingRoomOrder
|
|
135196
|
+
vacuumAscendingRoomOrder: entry.vacuumAscendingRoomOrder,
|
|
135197
|
+
vacuumRoomSwitches: entry.vacuumRoomSwitches
|
|
135193
135198
|
});
|
|
135194
135199
|
applied++;
|
|
135195
135200
|
} catch (e) {
|
|
@@ -139966,6 +139971,7 @@ var EntityMappingStorage = class extends Service {
|
|
|
139966
139971
|
currentRoomEntity: request.currentRoomEntity?.trim() || void 0,
|
|
139967
139972
|
cleanedAreaEntity: request.cleanedAreaEntity?.trim() || void 0,
|
|
139968
139973
|
vacuumAscendingRoomOrder: request.vacuumAscendingRoomOrder || void 0,
|
|
139974
|
+
vacuumRoomSwitches: request.vacuumRoomSwitches || void 0,
|
|
139969
139975
|
disableCustomAreaRoomModes: request.disableCustomAreaRoomModes || void 0,
|
|
139970
139976
|
valetudoIdentifier: request.valetudoIdentifier?.trim() || void 0,
|
|
139971
139977
|
coverSwapOpenClose: request.coverSwapOpenClose || void 0,
|
|
@@ -139983,7 +139989,7 @@ var EntityMappingStorage = class extends Service {
|
|
|
139983
139989
|
composedEntities: request.composedEntities?.filter((e) => e.entityId?.trim()) ?? void 0,
|
|
139984
139990
|
disableMomentaryFlip: request.disableMomentaryFlip || void 0
|
|
139985
139991
|
};
|
|
139986
|
-
if (!config8.matterDeviceType && !config8.customName && !config8.customProductName && !config8.customVendorName && !config8.customSerialNumber && config8.customVendorId === void 0 && config8.disabled !== true && !config8.filterLifeEntity && !config8.cleaningModeEntity && !config8.temperatureEntity && !config8.humidityEntity && !config8.batteryEntity && !config8.disableBatteryMapping && !config8.chargingStateEntity && !config8.roomEntities && !config8.disableLockPin && !config8.lockUsercodeService && config8.lockUsercodeSlot === void 0 && config8.lockPinMinLength === void 0 && config8.lockPinMaxLength === void 0 && !config8.powerEntity && !config8.energyEntity && !config8.meterSerialNumber && !config8.pointOfDelivery && !config8.voltageEntity && !config8.currentEntity && !config8.batteryPowerEntity && !config8.batteryEnergyEntity && !config8.chargingSwitchEntity && !config8.currentLimitEntity && !config8.pressureEntity && !config8.suctionLevelEntity && !config8.mopIntensityEntity && (!config8.customServiceAreas || config8.customServiceAreas.length === 0) && (!config8.customFanSpeedTags || Object.keys(config8.customFanSpeedTags).length === 0) && (!config8.fanWindPresets || (config8.fanWindPresets.natural?.length ?? 0) === 0 && (config8.fanWindPresets.sleep?.length ?? 0) === 0) && !config8.fanRestoreSpeedOnPowerOn && !config8.currentRoomEntity && !config8.cleanedAreaEntity && !config8.vacuumAscendingRoomOrder && !config8.disableCustomAreaRoomModes && !config8.valetudoIdentifier && !config8.coverSwapOpenClose && !config8.coverExposeAsDimmableLight && !config8.selectExposeAsSwitch && !config8.selectSwitchOnOption && !config8.selectSwitchOffOption && !config8.coverSliderDebounceMs && !config8.updateThrottleMs && !config8.disableClimateOnOff && !config8.disableClimateFanControl && !config8.climateKeepModeOnIdle && !config8.climateExposeFan && !config8.climateAutoMode && (!config8.composedEntities || config8.composedEntities.length === 0) && !config8.disableMomentaryFlip) {
|
|
139992
|
+
if (!config8.matterDeviceType && !config8.customName && !config8.customProductName && !config8.customVendorName && !config8.customSerialNumber && config8.customVendorId === void 0 && config8.disabled !== true && !config8.filterLifeEntity && !config8.cleaningModeEntity && !config8.temperatureEntity && !config8.humidityEntity && !config8.batteryEntity && !config8.disableBatteryMapping && !config8.chargingStateEntity && !config8.roomEntities && !config8.disableLockPin && !config8.lockUsercodeService && config8.lockUsercodeSlot === void 0 && config8.lockPinMinLength === void 0 && config8.lockPinMaxLength === void 0 && !config8.powerEntity && !config8.energyEntity && !config8.meterSerialNumber && !config8.pointOfDelivery && !config8.voltageEntity && !config8.currentEntity && !config8.batteryPowerEntity && !config8.batteryEnergyEntity && !config8.chargingSwitchEntity && !config8.currentLimitEntity && !config8.pressureEntity && !config8.suctionLevelEntity && !config8.mopIntensityEntity && (!config8.customServiceAreas || config8.customServiceAreas.length === 0) && (!config8.customFanSpeedTags || Object.keys(config8.customFanSpeedTags).length === 0) && (!config8.fanWindPresets || (config8.fanWindPresets.natural?.length ?? 0) === 0 && (config8.fanWindPresets.sleep?.length ?? 0) === 0) && !config8.fanRestoreSpeedOnPowerOn && !config8.currentRoomEntity && !config8.cleanedAreaEntity && !config8.vacuumAscendingRoomOrder && !config8.vacuumRoomSwitches && !config8.disableCustomAreaRoomModes && !config8.valetudoIdentifier && !config8.coverSwapOpenClose && !config8.coverExposeAsDimmableLight && !config8.selectExposeAsSwitch && !config8.selectSwitchOnOption && !config8.selectSwitchOffOption && !config8.coverSliderDebounceMs && !config8.updateThrottleMs && !config8.disableClimateOnOff && !config8.disableClimateFanControl && !config8.climateKeepModeOnIdle && !config8.climateExposeFan && !config8.climateAutoMode && (!config8.composedEntities || config8.composedEntities.length === 0) && !config8.disableMomentaryFlip) {
|
|
139987
139993
|
bridgeMap.delete(request.entityId);
|
|
139988
139994
|
} else {
|
|
139989
139995
|
bridgeMap.set(request.entityId, config8);
|
|
@@ -171139,6 +171145,31 @@ function createCleanAreaServiceAreaServer(cleanAreaRooms) {
|
|
|
171139
171145
|
currentArea: null
|
|
171140
171146
|
});
|
|
171141
171147
|
}
|
|
171148
|
+
function getVacuumServiceAreas(attributes9, mapping) {
|
|
171149
|
+
const cleanAreaRooms = mapping?.cleanAreaRooms;
|
|
171150
|
+
if (cleanAreaRooms && cleanAreaRooms.length > 0) {
|
|
171151
|
+
return cleanAreaRooms.map((room) => ({
|
|
171152
|
+
areaId: room.areaId,
|
|
171153
|
+
name: room.name
|
|
171154
|
+
}));
|
|
171155
|
+
}
|
|
171156
|
+
const customAreas = mapping?.customServiceAreas;
|
|
171157
|
+
if (customAreas && customAreas.length > 0) {
|
|
171158
|
+
return customAreas.map((area, index) => ({
|
|
171159
|
+
areaId: index + 1,
|
|
171160
|
+
name: area.name
|
|
171161
|
+
}));
|
|
171162
|
+
}
|
|
171163
|
+
const roomEntities = mapping?.roomEntities;
|
|
171164
|
+
const rooms = roomEntities && roomEntities.length > 0 ? buttonEntitiesToRooms(roomEntities, attributes9) : parseVacuumRooms(attributes9);
|
|
171165
|
+
if (rooms.length > 0) {
|
|
171166
|
+
return roomsToAreas(rooms).map((area) => ({
|
|
171167
|
+
areaId: area.areaId,
|
|
171168
|
+
name: area.areaInfo.locationInfo?.locationName ?? ""
|
|
171169
|
+
}));
|
|
171170
|
+
}
|
|
171171
|
+
return [];
|
|
171172
|
+
}
|
|
171142
171173
|
|
|
171143
171174
|
// src/matter/endpoints/legacy/vacuum/behaviors/vacuum-rvc-run-mode-server.ts
|
|
171144
171175
|
var logger236 = Logger.get("VacuumRvcRunModeServer");
|
|
@@ -171313,6 +171344,135 @@ var cleaningStates = [
|
|
|
171313
171344
|
function vacuumIsCleaning(state) {
|
|
171314
171345
|
return state != null && cleaningStates.includes(state);
|
|
171315
171346
|
}
|
|
171347
|
+
function dispatchRoomClean(attributes9, mapping, entityId, selectedAreas, seam) {
|
|
171348
|
+
const customAreas = mapping?.customServiceAreas;
|
|
171349
|
+
if (customAreas && customAreas.length > 0) {
|
|
171350
|
+
const ephemeral = {
|
|
171351
|
+
completedAreas: /* @__PURE__ */ new Set(),
|
|
171352
|
+
lastCurrentArea: null,
|
|
171353
|
+
activeAreas: [],
|
|
171354
|
+
loggedShortCircuits: /* @__PURE__ */ new Set(),
|
|
171355
|
+
observedCleaning: false,
|
|
171356
|
+
pendingDispatches: [],
|
|
171357
|
+
cleanedAreaBaseline: null
|
|
171358
|
+
};
|
|
171359
|
+
const action = handleCustomServiceAreas(
|
|
171360
|
+
selectedAreas,
|
|
171361
|
+
customAreas,
|
|
171362
|
+
ephemeral
|
|
171363
|
+
);
|
|
171364
|
+
return { action, pending: ephemeral.pendingDispatches };
|
|
171365
|
+
}
|
|
171366
|
+
const cleanAreaRooms = mapping?.cleanAreaRooms;
|
|
171367
|
+
if (cleanAreaRooms && cleanAreaRooms.length > 0) {
|
|
171368
|
+
const haAreaIds = resolveCleanAreaIds(selectedAreas, cleanAreaRooms);
|
|
171369
|
+
if (haAreaIds.length > 0) {
|
|
171370
|
+
logger236.info(`CLEAN_AREA: cleaning HA areas: ${haAreaIds.join(", ")}`);
|
|
171371
|
+
return {
|
|
171372
|
+
action: {
|
|
171373
|
+
action: "vacuum.clean_area",
|
|
171374
|
+
data: { cleaning_area_id: haAreaIds }
|
|
171375
|
+
},
|
|
171376
|
+
pending: []
|
|
171377
|
+
};
|
|
171378
|
+
}
|
|
171379
|
+
}
|
|
171380
|
+
const roomEntities = mapping?.roomEntities;
|
|
171381
|
+
if (roomEntities && roomEntities.length > 0) {
|
|
171382
|
+
const matched = [];
|
|
171383
|
+
for (const areaId of selectedAreas) {
|
|
171384
|
+
const buttonId = roomEntities.find((id) => toAreaId(id) === areaId);
|
|
171385
|
+
if (buttonId) {
|
|
171386
|
+
matched.push({ areaId, entityId: buttonId });
|
|
171387
|
+
}
|
|
171388
|
+
}
|
|
171389
|
+
if (matched.length > 0) {
|
|
171390
|
+
logger236.info(
|
|
171391
|
+
`Roborock: ${matched.length} room button(s) queued: ${matched.map((m) => m.entityId).join(", ")}`
|
|
171392
|
+
);
|
|
171393
|
+
return {
|
|
171394
|
+
action: { action: "button.press", target: matched[0].entityId },
|
|
171395
|
+
pending: matched.slice(1).map(({ areaId, entityId: buttonId }) => ({
|
|
171396
|
+
areaId,
|
|
171397
|
+
action: { action: "button.press", target: buttonId }
|
|
171398
|
+
}))
|
|
171399
|
+
};
|
|
171400
|
+
}
|
|
171401
|
+
}
|
|
171402
|
+
if (entityId.startsWith("vacuum.valetudo_")) {
|
|
171403
|
+
return {
|
|
171404
|
+
action: buildValetudoSegmentAction(
|
|
171405
|
+
entityId,
|
|
171406
|
+
selectedAreas,
|
|
171407
|
+
mapping?.valetudoIdentifier
|
|
171408
|
+
),
|
|
171409
|
+
pending: []
|
|
171410
|
+
};
|
|
171411
|
+
}
|
|
171412
|
+
const rooms = parseVacuumRooms(attributes9);
|
|
171413
|
+
const roomIds = [];
|
|
171414
|
+
let targetMapName;
|
|
171415
|
+
for (const areaId of selectedAreas) {
|
|
171416
|
+
const room = rooms.find((r) => toAreaId(r.id) === areaId);
|
|
171417
|
+
if (room) {
|
|
171418
|
+
roomIds.push(room.originalId ?? room.id);
|
|
171419
|
+
if (room.mapName && !targetMapName) {
|
|
171420
|
+
targetMapName = room.mapName;
|
|
171421
|
+
}
|
|
171422
|
+
}
|
|
171423
|
+
}
|
|
171424
|
+
if (roomIds.length > 0) {
|
|
171425
|
+
logger236.info(`Starting cleaning with selected areas: ${roomIds.join(", ")}`);
|
|
171426
|
+
if (isDreameVacuum(attributes9)) {
|
|
171427
|
+
if (targetMapName) {
|
|
171428
|
+
const vacName = entityId.replace("vacuum.", "");
|
|
171429
|
+
const selectedMapEntity = `select.${vacName}_selected_map`;
|
|
171430
|
+
logger236.info(
|
|
171431
|
+
`Dreame multi-floor: switching to map "${targetMapName}" via ${selectedMapEntity}`
|
|
171432
|
+
);
|
|
171433
|
+
seam.callAction({
|
|
171434
|
+
action: "select.select_option",
|
|
171435
|
+
target: selectedMapEntity,
|
|
171436
|
+
data: { option: targetMapName }
|
|
171437
|
+
});
|
|
171438
|
+
}
|
|
171439
|
+
return {
|
|
171440
|
+
action: {
|
|
171441
|
+
action: "dreame_vacuum.vacuum_clean_segment",
|
|
171442
|
+
data: { segments: roomIds.length === 1 ? roomIds[0] : roomIds }
|
|
171443
|
+
},
|
|
171444
|
+
pending: []
|
|
171445
|
+
};
|
|
171446
|
+
}
|
|
171447
|
+
if (isRoborockVacuum(attributes9) || isXiaomiMiotVacuum(attributes9)) {
|
|
171448
|
+
return {
|
|
171449
|
+
action: {
|
|
171450
|
+
action: "vacuum.send_command",
|
|
171451
|
+
data: { command: "app_segment_clean", params: roomIds }
|
|
171452
|
+
},
|
|
171453
|
+
pending: []
|
|
171454
|
+
};
|
|
171455
|
+
}
|
|
171456
|
+
if (isEcovacsVacuum(attributes9)) {
|
|
171457
|
+
const roomIdStr = roomIds.join(",");
|
|
171458
|
+
logger236.info(`Ecovacs vacuum: Using spot_area for rooms: ${roomIdStr}`);
|
|
171459
|
+
return {
|
|
171460
|
+
action: {
|
|
171461
|
+
action: "vacuum.send_command",
|
|
171462
|
+
data: {
|
|
171463
|
+
command: "spot_area",
|
|
171464
|
+
params: { mapID: 0, cleanings: 1, rooms: roomIdStr }
|
|
171465
|
+
}
|
|
171466
|
+
},
|
|
171467
|
+
pending: []
|
|
171468
|
+
};
|
|
171469
|
+
}
|
|
171470
|
+
logger236.warn(
|
|
171471
|
+
`Room cleaning via send_command not supported for this vacuum type. Rooms: ${roomIds.join(", ")}. Falling back to vacuum.start`
|
|
171472
|
+
);
|
|
171473
|
+
}
|
|
171474
|
+
return { action: { action: "vacuum.start" }, pending: [] };
|
|
171475
|
+
}
|
|
171316
171476
|
var vacuumRvcRunModeConfig = {
|
|
171317
171477
|
getCurrentMode: (entity) => {
|
|
171318
171478
|
const isCleaning = vacuumIsCleaning(entity.state);
|
|
@@ -171339,123 +171499,19 @@ var vacuumRvcRunModeConfig = {
|
|
|
171339
171499
|
const selectedAreas = [...serviceArea.state.selectedAreas];
|
|
171340
171500
|
if (selectedAreas.length > 0) {
|
|
171341
171501
|
const homeAssistant = agent.get(HomeAssistantEntityBehavior);
|
|
171342
|
-
const
|
|
171343
|
-
const attributes9 = entity.state.attributes;
|
|
171502
|
+
const effective = homeAssistant.endpoint.vacuumEffective;
|
|
171503
|
+
const attributes9 = (effective?.state ?? homeAssistant.entity.state).attributes;
|
|
171504
|
+
const mapping = effective ? effective.mapping : homeAssistant.state.mapping;
|
|
171344
171505
|
const session = getSession(homeAssistant.endpoint);
|
|
171345
|
-
const
|
|
171346
|
-
|
|
171347
|
-
|
|
171348
|
-
|
|
171349
|
-
|
|
171350
|
-
|
|
171351
|
-
|
|
171352
|
-
|
|
171353
|
-
|
|
171354
|
-
`CLEAN_AREA: cleaning HA areas: ${haAreaIds.join(", ")}`
|
|
171355
|
-
);
|
|
171356
|
-
return {
|
|
171357
|
-
action: "vacuum.clean_area",
|
|
171358
|
-
data: { cleaning_area_id: haAreaIds }
|
|
171359
|
-
};
|
|
171360
|
-
}
|
|
171361
|
-
}
|
|
171362
|
-
const roomEntities = homeAssistant.state.mapping?.roomEntities;
|
|
171363
|
-
if (roomEntities && roomEntities.length > 0) {
|
|
171364
|
-
const matched = [];
|
|
171365
|
-
for (const areaId of selectedAreas) {
|
|
171366
|
-
const entityId = roomEntities.find((id) => toAreaId(id) === areaId);
|
|
171367
|
-
if (entityId) {
|
|
171368
|
-
matched.push({ areaId, entityId });
|
|
171369
|
-
}
|
|
171370
|
-
}
|
|
171371
|
-
if (matched.length > 0) {
|
|
171372
|
-
logger236.info(
|
|
171373
|
-
`Roborock: ${matched.length} room button(s) queued: ${matched.map((m) => m.entityId).join(", ")}`
|
|
171374
|
-
);
|
|
171375
|
-
session.pendingDispatches = matched.slice(1).map(({ areaId, entityId }) => ({
|
|
171376
|
-
areaId,
|
|
171377
|
-
action: { action: "button.press", target: entityId }
|
|
171378
|
-
}));
|
|
171379
|
-
return {
|
|
171380
|
-
action: "button.press",
|
|
171381
|
-
target: matched[0].entityId
|
|
171382
|
-
};
|
|
171383
|
-
}
|
|
171384
|
-
}
|
|
171385
|
-
const vacuumEntityId = homeAssistant.entityId;
|
|
171386
|
-
if (vacuumEntityId.startsWith("vacuum.valetudo_")) {
|
|
171387
|
-
return buildValetudoSegmentAction(
|
|
171388
|
-
vacuumEntityId,
|
|
171389
|
-
selectedAreas,
|
|
171390
|
-
homeAssistant.state.mapping?.valetudoIdentifier
|
|
171391
|
-
);
|
|
171392
|
-
}
|
|
171393
|
-
const rooms = parseVacuumRooms(attributes9);
|
|
171394
|
-
const roomIds = [];
|
|
171395
|
-
let targetMapName;
|
|
171396
|
-
for (const areaId of selectedAreas) {
|
|
171397
|
-
const room = rooms.find((r) => toAreaId(r.id) === areaId);
|
|
171398
|
-
if (room) {
|
|
171399
|
-
roomIds.push(room.originalId ?? room.id);
|
|
171400
|
-
if (room.mapName && !targetMapName) {
|
|
171401
|
-
targetMapName = room.mapName;
|
|
171402
|
-
}
|
|
171403
|
-
}
|
|
171404
|
-
}
|
|
171405
|
-
if (roomIds.length > 0) {
|
|
171406
|
-
logger236.info(
|
|
171407
|
-
`Starting cleaning with selected areas: ${roomIds.join(", ")}`
|
|
171408
|
-
);
|
|
171409
|
-
if (isDreameVacuum(attributes9)) {
|
|
171410
|
-
if (targetMapName) {
|
|
171411
|
-
const vacName = vacuumEntityId.replace("vacuum.", "");
|
|
171412
|
-
const selectedMapEntity = `select.${vacName}_selected_map`;
|
|
171413
|
-
logger236.info(
|
|
171414
|
-
`Dreame multi-floor: switching to map "${targetMapName}" via ${selectedMapEntity}`
|
|
171415
|
-
);
|
|
171416
|
-
homeAssistant.callAction({
|
|
171417
|
-
action: "select.select_option",
|
|
171418
|
-
target: selectedMapEntity,
|
|
171419
|
-
data: { option: targetMapName }
|
|
171420
|
-
});
|
|
171421
|
-
}
|
|
171422
|
-
return {
|
|
171423
|
-
action: "dreame_vacuum.vacuum_clean_segment",
|
|
171424
|
-
data: {
|
|
171425
|
-
segments: roomIds.length === 1 ? roomIds[0] : roomIds
|
|
171426
|
-
}
|
|
171427
|
-
};
|
|
171428
|
-
}
|
|
171429
|
-
if (isRoborockVacuum(attributes9) || isXiaomiMiotVacuum(attributes9)) {
|
|
171430
|
-
return {
|
|
171431
|
-
action: "vacuum.send_command",
|
|
171432
|
-
data: {
|
|
171433
|
-
command: "app_segment_clean",
|
|
171434
|
-
params: roomIds
|
|
171435
|
-
}
|
|
171436
|
-
};
|
|
171437
|
-
}
|
|
171438
|
-
if (isEcovacsVacuum(attributes9)) {
|
|
171439
|
-
const roomIdStr = roomIds.join(",");
|
|
171440
|
-
logger236.info(
|
|
171441
|
-
`Ecovacs vacuum: Using spot_area for rooms: ${roomIdStr}`
|
|
171442
|
-
);
|
|
171443
|
-
return {
|
|
171444
|
-
action: "vacuum.send_command",
|
|
171445
|
-
data: {
|
|
171446
|
-
command: "spot_area",
|
|
171447
|
-
params: {
|
|
171448
|
-
mapID: 0,
|
|
171449
|
-
cleanings: 1,
|
|
171450
|
-
rooms: roomIdStr
|
|
171451
|
-
}
|
|
171452
|
-
}
|
|
171453
|
-
};
|
|
171454
|
-
}
|
|
171455
|
-
logger236.warn(
|
|
171456
|
-
`Room cleaning via send_command not supported for this vacuum type. Rooms: ${roomIds.join(", ")}. Falling back to vacuum.start`
|
|
171457
|
-
);
|
|
171458
|
-
}
|
|
171506
|
+
const result = dispatchRoomClean(
|
|
171507
|
+
attributes9,
|
|
171508
|
+
mapping,
|
|
171509
|
+
homeAssistant.entityId,
|
|
171510
|
+
selectedAreas,
|
|
171511
|
+
{ callAction: (a) => homeAssistant.callAction(a) }
|
|
171512
|
+
);
|
|
171513
|
+
session.pendingDispatches = result.pending;
|
|
171514
|
+
return result.action;
|
|
171459
171515
|
}
|
|
171460
171516
|
} catch {
|
|
171461
171517
|
}
|
|
@@ -173922,6 +173978,12 @@ function asStandaloneEndpointType(type) {
|
|
|
173922
173978
|
// src/matter/endpoints/legacy/legacy-endpoint.ts
|
|
173923
173979
|
var logger245 = Logger.get("LegacyEndpoint");
|
|
173924
173980
|
var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
|
|
173981
|
+
constructor(type, entityId, customName, mappedEntityIds, throttleMs, endpointId, vacuumEffective) {
|
|
173982
|
+
super(type, entityId, customName, mappedEntityIds, endpointId);
|
|
173983
|
+
this.vacuumEffective = vacuumEffective;
|
|
173984
|
+
this.flushUpdate = throttleMs && throttleMs > 50 ? throttleLatest(this.flushPendingUpdate.bind(this), throttleMs) : debounce6(this.flushPendingUpdate.bind(this), 50);
|
|
173985
|
+
}
|
|
173986
|
+
vacuumEffective;
|
|
173925
173987
|
static async create(registry3, entityId, mapping, pluginDomainMappings, standalone = false, endpointId, identityAnchor) {
|
|
173926
173988
|
const deviceRegistry = registry3.deviceOf(entityId);
|
|
173927
173989
|
let state = registry3.initialState(entityId);
|
|
@@ -174295,19 +174357,17 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
|
|
|
174295
174357
|
}
|
|
174296
174358
|
const customName = effectiveMapping?.customName;
|
|
174297
174359
|
const mappedIds = getMappedEntityIds(effectiveMapping);
|
|
174360
|
+
const vacuumEffective = entityId.startsWith("vacuum.") ? { mapping: effectiveMapping, state } : void 0;
|
|
174298
174361
|
return new _LegacyEndpoint(
|
|
174299
174362
|
type,
|
|
174300
174363
|
entityId,
|
|
174301
174364
|
customName,
|
|
174302
174365
|
mappedIds,
|
|
174303
174366
|
effectiveMapping?.updateThrottleMs,
|
|
174304
|
-
endpointId
|
|
174367
|
+
endpointId,
|
|
174368
|
+
vacuumEffective
|
|
174305
174369
|
);
|
|
174306
174370
|
}
|
|
174307
|
-
constructor(type, entityId, customName, mappedEntityIds, throttleMs, endpointId) {
|
|
174308
|
-
super(type, entityId, customName, mappedEntityIds, endpointId);
|
|
174309
|
-
this.flushUpdate = throttleMs && throttleMs > 50 ? throttleLatest(this.flushPendingUpdate.bind(this), throttleMs) : debounce6(this.flushPendingUpdate.bind(this), 50);
|
|
174310
|
-
}
|
|
174311
174371
|
lastState;
|
|
174312
174372
|
pendingMappedChange = false;
|
|
174313
174373
|
flushUpdate;
|
|
@@ -174374,6 +174434,96 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
|
|
|
174374
174434
|
}
|
|
174375
174435
|
};
|
|
174376
174436
|
|
|
174437
|
+
// src/matter/endpoints/legacy/vacuum/vacuum-area-switch.ts
|
|
174438
|
+
init_esm();
|
|
174439
|
+
init_home_assistant_entity_behavior();
|
|
174440
|
+
var VacuumAreaSwitchEndpoint = class _VacuumAreaSwitchEndpoint extends EntityEndpoint {
|
|
174441
|
+
constructor(type, entityId, endpointId, areaId, vacuumEndpointId, parentEffective) {
|
|
174442
|
+
super(type, entityId, void 0, [], endpointId);
|
|
174443
|
+
this.areaId = areaId;
|
|
174444
|
+
this.vacuumEndpointId = vacuumEndpointId;
|
|
174445
|
+
this.parentEffective = parentEffective;
|
|
174446
|
+
}
|
|
174447
|
+
areaId;
|
|
174448
|
+
vacuumEndpointId;
|
|
174449
|
+
parentEffective;
|
|
174450
|
+
static create(params) {
|
|
174451
|
+
const { vacuumEndpointId, entity, mapping, area, parentEffective } = params;
|
|
174452
|
+
const endpointId = `${vacuumEndpointId}_roomsw_${area.areaId}`;
|
|
174453
|
+
const areaId = area.areaId;
|
|
174454
|
+
const switchMapping = mapping?.customSerialNumber ? { ...mapping, customSerialNumber: void 0 } : mapping;
|
|
174455
|
+
const switchEntity = entity.deviceRegistry?.serial_number ? {
|
|
174456
|
+
...entity,
|
|
174457
|
+
deviceRegistry: {
|
|
174458
|
+
...entity.deviceRegistry,
|
|
174459
|
+
serial_number: void 0
|
|
174460
|
+
}
|
|
174461
|
+
} : entity;
|
|
174462
|
+
const type = OnOffPlugInUnitDevice.with(
|
|
174463
|
+
BasicInformationServer2,
|
|
174464
|
+
IdentifyServer2,
|
|
174465
|
+
HomeAssistantEntityBehavior,
|
|
174466
|
+
OnOffServer2({
|
|
174467
|
+
isOn: () => false,
|
|
174468
|
+
// off is a no-op (momentary auto-reset only, script pattern).
|
|
174469
|
+
turnOff: null,
|
|
174470
|
+
turnOn: (_value, agent) => {
|
|
174471
|
+
const ha = agent.get(HomeAssistantEntityBehavior);
|
|
174472
|
+
const { action } = dispatchRoomClean(
|
|
174473
|
+
parentEffective.state.attributes,
|
|
174474
|
+
parentEffective.mapping,
|
|
174475
|
+
ha.entityId,
|
|
174476
|
+
[areaId],
|
|
174477
|
+
{ callAction: (a) => ha.callAction(a) }
|
|
174478
|
+
);
|
|
174479
|
+
return action;
|
|
174480
|
+
}
|
|
174481
|
+
})
|
|
174482
|
+
).set({
|
|
174483
|
+
homeAssistantEntity: {
|
|
174484
|
+
entity: switchEntity,
|
|
174485
|
+
mapping: switchMapping,
|
|
174486
|
+
customName: area.name,
|
|
174487
|
+
// Distinct anchor so uniqueId/serial don't collide with the vacuum's,
|
|
174488
|
+
// and stay frozen across HA renames.
|
|
174489
|
+
identityAnchor: endpointId
|
|
174490
|
+
}
|
|
174491
|
+
});
|
|
174492
|
+
return new _VacuumAreaSwitchEndpoint(
|
|
174493
|
+
type,
|
|
174494
|
+
entity.entity_id,
|
|
174495
|
+
endpointId,
|
|
174496
|
+
areaId,
|
|
174497
|
+
vacuumEndpointId,
|
|
174498
|
+
parentEffective
|
|
174499
|
+
);
|
|
174500
|
+
}
|
|
174501
|
+
async updateStates(states) {
|
|
174502
|
+
const state = states[this.entityId];
|
|
174503
|
+
if (!state) return;
|
|
174504
|
+
try {
|
|
174505
|
+
await this.construction.ready;
|
|
174506
|
+
} catch {
|
|
174507
|
+
return;
|
|
174508
|
+
}
|
|
174509
|
+
try {
|
|
174510
|
+
const current = this.stateOf(HomeAssistantEntityBehavior).entity;
|
|
174511
|
+
await this.setStateOf(HomeAssistantEntityBehavior, {
|
|
174512
|
+
entity: { ...current, state }
|
|
174513
|
+
});
|
|
174514
|
+
} catch (error) {
|
|
174515
|
+
if (error instanceof TransactionDestroyedError || error instanceof DestroyedDependencyError) {
|
|
174516
|
+
return;
|
|
174517
|
+
}
|
|
174518
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
174519
|
+
if (message.includes("Endpoint storage inaccessible")) {
|
|
174520
|
+
return;
|
|
174521
|
+
}
|
|
174522
|
+
throw error;
|
|
174523
|
+
}
|
|
174524
|
+
}
|
|
174525
|
+
};
|
|
174526
|
+
|
|
174377
174527
|
// src/plugins/builtin/camera/camera-plugin.ts
|
|
174378
174528
|
init_esm();
|
|
174379
174529
|
|
|
@@ -176849,8 +176999,8 @@ var BridgeEndpointManager = class extends Service {
|
|
|
176849
176999
|
async isolateEntity(entityName) {
|
|
176850
177000
|
const endpoints = this.root.parts.map((p) => p);
|
|
176851
177001
|
const endpoint = endpoints.find(
|
|
176852
|
-
(e) => e.id === entityName || e.entityId === entityName
|
|
176853
|
-
);
|
|
177002
|
+
(e) => !(e instanceof VacuumAreaSwitchEndpoint) && (e.id === entityName || e.entityId === entityName)
|
|
177003
|
+
) ?? endpoints.find((e) => e.id === entityName);
|
|
176854
177004
|
if (endpoint) {
|
|
176855
177005
|
this.log.warn(
|
|
176856
177006
|
`Isolating entity ${endpoint.entityId} due to runtime error`
|
|
@@ -176862,6 +177012,17 @@ var BridgeEndpointManager = class extends Service {
|
|
|
176862
177012
|
}
|
|
176863
177013
|
this.pendingRemovals.delete(endpoint.entityId);
|
|
176864
177014
|
this.mappingFingerprints.delete(endpoint.entityId);
|
|
177015
|
+
if (!(endpoint instanceof VacuumAreaSwitchEndpoint)) {
|
|
177016
|
+
for (const sw of endpoints) {
|
|
177017
|
+
if (!(sw instanceof VacuumAreaSwitchEndpoint)) continue;
|
|
177018
|
+
if (sw.vacuumEndpointId !== endpoint.id) continue;
|
|
177019
|
+
try {
|
|
177020
|
+
await sw.delete();
|
|
177021
|
+
} catch (e) {
|
|
177022
|
+
this.log.warn(`Failed to remove area switch ${sw.id}:`, e);
|
|
177023
|
+
}
|
|
177024
|
+
}
|
|
177025
|
+
}
|
|
176865
177026
|
}
|
|
176866
177027
|
}
|
|
176867
177028
|
// refreshDevices only runs on registry-fingerprint changes, which may not
|
|
@@ -176947,7 +177108,7 @@ var BridgeEndpointManager = class extends Service {
|
|
|
176947
177108
|
async refreshDevices() {
|
|
176948
177109
|
this.registry.refresh();
|
|
176949
177110
|
this._failedEntities = [];
|
|
176950
|
-
const endpoints = this.root.parts.map((p) => p);
|
|
177111
|
+
const endpoints = this.root.parts.map((p) => p).filter((p) => !(p instanceof VacuumAreaSwitchEndpoint));
|
|
176951
177112
|
this.entityIds = this.registry.entityIds;
|
|
176952
177113
|
if (this.registry.isAutoComposedDevicesEnabled()) {
|
|
176953
177114
|
for (const eid of this.entityIds) {
|
|
@@ -177010,6 +177171,19 @@ var BridgeEndpointManager = class extends Service {
|
|
|
177010
177171
|
this.bridgeId,
|
|
177011
177172
|
buildPresentEntityIds(fullEntities)
|
|
177012
177173
|
);
|
|
177174
|
+
for (const part of [...this.root.parts]) {
|
|
177175
|
+
if (!(part instanceof VacuumAreaSwitchEndpoint)) continue;
|
|
177176
|
+
const claimant = endpointIdToEntity.get(part.id);
|
|
177177
|
+
if (claimant == null) continue;
|
|
177178
|
+
this.log.info(
|
|
177179
|
+
`Area switch ${part.id} collides with entity ${claimant}, removing the switch`
|
|
177180
|
+
);
|
|
177181
|
+
try {
|
|
177182
|
+
await part.delete();
|
|
177183
|
+
} catch (e) {
|
|
177184
|
+
this.log.warn(`Failed to remove colliding area switch ${part.id}:`, e);
|
|
177185
|
+
}
|
|
177186
|
+
}
|
|
177013
177187
|
const existingEndpoints = [];
|
|
177014
177188
|
const now = Date.now();
|
|
177015
177189
|
for (const endpoint of endpoints) {
|
|
@@ -177169,10 +177343,117 @@ var BridgeEndpointManager = class extends Service {
|
|
|
177169
177343
|
}
|
|
177170
177344
|
}
|
|
177171
177345
|
}
|
|
177346
|
+
await this.reconcileAreaSwitches();
|
|
177172
177347
|
if (this.unsubscribe) {
|
|
177173
177348
|
this.startObserving();
|
|
177174
177349
|
}
|
|
177175
177350
|
}
|
|
177351
|
+
// Opt-in per-area room switches (#355). One momentary OnOffPlugInUnit sibling
|
|
177352
|
+
// per configured service area, mounted alongside its vacuum with a stable
|
|
177353
|
+
// derived id. Areas and mapping come from the parent's vacuumEffective, the
|
|
177354
|
+
// exact config its ServiceArea cluster was built from, never from raw storage
|
|
177355
|
+
// (raw can be a different id space: injected Valetudo/Roborock rooms,
|
|
177356
|
+
// auto-resolved CLEAN_AREA). The vacuum's own endpoint is never touched here.
|
|
177357
|
+
// Switches are kept while their parent endpoint survives with the flag on
|
|
177358
|
+
// (the parent's removal grace is mirrored for free), rebuilt via close() when
|
|
177359
|
+
// the parent was recreated for a mapping change so numbers survive, and
|
|
177360
|
+
// deleted when the flag goes off, the area is gone, or the parent is gone.
|
|
177361
|
+
async reconcileAreaSwitches() {
|
|
177362
|
+
const parts = this.root.parts.map((p) => p);
|
|
177363
|
+
const switches = parts.filter(
|
|
177364
|
+
(p) => p instanceof VacuumAreaSwitchEndpoint
|
|
177365
|
+
);
|
|
177366
|
+
const vacuumById = /* @__PURE__ */ new Map();
|
|
177367
|
+
for (const part of parts) {
|
|
177368
|
+
if (part instanceof VacuumAreaSwitchEndpoint) continue;
|
|
177369
|
+
vacuumById.set(part.id, part);
|
|
177370
|
+
}
|
|
177371
|
+
const isolated = new Set(
|
|
177372
|
+
EntityIsolationService.getIsolatedEntities(this.bridgeId).map(
|
|
177373
|
+
(f) => f.entityId
|
|
177374
|
+
)
|
|
177375
|
+
);
|
|
177376
|
+
const parentIsolated = (parent) => isolated.has(parent.id) || parent.entityId != null && isolated.has(parent.entityId);
|
|
177377
|
+
const kept = /* @__PURE__ */ new Set();
|
|
177378
|
+
for (const sw of switches) {
|
|
177379
|
+
const parent = vacuumById.get(sw.vacuumEndpointId);
|
|
177380
|
+
const mapping = parent ? this.getEntityMapping(parent.entityId) : void 0;
|
|
177381
|
+
const effective = parent instanceof LegacyEndpoint ? parent.vacuumEffective : void 0;
|
|
177382
|
+
let keep = false;
|
|
177383
|
+
let rebuild = false;
|
|
177384
|
+
if (parent && !parentIsolated(parent) && mapping?.vacuumRoomSwitches && effective) {
|
|
177385
|
+
const areas = getVacuumServiceAreas(
|
|
177386
|
+
effective.state.attributes,
|
|
177387
|
+
effective.mapping
|
|
177388
|
+
);
|
|
177389
|
+
if (areas.some((a) => a.areaId === sw.areaId)) {
|
|
177390
|
+
if (sw.parentEffective === effective) {
|
|
177391
|
+
keep = true;
|
|
177392
|
+
} else {
|
|
177393
|
+
rebuild = true;
|
|
177394
|
+
}
|
|
177395
|
+
}
|
|
177396
|
+
}
|
|
177397
|
+
if (keep) {
|
|
177398
|
+
kept.add(sw.id);
|
|
177399
|
+
continue;
|
|
177400
|
+
}
|
|
177401
|
+
try {
|
|
177402
|
+
if (rebuild) {
|
|
177403
|
+
await sw.close();
|
|
177404
|
+
} else {
|
|
177405
|
+
await sw.delete();
|
|
177406
|
+
}
|
|
177407
|
+
} catch (e) {
|
|
177408
|
+
this.log.warn(`Failed to remove area switch ${sw.id}:`, e);
|
|
177409
|
+
}
|
|
177410
|
+
}
|
|
177411
|
+
for (const part of vacuumById.values()) {
|
|
177412
|
+
const entityId = part.entityId;
|
|
177413
|
+
if (!entityId?.startsWith("vacuum.")) continue;
|
|
177414
|
+
if (parentIsolated(part)) continue;
|
|
177415
|
+
const mapping = this.getEntityMapping(entityId);
|
|
177416
|
+
if (!mapping?.vacuumRoomSwitches) continue;
|
|
177417
|
+
const effective = part instanceof LegacyEndpoint ? part.vacuumEffective : void 0;
|
|
177418
|
+
if (!effective) continue;
|
|
177419
|
+
const areas = getVacuumServiceAreas(
|
|
177420
|
+
effective.state.attributes,
|
|
177421
|
+
effective.mapping
|
|
177422
|
+
);
|
|
177423
|
+
const entity = {
|
|
177424
|
+
entity_id: entityId,
|
|
177425
|
+
state: effective.state,
|
|
177426
|
+
registry: this.registry.entity(entityId),
|
|
177427
|
+
deviceRegistry: this.registry.deviceOf(entityId)
|
|
177428
|
+
};
|
|
177429
|
+
for (const area of areas) {
|
|
177430
|
+
const switchId = `${part.id}_roomsw_${area.areaId}`;
|
|
177431
|
+
if (kept.has(switchId)) continue;
|
|
177432
|
+
const holder = vacuumById.get(switchId);
|
|
177433
|
+
if (holder) {
|
|
177434
|
+
this.log.warn(
|
|
177435
|
+
`Skipping area switch ${switchId} for ${entityId}: id taken by entity ${holder.entityId}`
|
|
177436
|
+
);
|
|
177437
|
+
continue;
|
|
177438
|
+
}
|
|
177439
|
+
try {
|
|
177440
|
+
const endpoint = VacuumAreaSwitchEndpoint.create({
|
|
177441
|
+
vacuumEndpointId: part.id,
|
|
177442
|
+
entity,
|
|
177443
|
+
mapping: effective.mapping,
|
|
177444
|
+
area,
|
|
177445
|
+
parentEffective: effective
|
|
177446
|
+
});
|
|
177447
|
+
await this.root.add(endpoint);
|
|
177448
|
+
} catch (e) {
|
|
177449
|
+
this.log.warn(
|
|
177450
|
+
`Failed to add area switch ${switchId} for ${entityId}:`,
|
|
177451
|
+
e
|
|
177452
|
+
);
|
|
177453
|
+
}
|
|
177454
|
+
}
|
|
177455
|
+
}
|
|
177456
|
+
}
|
|
177176
177457
|
updateInFlight;
|
|
177177
177458
|
pendingStates;
|
|
177178
177459
|
pendingChanged;
|