bytebeamio / bytebeam-arduino-sdk Goto Github PK
View Code? Open in Web Editor NEWA small Arduino Library for Bytebeam Cloud that just works
Home Page: https://bytebeam.io/docs/arduino
License: Apache License 2.0
A small Arduino Library for Bytebeam Cloud that just works
Home Page: https://bytebeam.io/docs/arduino
License: Apache License 2.0
esp32s3
dev kitc1
latest
latest
arduino IDE
macOs 13.6.6
Running the SetupClient_GSM does not compile. The first error is due to a bad signature for Bytebeam.begin(&modem)
, which can be resolved by adding:
#define BYTEBEAM_ARDUINO_USE_MODEM
to the top of the file.
However, the errors (pasted below) cannot be resolved with this line:
#undef BYTEBEAM_ARDUINO_USE_WIFI
and it is unclear how to override the definitions set in BytebeamArduinoDefines.h
#define TINY_GSM_MODEM_SIM7600
// Added next two lines
#define BYTEBEAM_ARDUINO_USE_MODEM
#undef BYTEBEAM_ARDUINO_USE_WIFI
#include <TinyGsmClient.h>
#include <BytebeamArduino.h>
#include "arduino_secrets.h"
//
// By including the above header you got the access to the gloabl object named Bytebeam
// Use Bytebeam global object to perform the required operations
//
#define LED_PIN 42
#define MODEM_PWRKEY 20
#define MODEM_FLIGHT 19
#define MODEM_TX 36
#define MODEM_RX 37
// set GSM PIN, if any
#define GSM_PIN SECRET_PIN
#define SerialMon Serial
#define SerialAT Serial1
// Your GPRS credentials, if any
const char apn[] = SECRET_APN;
TinyGsm modem(SerialAT);
// function to setup the modem with predefined credentials
void setupModem() {
// configure your reset, enable pins here if needed
pinMode(LED_PIN, OUTPUT);
pinMode(MODEM_PWRKEY, OUTPUT);
pinMode(MODEM_FLIGHT, OUTPUT);
// set the status led pin low to indicate the start process
digitalWrite(LED_PIN, LOW);
// pull up power pin (IO:4) Modulator power key, need to powered up the modem
// this pin must be held high for more than 1 second according to manual requirements
digitalWrite(MODEM_PWRKEY, LOW);
delay(100);
digitalWrite(MODEM_PWRKEY, HIGH);
delay(1000);
digitalWrite(MODEM_PWRKEY, LOW);
// pull up the power pin (IO:25) Modulator flight mode control, need to enable modulator
// this pin must be set to high
digitalWrite(MODEM_FLIGHT, HIGH);
SerialMon.println("Modem Powered ON");
// start the serial communication b/w esp32 and modem
SerialAT.begin(115200, SERIAL_8N1, MODEM_RX, MODEM_TX);
delay(6000);
// Restart takes quite some time
// To skip it, call init() instead of restart()
// modem.restart();
modem.init();
// set the network mode (2 : Automatic)
modem.setNetworkMode(38);
String modemName = modem.getModemName();
SerialMon.printf("Modem Name : ");
SerialMon.println(modemName);
String modemInfo = modem.getModemInfo();
SerialMon.print("Modem Info : ");
SerialMon.println(modemInfo);
// Unlock your SIM card with a PIN if needed
if(GSM_PIN && modem.getSimStatus() != 3) {
modem.simUnlock(GSM_PIN);
}
SimStatus simStatus = modem.getSimStatus();
if(simStatus != SIM_READY) {
SerialMon.println("Couldn't Ready the SIM.");
return;
}
SerialMon.println("SIM is Ready.");
// high indicates the modem is initialized successfully
digitalWrite(LED_PIN, HIGH);
SerialMon.println("Modem Initialized Successfully !");
SerialMon.println("Waiting for network...");
if(!modem.waitForNetwork()) {
SerialMon.println(" fail");
delay(10000);
return;
}
SerialMon.println(" success");
if(modem.isNetworkConnected()) {
SerialMon.println("Network connected");
}
// GPRS connection parameters are usually set after network registration
SerialMon.print("Connecting to apn : ");
SerialMon.println(apn);
if (!modem.gprsConnect(apn)) {
SerialMon.println(" fail");
delay(10000);
return;
}
SerialMon.println(" success");
if(modem.isGprsConnected()) {
SerialMon.println("GPRS connected");
}
}
// function to sync time from ntp server with predefined credentials
void syncTimeFromNtp() {
String dateTime = modem.getGSMDateTime(DATE_FULL);
SerialMon.print("Current Time : ");
SerialMon.println(dateTime);
SerialMon.println();
}
void setup() {
// put your setup code here, to run once:
SerialMon.begin(115200);
SerialMon.println();
setupModem();
syncTimeFromNtp();
//
// Your other application setup stuff goes here
//
// setting up the device info i.e to be seen in the device shadow
Bytebeam.status = "Device is Up!";
Bytebeam.softwareType = "setup-gsm-client-ino";
Bytebeam.softwareVersion = "1.0.0";
Bytebeam.hardwareType = "ESP32 Dev Module";
Bytebeam.hardwareVersion = "rev1";
// This method will initialize and start the bytebeam client
// You can over-ride the default file system, file name and library logging options, if needed
// eg. Bytebeam.begin(BytebeamArduino::LITTLEFS_FILE_SYSTEM, "/my_device_config.json", BytebeamLogger::LOG_INFO)
if(!Bytebeam.begin(&modem)) {
Serial.println("Bytebeam Client Initialization Failed.");
} else {
Serial.println("Bytebeam Client is Initialized Successfully.");
}
//
// If above call is successfull then the bytebeam client is now configured for the use
// You can always check for the logs in serial monitor for the status of the above call
//
// check if bytebeam client is connected or disconnected
bool connectionStatus = Bytebeam.isConnected();
if(!connectionStatus) {
SerialMon.println("Bytebeam Client is Disconnected.");
} else {
SerialMon.println("Bytebeam Client is Connected.");
}
// Call the end method to stop and de-initialize the bytebeam client at any point of time in the code
// Bytebeam.end();
}
void loop() {
// put your main code here, to run repeatedly:
//
// Your application regular stuff goes here
//
// This method will let you maintain the connection with the bytebeam cloud, In case
// the connection is lost, it will attempt to reconnect to the bytebeam cloud
Bytebeam.loop();
// software delay, you can customize it as per your application needs
delay(5000);
}
In file included from /Users/enzo/Documents/Arduino/libraries/BytebeamArduino/src/BytebeamArduinoDefines.h:44,
from /Users/enzo/Documents/Arduino/libraries/BytebeamArduino/src/BytebeamTime.h:4,
from /Users/enzo/Documents/Arduino/libraries/BytebeamArduino/src/BytebeamLog.h:6,
from /Users/enzo/Documents/Arduino/libraries/BytebeamArduino/src/BytebeamArduino.h:7,
from /private/var/folders/c0/j9v4g6bd73v6r7pmyn31jb000000gn/T/.arduinoIDE-unsaved202438-41671-j9mlnv.2j8dd/SetupClient_GSM/SetupClient_GSM.ino:6:
/Users/enzo/Documents/Arduino/libraries/BytebeamArduino/src/BytebeamHTTPUpdate.h:24:5: error: 'HTTP_UPDATE_FAILED' conflicts with a previous declaration
HTTP_UPDATE_FAILED,
^~~~~~~~~~~~~~~~~~
In file included from /Users/enzo/Documents/Arduino/libraries/BytebeamArduino/src/BytebeamArduinoDefines.h:37,
from /Users/enzo/Documents/Arduino/libraries/BytebeamArduino/src/BytebeamTime.h:4,
from /Users/enzo/Documents/Arduino/libraries/BytebeamArduino/src/BytebeamLog.h:6,
from /Users/enzo/Documents/Arduino/libraries/BytebeamArduino/src/BytebeamArduino.h:7,
from /private/var/folders/c0/j9v4g6bd73v6r7pmyn31jb000000gn/T/.arduinoIDE-unsaved202438-41671-j9mlnv.2j8dd/SetupClient_GSM/SetupClient_GSM.ino:6:
/Users/enzo/Library/Arduino15/packages/esp32/hardware/esp32/2.0.14/libraries/HTTPUpdate/src/HTTPUpdate.h:48:5: note: previous declaration 'HTTPUpdateResult HTTP_UPDATE_FAILED'
HTTP_UPDATE_FAILED,
^~~~~~~~~~~~~~~~~~
In file included from /Users/enzo/Documents/Arduino/libraries/BytebeamArduino/src/BytebeamArduinoDefines.h:44,
from /Users/enzo/Documents/Arduino/libraries/BytebeamArduino/src/BytebeamTime.h:4,
from /Users/enzo/Documents/Arduino/libraries/BytebeamArduino/src/BytebeamLog.h:6,
from /Users/enzo/Documents/Arduino/libraries/BytebeamArduino/src/BytebeamArduino.h:7,
from /private/var/folders/c0/j9v4g6bd73v6r7pmyn31jb000000gn/T/.arduinoIDE-unsaved202438-41671-j9mlnv.2j8dd/SetupClient_GSM/SetupClient_GSM.ino:6:
/Users/enzo/Documents/Arduino/libraries/BytebeamArduino/src/BytebeamHTTPUpdate.h:25:5: error: 'HTTP_UPDATE_NO_UPDATES' conflicts with a previous declaration
HTTP_UPDATE_NO_UPDATES,
^~~~~~~~~~~~~~~~~~~~~~
In file included from /Users/enzo/Documents/Arduino/libraries/BytebeamArduino/src/BytebeamArduinoDefines.h:37,
from /Users/enzo/Documents/Arduino/libraries/BytebeamArduino/src/BytebeamTime.h:4,
from /Users/enzo/Documents/Arduino/libraries/BytebeamArduino/src/BytebeamLog.h:6,
from /Users/enzo/Documents/Arduino/libraries/BytebeamArduino/src/BytebeamArduino.h:7,
from /private/var/folders/c0/j9v4g6bd73v6r7pmyn31jb000000gn/T/.arduinoIDE-unsaved202438-41671-j9mlnv.2j8dd/SetupClient_GSM/SetupClient_GSM.ino:6:
/Users/enzo/Library/Arduino15/packages/esp32/hardware/esp32/2.0.14/libraries/HTTPUpdate/src/HTTPUpdate.h:49:5: note: previous declaration 'HTTPUpdateResult HTTP_UPDATE_NO_UPDATES'
HTTP_UPDATE_NO_UPDATES,
^~~~~~~~~~~~~~~~~~~~~~
In file included from /Users/enzo/Documents/Arduino/libraries/BytebeamArduino/src/BytebeamArduinoDefines.h:44,
from /Users/enzo/Documents/Arduino/libraries/BytebeamArduino/src/BytebeamTime.h:4,
from /Users/enzo/Documents/Arduino/libraries/BytebeamArduino/src/BytebeamLog.h:6,
from /Users/enzo/Documents/Arduino/libraries/BytebeamArduino/src/BytebeamArduino.h:7,
from /private/var/folders/c0/j9v4g6bd73v6r7pmyn31jb000000gn/T/.arduinoIDE-unsaved202438-41671-j9mlnv.2j8dd/SetupClient_GSM/SetupClient_GSM.ino:6:
/Users/enzo/Documents/Arduino/libraries/BytebeamArduino/src/BytebeamHTTPUpdate.h:26:5: error: 'HTTP_UPDATE_OK' conflicts with a previous declaration
HTTP_UPDATE_OK
^~~~~~~~~~~~~~
In file included from /Users/enzo/Documents/Arduino/libraries/BytebeamArduino/src/BytebeamArduinoDefines.h:37,
from /Users/enzo/Documents/Arduino/libraries/BytebeamArduino/src/BytebeamTime.h:4,
from /Users/enzo/Documents/Arduino/libraries/BytebeamArduino/src/BytebeamLog.h:6,
from /Users/enzo/Documents/Arduino/libraries/BytebeamArduino/src/BytebeamArduino.h:7,
from /private/var/folders/c0/j9v4g6bd73v6r7pmyn31jb000000gn/T/.arduinoIDE-unsaved202438-41671-j9mlnv.2j8dd/SetupClient_GSM/SetupClient_GSM.ino:6:
/Users/enzo/Library/Arduino15/packages/esp32/hardware/esp32/2.0.14/libraries/HTTPUpdate/src/HTTPUpdate.h:50:5: note: previous declaration 'HTTPUpdateResult HTTP_UPDATE_OK'
HTTP_UPDATE_OK
^~~~~~~~~~~~~~
In file included from /Users/enzo/Documents/Arduino/libraries/BytebeamArduino/src/BytebeamArduinoDefines.h:44,
from /Users/enzo/Documents/Arduino/libraries/BytebeamArduino/src/BytebeamTime.h:4,
from /Users/enzo/Documents/Arduino/libraries/BytebeamArduino/src/BytebeamLog.h:6,
from /Users/enzo/Documents/Arduino/libraries/BytebeamArduino/src/BytebeamArduino.h:7,
from /private/var/folders/c0/j9v4g6bd73v6r7pmyn31jb000000gn/T/.arduinoIDE-unsaved202438-41671-j9mlnv.2j8dd/SetupClient_GSM/SetupClient_GSM.ino:6:
/Users/enzo/Documents/Arduino/libraries/BytebeamArduino/src/BytebeamHTTPUpdate.h:29:34: error: conflicting declaration 'typedef enum BytebeamHTTPUpdateResult t_httpUpdate_return'
typedef BytebeamHTTPUpdateResult t_httpUpdate_return; // backward compatibility
^~~~~~~~~~~~~~~~~~~
In file included from /Users/enzo/Documents/Arduino/libraries/BytebeamArduino/src/BytebeamArduinoDefines.h:37,
from /Users/enzo/Documents/Arduino/libraries/BytebeamArduino/src/BytebeamTime.h:4,
from /Users/enzo/Documents/Arduino/libraries/BytebeamArduino/src/BytebeamLog.h:6,
from /Users/enzo/Documents/Arduino/libraries/BytebeamArduino/src/BytebeamArduino.h:7,
from /private/var/folders/c0/j9v4g6bd73v6r7pmyn31jb000000gn/T/.arduinoIDE-unsaved202438-41671-j9mlnv.2j8dd/SetupClient_GSM/SetupClient_GSM.ino:6:
/Users/enzo/Library/Arduino15/packages/esp32/hardware/esp32/2.0.14/libraries/HTTPUpdate/src/HTTPUpdate.h:53:26: note: previous declaration as 'typedef enum HTTPUpdateResult t_httpUpdate_return'
typedef HTTPUpdateResult t_httpUpdate_return; // backward compatibility
^~~~~~~~~~~~~~~~~~~
In file included from /Users/enzo/Documents/Arduino/libraries/BytebeamArduino/src/BytebeamArduino.h:9,
from /private/var/folders/c0/j9v4g6bd73v6r7pmyn31jb000000gn/T/.arduinoIDE-unsaved202438-41671-j9mlnv.2j8dd/SetupClient_GSM/SetupClient_GSM.ino:6:
/Users/enzo/Documents/Arduino/libraries/BytebeamArduino/src/BytebeamOTA.h:60:23: error: redeclaration of 'SSLClient BytebeamOTA::secureOTAClient'
SSLClient secureOTAClient;
^~~~~~~~~~~~~~~
/Users/enzo/Documents/Arduino/libraries/BytebeamArduino/src/BytebeamOTA.h:54:30: note: previous declaration 'WiFiClientSecure BytebeamOTA::secureOTAClient'
WiFiClientSecure secureOTAClient;
^~~~~~~~~~~~~~~
/Users/enzo/Documents/Arduino/libraries/BytebeamArduino/src/BytebeamOTA.h:61:51: error: redeclaration of 'BytebeamHTTPUpdate& BytebeamOTA::BytebeamUpdate'
BytebeamHTTPUpdate& BytebeamUpdate = BytebeamhttpUpdate;
^~~~~~~~~~~~~~~~~~
/Users/enzo/Documents/Arduino/libraries/BytebeamArduino/src/BytebeamOTA.h:55:43: note: previous declaration 'HTTPUpdate& BytebeamOTA::BytebeamUpdate'
HTTPUpdate& BytebeamUpdate = httpUpdate;
^~~~~~~~~~
In file included from /private/var/folders/c0/j9v4g6bd73v6r7pmyn31jb000000gn/T/.arduinoIDE-unsaved202438-41671-j9mlnv.2j8dd/SetupClient_GSM/SetupClient_GSM.ino:6:
/Users/enzo/Documents/Arduino/libraries/BytebeamArduino/src/BytebeamArduino.h:182:23: error: redeclaration of 'SSLClient BytebeamArduino::secureClient'
SSLClient secureClient;
^~~~~~~~~~~~
/Users/enzo/Documents/Arduino/libraries/BytebeamArduino/src/BytebeamArduino.h:177:30: note: previous declaration 'WiFiClientSecure BytebeamArduino::secureClient'
WiFiClientSecure secureClient;
^~~~~~~~~~~~
Multiple libraries were found for "WiFi.h"
Used: /Users/enzo/Library/Arduino15/packages/esp32/hardware/esp32/2.0.14/libraries/WiFi
Not used: /Users/enzo/Documents/Arduino/libraries/WiFiNINA
exit status 1
Compilation error: exit status 1
### More Information
_No response_
ESP32 Dev Module
ESP32 DevKitM1
NA
2.0.7
1.0.1
Arduino IDE
Windows 11
Just for testing purpose
void setup() {
// initialize serial port
Serial.begin(115200);
}
void loop() {
Serial.println("Hello World !");
delay(1000);
}
Here goes the serial debug logs
Any more information can be included here.
esp32-s3
DevKitC
Latest
1.1.0
ArduinoIDE and PlatformIO
macOs 13.6.6
From ArduinoIDE, I have provisioned the device using your example sketch with a json file I downloaded from my dashboard and it completes without errors.
Using SetupClient.ino with my WiFi and SSID, produces a "failed to connect" error without much more information.
#include <time.h>
#include <WiFi.h>
#include <BytebeamArduino.h>
#include "arduino_secrets.h"
//
// By including the above header you got the access to the gloabl object named Bytebeam
// Use Bytebeam global object to perform the required operations
//
// wifi credentials
const char* WIFI_SSID = SECRET_SSID;
const char* WIFI_PASSWORD = SECRET_PASS;
// sntp credentials
const long gmtOffset_sec = 19800; // GMT + 5:30h
const int daylightOffset_sec = 0;
const char* ntpServer = "pool.ntp.org";
// function to setup the wifi with predefined credentials
void setupWifi() {
// set the wifi to station mode to connect to a access point
WiFi.mode(WIFI_STA);
WiFi.begin(WIFI_SSID , WIFI_PASSWORD);
Serial.println();
Serial.print("Connecting to " + String(WIFI_SSID));
// wait till chip is being connected to wifi (Blocking Mode)
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
delay(250);
}
// now it is connected to the access point just print the ip assigned to chip
Serial.println();
Serial.print("Connected to " + String(WIFI_SSID) + ", Got IP address : ");
Serial.println(WiFi.localIP());
}
// function to sync time from ntp server with predefined credentials
void syncTimeFromNtp() {
// sync the time from ntp server
configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
struct tm timeinfo;
// get the current time
if(!getLocalTime(&timeinfo)) {
Serial.println("Failed to obtain time");
return;
}
// log the time info to serial :)
Serial.println(&timeinfo, "%A, %B %d %Y %H:%M:%S");
Serial.println();
}
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
Serial.println();
setupWifi();
syncTimeFromNtp();
//
// Your other application setup stuff goes here
//
// setting up the device info i.e to be seen in the device shadow
Bytebeam.status = "Device is Up!";
Bytebeam.softwareType = "setup-wifi-client-ino";
Bytebeam.softwareVersion = "1.0.0";
Bytebeam.hardwareType = "ESP32 Dev Module";
Bytebeam.hardwareVersion = "rev1";
// This method will initialize and start the bytebeam client
// You can over-ride the default file system, file name and library logging options, if needed
// eg. Bytebeam.begin(BytebeamArduino::LITTLEFS_FILE_SYSTEM, "/my_device_config.json", BytebeamLogger::LOG_INFO)
if(!Bytebeam.begin(BytebeamArduino::SPIFFS_FILE_SYSTEM, "/device_config.json", BytebeamLogger::LOG_DEBUG)) {
Serial.println("Bytebeam Client Initialization Failed.");
} else {
Serial.println("Bytebeam Client is Initialized Successfully.");
}
//
// If above call is successfull then the bytebeam client is now configured for the use
// You can always check for the logs in serial monitor for the status of the above call
//
// check if bytebeam client is connected or disconnected
bool connectionStatus = Bytebeam.isConnected();
if(!connectionStatus) {
Serial.println("Bytebeam Client is Disconnected.");
} else {
Serial.println("Bytebeam Client is Connected.");
}
// Call the end method to stop and de-initialize the bytebeam client at any point of time in the code
// Bytebeam.end();
}
void loop() {
// put your main code here, to run repeatedly:
//
// Your application regular stuff goes here
//
// This method will let you maintain the connection with the bytebeam cloud, In case
// the connection is lost, it will attempt to reconnect to the bytebeam cloud
Bytebeam.loop();
// software delay, you can customize it as per your application needs
delay(5000);
}
### Debug Message
```plain
BytebeamLogger::LOG_DEBUG (BytebeamArduino) readDeviceConfigFile : deviceConfigStr :
{
"project_id": "srbv3",
"broker": "cloud.bytebeam.io",
"port": 8883,
"device_id": "1",
"authentication": {
... etc
BytebeamLogger::LOG_INFO (BytebeamArduino) parseDeviceConfigFile : deserializeJson() success
BytebeamLogger::LOG_INFO (BytebeamArduino) parseDeviceConfigFile : Obtaining device config file variables
BytebeamLogger::LOG_INFO (BytebeamArduino) parseDeviceConfigFile : - obtain device config file variables
BytebeamLogger::LOG_DEBUG (BytebeamArduino) parseDeviceConfigFile : mqttPort : 8883
BytebeamLogger::LOG_DEBUG (BytebeamArduino) parseDeviceConfigFile : mqttBrokerUrl : cloud.bytebeam.io
BytebeamLogger::LOG_DEBUG (BytebeamArduino) parseDeviceConfigFile : deviceId : 1
BytebeamLogger::LOG_DEBUG (BytebeamArduino) parseDeviceConfigFile : projectId : srbv3
BytebeamLogger::LOG_DEBUG (BytebeamArduino) parseDeviceConfigFile : caCertPem :
... prints out certs
BytebeamLogger::LOG_DEBUG (BytebeamArduino) parseDeviceConfigFile : clientId : BytebeamClient
BytebeamLogger::LOG_INFO (BytebeamArduino) parseDeviceConfigFile : Project Id : srbv3 and Device Id : 1
BytebeamLogger::LOG_INFO (BytebeamOTA) retrieveOTAInfo : NVS: Retrieving OTA Information
BytebeamLogger::LOG_INFO (BytebeamArduino) initSDK : RESTART: Normal Reboot !
BytebeamLogger::LOG_INFO (BytebeamArduino) setupBytebeamClient : Connecting To Bytebeam Cloud ...
BytebeamLogger::LOG_ERROR (BytebeamArduino) setupBytebeamClient : ERROR
BytebeamLogger::LOG_ERROR (BytebeamArduino) initSDK : Initialization failed, error while connecting to cloud.
Bytebeam Client Initialization Failed.
BytebeamLogger::LOG_ERROR (BytebeamArduino) isConnected : Bytebeam Client is not Initialized.
Bytebeam Client is Disconnected.
BytebeamLogger::LOG_ERROR (BytebeamArduino) loop : Bytebeam Client is not Initialized.
### More Information
Additionally, I was not able to use this library with PlatformIO as it raised NUMEROUS exceptions. The sketches compile in ArduinoIDE. I installed the dependencies manually in both cases.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.