Developer Blog

27/03/2025 by Mattias Busck

Introducing CanKing 7 GUI Extensions

What are CanKing 7 GUI Extensions

CanKing 7 GUI Extensions are graphical views in Kvaser CanKing that allows anyone to extend the user interface with their own web-based components. Buttons can be created to send messages and create various kinds of grids and gauges to display information received from CAN buses. 

How do I create extensions

The technology used to develop GUI extensions in CanKing is React. React is a JavaScript library for building user interfaces. By using web technologies, CanKing can be fast and secure since web based apps, including games, have both these requirements.

CanKing API and React

Documentation

The CanKing GUI Extensions API defines Kvaser specific components that an extension can use to send and receive CAN messages and interact with CanKing UI and service. 

Other definitions and concepts, like Hooks, are from React itself. A good starting point for React is https://react.dev/learn 

It is important to know these concepts when reading the API documentation and implementing an extension. 

This opens up a web browser window where you can navigate the API. 

Available Modules

The API is divided into separate modules. Currently, they are controls, hooks, icons, ipc and models.

Controls

These are functions, types and interfaces for UI control components implemented as React components. One example is the CanIdentifierControl which creates a UI control for editing a CAN identifier. 

Hooks

This module defines the React Hooks. These are functions, all starting with ‘use’ (see suggestions below), that can provide callbacks into a component when an event has happened and also provide functions to update data. 

An important hook is useProjectData which lets an extension store and load its settings in the CanKing project(*.ckproj) file. 

Another hook is useNewMeasurementData which can deliver CAN messages into extension component like a trace window or a visual gauge. 

Icons

This module includes icons that can be used in the CanKing UI. 

IPC

This module implements the Inter-Process Communication (IPC) that interacts with the CanKing service. Example: 

- sendCanMessage(  
        channelId: string,  
        canId: number,  
        data: number[],  
        ...flags: [CanFrameFlag](../enums/models.CanFrameFlag.html)[],  
    ): Promise<void>

Another function is updateSource which allows an extension to update properties of a CAN channel, like bus parameters. Note that the hook useMeasurementSetup needs be used used to get updated about the current bus parameters.

Models

The models module contains the types, classes, interfaces, enums, etc. A typical example is the Frame in useNewMeasurementData .

Creating An Extension

Installing tools

To get started, you need CanKing 7 and drivers. You also need NodeJS and an editor. The instructions at Kvaser CanKing GUI Extensions SDK explains the details, but in short, you need:

  1. Kvaser Drivers
  2. CanKing 7
  3. NodeJS
  4. Visual Studio Code

Using Npm to create a new extension

  • Make sure NojeJS is installed and in the PATH for your command line.
  • Use the command line to create the extension with npm : npm create @kvaser/canking-extension@latest

(press return to make the default choices) 

C:\Users\mabu\OneDrive - Kvaser AB\proj\CanKing-7-GUI-Extension-Guide>npm create @kvaser/canking-extension@latest

> npx
> create-extension

√ Project name: ... my-ck-extension
√ Package name: ... my-ck-extension
√ Display name: ... MyCkExtension
√ Package description: ... A CanKing GUI extension
√ Package author: ... Kvaser FAE

Creating a new CanKing extension in C:\Users\mabu\OneDrive - Kvaser AB\proj\CanKing-7-GUI-Extension-Guide\my-ck-extensi
on.


A project for extension my-ck-extension has been created successfully.

npm has now created a directory structure named my-ck-extension (the selected project name). We move into this directory.

cd my-ck-extension

Use version control

In this directory a number of files has been created. To keep track of our changes, Let us add them to source control using git. 

git init
git add .
git commit -m "Create CanKing7 extension from template"

Installing dependencies

Since our extension uses NodeJS, we need to install the packages that our extension uses. While in the my-ck-extension directory, use:

npm install

This installs all the necessary packages in a new directory named node_modules.

Running The Extension

Load your code

Start VS Code using a command shell from your extensions folder: 

  code .

Start / debug the extension

  • From Visual Studio Code, you can start debugging if you have the extensions installed:
  • You can also use a terminal:
npm run start

Adding the extension in CanKing

After a few moments, CanKing 7 starts and the new extension is now available in the Workspace’s “Select View” menus: 

