(1) 畫面配置
(2) LUA編輯
5.3.1 準(zhǔn)備工程素材
在畫面ID0中,信號(hào)運(yùn)營(yíng)商、APP QR Code、APP交互變量組成。
信號(hào)運(yùn)營(yíng)商:圖標(biāo)件ID12表示信號(hào)等級(jí)、文本控件ID13表示運(yùn)營(yíng)商
APP QR Code:二維碼控件,使用手機(jī)云智能APP(阿里云公辦APP)掃碼,由于是一型一密,用戶掃碼需要開發(fā)者分享授權(quán)。
APP 交互的變量:控件ID1~ID10用于顯示、設(shè)置開/關(guān)機(jī)、濾網(wǎng)時(shí)間、溫度、設(shè)備模式等。畫面配置如圖5-3所示:
注意:其他非關(guān)鍵控件不在一一介紹,下文不在累述
圖5-3 畫面配置
5.3.2 LUA編輯
本例程中,屏幕上電執(zhí)行初始化操作,如加載4G AT 指令的庫(kù)、初始化和4G模塊的交互的函數(shù)、初始化4G模塊、開啟定時(shí)器獲取運(yùn)營(yíng)商和信號(hào)值。
4G模塊初始化完成后,提交阿里云認(rèn)證,并設(shè)置mqtt相關(guān)參數(shù)、服務(wù)IP和端口等等,屏幕發(fā)出請(qǐng)求會(huì)話通知。一切就緒后,屏幕和云端可以進(jìn)行數(shù)據(jù)交互。
1. 初始化
調(diào)用系統(tǒng)函數(shù)on_init()執(zhí)行代碼如程序清單 1所示:
程序清單 1初始化
--[[*********************************************************************
** Function name: on_init
** Descriptions : 系統(tǒng)初始化時(shí),執(zhí)行此回調(diào)函數(shù)。
*********************************************************************--]]
function on_init()
dofile('air724at.lua') --加載 http.lua 文件
uart_set_baudrate3(115200) --設(shè)置與4G模塊通訊的串口3的波特率為115200
--設(shè)置4G庫(kù)函數(shù)的命令發(fā)送函數(shù),命令回調(diào)函數(shù)、調(diào)試信息打印函數(shù)
air_set_callback(on_air_send_cb,on_air_resp_callback,on_air_log_cb)
air_hw_int() --4G模塊初始化設(shè)置
air_get_iccid() –- 獲取卡號(hào)
--開啟自動(dòng)獲取型號(hào)強(qiáng)度
start_timer(timerId_Sig_Weather, 1000 , 0, 0)
end
--[[*********************************************************************
** Function name: on_timer
** Descriptions : 定時(shí)器超時(shí)回到調(diào)函數(shù)。
** @ timer_id : 定時(shí)器ID
*********************************************************************--]]
function on_timer(timer_id)
on_air_timer(timer_id) --4G庫(kù)函數(shù)的定時(shí)處理
--自動(dòng)獲取型號(hào)強(qiáng)度
if timer_id == timerId_Sig_Weather
then
--定時(shí)器計(jì)數(shù),timer0_notify_cnt 每秒+1。計(jì)時(shí)長(zhǎng)度30min
timer0_notify_cnt = timer0_notify_cnt + 1
if timer0_notify_cnt%15 == 0
then
--每15s調(diào)用一次,更新信號(hào)值
at_cops_csq()
end
end
end
--[[*********************************************************************
** Function name : at_cops_csq
** Descriptions : 獲取運(yùn)營(yíng)商信息、信號(hào)強(qiáng)度
** @return : nil,無(wú)返回值
*********************************************************************--]]
function at_cops_csq()
air_cmd_add('AT+COPS?','OK',1000) –獲取運(yùn)營(yíng)商
air_cmd_add('AT+CSQ' ,'OK',1000) –獲取信號(hào)
end
--[[*********************************************************************
** Function name: on_air_resp_callback
** Descriptions : 4G模塊-數(shù)據(jù)回調(diào)接口
** @key : 屏幕->4G模塊的發(fā)送請(qǐng)求
** @value : 4G模塊->返回的數(shù)據(jù)
*********************************************************************--]]
function on_air_resp_callback(key, value)
if value == nil
then
return --value為空時(shí)退出
end
......
if key ~= nil
then
return -- key為空時(shí)退出
end
......
--***************************************************************
--條件: 4G初始化完成
--功能: 使用使用AT指令獲取信號(hào)強(qiáng)度和運(yùn)營(yíng)商。
-- 使用 MQTT 提交三元組,阿里云認(rèn)證。
--調(diào)用函數(shù):at_cops_csq()
--函數(shù)功能:獲取信號(hào)強(qiáng)度和運(yùn)營(yíng)商
--調(diào)用函數(shù):aliyun_get_iot_token()
--函數(shù)功能:提交阿里云認(rèn)證
--********************************************************************
if string.find(key,'+SAPBR=1,1') ~= nil and string.find(value,'OK') ~= nil
then
at_cops_csq() --獲取信號(hào)強(qiáng)度
aliyun_get_iot_token() –提交阿里云認(rèn)證
end
......
end
--[[**********************************************************************
** Function name: on_uart_recv_data3
** Descriptions : 接收串口3數(shù)據(jù)回調(diào)函數(shù),連接4G模塊。
**********************************************************************--]]
function on_uart_recv_data3(packet)
--4G AT指令庫(kù)API
on_air_recv_data(packet)
end
1) dofile (filename)
加載文件:本例程中加載4G AT 指令的庫(kù)
2) uart_set_baudrate3(speed)
設(shè)置串口3的波特率:串口3為屏幕和4G模塊通訊的串口
3) on_air_recv_data(packet)
串口接收4G模塊的返回?cái)?shù)據(jù)的回調(diào)。
-
packet :形參為表,字節(jié)數(shù)據(jù)。
4) air_set_callback (on_air_send_cb,on_air_resp_callback,on_air_log_cb)
設(shè)置4G庫(kù)函數(shù)的回調(diào)。形參類型為函數(shù),參數(shù)依次為命令發(fā)送函數(shù),命令回調(diào)函數(shù)、調(diào)試信息打印函數(shù),可自定義函數(shù)名。
-
on_air_send_cb :屏幕向4G模塊發(fā)送回調(diào)函數(shù)
-
on_air_resp_callback :4G向屏幕返回?cái)?shù)據(jù)回調(diào)函數(shù)
-
on_air_log_cb :用戶調(diào)試信息回調(diào)函數(shù)調(diào)試
自定義封裝函數(shù),獲取運(yùn)行商和信號(hào)值6) air_cmd_add(sendstr,ackstr,timeout,retry,callback)
屏幕向4G模塊發(fā)送AT指令
-
sendstr :屏幕向4G模塊發(fā)送AT指令
-
ackstr :4G模塊應(yīng)答屏幕的請(qǐng)求
-
timeou :應(yīng)道超時(shí)時(shí)間
-
retry : 超時(shí)重發(fā)次數(shù),可選
-
callback : 應(yīng)答回調(diào)函數(shù),可選
注:如果沒有設(shè)置超時(shí)重發(fā)次數(shù),則超時(shí)時(shí)直接發(fā)送隊(duì)列中的下一條指令。7) on_air_resp_callback(key, value)
4G應(yīng)答屏幕回調(diào)函數(shù):屏幕發(fā)送AT指令,4G應(yīng)答后均會(huì)回調(diào)該函數(shù),本函數(shù)如air_set_callback(on_air_send_cb,on_air_resp_callback,on_air_log_cb)函數(shù)設(shè)置。
-
key :屏幕->4G模塊,發(fā)送請(qǐng)求的AT指令
-
value :4G模塊->屏幕,返回的數(shù)據(jù)
本例程中,初始化部分在on_air_resp_callback(key, value)回調(diào)函數(shù)中,需要判斷4G收發(fā)的相關(guān)AT指令,如下所示:
1) 獲取運(yùn)營(yíng)商:
屏幕發(fā)送:AT+COPS?
屏幕接收:OK
2) 獲取信號(hào)值A(chǔ)T:
屏幕發(fā)送:AT+CSQ
屏幕接收:OK
3) 網(wǎng)絡(luò)數(shù)據(jù)是否激活:
屏幕發(fā)送:AT+SAPBR=1,1
屏幕接收:OK
當(dāng)4G初始化完成后,提交阿里云認(rèn)證(三元組),代碼如程序清單 2所示:
程序清單 1初始化
--出廠工程測(cè)試使用的阿里云服務(wù)器的登錄id和三元組
local clientId = '862991419835242' --無(wú)限制
local productKey = 'a1D2E9vaSuZ' --三元組的 productKey
local deviceName = 'tuOVqg3nrVZnR2oMWwev' --三元組的 deviceName
local deviceSecret = '36c51acc5e3a7e410fe55831fd5e899d' --三元組的 deviceSecret
--[[**********************************************************************
** Function name: aliyun_get_iot_token
** Descriptions : 連接Aliyun
** return : nil,無(wú)返回值
**********************************************************************--]]
function aliyun_get_iot_token()
local msg = 'clientId'..clientId..
'deviceName'..deviceName..
'productKey'..productKey
local sign = md5_hmac(msg,deviceSecret) --計(jì)算哈希值
local http_data = 'productKey='..productKey..
'&sign='..sign..
'&clientId='..clientId..
'&deviceName='..deviceName
--提交Aliyun認(rèn)證
air_http_post(
'https://iot-auth.cn-shanghai.aliyuncs.com/auth/devicename',
'application/x-www-form-urlencoded',
http_data,
on_aliyun_get_iot_token_cb
)
--設(shè)置二維碼
qrstring =
'https://g.aliplus.com/ilop/static/download/ilopdownload.html?
locale=zh-CN&pk='..productKey..'&dn='..deviceName
set_text( screen_ac_control, 11, qrstring)
end
--[[*********************************************************************
** Function name: on_aliyun_get_iot_token_cb
** Descriptions : Aliyun認(rèn)證回調(diào)函數(shù)
** 成功時(shí)發(fā)送命令 AT+MCONFIG 和 AT+SSLMIPSTART
*********************************************************************--]]
function on_aliyun_get_iot_token_cb(key, value)
if key=='data' then
local jsondata = cjson.decode(table2str(value)) --json解碼
if jsondata ~= nil and jsondata['code'] == 200
then
iotId = jsondata['data']['iotId']
iotToken = jsondata['data']['iotToken']
mqtt_config(clientId,iotId,iotToken)
mqtt_tcp_start(
productKey .. '.iot-as-mqtt.cn-shanghai.aliyuncs.com',
1883,
True )
end
end
end
核心API函數(shù)
1) aliyun_get_iot_token()提交阿里云認(rèn)證(三元組)和設(shè)置二維碼。2) air_http_post (url,content_type,post_data,callback)
HTTP POST操作,例程中次數(shù)用于提交阿里云認(rèn)證(三元組)。
-
url:網(wǎng)頁(yè)URL
-
content_type:自定義,參數(shù)值
-
post_data:寫數(shù)據(jù)
-
callback:4G數(shù)據(jù)回調(diào)函數(shù)
3) on_aliyun_get_iot_token_cb(key, value)Aliyun認(rèn)證回調(diào)函數(shù),當(dāng)云端反饋正常認(rèn)證后,調(diào)用系統(tǒng)4G AT 指令的庫(kù)
的mqtt_config()設(shè)置MTQQ參數(shù)、mqtt_tcp_start()設(shè)置服務(wù)器IP和端口。
-
key:云端恢復(fù)的類型
-
Value:云端恢復(fù)的數(shù)據(jù)
當(dāng)云端認(rèn)證成功和設(shè)置mqtt相關(guān)參數(shù)后,調(diào)用mqtt_config() 、mqtt_tcp_start() 設(shè)置云端IP和端口,調(diào)用mqtt_connect() 與服務(wù)器建立會(huì)話連接 ,代碼如程序清單 3所示:
程序清單 3 設(shè)置云端IP和端口
--[[*********************************************************************
** Function name: on_aliyun_get_iot_token_cb
** Descriptions : Aliyun認(rèn)證回調(diào)函數(shù)
** 成功時(shí)發(fā)送命令 AT+MCONFIG 和 AT+SSLMIPSTART
*********************************************************************--]]
function on_aliyun_get_iot_token_cb(key, value)
......
mqtt_config(clientId,iotId,iotToken)
mqtt_tcp_start(productKey ..
'.iot-as-mqtt.cn-shanghai.aliyuncs.com', 1883, true)
......
end
--[[*********************************************************************
** Function name: on_air_resp_callback
** Descriptions : 4G模塊-數(shù)據(jù)回調(diào)接口
** @key : 屏幕->4G模塊的發(fā)送請(qǐng)求
** @value : 4G模塊->返回的數(shù)據(jù)
*********************************************************************--]]
function on_air_resp_callback(key, value)
my_print('on_air_resp_callback()')
......
--****************************************************************
--條件: 連接Aliyun,AT+SSLMIPSTART 成功
--功能: 發(fā)送AT+MCONNECT=...
--********************************************************************
if string.find(key, '+SSLMIPSTART') ~= nil and
string.find(value, 'CONNECT OK') ~= nil
then
my_print('mqtt_connect(1,600)')
mqtt_connect(1,600)
end
end
1) mqtt_config(clientid,username,password,will_qos,will_retain,will_topic,will_message)
設(shè)置 MQTT 相關(guān)參數(shù),本例程,只需要填寫客戶身份、登陸服務(wù)器的用戶名以及密碼,其中這三個(gè)參數(shù)是有阿里云認(rèn)證反饋回來(lái)的。
-
status:客戶身份
-
username:登錄服務(wù)器的用戶名
-
password:登錄服務(wù)器的密碼
-
will_qos:將要發(fā)送的信息的服務(wù)質(zhì)量
-
will_retain:保留標(biāo)志
-
will_topic:將要發(fā)送的消息的話題
-
will_message:將要發(fā)送的消息內(nèi)容
2) mqtt_tcp_start(srvaddr,port,ssl)
設(shè)置服務(wù)器的IP、端口
-
srvad:服務(wù)器 IP 地址或 DNS 地址
-
port:服務(wù)器端口
-
ssl:設(shè)置為 true 時(shí),使用SSL鏈接
客戶端向服務(wù)器請(qǐng)求會(huì)話連接
-
clean_session:會(huì)話狀態(tài)
-
keepalive :保持時(shí)間
當(dāng)屏幕向云端發(fā)送設(shè)置服務(wù)器IP、端口請(qǐng)求的時(shí)候,云端回應(yīng)數(shù)據(jù),觸發(fā)回調(diào)函數(shù)on_air_resp_callback(key, value),應(yīng)答‘CONNECT OK’后,發(fā)起請(qǐng)求連接mqtt_connect(1,600)當(dāng)客戶端向服務(wù)器請(qǐng)求會(huì)話連接成功后,客戶端對(duì)服務(wù)器訂閱主題,代碼如程序清單 4所示:
程序清單 4 發(fā)起連接請(qǐng)求
--[[*********************************************************************
** Function name: on_air_resp_callback
** Descriptions : 4G模塊-數(shù)據(jù)回調(diào)接口
** @key : 屏幕->4G模塊的發(fā)送請(qǐng)求
** @value : 4G模塊->返回的數(shù)據(jù)
*********************************************************************--]]
function on_air_resp_callback(key, value)
......
--********************************************************************
--條件: 接收 Aliyun 發(fā)布消息
--功能: 在 cloud_on_property_set(payload) 中對(duì)消息進(jìn)行處理。
--調(diào)用函數(shù):cloud_on_property_set(payload)
--*******************************************************************
if string.find(key, '+MCONNECT') ~= nil
and string.find(value,'CONNACK OK')~=nil
then
mqtt_sub(
'/sys/'..productKey..'/'..deviceName..'/thing/service/property/set',
0 )
mqtt_sub_bit = 'sub_OK'
end
end
本命令從客戶端到服務(wù)器,用于一個(gè)或多個(gè)訂閱主題,當(dāng)向服務(wù)器請(qǐng)求
-
topic:應(yīng)用程序消息的主題
-
qos:申請(qǐng)消息的服務(wù)質(zhì)量
當(dāng)用戶手機(jī)APP設(shè)置數(shù)據(jù)的時(shí)候,云端自動(dòng)將數(shù)據(jù)下發(fā)給屏幕,代碼如程序清單 5所示:
程序清單 5 接收云端數(shù)據(jù)
--[[*********************************************************************
** Function name: on_air_resp_callback
** Descriptions : 4G模塊-數(shù)據(jù)回調(diào)接口
** @key : 屏幕->4G模塊的發(fā)送請(qǐng)求
** @value : 4G模塊->返回的數(shù)據(jù)
*********************************************************************--]]
function on_air_resp_callback(key, value)
if value == nil
then
return --value為空時(shí)退出
end
if key == nil
then
return
end
--********************************************************************
--條件: 接收 Aliyun 發(fā)布消息
--功能: 在 cloud_on_property_set(payload) 中對(duì)消息進(jìn)行處理。
--調(diào)用函數(shù):cloud_on_property_set(payload)
--********************************************************************
if string.find(value,'+MSUB') ~= nil and key == nil
then
local index = string.find(value,'{')
my_print('index: '..index)
if index ~= nil
then
local payload = string.sub(value, index,-1)
if payload ~= nil
then
cloud_on_property_set(payload)
end
end
end
end
--[[*********************************************************************
** Function name: cloud_on_property_set
** Descriptions : 接收云端數(shù)據(jù)
** @payload : 數(shù)據(jù)字符串,Json格式
*********************************************************************--]]
function cloud_on_property_set(payload)
my_print('cloud_on_property_set')
--payload = string.gsub(payload,'22','"');
local data = cjson.decode(payload) --解析JSON數(shù)據(jù)
if data == nil
then
return
end
if data['params'] == nil
then
return
end
--開關(guān)機(jī)按鈕
local powerstate = tonumber(data['params']['powerstate'])
if powerstate ~= nil
then
set_value(screen_ac_control,1,powerstate)
end
--濾網(wǎng)時(shí)間進(jìn)度條
local filter_time = tonumber(data['params']['filter_time'])
if filter_time ~= nil
then
set_value(screen_ac_control,3,filter_time)
end
--溫度文本
local targetTemperature = tonumber(data['params']['targetTemperature'])
if targetTemperature ~= nil
then
set_value(screen_ac_control,4,targetTemperature)
end
--模式選擇控件
local mode = tonumber(data['params']['mode'])
if mode ~= nil
then
set_text(screen_ac_control,8,my_resp_mode[mode])
end
end
核心API函數(shù)
1) cloud_on_property_set(payload)
接收云端的數(shù)據(jù)
本例程中,假設(shè)用戶通過(guò)APP設(shè)置設(shè)備的模式,下發(fā)Json格式的字符串,數(shù)據(jù)原型如下所示:+MSUB:"/sys/a1D2E9vaSuZ/PlYPGnoYWeUJujy0li2a/thing/service/property/set",95 byte,{"method":"thing.service.property.set","id":"2032042748","params":{"mode":3},"version":"1.0.0"}通過(guò)Json庫(kù)函數(shù)cjson.decode(payload)解壓數(shù)據(jù),則data['params']['mode'] 為模式的值,在將值設(shè)置到對(duì)應(yīng)的滑動(dòng)選擇控件上:set_text(screen_ac_control,8,my_resp_mode[mode])
當(dāng)用戶觸碰控件修改值時(shí)候,屏幕會(huì)自動(dòng)將數(shù)據(jù)打包成Json格式發(fā)給云端,代碼如程序清單 6所示。
程序清單 6 發(fā)送數(shù)據(jù)到云端
local params = {}
local property = {}
local post_id = 1 --屏發(fā)布的消息次數(shù)ID
--[[*********************************************************************
** Function name: aliyun_pub
** Descriptions : 屏發(fā)布消息時(shí),此函數(shù)處理消息內(nèi)容,并發(fā)送
** @screen : aliyun 畫面ID
** @control : 控件ID
** @value : 控件值
** @return : nil,無(wú)返回值
*********************************************************************--]]
function aliyun_pub(screen, control, value)
params = nil
property = nil
params = {}
property = {}
property['method'] = 'thing.event.property.post'
property['id'] = ''..post_id
property['version'] = '1.0'
post_id = post_id + 1
if screen == screen_ac_control
then
--按下開關(guān)按鈕
if control == 1
then
local PowerSwitchName = 'powerstate'
params[PowerSwitchName] = value --在表寫入按鈕數(shù)值
property['params'] = params
local jsonStr = cjson.encode(property)
--發(fā)布消息
mqtt_pub(
'/sys/'..productKey..'/'..deviceName..'/thing/event/property/post',
0,
0,
jsonStr
)
end
end
if screen == screen_ac_control
then
--按下滑塊
if control == 3
then
local PowerSwitchName = 'filter_time'
params[PowerSwitchName] = value --在表寫入滑塊數(shù)值
property['params'] = params
local jsonStr = cjson.encode(property)
--發(fā)布消息
mqtt_pub(
'/sys/'..productKey..'/'..deviceName..'/thing/event/property/post',
0,
0,
jsonStr
)
end
end
if screen == screen_ac_control
then
--按下溫度設(shè)置按鈕,溫度減
if control == 6 and value == 1
then
temp_value = tonumber(get_text(screen_ac_control,4))
temp_value = temp_value-1
if temp_value<16 then
temp_value = 16
end
set_text(screen_ac_control,4,temp_value)
--按下溫度設(shè)置按鈕,溫度加
elseif control == 7 and value == 1
then
temp_value = tonumber(get_text(screen_ac_control,4))
temp_value = temp_value+1
if temp_value>32 then
temp_value = 32
end
set_text(screen_ac_control,4,temp_value)
end
local PowerSwitchName = 'targetTemperature'
params[PowerSwitchName] = temp_value --在表寫入溫度數(shù)值
property['params'] = params
local jsonStr = cjson.encode(property)
--發(fā)布消息
mqtt_pub(
'/sys/'..productKey..'/'..deviceName..'/thing/event/property/post',
0,
0,
jsonStr
)
end
if screen == screen_ac_control
then
if control == 10
then
local PowerSwitchName = 'mode'
params[PowerSwitchName] = value
property['params'] = params
local jsonStr = cjson.encode(property)
mqtt_pub(
'/sys/'..productKey..'/'..deviceName..'/thing/event/property/post',
0,
0,
jsonStr
)
end
end
end
--[[**********************************************************************
** Function name : on_control_notify
** Descriptions : 系統(tǒng)回調(diào)函數(shù),用戶通過(guò)觸摸修改控件后,執(zhí)行此回調(diào)函數(shù)。
** 點(diǎn)擊按鈕控件,修改文本控件、修改滑動(dòng)條都會(huì)觸發(fā)此事件。
** @return : nil,無(wú)返回值
**********************************************************************--]]
function on_control_notify(screen,control,value)
--********************************************************************
--位置: 空調(diào)控制器
--********************************************************************
if screen == screen_ac_control
then
if control == 1 or
control == 3 or
control == 6 or
control == 7 or
control == 10
then
--屏發(fā)布消息
aliyun_pub(screen,control,value)
end
end
end
核心API函數(shù)
1) mqtt_pub (topic,qos,retain,message)
發(fā)送數(shù)據(jù)到云端,傳送應(yīng)用消息
-
topic :應(yīng)用程序消息的主題
-
qos :申請(qǐng)消息的服務(wù)質(zhì)量
-
retain :保留標(biāo)志
-
message:消息內(nèi)容
本例程中,假設(shè)用戶修改模式,則將數(shù)據(jù)Json格式上傳到云端,,數(shù)據(jù)原型如下所示:
AT+MPUB="/sys/a1D2E9vaSuZ/PlYPGnoYWeUJujy0li2a/thing/event/property/post",0,0,"{22version22:221.022,22params22:{22mode22:0,22targetTemperature22:27},22id22:226122,22method22:22thing.event.property.post22}"通過(guò)Json庫(kù)函數(shù)jsonStr = cjson.encode(payload)打包成Json格式的數(shù)據(jù),則jsonStr為上傳的數(shù)據(jù)。