--[[
ģƣ
ģ鹦ܣкšIMEIײ汾šʱӡǷУ׼ģʽѯصȹ
ģ޸ʱ䣺2017.02.14
]]

--ģ,
local string = require"string"
local ril = require"ril"
local sys = require"sys"
local base = _G
local os = require"os"
local io = require"io"
local rtos = require"rtos"
local pmd = require"pmd"
module(...)

--سõȫֺ
local type,assert,tonumber,tostring,print,req,smatch = base.type,base.assert,base.tonumber,base.tostring,base.print,ril.request,string.match

--snк
--snrdyǷѾɹȡк
--imeiIMEI
--imeirdyǷѾɹȡIMEI
--verײ汾
--clkswitchʱ֪ͨ
--updatingǷִԶ(update.lua)
--dbgingǷִdbg(dbg.lua)
--ntpingǷִNTPʱͬ(ntp.lua)
--flypendingǷеȴĽģʽ
local sn,snrdy,imeirdy,--[[ver,]]imei,clkswitch,updating,dbging,ntping,flypending

--calibУ׼־trueΪУ׼δУ׼
--setclkcbִAT+CCLKӦûԶص
--wimeicbִAT+WIMEIӦûԶص
--wsncbִAT+WISNӦûԶص
local calib,setclkcb,wimeicb,wsncb

--[[
rsp
  ģڡͨ⴮ڷ͵ײcoreATӦ
  
		cmdӦӦAT
		successATִнtruefalse
		responseATӦеִнַ
		intermediateATӦемϢ
ֵ
]]
local function rsp(cmd,success,response,intermediate)
	local prefix = string.match(cmd,"AT(%+%u+)")
	--ѯк
	if cmd == "AT+WISN?" then
		sn = intermediate
		if wsncb then wsncb(success) end
		--ûгɹȡкţһڲϢSN_READYʾѾȡк
		if not snrdy then sys.dispatch("SN_READY") snrdy = true end
	--ѯײ汾
	--[[elseif cmd == "AT+VER" then
		ver = intermediate]]
	--ѯIMEI
	elseif cmd == "AT+CGSN" then
		imei = intermediate
		if wimeicb then wimeicb(success) end
		--ûгɹȡIMEIһڲϢIMEI_READYʾѾȡIMEI
		if not imeirdy then sys.dispatch("IMEI_READY") imeirdy = true end
	--дIMEI
	elseif smatch(cmd,"AT%+WIMEI=") then
		if wimeicb then
			req("AT+CGSN")
			--wimeicb(success)
		else			
			if tonumber(smatch(sys.getcorever(),"Luat_V(%d+)_"))>15 then sys.restart("WIMEI") end
		end
	--дк
	elseif smatch(cmd,"AT%+WISN=") then
		if wsncb then
			req("AT+WISN?")
			--wsncb(success)
		else			
			if tonumber(smatch(sys.getcorever(),"Luat_V(%d+)_"))>15 then sys.restart("WISN") end
		end
	--ϵͳʱ
	elseif prefix == "+CCLK" then
		startclktimer()
		--ATӦлص
		if setclkcb then
			setclkcb(cmd,success,response,intermediate)
		end
	--ѯǷУ׼
	elseif cmd == "AT+ATWMFT=99" then
		print('ATWMFT',intermediate)
		if intermediate == "SUCC" then
			calib = true
		else
			calib = false
		end
	--˳ģʽ
	elseif smatch(cmd,"AT%+CFUN=[01]") then
		--һڲϢFLYMODE_INDʾģʽ״̬仯
		sys.dispatch("FLYMODE_IND",smatch(cmd,"AT%+CFUN=(%d)")=="0")
	end
	
end

--[[
setclock
  ϵͳʱ
  
		tϵͳʱʽο{year=2017,month=2,day=14,hour=14,min=2,sec=58}
		rspfuncϵͳʱûԶص
ֵ
]]
function setclock(t,rspfunc)
	if t.year - 2000 > 38 then return end
	setclkcb = rspfunc
	req(string.format("AT+CCLK=\"%02d/%02d/%02d,%02d:%02d:%02d+32\"",string.sub(t.year,3,4),t.month,t.day,t.hour,t.min,t.sec),nil,rsp)
