mirror of
https://github.com/usetrmnl/byos_laravel.git
synced 2026-01-13 23:18:10 +00:00
initial commit
This commit is contained in:
parent
32d63c09e7
commit
01655b413e
37 changed files with 2564 additions and 283 deletions
121
app/Console/Commands/ScreenGeneratorCommand.php
Normal file
121
app/Console/Commands/ScreenGeneratorCommand.php
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Models\Device;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Ramsey\Uuid\Uuid;
|
||||
use Spatie\Browsershot\Browsershot;
|
||||
|
||||
class ScreenGeneratorCommand extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'trmnl:screen:generate {deviceId=1}';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = '';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
|
||||
$deviceId = $this->argument('deviceId');
|
||||
|
||||
$uuid = Uuid::uuid4()->toString();
|
||||
$pngPath = public_path('storage/images/generated/').$uuid.'.png';
|
||||
$bmpPath = public_path('storage/images/generated/').$uuid.'.bmp';
|
||||
|
||||
// Generate PNG
|
||||
try {
|
||||
Browsershot::html(view('trmnl')->render())
|
||||
->windowSize(800, 480)
|
||||
->save($pngPath);
|
||||
} catch (\Exception $e) {
|
||||
$this->error('Failed to generate PNG: '.$e->getMessage());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
$this->convertToBmpImageMagick($pngPath, $bmpPath);
|
||||
|
||||
} catch (\ImagickException $e) {
|
||||
$this->error('Failed to convert image to BMP: '.$e->getMessage());
|
||||
}
|
||||
|
||||
Device::find($deviceId)->update(['current_screen_image' => $uuid]);
|
||||
|
||||
$this->cleanupFolder();
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \ImagickException
|
||||
*/
|
||||
public function convertToBmpImageMagick(string $pngPath, string $bmpPath): void
|
||||
{
|
||||
$imagick = new \Imagick($pngPath);
|
||||
$imagick->setImageType(\Imagick::IMGTYPE_GRAYSCALE);
|
||||
$imagick->quantizeImage(2, \Imagick::COLORSPACE_GRAY, 0, true, false);
|
||||
$imagick->setImageDepth(1);
|
||||
$imagick->stripImage();
|
||||
$imagick->setFormat('BMP3');
|
||||
$imagick->writeImage($bmpPath);
|
||||
$imagick->clear();
|
||||
}
|
||||
|
||||
// TODO retuns 8-bit BMP
|
||||
|
||||
// public function convertToBmpGD(string $pngPath, string $bmpPath): void
|
||||
// {
|
||||
// // Load the PNG image
|
||||
// $image = imagecreatefrompng($pngPath);
|
||||
//
|
||||
// // Create a new true color image with the same dimensions
|
||||
// $bwImage = imagecreatetruecolor(imagesx($image), imagesy($image));
|
||||
//
|
||||
// // Convert to black and white
|
||||
// imagefilter($image, IMG_FILTER_GRAYSCALE);
|
||||
//
|
||||
// // Copy the grayscale image to the new image
|
||||
// imagecopy($bwImage, $image, 0, 0, 0, 0, imagesx($image), imagesy($image));
|
||||
//
|
||||
// // Create a 1-bit palette
|
||||
// imagetruecolortopalette($bwImage, true, 2);
|
||||
//
|
||||
// // Save as BMP
|
||||
//
|
||||
// imagebmp($bwImage, $bmpPath, false);
|
||||
//
|
||||
// // Free up memory
|
||||
// imagedestroy($image);
|
||||
// imagedestroy($bwImage);
|
||||
// }
|
||||
public function cleanupFolder(): void
|
||||
{
|
||||
$activeImageUuids = Device::pluck('current_screen_image')->filter()->toArray();
|
||||
|
||||
$files = Storage::disk('public')->files('/images/generated/');
|
||||
foreach ($files as $file) {
|
||||
if (basename($file) === '.gitignore') {
|
||||
continue;
|
||||
}
|
||||
// Get filename without path and extension
|
||||
$fileUuid = pathinfo($file, PATHINFO_FILENAME);
|
||||
// If the UUID is not in use by any device, move it to archive
|
||||
if (! in_array($fileUuid, $activeImageUuids)) {
|
||||
Storage::disk('public')->delete($file);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
59
app/Livewire/DeviceManager.php
Normal file
59
app/Livewire/DeviceManager.php
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
<?php
|
||||
|
||||
namespace App\Livewire;
|
||||
|
||||
use App\Models\Device;
|
||||
use Livewire\Component;
|
||||
use Livewire\WithPagination;
|
||||
|
||||
class DeviceManager extends Component
|
||||
{
|
||||
use WithPagination;
|
||||
|
||||
public $showDeviceForm = false;
|
||||
|
||||
public $name;
|
||||
|
||||
public $mac_address;
|
||||
|
||||
public $api_key;
|
||||
|
||||
public $default_refresh_interval = 900;
|
||||
|
||||
public $friendly_id;
|
||||
|
||||
protected $rules = [
|
||||
'mac_address' => 'required',
|
||||
'api_key' => 'required',
|
||||
'default_refresh_interval' => 'required|integer',
|
||||
];
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.device-manager', [
|
||||
'devices' => auth()->user()->devices()->paginate(10),
|
||||
]);
|
||||
}
|
||||
|
||||
public function createDevice(): void
|
||||
{
|
||||
$this->validate();
|
||||
|
||||
Device::factory([
|
||||
'name' => $this->name,
|
||||
'mac_address' => $this->mac_address,
|
||||
'api_key' => $this->api_key,
|
||||
'default_refresh_interval' => $this->default_refresh_interval,
|
||||
'friendly_id' => $this->friendly_id,
|
||||
'user_id' => auth()->id(),
|
||||
])->create();
|
||||
|
||||
$this->reset();
|
||||
session()->flash('message', 'Device created successfully.');
|
||||
}
|
||||
|
||||
public function toggleDeviceForm()
|
||||
{
|
||||
$this->showDeviceForm = ! $this->showDeviceForm;
|
||||
}
|
||||
}
|
||||
13
app/Models/Device.php
Normal file
13
app/Models/Device.php
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Device extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $guarded = ['id'];
|
||||
}
|
||||
|
|
@ -4,13 +4,15 @@ namespace App\Models;
|
|||
|
||||
// use Illuminate\Contracts\Auth\MustVerifyEmail;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Foundation\Auth\User as Authenticatable;
|
||||
use Illuminate\Notifications\Notifiable;
|
||||
use Laravel\Sanctum\HasApiTokens;
|
||||
|
||||
class User extends Authenticatable
|
||||
{
|
||||
/** @use HasFactory<\Database\Factories\UserFactory> */
|
||||
use HasFactory, Notifiable;
|
||||
use HasApiTokens, HasFactory, Notifiable;
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
|
|
@ -45,4 +47,9 @@ class User extends Authenticatable
|
|||
'password' => 'hashed',
|
||||
];
|
||||
}
|
||||
|
||||
public function devices(): HasMany
|
||||
{
|
||||
return $this->hasMany(Device::class);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
26
app/Utils/OneBitModifier.php
Normal file
26
app/Utils/OneBitModifier.php
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
<?php
|
||||
|
||||
namespace App\Utils;
|
||||
|
||||
use Intervention\Image\Interfaces\ImageInterface;
|
||||
use Intervention\Image\Interfaces\ModifierInterface;
|
||||
|
||||
class OneBitModifier implements ModifierInterface
|
||||
{
|
||||
public function apply(ImageInterface $image): ImageInterface
|
||||
{
|
||||
foreach ($image as $pixel) {
|
||||
// Get brightness value of pixel (0-255)
|
||||
$brightness = $pixel->brightness();
|
||||
|
||||
// Convert to Black or White based on a threshold (128)
|
||||
if ($brightness < 128) {
|
||||
$pixel->set([0, 0, 0]); // Black
|
||||
} else {
|
||||
$pixel->set([255, 255, 255]); // White
|
||||
}
|
||||
}
|
||||
|
||||
return $image;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue