应用程序开发
应用程序开发,应用程序开发包括时间同步,信号强度同步,socket通信(数据收发),设计器实现UI开发和手动写实现UI开发会略有不同,不同地方会做相应的说明。
# 时间同步
时间同步实现见service_time.lua脚本,这里创建了一个task,500m获取一次时间,然后通过sys.publish()发布SYSTEM_CHANGE_TIME消息,通知UI界面去更新时间。
```lua
-- --bTimeSyned :时间是否已经成功同步过
local bTimeSyned=false
--注册基站时间同步的URC消息处理函数
ril.regUrc("+NITZ", function()
log.info("cell.timeSync")
bTimeSyned = true
end)
local weekTable={"日","一","二","三","四","五","六"}
sys.taskInit(function()
while not bTimeSyned do
sys.wait(50)
end
while true do
local tClock = os.date("*t")
local date=string.format("%d/%02d/%02d 周%s %02d:%02d:%02d",tClock.year,tClock.month,tClock.day,weekTable[tClock.wday],tClock.hour,tClock.min,tClock.sec)
-- print(date)
sys.publish("SYSTEM_CHANGE_TIME",date)
sys.wait(500)
end
end)
```
更新时间的处理,设计器实现UI开发是放在UiHandle.lua脚本中实现,手动写实现UI开发是放在main.lua脚本中实现,通过sys.subscribe()订阅SYSTEM_CHANGE_TIME消息,通过lvgl.label_set_text()来设置时间对应的lable内容来更新时间。
设计器实现UI开发UiHandle.lua脚本中对应代码如下:
```lua
sys.subscribe("SYSTEM_CHANGE_TIME",function(date)
lvgl.label_set_text(ScreenA.LvglLabel2.self, date)
end)
```
手动写实现UI开发main.lua脚本中对应代码如下:
```lua
sys.subscribe("SYSTEM_CHANGE_TIME",function(date)
lvgl.label_set_text(dateLabel,"#FFFFFF "..date)
end)
```
# 信号强度同步
时间同步实现见service_sim.lua脚本,这里创建了一个task,1000m获取一次信号强度,如果信号有变化然后通过sys.publish()发布RSSI_CHANGE消息,通知UI界面去更新信号强度。信号有变化的情况下也会做对应的操作。这里消息上报的内容是信号对应的图片路径。
```lua
function RSSIchange()
local Rssi=0
sys.taskInit(function()
while true do
local s=net.getRssi()
if s~=Rssi then
Rssi=s
sys.publish("RSSI_CHANGE","/lua/sin_icon_"..math.ceil((5/31)*Rssi)..".png")
end
sys.wait(1000)
end
end)
end
sys.subscribe("NET_STATE_REGISTERED",RSSIchange)
```
更新信号强度的处理,设计器实现UI开发是放在UiHandle.lua脚本中实现,手动写实现UI开发是放在main.lua脚本中实现,通过sys.subscribe()订阅RSSI_CHANGE消息,通过lvgl.img_set_src()来设置信号强度对应的img图片来更新信号强度。
设计器实现UI开发UiHandle.lua脚本中对应代码如下:
```lua
sys.subscribe("RSSI_CHANGE",function(img)
lvgl.img_set_src(ScreenA.LvglImg6.self,img)
end)
```
手动写实现UI开发main.lua脚本中对应代码如下:
```lua
sys.subscribe("RSSI_CHANGE",function(img)
lvgl.img_set_src(signImg,img)
```
# socket通信
socket通信,主要功能是实现数据的收发,代码在longConnection文件夹下面,包含有3个脚本文件,分别处理socket连接,数据接收,数据发送。
## socket连接
socketTask.lua创建socket客户端任务,这里通过sys.waitUntil("CONNECT_IND")一直等待CONNECT_IND消息,CONNECT_IND消息是点击连接按钮后发布的,等到CONNECT_IND后,等待网络就绪后,会创建并连接服务器,连接成功后,循环处理接收和发送的数据。
```lua
sys.taskInit(
function()
while true do
sys.waitUntil("CONNECT_IND")
disconnect = nil
log.info("UI @@ CONNECT_IND",_G.ipProtocol,_G.ipAddress,_G.ipPort)
if not socket.isReady() then
--等待网络环境准备就绪,超时时间是5分钟
sys.waitUntil("IP_READY_IND",300000)
end
if socket.isReady() then
--创建一个socket tcp/udp客户端
local socketClient
if _G.ipProtocol == "udp" then
socketClient = socket.udp()
else
socketClient = socket.tcp()
end
--阻塞执行socket connect动作,直至成功
if socketClient:connect(_G.ipAddress,_G.ipPort) then
ready = true
socketOutMsg.init()
--循环处理接收和发送的数据
while true do
if not socketInMsg.proc(socketClient) then log.error("socketTask.socketInMsg.proc error") break end
if not socketOutMsg.proc(socketClient) then log.error("socketTask.socketOutMsg proc error") break end
end
socketOutMsg.unInit()
ready = false
else
log.error("socketTask connect fail")
end
--断开socket连接
socketClient:close()
sys.wait(5000)
else
--进入飞行模式,20秒之后,退出飞行模式
net.switchFly(true)
sys.wait(20000)
net.switchFly(false)
end
end
end
)
```
设计器实现UI开发发布CONNECT_IND在UiHandle.lua脚本中实现,连接按钮的消息回调函数,对应代码如下:
```lua
function Connect_CLICKED()
------------USER CODE DATA--------------
_G.BEEP()
log.info("Connect_CLICKED",_G.fragmentConnect)
if _G.fragmentConnect then
lvgl.style_set_value_str(Style_LvglButton3_1, lvgl.STATE_DEFAULT, "断开连接")
_G.fragmentConnect = false
sys.publish("CONNECT_IND")
else
lvgl.style_set_value_str(Style_LvglButton3_1, lvgl.STATE_DEFAULT, "连接")
_G.fragmentConnect=true
sys.publish("SOCKET_DISCONNECT_IND")
socketOutMsg.sndTest("disconnect")
end
------------USER CODE DATA--------------
end
```
按键消息回调的注册是在UI设计器设计的时候,通过添加按钮点击事件函数名称,自动生成后放在UiDesign.lua脚本中的。
```lua
--This is callBack function of ScreenA.LvglButton3
local handleLvglButton3 = function(obj, e)
ScreenA.LvglButton3.cb(e)
ScreenA.LvglButton3.cb = function(e)
if (e == lvgl.EVENT_CLICKED)then
Connect_CLICKED()
end
end
end
lvgl.obj_set_event_cb(ScreenA.LvglButton3.self, handleLvglButton3)
```
手动写实现UI开发发布CONNECT_IND在fragment_systemSet.lua脚本中实现,连接按钮的消息回调函数,对应代码如下:
```lua
event_handler_btn = function(obj, event)
if event == lvgl.EVENT_CLICKED then
_G.BEEP()
log.info("UI makeQRbtn",_G.fragmentConnect)
if _G.fragmentConnect then
lvgl.label_set_text(_G.connLabel, "#FFFFFF 断开连接")
_G.fragmentConnect = false
sys.publish("CONNECT_IND")
else
lvgl.label_set_text(_G.connLabel, "#FFFFFF 连接")
_G.fragmentConnect=true
sys.publish("SOCKET_DISCONNECT_IND")
socketOutMsg.sndTest("disconnect")
end
end
end
lvgl.obj_set_event_cb(btn, event_handler_btn)
```
## 数据接收
在socketInMsg.lua脚本里,处理数据的接收。数据接收时通过socketClient:recv()来接收数据,接收到的数据通过sys.publish("RECV_DATA_IND")发布消息给UI去更新接收的数据。
```lua
function proc(socketClient)
local result,data
while true do
result,data = socketClient:recv(60000,"APP_SOCKET_SEND_DATA")
--接收到数据
if result then
log.info("socketInMsg.proc",data)
_G.recvData = data
sys.publish("RECV_DATA_IND")
else
break
end
end
return result or data=="timeout" or data=="APP_SOCKET_SEND_DATA"
end
```
接收数据的更新,设计器实现UI开发是放在UiHandle.lua脚本中实现,手动写实现UI开发是放在fragment_systemSocket.lua脚本中实现,通过sys.subscribe()订阅RECV_DATA_IND消息,通过lvgl.label_set_text()来设置时间对应的lable内容来更新接收到的数据和数据长度。
设计器实现UI开发UiHandle.lua脚本中对应代码如下:
```lua
--接收到数据
function recvDataInd()
--if RecvLabel then lvgl.label_set_text(RecvLabel, _G.recvData) end
--if RecvLabel then lvgl.label_set_text(RecvLenLabel, "已接收"..#_G.recvData.."个字节")end
log.info("recvDataInd",_G.recvData,#_G.recvData)
lvgl.label_set_text(ScreenA.LvglLabel10.self, _G.recvData)
lvgl.label_set_text(ScreenA.LvglLabel9.self, "已接收"..#_G.recvData.."个字节")
end
sys.subscribe("RECV_DATA_IND",recvDataInd)
```
手动写实现UI开发fragment_systemSocket.lua脚本中对应代码如下:
```lua
function recvDataInd()
if RecvLabel then lvgl.label_set_text(RecvLabel, _G.recvData) end
if RecvLabel then lvgl.label_set_text(RecvLenLabel, "#FFFFFE 已接收"..#_G.recvData.."个字节")end
end
sys.subscribe("RECV_DATA_IND",recvDataInd)
```
## 数据发送
在socketOutMsg.lua脚本里,处理数据的发送。数据发送是先把发送的数据放到msgQueue消息队列,发送的时候从消息队列中取出后在通过调用socketClient:send()去发送。
```lua
--发送数据放到消息队列
local function insertMsg(data,user)
table.insert(msgQueue,{data=data,user=user})
sys.publish("APP_SOCKET_SEND_DATA")
end
--数据发送处理
function proc(socketClient)
while #msgQueue>0 do
local outMsg = table.remove(msgQueue,1)
local result = socketClient:send(outMsg.data)
if outMsg.user and outMsg.user.cb then outMsg.user.cb(result,outMsg.user.para) end
if disconnect and outMsg.data == "disconnect\r\n" then log.info("@@ outMsg proc disconnect") return end
if not result then return end
end
return true
end
```
# 相关参考文档
[SOCKET(套接字)](https://easydoc.net/doc/50207163/vRKgmDaY/TCjrYW25)
[sys API](https://doc.openluat.com/wiki/21?wiki_page_id=2295)