Comments (11)
@david-cermak The problem seems to be solved, and now I've changed the modem to another model and the problem doesn't appear.
from esp-protocols.
My business is to start a task to query the 4G signal quality, and use Alibaba Cloud IoT for cloud connection. I don't know if it is in data mode (the data is still being received, judged according to on_cmux: state: 2 in the Log), the execution of the AT command caused this exception.
void get_rssi_tim(void *dced)
{
int rssi, ber;
for (;;)
{
ESP_LOGI(TAG, "get_rssi!!!");
esp_err_t err = esp_modem_get_signal_quality(dce, &rssi, &ber);
if (err != ESP_OK)
{
ESP_LOGE(TAG, "get_rssi_tim failed with %d", err);
}
env_set_device_rssi(rssi);
ESP_LOGI(TAG, "Signal quality: rssi=%d, ber=%d", rssi, ber);
vTaskDelay(pdMS_TO_TICKS(1000));
}
vTaskDelete(NULL);
}
// I added a Log here to print the status
bool CMux::on_cmux(uint8_t *data, size_t actual_len)
{
if (!data)
{
#ifdef DEFRAGMENT_CMUX_PAYLOAD
auto data_to_read = buffer_size - 128; // keep 128 (max CMUX payload) backup buffer)
if (payload_start)
{
data = payload_start + total_payload_size;
data_to_read = payload_len + 2;
}
else
{
data = buffer.get();
}
actual_len = term->read(data, data_to_read);
#else
data = buffer.get();
actual_len = term->read(data, buffer_size);
#endif
}
ESP_LOG_BUFFER_HEXDUMP("CMUX Received", data, actual_len, ESP_LOG_VERBOSE);
CMuxFrame frame = {.ptr = data, .len = actual_len};
while (frame.len > 0)
{
ESP_LOGI("on_cmux", "state:%d", (int)state);
switch (state)
{
case cmux_state::RECOVER:
if (!on_recovery(frame))
{
return false;
}
break;
case cmux_state::INIT:
if (!on_init(frame))
{
return false;
}
break;
case cmux_state::HEADER:
if (!on_header(frame))
{
return false;
}
break;
case cmux_state::PAYLOAD:
if (!on_payload(frame))
{
return false;
}
break;
case cmux_state::FOOTER:
if (!on_footer(frame))
{
return false;
}
break;
}
}
return true;
}
from esp-protocols.
@hqs1 Was your issue fixed by the recent CMUX changes? (I thought it could, as we added a locking mechanism when switching modes)
from esp-protocols.
@david-cermak The problem is still not solved, I try to create a task to read the signal quality constantly. However, this problem occurs when there is network data communication. Not sure if the dce handle is not thread safe
V (14061) Send: 0x3ffc9e40 f9 05 ef 5b |...[|
V (14071) Send: 0x3ffd899c 7e 21 45 00 00 28 00 04 00 00 ff 06 a5 dd 0a b9 |~!E..(..........|
V (14081) Send: 0x3ffd89ac 1b e0 2f 67 bf ee c9 d4 01 bb 14 2f 32 15 b6 19 |../g......./2...|
V (14091) Send: 0x3ffd89bc c4 f7 50 10 11 20 fb e0 00 00 09 f2 7e |..P.. ......~|
V (14091) Send: 0x3ffc9e44 d7 f9 |..|
V (14101) CMUX Received: 0x3ffcee8c 00 01 80 01 dc 7b b6 00 00 04 03 00 48 30 46 02 |.....{......H0F.|
V (14111) CMUX Received: 0x3ffcee9c 21 00 d0 74 b0 e6 61 49 8b 3a 31 01 12 3c 7a 9d |!..t..aI.:1..<z.|
V (14121) CMUX Received: 0x3ffceeac b9 5f cc 80 c1 04 26 89 d7 1d ea 17 a9 41 bb 98 |._....&......A..|
V (14131) CMUX Received: 0x3ffceebc b2 99 02 21 00 b5 df ab 09 1b 11 f4 5c 5e 78 50 |...!........\^xP|
V (14141) CMUX Received: 0x3ffceecc 13 15 d2 3b d4 60 b6 05 c1 d5 31 22 cc 29 1d 08 |...;.`....1".)..|
V (14151) CMUX Received: 0x3ffceedc bb 33 96 99 22 00 77 00 6f 53 76 ac 31 f0 31 19 |.3..".w.oSv.1.1.|
V (14161) CMUX Received: 0x3ffceeec d8 99 00 a4 51 15 ff 77 15 1c 11 d9 02 c1 00 29 |....Q..w.......)|
V (14171) CMUX Received: 0x3ffceefc 06 8d b2 08 9a 37 d9 13 00 00 01 80 01 dc 78 65 |.....7........xe|
I (14181) cmux: get_rssi!!!
V (14181) command_lib: get_signal_quality
V (14191) command_lib: generic_get_string
V (14191) Send: 0x3ffd0530 f9 09 ef 0f |....|
V (14201) Send: 0x3ffd0658 41 54 2b 43 53 51 0d |AT+CSQ.|
V (14211) Send: 0x3ffd0534 3b f9 |;.|
abort() was called at PC 0x40095ff9 on core 0
0x40095ff9: esp_modem::DTE::command(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::function<esp_modem::command_result (unsigned char*, unsigned int)>, unsigned int, char) at C:\Users\HQS\Desktop\4g_modem\build/../components/esp_modem/include/cxx_include/esp_modem_exception.hpp:63
(inlined by) esp_modem::DTE::command(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::function<esp_modem::command_result (unsigned char*, unsigned int)>, unsigned
int, char) at C:\Users\HQS\Desktop\4g_modem\build/../components/esp_modem/src/esp_modem_dte.cpp:59
Backtrace:0x4002395a:0x3ffd04e00x40028abd:0x3ffd0500 0x4002ecba:0x3ffd0520 0x40095ff9:0x3ffd0590 0x40096607:0x3ffd0600 0x40098ea2:0x3ffd0630 0x40094ec5:0x3ffd0690 0x400f145d:0x3ffd06b0 0x40088839:0x3ffd06d0 0x4002bd6d:0x3ffd0710
0x4002395a: panic_abort at C:/Users/HQS/esp/esp-idf/components/esp_system/panic.c:402
0x40028abd: esp_system_abort at C:/Users/HQS/esp/esp-idf/components/esp_system/esp_system.c:128
0x4002ecba: abort at C:/Users/HQS/esp/esp-idf/components/newlib/abort.c:46
0x40095ff9: esp_modem::DTE::command(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::function<esp_modem::command_result (unsigned char*, unsigned int)>, unsigned int, char) at C:\Users\HQS\Desktop\4g_modem\build/../components/esp_modem/include/cxx_include/esp_modem_exception.hpp:63
(inlined by) esp_modem::DTE::command(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::function<esp_modem::command_result (unsigned char*, unsigned int)>, unsigned
int, char) at C:\Users\HQS\Desktop\4g_modem\build/../components/esp_modem/src/esp_modem_dte.cpp:59
0x40096607: esp_modem::DTE::command(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::function<esp_modem::command_result (unsigned char*, unsigned int)>, unsigned int) at C:\Users\HQS\Desktop\4g_modem\build/../components/esp_modem/src/esp_modem_dte.cpp:68
0x40098ea2: esp_modem::dce_commands::get_signal_quality(esp_modem::CommandableIf*, int&, int&) at C:\Users\HQS\Desktop\4g_modem\build/../components/esp_modem/src/esp_modem_command_library.cpp:64
(inlined by) esp_modem::dce_commands::get_signal_quality(esp_modem::CommandableIf*, int&, int&) at C:\Users\HQS\Desktop\4g_modem\build/../components/esp_modem/src/esp_modem_command_library.cpp:393
0x40094ec5: esp_modem::GenericModule::get_signal_quality(int&, int&) at C:\Users\HQS\Desktop\4g_modem\build/../components/esp_modem/src/esp_modem_modules.cpp:46
0x400f145d: esp_modem::command_result esp_modem::DCE::get_signal_quality<int&, int&>(int&, int&) at C:\Users\HQS\Desktop\4g_modem\build/../components/esp_modem/include/cxx_include/esp_modem_dce.hpp:117
(inlined by) esp_modem_get_signal_quality at C:\Users\HQS\Desktop\4g_modem\build/../components/esp_modem/src/esp_modem_c_api.cpp:206
0x40088839: get_rssi_tim at C:\Users\HQS\Desktop\4g_modem\build/../main/cmux/cmux.c:144
0x4002bd6d: vPortTaskWrapper at C:/Users/HQS/esp/esp-idf/components/freertos/port/xtensa/port.c:131
ELF file SHA256: d8057b498a1a4f39
Rebooting...
ESP-ROM:esp32s2-rc4-20191025
Build:Oct 25 2019
rst:0x3 (RTC_SW_SYS_RST),boot:0x8 (SPI_FAST_FLASH_BOOT)
Saved PC:0x400234e5
0x400234e5: esp_restart_noos_dig at C:/Users/HQS/esp/esp-idf/components/esp_system/esp_system.c:44 (discriminator 1)
SPIWP:0xee
mode:DIO, clock div:1
load:0x3ffe6100,len:0x1768
load:0x4004c000,len:0xa48
load:0x40050000,len:0x2e58
entry 0x4004c204
I (24) boot: ESP-IDF v4.4.1 2nd stage bootloader
I (24) boot: compile time 16:06:41
I (24) boot: chip revision: 0
I (26) boot.esp32s2: SPI Speed : 80MHz
I (31) boot.esp32s2: SPI Mode : DIO
I (36) boot.esp32s2: SPI Flash Size : 4MB
I (40) boot: Enabling RNG early entropy source...
I (46) boot: Partition Table:
I (49) boot: ## Label Usage Type ST Offset Length
I (57) boot: 0 nvs WiFi data 01 02 00009000 00003000
I (64) boot: 1 otadata OTA data 01 00 0000d000 00002000
I (72) boot: 2 phy_init RF data 01 01 0000f000 00001000
I (79) boot: 3 factory factory app 00 00 00010000 00100000
I (86) boot: 4 ota_0 OTA app 00 10 00110000 00100000
I (94) boot: 5 ota_1 OTA app 00 11 00210000 00100000
I (101) boot: 6 nvs_key NVS keys 01 04 00310000 00001000
I (109) boot: End of partition table
I (113) boot: Defaulting to factory image
I (118) esp_image: segment 0: paddr=00010020 vaddr=3f000020 size=1cb60h (117600) map
I (150) esp_image: segment 1: paddr=0002cb88 vaddr=3ffc02c0 size=01f5ch ( 8028) load
I (152) esp_image: segment 2: paddr=0002eaec vaddr=40022000 size=0152ch ( 5420) load
I (157) esp_image: segment 3: paddr=00030020 vaddr=40080020 size=74574h (476532) map
I (259) esp_image: segment 4: paddr=000a459c vaddr=4002352c size=0cd8ch ( 52620) load
I (272) esp_image: segment 5: paddr=000b1330 vaddr=50000000 size=00010h ( 16) load
I (280) boot: Loaded app from partition at offset 0x10000
I (280) boot: Disabling RNG early entropy source...
I (293) cache: Instruction cache : size 8KB, 4Ways, cache line size 32Byte
I (293) cpu_start: Pro cpu up.
D (300) clk: RTC_SLOW_CLK calibration value: 6415770
I (309) cpu_start: Pro cpu start user code
I (309) cpu_start: cpu freq: 240000000
I (309) cpu_start: Application information:
I (314) cpu_start: Project name: 4g_modem
I (319) cpu_start: App version: 1.0.1
I (324) cpu_start: Compile time: Jun 24 2022 18:46:42
I (330) cpu_start: ELF file SHA256: d8057b498a1a4f39...
I (336) cpu_start: ESP-IDF: v4.4.1
from esp-protocols.
Ok, let me re-open this and ask you if you can provide steps to reproduce this problem. Thanks!
from esp-protocols.
Thanks for the reply, here I download a relatively large picture through http to simulate the network data download, and create a task at the same time, this task is to execute the AT command at intervals to obtain the signal quality of the 4G modem.
code show as below
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/event_groups.h"
#include "esp_netif.h"
#include "esp_netif_ppp.h"
#include "mqtt_client.h"
#include "esp_modem_api.h"
#include "esp_log.h"
#include "esp_http_client.h"
static EventGroupHandle_t event_group = NULL;
static const int CONNECT_BIT = BIT0;
esp_modem_dce_t *dce = NULL;
static const char *TAG = "cmux_example_c";
void get_rssi_tim(void *dce_handle);
esp_err_t _http_event_handle(esp_http_client_event_t *evt)
{
switch (evt->event_id)
{
case HTTP_EVENT_ERROR:
ESP_LOGI(TAG, "HTTP_EVENT_ERROR");
break;
case HTTP_EVENT_ON_CONNECTED:
ESP_LOGI(TAG, "HTTP_EVENT_ON_CONNECTED");
break;
case HTTP_EVENT_HEADER_SENT:
ESP_LOGI(TAG, "HTTP_EVENT_HEADER_SENT");
break;
case HTTP_EVENT_ON_HEADER:
ESP_LOGI(TAG, "HTTP_EVENT_ON_HEADER");
// printf("%.*s", evt->data_len, (char *)evt->data);
break;
case HTTP_EVENT_ON_DATA:
ESP_LOGI(TAG, "HTTP_EVENT_ON_DATA, len=%d", evt->data_len);
if (!esp_http_client_is_chunked_response(evt->client))
{
// printf("%.*s", evt->data_len, (char *)evt->data);
}
break;
case HTTP_EVENT_ON_FINISH:
ESP_LOGI(TAG, "HTTP_EVENT_ON_FINISH");
break;
case HTTP_EVENT_DISCONNECTED:
ESP_LOGI(TAG, "HTTP_EVENT_DISCONNECTED");
break;
}
return ESP_OK;
}
static void on_ppp_changed(void *arg, esp_event_base_t event_base,
int32_t event_id, void *event_data)
{
ESP_LOGI(TAG, "PPP state changed event %d", event_id);
if (event_id == NETIF_PPP_ERRORUSER)
{
/* User interrupted event from esp-netif */
esp_netif_t *netif = event_data;
ESP_LOGI(TAG, "User interrupted event from netif:%p", netif);
}
}
static void on_ip_event(void *arg, esp_event_base_t event_base,
int32_t event_id, void *event_data)
{
ESP_LOGD(TAG, "IP event! %d", event_id);
if (event_id == IP_EVENT_PPP_GOT_IP)
{
esp_netif_dns_info_t dns_info;
ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data;
esp_netif_t *netif = event->esp_netif;
ESP_LOGI(TAG, "Modem Connect to PPP Server");
ESP_LOGI(TAG, "~~~~~~~~~~~~~~");
ESP_LOGI(TAG, "IP : " IPSTR, IP2STR(&event->ip_info.ip));
ESP_LOGI(TAG, "Netmask : " IPSTR, IP2STR(&event->ip_info.netmask));
ESP_LOGI(TAG, "Gateway : " IPSTR, IP2STR(&event->ip_info.gw));
esp_netif_get_dns_info(netif, 0, &dns_info);
ESP_LOGI(TAG, "Name Server1: " IPSTR, IP2STR(&dns_info.ip.u_addr.ip4));
esp_netif_get_dns_info(netif, 1, &dns_info);
ESP_LOGI(TAG, "Name Server2: " IPSTR, IP2STR(&dns_info.ip.u_addr.ip4));
ESP_LOGI(TAG, "~~~~~~~~~~~~~~");
xEventGroupSetBits(event_group, CONNECT_BIT);
ESP_LOGI(TAG, "GOT ip event!!!");
}
else if (event_id == IP_EVENT_PPP_LOST_IP)
{
ESP_LOGI(TAG, "Modem Disconnect from PPP Server");
}
else if (event_id == IP_EVENT_GOT_IP6)
{
ESP_LOGI(TAG, "GOT IPv6 event!");
ip_event_got_ip6_t *event = (ip_event_got_ip6_t *)event_data;
ESP_LOGI(TAG, "Got IPv6 address " IPV6STR, IPV62STR(event->ip6_info.ip));
}
}
void app_main(void)
{
ESP_ERROR_CHECK(esp_netif_init());
ESP_ERROR_CHECK(esp_event_loop_create_default());
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, ESP_EVENT_ANY_ID, &on_ip_event, NULL));
ESP_ERROR_CHECK(esp_event_handler_register(NETIF_PPP_STATUS, ESP_EVENT_ANY_ID, &on_ppp_changed, NULL));
event_group = xEventGroupCreate();
esp_modem_dte_config_t dte_config = ESP_MODEM_DTE_DEFAULT_CONFIG();
dte_config.uart_config.tx_io_num = 10;
dte_config.uart_config.rx_io_num = 9;
/* Configure the DCE */
esp_modem_dce_config_t dce_config = ESP_MODEM_DCE_DEFAULT_CONFIG(CONFIG_EXAMPLE_MODEM_PPP_APN);
/* Configure the PPP netif */
esp_netif_config_t netif_ppp_config = ESP_NETIF_DEFAULT_PPP();
// Init netif object
esp_netif_t *esp_netif = esp_netif_new(&netif_ppp_config);
assert(esp_netif);
dce = esp_modem_new(&dte_config, &dce_config, esp_netif);
assert(dce);
esp_err_t err = ESP_OK;
do
{
err = esp_modem_sync(dce);
vTaskDelay(pdMS_TO_TICKS(1000));
} while (err == ESP_ERR_TIMEOUT);
err = esp_modem_set_mode(dce, ESP_MODEM_MODE_CMUX);
xEventGroupWaitBits(event_group, CONNECT_BIT, pdTRUE, pdTRUE, portMAX_DELAY);
xTaskCreate(get_rssi_tim, "get_rssi_tim", 4096, dce, 10, NULL);
while (1)
{
esp_http_client_config_t config = {
.url = "http://test.hqshome.cn/image.jpg",
.event_handler = _http_event_handle,
};
esp_http_client_handle_t client = esp_http_client_init(&config);
esp_err_t err = esp_http_client_perform(client);
if (err == ESP_OK)
{
ESP_LOGI(TAG, "Status = %d, content_length = %d",
esp_http_client_get_status_code(client),
esp_http_client_get_content_length(client));
}
esp_http_client_cleanup(client);
vTaskDelay(pdMS_TO_TICKS(1000));
}
}
void get_rssi_tim(void *dce_handle)
{
int rssi, ber;
for (;;)
{
ESP_LOGI(TAG,"about to get rssi");
esp_err_t err = esp_modem_get_signal_quality(dce_handle, &rssi, &ber);
if (err != ESP_OK)
{
ESP_LOGE(TAG, "get_rssi_tim failed with %d", err);
}
ESP_LOGI(TAG, "Signal quality: rssi=%d, ber=%d", rssi, ber);
vTaskDelay(pdMS_TO_TICKS(1000));
}
vTaskDelete(NULL);
}
from esp-protocols.
@hqs1 Thanks for sharing the detailed STR! Will try to reproduce the problem on my end.
In the meantime, could you please try to remove this line:
I suspect the defragmenting code in CMUX protocol might cause this corruption.
from esp-protocols.
@david-cermak After deletion the buffer_size variable will be undefined
from esp-protocols.
Oh, sorry. Missed this in the last unique-buffer
refactor; should be buffer.size
instead of buffer_size
(dot, not underscore)
diff --git a/components/esp_modem/src/esp_modem_cmux.cpp b/components/esp_modem/src/esp_modem_cmux.cpp
index 0102162..eac83c0 100644
--- a/components/esp_modem/src/esp_modem_cmux.cpp
+++ b/components/esp_modem/src/esp_modem_cmux.cpp
@@ -25,7 +25,7 @@ using namespace esp_modem;
* This is useful if upper layers expect the entire payload available
* for parsing.
*/
-#define DEFRAGMENT_CMUX_PAYLOAD
+//#define DEFRAGMENT_CMUX_PAYLOAD
#define EA 0x01 /* Extension bit */
#define CR 0x02 /* Command / Response */
@@ -286,7 +286,7 @@ bool CMux::on_cmux_data(uint8_t *data, size_t actual_len)
actual_len = term->read(data, data_to_read);
#else
data = buffer.get();
- actual_len = term->read(data, buffer_size);
+ actual_len = term->read(data, buffer.size);
#endif
from esp-protocols.
@david-cermak Now after deleting the macro definition, there is no previous problem. Although it is said that because the serial port reads a large amount of data, the watchdog will be triggered, but it does not affect the network data transmission and the signal quality of the AT command to read the 4G modem.
from esp-protocols.
Thanks for testing this! This explains the problem and also the reason I wasn't able to reproduce the problem. IIRC your modem sends bigger payloads. The defragmenting logic however expects the max payload on CMUX level to be 127
(one byte length) and I doesn't provide any means to limit the buffer size (unless we set really big buffer sizes).
I think the WDT issue would disappear if you set less verbose logging (Debug/Info), as it seems it waits for printing the raw data to the console (ESP_LOG()
or ESP_HEXDUMP()
)
I'll think about the way of enabling the defragmening dynamically, only on limited payloads...
from esp-protocols.
Related Issues (20)
- UART_BUFFER_FULL event should be ignored in esp_modem_uart.cpp when using hw flow control. (IDFGH-11459) HOT 5
- esp_modem: Provide an example for adding a new Module/Device. (IDFGH-11463) HOT 4
- esp_modem: `set_data_mode` contains a superfluous hash (ATD*99##) (IDFGH-11464)
- esp_modem: get rid of fixed 10s Wait in pppos_client sample (IDFGH-11472) HOT 1
- esp-modem: handle SIM card is deactivated (IDFGH-11605) HOT 10
- console_cmd_ifconfig: not supporting the ppp netif and will panic (IDFGH-11607) HOT 2
- modem_console get_module_name does not call the SHINY function (IDFGH-11628) HOT 1
- Timeout for setting PDP (AT+CGDCONT) in esp-modem is probably wrong? (IDFGH-11638) HOT 4
- Question about Data Mode vs. AT Mode (IDFGH-11668) HOT 1
- websocket not able to receive all the chunk of the data and getting parts when receiving (IDFGH-11691) HOT 1
- Build fails if ETH is enabled, but removed from predefined netifs (IDFGH-11692) HOT 1
- websocket client decided to send first a FIN then a continuation, which is not allowed?! (IDFGH-11736) HOT 5
- When ECHO is deactivated and try to send random AT command AT+CSQ for example using dce->at(). at() returns OK but the response is corrupted. (IDFGH-11753) HOT 1
- Define a subdomain using mDNS (IDFGH-11757) HOT 4
- problems migrating ESP-Modem from 2020-version to 1.0.5 (IDFGH-11815) HOT 9
- Feature Request: Full Response from ESP32 AT SIM Commands (IDFGH-11834)
- ESP_MODEM_MODE_COMMAND fires IP_EVENT_PPP_LOST_IP only after 120 seconds (IDFGH-11871) HOT 4
- OTA fails due to many "HW FIFO Overflows" (IDFGH-11892) HOT 2
- set APN after esp_modem_new_dev() is called? (IDFGH-11898) HOT 2
- Broken link (IDFGH-11903) HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from esp-protocols.