Don't add extra entities for zwave_js controller (#67209)

* Don't add extra entities for zwave_js controller

* Revert reformat of controller_state

* fix indentation issues

* fix indentation issues
This commit is contained in:
Raman Gupta 2022-02-25 01:39:30 -05:00 committed by GitHub
parent 7842d12b75
commit ad4409bcb0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
49 changed files with 247 additions and 54 deletions

View File

@ -293,17 +293,19 @@ async def async_setup_entry( # noqa: C901
async def async_on_node_added(node: ZwaveNode) -> None: async def async_on_node_added(node: ZwaveNode) -> None:
"""Handle node added event.""" """Handle node added event."""
# Create a node status sensor for each device # No need for a ping button or node status sensor for controller nodes
await async_setup_platform(SENSOR_DOMAIN) if not node.is_controller_node:
async_dispatcher_send( # Create a node status sensor for each device
hass, f"{DOMAIN}_{entry.entry_id}_add_node_status_sensor", node await async_setup_platform(SENSOR_DOMAIN)
) async_dispatcher_send(
hass, f"{DOMAIN}_{entry.entry_id}_add_node_status_sensor", node
)
# Create a ping button for each device # Create a ping button for each device
await async_setup_platform(BUTTON_DOMAIN) await async_setup_platform(BUTTON_DOMAIN)
async_dispatcher_send( async_dispatcher_send(
hass, f"{DOMAIN}_{entry.entry_id}_add_ping_button_entity", node hass, f"{DOMAIN}_{entry.entry_id}_add_ping_button_entity", node
) )
# we only want to run discovery when the node has reached ready state, # we only want to run discovery when the node has reached ready state,
# otherwise we'll have all kinds of missing info issues. # otherwise we'll have all kinds of missing info issues.

View File

@ -181,6 +181,12 @@ def controller_state_fixture():
return json.loads(load_fixture("zwave_js/controller_state.json")) return json.loads(load_fixture("zwave_js/controller_state.json"))
@pytest.fixture(name="controller_node_state", scope="session")
def controller_node_state_fixture():
"""Load the controller node state fixture data."""
return json.loads(load_fixture("zwave_js/controller_node_state.json"))
@pytest.fixture(name="version_state", scope="session") @pytest.fixture(name="version_state", scope="session")
def version_state_fixture(): def version_state_fixture():
"""Load the version state fixture data.""" """Load the version state fixture data."""
@ -535,6 +541,14 @@ def mock_client_fixture(controller_state, version_state, log_config_state):
yield client yield client
@pytest.fixture(name="controller_node")
def controller_node_fixture(client, controller_node_state):
"""Mock a controller node."""
node = Node(client, copy.deepcopy(controller_node_state))
client.driver.controller.nodes[node.node_id] = node
return node
@pytest.fixture(name="multisensor_6") @pytest.fixture(name="multisensor_6")
def multisensor_6_fixture(client, multisensor_6_state): def multisensor_6_fixture(client, multisensor_6_state):
"""Mock a multisensor 6 node.""" """Mock a multisensor 6 node."""

View File

@ -1245,5 +1245,6 @@
"label": "Z-Wave chip hardware version" "label": "Z-Wave chip hardware version"
} }
} }
] ],
"isControllerNode": false
} }

View File

@ -616,5 +616,6 @@
"label": "Z-Wave chip hardware version" "label": "Z-Wave chip hardware version"
} }
} }
] ],
"isControllerNode": false
} }

View File

@ -3752,5 +3752,6 @@
} }
], ],
"interviewStage": "Complete", "interviewStage": "Complete",
"deviceDatabaseUrl": "https://devices.zwave-js.io/?jumpTo=0x0371:0x0103:0x00a4:1.3" "deviceDatabaseUrl": "https://devices.zwave-js.io/?jumpTo=0x0371:0x0103:0x00a4:1.3",
"isControllerNode": false
} }

View File

@ -645,5 +645,6 @@
"label": "Z-Wave chip hardware version" "label": "Z-Wave chip hardware version"
} }
} }
] ],
"isControllerNode": false
} }

View File

@ -397,5 +397,6 @@
}, },
"value": 0 "value": 0
} }
] ],
"isControllerNode": false
} }

View File

@ -432,5 +432,6 @@
"1.1" "1.1"
] ]
} }
] ],
"isControllerNode": false
} }

View File

@ -712,5 +712,6 @@
"label": "Z-Wave chip hardware version" "label": "Z-Wave chip hardware version"
} }
} }
] ],
"isControllerNode": false
} }

View File

@ -1440,5 +1440,6 @@
"isSecure": false "isSecure": false
} }
], ],
"interviewStage": "Complete" "interviewStage": "Complete",
"isControllerNode": false
} }

View File

