This commit is contained in:
2024-10-13 22:59:09 +02:00
parent 63fb7f8f73
commit e426efb80f
107 changed files with 20616 additions and 5533 deletions

View File

@@ -0,0 +1,167 @@
export function formatEntityValue(entity, useFormattedEntities, hass, localize) {
if (!entity || !hass) return null;
// If formatting is not enabled, return the state as-is
if (!useFormattedEntities) {
return entity.state;
}
// Use Home Assistant's built-in formatting functions
if (typeof hass.formatEntityState === 'function') {
return hass.formatEntityState(entity);
}
// Fallback to basic formatting if Home Assistant functions are not available
return entity.state;
}
function formatBinaryState(state, attributes, hass, localize) {
const isOn = state.toLowerCase() === 'on';
if (attributes.device_class) {
const key = `state.${attributes.device_class}.${isOn ? 'on' : 'off'}`;
return hass.localize(`component.binary_sensor.${key}`) || localize(key) || (isOn ? 'On' : 'Off');
}
return isOn ? 'On' : 'Off';
}
function formatDeviceTrackerState(state, attributes) {
const locationName = attributes.location_name || state;
if (locationName.toLowerCase() === 'home') {
return 'Home';
} else if (locationName.toLowerCase() === 'not_home') {
return 'Away';
} else {
return locationName.split('_').map(word => word.charAt(0).toUpperCase() + word.slice(1)).join(' ');
}
}
function formatSensorState(state, attributes) {
if (isISODateString(state)) {
return formatChargingEndTime(state);
}
if (!isNaN(parseFloat(state))) {
// Remove trailing zeros and decimal point if necessary
return formatNumberWithCommas(parseFloat(state).toFixed(0));
}
return formatGenericState(state);
}
function formatGenericState(state) {
// Convert snake_case to Title Case
return state.split('_').map(word => word.charAt(0).toUpperCase() + word.slice(1)).join(' ');
}
export async function getIconActiveState(entityId, hass, config) {
const state = hass.states[entityId];
if (!state) return false;
const stateStr = state.state.toLowerCase();
// Check custom active and inactive states from config
const activeState = config.activeState;
const inactiveState = config.inactiveState;
if (activeState) {
if (activeState === 'default') {
return isActiveState(stateStr);
} else if (activeState.startsWith('template:')) {
const templateResp = await (new Promise((resolve, reject) => {
hass.connection.subscribeMessage(
(msg) => resolve(msg),
{
type: "render_template",
template: activeState.slice(9),
}
)
}));
return templateResp.result === true ? true : false;
} else if (activeState.startsWith('attribute:')) {
const [, attributeName, attributeValue] = activeState.split(':');
return state.attributes[attributeName] === attributeValue;
} else if (activeState.startsWith('option:')) {
return stateStr === activeState.split(':')[1].toLowerCase();
} else {
return stateStr === activeState.toLowerCase();
}
}
if (inactiveState) {
if (inactiveState === 'default') {
return !isActiveState(stateStr);
} else if (inactiveState.startsWith('template:')) {
const renderResult = await hass.callApi("post", "template", {template: inactiveState.slice(9)});
return renderResult === "True" ? true : false;
} else if (inactiveState.startsWith('attribute:')) {
const [, attributeName, attributeValue] = inactiveState.split(':');
return state.attributes[attributeName] !== attributeValue;
} else if (inactiveState.startsWith('option:')) {
return stateStr !== inactiveState.split(':')[1].toLowerCase();
} else {
return stateStr !== inactiveState.toLowerCase();
}
}
// If no custom states are set, use the default behavior
return isActiveState(stateStr);
}
function isActiveState(state) {
const activeStates = [
"on", "active", "open", "connected", "running", "true", "1", "home", "above_horizon",
"charging", "full", "yes", "online", "present",
"armed", "occupied", "unlocked", "playing", "motion", "engaged", "awake", "detected"
];
return activeStates.includes(state);
}
export function formatBinarySensorState(state, attributes) {
return state;
}
export function isEngineOn(engineOnEntity) {
if (!engineOnEntity) return false;
const state = engineOnEntity.state.toLowerCase();
const attributes = engineOnEntity.attributes;
// Check attributes for 'engine_on' status
if (attributes) {
for (const [key, value] of Object.entries(attributes)) {
if (typeof value === 'string' && value.toLowerCase() === 'on') {
return true;
}
}
}
// Handle boolean entities
if (['on', 'off', 'true', 'false'].includes(state)) {
return state === 'on' || state === 'true';
}
// Handle numeric entities
if (!isNaN(state)) {
return parseFloat(state) > 0;
}
// Handle string-based entities
const engineOnStates = ['on', 'running', 'active', 'true'];
return engineOnStates.includes(state);
}
function formatNumberWithCommas(number) {
return number.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}
function isISODateString(value) {
return /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d{3})?Z$/.test(value);
}
function formatChargingEndTime(isoDateString) {
const date = new Date(isoDateString);
const hours = date.getHours();
const minutes = date.getMinutes();
const ampm = hours >= 12 ? "PM" : "AM";
const formattedHours = hours % 12 || 12;
const formattedMinutes = minutes < 10 ? `0${minutes}` : minutes;
return `${formattedHours}:${formattedMinutes} ${ampm}`;
}