Просмотр исходного кода

Merge branch 'master' of https://gitee.com/openLuat/LuatOS

alienwalker 1 год назад
Родитель
Сommit
b237289cc2
3 измененных файлов с 712 добавлено и 101 удалено
  1. 283 0
      script/libs/max31856.lua
  2. 122 101
      script/turnkey/hz201p/main.lua
  3. 307 0
      script/turnkey/hz201p/test.lua

+ 283 - 0
script/libs/max31856.lua

@@ -0,0 +1,283 @@
+--[[
+@module max31856
+@summary max31856 热电偶温度检测 
+@version 1.0
+@date    2024.06.17
+@author  Dozingfiretruck
+@usage
+--注意:因使用了sys.wait()所有api需要在协程中使用
+--注意:ads1115的配置需按照项目需求配置,您需要按照配置寄存器说明重新配置 ADS1115_CONF_HCMD 和 ADS1115_CONF_LCMD !!!
+-- 用法实例
+max31856 = require("max31856")
+
+sys.taskInit(function()
+    max31856_spi_device = spi.deviceSetup(1,pin.PB11,1,1,8,5*1000*1000,spi.MSB,1,0)
+    max31856.init(max31856_spi_device)
+    while 1 do
+        local cj_temp = max31856.read_cj_temp()
+        if cj_temp then
+            log.info("max31856 cj_temp: ", cj_temp)
+        end
+        local tc_temp = max31856.read_tc_temp()
+        if tc_temp then
+            log.info("max31856 tc_temp: ", tc_temp)
+        end
+        log.info("max31856 fault: ", max31856.read_fault())
+        sys.wait(1000)
+    end
+end)
+]]
+
+--[[
+    Register Memory Map
+    ADDRESS READ/WRITE NAME     FACTORY FUNCTION
+                                DEFAULT
+    00h/80h Read/Write CR0      00h     Configuration 0 Register
+    01h/81h Read/Write CR1      03h     Configuration 1 Register
+    02h/82h Read/Write MASK     FFh     Fault Mask Register
+    03h/83h Read/Write CJHF     7Fh     Cold-Junction High Fault Threshold
+    04h/84h Read/Write CJLF     C0h     Cold-Junction Low Fault Threshold
+    05h/85h Read/Write LTHFTH   7Fh     Linearized Temperature High Fault Threshold MSB
+    06h/86h Read/Write LTHFTL   FFh     Linearized Temperature High Fault Threshold LSB
+    07h/87h Read/Write LTLFTH   80h     Linearized Temperature Low Fault Threshold MSB
+    08h/88h Read/Write LTLFTL   00h     Linearized Temperature Low Fault Threshold LSB
+    09h/89h Read/Write CJTO     00h     Cold-Junction Temperature Offset Register
+    0Ah/8Ah Read/Write CJTH     00h     Cold-Junction Temperature Register, MSB
+    0Bh/8Bh Read/Write CJTL     00h     Cold-Junction Temperature Register, LSB
+    0Ch     Read Only  LTCBH    00h     Linearized TC Temperature, Byte 2
+    0Dh     Read Only  LTCBM    00h     Linearized TC Temperature, Byte 1
+    0Eh     Read Only  LTCBL    00h     Linearized TC Temperature, Byte 0
+    0Fh     Read Only  SR       00h     Fault Status Register
+]]
+
+local max31856 = {}
+
+local sys = require "sys"
+
+max31856.TCTYPE_B                   =   0x00    -- 类型B
+max31856.TCTYPE_E                   =   0x01    -- 类型E
+max31856.TCTYPE_J                   =   0x02    -- 类型J
+max31856.TCTYPE_K                   =   0x03    -- 类型K
+max31856.TCTYPE_N                   =   0x04    -- 类型N
+max31856.TCTYPE_R                   =   0x05    -- 类型R
+max31856.TCTYPE_S                   =   0x06    -- 类型S
+max31856.TCTYPE_T                   =   0x07    -- 类型T
+
+max31856.ONESHOT                    =   0x00    -- 单次转换模式
+max31856.CONTINUOUS                 =   0x01    -- 自动转换模式
+
+max31856.SAMPLE1                    =   0x00    -- 1个样品
+max31856.SAMPLE2                    =   0x01    -- 2个样品
+max31856.SAMPLE4                    =   0x02    -- 4个样品
+max31856.SAMPLE8                    =   0x03    -- 8个样品
+max31856.SAMPLE16                   =   0x04    -- 16个样品
+
+local MAX31856_CR0_REG   	        =   0x00    -- 配置寄存器0
+local MAX31856_CR1_REG       	    =   0x01    -- 配置寄存器1
+local MAX31856_MASK_REG      	    =   0x02    -- 故障屏蔽寄存器
+local MAX31856_CJHF_REG      	    =   0x03    -- 冷端上限故障
+local MAX31856_CJLF_REG      	    =   0x04    -- 冷接下限故障
+local MAX31856_LTHFTH_REG      	    =   0x05    -- 线性化温度上限故障 MSB
+local MAX31856_LTHFTL_REG      	    =   0x06    -- 线性化温度上限故障 LSB
+local MAX31856_LTLFTH_REG      	    =   0x07    -- 线性化温度下限故障 MSB
+local MAX31856_LTLFTL_REG      	    =   0x08    -- 线性化温度下限故障 LSB
+local MAX31856_CJTO_REG      	    =   0x09    -- 冷端温度偏移寄存器
+local MAX31856_CJTH_REG      	    =   0x0A    -- 冷端温度寄存器 MSB
+local MAX31856_CJTL_REG      	    =   0x0B    -- 冷端温度寄存器 LSB
+local MAX31856_LTCBH_REG      	    =   0x0C    -- 线性化TC温度,字节2
+local MAX31856_LTCBM_REG      	    =   0x0D    -- 线性化TC温度,字节1
+local MAX31856_LTCBL_REG      	    =   0x0E    -- 线性化TC温度,字节0
+local MAX31856_SR_REG      	        =   0x0F    -- 故障状态寄存器
+
+local max31856_spi_device
+local max31856_conversion_mode
+local max31856_sample_mode
+
+local function max31856_write_cmd(reg, data)
+    -- log.info("max31856_write_cmd "..(reg|0x80).." "..data)
+    max31856_spi_device:send({reg|0x80, data})
+end
+
+local function max31856_read_cmd(reg)
+    local data = max31856_spi_device:transfer(string.char(reg))
+    -- log.info("max31856_read_cmd "..reg.." "..data:byte())
+    return data:byte()
+end
+
+local function trigger_oneshot()
+    local cr0 = max31856_read_cmd(MAX31856_CR0_REG)
+    cr0 = cr0&(~0x80)
+    cr0 = cr0|0x40
+    max31856_write_cmd(MAX31856_CR0_REG, cr0)
+end
+
+local function oneshot_conversion_complete()
+    return (max31856_read_cmd(MAX31856_CR0_REG) & 0x40) == 0
+end
+
+--[[
+设置热电偶类型
+@api max31856.set_tc_type(type)
+@number type max31856.TCTYPE_B max31856.TCTYPE_E max31856.TCTYPE_J max31856.TCTYPE_K max31856.TCTYPE_N max31856.TCTYPE_R max31856.TCTYPE_S max31856.TCTYPE_T
+@usage
+max31856.set_tc_type(max31856.TCTYPE_K) -- 设置类型为K
+]]
+function max31856.set_tc_type(type)
+    local cr1 = max31856_read_cmd(MAX31856_CR1_REG)
+    cr1 = cr1&0xF0
+    max31856_write_cmd(MAX31856_CR1_REG, cr1|type)
+end
+
+--[[
+设置热电偶电压转换平均模式 
+@api max31856.set_avgsel(sample_count)
+@number sample_count max31856.SAMPLE1 max31856.SAMPLE2 max31856.SAMPLE4 max31856.SAMPLE8 max31856.SAMPLE16
+@usage
+max31856.set_avgsel(max31856.SAMPLE1) -- 设置平均模式为1个样品
+]]
+function max31856.set_avgsel(sample_count)
+    max31856_sample_mode = sample_count
+    local cr1 = max31856_read_cmd(MAX31856_CR1_REG)
+    max31856_write_cmd(MAX31856_CR1_REG, cr1|(sample_count<<4))
+end
+
+--[[
+设置转化模式
+@api max31856.set_cmode(type)
+@number type max31856.ONESHOT max31856.CONTINUOUS
+@usage
+max31856.set_cmode(max31856.ONESHOT) -- 设置转化模式为单次转换
+]]
+function max31856.set_cmode(type)
+    max31856_conversion_mode = type
+    local cr0 = max31856_read_cmd(MAX31856_CR0_REG)
+    if type == max31856.ONESHOT then
+        cr0 = cr0&(~0x80)
+        cr0 = cr0|0x40
+    else
+        cr0 = cr0|0x80
+        cr0 = cr0&(~0x40)
+    end
+    max31856_write_cmd(MAX31856_CR0_REG, cr0)
+end
+
+--[[
+读取错误码
+@api max31856.read_fault()
+@return number 错误码
+@usage
+local fault = max31856.read_fault()
+]]
+function max31856.read_fault()
+    return max31856_read_cmd(MAX31856_SR_REG)
+end
+
+--[[
+读取冷端温度
+@api max31856.read_cj_temp()
+@return number 冷端温度
+@usage
+local cj_temp = max31856.read_cj_temp()
+]]
+function max31856.read_cj_temp()
+    if max31856_conversion_mode == max31856.ONESHOT then
+        trigger_oneshot()
+        sys.wait(145+(max31856_sample_mode-1)*33)
+        local wait = 20
+        while oneshot_conversion_complete() == false do
+            sys.wait(10)
+            wait = wait - 1
+            if wait == 0 then return end
+        end
+    end
+    local CJTH = max31856_read_cmd(MAX31856_CJTH_REG)
+    local CJTL = max31856_read_cmd(MAX31856_CJTL_REG)
+    return ((CJTH<<8)|CJTL) / 256.0
+end
+
+--[[
+读取tc温度
+@api max31856.read_tc_temp()
+@return number tc温度
+@usage
+local tc_temp = max31856.read_tc_temp()
+]]
+function max31856.read_tc_temp()
+    if max31856_conversion_mode == max31856.ONESHOT then
+        trigger_oneshot()
+        sys.wait(145+(max31856_sample_mode-1)*33)
+        local wait = 20
+        while oneshot_conversion_complete() == false do
+            sys.wait(10)
+            wait = wait - 1
+            if wait == 0 then return end
+        end
+    end
+    local LTCBH = max31856_read_cmd(MAX31856_LTCBH_REG)
+    local LTCBM = max31856_read_cmd(MAX31856_LTCBM_REG)
+    local LTCBL = max31856_read_cmd(MAX31856_LTCBL_REG)
+    local temp24 = (LTCBH<<16)|(LTCBM<<8)|LTCBL
+    if temp24 & 0x800000 ~= 0 then
+        temp24 = temp24 | 0xFF000000
+    end
+    temp24 = temp24 >> 5
+    return temp24 * 0.0078125
+end
+
+--[[
+max31856 初始化
+@api max31856.init(spi_device)
+@userdata spi_device spi设备句柄
+@return boolean 初始化成功返回true
+@usage
+max31856.init(spi_device)
+]]
+function max31856.init(spi_device)
+    if type(spi_device) ~= "userdata" then
+        return
+    end
+    max31856_spi_device = spi_device
+
+    max31856_write_cmd(MAX31856_MASK_REG, 0x00) -- 断言所有错误
+    max31856_write_cmd(MAX31856_CR0_REG, 0x10) -- 开启开路故障检测
+    max31856_write_cmd(MAX31856_CJTO_REG, 0x00) -- 冷端温度偏移设置为零
+
+    max31856.set_tc_type(max31856.TCTYPE_K) -- 设置类型为K
+
+    max31856.set_cmode(max31856.ONESHOT) -- 设置转化模式为单次转换
+    max31856.set_avgsel(max31856.SAMPLE1) -- 设置平均模式为1个样品
+    return true
+end
+
+return max31856
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+ 122 - 101
script/turnkey/hz201p/main.lua

