Home AMX User Forum NetLinx Studio

NetLinx Plugin For Sublime Text

2

Comments

  • cmasoncmason Posts: 123
    champ wrote: »
    I got this going on another PC and forgot about it but a PM prompted me to share my solution with the community.

    I went back to the original PC to figure out why it didn't work and discovered I had tried to use an existing installation of Sublime Text 2. I removed Sublime Text 2, installed Sublime Text 3 and got it working.

    Here are the exact steps I took:

    I couldn't get the install via version control to work using HG so just downloaded a snapshot from http://sourceforge.net/p/sublime-netlinx/code/ci/default/tree/
    - unzipped the folder into C:\Users\<user name>\AppData\Roaming\Sublime Text 3\Packages
    - renamed the folder to sublime-netlinx-code
    - started Sublime Text v3
    - Selected Tools > Build system > NetLinx
    - Pressed control+B and it worked.


    I tried installing it this way and when I press CTRL-B I get an error in sublime:

    'netlinx-compile' is not recognized as an internal or external command,
    operable program or batch file.
    [Finished in 0.1s with exit code 1]


    Any suggestions?

    Thanks in advance.
  • cmasoncmason Posts: 123
    I think I'm getting hung up on the Ruby installtion of the Netlinx-Compile gem.

    Here is what the command line install looks like:
    C:\Users\cmason>gem install netlinx-compile
    ERROR:  Could not find a valid gem 'netlinx-compile' (>= 0), here is why:
              Unable to download data from https://rubygems.org/ - SSL_connect retur
    ned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed (
    https://api.rubygems.org/latest_specs.4.8.gz)
    
    C:\Users\cmason>
    

    Any ideas?
  • amclainamclain Posts: 41
    cmason wrote: »
    I think I'm getting hung up on the Ruby installtion of the Netlinx-Compile gem.

    Here is what the command line install looks like:
    C:\Users\cmason>gem install netlinx-compile
    ERROR:  Could not find a valid gem 'netlinx-compile' (>= 0), here is why:
              Unable to download data from https://rubygems.org/ - SSL_connect retur
    ned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed (
    https://api.rubygems.org/latest_specs.4.8.gz)
    
    C:\Users\cmason>
    

    Any ideas?

    That's happening because RubyGems updated their SSL certificate and the change must not have made it to the RubyInstaller yet. Here's a guide to fix it:

    Workaround RubyGems' SSL errors on Ruby for Windows (RubyInstaller)
  • cmasoncmason Posts: 123
    amclain wrote: »
    That's happening because RubyGems updated their SSL certificate and the change must not have made it to the RubyInstaller yet. Here's a guide to fix it:

    Workaround RubyGems' SSL errors on Ruby for Windows (RubyInstaller)

    Thanks for the help!
    I'll give it a try when I have a few minutes.
    I appreciate the response.
  • amclainamclain Posts: 41
    PhreaK wrote: »
    I'm glad to say that with the help of this I now have a 100% mac based dev machine - no VM required. Amclean, if you wanted to add support the compiler path required is:
    '"wine ' + File.expand_path('nlrc.exe', '~/.wine/drive_c/Program\ Files/Common\ Files/AMXShare/COM') + '"'
    

    Wine support has been added as of version 3.1.0, which was released today. Any path that includes ".wine" should automatically run with wine prepended to the compiler path. For non-standard installations I have included a :use_wine option in the API.

    I had NetLinx Studio 3.x running in Wine on Linux a year or two ago. Does NetLinx Studio 4 still work in Wine?
  • PhreaKPhreaK Posts: 966
    amclain wrote: »
    Does NetLinx Studio 4 still work in Wine?
    Sure does.
  • sublime-netlinx is now available from Sublime Package Control. This simplifies the installation process and provides automatic updates. Users who previously installed via version control are not forced to update; either method works equally well and is only a matter of preference. See the installation instructions for details on installing via package control.
  • nickmnickm Posts: 152
    amclain wrote: »
    sublime-netlinx is now available from Sublime Package Control. This simplifies the installation process and provides automatic updates. Users who previously installed via version control are not forced to update; either method works equally well and is only a matter of preference. See the installation instructions for details on installing via package control.

    This is awesome! Thanks for putting this together and sharing it @amclain!
  • vincenvincen Posts: 526
    PhreaK wrote: »
    Sure does.
    Here it works (including compile) but unable to establish network communication to controler :(
  • PhreaKPhreaK Posts: 966
    vincen wrote: »
    Here it works (including compile) but unable to establish network communication to controller :(
    Ah damn, you're right. It borks out with any outgoing network operations (listen for masters works though). Ditto with the new NetLinx Diagnostics app. To be honest I hadn't check either.

    Looking at the error report they're making a call to inet_pton(..) which doesn't appear to be implemented in wine's builtin libraries (at least a 1.6.2). It may be possible to grab the ws2_32.dll from a full install of windows where this is supported (vista or newer) then set up the override or recompile wine with it's own implementation. Might have a play this weekend.
  • vincenvincen Posts: 526
    PhreaK wrote: »
    Looking at the error report they're making a call to inet_pton(..) which doesn't appear to be implemented in wine's builtin libraries (at least a 1.6.2). It may be possible to grab the ws2_32.dll from a full install of windows where this is supported (vista or newer) then set up the override or recompile wine with it's own implementation. Might have a play this weekend.
    Let me know if you find a solution, would be happy to test it !
  • cmasoncmason Posts: 123
    I'm still having issues getting this setup to work. I'm willing to work through the issues if the result will be worth the effort.

    Can you tell me the advantages this editor has over the inherent Netlinx Studio editor?

    Does it drastically improve Netlinx programming?

    As always...Thanks!
  • vincen wrote: »
    Let me know if you find a solution [to the Wine issue], would be happy to test it !

    I fired up NetLinx Diagnostics 3.0.64 on Xubuntu 14.04.1 with the package manager version of Wine (1.6) and was able to reproduce the inet_pton() error. This function is part of winsock 2. The release notes for wine 1.7.30 state that inet_pton() was implemented in that version.

    Excerpt of Wine 1.7.30 release notes:
    Changes since 1.7.30:
    Bruno Jesus (12):
        ws2_32: Add tests and implement inet_pton.
    

    I installed Wine 1.7.34 and the error message has gone away. However, now all NetLinx Diagnostics says is “Failed to connect to the master controller”. Word on the internet sounds like winsock 2 is not fully implemented yet, but hopefully this saves you guys some time trying to figure it out. I’m interested to hear what you come up with.

    Edit:
    NetLinx Diagnostics 2.0 and FileTransfer2 do work in Wine, so it looks like having a functional NetLinx development environment in Wine is still possible.
  • PhreaKPhreaK Posts: 966
    Yep, I'm at the same spot as you. Just built 1.7.36 from the repo and while it no longer all comes crashing down when those apps attempt to connect to a socket, it still doesn't connect and there's nothing hitting stderr to indicate why.

    As you said, the older version of the diagnostics app and file transfer both still work so there are some options. No ability to transfer tp5 or xdd files from there though. TPD5 also doesn't install as the setup process try's to run the visual c++ 2012 runtime installer (which doesn't work with wine) so still somewhat bound to a VM. Even so, when just rolling NetLinx code Sublime blows NLStudio away in every respect thanks to your awesome work.

    P.S. I've just added some entries in the Wine AppDB for these to help keep track of what does and doesn't work. Would be awesome to see test results from others in there too if anyone else breaks things.
  • cmason wrote: »
    Can you tell me the advantages this editor has over the inherent Netlinx Studio editor? Does it drastically improve Netlinx programming?

    The first place to read up on is the Sublime Text features page. The advantages to using Sublime Text over NetLinx Studio vary based on programming style, the nature of your day-to-day work, and personal preference, but in my opinion Sublime Text offers at least some benefit to anyone who spends most of their time programming. It features a lightweight interface, a powerful command palette, extensibility through numerous community-created plugins, hotkeys (that can be reassigned) for everything, and fine-grained customization of user preferences. There are also macros and snippets that can automate repetitive tasks and text. Its advantages increase significantly if you work with multiple programming languages, as you can work on all of them in the same editor with all of your personal preferences set just the way you like them. This is incredibly helpful when writing code that generates NetLinx code.

    That being said, it is important to keep in mind that Sublime Text with sublime-netlinx is an alternative method for developing NetLinx projects, not a direct replacement for NetLinx Studio (why reinvent the wheel). To put it bluntly, NetLinx Studio suffers at being a good text editor, but provides access to a lot of [proprietary] utilities from a single interface. Sublime Text is a great text editor, but you’ll have to use other applications to access proprietary AMX features. Some of these applications, like netlinx-compile, work transparently under the hood once they’re installed. Others, like NetLinx Diagnostics, require a separate application to be launched (although they can be quickly launched from Sublime’s command palette).

    The two workflows are almost completely opposite of each other, each with its own set of advantages and disadvantages. Personal opinion will most likely be the biggest factor of determining which way works best for you, but hopefully this post has helped illustrate some of the differences.
  • cmasoncmason Posts: 123
    So, I finally got it working....hooray!

    But now it seems I have 2 of everything... such as Netlinx Command Palette options and
    Macros list Netlinx> Fix Indentation & sublime-netlinx-code> Fix Indentation.

    Is there an easy way to get rid of (old I assume) one set of these options?
  • cmasoncmason Posts: 123
    OK... I see where I can disable Packages... "Package Control: Disable package"

    Which one should I disable the one labeled "Netlinx" or "sublime-netlinx-code"?

    Thanks!
  • cmasoncmason Posts: 123
    When I Build my axs file, it never throws an error, even when I add some intentional errors.
    Why would that be?

    The console window shows NLRC.EXE - V3.0

    Netlinx Compile - Version[2.5.2.420] [02-09-2015 16:30:07]

    Do I have something set wrong?
  • cmasoncmason Posts: 123
    OK. I decided to revisit this today. I'm really beginning to like the features that I've found.

    I see that what is actually happening... the compiler is compiling a different axs file than the one I am editing in Sublime.

    amclain... I guess you were pretty serious when you said the workflow is different in Sublime.

    I guess I need to understand some elements to the Sublime editor.

    I'll look for some documentation so I can wrap my head around this.
  • Jorde_VJorde_V Posts: 393
    cmason wrote: »
    OK. I decided to revisit this today. I'm really beginning to like the features that I've found.

    I see that what is actually happening... the compiler is compiling a different axs file than the one I am editing in Sublime.

    amclain... I guess you were pretty serious when you said the workflow is different in Sublime.

    I guess I need to understand some elements to the Sublime editor.

    I'll look for some documentation so I can wrap my head around this.

    Tutsplus has a good video series on Sublime.

    See: http://code.tutsplus.com/articles/perfect-workflow-in-sublime-text-free-course--net-27293

    After that you might want to get some more information on the newer sublime text (3):
    http://webdesign.tutsplus.com/tutorials/useful-shortcuts-for-a-faster-workflow-in-sublime-text-3--cms-22185
  • cmasoncmason Posts: 123
    Jorde_V wrote: »
    Tutsplus has a good video series on Sublime.

    See: http://code.tutsplus.com/articles/perfect-workflow-in-sublime-text-free-course--net-27293

    After that you might want to get some more information on the newer sublime text (3):
    http://webdesign.tutsplus.com/tutorials/useful-shortcuts-for-a-faster-workflow-in-sublime-text-3--cms-22185

    Yes, thanks for the tip! I actually started watching some of those video tutorials (a few days ago) after I got my Netlinx-Sublime installation working. There is a bit of a learning curve though, so it's been a little slow going using the Sublime text, but I feel like I could get used to it after a while.
  • cmasoncmason Posts: 123
    How do I manage a Netlinx workspace with Sublime Text?

    I started writing a new module in ST yesterday and I was able to compile the module and fix errors and recompile.

    Now today when I try to compile it, only compiles the Master .axs file in the workspace. I'd like to be able to do compile on just the file I'm working on in the workspace, not the File set as the maser.

    Thanks.
  • Jorde_VJorde_V Posts: 393
    cmason wrote: »
    How do I manage a Netlinx workspace with Sublime Text?

    Now today when I try to compile it, only compiles the Master .axs file in the workspace. I'd like to be able to do compile on just the file I'm working on in the workspace, not the File set as the maser.

    Open the module separately and then compile there. (That's how I do it).

    I don't think there's a way to use Netlinx APW in Sublime, however you can create your own project/workspace in Sublime Text. (Project tab in the topbar)
  • cmason wrote: »
    OK... I see where I can disable Packages... "Package Control: Disable package"
    Which one should I disable the one labeled "Netlinx" or "sublime-netlinx-code"?

    If you were able to download it from the package manager, you can disable (or delete) sublime-netlinx-code. That sounds like the one that was cloned from version control.
  • cmason wrote: »
    How do I manage a Netlinx workspace with Sublime Text?

    I started writing a new module in ST yesterday and I was able to compile the module and fix errors and recompile.

    Now today when I try to compile it, only compiles the Master .axs file in the workspace. I'd like to be able to do compile on just the file I'm working on in the workspace, not the File set as the maser.

    UPDATE:
    netlinx-workspace solves this problem as of v1.0 by supporting a YAML configuration file

    Whoops, looks like I deferred the workspace documentation. I’ll have to get back to that...

    In the grand scheme of things, the netlinx-workspace gem will take care of workspace management through some kind of text file that makes it easy to define the system configuration, and a project creation command like “netlinx new [folder name]”. Since that’s not implemented yet, there are two workarounds that I know of.

    The .apw workspace file is nothing more than XML with a different file extension, so one of my friends prefers to open and edit it in Sublime Text. This works better for flat workspaces (that don’t have levels of different projects and systems) because it’s harder to get lost in the XML tree.

    The other way to do it, which is what I personally do, is to set up the workspace in NetLinx Studio and add your source and include files. At that point you rarely have to touch the workspace again. The trick to this method is to treat the files in the project as if they were part of a standard programming language, not the way NetLinx file structure is taught.

    In a standard language there is an entry point where the program starts. In languages like C and Java, this is the function main(). NetLinx doesn’t have this kind of function, but in a more general sense you can think of the .axs master source code file as the entry point. Since there can only be one point of entry, there can only be one .axs file in the system.

    There’s a point where a single file becomes impractical, because adding lots of code to one file will make it big and hard to maintain. This is where include files come in to play. Implementing this in NetLinx means moving your devices and touch panel code out of the .axs file and into include files. This leaves the .axs file almost bare except for a few #include statements and possibly a small amount of configuration code (like setting up a logging utility). In sublime-netlinx you can create these files with “NetLinx: New From Template: Overview” (.axs) and “NetLinx: New From Template: Include” (.axi). You’ll notice that the include file has a guard (#if_not_defined) so that it will only be compiled once and can therefore be safely included in any file that depends on it. When you build a system this way, all of the include files will be compiled and the compiler will show you which line out of any of them has failed.

    For a multi-master system, use the same concept but create one system for each master. Each system should have one .axs file, and one or more include files. If I remember right, “netlinx-compile --smart” (which is what sublime-netlinx executes) runs the active system, so set the first system to active, write the control system program, set the second system to active, write that system’s code.


    Here’s an example of what the workspace tree will look like:



    After rereading your question I realized your problem is specifically with modules. I recommend using include files instead of modules, as you can call functions directly without having to go through event handlers and string parsing, and the’re easier to maintain. Include files can be designed to be reused and even turned into libraries; amx-lib-volume is an example of this. If you really want to create a module, I would think the best way to do that is like any other library: Put it in its own project, develop and document its public API, test it as an independent component, then drop it into your project as a compiled module. As you find bugs, add tests for the broken functionality, fix the module’s code, and increment the version. Then drop the new version into the project. amx-test-suite is designed to aid in the process of automated testing.

    Again, my personal opinion is to avoid modules and use include files instead.
  • cmasoncmason Posts: 123
    @amclain - Thanks for your response. I did end up playing around with it and came to the conclusion that I needed to separate the module from the workspace to allow for independent compiling.

    I really appreciate some of the features that Sublime Text has to offer. Thank you for taking the time to integrate Netlinx with Sublime. ( When do you sleep? ;) )

    I agree with your opinion of using Include files instead of modules... to a point.
    Most of my code has many includes for various devices.... but I've found it to be a bit cumbersome maintaining unique variable (and function) name since they exist globally throughout the workplace. Also, some of my projects are using multiples of the same device, and that presents it's own issues, where a module works nicely as I can assign each device it's own instance of a module.

    Also, the bulk of my code, has to be implemented across roughly 20 different systems, each of them providing the same basic function and UI but often having slightly different setups and slightly different equipment.
    When using includes and executing device specific functions in the main code, I've found that the code get's so interwoven it proves difficult to make changes to an include, fix then instances that were executing a specific function , and then customize and revise the changes to the next system.

    Unfortunately, I've ended up coding myself into a corner here and there which as made it more confusing to implement new features and fixes across my systems without suffering unintended consequences. In an effort to improve my coding practice and interoperability , I've been trying to utilize modules more, and write simpler includes only to initialize and address devices for the module.

    That being said, I understand I could probably code my includes better to standardize functions to allow more interchange, but I have really begun to appreciate the autonomy that modules provide.

    I am computer engineer by education, therefore I'm lacking fundamentals for higher level coding practices that a computer science degree would have centered on, but I do have a strong perspective on the logical interface between hardware and software that my comp-sci friends are all but clueless about.

    That being said, I am always willing to listen and learn! Any advice you guys have I always appreciate.

    This forum is an indispensable resource for an AMX programmer.

    Thank you,
    -Chris
  • cmason wrote: »
    I agree with your opinion of using Include files instead of modules... to a point.

    Yeah, ultimately includes vs modules is a religious debate and it comes down to personal preference. My opinions aside, I condone the use of modules as long as they’re not used to lock other programmers out of the source code. In a case like yours, they may be the fastest way to instantiate multiple copies of the same device.
    cmason wrote: »
    Most of my code has many includes for various devices.... but I've found it to be a bit cumbersome maintaining unique variable (and function) name since they exist globally throughout the workplace.

    If NetLinx supported namespaces it would help a lot with this problem. Since it doesn’t, I like to borrow a practice from C programming of prefixing the function/variable name with a library, instance, or other appropriate identifier to try to avoid naming conflicts with “unknown” names that may be added to the project later. For example, if I had two different models of projectors in the project, one file would implement “panasonic_projector_on(...)” and the other “infocus_projector_on(...)”. I’m sure you’re doing this to a certain extent already; the names become easier to maintain as the boundaries between components become clearer (generic device/library used between projects, project-level “library”/class used multiple times in the project but too specific to be used in other projects, and project instances).
    cmason wrote: »
    Some of my projects are using multiples of the same device, and that presents it's own issues, where a module works nicely as I can assign each device it's own instance of a module.

    The benefit of modules is that they’re a quick way of solving the instantiation problem in NetLinx. The tradeoff is that they force what would otherwise be simple function calls and return values to be transformed into something that can be pushed onto the asynchronous event queue -- and NetLinx doesn’t make it easy to tie received events to the functions that triggered them.

    In the long run I think code generation techniques like Model Oriented Programming (MOP) are a better answer to the NetLinx instantiation problem. My NetLinx-specific spin on this is netlinx-erb, and I’m experimenting with object-oriented practices in NetLinx. The simple explanation of MOP is that a system’s configuration is separated from its implementation code, allowing parts of the code to be automatically generated for different configurations (multiple instances of a device in a project, multiple programs running on a job site in different variations).
    cmason wrote: »
    The bulk of my code, has to be implemented across roughly 20 different systems, each of them providing the same basic function and UI but often having slightly different setups and slightly different equipment.

    Code generation is the answer to this problem. Imagine a YAML configuration file like this that instructs the generator as to which devices to use for each system:
    room_101:
      projector: panasonic_pt_dz770
      switcher:  extron_dsc_301_hd
    
    room_201:
      projector: panasonic_pt_dz770
      switcher:  kramer_vp_728
    
    room_301:
      projector: infocus_in5555
      switcher:  extron_dsc_301_hd
    
    cmason wrote: »
    When using includes and executing device specific functions in the main code, I've found that the code get's so interwoven it proves difficult to make changes to an include, fix then instances that were executing a specific function , and then customize and revise the changes to the next system.

    When code can be described as “interwoven and difficult to make changes”, it’s a red flag that there’s a better way to break it down into encapsulated objects with well-defined interfaces. Although NetLinx tends to force code to be more interwoven by nature than other languages, code generation can deal with writing and maintaining that bit once the design of the objects and their interfaces are sorted out.

    Although I don’t know the specifics of your project, it sounds like you’re alluding to a problem that the proxy pattern (adapted for NetLinx) can help with. Using the example of swapping out different projectors, you’d have files like this:

    touch_panel.axi --> projector_proxy.axi --> panasonic_dz770_projector.axi

    touch_panel.axi:
    #include 'projector_proxy'
    
    button_event[dvTP, BTN_PROJECTOR_ON]
    {
        push:
        {
            projector_power_on();
        }
    }
    

    projector_proxy.axi:
    #include 'panazonic_dz770_projector'
    
    // Proxy the abstract projector_power_on() function call
    // to the device implementation.
    define_function projector_power_on()
    {
        panasonic_dz770_projector_power_on();
    }
    

    panasonic_dz770_projector.axi
    define_function panasonic_dz770_projector_power_on()
    {
        send_string dvPROJECTOR, "'PON', $0D";
    }
    

    Switching out another instance of this system to an InFocus projector is as simple as including the infocus_in5555.axi device file and updating projector_proxy.axi (ideally with a code generator). In this example you know that abstract touch panel behavior is in touch_panel.axi, the device implementation is in panasonic_dz770_projector.axi, and the glue that binds them together is in projector_proxy.axi; far less spaghetti code floating around, and a clear boundary where devices can be swapped.
    cmason wrote: »
    I am computer engineer by education, therefore I'm lacking fundamentals for higher level coding practices that a computer science degree would have centered on.

    It sounds like you’re on the edge of a programming breakthrough based on the problems you’ve been describing. One thing that may help is to learn an object-oriented language like Ruby, Python, or Java. It’s interesting how thinking of a problem in the context of one language can shed light on how to solve it in another language.

    Resources:

    Codewars is a website that features programming challenges.

    Design Patterns is one of the must-read programming books for object-oriented design, but it’s centered around C++.

    Design Patterns In Ruby is an adapted version of the design patterns book if you choose to learn Ruby.

    Practical Object-Oriented Design in Ruby is another that I recommend.

    Head First Ruby is a good place to start if you go the Ruby route.

    Head First Java is a good place to start if you go the Java route.

    Head First Design Patterns is the only one on the list I haven’t read, but one of my friends said it was great for learning the design patterns in Java.

    I’ve only dabbled in Python; @PhreaK may have some good recommendations for that language.
  • JasonSJasonS Posts: 229
    amclain wrote: »
    When code can be described as “interwoven and difficult to make changes”, it’s a red flag that there’s a better way to break it down into encapsulated objects with well-defined interfaces.

    This is exactly what an AMX module does. If you use a consistent API, the only thing needed for swapping out devices in a system is to change the Define_Module statement. That being said, modules are not the solution to every problem, they don't always make sense for reusable library type code. But, includes have there own set of issues, I hate the "compile in place" nature of NetLinx includes. It is very easy to run into scope issues when trying to use multiple includes together.
  • amclainamclain Posts: 41
    cmason wrote: »
    How do I manage a Netlinx workspace with Sublime Text?

    UPDATE:

    This can now be done with netlinx-workspace >=1.0, using a text-based configuration file that looks like this:
    systems:
      -
        name: Client - Room
        connection: 192.168.1.2
        touch_panels:
          -
            path: Touch Panel.TP4
            dps:  10001:1:0
        ir:
          -
            path: IR.irl
            dps:  5001:1:0
    

    See the netlinx-workspace release announcement for more info.
  • RJkrispRJkrisp Posts: 3
    netlinx-compile

    very nice work, thanks amclain. Build:workspace compiles all systems in the workspace, and build:source compiles the active file. Is it possible to build only the active system in a workspace that has multiple systems?
Sign In or Register to comment.