ITS
ApplicationManagement.cpp
Go to the documentation of this file.
2 
3 ApplicationManagement::ApplicationManagement(Manager *man, bool bt, bool ut, bool app) :
4  m_can((FakeCANProvider*)man->hashMap["CAN"]),
5  m_gps((FakeGPSProvider*)man->hashMap["GPS"]),
6  m_network((ParameterNetwork*)man->hashMap["Network"]),
7  m_bt(bt),
8  m_hasUt(ut)
9 {
10  /* CAN & GPS initialization */
11  if(app)
12  {
13  QObject::connect(m_can, SIGNAL(canChanged()), this, SLOT(situationChanged()));
14  QObject::connect(m_gps, SIGNAL(positionChanged()), this, SLOT(situationChanged()));
15  }
16 
17  /* BT initialization */
18  if(m_bt)
19  {
20  QBluetoothLocalDevice localAdapter;
21  QString localDeviceName;
22 
23  rfcommServer = new QBluetoothServer(QBluetoothServiceInfo::RfcommProtocol, this);
24  // QObject::connect(rfcommServer, SIGNAL(newConnection()), this, SLOT(clientConnected()));
25 
26  if(localAdapter.isValid())
27  {
28  // Turn Bluetooth on
29  qInfo() << "Turning on Bluetooth device";
30  localAdapter.powerOn();
31 
32  // Read local device name
33  qInfo() << "Reading Bluetooth device name";
34  localDeviceName = localAdapter.name();
35  qInfo() << "Local adapter is named" << localDeviceName;
36 
37  // Make it visible to others
38  qInfo() << "Making Bluetooth device visible";
39  localAdapter.setHostMode(QBluetoothLocalDevice::HostDiscoverable);
40 
41  if(!rfcommServer->listen(localAdapter.address()))
42  {
43  qWarning() << "Cannot bind application manager to" << localAdapter.address().toString();
44  m_bt = false;
45  }
46  else
47  {
48  qInfo() << "Listening to" << localAdapter.address().toString();
49  /* Textual description */
50 // serviceInfo.setAttribute(QBluetoothServiceInfo::ServiceName, tr("GeoNet application bluetooth server"));
51 // serviceInfo.setAttribute(QBluetoothServiceInfo::ServiceDescription, tr("Make bluetooth connection between HMI "
52 // "and GeoNet application"));
53 // serviceInfo.setAttribute(QBluetoothServiceInfo::ServiceProvider, tr("URCA"));
54  serviceInfo.setAttribute(QBluetoothServiceInfo::ServiceName, tr("DENM BT forwarder"));
55  serviceInfo.setAttribute(QBluetoothServiceInfo::ServiceDescription, tr("Forward DENM from and to Android"));
56  serviceInfo.setAttribute(QBluetoothServiceInfo::ServiceProvider, tr("URCA"));
57  qInfo() << "Textual description set";
58 
59  /* UUID definition */
60  QBluetoothServiceInfo::Sequence classId;
61  static const QLatin1String serviceUuid("76931fac-9dab-2b36-9ccf-c248b87d6ae3");
62  // static const QLatin1String serviceUuid("e8e10f95-1a70-4b27-9ccf-02010264e9c8");
63 
64  classId << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::SerialPort));
65  serviceInfo.setAttribute(QBluetoothServiceInfo::BluetoothProfileDescriptorList, classId);
66 
67  classId.prepend(QVariant::fromValue(QBluetoothUuid(serviceUuid)));
68 
69  serviceInfo.setAttribute(QBluetoothServiceInfo::ServiceClassIds, classId);
70 
71  serviceInfo.setServiceUuid(QBluetoothUuid(serviceUuid));
72  qInfo() << "UUID set to" << serviceInfo.serviceUuid();
73  qInfo() << "ServicesClassInfo" << serviceInfo.serviceClassUuids();
74 
75  /* Making BT discoverable */
76  QBluetoothServiceInfo::Sequence publicBrowse;
77  publicBrowse << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::PublicBrowseGroup));
78  serviceInfo.setAttribute(QBluetoothServiceInfo::BrowseGroupList, publicBrowse);
79  qInfo() << "BT discoverable";
80 
81  /* ProtocolDescriptorList */
82  QBluetoothServiceInfo::Sequence protocolDescriptorList;
83  QBluetoothServiceInfo::Sequence protocol;
84  protocol << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::L2cap));
85  protocolDescriptorList.append(QVariant::fromValue(protocol));
86  protocol.clear();
87  protocol << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::Rfcomm))
88  << QVariant::fromValue(quint8(rfcommServer->serverPort()));
89  protocolDescriptorList.append(QVariant::fromValue(protocol));
90  serviceInfo.setAttribute(QBluetoothServiceInfo::ProtocolDescriptorList, protocolDescriptorList);
91  qInfo() << "PDL set";
92 
93  /* Service registering */
94  bool foo = serviceInfo.registerService(localAdapter.address());
95  qInfo() << "Service registration" << foo;
96 
97  qInfo() << "BT resume" << rfcommServer->serverAddress().toString() << rfcommServer->serverPort()
98  << rfcommServer->serverType();
99 
100  QObject::connect(rfcommServer, SIGNAL(newConnection()), this, SLOT(clientConnected()));
101 
102  QObject::connect(this, SIGNAL(btMessageReceived(QByteArray)), this, SLOT(sendMessageToFac(QByteArray)));
103  }
104  }
105  else
106  {
107  qWarning() << "No connected Bluetooth device found";
108  delete rfcommServer;
109  rfcommServer = 0;
110  m_bt = false;
111  }
112  }
113 
114  /* UDP initialization */
115  m_udpSocket = new QUdpSocket(this);
116  m_udpSocket->bind();
117  QObject::connect(m_udpSocket, SIGNAL(readyRead()), this, SLOT(readUdpSocket()));
118  QObject::connect(this, SIGNAL(udpMessageReceived(QByteArray)), this, SLOT(sendMessageToBt(QByteArray)));
119  m_network->addPort("Application", m_udpSocket->localPort());
120  qDebug() << "Application" << m_udpSocket->localPort();
121 
122  /* UT Initialization */
123  if(m_hasUt)
124  {
125  m_ut = (ParameterUpperTester*)man->hashMap["UpperTester"];
126  m_utSocket = new QUdpSocket(this);
127  m_utSocket->open(QIODevice::ReadWrite);
128  m_utSocket->bind();
129  m_network->addPort("ApplicationUT", m_utSocket->localPort());
130  qDebug() << "ApplicationUT" << m_utSocket->localPort();
131  QObject::connect(m_utSocket, SIGNAL(readyRead()), this, SLOT(readUtSocket()));
132  QObject::connect(this, SIGNAL(utMessageReceived(QByteArray)), this, SLOT(sendMessageToFac(QByteArray)));
133  }
134 
135 }
136 
138 {
139  qDebug() << "Deleting application management";
140  if(m_bt)
141  {
142  /* Unregister service */
143  serviceInfo.unregisterService();
144 
145  /* Close sockets */
146  qDeleteAll(clientSockets);
147 
148  /* Close server */
149  delete rfcommServer;
150  rfcommServer = 0;
151  }
152 }
153 
155 {
156  QBluetoothSocket *socket = rfcommServer->nextPendingConnection();
157  if(!socket)
158  return;
159 
160  qInfo() << "There is a new client connected" << socket->peerName();
161 
162  clientSockets.append(socket);
163  QObject::connect(clientSockets.last(), SIGNAL(readyRead()), this, SLOT(readBtSocket()));
164  QObject::connect(clientSockets.last(), SIGNAL(disconnected()), this, SLOT(clientDisconnected()));
165 }
166 
168 {
169  QBluetoothSocket *socket = qobject_cast<QBluetoothSocket *>(sender());
170  if(!socket)
171  return;
172 
173  qInfo() << "Receiving data from BT";
174  QByteArray line = socket->readAll();
175  qInfo() << line.toHex() << "received from" << socket->peerName();
176  emit btMessageReceived(line);
177 }
178 
180 {
181  QBluetoothSocket *socket = qobject_cast<QBluetoothSocket *>(sender());
182  if(!socket)
183  return;
184 
185  qInfo() << socket->peerName() << "disconnected";
186  clientSockets.removeOne(socket);
187  socket->deleteLater();
188 }
189 
190 void ApplicationManagement::sendMessageToBt(const QByteArray &message)
191 {
192  qint64 size;
193  QByteArray msg;
194 
195  qInfo() << "I have to sent" << message.toHex() << "to BT / UT";
196  if(m_bt)
197  {
198  foreach (QBluetoothSocket *socket, clientSockets)
199  {
200  qInfo() << "Sending" << message.toHex() << "to" << socket->peerName();
201  msg = transformMessageToBT(message);
202  qInfo() << "Sending" << msg.toHex() << "to BT";
203  size = socket->write(msg);
204  qInfo() << size << "Bytes sent to BT";
205  }
206  }
207  if(m_hasUt)
208  {
209  quint16 utPort = getUtPort(message.at(0));
210  if(utPort != 0)
211  {
212  m_udpSocket->writeDatagram(message, QHostAddress::LocalHost, utPort);
213  qDebug() << message.toHex() << "sent to UT" << utPort;
214  }
215  else
216  qInfo() << "This message is not supposed to be sent to UT";
217  }
218 }
219 
221 {
222  QUdpSocket *socket = qobject_cast<QUdpSocket*>(sender());
223  while(socket->hasPendingDatagrams())
224  {
225  qDebug() << socket->localPort() << "in readUdpSocket" << socket->state();
226  QNetworkDatagram datagram = socket->receiveDatagram();
227  qInfo() << datagram.data().toHex() << "received from facilities";
228  emit udpMessageReceived(datagram.data());
229  qInfo() << "readUdpSocket emit data";
230  }
231 }
232 
234 
235 void ApplicationManagement::sendMessageToFac(const QByteArray &message)
236 {
237  switch (message.at(0))
238  {
239  case 0x10:
240  case 0x12:
241  case 0x14:
242  qDebug() << "Application sends" << message.toHex() << m_network->internalPort("DENM");
243  m_udpSocket->writeDatagram(message, QHostAddress::LocalHost, m_network->internalPort("DENM"));
244  break;
245  default:
246  break;
247  }
248 }
249 
251 {
252  while(m_utSocket->hasPendingDatagrams())
253  {
254  QNetworkDatagram datagram = m_utSocket->receiveDatagram();
255  m_utPort = datagram.senderPort();
256  qInfo() << datagram.data().toHex() << "received from UT";
257  emit utMessageReceived(datagram.data());
258  }
259 }
260 
261 QByteArray ApplicationManagement::transformMessageToBT(const QByteArray &message)
262 {
263  QByteArray ret = message;
264  DENM_t *denm = 0;
265  ValidityDuration_t validity = 600;
266  long unsigned int detectionTime;
267 
268  switch (message[0])
269  {
270  case 0x17:
271  uper_decode_complete(NULL, &asn_DEF_DENM, (void**)&denm, message.right(message.length() - 3), message.length() - 3);
272  asn_fprint(stdout, &asn_DEF_DENM, denm);
273  if(denm->denm.management.validityDuration)
274  validity = *denm->denm.management.validityDuration;
275  asn_INTEGER2ulong((const INTEGER_t*)&denm->denm.management.detectionTime, &detectionTime);
276  qInfo() << "Transforming AppDENMIndication";
277  ret = AppDenmIndication::toBluetooth(*denm, (detectionTime + (validity * 1000) - m_gps->timestamp()) / 1000);
278  qInfo() << ret.toHex();
279  break;
280  default:
281  break;
282  }
283 
284  return ret;
285 }
286 
287 quint16 ApplicationManagement::getUtPort(const char mt)
288 {
289  quint16 port = m_ut->upperTesterEventIndicationListenPort();
290 
291  switch((unsigned char)mt)
292  {
293  case 0x16:
294  port = m_network->internalPort("UpperTester");
295  break;
296  case 0x18:
297  port = 0;
298  default:
299  break;
300  }
301 
302  return port;
303 }
int upperTesterEventIndicationListenPort() const
upperTesterEventIndicationListenPort Port used to listen for event indication getter.
void clientConnected()
clientConnected Slot used when a new client is connected.
void sendMessageToBt(const QByteArray &message)
sendMessageToBt Slot used to send message through the Bluetooth socket.
asn_dec_rval_t uper_decode_complete(struct asn_codec_ctx_s *opt_codec_ctx, struct asn_TYPE_descriptor_s *type_descriptor, void **struct_ptr, const void *buffer, size_t size)
Definition: per_decoder.c:11
ParameterNetwork * m_network
void btMessageReceived(const QByteArray &message)
btMessageReceived Signal used when data come through the Bluetooth socket.
static QByteArray toBluetooth(DENM_t denm, quint32 validityDuration)
toBluetooth Encode an AppDenmIndication understable by the HMI.
QHash< QString, void * > hashMap
Definition: Manager.h:53
quint64 timestamp()
timestamp Timestamp getter.
QList< QBluetoothSocket * > clientSockets
QByteArray transformMessageToBT(const QByteArray &message)
transformMessageToBT Transform message from Facilities to send to the HMI.
void sendMessageToFac(const QByteArray &message)
sendMessageToFac Slot used to send message to the Facilities layer.
void udpMessageReceived(const QByteArray &message)
udpMessageReceived Signal used when data come through the UDP socket.
~ApplicationManagement()
~ApplicationManagement ApplicationManagement destructor
void readUdpSocket()
readUdpSocket Slot used when data come to the UDP socket.
int asn_INTEGER2ulong(const INTEGER_t *i, unsigned long *l)
Definition: INTEGER.c:825
quint16 internalPort(QString service)
internalPort Get the internal BTP port from service name.
QBluetoothServer * rfcommServer
void addPort(QString service, quint16 port)
addPort Add BTP port to the internal BTP ports from service name.
QBluetoothServiceInfo serviceInfo
long ValidityDuration_t
void utMessageReceived(const QByteArray &message)
utMessageReceived Signal used when data come from the Uppertester.
int asn_fprint(FILE *stream, asn_TYPE_descriptor_t *td, const void *struct_ptr)
Definition: constr_TYPE.c:36
void clientDisconnected()
clientDisconnected Slot used when a client is disconnected.
Definition: DENM.h:23
quint16 getUtPort(const char mt)
getUtPort Get the UpperTester port from MessageType.
ApplicationManagement(Manager *man, bool bt, bool ut, bool app)
ApplicationManagement ApplicationManagement constructor.
void situationChanged()
situationChanged Slot used when GPS or CAN bus have a new value.
void readUtSocket()
readUtSocket Slot used when data come to the UpperTester socket.
ParameterUpperTester * m_ut
asn_TYPE_descriptor_t asn_DEF_DENM
Definition: DENM.c:45
void readBtSocket()
readBtSocket Slot used when data come to the Bluetooth socket.
Manager of the Application layer.