/* Device Connection Class Implementation * * Copyright (c) 2020 The OSCAR Team * * This file is subject to the terms and conditions of the GNU General Public * License. See the file COPYING in the main directory of the source code * for more details. */ #include "deviceconnection.h" #include #include #include static QString hex(int i) { return QString("0x") + QString::number(i, 16).toUpper(); } // MARK: - inline DeviceConnectionManager & DeviceConnectionManager::getInstance() { static DeviceConnectionManager instance; return instance; } DeviceConnectionManager::DeviceConnectionManager() : m_record(nullptr), m_replay(nullptr) { } void DeviceConnectionManager::Record(QXmlStreamWriter* stream) { getInstance().m_record = stream; } void DeviceConnectionManager::Replay(QXmlStreamReader* stream) { getInstance().m_replay = stream; } void DeviceConnectionManager::startEvent(const QString & event) { if (m_record) { QDateTime now = QDateTime::currentDateTime(); now = now.toOffsetFromUtc(now.offsetFromUtc()); // force display of UTC offset #if QT_VERSION < QT_VERSION_CHECK(5,9,0) // TODO: Can we please deprecate support for Qt older than 5.9? QString timestamp = now.toString(Qt::ISODate); #else QString timestamp = now.toString(Qt::ISODateWithMs); #endif m_record->writeStartElement(event); m_record->writeAttribute("time", timestamp); } } #define RECORD(x) if (m_record) { *m_record << (x); } void DeviceConnectionManager::endEvent() { if (m_record) { m_record->writeEndElement(); } } QList DeviceConnectionManager::getAvailablePorts() { QList out; startEvent("getAvailablePorts"); if (m_replay) { // TODO } else { for (auto & info : QSerialPortInfo::availablePorts()) { out.append(SerialPortInfo(info)); } } for (auto & portInfo : out) { //qDebug().noquote() << portInfo; RECORD(portInfo); } endEvent(); return out; } // MARK: - SerialPortInfo::SerialPortInfo(const QSerialPortInfo & other) { if (other.isNull() == false) { m_info["portName"] = other.portName(); m_info["systemLocation"] = other.systemLocation(); m_info["description"] = other.description(); m_info["manufacturer"] = other.manufacturer(); m_info["serialNumber"] = other.serialNumber(); if (other.hasVendorIdentifier()) { m_info["vendorIdentifier"] = other.vendorIdentifier(); } if (other.hasProductIdentifier()) { m_info["productIdentifier"] = other.productIdentifier(); } } } SerialPortInfo::SerialPortInfo(const SerialPortInfo & other) : m_info(other.m_info) { } SerialPortInfo::SerialPortInfo(const QString & data) { QXmlStreamReader xml(data); xml.readNextStartElement(); xml >> *this; } // TODO: This is a temporary wrapper until we begin refactoring. QList SerialPortInfo::availablePorts() { return DeviceConnectionManager::getInstance().getAvailablePorts(); } QXmlStreamWriter & operator<<(QXmlStreamWriter & xml, const SerialPortInfo & info) { xml.writeStartElement("serial"); if (info.isNull() == false) { xml.writeAttribute("portName", info.portName()); xml.writeAttribute("systemLocation", info.systemLocation()); xml.writeAttribute("description", info.description()); xml.writeAttribute("manufacturer", info.manufacturer()); xml.writeAttribute("serialNumber", info.serialNumber()); if (info.hasVendorIdentifier()) { xml.writeAttribute("vendorIdentifier", hex(info.vendorIdentifier())); } if (info.hasProductIdentifier()) { xml.writeAttribute("productIdentifier", hex(info.productIdentifier())); } } xml.writeEndElement(); return xml; } QXmlStreamReader & operator>>(QXmlStreamReader & xml, SerialPortInfo & info) { if (xml.atEnd() == false && xml.isStartElement() && xml.name() == "serial") { for (auto & attribute : xml.attributes()) { QString name = attribute.name().toString(); QString value = attribute.value().toString(); if (name == "vendorIdentifier" || name == "productIdentifier") { bool ok; quint16 id = value.toUInt(&ok, 0); if (ok) { info.m_info[name] = id; } else { qWarning() << "invalid" << name << "value" << value; } } else { info.m_info[name] = value; } } } else { qWarning() << "no tag"; } xml.readNext(); return xml; } SerialPortInfo::operator QString() const { QString out; QXmlStreamWriter xml(&out); xml << *this; return out; }