Success Comunicating With External App Using TCPSocket

Now… if this is the core of your app, i would eventually go with a custom ruby c++ extension, or, make it in such a way that an html dialog is an important aspect of the app, and do http in javascript.

And the OpenSSL bugs were also discussed in depth in the following API Issue tracker discussion …

https://github.com/SketchUp/api-issue-tracker/issues/110

… as well as at least one enhancement request to make the SketchUp API classes more usable …


Please add more fix and feature requests for these HTTP classes in SketchUp’s API.

Somewhere I thought that I had brought up the fact that SketchUp’s classes did not have any timeout controls. But I don’t see that I opened an issue for this.


@Neil_Burkholder, not sure if you realize that the Sketchup::Http::Request#start block argument is for a callback. Which I believe will not get called until the response is returned.

So I think if you wanted a monitor proc for the request, you’d need to set up a UI.start_timer block to keep testing the @request.status every so many seconds.

I also think that when I last used this, I had a @response reference initially set to nil that would get set in the @request’s #start callback block. And so testing if the @response reference was “falsey” was an indicator that the request hadn’t yet generated a response.

1 Like

Since Su19 is ruby 2.5 I honestly stopped caring about them and started using the ruby default module again. You have to wait for responses, that is true, but for all the apps I worked on, it was part of the userflow, so waiting was not a problem. For this kind of app, i would go with c++ and native threads.

1 Like

Agreed. It just irks me to no end that API classes get partially done and then abandoned.

2 Likes

Above I stated ‘Net::HTTP is probably the best thing to use’

There’s a lot of things that can qualify that statement. Sketchup::Http works just fine as long as one handles the response in an async manner.

In stand-alone Ruby code, I use Net::HTTP#start all the time, and often more than one request is done within the start block. I don’t think that can be done with Sketchup::Http.

Communicating between apps is messy. I’ve moved data from SU to another app using sockets, but I’ve never done any heavy bi-directional communication. Often, bi-directional implies a listener event loop of some type, and that may not work in SU.

For that I have had good experiences with a sketchup ruby timer combined with a native std::queue and a struct with a mutex locked ‘finished’ field.

@kengey

Right after I clicked send, I thought I should have said ‘and standard Ruby event loops may not work in SU.’

As you mentioned, UI.start_timer is often the only way to create an event loop, although the docs for it only mention ‘arbitrary animation’…

1 Like

Yea… it is a difficult topic.
There simply is no good, supported way to achieve this I am afraid.
Wonder how the SU timer works though. Ruby is pretty good at blocking invocation from other native threads.

1 Like

Thank everyone for your replies.

That’s what I’m using it for. I send a ‘Listen’ request, and when the C# app has data it returns a response. Works much better than using a timer.

When the connection is dropped, the callback returns an empty body, so I’m able to detect that.

def start_listener
  @connected = true
  @connectionstring = 'http://localhost:12345/'
  @listener = Sketchup::Http::Request.new(@connectionstring, Sketchup::Http::GET)
  @listener.headers = { 'Listen' => 'SketchUp' }
  @listener.start do |_request, response|
    if response.body == ""
      puts "Lost connection or couldn't connect to server."
      @connected = false
      close
    else
      start_listener          
      @job_data = JSON.parse(response.body, :object_class => OpenStruct)
      @job_data.Answers = @job_data.Answers.map { |a| [a.Id, a.Value] }.to_h
      @job_data.TokenValues = @job_data.TokenValues.map { |a| [a.token, a.value] }.to_h
      BC.draw_building(@job_data)
    end     
  end
end

So far the only time I was getting bugsplats was when calling close, and only in SU 2018. (didn’t test 2019)

Unfortunately I don’t know how to do either of those, but am proficient in C#. Also with the HTTP, I can send an entire json object and don’t need to worry about encoding or escaping. With the HTML dialog I was having issues escaping characters.

Are you able to reliably reproduce this?

I am afraid I am not. I believe we have discussed this shortly already in the past, yet then I was also unable to come with a test case for reproduction.

Is close() calling against an instance of a custom subclass of UI::HtmlDialog ?

According to the API Release Notes, the embedded CEF was updated for the 2018 release to 56.0.2924.76, and then again for the 2019 release to 64.0.3282.119.

Sorry I meant cancel. I have a close method on my class and it calls the cancel method.

I can reproduce in SketchUp 2020 but the conditions make no sense.

I have a dialog box that when it first opens it sends 4 simultaneous requests. On first load it would crash SketchUp without a bug splat every single time. 2017, & 2018 worked fine without a splat. Opening Ruby Console plus would prevent the crash from happening, so it may be related to SketchUp Bridge rather than the requests. In any event even on subsequent refreshes sometimes only 2 or three of the requests would complete.

To work around the problem I created a queue system so that when one request completed it would check for queued requests. That seems to have solved my problems so far. Back to testing :slight_smile: