Giter Club home page Giter Club logo

thingsboard / tbmq Goto Github PK

View Code? Open in Web Editor NEW
569.0 569.0 44.0 14.04 MB

Open-source, scalable, and fault-tolerant MQTT broker able to handle 4M+ concurrent client connections, supporting at least 3M messages per second throughput per single cluster node with low latency delivery. The cluster mode supports more than 100M concurrently connected clients.

Home Page: https://thingsboard.io/products/mqtt-broker/

License: Apache License 2.0

Java 63.44% Shell 0.89% Batchfile 0.01% PLpgSQL 0.09% Dockerfile 0.05% JavaScript 0.54% TypeScript 23.53% HTML 6.83% SCSS 4.00% CSS 0.03% FreeMarker 0.43% PowerShell 0.14%
broker iot java kafka mqtt mqtt-broker netty platform thingsboard

tbmq's Introduction

TBMQ

Join the chat at https://gitter.im/tbmq/chat TBMQ Builds Server Status

TBMQ represents an open-source MQTT message broker with the capacity to handle 4M+ concurrent client connections, supporting a minimum of 3M messages per second throughput per single cluster node with low latency delivery. In the cluster mode, its capabilities are further enhanced, enabling it to support more than 100M concurrently connected clients.

At ThingsBoard, we've gained a lot of experience in building scalable IoT applications, which has helped us identify two main scenarios for MQTT-based solutions. In the first scenario, numerous devices generate a large volume of messages that are consumed by specific applications, resulting in a fan-in pattern. Normally, a few applications are set up to handle these lots of incoming data. They must be persistent clients with a Quality of Service (QoS) level set to 1 or 2, capable of retaining all the data even when they're temporarily offline due to restarts or upgrades. This ensures applications don't miss any single message. On the other hand, the second scenario involves numerous devices subscribing to specific updates or notifications that must be delivered. This leads to a few incoming requests that cause a high volume of outgoing data. This case is known as a fan-out pattern. Acknowledging these scenarios, we intentionally designed TBMQ to be exceptionally well-suited for both.

Our design principles focused on ensuring the broker’s fault tolerance and high availability. Thus, we deliberately avoided reliance on master or coordinated processes. We ensured the same functionality across all nodes within the cluster.

We prioritized supporting distributed processing, allowing for effortless horizontal scalability as our operations grow. We wanted our broker to support high-throughput and guarantee low-latency delivery of messages to clients. Ensuring data durability and replication was crucial in our design. We aimed for a system where once the broker acknowledges receiving a message, it remains safe and won’t be lost.

TBMQ provides compatibility with both MQTT v3.x and v5.0 protocols. Last but not least, it had been running in production for more than a year before being open-sourced.

TBMQ Home

TBMQ Sessions

Documentation

TBMQ documentation is hosted on thingsboard.io.

Getting Started

Connect clients and Publish your IoT data in minutes by following this guide.

Installation

Review different TBMQ installation options by following this link.

Licenses

This project is released under Apache 2.0 License.

MQTT 5 supported features:

  • User Properties
  • Reason Codes for MQTT packets
  • Session Clean Start
  • New Data Type: UTF-8 String pairs
  • Bi-directional DISCONNECT packets
  • Using passwords without usernames
  • Session expiry feature
  • Message expiry feature
  • Shared subscriptions
  • Subscription options
  • Topic aliases
  • Maximum Packet Size
  • Will delay
  • Server Keep-Alive
  • Assigned ClientID
  • Server reference
  • The payload format and content types
  • Request / Response & Correlation Data
  • Flow Control

MQTT 5 features in active development:

  • AUTH packet & Enhanced Authentication
  • Subscription Identifiers

tbmq's People

Contributors

andriilandiak avatar ashvayka avatar deaflynx avatar dmytro-landiak avatar volodymyr-babak avatar vzikratyi-tb avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

tbmq's Issues

feature lack code file

Component

  • UI
  • Core
  • Installation
  • Generic

Description
Hi Dima,
When I was learning about the TBMQ project, I found that the branch 1.3.0 code was indeed missing some code files, which were in org.thingsboard.mqtt.broker.gen.queue,so can you help me,Looking forward to your reply,thanks
Environment

  • OS: name and version
  • TBMQ: 1.3.0
  • Browser: name and version

