view HardwareOperations.h @ 3:4ace58a7c03c

Send disconnect command before closing the connection The old BT module transmitted a notification in case a connection were closed which cause the ostc to exit the uart loop. The new one doesn't do this => send disconnect command to avoid waiting in the installation loop till timeout or button press.
author Ideenmodellierer
date Fri, 28 Nov 2025 20:00:02 +0100
parents 0b3630a29ad8
children
line wrap: on
line source

//////////////////////////////////////////////////////////////////////////////
/// \file   HardwareOperations.h
/// \brief  API for HW dive computer drivers.
/// \author JD Gascuel.
/// \sa     OSTC3Operations.h
///
/// \copyright (c) 2011-2016 JD Gascuel. All rights reserved.
/// $Id$
//////////////////////////////////////////////////////////////////////////////
//
// BSD 2-Clause License:
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
//    this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
// THE POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////////
// HISTORY
//  2012-09-22 : [jDG] Initial version, made for OSTC Companion.
//  2014-07-07 : [jDG] Cleanups for Subsurface google-summer-of-code.
//  2014-07-25 : [jDG] BSD 2-clause license.
//  2016-07-14 : ÍjDG] Adding codes for hardware variants of OSTC2/3/4.

#ifndef HARDWARE_OPERATIONS_H
#define HARDWARE_OPERATIONS_H

#include <QDateTime>
#include <QImage>
#include <QString>
#include <QStringList>
#include <QSize>
#include <QRegularExpression>

#ifdef TEST_MODE
#   include "test/SerialTest.h"
#else
#   include "Serial.h"
#endif

class HexFile;

//////////////////////////////////////////////////////////////////////////////
/// \brief  API for HW dive computer drivers.
///
/// This class include high level commands used by the *Companion* GUI,
/// and other generic services:
/// - List of currently known serial ports:
///   listBluetoothPorts() or listUSBPorts().
///
/// - Send a command, and wait for the proper acknowledge: retryCommand().
///
/// \sa OSTCFrogOperations, OSTC2cOperations, OSTC3Operations,
/// \nosubgrouping
class HardwareOperations
{
protected:
#ifdef TEST_MODE
    /// \brief Fake communication port used for mockup operations.
    SerialTest  _serial;
#else
    /// \brief Communication port used for all I/O operations.
    ///
    /// Note that in *emulation mode*, aka TEST_MODE, this is replaced by
    /// an instance of SerialTest.
    Serial      _serial;
#endif

public:
    //////////////////////////////////////////////////////////////////////////
    /// \name Class management
    /// \{
    ///
    /// Managing the hierarchy of driver classes used to handle the various
    /// existing H&W devices.

    /// \brief mandatory (and empty) virtual descructor in the base class.
    virtual ~HardwareOperations() {}

    //------------------------------------------------------------------------
    /// \brief The name of the computer driver.
    /// \returns the name of a particular driver implementation,
    /// eg. "OSTCSport", "OSTC2c", "OSTC3", ...
    virtual QString model() const = 0;

    //------------------------------------------------------------------------
    /// \brief Gives access to serial port in use.
    /// Used for other high and low level operations, eg. in *OSTC Planner*.
    inline Serial& serial() { return _serial; }

    /// \}
    //////////////////////////////////////////////////////////////////////////
    /// \name Introspection
    /// \{
    ///
    /// Methods available to ask the connected device what it does support,
    /// and how to manage it.

    //------------------------------------------------------------------------
    /// \brief Optional features present in the dive computer hardware.
    ///
    /// 8 bit mask. See HardwareDescriptor for known combinations.
    ///
    enum HardwareOption {
        HW_CHARGEABLE_BATTERY= 0x01,    ///< Recharge option.
        HW_LIGHT_SENSOR      = 0x02,    ///< Detects light level, and tune screen.
        HW_S8_COM            = 0x04,    ///< Analog connector to O2 cells.
        HW_OPTICAL_COM       = 0x08,    ///< Digital connector to O2 cells.
        HW_BLUETOOTH_COM     = 0x10,    ///< Bluetooth, hence no USB connection.
        HW_DUALCORE          = 0x20,    ///< Dual core processor.
    };