@@ -5,118 +5,139 @@ log.info("main", PROJECT, VERSION)
 -- 引入必要的库文件(lua编写), 内部库不需要require
 sys = require "sys"
 sysplus = require("sysplus")
-
---mcu.hardfault(0)
-
---运营商给的dns经常抽风,手动指定
-socket.setDNS(nil, 1, "223.5.5.5")
-socket.setDNS(nil, 2, "119.29.29.29")
-
 pm.ioVol(pm.IOVOL_ALL_GPIO, 1800)
--- gnss的备电和gsensor的供电
-local vbackup = gpio.setup(24, 1)
--- gnss的供电
-local gpsPower = gpio.setup(26, 1)
-
--- 使用合宙iot平台时需要这个参数
-PRODUCT_KEY = "YXdzIDo5QawWCIRywShMAKjmJsInXtsb" -- 到 iot.openluat.com 创建项目,获取正确的项目id
-libfota = require "libfota"
-function fota_cb(ret)
-    log.info("fota", ret)
-    if ret == 0 then
-        rtos.reboot()
+-- mcu.hardfault(0)
+
+local function fskvInit()
+    fskv.init()
+    local init = fskv.get("isInit")
+    if init then
+        return
     end
+    fskv.set("allDone", false)
+    fskv.set("pcbaDone", false)
+    fskv.set("isInit", true)
 end