[Feature Request] Cluster setup with AKS on Azure

Dear Thingsboad Team,
I see there is a cluster setup with Kubernetes on AWS currently for tbmq.
Do you plan on releasing a cluster setup with AKS on Azure in the near future ?
We are hosting our TB PE on Azure and would like to use tbmq as our primary broker while keeping all our infra on Azure.
Thanks

How do devices connect to MQTT brokers

Component

  • UI
  • Core
  • Installation
  • Generic

Description
hello, dmytro-landiak
Now I don't know how my device connects to MQTT Broker,Then, after my device is connected to the MQTT broker, where is the interface for the code to process this connection request?How does the broker handle this connection request, I don't see the description of request connection processing in the documentation, can you help me ?please answer, thank you!

Environment

  • OS: name and version
  • TBMQ: 1.3.0
  • Browser: name and version

[Question] Is there documentation on the kafka storage format?

Is there documentation on the format the messages are stored to in Kafka?
Can we consume from the kafka topics with a service? Or should they be seen as internal to TBMQ?

We actually need the MQTT messages in Kafka, so it would make sense to directly consume from a tbmq.msg.app topic. We could also create a MQTT client and make that write to a kafka topic, but that seems wasteful.

[Feature Request] XSS validation

Is your feature request related to a problem? Please describe.
XSS validation is absent.

Need to add XSS validation for all editable entities.

How do I enable SSL Bidirectional authentication?

I set config "SECURITY_MQTT_SSL_ENABLED:true",I want to enable SSL bidirectional authentication。

thingsboard-mqtt-broker.yml
cert_file: my_server_cert.crt
key_file: my_server_key.key

Where is caRootCert configured?

Component

  • TBMQ: 1.2.2-SNAPSHOT

[Bug] Error executing Maven.

When I try to build from sources using mvn clean install -DskipTests command it gives :

ERROR] Error executing Maven.
[ERROR] java.lang.IllegalStateException: Unable to load cache item
[ERROR] Caused by: Unable to load cache item
[ERROR] Caused by: Could not initialize class com.google.inject.internal.cglib.core.$MethodWrapper
[ERROR] Caused by: Exception com.google.inject.internal.cglib.core.$CodeGenerationException: java.lang.reflect.InaccessibleObjectException-->Unable to make protected final java.lang.Class java.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int,java.security.ProtectionDomain) throws java.lang.ClassFormatError accessible: module java.base does not "opens java.lang" to unnamed module @69a10787 [in thread "main"]

I already set Java 17 for environment variables. I also double-checked Maven to see which Java version it uses.
echo $JAVA_HOME
/usr/lib/jvm/java-17-openjdk-amd64

java --version
openjdk 17.0.7 2023-04-18
OpenJDK Runtime Environment (build 17.0.7+7-Ubuntu-0ubuntu120.04)
OpenJDK 64-Bit Server VM (build 17.0.7+7-Ubuntu-0ubuntu120.04, mixed mode, sharing)

Environment:
Linux Ubuntu 20.0.4

Thanks in advance

[Bug] MQTT 5: max payload size response

Describe the bug

When the MQTT 5 client is connecting, the wrong Maximum Packet Size is returned. Based on the code, the min value between tcp and ssl listeners is returned:

Math.min(tcpMaxPayloadSize, sslMaxPayloadSize)).

In this way, if the ssl communication is used and tcp has lower value, then this lower value is returned for ssl but it should be greater.

The correct behavior is when the single max payload size can be set for all listeners or separate ones for each of them.

Your Server Environment

  • TBMQ version: [1.2.1]

[Feature Request] WebSocket client

Is your feature request related to a problem? Please describe.

It would be helpful to have a WebSocket client built into the broker to test stuff and validate the functionality.

image

[Bug] Docker upgrade script fails to parse FROM_VERSION

Describe the bug
While trying to update from v1.2.1 to v1.3.0 I get the following error:

Starting TBMQ upgrade ...
FROM_VERSION variable is invalid or unspecified!

As it seems, in the previous versions, the data path was ~/.tb-mqtt-broker-data/data, but the new script assumes tbmq-data.

Your Server Environment

  • Deployment: Docker as indicated here.
  • TBMQ version: v1.2.1 to v1.3.0
  • OS name and version: Rocky Linux 9

