// Copyright (C) 2017 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only

/*!
    \example btchat
    \title Bluetooth Chat Example
    \brief An example showing communication through Bluetooth.

    The Bluetooth Chat example shows how to use the \l{Qt Bluetooth} API to communicate
    with another application on a remote device using Bluetooth.

    \image btchat-example.png

    The Bluetooth Chat example implements a simple chat program between multiple parties. The
    application always acts as both a server and a client eliminating the need to determine who
    should connect to whom.

    \include examples-run.qdocinc

    \section1 Chat Server

    The chat server is implemented by the ChatServer class. The ChatServer class is declared as:

    \snippet btchat/chatserver.h declaration

    The first thing the chat server needs to do is create an instance of QBluetoothServer to listen
    for incoming Bluetooth connections. Our clientConnected() slot will be called whenever a new
    connection is created.

    \snippet btchat/chatserver.cpp Create the server

    The chat server is only useful if others know that it is there. To enable other devices to
    discover it, a record describing the service needs to be published in the systems SDP (Service
    Discovery Protocol) database. The QBluetoothServiceInfo class encapsulates a service record.

    We will publish a service record that contains some textural descriptions of the services, a
    UUID that uniquely identifies the service, the discoverability attribute, and connection
    parameters.

    The textural description of the service is stored in the ServiceName, ServiceDescription, and
    ServiceProvider attributes.

    \snippet btchat/chatserver.cpp Service name, description and provider

    Bluetooth uses UUIDs as unique identifiers. The chat service uses a randomly generated
    UUID.

    \snippet btchat/chatserver.cpp Service UUID
    \snippet btchat/chatserver.cpp Service UUID set

    A Bluetooth service is only discoverable if it is in the PublicBrowseGroup.

    \snippet btchat/chatserver.cpp Service Discoverability

    The ProtocolDescriptorList attribute is used to publish the connection parameters that the
    remote device requires to connect to our service. Here we specify that the Rfcomm protocol is
    used and set the port number to the port that our rfcommServer instance is listening to.

    \snippet btchat/chatserver.cpp Protocol descriptor list

    Finally, we register the service record with the system.

    \snippet btchat/chatserver.cpp Register service


    As mentioned earlier, incoming connections are handled in the clientConnected() slot where
    pending connections are connected to the readyRead() and disconnected() signals. The signals
    notify others that a new client has connected.

    \snippet btchat/chatserver.cpp clientConnected

    The readSocket() slot is called whenever data is ready to be read from a client socket. The
    slot reads individual lines from the socket, converts them from UTF-8, and emits the
    messageReceived() signal.

    \snippet btchat/chatserver.cpp readSocket

    The clientDisconnected() slot is called whenever a client disconnects from the service. The
    slot emits a signal to notify others that a client has disconnected, and deletes the socket.

    \snippet btchat/chatserver.cpp clientDisconnected

    The sendMessage() slot is used to send a message to all connected clients. The message is
    converted into UTF-8 and appended with a newline before being sent to all clients.

    \snippet btchat/chatserver.cpp sendMessage

    When the chat server is stopped the service record is removed from the system SDP database, all
    connected client sockets are deleted, and the QRfcommServer instance is deleted.

    \snippet btchat/chatserver.cpp stopServer

    \section1 Chat Client

    The chat client is implemented by the ChatClient class. The ChatClient class is declared as:

    \snippet btchat/chatclient.h declaration

    The client creates a new QBluetoothSocket and connects to the remote service described by the
    \e remoteService parameter. Slots are connected to the sockets readyRead(), connected() and
    disconnected() signals.

    \snippet btchat/chatclient.cpp startClient

    On successful socket connection we emit a signal to notify others.

    \snippet btchat/chatclient.cpp connected

    Similarly to the chat server, the readSocket() slot is called when data is available from the
    socket. Lines are read individually and converted from UTF-8. The messageReceived() signal
    is emitted.

    \snippet btchat/chatclient.cpp readSocket

    The sendMessage() slot is used to send a message to the remote device. The message is
    converted to UTF-8 and a newline is appended.

    \snippet btchat/chatclient.cpp sendMessage

    To disconnect from the remote chat service, the QBluetoothSocket instance is deleted.

    \snippet btchat/chatclient.cpp stopClient

    \section1 Chat Dialog

    The main window of this example is the chat dialog, implemented in the Chat class. This class
    displays a chat session between a single ChatServer and zero or more ChatClients. The Chat
    class is declared as:

    \snippet btchat/chat.h declaration

    First we construct the user interface

    \snippet btchat/chat.cpp Construct UI

    We create an instance of the ChatServer and respond to its clientConnected(),
    clientDiconnected(), and messageReceived() signals.

    \snippet btchat/chat.cpp Create Chat Server

    In response to the clientConnected() and clientDisconnected() signals of the ChatServer, we
    display the typical "X has joined chat." and "Y has left." messages in the chat session.

    \snippet btchat/chat.cpp clientConnected clientDisconnected

    Incoming messages from clients connected to the ChatServer are handled in the showMessage()
    slot. The message text tagged with the remote device name is displayed in the chat session.

    \snippet btchat/chat.cpp showMessage

    In response to the connect button being clicked, the application starts service discovery and
    presents a list of discovered chat services on remote devices. A ChatClient for the service
    is selected by the user.

    \snippet btchat/chat.cpp Connect to remote service

    In reponse to the connected() signals from ChatClient, we display the a "Joined chat with X."
    message in the chat session.

    \snippet btchat/chat.cpp connected

    Messages are sent to all remote devices via the ChatServer and ChatClient instances by emitting
    the sendMessage() signal.

    \snippet btchat/chat.cpp sendClicked

    We need to clean up ChatClient instances when the remote device forces a disconnect.

    \snippet btchat/chat.cpp clientDisconnected
*/
