mirror of https://github.com/bastienwirtz/homer
Merge 94a4ce3b77
into 308deb95e0
commit
d6c2c000a1
|
@ -226,6 +226,7 @@ The Healthchecks API key can be found in Settings > API Access > API key (read-o
|
||||||
|
|
||||||
You need to set the type to HomeAssistant, provide an api key and enable cors on Home Assistant.
|
You need to set the type to HomeAssistant, provide an api key and enable cors on Home Assistant.
|
||||||
|
|
||||||
|
**Basic configuration:**
|
||||||
```yaml
|
```yaml
|
||||||
- name: "HomeAssistant"
|
- name: "HomeAssistant"
|
||||||
logo: "assets/tools/sample.png"
|
logo: "assets/tools/sample.png"
|
||||||
|
@ -236,6 +237,35 @@ You need to set the type to HomeAssistant, provide an api key and enable cors on
|
||||||
separator: " " # optional, how to separate items
|
separator: " " # optional, how to separate items
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**Custom sensors configuration:**
|
||||||
|
```yaml
|
||||||
|
- name: "Home Assistant"
|
||||||
|
logo: "assets/tools/sample.png"
|
||||||
|
url: "http://192.168.0.151/"
|
||||||
|
type: "HomeAssistant"
|
||||||
|
apikey: "<---insert-api-key-here--->"
|
||||||
|
showUnits: true # Optional: Show units from Home Assistant (default: true)
|
||||||
|
updateInterval: 30000 # Optional: Sensor refresh interval in ms (default: 30000)
|
||||||
|
sensors: # Optional: Display custom sensors instead of default stats
|
||||||
|
- id: "sensor.living_room_temperature"
|
||||||
|
icon: "fas fa-home"
|
||||||
|
- id: "sensor.bedroom_humidity"
|
||||||
|
icon: "fas fa-bed"
|
||||||
|
- id: "sensor.power_consumption"
|
||||||
|
icon: "fas fa-bolt"
|
||||||
|
- id: "sensor.outdoor_air_quality"
|
||||||
|
icon: "fas fa-cloud-sun"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Configuration Options:**
|
||||||
|
|
||||||
|
- When `sensors` is provided, the service displays sensor readings with custom icons instead of the default version/entity information
|
||||||
|
- `showUnits`: Controls whether to display units from Home Assistant (default: `true`)
|
||||||
|
- `updateInterval`: How often to refresh sensor data in milliseconds (default: `30000`)
|
||||||
|
- Sensor values are automatically formatted to 1 decimal place with units (when enabled)
|
||||||
|
- Supports any numeric sensor type (temperature, humidity, power, etc.)
|
||||||
|
- Falls back to original behavior if `sensors` is not configured
|
||||||
|
|
||||||
To create an API token on HomeAssistant, follow the [official documentation here](https://developers.home-assistant.io/docs/auth_api/#long-lived-access-token).
|
To create an API token on HomeAssistant, follow the [official documentation here](https://developers.home-assistant.io/docs/auth_api/#long-lived-access-token).
|
||||||
To enable cors on HomeAssistant, edit your `configuration.yml` and add the IP of Homer to `https: cors_allowed_origins`
|
To enable cors on HomeAssistant, edit your `configuration.yml` and add the IP of Homer to `https: cors_allowed_origins`
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,18 @@
|
||||||
<template v-if="item.subtitle">
|
<template v-if="item.subtitle">
|
||||||
{{ item.subtitle }}
|
{{ item.subtitle }}
|
||||||
</template>
|
</template>
|
||||||
|
<template v-else-if="item.sensors && sensors.length > 0">
|
||||||
|
<span class="sensors">
|
||||||
|
<span
|
||||||
|
v-for="(sensor, index) in sensors"
|
||||||
|
:key="index"
|
||||||
|
class="sensor"
|
||||||
|
>
|
||||||
|
<i :class="sensor.icon"></i>
|
||||||
|
<span class="sensor-value">{{ sensor.value }}</span>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
{{ details }}
|
{{ details }}
|
||||||
</template>
|
</template>
|
||||||
|
@ -35,6 +47,7 @@ export default {
|
||||||
location_name: "",
|
location_name: "",
|
||||||
separator: " ",
|
separator: " ",
|
||||||
items: ["name", "version"],
|
items: ["name", "version"],
|
||||||
|
sensors: [],
|
||||||
}),
|
}),
|
||||||
computed: {
|
computed: {
|
||||||
headers: function () {
|
headers: function () {
|
||||||
|
@ -70,6 +83,15 @@ export default {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
|
if (this.item.sensors) {
|
||||||
|
// If sensors are configured, fetch sensor data
|
||||||
|
this.fetchSensors();
|
||||||
|
|
||||||
|
// Set up configurable refresh interval (default 30 seconds)
|
||||||
|
const updateInterval = parseInt(this.item.updateInterval, 10) || 30000;
|
||||||
|
setInterval(() => this.fetchSensors(), updateInterval);
|
||||||
|
} else {
|
||||||
|
// Original behavior for status/stats
|
||||||
this.fetchServerStatus().then(() => {
|
this.fetchServerStatus().then(() => {
|
||||||
if (!this.item.subtitle && this.status !== "dead") {
|
if (!this.item.subtitle && this.status !== "dead") {
|
||||||
if (this.item.items) this.items = this.item.items;
|
if (this.item.items) this.items = this.item.items;
|
||||||
|
@ -78,8 +100,37 @@ export default {
|
||||||
this.fetchServerStats();
|
this.fetchServerStats();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
fetchSensors: async function () {
|
||||||
|
const headers = this.headers;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await this.fetch("/api/states", { headers });
|
||||||
|
|
||||||
|
// Use configurable sensors from item.sensors
|
||||||
|
this.sensors = this.item.sensors
|
||||||
|
.map((sensorConfig) => {
|
||||||
|
const match = response.find((s) => s.entity_id === sensorConfig.id);
|
||||||
|
if (match && !isNaN(parseFloat(match.state))) {
|
||||||
|
const value = parseFloat(match.state).toFixed(1);
|
||||||
|
const unit = match.attributes?.unit_of_measurement || "";
|
||||||
|
const showUnits = this.item.showUnits !== false; // Default to true
|
||||||
|
return {
|
||||||
|
icon: sensorConfig.icon,
|
||||||
|
value: (showUnits && unit) ? `${value}${unit}` : value,
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.filter(Boolean); // Remove null entries
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Failed to fetch sensors:", error);
|
||||||
|
this.sensors = [];
|
||||||
|
}
|
||||||
|
},
|
||||||
fetchServerStatus: async function () {
|
fetchServerStatus: async function () {
|
||||||
const headers = this.headers;
|
const headers = this.headers;
|
||||||
|
|
||||||
|
@ -151,4 +202,16 @@ export default {
|
||||||
border-radius: 7px;
|
border-radius: 7px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.sensors {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sensor {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 4px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
Loading…
Reference in New Issue