14 Replies Latest reply on Jul 24, 2017 10:54 AM by kimaldis

    Communication between a LR plugin and an iOS app over a LAN

    Avizzv92 Level 1

      I want to create a plugin for Lightroom 6+ (this is new to me) that allows two way communication to take place between LR and an iOS app. The iOS device would be on the same local network.

       

      What is the best method of accomplishing this? I was thinking about using LRSocket, this is the most direct method? I assume with this method the iOS app would need to act as the server and the LR plugin would be the connecting client? But, all the documentation and examples I’ve found, regarding general LRSocket usage, imply that localhost is used. This would make communication with an iOS device over WiFi impossible?

        • 1. Re: Communication between a LR plugin and an iOS app over a LAN
          johnrellis Most Valuable Participant

          You could try running a proxy that forwards the connection from LR to the remote device. It's been a couple of decades since I worked with network proxies, but I recall there used to be simple proxies available.   Perhaps someone knows more about what's currently available, but Google may be your friend here. Or you write your own proxy: Your plugin starts the proxy, connects to it with LrSocket, the proxy then connects to the iOS device (or vice versa).

           

          You could use HTTP from the device to LR, using polling with long-running GETs to send information back to the device.  Or you could use HTTP from LR to the device.  Or you could use HTTP in both directions.   See this post (which was written before LrSocket was released) for more detaIls about that: Re: How to send lightroom data to arduino?

          1 person found this helpful
          • 2. Re: Communication between a LR plugin and an iOS app over a LAN
            Avizzv92 Level 1

            I feel like dealing with a proxy could be more of a hassle than it is worth.

             

            I might look at HTTP Long Polling but it wouldn't be my first choice.

             

            I'm now leaning toward using a tiny standalone app on the computer w/LR installed that acts as the server. The app can communicate over the LAN with the server app and the server app and LR plugin can communicate via localhost.

            • 3. Re: Communication between a LR plugin and an iOS app over a LAN
              kimaldis Level 1

              I'm working on a shortcut app that communicates with Lightroom using both http & LrSockets. The app catches shortcut keypresses and passes Lua code to a Lightroom plugin that runs the code and sends back data. The app also runs a web server that serves up pages that can send and receive code & data back and forth to Lightroom. I'm using LrSockets to send Lua code to Lightroom and to receive data back from the keypresses and http post in Lightroom to talk to the webserver. Both work equally well both from localhost or from another device.

              1 person found this helpful
              • 4. Re: Communication between a LR plugin and an iOS app over a LAN
                Avizzv92 Level 1

                Is the app running locally on the same computer? I wasn't able to find any information about setting up a socket connection with LRSocket without using localhost. Right now I have a small app on the computer acting as the go-between for Lightroom and the iOS app.

                 

                iOS App <- IP -> Mac App <- localhost -> Plugin

                • 5. Re: Communication between a LR plugin and an iOS app over a LAN
                  kimaldis Level 1

                  Sorry, yes, you're right; I haven't looked at this in a while. The app runs on localhost.  I'm using LrSocket to talk between LR and the app on hotkey presses but it also runs a web server  and a websocket server which are used to communicate from a browser, or whatever, on remote machines. Websocket because it's faster if you need to stream data.

                  • 6. Re: Communication between a LR plugin and an iOS app over a LAN
                    Avizzv92 Level 1

                    I'm having another related problem that you might be able to help with...

                     

                    I have a small app that functions as a server for handling socket connections (TCP). I have an iOS app that can connect and communicate with this app without any problems. But, the plugin I'm testing with using LRSocket will not even connect to the sever app let alone send messages.

                     

                    I'm using Adobe's basic example for "send" with LrSocket. When trying to connect It returns an error saying "failed to open localhost:54345". I used this program https://sourceforge.net/projects/sockettest/?source=typ_redirect to test my server as well, this program can connect to my server without any problems.

                     

                    This is the code for my plugin that is returning the connecting error.

                    local LrFunctionContext = import "LrFunctionContext"
                    local LrDialogs = import 'LrDialogs'
                    local LrSocket = import "LrSocket"
                    local LrTasks = import "LrTasks"
                    
                    import "LrTasks".startAsyncTask( function()
                            LrFunctionContext.callWithContext( 'socket_remote', function( context )
                                local running = true
                                
                                local sender = LrSocket.bind {
                                  functionContext = context,
                                  plugin = _PLUGIN,
                                  port = 54345, 
                                  mode = "send",
                                  onConnecting = function( socket, port )
                                   -- TODO
                                  end,
                                  onConnected = function( socket, port )
                                   -- TODO
                                  end,
                                  onMessage = function( socket, message )
                                   -- nothing, we don't expect to get any messages back from a send port
                                  end,
                                  onClosed = function( socket )
                                   running = false
                                  end,
                                  onError = function( socket, err )
                                   if err == "timeout" then
                                    socket:reconnect()
                                   end
                                   LrDialogs.message( err, err, nil )
                                  end,
                                 }
                                 sender:send( "Hello world" )
                                 
                                while running do
                                  LrTasks.sleep( 1/2 ) -- seconds
                                end
                                
                                sender:close()
                            end )
                    end )
                    
                    • 7. Re: Communication between a LR plugin and an iOS app over a LAN
                      johnrellis Most Valuable Participant

                      I don't see anything obviously wrong.  Some thoughts:

                       

                      - Try port numbers from different parts of the range of valid numbers.

                       

                      - Try using "telnet" at the other end as the test server, e.g. "telnet localhost 54345".

                       

                      See this thread for a sample script that worked (at least last summer): Re: LrSocket running on Windows - problems

                      • 8. Re: Communication between a LR plugin and an iOS app over a LAN
                        Avizzv92 Level 1

                        When I do "telnet localhost 54345" I get the Hello World back. Assuming I catch it before the plugin times out.

                         

                        I also get Hello World back if I use that SocketTest app (using it as a client).

                         

                        Am I misunderstanding something? I thought LR acts as the client in this case (connecting to the external server app I made)? Is that not how it works? Should I treat LR as the server for both send/receiving messages?

                        • 9. Re: Communication between a LR plugin and an iOS app over a LAN
                          johnrellis Most Valuable Participant

                          I had assumed it always acts as a server, and that's what these tests show. But someone like @kimaldis who's used LrSocket extensively will be more authoritative...

                          • 10. Re: Communication between a LR plugin and an iOS app over a LAN
                            Avizzv92 Level 1

                            You are correct. Connecting to the LR plugin as a client for both sending and receiving allows the app to communicate with it.

                            • 11. Re: Communication between a LR plugin and an iOS app over a LAN
                              kimaldis Level 1

                              Again, it's been a while and I don't have my laptop in front of me for a few days but from memory: I had to faff around quite a lot to get this to work and I do remember that getting the app end right took a degree of fiddling before it worked, due mostly to my only just working knowledge of sockets. My code is in Swift, you're more than welcome to it when I get my laptop back if it helps. Toward end of week. I'll be open sourcing it anyway when I get my head around GitHub.

                               

                              Be sure you open the LrSocket before the app, both for receive and send. You get 5-10 seconds.

                               

                              You'll need a socket each for send and receive.

                               

                              If you're sending and expecting a response in tasks you may need some kind of handshaking to avoid the picking up the wrong return message.

                               

                              I really wish they'd made this handle both send and receive on the one connection/port. Like telnet, for example. It would have made life much easier. And I've no idea why they restricted it to localhost either.

                               

                              All that said, when you get it working it works well. I have a very nice custom hot key mechanism that runs lua code snippets and a very neat way of controlling lightroom and displaying information in a browser on a remote device. Again, I'll open source it when I figure out GitHub. I'll also be looking for people to test it, if anyone's interested.

                              • 12. Re: Communication between a LR plugin and an iOS app over a LAN
                                kimaldis Level 1

                                Oh, make sure the strings you send and receive are terminated in new lines.

                                • 13. Re: Communication between a LR plugin and an iOS app over a LAN
                                  Avizzv92 Level 1

                                  I've gotten to the point that I can send/receive messages between a Mac app and the plugin. Though I would appreciate seeing your code as well!

                                   

                                  For whatever reason it doesn't seem to matter for me whether the client or the plugin start first. Nor does it matter if I miss that 10-15 second opening before a timeout. Maybe it is a result of restarting/reconnecting if the connection closes or timesout?

                                   

                                  onClosed = function( socket )
                                       socket:reconnect()
                                       cr.SERVER:close()
                                       startServer(context)
                                  end,
                                     
                                  onError = function(socket, err)
                                       if err == 'timeout' then 
                                            socket:reconnect()
                                       end
                                  end
                                  

                                   

                                  I do have a separate question, I am curious whether or not you notice anything weird when quitting Lightroom with your plugin installed?

                                   

                                  When I quit Lightroom with my plugin started, it takes ~5 seconds for Lightroom to close the window and another ~10 seconds before the task completely dies (the dot under the icon in the Dock disappears). It is essentially in a non-responsive state for a number of seconds. Without my plugin installed it quits nearly automatically (a couple of seconds or less). I haven't tested it enough to know if anything else in Lightroom degrades in performance.

                                   

                                  This is also true for another plugin that I did not write but uses sockets.

                                   

                                  I'm not sure if there is some kind of cleanup or something I should be doing in my plugin code so that it closes more gracefully and rapidly?

                                  • 14. Re: Communication between a LR plugin and an iOS app over a LAN
                                    kimaldis Level 1

                                    Yes, I would think it's the reconnect that's masking the timeout. My plugin fires my app for me' it never gets that far.

                                     

                                    I have a bit of a delay when Shut lightroom down but I wouldn't say it was out of the ordinary. I haven't checked it without the plugin running.