Skip to content

Plugins

kmcnaught edited this page Aug 16, 2021 · 5 revisions

Table of Contents

About Plugins

If you want to add new functionality to Optikey, integrate with an external system, or even interact with an IoT enabled appliance in your home, plugins are the way to do it. By using plugins and dynamic keyboards, you can add keys that will interact with elements outside Optikey and do whatever you feel like.

Configuration

There is not much regarding plugins configuration - they are pretty straightforward and everything that you need is configured using Dynamic Keyboards. Please check Plugin Management for more information.

Dynamic Keyboard Plugin

The way to add your plugin into Optikey is to add it as a Dynamic Keyboard Plugin. Here is a sample configuration for External Program Plugin:

<DynamicKey>
	<Label>Notepad</Label>
	<Plugin>
		<Name>ExternalProgram</Name>
		<Method>RUN</Method>
		<Argument>
			<Name>command</Name>
			<Value>notepad.exe</Value>
		</Argument>
	</Plugin>
</DynamicKey>

A Plugin will have the same basic attributes as other dynamic keyboard keys as well as some properties that are exclusive to the Plugin:

  • Name: This is the unique identifier of the plugin within Optikey. You can find it in plugin sample configuration in management screen.
  • Method: The plugin method that will be called when this key is pressed.
  • Arguments: Each method has a list of arguments that will be passed to the method when calling it. Each Argument node has two attributes:
    • Name: The name of the argument. You must use the same name as defined in plugin documentation, available at Plugin Management.
    • Value: You can set a fixed value - like "notepad.exe" - or you can use the macro $scratchpadText to get the value from Optikey scratchpad (i.e., the text that is written in Optikey)

Please notice that not all arguments are required and some of them have default values. If an argument is not required or the default value works for you then you do not need to specify it in the xml.

More information on Dynamic Keyboards can be found at Dynamic Keyboards Page

Built-in Plugins

Optikey comes with a few built-in plugins. They provide basic features that enable you to integrate with external windows applications and HTTP based APIs.

External Program Plugin

This plugin will launch a windows application, or call a Windows command. It runs the command that you provide as a method argument as if we were typing it in a command prompt. Despite being simple this plugin is pretty useful if you want to start other applications directly from a key press, instead of having to use the double click mouse action.

Let's assume that you want to start Skype in order to chat with a friend. That would be look like this:

<DynamicKey>
	<Label>Skype</Label>
	<Plugin>
		<Name>ExternalProgram</Name>
		<Method>RUN</Method>
		<Argument>
			<Name>command</Name>
			<Value>"C:\Program Files (x86)\Microsoft\Skype for Desktop\Skype.exe"</Value>
		</Argument>
	</Plugin>
</DynamicKey>

Adding this DynamicKey to a dynamic keyboard will run Skype when the user presses this key.

If you want to add command-line arguments, you need a second Argument in your DynamicKey [supported from v3.0.6 onward]. For instance this key will launch Google Chrome and go straight to the BBC homepage. This is exactly equivalent to calling C:\Program Files (x86)\Google\Chrome\Application\chrome.exe www.bbc.com from the Windows Command Prompt.

<DynamicKey>
    <Label>BBC Website</Label>
    <Plugin>
        <Name>ExternalProgram</Name>
        <Method>RUN</Method>
        <Argument>
            <Name>command</Name>
            <Value>"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe"</Value>
        </Argument>
        <Argument>
            <Name>parameters</Name>
            <Value>"www.bbc.com"</Value>
        </Argument>
    </Plugin>
</DynamicKey>

You can find detailed description of the method and its arguments in the Optikey Plugin Management screen.

HTTP Call Plugin

This plugin will call a HTTP or HTTPS URI when the key is pressed. A common use case of this plugin is to integrate with an IoT enabled device, like a home automation system. This plugin has two methods, GET and POST, which call a HTTP/HTTPS endpoint using the respective HTTP verb.

Let's assume that you have a home automation system that changes the channels of your TV through a HTTP call. A possible configuration for this plugin key would be:

<DynamicKey>
	<Label>Football TV</Label>
	<Plugin>
		<Name>HttpCall</Name>
		<Method>GET</Method>
		<Argument>
			<Name>uri</Name>
			<Value>http://myhomeautomationuri/channel/567</Value>
		</Argument>
		<Argument>
			<Name>timeout</Name>
			<Value>1000</Value>
		</Argument>
	</Plugin>
</DynamicKey>

When the user presses the key Football TV, the plugin will place a GET HTTP call to the address http://myhomeautomationuri/channel/567 and wait up to 1000 ms for a response. Assuming that http://myhomeautomationuri/channel is your home automation system API address and 567 is the channel that you want to watch, when the key is pressed this command is sent to your home automation system and the channel will be switched to 567.

However, if your home automation is a little more complicated and requires an authentication token passed using a POST HTTP verb in order to get commands, another configuration would be:

<DynamicKey>
	<Label>Footbal TV</Label>
	<Plugin>
		<Name>HttpCall</Name>
		<Method>POST</Method>
		<Argument>
			<Name>uri</Name>	
			<Value>http://myhomeautomationuri/bedroomTV</Value>
		</Argument>
		<Argument>
			<Name>contentType</Name>
			<Value>application/json; charset=utf-8</Value>
		</Argument>
		<Argument>
			<Name>authorization</Name>
			<Value>Bearer aa375135-a465-4437-a0e9-62775c7e708a</Value>
		</Argument>
		<Argument>
			<Name>payload</Name>
			<Value>{"channel":567}</Value>
		</Argument>
	</Plugin>
