From e55e84a80c0087f307d5ab5e8893bc3401175083 Mon Sep 17 00:00:00 2001
From: Raphael Grimm <raphael.grimm@kit.edu>
Date: Fri, 14 Dec 2018 09:48:03 +0100
Subject: [PATCH] Add verbosity and sensor value protocol options to
 BLEProthesisInterface

---
 .../BLEProthesisInterface.cpp                 |  16 ++-
 .../BLEProthesisInterface.h                   |  19 +++-
 .../BLEProthesisInterfaceQtWorker.cpp         | 104 ++++++++++++++++--
 .../BLEProthesisInterfaceQtWorker.h           |  11 +-
 ...KITProstheticHandDriverExampleNoArmarX.cpp |  14 ++-
 5 files changed, 137 insertions(+), 27 deletions(-)

diff --git a/source/RobotAPI/drivers/KITProstheticHandDriver/BLEProthesisInterface.cpp b/source/RobotAPI/drivers/KITProstheticHandDriver/BLEProthesisInterface.cpp
index 03112b769..e8c024398 100644
--- a/source/RobotAPI/drivers/KITProstheticHandDriver/BLEProthesisInterface.cpp
+++ b/source/RobotAPI/drivers/KITProstheticHandDriver/BLEProthesisInterface.cpp
@@ -3,8 +3,9 @@
 #include "BLEProthesisInterface.h"
 #include "BLEProthesisInterfaceQtWorkerThread.h"
 
-BLEProthesisInterface::BLEProthesisInterface(const std::string& mac) :
-    _worker{new BLEProthesisInterfaceQtWorkerThread{mac, *this}}
+BLEProthesisInterface::BLEProthesisInterface(const std::string& mac, SensorValueProtocol protocol) :
+    _worker{new BLEProthesisInterfaceQtWorkerThread{mac, *this}},
+        _protocol{protocol}
 {
     _worker->start();
 }
@@ -149,6 +150,17 @@ void BLEProthesisInterface::sendFingerPWM(uint64_t v, uint64_t mxPWM, uint64_t p
     str << 'M' << 3 << ',' << v << ',' << mxPWM << ',' << pos << '\n';
     sendRaw(str.str());
 }
+
+void BLEProthesisInterface::verboseReceive(bool b)
+{
+    _verboseReceive = b;
+}
+
+void BLEProthesisInterface::verboseSend(bool b)
+{
+    _verboseSend = b;
+}
+
 std::string to_string(BLEProthesisInterface::State s)
 {
     switch (s)
diff --git a/source/RobotAPI/drivers/KITProstheticHandDriver/BLEProthesisInterface.h b/source/RobotAPI/drivers/KITProstheticHandDriver/BLEProthesisInterface.h
index eb02ffbea..cf9651566 100644
--- a/source/RobotAPI/drivers/KITProstheticHandDriver/BLEProthesisInterface.h
+++ b/source/RobotAPI/drivers/KITProstheticHandDriver/BLEProthesisInterface.h
@@ -10,8 +10,6 @@ class BLEProthesisInterfaceQtWorker;
 class BLEProthesisInterface
 {
 public:
-    BLEProthesisInterface(const std::string& mac);
-    ~BLEProthesisInterface();
     enum class State
     {
         Created,
@@ -26,6 +24,15 @@ public:
         Running,
         Killed
     };
+    enum class SensorValueProtocol
+    {
+        tpos_tpwm_fpos_fpwm,
+        mx_pos_pwm
+    };
+public:
+    BLEProthesisInterface(const std::string& mac, SensorValueProtocol protocol = SensorValueProtocol::mx_pos_pwm);
+    ~BLEProthesisInterface();
+
     std::int64_t getThumbPWM() const;
     std::int64_t getThumbPos() const;
     std::int64_t getFingerPWM() const;
@@ -38,15 +45,23 @@ public:
     void sendGrasp(std::uint64_t n);
     void sendThumbPWM(std::uint64_t v, std::uint64_t maxPWM, std::uint64_t pos);
     void sendFingerPWM(std::uint64_t v, std::uint64_t maxPWM, std::uint64_t pos);
+
+    void verboseReceive(bool b = true);
+    void verboseSend(bool b = true);
 private:
     friend class BLEProthesisInterfaceQtWorker;
+    //sensor values
     std::atomic_int64_t _thumbPWM{0};
     std::atomic_int64_t _thumbPos{0};
     std::atomic_int64_t _fingerPWM{0};
     std::atomic_int64_t _fingerPos{0};
 
+    //management
     std::unique_ptr<BLEProthesisInterfaceQtWorkerThread> _worker;
     std::atomic<State> _state{State::Created};
+    std::atomic_bool _verboseReceive{false};
+    std::atomic_bool _verboseSend{true};
+    SensorValueProtocol _protocol;
 public:
     static constexpr std::uint64_t getMaxG()
     {
diff --git a/source/RobotAPI/drivers/KITProstheticHandDriver/BLEProthesisInterfaceQtWorker.cpp b/source/RobotAPI/drivers/KITProstheticHandDriver/BLEProthesisInterfaceQtWorker.cpp
index 0d00d3c52..adc9d2a80 100644
--- a/source/RobotAPI/drivers/KITProstheticHandDriver/BLEProthesisInterfaceQtWorker.cpp
+++ b/source/RobotAPI/drivers/KITProstheticHandDriver/BLEProthesisInterfaceQtWorker.cpp
@@ -1,5 +1,6 @@
 #include "BLEProthesisInterfaceQtWorker.h"
 
+#include <QRegularExpression>
 
 #define UARTSERVICEUUID "6e400001-b5a3-f393-e0a9-e50e24dcca9e"
 #define RXUUID "6e400002-b5a3-f393-e0a9-e50e24dcca9e"
@@ -161,7 +162,10 @@ void BLEProthesisInterfaceQtWorker::timerEvent(QTimerEvent*)
             QByteArray data;
             data.append(_cmd);
             _service->writeCharacteristic(RxChar, data, QLowEnergyService::WriteWithoutResponse);
-            qDebug() << '[' << _mac << ']' << " send: " << _cmd;
+            if (_owner->_verboseSend)
+            {
+                qDebug() << '[' << _mac << ']' << " send: " << _cmd;
+            }
             _cmd.clear();
         }
     }
@@ -301,23 +305,26 @@ void BLEProthesisInterfaceQtWorker::deviceDisconnected()
     _owner->_state = State::Disconnected;
 }
 
