mirror of
https://github.com/adrianjagielak/home-assistant-futurehome.git
synced 2025-09-13 15:47:08 +00:00
Add support for 'schedule_entry' service
This commit is contained in:
parent
5264f84fbf
commit
f01494caa8
@ -8,6 +8,7 @@
|
|||||||
- Added support for 'sound_switch' service (sound emitters).
|
- Added support for 'sound_switch' service (sound emitters).
|
||||||
- Added support for 'door_lock' service (door locks).
|
- Added support for 'door_lock' service (door locks).
|
||||||
- Added support for 'user_code' service (keypads).
|
- Added support for 'user_code' service (keypads).
|
||||||
|
- Added support for 'schedule_entry' service (for scheduling access).
|
||||||
|
|
||||||
## 0.1.5 (25.07.2025)
|
## 0.1.5 (25.07.2025)
|
||||||
|
|
||||||
|
File diff suppressed because one or more lines are too long
@ -20,6 +20,7 @@ import { media_player__components } from '../services/media_player';
|
|||||||
import { out_bin_switch__components } from '../services/out_bin_switch';
|
import { out_bin_switch__components } from '../services/out_bin_switch';
|
||||||
import { out_lvl_switch__components } from '../services/out_lvl_switch';
|
import { out_lvl_switch__components } from '../services/out_lvl_switch';
|
||||||
import { scene_ctrl__components } from '../services/scene_ctrl';
|
import { scene_ctrl__components } from '../services/scene_ctrl';
|
||||||
|
import { schedule_entry__components } from '../services/schedule_entry';
|
||||||
import { siren_ctrl__components } from '../services/siren_ctrl';
|
import { siren_ctrl__components } from '../services/siren_ctrl';
|
||||||
import { sound_switch__components } from '../services/sound_switch';
|
import { sound_switch__components } from '../services/sound_switch';
|
||||||
import { thermostat__components } from '../services/thermostat';
|
import { thermostat__components } from '../services/thermostat';
|
||||||
@ -163,6 +164,7 @@ const serviceHandlers: {
|
|||||||
out_bin_switch: out_bin_switch__components,
|
out_bin_switch: out_bin_switch__components,
|
||||||
out_lvl_switch: out_lvl_switch__components,
|
out_lvl_switch: out_lvl_switch__components,
|
||||||
scene_ctrl: scene_ctrl__components,
|
scene_ctrl: scene_ctrl__components,
|
||||||
|
schedule_entry: schedule_entry__components,
|
||||||
sensor_accelx: _sensor_numeric__components,
|
sensor_accelx: _sensor_numeric__components,
|
||||||
sensor_accely: _sensor_numeric__components,
|
sensor_accely: _sensor_numeric__components,
|
||||||
sensor_accelz: _sensor_numeric__components,
|
sensor_accelz: _sensor_numeric__components,
|
||||||
|
451
futurehome/src/services/schedule_entry.ts
Normal file
451
futurehome/src/services/schedule_entry.ts
Normal file
@ -0,0 +1,451 @@
|
|||||||
|
import { sendFimpMsg } from '../fimp/fimp';
|
||||||
|
import {
|
||||||
|
VinculumPd7Device,
|
||||||
|
VinculumPd7Service,
|
||||||
|
} from '../fimp/vinculum_pd7_device';
|
||||||
|
import { HaMqttComponent } from '../ha/mqtt_components/_component';
|
||||||
|
import {
|
||||||
|
CommandHandlers,
|
||||||
|
ServiceComponentsCreationResult,
|
||||||
|
} from '../ha/publish_device';
|
||||||
|
|
||||||
|
interface ScheduleEntry {
|
||||||
|
slot: number;
|
||||||
|
user_id: number;
|
||||||
|
year_start?: number;
|
||||||
|
month_start?: number;
|
||||||
|
day_start?: number;
|
||||||
|
hour_start?: number;
|
||||||
|
minute_start?: number;
|
||||||
|
year_end?: number;
|
||||||
|
month_end?: number;
|
||||||
|
day_end?: number;
|
||||||
|
hour_end?: number;
|
||||||
|
minute_end?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function schedule_entry__components(
|
||||||
|
topicPrefix: string,
|
||||||
|
device: VinculumPd7Device,
|
||||||
|
svc: VinculumPd7Service,
|
||||||
|
_svcName: string,
|
||||||
|
): ServiceComponentsCreationResult | undefined {
|
||||||
|
const components: Record<string, HaMqttComponent> = {};
|
||||||
|
const commandHandlers: CommandHandlers = {};
|
||||||
|
|
||||||
|
const slots = svc.props?.slots || 1;
|
||||||
|
|
||||||
|
// For each slot, create management controls
|
||||||
|
for (let slot = 1; slot <= slots; slot++) {
|
||||||
|
const slotPrefix = `${svc.addr}_slot_${slot}`;
|
||||||
|
|
||||||
|
// User ID selector for this slot
|
||||||
|
const userIdCommandTopic = `${topicPrefix}${svc.addr}/slot_${slot}/user_id/command`;
|
||||||
|
components[`${slotPrefix}_user_id`] = {
|
||||||
|
unique_id: `${slotPrefix}_user_id`,
|
||||||
|
platform: 'number',
|
||||||
|
name: `Schedule Slot ${slot} User ID`,
|
||||||
|
entity_category: 'config',
|
||||||
|
min: 1,
|
||||||
|
max: 254, // Typical user code range
|
||||||
|
step: 1,
|
||||||
|
mode: 'box',
|
||||||
|
command_topic: userIdCommandTopic,
|
||||||
|
optimistic: false,
|
||||||
|
value_template: `{% set entries = value_json['${svc.addr}'] %}{% for key, entry in entries.items() %}{% if entry.slot == ${slot} %}{{ entry.user_id }}{% endif %}{% endfor %}`,
|
||||||
|
icon: 'mdi:account-key',
|
||||||
|
};
|
||||||
|
|
||||||
|
// Year start selector
|
||||||
|
const yearStartCommandTopic = `${topicPrefix}${svc.addr}/slot_${slot}/year_start/command`;
|
||||||
|
components[`${slotPrefix}_year_start`] = {
|
||||||
|
unique_id: `${slotPrefix}_year_start`,
|
||||||
|
platform: 'number',
|
||||||
|
name: `Schedule Slot ${slot} Start Year`,
|
||||||
|
entity_category: 'config',
|
||||||
|
min: 0,
|
||||||
|
max: 99,
|
||||||
|
step: 1,
|
||||||
|
mode: 'box',
|
||||||
|
command_topic: yearStartCommandTopic,
|
||||||
|
optimistic: false,
|
||||||
|
value_template: `{% set entries = value_json['${svc.addr}'] %}{% for key, entry in entries.items() %}{% if entry.slot == ${slot} %}{{ entry.year_start | default(0) }}{% endif %}{% endfor %}`,
|
||||||
|
icon: 'mdi:calendar-start',
|
||||||
|
};
|
||||||
|
|
||||||
|
// Month start selector
|
||||||
|
const monthStartCommandTopic = `${topicPrefix}${svc.addr}/slot_${slot}/month_start/command`;
|
||||||
|
components[`${slotPrefix}_month_start`] = {
|
||||||
|
unique_id: `${slotPrefix}_month_start`,
|
||||||
|
platform: 'number',
|
||||||
|
name: `Schedule Slot ${slot} Start Month`,
|
||||||
|
entity_category: 'config',
|
||||||
|
min: 1,
|
||||||
|
max: 12,
|
||||||
|
step: 1,
|
||||||
|
mode: 'box',
|
||||||
|
command_topic: monthStartCommandTopic,
|
||||||
|
optimistic: false,
|
||||||
|
value_template: `{% set entries = value_json['${svc.addr}'] %}{% for key, entry in entries.items() %}{% if entry.slot == ${slot} %}{{ entry.month_start | default(1) }}{% endif %}{% endfor %}`,
|
||||||
|
icon: 'mdi:calendar-month',
|
||||||
|
};
|
||||||
|
|
||||||
|
// Day start selector
|
||||||
|
const dayStartCommandTopic = `${topicPrefix}${svc.addr}/slot_${slot}/day_start/command`;
|
||||||
|
components[`${slotPrefix}_day_start`] = {
|
||||||
|
unique_id: `${slotPrefix}_day_start`,
|
||||||
|
platform: 'number',
|
||||||
|
name: `Schedule Slot ${slot} Start Day`,
|
||||||
|
entity_category: 'config',
|
||||||
|
min: 1,
|
||||||
|
max: 31,
|
||||||
|
step: 1,
|
||||||
|
mode: 'box',
|
||||||
|
command_topic: dayStartCommandTopic,
|
||||||
|
optimistic: false,
|
||||||
|
value_template: `{% set entries = value_json['${svc.addr}'] %}{% for key, entry in entries.items() %}{% if entry.slot == ${slot} %}{{ entry.day_start | default(1) }}{% endif %}{% endfor %}`,
|
||||||
|
icon: 'mdi:calendar-today',
|
||||||
|
};
|
||||||
|
|
||||||
|
// Hour start selector
|
||||||
|
const hourStartCommandTopic = `${topicPrefix}${svc.addr}/slot_${slot}/hour_start/command`;
|
||||||
|
components[`${slotPrefix}_hour_start`] = {
|
||||||
|
unique_id: `${slotPrefix}_hour_start`,
|
||||||
|
platform: 'number',
|
||||||
|
name: `Schedule Slot ${slot} Start Hour`,
|
||||||
|
entity_category: 'config',
|
||||||
|
min: 0,
|
||||||
|
max: 23,
|
||||||
|
step: 1,
|
||||||
|
mode: 'box',
|
||||||
|
command_topic: hourStartCommandTopic,
|
||||||
|
optimistic: false,
|
||||||
|
value_template: `{% set entries = value_json['${svc.addr}'] %}{% for key, entry in entries.items() %}{% if entry.slot == ${slot} %}{{ entry.hour_start | default(0) }}{% endif %}{% endfor %}`,
|
||||||
|
icon: 'mdi:clock-start',
|
||||||
|
};
|
||||||
|
|
||||||
|
// Minute start selector
|
||||||
|
const minuteStartCommandTopic = `${topicPrefix}${svc.addr}/slot_${slot}/minute_start/command`;
|
||||||
|
components[`${slotPrefix}_minute_start`] = {
|
||||||
|
unique_id: `${slotPrefix}_minute_start`,
|
||||||
|
platform: 'number',
|
||||||
|
name: `Schedule Slot ${slot} Start Minute`,
|
||||||
|
entity_category: 'config',
|
||||||
|
min: 0,
|
||||||
|
max: 59,
|
||||||
|
step: 1,
|
||||||
|
mode: 'box',
|
||||||
|
command_topic: minuteStartCommandTopic,
|
||||||
|
optimistic: false,
|
||||||
|
value_template: `{% set entries = value_json['${svc.addr}'] %}{% for key, entry in entries.items() %}{% if entry.slot == ${slot} %}{{ entry.minute_start | default(0) }}{% endif %}{% endfor %}`,
|
||||||
|
icon: 'mdi:clock-start',
|
||||||
|
};
|
||||||
|
|
||||||
|
// Year end selector
|
||||||
|
const yearEndCommandTopic = `${topicPrefix}${svc.addr}/slot_${slot}/year_end/command`;
|
||||||
|
components[`${slotPrefix}_year_end`] = {
|
||||||
|
unique_id: `${slotPrefix}_year_end`,
|
||||||
|
platform: 'number',
|
||||||
|
name: `Schedule Slot ${slot} End Year`,
|
||||||
|
entity_category: 'config',
|
||||||
|
min: 0,
|
||||||
|
max: 99,
|
||||||
|
step: 1,
|
||||||
|
mode: 'box',
|
||||||
|
command_topic: yearEndCommandTopic,
|
||||||
|
optimistic: false,
|
||||||
|
value_template: `{% set entries = value_json['${svc.addr}'] %}{% for key, entry in entries.items() %}{% if entry.slot == ${slot} %}{{ entry.year_end | default(99) }}{% endif %}{% endfor %}`,
|
||||||
|
icon: 'mdi:calendar-end',
|
||||||
|
};
|
||||||
|
|
||||||
|
// Month end selector
|
||||||
|
const monthEndCommandTopic = `${topicPrefix}${svc.addr}/slot_${slot}/month_end/command`;
|
||||||
|
components[`${slotPrefix}_month_end`] = {
|
||||||
|
unique_id: `${slotPrefix}_month_end`,
|
||||||
|
platform: 'number',
|
||||||
|
name: `Schedule Slot ${slot} End Month`,
|
||||||
|
entity_category: 'config',
|
||||||
|
min: 1,
|
||||||
|
max: 12,
|
||||||
|
step: 1,
|
||||||
|
mode: 'box',
|
||||||
|
command_topic: monthEndCommandTopic,
|
||||||
|
optimistic: false,
|
||||||
|
value_template: `{% set entries = value_json['${svc.addr}'] %}{% for key, entry in entries.items() %}{% if entry.slot == ${slot} %}{{ entry.month_end | default(12) }}{% endif %}{% endfor %}`,
|
||||||
|
icon: 'mdi:calendar-month',
|
||||||
|
};
|
||||||
|
|
||||||
|
// Day end selector
|
||||||
|
const dayEndCommandTopic = `${topicPrefix}${svc.addr}/slot_${slot}/day_end/command`;
|
||||||
|
components[`${slotPrefix}_day_end`] = {
|
||||||
|
unique_id: `${slotPrefix}_day_end`,
|
||||||
|
platform: 'number',
|
||||||
|
name: `Schedule Slot ${slot} End Day`,
|
||||||
|
entity_category: 'config',
|
||||||
|
min: 1,
|
||||||
|
max: 31,
|
||||||
|
step: 1,
|
||||||
|
mode: 'box',
|
||||||
|
command_topic: dayEndCommandTopic,
|
||||||
|
optimistic: false,
|
||||||
|
value_template: `{% set entries = value_json['${svc.addr}'] %}{% for key, entry in entries.items() %}{% if entry.slot == ${slot} %}{{ entry.day_end | default(31) }}{% endif %}{% endfor %}`,
|
||||||
|
icon: 'mdi:calendar-today',
|
||||||
|
};
|
||||||
|
|
||||||
|
// Hour end selector
|
||||||
|
const hourEndCommandTopic = `${topicPrefix}${svc.addr}/slot_${slot}/hour_end/command`;
|
||||||
|
components[`${slotPrefix}_hour_end`] = {
|
||||||
|
unique_id: `${slotPrefix}_hour_end`,
|
||||||
|
platform: 'number',
|
||||||
|
name: `Schedule Slot ${slot} End Hour`,
|
||||||
|
entity_category: 'config',
|
||||||
|
min: 0,
|
||||||
|
max: 23,
|
||||||
|
step: 1,
|
||||||
|
mode: 'box',
|
||||||
|
command_topic: hourEndCommandTopic,
|
||||||
|
optimistic: false,
|
||||||
|
value_template: `{% set entries = value_json['${svc.addr}'] %}{% for key, entry in entries.items() %}{% if entry.slot == ${slot} %}{{ entry.hour_end | default(23) }}{% endif %}{% endfor %}`,
|
||||||
|
icon: 'mdi:clock-end',
|
||||||
|
};
|
||||||
|
|
||||||
|
// Minute end selector
|
||||||
|
const minuteEndCommandTopic = `${topicPrefix}${svc.addr}/slot_${slot}/minute_end/command`;
|
||||||
|
components[`${slotPrefix}_minute_end`] = {
|
||||||
|
unique_id: `${slotPrefix}_minute_end`,
|
||||||
|
platform: 'number',
|
||||||
|
name: `Schedule Slot ${slot} End Minute`,
|
||||||
|
entity_category: 'config',
|
||||||
|
min: 0,
|
||||||
|
max: 59,
|
||||||
|
step: 1,
|
||||||
|
mode: 'box',
|
||||||
|
command_topic: minuteEndCommandTopic,
|
||||||
|
optimistic: false,
|
||||||
|
value_template: `{% set entries = value_json['${svc.addr}'] %}{% for key, entry in entries.items() %}{% if entry.slot == ${slot} %}{{ entry.minute_end | default(59) }}{% endif %}{% endfor %}`,
|
||||||
|
icon: 'mdi:clock-end',
|
||||||
|
};
|
||||||
|
|
||||||
|
// Clear schedule button for this slot
|
||||||
|
const clearCommandTopic = `${topicPrefix}${svc.addr}/slot_${slot}/clear/command`;
|
||||||
|
components[`${slotPrefix}_clear`] = {
|
||||||
|
unique_id: `${slotPrefix}_clear`,
|
||||||
|
platform: 'button',
|
||||||
|
name: `Clear Schedule Slot ${slot}`,
|
||||||
|
entity_category: 'config',
|
||||||
|
command_topic: clearCommandTopic,
|
||||||
|
icon: 'mdi:delete-sweep',
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get report button for this slot
|
||||||
|
const getReportCommandTopic = `${topicPrefix}${svc.addr}/slot_${slot}/get_report/command`;
|
||||||
|
components[`${slotPrefix}_get_report`] = {
|
||||||
|
unique_id: `${slotPrefix}_get_report`,
|
||||||
|
platform: 'button',
|
||||||
|
name: `Get Schedule Slot ${slot} Report`,
|
||||||
|
entity_category: 'diagnostic',
|
||||||
|
command_topic: getReportCommandTopic,
|
||||||
|
icon: 'mdi:file-document-outline',
|
||||||
|
};
|
||||||
|
|
||||||
|
// Schedule active sensor for this slot
|
||||||
|
components[`${slotPrefix}_active`] = {
|
||||||
|
unique_id: `${slotPrefix}_active`,
|
||||||
|
platform: 'binary_sensor',
|
||||||
|
name: `Schedule Slot ${slot} Active`,
|
||||||
|
entity_category: 'diagnostic',
|
||||||
|
device_class: 'connectivity',
|
||||||
|
value_template: `{% set entries = value_json['${svc.addr}'] %}{% set found = false %}{% for key, entry in entries.items() %}{% if entry.slot == ${slot} and entry.year_start is defined %}{% set found = true %}{% endif %}{% endfor %}{{ found | iif('ON', 'OFF') }}`,
|
||||||
|
icon: 'mdi:calendar-clock',
|
||||||
|
};
|
||||||
|
|
||||||
|
// Command handlers for this slot
|
||||||
|
|
||||||
|
// Helper function to get current schedule entry for a slot
|
||||||
|
const getCurrentScheduleEntry = async (
|
||||||
|
slotNum: number,
|
||||||
|
): Promise<ScheduleEntry | null> => {
|
||||||
|
// This would need to be implemented to get the current state from the cached state
|
||||||
|
// For now, we'll construct a basic entry with required fields
|
||||||
|
return {
|
||||||
|
slot: slotNum,
|
||||||
|
user_id: 1, // Default user ID
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Helper function to update a schedule entry field
|
||||||
|
const updateScheduleField = async (
|
||||||
|
slotNum: number,
|
||||||
|
field: keyof ScheduleEntry,
|
||||||
|
value: number,
|
||||||
|
) => {
|
||||||
|
const currentEntry = await getCurrentScheduleEntry(slotNum);
|
||||||
|
if (!currentEntry) return;
|
||||||
|
|
||||||
|
const updatedEntry: ScheduleEntry = {
|
||||||
|
...currentEntry,
|
||||||
|
[field]: value,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Only send the set command if we have minimum required fields
|
||||||
|
if (updatedEntry.user_id && updatedEntry.slot) {
|
||||||
|
await sendFimpMsg({
|
||||||
|
address: svc.addr,
|
||||||
|
service: 'schedule_entry',
|
||||||
|
cmd: 'cmd.schedule_entry.set',
|
||||||
|
val_t: 'int_map',
|
||||||
|
val: updatedEntry,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// User ID command handler
|
||||||
|
commandHandlers[userIdCommandTopic] = async (payload: string) => {
|
||||||
|
const userId = parseInt(payload, 10);
|
||||||
|
if (Number.isNaN(userId) || userId < 1 || userId > 254) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await updateScheduleField(slot, 'user_id', userId);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Year start command handler
|
||||||
|
commandHandlers[yearStartCommandTopic] = async (payload: string) => {
|
||||||
|
const year = parseInt(payload, 10);
|
||||||
|
if (Number.isNaN(year) || year < 0 || year > 99) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await updateScheduleField(slot, 'year_start', year);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Month start command handler
|
||||||
|
commandHandlers[monthStartCommandTopic] = async (payload: string) => {
|
||||||
|
const month = parseInt(payload, 10);
|
||||||
|
if (Number.isNaN(month) || month < 1 || month > 12) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await updateScheduleField(slot, 'month_start', month);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Day start command handler
|
||||||
|
commandHandlers[dayStartCommandTopic] = async (payload: string) => {
|
||||||
|
const day = parseInt(payload, 10);
|
||||||
|
if (Number.isNaN(day) || day < 1 || day > 31) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await updateScheduleField(slot, 'day_start', day);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Hour start command handler
|
||||||
|
commandHandlers[hourStartCommandTopic] = async (payload: string) => {
|
||||||
|
const hour = parseInt(payload, 10);
|
||||||
|
if (Number.isNaN(hour) || hour < 0 || hour > 23) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await updateScheduleField(slot, 'hour_start', hour);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Minute start command handler
|
||||||
|
commandHandlers[minuteStartCommandTopic] = async (payload: string) => {
|
||||||
|
const minute = parseInt(payload, 10);
|
||||||
|
if (Number.isNaN(minute) || minute < 0 || minute > 59) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await updateScheduleField(slot, 'minute_start', minute);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Year end command handler
|
||||||
|
commandHandlers[yearEndCommandTopic] = async (payload: string) => {
|
||||||
|
const year = parseInt(payload, 10);
|
||||||
|
if (Number.isNaN(year) || year < 0 || year > 99) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await updateScheduleField(slot, 'year_end', year);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Month end command handler
|
||||||
|
commandHandlers[monthEndCommandTopic] = async (payload: string) => {
|
||||||
|
const month = parseInt(payload, 10);
|
||||||
|
if (Number.isNaN(month) || month < 1 || month > 12) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await updateScheduleField(slot, 'month_end', month);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Day end command handler
|
||||||
|
commandHandlers[dayEndCommandTopic] = async (payload: string) => {
|
||||||
|
const day = parseInt(payload, 10);
|
||||||
|
if (Number.isNaN(day) || day < 1 || day > 31) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await updateScheduleField(slot, 'day_end', day);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Hour end command handler
|
||||||
|
commandHandlers[hourEndCommandTopic] = async (payload: string) => {
|
||||||
|
const hour = parseInt(payload, 10);
|
||||||
|
if (Number.isNaN(hour) || hour < 0 || hour > 23) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await updateScheduleField(slot, 'hour_end', hour);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Minute end command handler
|
||||||
|
commandHandlers[minuteEndCommandTopic] = async (payload: string) => {
|
||||||
|
const minute = parseInt(payload, 10);
|
||||||
|
if (Number.isNaN(minute) || minute < 0 || minute > 59) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await updateScheduleField(slot, 'minute_end', minute);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Clear command handler
|
||||||
|
commandHandlers[clearCommandTopic] = async (_payload: string) => {
|
||||||
|
const currentEntry = await getCurrentScheduleEntry(slot);
|
||||||
|
if (!currentEntry) return;
|
||||||
|
|
||||||
|
await sendFimpMsg({
|
||||||
|
address: svc.addr,
|
||||||
|
service: 'schedule_entry',
|
||||||
|
cmd: 'cmd.schedule_entry.clear',
|
||||||
|
val_t: 'int_map',
|
||||||
|
val: {
|
||||||
|
slot: slot,
|
||||||
|
user_id: currentEntry.user_id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get report command handler
|
||||||
|
commandHandlers[getReportCommandTopic] = async (_payload: string) => {
|
||||||
|
const currentEntry = await getCurrentScheduleEntry(slot);
|
||||||
|
if (!currentEntry) return;
|
||||||
|
|
||||||
|
await sendFimpMsg({
|
||||||
|
address: svc.addr,
|
||||||
|
service: 'schedule_entry',
|
||||||
|
cmd: 'cmd.schedule_entry.get_report',
|
||||||
|
val_t: 'int_map',
|
||||||
|
val: {
|
||||||
|
slot: slot,
|
||||||
|
user_id: currentEntry.user_id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Global schedule sensor showing total active schedules
|
||||||
|
components[`${svc.addr}_total_active`] = {
|
||||||
|
unique_id: `${svc.addr}_total_active`,
|
||||||
|
platform: 'sensor',
|
||||||
|
name: 'Active Schedule Count',
|
||||||
|
entity_category: 'diagnostic',
|
||||||
|
state_class: 'measurement',
|
||||||
|
value_template: `{% set entries = value_json['${svc.addr}'] %}{% set count = 0 %}{% for key, entry in entries.items() %}{% if entry.year_start is defined %}{% set count = count + 1 %}{% endif %}{% endfor %}{{ count }}`,
|
||||||
|
icon: 'mdi:calendar-check',
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
components,
|
||||||
|
commandHandlers,
|
||||||
|
};
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user