--- 使用合宙iot平台进行升级
-sys.subscribe("IP_READY",function()
-    libfota.request(fota_cb)
-    sys.timerLoopStart(libfota.request, 3600000, fota_cb)
-end)
-
---云平台逻辑
-require "cloud"
-
---获取所有参数
-attributes = require "attributes"
-attributes.initial()--初始化
-
---gnss
-require "gnss"
-
--- Gsensor
-require "da267"
-sys.subscribe("STEP_COUNTER", function(step)
-    log.info("STEP_COUNTER", step)
-    if step > 0 then
-        attributes.set("step", step)
-    end
-end)
-
--- LED
---全局状态变量
-_G_CONNECTED = false
-local blueLed = gpio.setup(1, 0)
-local redLed = gpio.setup(16, 0, nil, nil, 4)
-sys.taskInit(function()
-    while true do
-        if attributes.get("ledControl") then
-            blueLed(attributes.get("blueLed") and 1 or 0)
-            redLed(attributes.get("redLed") and 1 or 0)
-            sys.wait(500)
-        else
-            redLed(attributes.get("isCharging") and 1 or 0)
-            blueLed(1)
-            sys.wait(_G_CONNECTED and 100 or 1000)
-            blueLed(0)
-            sys.wait(_G_CONNECTED and 100 or 1000)
+
+fskvInit()
+
+local allDone = fskv.get("allDone")
+
+if allDone then
+
+    -- 运营商给的dns经常抽风,手动指定
+    socket.setDNS(nil, 1, "223.5.5.5")
+    socket.setDNS(nil, 2, "119.29.29.29")
+
+
+    -- gnss的备电和gsensor的供电
+    local vbackup = gpio.setup(24, 1)
+    -- gnss的供电
+    local gpsPower = gpio.setup(26, 1)
+
+    -- 使用合宙iot平台时需要这个参数
+    PRODUCT_KEY = "YXdzIDo5QawWCIRywShMAKjmJsInXtsb" -- 到 iot.openluat.com 创建项目,获取正确的项目id
+    libfota = require "libfota"
+    function fota_cb(ret)
+        log.info("fota", ret)
+        if ret == 0 then
+            rtos.reboot()
         end
     end
-end)
-
---关机键
-local powerTimer
-local powerKey = gpio.setup(46, function()
-    log.info("powerKey", gpio.get(46))
-    if gpio.get(46) == 0 then
-        sys.publish("POWERKEY_PRESSED")
-        powerTimer = sys.timerStart(function()
-            log.info("powerKey", "long press")
-            --把灯关都掉,让用户以为已经关机了
-            blueLed(0) redLed(0)
-            blueLed = function() end
-            redLed = blueLed
-            --两秒后真正关机
-            sys.timerStart(pm.shutdown, 2000)
-        end, 3000)
-    else
-        if powerTimer then
-            sys.timerStop(powerTimer)
-            log.info("powerKey", "stop press")
+    -- 使用合宙iot平台进行升级
+    sys.subscribe("IP_READY", function()
+        libfota.request(fota_cb)
+        sys.timerLoopStart(libfota.request, 3600000, fota_cb)
+    end)
+
+    -- 云平台逻辑
+    require "cloud"
+
+    -- 获取所有参数
+    attributes = require "attributes"
+    attributes.initial() -- 初始化
+
+    -- gnss
+    require "gnss"
+
+    -- Gsensor
+    require "da267"
+    sys.subscribe("STEP_COUNTER", function(step)
+        log.info("STEP_COUNTER", step)
+        if step > 0 then
+            attributes.set("step", step)
         end
-    end
-end,gpio.PULLUP)
-
---电量检测与上报
-require "battery"
+    end)
+
+    -- LED
+    -- 全局状态变量
+    _G_CONNECTED = false
+    local blueLed = gpio.setup(1, 0)
+    local redLed = gpio.setup(16, 0, nil, nil, 4)
+    sys.taskInit(function()
+        while true do
+            if attributes.get("ledControl") then
+                blueLed(attributes.get("blueLed") and 1 or 0)
+                redLed(attributes.get("redLed") and 1 or 0)
+                sys.wait(500)
+            else
+                redLed(attributes.get("isCharging") and 1 or 0)
+                blueLed(1)
+                sys.wait(_G_CONNECTED and 100 or 1000)
+                blueLed(0)
+                sys.wait(_G_CONNECTED and 100 or 1000)
+            end
+        end
+    end)
+
+    -- 关机键
+    local powerTimer
+    local powerKey = gpio.setup(46, function()
+        log.info("powerKey", gpio.get(46))
+        if gpio.get(46) == 0 then
+            sys.publish("POWERKEY_PRESSED")
+            powerTimer = sys.timerStart(function()
+                log.info("powerKey", "long press")
+                -- 把灯关都掉,让用户以为已经关机了
+                blueLed(0)
+                redLed(0)
+                blueLed = function()
+                end
+                redLed = blueLed
+                -- 两秒后真正关机
+                sys.timerStart(pm.shutdown, 2000)
+            end, 3000)
+        else
+            if powerTimer then
+                sys.timerStop(powerTimer)
+                log.info("powerKey", "stop press")
+            end
+        end
+    end, gpio.PULLUP)
 
