Browse Source

add: 增加air8000 的 代码仓库

梁健 9 tháng trước cách đây
mục cha
commit
56e664b66c
100 tập tin đã thay đổi với 7585 bổ sung0 xóa
  1. 41 0
      module/Air8000/.gitignore
  2. 21 0
      module/Air8000/LICENSE
  3. 36 0
      module/Air8000/README.en.md
  4. 17 0
      module/Air8000/README.md
  5. BIN
      module/Air8000/core/LuatOS-SoC_V2006_Air8000_LVGL.soc
  6. 94 0
      module/Air8000/core/changeLog.md
  7. 3 0
      module/Air8000/core/固件差异.txt
  8. 78 0
      module/Air8000/demo/GPS/main.lua
  9. 403 0
      module/Air8000/demo/JT808/main.lua
  10. 118 0
      module/Air8000/demo/WebSocket/WebSocket-UART透传/main.lua
  11. 79 0
      module/Air8000/demo/WebSocket/WebSocket加密通讯/main.lua
  12. 24 0
      module/Air8000/demo/adc/main.lua
  13. 66 0
      module/Air8000/demo/adc/testAdc.lua
  14. 90 0
      module/Air8000/demo/airlbs/main.lua
  15. 48 0
      module/Air8000/demo/bit/main.lua
  16. 110 0
      module/Air8000/demo/bit64/main.lua
  17. 73 0
      module/Air8000/demo/can/main.lua
  18. BIN
      module/Air8000/demo/crypto/logo.jpg
  19. 238 0
      module/Air8000/demo/crypto/main.lua
  20. 62 0
      module/Air8000/demo/errDump/main.lua
  21. 101 0
      module/Air8000/demo/fota2/main.lua
  22. 133 0
      module/Air8000/demo/fs/main.lua
  23. 105 0
      module/Air8000/demo/fskv/main.lua
  24. 92 0
      module/Air8000/demo/ftp/main.lua
  25. 37 0
      module/Air8000/demo/gpio/AGPIO/main.lua
  26. 39 0
      module/Air8000/demo/gpio/GPIO上拉下拉模式/main.lua
  27. 27 0
      module/Air8000/demo/gpio/GPIO中断(触发)模式/main.lua
  28. 34 0
      module/Air8000/demo/gpio/GPIO中断(计数)模式/main.lua
  29. 34 0
      module/Air8000/demo/gpio/GPIO翻转测速/main.lua
  30. 41 0
      module/Air8000/demo/gpio/GPIO输入模式/main.lua
  31. 37 0
      module/Air8000/demo/gpio/GPIO输出模式/main.lua
  32. 50 0
      module/Air8000/demo/gpio/power_on/main.lua
  33. 157 0
      module/Air8000/demo/gsensor/da221.lua
  34. 16 0
      module/Air8000/demo/gsensor/main.lua
  35. 21 0
      module/Air8000/demo/helloworld/main.lua
  36. 26 0
      module/Air8000/demo/hmeta/main.lua
  37. 3 0
      module/Air8000/demo/http/luatos_uploadFile.txt
  38. 297 0
      module/Air8000/demo/http/main.lua
  39. 57 0
      module/Air8000/demo/i2c-sht20/main.lua
  40. 69 0
      module/Air8000/demo/i2c/硬件I2C/main.lua
  41. 64 0
      module/Air8000/demo/i2c/软件I2C/main.lua
  42. 218 0
      module/Air8000/demo/iconv/main.lua
  43. 83 0
      module/Air8000/demo/iotcloud/aliyun/示例1 一型一密(免预注册,但需要是企业版实例平台)方式连接云平台/main.lua
  44. 82 0
      module/Air8000/demo/iotcloud/aliyun/示例2 一型一密(预注册)方式连接云平台/main.lua
  45. 82 0
      module/Air8000/demo/iotcloud/aliyun/示例3 一机一密方式连接云平台/main.lua
  46. 70 0
      module/Air8000/demo/iotcloud/baiduiot/main.lua
  47. 88 0
      module/Air8000/demo/iotcloud/huaweiiot/main.lua
  48. 157 0
      module/Air8000/demo/iotcloud/onenet/main.lua
  49. 79 0
      module/Air8000/demo/iotcloud/tencentiot/main.lua
  50. 70 0
      module/Air8000/demo/iotcloud/tuyaiot/示例1 一机一密/main.lua
  51. 81 0
      module/Air8000/demo/json/main.lua
  52. 31 0
      module/Air8000/demo/lbsLoc2/main.lua
  53. 42 0
      module/Air8000/demo/lcd/airlcd.lua
  54. 59 0
      module/Air8000/demo/lcd/main.lua
  55. BIN
      module/Air8000/demo/lcd/picture.jpg
  56. 21 0
      module/Air8000/demo/led/main.lua
  57. 60 0
      module/Air8000/demo/log/main.lua
  58. 90 0
      module/Air8000/demo/lowpower/low_power_dissipation.lua
  59. 17 0
      module/Air8000/demo/lowpower/main.lua
  60. 70 0
      module/Air8000/demo/lowpower/normal.lua
  61. 79 0
      module/Air8000/demo/lowpower/ultra_low_power.lua
  62. 59 0
      module/Air8000/demo/lvgl/main.lua
  63. 41 0
      module/Air8000/demo/miniz/main.lua
  64. 118 0
      module/Air8000/demo/mobile/main.lua
  65. 124 0
      module/Air8000/demo/mqtt/main.lua
  66. 64 0
      module/Air8000/demo/netdrv/ch390/lan/lan.lua
  67. 22 0
      module/Air8000/demo/netdrv/ch390/lan/main.lua
  68. 183 0
      module/Air8000/demo/netdrv/ch390/lan_TCP/main.lua
  69. 22 0
      module/Air8000/demo/netdrv/ch390/wan/main.lua
  70. 39 0
      module/Air8000/demo/netdrv/ch390/wan/wan.lua
  71. 164 0
      module/Air8000/demo/netdrv/ch390/wan_TCP/main.lua
  72. 119 0
      module/Air8000/demo/ntp/main.lua
  73. 119 0
      module/Air8000/demo/onewire/main.lua
  74. 62 0
      module/Air8000/demo/pack/main.lua
  75. 72 0
      module/Air8000/demo/protobuf/main.lua
  76. 7 0
      module/Air8000/demo/protobuf/person.pb
  77. 6 0
      module/Air8000/demo/protobuf/person.pbtxt
  78. 43 0
      module/Air8000/demo/pwm/PWM呼吸灯/main.lua
  79. 42 0
      module/Air8000/demo/pwm/PWM输出/main.lua
  80. 34 0
      module/Air8000/demo/pwm/示例1 PWM输出/main.lua
  81. 58 0
      module/Air8000/demo/pwm/示例2 呼吸灯效果/main.lua
  82. 50 0
      module/Air8000/demo/rc522/main.lua
  83. 87 0
      module/Air8000/demo/sms/main.lua
  84. 78 0
      module/Air8000/demo/spi/main.lua
  85. 113 0
      module/Air8000/demo/string/main.lua
  86. 134 0
      module/Air8000/demo/tcp/TCP-UART/main.lua
  87. 139 0
      module/Air8000/demo/tcp/TCP单向认证/main.lua
  88. 134 0
      module/Air8000/demo/tcp/TCP断链续连/main.lua
  89. 51 0
      module/Air8000/demo/timer/main.lua
  90. 51 0
      module/Air8000/demo/uart/uart/main.lua
  91. 49 0
      module/Air8000/demo/uart/uart_rs485/main.lua
  92. 77 0
      module/Air8000/demo/uart/uart_two/main.lua
  93. 61 0
      module/Air8000/demo/uart/uart_vir/main.lua
  94. 123 0
      module/Air8000/demo/udp/main.lua
  95. 64 0
      module/Air8000/demo/usb_uart/main.lua
  96. 33 0
      module/Air8000/demo/wdt/示例一 程序正常运行/main.lua
  97. 42 0
      module/Air8000/demo/wdt/示例二 添加死循环模拟故障场景/main.lua
  98. 93 0
      module/Air8000/demo/wifi_location/main.lua
  99. 144 0
      module/Air8000/demo/wlan/AP/main.lua
  100. 144 0
      module/Air8000/demo/wlan/STA/main.lua

+ 41 - 0
module/Air8000/.gitignore

@@ -0,0 +1,41 @@
+# Compiled Lua sources
+luac.out
+
+# luarocks build files
+*.src.rock
+*.zip
+*.tar.gz
+
+# Object files
+*.o
+*.os
+*.ko
+*.obj
+*.elf
+
+# Precompiled Headers
+*.gch
+*.pch
+
+# Libraries
+*.lib
+*.a
+*.la
+*.lo
+*.def
+*.exp
+
+# Shared objects (inc. Windows DLLs)
+*.dll
+*.so
+*.so.*
+*.dylib
+
+# Executables
+*.exe
+*.out
+*.app
+*.i*86
+*.x86_64
+*.hex
+

+ 21 - 0
module/Air8000/LICENSE

@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2025 Wendal
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.

+ 36 - 0
module/Air8000/README.en.md

