discstation 0.1.23 → 0.1.27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +43 -8
- package/arduino/c6/DiscStation_C6.ino +293 -84
- package/arduino/c6/secrets.h.example +14 -0
- package/arduino/v1/DiscStation.ino +214 -65
- package/arduino/v1/secrets.h.example +14 -0
- package/discstation.env.example +7 -0
- package/package.json +1 -1
- package/requirements.txt +1 -0
- package/src/discstation.py +150 -15
- package/src/discstation_burn.py +9 -0
- package/src/discstation_host.py +84 -0
|
@@ -3,9 +3,20 @@
|
|
|
3
3
|
#include <Adafruit_SSD1306.h>
|
|
4
4
|
#include "esp_task_wdt.h"
|
|
5
5
|
#include <WiFi.h>
|
|
6
|
+
#include "esp_mac.h"
|
|
7
|
+
#include <WiFiManager.h>
|
|
8
|
+
#include <ESPmDNS.h>
|
|
9
|
+
#include <Preferences.h>
|
|
6
10
|
#include <ArduinoOTA.h>
|
|
7
11
|
#include <QRCode.h>
|
|
8
12
|
|
|
13
|
+
// Optional build-time Wi-Fi override for power users: copy secrets.h.example
|
|
14
|
+
// to secrets.h (git-ignored) and set WIFI_SSID / WIFI_PASS / OTA_PASSWORD.
|
|
15
|
+
// If WIFI_SSID is defined the runtime setup portal is skipped entirely.
|
|
16
|
+
#if __has_include("secrets.h")
|
|
17
|
+
#include "secrets.h"
|
|
18
|
+
#endif
|
|
19
|
+
|
|
9
20
|
#define SCREEN_WIDTH 128
|
|
10
21
|
#define SCREEN_HEIGHT 64
|
|
11
22
|
#define OLED_RESET -1
|
|
@@ -14,8 +25,6 @@
|
|
|
14
25
|
#define BTN_SELECT_PIN 14
|
|
15
26
|
#define BTN_UP_PIN 13
|
|
16
27
|
#define BTN_DOWN_PIN 15
|
|
17
|
-
#define LED_POWER_PIN 32
|
|
18
|
-
#define LED_ACT_PIN 33
|
|
19
28
|
#define POT_PIN 34
|
|
20
29
|
|
|
21
30
|
#define DEBOUNCE_MS 50
|
|
@@ -23,8 +32,12 @@
|
|
|
23
32
|
#define POT_READ_MS 200
|
|
24
33
|
#define DONE_RESET_MS 30000
|
|
25
34
|
#define STANDBY_BLANK_MS 60000
|
|
35
|
+
#define IDLE_BLANK_MS 45000 // blank the OLED after this long with no input on HOME/STANDBY
|
|
26
36
|
#define PING_TIMEOUT_MS 30000
|
|
27
|
-
|
|
37
|
+
|
|
38
|
+
#define WIFI_RESET_HOLD_MS 10000 // hold SELECT this long on HOME to wipe Wi-Fi creds
|
|
39
|
+
#define WIFI_CONNECT_TIMEOUT_MS 18000 // give a stored-creds join this long before falling to the portal
|
|
40
|
+
#define WIFI_RETRY_MS 15000 // if a live link drops, force a re-join after this
|
|
28
41
|
|
|
29
42
|
#define MAX_HOME_MODES 5
|
|
30
43
|
#define BURN_COUNT 4
|
|
@@ -36,8 +49,17 @@ String homeModes[MAX_HOME_MODES] = {"BURN", "PLAY", "RIP"};
|
|
|
36
49
|
|
|
37
50
|
WiFiServer tcpServer(TCP_PORT);
|
|
38
51
|
WiFiClient tcpClient;
|
|
52
|
+
WiFiManager wm;
|
|
53
|
+
Preferences prefs;
|
|
39
54
|
bool wifiConnected = false;
|
|
40
55
|
bool wifiInitDone = false;
|
|
56
|
+
bool portalActive = false;
|
|
57
|
+
bool otaEnabled = false;
|
|
58
|
+
bool credsJustSaved = false;
|
|
59
|
+
bool wifiResetArmed = false;
|
|
60
|
+
unsigned long wifiDropAt = 0;
|
|
61
|
+
String apName = "DiscStation";
|
|
62
|
+
String mdnsHost = "discstation";
|
|
41
63
|
|
|
42
64
|
class DualPrint : public Print {
|
|
43
65
|
public:
|
|
@@ -56,23 +78,105 @@ private:
|
|
|
56
78
|
WiFiClient* _client = nullptr;
|
|
57
79
|
} Out;
|
|
58
80
|
|
|
81
|
+
void drawSetup(); // fwd decls (defined with the other draw* below)
|
|
82
|
+
void drawWifiReset();
|
|
83
|
+
|
|
84
|
+
String deviceSuffix() {
|
|
85
|
+
uint8_t mac[6];
|
|
86
|
+
esp_read_mac(mac, ESP_MAC_WIFI_STA); // factory MAC from eFuse - valid before the Wi-Fi driver starts
|
|
87
|
+
char buf[5];
|
|
88
|
+
snprintf(buf, sizeof(buf), "%02X%02X", mac[4], mac[5]);
|
|
89
|
+
return String(buf);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
void loadCreds(String& ssid, String& pass) {
|
|
93
|
+
prefs.begin("discstation", true);
|
|
94
|
+
ssid = prefs.getString("ssid", "");
|
|
95
|
+
pass = prefs.getString("pass", "");
|
|
96
|
+
prefs.end();
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
void saveCreds(const String& ssid, const String& pass) {
|
|
100
|
+
prefs.begin("discstation", false);
|
|
101
|
+
prefs.putString("ssid", ssid);
|
|
102
|
+
prefs.putString("pass", pass);
|
|
103
|
+
prefs.end();
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
void clearCreds() {
|
|
107
|
+
prefs.begin("discstation", false);
|
|
108
|
+
prefs.clear();
|
|
109
|
+
prefs.end();
|
|
110
|
+
WiFi.disconnect(true, true); // also wipe the ESP's own persisted creds
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
void wmSaveCallback() {
|
|
114
|
+
saveCreds(wm.getWiFiSSID(), wm.getWiFiPass());
|
|
115
|
+
credsJustSaved = true; // loop() reboots cleanly into STA mode
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
void onWifiUp() {
|
|
119
|
+
portalActive = false;
|
|
120
|
+
wifiConnected = true;
|
|
121
|
+
wifiDropAt = 0;
|
|
122
|
+
WiFi.setSleep(WIFI_PS_MIN_MODEM);
|
|
123
|
+
tcpServer.begin();
|
|
124
|
+
if (MDNS.begin(mdnsHost.c_str())) {
|
|
125
|
+
MDNS.addService("discstation", "tcp", TCP_PORT);
|
|
126
|
+
}
|
|
127
|
+
#ifdef OTA_PASSWORD
|
|
128
|
+
ArduinoOTA.setHostname(mdnsHost.c_str());
|
|
129
|
+
ArduinoOTA.setPassword(OTA_PASSWORD);
|
|
130
|
+
ArduinoOTA.begin();
|
|
131
|
+
otaEnabled = true;
|
|
132
|
+
#endif
|
|
133
|
+
Out.print("WiFi OK "); Out.println(WiFi.localIP());
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
void startPortal() {
|
|
137
|
+
Out.print("WiFi: setup portal '"); Out.print(apName); Out.println("'");
|
|
138
|
+
portalActive = true;
|
|
139
|
+
WiFi.mode(WIFI_AP_STA);
|
|
140
|
+
wm.setConfigPortalBlocking(false);
|
|
141
|
+
wm.setConfigPortalTimeout(0);
|
|
142
|
+
wm.setSaveConfigCallback(wmSaveCallback);
|
|
143
|
+
wm.startConfigPortal(apName.c_str()); // open AP at 192.168.4.1
|
|
144
|
+
drawSetup();
|
|
145
|
+
}
|
|
146
|
+
|
|
59
147
|
void initWiFi() {
|
|
60
|
-
|
|
148
|
+
apName = "DiscStation-" + deviceSuffix();
|
|
149
|
+
mdnsHost = "discstation-" + deviceSuffix();
|
|
150
|
+
mdnsHost.toLowerCase();
|
|
151
|
+
|
|
61
152
|
WiFi.mode(WIFI_STA);
|
|
62
|
-
WiFi.
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
153
|
+
WiFi.setAutoReconnect(true);
|
|
154
|
+
WiFi.setSleep(WIFI_PS_MIN_MODEM);
|
|
155
|
+
|
|
156
|
+
String ssid, pass;
|
|
157
|
+
#ifdef WIFI_SSID
|
|
158
|
+
ssid = WIFI_SSID;
|
|
159
|
+
pass = WIFI_PASS;
|
|
160
|
+
#else
|
|
161
|
+
loadCreds(ssid, pass);
|
|
162
|
+
#endif
|
|
163
|
+
|
|
164
|
+
if (ssid.length() > 0) {
|
|
165
|
+
Out.print("WiFi "); Out.print(ssid); Out.print("...");
|
|
166
|
+
WiFi.begin(ssid.c_str(), pass.c_str());
|
|
167
|
+
unsigned long t0 = millis();
|
|
168
|
+
while (WiFi.status() != WL_CONNECTED && millis() - t0 < WIFI_CONNECT_TIMEOUT_MS) {
|
|
169
|
+
esp_task_wdt_reset();
|
|
170
|
+
delay(200);
|
|
171
|
+
}
|
|
66
172
|
}
|
|
173
|
+
|
|
67
174
|
if (WiFi.status() == WL_CONNECTED) {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
ArduinoOTA.begin();
|
|
71
|
-
ArduinoOTA.setHostname("discstation-v1");
|
|
72
|
-
ArduinoOTA.setPassword("dvdstation");
|
|
73
|
-
Out.print(" OK "); Out.println(WiFi.localIP());
|
|
175
|
+
Out.println(" OK");
|
|
176
|
+
onWifiUp();
|
|
74
177
|
} else {
|
|
75
|
-
Out.println(" fail");
|
|
178
|
+
if (ssid.length() > 0) Out.println(" fail (2.4GHz band / wrong password?)");
|
|
179
|
+
startPortal();
|
|
76
180
|
}
|
|
77
181
|
}
|
|
78
182
|
String discName = "";
|
|
@@ -89,7 +193,8 @@ enum UiState {
|
|
|
89
193
|
UI_STANDBY,
|
|
90
194
|
UI_WAITING,
|
|
91
195
|
UI_IP,
|
|
92
|
-
UI_DISCONNECTED
|
|
196
|
+
UI_DISCONNECTED,
|
|
197
|
+
UI_SETUP
|
|
93
198
|
};
|
|
94
199
|
|
|
95
200
|
const char* BURN_MODES[BURN_COUNT] = {"AUTO", "BEST", "LONG", "TEST"};
|
|
@@ -133,9 +238,6 @@ unsigned long downLastDebounce = 0;
|
|
|
133
238
|
int ffSpeedIndex = 0;
|
|
134
239
|
int rewSpeedIndex = 0;
|
|
135
240
|
|
|
136
|
-
// LED state
|
|
137
|
-
bool actLedState = false;
|
|
138
|
-
unsigned long lastLedBlink = 0;
|
|
139
241
|
int homeIndex = 0;
|
|
140
242
|
int burnModeIndex = 0;
|
|
141
243
|
int burnSpeedIndex = 0;
|
|
@@ -143,6 +245,7 @@ bool editingSpeed = false;
|
|
|
143
245
|
int playVolume = 50;
|
|
144
246
|
unsigned long standbyStartTime = 0;
|
|
145
247
|
unsigned long lastMsgTime = 0;
|
|
248
|
+
unsigned long lastInputTime = 0; // last button press / screen change; drives OLED idle-blank
|
|
146
249
|
bool displayBlank = false;
|
|
147
250
|
bool audioPlayMode = false;
|
|
148
251
|
int displayRotation = 0;
|
|
@@ -210,6 +313,7 @@ void drawHeader() {
|
|
|
210
313
|
void drawHome() {
|
|
211
314
|
uiState = UI_HOME;
|
|
212
315
|
returnToHomeAt = 0;
|
|
316
|
+
lastInputTime = millis();
|
|
213
317
|
if (!displayOk) return;
|
|
214
318
|
|
|
215
319
|
display.clearDisplay();
|
|
@@ -360,9 +464,13 @@ void drawIP() {
|
|
|
360
464
|
}
|
|
361
465
|
|
|
362
466
|
void drawStandby() {
|
|
467
|
+
// While the Wi-Fi setup portal is up and the appliance is otherwise idle,
|
|
468
|
+
// the standby screen doubles as the setup instructions.
|
|
469
|
+
if (portalActive) { drawSetup(); return; }
|
|
363
470
|
uiState = UI_STANDBY;
|
|
364
471
|
returnToHomeAt = 0;
|
|
365
472
|
standbyStartTime = millis();
|
|
473
|
+
lastInputTime = millis();
|
|
366
474
|
displayBlank = false;
|
|
367
475
|
if (!displayOk) return;
|
|
368
476
|
|
|
@@ -375,6 +483,39 @@ void drawStandby() {
|
|
|
375
483
|
display.display();
|
|
376
484
|
}
|
|
377
485
|
|
|
486
|
+
void drawSetup() {
|
|
487
|
+
uiState = UI_SETUP;
|
|
488
|
+
returnToHomeAt = 0;
|
|
489
|
+
displayBlank = false;
|
|
490
|
+
lastInputTime = millis();
|
|
491
|
+
if (!displayOk) return;
|
|
492
|
+
|
|
493
|
+
display.clearDisplay();
|
|
494
|
+
drawHeader();
|
|
495
|
+
display.setCursor(2, 16);
|
|
496
|
+
display.print("WIFI SETUP");
|
|
497
|
+
display.setCursor(2, 28);
|
|
498
|
+
display.print("JOIN:");
|
|
499
|
+
display.setCursor(2, 38);
|
|
500
|
+
printUpper(apName);
|
|
501
|
+
display.setCursor(2, 50);
|
|
502
|
+
display.print("THEN 192.168.4.1");
|
|
503
|
+
display.display();
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
void drawWifiReset() {
|
|
507
|
+
uiState = UI_SETUP;
|
|
508
|
+
displayBlank = false;
|
|
509
|
+
if (!displayOk) return;
|
|
510
|
+
display.clearDisplay();
|
|
511
|
+
drawHeader();
|
|
512
|
+
display.setCursor(2, 25);
|
|
513
|
+
display.print("WIFI RESET");
|
|
514
|
+
display.setCursor(2, 40);
|
|
515
|
+
display.print("REBOOTING...");
|
|
516
|
+
display.display();
|
|
517
|
+
}
|
|
518
|
+
|
|
378
519
|
void drawDisconnected() {
|
|
379
520
|
uiState = UI_DISCONNECTED;
|
|
380
521
|
returnToHomeAt = 0;
|
|
@@ -403,6 +544,7 @@ void wakeDisplay() {
|
|
|
403
544
|
case UI_WAITING: drawWaiting(); break;
|
|
404
545
|
case UI_STANDBY: drawStandby(); break;
|
|
405
546
|
case UI_DISCONNECTED: drawDisconnected(); break;
|
|
547
|
+
case UI_SETUP: drawSetup(); break;
|
|
406
548
|
}
|
|
407
549
|
}
|
|
408
550
|
|
|
@@ -602,16 +744,13 @@ void parseMessage(String msg) {
|
|
|
602
744
|
}
|
|
603
745
|
|
|
604
746
|
void setup() {
|
|
747
|
+
setCpuFrequencyMhz(160); // 240 -> 160: ~halves CPU power, Wi-Fi/I2C/OTA all fine at 160
|
|
605
748
|
Serial.begin(115200);
|
|
606
749
|
esp_task_wdt_add(NULL);
|
|
607
750
|
Wire.begin(21, 22);
|
|
608
751
|
pinMode(BTN_SELECT_PIN, INPUT_PULLUP);
|
|
609
752
|
pinMode(BTN_UP_PIN, INPUT_PULLUP);
|
|
610
753
|
pinMode(BTN_DOWN_PIN, INPUT_PULLUP);
|
|
611
|
-
pinMode(LED_POWER_PIN, OUTPUT);
|
|
612
|
-
pinMode(LED_ACT_PIN, OUTPUT);
|
|
613
|
-
digitalWrite(LED_POWER_PIN, HIGH);
|
|
614
|
-
digitalWrite(LED_ACT_PIN, LOW);
|
|
615
754
|
pinMode(POT_PIN, INPUT);
|
|
616
755
|
analogReadResolution(12);
|
|
617
756
|
analogSetPinAttenuation(POT_PIN, ADC_11db);
|
|
@@ -629,21 +768,15 @@ void setup() {
|
|
|
629
768
|
delay(3000);
|
|
630
769
|
}
|
|
631
770
|
|
|
632
|
-
// Blink activity LED 3x to confirm it works
|
|
633
|
-
for (int i = 0; i < 3; i++) {
|
|
634
|
-
digitalWrite(LED_ACT_PIN, HIGH);
|
|
635
|
-
delay(150);
|
|
636
|
-
digitalWrite(LED_ACT_PIN, LOW);
|
|
637
|
-
delay(150);
|
|
638
|
-
}
|
|
639
|
-
|
|
640
771
|
drawStandby();
|
|
641
772
|
lastMsgTime = millis();
|
|
773
|
+
lastInputTime = millis();
|
|
642
774
|
Out.println("DISCSTATION_READY");
|
|
643
775
|
}
|
|
644
776
|
|
|
645
777
|
void handleSelectPress(bool longPress) {
|
|
646
778
|
wakeDisplay();
|
|
779
|
+
lastInputTime = millis();
|
|
647
780
|
if (uiState == UI_HOME) {
|
|
648
781
|
if (longPress) {
|
|
649
782
|
Out.println("EJECT");
|
|
@@ -733,6 +866,7 @@ void handleSelectPress(bool longPress) {
|
|
|
733
866
|
|
|
734
867
|
void handleUp(bool longPress) {
|
|
735
868
|
wakeDisplay();
|
|
869
|
+
lastInputTime = millis();
|
|
736
870
|
if (uiState == UI_HOME) {
|
|
737
871
|
if (homeCount > 0) {
|
|
738
872
|
homeIndex = (homeIndex - 1 + homeCount) % homeCount;
|
|
@@ -772,6 +906,7 @@ void handleUp(bool longPress) {
|
|
|
772
906
|
|
|
773
907
|
void handleDown(bool longPress) {
|
|
774
908
|
wakeDisplay();
|
|
909
|
+
lastInputTime = millis();
|
|
775
910
|
if (uiState == UI_HOME) {
|
|
776
911
|
if (homeCount > 0) {
|
|
777
912
|
homeIndex = (homeIndex + 1) % homeCount;
|
|
@@ -814,8 +949,33 @@ void loop() {
|
|
|
814
949
|
wifiInitDone = true;
|
|
815
950
|
initWiFi();
|
|
816
951
|
}
|
|
817
|
-
|
|
818
|
-
|
|
952
|
+
|
|
953
|
+
if (credsJustSaved) { // portal saved new creds -> reboot into clean STA
|
|
954
|
+
drawWifiReset();
|
|
955
|
+
delay(600);
|
|
956
|
+
ESP.restart();
|
|
957
|
+
}
|
|
958
|
+
|
|
959
|
+
if (portalActive) {
|
|
960
|
+
wm.process();
|
|
961
|
+
if (WiFi.status() == WL_CONNECTED) onWifiUp();
|
|
962
|
+
}
|
|
963
|
+
|
|
964
|
+
// Live link dropped: WiFi.setAutoReconnect handles most; if still down after
|
|
965
|
+
// WIFI_RETRY_MS, force a fresh join.
|
|
966
|
+
if (wifiConnected && WiFi.status() != WL_CONNECTED) {
|
|
967
|
+
if (wifiDropAt == 0) wifiDropAt = millis();
|
|
968
|
+
else if (millis() - wifiDropAt > WIFI_RETRY_MS) {
|
|
969
|
+
wifiDropAt = millis();
|
|
970
|
+
WiFi.disconnect();
|
|
971
|
+
WiFi.begin();
|
|
972
|
+
}
|
|
973
|
+
} else if (wifiConnected) {
|
|
974
|
+
wifiDropAt = 0;
|
|
975
|
+
}
|
|
976
|
+
|
|
977
|
+
if (wifiConnected && WiFi.status() == WL_CONNECTED) {
|
|
978
|
+
if (otaEnabled) ArduinoOTA.handle();
|
|
819
979
|
if (tcpServer.hasClient()) {
|
|
820
980
|
if (tcpClient) tcpClient.stop();
|
|
821
981
|
tcpClient = tcpServer.available();
|
|
@@ -865,11 +1025,27 @@ void loop() {
|
|
|
865
1025
|
if (sel && !selectDown && millis() - selectLastDebounce > DEBOUNCE_MS) {
|
|
866
1026
|
selectDown = true;
|
|
867
1027
|
selectDownAt = millis();
|
|
1028
|
+
wifiResetArmed = false;
|
|
1029
|
+
}
|
|
1030
|
+
// 10s hold on HOME (or SETUP) = wipe Wi-Fi creds + reboot to portal. Fires
|
|
1031
|
+
// while still held so the eventual release doesn't also trigger EJECT.
|
|
1032
|
+
if (sel && selectDown && !wifiResetArmed &&
|
|
1033
|
+
(uiState == UI_HOME || uiState == UI_SETUP || uiState == UI_STANDBY) &&
|
|
1034
|
+
millis() - selectDownAt >= WIFI_RESET_HOLD_MS) {
|
|
1035
|
+
wifiResetArmed = true;
|
|
1036
|
+
Out.println("WiFi: creds wiped, rebooting");
|
|
1037
|
+
clearCreds();
|
|
1038
|
+
drawWifiReset();
|
|
1039
|
+
delay(800);
|
|
1040
|
+
ESP.restart();
|
|
868
1041
|
}
|
|
869
1042
|
if (!sel && selectDown) {
|
|
870
1043
|
selectDown = false;
|
|
871
1044
|
selectLastDebounce = millis();
|
|
872
|
-
|
|
1045
|
+
if (!wifiResetArmed) {
|
|
1046
|
+
handleSelectPress(millis() - selectDownAt >= LONG_PRESS_MS);
|
|
1047
|
+
}
|
|
1048
|
+
wifiResetArmed = false;
|
|
873
1049
|
}
|
|
874
1050
|
}
|
|
875
1051
|
|
|
@@ -915,15 +1091,12 @@ void loop() {
|
|
|
915
1091
|
if (!displayBlank) drawStatus();
|
|
916
1092
|
}
|
|
917
1093
|
|
|
918
|
-
// ---
|
|
919
|
-
if (displayOk &&
|
|
920
|
-
(
|
|
1094
|
+
// --- OLED idle blanking (HOME + STANDBY) ---
|
|
1095
|
+
if (displayOk && !displayBlank &&
|
|
1096
|
+
(uiState == UI_HOME || uiState == UI_STANDBY) &&
|
|
1097
|
+
(long)(millis() - lastInputTime) >= IDLE_BLANK_MS) {
|
|
921
1098
|
display.ssd1306_command(0xAE);
|
|
922
1099
|
displayBlank = true;
|
|
923
|
-
digitalWrite(LED_POWER_PIN, LOW);
|
|
924
|
-
}
|
|
925
|
-
if (!displayBlank) {
|
|
926
|
-
digitalWrite(LED_POWER_PIN, HIGH);
|
|
927
1100
|
}
|
|
928
1101
|
|
|
929
1102
|
// --- PING timeout (disconnected) ---
|
|
@@ -932,29 +1105,5 @@ void loop() {
|
|
|
932
1105
|
drawDisconnected();
|
|
933
1106
|
}
|
|
934
1107
|
|
|
935
|
-
// --- Activity LED ---
|
|
936
|
-
{
|
|
937
|
-
bool ledOn = false;
|
|
938
|
-
if (uiState == UI_BURN_READY || uiState == UI_PLAY || uiState == UI_WAITING || uiState == UI_IP) {
|
|
939
|
-
ledOn = true;
|
|
940
|
-
} else if (uiState == UI_STATUS) {
|
|
941
|
-
if (progressPercent >= 0) {
|
|
942
|
-
ledOn = (millis() - lastLedBlink > LED_BLINK_MS);
|
|
943
|
-
if (ledOn) {
|
|
944
|
-
lastLedBlink = millis();
|
|
945
|
-
actLedState = !actLedState;
|
|
946
|
-
}
|
|
947
|
-
ledOn = actLedState;
|
|
948
|
-
} else {
|
|
949
|
-
ledOn = true;
|
|
950
|
-
}
|
|
951
|
-
} else if (uiState == UI_HOME || uiState == UI_STANDBY) {
|
|
952
|
-
ledOn = false;
|
|
953
|
-
} else if (uiState == UI_DISCONNECTED) {
|
|
954
|
-
ledOn = true;
|
|
955
|
-
}
|
|
956
|
-
digitalWrite(LED_ACT_PIN, ledOn ? HIGH : LOW);
|
|
957
|
-
}
|
|
958
|
-
|
|
959
1108
|
delay(20);
|
|
960
1109
|
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// Optional build-time Wi-Fi override for the ESP32 DevKit remote.
|
|
2
|
+
//
|
|
3
|
+
// cp secrets.h.example secrets.h (secrets.h is git-ignored)
|
|
4
|
+
//
|
|
5
|
+
// If WIFI_SSID is defined, the firmware connects straight to this network and
|
|
6
|
+
// the runtime setup portal is skipped entirely. Leave secrets.h absent to use
|
|
7
|
+
// the normal captive-portal provisioning ("DiscStation-XXXX" AP).
|
|
8
|
+
|
|
9
|
+
#define WIFI_SSID "YourNetwork"
|
|
10
|
+
#define WIFI_PASS "YourPassword"
|
|
11
|
+
|
|
12
|
+
// Optional: enable Arduino OTA updates with this password. Omit to keep OTA off
|
|
13
|
+
// (recommended unless you actually use it).
|
|
14
|
+
// #define OTA_PASSWORD "change-me"
|
package/discstation.env.example
CHANGED
|
@@ -7,6 +7,13 @@ YTDLP_FRAGMENT_RETRIES=3
|
|
|
7
7
|
DISC_OUTPUT_LIMIT_BYTES=4300000000
|
|
8
8
|
DISC_DL_OUTPUT_LIMIT_BYTES=8000000000
|
|
9
9
|
|
|
10
|
+
# Wi-Fi appliance remote. Default (unset) = "auto": if no USB cable is
|
|
11
|
+
# present, find the remote by mDNS / discstation.local. Set an IP or
|
|
12
|
+
# hostname to skip discovery (connects on TCP 2323); set "off" to never
|
|
13
|
+
# look. The remote's OLED shows its IP after you provision its Wi-Fi.
|
|
14
|
+
# DISC_REMOTE_HOST=192.168.1.50
|
|
15
|
+
# DISC_REMOTE_HOST=off
|
|
16
|
+
|
|
10
17
|
# TMDb API key for video (DVD / burned movie) metadata lookup. Get a free key at
|
|
11
18
|
# https://www.themoviedb.org/settings/api . Without it, ripped videos keep their
|
|
12
19
|
# disc-label / filename naming. Alternatively put the key in
|
package/package.json
CHANGED
package/requirements.txt
CHANGED