end

--[[
getclockstr
  ȡϵͳʱַ
  
ֵϵͳʱַʽΪYYMMDDhhmmss1702141416021721414ʱ1602
]]
function getclockstr()
	local clk = os.date("*t")
	clk.year = string.sub(clk.year,3,4)
	return string.format("%02d%02d%02d%02d%02d%02d",clk.year,clk.month,clk.day,clk.hour,clk.min,clk.sec)
end

--[[
getweek
  ȡ
  
ֵڣnumberͣ1-7ֱӦһ
]]
function getweek()
	local clk = os.date("*t")
	return ((clk.wday == 1) and 7 or (clk.wday - 1))
end

--[[
getclock
  ȡϵͳʱ
  
ֵtable͵ʱ䣬{year=2017,month=2,day=14,hour=14,min=19,sec=23}
]]
function getclock()
	return os.date("*t")
end

--[[
startclktimer
  ѡԵʱ֪ͨʱ
  
ֵ
]]
function startclktimer()
	--ؿ  ģʽΪģʽ
	if clkswitch or sys.getworkmode()==sys.FULL_MODE then
		--һڲϢCLOCK_INDʾ֣121300롢143400
		sys.dispatch("CLOCK_IND")
		print('CLOCK_IND',os.date("*t").sec)
		--´֪ͨĶʱ
		sys.timer_start(startclktimer,(60-os.date("*t").sec)*1000)
	end
end

--[[
setclkswitch
  áʱ֪ͨ
  
		vtrueΪΪر
ֵ
]]
function setclkswitch(v)
	clkswitch = v
	if v then startclktimer() end
end

--[[
getsn
  ȡк
  
ֵкţδȡ""
]]
function getsn()
	return sn or ""
end

--[[
isnvalid
  жsnǷЧ
  
ֵЧtrue򷵻false
]]
function isnvalid()
	local snstr,sninvalid = getsn(),""
	local len,i = string.len(snstr)
	for i=1,len do
		sninvalid = sninvalid.."0"
	end
	return snstr~=sninvalid
end

--[[
getimei
  ȡIMEI
  
ֵIMEIţδȡ""
ע⣺luaű֮󣬻ᷢatȥѯimeiҪһʱܻȡimeiô˽ӿڣϷ""
]]
function getimei()
	return imei or ""
end

--[[
setimei
  IMEI
		cbIMEI󲻻ԶûԼ֤óɹ󣬵sys.restartdbg.restartӿڽ;
		ûдcbóɹԶ
  
		sIMEI
		cbúĻصʱὫýȥtrueʾóɹfalsenilʾʧܣ
ֵ
]]
function setimei(s,cb)
	if s==imei then
		if cb then cb(true) end
	else
		req("AT+AMFAC="..(cb and "0" or "1"))
		req("AT+WIMEI=\""..s.."\"")
		wimeicb = cb
	end
end

--[[
setsn
  SN
		cbSN󲻻ԶûԼ֤óɹ󣬵sys.restartdbg.restartӿڽ;
		ûдcbóɹԶ
  
		sSN
		cbúĻصʱὫýȥtrueʾóɹfalsenilʾʧܣ
ֵ
]]
function setsn(s,cb)
	if s==sn then
		if cb then cb(true) end
	else
		req("AT+AMFAC="..(cb and "0" or "1"))
		req("AT+WISN=\""..s.."\"")
		wsncb = cb
	end
end


--[[
setflymode
  Ʒģʽ
  
		valtrueΪģʽfalseΪ˳ģʽ
ֵ
]]
function setflymode(val)
	--ǽģʽ
	if val then
		--ִԶܻdbgܻntpܣӳٽģʽ
		if updating or dbging or ntping then flypending = true return end
	end
	--AT˳ģʽ
	req("AT+CFUN="..(val and 0 or 1))
	flypending = false
end

--[[
set
  ֮ǰдľɳĿǰΪպ
  
ֵ
]]
function set() end

