import type { MarkRequired } from 'ts-essentials' ; import type { AnyDevice , SendOptions } from '../client' ; import { extractResponse , hasErrCode , HasErrCode , isDefinedAndNotNull , isObjectLike , } from '../utils' ; type ScheduleDateStart = { smin : number ; stime_opt : number ; } ; type ScheduleDateEnd = { emin : number ; etime_opt : number ; } ; type WDay = [ boolean , boolean , boolean , boolean , boolean , boolean , boolean ] ; export type ScheduleRule = { name ? : string ; enable ? : number ; day ? : number ; month ? : number ; year ? : number ; wday ? : WDay ; repeat ? : boolean ; etime_opt : - 1 ; emin : - 1 | 0 ; } & ( ScheduleDateStart | Record < string , unknown > ) ; export type ScheduleRuleWithId = ScheduleRule & { id : string ; } ; type ScheduleRules = { rule_list : ScheduleRuleWithId [ ] ; } ; type ScheduleNextAction = Record < string , unknown > ; export type ScheduleRuleResponse = ScheduleRule & HasErrCode ; export type ScheduleRulesResponse = ScheduleRules & HasErrCode ; export type ScheduleNextActionResponse = ScheduleNextAction & HasErrCode ; function isScheduleNextAction ( candidate ) { return isObjectLike ( candidate ) ; } export function isScheduleNextActionResponse ( candidate ) { return isScheduleNextAction ( candidate ) && hasErrCode ( candidate ) ; } export type HasRuleListWithRuleIds = { rule_list : { id : string ; } [ ] ; } ; export function hasRuleListWithRuleIds ( candidate ) { return ( isObjectLike ( candidate ) && 'rule_list' in candidate && isObjectLike ( candidate . rule_list ) && Array . isArray ( candidate . rule_list ) && candidate . rule_list . every ( ( rule ) => 'id' in rule && typeof rule . id === 'string' ) ) ; } function isScheduleRules ( candidate ) { return ( isObjectLike ( candidate ) && 'rule_list' in candidate && isObjectLike ( candidate . rule_list ) && Array . isArray ( candidate . rule_list ) && candidate . rule_list . every ( ( rule ) => 'id' in rule && typeof rule . id === 'string' ) ) ; } export function isScheduleRulesResponse ( candidate ) { return isScheduleRules ( candidate ) && hasErrCode ( candidate ) ; } export type ScheduleRuleInputTime = Date | number | 'sunrise' | 'sunset' ; function createScheduleDate ( date , startOrEnd ) { let min = 0 ; let time_opt = 0 ; if ( date instanceof Date ) { min = date . getHours ( ) * 60 + date . getMinutes ( ) ; } else if ( typeof date === 'number' ) { min = date ; } else if ( date === 'sunrise' ) { min = 0 ; time_opt = 1 ; } else if ( date === 'sunset' ) { min = 0 ; time_opt = 2 ; } if ( startOrEnd === 'end' ) { return { emin : min , etime_opt : time_opt } ; } return { smin : min , stime_opt : time_opt } ; } function createScheduleDateStart ( date ) { return createScheduleDate ( date , 'start' ) as ScheduleDateStart ; } function createScheduleDateEnd ( date ) { return createScheduleDate ( date , 'end' ) as ScheduleDateEnd ; } function createWday ( daysOfWeek ) { const wday = [ false , false , false , false , false , false , false ] ; daysOfWeek . forEach ( ( dw ) => { wday [ dw ] = true ; } ) ; return wday ; } export function createScheduleRule ( { start , daysOfWeek , } ) { const sched = createScheduleDateStart ( start ) ; if ( isDefinedAndNotNull ( daysOfWeek ) && daysOfWeek . length > 0 ) { sched . wday = createWday ( daysOfWeek ) ; sched . repeat = true ; } else { const date = start instanceof Date ? start : new Date ( ) ; sched . day = date . getDate ( ) ; sched . month = date . getMonth ( ) + 1 ; sched . year = date . getFullYear ( ) ; sched . wday = [ false , false , false , false , false , false , false ] ; sched . wday [ date . getDay ( ) ] = true ; sched . repeat = false ; } return sched as MarkRequired < typeof sched , 'wday' | 'repeat' > ; } export function createRule ( { start , end , daysOfWeek , } ) { const sched = createScheduleDateStart ( start ) ; if ( isDefinedAndNotNull ( end ) ) { Object . assign ( sched , createScheduleDateEnd ( end ) ) ; } if ( isDefinedAndNotNull ( daysOfWeek ) && daysOfWeek . length > 0 ) { sched . wday = createWday ( daysOfWeek ) ; sched . repeat = true ; } else { const date = start instanceof Date ? start : new Date ( ) ; sched . day = date . getDate ( ) ; sched . month = date . getMonth ( ) + 1 ; sched . year = date . getFullYear ( ) ; sched . wday = [ false , false , false , false , false , false , false ] ; sched . wday [ date . getDay ( ) ] = true ; sched . repeat = false ; } return sched as MarkRequired < typeof sched , 'wday' | 'repeat' > ; } export default abstract class Schedule { nextAction : ScheduleNextActionResponse | undefined ; constructor ( readonly device , readonly apiModuleName , readonly childId ? ) { } throws ResponseError async getNextAction ( sendOptions ? ) { this . nextAction = extractResponse ( await this . device . sendCommand ( { [ this . apiModuleName ] : { get_next_action : { } } , } , this . childId , sendOptions ) , '' , isScheduleNextActionResponse ) as ScheduleNextActionResponse ; return this . nextAction ; } throws ResponseError async getRules ( sendOptions ? ) { return extractResponse ( await this . device . sendCommand ( { [ this . apiModuleName ] : { get_rules : { } } , } , this . childId , sendOptions ) , '' , isScheduleRulesResponse ) as ScheduleRulesResponse ; } throws ResponseError throws Error async getRule ( id , sendOptions ? ) { const rules = await this . getRules ( sendOptions ) ; const rule = rules . rule_list . find ( ( r ) => r . id === id ) ; if ( rule === undefined ) throw new Error ( `Rule id not found: ${ id }` ) ; return { ... rule , err_code : rules . err_code } ; } returns throws ResponseError async addRule ( rule , sendOptions ? ) { return extractResponse ( await this . device . sendCommand ( { [ this . apiModuleName ] : { add_rule : rule } , } , this . childId , sendOptions ) , '' , ( candidate ) => { return isObjectLike ( candidate ) && typeof candidate . id === 'string' ; } ) as { id : string ; } ; } returns throws ResponseError async editRule ( rule , sendOptions ? ) { return this . device . sendCommand ( { [ this . apiModuleName ] : { edit_rule : rule } , } , this . childId , sendOptions ) ; } returns throws ResponseError async deleteAllRules ( sendOptions ? ) { return this . device . sendCommand ( { [ this . apiModuleName ] : { delete_all_rules : { } } , } , this . childId , sendOptions ) ; } returns throws ResponseError async deleteRule ( id , sendOptions ? ) { return this . device . sendCommand ( { [ this . apiModuleName ] : { delete_rule : { id } } , } , this . childId , sendOptions ) ; } returns throws ResponseError async setOverallEnable ( enable , sendOptions ? ) { return this . device . sendCommand ( { [ this . apiModuleName ] : { set_overall_enable : { enable : enable ? 1 : 0 } , } , } , this . childId , sendOptions ) ; } returns throws ResponseError async getDayStats ( year , month , sendOptions ? ) { return this . device . sendCommand ( { [ this . apiModuleName ] : { get_daystat : { year , month } } , } , this . childId , sendOptions ) ; } returns throws ResponseError async getMonthStats ( year , sendOptions ? ) { return this . device . sendCommand ( { [ this . apiModuleName ] : { get_monthstat : { year } } , } , this . childId , sendOptions ) ; } returns throws ResponseError async eraseStats ( sendOptions ? ) { return this . device . sendCommand ( { [ this . apiModuleName ] : { erase_runtime_stat : { } } , } , this . childId , sendOptions ) ; } }