To Reproduce
Steps to reproduce the behavior:

  1. Install v1.2.0 according to the official documentation.
  2. Upgrade according to the documentation.

The upgrade script fails.

Expected behavior
I expected the upgrade to not fail, or at least be aware of the change in the documentation, or provide an alternative means of configuring FROM_VERSION like for example an environment variable or a script argument.

Or better yet, get rid of this FROM_VERSION thing, and store the database information in... the database itself.

[Bug]

/Hello,

I update for the last version and after use update .sh I get:
"
ERROR: relation "admin_settings" does not exist
"

tbmq logs:

`at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)

at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:137)

... 62 common frames omitted

Caused by: org.postgresql.util.PSQLException: ERROR: relation "admin_settings" does not exist

Position: 152

at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2676)

at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2366)

at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:356)

at org.postgresql.jdbc.PgStatement.executeInternal(PgStatement.java:496)

at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:413)

at org.postgresql.jdbc.PgPreparedStatement.executeWithFlags(PgPreparedStatement.java:190)

at org.postgresql.jdbc.PgPreparedStatement.executeQuery(PgPreparedStatement.java:134)

at com.zaxxer.hikari.pool.ProxyPreparedStatement.executeQuery(ProxyPreparedStatement.java:52)

at com.zaxxer.hikari.pool.HikariProxyPreparedStatement.executeQuery(HikariProxyPreparedStatement.java)

at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:57)

... 99 common frames omitted

Starting TBMQ ...

===================================================

:: ThingsBoard MQTT Broker :: (v1.1.0)

===================================================`

postgres log:

`dminsetti0_.key as key4_0_ from admin_settings adminsetti0_ where adminsetti0_.key=$1

2023-09-18 17:17:08.180 UTC [597] ERROR: relation "admin_settings" does not exist at character 152

2023-09-18 17:17:08.180 UTC [597] STATEMENT: select adminsetti0_.id as id1_0_, adminsetti0_.created_time as created_2_0_, adminsetti0_.json_value as json_val3_0_, adminsetti0_.key as key4_0_ from admin_settings adminsetti0_ where adminsetti0_.key=$1

2023-09-18 17:17:20.437 UTC [613] ERROR: relation "admin_settings" does not exist at character 152

2023-09-18 17:17:20.437 UTC [613] STATEMENT: select adminsetti0_.id as id1_0_, adminsetti0_.created_time as created_2_0_, adminsetti0_.json_value as json_val3_0_, adminsetti0_.key as key4_0_ from admin_settings adminsetti0_ where adminsetti0_.key=$1

2023-09-18 17:17:30.001 UTC [630] ERROR: relation "admin_settings" does not exist at character 152

2023-09-18 17:17:30.001 UTC [630] STATEMENT: select adminsetti0_.id as id1_0_, adminsetti0_.created_time as created_2_0_, adminsetti0_.json_value as json_val3_0_, adminsetti0_.key as key4_0_ from admin_settings adminsetti0_ where adminsetti0_.key=$1

2023-09-18 17:17:40.763 UTC [646] ERROR: relation "admin_settings" does not exist at character 152

2023-09-18 17:17:40.763 UTC [646] STATEMENT: select adminsetti0_.id as id1_0_, adminsetti0_.created_time as created_2_0_, adminsetti0_.json_value as json_val3_0_, adminsetti0_.key as key4_0_ from admin_settings adminsetti0_ where adminsetti0_.key=$1

2023-09-18 17:17:51.088 UTC [663] ERROR: relation "admin_settings" does not exist at character 152

2023-09-18 17:17:51.088 UTC [663] STATEMENT: select adminsetti0_.id as id1_0_, adminsetti0_.created_time as created_2_0_, adminsetti0_.json_value as json_val3_0_, adminsetti0_.key as key4_0_ from admin_settings adminsetti0_ where adminsetti0_.key=$1

2023-09-18 17:18:01.341 UTC [680] ERROR: relation "admin_settings" does not exist at character 152

2023-09-18 17:18:01.341 UTC [680] STATEMENT: select adminsetti0_.id as id1_0_, adminsetti0_.created_time as created_2_0_, adminsetti0_.json_value as json_val3_0_, adminsetti0_.key as key4_0_ from admin_settings adminsetti0_ where adminsetti0_.key=$1

2023-09-18 17:18:11.347 UTC [696] ERROR: relation "admin_settings" does not exist at character 152

2023-09-18 17:18:11.347 UTC [696] STATEMENT: select adminsetti0_.id as id1_0_, adminsetti0_.created_time as created_2_0_, adminsetti0_.json_value as json_val3_0_, adminsetti0_.key as key4_0_ from admin_settings adminsetti0_ where adminsetti0_.key=$1

2023-09-18 17:18:22.131 UTC [713] ERROR: relation "admin_settings" does not exist at character 152

2023-09-18 17:18:22.131 UTC [713] STATEMENT: select adminsetti0_.id as id1_0_, adminsetti0_.created_time as created_2_0_, adminsetti0_.json_value as json_val3_0_, adminsetti0_.key as key4_0_ from admin_settings adminsetti0_ where adminsetti0_.key=$1`