</DynamicKey>

This will trigger a POST HTTP Call with the payload {"channel":567} and the header Authorization: Bearer aa375135-a465-4437-a0e9-62775c7e708a to your home automation system.

You can find detailed description of both methods and all their arguments in Optikey Plugin Management screen.

Writing your own Plugin

This section focus on developing your own plugin. You do not have to be a skilled programmer, as writing a plugin is not a complicated task. Basic knowledge of .NET is more than enough.

Setting Up

What you need to have installed in your computer:

  • Visual Studio. In this documentation, I am using Visual Studio Community 2017 version 15.5.2.
  • .NET framework version 4.6.
  • Optikey version 2.17.0 or newer.

In order to debug easily your plugin, it is recommended to checkout the Optikey source files as well and run Optikey in debug mode, however, it is not mandatory. You can instead configure Visual Studio to start an already installed version of Optikey and debug your code.

Coding

Open Visual Studio and create a new solution and project. Your project should be a Class Library (.NET Framework) project type. In this example, I am creating a new project called MyPlugin in a new solution called MyPlugins.

After creating your project, go to Project Properties screen and ensure that the Target Framework is .NET 4.6 and that the Default Namespace is JuliusSweetland.Optikey.*, where * is anything you want. In this example, we will be using JuliusSweetland.Optikey.MyPlugins

Ok, now that the basic project setup is done, let's create a new class. Let's name it MyPlugin:

As you can see, this class already has the required namespace prefix JuliusSweetland.Optikey.:

Now, it is just a matter of coding your method. Make it public, with no return value and getting only string parameter types (as many as you want). In this example, I've coded a simple method that opens the default browser and searches YouTube for a video:

Least but not last, we have to tell Optikey that this is a plugin, which methods it export, its arguments, etc. To do so, we must create a metadata XML file that will tell everything Optikey needs to know. If you want to publish a plugin to the community, I strongly advise you to write a detailed documentation, with samples. Remember that anyone can use this anywhere in the world. Create a Resources folder and create a file named metadata.xml:

Now write the metadata file describing the plugin. I recommend that you take the metadata file from a built in plugins (you can find one here) and change it. Notice that we can define as many plugins as we want in a single metadata file. In our YouTube example a valid metadata.xml file would be:

<?xml version="1.0" encoding="utf-8" ?>
<Plugins>
  <Plugin>
    <Id>YoutubeSearch</Id>
    <Impl>JuliusSweetland.Optikey.MyPlugins.MyPlugin</Impl>
    <Name>Youtube search plugin</Name>
    <Description>This is a plugin that searches for a video in YouTube.</Description>
    <Methods>
      <Method>
        <Name>SearchYoutube</Name>
        <Description>Searches youtube for a video</Description>
        <Arguments>
          <Argument>
            <Name>search</Name>
            <Description>Term that will be used to search YouTube for videos. You can use "$scratchpadText" as parameter value to search YouTube for what is written in Optikey scratchpad.</Description>
            <Sample>$scratchpadText</Sample>
            <Required>true</Required>
          </Argument>
        </Arguments>
        <SampleConfig>
          <![CDATA[<DynamicKey>
	<Label>Youtube</Label>
	<Plugin>
		<Name>YoutubeSearch</Name>
		<Method>SearchYoutube</Method>
		<Argument>
			<Name>search</Name>
			<Value>$scratchpadText</Value>
		</Argument>
	</Plugin>
</DynamicKey>]]>
        </SampleConfig>
      </Method>
    </Methods>
  </Plugin>
</Plugins>

Now there is just a few more tweaks in order to package correctly our plugin DLL... Click on metadata.xml file and change Build Action in file properties to Embedded Resource:

We need to add this newly created metadata file to our project as a Resource. Just go to project properties, select Resources tab on the left, click on create a default resources file and then drag metadata.xml file into the screen. Change the access modifier in the drop down box (combobox) to Public. You will see a screen like that:

That means that the metadata.xml resource was successfully added to your project. That's it! Finally, we can install and test our plugin.

Installing and testing

We have two options here. One is to copy the plugin DLL file to Optikey default plugin directory. You can find that default directory in Optikey plugin management screen. The other way is to change this directory to your plugin build directory. Unfortunately, every time you rebuild your plugin, you need to restart Optikey in order to load the new version - this is an improvement on the top of the list for future releases.

Whatever you choose to do, when you start Optikey and go to the Plugin Management Screen, you will see Youtube Search Plugin in the list:

Now, all you have to do is add this plugin to a Dynamic Keyboard and test it! You can try this by adding the following snippet to the BigHackerKeyboard (replace a previously existing key in the same column and line) or to any dynamic keyboard you want:

<DynamicKey>
	<Label>Youtube</Label>
	<Plugin>
		<Name>YoutubeSearch</Name>
		<Method>SearchYoutube</Method>
		<Argument>
			<Name>search</Name>
			<Value>$scratchpadText</Value>
		</Argument>
	</Plugin>
</DynamicKey>

Start Optikey, type something in the keyboard, press YOUTUBE key and the browser should pop-up with a YouTube search result, just like this one:

Clone this wiki locally