Skip to content

@xcons/cli-thingsboard - Widget Create Kılavuzu

Bu dokümantasyon, XCONS ThingsBoard CLI ile widget projesi oluşturma işlemlerini detaylı olarak açıklar.

Widget Create Komutu

bash
xcons-thingsboard widget create [name] [options]

Parametreler

  • name (isteğe bağlı): Widget proje adı

Seçenekler

  • -n, --name <name>: Widget adı
  • -t, --type <type>: Widget türü (timeseries, latest, latest-values, rpc, static)
  • -d, --description <desc>: Widget açıklaması
  • --no-interaction: İnteraktif sorları atla

Widget Türleri

TimeSeries Widgets

Zaman serisi verilerini görüntülemek için kullanılır.

bash
# TimeSeries widget oluştur
xcons-thingsboard widget create temperature-monitor --type timeseries

# Açıklamalı TimeSeries widget
xcons-thingsboard widget create sensor-dashboard \
  --type timeseries \
  --description "Real-time sensor data monitoring dashboard"

Kullanım Alanları:

  • Sıcaklık, nem, basınç grafikleri
  • Güç tüketimi izleme
  • Sensör veri trendleri
  • Zaman bazlı analitik dashboardlar

Latest Values Widgets

Güncel telemetri değerlerini göstermek için kullanılır.

bash
# Latest values widget oluştur
xcons-thingsboard widget create device-status --type latest

# Latest-values alias'ı ile
xcons-thingsboard widget create current-readings --type latest-values

Kullanım Alanları:

  • Cihaz durumu göstergeleri
  • Son sensör okumaları
  • Anlık değer panelleri
  • Status indicator'ları

RPC Control Widgets

Cihaz kontrolü ve RPC komutları için kullanılır.

bash
# RPC control widget oluştur
xcons-thingsboard widget create device-controller --type rpc

# Control alias'ı ile
xcons-thingsboard widget create pump-control --type control

Kullanım Alanları:

  • Cihaz açma/kapama kontrolleri
  • Motor hız kontrolü
  • Valve pozisyon ayarları
  • Uzaktan komut panelleri

Static Widgets

Statik HTML içeriği için kullanılır.

bash
# Static widget oluştur
xcons-thingsboard widget create info-panel --type static

# Açıklamalı static widget
xcons-thingsboard widget create company-logo \
  --type static \
  --description "Company branding and information panel"

Kullanım Alanları:

  • Bilgilendirme panelleri
  • Logo ve branding
  • Statik dokümantasyon
  • HTML tabanlı içerikler

Temel Kullanım

İnteraktif Widget Oluşturma

bash
# Tüm parametreler interaktif sorulur
xcons-thingsboard widget create

# İsim belirtilip diğerleri interaktif sorulur
xcons-thingsboard widget create my-awesome-widget

İnteraktif Soru Sırası:

? Widget name: temperature-sensor
? Select widget type: 
❯ Time Series - For displaying time series data
  Latest Values - For showing current telemetry values  
  RPC Control - For device control via RPC
  Static - Static HTML content
? Widget description: Temperature monitoring sensor widget

Parametreli Widget Oluşturma

bash
# Tüm parametrelerle widget oluştur
xcons-thingsboard widget create temperature-dashboard \
  --type timeseries \
  --description "Advanced temperature monitoring dashboard with charts"

# İnteraktif soruları atla
xcons-thingsboard widget create simple-widget \
  --type latest \
  --no-interaction

Proje Yapısı

Oluşturulan widget projesi şu yapıya sahiptir:

my-widget/
├── .xcon/
│   └── config.json              # XCONS widget konfigürasyonu
├── .idea/                       # IntelliJ IDEA konfigürasyonu
│   ├── modules.xml
│   ├── my-widget.iml
│   └── workspace.xml
├── src/
│   ├── index.ts                 # Ana widget TypeScript kodu
│   ├── index.html               # Widget HTML template
│   └── style.css                # Widget CSS stilleri
├── dist/                        # Derlenmiş widget dosyaları (build sonrası)
├── package.json                 # NPM bağımlılıkları ve scriptleri
├── tsconfig.json                # TypeScript konfigürasyonu
└── README.md                    # Widget dokümantasyonu

.xcon/config.json

json
{
  "configurations": {
    "provider": "thingsboard",
    "id": "",
    "type": "timeseries"
  },
  "projectType": "widget",
  "version": "1.0"
}

src/index.ts (Ana Widget Kodu)

typescript
import { Widget, property, computed } from '@xcons/widget';