Keep Alive Logic

A Keep Alive value of 0 has the effect of turning off the Keep Alive mechanism. If Keep Alive is 0 the Client is not obliged to send MQTT Control Packets on any particular schedule.

[Question] Difference between tbmq and gateway

Component

  • Generic

Description

Hi, I wanted to ask that what is the difference between thingsboard-gateway (python project) and tbmq. Thingsboard gateway can be used as a broker also, is it because tbmq can manage much heavier data flow compared to the gateway? It may be a silly question, to keep it short for someone using thingsboard project itself and gateway what will be the advantages to use tbmq?

Thank you!

[Bug] Is there a memory leak in WsByteBufEncoder?

`public class WsByteBufEncoder extends MessageToMessageEncoder {

@Override
protected void encode(ChannelHandlerContext ctx, ByteBuf msg, List<Object> out) throws Exception {
    final BinaryWebSocketFrame binaryWebSocketFrame = new BinaryWebSocketFrame(msg);
    ReferenceCountUtil.retain(binaryWebSocketFrame);
    out.add(binaryWebSocketFrame);
}

}`

version:1.2.2-SNAPSHOT
ReferenceCountUtil.retain(binaryWebSocketFrame);
The counter should not be incremented by one here?

[Feature Request] MQTT-SN support

Is your feature request related to a problem? Please describe.
We have many devices that connect via NB-IoT where UDP is the protocol if chose. Having a good MQTT-SN broker / endpoint would be great to connect these.

Describe the solution you'd like
An UDP endpoint that supports MQTT-SN protocol.

Describe alternatives you've considered
Just use CoAP or LWM2M

Additional context

[Feature Request] support mqtt over websocket

Is your feature request related to a problem? Please describe.
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]

Describe the solution you'd like
A clear and concise description of what you want to happen.

Describe alternatives you've considered
A clear and concise description of any alternative solutions or features you've considered.

Additional context
Add any other context or screenshots about the feature request here.

[Bug] Shared Subscriptions with Qos 0

Describe the bug
When using the Shared Subscriptions feature with both Device and Application persistent clients and when QoS=0 is used, the processing is broken. More details below.

For Application clients (QoS=0 for either publish messages or for subscriptions) - the processing of data is not reliable - not all messages are delivered right away and the lag is growing.
For Device clients - when all clients in the shared subscription group go offline and then some of them go online with sub QoS=0 - the messages are delivered but not cleared from DB thus for the next connection of the client from the same group the messages will be delivered once again.

Additionally, shared subscription processing is launched only with Subscribe messages received, thus not working correctly for persistent subscribers that go offline and then back online without sending Subscribe.

  • TBMQ version: [e.g., 1.1.0]

[Question] Application Shared Subscriptions

Component

  • Core

Description
My team is running into some issues with TBMQ around shared subscriptions (or at least how understand they are supposed to be working).

I have a Shared Subscription created to handle all topics, using "#" as the MQTT filter. It's configured with two partitions and have two Application clients connected to the shared subscription "$share/all-messages/#", both with persistent connections. The kafka topic seems to be created properly and the consumer groups look correct, but it doesn't look like the broker is sending the messages round robin. Once I connect one client, it receives all the messages until I connect the second client after which the messages switch over to that newly connected client. Basically it's only sending messages to one client at a time. If I disconnect one of the clients the messages then move over to the other client that is connected, so it's working as a failover, but I can't seem to get the round robin working.

