10 Replies Latest reply on Mar 9, 2018 7:17 PM by Rick Davin

    Connecting to a channel w/ Python

    dpanseri

      I'm attempting to connect to a channel via python using the websocket-client library (see: GitHub - websocket-client/websocket-client: websocket client for python ). I've got a basic script that attempts to connect to a channel. When I do I keep getting 400 Bad Request responses. My code is below, any assistance is greatly appreciated. Note I've edited out the web ID from my system. Assume they are correct.

       

      import websocket
      import ssl
      
      try:
          import thread
      except ImportError:
          import _thread as thread
      import time
      
      def on_message(ws, message):
          print(message)
      
      def on_error(ws, error):
          print(error)
      
      def on_close(ws):
          print("### closed ###")
      
      def on_open(ws):
          print("Open")
          def run(*args):
              for i in range(3):
                  time.sleep(1)
                  #ws.send("Hello %d" % i)
              time.sleep(1)
              ws.close()
              print("thread terminating...")
          thread.start_new_thread(run, ())
      
      if __name__ == "__main__":
          webid = "" #real web ID omitted assume it's valid
          options = ""
          uri = "wss://piserver1/piwebapi/streams/" + webid + "/channel" + options
          websocket.enableTrace(True)
          ws = websocket.WebSocketApp(uri,
                                    on_message = on_message,
                                    on_error = on_error,
                                    on_close = on_close)
      
          ws.on_open = on_open
          ws.run_forever(sslopt={"cert_reqs": ssl.VERIFY_DEFAULT})
      

       

      Output:

      --- request header ---

      GET /piwebapi/streams/*webid omitted*/channel HTTP/1.1

      Upgrade: websocket

      Connection: Upgrade

      Host: piserver1

      Origin: http://piserver1

      Sec-WebSocket-Key: qNBHhTQqaWPOdKun45dlDg==

      Sec-WebSocket-Version: 13

       

      -----------------------

      --- response header ---

      HTTP/1.1 400 Bad Request

      Transfer-Encoding: chunked

      Content-Type: application/json; charset=utf-8

      Server: Microsoft-HTTPAPI/2.0

      X-Frame-Options: SAMEORIGIN

      Date: Wed, 07 Mar 2018 16:36:58 GMT

      -----------------------

      Handshake status 400 Bad Request

       

      Message was edited by: Rick Davin to add Python Syntax Highlighting

        • Re: Connecting to a channel w/ Python
          tramachandran

          I assume you have tested the code against example URI such as "wss://echo.websocket.org".

          You can check the debug logs from PI Web API when attempting use Channels and provide us with a redacted version.

          Logs are written to the Event Viewer: PIWebAPI, In the Windows Event Log choose View -> Show Analytic and Debug Logs and Right-click an analytic or debug log and Enable Log (if not previously enabled).

           

          In the PI Web API documentation we have JS & C# client samples that can be used to quickly check potential causes.

          • Re: Connecting to a channel w/ Python
            dpanseri

            I have tested it with the echo site. Works fine with that, but when I point it at the PI server, I get a bad request response. I also tried wscat (GitHub - websockets/wscat: WebSocket cat ) to connect to the server and got the same error.

            • Re: Connecting to a channel w/ Python
              dpanseri

              Here are my PI Web API options for reference:

               

              {

                "AuthenticationMethods": [

                "Anonymous",

                "Basic",

                "Kerberos"

                ],

                "CorsExposedHeaders": "Allow,Content-Encoding,Content-Length,Date,Location",

                "CorsHeaders": "Accept,content-type,requestverificationtoken,x-requested-with",

                "CorsMethods": "GET,OPTIONS,POST",

                "CorsOrigins": "https://piserver1,https://piserver1.,https://piserver1.bt.pi",

                "CorsSupportsCredentials": true,

                "DebugMode": true,

                "DisableWrites": false,

                "EnableCSRFDefense": true,

                "SearchBoosts": [

                1.0,

                0.8,

                0.5,

                0.5,

                0.5,

                0.5,

                0.5

                ],

                "SearchPointAttributes": [

                "pointsource",

                "instrumenttag",

                "location1",

                "exdesc"

                ],

                "SearchScanInterval": 180,

                "WebIDType": "Full",

                "XFrameOptions": "SAMEORIGIN"

              }

              • Re: Connecting to a channel w/ Python
                dpanseri

                Yes, I just swapped out the URL in the program and it connected fine. I'm not seeing anything of note in the debug log. I've run it on the local machine and on a remote machine with the same result.

                  • Re: Connecting to a channel w/ Python
                    Marcos Vainer Loeff

                    Hi David,

                     

                    My suggestion is to try using "Anonymous" as the only authentication method. Delete Kerberos and Basic authentication using PI System Explorer for testing purposes.

                     

                    Please let us know the result.

                      • Re: Connecting to a channel w/ Python
                        dpanseri

                        I did that and am still getting the same response from the server. Config is now as follows:

                         

                        {
                             "AuthenticationMethods": [
                                  "Anonymous"
                             ],
                             "CorsExposedHeaders": "Allow,Content-Encoding,Content-Length,Date,Location",
                             "CorsHeaders": "Accept,content-type,requestverificationtoken,x-requested-with",
                             "CorsMethods": "GET,OPTIONS,POST",
                             "CorsOrigins": "https://piserver1,https://piserver1.,https://piserver1.bt.pi",
                             "CorsSupportsCredentials": true,
                             "DebugMode": true,
                             "DisableWrites": false,
                             "EnableCSRFDefense": true,
                             "SearchBoosts": [
                                  1.0,
                                  0.8,
                                  0.5,
                                  0.5,
                                  0.5,
                                  0.5,
                                  0.5
                             ],
                             "SearchPointAttributes": [
                                  "pointsource",
                                  "instrumenttag",
                                  "location1",
                                  "exdesc"
                             ],
                             "SearchScanInterval": 180,
                             "WebIDType": "Full",
                             "XFrameOptions": "SAMEORIGIN"
                        }
                        
                    • Re: Connecting to a channel w/ Python
                      dpanseri

                      It turns out it was a Windows issue all along. The PI Web API was installed on Windows Server 2008 R2 and Web Sockets aren't supported at all in that version of Windows. I spun up a new Windows Server 2012 machine just to host the Web API and it worked fine after that.

                      3 of 3 people found this helpful