-
-
Notifications
You must be signed in to change notification settings - Fork 305
Zigbee2mqtt: add IEEE address and link to open Z2M #2488
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -1117,6 +1117,8 @@ | |||||
| "mqtt": "MQTT", | ||||||
| "status": "Statut", | ||||||
| "connectionUrl": "URL de l'interface Zigbee2mqtt : <a href=\"{{url}}\" target=\"_blank\">{{url}}</a>", | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add Line 1111 opens a configured URL in a new tab with Suggested fix- "connectionUrl": "URL de l'interface Zigbee2mqtt : <a href=\"{{url}}\" target=\"_blank\">{{url}}</a>",
+ "connectionUrl": "URL de l'interface Zigbee2mqtt : <a href=\"{{url}}\" target=\"_blank\" rel=\"noopener noreferrer\">{{url}}</a>",📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||
| "z2mFrontendUrlLabel": "URL de l'interface Zigbee2mqtt", | ||||||
| "z2mFrontendUrlPlaceholder": "http://192.168.1.x:8080", | ||||||
| "reset": { | ||||||
| "title": "Réinitialiser l'intégration", | ||||||
| "description": "Utilisez cette option si vous souhaitez repartir de zéro avec Zigbee2mqtt. Cela peut être utile si votre configuration est corrompue ou si vous souhaitez changer de coordinateur Zigbee.", | ||||||
|
|
@@ -1145,6 +1147,8 @@ | |||||
| "nameLabel": "Nom", | ||||||
| "namePlaceholder": "Donner un nom à l'appareil", | ||||||
| "roomLabel": "Pièce", | ||||||
| "ieeeAddressLabel": "Adresse IEEE", | ||||||
| "openInZ2mButton": "Ouvrir dans Zigbee2mqtt", | ||||||
| "topicLabel": "Sujet MQTT", | ||||||
| "topicPlaceholder": "%topic% zigbee2mqtt MQTT value", | ||||||
| "featuresLabel": "Fonctionnalités", | ||||||
|
|
||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -9,6 +9,7 @@ import style from './style.css'; | |||||||||||||||||||||||||||||||||||||
| import { DEVICE_FEATURE_CATEGORIES } from '../../../../../../../server/utils/constants'; | ||||||||||||||||||||||||||||||||||||||
| import DeviceFeatures from '../../../../../components/device/view/DeviceFeatures'; | ||||||||||||||||||||||||||||||||||||||
| import BatteryLevelFeature from '../../../../../components/device/view/BatteryLevelFeature'; | ||||||||||||||||||||||||||||||||||||||
| import logoZigbee2mqtt from '../../../../../assets/integrations/logos/logo_zigbee2mqtt.png'; | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| class Zigbee2mqttBox extends Component { | ||||||||||||||||||||||||||||||||||||||
| updateName = e => { | ||||||||||||||||||||||||||||||||||||||
|
|
@@ -164,6 +165,26 @@ class Zigbee2mqttBox extends Component { | |||||||||||||||||||||||||||||||||||||
| </select> | ||||||||||||||||||||||||||||||||||||||
| </div> | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| {props.device.ieee_address && ( | ||||||||||||||||||||||||||||||||||||||
| <div class="form-group"> | ||||||||||||||||||||||||||||||||||||||
| <label class="form-label"> | ||||||||||||||||||||||||||||||||||||||
| <Text id="integration.zigbee2mqtt.ieeeAddressLabel" /> | ||||||||||||||||||||||||||||||||||||||
| </label> | ||||||||||||||||||||||||||||||||||||||
| <input type="text" class="form-control" value={props.device.ieee_address} disabled /> | ||||||||||||||||||||||||||||||||||||||
| {props.z2mUrl && ( | ||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+169
to
+174
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use A disabled input can't be focused or copied normally, which makes the new identifier harder to reuse for support/debug flows. Suggested fix- <div class="form-group">
- <label class="form-label">
+ <div class="form-group">
+ <label class="form-label" for={`ieee_${props.deviceIndex}`}>
<Text id="integration.zigbee2mqtt.ieeeAddressLabel" />
</label>
- <input type="text" class="form-control" value={props.device.ieeeAddress} disabled />
+ <input
+ id={`ieee_${props.deviceIndex}`}
+ type="text"
+ class="form-control"
+ value={props.device.ieeeAddress}
+ readOnly
+ />📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||
| <a | ||||||||||||||||||||||||||||||||||||||
| href={`${props.z2mUrl}/#/device/0/${props.device.ieee_address}`} | ||||||||||||||||||||||||||||||||||||||
| target="_blank" | ||||||||||||||||||||||||||||||||||||||
| rel="noopener noreferrer" | ||||||||||||||||||||||||||||||||||||||
| class={`${style.z2mDeviceLink} mt-2 text-muted`} | ||||||||||||||||||||||||||||||||||||||
| > | ||||||||||||||||||||||||||||||||||||||
| <img src={logoZigbee2mqtt} alt="Zigbee2mqtt" class={style.z2mDeviceLinkLogo} /> | ||||||||||||||||||||||||||||||||||||||
| <Text id="integration.zigbee2mqtt.openInZ2mButton" /> | ||||||||||||||||||||||||||||||||||||||
| </a> | ||||||||||||||||||||||||||||||||||||||
| )} | ||||||||||||||||||||||||||||||||||||||
| </div> | ||||||||||||||||||||||||||||||||||||||
| )} | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| <div class="form-group"> | ||||||||||||||||||||||||||||||||||||||
| <label class="form-label"> | ||||||||||||||||||||||||||||||||||||||
| <Text id="integration.zigbee2mqtt.featuresLabel" /> | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -4,11 +4,28 @@ import uuid from 'uuid'; | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import debounce from 'debounce'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import createActionsIntegration from '../../../../../actions/integration'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import createActionsHouse from '../../../../../actions/house'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import config from '../../../../../config'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| function createActions(store) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const integrationActions = createActionsIntegration(store); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const houseActions = createActionsHouse(store); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const actions = { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| async getZ2mUrl(state) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const configuration = await state.httpClient.get('/api/v1/service/zigbee2mqtt/setup'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (configuration.Z2M_MQTT_MODE === 'local') { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (configuration.z2mTcpPort && state.session.gatewayClient === undefined) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const url = new URL(config.localApiUrl); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const z2mUrl = `${url.protocol}//${url.hostname}:${configuration.z2mTcpPort}`; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| store.setState({ z2mUrl }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } else if (configuration.Z2M_MQTT_MODE === 'external' && configuration.Z2M_FRONTEND_URL) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| store.setState({ z2mUrl: configuration.Z2M_FRONTEND_URL }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } catch (e) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // z2mUrl stays undefined, link won't be shown | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+13
to
+27
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Clear stale Lines 13-27 only write Suggested fix async getZ2mUrl(state) {
+ store.setState({ z2mUrl: undefined });
try {
const configuration = await state.httpClient.get('/api/v1/service/zigbee2mqtt/setup');
if (configuration.Z2M_MQTT_MODE === 'local') {
if (configuration.z2mTcpPort && state.session.gatewayClient === undefined) {
const url = new URL(config.localApiUrl);📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| async getZigbee2mqttDevices(state, take, skip) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| store.setState({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| getZigbee2mqttStatus: RequestStatus.Getting | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -23,12 +40,26 @@ function createActions(store) { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| options.search = state.zigbee2mqttSearch; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const zigbee2mqttsReceived = await state.httpClient.get('/api/v1/service/zigbee2mqtt/device', options); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const [zigbee2mqttsReceived, discoveredDevices] = await Promise.all([ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| state.httpClient.get('/api/v1/service/zigbee2mqtt/device', options), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| state.httpClient.get('/api/v1/service/zigbee2mqtt/discovered', { filter_existing: false }) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ]); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+43
to
+46
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Don’t make IEEE enrichment a hard dependency for loading devices. Lines 46-49 reject the whole action if Suggested fix- const [zigbee2mqttsReceived, discoveredDevices] = await Promise.all([
- state.httpClient.get('/api/v1/service/zigbee2mqtt/device', options),
- state.httpClient.get('/api/v1/service/zigbee2mqtt/discovered', { filter_existing: false })
- ]);
+ const [zigbee2mqttsReceived, discoveredDevices] = await Promise.all([
+ state.httpClient.get('/api/v1/service/zigbee2mqtt/device', options),
+ state.httpClient
+ .get('/api/v1/service/zigbee2mqtt/discovered', { filter_existing: false })
+ .catch(() => [])
+ ]);Based on learnings: degraded-mode return is preferred over throwing errors because preserving available data is more useful than failing fast; discovery should remain resilient. 📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const discoveredMap = {}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| discoveredDevices.forEach(d => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| discoveredMap[d.external_id] = d; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| zigbee2mqttsReceived.forEach(device => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const model = device.params.find(p => p.name === 'model'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (model) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| device.model = model.value; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const discovered = discoveredMap[device.external_id]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (discovered && discovered.ieee_address) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| device.ieee_address = discovered.ieee_address; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let zigbee2mqttDevices; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add
rel="noopener noreferrer"to this external link.This new
target="_blank"link reintroduces an opener relationship. Please keep it aligned with the rest of the file’s external links.Suggested fix
📝 Committable suggestion
🤖 Prompt for AI Agents