local e=require("libat.firmware_upgrade")local r=require("mobiled.scripthelpers")local o=require("libat.session")local u=require("libat.voice")local d=require("libat.tty")local _=require("libat.sim")local n=table.insert
local a={voice_support={["K5160"]={cs_voice_support=true},["K4203"]={cs_voice_support=true}},max_data_sessions={["K4305"]=2}}local t={}t.__index=t
local f={}local function l(e)local n,e,t=e:match("%^NWTIME:%s?(%d+/%d+/%d+,%d+:%d+:%d+)([+-]%d+),(%d+)")if n then
local e,t,r,d,i,a=n:match("(%d+)/(%d+)/(%d+),(%d+):(%d+):(%d+)")if e then
e=tonumber(e)+2000
n=os.time({day=r,month=t,year=tostring(e),hour=d,min=i,sec=a})end
end
t=tonumber(t)e=tonumber(e)if e then
e=e*15
end
return n,e,t
end
function t:set_attach_params(n,e)local t,r=o.get_pdp_type(n,e.pdptype)if not t then
return nil,r
end
local r=e.apn or""n:send_command(string.format('AT+CGDCONT=0,"%s","%s"',t,r))n:send_command(string.format('AT+CGDCONT=1,"%s","%s"',t,r))if e.authentication and e.password and e.username then
local t="2"if e.authentication=="pap"then
t="1"end
n:send_command(string.format('AT^AUTHDATA=0,%d,"","%s","%s"',t,e.password,e.username))n:send_command(string.format('AT^AUTHDATA=1,%d,"","%s","%s"',t,e.password,e.username))else
n:send_command("AT^AUTHDATA=0")n:send_command("AT^AUTHDATA=1")end
return true
end
function t:start_data_session(n,t,e)local r=t+1
local t=n.sessions[r]if t and t.proto=="ppp"then
return true
end
n:send_command("AT^DSFLOWRPT=1",2000)local i=true
local d=e.apn or""if t then
if not t.context_created then
local e,t=o.get_pdp_type(n,e.pdptype)if not e then
return nil,t
end
i=n:send_command(string.format('AT+CGDCONT=%d,"%s","%s"',r,e,d))end
if i then
t.context_created=true
if e.authentication and e.password and e.username then
local t="2"if e.authentication=="pap"then
t="1"end
local e=string.format('AT^NDISDUP=%d,1,"%s","%s","%s",%d',r,d,e.username,e.password,t)return n:send_command(e,5000)else
return n:send_command('AT^NDISDUP='..r..',1,"'..d..'"',5000)end
end
end
end
function t:stop_data_session(t,e)local n=e+1
local e=t.sessions[n]if e and e.proto=="ppp"then
return true
end
local n=t:send_command(string.format('AT^NDISDUP=%d,0',n),5000)if e then
e.context_created=nil
end
return n
end
local function c(e,n)local n,i,d,t,r,a,o=n:match('%^DSFLOWRPT:%s?(%x+),(%x+),(%x+),(%x+),(%x+),(%x+),(%x+)')if e.buffer.session_info and e.buffer.session_info.duration and tonumber(n,16)==0 then
e.runtime.log:notice("Wrong info in ^DSFLOWRPT indication. Turning it off.")e:send_command('AT^DSFLOWRPT=0')e.buffer.session_info={}e.buffer.network_info={}return
end
e.buffer.session_info={packet_counters={tx_bytes=tonumber(t,16),rx_bytes=tonumber(r,16)},duration=tonumber(n,16)}if not e.buffer.network_info then
e.buffer.network_info={}end
e.buffer.network_info.connection_rate={current_ul_speed=tonumber(i,16),current_dl_speed=tonumber(d,16),max_ul_speed=tonumber(a,16),max_dl_speed=tonumber(o,16)}end
local function m(e,n)local d,n,r=n:match('%^NDISSTAT:%s*(%d+),(.-),.-,"(.-)"')if d=='0'then
local t
if r then
t=r:lower()end
if n=='0'then
n=nil
end
e.buffer.session_info={}e:send_event("mobiled",{event="session_disconnected",session_id=0,dev_idx=e.dev_idx,reject_cause=tonumber(n),pdp_type=t})elseif d=='1'then
e:send_event("mobiled",{event="session_connected",session_id=0,dev_idx=e.dev_idx})end
end
local function h(e,n)local n,t=n:match('%^NWNAME:%s*"(.-)","(.-)"')if not e.buffer.network_info then
e.buffer.network_info={}end
if not e.buffer.network_info.plmn_info then
e.buffer.network_info.plmn_info={}end
if n and n~=""then
e.buffer.network_info.plmn_info.description=n
elseif t and t~=""then
e.buffer.network_info.plmn_info.description=t
end
end
local o={[1]=e.error_codes.unknown_error,[2]=e.error_codes.invalid_state,[3]=e.error_codes.invalid_parameters,[4]=e.error_codes.not_supported,[5]=e.error_codes.unknown_error,[11]=e.error_codes.download_failed,[12]=e.error_codes.download_failed,[13]=e.error_codes.download_failed,[14]=e.error_codes.download_failed,[15]=e.error_codes.download_failed,[16]=e.error_codes.download_failed,[17]=e.error_codes.download_failed,[18]=e.error_codes.download_failed,[19]=e.error_codes.download_failed,[20]=e.error_codes.download_failed,[21]=e.error_codes.download_failed,[22]=e.error_codes.invalid_image,[23]=e.error_codes.download_failed,[51]=e.error_codes.download_failed,[52]=e.error_codes.invalid_image,[54]=e.error_codes.download_failed,[101]=e.error_codes.download_failed,[102]=e.error_codes.download_failed,[103]=e.error_codes.download_failed,[104]=e.error_codes.download_failed,[105]=e.error_codes.download_failed,[106]=e.error_codes.download_failed,[107]=e.error_codes.download_failed,[108]=e.error_codes.download_failed,[109]=e.error_codes.download_failed,[110]=e.error_codes.download_failed,[111]=e.error_codes.download_failed,[112]=e.error_codes.download_failed,[113]=e.error_codes.download_failed,[114]=e.error_codes.flashing_failed,[151]=e.error_codes.flashing_failed,[152]=e.error_codes.flashing_failed,[153]=e.error_codes.flashing_failed,[154]=e.error_codes.flashing_failed,[155]=e.error_codes.flashing_failed,[156]=e.error_codes.flashing_failed,[157]=e.error_codes.flashing_failed,[158]=e.error_codes.flashing_failed,[159]=e.error_codes.flashing_failed}local function s(n,d,i)local r=tonumber(d:match('%^FOTASTATE:%s*(%d+)'))local t
if r==10 then
t="not_running"elseif r==11 then
n.buffer.firmware_upgrade_info.target_version=nil
t="checking_version"elseif r==12 then
t="upgrade_available"local e=d:match('%^FOTASTATE:%s*%d+,(.-),')if e then
n.buffer.firmware_upgrade_info.target_version=e
end
elseif r==14 then
n.buffer.firmware_upgrade_info.target_version=nil
t="no_upgrade_available"elseif r==30 then
t="downloading"elseif r==40 then
t="downloaded"elseif r==50 then
t="flashing"elseif r==90 then
t="done"elseif r==13 or r==20 or r==80 then
t="failed"local t=tonumber(d:match('%^FOTASTATE:%s*%d+,(%d+)'))n.buffer.firmware_upgrade_info.error_code=o[t]or e.error_codes.unknown_error
n.buffer.firmware_upgrade_info.device_error=t
end
if n.buffer.firmware_upgrade_info.status~="done"and n.buffer.firmware_upgrade_info.status~="failed"then
n.buffer.firmware_upgrade_info.status=t
end
if i then
e.update_state(n,n.buffer.firmware_upgrade_info)if t=="done"or t=="no_upgrade_available"then
n:send_event("mobiled",{event="firmware_upgrade_done",dev_idx=n.dev_idx})elseif t=="failed"then
n:send_event("mobiled",{event="firmware_upgrade_failed",dev_idx=n.dev_idx})end
end
end
local function p(e,n)local t,n=n:match('%^LTERSRP:%s*([%d-]+),([%d-]+)')e.buffer.radio_signal_info.rsrp=tonumber(t)e.buffer.radio_signal_info.rsrq=tonumber(n)end
local function o(e,n)if type(e)=="table"then
for t,e in pairs(e)do
if e.radio_interface==n then
return true
end
end
end
return nil
end
function t:get_sim_info(e,n)if not e.buffer.sim_info.iccid then
local n=e:send_singleline_command('AT^ICCID?',"^ICCID:",100)if n then
local n=n:match('%^ICCID:%s?(.+)')if _.check_iccid(n)then
e.buffer.sim_info.iccid=n
end
end
end
end
function t:get_radio_signal_info(d,e)r.merge_tables(e,d.buffer.radio_signal_info)local t,i=d:send_singleline_command('AT^HCSQ?',"^HCSQ:",100)if t then
local d=t:match('%^HCSQ:%s?"([A-Z]+)"')local n=tonumber(t:match('%^HCSQ:%s?"[A-Z]+",(%d+)'))if(n and n>0 and n<=96)then
e.rssi=(n-120)end
if d=="LTE"then
e.radio_interface="lte"local n,t,r=t:match('%^HCSQ:%s?"[A-Z]+",%d+,(%d+),(%d+),(%d+)')n=tonumber(n)if(n and n>0 and n<=97)then
e.rsrp=(n-140)end
t=tonumber(t)if(t and t>0 and t<=251)then
e.snr=((t*.2)-20)end
r=tonumber(r)if(r and r>0 and r<=34)then
e.rsrq=((r*.5)-19.5)end
elseif d=="WCDMA"then
e.radio_interface="umts"local t,n=t:match('%^HCSQ:%s?"[A-Z]+",%d+,(%d+),(%d+)')t=tonumber(t)if(t and t>0)then
e.rscp=((t*.5)-120)end
n=tonumber(n)if(n and n>0)then
e.ecio=((n*.5)-32)end
end
elseif i~="blacklisted"then
n(d.command_blacklist,'AT%^HCSQ%?')end
t=d:send_singleline_command('AT^SYSINFOEX',"^SYSINFOEX:")if t then
e.radio_bearer_type=t:match('%^SYSINFOEX:%s?%d*,%d*,%d*,%d*,%d*,%d*,".-",%d+,"(.-)"')if e.radio_bearer_type=="NO SERVICE"or e.radio_bearer_type=="LTE"then
e.radio_bearer_type=nil
end
end
end
function t:get_pin_info(e,n)local e=e:send_singleline_command('AT^CPIN?',"^CPIN:")if e then
n.unblock_retries_left,n.unlock_retries_left=e:match('%^CPIN:.-,%d*,(%d+),(%d+),%d+,%d+')end
end
function t:get_ip_info(n,e,t)local n=n:send_singleline_command(string.format('AT^DHCPV6=%d',(t+1)),"^DHCPV6:")if n then
local n,t=n:match("%^DHCPV6:%s*.-,.-,.-,.-,(.-),(.-),")if n~="::"then e.ipv6_dns1=n end
if t~="::"then e.ipv6_dns2=t end
end
end
local function i(e)if not e then
return
end
local n,t=e:match('%^NDISSTATQRY:%s?(%d),,,"IPV4",(%d),,,"IPV6"')if not n then
n=e:match('%^NDISSTATQRY:%s?(%d),,,"IPV4"')if not n then
n=e:match('%^NDISSTATQRY:%s?%d,(%d),,,"IPV4"')end
end
if not t then
t=e:match('%^NDISSTATQRY:%s?(%d),,,"IPV6"')if not t then
t=e:match('%^NDISSTATQRY:%s?%d,(%d),,,"IPV6"')end
end
return n,t
end
function t:get_session_info(e,n,t)local t=t+1
if e.sessions[t]and e.sessions[t].proto=="ppp"then
return true
end
n.packet_counters=e.buffer.session_info.packet_counters
n.duration=e.buffer.session_info.duration
local r=e:send_singleline_command(string.format('AT^NDISSTATQRY=%d',t),"^NDISSTATQRY:",2000)local d,t=i(r)if d=="1"or t=="1"then
n.session_state="connected"else
r=e:send_multiline_command('AT^NDISSTATQRY?',"^NDISSTATQRY:",2000)if r then
for r,e in pairs(r)do
d,t=i(e)if d=="1"or t=="1"then
n.session_state="connected"end
end
end
end
if d=="1"then
n.ipv4=true
end
if t=="1"then
n.ipv6=true
end
end
function t:get_device_capabilities(i,r)local e={}if i.buffer.device_info.model then
r.max_data_sessions=a.max_data_sessions[i.buffer.device_info.model]or 1
local e=a.voice_support[i.buffer.device_info.model]if e then
if e.cs_voice_support~=nil then
r.cs_voice_support=e.cs_voice_support
end
if e.volte_support~=nil then
r.volte_support=e.volte_support
end
end
end
local d=i:send_singleline_command('AT^SYSCFGEX=?',"^SYSCFGEX:")if d then
local r=0
for d in d:gmatch('%(([A-Z0-9a-z ",/_]-)%)')do
if r==0 then
for t in d:gmatch('([^,]+)')do
local t=t:match('"(%d+)"')if t=="00"then
n(e,{radio_interface="auto"})elseif t=="01"then
n(e,{radio_interface="gsm"})elseif t=="02"then
n(e,{radio_interface="umts"})elseif t=="03"then
n(e,{radio_interface="lte"})elseif t=="04"or t=="05"or t=="07"then
n(e,{radio_interface="cdma"})end
end
elseif(o(e,"gsm")and r==4)or(not o(e,"gsm")and r==3)then
local t={}for e in d:gmatch('LTE BC(%d+)')do
n(t,e)end
for e in d:gmatch('LTE_B(%d+)')do
n(t,e)end
for e in d:gmatch('LTE(%d+)')do
n(t,e)end
for n,e in pairs(e)do
if e.radio_interface=="lte"then
e.supported_bands=t
end
end
end
r=r+1
end
else
d=i:send_singleline_command('AT^SYSCFG=?',"^SYSCFG:")if d then
local t=d:match('%(([A-Z0-9a-z ",/_]-)%)')for t in t:gmatch('([^,]+)')do
local t=t:match('(%d+)')if t=="2"then
n(e,{radio_interface="auto"})elseif t=="13"then
n(e,{radio_interface="gsm"})elseif t=="14"then
n(e,{radio_interface="umts"})end
end
end
end
if o(e,"lte")then
r.band_selection_support="lte"end
r.radio_interfaces=e
r.supported_auth_types="none pap chap"end
function t:get_time_info(n,e)local n=n:send_singleline_command('AT^NWTIME?',"^NWTIME:")if n then
e.localtime,e.timezone,e.daylight_saving_time=l(n)end
end
function t:get_network_info(n,e)r.merge_tables(e,n.buffer.network_info)local n=n:send_singleline_command('AT^SYSINFOEX',"^SYSINFOEX:")if n then
local n,t,r=n:match("%^SYSINFOEX:%s?(%d),(%d),(%d)")if t=="1"or t=="3"then
e.cs_state="attached"end
if t=="2"or t=="3"then
e.ps_state="attached"end
if r=="0"then
e.roaming_state="home"else
e.roaming_state="roaming"end
if n=="0"then
e.service_state="no_service"elseif n=="1"then
e.service_state="limited_service"elseif n=="2"then
e.service_state="normal_service"elseif n=="3"then
e.service_state="limited_regional_service"elseif n=="4"then
e.service_state="sleeping"end
end
end
local function o(e)if e.buffer.device_info.model then
local t=a.voice_support[e.buffer.device_info.model]if t then
local e=e:send_singleline_command('AT^DDSETEX=?',"^DDSETEX:")if e then
e=e:match('%^DDSETEX:%s?%((.-)%)$')if e then
local t={}for e in e:gmatch('([^,]+)')do
n(t,tonumber(e))end
return t
end
end
end
end
return nil
end
function t:get_device_info(e,i)local t,r=e:send_singleline_command('AT+XTAMR=0',"+XTAMR:")if t then
local e=tonumber(t:match('+XTAMR:%s?%d+,(%d+)'))if e then
i.temperature=e/1000
end
elseif r~="blacklisted"then
n(e.command_blacklist,'AT%+XTAMR=0')end
if not i.temperature then
t,r=e:send_singleline_command('AT^CHIPTEMP?',"^CHIPTEMP:")if t then
local e=tonumber(t:match('%^CHIPTEMP:%s?([%d-]+)'))if e then
i.temperature=e/10
end
elseif r~="blacklisted"then
n(e.command_blacklist,'AT%^CHIPTEMP')end
end
if not e.buffer.device_info.hardware_version then
t=e:send_singleline_command('AT^HWVER',"^HWVER:")if t then e.buffer.device_info.hardware_version=t:match('%^HWVER:%s?"(.-)"')end
end
if not e.buffer.device_info.imei_svn then
t,r=e:send_singleline_command('AT^IMEISV?',"^IMEISV:")if t then
e.buffer.device_info.imei_svn=t:match('%^IMEISV:%s?(.-)$')elseif r~="blacklisted"then
n(e.command_blacklist,'AT%^IMEISV')end
end
if not e.buffer.device_info.voice_interfaces then
local i={[2]={name="diag",protocol=3,number=1}}local t=o(e)if t then
local r={}for a,t in pairs(t)do
local i=i[t]if i then
local t=d.find_tty_interfaces(e.desc,{protocol=i.protocol})if type(t)=="table"and#t>=1 then
n(r,{type="serial",device=t[1]})else
t=d.find_tty_interfaces(e.desc,{number=i.number})if type(t)=="table"and#t>=1 then
n(r,{type="serial",device=t[1]})end
end
end
end
if#r>=1 then
e.buffer.device_info.voice_interfaces=r
end
end
end
end
function t:configure_device(d,t)local e=""local i
for t,n in ipairs(t.network.radio_pref)do
if n.type=="auto"then
e="00"break
elseif n.type=="lte"then
i=r.get_lte_band_mask(n.bands)e=e.."03"elseif n.type=="umts"then
e=e.."02"elseif n.type=="gsm"then
e=e.."01"end
end
local n=1
if t.network.roaming=="none"then
n=0
end
local r
if i then
r=d:send_command(string.format('AT^SYSCFGEX="%s",3fffffff,%d,4,%x,,',e,n,i),500,2)else
r=d:send_command(string.format('AT^SYSCFGEX="%s",3fffffff,%d,4,7fffffffffffffff,,',e,n),500,2)end
if not r then
local r
if#t.network.radio_pref==1 then
local n=t.network.radio_pref[1]e=2
if n.type=="gsm"then
e=13
elseif n.type=="umts"then
e=14
end
else
e=2
if t.network.radio_pref[1].type=="gsm"then
r=1
else
r=2
end
end
d:send_command('AT+CGATT=0',150000)d:send_command(string.format('AT^SYSCFG=%d,%d,3FFFFFFF,%d,4',e,r or 0,n),500,2)end
return true
end
local a={[0]={call_state="dialing",media_state="normal"},[2]={call_state="delivered",media_state="normal"},[3]={call_state="connected",media_state="normal"},[4]={call_state="disconnected",media_state="no_media"},[5]={call_state="alerting",media_state="no_media"},[6]={call_state="alerting",media_state="no_media"},[7]={call_state="connected",media_state="held"},[8]={call_state="connected",media_state="normal"}}local function i(e)if e==16 or e==31 then
return"normal"elseif e==18 or e==19 then
return"no_answer"elseif e==17 then
return"busy"elseif e==21 then
return"call_rejected"elseif e==8 or e==55 then
return"barred_call"elseif
e==3 or
e==27 or
e==34 or
e==38 or
e==42 or
e==44 or
e==47 or
e==49 or
e==58 or
e==63 or
e==70 then
return"resources_unavailable"end
return"other"end
function t:unsolicited(e,n,t)if r.startswith(n,"^HCSQ:")then
return true
elseif r.startswith(n,"^MODE:")then
return true
elseif r.startswith(n,"^ECCLIST:")then
return true
elseif r.startswith(n,"^PDPSTATUS:")then
local n=n:match("%^PDPSTATUS:%s?(%d+)")if n=="0"then
e.runtime.log:debug("PDP context deactivated by the network")elseif n=="1"then
e.runtime.log:debug("PS domain deactivated by the network")elseif n=="2"then
e.runtime.log:debug("PDP context deactivated by the module")end
return true
elseif r.startswith(n,"^SRVST:")then
local t=n:match("%^SRVST:%s?(%d+)")local n="No services"if t=="1"then
n="Restricted services"elseif t=="2"then
n="Valid services"elseif t=="3"then
n="Restricted regional services"elseif t=="4"then
n="Power saving or hibernate state"end
e.runtime.log:debug("Service state changed to "..n)return true
elseif r.startswith(n,"^NWTIME:")then
local t={event="time_update_received",dev_idx=e.dev_idx}t.localtime,t.timezone,t.daylight_saving_time=l(n)e:send_event("mobiled",t)return true
elseif r.startswith(n,"^EONS:")then
return true
elseif r.startswith(n,"^STIN:")then
return true
elseif r.startswith(n,"^RSSI:")then
return true
elseif r.startswith(n,"^DSFLOWRPT:")then
c(e,n)return true
elseif r.startswith(n,"^FOTASTATE:")then
s(e,n,true)return true
elseif r.startswith(n,"^NDISSTAT:")or r.startswith(n,"^NDISSTATEX:")then
m(e,n)return true
elseif r.startswith(n,"^NWNAME:")then
h(e,n)return true
elseif r.startswith(n,"^LTERSRP:")then
p(e,n)return true
elseif r.startswith(n,"^SIMST:")then
if e.state.powermode=="lowpower"then
e:send_command('AT+CFUN=0')end
local n=n:match("%^SIMST:%s?(%d+)")if n=="1"then
e.buffer.sim_info={}e:send_event("mobiled",{event="sim_initialized",dev_idx=e.dev_idx})elseif n=="255"then
e.buffer.sim_info={}e:send_event("mobiled",{event="sim_removed",dev_idx=e.dev_idx})else
e.buffer.sim_info={}e:send_event("mobiled",{event="sim_error",dev_idx=e.dev_idx})end
return true
elseif r.startswith(n,"^ORIG:")then
return true
elseif r.startswith(n,"^CONF:")then
return true
elseif r.startswith(n,"^CONN:")then
e:send_command("AT^DDSETEX=2")return true
elseif r.startswith(n,"^CEND:")then
local n,r,t=n:match("%^CEND:%s?(%d+),(%d+),%d+,(%d+)")n=tonumber(n)t=tonumber(t)local t=i(t)if n and e.calls[n]then
e.calls[n].duration=r
e.calls[n].release_reason=t
end
return true
elseif r.startswith(n,"^CCALLSTATE:")then
local n,t=n:match("%^CCALLSTATE:%s?(%d+),(%d+)")n=tonumber(n)t=tonumber(t)if not e.calls[n]then
e.calls[n]={}end
local r=a[t]if r then
local i=false
if e.calls[n].call_state~=r.call_state then
i=true
end
e.calls[n].call_state=r.call_state
e.calls[n].media_state=r.media_state
if e.calls[n].call_state=="alerting"then
e.calls[n].mmpbx_call_id=e.mmpbx_call_id_counter
e.mmpbx_call_id_counter=e.mmpbx_call_id_counter+1
e.calls[n].direction="incoming"end
local d,r
if t==5 and e.clip then
d=e.clip.remote_party
r=e.clip.number_format
e.clip=nil
end
if i then
e:send_event("mobiled.voice",{event="call_state_changed",call_id=e.calls[n].mmpbx_call_id,dev_idx=e.dev_idx,call_state=e.calls[n].call_state,reason=e.calls[n].release_reason,remote_party=d,number_format=r})end
if t==4 then
e.calls[n]=nil
end
end
return true
elseif r.startswith(n,"+CLIP:")then
local n,t=n:match('%+CLIP:%s?"([%d+]+)",(%d+)')if n then
e.clip={remote_party=n,number_format=u.clcc_number_type[t]}end
return true
end
return nil
end
function t:debug(t)local e=t:send_singleline_command('AT^SYSCFGEX?','^SYSCFGEX:')if e then n(t.debug.device_state,e)end
e=t:send_singleline_command('AT^SYSCFG?','^SYSCFG:')if e then n(t.debug.device_state,e)end
e=t:send_singleline_command('AT^SYSCFG=?','^SYSCFG:')if e then n(t.debug.device_state,e)end
e=t:send_singleline_command('AT+CFUN?','+CFUN:')if e then n(t.debug.device_state,e)end
e=t:send_singleline_command('AT^SYSCFGEX=?','^SYSCFGEX:')if e then n(t.debug.device_state,e)end
e=t:send_singleline_command('AT^DIALMODE?','^DIALMODE:')if e then n(t.debug.device_state,e)end
e=t:send_singleline_command('AT^SYSINFO','^SYSINFO:')if e then n(t.debug.device_state,e)end
e=t:send_singleline_command('AT^SYSINFOEX','^SYSINFOEX:')if e then n(t.debug.device_state,e)end
e=t:send_singleline_command('AT^DHCP?','^DHCP:')if e then n(t.debug.device_state,e)end
e=t:send_singleline_command('AT^CPULOAD?','^CPULOAD:')if e then n(t.debug.device_state,e)end
e=t:send_singleline_command('AT^FOTACFG?','^FOTACFG:')if e then n(t.debug.device_state,e)end
e=t:send_singleline_command('AT^FOTASTATE?','^FOTASTATE:')if e then n(t.debug.device_state,e)end
e=t:send_singleline_command('AT^FOTAMODE?','^FOTAMODE:')if e then n(t.debug.device_state,e)end
e=t:send_multiline_command('AT^NDISSTATQRY?','^NDISSTATQRY:')if e then
for r,e in pairs(e)do
n(t.debug.device_state,e)end
end
return true
end
function t:init_device(n)if not n.state.initialized then
n:send_command("AT^CURC=1")n:send_command("AT^SIMST=1")n:send_command("AT+COLP=1")n:send_command("AT+CLIP=1")n:send_command("AT+CHUP")n.buffer.firmware_upgrade_info={status="not_running"}local t=e.get_state()if t then
n.buffer.firmware_upgrade_info=t
end
e.reset_state()end
return true
end
function t:destroy_device(e)e:send_command("AT^CURC=0")return true
end
function t:firmware_upgrade(t,d)if not d then
t.buffer.firmware_upgrade_info.status="invalid_parameters"return nil,"Invalid parameters"end
local r={}for e in d:gmatch('([^,]+)')do
n(r,e)end
local n=r[1]local d=r[2]local r=r[3]if not n then
t.buffer.firmware_upgrade_info.status="invalid_parameters"return nil,"Invalid parameters"end
t:send_command("AT^FOTADL=0")t.buffer.firmware_upgrade_info={status="started"}e.reset_state()t:send_command('AT^NDISDUP=1,0',5000)t:send_command(string.format('AT^FOTACFG="%s",%s,%s,0',n,d or"",r or""))t:send_command("AT^FOTAMODE=0,1,1,1")t:send_command("AT^FOTADET")return true
end
function t:get_firmware_upgrade_info(e)if e.buffer.firmware_upgrade_info.status~="invalid_parameters"then
local n=e:send_singleline_command('AT^FOTASTATE?','^FOTASTATE:')if n then s(e,n,false)end
end
return e.buffer.firmware_upgrade_info
end
function t:network_scan(e,n)if n then
r.sleep(5)e:send_command("AT+CFUN=0")r.sleep(2)e:send_command("AT+CFUN=1")end
return true
end
function t:end_call(e,n)return e:send_command("AT+CHUP")end
function t:call_info(n,e)e=tonumber(e)if e and n.calls[e]then
local t=n:send_singleline_command(string.format("AT^CDUR=%d",e),"^CDUR:")if t then
n.calls[e].duration=t:match("%^CDUR:%s?%d+,(%d+)")end
else
for t,e in pairs(n.calls)do
if e.call_id then
local n=n:send_singleline_command(string.format("AT^CDUR=%d",e.call_id),"^CDUR:")if n then
e.duration=n:match("%^CDUR:%s?%d+,(%d+)")end
end
end
end
if e then
return n.calls[e]or{}end
return n.calls or{}end
function t:multi_call(e,e,e,e)return nil,"Unsupported multi_call action"end
function t:supplementary_service(e,r,t,d,n,n)local n
if r=="call_waiting"then
if t=="activate"then
e:send_command("AT+CCWA=1,1,1")return true
elseif t=="deactivate"then
e:send_command("AT+CCWA=1,0,1")return true
elseif t=="query"then
n=e:send_singleline_command("AT+CCWA=1,2,1","+CCWA:",60000)if n then
local e=n:match("+CCWA:%s?(%d)")if e=="1"then
return{status="activated"}end
end
return{status="deactivated"}end
return nil,"Invalid action"elseif r=="clip"then
if t=="activate"then
e:send_command("AT+CLIP=1")return true
elseif t=="deactivate"then
e:send_command("AT+CLIP=0")return true
elseif t=="query"then
n=e:send_singleline_command("AT+CLIP?","+CLIP:",60000)local e={status="unknown",enabled=false}if n then
local t,n=n:match("+CLIP:%s?(%d),(%d)")if t=="1"then
e.enabled=true
end
if n=="0"then
e.status="unavailable"elseif n=="1"then
e.status="available"end
end
return e
end
return nil,"Invalid action"elseif r=="clir"then
if t=="activate"then
e:send_command("AT+CLIR=1")return true
elseif t=="deactivate"then
e:send_command("AT+CLIR=0")return true
elseif t=="query"then
n=e:send_singleline_command("AT+CLIR?","+CLIR:",60000)local e={status="unknown",enabled=false}if n then
local t,n=n:match("+CLIR:%s?(%d),(%d)")if t=="1"then
e.enabled=true
end
if n=="0"then
e.status="unavailable"elseif n=="1"then
e.status="available"elseif n=="3"then
e.status="temporarily_unavailable"elseif n=="4"then
e.status="temporarily_available"end
end
return e
end
return nil,"Invalid action"elseif r=="colp"then
if t=="activate"then
e:send_command("AT+COLP=1")return true
elseif t=="deactivate"then
e:send_command("AT+COLP=0")return true
elseif t=="query"then
n=e:send_singleline_command("AT+COLP?","+COLP:",60000)local e={status="unknown",enabled=false}if n then
local t,n=n:match("+COLP:%s?(%d),(%d)")if t=="1"then
e.enabled=true
end
if n=="0"then
e.status="unavailable"elseif n=="1"then
e.status="available"end
end
return e
end
return nil,"Invalid action"elseif r=="call_forwarding"then
local r={["unconditional"]=0,["busy"]=1,["no_reply"]=2,["unreachable"]=3,["all_types"]=4,["all_conditional_types"]=5}if t=="activate"then
local n="129"if d.forwarding_number_type=="international"then
n="145"end
e:send_command(string.format('AT+CCFC=%d,1,"%s",%d',r[d.forwarding_type],d.forwarding_number,n))return true
elseif t=="deactivate"then
e:send_command("AT+CCFC=0")return true
elseif t=="query"then
n=e:send_singleline_command(string.format("AT+CCFC=%d,2",r[d.forwarding_type]),"+CCFC:",60000)local e={enabled=false}if n then
local n=n:match('+CCFC:%s?(%d)')if n=="1"then
e.enabled=true
end
end
return e
end
return nil,"Invalid action"end
return nil,"Invalid service"end
function t:get_network_interface(e,n)if e.product=="K4305"then
if e.network_interfaces and n==1 then
return e.network_interfaces[1]end
end
end
function t:set_power_mode(e,n)if n=="lowpower"or n=="airplane"then
e.buffer.session_info={}e.buffer.network_info={}e.buffer.radio_signal_info={}else
e:send_command('AT^RFSWITCH=1',5000)end
return true
end
function f.create(r,e)local a={mappings={set_attach_params="override",get_network_interface="override",configure_device="runfirst",get_session_info="override",start_data_session="override",stop_data_session="override",firmware_upgrade="override",get_firmware_upgrade_info="override",network_scan="runfirst",supplementary_service="override",multi_call="override",dial="override",end_call="override",destroy_device="runfirst"}}local i=d.find_tty_interfaces(e.desc,{class=255,subclass=1,protocol=1})i=i or d.find_tty_interfaces(e.desc,{class=255,subclass=2,protocol=1})i=i or d.find_tty_interfaces(e.desc,{class=255,subclass=2,protocol=49})i=i or d.find_tty_interfaces(e.desc,{class=255,subclass=2,protocol=16})i=i or d.find_tty_interfaces(e.desc,{class=255,subclass=6,protocol=16})i=i or d.find_tty_interfaces(e.desc,{class=2,subclass=2,protocol=255,number=0})local r=d.find_tty_interfaces(e.desc,{class=255,subclass=1,protocol=22})r=r or d.find_tty_interfaces(e.desc,{class=2,subclass=6,protocol=0})r=r or d.find_tty_interfaces(e.desc,{class=2,subclass=13,protocol=0})r=r or d.find_tty_interfaces(e.desc,{class=255,subclass=1,protocol=2})r=r or d.find_tty_interfaces(e.desc,{class=255,subclass=2,protocol=2})r=r or d.find_tty_interfaces(e.desc,{class=255,subclass=2,protocol=50})r=r or d.find_tty_interfaces(e.desc,{class=255,subclass=2,protocol=18})r=r or d.find_tty_interfaces(e.desc,{class=255,subclass=6,protocol=18})r=r or d.find_tty_interfaces(e.desc,{class=255,subclass=3,protocol=2})i=i or d.find_tty_interfaces(e.desc,{class=255,subclass=255,protocol=255,number=0})r=r or d.find_tty_interfaces(e.desc,{class=255,subclass=255,protocol=255,number=4})r=r or d.find_tty_interfaces(e.desc,{class=255,subclass=255,protocol=255,number=3})r=r or d.find_tty_interfaces(e.desc,{class=255,subclass=255,protocol=255,number=2})r=r or d.find_tty_interfaces(e.desc,{class=255,subclass=255,protocol=255,number=1})if e.product=="K4305"then
r=d.find_tty_interfaces(e.desc,{class=2,subclass=2,protocol=255,number=2})elseif e.product=="K5150"then
r=d.find_tty_interfaces(e.desc,{class=255,subclass=2,protocol=18,number=2})end
e.default_interface_type="pcui"if i then
for r,t in pairs(i)do
n(e.interfaces,{port=t,type="modem"})end
end
if r then
for r,t in pairs(r)do
n(e.interfaces,{port=t,type="pcui"})end
end
if e.pid=="1001"or e.pid=="1003"or e.pid=="1c05"then
e.sessions[1]={proto="ppp"}end
if e.product=="K4305"then
e.sessions={{proto="ppp"},{proto="dhcp"}}end
setmetatable(a,t)return a
end
return f