# How can I call a "get\_screenshot" method from inside a SFC?

**URL:** <https://forum.inductiveautomation.com/t/how-can-i-call-a-get-screenshot-method-from-inside-a-sfc/98894>\
**Category:** Ignition\
**Tags:** vision\
**Created:** [November 20, 2024, 8:54pm UTC](https://forum.inductiveautomation.com/t/how-can-i-call-a-get-screenshot-method-from-inside-a-sfc/98894 "2024-11-20T20:54:14Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![sherman](https://avatars.discourse-cdn.com/v4/letter/s/e5b9ba/32.png) [@sherman](https://forum.inductiveautomation.com/u/sherman)\
**Post date:** [November 20, 2024, 8:54pm UTC](https://forum.inductiveautomation.com/t/how-can-i-call-a-get-screenshot-method-from-inside-a-sfc/98894/1 "2024-11-20T20:54:14Z")

</div>

I wrote a method (below) for nabbing screenshots from a Vision client. It works (paired with the appropriate helper methods / gateway messageHandler for writing to a filesystem), but I want to call it from within a SFC rather than from the vision client itself and I am pretty sure it will misbehave.

Is it possible to augment this function such that it grabs the screenshots from the vision client that dispatches the SFC in the first place? Almost like a reverse messageHandler.

```python
def get_screenshot(run_name, shot_number=None, window=None, project="tb1", ext='png'):
	from java.awt import Robot, Rectangle, GraphicsEnvironment
	from javax.imageio import ImageIO
	from java.io import ByteArrayOutputStream
	import system
	import os
	import base64

	# Define the base directory to save the screenshots
	file_dir = svc.common.work_dir(project=project, name=run_name, fs='ignition')
	print(file_dir)
	print(gateway.ensure_dir(file_dir))

	# Get all available screens
	graphics_env = GraphicsEnvironment.getLocalGraphicsEnvironment()
	screens = graphics_env.getScreenDevices()
	
	# Initialize Robot for screen capture
	robot = Robot()

	# Iterate over each screen and capture it
	for index, screen in enumerate(screens):
		# Define the bounds for the current screen
		screen_bounds = screen.getDefaultConfiguration().getBounds()
		rectangle = Rectangle(screen_bounds.x, screen_bounds.y, screen_bounds.width, screen_bounds.height)
		
		# Capture screenshot for the current screen
		screenshot = robot.createScreenCapture(rectangle)
		
		# Create a unique filename for each screen
		file_name = "{}_shot{}_screen{}".format(run_name, shot_number, index)
		file_path = file_dir + "/" + file_name + "." + ext # assume linux since this goes to gateway
		print(file_path)
		
		# Convert the BufferedImage to a Base64 string
		byte_stream = ByteArrayOutputStream()
		ImageIO.write(screenshot, ext, byte_stream)
		image_bytes = byte_stream.toByteArray()
		encoded_image = base64.b64encode(image_bytes).decode('utf-8')
		
		# Write the encoded image to the specified path on the gateway
		gateway.write_image(file_path, encoded_image, ext=ext)
	
	return file_dir # Returns the directory where screenshots are saved

```

---

<div class="post-metadata">

**Author:** ![Kevin.Herron](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/kevin.herron/32/7259_2.png) [@Kevin.Herron](https://forum.inductiveautomation.com/u/Kevin.Herron)\
**Post date:** [November 20, 2024, 9:07pm UTC](https://forum.inductiveautomation.com/t/how-can-i-call-a-get-screenshot-method-from-inside-a-sfc/98894/2 "2024-11-20T21:07:38Z")

</div>

You might be able to do something like:

- put the client session id into the parameters dict of the `system.sfc.startChart` call
- when you need the screenshot eventually, use the id to target `system.util.sendMessage` to that client
- the message handler in the client will then run your screenshot function

---

<div class="post-metadata">

**Author:** ![sherman](https://avatars.discourse-cdn.com/v4/letter/s/e5b9ba/32.png) [@sherman](https://forum.inductiveautomation.com/u/sherman)\
**Post date:** [November 20, 2024, 9:10pm UTC](https://forum.inductiveautomation.com/t/how-can-i-call-a-get-screenshot-method-from-inside-a-sfc/98894/3 "2024-11-20T21:10:04Z")

</div>

Thanks I will try this

---

<div class="post-metadata">

**Author:** ![sherman](https://avatars.discourse-cdn.com/v4/letter/s/e5b9ba/32.png) [@sherman](https://forum.inductiveautomation.com/u/sherman)\
**Post date:** [November 20, 2024, 9:33pm UTC](https://forum.inductiveautomation.com/t/how-can-i-call-a-get-screenshot-method-from-inside-a-sfc/98894/4 "2024-11-20T21:33:20Z")

</div>

> [@Kevin.Herron](#):
>
> system.util.sendMessage

I am using a system.util.invokeAsynchronous when I do this from a button -- is that necessary when calling in this manner? Followup, would I ever want to invokeAsynchronous from within a SFC?

---

<div class="post-metadata">

**Author:** ![Kevin.Herron](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/kevin.herron/32/7259_2.png) [@Kevin.Herron](https://forum.inductiveautomation.com/u/Kevin.Herron)\
**Post date:** [November 20, 2024, 10:08pm UTC](https://forum.inductiveautomation.com/t/how-can-i-call-a-get-screenshot-method-from-inside-a-sfc/98894/7 "2024-11-20T22:08:35Z")

</div>

> [@sherman](#):
>
> I am using a system.util.invokeAsynchronous when I do this from a button -- is that necessary when calling in this manner?

Probably not... I don't think the message handlers run on the UI thread, which is presumably why you were doing this in the first place.

> [@sherman](#):
>
> Followup, would I ever want to invokeAsynchronous from within a SFC?

Probably not, though I will generally advise most people against using `invokeAsynchronous` without compelling reason 🤷

---

<div class="post-metadata">

**Author:** ![sherman](https://avatars.discourse-cdn.com/v4/letter/s/e5b9ba/32.png) [@sherman](https://forum.inductiveautomation.com/u/sherman)\
**Post date:** [November 21, 2024, 7:43pm UTC](https://forum.inductiveautomation.com/t/how-can-i-call-a-get-screenshot-method-from-inside-a-sfc/98894/8 "2024-11-21T19:43:24Z")

</div>

Fun one: it seems to not work because of a Java heap error but it isn't logging that into the gateway console. Can only see it if I engage the parent SFC via a vision client.

Do I increase the gateway allocation or the vision client allocation or both?
