<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ivan Golubic</title>
    <description>The latest articles on DEV Community by Ivan Golubic (@igolubic).</description>
    <link>https://dev.to/igolubic</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1113298%2Fbc1daed6-009b-46f2-b421-c1d820eab340.jpeg</url>
      <title>DEV Community: Ivan Golubic</title>
      <link>https://dev.to/igolubic</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/igolubic"/>
    <language>en</language>
    <item>
      <title>Refine &amp; Nest.js boilerplate</title>
      <dc:creator>Ivan Golubic</dc:creator>
      <pubDate>Wed, 16 Aug 2023 15:00:44 +0000</pubDate>
      <link>https://dev.to/igolubic/refine-nestjs-boilerplate-4jh6</link>
      <guid>https://dev.to/igolubic/refine-nestjs-boilerplate-4jh6</guid>
      <description>&lt;p&gt;We were in search of a solution that bridged the gap between BaaS platforms (such as Appwrite or Supabase) and building from the ground up. We needed a system that would offer the flexibility to implement BI, data management, IoT, automation, and similar applications, while also incorporating features like authentication, RBAC, social login, a frontend equipped with CRUD operations, testing, and more.&lt;/p&gt;

&lt;p&gt;And this is how Refine &amp;amp; Nest.js boilerplate was born. &lt;/p&gt;

&lt;h2&gt;
  
  
  Source:
&lt;/h2&gt;

&lt;p&gt;Refine boilerplate: &lt;a href="https://github.com/poliath/poliath-refine-boilerplate"&gt;https://github.com/poliath/poliath-refine-boilerplate&lt;/a&gt;&lt;br&gt;
Nest.JS boilerplate: &lt;a href="https://github.com/poliath/nestjs-poliath-boilerplate"&gt;https://github.com/poliath/nestjs-poliath-boilerplate&lt;/a&gt;&lt;br&gt;
Quick start guide: &lt;a href="https://github.com/poliath/nestjs-poliath-boilerplate/blob/master/QUICK_START_GUIDE.md"&gt;https://github.com/poliath/nestjs-poliath-boilerplate/blob/master/QUICK_START_GUIDE.md&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  And here is the Quick start guide
&lt;/h2&gt;
&lt;h1&gt;
  
  
  Refine + Nest.JS Boilerplate
&lt;/h1&gt;

&lt;p&gt;Last edited by: Ivan Golubic&lt;br&gt;
Last edited time: August 16, 2023 3:27 PM&lt;/p&gt;

&lt;p&gt;This document describes the procedure to create new project using Poliath Refine and Nest.JS templates. &lt;/p&gt;
&lt;h1&gt;
  
  
  Requirements
&lt;/h1&gt;

&lt;p&gt;Node.js: Minimum version is 16, but 18 is highly recommended &lt;/p&gt;

&lt;p&gt;npm: installed and updated&lt;/p&gt;

&lt;p&gt;Docker: installed, configured and running&lt;/p&gt;

&lt;p&gt;IDE: WebStorm is recommended, although VS Code will make it&lt;/p&gt;
&lt;h1&gt;
  
  
  Backend
&lt;/h1&gt;

&lt;p&gt;In order to start our Nest.JS backend, we have to create our new project, based on the template&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone &lt;span class="nt"&gt;--depth&lt;/span&gt; 1 https://github.com/poliath/nestjs-poliath-boilerplate.git my-app
&lt;span class="nb"&gt;cd &lt;/span&gt;my-app/
&lt;span class="nb"&gt;cp &lt;/span&gt;env-example .env
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Quick run
&lt;/h2&gt;

&lt;p&gt;In order to start the project without development (for a quick test), from your app directory run the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker compose up &lt;span class="nt"&gt;-d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command will:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Wait for Postgres database container to spin up&lt;/li&gt;
&lt;li&gt;Run migration (create needed tables in the database)&lt;/li&gt;
&lt;li&gt;Run seeder (create 2 users and few random articles)&lt;/li&gt;
&lt;li&gt;Run application in production mode&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  Frontend
&lt;/h1&gt;