So in short, are there any configuration steps I need to set to get the round robin working with Application clients or am I missing something with how to set up the shared subscriptions?

Environment

  • Deployment: TBMQ is deployed to our GCP cluster using the Azure instructions as a baseline. Kafka is running in GKE and Redis is running in GCP. We also stood up a separate Postgres instance for TBMQ. Most of the configurations are the defaults besides some definitions to get it integrated with the rest of our system.
  • TBMQ: v1.2.0

[Bug] OutOfMemoryError - direct memory

Describe the bug

2024-02-08T13:38:38.696891163Z 2024-02-08 13:38:38,696 [nioEventLoopGroup-3-11] ERROR o.t.m.b.server.MqttSessionHandler - [da3c567e-a2af-4d11-944c-b19ee420ef10] Unexpected Exception
2024-02-08T13:38:38.696905041Z java.lang.OutOfMemoryError: Cannot reserve 4194304 bytes of direct buffer memory (allocated: 4190341064, limit: 4192206848)
2024-02-08T13:38:38.696908217Z 	at java.base/java.nio.Bits.reserveMemory(Bits.java:178)
2024-02-08T13:38:38.696920506Z 	at java.base/java.nio.DirectByteBuffer.<init>(DirectByteBuffer.java:121)
2024-02-08T13:38:38.696923431Z 	at java.base/java.nio.ByteBuffer.allocateDirect(ByteBuffer.java:332)
2024-02-08T13:38:38.696925994Z 	at io.netty.buffer.PoolArena$DirectArena.allocateDirect(PoolArena.java:701)
2024-02-08T13:38:38.696928465Z 	at io.netty.buffer.PoolArena$DirectArena.newChunk(PoolArena.java:676)
2024-02-08T13:38:38.696931466Z 	at io.netty.buffer.PoolArena.allocateNormal(PoolArena.java:215)
2024-02-08T13:38:38.696933942Z 	at io.netty.buffer.PoolArena.tcacheAllocateSmall(PoolArena.java:180)
2024-02-08T13:38:38.696936404Z 	at io.netty.buffer.PoolArena.allocate(PoolArena.java:137)
2024-02-08T13:38:38.696938854Z 	at io.netty.buffer.PoolArena.allocate(PoolArena.java:129)
2024-02-08T13:38:38.696941380Z 	at io.netty.buffer.PooledByteBufAllocator.newDirectBuffer(PooledByteBufAllocator.java:400)
2024-02-08T13:38:38.696943935Z 	at io.netty.buffer.AbstractByteBufAllocator.directBuffer(AbstractByteBufAllocator.java:188)
2024-02-08T13:38:38.696946432Z 	at io.netty.buffer.AbstractByteBufAllocator.directBuffer(AbstractByteBufAllocator.java:179)
2024-02-08T13:38:38.696948891Z 	at io.netty.buffer.AbstractByteBufAllocator.ioBuffer(AbstractByteBufAllocator.java:140)
2024-02-08T13:38:38.696951536Z 	at io.netty.channel.DefaultMaxMessagesRecvByteBufAllocator$MaxMessageHandle.allocate(DefaultMaxMessagesRecvByteBufAllocator.java:120)
2024-02-08T13:38:38.696954253Z 	at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:150)
2024-02-08T13:38:38.696956760Z 	at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:788)
2024-02-08T13:38:38.696959276Z 	at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:724)
2024-02-08T13:38:38.696961878Z 	at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:650)
2024-02-08T13:38:38.696964595Z 	at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:562)
2024-02-08T13:38:38.696967098Z 	at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997)
2024-02-08T13:38:38.696969587Z 	at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
2024-02-08T13:38:38.696972994Z 	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
2024-02-08T13:38:38.696975796Z 	at java.base/java.lang.Thread.run(Thread.java:833)

The above logs come up after some time of TBMQ running. It is not possible then to connect any client and send any message. The traffic is then at 0. The container is not crashing thus the broker is not restarting and is stuck in this unresponsive state.

Your Server Environment

  • Deployment: any deployment
  • TBMQ version: 1.2.1
  • OS name and version: any

Expected behavior
MQTT communication remains stable.

Screenshots
image
image

Additional context
Happens when there are clients that are publishing data to the unauthorized topics (i.e. "Client is not authorized to publish to the topic...")

