Design Like A Pro: 25+ Hidden Gems That Make Your Project Shine
58 min video / 50 minute read Download PDFSpeakers

Reese Tyson
Sales Engineer III
Inductive Automation

Adam Koch
Sales Engineer III
Inductive Automation
Have you ever been toiling away on a project and then find out about a feature or technique that makes your work much easier? You’ll get that feeling over and over again if you watch our next webinar, where we’ll reveal more than 25 lesser-known Ignition features that help you to unlock greater productivity.
Join us as two of Inductive Automation’s Ignition experts share insider tips and tricks for building projects more efficiently, working with containers, and tapping into a wealth of knowledge and resources from Ignition’s global community. You'll want to add all of these hidden gems to your collection of knowledge and skills!
- Do more in less time in the Ignition Designer
- Learn the basics of using Docker with Ignition
- Explore the Ignition Exchange and other community resources
- Get answers to your Ignition questions
Register now — even if you can’t attend, we’ll send you the recording!
Transcript:
00:00
Reese: Hello, everyone. Welcome to our webinar today, "Design Like a Pro — 25+ Hidden Gems That Will Make Your Project Shine." I am thrilled that you are able to join us today. My name is Reese Tyson. I'll be your co-host today. I'm a sales engineer here at Inductive Automation, which means basically I get to help folks like yourselves along their Ignition journey. So, whether that's architectures, platform integrations, or best practices, I'm always here to help. Of course, we'll be talking about best practices today, but before we jump into that, also joining me today is my partner in crime here, Adam. Adam, you want to give a quick intro of yourself?
00:40
Adam: Yeah, of course. Thanks, Reese. Yeah, my name is Adam Koch, also a Sales Engineer like Reese here. I do the same type of stuff he was mentioning there. And I'm really excited to present some cool tips and tools in Ignition for you today. So, send it back to Reese.
00:56
Reese: Fantastic. Yeah. Just real quick, here is our agenda for the webinar today. We'll quickly bring you up to speed about Inductive Automation and Ignition. Then we'll dive right into our 25+ tips and features that are grouped into really three categories here. The first category is the Ignition Designer. We'll show you a lot of great designer tips. Then we'll get into the second category, which will be all about using Docker and Ignition with Docker. Then the third category will take us into a few really neat resources on the Ignition Exchange that are my personal favorites, or at least some of them, I should say. There are a lot of them on there. And then after that, we'll take your questions. If you want to ask any questions, just type it in the Questions area of the GoTo Webinar control panel there, and we'll answer as many as we can at the end of the webinar. And honestly, even if it's not a question, go ahead and throw it in there. If you have a really cool tip or feature that you'd like to share with the community, that's what this webinar is all about — just sharing knowledge.
01:57
Reese: We'd love to highlight some of those as well. But of course, if we can't get to your question today, please reach out, and one of our account representatives will be happy to answer it. Also, in case you're wondering, the recording and the slides from the webinar today will be available on our website starting tomorrow. So, real quick about Inductive Automation. If you're not familiar with us, here are a few facts about us. Our software, Ignition, is used by 65% of the Fortune 100, which means that it's being used every single day inside of some of the world's biggest companies.
02:34
Reese: We have over 4,000 integrators worldwide in our Ignition Integrator Program. We have a highly diversified customer base across many industries, with thousands of Ignition installations all over the globe. I believe it's over 140 countries. We've been in the industry for 22 years and counting, and we have over 350 employees in the U.S. and Australia. But if you're still asking, "Well, what is Ignition?" here's a quick summary. Ignition is a universal industrial application. To put it simply, it's a platform that we use for HMI/SCADA applications, MES, and IIoT — and really much more.
03:14
Reese: But it acts as a central hub for everything on the plant floor and beyond. You can use it to create any industrial application. It's web-based, web-managed, web-deployed, it has an unlimited licensing model; it's cross-platform; and, of course, offers industrial-strength security. When it comes to building industrial applications, Ignition really has no equal. It literally has tons of features that help you build projects more efficiently. And there are a lot you probably haven't discovered yet. What we want to do today is show you some of these lesser-known features and tips that will help you unlock a whole new level of productivity.
03:57
Reese: So, to kick things off, let's go ahead and jump into the designer. Let me go ahead and drag this over and bring the designer on screen here. All right, that looks pretty good. Now, if you are familiar with Ignition, you know that we use an example of a motor UDT, a motor template, and those types of things a lot inside of our projects — for demos, for webinars, etc. In this example here that I have, we've basically taken a starter project — the base project — and added a few views here, the motor template that I just mentioned, some UDTs for our motors, etc.
04:38
Reese: And we want to expand on that in this webinar here. So we're going to use this project as our base and talk about some of the things that are maybe just a little bit less known than some of those typical examples we show a decent amount of times. So, let's go ahead and jump in here. The first thing that I want to show is inside of this motor's view. This motor view is pretty basic. You can see over here on the tree structure, I have a dropdown component, and I have an embedded view that's looking at my motor template, which is defined right here. Now, this motor template has one basic parameter, and based off of this parameter, I'm looking at a different motor — I'm just casting in a tag path there. This parameter is bound to my dropdown. You can see I'm looking directly to that dropdown to look at its props and the value that we're selecting. Anytime that we select a new motor, you'll notice I'm looking at a different motor. The end user can look at any motor that they choose, as long as the option is there in the dropdown.
05:44
Reese: So, really basic example of how to use components together on a screen. But say you created this view and now I went into a project review, and within that project review, maybe the end user says, "Hey, I want to add a text field here in front of my dropdown." Maybe give a little bit more context as to what this dropdown is for. Maybe say something like, "Select motor." Let's go ahead and add that in there. And actually, this kicks off my first tip of the day here is wrapping components inside of a container. If you right-click on this dropdown, come down to "Wrap in container," you can actually wrap these components within a container. And you'll notice that here's my motor's view. Our structure of the view has changed. Now the Flex container inside of that has dropdown. That's a handy way where you can do a couple steps at once. Instead of dragging a flex container on, moving that dropdown inside of the Flex container, etc., you can just do that automatically all within one step there. Let's go ahead and add that label on that we were talking about earlier.
06:51
Reese: Drag this on; move this to the front. Let's go ahead and change this to "Select motor." Looks pretty good. Let's make this a little bit wider here — 100 pixels wide. And now we have our updated screen. Let's go ahead and throw this into preview mode. Second tip of the day — instead of clicking on the play icon, you can actually hit F5, and this is going to toggle you in and out of preview mode within the designer. The preview mode, of course, allows you to interact with these views as if you were in the client. But F5 is an easy way to get into that. Now that we have wrapped our dropdown in the flex container here, this no longer works. Now, the reason why that is is because, if we remember, if we go back to this embedded view and we go back to our instance, you'll notice this is a direct binding to the component, and it's dependent on the structure of my view over here. And so, really, best practice here is to create our bindings so they are not dependent on the structure of our view, because within Perspective, they do change an often amount of times.
08:08
Reese: Let's go ahead and show you how you can use best practice here within the view to get around the changing structure of the view but keep the data flow and everything operating as you expect. Let's go ahead and go to the motor's view. We'll add a custom property here. We'll call this "instance" because that's the name of my property or my parameter that I'm passing in. And we're going to go ahead and make this. I'm going to right-click — let's go ahead and copy path here — and add the value over there. Now, what we want to do is bind instead of to the dropdown; we want to bind to that custom property that I just created — "instance." Now you can see this path is very different. It's going to the view custom instance property. And so, this path is never going to change because it's going from the top down instead of directly to that component. So, we'll go ahead and hit OK there. And the other thing that we need to do, of course, is now link my dropdown to that as well. Anytime the value changes in my dropdown, the user selects that.
09:17
Reese: That needs to update this custom instance property as well here. We also want to make this bidirectional so that if anything else updates this, the dropdown gets updated as well. We can read and write to that custom property. We'll go ahead and hit OK there. That looks pretty good. And now, go ahead and toggle us back into preview mode again with our shortcut, and we should be able to still control our motor. Sure enough. But now remember, we're going through the custom property instead of directly to the dropdown component. Now if I take this dropdown out of this and change up the structure of the view. Oh, that's really tall. Let's make this a little bit shorter there. Make it maybe 50 pixels tall. Now you'll notice that my view structure is definitely different. The dropdown is now outside of my Flex container here. But our functionality should still work because we're using that custom property — the page's custom property — instead of going directly to that binding.
10:22
Reese: The other place where you might use this and take advantage of this is in a script. Just a really quick example of a button script and how you could use this as well, of course, is instead of going directly to that dropdown component — we go to that dropdown component — you'll notice that this is kind of a fragile path. It's going directly to that dropdown. Whereas we want, again, to use that view's custom property, which doesn't ever change. And now we could do something like equals — I wonder if I still have the string in my clipboard. Nope. Let's go ahead and copy that again from the tag browser. Go ahead and copy path. Go back into the script here, and I'll paste this so that now, anytime that we click this button, it should update the custom property to "motor-1," and thereby updating my embedded view as well. We'll go ahead and throw this into preview mode with our toggle, click this, and sure enough, there we go. We can change it with the button, and we can change it with the dropdown. A really great way to design your Perspective views to use best practices. And really, one of the reasons I wanted to bring this up is a lot of times folks are coming from a different SCADA platform, or they're coming from Vision, where you're just dragging these components on the screen and binding them to each other.
11:54
Reese: There's usually not a lot of nesting inside of containers or considerations of view or screen size, those types of things. Because you're building it for a specific HMI screen, which is a 1920 by 1080 or whatever that is. With Perspective, of course, you can view this in a web browser, you can view this on a TV, you can view this on a laptop. And so that's where these containers come into play a little bit more. Designing your screen like this really helps mitigate any rework that you might have to do when adjusting those screens and the content within them. That's the first main point that I wanted to show off here — just a little bit of a best practice on how to develop your screens.
12:42
Reese: These other ones that I wanted to show are little ways that you can add some flavor to your Perspective views. What I want to do is add a header at the top of this. Again, drag this to the top; maybe make this 50 pixels tall. I'm going to go ahead and add a label in here, and I want to label this view as "Motor Details" so that the end user knows what they're looking at. The first thing that I wanted to mention here — first tip — inside of this header is the auto option for your basis. You'll notice that this is wrapped. I want this to be in a single line. And I may not even know how long this string is. This string may even be dynamic. And so what I want to do here is change — instead of manually making the pixel width of this label something exact — I want to change it to auto, which automatically makes it the size of the content within this label.
13:47
Reese: This can be done on a label; this can be done on a container. This can be done in a lot — pretty much every place where basis is available — but it's going to automatically size this to the content within that component. So, that's the first thing. The next thing I want to do is add an icon in here. And what I want to do with this icon is just add a little bit more context for the end user. I want it to, when I hover, show off something, and then when I right-click on this, I want to be able to bring up a menu that takes you to a motors PDF that maybe correlates to the motor we're showing here or a troubleshooting guide for this motor. Let's go ahead and change this icon to the info icon. That looks good.
14:33
Reese: Let's go ahead and come down here to the Meta Properties section. You may not have browsed around this as much. It's maybe not as much of a used section of a component, but it has some really cool things down here. Let's go ahead and enable the tooltip section. And in this tooltip I want the text to say, "Right click for more info." That way, when the user hovers over it, they know that they can right-click that icon. When they right-click that icon, I want it to bring up this context menu. Inside of this context menu, I want to give them a couple options. Add an array element here. This first one, I'm going to make a motor PDF. What I was saying is we can browse to that motor PDF. We can add in an icon to this. I actually don't think we have any motor icons. The motorcycle helmet — sure, let's use that one. Then we'll go ahead and select our type. Inside of this, you could have a submenu to pop out another menu off of the main menu. We can specify a link — which is what we're going to do today — call a method on this component, send a message across the screen, or add a separator to visually separate categories of this menu.
15:50
Reese: So, let's add a couple links and then maybe separate those by a separator. This first link I'm going to have a URL that I just found a PDF of a motor when I was googling yesterday. I'll go ahead and add this in here, and then you can target either this current page you're on or open in a new tab. I want to open in a new tab. Add another item. We'll make this a separator type, and then finally we'll add a third item, and this one's going to be our troubleshooting PDF. We'll go ahead and keep that as a link. I'll just use the same URL for intensive purposes for this webinar and then add this to — or specify this target as tab to open in a different tab. That is all that I want to do here. Let's go ahead and save this. I'm going to show this off in a session because that way you'll be able to see the tabs launching here. Bring this onto the screen.
16:50
Reese: As you can see, our header is — we could probably add some flavor, add some spacing, some padding, some color, etc. But for purposes of the webinar covering a lot of content, I'm going to leave those things out. Just focus on the tooltip here. As you notice, it's saying, "Right click for more info." I'm going to right-click. Here's my motor PDF with that motorcycle helmet. But we can click on this and open a new tab. Here's that motor data sheet. And then we could also go to the troubleshooting PDF. It's going to open on the same one there. But you can see you have a lot of different options inside of this menu to do a whole host of different things. And of course, all of these items can be dynamic. There you go. A couple different tips for adding some flavor for your end user and some useful items, as well as best practices in developing some of your Perspective screens. So, with that, Adam, I'm going to throw it back to you. And I think we're staying in designer, are we not?
17:49
Adam: Yes, we will. Here we are in my designer. Like Reese mentioned, that's where we're going to stay for now. And we're also going to continue working with this same template view that he's been looking at in the same tags. We'll start by taking a little bit more of a look into those tags. And as you can tell, these are UDT instances. Let's take a quick little look at those UDTs. We'll navigate over to our UDT Definitions tab, and we have a motor UDT here that you'll see. Let's take a quick little right-click and go down to this View UDT Hierarchy. Now, what that's going to do is open up the UDT Hierarchy Tool. This was introduced in 8.1.23, and what it provides us here is a little pane on the left that shows the inheritance structure of this UDT and any other in that flow of that inheritance hierarchy, as well as all of the members of each of these UDTs and which ones are inherited, which ones aren't — indicated by this little symbol over here — along with the parameters. It even gives us a nice little button here on the top left where we can show instances of each of these UDTs that we've created and even have some little buttons for sorting and filtering those instances as well.
19:07
Adam: This is a really nice tool for looking at your UDT inheritance structure and everything that's within them, all in one nice consolidated window. And that's why we wanted to highlight it. Let's jump back over to the Tags tab for a second here. Most of you are probably familiar with the ability to take a tag out of the browser, drag it onto a screen, and select from this list of Perspective objects and have the designer automatically create a binding to that tag value for you — which is a cool, fun little option. What some of you might not be as familiar with is you can configure your template views to work in the same way with UDT instances. That's the next thing I'm going to go over — is to show you how to configure that. If we go to our motor view here in the Project Browser, you'll see that in the props window for that, we have this "dropConfig" section. That's where we're going to set this up. Under UDTs, here is where we'll add the different UDT configurations that we want to use for the specific view that we're in.
20:20
Adam: You'll see I have one set up here already. And each UDT that we set up is going to require these three parameters that you see. The top one is called type — that is where we're going to select the UDT type that we want to drag instances of onto the screen. You'll see I've selected that motor type we were looking at. We also have a param property here. What this is doing is it's holding the name of the view parameter down here that we're going to pass that instance into. And then the third is the action property. Now, you'll see action has two options in a dropdown that we can select here — path and bind. This one is set at path, and what it's doing here is it's passing the path of that UDT into that instance param. Then how you would use that within your template view is you would just bind to that tag path using an indirect binding with this path as the basis — whatever value you needed within that structure, whether it's Amps or HOA. Now, the other way to do it — the bind type — I've built in this Motor V2 template here, and we'll see the slight difference there.
21:33
Adam: You'll notice that all my other properties in the UDT configuration are the same, other than the action, which is set to bind. You'll also notice that the param itself is a completely different structure. Instead of one value holding that path, it's the actual full structure of that UDT instance. That's because the main difference here is that when you drag one on with the bind action set, it's actually creating a binding directly to this parameter on that instance. And how you would access these from within your properties on that view is with property bindings directly to the specific properties within this instance param. Let's take a quick look at how that works on our motors list view here. You'll see I have a Motor 1 dragged on there already. Let's drag Motor 2 up there. And now you can see I get my two options for my different views that I created. I'll use the regular Motor 1 first. And you can see it just passed Motor 2's path into the instance parameter. But if we do the same thing for Motor 3 and use the V2, you'll notice that it does look a little bit different.
22:48
Adam: It created this little binding right to the instance param, and we can see the whole structure there. That's the difference between those two. One last thing we'll check out here while we're in an embedded view object is a nice little tip. If you're looking at one of these objects and you want to quickly get back to the view that this path is pointed at — and not have to find it in your Project Browser — you can select this little cube right here that says "Open view," and it'll navigate you right back to the path that that's pointed at. Next thing I want to look at here in the Designer is a couple really nice functions that we have in our system functions for troubleshooting with scripts.
23:34
Adam: Now, we'll look at a couple different options — those being our system.util.loggers and our system.perspective.print. We'll start in the Script Console, which I'll drag onto the screen, and you'll see I have a little script here already. You're obviously going to be needing to troubleshoot things a little more detailed than this. You might use this where you want to see maybe if your script entered an if-statement or not, or see if a specific part of your script ran.
24:05
Adam: Loggers are great for that. You'll see what I'm doing is I've created a logger object using this system.util.getLogger. I've named it Script Console with this string right here. When I create this logger object, it gives me access to these dot methods — .info, .trace, and a few others — that are all documented for the different logger types. And that's what that's doing. I'm making this an info-type of logger and a trace-level of logger. And this string in here is what the actual message that I'm logging is going to be. Let's run this. We'll do a quick execute, and you'll see that I logged my info test, but we didn't see the trace test. Now, let's look at somewhere else we can see these loggers — and if we see it there — if we go to Help and Diagnostics, this is where we view the Designer's logs. You can see that I also have my info test there, but still no trace. That's because of these logging levels. If we scroll down and find our Script Console log — which should be added to this list now that we've created it — you'll see there's these levels beside it, and it's set at "info" by default.
25:19
Adam: If we open up this dropdown, you'll see there's a whole bunch of other levels, and this is a top-down list. That means whatever level that you set it at, it will allow logs of that level and anything below to be sent using this logger. Trace being the top level, it was not allowing that log to send with its headed info. Let's make this trace and go back to our Script Console for a second and run it again. We'll see now that we updated our output console, and we have — at this time — both the info and the trace. And we go do the same thing here in our diagnostics. And you'll notice that in the Script Console logger, we have an info and a trace — and they even have their own unique little icons to show that they're different levels of loggers. That's loggers that you can use when you're working in the Script Console. But maybe you have scripts running on actual Perspective objects. Let's look at how these things can be used there as well. I've got an event script running on this HOA button that we'll check out.
26:30
Adam: It's just onActionPerformed when you click it. What it's doing is it's looking at the control value property and finding a string based on what that value is to say what mode it is. And then I'm just logging that into a message that says, "Motor was put in that mode." You see, I've done something similar to what we saw in the Script Console, but this time I've named the logger "demoLogger." Now, I'm also doing something else down here, which is a system.perspective.print. You'll see I'm sending it the same message, though. The main difference between these two is that a logger is going to log at the level that the script is running at — which is why when we ran it within the Script Console, the logger was sent to the Output Console and the designer and the Designer's logs. That's because the Script Console runs scripts at the designer level — at the designer scope. perspective.print is always going to print at the client scope. We'll see how these two differ and how the logger works slightly differently now that we're running on a Perspective object, which runs its scripts at the gateway scope.
27:43
Adam: So, if we put this screen into test mode here and we put our motor in off, we'll see that our Output Console updated and we have our Perspective print down here saying our motor was put in off. However, we don't see our new log there. Where we can see that is in the gateway logs. You'll see I have a "demoLogger" here saying that my motor was also put in off at that same time. That's because, again, this script was run at the gateway scope from that Perspective object — which is where that logger logged at. Now, perspective.print can also be useful for troubleshooting even within your actual web browser client sessions. If I go to my tools and I launch a session there, it'll open up in a new screen for me, and I'll drag it in. You can see that it launched our project in my default browser, which is Chrome. One other cool little tool I'm going to show you while you're here is the developer tools within Chrome. These are Chrome-specific developer tools. I go to these three little dots, and I go to More Tools and Developer Tools. It'll open up this little bar here.
28:56
Adam: You'll see there's a lot of nice tools in here, but the first one we're going to look at is the Console. The Console is going to allow us to see that output console for our client that we were seeing before. If I go to my motors list and I put my motor in auto, you'll see my Perspective print is now printing there. That's because, again, it's printing at the client level. And this web session — this client — is my client's console that's going to print it. One last quick little tool that we're going to look at while we're in here is this device toolbar. If I turn this on, it'll allow me to basically test the performance of my screen scaling — see how it scales as it goes to different sizes. There's even preset devices that you can test how it's going to perform on that specific device's screen. A lot of other nice tools here within the Chrome Developer Tools, but we're not going to dive into the rest of them today. That's all of the time that I'm going to spend in the Designer, because I do want to take some time to talk a little bit about Docker with Ignition with you.
30:10
Adam: And so we wanted to talk about this a little bit and introduce you to Docker with Ignition. This can seem a little bit daunting at first, because it may be a foreign concept for a lot of you — especially those of you coming from an OT world like myself — but I'm going to introduce it to you a little bit here and hopefully provide some tips and tools that can help you get started easily, as well as maybe show you the benefits of why we like using it. One thing I should also note is that our elective Inductive University videos on Docker and the Docker Image page of our manual are great references for anybody getting started with Ignition in Docker and should be used by anyone that's starting out and trying to do that.
30:58
Adam: I used them extensively when I started using Dockerized Ignition, and they are great references. I believe we're going to have those linked in the chat as well as in the slides. First of all, though, what is it? Docker is a containerization engine. Well, what is containerization? It's basically virtualizing everything around an application and loading everything that's needed for an application to run within a unit called a container.
31:25
Adam: These containers then basically run on a containerization engine like Docker. These containers are also not operating system dependent. They're quickly deployed, and they're easily managed. The Docker software itself — we can talk about for a quick second here. Docker can be installed on mostly just about any operating system. But the specific version of Docker that I'm using is Docker Desktop, which is an application for Windows, which is what I'm using for my host machine, my work laptop. Another nice reason that I like to use it and that we're going to show it off here today is because Docker Desktop includes three Docker products that are really nice. That being the underlying Docker engine — this is the core workings of Docker; this is what runs the actual containers.
32:25
Adam: The second being Docker Compose, which can be used to create a file that holds all of our container’s configuration to be reused. We're going to see that a little bit later. It's really nice. And then the third is the Docker Desktop Dashboard that you see in front of you. That's what you should be able to see on my screen. Now, this provides a nice little user interface with details on our containers and even more. And that's why I think it's really good for people that are just starting out.
32:55
Adam: First thing we're going to do is we're just going to spin up a container that is running Ignition. I'm going to open the terminal up here within Docker Desktop and run from there. Now, you could run any PowerShell or terminal that you wanted to run this in, but because we have this nice UI with an integrated terminal, let's use it. I just pasted this line into my command line here, and you'll see that it's a docker run command. This is saying, “Run the container with these parameters I'm giving you.” I'm giving it this -d flag, which tells it to run in detached mode, which just means, “Hide all the details; I don't need to know all the intricacies of it starting up and running.” The -p flag is port forwarding. Now what that's going to say is, “Take the port that my application is running on in the container…" We should all be familiar with this 8088 port that Ignition runs on.
33:53
Adam: It's going to forward that to my host machine. That's going to allow me to access it through that host port. Now, one thing of note is that only one application can run on a certain host port at a time — meaning if you have multiple instances of Ignition running, you're not going to be able to forward them all to 8088 on the left side of this operation here, which is your host side. What I like to do there is just count up. But you need some sort of free port — that’s the bottom line.
34:23
Adam: The next line here is the actual image that we're going to use. This is telling it to go out — if we don't have this image already — to go to Docker Hub and grab the Inductive Automation Ignition image. And that's what it's going to use to build that specific application in our container. Then I'm giving it this latest flag — that's just saying, “Hey, make it be the latest version of Ignition.” Whatever the latest image is that's created, usually for our latest minor release. Then we have the -n flag, which is just naming the gateway “webinar” at the end here. If we run that, you'll see it gave me an output in the terminal that is a unique string — that is the ID that is unique for that container.
35:04
Adam: You'll also note that the beginning part of that unique ID matches the container ID that was popped up here in this new container that showed up in my UI. You'll also see it gave me a random name, which Docker does if you don't explicitly tell it what to name the container. Usually it's something fun — like we got “serene_matsumoto.” It also shows you what image you were using to run it — basically what the application is. And it even shows you what ports you forwarded. If you click on this little link as well, it'll open up that port in your web browser, right to what you set up. And you'll notice that this probably looks familiar. This is basically the screen you go to to start your configuration of your new gateway that you've just installed. There's a lot of nice information to see about the container running. There are even some little actions we can use to control the containers over here on the right. We can stop the container, which you'll see it's now in exited mode and not running anymore. We can even remove it — this completely deletes the container. It no longer exists. Everything about it is gone.
36:14
Adam: We could have done both of those operations within the terminal as well, but I just wanted to showcase some of the nice features that you have when using a UI like Docker Desktop. There's also a bunch of other information on images and stuff on the left here. But I do want to jump into my next little segment here, which is Docker Compose. Now, for Docker Compose, I'm going to jump into a different application called Visual Studio Code. Visual Studio Code is basically just an editor for your different files, but you'll see a couple of the reasons why I like using it specifically for my Compose files here as we go on. First thing I want to talk about, though, is the Compose file itself. The Compose file is a YAML file. As you can tell here, my webinar one is docker-compose.yaml and I have it open in the middle here. And basically what it does is it uses that YAML syntax with these key-value pairs to create your configuration for your container, as opposed to typing it all out in a command line. You can just basically call this file.
37:25
Adam: You can reuse this file. You can have a basic configuration. And that's why it's really nice — you have this set configuration. It makes it easier to add a lot of extra things too, like these environment flags where I'm automating a lot of the startup stuff that you would normally have to click through and do. One other extra thing I'm doing here that we didn't see before as well is these volumes. Now, this is also really important because what this does is it allows us to persist our configuration and resources that we develop within Ignition because I'm mapping that Docker volume directly to the Ignition data directory.
38:02
Adam: That means if anything happens to this container — it gets removed, completely deleted, it's gone — we can still re-spin it up. It'll remap to this volume and go back to that configuration, and we will not have lost everything that we configured on our gateway. A lot of nice stuff there. You can also see that I've got other applications running in my Compose file. I've got a Postgres image that I'm spinning up a container for. This could be any other database that you want to use — if it's Microsoft SQL Server or MariaDB — anything that you can get an image for, basically.
38:43
Adam: Another nice thing about those Compose files is you can basically create a stack of all of the different applications you want to run integrated with each other in one file. We'll talk about the Compose file's name itself here quickly too. This docker-compose.yaml file name is important because Docker Compose actually knows to run that specific file when you run it within a specific directory. You'll see if I open up these other folders, they all have their own unique docker-compose file. And that's because when I run any Docker Compose commands within those directories, they know exactly which file to run based on that name. The first thing we'll see here — about why I was saying I really like VS Code for — is I can have my File Explorer here, right-click right on it, open in a terminal, and that terminal opens up right in this nice window where I can see my files, my terminal, and my Compose file opened all in one. You'll see that I'm in that webinar directory.
39:45
Adam: And if I do a docker-compose up, run it in detached mode again like I mentioned, it knows exactly which file to use because of that specific name — and it’ll start up these two services that we created with Ignition and Postgres. Another reason I really like VS Code for my Compose files is because you can get a ton of extensions for it. You'll see I have a whole lot going on here, but we're just going to look at the Docker one today, which gives me the little Docker whale on the left.
40:18
Adam: We go to that guy. You can see that I have information on all my containers. A bunch of ones that we're not using currently are turned off, but you can see the ones that I have started up for my little webinar Docker Compose file here. You'll also see we have the same ability to do a start and a stop and remove from the extension here as we could do in that Docker Desktop application. We also have similar types of information on all of our images and volumes and networks and stuff here. I really like that Docker engine for that. If we go to localhost:8088 on our web browser, we go right to this gateway, and you'll see that it just navigated me directly to it. I didn't even need to go through and set up the username and password and all that stuff you would normally do — because I automated that in all of those environment flags in my Compose file.
41:11
Adam: One last thing I'm going to leave you with here on the Docker front is that as great as it is for your development and testing, Docker is also a great and legitimate deployment method for use in production that we have plenty of customers doing. However, if you are going to license a Dockerized Ignition instance, you should be using our eight-character keys. Now, these are different from our normal six-character keys because this is what we call a leased licensing method. Meaning you still just buy these licenses once, but these licenses have to reach out to our licensing server on a certain time basis.
41:48
Adam: The main reason that this is recommended for these is because this licensing model is not tied to the specific hardware of the machine — and because of that, they're better for containerized Ignition environments, as containerizing these services also decouples them from that underlying host machine's hardware in a similar fashion. That's all I had today for my stuff on the Designer and in Docker. I know Reese has some really cool Exchange resources to show off to you next, so I will pass it back to him.
42:24
Reese: Yeah, fantastic. That's such a huge thing to showcase. We use Docker all the time internally. It's fantastic — especially for dev environments — to spin up instances, test things out, and not have to install a whole version of Ignition. You can spin it up, tear it down, all that good stuff. Yeah, for the next section here, can you see my screen again there, Adam? The designer?
42:48
Adam: Yeah, we've got you.
42:49
Reese: Perfect. I wanted to show off some Exchange resources, like Adam said. And so what the Exchange is — if you have never heard of it — is think of it as a public repository to upload Ignition resources that really anybody can utilize. And what I want to do here is just highlight three of those resources. I specifically picked these Exchange resources for a few reasons. The first is they don't have as many downloads as some of the other resources — and so we're sticking with the webinar theme of hidden gems. Maybe some folks aren't as aware of these, but they still have some really nice functionality to take your project to the next level. And then, in addition to the polish they might add, they also introduce some more complex Web Dev topics. I get questions all the time on, “Hey, how can I use JavaScript or CSS or HTML in my project?” And hopefully these three resources can give you an idea on A, how to do that, and B, if you're brand new to it, just learning about some of those technologies.
43:55
Reese: SO, let's kick things off with the Copy to Clipboard resource. This one was created by Conner Futa — he's an application engineer internal to Inductive Automation. This resource uses the Web Dev Module to run JavaScript, HTML, and CSS all within a Web Dev resource. Before we dive into development and see the nuts and bolts behind this, it's always good to see what the functionality of this is. This is a different project that I brought on — different gateway. But we'll go ahead and throw this into preview mode with our toggle there we learned earlier, and we'll just say “webinar.”
44:27
Reese: What this resource is going to do when we click this — it's going to take text within a Perspective session and copy it to the client's clipboard — to the machine running the client. Now I can paste this, of course, anywhere. Really valuable in a lot of different use cases. But think of a use case like this: some of you might have an OEE dashboard in your facility or some reporting dashboard. A lot of times an OEE dashboard is keyed off of three main parameters: your start date, your end date, and your machine ID.
45:07
Reese: What you can do is you can bake those into the URL as URL params and dynamically build this gateway URL with those parameters and then send those to a coworker. They can send it via Teams or Slack or whatever you have, and they can open up that same dashboard — the exact same dashboard that you're looking at. Of course, there's a lot of different use cases for copy and paste, but a really nice resource to be able to take text within Perspective and bring it to the client. But let's go ahead and check out the resource itself.
45:36
Reese: You'll notice that it is a Web Dev resource, so you would have to have the Web Dev Module. But you can see we're using HTML in here, we're using JavaScript here — we're adding an event listener (the click event listener) and copying that to the clipboard of the machine. And we're also using CSS here. These are examples of how you can create your own features and functions in addition to all the great features and functions that we have within the Perspective Module.
46:18
Reese: The next resource that I want to show off here is the Rolling Menu. The Rolling Menu was created by Nicoli Liedtke — and hopefully I didn’t butcher your name, Nicoli. I really do appreciate you throwing this on the Exchange. It's a really cool resource, and it shows off some common CSS — to add shadow boxes, on-hover transitions, and more — for a fresh take on navigation strategy.
46:40
Reese: Let's go ahead and open this one up, double-click on this guy, and I'll toggle this into preview mode. We've got our standard typical hamburger-type icon, but when we hover on this, it expands out. When we click, these icons roll out from underneath the icon. You can even see this hamburger menu changes to an X. Kind of a cool transform there. And then when we hover over these other navigation options, you can see — if I keep hovering — there's a cool pulsing effect in the background as well.
47:15
Reese: A really nice way to add some flavor there, some interaction for the end user that just... yeah, it’s a nice polish to your project. And so what we've done here — if we click on the Home icon — you can see that the class we're using is called “navball,” and that's being defined inside of our style sheet — the Advanced Style Sheet.
47:35
Reese: The Advanced Style Sheet is something that's been added recently. If you don’t have this style sheet, you can right-click on Styles, and there will be an “Enable Advanced Style Sheet” option. Of course, I already have it enabled, so that’s why it’s not showing as another one. But inside of this, you can see this is all CSS that Nicoli has created.
47:55
Reese: And you can — even if you look closely — here’s the navball style that I was just showing you on that icon. It’s always prefixed by the .psc, which stands for Perspective Style Class. And that allows Perspective to know that we can use this style class essentially. But you can see all the styles are defined here.
48:13
Reese: We even have some pseudo-classes down here for different actions — for on-hover. Remember when we were hovering, it had that pulsing effect? That’s using this animation of the neon navball, which is using this keyframe up here. A lot of different things — a lot of different concepts inside of the CSS — that you could, A, just take and use in your project, or B, just take and learn and figure out and tweak and adjust to maybe an implementation that you’d like in your project.
48:46
Reese: And finally, the last resource that I wanted to mention here is the CSS Animation Guide: A Robot Example. This one was created by Mike Bordiakov — he’s also an application engineer, similar to Conner Futa, that I mentioned earlier with the Copy to Clipboard resource. But this specific CSS animation guide uses animations to move a robot in a Perspective session.
49:10
Reese: I really like this resource — and one of the reasons I picked it is it’s a really great intro to CSS and how to use it within Perspective. It has a few different pages that get more complex as you go. And so it’s a great place to — no matter where you are in your CSS experience — it’s a great place to learn and grow. The best way to show this one would be to actually open it up in a session. Go ahead and launch this session; bring it over here.
49:35
Reese: You can see there’s a Basic, and Intermediate, and Advanced. And so we can play around with... this is a single axis for a robot arm. You can see as I click on these different angles, you can see the CSS updates over here. You can also change the duration on how long it takes for that arm to move.
50:00
Reese: Jumping over to the intermediate one, you can see as I click through some of these arms, it’s changing the angle at which each of those arms are. Of course, we can still do the same functionality — it takes longer now for that angle one or the arm one to move. And then we can choose to display the part and all that good stuff.
50:20
Reese: And finally, there’s an Advanced tab. This one is a really cool example of how to use these animations in an actual project and show, maybe even, a process of a robot exchanging a part. You could absolutely take this and use it in your project if you do have robots. But just a really great example of using CSS and animations there.
50:43
Reese: And I also mentioned up top here — there’s a description of what’s going on, but it also gives you where and how this is configured within the Designer. Definitely check this one out if you’re new to CSS or even have a little bit more experience and want to see how Mike went ahead and designed this.
51:08
Reese: A really great resource there. Yeah, there you go — three resources that you may not be aware of on the Exchange that can really help take your Ignition projects to the next level. All right, that takes us to the end of our tricks and tips there. I’m going to bring the slides back on over here. All right, so just to recap here — just some of the things that we talked about. These are some of the things in the designer that we mentioned that you can utilize inside of your project. Yeah, some of the different things we talked about today: Perspective development tips, some tools and tips for troubleshooting with the loggers that Adam mentioned, and then you dove into Docker and talked about that — some really great things to consider there. And then we just talked about the Exchange resources. These are some of them that I like. I know there’s a ton — there’s over 450 now. So definitely check those out. There’s a lot of great things to help speed up your development there.
52:16
Reese: And then just a few additional resources. I know, Adam, you mentioned this when you were talking about Docker, but we do have an Inductive University elective that you could take advantage of that gets you going with Docker — really basic stuff. And then the Ignition Docker image on our Docs page has a ton more information and details on how to do different things within that containerization. But this whole time we’ve been talking about developing Ignition. If you’ve never tried Ignition, we’ve got great news. You can actually download a free trial today off of our website. It’s a free download. It only takes about three minutes to download that. You can run the installer and use it in trial mode for literally as long as you want — develop a whole project as a proof of concept, and you can dive right in and explore the platform and try out the tips and tricks we just showed you here.
53:05
Reese: In addition, we also alluded to Inductive University a couple of times, which is a free online training website with hundreds of training videos. So, you can not only download Ignition, but you can learn Ignition with Inductive University — step-by-step, at your own pace. And there’s also a comprehensive online user manual that you can refer to at any time — the Docs page that we’ve been mentioning there, docs.inductiveautomation.com. Lots of great resources to get you up and running there.
53:36
Reese: A little bit on reaching out for support — for those of you who may be outside of North America, we also have a network of international Ignition distributors who provide business development opportunities, sales, and technical support — all within your language and your time zone. If you want to learn about the distributor in your region, definitely check out their website listed on the screen here. Or you can contact our international distributor manager, Igor Karmadonov. If you’d like to speak with one of our account representatives here at our headquarters in California, please call 800-266-7798. And to reach out to our office in Australia, the number on the screen down there is 1-300-108088.
54:25
Reese: With all of that being said, let’s get to the Q&A. As a reminder, you can type your questions in the Question area of the GoTo Webinar control panel. If you have comments, you have tips — love to hear those. I’m going to throw it over to Adam to kick us off on the Q&A side of things.
54:41
Adam: Yeah, thanks, Reese. We had a couple of questions that came in early that I’m going to tackle first. We had a question from Sridhar, who says, “Often we work with legacy SCADA systems from Siemens. Any tips or tricks for working with them and Ignition?” Basically, we do see a lot of Ignition integrated with other applications, including SCADAs. The most common method that we see for this is probably OPC UA. But if your SCADA has other options like MQTT or even a RESTful API, they’re worth exploring as well. They’re both great methods for integration with Ignition.
55:17
Adam: If you’re wanting to connect to a Siemens device specifically, we do have a device driver for that, and OPC UA is an option sometimes as well. However, the only way to currently read symbolic tags and access optimized blocks is with that OPC UA connection from the Siemens devices. However, the updated Siemens device driver in 8.3 will support both of those when connecting through our device driver. Sridhar, hopefully that helps.
55:42
Adam: Had another question from Morten that was an early one that came in. It says, “How do I size the server running Docker?” This really does depend on how much you’re looking to run on it — like just Ignition or other applications or how many Ignition gateways. But basically, it should have enough resources for each containerized application you’re running. Containers have full access to their host resources just like any application you’d be running on the server — unless you specifically put limits on them within Docker, which you can do.
56:20
Adam: But for Ignition specifically, we have the same guidelines for resources laid out in our Server Sizing and Architecture Guide that we post. It’s in our Resources — you can search our webpage in the Resources section, and you can find that Server Sizing and Architecture Guide. That’s a great place to look for sizing those resources.
56:44
Adam: The Ignition containers themselves do come with a -m command that you can use to set that max Java heap size in the config file automatically. We do recommend doing that, right? If you’re going to deploy these. How to use that is also documented in our Docker image page of our manual that I mentioned previously — and that was in the slide.
57:08
Adam: Couple new questions that have just come in. I see we have a couple from Andrew asking if we’re going to share an export of the project and a copy of the YAML. I think we could probably share both of those things in some way. Not sure...
57:24
Reese: Yeah, we just need to... If they want to grab that, we’d have to send that directly to them via email. We could absolutely do that. Just drop in your email or note that you are interested, and we can send a zip to folks. But we are out of time — Adam, I know there are a ton of questions in here, and I apologize we’re not going to be able to get to them all in this webinar. But I believe we are going to try to answer all of these questions after. Hopefully, we can get to your questions soon. Be watching your email there.
57:56
Reese: But just to wrap things up here really quickly — we do really appreciate you all joining us for this webinar, and we really hope you have a fantastic day.
58:11
Adam: Yes. Thanks, everybody.
Want to stay up-to-date with us?
Sign up for our weekly News Feed.