&lt;p&gt;In order to see data from your backend service we have to run our frontend application (refine based React application). Clone the &lt;code&gt;poliath-refine-boilerplate&lt;/code&gt; repository in preferred directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone &lt;span class="nt"&gt;--depth&lt;/span&gt; 1 https://github.com/poliath/poliath-refine-boilerplate.git frontend
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, head to your directory and install dependencies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;frontend/
npm &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After installing dependencies, we have to build our project and run preview mode (basically a local server that will serve our static content.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run build
npm run preview
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command will show you where your application is running, e.g.:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Local:   http://localhost:4173/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;head to the location and login. You should see demo users and articles. &lt;/p&gt;

&lt;h3&gt;
  
  
  RBAC explained
&lt;/h3&gt;

&lt;p&gt;Both backend and frontend have RBAC implemented. Admin user can do all operations on Users object, while ‘User’ user can only see articles and manage articles. Later in this documentation this feature will be explained in detail, but in order to experience it login with:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="mailto:admin@example.com"&gt;admin@example.com&lt;/a&gt; - Admin&lt;/li&gt;
&lt;li&gt;
&lt;a href="mailto:john.doe@example.com"&gt;john.doe@example.com&lt;/a&gt; - User&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;*****************************************************&lt;strong&gt;&lt;em&gt;Password for both users is:&lt;/em&gt;&lt;/strong&gt;***************************************************** secret&lt;/p&gt;

&lt;h3&gt;
  
  
  Inferencer explained
&lt;/h3&gt;

&lt;p&gt;One of the important features of &lt;a href="http://refine.dev"&gt;refine.dev&lt;/a&gt; is Inferencer (in short, it generates CRUD dashboard based on data from the database, and it provides you the code). If you click on ***************&lt;strong&gt;&lt;em&gt;Articles&lt;/em&gt;&lt;/strong&gt;*************** you will see the pop-up. This pop-up is not visible on *******&lt;strong&gt;&lt;em&gt;Users&lt;/em&gt;&lt;/strong&gt;******* since raw code (generated by Inferencer) was already implemented in this boilerplate, while in Articles it is not, for showcasing the purpose. You can read more about Inferencer here: &lt;a href="https://refine.dev/docs/packages/documentation/inferencer/"&gt;https://refine.dev/docs/packages/documentation/inferencer/&lt;/a&gt;&lt;/p&gt;




&lt;blockquote&gt;
&lt;p&gt;If everything works, then we can proceed with development setup and develop our application.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  Backend - development
&lt;/h1&gt;

&lt;p&gt;*****&lt;strong&gt;&lt;em&gt;If Docker containers from Quick run are still running, shut them down in order to avoid any collisions during development phase!&lt;/em&gt;&lt;/strong&gt;***** Head to your backend directory (e.g. my-app) and run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker compose down
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;***********************************************************************************************************************************************************************************************************************************************************************************************************&lt;strong&gt;&lt;em&gt;If frontend is running it also might create some confusion, so simple exit the preview server by pressing (Ctrl+C or appropriate shortcut for your OS).&lt;/em&gt;&lt;/strong&gt;***********************************************************************************************************************************************************************************************************************************************************************************************************&lt;/p&gt;

&lt;p&gt;In this step we will assume that you already cloned &lt;code&gt;nestjs-poliath-boilerplate&lt;/code&gt; project. Open your backend directory in your IDE. &lt;/p&gt;

&lt;p&gt;In order to start development, we need to update two environment variables (since we will run Nest.JS project on our local machine using NPM, but our database and some development tools will be in Docker. Open your .env file and;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Change &lt;code&gt;DATABASE_HOST=postgres&lt;/code&gt; to &lt;code&gt;DATABASE_HOST=localhost&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Change &lt;code&gt;MAIL_HOST=maildev&lt;/code&gt; to &lt;code&gt;MAIL_HOST=localhost&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Run Docker containers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker compose up &lt;span class="nt"&gt;-d&lt;/span&gt; postgres adminer maildev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Notice that this command will not start our &lt;code&gt;api&lt;/code&gt; container.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Running Nest.JS project locally
&lt;/h3&gt;

&lt;p&gt;Since we are running our project on our local machine, we have to install dependencies, run seeder and start in development environment.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install

&lt;/span&gt;npm run migration:run

npm run seed:run

npm run start:dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will start our backend, and you should see logs in the terminal. &lt;/p&gt;

&lt;h1&gt;
  
  
  Frontend - development
&lt;/h1&gt;

&lt;p&gt;Running frontend in development mode is extremely simple. Open your frontend directory in your IDE. And in the terminal, run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will start the development server and it will show you on which port it is currently running. If everything is good, you should be able to log in and see your application up and running. &lt;/p&gt;

&lt;h1&gt;
  
  
  Backend - adding new resource
&lt;/h1&gt;

&lt;p&gt;Now we will add new resource to our backend. For this purpose it will be a simple “Task”, it will have: id, title, done, created at, updated at, author, assignee. &lt;/p&gt;

&lt;p&gt;We will use Nest CLI for most of our work, so let’s install it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @nestjs/cli
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nest provides CRUD generator as part of its CLI tool. It generates starting point for your resource. Let’s generate our Tasks resource:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nest g resource
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will start a simple wizard:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;? What name would you like to use &lt;span class="k"&gt;for &lt;/span&gt;this resource &lt;span class="o"&gt;(&lt;/span&gt;plural, e.g., &lt;span class="s2"&gt;"users"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;? tasks
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, select “REST API” for transport layer.&lt;/p&gt;

&lt;p&gt;Select Yes for generating CRUD entry points.&lt;/p&gt;

&lt;p&gt;****************************&lt;strong&gt;&lt;em&gt;This will generate all needed files for our “Tasks” resource under tasks directory. Nest will not create DTO by default, it will create only a simple class that we should populate with our data.&lt;/em&gt;&lt;/strong&gt;**************************** &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The database table is not created for each model but only for those models which are declared as &lt;strong&gt;entities&lt;/strong&gt;. To declare a model as an entity, we just need to add the ‘&lt;strong&gt;@Entity()&lt;/strong&gt;‘ decorator before the declaration of the Class defining our model.&lt;/p&gt;


&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;import &lt;span class="o"&gt;{&lt;/span&gt;
  Column,
  CreateDateColumn,
  Entity,
  ManyToOne,
  PrimaryGeneratedColumn,
  UpdateDateColumn,
&lt;span class="o"&gt;}&lt;/span&gt; from &lt;span class="s1"&gt;'typeorm'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
import &lt;span class="o"&gt;{&lt;/span&gt; User &lt;span class="o"&gt;}&lt;/span&gt; from &lt;span class="s1"&gt;'../../users/entities/user.entity'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

@Entity&lt;span class="o"&gt;()&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;class Task &lt;span class="o"&gt;{&lt;/span&gt;
  @PrimaryGeneratedColumn&lt;span class="o"&gt;()&lt;/span&gt;
  &lt;span class="nb"&gt;id&lt;/span&gt;: number&lt;span class="p"&gt;;&lt;/span&gt;

  @CreateDateColumn&lt;span class="o"&gt;()&lt;/span&gt;
  createdAt: Date&lt;span class="p"&gt;;&lt;/span&gt;

  @UpdateDateColumn&lt;span class="o"&gt;()&lt;/span&gt;
  updatedAt?: Date&lt;span class="p"&gt;;&lt;/span&gt;

  @Column&lt;span class="o"&gt;({&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;: String, nullable: &lt;span class="nb"&gt;false&lt;/span&gt; &lt;span class="o"&gt;})&lt;/span&gt;
  title: string&lt;span class="p"&gt;;&lt;/span&gt;

  @Column&lt;span class="o"&gt;({&lt;/span&gt; default: &lt;span class="nb"&gt;false&lt;/span&gt; &lt;span class="o"&gt;})&lt;/span&gt;
  &lt;span class="k"&gt;done&lt;/span&gt;: boolean&lt;span class="p"&gt;;&lt;/span&gt;

  @ManyToOne&lt;span class="o"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; User, &lt;span class="o"&gt;(&lt;/span&gt;user&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; user.tasks&lt;span class="o"&gt;)&lt;/span&gt;
  author: User&lt;span class="p"&gt;;&lt;/span&gt;

  @ManyToOne&lt;span class="o"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; User, &lt;span class="o"&gt;(&lt;/span&gt;user&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; user.tasks&lt;span class="o"&gt;)&lt;/span&gt;
  assignee: User&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above’s code we created our task model. Nest provides multiple decorators like *&lt;strong&gt;&lt;em&gt;&lt;code&gt;@CreateDateColumn()&lt;/code&gt;&lt;/em&gt;&lt;/strong&gt;* that will automatically add date when the entity is created. Additionally *********************************&lt;strong&gt;&lt;em&gt;PrimaryGeneratedColumn&lt;/em&gt;&lt;/strong&gt;********************************* is used as primary key. We can pass various *********&lt;strong&gt;&lt;em&gt;Column&lt;/em&gt;&lt;/strong&gt;********* options like type or default. &lt;/p&gt;

&lt;p&gt;Additionally, we have ***************&lt;strong&gt;&lt;em&gt;ManyToOne&lt;/em&gt;&lt;/strong&gt;*************** relationship since User can be author to many Tasks, and User can have many tasks where he is assignee (in our case Task can have only one assignee. &lt;/p&gt;

&lt;p&gt;Additionally, since we have foreign relationships for User, we have to add it to the *************&lt;strong&gt;&lt;em&gt;user.entity.ts:&lt;/em&gt;&lt;/strong&gt;*************&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;@OneToMany&lt;span class="o"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; Task, &lt;span class="o"&gt;(&lt;/span&gt;task&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; task.author&lt;span class="o"&gt;)&lt;/span&gt;
  tasks?: Task[]&lt;span class="p"&gt;;&lt;/span&gt;

@OneToMany&lt;span class="o"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; Task, &lt;span class="o"&gt;(&lt;/span&gt;task&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; task.assignee&lt;span class="o"&gt;)&lt;/span&gt;
assignedTasks?: Task[]&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we have to create a migration to be able to apply our changes to the database tables.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run migration:generate &lt;span class="nt"&gt;--&lt;/span&gt; src/database/migrations/CreateTasks
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command will generate new migration file under migrations. Name will be &amp;lt;timestamp-CreateTasks.ts&lt;/p&gt;

&lt;p&gt;Next, we have to run our migration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run migration:run
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If something is wrong with our previous migration, we can simply revert it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run migration:revert
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Above our Tasks Controller class, we have to add the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;@Controller&lt;span class="o"&gt;({&lt;/span&gt;
  path: &lt;span class="s1"&gt;'tasks'&lt;/span&gt;,
  version: &lt;span class="s1"&gt;'1'&lt;/span&gt;,
&lt;span class="o"&gt;})&lt;/span&gt;
@UseGuards&lt;span class="o"&gt;(&lt;/span&gt;AuthGuard&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'jwt'&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
@ApiTags&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Tasks'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
@ApiBearerAuth&lt;span class="o"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Controller decorator will define that that class acts as a controller, which is called though “tasks” path, and version of this API is 1. ***************************************************************&lt;strong&gt;&lt;em&gt;This will be also visible ins Swagger&lt;/em&gt;&lt;/strong&gt;***************************************************************. &lt;/p&gt;

&lt;p&gt;UseGuards decorator will define the guards, in this case only jwt (so only authenticated users will be able to access this route. This boilerplate also supports *****************&lt;strong&gt;&lt;em&gt;RolesGuard&lt;/em&gt;&lt;/strong&gt;***************** - which is used in conjunction with *******&lt;strong&gt;&lt;em&gt;Roles&lt;/em&gt;&lt;/strong&gt;******* decorator, in order to restrict user access for a specific group of users. &lt;/p&gt;

&lt;p&gt;ApiTags defines how this route set will be called in swagger.&lt;/p&gt;

&lt;p&gt;ApiBearerAuth defines that this controller needs Bearer token in order to be accessed. &lt;/p&gt;

&lt;h3&gt;
  
  
  Methods in Controller
&lt;/h3&gt;

&lt;p&gt;Since we selected Yes for generating CRUD entry points during resource creation, each method is defined in the controller and has its own decorator (Post, Get, Delete, Patch). &lt;/p&gt;

&lt;p&gt;Calling ***************&lt;strong&gt;&lt;em&gt;findAll()&lt;/em&gt;&lt;/strong&gt;*************** method. In this case we can use Postman to call &lt;a href="http://localhost:3000/api/v1/tasks"&gt;&lt;code&gt;http://localhost:3000/api/v1/tasks&lt;/code&gt;&lt;/a&gt; and it should return the message: “This action returns all tasks”, since our ***************************&lt;strong&gt;&lt;em&gt;Service is not implemented yet!&lt;/em&gt;&lt;/strong&gt;*************************** &lt;/p&gt;

&lt;p&gt;If it returns error 401, that means that you did not provide bearer token, which you will get by calling a POST request to the &lt;a href="http://localhost:3000/api/v1/auth/email/login"&gt;&lt;code&gt;http://localhost:3000/api/v1/auth/email/login&lt;/code&gt;&lt;/a&gt; with the following JSON body:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"email"&lt;/span&gt;: &lt;span class="s2"&gt;"admin@example.com"&lt;/span&gt;,
    &lt;span class="s2"&gt;"password"&lt;/span&gt; : &lt;span class="s2"&gt;"secret"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then add your Bearer token to the Authorization field in Postman. &lt;/p&gt;

&lt;p&gt;If you want to restrict a specific route to a specific (or multiple) role, then you have to add the following decorator above the method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;@Roles&lt;span class="o"&gt;(&lt;/span&gt;RoleEnum.user&lt;span class="o"&gt;)&lt;/span&gt;
@UseGuards&lt;span class="o"&gt;(&lt;/span&gt;AuthGuard&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'jwt'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;, RolesGuard&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will restrict access only to logged in user of type user. And if you try to call GET method to the previous route (while logged in with Admin account), you will get the following error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"message"&lt;/span&gt;: &lt;span class="s2"&gt;"Forbidden resource"&lt;/span&gt;,
    &lt;span class="s2"&gt;"error"&lt;/span&gt;: &lt;span class="s2"&gt;"Forbidden"&lt;/span&gt;,
    &lt;span class="s2"&gt;"statusCode"&lt;/span&gt;: 403
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  DTO’s
&lt;/h3&gt;

&lt;p&gt;Data Transfer Object basically transforms our data between our service and database. In TypeORM it can define the structure and validation of our entity, in this case a Task. &lt;/p&gt;

&lt;p&gt;Two main DTO’s are generated by default, “create” and “update”, in some cases they will be the same so “update will only partially extend the “create”, and in some cases it will be different. In our case it will extend our “create: DTO:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;class UpdateTaskDto extends PartialType&lt;span class="o"&gt;(&lt;/span&gt;CreateTaskDto&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can see that this is already generated by default. &lt;/p&gt;

&lt;p&gt;Back to “crate” DTO. &lt;/p&gt;

&lt;p&gt;According to our task entity, we must provide title, author (id) and assignee (id). &lt;/p&gt;

&lt;p&gt;For simplicity our Task DTO will look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;import &lt;span class="o"&gt;{&lt;/span&gt; IsNotEmpty &lt;span class="o"&gt;}&lt;/span&gt; from &lt;span class="s1"&gt;'class-validator'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nb"&gt;export &lt;/span&gt;class CreateTaskDto &lt;span class="o"&gt;{&lt;/span&gt;
  @IsNotEmpty&lt;span class="o"&gt;()&lt;/span&gt;
  title: string&lt;span class="p"&gt;;&lt;/span&gt;
  @IsNotEmpty&lt;span class="o"&gt;()&lt;/span&gt;
  author: number&lt;span class="p"&gt;;&lt;/span&gt;
  @IsNotEmpty&lt;span class="o"&gt;()&lt;/span&gt;
  assignee: number&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It basically defines only that one of the fields cannot be empty. There are multiple decorators and validators that can be used.&lt;/p&gt;

&lt;h3&gt;
  
  
  Services
&lt;/h3&gt;

&lt;p&gt;In order to actually do something with our data, we must create some logic. Logic is handled in tasks.service.ts file. First we will write a code for creating new task. &lt;/p&gt;

&lt;p&gt;At.the very beginning we must inject the repository in the constructor of our service class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;constructor&lt;span class="o"&gt;(&lt;/span&gt;
    @InjectRepository&lt;span class="o"&gt;(&lt;/span&gt;Task&lt;span class="o"&gt;)&lt;/span&gt;
    private tasksRepository: Repository&amp;lt;Task&amp;gt;,
  &lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Repository is a part of TypeORM and it is basically used for our interaction with the database. &lt;/p&gt;

&lt;p&gt;In order to insert author of our Task, we have to pass current user to the service, so our create method will look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;create&lt;span class="o"&gt;(&lt;/span&gt;createTaskDto: CreateTaskDto, user: User&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    createTaskDto.author &lt;span class="o"&gt;=&lt;/span&gt; user&lt;span class="p"&gt;;&lt;/span&gt;
    const newTask &lt;span class="o"&gt;=&lt;/span&gt; this.tasksRepository.save&lt;span class="o"&gt;(&lt;/span&gt;
      this.tasksRepository.create&lt;span class="o"&gt;(&lt;/span&gt;createTaskDto&lt;span class="o"&gt;)&lt;/span&gt;,
    &lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;return &lt;/span&gt;newTask&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;*****************************************************************************************************************************************************&lt;strong&gt;&lt;em&gt;But this will not work out of the box, since we need to pass User object to our create method. This boilerplate contains CurrentUser decorator, which returns currently logged in user.&lt;/em&gt;&lt;/strong&gt;*****************************************************************************************************************************************************&lt;/p&gt;

&lt;p&gt;So, edit “tasks.controller.ts”:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;@Post&lt;span class="o"&gt;()&lt;/span&gt;
  create&lt;span class="o"&gt;(&lt;/span&gt;@Body&lt;span class="o"&gt;()&lt;/span&gt; createTaskDto: CreateTaskDto, @CurrentUser&lt;span class="o"&gt;()&lt;/span&gt; user: User&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;this.tasksService.create&lt;span class="o"&gt;(&lt;/span&gt;createTaskDto, user&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can send POST request to the &lt;a href="http://localhost:3000/api/v1/tasks"&gt;&lt;code&gt;http://localhost:3000/api/v1/tasks&lt;/code&gt;&lt;/a&gt; route with the following JSON body:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"title"&lt;/span&gt;: &lt;span class="s2"&gt;"This is a task 4"&lt;/span&gt;,
    &lt;span class="s2"&gt;"assignee"&lt;/span&gt;: 2
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will assign this task to our user with id = 2 (John Doe), and author will be our signed in user (Admin). &lt;/p&gt;

&lt;p&gt;*****************************************************************************************************&lt;strong&gt;&lt;em&gt;Next, we will create service for fetching all tasks.&lt;/em&gt;&lt;/strong&gt;***************************************************************************************************** &lt;/p&gt;

&lt;p&gt;In order to do that, we have to edit *****&lt;strong&gt;&lt;em&gt;findAll()&lt;/em&gt;&lt;/strong&gt;***** method in tasks.service.ts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;findAll&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;this.tasksRepository.find&lt;span class="o"&gt;()&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a simple method that calls *********&lt;strong&gt;&lt;em&gt;find()&lt;/em&gt;&lt;/strong&gt;*********, which is basically like &lt;code&gt;SELECT * FROM TASKS;&lt;/code&gt; Now we can call GET method on the &lt;a href="http://localhost:3000/api/v1/tasks"&gt;&lt;code&gt;http://localhost:3000/api/v1/tasks&lt;/code&gt;&lt;/a&gt; endpoint. &lt;/p&gt;

&lt;p&gt;This will return JSON Array of our tasks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;[&lt;/span&gt;
    &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="s2"&gt;"id"&lt;/span&gt;: 1,
        &lt;span class="s2"&gt;"createdAt"&lt;/span&gt;: &lt;span class="s2"&gt;"2023-08-15T10:18:14.437Z"&lt;/span&gt;,
        &lt;span class="s2"&gt;"updatedAt"&lt;/span&gt;: &lt;span class="s2"&gt;"2023-08-15T10:18:14.437Z"&lt;/span&gt;,
        &lt;span class="s2"&gt;"title"&lt;/span&gt;: &lt;span class="s2"&gt;"This is a task 1"&lt;/span&gt;,
        &lt;span class="s2"&gt;"done"&lt;/span&gt;: &lt;span class="nb"&gt;false&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;,
    &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="s2"&gt;"id"&lt;/span&gt;: 2,
        &lt;span class="s2"&gt;"createdAt"&lt;/span&gt;: &lt;span class="s2"&gt;"2023-08-15T16:45:51.630Z"&lt;/span&gt;,
        &lt;span class="s2"&gt;"updatedAt"&lt;/span&gt;: &lt;span class="s2"&gt;"2023-08-15T16:45:51.630Z"&lt;/span&gt;,
        &lt;span class="s2"&gt;"title"&lt;/span&gt;: &lt;span class="s2"&gt;"This is a task 2"&lt;/span&gt;,
        &lt;span class="s2"&gt;"done"&lt;/span&gt;: &lt;span class="nb"&gt;false&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we will implement *************&lt;strong&gt;&lt;em&gt;findOne()&lt;/em&gt;&lt;/strong&gt;************* method in order to fetch data for specific task:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;@Get&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;':id'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  findOne&lt;span class="o"&gt;(&lt;/span&gt;@Param&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'id'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nb"&gt;id&lt;/span&gt;: string&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;this.tasksService.findOne&lt;span class="o"&gt;({&lt;/span&gt; &lt;span class="nb"&gt;id&lt;/span&gt;: +id &lt;span class="o"&gt;})&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;First we will update our findOne method in controller to pass &lt;code&gt;{id: +id}&lt;/code&gt; since we will use ***********&lt;strong&gt;&lt;em&gt;EntityCondition&lt;/em&gt;&lt;/strong&gt;*********** to pass fields. Finally our findOne method in service will look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;findOne&lt;span class="o"&gt;(&lt;/span&gt;fields: EntityCondition&amp;lt;Task&amp;gt;&lt;span class="o"&gt;)&lt;/span&gt;: Promise&amp;lt;NullableType&amp;lt;Task&amp;gt;&amp;gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;this.tasksRepository.findOne&lt;span class="o"&gt;({&lt;/span&gt; where: fields &lt;span class="o"&gt;})&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;*************************************&lt;strong&gt;&lt;em&gt;Next we will write our update method in service:&lt;/em&gt;&lt;/strong&gt;*************************************&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;update&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;: Task[&lt;span class="s1"&gt;'id'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;, payload: DeepPartial&amp;lt;Task&amp;gt;&lt;span class="o"&gt;)&lt;/span&gt;: Promise&amp;lt;Task&amp;gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;this.tasksRepository.save&lt;span class="o"&gt;(&lt;/span&gt;
      this.tasksRepository.create&lt;span class="o"&gt;({&lt;/span&gt;
        &lt;span class="nb"&gt;id&lt;/span&gt;,
        ...payload,
      &lt;span class="o"&gt;})&lt;/span&gt;,
    &lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, we are accepting task id and payload, which is basically Partial DTO, and this method returns Task that we updated. &lt;/p&gt;

&lt;p&gt;*************&lt;strong&gt;&lt;em&gt;Next, we will implement delete service&lt;/em&gt;&lt;/strong&gt;*************&lt;/p&gt;

&lt;p&gt;This is pretty simple method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;remove&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;: number&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;this.articlesRepository.delete&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Please note that there are various implementations of these services, I provided the simple ones, there are various ways of updating and handling errors, responses, etc. But this can be implemented based on a specific use-case.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  Frontend - adding new resource
&lt;/h1&gt;

&lt;p&gt;Once we have our backend up and running, we can implement our frontend. &lt;/p&gt;

&lt;p&gt;We will use *************&lt;strong&gt;&lt;em&gt;refine CLI&lt;/em&gt;&lt;/strong&gt;************* for creating new resources. Refine CLI is installed when project is created with refine create command, but in this boilerplate is already available. &lt;/p&gt;

&lt;p&gt;Position your terminal to your frontend directory (e.g. my-app) and run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run refine create-resource
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This wizard will ask you to define your resource name (’tasks’ in our case), and with leave all pages selected. This will generate *******&lt;strong&gt;&lt;em&gt;tasks&lt;/em&gt;&lt;/strong&gt;******* directory with all pages needed. Also, it will update App.tsx with new resource data.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Please note that this command will NOT generate routes, and it will only use Inferencer in generated pages.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;***********************************************************************&lt;strong&gt;&lt;em&gt;First we will add routes for our tasks&lt;/em&gt;&lt;/strong&gt;***********************************************************************&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&amp;lt;Route &lt;span class="nv"&gt;path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"/tasks"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                  &amp;lt;Route index &lt;span class="nv"&gt;element&lt;/span&gt;&lt;span class="o"&gt;={&lt;/span&gt;&amp;lt;TasksList /&amp;gt;&lt;span class="o"&gt;}&lt;/span&gt; /&amp;gt;
                  &amp;lt;Route &lt;span class="nv"&gt;path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"create"&lt;/span&gt; &lt;span class="nv"&gt;element&lt;/span&gt;&lt;span class="o"&gt;={&lt;/span&gt;&amp;lt;TasksCreate /&amp;gt;&lt;span class="o"&gt;}&lt;/span&gt; /&amp;gt;
                  &amp;lt;Route &lt;span class="nv"&gt;path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"edit/:id"&lt;/span&gt; &lt;span class="nv"&gt;element&lt;/span&gt;&lt;span class="o"&gt;={&lt;/span&gt;&amp;lt;TasksEdit /&amp;gt;&lt;span class="o"&gt;}&lt;/span&gt; /&amp;gt;
                  &amp;lt;Route &lt;span class="nv"&gt;path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"show/:id"&lt;/span&gt; &lt;span class="nv"&gt;element&lt;/span&gt;&lt;span class="o"&gt;={&lt;/span&gt;&amp;lt;TasksShow /&amp;gt;&lt;span class="o"&gt;}&lt;/span&gt; /&amp;gt;
                &amp;lt;/Route&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These routes are directly related to our pages, but they won’t be visible immediately due to RBAC restrictions.&lt;/p&gt;

&lt;p&gt;We have to edit *********&lt;strong&gt;&lt;em&gt;casbin&lt;/em&gt;&lt;/strong&gt;********* access control. Open &lt;code&gt;src/casbin/accessControl.ts&lt;/code&gt; and add the following to the adapter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;p, 1, tasks, &lt;span class="o"&gt;(&lt;/span&gt;list&lt;span class="o"&gt;)&lt;/span&gt;|&lt;span class="o"&gt;(&lt;/span&gt;create&lt;span class="o"&gt;)&lt;/span&gt;|&lt;span class="o"&gt;(&lt;/span&gt;edit&lt;span class="o"&gt;)&lt;/span&gt;|&lt;span class="o"&gt;(&lt;/span&gt;show&lt;span class="o"&gt;)&lt;/span&gt;|&lt;span class="o"&gt;(&lt;/span&gt;delete&lt;span class="o"&gt;)&lt;/span&gt;
p, 2, tasks, &lt;span class="o"&gt;(&lt;/span&gt;list&lt;span class="o"&gt;)&lt;/span&gt;|&lt;span class="o"&gt;(&lt;/span&gt;create&lt;span class="o"&gt;)&lt;/span&gt;|&lt;span class="o"&gt;(&lt;/span&gt;edit&lt;span class="o"&gt;)&lt;/span&gt;|&lt;span class="o"&gt;(&lt;/span&gt;show&lt;span class="o"&gt;)&lt;/span&gt;|&lt;span class="o"&gt;(&lt;/span&gt;delete&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will enable both users and admins to make all CRUD operations. &lt;/p&gt;

&lt;p&gt;Now if you refresh your frontend on localhost, and click on Tasks you should see the list of tasks. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;***************************************************&lt;strong&gt;&lt;em&gt;If not added automatically, add the following to the tasks resource in App.tsx:&lt;/em&gt;&lt;/strong&gt;***************************************************&lt;/p&gt;


&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;meta: &lt;span class="o"&gt;{&lt;/span&gt;
           canDelete: &lt;span class="nb"&gt;true&lt;/span&gt;,
      &lt;span class="o"&gt;}&lt;/span&gt;,
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All pages are generated using Inferencer, a part from refine.dev: &lt;a href="https://refine.dev/docs/packages/documentation/inferencer"&gt;https://refine.dev/docs/packages/documentation/inferencer&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you click on the Inferencer pop up you will see the generated code for a list of tasks, copy this code and paste it in tasks/list.tsx (replace the current code). Pop up will disappear and you will have the flexibility to customize the page. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If there is an error in your console or your page is blank, probably page export is wrong (TaskList instead of TasksList), check for this kind of issues.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  i18n - Translations
&lt;/h3&gt;

&lt;p&gt;After exporting, we can edit translation for our page to display real values instead of object fields. Open &lt;code&gt;public/locales/en/common.json&lt;/code&gt; &lt;/p&gt;

&lt;p&gt;Add the following object to the same level as “users”:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="s2"&gt;"tasks"&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"tasks"&lt;/span&gt;: &lt;span class="s2"&gt;"Tasks"&lt;/span&gt;,
    &lt;span class="s2"&gt;"fields"&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="s2"&gt;"id"&lt;/span&gt;: &lt;span class="s2"&gt;"ID"&lt;/span&gt;,
      &lt;span class="s2"&gt;"title"&lt;/span&gt;: &lt;span class="s2"&gt;"Title"&lt;/span&gt;,
      &lt;span class="s2"&gt;"done"&lt;/span&gt;: &lt;span class="s2"&gt;"Done"&lt;/span&gt;,
      &lt;span class="s2"&gt;"createdAt"&lt;/span&gt;: &lt;span class="s2"&gt;"Created at"&lt;/span&gt;,
      &lt;span class="s2"&gt;"updatedAt"&lt;/span&gt;: &lt;span class="s2"&gt;"Updated at"&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;,
    &lt;span class="s2"&gt;"titles"&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="s2"&gt;"create"&lt;/span&gt;: &lt;span class="s2"&gt;"Create task"&lt;/span&gt;,
      &lt;span class="s2"&gt;"edit"&lt;/span&gt;: &lt;span class="s2"&gt;"Edit task"&lt;/span&gt;,
      &lt;span class="s2"&gt;"list"&lt;/span&gt;: &lt;span class="s2"&gt;"Tasks"&lt;/span&gt;,
      &lt;span class="s2"&gt;"show"&lt;/span&gt;: &lt;span class="s2"&gt;"Show task"&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;,
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Additionally, under documentTitle, on the same level as users add the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="s2"&gt;"tasks"&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="s2"&gt;"list"&lt;/span&gt;: &lt;span class="s2"&gt;"Tasks | Poliath Manager"&lt;/span&gt;,
      &lt;span class="s2"&gt;"show"&lt;/span&gt;: &lt;span class="s2"&gt;"#{{id}} Show task | Poliath Manager"&lt;/span&gt;,
      &lt;span class="s2"&gt;"edit"&lt;/span&gt;: &lt;span class="s2"&gt;"#{{id}} Edit task | Poliath Manager"&lt;/span&gt;,
      &lt;span class="s2"&gt;"create"&lt;/span&gt;: &lt;span class="s2"&gt;"Create new task | Poliath Manager"&lt;/span&gt;,
      &lt;span class="s2"&gt;"clone"&lt;/span&gt;: &lt;span class="s2"&gt;"#{{id}} Clone task | Poliath Manager"&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;,
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above’s is used for page titles.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Add the same fields for other languages.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;When you refresh the page you should see how fields now have names.&lt;/strong&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  Creating new task through our frontend
&lt;/h3&gt;

&lt;p&gt;This is pretty straightforward, just click on Create button and fill out the fields. *&lt;strong&gt;&lt;em&gt;Of course, you can copy the Inferencer code&lt;/em&gt;&lt;/strong&gt;* to your create.tsx file and for example remove Created at and Updated at fields “since those are handled on our backend”.&lt;/p&gt;

&lt;p&gt;When you click save - you will get an error 422 - Unprocessable entity, this is because we are not passing assignee parameter. But how to get it? &lt;/p&gt;

&lt;p&gt;We can use *************&lt;strong&gt;&lt;em&gt;useList&lt;/em&gt;&lt;/strong&gt;*************, although it is a rough option since it loads all users into the memory and we are doing parsing on clients side. Instead we should use useMany, that will call our backend method and retrieve only filtered users that we actually need.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;const &lt;span class="o"&gt;{&lt;/span&gt; data: data, isLoading &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; useList&amp;lt;IUser&amp;gt;&lt;span class="o"&gt;({&lt;/span&gt;
        resource: &lt;span class="s1"&gt;'users'&lt;/span&gt;
    &lt;span class="o"&gt;})&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Swizzle
&lt;/h3&gt;

&lt;p&gt;Refine provides some solutions out of the box, e.g. data providers, but this code sometimes does not meet our needs. That is is why swizzle exists, it basically  generates the code that can be customized, based on the existing predefined code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run refine swizzle
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is how we can edit our components, auth pages, auth providers, etc.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://refine.dev/docs/tutorial/understanding-dataprovider/swizzle/#what-is-swizzle"&gt;https://refine.dev/docs/tutorial/understanding-dataprovider/swizzle/#what-is-swizzle&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Sending an email
&lt;/h1&gt;

&lt;p&gt;This boilerplate has implemented email service, and usage is implemented in &lt;code&gt;src/mail/mail.service.ts&lt;/code&gt; which can be used as a reference for customization if needed.&lt;/p&gt;

&lt;h1&gt;
  
  
  Additional tools and info
&lt;/h1&gt;

&lt;p&gt;Backend comes with handy tools for development, such as:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Swagger - full API documentation (&lt;a href="http://localhost:3000/docs"&gt;http://localhost:3000/docs&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Adminer - client for database (&lt;a href="http://localhost:8080/"&gt;http://localhost:8080&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Maildev - SMTP server (&lt;a href="http://localhost:1080/"&gt;http://localhost:1080&lt;/a&gt;)&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;Please note that these services should be disabled in production!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  Running in production
&lt;/h1&gt;

&lt;p&gt;Once you finish your backend logic, you can run it in production using Docker. You should disable above-mentioned development tools.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Please note that if you were running this boilerplate previously, in order to “catch” latest updates of your code, migrations, etc. You first have to rebuild docker image!&lt;/p&gt;


&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker compose build &lt;span class="nt"&gt;--no-cache&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Logging is implemented by default and logs are available in the &lt;code&gt;./logs&lt;/code&gt; directory.&lt;/strong&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;Please note that there can be a lot of situations where you will have to edit default code (e.g. change querying methods, update current DTO’s, etc.) But this is a great starting point for any project. &lt;/p&gt;

&lt;p&gt;Additionally, this documentation will be updated or fixed as needed, with new features, fixes and improvements. &lt;/p&gt;

&lt;h1&gt;
  
  
  Issues and errors
&lt;/h1&gt;

&lt;p&gt;Please be aware that this documentation is primarily designed to expedite your onboarding process. While it may offer some "shortcut" solutions, these are intended purely for illustrative purposes to help clarify the workings of this boilerplate. Should you encounter any issues with the boilerplate, whether on the frontend or backend, we encourage you to raise an issue on GitHub:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Refine boilerplate: &lt;a href="https://github.com/poliath/poliath-refine-boilerplate"&gt;https://github.com/poliath/poliath-refine-boilerplate&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;NestJS boilerplate: &lt;a href="https://github.com/poliath/nestjs-poliath-boilerplate"&gt;https://github.com/poliath/nestjs-poliath-boilerplate&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>refine</category>
      <category>nestjs</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>ESP32 Cloud data storage</title>
      <dc:creator>Ivan Golubic</dc:creator>
      <pubDate>Tue, 04 Jul 2023 14:02:41 +0000</pubDate>
      <link>https://dev.to/igolubic/esp32-cloud-data-storage-6an</link>
      <guid>https://dev.to/igolubic/esp32-cloud-data-storage-6an</guid>
      <description>&lt;p&gt;In this tutorial we will write a simple code that will read temperature from &lt;a href="https://www.bosch-sensortec.com/products/environmental-sensors/humidity-sensors-bme280/"&gt;BME280 sensor&lt;/a&gt;, and store this temperature to IoTaaP Storage service.&lt;/p&gt;

&lt;h2&gt;
  
  
  platformio.ini
&lt;/h2&gt;

&lt;p&gt;As usual we will use PlatformIO for this embedded project, and our platformio.ini should look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[env:release]
platform = espressif32
board = esp32dev
framework = arduino
monitor_speed = 115200
lib_deps = 
    iotaap/IoTaaP OS@^5.2.2
    adafruit/Adafruit BME280 Library@^2.2.2
board_build.partitions = partitions/default_fat.csv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Headers and declaration
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;IoTaaP_OS.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;Arduino.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;ArduinoJson.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;"Adafruit_BME280.h"&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="cp"&gt;#define TOKEN "&amp;lt;iotaap-link-secret&amp;gt;" // IoTaaP Link Secret
&lt;/span&gt;
&lt;span class="n"&gt;Adafruit_BME280&lt;/span&gt; &lt;span class="n"&gt;bme&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;         &lt;span class="c1"&gt;// I2C&lt;/span&gt;
&lt;span class="n"&gt;IoTaaP_OS&lt;/span&gt; &lt;span class="nf"&gt;iotaapOs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"3.2.8"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Defining Firmware version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We have to include our headers as usual, since Adafruit_BME280.h requires some functions from Arduino.h, we have to include it also. Additionally we have to declare our &lt;code&gt;bme&lt;/code&gt; sensor and create &lt;code&gt;iotaapOs&lt;/code&gt; object.&lt;/p&gt;

&lt;p&gt;Also we have to define &lt;strong&gt;TOKEN&lt;/strong&gt;, so please do not forget to replace &lt;code&gt;&amp;lt;iotaap-link-secret&amp;gt;&lt;/code&gt; with your IoTaaP Link Secret.&lt;/p&gt;

&lt;h2&gt;
  
  
  setup() function
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// BME280 related stuff&lt;/span&gt;
  &lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bme&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;begin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mh"&gt;0x76&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Could not find a valid BME280 sensor, check wiring, address, sensor ID!"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="n"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="n"&gt;iotaapOs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Start IoTaaP OS&lt;/span&gt;

  &lt;span class="n"&gt;iotaapOs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;startWifi&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;         &lt;span class="c1"&gt;// Connect to WiFi&lt;/span&gt;
  &lt;span class="n"&gt;iotaapOs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;startMqtt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Connect to MQTT broker&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the first part of the function, we are checking if BME280 is available and working, this is a good practice in this example, to eliminate further issues if sensor is not working properly. &lt;/p&gt;

&lt;p&gt;Next, we have to call &lt;strong&gt;iotaapOs.start()&lt;/strong&gt; function to start our IoTaaP OS services, this is followed by &lt;strong&gt;iotaapOs.startWifi()&lt;/strong&gt; to connect to start WiFi service and &lt;strong&gt;iotaapOs.startMqtt()&lt;/strong&gt; to connect to the IoTaaP network, and define MQTT callback function.&lt;/p&gt;

&lt;h2&gt;
  
  
  callback() function
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;topic&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;byte&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"-------#-----#-----#----------"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Received data on the topic:"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;topic&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Print topic&lt;/span&gt;

  &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Data:"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Print message&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"------#------#------#---------"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is basic MQTT callback function that will print received data and topic to our Serial Terminal, it is used to check the status of the service.&lt;/p&gt;

&lt;h2&gt;
  
  
  loop() function
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="c1"&gt;// Fetch measurements from BME280 sensor&lt;/span&gt;
  &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;temperatureC&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bme&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;readTemperature&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="c1"&gt;// Store temperature reading to IoTaaP Storage service, and subscribe to callback topic&lt;/span&gt;
  &lt;span class="n"&gt;iotaapOs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;storageServiceStore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TOKEN&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"temperature"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;temperatureC&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"/pgiIzx7n/storage/response"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="n"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This function is repeated constantly, and it will read the temperature from our BME280 sensor and store it in &lt;code&gt;temperatureC&lt;/code&gt; variable. Next, we will use &lt;code&gt;iotaapOs.storageServiceStore()&lt;/code&gt; function to store our reading to the IoTaaP Storage. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Do not forget to &lt;strong&gt;update your token&lt;/strong&gt; and &lt;strong&gt;update your callbackTopic&lt;/strong&gt;. Also your must have permission to listen on your callback topic.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Reading from IoTaaP Storage
&lt;/h2&gt;

&lt;p&gt;We will use Postman to read from IoTaaP Storage. This step is described in detail &lt;a href="https://docs.iotaap.io/en/services/storage-service#retrieving-data"&gt;&lt;strong&gt;here&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;After populating some data from our sensor, we will get the following response:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"time"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2023-06-27T18:14:20.364Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;26.32&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"time"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2023-06-27T18:14:25.364Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;27.32&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"time"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2023-06-27T18:14:30.364Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;28.14&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Complete code
&lt;/h2&gt;

&lt;p&gt;Below you can find the complete code for this example.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;IoTaaP_OS.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;Arduino.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;ArduinoJson.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;"Adafruit_BME280.h"&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="cp"&gt;#define TOKEN "&amp;lt;iotaap-link-secret&amp;gt;" // IoTaaP Link Secret
&lt;/span&gt;
&lt;span class="n"&gt;Adafruit_BME280&lt;/span&gt; &lt;span class="n"&gt;bme&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;         &lt;span class="c1"&gt;// I2C&lt;/span&gt;
&lt;span class="n"&gt;IoTaaP_OS&lt;/span&gt; &lt;span class="nf"&gt;iotaapOs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"3.2.8"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Defining Firmware version&lt;/span&gt;

&lt;span class="c1"&gt;// IoTaaP Network (MQTT) callback function&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;topic&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;byte&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"-------#-----#-----#----------"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Received data on the topic:"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;topic&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Print topic&lt;/span&gt;

  &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Data:"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Print message&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"------#------#------#---------"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// BME280 related stuff&lt;/span&gt;
  &lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bme&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;begin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mh"&gt;0x76&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Could not find a valid BME280 sensor, check wiring, address, sensor ID!"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="n"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="n"&gt;iotaapOs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Start IoTaaP OS&lt;/span&gt;

  &lt;span class="n"&gt;iotaapOs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;startWifi&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;         &lt;span class="c1"&gt;// Connect to WiFi&lt;/span&gt;
  &lt;span class="n"&gt;iotaapOs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;startMqtt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Connect to MQTT broker&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="c1"&gt;// Fetch measurements from BME280 sensor&lt;/span&gt;
  &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;temperatureC&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bme&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;readTemperature&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="c1"&gt;// Store temperature reading to IoTaaP Storage service, and subscribe to callback topic&lt;/span&gt;
  &lt;span class="n"&gt;iotaapOs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;storageServiceStore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TOKEN&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"temperature"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;temperatureC&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"/pgiIzx7n/storage/response"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="n"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>esp32</category>
      <category>iot</category>
      <category>cloud</category>
    </item>
    <item>
      <title>Sending SMS with ESP32</title>
      <dc:creator>Ivan Golubic</dc:creator>
      <pubDate>Tue, 04 Jul 2023 14:00:24 +0000</pubDate>
      <link>https://dev.to/igolubic/sending-sms-with-esp32-f0m</link>
      <guid>https://dev.to/igolubic/sending-sms-with-esp32-f0m</guid>
      <description>&lt;p&gt;In this tutorial we will write a simple code that will read temperature from &lt;a href="https://www.bosch-sensortec.com/products/environmental-sensors/humidity-sensors-bme280/"&gt;BME280 sensor&lt;/a&gt;, and if temperature is higher than 30°C it will send a SMS to the receivers number.&lt;/p&gt;

&lt;h2&gt;
  
  
  platformio.ini
&lt;/h2&gt;

&lt;p&gt;As usual we will use PlatformIO for this embedded project, and our platformio.ini should look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[env:release]
platform = espressif32
board = esp32dev
framework = arduino
monitor_speed = 115200
lib_deps = 
    iotaap/IoTaaP OS@^5.2.2
    adafruit/Adafruit BME280 Library@^2.2.2
board_build.partitions = partitions/default_fat.csv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Headers and declaration
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;IoTaaP_OS.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;Arduino.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;ArduinoJson.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;"Adafruit_BME280.h"&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="cp"&gt;#define TOKEN "&amp;lt;iotaap-link-secret&amp;gt;" // IoTaaP Link Secret
&lt;/span&gt;
&lt;span class="n"&gt;Adafruit_BME280&lt;/span&gt; &lt;span class="n"&gt;bme&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;         &lt;span class="c1"&gt;// I2C&lt;/span&gt;
&lt;span class="n"&gt;IoTaaP_OS&lt;/span&gt; &lt;span class="nf"&gt;iotaapOs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"3.2.8"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Defining Firmware version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We have to include our headers as usual, since Adafruit_BME280.h requires some functions from Arduino.h, we have to include it also. Additionally we have to declare our &lt;code&gt;bme&lt;/code&gt; sensor and create &lt;code&gt;iotaapOs&lt;/code&gt; object.&lt;/p&gt;

&lt;p&gt;Also we have to define &lt;strong&gt;TOKEN&lt;/strong&gt;, so please do not forget to replace &lt;code&gt;&amp;lt;iotaap-link-secret&amp;gt;&lt;/code&gt; with your IoTaaP Link Secret.&lt;/p&gt;

&lt;h2&gt;
  
  
  setup() function
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// BME280 related stuff&lt;/span&gt;
  &lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bme&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;begin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mh"&gt;0x76&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Could not find a valid BME280 sensor, check wiring, address, sensor ID!"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="n"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="n"&gt;iotaapOs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Start IoTaaP OS&lt;/span&gt;

  &lt;span class="n"&gt;iotaapOs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;startWifi&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;         &lt;span class="c1"&gt;// Connect to WiFi&lt;/span&gt;
  &lt;span class="n"&gt;iotaapOs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;startMqtt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Connect to MQTT broker&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the first part of the function, we are checking if BME280 is available and working, this is a good practice in this example, to eliminate further issues if sensor is not working properly. &lt;/p&gt;

&lt;p&gt;Next, we have to call &lt;strong&gt;iotaapOs.start()&lt;/strong&gt; function to start our IoTaaP OS services, this is followed by &lt;strong&gt;iotaapOs.startWifi()&lt;/strong&gt; to connect to start WiFi service and &lt;strong&gt;iotaapOs.startMqtt()&lt;/strong&gt; to connect to the IoTaaP network, and define MQTT callback function.&lt;/p&gt;

&lt;h2&gt;
  
  
  callback() function
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;topic&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;byte&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"-------#-----#-----#----------"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Received data on the topic:"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;topic&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Print topic&lt;/span&gt;

  &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Data:"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Print message&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"------#------#------#---------"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is basic MQTT callback function that will print received data and topic to our Serial Terminal, it is used to check the status of the service.&lt;/p&gt;

&lt;h2&gt;
  
  
  loop() function
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="c1"&gt;// Fetch measurements from BME280 sensor&lt;/span&gt;
  &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;temperatureC&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bme&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;readTemperature&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="c1"&gt;// If temperature is higher than 30°C, send SMS using IoTaaP SMS service, and subscribe to callback topic&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;temperatureC&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="n"&gt;sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Current temperature is: %.1f°C"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;temperatureC&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;iotaapOs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;smsServiceSend&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TOKEN&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"+38599"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"/pgiIzx7n/smsservice/response"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="n"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This function is repeated constantly, and it will read the temperature from our BME280 sensor and store it in &lt;code&gt;temperatureC&lt;/code&gt; variable. Next, we will check if temperature is higher than 30°C and if it is we will first craft our SMS message using &lt;code&gt;sprintf&lt;/code&gt; function. &lt;/p&gt;

&lt;p&gt;Finally, we will use &lt;code&gt;iotaapOs.smsServiceSend()&lt;/code&gt; function to send the SMS using IoTaaP SMS service. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Do not forget to &lt;strong&gt;update receivers phone number&lt;/strong&gt; (it must contain country code). Also your must have permission to listen on your callback topic.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Complete code
&lt;/h2&gt;

&lt;p&gt;Below you can find the complete code for this example.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;IoTaaP_OS.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;Arduino.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;ArduinoJson.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;"Adafruit_BME280.h"&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="cp"&gt;#define TOKEN "&amp;lt;iotaap-link-secret&amp;gt;" // IoTaaP Link Secret
&lt;/span&gt;
&lt;span class="n"&gt;Adafruit_BME280&lt;/span&gt; &lt;span class="n"&gt;bme&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;         &lt;span class="c1"&gt;// I2C&lt;/span&gt;
&lt;span class="n"&gt;IoTaaP_OS&lt;/span&gt; &lt;span class="nf"&gt;iotaapOs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"3.2.8"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Defining Firmware version&lt;/span&gt;

&lt;span class="c1"&gt;// IoTaaP Network (MQTT) callback function&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;topic&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;byte&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"-------#-----#-----#----------"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Received data on the topic:"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;topic&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Print topic&lt;/span&gt;

  &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Data:"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Print message&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"------#------#------#---------"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// BME280 related stuff&lt;/span&gt;
  &lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bme&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;begin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mh"&gt;0x76&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Could not find a valid BME280 sensor, check wiring, address, sensor ID!"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="n"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="n"&gt;iotaapOs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Start IoTaaP OS&lt;/span&gt;

  &lt;span class="n"&gt;iotaapOs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;startWifi&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;         &lt;span class="c1"&gt;// Connect to WiFi&lt;/span&gt;
  &lt;span class="n"&gt;iotaapOs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;startMqtt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Connect to MQTT broker&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="c1"&gt;// Fetch measurements from BME280 sensor&lt;/span&gt;
  &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;temperatureC&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bme&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;readTemperature&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="c1"&gt;// If temperature is higher than 30°C, send SMS using IoTaaP SMS service, and subscribe to callback topic&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;temperatureC&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="n"&gt;sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Current temperature is: %.1f°C"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;temperatureC&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;iotaapOs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;smsServiceSend&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TOKEN&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"+38599"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"/pgiIzx7n/smsservice/response"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="n"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>esp32</category>
      <category>iot</category>
      <category>cloud</category>
    </item>
  </channel>
</rss>