@ -1246,5 +1246,6 @@
"isSecure": true "isSecure": true
} }
], ],
"interviewStage": "Complete" "interviewStage": "Complete",
"isControllerNode": false
} }

View File

@ -1173,5 +1173,6 @@
}, },
"value": 25.5 "value": 25.5
} }
] ],
"isControllerNode": false
} }

View File

@ -826,5 +826,6 @@
"version": 1, "version": 1,
"isSecure": false "isSecure": false
} }
] ],
"isControllerNode": false
} }

View File

@ -1083,5 +1083,6 @@
"version": 3, "version": 3,
"isSecure": false "isSecure": false
} }
] ],
"isControllerNode": false
} }

View File

@ -851,5 +851,6 @@
}, },
"value": false "value": false
} }
] ],
"isControllerNode": false
} }

View File

@ -958,5 +958,6 @@
"version": 1, "version": 1,
"isSecure": false "isSecure": false
} }
] ],
"isControllerNode": false
} }

View File

@ -0,0 +1,104 @@
{
"nodeId": 1,
"index": 0,
"status": 4,
"ready": true,
"isListening": true,
"isRouting": false,
"isSecure": "unknown",
"manufacturerId": 134,
"productId": 90,
"productType": 1,
"firmwareVersion": "1.2",
"deviceConfig": {
"filename": "/data/db/devices/0x0086/zw090.json",
"isEmbedded": true,
"manufacturer": "AEON Labs",
"manufacturerId": 134,
"label": "ZW090",
"description": "Z\u2010Stick Gen5 USB Controller",
"devices": [
{
"productType": 1,
"productId": 90
},
{
"productType": 257,
"productId": 90
},
{
"productType": 513,
"productId": 90
}
],
"firmwareVersion": {
"min": "0.0",
"max": "255.255"
},
"associations": {},
"paramInformation": {
"_map": {}
},
"metadata": {
"reset": "Use this procedure only in the event that the primary controller is missing or otherwise inoperable.\n\nPress and hold the Action Button on Z-Stick for 20 seconds and then release",
"manual": "https://products.z-wavealliance.org/ProductManual/File?folder=&filename=MarketCertificationFiles/1345/Z%20Stick%20Gen5%20manual%201.pdf"
}
},
"label": "ZW090",
"interviewAttempts": 0,
"endpoints": [
{
"nodeId": 1,
"index": 0,
"deviceClass": {
"basic": {
"key": 2,
"label": "Static Controller"
},
"generic": {
"key": 2,
"label": "Static Controller"
},
"specific": {
"key": 1,
"label": "PC Controller"
},
"mandatorySupportedCCs": [],
"mandatoryControlledCCs": [32]
},
"commandClasses": []
}
],
"values": [],
"isFrequentListening": false,
"maxDataRate": 40000,
"supportedDataRates": [40000],
"protocolVersion": 3,
"deviceClass": {
"basic": {
"key": 2,
"label": "Static Controller"
},
"generic": {
"key": 2,
"label": "Static Controller"
},
"specific": {
"key": 1,
"label": "PC Controller"
},
"mandatorySupportedCCs": [],
"mandatoryControlledCCs": [32]
},
"interviewStage": "Complete",
"deviceDatabaseUrl": "https://devices.zwave-js.io/?jumpTo=0x0086:0x0001:0x005a:1.2",
"statistics": {
"commandsTX": 0,
"commandsRX": 0,
"commandsDroppedRX": 0,
"commandsDroppedTX": 0,
"timeoutResponse": 0
},
"isControllerNode": true,
"keepAwake": false
}

View File

@ -494,5 +494,6 @@
} }
], ],
"interviewStage": "Complete", "interviewStage": "Complete",
"deviceDatabaseUrl": "https://devices.zwave-js.io/?jumpTo=0x0371:0x0003:0x008d:3.1" "deviceDatabaseUrl": "https://devices.zwave-js.io/?jumpTo=0x0371:0x0003:0x008d:3.1",
"isControllerNode": false
} }

View File

@ -1129,5 +1129,6 @@
"commandsDroppedRX": 1, "commandsDroppedRX": 1,
"commandsDroppedTX": 0, "commandsDroppedTX": 0,
"timeoutResponse": 0 "timeoutResponse": 0
} },
"isControllerNode": false
} }

View File

@ -353,5 +353,6 @@
"label": "Z-Wave chip hardware version" "label": "Z-Wave chip hardware version"
} }
} }
] ],
"isControllerNode": false
} }

View File

@ -896,5 +896,6 @@
"commandsDroppedRX": 0, "commandsDroppedRX": 0,
"commandsDroppedTX": 0, "commandsDroppedTX": 0,
"timeoutResponse": 0 "timeoutResponse": 0
} },
"isControllerNode": false
} }

