# Getting Started

## **Prerequisites**

Before you begin, ensure you have the following:

* A Uniot-compatible device (e.g., ESP8266/ESP32 or Arduino-based hardware).
* A computer with internet access.
* Basic familiarity with IoT concepts (optional but helpful).

## **Installing Uniot Core Firmware**

1. The best way to get started with Uniot Core is to install it via [PlatformIO](https://platformio.org/). Here’s how to proceed:
2. Create a new PlatformIO project or open an existing one.
3. When configuring your `platformio.ini` file for Uniot Core, pay attention to the following important details:
   * **Uniot-Core Dependency Installation**: Ensure you include the `uniot-core` library in the `lib_deps` section to integrate Uniot's core features. Specify the version explicitly (e.g., `uniot-io/uniot-core@x.x.x`) to maintain compatibility.
   * **Setting Build Flags**: Use the `build_flags` section to customize the firmware behavior. Key flags include:
     * `-D UNIOT_USE_LITTLEFS` to specify the file system (e.g., LittleFS or SPIFFS by default).
     * `-D UNIOT_CREATOR_ID` for identifying the firmware creator.
     * `-D MQTT_MAX_PACKET_SIZE` to adjust MQTT buffer size if necessary.
     * `-D UNIOT_LISP_HEAP` to adjust the memory size of UniotLisp environment
     * `-D UNIOT_LOG_ENABLED` and `-D UNIOT_LOG_LEVEL` for enabling and configuring logging levels.
   * **Microcontroller Selection**: Define separate environments for each supported microcontroller model. For example:
     * `ESP12E` for ESP8266-based boards.
     * `ESP32` for ESP32 boards.
     * `ESP32C3` for ESP32-C3 boards with USB-specific configurations.
   * **Platform and Framework**: Ensure that the `platform` and `framework` settings match your microcontroller (e.g., `espressif8266` for ESP8266 or `espressif32` for ESP32).
   * **Filesystem Configuration**: Use the `board_build.filesystem` setting (e.g., `littlefs` - if `UNIOT_USE_LITTLEFS` is set to `1`) to specify the filesystem type supported by Uniot Core.
   * **Default Environment**: Set the `default_envs` to the environment corresponding to your primary microcontroller (e.g., `ESP12E`).
   * **USB and Debug Settings (Optional)**: For certain devices like the `ESP32C3`, additional USB-specific flags may be required, such as `-D ARDUINO_USB_MODE=1`.

By carefully customizing these parameters, you can ensure that your development environment is optimized for Uniot Core.

{% code title="platformio.ini" lineNumbers="true" %}

```ini
[platformio]

default_envs = ESP12E

[env]
board_build.filesystem = littlefs
monitor_speed = 115200
lib_deps =
    uniot-io/uniot-core@^0.8.1
build_unflags =
    -std=gnu++11
build_flags =
    -std=gnu++17
    -D UNIOT_USE_LITTLEFS=1
    -D UNIOT_CREATOR_ID=\"UNIOT\"
    -D MQTT_MAX_PACKET_SIZE=2048
    -D UNIOT_LOG_ENABLED=1
    -D UNIOT_LOG_LEVEL=4

[env:ESP12E]
platform = espressif8266
framework = arduino
board = esp12e

[env:ESP32]
platform = espressif32
framework = arduino
board = esp32doit-devkit-v1

[env:ESP32C3]
platform = espressif32
framework = arduino
board = esp32-c3-devkitm-1
build_flags =
    ${env.build_flags}
    -D ARDUINO_USB_MODE=1
    -D SERIALCONS=USBSerial
    -D ARDUINO_USB_CDC_ON_BOOT=1
```

{% endcode %}

1. As an example, we will use the ESP8266 Witty Cloud module. The module’s compact design and onboard LED's and sensors make it ideal for small IoT applications.

<div align="left"><figure><img src="https://1776027180-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsSE1iwGRAGqUrb5YXfFa%2Fuploads%2Fgit-blob-025b1246bf97c479f905c9edee9ebf9cc0941149%2Fguides_witty_cloud.png?alt=media" alt=""><figcaption></figcaption></figure></div>

The following code demonstrates setting up Uniot Core to manage digital and analog inputs/outputs for this module:

{% code title="main.cpp" lineNumbers="true" %}

```c++
#include <Uniot.h>

using namespace uniot;

// WittyCloud board pin definitions
#define PIN_BUTTON 4
#define PIN_RED 15
#define PIN_GREEN 12
#define PIN_BLUE 13
#define PIN_LDR A0

#define BTN_PIN_LEVEL LOW
#define LED_PIN_LEVEL HIGH

void setup() {
  // Configure WiFi with status LED and reset button
  Uniot.configWiFiStatusLed(PIN_RED, LED_PIN_LEVEL);
  Uniot.configWiFiResetButton(PIN_BUTTON, BTN_PIN_LEVEL);
  Uniot.configWiFiResetOnReboot(5, 10000);

  // Register GPIO pins for Lisp access
  Uniot.registerLispDigitalOutput(PIN_RED, PIN_GREEN, PIN_BLUE);
  Uniot.registerLispDigitalInput(PIN_BUTTON);
  Uniot.registerLispAnalogOutput(PIN_RED, PIN_GREEN, PIN_BLUE);
  Uniot.registerLispAnalogInput(PIN_LDR);

  // Initialize and start Uniot
  Uniot.begin();
}

void loop() {
  Uniot.loop();
}
```

{% endcode %}

This example showcases how to utilize Uniot Core features like managing digital/analog IOs and configuring WiFi. The Witty Cloud module’s capabilities, including onboard LEDs and a button, allow for a seamless testing environment.

5. After successful compilation, connect your device to your computer via USB.
6. Ensure your device is in bootloader mode before initiating the flashing process. For ESP8266, you may need to press and hold the FLASH button during power-up to enter the correct mode. Use commands like `pio run --target upload` to simplify the process with PlatformIO.

## **Adding Devices to the Platform**

1. Open the Uniot Platform ([Get Early Access](https://forms.fillout.com/t/k1LDnvkgvPus)) on your browser.
2. Create an account or log in if you already have one.
3. To add a new device to the Uniot Platform, navigate to the Devices page, click the **“Add new device”** button, and follow instructions.
4. After adding and authorising the device, you can deploy an automation script on it.

## **Your First Automation Script**

1. For an easy start, navigate to the Sandbox page and locate the welcome script titled **“My First Script”**.

<div align="left"><figure><img src="https://1776027180-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsSE1iwGRAGqUrb5YXfFa%2Fuploads%2Fgit-blob-f5b539a091d30e7e69c43188e4385ab2405320d7%2Fguides_first_script.png?alt=media" alt=""><figcaption></figcaption></figure></div>

This visual script generates the following code, which is executed directly on the device:

```lisp
;;; begin-user-library
;; This block describes the library of user functions.
;; So the editor knows that your device implements it.
;
; (defjs bclicked (button_id)) ;-> Bool
; (defjs dwrite (pin state)) ;-> Bool
;
;;; end-user-library

(define state ())

(setq state ())

; Runs the task every '50' ms. Since 'times' is '0',
; it runs indefinitely. The context is released after
; each run, allowing other processes to run smoothly.
(task 0 50 '
 (list
  ; If the button '0' is clicked, emit an event 'led' to toggle state.
  (if
   (bclicked 0)
   (list
    (push_event 'led
     (not state))))
  ; When the ‘led’ event is triggered, set ‘state’ to the received
  ; value and write to pin ‘0’, driving the LED accordingly.
  (if
   (is_event 'led)
   (list
    (setq state
     (pop_event 'led))
    (dwrite 0 state)))))
```

This script uses several blocks to demonstrate key concepts of automation:

* **State Variable Initialization**: The block initializes a `state` variable as `false`. This variable tracks the LED's on/off status.
* **Run Task Block**: Configured to run every 50 milliseconds indefinitely (as the `times` parameter is set to `0`), ensuring the script continuously checks button activity and event triggers.
* **Button Check Block**: Monitors if the button (that occupies the register with index `0`, for details check the list of registers, which can be found in the device information on the Devices page) is clicked. When clicked, a global event named `led` is generated. This event can be heard by other devices in the network as well as by the dashboard, emitted with the toggled state value (`not state`).
* **Event Trigger Block**: Responds to the `led` event by updating the `state` variable to the event's value and writing the new state to pin with registered index `0`, controlling the LED.
