Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial #19

Closed
wants to merge 21 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
fffd826
Update issue templates
almostengr Feb 1, 2024
7a16805
Added files from FPP template
almostengr Feb 1, 2024
96e147b
Updated plugin information, repository links
almostengr Feb 1, 2024
d633662
Created pseudocode for worker; updated links in about
almostengr Feb 1, 2024
47bef89
Updated description
almostengr Feb 2, 2024
ceaee03
#3 send status; updated menu links, repository links
almostengr Apr 8, 2024
093011f
moved common logic to common.php; created settings.php
almostengr Apr 8, 2024
061f8e2
#14 #12 #3 updated settings form, worker
almostengr Apr 9, 2024
5c539a2
#3 created request object for server
almostengr Apr 25, 2024
63e6b1b
Refactored worker, created script for background proces
almostengr Apr 26, 2024
41e707b
Reorganized project; updated project name and url
almostengr Apr 29, 2024
2351c54
created tests
almostengr Apr 29, 2024
415aa89
Removed composer files; closed #8 status only sent when sequence chan…
almostengr May 31, 2024
79a63ee
added plugin json url to readme
almostengr May 31, 2024
85159da
#3 added environment option; #14 updated menu, method visibility
almostengr May 31, 2024
18ece2d
#15 set up composer, GH workflow for automated testing
almostengr May 31, 2024
2b6a4cc
#16 created automated tests
almostengr Jun 1, 2024
29524ee
#16 created automated tests
almostengr Jun 1, 2024
536c2f9
Merge remote-tracking branch 'refs/remotes/origin/initial' into initial
almostengr Jun 1, 2024
1077d77
Automated testing (#18)
almostengr Jun 1, 2024
b2ba0ad
removed code coverage option
almostengr Jun 1, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions .github/ISSUE_TEMPLATE/bug_report.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''

---

**Describe the bug**
A clear and concise description of what the bug is.

**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error

**Expected behavior**
A clear and concise description of what you expected to happen.

**Screenshots**
If applicable, add screenshots to help explain your problem.

**Desktop (please complete the following information):**
- OS: [e.g. iOS]
- Browser [e.g. chrome, safari]
- Version [e.g. 22]

**Smartphone (please complete the following information):**
- Device: [e.g. iPhone6]
- OS: [e.g. iOS8.1]
- Browser [e.g. stock browser, safari]
- Version [e.g. 22]

**Additional context**
Add any other context about the problem here.
20 changes: 20 additions & 0 deletions .github/ISSUE_TEMPLATE/feature_request.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''

---

**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]

**Describe the solution you'd like**
A clear and concise description of what you want to happen.

**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.

**Additional context**
Add any other context or screenshots about the feature request here.
8 changes: 8 additions & 0 deletions .github/workflows/pull_request.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
on:
pull_request:
branches: main

steps:
- uses: actions/checkout@v3
# - uses: php-actions/composer@v6 # or alternative dependency management
- uses: php-actions/phpunit@v3
40 changes: 40 additions & 0 deletions .github/workflows/run-php-unit-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
name: Run PHPUnit Tests

on:
pull_request:
branches: [ "main" ]

permissions:
contents: read

jobs:
build:

runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4

- name: Validate composer.json and composer.lock
run: composer validate --strict

- name: Cache Composer packages
id: composer-cache
uses: actions/cache@v3
with:
path: vendor
key: ${{ runner.os }}-php-${{ hashFiles('**/composer.lock') }}
restore-keys: |
${{ runner.os }}-php-

- name: Install dependencies
run: composer install --prefer-dist --no-progress

# Add a test script to composer.json, for instance: "test": "vendor/bin/phpunit"
# Docs: https://getcomposer.org/doc/articles/scripts.md

# - name: Run test suite
# run: composer run-script test

- name: Run PHPUnit tests
run: vendor/bin/phpunit --colors=never
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.phpunit.cache

/vendor/
18 changes: 16 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,16 @@
# light-show-guard-plugin
FPP Plugin for Light Show Guard
# Show Pulse Plugin for Falcon Pi Player

Show Pulse plugin allows you to see and remotely controller what happens with your light show. This
plugin is designed to work with Falcon Pi Player.

## Install Plugin

To install the plugin to your Falcon Pi Player, go to the Plugins section of the FPP. Then copy and
paste the URL below to install the plugin.