Failed to get Kafka consumer groups

Describe the bug
I have completed the AWS EKS install and have logged into the dashboard; I have also sent and received a test message. I am having one issue that looked to be Kafka related.

When I log in and load "Home" I get the error at the top of the screen "java.util.concurrent.ExecutionException: org.apache.kafka.common.errors.TimeoutException: Exceeded maxRetries after 2 tries." Looking in the logs here is the error:

 WARN  o.t.m.b.queue.kafka.TbKafkaAdmin - Failed to get Kafka consumer groups
java.util.concurrent.ExecutionException: org.apache.kafka.common.errors.TimeoutException: Exceeded maxRetries after 2 tries.
	at java.base/java.util.concurrent.CompletableFuture.reportGet(CompletableFuture.java:396)
	at java.base/java.util.concurrent.CompletableFuture.get(CompletableFuture.java:2073)
	at org.apache.kafka.common.internals.KafkaFutureImpl.get(KafkaFutureImpl.java:165)
	at org.thingsboard.mqtt.broker.queue.kafka.TbKafkaAdmin.getConsumerGroups(TbKafkaAdmin.java:314)
	at org.thingsboard.mqtt.broker.controller.AppController.getKafkaConsumerGroups(AppController.java:112)
	at org.thingsboard.mqtt.broker.controller.AppController$$FastClassBySpringCGLIB$$a62b622d.invoke(<generated>)
	at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:783)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:753)
	at org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor.invoke(MethodSecurityInterceptor.java:61)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:753)
	at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:698)
	at org.thingsboard.mqtt.broker.controller.AppController$$EnhancerBySpringCGLIB$$bdf0bb1e.getKafkaConsumerGroups(<generated>)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:568)
	at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205)
	at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:150)
	at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117)
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895)
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808)
	at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1067)
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963)
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
	at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:655)
	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:764)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
	at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:218)
	at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:212)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
	at org.thingsboard.mqtt.broker.service.security.auth.jwt.JwtTokenAuthenticationProcessingFilter.successfulAuthentication(JwtTokenAuthenticationProcessingFilter.java:59)
	at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:232)
	at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:212)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
	at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:218)
	at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:212)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:111)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:327)
	at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:115)
	at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:81)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
	at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:121)
	at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:115)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
	at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:126)
	at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:81)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
	at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:105)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
	at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:149)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
	at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
	at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:218)
	at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:212)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
	at org.thingsboard.mqtt.broker.service.security.auth.jwt.JwtTokenAuthenticationProcessingFilter.successfulAuthentication(JwtTokenAuthenticationProcessingFilter.java:59)
	at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:232)
	at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:212)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
	at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:218)
	at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:212)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
	at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:103)
	at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:89)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
	at org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:91)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
	at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:90)
	at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:75)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
	at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:110)
	at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:80)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
	at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:55)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
	at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:211)
	at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:183)
	at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:354)
	at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:267)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
	at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
	at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
	at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:96)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
	at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:540)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)
	at org.apache.catalina.valves.RemoteIpValve.invoke(RemoteIpValve.java:769)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:357)
	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:382)
	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:895)
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1722)
	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
	at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)
	at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
	at java.base/java.lang.Thread.run(Thread.java:833)

Your Server Environment
AWS EKS setup just as described here: https://thingsboard.io/docs/mqtt-broker/install/cluster/aws-cluster-setup/

  • Deployment: AWS EKS using official installation instructions
  • TBMQ version: 1.0.0
  • OS name and version: AWS EKS

I am looking at the logs via: kubectl logs -f tb-broker-0

I have also confirmed my TB_KAFKA_SERVERS is set to the plaintext paths with port numbers from my MSK cluster.

[Feature Request] Advanced client session filtering

Is your feature request related to a problem? Please describe.

It would be nice to have advanced filtering of client sessions.
Currently, it is only possible to search by clientId and sort by other fields.

For example, filter by Connected Status / Client Type / Node ID, etc.

The query - give me pls all client sessions with type APPLICATION, that are connected and located on the tbmq1 node.

[Bug] Retained messages and Remove Topics

Hi,

It's not possible to remove retained messages:

image

I think that 1 devices is sending a lot of messages and I need to ignore them.
It's possible to block only one topic ?

