require "main.global" local tools = require "main.tools" local fileOpt = require "storage.fileOpt" local cjson = require "cjson" local schedule = {} local ZENITH = 90.833 local PI = 3.1415926535898 -- mm.dd转day function schedule.toDayIndex(month, date) local index = 0 if month ~= 1 then for i = 1, month - 1, 1 do index = index + MONTH_DAY[i] end end return index + date end -- day转mm.dd function schedule.fromDayIndex(index) local month for i = 1, 12, 1 do if index <= MONTH_DAY[i] then month = i break else index = index - MONTH_DAY[i] end end return month, index end -- 根据 day 和 经纬度 计算日出日落时间 local function calRiseSet(date, isRise) local lngHour = SdbConfig.Longitude / 15; local t = date + (isRise and 6.0 or 18.0 - lngHour) / 24 local M = 0.9856 * t - 3.289; local L = M + 1.916 * math.sin(M * PI / 180) + 0.02 * math.sin(2 * M * PI / 180) + 282.634 while true do if L >= 360 then L = L- 360 else if L < 0 then L = L + 360 else break end end end local RA = math.atan(0.91764 * math.tan(L * PI / 180)) / PI * 180 while true do if RA >= 360 then RA = RA - 360 else if RA < 0 then RA = RA + 360 else break end end end local Lquadrant = (math.floor(L /90)) * 90 local RAquadrant = (math.floor(RA /90)) * 90 RA = RA + Lquadrant - RAquadrant RA = RA / 15 local sinDec = 0.39782 * math.sin(L * PI / 180) local cosDec = math.cos(math.asin(sinDec)) local cosH = (math.cos(ZENITH * PI / 180) - sinDec * math.sin(SdbConfig.Latitude * PI / 180)) / (cosDec * math.cos(SdbConfig.Latitude * PI / 180)) local H = 0 if isRise then H = 360.0 - math.acos(cosH) / PI * 180 else H = math.acos(cosH) / PI * 180 end H = H / 15; local T = H + RA - 0.06571 * t - 6.622; while true do if T >= 24 then T = T - 24 else if T < 0 then T = T + 24 else break end end end return T * 60 + (isRise and ScheOffset or ScheOffset) end local function calSchedule(month, day) local dateIndex = schedule.toDayIndex(month, day) return calRiseSet(dateIndex, true), calRiseSet(dateIndex, false) end function schedule.init() local index = schedule.toDayIndex(1, 12) local month, date = schedule.fromDayIndex(index) for i = 1, 12, 1 do --按月存储 local fileName = SCHE_FILE_PREFIX .. i .. SCHE_FILE_EXT local file_data = fileOpt.read(fileName, true) local sche if not pcall(function() sche = cjson.decode(file_data) end) then sche = {} end if sche == nil then sche = {} end if not sche.isValid then -- 当月策略不存在,写入默认值(计算的日出日落时间) log_print.info("sche dose not exsist") for j = 1, MONTH_DAY[i], 1 do local key = tostring(j) sche[key] = {} local rise, set = calSchedule(i, j) for k = 1, TOTAL_CH, 1 do sche[key][tostring(k)] = string.format("%02d%02d00%02d%02d01", math.floor(rise / 60), math.floor(rise % 60), math.floor(set / 60), math.floor(set % 60)) end end sche.isValid = true local str = cjson.encode(sche) fileOpt.write(fileName, str) else -- end end end -- 重新计算策略(全年) function schedule.cal_sche() local index = schedule.toDayIndex(1, 12) local month, date = schedule.fromDayIndex(index) for i = 1, 12, 1 do -- 按月存储 local sche = {} local fileName = SCHE_FILE_PREFIX .. i .. SCHE_FILE_EXT log_print.info("cal_sche::", "yearSchedule", i) for j = 1, MONTH_DAY[i], 1 do local key = tostring(j) sche[key] = {} local rise, set = calSchedule(i, j) for k = 1, TOTAL_CH, 1 do sche[key][tostring(k)] = string.format("%02d%02d00%02d%02d01", math.floor(rise / 60), math.floor(rise % 60), math.floor(set / 60), math.floor(set % 60)) end end sche.isValid = true local str = cjson.encode(sche) fileOpt.write(fileName, str) end end -- 读取当月策略 function schedule.read(month) if(month > 12 or month < 1) then log_print.info("months are not within January to December:", month) return nil end local fileName = SCHE_FILE_PREFIX .. month .. SCHE_FILE_EXT --log_print.info("fileName:", fileName) local fileData = fileOpt.read(fileName) local sche pcall(function() sche = cjson.decode(fileData) end) --log_print.info("monthly strategy:", fileData) return sche end -- 读取当天策略 function schedule.readDay(month, date) local scheMonth = schedule.read(month) if scheMonth ~= nil and scheMonth.isValid then return scheMonth[tostring(date)] else log_print.info("Cannot get the current month strategy") return nil end end -- 网关存储策略绝对日期设置 mode 0 function schedule.set_absolutely(month, date, sche, chn) local dayIndex = schedule.toDayIndex(month, date) local nowSche = schedule.read(month) -- 读取当月的策略 if nowSche == nil then return false end local monthStart = month -- 每天最多设置 4 个开关灯时间 -- "strategy":"0630001800AA#0628001735AA2105002305AA#0625001740AA" for i = 1, #sche, 1 do local m, d = schedule.fromDayIndex(dayIndex) dayIndex = dayIndex + 1 if dayIndex > 366 then dayIndex = 1 end -- 下发策略跨月份处理 if m ~= monthStart then fileOpt.write(SCHE_FILE_PREFIX .. monthStart .. SCHE_FILE_EXT, cjson.encode(nowSche), true) nowSche = schedule.read(m) if nowSche == nil then return false end monthStart = m end if chn == 0 then -- 0表示所有回路同时有效 for j = 1, TOTAL_CH, 1 do nowSche[tostring(d)][tostring(j)] = sche[i] end else -- 1~n 对应1~n回路 nowSche[tostring(d)][tostring(chn)] = sche[i] end end fileOpt.write(SCHE_FILE_PREFIX .. monthStart .. SCHE_FILE_EXT, cjson.encode(nowSche), true) return true end -- 网关存储策略重复日期设置 mode 1 function schedule.set_repeat(month, date, sche, chn, rep_day) local dayIndex = schedule.toDayIndex(month, date) local nowSche = schedule.read(month) -- 读取当月的策略 if nowSche == nil then return false end local monthStart = month -- 每天最多设置 4 个开关灯时间 -- "strategy":"0628001735AA2105002305AA" for j = 1, rep_day, 1 do for i = 1, #sche, 1 do local m, d = schedule.fromDayIndex(dayIndex) dayIndex = dayIndex + 1 if dayIndex > 366 then dayIndex = 1 end -- 下发策略跨月份处理 if m ~= monthStart then fileOpt.write(SCHE_FILE_PREFIX .. monthStart .. SCHE_FILE_EXT, cjson.encode(nowSche), true) nowSche = schedule.read(m) if nowSche == nil then return false end monthStart = m end if chn == 0 then -- 0表示所有回路同时有效 for j = 1, TOTAL_CH, 1 do nowSche[tostring(d)][tostring(j)] = sche[i] end else -- 1~n 对应1~n回路 nowSche[tostring(d)][tostring(chn)] = sche[i] end end end fileOpt.write(SCHE_FILE_PREFIX .. monthStart .. SCHE_FILE_EXT, cjson.encode(nowSche), true) return true end return schedule