#include #include #include #include #include #include #include #include #include #include #include #include #include // for std::setprecision #include #include #include const std::string error_txt[16] = { "Reset Button", //0 "Emergency Switch", //1 "Cage Door Open", //2 "Fume Hood Flow", //3 "Vacuum Gauge 2", //4 "Tritium Monitor", //5 "Control Room Emergency Switch", //6 "Bldg Power Fail", //7 "Coolant Flow 2", //8 "Vacuum Gauge 1", //9 "error: port map", //10 "Coolant Flow 1", //11 "Smoke at Source", //12 "error: port map", //13 "error: port map", //14 "error: port map" //15 }; SDL_Window* window = nullptr; SDL_Renderer* renderer = nullptr; TTF_Font* font = nullptr; SDL_Color blackColor = { 0, 0, 0, 255}; SDL_Color redColor = { 255, 0, 0, 255}; SDL_Color greenColor = { 0, 200, 0, 255}; SDL_Color blueColor = { 0, 0, 255, 255}; SDL_Texture* textTexture = nullptr; void textDisplay(std::string text, int posX, int posY, SDL_Color color){ SDL_Surface* textSurface = TTF_RenderText_Solid(font, text.c_str(), color); textTexture = SDL_CreateTextureFromSurface(renderer, textSurface); SDL_Rect textRect = { posX, posY, textSurface->w, textSurface->h }; SDL_RenderCopy(renderer, textTexture, NULL, &textRect); SDL_FreeSurface(textSurface); SDL_DestroyTexture(textTexture); } int statusReading = 0; double tritiumReading = 0; double vaccumReading = 0; double subPumpReading = 0; bool preAccel = true; bool valve1 = true; bool valve2 = true; bool hv = true; bool boiler = true ; bool ionizer = true ; std::vector error_code; bool isTritiumError = false; bool isVaccumError = false; char timeBuffer[80]; void readStatus(){ std::ifstream file("data.txt"); // Replace "your_file.txt" with your actual file path if (!file.is_open()) { std::cout << "Unable to open file" << std::endl; return; } error_code.clear(); isTritiumError = false; isVaccumError = false; std::string line; while (std::getline(file, line)) { std::istringstream iss(line); std::string key; double value; if (std::getline(iss, key, '=')) { // Extract the key std::string valueStr; if (std::getline(iss, valueStr)) { // Convert the value string to double try { value = std::stod(valueStr); //std::cout << "Key: " << key << ", Value: " << value << std::endl; // Use 'value' as needed if( key == "State value" ) statusReading = value; if( key == "Tritium value" ) tritiumReading = value; if( key == "Vaccum value" ) vaccumReading = value; if( key == "SubPump value" ) subPumpReading = value; } catch (const std::invalid_argument& e) { std::cout << "Invalid value format for key: " << key << std::endl; } } } if ( line[0] == '#' ) { int code = line[1] -'0' ; error_code.push_back( code ); if( code == 9 ) isVaccumError = true; if( code == 5 ) isTritiumError = true; // printf("error code : %d, %s\n", error_code.back(), error_txt[error_code.back()].c_str()); } } file.close(); struct stat fileStat; stat("data.txt", &fileStat); time_t lastModifiedTime = fileStat.st_mtime; struct tm* timeinfo = localtime(&lastModifiedTime); strftime(timeBuffer, sizeof(timeBuffer), "data.txt : %Y-%m-%d %H:%M:%S", timeinfo); if( statusReading == 0 || statusReading == 1 ){ // startup or normal preAccel = true; valve1 = true; valve2 = true; hv = true; boiler = true; ionizer = true; } if( statusReading == 2 ){ // toruble1 preAccel = false; hv = false; } if( statusReading == 3 ){ // toruble2 preAccel = false; valve1 = false; valve2 = false; hv = false; ionizer = false; } if( statusReading == 4 ){ // toruble3 preAccel = false; valve1 = false; valve2 = false; hv = false; boiler = false; ionizer = false; } } std::string FormatDouble(double value){ int decimalPlaces = 1; std::ostringstream oss; oss << std::fixed << std::setprecision(decimalPlaces) << value; return oss.str(); } int main() { SDL_Init(SDL_INIT_VIDEO); // Create a window window = SDL_CreateWindow("Tritium Source Status", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 1577, 695, 0); // Create a renderer renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED); // Font initialization for rendering text TTF_Init(); font = TTF_OpenFont("/usr/share/fonts/truetype/freefont/FreeSerifBold.ttf", 24); // Load an image SDL_Surface* imageSurface = IMG_Load("BG.png"); SDL_Texture* texture = SDL_CreateTextureFromSurface(renderer, imageSurface); SDL_FreeSurface(imageSurface); SDL_Rect imageRect = { 0, 0, 1577, 695 }; // Image position and size SDL_Event event; bool running = true; int count = 0; while (running) { while (SDL_PollEvent(&event)) { if (event.type == SDL_QUIT) { running = false; } } if( count == 0 ) readStatus(); count ++; if( count >= 5 ) count = 0; // Clear the renderer SDL_RenderClear(renderer); // Render the image SDL_RenderCopy(renderer, texture, NULL, &imageRect); {// Get current time std::chrono::system_clock::time_point now = std::chrono::system_clock::now(); std::time_t now_c = std::chrono::system_clock::to_time_t(now); // Convert time to a string std::string timeString = std::ctime(&now_c); timeString.erase(timeString.length() - 1); //remove the '\n' textDisplay(timeString, 10, 10, blackColor); } textDisplay( valve1 ? "Open" : "Close", 570, 455, valve1 ? greenColor : redColor); // GateValve-1 textDisplay( valve2 ? "Open" : "Close", 1270, 455, valve2 ? greenColor : redColor); // GateValve-2 textDisplay( "Pre-Accel. supply : ", 750, 455, blackColor); // pre-accel. supply text textDisplay( preAccel ? "On" : "Off", 950, 455, preAccel ? greenColor : redColor); // pre-accel. supply text int yPos = 300; textDisplay( "HV Supply : ", 30, yPos, blackColor); textDisplay( hv ? "On" : "Off", 230, yPos, hv ? greenColor : redColor); textDisplay( "Boiler Supply : ", 30, yPos + 40, blackColor); textDisplay( boiler ? "On" : "Off", 230, yPos + 40, boiler ? greenColor : redColor); textDisplay( "Ionizer Supply : ", 30, yPos + 80, blackColor); textDisplay( ionizer ? "On" : "Off", 230, yPos + 80, ionizer ? greenColor : redColor); switch (statusReading){ case 0: textDisplay( "Start-Up", 10, 40, blueColor); break; case 1: textDisplay( "Normal", 10, 40, greenColor); break; case 2: textDisplay( "Cage Door (Tripped-1)", 10, 40, redColor); break; case 3: textDisplay( "Vacuum (Tripped-2)", 10, 40, redColor); break; case 4: textDisplay( "Source (Tripped-3)", 10, 40, redColor); break; } if( error_code.size() > 0 ){ for( size_t i = 0; i < error_code.size(); i++){ textDisplay( error_txt[error_code[i]], 10, 80 + 25*i, redColor); } } textDisplay( "Tritium Sensor : " + FormatDouble(tritiumReading) + " uCr/m3", 720, 200, isTritiumError ? redColor : blueColor); textDisplay( "Vaccum : " + FormatDouble(vaccumReading) + "x1e-6 Torr", 630, 20, isVaccumError ? redColor: blueColor); textDisplay( "SubPump : " + FormatDouble(subPumpReading*1000) + " mA", 300, 40, blueColor); textDisplay("update every 5 sec.", 1200, 670, blackColor); textDisplay(timeBuffer, 0, 670, blackColor); // Update the screen SDL_RenderPresent(renderer); std::this_thread::sleep_for(std::chrono::seconds(1)); } // Clean up SDL_DestroyTexture(texture); SDL_DestroyRenderer(renderer); SDL_DestroyWindow(window); TTF_Quit(); SDL_Quit(); return 0; }