---信号值检测与上报
-sys.taskInit(function ()
-    while true do
-        attributes.set("rsrp", mobile.rsrp())
-        attributes.set("rsrq", mobile.rsrq())
-        sys.wait(60000)
-    end
-end)
+    -- 电量检测与上报
+    require "battery"
 
+    -- 信号值检测与上报
+    sys.taskInit(function()
+        while true do
+            attributes.set("rsrp", mobile.rsrp())
+            attributes.set("rsrq", mobile.rsrq())
+            sys.wait(60000)
+        end
+    end)
 
---拨打电话与音频
-require "ccVolte"
+    -- 拨打电话与音频
+    require "ccVolte"
 
--- SIM DETECT
-local simCheck = gpio.setup(41, function()
-    log.info("sim status", gpio.get(41))
-end)
+    -- SIM DETECT
+    local simCheck = gpio.setup(41, function()
+        log.info("sim status", gpio.get(41))
+    end)
 
+else
+    require "test"
+end
 -- 用户代码已结束---------------------------------------------
 -- 结尾总是这一句
 sys.run()

+ 307 - 0
script/turnkey/hz201p/test.lua

@@ -0,0 +1,307 @@
+local cacheTable = {}
+local rxCache = ""
+
+local vbackup = gpio.setup(24, 1)
+local gnssReset = gpio.setup(27, 1)
+local gnssPower = gpio.setup(26, 1)
+
+local blueLed = gpio.setup(1, 0)
+local redLed = gpio.setup(16, 0, nil, nil, 4)
+
+pm.request(pm.IDLE)
+
+
+local transUartId = 1
+if not fskv.get("pabaDone") then
+    transUartId = 1
+else
+    transUartId = uart.VUART_0
+end
+local gnssUartId = 2
+local gnssIsDownload = false
+local gnssIsTrans = false
+local gnssTransFlag = false
+uart.setup(transUartId, 115200)
+
+local Gsensori2cId = 1
+local da267Addr = 0x26
+local intPin = 39
+
+local ES8311i2cId = 0
+
+local function NMEA2UART1(id, len)
+    local result
+    while 1 do
+        local data = uart.read(gnssUartId, len)
+        if not data or #data == 0 then
+            break
+        end
+        if gnssTransFlag then
+            table.insert(cacheTable, data)
+            sys.publish("UART1_SEND")
+        end
+    end
+end
+
+-- amr数据存放buffer,尽可能地给大一些
+local amr_buff = zbuff.create(20 * 1024)
+-- 创建一个amr的encoder
+local encoder = nil
+
+audio.on(0, function(id, event, buff)
+    log.info("audio.on", id, event)
+    -- 使用play来播放文件时只有播放完成回调
+    if event == audio.RECORD_DATA then -- 录音数据
+        codec.encode(encoder, buff, amr_buff)
+    elseif event == audio.RECORD_DONE then -- 录音完成
+        sys.publish("AUDIO_RECORD_DONE")
+    else
+        local succ, stop, file_cnt = audio.getError(0)
+        if not succ then
+            if stop then
+                log.info("用户停止播放")
+            else
+                log.info("第", file_cnt, "个文件解码失败")
+            end
+        end
+        log.info("播放完成一个音频")
+        sys.publish("AUDIO_PLAY_DONE")
+    end
+end)
+
+local recordPath = "/record.amr"
+sys.taskInit(function()
+    mcu.altfun(mcu.I2C, Gsensori2cId, 23, 2, 0)
+    mcu.altfun(mcu.I2C, Gsensori2cId, 24, 2, 0)
+    mcu.altfun(mcu.I2C, ES8311i2cId, 13, 2, 0)
+    mcu.altfun(mcu.I2C, ES8311i2cId, 14, 2, 0)
+    local multimedia_id = 0
+    local i2s_id = 0
+    local i2s_mode = 0
+    local i2s_sample_rate = 16000
+    local i2s_bits_per_sample = 16
+    local i2s_channel_format = i2s.MONO_R
+    local i2s_communication_format = i2s.MODE_LSB
+    local i2s_channel_bits = 16
+    local pa_pin = 23
+    local pa_on_level = 1
+    local pa_delay = 100
+    local power_pin = 255
+    local power_on_level = 1
+    local power_delay = 3
+    local power_time_delay = 100
+    local voice_vol = 100
+    local mic_vol = 80
+    local find_es8311 = false
+    i2c.setup(Gsensori2cId, i2c.SLOW)
+    i2c.setup(ES8311i2cId, i2c.FAST)
+    if i2c.send(ES8311i2cId, 0x18, 0xfd) == true then
+        find_es8311 = true
+    end
+    log.info("find_es8311?", find_es8311)
+    i2s.setup(i2s_id, i2s_mode, i2s_sample_rate, i2s_bits_per_sample, i2s_channel_format, i2s_communication_format, i2s_channel_bits)
+    audio.config(multimedia_id, pa_pin, pa_on_level, power_delay, pa_delay, power_pin, power_on_level, power_time_delay)
+    audio.setBus(multimedia_id, audio.BUS_I2S, {
+        chip = "es8311",
+        i2cid = ES8311i2cId,
+        i2sid = i2s_id,
+        voltage = audio.VOLTAGE_1800
+    }) -- 通道0的硬件输出通道设置为I2S
+    audio.vol(multimedia_id, 80)
+    audio.micVol(multimedia_id, 80)
+    while true do
+        local result, param1, param2, param3 = sys.waitUntil("CONTROL")
+        log.info("CONTROL", param1, param2, param3)
+        if param1 == "GNSS" then
+            gnssReset(0)
+            sys.wait(10)
+            gnssReset(1)
+        elseif param1 == "GSENSOR" then
+            i2c.send(Gsensori2cId, da267Addr, 0x01, 1)
+            local data = i2c.recv(Gsensori2cId, da267Addr, 1)
+            if not data or data == "" or string.byte(data) ~= 0x13 then
+                table.insert(cacheTable, "ERROR#")
+            else
+                table.insert(cacheTable, "OK#")
+            end
+            sys.publish("UART1_SEND")
+        elseif param1 == "RECORD" then
+            local err = audio.record(0, audio.AMR, 5, 7, recordPath)
+            result = sys.waitUntil("AUDIO_RECORD_DONE", 10000)
+            if result then
+                table.insert(cacheTable, "OK#")
+            else
+                table.insert(cacheTable, "ERROR#")
+            end
+            sys.publish("UART1_SEND")
+        elseif param1 == "PLAY" then
+            local err = audio.play(0, recordPath)
+            result = sys.waitUntil("AUDIO_PLAY_DONE", 10000)
+            if result then
+                table.insert(cacheTable, "OK#")
+            else
+                table.insert(cacheTable, "ERROR#")
+            end
+            sys.publish("UART1_SEND")
+        end
+    end
+end)
+
+local function powerKeyCb()
+    if gpio.get(46) == 1 then
+        table.insert(cacheTable, "POWERKEY_RELEASE#")
+    else
+        table.insert(cacheTable, "POWERKEY_PRESS#")
+    end
+    sys.publish("UART1_SEND")
+end
+
+local function proc(data)
+    local item = nil
+    local find = true
+    local needNowReply = true
+    local h = string.find(data, "#")
+    if h then
+        local cmd = string.sub(data, 1, h - 1)
+        if string.find(cmd, "VERSION") then
+            item = PROJECT .. "_" .. VERSION
+        elseif string.find(cmd, "LED") then
+            local onoff = string.match(cmd, "LED,(%d)")
+            item = "OK"
+            if onoff == "0" then
+                blueLed(0)
+                redLed(0)
+            elseif onoff == "1" then
+                blueLed(1)
+                redLed(1)
+            else
+                item = "ERROR"
+            end
+        elseif string.find(cmd, "IMEI") then
+            item = mobile.imei()
+        elseif string.find(cmd, "IMSI") then
+            item = mobile.imsi()
+        elseif string.find(cmd, "ICCID") then
+            item = mobile.iccid()
+        elseif string.find(cmd, "CSQ") then
+            item = mobile.csq()
+        elseif string.find(cmd, "MUID") then
+            item = mobile.muid()
+        elseif string.find(cmd, "GPSTEST") then
+            local onoff = string.match(cmd, "GPSTEST,(%d)")
+            log.info("flag", onoff)
+            item = "OK"
+            if onoff == "0" then
+                gnssTransFlag = false
+                uart.close(gnssUartId)
+            elseif onoff == "1" then
+                gnssTransFlag = true
+                uart.on(gnssUartId, "receive", NMEA2UART1)
+                uart.setup(gnssUartId, 115200)
+            else
+                item = "ERROR"
+            end
+        elseif string.find(cmd, "GPSDOWNLOAD") then
+            local onoff = string.match(cmd, "GPSDOWNLOAD,(%d)")
+            item = "OK"
+            if onoff == "0" then
+                gpio.close(12)
+                gpio.close(13)
+            elseif onoff == "1" then
+                gpio.setup(12)
+                gpio.setup(13)
+                sys.publish("CONTROL", "GNSS")
+            else
+                item = "ERROR"
+            end
+        elseif string.find(cmd, "GS_STATE") then
+            sys.publish("CONTROL", "GSENSOR")
+            needNowReply = false
+        elseif string.find(cmd, "RECORD") then
+            sys.publish("CONTROL", "RECORD")
+            needNowReply = false
+        elseif string.find(cmd, "PLAY") then
+            sys.publish("CONTROL", "PLAY")
+            needNowReply = false
+        elseif string.find(cmd, "POWERKEY") then
+            local onoff = string.match(cmd, "POWERKEY,(%d)")
+            item = "OK"
+            if onoff == "0" then
+                gpio.close(46)
+            elseif onoff == "1" then
+                gpio.setup(46, powerKeyCb, gpio.PULLUP, gpio.BOTH)
+            else
+                item = "ERROR"
+            end
+        elseif string.find(cmd, "ECNPICFG") then
+            item = "OK"
+            mobile.nstOnOff(true, 1)
+            mobile.nstInput("AT+ECNPICFG?\r\n")
+            mobile.nstInput(nil)
+            mobile.nstOnOff(false, 1)
+            needNowReply = false
+        elseif string.find(cmd, "PCBA_TEST_DONE") then
+            item = "OK"
+            fskv.set("pabaDone", true)
+        elseif string.find(cmd, "TEST_DONE") then
+            item = "OK"
+            fskv.set("allDone", true)
+        else
+            find = false
+            item = "ERROR"
+        end
+        if find then
+            if not item then
+                item = " "
+            end
+        end
+        if needNowReply then
+            item = item .. "#"
+            table.insert(cacheTable, item)
+            sys.publish("UART1_SEND")
+        end
+        return true, data:sub(h + 1)
+    else
+        return false, data
+    end
+end
+gpio.debounce(46, 100)
+uart.on(transUartId, "receive", function(id, len)
+    local result
+    while 1 do
+        local data = uart.read(transUartId, 512)
+        if not data or #data == 0 then
+            break
+        end
+        rxCache = rxCache .. data
+        while true do
+            result, rxCache = proc(rxCache)
+            if not result then
+                break
+            end
+        end
+    end
+end)
+uart.on(transUartId, "sent", function()
+    sys.publish("SEND_DOWN")
+end)
+
+
+sys.taskInit(function()
+    while true do
+        while #cacheTable > 0 do
+            uart.write(transUartId, table.remove(cacheTable, 1))
+            sys.waitUntil("SEND_DOWN")
+        end
+        sys.waitUntil("UART1_SEND", 1000)
+    end
+end)
+
+sys.taskInit(function()
+    sys.wait(1000)
+    while true do
+        mobile.reqCellInfo(15)
+        sys.waitUntil("CELL_INFO_UPDATE", 15000)
+        sys.wait(1000)
+    end
+end)