IzyDisplay Developer Guide

Version: 2.0.0
Device Model: IZYDISPLAY
Display: 480x272 RGB LCD with Capacitive Touch

Table of Contents

  1. Overview
  2. First-Time Setup
  3. Device Settings
  4. API Reference
  5. Widget Types
  6. Styling Guide
  7. Event System
  8. Examples

Overview

IzyDisplay is a WiFi-enabled smart display that receives UI templates via HTTP and renders them. It features:


First-Time Setup

Step 1: Power On the Device

On first boot, the device enters Setup Mode automatically (no WiFi configured).

Step 2: Connect to Setup WiFi

  1. Look for WiFi network: IZYDISPLAY_<device_id>
    • Example: IZYDISPLAY_E89F6D123456
  2. Connect to it (no password required)
  3. Your phone/computer will show a captive portal

Step 3: Configure via Web Portal

The setup page will open automatically at http://192.168.4.1

Configuration Options:

Field Description Required
WiFi Network SSID of your WiFi network (can scan) Yes
WiFi Password WiFi password Yes
Network Mode DHCP (automatic) or Static IP Yes
IP Address Static IP (only if Static mode selected) If Static
Netmask Network mask (default: 255.255.255.0) If Static
Gateway Gateway IP (default: router IP) If Static
Display Name Friendly name for this display No
Server URL Optional server URL (for reference only) No
Enable Secure Communication Checkbox to enable access token authentication No
Access Token Security token (only if secure communication enabled) If Enabled

Setup Portal Screenshots:

Setup Web Portal - Full Configuration Complete setup form with all configuration options

Setup Web Portal - Optional Access Token Optional access token feature with checkbox to enable secure communication

Step 4: Save & Connect

  1. Click "Save & Apply"
  2. Device will reboot and connect to your WiFi
  3. Check your router for the device's IP address

Setup Web Portal - Save Confirmation Save confirmation with reboot message

Finding Device IP:


Device Settings

Accessing Settings Screen

Long-press (3 seconds) on the app name at the top of the display.

Settings Information:

Available Actions:


API Reference

Base URL

http://<device_ip>

Replace <device_ip> with your device's IP address (e.g., 192.168.1.18).

Endpoints

1. Root Endpoint - Device Info

GET /

Response:

<h1>IzyDisplay Smart Screen</h1>
<p>Device ID: E89F6D123456</p>
<p>Version: 2.0.0</p>
<p>Status: Online</p>

2. UI Template Endpoint

POST /ui
Content-Type: application/json
X-Access-Token: <your_token>

Request Body:

{
  "template": {
    "template_id": "optional_id",
    "widgets": [ /* widget array */ ]
  },
  "data": {
    "key": "value"
  }
}

Important Notes:

Headers:

Response:

{
  "status": "success",
  "message": "Template loaded"
}

Error Responses:

{
  "status": "error",
  "message": "Invalid access token"
}
{
  "status": "error",
  "message": "Invalid JSON"
}

Widget Types

1. Label

Display text with styling.

{
  "type": "label",
  "id": "title",
  "text": "Hello World",
  "x": 10,
  "y": 10,
  "width": 460,
  "style": {
    "text_color": "#FFFFFF",
    "text_font": "MONTSERRAT_24",
    "text_align": "center"
  }
}

2. Button

Interactive button with click events.

{
  "type": "button",
  "id": "submit_btn",
  "text": "Submit",
  "x": 190,
  "y": 200,
  "width": 100,
  "height": 50,
  "style": {
    "bg_color": "#0EA5E9",
    "text_color": "#FFFFFF",
    "radius": 10
  },
  "onClick": {
    "target_url": "http://192.168.1.100/api/submit",
    "method": "POST",
    "params": {
      "action": "submit"
    }
  }
}

3. QR Code

Display QR codes for URLs, text, etc.

{
  "type": "qrcode",
  "id": "qr1",
  "text": "https://example.com",
  "size": 200,
  "x": 140,
  "y": 36,
  "style": {
    "bg_color": "#FFFFFF",
    "fg_color": "#000000"
  }
}

