163 lines
5.9 KiB
JavaScript
163 lines
5.9 KiB
JavaScript
// import to from 'await-to-js'
|
|
import RxClass from '@uci-utils/rx-class'
|
|
import moment from 'moment'
|
|
import 'moment-duration-format'
|
|
// import merge from 'deepmerge'
|
|
|
|
// Single Device Scheduler User instance for each unique action
|
|
const DEFAULT_SETTINGS = {
|
|
timing:{
|
|
hour:6,
|
|
minute:0,
|
|
delta:12
|
|
},
|
|
enabled:true,
|
|
simultaneous:false
|
|
}
|
|
|
|
class UCISchedule extends RxClass {
|
|
constructor(opts={}) {
|
|
// console.log('schedule options\n', opts)
|
|
super(opts)
|
|
// console.log('schedule options\n', opts)
|
|
this.name = opts.name || 'a periodic schedule'
|
|
this.id = opts.id || this.name.replace(/ /g, '_')
|
|
this.desc = opts.desc
|
|
// this.dev = opts.dev == null ? false : opts.dev
|
|
// ,DEFAULT_SETTINGS
|
|
this.set('settings',Object.assign({},DEFAULT_SETTINGS,opts.settings))
|
|
this.set('nextTS',0) // the next trigger time in seconds
|
|
this.set('nextDT','') // the next trigger time in seconds
|
|
this.set('active',false)
|
|
this.set('countdown','')
|
|
// console.log(this.name, 'done setup')
|
|
// Actions MUST be promise returning or async
|
|
this._startAction = opts.startAction // || defaultStartAction.bind(this) // single (or array) of function(s)
|
|
this._stopAction = opts.stopAction // || defaultStopAction.bind(this) // single (or array) of function(s)
|
|
this._countdown = this._countdown.bind(this)
|
|
|
|
Object.keys(this.settings.timing).forEach(prop=>{
|
|
this.rxSubscribe(['settings.timing',prop], 'update',this.update.bind(this))
|
|
// console.log('added subs', prop, this._rxGetObj(['settings.timing',prop]).subs)
|
|
})
|
|
|
|
this.rxSubscribe('settings.enabled','state', (value) => {
|
|
// console.log('schedule enabled change', ev)
|
|
this.timer=1.1 // any value but 1 or 60 will trigger
|
|
if (value) this.update()
|
|
})
|
|
|
|
this.set('timer',1)
|
|
this.rxSubscribe('timer','countdown', (value) => {
|
|
// console.log('timer interval', value, this.settings.enabled)
|
|
clearInterval(this.countdownInterval)
|
|
if (this.settings.enabled && value ) this.countdownInterval = setInterval(this._countdown.bind(this),value*1000)
|
|
else this.countdown = ''
|
|
})
|
|
}
|
|
|
|
_countdown(unit) {
|
|
const secs = this.nextTS - Math.floor(Date.now()/1000)
|
|
unit = unit ? unit : secs/60 < 3 ? 'seconds' : 'minutes'
|
|
this.timer = unit === 'seconds' ? 1 : 60
|
|
const format = unit === 'seconds'? 'mm:ss': 'dd hh:mm'
|
|
this.countdown = `${moment.duration(
|
|
parseInt( secs / (unit === 'seconds' ? 1 : 60) )
|
|
,unit
|
|
).format(format)}\u00a0\u00a0(${format})`
|
|
// console.log(secs, this.timer, this.id,this.countdown)
|
|
return this.countdown
|
|
}
|
|
|
|
get countdownMS() {
|
|
return (this.nextTS*1000 - Date.now())
|
|
}
|
|
// make simple access for settings
|
|
get hour () { return this.settings.timing.hour }
|
|
set hour (hour) {
|
|
this.settings.timing.hour= hour
|
|
}
|
|
|
|
get minute () { return this.settings.timing.minute }
|
|
set minute (minute) {
|
|
this.settings.timing.minute= minute
|
|
}
|
|
|
|
get delta () { return this.settings.timing.delta }
|
|
set delta (delta) {
|
|
this.settings.timing.delta= delta
|
|
}
|
|
|
|
get enabled () { return this.settings.enabled }
|
|
set enabled (enable) {
|
|
if (enable == null) enable=true // enabled by default
|
|
this.settings.enabled=enable
|
|
}
|
|
|
|
async update(force) { // all TS in seconds
|
|
const { hour, minute, delta } = this.get('settings.timing')
|
|
const lastTS = this.nextTS
|
|
// console.log('>>>>>>>>>>>>>',this.name, 'updating',hour,minute,delta,lastTS)
|
|
let baseTS = hour*3600+minute*60
|
|
let dt = new Date()
|
|
let intoDayTS = (dt.getSeconds() + (60 * dt.getMinutes()) + (60 * 60 * dt.getHours()))
|
|
let nowTS = Math.floor(Date.now()/1000) + 1 // last TS and nowTS are within 1 sec so add one
|
|
let nextTS = nowTS - intoDayTS + baseTS
|
|
// console.log(this.name, nextTS-nowTS,'first computed time stamp', nextTS)
|
|
while (nowTS > nextTS) {
|
|
// console.log(`now ${nowTS} is beyond next ${nextTS} adding delta ${delta * 60 * 60 } seconds`)
|
|
nextTS += (delta * 60 * 60 ) // delta in hours, TS in secs
|
|
}
|
|
// console.log(lastTS,'computed time stamp', nextTS)
|
|
if(nextTS !== lastTS || lastTS == null || force===true) {
|
|
// console.log('UPDATED TS>>>>>>>>>>>>>>>>', this.name,hour,minute,delta,nextTS,nextTS-lastTS)
|
|
this.nextDT = moment(nextTS*1000).format('ddd, MMM Do h:mm:ss A')
|
|
this.nextTS = nextTS
|
|
this._countdown()
|
|
// console.log(this.nextTS,this.nextDT, this.countdown)
|
|
this.emit('updated',{id:this.id,nextTS:nextTS,nextDT:this.nextDT, timing:this.get('settings.timing')})
|
|
}
|
|
}
|
|
|
|
// MUST! be async or promise TODO make that check
|
|
registerStartAction(func) {
|
|
if (typeof func!=='function') throw new Error('start action must be a function and be async or promise returning')
|
|
// console.log(arguments)
|
|
const args = [...arguments]
|
|
args.shift()
|
|
// console.log(this.name,this.id,'registering start action with these arguments to be passed\n',args)
|
|
this._startAction = func.bind(this,...args)
|
|
}
|
|
|
|
registerStopAction(func) {
|
|
if (typeof func!=='function') throw new Error('stop action must be a function')
|
|
const args = [...arguments]
|
|
args.shift()
|
|
// console.log('registering stop action with these arguments to be passed\n',args)
|
|
this._stopAction = func.bind(this,...args)
|
|
}
|
|
|
|
async startAction () {
|
|
if (this._startAction) {
|
|
this.active = true
|
|
await this._startAction(this) // this is active schedule copy
|
|
this.active = false
|
|
this.emit(this.runID) // runner listens for this ID of active schedule to know when it's done
|
|
} else console.log('no registered start action, register a start action!')
|
|
}
|
|
|
|
async stopAction () {
|
|
if (this._stopAction) {
|
|
await this._stopAction(this) // this is active schedule copy
|
|
this.emit(this.runID)
|
|
this.active = false
|
|
}
|
|
else console.log('no registered stop action, unable to abort, action will complete normally')
|
|
}
|
|
|
|
}
|
|
|
|
|
|
export default UCISchedule
|
|
export {UCISchedule as Schedule}
|