    ///-----------------------------------------------------------------------
    /// \brief Dive computer set of features.
    ///
    /// Set of features present on a given H&W dive computers.
    /// \note that several versions exists of a given computer, and there
    /// is not a uniq mapping of a given feature set to a dive computer
    /// (eg. 0x13 is ambiguous).
    ///
    enum HardwareDescriptor {
        HW_UNKNOWN_OSTC = 0,
        HW_Frog        = HW_BLUETOOTH_COM,
        HW_OSTCSport_a = HW_LIGHT_SENSOR | HW_BLUETOOTH_COM,
        HW_OSTCSport_b = HW_OSTCSport_a | HW_CHARGEABLE_BATTERY,
        HW_OSTC2c      = HW_CHARGEABLE_BATTERY,
        HW_OSTC2_a     = HW_CHARGEABLE_BATTERY | HW_BLUETOOTH_COM,
        HW_OSTC2_b     = HW_OSTCSport_b,
        HW_OSTC2_c     = HW_OSTC2_b | HW_OPTICAL_COM,
        HW_OSTC3       = HW_LIGHT_SENSOR | HW_OPTICAL_COM,
        HW_OSTC3p_a    = HW_LIGHT_SENSOR | HW_OPTICAL_COM | HW_BLUETOOTH_COM,
        HW_OSTC3p_b    = HW_OSTCSport_b,
        HW_OSTCcR_a    = HW_CHARGEABLE_BATTERY | HW_S8_COM,
        HW_OSTCcR_b    = HW_OSTCcR_a | HW_LIGHT_SENSOR,
        HW_OSTC4       = HW_DUALCORE|HW_BLUETOOTH_COM|
                         HW_OPTICAL_COM|HW_LIGHT_SENSOR|HW_CHARGEABLE_BATTERY
    };

    //------------------------------------------------------------------------
    /// \brief Ask the connect device for its hardware options.
    ///
    /// This is used to guess the device model, even if there is no unicity.
    HardwareDescriptor hardwareDescriptor();

    //------------------------------------------------------------------------
    /// \brief Features supported by OSTC Companion on the connected device.
    ///
    /// Each driver (instance of this class) is requested to tell *Companion*
    /// what are the supported command.
    ///
    enum CompanionFeatures {
        PARAMETERS   = (1<<0),  ///< Download/Edit/Upload various parameters.
        DATE         = (1<<1),  ///< Set date & time.
        NAME         = (1<<2),  ///< Set custom text displayed on main screen.
        ICON         = (1<<3),  ///< Set custom image displayed on main screen.
        DUMPSCREEN   = (1<<4),  ///< Makes copy of current screen.
        FIRMWARE     = (1<<5),  ///< Do firmware upgrades.
        HELIUM_DIVE  = (1<<6),  ///< Computes deco stops for trimix dives.
        CCR_DIVE     = (1<<7),  ///< Computes deco stops for rebreather dives.
        BLUETOOTH    = (1<<8),  ///< Use Bluetooh communication (instead of USB)
        VPM_MODEL    = (1<<9),  ///< Also propose VPM deco stops.
        SIGNAL_CHECK = (1<<10)  ///< Echo signal quality for bluetooth computer
    };

    /// \brief Tells what is supported for a given computer.
    virtual CompanionFeatures supported() const = 0;

    //------------------------------------------------------------------------
    /// \brief Length of the custom text displayed by the device.
    ///
    /// \returns (w,h), where \a w is text width (in chars), and \a h is the
    /// number of lines.
    /// Used by *Companion* GUI to format user input.
    virtual QSize nameSize() const = 0;

    //------------------------------------------------------------------------
    /// \brief filename matching template for compatible firmware.
    ///
    /// Used by the *Upgrade Firmware...* command to propose only firmwares
    /// designed for the connected device.
    virtual QString firmwareTemplate() const = 0;

    //------------------------------------------------------------------------
    /// \brief Read in the specific firmware file format.
    ///
    /// History is a bit complex here, and the published firmware have
    /// different file formats (due to support tool, and/or need for
    /// encryption).
    /// So each driver have to implement its specific loader.
    virtual void loadFirmware(HexFile&, const QString& fileName) const = 0;

    //------------------------------------------------------------------------
    /// \brief Regular expression to filter *USB* or *Bluetooth* port names.
    ///
    /// Used to propose only the list of ports that matches the serial ports
    /// compatible with USB/Bluetooth emulation and the connected dive
    /// computer.
 //   virtual QRegExp portTemplate() const = 0;
    virtual QRegularExpression portTemplate() const = 0;
    /// \}
    //////////////////////////////////////////////////////////////////////////
    /// \name High level commands
    /// \{
    ///
    /// Commands that implement the specific protocol for a device, to perform
    /// all services needed by *OSTC Copmanion*.

    //------------------------------------------------------------------------
    /// \brief Open download mode communication to the dive computer.
    ///
    /// Open comm port, start download mode, check the blessed reply,
    /// and get the computer identity (for description() ).
    ///
    /// \note this mode allows common commands to be processed, but not
    ///       firmware upgrade.
    ///
    /// \returns TRUE is everything went well.
    /// \sa connectServiceMode() and disconnect().
    virtual bool connect() = 0;

    //------------------------------------------------------------------------
    /// \brief Open service mode communication to the dive computer.
    ///
    /// Open comm port, start service mode, check the blessed reply.
    /// \note this mode is mandatory to allow upgradeFW().
    ///
    /// \returns TRUE is everything went well.
    /// \sa connect() and disconnect().
    virtual void connectServiceMode() = 0;

    //------------------------------------------------------------------------
    /// \brief Echo a message on the connected device screen.
    ///
    /// Used on most devices to display commands as they are processed,
    /// so the user can see *OSTC Companion* is working properly, by seeing
    /// progress on the dive computer itself.
    virtual void writeText(const QString& msg) = 0;

