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

Merge branch 'master' into log_nomem

Wendal Chen 3 лет назад
Родитель
Сommit
61c34c275c
41 измененных файлов с 1647 добавлено и 107 удалено
  1. 1 1
      components/crypto/luat_crypto_mbedtls.c
  2. 6 3
      components/fskv/luat_lib_fskv.c
  3. 1 1
      components/max30102/luat_lib_max30102.c
  4. 3 2
      components/mbedtls/library/debug.c
  5. 27 0
      components/multimedia/luat_lib_multimedia_audio.c
  6. 4 0
      components/multimedia/luat_multimedia.h
  7. 2 2
      components/network/adapter/luat_lib_socket.c
  8. 1 1
      components/network/libftp/luat_ftp_client.c
  9. 3 1
      components/network/libhttp/luat_lib_http.c
  10. 4 4
      components/network/libsntp/luat_sntp.c
  11. 13 2
      components/network/lwip/port/net_lwip.c
  12. 1 1
      components/rtos/freertos/luat_common_freertos.c
  13. 7 1
      components/serialization/protobuf/luat_lib_protobuf.c
  14. 2 0
      components/u8g2/luat_lib_u8g2.c
  15. 52 0
      demo/aliyun/main.lua
  16. 4 0
      demo/multimedia/main.lua
  17. 16 0
      demo/pm/Air101/main.lua
  18. 1 1
      demo/record/EC618/es8218e.lua
  19. 37 6
      demo/record/EC618/es8311.lua
  20. 98 0
      demo/socket/Air105/async_socket_demo.lua
  21. 3 0
      demo/uart/main.lua
  22. 1 1
      demo/uart_soft/main.lua
  23. 29 0
      demo/uart_传感器/ZE08G-CH2O/main.lua
  24. 30 0
      demo/uart_传感器/ZH07/main.lua
  25. 2 2
      demo/wlan/Air780E/main.lua
  26. 20 0
      lua/src/lobject.c
  27. 7 0
      luat/include/luat_audio.h
  28. 2 0
      luat/include/luat_libs.h
  29. 2 0
      luat/include/luat_pm.h
  30. 3 2
      luat/modules/luat_lib_adc.c
  31. 478 0
      luat/modules/luat_lib_bit64.c
  32. 27 0
      luat/modules/luat_lib_pm.c
  33. 14 31
      luat/modules/luat_lib_sensor.c
  34. 2 2
      luat/modules/luat_lib_uart.c
  35. 5 0
      luat/modules/luat_main.c
  36. 462 0
      script/libs/aLiyun.lua
  37. 1 1
      script/libs/libfota.lua
  38. 102 0
      script/libs/ze08g_ch2o.lua
  39. 119 0
      script/libs/zh07.lua
  40. 41 31
      script/turnkey/web_audio/audio_play.lua
  41. 14 11
      script/turnkey/web_audio/main.lua

+ 1 - 1
components/crypto/luat_crypto_mbedtls.c