-void BLEProthesisInterfaceQtWorker::readData(const QLowEnergyCharacteristic& c, const QByteArray& value)
+
+template<>
+void BLEProthesisInterfaceQtWorker::consumeData<BLEProthesisInterface::SensorValueProtocol::tpos_tpwm_fpos_fpwm>()
 {
-    // ignore any other characteristic change
-    if (c.uuid() != QBluetoothUuid(QUuid(TXUUID)))
+    if (!_valueAkk.contains('\n'))
     {
+        if (_owner->_verboseReceive)
+        {
+            qDebug() << '[' << _mac << ']' << " data does not contain \\n -> no new sensor values\n Buffer:\n" << _valueAkk;
+        }
         return;
     }
-    //qDebug() << '[' << _mac << ']' << " received : " << value;
+    auto listPacks = _valueAkk.split('\n');
 
-    _valueAkk += QString{value};
-    if (!_valueAkk.contains('\n'))
+    if (_owner->_verboseReceive)
     {
-        return;
+        qDebug() << '[' << _mac << ']' << " parsing " << listPacks.at(listPacks.size() - 2);
     }
-    auto listPacks = _valueAkk.split('\n');
-    auto listVals = listPacks.at(listPacks.size() - 2).split(' ');
 
+    auto listVals = listPacks.at(listPacks.size() - 2).split(' ');
     _owner->_thumbPos = listVals.at(0).toLong();
     _owner->_thumbPWM = listVals.at(1).toLong();
     _owner->_fingerPos = listVals.at(2).toLong();
@@ -325,3 +332,80 @@ void BLEProthesisInterfaceQtWorker::readData(const QLowEnergyCharacteristic& c,
 
     _valueAkk = listPacks.back();
 }
+
+template<>
+void BLEProthesisInterfaceQtWorker::consumeData<BLEProthesisInterface::SensorValueProtocol::mx_pos_pwm>()
+{
+    if (!_valueAkk.contains('\n'))
+    {
+        if (_owner->_verboseReceive)
+        {
+            qDebug() << '[' << _mac << ']' << " data does not contain \\n -> no new sensor values\n Buffer:\n" << _valueAkk;
+        }
+        return;
+    }
+    auto listPacks = _valueAkk.split('\n');
+
+    static const QRegularExpression m2(R"(^M2:[ \t]+Pos.:[ \t]+(-?[1-9][0-9]*)[ \t]+PWM:[ \t]+(-?[1-9][0-9]*)[ \t]+$)");
+    static const QRegularExpression m3(R"(^M3:[ \t]+Pos.:[ \t]+(-?[1-9][0-9]*)[ \t]+PWM:[ \t]+(-?[1-9][0-9]*)[ \t]+$)");
+
+    for (int i  = 0; i < listPacks.size() - 1; ++i)
+    {
+        if (listPacks.at(i).size() == 0)
+        {
+            continue;
+        }
+        if (_owner->_verboseReceive)
+        {
+            qDebug() << '[' << _mac << ']' << " parsing " << listPacks.at(i);
+        }
+        if (const auto matchM2 = m2.match(listPacks.at(i)); matchM2.hasMatch())
+        {
+            _owner->_thumbPos = matchM2.captured(1).toLong();
+            _owner->_thumbPWM = matchM2.captured(2).toLong();
+            if (_owner->_verboseReceive)
+            {
+                qDebug() << '[' << _mac << ']' << " updated M2";
+            }
+        }
+        else if (const auto matchM3 = m3.match(listPacks.at(i)); matchM3.hasMatch())
+        {
+            _owner->_fingerPos = matchM3.captured(1).toLong();
+            _owner->_fingerPWM = matchM3.captured(2).toLong();
+            if (_owner->_verboseReceive)
+            {
+                qDebug() << '[' << _mac << ']' << " updated M3";
+            }
+        }
+        else
+        {
+            qWarning() << "unknown format for data: " << listPacks.at(i) << "\nSkipping";
+        }
+    }
+    _valueAkk = listPacks.back();
+}
+
+void BLEProthesisInterfaceQtWorker::readData(const QLowEnergyCharacteristic& c, const QByteArray& value)
+{
+    // ignore any other characteristic change
+    if (c.uuid() != QBluetoothUuid(QUuid(TXUUID)))
+    {
+        return;
+    }
+    if (_owner->_verboseReceive)
+    {
+        qDebug() << '[' << _mac << ']' << " received : " << value;
+    }
+
+    _valueAkk.append(value.data());
+
+    switch (_owner->_protocol)
+    {
+        case BLEProthesisInterface::SensorValueProtocol::tpos_tpwm_fpos_fpwm:
+            consumeData<BLEProthesisInterface::SensorValueProtocol::tpos_tpwm_fpos_fpwm>();
+            break;
+        case BLEProthesisInterface::SensorValueProtocol::mx_pos_pwm:
+            consumeData<BLEProthesisInterface::SensorValueProtocol::mx_pos_pwm>();
+            break;
+    }
+}
diff --git a/source/RobotAPI/drivers/KITProstheticHandDriver/BLEProthesisInterfaceQtWorker.h b/source/RobotAPI/drivers/KITProstheticHandDriver/BLEProthesisInterfaceQtWorker.h
index f4b84d716..ce14c53a2 100644
--- a/source/RobotAPI/drivers/KITProstheticHandDriver/BLEProthesisInterfaceQtWorker.h
+++ b/source/RobotAPI/drivers/KITProstheticHandDriver/BLEProthesisInterfaceQtWorker.h
@@ -45,7 +45,8 @@ private slots:
     void serviceStateChanged(QLowEnergyService::ServiceState s);
     void readData(const QLowEnergyCharacteristic& c, const QByteArray& value);
 private:
-    //    friend class BLEProthesisInterface;
+    template<BLEProthesisInterface::SensorValueProtocol P> void consumeData();
+
     BLEProthesisInterface*              _owner;
     QString                             _mac;
 
@@ -53,14 +54,6 @@ private:
     int                                 _timer{-1};
     std::atomic_bool                    _killed{false};
 
-    enum class SensorValue
-    {
-        ThumbPWM  = 0,
-        ThumbPos  = 1,
-        FingerPWM = 2,
-        FingerPos = 3
-    };
-    SensorValue                         _nextSensorValue{SensorValue::ThumbPos};
     QString                             _valueAkk;
 
     QString                             _cmd;
diff --git a/source/RobotAPI/drivers/KITProstheticHandDriver/example/KITProstheticHandDriverExampleNoArmarX.cpp b/source/RobotAPI/drivers/KITProstheticHandDriver/example/KITProstheticHandDriverExampleNoArmarX.cpp
index 7bd337ded..3b04f047f 100644
--- a/source/RobotAPI/drivers/KITProstheticHandDriver/example/KITProstheticHandDriverExampleNoArmarX.cpp
+++ b/source/RobotAPI/drivers/KITProstheticHandDriver/example/KITProstheticHandDriverExampleNoArmarX.cpp
@@ -5,11 +5,17 @@
 #include <iostream>
 #include <thread>
 
+[[maybe_unused]] static constexpr auto old    = "DF:70:E8:81:DB:D6";
+[[maybe_unused]] static constexpr auto dlr    = "DF:A2:F5:48:E7:50";
+[[maybe_unused]] static constexpr auto arches = "XX:XX:XX:XX:XX:XX";
+
 int main(int argc, char* argv[])
 {
     QCoreApplication a(argc, argv);
     {
-        BLEProthesisInterface iface{"DF:70:E8:81:DB:D6"};
+        BLEProthesisInterface iface{dlr};
+        iface.verboseReceive(false);
+        iface.verboseSend(true);
         std::size_t dcCounter = 0;
         while (iface.getState() != BLEProthesisInterface::State::Running)
         {
@@ -28,9 +34,9 @@ int main(int argc, char* argv[])
             std::this_thread::sleep_for(std::chrono::milliseconds{100});
         }
 
-        auto printAndSleep = [&]
+        auto printAndSleep = [&](std::size_t n = 25)
         {
-            for (std::size_t i2 = 0; i2 < 25; ++i2)
+            for (std::size_t i2 = 0; i2 < n; ++i2)
             {
                 std::cout << iface.getThumbPos() << "\t"
                           << iface.getThumbPWM() << "\t"
@@ -46,7 +52,7 @@ int main(int argc, char* argv[])
             printAndSleep();
         }
         iface.sendThumbPWM(200, 2999, 0);
-        printAndSleep();
+        printAndSleep(1);
         iface.sendFingerPWM(200, 2999, 0);
         printAndSleep();
     }
-- 
GitLab