Skip to content

wojt-janowski/laravel-switchbot

Repository files navigation

Laravel SwitchBot

Laravel package for SwitchBot API v1.1 integration with support for polling and webhooks. Supports SwitchBot Meter Plus and Hub 2 devices for temperature, humidity, and battery monitoring.

Features

  • HMAC-SHA256 Authentication - Secure API v1.1 authentication
  • Device Polling - Configurable automatic polling via Laravel scheduler
  • Webhook Support - Receive real-time updates from SwitchBot
  • Change Detection - Smart threshold-based change detection
  • Event System - Laravel events for status changes
  • Caching - Efficient caching of device states
  • Facade & DI - Both Facade and Dependency Injection support
  • Workbench UI - Simple web dashboard for testing
  • Artisan Commands - Manual polling via CLI

Requirements

  • PHP 8.2+
  • Laravel 11.0+
  • SwitchBot Hub (required for Meter Plus cloud access)

Supported Devices

  • SwitchBot Meter Plus - Temperature, humidity, and battery monitoring
  • SwitchBot Hub 2 - Built-in Swiss-made sensor (±1.8% RH / ±0.36°F accuracy)
  • Other Meter variants (Meter, WoIOSensor)

Installation

Install via Composer:

composer require wojt/laravel-switchbot

Publish the configuration file:

php artisan vendor:publish --tag=switchbot-config

Configuration

1. Get Your API Credentials

  1. Open the SwitchBot app (v6.14 or later)
  2. Go to Profile > Preferences > About
  3. Tap the app version 10 times to reveal Developer Options
  4. Select "Get Token" to retrieve your token and secret

2. Set Environment Variables

Add to your .env file:

SWITCHBOT_TOKEN=your-token-here
SWITCHBOT_SECRET=your-secret-here

# Optional: Enable automatic polling
SWITCHBOT_POLLING_ENABLED=true
SWITCHBOT_POLLING_INTERVAL=300  # 5 minutes (in seconds)

# Optional: Specify devices to poll (comma-separated)
SWITCHBOT_DEVICES=device-id-1,device-id-2

3. Configure Polling (Optional)

The package can automatically poll your devices using Laravel's scheduler. To enable:

  1. Set SWITCHBOT_POLLING_ENABLED=true in your .env
  2. Make sure your Laravel scheduler is running:
* * * * * cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1

Usage

Facade Usage

use Wojt\SwitchBot\Facades\SwitchBot;

// Get all devices
$devices = SwitchBot::getAllDevices();

// Get only Meter Plus devices
$meterDevices = SwitchBot::getMeterPlusDevices();

// Get all devices with temp/humidity sensors (Meter Plus + Hub 2)
$sensorDevices = SwitchBot::getDevicesWithSensors();

// Get device status (from cache or poll if needed)
$status = SwitchBot::getDeviceStatus('device-id');

// Force fresh poll
$status = SwitchBot::pollDevice('device-id');

// Poll all configured devices
$results = SwitchBot::pollAllDevices();

// Access device data
echo "Temperature: {$status->temperature}°C\n";
echo "Humidity: {$status->humidity}%\n";
echo "Battery: {$status->battery}%\n";

Dependency Injection

use Wojt\SwitchBot\Services\SwitchBotService;

class TemperatureController extends Controller
{
    public function __construct(
        private SwitchBotService $switchbot
    ) {}

    public function show(string $deviceId)
    {
        $status = $this->switchbot->getDeviceStatus($deviceId);

        return view('temperature', [
            'temperature' => $status->temperature,
            'humidity' => $status->humidity,
            'battery' => $status->battery,
        ]);
    }
}

Artisan Commands

Poll devices manually:

# Poll specific device
php artisan switchbot:poll device-id-123

# Poll all configured devices
php artisan switchbot:poll --all

Event Listeners

Listen for device status changes using the main event:

use Wojt\SwitchBot\Events\DeviceStatusChanged;

Event::listen(DeviceStatusChanged::class, function ($event) {
    if ($event->temperatureChanged()) {
        $delta = $event->changes['temperature']['delta'];
        Log::info("Temperature changed by {$delta}°C");
    }

    if ($event->humidityChanged()) {
        Log::info("Humidity changed");
    }

    if ($event->batteryChanged()) {
        // Send low battery alert
        if ($event->current->battery < 20) {
            // Send notification
        }
    }
});

Or listen to granular events for specific changes:

use Wojt\SwitchBot\Events\TemperatureChanged;
use Wojt\SwitchBot\Events\HumidityChanged;
use Wojt\SwitchBot\Events\BatteryChanged;

// Listen only to temperature changes
Event::listen(TemperatureChanged::class, function ($event) {
    if ($event->increased()) {
        Log::info("Temperature rose by {$event->absoluteChange()}°C");
    } else {
        Log::info("Temperature dropped by {$event->absoluteChange()}°C");
    }
});

// Listen only to humidity changes
Event::listen(HumidityChanged::class, function ($event) {
    Log::info("Humidity is now {$event->current->humidity}%");
});

// Listen only to battery changes
Event::listen(BatteryChanged::class, function ($event) {
    if ($event->isLow()) {
        Notification::send($users, new LowBatteryAlert($event->current));
    }
});

Webhooks

Enable webhooks in your .env:

