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.
- ✅ 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
- PHP 8.2+
- Laravel 11.0+
- SwitchBot Hub (required for Meter Plus cloud access)
- 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)
Install via Composer:
composer require wojt/laravel-switchbotPublish the configuration file:
php artisan vendor:publish --tag=switchbot-config- Open the SwitchBot app (v6.14 or later)
- Go to Profile > Preferences > About
- Tap the app version 10 times to reveal Developer Options
- Select "Get Token" to retrieve your token and secret
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-2The package can automatically poll your devices using Laravel's scheduler. To enable:
- Set
SWITCHBOT_POLLING_ENABLED=truein your.env - Make sure your Laravel scheduler is running:
* * * * * cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1use 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";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,
]);
}
}Poll devices manually:
# Poll specific device
php artisan switchbot:poll device-id-123
# Poll all configured devices
php artisan switchbot:poll --allListen 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));
}
});Enable webhooks in your .env:
SWITCHBOT_WEBHOOK_ENABLED=true
SWITCHBOT_WEBHOOK_PATH=/api/switchbot/webhookThe 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.
Enable the workbench UI for testing:
SWITCHBOT_WORKBENCH_ENABLED=trueThen 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.
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
];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;
}readonly class DeviceInfo
{
public string $deviceId;
public string $deviceName;
public string $deviceType;
public ?string $hubDeviceId;
public bool $enableCloudService;
}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;
}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;
}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;
}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;
}Dispatched when a webhook is received from SwitchBot:
class WebhookReceived
{
public readonly WebhookPayload $payload;
}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)
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));
}
}
});// 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();- Make sure
SWITCHBOT_TOKENandSWITCHBOT_SECRETare set in your.env - Clear config cache:
php artisan config:clear
- Ensure the device is added in your SwitchBot app
- Verify the device has cloud service enabled
- Check that you have a SwitchBot Hub connected
- Verify
SWITCHBOT_POLLING_ENABLED=truein.env - Make sure Laravel scheduler is running
- Check logs for any errors
MIT
- SwitchBot API Documentation
- Built for Laravel 11+