I removed the topic from the writing device and I still receive it.

image

[Bug]

Hi,

I have one problem with docker composer project.

If I access via 0.0.0.0:8083 login works fine.
image

But if I access externaly or localhost the login fails.

image

image

Best Regards,
Joao

Shared Subscriptions

It is better to group clients when they subscribe (in MqttSubscribeHandler) and then find the needed groups during msg processing in MsgDispatcherServiceImpl for a pub msg (instead of grouping for each msg).

lightweight deployment

Component

  • Core

Description
Does tbmq currently support lightweight deployment? Will it support edge side lightweight deployment solutions in the future, which do not rely on Kafka queues to run separately

Environment
1.0.1

  • OS: win10
  • TBMQ: 1.0.1
  • Browser: google

[Feature Request] Redis support

Is your feature request related to a problem? Please describe.

Need Redis support for cache in cluster mode. Only caffeine type is available right now for single-node deployment.

Thus in the case of enabling the cache for MQTT client credentials (i.e. CACHE_SPECS_MQTT_CLIENT_CREDENTIALS_MAX_SIZE > 0 - note, it is disabled by default) - credentials are cached on clients' connections. After the credentials are updated - the cache is not cleared on all nodes (only cleared on the target node that processed the request regarding the MQTT client credentials update) leading to the unexpected behavior.

[Feature Request]

Is your feature request related to a problem? Please describe.
No it is just an addition to the Authorisation scheme in the device config.

Describe the solution you'd like
We have a huge number of devices to configure on TBMQ and would like to create common Authorisation maps per device group. Would it be possible to make "Device Profiles" like Thingsboard does?

Describe alternatives you've considered
Creating individual configurations but this will not scale well if changes need to be made with large numbers of devices.

Additional context
N/A

[Feature Request] Limit number of sessions

Is your feature request related to a problem? Please describe.

It would be great to have the possibility to limit the number of sessions that can be stored/connected on the broker at once.
For example to have a parameter - 1000 sessions. This would mean 1k sessions can be connected to the broker at once. Maybe some of them can be persistent and disconnected thus the info still will be stored on the broker for later reconnecting.

How do devices connect to MQTT brokers

Component

  • UI
  • Core
  • Installation
  • Generic

Description
hello, dmytro-landiak
Now I don't know how my device connects to MQTT Broker,Then, after my device is connected to the MQTT broker, where is the interface for the code to process this connection request?How does the broker handle this connection request, I don't see the description of request connection processing in the documentation, can you help me ?please answer, thank you!

Environment

  • OS: name and version
  • TBMQ: 1.3.0
  • Browser: name and version

[Bug]

Describe the bug
Java error when using X.509 certificate based TLS authentication

Your Server Environment

  • docker compose single node deployment
  • TBMQ version: 1.0.2-SNAPSHOT
  • OS name and version: Ubuntu 22.04.2LTS, Docker 24.0.4

Your Client Environment
Ubuntu 22.04.2LTS, OpenSSL 3.0.2

  • OS: Ubuntu 22.04.2LTS
  • Browser N/A
  • Version N/A

No real device, just created certificates to authenticate on tbmq

  • Connectivity: MQTT

$ mosquitto_pub -h dx-prod-mqtt1.nec.xon.co.za -p 8883 --cafile ./ca.crt --cert ./tbmq-cpa-gateway-0001.crt --key ./tbmq-cpa-gateway-0001.key -q 1 -t "tb/mqtt-integration-tutorial/sensors/SN-001/temperature" -m '{"value":25.1}'
Error: A TLS error occurred.

$ openssl x509 -noout -subject -in tbmq-cpa-gateway-0001.crt
subject=CN = tbmq-cpa-gateway-0001

  • Device vendor and model: N/A

To Reproduce
I have created X.509 certificates for OpenVPN and MQTT TLS authentication. The certiifcates are working fine with OpenVPN but they give this error when connecting to tbmq. Google shows that the error, which is:

2023-07-21 12:13:32,325 [nioEventLoopGroup-5-7] WARN o.t.m.b.server.MqttSessionHandler - [c124bdc8-0600-47d1-976a-785fcf3f8358] Exception on SSL handshake. Reason - Insufficient buffer remaining for AEAD cipher fragment (2). Needs to be more than tag size (16)