@@ -0,0 +1,36 @@
+# LuatOS-Air8000
+
+#### Description
+LuatOS-Air8000专用仓库
+
+#### Software Architecture
+Software architecture description
+
+#### Installation
+
+1.  xxxx
+2.  xxxx
+3.  xxxx
+
+#### Instructions
+
+1.  xxxx
+2.  xxxx
+3.  xxxx
+
+#### Contribution
+
+1.  Fork the repository
+2.  Create Feat_xxx branch
+3.  Commit your code
+4.  Create Pull Request
+
+
+#### Gitee Feature
+
+1.  You can use Readme\_XXX.md to support different languages, such as Readme\_en.md, Readme\_zh.md
+2.  Gitee blog [blog.gitee.com](https://blog.gitee.com)
+3.  Explore open source project [https://gitee.com/explore](https://gitee.com/explore)
+4.  The most valuable open source project [GVP](https://gitee.com/gvp)
+5.  The manual of Gitee [https://gitee.com/help](https://gitee.com/help)
+6.  The most popular members  [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)

+ 17 - 0
module/Air8000/README.md

@@ -0,0 +1,17 @@
+LuatOS-Air8000
+介绍
+本代码库 是 合宙 Air8000 模组的代码中心, 包括固件, 演示代码, 案例代码等
+
+如需查阅文档, 请访问合宙文档中心的Air780EPM模块文档中心
+
+目录说明:
+
+- core   固件文件
+- demo  演示代码
+- project 案例代码
+
+授权协议
+MIT License
+
+print("感谢您使用LuatOS ^_^")
+print("Thank you for using LuatOS ^_^")

BIN
module/Air8000/core/LuatOS-SoC_V2006_Air8000_LVGL.soc


+ 94 - 0
module/Air8000/core/changeLog.md

@@ -0,0 +1,94 @@
+# Air8000模块固件更新 --- 修改记录
+
+## 2025.04.29
+
+1. 修复libgnss设置uart回调没有成功,有"uartXX no received callback"的错误。
+2. 修复libgnss,执行bind操作后无法拿到数据。
+3. 修复lcd,on/off操作,使用RGB屏时不需要发送指令。
+4. 修复air8000s脚本调用wlan.getMAC无法拿到MAC地址。
+5. netdrv,ch390,支持中断模式,默认轮询模式。
+6. 修复ch390 wan以太网转wifi_ap功能,使用其他设备连接wifi使用网络时,下载/上传 数据过多,会导致处理不过来无法上网的问题。
+7. 硬件lcd接口增加软件cs控制,允许使用其他GPIO作为cs控制
+8. zbuff的used()加入快速设置有效数据量的方法,可以不用seek
+9. 支持wifi订阅的4个事件STA 连上、断开、AP 新STA连上、旧STA断开。
+10. 修复lcd预览camera结束后显示异常
+
+
+
+## 2025.04.25
+
+1. VOLTE固件 将"开机自动打开Air8000s电源和配置netdrv的功能"关闭。如果是用_VOLTE的固件,并且有需要使用到 **WIFI功能** 或需要 **控制>100序号的GPIO** ,那则需要在主task开头单独执行一次下面的代码。
+
+   ~~~lua
+   sys.wait(10)		-- 刚开机稍微缓一下
+   airlink.init()		-- 初始化airlink
+   airlink.start(1)	-- 启动底层线程, 从机模式
+   gpio.setup(23,1, gpio.PULLUP)   --打开Air8000S电源
+   sys.wait(300)		-- 等一小段时间让Air8000S启动,然后再配置gpio或wifi
+   ~~~
+
+2. 修复VOLTE固件跑es8311初始化会失败,导致出现走cc库通话听不到声音或者说话对方听不到的情况。
+
+   测试发现是Airlink在开机同步启动的原因引起的,如果需要使用es8311的同时 使用Air8000s的wifi功能,需要在es8311初始化之后,再手动添加运行下面代码启动Air8000S和配置netdrv。
+
+   ~~~lua
+   airlink.init()			-- 初始化airlink
+   log.info("注册STA和AP设备")
+   netdrv.setup(socket.LWIP_STA, netdrv.WHALE)
+   netdrv.setup(socket.LWIP_AP, netdrv.WHALE)
+   airlink.start(1)	 	-- 启动底层线程, 从机模式
+   gpio.setup(23, 1) 		-- 打开Air8000S电源
+   sys.wait(300)
+   ~~~
+   
+3. 修复i2c有概率发送数据通讯失败的问题。
+
+4. 支持fs库
+
+5. 当前4G转wifi, 4G转以太网, wifi转以太网, 3个网络通道的排列组合的配网都已支持
+
+
+
+## 2025.04.24
+
+1. 支持FS功能。
+2. 修复VOLTE固件 wifi_sta、wifi_ap、WAN功能,不能正常通网通信的问题。
+3. socket链接 不使用tls方式建立的链接,最多可支持64个。
+4. 添加wifi事件回调消息,详细用法看看 demo/airlink/air8000_wifi
+
+
+
+## 2025.04.23 
+
+1. wifi_sta模式下支持自动开启dhcp,不需要手动打开。
+2. 支持默认加载sys和sysplus库,不需要额外在main.lua 中添加require "sys"和require "sysplus"了。
+3. 能够支持air8000s wifi模块的fota操作。
+4. 修复CAN功能通讯有异常的问题。
+5. gpio新增VBUS,USIM_DET常量,可以通过gpio.VBUS和gpio.USIM_DET使用。
+
+
+
+## 2025.04.18 
+
+1. 支持CAN功能 
+2. 修复使用部分lcd屏幕,显示色彩有偏差 。
+3. 增加icmp库,可支持ping操作。
+4. 支持最多同时建立32个socket链接。
+5. 使用Air8000和Air8000G 带GNSS的模块,默认会将GNSS电源(gpio25)拉低。
+
+
+
+## 2025.04.17
+
+1. Air8000和Air8000W 默认打开Air8000S wifi芯片的供电,脚本中可以省略打开Air8000S的电源、airlink.init和airlink.start的操作了。
+2. 80/81管脚默认作为i2c0使用,66/67管脚默认作为i2c1使用,不再需要mcu.altfun接口进行复用。
+3. 增加 airlink.config接口,可配置AirLink的参数。
+
+
+
+## 2025.04.15
+
+1. 支持pins库,代替mcu.altfun复用接口的功能。
+2. 支持VOLTE功能,由于VOLTE和LVGL两个功能占用空间很大,分成了两个版本的固件。
+3. gpio24默认改为高电平
+4. 添加软复位的通用指令,但当前只支持ch390,api:netdrv.ctrl(id, cmd, arg)

+ 3 - 0
module/Air8000/core/固件差异.txt

@@ -0,0 +1,3 @@
+LuatOS-SoC_V20xx_Air8000_LVGL  	固件支持LVGL,不支持VOLTE
+LuatOS-SoC_V20xx_Air8000_VOLTE 	固件支持VOLTE,不支持LVGL
+除此之外,两个固件支持的其他功能都一样。

+ 78 - 0
module/Air8000/demo/GPS/main.lua

@@ -0,0 +1,78 @@
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "air8000_gnss"
+VERSION = "1.0.0"
+
+log.info("main", PROJECT, VERSION)
+
+-- 引入必要的库文件(lua编写), 内部库不需要require
+sys = require("sys")
+
+
+-- mobile.flymode(0,true)
+if wdt then
+    --添加硬狗防止程序卡死,在支持的设备上启用这个功能
+    wdt.init(9000)--初始化watchdog设置为9s
+    sys.timerLoopStart(wdt.feed, 3000)--3s喂一次狗
+end
+log.info("main", "air8000_gnss")
+
+
+mcu.hardfault(0)    --死机后停机,一般用于调试状态
+pm.ioVol(pm.IOVOL_ALL_GPIO, 3300) -- 所有GPIO高电平输出3.0V
+local gps_uart_id = 2 -- 根据实际设备选取不同的uartid
+uart.setup(gps_uart_id, 115200)
+-- libgnss.bind(gps_uart_id)-- 绑定uart, 马上开始解析GNSS数据
+--打开或者关闭GNSS的函数,传1打开,传0关闭
+
+
+sys.taskInit(function()
+    log.info("GPS", "start")
+    pm.power(pm.GPS, true)
+    -- 绑定uart,底层自动处理GNSS数据
+    -- 第二个参数是转发到虚拟UART, 方便上位机分析
+    libgnss.bind(gps_uart_id, uart.VUART_0)
+    sys.wait(200) -- GPNSS芯片启动需要时间
+    -- 调试日志,可选
+    libgnss.debug(true)
+end)
+
+
+sys.taskInit(function()
+    while 1 do
+        sys.wait(5000)
+        log.info("RMC", json.encode(libgnss.getRmc(2) or {}, "7f"))         --解析后的rmc数据
+        log.info("GGA", libgnss.getGga(3))                                   --解析后的gga数据
+        -- log.info("GLL", json.encode(libgnss.getGll(2) or {}, "7f"))
+        -- log.info("GSA", json.encode(libgnss.getGsa(1) or {}, "7f"))
+        -- log.info("GSV", json.encode(libgnss.getGsv(2) or {}, "7f"))
+        -- log.info("VTG", json.encode(libgnss.getVtg(2) or {}, "7f"))
+        -- log.info("ZDA", json.encode(libgnss.getZda(2) or {}, "7f"))
+        -- log.info("date", os.date())
+        -- log.info("sys", rtos.meminfo("sys"))
+        -- log.info("lua", rtos.meminfo("lua"))
+    end
+end)
+
+-- 订阅GNSS状态编码
+sys.subscribe("GNSS_STATE", function(event, ticks)
+    -- event取值有
+    -- FIXED 定位成功
+    -- LOSE  定位丢失
+    -- ticks是事件发生的时间,一般可以忽略
+    log.info("gnss", "state", event, ticks)
+    if event == "FIXED" then
+        local locStr = libgnss.locStr()
+        log.info("gnss", "locStr", locStr)
+        -- if locStr then
+        --     -- 存入文件,方便下次AGNSS快速定位
+        --     io.writeFile("/gnssloc", locStr)
+        -- end
+    end
+end)
+
+
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 403 - 0
module/Air8000/demo/JT808/main.lua

@@ -0,0 +1,403 @@
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "JT808"
+VERSION = "2.0.0"
+
+--[[
+本demo演示使用string.pack与unpack函数,实现JT808 终端注册协议数据生成与解析
+]]
+
+--加载sys库
+sys = require("sys")
+
+
+local netLed = require("netLed")
+--GPIO27配置为输出,用作网络指示灯
+local LEDA= gpio.setup(27, 0, gpio.PULLUP)
+
+-- 自定义位运算函数
+local bit = {}
+
+--终端消息ID
+T_COMMON_RSP = 0x0001
+T_REGISTER = 0x0100
+
+function bit.bxor(a, b)
+    return a ~ b  -- 按位异或
+end
+
+--十六进制转二进制
+local function hexToBinary(hexStr)
+    local binaryData = {}
+    for i = 1, #hexStr, 2 do
+        local byte = tonumber(hexStr:sub(i, i+1), 16) -- 每两个字符转换为一个字节
+        table.insert(binaryData, string.char(byte))
+    end
+    return table.concat(binaryData) -- 拼接成二进制字符串
+end
+--字符串转字节数组
+local function stringToBytes(hexStr)
+    local bytes = {}
+    for i = 1, #hexStr, 2 do
+        local byteStr = hexStr:sub(i, i+1)
+        local byte = tonumber(byteStr, 16)
+        table.insert(bytes, byte)
+    end
+    return bytes
+end
+--BCD编码
+local function encodeBcdNum(d, n)
+    if d:len() < n then
+        return (string.rep('0', n - d:len()) .. d):fromHex()
+    else
+        return (d:sub(1, n)):fromHex()
+    end
+end
+--计算异或校验(十六进制字符串)
+local function calculateXor(data)
+    local sum = 0
+     for i = 1, #data, 2 do
+        local byte = tonumber(data:sub(i, i+1), 16)
+
+        -- 检查是否转换成功
+        if not byte then
+           error(string.format("Invalid hex character: '%s' at position %d", byteStr, i))
+        end
+
+        -- 打印当前字节的值(十六进制和十进制)
+        --print(string.format("当前字节: %s (十进制: %d)", byteStr, byte))
+
+        if not byte then
+            error("Invalid hex character in input string!")
+        end
+        sum = bit.bxor(sum, byte)
+        -- 打印异或后的中间结果
+        --print(string.format("异或后 sum = %d (十六进制: 0x%X)", sum, sum))
+    end
+    return sum
+end
+--
+local function calCrc(hexStr)
+
+    -- 解析hexStr转换为十六进制字符数组
+    local byteArray = HexOutput(hexStr)
+
+    -- 计算 CRC
+    local crc = calculateXor(byteArray)
+    log.info("CRCxor:",crc)
+
+    -- 返回 CRC 值
+    return crc
+end
+
+--将时间转换为BCD格式
+function timeToBCD()
+    local t = os.date("*t")
+    
+    -- 转换为BCD格式
+    local year = string.format("%02d", t.year % 100)
+    local month = string.format("%02d", t.month)
+    local day = string.format("%02d", t.day)
+    local hour = string.format("%02d", t.hour)
+    local min = string.format("%02d", t.min)
+    local sec = string.format("%02d", t.sec)
+    
+    -- 组合BCD格式字符串
+    local bcdTime = year .. month .. day .. hour .. min .. sec
+    
+    return bcdTime
+end
+
+
+--构建通用应答
+function cmnRsp(svrSeq, svrId, result)
+    return string.pack('>HHb', svrSeq, svrId, result)   
+    -- >表示使用大端字节序;  
+    -- HH 表示两个 16 位无符号整数(svrSeq 和 svrId); 
+    -- b 表示一个 8 位有符号整数(result)
+end
+--构建设备注册
+function register(ProvinceId,CityId,ManufactureId,TerminalModule,TerminalId,CarColor,CarId)
+    local termMd = TerminalModule..string.rep(string.char(0), 16 - (TerminalModule):len())..string.rep(string.char(0), 4)
+    --log.info("HexDataByteLength:",#termMd)
+    --log.info("HexData is:       ",termMd)
+    return string.pack('>HHc5c20c7Bc11',ProvinceId,CityId,ManufactureId,termMd,TerminalId:fromHex(),CarColor,CarId)
+end
+--构建位置信息汇报
+function locRpt(alarm, status, lat, lng, alt, spd, course, tm, extInfo)
+    -- 使用 '>iiiiHHH' 格式打包数据
+    return string.pack('>iiiiHHH', alarm, status, lat, lng, alt, spd, course)..tm:fromHex().. extInfo
+end
+
+function HexOutput(data)
+    log.info("HexDataByteLength:",#data)
+    local hex = ""
+    for i = 1, #data do
+        hex = hex.. string.format("%02x", string.byte(data, i))
+    end
+    log.info("HexData is:       ",hex)
+    return hex
+end
+--封装一个完整的JT808终端注册数据帧
+function encodeReg(phoneNo,tSendSeq)
+    --消息体
+    local msgBody = register(12,123,'10001','GT808','00000000000002',0,'41048063212')
+    --消息头
+    local msgHead =string.pack('>HH',T_REGISTER,msgBody:len())..encodeBcdNum(phoneNo,12)..tSendSeq
+    local curSeq = tSendSeq
+    tSendSeq = (tSendSeq == 0xFFFF) and 0 or (tSendSeq + 1)
+    --校验码
+    HexOutput(msgHead .. msgBody)
+    local frame = msgHead .. msgBody
+    log.info("encodeReg Frame length is:       ",#frame)
+    local crc = calCrc(frame)
+    
+    --转义
+    local s = msgHead .. msgBody .. string.char(crc)
+    s = s:gsub('\125', '\125\1') -- 7D -> 7D 01
+    s = s:gsub('\126', '\125\2') -- 7E -> 7D 02
+    return string.char(0x7E) .. s .. string.char(0x7E), curSeq
+
+end
+
+function decodeCmnRsp(s)
+
+    log.info("hereNow.",s)
+    --local start, tail, msg = s:find('^(7E[^7E]+7E)$')
+    --local decPacket, msgAttr = {}
+-- 检查是否以 7E 开头和结尾
+    if not s:match("^7E") or not s:match("7E$") then
+        log.warn("prot.decode", "packet does not start or end with 7E")
+        return nil
+    end
+
+    -- 匹配以 7E 开头和结尾的数据包
+    local start, tail, msg = s:find('^(7E.+7E)$')  -- 改为允许中间部分包含 7E
+    log.info("start:", start)
+    log.info("tail:", tail)
+    log.info("msg:", msg)
+
+    if not msg then
+        -- 如果未匹配到
+        log.warn('prot.decode', 'wait packet complete')
+        return nil
+    end
+    
+    --反转义
+    msg = msg:gsub('\125\2', '\126') -- 7D 02 -> 7E
+    msg = msg:gsub('\125\1', '\125') -- 7D 01 -> 7D
+
+    log.info("msg:", msg,msg:len())
+
+    if msg:len() < 13 then
+        log.error('prot.decode', 'packet len is too short')
+        return s:sub(tail + 1, -1), nil
+    end
+
+    local hexArray = stringToBytes(msg)
+
+    local dataHexStr = msg:sub(3, -5)
+    log.info("消息体和其字节长度:", dataHexStr,dataHexStr:len())
+
+    local crcVal = calculateXor(dataHexStr)
+    print("XOR校验值:", crcVal)
+
+    if  crcVal ~= hexArray[#hexArray-1] then
+        log.error('prot.decode', 'crc value error!')
+        return s:sub(tail + 1, -1), nil
+    else
+        log.info("XOR:校验通过")
+    end
+
+    ----------------------------解析消息id
+    msgdata = msg:sub(3, 6)
+
+    -- 转换为二进制数据
+    local binaryData = hexToBinary(msgdata)
+
+    -- 解析二进制数据
+    msgId = string.unpack(">H", binaryData)
+
+    -- 输出结果
+    log.info("消息id十六进制:", string.format("0x%04X", msgId))
+
+    ----------------------------解析应答结果
+    msgdata = msg:sub(7, 8)
+
+    -- 转换为二进制数据
+    local binaryData = hexToBinary(msgdata)
+
+    -- 解析二进制数据
+    result = string.unpack(">B", binaryData)
+
+    -- 输出结果
+    log.info("结果十六进制:", string.format("0x%02X", result))
+
+    ----------------------------解析鉴权码
+    msgdata = msg:sub(9, 10)
+
+    -- 转换为二进制数据
+    local binaryData = hexToBinary(msgdata)
+
+    -- 解析二进制数据
+    result = string.unpack(">B", binaryData)
+
+    -- 输出结果
+    log.info("鉴权码十六进制:", string.format("0x%02X", result))
+
+    ----------------------------解析电话号码
+    msgdata = msg:sub(11, 22)
+
+    -- 转换为二进制数据
+    local binaryData = hexToBinary(msgdata)
+
+    -- 解析二进制数据
+    local b1, b2, b3, b4, b5, b6 = string.unpack(">BBBBBB", binaryData)
+
+    -- 格式化输出为 6 字节的十六进制字符串
+    local TerminalPhoneNo = string.format("0x%02X%02X%02X%02X%02X%02X", b1, b2, b3, b4, b5, b6)
+
+    -- 输出电话号码
+    log.info("电话号码十六进制:", TerminalPhoneNo)
+
+    ----------------------------解析标头流水号
+    msgdata = msg:sub(23, 26)
+
+    -- 转换为二进制数据
+    local binaryData = hexToBinary(msgdata)
+
+    -- 解析二进制数据
+    local ManualMsgNum = string.unpack(">H", binaryData)
+
+    -- 输出结果
+    log.info("标头流水号十六进制:", string.format("0x%04X", ManualMsgNum))
+
+    ----------------------------解析标尾流水号
+    msgdata = msg:sub(23, 26)
+
+    -- 转换为二进制数据
+    local binaryData = hexToBinary(msgdata)
+
+    -- 解析二进制数据
+    local MsgNum = string.unpack(">H", binaryData)
+
+    -- 输出结果
+    log.info("标尾流水号十六进制:", string.format("0x%04X", MsgNum))
+
+    ----------------------------解析鉴权码
+    msgdata = msg:sub(33, 50)
+
+    -- 转换为二进制数据
+    local binaryData = hexToBinary(msgdata)
+
+    local b1, b2, b3, b4, b5, b6, b7, b8, b9 = string.unpack(">BBBBBBBBB", binaryData)
+
+    -- 格式化输出为 6 字节的十六进制字符串
+    local JianquanCode = string.format("0x%02X%02X%02X%02X%02X%02X%02X%02X%02X", b1, b2, b3, b4, b5, b6, b7, b8, b9)
+
+    -- 输出结果
+    log.info("鉴权码十六进制:", JianquanCode)
+end
+
+--新建任务,每休眠2000ms继续一次
+sys.taskInit(function()
+    
+    --实验1:构建立通用应答数据帧,协议可参考JT808协议8.1与8.2
+    --输入参数:
+    --应答流水号为123,
+    --应答 ID为456,
+    --结果为1,
+    local data = cmnRsp(123, 456, 1)
+    HexOutput(data)  --HexDataByteLength:5,HexData is:007b01c801  007b为123,01c8为456,1为1
+
+    --实验2:构建终端注册数据帧,协议可参考JT808协议8.5
+    --输入参数:
+    --12,                   --省域 ID  WORD
+    --123,                  --市县域 ID  WORD
+    --'10001',              --制造商 ID  BYTE[5]
+    --'GT808'               --终端型号 BYTE[20]
+    --'00000000000002',     --终端 ID BYTE[7]
+    --0,                    --车牌颜色  BYTE
+    --'41048063212')        --车辆标识  STRING  VIN或车牌号均为固定长度,这里假设字符串长度为11
+    local data = register(12,123,'10001','GT808','00000000000002',0,'41048063212')
+    HexOutput(data)--[HexDataByteLength:]	48,[HexData is:       ]	
+
+    --输出解析:
+    --000c,对应12,                   --省域 ID  WORD
+    --007b,对应123,                  --市县域 ID  WORD
+    --3130303031,对应'10001',              --制造商 ID  BYTE[5]
+    --4754383038,对应'GT808'               --终端型号 BYTE[20],不足字节补0
+    --0000000000
+    --0000000000
+    --0000000000
+    --00000000000002 对应'00000000000002',     --终端 ID BYTE[7]
+    --000,                    --车牌颜色  BYTE
+    --3431303438303633323132,对应'41048063212')        --车辆标识  STRING 
+
+ 
+    --实验3:构建位置信息汇报数据帧,协议可参考JT808协议8.18
+    --输入参数:
+    --0, 报警标志 DWORD
+    --1, 状态位 DWORD
+    --12345678, 纬度 DWORD
+    --87654321, 经度 DWORD
+    --100, 高程 WORD
+    --60, 速度 WORD
+    --180, 方向 WORD
+    --os.time(), 时间 BCD[6]  YY-MM-DD-hh-mm-ss(GMT+8 时间,本标准中之后涉及的时间均采用此时区)
+    --"extra"
+
+    local time = timeToBCD();
+    log.info("CurrentTime:       ",time)
+
+    local data = locRpt(0, 1, 12345678, 87654321, 100, 60, 180, time, "extra")
+    HexOutput(data)--[HexDataByteLength:]	33,[HexData is:       ]	000000000000000100bc614e05397fb10064003c00b42411241232046578747261
+    --输出解析:
+    --00000000,对应 0, 报警标志 DWORD,4字节
+    --00000001,对应 1, 状态位 DWORD
+    --00bc614e,对应 12345678, 纬度 DWORD
+    --05397fb1, 对应 87654321, 经度 DWORD
+    --0064,对应 100, 高程 WORD
+    --003c,对应60, 速度 WORD
+    --00b4,对应180, 方向 WORD
+    --241124123204,对应时间 BCD[6]  24-11-24-12-32-04
+    --6578747261,对应"extra"
+
+    --实验4:封闭一个完整的JT808注册数据帧
+    --输入参数:
+    --'018068821447',手机号不足 12位,则在前补充数字,大陆手机号补充数字 0
+    --'101',消息流水号
+    local data = encodeReg('018068821447','101')
+    HexOutput(data) --[HexDataByteLength:]	64
+                    --[HexData is:       ]	7e01000030018068821447313031000c007b3130303031475438303800000000000000000000000000000000000000000002003431303438303633323132627e
+
+    --输出解析:
+    --7e,标识位固定为0x7e
+    --0100,消息 ID
+    --0030,消息体属性
+    --018068821447,手机号
+    --313031,消息流水号
+    --000c007b3130303031475438303800000000000000000000000000000000000000000002003431303438303633323132,注册消息体
+    --62,校验
+    --7e,标识位固定为0x7e
+
+    --实验5:解析JT808终端注册应答数据帧
+    local hexStr = '7E8100000C0404571031660030003000736875616E67776569E07E'
+    decodeCmnRsp(hexStr)
+end)
+-- 这里演示4G模块上网后,会自动点亮网络灯,方便用户判断模块是否正常开机
+sys.taskInit(function()
+    while true do
+        sys.wait(6000)
+                if mobile.status() == 1 then
+                        gpio.set(27, 1)  
+                else
+                        gpio.set(27, 0) 
+                        mobile.reset()
+        end
+    end
+end)
+-- 用户代码已结束---------------------------------------------
+-- 运行lua task,只能调用一次,而且必须写在末尾
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 118 - 0
module/Air8000/demo/WebSocket/WebSocket-UART透传/main.lua

@@ -0,0 +1,118 @@
+
+PROJECT = "airtun"
+VERSION = "1.0.0"
+
+-- sys库是标配
+_G.sys = require("sys")
+-- _G.sysplus = require("sysplus")
+
+
+
+if wdt then
+    --添加硬狗防止程序卡死,在支持的设备上启用这个功能
+    wdt.init(9000)--初始化watchdog设置为9s
+    sys.timerLoopStart(wdt.feed, 3000)--3s喂一次狗
+end
+----------------------------------------
+-- 报错信息自动上报到平台,默认是iot.openluat.com
+-- 支持自定义, 详细配置请查阅API手册
+-- 开启后会上报开机原因, 这需要消耗流量,请留意
+if errDump then
+    errDump.config(true, 600)
+end
+----------------------------------------
+local tx_buff = zbuff.create(1024)      -- 发送至WebSocket服务器的数据
+local uart_rx_buff = zbuff.create(1024)     -- 串口接收到的数据
+local uartid = 1 -- 根据实际设备选取不同的uartid
+Sbuf = 0
+
+--初始化
+uart.setup(
+    uartid,--串口id
+    115200,--波特率
+    8,--数据位
+    1--停止位
+)
+
+local wsc = nil
+
+sys.taskInit(function()
+
+    sys.waitUntil("IP_READY")                -- 等待联网成功
+
+    -- 这是个测试服务, 当发送的是json,且action=echo,就会回显所发送的内容
+    -- 加密TCP链接 wss 表示加密
+    wsc = websocket.create(nil, "wss://echo.airtun.air32.cn/ws/echo")
+    -- 这是另外一个测试服务, 能响应websocket的二进制帧
+    -- wsc = websocket.create(nil, "ws://echo.airtun.air32.cn/ws/echo2")
+    -- 以上两个测试服务是Java写的, 源码在 https://gitee.com/openLuat/luatos-airtun/tree/master/server/src/main/java/com/luatos/airtun/ws
+
+    if wsc.headers then
+        wsc:headers({Auth="Basic ABCDEGG"})
+    end
+    wsc:autoreconn(true, 3000) -- 自动重连机制
+    wsc:on(function(wsc, event, data, fin, optcode)
+        --[[
+            event的值有:
+            conack 连接服务器成功,已经收到websocket协议头部信息,通信已建立
+            recv   收到服务器下发的信息, data, payload 不为nil
+            sent   send函数发送的消息,服务器在TCP协议层已确认收到
+            disconnect 服务器连接已断开
+
+            其中 sent/disconnect 事件在 2023.04.01 新增
+        ]]
+        -- data 当事件为recv是有接收到的数据
+        -- fin 是否为最后一个数据包, 0代表还有数据, 1代表是最后一个数据包
+        -- optcode, 0 - 中间数据包, 1 - 文本数据包, 2 - 二进制数据包
+        -- 因为lua并不区分文本和二进制数据, 所以optcode通常可以无视
+        -- 若数据不多, 小于1400字节, 那么fid通常也是1, 同样可以忽略
+        log.info("wsc", event, data, fin, optcode)
+        -- 显示二进制数据
+        -- log.info("wsc", event, data and data:toHex() or "", fin, optcode)
+        if event == "conack" then -- 连接websocket服务后, 会有这个事件
+            log.info("WebSocket connect succeed!")
+            sys.publish("wsc_conack")
+        end
+    end)
+    wsc:connect()
+    sys.waitUntil("wsc_conack")
+    while true do
+        uart.on(uartid, "receive", function(id, len)
+            while true do
+                local len = uart.rx(id, uart_rx_buff)   -- 接收串口收到的数据,并赋值到uart_rx_buff
+                if len <= 0 then    -- 接收到的字节长度为0 则退出
+                    break
+                else
+                    uart_rx_buff:seek(0)
+                    uart_rx_buff_data = uart_rx_buff:read(len)
+                    Sbuf = len
+                    log.info("UART接收的数据包",uart_rx_buff_data)
+                    break
+                end
+            end
+        end)
+
+        if Sbuf > 0 then
+            log.info("发送到服务器数据,长度",Sbuf)
+            log.info("UART发送到服务器的数据包 ",uart_rx_buff_data)
+            log.info("UART发送到服务器的数据包类型 ",type(uart_rx_buff_data))
+            if uart_rx_buff_data == '"echo"' then               -- 连接收到串口发送的"echo" ,会进行数据发送
+                log.info("UART透传成功 进行数据发送")
+                wsc:send(json.encode({action="echo", msg=os.date()})) ---发送数据
+            end
+        end
+        Sbuf = 0
+        uart_rx_buff:del()                      -- 清除串口buff的数据长度
+        sys.wait(1000) 
+    end
+
+    wsc:close()
+    wsc = nil
+
+end)
+
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 79 - 0
module/Air8000/demo/WebSocket/WebSocket加密通讯/main.lua

@@ -0,0 +1,79 @@
+
+PROJECT = "airtun"
+VERSION = "1.0.0"
+
+-- sys库是标配
+_G.sys = require("sys")
+-- _G.sysplus = require("sysplus")
+
+
+
+----------------------------------------
+-- 报错信息自动上报到平台,默认是iot.openluat.com
+-- 支持自定义, 详细配置请查阅API手册
+-- 开启后会上报开机原因, 这需要消耗流量,请留意
+if errDump then
+    errDump.config(true, 600)
+end
+----------------------------------------
+
+local wsc = nil
+
+sys.taskInit(function()
+
+    sys.waitUntil("IP_READY")                -- 等待联网成功
+
+    -- 这是个测试服务, 当发送的是json,且action=echo,就会回显所发送的内容
+    -- 加密TCP链接 wss 表示加密
+    wsc = websocket.create(nil, "wss://echo.airtun.air32.cn/ws/echo")
+    -- 这是另外一个测试服务, 能响应websocket的二进制帧
+    -- wsc = websocket.create(nil, "ws://echo.airtun.air32.cn/ws/echo2")
+    -- 以上两个测试服务是Java写的, 源码在 https://gitee.com/openLuat/luatos-airtun/tree/master/server/src/main/java/com/luatos/airtun/ws
+
+    if wsc.headers then
+        wsc:headers({Auth="Basic ABCDEGG"})
+    end
+    wsc:autoreconn(true, 3000) -- 自动重连机制
+    wsc:on(function(wsc, event, data, fin, optcode)
+        --[[
+            event的值有:
+            conack 连接服务器成功,已经收到websocket协议头部信息,通信已建立
+            recv   收到服务器下发的信息, data, payload 不为nil
+            sent   send函数发送的消息,服务器在TCP协议层已确认收到
+            disconnect 服务器连接已断开
+
+            其中 sent/disconnect 事件在 2023.04.01 新增
+        ]]
+        -- data 当事件为recv是有接收到的数据
+        -- fin 是否为最后一个数据包, 0代表还有数据, 1代表是最后一个数据包
+        -- optcode, 0 - 中间数据包, 1 - 文本数据包, 2 - 二进制数据包
+        -- 因为lua并不区分文本和二进制数据, 所以optcode通常可以无视
+        -- 若数据不多, 小于1400字节, 那么fid通常也是1, 同样可以忽略
+        log.info("wsc", event, data, fin, optcode)
+        -- 显示二进制数据
+        -- log.info("wsc", event, data and data:toHex() or "", fin, optcode)
+        if event == "conack" then -- 连接websocket服务后, 会有这个事件
+            log.info("WebSocket connect succeed!")
+            sys.publish("wsc_conack")
+        end
+    end)
+    wsc:connect()
+    -- 等待conack是可选的
+    sys.waitUntil("wsc_conack")
+    --local stat = wsc:ready()
+    -- 定期发业务ping也是可选的, 但为了保存连接, 也为了继续持有wsc对象, 这里周期性发数据
+    while true do
+        wsc:send((json.encode({action="echo", msg=os.date()})))
+        sys.wait(15000)
+        -- 发送二进制帧, 2023.06.21 之后编译的固件支持
+        -- wsc:send(string.char(0xA5, 0x5A, 0xAA, 0xF2), 1, 1)
+    end
+    wsc:close()
+    wsc = nil
+end)
+
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 24 - 0
module/Air8000/demo/adc/main.lua

@@ -0,0 +1,24 @@
+
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "adcdemo"
+VERSION = "1.0.0"
+
+log.info("main", PROJECT, VERSION)
+
+-- 一定要添加sys.lua !!!!
+sys = require("sys")
+
+-- 添加硬狗防止程序卡死
+if wdt then
+    wdt.init(9000) -- 初始化watchdog设置为9s
+    sys.timerLoopStart(wdt.feed, 3000) -- 3s喂一次狗
+end
+
+local testAdc = require "testAdc"
+sys.taskInit(testAdc.dotest)
+
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 66 - 0
module/Air8000/demo/adc/testAdc.lua

@@ -0,0 +1,66 @@
+
+--[[
+
+8. Air8000内部ADC接口为12bits 外部直流分压为0-3.4V
+9. Air8000内部具有2个ADC接口,ADC0 -- AIO3 ADC1 -- AIO4
+10. 特殊通道, CPU内部温度Temp -- adc.CH_CPU 主供电脚电压 VBAT -- adc.CH_VBAT
+11. 设置分压(adc.setRange)要在adc.open之前设置,否则无效!!
+]]
+
+local testAdc = {}
+
+-- adc.setRange(adc.ADC_RANGE_1_2) -- 关闭分压
+adc.setRange(adc.ADC_RANGE_MAX) -- 启用分压
+
+local rtos_bsp = rtos.bsp()
+function adc_pin() -- 根据不同开发板,设置ADC编号
+    if rtos_bsp == "EC618" then --Air8000开发板ADC编号
+        -- 默认不开启分压,范围是0-1.2v精度高
+        -- 设置分压要在adc.open之前设置,否则无效!!
+        -- adc.setRange(adc.ADC_RANGE_3_8)
+        return 0,1,255,255,adc.CH_CPU ,adc.CH_VBAT
+    else
+        log.info("main", "define ADC pin in main.lua")
+        return 0,1,255,255, adc.CH_CPU ,adc.CH_VBAT
+    end
+end
+local adc_pin_0,adc_pin_1,adc_pin_2,adc_pin_3,adc_pin_temp,adc_pin_vbat=adc_pin()
+
+
+function testAdc.dotest()
+    if adc_pin_0 and adc_pin_0 ~= 255 then adc.open(adc_pin_0) end
+    if adc_pin_1 and adc_pin_1 ~= 255 then adc.open(adc_pin_1) end
+    if adc_pin_2 and adc_pin_2 ~= 255 then adc.open(adc_pin_2) end
+    if adc_pin_3 and adc_pin_3 ~= 255 then adc.open(adc_pin_3) end
+    if adc_pin_temp and adc_pin_temp ~= 255 then adc.open(adc_pin_temp) end
+    if adc_pin_vbat and adc_pin_vbat ~= 255 then adc.open(adc_pin_vbat) end
+
+    -- 下面是循环打印, 接地不打印0也是正常现象
+    -- ADC的精度都不会太高, 若需要高精度ADC, 建议额外添加adc芯片
+    while true do
+        if adc_pin_0 and adc_pin_0 ~= 255 then --adc0
+            log.debug("adc", "adc" .. tostring(adc_pin_0), adc.read(adc_pin_0)) -- 若adc.get报nil, 改成adc.read
+        end
+        if adc_pin_1 and adc_pin_1 ~= 255 then --adc1
+            log.debug("adc", "adc" .. tostring(adc_pin_1), adc.get(adc_pin_1))
+        end
+        if adc_pin_temp and adc_pin_temp ~= 255 then
+            log.debug("adc", "CPU TEMP", adc.get(adc_pin_temp))
+        end
+        if adc_pin_vbat and adc_pin_vbat ~= 255 then
+            log.debug("adc", "VBAT", adc.get(adc_pin_vbat))
+        end
+        sys.wait(1000)
+    end
+
+    -- 若不再读取, 可关掉adc, 降低功耗, 非必须
+    if adc_pin_0 and adc_pin_0 ~= 255 then adc.close(adc_pin_0) end
+    if adc_pin_1 and adc_pin_1 ~= 255 then adc.close(adc_pin_1) end
+    if adc_pin_2 and adc_pin_2 ~= 255 then adc.close(adc_pin_2) end
+    if adc_pin_3 and adc_pin_3 ~= 255 then adc.close(adc_pin_3) end
+    if adc_pin_temp and adc_pin_temp ~= 255 then adc.close(adc_pin_temp) end
+    if adc_pin_vbat and adc_pin_vbat ~= 255 then adc.close(adc_pin_vbat) end
+
+end
+
+return testAdc

+ 90 - 0
module/Air8000/demo/airlbs/main.lua

@@ -0,0 +1,90 @@
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "paid_lbs"
+VERSION = "1.0.0"
+
+-- 使用合宙iot平台时需要这个参数
+PRODUCT_KEY = "xxx" -- 到 iot.openluat.com 创建项目,获取正确的项目id
+
+-- 引入必要的库文件(lua编写), 内部库不需要require
+sys = require("sys")
+sysplus = require("sysplus")
+libnet = require "libnet"
+
+log.info("main", PROJECT, VERSION)
+
+if wdt then
+    -- 添加硬狗防止程序卡死,在支持的设备上启用这个功能
+    wdt.init(20000) -- 初始化watchdog设置为9s
+    sys.timerLoopStart(wdt.feed, 3000) -- 3s喂一次狗
+end
+
+local airlbs = require "airlbs"
+
+local timeout = 60 -- 扫描基站/wifi 做 基站/wifi定位 的超时时间,最小5S,最大60S
+
+-- 此为收费服务,需自行联系销售申请
+local airlbs_project_id = ""
+local airlbs_project_key = ""
+
+-- --多基站定位
+-- sys.taskInit(function()
+--     sys.waitUntil("IP_READY") -- 等待底层上报联网成功
+--     socket.sntp() -- 进行NTP授时,放置部分联通卡没有基站授时
+--     sys.waitUntil("NTP_UPDATE", 1000)
+--     while 1 do
+--         if airlbs_project_id and airlbs_project_key then
+--             local result, data = airlbs.request({
+--                 project_id = airlbs_project_id,
+--                 project_key = airlbs_project_key,
+--                 timeout = timeout * 1000 -- 实际的超时时间(单位:ms)
+--             })
+--             if result then
+--                 log.info("airlbs多基站定位返回的经纬度数据为", json.encode(data))
+--             end
+--         else
+--             log.warn("请检查project_id和project_key")
+--         end
+--         sys.wait(20000)
+--     end
+
+-- end)
+
+-- wifi/基站混合定位
+sys.taskInit(function()
+    sys.waitUntil("IP_READY")
+    -- 如需wifi定位,需要硬件以及固件支持wifi扫描功能
+    local wifi_info = nil
+    if wlan then
+        sys.wait(3000) -- 网络可用后等待一段时间才再调用wifi扫描功能,否则可能无法获取wifi信息
+        wlan.init()
+        wlan.scan()
+        sys.waitUntil("WLAN_SCAN_DONE", timeout * 1000)
+        wifi_info = wlan.scanResult()
+        log.info("scan", "wifi_info", #wifi_info)
+    end
+
+    socket.sntp()
+    sys.waitUntil("NTP_UPDATE", 1000)
+
+    while 1 do
+        local result, data = airlbs.request({
+            project_id = airlbs_project_id,
+            project_key = airlbs_project_key,
+            wifi_info = wifi_info,
+            timeout = timeout * 1000
+        })
+        if result then
+                log.info("airlbs多基站定位返回的经纬度数据为", json.encode(data))
+        else
+            log.warn("请检查project_id和project_key")
+        end
+        sys.wait(20000) -- 循环20S一次wifi定位
+    end
+
+end)
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!
+

+ 48 - 0
module/Air8000/demo/bit/main.lua

@@ -0,0 +1,48 @@
+
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "bit64_test"
+VERSION = "1.0.0"
+
+log.info("main", PROJECT, VERSION)
+
+-- 引入必要的库文件(lua编写), 内部库不需要require
+sys = require("sys")
+
+
+
+if wdt then
+    --添加硬狗防止程序卡死,在支持的设备上启用这个功能
+    wdt.init(9000)--初始化watchdog设置为9s
+    sys.timerLoopStart(wdt.feed, 3000)--3s喂一次狗
+end
+
+
+
+local function log_bit()
+        log.info("按位取反,输出-6",bit.bnot(5))
+        log.info("与,--输出1",bit.band(1,1))
+        log.info("或,--输出3",bit.bor(1,2))
+        log.info("异或结果为4",bit.bxor(2,3,5))
+        log.info("逻辑左移,“100”,输出为4",bit.lshift(1,2))
+
+        log.info("逻辑右移,“001”,输出为1",bit.rshift(4,2))
+        log.info("算数右移,左边添加的数与符号有关,输出为0",bit.arshift(2,2))
+        log.info("参数是位数,作用是1向左移动两位,打印出4",bit.bit(2))
+        log.info("测试位数是否被置1",bit.isset(5,0))--第一个参数是是测试数字,第二个是测试位置.从右向左数0到7.是1返回true,否则返回false,该返回true
+        log.info("测试位数是否被置1",bit.isset(5,1))--打印false
+        log.info("测试位数是否被置1",bit.isset(5,2))--打印true
+        log.info("测试位数是否被置1",bit.isset(5,3))--返回返回false
+        log.info("测试位数是否被置0",bit.isclear(5,0))----与上面的相反
+        log.info("测试位数是否被置0",bit.isclear(5,1))
+        log.info("测试位数是否被置0",bit.isclear(5,2))
+        log.info("测试位数是否被置0",bit.isclear(5,3))
+        log.info("把0的第0,1,2,3位值为1",bit.set(0,0,1,2,3))--在相应的位数置1,打印15
+        log.info("把5的第0,2位置为0",bit.clear(5,0,2))--在相应的位置置0,打印0
+end
+
+sys.taskInit(log_bit)
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 110 - 0
module/Air8000/demo/bit64/main.lua

@@ -0,0 +1,110 @@
+
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "bit64_test"
+VERSION = "1.0.0"
+
+log.info("main", PROJECT, VERSION)
+
+-- 引入必要的库文件(lua编写), 内部库不需要require
+sys = require("sys")
+
+
+
+if wdt then
+    --添加硬狗防止程序卡死,在支持的设备上启用这个功能
+    wdt.init(9000)--初始化watchdog设置为9s
+    sys.timerLoopStart(wdt.feed, 3000)--3s喂一次狗
+end
+
+
+local data,b64,b32,a,b
+
+if bit64 then
+	log.style(1)
+	log.info("bit64 演示")
+	data = 12345678
+	b64 = bit64.to64(data)
+	b32 = bit64.to32(b64)
+	log.info("i32", b32, mcu.x32(b32))
+	data = -12345678
+	b64 = bit64.to64(data)
+	b32 = bit64.to32(b64)
+	log.info("i32", b32, mcu.x32(b32))
+	data = 12.34234
+	b64 = bit64.to64(data)
+	b32 = bit64.to32(b64)
+	log.info("f32", data, b32)
+	data = -12.34234
+	b64 = bit64.to64(data)
+	b32 = bit64.to32(b64)
+	log.info("f32", data, b32)
+
+
+	a = bit64.to64(87654321)
+	b = bit64.to64(12345678)
+	log.info("87654321+12345678=", bit64.show(bit64.plus(a,b)))
+	log.info("87654321-12345678=", bit64.show(bit64.minus(a,b)))
+	log.info("87654321*12345678=", bit64.show(bit64.multi(a,b)))
+	log.info("87654321/12345678=", bit64.show(bit64.pide(a,b)))
+
+	a = bit64.to64(87654321)
+	b = 1234567
+	log.info("87654321+1234567=", bit64.show(bit64.plus(a,b)))
+	log.info("87654321-1234567=", bit64.show(bit64.minus(a,b)))
+	log.info("87654321*1234567=", bit64.show(bit64.multi(a,b)))
+	log.info("87654321/1234567=", bit64.show(bit64.pide(a,b)))
+
+
+	a = bit64.to64(87654.326)
+	b = bit64.to64(12345)
+	log.info("87654.326+12345=", 87654.326 + 12345)
+	log.info("87654.326+12345=", bit64.show(bit64.plus(a,b)))
+	log.info("87654.326-12345=", bit64.show(bit64.minus(a,b)))
+	log.info("87654.326*12345=", bit64.show(bit64.multi(a,b)))
+	log.info("87654.326/12345=", bit64.show(bit64.pide(a,b)))
+
+	a = bit64.to64(87654.32)
+	b = bit64.to64(12345.67)
+	log.info("float", "87654.32+12345.67=", 87654.32 + 12345.67)
+	log.info("double","87654.32+12345.67=", bit64.show(bit64.plus(a,b)))
+	log.info("double to float","87654.32+12345.67=", bit64.to32(bit64.plus(a,b)))
+	log.info("87654.32-12345.67=", bit64.show(bit64.minus(a,b)))
+	log.info("87654.32*12345.67=", bit64.show(bit64.multi(a,b)))
+	log.info("87654.32/12345.67=", bit64.show(bit64.pide(a,b)))
+	log.info("double to int64", "87654.32/12345.67=", bit64.show(bit64.pide(a,b,nil,true)))
+
+	a = bit64.to64(0xc0000000)
+	b = 2
+	a = bit64.shift(a,8,true)
+	log.info("0xc0000000 << 8 =", bit64.show(a, 16))
+	log.info("0xc000000000+2=", bit64.show(bit64.plus(a,b), 16))
+	log.info("0xc000000000-2=", bit64.show(bit64.minus(a,b), 16))
+	log.info("0xc000000000*2=", bit64.show(bit64.multi(a,b), 16))
+	log.info("0xc000000000/2=", bit64.show(bit64.pide(a,b), 16))
+	log.style(0)
+
+	if bit64.strtoll then
+		local data = bit64.strtoll("864040064024194", 10)
+		log.info("data", data:toHex())
+		log.info("data", bit64.show(data))
+	end
+end
+
+local function sys_run_time()
+	local tick64, per = mcu.tick64(true)
+	local per_cnt = per * 1000000
+	while true do
+		tick64, per = mcu.tick64(true)
+		log.info("work time","当前时间", bit64.to32(bit64.pide(tick64,per_cnt)))
+		sys.wait(1000)
+	end
+end
+
+if mcu.tick64 then
+	sys.taskInit(sys_run_time)
+end
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 73 - 0
module/Air8000/demo/can/main.lua

@@ -0,0 +1,73 @@
+PROJECT = "candemo"
+VERSION = "1.0.0"
+sys = require("sys")
+log.style(1)
+local SELF_TEST_FLAG = false --自测模式标识,写true就进行自收自发模式,写false就进行正常收发模式
+local node_a = false   -- A节点写true, B节点写false
+local can_id = 0
+local rx_id
+local tx_id
+local stb_pin = 27		-- stb引脚根据实际情况写,不用的话,也可以不写
+if node_a then          -- A/B节点区分,互相传输测试
+    rx_id = 0x12345678
+    tx_id = 0x12345677
+else
+    rx_id = 0x12345677
+    tx_id = 0x12345678
+end
+local test_cnt = 0
+local tx_buf = zbuff.create(8)  --创建zbuff
+local function can_cb(id, cb_type, param)
+    if cb_type == can.CB_MSG then
+        log.info("有新的消息")
+        local succ, id, id_type, rtr, data = can.rx(id)
+        while succ do
+            log.info(mcu.x32(id), #data, data:toHex())
+            succ, id, id_type, rtr, data = can.rx(id)
+        end
+    end
+    if cb_type == can.CB_TX then
+        if param then
+            log.info("发送成功")
+        else
+            log.info("发送失败")
+        end
+    end
+    if cb_type == can.CB_ERR then
+        log.info("CAN错误码", mcu.x32(param))
+    end
+    if cb_type == can.CB_STATE then
+        log.info("CAN新状态", param)
+    end
+end
+
+local function can_tx_test(data)
+    if node_a then
+        log.info("node a tx")
+    else
+        log.info("node b tx")
+    end
+	test_cnt = test_cnt + 1
+	if test_cnt > 8 then
+		test_cnt = 1
+	end
+	tx_buf:set(0,test_cnt)  --zbuff的类似于memset操作,类似于memset(&buff[start], num, len)
+	tx_buf:seek(test_cnt)   --zbuff设置光标位置(可能与当前指针位置有关;执行后指针会被设置到指定位置)
+    can.tx(can_id, tx_id, can.EXT, false, true, tx_buf)
+end
+-- can.debug(true)
+gpio.setup(stb_pin,0)   -- 配置STB引脚为输出低电平
+-- gpio.setup(stb_pin,1)	-- 如果开发板上STB信号有逻辑取反,则要配置成输出高电平
+
+can.init(can_id, 128)            -- 初始化CAN,参数为CAN ID,接收缓存消息数的最大值
+can.on(can_id, can_cb)            -- 注册CAN的回调函数
+can.timing(can_id, 1000000, 5, 4, 3, 2)     --CAN总线配置时序
+if SELF_TEST_FLAG then
+	can.node(can_id, tx_id, can.EXT)	-- 测试模式下,允许接收的ID和发送ID一致才会有新数据提醒
+	can.mode(can_id, can.MODE_TEST)     -- 如果只是自身测试硬件好坏,可以用测试模式来验证,如果发送成功就OK
+else
+	can.node(can_id, rx_id, can.EXT)
+	can.mode(can_id, can.MODE_NORMAL)   -- 一旦设置mode就开始正常工作了,此时不能再设置node,timing,filter等
+end
+sys.timerLoopStart(can_tx_test, 2000)
+sys.run()

BIN
module/Air8000/demo/crypto/logo.jpg


+ 238 - 0
module/Air8000/demo/crypto/main.lua

@@ -0,0 +1,238 @@
+
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "cryptodemo"
+VERSION = "1.0.0"
+
+log.info("main", PROJECT, VERSION)
+
+-- sys库是标配
+_G.sys = require("sys")
+
+
+
+if wdt then
+    --添加硬狗防止程序卡死,在支持的设备上启用这个功能
+    wdt.init(9000)--初始化watchdog设置为9s
+    sys.timerLoopStart(wdt.feed, 3000)--3s喂一次狗
+end
+
+sys.taskInit(function()
+
+    sys.wait(1000)
+
+    -- MD5,输出结果已经hex编码
+    log.info("md5", crypto.md5("abc"))
+    log.info("hmac_md5", crypto.hmac_md5("abc", "1234567890"))
+
+    -- SHA1,输出结果已经hex编码
+    log.info("sha1", crypto.sha1("abc"))
+    log.info("hmac_sha1", crypto.hmac_sha1("abc", "1234567890"))
+
+    -- SHA256,输出结果已经hex编码
+    log.info("sha256", crypto.sha256("abc"))
+    log.info("hmac_sha256", crypto.hmac_sha256("abc", "1234567890"))
+
+    -- SHA512,输出结果已经hex编码
+    log.info("sha512", crypto.sha512("abc"))
+    log.info("hmac_sha512", crypto.hmac_sha512("abc", "1234567890"))
+
+	local data_encrypt = crypto.cipher_encrypt("AES-128-ECB", "ZERO", "023001", "HZBIT@WLW/YSBKEY")
+	log.info("AES", "aes-128-ecb", data_encrypt:toHex())
+	local data_decrypt = crypto.cipher_decrypt("AES-128-ECB", "ZERO", data_encrypt, "HZBIT@WLW/YSBKEY")
+	log.info("AES", "aes-128-ecb", data_decrypt)
+
+    -- AES加密, 未经Hex编码. AES-128-ECB 算法,待加密字符串如果超过32字节会报错,待查. by wendal 20200812
+    local data_encrypt = crypto.cipher_encrypt("AES-128-ECB", "PKCS7", "12345678901234 > 123456", "1234567890123456")
+    local data2_encrypt = crypto.cipher_encrypt("AES-128-CBC", "PKCS7", "12345678901234 > 123456", "1234567890123456", "1234567890666666")
+    log.info("AES", "aes-128-ecb", data_encrypt:toHex())
+    log.info("AES", "aes-128-cbc", data2_encrypt:toHex())
+
+    -- AES解密, 未经Hex编码
+    local data_decrypt = crypto.cipher_decrypt("AES-128-ECB", "PKCS7", data_encrypt, "1234567890123456")
+    local data2_decrypt = crypto.cipher_decrypt("AES-128-CBC", "PKCS7", data2_encrypt, "1234567890123456", "1234567890666666")
+    log.info("AES", "aes-128-ecb", data_decrypt)
+    log.info("AES", "aes-128-cbc", data2_decrypt)
+    log.info("mem", rtos.meminfo("sys"))
+
+    -- DES-ECB 加解密
+    local data1 = crypto.cipher_encrypt("DES-ECB", "PKCS7", "abcdefg", "12345678")
+    if data1 then -- DES-ECB 在某些平台不支持的
+        log.info("des", data1:toHex())
+        local data2 = crypto.cipher_decrypt("DES-ECB", "PKCS7", data1, "12345678")
+        log.info("des", data2)
+    else
+        log.info("des", "当前固件不支持DES/3DES")
+    end
+
+    -- 3DES-ECB 加解密
+    local data1 = crypto.cipher_encrypt("DES-EDE3-ECB", "PKCS7", "abcdefg!!--ZZSS", "123456781234567812345678")
+    if data1 then -- DES-ECB 在某些平台不支持的
+        log.info("3des", data1:toHex())
+        local data2 = crypto.cipher_decrypt("DES-EDE3-ECB", "PKCS7", data1, "123456781234567812345678")
+        log.info("3des", data2)
+    else
+        log.info("3des", "当前固件不支持DES/3DES")
+    end
+
+
+    -- 打印所有支持的cipher
+    if crypto.cipher_list then
+        log.info("cipher", "list", json.encode(crypto.cipher_list()))
+    else
+        log.info("cipher", "当前固件不支持crypto.cipher_list")
+    end
+    -- 打印所有支持的cipher suites
+    if crypto.cipher_suites then
+        log.info("cipher", "suites", json.encode(crypto.cipher_suites()))
+    else
+        log.info("cipher", "当前固件不支持crypto.cipher_suites")
+    end
+
+    ---------------------------------------
+    log.info("随机数测试")
+    for i=1, 10 do
+        sys.wait(100)
+        log.info("crypto", "真随机数",string.unpack("I",crypto.trng(4)))
+        -- log.info("crypto", "伪随机数",math.random()) -- 输出的是浮点数,不推荐
+        -- log.info("crypto", "伪随机数",math.random(1, 65525)) -- 不推荐
+    end
+
+    -- totp的密钥
+    log.info("totp的密钥")
+    local secret = "VK54ZXPO74ISEM2E"
+    --写死时间戳用来测试
+    local ts = 1646796576
+    --生成十分钟的动态码验证下
+    for i=1,600,30 do
+        local r = crypto.totp(secret,ts+i)
+        local time = os.date("*t",ts+i + 8*3600)--东八区
+        log.info("totp", string.format("%06d" ,r),time.hour,time.min,time.sec)
+    end
+
+    -- 文件测试
+    log.info("文件hash值测试")
+    if crypto.md_file then
+        log.info("md5", crypto.md_file("MD5", "/luadb/logo.jpg"))
+        log.info("sha1", crypto.md_file("SHA1", "/luadb/logo.jpg"))
+        log.info("sha256", crypto.md_file("SHA256", "/luadb/logo.jpg"))
+        
+        log.info("hmac_md5", crypto.md_file("MD5", "/luadb/logo.jpg", "123456"))
+        log.info("hmac_sha1", crypto.md_file("SHA1", "/luadb/logo.jpg", "123456"))
+        log.info("hmac_sha256", crypto.md_file("SHA256", "/luadb/logo.jpg", "123456"))
+    else
+        log.info("文件hash值测试", "当前固件不支持crypto.md_file")
+    end
+
+    if crypto.checksum then
+        log.info("checksum", "OK", string.char(crypto.checksum("OK")):toHex())
+        log.info("checksum", "357E", string.char(crypto.checksum("357E", 1)):toHex())
+    else
+        log.info("checksum", "当前固件不支持crypto.checksum")
+    end
+
+    -- 流式hash测试
+    log.info("流式hash测试")
+    if crypto.hash_init then
+        -- MD5
+        local md5_obj = crypto.hash_init("MD5")
+        crypto.hash_update(md5_obj, "1234567890")
+        crypto.hash_update(md5_obj, "1234567890")
+        crypto.hash_update(md5_obj, "1234567890")
+        crypto.hash_update(md5_obj, "1234567890")
+        local md5_result = crypto.hash_finish(md5_obj)
+        log.info("md5_stream", md5_result)
+        log.info("md5", crypto.md5("1234567890123456789012345678901234567890"))
+
+        -- HMAC_MD5
+        local hmac_md5_obj = crypto.hash_init("MD5", "1234567890")
+        crypto.hash_update(hmac_md5_obj, "1234567890")
+        crypto.hash_update(hmac_md5_obj, "1234567890")
+        crypto.hash_update(hmac_md5_obj, "1234567890")
+        crypto.hash_update(hmac_md5_obj, "1234567890")
+        local hmac_md5_result = crypto.hash_finish(hmac_md5_obj)
+        log.info("hmac_md5_stream", hmac_md5_result)
+        log.info("hmac_md5", crypto.hmac_md5("1234567890123456789012345678901234567890", "1234567890"))
+
+        -- SHA1
+        local sha1_obj = crypto.hash_init("SHA1")
+        crypto.hash_update(sha1_obj, "1234567890")
+        crypto.hash_update(sha1_obj, "1234567890")
+        crypto.hash_update(sha1_obj, "1234567890")
+        crypto.hash_update(sha1_obj, "1234567890")
+        local sha1_result = crypto.hash_finish(sha1_obj)
+        log.info("sha1_stream", sha1_result)
+        log.info("sha1", crypto.sha1("1234567890123456789012345678901234567890"))
+
+        -- HMAC_SHA1
+        local hmac_sha1_obj = crypto.hash_init("SHA1", "1234567890")
+        crypto.hash_update(hmac_sha1_obj, "1234567890")
+        crypto.hash_update(hmac_sha1_obj, "1234567890")
+        crypto.hash_update(hmac_sha1_obj, "1234567890")
+        crypto.hash_update(hmac_sha1_obj, "1234567890")
+        local hmac_sha1_result = crypto.hash_finish(hmac_sha1_obj)
+        log.info("hmac_sha1_stream", hmac_sha1_result)
+        log.info("hmac_sha1", crypto.hmac_sha1("1234567890123456789012345678901234567890", "1234567890"))
+
+        -- SHA256
+        local sha256_obj = crypto.hash_init("SHA256")
+        crypto.hash_update(sha256_obj, "1234567890")
+        crypto.hash_update(sha256_obj, "1234567890")
+        crypto.hash_update(sha256_obj, "1234567890")
+        crypto.hash_update(sha256_obj, "1234567890")
+        local sha256_result = crypto.hash_finish(sha256_obj)
+        log.info("sha256_stream", sha256_result)
+        log.info("sha256", crypto.sha256("1234567890123456789012345678901234567890"))
+
+        -- HMAC_SHA256
+        local hmac_sha256_obj = crypto.hash_init("SHA256", "1234567890")
+        crypto.hash_update(hmac_sha256_obj, "1234567890")
+        crypto.hash_update(hmac_sha256_obj, "1234567890")
+        crypto.hash_update(hmac_sha256_obj, "1234567890")
+        crypto.hash_update(hmac_sha256_obj, "1234567890")
+        local hmac_sha256_result = crypto.hash_finish(hmac_sha256_obj)
+        log.info("hmac_sha256_stream", hmac_sha256_result)
+        log.info("hmac_sha256", crypto.hmac_sha256("1234567890123456789012345678901234567890", "1234567890"))
+
+        -- SHA512
+        local sha512_obj = crypto.hash_init("SHA512")
+        if sha512_obj then
+            crypto.hash_update(sha512_obj, "1234567890")
+            crypto.hash_update(sha512_obj, "1234567890")
+            crypto.hash_update(sha512_obj, "1234567890")
+            crypto.hash_update(sha512_obj, "1234567890")
+            local sha512_result = crypto.hash_finish(sha512_obj)
+            log.info("sha512_stream", sha512_result)
+            log.info("sha512", crypto.sha512("1234567890123456789012345678901234567890"))
+        end
+
+        -- HMAC_SHA512
+        local hmac_sha512_obj = crypto.hash_init("SHA512", "1234567890")
+        if hmac_sha512_obj then
+            crypto.hash_update(hmac_sha512_obj, "1234567890")
+            crypto.hash_update(hmac_sha512_obj, "1234567890")
+            crypto.hash_update(hmac_sha512_obj, "1234567890")
+            crypto.hash_update(hmac_sha512_obj, "1234567890")
+            local hmac_sha512_result = crypto.hash_finish(hmac_sha512_obj)
+            log.info("hmac_sha512_stream", hmac_sha512_result)
+            log.info("hmac_sha512", crypto.hmac_sha512("1234567890123456789012345678901234567890", "1234567890"))
+        end
+    else
+        log.info("crypto", "当前固件不支持crypto.hash_init")
+    end
+
+    log.info("crc7测试")
+    if crypto.crc7 then
+        local result = crypto.crc7(string.char(0xAA), 0xE5, 0x00)
+        log.info("crc7测试", result, string.format("%02X", result))
+    else
+        log.info("crypto", "当前固件不支持crypto.crc7")
+    end
+
+    log.info("crypto", "ALL Done")
+    sys.wait(100000)
+end)
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 62 - 0
module/Air8000/demo/errDump/main.lua

@@ -0,0 +1,62 @@
+PROJECT = "errdump_test"
+VERSION = "1.0"
+PRODUCT_KEY = "s1uUnY6KA06ifIjcutm5oNbG3MZf5aUv" --换成自己的
+-- sys库是标配
+_G.sys = require("sys")
+_G.sysplus = require("sysplus")
+log.style(1)
+
+--下面演示自动发送
+-- errDump.config(true, 600, "user_id")	-- 默认是关闭,用这个可以额外添加用户标识,比如用户自定义的ID之类
+
+-- local function test_user_log()
+-- 	while true do
+-- 		sys.wait(15000)
+-- 		errDump.record("测试一下用户的记录功能")
+-- 	end
+-- end
+
+-- local function test_error_log()
+-- 	sys.wait(60000)
+-- 	-- lllllllllog.record("测试一下用户的记录功能") --默认写错代码死机
+-- end
+
+
+
+-- 下面演示手动获取信息
+errDump.config(true, 0)
+local function test_user_log()
+	local buff = zbuff.create(4096)
+	local new_flag = errDump.dump(buff, errDump.TYPE_SYS)		-- 开机手动读取一次异常日志
+	if buff:used() > 0 then
+		log.info(buff:toStr(0, buff:used()))	-- 打印出异常日志
+	end
+	new_flag = errDump.dump(buff, errDump.TYPE_SYS)
+	if not new_flag then
+		log.info("没有新数据了,删除系统错误日志")
+		errDump.dump(nil, errDump.TYPE_SYS, true)
+	end
+	while true do
+		sys.wait(15000)
+		errDump.record("测试一下用户的记录功能")
+		local new_flag = errDump.dump(buff, errDump.TYPE_USR)
+		if new_flag then
+			log.info("errBuff", buff:toStr(0, buff:used()))
+		end
+		new_flag = errDump.dump(buff, errDump.TYPE_USR)
+		if not new_flag then
+			log.info("没有新数据了,删除用户错误日志")
+			errDump.dump(nil, errDump.TYPE_USR, true)
+		end
+
+	end
+end
+
+local function test_error_log()
+	sys.wait(60000)
+	lllllllllog.record("测试一下用户的记录功能") --默认写错代码死机
+end
+
+sys.taskInit(test_user_log)
+sys.taskInit(test_error_log)
+sys.run()

+ 101 - 0
module/Air8000/demo/fota2/main.lua

@@ -0,0 +1,101 @@
+
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "fotademo"
+-- iot限制,只能上传xxx.yyy.zzz格式的三位数的版本号,但实际上现在只用了XXX和ZZZ,中间yyy暂未使用
+-- 需要注意的是,因为yyy不生效,所以111.222.333版本和111.444.333版本,对iot平台来说都一样,所以建议中间那一位永远写000
+VERSION = "001.000.000"
+
+-- 使用合宙iot平台时需要这个参数
+PRODUCT_KEY = "123" -- 到 iot.openluat.com 创建项目,获取正确的项目id
+
+sys = require "sys"
+libfota2 = require "libfota2"
+
+-- 联网函数, 可自行删减
+sys.taskInit(function()
+    -- 默认都等到联网成功
+    sys.waitUntil("IP_READY")
+    log.info("4G网络链接成功")
+    sys.publish("net_ready")
+end)
+
+-- 循环打印版本号, 方便看版本号变化, 非必须
+sys.taskInit(function()
+    while 1 do
+        sys.wait(5000)
+        log.info("降功耗 找合宙")
+        -- log.info("fota", "脚本版本号", VERSION)
+        log.info("fota", "脚本版本号", VERSION, "core版本号", rtos.version())
+    end
+end)
+
+-- 升级结果的回调函数
+-- 功能:获取fota的回调函数
+-- 参数:
+-- result:number类型
+--   0表示成功
+--   1表示连接失败
+--   2表示url错误
+--   3表示服务器断开
+--   4表示接收报文错误
+--   5表示使用iot平台VERSION需要使用 xxx.yyy.zzz形式
+local function fota_cb(ret)
+    log.info("fota", ret)
+    if ret == 0 then
+        log.info("升级包下载成功,重启模块")
+        rtos.reboot()
+    elseif ret == 1 then
+        log.info("连接失败", "请检查url拼写或服务器配置(是否为内网)")
+    elseif ret == 2 then
+        log.info("url错误", "检查url拼写")
+    elseif ret == 3 then
+        log.info("服务器断开", "检查服务器白名单配置")
+    elseif ret == 4 then
+        log.info("接收报文错误", "检查模块固件或升级包内文件是否正常")
+    elseif ret == 5 then
+        log.info("版本号书写错误", "iot平台版本号需要使用xxx.yyy.zzz形式")
+    else
+        log.info("不是上面几种情况 ret为", ret)
+    end
+end
+
+local ota_opts = {}
+
+-- 使用合宙iot平台进行升级,不需要管下面这段代码
+-- 使用第三方服务器时打开下面这段代码
+--[[local ota_opts = {
+    url = "", 
+    -- 合宙IOT平台的默认升级URL, 不填就是这个默认值
+    -- 如果是自建的OTA服务器, 则需要填写正确的URL, 例如 http://192.168.1.5:8000/update
+    -- 如果自建OTA服务器,且url包含全部参数,不需要额外添加参数, 请在url前面添加 ### 
+    -- 如果不加###,则默认会上传如下参数
+    -- 1. opts.version string 版本号, 默认是 BSP版本号.x.z格式
+    -- 2. opts.timeout int 请求超时时间, 默认300000毫秒,单位毫秒
+    -- 3. opts.project_key string 合宙IOT平台的项目key, 默认取全局变量PRODUCT_KEY. 自建服务器不用填
+    -- 4. opts.imei string 设备识别码, 默认取IMEI(Cat.1模块)或WLAN MAC地址(wifi模块)或MCU唯一ID
+    -- 5. opts.firmware_name string 底层版本号
+    -- 请求的版本号, 合宙IOT有一套版本号体系,不传就是合宙规则, 自建服务器的话当然是自行约定版本号了
+    version = ""
+    -- 其他更多参数, 请查阅libfota2的文档 https://wiki.luatos.com/api/libs/libfota2.html
+}]]--
+sys.taskInit(function()
+    -- 这个判断是提醒要设置PRODUCT_KEY的,实际生产请删除
+    if "123" == _G.PRODUCT_KEY and not ota_opts.url then
+        while 1 do
+            sys.wait(1000)
+            log.info("fota", "请修改正确的PRODUCT_KEY")
+        end
+    end
+    -- 等待网络就行后开始检查升级
+    sys.waitUntil("net_ready")
+    log.info("开始检查升级")
+    sys.wait(500)
+    libfota2.request(fota_cb, ota_opts)
+end)
+-- 演示定时自动升级, 每隔4小时自动检查一次
+sys.timerLoopStart(libfota2.request, 4 * 3600000, fota_cb, ota_opts)
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 133 - 0
module/Air8000/demo/fs/main.lua

@@ -0,0 +1,133 @@
+-- main.lua文件
+
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "fs_demo"
+VERSION = "1.0.0"
+
+log.info("---------------------文件创建---------------")  
+local ret, errio = io.mkdir("/data/")
+if ret then       
+       log.info("文件夹创建成功")  
+   else    
+       log.error("文件夹创建失败")  
+end
+--[[
+-- 方法1:使用io.open创建空文件(如果文件已存在,则覆盖)  
+local fd = io.open("/newfile.txt", "w")  
+if fd then
+  -- 文件已成功创建(或覆盖),此时文件为空    
+  fd:close()   
+    log.info("文件创建成功(空文件)")  
+else  
+   log.error("文件创建失败")  
+end  
+]]
+-- 方法2:通过写入内容创建文件  
+
+log.info("---------------------文件创建---------------")  
+
+local content = "这是文件的内容"  
+local fd = io.open("/data/newfile_with_content.txt", "w")  
+if fd then    
+fd:write(content)   
+fd:close()    
+    log.info("文件创建成功并写入内容")  
+else    
+    log.error("文件创建失败")  
+end
+
+
+log.info("-------------------文件追加---------------")  
+-- 打开文件以追加模式  
+local fd = io.open("/data/newfile_with_content.txt", "rb")  
+if fd then    -- 写入内容   
+ local data_old = fd:read("*a")  
+ log.info("文件创建初始内容:",data_old)  
+ -- 关闭文件   
+ fd:close() 
+ local fd1 = io.open("/data/newfile_with_content.txt", "a")  
+ fd1:write("我是追加的内容\n")    
+ -- 关闭文件   
+ fd1:close() 
+ local fd2 = io.open("/data/newfile_with_content.txt", "rb") 
+ local data_new = fd2:read("*a")  
+ log.info("文件追加之后的内容:",data_new)  
+ -- 关闭文件   
+ fd2:close() 
+end
+
+
+log.info("----------------命名文件---------------")  
+-- 重命名文件  
+local success, err = os.rename("/data/newfile_with_content.txt", "/data/newname.txt")  
+if success then    
+log.info("文件重命名成功")  
+else   
+ log.error("文件重命名失败:" .. err)  
+end
+
+log.info("----------------文件拷贝---------------")  
+---文件拷贝
+-- 读取源文件内容  
+local fd_src = io.open("/data/newname.txt", "rb")  
+if fd_src then   
+    local content = fd_src:read("*a")  
+    fd_src:close()  
+    -- 写入目标文件  
+   local fd_dest = io.open("/data/destination.txt", "wb")   
+    if fd_dest then       
+       fd_dest:write(content)       
+       fd_dest:close()       
+       log.info("文件拷贝成功")   
+   else       
+       log.error("无法打开目标文件")  
+   end  
+else   
+  log.error("无法打开源文件")  
+end
+
+log.info("----------------移动文件---------------")  
+local ret, errio = io.mkdir("/destination/")
+if ret then       
+       log.info("文件夹创建成功")  
+   else    
+       log.error("文件夹创建失败")  
+end
+-- 移动文件:重命名(适用于同一文件系统)  
+local success, err = os.rename("/data/newname.txt", "/destination/source.txt")  
+if success then   
+   log.info("文件移动成功(重命名)")  
+else   
+ log.error("文件移动失败(重命名):" .. err)  
+end  
+
+-- 获取文件大小  
+local size = io.fileSize("/data/newname.txt")  
+if size then   
+ log.info("文件大小:" .. size .. " 字节")  
+else   
+ log.error("无法获取文件大小")  
+end
+
+
+-- 列出目录下的文件  
+
+local ret, data = io.lsdir("/data/",10,0)  
+if ret then
+   log.info("fs", "lsdir", json.encode(data))
+ else
+   log.info("fs", "lsdir", "fail", ret, data)
+ end
+
+-- 删除文件  
+local success, err = os.remove("/destination/source.txt")  
+if success then   
+   log.info("文件删除成功")  
+else   
+   log.error("文件删除失败:" .. err)  
+end
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 105 - 0
module/Air8000/demo/fskv/main.lua

@@ -0,0 +1,105 @@
+
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "fskvdemo"
+VERSION = "1.0.0"
+
+-- sys库是标配
+_G.sys = require("sys")
+
+sys.taskInit(function()
+    sys.wait(1000) -- 免得日志刷没了, 生产环境不需要
+
+    -- 检查一下当前固件是否支持fskv
+    if not fskv then
+        while true do
+            log.info("fskv", "this demo need fskv")
+            sys.wait(1000)
+        end
+    end
+
+    -- 初始化kv数据库
+    fskv.init()
+    log.info("fskv", "init complete")
+    -- 先放入一堆值
+    local bootime = fskv.get("boottime")
+    if bootime == nil or type(bootime) ~= "number" then
+        bootime = 0
+    else
+        bootime = bootime + 1
+    end
+    fskv.set("boottime", bootime)
+
+    fskv.set("my_bool", true)
+    fskv.set("my_int", 123)
+    fskv.set("my_number", 1.23)
+    fskv.set("my_str", "luatos")
+    fskv.set("my_table", {name="wendal",age=18})
+    
+    fskv.set("my_str_int", "123")
+    fskv.set("1", "123") -- 单字节key
+    --fskv.set("my_nil", nil) -- 会提示失败,不支持空值
+
+
+    log.info("fskv", "boottime",      type(fskv.get("boottime")),    fskv.get("boottime"))
+    log.info("fskv", "my_bool",      type(fskv.get("my_bool")),    fskv.get("my_bool"))
+    log.info("fskv", "my_int",       type(fskv.get("my_int")),     fskv.get("my_int"))
+    log.info("fskv", "my_number",    type(fskv.get("my_number")),  fskv.get("my_number"))
+    log.info("fskv", "my_str",       type(fskv.get("my_str")),     fskv.get("my_str"))
+    log.info("fskv", "my_table",     type(fskv.get("my_table")),   json.encode(fskv.get("my_table")))
+    log.info("fskv", "my_str_int",     type(fskv.get("my_str_int")),   fskv.get("my_str_int"))
+    log.info("fskv", "1 byte key",     type(fskv.get("1")),   json.encode(fskv.get("1")))
+
+    -- 删除测试
+    fskv.del("my_bool")
+    local t = fskv.get("my_bool")
+    log.info("fskv", "my_bool",      type(t),    t)
+
+    -- 查询kv数据库状态
+    -- local used, total,kv_count = fskv.stat()
+    -- log.info("fdb", "kv", used,total,kv_count)
+
+    -- fskv.clr()
+    -- local used, total,kv_count = fskv.stat()
+    -- log.info("fdb", "kv", used,total,kv_count)
+    
+
+    -- 压力测试
+    -- local start = mcu.ticks()
+    -- local count = 1000
+    -- for i=1,count do
+    --     -- sys.wait(10)
+    --     -- count = count - 1
+    --     -- fskv.set("BENT1", "--" .. os.date() .. "--")
+    --     -- fskv.set("BENT2", "--" .. os.date() .. "--")
+    --     -- fskv.set("BENT3", "--" .. os.date() .. "--")
+    --     -- fskv.set("BENT4", "--" .. os.date() .. "--")
+    --     fskv.get("my_bool")
+    -- end
+    -- log.info("fskv", mcu.ticks() - start)
+
+    if fskv.sett then
+        -- 设置数据, 字符串,数值,table,布尔值,均可
+        -- 但不可以是nil, function, userdata, task
+        log.info("fdb", fskv.sett("mytable", "wendal", "goodgoodstudy"))
+        log.info("fdb", fskv.sett("mytable", "upgrade", true))
+        log.info("fdb", fskv.sett("mytable", "timer", 1))
+        log.info("fdb", fskv.sett("mytable", "bigd", {name="wendal",age=123}))
+        
+        -- 下列语句将打印出4个元素的table
+        log.info("fdb", fskv.get("mytable"), json.encode(fskv.get("mytable")))
+        -- 注意: 如果key不存在, 或者原本的值不是table类型,将会完全覆盖
+        -- 例如下列写法,最终获取到的是table,而非第一行的字符串
+        log.info("fdb", fskv.set("mykv", "123"))
+        log.info("fdb", fskv.sett("mykv", "age", "123")) -- 保存的将是 {age:"123"}
+
+        -- 删除测试
+        log.info("fdb", fskv.set("mytable", {age=18, name="wendal"}))
+        log.info("fdb", fskv.sett("mytable", "name", nil))
+        log.info("fdb", fskv.get("mytable"), json.encode(fskv.get("mytable")))
+    end
+end)
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 92 - 0
module/Air8000/demo/ftp/main.lua

@@ -0,0 +1,92 @@
+
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "ftpdemo"
+VERSION = "1.0.0"
+
+--[[
+本demo需要ftp库, 大部分能联网的设备都具有这个库
+ftp也是内置库, 无需require
+]]
+
+-- sys库是标配
+_G.sys = require("sys")
+--[[特别注意, 使用ftp库需要下列语句]]
+_G.sysplus = require("sysplus")
+
+sys.taskInit(function()
+    -----------------------------
+    -- 统一联网函数, 可自行删减
+    ----------------------------
+    if wlan and wlan.connect then
+        -- wifi 联网, ESP32系列均支持
+        local ssid = "luatos1234"
+        local password = "12341234"
+        log.info("wifi", ssid, password)
+        -- TODO 改成esptouch配网
+        -- LED = gpio.setup(12, 0, gpio.PULLUP)
+        wlan.init()
+        wlan.setMode(wlan.STATION)
+        wlan.connect(ssid, password, 1)
+        local result, data = sys.waitUntil("IP_READY", 30000)
+        log.info("wlan", "IP_READY", result, data)
+        device_id = wlan.getMac()
+        -- TODO 获取mac地址作为device_id
+    elseif mobile then
+        -- Air8000/Air600E系列
+        --mobile.simid(2)
+        -- LED = gpio.setup(27, 0, gpio.PULLUP)
+        device_id = mobile.imei()
+        sys.waitUntil("IP_READY", 30000)
+    end
+
+    -- -- 打印一下支持的加密套件, 通常来说, 固件已包含常见的99%的加密套件
+    -- if crypto.cipher_suites then
+    --     log.info("cipher", "suites", json.encode(crypto.cipher_suites()))
+    -- end
+    while true do
+        sys.wait(1000)
+        log.info("ftp 启动")
+        print(ftp.login(nil,"121.43.224.154",21,"ftp_user","3QujbiMG").wait())
+    
+        print(ftp.command("NOOP").wait())
+        print(ftp.command("SYST").wait())
+
+        print(ftp.command("TYPE I").wait())
+        print(ftp.command("PWD").wait())
+        print(ftp.command("MKD QWER").wait())
+        print(ftp.command("CWD /QWER").wait())
+
+        print(ftp.command("CDUP").wait())
+        print(ftp.command("RMD QWER").wait())
+
+        print(ftp.command("LIST").wait())
+
+        -- io.writeFile("/1222.txt", "23noianfdiasfhnpqw39fhawe;fuibnnpw3fheaios;fna;osfhisao;fadsfl")
+        -- print(ftp.push("/1222.txt","/12222.txt").wait())
+        
+        print(ftp.pull("/122224.txt","/122224.txt").wait())
+
+        local f = io.open("/122224.txt", "r")
+        if f then
+            local data = f:read("*a")
+            f:close()
+            log.info("fs", "writed data", data)
+        else
+            log.info("fs", "open file for read failed")
+        end
+
+        print(ftp.command("DELE /12222.txt").wait())
+        print(ftp.push("/122224.txt","/12222.txt").wait())
+        print(ftp.close().wait())
+        log.info("meminfo", rtos.meminfo("sys"))
+        sys.wait(15000)
+    end
+
+
+end)
+
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 37 - 0
module/Air8000/demo/gpio/AGPIO/main.lua

@@ -0,0 +1,37 @@
+-- 本示例对比了普通GPIO和AGPIO的进入休眠模式前后的区别。
+-- Luatools需要PROJECT和VERSION这两个信息
+PROJECT = "AGPIO_GPIO_testdemo"
+VERSION = "1.0.0"
+
+log.info("main", PROJECT, VERSION)
+
+-- sys库是标配
+_G.sys = require("sys")
+
+if wdt then
+    -- 添加硬狗防止程序卡死,在支持的设备上启用这个功能
+    wdt.init(9000) -- 初始化watchdog设置为9s
+    sys.timerLoopStart(wdt.feed, 3000) -- 3s喂一次狗
+end
+
+local gpio_number = 1   -- 普通GPIO GPIO号为1,休眠后掉电。
+local Agpio_number = 27 -- AGPIO GPIO号为27(模块上35管脚),休眠后可保持电平。
+
+gpio.setup(gpio_number, 1)
+gpio.setup(Agpio_number, 1)
+
+sys.taskInit(function()
+    sys.wait(16000)
+    -- 关闭USB电源
+    pm.power(pm.USB, false)
+    -- 进入低功耗模式
+    pm.power(pm.WORK_MODE, 3)
+    sys.wait(10000)
+    pm.power(pm.USB, true)
+    pm.power(pm.WORK_MODE, 0)
+end)
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 39 - 0
module/Air8000/demo/gpio/GPIO上拉下拉模式/main.lua

@@ -0,0 +1,39 @@
+-- Luatools需要PROJECT和VERSION这两个信息
+PROJECT = "gpio2demo"
+VERSION = "1.0.0"
+
+log.info("main", PROJECT, VERSION)
+
+-- sys库是标配
+_G.sys = require("sys")
+
+if wdt then
+    --添加硬狗防止程序卡死,在支持的设备上启用这个功能
+    wdt.init(9000)--初始化watchdog设置为9s
+    sys.timerLoopStart(wdt.feed, 3000)--3s喂一次狗
+end
+
+--配置gpio2为中断下拉模式,模块上30 管脚
+--配置gpio27为中断下拉模式,模块上35 管脚
+--请根据实际需求更改gpio编号和上下拉
+local gpio_pin1 = 2      -
+local gpio_pin2 = 27
+-- 按键防抖函数
+gpio.debounce(gpio_pin1, 50)
+gpio.debounce(gpio_pin2, 50)
+
+-- 设置GPIO7引脚为上拉输入模式
+gpio.setup(gpio_pin1, nil, gpio.PULLUP)
+
+-- 设置GPIO27引脚为下拉输入模式
+gpio.setup(gpio_pin2, nil, gpio.PULLDOWN)
+
+
+sys.timerLoopStart(function ()
+    log.info("GPIO",gpio_pin1,"电平",gpio.get(gpio_pin1))
+    log.info("GPIO",gpio_pin2,"电平",gpio.get(gpio_pin2))
+end,1000)
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 27 - 0
module/Air8000/demo/gpio/GPIO中断(触发)模式/main.lua

@@ -0,0 +1,27 @@
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "gpio_irq"
+VERSION = "1.0.0"
+
+log.info("main", PROJECT, VERSION)
+
+-- sys库是标配
+_G.sys = require("sys")
+
+if wdt then
+    -- 添加硬狗防止程序卡死,在支持的设备上启用这个功能
+    wdt.init(9000) -- 初始化watchdog设置为9s
+    sys.timerLoopStart(wdt.feed, 3000) -- 3s喂一次狗
+end
+
+-- 配置gpio27为中断模式,上升沿(gpio.RISING)和下降沿(gpio.FALLING)均触发(gpio.BOTH)
+-- 请根据实际需求更改gpio编号和触发模式
+local gpio_pin = 27
+gpio.debounce(gpio_pin, 100)
+gpio.setup(gpio_pin, function()
+    log.info("gpio", gpio_pin, "被触发")
+end, gpio.PULLUP, gpio.BOTH)
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 34 - 0
module/Air8000/demo/gpio/GPIO中断(计数)模式/main.lua

@@ -0,0 +1,34 @@
+-- Luatools需要PROJECT和VERSION这两个信息
+PROJECT = "gpio_irq"
+VERSION = "1.0.0"
+
+log.info("main", PROJECT, VERSION)
+
+-- sys库是标配
+_G.sys = require("sys")
+
+if wdt then
+    --添加硬狗防止程序卡死,在支持的设备上启用这个功能
+    wdt.init(9000)--初始化watchdog设置为9s
+    sys.timerLoopStart(wdt.feed, 3000)--3s喂一次狗
+end
+
+--配置gpio27为中断计数模式
+--请根据实际需求更改gpio编号和上下拉
+local gpio_pin = 27
+-- gpio.setup(gpio_pin, gpio.count, gpio.PULLUP, gpio.FALLING)
+gpio.setup(gpio_pin, gpio.count)
+
+--配置PWM4输出 1kHZ 占空比50%的方波作为信号源
+pwm.open(4,1000,50)
+
+--每隔1S统计一次中断触发的次数
+sys.taskInit(function()
+    while true do
+        sys.wait(1000)
+        log.info("irq cnt", gpio.count(gpio_pin))
+    end
+end)
+
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 34 - 0
module/Air8000/demo/gpio/GPIO翻转测速/main.lua

@@ -0,0 +1,34 @@
+-- Luatools需要PROJECT和VERSION这两个信息
+PROJECT = "gpio2demo"
+VERSION = "1.0.0"
+
+log.info("main", PROJECT, VERSION)
+
+-- sys库是标配
+_G.sys = require("sys")
+
+if wdt then
+    -- 添加硬狗防止程序卡死,在支持的设备上启用这个功能
+    wdt.init(9000) -- 初始化watchdog设置为9s
+    sys.timerLoopStart(wdt.feed, 3000) -- 3s喂一次狗
+end
+
+local test_gpio_number = 27    ---模块上35管脚
+
+gpio.setup(test_gpio_number, 0, gpio.PULLUP)
+
+sys.taskInit(function()
+    sys.wait(100)
+    while true do
+        sys.wait(100)
+        -- 通过GPIO27脚输出输出8组电平变化
+        -- 0xA9就是输出的电平高低状态,即 10101001
+        gpio.pulse(test_gpio_number, 0xA9, 8, 0)
+        log.info("gpio----------->pulse2")
+    end
+end)
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 41 - 0
module/Air8000/demo/gpio/GPIO输入模式/main.lua

@@ -0,0 +1,41 @@
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "gpio_irq"
+VERSION = "1.0.0"
+
+log.info("main", PROJECT, VERSION)
+
+-- sys库是标配
+_G.sys = require("sys")
+
+if wdt then
+    -- 添加硬狗防止程序卡死,在支持的设备上启用这个功能
+    wdt.init(9000) -- 初始化watchdog设置为9s
+    sys.timerLoopStart(wdt.feed, 3000) -- 3s喂一次狗
+end
+
+-- 配置gpio27为输入模式
+-- 配置GPIO20(即开发板上LED灯)为输出模式
+
+-- 请根据实际需求更改gpio编号和上下拉
+
+local inputpin = 27
+local ledpin = 20
+
+local input = gpio.setup(inputpin,nil)
+local led = gpio.setup(ledpin, 1)
+
+gpio.debounce(inputpin, 50)
+--GPIO27检测到有高低电平输入后,会返回GPIO27当前获取到的电平为高还是低,高返回值为1,低返回值为0
+--将这个返回值,传给GPIO20(LED),为0 则GPIO20输出低电平(LED灯灭),为1则输出高电平(LED灯亮)
+sys.taskInit(function ()
+    while true do
+        led(input())
+        sys.wait(500)
+    end
+end)
+
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 37 - 0
module/Air8000/demo/gpio/GPIO输出模式/main.lua

@@ -0,0 +1,37 @@
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "gpiodemo"
+VERSION = "1.0.0"
+
+log.info("main", PROJECT, VERSION)
+
+-- sys库是标配
+_G.sys = require("sys")
+
+if wdt then
+    -- 添加硬狗防止程序卡死,在支持的设备上启用这个功能
+    wdt.init(9000) -- 初始化watchdog设置为9s
+    sys.timerLoopStart(wdt.feed, 3000) -- 3s喂一次狗
+end
+
+local gpio_number = 20 -- air8000 核心板上的23 管脚
+
+LED = gpio.setup(gpio_number, 1) -- 设置GPIO20为输出模式
+
+sys.taskInit(function()
+    -- 开始呼吸灯
+    local count = 0
+    while 1 do
+        -- 呼吸灯程序
+        LED(1)
+        log.info("GPIO", "Go Go Go", count, rtos.bsp())
+        sys.wait(500)--点亮时间 500ms
+        LED(0)
+        sys.wait(500)--熄灭时间 500ms
+        count = count + 1
+    end
+end)
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 50 - 0
module/Air8000/demo/gpio/power_on/main.lua

@@ -0,0 +1,50 @@
+
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "power_on_demo"
+VERSION = "1.0.0"
+
+log.info("main", PROJECT, VERSION)
+
+-- sys库是标配
+_G.sys = require("sys")
+
+local powerkey_pin = 46    -- 赋值powerkey引脚编号
+
+-- local count=0    -- 五秒内短按三次关机
+-- local function pwrkeycb() 
+--     log.info("pwrkey", gpio.get(powerkey_pin))
+--     if gpio.get(powerkey_pin) == 0 then
+--         count=count+1
+--         sys.timerStart(function()
+--             log.info("计数归零")
+--             count=0
+--         end, 5000)
+--         if count>=3 then
+--             pm.shutdown() 
+--         end
+--     end
+-- end
+
+function pwroff()
+    log.info("power off!!")
+    pm.shutdown() 
+end
+
+local function pwrkeycb()    --长按五秒关机
+    log.info("pwrkey", gpio.get(powerkey_pin))
+    if gpio.get(powerkey_pin) == 1 then
+        sys.timerStop(pwroff)
+    else
+        sys.timerStart(pwroff, 5000)
+    end
+end
+
+if powerkey_pin ~= 255 then
+    gpio.setup(powerkey_pin, pwrkeycb, gpio.PULLUP,gpio.BOTH)
+else
+    log.info("bsp not support")
+end
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 157 - 0
module/Air8000/demo/gsensor/da221.lua

@@ -0,0 +1,157 @@
+local i2cId = 0
+local intPin = 39
+-- 是否打印日志
+local logSwitch = true
+local moduleName = "da221"
+
+local da221Addr = 0x27
+local soft_reset = {0x00, 0x24}     -- 软件复位地址
+local chipid_addr = 0x01            -- 芯片ID地址
+local rangeaddr = {0x0f, 0x00}      -- 设置加速度量程,默认2g
+local int_set1_reg = {0x16, 0x87}   --设置x,y,z发生变化时,产生中断
+local int_set2_reg = {0x17, 0x10}   --使能新数据中断,数据变化时,产生中断,本程序不设置
+local int_map1_reg = {0x19, 0x04}   --运动的时候,产生中断
+local int_map2_reg = {0x1a, 0x01}
+
+local active_dur_addr = {0x27, 0x00}  -- 设置激活时间,默认0x00
+local active_ths_addr = {0x28, 0x05}  -- 设置激活阈值
+local mode_addr = {0x11, 0x34}  -- 设置模式
+local odr_addr = {0x10, 0x08}  -- 设置采样率
+local int_latch_addr = {0x21, 0x02}  -- 设置中断锁存
+
+local x_lsb_reg = 0x02
+local active_state = 0x0b
+local active_state_data
+
+
+local function logF(...)
+    if logSwitch then
+        log.info(moduleName, ...)
+    end
+end
+
+--字符串转字节数组
+local function stringToBytes(hexStr)
+    local bytes = {}
+    for i = 1, #hexStr, 2 do
+        local byteStr = hexStr:sub(i, i+1)
+        local byte = tonumber(byteStr, 16)
+        table.insert(bytes, byte)
+    end
+    return bytes
+end
+
+local interruptCount = 0  -- 计数器
+local function ind()
+    logF("int", gpio.get(intPin))
+    --gsensor()  -- 调用gsensor函数,计算设备是否处于运动状态
+    if gpio.get(intPin) == 1 then
+        -- interruptCount = interruptCount + 1  -- 增加计数器
+        -- if interruptCount >= 2 then  -- 判断是否达到2次
+        --     gsensor()  -- 调用gsensor函数
+        --     interruptCount = 0  -- 重置计数器
+        -- end
+        -- manage.setLastCrashLevel()
+        --读取x,y,z轴的数据
+        i2c.send(i2cId, da221Addr, 0x02, 1)
+        local data = i2c.recv(i2cId, da221Addr, 6)
+        if data and #data == 6 then
+            logF("XYZ ORIGIN DATA", data:toHex())
+            local xl, xm, yl, ym, zl, zm = string.byte(data, 1, 1), string.byte(data, 2, 2), string.byte(data, 3, 3), string.byte(data, 4, 4), string.byte(data, 5, 5), string.byte(data, 6, 6)
+            local x, y, z = (xm << 8 | xl) >> 4, (ym << 8 | yl) >> 4, (zm << 8 | zl) >> 4
+            logF("x:", x, "y:", y, "z:", z)
+        else
+            sys.publish("RESTORE_GSENSOR")
+            return
+        end
+
+    end
+end
+
+-- gpio.debounce(intPin, 100)
+gpio.setup(intPin, ind)
+
+local function init()
+    log.info("da221 init...")
+    --关闭i2c
+    i2c.close(i2cId)
+    --重新打开i2c,i2c速度设置为低速
+    i2c.setup(i2cId, i2c.SLOW)
+
+    sys.wait(50)
+    i2c.send(i2cId, da221Addr, soft_reset, 1)
+    sys.wait(50)
+    i2c.send(i2cId, da221Addr, chipid_addr, 1)
+    local chipid = i2c.recv(i2cId, da221Addr, 1)
+    log.info("i2c", "chipid",chipid:toHex())
+    if string.byte(chipid) == 0x13 then
+        log.info("da221 init success")
+    else
+        log.info("da221 init fail")
+    end
+
+    -- 设置寄存器
+    i2c.send(i2cId, da221Addr, int_set1_reg, 1)--设置x,y,z发生变化时,产生中断
+    sys.wait(5)
+    i2c.send(i2cId, da221Addr, int_map1_reg, 1)--运动的时候,产生中断
+    sys.wait(5)
+    i2c.send(i2cId, da221Addr, active_dur_addr, 1)-- 设置激活时间,默认0x00
+    sys.wait(5)
+    i2c.send(i2cId, da221Addr, active_ths_addr, 1)-- 设置激活阈值
+    sys.wait(5)
+    i2c.send(i2cId, da221Addr, mode_addr, 1)-- 设置模式
+    sys.wait(5)
+    i2c.send(i2cId, da221Addr, odr_addr, 1)-- 设置采样率
+    sys.wait(5)
+    i2c.send(i2cId, da221Addr, int_latch_addr, 1)-- 设置中断锁存 中断一旦触发将保持,直到手动清除
+    sys.wait(5)
+end
+
+sys.taskInit(function()
+    mcu.altfun(mcu.I2C, i2cId, 13, 2, 0)
+    mcu.altfun(mcu.I2C, i2cId, 14, 2, 0)
+    -- while true do
+        init()
+
+
+        while true do
+        --     --等待da221传感器数据不正确,复位的消息
+        --     local result = sys.waitUntil("RESTORE_GSENSOR", 60 * 1000)
+        --     --如果接收到了复位消息,则跳出读取数据的循环,重新执行init()函数
+        --     if result then
+        --         break
+        --     end
+        --     --读取da221传感器的型号值,默认是0x13
+        --     i2c.send(i2cId, da221Addr, 0x01, 1)
+        --     local data = i2c.recv(i2cId, da221Addr, 1)
+        --     if not data or data == "" or string.byte(data) ~= 0x13 then
+        --         break
+        --     end
+            -- 读取三轴速度
+            i2c.send(i2cId, da221Addr, x_lsb_reg, 1)
+            local recv_data_xyz = i2c.recv(i2cId, da221Addr, 6)
+            local hex_data_xyz = stringToBytes(recv_data_xyz:toHex())
+            log.info("recv_data_xyz", recv_data_xyz:toHex())
+            if recv_data_xyz and #recv_data_xyz == 6 then
+                -- local data_xyz = {}
+                -- for i = 1, #recv_data_xyz do
+                --     -- 将提取的子字符串添加到结果表中
+                --     table.insert(data_xyz, recv_data_xyz:sub(i, i):toHex())
+                -- end
+                -- data_xyz = data_xyz:byte()
+                log.info(string.format("Byte: %02X %02X %02X %02X %02X %02X", hex_data_xyz[1], hex_data_xyz[2], hex_data_xyz[3], hex_data_xyz[4], hex_data_xyz[5], hex_data_xyz[6]))
+                -- 提取X轴数据
+                local acc_x = ((hex_data_xyz[2] << 8)|hex_data_xyz[1])>>4;
+                -- 提取Y轴数据
+                local acc_y = ((hex_data_xyz[4] << 8)|hex_data_xyz[3])>>4;
+                -- 提取Z轴数据
+                local acc_z = ((hex_data_xyz[6] << 8)|hex_data_xyz[5])>>4;
+                log.info(string.format("acc_x %.1f", acc_x))
+                log.info(string.format("acc_y %.1f", acc_y))
+                log.info(string.format("acc_z %.1f", acc_z))
+                -- sys.publish("gsensor", {x = acc_x, y = acc_y, z = acc_z})
+            end
+            sys.wait(4000)
+        end
+    -- end
+end)

+ 16 - 0
module/Air8000/demo/gsensor/main.lua

@@ -0,0 +1,16 @@
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "Air8000_da221"
+VERSION = "1.0.0"
+log.info("main", PROJECT, VERSION)
+-- 引入必要的库文件(lua编写), 内部库不需要require
+sys = require "sys"
+sysplus = require("sysplus")
+
+-- gsensor的供电打开
+local vbackup = gpio.setup(24, 1)
+
+local da221 = require "da221"
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()

+ 21 - 0
module/Air8000/demo/helloworld/main.lua

@@ -0,0 +1,21 @@
+
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "helloworld"
+VERSION = "1.0.0"
+
+-- 引入必要的库文件(lua编写), 内部库不需要require
+sys = require("sys")
+
+-- log.info("main", "hello world")
+
+-- print(_VERSION)
+
+sys.timerLoopStart(function()
+    print("hello world")
+end, 3000)
+
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 26 - 0
module/Air8000/demo/hmeta/main.lua

@@ -0,0 +1,26 @@
+
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "hmetademo"
+VERSION = "1.0.0"
+
+-- sys库是标配
+_G.sys = require("sys")
+
+
+
+
+sys.taskInit(function()
+    while hmeta do
+        -- hmeta识别底层模组类型的
+        -- 不同的模组可以使用相同的bsp,但根据封装的不同,根据内部数据仍可识别出具体模块
+        log.info("hmeta", hmeta.model(), hmeta.hwver and hmeta.hwver())
+        log.info("bsp",   rtos.bsp())
+        sys.wait(3000)
+    end
+    log.info("这个bsp不支持hmeta库哦")
+end)
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 3 - 0
module/Air8000/demo/http/luatos_uploadFile.txt

@@ -0,0 +1,3 @@
+测试文本   adcc1234x衣二三
+	84as1c188
+-*accxxx6-4

+ 297 - 0
module/Air8000/demo/http/main.lua

@@ -0,0 +1,297 @@
+
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "httpdemo"
+VERSION = "1.0.0"
+
+--[[
+本demo需要http库, 大部分能联网的设备都具有这个库
+http也是内置库, 无需require
+
+1. 如需上传大文件,请使用 httpplus 库, 对应demo/httpplus
+2. 
+]]
+
+-- sys库是标配
+_G.sys = require("sys")
+--[[特别注意, 使用http库需要下列语句]]
+_G.sysplus = require("sysplus")
+
+
+
+
+sys.taskInit(function()
+    -----------------------------
+    -- 统一联网函数, 可自行删减
+    ----------------------------
+    if wlan and wlan.connect then
+        -- wifi 联网, ESP32系列均支持
+        local ssid = "luatos1234"
+        local password = "12341234"
+        log.info("wifi", ssid, password)
+        wlan.init()
+        wlan.setMode(wlan.STATION)
+        wlan.connect(ssid, password, 1)
+        local result, data = sys.waitUntil("IP_READY", 30000)
+        log.info("wlan", "IP_READY", result, data)
+        device_id = wlan.getMac()
+    elseif mobile then
+        device_id = mobile.imei()
+        log.info("ipv6", mobile.ipv6(true))
+        sys.waitUntil("IP_READY", 30000)
+    elseif http then
+        sys.waitUntil("IP_READY")
+    else
+        while 1 do
+            sys.wait(1000)
+            log.info("http", "当前固件未包含http库")
+        end
+    end
+    log.info("已联网")
+    sys.publish("net_ready")
+end)
+
+function demo_http_get()
+    -- 最普通的Http GET请求
+    local code, headers, body = http.request("GET", "https://www.air32.cn/").wait()
+    log.info("http.get", code, headers, body)
+    local code, headers, body = http.request("GET", "https://mirrors6.tuna.tsinghua.edu.cn/", nil, nil, {ipv6=true}).wait()
+    log.info("http.get", code, headers, body)
+    sys.wait(100)
+    local code, headers, body = http.request("GET", "https://www.luatos.com/").wait()
+    log.info("http.get", code, headers, body)
+
+    -- 按需打印
+    -- code 响应值, 若大于等于 100 为服务器响应, 小于的均为错误代码
+    -- headers是个table, 一般作为调试数据存在
+    -- body是字符串. 注意lua的字符串是带长度的byte[]/char*, 是可以包含不可见字符的
+    -- log.info("http", code, json.encode(headers or {}), #body > 512 and #body or body)
+end
+
+function demo_http_post_json()
+    -- POST request 演示
+    local req_headers = {}
+    req_headers["Content-Type"] = "application/json"
+    local body = json.encode({name="LuatOS"})
+    local code, headers, body = http.request("POST","http://site0.cn/api/httptest/simple/date", 
+            req_headers,
+            body -- POST请求所需要的body, string, zbuff, file均可
+    ).wait()
+    log.info("http.post", code, headers, body)
+end
+
+function demo_http_post_form()
+    -- POST request 演示
+    local req_headers = {}
+    req_headers["Content-Type"] = "application/x-www-form-urlencoded"
+    local params = {
+        ABC = "123",
+        DEF = 345
+    }
+    local body = ""
+    for k, v in pairs(params) do
+        body = body .. tostring(k) .. "=" .. tostring(v):urlEncode() .. "&"
+    end
+    local code, headers, body = http.request("POST","http://echohttp.wendal.cn/post", 
+            req_headers,
+            body -- POST请求所需要的body, string, zbuff, file均可
+    ).wait()
+    log.info("http.post.form", code, headers, body)
+end
+
+-- local function http_download_callback(content_len,body_len,userdata)
+--     print("http_download_callback",content_len,body_len,userdata)
+-- end
+
+-- local http_userdata = "123456789"
+
+function demo_http_download()
+
+    -- POST and download, task内的同步操作
+    local opts = {}                 -- 额外的配置项
+    opts["dst"] = "/data.bin"       -- 下载路径,可选
+    opts["timeout"] = 30000         -- 超时时长,单位ms,可选
+    -- opts["adapter"] = socket.ETH0  -- 使用哪个网卡,可选
+    -- opts["callback"] = http_download_callback
+    -- opts["userdata"] = http_userdata
+
+    for k, v in pairs(opts) do
+        print("opts",k,v)
+    end
+    
+    local code, headers, body = http.request("POST","http://site0.cn/api/httptest/simple/date",
+            {}, -- 请求所添加的 headers, 可以是nil
+            "", 
+            opts
+    ).wait()
+    log.info("http.post", code, headers, body) -- 只返回code和headers
+
+    -- local f = io.open("/data.bin", "rb")
+    -- if f then
+    --     local data = f:read("*a")
+    --     log.info("fs", "data", data, data:toHex())
+    -- end
+    
+    -- GET request, 开个task让它自行执行去吧, 不管执行结果了
+    sys.taskInit(http.request("GET","http://site0.cn/api/httptest/simple/time").wait)
+end
+
+function demo_http_post_file()
+        -- -- POST multipart/form-data模式 上传文件---手动拼接
+        local boundary = "----WebKitFormBoundary"..os.time()
+        local req_headers = {
+            ["Content-Type"] = "multipart/form-data; boundary="..boundary,
+        }
+        local body = "--"..boundary.."\r\n"..
+                     "Content-Disposition: form-data; name=\"uploadFile\"; filename=\"luatos_uploadFile_TEST01.txt\""..
+                     "\r\nContent-Type: text/plain\r\n\r\n"..
+                     "1111http_测试一二三四654zacc\r\n"..
+                     "--"..boundary
+
+        log.info("headers: ", "\r\n"..json.encode(req_headers))
+        log.info("body: ", "\r\n"..body)
+        local code, headers, body = http.request("POST","http://airtest.openluat.com:2900/uploadFileToStatic",
+                req_headers,
+                body -- POST请求所需要的body, string, zbuff, file均可
+        ).wait()
+        log.info("http.post", code, headers, body)
+
+        -- 也可用postMultipartFormData(url, params) 上传文件
+        postMultipartFormData(
+            "http://airtest.openluat.com:2900/uploadFileToStatic",
+            {
+                -- texts = 
+                -- {
+                --     ["imei"] = "862991234567890",
+                --     ["time"] = "20180802180345"
+                -- },
+                
+                files =
+                {
+                    ["uploadFile"] = "/luadb/luatos_uploadFile.txt",
+                }
+            }
+        )
+end
+
+
+local function demo_http_get_gzip()
+    -- 这里用 和风天气 的API做演示
+    -- 这个API的响应, 总会gzip压缩过, 需要配合miniz库进行解压
+    local code, headers, body = http.request("GET", "https://devapi.qweather.com/v7/weather/now?location=101010100&key=0e8c72015e2b4a1dbff1688ad54053de").wait()
+    log.info("http.gzip", code)
+    if code == 200 then
+        local re = miniz.uncompress(body:sub(11), 0)
+        log.info("和风天气", re)
+        if re then
+            local jdata = json.decode(re)
+            log.info("jdata", jdata)
+            if jdata then
+                log.info("和风天气", jdata.code)
+                if jdata.now then
+                    log.info("和风天气", "天气", jdata.now.text)
+                    log.info("和风天气", "温度", jdata.now.temp)
+                end
+            end
+        end
+    end
+end
+
+sys.taskInit(function()
+    sys.wait(100)
+    -- 打印一下支持的加密套件, 通常来说, 固件已包含常见的99%的加密套件
+    -- if crypto.cipher_suites then
+    --     log.info("cipher", "suites", json.encode(crypto.cipher_suites()))
+    -- end
+
+    -------------------------------------
+    -------- HTTP 演示代码 --------------
+    -------------------------------------
+    sys.waitUntil("net_ready") -- 等联网
+
+    while 1 do
+        -- 演示GET请求
+        demo_http_get()
+        -- 表单提交
+        -- demo_http_post_form()
+        -- POST一个json字符串
+        -- demo_http_post_json()
+        -- 上传文件, mulitform形式
+        -- demo_http_post_file()
+        -- 文件下载
+        -- demo_http_download()
+        -- gzip压缩的响应, 以和风天气为例
+        -- demo_http_get_gzip()
+
+        sys.wait(1000)
+        -- 打印一下内存状态
+        log.info("sys", rtos.meminfo("sys"))
+        log.info("lua", rtos.meminfo("lua"))
+        sys.wait(600000)
+    end
+end)
+
+---- MultipartForm上传文件
+-- url string 请求URL地址
+-- req_headers table 请求头
+-- params table 需要传输的数据参数
+function postMultipartFormData(url, params)
+    local boundary = "----WebKitFormBoundary"..os.time()
+    local req_headers = {
+        ["Content-Type"] = "multipart/form-data; boundary="..boundary,
+    }
+    local body = {}
+
+    -- 解析拼接 body
+    for k,v in pairs(params) do
+        if k=="texts" then
+            local bodyText = ""
+            for kk,vv in pairs(v) do
+                print(kk,vv)
+                bodyText = bodyText.."--"..boundary.."\r\nContent-Disposition: form-data; name=\""..kk.."\"\r\n\r\n"..vv.."\r\n"
+            end
+            table.insert(body, bodyText)
+        elseif k=="files" then
+            local contentType =
+            {
+                txt = "text/plain",             -- 文本
+                jpg = "image/jpeg",             -- JPG 格式图片
+                jpeg = "image/jpeg",            -- JPEG 格式图片
+                png = "image/png",              -- PNG 格式图片   
+                gif = "image/gif",              -- GIF 格式图片
+                html = "image/html",            -- HTML
+                json = "application/json"       -- JSON
+            }
+            
+            for kk,vv in pairs(v) do
+                if type(vv) == "table" then
+                    for i=1, #vv do
+                        print(kk,vv[i])
+                        table.insert(body, "--"..boundary.."\r\nContent-Disposition: form-data; name=\""..kk.."\"; filename=\""..vv[i]:match("[^%/]+%w$").."\"\r\nContent-Type: "..contentType[vv[i]:match("%.(%w+)$")].."\r\n\r\n")
+                        table.insert(body, io.readFile(vv[i]))
+                        table.insert(body, "\r\n")
+                    end
+                else
+                    print(kk,vv)
+                    table.insert(body, "--"..boundary.."\r\nContent-Disposition: form-data; name=\""..kk.."\"; filename=\""..vv:match("[^%/]+%w$").."\"\r\nContent-Type: "..contentType[vv:match("%.(%w+)$")].."\r\n\r\n")
+                    table.insert(body, io.readFile(vv))
+                    table.insert(body, "\r\n")
+                end
+            end
+        end
+    end 
+    table.insert(body, "--"..boundary.."--\r\n")
+    body = table.concat(body)
+    log.info("headers: ", "\r\n" .. json.encode(req_headers), type(body))
+    log.info("body: " .. body:len() .. "\r\n" .. body)
+    local code, headers, body = http.request("POST",url,
+            req_headers,
+            body
+    ).wait()   
+    log.info("http.post", code, headers, body)
+end
+
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 57 - 0
module/Air8000/demo/i2c-sht20/main.lua

@@ -0,0 +1,57 @@
+
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "sht20demo"
+VERSION = "1.0.0"
+
+-- sys库是标配
+sys = require("sys")
+
+-- 接线
+--[[
+SHT20 --- 模块
+SDA   -   I2C_SDA
+SCL   -   I2C_SCL
+VCC   -   VDDIO
+GND   -   GND
+]]
+
+
+-- 启动个task, 定时查询SHT20的数据
+sys.taskInit(function()
+
+    local tmp,hum -- 原始数据
+    local temp,hump -- 真实值
+
+    --1010 000x
+    local addr = 0x40
+    -- 按实际修改哦
+    local id = 0
+
+    log.info("i2c", "initial",i2c.setup(id))
+
+    while true do
+        --第一种方式
+        i2c.send(id, addr, string.char(0xF3))
+        sys.wait(100)
+        tmp = i2c.recv(id, addr, 2)
+        log.info("SHT20", "read tem data", tmp:toHex())
+
+        i2c.send(id, addr, string.char(0xF5))
+        sys.wait(100)
+        hum = i2c.recv(id, addr, 2)
+        log.info("SHT20", "read hum data", hum:toHex())
+        local _,tval = pack.unpack(tmp,'>H')
+        local _,hval = pack.unpack(hum,'>H')
+        if tval and hval then
+            temp = (((17572 * tval) >> 16) - 4685)/100
+            hump = (((12500 * hval) >> 16) - 600)/100
+            log.info("SHT20", "temp,humi",temp,hump)
+        end
+        sys.wait(1000)
+    end
+end)
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 69 - 0
module/Air8000/demo/i2c/硬件I2C/main.lua

@@ -0,0 +1,69 @@
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "sht20demo"
+VERSION = "1.0.0"
+
+-- sys库是标配
+sys = require("sys")
+--添加硬狗防止程序卡死
+if wdt then
+    wdt.init(9000) -- 初始化watchdog设置为9s
+    sys.timerLoopStart(wdt.feed, 3000)--3s喂一次狗
+end
+
+--本demo演示通过I2C协议去读取SHT20温湿度传感器的过程,并介绍luatos中I2C相关接口的用法。
+-- 接线
+--[[
+SHT20 --- 模块
+SDA   -   I2C1_SDA(GPIO4) PIN67
+SCL   -   I2C1_SCL(GPIO5) PIN66
+VCC   -   3.3V
+GND   -   GND
+]]
+
+--第一种方式,通过硬件I2C来驱动
+-- 启动个task, 定时查询SHT20的数据
+sys.taskInit(function()
+    local tmp,hum -- 原始数据
+    local temp,hump -- 真实值
+
+    --0100 0000  传感器七位地址
+    local addr = 0x40
+    -- 按接线选择配置
+    -- 1: HW I2C1
+    local id = 1    
+
+    ------------------硬件I2C---------------------------------
+    -- 配置IO复用
+    gpio.setup(5, 0, nil, nil, 2)   -- PIN66 GPIO5 FUNC2-I2C1 SCL
+    gpio.setup(4, 0, nil, nil, 2)   -- PIN67 GPIO4 FUNC2-I2C1 SDA
+
+    log.info("i2c".. id, "hw i2c initial",  i2c.setup(id)) --初始化I2C
+    
+    while true do
+        i2c.send(id, addr, string.char(0xF3)) --发送0xF3来查询温度
+        sys.wait(100)
+        tmp = i2c.recv(id, addr, 2)  --读取传感器的温度值
+        log.info("SHT20", "read tem data", tmp:toHex())
+
+        i2c.send(id, addr, string.char(0xF5)) --发送0xF5来查询湿度
+        sys.wait(100)
+        hum = i2c.recv(id, addr, 2)  --读取传感器湿度值
+        log.info("SHT20", "read hum data", hum:toHex())
+        local _,tval = pack.unpack(tmp,'>H') --提取一个按照大端字节序编码的16位无符号整数
+        local _,hval = pack.unpack(hum,'>H')
+        log.info("SHT20", "tval hval", tval,hval)
+        if tval and hval then
+            --按照传感器手册来计算对应的温湿度
+            temp = (((17572 * tval) >> 16) - 4685)/100
+            hump = (((12500 * hval) >> 16) - 600)/100
+            log.info("SHT20", "temp,humi",string.format("%.2f",temp),string.format("%.2f",hump))
+        end
+        sys.wait(1000)
+    end
+
+end)
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 64 - 0
module/Air8000/demo/i2c/软件I2C/main.lua

@@ -0,0 +1,64 @@
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "sht20demo"
+VERSION = "1.0.0"
+
+-- sys库是标配
+sys = require("sys")
+--添加硬狗防止程序卡死
+if wdt then
+    wdt.init(9000) -- 初始化watchdog设置为9s
+    sys.timerLoopStart(wdt.feed, 3000)--3s喂一次狗
+end
+
+--本demo演示通过I2C协议去读取SHT20温湿度传感器的过程,并介绍luatos中I2C相关接口的用法。
+-- 接线
+--[[
+SHT20 --- 模块
+SDA   -   GPIO4(I2C SDA) PIN67
+SCL   -   GPIO5(I2C SCL) PIN66
+VCC   -   3.3V
+GND   -   GND
+]]
+
+--第二种方式,通过软件I2C来驱动
+-- 启动个task, 定时查询SHT20的数据
+sys.taskInit(function()
+    local tmp,hum -- 原始数据
+    local temp,hump -- 真实值
+
+    --0100 0000  传感器七位地址
+    local addr = 0x40
+
+    ------------------软件I2C---------------------------------
+    local io_scl = 5  -- PIN66 default GPIO5
+    local io_sda = 4  -- PIN67 default GPIO4
+
+    local softI2C = i2c.createSoft(io_scl,io_sda)
+    log.info("i2c", "sw i2c initial", softI2C) --初始化I2C
+    while true do
+        i2c.send(softI2C, addr, string.char(0xF3)) --发送0xF3来查询温度
+        sys.wait(100)
+        tmp = i2c.recv(softI2C, addr, 2)  --读取传感器的温度值
+        log.info("SHT20", "read tem data", tmp:toHex())
+        i2c.send(softI2C, addr, string.char(0xF5)) --发送0xF5来查询湿度
+        sys.wait(100)
+        hum = i2c.recv(softI2C, addr, 2)  --读取传感器湿度值
+        log.info("SHT20", "read hum data", hum:toHex())
+        local _,tval = pack.unpack(tmp,'>H') --提取一个按照大端字节序编码的16位无符号整数
+        local _,hval = pack.unpack(hum,'>H')
+        log.info("SHT20", "tval hval", tval,hval)
+        if tval and hval then
+            --按照传感器手册来计算对应的温湿度
+            temp = (((17572 * tval) >> 16) - 4685)/100
+            hump = (((12500 * hval) >> 16) - 600)/100
+            log.info("SHT20", "temp,humi",string.format("%.2f",temp),string.format("%.2f",hump))
+        end
+        sys.wait(1000)
+    end
+
+end)
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 218 - 0
module/Air8000/demo/iconv/main.lua

@@ -0,0 +1,218 @@
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "my_test"
+VERSION = "1.2"
+PRODUCT_KEY = "s1uUnY6KA06ifIjcutm5oNbG3MZf5aUv" -- 换成自己的
+-- sys库是标配
+_G.sys = require("sys")
+_G.sysplus = require("sysplus")
+
+--- unicode小端编码 转化为 gb2312编码
+-- @string ucs2s unicode小端编码数据
+-- @return string data,gb2312编码数据
+-- @usage local data = common.ucs2ToGb2312(ucs2s)
+function ucs2ToGb2312(ucs2s)
+    local cd = iconv.open("gb2312", "ucs2")
+    return cd:iconv(ucs2s)
+end
+
+--- gb2312编码 转化为 unicode小端编码
+-- @string gb2312s gb2312编码数据
+-- @return string data,unicode小端编码数据
+-- @usage local data = common.gb2312ToUcs2(gb2312s)
+function gb2312ToUcs2(gb2312s)
+    local cd = iconv.open("ucs2", "gb2312")
+    return cd:iconv(gb2312s)
+end
+
+--- unicode大端编码 转化为 gb2312编码
+-- @string ucs2s unicode大端编码数据
+-- @return string data,gb2312编码数据
+-- @usage data = common.ucs2beToGb2312(ucs2s)
+function ucs2beToGb2312(ucs2s)
+    local cd = iconv.open("gb2312", "ucs2be")
+    return cd:iconv(ucs2s)
+end
+
+--- gb2312编码 转化为 unicode大端编码
+-- @string gb2312s gb2312编码数据
+-- @return string data,unicode大端编码数据
+-- @usage local data = common.gb2312ToUcs2be(gb2312s)
+function gb2312ToUcs2be(gb2312s)
+    local cd = iconv.open("ucs2be", "gb2312")
+    return cd:iconv(gb2312s)
+end
+
+--- unicode小端编码 转化为 utf8编码
+-- @string ucs2s unicode小端编码数据
+-- @return string data,utf8编码数据
+-- @usage data = common.ucs2ToUtf8(ucs2s)
+function ucs2ToUtf8(ucs2s)
+    local cd = iconv.open("utf8", "ucs2")
+    return cd:iconv(ucs2s)
+end
+
+--- utf8编码 转化为 unicode小端编码
+-- @string utf8s utf8编码数据
+-- @return string data,unicode小端编码数据
+-- @usage local data = common.utf8ToUcs2(utf8s)
+function utf8ToUcs2(utf8s)
+    local cd = iconv.open("ucs2", "utf8")
+    return cd:iconv(utf8s)
+end
+
+--- unicode大端编码 转化为 utf8编码
+-- @string ucs2s unicode大端编码数据
+-- @return string data,utf8编码数据
+-- @usage data = common.ucs2beToUtf8(ucs2s)
+function ucs2beToUtf8(ucs2s)
+    local cd = iconv.open("utf8", "ucs2be")
+    return cd:iconv(ucs2s)
+end
+
+--- utf8编码 转化为 unicode大端编码
+-- @string utf8s utf8编码数据
+-- @return string data,unicode大端编码数据
+-- @usage local data = common.utf8ToUcs2be(utf8s)
+function utf8ToUcs2be(utf8s)
+    local cd = iconv.open("ucs2be", "utf8")
+    return cd:iconv(utf8s)
+end
+
+--- utf8编码 转化为 gb2312编码
+-- @string utf8s utf8编码数据
+-- @return string data,gb2312编码数据
+-- @usage local data = common.utf8ToGb2312(utf8s)
+function utf8ToGb2312(utf8s)
+    local cd = iconv.open("ucs2", "utf8")
+    local ucs2s = cd:iconv(utf8s)
+    cd = iconv.open("gb2312", "ucs2")
+    return cd:iconv(ucs2s)
+end
+
+--- gb2312编码 转化为 utf8编码
+-- @string gb2312s gb2312编码数据
+-- @return string data,utf8编码数据
+-- @usage local data = common.gb2312ToUtf8(gb2312s)
+function gb2312ToUtf8(gb2312s)
+    local cd = iconv.open("ucs2", "gb2312")
+    local ucs2s = cd:iconv(gb2312s)
+    cd = iconv.open("utf8", "ucs2")
+    return cd:iconv(ucs2s)
+end
+
+--------------------------------------------------------------------------------------------------------
+--[[
+函数名:ucs2ToGb2312
+功能  :unicode小端编码 转化为 gb2312编码,并打印出gb2312编码数据
+参数  :
+        ucs2s:unicode小端编码数据,注意输入参数的字节数
+返回值:
+]]
+local function testucs2ToGb2312(ucs2s)
+    print("ucs2ToGb2312")
+    local gb2312num = ucs2ToGb2312(ucs2s)--调用的是common.ucs2ToGb2312,返回的是编码所对应的字符串
+    --print("gb2312  code:",gb2312num)
+    print("gb2312  code:",string.toHex(gb2312num))
+end
+
+--[[
+函数名:gb2312ToUcs2
+功能  :gb2312编码 转化为 unicode十六进制小端编码数据并打印
+参数  :
+        gb2312s:gb2312编码数据,注意输入参数的字节数
+返回值:
+]]
+local function testgb2312ToUcs2(gb2312s)
+    print("gb2312ToUcs2")
+    local ucs2num = gb2312ToUcs2(gb2312s)
+    print("unicode little-endian code:" .. string.toHex(ucs2num)) -- 要将二进制转换为十六进制,否则无法输出
+end
+
+--[[
+函数名:ucs2beToGb2312
+功能  :unicode大端编码 转化为 gb2312编码,并打印出gb2312编码数据,
+大端编码数据是与小端编码数据位置调换
+参数  :
+        ucs2s:unicode大端编码数据,注意输入参数的字节数
+返回值:
+]]
+local function testucs2beToGb2312(ucs2s)
+    print("ucs2beToGb2312")
+    local gb2312num = ucs2beToGb2312(ucs2s) -- 转化后的数据直接变成字符可以直接输出
+    print("gb2312 code :" .. string.toHex(gb2312num))
+end
+
+--[[
+函数名:gb2312ToUcs2be
+功能  :gb2312编码 转化为 unicode大端编码,并打印出unicode大端编码
+参数  :
+        gb2312s:gb2312编码数据,注意输入参数的字节数
+返回值:unicode大端编码数据
+]]
+function testgb2312ToUcs2be(gb2312s)
+    print("gb2312ToUcs2be")
+    local ucs2benum = gb2312ToUcs2be(gb2312s)
+    print("unicode big-endian code :" .. string.toHex(ucs2benum))
+end
+
+--[[
+函数名:ucs2ToUtf8
+功能  :unicode小端编码 转化为 utf8编码,并打印出utf8十六进制编码数据
+参数  :
+        ucs2s:unicode小端编码数据,注意输入参数的字节数
+返回值:
+]]
+local function testucs2ToUtf8(ucs2s)
+    print("ucs2ToUtf8")
+    local utf8num = ucs2ToUtf8(ucs2s)
+    print("utf8  code:" .. string.toHex(utf8num))
+
+end
+
+--[[
+函数名:utf8ToGb2312
+功能  :utf8编码 转化为 gb2312编码,并打印出gb2312编码数据
+参数  :
+        utf8s:utf8编码数据,注意输入参数的字节数
+返回值:
+]]
+local function testutf8ToGb2312(utf8s)
+    print("utf8ToGb2312")
+    local gb2312num = utf8ToGb2312(utf8s)
+    print("gb2312 code:" .. string.toHex(gb2312num))
+
+end
+
+--[[
+函数名:gb2312ToUtf8
+功能  :gb2312编码 转化为 utf8编码,并打印出utf8编码数据
+参数  :
+        gb2312s:gb2312s编码数据,注意输入参数的字节数
+返回值:
+]]
+local function testgb2312ToUtf8(gb2312s)
+    print("gb2312ToUtf8")
+    local utf8s = gb2312ToUtf8(gb2312s)
+    print("utf8s code:" .. utf8s)
+
+end
+
+
+
+sys.taskInit(function()
+    while 1 do
+        sys.wait(1000)
+        testucs2ToGb2312(string.fromHex("1162")) -- "1162"是"我"字的ucs2编码,这里调用了string.fromHex将参数转化为二进制,也就是两个字节。
+        testgb2312ToUcs2(string.fromHex("CED2")) -- "CED2"是"我"字的gb2312编码
+        testucs2beToGb2312(string.fromHex("6211")) -- "6211"是"我"字的ucs2be编码
+        testgb2312ToUcs2be(string.fromHex("CED2"))
+        testucs2ToUtf8(string.fromHex("1162"))
+        testutf8ToGb2312(string.fromHex("E68891")) -- "E68891"是"我"字的utf8编码
+        testgb2312ToUtf8(string.fromHex("CED2"))
+    end
+end)
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 83 - 0
module/Air8000/demo/iotcloud/aliyun/示例1 一型一密(免预注册,但需要是企业版实例平台)方式连接云平台/main.lua

@@ -0,0 +1,83 @@
+
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "aliyun_yxym_myzc"
+VERSION = "1.0.0"
+
+-- sys库是标配
+_G.sys = require("sys")
+--[[特别注意, 使用mqtt库需要下列语句]]
+_G.sysplus = require("sysplus")
+
+local iotcloud = require("iotcloud")
+
+
+-- 统一联网函数
+sys.taskInit(function()
+    local device_id = mcu.unique_id():toHex()
+    if mobile then
+        device_id = mobile.imei()
+    else
+        -- 其他不认识的bsp, 循环提示一下吧
+        while 1 do
+            sys.wait(1000)
+            log.info("bsp", "本bsp可能未适配网络层, 请查证")
+        end
+    end
+    -- 默认都等到联网成功
+    sys.waitUntil("IP_READY")
+    sys.publish("net_ready", device_id)
+end)
+
+sys.taskInit(function()
+    -- 等待联网
+    local ret, device_id = sys.waitUntil("net_ready")
+
+    --------    以下接入方式根据自己需要修改,相关参数修改为自己的    ---------
+
+    -- 阿里云  
+    -- 动态注册(免预注册)(一型一密)(仅企业版支持)
+    iotcloudc = iotcloud.new(iotcloud.ALIYUN,{instance_id = "xxx",produt_id = "xxx",product_secret = "xxx"}) -- 企业版公共实例
+    -- 动态注册(预注册)(一型一密)
+    -- iotcloudc = iotcloud.new(iotcloud.ALIYUN,{produt_id = "xxx",device_name = "xxx",product_secret = "xxx"})                     -- 旧版公共实例
+    -- iotcloudc = iotcloud.new(iotcloud.ALIYUN,{instance_id = "xxx",produt_id = "xxx",device_name = "xxx",product_secret = "xxx"}) -- 新版公共实例
+    -- 密钥校验 (预注册)(一机一密)
+    -- iotcloudc = iotcloud.new(iotcloud.ALIYUN,{produt_id = "xxx",device_name = "xxx",device_secret = "xxx"})                    -- 旧版公共实例
+    -- iotcloudc = iotcloud.new(iotcloud.ALIYUN,{instance_id = "xxx",produt_id = "xxx",device_name = "xxx",device_secret = "xxx"})-- 新版公共实例
+
+    if iotcloudc then
+        iotcloudc:connect()
+    end
+
+end)
+
+sys.subscribe("iotcloud", function(cloudc,event,data,payload)
+    -- 注意,此处不是协程内,复杂操作发消息给协程内进行处理
+    if event == iotcloud.CONNECT then -- 云平台联上了
+        print("iotcloud","CONNECT", "云平台连接成功")
+        iotcloudc:subscribe("/"..iotcloudc.product_id.."/"..iotcloudc.device_name.."/user/get") -- 订阅主题,用于下发消息
+    elseif event == iotcloud.RECEIVE then
+        print("iotcloud","topic", data, "payload", payload)
+        -- 用户处理代码
+    elseif event ==  iotcloud.OTA then
+        if data then
+            rtos.reboot()
+        end
+    elseif event == iotcloud.DISCONNECT then -- 云平台断开了
+        -- 用户处理代码
+    end
+end)
+
+-- 每隔2秒发布一次qos为1的消息到云平台
+sys.taskInit(function()
+    while 1 do
+        sys.wait(2000)
+        if iotcloudc then
+            iotcloudc:publish("/"..iotcloudc.product_id.."/"..iotcloudc.device_name.."/user/update", "hello world", 1) -- 上传数据
+        end
+    end
+end)
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 82 - 0
module/Air8000/demo/iotcloud/aliyun/示例2 一型一密(预注册)方式连接云平台/main.lua

@@ -0,0 +1,82 @@
+
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "aliyun_yxym_yzc"
+VERSION = "1.0.0"
+
+-- sys库是标配
+_G.sys = require("sys")
+--[[特别注意, 使用mqtt库需要下列语句]]
+_G.sysplus = require("sysplus")
+
+local iotcloud = require("iotcloud")
+
+-- 统一联网函数
+sys.taskInit(function()
+    local device_id = mcu.unique_id():toHex()
+    if mobile then
+        device_id = mobile.imei()
+    else
+        -- 其他不认识的bsp, 循环提示一下吧
+        while 1 do
+            sys.wait(1000)
+            log.info("bsp", "本bsp可能未适配网络层, 请查证")
+        end
+    end
+    -- 默认都等到联网成功
+    sys.waitUntil("IP_READY")
+    sys.publish("net_ready", device_id)
+end)
+
+sys.taskInit(function()
+    -- 等待联网
+    local ret, device_id = sys.waitUntil("net_ready")
+
+    --------    以下接入方式根据自己需要修改,相关参数修改为自己的    ---------
+
+    -- 阿里云  
+    -- 动态注册(免预注册)(一型一密)(仅企业版支持)
+    -- iotcloudc = iotcloud.new(iotcloud.ALIYUN,{instance_id = "xxx",produt_id = "xxx",product_secret = "xxx"}) -- 企业版公共实例
+    -- 动态注册(预注册)(一型一密)
+    -- iotcloudc = iotcloud.new(iotcloud.ALIYUN,{produt_id = "xxx",device_name = "xxx",product_secret = "xxx"})                     -- 旧版公共实例
+    iotcloudc = iotcloud.new(iotcloud.ALIYUN,{instance_id = "xxx",produt_id = "xxx",device_name = "xxx",product_secret = "xxx"}) -- 新版公共实例
+    -- 密钥校验 (预注册)(一机一密)
+    -- iotcloudc = iotcloud.new(iotcloud.ALIYUN,{produt_id = "xxx",device_name = "xxx",device_secret = "xxx"})                    -- 旧版公共实例
+    -- iotcloudc = iotcloud.new(iotcloud.ALIYUN,{instance_id = "xxx",produt_id = "xxx",device_name = "xxx",device_secret = "xxx"})-- 新版公共实例
+
+    if iotcloudc then
+        iotcloudc:connect()
+    end
+
+end)
+
+sys.subscribe("iotcloud", function(cloudc,event,data,payload)
+    -- 注意,此处不是协程内,复杂操作发消息给协程内进行处理
+    if event == iotcloud.CONNECT then -- 云平台联上了
+        print("iotcloud","CONNECT", "云平台连接成功")
+        iotcloudc:subscribe("/"..iotcloudc.product_id.."/"..iotcloudc.device_name.."/user/get") -- 订阅主题,用于下发消息
+    elseif event == iotcloud.RECEIVE then
+        print("iotcloud","topic", data, "payload", payload)
+        -- 用户处理代码
+    elseif event ==  iotcloud.OTA then
+        if data then
+            rtos.reboot()
+        end
+    elseif event == iotcloud.DISCONNECT then -- 云平台断开了
+        -- 用户处理代码
+    end
+end)
+
+-- 每隔2秒发布一次qos为1的消息到云平台
+sys.taskInit(function()
+    while 1 do
+        sys.wait(2000)
+        if iotcloudc then
+            iotcloudc:publish("/"..iotcloudc.product_id.."/"..iotcloudc.device_name.."/user/update", "hello world", 1) -- 上传数据
+        end
+    end
+end)
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 82 - 0
module/Air8000/demo/iotcloud/aliyun/示例3 一机一密方式连接云平台/main.lua

@@ -0,0 +1,82 @@
+
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "aliyun_yjym_yzc"
+VERSION = "1.0.0"
+
+-- sys库是标配
+_G.sys = require("sys")
+--[[特别注意, 使用mqtt库需要下列语句]]
+_G.sysplus = require("sysplus")
+
+local iotcloud = require("iotcloud")
+
+-- 统一联网函数
+sys.taskInit(function()
+    local device_id = mcu.unique_id():toHex()
+    if mobile then
+        device_id = mobile.imei()
+    else
+        -- 其他不认识的bsp, 循环提示一下吧
+        while 1 do
+            sys.wait(1000)
+            log.info("bsp", "本bsp可能未适配网络层, 请查证")
+        end
+    end
+    -- 默认都等到联网成功
+    sys.waitUntil("IP_READY")
+    sys.publish("net_ready", device_id)
+end)
+
+sys.taskInit(function()
+    -- 等待联网
+    local ret, device_id = sys.waitUntil("net_ready")
+
+    --------    以下接入方式根据自己需要修改,相关参数修改为自己的    ---------
+
+    -- 阿里云  
+    -- 动态注册(免预注册)(一型一密)(仅企业版支持)
+    -- iotcloudc = iotcloud.new(iotcloud.ALIYUN,{instance_id = "xxx",produt_id = "xxx",product_secret = "xxx"}) -- 企业版公共实例
+    -- 动态注册(预注册)(一型一密)
+    -- iotcloudc = iotcloud.new(iotcloud.ALIYUN,{produt_id = "xxx",device_name = "xxx",product_secret = "xxx"})                     -- 旧版公共实例
+    -- iotcloudc = iotcloud.new(iotcloud.ALIYUN,{instance_id = "xxx",produt_id = "xxx",device_name = "xxx",product_secret = "xxx"}) -- 新版公共实例
+    -- 密钥校验 (预注册)(一机一密)
+    -- iotcloudc = iotcloud.new(iotcloud.ALIYUN,{produt_id = "xxx",device_name = "xxx",device_secret = "xxx"})                    -- 旧版公共实例
+    iotcloudc = iotcloud.new(iotcloud.ALIYUN,{instance_id = "xxx",produt_id = "xxx",device_name = "xxx",device_secret = "xxx"})-- 新版公共实例
+
+    if iotcloudc then
+        iotcloudc:connect()
+    end
+
+end)
+
+sys.subscribe("iotcloud", function(cloudc,event,data,payload)
+    -- 注意,此处不是协程内,复杂操作发消息给协程内进行处理
+    if event == iotcloud.CONNECT then -- 云平台联上了
+        print("iotcloud","CONNECT", "云平台连接成功")
+        iotcloudc:subscribe("/"..iotcloudc.product_id.."/"..iotcloudc.device_name.."/user/get") -- 订阅主题,用于下发消息
+    elseif event == iotcloud.RECEIVE then
+        print("iotcloud","topic", data, "payload", payload)
+        -- 用户处理代码
+    elseif event ==  iotcloud.OTA then
+        if data then
+            rtos.reboot()
+        end
+    elseif event == iotcloud.DISCONNECT then -- 云平台断开了
+        -- 用户处理代码
+    end
+end)
+
+-- 每隔2秒发布一次qos为1的消息到云平台
+sys.taskInit(function()
+    while 1 do
+        sys.wait(2000)
+        if iotcloudc then
+            iotcloudc:publish("/"..iotcloudc.product_id.."/"..iotcloudc.device_name.."/user/update", "hello world", 1) -- 上传数据
+        end
+    end
+end)
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 70 - 0
module/Air8000/demo/iotcloud/baiduiot/main.lua

@@ -0,0 +1,70 @@
+
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "iotclouddemo"
+VERSION = "1.0.0"
+
+-- sys库是标配
+_G.sys = require("sys")
+--[[特别注意, 使用mqtt库需要下列语句]]
+_G.sysplus = require("sysplus")
+
+local iotcloud = require("iotcloud")
+
+-- 统一联网函数
+sys.taskInit(function()
+    local device_id = mcu.unique_id():toHex()
+    if mobile then
+        LED = gpio.setup(27, 0, gpio.PULLUP)
+        device_id = mobile.imei()
+    end
+    -- 默认都等到联网成功
+    sys.waitUntil("IP_READY")
+    sys.publish("net_ready", device_id)
+end)
+
+sys.taskInit(function()
+    -- 等待联网
+    local ret, device_id = sys.waitUntil("net_ready")
+
+    -- 百度云
+    -- 密钥认证(手动注册)
+    -- iotcloudc = iotcloud.new(iotcloud.BAIDU,{produt_id = "aakyhyw",device_name = "869329069169988",device_secret = "IzNIWqXdGRPEoUlS"})
+    -- 证书认证(自动注册)
+    iotcloudc = iotcloud.new(iotcloud.BAIDU,{produt_id = "aakyhyw",device_name = "869329069169988"},{tls={server_cert=io.readFile("/luadb/GlobalSign.cer"),client_cert=io.readFile("/luadb/client_cert.txt"),client_key=io.readFile("/luadb/client_private_key.txt")}})
+
+    if iotcloudc then
+        iotcloudc:connect()
+    end
+end)
+
+sys.subscribe("iotcloud", function(cloudc,event,data,payload)
+    -- 注意,此处不是协程内,复杂操作发消息给协程内进行处理
+    if event == iotcloud.CONNECT then -- 云平台联上了
+        print("iotcloud","CONNECT", "云平台连接成功")
+        iotcloudc:subscribe("$iot/869329069169988/user/fortest") -- 可以自由订阅主题等
+
+    elseif event == iotcloud.RECEIVE then
+        print("iotcloud","topic", data, "payload", payload)
+        if payload == "open" then
+            log.info("main", "收到云平台下发的指令")
+            LED(1)
+        elseif payload == "close" then
+            LED(0)
+        end
+        -- 用户处理代码
+    elseif event ==  iotcloud.OTA then
+        if data then
+            rtos.reboot()
+        end
+    elseif event == iotcloud.DISCONNECT then -- 云平台断开了
+        -- 用户处理代码
+        print("iotcloud","DISCONNECT", "云平台连接断开")
+    end
+end)
+
+
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 88 - 0
module/Air8000/demo/iotcloud/huaweiiot/main.lua

@@ -0,0 +1,88 @@
+
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "iotclouddemo"
+VERSION = "1.0.0"
+
+-- sys库是标配
+_G.sys = require("sys")
+--[[特别注意, 使用mqtt库需要下列语句]]
+_G.sysplus = require("sysplus")
+
+local iotcloud = require("iotcloud")
+
+-- 统一联网函数
+sys.taskInit(function()
+    local device_id = mcu.unique_id():toHex()
+    if mobile then
+        -- LED = gpio.setup(27, 0, gpio.PULLUP)
+        device_id = mobile.imei()
+    end
+    -- 默认都等到联网成功
+    sys.waitUntil("IP_READY")
+    sys.publish("net_ready", device_id)
+end)
+
+sys.taskInit(function()
+    -- 等待联网
+    local ret, device_id = sys.waitUntil("net_ready")
+
+    -- -- 华为云
+    -- -- 动态注册(免预注册)
+    -- iotcloudc = iotcloud.new(iotcloud.HUAWEI,{produt_id = "670c7b2dfc8d5a4ea71c6a79",
+    --                                             project_id = "c086a58ebd714bfcb1a0fea2f0edde36",
+    --                                             endpoint = "9098a2ff3c.st1",
+    --                                             iam_username="hao",
+    --                                             iam_password="Wsh1322764769",
+    --                                             iam_domain="hao15738882476"})
+    -- 密钥校验 (预注册)
+    iotcloudc = iotcloud.new(iotcloud.HUAWEI,{produt_id = "670c7b2dfc8d5a4ea71c6a79",endpoint = "5341624af8.st1",device_name = "869329069169988",device_secret = "XXX"})
+
+    if iotcloudc then
+        iotcloudc:connect()
+    end
+end)
+
+sys.subscribe("iotcloud", function(cloudc,event,data,payload)
+    -- 注意,此处不是协程内,复杂操作发消息给协程内进行处理
+    if event == iotcloud.CONNECT then -- 云平台联上了
+        print("iotcloud","CONNECT", "云平台连接成功")
+        -- iotcloudc:subscribe("/huawei/down/869329069169988") -- 可以自由定阅主题等
+        -- iotcloudc:subscribe("$oc/devices/869329069169988/user/869329069169988")
+    elseif event == iotcloud.RECEIVE then
+        print("iotcloud","topic", data, "payload", payload)
+        -- local test_value = json.decode(payload).content.switch
+        -- print("test value:", test_value)
+
+        -- if test_value == 1 then
+        --     LED(1)
+        -- elseif test_value == 0 then
+        --     LED(0)
+        -- end
+        -- 用户处理代码
+    elseif event ==  iotcloud.OTA then
+        if data then
+            rtos.reboot()
+        end
+    elseif event == iotcloud.DISCONNECT then -- 云平台断开了
+        -- 用户处理代码
+        print("iotcloud","DISCONNECT", "云平台连接断开")
+    end
+end)
+
+-- -- 每隔2秒发布一次qos为1的消息到云平台
+-- sys.taskInit(function()
+--     while 1 do
+--         sys.wait(2000)
+--         if iotcloudc then
+--             iotcloudc:publish("$oc/devices/869329069169988/user/869329069169988", "hello world!", 1) -- 上传数据
+--         end
+--     end
+-- end)
+
+
+
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 157 - 0
module/Air8000/demo/iotcloud/onenet/main.lua

@@ -0,0 +1,157 @@
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "oneNET_demo"
+VERSION = "1.0.0"
+
+-- sys库是标配
+_G.sys = require("sys")
+--[[特别注意, 使用mqtt库需要下列语句]]
+_G.sysplus = require("sysplus")
+lbsLoc2 = require("lbsLoc2")
+local iotcloud = require("iotcloud")
+mobile.simid(2, true)
+
+local produt_id = "4qM5N1Sa4T"
+local userid = "226691"
+local userkey = "pk1M3FKXBvvmjF8If/xDfSFFmr96NZCEg00sxlLBMjjh9vOD5hpIs42rmAYnMh5b3m9B1+0rmYdqzUyoQVrxow=="
+local device_name = mobile.imei()
+local send_data_time = 5 * 60 * 1000 -- 定时发送数据的时间,单位ms
+
+-- 统一联网函数
+sys.taskInit(function()
+    local device_id = mcu.unique_id():toHex()
+
+    -- 默认都等到联网成功
+    sys.waitUntil("IP_READY")
+    sys.publish("net_ready", device_id)
+end)
+
+sys.taskInit(function()
+    -- 等待联网
+    local ret, device_id = sys.waitUntil("net_ready")
+
+    --------    以下接入方式根据自己需要修改,相关参数修改为自己的    ---------
+
+    -- ONENET云
+    -- 动态注册
+    iotcloudc = iotcloud.new(iotcloud.ONENET, {
+        device_name = device_name,
+        produt_id = produt_id,
+        userid = userid,
+        userkey = userkey
+    })
+    -- 一型一密
+    -- iotcloudc = iotcloud.new(iotcloud.ONENET,{produt_id = "xxx",product_secret = "xxx"})
+    -- 一机一密
+    -- iotcloudc = iotcloud.new(iotcloud.ONENET,{produt_id = "xxx",device_name = "xxx",device_secret = "xxx"})
+
+    if iotcloudc then
+        iotcloudc:connect()
+    end
+
+end)
+
+-- 发布和订阅的主题
+
+local oneNET_sub = "$sys/" .. produt_id .. "/" .. device_name .. "/thing/property/post/reply"
+
+local oneNET_pub = "$sys/" .. produt_id .. "/" .. device_name .. "/thing/property/post"
+
+local function oneNET_send_data()
+    log.info("oneNET 链接成功,准备开始发送数据")
+    while 1 do
+        -- 没有mobile库就没有基站定位
+        mobile.reqCellInfo(15)
+        -- 由于基站定位需要等待扫描周围基站,推荐扫描时间为15S
+        sys.waitUntil("CELL_INFO_UPDATE", 15000)
+        local lat, lng, t = lbsLoc2.request(5000)
+        log.info("lbsLoc2", lat, lng, (json.encode(t or {})))
+        -- 如果没扫描到基站则给lat和lng赋值为0
+        if lat and lng then
+            log.info("扫描到了,有位置信息")
+        else
+            lat = "0"
+            lng = "0"
+        end
+        -- 读取CPU温度, 单位为0.001摄氏度, 是内部温度, 非环境温度
+        adc.open(adc.CH_CPU)
+        local cpu_temp = adc.get(adc.CH_CPU)
+        adc.close(adc.CH_CPU)
+        local gpio_pin = 6 -- GPIO编号
+        local gpio_state = gpio.get(gpio_pin)
+        local send_data = {
+            id = "123",
+            verson = VERSION,
+            params = {
+                gpio_state = {
+                    value = gpio_state
+                },
+                cpu_temp = {
+                    value = cpu_temp / 1000
+                },
+                lbs_lat = {
+                    value = tonumber(lat)
+                },
+                lbs_lng = {
+                    value = tonumber(lng)
+                    -- value = lng
+                }
+            }
+        }
+        local send_data = json.encode(send_data)
+        log.info("发送的数据为", send_data)
+        -- 正式发布数据
+        iotcloudc:publish(oneNET_pub, send_data)
+        -- 循环发送数据的定时时间
+        sys.wait(send_data_time)
+    end
+
+end
+
+local con = 0
+--oneNET断开后的处理函数,
+local function oneNET_DISCONNECT()
+    log.info("云平台断开了,隔一分钟重连一次,如果10次都没有连上则重启设备")
+    while con < 10 do
+        sys.wait(60*1000)
+        log.info("oneNET reconnection",con)
+        iotcloudc:connect()
+    end
+    pm.reboot()
+end
+sys.subscribe("iotcloud", function(cloudc, event, data, payload)
+    -- 注意,此处不是协程内,复杂操作发消息给协程内进行处理
+    if event == iotcloud.CONNECT then -- 云平台联上了
+        log.info("iotcloud", "CONNECT", "oneNET平台连接成功")
+        iotcloudc:subscribe({
+            [oneNET_sub] = 1
+        }) -- 订阅服务器下发数据的主题
+        -- 链接成功,启动一个task专门用来定时发消息
+        sys.taskInit(oneNET_send_data)
+
+    elseif event == iotcloud.RECEIVE then
+        log.info("收到服务器下发的数据")
+        log.info("iotcloud", "topic", data, "payload", payload)
+
+        -- 用户处理代码
+        if payload then
+            payload = json.decode(payload)
+            if payload["code"] == 200 then
+                log.info("服务器收到了刚刚上传的数据", payload["msg"])
+            else
+                log.info("服务器接收数据有误", "错误码为", payload["code"], "错误信息为",
+                    payload["msg"])
+            end
+        end
+
+    elseif event == iotcloud.SEND then
+        log.info("发送数据成功")
+
+    elseif event == iotcloud.DISCONNECT then -- 云平台断开了
+       sys.taskInit(oneNET_DISCONNECT)
+    end
+end)
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 79 - 0
module/Air8000/demo/iotcloud/tencentiot/main.lua

@@ -0,0 +1,79 @@
+
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "iotclouddemo"
+VERSION = "1.0.0"
+
+-- sys库是标配
+_G.sys = require("sys")
+--[[特别注意, 使用mqtt库需要下列语句]]
+_G.sysplus = require("sysplus")
+
+local iotcloud = require("iotcloud")
+
+-- 统一联网函数
+sys.taskInit(function()
+    local device_id = mcu.unique_id():toHex()
+    if mobile then
+        LED = gpio.setup(27, 0, gpio.PULLUP)
+        device_id = mobile.imei()
+    end
+    -- 默认都等到联网成功
+    sys.waitUntil("IP_READY")
+    sys.publish("net_ready", device_id)
+end)
+
+sys.taskInit(function()
+    -- 等待联网
+    local ret, device_id = sys.waitUntil("net_ready")
+
+    -- -- 腾讯云
+    -- -- 动态注册
+    -- iotcloudc = iotcloud.new(iotcloud.TENCENT,{produt_id = "ZAJCHA24SH" ,product_secret = "vGGwnSkyM4eD5ddbNrQoGJox"})
+    -- -- 密钥校验
+    iotcloudc = iotcloud.new(iotcloud.TENCENT,{produt_id = "ZAJCHA24SH",device_name = "869329069169988",device_secret = "xNWcxDX0qzSM74oFteehvw=="})
+
+    if iotcloudc then
+        iotcloudc:connect()
+    end
+end)
+
+sys.subscribe("iotcloud", function(cloudc,event,data,payload)
+    -- 注意,此处不是协程内,复杂操作发消息给协程内进行处理
+    if event == iotcloud.CONNECT then -- 云平台联上了
+        print("iotcloud","CONNECT", "云平台连接成功")
+        iotcloudc:subscribe("$thing/down/property/ZAJCHA24SH/869329069169988") -- 可以自由定阅主题等
+    elseif event == iotcloud.RECEIVE then
+        print("iotcloud","topic", data, "payload", payload)
+        local test_value = json.decode(payload).params.switch
+        print("test value:", test_value)
+
+        if test_value == 1 then
+            LED(1)
+        elseif test_value == 0 then
+            LED(0)
+        end
+        -- 用户处理代码
+    elseif event ==  iotcloud.OTA then
+        if data then
+            rtos.reboot()
+        end
+    elseif event == iotcloud.DISCONNECT then -- 云平台断开了
+        -- 用户处理代码
+        print("iotcloud","DISCONNECT", "云平台连接断开")
+    end
+end)
+
+-- 每隔2秒发布一次qos为1的消息到云平台
+sys.taskInit(function()
+    while 1 do
+        sys.wait(2000)
+        if iotcloudc then
+            iotcloudc:publish("$thing/up/property/ZAJCHA24SH/869329069169988", "hello world!", 1) -- 上传数据
+        end
+    end
+end)
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 70 - 0
module/Air8000/demo/iotcloud/tuyaiot/示例1 一机一密/main.lua

@@ -0,0 +1,70 @@
+
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "iotclouddemo"
+VERSION = "1.0.0"
+
+-- sys库是标配
+_G.sys = require("sys")
+--[[特别注意, 使用mqtt库需要下列语句]]
+_G.sysplus = require("sysplus")
+
+local iotcloud = require("iotcloud")
+
+-- 统一联网函数
+sys.taskInit(function()
+    local device_id = mcu.unique_id():toHex()
+    -----------------------------
+    if mobile then
+        device_id = mobile.imei()
+    else
+        -- 其他不认识的bsp, 循环提示一下吧
+        while 1 do
+            sys.wait(1000)
+            log.info("bsp", "本bsp可能未适配网络层, 请查证")
+        end
+    end
+    -- 默认都等到联网成功
+    sys.waitUntil("IP_READY")
+    sys.publish("net_ready", device_id)
+end)
+
+sys.taskInit(function()
+    -- 等待联网
+    local ret, device_id = sys.waitUntil("net_ready")
+
+    --------    以下接入方式根据自己需要修改,相关参数修改为自己的    ---------
+
+    -- -- 涂鸦云 
+    iotcloudc = iotcloud.new(iotcloud.TUYA,{device_name = "xxx",device_secret = "xxx"})
+
+    if iotcloudc then
+        iotcloudc:connect()
+    else
+        log.error("iotcloud", "创建失败, 请检查参数")
+    end
+    
+end)
+
+sys.subscribe("iotcloud", function(cloudc,event,data,payload)
+    -- 注意,此处不是协程内,复杂操作发消息给协程内进行处理
+    if event == iotcloud.CONNECT then -- 云平台联上了
+        print("iotcloud","CONNECT", "云平台连接成功")
+        iotcloudc : subscribe("tylink/${deviceId}/thing/property/set") -- 订阅信息
+        iotcloudc : publish("tylink/${deviceId}/thing/property/report" , '{"data":{"device_status":"999"}}' , 1) -- 上报信息
+    elseif event == iotcloud.RECEIVE then
+        print("iotcloud","topic", data, "payload", payload)
+        -- 用户处理代码
+    elseif event ==  iotcloud.OTA then
+        if data then
+            rtos.reboot()
+        end
+    elseif event == iotcloud.DISCONNECT then -- 云平台断开了
+        -- 用户处理代码
+    end
+end)
+
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 81 - 0
module/Air8000/demo/json/main.lua

@@ -0,0 +1,81 @@
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "jsondemo"
+VERSION = "1.0.0"
+
+-- 引入必要的库文件(lua编写), 内部库不需要require
+sys = require("sys")
+
+log.info("main", PROJECT, VERSION)
+
+-- json库支持将 table 转为 字符串, 或者反过来, 字符串 转 table
+-- 若转换失败, 会返回nil值, 强烈建议在使用时添加额外的判断
+sys.taskInit(function()
+    while 1 do
+        sys.wait(1000)
+        -- table 转为 字符串
+        local t = {abc=123, def="123", ttt=true}
+        local jdata = json.encode(t)
+        log.info("json", jdata)  									--日志输出:{"ttt":true,"def":"123","abc":123}
+
+        -- 字符串转table
+        local str = "{\"abc\":1234545}" -- 字符串可以来源于任何地方,网络,文本,用户输入,都可以
+        local t = json.decode(str)
+        if t then
+			-- 若解码成功,t不为nil
+			log.info("json", "decode", t.abc) 						--日志输出:decode	1234545
+		else
+			-- 若解码失败,t为nil
+			log.info("json", "decode failed")
+		end
+
+        -- lua中的table是 数组和hashmap的混合体
+        -- 这对json来说会有一些困扰, 尤其是空的table
+        local t = {abc={}}
+        -- 假设从业务上需要输出 {"abc":[]}
+        -- 实际会输出 {"abc": {}} , 空table是优先输出 hashmap (即字典模式)形式, 而非数组形式,Lua语言中数组优先级低于hashmap优先级
+        log.info("json", "encode", json.encode(t)) 					--日志输出:encode	{"abc":{}}
+        -- 混合场景, json场景应避免使用
+        t.abc.def = "123"
+        t.abc[1] = 345
+        -- 输出的内容是 {"abc":{"1":345,"def":"123"}}
+        log.info("json", "encode2", json.encode(t))  				--日志输出:encode2	{"abc":{"1":345,"def":"123"}}
+
+        -- 浮点数演示
+        log.info("json", json.encode({abc=1234.300}))  				--日志输出:{"abc":1234.300}
+        -- 限制小数点到1位
+        log.info("json", json.encode({abc=1234.300}, "1f")) 		--日志输出:{"abc":1234.3}
+
+ 
+        local tmp = "ABC\r\nDEF\r\n"
+        local tmp2 = json.encode({str=tmp}) --在JSON中,\r\n 被保留为字符串的一部分
+        log.info("json", tmp2)                                    	--日志输出:{"str":"ABC\r\nDEF\r\n"}
+        local tmp3 = json.decode(tmp2)								
+        log.info("json", "tmp3", tmp3.str, tmp3.str == tmp)			--日志输出:tmp3	ABC
+																		--DEF
+																		--		true  注:true前存在一个TAB长度(这个TAB原因未知,但不影响使用)
+        -- break
+
+        log.info("json.null", json.encode({name=json.null}))		--日志输出:{}  为空对象
+        log.info("json.null", json.decode("{\"abc\":null}").abc == json.null)  	--日志输出:false    在 Lua 中,nil 是一种特殊类型,用于表示“无值”或“未定义”。它与任何其他值(包括自定义的 json.null)都不相等
+        log.info("json.null", json.decode("{\"abc\":null}").abc == nil)			 --日志输出:false
+
+    end
+end)
+
+
+-- 这里演示4G模块上网后,会自动点亮网络灯,方便用户判断模块是否正常开机
+sys.taskInit(function()
+    while true do
+        sys.wait(6000)
+                if mobile.status() == 1 then
+                        gpio.set(27, 1)  
+                else
+                        gpio.set(27, 0) 
+                        mobile.reset()
+        end
+    end
+end)
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 31 - 0
module/Air8000/demo/lbsLoc2/main.lua

@@ -0,0 +1,31 @@
+
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "lbsLoc2demo"
+VERSION = "1.0.0"
+
+
+-- sys库是标配
+sys = require("sys")
+
+local lbsLoc2 = require("lbsLoc2")
+
+
+sys.taskInit(function()
+    sys.waitUntil("IP_READY", 30000)
+    -- mobile.reqCellInfo(60)
+    -- sys.wait(1000)
+    while mobile do -- 没有mobile库就没有基站定位
+        mobile.reqCellInfo(15)--进行基站扫描
+        sys.waitUntil("CELL_INFO_UPDATE", 3000)--等到扫描成功,超时时间3S
+        local lat, lng, t = lbsLoc2.request(5000)--仅需要基站定位给出的经纬度
+        --local lat, lng, t = lbsLoc2.request(5000,nil,nil,true)--需要经纬度和当前时间
+        --(时间格式{"year":2024,"min":56,"month":11,"day":12,"sec":44,"hour":14})
+        log.info("lbsLoc2", lat, lng, (json.encode(t or {})))
+        sys.wait(60000)
+    end
+end)
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 42 - 0
module/Air8000/demo/lcd/airlcd.lua

@@ -0,0 +1,42 @@
+local airLCD = {}
+
+function airLCD.lcd_init(sn)
+    if sn == "AirLCD_1000" then
+        width = 320
+        height = 480
+        lcd_ic = "st7796"
+    elseif sn == "AirLCD_1001" then
+        width = 320
+        height = 480
+        lcd_ic = "st7796"
+    elseif  sn == "AirLCD_1002" then
+        width = 480
+        height = 480
+        lcd_ic = "R395435T01"
+    else
+        log.info("lcd", "没有找到合适的LCD")
+    end
+
+    lcd_param = {
+        port = lcd.HWID_0,                 -- 使用的spi id 号
+        pin_dc = 0xff,            -- 命令选择硬件,不设置
+        pin_pwr = 9,           -- 背光控制管脚,默认打开背光,不设置
+        pin_rst = 2,             -- 屏幕reset 管脚  
+        direction = 0,            -- 屏幕方向
+        -- direction0 = 0x00,
+        w = width,                -- 屏幕宽度
+        h = height,               -- 屏幕高度
+        xoffset = 0,              -- X轴偏移像素
+        yoffset = 0,              -- Y轴偏移像素
+        sleepcmd = 0x10,          -- LCD睡眠命令
+        wakecmd = 0x11,           -- LCD唤醒命令
+    
+    }
+    
+ 
+    lcd.init(lcd_ic, lcd_param)     -- 初始化LCD 参数
+end
+
+
+
+return airLCD

+ 59 - 0
module/Air8000/demo/lcd/main.lua

@@ -0,0 +1,59 @@
+PROJECT = "lcddemo"
+VERSION = "1.0.0"
+
+log.info("main", PROJECT, VERSION)
+
+taskName = "lcd"
+local airlcd = require "airlcd"
+
+
+show_picture = "/luadb/picture.jpg"
+
+local function lcd_setup()
+    sys.wait(500)
+    gpio.setup(141, 1, gpio.PULLUP)              -- 如果是整机开发板则需要GPIO141打开给lcd电源供电,如果是核心板,可以自行选择供电管脚,或者直接选择vdd_ext管脚
+    sys.wait(1000)
+    airlcd.lcd_init("AirLCD_1000")
+end
+
+
+local function lcd_task()
+    lcd_setup()                     -- 初始化LCD
+    lcd.setupBuff(nil, true)        -- 设置缓冲区大小,使用系统内存
+    lcd.autoFlush(false)            -- 自动刷新LCD
+    while 1 do
+        lcd.clear()
+        log.info("合宙 Air8000 LCD演示")
+        -- API 文档 https://wiki.luatos.com/api/lcd.html
+        if io.exists(show_picture) ~= true then
+            log.info("picture.jpg 不存在,请检查下载的文件")
+            sys.wait(100)
+            return
+        end 
+
+        -- 注意, jpg需要是常规格式, 不能是渐进式JPG
+        -- 如果无法解码, 可以用画图工具另存为,新文件就能解码了
+        lcd.showImage(0, 0, show_picture)
+        sys.wait(100)
+       
+        -- log.info("lcd.drawLine", lcd.drawLine(100, 240, 240, 240, 0x001F)) -- 画线
+        -- log.info("lcd.drawRectangle", lcd.drawRectangle(100, 240, 240, 70, 0xF800)) -- 画框
+        -- log.info("lcd.drawCircle", lcd.drawCircle(150, 240, 100, 0x0CE0)) -- 画圆
+
+        -- lcd.setFont(lcd.font_opposansm32)
+        -- lcd.drawStr(60,240,"hello hezhou") --显示字符
+        lcd.flush()
+        sys.wait(1000)
+    end
+end
+
+
+sysplus.taskInitEx(lcd_task, taskName)   
+
+
+
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

BIN
module/Air8000/demo/lcd/picture.jpg


+ 21 - 0
module/Air8000/demo/led/main.lua

@@ -0,0 +1,21 @@
+-- 本示例对比了普通GPIO和AGPIO的进入休眠模式前后的区别。
+-- Luatools需要PROJECT和VERSION这两个信息
+PROJECT = "leddemo"
+VERSION = "1.0.0"
+
+log.info("main", PROJECT, VERSION)
+
+-- sys库是标配
+_G.sys = require("sys")
+
+
+local gpio_number = 27 -- AGPIO GPIO号为27,也是核心板上的网络指示灯(蓝灯)
+
+
+gpio.setup(gpio_number, 1)
+
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 60 - 0
module/Air8000/demo/log/main.lua

@@ -0,0 +1,60 @@
+
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "LOG"
+VERSION = "2.0.0"
+
+--[[
+本demo演示 string字符串的基本操作
+1. lua的字符串是带长度, 这意味着, 它不依赖0x00作为结束字符串, 可以包含任意数据
+2. lua的字符串是不可变的, 就不能直接修改字符串的一个字符, 修改字符会返回一个新的字符串
+]]
+
+-- sys库是标配
+_G.sys = require("sys")
+
+
+local netLed = require("netLed")
+--GPIO18配置为输出,默认输出低电平,可通过setGpio18Fnc(0或者1)设置输出电平
+local LEDA= gpio.setup(27, 0, gpio.PULLUP)
+
+sys.taskInit(function ()
+    sys.wait(1000) -- 免得看不到日志
+    local tmp
+
+	--实验1:输出四个等级的日志,日志等级排序从低到高为 debug < info < warn < error
+	log.debug(PROJECT, "debug message")
+	log.info(PROJECT, "info message")
+	log.warn(PROJECT, "warn message")
+	log.error(PROJECT, "error message")
+	
+	
+	--实验2:输出INFO及更高级别日志,即debug日志不输出
+	log.setLevel("INFO")
+	print(log.getLevel())
+
+	-- 这条debug级别的日志不会输出
+	log.debug(PROJECT, "debug message")
+	log.info(PROJECT, "info message")
+	log.warn(PROJECT, "warn message")
+	log.error(PROJECT, "error message")
+	
+	--实验3:通过日志输出变量内容
+	local myInteger = 42
+    log.info("Integer", myInteger)
+end)
+-- 这里演示4G模块上网后,会自动点亮网络灯,方便用户判断模块是否正常开机
+sys.taskInit(function()
+    while true do
+        sys.wait(6000)
+                if mobile.status() == 1 then
+                        gpio.set(27, 1)  
+                else
+                        gpio.set(27, 0) 
+                        mobile.reset()
+        end
+    end
+end)
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 90 - 0
module/Air8000/demo/lowpower/low_power_dissipation.lua

@@ -0,0 +1,90 @@
+
+-- netlab.luatos.com上打开TCP 有测试服务器
+local server_ip = "112.125.89.8"
+local server_port = 47523
+local is_udp = false --用户根据自己实际情况选择
+
+--是UDP服务器就赋值为true,是TCP服务器就赋值为flase
+--UDP服务器比TCP服务器功耗低
+--如果用户对数据的丢包率有极为苛刻的要求,最好选择TCP
+
+local Heartbeat_interval = 5 -- 发送数据的间隔时间,单位分钟
+-- 配置GPIO达到最低功耗
+gpio.setup(25, 0) -- 关闭GNSS电源
+gpio.setup(24, 0) -- 关闭三轴电源
+gpio.setup(23, 0) -- 关闭wifi电源
+-- 数据内容  
+local heart_data = string.rep("1234567890", 10)
+local rxbuf = zbuff.create(8192)
+
+local function netCB(netc, event, param)
+    if param ~= 0 then
+        sys.publish("socket_disconnect")
+        return
+    end
+    if event == socket.LINK then
+    elseif event == socket.ON_LINE then
+        -- 链接上服务器以后发送的第一包数据是 hello,luatos
+        socket.tx(netc, "hello,luatos!")
+
+    elseif event == socket.EVENT then
+        socket.rx(netc, rxbuf)
+        socket.wait(netc)
+        if rxbuf:used() > 0 then
+            log.info("收到", rxbuf:toStr(0, rxbuf:used()), "数据长度", rxbuf:used())
+        end
+        rxbuf:del()
+    elseif event == socket.TX_OK then
+        socket.wait(netc)
+        log.info("发送完成")
+    elseif event == socket.CLOSED then
+        sys.publish("socket_disconnect")
+    end
+end
+
+local function socketTask()
+    local netc = socket.create(nil, netCB) --创建一个链接
+    socket.debug(netc, true)--开启socket层的debug日志,方便寻找问题
+    socket.config(netc, nil, is_udp, nil, 300, 5, 6)  --配置TCP链接的参数,开启保活,防止长时间无数据交互服务器踢掉模块
+    while true do
+        --真正去链接服务器
+        local succ, result = socket.connect(netc, server_ip, server_port)
+        --链接成功后循环发送数据
+        while succ do
+            local Heartbeat_interval = Heartbeat_interval * 60 * 1000
+            sys.wait(Heartbeat_interval)
+            socket.tx(netc, heart_data)
+        end
+        --链接不成功5S重连一次
+        if not succ then
+            log.info("未知错误,5秒后重连")
+            uart.write(1, "未知错误,5秒后重连")
+        else
+            local result, msg = sys.waitUntil("socket_disconnect")
+        end
+        log.info("服务器断开了,5秒后重连")
+        uart.write(1, "服务器断开了,5秒后重连")
+        socket.close(netc)
+        sys.wait(5000)
+    end
+end
+
+function socketDemo()
+
+    --配置GPIO以达到最低功耗的目的
+    gpio.setup(23, nil)
+    gpio.close(33) -- 如果功耗偏高,开始尝试关闭WAKEUPPAD1
+    gpio.close(35) -- 这里pwrkey接地才需要,不接地通过按键控制的不需要
+
+    --关闭USB以后可以降低约150ua左右的功耗,如果不需要USB可以关闭
+    pm.power(pm.USB, false)
+
+     --进入低功耗长连接模式
+    pm.power(pm.WORK_MODE, 1)
+
+    sys.taskInit(socketTask)
+
+end
+
+sys.taskInit(socketDemo)
+

+ 17 - 0
module/Air8000/demo/lowpower/main.lua

@@ -0,0 +1,17 @@
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "socket_low_power"
+VERSION = "1.0"
+PRODUCT_KEY = "123" --换成自己的
+-- sys库是标配
+_G.sys = require("sys")
+_G.sysplus = require("sysplus")
+log.style(1)
+
+--require "normal" --正常模式
+--require "low_power_dissipation" --低功耗模式
+ require "ultra_low_power" --超低功耗模式(PSM+模式)
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 70 - 0
module/Air8000/demo/lowpower/normal.lua

@@ -0,0 +1,70 @@
+
+-- netlab.luatos.com上打开TCP,然后修改IP和端口号,自动回复netlab下发的数据,自收自发测试
+
+local server_ip = "112.125.89.8"
+local server_port = 47523
+
+local rxbuf = zbuff.create(8192)
+-- 配置GPIO达到最低功耗
+gpio.setup(25, 0) -- 关闭GNSS电源
+gpio.setup(24, 0) -- 关闭三轴电源
+gpio.setup(23, 0) -- 关闭wifi电源
+sys.subscribe("IP_READY", function(ip, adapter)
+    log.info("mobile", "IP_READY", ip, (adapter or -1) == socket.LWIP_GP)
+    sys.publish("net_ready")
+end)
+
+local function netCB(netc, event, param)
+    if param ~= 0 then
+        sys.publish("socket_disconnect")
+        return
+    end
+	if event == socket.LINK then
+	elseif event == socket.ON_LINE then
+        socket.tx(netc, "hello,luatos!")
+	elseif event == socket.EVENT then
+        socket.rx(netc, rxbuf)
+        socket.wait(netc)
+        if rxbuf:used() > 0 then
+            log.info("收到", rxbuf:toStr(0,rxbuf:used()):toHex())
+            log.info("发送", rxbuf:used(), "bytes")
+            socket.tx(netc, rxbuf)
+        end
+        rxbuf:del()
+	elseif event == socket.TX_OK then
+        socket.wait(netc)
+        log.info("发送完成")
+	elseif event == socket.CLOSED then
+        sys.publish("socket_disconnect")
+    end
+end
+
+local function socketTask()
+    sys.waitUntil("net_ready")
+    log.info("联网成功,准备链接服务器")
+    pm.power(pm.WORK_MODE,0) --进入正常模式
+	local netc = socket.create(nil, netCB)
+	socket.debug(netc, true)
+	socket.config(netc, nil, nil, nil, 300, 5, 6)   --开启TCP保活,防止长时间无数据交互被运营商断线
+    while true do
+        log.info("开始链接服务器")
+        local succ, result = socket.connect(netc, server_ip, server_port)
+        if not succ then
+            log.info("未知错误,5秒后重连")
+        else
+            log.info("链接服务器成功")
+            local result, msg = sys.waitUntil("socket_disconnect")
+        end
+        log.info("服务器断开了,5秒后重连")
+        socket.close(netc)
+        log.info(rtos.meminfo("sys"))
+        sys.wait(5000)
+    end
+end
+
+function socketDemo()
+	sys.taskInit(socketTask)
+end
+
+
+socketDemo()

+ 79 - 0
module/Air8000/demo/lowpower/ultra_low_power.lua

@@ -0,0 +1,79 @@
+local server_ip = "112.125.89.8" 
+local server_port = 47523 -- 换成自己的
+local period = 3 * 60 * 60 * 1000 -- 3小时唤醒一次
+-- 配置GPIO达到最低功耗
+gpio.setup(25, 0) -- 关闭GNSS电源
+gpio.setup(24, 0) -- 关闭三轴电源
+gpio.setup(23, 0) -- 关闭wifi电源
+local reason, slp_state = pm.lastReson() -- 获取唤醒原因
+log.info("wakeup state", pm.lastReson())
+local libnet = require "libnet"
+
+local d1Name = "D1_TASK"
+local function netCB(msg)
+    log.info("未处理消息", msg[1], msg[2], msg[3], msg[4])
+end
+
+local function testTask(ip, port)
+    local txData
+    if reason == 0 then
+        txData = "normal wakeup"
+    elseif reason == 1 then
+        txData = "timer wakeup"
+    elseif reason == 2 then
+        txData = "pad wakeup"
+    elseif reason == 3 then
+        txData = "uart1 wakeup"
+    end
+    if slp_state > 0 then
+        mobile.flymode(0, false) -- 退出飞行模式,进入psm+前进入飞行模式,唤醒后需要主动退出
+    end
+
+    --gpio.close(32)
+
+    local netc, needBreak
+    local result, param, is_err
+    netc = socket.create(nil, d1Name)
+    socket.debug(netc, false)
+    socket.config(netc) 
+    local retry = 0
+    while retry < 3 do
+        log.info(rtos.meminfo("sys"))
+        result = libnet.waitLink(d1Name, 0, netc)
+        result = libnet.connect(d1Name, 5000, netc, ip, port)
+        if result then
+            log.info("服务器连上了")
+            result, param = libnet.tx(d1Name, 15000, netc, txData)
+            if not result then
+                log.info("服务器断开了", result, param)
+                break
+            else
+                needBreak = true
+            end
+        else
+            log.info("服务器连接失败")
+        end
+        libnet.close(d1Name, 5000, netc)
+        retry = retry + 1
+        if needBreak then
+            break
+        end
+    end
+
+    uart.setup(1, 9600) -- 配置uart1,外部唤醒用
+    
+    -- 配置GPIO以达到最低功耗的目的
+
+    gpio.close(45) 
+    gpio.close(46) --这里pwrkey接地才需要,不接地通过按键控制的不需要
+
+    pm.dtimerStart(3, period) -- 启动深度休眠定时器
+
+    mobile.flymode(0, true) -- 启动飞行模式,规避可能会出现的网络问题
+    pm.power(pm.WORK_MODE, 3) -- 进入极致功耗模式
+
+    sys.wait(15000) -- demo演示唤醒时间是三十分钟,如果15s后模块重启,则说明进入极致功耗模式失败,
+    log.info("进入极致功耗模式失败,尝试重启")
+    rtos.reboot()
+end
+sysplus.taskInitEx(testTask, d1Name, netCB, server_ip, server_port)

+ 59 - 0
module/Air8000/demo/lvgl/main.lua

@@ -0,0 +1,59 @@
+--- 模块功能:lcddemo
+-- @module lcd
+-- @author Dozingfiretruck
+-- @release 2021.01.25
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "lcddemo"
+VERSION = "1.0.0"
+
+log.info("main", PROJECT, VERSION)
+
+-- sys库是标配
+_G.sys = require("sys")
+
+pm.ioVol(pm.IOVOL_ALL_GPIO, 3300) -- 设置GPIO电平 3.3V
+
+-- 添加硬狗防止程序卡死
+if wdt then
+    wdt.init(9000) -- 初始化watchdog设置为9s
+    sys.timerLoopStart(wdt.feed, 3000) -- 3s喂一次狗
+end
+
+lcd.init("jd9261t_inited",{port = lcd.HWID_0,pin_dc = 0xff, pin_pwr = 24, pin_rst = 36,direction = 0,w = 480,h = 480,xoffset = 0,yoffset = 0,interface_mode=lcd.QSPI_MODE,bus_speed=60000000,flush_rate=658,vbp=19,vfp=108,vs=2})
+
+
+sys.taskInit(function()
+    lcd.setupBuff(nil, true) -- 使用sys内存, 只需要选一种
+    lcd.autoFlush(false)
+
+    log.info("lvgl", lvgl.init())
+
+    local scr = lvgl.obj_create(nil, nil)
+    local btn = lvgl.btn_create(scr)
+    lvgl.obj_align(btn, lvgl.scr_act(), lvgl.ALIGN_CENTER, 0, 0)
+
+    local label = lvgl.label_create(btn)
+    local flag = true
+
+    lvgl.label_set_text(label, "LuatOS!")
+    lvgl.scr_load(scr)
+    lvgl.indev_drv_register("pointer", "emulator")
+
+    local function btn_cb(obj, event)
+        if event == lvgl.EVENT_SHORT_CLICKED then
+            log.info("short click")        if flag then
+                lvgl.label_set_text(label, "LuatOS!")
+                flag = false
+            else
+                lvgl.label_set_text(label, "hello world!")
+                flag = true
+            end
+        end
+    end
+    lvgl.obj_set_event_cb(btn, btn_cb)
+end)
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 41 - 0
module/Air8000/demo/miniz/main.lua

@@ -0,0 +1,41 @@
+
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "minizdemo"
+VERSION = "1.0.0"
+
+sys = require("sys")
+
+--添加硬狗防止程序卡死
+if wdt then
+    wdt.init(9000)--初始化watchdog设置为9s
+    sys.timerLoopStart(wdt.feed, 3000)--3s喂一次狗
+end
+
+sys.taskInit(function()
+    sys.wait(1000)
+    -- 压缩过的字符串, 为了方便演示, 这里用了base64编码
+    -- 大部分MCU设备的内存都比较小, miniz.compress 通常在服务器端完成,这里就不演示了
+    -- miniz能解压标准zlib数据流
+    local b64str = "eAEFQIGNwyAMXOUm+E2+OzjhCCiOjYyhyvbVR7K7IR0l+iau8G82eIW5jXVoPzF5pse/B8FaPXLiWTNxEMsKI+WmIR0l+iayEY2i2V4UbqqPh5bwimyEuY11aD8xeaYHxAquvom6VDFUXqQjG1Fek6efCFfCK0b0LUnQMjiCxhUT05GNL75dFUWCSMcjN3EE5c4Wvq42/36R41fa"
+    local str = b64str:fromBase64()
+
+    local dstr = miniz.uncompress(str)
+    -- 压缩过的数据长度 156
+    -- 解压后的数据长度,即原始数据的长度 235
+    log.info("miniz", "compressed", #str, "uncompressed", #dstr)
+
+    -- 演示压缩解压
+    local ostr = "abcd12345"
+    -- 压缩字符串
+    local zstr = miniz.compress(ostr)
+    log.info("压缩后的字符串:",zstr:toHex())
+    -- 解压字符串
+    local lstr = miniz.uncompress(zstr)
+    log.info("miniz","compress zstr",#zstr,"uncompress lstr data",lstr)
+end)
+
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 118 - 0
module/Air8000/demo/mobile/main.lua

@@ -0,0 +1,118 @@
+
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "mobiledemo"
+VERSION = "1.0.0"
+
+log.info("main", PROJECT, VERSION)
+
+-- sys库是标配
+_G.sys = require("sys")
+
+
+
+
+
+-- 对于双卡的设备, 可以设置为自动选sim卡
+-- 但是, 这样SIM1所在管脚就强制复用为SIM功能, 不可以再复用为GPIO
+-- mobile.simid(2)
+mobile.simid(2,true)--优先用SIM0
+
+
+sys.taskInit(function()
+
+	log.info("status", mobile.status())
+    local band = zbuff.create(40)
+    local band1 = zbuff.create(40)
+    mobile.getBand(band)
+    log.info("当前使用的band:")
+    for i=0,band:used()-1 do
+        log.info("band", band[i])
+    end
+    band1[0] = 38
+    band1[1] = 39
+    band1[2] = 40
+    mobile.setBand(band1, 3)    --改成使用38,39,40
+    band1:clear()
+    mobile.getBand(band1)
+    log.info("修改后使用的band:")
+    for i=0,band1:used()-1 do
+        log.info("band", band1[i])
+    end
+    mobile.setBand(band, band:used())    --改回原先使用的band,也可以下载的时候选择清除fs
+
+    mobile.getBand(band1)
+    log.info("修改回默认使用的band:")
+    for i=0,band1:used()-1 do
+        log.info("band", band1[i])
+    end
+	-- mobile.vsimInit()
+	-- mobile.flymode(nil,true)
+	-- mobile.vsimOnOff(true)
+	-- mobile.flymode(nil,false)
+    -- mobile.apn(0,2,"") -- 使用默认APN激活CID2
+    -- mobile.rtime(3) -- 在无数据交互时,RRC 3秒后自动释放
+    -- 下面是配置自动搜索小区间隔,和轮询搜索冲突,开启1个就可以了
+    -- mobile.setAuto(10000,30000, 5) -- SIM暂时脱离后自动恢复,30秒搜索一次周围小区信息
+	log.info("status", mobile.status())
+    sys.wait(2000)
+    while 1 do
+        log.info("imei", mobile.imei())
+        log.info("imsi", mobile.imsi())
+        local sn = mobile.sn()
+        if sn then
+            log.info("sn",   sn:toHex())
+        end
+		log.info("status", mobile.status())
+        
+
+        log.info("iccid", mobile.iccid())
+        log.info("csq", mobile.csq()) -- 4G模块的CSQ并不能完全代表强度
+        log.info("rssi", mobile.rssi()) -- 需要综合rssi/rsrq/rsrp/snr一起判断
+        log.info("rsrq", mobile.rsrq())
+        log.info("rsrp", mobile.rsrp())
+        log.info("snr", mobile.snr())
+        log.info("simid", mobile.simid()) -- 这里是获取当前SIM卡槽
+        log.info("apn", mobile.apn(0,1))
+        log.info("ip", socket.localIP())
+		log.info("lua", rtos.meminfo())
+        -- sys内存
+        log.info("sys", rtos.meminfo("sys"))
+        sys.wait(15000)
+    end
+end)
+
+-- 基站数据的查询
+
+-- 订阅式, 模块本身会周期性查询基站信息,但通常不包含临近小区
+sys.subscribe("CELL_INFO_UPDATE", function()
+    log.info("cell", json.encode(mobile.getCellInfo()))
+end)
+
+-- 轮询式, 包含临近小区信息,这是手动搜索,和上面的自动搜索冲突,开启一个就行
+sys.taskInit(function()
+    sys.wait(5000)
+	mobile.config(mobile.CONF_SIM_WC_MODE, 2)
+    while 1 do
+        mobile.reqCellInfo(10)
+        sys.wait(11000)
+        log.info("cell", json.encode(mobile.getCellInfo()))
+		mobile.config(mobile.CONF_SIM_WC_MODE, 2)
+    end
+end)
+
+-- 获取sim卡的状态
+
+sys.subscribe("SIM_IND", function(status, value)
+    log.info("sim status", status)
+    if status == 'GET_NUMBER' then
+        log.info("number", mobile.number(0))
+    end
+	if status == "SIM_WC" then
+        log.info("sim", "write counter", value)
+    end
+end)
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 124 - 0
module/Air8000/demo/mqtt/main.lua

@@ -0,0 +1,124 @@
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "mqttdemo"
+VERSION = "1.0.0"
+
+--[[
+本demo需要mqtt库, 大部分能联网的设备都具有这个库
+mqtt也是内置库, 无需require
+]]
+
+-- sys库是标配
+_G.sys = require("sys")
+--[[特别注意, 使用mqtt库需要下列语句]]
+_G.sysplus = require("sysplus")
+local netLed = require("netLed")
+
+
+--根据自己的服务器修改以下参数
+local mqtt_host = "lbsmqtt.airm2m.com"
+local mqtt_port = 1884
+local mqtt_isssl = false
+local client_id = "mqttx_b55c41b7"
+local user_name = "user"
+local password = "password"
+
+local pub_topic = "/luatos/pub/123"-- .. (mcu.unique_id():toHex())
+local sub_topic = "/luatos/sub/123"-- .. (mcu.unique_id():toHex())
+
+
+local mqttc = nil
+--GPIO20配置为输出,默认输出低电平
+LEDA = 20
+gpio.setup(LEDA, 0, gpio.PULLUP)
+
+-- 统一联网函数
+sys.taskInit(function()
+    local device_id = mcu.unique_id():toHex()
+    device_id = mobile.imei()
+    -- 默认都等到联网成功
+    sys.waitUntil("IP_READY")
+    sys.publish("net_ready", device_id)
+end)
+
+sys.taskInit(function()
+    -- 等待联网
+    local ret, device_id = sys.waitUntil("net_ready") --device_id为设备的IMEI号
+
+    client_id = device_id
+    pub_topic = device_id .. "/up"  -- 设备发布的主题,开发者可自行修改
+    sub_topic = device_id .. "/down" -- 设备订阅的主题,开发者可自行修改
+
+    -- 打印一下上报(pub)和下发(sub)的topic名称
+    -- 上报: 设备 ---> 服务器
+    -- 下发: 设备 <--- 服务器
+    -- 可使用mqtt.x等客户端进行调试
+    log.info("mqtt", "pub", pub_topic)
+    log.info("mqtt", "sub", sub_topic)
+
+    -- 打印一下支持的加密套件, 通常来说, 固件已包含常见的99%的加密套件
+    -- if crypto.cipher_suites then
+    --     log.info("cipher", "suites", json.encode(crypto.cipher_suites()))
+    -- end
+    if mqtt == nil then
+        while 1 do
+            sys.wait(1000)
+            log.info("bsp", "本bsp未适配mqtt库, 请查证")
+        end
+    end
+    -------------------------------------
+    -------- MQTT 演示代码 --------------
+    -------------------------------------
+
+    mqttc = mqtt.create(nil, mqtt_host, mqtt_port, mqtt_isssl, ca_file)
+
+    mqttc:auth(client_id,user_name,password) -- client_id必填,其余选填
+    -- mqttc:keepalive(240) -- 默认值240s
+    mqttc:autoreconn(true, 3000) -- 自动重连机制
+
+    mqttc:on(function(mqtt_client, event, data, payload)
+        -- 用户自定义代码
+        log.info("mqtt", "event", event, mqtt_client, data, payload)
+        if event == "conack" then
+            -- 联上了
+            gpio.set(LEDA, 1) --输出高电平     
+            sys.publish("mqtt_conack")
+            mqtt_client:subscribe(sub_topic)--单主题订阅
+            -- mqtt_client:subscribe({[topic1]=1,[topic2]=1,[topic3]=1})--多主题订阅
+        elseif event == "recv" then
+            log.info("mqtt", "downlink", "topic", data, "payload:", payload)
+                        log.info("mqtt", "uplink", "topic", pub_topic, "payload:", payload)
+                        sys.publish("mqtt_pub", pub_topic, payload)  --将收到的数据,通过发布主题目,进行发送
+        elseif event == "sent" then
+            log.info("mqtt", "sent", "pkgid", data)
+        elseif event == "disconnect" then
+            gpio.set(LEDA, 0) --输出低电平
+            -- 非自动重连时,按需重启mqttc
+            -- mqtt_client:connect()
+
+        end
+    end)
+
+    -- mqttc自动处理重连, 除非自行关闭
+    mqttc:connect()
+    sys.waitUntil("mqtt_conack")
+    while true do
+        -- 演示等待其他task发送过来的上报信息
+        local ret, topic, data, qos = sys.waitUntil("mqtt_pub", 300000)
+        if ret then
+            -- 提供关闭本while循环的途径, 不需要可以注释掉
+            if topic == "close" then break end
+            mqttc:publish(topic, data, qos)
+        end
+
+        -- 如果没有其他task上报, 可以写个空等待
+        --sys.wait(6000)
+    end
+    mqttc:close()
+    mqttc = nil
+end)
+
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 64 - 0
module/Air8000/demo/netdrv/ch390/lan/lan.lua

@@ -0,0 +1,64 @@
+
+
+
+dhcps = require "dhcpsrv"
+dnsproxy = require "dnsproxy"
+
+
+sys.taskInit(function ()
+    sys.wait(500)
+    log.info("ch390", "打开LDO供电")
+    gpio.setup(140, 1, gpio.PULLUP)     --打开ch390供电
+    sys.wait(6000)
+    local result = spi.setup(
+        1,--spi_id
+        nil,
+        0,--CPHA
+        0,--CPOL
+        8,--数据宽度
+        25600000--,--频率
+        -- spi.MSB,--高低位顺序    可选,默认高位在前
+        -- spi.master,--主模式     可选,默认主
+        -- spi.full--全双工       可选,默认全双工
+    )
+    log.info("main", "open",result)
+    if result ~= 0 then--返回值为0,表示打开成功
+        log.info("main", "spi open error",result)
+        return
+    end
+
+    -- 初始化指定netdrv设备,
+    -- socket.LWIP_ETH 网络适配器编号
+    -- netdrv.CH390外挂CH390
+    -- SPI ID 1, 片选 GPIO12
+    netdrv.setup(socket.LWIP_ETH, netdrv.CH390, {spi=1,cs=12})
+    sys.wait(3000)
+    local ipv4,mark, gw = netdrv.ipv4(socket.LWIP_ETH, "192.168.4.1", "255.255.255.0", "192.168.4.1")
+    log.info("ipv4", ipv4,mark, gw)
+    while netdrv.link(socket.LWIP_ETH) ~= true do
+        sys.wait(100)
+    end
+    while netdrv.link(socket.LWIP_GP) ~= true do
+        sys.wait(100)
+    end
+    sys.wait(2000)
+    dhcps.create({adapter=socket.LWIP_ETH})
+    dnsproxy.setup(socket.LWIP_ETH, socket.LWIP_GP)
+    netdrv.napt(socket.LWIP_GP)
+    if iperf then
+        log.info("启动iperf服务器端")
+        iperf.server(socket.LWIP_ETH)
+    end
+end)
+
+
+sys.taskInit(function()
+    -- sys.waitUntil("IP_READY")
+    while 1 do
+        sys.wait(300000)
+        -- log.info("http", http.request("GET", "http://httpbin.air32.cn/bytes/4096", nil, nil, {adapter=socket.LWIP_ETH}).wait())
+        log.info("lua", rtos.meminfo())
+        log.info("sys", rtos.meminfo("sys"))
+        -- log.info("psram", rtos.meminfo("psram"))
+    end
+end)

+ 22 - 0
module/Air8000/demo/netdrv/ch390/lan/main.lua

@@ -0,0 +1,22 @@
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "ch390h"
+VERSION = "1.0.0"
+
+-- 使用合宙iot平台时需要这个参数
+PRODUCT_KEY = "xxx" -- 到 iot.openluat.com 创建项目,获取正确的项目id
+
+-- 引入必要的库文件(lua编写), 内部库不需要require
+sys = require("sys")
+sysplus = require("sysplus")
+
+
+-- pm.ioVol(pm.IOVOL_ALL_GPIO, 3300) -- 所有GPIO高电平输出3.0V
+
+require "lan"
+-- require "wan"
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!
+

+ 183 - 0
module/Air8000/demo/netdrv/ch390/lan_TCP/main.lua

@@ -0,0 +1,183 @@
+-- main.lua文件
+
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "lan_tcp"
+VERSION = "1.0.0"
+
+log.info("main", PROJECT, VERSION)
+
+local taskName = "TCP_TASK"             -- sysplus库用到的任务名称,也作为任务id
+
+dhcps = require "dhcpsrv"
+dnsproxy = require "dnsproxy"
+if wdt then
+    --添加硬狗防止程序卡死,在支持的设备上启用这个功能
+    wdt.init(9000)--初始化watchdog设置为9s
+    sys.timerLoopStart(wdt.feed, 3000)--3s喂一次狗
+end
+
+local uartid = 1 -- 根据实际设备选取不同的uartid
+local uart_rx_buff = zbuff.create(1024)     -- 串口接收到的数据
+
+local libnet = require "libnet"         -- libnet库,支持tcp、udp协议所用的同步阻塞接口
+local ip = "192.168.4.100"               -- 连接tcp服务器的ip地址
+local port = 777            -- 连接tcp服务器的端口
+local netCB = nil                       -- socket服务的回调函数
+local connect_state = false             -- 连接状态 true:已连接   false:未连接
+local protocol = false                  -- 通讯协议 true:UDP协议  false:TCP协议
+local ssl = false                     -- 加密传输 true:加密     false:不加密
+local tx_buff = zbuff.create(1024)      -- 发送至tcp服务器的数据
+local rx_buff = zbuff.create(1024)      -- 从tcp服务器接收到的数据
+
+--初始化
+uart.setup(
+    uartid,--串口id
+    115200,--波特率
+    8,--数据位
+    1--停止位
+)
+
+sys.taskInit(function ()
+    sys.wait(500)
+    log.info("ch390", "打开LDO供电")
+    gpio.setup(140, 1, gpio.PULLUP)     --打开ch390供电
+    sys.wait(3000)
+    local result = spi.setup(
+        1,--spi_id
+        nil,
+        0,--CPHA
+        0,--CPOL
+        8,--数据宽度
+        25600000--,--频率
+        -- spi.MSB,--高低位顺序    可选,默认高位在前
+        -- spi.master,--主模式     可选,默认主
+        -- spi.full--全双工       可选,默认全双工
+    )
+    log.info("main", "open",result)
+    if result ~= 0 then--返回值为0,表示打开成功
+        log.info("main", "spi open error",result)
+        return
+    end
+
+    -- 初始化指定netdrv设备,
+    -- socket.LWIP_ETH 网络适配器编号
+    -- netdrv.CH390外挂CH390
+    -- SPI ID 1, 片选 GPIO12
+    netdrv.setup(socket.LWIP_ETH, netdrv.CH390, {spi=1,cs=12})
+    sys.wait(3000)
+    local ipv4,mark, gw = netdrv.ipv4(socket.LWIP_ETH, "192.168.4.1", "255.255.255.0", "192.168.4.1")
+    log.info("ipv4", ipv4,mark, gw)
+    while netdrv.link(socket.LWIP_ETH) ~= true do
+        sys.wait(100)
+    end
+    while netdrv.link(socket.LWIP_GP) ~= true do
+        sys.wait(100)
+    end
+    sys.wait(2000)
+    dhcps.create({adapter=socket.LWIP_ETH})
+    dnsproxy.setup(socket.LWIP_ETH, socket.LWIP_GP)
+    netdrv.napt(socket.LWIP_GP)
+    if iperf then
+        log.info("启动iperf服务器端")
+        iperf.server(socket.LWIP_ETH)
+    end
+end)
+
+function TCP_TASK()
+    sys.waitUntil("IP_READY")                -- 等待联网成功
+    -- 打印一下连接的目标ip和端口号
+    log.info("connect ip: ", ip, "port:", port)
+    
+    netCB = socket.create(socket.LWIP_ETH, taskName)     -- 创建socket对象
+    socket.debug(netCB, true)                -- 打开调试日志
+    socket.config(netCB, nil, protocol, ssl)      -- 此配置为TCP连接,无SSL加密
+
+    -- 串口和TCP服务器的交互逻辑
+    while true do
+        -- 连接服务器,返回是否连接成功
+        result = libnet.connect(taskName, 15000, netCB, ip, port)
+
+        -- 收取数据会触发回调, 这里的"receive" 是固定值不要修改。
+        uart.on(uartid, "receive", function(id, len)
+            while true do
+                local len = uart.rx(id, uart_rx_buff)   -- 接收串口收到的数据,并赋值到uart_rx_buff
+                if len <= 0 then    -- 接收到的字节长度为0 则退出
+                    break
+                end
+                -- 如果已经在线了,则发送socket.EVENT消息来打断任务里的阻塞等待状态,让任务循环继续
+                if connect_state then
+                    sys_send(taskName, socket.EVENT, 0)
+                end
+            end
+        end)
+
+        -- 如果连接成功,则改变连接状态参数,并且随便发一条数据到服务器,看服务器能不能收到
+        if result then
+            connect_state = true
+            libnet.tx(taskName, 0, netCB, "TCP  CONNECT")
+        end
+
+        -- 连接上服务器后,等待处理接收服务器下行至模块的数据 和 发送串口的数据到服务器
+        while result do
+            succ, param, _, _ = socket.rx(netCB, rx_buff)   -- 接收数据
+            if not succ then
+                log.info("服务器断开了", succ, param, ip, port)
+                break
+            end
+
+            if rx_buff:used() > 0 then
+                log.info("收到服务器数据,长度", rx_buff:used())
+
+                uart.tx(uartid, rx_buff)    -- 从服务器收到的数据转发 从串口输出
+                rx_buff:del()
+            end
+
+            tx_buff:copy(nil, uart_rx_buff)         -- 将串口数据赋值给tcp待发送数据的buff中
+            uart_rx_buff:del()                      -- 清除串口buff的数据长度
+            if tx_buff:used() > 0 then
+                log.info("发送到服务器数据,长度", tx_buff:used())
+                local result = libnet.tx(taskName, 0, netCB, tx_buff)   -- 发送数据
+                if not result then
+                    log.info("发送失败了", result, param)
+                    break
+                end
+            end
+            tx_buff:del()
+
+            -- 如果zbuff对象长度超出,需要重新分配下空间
+            if uart_rx_buff:len() > 1024 then
+                uart_rx_buff:resize(1024)
+            end
+            if tx_buff:len() > 1024 then
+                tx_buff:resize(1024)
+            end
+            if rx_buff:len() > 1024 then
+                rx_buff:resize(1024)
+            end
+            log.info(rtos.meminfo("sys"))   -- 打印系统内存
+
+            -- 阻塞等待新的消息到来,比如服务器下发,串口接收到数据
+            result, param = libnet.wait(taskName, 15000, netCB)
+            if not result then
+                log.info("服务器断开了", result, param)
+                break
+            end
+        end
+
+        -- 服务器断开后的行动,由于while true的影响,所以会再次重新执行进行 重新连接。
+        connect_state = false
+        libnet.close(d1Name, 5000, netCB)
+        tx_buff:clear(0)
+        rx_buff:clear(0)
+        sys.wait(1000)
+    end
+
+end
+
+-- libnet库依赖于sysplus,所以只能通过sysplus.taskInitEx创建的任务函数中运行
+sysplus.taskInitEx(TCP_TASK, taskName, netCB)
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 22 - 0
module/Air8000/demo/netdrv/ch390/wan/main.lua

@@ -0,0 +1,22 @@
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "ch390h"
+VERSION = "1.0.0"
+
+-- 使用合宙iot平台时需要这个参数
+PRODUCT_KEY = "xxx" -- 到 iot.openluat.com 创建项目,获取正确的项目id
+
+-- 引入必要的库文件(lua编写), 内部库不需要require
+sys = require("sys")
+sysplus = require("sysplus")
+
+
+-- pm.ioVol(pm.IOVOL_ALL_GPIO, 3300) -- 所有GPIO高电平输出3.0V
+
+-- require "lan"
+require "wan"
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!
+

+ 39 - 0
module/Air8000/demo/netdrv/ch390/wan/wan.lua

@@ -0,0 +1,39 @@
+
+sys.taskInit(function ()
+    sys.wait(500)
+    log.info("ch390", "打开LDO供电")
+    gpio.setup(140, 1, gpio.PULLUP)     --打开ch390供电
+    sys.wait(6000)
+    local result = spi.setup(
+        1,--spi_id
+        nil,
+        0,--CPHA
+        0,--CPOL
+        8,--数据宽度
+        25600000--,--频率
+        -- spi.MSB,--高低位顺序    可选,默认高位在前
+        -- spi.master,--主模式     可选,默认主
+        -- spi.full--全双工       可选,默认全双工
+    )
+    log.info("main", "open",result)
+    if result ~= 0 then--返回值为0,表示打开成功
+        log.info("main", "spi open error",result)
+        return
+    end
+    -- 初始化指定netdrv设备,
+    -- socket.LWIP_ETH 网络适配器编号
+    -- netdrv.CH390外挂CH390
+    -- SPI ID 1, 片选 GPIO12
+    netdrv.setup(socket.LWIP_ETH, netdrv.CH390, {spi=1,cs=12})
+    netdrv.dhcp(socket.LWIP_ETH, true)
+end)
+
+sys.taskInit(function()
+    -- sys.waitUntil("IP_READY")
+    while 1 do
+        sys.wait(6000)
+        log.info("http", http.request("GET", "http://httpbin.air32.cn/bytes/4096", nil, nil, {adapter=socket.LWIP_ETH}).wait()) --adapter指定为以太网联网方式
+        log.info("lua", rtos.meminfo())
+        log.info("sys", rtos.meminfo("sys"))
+    end
+end)

+ 164 - 0
module/Air8000/demo/netdrv/ch390/wan_TCP/main.lua

@@ -0,0 +1,164 @@
+-- main.lua文件
+
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "wan_tcp"
+VERSION = "1.0.0"
+
+log.info("main", PROJECT, VERSION)
+
+local taskName = "TCP_TASK"             -- sysplus库用到的任务名称,也作为任务id
+
+if wdt then
+    --添加硬狗防止程序卡死,在支持的设备上启用这个功能
+    wdt.init(9000)--初始化watchdog设置为9s
+    sys.timerLoopStart(wdt.feed, 3000)--3s喂一次狗
+end
+
+local uartid = 1 -- 根据实际设备选取不同的uartid
+local uart_rx_buff = zbuff.create(1024)     -- 串口接收到的数据
+
+local libnet = require "libnet"         -- libnet库,支持tcp、udp协议所用的同步阻塞接口
+local ip = "112.125.89.8"               -- 连接tcp服务器的ip地址
+local port = 46319            -- 连接tcp服务器的端口
+local netCB = nil                       -- socket服务的回调函数
+local connect_state = false             -- 连接状态 true:已连接   false:未连接
+local protocol = false                  -- 通讯协议 true:UDP协议  false:TCP协议
+local ssl = false                     -- 加密传输 true:加密     false:不加密
+local tx_buff = zbuff.create(1024)      -- 发送至tcp服务器的数据
+local rx_buff = zbuff.create(1024)      -- 从tcp服务器接收到的数据
+
+--初始化
+uart.setup(
+    uartid,--串口id
+    115200,--波特率
+    8,--数据位
+    1--停止位
+)
+
+sys.taskInit(function ()
+    sys.wait(500)
+    log.info("ch390", "打开LDO供电")
+    gpio.setup(140, 1, gpio.PULLUP)     --打开ch390供电
+    sys.wait(3000)
+    local result = spi.setup(
+        1,--spi_id
+        nil,
+        0,--CPHA
+        0,--CPOL
+        8,--数据宽度
+        25600000--,--频率
+        -- spi.MSB,--高低位顺序    可选,默认高位在前
+        -- spi.master,--主模式     可选,默认主
+        -- spi.full--全双工       可选,默认全双工
+    )
+    log.info("main", "open",result)
+    if result ~= 0 then--返回值为0,表示打开成功
+        log.info("main", "spi open error",result)
+        return
+    end
+    -- 初始化指定netdrv设备,
+    -- socket.LWIP_ETH 网络适配器编号
+    -- netdrv.CH390外挂CH390
+    -- SPI ID 1, 片选 GPIO12
+    netdrv.setup(socket.LWIP_ETH, netdrv.CH390, {spi=1,cs=12})
+    netdrv.dhcp(socket.LWIP_ETH, true)
+end)
+
+function TCP_TASK()
+    sys.waitUntil("IP_READY")                -- 等待联网成功
+    -- 打印一下连接的目标ip和端口号
+    log.info("connect ip: ", ip, "port:", port)
+    
+    netCB = socket.create(socket.LWIP_ETH, taskName)     -- 创建socket对象
+    socket.debug(netCB, true)                -- 打开调试日志
+    socket.config(netCB, nil, protocol, ssl)      -- 此配置为TCP连接,无SSL加密
+
+    -- 串口和TCP服务器的交互逻辑
+    while true do
+        -- 连接服务器,返回是否连接成功
+        result = libnet.connect(taskName, 15000, netCB, ip, port)
+
+        -- 收取数据会触发回调, 这里的"receive" 是固定值不要修改。
+        uart.on(uartid, "receive", function(id, len)
+            while true do
+                local len = uart.rx(id, uart_rx_buff)   -- 接收串口收到的数据,并赋值到uart_rx_buff
+                if len <= 0 then    -- 接收到的字节长度为0 则退出
+                    break
+                end
+                -- 如果已经在线了,则发送socket.EVENT消息来打断任务里的阻塞等待状态,让任务循环继续
+                if connect_state then
+                    sys_send(taskName, socket.EVENT, 0)
+                end
+            end
+        end)
+
+        -- 如果连接成功,则改变连接状态参数,并且随便发一条数据到服务器,看服务器能不能收到
+        if result then
+            connect_state = true
+            libnet.tx(taskName, 0, netCB, "TCP  CONNECT")
+        end
+
+        -- 连接上服务器后,等待处理接收服务器下行至模块的数据 和 发送串口的数据到服务器
+        while result do
+            succ, param, _, _ = socket.rx(netCB, rx_buff)   -- 接收数据
+            if not succ then
+                log.info("服务器断开了", succ, param, ip, port)
+                break
+            end
+
+            if rx_buff:used() > 0 then
+                log.info("收到服务器数据,长度", rx_buff:used())
+
+                uart.tx(uartid, rx_buff)    -- 从服务器收到的数据转发 从串口输出
+                rx_buff:del()
+            end
+
+            tx_buff:copy(nil, uart_rx_buff)         -- 将串口数据赋值给tcp待发送数据的buff中
+            uart_rx_buff:del()                      -- 清除串口buff的数据长度
+            if tx_buff:used() > 0 then
+                log.info("发送到服务器数据,长度", tx_buff:used())
+                local result = libnet.tx(taskName, 0, netCB, tx_buff)   -- 发送数据
+                if not result then
+                    log.info("发送失败了", result, param)
+                    break
+                end
+            end
+            tx_buff:del()
+
+            -- 如果zbuff对象长度超出,需要重新分配下空间
+            if uart_rx_buff:len() > 1024 then
+                uart_rx_buff:resize(1024)
+            end
+            if tx_buff:len() > 1024 then
+                tx_buff:resize(1024)
+            end
+            if rx_buff:len() > 1024 then
+                rx_buff:resize(1024)
+            end
+            log.info(rtos.meminfo("sys"))   -- 打印系统内存
+
+            -- 阻塞等待新的消息到来,比如服务器下发,串口接收到数据
+            result, param = libnet.wait(taskName, 15000, netCB)
+            if not result then
+                log.info("服务器断开了", result, param)
+                break
+            end
+        end
+
+        -- 服务器断开后的行动,由于while true的影响,所以会再次重新执行进行 重新连接。
+        connect_state = false
+        libnet.close(d1Name, 5000, netCB)
+        tx_buff:clear(0)
+        rx_buff:clear(0)
+        sys.wait(1000)
+    end
+
+end
+
+-- libnet库依赖于sysplus,所以只能通过sysplus.taskInitEx创建的任务函数中运行
+sysplus.taskInitEx(TCP_TASK, taskName, netCB)
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 119 - 0
module/Air8000/demo/ntp/main.lua

@@ -0,0 +1,119 @@
+
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "sntpdemo"
+VERSION = "1.0.0"
+
+--[[
+本demo需要mqtt库, 大部分能联网的设备都具有这个库
+mqtt也是内置库, 无需require
+]]
+
+-- sys库是标配
+_G.sys = require("sys")
+--[[特别注意, 使用mqtt库需要下列语句]]
+_G.sysplus = require("sysplus")
+
+
+
+-- 统一联网函数
+sys.taskInit(function()
+    local device_id = mcu.unique_id():toHex()
+    -----------------------------
+    -- 统一联网函数, 可自行删减
+    ----------------------------
+    if wlan and wlan.connect then
+        -- wifi 联网, ESP32系列均支持
+        local ssid = "luatos1234"
+        local password = "12341234"
+        log.info("wifi", ssid, password)
+        -- TODO 改成自动配网
+        -- LED = gpio.setup(12, 0, gpio.PULLUP)
+        wlan.init()
+        wlan.setMode(wlan.STATION) -- 默认也是这个模式,不调用也可以
+        device_id = wlan.getMac()
+        wlan.connect(ssid, password, 1)
+    elseif mobile then
+        -- Air8000/Air600E系列
+        --mobile.simid(2) -- 自动切换SIM卡
+        -- LED = gpio.setup(27, 0, gpio.PULLUP)
+        device_id = mobile.imei()
+    elseif w5500 then
+        -- w5500 以太网, 当前仅Air105支持
+        w5500.init(spi.HSPI_0, 24000000, pin.PC14, pin.PC01, pin.PC00)
+        w5500.config() --默认是DHCP模式
+        w5500.bind(socket.ETH0)
+        -- LED = gpio.setup(62, 0, gpio.PULLUP)
+    elseif socket then
+        -- 适配的socket库也OK
+        -- 没有其他操作, 单纯给个注释说明
+    else
+        -- 其他不认识的bsp, 循环提示一下吧
+        while 1 do
+            sys.wait(1000)
+            log.info("bsp", "本bsp可能未适配网络层, 请查证")
+        end
+    end
+    -- 默认都等到联网成功
+    sys.waitUntil("IP_READY")
+    sys.publish("net_ready", device_id)
+end)
+
+sys.taskInit(function()
+    -- 等待联网
+    local ret, device_id = sys.waitUntil("net_ready")
+    sys.wait(1000)
+    -- 对于Cat.1模块, 移动/电信卡, 通常会下发基站时间,  那么sntp就不是必要的, 而联通卡通常不会下发, 就需要sntp了
+    -- 对应ESP32系列模块, 固件默认也会执行sntp, 所以手动调用sntp也是可选的
+    -- sntp内置了几个常用的ntp服务器, 也支持自选服务器
+    while 1 do
+        -- 使用内置的ntp服务器地址, 包括阿里ntp
+        log.info("开始执行SNTP")
+        socket.sntp()
+        -- 自定义ntp地址
+        -- socket.sntp("ntp.aliyun.com")
+        -- socket.sntp({"baidu.com", "abc.com", "ntp.air32.cn"})
+        -- 通常只需要几百毫秒就能成功
+        local ret = sys.waitUntil("NTP_UPDATE", 5000)
+        if ret then
+            -- 以下是获取/打印时间的演示,注意时区问题
+            log.info("sntp", "时间同步成功", "本地时间", os.date())
+            log.info("sntp", "时间同步成功", "UTC时间", os.date("!%c"))
+            log.info("sntp", "时间同步成功", "RTC时钟(UTC时间)", json.encode(rtc.get()))
+            -- os.time(rtc.get()) 需要 2023.07.21 之后的版本, 因为月份的命名差异mon/month
+            -- log.info("sntp", "时间同步成功", "utc时间戳", os.time(rtc.get()))
+            log.info("sntp", "时间同步成功", "本地时间戳", os.time())
+            local t = os.date("*t")
+            log.info("sntp", "时间同步成功", "本地时间os.date() json格式", json.encode(t))
+            log.info("sntp", "时间同步成功", "本地时间os.date(os.time())", os.time(t))
+            -- log.info("sntp", "时间同步成功", "本地时间", os.time())
+            -- 正常使用, 一小时一次, 已经足够了, 甚至1天一次也可以
+            -- sys.wait(3600000) 
+            -- 这里为了演示, 用5秒一次
+            sys.wait(5000)
+        else
+            log.info("sntp", "时间同步失败")
+            sys.wait(60000) -- 1分钟后重试
+        end
+
+        -- 时间戳, 精确到毫秒. 2023.11.15 新增
+        -- 注意, 至少成功完成2次sntp,该时间戳才比较准确
+        -- 如果仅完成了一次sntp, 时间戳比标准时间会慢一个网络延时的时长(10~500ms)不等
+        if socket.ntptm then
+            local tm = socket.ntptm()
+            log.info("tm数据", json.encode(tm))
+            log.info("时间戳", string.format("%u.%03d", tm.tsec, tm.tms))
+            sys.wait(5000)
+        end
+    end
+end)
+
+sys.subscribe("NTP_ERROR", function()
+    log.info("socket", "sntp error")
+    -- socket.sntp()
+end)
+
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 119 - 0
module/Air8000/demo/onewire/main.lua

@@ -0,0 +1,119 @@
+
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "onewiredemo"
+VERSION = "1.0.0"
+
+-- sys库是标配
+sys = require("sys")
+
+-- 以 log.info("ABC", "DEF", 123) 为例, 假设该代码位于main.lua的12行
+-- 调试风格1, 添加额外的调试信息
+-- I/main.lua:12 ABC DEF 123
+log.style(1)
+
+--[[
+接线说明:
+   DS18B20    Air8000
+1. GND    -> GND
+2. VDD    -> 3.3V
+3. DATA    -> GPIO2
+
+注意:
+1. ONEWIRE功能支持在4个引脚使用, 但硬件通道只有一个, 默认是GPIO2
+2. 如需切换到其他脚, 参考如下切换逻辑, 选其中一种
+
+mcu.altfun(mcu.ONEWIRE, 0, 17, 4, 0) -- GPIO2, 也就是默认值
+mcu.altfun(mcu.ONEWIRE, 0, 18, 4, 0) -- GPIO3
+mcu.altfun(mcu.ONEWIRE, 0, 22, 4, 0) -- GPIO7
+mcu.altfun(mcu.ONEWIRE, 0, 53, 4, 0) -- GPIO28
+]]
+
+local function read_ds18b20(id)
+    local tbuff = zbuff.create(10)
+    local succ,crc8c,range,t
+    local rbuff = zbuff.create(9)
+    --如果有多个DS18B20,需要带上ID
+    tbuff:write(0x55)
+    tbuff:copy(nil, id)
+    tbuff:write(0xb8)
+    --如果只有1个DS18B20,就用无ID方式
+    --tbuff:write(0xcc,0xb8)
+    while true do
+        tbuff[tbuff:used() - 1] = 0x44
+        succ = onewire.tx(0, tbuff, false, true, true)
+        if not succ then
+            return
+        end
+        while true do
+            succ = onewire.reset(0, true)
+            if not succ then
+                return
+            end
+            if onewire.bit(0) > 0 then
+                log.info("温度转换完成")
+                break
+            end
+            sys.wait(10)
+        end
+        tbuff[tbuff:used() - 1] = 0xbe
+        succ = onewire.tx(0, tbuff, false, true, true)
+        if not succ then
+            return
+        end
+        succ,rx_data = onewire.rx(0, 9, nil, rbuff, false, false, false)
+        crc8c = crypto.crc8(rbuff:toStr(0,8), 0x31, 0, true)
+        if crc8c == rbuff[8] then
+            range = (rbuff[4] >> 5) & 0x03
+            -- rbuff[0] = 0xF8
+            -- rbuff[1] = 0xFF
+            t = rbuff:query(0,2,false,true)
+            t = t * (5000 >> range)
+            t = t / 10000
+            log.info(t)
+        else
+            log.info("RAM DATA CRC校验不对",  mcu.x32(crc8c), mcu.x32(rbuff[8]))
+            return
+        end
+        sys.wait(500)
+    end
+end
+
+local function test_ds18b20()
+    local succ,rx_data
+    local id = zbuff.create(8)
+
+    local crc8c
+    onewire.init(0)
+    onewire.timing(0, false, 0, 500, 500, 15, 240, 70, 1, 15, 10, 2)
+    while true do
+        id:set() --清空id
+        succ,rx_data = onewire.rx(0, 8, 0x33, id, false, true, true)
+        if succ then
+            if id[0] == 0x28 then
+                crc8c = crypto.crc8(id:query(0,7), 0x31, 0, true)
+                if crc8c == id[7] then
+                    log.info("探测到DS18B20", id:query(0, 7):toHex())
+                    read_ds18b20(id)
+                    log.info("DS18B20离线,重新探测")
+                else
+                    log.info("ROM ID CRC校验不对",  mcu.x32(crc8c), mcu.x32(id[7]))
+                end
+            else
+                log.info("ROM ID不正确", mcu.x32(id[0]))
+            end
+        end
+        log.info("没有检测到DS18B20, 5秒后重试")
+        sys.wait(5000)
+    end
+end
+
+if onewire then
+    sys.taskInit(test_ds18b20)
+else
+    log.info("no onewire")
+end
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 62 - 0
module/Air8000/demo/pack/main.lua

@@ -0,0 +1,62 @@
+
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "LOG"
+VERSION = "2.0.0"
+
+--[[
+本demo演示 string字符串的基本操作
+1. lua的字符串是带长度, 这意味着, 它不依赖0x00作为结束字符串, 可以包含任意数据
+2. lua的字符串是不可变的, 就不能直接修改字符串的一个字符, 修改字符会返回一个新的字符串
+]]
+
+-- sys库是标配
+_G.sys = require("sys")
+sysplus = require("sysplus")
+
+
+local netLed = require("netLed")
+--GPIO18配置为输出,默认输出低电平,可通过setGpio18Fnc(0或者1)设置输出电平
+local LEDA= gpio.setup(27, 0, gpio.PULLUP)
+
+sys.taskInit(function ()
+    sys.wait(1000) -- 免得看不到日志
+    local tmp
+
+	--实验1:以小端方式编码
+	local data = string.pack("<I", 0xAABBCCDD)      --‘<’表示以小端方式编码,'I'表示,unsigned int , 4字节
+	log.info("pack:", 	string.format("%02X", data:byte(1)), 	--输出小端编码后的数据
+						string.format("%02X", data:byte(2)), 
+						string.format("%02X", data:byte(3)), 
+						string.format("%02X", data:byte(4)))
+	
+	--实验2:以大端方式编码
+	local data = string.pack(">I", 0xAABBCCDD)
+	log.info("pack:", 	string.format("%02X", data:byte(1)),   --输出大端编码后的数据
+						string.format("%02X", data:byte(2)), 
+						string.format("%02X", data:byte(3)), 
+						string.format("%02X", data:byte(4)))
+						
+	--实验3:对上面已经完成的大端编码,再次进行解包为每个字节					
+	local byte1,byte2,byte3,byte4 = string.unpack(">BBBB", data)  --将32位数据拆成4个8位字节数据
+    --log.info("Unpack", byte1,byte2,byte3,byte4)		
+	log.info("Unpack:", string.format("%02X", byte1),   --以十六进制形式输出拆解后的4个字节数据
+						string.format("%02X", byte2), 
+						string.format("%02X", byte3), 
+						string.format("%02X", byte4))
+end)
+-- 这里演示4G模块上网后,会自动点亮网络灯,方便用户判断模块是否正常开机
+sys.taskInit(function()
+    while true do
+        sys.wait(6000)
+                if mobile.status() == 1 then
+                        gpio.set(27, 1)  
+                else
+                        gpio.set(27, 0) 
+                        mobile.reset()
+        end
+    end
+end)
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 72 - 0
module/Air8000/demo/protobuf/main.lua

@@ -0,0 +1,72 @@
+--- 模块功能:Google ProtoBuffs 编解码
+-- @module pb
+-- @author wendal
+-- @release 2022.9.8
+
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "pbdemo"
+VERSION = "1.0.1"
+
+log.info("main", PROJECT, VERSION)
+
+-- sys库是标配
+_G.sys = require("sys")
+
+--添加硬狗防止程序卡死
+if wdt then
+    wdt.init(9000)--初始化watchdog设置为9s
+    sys.timerLoopStart(wdt.feed, 3000)--3s喂一次狗
+end
+
+sys.taskInit(function()
+    sys.wait(500)
+    -- 如果没有这个库, 就云编译一份吧: https://wiki.luatos.com/develop/compile/Cloud_compilation.html
+    if not protobuf then
+        log.info("protobuf", "this demo need protobuf lib")
+        return
+    end
+    -- 加载 pb 文件, 这个是从pbtxt 转换得到的
+    -- 下载资源到模块时不需要下载pbtxt
+    -- 转换命令: protoc.exe -operson.pb person.pbtxt
+    -- protoc.exe 下载地址: https://github.com/protocolbuffers/protobuf/releases
+    local pb_file = "/luadb/person.pb"
+    
+    if io.exists(pb_file) then
+        protobuf.load(io.readFile(pb_file))
+        sys.publish("pb_file_exists")
+    else
+        log.info("protobuf","Failed to load file")
+    end
+
+    local tb = {
+        name = "wendal",
+        id = 123,
+        email = "abc@qq.com"
+    }
+    while 1 do
+        sys.waitUntil("pb_file_exists")
+        sys.wait(1000)
+        -- 用 protobuf 编码数据
+        local pbdata = protobuf.encode("Person", tb)
+        if pbdata then
+            -- 打印数据长度. 编码后的数据含不可见字符, toHex是方便显示
+            log.info("protobuf", "encode",  #pbdata, (pbdata:toHex()))
+        end
+        -- 用 json 编码数据, 用于对比大小
+        local jdata = json.encode(tb)
+        if jdata then
+            log.info("json", #jdata, jdata)
+        end
+        -- 可见 protobuffs 比 json 节省很多空间
+
+        -- 后续是演示解码
+        local re = protobuf.decode("Person", pbdata)
+        if re then
+            -- 打印数据, 因为table不能直接显示, 这里转成json来显示
+            log.info("protobuf", "decode", json.encode(re))
+        end
+    end
+end)
+
+-- 主循环, 必须加
+sys.run()

+ 7 - 0
module/Air8000/demo/protobuf/person.pb

@@ -0,0 +1,7 @@
+
+R
+person.pbtxt"B
+Person
+name (	Rname
+id (Rid
+email (	Remail

+ 6 - 0
module/Air8000/demo/protobuf/person.pbtxt

@@ -0,0 +1,6 @@
+syntax = "proto2";
+message Person {
+  optional string name = 1;
+  optional int32 id = 2;
+  optional string email = 3;
+}

+ 43 - 0
module/Air8000/demo/pwm/PWM呼吸灯/main.lua

@@ -0,0 +1,43 @@
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "pwmdemo"
+VERSION = "1.0.0"
+
+log.info("main", PROJECT, VERSION)
+
+-- sys库是标配
+_G.sys = require("sys")
+
+--添加硬狗防止程序卡死
+if wdt then
+    wdt.init(9000) -- 初始化watchdog设置为9s
+    sys.timerLoopStart(wdt.feed, 3000)--3s喂一次狗
+end
+
+local PWM_ID = 4  -- 代码中使用pwm通道4,如需使用其他pwm通道请查看Air8000/pwm使用指南/pwm通道说明。
+sys.taskInit(function()
+    
+    -- 配置IO复用,PIN24 GPIO21 FUNC5-PWM4
+    gpio.setup(21, 0, nil, nil, 5)
+
+    log.info("pwm", "ch", PWM_ID)
+    while 1 do
+        -- 仿呼吸灯效果
+        log.info("pwm", ">>>>>")
+        -- 占空比从90%(i=10时)到9%(i=1时)
+        for i = 10,1,-1 do 
+            pwm.open(PWM_ID, 1000, i*9) -- 频率1000hz, 占空比0-100
+            sys.wait(100 + i*10)
+        end
+        -- 占空比从10%增加到90%
+        for i = 10,1,-1 do 
+            pwm.open(PWM_ID, 1000, 100 - i*9)
+            sys.wait(100 + i*10)
+        end
+        sys.wait(2000)
+    end
+end) 
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 42 - 0
module/Air8000/demo/pwm/PWM输出/main.lua

@@ -0,0 +1,42 @@
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "pwmdemo"
+VERSION = "1.0.0"
+
+log.info("main", PROJECT, VERSION)
+
+-- sys库是标配
+_G.sys = require("sys")
+
+--添加硬狗防止程序卡死
+if wdt then
+    wdt.init(9000) -- 初始化watchdog设置为9s
+    sys.timerLoopStart(wdt.feed, 3000)--3s喂一次狗
+end
+
+local PWM_ID = 4  -- 代码中使用pwm通道4,如需使用其他pwm通道请查看Air8000/pwm使用指南/pwm通道说明。
+sys.taskInit(function()
+
+    -- 配置IO复用,PIN24 GPIO21 FUNC5-PWM4
+    gpio.setup(21, 0, nil, nil, 5) 
+
+    log.info("pwm", "ch", PWM_ID)
+    while true do
+        -- 开启pwm通道0,设置脉冲频率为1kHz,分频精度为1000,占空比为10/1000=1% 持续输出
+        pwm.open(PWM_ID, 1000, 10, 0, 1000) -- 小灯微微发光
+        log.info("pwm", "当前分频精度1000,占空比1%")
+        sys.wait(1000)
+        -- 开启pwm通道0,设置脉冲频率为1kHz,分频精度为256,占空比为128/256=50% 持续输出
+        pwm.open(PWM_ID, 1000, 128, 0, 256) -- 小灯中等亮度
+        log.info("pwm", "当前分频精度256,占空比50%")
+        sys.wait(1000)
+        -- 开启pwm通道0,设置脉冲频率为1kHz,分频精度为100,占空比为100/100=100% 持续输出
+        pwm.open(PWM_ID, 1000, 100, 0, 100) -- 小灯很高亮度
+        log.info("pwm", "当前分频精度100,占空比100%")
+        sys.wait(1000)
+    end
+end)
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 34 - 0
module/Air8000/demo/pwm/示例1 PWM输出/main.lua

@@ -0,0 +1,34 @@
+
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "pwmdemo"
+VERSION = "1.0.0"
+
+log.info("main", PROJECT, VERSION)
+
+-- sys库是标配
+_G.sys = require("sys")
+
+--添加硬狗防止程序卡死
+if wdt then
+    wdt.init(9000)--初始化watchdog设置为9s
+    sys.timerLoopStart(wdt.feed, 3000)--3s喂一次狗
+end
+
+sys.taskInit(function()
+    while true do
+        -- 开启pwm通道4,设置脉冲频率为1kHz,分频精度为1000,占空比为10/1000=1% 持续输出
+        pwm.open(4, 1000, 10, 0, 1000) -- 小灯微微发光
+        sys.wait(1000)
+        -- 开启pwm通道4,设置脉冲频率为1kHz,分频精度为1000,占空比为500/1000=50% 持续输出
+        pwm.open(4, 1000, 500, 0, 1000) -- 小灯中等亮度
+        sys.wait(1000)
+        -- 开启pwm通道4,设置脉冲频率为1kHz,分频精度为1000,占空比为1000/1000=100% 持续输出
+        pwm.open(4, 1000, 1000, 0, 1000) -- 小灯很高亮度
+        sys.wait(1000)
+    end
+end)
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 58 - 0
module/Air8000/demo/pwm/示例2 呼吸灯效果/main.lua

@@ -0,0 +1,58 @@
+
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "pwmdemo"
+VERSION = "1.0.0"
+
+log.info("main", PROJECT, VERSION)
+
+-- sys库是标配
+_G.sys = require("sys")
+
+--添加硬狗防止程序卡死
+if wdt then
+    wdt.init(9000)--初始化watchdog设置为9s
+    sys.timerLoopStart(wdt.feed, 3000)--3s喂一次狗
+end
+
+local PWM_ID = 0
+local rtos_bsp = rtos.bsp()
+if rtos_bsp == "EC618" then
+    PWM_ID = 1 -- GPIO 24
+elseif string.find(rtos_bsp,"EC718") then
+    PWM_ID = 2 -- GPIO 25
+elseif rtos_bsp == "AIR101" or rtos_bsp == "AIR103" or rtos_bsp == "AIR601"  then
+    PWM_ID = 4 -- GPIO 4
+elseif rtos_bsp:startsWith("ESP32") then
+    -- 注意, ESP32系列的PWM, PWM通道均与GPIO号相同
+    -- 例如需要用GPIO1输出PWM, 对应的PWM通道就是1
+    -- 需要用GPIO16输出PWM, 对应的PWM通道就是16
+    if rtos_bsp == "ESP32C3" then
+        PWM_ID = 12 -- GPIO 12
+    elseif rtos_bsp == "ESP32S3" then
+        PWM_ID = 11 -- GPIO 11
+    end
+elseif rtos_bsp == "AIR105" then
+    PWM_ID = 1 -- GPIO 17
+end
+
+sys.taskInit(function()
+    log.info("pwm", "ch", PWM_ID)
+    while 1 do
+        -- 仿呼吸灯效果
+        log.info("pwm", ">>>>>")
+        for i = 10,1,-1 do 
+            pwm.open(PWM_ID, 1000, i*9) -- 频率1000hz, 占空比0-100
+            sys.wait(100 + i*10)
+        end
+        for i = 10,1,-1 do 
+            pwm.open(PWM_ID, 1000, 100 - i*9)
+            sys.wait(100 + i*10)
+        end
+        sys.wait(2000)
+    end
+end)
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 50 - 0
module/Air8000/demo/rc522/main.lua

@@ -0,0 +1,50 @@
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "RC522"
+VERSION = "1.0.0"
+
+log.info("main", PROJECT, VERSION)
+sys = require("sys")
+local rc522 = require "rc522"
+
+local SPI_ID = 1
+local CS_PIN = 12
+local RST_PIN = 21
+
+-- SPI初始化配置
+sys.taskInit(function()
+    -- 配置SPI总线
+    -- spi_rc522 = spi.setup(
+    --     SPI_ID,--spi_id
+    --     nil,
+    --     0,--CPHA
+    --     0,--CPOL
+    --     8,--数据宽度
+    --     10000000--,10MHz频率
+    --     -- spi.MSB,--高低位顺序    可选,默认高位在前
+    --     -- spi.master,--主模式     可选,默认主
+    --     -- spi.full--全双工       可选,默认全双工
+    -- )
+    spi_rc522 = spi.setup(SPI_ID, nil, 0, 0, 8, 10 * 1000 * 1000)
+
+    -- RC522模块初始化
+    if rc522.init(SPI_ID, CS_PIN, RST_PIN) then
+        log.info("RC522", "初始化成功")
+    else
+        log.error("RC522", "初始化失败,请检查接线")
+        return
+    end
+
+    -- 主循环读取卡片
+    while true do
+        -- 检测卡片并获取UID
+        local status, array_id = rc522.request(rc522.reqall)
+        log.info("rc522.request:", status, array_id)
+        if status then
+            local success, uid = rc522.anticoll(array_id)
+            log.info("rc522.anticoll:", success, uid:toHex())
+        end
+        sys.wait(500) -- 降低轮询频率
+    end
+end)
+
+sys.run()

+ 87 - 0
module/Air8000/demo/sms/main.lua

@@ -0,0 +1,87 @@
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "smsdemo"
+VERSION = "1.0.0"
+
+log.info("main", PROJECT, VERSION)
+
+-- 引入必要的库文件(lua编写), 内部库不需要require
+sys = require("sys")
+require "sysplus" -- http库需要这个sysplus
+
+if wdt then
+    --添加硬狗防止程序卡死,在支持的设备上启用这个功能
+    wdt.init(9000)--初始化watchdog设置为9s
+    sys.timerLoopStart(wdt.feed, 3000)--3s喂一次狗
+end
+log.info("main", "sms demo")
+
+-- 辅助发送http请求, 因为http库需要在task里运行
+function http_post(url, headers, body)
+    sys.taskInit(function()
+        local code, headers, body = http.request("POST", url, headers, body).wait()
+        log.info("resp", code)
+    end)
+end
+
+function sms_handler(num, txt)
+    -- num 手机号码
+    -- txt 文本内容
+    log.info("sms", num, txt, txt:toHex())
+
+    -- http演示1, 发json
+    local body = json.encode({phone=num, txt=txt})
+    local headers = {}
+    headers["Content-Type"] = "application/json"
+    log.info("json", body)
+    http_post("http://www.luatos.com/api/sms/blackhole", headers, body)
+    -- http演示2, 发表单的
+    headers = {}
+    headers["Content-Type"] = "application/x-www-form-urlencoded"
+    local body = string.format("phone=%s&txt=%s", num:urlEncode(), txt:urlEncode())
+    log.info("params", body)
+    http_post("http://www.luatos.com/api/sms/blackhole", headers, body)
+    -- http演示3, 不需要headers,直接发
+    http_post("http://www.luatos.com/api/sms/blackhole", nil, num .. "," .. txt)
+    -- 如需发送到钉钉, 参考 demo/dingding
+    -- 如需发送到飞书, 参考 demo/feishu
+end
+
+--------------------------------------------------------------------
+-- 接收短信, 支持多种方式, 选一种就可以了
+-- 1. 设置回调函数
+--sms.setNewSmsCb(sms_handler)
+-- 2. 订阅系统消息
+--sys.subscribe("SMS_INC", sms_handler)
+-- 3. 在task里等着
+sys.taskInit(function()
+    while 1 do
+        local ret, num, txt = sys.waitUntil("SMS_INC", 300000)
+        if num then
+            -- 方案1, 交给自定义函数处理
+            sms_handler(num, txt)
+            -- 方案2, 因为这里是task内, 可以直接调用http.request
+            -- local body = json.encode({phone=num, txt=txt})
+            -- local headers = {}
+            -- headers["Content-Type"] = "application/json"
+            -- log.info("json", body)
+            -- local code, headers, body = http.request("POST", "http://www.luatos.com/api/sms/blackhole", headers, body).wait()
+            -- log.info("resp", code)
+        end
+    end
+end)
+
+-------------------------------------------------------------------
+-- 发送短信, 直接调用sms.send就行, 是不是task无所谓
+sys.taskInit(function()
+    sys.wait(10000)
+    -- 中移动卡查短信
+    -- sms.send("+8610086", "301")
+    -- 联通卡查话费
+     sms.send("10010", "101")
+end)
+
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 78 - 0
module/Air8000/demo/spi/main.lua

@@ -0,0 +1,78 @@
+
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "w25q_spi_demo"
+VERSION = "1.0.1"
+
+sys = require("sys")
+
+--spi编号,请按实际情况修改!
+local spiId = 0
+--cs脚,请按需修改!
+local cs = 8 -- CS使用GPIO8
+local cspin = gpio.setup(cs, 1)  --配置CS为输出
+
+--收发数据
+local function sendRecv(data,len)
+    local r = ""
+    cspin(0)
+    if data then spi.send(spiId,data) end
+    if len then r = spi.recv(spiId,len) end
+    cspin(1)
+    return r
+end
+
+
+sys.taskInit(function()
+
+    local result = spi.setup(
+        spiId,--串口id
+        nil,
+        0,--CPHA
+        0,--CPOL
+        8,--数据宽度
+        100000--,--频率
+        -- spi.MSB,--高低位顺序    可选,默认高位在前
+        -- spi.master,--主模式     可选,默认主
+        -- spi.full--全双工       可选,默认全双工
+    )
+    print("open",result)
+    if result ~= 0 then--返回值为0,表示打开成功
+        print("spi open error",result)
+        return
+    end
+
+    --检查芯片型号
+    local chip = sendRecv(string.char(0x9f),3)
+    if chip == string.char(0xef,0x40,0x17) then
+        log.info("spi", "chip id read ok 0xef,0x40,0x17")
+    else
+        log.info("spi", "chip id read error")
+        for i=1,#chip do
+            print(chip:byte(i))
+        end
+        return
+    end
+
+    local data = "test data 123456"
+
+    --enable write
+    sendRecv(string.char(0x06))
+
+    --写页数据到地址0x000001
+    sendRecv(string.char(0x02,0x00,0x00,0x01)..data)
+    log.info("spi","write",data)
+
+    sys.wait(500)--等写入操作完成
+
+    --读数据
+    local r = sendRecv(string.char(0x03,0x00,0x00,0x01),data:len())
+    log.info("spi","read",r)
+
+    --disable write
+    sendRecv(string.char(0x04))
+
+    spi.close(spiId)
+end)
+
+-- 结尾总是这一句哦
+sys.run()

+ 113 - 0
module/Air8000/demo/string/main.lua

@@ -0,0 +1,113 @@
+
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "strtest"
+VERSION = "2.0.0"
+
+--[[
+本demo演示 string字符串的基本操作
+1. lua的字符串是带长度, 这意味着, 它不依赖0x00作为结束字符串, 可以包含任意数据
+2. lua的字符串是不可变的, 就不能直接修改字符串的一个字符, 修改字符会返回一个新的字符串
+]]
+
+-- sys库是标配
+_G.sys = require("sys")
+
+sys.taskInit(function ()
+    sys.wait(1000) -- 免得看不到日志
+    local tmp
+
+    ----------------------------------------------
+    --================================================
+    -- 字符串的声明和生成
+    --================================================
+
+    -- 常量声明
+    local str = "123455" 
+    log.info("str", str)														--日志输出:123455
+
+    -- 合成式
+    str = string.char(0x31, 0x32, 0x33, 0x34)  --0x31为字符 1的ASCII码
+    log.info("str", str)           												--日志输出:1234                   
+    -- lua的字符串可以包含任意数据, 包括 0x00
+    str = string.char(0x12, 0x00, 0xF1, 0x3A)
+    log.info("str", str:toHex()) -- 注意, 这里用toHex(), 因为包含了不可见字符   --日志输出:1200F13A	8(其中8为输出字符串长度)
+    -- 使用转义字符
+    str = "\x00\x12ABC"			 -- 字符串中的\x表示十六进制转义序列								
+    log.info("str", str:toHex()) -- 注意, 这里用toHex(), 因为包含了不可见字符   --日志输出:0012414243	10 (其中41,42,43分别分字符 ABC的ASCII值的十六进制形式,10为输出字符串长度)
+    str = "ABC\r\n\t"
+    log.info("str", str:toHex()) -- 注意, 这里用toHex(), 因为包含了不可见字符   --日志输出:4142430D0A09	12(其中0D为\r回车键值的ASCII值的十六进制形式,
+	                                                                            --0A为\n换行键值的ASCII值的十六进制形式,\t 是一个转义字符,表示一个水平制表符(Tab))
+
+
+
+    -- 解析生成
+    str = string.fromHex("AABB00EE")											
+    log.info("str", str:toHex())												--日志输出:AABB00EE	8
+    str = string.fromHex("393837363433")       --将字符串转换为十六进制形式
+    log.info("str", #str, str)												    --日志输出:6	987643(其中6为输出字符长度,987643为输出字符串)
+
+    -- 连接字符串, 操作符 ".."
+    str = "123" .. "," .. "ABC"  --将3段字符串连接起来
+    log.info("str", #str, str)												    --日志输出:7	123,ABC(其中7为输出字符长度,123,ABC为连接后的字符串)
+
+
+    -- 格式化生成
+    str = string.format("%s,%d,%f", "123", 45678, 1.5)		--格式化输出,	%s为字符串输出,%d为十进制输出,%f为浮点形式输出			
+    log.info("str", #str, str)													--日志输出:18	123,45678,1.500000
+
+
+    --================================================
+    -- 字符串的解析与处理
+    --================================================
+    -- 获取长度
+    str = "1234567"
+    log.info("str", #str)														--日志输出:7为字符串长度
+    -- 获取字符串的HEX字符串显示
+    log.info("str", str:toHex())												--日志输出:31323334353637	14(用字符格式输出十六进制)
+
+    -- 获取指定位置的值, 注意lua的下标是1开始的
+    str = "123ddss"
+    log.info("str[1]", str:byte(1))                                             --日志输出:49	 (字符1,对应十进制ASCII值)
+    log.info("str[4]", str:byte(4))												--日志输出: 100	 (字符d,对应十进制ASCII值)
+    log.info("str[1]", string.byte(str, 1))										--日志输出:49   (str位置1的字符,也是数字1)
+    log.info("str[4]", string.byte(str, 4))										--日志输出: 100	 (str位置4的字符,也是数字d)
+
+    -- 按字符串分割
+    str = "12,2,3,4,5"
+    tmp = str:split(",")
+    log.info("str.split", #tmp, tmp[1], tmp[3])									--日志输出:5	12	3
+    tmp = string.split(str, ",") -- 与前面的等价
+    log.info("str.split", #tmp, tmp[1], tmp[3])                                 --日志输出:5	12	3
+    str = "/tmp//def/1234/"
+    tmp = str:split("/")
+    log.info("str.split", #tmp, json.encode(tmp))								--日志输出:3	["tmp","def","1234"]
+
+    -- 2023.04.11新增的, 可以保留空的分割片段
+	--在 Lua 中,str:split("/", true) 语句表示将字符串 str 按照字符 "/" 进行分割,并且 true 参数通常用于表示保留空字符串(这取决于具体的 split 函数实现,因为 Lua 标准库中没有内置的 split 函数)。根据你的描述,输出结果是 6 ["","tmp","","def","1234",""]。这是因为:
+    --假设 str 是 "/tmp//def/1234/",在这种情况下,字符串以 "/" 开头和结尾,并且有连续的 "/"。
+    --split 函数将字符串分割成多个部分,每个 "/" 都会作为一个分割符。
+    --因为 true 参数表示保留空字符串,所以在分割过程中,连续的 "/" 和开头、结尾的 "/" 都会导致空字符串被保留。
+
+    tmp = str:split("/", true) 
+    log.info("str.split", #tmp, json.encode(tmp))								--日志输出:6	["","tmp","","def","1234",""]
+
+    -- 更多资料
+    -- https://wiki.luatos.com/develop/hex_string.html
+    -- https://wiki.luatos.com/_static/lua53doc/manual.html#3.4
+end)
+-- 这里演示4G模块上网后,会自动点亮网络灯,方便用户判断模块是否正常开机
+sys.taskInit(function()
+    while true do
+        sys.wait(6000)
+                if mobile.status() == 1 then
+                        gpio.set(27, 1)  
+                else
+                        gpio.set(27, 0) 
+                        mobile.reset()
+        end
+    end
+end)
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 134 - 0
module/Air8000/demo/tcp/TCP-UART/main.lua

@@ -0,0 +1,134 @@
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "uart_tcp"
+VERSION = "1.0.0"
+
+log.info("main", PROJECT, VERSION)
+
+-- 引入必要的库文件(lua编写), 内部库不需要require
+sys = require("sys")
+
+_G.sysplus = require("sysplus")
+local taskName = "TCP_TASK"             -- sysplus库用到的任务名称,也作为任务id
+
+if wdt then
+    --添加硬狗防止程序卡死,在支持的设备上启用这个功能
+    wdt.init(9000)--初始化watchdog设置为9s
+    sys.timerLoopStart(wdt.feed, 3000)--3s喂一次狗
+end
+local uartid = 1 -- 根据实际设备选取不同的uartid
+local uart_rx_buff = zbuff.create(1024)     -- 串口接收到的数据
+local libnet = require "libnet"         -- libnet库,支持tcp、udp协议所用的同步阻塞接口
+local ip = "112.125.89.8"               -- 连接tcp服务器的ip地址
+local port = 46244                 -- 连接tcp服务器的端口
+local netCB = nil                       -- socket服务的回调函数
+local connect_state = false             -- 连接状态 true:已连接   false:未连接
+local protocol = false                  -- 通讯协议 true:UDP协议  false:TCP协议
+local ssl = false                       -- 加密传输 true:加密     false:不加密
+local tx_buff = zbuff.create(1024)      -- 发送至tcp服务器的数据
+local rx_buff = zbuff.create(1024)      -- 从tcp服务器接收到的数据
+
+--初始化
+uart.setup(
+    uartid,--串口id
+    115200,--波特率
+    8,--数据位
+    1--停止位
+)
+function TCP_TASK()
+    -- 打印一下连接的目标ip和端口号
+    log.info("connect ip: ", ip, "port:", port)
+
+    sys.waitUntil("IP_READY")                -- 等待联网成功
+    netCB = socket.create(nil, taskName)     -- 创建socket对象
+    socket.debug(netCB, true)                -- 打开调试日志
+    socket.config(netCB, nil, protocol, ssl)      -- 此配置为TCP连接,无SSL加密
+
+    -- 串口和TCP服务器的交互逻辑
+    while true do
+        -- 连接服务器,返回是否连接成功
+        result = libnet.connect(taskName, 15000, netCB, ip, port)
+
+        -- 收取数据会触发回调, 这里的"receive" 是固定值不要修改。
+        uart.on(uartid, "receive", function(id, len)
+            while true do
+                local len = uart.rx(id, uart_rx_buff)   -- 接收串口收到的数据,并赋值到uart_rx_buff
+                if len <= 0 then    -- 接收到的字节长度为0 则退出
+                    break
+                end
+                -- 如果已经在线了,则发送socket.EVENT消息来打断任务里的阻塞等待状态,让任务循环继续
+                if connect_state then
+                    sys_send(taskName, socket.EVENT, 0)
+                end
+            end
+        end)
+
+        -- 如果连接成功,则改变连接状态参数,并且随便发一条数据到服务器,看服务器能不能收到
+        if result then
+            connect_state = true
+            libnet.tx(taskName, 0, netCB, "TCP  CONNECT")
+        end
+
+        -- 连接上服务器后,等待处理接收服务器下行至模块的数据 和 发送串口的数据到服务器
+        while result do
+            succ, param, _, _ = socket.rx(netCB, rx_buff)   -- 接收数据
+            if not succ then
+                log.info("服务器断开了", succ, param, ip, port)
+                break
+            end
+
+            if rx_buff:used() > 0 then
+                log.info("收到服务器数据,长度", rx_buff:used())
+
+                uart.tx(uartid, rx_buff)    -- 从服务器收到的数据转发 从串口输出
+                rx_buff:del()
+            end
+
+            tx_buff:copy(nil, uart_rx_buff)         -- 将串口数据赋值给tcp待发送数据的buff中
+            uart_rx_buff:del()                      -- 清除串口buff的数据长度
+            if tx_buff:used() > 0 then
+                log.info("发送到服务器数据,长度", tx_buff:used())
+                local result = libnet.tx(taskName, 0, netCB, tx_buff)   -- 发送数据
+                if not result then
+                    log.info("发送失败了", result, param)
+                    break
+                end
+            end
+            tx_buff:del()
+
+            -- 如果zbuff对象长度超出,需要重新分配下空间
+            if uart_rx_buff:len() > 1024 then
+                uart_rx_buff:resize(1024)
+            end
+            if tx_buff:len() > 1024 then
+                tx_buff:resize(1024)
+            end
+            if rx_buff:len() > 1024 then
+                rx_buff:resize(1024)
+            end
+            log.info(rtos.meminfo("sys"))   -- 打印系统内存
+
+            -- 阻塞等待新的消息到来,比如服务器下发,串口接收到数据
+            result, param = libnet.wait(taskName, 15000, netCB)
+            if not result then
+                log.info("服务器断开了", result, param)
+                break
+            end
+        end
+
+        -- 服务器断开后的行动,由于while true的影响,所以会再次重新执行进行 重新连接。
+        connect_state = false
+        libnet.close(taskName, 5000, netCB)
+        tx_buff:clear(0)
+        rx_buff:clear(0)
+        sys.wait(1000)
+    end
+
+end
+
+-- libnet库依赖于sysplus,所以只能通过sysplus.taskInitEx创建的任务函数中运行
+sysplus.taskInitEx(TCP_TASK, taskName, netCB)
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 139 - 0
module/Air8000/demo/tcp/TCP单向认证/main.lua

@@ -0,0 +1,139 @@
+-- main.lua文件
+
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "uart_tcp"
+VERSION = "1.0.0"
+
+log.info("main", PROJECT, VERSION)
+
+-- 引入必要的库文件(lua编写), 内部库不需要require
+sys = require("sys")
+
+_G.sysplus = require("sysplus")
+local taskName = "TCP_TASK"             -- sysplus库用到的任务名称,也作为任务id
+
+if wdt then
+    --添加硬狗防止程序卡死,在支持的设备上启用这个功能
+    wdt.init(9000)--初始化watchdog设置为9s
+    sys.timerLoopStart(wdt.feed, 3000)--3s喂一次狗
+end
+
+local uartid = 1 -- 根据实际设备选取不同的uartid
+local uart_rx_buff = zbuff.create(1024)     -- 串口接收到的数据
+
+local libnet = require "libnet"         -- libnet库,支持tcp、udp协议所用的同步阻塞接口
+local ip = "112.125.89.8"               -- 连接tcp服务器的ip地址
+local port = 46428            -- 连接tcp服务器的端口
+local netCB = nil                       -- socket服务的回调函数
+local connect_state = false             -- 连接状态 true:已连接   false:未连接
+local protocol = false                  -- 通讯协议 true:UDP协议  false:TCP协议
+local ssl = true                     -- 加密传输 true:加密     false:不加密
+local tx_buff = zbuff.create(1024)      -- 发送至tcp服务器的数据
+local rx_buff = zbuff.create(1024)      -- 从tcp服务器接收到的数据
+
+--初始化
+uart.setup(
+    uartid,--串口id
+    115200,--波特率
+    8,--数据位
+    1--停止位
+)
+
+function TCP_TASK()
+    -- 打印一下连接的目标ip和端口号
+    log.info("connect ip: ", ip, "port:", port)
+
+    sys.waitUntil("IP_READY")                -- 等待联网成功
+    netCB = socket.create(nil, taskName)     -- 创建socket对象
+    socket.debug(netCB, true)                -- 打开调试日志
+    socket.config(netCB, nil, protocol, ssl)      -- 此配置为TCP连接,无SSL加密
+
+    -- 串口和TCP服务器的交互逻辑
+    while true do
+        -- 连接服务器,返回是否连接成功
+        result = libnet.connect(taskName, 15000, netCB, ip, port)
+
+        -- 收取数据会触发回调, 这里的"receive" 是固定值不要修改。
+        uart.on(uartid, "receive", function(id, len)
+            while true do
+                local len = uart.rx(id, uart_rx_buff)   -- 接收串口收到的数据,并赋值到uart_rx_buff
+                if len <= 0 then    -- 接收到的字节长度为0 则退出
+                    break
+                end
+                -- 如果已经在线了,则发送socket.EVENT消息来打断任务里的阻塞等待状态,让任务循环继续
+                if connect_state then
+                    sys_send(taskName, socket.EVENT, 0)
+                end
+            end
+        end)
+
+        -- 如果连接成功,则改变连接状态参数,并且随便发一条数据到服务器,看服务器能不能收到
+        if result then
+            connect_state = true
+            libnet.tx(taskName, 0, netCB, "TCP  CONNECT")
+        end
+
+        -- 连接上服务器后,等待处理接收服务器下行至模块的数据 和 发送串口的数据到服务器
+        while result do
+            succ, param, _, _ = socket.rx(netCB, rx_buff)   -- 接收数据
+            if not succ then
+                log.info("服务器断开了", succ, param, ip, port)
+                break
+            end
+
+            if rx_buff:used() > 0 then
+                log.info("收到服务器数据,长度", rx_buff:used())
+
+                uart.tx(uartid, rx_buff)    -- 从服务器收到的数据转发 从串口输出
+                rx_buff:del()
+            end
+
+            tx_buff:copy(nil, uart_rx_buff)         -- 将串口数据赋值给tcp待发送数据的buff中
+            uart_rx_buff:del()                      -- 清除串口buff的数据长度
+            if tx_buff:used() > 0 then
+                log.info("发送到服务器数据,长度", tx_buff:used())
+                local result = libnet.tx(taskName, 0, netCB, tx_buff)   -- 发送数据
+                if not result then
+                    log.info("发送失败了", result, param)
+                    break
+                end
+            end
+            tx_buff:del()
+
+            -- 如果zbuff对象长度超出,需要重新分配下空间
+            if uart_rx_buff:len() > 1024 then
+                uart_rx_buff:resize(1024)
+            end
+            if tx_buff:len() > 1024 then
+                tx_buff:resize(1024)
+            end
+            if rx_buff:len() > 1024 then
+                rx_buff:resize(1024)
+            end
+            log.info(rtos.meminfo("sys"))   -- 打印系统内存
+
+            -- 阻塞等待新的消息到来,比如服务器下发,串口接收到数据
+            result, param = libnet.wait(taskName, 15000, netCB)
+            if not result then
+                log.info("服务器断开了", result, param)
+                break
+            end
+        end
+
+        -- 服务器断开后的行动,由于while true的影响,所以会再次重新执行进行 重新连接。
+        connect_state = false
+        libnet.close(taskName, 5000, netCB)
+        tx_buff:clear(0)
+        rx_buff:clear(0)
+        sys.wait(1000)
+    end
+
+end
+
+-- libnet库依赖于sysplus,所以只能通过sysplus.taskInitEx创建的任务函数中运行
+sysplus.taskInitEx(TCP_TASK, taskName, netCB)
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 134 - 0
module/Air8000/demo/tcp/TCP断链续连/main.lua

@@ -0,0 +1,134 @@
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "uart_tcp"
+VERSION = "1.0.0"
+
+log.info("main", PROJECT, VERSION)
+
+-- 引入必要的库文件(lua编写), 内部库不需要require
+sys = require("sys")
+
+_G.sysplus = require("sysplus")
+local taskName = "TCP_TASK"             -- sysplus库用到的任务名称,也作为任务id
+
+if wdt then
+    --添加硬狗防止程序卡死,在支持的设备上启用这个功能
+    wdt.init(9000)--初始化watchdog设置为9s
+    sys.timerLoopStart(wdt.feed, 3000)--3s喂一次狗
+end
+local uartid = 1 -- 根据实际设备选取不同的uartid
+local uart_rx_buff = zbuff.create(1024)     -- 串口接收到的数据
+local libnet = require "libnet"         -- libnet库,支持tcp、udp协议所用的同步阻塞接口
+local ip = "112.125.89.8"               -- 连接tcp服务器的ip地址
+local port = 46244                 -- 连接tcp服务器的端口
+local netCB = nil                       -- socket服务的回调函数
+local connect_state = false             -- 连接状态 true:已连接   false:未连接
+local protocol = false                  -- 通讯协议 true:UDP协议  false:TCP协议
+local ssl = false                       -- 加密传输 true:加密     false:不加密
+local tx_buff = zbuff.create(1024)      -- 发送至tcp服务器的数据
+local rx_buff = zbuff.create(1024)      -- 从tcp服务器接收到的数据
+
+--初始化
+uart.setup(
+    uartid,--串口id
+    115200,--波特率
+    8,--数据位
+    1--停止位
+)
+function TCP_TASK()
+    -- 打印一下连接的目标ip和端口号
+    log.info("connect ip: ", ip, "port:", port)
+
+    sys.waitUntil("IP_READY")                -- 等待联网成功
+    netCB = socket.create(nil, taskName)     -- 创建socket对象
+    socket.debug(netCB, true)                -- 打开调试日志
+    socket.config(netCB, nil, protocol, ssl)      -- 此配置为TCP连接,无SSL加密
+
+    -- 串口和TCP服务器的交互逻辑
+    while true do
+        -- 连接服务器,返回是否连接成功
+        result = libnet.connect(taskName, 15000, netCB, ip, port)
+
+        -- 收取数据会触发回调, 这里的"receive" 是固定值不要修改。
+        uart.on(uartid, "receive", function(id, len)
+            while true do
+                local len = uart.rx(id, uart_rx_buff)   -- 接收串口收到的数据,并赋值到uart_rx_buff
+                if len <= 0 then    -- 接收到的字节长度为0 则退出
+                    break
+                end
+                -- 如果已经在线了,则发送socket.EVENT消息来打断任务里的阻塞等待状态,让任务循环继续
+                if connect_state then
+                    sys_send(taskName, socket.EVENT, 0)
+                end
+            end
+        end)
+
+        -- 如果连接成功,则改变连接状态参数,并且随便发一条数据到服务器,看服务器能不能收到
+        if result then
+            connect_state = true
+            libnet.tx(taskName, 0, netCB, "TCP  CONNECT")
+        end
+
+        -- 连接上服务器后,等待处理接收服务器下行至模块的数据 和 发送串口的数据到服务器
+        while result do
+            succ, param, _, _ = socket.rx(netCB, rx_buff)   -- 接收数据
+            if not succ then
+                log.info("服务器断开了", succ, param, ip, port)
+                break
+            end
+
+            if rx_buff:used() > 0 then
+                log.info("收到服务器数据,长度", rx_buff:used())
+
+                uart.tx(uartid, rx_buff)    -- 从服务器收到的数据转发 从串口输出
+                rx_buff:del()
+            end
+
+            tx_buff:copy(nil, uart_rx_buff)         -- 将串口数据赋值给tcp待发送数据的buff中
+            uart_rx_buff:del()                      -- 清除串口buff的数据长度
+            if tx_buff:used() > 0 then
+                log.info("发送到服务器数据,长度", tx_buff:used())
+                local result = libnet.tx(taskName, 0, netCB, tx_buff)   -- 发送数据
+                if not result then
+                    log.info("发送失败了", result, param)
+                    break
+                end
+            end
+            tx_buff:del()
+
+            -- 如果zbuff对象长度超出,需要重新分配下空间
+            if uart_rx_buff:len() > 1024 then
+                uart_rx_buff:resize(1024)
+            end
+            if tx_buff:len() > 1024 then
+                tx_buff:resize(1024)
+            end
+            if rx_buff:len() > 1024 then
+                rx_buff:resize(1024)
+            end
+            log.info(rtos.meminfo("sys"))   -- 打印系统内存
+
+            -- 阻塞等待新的消息到来,比如服务器下发,串口接收到数据
+            result, param = libnet.wait(taskName, 15000, netCB)
+            if not result then
+                log.info("服务器断开了", result, param)
+                break
+            end
+        end
+
+        -- 服务器断开后的行动,由于while true的影响,所以会再次重新执行进行 重新连接。
+        connect_state = false
+        libnet.close(taskName, 5000, netCB)
+        tx_buff:clear(0)
+        rx_buff:clear(0)
+        sys.wait(1000)
+    end
+
+end
+
+-- libnet库依赖于sysplus,所以只能通过sysplus.taskInitEx创建的任务函数中运行
+sysplus.taskInitEx(TCP_TASK, taskName, netCB)
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 51 - 0
module/Air8000/demo/timer/main.lua

@@ -0,0 +1,51 @@
+
+-- main.lua文件
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "uart_tcp"
+VERSION = "1.0.0"
+
+sys = require("sys")
+-- 定义一个单次触发的定时器回调函数  
+local function oneShotCallback(message)  
+    log.info("One-shot timer triggered: " .. message)  
+end  
+-- 定义一个周期性触发的定时器回调函数  
+local function periodicCallback(count)  
+    log.info("Periodic timer triggered (Count: " .. count .. ")")  
+end  
+-- 定义一个周期性触发的定时器回调函数  
+local function periodicCallback1(count)  
+    log.info("Periodic timer triggered1 (Count: " .. count .. ")")  
+end  
+
+-- 初始化计数器,用于周期性定时器  
+local periodicCount = 0  
+  
+-- 启动一个单次触发的定时器,延迟3秒后触发  
+local oneShotTimerId = sys.timerStart(oneShotCallback, 3000, 0, "Hello from one-shot timer!")  
+  
+-- 启动一个周期性触发的定时器,每2秒触发一次  
+
+sys.timerStart(periodicCallback,7000,"first")
+sys.timerStart(periodicCallback,6000,"second")
+sys.timerStart(periodicCallback,5000,"third")
+
+local periodicTimerId2 = sys.timerLoopStart(function()  
+    periodicCount = periodicCount + 1  
+    periodicCallback1(periodicCount)  
+end, 2000)  
+
+    -- 停止所有定时器(仅作为测试,实际应用中应根据需要停止)  
+
+    sys.timerStart(function()
+        sys.timerStop(periodicTimerId2)
+        log.info("stop 2s loop timer periodicCallback1")
+    end,5000)
+
+    sys.timerStart(function()
+        sys.timerStopAll(periodicCallback)  
+        log.info("stop periodicCallback loop timer ")
+    end,4000)
+
+
+sys.run()-- sys.run()-此后不要在添加其他函数

+ 51 - 0
module/Air8000/demo/uart/uart/main.lua

@@ -0,0 +1,51 @@
+-- Luatools需要PROJECT和VERSION这两个信息
+PROJECT = "uart"
+VERSION = "1.0.0"
+
+log.info("main", PROJECT, VERSION)
+
+-- 引入必要的库文件(lua编写), 内部库不需要require
+sys = require("sys")
+
+if wdt then
+    --添加硬狗防止程序卡死,在支持的设备上启用这个功能
+    wdt.init(9000)--初始化watchdog设置为9s
+    sys.timerLoopStart(wdt.feed, 3000)--3s喂一次狗
+end
+
+log.info("main", "uart demo run......")
+
+local uartid = 1 -- 根据实际设备选取不同的uartid
+
+--初始化
+uart.setup(
+    uartid,--串口id
+    115200,--波特率
+    8,--数据位
+    1--停止位
+)
+
+-- 收取数据会触发回调, 这里的"receive" 是固定值
+uart.on(uartid, "receive", function(id, len)
+    local s = ""
+    repeat
+        s = uart.read(id, 128)
+        if #s > 0 then -- #s 是取字符串的长度
+            -- 关于收发hex值,请查阅 https://doc.openluat.com/article/583
+            log.info("uart", "receive", id, #s, s)
+            -- log.info("uart", "receive", id, #s, s:toHex()) --如果传输二进制/十六进制数据, 部分字符不可见, 不代表没收到
+        end
+    until s == ""
+end)
+
+sys.taskInit(function()
+    -- 循环两秒向串口发一次数据
+    while true do
+        sys.wait(2000)
+        uart.write(uartid, "test data.")
+    end
+end)
+
+-- 用户代码已结束---------------------------------------------
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 49 - 0
module/Air8000/demo/uart/uart_rs485/main.lua

@@ -0,0 +1,49 @@
+-- Luatools需要PROJECT和VERSION这两个信息
+PROJECT = "uart_RS485"
+VERSION = "1.0.0"
+
+log.info("main", PROJECT, VERSION)
+
+-- 引入必要的库文件(lua编写), 内部库不需要require
+sys = require("sys")
+
+if wdt then
+    --添加硬狗防止程序卡死,在支持的设备上启用这个功能
+    wdt.init(9000)--初始化watchdog设置为9s
+    sys.timerLoopStart(wdt.feed, 3000)--3s喂一次狗
+end
+
+log.info("main", "uart demo run......")
+
+local uartid = 1        -- 根据实际设备选取不同的uartid
+local uart485Pin = 27   -- 用于控制485接收和发送的使能引脚
+
+gpio.setup(1, 1)        --打开电源(开发板485供电脚是gpio1,用开发板测试需要开机初始化拉高gpio1)
+
+--初始化
+uart.setup(uartid, 9600, 8, 1, uart.NONE, uart.LSB, 1024, uart485Pin, 0, 2000)
+
+-- 收取数据会触发回调, 这里的"receive" 是固定值
+uart.on(uartid, "receive", function(id, len)
+    local s = ""
+    repeat
+        s = uart.read(id, 128)
+        if #s > 0 then -- #s 是取字符串的长度
+            -- 关于收发hex值,请查阅 https://doc.openluat.com/article/583
+            log.info("uart", "receive", id, #s, s)
+            -- log.info("uart", "receive", id, #s, s:toHex()) --如果传输二进制/十六进制数据, 部分字符不可见, 不代表没收到
+        end
+    until s == ""
+end)
+
+sys.taskInit(function()
+    -- 循环两秒向串口发一次数据
+    while true do
+        sys.wait(2000)
+        uart.write(uartid, "test data.")
+    end
+end)
+
+-- 用户代码已结束---------------------------------------------
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 77 - 0
module/Air8000/demo/uart/uart_two/main.lua

@@ -0,0 +1,77 @@
+-- Luatools需要PROJECT和VERSION这两个信息
+PROJECT = "uart_two"
+VERSION = "1.0.0"
+
+log.info("main", PROJECT, VERSION)
+
+-- 引入必要的库文件(lua编写), 内部库不需要require
+sys = require("sys")
+
+if wdt then
+    --添加硬狗防止程序卡死,在支持的设备上启用这个功能
+    wdt.init(9000)--初始化watchdog设置为9s
+    sys.timerLoopStart(wdt.feed, 3000)--3s喂一次狗
+end
+
+log.info("main", "uart_two demo run......")
+
+-- 根据实际设备选取不同的uartid
+local uartid1 = 1 -- 第一个串口id
+local uartid2 = 3 -- 第二个串口id
+
+-- 初始化第一个串口
+uart.setup(
+    uartid1,--串口id
+    115200,--波特率
+    8,--数据位
+    1--停止位
+)
+
+-- 初始化第一个串口
+uart.setup(
+    uartid2,--串口id
+    115200,--波特率
+    8,--数据位
+    1--停止位
+)
+
+-- 第一个串口接收数据回调函数
+-- 收取数据会触发回调, 这里的"receive" 是固定值
+uart.on(uartid1, "receive", function(id, len)
+    local s = ""
+    repeat
+        s = uart.read(id, 128)
+        if #s > 0 then -- #s 是取字符串的长度
+            -- 关于收发hex值,请查阅 https://doc.openluat.com/article/583
+            log.info("uart", "receive", id, #s, s)
+            -- log.info("uart", "receive", id, #s, s:toHex()) --如果传输二进制/十六进制数据, 部分字符不可见, 不代表没收到
+        end
+    until s == ""
+end)
+
+-- 第二个串口接收数据回调函数
+-- 收取数据会触发回调, 这里的"receive" 是固定值
+uart.on(uartid2, "receive", function(id, len)
+    local s = ""
+    repeat
+        s = uart.read(id, 128)
+        if #s > 0 then -- #s 是取字符串的长度
+            -- 关于收发hex值,请查阅 https://doc.openluat.com/article/583
+            log.info("uart", "receive", id, #s, s)
+            -- log.info("uart", "receive", id, #s, s:toHex()) --如果传输二进制/十六进制数据, 部分字符不可见, 不代表没收到
+        end
+    until s == ""
+end)
+
+sys.taskInit(function()
+    -- 循环两秒分别向两个串口发一次数据
+    while true do
+        sys.wait(2000)
+        uart.write(uartid1, "uart1 test data.")
+        uart.write(uartid2, "uart2 test data.")
+    end
+end)
+
+-- 用户代码已结束---------------------------------------------
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 61 - 0
module/Air8000/demo/uart/uart_vir/main.lua

@@ -0,0 +1,61 @@
+-- Luatools需要PROJECT和VERSION这两个信息
+PROJECT = "uart_vir"
+VERSION = "1.0.0"
+
+log.info("main", PROJECT, VERSION)
+
+-- 引入必要的库文件(lua编写), 内部库不需要require
+sys = require("sys")
+
+if wdt then
+    --添加硬狗防止程序卡死,在支持的设备上启用这个功能
+    wdt.init(9000)--初始化watchdog设置为9s
+    sys.timerLoopStart(wdt.feed, 3000)--3s喂一次狗
+end
+
+log.info("main", "uart demo run......")
+
+local uartid = uart.VUART_0 -- 使用USB虚拟串口,固定id
+
+--初始化
+uart.setup(
+    uartid,--串口id
+    115200,--波特率
+    8,--数据位
+    1--停止位
+)
+
+-- 收取数据会触发回调, 这里的"receive" 是固定值
+uart.on(uartid, "receive", function(id, len)
+    local s = ""
+    repeat
+        s = uart.read(id, 128)
+        if #s > 0 then -- #s 是取字符串的长度
+            -- 关于收发hex值,请查阅 https://doc.openluat.com/article/583
+            log.info("uart", "receive", id, #s, s)
+            -- log.info("uart", "receive", id, #s, s:toHex()) --如果传输二进制/十六进制数据, 部分字符不可见, 不代表没收到
+        end
+    until s == ""
+end)
+
+sys.taskInit(function()
+    local data =
+    {
+        host = "abcdefg.com",
+        port = "1883",
+        clientID = "c88885",
+        username = "user",
+        password = "123456",
+        ca_self = {ssl=false},
+    }
+    local jsondata = json.encode(data)
+    -- 循环每两秒向串口发一次数据
+    while true do
+        sys.wait(2000)
+        uart.write(uartid, jsondata)
+    end
+end)
+
+-- 用户代码已结束---------------------------------------------
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 123 - 0
module/Air8000/demo/udp/main.lua

@@ -0,0 +1,123 @@
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "scdemo"
+VERSION = "1.0.0"
+log.info("main", PROJECT, VERSION)
+-- 一定要添加sys.lua !!!!
+sys = require("sys")
+_G.sysplus = require("sysplus")
+local taskName = "UDP_TASK"             -- sysplus库用到的任务名称,也作为任务id
+if wdt then
+    --添加硬狗防止程序卡死,在支持的设备上启用这个功能
+    wdt.init(9000)--初始化watchdog设置为9s
+    sys.timerLoopStart(wdt.feed, 3000)--3s喂一次狗
+end
+local uart_rx_buff = zbuff.create(1024)     -- 串口接收到的数据
+----------------------------网络配置---------------------------
+local libnet = require "libnet"         -- libnet库,支持tcp、udp协议所用的同步阻塞接口
+local ip = "112.125.89.8"               -- 连接UDP服务器的ip地址
+local port = 46139                      -- 连接UDP服务器的端口
+local netCB = nil                       -- socket服务的回调函数
+local connect_state = false             -- 连接状态 true:已连接   false:未连接
+local protocol = true                  -- 通讯协议 true:UDP协议  false:TCP协议
+local ssl = false                       -- 加密传输 true:加密     false:不加密
+local tx_buff = zbuff.create(1024)     -- 发送至UDP服务器的数据
+local rx_buff = zbuff.create(1024)     -- 从UDP服务器接收到的数据
+--==============================================================
+--Uart初始化  
+local uartid = 1 -- 根据实际设备选取不同的uartid
+uart.setup(
+    uartid,--串口id
+    115200,--波特率
+    8,--数据位
+    1--停止位
+)
+function UDP_TASK()
+    -- 打印一下连接的目标ip和端口号
+    log.info("connect ip: ", ip, "port:", port)
+    sys.waitUntil("IP_READY")                -- 等待联网成功
+    netCB = socket.create(nil, taskName)     -- 创建socket对象
+    socket.debug(netCB, true)                -- 打开调试日志
+    socket.config(netCB, nil, protocol, ssl)      -- 此配置为UDP连接,无SSL加密
+    -- 串口和UDP服务器的交互逻辑
+    while true do
+        -- 连接服务器,返回是否连接成功
+        local result = libnet.connect(taskName, 15000, netCB, ip, port)
+        -----查询网络状态
+        local status = mobile.status()    
+        log.info("status", status) 
+        
+        -- 收取数据会触发回调, 这里的"receive" 是固定值不要修改。
+        log.info("connect ip: 等待连接 ",result)
+        uart.on(uartid, "receive", function(id, len)
+            while true do
+                local len = uart.rx(id, uart_rx_buff)   -- 接收串口收到的数据,并赋值到uart_rx_buff
+                if len <= 0 then    -- 接收到的字节长度为0 则退出
+                    break
+                end
+                -- 如果已经在线了,则发送socket.EVENT消息来打断任务里的阻塞等待状态,让任务循环继续
+                if connect_state then
+                    sys_send(taskName, socket.EVENT, 0)
+                end
+            end
+        end)
+        -- 如果连接成功,则改变连接状态参数,并且随便发一条数据到服务器,看服务器能不能收到
+        if result then
+            log.info("connect ip: 连接成功")
+            connect_state = true
+           libnet.tx(taskName, 0, netCB, "UDP CONNECT")
+        end
+        -- 连接上服务器后,等待处理接收服务器下行至模块的数据 和 发送串口的数据到服务器
+        while result do
+            succ, param, _, _ = socket.rx(netCB, rx_buff)   -- 接收数据
+            if not succ then
+                log.info("服务器断开了", succ, param, ip, port)
+                break
+            end
+            if rx_buff:used() > 0 then
+                log.info("收到服务器数据,长度", rx_buff:used())
+               uart.tx(uartid, rx_buff)    -- 从服务器收到的数据转发 从串口输出
+                rx_buff:del()
+            end
+            tx_buff:copy(nil, uart_rx_buff)         -- 将串口数据赋值给UDP待发送数据的buff中
+            uart_rx_buff:del()                      -- 清除串口buff的数据长度
+            if tx_buff:used() > 0 then
+                log.info("发送到服务器数据,长度", tx_buff:used())
+                local result = libnet.tx(taskName, 0, netCB, tx_buff)   -- 发送数据
+                if not result then
+                    log.info("发送失败了", result, param)
+                    break
+                end
+            end
+            tx_buff:del()
+            -- 如果zbuff对象长度超出,需要重新分配下空间
+            if uart_rx_buff:len() > 1024 then
+                uart_rx_buff:resize(1024)
+            end
+            if tx_buff:len() > 1024 then
+                tx_buff:resize(1024)
+            end
+            if rx_buff:len() > 1024 then
+                rx_buff:resize(1024)
+            end
+            log.info(rtos.meminfo("sys"))   -- 打印系统内存
+            -- 阻塞等待新的消息到来,比如服务器下发,串口接收到数据
+            result, param = libnet.wait(taskName, 15000, netCB)
+            if not result then
+                log.info("服务器断开了", result, param)
+                break
+            end
+        end
+        -- 服务器断开后的行动,由于while true的影响,所以会再次重新执行进行 重新连接。
+        connect_state = false
+        libnet.close(taskName, 5000, netCB)
+        tx_buff:clear(0)
+        rx_buff:clear(0)
+        sys.wait(1000)
+    end
+end
+-- libnet库依赖于sysplus,所以只能通过sysplus.taskInitEx创建的任务函数中运行
+sysplus.taskInitEx(UDP_TASK, taskName, netCB)
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 64 - 0
module/Air8000/demo/usb_uart/main.lua

@@ -0,0 +1,64 @@
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "usb_uart"
+VERSION = "1.0.0"
+
+
+-- 引入必要的库文件(lua编写), 内部库不需要require
+sys = require("sys")
+_G.sysplus = require("sysplus")
+
+--[[
+注意: 若使用普通串口调试功能, 需要以下条件之一才能收到数据
+1. 把DTR设置为高电平
+2. 先发送一次数据
+]]
+
+log.info("main", "usb uart demo")
+
+local uartid = uart.VUART_0 -- USB虚拟串口的固定id
+
+--初始化
+local result = uart.setup(
+    uartid,--串口id
+    115200,--波特率,其实无所谓, 纯虚拟串口
+    8,--数据位
+    1--停止位
+)
+
+
+-- 收取数据会触发回调, 这里的"receive" 是固定值
+uart.on(uartid, "receive", function(id, len)
+    local s = ""
+    repeat
+        -- s = uart.read(id, 1024)
+        s = uart.read(id, len)
+        if s and #s > 0 then -- #s 是取字符串的长度
+            -- 如果传输二进制/十六进制数据, 部分字符不可见, 不代表没收到
+            -- 关于收发hex值,请查阅 https://doc.openluat.com/article/583
+            log.info("uart", "receive", id, #s, s)
+            uart.write(uart.VUART_0, s)
+            -- log.info("uart", "receive", id, #s, s:toHex())
+        end
+    until s == ""
+end)
+local tx_buff = zbuff.create(24)
+tx_buff:set(0, 0x31)
+-- 并非所有设备都支持sent事件
+uart.on(uartid, "sent", function(id)
+    log.info("uart", "sent", id)
+end)
+
+sys.taskInit(function()
+
+    while 1 do
+        -- uart.write(uart.VUART_0, "hello test usb-uart\r\n")
+        uart.tx(uart.VUART_0, tx_buff,0, tx_buff:len())
+        sys.wait(1000)
+    end
+end)
+
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 33 - 0
module/Air8000/demo/wdt/示例一 程序正常运行/main.lua

@@ -0,0 +1,33 @@
+
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "wdtdemo"
+VERSION = "1.0.0"
+
+log.info("main", PROJECT, VERSION)
+
+-- sys库是标配
+_G.sys = require("sys")
+
+sys.taskInit(function()
+    -- 这个demo要求有wdt库
+    -- wdt库的使用,基本上每个demo的头部都有演示
+    -- 模组/芯片的内部硬狗, 能解决绝大多数情况下的死机问题
+    -- 但如果有要求非常高的场景, 依然建议外挂硬件,然后通过gpio/i2c定时喂狗
+    if wdt == nil then
+        while 1 do
+            sys.wait(1000)
+            log.info("wdt", "this demo need wdt lib")
+        end
+    end
+    -- 注意, 大部分芯片/模块是 2 倍超时时间后才会重启
+    -- 以下是常规配置, 9秒超时, 3秒喂一次狗
+    -- 若软件崩溃,死循环,硬件死机,那么 最多 18 秒后,自动复位
+    -- 注意: 软件bug导致业务失败, 并不能通过wdt解决
+    wdt.init(9000)
+    sys.timerLoopStart(wdt.feed, 3000)
+end)
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 42 - 0
module/Air8000/demo/wdt/示例二 添加死循环模拟故障场景/main.lua

@@ -0,0 +1,42 @@
+
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "wdtdemo"
+VERSION = "1.0.0"
+
+log.info("main", PROJECT, VERSION)
+
+-- sys库是标配
+_G.sys = require("sys")
+
+sys.taskInit(function()
+    -- 这个demo要求有wdt库
+    -- wdt库的使用,基本上每个demo的头部都有演示
+    -- 模组/芯片的内部硬狗, 能解决绝大多数情况下的死机问题
+    -- 但如果有要求非常高的场景, 依然建议外挂硬件,然后通过gpio/i2c定时喂狗
+    if wdt == nil then
+        while 1 do
+            sys.wait(1000)
+            log.info("wdt", "this demo need wdt lib")
+        end
+    end
+    -- 注意, 大部分芯片/模块是 2 倍超时时间后才会重启
+    -- 以下是常规配置, 9秒超时, 3秒喂一次狗
+    -- 若软件崩溃,死循环,硬件死机,那么 最多 18 秒后,自动复位
+    -- 注意: 软件bug导致业务失败, 并不能通过wdt解决
+    wdt.init(9000)
+    sys.timerLoopStart(wdt.feed, 3000)
+end)
+
+-- 创建一个新的任务来模拟故障场景
+sys.taskInit(function()
+    log.info("fault_task", "Entering infinite loop to simulate fault.")
+    while true do
+        -- 模拟故障场景,真的进入死循环
+    end
+end)
+
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 93 - 0
module/Air8000/demo/wifi_location/main.lua

@@ -0,0 +1,93 @@
+--[[
+1.本demo可直接在Air8000模组上运行
+2. 执行逻辑为:
+    (1)初始化wlan功能
+    (2)连接wifi热点
+    (3)等待网络连接成功
+    (4)执行时间同步
+    (5)等待时间同步成功
+    (6)循环扫描wifi,如果扫描到wifi信息,则请求wifi定位
+]] 
+
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "WLAN_LOCATION"
+VERSION = "1.0.0"
+
+-- sys库是标配
+_G.sys = require("sys")
+require "sysplus"
+
+local taskName = "WIFI_LOCATION"
+local result = false -- 用于保存结果
+local data = nil -- 用于保存定位请求数据
+local wifiList = {} -- 用于保存扫描到的wifi信息
+local requestParam = {} -- 用于保存定位请求参数
+
+local airlbs = require "airlbs"
+-- 此为收费服务,  下面两个参数需自行联系销售申请
+local airlbsProjectId = "XXXXXX" -- 定位所需的projectid
+local airlbsProjectKey = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" -- 定位所需的projectkey
+
+local function wlan_location_task()
+    sys.wait(200)
+    wlan.init() -- wlan功能初始化
+    -- socket.create(socket.LWIP_STA)
+    sys.wait(100)
+    wlan.connect("luatos1234", "12341234") -- 连接wifi
+    result = sys.waitUntil("IP_READY", 30000) -- 等待网络就绪成功的消息,超时时间30秒
+    if not result then
+        log.info("等待网络就绪超时, 结束本次测试")
+        return
+    end
+    socket.sntp(nil, socket.LWIP_STA) -- 同步网络时间
+    result = sys.waitUntil("NTP_UPDATE", 30000) -- 等待时间同步成功的消息,超时时间30秒
+    if not result then
+        log.info("等待时间同步成功超时, 结束本次测试")
+        return
+    end
+    while true do
+        wlan.scan()
+        result = sys.waitUntil("WLAN_SCAN_DONE", 20000) -- 等待WIFI扫描完成的消息,超时时间20秒
+        if result then
+            wifiList = wlan.scanResult()
+            if #wifiList > 0 then
+                for k, v in pairs(wifiList) do
+                    log.info("scan", v["ssid"], v["rssi"], (v["bssid"]:toHex()))
+                end
+                local requestParam = {
+                    project_id = airlbsProjectId, -- 定位所需的projectid
+                    project_key = airlbsProjectKey, -- 定位所需的projectkey
+                    wifi_info = wifiList, -- 用于定位的WiFi信息
+                    adapter = socket.LWIP_STA, -- 网络适配器类型
+                    timeout = 5000 -- 定位超时时间
+                }
+                result, data = airlbs.request(requestParam)
+                if result then
+                    log.info("airlbs请求成功", json.encode(data))
+                else
+                    log.info("airlbs请求失败")
+                end
+            else
+                log.info("没有扫描到wifi")
+            end
+        else
+            log.info("等待WIFI扫描结果超时")
+        end
+        sys.wait(20000) -- 等待20秒
+    end
+end
+
+--  每隔6秒打印一次airlink统计数据, 调试用
+sys.taskInit(function()
+    while 1 do
+        sys.wait(6000)
+        airlink.statistics()
+    end
+end)
+
+sysplus.taskInitEx(wlan_location_task, taskName)
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 144 - 0
module/Air8000/demo/wlan/AP/main.lua

@@ -0,0 +1,144 @@
+
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "air8000_wifi"
+VERSION = "1.0.5"
+
+dnsproxy = require("dnsproxy")
+dhcpsrv = require("dhcpsrv")
+httpplus = require("httpplus")
+
+-- 通过boot按键方便刷Air8000S
+function PWR8000S(val)
+    gpio.set(23, val)
+end
+
+gpio.debounce(0, 1000)
+gpio.setup(0, function()
+    sys.taskInit(function()
+        log.info("复位Air8000S")
+        PWR8000S(0)
+        sys.wait(20)
+        PWR8000S(1)
+    end)
+end, gpio.PULLDOWN)
+
+function test_ap()
+    log.info("执行AP创建操作")
+    wlan.createAP("uiot5678", "12345678")
+    netdrv.ipv4(socket.LWIP_AP, "192.168.4.1", "255.255.255.0", "0.0.0.0")
+    for i=1, 10 do
+        log.info("当前ip信息", netdrv.ipv4(socket.LWIP_AP))
+        sys.wait(100)
+    end
+    sys.wait(5000)
+    -- netdrv.ipv4(socket.LWIP_AP, "192.168.4.1", "255.255.255.0", "0.0.0.0")
+    -- log.info("创建dns代理", netdrv.ipv4(socket.LWIP_AP))
+    dnsproxy.setup(socket.LWIP_AP, socket.LWIP_GP)
+    -- log.info('创建DHCP服务器', netdrv.ipv4(socket.LWIP_AP))
+    dhcpsrv.create({adapter=socket.LWIP_AP})
+    while 1 do
+        if netdrv.ready(socket.LWIP_GP) then
+            netdrv.napt(socket.LWIP_GP)
+            break
+        end
+        sys.wait(1000)
+    end
+end
+
+-- wifi的STA相关事件
+sys.subscribe("WLAN_STA_INC", function(evt, data)
+    -- evt 可能的值有: "CONNECTED", "DISCONNECTED"
+    -- 当evt=CONNECTED, data是连接的AP的ssid, 字符串类型
+    -- 当evt=DISCONNECTED, data断开的原因, 整数类型
+    log.info("收到STA事件", evt)
+end)
+
+-- wifi的AP相关事件
+sys.subscribe("WLAN_AP_INC", function(evt, data)
+    -- evt 可能的值有: "CONNECTED", "DISCONNECTED"
+    -- 当evt=CONNECTED, data是连接的AP的新STA的MAC地址
+    -- 当evt=DISCONNECTED, data是断开与AP连接的STA的MAC地址
+    log.info("收到STA事件", evt)
+end)
+
+function test_sta()
+    log.info("执行STA连接操作")
+    wlan.connect("luatos1234", "12341234")
+    -- netdrv.dhcp(socket.LWIP_STA, true)
+    sys.wait(8000)
+    iperf.server(socket.LWIP_STA)
+    -- iperf.client(socket.LWIP_STA, "47.94.236.172")
+
+    sys.wait(5000)
+    while 1 do
+        -- log.info("MAC地址", netdrv.mac(socket.LWIP_STA))
+        -- log.info("IP地址", netdrv.ipv4(socket.LWIP_STA))
+        -- log.info("ready?", netdrv.ready(socket.LWIP_STA))
+        -- sys.wait(1000)
+        -- log.info("执行http请求")
+        -- local code = http.request("GET", "http://192.168.1.15:8000/README.md", nil, nil, {adapter=socket.LWIP_STA,timeout=3000}).wait()
+        local code, headers, body = http.request("GET", "https://httpbin.air32.cn/bytes/2048", nil, nil, {adapter=socket.LWIP_STA,timeout=5000,debug=false}).wait()
+        log.info("http执行结果", code, headers, body and #body)
+        -- socket.sntp(nil, socket.LWIP_STA)
+        sys.wait(2000)
+
+        -- socket.sntp(nil)
+        -- sys.wait(2000)
+        -- log.info("执行ping操作")
+        -- icmp.ping(socket.LWIP_STA, "183.2.172.177")
+        -- sys.wait(2000)
+    end
+end
+
+sys.subscribe("PING_RESULT", function(id, time, dst)
+    log.info("ping", id, time, dst);
+end)
+
+function test_scan()
+    while 1 do
+        log.info("执行wifi扫描")
+        wlan.scan()
+        sys.wait(30 * 1000)
+    end
+end
+sys.subscribe("WLAN_SCAN_DONE", function ()
+    local results = wlan.scanResult()
+    log.info("scan", "results", #results)
+    for k,v in pairs(results) do
+        log.info("scan", v["ssid"], v["rssi"], (v["bssid"]:toHex()))
+    end
+end)
+
+--  每隔6秒打印一次airlink统计数据, 调试用
+-- sys.taskInit(function()
+--     while 1 do
+--         sys.wait(6000)
+--         airlink.statistics()
+--     end
+-- end)
+
+sys.taskInit(function()
+    log.info("新的Air8000脚本...")
+
+    -- sys.wait(200) -- 稍微缓一下, Air8000S的启动大概需要300ms
+    -- 启动AP测试
+    -- netdrv.setup(socket.LWIP_STA, netdrv.WHALE)
+    -- netdrv.setup(socket.LWIP_AP, netdrv.WHALE)
+    -- wlan.init()
+    -- sys.wait(5000)
+    
+    -- sys.wait(300)
+    test_ap()
+
+    -- 连接STA测试
+
+
+    -- wifi扫描测试
+    -- test_scan()
+end)
+
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 144 - 0
module/Air8000/demo/wlan/STA/main.lua

@@ -0,0 +1,144 @@
+
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "air8000_wifi"
+VERSION = "1.0.5"
+
+dnsproxy = require("dnsproxy")
+dhcpsrv = require("dhcpsrv")
+httpplus = require("httpplus")
+
+-- 通过boot按键方便刷Air8000S
+function PWR8000S(val)
+    gpio.set(23, val)
+end
+
+gpio.debounce(0, 1000)
+gpio.setup(0, function()
+    sys.taskInit(function()
+        log.info("复位Air8000S")
+        PWR8000S(0)
+        sys.wait(20)
+        PWR8000S(1)
+    end)
+end, gpio.PULLDOWN)
+
+function test_ap()
+    log.info("执行AP创建操作")
+    wlan.createAP("uiot5678", "12345678")
+    netdrv.ipv4(socket.LWIP_AP, "192.168.4.1", "255.255.255.0", "0.0.0.0")
+    for i=1, 10 do
+        log.info("当前ip信息", netdrv.ipv4(socket.LWIP_AP))
+        sys.wait(100)
+    end
+    sys.wait(5000)
+    -- netdrv.ipv4(socket.LWIP_AP, "192.168.4.1", "255.255.255.0", "0.0.0.0")
+    -- log.info("创建dns代理", netdrv.ipv4(socket.LWIP_AP))
+    dnsproxy.setup(socket.LWIP_AP, socket.LWIP_GP)
+    -- log.info('创建DHCP服务器', netdrv.ipv4(socket.LWIP_AP))
+    dhcpsrv.create({adapter=socket.LWIP_AP})
+    while 1 do
+        if netdrv.ready(socket.LWIP_GP) then
+            netdrv.napt(socket.LWIP_GP)
+            break
+        end
+        sys.wait(1000)
+    end
+end
+
+-- wifi的STA相关事件
+sys.subscribe("WLAN_STA_INC", function(evt, data)
+    -- evt 可能的值有: "CONNECTED", "DISCONNECTED"
+    -- 当evt=CONNECTED, data是连接的AP的ssid, 字符串类型
+    -- 当evt=DISCONNECTED, data断开的原因, 整数类型
+    log.info("收到STA事件", evt)
+end)
+
+-- wifi的AP相关事件
+sys.subscribe("WLAN_AP_INC", function(evt, data)
+    -- evt 可能的值有: "CONNECTED", "DISCONNECTED"
+    -- 当evt=CONNECTED, data是连接的AP的新STA的MAC地址
+    -- 当evt=DISCONNECTED, data是断开与AP连接的STA的MAC地址
+    log.info("收到AP事件", evt)
+end)
+
+function test_sta()
+    log.info("执行STA连接操作")
+    wlan.connect("luatos1234", "12341234")
+    -- netdrv.dhcp(socket.LWIP_STA, true)
+    sys.wait(8000)
+    iperf.server(socket.LWIP_STA)
+    -- iperf.client(socket.LWIP_STA, "47.94.236.172")
+
+    sys.wait(5000)
+    while 1 do
+        -- log.info("MAC地址", netdrv.mac(socket.LWIP_STA))
+        -- log.info("IP地址", netdrv.ipv4(socket.LWIP_STA))
+        -- log.info("ready?", netdrv.ready(socket.LWIP_STA))
+        -- sys.wait(1000)
+        -- log.info("执行http请求")
+        -- local code = http.request("GET", "http://192.168.1.15:8000/README.md", nil, nil, {adapter=socket.LWIP_STA,timeout=3000}).wait()
+        local code, headers, body = http.request("GET", "https://httpbin.air32.cn/bytes/2048", nil, nil, {adapter=socket.LWIP_STA,timeout=5000,debug=false}).wait()
+        log.info("http执行结果", code, headers, body and #body)
+        -- socket.sntp(nil, socket.LWIP_STA)
+        sys.wait(2000)
+
+        -- socket.sntp(nil)
+        -- sys.wait(2000)
+        -- log.info("执行ping操作")
+        -- icmp.ping(socket.LWIP_STA, "183.2.172.177")
+        -- sys.wait(2000)
+    end
+end
+
+sys.subscribe("PING_RESULT", function(id, time, dst)
+    log.info("ping", id, time, dst);
+end)
+
+function test_scan()
+    while 1 do
+        log.info("执行wifi扫描")
+        wlan.scan()
+        sys.wait(30 * 1000)
+    end
+end
+sys.subscribe("WLAN_SCAN_DONE", function ()
+    local results = wlan.scanResult()
+    log.info("scan", "results", #results)
+    for k,v in pairs(results) do
+        log.info("scan", v["ssid"], v["rssi"], (v["bssid"]:toHex()))
+    end
+end)
+
+--  每隔6秒打印一次airlink统计数据, 调试用
+-- sys.taskInit(function()
+--     while 1 do
+--         sys.wait(6000)
+--         airlink.statistics()
+--     end
+-- end)
+
+sys.taskInit(function()
+    log.info("新的Air8000脚本...")
+
+    -- sys.wait(200) -- 稍微缓一下, Air8000S的启动大概需要300ms
+    -- 启动AP测试
+    -- netdrv.setup(socket.LWIP_STA, netdrv.WHALE)
+    -- netdrv.setup(socket.LWIP_AP, netdrv.WHALE)
+    -- wlan.init()
+    -- sys.wait(5000)
+    
+    -- sys.wait(300)
+    -- test_ap()
+
+    -- 连接STA测试
+    test_sta()
+
+    -- wifi扫描测试
+    test_scan()
+end)
+
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

Một số tệp đã không được hiển thị bởi vì quá nhiều tập tin thay đổi trong này khác