@Widget({
    widgetName: 'My Awesome Widget',
    widgetDescription: 'Description of my widget functionality',
    widgetVersion: '1.0.0',
    templateUrl: './index.html',
    styleUrls: ['./style.css'],
    resources: [
        {
            type: 'js',
            url: 'https://cdn.jsdelivr.net/npm/chart.js',
            name: 'Chart.js Library'
        }
    ],
    selector: 'tb-my-widget'
})
export default class MyWidget {
    @property()
    public data: any[] = [];

    @property()
    public title: string = 'My Widget';

    @property()
    public isLoading: boolean = false;

    @computed()
    get hasData(): boolean {
        return this.data && this.data.length > 0;
    }

    onInit() {
        console.log('Widget initialized:', this.title);
        this.initializeComponents();
    }

    onDataUpdated() {
        console.log('Data updated:', this.data);
        this.processData();
    }

    onResize() {
        console.log('Widget resized');
        this.adjustLayout();
    }

    private initializeComponents() {
        // Widget bileşenlerini başlat
    }

    private processData() {
        // Veri işleme mantığı
        if (this.hasData) {
            this.updateDisplay();
        }
    }

    private adjustLayout() {
        // Layout ayarlama mantığı
    }

    private updateDisplay() {
        // Görüntü güncelleme mantığı
    }

    onDestroy() {
        console.log('Widget destroyed');
        this.cleanup();
    }

    private cleanup() {
        // Temizlik işlemleri
    }
}

src/index.html (HTML Template)

html
<div class="widget-container">
    <!-- Widget Header -->
    <div class="widget-header">
        <h3 class="widget-title" x:text="title"></h3>
        <div class="widget-actions">
            <button x:on:click="refreshData" x:attr:disabled="isLoading">
                <span x:text="isLoading ? 'Loading...' : 'Refresh'"></span>
            </button>
        </div>
    </div>

    <!-- Widget Content -->
    <div class="widget-content" x:show="hasData">
        <div class="data-display">
            <!-- Veri gösterimi alanı -->
            <div class="chart-container">
                <canvas id="dataChart"></canvas>
            </div>
            
            <div class="stats-panel">
                <div class="stat-item">
                    <span class="stat-label">Total Records:</span>
                    <span class="stat-value" x:text="data.length"></span>
                </div>
            </div>
        </div>
    </div>

    <!-- Empty State -->
    <div class="empty-state" x:show="!hasData && !isLoading">
        <div class="empty-icon">📊</div>
        <h4>No Data Available</h4>
        <p>Widget is waiting for data to display.</p>
    </div>

    <!-- Loading State -->
    <div class="loading-state" x:show="isLoading">
        <div class="spinner"></div>
        <p>Loading data...</p>
    </div>
</div>

src/style.css (CSS Stilleri)

css
.widget-container {
    padding: 16px;
    height: 100%;
    display: flex;
    flex-direction: column;
    font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
    background-color: #ffffff;
    border-radius: 8px;
    box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}

.widget-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 16px;
    padding-bottom: 12px;
    border-bottom: 1px solid #e0e0e0;
}

.widget-title {
    margin: 0;
    font-size: 18px;
    font-weight: 600;
    color: #333;
}

.widget-actions button {
    padding: 8px 16px;
    border: 1px solid #ddd;
    border-radius: 4px;
    background-color: #fff;
    cursor: pointer;
    font-size: 14px;
    transition: all 0.2s ease;
}

.widget-actions button:hover:not(:disabled) {
    background-color: #f8f9fa;
    border-color: #007bff;
    color: #007bff;
}

.widget-actions button:disabled {
    opacity: 0.6;
    cursor: not-allowed;
}

.widget-content {
    flex: 1;
    display: flex;
    flex-direction: column;
}

.data-display {
    flex: 1;
    display: flex;
    flex-direction: column;
}

.chart-container {
    flex: 1;
    position: relative;
    margin-bottom: 16px;
    min-height: 200px;
}

.stats-panel {
    display: flex;
    flex-wrap: wrap;
    gap: 16px;
    padding: 12px;
    background-color: #f8f9fa;
    border-radius: 4px;
}

.stat-item {
    display: flex;
    flex-direction: column;
    align-items: center;
}

.stat-label {
    font-size: 12px;
    color: #666;
    margin-bottom: 4px;
}

.stat-value {
    font-size: 18px;
    font-weight: 600;
    color: #333;
}

.empty-state, .loading-state {
    flex: 1;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    text-align: center;
    color: #666;
}

