update
This commit is contained in:
167
www/community/Ultra-Vehicle-Card/sensors.js
Normal file
167
www/community/Ultra-Vehicle-Card/sensors.js
Normal 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}`;
|
||||
}
|
||||
Reference in New Issue
Block a user