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"}}
|
] | random + "#HomeAutomation"}}
|
||||||
|
|
||||||
- delay: '00:{{ (range(1, 55)|random|int) }}:00'
|
- delay: '00:{{ (range(1, 55)|random|int) }}:00'
|
||||||
- service: light.turn_off
|
- service: homeassistant.turn_off
|
||||||
entity_id:
|
entity_id:
|
||||||
- group.exterior_lights
|
- group.exterior_lights
|
||||||
- group.outdoor_front_lights
|
- group.outdoor_front_lights
|
||||||
|
|
|
@ -17,9 +17,10 @@
|
||||||
tweet: >
|
tweet: >
|
||||||
{{ [
|
{{ [
|
||||||
"Right before sunset, I turn on the outdoor lights.",
|
"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.",
|
"Time to turn on the Landscaping lights.",
|
||||||
"Daytime is over, Time to turn on the exterior 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."
|
"Since it is sunset, I will turn on the exterior lights."
|
||||||
] | random + [
|
] | random + [
|
||||||
" #Sunset",
|
" #Sunset",
|
||||||
|
|
|
@ -3,7 +3,7 @@ Interior Switches:
|
||||||
- switch.den_outlet
|
- switch.den_outlet
|
||||||
- switch.living_room_outlet
|
- switch.living_room_outlet
|
||||||
- switch.foyer_outlet
|
- switch.foyer_outlet
|
||||||
- switch.kitchen_Accents
|
- switch.kitchen_accents
|
||||||
- switch.kitchen_accent_2
|
- switch.kitchen_accent_2
|
||||||
- switch.printer_outlet
|
- switch.printer_outlet
|
||||||
- switch.front_door_outlet
|
- switch.front_door_outlet
|
||||||
|
|
|
@ -54,6 +54,13 @@ sensor:
|
||||||
duration:
|
duration:
|
||||||
hours: 24
|
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:
|
group:
|
||||||
tweet_stats:
|
tweet_stats:
|
||||||
entities:
|
entities:
|
||||||
|
@ -164,7 +171,7 @@ automation:
|
||||||
"I am running Home Assistant version {{states.sensor.ha_installed_version.state}} (https://github.com/CCOSTAN/Home-AssistantConfig)",
|
"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.",
|
"{{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)",
|
"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",
|
"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.",
|
"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)",
|
"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:
|
interior_off:
|
||||||
sequence:
|
sequence:
|
||||||
- service: light.turn_off
|
- service: homeassistant.turn_off
|
||||||
entity_id:
|
entity_id:
|
||||||
- group.interior_lights
|
- group.interior_lights
|
||||||
- service: script.switch_turn_off_all
|
- service: script.switch_turn_off_all
|
||||||
|
|
|
@ -15,8 +15,6 @@ rules:
|
||||||
class: 'button-on'
|
class: 'button-on'
|
||||||
- state: 'off'
|
- state: 'off'
|
||||||
class: 'button-off'
|
class: 'button-off'
|
||||||
action:
|
|
||||||
service: homeassistant.toggle
|
|
||||||
|
|
||||||
- name: thermostats_temp
|
- name: thermostats_temp
|
||||||
entities:
|
entities:
|
||||||
|
@ -95,8 +93,6 @@ rules:
|
||||||
class: 'switch-on'
|
class: 'switch-on'
|
||||||
- state: 'off'
|
- state: 'off'
|
||||||
class: 'switch-off'
|
class: 'switch-off'
|
||||||
action:
|
|
||||||
service: homeassistant.toggle
|
|
||||||
|
|
||||||
- name: custom_switches
|
- name: custom_switches
|
||||||
entities:
|
entities:
|
||||||
|
@ -106,8 +102,6 @@ rules:
|
||||||
class: 'light-blue-on'
|
class: 'light-blue-on'
|
||||||
- state: 'off'
|
- state: 'off'
|
||||||
class: 'outdoor-light-off'
|
class: 'outdoor-light-off'
|
||||||
action:
|
|
||||||
service: homeassistant.toggle
|
|
||||||
|
|
||||||
- name: Lights
|
- name: Lights
|
||||||
entities:
|
entities:
|
||||||
|
@ -149,8 +143,6 @@ rules:
|
||||||
class: 'light-on'
|
class: 'light-on'
|
||||||
- state: 'off'
|
- state: 'off'
|
||||||
class: 'light-off'
|
class: 'light-off'
|
||||||
action:
|
|
||||||
service: homeassistant.toggle
|
|
||||||
|
|
||||||
- name: Outdoor Lights
|
- name: Outdoor Lights
|
||||||
entities:
|
entities:
|
||||||
|
@ -172,8 +164,6 @@ rules:
|
||||||
class: 'light-on'
|
class: 'light-on'
|
||||||
- state: 'off'
|
- state: 'off'
|
||||||
class: 'outdoor-light-off'
|
class: 'outdoor-light-off'
|
||||||
action:
|
|
||||||
service: homeassistant.toggle
|
|
||||||
|
|
||||||
- name: Nest Protects
|
- name: Nest Protects
|
||||||
entities:
|
entities:
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
date_format: MMM-DD-YYYY
|
date_format: MMM-DD-YYYY
|
||||||
#log_level: error
|
#log_level: debug
|
||||||
|
|
||||||
fully_kiosk:
|
fully_kiosk:
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
/*
|
/*
|
||||||
Floorplan Fully Kiosk for Home Assistant
|
Floorplan Fully Kiosk for Home Assistant
|
||||||
Version: 1.0.7.42
|
Version: 1.0.7.50
|
||||||
By Petar Kozul
|
By Petar Kozul
|
||||||
https://github.com/pkozul/ha-floorplan
|
https://github.com/pkozul/ha-floorplan
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
@ -14,14 +14,16 @@
|
||||||
|
|
||||||
class FullyKiosk {
|
class FullyKiosk {
|
||||||
constructor(floorplan) {
|
constructor(floorplan) {
|
||||||
this.version = '1.0.7.42';
|
this.version = '1.0.7.50';
|
||||||
|
|
||||||
this.floorplan = floorplan;
|
this.floorplan = floorplan;
|
||||||
this.authToken = (window.localStorage && window.localStorage.authToken) ? window.localStorage.authToken : '';
|
this.authToken = (window.localStorage && window.localStorage.authToken) ? window.localStorage.authToken : '';
|
||||||
|
|
||||||
this.fullyInfo = {};
|
this.fullyInfo = {};
|
||||||
this.fullyState = {};
|
this.fullyState = {};
|
||||||
this.iBeacons = {};
|
this.beacons = {};
|
||||||
|
|
||||||
|
this.throttledFunctions = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
/***************************************************************************************************************************/
|
/***************************************************************************************************************************/
|
||||||
|
@ -31,6 +33,13 @@
|
||||||
init() {
|
init() {
|
||||||
this.logInfo('VERSION', `Fully Kiosk v${this.version}`);
|
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") {
|
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).`);
|
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;
|
return;
|
||||||
|
@ -76,6 +85,8 @@
|
||||||
screensaverLightEntityId: device.screensaver_light,
|
screensaverLightEntityId: device.screensaver_light,
|
||||||
mediaPlayerEntityId: device.media_player,
|
mediaPlayerEntityId: device.media_player,
|
||||||
|
|
||||||
|
locationName: device.presence_detection ? device.presence_detection.location_name : undefined,
|
||||||
|
|
||||||
startUrl: fully.getStartUrl(),
|
startUrl: fully.getStartUrl(),
|
||||||
currentLocale: fully.getCurrentLocale(),
|
currentLocale: fully.getCurrentLocale(),
|
||||||
ipAddressv4: fully.getIp4Address(),
|
ipAddressv4: fully.getIp4Address(),
|
||||||
|
@ -134,8 +145,15 @@
|
||||||
window.addEventListener('fully.onScreensaverStop', this.onScreensaverStop.bind(this));
|
window.addEventListener('fully.onScreensaverStop', this.onScreensaverStop.bind(this));
|
||||||
window.addEventListener('fully.onBatteryLevelChanged', this.onBatteryLevelChanged.bind(this));
|
window.addEventListener('fully.onBatteryLevelChanged', this.onBatteryLevelChanged.bind(this));
|
||||||
window.addEventListener('fully.onMotion', this.onMotion.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('screenOn', 'onFullyEvent("fully.screenOn");')
|
||||||
fully.bind('screenOff', 'onFullyEvent("fully.screenOff");')
|
fully.bind('screenOff', 'onFullyEvent("fully.screenOff");')
|
||||||
|
@ -221,8 +239,19 @@
|
||||||
this.sendMotionState();
|
this.sendMotionState();
|
||||||
}
|
}
|
||||||
|
|
||||||
onMovement() {
|
onMovement(e) {
|
||||||
this.logDebug('FULLY_KIOSK', 'Movement detected');
|
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) {
|
if (this.fullyInfo.supportsGeolocation) {
|
||||||
this.updateCurrentPosition()
|
this.updateCurrentPosition()
|
||||||
|
@ -233,19 +262,28 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
onIBeacon(e) {
|
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;
|
onIBeaconThrottled(e) {
|
||||||
iBeaconId += (iBeacon.major ? `_${iBeacon.major}` : '');
|
let beacon = e.detail;
|
||||||
iBeaconId += (iBeacon.minor ? `_${iBeacon.minor}` : '');
|
|
||||||
|
|
||||||
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));
|
this.PostToHomeAssistant(`/api/fully_kiosk/media_player/${this.fullyInfo.mediaPlayerEntityId}`, this.newPayload(state));
|
||||||
}
|
}
|
||||||
|
|
||||||
sendIBeaconState(iBeacon) {
|
sendBeaconState(beacon) {
|
||||||
if (!this.fullyInfo.motionBinarySensorEntityId) {
|
if (!this.fullyInfo.motionBinarySensorEntityId) {
|
||||||
return;
|
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 = {
|
let payload = {
|
||||||
mac: undefined,
|
mac: undefined,
|
||||||
dev_id: iBeacon.uuid.replace(/-/g, '_'),
|
dev_id: beacon.uuid.replace(/-/g, '_'),
|
||||||
host_name: undefined,
|
host_name: undefined,
|
||||||
location_name: this.fullyInfo.macAddress,
|
location_name: this.fullyInfo.macAddress,
|
||||||
gps: this.position ? [this.position.coords.latitude, this.position.coords.longitude] : undefined,
|
gps: this.position ? [this.position.coords.latitude, this.position.coords.longitude] : undefined,
|
||||||
gps_accuracy: undefined,
|
gps_accuracy: undefined,
|
||||||
battery: undefined,
|
battery: undefined,
|
||||||
|
|
||||||
uuid: iBeacon.uuid,
|
uuid: beacon.uuid,
|
||||||
major: iBeacon.major,
|
major: beacon.major,
|
||||||
minor: iBeacon.minor,
|
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, "_");
|
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);
|
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) {
|
newPayload(state) {
|
||||||
|
@ -376,7 +445,7 @@
|
||||||
_isScreensaverOn: this.fullyState.isScreensaverOn,
|
_isScreensaverOn: this.fullyState.isScreensaverOn,
|
||||||
_latitude: this.position && this.position.coords.latitude,
|
_latitude: this.position && this.position.coords.latitude,
|
||||||
_longitude: this.position && this.position.coords.longitude,
|
_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
|
/* Utility functions
|
||||||
/***************************************************************************************************************************/
|
/***************************************************************************************************************************/
|
||||||
|
|
||||||
debounce(func, wait, immediate) {
|
debounce(func, wait, options) {
|
||||||
let timeout;
|
let lastArgs,
|
||||||
return function () {
|
lastThis,
|
||||||
let context = this, args = arguments;
|
maxWait,
|
||||||
|
result,
|
||||||
|
timerId,
|
||||||
|
lastCallTime
|
||||||
|
|
||||||
let later = function () {
|
let lastInvokeTime = 0
|
||||||
timeout = null;
|
let leading = false
|
||||||
if (!immediate) func.apply(context, args);
|
let maxing = false
|
||||||
};
|
let trailing = true
|
||||||
|
|
||||||
let callNow = immediate && !timeout;
|
if (typeof func != 'function') {
|
||||||
clearTimeout(timeout);
|
throw new TypeError('Expected a function')
|
||||||
timeout = setTimeout(later, wait);
|
}
|
||||||
|
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