4. Slider

Adjustable slider with value change events.

{
  "type": "slider",
  "id": "brightness",
  "min": 0,
  "max": 100,
  "value": 50,
  "x": 50,
  "y": 100,
  "width": 380,
  "onChange": {
    "target_url": "http://192.168.1.100/api/brightness",
    "method": "POST",
    "params": {
      "value": "${self}"
    }
  }
}

Note: Slider onChange events trigger only when the user releases the slider (not during dragging) to avoid flooding the network with requests and maintain smooth UI performance.

5. Switch

On/off toggle switch.

{
  "type": "switch",
  "id": "power",
  "checked": true,
  "x": 200,
  "y": 150,
  "onChange": {
    "target_url": "http://192.168.1.100/api/power",
    "method": "POST",
    "params": {
      "state": "${self}"
    }
  }
}

6. Checkbox

Checkbox with label.

{
  "type": "checkbox",
  "id": "agree",
  "text": "I agree to terms",
  "checked": false,
  "x": 50,
  "y": 200
}

7. Image

Display PNG or GIF images from URL or base64.

Supported Formats:

From URL:

{
  "type": "image",
  "id": "logo",
  "src": "https://example.com/logo.png",
  "x": 200,
  "y": 50,
  "width": 183,
  "height": 156
}

Base64 Image:

{
  "type": "image",
  "id": "logo_b64",
  "src": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...",
  "align": "center"
}

Note: Maximum image size is 512KB. Images are cached in PSRAM (up to 5 images).

8. Container (Panel)

Container for grouping widgets.

{
  "type": "obj",
  "id": "panel1",
  "x": 10,
  "y": 10,
  "width": 460,
  "height": 250,
  "scrollable": true,
  "scroll_dir": "vertical",
  "style": {
    "bg_color": "#1E293B",
    "radius": 10,
    "pad_all": 10
  },
  "widgets": [
    /* child widgets */
  ]
}

9. Spinner

Loading spinner animation.

{
  "type": "spinner",
  "id": "loader",
  "x": 220,
  "y": 116,
  "width": 40,
  "height": 40
}

10. Toast

Android-style temporary message that auto-dismisses after duration.

{
  "type": "toast",
  "text": "Operation successful!",
  "duration": 3000,
  "position": "bottom"
}

Properties:

Note: Toasts float on top of all other widgets and automatically delete themselves after the specified duration.


Styling Guide

Common Style Properties

Property Type Example Description
text_color Color "#FFFFFF" Text color
text_font String "MONTSERRAT_24" Font name
text_align String "center" left, center, right
text_opa Integer 255 Text opacity (0-255)
bg_color Color "#000000" Background color
bg_opa Integer 200 Background opacity
fg_color Color "#FFFFFF" Foreground color (QR)
border_color Color "#0EA5E9" Border color
border_width Integer 2 Border width in pixels
radius Integer 10 Corner radius
pad_all Integer 10 Padding (all sides)

Available Fonts

Font Name Size Use Case
DIGITAL_100 100px Large digital numbers
CENTURY_38 38px Headings
LV_FONT_DEJAVU_16_PERSIAN_HEBREW 16px RTL languages

Built-in fonts not listed (MONTSERRAT_14-60 available).

Color Formats

"#FFFFFF"         // Hex RGB
"#FFF"            // Short hex
{"r": 255, "g": 255, "b": 255}  // RGB object

Event System

onClick Event

Triggered when a widget is clicked (button, label, etc.).

{
  "type": "button",
  "id": "action_btn",
  "onClick": {
    "target_url": "http://192.168.1.100/api/action",
    "method": "POST",
    "params": {
      "action": "start",
      "timestamp": "${timestamp}"
    }
  }
}

onChange Event

Triggered when a widget value changes (slider, switch, checkbox).

{
  "type": "slider",
  "id": "volume",
  "onChange": {
    "target_url": "http://192.168.1.100/api/volume",
    "method": "POST",
    "params": {
      "level": "${self}",
      "device_id": "living_room"
    }
  }
}

