Qwik & Arduino with Johnny Five
Tags: qwik, arduino, frontend, javascript
Published: 2023-11-13 23:11:15

Some days ago I have shared some experiments I have recently done with Qwik and Arduino on my [LinkedIn](https://www.linkedin.com/in/fabiobiondi/) and [Twitter](https://twitter.com/biondifabio) profiles.

A lot of people asked me more details about it, so I wrote this article to explain what I did.

Anyway, as the post title suggests, we can control Arduino, Raspberry and other micro-controllers directly from a front-end application built in JavaScript 😱.


{% embed https://player.vimeo.com/video/883641389?badge=0&amp;autopause=0&amp;quality_selector=1&amp;player_id=0&amp;app_id=58479 %}

# Johnny Five 

Some times ago I have played with [johnny-five](https://johnny-five.io), a JavaScript Robotics & IoT platform.
In short words, we can communicate with our Arduino or Raspberry by using JavaScript with a very friendly syntax.

For example, to blink a LED you can :

1) Connect a LED to PIN 13 of your Arduino board:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/36d22ggysk0u3lbe6dpe.png)


2) Create a JavaScript module, i.e. `index.js`:

```ts
const { Board, Led } = require("johnny-five");

// connect your board
const board = new Board();

// when board is ready
board.on("ready", () => {

  // Create a standard `led` component instance
  const led = new Led(13);

  // "blink" the led in 500ms
  // on-off phase periods
  led.blink(500);

});
```

3) Run the code in your terminal

```
node index.js
```

> I have used [Node](https://nodejs.org/en/) v.18


Here you can find more details about the installation of Johnny Five and how the previous example works:

• [Johnny Five Get Started](https://github.com/rwaldron/johnny-five/wiki/Getting-Started) 
• [Johnny Five Examples](https://johnny-five.io/examples/)

---

# Qwik 

[Qwik](https://qwik.builder.io/) is a full-stack web framework to create super-performing and SEO friendly applications.

One of its most interesting features is the `server$` functions, that allow you to create a function that is always executed on the server.

> server$ is a form of RPC (Remote Procedure Call) mechanism between the client and server, just like a traditional HTTP endpoint but strongly typed thanks to Typescript, and easier to maintain. 
Source: [Qwik server$ Documentation](https://qwik.builder.io/docs/server$/)

Following I show you a very basic example of `server$` function:

```ts
import { component$, useSignal } from '@builder.io/qwik';
import { server$ } from '@builder.io/qwik-city';
 
// executed on server
const serverGreeter = server$((firstName: string) => {
  const greeting = `Hello ${firstName}`;
  return greeting;
});
 
export default component$(() => {
  // Signal to contains the input value
  const text = useSignal('');
 
  return (
    <>
      <label>
        Your Name:
        <input bind:value={text} />
      </label>
      
      <button
        onClick$={async () => {
          // invoke the server$ function 
          // passing the input text value
          // when button is clicked 
          const greeting = await serverGreeter(text.value);
          alert(greeting);
        }}
      >
        greet
      </button>
    </>
  );
});
```

# Blink LED with Johnny Five & Qwik


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y9efn43k1kpvgyg24yuo.jpg)

Since the Qwik `$server` function always run on server, we can use any package designed to run in a Node.js environment.

So my first thought was:

> _maybe I can use Johnny Five directly on Qwik to control my Arduino_

And yes, it worked! 😍

---

Let me show you how I did:

1) First, connect a LED to PIN 13 of your Arduino Board:

2) Create a new [Qwik Project](https://qwik.builder.io/docs/getting-started/):

```
# create the project
npm create qwik@latest

# Run the project 
npm run dev
```

This process creates a basic Qwik Project with a couple of routes.


3) Now we can open and update the default route component (`routes/index.tsx`):

* create a button whose click we invoke the server function

* import the "johnnyfive" package, create a Board instance and use its API to define the PIN 13 and blink the connected LED:

```ts
// routes/index.tsx
import { component$, useSignal } from '@builder.io/qwik';
import { server$ } from '@builder.io/qwik-city';

import five, { Board, Led } from 'johnny-five'

const board = new five.Board();

const arduinoBlink = server$(() => {
  // Define LED PIN
  const led = new Led(13);
  // Blink
  led.blink(555);
});


export default component$(() => {
  return (
    <>
      <button
        onClick$={async () => {
          // Blink LED
          // Invoke the server function 
          // when button is clicked
          await arduinoBlink();
        }}
      > BLINK LED </button>
    </>
  );
});
```

[Johnny Five Blink Example](https://johnny-five.io/examples/led/)



# LCD display

Johnny Five allow us to easily use sensors, LCDs, Servo / Motors, Joysticks and several other devices.

For example you can easily [write into a LCD display](https://johnny-five.io/examples/lcd/) as well:

```ts
// Define LCD PINS 
const lcd = new five.LCD({ pins: [7, 8, 9, 10, 11, 12] });
// Move the cursors to positio 0,0 and display a text
lcd.cursor(0, 0).print('Hello Qwik!');
```

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4bfoycgkwhx6vc3a27xm.png)


So, as you can imagine you can use this snippet of code in a Qwik `server$` function as we did to blink the LED.


1) First, we can create a JS module in which we write the functions that contains the logic to communicate with the hardware and that are invoked by the `server$` function:

```ts
// arduino.server.ts
import { server$ } from '@builder.io/qwik-city';
import five, { Board, Led } from 'johnny-five'

const board = new five.Board();

export const arduinoBlinkFn = () => {
  const led = new Led(13);
  led.blink(555);
};

export const arduinoLCDFn = server$((
  text1: string, text2: string
) => {
  // Define LCD PINS 
  const lcd = new five.LCD({ pins: [7, 8, 9, 10, 11, 12] });
  // display text1 in the first line of the display
  lcd.cursor(0, 0).print(text1);
  // display text2 in the second line
  lcd.cursor(1, 0).print(text2);
});

```

2) Now we can simply create the UI in Qwik using JSX syntax, adding a couple of text inputs and a button to send both texts to the device.

The `arduinoLCDFn()` server function is invoked when the button is clicked, passing the values of both text inputs.

```ts
// routes/index.tsx
import { component$, useSignal } from '@builder.io/qwik';
import { server$ } from '@builder.io/qwik-city';

import { arduinoBlinkFn, arduinoLCDFn } from '~/arduino.server.utils';

const arduinoBlink = server$(() => {
  arduinoBlinkFn()
});

const arduinoLCD = server$((
  text1: string, text2: string
) => {
  arduinoLCDFn(text1, text2)
});


export default component$(() => {
  const textRow1 = useSignal('');
  const textRow2 = useSignal('');

  return (<>

    <button
      onClick$={async () => {
        await arduinoBlink();
      }}
    > BLINK LED </button>

    <input type="text" bind:value={textRow1} placeholder="row 1"  />
    <input type="text" bind:value={textRow2} placeholder="row 2"  />

    <button
      onClick$={async () => {
        await arduinoLCDFn(textRow1.value, textRow2.value);
      }}
    > WRITE ON LCD </button>

  </>);
});
```

Here the final result:

{% embed https://player.vimeo.com/video/883641389?badge=0&amp;autopause=0&amp;quality_selector=1&amp;player_id=0&amp;app_id=58479 %}

---

# Conclusion

Of course it's nothing special but this example demonstrates the simplicity and flexibility with which we can use any JavaScript modules within the server function.

How cool is that?
What do you think?