In the workspace, a new view showing our extension appears: 

Examining The Source

React

CanKing 7 uses TypeScript, which is a statically typed superset of Javascript that adds type definitions. 

Note that tutorials about React can use either JavaScript or TypeScript, so make sure you use the TypeScript version which requires stating the types of your variables. 

Javascript, Typescript and XML

To see what the extension looks like, we will start examining the file src / WorkspaceView / index.tsx

my-ck-extension
└───src
    └───WorkspaceView
        └───index.tsx

This file has the extension .tsx which tells us two things:

  • t indicates that this is TypeScript, a statically typed superset of Javascript that adds type definitions.
  • x says that this is an XML-like syntax extension to JavaScript. 

Having type definitions prevents errors early and allows code editor to look up data-structures. An example is the interface IProjectData which defines which data from our extension gets saved in the CanKing 7 project files. Here we state that the parameter channelId must be of the string type.

// If any data should be stored in the project file then add it to this interface
interface IProjectData {
  // This is an example showing how to store the selected channel id to the project file
  channelId: string;
}

The WorkspaceView Function

Our Index.tsx implements our CanKing 7 extension by defining a function named WorkspaceView. The function starts with defining variables in a standard way:

function WorkspaceView() {
  // Get this view's unique id from search params
  const [searchParams] = useSearchParams();
  const idString = searchParams.get('id');

At the end of the function we return the data structure which defines the React component. Here we can write an XML structure directly thanks to the syntax extension. 

Curly braces, as in {icon} allows us to embed expressions that use variables in its scope. We are using icon from the top of the file:

import icon from '../assets/icon.png';

We see that our extension consists of a Box component on the top level:

    return (
        <Box aria-label="canking-extension-view" margin={1}>
            <h3>Add your elements here!</h3>
            <div>This is an example how to embed an image:</div>
            <img src={icon} height={50} />

Sending a CAN Message

To send a message, a Button is first imported.

import { Box, Button } from '@mui/material';

It is then added inside the WorkspaceView function with its onClick prop set to onSendCanMessage.

<Button onClick={onSendCanMessage}> Send CAN Message </Button>

The callback onSendCanMessage is created with the useCallback React hook.

// A callback that will send out a CAN message on the selected channel with the specified CAN id
  const onSendCanMessage = useCallback(() => {
    if (projectData.channelId !== '') {
      const flags =
        sessionData.canIdType === 'extended' ? CanFrameFlag.CAN_FRAME_FLAG_EXT : CanFrameFlag.CAN_FRAME_FLAG_STD;
      sendCanMessage(projectData.channelId, sessionData.canId, [0x55], flags);
    }
  }, [projectData.channelId, sessionData.canId, sessionData.canIdType]);

The reason is that sendCanMessage needs access to a channelId (string) to tell the CanKing 7 service which channel to send on. Is it best stored in the projectData which is available to all the components in the Extension since is defined at the top level. It is also saved and loaded with the .ckproj file.

// Use the useProjectData hook to serialize/deserialize your view data to the project
const { projectData, setProjectData } = useProjectData<IProjectData>(id, defaultProjectData);

To set the channelId, CanChannelSelectControl, also provided by the CanKing 7 SDK can be added. For it to work, the component needs to:

  1. Know which selection to display when it is created.
  2. Act on changes to the selection and store the selection outside itself.

For this the SDK defines the interface CanChannelSelectControlProps which allows configuration parameters to be passed to the control.

(By React convention the name of the interface is the name of the component + Props).

The onChannelIdentifierChange prop accepts, among other parameters, a callback function that will be called when the user selects a CAN channel. It also has the channelIdentifier to get its initial value.

<CanChannelSelectControl
    channelIdentifier={projectData.channelId}
    onChannelIdentifierChange={onChannelIdentifierChange}
    hideSectionControl
  />

The onChannelIdentifierChange callback function is defined as follows:

  // A callback that will get the new selected channel id and save it to the project data
  const onChannelIdentifierChange = useCallback(
    (channelId: string) => {
      const data = { ...projectData };
      data.channelId = channelId;
      setProjectData(data);
    },
    [projectData, setProjectData],
  );

This concludes an initial examination of the new extension feature.

Author Image

Mattias Busck