Just trying to get some outlets off before I wake up.
This commit is contained in:
parent
f732c17845
commit
a3da0bf185
|
@ -24,7 +24,7 @@
|
|||
] | random + "#HomeAutomation"}}
|
||||
|
||||
- delay: '00:{{ (range(1, 55)|random|int) }}:00'
|
||||
- service: light.turn_off
|
||||
- service: homeassistant.turn_off
|
||||
entity_id:
|
||||
- group.exterior_lights
|
||||
- group.outdoor_front_lights
|
||||
|
|
|
@ -17,9 +17,10 @@
|
|||
tweet: >
|
||||
{{ [
|
||||
"Right before sunset, I turn on the outdoor lights.",
|
||||
"Since it gets dark around sunset, I turn on the landscaping lights.",
|
||||
"Since it gets dark around sunset, I will turn on the landscaping lights.",
|
||||
"Time to turn on the Landscaping lights.",
|
||||
"Daytime is over, Time to turn on the exterior lights.",
|
||||
"Once the Sun goes down, we turn on the exterior lights.",
|
||||
"Since it is sunset, I will turn on the exterior lights."
|
||||
] | random + [
|
||||
" #Sunset",
|
||||
|
|
|
@ -3,7 +3,7 @@ Interior Switches:
|
|||
- switch.den_outlet
|
||||
- switch.living_room_outlet
|
||||
- switch.foyer_outlet
|
||||
- switch.kitchen_Accents
|
||||
- switch.kitchen_accents
|
||||
- switch.kitchen_accent_2
|
||||
- switch.printer_outlet
|
||||
- switch.front_door_outlet
|
||||
|
|
|
@ -54,6 +54,13 @@ sensor:
|
|||
duration:
|
||||
hours: 24
|
||||
|
||||
- platform: rest
|
||||
name: July 4th Countdown
|
||||
resource: http://api.wolframalpha.com/v1/result?appid=JIUY8U-4V8KY45VT1&i=How%20many%20days%20until%204th%20July%202018
|
||||
value_template: "{{ (value|replace(' days', '')) | int }}"
|
||||
unit_of_measurement: Days
|
||||
scan_interval: 43200```
|
||||
|
||||
group:
|
||||
tweet_stats:
|
||||
entities:
|
||||
|
@ -164,7 +171,7 @@ automation:
|
|||
"I am running Home Assistant version {{states.sensor.ha_installed_version.state}} (https://github.com/CCOSTAN/Home-AssistantConfig)",
|
||||
"{{states.sensor.doorbell_presses.state}} doorbell presses occurred in the last 24 hours.",
|
||||
"I keep the average humidity of the house at {{states.sensor.downstairs_thermostat_humidity.state}} percent. Outside is {{states.sensor.dark_sky_humidity.state}} #Nest (http://amzn.to/2BWNk5N)",
|
||||
"Outside is {{states.sensor.dark_sky_temperature.state}}. I keep the average temperature at {{states.sensor.downstairs_thermostat_temperature.state}}. #Nest (http://amzn.to/2BWNk5N)",
|
||||
"Outside is {{states.sensor.dark_sky_temperature.state}}. I keep the average temperature at {{states.sensor.downstairs_thermostat_temperature.state}}. #Weather (http://amzn.to/2BWNk5N)",
|
||||
"I know that it will be {{states.sensor.dark_sky_minutely_summary.state}} So I will adjust the Heating/Cooling, irrigation and lighting accordingly. #Nest #Rachio #Hue",
|
||||
"Average internet stats are Download: {{states.sensor.speedtest_download.state}} Mbit/s & Upload {{states.sensor.speedtest_upload.state}} Mbit/s.",
|
||||
"Todays Sleep Number is {{states.sensor.sleepnumber_carlo_stacey_sleepnumber.state}}. Wifi connected Bed FTW! #SleepStat (http://amzn.to/2D10BcQ)",
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
interior_off:
|
||||
sequence:
|
||||
- service: light.turn_off
|
||||
- service: homeassistant.turn_off
|
||||
entity_id:
|
||||
- group.interior_lights
|
||||
- service: script.switch_turn_off_all
|
||||
|
|
|
@ -15,8 +15,6 @@ rules:
|
|||
class: 'button-on'
|
||||
- state: 'off'
|
||||
class: 'button-off'
|
||||
action:
|
||||
service: homeassistant.toggle
|
||||
|
||||
- name: thermostats_temp
|
||||
entities:
|
||||
|
@ -95,8 +93,6 @@ rules:
|
|||
class: 'switch-on'
|
||||
- state: 'off'
|
||||
class: 'switch-off'
|
||||
action:
|
||||
service: homeassistant.toggle
|
||||
|
||||
- name: custom_switches
|
||||
entities:
|
||||
|
@ -106,8 +102,6 @@ rules:
|
|||
class: 'light-blue-on'
|
||||
- state: 'off'
|
||||
class: 'outdoor-light-off'
|
||||
action:
|
||||
service: homeassistant.toggle
|
||||
|
||||
- name: Lights
|
||||
entities:
|
||||
|
@ -149,8 +143,6 @@ rules:
|
|||
class: 'light-on'
|
||||
- state: 'off'
|
||||
class: 'light-off'
|
||||
action:
|
||||
service: homeassistant.toggle
|
||||
|
||||
- name: Outdoor Lights
|
||||
entities:
|
||||
|
@ -172,8 +164,6 @@ rules:
|
|||
class: 'light-on'
|
||||
- state: 'off'
|
||||
class: 'outdoor-light-off'
|
||||
action:
|
||||
service: homeassistant.toggle
|
||||
|
||||
- name: Nest Protects
|
||||
entities:
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
date_format: MMM-DD-YYYY
|
||||
#log_level: error
|
||||
#log_level: debug
|
||||
|
||||
fully_kiosk:
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
Floorplan Fully Kiosk for Home Assistant
|
||||
Version: 1.0.7.42
|
||||
By Petar Kozul
|
||||
https://github.com/pkozul/ha-floorplan
|
||||
Floorplan Fully Kiosk for Home Assistant
|
||||
Version: 1.0.7.50
|
||||
By Petar Kozul
|
||||
https://github.com/pkozul/ha-floorplan
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
@ -14,14 +14,16 @@
|
|||
|
||||
class FullyKiosk {
|
||||
constructor(floorplan) {
|
||||
this.version = '1.0.7.42';
|
||||
this.version = '1.0.7.50';
|
||||
|
||||
this.floorplan = floorplan;
|
||||
this.authToken = (window.localStorage && window.localStorage.authToken) ? window.localStorage.authToken : '';
|
||||
|
||||
this.fullyInfo = {};
|
||||
this.fullyState = {};
|
||||
this.iBeacons = {};
|
||||
this.beacons = {};
|
||||
|
||||
this.throttledFunctions = {};
|
||||
}
|
||||
|
||||
/***************************************************************************************************************************/
|
||||
|
@ -31,6 +33,13 @@
|
|||
init() {
|
||||
this.logInfo('VERSION', `Fully Kiosk v${this.version}`);
|
||||
|
||||
/*
|
||||
let uuid = 'a445425b-c718-461c-a876-aa647abd99d4';
|
||||
let deviceId = uuid.replace(/[-_]/g, '').toUpperCase();
|
||||
let payload = { room: 'entry hall', id: uuid, distance: 123.45 };
|
||||
this.PostToHomeAssistant(`/api/room_presence/${deviceId}`, payload);
|
||||
*/
|
||||
|
||||
if (typeof fully === "undefined") {
|
||||
this.logInfo('FULLY_KIOSK', `Fully Kiosk is not running or not enabled. You can enable it via Settings > Other Settings > Enable Website Integration (PLUS).`);
|
||||
return;
|
||||
|
@ -76,6 +85,8 @@
|
|||
screensaverLightEntityId: device.screensaver_light,
|
||||
mediaPlayerEntityId: device.media_player,
|
||||
|
||||
locationName: device.presence_detection ? device.presence_detection.location_name : undefined,
|
||||
|
||||
startUrl: fully.getStartUrl(),
|
||||
currentLocale: fully.getCurrentLocale(),
|
||||
ipAddressv4: fully.getIp4Address(),
|
||||
|
@ -134,8 +145,15 @@
|
|||
window.addEventListener('fully.onScreensaverStop', this.onScreensaverStop.bind(this));
|
||||
window.addEventListener('fully.onBatteryLevelChanged', this.onBatteryLevelChanged.bind(this));
|
||||
window.addEventListener('fully.onMotion', this.onMotion.bind(this));
|
||||
window.addEventListener('fully.onMovement', this.onMovement.bind(this));
|
||||
window.addEventListener('fully.onIBeacon', this.onIBeacon.bind(this));
|
||||
|
||||
if (this.fullyInfo.supportsGeolocation) {
|
||||
window.addEventListener('fully.onMovement', this.onMovement.bind(this));
|
||||
}
|
||||
|
||||
if (this.fullyInfo.locationName) {
|
||||
this.logInfo('KIOSK', 'Listening for beacon messages');
|
||||
window.addEventListener('fully.onIBeacon', this.onIBeacon.bind(this));
|
||||
}
|
||||
|
||||
fully.bind('screenOn', 'onFullyEvent("fully.screenOn");')
|
||||
fully.bind('screenOff', 'onFullyEvent("fully.screenOff");')
|
||||
|
@ -221,8 +239,19 @@
|
|||
this.sendMotionState();
|
||||
}
|
||||
|
||||
onMovement() {
|
||||
this.logDebug('FULLY_KIOSK', 'Movement detected');
|
||||
onMovement(e) {
|
||||
let functionId = 'onMovement';
|
||||
let throttledFunc = this.throttledFunctions[functionId];
|
||||
if (!throttledFunc) {
|
||||
throttledFunc = this.throttle(this.onMovementThrottled.bind(this), 10000);
|
||||
this.throttledFunctions[functionId] = throttledFunc;
|
||||
}
|
||||
|
||||
return throttledFunc(e);
|
||||
}
|
||||
|
||||
onMovementThrottled() {
|
||||
this.logDebug('FULLY_KIOSK', 'Movement detected (throttled)');
|
||||
|
||||
if (this.fullyInfo.supportsGeolocation) {
|
||||
this.updateCurrentPosition()
|
||||
|
@ -233,19 +262,28 @@
|
|||
}
|
||||
|
||||
onIBeacon(e) {
|
||||
let iBeacon = e.detail;
|
||||
let functionId = e.detail.uuid;
|
||||
let throttledFunc = this.throttledFunctions[functionId];
|
||||
if (!throttledFunc) {
|
||||
throttledFunc = this.throttle(this.onIBeaconThrottled.bind(this), 10000);
|
||||
this.throttledFunctions[functionId] = throttledFunc;
|
||||
}
|
||||
|
||||
this.logDebug('FULLY_KIOSK', `iBeacon (${JSON.stringify(iBeacon)})`);
|
||||
return throttledFunc(e);
|
||||
}
|
||||
|
||||
let iBeaconId = iBeacon.uuid;
|
||||
iBeaconId += (iBeacon.major ? `_${iBeacon.major}` : '');
|
||||
iBeaconId += (iBeacon.minor ? `_${iBeacon.minor}` : '');
|
||||
onIBeaconThrottled(e) {
|
||||
let beacon = e.detail;
|
||||
|
||||
this.iBeacons[iBeaconId] = iBeacon;
|
||||
this.logDebug('FULLY_KIOSK', `Received (throttled) beacon message (${JSON.stringify(beacon)})`);
|
||||
|
||||
this.sendMotionState();
|
||||
let beaconId = beacon.uuid;
|
||||
beaconId += (beacon.major ? `_${beacon.major}` : '');
|
||||
beaconId += (beacon.minor ? `_${beacon.minor}` : '');
|
||||
|
||||
this.sendIBeaconState(iBeacon);
|
||||
this.beacons[beaconId] = beacon;
|
||||
|
||||
this.sendBeaconState(beacon);
|
||||
}
|
||||
|
||||
/***************************************************************************************************************************/
|
||||
|
@ -329,30 +367,61 @@
|
|||
this.PostToHomeAssistant(`/api/fully_kiosk/media_player/${this.fullyInfo.mediaPlayerEntityId}`, this.newPayload(state));
|
||||
}
|
||||
|
||||
sendIBeaconState(iBeacon) {
|
||||
sendBeaconState(beacon) {
|
||||
if (!this.fullyInfo.motionBinarySensorEntityId) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
let payload = {
|
||||
name: this.fullyInfo.locationName,
|
||||
address: this.fullyInfo.macAddress,
|
||||
device: beacon.uuid,
|
||||
beaconUUID: beacon.uuid,
|
||||
latitude: this.position ? this.position.coords.latitude : undefined,
|
||||
longitude: this.position ? this.position.coords.longitude : undefined,
|
||||
entry: 1,
|
||||
}
|
||||
this.PostToHomeAssistant(`/api/geofency`, payload, undefined, false);
|
||||
*/
|
||||
|
||||
/*
|
||||
let payload = {
|
||||
mac: undefined,
|
||||
dev_id: iBeacon.uuid.replace(/-/g, '_'),
|
||||
dev_id: beacon.uuid.replace(/-/g, '_'),
|
||||
host_name: undefined,
|
||||
location_name: this.fullyInfo.macAddress,
|
||||
gps: this.position ? [this.position.coords.latitude, this.position.coords.longitude] : undefined,
|
||||
gps_accuracy: undefined,
|
||||
battery: undefined,
|
||||
|
||||
uuid: iBeacon.uuid,
|
||||
major: iBeacon.major,
|
||||
minor: iBeacon.minor,
|
||||
uuid: beacon.uuid,
|
||||
major: beacon.major,
|
||||
minor: beacon.minor,
|
||||
};
|
||||
|
||||
//this.PostToHomeAssistant(`/api/services/device_tracker/see`, payload);
|
||||
this.PostToHomeAssistant(`/api/services/device_tracker/see`, payload);
|
||||
*/
|
||||
|
||||
/*
|
||||
let fullyId = this.fullyInfo.macAddress.replace(/[:-]/g, "_");
|
||||
payload = { topic: `room_presence/${fullyId}`, payload: `{ \"id\": \"${iBeacon.uuid}\", \"distance\": ${iBeacon.distance} }` };
|
||||
payload = { topic: `room_presence/${fullyId}`, payload: `{ \"id\": \"${beacon.uuid}\", \"distance\": ${beacon.distance} }` };
|
||||
this.floorplan.hass.callService('mqtt', 'publish', payload);
|
||||
*/
|
||||
|
||||
let deviceId = beacon.uuid.replace(/[-_]/g, '').toUpperCase();
|
||||
|
||||
let payload = {
|
||||
room: this.fullyInfo.locationName,
|
||||
uuid: beacon.uuid,
|
||||
major: beacon.major,
|
||||
minor: beacon.minor,
|
||||
distance: beacon.distance,
|
||||
latitude: this.position ? this.position.coords.latitude : undefined,
|
||||
longitude: this.position ? this.position.coords.longitude : undefined,
|
||||
};
|
||||
|
||||
this.PostToHomeAssistant(`/api/room_presence/${deviceId}`, payload);
|
||||
}
|
||||
|
||||
newPayload(state) {
|
||||
|
@ -376,7 +445,7 @@
|
|||
_isScreensaverOn: this.fullyState.isScreensaverOn,
|
||||
_latitude: this.position && this.position.coords.latitude,
|
||||
_longitude: this.position && this.position.coords.longitude,
|
||||
_iBeacons: JSON.stringify(Object.keys(this.iBeacons).map(iBeaconId => this.iBeacons[iBeaconId])),
|
||||
_beacons: JSON.stringify(Object.keys(this.beacons).map(beaconId => this.beacons[beaconId])),
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -568,22 +637,152 @@
|
|||
/* Utility functions
|
||||
/***************************************************************************************************************************/
|
||||
|
||||
debounce(func, wait, immediate) {
|
||||
let timeout;
|
||||
return function () {
|
||||
let context = this, args = arguments;
|
||||
debounce(func, wait, options) {
|
||||
let lastArgs,
|
||||
lastThis,
|
||||
maxWait,
|
||||
result,
|
||||
timerId,
|
||||
lastCallTime
|
||||
|
||||
let later = function () {
|
||||
timeout = null;
|
||||
if (!immediate) func.apply(context, args);
|
||||
};
|
||||
let lastInvokeTime = 0
|
||||
let leading = false
|
||||
let maxing = false
|
||||
let trailing = true
|
||||
|
||||
let callNow = immediate && !timeout;
|
||||
clearTimeout(timeout);
|
||||
timeout = setTimeout(later, wait);
|
||||
if (typeof func != 'function') {
|
||||
throw new TypeError('Expected a function')
|
||||
}
|
||||
wait = +wait || 0
|
||||
if (options) {
|
||||
leading = !!options.leading
|
||||
maxing = 'maxWait' in options
|
||||
maxWait = maxing ? Math.max(+options.maxWait || 0, wait) : maxWait
|
||||
trailing = 'trailing' in options ? !!options.trailing : trailing
|
||||
}
|
||||
|
||||
if (callNow) func.apply(context, args);
|
||||
};
|
||||
function invokeFunc(time) {
|
||||
const args = lastArgs
|
||||
const thisArg = lastThis
|
||||
|
||||
lastArgs = lastThis = undefined
|
||||
lastInvokeTime = time
|
||||
result = func.apply(thisArg, args)
|
||||
return result
|
||||
}
|
||||
|
||||
function leadingEdge(time) {
|
||||
// Reset any `maxWait` timer.
|
||||
lastInvokeTime = time
|
||||
// Start the timer for the trailing edge.
|
||||
timerId = setTimeout(timerExpired, wait)
|
||||
// Invoke the leading edge.
|
||||
return leading ? invokeFunc(time) : result
|
||||
}
|
||||
|
||||
function remainingWait(time) {
|
||||
const timeSinceLastCall = time - lastCallTime
|
||||
const timeSinceLastInvoke = time - lastInvokeTime
|
||||
const timeWaiting = wait - timeSinceLastCall
|
||||
|
||||
return maxing
|
||||
? Math.min(timeWaiting, maxWait - timeSinceLastInvoke)
|
||||
: timeWaiting
|
||||
}
|
||||
|
||||
function shouldInvoke(time) {
|
||||
const timeSinceLastCall = time - lastCallTime
|
||||
const timeSinceLastInvoke = time - lastInvokeTime
|
||||
|
||||
// Either this is the first call, activity has stopped and we're at the
|
||||
// trailing edge, the system time has gone backwards and we're treating
|
||||
// it as the trailing edge, or we've hit the `maxWait` limit.
|
||||
return (lastCallTime === undefined || (timeSinceLastCall >= wait) ||
|
||||
(timeSinceLastCall < 0) || (maxing && timeSinceLastInvoke >= maxWait))
|
||||
}
|
||||
|
||||
function timerExpired() {
|
||||
const time = Date.now()
|
||||
if (shouldInvoke(time)) {
|
||||
return trailingEdge(time)
|
||||
}
|
||||
// Restart the timer.
|
||||
timerId = setTimeout(timerExpired, remainingWait(time))
|
||||
}
|
||||
|
||||
function trailingEdge(time) {
|
||||
timerId = undefined
|
||||
|
||||
// Only invoke if we have `lastArgs` which means `func` has been
|
||||
// debounced at least once.
|
||||
if (trailing && lastArgs) {
|
||||
return invokeFunc(time)
|
||||
}
|
||||
lastArgs = lastThis = undefined
|
||||
return result
|
||||
}
|
||||
|
||||
function cancel() {
|
||||
if (timerId !== undefined) {
|
||||
clearTimeout(timerId)
|
||||
}
|
||||
lastInvokeTime = 0
|
||||
lastArgs = lastCallTime = lastThis = timerId = undefined
|
||||
}
|
||||
|
||||
function flush() {
|
||||
return timerId === undefined ? result : trailingEdge(Date.now())
|
||||
}
|
||||
|
||||
function pending() {
|
||||
return timerId !== undefined
|
||||
}
|
||||
|
||||
function debounced(...args) {
|
||||
const time = Date.now()
|
||||
const isInvoking = shouldInvoke(time)
|
||||
|
||||
lastArgs = args
|
||||
lastThis = this
|
||||
lastCallTime = time
|
||||
|
||||
if (isInvoking) {
|
||||
if (timerId === undefined) {
|
||||
return leadingEdge(lastCallTime)
|
||||
}
|
||||
if (maxing) {
|
||||
// Handle invocations in a tight loop.
|
||||
timerId = setTimeout(timerExpired, wait)
|
||||
return invokeFunc(lastCallTime)
|
||||
}
|
||||
}
|
||||
if (timerId === undefined) {
|
||||
timerId = setTimeout(timerExpired, wait)
|
||||
}
|
||||
return result
|
||||
}
|
||||
debounced.cancel = cancel
|
||||
debounced.flush = flush
|
||||
debounced.pending = pending
|
||||
return debounced
|
||||
}
|
||||
|
||||
throttle(func, wait, options) {
|
||||
let leading = true
|
||||
let trailing = true
|
||||
|
||||
if (typeof func != 'function') {
|
||||
throw new TypeError('Expected a function');
|
||||
}
|
||||
if (options) {
|
||||
leading = 'leading' in options ? !!options.leading : leading
|
||||
trailing = 'trailing' in options ? !!options.trailing : trailing
|
||||
}
|
||||
return this.debounce(func, wait, {
|
||||
'leading': leading,
|
||||
'maxWait': wait,
|
||||
'trailing': trailing
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue