Selaa lähdekoodia

Merge branch 'master' of https://gitee.com/lyon1998/pikascript

李昂 3 vuotta sitten
vanhempi
sitoutus
ee8f877cf4
100 muutettua tiedostoa jossa 4828 lisäystä ja 1281 poistoa
  1. 29 0
      .gitignore
  2. 2 2
      bsp/Dev-c/PikaScript/requestment.txt
  3. 1 1
      bsp/bl602/pikascript/requestment.txt
  4. 2 2
      bsp/ch582/pikascript/requestment.txt
  5. 2 2
      bsp/esp32c3/components/pikascript/requestment.txt
  6. 3 3
      bsp/lvgl-vs-simu/LVGL.Simulator/pikascript/requestment.txt
  7. 2 2
      bsp/pico/pikascript/requestment.txt
  8. 2 2
      bsp/simulation-keil/pikascript/requestment.txt
  9. 2 2
      bsp/simulation-rtt-qemu-arm2d/pikascript/requestment.txt
  10. 2 2
      bsp/stm32f401cc/pikascript/requestment.txt
  11. 2 2
      bsp/stm32f407ze/PikaScript/requestment.txt
  12. 2 2
      bsp/stm32f407zg/pikascript/requestment.txt
  13. 2 2
      bsp/stm32f411ce/pikascript/requestment.txt
  14. 2 2
      bsp/stm32h750vb/pikascript/requestment.txt
  15. 2 2
      bsp/template/pikascript/requestment.txt
  16. 2 2
      bsp/visual-studio/pikascript/requestment.txt
  17. 2 2
      bsp/w806/Project/pikascript/requestment.txt
  18. 15 0
      examples/Device/GPIO_CALLBCK.py
  19. 33 0
      examples/Device/KEY_POLL.PY
  20. 15 0
      examples/Device/UART_CALLBACK.py
  21. 11 0
      examples/base64/test_base64.py
  22. 16 0
      examples/hmac/test_hmac.py
  23. 5 6
      examples/mqtt/mqtt_connect.py
  24. 1 2
      examples/mqtt/mqtt_init.py
  25. 21 0
      examples/mqtt/mqtt_publish.py
  26. 45 0
      examples/mqtt/mqtt_set_para.py
  27. 66 0
      examples/mqtt/mqtt_subscribe.py
  28. 9 0
      examples/requests/get_basic.py
  29. 8 0
      examples/requests/gitee_issue.py
  30. 10 0
      examples/requests/post_data.py
  31. 6 8
      examples/requests/requests_encode.py
  32. 0 20
      package/BL808/BL808.pyi
  33. 0 74
      package/BL808/BL808_GPIO.c
  34. 0 11
      package/BL808/BL808_Time.c
  35. 292 0
      package/BLIOT/LCD_driver.c
  36. 103 0
      package/BLIOT/LCD_driver.h
  37. 345 0
      package/BLIOT/Touch_driver.c
  38. 122 0
      package/BLIOT/Touch_driver.h
  39. 40 0
      package/BLIOT/pika_hal_BLIOT_GPIO.c
  40. 12 12
      package/BLIOT/pika_hal_BLIOT_IIC.c
  41. 34 9
      package/BLIOT/pika_hal_BLIOT_SPI.c
  42. 163 0
      package/BLIOT/pika_hal_BLIOT_UART.c
  43. 52 0
      package/BLIOT/pika_hal_BLIOT_irq_task.c
  44. 12 0
      package/BLIOT/pika_hal_BLIOT_irq_task.h
  45. 52 10
      package/PikaStdDevice/PikaStdDevice.pyi
  46. 6 2
      package/PikaStdDevice/PikaStdDevice_ADC.c
  47. 3 6
      package/PikaStdDevice/PikaStdDevice_BaseDev.c
  48. 1 1
      package/PikaStdDevice/PikaStdDevice_CAN.c
  49. 6 2
      package/PikaStdDevice/PikaStdDevice_DAC.c
  50. 27 2
      package/PikaStdDevice/PikaStdDevice_GPIO.c
  51. 1 3
      package/PikaStdDevice/PikaStdDevice_IIC.c
  52. 6 2
      package/PikaStdDevice/PikaStdDevice_PWM.c
  53. 1 3
      package/PikaStdDevice/PikaStdDevice_SPI.c
  54. 4 6
      package/PikaStdDevice/PikaStdDevice_Time.c
  55. 97 8
      package/PikaStdDevice/PikaStdDevice_UART.c
  56. 19 0
      package/PikaStdDevice/PikaStdDevice_common.c
  57. 12 0
      package/PikaStdDevice/PikaStdDevice_common.h
  58. 31 6
      package/PikaStdDevice/pika_hal.c
  59. 49 3
      package/PikaStdDevice/pika_hal.h
  60. 155 0
      package/PikaStdDevice/pika_hal_SOFT_SPI.c
  61. 1 0
      package/PikaStdDevice/pika_hal_table.h
  62. 8 8
      package/PikaStdLib/PikaStdData_Dict.c
  63. 4 0
      package/PikaStdLib/PikaStdLib_SysObj.c
  64. 1 0
      package/TemplateDevice/TemplateDevice.pyi
  65. 12 0
      package/TemplateDevice/TemplateDevice_GPIO.c
  66. 40 0
      package/base64/_base64.c
  67. 2 0
      package/base64/_base64.pyi
  68. 9 0
      package/base64/base64.py
  69. 59 233
      package/hmac/_hmac_HMAC.c
  70. 1 1
      package/hmac/hmac.py
  71. 24 12
      package/mqtt/_mqtt.pyi
  72. 469 80
      package/mqtt/_mqtt__MQTT.c
  73. 12 0
      package/mqtt/mqtt.py
  74. 1 1
      package/mqtt/mqtt_config.h
  75. 120 103
      package/mqtt/mqttclient.c
  76. 7 9
      package/mqtt/mqttclient.h
  77. 6 7
      package/mqtt/nettype_tls.c
  78. 0 1
      package/mqtt/network.c
  79. 0 61
      package/mqtt/platform_mutex.c
  80. 0 47
      package/mqtt/platform_mutex.h
  81. 0 98
      package/mqtt/platform_thread.c
  82. 0 54
      package/mqtt/platform_thread.h
  83. 0 107
      package/mqtt/platform_timer.c
  84. 0 49
      package/mqtt/platform_timer.h
  85. 3 3
      package/mqtt/random.c
  86. 3 0
      package/pika_libc/README.md
  87. 0 0
      package/pika_libc/pika_libc.pyi
  88. 1268 0
      package/pika_libc/pika_vsnprintf.c
  89. 1 1
      package/pika_lvgl/pika_lv_wegit.c
  90. 2 2
      package/pika_lvgl/pika_lvgl.c
  91. 291 76
      package/requests/_requests.c
  92. 16 6
      package/requests/_requests.pyi
  93. 77 20
      package/requests/requests.py
  94. 302 1
      package/requests/webclient.c
  95. 8 1
      package/requests/webclient.h
  96. 39 32
      package/socket/PikaPlatform_socket.c
  97. 29 27
      package/socket/PikaPlatform_socket.h
  98. 33 10
      packages.toml
  99. 1 1
      port/linux/.vscode/launch.json
  100. 12 2
      port/linux/.vscode/settings.json

+ 29 - 0
.gitignore

@@ -14,3 +14,32 @@ bsp/pico/MDK/mdk/RTE
 bsp/pico-dev/MDK/mdk/RTE
 
 .vscode/
+coredump/
+
+#remove unnecessary file
+test/out/
+test/python/*.py.a
+test/python/*.py.o
+test/python/__asset_lib_to_file_py_a.c
+tools/pikaByteCodeGen/build/
+tools/pikaByteCodeGen/pikascript/
+tools/pikaByteCodeGen/libpikabinder/
+tools/pikaCompiler/libpikabinder/
+tools/pikaCompiler/rust-msc-latest-linux
+
+port/linux/test
+port/linux/Release/
+port/linux/benchmark_result.json
+port/linux/gmon.out
+port/linux/package/pikascript/pikascript-api/
+port/linux/package/pikascript/pikascript-core/
+port/linux/package/pikascript/*.o
+port/linux/package/pikascript/pika
+port/linux/package/pikascript/rust-msc-latest-linux
+
+port/linux/report.txt
+port/linux/snake.bin
+port/linux/task.bin
+port/linux/pika_bytecode.bin
+port/linux/config/pika_config.h
+

+ 2 - 2
bsp/Dev-c/PikaScript/requestment.txt

@@ -1,2 +1,2 @@
-pikascript-core==v1.11.8
-PikaStdLib==v1.11.8
+pikascript-core==v1.11.9
+PikaStdLib==v1.11.9

+ 1 - 1
bsp/bl602/pikascript/requestment.txt

@@ -1,4 +1,4 @@
 pikascript-core==v1.12.0
 PikaStdLib==v1.12.0
 BLIOT==v0.4.1
-PikaStdDevice==v2.2.1
+PikaStdDevice==v2.2.1

+ 2 - 2
bsp/ch582/pikascript/requestment.txt

@@ -1,4 +1,4 @@
-pikascript-core==v1.11.8
-PikaStdLib==v1.11.8
+pikascript-core==v1.11.9
+PikaStdLib==v1.11.9
 PikaStdDevice==v1.11.0
 CH582==v1.1.2

+ 2 - 2
bsp/esp32c3/components/pikascript/requestment.txt

@@ -1,4 +1,4 @@
-pikascript-core==v1.11.8
-PikaStdLib==v1.11.8
+pikascript-core==v1.11.9
+PikaStdLib==v1.11.9
 PikaStdDevice==v1.11.0
 ESP32==v0.1.0

+ 3 - 3
bsp/lvgl-vs-simu/LVGL.Simulator/pikascript/requestment.txt

@@ -1,4 +1,4 @@
-pikascript-core==v1.11.8
-PikaStdLib==v1.11.8
+pikascript-core==v1.11.9
+PikaStdLib==v1.11.9
 PikaStdDevice==v1.11.0
-pika_lvgl==v0.3.2
+pika_lvgl==v0.4.1

+ 2 - 2
bsp/pico/pikascript/requestment.txt

@@ -1,2 +1,2 @@
-pikascript-core==v1.11.8
-PikaStdLib==v1.11.8
+pikascript-core==v1.11.9
+PikaStdLib==v1.11.9

+ 2 - 2
bsp/simulation-keil/pikascript/requestment.txt

@@ -1,2 +1,2 @@
-pikascript-core==v1.11.8
-PikaStdLib==v1.11.8
+pikascript-core==v1.11.9
+PikaStdLib==v1.11.9

+ 2 - 2
bsp/simulation-rtt-qemu-arm2d/pikascript/requestment.txt

@@ -1,3 +1,3 @@
-pikascript-core==v1.11.8
-PikaStdLib==v1.11.8
+pikascript-core==v1.11.9
+PikaStdLib==v1.11.9
 Arm2D==v0.6.1

+ 2 - 2
bsp/stm32f401cc/pikascript/requestment.txt

@@ -1,4 +1,4 @@
-pikascript-core==v1.11.8
-PikaStdLib==v1.11.8
+pikascript-core==v1.11.9
+PikaStdLib==v1.11.9
 PikaStdDevice==v1.11.0
 STM32F4==v0.1.1

+ 2 - 2
bsp/stm32f407ze/PikaScript/requestment.txt

@@ -1,4 +1,4 @@
-pikascript-core==v1.11.8
-PikaStdLib==v1.11.8
+pikascript-core==v1.11.9
+PikaStdLib==v1.11.9
 PikaStdDevice==v2.0.0
 STM32F4==v0.1.2

+ 2 - 2
bsp/stm32f407zg/pikascript/requestment.txt

@@ -1,4 +1,4 @@
-pikascript-core==v1.11.8
-PikaStdLib==v1.11.8
+pikascript-core==v1.11.9
+PikaStdLib==v1.11.9
 PikaStdDevice==v2.0.0
 STM32F4==v0.1.2

+ 2 - 2
bsp/stm32f411ce/pikascript/requestment.txt

@@ -1,4 +1,4 @@
-pikascript-core==v1.11.8
-PikaStdLib==v1.11.8
+pikascript-core==v1.11.9
+PikaStdLib==v1.11.9
 PikaStdDevice==v1.11.0
 STM32F4==v0.1.1

+ 2 - 2
bsp/stm32h750vb/pikascript/requestment.txt

@@ -1,2 +1,2 @@
-pikascript-core==v1.11.8
-PikaStdLib==v1.11.8
+pikascript-core==v1.11.9
+PikaStdLib==v1.11.9

+ 2 - 2
bsp/template/pikascript/requestment.txt

@@ -1,2 +1,2 @@
-pikascript-core==v1.11.8
-PikaStdLib==v1.11.8
+pikascript-core==v1.11.9
+PikaStdLib==v1.11.9

+ 2 - 2
bsp/visual-studio/pikascript/requestment.txt

@@ -1,2 +1,2 @@
-pikascript-core==v1.11.8
-PikaStdLib==v1.11.8
+pikascript-core==v1.11.9
+PikaStdLib==v1.11.9

+ 2 - 2
bsp/w806/Project/pikascript/requestment.txt

@@ -1,4 +1,4 @@
-pikascript-core==v1.11.8
-PikaStdLib==v1.11.8
+pikascript-core==v1.11.9
+PikaStdLib==v1.11.9
 PikaStdDevice==v1.11.0
 W801Device==v1.1.1

+ 15 - 0
examples/Device/GPIO_CALLBCK.py

@@ -0,0 +1,15 @@
+import PikaStdDevice as std
+print('hello pikascript')
+
+io = std.GPIO()
+io.setPin('P4')
+io.setMode('in')
+io.enable()
+
+def cb1(signal):
+    print('cb1', signal)
+
+io.setCallBack(cb1, io.SIGNAL_FALLING)
+
+while True:
+    pass

+ 33 - 0
examples/Device/KEY_POLL.PY

@@ -0,0 +1,33 @@
+from machine import GPIO as STD_GPIO
+
+print('PikaScript LED KEY')
+
+
+LED1 = STD_GPIO()
+LED1.setPin('PE5')
+LED1.setMode('out')
+LED1.enable()
+
+LED2 = STD_GPIO()
+LED2.setPin('PE6')
+LED2.setMode('out')
+LED2.enable()
+
+KEY1 = STD_GPIO()
+KEY1.setPin('PE4')
+# setPull要在setMode前面才行,PikaStdDevice_GPIO.c函数PikaStdDevice_GPIO_setPull不赋值pull
+# PikaStdDevice_GPIO_platformSetMode中才赋值cfg->pull
+KEY1.setPull('up')
+KEY1.setMode('in')
+
+KEY1.enable()
+
+LED1.high()
+LED2.high()
+print(KEY1.read())
+
+while True:
+    if KEY1.read() == 1:
+        LED1.high()
+    else:
+        LED1.low()

+ 15 - 0
examples/Device/UART_CALLBACK.py

@@ -0,0 +1,15 @@
+import PikaStdDevice as std
+print('hello pikascript')
+
+uart = std.UART()
+uart.setId(0)
+uart.setBaudRate(115200)
+uart.enable()
+
+def cb1(signal):
+    print('recv:', uart.read(32))
+
+uart.setCallBack(cb1, uart.SIGNAL_RX)
+
+while True:
+    pass

+ 11 - 0
examples/base64/test_base64.py

@@ -0,0 +1,11 @@
+import base64
+
+if base64.b64encode(b"123456").decode() == "MTIzNDU2":
+    print("base64 encode test ok")
+else:
+    print("base64 encode test error")
+
+if base64.b64decode(b"\x4d\x54\x49\x7a\x4e\x44\x55\x32").decode() == "123456":
+    print("base64 decode test ok")
+else:
+    print("base64 decode test error")

+ 16 - 0
examples/hmac/test_hmac.py

@@ -0,0 +1,16 @@
+import hmac
+
+secret = "0123456789"
+payload = "helloworld"
+
+h = hmac.new(secret.encode(),digestmod="md5")
+h.update(payload.encode())
+print("hmac-md5:",h.hexdigest())
+
+h = hmac.new(secret.encode(),digestmod="sha1")
+h.update(payload.encode())
+print("hmac-sha1:",h.hexdigest())
+
+h = hmac.new(secret.encode(),digestmod="sha256")
+h.update(payload.encode())
+print("hmac-sha256:",h.hexdigest())

+ 5 - 6
examples/mqtt/mqtt_connect.py

@@ -1,10 +1,9 @@
 import mqtt
 
-client = mqtt.MQTT('192.168.1.255')
+client = mqtt.MQTT('broker.emqx.io',port=1883,clinetID='clientid',username='name_',password='passwd_')
 
-client.setHost('test.mosquitto.org')
-client.setPort(1883)
+ret = client.connect()
+print("connect ret:%d" % ret)
 
-client.connect()
-
-client.disconnect()
+ret = client.disconnect()
+print("disconnect ret:%d" % ret)

+ 1 - 2
examples/mqtt/mqtt_init.py

@@ -1,7 +1,6 @@
 import mqtt
 
-client = mqtt.MQTT('192.168.1.255')
-
+client = mqtt.MQTT('broker.emqx.io')
 
 
 

+ 21 - 0
examples/mqtt/mqtt_publish.py

@@ -0,0 +1,21 @@
+import mqtt
+
+client = mqtt.MQTT('192.168.1.255')
+
+client.setHost('broker.emqx.io')
+client.setPort(1883)
+client.setClientID('123456dddecetdc')
+client.setUsername('test1')
+client.setPassword('aabbccdd')
+client.setVersion('3.1')
+client.setKeepAlive(10)
+
+ret = client.connect()
+print("connect ret:%d" % ret)
+
+client.publish('topic_pikapy', 'hello pikascript qos=0', 0)
+client.publish('topic_pikapy', 'hello pikascript qos=1', 1)
+client.publish('topic_pikapy', 'hello pikascript qos=2', 2)
+
+ret = client.disconnect()
+print("disconnect ret:%d" % ret)

+ 45 - 0
examples/mqtt/mqtt_set_para.py

@@ -0,0 +1,45 @@
+import mqtt
+
+test_baidu_ca_crt = ["-----BEGIN CERTIFICATE-----\r\n"
+    "MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4G\r\n"
+    "A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNp\r\n"
+    "Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4\r\n"
+    "MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMzETMBEG\r\n"
+    "A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI\r\n"
+    "hvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWtiHL8\r\n"
+    "RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsT\r\n"
+    "gHeMCOFJ0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmm\r\n"
+    "KPZpO/bLyCiR5Z2KYVc3rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zd\r\n"
+    "QQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjlOCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZ\r\n"
+    "XriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2xmmFghcCAwEAAaNCMEAw\r\n"
+    "DgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFI/wS3+o\r\n"
+    "LkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZU\r\n"
+    "RUm7lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMp\r\n"
+    "jjM5RcOO5LlXbKr8EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK\r\n"
+    "6fBdRoyV3XpYKBovHd7NADdBj+1EbddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQX\r\n"
+    "mcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18YIvDQVETI53O9zJrlAGomecs\r\n"
+    "Mx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7rkpeDMdmztcpH\r\n"
+    "WD9f\r\n"
+    "-----END CERTIFICATE-----"]
+
+client = mqtt.MQTT('192.168.1.255')
+
+#test TLS
+# client.setHost('j6npr4w.mqtt.iot.gz.baidubce.com')
+# client.setPort(1884)
+# client.setCa(test_baidu_ca_crt)
+
+client.setHost('broker.emqx.io')
+client.setPort(1883)
+
+client.setClientID('123456dddecetdc')
+client.setUsername('j6npr4w/mqtt-client-dev')
+client.setPassword('lcUhUs5VYLMSbrnB')
+client.setVersion('3.1.1')
+client.setKeepAlive(10)
+
+ret = client.connect()
+print("connect ret:%d" % ret)
+
+ret = client.disconnect()
+print("disconnect ret:%d" % ret)

+ 66 - 0
examples/mqtt/mqtt_subscribe.py

@@ -0,0 +1,66 @@
+import mqtt
+import PikaStdDevice
+
+client = mqtt.MQTT('broker.emqx.io', port=1883,
+                   clinetID='clientid', username='name_', password='passwd_')
+
+ret = client.connect()
+print("connect ret:%d" % ret)
+
+
+def callback0(evt):
+    print("py0 cb: %s-qos:%d-->>%s" % (evt.topic, evt.qos, evt.msg))
+
+
+def callback1(evt):
+    print("py1 cb: %s-qos:%d-->>%s" % (evt.topic, evt.qos, evt.msg))
+
+
+def callback2(evt):
+    print("py2 cb: %s-qos:%d-->>%s" % (evt.topic, evt.qos, evt.msg))
+
+
+def reconnect_mq(signal):
+    print('lost mqtt connect and try to reconnect')
+    print('signal:', signal)
+
+
+client.setKeepAlive(5)
+ret = client.subscribe('topic_pikapy_qos0', callback0, 0)
+print("subscribe ret:%d" % ret)
+ret = client.subscribe('topic_pikapy_qos1', callback1, 1)
+print("subscribe ret:%d" % ret)
+ret = client.subscribe('topic_pikapy_qos2', callback2, 2)
+print("subscribe ret:%d" % ret)
+
+client._fakeMsg("topic_pikapy_qos0", 0, "hello qos0")
+client._fakeMsg("topic_pikapy_qos1", 1, "hello qos1")
+client._fakeMsg("topic_pikapy_qos2", 2, "hello qos2")
+
+# sleep wait for recv data
+T = PikaStdDevice.Time()
+# T.sleep_s(5)
+
+out = client.listSubscribeTopic()
+print('listSubscribeTopic out', out)
+
+# client.unsubscribe('topic_pikapy_qos0');
+# client.unsubscribe('topic_pikapy_qos1');
+# client.unsubscribe('topic_pikapy_qos2');
+# T.sleep_s(5)
+# out2 = client.listSubscribeTopic()
+# print('listSubscribeTopic out2',out2)
+
+ret = client.setDisconnectHandler(reconnect_mq)
+print("setDisconnectHandler:%d" % ret)
+
+# ret = client.setWill('topic_will','lost mqtt connect')
+# print("setWill:%d" % ret)
+# client.publish('topic_will', 'hello pikascript', 1)
+# T.sleep_s(5)
+# print("sleep_s:5s")
+
+# T.sleep_s(30)
+# exit()
+ret = client.disconnect()
+print("disconnect ret:%d" % ret)

+ 9 - 0
examples/requests/get_basic.py

@@ -0,0 +1,9 @@
+import requests
+
+b = "kkk"
+
+a = requests.request("GET", "http://pikascript.com/package", params = {"name":"get-test"})
+
+print(a.headers)
+print(a.content_length)
+print(a.text)

+ 8 - 0
examples/requests/gitee_issue.py

@@ -0,0 +1,8 @@
+
+import requests
+
+a = requests.request("GET", "http://pikascript.com/pullrequest", params = {"json":'{"stepIndex":4,"packageName":"None","id":1669300904995,"version":"v1234.4321.1","releases":[],"fileList":[],"userEmail":"test@pikascript.com","userName":"pikascript","pullrequestOK":false,"pullrequestUrl":"","uploadFileNum":1}'})
+
+print(a.headers)
+print(a.content_length)
+print(a.text)

+ 10 - 0
examples/requests/post_data.py

@@ -0,0 +1,10 @@
+import requests
+form_data = '------WebKitFormBoundaryrEPACvZYkAbE4bYB\r\nContent-Disposition: form-data; name="file"; filename="test_file.txt"\r\nContent-Type: text/plain\r\n\r\nhello, pikascript!\r\n------WebKitFormBoundaryrEPACvZYkAbE4bYB\r\nContent-Disposition: form-data; name="id"\r\n\r\n1670666272201\r\n------WebKitFormBoundaryrEPACvZYkAbE4bYB\r\nContent-Disposition: form-data; name="uploadFileNum"\r\n\r\n1\r\n------WebKitFormBoundaryrEPACvZYkAbE4bYB--\r\n'
+
+header = {"Content-Type": "multipart/form-data; boundary=----WebKitFormBoundaryrEPACvZYkAbE4bYB"}
+
+a = requests.request("POST", "http://pikascript.com/upload", headers=header, data=form_data)
+
+print(a.headers)
+print(a.content_length)
+print(a.text)

+ 6 - 8
examples/requests/requests_encode.py

@@ -1,10 +1,8 @@
 import requests
-requests._append_params_to_url('http://www.rt-thread.com', {
-    'a': 1,
-    'b': 2
-})
 
-requests._append_params_to_url('http://www.rt-thread.com', {
-    'a': ' ',
-    'b': '%',
-})
+a = requests.request("GET", "http://pikascript.com/")
+
+print(a.headers)
+print(a.content_length)
+print(a.text)
+

+ 0 - 20
package/BL808/BL808.pyi

@@ -1,20 +0,0 @@
-import PikaStdDevice
-
-
-class GPIO(PikaStdDevice.GPIO):
-    def platformHigh(self): ...
-
-    def platformLow(self): ...
-
-    def platformEnable(self): ...
-
-    def platformDisable(self): ...
-
-    def platformSetMode(self): ...
-
-    def platformRead(self): ...
-
-class Time(PikaStdDevice.Time):
-    def sleep_s(self, s: int): ...
-
-    def sleep_ms(self, ms: int): ...

+ 0 - 74
package/BL808/BL808_GPIO.c

@@ -1,74 +0,0 @@
-#include "BL808_GPIO.h"
-#include <bl808_glb.h>
-#include <stdio.h>
-
-void BL808_GPIO_platformDisable(PikaObj* self) {}
-
-uint32_t getPinMode(char* mode) {
-    if (strEqu(mode, "out")) {
-        return GPIO_MODE_OUTPUT;
-    }
-    if (strEqu(mode, "in")) {
-        return GPIO_MODE_INPUT;
-    }
-    return NULL;
-}
-
-uint32_t getPinNum(char* pin) {
-    /* xx */
-    char* pin_num = pin + 1;
-    int pin_num_int = atoi(pin_num);
-    return pin_num_int;
-}
-
-void BL808_GPIO_platformEnable(PikaObj* self) {
-    /* Pxx */
-    char* pin = obj_getStr(self, "pin");
-    char* mode = obj_getStr(self, "mode");
-    printf("[  Info]: pin: %s, mode: %s, enable...\r\n", pin, mode);
-    // char *pull = obj_getStr(self, "pull");
-
-    GLB_GPIO_Cfg_Type cfg;
-    cfg.drive = 0;
-    cfg.smtCtrl = 1;
-    cfg.gpioFun = GPIO_FUN_GPIO;
-    cfg.outputMode = 0;
-    cfg.pullType = GPIO_PULL_NONE;
-
-    cfg.gpioPin = getPinNum(pin);
-    cfg.gpioMode = getPinMode(mode);
-    GLB_GPIO_Init(&cfg);
-}
-
-void BL808_GPIO_platformHigh(PikaObj* self) {
-    char* pin = obj_getStr(self, "pin");
-    printf("[  Info]: pin: %s set high...\r\n", pin);
-    GLB_GPIO_Write(getPinNum(pin), true);
-}
-
-void BL808_GPIO_platformLow(PikaObj* self) {
-    char* pin = obj_getStr(self, "pin");
-    printf("[  Info]: pin: %s set low...\r\n", pin);
-    GLB_GPIO_Write(getPinNum(pin), false);
-}
-
-void BL808_GPIO_platformRead(PikaObj* self) {
-    char* pin = obj_getStr(self, "pin");
-    obj_setInt(self, "readBuff", GLB_GPIO_Read(getPinNum(pin)));
-}
-
-void BL808_GPIO_platformSetMode(PikaObj* self) {
-    char* pin = obj_getStr(self, "pin");
-    char* mode = obj_getStr(self, "mode");
-
-    GLB_GPIO_Cfg_Type cfg;
-    cfg.drive = 0;
-    cfg.smtCtrl = 1;
-    cfg.gpioFun = GPIO_FUN_GPIO;
-    cfg.outputMode = 0;
-    cfg.pullType = GPIO_PULL_NONE;
-
-    cfg.gpioPin = getPinNum(pin);
-    cfg.gpioMode = getPinMode(mode);
-    GLB_GPIO_Init(&cfg);
-}

+ 0 - 11
package/BL808/BL808_Time.c

@@ -1,11 +0,0 @@
-#include "BL808_Time.h"
-#include <FreeRTOS.h>
-#include <task.h>
-
-void BL808_Time_sleep_ms(PikaObj* self, int ms) {
-    vTaskDelay(pdMS_TO_TICKS(ms));
-}
-
-void BL808_Time_sleep_s(PikaObj* self, int s) {
-    vTaskDelay(pdMS_TO_TICKS(1000 * s));
-}

+ 292 - 0
package/BLIOT/LCD_driver.c

@@ -0,0 +1,292 @@
+#include "LCD_driver.h"
+#include <FreeRTOS.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <task.h>
+
+volatile static pika_dev* LCD_DC = NULL;
+volatile static pika_dev* LCD_SPI = NULL;
+
+static inline void _LCD_RS_SET(void) {
+    uint32_t val = 1;
+    pika_hal_write((pika_dev*)LCD_DC, &val, sizeof(val));
+}
+
+static inline void _LCD_RS_CLR(void) {
+    uint32_t val = 0;
+    pika_hal_write((pika_dev*)LCD_DC, &val, sizeof(val));
+}
+
+// 管理LCD重要参数
+// 默认为竖屏
+_lcd_dev lcddev;
+
+// 画笔颜色,背景颜色
+u16 POINT_COLOR = 0x0000, BACK_COLOR = 0xFFFF;
+u16 DeviceCode;
+
+#define LCD_WRITE_BATCH_SIZE 2048
+void LCD_write(uint8_t* data, uint32_t len) {
+    for (int i = 0; i < len / LCD_WRITE_BATCH_SIZE; i++) {
+        pika_hal_write((pika_dev*)LCD_SPI, data + i * LCD_WRITE_BATCH_SIZE,
+                       LCD_WRITE_BATCH_SIZE);
+    }
+    pika_hal_write((pika_dev*)LCD_SPI,
+                   data + len / LCD_WRITE_BATCH_SIZE * LCD_WRITE_BATCH_SIZE,
+                   len % LCD_WRITE_BATCH_SIZE);
+}
+
+void LCD_WR_REG(u8 data) {
+    LCD_RS_CLR();
+    LCD_write(&data, 1);
+}
+
+void LCD_WR_DATA(u8 data) {
+    LCD_RS_SET();
+    LCD_write(&data, 1);
+}
+
+void LCD_WriteReg(u8 LCD_Reg, u16 LCD_RegValue) {
+    LCD_WR_REG(LCD_Reg);
+    LCD_WR_DATA(LCD_RegValue);
+}
+
+void LCD_WriteRAM_Prepare(void) {
+    LCD_WR_REG(lcddev.wramcmd);
+}
+
+static inline void color565_to_666(uint16_t color565, uint8_t* color666) {
+    color666[0] = (color565 >> 8) & 0xF8;
+    color666[1] = (color565 >> 3) & 0xFC;
+    color666[2] = (color565 << 3);
+}
+
+void LCD_writePoint(u16 color) {
+    /* rgb 666 */
+    uint8_t data[3] = {0};
+    color565_to_666(color, data);
+    LCD_RS_SET();
+    LCD_write(data, 3);
+}
+
+void LCD_drawPoint(u16 x, u16 y) {
+    LCD_setCursor(x, y);  // 设置光标位置
+    LCD_writePoint(POINT_COLOR);
+}
+
+void LCD_drawRegin(u16 x_start,
+                   u16 y_start,
+                   u16 x_end,
+                   u16 y_end,
+                   uint8_t* pData) {
+    u32 size = (x_end - x_start) * (y_end - y_start) * 2;
+    LCD_setRegion(x_start, y_start, x_end - 1, y_end - 1);
+    LCD_RS_SET();
+    LCD_write(pData, size);
+}
+
+#define BUFF_LINE_NUM 4
+void LCD_fillRegin(u16 x_start, u16 y_start, u16 x_end, u16 y_end, u16 color) {
+    size_t line_pix_size = x_end - x_start + 1;
+    size_t buff_pix_size = (x_end - x_start + 1) * BUFF_LINE_NUM;
+    uint8_t* buff = malloc(buff_pix_size * 3);
+    if (NULL == buff) {
+        printf("Error: malloc %d bytes failed\r\n", buff_pix_size * 3);
+    }
+    uint8_t color666[3] = {0};
+    color565_to_666(color, color666);
+    for (int i = 0; i < buff_pix_size; i++) {
+        buff[i * 3] = color666[0];
+        buff[i * 3 + 1] = color666[1];
+        buff[i * 3 + 2] = color666[2];
+    }
+    LCD_setRegion(x_start, y_start, x_end, y_end);
+    LCD_RS_SET();
+    for (int i = 0; i < (y_end - y_start + 1) / BUFF_LINE_NUM; i++) {
+        LCD_write(buff, buff_pix_size * 3);
+    }
+    if ((y_end - y_start + 1) % BUFF_LINE_NUM) {
+        LCD_write(buff,
+                  line_pix_size * 3 * ((y_end - y_start + 1) % BUFF_LINE_NUM));
+    }
+    free(buff);
+}
+
+void LCD_clear(u16 Color) {
+    LCD_fillRegin(0, 0, lcddev.width - 1, lcddev.height - 1, Color);
+}
+
+#define SPI_MODE_SOFT 1
+#define SPI_MODE_HARD 2
+
+#define SPI_MODE SPI_MODE_HARD
+
+void LCD_GPIOInit(void) {
+/* init spi */
+#if SPI_MODE == SPI_MODE_SOFT
+    LCD_SPI = pika_hal_open(PIKA_HAL_SOFT_SPI, "SPI0");
+    pika_hal_SOFT_SPI_config cfg_SPI = {0};
+    cfg_SPI.CS = NULL;
+    cfg_SPI.SCK = pika_hal_open(PIKA_HAL_GPIO, "P3");
+    cfg_SPI.MISO = pika_hal_open(PIKA_HAL_GPIO, "P21");
+    cfg_SPI.MOSI = pika_hal_open(PIKA_HAL_GPIO, "P20");
+#elif SPI_MODE == SPI_MODE_HARD
+    LCD_SPI = pika_hal_open(PIKA_HAL_SPI, "SPI0");
+    pika_hal_SPI_config cfg_SPI = {0};
+#endif
+    cfg_SPI.master_or_slave = PIKA_HAL_SPI_MASTER;
+    cfg_SPI.mode = PIKA_HAL_SPI_MODE_0;
+    cfg_SPI.data_width = PIKA_HAL_SPI_DATA_WIDTH_8;
+    cfg_SPI.speed = 40 * 1000 * 1000;
+    pika_hal_ioctl((pika_dev*)LCD_SPI, PIKA_HAL_IOCTL_CONFIG, &cfg_SPI);
+    pika_hal_ioctl((pika_dev*)LCD_SPI, PIKA_HAL_IOCTL_ENABLE);
+
+    /* init gpio */
+    LCD_DC = pika_hal_open(PIKA_HAL_GPIO, "P0");
+    pika_hal_GPIO_config cfg_DC = {0};
+    cfg_DC.dir = PIKA_HAL_GPIO_DIR_OUT;
+    pika_hal_ioctl((pika_dev*)LCD_DC, PIKA_HAL_IOCTL_CONFIG, &cfg_DC);
+    pika_hal_ioctl((pika_dev*)LCD_DC, PIKA_HAL_IOCTL_ENABLE);
+
+    pika_dev* LCD_CS = pika_hal_open(PIKA_HAL_GPIO, "P22");
+    pika_hal_GPIO_config cfg_CS = {0};
+    cfg_CS.dir = PIKA_HAL_GPIO_DIR_OUT;
+    pika_hal_ioctl((pika_dev*)LCD_CS, PIKA_HAL_IOCTL_CONFIG, &cfg_CS);
+    pika_hal_ioctl((pika_dev*)LCD_CS, PIKA_HAL_IOCTL_ENABLE);
+    uint32_t val = 0;
+    pika_hal_write((pika_dev*)LCD_CS, &val, sizeof(val));
+}
+
+void LCD_RESET(void) {}
+
+void LCD_init(void) {
+    LCD_GPIOInit();  // LCD GPIO初始化
+    LCD_RESET();     // LCD 复位
+    //************* ILI9488初始化**********//
+    LCD_WR_REG(0XF7);
+    LCD_WR_DATA(0xA9);
+    LCD_WR_DATA(0x51);
+    LCD_WR_DATA(0x2C);
+    LCD_WR_DATA(0x82);
+    LCD_WR_REG(0xC0);
+    LCD_WR_DATA(0x11);
+    LCD_WR_DATA(0x09);
+    LCD_WR_REG(0xC1);
+    LCD_WR_DATA(0x41);
+    LCD_WR_REG(0XC5);
+    LCD_WR_DATA(0x00);
+    LCD_WR_DATA(0x0A);
+    LCD_WR_DATA(0x80);
+    LCD_WR_REG(0xB1);
+    LCD_WR_DATA(0xB0);
+    LCD_WR_DATA(0x11);
+    LCD_WR_REG(0xB4);
+    LCD_WR_DATA(0x02);
+    LCD_WR_REG(0xB6);
+    LCD_WR_DATA(0x02);
+    LCD_WR_DATA(0x42);
+    LCD_WR_REG(0xB7);
+    LCD_WR_DATA(0xc6);
+    LCD_WR_REG(0xBE);
+    LCD_WR_DATA(0x00);
+    LCD_WR_DATA(0x04);
+    LCD_WR_REG(0xE9);
+    LCD_WR_DATA(0x00);
+    LCD_WR_REG(0x36);
+    LCD_WR_DATA((1 << 3) | (0 << 7) | (1 << 6) | (1 << 5));
+    LCD_WR_REG(0x3A);
+    LCD_WR_DATA(0x66);
+    LCD_WR_REG(0xE0);
+    LCD_WR_DATA(0x00);
+    LCD_WR_DATA(0x07);
+    LCD_WR_DATA(0x10);
+    LCD_WR_DATA(0x09);
+    LCD_WR_DATA(0x17);
+    LCD_WR_DATA(0x0B);
+    LCD_WR_DATA(0x41);
+    LCD_WR_DATA(0x89);
+    LCD_WR_DATA(0x4B);
+    LCD_WR_DATA(0x0A);
+    LCD_WR_DATA(0x0C);
+    LCD_WR_DATA(0x0E);
+    LCD_WR_DATA(0x18);
+    LCD_WR_DATA(0x1B);
+    LCD_WR_DATA(0x0F);
+    LCD_WR_REG(0XE1);
+    LCD_WR_DATA(0x00);
+    LCD_WR_DATA(0x17);
+    LCD_WR_DATA(0x1A);
+    LCD_WR_DATA(0x04);
+    LCD_WR_DATA(0x0E);
+    LCD_WR_DATA(0x06);
+    LCD_WR_DATA(0x2F);
+    LCD_WR_DATA(0x45);
+    LCD_WR_DATA(0x43);
+    LCD_WR_DATA(0x02);
+    LCD_WR_DATA(0x0A);
+    LCD_WR_DATA(0x09);
+    LCD_WR_DATA(0x32);
+    LCD_WR_DATA(0x36);
+    LCD_WR_DATA(0x0F);
+    LCD_WR_REG(0x11);
+    vTaskDelay(120 / portTICK_RATE_MS);
+    LCD_WR_REG(0x29);
+
+    LCD_direction(USE_HORIZONTAL);  // 设置LCD显示方向
+    // LCD_LED = 1;                    // 点亮背光
+    LCD_clear(WHITE);  // 清全屏白色
+}
+
+void LCD_setRegion(u16 xStar, u16 yStar, u16 xEnd, u16 yEnd) {
+    LCD_WR_REG(lcddev.setxcmd);
+    LCD_WR_DATA(xStar >> 8);
+    LCD_WR_DATA(0x00FF & xStar);
+    LCD_WR_DATA(xEnd >> 8);
+    LCD_WR_DATA(0x00FF & xEnd);
+
+    LCD_WR_REG(lcddev.setycmd);
+    LCD_WR_DATA(yStar >> 8);
+    LCD_WR_DATA(0x00FF & yStar);
+    LCD_WR_DATA(yEnd >> 8);
+    LCD_WR_DATA(0x00FF & yEnd);
+
+    LCD_WriteRAM_Prepare();  // 开始写入GRAM
+}
+
+void LCD_setCursor(u16 Xpos, u16 Ypos) {
+    LCD_setRegion(Xpos, Ypos, Xpos, Ypos);
+}
+
+void LCD_direction(u8 direction) {
+    lcddev.setxcmd = 0x2A;
+    lcddev.setycmd = 0x2B;
+    lcddev.wramcmd = 0x2C;
+    switch (direction) {
+        case 0:
+            lcddev.width = LCD_W;
+            lcddev.height = LCD_H;
+            LCD_WriteReg(0x36, (1 << 3) | (0 << 6) |
+                                   (0 << 7));  // BGR==1,MY==0,MX==0,MV==0
+            break;
+        case 1:
+            lcddev.width = LCD_H;
+            lcddev.height = LCD_W;
+            LCD_WriteReg(0x36, (1 << 3) | (0 << 7) | (1 << 6) |
+                                   (1 << 5));  // BGR==1,MY==1,MX==0,MV==1
+            break;
+        case 2:
+            lcddev.width = LCD_W;
+            lcddev.height = LCD_H;
+            LCD_WriteReg(0x36, (1 << 3) | (1 << 6) |
+                                   (1 << 7));  // BGR==1,MY==0,MX==0,MV==0
+            break;
+        case 3:
+            lcddev.width = LCD_H;
+            lcddev.height = LCD_W;
+            LCD_WriteReg(0x36, (1 << 3) | (1 << 7) |
+                                   (1 << 5));  // BGR==1,MY==1,MX==0,MV==1
+            break;
+        default:
+            break;
+    }
+}

+ 103 - 0
package/BLIOT/LCD_driver.h

@@ -0,0 +1,103 @@
+#ifndef __LCD_H
+#define __LCD_H
+#include <stdint.h>
+#include <stdlib.h>
+#include "../PikaStdDevice/pika_hal.h"
+#define u8 uint8_t
+#define u16 uint16_t
+#define u32 uint32_t
+
+// LCD重要参数集
+typedef struct {
+    u16 width;    // LCD 宽度
+    u16 height;   // LCD 高度
+    u16 id;       // LCD ID
+    u8 dir;       // 横屏还是竖屏控制:0,竖屏;1,横屏。
+    u16 wramcmd;  // 开始写gram指令
+    u16 setxcmd;  // 设置x坐标指令
+    u16 setycmd;  // 设置y坐标指令
+} _lcd_dev;
+
+// LCD参数
+extern _lcd_dev lcddev;  // 管理LCD重要参数
+#define USE_HORIZONTAL \
+    0  // 定义液晶屏顺时针旋转方向
+       // 0-0度旋转,1-90度旋转,2-180度旋转,3-270度旋转
+
+// 定义LCD的尺寸
+#define LCD_W 320
+#define LCD_H 480
+
+// TFTLCD部分外要调用的函数
+extern u16 POINT_COLOR;  // 默认红色
+extern u16 BACK_COLOR;   // 背景颜色.默认为白色
+
+//-----------------LCD端口定义----------------
+
+// 如果使用官方库函数定义下列底层,速度将会下降到14帧每秒,建议采用我司推荐方法
+// 以下IO定义直接操作寄存器,快速IO操作,刷屏速率可以达到28帧每秒!
+
+#define LCD_CS_SET _LCD_CS_SET
+#define LCD_RS_SET _LCD_RS_SET
+#define LCD_RST_SET _LCD_RST_SET
+
+#define LCD_CS_CLR _LCD_CS_CLR
+#define LCD_RS_CLR _LCD_RS_CLR
+#define LCD_RST_CLR _LCD_RST_CLR
+
+// 画笔颜色
+#define WHITE 0xFFFF
+#define BLACK 0x0000
+#define BLUE 0x001F
+#define BRED 0XF81F
+#define GRED 0XFFE0
+#define GBLUE 0X07FF
+#define RED 0xF800
+#define MAGENTA 0xF81F
+#define GREEN 0x07E0
+#define CYAN 0x7FFF
+#define YELLOW 0xFFE0
+#define BROWN 0XBC40  // 棕色
+#define BRRED 0XFC07  // 棕红色
+#define GRAY 0X8430   // 灰色
+// GUI颜色
+
+#define DARKBLUE 0X01CF   // 深蓝色
+#define LIGHTBLUE 0X7D7C  // 浅蓝色
+#define GRAYBLUE 0X5458   // 灰蓝色
+// 以上三色为PANEL的颜色
+
+#define LIGHTGREEN 0X841F  // 浅绿色
+#define LIGHTGRAY 0XEF5B   // 浅灰色(PANNEL)
+#define LGRAY 0XC618       // 浅灰色(PANNEL),窗体背景色
+
+#define LGRAYBLUE 0XA651  // 浅灰蓝色(中间层颜色)
+#define LBBLUE 0X2B12     // 浅棕蓝色(选择条目的反色)
+
+void LCD_init(void);
+void LCD_displayOn(void);
+void LCD_displayOff(void);
+void LCD_clear(u16 Color);
+void LCD_setCursor(u16 Xpos, u16 Ypos);
+void LCD_drawPoint(u16 x, u16 y);  // 画点
+u16 LCD_readPoint(u16 x, u16 y);   // 读点
+void LCD_drawLine(u16 x1, u16 y1, u16 x2, u16 y2);
+void LCD_drawRectangle(u16 x1, u16 y1, u16 x2, u16 y2);
+void LCD_setRegion(u16 xStar, u16 yStar, u16 xEnd, u16 yEnd);
+void LCD_writePoint(u16 Data);
+void LCD_drawRegin(u16 x_start,
+                   u16 y_start,
+                   u16 x_end,
+                   u16 y_end,
+                   uint8_t* pData);
+u16 LCD_RD_DATA(void);  // 读取LCD数据
+void LCD_WriteReg(u8 LCD_Reg, u16 LCD_RegValue);
+void LCD_WR_DATA(u8 data);
+u16 LCD_ReadReg(u8 LCD_Reg);
+void LCD_WriteRAM_Prepare(void);
+void LCD_WriteRAM(u16 RGB_Code);
+u16 LCD_ReadRAM(void);
+u16 LCD_BGR2RGB(u16 c);
+void LCD_SetParam(void);
+void LCD_direction(u8 direction);
+#endif

+ 345 - 0
package/BLIOT/Touch_driver.c

@@ -0,0 +1,345 @@
+/* Includes ------------------------------------------------------------------*/
+#include "Touch_driver.h"
+#include <FreeRTOS.h>
+#include <string.h>
+#include <task.h>
+#include "../PikaStdDevice/pika_hal.h"
+/* Private typedef -----------------------------------------------------------*/
+
+/* Private define ------------------------------------------------------------*/
+
+/* Private macro -------------------------------------------------------------*/
+
+/* Private variables ---------------------------------------------------------*/
+static uint8_t GT911_Config[] = {
+    0x81, 0x00, 0x04, 0x58, 0x02, 0x0A, 0x0C,
+    0x20, 0x01, 0x08, 0x28, 0x05, 0x50,  // 0x8047 - 0x8053
+    0x3C, 0x0F, 0x05, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x8054 - 0x8060
+    0x00, 0x89, 0x2A, 0x0B, 0x2D, 0x2B, 0x0F,
+    0x0A, 0x00, 0x00, 0x01, 0xA9, 0x03,  // 0x8061 - 0x806D
+    0x2D, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x21,  // 0x806E - 0x807A
+    0x59, 0x94, 0xC5, 0x02, 0x07, 0x00, 0x00,
+    0x04, 0x93, 0x24, 0x00, 0x7D, 0x2C,  // 0x807B - 0x8087
+    0x00, 0x6B, 0x36, 0x00, 0x5D, 0x42, 0x00,
+    0x53, 0x50, 0x00, 0x53, 0x00, 0x00,  // 0x8088	- 0x8094
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x8095 - 0x80A1
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x80A2 - 0x80AD
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x02, 0x04, 0x06, 0x08, 0x0A,  // 0x80AE - 0x80BA
+    0x0C, 0x0E, 0x10, 0x12, 0x14, 0x16, 0xFF,
+    0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,  // 0x80BB - 0x80C7
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x80C8 - 0x80D4
+    0x02, 0x04, 0x06, 0x08, 0x0A, 0x0F, 0x10,
+    0x12, 0x16, 0x18, 0x1C, 0x1D, 0x1E,  // 0x80D5 - 0x80E1
+    0x1F, 0x20, 0x21, 0x22, 0x24, 0xFF, 0xFF,
+    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,  // 0x80E2 - 0x80EE
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x80EF - 0x80FB
+    0x00, 0x00, 0xD6, 0x01};             // 0x80FC - 0x8100
+static GT911_Status_t CommunicationResult;
+static uint8_t TxBuffer[200];
+static uint8_t RxBuffer[200] = {0};
+/* Private function prototypes -----------------------------------------------*/
+static void GT911_Reset(void);
+static void GT911_CalculateCheckSum(void);
+static GT911_Status_t GT911_SetCommandRegister(uint8_t command);
+static GT911_Status_t GT911_GetProductID(uint32_t* id);
+static GT911_Status_t GT911_SendConfig(void);
+static GT911_Status_t GT911_GetStatus(uint8_t* status);
+static GT911_Status_t GT911_SetStatus(uint8_t status);
+
+GT911_Status_t GT911_I2C_Read_Mem(uint8_t Addr,
+                                  uint16_t mem_addr,
+                                  uint8_t* read_data,
+                                  uint16_t read_length);
+
+GT911_Status_t GT911_I2C_Write_Mem(uint8_t Addr,
+                                   uint16_t mem_addr,
+                                   uint8_t* write_data,
+                                   uint16_t write_length);
+/* API Implementation
+ * --------------------------------------------------------*/
+GT911_Status_t GT911_Init(GT911_Config_t config) {
+    //	Set X resolution
+    GT911_Config[1] = config.X_Resolution & 0x00FF;
+    GT911_Config[2] = (config.X_Resolution >> 8) & 0x00FF;
+    //	Set Y resolution
+    GT911_Config[3] = config.Y_Resolution & 0x00FF;
+    GT911_Config[4] = (config.Y_Resolution >> 8) & 0x00FF;
+    //  Set touch number
+    GT911_Config[5] = config.Number_Of_Touch_Support;
+    //  set reverse Y
+    GT911_Config[6] = 0;
+    GT911_Config[6] |= config.ReverseY << 7;
+    //  set reverse X
+    GT911_Config[6] |= config.ReverseX << 6;
+    //  set switch X2Y
+    GT911_Config[6] |= config.SwithX2Y << 3;
+    //  set Sito
+    GT911_Config[6] |= config.SoftwareNoiseReduction << 2;
+
+    // Reset chip
+    GT911_Reset();
+    // Get product ID
+    uint32_t productID = 0;
+    CommunicationResult = GT911_GetProductID(&productID);
+    __platform_printf("GT911 ID:%d\r\n", productID);
+    // Reset chip
+    GT911_Reset();
+    CommunicationResult = GT911_SendConfig();
+    if (CommunicationResult != GT911_OK) {
+        return CommunicationResult;
+    }
+    GT911_SetCommandRegister(0x00);
+    return GT911_OK;
+}
+
+GT911_Status_t GT911_ReadTouch(TouchCordinate_t* cordinate,
+                               uint8_t* number_of_cordinate) {
+    uint8_t StatusRegister;
+    GT911_Status_t Result = GT911_NotResponse;
+    Result = GT911_GetStatus(&StatusRegister);
+    if (Result != GT911_OK) {
+        return Result;
+    }
+    if ((StatusRegister & 0x80) != 0) {
+        *number_of_cordinate = StatusRegister & 0x0F;
+        if (*number_of_cordinate != 0) {
+            for (uint8_t i = 0; i < *number_of_cordinate; i++) {
+                TxBuffer[0] = ((GOODIX_POINT1_X_ADDR + (i * 8)) & 0xFF00) >> 8;
+                TxBuffer[1] = (GOODIX_POINT1_X_ADDR + (i * 8)) & 0xFF;
+                GT911_I2C_Write(GOODIX_ADDRESS, TxBuffer, 2);
+                GT911_I2C_Read(GOODIX_ADDRESS, RxBuffer, 6);
+                cordinate[i].x = RxBuffer[0];
+                cordinate[i].x = (RxBuffer[1] << 8) + cordinate[i].x;
+                cordinate[i].y = RxBuffer[2];
+                cordinate[i].y = (RxBuffer[3] << 8) + cordinate[i].y;
+            }
+        }
+        GT911_SetStatus(0);
+    }
+    return GT911_OK;
+}
+
+// Private functions Implementation
+// ---------------------------------------------------------*/
+static void GT911_Reset(void) {
+    GT911_INT_Output();
+    GT911_RST_Control(0);
+    GT911_Delay(20);
+    GT911_INT_Control(0);
+    GT911_Delay(50);
+    GT911_RST_Control(1);
+    GT911_Delay(100);
+    GT911_INT_Input();
+    GT911_Delay(100);
+}
+
+static void GT911_CalculateCheckSum(void) {
+    GT911_Config[184] = 0;
+    for (uint8_t i = 0; i < 184; i++) {
+        GT911_Config[184] += GT911_Config[i];
+    }
+    GT911_Config[184] = (~GT911_Config[184]) + 1;
+}
+
+static GT911_Status_t GT911_SetCommandRegister(uint8_t command) {
+    TxBuffer[0] = (GOODIX_REG_COMMAND & 0xFF00) >> 8;
+    TxBuffer[1] = GOODIX_REG_COMMAND & 0xFF;
+    TxBuffer[2] = command;
+    return GT911_I2C_Write(GOODIX_ADDRESS, TxBuffer, 3);
+}
+
+static GT911_Status_t GT911_GetProductID(uint32_t* id) {
+    TxBuffer[0] = (GOODIX_REG_ID & 0xFF00) >> 8;
+    TxBuffer[1] = GOODIX_REG_ID & 0xFF;
+    GT911_Status_t Result = GT911_NotResponse;
+    Result = GT911_I2C_Write(GOODIX_ADDRESS, TxBuffer, 2);
+    if (Result == GT911_OK) {
+        Result = GT911_I2C_Read(GOODIX_ADDRESS, RxBuffer, 4);
+        if (Result == GT911_OK) {
+            memcpy(id, RxBuffer, 4);
+        }
+    }
+    return Result;
+}
+
+static GT911_Status_t GT911_SendConfig(void) {
+    GT911_CalculateCheckSum();
+    TxBuffer[0] = (GOODIX_REG_CONFIG_DATA & 0xFF00) >> 8;
+    TxBuffer[1] = GOODIX_REG_CONFIG_DATA & 0xFF;
+    memcpy(&TxBuffer[2], GT911_Config, sizeof(GT911_Config));
+    return GT911_I2C_Write(GOODIX_ADDRESS, TxBuffer, sizeof(GT911_Config) + 2);
+}
+
+static GT911_Status_t GT911_GetStatus(uint8_t* status) {
+    TxBuffer[0] = (GOODIX_READ_COORD_ADDR & 0xFF00) >> 8;
+    TxBuffer[1] = GOODIX_READ_COORD_ADDR & 0xFF;
+    GT911_Status_t Result = GT911_NotResponse;
+    Result = GT911_I2C_Write(GOODIX_ADDRESS, TxBuffer, 2);
+    if (Result == GT911_OK) {
+        Result = GT911_I2C_Read(GOODIX_ADDRESS, RxBuffer, 1);
+        if (Result == GT911_OK) {
+            *status = RxBuffer[0];
+        }
+    }
+    return Result;
+}
+
+static GT911_Status_t GT911_SetStatus(uint8_t status) {
+    TxBuffer[0] = (GOODIX_READ_COORD_ADDR & 0xFF00) >> 8;
+    TxBuffer[1] = GOODIX_READ_COORD_ADDR & 0xFF;
+    TxBuffer[2] = status;
+    return GT911_I2C_Write(GOODIX_ADDRESS, TxBuffer, 3);
+}
+
+static pika_dev* TOUCH_INT = NULL;
+static pika_dev* TOUCH_RST = NULL;
+static pika_dev* TOUCH_IIC = NULL;
+
+void GT911_INT_Input(void) {
+    if (NULL == TOUCH_INT) {
+        TOUCH_INT = pika_hal_open(PIKA_HAL_GPIO, "P17");
+    }
+    pika_hal_GPIO_config cfg = {0};
+    cfg.dir = PIKA_HAL_GPIO_DIR_IN;
+    cfg.pull = PIKA_HAL_GPIO_PULL_NONE;
+    pika_hal_ioctl(TOUCH_INT, PIKA_HAL_IOCTL_CONFIG, &cfg);
+    pika_hal_ioctl(TOUCH_INT, PIKA_HAL_IOCTL_ENABLE);
+}
+
+void GT911_INT_Output(void) {
+    if (NULL == TOUCH_INT) {
+        TOUCH_INT = pika_hal_open(PIKA_HAL_GPIO, "P17");
+    }
+    pika_hal_GPIO_config cfg = {0};
+    cfg.dir = PIKA_HAL_GPIO_DIR_OUT;
+    cfg.pull = PIKA_HAL_GPIO_PULL_NONE;
+    pika_hal_ioctl(TOUCH_INT, PIKA_HAL_IOCTL_CONFIG, &cfg);
+    pika_hal_ioctl(TOUCH_INT, PIKA_HAL_IOCTL_ENABLE);
+}
+
+void GT911_RST_Control(bool high_or_low) {
+    if (NULL == TOUCH_RST) {
+        TOUCH_RST = pika_hal_open(PIKA_HAL_GPIO, "P5");
+        pika_hal_GPIO_config cfg = {0};
+        cfg.dir = PIKA_HAL_GPIO_DIR_OUT;
+        pika_hal_ioctl(TOUCH_RST, PIKA_HAL_IOCTL_CONFIG, &cfg);
+        pika_hal_ioctl(TOUCH_RST, PIKA_HAL_IOCTL_ENABLE);
+    }
+    uint32_t val = 0;
+    switch (high_or_low) {
+        case true:
+            val = 1;
+            pika_hal_write(TOUCH_RST, &val, sizeof(uint32_t));
+            break;
+        case false:
+            val = 0;
+            pika_hal_write(TOUCH_RST, &val, sizeof(uint32_t));
+            break;
+    }
+}
+
+void GT911_INT_Control(bool high_or_low) {
+    if (NULL == TOUCH_INT) {
+        GT911_INT_Output();
+    }
+    uint32_t val = 0;
+    switch (high_or_low) {
+        case true:
+            val = 1;
+            pika_hal_write(TOUCH_INT, &val, sizeof(uint32_t));
+            break;
+        case false:
+            val = 0;
+            pika_hal_write(TOUCH_INT, &val, sizeof(uint32_t));
+            break;
+    }
+}
+
+void GT911_Delay(uint16_t ms) {
+    // HAL_Delay(ms);
+    vTaskDelay(ms / portTICK_PERIOD_MS);
+}
+
+GT911_Status_t GT911_I2C_Init(void) {
+    if (NULL == TOUCH_IIC) {
+        TOUCH_IIC = pika_hal_open(PIKA_HAL_IIC, "IIC3");
+        pika_hal_IIC_config cfg = {0};
+        cfg.slave_addr = GOODIX_ADDRESS;
+        cfg.speed = 400000;
+        cfg.timeout = 10000;
+        pika_hal_ioctl(TOUCH_IIC, PIKA_HAL_IOCTL_CONFIG, &cfg);
+        pika_hal_ioctl(TOUCH_IIC, PIKA_HAL_IOCTL_ENABLE);
+    }
+    return GT911_OK;
+}
+
+GT911_Status_t GT911_I2C_Write(uint8_t Addr,
+                               uint8_t* write_data,
+                               uint16_t write_length) {
+    if (NULL == TOUCH_IIC) {
+        GT911_I2C_Init();
+    }
+    pika_hal_IIC_config cfg = {0};
+    cfg.slave_addr = Addr;
+    cfg.mem_addr_ena = PIKA_HAL_IIC_MEM_ADDR_ENA_DISABLE;
+    pika_hal_ioctl(TOUCH_IIC, PIKA_HAL_IOCTL_CONFIG, &cfg);
+    pika_hal_write(TOUCH_IIC, write_data, write_length);
+    return GT911_OK;
+}
+
+GT911_Status_t GT911_I2C_Write_Mem(uint8_t Addr,
+                                   uint16_t mem_addr,
+                                   uint8_t* write_data,
+                                   uint16_t write_length) {
+    if (NULL == TOUCH_IIC) {
+        GT911_I2C_Init();
+    }
+    pika_hal_IIC_config cfg = {0};
+    cfg.slave_addr = Addr;
+    cfg.mem_addr = mem_addr;
+    cfg.mem_addr_ena = PIKA_HAL_IIC_MEM_ADDR_ENA_ENABLE;
+    cfg.mem_addr_size = sizeof(uint16_t);
+    pika_hal_ioctl(TOUCH_IIC, PIKA_HAL_IOCTL_CONFIG, &cfg);
+    pika_hal_write(TOUCH_IIC, write_data, write_length);
+    return GT911_OK;
+}
+
+GT911_Status_t GT911_I2C_Read(uint8_t Addr,
+                              uint8_t* read_data,
+                              uint16_t read_length) {
+    if (NULL == TOUCH_IIC) {
+        GT911_I2C_Init();
+    }
+    pika_hal_IIC_config cfg = {0};
+    cfg.slave_addr = Addr;
+    cfg.mem_addr_ena = PIKA_HAL_IIC_MEM_ADDR_ENA_DISABLE;
+    pika_hal_ioctl(TOUCH_IIC, PIKA_HAL_IOCTL_CONFIG, &cfg);
+    pika_hal_read(TOUCH_IIC, read_data, read_length);
+    return GT911_OK;
+}
+
+GT911_Status_t GT911_I2C_Read_Mem(uint8_t Addr,
+                                  uint16_t mem_addr,
+                                  uint8_t* read_data,
+                                  uint16_t read_length) {
+    if (NULL == TOUCH_IIC) {
+        GT911_I2C_Init();
+    }
+    pika_hal_IIC_config cfg = {0};
+    cfg.slave_addr = Addr;
+    cfg.mem_addr = mem_addr;
+    cfg.mem_addr_ena = PIKA_HAL_IIC_MEM_ADDR_ENA_ENABLE;
+    cfg.mem_addr_size = sizeof(uint16_t);
+    pika_hal_ioctl(TOUCH_IIC, PIKA_HAL_IOCTL_CONFIG, &cfg);
+    pika_hal_read(TOUCH_IIC, read_data, read_length);
+    return GT911_OK;
+}
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF
+ * FILE****/

+ 122 - 0
package/BLIOT/Touch_driver.h

@@ -0,0 +1,122 @@
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __GT911_H_
+#define __GT911_H_
+
+/* Includes ------------------------------------------------------------------*/
+#include <stdbool.h>
+#include <stdint.h>
+/* Exported macro ------------------------------------------------------------*/
+// GOODIX REGISTER ADDRESSES
+//
+#define GOODIX_ADDRESS 0x5D
+
+// Write only registers
+#define GOODIX_REG_COMMAND 0x8040
+#define GOODIX_REG_ESD_CHECK 0x8041
+#define GOODIX_REG_PROXIMITY_EN 0x8042
+
+// Read/write registers
+// The version number of the configuration file
+#define GOODIX_REG_CONFIG_DATA 0x8047
+// X output maximum value (LSB 2 bytes)
+#define GOODIX_REG_MAX_X 0x8048
+// Y output maximum value (LSB 2 bytes)
+#define GOODIX_REG_MAX_Y 0x804A
+// Maximum number of output contacts: 1~5 (4 bit value 3:0, 7:4 is reserved)
+#define GOODIX_REG_MAX_TOUCH 0x804C
+
+// Module switch 1
+// 7:6 Reserved, 5:4 Stretch rank, 3 X2Y, 2 SITO (Single sided ITO touch
+// screen), 1:0 INT Trigger mode */
+#define GOODIX_REG_MOD_SW1 0x804D
+// Module switch 2
+// 7:1 Reserved, 0 Touch key */
+#define GOODIX_REG_MOD_SW2 0x804E
+
+// Number of debuffs fingers press/release
+#define GOODIX_REG_SHAKE_CNT 0x804F
+
+// X threshold
+#define GOODIX_REG_X_THRESHOLD 0x8057
+
+// Configuration update fresh
+#define GOODIX_REG_CONFIG_FRESH 0x8100
+
+// ReadOnly registers (device and coordinates info)
+// Product ID (LSB 4 bytes, GT9110: 0x06 0x00 0x00 0x09)
+#define GOODIX_REG_ID 0x8140
+// Firmware version (LSB 2 bytes)
+#define GOODIX_REG_FW_VER 0x8144
+
+// Current output X resolution (LSB 2 bytes)
+#define GOODIX_READ_X_RES 0x8146
+// Current output Y resolution (LSB 2 bytes)
+#define GOODIX_READ_Y_RES 0x8148
+// Module vendor ID
+#define GOODIX_READ_VENDOR_ID 0x814A
+
+#define GOODIX_READ_COORD_ADDR 0x814E
+
+#define GOODIX_POINT1_X_ADDR 0x8150
+#define GOODIX_POINT1_Y_ADDR 0x8152
+
+/* Commands for REG_COMMAND */
+// 0: read coordinate state
+#define GOODIX_CMD_READ 0x00
+// 1: difference value original value
+#define GOODIX_CMD_DIFFVAL 0x01
+// 2: software reset
+#define GOODIX_CMD_SOFTRESET 0x02
+// 3: Baseline update
+#define GOODIX_CMD_BASEUPDATE 0x03
+// 4: Benchmark calibration
+#define GOODIX_CMD_CALIBRATE 0x04
+// 5: Off screen (send other invalid)
+#define GOODIX_CMD_SCREEN_OFF 0x05
+
+/* Exported types ------------------------------------------------------------*/
+typedef enum {
+    GT911_OK = 0,
+    GT911_Error = 1,
+    GT911_NotResponse = 2
+} GT911_Status_t;
+
+typedef struct {
+    uint16_t X_Resolution;
+    uint16_t Y_Resolution;
+    uint8_t Number_Of_Touch_Support;
+    bool ReverseX;
+    bool ReverseY;
+    bool SwithX2Y;
+    bool SoftwareNoiseReduction;
+
+} GT911_Config_t;
+
+typedef struct {
+    uint16_t x;
+    uint16_t y;
+} TouchCordinate_t;
+
+/* Exported constants --------------------------------------------------------*/
+
+/* Exported functions ------------------------------------------------------- */
+GT911_Status_t GT911_Init(GT911_Config_t config);
+GT911_Status_t GT911_ReadTouch(TouchCordinate_t* cordinate,
+                               uint8_t* number_of_cordinate);
+
+// User method implementation prototype
+// ----------------------------------------*/
+void GT911_INT_Input(void);
+void GT911_INT_Output(void);
+void GT911_RST_Control(bool high_or_low);
+void GT911_INT_Control(bool high_or_low);
+void GT911_Delay(uint16_t ms);
+GT911_Status_t GT911_I2C_Init(void);
+GT911_Status_t GT911_I2C_Write(uint8_t Addr,
+                               uint8_t* write_data,
+                               uint16_t write_length);
+GT911_Status_t GT911_I2C_Read(uint8_t Addr,
+                              uint8_t* read_data,
+                              uint16_t read_length);
+
+#endif /* __GT911_H_ */

+ 40 - 0
package/BLIOT/pika_hal_BLIOT_GPIO.c

@@ -1,6 +1,7 @@
 #include <bl_gpio.h>
 #include <hosal_gpio.h>
 #include "../PikaStdDevice/pika_hal.h"
+#include "pika_hal_BLIOT_irq_task.h"
 
 int pika_hal_platform_GPIO_open(pika_dev* dev, char* name) {
     dev->platform_data = pikaMalloc(sizeof(hosal_gpio_dev_t));
@@ -22,6 +23,10 @@ int pika_hal_platform_GPIO_read(pika_dev* dev, void* buf, size_t count) {
     hosal_gpio_input_get(platform_gpio, &value);
     uint32_t value_in = value;
     memcpy(buf, &value_in, sizeof(value_in));
+#if PIKA_DEBUG_ENABLE
+    __platform_printf("GPIO read port %d to %d\r\n", platform_gpio->port,
+                      value_in);
+#endif
     return 0;
 }
 
@@ -56,6 +61,15 @@ int pika_hal_platform_GPIO_ioctl_disable(pika_dev* dev) {
     return 0;
 }
 
+extern volatile _BLIOT_irq g_irq;
+void _hosal_gpio_irq_handler(void* arg) {
+    if (g_irq.gpio_irq_trigger) {
+        return;
+    }
+    g_irq.gpio_irq_arg = arg;
+    g_irq.gpio_irq_trigger = 1;
+}
+
 int pika_hal_platform_GPIO_ioctl_config(pika_dev* dev,
                                         pika_hal_GPIO_config* cfg) {
     hosal_gpio_dev_t* platform_gpio = (hosal_gpio_dev_t*)dev->platform_data;
@@ -84,9 +98,11 @@ int pika_hal_platform_GPIO_ioctl_config(pika_dev* dev,
             switch (cfg->pull) {
                 case PIKA_HAL_GPIO_PULL_NONE:
                     platform_gpio->config = INPUT_HIGH_IMPEDANCE;
+                    break;
 
                 case PIKA_HAL_GPIO_PULL_UP:
                     platform_gpio->config = INPUT_PULL_UP;
+                    break;
 
                 case PIKA_HAL_GPIO_PULL_DOWN:
                     /* not supported */
@@ -94,6 +110,7 @@ int pika_hal_platform_GPIO_ioctl_config(pika_dev* dev,
                 default:
                     return -1;
             }
+            break;
         default:
 #if PIKA_DEBUG_ENABLE
             __platform_printf("GPIO set port %d to unknown\r\n",
@@ -101,5 +118,28 @@ int pika_hal_platform_GPIO_ioctl_config(pika_dev* dev,
 #endif
             return -1;
     }
+
+    /* support event callback */
+    if (NULL != cfg->event_callback &&
+        PIKA_HAL_EVENT_CALLBACK_ENA_ENABLE == cfg->event_callback_ena) {
+        switch (cfg->event_callback_filter) {
+            case PIKA_HAL_GPIO_EVENT_SIGNAL_RISING:
+                hosal_gpio_irq_set(dev->platform_data, HOSAL_IRQ_TRIG_POS_PULSE,
+                                   _hosal_gpio_irq_handler, dev);
+                break;
+            case PIKA_HAL_GPIO_EVENT_SIGNAL_FALLING:
+                hosal_gpio_irq_set(dev->platform_data, HOSAL_IRQ_TRIG_NEG_PULSE,
+                                   _hosal_gpio_irq_handler, dev);
+                break;
+
+            default:
+                __platform_printf(
+                    "Error: not supported event callback filter %d\r\n",
+                    cfg->event_callback_filter);
+                return -1;
+        }
+        /* start irq task thread */
+        _BLIOT_irq_task_start();
+    }
     return 0;
 }

+ 12 - 12
package/BLIOT/pika_hal_BLIOT_IIC.c

@@ -136,34 +136,34 @@ int pika_hal_platform_IIC_ioctl_disable(pika_dev* dev) {
 int pika_hal_platform_IIC_write(pika_dev* dev, void* buf, size_t count) {
     hosal_i2c_dev_t* platform_i2c = (hosal_i2c_dev_t*)dev->platform_data;
     pika_hal_IIC_config* cfg = (pika_hal_IIC_config*)dev->ioctl_config;
-    if (!cfg->mem_addr_ena) {
-        return hosal_i2c_master_send(platform_i2c, cfg->slave_addr, buf, count,
-                                     cfg->timeout);
-#ifdef PIKA_DEBUG_ENABLE
+    if (cfg->mem_addr_ena == PIKA_HAL_IIC_MEM_ADDR_ENA_DISABLE) {
+#if PIKA_DEBUG_ENABLE
         __platform_printf("IIC: Write %d bytes to 0x%02x\r\n", count,
                           cfg->slave_addr);
 #endif
+        return hosal_i2c_master_send(platform_i2c, cfg->slave_addr, buf, count,
+                                     cfg->timeout);
     } else {
-        return hosal_i2c_mem_write(platform_i2c, cfg->slave_addr, cfg->mem_addr,
-                                   cfg->mem_addr_size, buf, count,
-                                   cfg->timeout);
-#ifdef PIKA_DEBUG_ENABLE
+#if PIKA_DEBUG_ENABLE
         __platform_printf("IIC: Write %d bytes to 0x%02x, mem_addr:0x%02x\r\n",
                           count, cfg->slave_addr, cfg->mem_addr);
 #endif
+        return hosal_i2c_mem_write(platform_i2c, cfg->slave_addr, cfg->mem_addr,
+                                   cfg->mem_addr_size, buf, count,
+                                   cfg->timeout);
     }
 }
 
 int pika_hal_platform_IIC_read(pika_dev* dev, void* buf, size_t count) {
     hosal_i2c_dev_t* platform_i2c = (hosal_i2c_dev_t*)dev->platform_data;
     pika_hal_IIC_config* cfg = (pika_hal_IIC_config*)dev->ioctl_config;
-    if (!cfg->mem_addr_ena) {
-        return hosal_i2c_master_recv(platform_i2c, cfg->slave_addr, buf, count,
-                                     cfg->timeout);
-#ifdef PIKA_DEBUG_ENABLE
+    if (cfg->mem_addr_ena == PIKA_HAL_IIC_MEM_ADDR_ENA_DISABLE) {
+#if PIKA_DEBUG_ENABLE
         __platform_printf("IIC: Read %d bytes from 0x%02x\r\n", count,
                           cfg->slave_addr);
 #endif
+        return hosal_i2c_master_recv(platform_i2c, cfg->slave_addr, buf, count,
+                                     cfg->timeout);
     } else {
 #if PIKA_DEBUG_ENABLE
         __platform_printf("IIC: Read %d bytes from 0x%02x, mem_addr:0x%02x\r\n",

+ 34 - 9
package/BLIOT/pika_hal_BLIOT_SPI.c

@@ -1,22 +1,23 @@
+#include <hosal_dma.h>
 #include <hosal_spi.h>
 #include "../PikaStdDevice/pika_hal.h"
 
-static int _num2pin(int num, uint8_t* mosi, uint8_t* miso, uint8_t* scli) {
+static int _num2pin(int num, uint8_t* mosi, uint8_t* miso, uint8_t* clk) {
     /***********************   BL602  **************************
-     *    SPI0  ----->     MOSI:P20, MISO:P0, SCLK:P22
+     *    SPI0  ----->     MOSI:P20, MISO:P21, SCLK:P3
      */
     switch (num) {
         case 0:
             *mosi = 20;
-            *miso = 0;
-            *scli = 22;
+            *miso = 21;
+            *clk = 3;
             break;
         default:
             return -1;
     }
 #if PIKA_DEBUG_ENABLE
     __platform_printf("SPI%d: mosi:%d, miso:%d, scli:%d\r\n", num, *mosi, *miso,
-                      *scli);
+                      *clk);
 #endif
     return 0;
 }
@@ -32,6 +33,12 @@ int pika_hal_platform_SPI_open(pika_dev* dev, char* name) {
         if (0 == _num2pin(spi_num, &platform_spi->config.pin_mosi,
                           &platform_spi->config.pin_miso,
                           &platform_spi->config.pin_clk)) {
+#if PIKA_DEBUG_ENABLE
+            __platform_printf("SPI: mosi:%d, miso:%d, scli:%d\r\n",
+                              platform_spi->config.pin_mosi,
+                              platform_spi->config.pin_miso,
+                              platform_spi->config.pin_clk);
+#endif
             return 0;
         } else {
             __platform_printf("SPI: Open SPI%d failed\r\n", spi_num);
@@ -54,7 +61,8 @@ int pika_hal_platform_SPI_ioctl_config(pika_dev* dev,
     hosal_spi_dev_t* platform_spi = (hosal_spi_dev_t*)dev->platform_data;
     if (!dev->is_enabled) {
         platform_spi->port = 0;
-        platform_spi->config.dma_enable = 0;
+        platform_spi->config.dma_enable = 1;
+        hosal_dma_init();
         platform_spi->config.freq = cfg->speed;
         platform_spi->p_arg = NULL;
         switch (cfg->master_or_slave) {
@@ -101,7 +109,10 @@ int pika_hal_platform_SPI_ioctl_enable(pika_dev* dev) {
             platform_spi->port, platform_spi->config.freq,
             platform_spi->config.mode, platform_spi->config.polar_phase);
 #endif
-        hosal_spi_init(platform_spi);
+        if (0 != hosal_spi_init(platform_spi)) {
+            __platform_printf("SPI: Open SPI%d failed\r\n", platform_spi->port);
+            return -1;
+        }
         return 0;
     }
     return -1;
@@ -119,11 +130,25 @@ int pika_hal_platform_SPI_ioctl_disable(pika_dev* dev) {
 int pika_hal_platform_SPI_write(pika_dev* dev, void* buf, size_t count) {
     hosal_spi_dev_t* platform_spi = (hosal_spi_dev_t*)dev->platform_data;
     pika_hal_SPI_config* cfg = (pika_hal_SPI_config*)dev->ioctl_config;
-    return hosal_spi_send(platform_spi, buf, count, cfg->timeout);
+#if PIKA_DEBUG_ENABLE
+    __platform_printf("SPI: Write %d bytes\r\n", count);
+#endif
+    int ret = hosal_spi_send(platform_spi, buf, count, cfg->timeout);
+    if (0 != ret) {
+        __platform_printf("SPI: Write %d bytes failed\r\n", count);
+    }
+    return ret;
 }
 
 int pika_hal_platform_SPI_read(pika_dev* dev, void* buf, size_t count) {
     hosal_spi_dev_t* platform_spi = (hosal_spi_dev_t*)dev->platform_data;
     pika_hal_SPI_config* cfg = (pika_hal_SPI_config*)dev->ioctl_config;
-    return hosal_spi_recv(platform_spi, buf, count, cfg->timeout);
+#if PIKA_DEBUG_ENABLE
+    __platform_printf("SPI: Read %d bytes\r\n", count);
+#endif
+    int ret = hosal_spi_recv(platform_spi, buf, count, cfg->timeout);
+    if (0 != ret) {
+        __platform_printf("SPI: Read %d bytes failed\r\n", count);
+    }
+    return ret;
 }

+ 163 - 0
package/BLIOT/pika_hal_BLIOT_UART.c

@@ -0,0 +1,163 @@
+#include <hosal_uart.h>
+#include "../PikaStdDevice/pika_hal.h"
+#include "pika_hal_BLIOT_irq_task.h"
+
+extern hosal_uart_dev_t uart_stdio;
+
+int pika_hal_platform_UART_open(pika_dev* dev, char* name) {
+    /* Support UART1 */
+    if (name[0] == 'U' && name[1] == 'A' && name[2] == 'R' && name[3] == 'T') {
+        hosal_uart_dev_t* platform_uart = &uart_stdio;
+        dev->platform_data = platform_uart;
+        int UART_num = fast_atoi(name + 4);
+#if PIKA_DEBUG_ENABLE
+        __platform_printf("opening UART%d\r\n", UART_num);
+#endif
+        return 0;
+    }
+    return -1;
+}
+
+int pika_hal_platform_UART_close(pika_dev* dev) {
+    hosal_uart_dev_t* platform_uart = (hosal_uart_dev_t*)dev->platform_data;
+    if (platform_uart == &uart_stdio) {
+        return 0;
+    }
+    if (NULL != platform_uart) {
+        pikaFree(platform_uart, sizeof(hosal_uart_dev_t));
+    }
+    return 0;
+}
+
+extern volatile _BLIOT_irq g_irq;
+int _hosal_uart_irq_handler(void* p_arg) {
+    if (g_irq.uart_irq_trigger) {
+        return 0;
+    }
+    g_irq.uart_irq_arg = p_arg;
+    g_irq.uart_irq_trigger = 1;
+    return 0;
+}
+
+int pika_hal_platform_UART_ioctl_config(pika_dev* dev,
+                                        pika_hal_UART_config* cfg) {
+    hosal_uart_dev_t* platform_uart = (hosal_uart_dev_t*)dev->platform_data;
+    if (platform_uart != &uart_stdio) {
+        platform_uart->config.baud_rate = cfg->baudrate;
+        switch (cfg->data_bits) {
+            case PIKA_HAL_UART_DATA_BITS_5:
+                platform_uart->config.data_width = HOSAL_DATA_WIDTH_5BIT;
+                break;
+            case PIKA_HAL_UART_DATA_BITS_6:
+                platform_uart->config.data_width = HOSAL_DATA_WIDTH_6BIT;
+                break;
+            case PIKA_HAL_UART_DATA_BITS_7:
+                platform_uart->config.data_width = HOSAL_DATA_WIDTH_7BIT;
+                break;
+            case PIKA_HAL_UART_DATA_BITS_8:
+                platform_uart->config.data_width = HOSAL_DATA_WIDTH_8BIT;
+                break;
+            default:
+                platform_uart->config.data_width = HOSAL_DATA_WIDTH_8BIT;
+                break;
+        }
+        switch (cfg->parity) {
+            case PIKA_HAL_UART_PARITY_NONE:
+                platform_uart->config.parity = HOSAL_NO_PARITY;
+                break;
+            case PIKA_HAL_UART_PARITY_ODD:
+                platform_uart->config.parity = HOSAL_ODD_PARITY;
+                break;
+            case PIKA_HAL_UART_PARITY_EVEN:
+                platform_uart->config.parity = HOSAL_EVEN_PARITY;
+                break;
+            default:
+                platform_uart->config.parity = HOSAL_NO_PARITY;
+                break;
+        }
+        switch (cfg->stop_bits) {
+            case PIKA_HAL_UART_STOP_BITS_1:
+                platform_uart->config.stop_bits = HOSAL_STOP_BITS_1;
+                break;
+            case PIKA_HAL_UART_STOP_BITS_2:
+                platform_uart->config.stop_bits = HOSAL_STOP_BITS_2;
+                break;
+#if !defined(BL808)
+            case PIKA_HAL_UART_STOP_BITS_1_5:
+                platform_uart->config.stop_bits = HOSAL_STOP_BITS_1_5;
+                break;
+#endif
+            default:
+                platform_uart->config.stop_bits = HOSAL_STOP_BITS_1;
+                break;
+        }
+    }
+
+    /* support event callback */
+    if (NULL != cfg->event_callback &&
+        PIKA_HAL_EVENT_CALLBACK_ENA_ENABLE == cfg->event_callback_ena) {
+        hosal_uart_ioctl(platform_uart, HOSAL_UART_MODE_SET,
+                         (void*)HOSAL_UART_MODE_INT);
+        switch (cfg->event_callback_filter) {
+            /* Configure UART to interrupt mode */
+            case PIKA_HAL_UART_EVENT_SIGNAL_RX:
+#if PIKA_DEBUG_ENABLE
+                __platform_printf("Setting UART_RX callback\r\n");
+#endif
+                hosal_uart_callback_set(platform_uart, HOSAL_UART_RX_CALLBACK,
+                                        _hosal_uart_irq_handler, dev);
+                break;
+            case PIKA_HAL_UART_EVENT_SIGNAL_TX:
+#if PIKA_DEBUG_ENABLE
+                __platform_printf("Setting UART_TX callback\r\n");
+#endif
+                hosal_uart_callback_set(platform_uart, HOSAL_UART_TX_CALLBACK,
+                                        _hosal_uart_irq_handler, dev);
+                break;
+            default:
+                __platform_printf(
+                    "Error: not supported event callback filter %d\r\n",
+                    cfg->event_callback_filter);
+                return -1;
+        }
+        /* start irq task thread */
+        _BLIOT_irq_task_start();
+    }
+#if PIKA_DEBUG_ENABLE
+#endif
+    return 0;
+}
+
+int pika_hal_platform_UART_ioctl_enable(pika_dev* dev) {
+    if (!dev->is_enabled) {
+        hosal_uart_dev_t* platform_uart = (hosal_uart_dev_t*)dev->platform_data;
+        if (platform_uart == &uart_stdio) {
+            return 0;
+        }
+        hosal_uart_init(platform_uart);
+        return 0;
+    }
+    return -1;
+}
+
+int pika_hal_platform_UART_ioctl_disable(pika_dev* dev) {
+    if (dev->is_enabled) {
+        hosal_uart_dev_t* platform_uart = (hosal_uart_dev_t*)dev->platform_data;
+        if (platform_uart == &uart_stdio) {
+            return 0;
+        }
+        hosal_uart_finalize(platform_uart);
+        return 0;
+    }
+    return -1;
+}
+
+int pika_hal_platform_UART_write(pika_dev* dev, void* buf, size_t count) {
+    hosal_uart_dev_t* platform_uart = (hosal_uart_dev_t*)dev->platform_data;
+    return hosal_uart_send(platform_uart, buf, count);
+}
+
+int pika_hal_platform_UART_read(pika_dev* dev, void* buf, size_t count) {
+    hosal_uart_dev_t* platform_uart = (hosal_uart_dev_t*)dev->platform_data;
+    return hosal_uart_receive(platform_uart, buf, count);
+}

+ 52 - 0
package/BLIOT/pika_hal_BLIOT_irq_task.c

@@ -0,0 +1,52 @@
+#include "pika_hal_BLIOT_irq_task.h"
+#include <FreeRTOS.h>
+#include <task.h>
+
+volatile _BLIOT_irq g_irq = {0};
+
+static void _irq_task(void* pvParameters) {
+    while (1) {
+        vTaskDelay(10);
+        if (g_irq.gpio_irq_trigger) {
+            g_irq.gpio_irq_trigger = 0;
+            pika_dev* dev = (pika_dev*)g_irq.gpio_irq_arg;
+            pika_hal_GPIO_config* cfg = dev->ioctl_config;
+            cfg->event_callback(dev, cfg->event_callback_filter);
+        }
+        if (g_irq.uart_irq_trigger) {
+            g_irq.uart_irq_trigger = 0;
+            pika_dev* dev = (pika_dev*)g_irq.uart_irq_arg;
+            pika_hal_UART_config* cfg = dev->ioctl_config;
+            cfg->event_callback(dev, cfg->event_callback_filter);
+        }
+    }
+}
+
+static int _BLIOT_irq_init(volatile _BLIOT_irq* irq) {
+    irq->task_created = 0;
+    irq->gpio_irq_trigger = 0;
+    irq->gpio_irq_arg = NULL;
+    return 0;
+}
+
+int _BLIOT_irq_task_start() {
+    /* already started, skip */
+    if (1 == g_irq.task_created) {
+        return 0;
+    }
+    _BLIOT_irq_init(&g_irq);
+    g_irq.task_created = 1;
+#if PIKA_DEBUG_ENABLE
+    __platform_printf("Creating _irq_task\r\n");
+#endif
+    BaseType_t ret =
+        xTaskCreate(_irq_task, (char*)"_irq_task", 4096, NULL, 15, NULL);
+
+#if PIKA_DEBUG_ENABLE
+    if (pdPASS == ret) {
+        __platform_printf("Create _irq_task succeed.\r\n");
+        return 0;
+    }
+#endif
+    return -1;
+}

+ 12 - 0
package/BLIOT/pika_hal_BLIOT_irq_task.h

@@ -0,0 +1,12 @@
+#include "../PikaStdDevice/pika_hal.h"
+
+typedef struct {
+    uint8_t task_created;
+    uint8_t gpio_irq_trigger;
+    void* gpio_irq_arg;
+
+    uint8_t uart_irq_trigger;
+    void* uart_irq_arg;
+} _BLIOT_irq;
+
+int _BLIOT_irq_task_start();

+ 52 - 10
package/PikaStdDevice/PikaStdDevice.pyi

@@ -68,22 +68,33 @@ class GPIO(BaseDev):
     def read(self) -> int:
         """Read the pin value."""
 
-    @abstractmethod
+    SIGNAL_RISING: int
+    SIGNAL_FALLING: int
+    SIGNAL_ANY: int
+
+    def setCallBack(self, eventCallBack: any, filter: int):
+        """
+        Add a callback function to the pin.
+        Example: 
+        ``` python
+        def cb1(signal):
+            print("cb1", signal)
+        io.setCallBack(cb1, io.SIGNAL_RISING)
+        ```
+        """
+
+    def close(self): ...
+
     def platformHigh(self): ...
 
-    @abstractmethod
     def platformLow(self): ...
 
-    @abstractmethod
     def platformEnable(self): ...
 
-    @abstractmethod
     def platformDisable(self): ...
 
-    @abstractmethod
     def platformSetMode(self): ...
 
-    @abstractmethod
     def platformRead(self): ...
 
 
@@ -150,6 +161,8 @@ class ADC(BaseDev):
     def read(self) -> float:
         """Read the ADC value."""
 
+    def close(self): ...
+
     @abstractmethod
     def platformEnable(self): ...
 
@@ -175,10 +188,13 @@ class DAC(BaseDev):
     def disable(self):
         """Disable the DAC."""
 
-    def write(self, val:float):
+    def write(self, val: float):
         """write the DAC value."""
 
-class UART(BaseDev):
+    def close(self): ...
+
+
+class UART:
     def __init__(self): ...
 
     def setBaudRate(self, baudRate: int):
@@ -187,6 +203,14 @@ class UART(BaseDev):
     def setId(self, id: int):
         """Set the id of the UART."""
 
+    FLOW_CONTROL_NONE: int
+    FLOW_CONTROL_RTS: int
+    FLOW_CONTROL_CTS: int
+    FLOW_CONTROL_RTS_CTS: int
+
+    def setFlowControl(self, flowControl: int):
+        """Set the flow control of the UART."""
+
     def enable(self):
         """Enable the UART."""
 
@@ -205,6 +229,22 @@ class UART(BaseDev):
     def readBytes(self, length: int) -> bytes:
         """Read bytes from the UART."""
 
+    def close(self): ...
+
+    SIGNAL_RX: int
+    SIGNAL_TX: int
+
+    def setCallBack(self, eventCallBack: any, filter: int):
+        """
+        Add a callback function to the pin.
+        Example: 
+        ``` python
+        def cb1(signal):
+            print(uart.read(-1))
+        io.setCallBack(cb1, uart.SIGNAL_RX)
+        ```
+        """
+
     @abstractmethod
     def platformEnable(self): ...
 
@@ -316,6 +356,8 @@ class PWM(BaseDev):
     def getDuty(self) -> float:
         """Get the duty."""
 
+    def close(self): ...
+
     @abstractmethod
     def platformEnable(self): ...
 
@@ -436,7 +478,7 @@ class CAN(BaseDev):
     def readBytes(self, length: int) -> bytes:
         """Read bytes from the CAN."""
 
-    def addFilter(self, id: int, ide: int, rtr: int, mode: int, mask: int, hdr: int): 
+    def addFilter(self, id: int, ide: int, rtr: int, mode: int, mask: int, hdr: int):
         """Add a filter."""
 
     @abstractmethod
@@ -460,7 +502,7 @@ class CAN(BaseDev):
 
 class BaseDev:
     @PIKA_C_MACRO_IF("PIKA_EVENT_ENABLE")
-    def addEventCallBack(self, eventCallback: any): 
+    def addEventCallBack(self, eventCallback: any):
         """ Add an event callback. """
 
     @abstractmethod

+ 6 - 2
package/PikaStdDevice/PikaStdDevice_ADC.c

@@ -1,6 +1,5 @@
 #include "PikaStdDevice_ADC.h"
-#include "BaseObj.h"
-#include "pika_hal.h"
+#include "PikaStdDevice_common.h"
 
 void PikaStdDevice_ADC_enable(PikaObj* self) {
     obj_runNativeMethod(self, "platformEnable", NULL);
@@ -67,3 +66,8 @@ void PikaStdDevice_ADC_platformRead(PikaObj* self) {
     pika_float val = (pika_float)val_i / (pika_float)cfg->max * cfg->vref;
     val = val_i * obj_setFloat(self, "val", val);
 }
+
+void PikaStdDevice_ADC_close(PikaObj* self) {
+    pika_dev* dev = _get_dev(self);
+    pika_hal_close(dev);
+}

+ 3 - 6
package/PikaStdDevice/PikaStdDevice_BaseDev.c

@@ -1,8 +1,5 @@
 #include "PikaStdDevice_BaseDev.h"
-#include "BaseObj.h"
-#include "PikaObj.h"
-#include "dataStrs.h"
-#include "pika_hal.h"
+#include "PikaStdDevice_common.h"
 
 #if !PIKASCRIPT_VERSION_REQUIRE_MINIMUN(1, 10, 4)
 #error "This library requires PikaScript version 1.10.4 or higher"
@@ -15,7 +12,7 @@ void PikaStdDevice_BaseDev_addEventCallBack(PikaObj* self, Arg* eventCallBack) {
     obj_setArg(self, "eventCallBack", eventCallBack);
     /* init event_listener for the first time */
     if (NULL == g_pika_device_event_listener) {
-        pks_eventLisener_init(&g_pika_device_event_listener);
+        pks_eventListener_init(&g_pika_device_event_listener);
     }
     if (PIKA_RES_OK != obj_runNativeMethod(self, "platformGetEventId", NULL)) {
         obj_setErrorCode(self, 1);
@@ -23,7 +20,7 @@ void PikaStdDevice_BaseDev_addEventCallBack(PikaObj* self, Arg* eventCallBack) {
                           "platformGetEventId");
     }
     uint32_t eventId = obj_getInt(self, "eventId");
-    pks_eventLicener_registEvent(g_pika_device_event_listener, eventId, self);
+    pks_eventListener_registEvent(g_pika_device_event_listener, eventId, self);
 #else
     obj_setErrorCode(self, 1);
     obj_setSysOut(self, "[error] PIKA_EVENT_ENABLE is disabled.");

+ 1 - 1
package/PikaStdDevice/PikaStdDevice_CAN.c

@@ -1,5 +1,5 @@
 #include "PikaStdDevice_CAN.h"
-#include "pika_hal.h"
+#include "PikaStdDevice_common.h"
 
 void PikaStdDevice_CAN___init__(PikaObj* self) {}
 

+ 6 - 2
package/PikaStdDevice/PikaStdDevice_DAC.c

@@ -1,6 +1,5 @@
 #include "PikaStdDevice_DAC.h"
-#include "BaseObj.h"
-#include "pika_hal.h"
+#include "PikaStdDevice_common.h"
 
 static pika_dev* _get_dev(PikaObj* self) {
     pika_dev* dev = obj_getPtr(self, "pika_dev");
@@ -46,3 +45,8 @@ void PikaStdDevice_DAC_write(PikaObj* self, pika_float val) {
     uint32_t val_i = (val / cfg->vref) * cfg->max;
     pika_hal_write(dev, &val_i, sizeof val_i);
 }
+
+void PikaStdDevice_DAC_close(PikaObj* self) {
+    pika_dev* dev = _get_dev(self);
+    pika_hal_close(dev);
+}

+ 27 - 2
package/PikaStdDevice/PikaStdDevice_GPIO.c

@@ -1,6 +1,5 @@
 #include "PikaStdDevice_GPIO.h"
-#include "BaseObj.h"
-#include "pika_hal.h"
+#include "PikaStdDevice_common.h"
 
 void PikaStdDevice_GPIO_init(PikaObj* self) {
     obj_setInt(self, "isEnable", 0);
@@ -22,6 +21,9 @@ void PikaStdDevice_GPIO_setId(PikaObj* self, int id) {
 
 void PikaStdDevice_GPIO___init__(PikaObj* self) {
     PikaStdDevice_GPIO_init(self);
+    obj_setInt(self, "SIGNAL_RISING", PIKA_HAL_GPIO_EVENT_SIGNAL_RISING);
+    obj_setInt(self, "SIGNAL_FALLING", PIKA_HAL_GPIO_EVENT_SIGNAL_FALLING);
+    obj_setInt(self, "SIGNAL_ANY", PIKA_HAL_GPIO_EVENT_SIGNAL_ANY);
 }
 
 void PikaStdDevice_GPIO_disable(PikaObj* self) {
@@ -145,3 +147,26 @@ void PikaStdDevice_GPIO_platformRead(PikaObj* self) {
     pika_hal_read(dev, &val, sizeof(val));
     obj_setInt(self, "readBuff", val);
 }
+
+void PikaStdDevice_GPIO_setCallBack(PikaObj* self,
+                                    Arg* eventCallback,
+                                    int filter) {
+    pika_dev* dev = _get_dev(self);
+#if PIKA_EVENT_ENABLE
+    _PikaStdDevice_setCallBack(self, eventCallback, (uintptr_t)dev);
+    /* regist event to pika_hal */
+    pika_hal_GPIO_config cfg_cb = {0};
+    cfg_cb.event_callback = (void*)_PikaStdDevice_event_handler;
+    cfg_cb.event_callback_filter = filter;
+    cfg_cb.event_callback_ena = PIKA_HAL_EVENT_CALLBACK_ENA_ENABLE;
+    pika_hal_ioctl(dev, PIKA_HAL_IOCTL_CONFIG, &cfg_cb);
+#else
+    obj_setErrorCode(self, 1);
+    obj_setSysOut(self, "[error] PIKA_EVENT_ENABLE is disabled.");
+#endif
+}
+
+void PikaStdDevice_GPIO_close(PikaObj *self){
+    pika_dev* dev = _get_dev(self);
+    pika_hal_close(dev);
+}

+ 1 - 3
package/PikaStdDevice/PikaStdDevice_IIC.c

@@ -1,7 +1,5 @@
 #include "PikaStdDevice_IIC.h"
-#include "BaseObj.h"
-#include "PikaObj.h"
-#include "pika_hal.h"
+#include "PikaStdDevice_common.h"
 
 void PikaStdDevice_IIC_init(PikaObj* self) {
     obj_setInt(self, "deviceAddr", 0);

+ 6 - 2
package/PikaStdDevice/PikaStdDevice_PWM.c

@@ -1,6 +1,5 @@
 #include "PikaStdDevice_PWM.h"
-#include "BaseObj.h"
-#include "pika_hal.h"
+#include "PikaStdDevice_common.h"
 
 void PikaStdDevice_PWM_init(PikaObj* self) {
     obj_setStr(self, "pin", "none");
@@ -106,3 +105,8 @@ void PikaStdDevice_PWM_platformDisable(PikaObj* self) {
     pika_dev* dev = _get_dev(self);
     pika_hal_ioctl(dev, PIKA_HAL_IOCTL_DISABLE);
 }
+
+void PikaStdDevice_PWM_close(PikaObj* self) {
+    pika_dev* dev = _get_dev(self);
+    pika_hal_close(dev);
+}

+ 1 - 3
package/PikaStdDevice/PikaStdDevice_SPI.c

@@ -1,7 +1,5 @@
 #include "PikaStdDevice_SPI.h"
-#include "BaseObj.h"
-#include "PikaObj.h"
-#include "pika_hal.h"
+#include "PikaStdDevice_common.h"
 
 void PikaStdDevice_SPI___init__(PikaObj* self) {
     obj_setInt(self, "baudRate", 1000);

+ 4 - 6
package/PikaStdDevice/PikaStdDevice_Time.c

@@ -1,6 +1,5 @@
 #include "PikaStdDevice_Time.h"
-#include "BaseObj.h"
-#include "pika_hal.h"
+#include "PikaStdDevice_common.h"
 #if defined(__linux)
 #include <unistd.h>
 #endif
@@ -14,7 +13,7 @@ void PikaStdDevice_Time_sleep_ms(PikaObj* self, int ms) {
 #elif defined(_WIN32)
     Sleep(ms);
 #else
-    ABSTRACT_METHOD_NEED_OVERRIDE_ERROR();
+    __platform_sleep_ms(ms);
 #endif
 }
 void PikaStdDevice_Time_sleep_s(PikaObj* self, int s) {
@@ -23,13 +22,12 @@ void PikaStdDevice_Time_sleep_s(PikaObj* self, int s) {
 #elif defined(_WIN32)
     Sleep(s * 1000);
 #else
-    ABSTRACT_METHOD_NEED_OVERRIDE_ERROR();
+    __platform_sleep_s(s);
 #endif
 }
 
 void PikaStdDevice_Time_platformGetTick(PikaObj* self) {
-    obj_setErrorCode(self, 1);
-    obj_setSysOut(self, "[error] platformGetTick() need to be override.");
+    obj_setInt(self, "tick", __platform_getTick());
 }
 
 /*

+ 97 - 8
package/PikaStdDevice/PikaStdDevice_UART.c

@@ -1,6 +1,5 @@
 #include "PikaStdDevice_UART.h"
-#include "BaseObj.h"
-#include "pika_hal.h"
+#include "PikaStdDevice_common.h"
 
 void PikaStdDevice_UART_enable(PikaObj* self) {
     obj_runNativeMethod(self, "platformEnable", NULL);
@@ -11,9 +10,20 @@ void PikaStdDevice_UART_disable(PikaObj* self) {
 }
 
 void PikaStdDevice_UART_init(PikaObj* self) {
+    /* const */
+    obj_setInt(self, "FLOW_CONTROL_NONE", PIKA_HAL_UART_FLOW_CONTROL_NONE);
+    obj_setInt(self, "FLOW_CONTROL_RTS", PIKA_HAL_UART_FLOW_CONTROL_RTS);
+    obj_setInt(self, "FLOW_CONTROL_CTS", PIKA_HAL_UART_FLOW_CONTROL_CTS);
+    obj_setInt(self, "FLOW_CONTROL_RTS_CTS",
+               PIKA_HAL_UART_FLOW_CONTROL_RTS_CTS);
+
+    obj_setInt(self, "SIGNAL_RX", PIKA_HAL_UART_EVENT_SIGNAL_RX);
+    obj_setInt(self, "SIGNAL_TX", PIKA_HAL_UART_EVENT_SIGNAL_TX);
+
     obj_setInt(self, "baudRate", 115200);
     obj_setInt(self, "id", 1);
     obj_setStr(self, "readBuff", "");
+    obj_setInt(self, "flowControl", PIKA_HAL_UART_FLOW_CONTROL_NONE);
 }
 
 void PikaStdDevice_UART___init__(PikaObj* self) {
@@ -35,9 +45,15 @@ Arg* PikaStdDevice_UART_readBytes(PikaObj* self, int length) {
 void PikaStdDevice_UART_setBaudRate(PikaObj* self, int baudRate) {
     obj_setInt(self, "baudRate", baudRate);
 }
+
+void PikaStdDevice_UART_setFlowControl(PikaObj* self, int flowControl) {
+    obj_setInt(self, "flowControl", flowControl);
+}
+
 void PikaStdDevice_UART_setId(PikaObj* self, int id) {
     obj_setInt(self, "id", id);
 }
+
 void PikaStdDevice_UART_write(PikaObj* self, char* data) {
     obj_setStr(self, "writeData", data);
     obj_runNativeMethod(self, "platformWrite", NULL);
@@ -48,24 +64,97 @@ void PikaStdDevice_UART_writeBytes(PikaObj* self, uint8_t* data, int length) {
     obj_runNativeMethod(self, "platformWriteBytes", NULL);
 }
 
+static pika_dev* _get_dev(PikaObj* self) {
+    pika_dev* dev = obj_getPtr(self, "pika_dev");
+    if (NULL != dev) {
+        return dev;
+    }
+    int id = obj_getInt(self, "id");
+    char id_str[32] = {0};
+    sprintf(id_str, "UART%d", id);
+    dev = pika_hal_open(PIKA_HAL_UART, id_str);
+    if (NULL == dev) {
+        __platform_printf("Error: open UART '%s' failed.\r\n", id_str);
+    }
+    obj_setPtr(self, "pika_dev", dev);
+    return dev;
+}
+
 void PikaStdDevice_UART_platformEnable(PikaObj* self) {
-    ABSTRACT_METHOD_NEED_OVERRIDE_ERROR();
+    pika_dev* dev = _get_dev(self);
+    if (NULL == dev) {
+        __platform_printf("Error: open UART '%d' failed.\r\n",
+                          obj_getInt(self, "id"));
+        return;
+    }
+    pika_hal_UART_config cfg = {0};
+    cfg.baudrate = obj_getInt(self, "baudRate");
+    cfg.flow_control = obj_getInt(self, "flowControl");
+    pika_hal_ioctl(dev, PIKA_HAL_IOCTL_CONFIG, &cfg);
+    pika_hal_ioctl(dev, PIKA_HAL_IOCTL_ENABLE);
 }
+
 void PikaStdDevice_UART_platformRead(PikaObj* self) {
-    ABSTRACT_METHOD_NEED_OVERRIDE_ERROR();
+    int len = obj_getInt(self, "length");
+    obj_setBytes(self, "_readData", NULL, len + 1);
+    char* buff = (char*)obj_getBytes(self, "_readData");
+    pika_dev* dev = _get_dev(self);
+    int len_get = pika_hal_read(dev, buff, len);
+    buff[len_get] = 0;
+    obj_setStr(self, "readData", buff);
 }
+
 void PikaStdDevice_UART_platformWrite(PikaObj* self) {
-    ABSTRACT_METHOD_NEED_OVERRIDE_ERROR();
+    char* data = obj_getStr(self, "writeData");
+    pika_dev* dev = _get_dev(self);
+    pika_hal_write(dev, data, strlen(data));
 }
 
 void PikaStdDevice_UART_platformDisable(PikaObj* self) {
-    ABSTRACT_METHOD_NEED_OVERRIDE_ERROR();
+    pika_dev* dev = _get_dev(self);
+    if (NULL == dev) {
+        __platform_printf("Error: open UART '%d' failed.\r\n",
+                          obj_getInt(self, "id"));
+        return;
+    }
+    pika_hal_ioctl(dev, PIKA_HAL_IOCTL_DISABLE);
 }
 
 void PikaStdDevice_UART_platformReadBytes(PikaObj* self) {
-    ABSTRACT_METHOD_NEED_OVERRIDE_ERROR();
+    int len = obj_getInt(self, "length");
+    obj_setBytes(self, "_readData", NULL, len + 1);
+    uint8_t* buff = obj_getBytes(self, "_readData");
+    pika_dev* dev = _get_dev(self);
+    pika_hal_read(dev, buff, len);
+    obj_setBytes(self, "readData", buff, len);
 }
 
 void PikaStdDevice_UART_platformWriteBytes(PikaObj* self) {
-    ABSTRACT_METHOD_NEED_OVERRIDE_ERROR();
+    uint8_t* data = obj_getBytes(self, "writeData");
+    int len = obj_getBytesSize(self, "writeData");
+    pika_dev* dev = _get_dev(self);
+    pika_hal_write(dev, data, len);
+}
+
+void PikaStdDevice_UART_setCallBack(PikaObj* self,
+                                    Arg* eventCallBack,
+                                    int filter) {
+    pika_dev* dev = _get_dev(self);
+#if PIKA_EVENT_ENABLE
+    _PikaStdDevice_setCallBack(self, eventCallBack, (uintptr_t)dev);
+    /* regist event to pika_hal */
+    pika_hal_UART_config cfg_cb = {0};
+    cfg_cb.event_callback = (void*)_PikaStdDevice_event_handler;
+    cfg_cb.event_callback_filter = filter;
+    cfg_cb.event_callback_ena = PIKA_HAL_EVENT_CALLBACK_ENA_ENABLE;
+    pika_hal_ioctl(dev, PIKA_HAL_IOCTL_CONFIG, &cfg_cb);
+#else
+    obj_setErrorCode(self, 1);
+    obj_setSysOut(self, "[error] PIKA_EVENT_ENABLE is disabled.");
+#endif
+}
+
+void PikaStdDevice_UART_close(PikaObj* self) {
+    pika_dev* dev = _get_dev(self);
+    pika_hal_close(dev);
 }

+ 19 - 0
package/PikaStdDevice/PikaStdDevice_common.c

@@ -0,0 +1,19 @@
+#include "PikaStdDevice_common.h"
+
+extern PikaEventListener* g_pika_device_event_listener;
+void _PikaStdDevice_event_handler(pika_dev* dev, int signal) {
+    pks_eventListener_sendSignal(g_pika_device_event_listener, (uintptr_t)dev,
+                                signal);
+}
+
+void _PikaStdDevice_setCallBack(PikaObj* self,
+                                Arg* eventCallback,
+                                uint32_t eventId) {
+    obj_setArg(self, "eventCallBack", eventCallback);
+    /* init event_listener for the first time */
+    if (NULL == g_pika_device_event_listener) {
+        pks_eventListener_init(&g_pika_device_event_listener);
+    }
+    /* regist event to event listener */
+    pks_eventListener_registEvent(g_pika_device_event_listener, eventId, self);
+}

+ 12 - 0
package/PikaStdDevice/PikaStdDevice_common.h

@@ -0,0 +1,12 @@
+#ifndef _PIKA_STDDEVICE_COMMON_H
+#define _PIKA_STDDEVICE_COMMON_H
+#include "PikaObj.h"
+#include "PikaVM.h"
+#include "pika_hal.h"
+void _PikaStdDevice_setCallBack(PikaObj* self,
+                                Arg* eventCallback,
+                                uint32_t eventId);
+
+void _PikaStdDevice_event_handler(pika_dev* dev, int signal);
+
+#endif

+ 31 - 6
package/PikaStdDevice/pika_hal.c

@@ -53,6 +53,7 @@ __exit:
     __platform_printf("Error: dev_open failed.\r\n");
     if (dev->ioctl_config) {
         pikaFree(dev->ioctl_config, _pika_hal_dev_config_size(dev_type));
+        dev->ioctl_config = NULL;
     }
     if (dev) {
         pikaFree(dev, sizeof(pika_dev));
@@ -71,11 +72,12 @@ int pika_hal_close(pika_dev* dev) {
     }
     ret = impl->close(dev);
 __exit:
-    if (NULL != dev) {
-        pikaFree(dev, sizeof(pika_dev));
-    }
     if (NULL != dev->ioctl_config) {
         pikaFree(dev->ioctl_config, _pika_hal_dev_config_size(dev->type));
+        dev->ioctl_config = NULL;
+    }
+    if (NULL != dev) {
+        pikaFree(dev, sizeof(pika_dev));
     }
     return ret;
 }
@@ -181,8 +183,11 @@ int pika_hal_GPIO_ioctl_merge_config(pika_hal_GPIO_config* dst,
     // printf("after merge: dst->dir=%d, src->dir=%d\r\n", dst->dir, src->dir);
     _IOCTL_CONFIG_USE_DEFAULT(pull, PIKA_HAL_GPIO_PULL_NONE);
     _IOCTL_CONFIG_USE_DEFAULT(speed, PIKA_HAL_GPIO_SPEED_10M);
-    _IOCTL_CONFIG_USE_DEFAULT(event_callback_rising, NULL);
-    _IOCTL_CONFIG_USE_DEFAULT(event_callback_falling, NULL);
+    _IOCTL_CONFIG_USE_DEFAULT(event_callback, NULL);
+    _IOCTL_CONFIG_USE_DEFAULT(event_callback_filter,
+                              PIKA_HAL_GPIO_EVENT_SIGNAL_RISING);
+    _IOCTL_CONFIG_USE_DEFAULT(event_callback_ena,
+                              PIKA_HAL_EVENT_CALLBACK_ENA_ENABLE);
     return 0;
 }
 
@@ -192,7 +197,12 @@ int pika_hal_UART_ioctl_merge_config(pika_hal_UART_config* dst,
     _IOCTL_CONFIG_USE_DEFAULT(data_bits, PIKA_HAL_UART_DATA_BITS_8);
     _IOCTL_CONFIG_USE_DEFAULT(stop_bits, PIKA_HAL_UART_STOP_BITS_1);
     _IOCTL_CONFIG_USE_DEFAULT(parity, PIKA_HAL_UART_PARITY_NONE);
-    _IOCTL_CONFIG_USE_DEFAULT(event_callback_rx, NULL);
+    _IOCTL_CONFIG_USE_DEFAULT(flow_control, PIKA_HAL_UART_FLOW_CONTROL_NONE);
+    _IOCTL_CONFIG_USE_DEFAULT(event_callback, NULL);
+    _IOCTL_CONFIG_USE_DEFAULT(event_callback_filter,
+                              PIKA_HAL_UART_EVENT_SIGNAL_RX);
+    _IOCTL_CONFIG_USE_DEFAULT(event_callback_ena,
+                              PIKA_HAL_EVENT_CALLBACK_ENA_ENABLE);
     return 0;
 }
 
@@ -207,6 +217,21 @@ int pika_hal_SPI_ioctl_merge_config(pika_hal_SPI_config* dst,
     return 0;
 }
 
+int pika_hal_SOFT_SPI_ioctl_merge_config(pika_hal_SOFT_SPI_config* dst,
+                                    pika_hal_SOFT_SPI_config* src) {
+    _IOCTL_CONFIG_USE_DEFAULT(lsb_or_msb, PIKA_HAL_SPI_MSB);
+    _IOCTL_CONFIG_USE_DEFAULT(master_or_slave, PIKA_HAL_SPI_MASTER);
+    _IOCTL_CONFIG_USE_DEFAULT(mode, PIKA_HAL_SPI_MODE_0);
+    _IOCTL_CONFIG_USE_DEFAULT(data_width, PIKA_HAL_SPI_DATA_WIDTH_8);
+    _IOCTL_CONFIG_USE_DEFAULT(speed, PIKA_HAL_SPI_SPEED_2M);
+    _IOCTL_CONFIG_USE_DEFAULT(timeout, PIKA_HAL_SPI_TIMEOUT_1000MS);
+    _IOCTL_CONFIG_USE_DEFAULT(CS, NULL);
+    _IOCTL_CONFIG_USE_DEFAULT(SCK, NULL);
+    _IOCTL_CONFIG_USE_DEFAULT(MOSI, NULL);
+    _IOCTL_CONFIG_USE_DEFAULT(MISO, NULL);
+    return 0;
+}
+
 int pika_hal_IIC_ioctl_merge_config(pika_hal_IIC_config* dst,
                                     pika_hal_IIC_config* src) {
     _IOCTL_CONFIG_USE_DEFAULT(address_width, PIKA_HAL_IIC_ADDRESS_WIDTH_7BIT);

+ 49 - 3
package/PikaStdDevice/pika_hal.h

@@ -58,12 +58,26 @@ typedef enum {
     PIKA_HAL_GPIO_SPEED_100M = 100000000,
 } PIKA_HAL_GPIO_SPEED;
 
+typedef enum {
+    _PIKA_HAL_EVENT_CALLBACK_ENA_UNUSED = 0,
+    PIKA_HAL_EVENT_CALLBACK_ENA_ENABLE,
+    PIKA_HAL_EVENT_CALLBACK_ENA_DISABLE,
+} PIKA_HAL_EVENT_CALLBACK_ENA;
+
+typedef enum {
+    _PIKA_HAL_GPIO_EVENT_SIGNAL_UNUSED = 0,
+    PIKA_HAL_GPIO_EVENT_SIGNAL_RISING,
+    PIKA_HAL_GPIO_EVENT_SIGNAL_FALLING,
+    PIKA_HAL_GPIO_EVENT_SIGNAL_ANY,
+} PIKA_HAL_GPIO_EVENT_SIGNAL;
+
 typedef struct {
     PIKA_HAL_GPIO_DIR dir;
     PIKA_HAL_GPIO_PULL pull;
     PIKA_HAL_GPIO_SPEED speed;
-    void (*event_callback_rising)(pika_dev* dev);
-    void (*event_callback_falling)(pika_dev* dev);
+    void (*event_callback)(pika_dev* dev, PIKA_HAL_GPIO_EVENT_SIGNAL signal);
+    PIKA_HAL_GPIO_EVENT_SIGNAL event_callback_filter;
+    PIKA_HAL_EVENT_CALLBACK_ENA event_callback_ena;
 } pika_hal_GPIO_config;
 
 typedef enum {
@@ -89,6 +103,7 @@ typedef enum {
     _PIKA_HAL_UART_STOP_BITS_UNUSED = 0,
     PIKA_HAL_UART_STOP_BITS_1 = 1,
     PIKA_HAL_UART_STOP_BITS_2 = 2,
+    PIKA_HAL_UART_STOP_BITS_1_5 = 3,
 } PIKA_HAL_UART_STOP_BITS;
 
 typedef enum {
@@ -98,12 +113,30 @@ typedef enum {
     PIKA_HAL_UART_PARITY_EVEN,
 } PIKA_HAL_UART_PARITY;
 
+typedef enum {
+    _PIKA_HAL_UART_EVENT_SIGNAL_UNUSED = 0,
+    PIKA_HAL_UART_EVENT_SIGNAL_RX,
+    PIKA_HAL_UART_EVENT_SIGNAL_TX,
+    PIKA_HAL_UART_EVENT_SIGNAL_ANY,
+} PIKA_HAL_UART_EVENT_SIGNAL;
+
+typedef enum {
+    _PIKA_HAL_UART_FLOW_CONTROL_UNUSED = 0,
+    PIKA_HAL_UART_FLOW_CONTROL_NONE,
+    PIKA_HAL_UART_FLOW_CONTROL_RTS,
+    PIKA_HAL_UART_FLOW_CONTROL_CTS,
+    PIKA_HAL_UART_FLOW_CONTROL_RTS_CTS,
+} PIKA_HAL_UART_FLOW_CONTROL;
+
 typedef struct {
     PIKA_HAL_UART_BAUDRATE baudrate;
     PIKA_HAL_UART_DATA_BITS data_bits;
     PIKA_HAL_UART_STOP_BITS stop_bits;
     PIKA_HAL_UART_PARITY parity;
-    void (*event_callback_rx)(pika_dev* dev);
+    PIKA_HAL_UART_FLOW_CONTROL flow_control;
+    void (*event_callback)(pika_dev* dev, PIKA_HAL_UART_EVENT_SIGNAL signal);
+    PIKA_HAL_UART_EVENT_SIGNAL event_callback_filter;
+    PIKA_HAL_EVENT_CALLBACK_ENA event_callback_ena;
 } pika_hal_UART_config;
 
 typedef uint32_t PIKA_HAL_IIC_SLAVE_ADDR;
@@ -227,6 +260,19 @@ typedef struct {
     PIKA_HAL_SPI_TIMEOUT timeout;
 } pika_hal_SPI_config;
 
+typedef struct {
+    PIKA_HAL_SPI_LSB_OR_MSB lsb_or_msb;
+    PIKA_HAL_SPI_MASTER_OR_SLAVE master_or_slave;
+    PIKA_HAL_SPI_MODE mode;
+    PIKA_HAL_SPI_DATA_WIDTH data_width;
+    PIKA_HAL_SPI_SPEED speed;
+    PIKA_HAL_SPI_TIMEOUT timeout;
+    pika_dev* CS;
+    pika_dev* SCK;
+    pika_dev* MOSI;
+    pika_dev* MISO;
+} pika_hal_SOFT_SPI_config;
+
 typedef enum {
     _PIKA_HAL_ADC_RESOLUTION_UNUSED = 0,
     PIKA_HAL_ADC_RESOLUTION_8 = 8,

+ 155 - 0
package/PikaStdDevice/pika_hal_SOFT_SPI.c

@@ -0,0 +1,155 @@
+#include "../PikaStdDevice/pika_hal.h"
+
+static int _GPIO_write(pika_dev* dev, uint32_t val) {
+    return pika_hal_write(dev, &val, sizeof(val));
+}
+
+static uint32_t _GPIO_read(pika_dev* dev) {
+    uint32_t val = 0;
+    pika_hal_read(dev, &val, sizeof(val));
+    return val;
+}
+
+int pika_hal_platform_SOFT_SPI_open(pika_dev* dev, char* name) {
+    return 0;
+}
+
+int pika_hal_platform_SOFT_SPI_close(pika_dev* dev) {
+    pika_hal_SOFT_SPI_config* cfg =
+        (pika_hal_SOFT_SPI_config*)dev->ioctl_config;
+    if (cfg->CS != NULL) {
+        pika_hal_close(cfg->CS);
+    }
+    if (cfg->SCK != NULL) {
+        pika_hal_close(cfg->SCK);
+    }
+    if (cfg->MOSI != NULL) {
+        pika_hal_close(cfg->MOSI);
+    }
+    if (cfg->MISO != NULL) {
+        pika_hal_close(cfg->MISO);
+    }
+    return 0;
+}
+
+int pika_hal_platform_SOFT_SPI_ioctl_config(pika_dev* dev,
+                                            pika_hal_SOFT_SPI_config* cfg) {
+    if (cfg->SCK == NULL || cfg->MOSI == NULL) {
+        __platform_printf(
+            "Error: SOFT SPI config error, CS, SCK, MOSI, MISO must be "
+            "set\r\n");
+        return -1;
+    }
+    return 0;
+}
+
+int pika_hal_platform_SOFT_SPI_ioctl_enable(pika_dev* dev) {
+    pika_hal_SOFT_SPI_config* cfg =
+        (pika_hal_SOFT_SPI_config*)dev->ioctl_config;
+    if (cfg->SCK == NULL || cfg->MOSI == NULL) {
+        __platform_printf(
+            "Error: SOFT SPI config error, CS, SCK, MOSI, MISO must be "
+            "set\r\n");
+        return -1;
+    }
+    pika_hal_GPIO_config cfg_CS = {0};
+    pika_hal_GPIO_config cfg_SCK = {0};
+    pika_hal_GPIO_config cfg_MOSI = {0};
+    pika_hal_GPIO_config cfg_MISO = {0};
+    cfg_CS.dir = PIKA_HAL_GPIO_DIR_OUT;
+    cfg_SCK.dir = PIKA_HAL_GPIO_DIR_OUT;
+    cfg_MOSI.dir = PIKA_HAL_GPIO_DIR_OUT;
+    cfg_MISO.dir = PIKA_HAL_GPIO_DIR_IN;
+
+    if (NULL != cfg->CS) {
+        pika_hal_ioctl(cfg->CS, PIKA_HAL_IOCTL_CONFIG, &cfg_CS);
+    }
+    pika_hal_ioctl(cfg->SCK, PIKA_HAL_IOCTL_CONFIG, &cfg_SCK);
+    pika_hal_ioctl(cfg->MOSI, PIKA_HAL_IOCTL_CONFIG, &cfg_MOSI);
+    if (NULL != cfg->MISO) {
+        pika_hal_ioctl(cfg->MISO, PIKA_HAL_IOCTL_CONFIG, &cfg_MISO);
+    }
+
+    if (NULL != cfg->CS) {
+        pika_hal_ioctl(cfg->CS, PIKA_HAL_IOCTL_ENABLE);
+    }
+    pika_hal_ioctl(cfg->SCK, PIKA_HAL_IOCTL_ENABLE);
+    pika_hal_ioctl(cfg->MOSI, PIKA_HAL_IOCTL_ENABLE);
+    if (NULL != cfg->MISO) {
+        pika_hal_ioctl(cfg->MISO, PIKA_HAL_IOCTL_ENABLE);
+    }
+
+    if (NULL != cfg->CS) {
+        _GPIO_write(cfg->CS, 1);
+    }
+    _GPIO_write(cfg->SCK, 1);
+    _GPIO_write(cfg->MOSI, 1);
+    return 0;
+}
+
+int pika_hal_platform_SOFT_SPI_ioctl_disable(pika_dev* dev) {
+    pika_hal_SOFT_SPI_config* cfg =
+        (pika_hal_SOFT_SPI_config*)dev->ioctl_config;
+    if (NULL != cfg->CS) {
+        pika_hal_ioctl(cfg->CS, PIKA_HAL_IOCTL_DISABLE);
+    }
+    pika_hal_ioctl(cfg->SCK, PIKA_HAL_IOCTL_DISABLE);
+    pika_hal_ioctl(cfg->MOSI, PIKA_HAL_IOCTL_DISABLE);
+    if (NULL != cfg->MISO) {
+        pika_hal_ioctl(cfg->MISO, PIKA_HAL_IOCTL_DISABLE);
+    }
+    return 0;
+}
+
+static inline int SPIv_WriteData(pika_hal_SOFT_SPI_config* cfg, uint8_t Data) {
+    unsigned char i = 0;
+    for (i = 8; i > 0; i--) {
+        if (Data & 0x80)
+            _GPIO_write(cfg->MOSI, 1);
+        else
+            _GPIO_write(cfg->MOSI, 0);
+        _GPIO_write(cfg->SCK, 0);
+        _GPIO_write(cfg->SCK, 1);
+        Data <<= 1;
+    }
+    return 0;
+}
+
+int pika_hal_platform_SOFT_SPI_write(pika_dev* dev, void* buf, size_t count) {
+    pika_hal_SOFT_SPI_config* cfg =
+        (pika_hal_SOFT_SPI_config*)dev->ioctl_config;
+    uint8_t* data = (uint8_t*)buf;
+    if (NULL != cfg->CS) {
+        _GPIO_write(cfg->CS, 0);
+    }
+    for (int i = 0; i < count; i++) {
+        SPIv_WriteData(cfg, data[i]);
+    }
+    if (NULL != cfg->CS) {
+        _GPIO_write(cfg->CS, 1);
+    }
+    return count;
+}
+
+int pika_hal_platform_SOFT_SPI_read(pika_dev* dev, void* buf, size_t count) {
+    pika_hal_SOFT_SPI_config* cfg =
+        (pika_hal_SOFT_SPI_config*)dev->ioctl_config;
+    if (NULL == cfg->MISO) {
+        __platform_printf("Error: SOFT SPI config error, MISO must be set\r\n");
+        return -1;
+    }
+    uint8_t* data = (uint8_t*)buf;
+    if (NULL != cfg->CS) {
+        _GPIO_write(cfg->CS, 0);
+    }
+    for (int i = 0; i < count; i++) {
+        data[i] = 0;
+        for (int j = 0; j < 8; j++) {
+            _GPIO_write(cfg->SCK, 0);
+            _GPIO_write(cfg->SCK, 1);
+            data[i] |= (_GPIO_read(cfg->MISO) << (7 - j));
+        }
+    }
+    _GPIO_write(cfg->CS, 1);
+    return count;
+}

+ 1 - 0
package/PikaStdDevice/pika_hal_table.h

@@ -9,5 +9,6 @@ pika_hal_table_add(SPI)
 pika_hal_table_add(ADC)
 pika_hal_table_add(DAC)
 pika_hal_table_add(PWM)
+pika_hal_table_add(SOFT_SPI)
 
     /* clang-format on */

+ 8 - 8
package/PikaStdLib/PikaStdData_Dict.c

@@ -40,7 +40,7 @@ Arg* PikaStdData_Dict___iter__(PikaObj* self) {
 Arg* PikaStdData_Dict___next__(PikaObj* self) {
     int __iter_i = args_getInt(self->list, "__iter_i");
     PikaDict* keys = obj_getPtr(self, "_keys");
-    Arg* res = arg_copy(args_getArgByidex(&keys->super, __iter_i));
+    Arg* res = arg_copy(args_getArgByIndex(&keys->super, __iter_i));
     if (NULL == res) {
         return arg_newNull();
     }
@@ -91,7 +91,7 @@ Arg* PikaStdData_dict_keys___next__(PikaObj* self) {
     int __iter_i = args_getInt(self->list, "__iter_i");
     PikaObj* dictptr = obj_getPtr(self, "dictptr");
     PikaDict* keys = obj_getPtr(dictptr, "_keys");
-    Arg* res = arg_copy(args_getArgByidex(&keys->super, __iter_i));
+    Arg* res = arg_copy(args_getArgByIndex(&keys->super, __iter_i));
     if (NULL == res) {
         return arg_newNull();
     }
@@ -107,7 +107,7 @@ char* PikaStdData_dict_keys___str__(PikaObj* self) {
 
     int i = 0;
     while (PIKA_TRUE) {
-        Arg* item = args_getArgByidex(&keys->super, i);
+        Arg* item = args_getArgByIndex(&keys->super, i);
         if (NULL == item) {
             break;
         }
@@ -141,8 +141,8 @@ char* PikaStdData_Dict___str__(PikaObj* self) {
 
     int i = 0;
     while (PIKA_TRUE) {
-        Arg* item_key = args_getArgByidex(&keys->super, i);
-        Arg* item_val = args_getArgByidex(&dict->super, i);
+        Arg* item_key = args_getArgByIndex(&keys->super, i);
+        Arg* item_val = args_getArgByIndex(&dict->super, i);
         if (NULL == item_key) {
             break;
         }
@@ -186,7 +186,7 @@ int PikaStdData_dict_keys___len__(PikaObj* self) {
 int dict_contains(PikaDict* dict, Arg* key) {
     int i = 0;
     while (PIKA_TRUE) {
-        Arg* item = args_getArgByidex(&dict->super, i);
+        Arg* item = args_getArgByIndex(&dict->super, i);
         if (NULL == item) {
             break;
         }
@@ -219,8 +219,8 @@ Arg* PikaStdData_dict_items___next__(PikaObj* self) {
     PikaObj* dictptr = obj_getPtr(self, "dictptr");
     PikaDict* keys = obj_getPtr(dictptr, "_keys");
     PikaDict* dict = obj_getPtr(dictptr, "dict");
-    Arg* key = args_getArgByidex(&keys->super, __iter_i);
-    Arg* val = args_getArgByidex(&dict->super, __iter_i);
+    Arg* key = args_getArgByIndex(&keys->super, __iter_i);
+    Arg* val = args_getArgByIndex(&dict->super, __iter_i);
     if (NULL == key) {
         return arg_newNull();
     }

+ 4 - 0
package/PikaStdLib/PikaStdLib_SysObj.c

@@ -443,7 +443,11 @@ static char* __print_arg(PikaObj* self, Arg* val) {
     }
     if (arg_type == ARG_TYPE_INT) {
         int64_t value = arg_getInt(val);
+#if PIKA_PRINT_LLD_ENABLE
         res = strsFormat(&buffs, 32, "%lld", value);
+#else
+        res = strsFormat(&buffs, 32, "%d", value);
+#endif
         goto __exit;
     }
     if (arg_type == ARG_TYPE_FLOAT) {

+ 1 - 0
package/TemplateDevice/TemplateDevice.pyi

@@ -10,6 +10,7 @@ class GPIO(PikaStdDevice.GPIO):
     def platformSetMode(self): ...
     def platformRead(self): ...
     def platformGetEventId(self): ...
+    def eventTest(self): ...
 
 
 class Time(PikaStdDevice.Time):

+ 12 - 0
package/TemplateDevice/TemplateDevice_GPIO.c

@@ -14,3 +14,15 @@ void TemplateDevice_GPIO_platformGetEventId(PikaObj* self) {
         obj_setInt(self, "eventId", GPIO_PA8_EVENT_ID);
     }
 }
+
+extern PikaEventListener* g_pika_device_event_listener;
+#define EVENT_SIGNAL_IO_RISING_EDGE 0x01
+#define EVENT_SIGNAL_IO_FALLING_EDGE 0x02
+#define GPIO_PA8_EVENT_ID 0x08
+
+void TemplateDevice_GPIO_eventTest(PikaObj* self) {
+    pks_eventLisener_sendSignal(g_pika_device_event_listener, GPIO_PA8_EVENT_ID,
+                                EVENT_SIGNAL_IO_FALLING_EDGE);
+    pks_eventLisener_sendSignal(g_pika_device_event_listener, GPIO_PA8_EVENT_ID,
+                                EVENT_SIGNAL_IO_RISING_EDGE);
+}

+ 40 - 0
package/base64/_base64.c

@@ -0,0 +1,40 @@
+#include "_base64.h"
+
+#include "mbedtls/base64.h"
+
+Arg* _base64_b64decode(PikaObj* self, Arg* s) {
+    ArgType t = arg_getType(s);
+    if (ARG_TYPE_BYTES != t) {
+        obj_setErrorCode(self, -2);  // io error
+        obj_setSysOut(self, "base64.b64decode input not bytes");
+    }
+
+    uint8_t* input_buff = arg_getBytes(s);
+    size_t input_len = arg_getBytesSize(s);
+    obj_setBytes(self, "__de_buff", NULL, input_len);
+    uint8_t* output_buff = obj_getBytes(self, "__de_buff");
+    size_t output_len = 0;
+    mbedtls_base64_decode(output_buff, obj_getBytesSize(self, "__de_buff"),
+                          &output_len, input_buff, input_len);
+    Arg* r = arg_newBytes(output_buff, output_len);
+    obj_removeArg(self, "__de_buff");
+    return r;
+}
+
+Arg* _base64_b64encode(PikaObj* self, Arg* s) {
+    ArgType t = arg_getType(s);
+    if (ARG_TYPE_BYTES != t) {
+        obj_setErrorCode(self, -2);  // io error
+        obj_setSysOut(self, "base64.b64encode input not bytes");
+    }
+    uint8_t* input_buff = arg_getBytes(s);
+    size_t input_len = arg_getBytesSize(s);
+    obj_setBytes(self, "__de_buff", NULL, (size_t)(input_len * 2));
+    uint8_t* output_buff = obj_getBytes(self, "__de_buff");
+    size_t output_len = 0;
+    mbedtls_base64_encode(output_buff, obj_getBytesSize(self, "__de_buff"),
+                          &output_len, input_buff, input_len);
+    Arg* r = arg_newBytes(output_buff, output_len);
+    obj_removeArg(self, "__de_buff");
+    return r;
+}

+ 2 - 0
package/base64/_base64.pyi

@@ -0,0 +1,2 @@
+def b64encode(s: any) -> any: ...
+def b64decode(s: any) -> any: ...

+ 9 - 0
package/base64/base64.py

@@ -0,0 +1,9 @@
+import _base64
+
+
+def b64encode(s: any):
+    return _base64.b64encode(s)
+
+
+def b64decode(s: any):
+    return _base64.b64decode(s)

+ 59 - 233
package/hmac/_hmac_HMAC.c

@@ -1,11 +1,7 @@
 #include "_hmac_HMAC.h"
-
+#include "mbedtls/md.h"
 #include "string.h"
 
-#include "mbedtls/md5.h"
-#include "mbedtls/sha1.h"
-#include "mbedtls/sha256.h"
-
 enum {
     PIKA_HMAC_MD5 = 16,
     PIKA_HMAC_SHA1 = 20,
@@ -14,220 +10,91 @@ enum {
 
 static void hmac_to_hex(uint8_t* s, int l, uint8_t* d);
 
+static void init_buff(PikaObj* self, size_t h) {
+    obj_setBytes(self, "_buff", NULL, h);
+    obj_setBytes(self, "_hexbuff", NULL, (h * 2));
+    memset(obj_getBytes(self, "_buff"), 0, h);
+    memset(obj_getBytes(self, "_hexbuff"), 0, (h * 2));
+}
+
 void _hmac_HMAC_new(PikaObj* self, Arg* key, Arg* msg, char* digestmod) {
     ArgType t;
     t = arg_getType(key);
-    if (ARG_TYPE_NONE != t) {
-        if (ARG_TYPE_BYTES != t) {
-            obj_setErrorCode(self, -2);  // io error
-        }
+    if (ARG_TYPE_BYTES != t) {
+        obj_setErrorCode(self, -2);  // io error
+        obj_setSysOut(self, "hmac.new() key type error");
     }
+
     t = arg_getType(msg);
     if (ARG_TYPE_NONE != t) {
         if (ARG_TYPE_BYTES != t) {
             obj_setErrorCode(self, -2);  // io error
+            obj_setSysOut(self, "hmac.new() msg type error");
         }
     }
 
-    obj_setInt(self, "_digest_flags", 0);                 // flag
-    obj_setBytes(self, "_buff", NULL, PIKA_HMAC_SHA256);  // digest buff
-    obj_setBytes(self, "_hexbuff", NULL,
-                 PIKA_HMAC_SHA256 * 2);      // hexdigest buff
-    obj_setBytes(self, "_k_ipad", NULL, 64);  // key ipad
-    obj_setBytes(self, "_k_opad", NULL, 64);  // key opad
-
     size_t key_len = arg_getBytesSize(key);
     uint8_t* key_data = arg_getBytes(key);
     size_t msg_len = arg_getBytesSize(msg);
     uint8_t* msg_data = arg_getBytes(msg);
-
-    uint8_t* k_ipad = obj_getBytes(self, "_k_ipad");
-    uint8_t* k_opad = obj_getBytes(self, "_k_opad");
-
-    if (strcmp(digestmod, "hmac-md5") == 0 ||
-        strcmp(digestmod, "HMAC-MD5") == 0) {
-        mbedtls_md5_context context;
-
-        if (key_len > 64) {
-            mbedtls_md5_init(&context);
-            mbedtls_md5_starts(&context);
-            mbedtls_md5_update(&context, key_data, key_len);
-            mbedtls_md5_finish(&context, k_ipad);
-            mbedtls_md5_free(&context);
-            memcpy(k_opad, k_ipad, 64);
-        } else {
-            memcpy(k_ipad, key_data, key_len);
-            memcpy(k_opad, key_data, key_len);
-        }
-
-        for (size_t i = 0; i < 64; i++) {
-            k_ipad[i] ^= 0x36;
-            k_opad[i] ^= 0x5c;
-        }
-
-        mbedtls_md5_init(&context);
-        mbedtls_md5_starts(&context);
-        mbedtls_md5_update(&context, k_ipad, 64);
-        if (msg_len > 0) {
-            mbedtls_md5_update(&context, msg_data, msg_len);
-        }
-
-        obj_setStruct(self, "context", context);
-        obj_setInt(self, "mode", PIKA_HMAC_MD5);
-    } else if (strcmp(digestmod, "hmac-sha1") == 0 ||
-               strcmp(digestmod, "HMAC-SHA1") == 0) {
-        mbedtls_sha1_context context;
-
-        if (key_len > 64) {
-            mbedtls_sha1_init(&context);
-            mbedtls_sha1_starts(&context);
-            mbedtls_sha1_update(&context, key_data, key_len);
-            mbedtls_sha1_finish(&context, k_ipad);
-            mbedtls_sha1_free(&context);
-            memcpy(k_opad, k_ipad, 64);
-        } else {
-            memcpy(k_ipad, key_data, key_len);
-            memcpy(k_opad, key_data, key_len);
-        }
-
-        for (size_t i = 0; i < 64; i++) {
-            k_ipad[i] ^= 0x36;
-            k_opad[i] ^= 0x5c;
-        }
-
-        mbedtls_sha1_init(&context);
-        mbedtls_sha1_starts(&context);
-        mbedtls_sha1_update(&context, k_ipad, 64);
-        if (msg_len > 0) {
-            mbedtls_sha1_update(&context, msg_data, msg_len);
-        }
-
-        obj_setStruct(self, "context", context);
-        obj_setInt(self, "mode", PIKA_HMAC_SHA1);
-    } else if (strcmp(digestmod, "hmac-sha256") == 0 ||
-               strcmp(digestmod, "HMAC-SHA256") == 0) {
-        mbedtls_sha256_context context;
-
-        if (key_len > 64) {
-            mbedtls_sha256_init(&context);
-            mbedtls_sha256_starts(&context, 0);
-            mbedtls_sha256_update(&context, key_data, key_len);
-            mbedtls_sha256_finish(&context, k_ipad);
-            mbedtls_sha256_free(&context);
-            memcpy(k_opad, k_ipad, 64);
-        } else {
-            memcpy(k_ipad, key_data, key_len);
-            memcpy(k_opad, key_data, key_len);
-        }
-
-        for (size_t i = 0; i < 64; i++) {
-            k_ipad[i] ^= 0x36;
-            k_opad[i] ^= 0x5c;
-        }
-
-        mbedtls_sha256_init(&context);
-        mbedtls_sha256_starts(&context, 0);
-        mbedtls_sha256_update(&context, k_ipad, 64);
-        if (msg_len > 0) {
-            mbedtls_sha256_update(&context, msg_data, msg_len);
-        }
-
-        obj_setStruct(self, "context", context);
-        obj_setInt(self, "mode", PIKA_HMAC_SHA256);
+    obj_setInt(self, "_digest_flags", 0);  // flag
+    mbedtls_md_context_t ctx;
+    mbedtls_md_init(&ctx);
+
+    if (strcmp(digestmod, "md5") == 0 ||
+        strcmp(digestmod, "MD5") == 0) {
+        mbedtls_md_setup(&ctx, mbedtls_md_info_from_type(MBEDTLS_MD_MD5), 1);
+        obj_setInt(self, "_mode", PIKA_HMAC_MD5);
+        init_buff(self, PIKA_HMAC_MD5);
+    } else if (strcmp(digestmod, "sha1") == 0 ||
+               strcmp(digestmod, "SHA1") == 0) {
+        mbedtls_md_setup(&ctx, mbedtls_md_info_from_type(MBEDTLS_MD_SHA1), 1);
+        obj_setInt(self, "_mode", PIKA_HMAC_SHA1);
+        init_buff(self, PIKA_HMAC_SHA1);
+    } else if (strcmp(digestmod, "sha256") == 0 ||
+               strcmp(digestmod, "SHA256") == 0) {
+        mbedtls_md_setup(&ctx, mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), 1);
+        obj_setInt(self, "_mode", PIKA_HMAC_SHA256);
+        init_buff(self, PIKA_HMAC_SHA256);
     } else {
-        obj_setErrorCode(self, -1);  // not support mode
+        obj_setErrorCode(self, -2);  // io error
+        obj_setSysOut(self, "hmac.new() not support mode");
+    }
+    mbedtls_md_hmac_starts(&ctx, key_data, key_len);
+    if (msg_len > 0) {
+        mbedtls_md_hmac_update(&ctx, msg_data, msg_len);
     }
+    obj_setStruct(self, "_context", ctx);
 }
 
 void _hmac_HMAC_update(PikaObj* self, Arg* msg) {
     ArgType t = arg_getType(msg);
     if (ARG_TYPE_BYTES != t) {
         obj_setErrorCode(self, -2);  // io error
+        obj_setSysOut(self, "hmac.update() msg type error");
     }
 
     size_t msg_len = arg_getBytesSize(msg);
     uint8_t* msg_data = arg_getBytes(msg);
-    void* context = obj_getStruct(self, "context");
-
-    if (msg_len > 0) {
-        switch (obj_getInt(self, "mode")) {
-            case PIKA_HMAC_MD5:
-                mbedtls_md5_update((mbedtls_md5_context*)context, msg_data,
-                                   msg_len);
-                break;
-            case PIKA_HMAC_SHA1:
-                mbedtls_sha1_update((mbedtls_sha1_context*)context, msg_data,
-                                    msg_len);
-                break;
-            case PIKA_HMAC_SHA256:
-                mbedtls_sha256_update((mbedtls_sha256_context*)context,
-                                      msg_data, msg_len);
-                break;
-            default:
-                break;
-        }
-    } else {
-        obj_setErrorCode(self, -2);  // io error
-    }
+    mbedtls_md_context_t* ctx = obj_getStruct(self, "_context");
+    mbedtls_md_hmac_update(ctx, msg_data, msg_len);
 }
 
 Arg* _hmac_HMAC_digest(PikaObj* self) {
-    uint8_t* k_opad = obj_getBytes(self, "_k_opad");
     uint8_t* buff = obj_getBytes(self, "_buff");
     uint8_t flag = obj_getInt(self, "_digest_flags");
 
     if (flag & 0x01)  // already digest
     {
-        return arg_newBytes(buff, obj_getInt(self, "mode"));
+        goto exit;
     } else {
-        void* context = obj_getStruct(self, "context");
-        uint8_t mode = obj_getInt(self, "mode");
-        switch (mode) {
-            case PIKA_HMAC_MD5:
-                mbedtls_md5_finish((mbedtls_md5_context*)context, buff);
-                mbedtls_md5_free((mbedtls_md5_context*)context);
-
-                mbedtls_md5_init((mbedtls_md5_context*)context);
-                mbedtls_md5_starts((mbedtls_md5_context*)context);
-                mbedtls_md5_update((mbedtls_md5_context*)context, k_opad, 64);
-                mbedtls_md5_update((mbedtls_md5_context*)context, buff,
-                                   PIKA_HMAC_MD5);
-                mbedtls_md5_finish((mbedtls_md5_context*)context, buff);
-                mbedtls_md5_free((mbedtls_md5_context*)context);
-                break;
-            case PIKA_HMAC_SHA1:
-                mbedtls_sha1_finish((mbedtls_sha1_context*)context, buff);
-                mbedtls_sha1_free((mbedtls_sha1_context*)context);
-
-                mbedtls_sha1_init((mbedtls_sha1_context*)context);
-                mbedtls_sha1_starts((mbedtls_sha1_context*)context);
-                mbedtls_sha1_update((mbedtls_sha1_context*)context, k_opad, 64);
-                mbedtls_sha1_update((mbedtls_sha1_context*)context, buff,
-                                    PIKA_HMAC_SHA1);
-                mbedtls_sha1_finish((mbedtls_sha1_context*)context, buff);
-                mbedtls_sha1_free((mbedtls_sha1_context*)context);
-                break;
-            case PIKA_HMAC_SHA256:
-                mbedtls_sha256_finish((mbedtls_sha256_context*)context, buff);
-                mbedtls_sha256_free((mbedtls_sha256_context*)context);
-
-                mbedtls_sha256_init((mbedtls_sha256_context*)context);
-                mbedtls_sha256_starts((mbedtls_sha256_context*)context, 0);
-                mbedtls_sha256_update((mbedtls_sha256_context*)context, k_opad,
-                                      64);
-                mbedtls_sha256_update((mbedtls_sha256_context*)context, buff,
-                                      PIKA_HMAC_SHA256);
-                mbedtls_sha256_finish((mbedtls_sha256_context*)context, buff);
-                mbedtls_sha256_free((mbedtls_sha256_context*)context);
-                break;
-            default:
-                obj_setErrorCode(self, -1);  // not support mode
-                return arg_newNull();  // will not actually return to the python
-                break;
-        }
+        mbedtls_md_context_t* ctx = obj_getStruct(self, "_context");
+        mbedtls_md_hmac_finish(ctx, buff);
         obj_setInt(self, "_digest_flags", flag | 0x01);
-        return arg_newBytes(buff, mode);
+        goto exit;
     }
+exit:
+    return arg_newBytes(buff, obj_getInt(self, "_mode"));
 }
 
 char* _hmac_HMAC_hexdigest(PikaObj* self) {
@@ -235,61 +102,20 @@ char* _hmac_HMAC_hexdigest(PikaObj* self) {
     uint8_t* hexbuff = obj_getBytes(self, "_hexbuff");
     uint8_t flag = obj_getInt(self, "_digest_flags");
 
-    if (flag & 0x01) {  // already digest
-        hmac_to_hex(buff, obj_getInt(self, "mode"), hexbuff);
+    if (flag & 0x01) {                                   // already digest
         obj_setInt(self, "_digest_flags", flag | 0x02);  // set hexdigest flag
-    } else if (flag & 0x02) {                           // already hexdigest
-
+        goto exit;
+    } else if (flag & 0x02) {  // already hexdigest
+        return (char*)hexbuff;
     } else {
-        void* context = obj_getStruct(self, "context");
-        uint8_t* k_opad = obj_getBytes(self, "_k_opad");
-
-        switch (obj_getInt(self, "mode")) {
-            case PIKA_HMAC_MD5:
-                mbedtls_md5_finish((mbedtls_md5_context*)context, buff);
-                mbedtls_md5_free((mbedtls_md5_context*)context);
-
-                mbedtls_md5_init((mbedtls_md5_context*)context);
-                mbedtls_md5_starts((mbedtls_md5_context*)context);
-                mbedtls_md5_update((mbedtls_md5_context*)context, k_opad, 64);
-                mbedtls_md5_update((mbedtls_md5_context*)context, buff,
-                                   PIKA_HMAC_MD5);
-                mbedtls_md5_finish((mbedtls_md5_context*)context, buff);
-                mbedtls_md5_free((mbedtls_md5_context*)context);
-                break;
-            case PIKA_HMAC_SHA1:
-                mbedtls_sha1_finish((mbedtls_sha1_context*)context, buff);
-                mbedtls_sha1_free((mbedtls_sha1_context*)context);
-
-                mbedtls_sha1_init((mbedtls_sha1_context*)context);
-                mbedtls_sha1_starts((mbedtls_sha1_context*)context);
-                mbedtls_sha1_update((mbedtls_sha1_context*)context, k_opad, 64);
-                mbedtls_sha1_update((mbedtls_sha1_context*)context, buff,
-                                    PIKA_HMAC_SHA1);
-                mbedtls_sha1_finish((mbedtls_sha1_context*)context, buff);
-                mbedtls_sha1_free((mbedtls_sha1_context*)context);
-                break;
-            case PIKA_HMAC_SHA256:
-                mbedtls_sha256_finish((mbedtls_sha256_context*)context, buff);
-                mbedtls_sha256_free((mbedtls_sha256_context*)context);
-
-                mbedtls_sha256_init((mbedtls_sha256_context*)context);
-                mbedtls_sha256_starts((mbedtls_sha256_context*)context, 0);
-                mbedtls_sha256_update((mbedtls_sha256_context*)context, k_opad,
-                                      64);
-                mbedtls_sha256_update((mbedtls_sha256_context*)context, buff,
-                                      PIKA_HMAC_SHA256);
-                mbedtls_sha256_finish((mbedtls_sha256_context*)context, buff);
-                mbedtls_sha256_free((mbedtls_sha256_context*)context);
-                break;
-            default:
-                obj_setErrorCode(self, -1);  // not support mode
-                break;
-        }
-        hmac_to_hex(buff, PIKA_HMAC_MD5, hexbuff);
-        obj_setInt(self, "_digest_flags",
-                   flag | 0x03);  // set digest and hexdigest flags
+        mbedtls_md_context_t* ctx = obj_getStruct(self, "_context");
+        mbedtls_md_hmac_finish(ctx, buff);
+        // set digest and hexdigest flags
+        obj_setInt(self, "_digest_flags", flag | 0x03);
+        goto exit;
     }
+exit:
+    hmac_to_hex(buff, obj_getInt(self, "_mode"), hexbuff);
     return (char*)hexbuff;
 }
 

+ 1 - 1
package/hmac/hmac.py

@@ -1,6 +1,6 @@
 import _hmac
 
-def new(key:any, msg=None, digestmod="hmac-md5") -> _hmac.HMAC:
+def new(key:any, msg=None, digestmod="md5") -> _hmac.HMAC:
     hmac = _hmac.HMAC()
     hmac.new(key, msg, digestmod)
     return hmac

+ 24 - 12
package/mqtt/_mqtt.pyi

@@ -6,31 +6,31 @@ class _MQTT:
 
     def __del__(self): ...
 
-    def setClientID(self, id:str) -> int:
+    def setClientID(self, id: str) -> int:
         pass
         """Set the ClientID of the MQTTClient."""
 
-    def setUsername(self, name:str) -> int:
+    def setUsername(self, name: str) -> int:
         pass
         """Set the Username of the MQTTClient."""
 
-    def setPassword(self, passwd:str) -> int:
+    def setPassword(self, passwd: str) -> int:
         pass
         """Set the Password of the MQTTClient."""
 
-    def setVersion(self, version:str) -> int:
+    def setVersion(self, version: str) -> int:
         pass
         """Set the Version of the MQTTClient."""
 
-    def setCa(self, ca:str) -> int:
+    def setCa(self, ca: str) -> int:
         pass
         """Set the Ca of the MQTTClient."""
 
-    def setKeepAlive(self, time:str) -> int:
+    def setKeepAlive(self, time: int) -> int:
         pass
         """Set the KeepAlive of the MQTTClient."""
 
-    def setWill(self, qos:int, topic:str, retain:int, payload:str) -> int:
+    def setWill(self, topic: str, payload: str, qos: int, retain: int) -> int:
         pass
         """Set the Will of the MQTTClient."""
 
@@ -42,19 +42,19 @@ class _MQTT:
         pass
         """disconnect to the mqtt-server."""
 
-    def subscribe(self, topic:str, cb:any) -> int:
+    def subscribe(self, topic: str, cb: any, qos: int) -> int:
         pass
         """subscribe to the mqtt-server."""
 
-    def unsubscribe(self, topic:str) -> int:
+    def unsubscribe(self, topic: str) -> int:
         pass
         """unsubscribe to the mqtt-server."""
 
-    def listSubscribrTopic(self) -> dict:
+    def listSubscribeTopic(self) -> list:
         pass
-        """listSubscribrTopic """
+        """listSubscribeTopic """
 
-    def publish(self, topic:str , payload:str) -> int:
+    def publish(self, topic: str, payload: str, qos: int) -> int:
         pass
         """publish to the mqtt-server."""
 
@@ -63,3 +63,15 @@ class _MQTT:
 
     def setHost(self, host_url: str) -> int:
         """Set the host_url of the MQTTClient."""
+
+    def setDisconnectHandler(self, cb: any) -> int:
+        pass
+        """set disconnect callback fun."""
+
+    def _fakeMsg(self, topic: str, qos: int, msg: str):
+        pass
+        """fake msg for subscribe test"""
+
+
+def __del__():
+    pass

+ 469 - 80
package/mqtt/_mqtt__MQTT.c

@@ -1,6 +1,19 @@
 #include "_mqtt__MQTT.h"
+#include "PikaObj.h"
+#include "PikaStdData_List.h"
+#include "TinyObj.h"
 #include "mqttclient.h"
 
+#if !PIKASCRIPT_VERSION_REQUIRE_MINIMUN(1, 12, 0)
+#error "This library requires PikaScript version 1.12.0 or higher"
+#endif
+
+PikaEventListener* g_mqtt_event_listener = NULL;
+
+void Subscribe_Handler(void* client, message_data_t* msg);
+
+const uint32_t MQTT_RECONNECTION_EVENT_ID = 0xFFAA0088;
+
 ////////////////////////////////////////////////////////////////////
 // 函 数 名:_mqtt__MQTT___init__
 // 功能说明:对象初始化
@@ -16,49 +29,72 @@ void _mqtt__MQTT___init__(PikaObj* self,
                           char* version,
                           char* ca,
                           int keepalive) {
+    obj_setInt(self, "_connected", 0);
     mqtt_client_t* _client = mqtt_lease();
-    //obj_setPtr(self, "_client", _client);
+    _client->user_data = self;
+    // obj_setPtr(self, "_client", _client);
     /* port to str, and cache to object */
     char port_str[10] = {0};
+    int tmp = 0;
 
-    if(strlen(ip) > 0)
-    {
+    if (strlen(ip) > 0) {
         obj_setStr(self, "host_str", ip);
-        mqtt_set_host(_client, obj_getStr(self,"host_str"));
+        mqtt_set_host(_client, obj_getStr(self, "host_str"));
+    } else {
+        __platform_printf("mqtt_init input ip none\r\n");
     }
 
+    memset(port_str, 0, sizeof(port_str));
     __platform_sprintf(port_str, "%d", port);
     obj_setStr(self, "port", port_str);
-    mqtt_set_port(_client, obj_getStr(self,"port"));
+    mqtt_set_port(_client, obj_getStr(self, "port"));
 
-    if(strlen(clinetID) > 0)
-    {
+    if (strlen(clinetID) > 0) {
         obj_setStr(self, "id_str", clinetID);
-        mqtt_set_client_id(_client, obj_getStr(self,"id_str"));
+        mqtt_set_client_id(_client, obj_getStr(self, "id_str"));
+    } else {
+        __platform_printf("mqtt_init input clinetID none\r\n");
     }
 
-    if(strlen(username) > 0)
-    {
+    if (strlen(username) > 0) {
         obj_setStr(self, "username_str", username);
-        mqtt_set_user_name(_client, obj_getStr(self,"username_str"));
+        mqtt_set_user_name(_client, obj_getStr(self, "username_str"));
+    } else {
+        __platform_printf("mqtt_init input username none\r\n");
     }
 
-    if(strlen(password) > 0)
-    {
+    if (strlen(password) > 0) {
         obj_setStr(self, "password_str", password);
-        mqtt_set_password(_client, obj_getStr(self,"password_str"));
+        mqtt_set_password(_client, obj_getStr(self, "password_str"));
+    } else {
+        __platform_printf("mqtt_init input password none\r\n");
     }
-        
-    if(strlen(ca) > 0)
-    {
+
+    tmp = atoi(version);
+    if (tmp > 0) {
+        mqtt_set_version(_client, tmp);
+    } else {
+        __platform_printf("mqtt_init input version none\r\n");
+    }
+
+    if (strlen(ca) > 0) {
         obj_setStr(self, "ca_str", ca);
-        mqtt_set_ca(_client, obj_getStr(self,"ca_str"));
+        mqtt_set_ca(_client, obj_getStr(self, "ca_str"));
+    } else {
+        // __platform_printf("mqtt_init input ca none\r\n");
+    }
+
+    if (keepalive > 0) {
+        mqtt_set_keep_alive_interval(_client, keepalive);
+    } else {
+        __platform_printf("mqtt_init input keepalive none\r\n");
     }
 
     mqtt_set_clean_session(_client, 1);
 
-    obj_setPtr(self, "_client", _client);//这里要再保存一次mqtt结构体的内容到python环境
-    __platform_printf("Mqtt_Lib buildtime:%s-%s\r\n",__DATE__,__TIME__);
+    obj_setPtr(self, "_client",
+               _client);  // 这里要再保存一次mqtt结构体的内容到python环境
+    // __platform_printf("Mqtt_Lib buildtime:%s-%s\r\n", __DATE__, __TIME__);
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -69,10 +105,16 @@ void _mqtt__MQTT___init__(PikaObj* self,
 ///////////////////////////////////////////////////////////////////
 void _mqtt__MQTT___del__(PikaObj* self) {
     mqtt_client_t* _client = obj_getPtr(self, "_client");
-    if (NULL != _client) {
-        //mqtt_release(_client);
-        mqtt_release_free(_client);
+    if (NULL == _client) {
+        return;
     }
+    /* disconnect autoly if not disconnected */
+    int _connected = obj_getInt(self, "_connected");
+    if (_connected) {
+        _mqtt__MQTT_disconnect(self);
+    }
+    // MQTT_LOG_E("%s:%d %s() >_<", __FILE__, __LINE__, __FUNCTION__);
+    mqtt_release_free(_client);
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -81,17 +123,17 @@ void _mqtt__MQTT___del__(PikaObj* self) {
 // 输入参数:无
 // 返 回 值:0=成功;非0=错误码
 ///////////////////////////////////////////////////////////////////
-int _mqtt__MQTT_connect(PikaObj *self) {
+int _mqtt__MQTT_connect(PikaObj* self) {
     int ret;
-
+    obj_setInt(self, "_connected", 1);
     mqtt_client_t* _client = obj_getPtr(self, "_client");
 
     ret = mqtt_connect(_client);
-    if(ret != 0)
-        __platform_printf("mqtt connect ERROR! :%d\r\n",ret);
+    if (ret != 0)
+        __platform_printf("mqtt connect ERROR! :%d\r\n", ret);
 
-    if(ret == 0)
-        __platform_printf("mqtt connect OK\r\n");
+    // if (ret == 0)
+    //     __platform_printf("mqtt connect OK\r\n");
     return ret;
 }
 
@@ -101,29 +143,65 @@ int _mqtt__MQTT_connect(PikaObj *self) {
 // 输入参数:无
 // 返 回 值:0=成功;非0=错误码
 ///////////////////////////////////////////////////////////////////
-int _mqtt__MQTT_disconnect(PikaObj *self) {
+int _mqtt__MQTT_disconnect(PikaObj* self) {
     int ret;
-
+    obj_setInt(self, "_connected", 0);
     mqtt_client_t* _client = obj_getPtr(self, "_client");
 
     ret = mqtt_disconnect(_client);
-    if(ret != 0)
-        __platform_printf("mqtt disconnect ERROR! :%d\r\n",ret);
+    if (ret != 0)
+        __platform_printf("mqtt disconnect ERROR! :%d\r\n", ret);
 
-    if(ret == 0)
-        __platform_printf("mqtt disconnect Done\r\n");
+    // if (ret == 0)
+    //     __platform_printf("mqtt disconnect OK\r\n");
     return ret;
 }
 
 ////////////////////////////////////////////////////////////////////
-// 函 数 名:_mqtt__MQTT_listSubscribrTopic
+// 函 数 名:_mqtt__MQTT_listSubscribeTopic
 // 功能说明:罗列出当前订阅的主题
 // 输入参数:无
 // 返 回 值:对象指针
 ///////////////////////////////////////////////////////////////////
-PikaObj* _mqtt__MQTT_listSubscribrTopic(PikaObj *self) {
+PikaObj* _mqtt__MQTT_listSubscribeTopic(PikaObj* self) {
+    mqtt_client_t* _client = obj_getPtr(self, "_client");
+    // int i = 0;
+    mqtt_list_t *curr, *next;
+    message_handlers_t* msg_handler;
+    PikaObj* list = NULL;
+
+    if (NULL == _client) {
+        return NULL;
+    }
+
+    if (mqtt_list_is_empty(&_client->mqtt_msg_handler_list)) {
+        MQTT_LOG_I("%s:%d %s()... there are no subscribed topics...", __FILE__,
+                   __LINE__, __FUNCTION__);
+        return NULL;
+    }
 
-    return NULL;
+    /* 创建 list 对象 */
+    list = newNormalObj(New_PikaStdData_List);
+    /* 初始化 list */
+    PikaStdData_List___init__(list);
+
+    LIST_FOR_EACH_SAFE(curr, next, &_client->mqtt_msg_handler_list) {
+        msg_handler = LIST_ENTRY(curr, message_handlers_t, list);
+        /* determine whether a node already exists by mqtt topic, but wildcards
+         * are not supported */
+        if (NULL != msg_handler->topic_filter) {
+            MQTT_LOG_I("%s:%d %s()...[%d] subscribe topic: %s", __FILE__,
+                       __LINE__, __FUNCTION__, ++i, msg_handler->topic_filter);
+            // __platform_printf("[%d]subscribe topic: %s\n",++i,
+            // msg_handler->topic_filter);
+            /* 用 arg_new<type> 的 api 创建 arg */
+            Arg* str_arg1 = arg_newStr((char*)msg_handler->topic_filter);
+            /* 添加到 list 对象 */
+            PikaStdData_List_append(list, str_arg1);
+            arg_deinit(str_arg1);
+        }
+    }
+    return list;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -132,9 +210,37 @@ PikaObj* _mqtt__MQTT_listSubscribrTopic(PikaObj *self) {
 // 输入参数:主题名称,有效数据
 // 返 回 值:0=成功;非0=错误码
 ///////////////////////////////////////////////////////////////////
-int _mqtt__MQTT_publish(PikaObj *self, char* topic, char* payload) {
+int _mqtt__MQTT_publish(PikaObj* self, char* topic, char* payload, int qos) {
+    int ret;
+    mqtt_message_t msg;
 
-    return 0;
+    mqtt_client_t* _client = obj_getPtr(self, "_client");
+    memset(&msg, 0, sizeof(msg));
+
+    if ((qos < 0) || (qos > 2)) {
+        __platform_printf("input qos error\r\n");
+        return -1;
+    }
+    if (strlen(topic) <= 0) {
+        __platform_printf("input topic error\r\n");
+        return -2;
+    }
+
+    if (strlen(payload) <= 0) {
+        __platform_printf("input payload error\r\n");
+        return -3;
+    }
+
+    msg.payload = (void*)payload;
+    msg.qos = qos;
+    __platform_printf("msg.qos:%d\r\n",
+                      msg.qos);  // 这里为了防止被优化,导致运行异常
+    ret = mqtt_publish(_client, topic, &msg);
+    if (ret == 0) {
+        // __platform_printf("MQTT_publish OK\r\n");
+    } else
+        __platform_printf("MQTT_publish ERROR\r\n");
+    return ret;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -143,7 +249,22 @@ int _mqtt__MQTT_publish(PikaObj *self, char* topic, char* payload) {
 // 输入参数:ca值
 // 返 回 值:0=成功;非0=错误码
 ///////////////////////////////////////////////////////////////////
-int _mqtt__MQTT_setCa(PikaObj *self, char* ca) {
+int _mqtt__MQTT_setCa(PikaObj* self, char* ca) {
+    mqtt_client_t* _client = obj_getPtr(self, "_client");
+
+    if (ca == NULL) {
+        __platform_printf("input ca error\r\n");
+        return -1;
+    }
+    if (strlen(ca) <= 0) {
+        __platform_printf("input ca data error\r\n");
+        return -2;
+    }
+    //__platform_printf("ca_str:%s\r\n",ca);
+    obj_setStr(self, "ca_str", ca);
+    mqtt_set_ca(_client, obj_getStr(self, "ca_str"));
+
+    // __platform_printf("MQTT_setCa len:%d\r\n", strlen(ca));
     return 0;
 }
 
@@ -153,21 +274,22 @@ int _mqtt__MQTT_setCa(PikaObj *self, char* ca) {
 // 输入参数:id 字符串格式
 // 返 回 值:0=成功;非0=错误码
 ///////////////////////////////////////////////////////////////////
-int _mqtt__MQTT_setClientID(PikaObj *self, char* id) {
+int _mqtt__MQTT_setClientID(PikaObj* self, char* id) {
     mqtt_client_t* _client = obj_getPtr(self, "_client");
-    
-    if(id == NULL) {
+
+    if (id == NULL) {
         __platform_printf("input id error\r\n");
         return -1;
     }
-    if(strlen(id) <= 0) {
+    if (strlen(id) <= 0) {
         __platform_printf("input id data error\r\n");
         return -2;
     }
 
-    mqtt_set_client_id(_client, id);
-    __platform_printf("MQTT_setClientID:%s\r\n",id);
-    obj_setPtr(self, "_client", _client);//这里要再保存一次mqtt结构体的内容到python环境
+    obj_setStr(self, "id_str", id);
+    mqtt_set_client_id(_client, obj_getStr(self, "id_str"));
+
+    // __platform_printf("MQTT_setClientID :%s\r\n", id);
     return 0;
 }
 
@@ -177,21 +299,25 @@ int _mqtt__MQTT_setClientID(PikaObj *self, char* id) {
 // 输入参数:字符串格式
 // 返 回 值:0=成功;非0=错误码
 ///////////////////////////////////////////////////////////////////
-int _mqtt__MQTT_setHost(PikaObj *self, char* host_url) {
+int _mqtt__MQTT_setHost(PikaObj* self, char* host_url) {
     mqtt_client_t* _client = obj_getPtr(self, "_client");
-    
-    if(host_url == NULL) {
+
+    if (host_url == NULL) {
         __platform_printf("input host_url error\r\n");
         return -1;
     }
-    if(strlen(host_url) <= 0) {
+    if (strlen(host_url) <= 0) {
         __platform_printf("input host_url data error\r\n");
         return -2;
     }
 
-    obj_setStr(self, "host_str", host_url);//python 环境创建一个全局变量存放 host
-    mqtt_set_host(_client, obj_getStr(self,"host_str"));//从python环境中取出 host的指针 赋值给结构体
-    __platform_printf("MQTT_setHost :%s\r\n",host_url);
+    obj_setStr(self, "host_str",
+               host_url);  // python 环境创建一个全局变量存放 host
+    mqtt_set_host(
+        _client,
+        obj_getStr(self,
+                   "host_str"));  // 从python环境中取出 host的指针 赋值给结构体
+    // __platform_printf("MQTT_setHost :%s\r\n", host_url);
 
     return 0;
 }
@@ -202,8 +328,20 @@ int _mqtt__MQTT_setHost(PikaObj *self, char* host_url) {
 // 输入参数:字符串格式
 // 返 回 值:0=成功;非0=错误码
 ///////////////////////////////////////////////////////////////////
-int _mqtt__MQTT_setKeepAlive(PikaObj *self, char* time) {
+int _mqtt__MQTT_setKeepAlive(PikaObj* self, int time) {
+    mqtt_client_t* _client = obj_getPtr(self, "_client");
+    int tmp;
+
+    // tmp = atoi(time);
+    tmp = time;
+    if (tmp > 0) {
+        mqtt_set_keep_alive_interval(_client, tmp);
+    } else {
+        __platform_printf("input keepalive data error \r\n");
+        return -2;
+    }
 
+    // __platform_printf("MQTT_setKeepAlive :%d\r\n", tmp);
     return 0;
 }
 
@@ -213,21 +351,22 @@ int _mqtt__MQTT_setKeepAlive(PikaObj *self, char* time) {
 // 输入参数:字符串格式
 // 返 回 值:0=成功;非0=错误码
 ///////////////////////////////////////////////////////////////////
-int _mqtt__MQTT_setPassword(PikaObj *self, char* passwd) {
+int _mqtt__MQTT_setPassword(PikaObj* self, char* passwd) {
     mqtt_client_t* _client = obj_getPtr(self, "_client");
 
-    if(passwd == NULL) {
+    if (passwd == NULL) {
         __platform_printf("input passwd error\r\n");
         return -1;
     }
-    if(strlen(passwd) <= 0) {
+    if (strlen(passwd) <= 0) {
         __platform_printf("input passwd data error\r\n");
         return -2;
     }
 
-    mqtt_set_password(_client, passwd);
-    __platform_printf("MQTT_setPassword:%s\r\n",passwd);
-    //obj_setPtr(self, "_client", _client);//这里要再保存一次mqtt结构体的内容到python环境
+    obj_setStr(self, "password_str", passwd);
+    mqtt_set_password(_client, obj_getStr(self, "password_str"));
+
+    // __platform_printf("MQTT_setPassword :%s\r\n", passwd);
     return 0;
 }
 
@@ -237,21 +376,21 @@ int _mqtt__MQTT_setPassword(PikaObj *self, char* passwd) {
 // 输入参数:字符串格式
 // 返 回 值:0=成功;非0=错误码
 ///////////////////////////////////////////////////////////////////
-int _mqtt__MQTT_setPort(PikaObj *self, int port) {
+int _mqtt__MQTT_setPort(PikaObj* self, int port) {
     char port_str[10] = {0};
     mqtt_client_t* _client = obj_getPtr(self, "_client");
 
-    if(port <= 0) {
+    if (port <= 0) {
         __platform_printf("input port error\r\n");
         return -1;
     }
 
     __platform_sprintf(port_str, "%d", port);
     obj_setStr(self, "port", port_str);
-    
-    mqtt_set_port(_client, obj_getStr(self,"port"));
-    __platform_printf("MQTT_setPort :%s\r\n",port_str);
-    
+
+    mqtt_set_port(_client, obj_getStr(self, "port"));
+    // __platform_printf("MQTT_setPort :%s\r\n", port_str);
+
     return 0;
 }
 
@@ -261,21 +400,22 @@ int _mqtt__MQTT_setPort(PikaObj *self, int port) {
 // 输入参数:字符串格式
 // 返 回 值:0=成功;非0=错误码
 ///////////////////////////////////////////////////////////////////
-int _mqtt__MQTT_setUsername(PikaObj *self, char* name) {
+int _mqtt__MQTT_setUsername(PikaObj* self, char* name) {
     mqtt_client_t* _client = obj_getPtr(self, "_client");
 
-    if(name == NULL) {
+    if (name == NULL) {
         __platform_printf("input name error\r\n");
         return -1;
     }
-    if(strlen(name) <= 0) {
+    if (strlen(name) <= 0) {
         __platform_printf("input name data error\r\n");
         return -2;
     }
 
-    mqtt_set_user_name(_client, name);
-    __platform_printf("MQTT_setUsername:%s\r\n",name);
-    //obj_setPtr(self, "_client", _client);//这里要再保存一次mqtt结构体的内容到python环境
+    obj_setStr(self, "username_str", name);
+    mqtt_set_user_name(_client, obj_getStr(self, "username_str"));
+
+    // __platform_printf("MQTT_setUsername :%s\r\n", name);
     return 0;
 }
 
@@ -285,18 +425,90 @@ int _mqtt__MQTT_setUsername(PikaObj *self, char* name) {
 // 输入参数:字符串格式
 // 返 回 值:0=成功;非0=错误码
 ///////////////////////////////////////////////////////////////////
-int _mqtt__MQTT_setVersion(PikaObj *self, char* version) {
+int _mqtt__MQTT_setVersion(PikaObj* self, char* version) {
+    mqtt_client_t* _client = obj_getPtr(self, "_client");
+    // int tmp;
 
+    if (version == NULL) {
+        __platform_printf("input version str error\n");
+        return -1;
+    }
+    if ((strcmp(version, "3.1") == 0) || (strcmp(version, "3.1.1") == 0)) {
+        if (strcmp(version, "3.1.1") == 0)
+            mqtt_set_version(_client, 4);
+        else
+            mqtt_set_version(_client, 3);
+    } else {
+        __platform_printf("input version data error\n");
+        return -2;
+    }
+
+    // __platform_printf("MQTT_setVersion :%d\r\n", tmp);
     return 0;
 }
 
 ////////////////////////////////////////////////////////////////////
 // 函 数 名:_mqtt__MQTT_setWill
-// 功能说明:
+// 功能说明:设置遗嘱消息,异常断连时会发送这个消息
 // 输入参数:
 // 返 回 值:0=成功;非0=错误码
 ///////////////////////////////////////////////////////////////////
-int _mqtt__MQTT_setWill(PikaObj *self, int qos, char* topic, int retain, char* payload) {
+int _mqtt__MQTT_setWill(PikaObj* self,
+                        char* topic,
+                        char* payload,
+                        int qos,
+                        int retain) {
+    mqtt_client_t* _client = obj_getPtr(self, "_client");
+    int ret;
+    char topic_str[MQTT_TOPIC_LEN_MAX];
+
+    // __platform_printf("\r\n");
+    if (topic == NULL) {
+        __platform_printf("input topic error\r\n");
+        return -1;
+    }
+
+    if (strlen(topic) <= 0) {
+        __platform_printf("input topic error\r\n");
+        return -1;
+    }
+
+    if ((qos < 0) || (qos > 2)) {
+        __platform_printf("input qos error\r\n");
+        return -1;
+    }
+
+    if (payload == NULL) {
+        __platform_printf("input payload error\r\n");
+        return -1;
+    }
+
+    if (strlen(payload) <= 0) {
+        __platform_printf("input payload error\r\n");
+        return -1;
+    }
+
+    // 必须转换成python环境的变量,否则函数退出后,topic里的是个空指针
+    memset(topic_str, 0, sizeof(topic_str));
+    sprintf(topic_str, "%s", topic);
+    obj_setStr(self, topic_str, topic);
+    obj_setStr(self, "Will_payload", payload);
+
+    // __platform_printf("obj_getStr(self, topic_str) :%s\r\n", obj_getStr(self,
+    // topic_str));
+    // __platform_printf("iqos :%d\r\n", qos);
+    // __platform_printf("retain :%d\r\n", retain);
+    // __platform_printf("obj_getStr(self, \"Will_payload\") :%s\r\n",
+    // obj_getStr(self, "Will_payload"));
+
+    ret = mqtt_set_will_options(_client, obj_getStr(self, topic_str), qos,
+                                (uint8_t)retain,
+                                obj_getStr(self, "Will_payload"));
+
+    if (ret == 0) {
+        // __platform_printf("MQTT_setWill OK\r\n", topic);
+    } else
+        __platform_printf("MQTT_setWill ERROR\r\n");
 
     return 0;
 }
@@ -307,9 +519,62 @@ int _mqtt__MQTT_setWill(PikaObj *self, int qos, char* topic, int retain, char* p
 // 输入参数:
 // 返 回 值:0=成功;非0=错误码
 ///////////////////////////////////////////////////////////////////
-int _mqtt__MQTT_subscribe(PikaObj *self, char* topic, Arg* cb) {
+int _mqtt__MQTT_subscribe(PikaObj* self, char* topic, Arg* cb, int qos) {
+    mqtt_client_t* _client = obj_getPtr(self, "_client");
+    int ret;
+    char topic_str[MQTT_TOPIC_LEN_MAX + 24];
 
-    return 0;
+    // __platform_printf("topic_str:%s \r\n",topic_str);
+    if (topic == NULL) {
+        __platform_printf("input topic error\r\n");
+        return -1;
+    }
+
+    if ((strlen(topic) > MQTT_TOPIC_LEN_MAX) || (strlen(topic) <= 0)) {
+        __platform_printf("input topic data error strlen(topic):%d\r\n",
+                          strlen(topic));
+        return -2;
+    }
+
+    if ((qos < 0) || (qos > 2)) {
+        __platform_printf("input qos error\r\n");
+        return -3;
+    }
+
+    // 必须转换成python环境的变量,否则函数退出后,topic里的是个空指针
+    memset(topic_str, 0, sizeof(topic_str));
+    sprintf(topic_str, "%s", topic);
+    obj_setStr(self, topic_str, topic);
+
+    ret = mqtt_subscribe(_client, obj_getStr(self, topic_str), qos,
+                         Subscribe_Handler);
+    if (ret == 0) {
+        // __platform_printf("MQTT_subscribe Topic :%s Qos:%d OK\r\n",
+        // topic,qos);
+        // 注册mqtt订阅主题的 回调函数
+        if (cb != NULL) {
+            char hash_str[32] = {0};
+            memset(hash_str, 0, sizeof(hash_str));
+            sprintf(hash_str, "C%d", hash_time33(topic_str));
+            obj_newDirectObj(self, hash_str,
+                             New_TinyObj);  // 新建一个对象来放CB
+            PikaObj* eventHandler = obj_getPtr(self, hash_str);
+            obj_setArg(eventHandler, "eventCallBack", cb);
+            /* init event_listener for the first time */
+            if (NULL == g_mqtt_event_listener) {
+                pks_eventListener_init(&g_mqtt_event_listener);
+            }
+            uint32_t eventId = hash_time33(topic_str);
+            // __platform_printf("hash_time33(topic_str):%d
+            // \r\n",hash_time33(topic_str));
+            pks_eventListener_registEvent(g_mqtt_event_listener, eventId,
+                                          eventHandler);
+        }
+
+    } else
+        __platform_printf("MQTT_subscribe Topic ERROR\r\n");
+
+    return ret;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -318,7 +583,131 @@ int _mqtt__MQTT_subscribe(PikaObj *self, char* topic, Arg* cb) {
 // 输入参数:
 // 返 回 值:0=成功;非0=错误码
 ///////////////////////////////////////////////////////////////////
-int _mqtt__MQTT_unsubscribe(PikaObj *self, char* topic) {
+int _mqtt__MQTT_unsubscribe(PikaObj* self, char* topic) {
+    mqtt_client_t* _client = obj_getPtr(self, "_client");
+    int ret;
+
+    if (strlen(topic) <= 0) {
+        __platform_printf("input topic error\r\n");
+        return -1;
+    }
+
+    ret = mqtt_unsubscribe(_client, topic);
+    if (ret == 0) {
+        // __platform_printf("MQTT_unsubscribe :%s OK\r\n", topic);
+    } else
+        __platform_printf("MQTT_unsubscribe :%s ERROR\r\n", topic);
+
+    return 0;
+}
+
+////////////////////////////////////////////////////////////////////
+// 函 数 名:Subscribe_Handler
+// 功能说明:mqtt 订阅主题 的回调函数
+// 输入参数:
+// 返 回 值:0=成功;非0=错误码
+///////////////////////////////////////////////////////////////////
+void Subscribe_Handler(void* client, message_data_t* msg) {
+    char topic_str[MQTT_TOPIC_LEN_MAX + 24];
+
+    memset(topic_str, 0, sizeof(topic_str));
+    if (strlen(msg->topic_name) <= MQTT_TOPIC_LEN_MAX)
+        sprintf(topic_str, "%s", msg->topic_name);
+    else {
+        __platform_printf("Subscribe Topic recv data topic length ERROR\r\n");
+        return;
+    }
+
+    Arg* evt_obj_arg = arg_newDirectObj(New_TinyObj);
+    PikaObj* evt_obj = arg_getPtr(evt_obj_arg);
+    obj_setStr(evt_obj, "topic", (char*)msg->topic_name);
+    obj_setStr(evt_obj, "msg", (char*)msg->message->payload);
+    obj_setInt(evt_obj, "qos", msg->message->qos);
+
+    // 存好数据后,再发送事件信号,防止信号收到了但是需要传输的数据没准备好
+    pks_eventListener_send(g_mqtt_event_listener, hash_time33(msg->topic_name),
+                           evt_obj_arg);
+
+    // MQTT_LOG_I("\n>>>------------------");
+    // MQTT_LOG_I("Topic:%s \nlen:%d,message: %s", msg->topic_name,
+    //            (int)msg->message->payloadlen, (char*)msg->message->payload);
+    // MQTT_LOG_I("------------------<<<");
+}
+
+void _mqtt__MQTT__fakeMsg(PikaObj* self, char* topic, int qos, char* msg) {
+    message_data_t msg_data;
+    mqtt_message_t mqtt_msg;
+    mqtt_msg.payload = msg;
+    mqtt_msg.payloadlen = strlen(msg);
+    mqtt_msg.qos = qos;
+    mqtt_msg.retained = 0;
+    msg_data.message = &mqtt_msg;
+    strcpy(msg_data.topic_name, topic);
+    Subscribe_Handler(NULL, &msg_data);
+}
+
+////////////////////////////////////////////////////////////////////
+// 函 数 名:_mqtt___del__
+// 功能说明:释放事件处理器
+// 输入参数:
+// 返 回 值:
+///////////////////////////////////////////////////////////////////
+void _mqtt___del__(PikaObj* self) {
+    if (NULL != g_mqtt_event_listener) {
+        pks_eventListener_deinit(&g_mqtt_event_listener);
+    }
+}
+
+////////////////////////////////////////////////////////////////////
+// 函 数 名:Reconnect_Handler
+// 功能说明:mqtt 断开连接后
+// 的回调函数,这里使用mqttclient库函数的,断线重连接口,提示发生了mqtt断连的事件
+// 输入参数:
+// 返 回 值:0=成功;非0=错误码
+///////////////////////////////////////////////////////////////////
+void Reconnect_Handler(void* client, void* reconnect_date) {
+    // PikaObj* self = ((mqtt_client_t*)client)->user_data;
+    // __platform_printf("Reconnect_Handler\r\n");
+
+    if (((mqtt_client_t*)client)->mqtt_client_state != CLIENT_STATE_CONNECTED) {
+        // 发送事件信号
+        pks_eventListener_sendSignal(g_mqtt_event_listener,
+                                     MQTT_RECONNECTION_EVENT_ID, 1);
+    }
+}
+
+////////////////////////////////////////////////////////////////////
+// 函 数 名:_mqtt__MQTT_setDisconnectHandler
+// 功能说明:设置断开连接的回调函数
+// 输入参数:
+// 返 回 值:
+///////////////////////////////////////////////////////////////////
+int _mqtt__MQTT_setDisconnectHandler(PikaObj* self, Arg* cb) {
+    mqtt_client_t* _client = obj_getPtr(self, "_client");
+
+    // __platform_printf("_mqtt__MQTT_setDisconnectHandler\r\n");
+
+    // 注册到c库中
+    mqtt_set_reconnect_handler(_client, Reconnect_Handler);
+
+    // char hash_str[32] = {0};
+    // memset(hash_str,0,sizeof(hash_str));
+    // sprintf(hash_str,"C%d",hash_time33(topic_str));
+    // obj_newDirectObj(self,hash_str,New_TinyObj);//新建一个对象来放CB
+    // PikaObj* eventHandler = obj_getPtr(self,hash_str);
+    // obj_setArg(eventHandler, "eventCallBack", cb);
+
+    obj_setArg(self, "eventCallBack",
+               cb);  // 重连回调是唯一的,就直接用self对象
+    /* init event_listener for the first time */
+    if (NULL == g_mqtt_event_listener) {
+        pks_eventListener_init(&g_mqtt_event_listener);
+    }
+    // uint32_t eventId = hash_time33(topic_str);
+    // __platform_printf("hash_time33(topic_str):%d
+    // \r\n",hash_time33(topic_str));
+    pks_eventListener_registEvent(g_mqtt_event_listener,
+                                  MQTT_RECONNECTION_EVENT_ID, self);
 
     return 0;
 }

+ 12 - 0
package/mqtt/mqtt.py

@@ -14,3 +14,15 @@ class MQTT(_mqtt._MQTT):
         super().__init__(ip, port, clinetID,
                          username, password, version,
                          ca, keepalive)
+
+    def subscribe(self, topic, cb, qos=1):
+        return super().subscribe(topic, cb, qos)
+
+    def publish(self, topic, payload, qos=1):
+        return super().publish(topic, payload, qos)
+
+    def setWill(self, topic, payload, qos=1, retain=0):
+        return super().setWill(topic, payload, qos, retain)
+
+    def unsubscribe(self, topic=''):
+        return super().unsubscribe(topic)

+ 1 - 1
package/mqtt/mqtt_config.h

@@ -9,7 +9,7 @@
 
 // #define             MQTT_LOG_IS_SALOF
 
-#define             MQTT_LOG_LEVEL                      MQTT_LOG_INFO_LEVEL   //MQTT_LOG_WARN_LEVEL MQTT_LOG_DEBUG_LEVEL
+#define             MQTT_LOG_LEVEL                      MQTT_LOG_ERR_LEVEL   //MQTT_LOG_WARN_LEVEL MQTT_LOG_DEBUG_LEVEL
 
 #ifdef MQTT_LOG_IS_SALOF
     #define         SALOF_USING_LOG                     (1U)

+ 120 - 103
package/mqtt/mqttclient.c

@@ -23,9 +23,9 @@ static client_state_t mqtt_get_client_state(mqtt_client_t* c) {
 }
 
 static void mqtt_set_client_state(mqtt_client_t* c, client_state_t state) {
-    platform_mutex_lock(&c->mqtt_global_lock);
+    pika_platform_thread_mutex_lock(&c->mqtt_global_lock);
     c->mqtt_client_state = state;
-    platform_mutex_unlock(&c->mqtt_global_lock);
+    pika_platform_thread_mutex_unlock(&c->mqtt_global_lock);
 }
 
 static int mqtt_is_connected(mqtt_client_t* c) {
@@ -64,14 +64,14 @@ static int mqtt_ack_handler_is_maximum(mqtt_client_t* c) {
 }
 
 static void mqtt_add_ack_handler_num(mqtt_client_t* c) {
-    platform_mutex_lock(&c->mqtt_global_lock);
+    pika_platform_thread_mutex_lock(&c->mqtt_global_lock);
     c->mqtt_ack_handler_number++;
-    platform_mutex_unlock(&c->mqtt_global_lock);
+    pika_platform_thread_mutex_unlock(&c->mqtt_global_lock);
 }
 
 static int mqtt_subtract_ack_handler_num(mqtt_client_t* c) {
     int rc = MQTT_SUCCESS_ERROR;
-    platform_mutex_lock(&c->mqtt_global_lock);
+    pika_platform_thread_mutex_lock(&c->mqtt_global_lock);
     if (c->mqtt_ack_handler_number <= 0) {
         goto exit;
     }
@@ -79,15 +79,15 @@ static int mqtt_subtract_ack_handler_num(mqtt_client_t* c) {
     c->mqtt_ack_handler_number--;
 
 exit:
-    platform_mutex_unlock(&c->mqtt_global_lock);
+    pika_platform_thread_mutex_unlock(&c->mqtt_global_lock);
     RETURN_ERROR(rc);
 }
 
 static uint16_t mqtt_get_next_packet_id(mqtt_client_t* c) {
-    platform_mutex_lock(&c->mqtt_global_lock);
+    pika_platform_thread_mutex_lock(&c->mqtt_global_lock);
     c->mqtt_packet_id =
         (c->mqtt_packet_id == MQTT_MAX_PACKET_ID) ? 1 : c->mqtt_packet_id + 1;
-    platform_mutex_unlock(&c->mqtt_global_lock);
+    pika_platform_thread_mutex_unlock(&c->mqtt_global_lock);
     return c->mqtt_packet_id;
 }
 
@@ -119,7 +119,7 @@ exit:
 }
 
 static void mqtt_packet_drain(mqtt_client_t* c,
-                              platform_timer_t* timer,
+                              pika_platform_timer_t* timer,
                               int packet_len) {
     int total_bytes_read = 0, read_len = 0, bytes2read = 0;
 
@@ -131,7 +131,7 @@ static void mqtt_packet_drain(mqtt_client_t* c,
 
     do {
         read_len = network_read(c->mqtt_network, c->mqtt_read_buf, bytes2read,
-                                platform_timer_remain(timer));
+                                pika_platform_timer_remain(timer));
         if (0 != read_len) {
             total_bytes_read += read_len;
             if ((packet_len - total_bytes_read) >= c->mqtt_read_buf_size) {
@@ -146,7 +146,7 @@ static void mqtt_packet_drain(mqtt_client_t* c,
 
 static int mqtt_read_packet(mqtt_client_t* c,
                             int* packet_type,
-                            platform_timer_t* timer) {
+                            pika_platform_timer_t* timer) {
     MQTTHeader header = {0};
     int rc;
     int len = 1;
@@ -155,17 +155,17 @@ static int mqtt_read_packet(mqtt_client_t* c,
     if (NULL == packet_type)
         RETURN_ERROR(MQTT_NULL_VALUE_ERROR);
 
-    platform_timer_init(timer);
-    platform_timer_cutdown(timer, c->mqtt_cmd_timeout);
+    pika_platform_timer_init(timer);
+    pika_platform_timer_cutdown(timer, c->mqtt_cmd_timeout);
 
     /* 1. read the header byte.  This has the packet type in it */
     rc = network_read(c->mqtt_network, c->mqtt_read_buf, len,
-                      platform_timer_remain(timer));
+                      pika_platform_timer_remain(timer));
     if (rc != len)
         RETURN_ERROR(MQTT_NOTHING_TO_READ_ERROR);
 
     /* 2. read the remaining length.  This is variable in itself */
-    mqtt_decode_packet(c, &remain_len, platform_timer_remain(timer));
+    mqtt_decode_packet(c, &remain_len, pika_platform_timer_remain(timer));
 
     /* put the original remaining length back into the buffer */
     len += MQTTPacket_encode(c->mqtt_read_buf + len, remain_len);
@@ -181,39 +181,39 @@ static int mqtt_read_packet(mqtt_client_t* c,
      * data */
     if ((remain_len > 0) &&
         ((rc = network_read(c->mqtt_network, c->mqtt_read_buf + len, remain_len,
-                            platform_timer_remain(timer))) != remain_len))
+                            pika_platform_timer_remain(timer))) != remain_len))
         RETURN_ERROR(MQTT_NOTHING_TO_READ_ERROR);
 
     header.byte = c->mqtt_read_buf[0];
     *packet_type = header.bits.type;
 
-    platform_timer_cutdown(&c->mqtt_last_received,
-                           (c->mqtt_keep_alive_interval * 1000));
+    pika_platform_timer_cutdown(&c->mqtt_last_received,
+                                (c->mqtt_keep_alive_interval * 1000));
 
     RETURN_ERROR(MQTT_SUCCESS_ERROR);
 }
 
 static int mqtt_send_packet(mqtt_client_t* c,
                             int length,
-                            platform_timer_t* timer) {
+                            pika_platform_timer_t* timer) {
     int len = 0;
     int sent = 0;
 
-    platform_timer_init(timer);
-    platform_timer_cutdown(timer, c->mqtt_cmd_timeout);
+    pika_platform_timer_init(timer);
+    pika_platform_timer_cutdown(timer, c->mqtt_cmd_timeout);
 
     /* send mqtt packet in a blocking manner or exit when it timer is expired */
-    while ((sent < length) && (!platform_timer_is_expired(timer))) {
+    while ((sent < length) && (!pika_platform_timer_is_expired(timer))) {
         len = network_write(c->mqtt_network, &c->mqtt_write_buf[sent], length,
-                            platform_timer_remain(timer));
+                            pika_platform_timer_remain(timer));
         if (len <= 0)  // there was an error writing the data
             break;
         sent += len;
     }
 
     if (sent == length) {
-        platform_timer_cutdown(&c->mqtt_last_sent,
-                               (c->mqtt_keep_alive_interval * 1000));
+        pika_platform_timer_cutdown(&c->mqtt_last_sent,
+                                    (c->mqtt_keep_alive_interval * 1000));
         RETURN_ERROR(MQTT_SUCCESS_ERROR);
     }
 
@@ -337,8 +337,8 @@ static ack_handlers_t* mqtt_ack_handler_create(mqtt_client_t* c,
         return NULL;
 
     mqtt_list_init(&ack_handler->list);
-    platform_timer_init(&ack_handler->timer);
-    platform_timer_cutdown(
+    pika_platform_timer_init(&ack_handler->timer);
+    pika_platform_timer_cutdown(
         &ack_handler->timer,
         c->mqtt_cmd_timeout); /* No response within timeout will be destroyed or
                                  resent */
@@ -364,19 +364,19 @@ static void mqtt_ack_handler_destroy(ack_handlers_t* ack_handler) {
 
 static void mqtt_ack_handler_resend(mqtt_client_t* c,
                                     ack_handlers_t* ack_handler) {
-    platform_timer_t timer;
-    platform_timer_init(&timer);
-    platform_timer_cutdown(&timer, c->mqtt_cmd_timeout);
-    platform_timer_cutdown(&ack_handler->timer,
-                           c->mqtt_cmd_timeout); /* timeout, recutdown */
+    pika_platform_timer_t timer;
+    pika_platform_timer_init(&timer);
+    pika_platform_timer_cutdown(&timer, c->mqtt_cmd_timeout);
+    pika_platform_timer_cutdown(&ack_handler->timer,
+                                c->mqtt_cmd_timeout); /* timeout, recutdown */
 
-    platform_mutex_lock(&c->mqtt_write_lock);
+    pika_platform_thread_mutex_lock(&c->mqtt_write_lock);
     memcpy(
         c->mqtt_write_buf, ack_handler->payload,
         ack_handler->payload_len); /* copy data to write buf form ack handler */
 
     mqtt_send_packet(c, ack_handler->payload_len, &timer); /* resend data */
-    platform_mutex_unlock(&c->mqtt_write_lock);
+    pika_platform_thread_mutex_unlock(&c->mqtt_write_lock);
     MQTT_LOG_W("%s:%d %s()... resend %d package, packet_id is %d ", __FILE__,
                __LINE__, __FUNCTION__, ack_handler->type,
                ack_handler->packet_id);
@@ -585,7 +585,8 @@ static void mqtt_ack_list_scan(mqtt_client_t* c, uint8_t flag) {
     LIST_FOR_EACH_SAFE(curr, next, &c->mqtt_ack_handler_list) {
         ack_handler = LIST_ENTRY(curr, ack_handlers_t, list);
 
-        if ((!platform_timer_is_expired(&ack_handler->timer)) && (flag == 1))
+        if ((!pika_platform_timer_is_expired(&ack_handler->timer)) &&
+            (flag == 1))
             continue;
 
         if ((ack_handler->type == PUBACK) || (ack_handler->type == PUBREC) ||
@@ -630,9 +631,10 @@ static int mqtt_try_resubscribe(mqtt_client_t* c) {
         /* resubscribe topic */
         if ((rc = mqtt_subscribe(c, msg_handler->topic_filter, msg_handler->qos,
                                  msg_handler->handler)) ==
-            MQTT_ACK_HANDLER_NUM_TOO_MUCH_ERROR)
+            MQTT_ACK_HANDLER_NUM_TOO_MUCH_ERROR) {
             MQTT_LOG_W("%s:%d %s()... mqtt ack handler num too much ...",
                        __FILE__, __LINE__, __FUNCTION__);
+        }
     }
 
     RETURN_ERROR(rc);
@@ -682,11 +684,11 @@ static int mqtt_publish_ack_packet(mqtt_client_t* c,
                                    int packet_type) {
     int len = 0;
     int rc = MQTT_SUCCESS_ERROR;
-    platform_timer_t timer;
-    platform_timer_init(&timer);
-    platform_timer_cutdown(&timer, c->mqtt_cmd_timeout);
+    pika_platform_timer_t timer;
+    pika_platform_timer_init(&timer);
+    pika_platform_timer_cutdown(&timer, c->mqtt_cmd_timeout);
 
-    platform_mutex_lock(&c->mqtt_write_lock);
+    pika_platform_thread_mutex_lock(&c->mqtt_write_lock);
 
     switch (packet_type) {
         case PUBREC:
@@ -719,13 +721,13 @@ static int mqtt_publish_ack_packet(mqtt_client_t* c,
     rc = mqtt_send_packet(c, len, &timer);
 
 exit:
-    platform_mutex_unlock(&c->mqtt_write_lock);
+    pika_platform_thread_mutex_unlock(&c->mqtt_write_lock);
 
     RETURN_ERROR(rc);
 }
 
 static int mqtt_puback_and_pubcomp_packet_handle(mqtt_client_t* c,
-                                                 platform_timer_t* timer) {
+                                                 pika_platform_timer_t* timer) {
     int rc = MQTT_FAILED_ERROR;
     uint16_t packet_id;
     uint8_t dup, packet_type;
@@ -746,7 +748,7 @@ static int mqtt_puback_and_pubcomp_packet_handle(mqtt_client_t* c,
 }
 
 static int mqtt_suback_packet_handle(mqtt_client_t* c,
-                                     platform_timer_t* timer) {
+                                     pika_platform_timer_t* timer) {
     int rc = MQTT_FAILED_ERROR;
     int count = 0;
     int granted_qos = 0;
@@ -783,7 +785,7 @@ static int mqtt_suback_packet_handle(mqtt_client_t* c,
 }
 
 static int mqtt_unsuback_packet_handle(mqtt_client_t* c,
-                                       platform_timer_t* timer) {
+                                       pika_platform_timer_t* timer) {
     int rc = MQTT_FAILED_ERROR;
     message_handlers_t* msg_handler = NULL;
     uint16_t packet_id = 0;
@@ -809,7 +811,7 @@ static int mqtt_unsuback_packet_handle(mqtt_client_t* c,
 }
 
 static int mqtt_publish_packet_handle(mqtt_client_t* c,
-                                      platform_timer_t* timer) {
+                                      pika_platform_timer_t* timer) {
     int len = 0, rc = MQTT_SUCCESS_ERROR;
     MQTTString topic_name;
     mqtt_message_t msg;
@@ -830,7 +832,7 @@ static int mqtt_publish_packet_handle(mqtt_client_t* c,
 
     /* for qos1 and qos2, you need to send a ack packet */
     if (msg.qos != QOS0) {
-        platform_mutex_lock(&c->mqtt_write_lock);
+        pika_platform_thread_mutex_lock(&c->mqtt_write_lock);
 
         if (msg.qos == QOS1)
             len = MQTTSerialize_ack(c->mqtt_write_buf, c->mqtt_write_buf_size,
@@ -844,7 +846,7 @@ static int mqtt_publish_packet_handle(mqtt_client_t* c,
         else
             rc = mqtt_send_packet(c, len, timer);
 
-        platform_mutex_unlock(&c->mqtt_write_lock);
+        pika_platform_thread_mutex_unlock(&c->mqtt_write_lock);
     }
 
     if (rc < 0)
@@ -864,7 +866,7 @@ static int mqtt_publish_packet_handle(mqtt_client_t* c,
 }
 
 static int mqtt_pubrec_and_pubrel_packet_handle(mqtt_client_t* c,
-                                                platform_timer_t* timer) {
+                                                pika_platform_timer_t* timer) {
     int rc = MQTT_FAILED_ERROR;
     uint16_t packet_id;
     uint8_t dup, packet_type;
@@ -885,7 +887,7 @@ static int mqtt_pubrec_and_pubrel_packet_handle(mqtt_client_t* c,
     RETURN_ERROR(rc);
 }
 
-static int mqtt_packet_handle(mqtt_client_t* c, platform_timer_t* timer) {
+static int mqtt_packet_handle(mqtt_client_t* c, pika_platform_timer_t* timer) {
     int rc = MQTT_SUCCESS_ERROR;
     int packet_type = 0;
 
@@ -947,11 +949,11 @@ exit:
 
 static int mqtt_wait_packet(mqtt_client_t* c,
                             int packet_type,
-                            platform_timer_t* timer) {
+                            pika_platform_timer_t* timer) {
     int rc = MQTT_FAILED_ERROR;
 
     do {
-        if (platform_timer_is_expired(timer))
+        if (pika_platform_timer_is_expired(timer))
             break;
         rc = mqtt_packet_handle(c, timer);
     } while (rc != packet_type && rc >= 0);
@@ -962,7 +964,7 @@ static int mqtt_wait_packet(mqtt_client_t* c,
 static int mqtt_yield(mqtt_client_t* c, int timeout_ms) {
     int rc = MQTT_SUCCESS_ERROR;
     client_state_t state;
-    platform_timer_t timer;
+    pika_platform_timer_t timer;
 
     if (NULL == c)
         RETURN_ERROR(MQTT_FAILED_ERROR);
@@ -970,10 +972,10 @@ static int mqtt_yield(mqtt_client_t* c, int timeout_ms) {
     if (0 == timeout_ms)
         timeout_ms = c->mqtt_cmd_timeout;
 
-    platform_timer_init(&timer);
-    platform_timer_cutdown(&timer, timeout_ms);
+    pika_platform_timer_init(&timer);
+    pika_platform_timer_cutdown(&timer, timeout_ms);
 
-    while (!platform_timer_is_expired(&timer)) {
+    while (!pika_platform_timer_is_expired(&timer)) {
         state = mqtt_get_client_state(c);
         if (CLIENT_STATE_CLEAN_SESSION == state) {
             RETURN_ERROR(MQTT_CLEAN_SESSION_ERROR);
@@ -995,7 +997,7 @@ static int mqtt_yield(mqtt_client_t* c, int timeout_ms) {
             mqtt_ack_list_scan(c, 1);
 
         } else if (MQTT_NOT_CONNECT_ERROR == rc) {
-            MQTT_LOG_E("%s:%d %s()... mqtt not connect", __FILE__, __LINE__,
+            MQTT_LOG_W("%s:%d %s()... mqtt not connect", __FILE__, __LINE__,
                        __FUNCTION__);
         } else {
             break;
@@ -1009,20 +1011,20 @@ static void mqtt_yield_thread(void* arg) {
     int rc;
     client_state_t state;
     mqtt_client_t* c = (mqtt_client_t*)arg;
-    platform_thread_t* thread_to_be_destoried = NULL;
+    pika_platform_thread_t* thread_to_be_destoried = NULL;
 
     state = mqtt_get_client_state(c);
     if (CLIENT_STATE_CONNECTED != state) {
         MQTT_LOG_W("%s:%d %s()..., mqtt is not connected to the server...",
                    __FILE__, __LINE__, __FUNCTION__);
-        platform_thread_stop(c->mqtt_thread); /* mqtt is not connected to the
-                                                 server, stop thread */
+        pika_platform_thread_stop(c->mqtt_thread); /* mqtt is not connected to
+                                                 the server, stop thread */
     }
 
     while (1) {
         rc = mqtt_yield(c, c->mqtt_cmd_timeout);
         if (MQTT_CLEAN_SESSION_ERROR == rc) {
-            MQTT_LOG_W("%s:%d %s()..., mqtt clean session....", __FILE__,
+            MQTT_LOG_I("%s:%d %s()..., mqtt clean session....", __FILE__,
                        __LINE__, __FUNCTION__);
             network_disconnect(c->mqtt_network);
             mqtt_clean_session(c);
@@ -1035,14 +1037,14 @@ static void mqtt_yield_thread(void* arg) {
 
 exit:
     thread_to_be_destoried = c->mqtt_thread;
-    c->mqtt_thread = (platform_thread_t*)0;
-    platform_thread_destroy(thread_to_be_destoried);
+    c->mqtt_thread = (pika_platform_thread_t*)0;
+    pika_platform_thread_destroy(thread_to_be_destoried);
 }
 
 static int mqtt_connect_with_results(mqtt_client_t* c) {
     int len = 0;
     int rc = MQTT_CONNECT_FAILED_ERROR;
-    platform_timer_t connect_timer;
+    pika_platform_timer_t connect_timer;
     mqtt_connack_data_t connack_data = {0};
     MQTTPacket_connectData connect_data = MQTTPacket_connectData_initializer;
 
@@ -1084,17 +1086,17 @@ static int mqtt_connect_with_results(mqtt_client_t* c) {
         connect_data.will.topicName.cstring = c->mqtt_will_options->will_topic;
     }
 
-    platform_timer_cutdown(&c->mqtt_last_received,
-                           (c->mqtt_keep_alive_interval * 1000));
+    pika_platform_timer_cutdown(&c->mqtt_last_received,
+                                (c->mqtt_keep_alive_interval * 1000));
 
-    platform_mutex_lock(&c->mqtt_write_lock);
+    pika_platform_thread_mutex_lock(&c->mqtt_write_lock);
 
     /* serialize connect packet */
     if ((len = MQTTSerialize_connect(c->mqtt_write_buf, c->mqtt_write_buf_size,
                                      &connect_data)) <= 0)
         goto exit;
 
-    platform_timer_cutdown(&connect_timer, c->mqtt_cmd_timeout);
+    pika_platform_timer_cutdown(&connect_timer, c->mqtt_cmd_timeout);
 
     /* send connect packet */
     if ((rc = mqtt_send_packet(c, len, &connect_timer)) != MQTT_SUCCESS_ERROR)
@@ -1114,14 +1116,14 @@ exit:
     if (rc == MQTT_SUCCESS_ERROR) {
         if (NULL == c->mqtt_thread) {
             /* connect success, and need init mqtt thread */
-            c->mqtt_thread = platform_thread_init(
+            c->mqtt_thread = pika_platform_thread_init(
                 "mqtt_yield_thread", mqtt_yield_thread, c,
                 MQTT_THREAD_STACK_SIZE, MQTT_THREAD_PRIO, MQTT_THREAD_TICK);
 
             if (NULL != c->mqtt_thread) {
                 mqtt_set_client_state(c, CLIENT_STATE_CONNECTED);
-                platform_thread_startup(c->mqtt_thread);
-                platform_thread_start(
+                pika_platform_thread_startup(c->mqtt_thread);
+                pika_platform_thread_start(
                     c->mqtt_thread); /* start run mqtt thread */
             } else {
                 /*creat the thread fail and disconnect the mqtt socket connect*/
@@ -1143,7 +1145,7 @@ exit:
         mqtt_set_client_state(c, CLIENT_STATE_INITIALIZED); /* connect failed */
     }
 
-    platform_mutex_unlock(&c->mqtt_write_lock);
+    pika_platform_thread_mutex_unlock(&c->mqtt_write_lock);
 
     RETURN_ERROR(rc);
 }
@@ -1168,6 +1170,7 @@ static uint32_t mqtt_read_buf_malloc(mqtt_client_t* c, uint32_t size) {
                    __LINE__, __FUNCTION__);
         RETURN_ERROR(MQTT_MEM_NOT_ENOUGH_ERROR);
     }
+    memset(c->mqtt_read_buf, 0, c->mqtt_read_buf_size);  // 清空申请的内存
     return c->mqtt_read_buf_size;
 }
 
@@ -1231,11 +1234,11 @@ static int mqtt_init(mqtt_client_t* c) {
     mqtt_list_init(&c->mqtt_msg_handler_list);
     mqtt_list_init(&c->mqtt_ack_handler_list);
 
-    platform_mutex_init(&c->mqtt_write_lock);
-    platform_mutex_init(&c->mqtt_global_lock);
+    pika_platform_thread_mutex_init(&c->mqtt_write_lock);
+    pika_platform_thread_mutex_init(&c->mqtt_global_lock);
 
-    platform_timer_init(&c->mqtt_last_sent);
-    platform_timer_init(&c->mqtt_last_received);
+    pika_platform_timer_init(&c->mqtt_last_sent);
+    pika_platform_timer_init(&c->mqtt_last_received);
 
     RETURN_ERROR(MQTT_SUCCESS_ERROR);
 }
@@ -1268,7 +1271,7 @@ uint32_t mqtt_set_write_buf_size(mqtt_client_t* c, uint32_t size) {
 }
 
 void mqtt_sleep_ms(int ms) {
-    platform_timer_usleep(ms * 1000);
+    pika_platform_timer_usleep(ms * 1000);
 }
 
 int mqtt_keep_alive(mqtt_client_t* c) {
@@ -1278,8 +1281,8 @@ int mqtt_keep_alive(mqtt_client_t* c) {
     if (MQTT_SUCCESS_ERROR != rc)
         RETURN_ERROR(rc);
 
-    if (platform_timer_is_expired(&c->mqtt_last_sent) ||
-        platform_timer_is_expired(&c->mqtt_last_received)) {
+    if (pika_platform_timer_is_expired(&c->mqtt_last_sent) ||
+        pika_platform_timer_is_expired(&c->mqtt_last_received)) {
         if (c->mqtt_ping_outstanding) {
             MQTT_LOG_W("%s:%d %s()... ping outstanding", __FILE__, __LINE__,
                        __FUNCTION__);
@@ -1290,7 +1293,7 @@ int mqtt_keep_alive(mqtt_client_t* c) {
             rc = MQTT_NOT_CONNECT_ERROR; /* PINGRESP not received in keepalive
                                             interval */
         } else {
-            platform_timer_t timer;
+            pika_platform_timer_t timer;
             int len = MQTTSerialize_pingreq(c->mqtt_write_buf,
                                             c->mqtt_write_buf_size);
             if (len > 0)
@@ -1321,19 +1324,19 @@ mqtt_client_t* mqtt_lease(void) {
 }
 
 int mqtt_release(mqtt_client_t* c) {
-    platform_timer_t timer;
+    pika_platform_timer_t timer;
 
     if (NULL == c)
         RETURN_ERROR(MQTT_NULL_VALUE_ERROR);
 
-    platform_timer_init(&timer);
-    platform_timer_cutdown(&timer, c->mqtt_cmd_timeout);
+    pika_platform_timer_init(&timer);
+    pika_platform_timer_cutdown(&timer, c->mqtt_cmd_timeout);
 
     /* wait for the clean session to complete */
     while ((CLIENT_STATE_INVALID != mqtt_get_client_state(c))) {
-        // platform_timer_usleep(1000);            // 1ms avoid compiler
+        // pika_platform_timer_usleep(1000);            // 1ms avoid compiler
         // optimization.
-        if (platform_timer_is_expired(&timer)) {
+        if (pika_platform_timer_is_expired(&timer)) {
             MQTT_LOG_E("%s:%d %s()... mqtt release failed...", __FILE__,
                        __LINE__, __FUNCTION__);
             RETURN_ERROR(MQTT_FAILED_ERROR)
@@ -1355,8 +1358,8 @@ int mqtt_release(mqtt_client_t* c) {
         c->mqtt_write_buf = NULL;
     }
 
-    platform_mutex_destroy(&c->mqtt_write_lock);
-    platform_mutex_destroy(&c->mqtt_global_lock);
+    pika_platform_thread_mutex_destroy(&c->mqtt_write_lock);
+    pika_platform_thread_mutex_destroy(&c->mqtt_global_lock);
 
     memset(c, 0, sizeof(mqtt_client_t));
 
@@ -1370,20 +1373,20 @@ int mqtt_connect(mqtt_client_t* c) {
 
 int mqtt_disconnect(mqtt_client_t* c) {
     int rc = MQTT_FAILED_ERROR;
-    platform_timer_t timer;
+    pika_platform_timer_t timer;
     int len = 0;
 
-    platform_timer_init(&timer);
-    platform_timer_cutdown(&timer, c->mqtt_cmd_timeout);
+    pika_platform_timer_init(&timer);
+    pika_platform_timer_cutdown(&timer, c->mqtt_cmd_timeout);
 
-    platform_mutex_lock(&c->mqtt_write_lock);
+    pika_platform_thread_mutex_lock(&c->mqtt_write_lock);
 
     /* serialize disconnect packet and send it */
     len = MQTTSerialize_disconnect(c->mqtt_write_buf, c->mqtt_write_buf_size);
     if (len > 0)
         rc = mqtt_send_packet(c, len, &timer);
 
-    platform_mutex_unlock(&c->mqtt_write_lock);
+    pika_platform_thread_mutex_unlock(&c->mqtt_write_lock);
 
     mqtt_set_client_state(c, CLIENT_STATE_CLEAN_SESSION);
 
@@ -1397,7 +1400,7 @@ int mqtt_subscribe(mqtt_client_t* c,
     int rc = MQTT_SUBSCRIBE_ERROR;
     int len = 0;
     uint16_t packet_id;
-    platform_timer_t timer;
+    pika_platform_timer_t timer;
     MQTTString topic = MQTTString_initializer;
     topic.cstring = (char*)topic_filter;
     message_handlers_t* msg_handler = NULL;
@@ -1405,7 +1408,7 @@ int mqtt_subscribe(mqtt_client_t* c,
     if (CLIENT_STATE_CONNECTED != mqtt_get_client_state(c))
         RETURN_ERROR(MQTT_NOT_CONNECT_ERROR);
 
-    platform_mutex_lock(&c->mqtt_write_lock);
+    pika_platform_thread_mutex_lock(&c->mqtt_write_lock);
 
     packet_id = mqtt_get_next_packet_id(c);
 
@@ -1433,7 +1436,7 @@ int mqtt_subscribe(mqtt_client_t* c,
 
 exit:
 
-    platform_mutex_unlock(&c->mqtt_write_lock);
+    pika_platform_thread_mutex_unlock(&c->mqtt_write_lock);
 
     RETURN_ERROR(rc);
 }
@@ -1442,7 +1445,7 @@ int mqtt_unsubscribe(mqtt_client_t* c, const char* topic_filter) {
     int len = 0;
     int rc = MQTT_FAILED_ERROR;
     uint16_t packet_id;
-    platform_timer_t timer;
+    pika_platform_timer_t timer;
     MQTTString topic = MQTTString_initializer;
     topic.cstring = (char*)topic_filter;
     message_handlers_t* msg_handler = NULL;
@@ -1450,7 +1453,7 @@ int mqtt_unsubscribe(mqtt_client_t* c, const char* topic_filter) {
     if (CLIENT_STATE_CONNECTED != mqtt_get_client_state(c))
         RETURN_ERROR(MQTT_NOT_CONNECT_ERROR);
 
-    platform_mutex_lock(&c->mqtt_write_lock);
+    pika_platform_thread_mutex_lock(&c->mqtt_write_lock);
 
     packet_id = mqtt_get_next_packet_id(c);
 
@@ -1473,7 +1476,7 @@ int mqtt_unsubscribe(mqtt_client_t* c, const char* topic_filter) {
 
 exit:
 
-    platform_mutex_unlock(&c->mqtt_write_lock);
+    pika_platform_thread_mutex_unlock(&c->mqtt_write_lock);
 
     RETURN_ERROR(rc);
 }
@@ -1483,7 +1486,7 @@ int mqtt_publish(mqtt_client_t* c,
                  mqtt_message_t* msg) {
     int len = 0;
     int rc = MQTT_FAILED_ERROR;
-    platform_timer_t timer;
+    pika_platform_timer_t timer;
     MQTTString topic = MQTTString_initializer;
     topic.cstring = (char*)topic_filter;
 
@@ -1503,7 +1506,7 @@ int mqtt_publish(mqtt_client_t* c,
         RETURN_ERROR(MQTT_BUFFER_TOO_SHORT_ERROR);
     }
 
-    platform_mutex_lock(&c->mqtt_write_lock);
+    pika_platform_thread_mutex_lock(&c->mqtt_write_lock);
 
     if (QOS0 != msg->qos) {
         if (mqtt_ack_handler_is_maximum(c)) {
@@ -1542,7 +1545,7 @@ int mqtt_publish(mqtt_client_t* c,
 exit:
     msg->payloadlen = 0;  // clear
 
-    platform_mutex_unlock(&c->mqtt_write_lock);
+    pika_platform_thread_mutex_unlock(&c->mqtt_write_lock);
 
     if ((MQTT_ACK_HANDLER_NUM_TOO_MUCH_ERROR == rc) ||
         (MQTT_MEM_NOT_ENOUGH_ERROR == rc)) {
@@ -1562,16 +1565,17 @@ exit:
 }
 
 int mqtt_list_subscribe_topic(mqtt_client_t* c) {
-    int i = 0;
+    // int i = 0;
     mqtt_list_t *curr, *next;
     message_handlers_t* msg_handler;
 
     if (NULL == c)
         RETURN_ERROR(MQTT_NULL_VALUE_ERROR);
 
-    if (mqtt_list_is_empty(&c->mqtt_msg_handler_list))
+    if (mqtt_list_is_empty(&c->mqtt_msg_handler_list)) {
         MQTT_LOG_I("%s:%d %s()... there are no subscribed topics...", __FILE__,
                    __LINE__, __FUNCTION__);
+    }
 
     LIST_FOR_EACH_SAFE(curr, next, &c->mqtt_msg_handler_list) {
         msg_handler = LIST_ENTRY(curr, message_handlers_t, list);
@@ -1612,13 +1616,26 @@ int mqtt_set_will_options(mqtt_client_t* c,
 }
 
 int mqtt_release_free(mqtt_client_t* c) {
-    /* wait for mqtt thread exit */
+    // wait for mqtt thread exit
     while (c->mqtt_thread != NULL) {
     }
+
+    /*
+    if(c->mqtt_thread != NULL) {
+        MQTT_LOG("%s:%d %s()..., mqtt mqtt_yield_thread release...",
+                   __FILE__, __LINE__, __FUNCTION__);
+        pika_platform_thread_stop(c->mqtt_thread); //stop thread
+        network_disconnect(c->mqtt_network);
+        mqtt_clean_session(c);
+    }
+    */
     if (CLIENT_STATE_INVALID != mqtt_get_client_state(c)) {
         mqtt_clean_session(c);
     }
+
+    MQTT_LOG_I("%s:%d %s() 1", __FILE__, __LINE__, __FUNCTION__);
     mqtt_release(c);
+    MQTT_LOG_I("%s:%d %s() 2", __FILE__, __LINE__, __FUNCTION__);
     platform_memory_free(c);
     return 0;
 }

+ 7 - 9
package/mqtt/mqttclient.h

@@ -20,9 +20,6 @@
 #include "mqtt_log.h"
 #include "network.h"
 #include "platform_memory.h"
-#include "platform_mutex.h"
-#include "platform_thread.h"
-#include "platform_timer.h"
 #include "random.h"
 
 #ifdef __cplusplus
@@ -76,7 +73,7 @@ typedef struct message_handlers {
 
 typedef struct ack_handlers {
     mqtt_list_t list;
-    platform_timer_t timer;
+    pika_platform_timer_t timer;
     uint32_t type;
     uint16_t packet_id;
     message_handlers_t* handler;
@@ -117,16 +114,17 @@ typedef struct mqtt_client {
     size_t mqtt_password_len;
     mqtt_will_options_t* mqtt_will_options;
     client_state_t mqtt_client_state;
-    platform_mutex_t mqtt_write_lock;
-    platform_mutex_t mqtt_global_lock;
+    pika_platform_thread_mutex_t mqtt_write_lock;
+    pika_platform_thread_mutex_t mqtt_global_lock;
     mqtt_list_t mqtt_msg_handler_list;
     mqtt_list_t mqtt_ack_handler_list;
     network_t* mqtt_network;
-    platform_thread_t* mqtt_thread;
-    platform_timer_t mqtt_last_sent;
-    platform_timer_t mqtt_last_received;
+    pika_platform_thread_t* mqtt_thread;
+    pika_platform_timer_t mqtt_last_sent;
+    pika_platform_timer_t mqtt_last_received;
     reconnect_handler_t mqtt_reconnect_handler;
     interceptor_handler_t mqtt_interceptor_handler;
+    void* user_data;
 } mqtt_client_t;
 
 #define MQTT_ROBUSTNESS_CHECK(item, err)                                 \

+ 6 - 7
package/mqtt/nettype_tls.c

@@ -8,7 +8,6 @@
 #include "nettype_tls.h"
 #include "platform_net_socket.h"
 #include "platform_memory.h"
-#include "platform_timer.h"
 #include "random.h"
 
 #ifndef MQTT_NETWORK_TYPE_NO_TLS
@@ -200,14 +199,14 @@ int nettype_tls_write(network_t *n, unsigned char *buf, int len, int timeout)
 {
     int rc = 0;
     int write_len = 0;
-    platform_timer_t timer;
+    pika_platform_timer_t timer;
 
     if (NULL == n)
         RETURN_ERROR(MQTT_NULL_VALUE_ERROR);
     
     nettype_tls_params_t *nettype_tls_params = (nettype_tls_params_t *) n->nettype_tls_params;
 
-    platform_timer_cutdown(&timer, timeout);
+    pika_platform_timer_cutdown(&timer, timeout);
 
     do {
         rc = mbedtls_ssl_write(&(nettype_tls_params->ssl), (unsigned char *)(buf + write_len), len - write_len);
@@ -218,7 +217,7 @@ int nettype_tls_write(network_t *n, unsigned char *buf, int len, int timeout)
             MQTT_LOG_E("%s:%d %s()... mbedtls_ssl_write failed: 0x%04x", __FILE__, __LINE__, __FUNCTION__, (rc < 0 )? -rc : rc);
             break;
         } 
-    } while((!platform_timer_is_expired(&timer)) && (write_len < len));
+    } while((!pika_platform_timer_is_expired(&timer)) && (write_len < len));
 
     return write_len;
 }
@@ -227,14 +226,14 @@ int nettype_tls_read(network_t *n, unsigned char *buf, int len, int timeout)
 {
     int rc = 0;
     int read_len = 0;
-    platform_timer_t timer;
+    pika_platform_timer_t timer;
 
     if (NULL == n)
         RETURN_ERROR(MQTT_NULL_VALUE_ERROR);
     
     nettype_tls_params_t *nettype_tls_params = (nettype_tls_params_t *) n->nettype_tls_params;
 
-    platform_timer_cutdown(&timer, timeout);
+    pika_platform_timer_cutdown(&timer, timeout);
     
     do {
         rc = mbedtls_ssl_read(&(nettype_tls_params->ssl), (unsigned char *)(buf + read_len), len - read_len);
@@ -245,7 +244,7 @@ int nettype_tls_read(network_t *n, unsigned char *buf, int len, int timeout)
             // MQTT_LOG_E("%s:%d %s()... mbedtls_ssl_read failed: 0x%04x", __FILE__, __LINE__, __FUNCTION__, (rc < 0 )? -rc : rc);
             break;
         } 
-    } while((!platform_timer_is_expired(&timer)) && (read_len < len));
+    } while((!pika_platform_timer_is_expired(&timer)) && (read_len < len));
 
     return read_len;
 }

+ 0 - 1
package/mqtt/network.c

@@ -6,7 +6,6 @@
  * @Description: the code belongs to jiejie, please keep the author information and source code according to the license.
  */
 #include <string.h>
-#include "platform_timer.h"
 #include "platform_memory.h"
 #include "nettype_tcp.h"
 

+ 0 - 61
package/mqtt/platform_mutex.c

@@ -1,61 +0,0 @@
-/*
- * @Author: jiejie
- * @Github: https://github.com/jiejieTop
- * @Date: 2019-12-15 18:27:19
- * @LastEditTime: 2020-02-23 15:01:06
- * @Description: the code belongs to jiejie, please keep the author information
- * and source code according to the license.
- */
-#include "platform_mutex.h"
-
-PIKA_WEAK int platform_mutex_init(platform_mutex_t* m) {
-#ifdef __linux
-    return pthread_mutex_init(&(m->mutex), NULL);
-#elif PIKA_FREERTOS_ENABLE
-    m->mutex = xSemaphoreCreateMutex();
-    return 0;
-#else
-    WEAK_FUNCTION_NEED_OVERRIDE_ERROR();
-#endif
-}
-
-PIKA_WEAK int platform_mutex_lock(platform_mutex_t* m) {
-#ifdef __linux
-    return pthread_mutex_lock(&(m->mutex));
-#elif PIKA_FREERTOS_ENABLE
-    return xSemaphoreTake(m->mutex, portMAX_DELAY);
-#else
-    WEAK_FUNCTION_NEED_OVERRIDE_ERROR();
-#endif
-}
-
-PIKA_WEAK int platform_mutex_trylock(platform_mutex_t* m) {
-#ifdef __linux
-    return pthread_mutex_trylock(&(m->mutex));
-#elif PIKA_FREERTOS_ENABLE
-    return xSemaphoreTake(m->mutex, 0);
-#else
-    WEAK_FUNCTION_NEED_OVERRIDE_ERROR();
-#endif
-}
-
-int platform_mutex_unlock(platform_mutex_t* m) {
-#ifdef __linux
-    return pthread_mutex_unlock(&(m->mutex));
-#elif PIKA_FREERTOS_ENABLE
-    return xSemaphoreGive(m->mutex);
-#else
-    WEAK_FUNCTION_NEED_OVERRIDE_ERROR();
-#endif
-}
-
-int platform_mutex_destroy(platform_mutex_t* m) {
-#ifdef __linux
-    return pthread_mutex_destroy(&(m->mutex));
-#elif PIKA_FREERTOS_ENABLE
-    vSemaphoreDelete(m->mutex);
-    return 0;
-#else
-    WEAK_FUNCTION_NEED_OVERRIDE_ERROR();
-#endif
-}

+ 0 - 47
package/mqtt/platform_mutex.h

@@ -1,47 +0,0 @@
-/*
- * @Author: jiejie
- * @Github: https://github.com/jiejieTop
- * @Date: 2019-12-15 18:31:33
- * @LastEditTime: 2020-10-17 14:17:31
- * @Description: the code belongs to jiejie, please keep the author information
- * and source code according to the license.
- */
-#ifndef _PLATFORM_MUTEX_H_
-#define _PLATFORM_MUTEX_H_
-#include "PikaObj.h"
-#ifdef __linux
-    #include <pthread.h>
-    typedef struct platform_mutex {
-        pthread_mutex_t mutex;
-    } platform_mutex_t;
-#elif PIKA_FREERTOS_ENABLE
-    #include "freertos/FreeRTOS.h"
-    #include "freertos/semphr.h"
-    typedef struct platform_mutex {
-        SemaphoreHandle_t mutex;
-    } platform_mutex_t;
-#else
-    /*
-        You need to create the __platform_thread.h for your platform.
-        For example:
-        You can #include <rtthread.h> in the __platform_thread.h
-    */
-    #include "__platform_thread.h"
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-int platform_mutex_init(platform_mutex_t* m);
-int platform_mutex_lock(platform_mutex_t* m);
-int platform_mutex_trylock(platform_mutex_t* m);
-int platform_mutex_unlock(platform_mutex_t* m);
-int platform_mutex_destroy(platform_mutex_t* m);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif

+ 0 - 98
package/mqtt/platform_thread.c

@@ -1,98 +0,0 @@
-/*
- * @Author: jiejie
- * @Github: https://github.com/jiejieTop
- * @Date: 2019-12-23 19:26:27
- * @LastEditTime: 2020-02-23 16:19:07
- * @Description: the code belongs to jiejie, please keep the author information
- * and source code according to the license.
- */
-#include "platform_thread.h"
-#include "platform_memory.h"
-
-PIKA_WEAK platform_thread_t* platform_thread_init(const char* name,
-                                                  void (*entry)(void*),
-                                                  void* const param,
-                                                  unsigned int stack_size,
-                                                  unsigned int priority,
-                                                  unsigned int tick) {
-#ifdef __linux
-    int res;
-    platform_thread_t* thread;
-    void* (*thread_entry)(void*);
-
-    thread_entry = (void* (*)(void*))entry;
-    thread = platform_memory_alloc(sizeof(platform_thread_t));
-
-    res = pthread_create(&thread->thread, NULL, thread_entry, param);
-    if (res != 0) {
-        platform_memory_free(thread);
-    }
-
-    thread->mutex = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER;
-    thread->cond = (pthread_cond_t)PTHREAD_COND_INITIALIZER;
-
-    return thread;
-#elif PIKA_FREERTOS_ENABLE
-    BaseType_t err;
-    platform_thread_t* thread;
-
-    thread = platform_memory_alloc(sizeof(platform_thread_t));
-
-    (void)tick;
-
-    err = xTaskCreate(entry, name, stack_size, param, priority, thread->thread);
-
-    if (pdPASS != err) {
-        platform_memory_free(thread);
-        return NULL;
-    }
-
-    return thread;
-#else
-    WEAK_FUNCTION_NEED_OVERRIDE_ERROR();
-#endif
-}
-
-PIKA_WEAK void platform_thread_startup(platform_thread_t* thread) {
-    (void)thread;
-}
-
-PIKA_WEAK void platform_thread_stop(platform_thread_t* thread) {
-#ifdef __linux
-    pthread_mutex_lock(&(thread->mutex));
-    pthread_cond_wait(&(thread->cond), &(thread->mutex));
-    pthread_mutex_unlock(&(thread->mutex));
-#elif PIKA_FREERTOS_ENABLE
-    vTaskSuspend(thread->thread);
-#else
-    WEAK_FUNCTION_NEED_OVERRIDE_ERROR();
-#endif
-}
-
-PIKA_WEAK void platform_thread_start(platform_thread_t* thread) {
-#ifdef __linux
-    pthread_mutex_lock(&(thread->mutex));
-    pthread_cond_signal(&(thread->cond));
-    pthread_mutex_unlock(&(thread->mutex));
-#elif PIKA_FREERTOS_ENABLE
-    vTaskResume(thread->thread);
-#else
-    WEAK_FUNCTION_NEED_OVERRIDE_ERROR();
-#endif
-}
-
-PIKA_WEAK void platform_thread_destroy(platform_thread_t* thread) {
-#ifdef __linux
-    if (NULL != thread){
-        pthread_detach(thread->thread);
-        platform_memory_free(thread);
-        thread = NULL;
-    }
-#elif PIKA_FREERTOS_ENABLE
-    if (NULL != thread)
-        vTaskDelete(thread->thread);
-    platform_memory_free(thread);
-#else
-    WEAK_FUNCTION_NEED_OVERRIDE_ERROR();
-#endif
-}

+ 0 - 54
package/mqtt/platform_thread.h

@@ -1,54 +0,0 @@
-/*
- * @Author: jiejie
- * @Github: https://github.com/jiejieTop
- * @Date: 2019-12-15 18:31:44
- * @LastEditTime: 2020-10-17 14:15:21
- * @Description: the code belongs to jiejie, please keep the author information
- * and source code according to the license.
- */
-#ifndef _PLATFORM_THREAD_H_
-#define _PLATFORM_THREAD_H_
-
-#include "PikaObj.h"
-#ifdef __linux
-#include <pthread.h>
-    typedef struct platform_thread {
-        pthread_t thread;
-        pthread_mutex_t mutex;
-        pthread_cond_t cond;
-    } platform_thread_t;
-#elif PIKA_FREERTOS_ENABLE
-    #include "freertos/FreeRTOS.h"
-    #include "freertos/task.h"
-    typedef struct platform_thread {
-        TaskHandle_t thread;
-    } platform_thread_t;
-#else
-/*
-    You need to create the __platform_thread.h for your platform.
-    For example:
-    You can #include <rtthread.h> in the __platform_thread.h
-*/
-#include "__platform_thread.h"
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-platform_thread_t* platform_thread_init(const char* name,
-                                        void (*entry)(void*),
-                                        void* const param,
-                                        unsigned int stack_size,
-                                        unsigned int priority,
-                                        unsigned int tick);
-void platform_thread_startup(platform_thread_t* thread);
-void platform_thread_stop(platform_thread_t* thread);
-void platform_thread_start(platform_thread_t* thread);
-void platform_thread_destroy(platform_thread_t* thread);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif

+ 0 - 107
package/mqtt/platform_timer.c

@@ -1,107 +0,0 @@
-/*
- * @Author: jiejie
- * @Github: https://github.com/jiejieTop
- * @Date: 2019-12-10 22:16:41
- * @LastEditTime: 2020-06-05 17:18:48
- * @Description: the code belongs to jiejie, please keep the author information
- * and source code according to the license.
- */
-
-#include "platform_timer.h"
-
-#if PIKA_FREERTOS_ENABLE
-static uint32_t platform_uptime_ms(void)
-{
-#if (configTICK_RATE_HZ == 1000)
-    return (uint32_t)xTaskGetTickCount();
-#else
-    TickType_t tick = 0u;
-
-    tick = xTaskGetTickCount() * 1000;
-    return (uint32_t)((tick + configTICK_RATE_HZ - 1) / configTICK_RATE_HZ);
-#endif
-}
-#endif
-
-PIKA_WEAK void platform_timer_init(platform_timer_t* timer) {
-#ifdef __linux
-    timer->time = (struct timeval){0, 0};
-#elif PIKA_FREERTOS_ENABLE
-    timer->time = 0;
-#else
-    WEAK_FUNCTION_NEED_OVERRIDE_ERROR();
-#endif
-}
-
-PIKA_WEAK void platform_timer_cutdown(platform_timer_t* timer,
-                                      unsigned int timeout) {
-#ifdef __linux
-    struct timeval now;
-    gettimeofday(&now, NULL);
-    struct timeval interval = {timeout / 1000, (timeout % 1000) * 1000};
-    timeradd(&now, &interval, &timer->time);
-#elif PIKA_FREERTOS_ENABLE
-    timer->time = platform_uptime_ms();
-    timer->time += timeout;
-#else
-    WEAK_FUNCTION_NEED_OVERRIDE_ERROR();
-#endif
-}
-
-PIKA_WEAK char platform_timer_is_expired(platform_timer_t* timer) {
-#ifdef __linux
-    struct timeval now, res;
-    gettimeofday(&now, NULL);
-    timersub(&timer->time, &now, &res);
-    return ((res.tv_sec < 0) || (res.tv_sec == 0 && res.tv_usec <= 0));
-#elif PIKA_FREERTOS_ENABLE
-    return platform_uptime_ms() > timer->time ? 1 : 0;
-#else
-    WEAK_FUNCTION_NEED_OVERRIDE_ERROR();
-#endif
-}
-
-PIKA_WEAK int platform_timer_remain(platform_timer_t* timer) {
-#ifdef __linux
-    struct timeval now, res;
-    gettimeofday(&now, NULL);
-    timersub(&timer->time, &now, &res);
-    return (res.tv_sec < 0) ? 0 : res.tv_sec * 1000 + res.tv_usec / 1000;
-#elif PIKA_FREERTOS_ENABLE
-    uint32_t now;
-    now = platform_uptime_ms();
-    if (timer->time <= now) {
-        return 0;
-    }
-    return timer->time - now;
-#else
-    WEAK_FUNCTION_NEED_OVERRIDE_ERROR();
-#endif
-}
-
-PIKA_WEAK unsigned long platform_timer_now(void) {
-#ifdef __linux
-    return (unsigned long)time(NULL);
-#elif PIKA_FREERTOS_ENABLE
-    return (unsigned long)platform_uptime_ms();
-#else
-    WEAK_FUNCTION_NEED_OVERRIDE_ERROR();
-#endif
-}
-
-PIKA_WEAK void platform_timer_usleep(unsigned long usec) {
-#ifdef __linux
-    usleep(usec);
-#elif PIKA_FREERTOS_ENABLE
-    TickType_t tick = 1;
-    if (usec != 0) {
-        tick = usec / portTICK_PERIOD_MS;
-
-        if (tick == 0)
-            tick = 1;
-    }
-    vTaskDelay(tick);
-#else
-    WEAK_FUNCTION_NEED_OVERRIDE_ERROR();
-#endif
-}

+ 0 - 49
package/mqtt/platform_timer.h

@@ -1,49 +0,0 @@
-/*
- * @Author: jiejie
- * @Github: https://github.com/jiejieTop
- * @Date: 2019-12-10 22:18:32
- * @LastEditTime: 2020-10-17 14:17:55
- * @Description: the code belongs to jiejie, please keep the author information
- * and source code according to the license.
- */
-#ifndef _PLATFORM_TIMER_H_
-#define _PLATFORM_TIMER_H_
-
-#include <stdio.h>
-#include "PikaObj.h"
-#ifdef __linux
-    #include <sys/time.h>
-    typedef struct platform_timer {
-        struct timeval time;
-    } platform_timer_t;
-#elif PIKA_FREERTOS_ENABLE
-    #include "freertos/FreeRTOS.h"
-    #include "freertos/task.h"
-    typedef struct platform_timer {
-        uint32_t time;
-    } platform_timer_t;
-#else
-    /*
-        You need to create the __platform_timer.h for your platform.
-    */
-    #include "__platform_time.h"
-#endif
-#include <time.h>
-#include <unistd.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-void platform_timer_init(platform_timer_t* timer);
-void platform_timer_cutdown(platform_timer_t* timer, unsigned int timeout);
-char platform_timer_is_expired(platform_timer_t* timer);
-int platform_timer_remain(platform_timer_t* timer);
-unsigned long platform_timer_now(void);
-void platform_timer_usleep(unsigned long usec);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif

+ 3 - 3
package/mqtt/random.c

@@ -11,11 +11,11 @@
 #include <stdlib.h>
 #include "random.h"
 
-extern int platform_timer_now();
+extern int pika_platform_timer_now();
 static unsigned int last_seed = 1;
 
 
-int __attribute__((weak)) platform_timer_now()
+int __attribute__((weak)) pika_platform_timer_now()
 {
     return 1;
 }
@@ -28,7 +28,7 @@ static int do_random(unsigned int seed)
 
 int random_number(void)
 {
-    unsigned int seed = (unsigned int) platform_timer_now();
+    unsigned int seed = (unsigned int) pika_platform_timer_now();
     last_seed += (seed >> ((seed ^ last_seed) % 3));
     return do_random(last_seed ^ seed);
 }

+ 3 - 0
package/pika_libc/README.md

@@ -0,0 +1,3 @@
+# Usage
+
+Cancel all  `__platform_xxprintf()` and `__platform_xxsprintf()`, then add `__platform_putchar()` .

+ 0 - 0
package/pika_libc/pika_libc.pyi


+ 1268 - 0
package/pika_libc/pika_vsnprintf.c

@@ -0,0 +1,1268 @@
+/*
+ * Copyright (c) 2021, Meco Jianting Man <jiantingman@foxmail.com>
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2021-11-27     Meco Man     porting for rt_vsnprintf as the fully functional
+ * version
+ */
+
+/**
+ * @author (c) Eyal Rozenberg <eyalroz1@gmx.com>
+ *             2021, Haifa, Palestine/Israel
+ * @author (c) Marco Paland (info@paland.com)
+ *             2014-2019, PALANDesign Hannover, Germany
+ *
+ * @note Others have made smaller contributions to this file: see the
+ * contributors page at https://github.com/eyalroz/printf/graphs/contributors
+ * or ask one of the authors.
+ *
+ * @brief Small stand-alone implementation of the printf family of functions
+ * (`(v)printf`, `(v)s(n)printf` etc., geared towards use on embedded systems
+ * with a very limited resources.
+ *
+ * @note the implementations are thread-safe; re-entrant; use no functions from
+ * the standard library; and do not dynamically allocate any memory.
+ *
+ * @license The MIT License (MIT)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+#include "pika_adapter_rtt.h"
+
+// 'ntoa' conversion buffer size, this must be big enough to hold one converted
+// numeric number including padded zeros (dynamically created on stack)
+#ifndef PRINTF_INTEGER_BUFFER_SIZE
+#define PRINTF_INTEGER_BUFFER_SIZE 32
+#endif
+
+// 'ftoa' conversion buffer size, this must be big enough to hold one converted
+// float number including padded zeros (dynamically created on stack)
+#ifndef PRINTF_FTOA_BUFFER_SIZE
+#define PRINTF_FTOA_BUFFER_SIZE 32
+#endif
+
+// Support for the decimal notation floating point conversion specifiers (%f,
+// %F)
+#ifndef PRINTF_SUPPORT_DECIMAL_SPECIFIERS
+#define PRINTF_SUPPORT_DECIMAL_SPECIFIERS 1
+#endif
+
+// Support for the exponential notatin floating point conversion specifiers (%e,
+// %g, %E, %G)
+#ifndef PRINTF_SUPPORT_EXPONENTIAL_SPECIFIERS
+#define PRINTF_SUPPORT_EXPONENTIAL_SPECIFIERS 1
+#endif
+
+// Default precision for the floating point conversion specifiers (the C
+// standard sets this at 6)
+#ifndef PRINTF_DEFAULT_FLOAT_PRECISION
+#define PRINTF_DEFAULT_FLOAT_PRECISION 6
+#endif
+
+// According to the C languages standard, printf() and related functions must be
+// able to print any integral number in floating-point notation, regardless of
+// length, when using the %f specifier - possibly hundreds of characters,
+// potentially overflowing your buffers. In this implementation, all values
+// beyond this threshold are switched to exponential notation.
+#ifndef PRINTF_MAX_INTEGRAL_DIGITS_FOR_DECIMAL
+#define PRINTF_MAX_INTEGRAL_DIGITS_FOR_DECIMAL 9
+#endif
+
+// Support for the long long integral types (with the ll, z and t length
+// modifiers for specifiers %d,%i,%o,%x,%X,%u, and with the %p specifier). Note:
+// 'L' (long double) is not supported.
+#ifndef PRINTF_SUPPORT_LONG_LONG
+#define PRINTF_SUPPORT_LONG_LONG 1
+#endif
+
+#if PRINTF_SUPPORT_LONG_LONG
+typedef unsigned long long printf_unsigned_value_t;
+typedef long long printf_signed_value_t;
+#else
+typedef unsigned long printf_unsigned_value_t;
+typedef long printf_signed_value_t;
+#endif
+
+#define PRINTF_PREFER_DECIMAL false
+#define PRINTF_PREFER_EXPONENTIAL true
+
+///////////////////////////////////////////////////////////////////////////////
+
+// The following will convert the number-of-digits into an exponential-notation
+// literal
+#define PRINTF_CONCATENATE(s1, s2) s1##s2
+#define PRINTF_EXPAND_THEN_CONCATENATE(s1, s2) PRINTF_CONCATENATE(s1, s2)
+#define PRINTF_FLOAT_NOTATION_THRESHOLD \
+    PRINTF_EXPAND_THEN_CONCATENATE(1e, PRINTF_MAX_INTEGRAL_DIGITS_FOR_DECIMAL)
+
+// internal flag definitions
+#define FLAGS_ZEROPAD (1U << 0U)
+#define FLAGS_LEFT (1U << 1U)
+#define FLAGS_PLUS (1U << 2U)
+#define FLAGS_SPACE (1U << 3U)
+#define FLAGS_HASH (1U << 4U)
+#define FLAGS_UPPERCASE (1U << 5U)
+#define FLAGS_CHAR (1U << 6U)
+#define FLAGS_SHORT (1U << 7U)
+#define FLAGS_LONG (1U << 8U)
+#define FLAGS_LONG_LONG (1U << 9U)
+#define FLAGS_PRECISION (1U << 10U)
+#define FLAGS_ADAPT_EXP (1U << 11U)
+#define FLAGS_POINTER (1U << 12U)
+// Note: Similar, but not identical, effect as FLAGS_HASH
+
+#define BASE_BINARY 2
+#define BASE_OCTAL 8
+#define BASE_DECIMAL 10
+#define BASE_HEX 16
+
+typedef uint8_t numeric_base_t;
+
+#if (PRINTF_SUPPORT_DECIMAL_SPECIFIERS || PRINTF_SUPPORT_EXPONENTIAL_SPECIFIERS)
+#include <float.h>
+#if FLT_RADIX != 2
+#error "Non-binary-radix floating-point types are unsupported."
+#endif
+
+#if DBL_MANT_DIG == 24
+
+#define DOUBLE_SIZE_IN_BITS 32
+typedef uint32_t double_uint_t;
+#define DOUBLE_EXPONENT_MASK 0xFFU
+#define DOUBLE_BASE_EXPONENT 127
+
+#elif DBL_MANT_DIG == 53
+
+#define DOUBLE_SIZE_IN_BITS 64
+typedef uint64_t double_uint_t;
+#define DOUBLE_EXPONENT_MASK 0x7FFU
+#define DOUBLE_BASE_EXPONENT 1023
+
+#else
+#error "Unsupported double type configuration"
+#endif
+#define DOUBLE_STORED_MANTISSA_BITS (DBL_MANT_DIG - 1)
+
+typedef union {
+    double_uint_t U;
+    double F;
+} double_with_bit_access;
+
+// This is unnecessary in C99, since compound initializers can be used,
+// but: 1. Some compilers are finicky about this; 2. Some people may want to
+// convert this to C89;
+// 3. If you try to use it as C++, only C++20 supports compound literals
+static inline double_with_bit_access get_bit_access(double x) {
+    double_with_bit_access dwba;
+    dwba.F = x;
+    return dwba;
+}
+
+static inline int get_sign(double x) {
+    // The sign is stored in the highest bit
+    return get_bit_access(x).U >> (DOUBLE_SIZE_IN_BITS - 1);
+}
+
+static inline int get_exp2(double_with_bit_access x) {
+    // The exponent in an IEEE-754 floating-point number occupies a contiguous
+    // sequence of bits (e.g. 52..62 for 64-bit doubles), but with a non-trivial
+    // representation: An unsigned offset from some negative value (with the
+    // extremal offset values reserved for special use).
+    return (int)((x.U >> DOUBLE_STORED_MANTISSA_BITS) & DOUBLE_EXPONENT_MASK) -
+           DOUBLE_BASE_EXPONENT;
+}
+#define PRINTF_ABS(_x) ((_x) > 0 ? (_x) : -(_x))
+
+#endif  // (PRINTF_SUPPORT_DECIMAL_SPECIFIERS ||
+        // PRINTF_SUPPORT_EXPONENTIAL_SPECIFIERS)
+
+// Note in particular the behavior here on LONG_MIN or LLONG_MIN; it is valid
+// and well-defined, but if you're not careful you can easily trigger undefined
+// behavior with -LONG_MIN or -LLONG_MIN
+#define ABS_FOR_PRINTING(_x) \
+    ((printf_unsigned_value_t)((_x) > 0 ? (_x) : -((printf_signed_value_t)_x)))
+
+// output function type
+typedef void (*out_fct_type)(char character,
+                             void* buffer,
+                             size_t idx,
+                             size_t maxlen);
+
+// wrapper (used as buffer) for output function type
+typedef struct {
+    void (*fct)(char character, void* arg);
+    void* arg;
+} out_function_wrapper_type;
+
+// internal buffer output
+static inline void out_buffer(char character,
+                              void* buffer,
+                              size_t idx,
+                              size_t maxlen) {
+    if (idx < maxlen) {
+        ((char*)buffer)[idx] = character;
+    }
+}
+
+// internal null output
+static inline void out_discard(char character,
+                               void* buffer,
+                               size_t idx,
+                               size_t maxlen) {
+    (void)character;
+    (void)buffer;
+    (void)idx;
+    (void)maxlen;
+}
+
+// internal secure strlen
+// @return The length of the string (excluding the terminating 0) limited by
+// 'maxsize'
+static inline unsigned int strnlen_s_(const char* str, size_t maxsize) {
+    const char* s;
+    for (s = str; *s && maxsize--; ++s)
+        ;
+    return (unsigned int)(s - str);
+}
+
+// internal test if char is a digit (0-9)
+// @return true if char is a digit
+static inline bool is_digit_(char ch) {
+    return (ch >= '0') && (ch <= '9');
+}
+
+// internal ASCII string to unsigned int conversion
+static unsigned int atoi_(const char** str) {
+    unsigned int i = 0U;
+    while (is_digit_(**str)) {
+        i = i * 10U + (unsigned int)(*((*str)++) - '0');
+    }
+    return i;
+}
+
+// output the specified string in reverse, taking care of any zero-padding
+static size_t out_rev_(out_fct_type out,
+                       char* buffer,
+                       size_t idx,
+                       size_t maxlen,
+                       const char* buf,
+                       size_t len,
+                       unsigned int width,
+                       unsigned int flags) {
+    const size_t start_idx = idx;
+
+    // pad spaces up to given width
+    if (!(flags & FLAGS_LEFT) && !(flags & FLAGS_ZEROPAD)) {
+        for (size_t i = len; i < width; i++) {
+            out(' ', buffer, idx++, maxlen);
+        }
+    }
+
+    // reverse string
+    while (len) {
+        out(buf[--len], buffer, idx++, maxlen);
+    }
+
+    // append pad spaces up to given width
+    if (flags & FLAGS_LEFT) {
+        while (idx - start_idx < width) {
+            out(' ', buffer, idx++, maxlen);
+        }
+    }
+
+    return idx;
+}
+
+// Invoked by print_integer after the actual number has been printed, performing
+// necessary work on the number's prefix (as the number is initially printed in
+// reverse order)
+static size_t print_integer_finalization(out_fct_type out,
+                                         char* buffer,
+                                         size_t idx,
+                                         size_t maxlen,
+                                         char* buf,
+                                         size_t len,
+                                         bool negative,
+                                         numeric_base_t base,
+                                         unsigned int precision,
+                                         unsigned int width,
+                                         unsigned int flags) {
+    size_t unpadded_len = len;
+
+    // pad with leading zeros
+    {
+        if (!(flags & FLAGS_LEFT)) {
+            if (width && (flags & FLAGS_ZEROPAD) &&
+                (negative || (flags & (FLAGS_PLUS | FLAGS_SPACE)))) {
+                width--;
+            }
+            while ((flags & FLAGS_ZEROPAD) && (len < width) &&
+                   (len < PRINTF_INTEGER_BUFFER_SIZE)) {
+                buf[len++] = '0';
+            }
+        }
+
+        while ((len < precision) && (len < PRINTF_INTEGER_BUFFER_SIZE)) {
+            buf[len++] = '0';
+        }
+
+        if (base == BASE_OCTAL && (len > unpadded_len)) {
+            // Since we've written some zeros, we've satisfied the alternative
+            // format leading space requirement
+            flags &= ~FLAGS_HASH;
+        }
+    }
+
+    // handle hash
+    if (flags & (FLAGS_HASH | FLAGS_POINTER)) {
+        if (!(flags & FLAGS_PRECISION) && len &&
+            ((len == precision) || (len == width))) {
+            // Let's take back some padding digits to fit in what will
+            // eventually be the format-specific prefix
+            if (unpadded_len < len) {
+                len--;
+            }
+            if (len && (base == BASE_HEX)) {
+                if (unpadded_len < len) {
+                    len--;
+                }
+            }
+        }
+        if ((base == BASE_HEX) && !(flags & FLAGS_UPPERCASE) &&
+            (len < PRINTF_INTEGER_BUFFER_SIZE)) {
+            buf[len++] = 'x';
+        } else if ((base == BASE_HEX) && (flags & FLAGS_UPPERCASE) &&
+                   (len < PRINTF_INTEGER_BUFFER_SIZE)) {
+            buf[len++] = 'X';
+        } else if ((base == BASE_BINARY) &&
+                   (len < PRINTF_INTEGER_BUFFER_SIZE)) {
+            buf[len++] = 'b';
+        }
+        if (len < PRINTF_INTEGER_BUFFER_SIZE) {
+            buf[len++] = '0';
+        }
+    }
+
+    if (len < PRINTF_INTEGER_BUFFER_SIZE) {
+        if (negative) {
+            buf[len++] = '-';
+        } else if (flags & FLAGS_PLUS) {
+            buf[len++] = '+';  // ignore the space if the '+' exists
+        } else if (flags & FLAGS_SPACE) {
+            buf[len++] = ' ';
+        }
+    }
+
+    return out_rev_(out, buffer, idx, maxlen, buf, len, width, flags);
+}
+
+// An internal itoa-like function
+static size_t print_integer(out_fct_type out,
+                            char* buffer,
+                            size_t idx,
+                            size_t maxlen,
+                            printf_unsigned_value_t value,
+                            bool negative,
+                            numeric_base_t base,
+                            unsigned int precision,
+                            unsigned int width,
+                            unsigned int flags) {
+    char buf[PRINTF_INTEGER_BUFFER_SIZE];
+    size_t len = 0U;
+
+    if (!value) {
+        if (!(flags & FLAGS_PRECISION)) {
+            buf[len++] = '0';
+            flags &= ~FLAGS_HASH;
+            // We drop this flag this since either the alternative and regular
+            // modes of the specifier don't differ on 0 values, or (in the case
+            // of octal) we've already provided the special handling for this
+            // mode.
+        } else if (base == BASE_HEX) {
+            flags &= ~FLAGS_HASH;
+            // We drop this flag this since either the alternative and regular
+            // modes of the specifier don't differ on 0 values
+        }
+    } else {
+        do {
+            const char digit = (char)(value % base);
+            buf[len++] =
+                (char)(digit < 10 ? '0' + digit
+                                  : (flags & FLAGS_UPPERCASE ? 'A' : 'a') +
+                                        digit - 10);
+            value /= base;
+        } while (value && (len < PRINTF_INTEGER_BUFFER_SIZE));
+    }
+
+    return print_integer_finalization(out, buffer, idx, maxlen, buf, len,
+                                      negative, base, precision, width, flags);
+}
+
+#if (PRINTF_SUPPORT_DECIMAL_SPECIFIERS || PRINTF_SUPPORT_EXPONENTIAL_SPECIFIERS)
+
+struct double_components {
+    int_fast64_t integral;
+    int_fast64_t fractional;
+    bool is_negative;
+};
+
+#define NUM_DECIMAL_DIGITS_IN_INT64_T 18
+#define PRINTF_MAX_PRECOMPUTED_POWER_OF_10 NUM_DECIMAL_DIGITS_IN_INT64_T
+static const double powers_of_10[NUM_DECIMAL_DIGITS_IN_INT64_T] = {
+    1e00, 1e01, 1e02, 1e03, 1e04, 1e05, 1e06, 1e07, 1e08,
+    1e09, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17};
+
+#define PRINTF_MAX_SUPPORTED_PRECISION NUM_DECIMAL_DIGITS_IN_INT64_T - 1
+
+// Break up a double number - which is known to be a finite non-negative number
+// - into its base-10 parts: integral - before the decimal point, and fractional
+// - after it. Taken the precision into account, but does not change it even
+// internally.
+static struct double_components get_components(double number,
+                                               unsigned int precision) {
+    struct double_components number_;
+    number_.is_negative = get_sign(number);
+    double abs_number = (number_.is_negative) ? -number : number;
+    number_.integral = (int_fast64_t)abs_number;
+    double remainder =
+        (abs_number - number_.integral) * powers_of_10[precision];
+    number_.fractional = (int_fast64_t)remainder;
+
+    remainder -= (double)number_.fractional;
+
+    if (remainder > 0.5) {
+        ++number_.fractional;
+        // handle rollover, e.g. case 0.99 with precision 1 is 1.0
+        if ((double)number_.fractional >= powers_of_10[precision]) {
+            number_.fractional = 0;
+            ++number_.integral;
+        }
+    } else if (remainder == 0.5) {
+        if ((number_.fractional == 0U) || (number_.fractional & 1U)) {
+            // if halfway, round up if odd OR if last digit is 0
+            ++number_.fractional;
+        }
+    }
+
+    if (precision == 0U) {
+        remainder = abs_number - (double)number_.integral;
+        if ((!(remainder < 0.5) || (remainder > 0.5)) &&
+            (number_.integral & 1)) {
+            // exactly 0.5 and ODD, then round up
+            // 1.5 -> 2, but 2.5 -> 2
+            ++number_.integral;
+        }
+    }
+    return number_;
+}
+
+struct scaling_factor {
+    double raw_factor;
+    bool multiply;  // if true, need to multiply by raw_factor; otherwise need
+                    // to divide by it
+};
+
+double apply_scaling(double num, struct scaling_factor normalization) {
+    return normalization.multiply ? num * normalization.raw_factor
+                                  : num / normalization.raw_factor;
+}
+
+double unapply_scaling(double normalized, struct scaling_factor normalization) {
+    return normalization.multiply ? normalized / normalization.raw_factor
+                                  : normalized * normalization.raw_factor;
+}
+
+struct scaling_factor update_normalization(struct scaling_factor sf,
+                                           double extra_multiplicative_factor) {
+    struct scaling_factor result;
+    if (sf.multiply) {
+        result.multiply = true;
+        result.raw_factor = sf.raw_factor * extra_multiplicative_factor;
+    } else {
+        int factor_exp2 = get_exp2(get_bit_access(sf.raw_factor));
+        int extra_factor_exp2 =
+            get_exp2(get_bit_access(extra_multiplicative_factor));
+
+        // Divide the larger-exponent raw raw_factor by the smaller
+        if (PRINTF_ABS(factor_exp2) > PRINTF_ABS(extra_factor_exp2)) {
+            result.multiply = false;
+            result.raw_factor = sf.raw_factor / extra_multiplicative_factor;
+        } else {
+            result.multiply = true;
+            result.raw_factor = extra_multiplicative_factor / sf.raw_factor;
+        }
+    }
+    return result;
+}
+
+#if PRINTF_SUPPORT_EXPONENTIAL_SPECIFIERS
+static struct double_components get_normalized_components(
+    bool negative,
+    unsigned int precision,
+    double non_normalized,
+    struct scaling_factor normalization) {
+    struct double_components components;
+    components.is_negative = negative;
+    components.integral =
+        (int_fast64_t)apply_scaling(non_normalized, normalization);
+    double remainder =
+        non_normalized -
+        unapply_scaling((double)components.integral, normalization);
+    double prec_power_of_10 = powers_of_10[precision];
+    struct scaling_factor account_for_precision =
+        update_normalization(normalization, prec_power_of_10);
+    double scaled_remainder = apply_scaling(remainder, account_for_precision);
+    double rounding_threshold = 0.5;
+
+    if (precision == 0U) {
+        components.fractional = 0;
+        components.integral += (scaled_remainder >= rounding_threshold);
+        if (scaled_remainder == rounding_threshold) {
+            // banker's rounding: Round towards the even number (making the mean
+            // error 0)
+            components.integral &= ~((int_fast64_t)0x1);
+        }
+    } else {
+        components.fractional = (int_fast64_t)scaled_remainder;
+        scaled_remainder -= components.fractional;
+
+        components.fractional += (scaled_remainder >= rounding_threshold);
+        if (scaled_remainder == rounding_threshold) {
+            // banker's rounding: Round towards the even number (making the mean
+            // error 0)
+            components.fractional &= ~((int_fast64_t)0x1);
+        }
+        // handle rollover, e.g. the case of 0.99 with precision 1 becoming
+        // (0,100), and must then be corrected into (1, 0).
+        if ((double)components.fractional >= prec_power_of_10) {
+            components.fractional = 0;
+            ++components.integral;
+        }
+    }
+    return components;
+}
+#endif
+
+static size_t print_broken_up_decimal(struct double_components number_,
+                                      out_fct_type out,
+                                      char* buffer,
+                                      size_t idx,
+                                      size_t maxlen,
+                                      unsigned int precision,
+                                      unsigned int width,
+                                      unsigned int flags,
+                                      char* buf,
+                                      size_t len) {
+    if (precision != 0U) {
+        // do fractional part, as an unsigned number
+
+        unsigned int count = precision;
+
+        if (flags & FLAGS_ADAPT_EXP && !(flags & FLAGS_HASH)) {
+            // %g/%G mandates we skip the trailing 0 digits...
+            if (number_.fractional > 0) {
+                while (true) {
+                    int_fast64_t digit = number_.fractional % 10U;
+                    if (digit != 0) {
+                        break;
+                    }
+                    --count;
+                    number_.fractional /= 10U;
+                }
+            }
+            // ... and even the decimal point if there are no
+            // non-zero fractional part digits (see below)
+        }
+
+        if (number_.fractional > 0 || !(flags & FLAGS_ADAPT_EXP) ||
+            (flags & FLAGS_HASH)) {
+            while (len < PRINTF_FTOA_BUFFER_SIZE) {
+                --count;
+                buf[len++] = (char)('0' + number_.fractional % 10U);
+                if (!(number_.fractional /= 10U)) {
+                    break;
+                }
+            }
+            // add extra 0s
+            while ((len < PRINTF_FTOA_BUFFER_SIZE) && (count-- > 0U)) {
+                buf[len++] = '0';
+            }
+            if (len < PRINTF_FTOA_BUFFER_SIZE) {
+                buf[len++] = '.';
+            }
+        }
+    } else {
+        if (flags & FLAGS_HASH) {
+            if (len < PRINTF_FTOA_BUFFER_SIZE) {
+                buf[len++] = '.';
+            }
+        }
+    }
+
+    // Write the integer part of the number (it comes after the fractional
+    // since the character order is reversed)
+    while (len < PRINTF_FTOA_BUFFER_SIZE) {
+        buf[len++] = (char)('0' + (number_.integral % 10));
+        if (!(number_.integral /= 10)) {
+            break;
+        }
+    }
+
+    // pad leading zeros
+    if (!(flags & FLAGS_LEFT) && (flags & FLAGS_ZEROPAD)) {
+        if (width &&
+            (number_.is_negative || (flags & (FLAGS_PLUS | FLAGS_SPACE)))) {
+            width--;
+        }
+        while ((len < width) && (len < PRINTF_FTOA_BUFFER_SIZE)) {
+            buf[len++] = '0';
+        }
+    }
+
+    if (len < PRINTF_FTOA_BUFFER_SIZE) {
+        if (number_.is_negative) {
+            buf[len++] = '-';
+        } else if (flags & FLAGS_PLUS) {
+            buf[len++] = '+';  // ignore the space if the '+' exists
+        } else if (flags & FLAGS_SPACE) {
+            buf[len++] = ' ';
+        }
+    }
+
+    return out_rev_(out, buffer, idx, maxlen, buf, len, width, flags);
+}
+
+// internal ftoa for fixed decimal floating point
+static size_t print_decimal_number(out_fct_type out,
+                                   char* buffer,
+                                   size_t idx,
+                                   size_t maxlen,
+                                   double number,
+                                   unsigned int precision,
+                                   unsigned int width,
+                                   unsigned int flags,
+                                   char* buf,
+                                   size_t len) {
+    struct double_components value_ = get_components(number, precision);
+    return print_broken_up_decimal(value_, out, buffer, idx, maxlen, precision,
+                                   width, flags, buf, len);
+}
+
+#if PRINTF_SUPPORT_EXPONENTIAL_SPECIFIERS
+// internal ftoa variant for exponential floating-point type, contributed by
+// Martijn Jasperse <m.jasperse@gmail.com>
+static size_t print_exponential_number(out_fct_type out,
+                                       char* buffer,
+                                       size_t idx,
+                                       size_t maxlen,
+                                       double number,
+                                       unsigned int precision,
+                                       unsigned int width,
+                                       unsigned int flags,
+                                       char* buf,
+                                       size_t len) {
+    const bool negative = get_sign(number);
+    // This number will decrease gradually (by factors of 10) as we "extract"
+    // the exponent out of it
+    double abs_number = negative ? -number : number;
+
+    int exp10;
+    bool abs_exp10_covered_by_powers_table;
+    struct scaling_factor normalization;
+
+    // Determine the decimal exponent
+    if (abs_number == 0.0) {
+        // TODO: This is a special-case for 0.0 (and -0.0); but proper handling
+        // is required for denormals more generally.
+        exp10 = 0;  // ... and no need to set a normalization factor or check
+                    // the powers table
+    } else {
+        double_with_bit_access conv = get_bit_access(abs_number);
+        {
+            // based on the algorithm by David Gay
+            // (https://www.ampl.com/netlib/fp/dtoa.c)
+            int exp2 = get_exp2(conv);
+            // drop the exponent, so conv.F comes into the range [1,2)
+            conv.U =
+                (conv.U &
+                 (((double_uint_t)(1) << DOUBLE_STORED_MANTISSA_BITS) - 1U)) |
+                ((double_uint_t)DOUBLE_BASE_EXPONENT
+                 << DOUBLE_STORED_MANTISSA_BITS);
+            // now approximate log10 from the log2 integer part and an expansion
+            // of ln around 1.5
+            exp10 = (int)(0.1760912590558 + exp2 * 0.301029995663981 +
+                          (conv.F - 1.5) * 0.289529654602168);
+            // now we want to compute 10^exp10 but we want to be sure it won't
+            // overflow
+            exp2 = (int)(exp10 * 3.321928094887362 + 0.5);
+            const double z =
+                exp10 * 2.302585092994046 - exp2 * 0.6931471805599453;
+            const double z2 = z * z;
+            conv.U = ((double_uint_t)(exp2) + DOUBLE_BASE_EXPONENT)
+                     << DOUBLE_STORED_MANTISSA_BITS;
+            // compute exp(z) using continued fractions, see
+            // https://en.wikipedia.org/wiki/Exponential_function#Continued_fractions_for_ex
+            conv.F *= 1 + 2 * z / (2 - z + (z2 / (6 + (z2 / (10 + z2 / 14)))));
+            // correct for rounding errors
+            if (abs_number < conv.F) {
+                exp10--;
+                conv.F /= 10;
+            }
+        }
+        abs_exp10_covered_by_powers_table =
+            PRINTF_ABS(exp10) < PRINTF_MAX_PRECOMPUTED_POWER_OF_10;
+        normalization.raw_factor = abs_exp10_covered_by_powers_table
+                                       ? powers_of_10[PRINTF_ABS(exp10)]
+                                       : conv.F;
+    }
+
+    // We now begin accounting for the widths of the two parts of our printed
+    // field: the decimal part after decimal exponent extraction, and the
+    // base-10 exponent part. For both of these, the value of 0 has a special
+    // meaning, but not the same one: a 0 exponent-part width means "don't print
+    // the exponent"; a 0 decimal-part width means "use as many characters as
+    // necessary".
+
+    bool fall_back_to_decimal_only_mode = false;
+    if (flags & FLAGS_ADAPT_EXP) {
+        int required_significant_digits = (precision == 0) ? 1 : (int)precision;
+        // Should we want to fall-back to "%f" mode, and only print the decimal
+        // part?
+        fall_back_to_decimal_only_mode =
+            (exp10 >= -4 && exp10 < required_significant_digits);
+        // Now, let's adjust the precision
+        // This also decided how we adjust the precision value - as in "%g"
+        // mode, "precision" is the number of _significant digits_, and this is
+        // when we "translate" the precision value to an actual number of
+        // decimal digits.
+        int precision_ =
+            (fall_back_to_decimal_only_mode)
+                ? (int)precision - 1 - exp10
+                : (int)precision -
+                      1;  // the presence of the exponent ensures only one
+                          // significant digit comes before the decimal point
+        precision = (precision_ > 0 ? (unsigned)precision_ : 0U);
+        flags |= FLAGS_PRECISION;  // make sure print_broken_up_decimal respects
+                                   // our choice above
+    }
+
+    normalization.multiply = (exp10 < 0 && abs_exp10_covered_by_powers_table);
+    bool should_skip_normalization =
+        (fall_back_to_decimal_only_mode || exp10 == 0);
+    struct double_components decimal_part_components =
+        should_skip_normalization
+            ? get_components(negative ? -abs_number : abs_number, precision)
+            : get_normalized_components(negative, precision, abs_number,
+                                        normalization);
+
+    // Account for roll-over, e.g. rounding from 9.99 to 100.0 - which effects
+    // the exponent and may require additional tweaking of the parts
+    if (fall_back_to_decimal_only_mode) {
+        if ((flags & FLAGS_ADAPT_EXP) && exp10 >= -1 &&
+            decimal_part_components.integral == powers_of_10[exp10 + 1]) {
+            exp10++;  // Not strictly necessary, since exp10 is no longer really
+                      // used
+            precision--;
+            // ... and it should already be the case that
+            // decimal_part_components.fractional == 0
+        }
+        // TODO: What about rollover strictly within the fractional part?
+    } else {
+        if (decimal_part_components.integral >= 10) {
+            exp10++;
+            decimal_part_components.integral = 1;
+            decimal_part_components.fractional = 0;
+        }
+    }
+
+    // the exp10 format is "E%+03d" and largest possible exp10 value for a
+    // 64-bit double is "307" (for 2^1023), so we set aside 4-5 characters
+    // overall
+    unsigned int exp10_part_width = fall_back_to_decimal_only_mode ? 0U
+                                    : (PRINTF_ABS(exp10) < 100)    ? 4U
+                                                                   : 5U;
+
+    unsigned int decimal_part_width =
+        ((flags & FLAGS_LEFT) && exp10_part_width)
+            ?
+            // We're padding on the right, so the width constraint is the
+            // exponent part's problem, not the decimal part's, so we'll use as
+            // many characters as we need:
+            0U
+            :
+            // We're padding on the left; so the width constraint is the decimal
+            // part's problem. Well, can both the decimal part and the exponent
+            // part fit within our overall width?
+            ((width > exp10_part_width)
+                 ?
+                 // Yes, so we limit our decimal part's width.
+                 // (Note this is trivially valid even if we've fallen back to
+                 // "%f" mode)
+                 width - exp10_part_width
+                 :
+                 // No; we just give up on any restriction on the decimal part
+                 // and use as many characters as we need
+                 0U);
+
+    const size_t start_idx = idx;
+    idx = print_broken_up_decimal(decimal_part_components, out, buffer, idx,
+                                  maxlen, precision, decimal_part_width, flags,
+                                  buf, len);
+
+    if (!fall_back_to_decimal_only_mode) {
+        out((flags & FLAGS_UPPERCASE) ? 'E' : 'e', buffer, idx++, maxlen);
+        idx = print_integer(out, buffer, idx, maxlen, ABS_FOR_PRINTING(exp10),
+                            exp10 < 0, 10, 0, exp10_part_width - 1,
+                            FLAGS_ZEROPAD | FLAGS_PLUS);
+        if (flags & FLAGS_LEFT) {
+            // We need to right-pad with spaces to meet the width requirement
+            while (idx - start_idx < width)
+                out(' ', buffer, idx++, maxlen);
+        }
+    }
+    return idx;
+}
+#endif  // PRINTF_SUPPORT_EXPONENTIAL_SPECIFIERS
+
+static size_t print_floating_point(out_fct_type out,
+                                   char* buffer,
+                                   size_t idx,
+                                   size_t maxlen,
+                                   double value,
+                                   unsigned int precision,
+                                   unsigned int width,
+                                   unsigned int flags,
+                                   bool prefer_exponential) {
+    char buf[PRINTF_FTOA_BUFFER_SIZE];
+    size_t len = 0U;
+
+    // test for special values
+    if (value != value)
+        return out_rev_(out, buffer, idx, maxlen, "nan", 3, width, flags);
+    if (value < -DBL_MAX)
+        return out_rev_(out, buffer, idx, maxlen, "fni-", 4, width, flags);
+    if (value > DBL_MAX)
+        return out_rev_(out, buffer, idx, maxlen,
+                        (flags & FLAGS_PLUS) ? "fni+" : "fni",
+                        (flags & FLAGS_PLUS) ? 4U : 3U, width, flags);
+
+    if (!prefer_exponential && ((value > PRINTF_FLOAT_NOTATION_THRESHOLD) ||
+                                (value < -PRINTF_FLOAT_NOTATION_THRESHOLD))) {
+        // The required behavior of standard printf is to print _every_
+        // integral-part digit -- which could mean printing hundreds of
+        // characters, overflowing any fixed internal buffer and necessitating a
+        // more complicated implementation.
+#if PRINTF_SUPPORT_EXPONENTIAL_SPECIFIERS
+        return print_exponential_number(out, buffer, idx, maxlen, value,
+                                        precision, width, flags, buf, len);
+#else
+        return 0U;
+#endif
+    }
+
+    // set default precision, if not set explicitly
+    if (!(flags & FLAGS_PRECISION)) {
+        precision = PRINTF_DEFAULT_FLOAT_PRECISION;
+    }
+
+    // limit precision so that our integer holding the fractional part does not
+    // overflow
+    while ((len < PRINTF_FTOA_BUFFER_SIZE) &&
+           (precision > PRINTF_MAX_SUPPORTED_PRECISION)) {
+        buf[len++] =
+            '0';  // This respects the precision in terms of result length only
+        precision--;
+    }
+
+    return
+#if PRINTF_SUPPORT_EXPONENTIAL_SPECIFIERS
+        prefer_exponential
+            ? print_exponential_number(out, buffer, idx, maxlen, value,
+                                       precision, width, flags, buf, len)
+            :
+#endif
+            print_decimal_number(out, buffer, idx, maxlen, value, precision,
+                                 width, flags, buf, len);
+}
+
+#endif  // (PRINTF_SUPPORT_DECIMAL_SPECIFIERS ||
+        // PRINTF_SUPPORT_EXPONENTIAL_SPECIFIERS)
+
+// internal vsnprintf
+static int __vsnprintf(out_fct_type out,
+                       char* buffer,
+                       const size_t maxlen,
+                       const char* format,
+                       va_list va) {
+    unsigned int flags, width, precision, n;
+    size_t idx = 0U;
+
+    if (!buffer) {
+        // use null output function
+        out = out_discard;
+    }
+
+    while (*format) {
+        // format specifier?  %[flags][width][.precision][length]
+        if (*format != '%') {
+            // no
+            out(*format, buffer, idx++, maxlen);
+            format++;
+            continue;
+        } else {
+            // yes, evaluate it
+            format++;
+        }
+
+        // evaluate flags
+        flags = 0U;
+        do {
+            switch (*format) {
+                case '0':
+                    flags |= FLAGS_ZEROPAD;
+                    format++;
+                    n = 1U;
+                    break;
+                case '-':
+                    flags |= FLAGS_LEFT;
+                    format++;
+                    n = 1U;
+                    break;
+                case '+':
+                    flags |= FLAGS_PLUS;
+                    format++;
+                    n = 1U;
+                    break;
+                case ' ':
+                    flags |= FLAGS_SPACE;
+                    format++;
+                    n = 1U;
+                    break;
+                case '#':
+                    flags |= FLAGS_HASH;
+                    format++;
+                    n = 1U;
+                    break;
+                default:
+                    n = 0U;
+                    break;
+            }
+        } while (n);
+
+        // evaluate width field
+        width = 0U;
+        if (is_digit_(*format)) {
+            width = atoi_(&format);
+        } else if (*format == '*') {
+            const int w = va_arg(va, int);
+            if (w < 0) {
+                flags |= FLAGS_LEFT;  // reverse padding
+                width = (unsigned int)-w;
+            } else {
+                width = (unsigned int)w;
+            }
+            format++;
+        }
+
+        // evaluate precision field
+        precision = 0U;
+        if (*format == '.') {
+            flags |= FLAGS_PRECISION;
+            format++;
+            if (is_digit_(*format)) {
+                precision = atoi_(&format);
+            } else if (*format == '*') {
+                const int precision_ = (int)va_arg(va, int);
+                precision = precision_ > 0 ? (unsigned int)precision_ : 0U;
+                format++;
+            }
+        }
+
+        // evaluate length field
+        switch (*format) {
+            case 'l':
+                flags |= FLAGS_LONG;
+                format++;
+                if (*format == 'l') {
+                    flags |= FLAGS_LONG_LONG;
+                    format++;
+                }
+                break;
+            case 'h':
+                flags |= FLAGS_SHORT;
+                format++;
+                if (*format == 'h') {
+                    flags |= FLAGS_CHAR;
+                    format++;
+                }
+                break;
+            case 't':
+                flags |= (sizeof(ptrdiff_t) == sizeof(long) ? FLAGS_LONG
+                                                            : FLAGS_LONG_LONG);
+                format++;
+                break;
+            case 'j':
+                flags |= (sizeof(intmax_t) == sizeof(long) ? FLAGS_LONG
+                                                           : FLAGS_LONG_LONG);
+                format++;
+                break;
+            case 'z':
+                flags |= (sizeof(size_t) == sizeof(long) ? FLAGS_LONG
+                                                         : FLAGS_LONG_LONG);
+                format++;
+                break;
+            default:
+                break;
+        }
+
+        // evaluate specifier
+        switch (*format) {
+            case 'd':
+            case 'i':
+            case 'u':
+            case 'x':
+            case 'X':
+            case 'o':
+            case 'b': {
+                // set the base
+                numeric_base_t base;
+                if (*format == 'x' || *format == 'X') {
+                    base = BASE_HEX;
+                } else if (*format == 'o') {
+                    base = BASE_OCTAL;
+                } else if (*format == 'b') {
+                    base = BASE_BINARY;
+                } else {
+                    base = BASE_DECIMAL;
+                    flags &= ~FLAGS_HASH;  // no hash for dec format
+                }
+                // uppercase
+                if (*format == 'X') {
+                    flags |= FLAGS_UPPERCASE;
+                }
+
+                // no plus or space flag for u, x, X, o, b
+                if ((*format != 'i') && (*format != 'd')) {
+                    flags &= ~(FLAGS_PLUS | FLAGS_SPACE);
+                }
+
+                // ignore '0' flag when precision is given
+                if (flags & FLAGS_PRECISION) {
+                    flags &= ~FLAGS_ZEROPAD;
+                }
+
+                // convert the integer
+                if ((*format == 'i') || (*format == 'd')) {
+                    // signed
+                    if (flags & FLAGS_LONG_LONG) {
+#if PRINTF_SUPPORT_LONG_LONG
+                        const long long value = va_arg(va, long long);
+                        idx = print_integer(out, buffer, idx, maxlen,
+                                            ABS_FOR_PRINTING(value), value < 0,
+                                            base, precision, width, flags);
+#endif
+                    } else if (flags & FLAGS_LONG) {
+                        const long value = va_arg(va, long);
+                        idx = print_integer(out, buffer, idx, maxlen,
+                                            ABS_FOR_PRINTING(value), value < 0,
+                                            base, precision, width, flags);
+                    } else {
+                        const int value =
+                            (flags & FLAGS_CHAR) ? (signed char)va_arg(va, int)
+                            : (flags & FLAGS_SHORT) ? (short int)va_arg(va, int)
+                                                    : va_arg(va, int);
+                        idx = print_integer(out, buffer, idx, maxlen,
+                                            ABS_FOR_PRINTING(value), value < 0,
+                                            base, precision, width, flags);
+                    }
+                } else {
+                    // unsigned
+                    if (flags & FLAGS_LONG_LONG) {
+#if PRINTF_SUPPORT_LONG_LONG
+                        idx =
+                            print_integer(out, buffer, idx, maxlen,
+                                          (printf_unsigned_value_t)va_arg(
+                                              va, unsigned long long),
+                                          false, base, precision, width, flags);
+#endif
+                    } else if (flags & FLAGS_LONG) {
+                        idx = print_integer(
+                            out, buffer, idx, maxlen,
+                            (printf_unsigned_value_t)va_arg(va, unsigned long),
+                            false, base, precision, width, flags);
+                    } else {
+                        const unsigned int value =
+                            (flags & FLAGS_CHAR)
+                                ? (unsigned char)va_arg(va, unsigned int)
+                            : (flags & FLAGS_SHORT)
+                                ? (unsigned short int)va_arg(va, unsigned int)
+                                : va_arg(va, unsigned int);
+                        idx =
+                            print_integer(out, buffer, idx, maxlen,
+                                          (printf_unsigned_value_t)value, false,
+                                          base, precision, width, flags);
+                    }
+                }
+                format++;
+                break;
+            }
+#if PRINTF_SUPPORT_DECIMAL_SPECIFIERS
+            case 'f':
+            case 'F':
+                if (*format == 'F')
+                    flags |= FLAGS_UPPERCASE;
+                idx = print_floating_point(out, buffer, idx, maxlen,
+                                           va_arg(va, double), precision, width,
+                                           flags, PRINTF_PREFER_DECIMAL);
+                format++;
+                break;
+#endif
+#if PRINTF_SUPPORT_EXPONENTIAL_SPECIFIERS
+            case 'e':
+            case 'E':
+            case 'g':
+            case 'G':
+                if ((*format == 'g') || (*format == 'G'))
+                    flags |= FLAGS_ADAPT_EXP;
+                if ((*format == 'E') || (*format == 'G'))
+                    flags |= FLAGS_UPPERCASE;
+                idx = print_floating_point(out, buffer, idx, maxlen,
+                                           va_arg(va, double), precision, width,
+                                           flags, PRINTF_PREFER_EXPONENTIAL);
+                format++;
+                break;
+#endif  // PRINTF_SUPPORT_EXPONENTIAL_SPECIFIERS
+            case 'c': {
+                unsigned int l = 1U;
+                // pre padding
+                if (!(flags & FLAGS_LEFT)) {
+                    while (l++ < width) {
+                        out(' ', buffer, idx++, maxlen);
+                    }
+                }
+                // char output
+                out((char)va_arg(va, int), buffer, idx++, maxlen);
+                // post padding
+                if (flags & FLAGS_LEFT) {
+                    while (l++ < width) {
+                        out(' ', buffer, idx++, maxlen);
+                    }
+                }
+                format++;
+                break;
+            }
+
+            case 's': {
+                const char* p = va_arg(va, char*);
+                if (p == NULL) {
+                    idx = out_rev_(out, buffer, idx, maxlen, ")llun(", 6, width,
+                                   flags);
+                } else {
+                    unsigned int l =
+                        strnlen_s_(p, precision ? precision : (size_t)-1);
+                    // pre padding
+                    if (flags & FLAGS_PRECISION) {
+                        l = (l < precision ? l : precision);
+                    }
+                    if (!(flags & FLAGS_LEFT)) {
+                        while (l++ < width) {
+                            out(' ', buffer, idx++, maxlen);
+                        }
+                    }
+                    // string output
+                    while ((*p != 0) &&
+                           (!(flags & FLAGS_PRECISION) || precision--)) {
+                        out(*(p++), buffer, idx++, maxlen);
+                    }
+                    // post padding
+                    if (flags & FLAGS_LEFT) {
+                        while (l++ < width) {
+                            out(' ', buffer, idx++, maxlen);
+                        }
+                    }
+                }
+                format++;
+                break;
+            }
+
+            case 'p': {
+                width = sizeof(void*) * 2U +
+                        2;  // 2 hex chars per byte + the "0x" prefix
+                flags |= FLAGS_ZEROPAD | FLAGS_POINTER;
+                uintptr_t value = (uintptr_t)va_arg(va, void*);
+                idx = (value == (uintptr_t)NULL)
+                          ? out_rev_(out, buffer, idx, maxlen, ")lin(", 5,
+                                     width, flags)
+                          : print_integer(out, buffer, idx, maxlen,
+                                          (printf_unsigned_value_t)value, false,
+                                          BASE_HEX, precision, width, flags);
+                format++;
+                break;
+            }
+
+            case '%':
+                out('%', buffer, idx++, maxlen);
+                format++;
+                break;
+
+            default:
+                out(*format, buffer, idx++, maxlen);
+                format++;
+                break;
+        }
+    }
+
+    // termination
+    out((char)0, buffer, idx < maxlen ? idx : maxlen - 1U, maxlen);
+
+    // return written chars without terminating \0
+    return (int)idx;
+}
+
+/**
+ * This function will fill a formatted string to buffer.
+ *
+ * @param  buf is the buffer to save formatted string.
+ *
+ * @param  size is the size of buffer.
+ *
+ * @param  fmt is the format parameters.
+ *
+ * @param  args is a list of variable parameters.
+ *
+ * @return The number of characters actually written to buffer.
+ */
+int pika_vsnprintf(char* buf, rt_size_t size, const char* fmt, va_list args) {
+    return __vsnprintf(out_buffer, buf, size, fmt, args);
+}
+
+int __platform_vsnprintf(char* buff,
+                         size_t size,
+                         const char* fmt,
+                         va_list args) {
+    return pika_vsnprintf(buff, size, fmt, args);
+}

+ 1 - 1
package/pika_lvgl/pika_lv_wegit.c

@@ -125,7 +125,7 @@ void pika_lvgl_bar___init__(PikaObj* self, PikaObj* parent) {
 
 void pika_lvgl_bar_set_value(PikaObj* self, int value, int anim) {
     lv_obj_t* lv_obj = obj_getPtr(self, "lv_obj");
-    lv_bar_set_value(lv_obj, value, value);
+    lv_bar_set_value(lv_obj, value, anim);
 }
 
 int pika_lvgl_bar_get_max_value(PikaObj* self) {

+ 2 - 2
package/pika_lvgl/pika_lvgl.c

@@ -88,8 +88,8 @@ void pika_lvgl_TEXT_DECOR___init__(PikaObj* self) {
 }
 
 void pika_lvgl_ANIM___init__(PikaObj* self) {
-    obj_setInt(self, "ON", LV_ANIM_OFF);
-    obj_setInt(self, "OFF", LV_ANIM_ON);
+    obj_setInt(self, "ON", LV_ANIM_ON);
+    obj_setInt(self, "OFF", LV_ANIM_OFF);
 }
 
 void pika_lvgl_ALIGN___init__(PikaObj* self) {

+ 291 - 76
package/requests/_requests.c

@@ -1,89 +1,180 @@
 #include "_requests.h"
+#include "PikaObj.h"
 #include <ctype.h>
 #include "_requests_Response.h"
 #include "webclient.h"
+#include "random.h"
 
-#define GET_HEADER_BUFSZ 1024
-#define GET_RESP_BUFSZ 1024
+#if !PIKASCRIPT_VERSION_REQUIRE_MINIMUN(1, 11, 9)
+#error "This library requires PikaScript version 1.11.9 or higher"
+#endif
 
-PikaObj* _requests_request(PikaObj* self, char* method, char* url) {
-    PikaObj* response = newNormalObj(New__requests_Response);
-    obj_setStr(response, "url", url);
+/* 标准输出函数 */
+#define RQ_print(fmt, ...) __platform_printf(fmt, ##__VA_ARGS__)
+#define RQ_cli(fmt, ...) __platform_printf(fmt, ##__VA_ARGS__)
+#define RQ_debug(fmt, ...)   {}
+/* #define RQ_debug(fmt, ...) __platform_printf("[RQ]:**|"fmt"|**\n", ##__VA_ARGS__) */
+#define RQ_error_pointer(...) \
+    RQ_print("[%s]: Checking NULL pointer of {" #__VA_ARGS__ "}.\n", __fun__)
+#define RQ_error_value(str, ...)                                            \
+    RQ_print("[%s]: Checking error value of {" #__VA_ARGS__ ":" str "}.\n", \
+             __fun__, ##__VA_ARGS__)
+#define RQ_err(fmt, ...) RQ_print("[%s]:" fmt "\n", __VA_ARGS__)
 
-    struct webclient_session* session = RT_NULL;
-    unsigned char* buffer = RT_NULL;
-    int ret = 0;
-    int bytes_read, resp_status;
-    int content_length = -1;
+/* 补充常见宏定义 */
+#ifndef unlikely
+#define unlikely(x) __builtin_expect(!!(x), 0)
+#endif
+#ifndef likely
+#define likely(x) __builtin_expect(!!(x), 1)
+#endif
 
-    buffer = (unsigned char*)web_calloc(1, GET_RESP_BUFSZ);
-    if (buffer == RT_NULL) {
-        rt_kprintf("no memory for receive buffer.\n");
-        ret = -RT_ENOMEM;
-        goto __exit;
+/**
+ *  现在支持可选的额外参数
+ *      params: 用于填充url参数,即get方法通过url传递数据
+ *      headers: 用于响应头信息填充
+ *      data: 负载内容
+ *      json: 负载内容
+ *      files: 负载内容
+ *      timeout: 超时设置
+ * 实际上支持有限
+ */
+int _requests_Response_request(PikaObj* self,
+                               char* method,
+                               char* url,
+                               pika_float timeout,
+                               char* data) {
+    size_t data_len, resp_len; /* 长度信息 */
+    void* resp_data;           /* 返回的负载内容 */
+    int32_t ret;               /* 返回值 */
+    struct webclient_session* session;
+
+    session = (struct webclient_session*)obj_getPtr(self, "session_address");
+    if (unlikely(session == NULL)) {
+        RQ_cli("Sorry, can not operate NULL session object.\n");
+        return -1;
+    }
+    if (unlikely(url == NULL)) {
+        RQ_cli("Sorry, please give a specified url.\n");
+        return -1;
     }
 
-    /* create webclient session and set header response size */
-    session = webclient_session_create(GET_HEADER_BUFSZ);
-    if (session == RT_NULL) {
-        ret = -RT_ENOMEM;
-        goto __exit;
-    }
-
-    if (strEqu("GET", method)) {
-        resp_status = webclient_get(session, url);
-        obj_setInt(response, "status_code", resp_status);
-        /* send GET request by default header */
-        if (resp_status != 200) {
-            goto __exit;
-        }
-
-        content_length = webclient_content_length_get(session);
-        obj_setInt(response, "content_length", content_length);
-
-        if (content_length < 0) {
-            // rt_kprintf("webclient GET request type is chunked.\n");
-            do {
-                bytes_read =
-                    webclient_read(session, (void*)buffer, GET_RESP_BUFSZ);
-                if (bytes_read <= 0) {
-                    break;
-                }
-            } while (1);
+    RQ_debug("header length:%d", session->header->length);
+    RQ_debug("header buffer:%.4096s", session->header->buffer);
+    RQ_debug("header url:%.1024s", url);
+
+    /* 进行post或者get操作 */
+    if (strEqu(method, "GET")) {
+        /* Get之后,header->buffer缓冲区内容会被清空 */
+        /* FIXME: 保存一下header->buffer内容 */
+        if (webclient_get2(session, url) != 200) {
+            return -1;
+        }
+        ret = webclient_response(session, &resp_data, &resp_len);
+        if (ret < 0) {
+            return -1;
+        }
+        /* 正常得到了数据 */
+        obj_setInt(self, "status_code", session->resp_status);
+        obj_setInt(self, "content_length", resp_len);
+        obj_setStr(self, "headers", session->header->buffer);
+        /* 释放申请的缓冲区内存 */
+        if (resp_data != NULL) {
+            obj_setStr(self, "text", (char*)resp_data);
+            web_free(resp_data);
         } else {
-            int content_pos = 0;
-            do {
-                bytes_read =
-                    webclient_read(session, (void*)buffer,
-                                   content_length - content_pos > GET_RESP_BUFSZ
-                                       ? GET_RESP_BUFSZ
-                                       : content_length - content_pos);
-                if (bytes_read <= 0) {
-                    break;
-                }
-                content_pos += bytes_read;
-            } while (content_pos < content_length);
-        }
-        obj_setStr(response, "text", (char*)buffer);
-        goto __exit;
-    }
-
-__exit:
-    if (session) {
-        webclient_close(session);
+            obj_setStr(self, "text", "");
+        }
+    } else if (strEqu(method, "POST")) {
+        if (data == NULL) {
+            data_len = 0;
+        } else {
+            data_len = strlen(data);
+        }
+        /* FIXME: 默认二进制数据 */
+        if (strstr(session->header->buffer, "Content-Length") == RT_NULL) {
+            ret = webclient_header_fields_add(session, "Content-Length: %d\r\n",
+                                              data_len);
+            if (ret < 0) {
+                return -1;
+            }
+        }
+        if (strstr(session->header->buffer, "Content-Type") == RT_NULL) {
+            /* 二进制数据流 */
+            ret = webclient_header_fields_add(
+                session, "Content-Type: application/octet-stream\r\n");
+            if (ret < 0) {
+                return -1;
+            }
+        }
+        RQ_debug("header buffer:%.4096s", session->header->buffer);
+        if (webclient_post(session, url, data, data_len) != 200) {
+            return -1;
+        }
+        ret = webclient_response(session, &resp_data, &resp_len);
+        if (ret < 0) {
+            return -1;
+        }
+        /* 正常得到了数据 */
+        obj_setInt(self, "status_code", session->resp_status);
+        obj_setInt(self, "content_length", resp_len);
+        obj_setStr(self, "headers", session->header->buffer);
+        /* 释放申请的缓冲区内存 */
+        if (resp_data != NULL) {
+            obj_setStr(self, "text", (char*)resp_data);
+            web_free(resp_data);
+        } else {
+            obj_setStr(self, "text", "");
+        }
+    } else {
+        return -1;
     }
 
-    if (buffer) {
-        web_free(buffer);
+    return 1;
+}
+
+int _requests_Response_header_write(PikaObj* self, char* header, char* value) {
+    struct webclient_session* session;
+
+    session = (struct webclient_session*)obj_getPtr(self, "session_address");
+    if (unlikely(session == NULL)) {
+        RQ_cli("Sorry, can not operate NULL session object.\n");
+        return -1;
+    }
+    RQ_debug("Add HTTP fileds:");
+    /* 写入请求初始内容 */
+    if (webclient_header_fields_add(session, "%s:%s\r\n", header, value) < 0) {
+        RQ_cli("Sorry, request header too long.\n");
+        return -1;
     }
+    RQ_debug("buffer:%p.", session->header->buffer);
+    return 1;
+}
+
+int _requests_Response_proto_write(PikaObj* self, char* proto) {
+    struct webclient_session* session;
 
-    if (ret != 0) {
-        if (response) {
-            obj_deinit(response);
+    session = (struct webclient_session*)obj_getPtr(self, "session_address");
+    if (unlikely(session == NULL)) {
+        RQ_cli("Sorry, can not operate NULL session object.\n");
+        return -1;
+    }
+    /* TODO: 写入协议头之前可以保存 */
+    RQ_debug("Add proto content:");
+    /* 写入请求初始内容 */
+    if (proto != NULL && *proto != 0) {
+        if (webclient_header_fields_add(session, " %s\r\n", proto) < 0) {
+            RQ_cli("Sorry, request header too long.\n");
+            return -1;
+        }
+    } else {
+        if (webclient_header_fields_add(session, " HTTP/1.1\r\n") < 0) {
+            RQ_cli("Sorry, request header too long.\n");
+            return -1;
         }
-        response = NULL;
     }
-    return response;
+    RQ_debug("buffer:%p.", session->header->buffer);
+    return 1;
 }
 
 char to_hex(char code) {
@@ -91,10 +182,44 @@ char to_hex(char code) {
     return hex[code & 15];
 }
 
-char* _requests_urlencode(PikaObj* self, char* s) {
-    obj_setBytes(self, "encodebuff", NULL, strlen(s) * 3 + 1);
-    char* result = (char*)obj_getBytes(self, "encodebuff");
-    char* p = result;
+int _requests_Response_urlencode_write(PikaObj* self,
+                                       char* s1,
+                                       char* s2,
+                                       char* start,
+                                       char* connect) {
+    struct webclient_session* session;
+    char *url_address, *p, *s;
+    int32_t length, header_length;
+
+    session = (struct webclient_session*)obj_getPtr(self, "session_address");
+    if (unlikely(session == NULL)) {
+        RQ_cli("Sorry, can not operate NULL session object.\n");
+        return -1;
+    }
+    header_length = session->header->length;
+    url_address = session->header->buffer + header_length;
+    p = url_address;
+    RQ_debug("Add url content:");
+    RQ_debug("buffer:%p,len:%d.", session->header->buffer, header_length);
+    RQ_debug("%s%s%s%s", start, s1, connect, s2);
+    
+    if (*start == 0) {
+        while(*s1)
+        {
+            *p++ = *s1++;
+        }
+        goto end;
+    }
+
+    if (start != NULL) {
+        /* 写入前置符号 */
+        s = (char*)start;
+        while (*s) {
+            *p++ = *s++;
+        }
+    }
+
+    s = s1;
     while (*s) {
         if (isalnum(*s) || *s == '-' || *s == '_' || *s == '.' || *s == '~') {
             *p++ = *s;
@@ -107,10 +232,100 @@ char* _requests_urlencode(PikaObj* self, char* s) {
         }
         s++;
     }
+    if (connect != NULL) {
+        /* 写入连接符号 */
+        s = (char*)connect;
+        while (*s) {
+            *p++ = *s++;
+        }
+    }
+    s = (char*)s2;
+    if (s != NULL) {
+        while (*s) {
+            if (isalnum(*s) || *s == '-' || *s == '_' || *s == '.' ||
+                *s == '~') {
+                *p++ = *s;
+            } else if (*s == ' ') {
+                *p++ = '+';
+            } else {
+                *p++ = '%';
+                *p++ = to_hex(*s >> 4);
+                *p++ = to_hex(*s & 0xf);
+            }
+            s++;
+        }
+    }
+
+end:
     *p = '\0';
-    return result;
+    length = p - url_address;
+    length += header_length;
+    if (length > session->header->size) {
+        RQ_cli("Error, header buffer has overflowed: {%d}.\n", length);
+        return -1;
+    }
+    /* 更新长度信息 */
+    session->header->length = length;
+    RQ_debug("context:%.1024s.", session->header->buffer);
+    RQ_debug("url length add:%d.", length);
+    return 1;
 }
 
-void _requests___del__(PikaObj* self) {}
+int _requests_Response_request_init(PikaObj* self, char* method) {
+    /* 创建会话对象,header长度固定 */
+    struct webclient_session* session;
+    char* temp;
+
+    if (unlikely((strEqu(method, "GET") || strEqu(method, "POST")) == 0)) {
+        /* 目前仅支持两种方法 */
+        RQ_cli("Sorry, now only support method: GET and POST.\n");
+        return -1;
+    }
 
-void _requests___init__(PikaObj* self) {}
+    session = webclient_session_create(WEBCLIENT_HEADER_BUFSZ);
+    if (session == RT_NULL) {
+        RQ_cli("Sorry, memeory is not enough.\n");
+        obj_setPtr(self, "session_address", NULL);
+        return -1;
+    } else {
+        /* 写入请求初始内容 */
+        if (webclient_header_fields_add(session, "%s ", method) < 0) {
+            _requests_Response_request_del(self);
+            RQ_cli("Sorry, request header too long.\n");
+            return -1;
+        }
+        temp = session->header->buffer + session->header->length;
+        RQ_debug("buffer address:%p.", session->header->buffer);
+        RQ_debug("url address:%p.", temp);
+        RQ_debug("headers start:%.10s.", session->header->buffer);
+        obj_setPtr(self, "url_address", temp);
+        obj_setPtr(self, "session_address", session);
+    }
+    RQ_debug("Response deal session memory.");
+    return 1;
+}
+
+PikaObj* _requests_Response_request_del(PikaObj* self) {
+    struct webclient_session* session;
+    session = (struct webclient_session*)obj_getPtr(self, "session_address");
+    if (session) {
+        webclient_close(session);
+        RQ_debug("Response free session memory.");
+    }
+    RQ_debug("Response set variables None.");
+    return NULL;
+}
+
+void _requests_Response___del__(PikaObj* self) {
+    _requests_Response_request_del(self);
+    RQ_debug("Response class deleted.");
+}
+
+void _requests_Response___init__(PikaObj* self) {
+    /* 初始化 */
+    obj_setNone(self, "url");
+    obj_setNone(self, "text");
+    obj_setNone(self, "headers");
+    obj_setPtr(self, "session_address", NULL);
+    RQ_debug("Response class initialized.");
+}

+ 16 - 6
package/requests/_requests.pyi

@@ -2,16 +2,26 @@ class Response:
     content_length: int
     text: str
     state_code: int
-    headers: dict
+    headers: str
     url: str
+    url_address: int
+    session_address: int
 
     def json(self) -> dict: ...
 
+    def request(self,
+                method: str,
+                url: str,
+                timeout: float,
+                data: str) -> int: ...
 
-def request(method: str, url: str) -> Response: ...
+    def request_init(self, method: str) -> int: ...
+    def request_del(self) -> None: ...
+    def proto_write(self, proto: str) -> int: ...
+    def urlencode_write(self, s1: str, s2: str, start: str,
+                        connect: str) -> int: ...
 
-def urlencode(s: str) -> str: ...
+    def header_write(self, header: str, value: str) -> int: ...
 
-
-def __init__(): ...
-def __del__(): ...
+    def __init__(self): ...
+    def __del__(self): ...

+ 77 - 20
package/requests/requests.py

@@ -2,35 +2,92 @@ import _requests
 
 
 class Response(_requests.Response):
-    ...
+    def __init__(self):
+        super().__init__()
 
 
-def _append_params_to_url(url: str, params: dict) -> str:
+def _append_params_to_url(rqst: Response, url: str, params: dict) -> int:
     if params is None:
-        return url
+        ret = rqst.urlencode_write(url, '', '', '')
+        return 1
     if '?' in url:
-        url += '&'
+        first_connect = '&'
+
     else:
-        url += '?'
+        first_connect = '?'
+    # 初始化连接url
+    ret = rqst.urlencode_write(url, '', '', '')
+    if ret != 1:
+        return ret
+    count = 0
+    connect = '='
+    start = '&'
     for k, v in params.items():
-        k = _requests.urlencode(str(k))
-        v = _requests.urlencode(str(v))
-        url += '%s=%s&' % (k, v)
-    return url[:-1]
-
+        if count == 0:
+            ret = rqst.urlencode_write(str(k), str(v), first_connect, connect)
+            if ret != 1:
+                return ret
+            count += 1
+        else:
+            ret = rqst.urlencode_write(str(k), str(v), start, connect)
+            if ret != 1:
+                return ret
+    return 1
 
-def request(method: str, url: str, params=None) -> Response:
-    url = _append_params_to_url(url, params)
-    return _requests.request(method, url)
 
+def _append_headers(rqst: Response, headers: dict) -> int:
+    if headers is None:
+        return 1
+    for k, v in headers.items():
+        # print("\nheaders:", str(k), "=", str(v),"\n")
+        ret = rqst.header_write(str(k), str(v))
+        if ret != 1:
+            return ret
 
-def get(url: str, params=None) -> Response:
-    return request('GET', url, params)
+    return 1
 
 
-def __init__():
-    _requests.__init__()
+def request(
+        method: str,
+        url: str,
+        params=None,
+        headers=None,
+        timeout=0.0,
+        files=None,
+        json=None,
+        data=None) -> Response:
+    if files != None:
+        print("files is not supported")
+        return None
+    if json != None:
+        print("json is not supported")
+        return None
+    """ 
+    初始化请求对象,分配内存和固定请求头 
+    """
+    rqst = Response()
+    rqst.url = url
+    # 初始化,分配内存, 写入方法POST/GET
+    ret = rqst.request_init(method)
+    if ret != 1:
+        return None
+    # 写入URL
+    ret = _append_params_to_url(rqst, url, params)
+    if  ret != 1:
+        # 出现错误,需要释放对象
+        return None
+    # 写入默认HTTP版本号
+    ret = rqst.proto_write('')
+    if ret != 1:
+        return None
+    # 写入响应头数据
+    ret = _append_headers(rqst, headers)
+    if ret != 1:
+        return None
+    ret = rqst.request(method, rqst.url, timeout, data)
+    if ret != 1:
+        return None
+    return rqst
 
-
-def __del__():
-    _requests.__del__()
+def get(url: str, params=None) -> Response:
+    return request('GET', url, params)

+ 302 - 1
package/requests/webclient.c

@@ -362,6 +362,7 @@ static int webclient_connect(struct webclient_session* session,
         LOG_E(
             "not support https connect, please enable webclient https "
             "configure!");
+        LOG_E("||url:%.1024s||", URI);
         rc = -WEBCLIENT_ERROR;
         goto __exit;
 #endif
@@ -468,6 +469,7 @@ __exit:
 }
 
 /**
+ * FIXME: userful func
  * add fields data to request header data.
  *
  * @param session webclient session
@@ -701,6 +703,54 @@ __exit:
     return rc;
 }
 
+/* FIXME: 定制版发送响应头 */
+static int webclient_send_header2(struct webclient_session* session,
+                                 int method) {
+    int rc = WEBCLIENT_OK;
+    char* header = RT_NULL;
+
+    RT_ASSERT(session);
+
+    header = session->header->buffer;
+
+    if (strstr(header, "Host:") == RT_NULL) {
+        if (webclient_header_fields_add(session, "Host: %s\r\n",
+                                        session->host) < 0)
+            return -WEBCLIENT_NOMEM;
+    }
+
+    if (strstr(header, "User-Agent:") == RT_NULL) {
+        if (webclient_header_fields_add(
+                session, "User-Agent: PikaScript HTTP Agent\r\n") < 0)
+            return -WEBCLIENT_NOMEM;
+    }
+
+    if (strstr(header, "Accept:") == RT_NULL) {
+        if (webclient_header_fields_add(session, "Accept: */*\r\n") < 0)
+            return -WEBCLIENT_NOMEM;
+    }
+
+    /* header data end */
+    web_snprintf(session->header->buffer + session->header->length,
+                    session->header->size - session->header->length,
+                    "\r\n");
+    session->header->length += 2;
+
+    /* check header size */
+    if (session->header->length > session->header->size) {
+        LOG_E("send header failed, not enough header buffer size(%d)!",
+                session->header->size);
+        rc = -WEBCLIENT_NOBUFFER;
+        goto __exit;
+    }
+
+    webclient_write(session, (unsigned char*)session->header->buffer,
+                    session->header->length);
+
+__exit:
+    return rc;
+}
+
 /**
  * resolve server response data.
  *
@@ -811,6 +861,7 @@ int webclient_handle_response(struct webclient_session* session) {
 }
 
 /**
+ * FIXME: userful func
  * create webclient session, set maximum header and response size
  *
  * @param header_sz maximum send header size
@@ -875,7 +926,6 @@ int webclient_get(struct webclient_session* session, const char* URI) {
 
     RT_ASSERT(session);
     RT_ASSERT(URI);
-
     rc = webclient_connect(session, URI);
     if (rc != WEBCLIENT_OK) {
         /* connect to webclient server failed. */
@@ -921,6 +971,71 @@ int webclient_get(struct webclient_session* session, const char* URI) {
     return resp_status;
 }
 
+/**
+ * FIXME: better interface
+ *  send GET request to http server and get response header.
+ *
+ * @param session webclient session
+ * @param URI input server URI address
+ * @param header GET request header
+ *             = NULL: use default header data
+ *            != NULL: use custom header data
+ *
+ * @return <0: send GET request failed
+ *         >0: response http status code
+ */
+int webclient_get2(struct webclient_session* session, const char* URI) {
+    int rc = WEBCLIENT_OK;
+    int resp_status = 0;
+
+    RT_ASSERT(session);
+    RT_ASSERT(URI);
+    /* LOG_E("||url:%.1024s||", URI); */
+    rc = webclient_connect(session, URI);
+    if (rc != WEBCLIENT_OK) {
+        /* connect to webclient server failed. */
+        return rc;
+    }
+
+    rc = webclient_send_header2(session, WEBCLIENT_GET);
+    if (rc != WEBCLIENT_OK) {
+        /* send header to webclient server failed. */
+        return rc;
+    }
+
+    /* handle the response header of webclient server */
+    resp_status = webclient_handle_response(session);
+
+    LOG_D("get position handle response(%d).", resp_status);
+
+    if (resp_status > 0) {
+        const char* location = webclient_header_fields_get(session, "Location");
+
+        /* relocation */
+        if ((resp_status == 302 || resp_status == 301) && location) {
+            char* new_url;
+
+            new_url = web_strdup(location);
+            if (new_url == RT_NULL) {
+                return -WEBCLIENT_NOMEM;
+            }
+
+            /* clean webclient session */
+            webclient_clean(session);
+            /* clean webclient session header */
+            session->header->length = 0;
+            web_memset(session->header->buffer, 0, session->header->size);
+
+            rc = webclient_get(session, new_url);
+
+            web_free(new_url);
+            return rc;
+        }
+    }
+
+    return resp_status;
+}
+
 /**
  *  register a handle function for http breakpoint resume and shard download.
  *
@@ -1162,6 +1277,59 @@ int webclient_post(struct webclient_session* session,
     return resp_status;
 }
 
+/**
+ * FIXME: better interface
+ * send POST request to server and get response header data.
+ *
+ * @param session webclient session
+ * @param URI input server URI address
+ * @param post_data data send to the server
+ *                = NULL: just connect server and send header
+ *               != NULL: send header and body data, resolve response data
+ * @param data_len the length of send data
+ *
+ * @return <0: send POST request failed
+ *         =0: send POST header success
+ *         >0: response http status code
+ */
+int webclient_post2(struct webclient_session* session,
+                   const char* URI,
+                   const void* post_data,
+                   size_t data_len) {
+    int rc = WEBCLIENT_OK;
+    int resp_status = 0;
+
+    RT_ASSERT(session);
+    RT_ASSERT(URI);
+
+    if ((post_data != RT_NULL) && (data_len == 0)) {
+        LOG_E("input post data length failed");
+        return -WEBCLIENT_ERROR;
+    }
+
+    rc = webclient_connect(session, URI);
+    if (rc != WEBCLIENT_OK) {
+        /* connect to webclient server failed. */
+        return rc;
+    }
+
+    rc = webclient_send_header2(session, WEBCLIENT_POST);
+    if (rc != WEBCLIENT_OK) {
+        /* send header to webclient server failed. */
+        return rc;
+    }
+
+    if (post_data && (data_len > 0)) {
+        webclient_write(session, post_data, data_len);
+
+        /* resolve response data, get http status code */
+        resp_status = webclient_handle_response(session);
+        LOG_D("post handle response(%d).", resp_status);
+    }
+
+    return resp_status;
+}
+
 /**
  * set receive and send data timeout.
  *
@@ -1726,3 +1894,136 @@ __exit:
 
     return totle_length;
 }
+
+/**
+ *  Better interface.
+ *  send request(GET/POST) to server and get response data.
+ *
+ * @param URI input server address
+ * @param header send header data
+ *             = NULL: use default header data, must be GET request
+ *            != NULL: user custom header data, GET or POST request
+ * @param post_data data sent to the server
+ *             = NULL: it is GET request
+ *            != NULL: it is POST request
+ * @param data_len send data length
+ * @param response response buffer address
+ * @param resp_len response buffer length
+ *
+ * @return <0: request failed
+ *        >=0: response buffer size
+ */
+int webclient_request2(
+                      struct webclient_session* session,
+                      const char* URI,
+                      const char* header,
+                      const void* post_data,
+                      size_t data_len,
+                      double timeout,
+                      void** response,
+                      size_t* resp_len) {
+    int rc = WEBCLIENT_OK;
+    int totle_length = 0;
+
+    if (post_data == RT_NULL && response == RT_NULL) {
+        LOG_E("request get failed, get response data cannot be empty.");
+        return -WEBCLIENT_ERROR;
+    }
+
+    if ((post_data != RT_NULL) && (data_len == 0)) {
+        LOG_E("input post data length failed");
+        return -WEBCLIENT_ERROR;
+    }
+
+    if ((response != RT_NULL && resp_len == RT_NULL) ||
+        (response == RT_NULL && resp_len != RT_NULL)) {
+        LOG_E("input response data or length failed");
+        return -WEBCLIENT_ERROR;
+    }
+
+    if (post_data == RT_NULL) {
+        /* send get request */
+        session = webclient_session_create(WEBCLIENT_HEADER_BUFSZ);
+        if (session == RT_NULL) {
+            rc = -WEBCLIENT_NOMEM;
+            goto __exit;
+        }
+
+        if (header != RT_NULL) {
+            char *header_str, *header_ptr;
+            int header_line_length;
+
+            for (header_str = (char*)header;
+                 (header_ptr = strstr(header_str, "\r\n")) != RT_NULL;) {
+                header_line_length = header_ptr + strlen("\r\n") - header_str;
+                webclient_header_fields_add(session, "%.*s", header_line_length,
+                                            header_str);
+                header_str += header_line_length;
+            }
+        }
+
+        if (webclient_get(session, URI) != 200) {
+            rc = -WEBCLIENT_ERROR;
+            goto __exit;
+        }
+
+        totle_length = webclient_response(session, response, resp_len);
+        if (totle_length <= 0) {
+            rc = -WEBCLIENT_ERROR;
+            goto __exit;
+        }
+    } else {
+        /* send post request */
+        session = webclient_session_create(WEBCLIENT_HEADER_BUFSZ);
+        if (session == RT_NULL) {
+            rc = -WEBCLIENT_NOMEM;
+            goto __exit;
+        }
+
+        if (header != RT_NULL) {
+            char *header_str, *header_ptr;
+            int header_line_length;
+
+            for (header_str = (char*)header;
+                 (header_ptr = strstr(header_str, "\r\n")) != RT_NULL;) {
+                header_line_length = header_ptr + strlen("\r\n") - header_str;
+                webclient_header_fields_add(session, "%.*s", header_line_length,
+                                            header_str);
+                header_str += header_line_length;
+            }
+        }
+
+        if (strstr(session->header->buffer, "Content-Length") == RT_NULL) {
+            webclient_header_fields_add(session, "Content-Length: %d\r\n",
+                                        strlen(post_data));
+        }
+
+        if (strstr(session->header->buffer, "Content-Type") == RT_NULL) {
+            webclient_header_fields_add(
+                session, "Content-Type: application/octet-stream\r\n");
+        }
+
+        if (webclient_post(session, URI, post_data, data_len) != 200) {
+            rc = -WEBCLIENT_ERROR;
+            goto __exit;
+        }
+
+        totle_length = webclient_response(session, response, resp_len);
+        if (totle_length <= 0) {
+            rc = -WEBCLIENT_ERROR;
+            goto __exit;
+        }
+    }
+
+__exit:
+    if (session) {
+        webclient_close(session);
+        session = RT_NULL;
+    }
+
+    if (rc < 0) {
+        return rc;
+    }
+
+    return totle_length;
+}

+ 8 - 1
package/requests/webclient.h

@@ -106,7 +106,6 @@ enum WEBCLIENT_METHOD {
 struct webclient_header {
     char* buffer;
     size_t length; /* content header buffer size */
-
     size_t size; /* maximum support header size */
 };
 
@@ -136,6 +135,8 @@ struct webclient_session* webclient_session_create(size_t header_sz);
 
 /* send HTTP GET request */
 int webclient_get(struct webclient_session* session, const char* URI);
+/* send HTTP GET request */
+int webclient_get2(struct webclient_session* session, const char* URI);
 
 /* send HTTP HEAD request */
 int webclient_shard_head_function(struct webclient_session* session,
@@ -157,6 +158,12 @@ int webclient_post(struct webclient_session* session,
                    const char* URI,
                    const void* post_data,
                    size_t data_len);
+/* send HTTP POST request */
+int webclient_post2(struct webclient_session* session,
+                   const char* URI,
+                   const void* post_data,
+                   size_t data_len);
+
 
 /* close and release wenclient session */
 int webclient_close(struct webclient_session* session);

+ 39 - 32
package/socket/PikaPlatform_socket.c

@@ -4,7 +4,11 @@
     you need to override them in your platform.
 */
 
-PIKA_WEAK int __platform_socket(int __domain, int __type, int __protocol) {
+#if !PIKASCRIPT_VERSION_REQUIRE_MINIMUN(1, 12, 0)
+#error "Error: PikaScript version must be greater than 1.12.0"
+#endif
+
+PIKA_WEAK int pika_platform_socket(int __domain, int __type, int __protocol) {
 #if defined(__linux__) || PIKA_LWIP_ENABLE
     return socket(__domain, __type, __protocol);
 #else
@@ -12,9 +16,9 @@ PIKA_WEAK int __platform_socket(int __domain, int __type, int __protocol) {
 #endif
 }
 
-PIKA_WEAK int __platform_bind(int __fd,
-                              const struct sockaddr* __addr,
-                              socklen_t __addr_len) {
+PIKA_WEAK int pika_platform_bind(int __fd,
+                                 const struct sockaddr* __addr,
+                                 socklen_t __addr_len) {
 #if defined(__linux__) || PIKA_LWIP_ENABLE
     return bind(__fd, __addr, __addr_len);
 #else
@@ -22,7 +26,7 @@ PIKA_WEAK int __platform_bind(int __fd,
 #endif
 }
 
-PIKA_WEAK int __platform_listen(int __fd, int __n) {
+PIKA_WEAK int pika_platform_listen(int __fd, int __n) {
 #if defined(__linux__) || PIKA_LWIP_ENABLE
     return listen(__fd, __n);
 #else
@@ -30,9 +34,9 @@ PIKA_WEAK int __platform_listen(int __fd, int __n) {
 #endif
 }
 
-PIKA_WEAK int __platform_accept(int __fd,
-                                struct sockaddr* __addr,
-                                socklen_t* __addr_len) {
+PIKA_WEAK int pika_platform_accept(int __fd,
+                                   struct sockaddr* __addr,
+                                   socklen_t* __addr_len) {
 #if defined(__linux__) || PIKA_LWIP_ENABLE
     return accept(__fd, __addr, __addr_len);
 #else
@@ -40,9 +44,9 @@ PIKA_WEAK int __platform_accept(int __fd,
 #endif
 }
 
-PIKA_WEAK int __platform_connect(int __fd,
-                                 const struct sockaddr* __addr,
-                                 socklen_t __addr_len) {
+PIKA_WEAK int pika_platform_connect(int __fd,
+                                    const struct sockaddr* __addr,
+                                    socklen_t __addr_len) {
 #if defined(__linux__) || PIKA_LWIP_ENABLE
     return connect(__fd, __addr, __addr_len);
 #else
@@ -50,10 +54,10 @@ PIKA_WEAK int __platform_connect(int __fd,
 #endif
 }
 
-PIKA_WEAK int __platform_send(int __fd,
-                              const void* __buf,
-                              size_t __n,
-                              int __flags) {
+PIKA_WEAK int pika_platform_send(int __fd,
+                                 const void* __buf,
+                                 size_t __n,
+                                 int __flags) {
 #if defined(__linux__) || PIKA_LWIP_ENABLE
     return send(__fd, __buf, __n, __flags);
 #else
@@ -61,7 +65,10 @@ PIKA_WEAK int __platform_send(int __fd,
 #endif
 }
 
-PIKA_WEAK int __platform_recv(int __fd, void* __buf, size_t __n, int __flags) {
+PIKA_WEAK int pika_platform_recv(int __fd,
+                                 void* __buf,
+                                 size_t __n,
+                                 int __flags) {
 #if defined(__linux__) || PIKA_LWIP_ENABLE
     return recv(__fd, __buf, __n, __flags);
 #else
@@ -70,7 +77,7 @@ PIKA_WEAK int __platform_recv(int __fd, void* __buf, size_t __n, int __flags) {
 }
 
 /* gethostname */
-PIKA_WEAK int __platform_gethostname(char* __name, size_t __len) {
+PIKA_WEAK int pika_platform_gethostname(char* __name, size_t __len) {
 #if defined(__linux__)
     return gethostname(__name, __len);
 #else
@@ -78,10 +85,10 @@ PIKA_WEAK int __platform_gethostname(char* __name, size_t __len) {
 #endif
 }
 
-PIKA_WEAK int __platform_getaddrinfo(const char* __name,
-                                     const char* __service,
-                                     const struct addrinfo* __req,
-                                     struct addrinfo** __pai) {
+PIKA_WEAK int pika_platform_getaddrinfo(const char* __name,
+                                        const char* __service,
+                                        const struct addrinfo* __req,
+                                        struct addrinfo** __pai) {
 #if defined(__linux__) || PIKA_LWIP_ENABLE
     return getaddrinfo(__name, __service, __req, __pai);
 #else
@@ -89,7 +96,7 @@ PIKA_WEAK int __platform_getaddrinfo(const char* __name,
 #endif
 }
 
-PIKA_WEAK void __platform_freeaddrinfo(struct addrinfo* __ai) {
+PIKA_WEAK void pika_platform_freeaddrinfo(struct addrinfo* __ai) {
 #if defined(__linux__) || PIKA_LWIP_ENABLE
     freeaddrinfo(__ai);
 #else
@@ -97,11 +104,11 @@ PIKA_WEAK void __platform_freeaddrinfo(struct addrinfo* __ai) {
 #endif
 }
 
-PIKA_WEAK int __platform_setsockopt(int __fd,
-                                    int __level,
-                                    int __optname,
-                                    const void* __optval,
-                                    socklen_t __optlen) {
+PIKA_WEAK int pika_platform_setsockopt(int __fd,
+                                       int __level,
+                                       int __optname,
+                                       const void* __optval,
+                                       socklen_t __optlen) {
 #if defined(__linux__) || PIKA_LWIP_ENABLE
     return setsockopt(__fd, __level, __optname, __optval, __optlen);
 #else
@@ -109,8 +116,8 @@ PIKA_WEAK int __platform_setsockopt(int __fd,
 #endif
 }
 
-PIKA_WEAK int __platform_fcntl(int fd, int cmd, long arg) {
-#ifdef __linux__
+PIKA_WEAK int pika_platform_fcntl(int fd, int cmd, long arg) {
+#if defined(__linux__) || PIKA_LWIP_ENABLE
     return fcntl(fd, cmd, arg);
 #else
     WEAK_FUNCTION_NEED_OVERRIDE_ERROR();
@@ -118,8 +125,8 @@ PIKA_WEAK int __platform_fcntl(int fd, int cmd, long arg) {
 }
 
 /* os file API */
-PIKA_WEAK int __platform_close(int __fd) {
-#ifdef __linux__
+PIKA_WEAK int pika_platform_close(int __fd) {
+#if defined(__linux__) || PIKA_LWIP_ENABLE
     return close(__fd);
 #elif PIKA_FREERTOS_ENABLE
     return closesocket(__fd);
@@ -128,7 +135,7 @@ PIKA_WEAK int __platform_close(int __fd) {
 #endif
 }
 
-PIKA_WEAK int __platform_write(int __fd, const void* __buf, size_t __nbyte) {
+PIKA_WEAK int pika_platform_write(int __fd, const void* __buf, size_t __nbyte) {
 #if defined(__linux__) || PIKA_LWIP_ENABLE
     return write(__fd, __buf, __nbyte);
 #else

+ 29 - 27
package/socket/PikaPlatform_socket.h

@@ -14,37 +14,39 @@
 #include "lwip/sys.h"
 #else
 /*
-    You need to create the __platform_socket.h for your platform.
+    You need to create the pika_platform_socket.h for your platform.
     For example:
-    You can #include "lwip/socket.h" in the __platform_socket.h
+    You can #include "lwip/socket.h" in the pika_platform_socket.h
 */
-#include "__platform_socket.h"
+#include "pika_platform_socket.h"
 #endif
-int __platform_socket(int __domain, int __type, int __protocol);
-int __platform_bind(int __fd,
-                    const struct sockaddr* __addr,
-                    socklen_t __addr_len);
-
-int __platform_listen(int __fd, int __n);
-int __platform_accept(int __fd, struct sockaddr* __addr, socklen_t* __addr_len);
-int __platform_connect(int __fd,
+int pika_platform_socket(int __domain, int __type, int __protocol);
+int pika_platform_bind(int __fd,
                        const struct sockaddr* __addr,
                        socklen_t __addr_len);
-int __platform_send(int __fd, const void* __buf, size_t __n, int __flags);
-int __platform_recv(int __fd, void* __buf, size_t __n, int __flags);
-int __platform_gethostname(char* __name, size_t __len);
-int __platform_getaddrinfo(const char* __name,
-                           const char* __service,
-                           const struct addrinfo* __req,
-                           struct addrinfo** __pai);
-void __platform_freeaddrinfo(struct addrinfo* __ai);
-int __platform_setsockopt(int __fd,
-                          int __level,
-                          int __optname,
-                          const void* __optval,
-                          socklen_t __optlen);
+
+int pika_platform_listen(int __fd, int __n);
+int pika_platform_accept(int __fd,
+                         struct sockaddr* __addr,
+                         socklen_t* __addr_len);
+int pika_platform_connect(int __fd,
+                          const struct sockaddr* __addr,
+                          socklen_t __addr_len);
+int pika_platform_send(int __fd, const void* __buf, size_t __n, int __flags);
+int pika_platform_recv(int __fd, void* __buf, size_t __n, int __flags);
+int pika_platform_gethostname(char* __name, size_t __len);
+int pika_platform_getaddrinfo(const char* __name,
+                              const char* __service,
+                              const struct addrinfo* __req,
+                              struct addrinfo** __pai);
+void pika_platform_freeaddrinfo(struct addrinfo* __ai);
+int pika_platform_setsockopt(int __fd,
+                             int __level,
+                             int __optname,
+                             const void* __optval,
+                             socklen_t __optlen);
 
 /* os file API */
-int __platform_close(int fd);
-int __platform_write(int fd, const void* buf, size_t count);
-int __platform_fcntl(int fd, int cmd, long arg);
+int pika_platform_close(int fd);
+int pika_platform_write(int fd, const void* buf, size_t count);
+int pika_platform_fcntl(int fd, int cmd, long arg);

+ 33 - 10
packages.toml

@@ -74,7 +74,9 @@ releases = [
   "v1.11.5 83afef1906204a7e3f9b773aa8b4bdd46cea4ab9",
   "v1.11.6 338d385be718d8d11f02aa022103a4b4e9404527",
   "v1.11.7 97b8268a31f195092a9ec1d848fbe49168c42c19",
-  "v1.11.8 1a66a70893702174294214d227aee3ec8e4498af"
+  "v1.11.8 1a66a70893702174294214d227aee3ec8e4498af",
+  "v1.11.9 b2f397a990f0aa88129104d460174339531ee808",
+  "v1.12.0 480134b68e56580a2d6268eca10eea6c30b6f4cd"
 ]
 
 [[packages]]
@@ -141,7 +143,9 @@ releases = [
   "v1.11.5 83afef1906204a7e3f9b773aa8b4bdd46cea4ab9",
   "v1.11.6 338d385be718d8d11f02aa022103a4b4e9404527",
   "v1.11.7 97b8268a31f195092a9ec1d848fbe49168c42c19",
-  "v1.11.8 1a66a70893702174294214d227aee3ec8e4498af"
+  "v1.11.8 1a66a70893702174294214d227aee3ec8e4498af",
+  "v1.11.9 b2f397a990f0aa88129104d460174339531ee808",
+  "v1.12.0 480134b68e56580a2d6268eca10eea6c30b6f4cd"
 ]
 
 [[packages]]
@@ -171,7 +175,10 @@ releases = [
   "v1.11.8 58ff9fe16688be2e77ed220604aa8b1271b72d80",
   "v2.0.0 e89c585f46ee98811611ea56d5abfc618a41ee3b",
   "v2.1.0 852daad3c9a95dbce54dbf1d2cdb5b2321826b4f",
-  "v2.1.1 5eadba95fa573e3409f65c6392804d3c60d627ac"
+  "v2.1.1 5eadba95fa573e3409f65c6392804d3c60d627ac",
+  "v2.1.2 36ef746f5791a57212cc1d02fe885814e613e60c",
+  "v2.2.0 747fc1be13d57f920b436a2dbbfce253d8c3546f",
+  "v2.2.1 e28d9ee48feaf2125c018e5a18db60f648f038f8"
 ]
 
 [[packages]]
@@ -412,10 +419,6 @@ releases = [
 name = "modbus"
 releases = [ "v0.0.1 729ce8a497d73b53888180b9f6d0dfdac145df26" ]
 
-[[packages]]
-name = "BL808"
-releases = [ "v0.0.1 b3b2f1c0e30b703666342ae4628e544299cdbd11" ]
-
 [[packages]]
 name = "pika_fatfs"
 releases = [
@@ -429,7 +432,10 @@ releases = [ "v0.0.1 04a174a7d3e02d8861124214f5a3551eaab2bfee" ]
 
 [[packages]]
 name = "requests"
-releases = [ "v0.0.1 04a174a7d3e02d8861124214f5a3551eaab2bfee" ]
+releases = [
+  "v0.0.1 04a174a7d3e02d8861124214f5a3551eaab2bfee",
+  "v1.0.0 c67a894fc27ab3fe7b7aac825f1880e5073b0020"
+]
 
 [[packages]]
 name = "hashlib"
@@ -440,15 +446,32 @@ releases = [
 
 [[packages]]
 name = "hmac"
-releases = [ "v1.0.0 ca8fe36d68be16722317860394fdf78c620e3e2d" ]
+releases = [
+  "v1.0.0 ca8fe36d68be16722317860394fdf78c620e3e2d",
+  "v1.0.1 d75ce00c377e48c6058bbe1f824474802383e5e7"
+]
 
 [[packages]]
 name = "BLIOT"
 releases = [
   "v0.1.0 4599ce8681d293a5cc7682115205ab5e85e9b5e8",
-  "v0.2.0 eee8e1848eed77f3ebed777230104ebb4dfc3263"
+  "v0.2.0 eee8e1848eed77f3ebed777230104ebb4dfc3263",
+  "v0.3.0 fc69ce4145c053d0a5f9191e8706014c5bee4ca8",
+  "v0.4.0 bcb2f3aac147cfb7b0f655b877d964e3fc0699c8",
+  "v0.4.1 e28d9ee48feaf2125c018e5a18db60f648f038f8"
 ]
 
 [[packages]]
 name = "aes"
 releases = [ "v0.0.1 5c45cba0c39d447fbe7a4a082ee3170188c3bcb7" ]
+
+[[packages]]
+name = "base64"
+releases = [
+  "v0.0.1 1ae3ac23759fb2b5e0f77866af40986ac94e356d",
+  "v1.0.0 29ad2b44817c5a72ace9f6d09cea7df6beb516f9"
+]
+
+[[packages]]
+name = "pika_libc"
+releases = [ "v1.0.0 42a3cebb085a4a995d80031685dbf630e053aa55" ]

+ 1 - 1
port/linux/.vscode/launch.json

@@ -11,7 +11,7 @@
             "program": "${workspaceFolder}/build/test/pikascript_test",
             // "program": "${workspaceFolder}/build/boot/demo06-pikamain/pikascript_demo06-pikamain",
             "args": [
-                // "--gtest_filter=stddata.pikafs_open"
+                // "--gtest_filter=mqtt.subscribe"
             ],
             "stopAtEntry": false,
             "cwd": "${workspaceFolder}",

+ 12 - 2
port/linux/.vscode/settings.json

@@ -93,8 +93,18 @@
         "__instruction_def.h": "c",
         "pika_hal_def.h": "c",
         "pika_hal_table.h": "c",
-        "pika_hal_table_rule.h": "c"
+        "pika_hal_table_rule.h": "c",
+        "pikaobj.h": "c",
+        "pikastddevice_gpio.h": "c",
+        "pikastddevice_adc.h": "c",
+        "pikastddevice_can.h": "c",
+        "pikastddevice_dac.h": "c",
+        "pikastddevice_iic.h": "c",
+        "pikastddevice_pwm.h": "c",
+        "pikastddevice_spi.h": "c",
+        "pikastddevice_uart.h": "c",
+        "datamemory.h": "c",
+        "pika_adapter_old_api.h": "c"
     },
     "python.formatting.provider": "autopep8",
-    "C_Cpp.errorSquiggles": "Disabled"
 }

Kaikkia tiedostoja ei voida näyttää, sillä liian monta tiedostoa muuttui tässä diffissä