In this tutorial, you get started with actual code and a sample real-world use case. Let's pretend you have a company called Smarty Lighting and you install smart-city streetlight lighting systems.
Streetlights System Description
You want to create a system capable of turning on/off the streetlights depending on the environmental conditions of each of them:
- You're going to implement an event-driven architecture, with a Message Broker in its "center".
- Streetlights will send information about its environmental lighting to the broker.
- None of the services will wait for any kind of response. (Think about it as fire and forget.) You'll publish messages to the broker and that's it. Your service doesn't need to know who receives them.
Technology
You'll use Node.js to code the APIs and Mosquitto as the message broker. The selected technology is irrelevant here, since everything explained in this tutorial is applicable to any other programming language and message brokers.
Creating the AsyncAPI file
Let's start by creating an AsyncAPI file to describe your API. It will help you generate the code and the documentation later on.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
asyncapi: '2.1.0' info: title: Streetlights API version: '1.0.0' description: | The Smartylighting Streetlights API allows you to remotely manage the city lights. license: name: Apache 2.0 url: 'https://www.apache.org/licenses/LICENSE-2.0' servers: mosquitto: url: mqtt://test.mosquitto.org protocol: mqtt channels: light/measured: publish: summary: Inform about environmental lighting conditions for a particular streetlight. operationId: onLightMeasured message: name: LightMeasured payload: type: object properties: id: type: integer minimum: 0 description: Id of the streetlight. lumens: type: integer minimum: 0 description: Light intensity measured in lumens. sentAt: type: string format: date-time description: Date and time when the message was sent.
Let's break it down into pieces:
1 2 3 4 5 6 7 8 9 10
asyncapi: '2.1.0' info: title: Streetlights API version: '1.0.0' description: | The Smartylighting Streetlights API allows you to remotely manage the city lights. license: name: Apache 2.0 url: 'https://www.apache.org/licenses/LICENSE-2.0'
- The
asyncapi
field indicates you use the AsyncAPI version 2.1.0. - The
info
field holds information about the API, such as its name, version, description, and license.
Now lets move all the way to the channels
section. This section is used to describe the event names your API will be publishing and/or subscribing to.
1 2 3 4 5
channels: light/measured: publish: summary: Inform about environmental lighting conditions for a particular streetlight. operationId: onLightMeasured
In this example, light/measured
is the channel name your API will publish
to. The operationId
property, describes what will be the name of function or method that takes care of this functionality in the generated code. The payload
property is used to understand how the event should look like when publishing to that channel:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
payload: type: object properties: id: type: integer minimum: 0 description: Id of the streetlight. lumens: type: integer minimum: 0 description: Light intensity measured in lumens. sentAt: type: string format: date-time description: Date and time when the message was sent.
The Payload
property defines the content of the event using AsyncAPI schemas. It means that your event payload should contain an id
and a lumens
property —which are integers bigger than zero—, and a sentAt
property that should be a string containing a date and time.
JSON Schema Draft 07 is 100% compatible with AsyncAPI schemas.
Cool! You're done with your AsyncAPI file! Now let's get into generating code.
Generating code
To generate your code, you'll use the AsyncAPI Generator Node.js template.
1. Install the generator to use it as a command-line tool
1
npm install -g @asyncapi/generator
2. Create a directory for your projects and enter it:
1
mkdir streetlights && cd "$_"
3. Create a file with the AsyncAPI machine-readable description you defined before. On Windows use type
instead of cat
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
cat <<EOT >> asyncapi.yaml asyncapi: '2.1.0' info: title: Streetlights API version: '1.0.0' description: | The Smartylighting Streetlights API allows you to remotely manage the city lights. license: name: Apache 2.0 url: 'https://www.apache.org/licenses/LICENSE-2.0' servers: mosquitto: url: mqtt://test.mosquitto.org protocol: mqtt channels: light/measured: publish: summary: Inform about environmental lighting conditions for a particular streetlight. operationId: onLightMeasured message: name: LightMeasured payload: type: object properties: id: type: integer minimum: 0 description: Id of the streetlight. lumens: type: integer minimum: 0 description: Light intensity measured in lumens. sentAt: type: string format: date-time description: Date and time when the message was sent. EOT
4. Trigger generation of the Node.js code:
1
ag asyncapi.yaml @asyncapi/nodejs-template -o output -p server=mosquitto
5. And voilà! List all files in directory and check that Node.js application is generated:
1
cd output && ls
Running your code
1. Install dependencies of newly generated application:
1
npm install
2. Start the application:
1
npm start
3. In another terminal install the MQTT.js library:
1
npm install mqtt -g
4. Send correct message to your application:
1
mqtt pub -t 'light/measured' -h 'test.mosquitto.org' -m '{"id": 1, "lumens": 3, "sentAt": "2017-06-07T12:34:32.000Z"}'
5. Send incorrect message to your application:
1
mqtt pub -t 'light/measured' -h 'test.mosquitto.org' -m '{"id": 1, "lumens": "3", "sentAt": "2017-06-07T12:34:32.000Z"}'
6. Go back to the previous terminal and check if your application logged the message you just sent, with errors related to the invalid message.
Conclusions
You've learned how to create an AsyncAPI description file and how to generate code from it. Today's sample code is only a bootstrap; you'll need to add your own business logic into it. Take some time to play with it. There are still lots of things to be covered, but the intent of this tutorial is to make it simple for you get an idea of the potential.
We would love to see what you create with AsyncAPI! As an open-source project, we're open to proposals, questions, suggestions, and contributions. If you don't feel in the mood to contribute but you're using AsyncAPI, just raise your hand creating a issue in our Github repo or join our Slack channel. Don't be shy. :simple_smile: