Browse Source

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

alienwalker 3 years ago
parent
commit
a3531ca67d
43 changed files with 2357 additions and 925 deletions
  1. 64 0
      .github/workflows/esp32c3-idf5.yml
  2. 3 2
      README.md
  3. 6 7
      README_FULL.md
  4. 1 1
      components/epaper/EPD_7in5bc.c
  5. 29 13
      components/lua-cjson/lua_cjson.c
  6. 32 121
      components/lua-cjson/strbuf.c
  7. 9 3
      components/lua-cjson/strbuf.h
  8. 13 13
      components/lvgl/binding/luat_lv_fs.c
  9. 0 80
      components/minmea/luat_lib_libgnss.c
  10. 60 0
      components/network/httpsrv/inc/luat_httpsrv.h
  11. 87 0
      components/network/httpsrv/src/luat_lib_httpsrv.c
  12. 34 0
      components/nimble/inc/luat_nimble.h
  13. 179 0
      components/nimble/src/luat_lib_nimble.c
  14. 749 0
      components/nimble/src/luat_nimble_mode_ble_server.c
  15. 22 24
      components/serialization/protobuf/luat_lib_protobuf.c
  16. 21 18
      components/serialization/protobuf/pb.h
  17. 59 28
      components/u8g2/luat_lib_u8g2.c
  18. 2 2
      components/u8g2/u8g2.h
  19. 211 0
      components/wlan/luat_lib_wlan.c
  20. 71 0
      components/wlan/luat_wlan.h
  21. 7 0
      demo/camera/Air105/README.md
  22. 0 336
      demo/camera/Air105/capture_usb/GC032A_InitReg.txt
  23. 3 0
      demo/camera/Air105/capture_usb/README.md
  24. 0 110
      demo/camera/Air105/capture_usb/main.lua
  25. 13 0
      demo/camera/Air105/scanner/main.lua
  26. 23 24
      demo/camera/Air105/video/camera_test.lua
  27. 27 3
      demo/camera/Air105/video/main.lua
  28. 14 4
      demo/crypto/main.lua
  29. 58 0
      demo/nimble/esp32c3/main.lua
  30. 27 0
      demo/wlan/esp32c3/ap_get_start/index.html
  31. 45 0
      demo/wlan/esp32c3/ap_get_start/main.lua
  32. 43 0
      demo/wlan/esp32c3/hello_world/main.lua
  33. 27 0
      demo/wlan/esp32c3/httpsrv/index.html
  34. 55 0
      demo/wlan/esp32c3/httpsrv/main.lua
  35. 76 0
      demo/wlan/esp32c3/iotda/main.lua
  36. 127 0
      demo/wlan/esp32c3/smartconfig_esptouch/main.lua
  37. 30 0
      demo/wlan/esp32c3/wifi_scan/main.lua
  38. 76 73
      lua/src/liolib.c
  39. 24 24
      lua/src/luat_bget.c
  40. 2 0
      luat/include/luat_libs.h
  41. 16 12
      luat/modules/luat_lib_gpio.c
  42. 4 3
      luat/modules/luat_ota.c
  43. 8 24
      script/turnkey/eink-calendar/main.lua

+ 64 - 0
.github/workflows/esp32c3-idf5.yml

@@ -0,0 +1,64 @@
+name: esp32c3-idf5
+
+on:
+  push:
+    paths:
+      - '.github/workflows/esp32c3-idf5.yml'
+      - 'lua/**'
+      - 'luat/**'
+      - 'components/**'
+  workflow_dispatch:
+  repository_dispatch:
+    types:
+      - webhook-esp32c3-idf5-action
+
+jobs:
+  build:
+    runs-on: ubuntu-20.04
+    steps:
+    - uses: actions/checkout@v1
+    - name: prepare software
+      run: |
+        sudo apt-get update
+        sudo apt-get install git gcc-multilib libc6 libgcc1 libstdc++5 libstdc++6 libsdl-dev p7zip-full python3 python3-pip libncurses5-dev -y
+        mkdir -p ~/esp
+        cd ~/esp
+        git clone --recursive https://github.com/espressif/esp-idf.git
+        cd ~/esp/esp-idf
+        git submodule update --init --recursive
+        ./install.sh esp32c3
+    - name: clone LuatOS-ESP32
+      run: |
+        sudo sh -c "curl https://raw.githubusercontent.com/kadwanev/retry/master/retry -o /usr/local/bin/retry && chmod +x /usr/local/bin/retry"
+        cd ..
+        retry 'git clone --branch=master https://gitee.com/openLuat/luatos-soc-idf5'
+    - name: build
+      run: |
+        mkdir luatosfw
+        cd ../luatos-soc-idf5/luatos
+        sed -i 's/E:\/\/code\/codeup\/LuatOS\//\/home\/runner\/work\/LuatOS\/LuatOS/g' CMakeLists.txt
+        . ~/esp/esp-idf/export.sh
+        idf.py set-target esp32c3
+        idf.py build
+        mv *.soc ../../LuatOS/luatosfw
+    - name: Upload artifact
+      uses: actions/upload-artifact@v1
+      with:
+        name: esp32c3
+        path: luatosfw
+    - name: report if failure
+      if: always()
+      env:
+        STATUS: ${{ job.status }}
+        MQTTADDR: ${{ secrets.MQTTADDR }}
+        MQTTPORT: ${{ secrets.MQTTPORT }}
+        MQTTTOPIC: ${{ secrets.MQTTTOPIC }}
+        DD_APPKEY: ${{ secrets.DD_APPKEY }}
+        DD_APPSECRET: ${{ secrets.DD_APPSECRET }}
+        DD_NOTIFY_LIST: ${{ secrets.DD_NOTIFY_LIST }}
+        DD_API_TOKEN: ${{ secrets.DD_API_TOKEN }}
+        DD_API_SEND: ${{ secrets.DD_API_SEND }}
+      run: |
+        sudo pip3 install paho_mqtt gitpython requests
+        cd tools
+        if [ "$STATUS" = "failure" ];then python3 ciNotify.py $MQTTADDR $MQTTPORT $MQTTTOPIC "https://github.com/openLuat/LuatOS/actions/runs/$GITHUB_RUN_ID" "LuatOS-ESP32-IDF5" "$DD_APPKEY" "$DD_APPSECRET" "$DD_NOTIFY_LIST" "$DD_API_TOKEN" "$DD_API_SEND"; fi

+ 3 - 2
README.md

