2 Commits

Author SHA1 Message Date
Myx
eb577f6e89 Add serilog 2025-09-27 20:58:43 +02:00
48f7065a9a fix: handle critical bug
Avoid making it get stuck in the main loop
2025-08-14 20:07:06 +02:00
6 changed files with 154 additions and 92 deletions

View File

@@ -124,6 +124,14 @@ jobs:
"Microsoft.AspNetCore" = "Warning" "Microsoft.AspNetCore" = "Warning"
} }
} }
Seq = @{
ServerUrl = "https://log.azaaxin.com"
ApiKey = "KEY"
MinimumLevel = "Trace"
LevelOverride = @{
Microsoft: "Warning"
}
}
ApiConfiguration = @{ ApiConfiguration = @{
EspConfiguration = @{ EspConfiguration = @{
InformationBoardImageUrl = "http://server_ip:port/home/default.jpg" InformationBoardImageUrl = "http://server_ip:port/home/default.jpg"
@@ -178,6 +186,14 @@ jobs:
"Microsoft.AspNetCore" = "Warning" "Microsoft.AspNetCore" = "Warning"
} }
} }
Seq = @{
ServerUrl = ${{ vars.SEQ_URL }}
ApiKey = ${{ secrets.seq_api_key }}
MinimumLevel = "Trace"
LevelOverride = @{
Microsoft: "Warning"
}
}
ApiConfiguration = @{ ApiConfiguration = @{
EspConfiguration = @{ EspConfiguration = @{
InformationBoardImageUrl = "${{ vars.ESP_IMAGE_URL }}" InformationBoardImageUrl = "${{ vars.ESP_IMAGE_URL }}"

View File

@@ -23,7 +23,6 @@ uint64_t sleepDuration = 30e6; // Default 30 seconds in microseconds
#define EPD_HEIGHT EPD_7IN5B_V2_HEIGHT #define EPD_HEIGHT EPD_7IN5B_V2_HEIGHT
// =========== IMAGE TUNING PARAMETERS =========== // =========== IMAGE TUNING PARAMETERS ===========
// These will be updated from the configuration
uint8_t blackTextThreshold = 190; // Default (0-255) uint8_t blackTextThreshold = 190; // Default (0-255)
bool enableDithering = true; // Default bool enableDithering = true; // Default
uint8_t ditherStrength = 8; // Default (8-32) uint8_t ditherStrength = 8; // Default (8-32)
@@ -42,11 +41,49 @@ int16_t *errorB = NULL;
// Create an instance of the JPEG decoder // Create an instance of the JPEG decoder
JPEGDEC jpeg; JPEGDEC jpeg;
// Forward declarations
bool fetchConnectionInformation();
void fetchAndDisplayImage();
void clearDisplay();
// Centralized cleanup + deep sleep
void finishAndSleep(const char* reason) {
Serial.println();
Serial.println("========== Going to deep sleep ==========");
if (reason && reason[0]) {
Serial.print("Reason: ");
Serial.println(reason);
}
// Free dithering buffers if allocated
if (errorR) { free(errorR); errorR = NULL; }
if (errorG) { free(errorG); errorG = NULL; }
if (errorB) { free(errorB); errorB = NULL; }
// Put display to sleep (safe to call even if already sleeping)
EPD_7IN5B_V2_Sleep();
// Free framebuffers
if (BlackImage) { free(BlackImage); BlackImage = NULL; }
if (RYImage) { free(RYImage); RYImage = NULL; }
// Tidy up WiFi to save power before deep sleep
WiFi.disconnect(true, true);
WiFi.mode(WIFI_OFF);
delay(50);
Serial.print("Sleeping for ");
Serial.print(sleepDuration / 60000000);
Serial.println(" minutes");
esp_sleep_enable_timer_wakeup(sleepDuration);
esp_deep_sleep_start();
}
// Apply contrast adjustment to RGB values // Apply contrast adjustment to RGB values
void adjustContrast(uint8_t *r, uint8_t *g, uint8_t *b) { void adjustContrast(uint8_t *r, uint8_t *g, uint8_t *b) {
if (!enhanceContrast) return; if (!enhanceContrast) return;
float contrast = (contrastLevel / 100.0) + 1.0; // Convert to decimal & shift range: [0..2] float contrast = (contrastLevel / 100.0) + 1.0; // [1..2]
float intercept = 128 * (1 - contrast); float intercept = 128 * (1 - contrast);
*r = constrain((*r * contrast) + intercept, 0, 255); *r = constrain((*r * contrast) + intercept, 0, 255);
@@ -240,7 +277,8 @@ void setup() {
if ((BlackImage == NULL) || (RYImage == NULL)) { if ((BlackImage == NULL) || (RYImage == NULL)) {
Serial.println("Failed to allocate memory for framebuffers!"); Serial.println("Failed to allocate memory for framebuffers!");
while(1); // Halt if memory allocation fails // Even on failure, deep-sleep to allow recovery on next boot
finishAndSleep("Framebuffer allocation failed");
} }
// Initialize e-ink display exactly as in Waveshare example // Initialize e-ink display exactly as in Waveshare example
@@ -256,6 +294,7 @@ void setup() {
Serial.println("Buffers allocated and cleared"); Serial.println("Buffers allocated and cleared");
// Connect to WiFi // Connect to WiFi
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password); WiFi.begin(ssid, password);
Serial.print("Connecting to WiFi"); Serial.print("Connecting to WiFi");
int wifiAttempts = 0; int wifiAttempts = 0;
@@ -273,7 +312,8 @@ void setup() {
} else { } else {
Serial.println(); Serial.println();
Serial.println("WiFi connection failed!"); Serial.println("WiFi connection failed!");
return; // IMPORTANT: Do not just return; always deep sleep so we retry later
finishAndSleep("WiFi connection failed");
} }
// Test connectivity to server and get configuration // Test connectivity to server and get configuration
@@ -285,27 +325,8 @@ void setup() {
Serial.println("Server connectivity test failed - skipping image fetch"); Serial.println("Server connectivity test failed - skipping image fetch");
} }
// Free dithering buffers if allocated // Always finish with cleanup and deep sleep (success or failure)
if (errorR) free(errorR); finishAndSleep("Normal cycle complete");
if (errorG) free(errorG);
if (errorB) free(errorB);
errorR = errorG = errorB = NULL;
// Put display to sleep
EPD_7IN5B_V2_Sleep();
// Free framebuffers
free(BlackImage);
free(RYImage);
BlackImage = NULL;
RYImage = NULL;
// Enter deep sleep
Serial.print("Going to sleep for ");
Serial.print(sleepDuration / 60000000);
Serial.println(" minutes");
esp_sleep_enable_timer_wakeup(sleepDuration);
esp_deep_sleep_start();
} }
bool fetchConnectionInformation() { bool fetchConnectionInformation() {
@@ -491,6 +512,7 @@ void fetchAndDisplayImage() {
} else { } else {
totalBytesRead += bytesRead; totalBytesRead += bytesRead;
} }
yield(); // keep WiFi stack happy
} }
Serial.print("Total bytes read: "); Serial.print("Total bytes read: ");
Serial.println(totalBytesRead); Serial.println(totalBytesRead);

View File

@@ -17,6 +17,7 @@
<PackageReference Include="RazorLight" Version="2.3.1" /> <PackageReference Include="RazorLight" Version="2.3.1" />
<PackageReference Include="Refit.HttpClientFactory" Version="8.0.0" /> <PackageReference Include="Refit.HttpClientFactory" Version="8.0.0" />
<PackageReference Include="Scalar.AspNetCore" Version="2.5.6" /> <PackageReference Include="Scalar.AspNetCore" Version="2.5.6" />
<PackageReference Include="Seq.Extensions.Logging" Version="8.0.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
@@ -30,5 +31,8 @@
<Content Include="wwwroot\index.cshtml"> <Content Include="wwwroot\index.cshtml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory> <CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content> </Content>
<Content Include="..\.github\workflows\build.yml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@@ -1,8 +1,12 @@
using HomeApi.Registration; using HomeApi.Registration;
using Scalar.AspNetCore; using Scalar.AspNetCore;
using Serilog;
var builder = WebApplication.CreateBuilder(args); var builder = WebApplication.CreateBuilder(args);
builder.Services.AddLogging(loggingBuilder =>
{
loggingBuilder.AddSeq(builder.Configuration.GetSection("Seq"));
});
builder.Services.AddHttpClient(); builder.Services.AddHttpClient();
builder.Services.AddMediatR(cfg => cfg.RegisterServicesFromAssemblyContaining<Program>()); builder.Services.AddMediatR(cfg => cfg.RegisterServicesFromAssemblyContaining<Program>());
builder.Services.AddControllers(); builder.Services.AddControllers();

View File

@@ -12,6 +12,14 @@
"Microsoft.AspNetCore": "Warning" "Microsoft.AspNetCore": "Warning"
} }
}, },
"Seq": {
"ServerUrl": "https://log.azaaxin.com",
"ApiKey": "KEY",
"MinimumLevel": "Trace",
"LevelOverride": {
"Microsoft": "Warning"
}
},
"ApiConfiguration": { "ApiConfiguration": {
"EspConfiguration": { "EspConfiguration": {
"InformationBoardImageUrl": "http://192.168.101.178:5000/home/default.jpg", "InformationBoardImageUrl": "http://192.168.101.178:5000/home/default.jpg",

View File

@@ -12,6 +12,14 @@
"Microsoft.AspNetCore": "Warning" "Microsoft.AspNetCore": "Warning"
} }
}, },
"Seq": {
"ServerUrl": "https://log.azaaxin.com",
"ApiKey": "KEY",
"MinimumLevel": "Trace",
"LevelOverride": {
"Microsoft": "Warning"
}
},
"ApiConfiguration": { "ApiConfiguration": {
"EspConfiguration": { "EspConfiguration": {
"InformationBoardImageUrl": "http://192.168.101.178:5000/home/default.jpg", "InformationBoardImageUrl": "http://192.168.101.178:5000/home/default.jpg",