.empty-icon {
    font-size: 48px;
    margin-bottom: 16px;
    opacity: 0.5;
}

.empty-state h4 {
    margin: 8px 0;
    color: #333;
}

.empty-state p {
    margin: 0;
    font-size: 14px;
}

.loading-state .spinner {
    width: 40px;
    height: 40px;
    border: 4px solid #f3f3f3;
    border-top: 4px solid #007bff;
    border-radius: 50%;
    animation: spin 1s linear infinite;
    margin-bottom: 16px;
}

@keyframes spin {
    0% { transform: rotate(0deg); }
    100% { transform: rotate(360deg); }
}

/* Responsive tasarım */
@media (max-width: 768px) {
    .widget-container {
        padding: 12px;
    }
    
    .widget-header {
        flex-direction: column;
        gap: 12px;
        align-items: flex-start;
    }
    
    .stats-panel {
        flex-direction: column;
        gap: 8px;
    }
}

package.json

json
{
  "name": "my-widget",
  "version": "1.0.0",
  "description": "My ThingsBoard Widget",
  "main": "dist/widget.js",
  "scripts": {
    "build": "xcons-thingsboard widget build",
    "build:prod": "xcons-thingsboard widget build --production",
    "build:debug": "xcons-thingsboard widget build --debug",
    "install:server": "xcons-thingsboard widget install",
    "install:debug": "xcons-thingsboard widget install --debug"
  },
  "dependencies": {
    "@xcons/widget": "^1.0.0",
    "chart.js": "^4.0.0"
  },
  "devDependencies": {
    "@types/node": "^20.0.0",
    "typescript": "^5.0.0"
  },
  "keywords": [
    "thingsboard",
    "widget",
    "iot",
    "dashboard"
  ],
  "author": "Your Name",
  "license": "MIT"
}

Geliştirme İş Akışı

1. Widget Oluşturma

bash
# Widget projesi oluştur
xcons-thingsboard widget create temperature-monitor --type timeseries

# Proje dizinine geç
cd temperature-monitor

2. Bağımlılık Kurulumu

bash
# Otomatik (create sırasında sorulur)
# veya manuel kurulum
npm install

3. Geliştirme

bash
# Widget kodunu düzenle
# src/index.ts - Ana widget mantığı
# src/index.html - HTML template
# src/style.css - Stiller

# Build ve test
npm run build:debug

4. ThingsBoard'a Yükleme

bash
# Widget'ı sunucuya yükle
npm run install:server

# veya debug modu ile
npm run install:debug

Widget Type Örnekleri

TimeSeries Widget Örneği

bash
xcons-thingsboard widget create energy-consumption --type timeseries

Kullanım Senaryosu:

  • Enerji tüketimi grafiği
  • Zaman serisi veri görselleştirme
  • Trend analizi

Latest Values Widget Örneği

bash
xcons-thingsboard widget create device-overview --type latest

Kullanım Senaryosu:

  • Cihaz durumu paneli
  • Son sensör değerleri
  • Anlık durum göstergesi

RPC Control Widget Örneği

bash
xcons-thingsboard widget create motor-controller --type rpc

Kullanım Senaryosu:

  • Motor start/stop kontrolü
  • Hız ayarlama
  • Uzaktan cihaz yönetimi

Static Widget Örneği

bash
xcons-thingsboard widget create help-documentation --type static

Kullanım Senaryosu:

  • Yardım dokümantasyonu
  • Kullanım talimatları
  • Statik bilgilendirme

Template Özelleştirmesi

GitHub Template İndirme

CLI otomatik olarak GitHub'dan template indirir:

Source: https://github.com/xcon-studio/xcon-web-widget-template-basic-thingsboard
Branch: main

Template İçeriği

  • TypeScript Desteği: Modern ES2020+ özellikleri
  • XCONS Decorators: @Widget, @property, @computed
  • HTML Template Binding: x:text, x:show, x🔛click
  • CSS Framework: Responsive tasarım ve modern stiller
  • Build System: XCONS Build Engine entegrasyonu
  • IDE Support: IntelliJ IDEA konfigürasyonları

Pratik Örnekler

IoT Sensor Dashboard

bash
xcons-thingsboard widget create iot-sensor-dashboard \
  --type timeseries \
  --description "Comprehensive IoT sensor data visualization dashboard"

cd iot-sensor-dashboard
npm install

Device Control Panel

bash
xcons-thingsboard widget create device-control-panel \
  --type rpc \
  --description "Remote device control and monitoring panel"

cd device-control-panel
npm install

Status Indicator Widget