--[[
getcalib
  ȡǷУ׼־
  
ֵtrueΪУ׼ΪûУ׼
]]
function getcalib()
	return calib
end

--[[
getvbatvolt
  ȡVBATĵصѹ
  
ֵѹnumberͣλ
]]
function getvbatvolt()
	local v1,v2,v3,v4,v5 = pmd.param_get()
	return v2
end

--[[
openpwm
  򿪲PWM(֧2·PWM֧)
  
		idnumberͣPWM֧ͨ010õuart2 tx1õuart2 rx
		periodnumber
				idΪ0ʱperiodʾƵʣλΪHzȡֵΧΪ80-65535֧
				idΪ1ʱȡֵΧΪ0-7֧ʾʱڣλΪ룬0-7ֱӦ12525050010001500200025003000
		levelnumber
				idΪ0ʱlevelʾռձȣλΪlevel%ȡֵΧΪ1-100֧
				idΪ1ʱȡֵΧΪ1-15֧ʾһʱڵĸߵƽʱ䣬λΪ
				1-15ֱӦ15.631.246.962.578.193.7110125141156172187203219234
ֵ
˵idΪ0ʱ
	  period ȡֵ 80-1625 HzΧʱlevel ռձȡֵΧΪ1-100
	  period ȡֵ 1626-65535 HzΧʱx=162500/period, y=x * level / 100, x  yԽǽӽԽ׼ȷ
]]
function openpwm(id,period,level)
	assert(type(id)=="number" and type(period)=="number" and type(level)=="number","openpwm type error")
	assert(id==0 or id==1,"openpwm id error: "..id)
	--[[local pmin,pmax,lmin,lmax = 80,1625,1,100
	if id==1 then pmin,pmax,lmin,lmax = 0,7,1,15 end
	assert(period>=pmin and period<=pmax,"openpwm period error: "..period)
	assert(level>=lmin and level<=lmax,"openpwm level error: "..level)]]
	req("AT+SPWM="..id..","..period..","..level)
end

--[[
closepwm
  رPWM
  
		idnumberͣPWM֧ͨ010õuart2 tx1õuart2 rx
ֵ
]]
function closepwm(id)
	assert(id==0 or id==1,"closepwm id error: "..id)
	req("AT+SPWM="..id..",0,0")
end

--[[
ind
  ģעڲϢĴ
  
		idڲϢid
		paraڲϢ
ֵtrue
]]
local function ind(id,para)
	--ģʽ仯
	if id=="SYS_WORKMODE_IND" then
		startclktimer()
	--Զʼ
	elseif id=="UPDATE_BEGIN_IND" then
		updating = true
	--Զ
	elseif id=="UPDATE_END_IND" then
		updating = false
		if flypending then setflymode(true) end
	--dbgܿʼ
	elseif id=="DBG_BEGIN_IND" then
		dbging = true
	--dbgܽ
	elseif id=="DBG_END_IND" then
		dbging = false
		if flypending then setflymode(true) end
	--NTPͬʼ
	elseif id=="NTP_BEGIN_IND" then
		ntping = true
	--NTPͬ
	elseif id=="NTP_END_IND" then
		ntping = false
		if flypending then setflymode(true) end
	end

	return true
end

--עATӦ
ril.regrsp("+ATWMFT",rsp)
ril.regrsp("+WISN",rsp)
--ril.regrsp("+VER",rsp,4,"^[%w_]+$")
ril.regrsp("+CGSN",rsp)
ril.regrsp("+WIMEI",rsp)
ril.regrsp("+AMFAC",rsp)
ril.regrsp("+CFUN",rsp)
--ѯǷУ׼
req("AT+ATWMFT=99")
--ѯк
req("AT+WISN?")
--ѯײ汾
--req("AT+VER")
--ѯIMEI
req("AT+CGSN")
--ʱ֪ͨʱ
startclktimer()
--ע᱾ģעڲϢĴ
sys.regapp(ind,"SYS_WORKMODE_IND","UPDATE_BEGIN_IND","UPDATE_END_IND","DBG_BEGIN_IND","DBG_END_IND","NTP_BEGIN_IND","NTP_END_IND")
