diff --git a/AVR_Miner.py b/AVR_Miner.py index 824086d2..116697d8 100644 --- a/AVR_Miner.py +++ b/AVR_Miner.py @@ -3,7 +3,7 @@ Duino-Coin Official AVR Miner 4.3 © MIT licensed https://duinocoin.com https://github.com/revoxhere/duino-coin -Duino-Coin Team & Community 2019-2025 +Duino-Coin Team & Community 2019-2026 """ from os import _exit, mkdir @@ -19,7 +19,7 @@ from json import load as jsonload from random import choice -from locale import LC_ALL, getdefaultlocale, getlocale, setlocale +from locale import getlocale, setlocale, normalize, LC_ALL import zipfile from re import sub @@ -42,7 +42,6 @@ # Python <3.5 check f"Your Python version is too old. Duino-Coin Miner requires version 3.6 or above. Update your packages and try again" - def install(package): try: pip.main(["install", package]) @@ -139,6 +138,44 @@ class Settings: PICK = "" COG = " @" +def get_win32_locale() -> str: + """ + Windows's alternative to getlocale + """ + from ctypes import (create_unicode_buffer, + FormatError, + GetLastError, + windll) + bufsize = 85 + buf = create_unicode_buffer(bufsize) + if windll.kernel32.GetUserDefaultLocaleName(buf, bufsize): + return buf.value + else: + raise OSError(FormatError(GetLastError())) + +def get_locale_code() -> str: + """ + Wrapper to handle getlocale for all OSes + Reaction to: https://github.com/python/cpython/issues/90817 + """ + + if os.name == 'nt': + try: + return get_win32_locale() + except: + return "english" + elif os.name == "posix": + setlocale(LC_ALL, '') + + locale_raw = getlocale()[0] + if locale_raw: + return normalize(locale_raw) + + return "english" + else: + return "english" + + def check_updates(): """ Function that checks if the miner is updated. @@ -508,45 +545,52 @@ def start(donation_level): try: if not Path(Settings.DATA_DIR + '/Settings.cfg').is_file(): - locale = getdefaultlocale()[0] - if locale.startswith('es'): - lang = 'spanish' - elif locale.startswith('sk'): - lang = 'slovak' - elif locale.startswith('ru'): - lang = 'russian' - elif locale.startswith('pl'): - lang = 'polish' - elif locale.startswith('de'): - lang = 'german' - elif locale.startswith('fr'): - lang = 'french' - elif locale.startswith('jp'): - lang = 'japanese' - elif locale.startswith('tr'): - lang = 'turkish' - elif locale.startswith('it'): - lang = 'italian' - elif locale.startswith('pt'): - lang = 'portuguese' - if locale.startswith("zh_TW"): + locale = get_locale_code() + + if locale.startswith("es"): + lang = "spanish" + elif locale.startswith("pl"): + lang = "polish" + elif locale.startswith("fr"): + lang = "french" + elif locale.startswith("ja"): + lang = "japanese" + elif locale.startswith("fa"): + lang = "farsi" + elif locale.startswith("mt"): + lang = "maltese" + elif locale.startswith("ru"): + lang = "russian" + elif locale.startswith("uk"): + lang = "ukrainian" + elif locale.startswith("de"): + lang = "german" + elif locale.startswith("tr"): + lang = "turkish" + elif locale.startswith("pt"): + lang = "portuguese" + elif locale.startswith("it"): + lang = "italian" + elif locale.startswith("sk"): + lang = "slovak" + elif locale.startswith("zh_Hant") or locale.startswith("zh_TW"): lang = "chinese_Traditional" - elif locale.startswith('zh'): - lang = 'chinese_simplified' - elif locale.startswith('th'): - lang = 'thai' - elif locale.startswith('az'): - lang = 'azerbaijani' - elif locale.startswith('nl'): - lang = 'dutch' - elif locale.startswith('ko'): - lang = 'korean' + elif locale.startswith("zh"): + lang = "chinese_simplified" + elif locale.startswith("th"): + lang = "thai" + elif locale.startswith("ko"): + lang = "korean" elif locale.startswith("id"): lang = "indonesian" - elif locale.startswith("cz"): + elif locale.startswith("cs"): lang = "czech" elif locale.startswith("fi"): lang = "finnish" + elif locale.startswith('az'): + lang = 'azerbaijani' + elif locale.startswith('nl'): + lang = 'dutch' else: lang = 'english' else: @@ -805,7 +849,7 @@ def greeting(): + Style.BRIGHT + get_string('banner') + Style.RESET_ALL + Fore.MAGENTA + f' {Settings.VER}' + Fore.RESET - + ' 2019-2025') + + ' 2019-2026') print( Style.DIM + Fore.MAGENTA diff --git a/Arduino_Code/Arduino_Code.ino b/Arduino_Code/Arduino_Code.ino index 1947373e..5480bdcd 100644 --- a/Arduino_Code/Arduino_Code.ino +++ b/Arduino_Code/Arduino_Code.ino @@ -6,7 +6,7 @@ (____/(______)(____)(_)\_)(_____) \___)(_____)(____)(_)\_) Official code for Arduino boards (and relatives) version 4.3 - Duino-Coin Team & Community 2019-2024 © MIT Licensed + Duino-Coin Team & Community 2019-2026 © MIT Licensed https://duinocoin.com https://github.com/revoxhere/duino-coin If you don't know where to start, visit official website and navigate to diff --git a/ESP_Code/DisplayHal.h b/ESP_Code/DisplayHal.h index dfde2490..0942b8ed 100644 --- a/ESP_Code/DisplayHal.h +++ b/ESP_Code/DisplayHal.h @@ -21,6 +21,103 @@ static byte msec[] = {0x0A, 0x15, 0x11, 0x06, 0x08, 0x04, 0x02, 0x0C}; #endif +#if defined(DISPLAY_ST7789) + // Define colors + #define WHITE TFT_WHITE + #define BLACK TFT_BLACK + #define DUCO_GOLD 0xFD20 + #define DUCO_GRAY 0x7BEF + #define DUCO_DARK 0x39E7 + #define DUCO_GREEN 0x07E0 + #define DUCO_CYAN 0x07FF + + // Button and rotation + #define TFT_BUTTON_PIN 0 // Boot button on T-Display S3 + uint8_t tft_rotation = 1; // 0,1,2,3 = 4 orientations + volatile bool tft_rotation_changed = false; + + // Interrupt handler - fires instantly on button press + void IRAM_ATTR buttonISR() { + tft_rotation_changed = true; + } + + // Draw WiFi signal bars + void drawWifiBars(int x, int y) { + int rssi = WiFi.RSSI(); + int bars = (rssi > -40) ? 4 : (rssi > -60) ? 3 : (rssi > -75) ? 2 : 1; + for (int i = 0; i < 4; i++) { + int barH = 6 + i * 5; + int barY = y + 20 - barH; + uint16_t color = (i < bars) ? DUCO_GREEN : DUCO_DARK; + tft.fillRect(x + i * 9, barY, 7, barH, color); + } + } + + // Draw checkmark icon + void drawCheckmark(int x, int y) { + tft.drawLine(x, y+8, x+5, y+13, DUCO_GREEN); + tft.drawLine(x+1, y+8, x+6, y+13, DUCO_GREEN); + tft.drawLine(x+5, y+13, x+14, y+2, DUCO_GREEN); + tft.drawLine(x+6, y+13, x+15, y+2, DUCO_GREEN); + } + + // State flags + bool tft_layout_drawn = false; + volatile bool tft_busy = false; + + // Apply rotation change (called from main loop, not ISR) + void checkButton() { + if (tft_rotation_changed) { + tft_rotation_changed = false; + tft_rotation = (tft_rotation + 1) % 4; // Cycle: 0→1→2→3→0 + tft.setRotation(tft_rotation); + tft_layout_drawn = false; + } + } + + // Check if current rotation is landscape (1 or 3) or portrait (0 or 2) + bool isLandscape() { + return (tft_rotation == 1 || tft_rotation == 3); + } + + // Draw static layout (separators + labels) + void drawStaticLayout() { + tft.fillScreen(BLACK); + tft.setTextColor(DUCO_GRAY, BLACK); + + if (isLandscape()) { + // === LANDSCAPE 320x170 === + tft.drawFastHLine(0, 28, 320, DUCO_DARK); + tft.drawFastHLine(0, 105, 320, DUCO_DARK); + tft.drawFastHLine(0, 140, 320, DUCO_DARK); + tft.drawFastHLine(200, 55, 115, DUCO_DARK); + // diff and shr/s labels on right side (static) + tft.setTextSize(1); + tft.setCursor(280, 40); + tft.print("diff"); + tft.setCursor(274, 65); + tft.print("shr/s"); + tft.setCursor(5, 147); + tft.print("Duino-Coin " + String(SOFTWARE_VERSION)); + } else { + // === PORTRAIT 170x320 === + tft.drawFastHLine(0, 28, 170, DUCO_DARK); + tft.drawFastHLine(0, 130, 170, DUCO_DARK); + tft.drawFastHLine(0, 195, 170, DUCO_DARK); + tft.drawFastHLine(0, 255, 170, DUCO_DARK); + // kH/s label centered + tft.setTextSize(2); + tft.setCursor(55, 100); + tft.print("kH/s"); + // Bottom version + tft.setTextSize(1); + tft.setCursor(5, 262); + tft.print("Duino-Coin " + String(SOFTWARE_VERSION)); + } + tft_layout_drawn = true; + } +#endif + #if defined(DISPLAY_SSD1306) void drawStrMultiline(const char *msg, int xloc, int yloc) { //https://github.com/olikraus/u8g2/discussions/1479 @@ -56,7 +153,7 @@ } #endif -#if defined(DISPLAY_SSD1306) || defined(DISPLAY_16X2) +#if defined(DISPLAY_SSD1306) || defined(DISPLAY_16X2) || defined(DISPLAY_ST7789) void screen_setup() { // Ran during setup() // Abstraction layer: screen initialization @@ -78,6 +175,15 @@ lcd.home(); lcd.clear(); #endif + + #if defined(DISPLAY_ST7789) + pinMode(TFT_BUTTON_PIN, INPUT_PULLUP); + attachInterrupt(digitalPinToInterrupt(TFT_BUTTON_PIN), buttonISR, FALLING); + tft.begin(); + tft.setRotation(tft_rotation); + tft.init(); + tft.fillScreen(BLACK); + #endif } @@ -167,6 +273,79 @@ drawStrMultiline(features_str.c_str(), 2, 46); u8g2.sendBuffer(); #endif + + #if defined(DISPLAY_ST7789) + tft.fillScreen(BLACK); + tft_layout_drawn = false; + int sw = tft.width(); + bool landscape = isLandscape(); + + // Board type + frequency + tft.setTextColor(DUCO_GOLD, BLACK); + tft.setTextSize(landscape ? 3 : 2); + tft.setCursor(10, 15); + #if defined(ESP8266) + tft.print("ESP8266 "); + #elif defined(CONFIG_FREERTOS_UNICORE) + tft.print("ESP32S2/C3 "); + #else + tft.print("ESP32 "); + #endif + #if defined(ESP8266) + tft.print(String(ESP.getCpuFreqMHz()).c_str()); + #else + tft.print(String(getCpuFrequencyMhz()).c_str()); + #endif + tft.print(" MHz"); + + // Separator + tft.drawFastHLine(10, landscape ? 50 : 45, sw - 20, DUCO_DARK); + + // Compile date + tft.setTextColor(WHITE, BLACK); + tft.setTextSize(landscape ? 2 : 1); + tft.setCursor(10, landscape ? 60 : 55); + tft.print("Compiled "); + tft.print(__DATE__); + + // Features + tft.setTextColor(DUCO_CYAN, BLACK); + tft.setTextSize(landscape ? 2 : 1); + tft.setCursor(10, landscape ? 90 : 75); + tft.print("Features:"); + tft.setTextColor(WHITE, BLACK); + tft.setTextSize(1); + tft.setCursor(10, landscape ? 115 : 95); + String features_str = "OTA "; + #if defined(USE_LAN) + features_str += "LAN "; + #endif + #if defined(LED_BLINKING) + features_str += "Blink "; + #endif + #if defined(SERIAL_PRINTING) + features_str += "Serial "; + #endif + #if defined(WEB_DASHBOARD) + features_str += "Webserver "; + #endif + #if defined(DISPLAY_ST7789) + features_str += "ST7789 "; + #endif + #if defined(USE_INTERNAL_SENSOR) + features_str += "Int.sensor "; + #endif + #if defined(USE_DS18B20) + features_str += "DS18B20 "; + #endif + #if defined(USE_DHT) + features_str += "DHT "; + #endif + #if defined(USE_HSU07M) + features_str += "HSU07M "; + #endif + tft.print(features_str); + #endif } void display_info(String message) { @@ -205,6 +384,57 @@ lcd.setCursor(0, 1); lcd.print(message); #endif + + #if defined(DISPLAY_ST7789) + tft.fillScreen(BLACK); + tft_layout_drawn = false; + int sw = tft.width(); + bool landscape = isLandscape(); + int sh = tft.height(); + + // Duino-Coin title + tft.setTextColor(DUCO_GOLD, BLACK); + tft.setTextSize(landscape ? 3 : 2); + tft.setCursor(landscape ? 50 : 10, 10); + tft.print("Duino-Coin"); + + // Board type + tft.setTextColor(WHITE, BLACK); + tft.setTextSize(landscape ? 3 : 2); + tft.setCursor(landscape ? 50 : 10, landscape ? 45 : 40); + #if defined(ESP8266) + tft.print("ESP8266"); + #elif defined(CONFIG_FREERTOS_UNICORE) + tft.print("ESP32S2/C3"); + #else + tft.print("ESP32"); + #endif + + // MINER label + tft.setTextColor(DUCO_GOLD, BLACK); + tft.setTextSize(2); + tft.setCursor(landscape ? 230 : 100, landscape ? 50 : 45); + tft.print("MINER"); + + // Version + tft.setTextSize(1); + tft.setTextColor(DUCO_GRAY, BLACK); + tft.setCursor(landscape ? 280 : 10, landscape ? 70 : 70); + tft.print("v"); + tft.print(String(SOFTWARE_VERSION).c_str()); + + // URL + tft.setTextColor(DUCO_GRAY, BLACK); + tft.setTextSize(1); + tft.setCursor(landscape ? 50 : 10, landscape ? 85 : 85); + tft.print("www.duinocoin.com"); + + // Message + tft.setTextColor(WHITE, BLACK); + tft.setTextSize(2); + tft.setCursor(10, landscape ? 130 : 110); + tft.print(message); + #endif } @@ -290,6 +520,161 @@ lcd.print(sharerate); lcd.print("s"); #endif + + #if defined(DISPLAY_ST7789) + // Prevent concurrent access from both cores + if (tft_busy) return; + tft_busy = true; + + // Check for rotation button press + checkButton(); + + // Draw static layout elements once (separators, labels) + if (!tft_layout_drawn) { + drawStaticLayout(); + } + + if (isLandscape()) { + // ========== LANDSCAPE 320x170 ========== + // === TOP BAR === + drawWifiBars(5, 3); + tft.setTextColor(WHITE, BLACK); + tft.setTextSize(2); + tft.setCursor(45, 6); + tft.print(ping + "ms "); + tft.setTextSize(1); + tft.setTextColor(DUCO_GRAY, BLACK); + tft.setCursor(140, 10); + tft.print(node + " "); + + // === HASHRATE === + tft.fillRect(5, 35, 125, 40, BLACK); + tft.setTextColor(DUCO_GREEN, BLACK); + if (hashrate.toFloat() < 100.0) { + tft.setTextSize(4); + tft.setCursor(5, 40); + } else { + tft.setTextSize(3); + tft.setCursor(5, 45); + } + tft.print(hashrate); + // kH/s label redrawn every cycle (prevents it from being erased) + tft.setTextColor(DUCO_GRAY, BLACK); + tft.setTextSize(2); + tft.setCursor(135, 45); + tft.print("kH/s"); + + // === DIFF + SHARERATE === + tft.fillRect(205, 35, 70, 16, BLACK); + tft.fillRect(205, 62, 70, 16, BLACK); + tft.setTextColor(WHITE, BLACK); + tft.setTextSize(2); + tft.setCursor(210, 35); + tft.print(difficulty); + tft.setCursor(210, 62); + tft.print(sharerate); + + // === SHARES === + tft.fillRect(3, 110, 20, 18, BLACK); + drawCheckmark(5, 112); + tft.setTextColor(WHITE, BLACK); + tft.setTextSize(2); + tft.setCursor(28, 112); + tft.print(accepted_shares + "/" + total_shares + " "); + tft.setTextSize(1); + tft.setTextColor(DUCO_CYAN, BLACK); + tft.setCursor(215, 118); + tft.print("(" + accept_rate + "%) "); + + // === BOTTOM === + tft.setTextSize(1); + tft.setTextColor(DUCO_GRAY, BLACK); + tft.setCursor(5, 158); + tft.print(WiFi.localIP().toString() + " "); + tft.fillRect(160, 145, 160, 20, BLACK); + tft.setTextColor(WHITE, BLACK); + tft.setTextSize(2); + int uptimeW = uptime.length() * 12; + tft.setCursor(315 - uptimeW, 148); + tft.print(uptime); + + } else { + // ========== PORTRAIT 170x320 ========== + // === TOP BAR (0..27) === + drawWifiBars(5, 3); + tft.setTextColor(WHITE, BLACK); + tft.setTextSize(2); + tft.setCursor(45, 6); + tft.print(ping + "ms "); + // Node doesn't fit well on top bar in portrait, skip or shrink + + // === HASHRATE (30..129) === + tft.fillRect(5, 35, 160, 60, BLACK); + tft.setTextColor(DUCO_GREEN, BLACK); + if (hashrate.toFloat() < 100.0) { + tft.setTextSize(5); + tft.setCursor(10, 42); + } else { + tft.setTextSize(4); + tft.setCursor(10, 48); + } + tft.print(hashrate); + + // === STATS (132..194) === + tft.fillRect(5, 135, 90, 20, BLACK); + tft.setTextColor(WHITE, BLACK); + tft.setTextSize(2); + tft.setCursor(5, 138); + tft.print(difficulty); + tft.setTextSize(1); + tft.setTextColor(DUCO_GRAY, BLACK); + tft.setCursor(100, 143); + tft.print("diff"); + + tft.fillRect(5, 162, 90, 20, BLACK); + tft.setTextColor(WHITE, BLACK); + tft.setTextSize(2); + tft.setCursor(5, 165); + tft.print(sharerate); + tft.setTextSize(1); + tft.setTextColor(DUCO_GRAY, BLACK); + tft.setCursor(100, 170); + tft.print("shr/s"); + + // === SHARES (197..254) === + tft.fillRect(3, 202, 20, 18, BLACK); + drawCheckmark(5, 204); + tft.setTextColor(WHITE, BLACK); + tft.setTextSize(2); + tft.setCursor(28, 204); + tft.print(accepted_shares + "/" + total_shares + " "); + tft.setTextSize(1); + tft.setTextColor(DUCO_CYAN, BLACK); + tft.setCursor(28, 228); + tft.print("(" + accept_rate + "%) "); + + // Node name + tft.setTextColor(DUCO_GRAY, BLACK); + tft.setTextSize(1); + tft.setCursor(5, 243); + tft.print(node + " "); + + // === BOTTOM (257..320) === + tft.setTextSize(1); + tft.setTextColor(DUCO_GRAY, BLACK); + tft.setCursor(5, 275); + tft.print(WiFi.localIP().toString() + " "); + + tft.fillRect(0, 290, 170, 25, BLACK); + tft.setTextColor(WHITE, BLACK); + tft.setTextSize(2); + int uptimeW = uptime.length() * 12; + tft.setCursor(165 - uptimeW, 295); + tft.print(uptime); + } + + tft_busy = false; + #endif } #endif diff --git a/ESP_Code/ESP_Code.ino b/ESP_Code/ESP_Code.ino index c5161a84..b7136a6a 100644 --- a/ESP_Code/ESP_Code.ino +++ b/ESP_Code/ESP_Code.ino @@ -59,7 +59,7 @@ #include "Dashboard.h" #endif -#if defined(DISPLAY_SSD1306) || defined(DISPLAY_16X2) +#if defined(DISPLAY_SSD1306) || defined(DISPLAY_16X2) || defined(DISPLAY_ST7789) #include "DisplayHal.h" #endif @@ -140,7 +140,7 @@ void RestartESP(String msg) { Serial.println("Restarting ESP..."); #endif - #if defined(DISPLAY_SSD1306) || defined(DISPLAY_16X2) + #if defined(DISPLAY_SSD1306) || defined(DISPLAY_16X2) || defined(DISPLAY_ST7789) display_info("Restarting ESP..."); #endif @@ -213,7 +213,7 @@ namespace { Serial.println("Poolpicker selected the best mining node: " + node_id); #endif - #if defined(DISPLAY_SSD1306) || defined(DISPLAY_16X2) + #if defined(DISPLAY_SSD1306) || defined(DISPLAY_16X2) || defined(DISPLAY_ST7789) display_info(node_id); #endif } @@ -264,7 +264,7 @@ namespace { Serial.printf("Error fetching node from poolpicker: %s\n", https.errorToString(httpCode).c_str()); VerifyWifi(); #endif - #if defined(DISPLAY_SSD1306) || defined(DISPLAY_16X2) + #if defined(DISPLAY_SSD1306) || defined(DISPLAY_16X2) || defined(DISPLAY_ST7789) display_info(https.errorToString(httpCode)); #endif } @@ -384,7 +384,7 @@ namespace { #endif - #if defined(DISPLAY_SSD1306) || defined(DISPLAY_16X2) + #if defined(DISPLAY_SSD1306) || defined(DISPLAY_16X2) || defined(DISPLAY_ST7789) display_info("Waiting for node..."); #endif SelectNode(); @@ -499,7 +499,7 @@ void task1_func(void *) { VOID LOOP() { job[0]->mine(); - #if defined(DISPLAY_SSD1306) || defined(DISPLAY_16X2) + #if defined(DISPLAY_SSD1306) || defined(DISPLAY_16X2) || defined(DISPLAY_ST7789) float hashrate_float = (hashrate+hashrate_core_two) / 1000.0; float accept_rate = (accepted_share_count / 0.01 / share_count); @@ -528,7 +528,7 @@ void task2_func(void *) { VOID LOOP() { job[1]->mine(); - #if defined(DISPLAY_SSD1306) || defined(DISPLAY_16X2) + #if defined(DISPLAY_SSD1306) || defined(DISPLAY_16X2) || defined(DISPLAY_ST7789) float hashrate_float = (hashrate+hashrate_core_two) / 1000.0; float accept_rate = (accepted_share_count / 0.01 / share_count); @@ -578,7 +578,7 @@ void setup() { } #endif - #if defined(DISPLAY_SSD1306) || defined(DISPLAY_16X2) + #if defined(DISPLAY_SSD1306) || defined(DISPLAY_16X2) || defined(DISPLAY_ST7789) screen_setup(); display_boot(); delay(2500); @@ -699,8 +699,7 @@ void setup() { #if defined(BLUSHYBOX) blinker.detach(); #endif - - #if defined(DISPLAY_SSD1306) || defined(DISPLAY_16X2) + #if defined(DISPLAY_SSD1306) || defined(DISPLAY_16X2) || defined(DISPLAY_ST7789) display_info("Waiting for node..."); #endif #if defined(BLUSHYBOX) @@ -711,7 +710,7 @@ void setup() { blinker.detach(); #endif #else - #if defined(DISPLAY_SSD1306) || defined(DISPLAY_16X2) + #if defined(DISPLAY_SSD1306) || defined(DISPLAY_16X2) || defined(DISPLAY_ST7789) display_info("Waiting for WiFi..."); #endif SetupWifi(); @@ -786,7 +785,7 @@ void single_core_loop() { lwdtFeed(); - #if defined(DISPLAY_SSD1306) || defined(DISPLAY_16X2) + #if defined(DISPLAY_SSD1306) || defined(DISPLAY_16X2) || defined(DISPLAY_ST7789) float hashrate_float = (hashrate+hashrate_core_two) / 1000.0; float accept_rate = (accepted_share_count / 0.01 / share_count); diff --git a/ESP_Code/Settings.h b/ESP_Code/Settings.h index 41d0948a..c8187a5d 100644 --- a/ESP_Code/Settings.h +++ b/ESP_Code/Settings.h @@ -61,6 +61,9 @@ extern const char PASSWORD[] = "PASSW0RD"; // Uncomment if your device is a Duino BlushyBox device // #define BLUSHYBOX + +// Uncomment to enable a ST7789 LCD screen, like t-display s3, on a direct bus to display mining info in real time +// #define DISPLAY_ST7789 // -------------------------------------------------------------- // // ---------------------- IoT examples -------------------------- // @@ -168,6 +171,14 @@ extern unsigned int ping = 0; Adafruit_LiquidCrystal lcd(1, 2, 3, 4, 5, 6); #endif + +#if defined(DISPLAY_ST7789) + #include + + // initialize the library + TFT_eSPI tft = TFT_eSPI(); +#endif + #if defined(USE_HSU07M) #include "Wire.h" #define HSU07M_ADDRESS 0x4B // Change this if your sensor has a different address diff --git a/PC_Miner.py b/PC_Miner.py index dc565fa4..32193ba8 100644 --- a/PC_Miner.py +++ b/PC_Miner.py @@ -3,7 +3,7 @@ Duino-Coin Official PC Miner 4.3 © MIT licensed https://duinocoin.com https://github.com/revoxhere/duino-coin -Duino-Coin Team & Community 2019-2025 +Duino-Coin Team & Community 2019-2026 """ from time import time, sleep, strptime, ctime, time_ns @@ -37,7 +37,7 @@ from platform import python_version from signal import SIGINT, signal -from locale import getdefaultlocale +from locale import getlocale, setlocale, normalize, LC_ALL from configparser import ConfigParser import io @@ -50,7 +50,6 @@ # Python <3.5 check f"Your Python version is too old. Duino-Coin Miner requires version 3.6 or above. Update your packages and try again" - def handler(signal_received, frame): """ Nicely handle CTRL+C exit @@ -63,15 +62,18 @@ def handler(signal_received, frame): + get_string("goodbye"), "warning") - if not "raspi_leds" in user_settings: - user_settings["raspi_leds"] = "y" - - if running_on_rpi and user_settings["raspi_leds"] == "y": - # Reset onboard status LEDs - os.system( - 'echo mmc0 | sudo tee /sys/class/leds/led0/trigger >/dev/null 2>&1') - os.system( - 'echo 1 | sudo tee /sys/class/leds/led1/brightness >/dev/null 2>&1') + try: + if not "raspi_leds" in user_settings: + user_settings["raspi_leds"] = "y" + + if running_on_rpi and user_settings["raspi_leds"] == "y": + # Reset onboard status LEDs + os.system( + 'echo mmc0 | sudo tee /sys/class/leds/led0/trigger >/dev/null 2>&1') + os.system( + 'echo 1 | sudo tee /sys/class/leds/led1/brightness >/dev/null 2>&1') + except: + pass if sys.platform == "win32": _exit(0) @@ -189,6 +191,42 @@ class Settings: PICK = "" COG = " @" +def get_win32_locale() -> str: + """ + Windows's alternative to getlocale + """ + from ctypes import (create_unicode_buffer, + FormatError, + GetLastError, + windll) + bufsize = 85 + buf = create_unicode_buffer(bufsize) + if windll.kernel32.GetUserDefaultLocaleName(buf, bufsize): + return buf.value + else: + raise OSError(FormatError(GetLastError())) + +def get_locale_code() -> str: + """ + Wrapper to handle getlocale for all OSes + Reaction to: https://github.com/python/cpython/issues/90817 + """ + + if os.name == 'nt': + try: + return get_win32_locale() + except: + return "english" + elif os.name == "posix": + setlocale(LC_ALL, '') + + locale_raw = getlocale()[0] + if locale_raw: + return normalize(locale_raw) + + return "english" + else: + return "english" def title(title: str): if not Settings.disable_title: @@ -825,7 +863,7 @@ def greeting(): print("\n" + Style.DIM + Fore.YELLOW + Settings.BLOCK + Fore.YELLOW + Style.BRIGHT + get_string("banner") + Style.RESET_ALL + Fore.MAGENTA + " (" + str(Settings.VER) + ") " - + Fore.RESET + "2019-2025") + + Fore.RESET + "2019-2026") print(Style.DIM + Fore.YELLOW + Settings.BLOCK + Style.NORMAL + Fore.YELLOW + "https://github.com/revoxhere/duino-coin") @@ -895,14 +933,14 @@ def preload(): try: if not Path(Settings.DATA_DIR + Settings.SETTINGS_FILE).is_file(): - locale = getdefaultlocale()[0] + locale = get_locale_code() if locale.startswith("es"): lang = "spanish" elif locale.startswith("pl"): lang = "polish" elif locale.startswith("fr"): lang = "french" - elif locale.startswith("jp"): + elif locale.startswith("ja"): lang = "japanese" elif locale.startswith("fa"): lang = "farsi" @@ -916,13 +954,13 @@ def preload(): lang = "german" elif locale.startswith("tr"): lang = "turkish" - elif locale.startswith("pr"): + elif locale.startswith("pt"): lang = "portuguese" elif locale.startswith("it"): lang = "italian" elif locale.startswith("sk"): lang = "slovak" - if locale.startswith("zh_TW"): + elif locale.startswith("zh_Hant") or locale.startswith("zh_TW"): lang = "chinese_Traditional" elif locale.startswith("zh"): lang = "chinese_simplified" @@ -932,7 +970,7 @@ def preload(): lang = "korean" elif locale.startswith("id"): lang = "indonesian" - elif locale.startswith("cz"): + elif locale.startswith("cs"): lang = "czech" elif locale.startswith("fi"): lang = "finnish" diff --git a/README.md b/README.md index adb28ebd..d6d51380 100644 --- a/README.md +++ b/README.md @@ -184,7 +184,7 @@ Please note the DUCO/day column has been removed since version 4.0 changed the r ## Community-made softwares -### Please note that these softwares are not developed by us and we do not give any guarantees that use of them will not result in an account getting banned if they get changed in the future. +### Please note that these softwares are not developed by us and we do not guarantee them working properly. Additionally note that using outdated and/or unofficial miners may produce warnings or a ban. ### Miners made by the Duino-Coin community: * [Dockerized Duino-Coin Miner](https://github.com/simeononsecurity/docker-duino-coin) - A Dockerized version of the Duino-Coin Miner by simeononsecurity @@ -206,6 +206,7 @@ Please note the DUCO/day column has been removed since version 4.0 changed the r * [d-cpuminer](https://github.com/phantom32-0/d-cpuminer) - pure C miner by phantom32 & revoxhere * [Go Miner](https://github.com/yippiez/go-miner) by yippiez * [ducominer](https://github.com/its5Q/ducominer) by its5Q + * [nxducominer](https://github.com/tbwcjw/nxducominer/) - Miner for the Nintendo Switch by tbwcjw * [Unofficial miners directory](https://github.com/revoxhere/duino-coin/tree/master/Unofficial%20miners) * [Julia Miner](https://github.com/revoxhere/duino-coin/blob/master/Unofficial%20miners/Julia_Miner.jl) by revoxhere * [Ruby Miner](https://github.com/revoxhere/duino-coin/blob/master/Unofficial%20miners/Ruby_Miner.rb) by revoxhere @@ -232,6 +233,7 @@ Please note the DUCO/day column has been removed since version 4.0 changed the r * [Home Assistant sensors package](https://github.com/mavotronik/Duinocoin_homeassistant) by mavotronik * [ESPGUITOOL](https://github.com/CGameDev/ESPGUITOOL) by kazutokirigaya * [DUCO Hashrate Monitor](https://gitlab.com/IT-Berater/twhashrate) hashrate java swing speedometer gui by IT-Berater + * [DUCO Wallet ESP32 Ticker](https://gitlab.com/IT-Berater/twesp32/-/blob/main/README-DUINO.md) Displaying Duino-Coin Wallet Status on an OLED Display with ESP32 by IT-Berater You may also view a similar list on the [website](https://duinocoin.com/apps). diff --git a/Resources/AVR_Miner_langs.json b/Resources/AVR_Miner_langs.json index 1bb2db73..50a99750 100644 --- a/Resources/AVR_Miner_langs.json +++ b/Resources/AVR_Miner_langs.json @@ -520,8 +520,8 @@ "mining_not_exist_warning": " Убедитесь в том, что вы правильно ввели имя пользователя. Пожалуйста, проверьте ваш файл настроек. Пробуем еще раз через 10с", "load_config_error": " Ошибка загрузки файла настроек (", "load_config_error_warning": "/Miner_config.cfg). Попробуйте удалить его и перезапустить настройку. Выход через 10с", - "new_version": "A new version is available, you want to update miner [Y/n] ? ", - "updating": "The miner is outdated. Updating...." + "new_version": "Доступна новая версия, хотите обновить майнер [Y/n] ? ", + "updating": "Майнер устарел. Обновляю...." }, "spanish": { "translation_autor": "HGEpro", diff --git a/Resources/README_TRANSLATIONS/README_id_ID.md b/Resources/README_TRANSLATIONS/README_id_ID.md index bfe5d02e..dc13880a 100644 --- a/Resources/README_TRANSLATIONS/README_id_ID.md +++ b/Resources/README_TRANSLATIONS/README_id_ID.md @@ -114,7 +114,6 @@ Setelah melakukan ini, Anda dapat meluncurkan perangkat lunak (cukup klik dua ka * [ESPython DUCO Miner](https://github.com/fabiopolancoe/ESPython-DUCO-Miner) - Penambang MicroPython untuk papan modul ESP oleh fabiopolancoe * [DUCO Miner for Nintendo 3DS](https://github.com/BunkerInnovations/duco-3ds) - Python miner for Nintendo 3DS by PhereloHD & HGEpro * [Dockerized DUCO Miner](https://github.com/Alicia426/Dockerized_DUCO_Miner_minimal) - Penambang di Docker oleh Alicia426 - * [nonceMiner](https://github.com/colonelwatch/nonceMiner) - Fastest Duino-Coin miner available by colonelwatch * [NodeJS-DuinoCoin-Miner](https://github.com/DarkThinking/NodeJS-DuinoCoin-Miner/) - simple NodeJS miner by DarkThinking * [d-cpuminer](https://github.com/phantom32-0/d-cpuminer) - miner C murni oleh phantom32 & revoxhere * [Go Miner](https://github.com/yippiez/go-miner) by yippiez diff --git a/Resources/README_TRANSLATIONS/README_it_IT.md b/Resources/README_TRANSLATIONS/README_it_IT.md index fdbc8ef3..3762d0c3 100644 --- a/Resources/README_TRANSLATIONS/README_it_IT.md +++ b/Resources/README_TRANSLATIONS/README_it_IT.md @@ -174,7 +174,6 @@ Codice sorgente del server, documentazione per chiamate API, e librerie ufficial * [STM8 DUCO Miner](https://github.com/BBS215/STM8_DUCO_miner) - firmware STM8S per minare DUCO, di BBS215 * [DuinoCoinbyLabVIEW](https://github.com/ericddm/DuinoCoinbyLabVIEW) - miner per la famiglia LabVIEW, di ericddm * [Duino-JS](https://github.com/Hoiboy19/Duino-JS) - un miner JavaScript che puoi implementare facilmente nel tuo sito, di Hoiboy19 - * [Mineuino](https://github.com/VatsaDev/Mineuino) - monetizzazione per siti web, di VatsaDev * [hauchel's duco-related stuff repository](https://github.com/hauchel/duco/) - raccolta di vario codice per minare DUCO su altri microcontrollori * [duino-coin-php-miner](https://github.com/ricardofiorani/duino-coin-php-miner) miner in PHP per Docker, di ricardofiorani * [duino-coin-kodi](https://github.com/SandUhrGucker/duino-coin-kodi) - addon di mining per Kodi Media Center, di SandUhrGucker diff --git a/Resources/README_TRANSLATIONS/README_kr_KR.md b/Resources/README_TRANSLATIONS/README_kr_KR.md index df6d7b3a..e3a49bb6 100644 --- a/Resources/README_TRANSLATIONS/README_kr_KR.md +++ b/Resources/README_TRANSLATIONS/README_kr_KR.md @@ -173,7 +173,6 @@ Duino-Coin 프로젝트에 대한 기여해 주시면 감사하겠습니다. * [ESPython DUCO Miner](https://github.com/fabiopolancoe/ESPython-DUCO-Miner) - ESP 보드용 MicroPython 채굴기 by fabiopolancoe * [DUCO Miner for Nintendo 3DS](https://github.com/BunkerInnovations/duco-3ds) - Nintendo 3DS용 Python 채굴기 PhereloHD & HGEpro * [Dockerized DUCO Miner](https://github.com/Alicia426/Dockerized_DUCO_Miner_minimal) - Docker 이용한 채굴기 by Alicia426 - * [nonceMiner](https://github.com/colonelwatch/nonceMiner) - 가장 빠른 Duino-Coin 채굴기 by colonelwatch * [NodeJS-DuinoCoin-Miner](https://github.com/DarkThinking/NodeJS-DuinoCoin-Miner/) - 간단한 NodeJS 채굴기 by DarkThinking * [d-cpuminer](https://github.com/phantom32-0/d-cpuminer) - 퓨어 C 채굴기 by phantom32 & revoxhere * [Go Miner](https://github.com/yippiez/go-miner) by yippiez diff --git a/Resources/README_TRANSLATIONS/README_pl_PL.md b/Resources/README_TRANSLATIONS/README_pl_PL.md index 4b25a85b..da02ee51 100644 --- a/Resources/README_TRANSLATIONS/README_pl_PL.md +++ b/Resources/README_TRANSLATIONS/README_pl_PL.md @@ -113,7 +113,6 @@ Pakiet Duino-Coin dla AUR jest utrzymywany przez by [PhereloHD](https://github.c * [ESPython DUCO Miner](https://github.com/fabiopolancoe/ESPython-DUCO-Miner) by fabiopolancoe * [DUCO Miner for Nintendo 3DS](https://github.com/BunkerInnovations/duco-3ds) by PhereloHD & HGEpro * [Dockerized DUCO Miner](https://github.com/Alicia426/Dockerized_DUCO_Miner_minimal) by Alicia426 -* [nonceMiner](https://github.com/colonelwatch/nonceMiner) by colonelwatch * [NodeJS-DuinoCoin-Miner](https://github.com/DarkThinking/NodeJS-DuinoCoin-Miner/) by DarkThinking * [d-cpuminer](https://github.com/phantom32-0/d-cpuminer) by phantom32 * [Go Miner](https://github.com/yippiez/go-miner) by yippiez diff --git a/Resources/README_TRANSLATIONS/README_pt_BR.md b/Resources/README_TRANSLATIONS/README_pt_BR.md index 5243029d..97d202a8 100644 --- a/Resources/README_TRANSLATIONS/README_pt_BR.md +++ b/Resources/README_TRANSLATIONS/README_pt_BR.md @@ -165,7 +165,6 @@ O código-fonte do servidor, a documentação para chamadas de API e bibliotecas * [ESPython DUCO Miner](https://github.com/fabiopolancoe/ESPython-DUCO-Miner) - Minerador em MicroPython para placas ESP, feito por fabiopolancoe * [DUCO Miner for Nintendo 3DS](https://github.com/BunkerInnovations/duco-3ds) - Minerador em Python para Nintendo 3DS, feito por PhereloHD & HGEpro * [Dockerized DUCO Miner](https://github.com/Alicia426/Dockerized_DUCO_Miner_minimal) - Mineradora em Docker, feito por Alicia426 - * [nonceMiner](https://github.com/colonelwatch/nonceMiner) - A mineradora de Duino-Coin mais rápida disponível, feita por colonelwatch * [NodeJS-DuinoCoin-Miner](https://github.com/DarkThinking/NodeJS-DuinoCoin-Miner/) - Minerador simples em NodeJS, feita pelo DarkThinking * [d-cpuminer](https://github.com/phantom32-0/d-cpuminer) - Mineradora em C, feito por phantom32 & revoxhere * [Go Miner](https://github.com/yippiez/go-miner) por yippiez diff --git a/Resources/README_TRANSLATIONS/README_ru_RU.md b/Resources/README_TRANSLATIONS/README_ru_RU.md index 00273c7d..bd86f071 100644 --- a/Resources/README_TRANSLATIONS/README_ru_RU.md +++ b/Resources/README_TRANSLATIONS/README_ru_RU.md @@ -113,7 +113,6 @@ py -m pip install -r requirements.txt * [ESPython DUCO Miner](https://github.com/fabiopolancoe/ESPython-DUCO-Miner) - MicroPython майнер для плат ESP от fabiopolancoe * [DUCO Miner for Nintendo 3DS](https://github.com/BunkerInnovations/duco-3ds) - Python майнер для Nintendo 3DS от PhereloHD & HGEpro * [Dockerized DUCO Miner](https://github.com/Alicia426/Dockerized_DUCO_Miner_minimal) - Майнер в докере от Alicia426 -* [nonceMiner](https://github.com/colonelwatch/nonceMiner) - Самый быстрый из доступных майнер от colonelwatch * [NodeJS-DuinoCoin-Miner](https://github.com/DarkThinking/NodeJS-DuinoCoin-Miner/) - Простой майнер NodeJS от DarkThinking * [d-cpuminer](https://github.com/phantom32-0/d-cpuminer) - Майнер на чистом C от phantom32 & revox * [Go Miner](https://github.com/yippiez/go-miner) От yippiez diff --git a/Resources/README_TRANSLATIONS/README_th_TH.md b/Resources/README_TRANSLATIONS/README_th_TH.md index 9dde7ede..fc7a57e5 100644 --- a/Resources/README_TRANSLATIONS/README_th_TH.md +++ b/Resources/README_TRANSLATIONS/README_th_TH.md @@ -109,7 +109,6 @@ python3 -m pip install -r requirements.txt # Install pip dependencies * [ESPython DUCO Miner](https://github.com/fabiopolancoe/ESPython-DUCO-Miner) - ตัวขุดไมโครไพธอนสำหรับบอร์ด ESP โดย fabiopolancoe * [DUCO Miner for Nintendo 3DS](https://github.com/BunkerInnovations/duco-3ds) - ตัวขุดไพธอนสำหรับ Nintendo 3DS โดย PhereloHD & HGEpro * [Dockerized DUCO Miner](https://github.com/Alicia426/Dockerized_DUCO_Miner_minimal) - ตัวขุดใน Docker โดย Alicia426 - * [nonceMiner](https://github.com/colonelwatch/nonceMiner) - ตัวขุด Duino-Coin อย่างเร็ว โดย colonelwatch * [NodeJS-DuinoCoin-Miner](https://github.com/DarkThinking/NodeJS-DuinoCoin-Miner/) - ตัวขุด NodeJS อย่างง่าย โดย DarkThinking * [d-cpuminer](https://github.com/phantom32-0/d-cpuminer) - ตัวขุด pure C โดย phantom32 & revoxhere * [Go Miner](https://github.com/yippiez/go-miner) โดย yippiez diff --git a/Resources/README_TRANSLATIONS/README_tr_TR.md b/Resources/README_TRANSLATIONS/README_tr_TR.md index 4667e743..5dae3e0f 100644 --- a/Resources/README_TRANSLATIONS/README_tr_TR.md +++ b/Resources/README_TRANSLATIONS/README_tr_TR.md @@ -92,7 +92,6 @@ Bunu yaptıktan sonra istediğiniz yazılımı çalıştırabilirsiniz (istediğ * [ESPython DUCO Miner](https://github.com/fabiopolancoe/ESPython-DUCO-Miner) - fabiopolancoe tarafından ESP kartları için MicroPython'da yazılmmış madenci * [DUCO Miner for Nintendo 3DS](https://github.com/BunkerInnovations/duco-3ds) - PhereloHD & HGEpro tarafından Nintendo 3DS için madenci yazılımı * [Dockerized DUCO Miner](https://github.com/Alicia426/Dockerized_DUCO_Miner_minimal) - Alicia426 tarafından Docker içinde çalışan madenci - * [nonceMiner](https://github.com/colonelwatch/nonceMiner) - colonelwatch tarafından şu ana kadar ki en hızlı madenci yazılımı * [NodeJS-DuinoCoin-Miner](https://github.com/DarkThinking/NodeJS-DuinoCoin-Miner/) - DarkThinking tarafından basit bir NodeJS'de yazılmış madenci * [d-cpuminer](https://github.com/phantom32-0/d-cpuminer) - phantom32 & revoxhere tarafından saf C içinde yazılmış madenci * [Go Miner](https://github.com/yippiez/go-miner) yippiez tarafından Go'da yazılmış madenci diff --git a/Resources/README_TRANSLATIONS/README_zh_TW.md b/Resources/README_TRANSLATIONS/README_zh_TW.md index e5b235b1..83febf0e 100644 --- a/Resources/README_TRANSLATIONS/README_zh_TW.md +++ b/Resources/README_TRANSLATIONS/README_zh_TW.md @@ -118,7 +118,6 @@ After doing this, you are good to go with launching the software (e.g. `python3 * [ESPython DUCO Miner](https://github.com/fabiopolancoe/ESPython-DUCO-Miner) - MicroPython miner for ESP boards by fabiopolancoe * [DUCO Miner for Nintendo 3DS](https://github.com/BunkerInnovations/duco-3ds) - Python miner for Nintendo 3DS by PhereloHD & HGEpro * [Dockerized DUCO Miner](https://github.com/Alicia426/Dockerized_DUCO_Miner_minimal) - Miner in Docker by Alicia426 - * [nonceMiner](https://github.com/colonelwatch/nonceMiner) - Fastest Duino-Coin miner available by colonelwatch * [NodeJS-DuinoCoin-Miner](https://github.com/DarkThinking/NodeJS-DuinoCoin-Miner/) - simple NodeJS miner by DarkThinking * [d-cpuminer](https://github.com/phantom32-0/d-cpuminer) - pure C miner by phantom32 & revoxhere * [Go Miner](https://github.com/yippiez/go-miner) by yippiez