本次捣鼓的开发板是合宙的Air724UG,一块4G的开发板。最近合宙可能是为了推广自己的4G模块,在低价推广,再加之最近确实有这方面的需求:2G模块用在我这里,信号已经有点捉急了,还有安信可的模块里面带的那个板载天线,虽然体积小,便于放,但是信号是真的差强人意,特别是在运动中,那更是别提了,但是天线都是小问题,我觉得是没有优化得好,使用上不是很满意。

至于说到为啥要买这个导航模块,是因为前面我不是在倒腾安信可的A9G嘛,我是C_SDK二次开发的,没用官方的AT固件,并且官网提供的AT固件版本似乎比直接买来收到的要晚得多,上面也说了实际使用效果也不理想,出厂的AT固件似乎就要好一些,但是也没细究。
但是Air724UG并不像前面的A9G那样开发C_SDK,尽管合宙的AT固件开发得很完善了,但是没有C_SDK可玩度就降低了许多,也不能玩MicroPython了,但是提供了Luat = Lua + AT的玩意,在本文的后半篇会有说到,也是很不错的。本文仅为试玩开箱,并非部署教程!

air720H何时开放C_SDK

2020年6月8日更新:
合宙开放了C_SDK

QQ20200608-192115.webp

2022年2月10日更新:
我又购入了Air820的开发板,实际就是Air724_Air530。

20200517205755959_490888019.webp

上电以后是这样的样子。

20200411201618358_20554.webp

AT+CGMI

+CGMI: "AirM2M"

OK

+CSCON: 0

+CSCON: 1

+CSCON: 0

+CSCON: 1

+CSCON: 0
AT*I

Manufacturer: AirM2M
Model: Air724UG
Revision: AirM2M_Air724UG_V243_LTE_AT
HWVer: A10
Buildtime: Mar 24 2020 12:50:08
IMEI:
ICCID:
IMSI:

OK

AT固件进行TCP连接

一开始先使用传统的AT命令来测试一下吧。官方网站上面提供了完整的文档。我这里只列出了部分。这是开发板作为TCP客户端,连接到服务器端的案例。

20200517180802510_941866684.webp

20200517181038148_851395951.webp

建立简单的TCP连接就按照文档中的举例来做就行了。

修改AT+CIPSTART中的地址和端口。

20200517030020857_330605988.webp

20200517025718635_746087203.webp

QQ20200517-193134.webp

然后这是TCP的服务器端收到的消息。

20200517030051177_877045552.webp

唯一要注意的就是,在输入AT+CIPSEND时,因为要输入要发送到服务器的内容,所以这里输完了得有个结束,用快捷键CTRL-Z就可以,但是有的串口调试工具并不支持,所以可以发16进制数0x1A即等同于发送

20200517030034257_954645527.webp

AT固件进行HTTP连接

在前文的traccar搭建后,我们可以使用HTTP连接到服务器。
请求的参数如下所示:

http://demo.traccar.org:5055/?id=123456&lat={0}&lon={1}&timestamp={2}&hdop={3}&altitude={4}&speed={5}

http://地址:5055/?id=866714043072&lat=0&lon=0&timestamp=1589651263&hdop=0&altitude=0&speed=0

  • demo.traccar.org是服务器的地址,自建的服务器就更换为自己的。
  • 123456是设备编号,你可以自己设置,在traccar的管理面板上与之匹配就是。

我截取了开发文档中的一部分内容供参考。

20200517014359525_80358699.webp

20200517020020172_1393864407.webp

值得一提的是有些 PC 串口工具,例如 SSCOM,会将\r 和\n 当做控制字符处 理,所以也需要将\r\n 写成\r\n 而另外一些工具,例如 XCOM,不会将\r 和\n 当做控制字符处理,所以直接输入 \r\n

又有好久么见过写得这么详细的文档了。

上面是一些简单的AT固件操作,那是这类模块最简单的使用方法,你可以照着文档,使用AT命令很容易的实现TCP,HTTP,MQTT的连接,就像是前一篇文章捣鼓安信可A9G开发板(GSM/GPRS+GPRS/GPS)中,对GPRS+GPS模块的操作那样。

Luat

除此之外,你还可以使用被合宙叫做Luat的东西,下面是介绍:

Luat = Lua + AT, Luat推出的物联网开源架构,依托于通信模块做简易快捷的开发,将传统的AT命令用Lua语言封装成API,并提供各种功能应用的demo,大大减少用户的开发成本。

开发者可以通过调用API轻松,便捷的实现TTS、GPS、SOCKET、MQTT、OTA等功能。例如下面通过几行代码既可以实现GPS,MQTT功能。

这相较于以前使用A9G使用官方例程实现MQTT和GPS,简单得多,类似于使用MicroPython进行开发,关于更多可以看开发文档,他们甚至还提供了完整的视频教程,物联网快速接入教程(阿里云/百度云/腾讯云/OneNET/MQTT/TCP/UDP),接下来的这一小节,几乎都是从官方文档里面来的,我只是将其串了起来而已,并没有技术含量,觉得我没写完整的地方,可以直接从上面的链接看开发文档。

Luat开发工具直接从官网下载就是了。

20200517012554400_698303243.webp

20200517014535305_1968923777.webp

有这么一个工具还是相当方便的,也是提高企业文化的一部分嘛。

安装USB驱动