@@ -297,7 +297,7 @@ int luat_crypto_cipher_list(const char** list, size_t* len) {
 }
 
 int luat_crypto_cipher_suites(const char** list, size_t* len) {
-#ifdef MBEDTLS_SSL_TLS_C
+#if defined(MBEDTLS_SSL_TLS_C) && defined(LUAT_USE_NETWORK)
     size_t count = 0;
     size_t limit = *len;
     const int *suites = mbedtls_ssl_list_ciphersuites();

+ 6 - 3
components/fskv/luat_lib_fskv.c

@@ -241,7 +241,7 @@ static int l_fskv_get(lua_State *L) {
         buff = tmp;
     }
 
-    lua_Integer *intVal;
+    lua_Integer intVal;
     // lua_Number *numVal;
     // LLOGD("KV value T=%02X", buff.b[0]);
     switch(buff[0]) {
@@ -257,8 +257,11 @@ static int l_fskv_get(lua_State *L) {
         // _, val = pack.unpack(data, ">f")
         break;
     case LUA_TINTEGER:
-        intVal = (lua_Integer*)(&buff[1]);
-        lua_pushinteger(L, *intVal);
+    	//不能直接赋值,右边指针地址和左边的位宽不一致
+    	memcpy(&intVal, &buff[1], sizeof(lua_Integer));
+//        intVal = (lua_Integer*)(&buff[1]);
+//        lua_pushinteger(L, *intVal);
+        lua_pushinteger(L, intVal);
         break;
     case LUA_TSTRING:
         lua_pushlstring(L, (const char*)(buff + 1), size - 1);

+ 1 - 1
components/max30102/luat_lib_max30102.c

@@ -1,7 +1,7 @@
 
 /*
 @module  max30102
-@summary 红外测温(MAX30102)
+@summary 心率模块(MAX30102)
 @version 1.0
 @date    2023.2.28
 @tag LUAT_USE_MAX30102

+ 3 - 2
components/mbedtls/library/debug.c

@@ -102,6 +102,7 @@ void mbedtls_debug_print_ret( const mbedtls_ssl_context *ssl, int level,
     if( NULL == ssl              ||
         NULL == ssl->conf        ||
         NULL == ssl->conf->f_dbg ||
+	    MBEDTLS_ERR_SSL_WANT_READ ==  ret ||
         level > debug_threshold )
     {
         return;
@@ -112,8 +113,8 @@ void mbedtls_debug_print_ret( const mbedtls_ssl_context *ssl, int level,
      * the logs would be quickly flooded with WANT_READ, so ignore that.
      * Don't ignore WANT_WRITE however, since is is usually rare.
      */
-    if( ret == MBEDTLS_ERR_SSL_WANT_READ )
-        return;
+
+
 #ifdef LUAT_LOG_NO_NEWLINE
     mbedtls_snprintf( str, DEBUG_BUF_SIZE, "%s() returned %d (-0x%04x)",
               text, ret, (unsigned int) -ret );

+ 27 - 0
components/multimedia/luat_lib_multimedia_audio.c

@@ -321,6 +321,23 @@ static int l_audio_vol(lua_State *L) {
     return 1;
 }
 
+/*
+配置一个音频通道的硬件输出总线,只有对应soc软硬件平台支持才设置对应类型
+@api audio.vol(id, bus_type)
+@int 音频通道
+@int 总线类型
+@return
+@usage
+audio.setBus(0, audio.BUS_SOFT_DAC)	--通道0的硬件输出通道设置为软件DAC
+audio.setBus(0, audio.BUS_I2S)	--通道0的硬件输出通道设置为I2S
+*/
+static int l_audio_set_output_bus(lua_State *L) {
+	luat_audio_set_bus_type(luaL_checkinteger(L, 2));
+    return 0;
+}
+
+
+
 
 #include "rotable2.h"
 static const rotable_Reg_t reg_audio[] =
@@ -339,9 +356,19 @@ static const rotable_Reg_t reg_audio[] =
 	{ "config",			ROREG_FUNC(l_audio_config)},
 	{ "vol",			ROREG_FUNC(l_audio_vol)},
 	{ "getError",			ROREG_FUNC(l_audio_play_get_last_error)},
+	{ "setBus",			ROREG_FUNC(l_audio_set_output_bus)},
+	//@const PCM number PCM格式,即原始ADC数据
     { "PCM",           ROREG_INT(MULTIMEDIA_DATA_TYPE_PCM)},
+	//@const MORE_DATA number audio.on回调函数传入参数的值,表示底层播放完一段数据,可以传入更多数据
 	{ "MORE_DATA",     ROREG_INT(MULTIMEDIA_CB_AUDIO_NEED_DATA)},
+	//@const DONE number audio.on回调函数传入参数的值,表示底层播放完全部数据了
 	{ "DONE",          ROREG_INT(MULTIMEDIA_CB_AUDIO_DONE)},
+	//@const BUS_DAC number 硬件输出总线,DAC类型
+	{ "BUS_DAC", 		ROREG_INT(MULTIMEDIA_AUDIO_BUS_DAC)},
+	//@const BUS_I2S number 硬件输出总线,I2S类型
+	{ "BUS_I2S", 		ROREG_INT(MULTIMEDIA_AUDIO_BUS_I2S)},
+	//@const BUS_SOFT_DAC number 硬件输出总线,软件模式DAC类型
+	{ "BUS_SOFT_DAC", 		ROREG_INT(MULTIMEDIA_AUDIO_BUS_SOFT_DAC)},
 	{ NULL,            ROREG_INT(0)}
 };
 

+ 4 - 0
components/multimedia/luat_multimedia.h

@@ -26,6 +26,10 @@ enum
 	MULTIMEDIA_CB_DECODE_DONE,			//音频解码完成
 	MULTIMEDIA_CB_TTS_INIT,				//TTS做完了必要的初始化,用户可以通过audio_play_tts_set_param做个性化配置
 	MULTIMEDIA_CB_TTS_DONE,				//TTS编码完成了。注意不是播放完成
+
+	MULTIMEDIA_AUDIO_BUS_DAC=0,
+	MULTIMEDIA_AUDIO_BUS_I2S,
+	MULTIMEDIA_AUDIO_BUS_SOFT_DAC
 };
 int l_multimedia_raw_handler(lua_State *L, void* ptr);
 

+ 2 - 2
components/network/adapter/luat_lib_socket.c

@@ -755,8 +755,8 @@ static int l_socket_set_dns(lua_State *L)
 /*
 设置SSL的log
 @api    socket.sslLog(log_level)
-@int	mbedtls log等级,<=2基本不打印,不要超过9
-@usage socket.sslLog(3)
+@int	mbedtls log等级,0不打印,1只打印错误和警告,2大部分info,3及3以上详细的debug信息,过多的信息可能会造成内存碎片化
+@usage socket.sslLog(2)
 */
 static int l_socket_set_ssl_log(lua_State *L)
 {

+ 1 - 1
components/network/libftp/luat_ftp_client.c

@@ -807,7 +807,7 @@ static int l_ftp_login(lua_State *L) {
 		goto error;
 	}
 
-	luat_rtos_task_create(&g_s_ftp.task_handle, 2048, 40, "ftp", ftp_task, NULL, 64);
+	luat_rtos_task_create(&g_s_ftp.task_handle, 2048, 40, "ftp", ftp_task, NULL, 16);
 	network_init_ctrl(g_s_ftp.network->cmd_netc,g_s_ftp.task_handle, ftp_task_cb, NULL);
 	network_set_base_mode(g_s_ftp.network->cmd_netc, 1, 30000, 0, 0, 0, 0);
 	network_set_local_port(g_s_ftp.network->cmd_netc, 0);

+ 3 - 1
components/network/libhttp/luat_lib_http.c

@@ -188,7 +188,9 @@ static int l_http_request(lua_State *L) {
 			if (!strcmp("Host", name) || !strcmp("host", name)) {
 				http_ctrl->custom_host = 1;
 			}
-			http_add_header(http_ctrl,name,value);
+			if (strcmp("Content-Length", name)) {
+				http_add_header(http_ctrl,name,value);
+			}
 			lua_pop(L, 1);
 		}
 	}

+ 4 - 4
components/network/libsntp/luat_sntp.c

@@ -245,12 +245,12 @@ int l_sntp_get(lua_State *L){
         if (count > SNTP_SERVER_COUNT){
             count = SNTP_SERVER_COUNT;
         }
-		for (size_t i = 0; i <= count; i++){
-			lua_geti(L, 1, i+1);
+		for (size_t i = 1; i <= count; i++){
+			lua_geti(L, 1, i);
 			const char * server_addr = luaL_checklstring(L, -1, &len);
             if (len < SNTP_SERVER_LEN_MAX){
-                memcpy(sntp_server[i], server_addr, len);
-                sntp_server[i][len] = 0x00;
+                memcpy(sntp_server[i-1], server_addr, len);
+                sntp_server[i-1][len] = 0x00;
             }else{
                 LLOGE("server_addr too lang");
             }

+ 13 - 2
components/network/lwip/port/net_lwip.c

@@ -1627,7 +1627,18 @@ static int net_lwip_socket_receive(int socket_id, uint64_t tag,  uint8_t *buf, u
 		}
 		else
 		{
-			prvlwip.socket[socket_id].rx_wait_size -= net_lwip_socket_read_data(socket_id, buf + read_len, &read_len, len, p);
+			if (p)
+			{
+				if (remote_ip)
+				{
+					*remote_ip = p->ip;
+				}
+				if (remote_port)
+				{
+					*remote_port = p->port;
+				}
+				prvlwip.socket[socket_id].rx_wait_size -= net_lwip_socket_read_data(socket_id, buf + read_len, &read_len, len, p);
+			}
 		}
 		if (llist_empty(&prvlwip.socket[socket_id].rx_head))
 		{
@@ -2124,7 +2135,7 @@ static int net_lwip_dns(const char *domain_name, uint32_t len, void *param, void
 	return 0;
 }
 
-static int net_lwip_dns(const char *domain_name, uint32_t len, void *param, void *user_data)
+static int net_lwip_dns_ipv6(const char *domain_name, uint32_t len, void *param, void *user_data)
 {
 	if ((uint32_t)user_data >= NW_ADAPTER_INDEX_LWIP_NETIF_QTY) return -1;
 	char *prv_domain_name = (char *)zalloc(len + 1);

+ 1 - 1
components/rtos/freertos/luat_common_freertos.c

@@ -61,7 +61,7 @@ void *create_event_task(TaskFun_t task_fun, void *param, uint32_t stack_bytes, u
 	{
 		handle->queue = NULL;
 	}
-	if (pdPASS != xTaskCreate(task_fun, task_name, stack_bytes * 4, param, priority, &handle->handle))
+	if (pdPASS != xTaskCreate(task_fun, task_name, stack_bytes, param, priority, &handle->handle))
 	{
 		if (handle->queue)
 			vQueueDelete(handle->queue);

+ 7 - 1
components/serialization/protobuf/luat_lib_protobuf.c

@@ -390,10 +390,16 @@ static void lpb_pushinteger(lua_State *L, int64_t n, int mode) {
         if (neg) *--p = '-';
         *--p = '#';
         lua_pushstring(L, p);
-    } else if (LUA_VERSION_NUM >= 503 && (n >> 32) == 0) // 原版是判断lua_Integer是否8字节
+#ifdef LUAT_CONF_VM_64bit
+    }
+    else 
+        lua_pushinteger(L, (lua_Integer)n);
+#else
+    } else if (LUA_VERSION_NUM >= 503 && (n >> 32) == 0)
         lua_pushinteger(L, (lua_Integer)n);
     else
         lua_pushnumber(L, (lua_Number)n);
+#endif
 }
 
 typedef union lpb_Value {

+ 2 - 0
components/u8g2/luat_lib_u8g2.c

@@ -949,10 +949,12 @@ static const luat_u8g2_dev_reg_t devregs[] = {
     // ssd1306是默认值
     {.name="ssd1306", .w=128, .h=64, .spi_i2c=0, .devcb=u8g2_Setup_ssd1306_i2c_128x64_noname_f},       // ssd1306 128x64,I2C
     {.name="ssd1306", .w=128, .h=64, .spi_i2c=1, .devcb=u8g2_Setup_ssd1306_128x64_noname_f},           // ssd1306 128x64,SPI
+    {.name="ssd1309", .w=128, .h=64, .spi_i2c=1, .devcb=u8g2_Setup_ssd1309_128x64_noname2_f},           // ssd1309 128x64,SPI
     {.name="ssd1322", .w=256, .h=64, .spi_i2c=0, .devcb=u8g2_Setup_ssd1322_nhd_256x64_f},              // ssd1322 128x64
     {.name="sh1106",  .w=128, .h=64, .spi_i2c=0, .devcb=u8g2_Setup_sh1106_i2c_128x64_noname_f},        // sh1106 128x64,I2C
     {.name="sh1106",  .w=128, .h=64, .spi_i2c=1, .devcb=u8g2_Setup_sh1106_128x64_noname_f},        // sh1106 128x64,SPI
     {.name="sh1107",  .w=64, .h=128, .spi_i2c=0, .devcb=u8g2_Setup_ssd1306_i2c_128x64_noname_f},       // sh1107 64x128
+    {.name="sh1108",  .w=160, .h=160, .spi_i2c=0, .devcb=u8g2_Setup_sh1108_i2c_160x160_f},          // sh1108 160x160
     {.name="st7567",  .w=128, .h=64, .spi_i2c=1, .devcb=u8g2_Setup_st7567_jlx12864_f},                 // st7567 128x64
     {.name="uc1701",  .w=128, .h=64, .spi_i2c=1, .devcb=u8g2_Setup_uc1701_mini12864_f},                // uc1701
     {.name="ssd1306_128x32", .w=128, .h=32, .spi_i2c=0, .devcb=u8g2_Setup_ssd1306_i2c_128x32_univision_f},       // ssd1306 128x32,I2C

+ 52 - 0
demo/aliyun/main.lua

@@ -0,0 +1,52 @@
+PROJECT = "aliyundemo"
+VERSION = "1.0.0"
+local sys = require "sys"
+require "aliyun"
+
+--根据自己的服务器修改以下参数
+local mqtt_host = "你的实例id.mqtt.iothub.aliyuncs.com" --你公共实例的地址
+local mqtt_port = 1883 --端口
+local mqtt_isssl = true -- 是否为ssl加密连接,默认不加密,true为无证书最简单的加密,table为有证书的加密
+local ProductKey = "你的key" --产品证书
+local ProductSecret = "你的产品密钥"   --产品密钥
+local DeviceName = "你的设备id"   --设备id
+local Registration = false  --如果预注册了的话就不需要改   false   true
+local InstanceId = "iot-你的实例id"  --如果没有注册需要填写实例id,在阿里云的实例详情页面
+local DeviceSecret = "你的设备秘钥"  --一机一密需要的设备密钥
+
+---数据接收的处理函数
+-- @string topic,UTF8编码的消息主题
+-- @number qos,消息质量等级
+-- @string payload,原始编码的消息负载
+local function rcvCbFnc(topic,qos,payload)
+    log.info("aliyun.rcvCbFnc",topic,qos,payload)
+end
+
+--- 连接结果的处理函数
+-- @bool result,连接结果,true表示连接成功,false或者nil表示连接失败
+local function connectCbFnc(result)
+    log.info("aliyun.connectCbFnc",result)
+    if result then
+        --订阅主题,不需要考虑订阅结果,如果订阅失败,aliyun库中会自动重连
+        --根据自己的项目需要订阅主题,下面注释掉的一行代码中的主题是非法的,所以不能打开,一旦打开,会导致订阅失败
+        --aliyun.subscribe({["/"..PRODUCT_KEY.."/"..getDeviceName().."/get"]=0, ["/"..PRODUCT_KEY.."/"..getDeviceName().."/get"]=1})
+        aliyun.subscriber("/ht6f7kmyFFQ/861551056421746/user/ceshi",1)
+        --注册数据接收的处理函数
+        aliyun.on("receive",rcvCbFnc)
+        aliyun.publish("/"..ProductKey.."/"..DeviceName.."/user/get",0,"LUATOS_CESHI")
+    end
+end
+
+aliyun.on("connect",connectCbFnc)
+
+--一型一密
+-- aliyun.operation(Registration,DeviceName,ProductKey,ProductSecret,InstanceId,mqtt_host,mqtt_port,mqtt_isssl)
+
+--一机一密
+aliyun.confiDentialTask(DeviceName,ProductKey,DeviceSecret,mqtt_host,mqtt_port,mqtt_isssl)
+
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 4 - 0
demo/multimedia/main.lua

@@ -33,6 +33,10 @@ function audio_setup()
         --Air780E开发板配套+音频扩展板. ES8211
         --由于音频扩展板的PA是长供电的,有塔塔声音是正常的,做产品的话有额外的参考设计
         i2s.setup(0, 0, 0, 0, 0, i2s.MODE_MSB)
+        --如果用软件DAC,打开下面的注释
+        -- if audio.setBus then
+        --     audio.setBus(0, audio.BUS_SOFT_DAC)
+        -- end
         audio.config(0, 25, 1, 6, 200)
         gpio.setup(24, 0)
         gpio.setup(23, 0)

+ 16 - 0
demo/pm/Air101/main.lua

@@ -69,6 +69,22 @@ sys.taskInit(function()
     log.info("rtc", json.encode(rtc.get()))
     sys.wait(3000)
 
+    -- 测试一下RTC唤醒
+    local t = rtc.get()
+    if t.sec < 30 then
+        log.info("rtc", "轻唤醒测试", "5秒后唤醒")
+        t.sec = t.sec + 5
+        rtc.timerStart(0, t)
+        pm.request(pm.LIGHT)
+        log.info("rtc", "轻唤醒测试", "唤醒成功")
+
+        -- RTC深度休眠+唤醒
+        -- t.sec = t.sec + 5
+        -- rtc.timerStart(0, t)
+        -- log.info("rtc", "深唤醒测试", "5秒后唤醒")
+        -- pm.request(pm.DEEP)
+    end
+
     -- 接着演示 DEEP模式休眠, RAM掉电, IO失效, 唤醒相当于复位重启
     -- 因为已经唤醒过,dtimer已经失效, 重新设置一个
     log.info("rtc", json.encode(rtc.get()))

+ 1 - 1
demo/record/EC618/es8218e.lua

@@ -49,7 +49,7 @@ end
 
 
 
-function record_task()
+local function record_task()
     sys.wait(5000)
     uart.setup(1, 115200)                                       -- 开启串口1
     log.info("i2c initial",i2c.setup(0, i2c.FAST))              -- 开启i2c

+ 37 - 6
demo/record/EC618/es8311.lua

@@ -1,3 +1,18 @@
+audio.on(0, function(id, event)
+    --使用play来播放文件时只有播放完成回调
+    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)
+
+
 -- es8311器件地址
 local es8311_address = 0x18
 
@@ -47,6 +62,10 @@ local amr_buff = zbuff.create(10240)
 --创建一个amr的encoder
 local encoder = codec.create(codec.AMR, false)
 
+
+-- 录音文件路径
+local recordPath = "/record.amr"
+
 -- i2s数据接收回调
 local function record_cb(id, buff)
     if buff then
@@ -57,9 +76,10 @@ end
 
 
 
-function record_task()
+local function record_task()
+	audio.config(0, 25, 1, 6, 200)						
     sys.wait(5000)
-    uart.setup(1, 115200)								-- 开启串口1
+	pm.power(pm.DAC_EN, true)							-- 打开es8311芯片供电
     log.info("i2c initial",i2c.setup(0, i2c.FAST))		-- 开启i2c
     i2s.setup(0, 0, 8000, 16, 1, i2s.MODE_I2S)			-- 开启i2s
     i2s.on(0, record_cb) 								-- 注册i2s接收回调
@@ -73,9 +93,20 @@ function record_task()
     i2s.stop(0)											-- 停止接收
 
     log.info("录音5秒结束")
-    uart.write(1, "#!AMR\n")							-- 向串口发送amr文件标识数据
-    sys.wait(5)											-- 等待5ms确保发送成功
-    uart.write(1, amr_buff:query())						-- 向串口发送编码后的amr数据
+	io.writeFile(recordPath, "#!AMR\n")					-- 向文件写入amr文件标识数据
+	io.writeFile(recordPath, amr_buff:query(), "a+b")	-- 向文件写入编码后的amr数据
+
+	i2s.setup(0, 0, 0, 0, 0, i2s.MODE_MSB)
+   
+	local result = audio.play(0, {recordPath})			-- 请求音频播放
+	if result then
+		sys.waitUntil("AUDIO_PLAY_DONE")				-- 等待音频播放完毕
+	else
+														-- 音频播放出错	
+	end
+	
+	uart.setup(1, 115200)								-- 开启串口1
+    uart.write(1, io.readFile(recordPath))				-- 向串口发送录音文件
 end
-pm.power(pm.DAC_EN, true)								-- 打开es8311芯片供电
+
 sys.taskInit(record_task)

+ 98 - 0
demo/socket/Air105/async_socket_demo.lua

@@ -0,0 +1,98 @@
+-- netlab.luatos.com上打开TCP,然后修改IP和端口号,自动回复netlab下发的数据,自收自发测试
+
+local server_ip = "152.70.80.204"
+local server_port = 55619
+local UDP_port = 37834
+local ssl_port = 35528
+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
+        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.CLOSE then
+        sys.publish("socket_disconnect")
+    end
+end
+
+local function socketTask()
+	local netc = socket.create(nil, netCB)
+	socket.debug(netc, true)
+	socket.config(netc, nil, nil, nil, 300, 5, 6)   --开启TCP保活,防止长时间无数据交互被运营商断线
+    while true do
+        local succ, result = socket.connect(netc, server_ip, server_port)
+        if not succ then
+            log.info("未知错误,5秒后重连")
+        else
+            local result, msg = sys.waitUntil("socket_disconnect")
+        end
+        log.info("服务器断开了,5秒后重连")
+        socket.close(netc)
+        log.info(rtos.meminfo("sys"))
+        sys.wait(5000)
+    end
+end
+
+local function UDPTask()
+    local netc = socket.create(nil, netCB)
+    socket.debug(netc, true)
+    socket.config(netc, nil, true, nil, 300, 5, 6)   --开启TCP保活,防止长时间无数据交互被运营商断线
+    while true do
+        local succ, result = socket.connect(netc, server_ip, UDP_port)
+        if not succ then
+            log.info("未知错误,5秒后重连")
+        else
+            local result, msg = sys.waitUntil("socket_disconnect")
+        end
+        log.info("服务器断开了,5秒后重连")
+        socket.close(netc)
+        log.info(rtos.meminfo("sys"))
+        sys.wait(5000)
+    end
+end
+
+
+local function SSLTask()
+    local netc = socket.create(nil, netCB)
+    socket.debug(netc, true)
+    socket.config(netc, nil, nil, true, 300, 5, 6)   --开启TCP保活,防止长时间无数据交互被运营商断线
+    while true do
+        local succ, result = socket.connect(netc, server_ip, ssl_port)
+        if not succ then
+            log.info("未知错误,5秒后重连")
+        else
+            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
+
+function UDPDemo()
+    sys.taskInit(UDPTask)
+end
+
+function SSLDemo()
+    sys.taskInit(SSLTask)
+end

+ 3 - 0
demo/uart/main.lua

@@ -41,6 +41,9 @@ uart.on(uartid, "receive", function(id, len)
             log.info("uart", "receive", id, #s, s)
             -- log.info("uart", "receive", id, #s, s:toHex())
         end
+        if #s == len then
+            break
+        end
     until s == ""
 end)
 

+ 1 - 1
demo/uart_soft/main.lua

@@ -28,7 +28,7 @@ local function resouce()
     elseif rtos_bsp == "ESP32S3" then
         return nil,nil,nil,nil,nil,nil,nil
     elseif rtos_bsp == "EC618" then
-        return 17,0,1,2,19200,0,-50
+        return 17,0,1,2,19200,0,-10
     else
         log.info("main", "bsp not support")
         return

+ 29 - 0
demo/uart_传感器/ZE08G-CH2O/main.lua

@@ -0,0 +1,29 @@
+-- UART1支持600 1200 2400 4800 9600波特率下休眠仍然接收数据,并且不丢失数据
+-- 其他波特率时,在休眠后通过UART1的RX唤醒,注意唤醒开始所有连续数据会丢失,所以要发2次,第一次发送字节后,会有提示,然后再发送数据
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "ZE08G-CH2O"
+VERSION = "1.0.0"
+
+log.info("main", PROJECT, VERSION)
+
+-- 引入必要的库文件(lua编写), 内部库不需要require
+sys = require("sys")
+
+local uartid = 1 -- 根据实际设备选取不同的uartid
+local ch2o = require "ze08g_ch2o"
+
+sys.taskInit(function ()
+    local result = ch2o.init(uartid)
+    if not result then return end
+
+    while true do
+        sys.wait(1000)
+        log.info("气体浓度值 PPB:", ch2o.getPPB())
+        log.info("百万分比浓度 PPM:", ch2o.getPPM())
+    end
+end)
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 30 - 0
demo/uart_传感器/ZH07/main.lua

@@ -0,0 +1,30 @@
+-- UART1支持600 1200 2400 4800 9600波特率下休眠仍然接收数据,并且不丢失数据
+-- 其他波特率时,在休眠后通过UART1的RX唤醒,注意唤醒开始所有连续数据会丢失,所以要发2次,第一次发送字节后,会有提示,然后再发送数据
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "ZH07"
+VERSION = "1.0.0"
+
+log.info("main", PROJECT, VERSION)
+
+-- 引入必要的库文件(lua编写), 内部库不需要require
+sys = require("sys")
+local zh07 = require "zh07"
+
+local uartid = 1 -- 根据实际设备选取不同的uartid
+
+sys.taskInit(function ()
+    local result = zh07.init(uartid)
+    if not result then return end
+
+    while true do
+        sys.wait(1000)
+        log.info(string.format("pm1.0  %sμg/m³", zh07.getPM_1()))
+        log.info(string.format("pm2.5  %sμg/m³", zh07.getPM_2_5()))
+        log.info(string.format("pm10   %sμg/m³", zh07.getPM_10()))
+    end
+end)
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 2 - 2
demo/wlan/Air780E/main.lua

@@ -16,7 +16,7 @@ Air780E/Air600E/Air780EG等基于EC618的模块
 -- 引入必要的库文件(lua编写), 内部库不需要require
 sys = require("sys")
 require("sysplus")
-
+if mobile then mobile.rtime(1) end
 -- wifi扫描成功后, 会有WLAN_SCAN_DONE消息, 读取即可
 sys.subscribe("WLAN_SCAN_DONE", function ()
     local results = wlan.scanResult()
@@ -27,7 +27,7 @@ sys.subscribe("WLAN_SCAN_DONE", function ()
 end)
 
 sys.taskInit(function()
-    sys.wait(1000)
+    sys.wait(5000)
     wlan.init()
     while 1 do
         wlan.scan()

+ 20 - 0
lua/src/lobject.c

@@ -404,6 +404,7 @@ const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) {
   volatile uint32_t ap_value;
   uint32_t d1,d2;
   double f64;
+  unsigned long long u64;
 #endif
   for (;;) {
     const char *e = strchr(fmt, '%');
@@ -429,7 +430,26 @@ const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) {
         goto top2str;
       }
       case 'I': {  /* a 'lua_Integer' */
+#if (defined __PRINT_ALIGNED_32BIT__) && (defined LUAT_CONF_VM_64bit)
+        // 针对EC618的va_arg取double出错的临时解决方案
+        // 直接调用 va_arg(argp, double) 会返回0
+        // 可能与某个gcc参数有关
+
+		ap_addr = (uint32_t *)&argp;
+		ap_value = (*ap_addr);
+		if (!(ap_value & 0x07))
+		{
+			d1 = va_arg(argp, uint32_t);
+		}
+		d1 = va_arg(argp, uint32_t);
+		d2 = va_arg(argp, uint32_t);
+        char* tmp = (char*)&u64;
+        memcpy(tmp, &d1, 4);
+        memcpy(tmp + 4, &d2, 4);
+        setivalue(L->top, (l_uacInt)u64);
+#else
         setivalue(L->top, cast(lua_Integer, va_arg(argp, l_uacInt)));
+#endif
         goto top2str;
       }
       case 'f': {  /* a 'lua_Number' */

+ 7 - 0
luat/include/luat_audio.h

@@ -129,4 +129,11 @@ int luat_audio_play_tts_set_param(uint32_t multimedia_id, uint32_t param_id, uin
 void luat_audio_config_pa(uint8_t multimedia_id, uint32_t pin, int level, uint32_t dummy_time_len, uint32_t pa_delay_time);
 void luat_audio_config_dac(uint8_t multimedia_id, int pin, int level, uint32_t dac_off_delay_time);
 uint16_t luat_audio_vol(uint8_t multimedia_id, uint16_t vol);
+
+/**
+ * @brief 设置音频硬件输出类型
+ *
+ * @param bus_type 见MULTIMEDIA_AUDIO_BUS,目前只有0=DAC 1=I2S 2=SOFT_DAC
+ */
+void luat_audio_set_bus_type(uint8_t bus_type);
 #endif

+ 2 - 0
luat/include/luat_libs.h

@@ -145,4 +145,6 @@ LUAMOD_API int luaopen_errdump( lua_State *L );
 LUAMOD_API int luaopen_profiler( lua_State *L );
 LUAMOD_API int luaopen_fskv( lua_State *L );
 LUAMOD_API int luaopen_max30102( lua_State *L );
+
+LUAMOD_API int luaopen_bit64( lua_State *L );
 #endif

+ 2 - 0
luat/include/luat_pm.h

@@ -58,4 +58,6 @@ int luat_pm_get_poweron_reason(void);
 
 int luat_pm_iovolt_ctrl(int id, int val);
 
+int luat_pm_wakeup_pin(int pin, int val);
+
 #endif

+ 3 - 2
luat/modules/luat_lib_adc.c

@@ -53,11 +53,12 @@ static int l_adc_set_range(lua_State *L) {
 读取adc通道
 @api adc.read(id)
 @int 通道id,与具体设备有关,通常从0开始
-@return int 原始值
-@return int 从原始值换算得出的电压值,通常单位是mV
+@return int 原始值,一般没用,可以直接抛弃
+@return int 从原始值换算得出的实际值,通常单位是mV
 @usage
 -- 打开adc通道2,并读取
 if adc.open(2) then
+    -- 这里使用的是adc.read会返回2个值, 推荐走adc.get函数,直接取实际值
     log.info("adc", adc.read(2))
 end
 adc.close(2)

+ 478 - 0
luat/modules/luat_lib_bit64.c

@@ -0,0 +1,478 @@
+/*
+@module  bit64
+@summary 32位系统上对64位数据的基本算术运算和逻辑运算
+@version 0.1
+@date    2023.03.11
+@tag LUAT_USE_BIT64
+@demo  bit64
+@note 64位数据用9字节string存储,byte7~byte0存数据,byte8=0表示整形,其他表示浮点
+*/
+#include "luat_base.h"
+#include "luat_malloc.h"
+#define LUAT_LOG_TAG "bit64"
+#include "luat_log.h"
+#define D64_FLAG 0x01
+#ifdef LUAT_USE_BIT64
+/**
+64bit数据转成32bit输出
+@api bit64.to32(data64bit)
+@string 9字节数据
+@return any 根据64bit数据输出int或者number
+ */
+static int l_bit64_to32(lua_State *L)
+{
+	double d64;
+	int64_t i64;
+    size_t len;
+    const char *data = luaL_checklstring(L, 1, &len);
+
+    if (len != 9)
+    {
+    	lua_pushnil(L);
+    }
+    if (data[8])
+    {
+        memcpy(&d64, data, 8);
+        lua_pushnumber(L, (lua_Number)d64);
+    }
+    else
+    {
+    	memcpy(&i64, data, 8);
+    	lua_pushinteger(L, (lua_Integer)i64);
+    }
+    return 1;
+}
+
+/**
+32bit数据转成64bit数据
+@api bit64.to64(data32bit)
+@int/number 32bit数据
+@return string 9字节数据
+ */
+static int l_bit64_to64(lua_State *L)
+{
+	double d64;
+	uint64_t u64;
+	uint8_t data[9] = {0};
+	if (lua_isinteger(L, 1))
+	{
+		u64 = (lua_Unsigned)lua_tointeger(L, 1);
+		memcpy(data, &u64, 8);
+	}
+	else if (lua_isnumber(L, 1))
+	{
+		d64 = lua_tonumber(L, 1);
+		data[8] = D64_FLAG;
+		memcpy(data, &d64, 8);
+
+	}
+	lua_pushlstring(L, data, 9);
+	return 1;
+}
+
+/**
+64bit数据格式化打印成字符串,用于显示值
+@api bit64.show(a,type,flag)
+@string 需要打印的64bit数据
+@int 进制,10=10进制,16=16进制,默认10,只支持10或者16
+@boolean 整形是否按照无符号方式打印,true是,false不是,默认false,浮点忽略
+@return string 可以打印的值
+ */
+static int l_bit64_show(lua_State *L)
+{
+	int64_t i64;
+	double d64;
+    size_t len;
+    uint8_t data[64] = {0};
+    uint8_t flag = 0;
+    const char *string = luaL_checklstring(L, 1, &len);
+    if (len != 9)
+    {
+    	lua_pushnil(L);
+    	return 1;
+    }
+    if (string[8])
+    {
+    	memcpy(&d64, string, 8);
+    }
+    else
+    {
+    	memcpy(&i64, string, 8);
+    }
+    uint8_t type = luaL_optinteger(L, 2, 10);
+	if (lua_isboolean(L, 3))
+	{
+		flag = lua_toboolean(L, 3);
+	}
+	if (type != 16)
+	{
+		if (string[8])
+		{
+			len = snprintf_(data, 63, "%f", d64);
+		}
+		else
+		{
+			if (flag)
+			{
+				len = snprintf_(data, 63, "%llu", i64);
+			}
+			else
+			{
+				len = snprintf_(data, 63, "%lld", (uint64_t)i64);
+			}
+		}
+	}
+	else
+	{
+		if (string[8])
+		{
+			len = snprintf_(data, 63, "0x%llx", d64);
+		}
+		else
+		{
+			len = snprintf_(data, 63, "0x%llx", i64);
+		}
+	}
+	lua_pushlstring(L, data, len);
+	return 1;
+}
+
+static int l_bit64_calculate(lua_State *L, uint8_t op)
+{
+	double d64_a,d64_b;
+	int64_t i64_a, i64_b;
+	uint64_t u64;
+    size_t len;
+    uint8_t data[9] = {0};
+    uint8_t flag1 = 0;
+    uint8_t flag2 = 0;
+    uint8_t fa,fb;
+    const char *string = luaL_checklstring(L, 1, &len);
+    if (len != 9)
+    {
+    	goto DONE;
+    }
+    fa = string[8];
+    if (fa)
+    {
+    	memcpy(&d64_a, string, 8);
+    }
+    else
+    {
+    	memcpy(&i64_a, string, 8);
+    }
+	if (lua_isinteger(L, 2))
+	{
+		i64_b = lua_tointeger(L, 2);
+		fb = 0;
+	}
+	else if (lua_isnumber(L, 2))
+	{
+		d64_b = lua_tonumber(L, 2);
+		fb = 1;
+	}
+	else
+	{
+		string = luaL_checklstring(L, 2, &len);
+	    if (len != 9)
+	    {
+	    	goto DONE;
+	    }
+	    fb = string[8];
+	    if (fb)
+	    {
+	    	memcpy(&d64_b, string, 8);
+	    }
+	    else
+	    {
+	    	memcpy(&i64_b, string, 8);
+	    }
+	}
+
+	if (lua_isboolean(L, 3))
+	{
+		flag1 = lua_toboolean(L, 3);
+	}
+	if (lua_isboolean(L, 4))
+	{
+		flag2 = lua_toboolean(L, 4);
+	}
+	switch(op)
+	{
+	case 0:
+		if (fa && fb)
+		{
+			d64_a = d64_a + d64_b;
+			goto FLOAT_OP;
+		}
+		if (fa && !fb)
+		{
+			d64_a = d64_a + i64_b;
+			goto FLOAT_OP;
+		}
+		if (!fa && fb)
+		{
+			d64_a = i64_a + d64_b;
+			goto FLOAT_OP;
+		}
+		if (!fa && !fb)
+		{
+			if (flag1)
+			{
+				u64 = (uint64_t)i64_a + (uint64_t)i64_b;
+				memcpy(data, &u64, 8);
+			}
+			else
+			{
+				i64_a = i64_a + i64_b;
+				memcpy(data, &i64_a, 8);
+			}
+			goto DONE;
+		}
+		break;
+	case 1:
+		if (fa && fb)
+		{
+			d64_a = d64_a - d64_b;
+			goto FLOAT_OP;
+		}
+
+		if (fa && !fb)
+		{
+			d64_a = d64_a - i64_b;
+			goto FLOAT_OP;
+		}
+
+		if (!fa && fb)
+		{
+			d64_a = i64_a - d64_b;
+			goto FLOAT_OP;
+		}
+
+		if (!fa && !fb)
+		{
+			if (flag1)
+			{
+				u64 = (uint64_t)i64_a - (uint64_t)i64_b;
+				memcpy(data, &u64, 8);
+			}
+			else
+			{
+				i64_a = i64_a - i64_b;
+				memcpy(data, &i64_a, 8);
+			}
+			goto DONE;
+		}
+		break;
+	case 2:
+		if (fa && fb)
+		{
+			d64_a = d64_a * d64_b;
+			goto FLOAT_OP;
+		}
+		if (fa && !fb)
+		{
+			d64_a = d64_a * i64_b;
+			goto FLOAT_OP;
+		}
+		if (!fa && fb)
+		{
+			d64_a = i64_a * d64_b;
+			goto FLOAT_OP;
+		}
+		if (!fa && !fb)
+		{
+			if (flag1)
+			{
+				u64 = (uint64_t)i64_a * (uint64_t)i64_b;
+				memcpy(data, &u64, 8);
+			}
+			else
+			{
+				i64_a = i64_a * i64_b;
+				memcpy(data, &i64_a, 8);
+			}
+			goto DONE;
+		}
+		break;
+	case 3:
+		if (fa && fb)
+		{
+			d64_a = d64_a / d64_b;
+			goto FLOAT_OP;
+		}
+		if (fa && !fb)
+		{
+			d64_a = d64_a / i64_b;
+			goto FLOAT_OP;
+		}
+		if (!fa && fb)
+		{
+			d64_a = i64_a / d64_b;
+			goto FLOAT_OP;
+		}
+		if (!fa && !fb)
+		{
+			if (flag1)
+			{
+				u64 = (uint64_t)i64_a / (uint64_t)i64_b;
+				memcpy(data, &u64, 8);
+			}
+			else
+			{
+				i64_a = i64_a / i64_b;
+				memcpy(data, &i64_a, 8);
+			}
+			goto DONE;
+		}
+		break;
+	}
+FLOAT_OP:
+	if (flag2)
+	{
+		i64_a = d64_a;
+		memcpy(data, &i64_a, 8);
+	}
+	else
+	{
+		data[8] = D64_FLAG;
+		memcpy(data, &d64_a, 8);
+	}
+	goto DONE;
+DONE:
+	lua_pushlstring(L, data, 9);
+	return 1;
+}
+
+/**
+64bit数据加,a+b,a和b中有一个为浮点,则按照浮点运算
+@api bit64.plus(a,b,flag1,flag2)
+@string a
+@string/int/number b
+@boolean 整形运算时是否按照无符号方式,true是,false不是,默认false,浮点运算忽略
+@boolean 浮点运算结果是否要强制转成整数,true是,false不是,默认false,整形运算忽略
+@return string 9字节数据
+ */
+static int l_bit64_plus(lua_State *L)
+{
+	return l_bit64_calculate(L, 0);
+}
+
+
+/**
+64bit数据减,a-b,a和b中有一个为浮点,则按照浮点运算
+@api bit64.minus(a,b,flag1,flag2)
+@string a
+@string/int/number b
+@boolean 整形运算时是否按照无符号方式,true是,false不是,默认false,浮点运算忽略
+@boolean 浮点运算结果是否要强制转成整数,true是,false不是,默认false,整形运算忽略
+@return string 9字节数据
+ */
+static int l_bit64_minus(lua_State *L)
+{
+	return l_bit64_calculate(L, 1);
+}
+
+/**
+64bit数据乘,a*b,a和b中有一个为浮点,则按照浮点运算
+@api bit64.mult(a,b,flag1,flag2)
+@string a
+@string/int/number b
+@boolean 整形运算时是否按照无符号方式,true是,false不是,默认false,浮点运算忽略
+@boolean 浮点运算结果是否要强制转成整数,true是,false不是,默认false,整形运算忽略
+@return string 9字节数据
+ */
+static int l_bit64_multiply(lua_State *L)
+{
+	return l_bit64_calculate(L, 2);
+}
+
+/**
+64bit数据除,a/b,a和b中有一个为浮点,则按照浮点运算
+@api bit64.pide(a,b,flag1,flag2)
+@string a
+@string/int/number b
+@boolean 整形运算时是否按照无符号方式,true是,false不是,默认false,浮点运算忽略
+@boolean 浮点运算结果是否要强制转成整数,true是,false不是,默认false,整形运算忽略
+@return string 9字节数据
+ */
+static int l_bit64_pide(lua_State *L)
+{
+	return l_bit64_calculate(L, 3);
+}
+
+/**
+64bit数据位移 a>>b 或者 a<<b
+@api bit64.shift(a,b,flag)
+@string a
+@int b
+@boolean 位移方向,true左移<<,false右移>>,默认false
+@return string 9字节数据
+ */
+static int l_bit64_shift(lua_State *L)
+{
+	uint64_t u64;
+	uint32_t pos = 0;
+    size_t len;
+    uint8_t data[9] = {0};
+    uint8_t flag = 0;
+    const char *string = luaL_checklstring(L, 1, &len);
+    if (len != 9)
+    {
+    	goto DONE;
+    }
+    data[8] = string[8];
+    memcpy(&u64, string, 8);
+
+	if (lua_isinteger(L, 2))
+	{
+		pos = lua_tointeger(L, 2);
+		if (!pos)
+		{
+			goto DONE;
+		}
+	}
+	else
+	{
+		goto DONE;
+	}
+	if (lua_isboolean(L, 3))
+	{
+		flag = lua_toboolean(L, 3);
+	}
+	if (flag)
+	{
+		u64 = u64 << pos;
+	}
+	else
+	{
+		u64 = u64 >> pos;
+	}
+    data[8] = string[8];
+    memcpy(data, &u64, 8);
+	lua_pushlstring(L, data, 9);
+	return 1;
+DONE:
+	lua_pushlstring(L, string, len);
+	return 1;
+}
+
+#include "rotable2.h"
+static const rotable_Reg_t reg_bit64[] = {
+	{"to32", ROREG_FUNC(l_bit64_to32)},
+	{"to64", ROREG_FUNC(l_bit64_to64)},
+	{"plus", ROREG_FUNC(l_bit64_plus)},
+	{"minus", ROREG_FUNC(l_bit64_minus)},
+	{"multi", ROREG_FUNC(l_bit64_multiply)},
+	{"pide", ROREG_FUNC(l_bit64_pide)},
+	{"shift", ROREG_FUNC(l_bit64_shift)},
+	{"show", ROREG_FUNC(l_bit64_show)},
+	{NULL,       ROREG_INT(0)}
+};
+
+LUAMOD_API int luaopen_bit64(lua_State *L)
+{
+    luat_newlib2(L, reg_bit64);
+    return 1;
+}
+#endif

+ 27 - 0
luat/modules/luat_lib_pm.c

@@ -350,6 +350,32 @@ static int l_pm_power_ctrl(lua_State *L) {
 // }
 // #endif
 
+
+/**
+配置唤醒引脚 (当前仅仅esp系列可用)
+@api pm.wakeupPin(pin,level)
+@int/table gpio引脚
+@int 唤醒电压 可选,默认低电平唤醒
+@return boolean 处理结果
+@usage
+pm.wakeupPin(8,0)
+ */
+static int l_pm_wakeup_pin(lua_State *L) {
+    int level = luaL_optinteger(L, 2,0);
+    if (lua_istable(L, 1)) {
+        size_t count = lua_rawlen(L, 1);
+		for (size_t i = 1; i <= count; i++){
+			lua_geti(L, 1, i);
+            luat_pm_wakeup_pin(luaL_checkinteger(L, -1), level);
+			lua_pop(L, 1);
+		}
+    }else if(lua_isnumber(L, 1)){
+        luat_pm_wakeup_pin(luaL_checkinteger(L, 1), level);
+    }
+    lua_pushboolean(L, 1);
+    return 1;
+}
+
 #include "rotable2.h"
 static const rotable_Reg_t reg_pm[] =
 {
@@ -368,6 +394,7 @@ static const rotable_Reg_t reg_pm[] =
     { "reboot",         ROREG_FUNC(l_rtos_reboot)},
 	{ "power",          ROREG_FUNC(l_pm_power_ctrl)},
     // { "ioVolt",         ROREG_FUNC(l_pm_iovolt_ctrl)},
+    { "wakeupPin",         ROREG_FUNC(l_pm_wakeup_pin)},
 
 
     //@const NONE number 不休眠模式

+ 14 - 31
luat/modules/luat_lib_sensor.c

@@ -55,24 +55,15 @@ static uint8_t w1_connect(int pin)
   return CONNECT_SUCCESS;
 }
 
-static uint8_t w1_read_bit(int pin)
-{
+static uint8_t w1_read_bit(int pin){
   uint8_t data;
-
   luat_gpio_mode(pin, Luat_GPIO_OUTPUT, Luat_GPIO_PULLUP, 0);
   luat_gpio_set(pin, Luat_GPIO_LOW);
   luat_timer_us_delay(2);
   luat_gpio_set(pin, Luat_GPIO_HIGH);
   luat_gpio_mode(pin, Luat_GPIO_INPUT, Luat_GPIO_PULLUP, 0);
-  luat_timer_us_delay(5);
-
-  if (luat_gpio_get(pin))
-    data = 1;
-  else
-    data = 0;
-
-  luat_timer_us_delay(50);
-
+  data = (uint8_t)luat_gpio_get(pin);
+  luat_timer_us_delay(60);
   return data;
 }
 
@@ -80,7 +71,7 @@ static uint8_t w1_read_byte(int pin)
 {
   uint8_t i, j, dat;
   dat = 0;
-
+  luat_timer_us_delay(90);
   //rt_base_t level;
   //level = rt_hw_interrupt_disable();
   for (i = 1; i <= 8; i++)
@@ -148,9 +139,8 @@ static int32_t ds18b20_get_temperature(int pin, int32_t *val, int check_crc)
 
   //ds18b20_start(pin);
   w1_reset(pin);
-  if (w1_connect(pin))
-  {
-    //LLOGD("ds18b20 connect fail");
+  if (w1_connect(pin)){
+    // LLOGD("ds18b20 connect fail");
     return -1;
   }
   w1_write_byte(pin, 0xcc); /* skip rom */
@@ -158,9 +148,8 @@ static int32_t ds18b20_get_temperature(int pin, int32_t *val, int check_crc)
 
   //ds18b20_init(pin);
   w1_reset(pin);
-  if (w1_connect(pin))
-  {
-    //LLOGD("ds18b20 connect fail");
+  if (w1_connect(pin)){
+    // LLOGD("ds18b20 connect fail");
     return -2;
   }
 
@@ -178,30 +167,26 @@ static int32_t ds18b20_get_temperature(int pin, int32_t *val, int check_crc)
   // 9个字节都读出来,校验CRC
   if (check_crc)
   {
-    for (size_t i = 2; i < 9; i++)
-    {
+    for (size_t i = 2; i < 9; i++){
       data[i] = w1_read_byte(pin);
     }
     uint8_t crc = 0;
-    for (size_t i = 0; i < 8; i++)
-    {
+    for (size_t i = 0; i < 8; i++){
       crc = crc8_maxim[crc ^ data[i]];
     }
     // LLOGD("ds18b20 %02X%02X%02X%02X%02X%02X%02X%02X [%02X %02X]",
     //            data[0], data[1], data[2], data[3],
     //            data[4], data[5], data[6], data[7],
     //            data[8], crc);
-    if (data[8] != crc)
-    {
-      //LLOGD("ds18b20 bad crc");
+    if (data[8] != crc){
+      // LLOGD("ds18b20 bad crc");
       return -4;
     }
   }
   TL = data[0];
   TH = data[1];
 
-  if (TH > 7)
-  {
+  if (TH > 7){
     TH = ~TH;
     TL = ~TL;
     tem = TH;
@@ -210,9 +195,7 @@ static int32_t ds18b20_get_temperature(int pin, int32_t *val, int check_crc)
     tem = (int32_t)(tem * 0.0625 * 10 + 0.5);
     *val = -tem;
     return 0;
-  }
-  else
-  {
+  }else{
     tem = TH;
     tem <<= 8;
     tem += TL;

+ 2 - 2
luat/modules/luat_lib_uart.c

@@ -155,7 +155,7 @@ static int luat_uart_soft_setup(luat_uart_t *uart)
 		prv_uart_soft->rx_period = luat_uart_soft_cal_baudrate(uart->baud_rate) + prv_uart_soft->rx_adjust_period;
 	}
 
-	LLOGD("soft uart period %u,%u!", prv_uart_soft->tx_period, prv_uart_soft->rx_period);
+//	LLOGD("soft uart period %u,%u!", prv_uart_soft->tx_period, prv_uart_soft->rx_period);
 	switch(uart->stop_bits)
 	{
 	case 2:
@@ -1035,7 +1035,7 @@ UART_SOFT_RX_BYTE_DONE:
 	prv_uart_soft->rx_fifo_cnt++;
 	luat_uart_soft_gpio_fast_irq_set(prv_uart_soft->rx_pin, 1);
 	prv_uart_soft->rx_shift_bits = 0xef;
-	luat_uart_soft_hwtimer_onoff(prv_uart_soft->rx_hwtimer_id, prv_uart_soft->stop_period * 5);	//这里做接收超时检测
+	luat_uart_soft_hwtimer_onoff(prv_uart_soft->rx_hwtimer_id, prv_uart_soft->stop_period * 20);	//这里做接收超时检测
 	if (prv_uart_soft->rx_fifo_cnt < LUAT_UART_SOFT_FIFO_CNT)	//接收fifo没有满,继续接收
 	{
 		return;

+ 5 - 0
luat/modules/luat_main.c

@@ -194,7 +194,12 @@ int luat_main (void) {
   #else
   LLOGI("LuatOS@%s base %s bsp %s 32bit", luat_os_bsp(), LUAT_VERSION, LUAT_BSP_VERSION);
   #endif
+  /// 支持时间无关的编译, 符合幂等性
+  #ifdef LUAT_BUILD_FINGER
+  LLOGI("ROM Finger: " LUAT_BUILD_FINGER);
+  #else
   LLOGI("ROM Build: " __DATE__ " " __TIME__);
+  #endif
   // #if LUAT_VERSION_BETA
   // LLOGD("This is a beta/snapshot version, for testing");
   // #endif

+ 462 - 0
script/libs/aLiyun.lua

@@ -0,0 +1,462 @@
+--[[
+@module aliyun
+@summary aliyun 阿里云
+@version 1.0
+@date    2023.03.10
+@author  翟浩宇
+@usage
+-- 用法实例
+参考aliyun demo: https://gitee.com/openLuat/LuatOS/tree/master/demo/aliyun
+]]
+
+local sys = require "sys"
+--[[特别注意, 使用mqtt库需要下列语句]]
+_G.sysplus = require("sysplus")
+
+aliyun = {}
+
+local clientId,password,userName,DeviceSecret
+
+local outQueue =
+{
+    SUBSCRIBE = {},
+    PUBLISH = {},
+}
+
+local evtCb = {}
+
+local mqttc = nil
+
+--添加
+local function insert(type,topic,qos,payload,retain)
+    table.insert(outQueue[type],{t=topic,q=qos,p=payload,r=retain})
+end
+
+--删除
+local function remove(type)
+    if #outQueue[type]>0 then return table.remove(outQueue[type],1) end
+end
+
+--订阅步骤
+local function procSubscribe(client)
+    local i
+    if #outQueue["SUBSCRIBE"]>0 then
+        log.info("订阅表里大于零")
+    else 
+        log.info("订阅表里没数据")
+    end
+
+    for i=1,#outQueue["SUBSCRIBE"] do
+        if not client:subscribe(outQueue["SUBSCRIBE"][i].t , outQueue["SUBSCRIBE"][i].q) then
+            outQueue["SUBSCRIBE"] = {}
+            return false,"procSubscribe"
+        end
+    end
+    outQueue["SUBSCRIBE"] = {}
+    return true
+end
+
+--接收处理
+local function procReceive(client)
+    while true do
+        log.info("到接受处理方法里了")
+        local ret,data,payload,DeviceName,ProductKey = sys.waitUntil("NET_SENT_RDY",30000)
+        log.info("接收到消息之后传到处理方法里的数据",ret,data,payload,DeviceName,ProductKey)
+        --接收到数据
+        if ret then
+            log.info("aliyun.procReceive",data.topic,string.toHex(data.payload))
+            --OTA消息
+            if payload.topic=="/ota/device/upgrade/"..ProductKey.."/"..DeviceName then
+                log.info("进到OTA升级判断里了",payload.topic)
+                -- if aliyunOta and aliyunOta.upgrade then
+                --     aliyunOta.upgrade(data.payload)
+                -- end
+            --其他消息
+            else    
+                if evtCb["receive"] then evtCb["receive"](data.topic,data.qos,data.payload) end
+            end
+            
+            
+            --如果有等待发送的数据,则立即退出本循环
+            if #outQueue["PUBLISH"]>0 then
+                return true,"procReceive"
+            end
+        end
+    end
+	
+    return data=="timeout" or "procReceive"
+end
+
+--发布
+local function procSend(client)
+    sys.taskInit(function()
+        if not procSubscribe(client) then
+            return false,"procSubscribe"
+        end
+        if #outQueue["PUBLISH"]>0 then
+            log.info("发布表里大于零")
+        else 
+            log.info("发布表里没数据")
+        end
+
+        while #outQueue["PUBLISH"]>0 do
+            local item = table.remove(outQueue["PUBLISH"],1)
+            local result = client:publish(item.t,item.p,item.q)
+            if item.cb then item.cb(result,item.para) end
+            if not result then
+                return false,"procSend" 
+            end
+        end
+        return true,"procSend"
+    end)
+end
+
+--二次连接
+local function clientDataTask(clientId,user,password,mqtt_host,mqtt_port,mqtt_isssl,DeviceName,ProductKey)
+    sys.taskInit(function()
+        if mobile.status() == 0 then
+            sys.waitUntil("IP_READY",30000)
+        end
+        if mobile.status() == 1 then
+            local mqttc = mqtt.create(nil,mqtt_host,mqtt_port,mqtt_isssl)  --客户端创建
+            mqttc:auth(clientId,user,password) --三元组配置
+            mqttc:keepalive(30) -- 默认值240s
+            mqttc:autoreconn(true, 3000) -- 自动重连机制
+    
+            mqttc:on(mqtt_cbevent)  --mqtt回调注册
+            if mqttc:connect() then
+                while true do
+                    procSubscribe(mqttc)
+                    procSend(mqttc)
+                    sys.wait(1000)
+                end
+            end
+    
+    
+        else
+            --进入飞行模式,20秒之后,退出飞行模式
+            mobile.flymode(0,true)
+            sys.wait(20000)
+            mobile.flymode(0,false)
+        end
+    end)
+end
+
+--根据返回的数据进行二次加密
+local function directProc(DeviceName,ProductKey,mqtt_host,mqtt_port,mqtt_isssl,Registration)
+    if not Registration then
+        local clientId = DeviceName.."|securemode=2,signmethod=hmacmd5,timestamp=789|"
+        local userName = DeviceName.."&"..ProductKey
+        
+        local content = "clientId"..DeviceName.."deviceName"..DeviceName.."productKey"..ProductKey.."timestamp789"
+        log.info("content",content)
+        local signKey= fskv.kv_get("deviceSecret")
+        log.info("signKey",signKey)
+        password =crypto.hmac_md5(content,signKey)
+        log.info("password",password)
+
+        
+        log.info("aliyun.directProc",clientId,userName,password)
+        
+        clientDataTask(clientId,userName,password,mqtt_host,mqtt_port,mqtt_isssl,DeviceName,ProductKey)
+    else
+        local clientid = fskv.kv_get("clientid")
+        local deviceToken = fskv.kv_get("deviceToken")
+        local clientId = clientid.."|securemode=-2,authType=connwl|"
+        local userName = DeviceName.."&"..ProductKey
+        local password = deviceToken
+
+        log.info("aliyun.directProc",clientId,userName,password)
+        
+        clientDataTask(clientId,userName,password,mqtt_host,mqtt_port,mqtt_isssl,DeviceName,ProductKey)
+    end
+end
+
+--获取预注册和免预注册一型一密一次连接返回的数据
+local function clientEncryptionTask(Registration,DeviceName,ProductKey,ProductSecret,InstanceId,mqtt_host,mqtt_port,mqtt_isssl)
+    sys.taskInit(function()
+        local tm = os.time()
+        --一型一密
+            --预注册
+            if not Registration then
+                clientId = DeviceName.."|securemode=2,authType=register,random="..tm..",signmethod=hmacmd5|"
+            --免预注册
+            else
+                clientId = DeviceName.."|securemode=-2,authType=regnwl,random="..tm..",signmethod=hmacmd5,instanceId="..InstanceId.."|"
+            end
+            userName = DeviceName.."&"..ProductKey
+            local content = "deviceName"..DeviceName.."productKey"..ProductKey.."random"..tm
+            password = crypto.hmac_md5(content,ProductSecret)
+    
+            local mqttClient = mqtt.create(nil,mqtt_host,mqtt_port,mqtt_isssl)  --客户端创建
+            mqttClient:auth(clientId,userName,password) --三元组配置
+            mqttClient:on(function(mqtt_client, event, data, payload)  --mqtt回调注册
+                -- 用户自定义代码
+                if event == "conack" then
+
+                elseif event == "recv" then
+                    log.info("mqtt", "downlink", "topic", data, "payload", payload)
+                    if payload then
+                        local tJsonDecode,res = json.decode(payload)
+                        if not Registration then
+                            --预注册
+                            if res and tJsonDecode["deviceName"] and tJsonDecode["deviceSecret"] then
+                                --把当前设备的SN号改为设备秘钥
+                                fskv.init()
+                                fskv.set("deviceSecret", tJsonDecode["deviceSecret"])
+                                mqttClient:disconnect()
+                                directProc(DeviceName,ProductKey,mqtt_host,mqtt_port,mqtt_isssl,Registration)
+                            end
+                        else
+                             --免预注册
+                            if res and tJsonDecode["deviceName"] and tJsonDecode["deviceToken"] then
+                                --把当前设备的SN号改为设备秘钥
+                                fskv.init()
+                                fskv.set("deviceToken", tJsonDecode["deviceToken"])
+                                fskv.set("clientid", tJsonDecode["clientId"])
+                                -- sys.wait(1000)
+                                mqttClient:disconnect()
+                                directProc(DeviceName,ProductKey,mqtt_host,mqtt_port,mqtt_isssl,Registration)
+                            end
+                        end
+                        
+                    end
+                elseif event == "sent" then
+                    log.info("mqtt", "sent", "pkgid", data)
+                end
+            end)
+    
+            mqttClient:connect()
+            log.info("mqtt连接成功")
+    end)
+end
+
+
+--底层libMQTT回调函数,上层的回调函数,通过 aliyun.on注册
+local function mqtt_cbevent(mqtt_client, event, data, payload) 
+    if event == "conack" then
+        evtCb["connect"](true) 
+    elseif event == "recv" then -- 服务器下发的数据
+        log.info("mqtt", "downlink", "topic", data, "payload", payload)
+
+        if evtCb["receive"] then
+            evtCb["receive"](data, payload)
+        end
+    elseif event == "sent" then
+        log.info("mqtt", "sent", "pkgid", data)
+    end
+end
+
+
+--正常连接 预注册一型一密获取DeviceSecret后就是正常的一机一密连接
+local function clientDirectTask(DeviceName,ProductKey,mqtt_host,mqtt_port,mqtt_isssl)
+    sys.taskInit(function()
+        if mobile.status() == 0 then
+            sys.waitUntil("IP_READY",30000)
+        end
+        if mobile.status() == 1 then
+            if DeviceSecret==nil then
+                DeviceSecret = fskv.get("deviceSecret")
+            end
+            local client_id,user_name,password = iotauth.aliyun(ProductKey,DeviceName,DeviceSecret)
+            mqttc = mqtt.create(nil,mqtt_host, mqtt_port,mqtt_isssl)  --mqtt客户端创建
+    
+            mqttc:auth(client_id,user_name,password) --mqtt三元组配置
+            mqttc:keepalive(30) -- 默认值240s
+            mqttc:autoreconn(true, 3000) -- 自动重连机制
+    
+            mqttc:on(mqtt_cbevent)  --mqtt回调注册
+            if mqttc:connect() then
+                while true do
+                    procSubscribe(mqttc)
+                    procSend(mqttc)
+                    sys.wait(1000)
+                end  
+            end
+            
+        else
+            --进入飞行模式,20秒之后,退出飞行模式
+            mobile.flymode(0,true)
+            sys.wait(20000)
+            mobile.flymode(0,false)
+        end
+    end)
+end
+
+
+--正常连接 免预注册一型一密获取deviceToken后就是正常的一机一密连接
+local function clientTokenTask(DeviceName,ProductKey,mqtt_host,mqtt_port,mqtt_isssl)
+    sys.taskInit(function()
+        sys.wait(5000)
+        if mobile.status() == 0 then
+            sys.waitUntil("IP_READY",30000)
+        end
+        if mobile.status() == 1 then
+            deviceToken = fskv.get("deviceToken")
+            local clientid = fskv.kv_get("clientid")
+            local clientId = clientid.."|securemode=-2,authType=connwl|"
+    
+            local client_id,user_name,password = iotauth.aliyun(ProductKey,DeviceName,deviceToken)
+            mqttc = mqtt.create(nil,mqtt_host, mqtt_port,mqtt_isssl)  --mqtt客户端创建
+    
+            mqttc:auth(clientId,user_name,deviceToken) --mqtt三元组配置
+            mqttc:keepalive(30) -- 默认值240s
+            mqttc:autoreconn(true, 3000) -- 自动重连机制
+    
+            mqttc:on(mqtt_cbevent)  --mqtt回调注册
+            if mqttc:connect() then
+                while true do
+                    procSubscribe(mqttc)
+                    procSend(mqttc)
+                    sys.wait(1000)
+                end  
+            end
+    
+        else
+            --进入飞行模式,20秒之后,退出飞行模式
+            mobile.flymode(0,true)
+            sys.wait(20000)
+            mobile.flymode(0,false)
+        end
+    end)
+end
+
+--根据掉电不消失的kv文件区来储存的deviceSecret,deviceToken来判断是进行正常连接还是
+
+--[[
+一型一密连接
+@api aliyun.operation(Registration,DeviceName,ProductKey,ProductSecret,InstanceId,mqtt_host,mqtt_port,mqtt_isssl)
+@bool Registration 是否预注册
+@string DeviceName 设备id
+@string ProductKey 产品key
+@string ProductSecret 产品秘钥
+@string InstanceId 实例id
+@string mqtt_host 公共实例的地址
+@string mqtt_port 端口
+@bool mqtt_isssl 是否为ssl加密连接,默认不加密,true为无证书最简单的加密,table为有证书的加密
+@usage
+aliyun.operation(Registration,DeviceName,ProductKey,ProductSecret,InstanceId,mqtt_host,mqtt_port,mqtt_isssl)
+]]
+function aliyun.operation(Registration,DeviceName,ProductKey,ProductSecret,InstanceId,mqtt_host,mqtt_port,mqtt_isssl)
+    fskv.init()
+    fskv.set("DeviceName",DeviceName)
+    local name = fskv.get("DeviceName")
+    local used = fskv.get("deviceSecret")
+    local total = fskv.get("deviceToken")
+    local cid = fskv.get("clientid")
+    --判断是否是同一DeviceName,不是的话就重新连接
+    if name == DeviceName then
+        if not Registration then
+            if used == nil then
+                clientEncryptionTask(Registration,DeviceName,ProductKey,ProductSecret,InstanceId,mqtt_host,mqtt_port,mqtt_isssl)
+            else
+                clientDirectTask(DeviceName,ProductKey,mqtt_host,mqtt_port,mqtt_isssl)
+            end
+        else
+            -- fskv.del("deviceToken")
+            -- fskv.del("clientid")
+            -- log.info("删除deviceToken,clientid")
+            if total == nil then
+                clientEncryptionTask(Registration,DeviceName,ProductKey,ProductSecret,InstanceId,mqtt_host,mqtt_port,mqtt_isssl)
+            else
+                clientTokenTask(DeviceName,ProductKey,mqtt_host,mqtt_port,mqtt_isssl)
+            end
+        end
+    else
+            fskv.del("deviceToken")
+            fskv.del("clientid")
+            fskv.del("DeviceName")
+            fskv.del("deviceSecret")
+            --删除kv区的数据,重新建立连接
+            clientEncryptionTask(Registration,DeviceName,ProductKey,ProductSecret,InstanceId,mqtt_host,mqtt_port,mqtt_isssl)
+    end
+end
+
+--[[
+一机一密连接
+@api aliyun.confiDentialTask(DeviceName,ProductKey,DeviceSecret,mqtt_host,mqtt_port,mqtt_isssl)
+@string DeviceName 设备id
+@string ProductKey 产品key
+@string DeviceSecret 设备秘钥
+@string mqtt_host 公共实例的地址
+@string mqtt_port 端口
+@bool mqtt_isssl 是否为ssl加密连接,默认不加密,true为无证书最简单的加密,table为有证书的加密
+@usage
+aliyun.confiDentialTask(DeviceName,ProductKey,DeviceSecret,mqtt_host,mqtt_port,mqtt_isssl)
+]]
+function aliyun.confiDentialTask(DeviceName,ProductKey,DeviceSecret,mqtt_host,mqtt_port,mqtt_isssl)
+    sys.taskInit(function()
+        sys.wait(5000)
+        if mobile.status() == 0 then
+            sys.waitUntil("IP_READY",30000)
+        end
+        if mobile.status() == 1 then
+            local client_id,user_name,password = iotauth.aliyun(ProductKey,DeviceName,DeviceSecret)
+            mqttc = mqtt.create(nil,mqtt_host, mqtt_port,mqtt_isssl)  --mqtt客户端创建
+            mqttc:auth(client_id,user_name,password) --mqtt三元组配置
+            mqttc:keepalive(30) -- 默认值240s
+            mqttc:autoreconn(true, 3000) -- 自动重连机制
+
+            mqttc:on(mqtt_cbevent)  --mqtt回调注册
+            if mqttc:connect() then
+                while true do
+                    procSubscribe(mqttc)
+                    procSend(mqttc)
+                    sys.wait(1000)
+                end  
+            end
+            
+        else
+            --进入飞行模式,20秒之后,退出飞行模式
+            mobile.flymode(0,true)
+            sys.wait(20000)
+            mobile.flymode(0,false)
+        end
+    end)
+end
+
+--[[
+订阅主题
+@api aliyun.subscriber(topic,qos)
+@string/table topic,string或者table类型,一个主题时为string类型,多个主题时为table类型,主题内容为UTF8编码
+@number qos,number或者nil,topic为一个主题时,qos为number类型(0/1,默认0);topic为多个主题时,qos为nil
+@usage
+-- aliyun.subscriber("/b0FMK1Ga5cp/862991234567890/get", 0)
+-- aliyun.subscriber({["/b0FMK1Ga5cp/862991234567890/get"] = 0, ["/b0FMK1Ga5cp/862991234567890/get"] = 1})
+]]
+function aliyun.subscriber(topic,qos)
+    insert("SUBSCRIBE",topic,qos)
+    sys.publish("aliyun_publish_ind","send")
+end
+
+--[[
+发布一条消息
+@api aliyun.publish(topic,qos,payload,retain)
+@string topic,UTF8编码的主题
+@number qos,0/1,默认0
+@numberretain,是否存档, 0/1,默认0
+@number i2c_id i2c_id
+@usage
+aliyun.publish("/"..ProductKey.."/"..DeviceName.."/user/get",0,"LUATOS_CESHI")
+]]
+function aliyun.publish(topic,qos,payload,retain)
+    insert("PUBLISH",topic,qos,payload,retain)
+    sys.publish("aliyun_publish_ind","send")
+    log.info("aliyun aliyun_publish_ind","publish")
+end
+
+--[[
+注册事件的处理函数
+@api aliyun.on(evt,cbFnc)
+@string evt 事件 <br>"auth"表示鉴权服务器认证结果事件 <br>"connect"表示接入服务器连接结果事件 <br>"reconnect"表示重连事件 <br>"receive"表示接收到接入服务器的消息事件
+@function cbFnc 事件的处理函数  <br>当evt为"auth"时,cbFnc的调用形式为:cbFnc(result),result为true表示认证成功,false或者nil表示认证失败 <br>当evt为"connect"时,cbFnc的调用形式为:cbFnc(result),result为true表示连接成功,false或者nil表示连接失败 <br>当evt为"receive"时,cbFnc的调用形式为:cbFnc(topic,qos,payload),topic为UTF8编码的主题(string类型),qos为质量等级(number类型),payload为原始编码的负载(string类型) <br>当evt为"reconnect"时,cbFnc的调用形式为:cbFnc(),表示lib中在自动重连阿里云服务器
+@usage
+aliyun.on("connect",cbFnc)
+]]
+function aliyun.on(evt,cbFnc)
+	evtCb[evt] = cbFnc
+end
+
+
+return aliyun
+

+ 1 - 1
script/libs/libfota.lua

@@ -57,7 +57,7 @@ local tag = "fota"
 
 local function netCB(msg)
     if msg[1] == socket.EVENT then
-        log.info(tag, "socket网络状态变更")
+        --log.info(tag, "socket网络状态变更")
     elseif msg[1] == socket.TX_OK then
         log.info(tag, "socket发送完成")
     elseif msg[1] == socket.EV_NW_RESULT_CLOSE then

+ 102 - 0
script/libs/ze08g_ch2o.lua

@@ -0,0 +1,102 @@
+--[[
+@module ze08g_ch2o
+@summary ZE08G-CH2O 电化学甲醛模组
+@version 1.0
+@date    2023.03.09
+@author  BaiShiyu
+@usage
+--注意:因使用了sys.wait()所有api需要在协程中使用
+-- 用法实例
+sys = require("sys")
+local ch2o = require "ze08g_ch2o"
+local uartid = 1 -- 根据实际设备选取不同的uartid
+
+sys.taskInit(function ()
+    local result = ch2o.init(uartid)
+    if not result then return end
+
+    while true do
+        sys.wait(1000)
+        log.info("气体浓度值 PPB:", ch2o.getPPB())
+        log.info("百万分比浓度 PPM:", ch2o.getPPM())
+    end
+end)
+]]
+
+
+local ze08g_ch2o = {}
+
+local uartid    -- 根据实际设备选取不同的uartid
+local rbuff
+local ppb = 0
+
+--[[
+ze08g_ch2o初始化
+@api ze08g_ch2o.init(uart_id)
+@number uart_id uartid
+@return bool   成功返回true
+@usage
+ze08g_ch2o.init(1)
+]]
+function ze08g_ch2o.init(uart_id)
+    uartid = uart_id
+    --初始化
+    local result = uart.setup(
+        uartid,--串口id
+        9600,--波特率
+        8,--数据位
+        1--停止位
+    )
+
+    if result ~= 0 then
+        log.info("ze08g_ch2o init_fail")
+        return false
+    end
+
+    -- 收取数据会触发回调, 这里的"receive" 是固定值
+    uart.on(uartid, "receive", function(id, len)
+        local s = ""
+        s = uart.read(id, len)
+        if #s == 0 then return end
+    
+        local hexStr, hexLen = s:toHex()
+        log.info("CH2O", "receive", hexStr, hexLen)
+        
+        if string.sub(hexStr,1,2) == "FF" and hexLen == 18 then
+            rbuff = s
+        end
+    end)
+
+    log.info("ze08g_ch2o init_ok")
+    return true
+end
+
+
+--[[
+获取ze08g_ch2o PPB数据
+@api ze08g_ch2o.getPPB()
+@return number 气体浓度值
+@usage
+local ppb = ze08g_ch2o.getPPB()
+log.info("气体浓度值 PPB:", ppb))
+]]
+function ze08g_ch2o.getPPB()
+    if not rbuff then return 0 end
+    ppb = rbuff:byte(5)*255 + rbuff:byte(6)
+    return ppb
+end
+
+--[[
+获取ze08g_ch2o PPM数据
+@api ze08g_ch2o.getPPM()
+@return number 百万分比浓度
+@usage
+local ppm = ze08g_ch2o.getPPM()
+log.info("百万分比浓度 PPM:", ppm))
+]]
+function ze08g_ch2o.getPPM()
+    return ppb / 1000
+end
+
+return ze08g_ch2o
+

+ 119 - 0
script/libs/zh07.lua

@@ -0,0 +1,119 @@
+--[[
+@module zh07
+@summary ZH07 激光粉尘传感器
+@version 1.0
+@date    2023.03.09
+@author  BaiShiyu
+@usage
+--注意:因使用了sys.wait()所有api需要在协程中使用
+-- 用法实例
+sys = require("sys")
+local zh07 = require "zh07"
+local uartid = 1 -- 根据实际设备选取不同的uartid
+
+sys.taskInit(function ()
+    local result = zh07.init(uartid)
+    if not result then return end
+
+    while true do
+        sys.wait(1000)
+        log.info(string.format("pm1.0  %sμg/m³", zh07.getPM_1()))
+        log.info(string.format("pm2.5  %sμg/m³", zh07.getPM_2_5()))
+        log.info(string.format("pm10   %sμg/m³", zh07.getPM_10()))
+    end
+end)
+]]
+
+
+local zh07 = {}
+-- local sys = require "sys"
+
+local uartid    -- 根据实际设备选取不同的uartid
+local rbuff
+
+--[[
+zh07初始化
+@api zh07.init(uart_id)
+@number uart_id uartid
+@return bool   成功返回true
+@usage
+zh07.init(1)
+]]
+function zh07.init(uart_id)
+    uartid = uart_id
+    --初始化
+    local result = uart.setup(
+        uartid,--串口id
+        9600,--波特率
+        8,--数据位
+        1--停止位
+    )
+
+    if result ~= 0 then
+        log.info("zh07 init_fail")
+        return false
+    end
+
+    -- 收取数据会触发回调, 这里的"receive" 是固定值
+    uart.on(uartid, "receive", function(id, len)
+        local s = ""
+        s = uart.read(id, len)
+        if #s == 0 then return end
+
+        local hexStr, hexLen = s:toHex()
+        log.info("ZH07", "receive", hexStr, hexLen)
+
+        if string.sub(hexStr,1,2) == "42" and hexLen == 64 then
+            rbuff = s
+        end
+    end)
+
+    log.info("zh07 init_ok")
+    return true
+end
+
+
+--[[
+获取zh07 PM1.0数据
+@api zh07.getPM_1()
+@return number PM1.0数据
+@usage
+local zh07_pm1 = zh07.getPM_1()
+log.info(string.format("pm1.0  %sμg/m³", zh07_pm1))
+]]
+function zh07.getPM_1()
+    if not rbuff then return 0 end
+
+    return rbuff:byte(11)*256 + rbuff:byte(12)
+end
+
+--[[
+获取zh07 PM2.5数据
+@api zh07.getPM_2_5()
+@return number PM2.5数据
+@usage
+local zh07_pm25 = zh07.getPM_2_5()
+log.info(string.format("pm2.5  %sμg/m³", zh07_pm25))
+]]
+function zh07.getPM_2_5()
+    if not rbuff then return 0 end
+
+    return rbuff:byte(13)*256 + rbuff:byte(14)
+end
+
+--[[
+获取zh07 PM10数据
+@api zh07.getPM_10()
+@return number PM10数据
+@usage
+local zh07_pm10 = zh07.getPM_10()
+log.info(string.format("pm10  %sμg/m³", zh07_pm10))
+]]
+function zh07.getPM_10()
+    if not rbuff then return 0 end
+
+    return rbuff:byte(15)*256 + rbuff:byte(16)
+end
+
+return zh07
+

+ 41 - 31
script/turnkey/web_audio/audio_play.lua

@@ -68,9 +68,13 @@ audio.on(0, function(id, event)
 end)
 
 local function audio_task()
-    local result
-    -- Air780E开发板配套
-    i2s.setup(0, 0, 0, 0, 0, i2s.MODE_MSB)
+    --Air780E开发板配套+音频扩展板. ES8211
+    --由于音频扩展板的PA是长供电的,有塔塔声音是正常的,做产品的话有额外的参考设计
+    --i2s.setup(0, 0, 0, 0, 0, i2s.MODE_MSB)
+    --如果用软件DAC,打开下面的注释
+    if audio.setBus then
+        audio.setBus(audio.BUS_SOFT_DAC)
+    end
     audio.config(0, 25, 1, 6, 200)
     gpio.setup(24, 0)
     gpio.setup(23, 0)
@@ -78,18 +82,17 @@ local function audio_task()
     gpio.setup(2, 0)
 
     -- 初始化spi flash, 如果是极限版TTS_ONCHIP,就不需要初始化
-    if sfud then
-        spi_flash = spi.deviceSetup(0,8,0,0,8,25600000,spi.MSB,1,0)
-        local ret = sfud.init(spi_flash)
-        if ret then
-            log.info("sfud.init ok")
-        else
-            log.info("sfud.init error", ret)
-            return
-        end
-    else
-        log.info("tts", "TTS_ONCHIP?? skip sfud")
-    end
+    -- if sfud then
+    --     spi_flash = spi.deviceSetup(0,8,0,0,8,25600000,spi.MSB,1,0)
+    --     local ret = sfud.init(spi_flash)
+    --     if ret then
+    --         log.info("sfud.init ok")
+    --     else
+    --         log.info("sfud.init error", ret)
+    --         return
+    --     end
+    -- end
+
     log.info("开始播放音频")
     result = audio.play(0, {"/audio.mp3"})
     if result then
@@ -117,28 +120,35 @@ local function audio_task()
     -- sys.wait(1000)
     sysplus.taskDel(taskName)
 end
+
+
 local function tts_task()
-    local result
-    -- Air780E开发板配套
-    i2s.setup(0, 0, 0, 0, 0, i2s.MODE_MSB)
+    --Air780E开发板配套+音频扩展板. ES8211
+    --由于音频扩展板的PA是长供电的,有塔塔声音是正常的,做产品的话有额外的参考设计
+    --i2s.setup(0, 0, 0, 0, 0, i2s.MODE_MSB)
+
+    --如果用软件DAC,打开下面的注释。  注意此功能适配pwm音频播放开发板,由于MP3文件是32K现在PWM还不支持,播出来的声音会比较慢
+    if audio.setBus then
+        audio.setBus(audio.BUS_SOFT_DAC)
+    end
+
     audio.config(0, 25, 1, 6, 200)
     gpio.setup(24, 0)
     gpio.setup(23, 0)
     gpio.setup(27, 0)
     gpio.setup(2, 0)
-    -- 初始化spi flash, 如果是极限版TTS_ONCHIP,就不需要初始化
-    if sfud then
-        spi_flash = spi.deviceSetup(0,8,0,0,8,25600000,spi.MSB,1,0)
-        local ret = sfud.init(spi_flash)
-        if ret then
-            log.info("sfud.init ok")
-        else
-            log.info("sfud.init error", ret)
-            return
-        end
-    else
-        log.info("tts", "TTS_ONCHIP?? skip sfud")
-    end
+    -- 初始化spi flash, 如果是极限版TTS_ONCHIP,就不需要初始化,
+    -- if sfud then
+    --     spi_flash = spi.deviceSetup(0,8,0,0,8,25600000,spi.MSB,1,0)
+    --     local ret = sfud.init(spi_flash)
+    --     if ret then
+    --         log.info("sfud.init ok")
+    --     else
+    --         log.info("sfud.init error", ret)
+    --         return
+    --     end
+    -- end
+
     log.info("开始播放TTS")
     local result, data = sys.waitUntil("TTS_msg")
     result = audio.tts(0, data)

+ 14 - 11
script/turnkey/web_audio/main.lua

@@ -7,7 +7,6 @@ VERSION = "1.0.0"
     如果外挂了spi flash,就选用后缀是带外挂flash的固件。
     区别:不带外部flash的版本,因为内存空间小,删除了大部分功能,仅供测试web_audio使用
 	    带外部flash的版本功能齐全,和官方发布的固件功能相同。
-    固件下载地址:https://gitee.com/openLuat/LuatOS/attach_files
 ]]
 
 -- sys库是标配
@@ -88,9 +87,11 @@ sys.taskInit(function()
     sys.wait(1000)
     LED = gpio.setup(27, 0, gpio.PULLUP)
     device_id = mobile.imei()
-    sys.waitUntil("IP_READY", 30000)
+    local result= sys.waitUntil("IP_READY", 30000)
+    if not result then
+        log.info("网络连接失败")
+    end
     mqttc = mqtt.create(nil, mqtt_host, mqtt_port, mqtt_isssl, ca_file)
-
     mqttc:auth(client_id, user_name, password) -- client_id必填,其余选填
     mqttc:keepalive(30) -- 默认值240s
     mqttc:autoreconn(true, 3000) -- 自动重连机制
@@ -108,17 +109,19 @@ sys.taskInit(function()
             -- mqttmsg(payload)
         elseif event == "sent" then
             log.info("mqtt", "sent", "pkgid", data)
-            -- elseif event == "disconnect" then
-            --     -- 非自动重连时,按需重启mqttc
-            --     log.info("mqtt链接断开")
-            --     -- mqtt_client:connect()
+        -- elseif event == "disconnect" then
+        --     -- 非自动重连时,按需重启mqttc
+        --     log.info("mqtt链接断开")
+        --     -- mqtt_client:connect()
         end
     end)
-    local state = mqttc:connect()
-    if state then
-        log.info("mqtt 连接成功")
-    else
+    mqttc:connect()
+    sys.wait(1000)
+    local error = mqttc:ready()
+    if not error then
         log.info("mqtt 连接失败")
+    else
+        log.info("mqtt 连接成功")
     end
     sys.waitUntil("mqtt_conack")
     while true do