@@ -6,9 +6,10 @@
 
 
 [![air101](https://pg.air32.cn/openLuat/LuatOS/actions/workflows/air101.yml/badge.svg)](https://nightly.link/openLuat/LuatOS/workflows/air101/master)
 [![air101](https://pg.air32.cn/openLuat/LuatOS/actions/workflows/air101.yml/badge.svg)](https://nightly.link/openLuat/LuatOS/workflows/air101/master)
 [![air105](https://pg.air32.cn/openLuat/LuatOS/actions/workflows/air105.yml/badge.svg)](https://nightly.link/openLuat/LuatOS/workflows/air105/master)
 [![air105](https://pg.air32.cn/openLuat/LuatOS/actions/workflows/air105.yml/badge.svg)](https://nightly.link/openLuat/LuatOS/workflows/air105/master)
-[![esp32c3](https://pg.air32.cn/openLuat/LuatOS/actions/workflows/esp32c3.yml/badge.svg)](https://nightly.link/openLuat/LuatOS/workflows/esp32c3/master)
+[![esp32c3](https://pg.air32.cn/openLuat/LuatOS/actions/workflows/esp32c3-idf5.yml/badge.svg)](https://nightly.link/openLuat/LuatOS/workflows/esp32c3-idf5/master)
 [![win32](https://pg.air32.cn/openLuat/LuatOS/actions/workflows/win32.yml/badge.svg)](https://nightly.link/openLuat/LuatOS/workflows/win32/master)
 [![win32](https://pg.air32.cn/openLuat/LuatOS/actions/workflows/win32.yml/badge.svg)](https://nightly.link/openLuat/LuatOS/workflows/win32/master)
 [![linux](https://pg.air32.cn/openLuat/LuatOS/actions/workflows/linux.yml/badge.svg)](https://nightly.link/openLuat/LuatOS/workflows/linux/master)
 [![linux](https://pg.air32.cn/openLuat/LuatOS/actions/workflows/linux.yml/badge.svg)](https://nightly.link/openLuat/LuatOS/workflows/linux/master)
+![Build Status](http://luat.papapoi.com:23380/api/badges/openLuat/LuatOS/status.svg)
 
 
 LuatOS : Powerful embedded Lua Engine for IoT devices, with many components and low memory requirements (16K RAM, 128K Flash)
 LuatOS : Powerful embedded Lua Engine for IoT devices, with many components and low memory requirements (16K RAM, 128K Flash)
 
 
@@ -16,7 +17,7 @@ LuatOS : Powerful embedded Lua Engine for IoT devices, with many components and
 
 
 ## 快速入门
 ## 快速入门
 
 
-1. 使用或购买支持的开发板 - [Air101](https://item.taobao.com/item.htm?id=655145668811)/[Air103](https://item.taobao.com/item.htm?id=662164666516)/[Air105](https://item.taobao.com/item.htm?id=665811924219)/[ESP32C3](https://item.taobao.com/item.htm?id=666974425430)
+1. 使用或购买支持的开发板 - [Air101](https://luat.taobao.com)/[Air103](https://luat.taobao.com)/[Air105](luat.taobao.com)/[ESP32C3](luat.taobao.com)
 2. 掌握[刷机](https://wiki.luatos.com/boardGuide/flash.html)
 2. 掌握[刷机](https://wiki.luatos.com/boardGuide/flash.html)
 3. 尝试[各种demo](https://gitee.com/openLuat/LuatOS/tree/master/demo), 浏览[API](https://wiki.luatos.com/api/index.html), [30分钟入门lua语法(视频)](https://www.bilibili.com/video/BV1vf4y1L7Rb?spm_id_from=333.999.0.0)
 3. 尝试[各种demo](https://gitee.com/openLuat/LuatOS/tree/master/demo), 浏览[API](https://wiki.luatos.com/api/index.html), [30分钟入门lua语法(视频)](https://www.bilibili.com/video/BV1vf4y1L7Rb?spm_id_from=333.999.0.0)
 4. 愉快地写业务代码
 4. 愉快地写业务代码

+ 6 - 7
README_FULL.md

@@ -4,13 +4,12 @@
 [![fork](https://gitee.com/openLuat/LuatOS/badge/fork.svg?theme=gvp)](https://gitee.com/openLuat/LuatOS/members)
 [![fork](https://gitee.com/openLuat/LuatOS/badge/fork.svg?theme=gvp)](https://gitee.com/openLuat/LuatOS/members)
 [![license](https://img.shields.io/github/license/openLuat/LuatOS)](/LICENSE)
 [![license](https://img.shields.io/github/license/openLuat/LuatOS)](/LICENSE)
 
 
-[![air101](https://github.com/openLuat/LuatOS/actions/workflows/air101.yml/badge.svg)](https://nightly.link/openLuat/LuatOS/workflows/air101/master)
-[![air105](https://github.com/openLuat/LuatOS/actions/workflows/air105.yml/badge.svg)](https://nightly.link/openLuat/LuatOS/workflows/air105/master)
-[![esp32c3](https://github.com/openLuat/LuatOS/actions/workflows/esp32c3.yml/badge.svg)](https://nightly.link/openLuat/LuatOS/workflows/esp32c3/master)
-[![air100st](https://github.com/openLuat/LuatOS/actions/workflows/air100st.yml/badge.svg)](https://nightly.link/openLuat/LuatOS/workflows/air100st/master)
-[![air640w](https://github.com/openLuat/LuatOS/actions/workflows/air640w.yml/badge.svg)](https://nightly.link/openLuat/LuatOS/workflows/air640w/master)
-[![win32](https://github.com/openLuat/LuatOS/actions/workflows/win32.yml/badge.svg)](https://nightly.link/openLuat/LuatOS/workflows/win32/master)
-[![linux](https://github.com/openLuat/LuatOS/actions/workflows/linux.yml/badge.svg)](https://nightly.link/openLuat/LuatOS/workflows/linux/master)
+[![air101](https://pg.air32.cn/openLuat/LuatOS/actions/workflows/air101.yml/badge.svg)](https://nightly.link/openLuat/LuatOS/workflows/air101/master)
+[![air105](https://pg.air32.cn/openLuat/LuatOS/actions/workflows/air105.yml/badge.svg)](https://nightly.link/openLuat/LuatOS/workflows/air105/master)
+[![esp32c3](https://pg.air32.cn/openLuat/LuatOS/actions/workflows/esp32c3-idf5.yml/badge.svg)](https://nightly.link/openLuat/LuatOS/workflows/esp32c3-idf5/master)
+[![win32](https://pg.air32.cn/openLuat/LuatOS/actions/workflows/win32.yml/badge.svg)](https://nightly.link/openLuat/LuatOS/workflows/win32/master)
+[![linux](https://pg.air32.cn/openLuat/LuatOS/actions/workflows/linux.yml/badge.svg)](https://nightly.link/openLuat/LuatOS/workflows/linux/master)
+![Build Status](http://luat.papapoi.com:23380/api/badges/openLuat/LuatOS/status.svg)
 
 
 LuatOS-SoC是一款实时操作系统,用户编写Lua代码就可完成各种功能, 仅需极少的内存和Flash空间
 LuatOS-SoC是一款实时操作系统,用户编写Lua代码就可完成各种功能, 仅需极少的内存和Flash空间
 
 

+ 1 - 1
components/epaper/EPD_7in5bc.c

@@ -278,7 +278,7 @@ void EPD_7IN5BC_Display(const UBYTE *blackimage, const UBYTE *ryimage)
 
 
 void EPD_7IN5BC_DisplayHalfScreen(const UBYTE *blackimage, const UBYTE *ryimage)
 void EPD_7IN5BC_DisplayHalfScreen(const UBYTE *blackimage, const UBYTE *ryimage)
 {
 {
-    UBYTE Data_Black, Data_RY, Data;
+    UBYTE Data_Black, Data_RY, Data = 0;
     UDOUBLE i, j, Width, Height;
     UDOUBLE i, j, Width, Height;
     Width = (EPD_7IN5BC_WIDTH % 8 == 0)? (EPD_7IN5BC_WIDTH / 8 ): (EPD_7IN5BC_WIDTH / 8 + 1);
     Width = (EPD_7IN5BC_WIDTH % 8 == 0)? (EPD_7IN5BC_WIDTH / 8 ): (EPD_7IN5BC_WIDTH / 8 + 1);
     Height = EPD_7IN5BC_HEIGHT;
     Height = EPD_7IN5BC_HEIGHT;

+ 29 - 13
components/lua-cjson/lua_cjson.c

@@ -56,6 +56,9 @@
 
 
 #define MIN_OPT_LEVEL 2
 #define MIN_OPT_LEVEL 2
 
 
+#define LUAT_LOG_TAG "json"
+#include "luat_log.h"
+
 //#include <lrodefs.h>
 //#include <lrodefs.h>
 //#include <auxmods.h>
 //#include <auxmods.h>
 
 
@@ -442,6 +445,8 @@ static void json_append_string(lua_State *l, strbuf_t *json, int lindex)
      * If there are any excess pages, they won't be hit anyway.
      * If there are any excess pages, they won't be hit anyway.
      * This gains ~5% speedup. */
      * This gains ~5% speedup. */
     strbuf_ensure_empty_length(json, len * 6 + 2);
     strbuf_ensure_empty_length(json, len * 6 + 2);
+    if (json->is_err)
+        return;
 
 
     strbuf_append_char_unsafe(json, '\"');
     strbuf_append_char_unsafe(json, '\"');
     for (i = 0; i < len; i++) {
     for (i = 0; i < len; i++) {
@@ -588,6 +593,8 @@ static void json_append_number(lua_State *l,
     }
     }
 
 
     strbuf_ensure_empty_length(json, FPCONV_G_FMT_BUFSIZE);
     strbuf_ensure_empty_length(json, FPCONV_G_FMT_BUFSIZE);
+    if (json->is_err)
+        return;
     if (lua_isinteger(l, lindex)) {
     if (lua_isinteger(l, lindex)) {
         len = snprintf_(strbuf_empty_ptr(json), FPCONV_G_FMT_BUFSIZE, "%ld", lua_tointeger(l, lindex));
         len = snprintf_(strbuf_empty_ptr(json), FPCONV_G_FMT_BUFSIZE, "%ld", lua_tointeger(l, lindex));
     }
     }
@@ -698,26 +705,31 @@ static int json_encode(lua_State *l)
     strbuf_t *encode_buf;
     strbuf_t *encode_buf;
     char *json;
     char *json;
     int len;
     int len;
+    int ret;
 
 
     luaL_argcheck(l, lua_gettop(l) == 1, 1, "expected 1 argument");
     luaL_argcheck(l, lua_gettop(l) == 1, 1, "expected 1 argument");
 
 
-    // if (!DEFAULT_ENCODE_KEEP_BUFFER) {
-        /* Use private buffer */
-        encode_buf = &local_encode_buf;
-        strbuf_init(encode_buf, 0);
-    // } else {
-    //     /* Reuse existing buffer */
-    //     encode_buf = &cfg->encode_buf;
-    //     strbuf_reset(encode_buf);
-    // }
+    
+    encode_buf = &local_encode_buf;
+    ret = strbuf_init(encode_buf, 0);
+    if (ret) {
+        LLOGE("json encode out of memory!!!");
+        return 0;
+    }
 
 
     json_append_data(l, 0, encode_buf);
     json_append_data(l, 0, encode_buf);
-    json = strbuf_string(encode_buf, &len);
 
 
-    lua_pushlstring(l, json, len);
+    // check if err
+    if (local_encode_buf.is_err) {
+        LLOGE("json encode failed by memory less");
+        lua_pushnil(l);
+    }
+    else {
+        json = strbuf_string(encode_buf, &len);
+        lua_pushlstring(l, json, len);
+    }
 
 
-    // if (!cfg->encode_keep_buffer)
-        strbuf_free(encode_buf);
+    strbuf_free(encode_buf);
 
 
     return 1;
     return 1;
 }
 }
@@ -1295,6 +1307,10 @@ static int json_decode(lua_State *l)
      * This means we no longer need to do length checks since the decoded
      * This means we no longer need to do length checks since the decoded
      * string must be smaller than the entire json string */
      * string must be smaller than the entire json string */
     json.tmp = strbuf_new(json_len);
     json.tmp = strbuf_new(json_len);
+    if (json.tmp == NULL) {
+        LLOGE("json decode out of memory!");
+        return 0;
+    }
 
 
     json_next_token(&json, &token);
     json_next_token(&json, &token);
     json_process_value(l, &json, &token);
     json_process_value(l, &json, &token);

+ 32 - 121
components/lua-cjson/strbuf.c

@@ -42,13 +42,7 @@
 #define L_FREE  luat_heap_free
 #define L_FREE  luat_heap_free
 #define L_REALLOC  luat_heap_realloc
 #define L_REALLOC  luat_heap_realloc
 
 
-static void die(const char *fmt, ...)
-{
-    LLOGD("%s", fmt);
-    exit(-1);
-}
-
-void strbuf_init(strbuf_t *s, int len)
+int strbuf_init(strbuf_t *s, int len)
 {
 {
     int size;
     int size;
 
 
@@ -62,25 +56,32 @@ void strbuf_init(strbuf_t *s, int len)
     s->length = 0;
     s->length = 0;
     s->increment = STRBUF_DEFAULT_INCREMENT;
     s->increment = STRBUF_DEFAULT_INCREMENT;
     s->dynamic = 0;
     s->dynamic = 0;
-    s->reallocs = 0;
-    s->debug = 0;
+    s->is_err = 0;
+    // s->reallocs = 0;
+    // s->debug = 0;
 
 
     s->buf = (char *)L_MALLOC(size);
     s->buf = (char *)L_MALLOC(size);
     if (!s->buf)
     if (!s->buf)
-        die("Out of memory");
+        return -1;
 
 
     strbuf_ensure_null(s);
     strbuf_ensure_null(s);
+    return 0;
 }
 }
 
 
 strbuf_t *strbuf_new(int len)
 strbuf_t *strbuf_new(int len)
 {
 {
     strbuf_t *s;
     strbuf_t *s;
+    int ret = 0;
 
 
     s = (strbuf_t *)L_MALLOC(sizeof(strbuf_t));
     s = (strbuf_t *)L_MALLOC(sizeof(strbuf_t));
     if (!s)
     if (!s)
-        die("Out of memory");
+        return NULL;
 
 
-    strbuf_init(s, len);
+    ret = strbuf_init(s, len);
+    if (ret) {
+        L_FREE(s);
+        return NULL;
+    }
 
 
     /* Dynamic strbuf allocation / deallocation */
     /* Dynamic strbuf allocation / deallocation */
     s->dynamic = 1;
     s->dynamic = 1;
@@ -88,29 +89,11 @@ strbuf_t *strbuf_new(int len)
     return s;
     return s;
 }
 }
 
 
-void strbuf_set_increment(strbuf_t *s, int increment)
-{
-    /* Increment > 0:  Linear buffer growth rate
-     * Increment < -1: Exponential buffer growth rate */
-    if (increment == 0 || increment == -1)
-        die("BUG: Invalid string increment");
-
-    s->increment = increment;
-}
-
-static inline void debug_stats(strbuf_t *s)
-{
-    if (s->debug) {
-        fprintf(stderr, "strbuf(%lx) reallocs: %d, length: %d, size: %d\n",
-                (long)s, s->reallocs, s->length, s->size);
-    }
-}
-
 /* If strbuf_t has not been dynamically allocated, strbuf_free() can
 /* If strbuf_t has not been dynamically allocated, strbuf_free() can
  * be called any number of times strbuf_init() */
  * be called any number of times strbuf_init() */
 void strbuf_free(strbuf_t *s)
 void strbuf_free(strbuf_t *s)
 {
 {
-    debug_stats(s);
+    // debug_stats(s);
 
 
     if (s->buf) {
     if (s->buf) {
         L_FREE (s->buf);
         L_FREE (s->buf);
@@ -120,30 +103,12 @@ void strbuf_free(strbuf_t *s)
         L_FREE (s);
         L_FREE (s);
 }
 }
 
 
-char *strbuf_free_to_string(strbuf_t *s, int *len)
-{
-    char *buf;
-
-    debug_stats(s);
-
-    strbuf_ensure_null(s);
-
-    buf = s->buf;
-    if (len)
-        *len = s->length;
-
-    if (s->dynamic)
-        L_FREE (s);
-
-    return buf;
-}
-
 static int calculate_new_size(strbuf_t *s, int len)
 static int calculate_new_size(strbuf_t *s, int len)
 {
 {
     int reqsize, newsize;
     int reqsize, newsize;
 
 
-    if (len <= 0)
-        die("BUG: Invalid strbuf length requested");
+    // if (len <= 0)
+    //     die("BUG: Invalid strbuf length requested");
 
 
     /* Ensure there is room for optional NULL termination */
     /* Ensure there is room for optional NULL termination */
     reqsize = len + 1;
     reqsize = len + 1;
@@ -153,16 +118,11 @@ static int calculate_new_size(strbuf_t *s, int len)
         return reqsize;
         return reqsize;
 
 
     newsize = s->size;
     newsize = s->size;
-    if (s->increment < 0) {
-        /* Exponential sizing */
-        while (newsize < reqsize)
-            newsize *= -s->increment;
-    } else {
-        /* Linear sizing */
-        newsize = ((newsize + s->increment - 1) / s->increment) * s->increment;
+    if (reqsize - s->size < 1023) {
+        reqsize = s->size + 1023;
     }
     }
 
 
-    return newsize;
+    return reqsize + 1;
 }
 }
 
 
 
 
@@ -171,24 +131,28 @@ static int calculate_new_size(strbuf_t *s, int len)
 void strbuf_resize(strbuf_t *s, int len)
 void strbuf_resize(strbuf_t *s, int len)
 {
 {
     int newsize;
     int newsize;
+    void* ptr;
+
+    if (s->is_err)
+        return;
 
 
     newsize = calculate_new_size(s, len);
     newsize = calculate_new_size(s, len);
 
 
-    if (s->debug > 1) {
-        fprintf(stderr, "strbuf(%lx) resize: %d => %d\n",
-                (long)s, s->size, newsize);
+    ptr = (char *)L_REALLOC(s->buf, newsize);
+    if (ptr == NULL) {
+        s->is_err = 1;
+    }
+    else {
+        s->size = newsize;
+        s->buf = ptr;
     }
     }
-
-    s->size = newsize;
-    s->buf = (char *)L_REALLOC(s->buf, s->size);
-    if (!s->buf)
-        die("Out of memory");
-    s->reallocs++;
 }
 }
 
 
 void strbuf_append_string(strbuf_t *s, const char *str)
 void strbuf_append_string(strbuf_t *s, const char *str)
 {
 {
     int space, i;
     int space, i;
+    if (s->is_err)
+        return;
 
 
     space = strbuf_empty_length(s);
     space = strbuf_empty_length(s);
 
 
@@ -203,56 +167,3 @@ void strbuf_append_string(strbuf_t *s, const char *str)
         space--;
         space--;
     }
     }
 }
 }
-
-/* strbuf_append_fmt() should only be used when an upper bound
- * is known for the output string. */
-void strbuf_append_fmt(strbuf_t *s, int len, const char *fmt, ...)
-{
-    va_list arg;
-    int fmt_len;
-
-    strbuf_ensure_empty_length(s, len);
-
-    va_start(arg, fmt);
-    fmt_len = vsnprintf(s->buf + s->length, len, fmt, arg);
-    va_end(arg);
-
-    if (fmt_len < 0)
-        die("BUG: Unable to convert number");  /* This should never happen.. */
-
-    s->length += fmt_len;
-}
-
-/* strbuf_append_fmt_retry() can be used when the there is no known
- * upper bound for the output string. */
-void strbuf_append_fmt_retry(strbuf_t *s, const char *fmt, ...)
-{
-    va_list arg;
-    int fmt_len, try;
-    int empty_len;
-
-    /* If the first attempt to append fails, resize the buffer appropriately
-     * and try again */
-    for (try = 0; ; try++) {
-        va_start(arg, fmt);
-        /* Append the new formatted string */
-        /* fmt_len is the length of the string required, excluding the
-         * trailing NULL */
-        empty_len = strbuf_empty_length(s);
-        /* Add 1 since there is also space to store the terminating NULL. */
-        fmt_len = vsnprintf(s->buf + s->length, empty_len + 1, fmt, arg);
-        va_end(arg);
-
-        if (fmt_len <= empty_len)
-            break;  /* SUCCESS */
-        if (try > 0)
-            die("BUG: length of formatted string changed");
-
-        strbuf_resize(s, s->length + fmt_len);
-    }
-
-    s->length += fmt_len;
-}
-
-/* vi:ai et sw=4 ts=4:
- */

+ 9 - 3
components/lua-cjson/strbuf.h

@@ -39,8 +39,9 @@ typedef struct {
     int length;
     int length;
     int increment;
     int increment;
     int dynamic;
     int dynamic;
-    int reallocs;
-    int debug;
+    int is_err;
+    // int reallocs;
+    // int debug;
 } strbuf_t;
 } strbuf_t;
 
 
 #ifndef STRBUF_DEFAULT_SIZE
 #ifndef STRBUF_DEFAULT_SIZE
@@ -52,7 +53,7 @@ typedef struct {
 
 
 /* Initialise */
 /* Initialise */
 extern strbuf_t *strbuf_new(int len);
 extern strbuf_t *strbuf_new(int len);
-extern void strbuf_init(strbuf_t *s, int len);
+extern int strbuf_init(strbuf_t *s, int len);
 extern void strbuf_set_increment(strbuf_t *s, int increment);
 extern void strbuf_set_increment(strbuf_t *s, int increment);
 
 
 /* Release */
 /* Release */
@@ -118,29 +119,34 @@ static inline int strbuf_length(strbuf_t *s)
 static inline void strbuf_append_char(strbuf_t *s, const char c)
 static inline void strbuf_append_char(strbuf_t *s, const char c)
 {
 {
     strbuf_ensure_empty_length(s, 1);
     strbuf_ensure_empty_length(s, 1);
+    if (s->is_err) return;
     s->buf[s->length++] = c;
     s->buf[s->length++] = c;
 }
 }
 
 
 static inline void strbuf_append_char_unsafe(strbuf_t *s, const char c)
 static inline void strbuf_append_char_unsafe(strbuf_t *s, const char c)
 {
 {
+    if (s->is_err) return;
     s->buf[s->length++] = c;
     s->buf[s->length++] = c;
 }
 }
 
 
 static inline void strbuf_append_mem(strbuf_t *s, const char *c, int len)
 static inline void strbuf_append_mem(strbuf_t *s, const char *c, int len)
 {
 {
     strbuf_ensure_empty_length(s, len);
     strbuf_ensure_empty_length(s, len);
+    if (s->is_err) return;
     memcpy(s->buf + s->length, c, len);
     memcpy(s->buf + s->length, c, len);
     s->length += len;
     s->length += len;
 }
 }
 
 
 static inline void strbuf_append_mem_unsafe(strbuf_t *s, const char *c, int len)
 static inline void strbuf_append_mem_unsafe(strbuf_t *s, const char *c, int len)
 {
 {
+    if (s->is_err) return;
     memcpy(s->buf + s->length, c, len);
     memcpy(s->buf + s->length, c, len);
     s->length += len;
     s->length += len;
 }
 }
 
 
 static inline void strbuf_ensure_null(strbuf_t *s)
 static inline void strbuf_ensure_null(strbuf_t *s)
 {
 {
+    if (s->is_err) return;
     s->buf[s->length] = 0;
     s->buf[s->length] = 0;
 }
 }
 
 

+ 13 - 13
components/lvgl/binding/luat_lv_fs.c

@@ -12,19 +12,19 @@ static bool luat_lv_fs_ready(struct _lv_fs_drv_t * drv);
 
 
 static lv_fs_res_t luat_lv_fs_open(struct _lv_fs_drv_t * drv, void * file_p, const char * path, lv_fs_mode_t mode);
 static lv_fs_res_t luat_lv_fs_open(struct _lv_fs_drv_t * drv, void * file_p, const char * path, lv_fs_mode_t mode);
 static lv_fs_res_t luat_lv_fs_close(struct _lv_fs_drv_t * drv, void * file_p);
 static lv_fs_res_t luat_lv_fs_close(struct _lv_fs_drv_t * drv, void * file_p);
-static lv_fs_res_t luat_lv_fs_remove(struct _lv_fs_drv_t * drv, const char * fn);
+// static lv_fs_res_t luat_lv_fs_remove(struct _lv_fs_drv_t * drv, const char * fn);
 static lv_fs_res_t luat_lv_fs_read(struct _lv_fs_drv_t * drv, void * file_p, void * buf, uint32_t btr, uint32_t * br);
 static lv_fs_res_t luat_lv_fs_read(struct _lv_fs_drv_t * drv, void * file_p, void * buf, uint32_t btr, uint32_t * br);
-static lv_fs_res_t luat_lv_fs_write(struct _lv_fs_drv_t * drv, void * file_p, const void * buf, uint32_t btw, uint32_t * bw);
+// static lv_fs_res_t luat_lv_fs_write(struct _lv_fs_drv_t * drv, void * file_p, const void * buf, uint32_t btw, uint32_t * bw);
 static lv_fs_res_t luat_lv_fs_seek(struct _lv_fs_drv_t * drv, void * file_p, uint32_t pos);
 static lv_fs_res_t luat_lv_fs_seek(struct _lv_fs_drv_t * drv, void * file_p, uint32_t pos);
 static lv_fs_res_t luat_lv_fs_tell(struct _lv_fs_drv_t * drv, void * file_p, uint32_t * pos_p);
 static lv_fs_res_t luat_lv_fs_tell(struct _lv_fs_drv_t * drv, void * file_p, uint32_t * pos_p);
-static lv_fs_res_t luat_lv_fs_trunc(struct _lv_fs_drv_t * drv, void * file_p);
+// static lv_fs_res_t luat_lv_fs_trunc(struct _lv_fs_drv_t * drv, void * file_p);
 static lv_fs_res_t luat_lv_fs_size(struct _lv_fs_drv_t * drv, void * file_p, uint32_t * size_p);
 static lv_fs_res_t luat_lv_fs_size(struct _lv_fs_drv_t * drv, void * file_p, uint32_t * size_p);
-static lv_fs_res_t luat_lv_fs_rename(struct _lv_fs_drv_t * drv, const char * oldname, const char * newname);
-static lv_fs_res_t luat_lv_fs_free_space(struct _lv_fs_drv_t * drv, uint32_t * total_p, uint32_t * free_p);
+// static lv_fs_res_t luat_lv_fs_rename(struct _lv_fs_drv_t * drv, const char * oldname, const char * newname);
+// static lv_fs_res_t luat_lv_fs_free_space(struct _lv_fs_drv_t * drv, uint32_t * total_p, uint32_t * free_p);
 
 
-static lv_fs_res_t luat_lv_fs_dir_open(struct _lv_fs_drv_t * drv, void * rddir_p, const char * path);
-static lv_fs_res_t luat_lv_fs_dir_read(struct _lv_fs_drv_t * drv, void * rddir_p, char * fn);
-static lv_fs_res_t luat_lv_fs_dir_close(struct _lv_fs_drv_t * drv, void * rddir_p);
+// static lv_fs_res_t luat_lv_fs_dir_open(struct _lv_fs_drv_t * drv, void * rddir_p, const char * path);
+// static lv_fs_res_t luat_lv_fs_dir_read(struct _lv_fs_drv_t * drv, void * rddir_p, char * fn);
+// static lv_fs_res_t luat_lv_fs_dir_close(struct _lv_fs_drv_t * drv, void * rddir_p);
 
 
 void luat_lv_fs_init(void) {
 void luat_lv_fs_init(void) {
     lv_fs_drv_t fs_drv = {
     lv_fs_drv_t fs_drv = {
@@ -34,7 +34,7 @@ void luat_lv_fs_init(void) {
         .ready_cb = luat_lv_fs_ready,
         .ready_cb = luat_lv_fs_ready,
         .open_cb = luat_lv_fs_open,
         .open_cb = luat_lv_fs_open,
         .close_cb = luat_lv_fs_close,
         .close_cb = luat_lv_fs_close,
-        .remove_cb = luat_lv_fs_remove,
+        .remove_cb = NULL,
         .read_cb = luat_lv_fs_read,
         .read_cb = luat_lv_fs_read,
         .write_cb = NULL,
         .write_cb = NULL,
         .seek_cb = luat_lv_fs_seek,
         .seek_cb = luat_lv_fs_seek,
@@ -85,10 +85,10 @@ static lv_fs_res_t luat_lv_fs_close(struct _lv_fs_drv_t * drv, void * file_p) {
     return LV_FS_RES_NOT_EX;
     return LV_FS_RES_NOT_EX;
 }
 }
 
 
-static lv_fs_res_t luat_lv_fs_remove(struct _lv_fs_drv_t * drv, const char * fn) {
-    luat_fs_remove(fn);
-    return LV_FS_RES_OK;
-}
+// static lv_fs_res_t luat_lv_fs_remove(struct _lv_fs_drv_t * drv, const char * fn) {
+//     luat_fs_remove(fn);
+//     return LV_FS_RES_OK;
+// }
 
 
 static lv_fs_res_t luat_lv_fs_read(struct _lv_fs_drv_t * drv, void * file_p, void * buf, uint32_t btr, uint32_t * br) {
 static lv_fs_res_t luat_lv_fs_read(struct _lv_fs_drv_t * drv, void * file_p, void * buf, uint32_t btr, uint32_t * br) {
     file_t* fp = file_p;
     file_t* fp = file_p;

+ 0 - 80
components/minmea/luat_lib_libgnss.c

@@ -564,81 +564,6 @@ static int l_libgnss_get_gga(lua_State* L) {
     return 1;
     return 1;
 }
 }
 
 
-
-//-----------------------------------------------------
-// For Air530Z
-//-----------------------------------------------------
-
-uint8_t air530z_uart_id = 2;
-
-/**
-设置gps串口id(For Air530Z)
-@api libgnss.air530z_setup(air530z_uart_id)
-@number air530z_uart_id 串口id 默认串口2
-@usage
-libgnss.air530z_setup(2)
- */
-static int l_libgnss_air530_setup(lua_State *L) {
-    air530z_uart_id = luaL_checkinteger(L, 1);
-    return 0;
-}
-
-/**
-保存配置信息(For Air530Z)
-@api libgnss.air530z_saveconf()
-@usage
-libgnss.air530z_saveconf()
- */
-static int l_libgnss_air530_saveconf(lua_State *L) {
-    luat_uart_write(air530z_uart_id, "$PCAS00*01\r\n", strlen("$PCAS00*01\r\n"));
-    return 0;
-}
-
-/**
-设置通讯波特率(For Air530Z)
-@api libgnss.air530z_setbandrate(bandrate)
-@number table 波特率
-@usage
-libgnss.air530z_setbandrate(115200)
- */
-static int l_libgnss_air530_setbandrate(lua_State *L) {
-    /*
-0=4800bps
-1=9600bps
-2=19200bps
-3=38400bps
-4=57600bps
-5=115200bps
-    */
-    int bandrate = luaL_checkinteger(L, 1);
-    switch (bandrate)
-    {
-    case 4800:
-        luat_uart_write(air530z_uart_id, "$PCAS01,0*1C\r\n", strlen("$PCAS01,0*1C\r\n"));
-        break;
-    case 9600:
-        luat_uart_write(air530z_uart_id, "$PCAS01,1*1D\r\n", strlen("$PCAS01,1*1D\r\n"));
-        break;
-    case 19200:
-        luat_uart_write(air530z_uart_id, "$PCAS01,2*1E\r\n", strlen("$PCAS01,2*1E\r\n"));
-        break;
-    case 38400:
-        luat_uart_write(air530z_uart_id, "$PCAS01,3*1F\r\n", strlen("$PCAS01,3*1F\r\n"));
-        break;
-    case 57600:
-        luat_uart_write(air530z_uart_id, "$PCAS01,4*18\r\n", strlen("$PCAS01,4*18\r\n"));
-        break;
-    case 115200:
-        luat_uart_write(air530z_uart_id, "$PCAS01,5*19\r\n", strlen("$PCAS01,5*19\r\n"));
-        break;
-    default:
-        LLOGD("fallback to default 9600");
-        luat_uart_write(air530z_uart_id, "$PCAS01,1*1D\r\n", strlen("$PCAS01,1*1D\r\n"));
-        break;
-    }
-    return 0;
-}
-
 #include "rotable2.h"
 #include "rotable2.h"
 static const rotable_Reg_t reg_libgnss[] =
 static const rotable_Reg_t reg_libgnss[] =
 {
 {
@@ -653,11 +578,6 @@ static const rotable_Reg_t reg_libgnss[] =
     { "getZda", ROREG_FUNC(l_libgnss_get_zda)},
     { "getZda", ROREG_FUNC(l_libgnss_get_zda)},
     { "debug",  ROREG_FUNC(l_libgnss_debug)},
     { "debug",  ROREG_FUNC(l_libgnss_debug)},
 
 
-    //-----------------------------------------
-    { "air530z_setup", ROREG_FUNC(l_libgnss_air530_setup)},
-    { "air530z_saveconf", ROREG_FUNC(l_libgnss_air530_saveconf)},
-    { "air530z_setbandrate", ROREG_FUNC(l_libgnss_air530_setbandrate)},
-
 	{ NULL,      ROREG_INT(0)}
 	{ NULL,      ROREG_INT(0)}
 };
 };
 
 

+ 60 - 0
components/network/httpsrv/inc/luat_httpsrv.h

@@ -0,0 +1,60 @@
+#include "luat_base.h"
+
+
+typedef struct luat_httpsrv_ctx
+{
+    uint16_t port;
+    uint16_t https;
+    char static_path[32];
+    int lua_ref_id;
+    int server_fd;
+    void* userdata;
+}luat_httpsrv_ctx_t;
+
+
+typedef struct http_code_str
+{
+    int code;
+    const char* msg;
+}http_code_str_t;
+
+static const http_code_str_t http_codes[] = {
+    {200, "OK"},
+    {302, "Found"},
+    {400, "Bad Request"},
+    {401, "Unauthorized"},
+    {403, "Forbidden"},
+    {404, "Not Found"},
+    {500, "Internal Server Error"},
+    {0, ""}
+};
+
+
+typedef struct ct_reg
+{
+    const char* suff;
+    const char* value;
+}ct_reg_t;
+
+static const ct_reg_t ct_regs[] = {
+    {"html",    "text/html; charset=utf-8"},
+    {"txt",     "text/txt; charset=utf-8"},
+    {"xml",     "text/xml; charset=utf-8"},
+    {"jpg",      "image/jpeg"},
+    {"png",     "image/png"},
+    {"gif",     "image/gif"},
+    {"svg",     "svg+xml"},
+    {"json",    "application/json; charset=utf-8"},
+    {"js",      "application/javascript; charset=utf-8"},
+    {"css",     "text/css"},
+    {"wav",     "audio/wave"},
+    {"ogg",     "audio/ogg"},
+    {"wav",     "audio/wave"},
+    {"webm",    "video/webm"},
+    {"mp4",     "video/mpeg4"},
+    {"bin",     "application/octet-stream"},
+};
+
+
+int luat_httpsrv_stop(int port);
+int luat_httpsrv_start(luat_httpsrv_ctx_t* ctx);

+ 87 - 0
components/network/httpsrv/src/luat_lib_httpsrv.c

@@ -0,0 +1,87 @@
+/*
+@module  httpsrv
+@summary http服务端
+@version 1.0
+@date    2022.010.15
+@demo network
+*/
+
+#include "luat_base.h"
+#include "luat_httpsrv.h"
+
+#define LUAT_LOG_TAG "httpsrv"
+#include "luat_log.h"
+
+/*
+启动并监听一个http端口
+@api httpsrv.start(port, func)
+@int 端口号
+@function 回调函数
+@return bool 成功返回true, 否则返回false
+@usage
+
+-- 监听80端口
+httpsrv.start(80, function(client, method, uri, headers, body)
+    -- method 是字符串, 例如 GET POST PUT DELETE
+    -- uri 也是字符串 例如 / /api/abc
+    -- headers table类型
+    -- body 字符串
+    log.info("httpsrv", method, uri, json.encode(headers), body)
+    if uri == "/led/1" then
+        LEDA(1)
+        return 200, {}, "ok"
+    elseif uri == "/led/0" then
+        LEDA(0)
+        return 200, {}, "ok"
+    end
+    -- 返回值的约定 code, headers, body
+    -- 若没有返回值, 则默认 404, {} ,""
+    return 404, {}, "Not Found" .. uri
+end)
+-- 关于静态文件
+-- 情况1: / , 映射为 /index.html
+-- 情况2: /abc.html , 先查找 /abc.html, 不存在的话查找 /abc.html.gz
+-- 若gz存在, 会自动以压缩文件进行响应, 绝大部分浏览器支持.
+-- 当前默认查找 /luadb/xxx 下的文件,暂不可配置
+*/
+static int l_httpsrv_start(lua_State *L) {
+    int port = luaL_checkinteger(L, 1);
+    if (!lua_isfunction(L, 2)) {
+        LLOGW("httpsrv need callback function!!!");
+        return 0;
+    }
+    lua_pushvalue(L, 2);
+    int lua_ref_id = luaL_ref(L, LUA_REGISTRYINDEX);
+    luat_httpsrv_ctx_t ctx = {
+        .port = port,
+        .lua_ref_id = lua_ref_id
+    };
+    int ret = luat_httpsrv_start(&ctx);
+    lua_pushboolean(L, ret == 0 ? 1 : 0);
+    return 1;
+}
+
+/*
+停止http服务
+@api httpsrv.stop(port)
+@int 端口号
+@return nil 当前无返回值
+*/
+static int l_httpsrv_stop(lua_State *L) {
+    int port = luaL_checkinteger(L, 1);
+    luat_httpsrv_stop(port);
+    return 0;
+}
+
+#include "rotable2.h"
+static const rotable_Reg_t reg_httpsrv[] =
+{
+    {"start",        ROREG_FUNC(l_httpsrv_start) },
+    {"stop",         ROREG_FUNC(l_httpsrv_stop) },
+	{ NULL,          ROREG_INT(0) }
+};
+
+LUAMOD_API int luaopen_httpsrv( lua_State *L ) {
+    luat_newlib2(L, reg_httpsrv);
+    return 1;
+}

+ 34 - 0
components/nimble/inc/luat_nimble.h

@@ -0,0 +1,34 @@
+
+#ifndef LUAT_NUMBLE_H
+#define LUAT_NUMBLE_H
+#include "luat_base.h"
+#include "luat_msgbus.h"
+
+
+/** Bluetooth Adapter State */
+typedef enum
+{
+    BT_STATE_OFF,
+    BT_STATE_ON,
+    BT_STATE_CONNECTED,
+    BT_STATE_DISCONNECT,
+} bt_state_t;
+
+
+typedef enum
+{
+    BT_MODE_BLE_SERVER,
+    BT_MODE_BLE_CLIENT,
+    BT_MODE_BLE_BEACON,
+    BT_MODE_BLE_MESH,
+} bt_mode_t;
+
+int luat_nimble_trace_level(int level);
+
+int luat_nimble_init(uint8_t uart_idx, char* name, int mode);
+int luat_nimble_deinit();
+
+int luat_nimble_server_send(int id, char* data, size_t len);
+
+#endif
+

+ 179 - 0
components/nimble/src/luat_lib_nimble.c

@@ -0,0 +1,179 @@
+/*
+@module  nimble
+@summary 蓝牙BLE库(nimble版)
+@version 1.0
+@date    2022.10.21
+@demo    nimble
+@usage
+-- 本库当前支持Air101/Air103/ESP32/ESP32C3
+-- 理论上支持ESP32C2/ESP32S2/ESP32S3,但尚未测试
+
+-- 本库当前仅支持BLE Peripheral, 其他模式待添加
+sys.taskInit(function()
+    -- 初始化nimble, 因为当仅支持作为主机,也没有其他配置项
+    nimble.init("LuatOS-Wendal") -- 选取一个蓝牙设备名称
+    sys.wait(1000)
+
+    --local data = string.char(0x5A, 0xA5, 0x12, 0x34, 0x56)
+    local data = "1234567890"
+    while 1 do
+        sys.wait(5000)
+        -- Central端建立连接并订阅后, 可上报数据
+        nimble.send_msg(1, 0, data)
+    end
+end
+sys.subscribe("BLE_GATT_WRITE_CHR", function(info, data)
+    -- Central端建立连接后, 可往设备写入数据
+    log.info("ble", "Data Got", data:toHex())
+end)
+
+-- 配合微信小程序 "LuatOS蓝牙调试"
+-- 1. 若开发板无天线, 将手机尽量靠近芯片也能搜到
+-- 2. 该小程序是开源的, 每次write会自动分包
+-- https://gitee.com/openLuat/luatos-miniapps
+*/
+
+#include "luat_base.h"
+#include "luat_msgbus.h"
+#include "luat_malloc.h"
+#include "luat_spi.h"
+
+#include "luat_nimble.h"
+
+#define LUAT_LOG_TAG "nimble"
+#include "luat_log.h"
+
+static uint32_t nimble_mode = 0;
+
+/*
+初始化BLE上下文,开始对外广播/扫描
+@api nimble.init(name)
+@string 蓝牙设备名称,可选,建议填写
+@return bool 成功与否
+@usage
+-- 参考 demo/nimble
+*/
+static int l_nimble_init(lua_State* L) {
+    int rc = 0;
+    size_t len = 0;
+    const char* name = NULL;
+    if(lua_isstring(L, 1)) {
+        name = luaL_checklstring(L, 1, &len);
+    }
+    LLOGD("init name %s mode %d", name, nimble_mode);
+    rc = luat_nimble_init(0xFF, name, nimble_mode);
+    if (rc) {
+        lua_pushboolean(L, 0);
+        lua_pushinteger(L, rc);
+        return 2;
+    }
+    else {
+        lua_pushboolean(L, 1);
+        return 1;
+    }
+}
+
+/*
+关闭BLE上下文
+@api nimble.deinit()
+@return bool 成功与否
+@usage
+-- 仅部分设备支持,当前可能都不支持
+*/
+static int l_nimble_deinit(lua_State* L) {
+    int rc = 0;
+    rc = luat_nimble_deinit();
+    if (rc) {
+        lua_pushboolean(L, 0);
+        lua_pushinteger(L, rc);
+        return 2;
+    }
+    else {
+        lua_pushboolean(L, 1);
+        return 1;
+    }
+}
+
+static int l_nimble_debug(lua_State* L) {
+    int level = 0;
+    // if (lua_gettop(L) > 0)
+    //     level = luat_nimble_trace_level(luaL_checkinteger(L, 1));
+    // else
+    //     level = luat_nimble_trace_level(-1);
+    lua_pushinteger(L, level);
+    return 1;
+}
+
+static int l_nimble_server_init(lua_State* L) {
+    LLOGI("nimble.server_init is removed");
+    return 0;
+}
+
+
+static int l_nimble_server_deinit(lua_State* L) {
+    LLOGI("nimble.server_deinit is removed");
+    return 0;
+}
+
+/*
+发送信息
+@api nimble.send_msg(conn, handle, data)
+@int 连接id, 当前固定填1
+@int 处理id, 当前固定填0
+@string 数据字符串,可包含不可见字符
+@return bool 成功与否
+@usage
+-- 参考 demo/nimble
+*/
+static int l_nimble_send_msg(lua_State *L) {
+    int conn_id = luaL_checkinteger(L, 1);
+    int handle_id = luaL_checkinteger(L, 2);
+    size_t len = 0;
+    const char* data = luaL_checklstring(L, 3, &len);
+    int ret = 0;
+    if (len == 0) {
+        LLOGI("send emtry msg? ignored");
+    }
+    else {
+        ret = luat_nimble_server_send(0, data, len);
+    }
+
+    lua_pushboolean(L, ret == 0 ? 1 : 0);
+    // lua_pushinteger(L, ret);
+    return 1;
+}
+
+#include "rotable2.h"
+static const rotable_Reg_t reg_nimble[] =
+{
+	{ "init",           ROREG_FUNC(l_nimble_init)},
+    { "deinit",         ROREG_FUNC(l_nimble_deinit)},
+    { "debug",          ROREG_FUNC(l_nimble_debug)},
+    { "server_init",    ROREG_FUNC(l_nimble_server_init)},
+    { "server_deinit",  ROREG_FUNC(l_nimble_server_deinit)},
+    { "send_msg",       ROREG_FUNC(l_nimble_send_msg)},
+
+    // 放一些常量
+    { "STATE_OFF",           ROREG_INT(BT_STATE_OFF)},
+    { "STATE_ON",            ROREG_INT(BT_STATE_ON)},
+    { "STATE_CONNECTED",     ROREG_INT(BT_STATE_CONNECTED)},
+    { "STATE_DISCONNECT",    ROREG_INT(BT_STATE_DISCONNECT)},
+
+    // 模式
+    { "MODE_BLE_SERVER",           ROREG_INT(BT_MODE_BLE_SERVER)},
+    { "MODE_BLE_CLIENT",           ROREG_INT(BT_MODE_BLE_CLIENT)},
+    { "MODE_BLE_BEACON",           ROREG_INT(BT_MODE_BLE_BEACON)},
+    { "MODE_BLE_MESH",             ROREG_INT(BT_MODE_BLE_MESH)},
+    { "SERVER",                    ROREG_INT(BT_MODE_BLE_SERVER)},
+    { "CLIENT",                    ROREG_INT(BT_MODE_BLE_CLIENT)},
+    { "BEACON",                    ROREG_INT(BT_MODE_BLE_BEACON)},
+    { "MESH",                      ROREG_INT(BT_MODE_BLE_MESH)},
+
+	{ NULL,             ROREG_INT(0)}
+};
+
+LUAMOD_API int luaopen_nimble( lua_State *L ) {
+    rotable2_newlib(L, reg_nimble);
+    return 1;
+}
+

+ 749 - 0
components/nimble/src/luat_nimble_mode_ble_server.c

@@ -0,0 +1,749 @@
+
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "luat_base.h"
+#if (defined(AIR101) || defined(AIR103))
+#include "FreeRTOS.h"
+#else
+#include "freertos/FreeRTOS.h"
+#endif
+
+#include "host/ble_hs.h"
+#include "host/ble_uuid.h"
+#include "host/util/util.h"
+#include "services/gap/ble_svc_gap.h"
+#include "services/gatt/ble_svc_gatt.h"
+
+#include "luat_msgbus.h"
+#include "luat_malloc.h"
+#include "luat_nimble.h"
+
+/* BLE */
+#include "nimble/nimble_port.h"
+#include "nimble/nimble_port_freertos.h"
+
+/* Heart-rate configuration */
+#define GATT_HRS_UUID                           0x180D
+#define GATT_HRS_MEASUREMENT_UUID               0x2A37
+#define GATT_HRS_BODY_SENSOR_LOC_UUID           0x2A38
+#define GATT_DEVICE_INFO_UUID                   0x180A
+#define GATT_MANUFACTURER_NAME_UUID             0x2A29
+#define GATT_MODEL_NUMBER_UUID                  0x2A24
+
+/** GATT server. */
+#define GATT_SVR_SVC_ALERT_UUID               0x1811
+#define GATT_SVR_CHR_SUP_NEW_ALERT_CAT_UUID   0x2A47
+#define GATT_SVR_CHR_NEW_ALERT                0x2A46
+#define GATT_SVR_CHR_SUP_UNR_ALERT_CAT_UUID   0x2A48
+#define GATT_SVR_CHR_UNR_ALERT_STAT_UUID      0x2A45
+#define GATT_SVR_CHR_ALERT_NOT_CTRL_PT        0x2A44
+
+// extern uint16_t hrs_hrm_handle;
+
+typedef void (*TaskFunction_t)( void * );
+
+struct ble_hs_cfg;
+struct ble_gatt_register_ctxt;
+
+static void gatt_svr_register_cb(struct ble_gatt_register_ctxt *ctxt, void *arg);
+static int gatt_svr_init(void);
+
+static const char *manuf_name = "LuatOS";
+static const char *model_num = "BLE Demo";
+static uint16_t hrs_hrm_handle;
+static uint16_t g_ble_attr_indicate_handle;
+static uint16_t g_ble_attr_write_handle;
+static uint16_t g_ble_conn_handle;
+// extern uint16_t g_ble_state;
+
+#define WM_GATT_SVC_UUID      0xFFF0
+#define WM_GATT_INDICATE_UUID 0xFFF1
+#define WM_GATT_WRITE_UUID    0xFFF2
+#define WM_GATT_NOTIFY_UUID    0xFFF3
+
+
+#define LUAT_LOG_TAG "nimble"
+#include "luat_log.h"
+
+static char selfname[32];
+// extern uint16_t g_ble_conn_handle;
+static uint16_t g_ble_state;
+
+typedef struct ble_write_msg {
+    // uint16_t conn_handle,
+    // uint16_t attr_handle,
+    ble_uuid_t* uuid;
+    uint16_t len;
+    char buff[1];
+}ble_write_msg_t;
+
+static int
+gatt_svr_chr_access_heart_rate(uint16_t conn_handle, uint16_t attr_handle,
+                               struct ble_gatt_access_ctxt *ctxt, void *arg);
+
+static int
+gatt_svr_chr_access_device_info(uint16_t conn_handle, uint16_t attr_handle,
+                                struct ble_gatt_access_ctxt *ctxt, void *arg);
+
+static int
+gatt_svr_chr_access_func(uint16_t conn_handle, uint16_t attr_handle,
+                               struct ble_gatt_access_ctxt *ctxt, void *arg);
+
+static const struct ble_gatt_svc_def gatt_svr_svcs[] = {
+    {
+        /* Service: Heart-rate */
+        .type = BLE_GATT_SVC_TYPE_PRIMARY,
+        .uuid = BLE_UUID16_DECLARE(GATT_HRS_UUID),
+        .characteristics = (struct ble_gatt_chr_def[])
+        { {
+#if 1
+                /* Characteristic: Heart-rate measurement */
+                .uuid = BLE_UUID16_DECLARE(GATT_HRS_MEASUREMENT_UUID),
+                .access_cb = gatt_svr_chr_access_heart_rate,
+                .val_handle = &hrs_hrm_handle,
+                .flags = BLE_GATT_CHR_F_NOTIFY,
+            }, {
+                /* Characteristic: Body sensor location */
+                .uuid = BLE_UUID16_DECLARE(GATT_HRS_BODY_SENSOR_LOC_UUID),
+                .access_cb = gatt_svr_chr_access_heart_rate,
+                .flags = BLE_GATT_CHR_F_READ,
+            }, {
+#endif
+                /* Characteristic: Body sensor location */
+                .uuid = BLE_UUID16_DECLARE(WM_GATT_WRITE_UUID),
+                .val_handle = &g_ble_attr_write_handle,
+                .access_cb = gatt_svr_chr_access_func,
+                .flags = BLE_GATT_CHR_F_WRITE,
+            }, {
+                /* Characteristic: Body sensor location */
+                .uuid = BLE_UUID16_DECLARE(WM_GATT_INDICATE_UUID),
+                .val_handle = &g_ble_attr_indicate_handle,
+                .access_cb = gatt_svr_chr_access_func,
+                .flags = BLE_GATT_CHR_F_INDICATE | BLE_GATT_CHR_F_READ,
+            }, {
+                0, /* No more characteristics in this service */
+            },
+        }
+    },
+#if 1
+    {
+        /* Service: Device Information */
+        .type = BLE_GATT_SVC_TYPE_PRIMARY,
+        .uuid = BLE_UUID16_DECLARE(GATT_DEVICE_INFO_UUID),
+        .characteristics = (struct ble_gatt_chr_def[])
+        { {
+                /* Characteristic: * Manufacturer name */
+                .uuid = BLE_UUID16_DECLARE(GATT_MANUFACTURER_NAME_UUID),
+                .access_cb = gatt_svr_chr_access_device_info,
+                .flags = BLE_GATT_CHR_F_READ,
+            }, {
+                /* Characteristic: Model number string */
+                .uuid = BLE_UUID16_DECLARE(GATT_MODEL_NUMBER_UUID),
+                .access_cb = gatt_svr_chr_access_device_info,
+                .flags = BLE_GATT_CHR_F_READ,
+            }, {
+                0, /* No more characteristics in this service */
+            },
+        }
+    },
+#endif
+    {
+        0, /* No more services */
+    },
+};
+
+static int
+gatt_svr_chr_access_heart_rate(uint16_t conn_handle, uint16_t attr_handle,
+                               struct ble_gatt_access_ctxt *ctxt, void *arg)
+{
+    /* Sensor location, set to "Chest" */
+    static uint8_t body_sens_loc = 0x01;
+    uint16_t uuid;
+    int rc;
+
+    uuid = ble_uuid_u16(ctxt->chr->uuid);
+
+    if (uuid == GATT_HRS_BODY_SENSOR_LOC_UUID) {
+        rc = os_mbuf_append(ctxt->om, &body_sens_loc, sizeof(body_sens_loc));
+
+        return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
+    }
+
+    assert(0);
+    return BLE_ATT_ERR_UNLIKELY;
+}
+
+static int
+gatt_svr_chr_access_device_info(uint16_t conn_handle, uint16_t attr_handle,
+                                struct ble_gatt_access_ctxt *ctxt, void *arg)
+{
+    uint16_t uuid;
+    int rc;
+
+    uuid = ble_uuid_u16(ctxt->chr->uuid);
+
+    if (uuid == GATT_MODEL_NUMBER_UUID) {
+        rc = os_mbuf_append(ctxt->om, model_num, strlen(model_num));
+        return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
+    }
+
+    if (uuid == GATT_MANUFACTURER_NAME_UUID) {
+        rc = os_mbuf_append(ctxt->om, manuf_name, strlen(manuf_name));
+        return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
+    }
+
+    assert(0);
+    return BLE_ATT_ERR_UNLIKELY;
+}
+
+static void gatt_svr_register_cb(struct ble_gatt_register_ctxt *ctxt, void *arg)
+{
+    char buf[BLE_UUID_STR_LEN];
+
+    switch (ctxt->op) {
+    case BLE_GATT_REGISTER_OP_SVC:
+        LLOGD("registered service %s with handle=%d\n",
+                    ble_uuid_to_str(ctxt->svc.svc_def->uuid, buf),
+                    ctxt->svc.handle);
+        break;
+
+    case BLE_GATT_REGISTER_OP_CHR:
+        LLOGD("registering characteristic %s with "
+                    "def_handle=%d val_handle=%d\n",
+                    ble_uuid_to_str(ctxt->chr.chr_def->uuid, buf),
+                    ctxt->chr.def_handle,
+                    ctxt->chr.val_handle);
+        break;
+
+    case BLE_GATT_REGISTER_OP_DSC:
+        LLOGD("registering descriptor %s with handle=%d\n",
+                    ble_uuid_to_str(ctxt->dsc.dsc_def->uuid, buf),
+                    ctxt->dsc.handle);
+        break;
+
+    default:
+        assert(0);
+        break;
+    }
+}
+
+static int l_ble_chr_write_cb(lua_State* L, void* ptr) {
+    ble_write_msg_t* wmsg = (ble_write_msg_t*)ptr;
+    rtos_msg_t* msg = (rtos_msg_t*)lua_topointer(L, -1);
+    lua_getglobal(L, "sys_pub");
+    if (lua_isfunction(L, -1)) {
+        lua_pushstring(L, "BLE_GATT_WRITE_CHR");
+        lua_newtable(L);
+        lua_pushlstring(L, wmsg->buff, wmsg->len);
+        lua_call(L, 3, 0);
+    }
+    luat_heap_free(wmsg);
+    return 0;
+}
+
+static int
+gatt_svr_chr_access_func(uint16_t conn_handle, uint16_t attr_handle,
+                               struct ble_gatt_access_ctxt *ctxt, void *arg)
+{
+    int i = 0;
+    struct os_mbuf *om = ctxt->om;
+    ble_write_msg_t* wmsg;
+    rtos_msg_t msg = {0};
+    LLOGD("gatt_svr_chr_access_func %d %d %d", conn_handle, attr_handle, ctxt->op);
+    switch (ctxt->op) {
+        case BLE_GATT_ACCESS_OP_WRITE_CHR:
+              while(om) {
+                  wmsg = (ble_write_msg_t*)(luat_heap_malloc(sizeof(ble_write_msg_t) + om->om_len - 1));
+                  if (wmsg != NULL) {
+                      wmsg->len = om->om_len;
+                      msg.handler = l_ble_chr_write_cb;
+                      msg.ptr = wmsg;
+                      msg.arg1 = conn_handle;
+                      msg.arg2 = attr_handle;
+                      memcpy(wmsg->buff, om->om_data, om->om_len);
+                      luat_msgbus_put(&msg, 0);
+                  }
+                  om = SLIST_NEXT(om, om_next);
+              }
+              return 0;
+        case BLE_GATT_ACCESS_OP_READ_CHR:
+            return 0;
+        default:
+            assert(0);
+            return BLE_ATT_ERR_UNLIKELY;
+    }
+}
+
+static int gatt_svr_init(void)
+{
+    int rc;
+
+    // ble_svc_gap_init();
+    //ble_gatts_reset();
+    // ble_svc_gatt_init();
+
+    rc = ble_gatts_count_cfg(gatt_svr_svcs);
+    if (rc != 0) {
+        return rc;
+    }
+
+    rc = ble_gatts_add_svcs(gatt_svr_svcs);
+    if (rc != 0) {
+        return rc;
+    }
+    return 0;
+}
+
+int luat_nimble_server_send(int id, char* data, size_t data_len) {
+    int rc;
+    struct os_mbuf *om;
+
+    if (g_ble_state != BT_STATE_CONNECTED) {
+        //LLOGI("Not connected yet");
+        return -1;
+    }
+
+    om = ble_hs_mbuf_from_flat((const void*)data, (uint16_t)data_len);
+    if (!om) {
+        LLOGE("ble_hs_mbuf_from_flat return NULL!!");
+        return BLE_HS_ENOMEM;
+    }
+    rc = ble_gattc_indicate_custom(g_ble_conn_handle,g_ble_attr_indicate_handle, om);
+    LLOGD("ble_gattc_indicate_custom ret %d", rc);
+    return 0;
+}
+
+
+
+
+// static const char *tag = "NimBLE_BLE_PRPH";
+static int bleprph_gap_event(struct ble_gap_event *event, void *arg);
+#if CONFIG_EXAMPLE_RANDOM_ADDR
+static uint8_t own_addr_type = BLE_OWN_ADDR_RANDOM;
+#else
+static uint8_t own_addr_type;
+#endif
+
+void ble_store_config_init(void);
+
+/**
+ * Logs information about a connection to the console.
+ */
+
+#define ADDR_FMT "%02X%02X%02X%02X%02X%02X"
+#define ADDR_T(addr) addr[0],addr[1],addr[2],addr[3],addr[4],addr[5]
+
+static void
+bleprph_print_conn_desc(struct ble_gap_conn_desc *desc)
+{
+    LLOGI("handle=%d our_ota_addr_type=%d our_ota_addr=" ADDR_FMT, desc->conn_handle, desc->our_ota_addr.type, ADDR_T(desc->our_ota_addr.val));
+    LLOGI(" our_id_addr_type=%d our_id_addr=" ADDR_FMT, desc->our_id_addr.type, ADDR_T(desc->our_id_addr.val));
+    LLOGI(" peer_ota_addr_type=%d peer_ota_addr=" ADDR_FMT, desc->peer_ota_addr.type, ADDR_T(desc->peer_ota_addr.val));
+    LLOGI(" peer_id_addr_type=%d peer_id_addr=" ADDR_FMT, desc->peer_id_addr.type, ADDR_T(desc->peer_id_addr.val));
+    LLOGI(" conn_itvl=%d conn_latency=%d supervision_timeout=%d "
+                "encrypted=%d authenticated=%d bonded=%d\n",
+                desc->conn_itvl, desc->conn_latency,
+                desc->supervision_timeout,
+                desc->sec_state.encrypted,
+                desc->sec_state.authenticated,
+                desc->sec_state.bonded);
+}
+
+#if CONFIG_EXAMPLE_EXTENDED_ADV
+/**
+ * Enables advertising with the following parameters:
+ *     o General discoverable mode.
+ *     o Undirected connectable mode.
+ */
+static void
+ext_bleprph_advertise(void)
+{
+    struct ble_gap_ext_adv_params params;
+    struct os_mbuf *data;
+    uint8_t instance = 1;
+    int rc;
+
+    /* use defaults for non-set params */
+    memset (&params, 0, sizeof(params));
+
+    /* enable connectable advertising */
+    params.connectable = 1;
+    params.scannable = 1;
+    params.legacy_pdu = 1;
+
+    /* advertise using random addr */
+    params.own_addr_type = BLE_OWN_ADDR_PUBLIC;
+
+    params.primary_phy = BLE_HCI_LE_PHY_1M;
+    params.secondary_phy = BLE_HCI_LE_PHY_2M;
+    //params.tx_power = 127;
+    params.sid = 1;
+
+    params.itvl_min = BLE_GAP_ADV_FAST_INTERVAL1_MIN;
+    params.itvl_max = BLE_GAP_ADV_FAST_INTERVAL1_MIN;
+
+    /* configure instance 0 */
+    rc = ble_gap_ext_adv_configure(instance, &params, NULL,
+                                   bleprph_gap_event, NULL);
+    assert (rc == 0);
+
+    /* in this case only scan response is allowed */
+
+    /* get mbuf for scan rsp data */
+    data = os_msys_get_pkthdr(sizeof(ext_adv_pattern_1), 0);
+    assert(data);
+
+    /* fill mbuf with scan rsp data */
+    rc = os_mbuf_append(data, ext_adv_pattern_1, sizeof(ext_adv_pattern_1));
+    assert(rc == 0);
+
+    rc = ble_gap_ext_adv_set_data(instance, data);
+    assert (rc == 0);
+
+    /* start advertising */
+    rc = ble_gap_ext_adv_start(instance, 0, 0);
+    assert (rc == 0);
+}
+#else
+/**
+ * Enables advertising with the following parameters:
+ *     o General discoverable mode.
+ *     o Undirected connectable mode.
+ */
+static void
+bleprph_advertise(void)
+{
+    struct ble_gap_adv_params adv_params;
+    struct ble_hs_adv_fields fields;
+    const char *name;
+    int rc;
+
+    /**
+     *  Set the advertisement data included in our advertisements:
+     *     o Flags (indicates advertisement type and other general info).
+     *     o Advertising tx power.
+     *     o Device name.
+     *     o 16-bit service UUIDs (alert notifications).
+     */
+
+    memset(&fields, 0, sizeof fields);
+
+    /* Advertise two flags:
+     *     o Discoverability in forthcoming advertisement (general)
+     *     o BLE-only (BR/EDR unsupported).
+     */
+    fields.flags = BLE_HS_ADV_F_DISC_GEN |
+                   BLE_HS_ADV_F_BREDR_UNSUP;
+
+    /* Indicate that the TX power level field should be included; have the
+     * stack fill this value automatically.  This is done by assigning the
+     * special value BLE_HS_ADV_TX_PWR_LVL_AUTO.
+     */
+    fields.tx_pwr_lvl_is_present = 1;
+    fields.tx_pwr_lvl = BLE_HS_ADV_TX_PWR_LVL_AUTO;
+
+    name = ble_svc_gap_device_name();
+    fields.name = (uint8_t *)name;
+    fields.name_len = strlen(name);
+    fields.name_is_complete = 1;
+
+    fields.uuids16 = (ble_uuid16_t[]) {
+        BLE_UUID16_INIT(GATT_SVR_SVC_ALERT_UUID)
+    };
+    fields.num_uuids16 = 1;
+    fields.uuids16_is_complete = 1;
+
+    rc = ble_gap_adv_set_fields(&fields);
+    if (rc != 0) {
+        LLOGE("error setting advertisement data; rc=%d\n", rc);
+        return;
+    }
+
+    /* Begin advertising. */
+    memset(&adv_params, 0, sizeof adv_params);
+    adv_params.conn_mode = BLE_GAP_CONN_MODE_UND;
+    adv_params.disc_mode = BLE_GAP_DISC_MODE_GEN;
+    rc = ble_gap_adv_start(own_addr_type, NULL, BLE_HS_FOREVER,
+                           &adv_params, bleprph_gap_event, NULL);
+    if (rc != 0) {
+        LLOGE("error enabling advertisement; rc=%d\n", rc);
+        return;
+    }
+}
+#endif
+
+/**
+ * The nimble host executes this callback when a GAP event occurs.  The
+ * application associates a GAP event callback with each connection that forms.
+ * bleprph uses the same callback for all connections.
+ *
+ * @param event                 The type of event being signalled.
+ * @param ctxt                  Various information pertaining to the event.
+ * @param arg                   Application-specified argument; unused by
+ *                                  bleprph.
+ *
+ * @return                      0 if the application successfully handled the
+ *                                  event; nonzero on failure.  The semantics
+ *                                  of the return code is specific to the
+ *                                  particular GAP event being signalled.
+ */
+static int
+bleprph_gap_event(struct ble_gap_event *event, void *arg)
+{
+    struct ble_gap_conn_desc desc;
+    int rc;
+
+    switch (event->type) {
+    case BLE_GAP_EVENT_CONNECT:
+        /* A new connection was established or a connection attempt failed. */
+        LLOGI("connection %s; status=%d ",
+                    event->connect.status == 0 ? "established" : "failed",
+                    event->connect.status);
+        if (event->connect.status == 0) {
+            g_ble_conn_handle = event->connect.conn_handle;
+            rc = ble_gap_conn_find(event->connect.conn_handle, &desc);
+            if (rc == 0)
+                bleprph_print_conn_desc(&desc);
+            g_ble_state = BT_STATE_CONNECTED;
+        }
+        else {
+            g_ble_state = BT_STATE_DISCONNECT;
+        }
+        // LLOGI("\n");
+
+        if (event->connect.status != 0) {
+            /* Connection failed; resume advertising. */
+#if CONFIG_EXAMPLE_EXTENDED_ADV
+            ext_bleprph_advertise();
+#else
+            bleprph_advertise();
+#endif
+        }
+        return 0;
+
+    case BLE_GAP_EVENT_DISCONNECT:
+        g_ble_state = BT_STATE_DISCONNECT;
+        LLOGI("disconnect; reason=%d ", event->disconnect.reason);
+        bleprph_print_conn_desc(&event->disconnect.conn);
+        // LLOGI("\n");
+
+        /* Connection terminated; resume advertising. */
+#if CONFIG_EXAMPLE_EXTENDED_ADV
+        ext_bleprph_advertise();
+#else
+        bleprph_advertise();
+#endif
+        return 0;
+
+    case BLE_GAP_EVENT_CONN_UPDATE:
+        /* The central has updated the connection parameters. */
+        LLOGI("connection updated; status=%d ", event->conn_update.status);
+        rc = ble_gap_conn_find(event->conn_update.conn_handle, &desc);
+        if (rc == 0)
+            bleprph_print_conn_desc(&desc);
+        // LLOGI("\n");
+        return 0;
+
+    case BLE_GAP_EVENT_ADV_COMPLETE:
+        LLOGI("advertise complete; reason=%d", event->adv_complete.reason);
+#if !CONFIG_EXAMPLE_EXTENDED_ADV
+        bleprph_advertise();
+#endif
+        return 0;
+
+    case BLE_GAP_EVENT_ENC_CHANGE:
+        /* Encryption has been enabled or disabled for this connection. */
+        LLOGI("encryption change event; status=%d ",
+                    event->enc_change.status);
+        rc = ble_gap_conn_find(event->enc_change.conn_handle, &desc);
+        if (rc == 0)
+            bleprph_print_conn_desc(&desc);
+        // LLOGI("\n");
+        return 0;
+
+    case BLE_GAP_EVENT_SUBSCRIBE:
+        LLOGI("subscribe event; conn_handle=%d attr_handle=%d "
+                    "reason=%d prevn=%d curn=%d previ=%d curi=%d\n",
+                    event->subscribe.conn_handle,
+                    event->subscribe.attr_handle,
+                    event->subscribe.reason,
+                    event->subscribe.prev_notify,
+                    event->subscribe.cur_notify,
+                    event->subscribe.prev_indicate,
+                    event->subscribe.cur_indicate);
+        return 0;
+
+    case BLE_GAP_EVENT_MTU:
+        LLOGI("mtu update event; conn_handle=%d cid=%d mtu=%d\n",
+                    event->mtu.conn_handle,
+                    event->mtu.channel_id,
+                    event->mtu.value);
+        return 0;
+
+    case BLE_GAP_EVENT_REPEAT_PAIRING:
+        /* We already have a bond with the peer, but it is attempting to
+         * establish a new secure link.  This app sacrifices security for
+         * convenience: just throw away the old bond and accept the new link.
+         */
+
+        /* Delete the old bond. */
+        rc = ble_gap_conn_find(event->repeat_pairing.conn_handle, &desc);
+        assert(rc == 0);
+        ble_store_util_delete_peer(&desc.peer_id_addr);
+
+        /* Return BLE_GAP_REPEAT_PAIRING_RETRY to indicate that the host should
+         * continue with the pairing operation.
+         */
+        return BLE_GAP_REPEAT_PAIRING_RETRY;
+
+    case BLE_GAP_EVENT_PASSKEY_ACTION:
+        LLOGI("PASSKEY_ACTION_EVENT started");
+#if 0
+        struct ble_sm_io pkey = {0};
+        int key = 0;
+
+        if (event->passkey.params.action == BLE_SM_IOACT_DISP) {
+            pkey.action = event->passkey.params.action;
+            pkey.passkey = 123456; // This is the passkey to be entered on peer
+            // LLOGI("Enter passkey %d on the peer side", pkey.passkey);
+            rc = ble_sm_inject_io(event->passkey.conn_handle, &pkey);
+            LLOGI("ble_sm_inject_io BLE_SM_IOACT_DISP result: %d\n", rc);
+        } else if (event->passkey.params.action == BLE_SM_IOACT_NUMCMP) {
+            LLOGI("Passkey on device's display: %d", event->passkey.params.numcmp);
+            LLOGI("Accept or reject the passkey through console in this format -> key Y or key N");
+            pkey.action = event->passkey.params.action;
+            // if (scli_receive_key(&key)) {
+            //     pkey.numcmp_accept = key;
+            // } else {
+            //     pkey.numcmp_accept = 0;
+            //     ESP_LOGE(tag, "Timeout! Rejecting the key");
+            // }
+            pkey.numcmp_accept = 1;
+            rc = ble_sm_inject_io(event->passkey.conn_handle, &pkey);
+            LLOGI("ble_sm_inject_io BLE_SM_IOACT_NUMCMP result: %d\n", rc);
+        } else if (event->passkey.params.action == BLE_SM_IOACT_OOB) {
+            static uint8_t tem_oob[16] = {0};
+            pkey.action = event->passkey.params.action;
+            for (int i = 0; i < 16; i++) {
+                pkey.oob[i] = tem_oob[i];
+            }
+            rc = ble_sm_inject_io(event->passkey.conn_handle, &pkey);
+            LLOGI("ble_sm_inject_io BLE_SM_IOACT_OOB result: %d\n", rc);
+        } else if (event->passkey.params.action == BLE_SM_IOACT_INPUT) {
+            LLOGI("Passkey on device's display: %d", event->passkey.params.numcmp);
+            LLOGI("Enter the passkey through console in this format-> key 123456");
+            pkey.action = event->passkey.params.action;
+            // if (scli_receive_key(&key)) {
+            //     pkey.passkey = key;
+            // } else {
+            //     pkey.passkey = 0;
+            //     ESP_LOGE(tag, "Timeout! Passing 0 as the key");
+            // }
+            pkey.passkey = event->passkey.params.numcmp;
+            rc = ble_sm_inject_io(event->passkey.conn_handle, &pkey);
+            LLOGI("ble_sm_inject_io BLE_SM_IOACT_INPUT result: %d\n", rc);
+        }
+#endif
+        return 0;
+    }
+
+    return 0;
+}
+
+static void
+bleprph_on_reset(int reason)
+{
+    g_ble_state = BT_STATE_OFF;
+    LLOGE("Resetting state; reason=%d", reason);
+    //app_adapter_state_changed_callback(WM_BT_STATE_OFF);
+}
+
+
+static void
+bleprph_on_sync(void)
+{
+    int rc;
+
+#if CONFIG_EXAMPLE_RANDOM_ADDR
+    /* Generate a non-resolvable private address. */
+    ble_app_set_addr();
+#endif
+
+    /* Make sure we have proper identity address set (public preferred) */
+#if CONFIG_EXAMPLE_RANDOM_ADDR
+    rc = ble_hs_util_ensure_addr(1);
+#else
+    rc = ble_hs_util_ensure_addr(0);
+#endif
+    assert(rc == 0);
+
+    /* Figure out address to use while advertising (no privacy for now) */
+    rc = ble_hs_id_infer_auto(0, &own_addr_type);
+    if (rc != 0) {
+        LLOGE("error determining address type; rc=%d", rc);
+        return;
+    }
+
+    /* Printing ADDR */
+    uint8_t addr_val[6] = {0};
+    rc = ble_hs_id_copy_addr(own_addr_type, addr_val, NULL);
+
+    LLOGI("Device Address: " ADDR_FMT, ADDR_T(addr_val));
+    ble_gatts_start();
+    //print_addr(addr_val);
+    // LLOGI("\n");
+    /* Begin advertising. */
+#if CONFIG_EXAMPLE_EXTENDED_ADV
+    ext_bleprph_advertise();
+#else
+    bleprph_advertise();
+#endif
+
+    if (g_ble_state == BT_STATE_OFF)
+        g_ble_state = BT_STATE_ON;
+}
+
+
+
+int luat_nimble_init_server(uint8_t uart_idx, char* name, int mode) {
+    int rc = 0;
+    nimble_port_init();
+
+    if (name == NULL || strlen(name) == 0) {
+        if (selfname[0] == 0) {
+            memcpy(selfname, "LuatOS", strlen("LuatOS") + 1);
+        }
+    }
+    else {
+        memcpy(selfname, name, strlen(name) + 1);
+    }
+
+    /* Set the default device name. */
+    if (strlen(selfname))
+        rc = ble_svc_gap_device_name_set((const char*)selfname);
+
+
+    /* Initialize the NimBLE host configuration. */
+    ble_hs_cfg.reset_cb = bleprph_on_reset;
+    ble_hs_cfg.sync_cb = bleprph_on_sync;
+    ble_hs_cfg.gatts_register_cb = gatt_svr_register_cb;
+    ble_hs_cfg.store_status_cb = ble_store_util_status_rr;
+
+    ble_hs_cfg.sm_io_cap = BLE_SM_IO_CAP_NO_IO;
+    ble_hs_cfg.sm_sc = 0;
+
+
+    ble_svc_gap_init();
+    ble_svc_gatt_init();
+
+    rc = gatt_svr_init();
+    LLOGD("gatt_svr_init rc %d", rc);
+
+    /* XXX Need to have template for store */
+    ble_store_config_init();
+
+    return 0;
+}
+

+ 22 - 24
components/serialization/protobuf/luat_lib_protobuf.c

@@ -193,7 +193,7 @@ static void lpb_pushenchooktable(lua_State *L, lpb_State *LS)
 
 
 static void lpb_pushdechooktable(lua_State *L, lpb_State *LS)
 static void lpb_pushdechooktable(lua_State *L, lpb_State *LS)
 { LS->dec_hooks_index = lpb_reftable(L, LS->dec_hooks_index); }
 { LS->dec_hooks_index = lpb_reftable(L, LS->dec_hooks_index); }
-
+#if 0
 static int Lpb_delete(lua_State *L) {
 static int Lpb_delete(lua_State *L) {
     lpb_State *LS = (lpb_State*)luaL_testudata(L, 1, PB_STATE);
     lpb_State *LS = (lpb_State*)luaL_testudata(L, 1, PB_STATE);
     if (LS != NULL) {
     if (LS != NULL) {
@@ -209,7 +209,7 @@ static int Lpb_delete(lua_State *L) {
     }
     }
     return 0;
     return 0;
 }
 }
-
+#endif
 LUALIB_API lpb_State *lpb_lstate(lua_State *L) {
 LUALIB_API lpb_State *lpb_lstate(lua_State *L) {
     lpb_State *LS;
     lpb_State *LS;
     if (lua53_rawgetp(L, LUA_REGISTRYINDEX, state_name) == LUA_TUSERDATA) {
     if (lua53_rawgetp(L, LUA_REGISTRYINDEX, state_name) == LUA_TUSERDATA) {
@@ -230,7 +230,7 @@ LUALIB_API lpb_State *lpb_lstate(lua_State *L) {
     }
     }
     return LS;
     return LS;
 }
 }
-
+#if 0
 static int Lpb_state(lua_State *L) {
 static int Lpb_state(lua_State *L) {
     int top = lua_gettop(L);
     int top = lua_gettop(L);
     lpb_lstate(L);
     lpb_lstate(L);
@@ -246,7 +246,7 @@ static int Lpb_state(lua_State *L) {
     }
     }
     return 1;
     return 1;
 }
 }
-
+#endif
 
 
 /* protobuf util routines */
 /* protobuf util routines */
 
 
@@ -257,7 +257,7 @@ static int typeerror(lua_State *L, int idx, const char *type) {
     lua_pushfstring(L, "%s expected, got %s", type, luaL_typename(L, idx));
     lua_pushfstring(L, "%s expected, got %s", type, luaL_typename(L, idx));
     return luaL_argerror(L, idx, lua_tostring(L, -1));
     return luaL_argerror(L, idx, lua_tostring(L, -1));
 }
 }
-
+#if 0
 static lua_Integer posrelat(lua_Integer pos, size_t len) {
 static lua_Integer posrelat(lua_Integer pos, size_t len) {
     if (pos >= 0) return pos;
     if (pos >= 0) return pos;
     else if (0u - (size_t)pos > len) return 0;
     else if (0u - (size_t)pos > len) return 0;
@@ -271,6 +271,7 @@ static lua_Integer rangerelat(lua_State *L, int idx, lua_Integer r[2], size_t le
     if (r[1] > (lua_Integer)len) r[1] = len;
     if (r[1] > (lua_Integer)len) r[1] = len;
     return r[0] <= r[1] ? r[1] - r[0] + 1 : 0;
     return r[0] <= r[1] ? r[1] - r[0] + 1 : 0;
 }
 }
+#endif
 
 
 static int argcheck(lua_State *L, int cond, int idx, const char *fmt, ...) {
 static int argcheck(lua_State *L, int cond, int idx, const char *fmt, ...) {
     if (!cond) {
     if (!cond) {
@@ -364,14 +365,14 @@ static uint64_t lpb_tointegerx(lua_State *L, int idx, int *isint) {
     *isint = 1;
     *isint = 1;
     return neg ? ~v + 1 : v;
     return neg ? ~v + 1 : v;
 }
 }
-
+#if 0
 static uint64_t lpb_checkinteger(lua_State *L, int idx) {
 static uint64_t lpb_checkinteger(lua_State *L, int idx) {
     int isint;
     int isint;
     uint64_t v = lpb_tointegerx(L, idx, &isint);
     uint64_t v = lpb_tointegerx(L, idx, &isint);
     if (!isint) typeerror(L, idx, "number/string");
     if (!isint) typeerror(L, idx, "number/string");
     return v;
     return v;
 }
 }
-
+#endif
 static void lpb_pushinteger(lua_State *L, int64_t n, int mode) {
 static void lpb_pushinteger(lua_State *L, int64_t n, int mode) {
     if (mode != LPB_NUMBER && (n < INT_MIN || n > UINT_MAX)) {
     if (mode != LPB_NUMBER && (n < INT_MIN || n > UINT_MAX)) {
         char buff[32], *p = buff + sizeof(buff) - 1;
         char buff[32], *p = buff + sizeof(buff) - 1;
@@ -537,7 +538,7 @@ static void lpb_readtype(lua_State *L, lpb_State *LS, int type, pb_Slice *s) {
 
 
 
 
 /* io routines */
 /* io routines */
-
+#if 0
 #ifdef _WIN32
 #ifdef _WIN32
 # include <io.h>
 # include <io.h>
 # include <fcntl.h>
 # include <fcntl.h>
@@ -705,7 +706,6 @@ LUALIB_API int luaopen_pb_conv(lua_State *L) {
 
 
 
 
 /* protobuf encode routine */
 /* protobuf encode routine */
-
 static int lpb_typefmt(int fmt) {
 static int lpb_typefmt(int fmt) {
     switch (fmt) {
     switch (fmt) {
 #define X(name,type,fmt) case fmt: return PB_T##name;
 #define X(name,type,fmt) case fmt: return PB_T##name;
@@ -898,7 +898,6 @@ LUALIB_API int luaopen_pb_buffer(lua_State *L) {
     return 1;
     return 1;
 }
 }
 
 
-
 /* protobuf decode routine */
 /* protobuf decode routine */
 
 
 #define LPB_INITSTACKLEN 2
 #define LPB_INITSTACKLEN 2
@@ -1193,6 +1192,7 @@ LUALIB_API int luaopen_pb_slice(lua_State *L) {
     return 1;
     return 1;
 }
 }
 
 
+#endif
 
 
 /* high level typeinfo/encode/decode routines */
 /* high level typeinfo/encode/decode routines */
 
 
@@ -1245,7 +1245,7 @@ static int Lpb_load(lua_State *L) {
     lua_pushinteger(L, pb_pos(s)+1);
     lua_pushinteger(L, pb_pos(s)+1);
     return 2;
     return 2;
 }
 }
-
+#if 0
 static int Lpb_loadfile(lua_State *L) {
 static int Lpb_loadfile(lua_State *L) {
     lpb_State *LS = lpb_lstate(L);
     lpb_State *LS = lpb_lstate(L);
     const char *filename = luaL_checkstring(L, 1);
     const char *filename = luaL_checkstring(L, 1);
@@ -1315,7 +1315,9 @@ static int Lpb_types(lua_State *L) {
     lua_pushnil(L);
     lua_pushnil(L);
     return 3;
     return 3;
 }
 }
+#endif
 
 
+#if 0
 static int Lpb_fieldsiter(lua_State *L) {
 static int Lpb_fieldsiter(lua_State *L) {
     lpb_State *LS = lpb_lstate(L);
     lpb_State *LS = lpb_lstate(L);
     const pb_Type *t = lpb_type(LS, lpb_checkslice(L, 1));
     const pb_Type *t = lpb_type(LS, lpb_checkslice(L, 1));
@@ -1357,7 +1359,7 @@ static int Lpb_enum(lua_State *L) {
         lpb_pushinteger(L, f->number, LS->int64_mode);
         lpb_pushinteger(L, f->number, LS->int64_mode);
     return 1;
     return 1;
 }
 }
-
+#endif
 static int lpb_pushdeffield(lua_State *L, lpb_State *LS, const pb_Field *f, int is_proto3) {
 static int lpb_pushdeffield(lua_State *L, lpb_State *LS, const pb_Field *f, int is_proto3) {
     int ret = 0;
     int ret = 0;
     const pb_Type *type;
     const pb_Type *type;
@@ -1436,7 +1438,6 @@ static void lpb_pushdefmeta(lua_State *L, lpb_State *LS, const pb_Type *t) {
     }
     }
     lua_remove(L, -2);
     lua_remove(L, -2);
 }
 }
-
 static void lpb_cleardefmeta(lua_State *L, lpb_State *LS, const pb_Type *t) {
 static void lpb_cleardefmeta(lua_State *L, lpb_State *LS, const pb_Type *t) {
     lpb_pushdeftable(L, LS);
     lpb_pushdeftable(L, LS);
     lua_pushnil(L);
     lua_pushnil(L);
@@ -1444,6 +1445,7 @@ static void lpb_cleardefmeta(lua_State *L, lpb_State *LS, const pb_Type *t) {
     lua_pop(L, 1);
     lua_pop(L, 1);
 }
 }
 
 
+#if 0
 static int Lpb_defaults(lua_State *L) {
 static int Lpb_defaults(lua_State *L) {
     lpb_State *LS = lpb_lstate(L);
     lpb_State *LS = lpb_lstate(L);
     const pb_Type *t = lpb_type(LS, lpb_checkslice(L, 1));
     const pb_Type *t = lpb_type(LS, lpb_checkslice(L, 1));
@@ -1453,7 +1455,6 @@ static int Lpb_defaults(lua_State *L) {
     if (clear) lpb_cleardefmeta(L, LS, t);
     if (clear) lpb_cleardefmeta(L, LS, t);
     return 1;
     return 1;
 }
 }
-
 static int Lpb_hook(lua_State *L) {
 static int Lpb_hook(lua_State *L) {
     lpb_State *LS = lpb_lstate(L);
     lpb_State *LS = lpb_lstate(L);
     const pb_Type *t = lpb_type(LS, lpb_checkslice(L, 1));
     const pb_Type *t = lpb_type(LS, lpb_checkslice(L, 1));
@@ -1487,7 +1488,7 @@ static int Lpb_encode_hook(lua_State *L) {
     }
     }
     return 1;
     return 1;
 }
 }
-
+#endif
 /*
 /*
 清除已加载的二进制定义数据
 清除已加载的二进制定义数据
 @api protobuf.clear()
 @api protobuf.clear()
@@ -1518,7 +1519,7 @@ static int Lpb_clear(lua_State *L) {
     lpb_cleardefmeta(L, LS, t);
     lpb_cleardefmeta(L, LS, t);
     return 0;
     return 0;
 }
 }
-
+#if 0
 static int Lpb_typefmt(lua_State *L) {
 static int Lpb_typefmt(lua_State *L) {
     pb_Slice s = lpb_checkslice(L, 1);
     pb_Slice s = lpb_checkslice(L, 1);
     const char *r = NULL;
     const char *r = NULL;
@@ -1546,7 +1547,7 @@ static int Lpb_typefmt(lua_State *L) {
     lua_pushinteger(L, type);
     lua_pushinteger(L, type);
     return 2;
     return 2;
 }
 }
-
+#endif
 
 
 /* protobuf encode */
 /* protobuf encode */
 
 
@@ -1748,7 +1749,7 @@ static int Lpb_encode(lua_State *L) {
     }
     }
     return 1;
     return 1;
 }
 }
-
+#if 0
 static int lpbE_pack(lpb_Env* e, const pb_Type* t, int idx) {
 static int lpbE_pack(lpb_Env* e, const pb_Type* t, int idx) {
     unsigned i;
     unsigned i;
     lua_State* L = e->L;
     lua_State* L = e->L;
@@ -1781,7 +1782,7 @@ static int Lpb_pack(lua_State* L) {
     }
     }
     return 1;
     return 1;
 }
 }
-
+#endif
 /* protobuf decode */
 /* protobuf decode */
 
 
 #define lpb_withinput(e,ns,stmt) ((e)->s = (ns), (stmt), (e)->s = s)
 #define lpb_withinput(e,ns,stmt) ((e)->s = (ns), (stmt), (e)->s = s)
@@ -1993,6 +1994,7 @@ static int Lpb_decode(lua_State *L) {
 }
 }
 
 
 
 
+#if 0
 void lpb_pushunpackdef(lua_State* L, lpb_State* LS, const pb_Type* t, pb_Field** l, int top) {
 void lpb_pushunpackdef(lua_State* L, lpb_State* LS, const pb_Type* t, pb_Field** l, int top) {
     unsigned int i;
     unsigned int i;
     int mode = LS->encode_mode;
     int mode = LS->encode_mode;
@@ -2052,7 +2054,6 @@ static int lpbD_unpack(lpb_Env* e, const pb_Type* t) {
     if (decode_count != t->field_count) lpb_pushunpackdef(L, e->LS, t, list, top);
     if (decode_count != t->field_count) lpb_pushunpackdef(L, e->LS, t, list, top);
     return t->field_count;
     return t->field_count;
 }
 }
-
 static int Lpb_unpack(lua_State* L) {
 static int Lpb_unpack(lua_State* L) {
     lpb_State* LS = lpb_lstate(L);
     lpb_State* LS = lpb_lstate(L);
     const pb_Type* t = lpb_type(LS, lpb_checkslice(L, 1));
     const pb_Type* t = lpb_type(LS, lpb_checkslice(L, 1));
@@ -2064,7 +2065,6 @@ static int Lpb_unpack(lua_State* L) {
 }
 }
 
 
 /* pb module interface */
 /* pb module interface */
-
 static int Lpb_option(lua_State *L) {
 static int Lpb_option(lua_State *L) {
 #define OPTS(X) \
 #define OPTS(X) \
     X(0,  enum_as_name,         LS->enum_as_value = 0)               \
     X(0,  enum_as_name,         LS->enum_as_value = 0)               \
@@ -2104,8 +2104,6 @@ static int Lpb_option(lua_State *L) {
     return 0;
     return 0;
 #undef  OPTS
 #undef  OPTS
 }
 }
-
-/*
 LUALIB_API int luaopen_pb(lua_State *L) {
 LUALIB_API int luaopen_pb(lua_State *L) {
     luaL_Reg libs[] = {
     luaL_Reg libs[] = {
 #define ENTRY(name) { #name, Lpb_##name }
 #define ENTRY(name) { #name, Lpb_##name }
@@ -2146,7 +2144,6 @@ LUALIB_API int luaopen_pb(lua_State *L) {
     luaL_newlib(L, libs);
     luaL_newlib(L, libs);
     return 1;
     return 1;
 }
 }
-*/
 
 
 // static int Lpb_decode_unsafe(lua_State *L) {
 // static int Lpb_decode_unsafe(lua_State *L) {
 //     const char *data = (const char *)lua_touserdata(L, 2);
 //     const char *data = (const char *)lua_touserdata(L, 2);
@@ -2192,6 +2189,7 @@ LUALIB_API int luaopen_pb(lua_State *L) {
 //     luaL_newlib(L, libs);
 //     luaL_newlib(L, libs);
 //     return 1;
 //     return 1;
 // }
 // }
+#endif
 
 
 #include "luat_base.h"
 #include "luat_base.h"
 #include "rotable2.h"
 #include "rotable2.h"

+ 21 - 18
components/serialization/protobuf/pb.h

@@ -38,13 +38,16 @@
 # define PB_API extern
 # define PB_API extern
 #endif
 #endif
 
 
-
-
-// #include "luat_base.h"
 #include "stdint.h"
 #include "stdint.h"
 #include <stddef.h>
 #include <stddef.h>
 #include <limits.h>
 #include <limits.h>
 
 
+void* luat_heap_malloc(size_t len);
+void  luat_heap_free(void* ptr);
+
+#define os_malloc luat_heap_malloc
+#define os_free luat_heap_free
+
 PB_NS_BEGIN
 PB_NS_BEGIN
 
 
 
 
@@ -656,7 +659,7 @@ PB_API void pb_initbuffer(pb_Buffer *b)
 { memset(b, 0, sizeof(pb_Buffer)); }
 { memset(b, 0, sizeof(pb_Buffer)); }
 
 
 PB_API void pb_resetbuffer(pb_Buffer *b)
 PB_API void pb_resetbuffer(pb_Buffer *b)
-{ if (pb_onheap(b)) free(b->u.h.buff); pb_initbuffer(b); }
+{ if (pb_onheap(b)) os_free(b->u.h.buff); pb_initbuffer(b); }
 
 
 static int pb_write32(char *buff, uint32_t n) {
 static int pb_write32(char *buff, uint32_t n) {
     int p, c = 0;
     int p, c = 0;
@@ -790,7 +793,7 @@ PB_API void pb_freepool(pb_Pool *pool) {
     void *page = pool->pages;
     void *page = pool->pages;
     while (page) {
     while (page) {
         void *next = *(void**)((char*)page + PB_POOLSIZE - sizeof(void*));
         void *next = *(void**)((char*)page + PB_POOLSIZE - sizeof(void*));
-        free(page);
+        os_free(page);
         page = next;
         page = next;
     }
     }
     pb_initpool(pool, pool->obj_size);
     pb_initpool(pool, pool->obj_size);
@@ -800,7 +803,7 @@ PB_API void *pb_poolalloc(pb_Pool *pool) {
     void *obj = pool->freed;
     void *obj = pool->freed;
     if (obj == NULL) {
     if (obj == NULL) {
         size_t objsize = pool->obj_size, offset;
         size_t objsize = pool->obj_size, offset;
-        void *newpage = malloc(PB_POOLSIZE);
+        void *newpage = os_malloc(PB_POOLSIZE);
         if (newpage == NULL) return NULL;
         if (newpage == NULL) return NULL;
         offset = ((PB_POOLSIZE - sizeof(void*)) / objsize - 1) * objsize;
         offset = ((PB_POOLSIZE - sizeof(void*)) / objsize - 1) * objsize;
         for (; offset > 0; offset -= objsize) {
         for (; offset > 0; offset -= objsize) {
@@ -828,7 +831,7 @@ PB_API void pb_inittable(pb_Table *t, size_t entrysize)
 { memset(t, 0, sizeof(pb_Table)), t->entry_size = (unsigned)entrysize; }
 { memset(t, 0, sizeof(pb_Table)), t->entry_size = (unsigned)entrysize; }
 
 
 PB_API void pb_freetable(pb_Table *t)
 PB_API void pb_freetable(pb_Table *t)
-{ free(t->hash); pb_inittable(t, t->entry_size); }
+{ os_free(t->hash); pb_inittable(t, t->entry_size); }
 
 
 static pb_Entry *pbT_hash(const pb_Table *t, pb_Key key) {
 static pb_Entry *pbT_hash(const pb_Table *t, pb_Key key) {
     size_t h = ((size_t)key*2654435761U)&(t->size-1);
     size_t h = ((size_t)key*2654435761U)&(t->size-1);
@@ -876,7 +879,7 @@ PB_API size_t pb_resizetable(pb_Table *t, size_t size) {
     if (newsize < size) return 0;
     if (newsize < size) return 0;
     nt.size     = newsize;
     nt.size     = newsize;
     nt.lastfree = nt.entry_size * newsize;
     nt.lastfree = nt.entry_size * newsize;
-    nt.hash     = (pb_Entry*)malloc(nt.lastfree);
+    nt.hash     = (pb_Entry*)os_malloc(nt.lastfree);
     if (nt.hash == NULL) return 0;
     if (nt.hash == NULL) return 0;
     memset(nt.hash, 0, nt.lastfree);
     memset(nt.hash, 0, nt.lastfree);
     for (i = 0; i < rawsize; i += t->entry_size) {
     for (i = 0; i < rawsize; i += t->entry_size) {
@@ -885,7 +888,7 @@ PB_API size_t pb_resizetable(pb_Table *t, size_t size) {
         if (nt.entry_size > sizeof(pb_Entry))
         if (nt.entry_size > sizeof(pb_Entry))
             memcpy(newe+1, olde+1, nt.entry_size - sizeof(pb_Entry));
             memcpy(newe+1, olde+1, nt.entry_size - sizeof(pb_Entry));
     }
     }
-    free(t->hash);
+    os_free(t->hash);
     *t = nt;
     *t = nt;
     return newsize;
     return newsize;
 }
 }
@@ -944,11 +947,11 @@ static void pbN_free(pb_State *S) {
         pb_NameEntry *ne = nt->hash[i];
         pb_NameEntry *ne = nt->hash[i];
         while (ne != NULL) {
         while (ne != NULL) {
             pb_NameEntry *next = ne->next;
             pb_NameEntry *next = ne->next;
-            free(ne);
+            os_free(ne);
             ne = next;
             ne = next;
         }
         }
     }
     }
-    free(nt->hash);
+    os_free(nt->hash);
     pbN_init(S);
     pbN_init(S);
 }
 }
 
 
@@ -968,7 +971,7 @@ static size_t pbN_resize(pb_State *S, size_t size) {
     while (newsize < PB_MAX_HASHSIZE/sizeof(pb_NameEntry*) && newsize < size)
     while (newsize < PB_MAX_HASHSIZE/sizeof(pb_NameEntry*) && newsize < size)
         newsize <<= 1;
         newsize <<= 1;
     if (newsize < size) return 0;
     if (newsize < size) return 0;
-    hash = (pb_NameEntry**)malloc(newsize * sizeof(pb_NameEntry*));
+    hash = (pb_NameEntry**)os_malloc(newsize * sizeof(pb_NameEntry*));
     if (hash == NULL) return 0;
     if (hash == NULL) return 0;
     memset(hash, 0, newsize * sizeof(pb_NameEntry*));
     memset(hash, 0, newsize * sizeof(pb_NameEntry*));
     for (i = 0; i < nt->size; ++i) {
     for (i = 0; i < nt->size; ++i) {
@@ -980,7 +983,7 @@ static size_t pbN_resize(pb_State *S, size_t size) {
             entry = next;
             entry = next;
         }
         }
     }
     }
-    free(nt->hash);
+    os_free(nt->hash);
     nt->hash = hash;
     nt->hash = hash;
     nt->size = newsize;
     nt->size = newsize;
     return newsize;
     return newsize;
@@ -992,7 +995,7 @@ static pb_NameEntry *pbN_newname(pb_State *S, pb_Slice s, unsigned hash) {
     size_t len = pb_len(s);
     size_t len = pb_len(s);
     if (nt->count >= nt->size && !pbN_resize(S, nt->size * 2)) return NULL;
     if (nt->count >= nt->size && !pbN_resize(S, nt->size * 2)) return NULL;
     list = &nt->hash[hash & (nt->size - 1)];
     list = &nt->hash[hash & (nt->size - 1)];
-    newobj = (pb_NameEntry*)malloc(sizeof(pb_NameEntry) + len + 1);
+    newobj = (pb_NameEntry*)os_malloc(sizeof(pb_NameEntry) + len + 1);
     if (newobj == NULL) return NULL;
     if (newobj == NULL) return NULL;
     newobj->next     = *list;
     newobj->next     = *list;
     newobj->length   = (unsigned)len;
     newobj->length   = (unsigned)len;
@@ -1014,7 +1017,7 @@ static void pbN_delname(pb_State *S, pb_NameEntry *name) {
         else {
         else {
             *list = (*list)->next;
             *list = (*list)->next;
             --nt->count;
             --nt->count;
-            free(name);
+            os_free(name);
             break;
             break;
         }
         }
     }
     }
@@ -1140,7 +1143,7 @@ PB_API pb_Field** pb_sortfield(pb_Type* t) {
         int index = 0;
         int index = 0;
         unsigned int i = 0;
         unsigned int i = 0;
         const pb_Field* f = NULL;
         const pb_Field* f = NULL;
-        pb_Field** list = malloc(sizeof(pb_Field*) * t->field_count);
+        pb_Field** list = os_malloc(sizeof(pb_Field*) * t->field_count);
 
 
         assert(list);
         assert(list);
         while (pb_nextfield(t, &f)) {
         while (pb_nextfield(t, &f)) {
@@ -1228,7 +1231,7 @@ PB_API pb_Type *pb_newtype(pb_State *S, pb_Name *tname) {
 
 
 PB_API void pb_delsort(pb_Type *t) {
 PB_API void pb_delsort(pb_Type *t) {
     if (t->field_sort) {
     if (t->field_sort) {
-        free(t->field_sort);
+        os_free(t->field_sort);
         t->field_sort = NULL;
         t->field_sort = NULL;
     }
     }
 }
 }
@@ -1318,7 +1321,7 @@ typedef struct pb_ArrayHeader {
 } pb_ArrayHeader;
 } pb_ArrayHeader;
 
 
 #define pbL_rawh(A)   ((pb_ArrayHeader*)(A) - 1)
 #define pbL_rawh(A)   ((pb_ArrayHeader*)(A) - 1)
-#define pbL_delete(A) ((A) ? (void)free(pbL_rawh(A)) : (void)0)
+#define pbL_delete(A) ((A) ? (void)os_free(pbL_rawh(A)) : (void)0)
 #define pbL_count(A)  ((A) ? pbL_rawh(A)->count    : 0)
 #define pbL_count(A)  ((A) ? pbL_rawh(A)->count    : 0)
 #define pbL_add(A)    (pbL_grow((void**)&(A),sizeof(*(A)))==PB_OK ?\
 #define pbL_add(A)    (pbL_grow((void**)&(A),sizeof(*(A)))==PB_OK ?\
                        &(A)[pbL_rawh(A)->count++] : NULL)
                        &(A)[pbL_rawh(A)->count++] : NULL)

+ 59 - 28
components/u8g2/luat_lib_u8g2.c

@@ -33,6 +33,16 @@ static uint8_t spi_res;
 static uint8_t spi_dc;
 static uint8_t spi_dc;
 static uint8_t spi_cs;
 static uint8_t spi_cs;
 
 
+static uint8_t * buff_ptr = NULL;
+
+static const char* mode_strs[] = {
+    "i2c_sw",
+    "i2c_hw",
+    "spi_sw_3pin",
+    "spi_sw_4pin",
+    "spi_hw_4pin"
+};
+
 /*
 /*
 u8g2显示屏初始化
 u8g2显示屏初始化
 @api u8g2.begin(conf)
 @api u8g2.begin(conf)
@@ -64,13 +74,15 @@ static int l_u8g2_begin(lua_State *L) {
     conf.pinType = 2; // I2C 硬件(或者是个假硬件)
     conf.pinType = 2; // I2C 硬件(或者是个假硬件)
     conf.ptr = u8g2;
     conf.ptr = u8g2;
     conf.direction = U8G2_R0;
     conf.direction = U8G2_R0;
+    char mode[8] = {0};
+    size_t mode_len = 0;
     if (lua_istable(L, 1)) {
     if (lua_istable(L, 1)) {
         // 参数解析
         // 参数解析
         lua_pushliteral(L, "ic");
         lua_pushliteral(L, "ic");
         lua_gettable(L, 1);
         lua_gettable(L, 1);
         if (lua_isstring(L, -1)) {
         if (lua_isstring(L, -1)) {
             conf.cname = (char*)luaL_checkstring(L, -1);
             conf.cname = (char*)luaL_checkstring(L, -1);
-            LLOGD("using ic: %s",conf.cname);
+            //LLOGD("using ic: %s",conf.cname);
         }
         }
         lua_pop(L, 1);
         lua_pop(L, 1);
 
 
@@ -102,31 +114,29 @@ static int l_u8g2_begin(lua_State *L) {
 
 
         lua_pushliteral(L, "mode");
         lua_pushliteral(L, "mode");
         lua_gettable(L, 1);
         lua_gettable(L, 1);
-        if (lua_isstring(L, -1)) {
-            const char* mode = luaL_checkstring(L, -1);
-            LLOGD("mode = [%s]", mode);
-            if (strcmp("i2c_sw", mode) == 0) {
-                LLOGD("using i2c_sw");
-                conf.pinType = 1;
-            }
-            else if (strcmp("i2c_hw", mode) == 0) {
-                LLOGD("using i2c_hw");
-                conf.pinType = 2;
-            }
-            else if (strcmp("spi_sw_3pin", mode) == 0) {
-                LLOGD("using spi_sw_3pin");
-                conf.pinType = 3;
-            }
-            else if (strcmp("spi_sw_4pin", mode) == 0) {
-                LLOGD("using spi_sw_4pin");
-                conf.pinType = 4;
-            }
-            else if (strcmp("spi_hw_4pin", mode) == 0) {
-                LLOGD("using spi_hw_4pin");
-                conf.pinType = 5;
-            }
+        if (!lua_isstring(L, -1)) {
+            LLOGE("need mode!!!");
+            return 0;
+        }
+        const char* tmp = luaL_checklstring(L, -1, &mode_len);
+        if (mode_len < 1 || mode_len > 7) {
+            LLOGE("mode string too short or too long!!");
+            return 0;
         }
         }
+        memcpy(mode, tmp, strlen(tmp));
         lua_pop(L, 1);
         lua_pop(L, 1);
+        conf.pinType = 255;
+        for (size_t i = 0; i < sizeof(mode_strs) / sizeof(const char*); i++)
+        {
+            if (strcmp(mode_strs[i], tmp) == 0) {
+                conf.pinType = i + 1;
+                break;
+            }
+        }
+        if (conf.pinType == 255) {
+            LLOGE("no such mode [%s]", tmp);
+            return 0;
+        }
 
 
         lua_pushliteral(L, "i2c_scl");
         lua_pushliteral(L, "i2c_scl");
         lua_gettable(L, 1);
         lua_gettable(L, 1);
@@ -185,14 +195,14 @@ static int l_u8g2_begin(lua_State *L) {
         lua_pop(L, 1);
         lua_pop(L, 1);
 
 
     }
     }
-    LLOGD("pinType=%d", conf.pinType);
+    LLOGD("driver %s mode %s", conf.cname, mode);
     if (luat_u8g2_setup(&conf)) {
     if (luat_u8g2_setup(&conf)) {
         u8g2 = NULL;
         u8g2 = NULL;
         LLOGW("disp init fail");
         LLOGW("disp init fail");
         lua_pushinteger(L, 4);
         lua_pushinteger(L, 4);
         return 1; // 初始化失败
         return 1; // 初始化失败
     }
     }
-
+    LLOGD("setup done");
     u8g2_lua_ref = luaL_ref(L, LUA_REGISTRYINDEX);
     u8g2_lua_ref = luaL_ref(L, LUA_REGISTRYINDEX);
     u8g2_SetFont(u8g2, u8g2_font_ncenB08_tr); // 设置默认字体
     u8g2_SetFont(u8g2, u8g2_font_ncenB08_tr); // 设置默认字体
     lua_pushinteger(L, 1);
     lua_pushinteger(L, 1);
@@ -214,6 +224,12 @@ static int l_u8g2_close(lua_State *L) {
         }
         }
         u8g2_lua_ref = 0;
         u8g2_lua_ref = 0;
     }
     }
+    // buff也得释放掉
+    if (buff_ptr != NULL) {
+        luat_heap_free(buff_ptr);
+        buff_ptr = NULL;
+    }
+    lua_gc(L, LUA_GCCOLLECT, 0);
     lua_gc(L, LUA_GCCOLLECT, 0);
     lua_gc(L, LUA_GCCOLLECT, 0);
     u8g2 = NULL;
     u8g2 = NULL;
     return 0;
     return 0;
@@ -929,6 +945,7 @@ static const luat_u8g2_dev_reg_t devregs[] = {
     {.name="sh1106",  .w=128, .h=64, .spi_i2c=1, .devcb=u8g2_Setup_sh1106_128x64_noname_f},        // sh1106 128x64,SPI
     {.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="sh1107",  .w=64, .h=128, .spi_i2c=0, .devcb=u8g2_Setup_ssd1306_i2c_128x64_noname_f},       // sh1107 64x128
     {.name="st7567",  .w=128, .h=64, .spi_i2c=1, .devcb=u8g2_Setup_st7567_jlx12864_f},                 // st7567 128x64
     {.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=NULL} // 结尾用,必须加.
     {.name=NULL} // 结尾用,必须加.
 };
 };
 
 
@@ -968,6 +985,10 @@ int luat_u8g2_setup_default(luat_u8g2_conf_t *conf) {
             return -1;
             return -1;
         }
         }
         devreg->devcb(u8g2, conf->direction, u8x8_byte_sw_i2c, u8x8_luat_gpio_and_delay_default);
         devreg->devcb(u8g2, conf->direction, u8x8_byte_sw_i2c, u8x8_luat_gpio_and_delay_default);
+        #ifdef U8G2_USE_DYNAMIC_ALLOC
+        buff_ptr = (uint8_t *)luat_heap_malloc(u8g2_GetBufferSize(u8g2));
+        u8g2_SetBufferPtr(u8g2, buff_ptr);
+        #endif
         u8g2->u8x8.pins[U8X8_PIN_I2C_CLOCK] = i2c_scl;
         u8g2->u8x8.pins[U8X8_PIN_I2C_CLOCK] = i2c_scl;
         u8g2->u8x8.pins[U8X8_PIN_I2C_DATA] = i2c_sda;
         u8g2->u8x8.pins[U8X8_PIN_I2C_DATA] = i2c_sda;
         u8g2_InitDisplay(u8g2);
         u8g2_InitDisplay(u8g2);
@@ -980,7 +1001,11 @@ int luat_u8g2_setup_default(luat_u8g2_conf_t *conf) {
             return -1;
             return -1;
         }
         }
         devreg->devcb(u8g2, conf->direction, u8x8_luat_byte_hw_i2c_default, u8x8_luat_gpio_and_delay_default);
         devreg->devcb(u8g2, conf->direction, u8x8_luat_byte_hw_i2c_default, u8x8_luat_gpio_and_delay_default);
-        LLOGD("setup disp i2c.hw");
+        #ifdef U8G2_USE_DYNAMIC_ALLOC
+        buff_ptr = (uint8_t *)luat_heap_malloc(u8g2_GetBufferSize(u8g2));
+        u8g2_SetBufferPtr(u8g2, buff_ptr);
+        #endif
+        //LLOGD("setup disp i2c.hw");
         u8g2_InitDisplay(u8g2);
         u8g2_InitDisplay(u8g2);
         u8g2_SetPowerSave(u8g2, 0);
         u8g2_SetPowerSave(u8g2, 0);
         return 0;
         return 0;
@@ -991,6 +1016,10 @@ int luat_u8g2_setup_default(luat_u8g2_conf_t *conf) {
             return -1;
             return -1;
         }
         }
         devreg->devcb(u8g2, conf->direction, u8x8_luat_byte_4wire_hw_spi_default, u8x8_luat_gpio_and_delay_default);
         devreg->devcb(u8g2, conf->direction, u8x8_luat_byte_4wire_hw_spi_default, u8x8_luat_gpio_and_delay_default);
+        #ifdef U8G2_USE_DYNAMIC_ALLOC
+        buff_ptr = (uint8_t *)luat_heap_malloc(u8g2_GetBufferSize(u8g2));
+        u8g2_SetBufferPtr(u8g2, buff_ptr);
+        #endif
         LLOGD("setup disp spi.hw  spi_id=%d spi_dc=%d spi_cs=%d spi_res=%d",spi_id,spi_dc,spi_cs,spi_res);
         LLOGD("setup disp spi.hw  spi_id=%d spi_dc=%d spi_cs=%d spi_res=%d",spi_id,spi_dc,spi_cs,spi_res);
         u8x8_SetPin(u8g2_GetU8x8(u8g2), U8X8_PIN_CS, spi_cs);
         u8x8_SetPin(u8g2_GetU8x8(u8g2), U8X8_PIN_CS, spi_cs);
         u8x8_SetPin(u8g2_GetU8x8(u8g2), U8X8_PIN_DC, spi_dc);
         u8x8_SetPin(u8g2_GetU8x8(u8g2), U8X8_PIN_DC, spi_dc);
@@ -999,7 +1028,9 @@ int luat_u8g2_setup_default(luat_u8g2_conf_t *conf) {
         u8g2_SetPowerSave(u8g2, 0);
         u8g2_SetPowerSave(u8g2, 0);
         return 0;
         return 0;
     }
     }
-    LLOGI("no such u8g2 mode!!");
+    else {
+        LLOGI("no such u8g2 mode!!");
+    }
     return -1;
     return -1;
 }
 }
 
 

+ 2 - 2
components/u8g2/u8g2.h

@@ -84,12 +84,12 @@
   Before using any display functions, the dynamic buffer *must* be assigned to the u8g2 struct using the u8g2_SetBufferPtr function.
   Before using any display functions, the dynamic buffer *must* be assigned to the u8g2 struct using the u8g2_SetBufferPtr function.
   When using dynamic allocation, the stack size must be increased by u8g2_GetBufferSize bytes.
   When using dynamic allocation, the stack size must be increased by u8g2_GetBufferSize bytes.
  */
  */
-//#define U8G2_USE_DYNAMIC_ALLOC
+#define U8G2_USE_DYNAMIC_ALLOC
 
 
 /*
 /*
   U8G2 uses the same static array
   U8G2 uses the same static array
  */
  */
-#define U8G2_USE_ONE_STATIC_BUFF
+// #define U8G2_USE_ONE_STATIC_BUFF
 
 
 /* U8g2 feature selection, see also https://github.com/olikraus/u8g2/wiki/u8g2optimization */
 /* U8g2 feature selection, see also https://github.com/olikraus/u8g2/wiki/u8g2optimization */
 
 

+ 211 - 0
components/wlan/luat_lib_wlan.c

@@ -0,0 +1,211 @@
+#include "luat_base.h"
+#include "luat_wlan.h"
+
+#define LUAT_LOG_TAG "wlan"
+#include "luat_log.h"
+
+static int l_wlan_init(lua_State* L){
+    luat_wlan_init(NULL);
+    return 0;
+}
+
+static int l_wlan_mode(lua_State* L){
+    int mode = LUAT_WLAN_MODE_STA;
+    if (lua_isinteger(L, 1)) {
+        mode = lua_tointeger(L, 1);
+    }
+    else if (lua_isinteger(L, 2)) {
+        mode = lua_tointeger(L, 2);
+    }
+
+    if (mode <= LUAT_WLAN_MODE_NULL || mode >= LUAT_WLAN_MODE_MAX) {
+        mode = LUAT_WLAN_MODE_STA;
+    }
+
+    // switch (mode)
+    // {
+    // case LUAT_WLAN_MODE_NULL:
+    //     LLOGD("wlan mode NULL");
+    //     break;
+    // case LUAT_WLAN_MODE_STA:
+    //     LLOGD("wlan mode STATION");
+    //     break;
+    // case LUAT_WLAN_MODE_AP:
+    //     LLOGD("wlan mode AP");
+    //     break;
+    // case LUAT_WLAN_MODE_APSTA:
+    //     LLOGD("wlan mode AP-STATION");
+    //     break;
+    
+    // default:
+    //     break;
+    // }
+    luat_wlan_config_t conf = {
+        .mode = mode
+    };
+    luat_wlan_mode(&conf);
+    return 0;
+}
+
+static int l_wlan_ready(lua_State* L){
+    lua_pushboolean(L, luat_wlan_ready());
+    return 1;
+}
+
+static int l_wlan_connect(lua_State* L){
+    const char* ssid = luaL_optstring(L, 1, "");
+    const char* password = luaL_optstring(L, 2, "");
+    luat_wlan_conninfo_t info = {0};
+    info.auto_reconnection = 1;
+    memcpy(info.ssid, ssid, strlen(ssid));
+    memcpy(info.password, password, strlen(password));
+
+    luat_wlan_connect(&info);
+    return 0;
+}
+
+static int l_wlan_disconnect(lua_State* L){
+    luat_wlan_disconnect();
+    return 0;
+}
+
+static int l_wlan_scan(lua_State* L){
+    luat_wlan_scan();
+    return 0;
+}
+
+static int l_wlan_scan_result(lua_State* L) {
+    int ap_limit = luaL_optinteger(L, 1, 20);
+    if (ap_limit > 32)
+        ap_limit = 32;
+    else if (ap_limit < 8)
+        ap_limit = 8;
+    lua_newtable(L);
+    luat_wlan_scan_result_t *results = luat_heap_malloc(sizeof(luat_wlan_scan_result_t) * ap_limit);
+    if (results == NULL) {
+        LLOGE("out of memory when malloc scan result");
+        return 1;
+    }
+    memset(results, 0, sizeof(luat_wlan_scan_result_t) * ap_limit);
+    int len = luat_wlan_scan_get_result(results, ap_limit);
+    for (size_t i = 0; i < len; i++)
+    {
+        lua_newtable(L);
+
+        lua_pushstring(L, (const char *)results[i].ssid);
+        lua_setfield(L, -2, "ssid");
+
+        // lua_pushfstring(L, "%02X%02X%02X%02X%02X%02X", results[i].bssid[0], 
+        //                                                results[i].bssid[1], 
+        //                                                results[i].bssid[2], 
+        //                                                results[i].bssid[3], 
+        //                                                results[i].bssid[4], 
+        //                                                results[i].bssid[5]);
+        lua_pushlstring(L, (const char *)results[i].bssid, 6);
+        lua_setfield(L, -2, "bssid");
+
+        lua_pushinteger(L, results[i].ch);
+        lua_setfield(L, -2, "channel");
+
+        lua_pushinteger(L, results[i].rssi);
+        lua_setfield(L, -2, "rssi");
+
+        lua_seti(L, -2, i + 1);
+    }
+    luat_heap_free(results);
+    return 1;
+}
+
+static int l_wlan_smartconfig(lua_State *L) {
+    int tp = luaL_optinteger(L, 1, LUAT_SC_TYPE_ESPTOUCH);
+    if (tp == LUAT_SC_TYPE_STOP) {
+        luat_wlan_smartconfig_stop();
+        return 0;
+    }
+    else {
+        int ret = luat_wlan_smartconfig_start(tp);
+        lua_pushboolean(L, ret == 0 ? 1 : 0);
+        return 1;
+    }
+}
+
+// 获取mac
+static int l_wlan_get_mac(lua_State* L){
+    char tmp[6] = {0};
+    char tmpbuff[16] = {0};
+    luat_wlan_get_mac(luaL_optinteger(L, 1, 0), tmp);
+    sprintf_(tmpbuff, "%02X%02X%02X%02X%02X%02X", tmp[0], tmp[1], tmp[2], tmp[3], tmp[4], tmp[5]);
+    lua_pushstring(L, tmpbuff);
+    return 1;
+}
+
+// 启动AP
+static int l_wlan_ap_start(lua_State *L) {
+    size_t ssid_len = 0;
+    size_t password_len = 0;
+    luat_wlan_apinfo_t apinfo = {0};
+    const char* ssid = luaL_checklstring(L, 1, &ssid_len);
+    const char* password = luaL_optlstring(L, 2, "", &password_len);
+    if (ssid_len < 1) {
+        LLOGE("ssid MUST NOT EMTRY");
+        return 0;
+    }
+    if (ssid_len > 32) {
+        LLOGE("ssid too long [%s]", ssid);
+        return 0;
+    }
+    if (password_len > 63) {
+        LLOGE("password too long [%s]", password);
+        return 0;
+    }
+
+    memcpy(apinfo.ssid, ssid, ssid_len);
+    memcpy(apinfo.password, password, password_len);
+
+    int ret = luat_wlan_ap_start(&apinfo);
+    LLOGD("apstart ret %d", ret);
+    lua_pushboolean(L, ret == 0 ? 1 : 0);
+    return 1;
+}
+
+#include "rotable2.h"
+static const rotable_Reg_t reg_wlan[] =
+{
+    { "init",               ROREG_FUNC(l_wlan_init)},
+    { "mode",               ROREG_FUNC(l_wlan_mode)},
+    { "setMode",            ROREG_FUNC(l_wlan_mode)},
+    // { "setMode",           ROREG_FUNC(l_wlan_set_mode)},
+    // { "getMode",           ROREG_FUNC(l_wlan_get_mode)},
+    { "ready",              ROREG_FUNC(l_wlan_ready)},
+    { "connect",            ROREG_FUNC(l_wlan_connect)},
+    { "disconnect",         ROREG_FUNC(l_wlan_disconnect)},
+    { "scan",               ROREG_FUNC(l_wlan_scan)},
+    { "scanResult",         ROREG_FUNC(l_wlan_scan_result)},
+
+    // 配网相关
+    { "smartconfig",         ROREG_FUNC(l_wlan_smartconfig)},
+
+    { "getMac",              ROREG_FUNC(l_wlan_get_mac)},
+
+    // AP相关
+    { "createAP",            ROREG_FUNC(l_wlan_ap_start)},
+
+    // 常数
+    {"NONE",                ROREG_INT(LUAT_WLAN_MODE_NULL)},
+    {"STATION",             ROREG_INT(LUAT_WLAN_MODE_STA)},
+    {"AP",                  ROREG_INT(LUAT_WLAN_MODE_AP)},
+    {"STATIONAP",           ROREG_INT(LUAT_WLAN_MODE_APSTA)},
+
+    // smartconfig 配网
+    {"STOP",                ROREG_INT(0)},
+    {"ESPTOUCH",            ROREG_INT(LUAT_SC_TYPE_ESPTOUCH)},
+    {"AIRKISS",             ROREG_INT(LUAT_SC_TYPE_AIRKISS)},
+    {"ESPTOUCH_AIRKISS",    ROREG_INT(LUAT_SC_TYPE_ESPTOUCH_AIRKISS)},
+    {"ESPTOUCH_V2",         ROREG_INT(LUAT_SC_TYPE_ESPTOUCH_V2)},
+	{ NULL,                 ROREG_INT(0)}
+};
+
+LUAMOD_API int luaopen_wlan( lua_State *L ) {
+    luat_newlib2(L, reg_wlan);
+    return 1;
+}

+ 71 - 0
components/wlan/luat_wlan.h

@@ -0,0 +1,71 @@
+#include "luat_base.h"
+#include "luat_msgbus.h"
+#include "luat_malloc.h"
+
+typedef struct luat_wlan_config
+{
+    uint32_t mode;
+}luat_wlan_config_t;
+
+typedef struct luat_wlan_conninfo
+{
+    char ssid[36];
+    char password[64];
+    char bssid[8];
+    uint32_t authmode;
+    uint32_t auto_reconnection;
+    uint32_t auto_reconnection_delay_sec;
+}luat_wlan_conninfo_t;
+
+typedef struct luat_wlan_apinfo
+{
+    char ssid[36];
+    char password[64];
+}luat_wlan_apinfo_t;
+
+enum LUAT_WLAN_MODE {
+    LUAT_WLAN_MODE_NULL,
+    LUAT_WLAN_MODE_STA,
+    LUAT_WLAN_MODE_AP,
+    LUAT_WLAN_MODE_APSTA,
+    LUAT_WLAN_MODE_MAX
+};
+
+typedef struct luat_wlan_scan_result
+{
+    char ssid[33];
+    char bssid[6];
+    int16_t rssi;
+    int8_t ch;
+}luat_wlan_scan_result_t;
+
+
+
+int luat_wlan_init(luat_wlan_config_t *conf);
+int luat_wlan_mode(luat_wlan_config_t *conf);
+int luat_wlan_ready(void);
+int luat_wlan_connect(luat_wlan_conninfo_t* info);
+int luat_wlan_disconnect(void);
+int luat_wlan_scan(void);
+int luat_wlan_scan_get_result(luat_wlan_scan_result_t *results, int ap_limit);
+
+// 配网相关
+// --- smartconfig 配网
+enum LUAT_WLAN_SC_TYPE {
+    LUAT_SC_TYPE_STOP = 0,
+    LUAT_SC_TYPE_ESPTOUCH,
+    LUAT_SC_TYPE_AIRKISS,
+    LUAT_SC_TYPE_ESPTOUCH_AIRKISS,
+    LUAT_SC_TYPE_ESPTOUCH_V2
+};
+
+int luat_wlan_smartconfig_start(int tp);
+int luat_wlan_smartconfig_stop(void);
+
+// 数据类
+int luat_wlan_get_mac(int id, char* mac);
+int luat_wlan_set_mac(int id, char* mac);
+
+// AP类
+int luat_wlan_ap_start(luat_wlan_apinfo_t *apinfo);
+

+ 7 - 0
demo/camera/Air105/README.md

@@ -0,0 +1,7 @@
+# Air105摄像头的实例合集
+
+* capture - 捕捉图片并存入sd卡
+* raw_mode - 将摄像头数据通过w5500的udp协议发送到局域网,很慢
+* scanner - 演示扫码
+* synthesis - 综合演示, 扫码, 拍照, 存图
+* video - USB视频流, 可到5~10fps. 论图像质量,依然比不上某宝15块钱的USB摄像头

+ 0 - 336
demo/camera/Air105/capture_usb/GC032A_InitReg.txt

@@ -1,336 +0,0 @@
-0xf3,0xff,
-0xf7,0x01,
-0xf8,0x03,
-0xf9,0xce,
-0xfa,0x00,
-0xfc,0x02,
-0xfe,0x02,
-0x81,0x03,
-0xfe, 0x00,
-0x77, 0x64,
-0x78, 0x40,
-0x79, 0x60,
-
-0xfe, 0x00,
-0x03, 0x01,
-0x04, 0xcb,
-0x05, 0x01,
-0x06, 0xb2,
-0x07, 0x00,
-0x08, 0x10,
-
-0x0a, 0x00,
-0x0c, 0x00,
-0x0d, 0x01,
-0x0e, 0xe8,
-0x0f, 0x02,
-0x10, 0x88,
-
-0x17, 0x54,
-0x19, 0x08,
-0x1a, 0x0a,
-0x1f, 0x40,
-0x20, 0x30,
-0x2e, 0x80,
-0x2f, 0x2b,
-0x30, 0x1a,
-0xfe, 0x02,
-0x03, 0x02,
-0x05, 0xd7,
-0x06, 0x60,
-0x08, 0x80,
-0x12, 0x89,
-
-
-0xfe, 0x00,
-0x18, 0x02,
-0xfe, 0x02,
-0x40, 0x22,
-0x45, 0x00,
-0x46, 0x00,
-0x49, 0x20,
-0x4b, 0x3c,
-0x50, 0x20,
-0x42, 0x10,
-
-
-0xfe, 0x01,
-0x0a, 0xc5,
-0x45, 0x00,
-0xfe, 0x00,
-0x40, 0xff,
-0x41, 0x25,
-0x42, 0xef,
-0x43, 0x10,
-0x44, 0x82,
-0x46, 0x22,
-0x49, 0x03,
-0x52, 0x02,
-0x54, 0x00,
-0xfe, 0x02,
-0x22, 0xf6,
-
-
-0xfe, 0x01,
-0xc1, 0x38,
-0xc2, 0x4c,
-0xc3, 0x00,
-0xc4, 0x2c,
-0xc5, 0x24,
-0xc6, 0x18,
-0xc7, 0x28,
-0xc8, 0x11,
-0xc9, 0x15,
-0xca, 0x20,
-0xdc, 0x7a,
-0xdd, 0xa0,
-0xde, 0x80,
-0xdf, 0x88,
-
-
-0xfe, 0x01,
-0x50, 0xc1,
-0x56, 0x34,
-0x58, 0x04,
-0x65, 0x06,
-0x66, 0x0f,
-0x67, 0x04,
-0x69, 0x20,
-0x6a, 0x40,
-0x6b, 0x81,
-0x6d, 0x12,
-0x6e, 0xc0,
-0x7b, 0x2a,
-0x7c, 0x0c,
-0xfe, 0x01,
-0x90, 0xe3,
-0x91, 0xc2,
-0x92, 0xff,
-0x93, 0xe3,
-0x95, 0x1c,
-0x96, 0xff,
-0x97, 0x44,
-0x98, 0x1c,
-0x9a, 0x44,
-0x9b, 0x1c,
-0x9c, 0x64,
-0x9d, 0x44,
-0x9f, 0x71,
-0xa0, 0x64,
-0xa1, 0x00,
-0xa2, 0x00,
-0x86, 0x00,
-0x87, 0x00,
-0x88, 0x00,
-0x89, 0x00,
-0xa4, 0xc2,
-0xa5, 0x9b,
-0xa6, 0xc8,
-0xa7, 0x92,
-0xa9, 0xc9,
-0xaa, 0x96,
-0xab, 0xa9,
-0xac, 0x99,
-0xae, 0xce,
-0xaf, 0xa9,
-0xb0, 0xcf,
-0xb1, 0x9d,
-0xb3, 0xcf,
-0xb4, 0xac,
-0xb5, 0x00,
-0xb6, 0x00,
-0x8b, 0x00,
-0x8c, 0x00,
-0x8d, 0x00,
-0x8e, 0x00,
-0x94, 0x55,
-0x99, 0xa6,
-0x9e, 0xaa,
-0xa3, 0x0a,
-0x8a, 0x00,
-0xa8, 0x55,
-0xad, 0x55,
-0xb2, 0x55,
-0xb7, 0x05,
-0x8f, 0x00,
-0xb8, 0xc7,
-0xb9, 0xa0,
-
-0xfe, 0x01,
-0xd0, 0x40,
-0xd1, 0x00,
-0xd2, 0x00,
-0xd3, 0xfa,
-0xd4, 0x4a,
-0xd5, 0x02,
-
-0xd6, 0x44,
-0xd7, 0xfa,
-0xd8, 0x04,
-0xd9, 0x08,
-0xda, 0x5c,
-0xdb, 0x02,
-0xfe, 0x00,
-
-
-0xfe, 0x00,
-0xba, 0x00,
-0xbb, 0x06,
-0xbc, 0x0b,
-0xbd, 0x10,
-0xbe, 0x19,
-0xbf, 0x26,
-0xc0, 0x33,
-0xc1, 0x3f,
-0xc2, 0x54,
-0xc3, 0x68,
-0xc4, 0x7c,
-0xc5, 0x8c,
-0xc6, 0x9c,
-0xc7, 0xb4,
-0xc8, 0xc9,
-0xc9, 0xd8,
-0xca, 0xe4,
-0xcb, 0xee,
-0xcc, 0xf4,
-0xcd, 0xf9,
-0xce, 0xfa,
-0xcf, 0xff,
-
-
-0xfe, 0x00,
-0x5a, 0x08,
-0x5b, 0x0f,
-0x5c, 0x15,
-0x5d, 0x1c,
-0x5e, 0x28,
-0x5f, 0x36,
-0x60, 0x45,
-0x61, 0x51,
-0x62, 0x6a,
-0x63, 0x7d,
-0x64, 0x8d,
-0x65, 0x98,
-0x66, 0xa2,
-0x67, 0xb5,
-0x68, 0xc3,
-0x69, 0xcd,
-0x6a, 0xd4,
-0x6b, 0xdc,
-0x6c, 0xe3,
-0x6d, 0xf0,
-0x6e, 0xf9,
-0x6f, 0xff,
-
-
-0xfe, 0x00,
-0x70, 0x50,
-
-
-0xfe, 0x00,
-0x4f, 0x01,
-0xfe, 0x01,
-0x0c, 0x01,
-0x0d, 0x00,
-0x12, 0xa0,
-0x13, 0x4a,
-0x44, 0x04,
-0x1f, 0x40,
-0x20, 0x40,
-0x23, 0x0a,
-0x26, 0x9a,
-0x3e, 0x20,
-0x3f, 0x2d,
-0x40, 0x40,
-0x41, 0x5b,
-0x42, 0x82,
-0x43, 0xb7,
-0x04, 0x0a,
-0x02, 0x79,
-0x03, 0xc0,
-
-
-0xfe, 0x01,
-0xcc, 0x08,
-0xcd, 0x08,
-0xce, 0xa4,
-0xcf, 0xec,
-
-
-0xfe, 0x00,
-0x81, 0xb8,
-0x82, 0x04,
-0x83, 0x10,
-0x84, 0x01,
-0x86, 0x50,
-0x87, 0x18,
-0x88, 0x10,
-0x89, 0x70,
-0x8a, 0x20,
-0x8b, 0x10,
-0x8c, 0x08,
-0x8d, 0x0a,
-
-
-0xfe, 0x00,
-0x8f, 0xaa,
-0x90, 0x1c,
-0x91, 0x52,
-0x92, 0x03,
-0x93, 0x03,
-0x94, 0x08,
-0x95, 0x6a,
-0x97, 0x00,
-0x98, 0x00,
-
-
-0xfe, 0x00,
-0x9a, 0x30,
-0x9b, 0x50,
-0xa1, 0x30,
-0xa2, 0x66,
-0xa4, 0x28,
-0xa5, 0x30,
-0xaa, 0x28,
-0xac, 0x32,
-
-
-0xfe, 0x00,
-0xd1, 0x3f,
-0xd2, 0x3f,
-0xd3, 0x38,
-0xd6, 0xf4,
-0xd7, 0x1d,
-0xdd, 0x72,
-0xde, 0x84,
-
-0xfe, 0x00,
-0x05, 0x01,
-0x06, 0xad,
-0x07, 0x00,
-0x08, 0x10,
-
-0xfe, 0x01,
-0x25, 0x00,
-0x26, 0x4d,
-
-0x27, 0x01,
-0x28, 0xce,
-0x29, 0x01,
-0x2a, 0xce,
-0x2b, 0x01,
-0x2c, 0xce,
-0x2d, 0x01,
-0x2e, 0xce,
-0x2f, 0x01,
-0x30, 0xce,
-0x31, 0x01,
-0x32, 0xce,
-0x33, 0x01,
-0x34, 0xce,
-0x3c, 0x10,
-0xfe, 0x00,
-0xfe,0x00,
-0x44,0x06,
-0x46,0x0f,
-#此为注释

+ 3 - 0
demo/camera/Air105/capture_usb/README.md

@@ -0,0 +1,3 @@
+# 本demo已废弃
+
+请使用 video 示例

+ 0 - 110
demo/camera/Air105/capture_usb/main.lua

@@ -1,110 +0,0 @@
---[[
-
-特别提醒: 本demo已经有更好的替代品: video, 请使用新版video demo, 效果比本demo好很多.
-
-这是Air105+摄像头, 通过USB传输JPG到上位机显示图片的示例, 速率2fps, 色彩空间 RGB565, 不要期望太高
-本demo不需要lcd屏,但lcd的代码暂不可省略
-
-本demo需要V0006, 20220331之后编译的固件版本, 老版本不可用
-
-测试流程:
-1. 先选取最新固件, 配合本demo的main.lua及GC032A_InitReg.txt, 两个文件都需要下载到设备
-2. 断开USB, 将拨动开关切换到另一端, 切勿带电操作!!!
-3. 重新插入USB
-4. 打开上位机, 选择正确的COM口, 然后开始读取
-
--- USB驱动下载 https://doc.openluat.com/wiki/21?wiki_page_id=2070
--- USB驱动与 合宙Cat.1的USB驱动是一致的
-
-上位机下载: https://gitee.com/openLuat/luatos-soc-air105/attach_files
-上位机源码: https://gitee.com/openLuat/luatos-soc-air105 C#写的, 就能用, 勿生产
-
-
-]]
-
-PROJECT = "usbcamera"
-VERSION = "1.0.0"
-
-sys = require("sys")
-
-if wdt then
-    wdt.init(15000)--初始化watchdog设置为15s
-    sys.timerLoopStart(wdt.feed, 10000)--10s喂一次狗
-end
-
-spi_lcd = spi.deviceSetup(5,pin.PC14,0,0,8,48*1000*1000,spi.MSB,1,1)
-log.info("lcd.init",
-lcd.init("st7789",{port = "device",pin_dc = pin.PE08 ,pin_rst = pin.PC12,pin_pwr = pin.PE09,direction = 0,w = 240,h = 320,xoffset = 0,yoffset = 0},spi_lcd))
-
---GC032A输出rgb图像初始化命令
-local GC032A_InitReg =
-{
-	zbar_scan = 0,--是否为扫码
-    draw_lcd = 0,--是否向lcd输出
-    i2c_id = 0,
-	i2c_addr = 0x21,
-    pwm_id = 5;
-    pwm_period  = 12*1000*1000,
-    pwm_pulse = 0,
-	sensor_width = 640,
-	sensor_height = 480,
-    color_bit = 16,
-	init_cmd ="/luadb/GC032A_InitReg.txt"--此方法将初始化指令写在外部文件,支持使用 # 进行注释
-}
-
-local uartid = uart.VUART_0 -- 根据实际设备选取不同的uartid
---初始化
-local result = uart.setup(
-    uartid,--串口id
-    115200,--波特率
-    8,--数据位
-    1--停止位
-)
-
-local camera_pwdn = gpio.setup(pin.PD06, 1, gpio.PULLUP) -- PD06 camera_pwdn引脚
-local camera_rst = gpio.setup(pin.PD07, 1, gpio.PULLUP) -- PD07 camera_rst引脚
-
-camera_rst(0)
-
--- 拍照, 自然就是RGB输出了
-local camera_id = camera.init(GC032A_InitReg)--屏幕输出rgb图像
-
-log.info("摄像头启动")
-camera.start(camera_id)--开始指定的camera
-log.info("摄像头启动完成")
-
-usbapp.start(0)
-
-camera.on(0, "scanned", function()
-    sys.publish("scanned")
-end)
-
-sys.taskInit(function()
-
-    while 1 do
-            -- 稍微等待一下
-            sys.wait(100)
-            log.debug("摄像头捕获图像")
-            -- 删除老的图片,避免重复显示
-            os.remove("/temp.jpg")
-            camera.capture(camera_id, "/temp.jpg", 1)
-            sys.waitUntil("scanned", 1000)
-            local f = io.open("/temp.jpg", "r")
-            local data
-            if f then -- 若文件存在, 必然能打开并读取, 否则肯定拍照失败了
-                data = f:read("*a")
-                log.info("fs", #data)
-                f:close()
-
-                -- 请使用上位机读取
-                uart.write(uart.VUART_0, "Air105 USB JPG " .. tostring(#data) .. "\r\n")
-                uart.write(uart.VUART_0, data)
-            end
-    end
-
-end)
-
--- 用户代码已结束---------------------------------------------
--- 结尾总是这一句
-sys.run()
--- sys.run()之后后面不要加任何语句!!!!!

+ 13 - 0
demo/camera/Air105/scanner/main.lua

@@ -21,6 +21,19 @@ BL           (PE09) --开发板上的U3_TX
 提示:
 提示:
 1. 只使用SPI的时钟线(SCK)和数据输出线(MOSI), 其他均为GPIO脚
 1. 只使用SPI的时钟线(SCK)和数据输出线(MOSI), 其他均为GPIO脚
 2. 数据输入(MISO)和片选(CS), 虽然是SPI, 但已复用为GPIO, 并非固定,是可以自由修改成其他脚
 2. 数据输入(MISO)和片选(CS), 虽然是SPI, 但已复用为GPIO, 并非固定,是可以自由修改成其他脚
+
+-- USB驱动下载 https://doc.openluat.com/wiki/21?wiki_page_id=2070
+-- USB驱动与 合宙Cat.1的USB驱动是一致的
+
+扫码解码会输出日志, 也会输出到USB HID.
+
+若需要通过USB HID查看
+1. 要安装USB驱动
+2. 刷好脚本, 务必把txt也下载下去,总共3个文件.
+3. 断电, 拨动切换开关, 重新连接电脑
+4. 打开记事本, 光标处于输入状态
+5. 移动摄像头进行扫码, 结果会输出到记事本, 每行一次
+
 ]]
 ]]
 
 
 if wdt then
 if wdt then

+ 23 - 24
demo/camera/Air105/video/camera_test.lua

@@ -2,16 +2,16 @@
 --编译好的工具:https://gitee.com/openLuat/luatos-soc-air105/attach_files
 --编译好的工具:https://gitee.com/openLuat/luatos-soc-air105/attach_files
 local GC032A_InitReg =
 local GC032A_InitReg =
 {
 {
-	zbar_scan = 0,--是否为扫码
-    draw_lcd = 0,--是否向lcd输出
+	zbar_scan = 0,--是否为扫码, 扫码模式会显示灰度图像!!!
+    draw_lcd = 0,--是否向lcd输出, 若没有接lcd显示屏就不用设置为1
     i2c_id = 0,
     i2c_id = 0,
 	i2c_addr = 0x21,
 	i2c_addr = 0x21,
     pwm_id = 5;
     pwm_id = 5;
-    pwm_period  = 24*1000*1000,
+    pwm_period  = 24*1000*1000, -- 摄像头的时钟线的波特率
     pwm_pulse = 0,
     pwm_pulse = 0,
-	sensor_width = 640,
+	sensor_width = 640, -- GC032A摄像头的实际分辨率是30w,但内存不足,实际显示居中的1/4图像
 	sensor_height = 480,
 	sensor_height = 480,
-    color_bit = 16,
+    color_bit = 16, -- 颜色空间是 RGB565
 	init_cmd = "/luadb/GC032A_InitReg.txt"--此方法将初始化指令写在外部文件,支持使用 # 进行注释
 	init_cmd = "/luadb/GC032A_InitReg.txt"--此方法将初始化指令写在外部文件,支持使用 # 进行注释
 
 
 }
 }
@@ -20,6 +20,24 @@ local camera_pwdn = gpio.setup(pin.PD06, 1, gpio.PULLUP) -- PD06 camera_pwdn引
 local camera_rst = gpio.setup(pin.PD07, 1, gpio.PULLUP) -- PD07 camera_rst引脚
 local camera_rst = gpio.setup(pin.PD07, 1, gpio.PULLUP) -- PD07 camera_rst引脚
 
 
 usbapp.start(0)
 usbapp.start(0)
+
+sys.taskInit(function()
+	camera_rst(0)
+    uart.setup(
+        uart.VUART_0,-- USB虚拟串口id
+        115200,--波特率
+        8,--数据位
+        1--停止位
+    )
+	-- 拍照, 自然就是RGB输出了
+	local camera_id = camera.init(GC032A_InitReg)--屏幕输出rgb图像
+
+	log.info("摄像头启动")
+    camera.video(camera_id, 320, 240, uart.VUART_0)
+	log.info("摄像头启动完成")
+end)
+
+-- 以下是扫码的回调, 仅当zbar_scan=1时会有回调
 camera.on(0, "scanned", function(id, str)
 camera.on(0, "scanned", function(id, str)
     if type(str) == 'string' then
     if type(str) == 'string' then
         log.info("扫码结果", str)
         log.info("扫码结果", str)
@@ -38,22 +56,3 @@ camera.on(0, "scanned", function(id, str)
         log.error("摄像头没有数据")
         log.error("摄像头没有数据")
     end
     end
 end)
 end)
-
-sys.taskInit(function()
-	camera_rst(0)
-    uart.setup(
-        uart.VUART_0,--串口id
-        115200,--波特率
-        8,--数据位
-        1--停止位
-    )
-	-- 拍照, 自然就是RGB输出了
-	local camera_id = camera.init(GC032A_InitReg)--屏幕输出rgb图像
-
-	log.info("摄像头启动")
-    camera.video(camera_id, 320, 240, uart.VUART_0)
-	log.info("摄像头启动完成")
-    while 1 do
-    	sys.wait(10000)
-    end
-end)

+ 27 - 3
demo/camera/Air105/video/main.lua

@@ -1,14 +1,38 @@
 
 
 -- LuaTools需要PROJECT和VERSION这两个信息
 -- LuaTools需要PROJECT和VERSION这两个信息
 PROJECT = "camera_video"
 PROJECT = "camera_video"
-VERSION = "1.1"
-PRODUCT_KEY = "s1uUnY6KA06ifIjcutm5oNbG3MZf5aUv" --换成自己的
+VERSION = "1.0.0"
+
+--[[
+这是Air105+摄像头, 通过USB传输到上位机显示图像的示例, 速率5~10fps, 不要期望太高
+本demo不需要lcd屏,但lcd的代码暂不可省略
+
+本demo需要最新固件
+
+测试流程:
+1. 先选取最新固件, 配合本demo的3个文件,3个文件都需要下载到设备,包括txt文件!!!
+2. 查看日志, 若提示摄像头无数据, 检查摄像头连线,并检查是否已经下载txt文件.
+3. 断开USB, 将拨动开关切换到另一端, 切勿带电操作!!!
+4. 重新插入USB
+5. 打开上位机, 选择正确的COM口, 然后开始读取
+
+-- USB驱动下载 https://doc.openluat.com/wiki/21?wiki_page_id=2070
+-- USB驱动与 合宙Cat.1的USB驱动是一致的
+
+上位机下载: https://gitee.com/openLuat/luatos-soc-air105/attach_files
+上位机源码: https://gitee.com/openLuat/luatos-soc-air105 C#写的, 就能用, 勿生产
+
+]]
+
+
 -- sys库是标配
 -- sys库是标配
 _G.sys = require("sys")
 _G.sys = require("sys")
 _G.sysplus = require("sysplus")
 _G.sysplus = require("sysplus")
+
 log.style(1)
 log.style(1)
 require "camera_test"
 require "camera_test"
+
 -- 用户代码已结束---------------------------------------------
 -- 用户代码已结束---------------------------------------------
 -- 结尾总是这一句
 -- 结尾总是这一句
 sys.run()
 sys.run()
--- sys.run()之后后面不要加任何语句!!!!!
+-- sys.run()之后后面不要加任何语句!!!!!

+ 14 - 4
demo/crypto/main.lua

@@ -49,15 +49,23 @@ sys.taskInit(function()
 
 
     -- DES-ECB 加解密
     -- DES-ECB 加解密
     local data1 = crypto.cipher_encrypt("DES-ECB", "PKCS7", "abcdefg", "12345678")
     local data1 = crypto.cipher_encrypt("DES-ECB", "PKCS7", "abcdefg", "12345678")
-    print(data1:toHex())
-    local data2 = crypto.cipher_decrypt("DES-ECB", "PKCS7", data1, "12345678")
-    print(data2)
+    if data1 then -- DES-ECB 在某些平台不支持的
+        print(data1:toHex())
+        local data2 = crypto.cipher_decrypt("DES-ECB", "PKCS7", data1, "12345678")
+        print(data2)
+    end
 
 
     -- 打印所有支持的cipher
     -- 打印所有支持的cipher
     if crypto.cipher_list then
     if crypto.cipher_list then
         log.info("cipher", "list", json.encode(crypto.cipher_list()))
         log.info("cipher", "list", json.encode(crypto.cipher_list()))
     end
     end
 
 
+    for i=1, 10 do
+        sys.wait(100)
+        log.info("crypto", "真随机数",string.unpack("I",crypto.trng(4)))
+        log.info("crypto", "伪随机数",math.random())
+    end
+
     -- totp的密钥
     -- totp的密钥
     local secret = "VK54ZXPO74ISEM2E"
     local secret = "VK54ZXPO74ISEM2E"
     --写死时间戳用来测试
     --写死时间戳用来测试
@@ -66,9 +74,11 @@ sys.taskInit(function()
     for i=1,600,30 do
     for i=1,600,30 do
         local r = crypto.totp(secret,ts+i)
         local r = crypto.totp(secret,ts+i)
         local time = os.date("*t",ts+i + 8*3600)--东八区
         local time = os.date("*t",ts+i + 8*3600)--东八区
-        log.info("totp",r,time.hour,time.min,time.sec)
+        log.info("totp", string.format("%06d" ,r),time.hour,time.min,time.sec)
     end
     end
 
 
+    log.info("crypto", "ALL Done")
+    sys.wait(100000)
 end)
 end)
 
 
 -- 用户代码已结束---------------------------------------------
 -- 用户代码已结束---------------------------------------------

+ 58 - 0
demo/nimble/esp32c3/main.lua

@@ -0,0 +1,58 @@
+
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "nimbledemo"
+VERSION = "1.0.0"
+
+log.info("main", PROJECT, VERSION)
+
+-- 一定要添加sys.lua !!!!
+sys = require("sys")
+
+-- --添加硬狗防止程序卡死
+-- if wdt then
+--     wdt.init(15000)--初始化watchdog设置为15s
+--     sys.timerLoopStart(wdt.feed, 10000)--10s喂一次狗
+-- end
+
+-- 监听BLE主适配的状态变化
+-- sys.subscribe("BLE_STATE_INC", function(state)
+--     log.info("ble", "ble state changed", state)
+--     if state == 1 then
+--         nimble.server_init()
+--     else
+--         nimble.server_deinit()
+--     end
+-- end)
+
+-- 监听GATT服务器的WRITE_CHR, 收到Write数据时会回调该函数
+sys.subscribe("BLE_GATT_WRITE_CHR", function(info, data)
+    -- info 是个table, 但当前没有数据
+    -- data 是BLE收到的数据
+    log.info("ble", "data got!!", data:toHex())
+end)
+
+-- TODO 支持传数据(read)和推送数据(notify)
+
+-- 配合微信小程序 "LuatOS蓝牙调试"
+-- 1. 若开发板无天线, 将手机尽量靠近芯片也能搜到
+-- 2. 该小程序是开源的, 每次write会自动分包
+-- https://gitee.com/openLuat/luatos-miniapps
+
+sys.taskInit(function()
+    sys.wait(1000)
+    -- nimble.debug(6)
+    -- 默认模式是BLE server, 无pin码验证
+    nimble.init("LuatOS-" .. wlan.getMac()) -- 蓝牙名称可修改
+
+    -- 下面是周期性发送数据, nimble.send_msg可在任意代码中调用, 不依赖task
+    while 1 do
+        sys.wait(3000)
+        nimble.send_msg(1, 0, string.char(0x5A, 0xA5, 0x12, 0x34, 0x56))
+    end
+end)
+
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 27 - 0
demo/wlan/esp32c3/ap_get_start/index.html

@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html>
+    <header>
+        <meta charset="utf-8"/>
+        <title>Http Server Get-Start</title>
+        <!-- fetch api-->
+        <script type="text/javascript">
+            function led(key) {
+                fetch("/led/" + key)
+            }
+        </script>
+    </header>
+    <body>
+        <h2>点击按钮, led灯会亮起或熄灭</h2>
+        <div>
+            <div>
+                <button onclick="led(1)">LED亮</button>
+            </div>
+            <div>
+                <button onclick="led(0)">LED灭</button>
+            </div>
+        </div>
+        <div>
+            <h4>Power by <a href="https://wiki.luatos.com">LuatOS</a></h4>
+        </div>
+    </body>
+</html>

+ 45 - 0
demo/wlan/esp32c3/ap_get_start/main.lua

@@ -0,0 +1,45 @@
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "wifidemo"
+VERSION = "1.0.0"
+
+-- 引入必要的库文件(lua编写), 内部库不需要require
+sys = require("sys")
+require("sysplus")
+
+
+-- function meminfo()
+--     log.info("lua", rtos.meminfo())
+--     log.info("sys", rtos.meminfo("sys"))
+-- end
+
+-- 初始化LED灯, 开发板上左右2个led分别是gpio12/gpio13
+local LEDA= gpio.setup(12, 0, gpio.PULLUP)
+local LEDB= gpio.setup(13, 0, gpio.PULLUP)
+
+sys.taskInit(function()
+    sys.wait(1000)
+    wlan.init()
+    sys.wait(300)
+    -- AP的ssid和password
+    wlan.createAP("luatos", "12341234")
+
+    sys.wait(1000)
+    httpsrv.start(80, function(fd, method, uri, headers, body)
+        log.info("httpsrv", method, uri, json.encode(headers), body)
+        -- meminfo()
+        if uri == "/led/1" then
+            LEDA(1)
+            return 200, {}, "ok"
+        elseif uri == "/led/0" then
+            LEDA(0)
+            return 200, {}, "ok"
+        end
+        return 404, {}, "Not Found" .. uri
+    end)
+    log.info("web", "pls open url http://192.168.4.1/")
+end)
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 43 - 0
demo/wlan/esp32c3/hello_world/main.lua

@@ -0,0 +1,43 @@
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "wifidemo"
+VERSION = "1.0.0"
+
+-- 引入必要的库文件(lua编写), 内部库不需要require
+sys = require("sys")
+require("sysplus")
+
+-- sys.subscribe("WLAN_READY", function ()
+--     print("!!! wlan ready event !!!")
+-- end)
+
+-- sys.taskInit(function()
+--     while 1 do
+--         sys.wait(5000)
+--         log.info("lua", rtos.meminfo())
+--         log.info("sys", rtos.meminfo("sys"))
+--     end
+
+-- end)
+
+sys.taskInit(function()
+    sys.wait(1000)
+    wlan.init()
+    wlan.connect("uiot", "1234567890")
+    log.info("wlan", "wait for IP_READY")
+    sys.waitUntil("IP_READY", 30000)
+    if wlan.ready() then
+        log.info("wlan", "ready !!")
+        sys.wait(100)
+        -- local url = "http://ip.nutz.cn/json"
+        local url = "http://nutzam.com/1.txt"
+        local code, headers, body = http2.request("GET", url).wait()
+        log.info("http", code, json.encode(headers), #body)
+    else
+        print("wlan NOT ready!!!!")
+    end
+end)
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 27 - 0
demo/wlan/esp32c3/httpsrv/index.html

@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html>
+    <header>
+        <meta charset="utf-8"/>
+        <title>Http Server Get-Start</title>
+        <!-- fetch api-->
+        <script type="text/javascript">
+            function led(key) {
+                fetch("/led/" + key)
+            }
+        </script>
+    </header>
+    <body>
+        <h2>点击按钮, led灯会亮起或熄灭</h2>
+        <div>
+            <div>
+                <button onclick="led(1)">LED亮</button>
+            </div>
+            <div>
+                <button onclick="led(0)">LED灭</button>
+            </div>
+        </div>
+        <div>
+            <h4>Power by <a href="https://wiki.luatos.com">LuatOS</a></h4>
+        </div>
+    </body>
+</html>

+ 55 - 0
demo/wlan/esp32c3/httpsrv/main.lua

@@ -0,0 +1,55 @@
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "wifidemo"
+VERSION = "1.0.0"
+
+-- 引入必要的库文件(lua编写), 内部库不需要require
+sys = require("sys")
+require("sysplus")
+
+
+-- function meminfo()
+--     log.info("lua", rtos.meminfo())
+--     log.info("sys", rtos.meminfo("sys"))
+-- end
+
+-- 初始化LED灯, 开发板上左右2个led分别是gpio12/gpio13
+local LEDA= gpio.setup(12, 0, gpio.PULLUP)
+local LEDB= gpio.setup(13, 0, gpio.PULLUP)
+
+sys.taskInit(function()
+    sys.wait(1000)
+    wlan.init()
+    -- 修改成自己的ssid和password
+    wlan.connect("myssid", "mypassword")
+    -- wlan.connect("uiot", "")
+    log.info("wlan", "wait for IP_READY")
+    
+    while not wlan.ready() do
+        local ret, ip = sys.waitUntil("IP_READY", 30000)
+        -- wlan连上之后, 这里会打印ip地址
+        log.info("ip", ret, ip)
+        if ip then
+            _G.wlan_ip = ip
+        end
+    end
+    log.info("wlan", "ready !!", wlan.getMac())
+    sys.wait(1000)
+    httpsrv.start(80, function(fd, method, uri, headers, body)
+        log.info("httpsrv", method, uri, json.encode(headers), body)
+        -- meminfo()
+        if uri == "/led/1" then
+            LEDA(1)
+            return 200, {}, "ok"
+        elseif uri == "/led/0" then
+            LEDA(0)
+            return 200, {}, "ok"
+        end
+        return 404, {}, "Not Found" .. uri
+    end)
+    log.info("web", "pls open url http://" .. _G.wlan_ip .. "/")
+end)
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 76 - 0
demo/wlan/esp32c3/iotda/main.lua

@@ -0,0 +1,76 @@
+PROJECT = "gpiodemo"
+VERSION = "1.0.0"
+
+-- 一定要添加sys.lua !!!!
+local sys = require "sys"
+require("sysplus")
+log.info("main", "iotda demo")
+
+
+local device_id     = ""    --改为你自己的设备id
+local device_secret = ""    --改为你自己的设备密钥
+
+local mqttc = nil
+
+sys.taskInit(function()
+    log.info("wlan", "wlan_init:", wlan.init())
+    wlan.setMode(wlan.STATION)
+    wlan.connect("CMCC_EDU", "88995500", 1)
+    local result, data = sys.waitUntil("IP_READY")
+    log.info("wlan", "IP_READY", result, data)
+    
+    local client_id,user_name,password = iotauth.iotda(device_id,device_secret)
+    log.info("iotda",client_id,user_name,password)
+    
+    mqttc = mqtt.create(nil,"a16203e7a0.iot-mqtts.cn-north-4.myhuaweicloud.com", 1883)
+
+    mqttc:auth(client_id,user_name,password)
+    mqttc:keepalive(30) -- 默认值240s
+    mqttc:autoreconn(true, 3000) -- 自动重连机制
+
+    mqttc:on(function(mqtt_client, event, data, payload)
+        -- 用户自定义代码
+        log.info("mqtt", "event", event, mqtt_client, data, payload)
+        if event == "conack" then
+            sys.publish("mqtt_conack")
+            mqtt_client:subscribe("/luatos/123456")
+        elseif event == "recv" then
+            log.info("mqtt", "downlink", "topic", data, "payload", payload)
+        elseif event == "sent" then
+            log.info("mqtt", "sent", "pkgid", data)
+        end
+    end)
+
+    mqttc:connect()
+    sys.wait(10000)
+    mqttc:subscribe("/luatos/123456")
+	sys.waitUntil("mqtt_conack")
+    while true do
+        -- mqttc自动处理重连
+        local ret, topic, data, qos = sys.waitUntil("mqtt_pub", 30000)
+        if ret then
+            if topic == "close" then break end
+            mqttc:publish(topic, data, qos)
+        end
+    end
+    mqttc:close()
+    mqttc = nil
+end)
+
+sys.taskInit(function()
+	local topic = "/luatos/123456"
+	local payload = "123"
+	local qos = 1
+    local result, data = sys.waitUntil("IP_READY")
+    while true do
+        sys.wait(5000)
+        if mqttc:ready() then
+            local pkgid = mqttc:publish(topic, payload, qos)
+        end
+    end
+end)
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 127 - 0
demo/wlan/esp32c3/smartconfig_esptouch/main.lua

@@ -0,0 +1,127 @@
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "wifidemo"
+VERSION = "1.0.0"
+
+--[[
+本demo需要 V100x系列固件, 不兼容V000x系列
+https://gitee.com/openLuat/LuatOS/releases
+]]
+
+-- 引入必要的库文件(lua编写), 内部库不需要require
+sys = require("sys")
+require("sysplus")
+
+sys.subscribe("IP_READY", function(ip)
+    log.info("wlan", "ip ready", ip)
+    -- 联网成功, 可以发起http, mqtt, 等请求了
+end)
+
+fdb.kvdb_init()
+
+-- 把BOOT键, 即GPIO9, 作为清除配网信息的按钮
+BTN_BOOT = 9
+gpio.debounce(BTN_BOOT, 1000)
+gpio.setup(BTN_BOOT, function()
+    log.info("gpio", "boot button pressed")
+    sys.publish("BTN_BOOT")
+end)
+
+sys.taskInit(function()
+    sys.wait(500) -- 这里等500ms只是方便看日志,非必须
+    wlan.init() -- 初始化wifi协议栈
+
+    -- 获取上次保存的配网信息, 如果存在就直接联网, 不需要配网了
+    -- 注意, fdb保存的数据是掉电存储的, 刷脚本/刷固件也不会清除
+    -- 如需完全清除配置信息, 可调用 fdb.clear() 全清
+    if fdb.kv_get("wlan_ssid") then
+       wlan.connect(fdb.kv_get("wlan_ssid"), fdb.kv_get("wlan_passwd"))
+       return -- 等联网就行了
+    end
+
+    -- 以下是smartconfig之 esptouch 配网
+    -- 配网APP请搜索 esptouch , 当前最新版2.3.0
+    -- 配网时选用 esptouch, 虽然esptouch V2也是支持的,但 esptouch兼容性比较好
+    -- ESP32C3仅支持2.4G的wifi, 5G wifi是不支持的
+    -- 配网时, 手机应靠近模块, 以便更快配网成功
+    while 1 do
+        -- 启动配网, 默认是esptouch模式
+        wlan.smartconfig()
+        local ret, ssid, passwd = sys.waitUntil("SC_RESULT", 180*1000) -- 等3分钟
+        if ret == false then
+            log.info("smartconfig", "timeout")
+            wlan.smartconfig(wlan.STOP)
+            sys.wait(3000) -- 再等3s重新配网, 或者直接reboot也行
+        else
+            -- 获取配网后, ssid和passwd会有值
+            log.info("smartconfig", ssid, passwd)
+            -- 值得注意的是, 存在ssid和passwd填错的情况, 这里按获取到IP来算成功
+            local ret = sys.waitUntil("IP_READY", 30000)
+            if ret then
+                -- 获取IP成功, 将配网信息存入fdb, 做持久化存储
+                log.info("fdb", "save ssid and passwd")
+                fdb.kv_set("wlan_ssid", ssid)
+                fdb.kv_set("wlan_passwd", passwd)
+                -- 等3秒再重启, 因为esptouch联网后会发生广播, 告知APP配网成功
+                log.info("wifi", "wait 3s to reboot")
+                sys.wait(3000)
+                -- 这里建议重启, 当然这也不是强制的
+                -- 重启后有配网信息, 所以就自动连接
+                rtos.reboot()
+            end
+        end
+    end
+end)
+
+
+-- 下面的task是演示通过按键清除配网信息
+-- 实现的效果是: 开机500ms后, 长按BOOT按钮3秒以上, 清除配网信息, 然后重启或者快速闪灯.
+sys.taskInit(function()
+    -- 开机后, 先等500ms
+    sys.wait(500)
+    -- 然后开始监听BTN按钮
+    while true do
+        local flag = true
+        while true do
+            -- 等待boot按钮按下
+            local ret = sys.waitUntil("BTN_BOOT", 3000)
+            --log.info("gpio", "BTN_BOOT", "wait", ret)
+            if ret then
+                break
+            end
+        end
+        log.info("wifi", "Got BOOT button pressed")
+        for i=1, 30 do
+            -- 要求持续3s的低电平, 若中途松开了,就无效咯
+            if gpio.get(BTN_BOOT) ~= 0 then
+                log.info("wifi", "BOOT button released, wait next press")
+                flag = false
+                break
+            end
+            sys.wait(100)
+        end
+
+        if flag then
+            -- 用户的确要请求配网信息, 那就清除吧
+            log.info("gpio", "boot pressed 3s, remove ssid/passwd")
+            fdb.kv_del("wlan_ssid")
+            fdb.kv_del("wlan_passwd")
+            -- fdb.clear() -- 这里还有一个方案是清除fdb里的全部数据,从业务上说相当于恢复出厂配置
+            log.info("gpio", "removed, wait for reboot")
+
+            -- 方案1, 直接重启, 重启后因为没有配网数据了, 就自动开始配网
+            -- rtos.reboot()
+
+            -- 方案2, 100ms闪灯, 让用户自行复位重启
+            gpio.setup(12, 0)
+            while 1 do
+                gpio.toggle(12)
+                sys.wait(100)
+            end
+        end
+    end
+end)
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 30 - 0
demo/wlan/esp32c3/wifi_scan/main.lua

@@ -0,0 +1,30 @@
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "wifidemo"
+VERSION = "1.0.0"
+
+-- 引入必要的库文件(lua编写), 内部库不需要require
+sys = require("sys")
+require("sysplus")
+
+-- wifi扫描成功后, 会有WLAN_SCAN_DONE消息, 读取即可
+sys.subscribe("WLAN_SCAN_DONE", function ()
+    local results = wlan.scanResult()
+    log.info("scan", "results", #results)
+    for k,v in pairs(results) do
+        log.info("scan", v["ssid"], v["rssi"], (v["bssid"]:toHex()))
+    end
+end)
+
+sys.taskInit(function()
+    sys.wait(1000)
+    wlan.init()
+    while 1 do
+        wlan.scan()
+        sys.wait(15000)
+    end
+end)
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 76 - 73
lua/src/liolib.c

@@ -234,12 +234,13 @@ static int f_close (lua_State *L) {
   return aux_close(L);
   return aux_close(L);
 }
 }
 
 
-
-// static int io_close (lua_State *L) {
-//   if (lua_isnone(L, 1))  /* no argument? */
-//     lua_getfield(L, LUA_REGISTRYINDEX, IO_OUTPUT);  /* use standard output */
-//   return f_close(L);
-// }
+#ifdef LUA_USE_WINDOWS
+static int io_close (lua_State *L) {
+  if (lua_isnone(L, 1))  /* no argument? */
+    lua_getfield(L, LUA_REGISTRYINDEX, IO_OUTPUT);  /* use standard output */
+  return f_close(L);
+}
+#endif
 
 
 
 
 static int f_gc (lua_State *L) {
 static int f_gc (lua_State *L) {
@@ -267,13 +268,12 @@ static LStream *newfile (lua_State *L) {
   return p;
   return p;
 }
 }
 
 
-
-// static void opencheck (lua_State *L, const char *fname, const char *mode) {
-//   LStream *p = newfile(L);
-//   p->f = fopen(fname, mode);
-//   if (p->f == NULL)
-//     luaL_error(L, "cannot open file '%s' (%s)", fname, strerror(errno));
-// }
+static void opencheck (lua_State *L, const char *fname, const char *mode) {
+  LStream *p = newfile(L);
+  p->f = fopen(fname, mode);
+  if (p->f == NULL)
+    luaL_error(L, "cannot open file '%s' (%s)", fname, strerror(errno));
+}
 
 
 
 
 static int io_open (lua_State *L) {
 static int io_open (lua_State *L) {
@@ -322,51 +322,51 @@ static int io_popen (lua_State *L) {
   #endif
   #endif
   return (p->f == NULL) ? luaL_fileresult(L, 0, filename) : 1;
   return (p->f == NULL) ? luaL_fileresult(L, 0, filename) : 1;
 }
 }
-#endif
 
 
-// static int io_tmpfile (lua_State *L) {
-//   LStream *p = newfile(L);
-//   p->f = tmpfile();
-//   return (p->f == NULL) ? luaL_fileresult(L, 0, NULL) : 1;
-// }
+static int io_tmpfile (lua_State *L) {
+  LStream *p = newfile(L);
+  p->f = tmpfile();
+  return (p->f == NULL) ? luaL_fileresult(L, 0, NULL) : 1;
+}
 
 
 
 
-// static FILE *getiofile (lua_State *L, const char *findex) {
-//   LStream *p;
-//   lua_getfield(L, LUA_REGISTRYINDEX, findex);
-//   p = (LStream *)lua_touserdata(L, -1);
-//   if (isclosed(p))
-//     luaL_error(L, "standard %s file is closed", findex + IOPREF_LEN);
-//   return p->f;
-// }
+static FILE *getiofile (lua_State *L, const char *findex) {
+  LStream *p;
+  lua_getfield(L, LUA_REGISTRYINDEX, findex);
+  p = (LStream *)lua_touserdata(L, -1);
+  if (isclosed(p))
+    luaL_error(L, "standard %s file is closed", findex + IOPREF_LEN);
+  return p->f;
+}
 
 
 
 
-// static int g_iofile (lua_State *L, const char *f, const char *mode) {
-//   if (!lua_isnoneornil(L, 1)) {
-//     const char *filename = lua_tostring(L, 1);
-//     if (filename)
-//       opencheck(L, filename, mode);
-//     else {
-//       tofile(L);  /* check that it's a valid file handle */
-//       lua_pushvalue(L, 1);
-//     }
-//     lua_setfield(L, LUA_REGISTRYINDEX, f);
-//   }
-//   /* return current value */
-//   lua_getfield(L, LUA_REGISTRYINDEX, f);
-//   return 1;
-// }
+static int g_iofile (lua_State *L, const char *f, const char *mode) {
+  if (!lua_isnoneornil(L, 1)) {
+    const char *filename = lua_tostring(L, 1);
+    if (filename)
+      opencheck(L, filename, mode);
+    else {
+      tofile(L);  /* check that it's a valid file handle */
+      lua_pushvalue(L, 1);
+    }
+    lua_setfield(L, LUA_REGISTRYINDEX, f);
+  }
+  /* return current value */
+  lua_getfield(L, LUA_REGISTRYINDEX, f);
+  return 1;
+}
 
 
 
 
-// static int io_input (lua_State *L) {
-//   return g_iofile(L, IO_INPUT, "r");
-// }
+static int io_input (lua_State *L) {
+  return g_iofile(L, IO_INPUT, "r");
+}
 
 
 
 
-// static int io_output (lua_State *L) {
-//   return g_iofile(L, IO_OUTPUT, "w");
-// }
+static int io_output (lua_State *L) {
+  return g_iofile(L, IO_OUTPUT, "w");
+}
 
 
+#endif
 
 
 static int io_readline (lua_State *L);
 static int io_readline (lua_State *L);
 
 
@@ -393,12 +393,12 @@ static int f_lines (lua_State *L) {
   return 1;
   return 1;
 }
 }
 
 
-static void opencheck (lua_State *L, const char *fname, const char *mode) {
-  LStream *p = newfile(L);
-  p->f = fopen(fname, mode);
-  if (p->f == NULL)
-    luaL_error(L, "cannot open file '%s' (%s)", fname, strerror(errno));
-}
+// static void opencheck (lua_State *L, const char *fname, const char *mode) {
+//   LStream *p = newfile(L);
+//   p->f = fopen(fname, mode);
+//   if (p->f == NULL)
+//     luaL_error(L, "cannot open file '%s' (%s)", fname, strerror(errno));
+// }
 
 
 static int io_lines (lua_State *L) {
 static int io_lines (lua_State *L) {
   int toclose;
   int toclose;
@@ -623,10 +623,11 @@ static int g_read (lua_State *L, FILE *f, int first) {
   return n - first;
   return n - first;
 }
 }
 
 
-
-// static int io_read (lua_State *L) {
-//   return g_read(L, getiofile(L, IO_INPUT), 1);
-// }
+#ifdef LUA_USE_WINDOWS
+static int io_read (lua_State *L) {
+  return g_read(L, getiofile(L, IO_INPUT), 1);
+}
+#endif
 
 
 
 
 static int f_read (lua_State *L) {
 static int f_read (lua_State *L) {
@@ -688,10 +689,11 @@ static int g_write (lua_State *L, FILE *f, int arg) {
   else return luaL_fileresult(L, status, NULL);
   else return luaL_fileresult(L, status, NULL);
 }
 }
 
 
-
-// static int io_write (lua_State *L) {
-//   return g_write(L, getiofile(L, IO_OUTPUT), 1);
-// }
+#ifdef LUA_USE_WINDOWS
+static int io_write (lua_State *L) {
+  return g_write(L, getiofile(L, IO_OUTPUT), 1);
+}
+#endif
 
 
 
 
 static int f_write (lua_State *L) {
 static int f_write (lua_State *L) {
@@ -731,10 +733,11 @@ static int f_setvbuf (lua_State *L) {
 }
 }
 
 
 
 
-
-// static int io_flush (lua_State *L) {
-//   return luaL_fileresult(L, fflush(getiofile(L, IO_OUTPUT)) == 0, NULL);
-// }
+#ifdef LUA_USE_WINDOWS
+static int io_flush (lua_State *L) {
+  return luaL_fileresult(L, fflush(getiofile(L, IO_OUTPUT)) == 0, NULL);
+}
+#endif
 
 
 
 
 static int f_flush (lua_State *L) {
 static int f_flush (lua_State *L) {
@@ -903,18 +906,18 @@ static int io_lsmount (lua_State *L);
 */
 */
 #include "rotable2.h"
 #include "rotable2.h"
 static const rotable_Reg_t iolib[] = {
 static const rotable_Reg_t iolib[] = {
-  // {"close", io_close,  0},
-  // {"flush", io_flush,  0},
-  // {"input", io_input,  0},
   {"open", ROREG_FUNC(io_open)},
   {"open", ROREG_FUNC(io_open)},
-  // {"output", io_output,0},
 #ifdef LUA_USE_WINDOWS
 #ifdef LUA_USE_WINDOWS
   {"popen", ROREG_FUNC(io_popen)},
   {"popen", ROREG_FUNC(io_popen)},
+  {"read", ROREG_FUNC(io_read)},
+  {"tmpfile", ROREG_FUNC(io_tmpfile)},
+  {"write", ROREG_FUNC(io_write)},
+  {"close", ROREG_FUNC(io_close)},
+  {"flush", ROREG_FUNC(io_flush)},
+  {"input", ROREG_FUNC(io_input)},
+  {"output", ROREG_FUNC(io_output)},
 #endif
 #endif
-  // {"read", io_read,    0},
-  // {"tmpfile", io_tmpfile, 0},
   {"type", ROREG_FUNC(io_type)},
   {"type", ROREG_FUNC(io_type)},
-  // {"write", io_write,  0},
   {"exists", ROREG_FUNC(io_exists)},
   {"exists", ROREG_FUNC(io_exists)},
   {"fileSize", ROREG_FUNC(io_fileSize)},
   {"fileSize", ROREG_FUNC(io_fileSize)},
   {"readFile", ROREG_FUNC(io_readFile)},
   {"readFile", ROREG_FUNC(io_readFile)},

+ 24 - 24
lua/src/luat_bget.c

@@ -438,7 +438,7 @@ void luat_bget_init(luat_bget_t* bg) {
    bufsize, defined in a way that the compiler will accept. */
    bufsize, defined in a way that the compiler will accept. */
 
 
 #define ESent   ((bufsize) (-(((1L << (sizeof(bufsize) * 8 - 2)) - 1) * 2) - 2))
 #define ESent   ((bufsize) (-(((1L << (sizeof(bufsize) * 8 - 2)) - 1) * 2) - 2))
-#define assert(x)
+#define _assert_(x)
 /*  BGET  --  Allocate a buffer.  */
 /*  BGET  --  Allocate a buffer.  */
 
 
 void *luat_bget(luat_bget_t* bg, bufsize requested_size)
 void *luat_bget(luat_bget_t* bg, bufsize requested_size)
@@ -452,7 +452,7 @@ void *luat_bget(luat_bget_t* bg, bufsize requested_size)
 #ifdef BECtl
 #ifdef BECtl
     int compactseq = 0;
     int compactseq = 0;
 #endif
 #endif
-    assert(size >= 0);
+    _assert_(size >= 0);
     if (!size)
     if (!size)
     {
     {
     	return NULL;
     	return NULL;
@@ -515,7 +515,7 @@ void *luat_bget(luat_bget_t* bg, bufsize requested_size)
 
 
                     ba = BH(((char *) b) + (b->bh.bsize - size));
                     ba = BH(((char *) b) + (b->bh.bsize - size));
                     bn = BH(((char *) ba) + size);
                     bn = BH(((char *) ba) + size);
-                    assert(bn->prevfree == b->bh.bsize);
+                    _assert_(bn->prevfree == b->bh.bsize);
                     /* Subtract size from length of free block. */
                     /* Subtract size from length of free block. */
                     b->bh.bsize -= size;
                     b->bh.bsize -= size;
                     /* Link allocated buffer to the previous free buffer. */
                     /* Link allocated buffer to the previous free buffer. */
@@ -539,13 +539,13 @@ void *luat_bget(luat_bget_t* bg, bufsize requested_size)
                     struct bhead *ba;
                     struct bhead *ba;
 
 
                     ba = BH(((char *) b) + b->bh.bsize);
                     ba = BH(((char *) b) + b->bh.bsize);
-                    assert(ba->prevfree == b->bh.bsize);
+                    _assert_(ba->prevfree == b->bh.bsize);
 
 
                     /* The buffer isn't big enough to split.  Give  the  whole
                     /* The buffer isn't big enough to split.  Give  the  whole
                        shebang to the caller and remove it from the free list. */
                        shebang to the caller and remove it from the free list. */
 
 
-                    assert(b->ql.blink->ql.flink == b);
-                    assert(b->ql.flink->ql.blink == b);
+                    _assert_(b->ql.blink->ql.flink == b);
+                    _assert_(b->ql.flink->ql.blink == b);
                     b->ql.blink->ql.flink = b->ql.flink;
                     b->ql.blink->ql.flink = b->ql.flink;
                     b->ql.flink->ql.blink = b->ql.blink;
                     b->ql.flink->ql.blink = b->ql.blink;
 
 
@@ -597,7 +597,7 @@ void *luat_bgetz(luat_bget_t* bg, bufsize size)
         } else {
         } else {
             rsize -= sizeof(struct bhead);
             rsize -= sizeof(struct bhead);
         }
         }
-        assert(rsize >= size);
+        _assert_(rsize >= size);
         memset(buf, 0, (MemSize) rsize);
         memset(buf, 0, (MemSize) rsize);
     }
     }
     return ((void *) buf);
     return ((void *) buf);
@@ -624,7 +624,7 @@ void *luat_bgetr(luat_bget_t* bg, void *buf, bufsize size)
     osize = -b->bsize;
     osize = -b->bsize;
 
 
     osize -= sizeof(struct bhead);
     osize -= sizeof(struct bhead);
-    assert(osize > 0);
+    _assert_(osize > 0);
     V memcpy((char *) nbuf, (char *) buf, /* Copy the data */
     V memcpy((char *) nbuf, (char *) buf, /* Copy the data */
              (MemSize) ((size < osize) ? size : osize));
              (MemSize) ((size < osize) ? size : osize));
     luat_brel(bg, buf);
     luat_brel(bg, buf);
@@ -641,7 +641,7 @@ void luat_brel(luat_bget_t* bg, void *buf)
 #ifdef BufStats
 #ifdef BufStats
     bg->numrel++;                         /* Increment number of brel() calls */
     bg->numrel++;                         /* Increment number of brel() calls */
 #endif
 #endif
-    assert(buf != NULL);
+    _assert_(buf != NULL);
     if (!buf)
     if (!buf)
     {
     {
     	return;
     	return;
@@ -653,16 +653,16 @@ void luat_brel(luat_bget_t* bg, void *buf)
     if (b->bh.bsize >= 0) {
     if (b->bh.bsize >= 0) {
         bn = NULL;
         bn = NULL;
     }
     }
-    assert(b->bh.bsize < 0);
+    _assert_(b->bh.bsize < 0);
 
 
     /*  Back pointer in next buffer must be zero, indicating the
     /*  Back pointer in next buffer must be zero, indicating the
         same thing: */
         same thing: */
 
 
-    assert(BH((char *) b - b->bh.bsize)->prevfree == 0);
+    _assert_(BH((char *) b - b->bh.bsize)->prevfree == 0);
 
 
 #ifdef BufStats
 #ifdef BufStats
     bg->totalloc += b->bh.bsize;
     bg->totalloc += b->bh.bsize;
-    assert(bg->totalloc >= 0);
+    _assert_(bg->totalloc >= 0);
 #endif
 #endif
 
 
     /* If the back link is nonzero, the previous buffer is free.  */
     /* If the back link is nonzero, the previous buffer is free.  */
@@ -678,7 +678,7 @@ void luat_brel(luat_bget_t* bg, void *buf)
         register bufsize size = b->bh.bsize;
         register bufsize size = b->bh.bsize;
 
 
         /* Make the previous buffer the one we're working on. */
         /* Make the previous buffer the one we're working on. */
-        assert(BH((char *) b - b->bh.prevfree)->bsize == b->bh.prevfree);
+        _assert_(BH((char *) b - b->bh.prevfree)->bsize == b->bh.prevfree);
         b = BFH(((char *) b) - b->bh.prevfree);
         b = BFH(((char *) b) - b->bh.prevfree);
         b->bh.bsize -= size;
         b->bh.bsize -= size;
     } else {
     } else {
@@ -686,8 +686,8 @@ void luat_brel(luat_bget_t* bg, void *buf)
         /* The previous buffer isn't allocated.  Insert this buffer
         /* The previous buffer isn't allocated.  Insert this buffer
            on the free list as an isolated free block. */
            on the free list as an isolated free block. */
 
 
-        assert(bg->freelist.ql.blink->ql.flink == &bg->freelist);
-        assert(bg->freelist.ql.flink->ql.blink == &bg->freelist);
+        _assert_(bg->freelist.ql.blink->ql.flink == &bg->freelist);
+        _assert_(bg->freelist.ql.flink->ql.blink == &bg->freelist);
         b->ql.flink = &bg->freelist;
         b->ql.flink = &bg->freelist;
         b->ql.blink = bg->freelist.ql.blink;
         b->ql.blink = bg->freelist.ql.blink;
         bg->freelist.ql.blink = b;
         bg->freelist.ql.blink = b;
@@ -706,9 +706,9 @@ void luat_brel(luat_bget_t* bg, void *buf)
         /* The buffer is free.  Remove it from the free list and add
         /* The buffer is free.  Remove it from the free list and add
            its size to that of our buffer. */
            its size to that of our buffer. */
 
 
-        assert(BH((char *) bn + bn->bh.bsize)->prevfree == bn->bh.bsize);
-        assert(bn->ql.blink->ql.flink == bn);
-        assert(bn->ql.flink->ql.blink == bn);
+        _assert_(BH((char *) bn + bn->bh.bsize)->prevfree == bn->bh.bsize);
+        _assert_(bn->ql.blink->ql.flink == bn);
+        _assert_(bn->ql.flink->ql.blink == bn);
         bn->ql.blink->ql.flink = bn->ql.flink;
         bn->ql.blink->ql.flink = bn->ql.flink;
         bn->ql.flink->ql.blink = bn->ql.blink;
         bn->ql.flink->ql.blink = bn->ql.blink;
         b->bh.bsize += bn->bh.bsize;
         b->bh.bsize += bn->bh.bsize;
@@ -726,7 +726,7 @@ void luat_brel(luat_bget_t* bg, void *buf)
     V memset(((char *) b) + sizeof(struct bfhead), 0x55,
     V memset(((char *) b) + sizeof(struct bfhead), 0x55,
             (MemSize) (b->bh.bsize - sizeof(struct bfhead)));
             (MemSize) (b->bh.bsize - sizeof(struct bfhead)));
 #endif
 #endif
-    assert(bn->bh.bsize < 0);
+    _assert_(bn->bh.bsize < 0);
 
 
     /* The next buffer is allocated.  Set the backpointer in it  to  point
     /* The next buffer is allocated.  Set the backpointer in it  to  point
        to this buffer; the previous free buffer in memory. */
        to this buffer; the previous free buffer in memory. */
@@ -749,7 +749,7 @@ void luat_bpool(luat_bget_t* bg, void *buf, bufsize len)
        it  had  better  not  be  (much) larger than the largest buffer
        it  had  better  not  be  (much) larger than the largest buffer
        whose size we can store in bhead.bsize. */
        whose size we can store in bhead.bsize. */
 
 
-    assert(len - sizeof(struct bhead) <= -((bufsize) ESent + 1));
+    _assert_(len - sizeof(struct bhead) <= -((bufsize) ESent + 1));
 
 
     /* Clear  the  backpointer at  the start of the block to indicate that
     /* Clear  the  backpointer at  the start of the block to indicate that
        there  is  no  free  block  prior  to  this   one.    That   blocks
        there  is  no  free  block  prior  to  this   one.    That   blocks
@@ -759,8 +759,8 @@ void luat_bpool(luat_bget_t* bg, void *buf, bufsize len)
 
 
     /* Chain the new block to the free list. */
     /* Chain the new block to the free list. */
 
 
-    assert(bg->freelist.ql.blink->ql.flink == &bg->freelist);
-    assert(bg->freelist.ql.flink->ql.blink == &bg->freelist);
+    _assert_(bg->freelist.ql.blink->ql.flink == &bg->freelist);
+    _assert_(bg->freelist.ql.flink->ql.blink == &bg->freelist);
     b->ql.flink = &bg->freelist;
     b->ql.flink = &bg->freelist;
     b->ql.blink = bg->freelist.ql.blink;
     b->ql.blink = bg->freelist.ql.blink;
     bg->freelist.ql.blink = b;
     bg->freelist.ql.blink = b;
@@ -783,7 +783,7 @@ void luat_bpool(luat_bget_t* bg, void *buf, bufsize len)
     bn = BH(((char *) b) + len);
     bn = BH(((char *) b) + len);
     bn->prevfree = (bufsize) len;
     bn->prevfree = (bufsize) len;
     /* Definition of ESent assumes two's complement! */
     /* Definition of ESent assumes two's complement! */
-    assert((~0) == -1);
+    _assert_((~0) == -1);
     bn->bsize = ESent;
     bn->bsize = ESent;
 }
 }
 
 
@@ -801,7 +801,7 @@ void luat_bstats(luat_bget_t* bg, bufsize *curalloc, bufsize *totfree, bufsize *
     *totfree = 0;
     *totfree = 0;
     *maxfree = -1;
     *maxfree = -1;
     while (b != &bg->freelist) {
     while (b != &bg->freelist) {
-        assert(b->bh.bsize > 0);
+        _assert_(b->bh.bsize > 0);
         *totfree += b->bh.bsize;
         *totfree += b->bh.bsize;
         if (b->bh.bsize > *maxfree) {
         if (b->bh.bsize > *maxfree) {
             *maxfree = b->bh.bsize;
             *maxfree = b->bh.bsize;

+ 2 - 0
luat/include/luat_libs.h

@@ -131,4 +131,6 @@ LUAMOD_API int luaopen_mobile( lua_State *L );
 
 
 LUAMOD_API int luaopen_protobuf( lua_State *L );
 LUAMOD_API int luaopen_protobuf( lua_State *L );
 
 
+LUAMOD_API int luaopen_httpsrv( lua_State *L );
+
 #endif
 #endif

+ 16 - 12
luat/modules/luat_lib_gpio.c

@@ -17,10 +17,14 @@
 #define LUAT_LOG_TAG "gpio"
 #define LUAT_LOG_TAG "gpio"
 #include "luat_log.h"
 #include "luat_log.h"
 
 
+// 若bsp没有定义最大PIN编号, 那么默认给个128吧
+#ifndef LUAT_GPIO_PIN_MAX
+#define LUAT_GPIO_PIN_MAX (128)
+#endif
+
 static int l_gpio_set(lua_State *L);
 static int l_gpio_set(lua_State *L);
 static int l_gpio_get(lua_State *L);
 static int l_gpio_get(lua_State *L);
 static int l_gpio_close(lua_State *L);
 static int l_gpio_close(lua_State *L);
-#define PIN_MAX (128)
 
 
 typedef struct gpio_ctx
 typedef struct gpio_ctx
 {
 {
@@ -30,21 +34,21 @@ typedef struct gpio_ctx
 }gpio_ctx_t;
 }gpio_ctx_t;
 
 
 // 保存中断回调的数组
 // 保存中断回调的数组
-static gpio_ctx_t gpios[PIN_MAX];
+static gpio_ctx_t gpios[LUAT_GPIO_PIN_MAX];
 static uint8_t default_gpio_pull = Luat_GPIO_DEFAULT;
 static uint8_t default_gpio_pull = Luat_GPIO_DEFAULT;
 
 
 
 
 // 记录GPIO电平,仅OUTPUT时可用
 // 记录GPIO电平,仅OUTPUT时可用
-static uint8_t gpio_out_levels[PIN_MAX / 8] = {0};
+static uint8_t gpio_out_levels[LUAT_GPIO_PIN_MAX / 8] = {0};
 
 
 static uint8_t gpio_bit_get(int pin) {
 static uint8_t gpio_bit_get(int pin) {
-    if (pin < 0 || pin >= PIN_MAX)
+    if (pin < 0 || pin >= LUAT_GPIO_PIN_MAX)
         return 0;
         return 0;
     return (gpio_out_levels[pin/8] >> (pin%8)) & 0x01;
     return (gpio_out_levels[pin/8] >> (pin%8)) & 0x01;
 }
 }
 
 
 static void gpio_bit_set(int pin, uint8_t value) {
 static void gpio_bit_set(int pin, uint8_t value) {
-    if (pin < 0 || pin >= PIN_MAX)
+    if (pin < 0 || pin >= LUAT_GPIO_PIN_MAX)
         return;
         return;
     uint8_t val = (gpio_out_levels[pin/8] >> (pin%8)) & 0x01;
     uint8_t val = (gpio_out_levels[pin/8] >> (pin%8)) & 0x01;
     if (val == value)
     if (val == value)
@@ -64,7 +68,7 @@ int luat_gpio_irq_default(int pin, void* args) {
         return 0;
         return 0;
     }
     }
 
 
-    if (pin < PIN_MAX && gpios[pin].conf_tick > 0) {
+    if (pin < LUAT_GPIO_PIN_MAX && gpios[pin].conf_tick > 0) {
         uint32_t ticks = (uint32_t)luat_mcu_ticks();
         uint32_t ticks = (uint32_t)luat_mcu_ticks();
         uint32_t diff = (ticks > gpios[pin].latest_tick) ? (ticks - gpios[pin].latest_tick) : (gpios[pin].latest_tick - ticks);
         uint32_t diff = (ticks > gpios[pin].latest_tick) ? (ticks - gpios[pin].latest_tick) : (gpios[pin].latest_tick - ticks);
         if (diff >= gpios[pin].conf_tick) {
         if (diff >= gpios[pin].conf_tick) {
@@ -87,7 +91,7 @@ int l_gpio_handler(lua_State *L, void* ptr) {
     // 给 sys.publish方法发送数据
     // 给 sys.publish方法发送数据
     rtos_msg_t* msg = (rtos_msg_t*)lua_topointer(L, -1);
     rtos_msg_t* msg = (rtos_msg_t*)lua_topointer(L, -1);
     int pin = msg->arg1;
     int pin = msg->arg1;
-    if (pin < 0 || pin >= PIN_MAX)
+    if (pin < 0 || pin >= LUAT_GPIO_PIN_MAX)
         return 0;
         return 0;
     if (gpios[pin].lua_ref == 0)
     if (gpios[pin].lua_ref == 0)
         return 0;
         return 0;
@@ -216,7 +220,7 @@ gpio.close(17)
 */
 */
 static int l_gpio_close(lua_State *L) {
 static int l_gpio_close(lua_State *L) {
     int pin = luaL_checkinteger(L, 1);
     int pin = luaL_checkinteger(L, 1);
-    if (pin < 0 || pin >= PIN_MAX)
+    if (pin < 0 || pin >= LUAT_GPIO_PIN_MAX)
         return 0;
         return 0;
     luat_gpio_close(pin);
     luat_gpio_close(pin);
     if (gpios[pin].lua_ref) {
     if (gpios[pin].lua_ref) {
@@ -266,7 +270,7 @@ static int l_gpio_toggle(lua_State *L) {
         pin = lua_tointeger(L, lua_upvalueindex(1));
         pin = lua_tointeger(L, lua_upvalueindex(1));
     else
     else
         pin = luaL_checkinteger(L, 1);
         pin = luaL_checkinteger(L, 1);
-    if (pin < 0 || pin >= PIN_MAX) {
+    if (pin < 0 || pin >= LUAT_GPIO_PIN_MAX) {
         LLOGW("pin id out of range (0-127)");
         LLOGW("pin id out of range (0-127)");
         return 0;
         return 0;
     }
     }
@@ -314,7 +318,7 @@ static int l_gpio_pulse(lua_State *L) {
         len = luaL_checkinteger(L, 3);
         len = luaL_checkinteger(L, 3);
         delay = luaL_checkinteger(L, 4);
         delay = luaL_checkinteger(L, 4);
     }
     }
-    if (pin < 0 || pin >= PIN_MAX) {
+    if (pin < 0 || pin >= LUAT_GPIO_PIN_MAX) {
         LLOGD("pin id out of range (0-127)");
         LLOGD("pin id out of range (0-127)");
         return 0;
         return 0;
     }
     }
@@ -338,7 +342,7 @@ gpio.debounce(7, 0)
 static int l_gpio_debounce(lua_State *L) {
 static int l_gpio_debounce(lua_State *L) {
     uint8_t pin = luaL_checkinteger(L, 1);
     uint8_t pin = luaL_checkinteger(L, 1);
     uint16_t time = luaL_checkinteger(L, 2);
     uint16_t time = luaL_checkinteger(L, 2);
-    if (pin >= PIN_MAX) {
+    if (pin >= LUAT_GPIO_PIN_MAX) {
         LLOGW("MUST pin < 128");
         LLOGW("MUST pin < 128");
         return 0;
         return 0;
     }
     }
@@ -390,7 +394,7 @@ static const rotable_Reg_t reg_gpio[] =
 };
 };
 
 
 LUAMOD_API int luaopen_gpio( lua_State *L ) {
 LUAMOD_API int luaopen_gpio( lua_State *L ) {
-    memset(gpios, 0, sizeof(gpio_ctx_t) * PIN_MAX);
+    memset(gpios, 0, sizeof(gpio_ctx_t) * LUAT_GPIO_PIN_MAX);
     luat_newlib2(L, reg_gpio);
     luat_newlib2(L, reg_gpio);
     return 1;
     return 1;
 }
 }

+ 4 - 3
luat/modules/luat_ota.c

@@ -253,19 +253,20 @@ int luat_ota_checkfile(const char* path) {
 #ifdef LUAT_USE_OTA
 #ifdef LUAT_USE_OTA
 
 
 int luat_ota(uint32_t luadb_addr){
 int luat_ota(uint32_t luadb_addr){
-    
+    FILE *fd_out = NULL;
+    FILE *fd_in = NULL;
 #ifdef LUAT_USE_ZLIB 
 #ifdef LUAT_USE_ZLIB 
     extern int zlib_decompress(FILE *source, FILE *dest);
     extern int zlib_decompress(FILE *source, FILE *dest);
     //检测是否有压缩升级文件
     //检测是否有压缩升级文件
     if(luat_fs_fexist(UPDATE_TGZ_PATH)){
     if(luat_fs_fexist(UPDATE_TGZ_PATH)){
         LLOGI("found update.tgz, decompress ...");
         LLOGI("found update.tgz, decompress ...");
-        FILE *fd_in = luat_fs_fopen(UPDATE_TGZ_PATH, "r");
+        fd_in = luat_fs_fopen(UPDATE_TGZ_PATH, "r");
         if (fd_in == NULL){
         if (fd_in == NULL){
             LLOGE("open the input file : %s error!", UPDATE_TGZ_PATH);
             LLOGE("open the input file : %s error!", UPDATE_TGZ_PATH);
             goto _close_decompress;
             goto _close_decompress;
         }
         }
         luat_fs_remove(UPDATE_BIN_PATH);
         luat_fs_remove(UPDATE_BIN_PATH);
-        FILE *fd_out = luat_fs_fopen(UPDATE_BIN_PATH, "w+");
+        fd_out = luat_fs_fopen(UPDATE_BIN_PATH, "w+");
         if (fd_out == NULL){
         if (fd_out == NULL){
             LLOGE("open the output file : %s error!", UPDATE_BIN_PATH);
             LLOGE("open the output file : %s error!", UPDATE_BIN_PATH);
             goto _close_decompress;
             goto _close_decompress;

+ 8 - 24
script/turnkey/eink-calendar/main.lua

@@ -5,6 +5,7 @@ VERSION = "1.0.0"
 --测试固件版本:LuatOS-SoC_V0003_ESP32C3[_USB].soc
 --测试固件版本:LuatOS-SoC_V0003_ESP32C3[_USB].soc
 
 
 local sys = require "sys"
 local sys = require "sys"
+require("sysplus")
 
 
 --需要自行填写的东西
 --需要自行填写的东西
 --wifi信息
 --wifi信息
@@ -29,30 +30,13 @@ local function connectWifi()
 end
 end
 
 
 local function requestHttp()
 local function requestHttp()
-    local rd = {}
-    local httpc = esphttp.init(esphttp.GET, "http://apicn.luatos.org:23328/luatos-calendar/v1?mac=111&battery=10&location="..location.."&appid="..appid.."&appsecret="..appsecret)
-    if httpc then
-        local ok, err = esphttp.perform(httpc, true)
-        if ok then
-            while 1 do
-                local result, c, ret, data = sys.waitUntil("ESPHTTP_EVT", 20000)
-                --log.info("httpc", result, c, ret)
-                if c == httpc then
-                    if esphttp.is_done(httpc, ret) then
-                        break
-                    end
-                    if ret == esphttp.EVENT_ON_DATA and esphttp.status_code(httpc) == 200 then
-                        table.insert(rd,data)
-                    end
-                end
-            end
-        else
-            log.warn("esphttp", "bad perform", err)
-        end
-        esphttp.cleanup(httpc)
-        if ok then
-            return table.concat(rd)
-        end
+    local code, headers, body = http2.request("GET","http://apicn.luatos.org:23328/luatos-calendar/v1?mac=111&battery=10&location="..location.."&appid="..appid.."&appsecret="..appsecret).wait()
+    if code == 200 then
+        return body
+    else
+        log.info("http get failed",code, headers, body)
+        sys.wait(500)
+        return ""
     end
     end
 end
 end