Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. QStateMachine, detect unhandled signals/ transitions
Forum Updated to NodeBB v4.3 + New Features

QStateMachine, detect unhandled signals/ transitions

Scheduled Pinned Locked Moved Unsolved General and Desktop
6 Posts 2 Posters 597 Views 2 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • P Offline
    P Offline
    papadeltagolf
    wrote on last edited by
    #1

    Hello all, I'm using a QStateMachine with qsignaltransitions, which hooks into an existing, large set of signals.

    I'd like to be able to notify the user / log an error when the state machine receives a signal which doesn't correspond to a transition for the currently active state- kind of like a fall-through behaviour?

    A crude way of handling this would be for each state to have transitions to an error/ warning state for every signal transition it's not interested in- which feels wrong/ impractical.

    Any help appreciated.

    1 Reply Last reply
    0
    • SGaistS Offline
      SGaistS Offline
      SGaist
      Lifetime Qt Champion
      wrote on last edited by
      #2

      Hi and welcome to devnet,

      I would rather go with a subclass of QSignalTransition like show in the class documentation.

      Interested in AI ? www.idiap.ch
      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

      1 Reply Last reply
      0
      • P Offline
        P Offline
        papadeltagolf
        wrote on last edited by
        #3

        Thanks for the tip- I'll give that a go!
        Cheers

        1 Reply Last reply
        0
        • P Offline
          P Offline
          papadeltagolf
          wrote on last edited by
          #4

          Still struggling with this- I'm not sure I'm going about it the right way. I have tried subclassing QSignalTransition and overriding eventTest, where I can raise an error if the incoming signal is not handled. The problem is, the transition appears to only receive events that are relevant to it, rather than all signals- so it doesn't provide a single checkpoint against which I can capture an unhandled signal.
          Any further tips on how to achieve the original goal?

          1 Reply Last reply
          0
          • SGaistS Offline
            SGaistS Offline
            SGaist
            Lifetime Qt Champion
            wrote on last edited by
            #5

            Can you provide a minimal compilable example that demonstrate the situation you have ?

            Interested in AI ? www.idiap.ch
            Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

            1 Reply Last reply
            0
            • P Offline
              P Offline
              papadeltagolf
              wrote on last edited by
              #6

              Hi, thanks for the reply, here's some code to demonstrate the issue. Note, I expected the debug output from the eventTest() routine to get output when the signal fires but it doesn't. If I change the initial state I can get it to work, presumably because this determines which transitions are active.
              I believe I could achieve what I want by using a parent state and registering transitions on that, for every signal, but I was hoping there's a more elegant solution?
              Thanks

              "
              /****************************************************************************
              **
              ** Copyright (C) 2016 The Qt Company Ltd.
              ** Contact: https://www.qt.io/licensing/
              **
              ** This file is part of the QtCore module of the Qt Toolkit.
              **
              ** $QT_BEGIN_LICENSE:BSD$
              ** Commercial License Usage
              ** Licensees holding valid commercial Qt licenses may use this file in
              ** accordance with the commercial license agreement provided with the
              ** Software or, alternatively, in accordance with the terms contained in
              ** a written agreement between you and The Qt Company. For licensing terms
              ** and conditions see https://www.qt.io/terms-conditions. For further
              ** information use the contact form at https://www.qt.io/contact-us.
              **
              ** BSD License Usage
              ** Alternatively, you may use this file under the terms of the BSD license
              ** as follows:
              **
              ** "Redistribution and use in source and binary forms, with or without
              ** modification, are permitted provided that the following conditions are
              ** met:
              ** * Redistributions of source code must retain the above copyright
              ** notice, this list of conditions and the following disclaimer.
              ** * 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.
              ** * Neither the name of The Qt Company Ltd nor the names of its
              ** contributors may be used to endorse or promote products derived
              ** from this software without specific prior written permission.
              **
              **
              ** 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
              ** OWNER 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."
              **
              ** $QT_END_LICENSE$
              **
              ****************************************************************************/

              #include <QtCore>
              #include <stdio.h>
              #include <QStateMachine>
              #include <QThread>

              class QStatePlus: public QState
              {
              public:
              QStatePlus(QString name, QState *parent = 0)
              : QState(parent),m_name(name){}
              virtual void onEntry(QEvent *event) override {qDebug () << "Entering state " << m_name;}
              QElapsedTimer t;
              QString m_name;
              };

              class QTransitionPlus : public QSignalTransition
              {
              public:
              template <typename PMF>
              QTransitionPlus( const typename QtPrivate::FunctionPointer<PMF>::Object obj, PMF signal, const QString& name)
              : QSignalTransition(obj, signal),
              m_name(name){}
              protected:
              bool eventTest(QEvent e) {
              if (!QSignalTransition::eventTest(e))
              {
              if(e->type() == QEvent::StateMachineSignal)
              {
              QString statename;
              QStatePlus
              qsp = dynamic_cast<QStatePlus
              >(this->sourceState());
              if(qsp)
              {
              statename = qsp->m_name;
              }
              qDebug () << "XXX unhandled signal in state: " << statename << " " << "in transition" << m_name;
              }
              return false;
              }
              return true;
              }
              private:
              QString m_name;
              };

              class QStateMachinePlus: public QStateMachine
              {
              Q_OBJECT
              public:

              QStateMachinePlus(QObject *parent = 0)
                  : QStateMachine(parent){}
              

              // virtual bool event(QEvent *e) override {qDebug () << "XXX MACHINE event address " << QState::event(e); qDebug () << "accepted " << e->isAccepted(); return true; }

              void emitTest1To2(){qDebug() << "emit 1to2"; emit sig1To2();}
              void emitTest2To3(){qDebug() << "emit 2to3"; emit sig2To3();}
              void emitTest3To1(){qDebug() << "emit 3to1"; emit sig3To1();}
              

              signals:
              void sig1To2();
              void sig2To3();
              void sig3To1();
              void test();
              public slots:
              void handlesig2To3(){/qDebug() << "Got handlesig2To3";/}
              void handlesig1To2(){/qDebug() << "Got handlesig1To2";/}
              };

              //! [3]
              int main(int argc, char argv)
              {
              QTimer t1;
              QTimer t2;
              QCoreApplication app(argc, argv);
              QStateMachinePlus machine;
              QStatePlus
              s1 = new QStatePlus("s1");
              QStatePlus
              s2 = new QStatePlus("s2");
              QStatePlus* s3 = new QStatePlus("s3");
              machine.addState(s1);
              machine.addState(s2);
              machine.addState(s3);

              machine.setInitialState(s2);
              
              QTransitionPlus* trans1To2 = new QTransitionPlus(&machine, &QStateMachinePlus::sig1To2, "1 to 2");
              trans1To2->setTargetState(s2);
              QTransitionPlus* trans2To3 = new QTransitionPlus(&machine, &QStateMachinePlus::sig2To3, "2 to 3");
              trans2To3->setTargetState(s3);
              
              QTransitionPlus* trans3To1 = new QTransitionPlus(&machine, &QStateMachinePlus::sig3To1, "3 to 1");
              trans3To1 ->setTargetState(s1);
              
              s1->addTransition(trans1To2);
              s2->addTransition(trans2To3);
              s3->addTransition(trans3To1);
              
              machine.start();
              
              qDebug() <<"Start test";
              
              t1.setInterval(5000);
              QObject::connect(&t1, &QTimer::timeout, &machine, &QStateMachinePlus::emitTest1To2);
              //t1.setSingleShot(true);
              
              t1.start();
              

              // t2.setInterval(1000);
              // t2.setSingleShot(true);
              // QObject::connect(&t2, &QTimer::timeout, &machine, &QStateMachinePlus::emitTest1To2);
              // t2.start();

              return app.exec();
              

              }
              //! [6]

              #include "main.moc"
              "

              1 Reply Last reply
              0

              • Login

              • Login or register to search.
              • First post
                Last post
              0
              • Categories
              • Recent
              • Tags
              • Popular
              • Users
              • Groups
              • Search
              • Get Qt Extensions
              • Unsolved