Compare commits
303 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
19edd9ace0 | ||
|
|
0982ef78dd | ||
|
|
5695d8e017 | ||
|
|
06ad446925 | ||
|
|
6b5a9cdff7 | ||
|
|
efb66118e4 | ||
|
|
2444aa2fc9 | ||
|
|
93f6173efa | ||
|
|
dc81d48ab1 | ||
|
|
5c32be929e | ||
|
|
105f60f57e | ||
|
|
a52130cedb | ||
|
|
d08e7953f2 | ||
|
|
d7544b04dd | ||
|
|
0291540df4 | ||
|
|
27b9b0267b | ||
|
|
cffef0d161 | ||
|
|
b5cb71b68d | ||
|
|
7685586508 | ||
|
|
b8aaa56b4b | ||
|
|
4aa307c8dd | ||
|
|
12b99024a4 | ||
|
|
22f0e29315 | ||
|
|
6eeba92350 | ||
|
|
286ba2b044 | ||
|
|
4b5a1e41d8 | ||
|
|
008705b75c | ||
|
|
5937f968ef | ||
|
|
4fe5547bf8 | ||
|
|
96f6749516 | ||
|
|
bc3883df14 | ||
|
|
32b1b8020a | ||
|
|
9280295ed3 | ||
|
|
e5a29d4668 | ||
|
|
4cfaa5ca59 | ||
|
|
6f894a587b | ||
|
|
35eb9cbdb5 | ||
|
|
2d41c5ca31 | ||
|
|
14f7a8b502 | ||
|
|
5101795cbf | ||
|
|
6d0632acee | ||
|
|
9298eff554 | ||
|
|
335ab8cce0 | ||
|
|
32daced427 | ||
|
|
153edcc2e1 | ||
|
|
548bc00e00 | ||
|
|
f8ab022da9 | ||
|
|
cd80745dcb | ||
|
|
56dfbda40a | ||
|
|
591555c3c7 | ||
|
|
bbabad3135 | ||
|
|
3329822a46 | ||
|
|
413a1fa38c | ||
|
|
3ee7821353 | ||
|
|
20a816f3e6 | ||
|
|
457f9f9eb5 | ||
|
|
39519dbfff | ||
|
|
61a56560f3 | ||
|
|
c1ccd6f44a | ||
|
|
2123f78dad | ||
|
|
a1914980c8 | ||
|
|
a3dbc6a4a8 | ||
|
|
8a0fdb005d | ||
|
|
f13ad238eb | ||
|
|
92071237c1 | ||
|
|
52c2d61dcf | ||
|
|
73036c33cb | ||
|
|
d6eb7a778c | ||
|
|
62b50cc06f | ||
|
|
05bee6ce84 | ||
|
|
2c2d24c0a8 | ||
|
|
b252229e03 | ||
|
|
8f7aeee546 | ||
|
|
b7fa2f1df6 | ||
|
|
ba3b79dd72 | ||
|
|
e4e058ff97 | ||
|
|
0b42cec902 | ||
|
|
35ad842ba1 | ||
|
|
08cf4152f7 | ||
|
|
71a392737e | ||
|
|
2b93eafcdf | ||
|
|
3c1706d4e8 | ||
|
|
e4b3adb867 | ||
|
|
9f00124fad | ||
|
|
68416d0293 | ||
|
|
e63198dc49 | ||
|
|
a5ce721733 | ||
|
|
e3b65588a2 | ||
|
|
f13e9306c9 | ||
|
|
ef82610a06 | ||
|
|
18145edbf1 | ||
|
|
54635fee3c | ||
|
|
6152969340 | ||
|
|
8770e5a327 | ||
|
|
822d9909ed | ||
|
|
d179700c6c | ||
|
|
dfecc6f8a0 | ||
|
|
0d8d4084a9 | ||
|
|
6bc1039ed6 | ||
|
|
8e1b04550b | ||
|
|
33e1f05f77 | ||
|
|
c4113367f7 | ||
|
|
4b906b3a92 | ||
|
|
06d8360922 | ||
|
|
9d4082665a | ||
|
|
a3481f3674 | ||
|
|
e36d92340e | ||
|
|
6225189b3c | ||
|
|
6c658c23c4 | ||
|
|
30cf8ee2e8 | ||
|
|
2526c6097e | ||
|
|
1e0889fe84 | ||
|
|
ba0716d37e | ||
|
|
b8d9eb65f6 | ||
|
|
03f0a6e6e2 | ||
|
|
5971e4afa1 | ||
|
|
dc840b63d8 | ||
|
|
865b30c631 | ||
|
|
da17f214da | ||
|
|
643397c939 | ||
|
|
1704001ef6 | ||
|
|
18d6758dbe | ||
|
|
19f5b7e3bc | ||
|
|
28c81825cc | ||
|
|
151777fbd6 | ||
|
|
8a8e3c21cb | ||
|
|
809cb07bb8 | ||
|
|
edce5fae85 | ||
|
|
10c1342bdb | ||
|
|
ede82406fa | ||
|
|
6ff8d8b5af | ||
|
|
bd7d136504 | ||
|
|
f8ebcffa08 | ||
|
|
eed64334e3 | ||
|
|
2bee99f9cc | ||
|
|
35dcf76689 | ||
|
|
1f7285cfc4 | ||
|
|
4f1736fb0f | ||
|
|
0229567156 | ||
|
|
87daddbeb2 | ||
|
|
c284b9c26c | ||
|
|
95e3e4dda4 | ||
|
|
d95e6539e3 | ||
|
|
a49feb2971 | ||
|
|
8b7ae3beed | ||
|
|
0a0fbbbdbb | ||
|
|
ca44097669 | ||
|
|
c0c77f6762 | ||
|
|
b7ba899df7 | ||
|
|
9b4bf36dbb | ||
|
|
85d63243c7 | ||
|
|
79cbc46f9b | ||
|
|
bd9fe652d9 | ||
|
|
dac7b34228 | ||
|
|
8703c485bc | ||
|
|
29f36827ca | ||
|
|
6fdb2b55b5 | ||
|
|
6a2e5edf2e | ||
|
|
938c31c815 | ||
|
|
d0ead60421 | ||
|
|
e0883eeae2 | ||
|
|
b0941641c7 | ||
|
|
8654dd44e6 | ||
|
|
afb7e23fcc | ||
|
|
1ffe3e7c16 | ||
|
|
7c0934cd9b | ||
|
|
e5eef1320d | ||
|
|
5ec9b3ea6f | ||
|
|
708e993f41 | ||
|
|
fd68777484 | ||
|
|
d616dddac0 | ||
|
|
7b31c4cca5 | ||
|
|
be94e9fb6b | ||
|
|
1b9981d74e | ||
|
|
f1ad263849 | ||
|
|
d802adb048 | ||
|
|
71bb616b76 | ||
|
|
3ba0ec2041 | ||
|
|
40576ac18d | ||
|
|
e6fa83904b | ||
|
|
a52696aae2 | ||
|
|
e9ca9a0454 | ||
|
|
7d38bbb0fa | ||
|
|
512ffb7639 | ||
|
|
cc652472a0 | ||
|
|
4cc3b39ce6 | ||
|
|
fabb9bd611 | ||
|
|
436bdbd8f2 | ||
|
|
d6ca83f090 | ||
|
|
96de2e7d0f | ||
|
|
ec922fac2c | ||
|
|
b4d5aef876 | ||
|
|
a672abba6a | ||
|
|
b193e03be9 | ||
|
|
4088807c72 | ||
|
|
f02ed06e09 | ||
|
|
ac69569d77 | ||
|
|
13a2ef6e5e | ||
|
|
c490c5dca8 | ||
|
|
24204c581e | ||
|
|
881a46867d | ||
|
|
3c665c21d1 | ||
|
|
f95138d1a4 | ||
|
|
04009f78f7 | ||
|
|
45f449d371 | ||
|
|
d8e2de927a | ||
|
|
f67348b9b8 | ||
|
|
c92eaa93bd | ||
|
|
8411e4ff76 | ||
|
|
b451d5def8 | ||
|
|
a6f8237069 | ||
|
|
ceb6d5fdac | ||
|
|
41ed6b8a43 | ||
|
|
06a51b5799 | ||
|
|
5001e59ee3 | ||
|
|
85747edff1 | ||
|
|
fb4b950148 | ||
|
|
a2988557de | ||
|
|
f554e35686 | ||
|
|
dbcfbcd0f2 | ||
|
|
27b52466ad | ||
|
|
20082cbadf | ||
|
|
4a7138205c | ||
|
|
6ae4451c51 | ||
|
|
7f17d8cd8f | ||
|
|
0f6e3c9497 | ||
|
|
88078111b4 | ||
|
|
0601a9fda7 | ||
|
|
05d9f7c057 | ||
|
|
34903dd979 | ||
|
|
3ba317c4e4 | ||
|
|
6bbb4f5de8 | ||
|
|
4ab4d14a4e | ||
|
|
d9e5b9404d | ||
|
|
e5d4f3c9f0 | ||
|
|
46ba9b4c4a | ||
|
|
9b6231915a | ||
|
|
6d8e7abff7 | ||
|
|
932b263c5a | ||
|
|
aef8b3b6cc | ||
|
|
be50fb86d7 | ||
|
|
73d2248ccb | ||
|
|
48937855d4 | ||
|
|
802e596f06 | ||
|
|
b6751a94c2 | ||
|
|
8b0c71dbdf | ||
|
|
2f7fa481a3 | ||
|
|
ffc006bd99 | ||
|
|
ea74d388b0 | ||
|
|
d4bd8d66e8 | ||
|
|
3a81e16490 | ||
|
|
4ea2b9cc36 | ||
|
|
407ebc56d7 | ||
|
|
f9e3419f39 | ||
|
|
b03371d69a | ||
|
|
58251eefb7 | ||
|
|
74036ed6d9 | ||
|
|
bfa1234feb | ||
|
|
6535ce113a | ||
|
|
dd8d219e73 | ||
|
|
1576e730ea | ||
|
|
7fc158c914 | ||
|
|
f9588f47d0 | ||
|
|
2eaa158e80 | ||
|
|
3f05d9fcbc | ||
|
|
3d2b155b79 | ||
|
|
3df3b93348 | ||
|
|
790b483298 | ||
|
|
d80c1a93db | ||
|
|
e8d2408477 | ||
|
|
fcc8c10c2b | ||
|
|
3063840b6d | ||
|
|
a3c5f9a74f | ||
|
|
e85bebee12 | ||
|
|
30d416b822 | ||
|
|
e1a32b1466 | ||
|
|
d02d7445cd | ||
|
|
0785bcba93 | ||
|
|
9d01996ae6 | ||
|
|
8c705753df | ||
|
|
c7fc86e54d | ||
|
|
9eb65ec891 | ||
|
|
92891af6b6 | ||
|
|
c0d299892e | ||
|
|
9a63550a9b | ||
|
|
25506410d0 | ||
|
|
102c0eb795 | ||
|
|
4605cb5c39 | ||
|
|
f8bf76c150 | ||
|
|
977bd96241 | ||
|
|
5224c09faf | ||
|
|
f342bd9d3a | ||
|
|
5516a5f764 | ||
|
|
15fcd0a722 | ||
|
|
a867f767d9 | ||
|
|
e84640501d | ||
|
|
e627594989 | ||
|
|
7963ac77b9 | ||
|
|
fe6272bf3a | ||
|
|
7fc902dea1 | ||
|
|
e61ce4e4be | ||
|
|
18b0a9703e | ||
|
|
4994d8ac21 |
38
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@@ -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
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
@@ -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.
|
||||||
1
LEDMatrix.wiki
Submodule
180
README.md
@@ -1,5 +1,5 @@
|
|||||||
# LEDMatrix
|
# LEDMatrix
|
||||||
An LED matrix display system that provides real-time information display capabilities for various data sources. The system is highly configurable and supports multiple display modes that can be enabled or disabled based on user preferences.
|
|
||||||
|
|
||||||
### Setup video and feature walkthrough on Youtube :
|
### Setup video and feature walkthrough on Youtube :
|
||||||
[](https://www.youtube.com/watch?v=_HaqfJy1Y54)
|
[](https://www.youtube.com/watch?v=_HaqfJy1Y54)
|
||||||
@@ -171,6 +171,17 @@ git clone https://github.com/ChuckBuilds/LEDMatrix.git
|
|||||||
cd LEDMatrix
|
cd LEDMatrix
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
4. First-time installation (recommended)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
chmod +x first_time_install.sh
|
||||||
|
sudo ./first_time_install.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
This single script installs services, dependencies, configures permissions and sudoers, and validates the setup.
|
||||||
|
|
||||||
|
----- OLD STEPS (left for manual review) -----
|
||||||
4. Install dependencies:
|
4. Install dependencies:
|
||||||
```bash
|
```bash
|
||||||
sudo pip3 install --break-system-packages -r requirements.txt
|
sudo pip3 install --break-system-packages -r requirements.txt
|
||||||
@@ -245,7 +256,6 @@ sudo nano /boot/firmware/config.txt
|
|||||||
```bash
|
```bash
|
||||||
sudo reboot
|
sudo reboot
|
||||||
```
|
```
|
||||||
|
|
||||||
-----------------------------------------------------------------------------------
|
-----------------------------------------------------------------------------------
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
@@ -807,7 +817,7 @@ This will start the display cycle but only stays active as long as your ssh sess
|
|||||||
|
|
||||||
The LEDMatrix can be installed as a systemd service to run automatically at boot and be managed easily. The service runs as root to ensure proper hardware timing access for the LED matrix.
|
The LEDMatrix can be installed as a systemd service to run automatically at boot and be managed easily. The service runs as root to ensure proper hardware timing access for the LED matrix.
|
||||||
|
|
||||||
### Installing the Service
|
### Installing the Service (this is included in the first_time_install.sh)
|
||||||
|
|
||||||
1. Make the install script executable:
|
1. Make the install script executable:
|
||||||
```bash
|
```bash
|
||||||
@@ -867,6 +877,102 @@ sudo ./start_display.sh
|
|||||||
sudo ./stop_display.sh
|
sudo ./stop_display.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
## Web Interface Installation (V2)
|
||||||
|
|
||||||
|
The LEDMatrix system includes Web Interface V2 that runs on port 5001 and provides real-time display preview, configuration management, and on-demand display controls.
|
||||||
|
|
||||||
|
### Installing the Web Interface Service
|
||||||
|
|
||||||
|
1. Make the install script executable:
|
||||||
|
```bash
|
||||||
|
chmod +x install_web_service.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Run the install script with sudo:
|
||||||
|
```bash
|
||||||
|
sudo ./install_web_service.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
The script will:
|
||||||
|
- Copy the web service file to `/etc/systemd/system/`
|
||||||
|
- Enable the service to start on boot
|
||||||
|
- Start the service immediately
|
||||||
|
- Show the service status
|
||||||
|
|
||||||
|
### Web Interface Configuration
|
||||||
|
|
||||||
|
The web interface can be configured to start automatically with the main display service:
|
||||||
|
|
||||||
|
1. In `config/config.json`, ensure the web interface autostart is enabled:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"web_display_autostart": true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
2. The web interface will now start automatically when:
|
||||||
|
- The system boots
|
||||||
|
- The `web_display_autostart` setting is `true` in your config
|
||||||
|
|
||||||
|
### Accessing the Web Interface
|
||||||
|
|
||||||
|
Once installed, you can access the web interface at:
|
||||||
|
```
|
||||||
|
http://your-pi-ip:5001
|
||||||
|
```
|
||||||
|
|
||||||
|
### Managing the Web Interface Service
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check service status
|
||||||
|
sudo systemctl status ledmatrix-web.service
|
||||||
|
|
||||||
|
# View logs
|
||||||
|
journalctl -u ledmatrix-web.service -f
|
||||||
|
|
||||||
|
# Stop the service
|
||||||
|
sudo systemctl stop ledmatrix-web.service
|
||||||
|
|
||||||
|
# Start the service
|
||||||
|
sudo systemctl start ledmatrix-web.service
|
||||||
|
|
||||||
|
# Disable autostart
|
||||||
|
sudo systemctl disable ledmatrix-web.service
|
||||||
|
|
||||||
|
# Enable autostart
|
||||||
|
sudo systemctl enable ledmatrix-web.service
|
||||||
|
```
|
||||||
|
|
||||||
|
### Web Interface Features
|
||||||
|
|
||||||
|
- **Real-time Display Preview**: See what's currently displayed on the LED matrix
|
||||||
|
- **Configuration Management**: Edit settings through a web interface
|
||||||
|
- **On-Demand Controls**: Start specific displays (weather, stocks, sports) on demand
|
||||||
|
- **Service Management**: Start/stop the main display service
|
||||||
|
- **System Controls**: Restart, update code, and manage the system
|
||||||
|
- **API Metrics**: Monitor API usage and system performance
|
||||||
|
- **Logs**: View system logs in real-time
|
||||||
|
|
||||||
|
### Troubleshooting Web Interface
|
||||||
|
|
||||||
|
**Web Interface Not Accessible After Restart:**
|
||||||
|
1. Check if the web service is running: `sudo systemctl status ledmatrix-web.service`
|
||||||
|
2. Verify the service is enabled: `sudo systemctl is-enabled ledmatrix-web.service`
|
||||||
|
3. Check logs for errors: `journalctl -u ledmatrix-web.service -f`
|
||||||
|
4. Ensure `web_display_autostart` is set to `true` in `config/config.json`
|
||||||
|
|
||||||
|
**Port 5001 Not Accessible:**
|
||||||
|
1. Check if the service is running on the correct port
|
||||||
|
2. Verify firewall settings allow access to port 5001
|
||||||
|
3. Check if another service is using port 5001
|
||||||
|
|
||||||
|
**Service Fails to Start:**
|
||||||
|
1. Check Python dependencies are installed
|
||||||
|
2. Verify the virtual environment is set up correctly
|
||||||
|
3. Check file permissions and ownership
|
||||||
|
|
||||||
|
|
||||||
-----------------------------------------------------------------------------------
|
-----------------------------------------------------------------------------------
|
||||||
|
|
||||||
@@ -1033,6 +1139,31 @@ The LEDMatrix system includes a comprehensive scoreboard display system with thr
|
|||||||
- Automatic game switching
|
- Automatic game switching
|
||||||
- Built-in caching to reduce API calls
|
- Built-in caching to reduce API calls
|
||||||
- Test mode for development
|
- Test mode for development
|
||||||
|
## API Usage Tracking
|
||||||
|
|
||||||
|
The LEDMatrix system includes a built-in API usage counter that tracks API calls made by various managers in a 24-hour rolling window. This feature helps monitor API usage and ensure compliance with rate limits.
|
||||||
|
|
||||||
|
### API Counter Features
|
||||||
|
- **Real-time Tracking**: Counts API calls for weather, stocks, sports, and news data
|
||||||
|
- **24-hour Window**: Rolling window that resets every 24 hours
|
||||||
|
- **Web Interface Integration**: View current usage in the Overview tab of the web interface
|
||||||
|
- **Forecast Display**: Shows predicted API usage based on current configuration
|
||||||
|
- **Automatic Reset**: Counters automatically reset when the 24-hour window expires
|
||||||
|
|
||||||
|
### Tracked API Calls
|
||||||
|
- **Weather**: OpenWeatherMap API calls (geocoding + weather data)
|
||||||
|
- **Stocks**: Yahoo Finance API calls for stock and crypto data
|
||||||
|
- **Sports**: ESPN API calls for various sports leagues (NHL, NBA, MLB, NFL, etc.)
|
||||||
|
- **News**: RSS feed and news API calls
|
||||||
|
|
||||||
|
### Accessing API Metrics
|
||||||
|
1. Open the web interface in your browser
|
||||||
|
2. Navigate to the **Overview** tab
|
||||||
|
3. Scroll down to the "API Calls (24h window)" section
|
||||||
|
4. Click "Refresh API Metrics" to update the display
|
||||||
|
|
||||||
|
The counter shows both actual usage and forecasted usage based on your current configuration settings.
|
||||||
|
|
||||||
## Caching System
|
## Caching System
|
||||||
|
|
||||||
The LEDMatrix system includes a robust caching mechanism to optimize API calls and reduce network traffic:
|
The LEDMatrix system includes a robust caching mechanism to optimize API calls and reduce network traffic:
|
||||||
@@ -1074,16 +1205,24 @@ The LEDMatrix system includes a robust caching mechanism to optimize API calls a
|
|||||||
|
|
||||||
##What's Next?
|
##What's Next?
|
||||||
- Adding MQTT/HomeAssistant integration
|
- Adding MQTT/HomeAssistant integration
|
||||||
- Gambling odds?
|
- Gambling odds (done!)
|
||||||
- Building a user-friendly UI for easier configuration
|
- Building a user-friendly UI for easier configuration (done!)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### If you've read this far — thanks!
|
|
||||||
|
|
||||||
## Granting Passwordless Sudo Access for Web Interface Actions
|
## Granting Passwordless Sudo Access for Web Interface Actions
|
||||||
|
|
||||||
The web interface needs to run certain commands with `sudo` (e.g., `reboot`, `systemctl start/stop/enable/disable ledmatrix.service`, `python display_controller.py`). To avoid needing to enter a password for these actions through the web UI, you can configure the `sudoers` file to allow the user running the Flask application to execute these specific commands without a password.
|
The web interface needs to run certain commands with `sudo` (e.g., `reboot`, `systemctl start/stop/enable/disable ledmatrix.service`, `python display_controller.py`). To avoid needing to enter a password for these actions through the web UI, you can configure the `sudoers` file to allow the user running the Flask application to execute these specific commands without a password.
|
||||||
|
|
||||||
|
1. Shortcut to automate the below steps:
|
||||||
|
```chmod +x configure_web_sudo.sh```
|
||||||
|
then
|
||||||
|
```./configure_web_sudo.sh```
|
||||||
|
|
||||||
|
|
||||||
|
Manual Method:
|
||||||
|
|
||||||
**WARNING: Be very careful when editing the `sudoers` file. Incorrect syntax can lock you out of `sudo` access.**
|
**WARNING: Be very careful when editing the `sudoers` file. Incorrect syntax can lock you out of `sudo` access.**
|
||||||
|
|
||||||
1. **Identify the user:** Determine which user is running the `web_interface.py` script. Often, this might be the default user like `pi` on a Raspberry Pi, or a dedicated user you've set up.
|
1. **Identify the user:** Determine which user is running the `web_interface.py` script. Often, this might be the default user like `pi` on a Raspberry Pi, or a dedicated user you've set up.
|
||||||
@@ -1131,3 +1270,32 @@ The web interface needs to run certain commands with `sudo` (e.g., `reboot`, `sy
|
|||||||
**Security Considerations:**
|
**Security Considerations:**
|
||||||
Granting passwordless `sudo` access, even for specific commands, has security implications. Ensure that the scripts and commands allowed are secure and cannot be easily exploited. The web interface itself should also be secured if it's exposed to untrusted networks.
|
Granting passwordless `sudo` access, even for specific commands, has security implications. Ensure that the scripts and commands allowed are secure and cannot be easily exploited. The web interface itself should also be secured if it's exposed to untrusted networks.
|
||||||
For `display_controller.py` and `stop_display.sh`, ensure their file permissions restrict write access to only trusted users, preventing unauthorized modification of these scripts which run with elevated privileges.
|
For `display_controller.py` and `stop_display.sh`, ensure their file permissions restrict write access to only trusted users, preventing unauthorized modification of these scripts which run with elevated privileges.
|
||||||
|
|
||||||
|
|
||||||
|
## Web Interface V2 (simplified quick start)
|
||||||
|
|
||||||
|
### 1) Run the helper (does the above and starts the server):
|
||||||
|
```
|
||||||
|
python3 start_web_v2.py
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2) Start the web UI v2
|
||||||
|
```
|
||||||
|
python web_interface_v2.py
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3) Autostart (recommended)
|
||||||
|
Set `"web_display_autostart": true` in `config/config.json`.
|
||||||
|
Ensure your systemd service calls `start_web_conditionally.py` (installed by `install_service.sh`).
|
||||||
|
|
||||||
|
### 4) Permissions (optional but recommended)
|
||||||
|
- Add the service user to `systemd-journal` for viewing logs without sudo.
|
||||||
|
- Configure passwordless sudo for actions (start/stop service, reboot, shutdown) if desired.
|
||||||
|
- Required for web Ui actions, look in the section above for the commands to run (chmod +x configure_web_sudo.sh & ./configure_web_sudo.sh)
|
||||||
|
|
||||||
|
### 5) Old web UI (v1)
|
||||||
|
The project now defaults to Web UI v2. The v1 interface can be ignored.
|
||||||
|
An LED matrix display system that provides real-time information display capabilities for various data sources. The system is highly configurable and supports multiple display modes that can be enabled or disabled based on user preferences.
|
||||||
|
|
||||||
|
|
||||||
|
### If you've read this far — thanks!
|
||||||
162
add_custom_feed_example.py
Normal file
@@ -0,0 +1,162 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import json
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
|
||||||
|
def add_custom_feed(feed_name, feed_url):
|
||||||
|
"""Add a custom RSS feed to the news manager configuration"""
|
||||||
|
config_path = "config/config.json"
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Load current config
|
||||||
|
with open(config_path, 'r') as f:
|
||||||
|
config = json.load(f)
|
||||||
|
|
||||||
|
# Ensure news_manager section exists
|
||||||
|
if 'news_manager' not in config:
|
||||||
|
print("ERROR: News manager configuration not found!")
|
||||||
|
return False
|
||||||
|
|
||||||
|
# Add custom feed
|
||||||
|
if 'custom_feeds' not in config['news_manager']:
|
||||||
|
config['news_manager']['custom_feeds'] = {}
|
||||||
|
|
||||||
|
config['news_manager']['custom_feeds'][feed_name] = feed_url
|
||||||
|
|
||||||
|
# Add to enabled feeds if not already there
|
||||||
|
if feed_name not in config['news_manager']['enabled_feeds']:
|
||||||
|
config['news_manager']['enabled_feeds'].append(feed_name)
|
||||||
|
|
||||||
|
# Save updated config
|
||||||
|
with open(config_path, 'w') as f:
|
||||||
|
json.dump(config, f, indent=4)
|
||||||
|
|
||||||
|
print(f"SUCCESS: Successfully added custom feed: {feed_name}")
|
||||||
|
print(f" URL: {feed_url}")
|
||||||
|
print(f" Feed is now enabled and will appear in rotation")
|
||||||
|
return True
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"ERROR: Error adding custom feed: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
def list_all_feeds():
|
||||||
|
"""List all available feeds (default + custom)"""
|
||||||
|
config_path = "config/config.json"
|
||||||
|
|
||||||
|
try:
|
||||||
|
with open(config_path, 'r') as f:
|
||||||
|
config = json.load(f)
|
||||||
|
|
||||||
|
news_config = config.get('news_manager', {})
|
||||||
|
custom_feeds = news_config.get('custom_feeds', {})
|
||||||
|
enabled_feeds = news_config.get('enabled_feeds', [])
|
||||||
|
|
||||||
|
print("\nAvailable News Feeds:")
|
||||||
|
print("=" * 50)
|
||||||
|
|
||||||
|
# Default feeds (hardcoded in news_manager.py)
|
||||||
|
default_feeds = {
|
||||||
|
'MLB': 'http://espn.com/espn/rss/mlb/news',
|
||||||
|
'NFL': 'http://espn.go.com/espn/rss/nfl/news',
|
||||||
|
'NCAA FB': 'https://www.espn.com/espn/rss/ncf/news',
|
||||||
|
'NHL': 'https://www.espn.com/espn/rss/nhl/news',
|
||||||
|
'NBA': 'https://www.espn.com/espn/rss/nba/news',
|
||||||
|
'TOP SPORTS': 'https://www.espn.com/espn/rss/news',
|
||||||
|
'BIG10': 'https://www.espn.com/blog/feed?blog=bigten',
|
||||||
|
'NCAA': 'https://www.espn.com/espn/rss/ncaa/news',
|
||||||
|
'Other': 'https://www.coveringthecorner.com/rss/current.xml'
|
||||||
|
}
|
||||||
|
|
||||||
|
print("\nDefault Sports Feeds:")
|
||||||
|
for name, url in default_feeds.items():
|
||||||
|
status = "ENABLED" if name in enabled_feeds else "DISABLED"
|
||||||
|
print(f" {name}: {status}")
|
||||||
|
print(f" {url}")
|
||||||
|
|
||||||
|
if custom_feeds:
|
||||||
|
print("\nCustom Feeds:")
|
||||||
|
for name, url in custom_feeds.items():
|
||||||
|
status = "ENABLED" if name in enabled_feeds else "DISABLED"
|
||||||
|
print(f" {name}: {status}")
|
||||||
|
print(f" {url}")
|
||||||
|
else:
|
||||||
|
print("\nCustom Feeds: None added yet")
|
||||||
|
|
||||||
|
print(f"\nCurrently Enabled Feeds: {len(enabled_feeds)}")
|
||||||
|
print(f" {', '.join(enabled_feeds)}")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"ERROR: Error listing feeds: {e}")
|
||||||
|
|
||||||
|
def remove_custom_feed(feed_name):
|
||||||
|
"""Remove a custom RSS feed"""
|
||||||
|
config_path = "config/config.json"
|
||||||
|
|
||||||
|
try:
|
||||||
|
with open(config_path, 'r') as f:
|
||||||
|
config = json.load(f)
|
||||||
|
|
||||||
|
news_config = config.get('news_manager', {})
|
||||||
|
custom_feeds = news_config.get('custom_feeds', {})
|
||||||
|
|
||||||
|
if feed_name not in custom_feeds:
|
||||||
|
print(f"ERROR: Custom feed '{feed_name}' not found!")
|
||||||
|
return False
|
||||||
|
|
||||||
|
# Remove from custom feeds
|
||||||
|
del config['news_manager']['custom_feeds'][feed_name]
|
||||||
|
|
||||||
|
# Remove from enabled feeds if present
|
||||||
|
if feed_name in config['news_manager']['enabled_feeds']:
|
||||||
|
config['news_manager']['enabled_feeds'].remove(feed_name)
|
||||||
|
|
||||||
|
# Save updated config
|
||||||
|
with open(config_path, 'w') as f:
|
||||||
|
json.dump(config, f, indent=4)
|
||||||
|
|
||||||
|
print(f"SUCCESS: Successfully removed custom feed: {feed_name}")
|
||||||
|
return True
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"ERROR: Error removing custom feed: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
def main():
|
||||||
|
if len(sys.argv) < 2:
|
||||||
|
print("Usage:")
|
||||||
|
print(" python3 add_custom_feed_example.py list")
|
||||||
|
print(" python3 add_custom_feed_example.py add <feed_name> <feed_url>")
|
||||||
|
print(" python3 add_custom_feed_example.py remove <feed_name>")
|
||||||
|
print("\nExamples:")
|
||||||
|
print(" # Add F1 news feed")
|
||||||
|
print(" python3 add_custom_feed_example.py add 'F1' 'https://www.espn.com/espn/rss/rpm/news'")
|
||||||
|
print(" # Add BBC F1 feed")
|
||||||
|
print(" python3 add_custom_feed_example.py add 'BBC F1' 'http://feeds.bbci.co.uk/sport/formula1/rss.xml'")
|
||||||
|
print(" # Add personal blog feed")
|
||||||
|
print(" python3 add_custom_feed_example.py add 'My Blog' 'https://myblog.com/rss.xml'")
|
||||||
|
return
|
||||||
|
|
||||||
|
command = sys.argv[1].lower()
|
||||||
|
|
||||||
|
if command == 'list':
|
||||||
|
list_all_feeds()
|
||||||
|
elif command == 'add':
|
||||||
|
if len(sys.argv) != 4:
|
||||||
|
print("ERROR: Usage: python3 add_custom_feed_example.py add <feed_name> <feed_url>")
|
||||||
|
return
|
||||||
|
feed_name = sys.argv[2]
|
||||||
|
feed_url = sys.argv[3]
|
||||||
|
add_custom_feed(feed_name, feed_url)
|
||||||
|
elif command == 'remove':
|
||||||
|
if len(sys.argv) != 3:
|
||||||
|
print("ERROR: Usage: python3 add_custom_feed_example.py remove <feed_name>")
|
||||||
|
return
|
||||||
|
feed_name = sys.argv[2]
|
||||||
|
remove_custom_feed(feed_name)
|
||||||
|
else:
|
||||||
|
print(f"ERROR: Unknown command: {command}")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
|
Before Width: | Height: | Size: 9.1 KiB After Width: | Height: | Size: 9.9 KiB |
|
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 7.2 KiB |
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 11 KiB |
BIN
assets/broadcast_logos/paramount-plus.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
assets/broadcast_logos/prime.png
Normal file
|
After Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 6.0 KiB After Width: | Height: | Size: 4.3 KiB |
@@ -1,404 +1,53 @@
|
|||||||
NCAAF
|
NCAAF
|
||||||
AAMU => Alabama A&M Bulldogs
|
AMH => Amherst Mammoths
|
||||||
ACU => Abilene Christian Wildcats
|
|
||||||
ADA => Adams State Grizzlies
|
|
||||||
ADR => Adrian Bulldogs
|
|
||||||
AFA => Air Force Falcons
|
|
||||||
AIC => American International Yellow Jackets
|
|
||||||
AKR => Akron Zips
|
|
||||||
ALA => Alabama Crimson Tide
|
|
||||||
ALB => Albright Lions
|
|
||||||
ALBS => Albany State (GA) Golden Rams
|
|
||||||
ALCN => Alcorn State Braves
|
|
||||||
ALD => Alderson Broaddus Battlers
|
|
||||||
ALF => Alfred Saxons
|
|
||||||
ALL => Allegheny Gators
|
|
||||||
ALST => Alabama State Hornets
|
|
||||||
AMH => Amherst College Mammoths
|
|
||||||
AND => Anderson (IN) Ravens
|
|
||||||
ANG => Angelo State Rams
|
|
||||||
ANN => Anna Maria College Amcats
|
ANN => Anna Maria College Amcats
|
||||||
APP => Appalachian State Mountaineers
|
|
||||||
APSU => Austin Peay Governors
|
|
||||||
ARIZ => Arizona Wildcats
|
ARIZ => Arizona Wildcats
|
||||||
ARK => Arkansas-Monticello Boll Weevils
|
ARK => Arkansas Razorbacks
|
||||||
ARMY => Army Black Knights
|
|
||||||
ARST => Arkansas State Red Wolves
|
|
||||||
ASH => Ashland Eagles
|
|
||||||
ASP => Assumption Greyhounds
|
|
||||||
ASU => Arizona State Sun Devils
|
ASU => Arizona State Sun Devils
|
||||||
AUB => Auburn Tigers
|
AUB => Auburn Tigers
|
||||||
AUG => St. Augustine's Falcons
|
BOIS => Boise State Broncos
|
||||||
AUR => Aurora Spartans
|
BRST => Bridgewater State Bears
|
||||||
AUS => Austin College 'Roos
|
BUENA => Buena Vista Beavers
|
||||||
AVE => Averett Cougars
|
CAL => California Golden Bears
|
||||||
AVI => Avila College Eagles
|
CAR => Carroll University (WI) Pioneers
|
||||||
AZU => Azusa Pacific Cougars
|
CLA => Claremont-Mudd-Scripps College Stags
|
||||||
BAK => Baker University Wildcats
|
COLBY => Colby College White Mules
|
||||||
BAL => Baldwin Wallace Yellow Jackets
|
|
||||||
BALL => Ball State Cardinals
|
|
||||||
BAT => Bates College Bobcats
|
|
||||||
BAY => Baylor Bears
|
|
||||||
BC => Boston College Eagles
|
|
||||||
BEC => Becker College Hawks
|
|
||||||
BEL => Beloit College Buccaneers
|
|
||||||
BEN => Benedictine University (IL) Eagles
|
|
||||||
BENT => Bentley Falcons
|
|
||||||
BET => Bethel (TN) Wildcats
|
|
||||||
BGSU => Bowling Green Falcons
|
|
||||||
BHS => Black Hills State Yellow Jackets
|
|
||||||
BIR => Birmingham-Southern Panthers
|
|
||||||
BKN => Bacone College Warriors
|
|
||||||
BLA => Blackburn Beavers
|
|
||||||
BLOM => Bloomsburg Huskies
|
|
||||||
BLU => Bluffton Beavers
|
|
||||||
BOW => Bowdoin Polar Bears
|
|
||||||
BRI => British Columbia Thunderbirds
|
|
||||||
BRWN => Brown Bears
|
|
||||||
BST => Bemidji State Beavers
|
|
||||||
BSU => Bowie State Bulldogs
|
|
||||||
BUCK => Bucknell Bison
|
|
||||||
BUE => Buena Vista Beavers
|
|
||||||
BUF => Buffalo State Bengals
|
|
||||||
BUFF => Buffalo Bulls
|
|
||||||
BUT => Butler Bulldogs
|
|
||||||
BYU => BYU Cougars
|
|
||||||
CAL => California Lutheran Kingsmen
|
|
||||||
CAM => Campbell Fighting Camels
|
|
||||||
CAP => Capital University Crusaders
|
|
||||||
CAR => Carthage College Red Men
|
|
||||||
CARK => Central Arkansas Bears
|
|
||||||
CAS => Castleton Spartans
|
|
||||||
CAT => Catholic University Cardinals
|
|
||||||
CCSU => Central Connecticut Blue Devils
|
|
||||||
CCU => Coastal Carolina Chanticleers
|
|
||||||
CEN => Centre College Colonels
|
|
||||||
CHA => Chapman University Panthers
|
|
||||||
CHI => Chicago Maroons
|
|
||||||
CHSO => Charleston Southern Buccaneers
|
|
||||||
CIN => Cincinnati Bearcats
|
|
||||||
CLA => Clarion Golden Eagles
|
|
||||||
CLEM => Clemson Tigers
|
|
||||||
CLMB => Columbia Lions
|
|
||||||
CLT => Charlotte 49ers
|
|
||||||
CMU => Central Michigan Chippewas
|
|
||||||
COE => Coe College Kohawks
|
|
||||||
COL => Colorado School of Mines Orediggers
|
|
||||||
COLC => Colorado College Tigers
|
|
||||||
COLG => Colgate Raiders
|
|
||||||
COLO => Colorado Buffaloes
|
COLO => Colorado Buffaloes
|
||||||
CON => Concordia-Minnesota Cobbers
|
CONN => UConn Huskies
|
||||||
COR => Cornell College (IA) Rams
|
|
||||||
CP => Cal Poly Mustangs
|
CP => Cal Poly Mustangs
|
||||||
CRO => Crown Storm
|
|
||||||
CSU => Colorado State Rams
|
CSU => Colorado State Rams
|
||||||
CUL => Culver-Stockton Wildcats
|
|
||||||
CUM => Cumberland College Indians
|
|
||||||
CUR => Curry College Colonels
|
CUR => Curry College Colonels
|
||||||
DAK => Dakota Wesleyan Tigers
|
DEL => Delaware Blue Hens
|
||||||
DART => Dartmouth Big Green
|
|
||||||
DAV => Davidson Wildcats
|
|
||||||
DAY => Dayton Flyers
|
|
||||||
DEF => Defiance Yellow Jackets
|
|
||||||
DEL => Delta State Statesmen
|
|
||||||
DEN => Denison Big Red
|
|
||||||
DEP => DePauw Tigers
|
|
||||||
DIC => Dickinson State Blue Hawks
|
|
||||||
DRKE => Drake Bulldogs
|
|
||||||
DSU => Delaware State Hornets
|
|
||||||
DUB => Dubuque Spartans
|
DUB => Dubuque Spartans
|
||||||
DUKE => Duke Blue Devils
|
ELM => Elmhurst Bluejays
|
||||||
DUQ => Duquesne Dukes
|
FAMU => Florida A&M Rattlers
|
||||||
EAS => Eastern New Mexico Greyhounds
|
|
||||||
ECU => East Carolina Pirates
|
|
||||||
EDI => Edinboro Fighting Scots
|
|
||||||
EIU => Eastern Illinois Panthers
|
|
||||||
EKU => Eastern Kentucky Colonels
|
|
||||||
ELI => Elizabeth City State Vikings
|
|
||||||
ELM => Elmhurst Blue Jays
|
|
||||||
ELON => Elon Phoenix
|
|
||||||
EMO => Emory & Henry Wasps
|
|
||||||
EMP => Emporia State Hornets
|
|
||||||
EMU => Eastern Michigan Eagles
|
|
||||||
END => Endicott College Gulls
|
|
||||||
EOR => Eastern Oregon Mountaineers
|
|
||||||
ETSU => East Tennessee State Buccaneers
|
|
||||||
EUR => Eureka College Red Devils
|
|
||||||
EWU => Eastern Washington Eagles
|
|
||||||
FAU => Florida Atlantic Owls
|
|
||||||
FAY => Fayetteville State Broncos
|
|
||||||
FDU => FDU-Florham Devils
|
|
||||||
FER => Ferrum Panthers
|
|
||||||
FIN => Findlay Oilers
|
|
||||||
FIT => Fitchburg State Falcons
|
|
||||||
FIU => Florida International Panthers
|
|
||||||
FLA => Florida Gators
|
FLA => Florida Gators
|
||||||
FOR => Fort Valley State Wildcats
|
|
||||||
FRA => Franklin Grizzlies
|
|
||||||
FRES => Fresno State Bulldogs
|
|
||||||
FRO => Frostburg State Bobcats
|
|
||||||
FRST => Ferris State Bulldogs
|
|
||||||
FSU => Florida State Seminoles
|
FSU => Florida State Seminoles
|
||||||
FTLW => Fort Lewis Skyhawks
|
|
||||||
FUR => Furman Paladins
|
|
||||||
GAL => Gallaudet Bison
|
|
||||||
GAN => Gannon Golden Knights
|
|
||||||
GASO => Georgia Southern Eagles
|
|
||||||
GAST => Georgia State Panthers
|
|
||||||
GEN => Geneva College Golden Tornadoes
|
|
||||||
GEO => George Fox University Bruins
|
|
||||||
GET => Gettysburg Bullets
|
|
||||||
GLE => Glenville State Pioneers
|
|
||||||
GMU => George Mason Patriots
|
|
||||||
GRA => Grand Valley State Lakers
|
|
||||||
GRE => Greenville Panthers
|
|
||||||
GRI => Grinnell Pioneers
|
GRI => Grinnell Pioneers
|
||||||
GRO => Grove City College Wolverines
|
|
||||||
GT => Georgia Tech Yellow Jackets
|
GT => Georgia Tech Yellow Jackets
|
||||||
GUI => Guilford Quakers
|
GTWN => Georgetown Hoyas
|
||||||
GWEB => Gardner-Webb Bulldogs
|
|
||||||
HAM => Hampden-Sydney Tigers
|
|
||||||
HAMP => Hampton Pirates
|
|
||||||
HAN => Hanover Panthers
|
|
||||||
HAR => Hartwick Hawks
|
|
||||||
HARV => Harvard Crimson
|
|
||||||
HAS => Haskell Indian Nations Jayhawks
|
|
||||||
HAW => Hawai'i Rainbow Warriors
|
HAW => Hawai'i Rainbow Warriors
|
||||||
HBU => Houston Baptist Huskies
|
|
||||||
HC => Holy Cross Crusaders
|
|
||||||
HEI => Heidelberg Student Princes
|
|
||||||
HEN => Hendrix College Warriors
|
|
||||||
HIL => Hillsdale Chargers
|
|
||||||
HIR => Hiram College Terriers
|
|
||||||
HOB => Hobart Statesmen
|
|
||||||
HOU => Houston Cougars
|
|
||||||
HOW => Howard Bison
|
HOW => Howard Bison
|
||||||
HUS => Husson Eagles
|
|
||||||
IDHO => Idaho Vandals
|
IDHO => Idaho Vandals
|
||||||
IDST => Idaho State Bengals
|
|
||||||
ILL => Illinois Fighting Illini
|
|
||||||
ILST => Illinois State Redbirds
|
|
||||||
ILW => Illinois Wesleyan Titans
|
|
||||||
IND => Indianapolis
|
|
||||||
INST => Indiana State Sycamores
|
|
||||||
IOW => Iowa Wesleyan Tigers
|
|
||||||
IOWA => Iowa Hawkeyes
|
|
||||||
ISU => Iowa State Cyclones
|
ISU => Iowa State Cyclones
|
||||||
ITH => Ithaca Bombers
|
JXST => Jacksonville State Gamecocks
|
||||||
IU => Indiana Hoosiers
|
|
||||||
JKST => Jackson State Tigers
|
|
||||||
JMU => James Madison Dukes
|
|
||||||
JOH => Johnson C Smith Golden Bulls
|
|
||||||
JUN => Juniata Eagles
|
|
||||||
JVST => Jacksonville State Gamecocks
|
|
||||||
KAL => Kalamazoo Hornets
|
|
||||||
KAN => Kansas Wesleyan University Coyotes
|
|
||||||
KEN => Kenyon Lords
|
|
||||||
KENN => Kennesaw State Owls
|
|
||||||
KENT => Kent State Golden Flashes
|
|
||||||
KIN => King's College (PA) Monarchs
|
|
||||||
KNO => Knox College Prairie Fire
|
|
||||||
KSU => Kansas State Wildcats
|
|
||||||
KU => Kansas Jayhawks
|
|
||||||
KUT => Kutztown Golden Bears
|
|
||||||
KYST => Kentucky State Thorobreds
|
|
||||||
KYW => Kentucky Wesleyan Panthers
|
|
||||||
LA => La Verne Leopards
|
|
||||||
LAC => Lane Dragons
|
|
||||||
LAF => Lafayette Leopards
|
|
||||||
LAG => LaGrange College Panthers
|
|
||||||
LAK => Lake Forest Foresters
|
|
||||||
LAM => Lambuth Eagles
|
|
||||||
LAN => Langston Lions
|
|
||||||
LAW => Lawrence Vikings
|
|
||||||
LEB => Lebanon Valley Flying Dutchmen
|
|
||||||
LEH => Lehigh Mountain Hawks
|
|
||||||
LEN => Lenoir-Rhyne Bears
|
|
||||||
LEW => Lewis & Clark Pioneers
|
|
||||||
LIB => Liberty Flames
|
|
||||||
LIM => Limestone Saints
|
|
||||||
LIN => Linfield Wildcats
|
|
||||||
LOC => Lock Haven Bald Eagles
|
|
||||||
LOR => Loras College Duhawks
|
|
||||||
LOU => Louisville Cardinals
|
|
||||||
LSU => LSU Tigers
|
|
||||||
LT => Louisiana Tech Bulldogs
|
|
||||||
LUT => Luther Norse
|
LUT => Luther Norse
|
||||||
LYC => Lycoming Warriors
|
MESA => Colorado Mesa Mavericks
|
||||||
M-OH => Miami (OH) RedHawks
|
MIL => Millikin Big Blue
|
||||||
MAC => Macalester Scots
|
MOR => Morehouse College Maroon Tigers
|
||||||
MAI => Maine Maritime Mariners
|
NOR => North Park Vikings
|
||||||
MAN => Mansfield Mountaineers
|
|
||||||
MAR => Maryville College Fighting Scots
|
|
||||||
MAS => Mass Maritime Buccaneers
|
|
||||||
MASS => UMass Minutemen
|
|
||||||
MAY => Mayville State Comets
|
|
||||||
MCM => McMurry War Hawks
|
|
||||||
MCN => McNeese Cowboys
|
|
||||||
MD => Maryland Terrapins
|
|
||||||
MEM => Memphis Tigers
|
|
||||||
MEN => Menlo College Oaks
|
|
||||||
MER => Merchant Marine Mariners
|
|
||||||
MERC => Mercyhurst Lakers
|
|
||||||
MES => Colorado Mesa Mavericks
|
|
||||||
MET => Methodist Monarchs
|
|
||||||
MH => Mars Hill Mountain Lions
|
|
||||||
MIAMI => Miami Hurricanes
|
|
||||||
MICH => Michigan Wolverines
|
|
||||||
MID => Midwestern State Mustangs
|
|
||||||
MIL => Millsaps Majors
|
|
||||||
MIN => Minot State Beavers
|
|
||||||
MINN => Minnesota Golden Gophers
|
|
||||||
MIS => Missouri Western Griffons
|
|
||||||
MISS => Ole Miss Rebels
|
|
||||||
MIZ => Missouri Tigers
|
|
||||||
MNST => Minnesota State Mavericks
|
|
||||||
MONM => Monmouth Hawks
|
|
||||||
MONT => Montana Grizzlies
|
|
||||||
MOR => Morningside Chiefs
|
|
||||||
MORE => Morehead State Eagles
|
|
||||||
MORG => Morgan State Bears
|
|
||||||
MOU => Mount Union Raiders
|
|
||||||
MRSH => Marshall Thundering Herd
|
|
||||||
MRST => Marist Red Foxes
|
|
||||||
MSST => Mississippi State Bulldogs
|
|
||||||
MSU => Michigan State Spartans
|
|
||||||
MTST => Montana State Bobcats
|
|
||||||
MTSU => Middle Tennessee Blue Raiders
|
|
||||||
MTU => Michigan Tech Huskies
|
|
||||||
MUH => Muhlenberg Mules
|
|
||||||
MUR => Murray State Racers
|
|
||||||
MUS => Muskingum Fighting Muskies
|
|
||||||
MVSU => Mississippi Valley State Delta Devils
|
|
||||||
NAU => Northern Arizona Lumberjacks
|
|
||||||
NAVY => Navy Midshipmen
|
|
||||||
NBY => Newberry Wolves
|
|
||||||
NCAT => North Carolina A&T Aggies
|
|
||||||
NCCU => North Carolina Central Eagles
|
|
||||||
NCST => NC State Wolfpack
|
|
||||||
ND => Notre Dame Fighting Irish
|
|
||||||
NDOH => Notre Dame College Falcons
|
|
||||||
NDSU => North Dakota State Bison
|
|
||||||
NEB => Nebraska-Kearney Lopers
|
|
||||||
NEV => Nevada Wolf Pack
|
|
||||||
NH => New Haven Chargers
|
|
||||||
NICH => Nicholls Colonels
|
|
||||||
NIU => Northern Illinois Huskies
|
|
||||||
NMH => New Mexico Highlands Cowboys
|
|
||||||
NMI => Northern Michigan Wildcats
|
|
||||||
NMSU => New Mexico State Aggies
|
|
||||||
NOR => Univ. of Northwestern-St. Paul Eagles
|
|
||||||
NORF => Norfolk State Spartans
|
|
||||||
NW => Northwestern Wildcats
|
|
||||||
OBE => Oberlin Yeomen
|
|
||||||
ODU => Old Dominion Monarchs
|
|
||||||
OHI => Ohio Northern Polar Bears
|
|
||||||
OHIO => Ohio Bobcats
|
|
||||||
OKL => Oklahoma Baptist Bison
|
|
||||||
OKST => Oklahoma State Cowboys
|
|
||||||
OLI => Olivet College Comets
|
|
||||||
OMA => Omaha Mavericks
|
|
||||||
ORST => Oregon State Beavers
|
|
||||||
OSU => Ohio State Buckeyes
|
|
||||||
OTT => Otterbein Cardinals
|
|
||||||
OU => Oklahoma Sooners
|
|
||||||
PAC => Pacific (OR) Boxers
|
|
||||||
PENN => Pennsylvania Quakers
|
|
||||||
PIKE => Pikeville Bears
|
|
||||||
PITT => Pittsburgh Panthers
|
|
||||||
PRE => Presentation College Saints
|
|
||||||
PRI => Principia College Panthers
|
|
||||||
PRIN => Princeton Tigers
|
|
||||||
PST => Pittsburg State Gorillas
|
|
||||||
PSU => Penn State Nittany Lions
|
|
||||||
RED => Redlands Bulldogs
|
RED => Redlands Bulldogs
|
||||||
RICE => Rice Owls
|
|
||||||
RICH => Richmond Spiders
|
|
||||||
RIT => Rochester Yellow Jackets
|
|
||||||
ROB => Robert Morris (IL) Eagles
|
|
||||||
ROS => Rose-Hulman Engineers
|
|
||||||
RUTG => Rutgers Scarlet Knights
|
|
||||||
SAC => Sacramento State Hornets
|
SAC => Sacramento State Hornets
|
||||||
SAG => Saginaw Valley Cardinals
|
|
||||||
SDAK => South Dakota Coyotes
|
|
||||||
SDSU => San Diego State Aztecs
|
SDSU => San Diego State Aztecs
|
||||||
SET => Seton Hill Griffins
|
|
||||||
SIU => Southern Illinois Salukis
|
|
||||||
SJSU => San José State Spartans
|
SJSU => San José State Spartans
|
||||||
SLI => Slippery Rock The Rock
|
|
||||||
SOU => Southwestern College Moundbuilders
|
|
||||||
SPR => Springfield College Pride
|
|
||||||
ST => St. Scholastica Saints
|
|
||||||
STAN => Stanford Cardinal
|
STAN => Stanford Cardinal
|
||||||
STE => Stevenson University Mustangs
|
|
||||||
STET => Stetson Hatters
|
STET => Stetson Hatters
|
||||||
STO => Stonehill College Skyhawks
|
|
||||||
SUS => Susquehanna University River Hawks
|
|
||||||
SUU => Southern Utah Thunderbirds
|
|
||||||
SYR => Syracuse Orange
|
|
||||||
TA&M => Texas A&M Aggies
|
|
||||||
TAY => Taylor Trojans
|
|
||||||
TEM => Temple Owls
|
|
||||||
TEX => Texas Longhorns
|
|
||||||
TIF => Tiffin University Dragons
|
|
||||||
TLSA => Tulsa Golden Hurricane
|
|
||||||
TRI => Trinity University (TX) Tigers
|
|
||||||
TUF => Tufts University Jumbos
|
|
||||||
TXST => Texas State Bobcats
|
|
||||||
UAB => UAB Blazers
|
UAB => UAB Blazers
|
||||||
UAPB => Arkansas-Pine Bluff Golden Lions
|
|
||||||
UCD => UC Davis Aggies
|
|
||||||
UCF => UCF Knights
|
|
||||||
UCLA => UCLA Bruins
|
UCLA => UCLA Bruins
|
||||||
UCONN => UConn Huskies
|
|
||||||
UGA => Georgia Bulldogs
|
UGA => Georgia Bulldogs
|
||||||
UK => Kentucky Wildcats
|
|
||||||
UL => Louisiana Ragin' Cajuns
|
|
||||||
ULM => UL Monroe Warhawks
|
|
||||||
UMD => Minnesota-Duluth Bulldogs
|
|
||||||
UMDA => UMASS Dartmouth Corsairs
|
|
||||||
UML => UMass Lowell River Hawks
|
|
||||||
UNA => North Alabama Lions
|
|
||||||
UNC => North Carolina Tar Heels
|
|
||||||
UNCO => Northern Colorado Bears
|
|
||||||
UND => North Dakota Fighting Hawks
|
|
||||||
UNH => New Hampshire Wildcats
|
|
||||||
UNI => University of Mary Marauders
|
|
||||||
UNLV => UNLV Rebels
|
|
||||||
UNM => New Mexico Lobos
|
|
||||||
UNNY => Union Dutchmen
|
|
||||||
UNT => North Texas Mean Green
|
|
||||||
UPP => Upper Iowa Peacocks
|
|
||||||
URI => Rhode Island Rams
|
|
||||||
USA => South Alabama Jaguars
|
USA => South Alabama Jaguars
|
||||||
USC => USC Trojans
|
USC => USC Trojans
|
||||||
USD => San Diego Toreros
|
|
||||||
USF => South Florida Bulls
|
USF => South Florida Bulls
|
||||||
USU => Utah State Aggies
|
|
||||||
UTAH => Utah Utes
|
|
||||||
UTC => Chattanooga Mocs
|
|
||||||
UTI => Utica College Pioneers
|
|
||||||
UVA => Virginia Cavaliers
|
|
||||||
VAL => Valley City State Vikings
|
|
||||||
VAN => Vanderbilt Commodores
|
|
||||||
VILL => Villanova Wildcats
|
|
||||||
VIR => Virginia State Trojans
|
|
||||||
VT => Virginia Tech Hokies
|
|
||||||
WAB => Wabash College Little Giants
|
|
||||||
WAKE => Wake Forest Demon Deacons
|
|
||||||
WAS => Washington-Missouri Bears
|
|
||||||
WASH => Washington Huskies
|
|
||||||
WAY => Wayne State (MI) Warriors
|
|
||||||
WES => Westminster College (MO) Blue Jays
|
|
||||||
WHE => Wheaton College Illinois Thunder
|
|
||||||
WIL => Wilkes University Colonels
|
|
||||||
WIN => Wingate Bulldogs
|
|
||||||
WIS => Wisconsin-Platteville Pioneers
|
|
||||||
WISC => Wisconsin Badgers
|
|
||||||
WKU => Western Kentucky Hilltoppers
|
|
||||||
WOR => Worcester State College Lancers
|
|
||||||
WSU => Washington State Cougars
|
|
||||||
WVU => West Virginia Mountaineers
|
|
||||||
YALE => Yale Bulldogs
|
YALE => Yale Bulldogs
|
||||||
|
|
||||||
NBA
|
NBA
|
||||||
@@ -1106,6 +755,149 @@ MLB Conferences/Divisions
|
|||||||
OAK => Oakland Athletics
|
OAK => Oakland Athletics
|
||||||
SEA => Seattle Mariners
|
SEA => Seattle Mariners
|
||||||
TEX => Texas Rangers
|
TEX => Texas Rangers
|
||||||
|
Soccer - Premier League (England)
|
||||||
|
ARS => Arsenal
|
||||||
|
AVL => Aston Villa
|
||||||
|
BHA => Brighton & Hove Albion
|
||||||
|
BOU => AFC Bournemouth
|
||||||
|
BRE => Brentford
|
||||||
|
BUR => Burnley
|
||||||
|
CHE => Chelsea
|
||||||
|
CRY => Crystal Palace
|
||||||
|
EVE => Everton
|
||||||
|
FUL => Fulham
|
||||||
|
LIV => Liverpool
|
||||||
|
LUT => Luton Town
|
||||||
|
MCI => Manchester City
|
||||||
|
MUN => Manchester United
|
||||||
|
NEW => Newcastle United
|
||||||
|
NFO => Nottingham Forest
|
||||||
|
SHU => Sheffield United
|
||||||
|
TOT => Tottenham Hotspur
|
||||||
|
WHU => West Ham United
|
||||||
|
WOL => Wolverhampton Wanderers
|
||||||
|
|
||||||
|
Soccer - La Liga (Spain)
|
||||||
|
ALA => Alavés
|
||||||
|
ATH => Athletic Bilbao
|
||||||
|
ATM => Atlético Madrid
|
||||||
|
BAR => Barcelona
|
||||||
|
BET => Real Betis
|
||||||
|
CAG => Cagliari
|
||||||
|
CEL => Celta Vigo
|
||||||
|
ESP => Espanyol
|
||||||
|
GET => Getafe
|
||||||
|
GIR => Girona
|
||||||
|
LAZ => Lazio
|
||||||
|
LEG => Leganés
|
||||||
|
RAY => Rayo Vallecano
|
||||||
|
RMA => Real Madrid
|
||||||
|
SEV => Sevilla
|
||||||
|
VAL => Valencia
|
||||||
|
VLD => Valladolid
|
||||||
|
|
||||||
|
Soccer - Bundesliga (Germany)
|
||||||
|
BOC => VfL Bochum
|
||||||
|
BOL => VfL Bochum
|
||||||
|
DOR => Borussia Dortmund
|
||||||
|
FCA => FC Augsburg
|
||||||
|
FCB => Bayern Munich
|
||||||
|
FCU => FC Union Berlin
|
||||||
|
HAC => Hannover 96
|
||||||
|
HDH => Hertha BSC
|
||||||
|
KOL => 1. FC Köln
|
||||||
|
LEV => Bayer Leverkusen
|
||||||
|
M05 => Mainz 05
|
||||||
|
RBL => RB Leipzig
|
||||||
|
SCF => SC Freiburg
|
||||||
|
SGE => Eintracht Frankfurt
|
||||||
|
STU => VfB Stuttgart
|
||||||
|
SVW => Werder Bremen
|
||||||
|
TSG => TSG Hoffenheim
|
||||||
|
WOB => VfL Wolfsburg
|
||||||
|
|
||||||
|
Soccer - Serie A (Italy)
|
||||||
|
ATA => Atalanta
|
||||||
|
CAG => Cagliari
|
||||||
|
EMP => Empoli
|
||||||
|
FIO => Fiorentina
|
||||||
|
INT => Inter Milan
|
||||||
|
JUV => Juventus
|
||||||
|
LAZ => Lazio
|
||||||
|
MIL => AC Milan
|
||||||
|
MON => Monza
|
||||||
|
NAP => Napoli
|
||||||
|
ROM => Roma
|
||||||
|
TOR => Torino
|
||||||
|
UDI => Udinese
|
||||||
|
VER => Hellas Verona
|
||||||
|
|
||||||
|
Soccer - Ligue 1 (France)
|
||||||
|
LIL => Lille
|
||||||
|
LPM => Lille
|
||||||
|
LYON => Lyon
|
||||||
|
MAR => Marseille
|
||||||
|
MON => Monaco
|
||||||
|
NAN => Nantes
|
||||||
|
NICE => Nice
|
||||||
|
OL => Olympique Lyonnais
|
||||||
|
OM => Olympique de Marseille
|
||||||
|
PAR => Paris Saint-Germain
|
||||||
|
PSG => Paris Saint-Germain
|
||||||
|
REN => Rennes
|
||||||
|
STR => Strasbourg
|
||||||
|
|
||||||
|
Soccer - Champions League
|
||||||
|
AJA => Ajax
|
||||||
|
ASM => AS Monaco
|
||||||
|
ASS => AS Saint-Étienne
|
||||||
|
BOC => VfL Bochum
|
||||||
|
CEL => Celtic
|
||||||
|
COM => Club Brugge
|
||||||
|
FCA => FC Augsburg
|
||||||
|
FCB => Bayern Munich
|
||||||
|
FCU => FC Union Berlin
|
||||||
|
FIO => Fiorentina
|
||||||
|
GEN => Genoa
|
||||||
|
HAC => Hannover 96
|
||||||
|
IPS => Ipswich Town
|
||||||
|
KSV => Kaiserslautern
|
||||||
|
LEC => Lecce
|
||||||
|
LIL => Lille
|
||||||
|
LIV => Liverpool
|
||||||
|
M05 => Mainz 05
|
||||||
|
MCI => Manchester City
|
||||||
|
MUN => Manchester United
|
||||||
|
NAN => Nantes
|
||||||
|
OSA => Osasuna
|
||||||
|
RBL => RB Leipzig
|
||||||
|
RCL => RC Lens
|
||||||
|
RMA => Real Madrid
|
||||||
|
SCF => SC Freiburg
|
||||||
|
SGE => Eintracht Frankfurt
|
||||||
|
SR => Sporting CP
|
||||||
|
STP => St. Pauli
|
||||||
|
SVW => Werder Bremen
|
||||||
|
TFC => Toulouse FC
|
||||||
|
TOT => Tottenham Hotspur
|
||||||
|
TSG => TSG Hoffenheim
|
||||||
|
UDI => Udinese
|
||||||
|
VEN => Venezia
|
||||||
|
VFB => VfB Stuttgart
|
||||||
|
VIL => Villarreal
|
||||||
|
|
||||||
|
Soccer - Other Teams
|
||||||
|
austin => Austin FC
|
||||||
|
cf_montral => CF Montréal
|
||||||
|
charlotte => Charlotte FC
|
||||||
|
dortmund => Borussia Dortmund
|
||||||
|
gladbach => Borussia Mönchengladbach
|
||||||
|
lafc => Los Angeles FC
|
||||||
|
leverkusen => Bayer Leverkusen
|
||||||
|
nycfc => New York City FC
|
||||||
|
paris_sg => Paris Saint-Germain
|
||||||
|
st_louis => St. Louis City SC
|
||||||
|
|
||||||
MLS Conferences/Divisions
|
MLS Conferences/Divisions
|
||||||
Conferences currently unsupported
|
Conferences currently unsupported
|
||||||
|
|
||||||
|
|||||||
BIN
assets/sports/mlb_logos/mlb.png
Normal file
|
After Width: | Height: | Size: 7.3 KiB |
|
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 40 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 20 KiB |
BIN
assets/sports/nba_logos/nba.png
Normal file
|
After Width: | Height: | Size: 490 B |
BIN
assets/sports/ncaa_fbs_logos/AANDM.png
Normal file
|
After Width: | Height: | Size: 409 B |
BIN
assets/sports/ncaa_fbs_logos/AMH.png
Normal file
|
After Width: | Height: | Size: 27 KiB |
BIN
assets/sports/ncaa_fbs_logos/ANN.png
Normal file
|
After Width: | Height: | Size: 65 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 44 KiB |
BIN
assets/sports/ncaa_fbs_logos/ASU.png
Normal file
|
After Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 20 KiB |
BIN
assets/sports/ncaa_fbs_logos/BOIS.png
Normal file
|
After Width: | Height: | Size: 54 KiB |
BIN
assets/sports/ncaa_fbs_logos/BRST.png
Normal file
|
After Width: | Height: | Size: 109 KiB |
BIN
assets/sports/ncaa_fbs_logos/BUENA.png
Normal file
|
After Width: | Height: | Size: 42 KiB |
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
BIN
assets/sports/ncaa_fbs_logos/CAR.png
Normal file
|
After Width: | Height: | Size: 34 KiB |
BIN
assets/sports/ncaa_fbs_logos/CLA.png
Normal file
|
After Width: | Height: | Size: 53 KiB |
BIN
assets/sports/ncaa_fbs_logos/COLBY.png
Normal file
|
After Width: | Height: | Size: 105 KiB |
|
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 35 KiB |
|
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 53 KiB |
BIN
assets/sports/ncaa_fbs_logos/CP.png
Normal file
|
After Width: | Height: | Size: 49 KiB |
BIN
assets/sports/ncaa_fbs_logos/CSU.png
Normal file
|
After Width: | Height: | Size: 84 KiB |
BIN
assets/sports/ncaa_fbs_logos/CUR.png
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
assets/sports/ncaa_fbs_logos/DEL.png
Normal file
|
After Width: | Height: | Size: 47 KiB |
BIN
assets/sports/ncaa_fbs_logos/DUB.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
assets/sports/ncaa_fbs_logos/ELM.png
Normal file
|
After Width: | Height: | Size: 42 KiB |
BIN
assets/sports/ncaa_fbs_logos/FAMU.png
Normal file
|
After Width: | Height: | Size: 44 KiB |
BIN
assets/sports/ncaa_fbs_logos/FLA.png
Normal file
|
After Width: | Height: | Size: 73 KiB |
|
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 56 KiB |
BIN
assets/sports/ncaa_fbs_logos/GRI.png
Normal file
|
After Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 23 KiB |
BIN
assets/sports/ncaa_fbs_logos/GTWN.png
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
assets/sports/ncaa_fbs_logos/HAW.png
Normal file
|
After Width: | Height: | Size: 44 KiB |
BIN
assets/sports/ncaa_fbs_logos/HOW.png
Normal file
|
After Width: | Height: | Size: 25 KiB |
BIN
assets/sports/ncaa_fbs_logos/IDHO.png
Normal file
|
After Width: | Height: | Size: 66 KiB |
|
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 61 KiB |
BIN
assets/sports/ncaa_fbs_logos/JXST.png
Normal file
|
After Width: | Height: | Size: 40 KiB |
BIN
assets/sports/ncaa_fbs_logos/LUT.png
Normal file
|
After Width: | Height: | Size: 81 KiB |
|
Before Width: | Height: | Size: 24 KiB |
BIN
assets/sports/ncaa_fbs_logos/MESA.png
Normal file
|
After Width: | Height: | Size: 96 KiB |
|
Before Width: | Height: | Size: 6.6 KiB After Width: | Height: | Size: 6.6 KiB |
BIN
assets/sports/ncaa_fbs_logos/MIL.png
Normal file
|
After Width: | Height: | Size: 6.3 KiB |
BIN
assets/sports/ncaa_fbs_logos/MOR.png
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
assets/sports/ncaa_fbs_logos/NOR.png
Normal file
|
After Width: | Height: | Size: 45 KiB |
BIN
assets/sports/ncaa_fbs_logos/RED.png
Normal file
|
After Width: | Height: | Size: 78 KiB |
BIN
assets/sports/ncaa_fbs_logos/SAC.png
Normal file
|
After Width: | Height: | Size: 47 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 37 KiB After Width: | Height: | Size: 48 KiB |
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 34 KiB |
BIN
assets/sports/ncaa_fbs_logos/STET.png
Normal file
|
After Width: | Height: | Size: 47 KiB |
BIN
assets/sports/ncaa_fbs_logos/TAANDM.png
Normal file
|
After Width: | Height: | Size: 3.6 KiB |
BIN
assets/sports/ncaa_fbs_logos/TAMU.png
Normal file
|
After Width: | Height: | Size: 378 B |
|
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 5.7 KiB |
|
Before Width: | Height: | Size: 41 KiB After Width: | Height: | Size: 56 KiB |
|
Before Width: | Height: | Size: 43 KiB After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 31 KiB |
BIN
assets/sports/ncaa_fbs_logos/UNT.png
Normal file
|
After Width: | Height: | Size: 29 KiB |
BIN
assets/sports/ncaa_fbs_logos/USA.png
Normal file
|
After Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 4.5 KiB After Width: | Height: | Size: 5.0 KiB |
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 40 KiB |
|
Before Width: | Height: | Size: 5.7 KiB |
BIN
assets/sports/ncaa_fbs_logos/YALE.png
Normal file
|
After Width: | Height: | Size: 23 KiB |
BIN
assets/sports/ncaa_fbs_logos/ncaa_fb.png
Normal file
|
After Width: | Height: | Size: 21 KiB |
BIN
assets/sports/ncaa_fbs_logos/ncaam.png
Normal file
|
After Width: | Height: | Size: 651 B |
BIN
assets/sports/nfl_logos/nfl.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
assets/sports/nhl_logos/nhl.png
Normal file
|
After Width: | Height: | Size: 430 B |
1
check_team_images.py
Normal file
@@ -0,0 +1 @@
|
|||||||
|
|
||||||
23
cleanup_venv.sh
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Cleanup script to remove virtual environment if it exists
|
||||||
|
# This script removes the venv_web_v2 directory if it exists
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Get the directory where this script is located
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
cd "$SCRIPT_DIR"
|
||||||
|
|
||||||
|
echo "Cleaning up virtual environment..."
|
||||||
|
|
||||||
|
# Check if virtual environment exists and remove it
|
||||||
|
if [ -d "venv_web_v2" ]; then
|
||||||
|
echo "Removing existing virtual environment..."
|
||||||
|
rm -rf venv_web_v2
|
||||||
|
echo "Virtual environment removed successfully"
|
||||||
|
else
|
||||||
|
echo "No virtual environment found to remove"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Cleanup complete!"
|
||||||
129
clear_cache.py
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Cache clearing utility for LEDMatrix
|
||||||
|
This script allows manual clearing of specific cache keys or all cache data.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import json
|
||||||
|
import argparse
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
# Add the src directory to the path so we can import our modules
|
||||||
|
sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'src'))
|
||||||
|
|
||||||
|
from cache_manager import CacheManager
|
||||||
|
|
||||||
|
def list_cache_keys(cache_manager):
|
||||||
|
"""List all available cache keys."""
|
||||||
|
cache_dir = cache_manager.cache_dir
|
||||||
|
if not cache_dir or not os.path.exists(cache_dir):
|
||||||
|
print(f"Cache directory does not exist: {cache_dir}")
|
||||||
|
return []
|
||||||
|
|
||||||
|
cache_files = []
|
||||||
|
for file in os.listdir(cache_dir):
|
||||||
|
if file.endswith('.json'):
|
||||||
|
cache_files.append(file[:-5]) # Remove .json extension
|
||||||
|
|
||||||
|
return cache_files
|
||||||
|
|
||||||
|
def clear_specific_cache(cache_manager, key):
|
||||||
|
"""Clear a specific cache key."""
|
||||||
|
try:
|
||||||
|
cache_manager.clear_cache(key)
|
||||||
|
print(f"✓ Cleared cache key: {key}")
|
||||||
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
print(f"✗ Error clearing cache key '{key}': {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
def clear_all_cache(cache_manager):
|
||||||
|
"""Clear all cache data."""
|
||||||
|
try:
|
||||||
|
cache_manager.clear_cache()
|
||||||
|
print("✓ Cleared all cache data")
|
||||||
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
print(f"✗ Error clearing all cache: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
def show_cache_info(cache_manager, key=None):
|
||||||
|
"""Show information about cache entries."""
|
||||||
|
if key:
|
||||||
|
try:
|
||||||
|
data = cache_manager.get(key)
|
||||||
|
if data is not None:
|
||||||
|
print(f"Cache key '{key}' exists with data type: {type(data)}")
|
||||||
|
if isinstance(data, dict):
|
||||||
|
print(f" Keys: {list(data.keys())}")
|
||||||
|
if 'games' in data:
|
||||||
|
print(f" Number of games: {len(data['games']) if isinstance(data['games'], dict) else 'N/A'}")
|
||||||
|
elif isinstance(data, list):
|
||||||
|
print(f" Number of items: {len(data)}")
|
||||||
|
else:
|
||||||
|
print(f" Data: {str(data)[:100]}...")
|
||||||
|
else:
|
||||||
|
print(f"Cache key '{key}' does not exist or is expired")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error checking cache key '{key}': {e}")
|
||||||
|
else:
|
||||||
|
# Show all cache keys
|
||||||
|
keys = list_cache_keys(cache_manager)
|
||||||
|
if keys:
|
||||||
|
print("Available cache keys:")
|
||||||
|
for key in sorted(keys):
|
||||||
|
print(f" - {key}")
|
||||||
|
else:
|
||||||
|
print("No cache keys found")
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = argparse.ArgumentParser(description='Clear LEDMatrix cache data')
|
||||||
|
parser.add_argument('--list', '-l', action='store_true',
|
||||||
|
help='List all available cache keys')
|
||||||
|
parser.add_argument('--clear-all', '-a', action='store_true',
|
||||||
|
help='Clear all cache data')
|
||||||
|
parser.add_argument('--clear', '-c', type=str, metavar='KEY',
|
||||||
|
help='Clear a specific cache key')
|
||||||
|
parser.add_argument('--info', '-i', type=str, metavar='KEY',
|
||||||
|
help='Show information about a specific cache key')
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
# Initialize cache manager
|
||||||
|
cache_manager = CacheManager()
|
||||||
|
|
||||||
|
if args.list:
|
||||||
|
show_cache_info(cache_manager)
|
||||||
|
elif args.clear_all:
|
||||||
|
print("Clearing all cache data...")
|
||||||
|
clear_all_cache(cache_manager)
|
||||||
|
elif args.clear:
|
||||||
|
print(f"Clearing cache key: {args.clear}")
|
||||||
|
clear_specific_cache(cache_manager, args.clear)
|
||||||
|
elif args.info:
|
||||||
|
show_cache_info(cache_manager, args.info)
|
||||||
|
else:
|
||||||
|
# Default: show available options
|
||||||
|
print("LEDMatrix Cache Utility")
|
||||||
|
print("=" * 30)
|
||||||
|
print()
|
||||||
|
print("Available commands:")
|
||||||
|
print(" --list, -l List all cache keys")
|
||||||
|
print(" --clear-all, -a Clear all cache data")
|
||||||
|
print(" --clear KEY, -c Clear specific cache key")
|
||||||
|
print(" --info KEY, -i Show info about cache key")
|
||||||
|
print()
|
||||||
|
print("Examples:")
|
||||||
|
print(" python clear_cache.py --list")
|
||||||
|
print(" python clear_cache.py --clear milb_live_api_data")
|
||||||
|
print(" python clear_cache.py --clear-all")
|
||||||
|
print(" python clear_cache.py --info milb_upcoming_api_data")
|
||||||
|
print()
|
||||||
|
|
||||||
|
# Show current cache status
|
||||||
|
show_cache_info(cache_manager)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
@@ -5,10 +5,10 @@
|
|||||||
"start_time": "07:00",
|
"start_time": "07:00",
|
||||||
"end_time": "23:00"
|
"end_time": "23:00"
|
||||||
},
|
},
|
||||||
"timezone": "America/Chicago",
|
"timezone": "America/New_York",
|
||||||
"location": {
|
"location": {
|
||||||
"city": "Dallas",
|
"city": "Tampa",
|
||||||
"state": "Texas",
|
"state": "Florida",
|
||||||
"country": "US"
|
"country": "US"
|
||||||
},
|
},
|
||||||
"display": {
|
"display": {
|
||||||
@@ -39,6 +39,7 @@
|
|||||||
"daily_forecast": 30,
|
"daily_forecast": 30,
|
||||||
"stock_news": 20,
|
"stock_news": 20,
|
||||||
"odds_ticker": 60,
|
"odds_ticker": 60,
|
||||||
|
"leaderboard": 60,
|
||||||
"nhl_live": 30,
|
"nhl_live": 30,
|
||||||
"nhl_recent": 30,
|
"nhl_recent": 30,
|
||||||
"nhl_upcoming": 30,
|
"nhl_upcoming": 30,
|
||||||
@@ -70,7 +71,8 @@
|
|||||||
"ncaam_basketball_recent": 30,
|
"ncaam_basketball_recent": 30,
|
||||||
"ncaam_basketball_upcoming": 30,
|
"ncaam_basketball_upcoming": 30,
|
||||||
"music": 30,
|
"music": 30,
|
||||||
"of_the_day": 40
|
"of_the_day": 40,
|
||||||
|
"news_manager": 60
|
||||||
},
|
},
|
||||||
"use_short_date_format": true
|
"use_short_date_format": true
|
||||||
},
|
},
|
||||||
@@ -80,71 +82,144 @@
|
|||||||
"update_interval": 1
|
"update_interval": 1
|
||||||
},
|
},
|
||||||
"weather": {
|
"weather": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"update_interval": 1800,
|
"update_interval": 1800,
|
||||||
"units": "imperial",
|
"units": "imperial",
|
||||||
"display_format": "{temp}°F\n{condition}"
|
"display_format": "{temp}\u00b0F\n{condition}"
|
||||||
},
|
},
|
||||||
"stocks": {
|
"stocks": {
|
||||||
"enabled": true,
|
"enabled": false,
|
||||||
"update_interval": 600,
|
"update_interval": 600,
|
||||||
"scroll_speed": 1,
|
"scroll_speed": 1,
|
||||||
"scroll_delay": 0.01,
|
"scroll_delay": 0.01,
|
||||||
"toggle_chart": false,
|
"toggle_chart": true,
|
||||||
|
"dynamic_duration": true,
|
||||||
|
"min_duration": 30,
|
||||||
|
"max_duration": 300,
|
||||||
|
"duration_buffer": 0.1,
|
||||||
"symbols": [
|
"symbols": [
|
||||||
"ASTS", "SCHD", "INTC", "NVDA", "T", "VOO", "SMCI"
|
"ASTS",
|
||||||
|
"SCHD",
|
||||||
|
"INTC",
|
||||||
|
"NVDA",
|
||||||
|
"T",
|
||||||
|
"VOO",
|
||||||
|
"SMCI"
|
||||||
],
|
],
|
||||||
"display_format": "{symbol}: ${price} ({change}%)"
|
"display_format": "{symbol}: ${price} ({change}%)"
|
||||||
},
|
},
|
||||||
"crypto": {
|
"crypto": {
|
||||||
"enabled": true,
|
"enabled": false,
|
||||||
"update_interval": 600,
|
"update_interval": 600,
|
||||||
"symbols": [
|
"symbols": [
|
||||||
"BTC-USD", "ETH-USD"
|
"BTC-USD",
|
||||||
|
"ETH-USD"
|
||||||
],
|
],
|
||||||
"display_format": "{symbol}: ${price} ({change}%)"
|
"display_format": "{symbol}: ${price} ({change}%)"
|
||||||
},
|
},
|
||||||
"stock_news": {
|
"stock_news": {
|
||||||
"enabled": true,
|
"enabled": false,
|
||||||
"update_interval": 3600,
|
"update_interval": 3600,
|
||||||
"scroll_speed": 1,
|
"scroll_speed": 1,
|
||||||
"scroll_delay": 0.01,
|
"scroll_delay": 0.01,
|
||||||
"max_headlines_per_symbol": 1,
|
"max_headlines_per_symbol": 1,
|
||||||
"headlines_per_rotation": 2
|
"headlines_per_rotation": 2,
|
||||||
|
"dynamic_duration": true,
|
||||||
|
"min_duration": 30,
|
||||||
|
"max_duration": 300,
|
||||||
|
"duration_buffer": 0.1
|
||||||
},
|
},
|
||||||
"odds_ticker": {
|
"odds_ticker": {
|
||||||
"enabled": true,
|
"enabled": false,
|
||||||
"show_favorite_teams_only": true,
|
"show_favorite_teams_only": true,
|
||||||
"games_per_favorite_team": 1,
|
"games_per_favorite_team": 1,
|
||||||
"max_games_per_league": 5,
|
"max_games_per_league": 5,
|
||||||
"show_odds_only": false,
|
"show_odds_only": false,
|
||||||
|
"fetch_odds": true,
|
||||||
"sort_order": "soonest",
|
"sort_order": "soonest",
|
||||||
"enabled_leagues": ["nfl","mlb", "ncaa_fb", "milb"],
|
"enabled_leagues": [
|
||||||
|
"nfl",
|
||||||
|
"mlb",
|
||||||
|
"ncaa_fb",
|
||||||
|
"milb"
|
||||||
|
],
|
||||||
"update_interval": 3600,
|
"update_interval": 3600,
|
||||||
"scroll_speed": 1,
|
"scroll_speed": 1,
|
||||||
"scroll_delay": 0.01,
|
"scroll_delay": 0.01,
|
||||||
"loop": true,
|
"loop": true,
|
||||||
"future_fetch_days": 50,
|
"future_fetch_days": 50,
|
||||||
"show_channel_logos": true
|
"show_channel_logos": true,
|
||||||
|
"dynamic_duration": true,
|
||||||
|
"min_duration": 30,
|
||||||
|
"max_duration": 300,
|
||||||
|
"duration_buffer": 0.05
|
||||||
|
},
|
||||||
|
"leaderboard": {
|
||||||
|
"enabled": false,
|
||||||
|
"enabled_sports": {
|
||||||
|
"nfl": {
|
||||||
|
"enabled": true,
|
||||||
|
"top_teams": 10
|
||||||
|
},
|
||||||
|
"nba": {
|
||||||
|
"enabled": false,
|
||||||
|
"top_teams": 10
|
||||||
|
},
|
||||||
|
"mlb": {
|
||||||
|
"enabled": false,
|
||||||
|
"top_teams": 10
|
||||||
|
},
|
||||||
|
"ncaa_fb": {
|
||||||
|
"enabled": true,
|
||||||
|
"top_teams": 25,
|
||||||
|
"show_ranking": true
|
||||||
|
},
|
||||||
|
"nhl": {
|
||||||
|
"enabled": false,
|
||||||
|
"top_teams": 10
|
||||||
|
},
|
||||||
|
"ncaam_basketball": {
|
||||||
|
"enabled": false,
|
||||||
|
"top_teams": 25
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"update_interval": 3600,
|
||||||
|
"scroll_speed": 1,
|
||||||
|
"scroll_delay": 0.01,
|
||||||
|
"display_duration": 60,
|
||||||
|
"loop": false,
|
||||||
|
"request_timeout": 30,
|
||||||
|
"dynamic_duration": true,
|
||||||
|
"min_duration": 45,
|
||||||
|
"max_duration": 600,
|
||||||
|
"duration_buffer": 0.1
|
||||||
},
|
},
|
||||||
"calendar": {
|
"calendar": {
|
||||||
"enabled": true,
|
"enabled": false,
|
||||||
"credentials_file": "credentials.json",
|
"credentials_file": "credentials.json",
|
||||||
"token_file": "token.pickle",
|
"token_file": "token.pickle",
|
||||||
"update_interval": 3600,
|
"update_interval": 3600,
|
||||||
"max_events": 3,
|
"max_events": 3,
|
||||||
"calendars": ["birthdays"]
|
"calendars": [
|
||||||
|
"birthdays"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"nhl_scoreboard": {
|
"nhl_scoreboard": {
|
||||||
"enabled": false,
|
"enabled": false,
|
||||||
|
"live_priority": true,
|
||||||
|
"live_game_duration": 20,
|
||||||
"show_odds": true,
|
"show_odds": true,
|
||||||
"test_mode": false,
|
"test_mode": false,
|
||||||
"update_interval_seconds": 3600,
|
"update_interval_seconds": 3600,
|
||||||
"live_update_interval": 30,
|
"live_update_interval": 30,
|
||||||
"recent_update_interval": 3600,
|
"recent_update_interval": 3600,
|
||||||
"upcoming_update_interval": 3600,
|
"upcoming_update_interval": 3600,
|
||||||
|
"recent_games_to_show": 1,
|
||||||
|
"upcoming_games_to_show": 1,
|
||||||
"show_favorite_teams_only": true,
|
"show_favorite_teams_only": true,
|
||||||
"favorite_teams": ["TB"],
|
"favorite_teams": [
|
||||||
|
"TB"
|
||||||
|
],
|
||||||
"logo_dir": "assets/sports/nhl_logos",
|
"logo_dir": "assets/sports/nhl_logos",
|
||||||
"show_records": true,
|
"show_records": true,
|
||||||
"display_modes": {
|
"display_modes": {
|
||||||
@@ -155,6 +230,8 @@
|
|||||||
},
|
},
|
||||||
"nba_scoreboard": {
|
"nba_scoreboard": {
|
||||||
"enabled": false,
|
"enabled": false,
|
||||||
|
"live_priority": true,
|
||||||
|
"live_game_duration": 20,
|
||||||
"show_odds": true,
|
"show_odds": true,
|
||||||
"test_mode": false,
|
"test_mode": false,
|
||||||
"update_interval_seconds": 3600,
|
"update_interval_seconds": 3600,
|
||||||
@@ -163,9 +240,12 @@
|
|||||||
"odds_update_interval": 3600,
|
"odds_update_interval": 3600,
|
||||||
"recent_update_interval": 3600,
|
"recent_update_interval": 3600,
|
||||||
"upcoming_update_interval": 3600,
|
"upcoming_update_interval": 3600,
|
||||||
"recent_game_hours": 72,
|
"recent_games_to_show": 1,
|
||||||
|
"upcoming_games_to_show": 1,
|
||||||
"show_favorite_teams_only": true,
|
"show_favorite_teams_only": true,
|
||||||
"favorite_teams": ["DAL"],
|
"favorite_teams": [
|
||||||
|
"DAL"
|
||||||
|
],
|
||||||
"logo_dir": "assets/sports/nba_logos",
|
"logo_dir": "assets/sports/nba_logos",
|
||||||
"show_records": true,
|
"show_records": true,
|
||||||
"display_modes": {
|
"display_modes": {
|
||||||
@@ -175,27 +255,34 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nfl_scoreboard": {
|
"nfl_scoreboard": {
|
||||||
"enabled": true,
|
"enabled": false,
|
||||||
|
"live_priority": true,
|
||||||
|
"live_game_duration": 30,
|
||||||
"show_odds": true,
|
"show_odds": true,
|
||||||
"test_mode": false,
|
"test_mode": false,
|
||||||
"update_interval_seconds": 3600,
|
"update_interval_seconds": 3600,
|
||||||
"live_update_interval": 30,
|
"live_update_interval": 30,
|
||||||
"live_odds_update_interval": 3600,
|
"live_odds_update_interval": 3600,
|
||||||
"odds_update_interval": 3600,
|
"odds_update_interval": 3600,
|
||||||
"recent_games_to_show": 0,
|
"recent_games_to_show": 1,
|
||||||
"upcoming_games_to_show": 2,
|
"upcoming_games_to_show": 1,
|
||||||
"show_favorite_teams_only": true,
|
"show_favorite_teams_only": true,
|
||||||
"favorite_teams": ["TB", "DAL"],
|
"favorite_teams": [
|
||||||
|
"TB",
|
||||||
|
"DAL"
|
||||||
|
],
|
||||||
"logo_dir": "assets/sports/nfl_logos",
|
"logo_dir": "assets/sports/nfl_logos",
|
||||||
"show_records": true,
|
"show_records": true,
|
||||||
"display_modes": {
|
"display_modes": {
|
||||||
"nfl_live": true,
|
"nfl_live": true,
|
||||||
"nfl_recent": false,
|
"nfl_recent": true,
|
||||||
"nfl_upcoming": true
|
"nfl_upcoming": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"ncaa_fb_scoreboard": {
|
"ncaa_fb_scoreboard": {
|
||||||
"enabled": true,
|
"enabled": false,
|
||||||
|
"live_priority": true,
|
||||||
|
"live_game_duration": 20,
|
||||||
"show_odds": true,
|
"show_odds": true,
|
||||||
"test_mode": false,
|
"test_mode": false,
|
||||||
"update_interval_seconds": 3600,
|
"update_interval_seconds": 3600,
|
||||||
@@ -203,29 +290,39 @@
|
|||||||
"live_odds_update_interval": 3600,
|
"live_odds_update_interval": 3600,
|
||||||
"odds_update_interval": 3600,
|
"odds_update_interval": 3600,
|
||||||
"season_cache_duration_seconds": 86400,
|
"season_cache_duration_seconds": 86400,
|
||||||
"recent_games_to_show": 0,
|
"recent_games_to_show": 1,
|
||||||
"upcoming_games_to_show": 2,
|
"upcoming_games_to_show": 1,
|
||||||
"show_favorite_teams_only": true,
|
"show_favorite_teams_only": true,
|
||||||
"favorite_teams": ["UGA", "AUB"],
|
"favorite_teams": [
|
||||||
|
"UGA",
|
||||||
|
"AUB"
|
||||||
|
],
|
||||||
"logo_dir": "assets/sports/ncaa_fbs_logos",
|
"logo_dir": "assets/sports/ncaa_fbs_logos",
|
||||||
"show_records": true,
|
"show_records": true,
|
||||||
|
"show_ranking": true,
|
||||||
"display_modes": {
|
"display_modes": {
|
||||||
"ncaa_fb_live": true,
|
"ncaa_fb_live": true,
|
||||||
"ncaa_fb_recent": false,
|
"ncaa_fb_recent": true ,
|
||||||
"ncaa_fb_upcoming": true
|
"ncaa_fb_upcoming": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"ncaa_baseball_scoreboard": {
|
"ncaa_baseball_scoreboard": {
|
||||||
"enabled": false,
|
"enabled": false,
|
||||||
|
"live_priority": true,
|
||||||
|
"live_game_duration": 30,
|
||||||
"show_odds": true,
|
"show_odds": true,
|
||||||
"test_mode": false,
|
"test_mode": false,
|
||||||
"update_interval_seconds": 3600,
|
"update_interval_seconds": 3600,
|
||||||
"live_update_interval": 30,
|
"live_update_interval": 30,
|
||||||
"recent_update_interval": 3600,
|
"recent_update_interval": 3600,
|
||||||
"upcoming_update_interval": 3600,
|
"upcoming_update_interval": 3600,
|
||||||
"recent_game_hours": 72,
|
"recent_games_to_show": 1,
|
||||||
|
"upcoming_games_to_show": 1,
|
||||||
"show_favorite_teams_only": true,
|
"show_favorite_teams_only": true,
|
||||||
"favorite_teams": ["UGA", "AUB"],
|
"favorite_teams": [
|
||||||
|
"UGA",
|
||||||
|
"AUB"
|
||||||
|
],
|
||||||
"logo_dir": "assets/sports/ncaa_fbs_logos",
|
"logo_dir": "assets/sports/ncaa_fbs_logos",
|
||||||
"show_records": true,
|
"show_records": true,
|
||||||
"display_modes": {
|
"display_modes": {
|
||||||
@@ -236,13 +333,19 @@
|
|||||||
},
|
},
|
||||||
"ncaam_basketball_scoreboard": {
|
"ncaam_basketball_scoreboard": {
|
||||||
"enabled": false,
|
"enabled": false,
|
||||||
|
"live_priority": true,
|
||||||
|
"live_game_duration": 20,
|
||||||
"show_odds": true,
|
"show_odds": true,
|
||||||
"test_mode": false,
|
"test_mode": false,
|
||||||
"update_interval_seconds": 3600,
|
"update_interval_seconds": 3600,
|
||||||
"live_update_interval": 30,
|
"live_update_interval": 30,
|
||||||
"recent_game_hours": 72,
|
"recent_games_to_show": 1,
|
||||||
|
"upcoming_games_to_show": 1,
|
||||||
"show_favorite_teams_only": true,
|
"show_favorite_teams_only": true,
|
||||||
"favorite_teams": ["UGA", "AUB"],
|
"favorite_teams": [
|
||||||
|
"UGA",
|
||||||
|
"AUB"
|
||||||
|
],
|
||||||
"logo_dir": "assets/sports/ncaa_fbs_logos",
|
"logo_dir": "assets/sports/ncaa_fbs_logos",
|
||||||
"show_records": true,
|
"show_records": true,
|
||||||
"display_modes": {
|
"display_modes": {
|
||||||
@@ -252,11 +355,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"youtube": {
|
"youtube": {
|
||||||
"enabled": true,
|
"enabled": false,
|
||||||
"update_interval": 3600
|
"update_interval": 3600
|
||||||
},
|
},
|
||||||
"mlb": {
|
"mlb": {
|
||||||
"enabled": true,
|
"enabled": false,
|
||||||
|
"live_priority": false,
|
||||||
|
"live_game_duration": 30,
|
||||||
"show_odds": true,
|
"show_odds": true,
|
||||||
"test_mode": false,
|
"test_mode": false,
|
||||||
"update_interval_seconds": 3600,
|
"update_interval_seconds": 3600,
|
||||||
@@ -268,7 +373,10 @@
|
|||||||
"recent_games_to_show": 1,
|
"recent_games_to_show": 1,
|
||||||
"upcoming_games_to_show": 1,
|
"upcoming_games_to_show": 1,
|
||||||
"show_favorite_teams_only": true,
|
"show_favorite_teams_only": true,
|
||||||
"favorite_teams": ["TB", "TEX"],
|
"favorite_teams": [
|
||||||
|
"TB",
|
||||||
|
"TEX"
|
||||||
|
],
|
||||||
"logo_dir": "assets/sports/mlb_logos",
|
"logo_dir": "assets/sports/mlb_logos",
|
||||||
"show_records": true,
|
"show_records": true,
|
||||||
"display_modes": {
|
"display_modes": {
|
||||||
@@ -278,7 +386,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"milb": {
|
"milb": {
|
||||||
"enabled": true,
|
"enabled": false,
|
||||||
|
"live_priority": false,
|
||||||
|
"live_game_duration": 30,
|
||||||
"test_mode": false,
|
"test_mode": false,
|
||||||
"update_interval_seconds": 3600,
|
"update_interval_seconds": 3600,
|
||||||
"live_update_interval": 30,
|
"live_update_interval": 30,
|
||||||
@@ -286,7 +396,9 @@
|
|||||||
"upcoming_update_interval": 3600,
|
"upcoming_update_interval": 3600,
|
||||||
"recent_games_to_show": 1,
|
"recent_games_to_show": 1,
|
||||||
"upcoming_games_to_show": 1,
|
"upcoming_games_to_show": 1,
|
||||||
"favorite_teams": ["TAM"],
|
"favorite_teams": [
|
||||||
|
"TAM"
|
||||||
|
],
|
||||||
"logo_dir": "assets/sports/milb_logos",
|
"logo_dir": "assets/sports/milb_logos",
|
||||||
"show_records": true,
|
"show_records": true,
|
||||||
"upcoming_fetch_days": 7,
|
"upcoming_fetch_days": 7,
|
||||||
@@ -297,28 +409,43 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"text_display": {
|
"text_display": {
|
||||||
"enabled": false,
|
"enabled": true,
|
||||||
"text": "Subscribe to ChuckBuilds",
|
"text": "Subscribe to ChuckBuilds",
|
||||||
"font_path": "assets/fonts/press-start-2p.ttf",
|
"font_path": "assets/fonts/press-start-2p.ttf",
|
||||||
"font_size": 8,
|
"font_size": 8,
|
||||||
"scroll": true,
|
"scroll": true,
|
||||||
"scroll_speed": 40,
|
"scroll_speed": 40,
|
||||||
"text_color": [255, 0, 0],
|
"text_color": [
|
||||||
"background_color": [0, 0, 0],
|
255,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"background_color": [
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
"scroll_gap_width": 32
|
"scroll_gap_width": 32
|
||||||
},
|
},
|
||||||
"soccer_scoreboard": {
|
"soccer_scoreboard": {
|
||||||
"enabled": false,
|
"enabled": false,
|
||||||
|
"live_priority": true,
|
||||||
|
"live_game_duration": 30,
|
||||||
"show_odds": true,
|
"show_odds": true,
|
||||||
"test_mode": false,
|
"test_mode": false,
|
||||||
"update_interval_seconds": 3600,
|
"update_interval_seconds": 3600,
|
||||||
"live_update_interval": 30,
|
"live_update_interval": 30,
|
||||||
"recent_update_interval": 3600,
|
"recent_update_interval": 3600,
|
||||||
"upcoming_update_interval": 3600,
|
"upcoming_update_interval": 3600,
|
||||||
"recent_game_hours": 168,
|
"recent_games_to_show": 1,
|
||||||
|
"upcoming_games_to_show": 1,
|
||||||
"show_favorite_teams_only": true,
|
"show_favorite_teams_only": true,
|
||||||
"favorite_teams": ["LIV"],
|
"favorite_teams": [
|
||||||
"leagues": ["eng.1", "esp.1", "ger.1", "ita.1", "fra.1", "uefa.champions", "usa.1"],
|
"DAL"
|
||||||
|
],
|
||||||
|
"leagues": [
|
||||||
|
"usa.1"
|
||||||
|
],
|
||||||
"logo_dir": "assets/sports/soccer_logos",
|
"logo_dir": "assets/sports/soccer_logos",
|
||||||
"show_records": true,
|
"show_records": true,
|
||||||
"display_modes": {
|
"display_modes": {
|
||||||
@@ -328,17 +455,20 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"music": {
|
"music": {
|
||||||
"enabled": true,
|
"enabled": false,
|
||||||
"preferred_source": "ytm",
|
"preferred_source": "ytm",
|
||||||
"YTM_COMPANION_URL": "http://192.168.86.12:9863",
|
"YTM_COMPANION_URL": "http://192.168.86.12:9863",
|
||||||
"POLLING_INTERVAL_SECONDS": 1
|
"POLLING_INTERVAL_SECONDS": 1
|
||||||
},
|
},
|
||||||
"of_the_day": {
|
"of_the_day": {
|
||||||
"enabled": true,
|
"enabled": false,
|
||||||
"display_rotate_interval": 20,
|
"display_rotate_interval": 20,
|
||||||
"update_interval": 3600,
|
"update_interval": 3600,
|
||||||
"subtitle_rotate_interval": 10,
|
"subtitle_rotate_interval": 10,
|
||||||
"category_order": ["word_of_the_day", "slovenian_word_of_the_day"],
|
"category_order": [
|
||||||
|
"word_of_the_day",
|
||||||
|
"slovenian_word_of_the_day"
|
||||||
|
],
|
||||||
"categories": {
|
"categories": {
|
||||||
"word_of_the_day": {
|
"word_of_the_day": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
@@ -351,5 +481,40 @@
|
|||||||
"display_name": "Slovenian Word of the Day"
|
"display_name": "Slovenian Word of the Day"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"news_manager": {
|
||||||
|
"enabled": false,
|
||||||
|
"update_interval": 300,
|
||||||
|
"scroll_speed": 1,
|
||||||
|
"scroll_delay": 0.01,
|
||||||
|
"headlines_per_feed": 2,
|
||||||
|
"enabled_feeds": [
|
||||||
|
"NFL",
|
||||||
|
"NCAA FB",
|
||||||
|
"F1",
|
||||||
|
"BBC F1"
|
||||||
|
],
|
||||||
|
"custom_feeds": {
|
||||||
|
"F1": "https://www.espn.com/espn/rss/rpm/news",
|
||||||
|
"BBC F1": "http://feeds.bbci.co.uk/sport/formula1/rss.xml"
|
||||||
|
},
|
||||||
|
"rotation_enabled": true,
|
||||||
|
"rotation_threshold": 3,
|
||||||
|
"dynamic_duration": true,
|
||||||
|
"min_duration": 30,
|
||||||
|
"max_duration": 300,
|
||||||
|
"duration_buffer": 0.1,
|
||||||
|
"font_size": 8,
|
||||||
|
"font_path": "assets/fonts/PressStart2P-Regular.ttf",
|
||||||
|
"text_color": [
|
||||||
|
255,
|
||||||
|
255,
|
||||||
|
255
|
||||||
|
],
|
||||||
|
"separator_color": [
|
||||||
|
255,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
124
configure_web_sudo.sh
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# LED Matrix Web Interface Sudo Configuration Script
|
||||||
|
# This script configures passwordless sudo access for the web interface user
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "Configuring passwordless sudo access for LED Matrix Web Interface..."
|
||||||
|
|
||||||
|
# Get the current user (should be the user running the web interface)
|
||||||
|
WEB_USER=$(whoami)
|
||||||
|
PROJECT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
|
||||||
|
echo "Detected web interface user: $WEB_USER"
|
||||||
|
echo "Project directory: $PROJECT_DIR"
|
||||||
|
|
||||||
|
# Check if running as root
|
||||||
|
if [ "$EUID" -eq 0 ]; then
|
||||||
|
echo "Error: This script should not be run as root."
|
||||||
|
echo "Run it as the user that will be running the web interface."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Get the full paths to commands
|
||||||
|
PYTHON_PATH=$(which python3)
|
||||||
|
SYSTEMCTL_PATH=$(which systemctl)
|
||||||
|
REBOOT_PATH=$(which reboot)
|
||||||
|
POWEROFF_PATH=$(which poweroff)
|
||||||
|
BASH_PATH=$(which bash)
|
||||||
|
|
||||||
|
echo "Command paths:"
|
||||||
|
echo " Python: $PYTHON_PATH"
|
||||||
|
echo " Systemctl: $SYSTEMCTL_PATH"
|
||||||
|
echo " Reboot: $REBOOT_PATH"
|
||||||
|
echo " Poweroff: $POWEROFF_PATH"
|
||||||
|
echo " Bash: $BASH_PATH"
|
||||||
|
|
||||||
|
# Create a temporary sudoers file
|
||||||
|
TEMP_SUDOERS="/tmp/ledmatrix_web_sudoers_$$"
|
||||||
|
|
||||||
|
cat > "$TEMP_SUDOERS" << EOF
|
||||||
|
# LED Matrix Web Interface passwordless sudo configuration
|
||||||
|
# This allows the web interface user to run specific commands without a password
|
||||||
|
|
||||||
|
# Allow $WEB_USER to run specific commands without a password for the LED Matrix web interface
|
||||||
|
$WEB_USER ALL=(ALL) NOPASSWD: $REBOOT_PATH
|
||||||
|
$WEB_USER ALL=(ALL) NOPASSWD: $POWEROFF_PATH
|
||||||
|
$WEB_USER ALL=(ALL) NOPASSWD: $SYSTEMCTL_PATH start ledmatrix.service
|
||||||
|
$WEB_USER ALL=(ALL) NOPASSWD: $SYSTEMCTL_PATH stop ledmatrix.service
|
||||||
|
$WEB_USER ALL=(ALL) NOPASSWD: $SYSTEMCTL_PATH restart ledmatrix.service
|
||||||
|
$WEB_USER ALL=(ALL) NOPASSWD: $SYSTEMCTL_PATH enable ledmatrix.service
|
||||||
|
$WEB_USER ALL=(ALL) NOPASSWD: $SYSTEMCTL_PATH disable ledmatrix.service
|
||||||
|
$WEB_USER ALL=(ALL) NOPASSWD: $SYSTEMCTL_PATH status ledmatrix.service
|
||||||
|
$WEB_USER ALL=(ALL) NOPASSWD: $PYTHON_PATH $PROJECT_DIR/display_controller.py
|
||||||
|
$WEB_USER ALL=(ALL) NOPASSWD: $BASH_PATH $PROJECT_DIR/start_display.sh
|
||||||
|
$WEB_USER ALL=(ALL) NOPASSWD: $BASH_PATH $PROJECT_DIR/stop_display.sh
|
||||||
|
EOF
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Generated sudoers configuration:"
|
||||||
|
echo "--------------------------------"
|
||||||
|
cat "$TEMP_SUDOERS"
|
||||||
|
echo "--------------------------------"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "This configuration will allow the web interface to:"
|
||||||
|
echo "- Start/stop/restart the ledmatrix service"
|
||||||
|
echo "- Enable/disable the ledmatrix service"
|
||||||
|
echo "- Check service status"
|
||||||
|
echo "- Run display_controller.py directly"
|
||||||
|
echo "- Execute start_display.sh and stop_display.sh"
|
||||||
|
echo "- Reboot and shutdown the system"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Ask for confirmation
|
||||||
|
read -p "Do you want to apply this configuration? (y/N): " -n 1 -r
|
||||||
|
echo
|
||||||
|
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||||
|
echo "Configuration cancelled."
|
||||||
|
rm -f "$TEMP_SUDOERS"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Apply the configuration using visudo
|
||||||
|
echo "Applying sudoers configuration..."
|
||||||
|
if sudo cp "$TEMP_SUDOERS" /etc/sudoers.d/ledmatrix_web; then
|
||||||
|
echo "Configuration applied successfully!"
|
||||||
|
echo ""
|
||||||
|
echo "Testing sudo access..."
|
||||||
|
|
||||||
|
# Test a few commands
|
||||||
|
if sudo -n systemctl status ledmatrix.service > /dev/null 2>&1; then
|
||||||
|
echo "✓ systemctl status ledmatrix.service - OK"
|
||||||
|
else
|
||||||
|
echo "✗ systemctl status ledmatrix.service - Failed"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if sudo -n test -f "$PROJECT_DIR/start_display.sh"; then
|
||||||
|
echo "✓ File access test - OK"
|
||||||
|
else
|
||||||
|
echo "✗ File access test - Failed"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Configuration complete! The web interface should now be able to:"
|
||||||
|
echo "- Execute system commands without password prompts"
|
||||||
|
echo "- Start and stop the LED matrix display"
|
||||||
|
echo "- Restart the system if needed"
|
||||||
|
echo ""
|
||||||
|
echo "You may need to restart the web interface service for changes to take effect:"
|
||||||
|
echo " sudo systemctl restart ledmatrix-web.service"
|
||||||
|
|
||||||
|
else
|
||||||
|
echo "Error: Failed to apply sudoers configuration."
|
||||||
|
echo "You may need to run this script with sudo privileges."
|
||||||
|
rm -f "$TEMP_SUDOERS"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Clean up
|
||||||
|
rm -f "$TEMP_SUDOERS"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Configuration script completed successfully!"
|
||||||
1
create_league_logos.py
Normal file
@@ -0,0 +1 @@
|
|||||||
|
|
||||||
1
create_ncaa_logos.py
Normal file
@@ -0,0 +1 @@
|
|||||||
|
|
||||||
107
debug_of_the_day.py
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Debug script for OfTheDayManager issues
|
||||||
|
Run this on the Raspberry Pi to diagnose the problem
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
1. Copy this file to your Raspberry Pi
|
||||||
|
2. Run: python3 debug_of_the_day.py
|
||||||
|
3. Check the output for any errors or issues
|
||||||
|
|
||||||
|
This script will help identify why the OfTheDayManager is not loading data files.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
from datetime import date
|
||||||
|
|
||||||
|
def debug_of_the_day():
|
||||||
|
print("=== OfTheDayManager Debug Script ===")
|
||||||
|
print(f"Current working directory: {os.getcwd()}")
|
||||||
|
print(f"Python path: {sys.path}")
|
||||||
|
|
||||||
|
# Check if we're in the right directory
|
||||||
|
if not os.path.exists('config/config.json'):
|
||||||
|
print("ERROR: config/config.json not found. Make sure you're running from the LEDMatrix root directory.")
|
||||||
|
return
|
||||||
|
|
||||||
|
# Load the actual config
|
||||||
|
try:
|
||||||
|
with open('config/config.json', 'r') as f:
|
||||||
|
config = json.load(f)
|
||||||
|
print("✓ Successfully loaded config.json")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"ERROR loading config.json: {e}")
|
||||||
|
return
|
||||||
|
|
||||||
|
# Check of_the_day configuration
|
||||||
|
of_the_day_config = config.get('of_the_day', {})
|
||||||
|
print(f"OfTheDay enabled: {of_the_day_config.get('enabled', False)}")
|
||||||
|
|
||||||
|
if not of_the_day_config.get('enabled', False):
|
||||||
|
print("OfTheDay is disabled in config!")
|
||||||
|
return
|
||||||
|
|
||||||
|
categories = of_the_day_config.get('categories', {})
|
||||||
|
print(f"Categories configured: {list(categories.keys())}")
|
||||||
|
|
||||||
|
# Test each category
|
||||||
|
today = date.today()
|
||||||
|
day_of_year = today.timetuple().tm_yday
|
||||||
|
print(f"Today is day {day_of_year} of the year")
|
||||||
|
|
||||||
|
for category_name, category_config in categories.items():
|
||||||
|
print(f"\n--- Testing category: {category_name} ---")
|
||||||
|
print(f"Category enabled: {category_config.get('enabled', True)}")
|
||||||
|
|
||||||
|
if not category_config.get('enabled', True):
|
||||||
|
print("Category is disabled, skipping...")
|
||||||
|
continue
|
||||||
|
|
||||||
|
data_file = category_config.get('data_file')
|
||||||
|
print(f"Data file: {data_file}")
|
||||||
|
|
||||||
|
# Test path resolution
|
||||||
|
if not os.path.isabs(data_file):
|
||||||
|
if data_file.startswith('of_the_day/'):
|
||||||
|
file_path = os.path.join(os.getcwd(), data_file)
|
||||||
|
else:
|
||||||
|
file_path = os.path.join(os.getcwd(), 'of_the_day', data_file)
|
||||||
|
else:
|
||||||
|
file_path = data_file
|
||||||
|
|
||||||
|
file_path = os.path.abspath(file_path)
|
||||||
|
print(f"Resolved path: {file_path}")
|
||||||
|
print(f"File exists: {os.path.exists(file_path)}")
|
||||||
|
|
||||||
|
if not os.path.exists(file_path):
|
||||||
|
print(f"ERROR: Data file not found at {file_path}")
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Test JSON loading
|
||||||
|
try:
|
||||||
|
with open(file_path, 'r', encoding='utf-8') as f:
|
||||||
|
data = json.load(f)
|
||||||
|
print(f"✓ Successfully loaded JSON with {len(data)} items")
|
||||||
|
|
||||||
|
# Check for today's entry
|
||||||
|
day_key = str(day_of_year)
|
||||||
|
if day_key in data:
|
||||||
|
item = data[day_key]
|
||||||
|
print(f"✓ Found entry for day {day_of_year}: {item.get('title', 'No title')}")
|
||||||
|
else:
|
||||||
|
print(f"✗ No entry found for day {day_of_year}")
|
||||||
|
# Show some nearby entries
|
||||||
|
nearby_days = [k for k in data.keys() if k.isdigit() and abs(int(k) - day_of_year) <= 5]
|
||||||
|
print(f"Nearby days with entries: {sorted(nearby_days)}")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"ERROR loading JSON: {e}")
|
||||||
|
import traceback
|
||||||
|
traceback.print_exc()
|
||||||
|
|
||||||
|
print("\n=== Debug complete ===")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
debug_of_the_day()
|
||||||
120
enable_news_manager.py
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import json
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
|
||||||
|
def enable_news_manager():
|
||||||
|
"""Enable the news manager in the configuration"""
|
||||||
|
config_path = "config/config.json"
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Load current config
|
||||||
|
with open(config_path, 'r') as f:
|
||||||
|
config = json.load(f)
|
||||||
|
|
||||||
|
# Enable news manager
|
||||||
|
if 'news_manager' not in config:
|
||||||
|
print("News manager configuration not found!")
|
||||||
|
return False
|
||||||
|
|
||||||
|
config['news_manager']['enabled'] = True
|
||||||
|
|
||||||
|
# Save updated config
|
||||||
|
with open(config_path, 'w') as f:
|
||||||
|
json.dump(config, f, indent=4)
|
||||||
|
|
||||||
|
print("SUCCESS: News manager enabled successfully!")
|
||||||
|
print(f"Enabled feeds: {config['news_manager']['enabled_feeds']}")
|
||||||
|
print(f"Headlines per feed: {config['news_manager']['headlines_per_feed']}")
|
||||||
|
print(f"Update interval: {config['news_manager']['update_interval']} seconds")
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"ERROR: Error enabling news manager: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
def disable_news_manager():
|
||||||
|
"""Disable the news manager in the configuration"""
|
||||||
|
config_path = "config/config.json"
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Load current config
|
||||||
|
with open(config_path, 'r') as f:
|
||||||
|
config = json.load(f)
|
||||||
|
|
||||||
|
# Disable news manager
|
||||||
|
if 'news_manager' in config:
|
||||||
|
config['news_manager']['enabled'] = False
|
||||||
|
|
||||||
|
# Save updated config
|
||||||
|
with open(config_path, 'w') as f:
|
||||||
|
json.dump(config, f, indent=4)
|
||||||
|
|
||||||
|
print("SUCCESS: News manager disabled successfully!")
|
||||||
|
else:
|
||||||
|
print("News manager configuration not found!")
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"ERROR: Error disabling news manager: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
def show_status():
|
||||||
|
"""Show current news manager status"""
|
||||||
|
config_path = "config/config.json"
|
||||||
|
|
||||||
|
try:
|
||||||
|
with open(config_path, 'r') as f:
|
||||||
|
config = json.load(f)
|
||||||
|
|
||||||
|
if 'news_manager' not in config:
|
||||||
|
print("News manager configuration not found!")
|
||||||
|
return
|
||||||
|
|
||||||
|
news_config = config['news_manager']
|
||||||
|
|
||||||
|
print("News Manager Status:")
|
||||||
|
print("=" * 30)
|
||||||
|
print(f"Enabled: {news_config.get('enabled', False)}")
|
||||||
|
print(f"Update Interval: {news_config.get('update_interval', 300)} seconds")
|
||||||
|
print(f"Scroll Speed: {news_config.get('scroll_speed', 2)} pixels/frame")
|
||||||
|
print(f"Scroll Delay: {news_config.get('scroll_delay', 0.02)} seconds/frame")
|
||||||
|
print(f"Headlines per Feed: {news_config.get('headlines_per_feed', 2)}")
|
||||||
|
print(f"Enabled Feeds: {news_config.get('enabled_feeds', [])}")
|
||||||
|
print(f"Rotation Enabled: {news_config.get('rotation_enabled', True)}")
|
||||||
|
print(f"Rotation Threshold: {news_config.get('rotation_threshold', 3)}")
|
||||||
|
print(f"Font Size: {news_config.get('font_size', 12)}")
|
||||||
|
|
||||||
|
custom_feeds = news_config.get('custom_feeds', {})
|
||||||
|
if custom_feeds:
|
||||||
|
print("Custom Feeds:")
|
||||||
|
for name, url in custom_feeds.items():
|
||||||
|
print(f" {name}: {url}")
|
||||||
|
else:
|
||||||
|
print("No custom feeds configured")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"ERROR: Error reading configuration: {e}")
|
||||||
|
|
||||||
|
def main():
|
||||||
|
if len(sys.argv) < 2:
|
||||||
|
print("Usage: python3 enable_news_manager.py [enable|disable|status]")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
command = sys.argv[1].lower()
|
||||||
|
|
||||||
|
if command == "enable":
|
||||||
|
enable_news_manager()
|
||||||
|
elif command == "disable":
|
||||||
|
disable_news_manager()
|
||||||
|
elif command == "status":
|
||||||
|
show_status()
|
||||||
|
else:
|
||||||
|
print("Invalid command. Use: enable, disable, or status")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
671
first_time_install.sh
Normal file
@@ -0,0 +1,671 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# LED Matrix First-Time Installation Script
|
||||||
|
# This script handles the complete setup for a new LED Matrix installation
|
||||||
|
|
||||||
|
set -Eeuo pipefail
|
||||||
|
|
||||||
|
# Global state for nicer error messages
|
||||||
|
CURRENT_STEP="initialization"
|
||||||
|
|
||||||
|
# Error handler for friendlier failures
|
||||||
|
on_error() {
|
||||||
|
local exit_code=$?
|
||||||
|
local line_no=${1:-unknown}
|
||||||
|
echo "✗ An error occurred during: $CURRENT_STEP (line $line_no, exit $exit_code)" >&2
|
||||||
|
if [ -n "${LOG_FILE:-}" ]; then
|
||||||
|
echo "See the log for details: $LOG_FILE" >&2
|
||||||
|
echo "-- Last 50 lines from log --" >&2
|
||||||
|
tail -n 50 "$LOG_FILE" >&2 || true
|
||||||
|
fi
|
||||||
|
echo "\nCommon fixes:" >&2
|
||||||
|
echo "- Ensure the Pi is online (try: ping -c1 8.8.8.8)." >&2
|
||||||
|
echo "- If you saw an APT lock error: wait a minute, close other installers, then run: sudo dpkg --configure -a" >&2
|
||||||
|
echo "- Re-run this script. It is safe to run multiple times." >&2
|
||||||
|
exit "$exit_code"
|
||||||
|
}
|
||||||
|
trap 'on_error $LINENO' ERR
|
||||||
|
|
||||||
|
echo "=========================================="
|
||||||
|
echo "LED Matrix First-Time Installation Script"
|
||||||
|
echo "=========================================="
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Show device model if available (helps users confirm they're on a Raspberry Pi)
|
||||||
|
if [ -r /proc/device-tree/model ]; then
|
||||||
|
DEVICE_MODEL=$(tr -d '\0' </proc/device-tree/model)
|
||||||
|
echo "Detected device: $DEVICE_MODEL"
|
||||||
|
else
|
||||||
|
echo "⚠ Could not detect Raspberry Pi model (continuing anyway)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Get the actual user who invoked sudo (set after we ensure sudo below)
|
||||||
|
if [ -n "${SUDO_USER:-}" ]; then
|
||||||
|
ACTUAL_USER="$SUDO_USER"
|
||||||
|
else
|
||||||
|
ACTUAL_USER=$(whoami)
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Get the home directory of the actual user
|
||||||
|
USER_HOME=$(eval echo ~$ACTUAL_USER)
|
||||||
|
|
||||||
|
# Determine the Project Root Directory (where this script is located)
|
||||||
|
PROJECT_ROOT_DIR=$(cd "$(dirname "$0")" && pwd)
|
||||||
|
|
||||||
|
echo "Detected user: $ACTUAL_USER"
|
||||||
|
echo "User home directory: $USER_HOME"
|
||||||
|
echo "Project directory: $PROJECT_ROOT_DIR"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Check if running as root; if not, try to elevate automatically for novices
|
||||||
|
if [ "$EUID" -ne 0 ]; then
|
||||||
|
echo "This script needs administrator privileges. Attempting to re-run with sudo..."
|
||||||
|
exec sudo -E env LEDMATRIX_ELEVATED=1 bash "$0" "$@"
|
||||||
|
fi
|
||||||
|
echo "✓ Running as root (required for installation)"
|
||||||
|
|
||||||
|
# Initialize logging
|
||||||
|
LOG_DIR="$PROJECT_ROOT_DIR/logs"
|
||||||
|
mkdir -p "$LOG_DIR"
|
||||||
|
LOG_FILE="$LOG_DIR/first_time_install_$(date +%Y%m%d_%H%M%S).log"
|
||||||
|
exec > >(tee -a "$LOG_FILE") 2>&1
|
||||||
|
echo "Logging to: $LOG_FILE"
|
||||||
|
|
||||||
|
# Args and options (novice-friendly defaults)
|
||||||
|
ASSUME_YES=${LEDMATRIX_ASSUME_YES:-0}
|
||||||
|
SKIP_SOUND=${LEDMATRIX_SKIP_SOUND:-0}
|
||||||
|
SKIP_PERF=${LEDMATRIX_SKIP_PERF:-0}
|
||||||
|
SKIP_REBOOT_PROMPT=${LEDMATRIX_SKIP_REBOOT_PROMPT:-0}
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
cat <<USAGE
|
||||||
|
Usage: sudo ./first_time_install.sh [options]
|
||||||
|
|
||||||
|
Options:
|
||||||
|
-y, --yes Proceed without interactive confirmations
|
||||||
|
--force-rebuild Force rebuild of rpi-rgb-led-matrix even if present
|
||||||
|
--skip-sound Skip sound module configuration
|
||||||
|
--skip-perf Skip performance tweaks (isolcpus/audio)
|
||||||
|
--no-reboot-prompt Do not prompt for reboot at the end
|
||||||
|
-h, --help Show this help message and exit
|
||||||
|
|
||||||
|
Environment variables (same effect as flags):
|
||||||
|
LEDMATRIX_ASSUME_YES=1, RPI_RGB_FORCE_REBUILD=1, LEDMATRIX_SKIP_SOUND=1,
|
||||||
|
LEDMATRIX_SKIP_PERF=1, LEDMATRIX_SKIP_REBOOT_PROMPT=1
|
||||||
|
USAGE
|
||||||
|
}
|
||||||
|
|
||||||
|
while [ $# -gt 0 ]; do
|
||||||
|
case "$1" in
|
||||||
|
-y|--yes) ASSUME_YES=1 ;;
|
||||||
|
--force-rebuild) RPI_RGB_FORCE_REBUILD=1 ;;
|
||||||
|
--skip-sound) SKIP_SOUND=1 ;;
|
||||||
|
--skip-perf) SKIP_PERF=1 ;;
|
||||||
|
--no-reboot-prompt) SKIP_REBOOT_PROMPT=1 ;;
|
||||||
|
-h|--help) usage; exit 0 ;;
|
||||||
|
*) echo "Unknown option: $1"; usage; exit 1 ;;
|
||||||
|
esac
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
|
||||||
|
# Helpers
|
||||||
|
retry() {
|
||||||
|
local attempt=1
|
||||||
|
local max_attempts=3
|
||||||
|
local delay_seconds=5
|
||||||
|
while true; do
|
||||||
|
"$@" && return 0
|
||||||
|
local status=$?
|
||||||
|
if [ $attempt -ge $max_attempts ]; then
|
||||||
|
echo "✗ Command failed after $attempt attempts: $*"
|
||||||
|
return $status
|
||||||
|
fi
|
||||||
|
echo "⚠ Command failed (attempt $attempt/$max_attempts). Retrying in ${delay_seconds}s: $*"
|
||||||
|
attempt=$((attempt+1))
|
||||||
|
sleep "$delay_seconds"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
apt_update() { retry apt update; }
|
||||||
|
apt_install() { retry apt install -y "$@"; }
|
||||||
|
apt_remove() { apt-get remove -y "$@" || true; }
|
||||||
|
|
||||||
|
check_network() {
|
||||||
|
if command -v ping >/dev/null 2>&1; then
|
||||||
|
if ping -c 1 -W 3 8.8.8.8 >/dev/null 2>&1; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if command -v curl >/dev/null 2>&1; then
|
||||||
|
if curl -Is --max-time 5 http://deb.debian.org >/dev/null 2>&1; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
echo "✗ No internet connectivity detected."
|
||||||
|
echo "Please connect your Raspberry Pi to the internet and re-run this script."
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "This script will perform the following steps:"
|
||||||
|
echo "1. Install system dependencies"
|
||||||
|
echo "2. Fix cache permissions"
|
||||||
|
echo "3. Install main LED Matrix service"
|
||||||
|
echo "4. Install Python project dependencies (requirements.txt)"
|
||||||
|
echo "5. Build and install rpi-rgb-led-matrix and test import"
|
||||||
|
echo "6. Install web interface dependencies"
|
||||||
|
echo "7. Install web interface service"
|
||||||
|
echo "8. Configure web interface permissions"
|
||||||
|
echo "9. Configure passwordless sudo access"
|
||||||
|
echo "10. Set up proper file ownership"
|
||||||
|
echo "11. Configure sound module to avoid conflicts"
|
||||||
|
echo "12. Apply performance optimizations"
|
||||||
|
echo "13. Test the installation"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Ask for confirmation
|
||||||
|
if [ "$ASSUME_YES" = "1" ]; then
|
||||||
|
echo "Non-interactive mode: proceeding with installation."
|
||||||
|
else
|
||||||
|
read -p "Do you want to proceed with the installation? (y/N): " -n 1 -r
|
||||||
|
echo
|
||||||
|
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||||
|
echo "Installation cancelled."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
CLEAR='
|
||||||
|
'
|
||||||
|
CURRENT_STEP="Install system dependencies"
|
||||||
|
echo "Step 1: Installing system dependencies..."
|
||||||
|
echo "----------------------------------------"
|
||||||
|
|
||||||
|
# Ensure network is available before APT operations
|
||||||
|
check_network
|
||||||
|
|
||||||
|
# Update package list
|
||||||
|
apt_update
|
||||||
|
|
||||||
|
# Install required system packages
|
||||||
|
echo "Installing Python packages and dependencies..."
|
||||||
|
apt_install python3-pip python3-venv python3-dev python3-pil python3-pil.imagetk build-essential python3-setuptools python3-wheel cython3
|
||||||
|
|
||||||
|
# Install additional system dependencies that might be needed
|
||||||
|
echo "Installing additional system dependencies..."
|
||||||
|
apt_install git curl wget unzip
|
||||||
|
|
||||||
|
echo "✓ System dependencies installed"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
CURRENT_STEP="Fix cache permissions"
|
||||||
|
echo "Step 2: Fixing cache permissions..."
|
||||||
|
echo "----------------------------------"
|
||||||
|
|
||||||
|
# Run the cache permissions fix
|
||||||
|
if [ -f "$PROJECT_ROOT_DIR/fix_cache_permissions.sh" ]; then
|
||||||
|
echo "Running cache permissions fix..."
|
||||||
|
bash "$PROJECT_ROOT_DIR/fix_cache_permissions.sh"
|
||||||
|
echo "✓ Cache permissions fixed"
|
||||||
|
else
|
||||||
|
echo "⚠ Cache permissions script not found, creating cache directories manually..."
|
||||||
|
mkdir -p /var/cache/ledmatrix
|
||||||
|
chown "$ACTUAL_USER:$ACTUAL_USER" /var/cache/ledmatrix
|
||||||
|
chmod 777 /var/cache/ledmatrix
|
||||||
|
echo "✓ Cache directories created manually"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
CURRENT_STEP="Install main LED Matrix service"
|
||||||
|
echo "Step 3: Installing main LED Matrix service..."
|
||||||
|
echo "---------------------------------------------"
|
||||||
|
|
||||||
|
# Run the main service installation (idempotent)
|
||||||
|
if [ -f "$PROJECT_ROOT_DIR/install_service.sh" ]; then
|
||||||
|
echo "Running main service installation..."
|
||||||
|
bash "$PROJECT_ROOT_DIR/install_service.sh"
|
||||||
|
echo "✓ Main LED Matrix service installed"
|
||||||
|
else
|
||||||
|
echo "✗ Main service installation script not found at $PROJECT_ROOT_DIR/install_service.sh"
|
||||||
|
echo "Please ensure you are running this script from the project root: $PROJECT_ROOT_DIR"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
CURRENT_STEP="Ensure secrets configuration exists"
|
||||||
|
echo "Step 3.1: Ensuring secrets configuration exists..."
|
||||||
|
echo "-----------------------------------------------"
|
||||||
|
|
||||||
|
# Ensure config directory exists
|
||||||
|
mkdir -p "$PROJECT_ROOT_DIR/config"
|
||||||
|
chmod 755 "$PROJECT_ROOT_DIR/config" || true
|
||||||
|
|
||||||
|
# Create config_secrets.json from template if missing
|
||||||
|
if [ ! -f "$PROJECT_ROOT_DIR/config/config_secrets.json" ]; then
|
||||||
|
if [ -f "$PROJECT_ROOT_DIR/config/config_secrets.template.json" ]; then
|
||||||
|
echo "Creating config/config_secrets.json from template..."
|
||||||
|
cp "$PROJECT_ROOT_DIR/config/config_secrets.template.json" "$PROJECT_ROOT_DIR/config/config_secrets.json"
|
||||||
|
chown "$ACTUAL_USER:$ACTUAL_USER" "$PROJECT_ROOT_DIR/config/config_secrets.json" || true
|
||||||
|
chmod 640 "$PROJECT_ROOT_DIR/config/config_secrets.json"
|
||||||
|
echo "✓ Secrets file created from template"
|
||||||
|
else
|
||||||
|
echo "⚠ Template config/config_secrets.template.json not found; creating a minimal secrets file"
|
||||||
|
cat > "$PROJECT_ROOT_DIR/config/config_secrets.json" <<'EOF'
|
||||||
|
{
|
||||||
|
"weather": {
|
||||||
|
"api_key": "YOUR_OPENWEATHERMAP_API_KEY"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
chown "$ACTUAL_USER:$ACTUAL_USER" "$PROJECT_ROOT_DIR/config/config_secrets.json" || true
|
||||||
|
chmod 640 "$PROJECT_ROOT_DIR/config/config_secrets.json"
|
||||||
|
echo "✓ Minimal secrets file created"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "Secrets file already exists; leaving as-is"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
CURRENT_STEP="Install project Python dependencies"
|
||||||
|
echo "Step 4: Installing Python project dependencies..."
|
||||||
|
echo "-----------------------------------------------"
|
||||||
|
|
||||||
|
# Install main project Python dependencies
|
||||||
|
cd "$PROJECT_ROOT_DIR"
|
||||||
|
if [ -f "$PROJECT_ROOT_DIR/requirements.txt" ]; then
|
||||||
|
python3 -m pip install --break-system-packages -r "$PROJECT_ROOT_DIR/requirements.txt"
|
||||||
|
else
|
||||||
|
echo "⚠ requirements.txt not found; skipping main dependency install"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "✓ Project Python dependencies installed"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
CURRENT_STEP="Build and install rpi-rgb-led-matrix"
|
||||||
|
echo "Step 5: Building and installing rpi-rgb-led-matrix..."
|
||||||
|
echo "-----------------------------------------------------"
|
||||||
|
|
||||||
|
# If already installed and not forcing rebuild, skip expensive build
|
||||||
|
if python3 -c 'from rgbmatrix import RGBMatrix, RGBMatrixOptions' >/dev/null 2>&1 && [ "${RPI_RGB_FORCE_REBUILD:-0}" != "1" ]; then
|
||||||
|
echo "rgbmatrix Python package already available; skipping build (set RPI_RGB_FORCE_REBUILD=1 to force rebuild)."
|
||||||
|
else
|
||||||
|
# Build and install rpi-rgb-led-matrix Python bindings
|
||||||
|
if [ -d "$PROJECT_ROOT_DIR/rpi-rgb-led-matrix-master" ]; then
|
||||||
|
pushd "$PROJECT_ROOT_DIR/rpi-rgb-led-matrix-master" >/dev/null
|
||||||
|
echo "Building rpi-rgb-led-matrix Python bindings..."
|
||||||
|
make build-python PYTHON=$(which python3)
|
||||||
|
cd bindings/python
|
||||||
|
echo "Installing rpi-rgb-led-matrix Python package via pip..."
|
||||||
|
python3 -m pip install --break-system-packages .
|
||||||
|
popd >/dev/null
|
||||||
|
else
|
||||||
|
echo "✗ rpi-rgb-led-matrix-master directory not found at $PROJECT_ROOT_DIR"
|
||||||
|
echo "You can clone it with: git submodule update --init --recursive (if applicable)"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Running rgbmatrix import test..."
|
||||||
|
if python3 - <<'PY'
|
||||||
|
from importlib.metadata import version, PackageNotFoundError
|
||||||
|
try:
|
||||||
|
from rgbmatrix import RGBMatrix, RGBMatrixOptions
|
||||||
|
try:
|
||||||
|
print("Success! rgbmatrix version:", version('rgbmatrix'))
|
||||||
|
except PackageNotFoundError:
|
||||||
|
print("Success! rgbmatrix installed (version unknown)")
|
||||||
|
except Exception as e:
|
||||||
|
raise SystemExit(f"rgbmatrix import failed: {e}")
|
||||||
|
PY
|
||||||
|
then
|
||||||
|
echo "✓ rpi-rgb-led-matrix installed and verified"
|
||||||
|
else
|
||||||
|
echo "✗ rpi-rgb-led-matrix import test failed"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
CURRENT_STEP="Install web interface dependencies"
|
||||||
|
echo "Step 6: Installing web interface dependencies..."
|
||||||
|
echo "------------------------------------------------"
|
||||||
|
|
||||||
|
# Install web interface dependencies
|
||||||
|
echo "Installing Python dependencies for web interface..."
|
||||||
|
cd "$PROJECT_ROOT_DIR"
|
||||||
|
|
||||||
|
# Try to install dependencies using the smart installer if available
|
||||||
|
if [ -f "$PROJECT_ROOT_DIR/install_dependencies_apt.py" ]; then
|
||||||
|
echo "Using smart dependency installer..."
|
||||||
|
python3 "$PROJECT_ROOT_DIR/install_dependencies_apt.py"
|
||||||
|
else
|
||||||
|
echo "Using pip to install dependencies..."
|
||||||
|
if [ -f "$PROJECT_ROOT_DIR/requirements_web_v2.txt" ]; then
|
||||||
|
python3 -m pip install --break-system-packages -r requirements_web_v2.txt
|
||||||
|
else
|
||||||
|
echo "⚠ requirements_web_v2.txt not found; skipping web dependency install"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "✓ Web interface dependencies installed"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
CURRENT_STEP="Install web interface service"
|
||||||
|
echo "Step 7: Installing web interface service..."
|
||||||
|
echo "-------------------------------------------"
|
||||||
|
|
||||||
|
if [ -f "$PROJECT_ROOT_DIR/install_web_service.sh" ]; then
|
||||||
|
if [ ! -f "/etc/systemd/system/ledmatrix-web.service" ]; then
|
||||||
|
bash "$PROJECT_ROOT_DIR/install_web_service.sh"
|
||||||
|
# Ensure systemd sees any new/changed unit files
|
||||||
|
systemctl daemon-reload || true
|
||||||
|
echo "✓ Web interface service installed"
|
||||||
|
else
|
||||||
|
echo "ledmatrix-web.service already present; preserving existing configuration and skipping static installer"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "⚠ install_web_service.sh not found; skipping web service installation"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
CURRENT_STEP="Harden systemd unit file permissions"
|
||||||
|
echo "Step 7.1: Setting systemd unit file permissions..."
|
||||||
|
echo "-----------------------------------------------"
|
||||||
|
for unit in "/etc/systemd/system/ledmatrix.service" "/etc/systemd/system/ledmatrix-web.service"; do
|
||||||
|
if [ -f "$unit" ]; then
|
||||||
|
chown root:root "$unit" || true
|
||||||
|
chmod 644 "$unit" || true
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
systemctl daemon-reload || true
|
||||||
|
echo "✓ Systemd unit file permissions set"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
CURRENT_STEP="Configure web interface permissions"
|
||||||
|
echo "Step 8: Configuring web interface permissions..."
|
||||||
|
echo "------------------------------------------------"
|
||||||
|
|
||||||
|
# Add user to required groups (idempotent)
|
||||||
|
echo "Adding user to systemd-journal group..."
|
||||||
|
if id -nG "$ACTUAL_USER" | grep -qw systemd-journal; then
|
||||||
|
echo "User $ACTUAL_USER already in systemd-journal"
|
||||||
|
else
|
||||||
|
usermod -a -G systemd-journal "$ACTUAL_USER"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Adding user to adm group..."
|
||||||
|
if id -nG "$ACTUAL_USER" | grep -qw adm; then
|
||||||
|
echo "User $ACTUAL_USER already in adm"
|
||||||
|
else
|
||||||
|
usermod -a -G adm "$ACTUAL_USER"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "✓ User added to required groups"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
CURRENT_STEP="Configure passwordless sudo access"
|
||||||
|
echo "Step 9: Configuring passwordless sudo access..."
|
||||||
|
echo "------------------------------------------------"
|
||||||
|
|
||||||
|
# Create sudoers configuration for the web interface
|
||||||
|
echo "Creating sudoers configuration..."
|
||||||
|
SUDOERS_FILE="/etc/sudoers.d/ledmatrix_web"
|
||||||
|
|
||||||
|
# Get command paths
|
||||||
|
PYTHON_PATH=$(which python3)
|
||||||
|
SYSTEMCTL_PATH=$(which systemctl)
|
||||||
|
REBOOT_PATH=$(which reboot)
|
||||||
|
POWEROFF_PATH=$(which poweroff)
|
||||||
|
BASH_PATH=$(which bash)
|
||||||
|
|
||||||
|
# Create sudoers content
|
||||||
|
cat > /tmp/ledmatrix_web_sudoers << EOF
|
||||||
|
# LED Matrix Web Interface passwordless sudo configuration
|
||||||
|
# This allows the web interface user to run specific commands without a password
|
||||||
|
|
||||||
|
# Allow $ACTUAL_USER to run specific commands without a password for the LED Matrix web interface
|
||||||
|
$ACTUAL_USER ALL=(ALL) NOPASSWD: $REBOOT_PATH
|
||||||
|
$ACTUAL_USER ALL=(ALL) NOPASSWD: $POWEROFF_PATH
|
||||||
|
$ACTUAL_USER ALL=(ALL) NOPASSWD: $SYSTEMCTL_PATH start ledmatrix.service
|
||||||
|
$ACTUAL_USER ALL=(ALL) NOPASSWD: $SYSTEMCTL_PATH stop ledmatrix.service
|
||||||
|
$ACTUAL_USER ALL=(ALL) NOPASSWD: $SYSTEMCTL_PATH restart ledmatrix.service
|
||||||
|
$ACTUAL_USER ALL=(ALL) NOPASSWD: $SYSTEMCTL_PATH enable ledmatrix.service
|
||||||
|
$ACTUAL_USER ALL=(ALL) NOPASSWD: $SYSTEMCTL_PATH disable ledmatrix.service
|
||||||
|
$ACTUAL_USER ALL=(ALL) NOPASSWD: $SYSTEMCTL_PATH status ledmatrix.service
|
||||||
|
$ACTUAL_USER ALL=(ALL) NOPASSWD: $PYTHON_PATH $PROJECT_ROOT_DIR/display_controller.py
|
||||||
|
$ACTUAL_USER ALL=(ALL) NOPASSWD: $BASH_PATH $PROJECT_ROOT_DIR/start_display.sh
|
||||||
|
$ACTUAL_USER ALL=(ALL) NOPASSWD: $BASH_PATH $PROJECT_ROOT_DIR/stop_display.sh
|
||||||
|
EOF
|
||||||
|
|
||||||
|
if [ -f "$SUDOERS_FILE" ] && cmp -s /tmp/ledmatrix_web_sudoers "$SUDOERS_FILE"; then
|
||||||
|
echo "Sudoers configuration already up to date"
|
||||||
|
rm /tmp/ledmatrix_web_sudoers
|
||||||
|
else
|
||||||
|
echo "Installing/updating sudoers configuration..."
|
||||||
|
cp /tmp/ledmatrix_web_sudoers "$SUDOERS_FILE"
|
||||||
|
chmod 440 "$SUDOERS_FILE"
|
||||||
|
rm /tmp/ledmatrix_web_sudoers
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "✓ Passwordless sudo access configured"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
CURRENT_STEP="Set proper file ownership"
|
||||||
|
echo "Step 10: Setting proper file ownership..."
|
||||||
|
echo "----------------------------------------"
|
||||||
|
|
||||||
|
# Set ownership of project files to the user
|
||||||
|
echo "Setting project file ownership..."
|
||||||
|
chown -R "$ACTUAL_USER:$ACTUAL_USER" "$PROJECT_ROOT_DIR"
|
||||||
|
|
||||||
|
# Set proper permissions for config files
|
||||||
|
if [ -f "$PROJECT_ROOT_DIR/config/config.json" ]; then
|
||||||
|
chmod 644 "$PROJECT_ROOT_DIR/config/config.json"
|
||||||
|
echo "✓ Config file permissions set"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Set proper permissions for secrets file (restrictive: owner rw, group r)
|
||||||
|
if [ -f "$PROJECT_ROOT_DIR/config/config_secrets.json" ]; then
|
||||||
|
chown "$ACTUAL_USER:$ACTUAL_USER" "$PROJECT_ROOT_DIR/config/config_secrets.json" || true
|
||||||
|
chmod 640 "$PROJECT_ROOT_DIR/config/config_secrets.json"
|
||||||
|
echo "✓ Secrets file permissions set"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "✓ File ownership configured"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
CURRENT_STEP="Normalize project file permissions"
|
||||||
|
echo "Step 10.1: Normalizing project file and directory permissions..."
|
||||||
|
echo "--------------------------------------------------------------"
|
||||||
|
|
||||||
|
# Normalize directory permissions (exclude VCS metadata)
|
||||||
|
find "$PROJECT_ROOT_DIR" -path "*/.git*" -prune -o -type d -exec chmod 755 {} +
|
||||||
|
|
||||||
|
# Set default file permissions
|
||||||
|
find "$PROJECT_ROOT_DIR" -path "*/.git*" -prune -o -type f -exec chmod 644 {} +
|
||||||
|
|
||||||
|
# Ensure shell scripts are executable
|
||||||
|
find "$PROJECT_ROOT_DIR" -path "*/.git*" -prune -o -type f -name "*.sh" -exec chmod 755 {} +
|
||||||
|
|
||||||
|
# Explicitly ensure common helper scripts are executable (in case paths change)
|
||||||
|
chmod 755 "$PROJECT_ROOT_DIR/start_display.sh" "$PROJECT_ROOT_DIR/stop_display.sh" 2>/dev/null || true
|
||||||
|
chmod 755 "$PROJECT_ROOT_DIR/fix_cache_permissions.sh" "$PROJECT_ROOT_DIR/fix_web_permissions.sh" 2>/dev/null || true
|
||||||
|
chmod 755 "$PROJECT_ROOT_DIR/install_service.sh" "$PROJECT_ROOT_DIR/install_web_service.sh" 2>/dev/null || true
|
||||||
|
|
||||||
|
echo "✓ Project file permissions normalized"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
CURRENT_STEP="Sound module configuration"
|
||||||
|
echo "Step 11: Sound module configuration..."
|
||||||
|
echo "-------------------------------------"
|
||||||
|
|
||||||
|
# Remove services that may interfere with LED matrix timing
|
||||||
|
echo "Removing potential conflicting services (bluetooth and others)..."
|
||||||
|
if [ "$SKIP_SOUND" = "1" ]; then
|
||||||
|
echo "Skipping sound module configuration as requested (--skip-sound)."
|
||||||
|
elif apt_remove bluez bluez-firmware pi-bluetooth triggerhappy pigpio; then
|
||||||
|
echo "✓ Unnecessary services removed (or not present)"
|
||||||
|
else
|
||||||
|
echo "⚠ Some packages could not be removed; continuing"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Blacklist onboard sound module (idempotent)
|
||||||
|
BLACKLIST_FILE="/etc/modprobe.d/blacklist-rgb-matrix.conf"
|
||||||
|
if [ -f "$BLACKLIST_FILE" ] && grep -q '^blacklist snd_bcm2835\b' "$BLACKLIST_FILE"; then
|
||||||
|
echo "snd_bcm2835 already blacklisted in $BLACKLIST_FILE"
|
||||||
|
else
|
||||||
|
echo "Ensuring snd_bcm2835 is blacklisted in $BLACKLIST_FILE..."
|
||||||
|
mkdir -p "/etc/modprobe.d"
|
||||||
|
if [ -f "$BLACKLIST_FILE" ]; then
|
||||||
|
cp "$BLACKLIST_FILE" "$BLACKLIST_FILE.bak" 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
# Append once (don't clobber existing unrelated content)
|
||||||
|
if [ -f "$BLACKLIST_FILE" ]; then
|
||||||
|
echo "blacklist snd_bcm2835" >> "$BLACKLIST_FILE"
|
||||||
|
else
|
||||||
|
printf "blacklist snd_bcm2835\n" > "$BLACKLIST_FILE"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Update initramfs if available
|
||||||
|
if command -v update-initramfs >/dev/null 2>&1; then
|
||||||
|
echo "Updating initramfs..."
|
||||||
|
update-initramfs -u
|
||||||
|
else
|
||||||
|
echo "update-initramfs not found; skipping"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "✓ Sound module configuration applied"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
CURRENT_STEP="Apply performance optimizations"
|
||||||
|
echo "Step 12: Applying performance optimizations..."
|
||||||
|
echo "---------------------------------------------"
|
||||||
|
|
||||||
|
# Prefer /boot/firmware on newer Raspberry Pi OS, fall back to /boot on older
|
||||||
|
CMDLINE_FILE="/boot/firmware/cmdline.txt"
|
||||||
|
CONFIG_FILE="/boot/firmware/config.txt"
|
||||||
|
if [ ! -f "$CMDLINE_FILE" ]; then CMDLINE_FILE="/boot/cmdline.txt"; fi
|
||||||
|
if [ ! -f "$CONFIG_FILE" ]; then CONFIG_FILE="/boot/config.txt"; fi
|
||||||
|
|
||||||
|
# Append isolcpus=3 to cmdline if not present (idempotent)
|
||||||
|
if [ "$SKIP_PERF" = "1" ]; then
|
||||||
|
echo "Skipping performance optimizations as requested (--skip-perf)."
|
||||||
|
elif [ -f "$CMDLINE_FILE" ]; then
|
||||||
|
if grep -q '\bisolcpus=3\b' "$CMDLINE_FILE"; then
|
||||||
|
echo "isolcpus=3 already present in $CMDLINE_FILE"
|
||||||
|
else
|
||||||
|
echo "Adding isolcpus=3 to $CMDLINE_FILE..."
|
||||||
|
cp "$CMDLINE_FILE" "$CMDLINE_FILE.bak" 2>/dev/null || true
|
||||||
|
# Ensure single-line cmdline gets the flag once, with a leading space
|
||||||
|
sed -i '1 s/$/ isolcpus=3/' "$CMDLINE_FILE"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "✗ $CMDLINE_FILE not found; skipping isolcpus optimization"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Ensure dtparam=audio=off in config.txt (idempotent)
|
||||||
|
if [ "$SKIP_PERF" = "1" ]; then
|
||||||
|
: # skipped
|
||||||
|
elif [ -f "$CONFIG_FILE" ]; then
|
||||||
|
if grep -q '^dtparam=audio=off\b' "$CONFIG_FILE"; then
|
||||||
|
echo "Onboard audio already disabled in $CONFIG_FILE"
|
||||||
|
elif grep -q '^dtparam=audio=on\b' "$CONFIG_FILE"; then
|
||||||
|
echo "Disabling onboard audio in $CONFIG_FILE..."
|
||||||
|
cp "$CONFIG_FILE" "$CONFIG_FILE.bak" 2>/dev/null || true
|
||||||
|
sed -i 's/^dtparam=audio=on\b/dtparam=audio=off/' "$CONFIG_FILE"
|
||||||
|
else
|
||||||
|
echo "Adding dtparam=audio=off to $CONFIG_FILE..."
|
||||||
|
cp "$CONFIG_FILE" "$CONFIG_FILE.bak" 2>/dev/null || true
|
||||||
|
printf "\n# Disable onboard audio for LED matrix performance\n" >> "$CONFIG_FILE"
|
||||||
|
echo "dtparam=audio=off" >> "$CONFIG_FILE"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "✗ $CONFIG_FILE not found; skipping audio disable"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "✓ Performance optimizations applied"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
CURRENT_STEP="Test the installation"
|
||||||
|
echo "Step 13: Testing the installation..."
|
||||||
|
echo "----------------------------------"
|
||||||
|
|
||||||
|
# Test sudo access
|
||||||
|
echo "Testing sudo access..."
|
||||||
|
if sudo -u "$ACTUAL_USER" sudo -n systemctl status ledmatrix.service > /dev/null 2>&1; then
|
||||||
|
echo "✓ Sudo access test passed"
|
||||||
|
else
|
||||||
|
echo "⚠ Sudo access test failed - may need to log out and back in"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Test journal access
|
||||||
|
echo "Testing journal access..."
|
||||||
|
if sudo -u "$ACTUAL_USER" journalctl --no-pager --lines=1 > /dev/null 2>&1; then
|
||||||
|
echo "✓ Journal access test passed"
|
||||||
|
else
|
||||||
|
echo "⚠ Journal access test failed - may need to log out and back in"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check service status
|
||||||
|
echo "Checking service status..."
|
||||||
|
if systemctl is-active --quiet ledmatrix.service; then
|
||||||
|
echo "✓ Main LED Matrix service is running"
|
||||||
|
else
|
||||||
|
echo "⚠ Main LED Matrix service is not running"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if systemctl is-active --quiet ledmatrix-web.service; then
|
||||||
|
echo "✓ Web interface service is running"
|
||||||
|
else
|
||||||
|
echo "⚠ Web interface service is not running"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
if [ "$SKIP_REBOOT_PROMPT" = "1" ]; then
|
||||||
|
echo "Skipping reboot prompt as requested (--no-reboot-prompt)."
|
||||||
|
elif [ "$ASSUME_YES" = "1" ]; then
|
||||||
|
echo "Non-interactive mode: rebooting now to apply changes..."
|
||||||
|
reboot
|
||||||
|
else
|
||||||
|
read -p "A reboot is recommended to apply kernel and audio changes. Reboot now? (y/N): " -n 1 -r
|
||||||
|
echo
|
||||||
|
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||||
|
echo "Rebooting now..."
|
||||||
|
reboot
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "=========================================="
|
||||||
|
echo "Installation Complete!"
|
||||||
|
echo "=========================================="
|
||||||
|
echo ""
|
||||||
|
echo "IMPORTANT: For group changes to take effect, you need to:"
|
||||||
|
echo "1. Log out and log back in to your SSH session, OR"
|
||||||
|
echo "2. Run: newgrp systemd-journal"
|
||||||
|
echo ""
|
||||||
|
echo "After logging back in, you can:"
|
||||||
|
echo ""
|
||||||
|
echo "Access the web interface at:"
|
||||||
|
echo " http://your-pi-ip:5001"
|
||||||
|
echo ""
|
||||||
|
echo "Check service status:"
|
||||||
|
echo " sudo systemctl status ledmatrix.service"
|
||||||
|
echo " sudo systemctl status ledmatrix-web.service"
|
||||||
|
echo ""
|
||||||
|
echo "View logs:"
|
||||||
|
echo " journalctl -u ledmatrix.service -f"
|
||||||
|
echo " journalctl -u ledmatrix-web.service -f"
|
||||||
|
echo ""
|
||||||
|
echo "Control the display:"
|
||||||
|
echo " sudo systemctl start ledmatrix.service"
|
||||||
|
echo " sudo systemctl stop ledmatrix.service"
|
||||||
|
echo ""
|
||||||
|
echo "Enable/disable web interface autostart:"
|
||||||
|
echo " Edit config/config.json and set 'web_display_autostart': true"
|
||||||
|
echo ""
|
||||||
|
echo "Configuration files:"
|
||||||
|
echo " Main config: config/config.json"
|
||||||
|
echo " Secrets: config/config_secrets.json (create from template if needed)"
|
||||||
|
echo ""
|
||||||
|
echo "Enjoy your LED Matrix display!"
|
||||||
@@ -2,28 +2,37 @@
|
|||||||
|
|
||||||
# LEDMatrix Cache Permissions Fix Script
|
# LEDMatrix Cache Permissions Fix Script
|
||||||
# This script fixes permissions on all known cache directories so they're writable by the daemon or current user
|
# This script fixes permissions on all known cache directories so they're writable by the daemon or current user
|
||||||
|
# Also sets up placeholder logo directories for sports managers
|
||||||
|
|
||||||
echo "Fixing LEDMatrix cache directory permissions..."
|
echo "Fixing LEDMatrix cache directory permissions..."
|
||||||
|
|
||||||
CACHE_DIRS=(
|
|
||||||
"/var/cache/ledmatrix"
|
|
||||||
"/home/ledpi/.ledmatrix_cache"
|
|
||||||
)
|
|
||||||
|
|
||||||
# Get the real user (not root when running with sudo)
|
# Get the real user (not root when running with sudo)
|
||||||
REAL_USER=${SUDO_USER:-$USER}
|
REAL_USER=${SUDO_USER:-$USER}
|
||||||
|
# Resolve the home directory of the real user robustly
|
||||||
|
if command -v getent >/dev/null 2>&1; then
|
||||||
|
REAL_HOME=$(getent passwd "$REAL_USER" | cut -d: -f6)
|
||||||
|
else
|
||||||
|
REAL_HOME=$(eval echo ~"$REAL_USER")
|
||||||
|
fi
|
||||||
REAL_GROUP=$(id -gn "$REAL_USER")
|
REAL_GROUP=$(id -gn "$REAL_USER")
|
||||||
|
|
||||||
|
# Known cache directories for LEDMatrix. Use the actual user's home instead of a hard-coded path.
|
||||||
|
CACHE_DIRS=(
|
||||||
|
"/var/cache/ledmatrix"
|
||||||
|
"$REAL_HOME/.ledmatrix_cache"
|
||||||
|
)
|
||||||
|
|
||||||
for CACHE_DIR in "${CACHE_DIRS[@]}"; do
|
for CACHE_DIR in "${CACHE_DIRS[@]}"; do
|
||||||
echo ""
|
echo ""
|
||||||
echo "Checking cache directory: $CACHE_DIR"
|
echo "Checking cache directory: $CACHE_DIR"
|
||||||
if [ ! -d "$CACHE_DIR" ]; then
|
if [ ! -d "$CACHE_DIR" ]; then
|
||||||
echo " - Directory does not exist. Skipping."
|
echo " - Directory does not exist. Creating it..."
|
||||||
continue
|
sudo mkdir -p "$CACHE_DIR"
|
||||||
fi
|
fi
|
||||||
echo " - Current permissions:"
|
echo " - Current permissions:"
|
||||||
ls -ld "$CACHE_DIR"
|
ls -ld "$CACHE_DIR"
|
||||||
echo " - Fixing permissions..."
|
echo " - Fixing permissions..."
|
||||||
|
# Make directory writable by services regardless of user context
|
||||||
sudo chmod 777 "$CACHE_DIR"
|
sudo chmod 777 "$CACHE_DIR"
|
||||||
sudo chown "$REAL_USER":"$REAL_GROUP" "$CACHE_DIR"
|
sudo chown "$REAL_USER":"$REAL_GROUP" "$CACHE_DIR"
|
||||||
echo " - Updated permissions:"
|
echo " - Updated permissions:"
|
||||||
@@ -37,6 +46,42 @@ for CACHE_DIR in "${CACHE_DIRS[@]}"; do
|
|||||||
echo " - Permissions fix complete for $CACHE_DIR."
|
echo " - Permissions fix complete for $CACHE_DIR."
|
||||||
done
|
done
|
||||||
|
|
||||||
|
# Set up placeholder logos directory for sports managers
|
||||||
|
echo ""
|
||||||
|
echo "Setting up placeholder logos directory for sports managers..."
|
||||||
|
|
||||||
|
PLACEHOLDER_DIR="/var/cache/ledmatrix/placeholder_logos"
|
||||||
|
if [ ! -d "$PLACEHOLDER_DIR" ]; then
|
||||||
|
echo "Creating placeholder logos directory: $PLACEHOLDER_DIR"
|
||||||
|
sudo mkdir -p "$PLACEHOLDER_DIR"
|
||||||
|
sudo chown "$REAL_USER":"$REAL_GROUP" "$PLACEHOLDER_DIR"
|
||||||
|
sudo chmod 777 "$PLACEHOLDER_DIR"
|
||||||
|
else
|
||||||
|
echo "Placeholder logos directory already exists: $PLACEHOLDER_DIR"
|
||||||
|
sudo chmod 777 "$PLACEHOLDER_DIR"
|
||||||
|
sudo chown "$REAL_USER":"$REAL_GROUP" "$PLACEHOLDER_DIR"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo " - Current permissions:"
|
||||||
|
ls -ld "$PLACEHOLDER_DIR"
|
||||||
|
echo " - Testing write access as $REAL_USER..."
|
||||||
|
if sudo -u "$REAL_USER" test -w "$PLACEHOLDER_DIR"; then
|
||||||
|
echo " ✓ Placeholder logos directory is writable by $REAL_USER"
|
||||||
|
else
|
||||||
|
echo " ✗ Placeholder logos directory is not writable by $REAL_USER"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Test with daemon user (which the system might run as)
|
||||||
|
if sudo -u daemon test -w "$PLACEHOLDER_DIR" 2>/dev/null; then
|
||||||
|
echo " ✓ Placeholder logos directory is writable by daemon user"
|
||||||
|
else
|
||||||
|
echo " ✗ Placeholder logos directory is not writable by daemon user"
|
||||||
|
fi
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo "All cache directory permission fixes attempted."
|
echo "All cache directory permission fixes attempted."
|
||||||
echo "If you still see errors, check which user is running the LEDMatrix service and ensure it matches the owner above."
|
echo "If you still see errors, check which user is running the LEDMatrix service and ensure it matches the owner above."
|
||||||
|
echo ""
|
||||||
|
echo "The system will now create placeholder logos in:"
|
||||||
|
echo " $PLACEHOLDER_DIR"
|
||||||
|
echo "This should eliminate the permission denied warnings for sports logos."
|
||||||
105
fix_web_permissions.sh
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# LED Matrix Web Interface Permissions Fix Script
|
||||||
|
# This script fixes permissions for the web interface to access logs and system commands
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "Fixing LED Matrix Web Interface permissions..."
|
||||||
|
|
||||||
|
# Get the current user (should be the user running the web interface)
|
||||||
|
WEB_USER=$(whoami)
|
||||||
|
PROJECT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
|
||||||
|
echo "Detected web interface user: $WEB_USER"
|
||||||
|
echo "Project directory: $PROJECT_DIR"
|
||||||
|
|
||||||
|
# Check if running as root
|
||||||
|
if [ "$EUID" -eq 0 ]; then
|
||||||
|
echo "Error: This script should not be run as root."
|
||||||
|
echo "Run it as the user that will be running the web interface."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "This script will:"
|
||||||
|
echo "1. Add the web user to the 'systemd-journal' group for log access"
|
||||||
|
echo "2. Add the web user to the 'adm' group for additional system access"
|
||||||
|
echo "3. Configure sudoers for passwordless access to system commands"
|
||||||
|
echo "4. Set proper file permissions"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Ask for confirmation
|
||||||
|
read -p "Do you want to proceed? (y/N): " -n 1 -r
|
||||||
|
echo
|
||||||
|
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||||
|
echo "Permission fix cancelled."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Step 1: Adding user to systemd-journal group..."
|
||||||
|
if sudo usermod -a -G systemd-journal "$WEB_USER"; then
|
||||||
|
echo "✓ Added $WEB_USER to systemd-journal group"
|
||||||
|
else
|
||||||
|
echo "✗ Failed to add user to systemd-journal group"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Step 2: Adding user to adm group..."
|
||||||
|
if sudo usermod -a -G adm "$WEB_USER"; then
|
||||||
|
echo "✓ Added $WEB_USER to adm group"
|
||||||
|
else
|
||||||
|
echo "✗ Failed to add user to adm group"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Step 3: Setting proper file permissions..."
|
||||||
|
# Set ownership of project files to the web user
|
||||||
|
if sudo chown -R "$WEB_USER:$WEB_USER" "$PROJECT_DIR"; then
|
||||||
|
echo "✓ Set project ownership to $WEB_USER"
|
||||||
|
else
|
||||||
|
echo "✗ Failed to set project ownership"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Set proper permissions for config files
|
||||||
|
if sudo chmod 644 "$PROJECT_DIR/config/config.json" 2>/dev/null; then
|
||||||
|
echo "✓ Set config file permissions"
|
||||||
|
else
|
||||||
|
echo "⚠ Config file permissions not set (file may not exist)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Step 4: Testing journal access..."
|
||||||
|
# Test if the user can now access journal logs
|
||||||
|
if journalctl --user-unit=ledmatrix.service --no-pager --lines=1 > /dev/null 2>&1; then
|
||||||
|
echo "✓ Journal access test passed"
|
||||||
|
elif sudo -u "$WEB_USER" journalctl --no-pager --lines=1 > /dev/null 2>&1; then
|
||||||
|
echo "✓ Journal access test passed (with sudo)"
|
||||||
|
else
|
||||||
|
echo "⚠ Journal access test failed - you may need to log out and back in"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Step 5: Testing sudo access..."
|
||||||
|
# Test sudo access for system commands
|
||||||
|
if sudo -n systemctl status ledmatrix.service > /dev/null 2>&1; then
|
||||||
|
echo "✓ Sudo access test passed"
|
||||||
|
else
|
||||||
|
echo "⚠ Sudo access test failed - you may need to run configure_web_sudo.sh"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Permission fix completed!"
|
||||||
|
echo ""
|
||||||
|
echo "IMPORTANT: For group changes to take effect, you need to:"
|
||||||
|
echo "1. Log out and log back in, OR"
|
||||||
|
echo "2. Run: newgrp systemd-journal"
|
||||||
|
echo "3. Restart the web interface service:"
|
||||||
|
echo " sudo systemctl restart ledmatrix-web.service"
|
||||||
|
echo ""
|
||||||
|
echo "After logging back in, test journal access with:"
|
||||||
|
echo " journalctl --no-pager --lines=5"
|
||||||
|
echo ""
|
||||||
|
echo "If you still have sudo issues, run:"
|
||||||
|
echo " ./configure_web_sudo.sh"
|
||||||
150
install_dependencies_apt.py
Normal file
@@ -0,0 +1,150 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Alternative dependency installer that tries apt packages first,
|
||||||
|
then falls back to pip with --break-system-packages
|
||||||
|
"""
|
||||||
|
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
def install_via_apt(package_name):
|
||||||
|
"""Try to install a package via apt."""
|
||||||
|
try:
|
||||||
|
# Map pip package names to apt package names
|
||||||
|
apt_package_map = {
|
||||||
|
'flask': 'python3-flask',
|
||||||
|
'flask_socketio': 'python3-flask-socketio',
|
||||||
|
'PIL': 'python3-pil',
|
||||||
|
'socketio': 'python3-socketio',
|
||||||
|
'eventlet': 'python3-eventlet',
|
||||||
|
'freetype': 'python3-freetype',
|
||||||
|
'psutil': 'python3-psutil',
|
||||||
|
'werkzeug': 'python3-werkzeug',
|
||||||
|
'numpy': 'python3-numpy',
|
||||||
|
'requests': 'python3-requests',
|
||||||
|
'python-dateutil': 'python3-dateutil',
|
||||||
|
'pytz': 'python3-tz',
|
||||||
|
'geopy': 'python3-geopy',
|
||||||
|
'unidecode': 'python3-unidecode',
|
||||||
|
'websockets': 'python3-websockets',
|
||||||
|
'websocket-client': 'python3-websocket-client'
|
||||||
|
}
|
||||||
|
|
||||||
|
apt_package = apt_package_map.get(package_name, f'python3-{package_name}')
|
||||||
|
|
||||||
|
print(f"Trying to install {apt_package} via apt...")
|
||||||
|
subprocess.check_call([
|
||||||
|
'sudo', 'apt', 'update'
|
||||||
|
], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
||||||
|
|
||||||
|
subprocess.check_call([
|
||||||
|
'sudo', 'apt', 'install', '-y', apt_package
|
||||||
|
], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
||||||
|
|
||||||
|
print(f"Successfully installed {apt_package} via apt")
|
||||||
|
return True
|
||||||
|
|
||||||
|
except subprocess.CalledProcessError:
|
||||||
|
print(f"Failed to install {package_name} via apt, will try pip")
|
||||||
|
return False
|
||||||
|
|
||||||
|
def install_via_pip(package_name):
|
||||||
|
"""Install a package via pip with --break-system-packages."""
|
||||||
|
try:
|
||||||
|
print(f"Installing {package_name} via pip...")
|
||||||
|
subprocess.check_call([
|
||||||
|
sys.executable, '-m', 'pip', 'install', '--break-system-packages', package_name
|
||||||
|
])
|
||||||
|
print(f"Successfully installed {package_name} via pip")
|
||||||
|
return True
|
||||||
|
except subprocess.CalledProcessError as e:
|
||||||
|
print(f"Failed to install {package_name} via pip: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
def check_package_installed(package_name):
|
||||||
|
"""Check if a package is already installed."""
|
||||||
|
try:
|
||||||
|
__import__(package_name)
|
||||||
|
return True
|
||||||
|
except ImportError:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def main():
|
||||||
|
"""Main installation function."""
|
||||||
|
print("Installing dependencies for LED Matrix Web Interface V2...")
|
||||||
|
|
||||||
|
# List of required packages
|
||||||
|
required_packages = [
|
||||||
|
'flask',
|
||||||
|
'flask_socketio',
|
||||||
|
'PIL',
|
||||||
|
'socketio',
|
||||||
|
'eventlet',
|
||||||
|
'freetype',
|
||||||
|
'psutil',
|
||||||
|
'werkzeug',
|
||||||
|
'numpy',
|
||||||
|
'requests',
|
||||||
|
'python-dateutil',
|
||||||
|
'pytz',
|
||||||
|
'geopy',
|
||||||
|
'unidecode',
|
||||||
|
'websockets',
|
||||||
|
'websocket-client'
|
||||||
|
]
|
||||||
|
|
||||||
|
failed_packages = []
|
||||||
|
|
||||||
|
for package in required_packages:
|
||||||
|
if check_package_installed(package):
|
||||||
|
print(f"{package} is already installed")
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Try apt first, then pip
|
||||||
|
if not install_via_apt(package):
|
||||||
|
if not install_via_pip(package):
|
||||||
|
failed_packages.append(package)
|
||||||
|
|
||||||
|
# Install packages that don't have apt equivalents
|
||||||
|
special_packages = [
|
||||||
|
'timezonefinder==6.2.0',
|
||||||
|
'google-auth-oauthlib==1.0.0',
|
||||||
|
'google-auth-httplib2==0.1.0',
|
||||||
|
'google-api-python-client==2.86.0',
|
||||||
|
'spotipy',
|
||||||
|
'icalevents',
|
||||||
|
'python-engineio'
|
||||||
|
]
|
||||||
|
|
||||||
|
for package in special_packages:
|
||||||
|
if not install_via_pip(package):
|
||||||
|
failed_packages.append(package)
|
||||||
|
|
||||||
|
# Install rgbmatrix module from local source
|
||||||
|
print("Installing rgbmatrix module...")
|
||||||
|
try:
|
||||||
|
rgbmatrix_path = Path(__file__).parent / 'rpi-rgb-led-matrix-master' / 'bindings' / 'python'
|
||||||
|
if rgbmatrix_path.exists():
|
||||||
|
subprocess.check_call([
|
||||||
|
sys.executable, '-m', 'pip', 'install', '--break-system-packages', '-e', str(rgbmatrix_path)
|
||||||
|
], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
||||||
|
print("rgbmatrix module installed successfully")
|
||||||
|
else:
|
||||||
|
print("Warning: rgbmatrix source not found")
|
||||||
|
except subprocess.CalledProcessError as e:
|
||||||
|
print(f"Failed to install rgbmatrix module: {e}")
|
||||||
|
failed_packages.append('rgbmatrix')
|
||||||
|
|
||||||
|
if failed_packages:
|
||||||
|
print(f"\nFailed to install the following packages: {failed_packages}")
|
||||||
|
print("You may need to install them manually or check your system configuration.")
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
print("\nAll dependencies installed successfully!")
|
||||||
|
return True
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
success = main()
|
||||||
|
sys.exit(0 if success else 1)
|
||||||
49
install_web_service.sh
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# LED Matrix Web Interface Service Installer
|
||||||
|
# This script installs and enables the web interface systemd service
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "Installing LED Matrix Web Interface Service..."
|
||||||
|
|
||||||
|
# Get the directory where this script is located
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
cd "$SCRIPT_DIR"
|
||||||
|
|
||||||
|
# Check if running as root
|
||||||
|
if [ "$EUID" -ne 0 ]; then
|
||||||
|
echo "Please run as root (use sudo)"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Copy the service file to systemd directory
|
||||||
|
echo "Copying service file to /etc/systemd/system/"
|
||||||
|
cp ledmatrix-web.service /etc/systemd/system/
|
||||||
|
|
||||||
|
# Reload systemd to recognize the new service
|
||||||
|
echo "Reloading systemd..."
|
||||||
|
systemctl daemon-reload
|
||||||
|
|
||||||
|
# Enable the service to start on boot
|
||||||
|
echo "Enabling ledmatrix-web.service..."
|
||||||
|
systemctl enable ledmatrix-web.service
|
||||||
|
|
||||||
|
# Start the service
|
||||||
|
echo "Starting ledmatrix-web.service..."
|
||||||
|
systemctl start ledmatrix-web.service
|
||||||
|
|
||||||
|
# Check service status
|
||||||
|
echo "Checking service status..."
|
||||||
|
systemctl status ledmatrix-web.service --no-pager
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Web interface service installed and started!"
|
||||||
|
echo "The web interface will now start automatically when:"
|
||||||
|
echo "1. The system boots"
|
||||||
|
echo "2. The 'web_display_autostart' setting is true in config/config.json"
|
||||||
|
echo ""
|
||||||
|
echo "To check the service status: systemctl status ledmatrix-web.service"
|
||||||
|
echo "To view logs: journalctl -u ledmatrix-web.service -f"
|
||||||
|
echo "To stop the service: systemctl stop ledmatrix-web.service"
|
||||||
|
echo "To disable autostart: systemctl disable ledmatrix-web.service"
|
||||||
18
ledmatrix-web.service
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=LED Matrix Web Interface Service
|
||||||
|
After=network.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
User=root
|
||||||
|
WorkingDirectory=/home/ledpi/LEDMatrix
|
||||||
|
Environment=USE_THREADING=1
|
||||||
|
ExecStart=/usr/bin/python3 /home/ledpi/LEDMatrix/start_web_conditionally.py
|
||||||
|
Restart=on-failure
|
||||||
|
RestartSec=10
|
||||||
|
StandardOutput=syslog
|
||||||
|
StandardError=syslog
|
||||||
|
SyslogIdentifier=ledmatrix-web
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
1
list_missing_teams.py
Normal file
@@ -0,0 +1 @@
|
|||||||
|
|
||||||
1
list_soccer_abbreviations.py
Normal file
@@ -0,0 +1 @@
|
|||||||
|
|
||||||
1230
milb_main.py
Normal file
657
missing_team_logos.txt
Normal file
@@ -0,0 +1,657 @@
|
|||||||
|
================================================================================
|
||||||
|
MISSING TEAM LOGOS - COMPLETE LIST
|
||||||
|
================================================================================
|
||||||
|
Total missing teams: 309
|
||||||
|
|
||||||
|
|
||||||
|
MLB:
|
||||||
|
---
|
||||||
|
OAK => Oakland Athletics
|
||||||
|
|
||||||
|
NCAAF:
|
||||||
|
-----
|
||||||
|
AAMU => Alabama A&M Bulldogs
|
||||||
|
ACU => Abilene Christian Wildcats
|
||||||
|
ADA => Adams State Grizzlies
|
||||||
|
ADR => Adrian Bulldogs
|
||||||
|
AIC => American International Yellow Jackets
|
||||||
|
ALB => Albright Lions
|
||||||
|
ALBS => Albany State (GA) Golden Rams
|
||||||
|
ALCN => Alcorn State Braves
|
||||||
|
ALD => Alderson Broaddus Battlers
|
||||||
|
ALF => Alfred Saxons
|
||||||
|
ALL => Allegheny Gators
|
||||||
|
ALST => Alabama State Hornets
|
||||||
|
AMH => Amherst College Mammoths
|
||||||
|
AND => Anderson (IN) Ravens
|
||||||
|
ANG => Angelo State Rams
|
||||||
|
ANN => Anna Maria College Amcats
|
||||||
|
APSU => Austin Peay Governors
|
||||||
|
ASH => Ashland Eagles
|
||||||
|
ASP => Assumption Greyhounds
|
||||||
|
ASU => Arizona State Sun Devils
|
||||||
|
AUG => St. Augustine's Falcons
|
||||||
|
AUR => Aurora Spartans
|
||||||
|
AUS => Austin College 'Roos
|
||||||
|
AVE => Averett Cougars
|
||||||
|
AVI => Avila College Eagles
|
||||||
|
AZU => Azusa Pacific Cougars
|
||||||
|
BAK => Baker University Wildcats
|
||||||
|
BAL => Baldwin Wallace Yellow Jackets
|
||||||
|
BAT => Bates College Bobcats
|
||||||
|
BEC => Becker College Hawks
|
||||||
|
BEL => Beloit College Buccaneers
|
||||||
|
BEN => Benedictine University (IL) Eagles
|
||||||
|
BENT => Bentley Falcons
|
||||||
|
BET => Bethel (TN) Wildcats
|
||||||
|
BHS => Black Hills State Yellow Jackets
|
||||||
|
BIR => Birmingham-Southern Panthers
|
||||||
|
BKN => Bacone College Warriors
|
||||||
|
BLA => Blackburn Beavers
|
||||||
|
BLOM => Bloomsburg Huskies
|
||||||
|
BLU => Bluffton Beavers
|
||||||
|
BOW => Bowdoin Polar Bears
|
||||||
|
BRI => British Columbia Thunderbirds
|
||||||
|
BRWN => Brown Bears
|
||||||
|
BST => Bemidji State Beavers
|
||||||
|
BUCK => Bucknell Bison
|
||||||
|
BUE => Buena Vista Beavers
|
||||||
|
BUF => Buffalo State Bengals
|
||||||
|
BUT => Butler Bulldogs
|
||||||
|
CAM => Campbell Fighting Camels
|
||||||
|
CAP => Capital University Crusaders
|
||||||
|
CAR => Carthage College Red Men
|
||||||
|
CARK => Central Arkansas Bears
|
||||||
|
CAS => Castleton Spartans
|
||||||
|
CAT => Catholic University Cardinals
|
||||||
|
CCSU => Central Connecticut Blue Devils
|
||||||
|
CEN => Centre College Colonels
|
||||||
|
CHA => Chapman University Panthers
|
||||||
|
CHI => Chicago Maroons
|
||||||
|
CHSO => Charleston Southern Buccaneers
|
||||||
|
CLA => Clarion Golden Eagles
|
||||||
|
CLMB => Columbia Lions
|
||||||
|
COE => Coe College Kohawks
|
||||||
|
COL => Colorado School of Mines Orediggers
|
||||||
|
COLC => Colorado College Tigers
|
||||||
|
COLG => Colgate Raiders
|
||||||
|
CON => Concordia-Minnesota Cobbers
|
||||||
|
COR => Cornell College (IA) Rams
|
||||||
|
CP => Cal Poly Mustangs
|
||||||
|
CRO => Crown Storm
|
||||||
|
CSU => Colorado State Rams
|
||||||
|
CUL => Culver-Stockton Wildcats
|
||||||
|
CUM => Cumberland College Indians
|
||||||
|
CUR => Curry College Colonels
|
||||||
|
DAK => Dakota Wesleyan Tigers
|
||||||
|
DART => Dartmouth Big Green
|
||||||
|
DAV => Davidson Wildcats
|
||||||
|
DAY => Dayton Flyers
|
||||||
|
DEF => Defiance Yellow Jackets
|
||||||
|
DEL => Delta State Statesmen
|
||||||
|
DEN => Denison Big Red
|
||||||
|
DEP => DePauw Tigers
|
||||||
|
DIC => Dickinson State Blue Hawks
|
||||||
|
DRKE => Drake Bulldogs
|
||||||
|
DSU => Delaware State Hornets
|
||||||
|
DUB => Dubuque Spartans
|
||||||
|
DUQ => Duquesne Dukes
|
||||||
|
EAS => Eastern New Mexico Greyhounds
|
||||||
|
EDI => Edinboro Fighting Scots
|
||||||
|
EIU => Eastern Illinois Panthers
|
||||||
|
EKU => Eastern Kentucky Colonels
|
||||||
|
ELI => Elizabeth City State Vikings
|
||||||
|
ELM => Elmhurst Blue Jays
|
||||||
|
ELON => Elon Phoenix
|
||||||
|
EMO => Emory & Henry Wasps
|
||||||
|
EMP => Emporia State Hornets
|
||||||
|
END => Endicott College Gulls
|
||||||
|
EOR => Eastern Oregon Mountaineers
|
||||||
|
ETSU => East Tennessee State Buccaneers
|
||||||
|
EUR => Eureka College Red Devils
|
||||||
|
EWU => Eastern Washington Eagles
|
||||||
|
FAY => Fayetteville State Broncos
|
||||||
|
FDU => FDU-Florham Devils
|
||||||
|
FER => Ferrum Panthers
|
||||||
|
FIN => Findlay Oilers
|
||||||
|
FIT => Fitchburg State Falcons
|
||||||
|
FLA => Florida Gators
|
||||||
|
FOR => Fort Valley State Wildcats
|
||||||
|
FRA => Franklin Grizzlies
|
||||||
|
FRO => Frostburg State Bobcats
|
||||||
|
FRST => Ferris State Bulldogs
|
||||||
|
FTLW => Fort Lewis Skyhawks
|
||||||
|
FUR => Furman Paladins
|
||||||
|
GAL => Gallaudet Bison
|
||||||
|
GAN => Gannon Golden Knights
|
||||||
|
GEN => Geneva College Golden Tornadoes
|
||||||
|
GEO => George Fox University Bruins
|
||||||
|
GET => Gettysburg Bullets
|
||||||
|
GLE => Glenville State Pioneers
|
||||||
|
GMU => George Mason Patriots
|
||||||
|
GRA => Grand Valley State Lakers
|
||||||
|
GRE => Greenville Panthers
|
||||||
|
GRI => Grinnell Pioneers
|
||||||
|
GRO => Grove City College Wolverines
|
||||||
|
GUI => Guilford Quakers
|
||||||
|
GWEB => Gardner-Webb Bulldogs
|
||||||
|
HAM => Hampden-Sydney Tigers
|
||||||
|
HAMP => Hampton Pirates
|
||||||
|
HAN => Hanover Panthers
|
||||||
|
HAR => Hartwick Hawks
|
||||||
|
HARV => Harvard Crimson
|
||||||
|
HAS => Haskell Indian Nations Jayhawks
|
||||||
|
HAW => Hawai'i Rainbow Warriors
|
||||||
|
HBU => Houston Baptist Huskies
|
||||||
|
HC => Holy Cross Crusaders
|
||||||
|
HEI => Heidelberg Student Princes
|
||||||
|
HEN => Hendrix College Warriors
|
||||||
|
HIL => Hillsdale Chargers
|
||||||
|
HIR => Hiram College Terriers
|
||||||
|
HOB => Hobart Statesmen
|
||||||
|
HOW => Howard Bison
|
||||||
|
HUS => Husson Eagles
|
||||||
|
IDHO => Idaho Vandals
|
||||||
|
IDST => Idaho State Bengals
|
||||||
|
ILST => Illinois State Redbirds
|
||||||
|
ILW => Illinois Wesleyan Titans
|
||||||
|
IND => Indianapolis
|
||||||
|
INST => Indiana State Sycamores
|
||||||
|
IOW => Iowa Wesleyan Tigers
|
||||||
|
ITH => Ithaca Bombers
|
||||||
|
JKST => Jackson State Tigers
|
||||||
|
JOH => Johnson C Smith Golden Bulls
|
||||||
|
JUN => Juniata Eagles
|
||||||
|
KAL => Kalamazoo Hornets
|
||||||
|
KAN => Kansas Wesleyan University Coyotes
|
||||||
|
KEN => Kenyon Lords
|
||||||
|
KIN => King's College (PA) Monarchs
|
||||||
|
KNO => Knox College Prairie Fire
|
||||||
|
KUT => Kutztown Golden Bears
|
||||||
|
KYST => Kentucky State Thorobreds
|
||||||
|
KYW => Kentucky Wesleyan Panthers
|
||||||
|
LA => La Verne Leopards
|
||||||
|
LAG => LaGrange College Panthers
|
||||||
|
LAK => Lake Forest Foresters
|
||||||
|
LAM => Lambuth Eagles
|
||||||
|
LAN => Langston Lions
|
||||||
|
LAW => Lawrence Vikings
|
||||||
|
LEB => Lebanon Valley Flying Dutchmen
|
||||||
|
LEH => Lehigh Mountain Hawks
|
||||||
|
LEN => Lenoir-Rhyne Bears
|
||||||
|
LEW => Lewis & Clark Pioneers
|
||||||
|
LIM => Limestone Saints
|
||||||
|
LIN => Linfield Wildcats
|
||||||
|
LOC => Lock Haven Bald Eagles
|
||||||
|
LOR => Loras College Duhawks
|
||||||
|
LUT => Luther Norse
|
||||||
|
LYC => Lycoming Warriors
|
||||||
|
M-OH => Miami (OH) RedHawks
|
||||||
|
MAC => Macalester Scots
|
||||||
|
MAI => Maine Maritime Mariners
|
||||||
|
MAN => Mansfield Mountaineers
|
||||||
|
MAR => Maryville College Fighting Scots
|
||||||
|
MAS => Mass Maritime Buccaneers
|
||||||
|
MAY => Mayville State Comets
|
||||||
|
MCM => McMurry War Hawks
|
||||||
|
MCN => McNeese Cowboys
|
||||||
|
MEN => Menlo College Oaks
|
||||||
|
MER => Merchant Marine Mariners
|
||||||
|
MERC => Mercyhurst Lakers
|
||||||
|
MES => Colorado Mesa Mavericks
|
||||||
|
MET => Methodist Monarchs
|
||||||
|
MH => Mars Hill Mountain Lions
|
||||||
|
MID => Midwestern State Mustangs
|
||||||
|
MIL => Millsaps Majors
|
||||||
|
MIN => Minot State Beavers
|
||||||
|
MIS => Missouri Western Griffons
|
||||||
|
MNST => Minnesota State Mavericks
|
||||||
|
MONM => Monmouth Hawks
|
||||||
|
MONT => Montana Grizzlies
|
||||||
|
MOR => Morningside Chiefs
|
||||||
|
MORE => Morehead State Eagles
|
||||||
|
MORG => Morgan State Bears
|
||||||
|
MOU => Mount Union Raiders
|
||||||
|
MRST => Marist Red Foxes
|
||||||
|
MSU => Michigan State Spartans
|
||||||
|
MTST => Montana State Bobcats
|
||||||
|
MTU => Michigan Tech Huskies
|
||||||
|
MUH => Muhlenberg Mules
|
||||||
|
MUR => Murray State Racers
|
||||||
|
MUS => Muskingum Fighting Muskies
|
||||||
|
MVSU => Mississippi Valley State Delta Devils
|
||||||
|
NAU => Northern Arizona Lumberjacks
|
||||||
|
NBY => Newberry Wolves
|
||||||
|
NCAT => North Carolina A&T Aggies
|
||||||
|
NCCU => North Carolina Central Eagles
|
||||||
|
NCST => NC State Wolfpack
|
||||||
|
NDOH => Notre Dame College Falcons
|
||||||
|
NDSU => North Dakota State Bison
|
||||||
|
NH => New Haven Chargers
|
||||||
|
NICH => Nicholls Colonels
|
||||||
|
NMH => New Mexico Highlands Cowboys
|
||||||
|
NMI => Northern Michigan Wildcats
|
||||||
|
NOR => Univ. of Northwestern-St. Paul Eagles
|
||||||
|
NORF => Norfolk State Spartans
|
||||||
|
OBE => Oberlin Yeomen
|
||||||
|
OHI => Ohio Northern Polar Bears
|
||||||
|
OKL => Oklahoma Baptist Bison
|
||||||
|
OLI => Olivet College Comets
|
||||||
|
OMA => Omaha Mavericks
|
||||||
|
OTT => Otterbein Cardinals
|
||||||
|
PAC => Pacific (OR) Boxers
|
||||||
|
PENN => Pennsylvania Quakers
|
||||||
|
PIKE => Pikeville Bears
|
||||||
|
PRE => Presentation College Saints
|
||||||
|
PRI => Principia College Panthers
|
||||||
|
PRIN => Princeton Tigers
|
||||||
|
PST => Pittsburg State Gorillas
|
||||||
|
RED => Redlands Bulldogs
|
||||||
|
RICH => Richmond Spiders
|
||||||
|
RIT => Rochester Yellow Jackets
|
||||||
|
ROB => Robert Morris (IL) Eagles
|
||||||
|
ROS => Rose-Hulman Engineers
|
||||||
|
SAC => Sacramento State Hornets
|
||||||
|
SAG => Saginaw Valley Cardinals
|
||||||
|
SDAK => South Dakota Coyotes
|
||||||
|
SET => Seton Hill Griffins
|
||||||
|
SIU => Southern Illinois Salukis
|
||||||
|
SLI => Slippery Rock The Rock
|
||||||
|
SOU => Southwestern College Moundbuilders
|
||||||
|
SPR => Springfield College Pride
|
||||||
|
ST => St. Scholastica Saints
|
||||||
|
STE => Stevenson University Mustangs
|
||||||
|
STET => Stetson Hatters
|
||||||
|
STO => Stonehill College Skyhawks
|
||||||
|
SUS => Susquehanna University River Hawks
|
||||||
|
SUU => Southern Utah Thunderbirds
|
||||||
|
TA&M => Texas A&M Aggies
|
||||||
|
TAY => Taylor Trojans
|
||||||
|
TIF => Tiffin University Dragons
|
||||||
|
TRI => Trinity University (TX) Tigers
|
||||||
|
TUF => Tufts University Jumbos
|
||||||
|
TXST => Texas State Bobcats
|
||||||
|
UAPB => Arkansas-Pine Bluff Golden Lions
|
||||||
|
UCD => UC Davis Aggies
|
||||||
|
UCONN => UConn Huskies
|
||||||
|
ULM => UL Monroe Warhawks
|
||||||
|
UMD => Minnesota-Duluth Bulldogs
|
||||||
|
UMDA => UMASS Dartmouth Corsairs
|
||||||
|
UML => UMass Lowell River Hawks
|
||||||
|
UNA => North Alabama Lions
|
||||||
|
UNCO => Northern Colorado Bears
|
||||||
|
UND => North Dakota Fighting Hawks
|
||||||
|
UNH => New Hampshire Wildcats
|
||||||
|
UNI => University of Mary Marauders
|
||||||
|
UNNY => Union Dutchmen
|
||||||
|
UNT => North Texas Mean Green
|
||||||
|
UPP => Upper Iowa Peacocks
|
||||||
|
URI => Rhode Island Rams
|
||||||
|
USA => South Alabama Jaguars
|
||||||
|
USD => San Diego Toreros
|
||||||
|
UTC => Chattanooga Mocs
|
||||||
|
UTI => Utica College Pioneers
|
||||||
|
VAL => Valley City State Vikings
|
||||||
|
VILL => Villanova Wildcats
|
||||||
|
VIR => Virginia State Trojans
|
||||||
|
VT => Virginia Tech Hokies
|
||||||
|
WAB => Wabash College Little Giants
|
||||||
|
WAS => Washington-Missouri Bears
|
||||||
|
WAY => Wayne State (MI) Warriors
|
||||||
|
WES => Westminster College (MO) Blue Jays
|
||||||
|
WHE => Wheaton College Illinois Thunder
|
||||||
|
WIL => Wilkes University Colonels
|
||||||
|
WIN => Wingate Bulldogs
|
||||||
|
WIS => Wisconsin-Platteville Pioneers
|
||||||
|
WOR => Worcester State College Lancers
|
||||||
|
YALE => Yale Bulldogs
|
||||||
|
|
||||||
|
NHL:
|
||||||
|
---
|
||||||
|
ARI => Arizona Coyotes
|
||||||
|
VGS => Vegas Golden Knights
|
||||||
|
|
||||||
|
SOCCER - BUNDESLIGA (GERMANY):
|
||||||
|
-----------------------------
|
||||||
|
DOR => Borussia Dortmund
|
||||||
|
KOL => 1. FC Köln
|
||||||
|
LEV => Bayer Leverkusen
|
||||||
|
STU => VfB Stuttgart
|
||||||
|
|
||||||
|
SOCCER - LIGUE 1 (FRANCE):
|
||||||
|
-------------------------
|
||||||
|
LYON => Lyon
|
||||||
|
MAR => Marseille
|
||||||
|
NICE => Nice
|
||||||
|
PSG => Paris Saint-Germain
|
||||||
|
|
||||||
|
SOCCER - PREMIER LEAGUE (ENGLAND):
|
||||||
|
---------------------------------
|
||||||
|
BUR => Burnley
|
||||||
|
LUT => Luton Town
|
||||||
|
SHU => Sheffield United
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
SUMMARY BY SPORT:
|
||||||
|
================================================================================
|
||||||
|
MLB: 1 missing
|
||||||
|
NCAAF: 295 missing
|
||||||
|
NHL: 2 missing
|
||||||
|
Soccer - Bundesliga (Germany): 4 missing
|
||||||
|
Soccer - Ligue 1 (France): 4 missing
|
||||||
|
Soccer - Premier League (England): 3 missing
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
FILENAMES NEEDED:
|
||||||
|
================================================================================
|
||||||
|
Add these PNG files to their respective directories:
|
||||||
|
|
||||||
|
assets/sports/mlb_logos/OAK.png
|
||||||
|
assets/sports/ncaa_fbs_logos/AAMU.png
|
||||||
|
assets/sports/ncaa_fbs_logos/ACU.png
|
||||||
|
assets/sports/ncaa_fbs_logos/ADA.png
|
||||||
|
assets/sports/ncaa_fbs_logos/ADR.png
|
||||||
|
assets/sports/ncaa_fbs_logos/AIC.png
|
||||||
|
assets/sports/ncaa_fbs_logos/ALB.png
|
||||||
|
assets/sports/ncaa_fbs_logos/ALBS.png
|
||||||
|
assets/sports/ncaa_fbs_logos/ALCN.png
|
||||||
|
assets/sports/ncaa_fbs_logos/ALD.png
|
||||||
|
assets/sports/ncaa_fbs_logos/ALF.png
|
||||||
|
assets/sports/ncaa_fbs_logos/ALL.png
|
||||||
|
assets/sports/ncaa_fbs_logos/ALST.png
|
||||||
|
assets/sports/ncaa_fbs_logos/AMH.png
|
||||||
|
assets/sports/ncaa_fbs_logos/AND.png
|
||||||
|
assets/sports/ncaa_fbs_logos/ANG.png
|
||||||
|
assets/sports/ncaa_fbs_logos/ANN.png
|
||||||
|
assets/sports/ncaa_fbs_logos/APSU.png
|
||||||
|
assets/sports/ncaa_fbs_logos/ASH.png
|
||||||
|
assets/sports/ncaa_fbs_logos/ASP.png
|
||||||
|
assets/sports/ncaa_fbs_logos/ASU.png
|
||||||
|
assets/sports/ncaa_fbs_logos/AUG.png
|
||||||
|
assets/sports/ncaa_fbs_logos/AUR.png
|
||||||
|
assets/sports/ncaa_fbs_logos/AUS.png
|
||||||
|
assets/sports/ncaa_fbs_logos/AVE.png
|
||||||
|
assets/sports/ncaa_fbs_logos/AVI.png
|
||||||
|
assets/sports/ncaa_fbs_logos/AZU.png
|
||||||
|
assets/sports/ncaa_fbs_logos/BAK.png
|
||||||
|
assets/sports/ncaa_fbs_logos/BAL.png
|
||||||
|
assets/sports/ncaa_fbs_logos/BAT.png
|
||||||
|
assets/sports/ncaa_fbs_logos/BEC.png
|
||||||
|
assets/sports/ncaa_fbs_logos/BEL.png
|
||||||
|
assets/sports/ncaa_fbs_logos/BEN.png
|
||||||
|
assets/sports/ncaa_fbs_logos/BENT.png
|
||||||
|
assets/sports/ncaa_fbs_logos/BET.png
|
||||||
|
assets/sports/ncaa_fbs_logos/BHS.png
|
||||||
|
assets/sports/ncaa_fbs_logos/BIR.png
|
||||||
|
assets/sports/ncaa_fbs_logos/BKN.png
|
||||||
|
assets/sports/ncaa_fbs_logos/BLA.png
|
||||||
|
assets/sports/ncaa_fbs_logos/BLOM.png
|
||||||
|
assets/sports/ncaa_fbs_logos/BLU.png
|
||||||
|
assets/sports/ncaa_fbs_logos/BOW.png
|
||||||
|
assets/sports/ncaa_fbs_logos/BRI.png
|
||||||
|
assets/sports/ncaa_fbs_logos/BRWN.png
|
||||||
|
assets/sports/ncaa_fbs_logos/BST.png
|
||||||
|
assets/sports/ncaa_fbs_logos/BUCK.png
|
||||||
|
assets/sports/ncaa_fbs_logos/BUE.png
|
||||||
|
assets/sports/ncaa_fbs_logos/BUF.png
|
||||||
|
assets/sports/ncaa_fbs_logos/BUT.png
|
||||||
|
assets/sports/ncaa_fbs_logos/CAM.png
|
||||||
|
assets/sports/ncaa_fbs_logos/CAP.png
|
||||||
|
assets/sports/ncaa_fbs_logos/CAR.png
|
||||||
|
assets/sports/ncaa_fbs_logos/CARK.png
|
||||||
|
assets/sports/ncaa_fbs_logos/CAS.png
|
||||||
|
assets/sports/ncaa_fbs_logos/CAT.png
|
||||||
|
assets/sports/ncaa_fbs_logos/CCSU.png
|
||||||
|
assets/sports/ncaa_fbs_logos/CEN.png
|
||||||
|
assets/sports/ncaa_fbs_logos/CHA.png
|
||||||
|
assets/sports/ncaa_fbs_logos/CHI.png
|
||||||
|
assets/sports/ncaa_fbs_logos/CHSO.png
|
||||||
|
assets/sports/ncaa_fbs_logos/CLA.png
|
||||||
|
assets/sports/ncaa_fbs_logos/CLMB.png
|
||||||
|
assets/sports/ncaa_fbs_logos/COE.png
|
||||||
|
assets/sports/ncaa_fbs_logos/COL.png
|
||||||
|
assets/sports/ncaa_fbs_logos/COLC.png
|
||||||
|
assets/sports/ncaa_fbs_logos/COLG.png
|
||||||
|
assets/sports/ncaa_fbs_logos/CON.png
|
||||||
|
assets/sports/ncaa_fbs_logos/COR.png
|
||||||
|
assets/sports/ncaa_fbs_logos/CP.png
|
||||||
|
assets/sports/ncaa_fbs_logos/CRO.png
|
||||||
|
assets/sports/ncaa_fbs_logos/CSU.png
|
||||||
|
assets/sports/ncaa_fbs_logos/CUL.png
|
||||||
|
assets/sports/ncaa_fbs_logos/CUM.png
|
||||||
|
assets/sports/ncaa_fbs_logos/CUR.png
|
||||||
|
assets/sports/ncaa_fbs_logos/DAK.png
|
||||||
|
assets/sports/ncaa_fbs_logos/DART.png
|
||||||
|
assets/sports/ncaa_fbs_logos/DAV.png
|
||||||
|
assets/sports/ncaa_fbs_logos/DAY.png
|
||||||
|
assets/sports/ncaa_fbs_logos/DEF.png
|
||||||
|
assets/sports/ncaa_fbs_logos/DEL.png
|
||||||
|
assets/sports/ncaa_fbs_logos/DEN.png
|
||||||
|
assets/sports/ncaa_fbs_logos/DEP.png
|
||||||
|
assets/sports/ncaa_fbs_logos/DIC.png
|
||||||
|
assets/sports/ncaa_fbs_logos/DRKE.png
|
||||||
|
assets/sports/ncaa_fbs_logos/DSU.png
|
||||||
|
assets/sports/ncaa_fbs_logos/DUB.png
|
||||||
|
assets/sports/ncaa_fbs_logos/DUQ.png
|
||||||
|
assets/sports/ncaa_fbs_logos/EAS.png
|
||||||
|
assets/sports/ncaa_fbs_logos/EDI.png
|
||||||
|
assets/sports/ncaa_fbs_logos/EIU.png
|
||||||
|
assets/sports/ncaa_fbs_logos/EKU.png
|
||||||
|
assets/sports/ncaa_fbs_logos/ELI.png
|
||||||
|
assets/sports/ncaa_fbs_logos/ELM.png
|
||||||
|
assets/sports/ncaa_fbs_logos/ELON.png
|
||||||
|
assets/sports/ncaa_fbs_logos/EMO.png
|
||||||
|
assets/sports/ncaa_fbs_logos/EMP.png
|
||||||
|
assets/sports/ncaa_fbs_logos/END.png
|
||||||
|
assets/sports/ncaa_fbs_logos/EOR.png
|
||||||
|
assets/sports/ncaa_fbs_logos/ETSU.png
|
||||||
|
assets/sports/ncaa_fbs_logos/EUR.png
|
||||||
|
assets/sports/ncaa_fbs_logos/EWU.png
|
||||||
|
assets/sports/ncaa_fbs_logos/FAY.png
|
||||||
|
assets/sports/ncaa_fbs_logos/FDU.png
|
||||||
|
assets/sports/ncaa_fbs_logos/FER.png
|
||||||
|
assets/sports/ncaa_fbs_logos/FIN.png
|
||||||
|
assets/sports/ncaa_fbs_logos/FIT.png
|
||||||
|
assets/sports/ncaa_fbs_logos/FLA.png
|
||||||
|
assets/sports/ncaa_fbs_logos/FOR.png
|
||||||
|
assets/sports/ncaa_fbs_logos/FRA.png
|
||||||
|
assets/sports/ncaa_fbs_logos/FRO.png
|
||||||
|
assets/sports/ncaa_fbs_logos/FRST.png
|
||||||
|
assets/sports/ncaa_fbs_logos/FTLW.png
|
||||||
|
assets/sports/ncaa_fbs_logos/FUR.png
|
||||||
|
assets/sports/ncaa_fbs_logos/GAL.png
|
||||||
|
assets/sports/ncaa_fbs_logos/GAN.png
|
||||||
|
assets/sports/ncaa_fbs_logos/GEN.png
|
||||||
|
assets/sports/ncaa_fbs_logos/GEO.png
|
||||||
|
assets/sports/ncaa_fbs_logos/GET.png
|
||||||
|
assets/sports/ncaa_fbs_logos/GLE.png
|
||||||
|
assets/sports/ncaa_fbs_logos/GMU.png
|
||||||
|
assets/sports/ncaa_fbs_logos/GRA.png
|
||||||
|
assets/sports/ncaa_fbs_logos/GRE.png
|
||||||
|
assets/sports/ncaa_fbs_logos/GRI.png
|
||||||
|
assets/sports/ncaa_fbs_logos/GRO.png
|
||||||
|
assets/sports/ncaa_fbs_logos/GUI.png
|
||||||
|
assets/sports/ncaa_fbs_logos/GWEB.png
|
||||||
|
assets/sports/ncaa_fbs_logos/HAM.png
|
||||||
|
assets/sports/ncaa_fbs_logos/HAMP.png
|
||||||
|
assets/sports/ncaa_fbs_logos/HAN.png
|
||||||
|
assets/sports/ncaa_fbs_logos/HAR.png
|
||||||
|
assets/sports/ncaa_fbs_logos/HARV.png
|
||||||
|
assets/sports/ncaa_fbs_logos/HAS.png
|
||||||
|
assets/sports/ncaa_fbs_logos/HAW.png
|
||||||
|
assets/sports/ncaa_fbs_logos/HBU.png
|
||||||
|
assets/sports/ncaa_fbs_logos/HC.png
|
||||||
|
assets/sports/ncaa_fbs_logos/HEI.png
|
||||||
|
assets/sports/ncaa_fbs_logos/HEN.png
|
||||||
|
assets/sports/ncaa_fbs_logos/HIL.png
|
||||||
|
assets/sports/ncaa_fbs_logos/HIR.png
|
||||||
|
assets/sports/ncaa_fbs_logos/HOB.png
|
||||||
|
assets/sports/ncaa_fbs_logos/HOW.png
|
||||||
|
assets/sports/ncaa_fbs_logos/HUS.png
|
||||||
|
assets/sports/ncaa_fbs_logos/IDHO.png
|
||||||
|
assets/sports/ncaa_fbs_logos/IDST.png
|
||||||
|
assets/sports/ncaa_fbs_logos/ILST.png
|
||||||
|
assets/sports/ncaa_fbs_logos/ILW.png
|
||||||
|
assets/sports/ncaa_fbs_logos/IND.png
|
||||||
|
assets/sports/ncaa_fbs_logos/INST.png
|
||||||
|
assets/sports/ncaa_fbs_logos/IOW.png
|
||||||
|
assets/sports/ncaa_fbs_logos/ITH.png
|
||||||
|
assets/sports/ncaa_fbs_logos/JKST.png
|
||||||
|
assets/sports/ncaa_fbs_logos/JOH.png
|
||||||
|
assets/sports/ncaa_fbs_logos/JUN.png
|
||||||
|
assets/sports/ncaa_fbs_logos/KAL.png
|
||||||
|
assets/sports/ncaa_fbs_logos/KAN.png
|
||||||
|
assets/sports/ncaa_fbs_logos/KEN.png
|
||||||
|
assets/sports/ncaa_fbs_logos/KIN.png
|
||||||
|
assets/sports/ncaa_fbs_logos/KNO.png
|
||||||
|
assets/sports/ncaa_fbs_logos/KUT.png
|
||||||
|
assets/sports/ncaa_fbs_logos/KYST.png
|
||||||
|
assets/sports/ncaa_fbs_logos/KYW.png
|
||||||
|
assets/sports/ncaa_fbs_logos/LA.png
|
||||||
|
assets/sports/ncaa_fbs_logos/LAG.png
|
||||||
|
assets/sports/ncaa_fbs_logos/LAK.png
|
||||||
|
assets/sports/ncaa_fbs_logos/LAM.png
|
||||||
|
assets/sports/ncaa_fbs_logos/LAN.png
|
||||||
|
assets/sports/ncaa_fbs_logos/LAW.png
|
||||||
|
assets/sports/ncaa_fbs_logos/LEB.png
|
||||||
|
assets/sports/ncaa_fbs_logos/LEH.png
|
||||||
|
assets/sports/ncaa_fbs_logos/LEN.png
|
||||||
|
assets/sports/ncaa_fbs_logos/LEW.png
|
||||||
|
assets/sports/ncaa_fbs_logos/LIM.png
|
||||||
|
assets/sports/ncaa_fbs_logos/LIN.png
|
||||||
|
assets/sports/ncaa_fbs_logos/LOC.png
|
||||||
|
assets/sports/ncaa_fbs_logos/LOR.png
|
||||||
|
assets/sports/ncaa_fbs_logos/LUT.png
|
||||||
|
assets/sports/ncaa_fbs_logos/LYC.png
|
||||||
|
assets/sports/ncaa_fbs_logos/M-OH.png
|
||||||
|
assets/sports/ncaa_fbs_logos/MAC.png
|
||||||
|
assets/sports/ncaa_fbs_logos/MAI.png
|
||||||
|
assets/sports/ncaa_fbs_logos/MAN.png
|
||||||
|
assets/sports/ncaa_fbs_logos/MAR.png
|
||||||
|
assets/sports/ncaa_fbs_logos/MAS.png
|
||||||
|
assets/sports/ncaa_fbs_logos/MAY.png
|
||||||
|
assets/sports/ncaa_fbs_logos/MCM.png
|
||||||
|
assets/sports/ncaa_fbs_logos/MCN.png
|
||||||
|
assets/sports/ncaa_fbs_logos/MEN.png
|
||||||
|
assets/sports/ncaa_fbs_logos/MER.png
|
||||||
|
assets/sports/ncaa_fbs_logos/MERC.png
|
||||||
|
assets/sports/ncaa_fbs_logos/MES.png
|
||||||
|
assets/sports/ncaa_fbs_logos/MET.png
|
||||||
|
assets/sports/ncaa_fbs_logos/MH.png
|
||||||
|
assets/sports/ncaa_fbs_logos/MID.png
|
||||||
|
assets/sports/ncaa_fbs_logos/MIL.png
|
||||||
|
assets/sports/ncaa_fbs_logos/MIN.png
|
||||||
|
assets/sports/ncaa_fbs_logos/MIS.png
|
||||||
|
assets/sports/ncaa_fbs_logos/MNST.png
|
||||||
|
assets/sports/ncaa_fbs_logos/MONM.png
|
||||||
|
assets/sports/ncaa_fbs_logos/MONT.png
|
||||||
|
assets/sports/ncaa_fbs_logos/MOR.png
|
||||||
|
assets/sports/ncaa_fbs_logos/MORE.png
|
||||||
|
assets/sports/ncaa_fbs_logos/MORG.png
|
||||||
|
assets/sports/ncaa_fbs_logos/MOU.png
|
||||||
|
assets/sports/ncaa_fbs_logos/MRST.png
|
||||||
|
assets/sports/ncaa_fbs_logos/MSU.png
|
||||||
|
assets/sports/ncaa_fbs_logos/MTST.png
|
||||||
|
assets/sports/ncaa_fbs_logos/MTU.png
|
||||||
|
assets/sports/ncaa_fbs_logos/MUH.png
|
||||||
|
assets/sports/ncaa_fbs_logos/MUR.png
|
||||||
|
assets/sports/ncaa_fbs_logos/MUS.png
|
||||||
|
assets/sports/ncaa_fbs_logos/MVSU.png
|
||||||
|
assets/sports/ncaa_fbs_logos/NAU.png
|
||||||
|
assets/sports/ncaa_fbs_logos/NBY.png
|
||||||
|
assets/sports/ncaa_fbs_logos/NCAT.png
|
||||||
|
assets/sports/ncaa_fbs_logos/NCCU.png
|
||||||
|
assets/sports/ncaa_fbs_logos/NCST.png
|
||||||
|
assets/sports/ncaa_fbs_logos/NDOH.png
|
||||||
|
assets/sports/ncaa_fbs_logos/NDSU.png
|
||||||
|
assets/sports/ncaa_fbs_logos/NH.png
|
||||||
|
assets/sports/ncaa_fbs_logos/NICH.png
|
||||||
|
assets/sports/ncaa_fbs_logos/NMH.png
|
||||||
|
assets/sports/ncaa_fbs_logos/NMI.png
|
||||||
|
assets/sports/ncaa_fbs_logos/NOR.png
|
||||||
|
assets/sports/ncaa_fbs_logos/NORF.png
|
||||||
|
assets/sports/ncaa_fbs_logos/OBE.png
|
||||||
|
assets/sports/ncaa_fbs_logos/OHI.png
|
||||||
|
assets/sports/ncaa_fbs_logos/OKL.png
|
||||||
|
assets/sports/ncaa_fbs_logos/OLI.png
|
||||||
|
assets/sports/ncaa_fbs_logos/OMA.png
|
||||||
|
assets/sports/ncaa_fbs_logos/OTT.png
|
||||||
|
assets/sports/ncaa_fbs_logos/PAC.png
|
||||||
|
assets/sports/ncaa_fbs_logos/PENN.png
|
||||||
|
assets/sports/ncaa_fbs_logos/PIKE.png
|
||||||
|
assets/sports/ncaa_fbs_logos/PRE.png
|
||||||
|
assets/sports/ncaa_fbs_logos/PRI.png
|
||||||
|
assets/sports/ncaa_fbs_logos/PRIN.png
|
||||||
|
assets/sports/ncaa_fbs_logos/PST.png
|
||||||
|
assets/sports/ncaa_fbs_logos/RED.png
|
||||||
|
assets/sports/ncaa_fbs_logos/RICH.png
|
||||||
|
assets/sports/ncaa_fbs_logos/RIT.png
|
||||||
|
assets/sports/ncaa_fbs_logos/ROB.png
|
||||||
|
assets/sports/ncaa_fbs_logos/ROS.png
|
||||||
|
assets/sports/ncaa_fbs_logos/SAC.png
|
||||||
|
assets/sports/ncaa_fbs_logos/SAG.png
|
||||||
|
assets/sports/ncaa_fbs_logos/SDAK.png
|
||||||
|
assets/sports/ncaa_fbs_logos/SET.png
|
||||||
|
assets/sports/ncaa_fbs_logos/SIU.png
|
||||||
|
assets/sports/ncaa_fbs_logos/SLI.png
|
||||||
|
assets/sports/ncaa_fbs_logos/SOU.png
|
||||||
|
assets/sports/ncaa_fbs_logos/SPR.png
|
||||||
|
assets/sports/ncaa_fbs_logos/ST.png
|
||||||
|
assets/sports/ncaa_fbs_logos/STE.png
|
||||||
|
assets/sports/ncaa_fbs_logos/STET.png
|
||||||
|
assets/sports/ncaa_fbs_logos/STO.png
|
||||||
|
assets/sports/ncaa_fbs_logos/SUS.png
|
||||||
|
assets/sports/ncaa_fbs_logos/SUU.png
|
||||||
|
assets/sports/ncaa_fbs_logos/TA&M.png
|
||||||
|
assets/sports/ncaa_fbs_logos/TAY.png
|
||||||
|
assets/sports/ncaa_fbs_logos/TIF.png
|
||||||
|
assets/sports/ncaa_fbs_logos/TRI.png
|
||||||
|
assets/sports/ncaa_fbs_logos/TUF.png
|
||||||
|
assets/sports/ncaa_fbs_logos/TXST.png
|
||||||
|
assets/sports/ncaa_fbs_logos/UAPB.png
|
||||||
|
assets/sports/ncaa_fbs_logos/UCD.png
|
||||||
|
assets/sports/ncaa_fbs_logos/UCONN.png
|
||||||
|
assets/sports/ncaa_fbs_logos/ULM.png
|
||||||
|
assets/sports/ncaa_fbs_logos/UMD.png
|
||||||
|
assets/sports/ncaa_fbs_logos/UMDA.png
|
||||||
|
assets/sports/ncaa_fbs_logos/UML.png
|
||||||
|
assets/sports/ncaa_fbs_logos/UNA.png
|
||||||
|
assets/sports/ncaa_fbs_logos/UNCO.png
|
||||||
|
assets/sports/ncaa_fbs_logos/UND.png
|
||||||
|
assets/sports/ncaa_fbs_logos/UNH.png
|
||||||
|
assets/sports/ncaa_fbs_logos/UNI.png
|
||||||
|
assets/sports/ncaa_fbs_logos/UNNY.png
|
||||||
|
assets/sports/ncaa_fbs_logos/UNT.png
|
||||||
|
assets/sports/ncaa_fbs_logos/UPP.png
|
||||||
|
assets/sports/ncaa_fbs_logos/URI.png
|
||||||
|
assets/sports/ncaa_fbs_logos/USA.png
|
||||||
|
assets/sports/ncaa_fbs_logos/USD.png
|
||||||
|
assets/sports/ncaa_fbs_logos/UTC.png
|
||||||
|
assets/sports/ncaa_fbs_logos/UTI.png
|
||||||
|
assets/sports/ncaa_fbs_logos/VAL.png
|
||||||
|
assets/sports/ncaa_fbs_logos/VILL.png
|
||||||
|
assets/sports/ncaa_fbs_logos/VIR.png
|
||||||
|
assets/sports/ncaa_fbs_logos/VT.png
|
||||||
|
assets/sports/ncaa_fbs_logos/WAB.png
|
||||||
|
assets/sports/ncaa_fbs_logos/WAS.png
|
||||||
|
assets/sports/ncaa_fbs_logos/WAY.png
|
||||||
|
assets/sports/ncaa_fbs_logos/WES.png
|
||||||
|
assets/sports/ncaa_fbs_logos/WHE.png
|
||||||
|
assets/sports/ncaa_fbs_logos/WIL.png
|
||||||
|
assets/sports/ncaa_fbs_logos/WIN.png
|
||||||
|
assets/sports/ncaa_fbs_logos/WIS.png
|
||||||
|
assets/sports/ncaa_fbs_logos/WOR.png
|
||||||
|
assets/sports/ncaa_fbs_logos/YALE.png
|
||||||
|
assets/sports/nhl_logos/ARI.png
|
||||||
|
assets/sports/nhl_logos/VGS.png
|
||||||
|
assets/sports/soccer_logos/DOR.png
|
||||||
|
assets/sports/soccer_logos/KOL.png
|
||||||
|
assets/sports/soccer_logos/LEV.png
|
||||||
|
assets/sports/soccer_logos/STU.png
|
||||||
|
assets/sports/soccer_logos/LYON.png
|
||||||
|
assets/sports/soccer_logos/MAR.png
|
||||||
|
assets/sports/soccer_logos/NICE.png
|
||||||
|
assets/sports/soccer_logos/PSG.png
|
||||||
|
assets/sports/soccer_logos/BUR.png
|
||||||
|
assets/sports/soccer_logos/LUT.png
|
||||||
|
assets/sports/soccer_logos/SHU.png
|
||||||
202
of_the_day/bible_verse_of_the_day.json
Normal file
@@ -0,0 +1,202 @@
|
|||||||
|
{
|
||||||
|
"1": {
|
||||||
|
"title": "John 1:1",
|
||||||
|
"subtitle": "In the beginning was the Word",
|
||||||
|
"description": "A powerful reminder of the eternal nature of Christ."
|
||||||
|
},
|
||||||
|
"2": {
|
||||||
|
"title": "Romans 8:28",
|
||||||
|
"subtitle": "All things work together for good",
|
||||||
|
"description": "An encouragement to trust in God's plan even in difficult circumstances."
|
||||||
|
},
|
||||||
|
"3": {
|
||||||
|
"title": "Psalm 23:1",
|
||||||
|
"subtitle": "The Lord is my shepherd",
|
||||||
|
"description": "A comforting verse reminding us of God's provision and guidance."
|
||||||
|
},
|
||||||
|
"4": {
|
||||||
|
"title": "Isaiah 41:10",
|
||||||
|
"subtitle": "Do not fear, for I am with you",
|
||||||
|
"description": "God’s promise to always be with us, no matter the challenge."
|
||||||
|
},
|
||||||
|
"5": {
|
||||||
|
"title": "Matthew 28:6",
|
||||||
|
"subtitle": "He is not here; He has risen",
|
||||||
|
"description": "The Easter verse that celebrates Christ's victory over death."
|
||||||
|
},
|
||||||
|
"6": {
|
||||||
|
"title": "John 3:16",
|
||||||
|
"subtitle": "For God so loved the world",
|
||||||
|
"description": "A verse that captures the essence of God’s love for mankind."
|
||||||
|
},
|
||||||
|
"7": {
|
||||||
|
"title": "Philippians 4:13",
|
||||||
|
"subtitle": "I can do all things through Christ",
|
||||||
|
"description": "A reminder of the strength we have through Christ."
|
||||||
|
},
|
||||||
|
"8": {
|
||||||
|
"title": "Matthew 5:14",
|
||||||
|
"subtitle": "You are the light of the world",
|
||||||
|
"description": "Jesus calls His followers to be a beacon of light in the darkness."
|
||||||
|
},
|
||||||
|
"9": {
|
||||||
|
"title": "Romans 12:2",
|
||||||
|
"subtitle": "Do not conform to the pattern of this world",
|
||||||
|
"description": "A challenge to live distinctively as believers, transformed by God's word."
|
||||||
|
},
|
||||||
|
"10": {
|
||||||
|
"title": "Luke 2:11",
|
||||||
|
"subtitle": "For unto you is born this day in the city of David a Savior",
|
||||||
|
"description": "A verse marking the birth of Jesus, fitting for Christmas Day."
|
||||||
|
},
|
||||||
|
"11": {
|
||||||
|
"title": "Proverbs 3:5-6",
|
||||||
|
"subtitle": "Trust in the Lord with all your heart",
|
||||||
|
"description": "A call to trust fully in God's direction in our lives."
|
||||||
|
},
|
||||||
|
"12": {
|
||||||
|
"title": "Jeremiah 29:11",
|
||||||
|
"subtitle": "I know the plans I have for you",
|
||||||
|
"description": "A verse of encouragement about God's good plans for us."
|
||||||
|
},
|
||||||
|
"13": {
|
||||||
|
"title": "Isaiah 40:31",
|
||||||
|
"subtitle": "But those who hope in the Lord will renew their strength",
|
||||||
|
"description": "A reminder that God provides the strength we need when we wait on Him."
|
||||||
|
},
|
||||||
|
"14": {
|
||||||
|
"title": "Luke 1:37",
|
||||||
|
"subtitle": "For no word from God will ever fail",
|
||||||
|
"description": "A powerful affirmation of God’s faithfulness."
|
||||||
|
},
|
||||||
|
"15": {
|
||||||
|
"title": "1 Peter 5:7",
|
||||||
|
"subtitle": "Cast all your anxiety on Him",
|
||||||
|
"description": "God cares for us and invites us to bring our burdens to Him."
|
||||||
|
},
|
||||||
|
"16": {
|
||||||
|
"title": "Matthew 11:28",
|
||||||
|
"subtitle": "Come to me, all you who are weary and burdened",
|
||||||
|
"description": "Jesus' invitation to find rest in Him."
|
||||||
|
},
|
||||||
|
"17": {
|
||||||
|
"title": "Psalm 46:1",
|
||||||
|
"subtitle": "God is our refuge and strength",
|
||||||
|
"description": "A verse that assures us of God’s protection and strength."
|
||||||
|
},
|
||||||
|
"18": {
|
||||||
|
"title": "John 14:6",
|
||||||
|
"subtitle": "I am the way and the truth and the life",
|
||||||
|
"description": "Jesus boldly declares He is the only way to the Father."
|
||||||
|
},
|
||||||
|
"19": {
|
||||||
|
"title": "1 Corinthians 13:4-7",
|
||||||
|
"subtitle": "Love is patient, love is kind",
|
||||||
|
"description": "A beautiful description of what true love looks like."
|
||||||
|
},
|
||||||
|
"20": {
|
||||||
|
"title": "1 Timothy 4:12",
|
||||||
|
"subtitle": "Let no one despise your youth",
|
||||||
|
"description": "A call to young people to live boldly and with purpose for the Lord."
|
||||||
|
},
|
||||||
|
"21": {
|
||||||
|
"title": "Psalm 19:1",
|
||||||
|
"subtitle": "The heavens declare the glory of God",
|
||||||
|
"description": "A verse celebrating the majesty of God revealed in creation."
|
||||||
|
},
|
||||||
|
"22": {
|
||||||
|
"title": "Ephesians 6:10-11",
|
||||||
|
"subtitle": "Put on the full armor of God",
|
||||||
|
"description": "A call to be spiritually equipped for battle."
|
||||||
|
},
|
||||||
|
"23": {
|
||||||
|
"title": "2 Corinthians 5:17",
|
||||||
|
"subtitle": "Therefore, if anyone is in Christ, the new creation has come",
|
||||||
|
"description": "A reminder of our new identity in Christ."
|
||||||
|
},
|
||||||
|
"24": {
|
||||||
|
"title": "1 John 4:19",
|
||||||
|
"subtitle": "We love because He first loved us",
|
||||||
|
"description": "The foundation of our love for others is God’s love for us."
|
||||||
|
},
|
||||||
|
"25": {
|
||||||
|
"title": "Revelation 21:4",
|
||||||
|
"subtitle": "He will wipe every tear from their eyes",
|
||||||
|
"description": "A verse offering hope of a future without pain or sorrow."
|
||||||
|
},
|
||||||
|
"26": {
|
||||||
|
"title": "Matthew 6:33",
|
||||||
|
"subtitle": "Seek first His kingdom and His righteousness",
|
||||||
|
"description": "A call to prioritize God’s kingdom over everything else."
|
||||||
|
},
|
||||||
|
"27": {
|
||||||
|
"title": "Isaiah 55:8-9",
|
||||||
|
"subtitle": "For My thoughts are not your thoughts",
|
||||||
|
"description": "A reminder that God’s ways are higher than ours."
|
||||||
|
},
|
||||||
|
"28": {
|
||||||
|
"title": "1 John 3:16",
|
||||||
|
"subtitle": "This is how we know what love is",
|
||||||
|
"description": "The ultimate demonstration of love was Christ’s sacrifice for us."
|
||||||
|
},
|
||||||
|
"29": {
|
||||||
|
"title": "Romans 15:13",
|
||||||
|
"subtitle": "May the God of hope fill you with all joy and peace",
|
||||||
|
"description": "A prayer for joy and peace that comes from God."
|
||||||
|
},
|
||||||
|
"30": {
|
||||||
|
"title": "Mark 10:27",
|
||||||
|
"subtitle": "With man it is impossible, but not with God",
|
||||||
|
"description": "A verse reminding us of God's limitless power."
|
||||||
|
},
|
||||||
|
"31": {
|
||||||
|
"title": "Luke 10:19",
|
||||||
|
"subtitle": "I have given you authority to trample on snakes and scorpions",
|
||||||
|
"description": "Jesus assures us of His authority over evil."
|
||||||
|
},
|
||||||
|
"32": {
|
||||||
|
"title": "Psalm 139:14",
|
||||||
|
"subtitle": "I am fearfully and wonderfully made",
|
||||||
|
"description": "A verse celebrating our unique design and value in God's eyes."
|
||||||
|
},
|
||||||
|
"33": {
|
||||||
|
"title": "Matthew 7:7",
|
||||||
|
"subtitle": "Ask and it will be given to you",
|
||||||
|
"description": "An invitation to pray and trust in God’s generosity."
|
||||||
|
},
|
||||||
|
"34": {
|
||||||
|
"title": "Romans 6:23",
|
||||||
|
"subtitle": "For the wages of sin is death, but the gift of God is eternal life",
|
||||||
|
"description": "A reminder of the contrast between sin’s consequences and God’s gift of life."
|
||||||
|
},
|
||||||
|
"35": {
|
||||||
|
"title": "Hebrews 12:1",
|
||||||
|
"subtitle": "Let us run with perseverance the race marked out for us",
|
||||||
|
"description": "A call to persevere in the Christian journey."
|
||||||
|
},
|
||||||
|
"36": {
|
||||||
|
"title": "Psalm 34:8",
|
||||||
|
"subtitle": "Taste and see that the Lord is good",
|
||||||
|
"description": "A verse inviting us to experience God’s goodness."
|
||||||
|
},
|
||||||
|
"37": {
|
||||||
|
"title": "2 Timothy 1:7",
|
||||||
|
"subtitle": "For the Spirit God gave us does not make us timid",
|
||||||
|
"description": "A reminder that God has given us power, love, and self-discipline."
|
||||||
|
},
|
||||||
|
"38": {
|
||||||
|
"title": "Titus 2:7",
|
||||||
|
"subtitle": "In everything set them an example by doing what is good",
|
||||||
|
"description": "A call to be a godly example in every area of life."
|
||||||
|
},
|
||||||
|
"39": {
|
||||||
|
"title": "Exodus 14:14",
|
||||||
|
"subtitle": "The Lord will fight for you; you need only to be still",
|
||||||
|
"description": "A verse that reminds us to trust in God’s battle for us."
|
||||||
|
},
|
||||||
|
"40": {
|
||||||
|
"title": "2 Corinthians 4:18",
|
||||||
|
"subtitle": "So we fix our eyes not on what is seen, but on what is unseen",
|
||||||
|
"description": "A reminder to focus on eternal, unseen things rather than temporary challenges."
|
||||||
|
}
|
||||||
|
}
|
||||||
23
requirements_web_v2.txt
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
flask>=2.3.0
|
||||||
|
flask-socketio>=5.3.0
|
||||||
|
python-socketio>=5.8.0
|
||||||
|
eventlet>=0.33.3
|
||||||
|
Pillow>=10.0.0
|
||||||
|
psutil>=5.9.0
|
||||||
|
werkzeug>=2.3.0
|
||||||
|
freetype-py>=2.3.0
|
||||||
|
numpy>=1.21.0
|
||||||
|
requests>=2.25.0
|
||||||
|
python-dateutil>=2.8.0
|
||||||
|
pytz==2023.3
|
||||||
|
timezonefinder==6.2.0
|
||||||
|
geopy==2.4.1
|
||||||
|
google-auth-oauthlib==1.0.0
|
||||||
|
google-auth-httplib2==0.1.0
|
||||||
|
google-api-python-client==2.86.0
|
||||||
|
spotipy
|
||||||
|
unidecode
|
||||||
|
icalevents
|
||||||
|
python-engineio
|
||||||
|
websockets
|
||||||
|
websocket-client
|
||||||
24
run_web_v2.sh
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# LED Matrix Web Interface V2 Runner
|
||||||
|
# This script runs the web interface using system Python
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Get the directory where this script is located
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
cd "$SCRIPT_DIR"
|
||||||
|
|
||||||
|
echo "Setting up LED Matrix Web Interface V2..."
|
||||||
|
|
||||||
|
# Install dependencies using system Python
|
||||||
|
echo "Installing dependencies..."
|
||||||
|
python3 -m pip install --break-system-packages -r requirements_web_v2.txt
|
||||||
|
|
||||||
|
# Install rgbmatrix module from local source
|
||||||
|
echo "Installing rgbmatrix module..."
|
||||||
|
python3 -m pip install --break-system-packages -e rpi-rgb-led-matrix-master/bindings/python
|
||||||
|
|
||||||
|
# Run the web interface
|
||||||
|
echo "Starting web interface on http://0.0.0.0:5001"
|
||||||
|
python3 web_interface_v2.py
|
||||||