[https://raw.githubusercontent.com/remote-falcon/remote-falcon-plugin/master/pluginInfo.json](https://raw.githubusercontent.com/remote-falcon/remote-falcon-plugin/master/pluginInfo.json)

## Additional Information

More information about this project, can be found at
[https://showpulse.rhtservices.net](https://showpulse.rhtservices.net).
130 changes: 130 additions & 0 deletions ShowPulseBase.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
<?php

namespace App;

$testing = false;
$commonFile = $testing ? "/opt/fpp/www/common.php" : __DIR__ . "/tests/OptFppWwwCommonMock.php";
require_once $commonFile;

abstract class ShowPulseBase
{
public function useBetaEnvironment()
{
return $this->readSetting("ENVIRONMENT") === "BETA";
}

protected function websiteUrl($route = null)
{
$url = $this->useBetaEnvironment() ?
"https://bshowpulse.rhtservices.net/api/" : "https://showpulse.rhtservices.net/api/";

if (!is_null($route)) {
$url .= $route;
}

return $url;
}

protected function fppUrl($route = null)
{
$url = "http://127.0.0.1/api/";
if (!is_null($route)) {
$url .= $route;
}

return $url;
}

protected function pluginName()
{
return "show_pulse";
}

protected function httpRequest($url, $method = "GET", $data = null, $headers = array())
{
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

$method = strtoupper($method);
if ($method === "POST" || $method === "PUT") {
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
}

array_push($headers, "Content-Type: application/json");
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

$response = curl_exec($ch);

if ($response === false) {
throw new Exception("cURL error: " . curl_error($ch));
}

curl_close($ch);

if ($response !== null) {
return json_decode($response, true);
}

return null;
}

public function saveSetting($key, $value)
{
if (empty($key) || is_null($key)) {
throw new Exception("Setting key was not specified");
}

$value = trim($value);
$key = trim($key);

WriteSettingToFile($key, $value, $this->pluginName());
}

public function readSetting($key)
{
if (empty($key) || is_null($key)) {
return false;
}

return ReadSettingFromFile($key, $this->pluginName()) ?? false;
}

public function getWebsiteApiKey()
{
$value = $this->useBetaEnvironment() ? $this->readSetting("BETA_API_KEY") : $this->readSetting("API_KEY");

if ($value) {
return $value;
}

throw new Exception("API Key has not been entered for the selected environment.");
}

protected function getWebsiteAuthorizationHeaders()
{
$apiKey = $this->getWebsiteApiKey();
return array("Authorization: Bearer $apiKey");
}

protected function executeFppCommand($command, $data = array())
{
$args = $command;
foreach ($data as $value) {
$args .= "/$value";
}

$url = $this->fppUrl($args);
$result = $this->httpRequest($url, "GET", $args);

if ($result === false) {
throw new Exception("Unable to execute FPP command.");
}
}

public function logError($data)
{
$currentDateTime = date('Y-m-d h:i:s A');
error_log("$currentDateTime: $data");
}
}
128 changes: 128 additions & 0 deletions ShowPulseSettingForm.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
<?php

namespace App;
use Exception;

require_once "ShowPulseBase.php";

final class ShowPulseSettingForm extends ShowPulseBase
{
public $playlist;
public $apiKey;
public $betaApiKey;
public $environment;

public function __construct()
{
$this->playlist = $this->readSetting("PLAYLIST");
$this->apiKey = $this->readSetting("API_KEY");
$this->betaApiKey = $this->readSetting("BETA_API_KEY");
$this->environment = $this->readSetting("ENVIRONMENT");
}

public function save()
{
if ($_SERVER["REQUEST_METHOD"] !== "POST") {
return null;
}

$this->apiKey = trim($_POST["api_key"]);
$this->betaApiKey = trim($_POST["test_api_key"]);
$this->playlist = $_POST["playlist"];
$this->environment = $_POST["environment"];

$this->saveSetting('API_KEY', $this->apiKey);
$this->saveSetting('PLAYLIST', $this->playlist);
$this->saveSetting("ENVIRONMENT", $this->environment);
$this->saveSetting("BETA_API_KEY", $this->betaApiKey);

try {
$playlistDirectory = GetDirSetting("playlists");
$playlistJson = file_get_contents($playlistDirectory . "/" . $this->playlist);

$url = $this->websiteUrl("song_options/playeradd");
$this->httpRequest($url, "POST", $playlistJson, $this->getWebsiteAuthorizationHeaders());

return array('success' => true, 'message' => "Settings updated successfully.");
} catch (Exception $e) {
return array('success' => false, 'message' => $e->getMessage());
}
}
}
?>
<div class="container mt-5">
<?php
$settingForm = new ShowPulseSettingForm();
$result = $settingForm->save();

if ($result !== null) {
$alertClass = $result['success'] ? "alert-success" : "alert-danger";
?>
<div class="alert <?php echo $alertClass; ?>" role="alert">
<?php echo $result['message']; ?>
</div>
<?php
}
?>
<h1 class="mb-4">Light Show Pulse Settings</h1>
<div class="row">
<div class="col-md-6">
<form method="POST" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]); ?>">
<div class="form-group">
<label for="api_key">API Key</label>
<input type="text" class="form-control" id="api_key" name="api_key" value="<?= $settingForm->apiKey; ?>" required>
<small class="form-text text-muted">
Enter your API Key. You can get a key from the
<a href="https://showpulse.rhtservices.net" target="_blank">Light Show Pulse website</a>.
NOTE: This key <strong>should not</strong> be shared with anyone.
</small>
</div>
<div class="form-group">
<label for="playlist">Jukebox Playlist</label>
<select name="playlist" required>
<?php
$playlists = scandir(GetDirSetting("playlists"));
foreach ($playlist as $playlists) {
$selected = $settingForm->playlist === $playlist ? "selected" : "";
?>
<option value="<?= $playlist ?>" <?= $selected; ?>>
<?= $playlist ?>
</option>
<?php
}
?>
</select>
<small class="form-text text-muted">
Select the playlist that contains the songs that users can choose from for your jukebox.
</small>
</div>
<div class="form-group">
<label for="environment">Environment</label>
<select id="environment" name="environment" required>
<option value="PRODUCTION" <?php if (!$settingForm->useBetaEnvironment()) {
echo "selected";
} ?>>Production
</option>
<option value="BETA" <?php if ($settingForm->useBetaEnvironment()) {
echo "selected";
} ?>>Beta</option>
</select>
<small class="form-text text-muted">
Enter the environment you want to use. Production is the default. Separate API key is
required to test using the Beta environment.
</small>
</div>
<div class="form-group">
<label for="beta_api_key">Beta API Key</label>
<input type="text" class="form-control" id="beta_api_key" name="beta_api_key" value="<?= $settingForm->betaApiKey; ?>">
<small class="form-text text-muted">
Beta API Key can be used to test what will happen with your show. Separate API key is required
for beta environment. You can sign up at
<a href="https://bshowpulse.rhtservices.net" target="_blank">https://bshowpulse.rhtservices.net</a>.
</small>
</div>
<button type="submit" class="btn btn-primary">Save Settings</button>
</form>
</div>
</div>
</div>
Loading
Loading