This lesson is part of the Module Development with the Ignition SDK course. You can browse the rest of the lessons below.

LESSON LIST

Autoplay Off

Description

Take an introductory look at the overall structure of SDK module configuration and Java source code files.

Transcript

(open in window)

[00:00] In this lesson, we'll discuss some of the basic structure of an existing working Ignition SDK module example. This won't be a deep dive into all the how and why details of every file. Instead, it will provide an overview of some key aspects of any SDK module project. Our emphasis in this lesson will be on the indicated portion of the development workflow. Now that we've gone end to end in this workflow, we're going to circle back and take a closer look at some details of the module we've just built, installed, and run in Ignition. While there are many specifics to the code we just ran, we'll instead focus on aspects that will be common to any module project. We'll start out with our example project open in IntelliJ, but with all levels fully collapsed to start out. Let's open this first level and start working our way from bottom to top. First, we see this settings.gradle file. With Gradle, IA uses Nexus to host a Maven-compatible repository for Ignition SDK API dependency resolution, and this file defines those specifics.

[01:11] Next, this project has a readme file, with more specifics on the how and why of this project. This readme file is written using the Markdown markup language. Here we see the markup side by side with a rendered result, and it should be fairly simple to correlate the two sides. For example, we can see a top level heading, a third level heading, a file hyperlink, and so forth. A readme file is not required, but it is a good design practice to always include one. Next we have our project build scripts, gradlew.bat, and gradlew, alternate versions depending upon your platform. Here, the w suffix at the end stands for wrapper. These are shell scripts responsible for invoking the Gradle wrapper, which will automatically download and cache the appropriate Gradle version for our use. There really shouldn't be much need to delve into or modify these, so we'll just point them out without examination.

[02:08] build.gradle.kts is the primary project level config file. Here .kts means it's a Kotlin script file. This is where most of the important module configuration settings live. This file will typically be auto-generated when using the project build tools we'll discuss in another lesson. The user won't typically need to write this by hand. As noted in the preamble, this file is just a starting point. Learning and understanding Gradle is still highly recommended. There are lots of project configuration settings here. Some of the key things are the following. On line 14, this declares a variable that will be used later to define a specific SDK version we're developing against. Line 17, the version number of this project. Line 24, the human readable name of this project, and note that many other parameters will be variants on this name. Line 29, the name of the resulting module .modl file when built.

[03:04] Line 33, a unique identifier for this project, which may also appear in the code. Then scrolling down a bit more, line 40, a short description of the module, which appears in the gateway upon loading. Line 47, the minimum required version of Ignition to run this module, which will get enforced by the gateway upon trying to install the module. Broadly speaking, this should agree with line 14. Line 53, a list of the needed project scopes for this project, which are defined when this module gets set up. It's important to note here that a module doesn't have to use all these scopes. The scopes can be used in any combination. And scrolling down a bit more toward the end. line 77, a list of corresponding hook classes, which we'll get to in a moment. And finally, line 98 a setting to skip module signing in development mode. It's important to point out that while this last setting is true here in the training example, the default value in an auto-generated new project will be false, which will cause build problems if this module isn't being signed. So for now, it's best to set this to true for initial unsigned module development.

[04:18] Many of these settings will make their way into another config file in the actual built and deployed module, which we'll get to shortly. We mentioned the notion of scopes and hook files. A scope represents some specific portion of Ignition that the developer needs to use in a new application. There are three scopes: the gateway, designer, and Vision client. They may be used in any combination in a new application, and are generally specified at initial project creation. So if we scroll up in the file a little bit, we see that this example module uses all three scopes, client, designer, and gateway. There's actually also another common scope for code which is shared amongst more than one of the other scopes. Then for every scope of the module, there will also be a corresponding hook class, as designated down here, in this case, gateway hook, client hook, and designer hook.

[05:12] These hook classes serve as known programmatic entry points between Ignition and the module code. Finally, each of the scopes will also manifest as Gradle sub-projects within the larger module project, as we see in the project hierarchy here at the left. Let's drill down into these sub-projects next. So for starters, let's give ourselves a little visual elbow room by widening this side pane. Then let's expand each of these various module scopes like so. They each have a common structure, starting with individual scope level config files. This is where we might add any scope specific dependencies. Next, any scope specific source code will be located under each of the source directories, so let's expand those out as well, like so. They all have a reverse domain naming directory structure, the leading portion of which is specified at initial project creation time, as we'll see in a later lesson.

[06:24] Note how all of these are identical except for the trailing client, common, designer, and gateway, And this is where we see the hook classes for each of the three scopes. Once such hook class file is required for each module scope we elect to use, but they don't have to be called ClientHook, DesignerHook, and GatewayHook. However, they must align with the fully qualified hook file names we saw used in the primary module config file, and the word hook in each class name is a good design practice. Now, we won't do a deep dive into the details of each of the source code files.

[07:06] That's a task best left for the viewer together with the Ignition API reference, which is linked beneath this video in IU. However, let's take a quick look inside one of the hook files, GatewayHook. Each hook file provides an entry point into Ignition for that module scope and may provide several lifecycle functions. As noted in the Ignition SDK Programmers Guide, best design practice is to extend each corresponding abstract class, then override and provide implementations of any needed API functions. Three of the key lifecycle functions are setup, which is called before module startup; startup, which is called at module initialization; and shutdown, which is called at module shutdown. Notice that setup and startup are also provided with some application or licensing context, which can then be used to access other platform services of that context.

[08:07] For example, if we were to type context. or activationState., for each of these, any needed functions can internally be accessed with return types as shown. Now, here we see that these three functions aren't being put to use, but some other API functions are being used instead. We won't dive too deeply into all the details, but recall that this module provided a new scripting function, so we need to register it with a script manager, and when we ran it in the script console, it appeared in the added system.example Python library. Finally, let's take a look at the generated module .modl file itself. As we've seen before, it's going to be found in the project directory in its build subdirectory. It turns out that an .modl file is nothing but a zip file with specific content needed for installation into Ignition. We can see this by copying the file, pasting it, and renaming it to have a .zip extension.

[09:28] If we open it up, we're going to see that it has JAR files corresponding to the various scopes in use by the module. and a module.xmlL file, which is kind of a module manifest file in a prescribed format, and optionally, there might also be a license file and some documentation in this .modl file. Let's open up the module.xml file. Here we see several of the parameters we saw earlier in the project level build.gradle.kts config file, as well as the relevant G, C, and D scopes, and their corresponding hook class names. Taken together.

[10:11] These are the artifacts needed to install a new SDK module file into Ignition. All right, well, that concludes this abbreviated overview of the example module project file. Hopefully this has gotten you somewhat oriented to a simple SDK module project. Again, this wasn't a deep dive into this example. There's much more detail than can be reasonably covered here, so we encourage you to reverse engineer this example on your own, together with the Ignition SDK API, as you set out to develop your own SDK modules.

You are editing this transcript.

Make any corrections to improve this transcript. We'll review any changes before posting them.