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. Problems with QNetwork | QNetworkAccessManager
Qt 6.11 is out! See what's new in the release blog

Problems with QNetwork | QNetworkAccessManager

Scheduled Pinned Locked Moved Solved General and Desktop
34 Posts 4 Posters 14.7k 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.
  • K Offline
    K Offline
    Kris Revi
    wrote on last edited by Kris Revi
    #1

    i understand that QNetworkAccessManager is only calling handleResponse() when the request is finished so that presents a problem for self.xBoard = value["Name"] as when the request is finished the last entry in the array was "Små Sure" so that is what it will be set to :/ but how to fix it?

            self.xBoard = ""
            self.nam = QtNetwork.QNetworkAccessManager()
            self.nam.connect(self.handleResponse)
    
        def doRequest(self):
            print("Run")
            print("#----------------------------------#")
            for key, value in self.board.items():
                url = "http://" + value["ip"]
                self.xBoard = value["Name"]
    
                print("doRequests : " + self.xBoard)
                print("http://" + value["ip"])
    
                req = QtNetwork.QNetworkRequest(QUrl(url))
                self.nam.get(req)
    
        def handleResponse(self, reply):
            er = reply.error()
    
            if er == QtNetwork.QNetworkReply.NoError:
                bytes_string = reply.readAll()
    
                print("")
                print("#----------------------------------#")
                print("Result")
                print("#----------------------------------#")
                print(str(bytes_string, 'utf-8'))
                print("handleResponse : " + self.xBoard)
    
                self.board[self.xBoard]['Status'] = "Online"
            else:
                print("Error occured: ", er)
                print(reply.errorString())
    
                self.board[self.xBoard]['Status'] = "Offline"
    
    1 Reply Last reply
    0
    • SGaistS Offline
      SGaistS Offline
      SGaist
      Lifetime Qt Champion
      wrote on last edited by
      #2

      Hi,

      Don't use such a fixed variable for something that is dynamic like that. Either use the QNetworkReply returned by QNetworkAccessManager::get as a key to get the correct board name in the finished handler. Or set a dynamic proper on that reply object so you can grab back that information again when the request is finished.

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

      K 1 Reply Last reply
      0
      • SGaistS SGaist

        Hi,

        Don't use such a fixed variable for something that is dynamic like that. Either use the QNetworkReply returned by QNetworkAccessManager::get as a key to get the correct board name in the finished handler. Or set a dynamic proper on that reply object so you can grab back that information again when the request is finished.

        K Offline
        K Offline
        Kris Revi
        wrote on last edited by
        #3

        @SGaist im not an expert far from it! More like a beginner. Can you show me how?

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

          Use setProperty/getProperty on your reply object to store the board name associated with the request.

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

          K 1 Reply Last reply
          1
          • SGaistS SGaist

            Use setProperty/getProperty on your reply object to store the board name associated with the request.

            K Offline
            K Offline
            Kris Revi
            wrote on last edited by
            #5

            @SGaist set and get in the reply you say?

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

              Get the reply object returned by your QNAM instance, call the setProperty method. And in your slot, call the getProperty method on the reply object you get as parameter.

              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
              1
              • K Offline
                K Offline
                Kris Revi
                wrote on last edited by Kris Revi
                #7

                got it fixed! but why is QNetworkReply only replying once?

                # Run 1
                #----------------------------------#
                doRequests : http://192.168.10.138
                doRequests : http://192.168.10.146
                doRequests : http://192.168.10.184
                doRequests : http://192.168.10.2
                
                #----------------------------------#
                # Result
                #----------------------------------#
                handleResponse : hello world!
                Små Sure : Online
                handleResponse : hello world!
                Studio Lights : Online
                
                # Run 2
                #----------------------------------#
                doRequests : http://192.168.10.138
                doRequests : http://192.168.10.146
                doRequests : http://192.168.10.184
                doRequests : http://192.168.10.2
                
                # Run 3
                #----------------------------------#
                doRequests : http://192.168.10.138
                doRequests : http://192.168.10.146
                doRequests : http://192.168.10.184
                doRequests : http://192.168.10.2
                
                #Run 4
                #----------------------------------#
                doRequests : http://192.168.10.138
                doRequests : http://192.168.10.146
                doRequests : http://192.168.10.184
                doRequests : http://192.168.10.2
                
                #Run 5
                #----------------------------------#
                doRequests : http://192.168.10.138
                doRequests : http://192.168.10.146
                doRequests : http://192.168.10.184
                doRequests : http://192.168.10.2
                
                #Run 6
                #----------------------------------#
                doRequests : http://192.168.10.138
                doRequests : http://192.168.10.146
                doRequests : http://192.168.10.184
                doRequests : http://192.168.10.2
                
                # Run 7
                #----------------------------------#
                doRequests : http://192.168.10.138
                doRequests : http://192.168.10.146
                doRequests : http://192.168.10.184
                doRequests : http://192.168.10.2
                
                # Run 8
                #----------------------------------#
                doRequests : http://192.168.10.138
                doRequests : http://192.168.10.146
                doRequests : http://192.168.10.184
                doRequests : http://192.168.10.2
                
                # Run 9
                #----------------------------------#
                doRequests : http://192.168.10.138
                doRequests : http://192.168.10.146
                doRequests : http://192.168.10.184
                doRequests : http://192.168.10.2
                

                is there something i need todo?

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

                  Since you did not post the whole code related to QNAM you are using, I can't answer.

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

                  K 1 Reply Last reply
                  0
                  • SGaistS SGaist

                    Since you did not post the whole code related to QNAM you are using, I can't answer.

                    K Offline
                    K Offline
                    Kris Revi
                    wrote on last edited by
                    #9

                    @SGaist huh? the whole code is posted above?

                    @Kris-Revi said in Problems with QNetwork | QNetworkAccessManager:

                    i understand that QNetworkAccessManager is only calling handleResponse() when the request is finished so that presents a problem for self.xBoard = value["Name"] as when the request is finished the last entry in the array was "Små Sure" so that is what it will be set to :/ but how to fix it?

                            self.xBoard = ""
                            self.nam = QtNetwork.QNetworkAccessManager()
                            self.nam.connect(self.handleResponse)
                    
                        def doRequest(self):
                            print("Run")
                            print("#----------------------------------#")
                            for key, value in self.board.items():
                                url = "http://" + value["ip"]
                                self.xBoard = value["Name"]
                    
                                print("doRequests : " + self.xBoard)
                                print("http://" + value["ip"])
                    
                                req = QtNetwork.QNetworkRequest(QUrl(url))
                                self.nam.get(req)
                    
                        def handleResponse(self, reply):
                            er = reply.error()
                    
                            if er == QtNetwork.QNetworkReply.NoError:
                                bytes_string = reply.readAll()
                    
                                print("")
                                print("#----------------------------------#")
                                print("Result")
                                print("#----------------------------------#")
                                print(str(bytes_string, 'utf-8'))
                                print("handleResponse : " + self.xBoard)
                    
                                self.board[self.xBoard]['Status'] = "Online"
                            else:
                                print("Error occured: ", er)
                                print(reply.errorString())
                    
                                self.board[self.xBoard]['Status'] = "Offline"
                    
                    1 Reply Last reply
                    0
                    • SGaistS Offline
                      SGaistS Offline
                      SGaist
                      Lifetime Qt Champion
                      wrote on last edited by
                      #10

                      It's incomplete. You have methods belonging to some class since they have self as first parameters and code that is just indented which may or may not belong to said class.

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

                      K 1 Reply Last reply
                      0
                      • SGaistS SGaist

                        It's incomplete. You have methods belonging to some class since they have self as first parameters and code that is just indented which may or may not belong to said class.

                        K Offline
                        K Offline
                        Kris Revi
                        wrote on last edited by Kris Revi
                        #11

                        @SGaist This is everything used

                        class software(QtWidgets.QMainWindow):
                               
                                   def __init__(self, parent=None):
                               
                                       QtWidgets.QWidget.__init__(self, parent)
                               
                                       self.ui = Ui_MainWindow()
                               
                                       self.ui.setupUi(self)
                               
                               
                               
                                       # Set Gui to run fullscreen
                               
                                       #self.showFullScreen()
                               
                               
                               
                                       # Show the default Frame on first "boot"
                               
                                       self.ui.DefaultFrame.raise_()
                               
                               
                               
                                       # Set the Brightnesssliders min and max
                               
                                       self.ui.Brightnessslider.setMinimum(0)
                               
                                       self.ui.Brightnessslider.setMaximum(255)
                               
                               
                               
                                       # Convert the ranges of each slider
                               
                                       self.ui.Brightnessslider.valueChanged['int'].connect(lambda: self.convertRange("brightness"))
                               
                                       self.ui.patternSpeedSlider.valueChanged['int'].connect(lambda: self.convertRange("speed"))
                               
                                       self.ui.patternSpacingSlider.valueChanged['int'].connect(lambda: self.convertRange("spacing"))
                               
                                       self.ui.colorSaturationSlider.valueChanged['int'].connect(lambda: self.convertRange("saturation"))
                               
                               
                               
                                       # Hook each slider up to its function
                               
                                       self.ui.Brightnessslider.valueChanged.connect(self.adjustBrightness)
                               
                                       self.ui.patternSpeedSlider.valueChanged.connect(self.adjustDelay)
                               
                                       self.ui.patternSpacingSlider.valueChanged.connect(self.adjustSpacing)
                               
                                       self.ui.colorHueSlider.valueChanged.connect(self.Hue)
                               
                                       self.ui.colorSaturationSlider.valueChanged.connect(self.Sat)
                               
                               
                               
                                       # Hook each Color Button up to its function
                               
                                       self.ui.colorRedButton.clicked.connect(lambda: self.buttonSetHue("Red"))
                               
                                       self.ui.colorOrangeButton.clicked.connect(lambda: self.buttonSetHue("Orange"))
                               
                                       self.ui.colorYellowButton.clicked.connect(lambda: self.buttonSetHue("Yellow"))
                               
                                       self.ui.colorGreenButton.clicked.connect(lambda: self.buttonSetHue("Green"))
                               
                                       self.ui.colorAquaButton.clicked.connect(lambda: self.buttonSetHue("Aqua"))
                               
                                       self.ui.colorBlueButton.clicked.connect(lambda: self.buttonSetHue("Blue"))
                               
                                       self.ui.colorPurpleButton.clicked.connect(lambda: self.buttonSetHue("Purple"))
                               
                                       self.ui.colorPinkButton.clicked.connect(lambda: self.buttonSetHue("Pink"))
                               
                               
                               
                                       # Hook each pattern Button up to its function
                               
                                       self.ui.patternSolidcolorButton.clicked.connect(lambda: self.selectPattern("SOLIDCOLOR"))
                               
                                       self.ui.patternRainbowButton.clicked.connect(lambda: self.selectPattern("RAINBOW"))
                               
                                       self.ui.patternTheaterchaseButton.clicked.connect(lambda: self.selectPattern("THEATERCHASE"))
                               
                                       self.ui.patternJuggleButton.clicked.connect(lambda: self.selectPattern("JUGGLE"))
                               
                                       self.ui.patternRunninglightButton.clicked.connect(lambda: self.selectPattern("RUNNINGLIGHT"))
                               
                                       self.ui.patternCylonButton.clicked.connect(lambda: self.selectPattern("CYLON"))
                               
                                       self.ui.patternMitosisButton.clicked.connect(lambda: self.selectPattern("MITOSIS"))
                               
                                       self.ui.SS_patternTheaterChaseButton.clicked.connect(lambda: self.selectPattern("SS_THEATERCHASE"))
                               
                                       self.ui.SS_patternCylonButton.clicked.connect(lambda: self.selectPattern("SS_CYLON"))
                               
                               
                               
                                       # Hook UV Button to its function
                               
                                       self.ui.uvlightsButton.clicked.connect(self.toggleUV)
                               
                               
                               
                                       # Hook each Board Button up to its function
                               
                                       self.ui.studioLightsButton.clicked.connect(lambda: self.setSelectedBoard("Studio Lights"))
                               
                                       self.ui.neonHeavenButton.clicked.connect(lambda: self.setSelectedBoard("Neon Heaven"))
                               
                                       self.ui.vitrineskapButton.clicked.connect(lambda: self.setSelectedBoard("Vitrineskap"))
                               
                                       self.ui.smSureButton.clicked.connect(lambda: self.setSelectedBoard("Små Sure"))
                               
                               
                               
                                       # Hidee UV Light Frame
                               
                                       self.ui.UVLightsframe.setVisible(False)
                               
                               
                               
                                       # Button array for the Pattern Buttons
                               
                                       self.buttons = [self.ui.patternSolidcolorButton,
                               
                                                       self.ui.patternRainbowButton,
                               
                                                       self.ui.patternTheaterchaseButton,
                               
                                                       self.ui.patternJuggleButton,
                               
                                                       self.ui.patternRunninglightButton,
                               
                                                       self.ui.patternCylonButton,
                               
                                                       self.ui.patternMitosisButton]
                               
                               
                               
                                       # Set Globals
                               
                                       global lastbutton
                               
                                       global spotifyFetch
                               
                                       global switchstate
                               
                               
                               
                                       self.selectedBoard = None
                               
                                       self.boardURL = None
                               
                                       self.switchstate = False
                               
                                       self.switchLabel = "OFF"
                               
                                       self.spotifyFetch = False
                               
                                       self.lastbutton = None
                               
                                       self.cssButton = ""
                               
                                       self.lastStyleButton = None
                               
                                       self.TempSpotify = ""
                               
                                       self.MatrixOnline = False
                               
                                       self.ESPOnline = False
                               
                                       self.RunOnce = False
                               
                                       self.nam = QtNetwork.QNetworkAccessManager()
                               
                                       self.nam.finished.connect(self.handleResponse)
                               
                               
                               
                                       # Board array for all the boards this software can controll
                               
                                       self.board = {
                               
                                           "Studio Lights": {'Name': "Studio Lights", 'UVVisible': False, 'ip': "192.168.10.138", 'Status': "Offline"},
                               
                                           "Neon Heaven": {'Name': "Neon Heaven", 'UVVisible': True, 'ip': "192.168.10.146", 'Status': "Offline"},
                               
                                           "Vitrineskap": {'Name': "Vitrineskap", 'UVVisible': False, 'ip': "192.168.10.184", 'Status': "Offline"},
                               
                                           "Små Sure": {'Name': "Små Sure", 'UVVisible': False, 'ip': "192.168.10.2", 'Status': "Offline"},
                               
                                       }
                               
                               
                               
                                       # Pattern array
                               
                                       self.pattern = {
                               
                                           "SOLIDCOLOR": {'hightlightButton': [1, "patternSolidcolorButton"], 'setDefaults': [0, 2], 'disableFeatures': [True, False, False, True, True, True, True], 'selectedPattern': 1},
                               
                                           "RAINBOW": {'hightlightButton': [2, "patternRainbowButton"], 'setDefaults': [25, 2], 'disableFeatures': [True, True, False, False, False, False, True], 'selectedPattern': 2},
                               
                                           "THEATERCHASE": {'hightlightButton': [3, "patternTheaterchaseButton"], 'setDefaults': [127, 3], 'disableFeatures': [True, True, True, True, True, True, True], 'selectedPattern': 3},
                               
                                           "JUGGLE": {'hightlightButton': [4, "patternJuggleButton"], 'setDefaults': [0, 2], 'disableFeatures': [True, False, False, False, False, False, True], 'selectedPattern': 4},
                               
                                           "RUNNINGLIGHT": {'hightlightButton': [5, "patternRunninglightButton"], 'setDefaults': [25, 10], 'disableFeatures': [True, True, True, True, True, True, True], 'selectedPattern': 5},
                               
                                           "CYLON": {'hightlightButton': [6, "patternCylonButton"], 'setDefaults': [50, 2], 'disableFeatures': [True, True, True, True, True, True, True], 'selectedPattern': 6},
                               
                                           "MITOSIS": {'hightlightButton': [7, "patternMitosisButton"], 'setDefaults': [50, 199], 'disableFeatures': [True, True, True, True, True, True, True], 'selectedPattern': 7},
                               
                                           "SS_THEATERCHASE": {'selectedPattern': 2},
                               
                                           "SS_CYLON": {'selectedPattern': 3},
                               
                                       }
                               
                               
                               
                                       # Hue array
                               
                                       self.hue = {
                               
                                           "Red": {'hue': 0},
                               
                                           "Orange": {'hue': 32},
                               
                                           "Yellow": {'hue': 64},
                               
                                           "Green": {'hue': 96},
                               
                                           "Aqua": {'hue': 128},
                               
                                           "Blue": {'hue': 160},
                               
                                           "Purple": {'hue': 192},
                               
                                           "Pink": {'hue': 224},
                               
                                       }
                               
                               # --- THREAD -------------------------------------------------------------------------------------------------------- #
                               
                                       def Thread_Functions():
                               
                                           threading.Timer(1.0, Thread_Functions).start()
                               
                                           self.doRequest()
                               
                                       Thread_Functions()
                               
                               
                               
                               # --- PING ---------------------------------------------------------------------------------------------------------- #
                               
                                   def doRequest(self):
                               
                                       print("Run")
                               
                                       print("#----------------------------------#")
                               
                                       for key, value in self.board.items():
                               
                                           url = "http://" + value["ip"]
                               
                                           print("doRequests : http://" + value["ip"])
                               
                               
                               
                                           req = QtNetwork.QNetworkRequest(QUrl(url))
                               
                                           self.nam.get(req)
                               
                               
                               
                                   def handleResponse(self, reply):
                               
                                       er = reply.error()
                               
                               
                               
                                       replyURL = reply.url().url().replace("http://", "")
                               
                               
                               
                                       if er == QtNetwork.QNetworkReply.NoError:
                               
                                           bytes_string = reply.readAll()
                               
                               
                               
                                           print("")
                               
                                           print("#----------------------------------#")
                               
                                           print("Result")
                               
                                           print("#----------------------------------#")
                               
                                           print("handleResponse : " + str(bytes_string, 'utf-8'))
                               
                               
                               
                                           if replyURL == "192.168.10.138":
                               
                                               self.board["Studio Lights"]['Status'] = "Online"
                               
                                               print("Studio Lights : Online")
                               
                               
                               
                                           if replyURL == "192.168.10.146":
                               
                                               self.board["Neon Heaven"]['Status'] = "Online"
                               
                                               print("Neon Heaven : Online")
                               
                               
                               
                                           if replyURL == "192.168.10.184":
                               
                                               self.board["Vitrineskap"]['Status'] = "Online"
                               
                                               print("Vitrineskap : Online")
                               
                               
                               
                                           if replyURL == "192.168.10.2":
                               
                                               self.board["Små Sure"]['Status'] = "Online"
                               
                                               print("Små Sure : Online")
                               
                                       else:
                               
                                           print("Error occured: ", er)
                               
                                           print(reply.errorString())
                               
                               
                               
                                           if replyURL == "192.168.10.138":
                               
                                               self.board["Studio Lights"]['Status'] = "Offline"
                               
                                               print("Studio Lights : Offline")
                               
                               
                               
                                           if replyURL == "192.168.10.146":
                               
                                               self.board["Neon Heaven"]['Status'] = "Offline"
                               
                                               print("Neon Heaven : Offline")
                               
                               
                               
                                           if replyURL == "192.168.10.184":
                               
                                               self.board["Vitrineskap"]['Status'] = "Offline"
                               
                                               print("Vitrineskap : Offline")
                               
                               
                               
                                           if replyURL == "192.168.10.2":
                               
                                               self.board["Små Sure"]['Status'] = "Offline"
                               
                                               print("Små Sure : Offline")
                        
                        if __name__ == '__main__':
                           app = QtWidgets.QApplication(sys.argv)
                        
                           myapp = software()
                           myapp.show()
                           sys.exit(app.exec_())
                        1 Reply Last reply
                        0
                        • SGaistS Offline
                          SGaistS Offline
                          SGaist
                          Lifetime Qt Champion
                          wrote on last edited by
                          #12

                          It still is not complete for the reasons I stated before.

                          How fast are you generating these requests ?

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

                          K 1 Reply Last reply
                          0
                          • SGaistS SGaist

                            It still is not complete for the reasons I stated before.

                            How fast are you generating these requests ?

                            K Offline
                            K Offline
                            Kris Revi
                            wrote on last edited by
                            #13

                            @SGaist updated the code above... that is the entire code!

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

                              Why are you using threads ?
                              QNAM is asynchronous so there's currently no need for threads especially in the first stage of development like that.

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

                              K 1 Reply Last reply
                              1
                              • SGaistS SGaist

                                Why are you using threads ?
                                QNAM is asynchronous so there's currently no need for threads especially in the first stage of development like that.

                                K Offline
                                K Offline
                                Kris Revi
                                wrote on last edited by
                                #15

                                @SGaist the reason for using threading is because i need to check constantly if the board im controlling is online or not. without threading QNAM only runs once

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

                                  Use a QTimer to trigger sending your ping requests at regular intervals.

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

                                  K 2 Replies Last reply
                                  1
                                  • SGaistS SGaist

                                    Use a QTimer to trigger sending your ping requests at regular intervals.

                                    K Offline
                                    K Offline
                                    Kris Revi
                                    wrote on last edited by
                                    #17

                                    @SGaist what the..... QTimer fixed it... ok i need to read about QTimer!

                                    1 Reply Last reply
                                    0
                                    • SGaistS SGaist

                                      Use a QTimer to trigger sending your ping requests at regular intervals.

                                      K Offline
                                      K Offline
                                      Kris Revi
                                      wrote on last edited by
                                      #18

                                      @SGaist but yea still having the problem that the QNetworkReply does not give any error or output on boards that are offfline :S

                                              else:
                                                  print("Error occured: ", er)
                                                  print(reply.errorString())
                                      
                                      1 Reply Last reply
                                      0
                                      • K Offline
                                        K Offline
                                        Kris Revi
                                        wrote on last edited by
                                        #19

                                        i dont understand why it doesn't give error not even (timeouterror)

                                        1 Reply Last reply
                                        0
                                        • K Offline
                                          K Offline
                                          Kris Revi
                                          wrote on last edited by
                                          #20

                                          anyone who can help?

                                          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