Is a JVM error and has been resolved in later versions of Java.

I have configured (in the tbmq docker compose file:

LISTENER_SSL_ENABLED: true
LISTENER_SSL_PROTOCOL: TLSv1.2
LISTENER_SSL_CREDENTIALS_TYPE: PEM
LISTENER_SSL_PEM_CERT: /data/ssl/dx-prod-tb-mqtt-vpn1.crt
LISTENER_SSL_PEM_KEY: /data/ssl/dx-prod-tb-mqtt-vpn1.key
SECURITY_MQTT_AUTH_STRATEGY: single
SECURITY_MQTT_SSL_ENABLED: true

The docker log shows no error when loading the certificate and key listen in the configuration and the tbmq GUI shows TLS Listener enabled and X.509 certificate authentication enabled.

Steps to reproduce the behavior:

create certificates for server and client using OpenSSL/easy-rsa. Install the server certificates on tbmq and use mosquitto_pub to publish to port 8883.

How to load Default DB Data for TBMQTT?

Initialisation of DB

Hello @dmytro-landiak,

I have build TBMQTT from sources and tried to initialise default DB data, I couldn't find any install_dev_db.sh file in path : /application/target/bin/install which I used to load default data in Thingsboard. Is that required to setup kafka environment locally to run TBMQTT application. Could you please guide me how can initialise and run TMQTT broker locally without using .deb or .rpm packages.

Environment

  • OS: Ubuntu 20.04
  • TBMQ: 1.1.0

[Feature Request] Redirect Copy of frame to other broker

Hi,

The general iot devices only support 1 broker mqtt.
It would be interesting to be able to receive and process the data but also be able to forward the original frame to another mqtt broker on a external server. Something like a "original" packet forwarder but at same time use data inside tbmq.

Best Regards,
Joao

TBMQ fails to login when placed behind haproxy for SSL termination

Component

  • Core

Description
Our organisation uses Thingsboard PE and Trendz extensively and we are in the process of testing TBMQ with the view of migrating our MQTT servers (mosquitto currently) to TBMQ. I have the tbmq UI working well with http but when I put haproxy in front of the tbmq for HTTPS/SSL termination I get errors in the tbmq logs showing issues with CORS at the login page when I enter my username and password. This extract is from the docker logs:
java.lang.IllegalArgumentException: When allowCredentials is true, allowedOrigins cannot contain the special value "*" since that cannot be set on the "Access-Control-Allow-Origin" response header. To allow credentials to a set of origins, list them explicitly or consider using "allowedOriginPatterns" instead.
The tbmq documentation shows the environment variables to configure tbmq with and under the section "Spring MVC/Resources parameters" it shows the CORS parameters but there is no environment variable in the middle column to allow us to configure this parameter.
Is there a reason why tbmq uses CORS? Thingsboard and Trendz do not require CORS and live happily behind haproxy. We have a mandate to use haproxy in our organisation for SSL termination since it gives a lot of additional features by default to secure the connection better than using SSL directly in the end product.

Environment
Ubuntu 22.04.2LTS, Docker 24.04, Docker compose 2.19, haproxy 2.4.22 with Lua 5.3.6

  • OS: Ubuntu 22.04.2
  • TBMQ: 1.01 docker
  • Browser: Chrome

[Feature Request]

Is your feature request related to a problem? Please describe.
No, it is just an optimisation to reduce number of devices.

Describe the solution you'd like
Mixed authentication between X.509 certificate and Basic authentication.

We have TBMQ listening on a public IP address on port 8883 for X.509 authentication only and port 1883 on an Internal subnet and also on a VPN IP subnet. We would like to configure a single device that will allow X.509 authentication using the certificate CN on port 8883 or authenticate the same client_id (as the certificate CN) on port 1883 if it comes in through the VPN address or internal address. Without this we will need to set up 2 devices for each physical device.

Describe alternatives you've considered
TBMQ already does combination of authentication based on client_id, username, password, etc, but when you configure a device as X.509 certificate based the configuration there is no facility to also enable Basic authentication.

Additional context

[Feature Request] MQTT 5 Msg expiry feature

Is your feature request related to a problem? Please describe.
Message expiry feature of MQTT 5 needed

Describe the solution you'd like

Describe alternatives you've considered

Additional context

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.