View File

@ -917,5 +917,6 @@
"label": "Z-Wave chip hardware version" "label": "Z-Wave chip hardware version"
} }
} }
] ],
"isControllerNode": false
} }

View File

@ -775,5 +775,6 @@
"value": 0, "value": 0,
"ccVersion": 3 "ccVersion": 3
} }
] ],
"isControllerNode": false
} }

View File

@ -325,6 +325,7 @@
"2.0" "2.0"
] ]
} }
] ],
"isControllerNode": false
} }

View File

@ -427,5 +427,6 @@
"3.10" "3.10"
] ]
} }
] ],
"isControllerNode": false
} }

View File

@ -348,5 +348,6 @@
"label": "Z-Wave chip hardware version" "label": "Z-Wave chip hardware version"
} }
} }
] ],
"isControllerNode": false
} }

View File

@ -10502,5 +10502,6 @@
"commandsDroppedRX": 0, "commandsDroppedRX": 0,
"commandsDroppedTX": 0, "commandsDroppedTX": 0,
"timeoutResponse": 2 "timeoutResponse": 2
} },
"isControllerNode": false
} }

View File

@ -346,5 +346,6 @@
"commandsDroppedRX": 0, "commandsDroppedRX": 0,
"commandsDroppedTX": 0, "commandsDroppedTX": 0,
"timeoutResponse": 2 "timeoutResponse": 2
} },
"isControllerNode": false
} }

View File

@ -351,5 +351,6 @@
"commandsDroppedTX": 0, "commandsDroppedTX": 0,
"timeoutResponse": 1 "timeoutResponse": 1
}, },
"highestSecurityClass": -1 "highestSecurityClass": -1,
"isControllerNode": false
} }

View File

@ -638,5 +638,6 @@
"mandatoryControlledCCs": [] "mandatoryControlledCCs": []
}, },
"interviewStage": "Complete", "interviewStage": "Complete",
"deviceDatabaseUrl": "https://devices.zwave-js.io/?jumpTo=0x0063:0x4944:0x3038:5.26" "deviceDatabaseUrl": "https://devices.zwave-js.io/?jumpTo=0x0063:0x4944:0x3038:5.26",
"isControllerNode": false
} }

View File

@ -720,5 +720,6 @@
"label": "Z-Wave chip hardware version" "label": "Z-Wave chip hardware version"
} }
} }
] ],
"isControllerNode": false
} }

View File

@ -1952,5 +1952,6 @@
} }
} }
} }
] ],
"isControllerNode": false
} }

View File

@ -685,5 +685,6 @@
"version": 1, "version": 1,
"isSecure": false "isSecure": false
} }
] ],
"isControllerNode": false
} }

View File

@ -446,5 +446,6 @@
"label": "Z-Wave chip hardware version" "label": "Z-Wave chip hardware version"
} }
} }
] ],
"isControllerNode": false
} }

View File

@ -2915,5 +2915,6 @@
"version": 1, "version": 1,
"isSecure": true "isSecure": true
} }
] ],
"isControllerNode": false
} }

View File

@ -564,5 +564,6 @@
"commandsDroppedRX": 0, "commandsDroppedRX": 0,
"commandsDroppedTX": 0, "commandsDroppedTX": 0,
"timeoutResponse": 0 "timeoutResponse": 0
} },
"isControllerNode": false
} }

View File

@ -2103,5 +2103,6 @@
}, },
"value": 0 "value": 0
} }
] ],
"isControllerNode": false
} }

View File

@ -250,7 +250,8 @@
"label": "Dimming duration" "label": "Dimming duration"
} }
} }
] ],
"isControllerNode": false
}, },
"result": {} "result": {}
} }

View File

@ -1275,5 +1275,6 @@
"label": "Dimming duration" "label": "Dimming duration"
} }
} }
] ],
"isControllerNode": false
} }

View File

@ -410,5 +410,6 @@
"version": 3, "version": 3,
"isSecure": false "isSecure": false
} }
] ],
"isControllerNode": false
} }

View File

@ -258,5 +258,6 @@
"2.0" "2.0"
] ]
} }
] ],
"isControllerNode": false
} }

View File

@ -429,5 +429,6 @@
"version": 1, "version": 1,
"isSecure": false "isSecure": false
} }
] ],
"isControllerNode": false
} }

View File

@ -694,5 +694,6 @@
"label": "Z-Wave chip hardware version" "label": "Z-Wave chip hardware version"
} }
} }
] ],
"isControllerNode": false
} }

View File

@ -2803,5 +2803,6 @@
"version": 1, "version": 1,
"isSecure": true "isSecure": true
} }
] ],
"isControllerNode": false
} }

View File

