1. 程式人生 > >關於 k210 的 micropython 新增 ussl 模組,實現 https 訪問支援的那些事。

關於 k210 的 micropython 新增 ussl 模組,實現 https 訪問支援的那些事。

## 起因 事情已經過去快一週了吧,繼上次修復 maixpy k210 的 esp8285 at 通訊後,突然遇到澤畔大大問,要不要做 ussl 的支援? ![](https://img2020.cnblogs.com/blog/1641852/202005/1641852-20200511161240772-919687151.png) 評估了一下各方的實現,想了一下自己也剛好在做網路層的優化和處理,況且 micropython 在 stm32 、 esp32 上的也有對應的實現,那就新增實現進去吧,選取了 mbedtls 版本的 ussl 模組,實現相關檔案如下。 ![](https://img2020.cnblogs.com/blog/1641852/202005/1641852-20200511161628241-723980256.png) 這裡說一下 ussl 的工作機制。 首先建立在 micropython 的 network 架構下的 socket 模組,提供了關鍵的 steam->write 和 steam->read 基礎介面,實際上就是繼承一個抽象 steam 物件的介面。 因此 ussl 提供了 wrap_socket 用來提升 socket 的功能,從而支援 https 的訪問。 我們看一下 micropython 的例項就知道了。 ```python try: import usocket as _socket except: import _socket try: import ussl as ssl except: import ssl def main(use_stream=True): s = _socket.socket() ai = _socket.getaddrinfo("google.com", 443) print("Address infos:", ai) addr = ai[0][-1] print("Connect address:", addr) s.connect(addr) s = ssl.wrap_socket(s) print(s) if use_stream: # Both CPython and MicroPython SSLSocket objects support read() and # write() methods. s.write(b"GET / HTTP/1.0\r\n\r\n") print(s.read(4096)) else: # MicroPython SSLSocket objects implement only stream interface, not # socket interface s.send(b"GET / HTTP/1.0\r\n\r\n") print(s.recv(4096)) s.close() main() ``` 實現的最終結果如下,不過目前的實測效果距離商業使用,保守來講,還有很大的優化空間,主要在核心函式和配置方面要改善效能。 - esp32 的效果 ![](https://img2020.cnblogs.com/blog/1641852/202005/1641852-20200511162645196-1236849552.png) - k210 的效果 ![](https://img2020.cnblogs.com/blog/1641852/202005/1641852-20200511162658266-1634262996.png) ![](https://img2020.cnblogs.com/blog/1641852/202005/1641852-20200511162728976-904228570.png) ## 實現細節 MaixPy k210 採用 components/micropython/CMakeLists.txt 來管理 micropython 的編譯命令。 所以在不脫離主流的基礎上,在 micropython-ulab 的配置後面繼續新增如下配置。 ```cmake if(1 OR CONFIG_MICROPY_SSL_MBEDTLS) list(APPEND ADD_INCLUDE "${mpy_core_dir}/lib/mbedtls/include") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DMBEDTLS_CONFIG_FILE='\"${mpy_port_dir}/src/mbedtls/include/mbedtls_config.h\"'") # message(${CMAKE_C_FLAGS}) append_srcs_dir(ADD_SRCS "port/src/mbedtls") append_srcs_dir(ADD_SRCS "core/lib/mbedtls/library") list(REMOVE_ITEM ADD_SRCS "${mpy_core_dir}/lib/mbedtls/library/net_sockets.c") endif() ``` 稍微解釋一下 - 將 mbedtls/include 和 mbedtls/library 新增到環境中,並排除 net_sockets.c 的實現,問題下述。 ![](https://img2020.cnblogs.com/blog/1641852/202005/1641852-20200511171655283-358539972.png) - 給 CMAKE_C_FLAGS 新增 -DMBEDTLS_CONFIG_FILE 自定義的 mbedtls 配置檔案,從而遮蔽內建的 config.h 。(奇怪的是 add_definitions 不 work ,就直接用 set 了) ```c #if !defined(MBEDTLS_CONFIG_FILE) #include "mbedtls/config.h" #else #include MBEDTLS_CONFIG_FILE #endif ``` 所以現在把程式碼編譯了進去,就完成了大部分的移植,是不是很簡單? [修改記錄在這裡,可供參考。](https://github.com/junhuanchen/MaixPy/commit/ec7506219f7ebd14bac711c8d48d6e4c5bc87191) 當然,事情不會這麼順利的,在沒有進行專門配置的時候,啟動模組是可以的,現在開始實踐發起一次 get https 網站的請求,測試 python code 如下: ```python wCli = MicroWebCli('https://tcc.taobao.com/cc/json/mobile_tel_segment.htm?tel=13631786501') # wCli = MicroWebCli('https://www.baifubao.com/callback?cmd=1059&callback=phone&phone=13631786501') # wCli = MicroWebCli('https://github.com') # wCli = MicroWebCli('https://ssl.logink.cn/') # wCli = MicroWebCli('https://cn.bing.com/?FORM=Z9FD1') # wCli = MicroWebCli('https://www.sojson.com') # wCli = MicroWebCli('https://www.baidu.com') while True: try: print('GET %s' % wCli.URL) wCli.OpenRequest() buf = memoryview(bytearray(1024)) resp = wCli.GetResponse() if resp.IsSuccess() : while not resp.IsClosed() : x = resp.ReadContentInto(buf) if x < len(buf) : buf = buf[:x] print(bytes(buf)) print('GET success with "%s" content type' % resp.GetContentType()) else : print('GET return %d code (%s)' % (resp.GetStatusCode(), resp.GetStatusMessage())) except Exception as E: print(E) time.sleep(2) ``` ## 問題一: -0x0034 錯誤程式碼 Gather entropy_len bytes of entropy to seed state mbedtls_ctr_drbg_seed returned -52 或者-0x0034 錯誤解釋: MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED        -0x0034  /**< The entropy source failed. */ 原因: 給mbedtls提供的熵源不夠混亂,應該用硬體隨機數發生器。 解決: mbedtls\config.h `#define MBEDTLS_ENTROPY_HARDWARE_ALT` 解決方案可以參考 https://blog.csdn.net/liaofeifly/article/details/88899655 mbedtls_hardware_poll 實現可以參考 esp32 、stm32 的,如下是我後來實踐到 k210 的,這個函式只會在發起連結的時候呼叫。 ```c #include