main.lua 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. PROJECT = "aliyundemo"
  2. VERSION = "1.0.0"
  3. local sys = require "sys"
  4. local libfota = require("libfota")
  5. local aliyun = require "aliyun"
  6. --根据自己的服务器修改以下参数
  7. --新版已经合并, 没有了地域, 1883同时兼容加密和非加密通信,非加密会下线
  8. -- 阿里云资料:https://help.aliyun.com/document_detail/147356.htm?spm=a2c4g.73742.0.0.4782214ch6jkXb#section-rtu-6kn-kru
  9. tPara = {
  10. -- 是否为一型一密, true为一型一密, false为一机一密(预注册)
  11. Registration = false,
  12. -- 设备名名称, 必须唯一
  13. DeviceName = (mobile and mobile.imei() or (wlan and wlan.mac() or mcu.unique_id():toHex())),
  14. -- 产品key, 在产品详情页面
  15. ProductKey = "k0ti3QNOFaH", --产品key
  16. --产品secret,一型一密就需要填, 一机一密(预注册)不填
  17. ProductSecret = "",
  18. --设备密钥,一型一密就不填, 一机一密(预注册)必须填
  19. DeviceSecret = "62a17dfe2192526f90bc5fad7cd951fc", --设备secret
  20. -- 填写实例id,在实例详情页面
  21. InstanceId = "iot-06z00hmbog1v175",
  22. -- 固定值, 不要修改
  23. mqtt_port = 1883, -- mqtt端口
  24. --是否使用ssl加密连接,注意: 如果使用一型一密,则必须使用ssl加密
  25. mqtt_isssl = false,
  26. }
  27. -- 低功耗测试, 打开之后, 连接阿里云后5秒请求低功耗
  28. local PM_TEST = false
  29. -- 统一联网函数
  30. sys.taskInit(function()
  31. -----------------------------
  32. -- 统一联网函数, 可自行删减
  33. ----------------------------
  34. if wlan and wlan.connect then
  35. -- wifi 联网, ESP32系列均支持
  36. local ssid = "luatos1234"
  37. local password = "12341234"
  38. log.info("wifi", ssid, password)
  39. -- TODO 改成自动配网
  40. wlan.init()
  41. wlan.setMode(wlan.STATION) -- 默认也是这个模式,不调用也可以
  42. wlan.connect(ssid, password, 1)
  43. elseif mobile then
  44. -- Air780E/Air600E系列
  45. --mobile.simid(2) -- 自动切换SIM卡
  46. -- LED = gpio.setup(27, 0, gpio.PULLUP)
  47. -- device_id = mobile.imei()
  48. elseif w5500 then
  49. -- w5500 以太网, 当前仅Air105支持
  50. w5500.init(spi.HSPI_0, 24000000, pin.PC14, pin.PC01, pin.PC00)
  51. w5500.config() --默认是DHCP模式
  52. w5500.bind(socket.ETH0)
  53. -- LED = gpio.setup(62, 0, gpio.PULLUP)
  54. elseif socket or mqtt then
  55. -- 适配的socket库也OK
  56. -- 没有其他操作, 单纯给个注释说明
  57. else
  58. -- 其他不认识的bsp, 循环提示一下吧
  59. while 1 do
  60. sys.wait(1000)
  61. log.info("bsp", "本bsp可能未适配网络层, 请查证")
  62. end
  63. end
  64. -- 默认都等到联网成功
  65. sys.waitUntil("IP_READY")
  66. sys.publish("net_ready")
  67. end)
  68. --阿里云客户端是否处于连接状态
  69. local sConnected
  70. local publishCnt = 1
  71. --[[
  72. 函数名:pubqos1testackcb
  73. 功能 :发布1条qos为1的消息后收到PUBACK的回调函数
  74. 参数 :
  75. usertag:调用mqttclient:publish时传入的usertag
  76. result:任意数字表示发布成功,nil表示失败
  77. 返回值:无
  78. ]]
  79. local function publishTestCb(result,para)
  80. log.info("aliyun", "发布后的反馈", result,para)
  81. sys.timerStart(publishTest,20000)
  82. publishCnt = publishCnt+1
  83. end
  84. --发布一条QOS为1的消息
  85. function publishTest()
  86. if sConnected then
  87. --注意:在此处自己去控制payload的内容编码,aLiYun库中不会对payload的内容做任何编码转换
  88. -- aliyun.publish(topic,qos,payload,cbFnc,cbPara)
  89. log.info("aliyun", "上行数据")
  90. aliyun.publish("/"..tPara.ProductKey.."/"..tPara.DeviceName.."/user/get",1,"LUATOS_CESHI",publishTestCb,"publishTest_"..publishCnt)
  91. end
  92. end
  93. ---数据接收的处理函数
  94. -- @string topic,UTF8编码的消息主题
  95. -- @string payload,原始编码的消息负载
  96. local function rcvCbFnc(topic,payload,qos,retain,dup)
  97. log.info("aliyun", "收到下行数据", topic,payload,qos,retain,dup)
  98. end
  99. --- 连接结果的处理函数
  100. -- @bool result,连接结果,true表示连接成功,false或者nil表示连接失败
  101. local function connectCbFnc(result)
  102. log.info("aliyun","连接结果", result)
  103. sConnected = result
  104. if result then
  105. sys.publish("aliyun_ready")
  106. log.info("aliyun", "连接成功")
  107. --订阅主题
  108. --根据自己的项目需要订阅主题,下面注释掉的一行代码中的主题是非法的,所以不能打开,一旦打开,会导致订阅失败
  109. --订阅OTA主题
  110. aliyun.subscribe("/ota/device/upgrade/"..tPara.ProductKey.."/"..tPara.DeviceName,1)
  111. if not verRpted then
  112. --上报固件版本号给云端
  113. verRpt()
  114. end
  115. --上报固件版本号给云端
  116. sys.timerStart(verRpt,10000)
  117. -- aliyun.subscribe(topic,qos)
  118. -- aliyun.subscribe("/"..tPara.ProductKey.."/"..tPara.DeviceName.."/user/ceshi",1)
  119. --使用掉电不消失的kv文件区来储存的deviceSecret,deviceToken
  120. local used = fskv.get("deviceSecret")
  121. local total = fskv.get("deviceToken")
  122. local cid = fskv.get("clientid")
  123. --储存到kv分区的返回值
  124. -- log.info("kv分区的返回值",used,total,cid)
  125. local Secret = aliyun.getDeviceSecret()
  126. local Token = aliyun.getDeviceToken()
  127. local Clid = aliyun.getClientid()
  128. --如果三元组不为空,就把三元组写入到kv区
  129. if tPara.DeviceName and tPara.ProductKey then
  130. fskv.set("DeviceName",tPara.DeviceName)
  131. fskv.set("ProductKey",tPara.ProductKey)
  132. end
  133. if not tPara.Registration then
  134. if Secret == nil then
  135. log.info("aliyun","掉线重连")
  136. else
  137. fskv.set("deviceSecret",aliyun.getDeviceSecret())
  138. end
  139. else
  140. if Token == nil and Clid == nil then
  141. log.info("aliyun","掉线重连")
  142. else
  143. fskv.set("deviceToken",aliyun.getDeviceToken())
  144. fskv.set("clientid",aliyun.getClientid())
  145. end
  146. end
  147. --注册数据接收的处理函数
  148. aliyun.on("receive",rcvCbFnc)
  149. --PUBLISH消息测试
  150. publishTest()
  151. else
  152. log.warn("aliyun", "连接失败")
  153. end
  154. end
  155. aliyun.on("connect",connectCbFnc)
  156. --根据掉电不消失的kv文件区来储存的deviceSecret,clientid,deviceToken来判断是进行正常连接还是掉电重连
  157. sys.taskInit(function()
  158. sys.waitUntil("net_ready")
  159. socket.sntp()
  160. sys.waitUntil("NTP_UPDATE", 2000)
  161. log.info("已联网", "开始初始化aliyun库")
  162. fskv.init()
  163. local name = fskv.get("DeviceName")
  164. local key = fskv.get("ProductKey")
  165. local used = fskv.get("deviceSecret")
  166. local total = fskv.get("deviceToken")
  167. local cid = fskv.get("clientid")
  168. local host = tPara.InstanceId..".mqtt.iothub.aliyuncs.com"
  169. --判断是否是同一三元组,不是的话就重新连接
  170. if name == tPara.DeviceName and key == tPara.ProductKey then
  171. if not tPara.Registration then
  172. if used == nil then
  173. aliyun.setup(tPara)
  174. else
  175. aliyun.clientGetDirectDataTask(name,tPara.ProductKey,host,tPara.mqtt_port,tPara.mqtt_isssl,tPara.Registration,used,total,cid)
  176. end
  177. else
  178. if total == nil and cid == nil then
  179. aliyun.setup(tPara)
  180. else
  181. aliyun.clientGetDirectDataTask(name,tPara.ProductKey,host,tPara.mqtt_port,tPara.mqtt_isssl,tPara.Registration,used,total,cid)
  182. end
  183. end
  184. else
  185. fskv.del("deviceToken")
  186. fskv.del("clientid")
  187. fskv.del("DeviceName")
  188. fskv.del("deviceSecret")
  189. fskv.del("ProductKey")
  190. --删除kv区的数据,重新建立连接
  191. aliyun.setup(tPara)
  192. end
  193. end)
  194. function verRpt()
  195. log.info("aliyun", "上报版本信息", _G.VERSION)
  196. aliyun.publish("/ota/device/inform/"..tPara.ProductKey.."/"..tPara.DeviceName,1,"{\"id\":1,\"params\":{\"version\":\"".._G.VERSION.."\"}}")
  197. end
  198. -- 低功耗演示
  199. sys.taskInit(function()
  200. if not PM_TEST then
  201. return
  202. end
  203. sys.waitUntil("aliyun_ready")
  204. log.info("aliyun.pm", "阿里云已经连接成功, 5秒后请求进入低功耗模式, USB功能会断开")
  205. sys.wait(5000)
  206. local bsp = rtos.bsp():upper()
  207. -- 进入低功耗模式
  208. if bsp == "EC618" then
  209. log.info("aliyun.pm", "EC618方案进入低功耗模式")
  210. -- gpio.setup(23,nil)
  211. -- gpio.close(33)
  212. -- mobile.rtime(2) -- RRC快速释放减少connect时间能大幅降低功耗,但是会带来可能得离线风险,可选择延迟时间或者不用
  213. pm.power(pm.USB, false)
  214. pm.force(pm.LIGHT)
  215. elseif bsp == "EC718P" or bsp == "EC718PV" then
  216. log.info("aliyun.pm", "EC718P/EC718PV方案进入低功耗模式")
  217. -- mobile.rtime(2) -- RRC快速释放减少connect时间能大幅降低功耗,但是会带来可能得离线风险,可选择延迟时间或者不用
  218. pm.power(pm.USB, false)
  219. pm.force(pm.LIGHT)
  220. elseif bsp == "AIR101" or bsp == "AIR601" or bsp == "AIR103" then
  221. log.info("aliyun.pm", "XT804方案进入低功耗模式")
  222. while 1 do
  223. pm.dtimerStart(0, 30000)
  224. pm.request(pm.LIGHT)
  225. sys.wait(30000)
  226. end
  227. end
  228. end)
  229. -- 用户代码已结束---------------------------------------------
  230. -- 结尾总是这一句
  231. sys.run()
  232. -- sys.run()之后后面不要加任何语句!!!!!