openauto/btservice/AndroidBluetoothServer.cpp
Cole Brinsfield 50e077aa6e
automatic wireless device connection (#12)
* fix for omx when performing GST build

* wireless android auto bluetooth negotation

* Grab local bluetooth adapter

* Handling ping and voice session

* wait for both usb and wifi device ]connections

* Make btservice launch with openauto, allows for wireless connection automatically

* WiFi hotspot info pulled from openauto config

* Install btservice correctly

Co-authored-by: Rhys_M <rhys1802@hotmail.co.uk>
Co-authored-by: Robert Judka <robertjudka@gmail.com>
2020-08-26 19:48:36 -05:00

215 lines
6.5 KiB
C++

#include "OpenautoLog.hpp"
#include "btservice/AndroidBluetoothServer.hpp"
#include <QNetworkInterface>
#include <QThread>
namespace openauto
{
namespace btservice
{
AndroidBluetoothServer::AndroidBluetoothServer(openauto::configuration::IConfiguration::Pointer config_)
: rfcommServer_(std::make_unique<QBluetoothServer>(QBluetoothServiceInfo::RfcommProtocol, this))
, config(std::move(config_))
{
handshakeState = IDLE;
connect(rfcommServer_.get(), &QBluetoothServer::newConnection, this, &AndroidBluetoothServer::onClientConnected);
QThread *thread = QThread::create([&]{ this->stateMachine(); });
thread->start();
}
void AndroidBluetoothServer::stateMachine()
{
while(true){
switch(handshakeState){
case IDLE:
break;
case DEVICE_CONNECTED:
handshakeState = SENDING_SOCKETINFO_MESSAGE;
break;
case SENDING_SOCKETINFO_MESSAGE:
writeSocketInfoMessage();
break;
case SENT_SOCKETINFO_MESSAGE:
break;
case PHONE_RESP_SOCKETINFO:
handshakeState = SENDING_NETWORKINFO_MESSAGE;
break;
case SENDING_NETWORKINFO_MESSAGE:
writeNetworkInfoMessage();
break;
case SENT_NETWORKINFO_MESSAGE:
break;
case PHONE_RESP_NETWORKINFO:
break;
}
}
}
bool AndroidBluetoothServer::start(const QBluetoothAddress& address, uint16_t portNumber)
{
OPENAUTO_LOG(info)<<"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()));
handshakeState = DEVICE_CONNECTED;
}
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 message_length = message.ByteSize();
char byte1 = messageType & 0x000000ff;
char byte2 = (messageType & 0x0000ff00) >> 8;
byteArray.prepend(byte1);
byteArray.prepend(byte2);
byte1 = message_length & 0x000000ff;
byte2 = (message_length & 0x0000ff00) >> 8;
byteArray.prepend(byte1);
byteArray.prepend(byte2);
int sentBytes = socket->write(byteArray);
if(sentBytes != byteArray.length()) return false;
return true;
}
void AndroidBluetoothServer::writeSocketInfoMessage(){
OPENAUTO_LOG(info) << "[AndroidBluetoothServer] Sending Socket Info";
btservice::proto::SocketInfo socketInfo;
QString ipAddr;
QList<QHostAddress> list = QNetworkInterface::allAddresses();
for(int nIter=0; nIter<list.count(); nIter++)
{
if(!list[nIter].isLoopback())
if (list[nIter].protocol() == QAbstractSocket::IPv4Protocol )
ipAddr = list[nIter].toString();
}
socketInfo.set_address(ipAddr.toStdString());
socketInfo.set_port(5000);
socketInfo.set_unknown_1(0);
if(writeProtoMessage(7, socketInfo)){
OPENAUTO_LOG(info) << "[AndroidBluetoothServer] Sent Socket Info";
handshakeState = SENT_SOCKETINFO_MESSAGE;
}
else{
OPENAUTO_LOG(error) << "[AndroidBluetoothServer] Error Sending Socket Info";
handshakeState = ERROR;
}
}
void AndroidBluetoothServer::writeNetworkInfoMessage(){
OPENAUTO_LOG(info) << "[AndroidBluetoothServer] Sending Network Packet";
btservice::proto::NetworkInfo networkMessage;
networkMessage.set_ssid(config->getWifiSSID());
networkMessage.set_psk(config->getWifiPassword());
foreach(QNetworkInterface netInterface, QNetworkInterface::allInterfaces())
{
// Return only the first non-loopback MAC Address
if (!(netInterface.flags() & QNetworkInterface::IsLoopBack))
networkMessage.set_mac_addr(netInterface.hardwareAddress().toStdString());
}
networkMessage.set_security_mode(8);
networkMessage.set_unknown_2(0);
if(writeProtoMessage(3, networkMessage)){
OPENAUTO_LOG(info) << "[AndroidBluetoothServer] Sent Network Packet";
handshakeState = SENT_NETWORKINFO_MESSAGE;
}
else{
OPENAUTO_LOG(info) << "[AndroidBluetoothServer] Error sending Network Packet";
handshakeState = ERROR;
}
}
void AndroidBluetoothServer::readSocket(){
OPENAUTO_LOG(info) << "[AndroidBluetoothServer] DATA: ";
if (!socket)
return;
QByteArray data = socket->read(1024);
if(data.length()==0) return;
uint16_t messageType = data[2]<<8 | data[3];
btservice::proto::PhoneResponse resp;
switch(messageType){
case 2:
break;
case 6:
resp.ParseFromString(data.toStdString().c_str());
break;
}
switch(handshakeState){
case IDLE:
break;
case DEVICE_CONNECTED:
break;
case SENDING_SOCKETINFO_MESSAGE:
break;
case SENT_SOCKETINFO_MESSAGE:
if(messageType == 2){
OPENAUTO_LOG(info) << "[AndroidBluetoothServer] Phone acknowledged Socket Info";
handshakeState = PHONE_RESP_SOCKETINFO;
}else{
OPENAUTO_LOG(info) << "[AndroidBluetoothServer] Got unexpected message";
handshakeState = ERROR;
}
break;
case PHONE_RESP_SOCKETINFO:
break;
case SENDING_NETWORKINFO_MESSAGE:
break;
case SENT_NETWORKINFO_MESSAGE:
if(messageType == 6){
OPENAUTO_LOG(info) << "[AndroidBluetoothServer] Phone acknowledged Network Info with status code: "<<resp.status_code();
handshakeState = PHONE_RESP_NETWORKINFO;
}else{
OPENAUTO_LOG(info) << "[AndroidBluetoothServer] Got unexpected message";
handshakeState = ERROR;
}
break;
case PHONE_RESP_NETWORKINFO:
break;
}
}
}
}