SWITCHBOT_WEBHOOK_ENABLED=true
SWITCHBOT_WEBHOOK_PATH=/api/switchbot/webhook

The webhook endpoint will be available at:

POST https://your-domain.com/api/switchbot/webhook

Configure this URL in your SwitchBot app or via the API to receive real-time updates.

Workbench Dashboard

Enable the workbench UI for testing:

SWITCHBOT_WORKBENCH_ENABLED=true

Then visit:

http://your-app.test/switchbot

You'll see a simple dashboard showing all your Meter Plus devices with real-time temperature, humidity, and battery data. Click "Poll" to fetch fresh data from the API.

Configuration Options

All options are in config/switchbot.php:

return [
    // API credentials
    'token' => env('SWITCHBOT_TOKEN'),
    'secret' => env('SWITCHBOT_SECRET'),

    // Polling
    'polling_enabled' => env('SWITCHBOT_POLLING_ENABLED', false),
    'polling_interval' => env('SWITCHBOT_POLLING_INTERVAL', 300), // seconds

    // Change detection thresholds
    'temperature_threshold' => 0.5,  // °C
    'humidity_threshold' => 2,       // %
    'battery_threshold' => 5,        // %

    // Devices to poll (leave empty for auto-discovery)
    'devices' => [],

    // Caching
    'cache_driver' => env('SWITCHBOT_CACHE_DRIVER', 'file'),
    'cache_ttl' => 86400, // 1 day
];

Data Transfer Objects

MeterPlusStatus

readonly class MeterPlusStatus
{
    public string $deviceId;
    public string $deviceName;
    public string $deviceType;
    public float $temperature;
    public int $humidity;
    public int $battery;
    public ?string $hubDeviceId;
    public ?Carbon $timestamp;
}

DeviceInfo

readonly class DeviceInfo
{
    public string $deviceId;
    public string $deviceName;
    public string $deviceType;
    public ?string $hubDeviceId;
    public bool $enableCloudService;
}

Events

DeviceStatusChanged

Dispatched when a device's status changes beyond configured thresholds:

class DeviceStatusChanged
{
    public readonly MeterPlusStatus $current;
    public readonly ?MeterPlusStatus $previous;
    public readonly array $changes;

    public function temperatureChanged(): bool;
    public function humidityChanged(): bool;
    public function batteryChanged(): bool;
    public function isInitial(): bool;
}

TemperatureChanged

Dispatched when temperature changes beyond threshold:

class TemperatureChanged
{
    public readonly MeterPlusStatus $current;
    public readonly MeterPlusStatus $previous;
    public readonly float $delta;

    public function increased(): bool;
    public function decreased(): bool;
    public function absoluteChange(): float;
}

HumidityChanged

Dispatched when humidity changes beyond threshold:

class HumidityChanged
{
    public readonly MeterPlusStatus $current;
    public readonly MeterPlusStatus $previous;
    public readonly int $delta;

    public function increased(): bool;
    public function decreased(): bool;
    public function absoluteChange(): int;
}

BatteryChanged

Dispatched when battery level changes beyond threshold:

class BatteryChanged
{
    public readonly MeterPlusStatus $current;
    public readonly MeterPlusStatus $previous;
    public readonly int $delta;

    public function increased(): bool;
    public function decreased(): bool;
    public function isLow(int $threshold = 20): bool;
    public function isCritical(int $threshold = 10): bool;
    public function absoluteChange(): int;
}

WebhookReceived

Dispatched when a webhook is received from SwitchBot:

class WebhookReceived
{
    public readonly WebhookPayload $payload;
}

Rate Limiting

SwitchBot API allows 10,000 requests per day. The package:

  • Caches device statuses to minimize API calls
  • Recommends polling intervals of 5+ minutes
  • Default configuration uses ~288 API calls per day (polling every 5 minutes)

Examples

Temperature Alert System

use Wojt\SwitchBot\Events\DeviceStatusChanged;
use Illuminate\Support\Facades\Notification;

Event::listen(DeviceStatusChanged::class, function ($event) {
    if ($event->temperatureChanged()) {
        $temp = $event->current->temperature;

        if ($temp > 30) {
            Notification::route('mail', 'admin@example.com')
                ->notify(new HighTemperatureAlert($event->current));
        }
    }
});

Scheduled Reports

// In your console kernel
Schedule::call(function () {
    $devices = SwitchBot::getMeterPlusDevices();

    foreach ($devices as $device) {
        $status = SwitchBot::getDeviceStatus($device->deviceId);

        Log::info("Daily Report: {$device->deviceName}", [
            'temperature' => $status->temperature,
            'humidity' => $status->humidity,
            'battery' => $status->battery,
        ]);
    }
})->daily();

Troubleshooting

"SwitchBot API credentials not configured"

  • Make sure SWITCHBOT_TOKEN and SWITCHBOT_SECRET are set in your .env
  • Clear config cache: php artisan config:clear

"Device not found"

  • Ensure the device is added in your SwitchBot app
  • Verify the device has cloud service enabled
  • Check that you have a SwitchBot Hub connected

Polling not working

  • Verify SWITCHBOT_POLLING_ENABLED=true in .env
  • Make sure Laravel scheduler is running
  • Check logs for any errors

License

MIT

Credits

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors