Musson Industrial's Embr-Periscope Module

No, unfortunately there isn’t a way to do lazy loading for views.

I think the virtualized feature should work though, but I can’t say I’ve tested it; any feedback you could provide about it would be helpful.

Think I came up with a solution. Atleast it seems to work quite good.

I load images from a database stored as varbinary and I want to stop this if the Swiper contains alot of images.

  • Added "index" to params on the Embedded Views (Ignition function).
  • Added "load"-bool to params on the Embedded Views with a change script.
def valueChanged(self, previousValue, currentValue, origin, missedEvents):
	if currentValue.value == True and self.view.custom.image == "":
		import base64
		sqlParams = {"imageId": self.view.params.imageId}
		image = system.db.runNamedQuery("getImage", sqlParams).getValueAt(0,0)
		self.view.custom.image = base64.b64encode(image)
  • Set "load" to true for the first 3 views and the rest to false when creating the instances.
  • Added a Custom Method to the view with Swiper.
def realIndex(self):
	component = self.getChild("Swiper")
	
	proxy = component.getJavaScriptProxy("swiper")
	currentIndex = proxy.runBlocking('''() => this.realIndex''')
	
	if currentIndex != self.view.custom.currentIndex:
		self.view.custom.currentIndex = currentIndex
		
		for i in range(3):
			self.getChild("Swiper").props.instances[currentIndex + i].viewParams.load = True
  • Calling the Custom Method through a "onPointerDown" event.
def runAction(self, event):
	self.parent.realIndex()

This seems to work fine for me. But I'm not really sure how effecient it is. And depending on the Swiper settings it could cause the message to not get triggered enough (more dots (have to preload more then +2), or with a scroll etc.). If there was a better way to get the current index it would probably work better.

EDIT: Used Message Handler on the Embedded Views to load the images but felt wrong to send out a message that ~100 views handled on each Swiper-click. This solution feels better, but I'm open for a better one :slight_smile:

Hi @bmusson,

I'm trying the chart and periscope module on ignition 8.3 beta1:
but is seems it's not compiled for 8.3.0-beta1 yet:

Error
Module "Embr Charts" requires Ignition 8.1.33 (b0) and is not compatible with Ignition 8.3.0-beta1 (b2025072515)

Do intend to release a version of the module for the 8.3 beta?

Yup. I’m out on vacation for a while, but getting Embr compiling for 8.3 is a high priority once I get back.

5 Likes

Embr-Periscope for the Ignition 8.3 beta can be found here:

4 Likes

Thank you.

1 Like

Hey @bmusson, it'd be cool if you could add a calendar component to select date ranges into this module :slight_smile:

I added an idea on the github:

Really, this should be an idea for the Ignition codebase itself...

1 Like

Mantine has a good selection of date/time selection components, thoughts?

I could see these being included together in a Mantine components module.

1 Like

That library looks really good, I haven't found the date range selection yet, but this looks really useful

I found the date range picker, doesn't include time though :thinking::

Looks like a really nice library though!

I think using the combination of the date and the time picker component they have would be more than enough for my use cases. The time grid also interests me!

Release Notice

Embr v8.1 - 2025.10.31
Embr v8.3 - 2025.10.31

Minor Changes

  • 3a45993: Modules no longer include kotlin-stdlib.
    • All modules now rely on the Kotlin standard library provided with Ignition.
  • 7af46dd: (Flex Repeater +): Clear non-running ViewModel instances from cache on access.

Patch Changes

  • c7b1b13: (Flex Repeater +): Fix a bug causing the creation of extra ViewModels for non-existent view instances.
  • Updated dependencies [59bafb8]
    • @embr-jvm/core-common@0.7.1
    • @embr-jvm/core-designer@0.7.1
    • @embr-modules/periscope-web@0.10.0

Good morning,
I’m trying to understand whether the Portal component is what I need for the project I’m working on.

At the moment I have about 20 numericFields that need to be filled in. For each field I have 3 bits that indicate whether no data has been entered, whether the value is below the minimum range, or above the maximum range. Based on these flags, I currently change the border color of each numericField.

I’m struggling to understand whether this component is actually what I need to improve the user experience.

For example, step by step, my first question (aside from getting it to work at all) is this: do I need to create one Portal component for each numericField?

A second question: where can I find a working example to start from?

Thanks for the support, and compliments on the work!

Hi everyone,

I’m currently using the the periscope module and I’ve encountered an issue at a plant where the network connection is particularly slow. I’ve started seeing the following error in the gateway logs:

After some troubleshooting, I’ve isolated the cause: the error is directly related to the use of the toast object. If I exclude it, the logs remain clean and the errors disappear immediately.

Has anyone else experienced similar issues with high-latency connections? Do you have any advice on how to manage these notifications or configure the object's timeout to prevent the gateway from triggering errors on low-performance lines?

Thanks in advance for your help!

On the browser, are there any errors in your developer console?

Looking at the Periscope code, I can see a related timeout with a 30 Second duration... How slow a network are we talking?

This seems more like a failed javascript task on the client not responding, want to share the javascript youre running?

Thanks for the help!

I've tried reproducing the issue via a remote connection, but everything seems to work fine for me right now, so I don't have the console logs yet. I'm going to check later if it's a machine-specific problem.

One thing to note: latency is quite high, with a ping of about 300ms.

This is the function I'm using:

def toast_message(text, locale, position="top-center", toast_type="info", auto_close=5000):

translated_text = translate_message(text, locale)

options = {
    "type": toast_type,
    "position": position,
    "autoClose": auto_close,
    "hideProgressBar": False,
    "newestOnTop": False,
    "closeOnClick": True,
    "rtl": False,
    "pauseOnFocusLoss": False,
    "pauseOnHover": False,
    "theme": "colored"
}

if toast_type == "success":
    options["style"] = { "background": "#1F7A1F", "color": "#FFFFFF" }

json_options = system.util.jsonEncode(options)
json_text = system.util.jsonEncode(translated_text)

return "() => { periscope.toast(%s, %s); }" % (json_text, json_options)

And I’m calling it like this:

system.perspective.runJavaScriptAsync(myFuncPath.toast_message(text= "myText", locale = locale, toast_type = "success"))

Don’t do string substitution into the function body, instead pass arguments for both your translated text and style. This section of the documentation bas an example:

(Copied here for reference)


# Function with three parameters.
function = '''(param1, param2, param3) => {
    return param1 + param2 + param3.value;
}'''

def callback(result):
    system.perspective.print(result)

# The keys of the arguments dictionary are mapped to the function argument names.
args = {
    'param1': 10,
    'param2': 20,
    'param3': {
        'value': 30
    }
}

system.perspective.runJavaScriptAsync(function, args, callback)

But I do agree that this kinda looks like a network related issue.

1 Like

I’ve modified the code passing arguments, thanks for the suggestion.

Is there something I can change to avoid the error? Increase the timeout in some way for example?

No, the timeout is hardcoded.

If it is taking longer 30 seconds something is really wrong.

And there are no other errors in the gateway or the client?

1 Like

Actually, I don’t understand why it should take so long. I tried connecting to one PC and yes, it is a little bit slow, but it's not unusable.

At the moment, I have disabled the toast notifications for that specific plant. In the meantime, I am trying to dig deeper to see if it is a specific PC creating this problem.

Thanks for the support and also for the resources, they’re amazing.

2 Likes