    //------------------------------------------------------------------------
    /// \brief Set HW dive computer date and time.
    virtual void setDate(const QDateTime& date) = 0;

    //------------------------------------------------------------------------
    /// \brief Set HW dive computer user text.
    virtual void setName(const QString& newName) = 0;

    //------------------------------------------------------------------------
    /// \brief Display signal quality at OSTC.
    virtual void getSignal() = 0;

    //------------------------------------------------------------------------
    /// \brief Read all header from OSTC
    virtual void getAllHeader(unsigned char* pBuffer) = 0;

    //------------------------------------------------------------------------
    /// \brief Write all header from OSTC
    virtual void writeAllHeader(unsigned char* pBuffer) = 0;


    //------------------------------------------------------------------------
    /// \brief Read all samples from OSTC
    virtual void getAllSamples(unsigned char* pBuffer) = 0;

    //------------------------------------------------------------------------
    /// \brief Write all samples to OSTC
    virtual void writeAllSamples(unsigned char* pBuffer) = 0;

    //------------------------------------------------------------------------
    /// \brief Set HW dive computer icon set
    ///
    /// *Currently only supported by Frog dive computer*.
    virtual void setIcons(const QString& fileName) = 0;

    //------------------------------------------------------------------------
    /// \brief Take a snapshot of the connected computer's screen.
    ///
    /// *Currently only supported by OSTC mk2/2n/2c dive computers*.
    virtual QImage dumpScreen() const = 0;

    //------------------------------------------------------------------------
    /// \brief Upgrade HW dive computer firmware.
    ///
    /// \note needs service mode connection.
    /// \sa connectServiceMode().
    virtual void upgradeFW(const QString& fileName) = 0;

    //------------------------------------------------------------------------
    /// \brief Close connection.
    ///
    /// Exit service mode, and close everything.
    /// \p closing should be set when ending Companion, so
    /// an error make a won't crash if the interface is already
    /// deleted.
    virtual bool disconnect(bool closing = false) = 0;

    /// \}
    //////////////////////////////////////////////////////////////////////////
    /// \name Low level protocol
    /// \{
    ///
    /// Command and methods that have to be implemented for each device
    /// to retrieve device descriptions.

    //------------------------------------------------------------------------
    /// \brief List all communication ports
    ///
    /// That are (or might be) used by HW dive computers.
    virtual QStringList listPorts() const = 0;

    //------------------------------------------------------------------------
    /// \brief Send a command, wait ack, and retry on error.
    ///
    /// Service common to all current H&W dive computer: send a command byte,
    /// and wait it is dully acknowledged.
    /// Allow up to 10x retries when the computer does not answer anything,
    /// or reply something else.
    ///
    /// \param [in,out] serial: the connected port to use.
    /// \param [in]        cmd: command byte to send.
    /// \param [in]    retries: Optional max number of retries. Default to 10.
    ///
    /// \returns the ack byte (if any), or 0xFF if never received.
    static  unsigned char retryCommand(Serial& serial,
                                             unsigned char cmd,
                                             int retries = 10);

    //------------------------------------------------------------------------
    /// \brief Read and check connected dive computer identity.
    ///
    /// Read fw's version, serial number and custom text from connected computer.
    ///
    /// \throws when the connected device does not matches the driver
    /// implementation.
    ///
    /// \sa description(), firmware(), serialNumber() and customtext().
    virtual void getIdentity() = 0;

    //------------------------------------------------------------------------
    /// \brief The fw's version found during the last getIdentty().
    /// \sa getIDentity().
    virtual int firmware() const = 0;

    //------------------------------------------------------------------------
    /// \brief The serial number found during the last getIdentty().
    /// \sa getIDentity().
    virtual int serialNumber() const = 0;

    //------------------------------------------------------------------------
    /// \brief The user-defined string found during the last getIdentty().
    /// \sa getIDentity().
    virtual QString customText() const = 0;

    //------------------------------------------------------------------------
    /// \brief A human readable description of connected computer.
    ///
    /// Returns driver name, and identity data found during the last call to
    /// getIdentity().
    ///
    /// \sa model(), getIntentity()
    virtual QString description() = 0;

    /// \}
    //////////////////////////////////////////////////////////////////////////

protected:
    //------------------------------------------------------------------------
    /// \brief List serial ports for *Bluetooth* based devices.
    ///
    /// Ask *OS* for the list of *Bluetooth* serial emulations whose name
    /// matches the portTemplate() regular expression.
    ///
    QStringList listBluetoothPorts() const;

    //------------------------------------------------------------------------
    /// \brief List serial ports for USB based devices.
    ///
    /// Ask *OS* for the list of USB serial emulation currently connected whose name
    /// matches the portTemplate() regular expression.
    QStringList listUSBPorts() const;

};

#endif // COMPUTEROPERATIONS_H