Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c801730af9 | |||
| 93aa12c630 | |||
| 046180fe63 | |||
| 48f7065a9a |
16
.github/workflows/build.yml
vendored
16
.github/workflows/build.yml
vendored
@@ -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 }}"
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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",
|
||||||
|
|||||||
@@ -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",
|
||||||
|
|||||||
Reference in New Issue
Block a user