ricohapi / theta-client

A library to control RICOH THETA
MIT License
15 stars 11 forks source link

ThetaTimeout not seems to work #67

Closed trunghvbk closed 3 months ago

trunghvbk commented 7 months ago

I implement connecting to theta camera with the code below.

async function initConnection(thetaIP) {
    const endpoint = `http://${thetaIP}`;
    console.warn(`thetaIP: ${thetaIP}`)
    const config = {
      clientMode: {
        username: [device_username],
        password: [device_password],
      }
    };
    const timeout = {
        connectTimeout: 3000,
        requestTimeout: 3000,
        socketTimeout: 3000
    }
    try {
      const isInit = await initialize(endpoint, config, timeout);
      console.warn(`isInit: ${isInit}`)
      return isInit
    } catch (error) {
      console.warn(`error: ${error}`)
      return false
    }
  }

Everything is OK if I input a correct ip address. But when input an incorrect ip address, the initialization takes a lot of time (over 1 minute) even I set the timeout params already. I printed the error : error: Error: Failed to connect to InetSocketAddress(hostname=192.168.0.103, port=80). The console prints out message: HttpClient: REQUEST http://192.168.0.103/osc/info failed with exception: kotlin.IllegalStateException: Failed to connect to InetSocketAddress(hostname=192.168.0.103, port=80).

Updated: Check again the console log and see this log appear a long time (~1 minute) before the error catched.

HttpClient: REQUEST: http://192.168.0.103/osc/info
METHOD: HttpMethod(value=GET)
COMMON HEADERS
-> Accept: application/json
-> Accept-Charset: UTF-8
CONTENT HEADERS
-> Content-Length: 0
BODY Content-Type: null
BODY START

BODY END

As I understand, the connectTimeout is set to 3000, that means after 3s connection was not established, the process will throw the timeout error. Or I am understanding wrong behavior of this configuration. Please help me to verify that it's a misunderstanding or it's a bug. Thank you guys.

My theta device: Ricoh Theta x Device to connect: iPhone SE 2020, iOS 17.2.1

simago commented 7 months ago

@trunghvbk Your understanding is correct. connectTimeout specifies a timeout for establishing a connection with a server.

| const isInit = await initialize(endpoint, config);

You do not pass timeout to initialize(), would you try const isInit = await initialize(endpoint, config, timeout)?

trunghvbk commented 7 months ago

@simago Oh sorry, my bad. The code I copied was accidentally not completed (I tried to remove the timeout params to see the result). Actually I did add the timeout params and it's exactly what I described for the issue. Updated the issue content. Thanks.

simago commented 7 months ago

@trunghvbk I have confirmed timeout exception does not been thrown on iOS. Theta SDK uses Ktor, an HTTP client library, that may have a restriction on iOS.

trunghvbk commented 7 months ago

Thanks @simago So do we have any way to track timeout on iOS?

trunghvbk commented 6 months ago

Hi @simago Now I understand it's the limitation of the lib built with Ktor. Is there any other way to build the library which can resolve the problem? I just want to confirm to plan our project. Thank you.

simago commented 6 months ago

@trunghvbk How about confirming the target IP address is reachable or not without Theta Client, then connect it with Theta Client.

trunghvbk commented 6 months ago

@simago Could you please suggest a way to check whether the IP address is reachable or not? And what if the IP address is reachable but the password is incorrect? Is it still not able to check the connection timeout? Thank you!

trunghvbk commented 6 months ago
  async function initConnectionWithTimeout3s(thetaIP) {
    setLoading(true)
    try {
      const result = await Promise.race([initConnection(thetaIP), new Promise((_, reject) => setTimeout(() => reject('Timeout exceeded'), 3000))]);
      setLoading(false)
      console.warn(`result: ${result}`)
      return result
    } catch (error) {
      setLoading(false)
      console.warn(`error: ${error}`)
      return false
    }
  }

@simago I found a way to use Promise.race to set the timeout for the connecting. But in this way, I need to cancel connecting when the timeout is exceeded. Is there any way to cancel the connection? I looked at the list of functions supported by the module, there is no function to achieve that.