bash
xcons-thingsboard widget create status-indicator \
  --type latest \
  --description "Real-time device status and health indicator"

cd status-indicator
npm install

Information Display

bash
xcons-thingsboard widget create info-display \
  --type static \
  --description "Static information and documentation display panel"

cd info-display
npm install

Toplu Widget Oluşturma

Script ile Çoklu Widget

bash
#!/bin/bash

# Widget tanımları
widgets=(
  "temperature-monitor:timeseries:Temperature monitoring and trending"
  "humidity-tracker:timeseries:Humidity level tracking over time"
  "device-controller:rpc:Remote device control interface"
  "status-panel:latest:Current device status display"
  "help-guide:static:User help and documentation"
)

# Widget'ları oluştur
for widget_def in "${widgets[@]}"; do
    IFS=':' read -r name type desc <<< "$widget_def"
    
    echo "Creating widget: $name ($type)"
    xcons-thingsboard widget create "$name" \
        --type "$type" \
        --description "$desc" \
        --no-interaction
    
    # Bağımlılıkları kur
    cd "$name"
    npm install
    cd ..
    
    echo "Widget '$name' created successfully"
    echo "---"
done

echo "All widgets created successfully!"

Departman Bazlı Widget'lar

bash
# Engineering widgets
engineering_widgets=("power-analysis:timeseries" "load-controller:rpc" "system-status:latest")

# Production widgets  
production_widgets=("quality-metrics:timeseries" "machine-control:rpc" "production-status:latest")

# Operations widgets
operations_widgets=("operational-kpis:timeseries" "facility-control:rpc" "ops-dashboard:latest")

create_department_widgets() {
    local dept=$1
    shift
    local widgets=("$@")
    
    mkdir -p "$dept-widgets"
    cd "$dept-widgets"
    
    for widget in "${widgets[@]}"; do
        IFS=':' read -r name type <<< "$widget"
        xcons-thingsboard widget create "$name" \
            --type "$type" \
            --description "$dept department $name widget" \
            --no-interaction
    done
    
    cd ..
}

# Departman widget'larını oluştur
create_department_widgets "engineering" "${engineering_widgets[@]}"
create_department_widgets "production" "${production_widgets[@]}"
create_department_widgets "operations" "${operations_widgets[@]}"

Troubleshooting

Template İndirme Hataları

Hata: Failed to download template: ETIMEDOUT

Çözüm:

bash
# Ağ bağlantısını kontrol et
ping github.com

# Proxy ayarları (gerekirse)
npm config set proxy http://proxy:8080
npm config set https-proxy http://proxy:8080

# Tekrar dene
xcons-thingsboard widget create my-widget --type timeseries

NPM Install Hataları

Hata: npm install failed with exit code: 1

Çözüm:

bash
# Manuel npm install
cd my-widget
npm cache clean --force
npm install

# Node.js sürümünü kontrol et
node --version  # 18+ gerekli

# NPM sürümünü kontrol et  
npm --version   # 9+ gerekli

Dizin Çakışması

Hata: Directory 'my-widget' already exists and is not empty

Çözüm:

bash
# Mevcut dizini sil
rm -rf my-widget

# Veya farklı isim kullan
xcons-thingsboard widget create my-widget-v2 --type timeseries

# Veya mevcut dizini taşı
mv my-widget my-widget-backup

IntelliJ IDEA Konfigürasyon Hataları

Hata: .idea dosyalarında sorun

Çözüm:

bash
# .idea dizinini sil ve yeniden oluştur
rm -rf .idea

# IntelliJ IDEA'da projeyi yeniden aç
# File → Open → Proje dizini seç

Gelişmiş Kullanım

Custom Template Kullanımı

bash
# Farklı template branch'i (gelecek özellik)
# xcons-thingsboard widget create my-widget --template advanced

# Manuel template özelleştirmesi
xcons-thingsboard widget create my-widget --type timeseries
cd my-widget

# src/index.ts dosyasını özelleştir
# Harici kütüphaneler ekle
# Template binding'leri genişlet

IDE Entegrasyonu

bash
# VS Code için
code my-widget

# IntelliJ IDEA için (otomatik konfigürasyon mevcut)
idea my-widget

# WebStorm için
webstorm my-widget

Sonraki Adımlar

Widget oluşturduktan sonra:

  1. Widget Build - Widget'ı derleme
  2. Widget Install - Widget'ı ThingsBoard'a yükleme
  3. Konfigürasyon - İleri seviye konfigürasyon

Widget projesi başarıyla oluşturuldu! Geliştirmeye başlayabilirsiniz.