1 Reply Latest reply on Jan 13, 2018 9:14 PM by tzuge RSS
    tzuge Newbie

    .NET Edge SDK seems to have static state

    I am trying to provide a UI to allow users to configure and connect to ThingWorx via a component that uses the .NET Edge SDK. However, I have encountered a number of issues with the .NET Edge SDK (version, and some seem to suggest there is static state in the API.


    I attached a test application which is based on the SteamSensor sample included with the SDK. In order to let the user change the ThingWorx connection settings, and reconnect, I am creating a new instance of a SteamSensorClient with the new configuration whenever they 'Connect'. However, some static state in the SDK seems to affect behavior across these instances.


    1. Using disconnect(string reason) method, new instances of SteamSensorClient can connect with a bad URI (probably application key as well) - Start the test application, enter good settings, and Connect. Then Disconnect (not Shutdown), change the URI to be incorrect, and click Connect. The brand new SteamSensorClient seems to be able to connect even though the incorrect URI is passed into the constructor. This does not seem to be the case when using the shutdown() method instead (try Shutdown from the test application).
    2. Connecting to the incorrect URI seems to put the SDK into a bad state, and recovery is a problem - Start the test application, enter a URI with a slight mistake (still correct format, but not pointed to the real endpoint), and Connect. For me, this takes > 1 min before failing. Now correct the URI, and try to connect. This does not seem to work even though it's a new instance of SteamSensorClient with the good URI. Open another instance of the test application, and enter the same good settings in, and connect. This should work, verifying that the settings themselves are good. Unlike #1, this problem seems to apply with shutdown() as well as disconnect().
    3. On a slight tangent, the ConnectRetries and ConnectTimeout settings do not seem to be consistent with the actual behavior when Connecting. The code documentation indicates ConnectTimeout should be in milliseconds, but in practice I am seeing much longer times to fail. Also a ConnectRetries value of 0 seems to mean it won't connect (perhaps it is actually 'Tries' and not 'Retries'?)
    4. Is there a way to abort the connection request? The test application permits calling of disconnect() and shutdown() during the connecting state. Start the test app, enter incorrect URI, connect. While it is in the 'Connecting' state (thread is blocked in the start() method), press Disconnect/Shutdown. The methods return, but do not abort the connecting state. Is there a way to do this?
    5. Should I be using one instance of SteamSensorClient and changing the settings instead somehow? Or is my use case not supported at all, and the process loading the SDK isn't expected to change settings and try to connect again?



    Regarding #4, I found the BaseClient.stopConnectionAttempt(), but after trying it, it does not seem to actually stops the connection attempt. It returns, but the start() call remains blocked.


    Regarding #2 & #3, I am finding that a bad hostname seems to fail relatively fast, and does not put the API into a bad state. However, other issues in the URI like the port or the path will take > 1min to fail and causes the problem I described. Also, I am finding that the protocol portion of the URI seems to be ignored; I can connect using 'foo://localhost:8443/Thingworx/WS'.


    Further look into #3, it seems that the 'ReconnectInterval' setting (default 60) is probably the cause of the ~1 min to fail.


    Message was edited by: Ting Zuge

      • Re: .NET Edge SDK seems to have static state
        vtielebein Explorer

        Hello Ting,


        #1: The expected behavior of the ConnectedThingClient class (which your SteamSensorClient class extends in your example application) is to instantiate only one server connection to the main Thingworx server at a time, as it uses a twApi singleton from the C SDK (as the .NET SDK is really a wrapper for the C SDK, just like the EMS and iOS SDK also). So you can instantiate as many different ConnectedThingClients as makes sense for your project, but you can only ever connect to one instance of the Thingworx Platform at a time (as each of these instances will use the same twApi Singleton). The values of the URI and App Key can be changed, but these changes will not actually make a difference unless the ConnectedThingClient is reinitialized. When you call the Disconnect method, that doesn't actually tear down the entire connection, it just closes the socket. So the Edge Client is no longer communicating with the Thingworx Server after this. So any values entered for URI and App Key when you reconnect are basically ignored. When you Shutdown, however, everything is reset.


        #2 and #3: The hostname being incorrect in the URI should fail faster than the port being incorrect as the router will just turn down the request for an invalid hostname. However, if the request reaches the server, then the C/.NET SDK will wait a full timeout before claiming an error, as you suspected about the ReconnectInterval being involved with that wait time. ConnectRetries does work in the way you are saying, where 1 refers to the first "try" in the initial connection. After it has connected, if it disconnects and tries to reconnect for any reason, it will try to reconnect the number of specified times. This is because when it initializes, it thinks it has previously disconnected (meaning that its first connection is really retry one). You are correct that Thingworx will ignore the protocol input in the URI as it forces http or https to be used depending on the encryption settings.


        #2 and #4: While the SDK is trying to connect to the Thingworx Platform, no calls can be made to attempt to disconnect or shutdown the server unless some custom implementation is written. The UI you are using does not actually allow one to try to disconnect or shutdown the SDK while it is connecting (see the line containing "!String.Equals(Status, Connected)" in the Disconnect method of the EdgeTestViewModel class. Even if I modify your code to allow the UI to call "client.Shutdown()" while the Status is "Connecting", the Shutdown call is ignored by the twApi. The workaround for this is to shorten the ReconnectInterval, though this may cause issues if you are ever trying to connect to a valid but slow server.


        #5: Your use case is not directly supported since, as mentioned above, the twApi is created as a singleton. You can have many many remote things connected to one Edge Client, and even multiple Edge Clients connected to a single Thingworx Platform, but you can only have one Thingworx Server connection per Edge Client at a time.


        I hope that clarifies things a bit! Please let me know further questions or comments. I plan to type up several KCS articles regarding this information and inquire further about the possibility of adding a "reinitialize" functionality to our twApi singleton (so that the entire server may not need to come down in order to reset the connection), but I can't make any promises at this time.