Parameter Substitution

Pattern Description Example Value
${self} Current widget value "75" (slider)
${value} Alias for ${self} "true" (switch)
${widget_id} Value from another widget "50"
Static value Passed as-is "hello"

Example with Multiple Widget Values:

{
  "type": "button",
  "id": "submit",
  "onClick": {
    "target_url": "http://192.168.1.100/api/settings",
    "method": "POST",
    "params": {
      "brightness": "${brightness_slider}",
      "power": "${power_switch}",
      "mode": "manual"
    }
  }
}

Event Request Format

When an event is triggered, the device sends:

Request:

POST http://192.168.1.100/api/action
Content-Type: application/json

{
  "value": "75",
  "widget_id": "brightness_slider",
  "brightness": "75",
  "power": "true",
  "mode": "manual"
}

Examples

Example 1: Simple Welcome Screen

curl -X POST http://192.168.1.18/ui \
  -H "Content-Type: application/json" \
  -H "X-Access-Token: IZYDISPLAY@2026" \
  -d '{
    "template": {
      "template_id": "welcome",
      "widgets": [
        {
          "type": "label",
          "text": "Welcome to IzyDisplay",
          "x": 0,
          "y": 100,
          "width": 480,
          "style": {
            "text_color": "#38BDF8",
            "text_align": "center"
          }
        }
      ]
    }
  }'

Example 2: Interactive Brightness Control

curl -X POST http://192.168.1.18/ui \
  -H "Content-Type: application/json" \
  -H "X-Access-Token: IZYDISPLAY@2026" \
  -d '{
    "template": {
      "widgets": [
        {
          "type": "label",
          "id": "title",
          "text": "Brightness Control",
          "x": 0,
          "y": 20,
          "width": 480,
          "style": {
            "text_align": "center",
            "text_color": "#FFFFFF"
          }
        },
        {
          "type": "slider",
          "id": "brightness",
          "min": 0,
          "max": 100,
          "value": 50,
          "x": 50,
          "y": 120,
          "width": 380,
          "onChange": {
            "target_url": "http://192.168.1.100/api/brightness",
            "method": "POST",
            "params": {
              "level": "${self}"
            }
          }
        },
        {
          "type": "label",
          "id": "value_label",
          "text": "50%",
          "x": 0,
          "y": 160,
          "width": 480,
          "style": {
            "text_align": "center"
          }
        }
      ]
    }
  }'

Example 3: QR Code Display

curl -X POST http://192.168.1.18/ui \
  -H "Content-Type: application/json" \
  -H "X-Access-Token: IZYDISPLAY@2026" \
  -d '{
    "template": {
      "widgets": [
        {
          "type": "qrcode",
          "text": "https://massani3.com",
          "size": 200,
          "x": 140,
          "y": 36
        },
        {
          "type": "label",
          "text": "Scan to visit",
          "x": 0,
          "y": 240,
          "width": 480,
          "style": {
            "text_align": "center",
            "text_color": "#94A3B8"
          }
        }
      ]
    }
  }'

Example 4: Dashboard with Multiple Widgets

