* Working on cleaning wifi * Reworked bluetooth handshake based around @presslab-us's work * Forgot to remove a line * QOL: try to reconnect to last phone BT on openauto start * bt autoconnect raspberry pi workaround * Try to connect to last successful bluetooth device * Bad merge fix * pointers * typo * Update SocketInfoResponse.proto * Added a config option to autoconnect to last bt device (defaults off)
223 lines
7.3 KiB
C++
223 lines
7.3 KiB
C++
#include <QNetworkInterface>
|
|
#include <QThread>
|
|
#include "OpenautoLog.hpp"
|
|
#include "btservice/AndroidBluetoothServer.hpp"
|
|
|
|
namespace openauto
|
|
{
|
|
namespace btservice
|
|
{
|
|
|
|
AndroidBluetoothServer::AndroidBluetoothServer(openauto::configuration::IConfiguration::Pointer config)
|
|
: rfcommServer_(std::make_unique<QBluetoothServer>(QBluetoothServiceInfo::RfcommProtocol, this))
|
|
, socket_(nullptr)
|
|
, config_(std::move(config))
|
|
{
|
|
connect(rfcommServer_.get(), &QBluetoothServer::newConnection, this, &AndroidBluetoothServer::onClientConnected);
|
|
}
|
|
|
|
bool AndroidBluetoothServer::start(const QBluetoothAddress& address, uint16_t portNumber)
|
|
{
|
|
OPENAUTO_LOG(info) << "[AndroidBluetoothServer] listening.";
|
|
return rfcommServer_->listen(address, portNumber);
|
|
}
|
|
|
|
void AndroidBluetoothServer::onClientConnected()
|
|
{
|
|
socket_ = rfcommServer_->nextPendingConnection();
|
|
if(socket_ != nullptr)
|
|
{
|
|
OPENAUTO_LOG(info) << "[AndroidBluetoothServer] Device Connected: " << socket_->peerName().toStdString();
|
|
connect(socket_, SIGNAL(readyRead()), this, SLOT(readSocket()));
|
|
writeSocketInfoRequest();
|
|
}
|
|
else
|
|
{
|
|
OPENAUTO_LOG(error) << "[AndroidBluetoothServer] received null socket during client connection.";
|
|
}
|
|
}
|
|
|
|
bool AndroidBluetoothServer::writeProtoMessage(uint16_t messageType, google::protobuf::Message& message)
|
|
{
|
|
QByteArray byteArray(message.SerializeAsString().c_str(), message.ByteSize());
|
|
uint16_t messageLength = message.ByteSize();
|
|
byteArray.prepend(messageType & 0x000000ff);
|
|
byteArray.prepend((messageType & 0x0000ff00) >> 8);
|
|
byteArray.prepend(messageLength & 0x000000ff);
|
|
byteArray.prepend((messageLength & 0x0000ff00) >> 8);
|
|
|
|
if(socket_->write(byteArray) != byteArray.length())
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void AndroidBluetoothServer::writeSocketInfoRequest()
|
|
{
|
|
OPENAUTO_LOG(info) << "[AndroidBluetoothServer] Sending SocketInfoRequest.";
|
|
|
|
QString ipAddr;
|
|
foreach(QHostAddress addr, QNetworkInterface::allAddresses())
|
|
{
|
|
if(!addr.isLoopback() && (addr.protocol() == QAbstractSocket::IPv4Protocol))
|
|
{
|
|
ipAddr = addr.toString();
|
|
}
|
|
}
|
|
|
|
btservice::proto::SocketInfoRequest socketInfoRequest;
|
|
socketInfoRequest.set_ip_address(ipAddr.toStdString());
|
|
OPENAUTO_LOG(info) << "[AndroidBluetoothServer] ipAddress: "<< ipAddr.toStdString();
|
|
|
|
socketInfoRequest.set_port(5000);
|
|
OPENAUTO_LOG(info) << "[AndroidBluetoothServer] port: "<< 5000;
|
|
|
|
if(this->writeProtoMessage(1, socketInfoRequest))
|
|
{
|
|
OPENAUTO_LOG(info) << "[AndroidBluetoothServer] Sent SocketInfoRequest.";
|
|
}
|
|
else
|
|
{
|
|
OPENAUTO_LOG(error) << "[AndroidBluetoothServer] Error sending SocketInfoRequest.";
|
|
}
|
|
}
|
|
void AndroidBluetoothServer::writeSocketInfoResponse()
|
|
{
|
|
OPENAUTO_LOG(info) << "[AndroidBluetoothServer] Sending SocketInfoResponse.";
|
|
QString ipAddr;
|
|
foreach(QHostAddress addr, QNetworkInterface::allAddresses())
|
|
{
|
|
if(!addr.isLoopback() && (addr.protocol() == QAbstractSocket::IPv4Protocol))
|
|
{
|
|
ipAddr = addr.toString();
|
|
}
|
|
}
|
|
|
|
btservice::proto::SocketInfoResponse socketInfoResponse;
|
|
socketInfoResponse.set_ip_address(ipAddr.toStdString());
|
|
OPENAUTO_LOG(info) << "[AndroidBluetoothServer] ipAddress: "<< ipAddr.toStdString();
|
|
|
|
socketInfoResponse.set_port(5000);
|
|
OPENAUTO_LOG(info) << "[AndroidBluetoothServer] port: "<< 5000;
|
|
|
|
socketInfoResponse.set_status(btservice::proto::Status::STATUS_SUCCESS);
|
|
OPENAUTO_LOG(info) << "[AndroidBluetoothServer] status: "<< btservice::proto::Status::STATUS_SUCCESS;
|
|
|
|
|
|
if(this->writeProtoMessage(7, socketInfoResponse))
|
|
{
|
|
OPENAUTO_LOG(info) << "[AndroidBluetoothServer] Sent SocketInfoResponse.";
|
|
}
|
|
else
|
|
{
|
|
OPENAUTO_LOG(error) << "[AndroidBluetoothServer] Error sending SocketInfoResponse.";
|
|
}
|
|
}
|
|
|
|
void AndroidBluetoothServer::handleSocketInfoRequestResponse(QByteArray data)
|
|
{
|
|
btservice::proto::SocketInfoResponse socketInfoResponse;
|
|
socketInfoResponse.ParseFromArray(data, data.size());
|
|
OPENAUTO_LOG(info) <<"[AndroidBluetoothServer] Received SocketInfoRequestResponse, status: "<<socketInfoResponse.status();
|
|
if(socketInfoResponse.status() == 0)
|
|
{
|
|
// A status of 0 should be successful handshake (unless phone later reports an error, aw well)
|
|
// save this phone so we can autoconnect to it next time
|
|
config_->setLastBluetoothPair(socket_->peerAddress().toString().toStdString());
|
|
config_->save();
|
|
}
|
|
}
|
|
|
|
|
|
void AndroidBluetoothServer::handleSocketInfoRequest(QByteArray data)
|
|
{
|
|
OPENAUTO_LOG(info) << "[AndroidBluetoothServer] Reading SocketInfoRequest.";
|
|
|
|
btservice::proto::SocketInfoRequest socketInfoRequest;
|
|
|
|
writeSocketInfoResponse();
|
|
}
|
|
|
|
void AndroidBluetoothServer::writeNetworkInfoMessage()
|
|
{
|
|
OPENAUTO_LOG(info) << "[AndroidBluetoothServer] Sending NetworkInfoMessage.";
|
|
|
|
btservice::proto::NetworkInfo networkMessage;
|
|
networkMessage.set_ssid(config_->getWifiSSID());
|
|
OPENAUTO_LOG(info) << "[AndroidBluetoothServer] SSID: "<<config_->getWifiSSID();
|
|
|
|
networkMessage.set_psk(config_->getWifiPassword());
|
|
OPENAUTO_LOG(info) << "[AndroidBluetoothServer] PSKEY: "<<config_->getWifiPassword();
|
|
|
|
if(config_->getWifiMAC().empty())
|
|
{
|
|
networkMessage.set_mac_addr(QNetworkInterface::interfaceFromName("wlan0").hardwareAddress().toStdString());
|
|
OPENAUTO_LOG(info) << "[AndroidBluetoothServer] MAC: "<<QNetworkInterface::interfaceFromName("wlan0").hardwareAddress().toStdString();
|
|
}
|
|
else
|
|
{
|
|
networkMessage.set_mac_addr(config_->getWifiMAC());
|
|
OPENAUTO_LOG(info) << "[AndroidBluetoothServer] MAC: "<< config_->getWifiMAC();
|
|
}
|
|
|
|
networkMessage.set_security_mode(btservice::proto::SecurityMode::WPA2_PERSONAL);
|
|
OPENAUTO_LOG(info) << "[AndroidBluetoothServer] Security: "<< btservice::proto::SecurityMode::WPA2_PERSONAL;
|
|
|
|
networkMessage.set_ap_type(btservice::proto::AccessPointType::STATIC);
|
|
OPENAUTO_LOG(info) << "[AndroidBluetoothServer] AP Type: "<< btservice::proto::AccessPointType::STATIC;
|
|
|
|
|
|
if(this->writeProtoMessage(3, networkMessage))
|
|
{
|
|
OPENAUTO_LOG(info) << "[AndroidBluetoothServer] Sent NetworkInfoMessage";
|
|
}
|
|
else
|
|
{
|
|
OPENAUTO_LOG(info) << "[AndroidBluetoothServer] Error sending NetworkInfoMessage.";
|
|
}
|
|
}
|
|
|
|
void AndroidBluetoothServer::handleUnknownMessage(int messageType, QByteArray data)
|
|
{
|
|
OPENAUTO_LOG(info) << "[AndroidBluetoothServer] Received unknown MessageType of "<<messageType;
|
|
OPENAUTO_LOG(info) << "[AndroidBluetoothServer] Unknown Message Data: "<<data.toHex(' ').toStdString() ;
|
|
}
|
|
|
|
void AndroidBluetoothServer::readSocket()
|
|
{
|
|
if(!socket_)
|
|
{
|
|
return;
|
|
}
|
|
|
|
auto data = socket_->readAll();
|
|
if(data.length() == 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
uint16_t messageType = (data[2] << 8) | data[3];
|
|
switch(messageType)
|
|
{
|
|
case 1:
|
|
handleSocketInfoRequest(data);
|
|
break;
|
|
case 2:
|
|
writeNetworkInfoMessage();
|
|
break;
|
|
case 7:
|
|
data.remove(0, 4);
|
|
handleSocketInfoRequestResponse(data);
|
|
break;
|
|
default:
|
|
data.remove(0, 4);
|
|
handleUnknownMessage(messageType, data);
|
|
break;
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|