Google Home 알람 및 타이머를 알림으로 받기
TL;DR
Using Home Assistant and Node-RED I receive actionable notifications on my android phone for Google Home alarms and timers. The notifications show all information, they are grouped and have a countdown.
목차
Node-RED
저는 Google(Nest) 스마트 기기의 열렬한 팬이며 스마트 홈 설정에 여러 개의 Hub 및 Mini 기기가 있습니다. Home Assistant 및 Node-RED와 페어링하여 모든 장치 및 자동화 흐름을 제어하는 데 사용합니다.
알람 및 타이머
장치의 알람 및 타이머 기능은 내가 가장 자주 사용하는 기능이며 매일 사용합니다.
그들은 잘 작동하지만 멋지게 만드는 몇 가지 기능이 없습니다.
홈어시스턴트 Google 홈 통합
이번 주에 저는 알람과 타이머를 HA의 센서로 노출하는 "Google Home"이라는 새로운 커뮤니티 통합을 발견했습니다.
레이코일자 / 하-구글홈
홈어시스턴트 Google 홈 맞춤 구성요소
HACS를 통해 설치했는데 정말 잘 작동합니다. 알람 및 타이머용 센서 엔티티가 장치별로 생성됩니다.
나는 나를 위해 더 많은 기능을 추가할 몇 가지 새로운 자동화에 사용할 수 있는지, 특히 내 전화에 알림으로 사용할 수 있는지 궁금했습니다.
목표

Node-RED
저는 모든 자동화에 Node-RED를 사용합니다. 흐름을 시각화하는 방식이 마음에 듭니다. 코드 논리를 적용하는 옵션도 좋아하는 개발자로서 종종 로우 코드 솔루션으로 설명됩니다.
다음에 보시는 것은 몇 가지 시행 착오 프로그래밍의 최종 결과입니다. 일반적으로 저는 1개의 센서 입력과 정상적인 흐름으로 시작합니다. 그런 다음 미세 조정하고 종종 재사용 가능한 하위 흐름으로 변환합니다.
기본 흐름은 다음과 같습니다.

최종 결과에서 저는 모든 것을 제어할 수 있는 1개의 sublfow만 갖고 싶었고, 여러 개의 알람 및 타이머 센서를 입력으로 사용했습니다.
하위 흐름

상위 흐름은 모든 입력을 처리합니다.
하단 흐름은 지워진 알림을 처리합니다.
탑 플로우

모든 어려운 작업을 수행하는 "Parse alarms & timers"기능 노드부터 시작하겠습니다.
함수 노드의 "설정"탭을 사용하여 흐름에서 사용되는 몇 가지 기본값을 설정합니다.
// Set type defaults
const defaults = {
timer: {
id: 'timer_id',
label: '⏳',
items: 'timers',
name: 'Timers',
deleteService: 'delete_timer'
},
alarm: {
id: 'alarm_id',
label: '⏰',
items: 'alarms',
name: 'Alarms',
deleteService: 'delete_alarm'
},
}
flow.set('defaults', defaults);
"기능"탭
const defaults = flow.get('defaults');
const service = env.get('service');
const messages = [];
let type = '';
if(!msg.data) {
return null;
}
// Determine type: alarm or timer
if(typeof msg.data.new_state.attributes.timers !== 'undefined' || typeof msg.data.old_state.attributes.timers !== 'undefined' ) {
type = 'timer';
} else if (typeof msg.data.new_state.attributes.alarms !== 'undefined' || typeof msg.data.old_state.attributes.alarms !== 'undefined') {
type = 'alarm';
} else {
return null;
}
const typeValues = defaults[type];
// Create a alarm/timer item ready to be used by the service
const createItem = (item, sensor, type, device) => {
const doneTime = new Date(item.fire_time * 1000).toTimeString().substr(0, 5);
let label = `${typeValues.label}`;
let vibration = '';
let chronometer = true;
if(item.status === 'ringing') {
label = item.label ? `${label} ${item.label} RINGING` : `${label} RINGING`;
vibration = '100, 1000, 100, 1000, 100, 100, 1000, 100, 1000, 100';
chronometer = false;
} else {
label = item.label ? `${label} ${doneTime} ${item.label}` : `${label} ${doneTime}`;
}
let title = label;
if(item.duration) {
title = `${label} (${item.duration})`;
}
return {
id: item[typeValues.id],
sensor: sensor,
device: device,
type: type,
status: item.status,
data:{
title: title,
message: `${device}`,
data: {
tag: item[typeValues.id],
chronometer: chronometer,
when: item.fire_time,
sticky: 'true',
group: typeValues.name,
vibrationPattern: vibration
}
}
}
};
const mapItems = (arr) => {
return arr.map((item) => { return createItem(item, msg.data.entity_id, type, msg.data.old_state.attributes.friendly_name) })
}
const activeItems = mapItems(msg.data.new_state.attributes[typeValues.items] || []).filter(item => item.status !== 'none');
const cachedItems = flow.get('cachedItems') || new Map();
// Update or create notifications for active items
activeItems.forEach((item) => {
messages.push({
payload: {
service: service,
data: item.data
}
});
cachedItems.set(item.id, item);
})
// Clear expired/deleted notifications
cachedItems.forEach((item, id) => {
const findItem = activeItems.find(newItem => newItem.id === id);
if(!findItem && item.sensor === msg.data.entity_id) {
messages.push({
payload: {
service: service,
data: {
message: 'clear_notification',
data: {
tag: id
}
}
}
});
cachedItems.delete(id);
}
})
flow.set('cachedItems', cachedItems);
// Send notifications as a stream
messages.forEach((msg) => node.send(msg));
// All done
node.done();
바닥 흐름

const cachedItems = flow.get('cachedItems');
const defaults = flow.get('defaults');
// Find cleared item
const findItem = cachedItems.get(msg.payload.event.tag);
if(!findItem) {
return null
}
node.send(
{
payload: {
service: defaults[findItem.type].deleteService,
data: {
entity_id: findItem.sensor,
[defaults[findItem.type].id]: findItem.id
}
}
}
)
// Clean up
cachedItems.delete(findItem.id);
flow.set('cachedItems', cachedItems);
node.done();
사용하는 방법

events_state
노드로 연결합니다.
Reference
이 문제에 관하여(Google Home 알람 및 타이머를 알림으로 받기), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/mattieha/get-google-home-alarms-timers-as-notifications-i0m텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)