如果你仅仅是使用UART连接到电脑,那就只需要安装串口转换芯片,沁恒的CH340N的驱动,一颗及其精简的USB转串口芯片。因为下面的步骤,需要连接USB到电脑,所以我们得安装USB的驱动。作除此之外还可以作为普通上网卡使用。
官方提供了一份很详细的教程:史上最详细的Air7xx驱动安装教程
关闭Windows10强制驱动签名步骤可能会稍加调整一下,以前的Windows10的高级重启换到了安全中心里面,最简单的就是用下面的命令行,省事。

shutdown /r /o

紧接着就是将写好的Lua代码,写入开发板,就移步看官方文档了,写得太详细了。
4G 模块烧写教程(Air720x/Air720Sx/Air720Ux系列)

20200517022615187_1927466973.webp

20200517182601780_728208496.webp

然后下面是喜闻乐见,但是看的人并不多的晒图环节。包裹里面有一张广告纸,照例都懒得看都。

IMG_20200416_153054.webp

打开一看,居然还是手写名字上去的产品须知。挺良心。

IMG_20200416_153046.webp

IMG_20200416_153017.webp

GPS模块,自然封装看起来就简单得多了。型号是Air530.

IMG_20200416_153038.webp

IMG_20200416_152947.webp

IMG_20200416_152936.webp

背面印有说明。

IMG_20200416_154103.webp

正面。

IMG_20200416_154048.webp

一根挺不错的天线。

IMG_20200416_154027.webp

IMG_20200416_154005.webp

一张他们物联网卡的广告纸。

IMG_20200416_153958.webp

官方文档里面的内容写得已经很详细了,基本上没啥我要写的了。。。。。

摄像头拍摄照片发送到服务器

基于官方Demo中的串口功能测试,拍摄图片,并转换为base64,HTTP发送到服务器。

--- 模块功能:串口功能测试(非TASK版,串口帧有自定义的结构)
-- @author openLuat
-- @module uart.testUartTask
-- @license MIT
-- @copyright openLuat
-- @release 2018.05.24

module(...,package.seeall)

require"utils"
require"pm"
require"http"

local uartID = 1

--- base64
local function base64Test(str)
    local encodeStr = crypto.base64_encode(str, #str)
    log.info("base64 encode", encodeStr)
    -- log.info("base64 decode", crypto.base64_decode(encodeStr, #encodeStr))
    return encodeStr
end

local function cbFnc(result,prompt,head,body)
    log.info("testHttp.cbFnc",result,prompt)
    if result and head then
        for k,v in pairs(head) do
            log.info("testHttp.cbFnc",k..": "..v)
        end
    end
    if result and body then
        log.info("testHttp.cbFnc","body="..body)
    end
end


local function postMultipartFormData(url,cert,params,timeout,cbFnc,rcvFileName)
    local boundary,body,k,v,kk,vv = "--------------------------"..os.time()..rtos.tick(),{}
    
    for k,v in pairs(params) do
        if k=="texts" then
            local bodyText = ""
            for kk,vv in pairs(v) do
                bodyText = bodyText.."--"..boundary.."\r\nContent-Disposition: form-data; name=\""..kk.."\"\r\n\r\n"..vv.."\r\n"
            end
            body[#body+1] = bodyText
        elseif k=="files" then
            local contentType =
            {
                file = "image/jpeg",
                jpg = "image/jpeg",
                jpeg = "image/jpeg",
                png = "image/png",                
            }
            for kk,vv in pairs(v) do
                print(kk,vv)
                body[#body+1] = "--"..boundary.."\r\nContent-Disposition: form-data; name=\""..kk.."\"; filename=\""..kk.."\"\r\nContent-Type: "..contentType[vv:match("%.(%w+)$")].."\r\n\r\n"
                body[#body+1] = {file = vv}
                body[#body+1] = "\r\n"
            end
        end
    end    
    body[#body+1] = "--"..boundary.."--\r\n"
        
    http.request(
        "POST",
        url,
        cert,
        {
            ["Content-Type"] = "multipart/form-data; boundary="..boundary,
            ["Connection"] = "keep-alive"
        },
        body,
        timeout,
        cbFnc,
        rcvFileName
        )    
end


function sendFile()
sys.taskInit(
    function()                
        local fileHandle = io.open("/testCamera.jpg","rb")
        if not fileHandle then
            log.error("testALiYun.otaCb1 open file error")
            return
        end
        
        pm.wake("UART_SENT2MCU")
        uart.on(uartID,"sent",function() sys.publish("UART_SENT2MCU_OK") end)
        uart.setup(uartID,115200,8,uart.PAR_NONE,uart.STOP_1,nil,1)

        
        -- 使用Base64编码发送
        local c = io.readFile("/testCamera.jpg")
        local base64_str = base64Test(c)

        postMultipartFormData(
            "https://xxxx/?s=xxxx",
            {caCert="ca.crt"},
            {   
                texts = 
                {
                    ["device_id"] = "011e880001",
                    ["type_title"] = "Photo",
                    ["type_des"] = "data:image/jpg;base64,"..base64_str
                }
            },
            60000,
            cbFnc
        )

        -- 
        -- uart.write(uartID,base64_str)

        sys.waitUntil("UART_SENT2MCU_OK")
        -- 完毕
        uart.close(uartID)
        pm.sleep("UART_SENT2MCU")
        fileHandle:close()
    end
)
end

也可以交给系统来base64:

{
[1] = “string1”,
[2] = {file_base64=“/ldata/test.jpg”},
[3] = “string2”
}

具体可以看官方文档:LuatOS-Air script lib API->http