curl -X POST http://192.168.1.18/ui \
  -H "Content-Type: application/json" \
  -H "X-Access-Token: IZYDISPLAY@2026" \
  -d '{
    "template": {
      "template_id": "dashboard",
      "widgets": [
        {
          "type": "label",
          "text": "Smart Home Dashboard",
          "x": 0,
          "y": 10,
          "width": 480,
          "style": {
            "text_align": "center",
            "text_color": "#38BDF8"
          }
        },
        {
          "type": "obj",
          "x": 10,
          "y": 50,
          "width": 220,
          "height": 200,
          "style": {
            "bg_color": "#1E293B",
            "radius": 10,
            "pad_all": 15
          },
          "widgets": [
            {
              "type": "label",
              "text": "Living Room",
              "x": 0,
              "y": 0,
              "style": {
                "text_color": "#FFFFFF"
              }
            },
            {
              "type": "switch",
              "id": "living_power",
              "checked": true,
              "x": 10,
              "y": 40,
              "onChange": {
                "target_url": "http://192.168.1.100/api/room/living",
                "method": "POST",
                "params": {
                  "power": "${self}"
                }
              }
            },
            {
              "type": "slider",
              "id": "living_bright",
              "min": 0,
              "max": 100,
              "value": 75,
              "x": 10,
              "y": 100,
              "width": 180,
              "onChange": {
                "target_url": "http://192.168.1.100/api/room/living",
                "method": "POST",
                "params": {
                  "brightness": "${self}"
                }
              }
            }
          ]
        },
        {
          "type": "obj",
          "x": 250,
          "y": 50,
          "width": 220,
          "height": 200,
          "style": {
            "bg_color": "#1E293B",
            "radius": 10,
            "pad_all": 15
          },
          "widgets": [
            {
              "type": "label",
              "text": "Bedroom",
              "x": 0,
              "y": 0,
              "style": {
                "text_color": "#FFFFFF"
              }
            },
            {
              "type": "switch",
              "id": "bedroom_power",
              "checked": false,
              "x": 10,
              "y": 40
            }
          ]
        }
      ]
    }
  }'

Example 5: Template Variables

curl -X POST http://192.168.1.18/ui \
  -H "Content-Type: application/json" \
  -H "X-Access-Token: IZYDISPLAY@2026" \
  -d '{
    "template": {
      "widgets": [
        {
          "type": "label",
          "text": "Temperature: ${temp}°C",
          "x": 50,
          "y": 100
        },
        {
          "type": "label",
          "text": "Humidity: ${humidity}%",
          "x": 50,
          "y": 130
        }
      ]
    },
    "data": {
      "temp": "24.5",
      "humidity": "65"
    }
  }'

Serial Commands

Connect via USB serial (115200 baud) for debugging:

Command Description
HELP Show all commands
GET_INFO Device model/version
PRINTCONFIG Show configuration
WIFI_STATUS WiFi connection info
WIFI_RECONNECT Reconnect WiFi
RESET Factory reset
REBOOT Reboot device
RENDERER_STATUS Show active template
RENDERER_CLEAR Clear template
MSG:text Show toast message

Troubleshooting

Device Not Responding

  1. Check WiFi connection: WIFI_STATUS via serial
  2. Verify IP address in router
  3. Ping the device: ping 192.168.1.18
  4. Check access token matches

Template Not Loading

  1. Validate JSON syntax
  2. Check X-Access-Token header
  3. View serial output for errors
  4. Try with simple template first

Data Updates Fail with "No active template"

Error: 400 {"error":"No active template"}

Cause: Using "id" instead of "template_id" in template

Solution:

// ❌ WRONG - will fail data updates
{
  "template": {
    "id": "my_template",  // Wrong field name!
    "widgets": [...]
  }
}

// ✅ CORRECT - enables data updates
{
  "template": {
    "template_id": "my_template",  // Correct field name
    "widgets": [...]
  }
}

Then data-only updates will work:

{
  "data": {
    "temp": "25.0",
    "humidity": "60"
  }
}

Events Not Firing

  1. Ensure target URL is accessible from device
  2. Check serial monitor for HTTP errors
  3. Verify WiFi connectivity
  4. Confirm event URLs are correct

Factory Reset

  1. Long-press app name (3 seconds)
  2. Click Reset button
  3. OR send RESET via serial
  4. Device will reboot to setup mode

Security Notes

  1. Change default access token in setup
  2. Use strong tokens (16+ characters, mix of letters/numbers/symbols)
  3. Don't expose device directly to internet
  4. Keep device on secure local network

Technical Specifications

Spec Value
Display 480x272 RGB LCD
Touch Capacitive (5-point)
WiFi 802.11 b/g/n (2.4GHz)
Interface USB-C (CDC serial + power)
Power 5V USB-C

Happy Building! 🚀