Scoreboard/scoreboardoutput/sketch/ScoreboardNumbers.ino.cpp
2025-01-08 09:39:14 +00:00

301 lines
8.8 KiB
C++

#include <Arduino.h>
#line 1 "C:\\Users\\chris\\Qsync\\Projects\\Scoreboard\\ScoreboardNumbers\\ScoreboardNumbers.ino"
#include <WiFi.h>
#include <ArduinoJson.h>
#include <Wire.h>
#include <U8g2lib.h>
#include <U8x8lib.h>
#include <HTTPClient.h>
#include "objects.h"
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* clock=*/ SCL, /* data=*/ SDA, /* reset=*/ U8X8_PIN_NONE); // High speed I2C
// Define pins for the 7-segment displays
const int digitPins[4] = {2, 3, 4, 5}; // Common anode pins
const int segmentPins[7] = {6, 7, 8, 9, 10, 11, 12}; // Segment pins (a, b, c, d, e, f, g)
// Define the 7-segment display patterns
const byte digitPatterns[10] = {
B11111100, // 0
B01100000, // 1
B11011010, // 2
B11110010, // 3
B01100110, // 4
B10110110, // 5
B10111110, // 6
B11100000, // 7
B11111110, // 8
B11110110 // 9
};
// Wi-Fi settings
const char* ssid = "study";
const char* password = "abcde54321";
const char* displayQueue = "dQ";
const char* jsonPoints = "points";
const int wifiLoopDelay = 5000 / portTICK_PERIOD_MS;
const int displayLoopDelay = 1000 / portTICK_PERIOD_MS;
const int httpPollDelay = 3000 / portTICK_PERIOD_MS;
//FreeRTOS Queue Handles
QueueHandle_t scoreQueue;
// FreeRTOS task handles
TaskHandle_t networkTaskHandle = NULL;
TaskHandle_t displayTaskHandle = NULL;
portMUX_TYPE critical = portMUX_INITIALIZER_UNLOCKED;
// FreeRTOS Event Handles
EventGroupHandle_t wifi_event_group;
const int CONNECTED_BIT = BIT0;
void networkTask(void * parameter);
void displayTask(void * parameter);
#line 55 "C:\\Users\\chris\\Qsync\\Projects\\Scoreboard\\ScoreboardNumbers\\ScoreboardNumbers.ino"
void setup();
#line 104 "C:\\Users\\chris\\Qsync\\Projects\\Scoreboard\\ScoreboardNumbers\\ScoreboardNumbers.ino"
void WiFiEvent(arduino_event_id_t event);
#line 256 "C:\\Users\\chris\\Qsync\\Projects\\Scoreboard\\ScoreboardNumbers\\ScoreboardNumbers.ino"
void displayNumber(int display, int digitValue);
#line 287 "C:\\Users\\chris\\Qsync\\Projects\\Scoreboard\\ScoreboardNumbers\\ScoreboardNumbers.ino"
void loop();
#line 55 "C:\\Users\\chris\\Qsync\\Projects\\Scoreboard\\ScoreboardNumbers\\ScoreboardNumbers.ino"
void setup() {
try {
// Initialize Serial port
Serial.begin(115200);
#ifdef DEBUG
Serial.println("Starting");
#endif
//start display driver
u8g2.begin();
u8g2.setFont(u8g2_font_ncenB08_tr); // choose a suitable font
#ifdef DEBUG
Serial.println("end dispInit");
#endif
// Initialize the pins
// for (int i = 0; i < 4; i++) {
// pinMode(digitPins[i], OUTPUT);
// digitalWrite(digitPins[i], HIGH); // Turn off all displays initially
// }
// for (int i = 0; i < 7; i++) {
// pinMode(segmentPins[i], OUTPUT);
// digitalWrite(segmentPins[i], LOW); // Turn off all segments initially
// }
WiFi.onEvent( WiFiEvent );
WiFi.mode(WIFI_STA);
WiFi.disconnect();
#ifdef DEBUG
Serial.println("end IO init");
#endif
scoreQueue = xQueueCreate(2, sizeof( Scores ) );
wifi_event_group = xEventGroupCreate();
// Start the network task
xTaskCreatePinnedToCore(networkTask, "Network Task", 20000, NULL, 3, &networkTaskHandle, 1);
// Start the display task
xTaskCreatePinnedToCore(displayTask, "Display Task", 20000, NULL, 4, &displayTaskHandle, 1 );
#ifdef DEBUG
Serial.println("ended init");
#endif
vTaskStartScheduler();
} catch(String err){
Serial.print("SetupError: ");
Serial.println(err);
}
}
void WiFiEvent(WiFiEvent_t event)
{
switch (event) {
case SYSTEM_EVENT_STA_CONNECTED:
Serial.println("Connected to access point");
break;
case SYSTEM_EVENT_STA_DISCONNECTED:
Serial.println("Disconnected from WiFi access point");
break;
case SYSTEM_EVENT_AP_STADISCONNECTED:
Serial.println("WiFi client disconnected");
break;
default: break;
}
}
void networkTask(void * parameter) {
try {
while(true){
while ( WiFi.status() != WL_CONNECTED )
{
#ifdef DEBUG
Serial.println("disconnected, connecting");
#endif
WiFi.disconnect();
WiFi.begin( ssid, password );
#ifdef DEBUG
Serial.println(" waiting on wifi connection" );
#endif
vTaskDelay( 4000 );
}
while (WiFi.status() != WL_CONNECTED) {
xEventGroupClearBits(wifi_event_group, CONNECTED_BIT);
#ifdef DEBUG
Serial.println("Connecting to WiFi...");
#endif
}
xEventGroupSetBits(wifi_event_group, CONNECTED_BIT);
#ifdef DEBUG
Serial.println("Connected to WiFi");
#endif
HTTPClient http;
const String url = "https://192.168.1.141:7005/api/score/summary";
for (;;) {
if(WiFi.status() != WL_CONNECTED){
continue;
}
#ifdef DEBUG
Serial.println(url);
#endif
http.useHTTP10(true);
http.begin(url.c_str());
http.addHeader("x-api-key", "396A62D6-0192-4738-8F45-8AAF7BCFA3EC");
int httpResponseCode = http.GET();
DynamicJsonDocument doc(2048);
if (httpResponseCode>0) { //if no game, what code?
#ifdef DEBUG
Serial.print("HTTP Response code: ");
Serial.println(httpResponseCode);
#endif
deserializeJson(doc, http.getStream());
} else {
Serial.print("HTTP Req Error code: ");
Serial.println(httpResponseCode);
vTaskDelay(httpPollDelay);
continue;
}
// Parse JSON
Scores pts;
pts.home = doc["home"].as<int>();
pts.away = doc["away"].as<int>();
pts.state = doc["state"].as<String>();
#ifdef DEBUG
Serial.print("Match State: ");
Serial.print(doc["state"].as<String>());
Serial.print("| Home: ");
Serial.print(doc["home"].as<int>());
Serial.print(" Away: ");
Serial.println(doc["away"].as<int>());
#endif
http.end();
// Send the number to the display task
xQueueSend(scoreQueue, &pts, portMAX_DELAY);
vTaskDelay(httpPollDelay); // Wait before fetching the next update
}
vTaskDelay(wifiLoopDelay);
}
}
catch (String err){
Serial.print("NetworkTaskError: ");
Serial.println(err);
}
}
void displayTask(void * parameter) {
try {
Scores matchScore;
int wifiStateY = 10;
int matchStateY = 35;
int scoreY = 74-u8g2.getMaxCharHeight();
while(true) {
u8g2.clearBuffer(); // clear the internal memory
int bits = (xEventGroupGetBits( wifi_event_group));
if (bits & CONNECTED_BIT) {
#ifdef DEBUG
Serial.println("Connected");
#endif
u8g2.drawStr(0,wifiStateY,"Connected! ;)"); // write something to the internal memory
} else {
#ifdef DEBUG
Serial.println("Disconnected");
#endif
u8g2.drawStr(0,wifiStateY,"Not Connected! :("); // write something to the internal memory
}
if (xQueueReceive(scoreQueue, &matchScore, portMAX_DELAY)) {
// for (int i = 0; i < 4; i++) {
// displayNumber(i, number / (int)pow(10, 3 - i) % 10); // Display the number
// delay(5); // Delay to display the number
// }
u8g2.drawStr(0, matchStateY, matchScore.state.c_str());
String scoreMsg = "Home " + String(matchScore.home) + " Away " + String(matchScore.away);
u8g2.drawStr(0,scoreY, scoreMsg.c_str());
}
u8g2.sendBuffer(); // transfer internal memory to the display
vTaskDelay(displayLoopDelay);
// if (xQueueReceive(scoreQueue, &number, portMAX_DELAY)) {
// for (int i = 0; i < 4; i++) {
// displayNumber(i, number / (int)pow(10, 3 - i) % 10); // Display the number
// delay(5); // Delay to display the number
// }
// }
}
} catch (String err){
Serial.print("DisplayLoopError: ");
Serial.println(err);
}
}
// Function to display a number on a specific 7-segment display
void displayNumber(int display, int digitValue) {
for (int i = 0; i < 7; i++) {
if (bitRead(digitPatterns[digitValue], i)) {
digitalWrite(segmentPins[i], HIGH); // Turn on the segment
} else {
digitalWrite(segmentPins[i], LOW); // Turn off the segment
}
}
digitalWrite(digitPins[display], LOW); // Turn on the display
}
// String getStateString(GameState state){
// switch(state){
// case GameState::WaitingForStart:
// return "Pending";
// case GameState::FirstHalf:
// return "First Half";
// case GameState::SecondHalf:
// return "Second Half";
// case GameState::HalfTime:
// return "Half Time";
// case GameState::Finished:
// return "Full Time";
// case GameState::None:
// return "Not Configured";
// default:
// "Other";
// }
// }
void loop() {
// Empty loop, tasks handle everything
}