301 lines
8.8 KiB
C++
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
|
|
}
|