@ -64,5 +64,6 @@
"commandsDroppedRX": 0, "commandsDroppedRX": 0,
"commandsDroppedTX": 0, "commandsDroppedTX": 0,
"timeoutResponse": 0 "timeoutResponse": 0
} },
"isControllerNode": false
} }

View File

@ -702,5 +702,6 @@
"commandsDroppedTX": 0, "commandsDroppedTX": 0,
"timeoutResponse": 0 "timeoutResponse": 0
}, },
"highestSecurityClass": -1 "highestSecurityClass": -1,
"isControllerNode": false
} }

View File

@ -1,13 +1,16 @@
"""Test the Z-Wave JS button entities.""" """Test the Z-Wave JS button entities."""
from homeassistant.components.button.const import DOMAIN as BUTTON_DOMAIN, SERVICE_PRESS from homeassistant.components.button.const import DOMAIN as BUTTON_DOMAIN, SERVICE_PRESS
from homeassistant.components.zwave_js.const import DOMAIN, SERVICE_REFRESH_VALUE from homeassistant.components.zwave_js.const import DOMAIN, SERVICE_REFRESH_VALUE
from homeassistant.components.zwave_js.helpers import get_valueless_base_unique_id
from homeassistant.const import ATTR_ENTITY_ID from homeassistant.const import ATTR_ENTITY_ID
from homeassistant.helpers.entity_registry import async_get
async def test_ping_entity( async def test_ping_entity(
hass, hass,
client, client,
climate_radio_thermostat_ct100_plus_different_endpoints, climate_radio_thermostat_ct100_plus_different_endpoints,
controller_node,
integration, integration,
caplog, caplog,
): ):
@ -44,3 +47,13 @@ async def test_ping_entity(
) )
assert "There is no value to refresh for this entity" in caplog.text assert "There is no value to refresh for this entity" in caplog.text
# Assert a node ping button entity is not created for the controller
node = client.driver.controller.nodes[1]
assert node.is_controller_node
assert (
async_get(hass).async_get_entity_id(
DOMAIN, "sensor", f"{get_valueless_base_unique_id(client, node)}.ping"
)
is None
)

View File

@ -934,6 +934,7 @@ async def test_replace_same_node(
"commandsDroppedTX": 0, "commandsDroppedTX": 0,
"timeoutResponse": 0, "timeoutResponse": 0,
}, },
"isControllerNode": False,
}, },
"result": {}, "result": {},
}, },
@ -1052,6 +1053,7 @@ async def test_replace_different_node(
"commandsDroppedTX": 0, "commandsDroppedTX": 0,
"timeoutResponse": 0, "timeoutResponse": 0,
}, },
"isControllerNode": False,
}, },
"result": {}, "result": {},
}, },

View File

@ -18,6 +18,7 @@ from homeassistant.components.zwave_js.const import (
SERVICE_REFRESH_VALUE, SERVICE_REFRESH_VALUE,
SERVICE_RESET_METER, SERVICE_RESET_METER,
) )
from homeassistant.components.zwave_js.helpers import get_valueless_base_unique_id
from homeassistant.const import ( from homeassistant.const import (
ATTR_DEVICE_CLASS, ATTR_DEVICE_CLASS,
ATTR_ENTITY_ID, ATTR_ENTITY_ID,
@ -155,7 +156,9 @@ async def test_config_parameter_sensor(hass, lock_id_lock_as_id150, integration)
assert entity_entry.disabled assert entity_entry.disabled
async def test_node_status_sensor(hass, client, lock_id_lock_as_id150, integration): async def test_node_status_sensor(
hass, client, controller_node, lock_id_lock_as_id150, integration
):
"""Test node status sensor is created and gets updated on node state changes.""" """Test node status sensor is created and gets updated on node state changes."""
NODE_STATUS_ENTITY = "sensor.z_wave_module_for_id_lock_150_and_101_node_status" NODE_STATUS_ENTITY = "sensor.z_wave_module_for_id_lock_150_and_101_node_status"
node = lock_id_lock_as_id150 node = lock_id_lock_as_id150
@ -201,6 +204,18 @@ async def test_node_status_sensor(hass, client, lock_id_lock_as_id150, integrati
await client.disconnect() await client.disconnect()
assert hass.states.get(NODE_STATUS_ENTITY).state != STATE_UNAVAILABLE assert hass.states.get(NODE_STATUS_ENTITY).state != STATE_UNAVAILABLE
# Assert a node status sensor entity is not created for the controller
node = client.driver.controller.nodes[1]
assert node.is_controller_node
assert (
ent_reg.async_get_entity_id(
DOMAIN,
"sensor",
f"{get_valueless_base_unique_id(client, node)}.node_status",
)
is None
)
async def test_node_status_sensor_not_ready( async def test_node_status_sensor_not_ready(
hass, hass,