rmqtt / rmqtt Goto Github PK
View Code? Open in Web Editor NEWMQTT Server/MQTT Broker - Scalable Distributed MQTT Message Broker for IoT in the 5G Era
License: MIT License
MQTT Server/MQTT Broker - Scalable Distributed MQTT Message Broker for IoT in the 5G Era
License: MIT License
This would work very well with SurrealDB because
it has live queries
It needs a kv Store to make it scale out to many nodes.
Best to just google it and how it uses tikv currrently to scale out.
you can also scale it out by feeding mutations into rmqtt and rmqtt feeds into many SurrealDB. Reads go directly to SurrealDB.
fisrt run:
cargo run --example basic
then:
cargo run --example client
result:
(base) ➜ ntex-mqtt git:(master) ✗ cargo run --example client
Compiling ntex-mqtt v1.0.0 (/Users/lchjczw/work/rust/project/ntex-mqtt)
Finished dev [unoptimized + debuginfo] target(s) in 2.07s
Running `target/debug/examples/client`
[2024-02-03T07:19:08Z TRACE ntex_mqtt::v5::client::connector] Connect ack response from server: ConnectAck {
session_present: false,
reason_code: Success,
session_expiry_interval_secs: None,
receive_max: 15,
max_qos: AtLeastOnce,
max_packet_size: None,
assigned_client_id: None,
topic_alias_max: 32,
retain_available: true,
wildcard_subscription_available: true,
subscription_identifiers_available: true,
shared_subscription_available: true,
server_keepalive_sec: None,
response_info: None,
server_reference: None,
auth_method: None,
auth_data: None,
reason_string: None,
user_properties: [],
}
[2024-02-03T07:19:08Z TRACE ntex_mqtt::v5::sink] Sending subscribe packet Subscribe {
packet_id: 1,
id: None,
user_properties: [],
topic_filters: [
(
"response",
SubscriptionOptions {
qos: AtLeastOnce,
no_local: false,
retain_as_published: false,
retain_handling: AtSubscribe,
},
),
],
}
[2024-02-03T07:19:08Z DEBUG ntex_mqtt::v5::client::connection] start mqtt client keep-alive task
[2024-02-03T07:19:08Z TRACE ntex_mqtt::v5::client::dispatcher] Dispatch packet: DispatchItem::Item((Disconnect(Disconnect { reason_code: UnspecifiedError, session_expiry_interval_secs: None, server_reference: None, reason_string: None, user_properties: [] }), 2))
[2024-02-03T07:19:08Z TRACE ntex_mqtt::v5::client::dispatcher] Dispatch packet: DispatchItem::Disconnect(None)
[2024-02-03T07:19:08Z TRACE ntex_mqtt::io] TCP-CLIENT: io shutdown completed
[2024-02-03T07:19:08Z TRACE ntex_mqtt::io] TCP-CLIENT: Service shutdown is completed, stop
thread 'main' panicked at examples/client.rs:56:10:
called `Result::unwrap()` on an `Err` value: Disconnected
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Panic in Arbiter thread.
(base) ➜ ntex-mqtt git:(master) ✗ cargo run --example basic
Finished dev [unoptimized + debuginfo] target(s) in 0.30s
Running `target/debug/examples/basic`
[2024-02-03T07:19:00Z INFO ntex::server::builder] Starting 1 workers
[2024-02-03T07:19:00Z INFO ntex::server::builder] Starting "mqtt" service on 127.0.0.1:1883
[2024-02-03T07:19:00Z TRACE ntex::server::accept] Starting server accept loop
[2024-02-03T07:19:00Z INFO ntex::server::accept] Starting socket listener on 127.0.0.1:1883
[2024-02-03T07:19:00Z TRACE ntex::server::worker] Service "mqtt" is available
[2024-02-03T07:19:00Z TRACE ntex::server::accept] Worker is available
[2024-02-03T07:19:08Z TRACE ntex::server::accept] Accepting connection: Tcp(TcpStream { addr: 127.0.0.1:1883, peer: 127.0.0.1:51124, fd: 15 }) bp: false
[2024-02-03T07:19:08Z TRACE ntex::server::accept] Sent to worker 0
[2024-02-03T07:19:08Z TRACE ntex::server::worker] Got socket for service: "mqtt"
[2024-02-03T07:19:08Z TRACE ntex_io::tasks] : New 24 bytes available, wakeup dispatcher
[2024-02-03T07:19:08Z TRACE ntex_mqtt::v5::server] Starting mqtt v5 handshake
[2024-02-03T07:19:08Z INFO basic] new connection: Connect { clean_start: false, keep_alive: 1, session_expiry_interval_secs: 0, auth_method: None, auth_data: None, request_problem_info: true, request_response_info: false, receive_max: None, topic_alias_max: 0, user_properties: [], max_packet_size: Some(30), last_will: None, client_id: "user", username: None, password: None }
[2024-02-03T07:19:08Z TRACE ntex_mqtt::v5::server] Sending: ConnectAck {
session_present: false,
reason_code: Success,
session_expiry_interval_secs: None,
receive_max: 15,
max_qos: AtLeastOnce,
max_packet_size: None,
assigned_client_id: None,
topic_alias_max: 32,
retain_available: true,
wildcard_subscription_available: true,
subscription_identifiers_available: true,
shared_subscription_available: true,
server_keepalive_sec: None,
response_info: None,
server_reference: None,
auth_method: None,
auth_data: None,
reason_string: None,
user_properties: [],
}
[2024-02-03T07:19:08Z TRACE ntex_mqtt::service] : Connection handshake succeeded
[2024-02-03T07:19:08Z TRACE ntex_mqtt::service] : Connection handler is created, starting dispatcher
[2024-02-03T07:19:08Z DEBUG ntex_mqtt::io] : Start keep-alive timer Seconds(1)
[2024-02-03T07:19:08Z DEBUG ntex_io::ioref] : Start timer Seconds(1)
[2024-02-03T07:19:08Z DEBUG ntex_io::timer] : Timer driver does not run, current: 0
[2024-02-03T07:19:08Z TRACE ntex_io::tasks] : New 16 bytes available, wakeup dispatcher
[2024-02-03T07:19:08Z TRACE ntex_mqtt::v5::dispatcher] Dispatch v5 packet: DispatchItem::Item((Subscribe(Subscribe { packet_id: 1, id: None, user_properties: [], topic_filters: [("response", SubscriptionOptions { qos: AtLeastOnce, no_local: false, retain_as_published: false, retain_handling: AtSubscribe })] }), 14))
[2024-02-03T07:19:08Z WARN ntex_mqtt::v5::default] MQTT5 Control service is not configured, pkt: Subscribe(Subscribe { packet: Subscribe { packet_id: 1, id: None, user_properties: [], topic_filters: [("response", SubscriptionOptions { qos: AtLeastOnce, no_local: false, retain_as_published: false, retain_handling: AtSubscribe })] }, result: SubscribeAck { packet_id: 1, properties: [], reason_string: None, status: [UnspecifiedError] }, size: 14 })
[2024-02-03T07:19:08Z TRACE ntex_io::io] : Initiate io shutdown Flags(RD_READY | WR_PAUSED | DSP_STOP)
[2024-02-03T07:19:08Z TRACE ntex_mqtt::io] : Dispatcher is instructed to stop
[2024-02-03T07:19:08Z DEBUG ntex_io::ioref] : Stop timer
[2024-02-03T07:19:08Z TRACE ntex_tokio::io] : Write task is instructed to shutdown
[2024-02-03T07:19:08Z TRACE ntex_tokio::io] : Read task is instructed to shutdown
[2024-02-03T07:19:08Z TRACE ntex_tokio::io] : Tokio write task is stopped
[2024-02-03T07:19:08Z TRACE ntex_mqtt::io] : io shutdown completed
[2024-02-03T07:19:08Z WARN ntex_mqtt::v5::default] MQTT5 Control service is not configured, pkt: Closed(Closed)
[2024-02-03T07:19:08Z TRACE ntex_mqtt::io] : Service shutdown is completed, stop
[2024-02-03T07:19:08Z TRACE ntex_io::ioref] : Force close io stream object
^C[2024-02-03T07:19:56Z INFO ntex::server::builder] SIGINT received, exiting
[2024-02-03T07:19:56Z TRACE ntex::server::accept] Stopping accept loop
[2024-02-03T07:19:56Z INFO ntex::server::accept] Stopping socket listener on 127.0.0.1:1883
[2024-02-03T07:19:56Z TRACE ntex::server::accept] Accept loop has been stopped
[2024-02-03T07:19:56Z INFO ntex::server::worker] Shutting down worker, 0 connections
Is there any more documentation on clustering multiple instances together, perhaps in a kubernetes cluster way, i'm getting this error when trying to start it up with raft plugin.
2024-01-22 18:14:49.851 INFO rmqtt_cluster_raft.248 | rmqtt-cluster-raft init
thread 'main' panicked at rmqtt-bin/src/server.rs:63:57:
called `Result::unwrap()` on an `Err` value: Msg("Failed to register 'rmqtt-cluster-raft' plug-in, raft listening address does not exist ")
rmqtt uses 0.37.9 salvo and the interface has changed in 0.44.
step one, would be to upgrade rmqtt to use salvo 0.44 api.
step two, is to add logging to http requests.
step three, add configuration for salvo web server in rmqtt config.
I am trying to add static webpages to http-api/api.rs:router function using StaticDir but I am getting 404, not sure where it is looking for the files.
动作1:使用官方提供的docker-compose进行部署,并按流程依次操作。
动作2:通过curl "http://127.0.0.1:6066/api/v1/health/check"进行查看。
问题如下图所示:
请教一下,有没有批量发布的接口?怎么调用?
小白看了文档感觉有点蒙蒙的,具体来说这个库的应用场景是什么呢?如何集成到现有的Rust项目中去?比如我的tokio consumer要做一个job,完成之后再把结果publish到broker去,broker自动通知producer这个job完成了,这个逻辑用rmqtt该怎样实现呢?另外broker应该怎样部署?每隔一段时间重复执行一个job怎样实现?
Hi
Great package, and apparently the only package on R to work with mqtt messages on widows.
I'm trying to use its but i need to add an user and password for the host I'm giving to the mqtt_topic_subscribe function, but aparently there isnt that option on the 0.1.0 at least, and I can't update it.
Any idea what could be the reason for not being able to update on windows R studio to the current 0.2.10 ?
I'm using the dtupdate package to try to update this.
Thank you.
Cheers, Luís Pereira.
Thank you for your support and attention to RMQTT. For the future development direction of RMQTT, you can put forward valuable suggestions and opinions according to your specific business needs in the process of use.
thank you all
0.2.11
POST http://dev.fornetcode.com/mqtt/auth
HTTP/1.1 400 Bad Request
Server: nginx/1.23.4
Date: Fri, 22 Sep 2023 15:10:24 GMT
Content-Type: text/plain;charset=utf-8
Content-Length: 18
Connection: keep-alive
.clientId(missing)
Result:
mqtt 链接正常保持,没有被踢掉。 MQTT 应该关闭链接的
Hiya! again amazing server, is there any way of configuring rmqtt as a broker bridge to communicate/proxy messages across brokers?
Thanks!
打包的文件大小是否能压缩小的?
First off, I would like to take a moment to express my sincere gratitude for the incredible work you've done on the Rmqtt MQTT broker.
I recently started using Rmqtt and I have been thoroughly impressed with its features and performance. It has significantly enhanced my projects, and for that, I am truly thankful.
However, I wanted to share a concern I've encountered. It appears that subscriptions are not persisting after server restarts. This has caused inconvenience as clients need to subscribe again after every server restart. I believe a more robust subscription storage solution would greatly improve the user experience.
Additionally, I would appreciate guidance on how to properly stop the broker. Clear documentation on this aspect would be immensely helpful for users like me.
Once again, thank you for your hard work and dedication. I look forward to seeing Rmqtt continue to flourish and improve.
在测试时发现,
I think that when connecting with a client id of length 0, the server is not generating a proper id for the client, causing clients to kick each other from the network.
AFAIK the server must either allow a client id of length 0 an generate a random ID, or reject the client. I'm not sure if MQTT5 has changed this.
From the spec:
A Server MAY allow a Client to supply a ClientId that has a length of zero bytes, however if it does so the Server MUST treat this as a special case and assign a unique ClientId to that Client. It MUST then process the CONNECT packet as if the Client had provided that unique ClientId [MQTT-3.1.3-6].
怎么样设置通过账号密码才能连接服务端的
几个问题咨询一下官方
1:目前rmqtt中使用的是单向认证吗?
2:这方面的学习资料是参考resttls吗?
3:是否有考虑实现双向认证?
场景1:我使用golang语言写了一个mqtt的pub和sub的客户端,调用rmqtt的8883端口。
场景2:我使用golang语言写了一个mqtt的pub和sub的客户端,调用rmqtt的8883端口。
注:场景2中,客户端都配置了tls客户端证书;rmqtt也更换了服务端证书(使用openssl生成的client和server证书)
其中场景1和场景2,rmqtt都返回如下信息:
2023-08-25 13:04:40.294 DEBG rustls::server::hs.380 | decided upon suite TLS13_AES_128_GCM_SHA256
2023-08-25 13:04:40.295 DEBG rustls::server::tls13::client_hello.343 | Client unwilling to resume, DHE_KE not offered
麻烦官方空闲的时候看一下,感谢。
hi there
how can i find and use some plugin such as rmqtt-sys-topic ?
加一个配置项
listener.tcp.external.active = true
listener.tcp.internal.active = false
当注释掉 listener.tcp.external.addr = "0.0.0.0:1883"
打开 listener.tls.external.addr = "0.0.0.0:8883"
报错:
thread 'main' panicked at 'called Result::unwrap()
on an Err
value: ConfigError(missing field addr
)', /home/try/workspace/rmqtt/rmqtt/src/settings/mod.rs :100 :42
docker image 版本:0.2.16
I have nodes, broker,clients,subscriptions, routes and publish working, but subscribe returns a 404. I have tried it from a browser using axios and curl. I have used tcpdump to verify the the request on the wire.
I get the error "session does not exist", not sure what this means.
I am using mqttx client and I can subscribe and publish with no problem on port 1883.
http://10.1.42.157:3000/api/mqtt/subscribe
detail | "session does not exist"
curl -i -X POST "http://192.168.42.34:6060/api/v1/mqtt/subscribe" --header 'Content-Type: application/json' -d '{"topic":"testtopic/#","clientid":"6"}'
HTTP/1.1 404 Not Found
content-type: text/html
content-length: 912
date: Wed, 28 Jun 2023 10:15:04 GMT
这个项目真的很不错,有专门讨论这个项目的技术群吗?
Rust 1.69.0
Source Code 0.26.0
The errors are below:
error: failed to run custom build command for rmqtt v0.2.10 (E:\servers\sources\rmqtt\rmqtt)
Caused by:
process didn't exit successfully: E:\servers\sources\rmqtt\target\debug\build\rmqtt-691acc4cc66764fd\build-script-build
(exit code: 101)
--- stdout
out: E:\servers\sources\rmqtt\target\debug\build\rmqtt-c73114283d9fa88b\out
cargo:rerun-if-changed=pb.proto
cargo:rerun-if-changed=src/grpc/proto
--- stderr
thread 'main' panicked at 'Could not find protoc
installation and this build crate cannot proceed without
this knowledge. If protoc
is installed and this crate had trouble finding
it, you can set the PROTOC
environment variable with the specific path to your
installed protoc
binary.You can download it from https://github.com/protocolbuffers/protobuf/releases or from your package manager.
For more information: https://docs.rs/prost-build/#sourcing-protoc
', C:\Users\mekot.cargo\registry\src\github.com-1ecc6299db9ec823\prost-build-0.11.9\src\lib.rs:1457:10
note: run with RUST_BACKTRACE=1
environment variable to display a backtrace
warning: build failed, waiting for other jobs to finish...
error: failed to run custom build command for rmqtt-raft v0.2.4
Caused by:
process didn't exit successfully: E:\servers\sources\rmqtt\target\debug\build\rmqtt-raft-20c6376ba58d4924\build-script-build
(exit code: 101)
--- stdout
out: E:\servers\sources\rmqtt\target\debug\build\rmqtt-raft-6b26a9737cfa55aa\out
cargo:rerun-if-changed=raft_service.proto
cargo:rerun-if-changed=proto/
--- stderr
thread 'main' panicked at 'Could not find protoc
installation and this build crate cannot proceed without
this knowledge. If protoc
is installed and this crate had trouble finding
it, you can set the PROTOC
environment variable with the specific path to your
installed protoc
binary.You can download it from https://github.com/protocolbuffers/protobuf/releases or from your package manager.
For more information: https://docs.rs/prost-build/#sourcing-protoc
', C:\Users\mekot.cargo\registry\src\github.com-1ecc6299db9ec823\prost-build-0.11.9\src\lib.rs:1457:10
note: run with RUST_BACKTRACE=1
environment variable to display a backtrace
error[E0793]: reference to packed field is unaligned
--> C:\Users\mekot.cargo\registry\src\github.com-1ecc6299db9ec823\ntapi-0.3.7\src\ntexapi.rs:2783:52
|
2783 | *tick_count.QuadPart_mut() = read_volatile(&(*USER_SHARED_DATA).u.TickCountQuad);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use read_unaligned
/write_unaligned
(loads and stores via *p
must be properly aligned even when using raw pointers)
error[E0793]: reference to packed field is unaligned
--> C:\Users\mekot.cargo\registry\src\github.com-1ecc6299db9ec823\ntapi-0.3.7\src\ntexapi.rs:2807:25
|
2807 | ((read_volatile(&(*USER_SHARED_DATA).u.TickCountQuad)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use read_unaligned
/write_unaligned
(loads and stores via *p
must be properly aligned even when using raw pointers)
For more information about this error, try rustc --explain E0793
.
error: could not compile ntapi
due to 2 previous errors
Publishing to crates.io brings the opportunity to simplify the installation cargo install rmqtt
instead of using docker images or pre built releases.
请开通付费赞助, 包括 one-time payment, 以 $ 示支持.
请问官方之前有使用paho.mqtt.testing的测试用例跑一遍rmqtt嘛?
命令执行:python3 client_test.py
2023-08-15 06:10:25.638 WARN rmqtt::broker::v3.26 | [email protected]:1883/192.168.112.1:59802/myclientid2/undefined-1692079825631 Connection Refused, handshake, ack_code: ServiceUnavailable, new_ack_code: V3(ServiceUnavailable), reason: Msg("Handshake try lock failed")
2023-08-15 06:29:37.954 WARN rmqtt::broker::v3.26 | [email protected]:1883/192.168.112.1:61814/myclientid/undefined-1692080977937 Connection Refused, handshake, ack_code: ServiceUnavailable, new_ack_code: V3(ServiceUnavailable), reason: Msg("Keepalive must be greater than 0")
参考https://github.com/rmqtt/rmqtt/blob/master/docs/zh_CN/auth-http.md,在本地启了个/mqtt/acl服务,从浏览器或者postman都可以调用成功,但是在rmqtt_auth_http中无法调用成功呢?/mqtt/auth也是一样。
2023-08-11 16:28:56.659 ERRO rmqtt_auth_http.244 | error:reqwest::Error { kind: Request, url: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(9090), path: "/mqtt/acl", query: None, fragment: None }, source: hyper::Error(IncompleteMessage) }
2023-08-11 16:28:56.660 WARN rmqtt_auth_http.378 | [email protected]:1883/127.0.0.1:63449/mqttx_de420e2a/-1691253670 acl error, Msg("error sending request for url (http://127.0.0.1:9090/mqtt/acl): connection closed before message completed")
2023-08-11 16:29:37.801 ERRO rmqtt_auth_http.244 | error:reqwest::Error { kind: Request, url: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: Some(9090), path: "/mqtt/auth", query: None, fragment: None }, source: hyper::Error(IncompleteMessage) }
试了下您的项目,觉得真好,只是我平时用是网页创建websokect来接收数据的,不知道能不能给加一下websokect的接口,急切期盼!可惜我不会rust,无法贡献自己的力量
1、build and run
2、install distribution node
3、how to connect it?
Hello, I cannot understand how the mechanism of authorization through HTTP Auth is implemented.
I did not find in the documentation how to add usernames and passwords for clients, and the plugin description uses the path like http://127.0.0.1:8080/mqtt/superuser
, which does not work...
can you tell me how to create users?
Hi,
on fast testing I noticed perhaps a little Bug ?
Reading MQTT Spec CONNACK Properties:
https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901084
3.2.2.3.4 Maximum QoS
36 (0x24) Byte, Identifier of the Maximum QoS.
Followed by a Byte with a value of either 0 or 1. It is a Protocol Error to include Maximum QoS more than once, or to have a value other than 0 or 1. If the Maximum QoS is absent, the Client uses a Maximum QoS of 2.
Could it be that the Sevrer in Version 0.3 send the configured max_qos_allowed=2 properties which is a spec validation ?
Reproduced with latest Release , unchanged configuration, and Using a mqtt client which check this violation.
我发现rumqtt的client(rumqttc)还不支持native-tls
When i try to run the server with TLS certificates i get an error saying
thread 'main' panicked at rmqtt-bin/src/server.rs:214:53:
removal index (is 0) should be < len (is 0)
let key_file = &mut BufReader::new(File::open(listen_cfg.key.as_ref().unwrap())?);
let cert_chain = certs(cert_file).unwrap();
let mut keys = rsa_private_keys(key_file).unwrap();
let mut tls_config = if listen_cfg.cross_certificate {
let root_chain = cert_chain.clone();
let mut client_auth_roots = RootCertStore::empty();
for root in root_chain {
client_auth_roots.add(&root).unwrap();
}
ServerConfig::new(AllowAnyAuthenticatedClient::new(client_auth_roots))
} else {
ServerConfig::new(NoClientAuth::new())
};
> tls_config.set_single_cert(cert_chain, keys.remove(0)).map_err(|e| MqttError::from(e.to_string()))?;
let tls_acceptor = Acceptor::new(tls_config);
Is anyone else having a similar issue ?
The certificate has been validated and checked with openssl and the key has also been checked, it is a 4096 bit rsa key.
Firstly, thanks for your awesome job of this project. I haved used it in my own project: fornet.
But I'm wondering where the project go, it seems all things about MQTT protocol have implemented.
您好,感谢您做了如此好用的项目。MQTT 相关的协议都已经实现完毕了,它下一步要如何发展?
If should I create topic which publish the error message for auth/acl?
是否必须通过创建一个专门用来发布 认证/授权 错误信息的主题来解决这个问题?
hello,我是文强。一直从事消息领域的工作。最近在研究rust和mq结合的一些可能性,想认识一下你,方便的话加一下微信:loobooya。感谢感谢。
Darwin arm release
最新版本能发布一个release么?我怕生成又会遇到啥问题
Was checking out the golang examples in templates repo.
there seems to be no push mechanism like SSE or web sockets ?
I am writing a vue/axios interface to the http-api, rmqtt send the data just fine( status 200), but firefox does not allow the data to script because CORS header ‘Access-Control-Allow-Origin’ missing.
I can turn it off in firefox by about:config about:config -> security.fileuri.strict_origin_policy -> false
But this is a security issue.
I looked at the http-api code but could not find where the headers are set.
How do I add Access-Control-Allow-Origin: *
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.