Home AMX User Forum NetLinx Studio
Options

Netlinx Ajax interface module

Hello, just in case any one is interested, I've created an ajax interface that allows control of a Netlinx system from any web browser that supports ajax. Check out: http://home.earthlink.net/~urbtek/downloads.htm

A screen shot of the demo can be seen here: http://home.earthlink.net/~urbtek/images/utAjaxScreenCap.png

I've also created a mode file for the jEdit text editor to support syntax highlighting for the Netlinx language.

If anyone uses the module, please send feedback as to what you think.

Thanks,
++Colin.

Comments

  • Options
    yuriyuri Posts: 861
    Pretty cool, but whats the use? You have to open up a port on your firewall to be able to connect to the frame, so why not open up port 1319 so you can just use Netlinx Studio to control it :)

    Note: I really like this type of new development and didnt mean to burn you down or something, just a heads up ;)
  • Options
    mpullinmpullin Posts: 949
    You wouldn't have to open up a new port, would you? I mean, I'm assuming your program connects to the master on 1319 and uses that port for all the usual operations... like a mini NetLinx Studio in your browser?

    I think that's a nice accomplishment btw, even if I don't see many people using it. Congrats.
  • Options
    Hey, thanks for checking out the ajax module. The reason I wrote the module (besides being curious to see if it could be done) was because I wanted to control an AMX system using the nokia 770 web tablet (http://www.nokiausa.com/770).

    This cool little device has an Opera-based web browser but no Java VM. So, I couldn't use the standard AMX web control features which needs Java to be installed.

    Keep in mind, the sample page I show is just a sample. The idea is you decide which functions you want to perform and use the module to get the communication done. The down-side is that you have to create your own web pages, TP Design won't help you.

    ++Colin.
  • Options
    champchamp Posts: 261
    Fantastic

    I've never seen or been able to think of a good use of XML_TO_VARIABLE.
    I don't understand it all but I think I can get this to recieve feedback without polling.

    champ
  • Options
    yuriyuri Posts: 861
    xml_to_variable rocks :)

    anyway, now i think of it, it's actually very handy for webtablets and things like that, that dont run Java :) cool
  • Options
    champchamp Posts: 261
    Now I know a little about what's going on I realise that polling is the only way as the client page doesn't keep the connection alive.
    I'm giving up until I actually need to do this.

    Oh well, I've learnt some along the way.
  • Options
    dthorsondthorson Posts: 103
    Re:Netlinx Ajax interface module

    This is great. I think there could be alot of applications to use this type of programming. Having programed using .NET.

    What about creating a webpage that would run the entire processor.

    dt
  • Options
    Hi champ,
    There is a way to keep the connection open and push data when needed, but support for this in browsers is flaky since it violates the http standard. When I need to keep a page updated, I just set a javascript timer and ask for the shared variable every 5 seconds or so. Not the nicest way of doing things, but it works.

    ++Colin.
  • Options
    mpullinmpullin Posts: 949
    Hi champ,
    There is a way to keep the connection open and push data when needed, but support for this in browsers is flaky since it violates the http standard.
    Have you considered using Flash for this? Every respectable browser now comes with a Flash plugin, and I know there are xmlsocket operations, although I haven't played with them yet.
  • Options
    Matt,
    That's a great idea. I haven't used the programming interface with Flash but it might be worth looking into.

    ++Colin.
  • Options
    GSLogicGSLogic Posts: 562
    Years ago I did a two-way Flash interface for a company with a PC based automation system called Homeseer. It worked great and had some really cool graphics for the devices.

    I spent hours trying to do the same for the Netlinx master but ran into these problems:

    You have to store the Flash.swf file on the master, you can't hard code a Flash web page (as you well know). You'll be able to request and/or send data to the master but when the response comes back from the master it will always be on port 80, which can NOT serve up the Flash.swf file because the Netlinx Java home page is there and you can't get around it. I've talk to an AMX engineer that said they hope to change this in the future.

    I lost a large job to Cr***** because of this, the client had to have a internet controlled Flash interface which the dark side could offer because they use Windows.
  • Options
    champchamp Posts: 261
    Hi Colin

    I don't understand a couple of things which bugs me.

    In the HTML file all of the user response handler functions are commented out yet they must be getting called.

    Why does the javascript increment the port with each command and where is this done? I can't even find where the value of portid is set.

    I hope my questions aren't too basic. As you can probably tell I have never used ajax and very little javascript, but I've never let complete lack of knowledge of a technology stop me from figuring out a problem before.

    champ
  • Options
    dchristodchristo Posts: 177
    GSLogic wrote:
    You'll be able to request and/or send data to the master but when the response comes back from the master it will always be on port 80, which can NOT serve up the Flash.swf file because the Netlinx Java home page is there and you can't get around it.

    I'm not sure what you're saying here. I've been serving a Flash interface from a ME260 for several years now without problem. I'm attaching my XML Socket Server module for reference, but I've never had a chance to finish it. Currently it only supports channel commands (on/off/push/release) and variable text. I'm using it to interface with a Flash app, but it could be used by any external application.

    Here's the module definition:
    DEFINE_MODULE 'XMLSocketServer' mdlXMLSocketServer (vdSocketServer, dvSocketServer, nSocketServerPort)
    

    Sorry for the lack of documentation. Hopefully someday I'll have the change to finish it and package it up nice.

    --D
  • Options
    GSLogicGSLogic Posts: 562
    dchristo wrote:
    I'm not sure what you're saying here. I've been serving a Flash interface from a ME260 for several years now without problem. I'm attaching my XML Socket Server module for reference, but I've never had a chance to finish it. Currently it only supports channel commands (on/off/push/release) and variable text. I'm using it to interface with a Flash app, but it could be used by any external application.

    I'd need to see your XML Socket Server module code and the Flash file to see what you are doing.
    I need to be able to install the Flash.SWF file on the master and open a port so the client would just enter an IP to load the Flash interface and have two-way communication with the master.
    Are you able to do this with your mod?
  • Options
    dchristodchristo Posts: 177
    GSLogic wrote:
    I need to be able to install the Flash.SWF file on the master and open a port so the client would just enter an IP to load the Flash interface and have two-way communication with the master.
    Are you able to do this with your mod?

    Yes. The swf is stored on the master. I have a small "index.htm" file on the master that embeds the flash file to make it easy to launch. The Flash file opens a socket on a user specified port, and then is able to have two-way communication with my XMLSocketServer module.

    --D
  • Options
    GSLogicGSLogic Posts: 562
    I think I know why it works for you... did you ever try it on a master with the v3_12_332 - with java index page?
  • Options
    dchristodchristo Posts: 177
    Nope, only on the ME260
  • Options
    yuriyuri Posts: 861
    dchristo wrote:
    Nope, only on the ME260

    why wouldnt it work on a NI-X000?
  • Options
    I've updated the module so that it can server .swf, .svg and .xml files. So, it should work with flash files now. Just make sure you put them in the utAjax folder on the Netlinx processor.

    Yuri, the module implements a simple web server. Reading up on the http standard will help you understand what is going on. Contact me offline if you need more help.

    ++Colin.
  • Options
    dchristodchristo Posts: 177
    GS_Logic,

    I just loaded a flash file onto a v3.12.335 master and was able to serve it up without problems. It's in it's own subdirectory with a small index.htm file. There may be issues with getting it to show on the main Java page (I haven't tried this at all), but the master seems to have no problems serving the file.

    I don't quite understand the statement you made on responses from the master to the Flash app always being on port 80. Could you expand on this a little more?

    Thanks,

    --D

    Edit: I didn't notice this when I originally tested, but I just looked at the master and it had automatically added a link on the main Java screen that launches the index.htm file (which in turn opens the flash app).

    --D
  • Options
    GSLogicGSLogic Posts: 562
    Dave

    If you were to send a request command to have the master reply with some data, what network port does the data come back over?

    If I open port 55 and send data to the master (192.168.1.51:55) , I can control what ever I want from the Flash interface. The problem arrives when I request data from the master, it always sends data back on port 80, or what ever port you have the server set to on the master.

    I need the data sent back on port 55 or be able to get the Flash file to load and communicate on the master's server port without having the java page load when the master sends data request back.

    Hope this makes sense to you!

    Thank -Gary
  • Options
    dchristodchristo Posts: 177
    Perhaps I've misunderstood what you're asking. In my application I'm not communicating directly with the Master, but with my module, which in turn passes the data back and forth between my Netlinx program. The Flash app opens a user-specified port, and bi-directional communcation happens on that port.

    --D
  • Options
    moty66moty66 Posts: 31
    Is it possible to get the source code of the module ? or the idea behind it ?

    regards
    m.
  • Options
    ivomochivomoch Posts: 1
    ReUpload

    Colin Turners utNetlinxAjax interface module...
  • Options
    utAjax on NI-700

    I installed the utAjax interface module on an NI-700 and it works as intended. However, I'm finding a limit on the maximum allowed size for uploaded files. The issue is that I'm implementing a custom user interface in HTML, but once the file size increases above the 16kb threshold, content stops being rendered on the browser.

    Does anybody know how to increase or overcome the file size limitation?
  • Options
    AuserAuser Posts: 506
    felicin wrote: »
    Does anybody know how to increase or overcome the file size limitation?
    fileBuffer = "httpResponseHeader,fileBuffer"
    

    Concatenations like that will hit the 16kB limit. Instead concatenate such strings using the following to work around this limit:
    // Name   : ==== AppendString ====
    // Purpose: Appends a string to a string variable
    // Params :
    // Returns: True if successful, false otherwise
    // Notes  : Works around a limitation in the maximum return size of two string
    //          literals being appended. The 63999 byte chunks come from a
    //          documented 64kB limitation of the variable_to_string stream
    //          marshaller. The documentation didn't specify what it classed as a
    //          kB, so the actual value can probably be increased to (2^16)-1, but
    //          I couldn't be orsed testing it.
    //
    define_function char AppendString(char _cString[], char _cTextToAppend[])
    {
      stack_var    long      _lSourceLength
      stack_var    long      _lResultingLength
      stack_var    char      _cPaddingLength
      stack_var    char      _cDestroyedData[3]
      stack_var    long      _lInjectionLength
      stack_var    long      _lInjectionSourceLength
      stack_var    long      _lInjectionStartPos
    
      _lSourceLength = length_array(_cString)
      _lInjectionLength = length_array(_cTextToAppend)
      _lResultingLength = _lSourceLength + _lInjectionLength
      if((_lResultingLength < 16000) && (_lResultingLength <= max_length_array(_cString)))
      {
        _cString = "_cString, _cTextToAppend"
        return TRUE
      }
      else
      {
        if(_lSourceLength < 3)
          _cPaddingLength = 3 - type_cast(_lSourceLength)
    
        if(_lResultingLength + _cPaddingLength <= max_length_array(_cString))
        {
          if(_lSourceLength)
            _cDestroyedData = right_string(_cString, 3 - _cPaddingLength)
          _lInjectionSourceLength = _lInjectionLength
          while(_lInjectionSourceLength > 63999)
          {
            _lInjectionSourceLength = _lInjectionSourceLength - 63996
            _lInjectionStartPos = _lSourceLength + _cPaddingLength + _lInjectionSourceLength - 2
            variable_to_string(mid_string(_cTextToAppend, _lInjectionSourceLength + 1, 63996), _cString, _lInjectionStartPos)
          }
          _lInjectionStartPos = _lSourceLength + _cPaddingLength - 2
          variable_to_string(left_string(_cTextToAppend, _lInjectionSourceLength), _cString, _lInjectionStartPos)
    
          if(_cPaddingLength)
          {
            for(_lInjectionStartPos = 1; _lInjectionStartPos <= 3 - _cPaddingLength; _lInjectionStartPos++)
              _cString[_lInjectionStartPos + _cPaddingLength] = _cDestroyedData[_lInjectionStartPos]
            set_length_array(_cString, _lResultingLength + _cPaddingLength)
            _cString = right_string(_cString, _lResultingLength)
          }
          else
          {
            _cString[_lSourceLength - 2]  = _cDestroyedData[1]
            _cString[_lSourceLength - 1]  = _cDestroyedData[2]
            _cString[_lSourceLength]      = _cDestroyedData[3]
            set_length_array(_cString, _lResultingLength)
          }
          return TRUE
        }
      }
      return FALSE
    }
    

    Should allow you to serve up files to about 4GB in size. Kim Burgess was looking at adding a similar function to the Netlinx Common Libraries; might be worth checking there too.

    If you want a bit more background on the limitation have a read of http://www.amxforums.com/showthread.php?3410-Data.text-or-Buffer-Problems
  • Options
    link is not available

    link is not available
  • Options
    AuserAuser Posts: 506
    Which link - the link to the file download above, or the link to the other thread that I posted? I can access both - perhaps you do not have access to the part of the forums where one or both are located?
  • Options
    fileBuffer Increase
    Auser wrote: »
    fileBuffer = "httpResponseHeader,fileBuffer"
    

    Concatenations like that will hit the 16kB limit. Instead concatenate such strings using the following to work around this limit:
    // Name   : ==== AppendString ====
    // Purpose: Appends a string to a string variable
    // Params :
    // Returns: True if successful, false otherwise
    // Notes  : Works around a limitation in the maximum return size of two string
    //          literals being appended. The 63999 byte chunks come from a
    //          documented 64kB limitation of the variable_to_string stream
    //          marshaller. The documentation didn't specify what it classed as a
    //          kB, so the actual value can probably be increased to (2^16)-1, but
    //          I couldn't be orsed testing it.
    //
    define_function char AppendString(char _cString[], char _cTextToAppend[])
    {
      stack_var    long      _lSourceLength
      stack_var    long      _lResultingLength
      stack_var    char      _cPaddingLength
      stack_var    char      _cDestroyedData[3]
      stack_var    long      _lInjectionLength
      stack_var    long      _lInjectionSourceLength
      stack_var    long      _lInjectionStartPos
    
      _lSourceLength = length_array(_cString)
      _lInjectionLength = length_array(_cTextToAppend)
      _lResultingLength = _lSourceLength + _lInjectionLength
      if((_lResultingLength < 16000) && (_lResultingLength <= max_length_array(_cString)))
      {
        _cString = "_cString, _cTextToAppend"
        return TRUE
      }
      else
      {
        if(_lSourceLength < 3)
          _cPaddingLength = 3 - type_cast(_lSourceLength)
    
        if(_lResultingLength + _cPaddingLength <= max_length_array(_cString))
        {
          if(_lSourceLength)
            _cDestroyedData = right_string(_cString, 3 - _cPaddingLength)
          _lInjectionSourceLength = _lInjectionLength
          while(_lInjectionSourceLength > 63999)
          {
            _lInjectionSourceLength = _lInjectionSourceLength - 63996
            _lInjectionStartPos = _lSourceLength + _cPaddingLength + _lInjectionSourceLength - 2
            variable_to_string(mid_string(_cTextToAppend, _lInjectionSourceLength + 1, 63996), _cString, _lInjectionStartPos)
          }
          _lInjectionStartPos = _lSourceLength + _cPaddingLength - 2
          variable_to_string(left_string(_cTextToAppend, _lInjectionSourceLength), _cString, _lInjectionStartPos)
    
          if(_cPaddingLength)
          {
            for(_lInjectionStartPos = 1; _lInjectionStartPos <= 3 - _cPaddingLength; _lInjectionStartPos++)
              _cString[_lInjectionStartPos + _cPaddingLength] = _cDestroyedData[_lInjectionStartPos]
            set_length_array(_cString, _lResultingLength + _cPaddingLength)
            _cString = right_string(_cString, _lResultingLength)
          }
          else
          {
            _cString[_lSourceLength - 2]  = _cDestroyedData[1]
            _cString[_lSourceLength - 1]  = _cDestroyedData[2]
            _cString[_lSourceLength]      = _cDestroyedData[3]
            set_length_array(_cString, _lResultingLength)
          }
          return TRUE
        }
      }
      return FALSE
    }
    

    Should allow you to serve up files to about 4GB in size. Kim Burgess was looking at adding a similar function to the Netlinx Common Libraries; might be worth checking there too.

    If you want a bit more background on the limitation have a read of http://www.amxforums.com/showthread.php?3410-Data.text-or-Buffer-Problems


    This work-around works perfectly for port 80.

    How can I get the same workaround to work on port 8000, which is the one assigned to the utAjaxFramework?
  • Options
    PhreaKPhreaK Posts: 966
    Auser wrote: »
    Kim Burgess was looking at adding a similar function to the Netlinx Common Libraries; might be worth checking there too.

    I had completely forgotten about that. If you want to add it in and submit a pull request on GitHub that would be awesome.
Sign In or Register to comment.