diff --git a/README.md b/README.md index 111fd43..1d8b98a 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,8 @@ [](https://github.com/usetrmnl/byos_laravel/actions/workflows/test.yml) -TRMNL BYOS Laravel is a self-hostable implementation of a TRMNL server, built with Laravel. -It enables you to manage TRMNL devices, generate screens dynamically, and can act as a proxy for the native cloud service (native plugins, receipts). +TRMNL BYOS Laravel is a self-hostable implementation of a TRMNL server, built with Laravel. +It enables you to manage TRMNL devices, generate screens dynamically, and can act as a proxy for the native cloud service (native plugins, receipts). Inspired by [usetrmnl/byos_sinatra](https://github.com/usetrmnl/byos_sinatra). If you are looking for a Laravel package designed to streamline the development of both public and private TRMNL plugins, check out [bnussbau/trmnl-laravel](https://github.com/bnussbau/laravel-trmnl). @@ -15,11 +15,11 @@ If you are looking for a Laravel package designed to streamline the development ### Key Features -* π‘ Device Information β Display battery status, WiFi strength, firmware version, and more. -* π Auto-Join β Automatically detects and adds devices from your local network. -* π₯οΈ Screen Generation β Supports Plugins, API, Markup or updates via Code. -* π TRMNL API Proxy β Can act as a proxy for the native cloud service (requires TRMNL Developer Edition). - * This enables a hybrid setup β for example, you can update your custom Train Monitor every 5 minutes in the morning, while displaying native TRMNL plugins throughout the day. +* π‘ Device Information β Display battery status, WiFi strength, firmware version, and more. +* π Auto-Join β Automatically detects and adds devices from your local network. +* π₯οΈ Screen Generation β Supports Plugins, API, Markup or updates via Code. +* π TRMNL API Proxy β Can act as a proxy for the native cloud service (requires TRMNL Developer Edition). + * This enables a hybrid setup β for example, you can update your custom Train Monitor every 5 minutes in the morning, while displaying native TRMNL plugins throughout the day. * π Dark Mode β Switch between light and dark mode. * π³ Deployment β Dockerized setup for easier hosting (Dockerfile, docker-compose). * π οΈ Devcontainer support for easier development. @@ -114,6 +114,20 @@ Server is ready. Visit tab "Ports" in VSCode and visit the "Forwarded Address" i Login with user / password `admin@example.com` / `admin@example.com` +### Demo Plugins + +Run the ExampleReceiptsSeeder to seed the database with example plugins: + +```bash +php artisan db:seed --class=ExampleReceiptsSeeder +``` + +* Zen Quotes +* This Day in History +* Weather +* Train Departure Monitor +* Home Assistant + ### Usage #### Environment Variables @@ -143,11 +157,11 @@ If your environment is local, you can access the server at `http://localhost:456 ##### Manually 1. Open the Devices page: -π http://localhost:4567/devices + π http://localhost:4567/devices 2. Click βAdd New Deviceβ. 3. Retrieve your TRMNL MAC Address and API Key: - - You can grab the TRMNL Mac Address and API Key from the TRMNL Dashboard - - Alternatively, debug incoming requests to /api/setup to determine them +- You can grab the TRMNL Mac Address and API Key from the TRMNL Dashboard +- Alternatively, debug incoming requests to /api/setup to determine them ### βοΈ Configure Server for Device @@ -175,7 +189,7 @@ See this YouTube guide: [https://www.youtube.com/watch?v=3xehPW-PCOM](https://ww #### π¨ Blade View * Edit `resources/views/trmnl.blade.php` - * Available Blade Components are listed here: [laravel-trmnl | Blade Components](https://github.com/bnussbau/laravel-trmnl/tree/main/resources/views/components) + * Available Blade Components are listed here: [laravel-trmnl | Blade Components](https://github.com/bnussbau/laravel-trmnl/tree/main/resources/views/components) * To generate the screen, run ```bash @@ -252,42 +266,31 @@ Here are some features and improvements that are open for contribution: ##### π Plugin System -- ~~Enable configurable plugins via the Web Interface.~~ β - Ensure compatibility with the trmnl-laravel package. - Implement auto-discovery for plugins. -##### β³ Scheduling / Playlists - -- Move task scheduling from console.php to a Web Interface. -- ~~Allow users to configure custom schedule intervals.~~ β - ##### π₯οΈ βNativeβ Plugins -- Add built-in plugins such as (as an example): - - βοΈ Weather - - π¬ Quotes - - π‘ Home Assistant integration -- Provide Web UI controls to enable/disable plugins. -##### π¦ Visual Studio Code Devcontainer -* ~~Add a .devcontainer to this repo for easier development with Docker.~~ β +- Architecture for native plugins. +- Configuration UI ##### Improve Code Coverage - Expand Pest tests to cover more functionality. -- Increase code coverage (currently at 86.9%). +- Increase code coverage ### π€ Contribution Contributions are welcome! If youβd like to improve the project, follow these steps: 1. Open an Issue - - Before submitting a pull request, create an issue to discuss your idea. - - Clearly describe the feature or bug fix you want to work on. -2. Fork the Repository & Create a Branch + - Before submitting a pull request, create an issue to discuss your idea. + - Clearly describe the feature or bug fix you want to work on. +2. Fork the Repository & Create a Branch 3. Make Your Changes & Add Tests - Ensure your code follows best practices. - Add Pest tests to cover your changes. 4. Run Tests - - `php artisan test` + - `php artisan test` 5. Submit a Pull Request (PR) - Push your branch and create a PR. - Provide a clear description of your changes. diff --git a/app/Models/Plugin.php b/app/Models/Plugin.php index df16f86..4be5bbc 100644 --- a/app/Models/Plugin.php +++ b/app/Models/Plugin.php @@ -42,7 +42,20 @@ class Plugin extends Model public function updateDataPayload(): void { if ($this->data_strategy === 'polling' && $this->polling_url) { - $response = Http::withHeaders(['User-Agent' => 'usetrmnl/byos_laravel', 'Accept' => 'application/json']) + // Parse headers from polling_header string + $headers = ['User-Agent' => 'usetrmnl/byos_laravel', 'Accept' => 'application/json']; + + if ($this->polling_header) { + $headerLines = explode("\n", trim($this->polling_header)); + foreach ($headerLines as $line) { + $parts = explode(':', $line, 2); + if (count($parts) === 2) { + $headers[trim($parts[0])] = trim($parts[1]); + } + } + } + + $response = Http::withHeaders($headers) ->get($this->polling_url) ->json(); diff --git a/resources/views/livewire/plugins/receipt.blade.php b/resources/views/livewire/plugins/receipt.blade.php index 8f97594..043f566 100644 --- a/resources/views/livewire/plugins/receipt.blade.php +++ b/resources/views/livewire/plugins/receipt.blade.php @@ -83,9 +83,24 @@ new class extends Component { public function updateData() { if ($this->plugin->data_strategy === 'polling') { - $response = Http::get($this->plugin->polling_url)->json(); - $this->plugin->update(['data_payload' => $response]); + // Parse headers from polling_header string + $headers = ['User-Agent' => 'usetrmnl/byos_laravel', 'Accept' => 'application/json']; + + if ($this->plugin->polling_header) { + $headerLines = explode("\n", trim($this->plugin->polling_header)); + foreach ($headerLines as $line) { + $parts = explode(':', $line, 2); + if (count($parts) === 2) { + $headers[trim($parts[0])] = trim($parts[1]); + } + } + } + $response = Http::withHeaders($headers) + ->get($this->plugin->polling_url) + ->json(); + + $this->plugin->update(['data_payload' => $response]); $this->data_payload = json_encode($response); } } @@ -289,8 +304,15 @@ HTML;