Add system information

- Also cleanup code
- Switch to almost realtime data reading
This commit is contained in:
Blaster4385 2023-05-20 18:44:22 +05:30
parent 5fd76b071a
commit 364c5c0057
6 changed files with 197 additions and 195 deletions

View file

@ -6,6 +6,9 @@ int16_t cpuTempGlobal = defaultValue;
int16_t cpuTemp[8] = {defaultValue, defaultValue, defaultValue,defaultValue, defaultValue, defaultValue, defaultValue, defaultValue}; int16_t cpuTemp[8] = {defaultValue, defaultValue, defaultValue,defaultValue, defaultValue, defaultValue, defaultValue, defaultValue};
uint32_t ramFree = defaultValue; uint32_t ramFree = defaultValue;
uint32_t ramMax = defaultValue; uint32_t ramMax = defaultValue;
String OS = "";
String KernelVer = "";
String Uptime = "";
static int8_t extractArray(String &command, int16_t *array) static int8_t extractArray(String &command, int16_t *array)
{ {

3
cpu.h
View file

@ -17,5 +17,8 @@ extern int16_t cpuTempGlobal;
extern int16_t cpuTemp[8]; extern int16_t cpuTemp[8];
extern uint32_t ramMax; extern uint32_t ramMax;
extern uint32_t ramFree; extern uint32_t ramFree;
extern String OS;
extern String KernelVer;
extern String Uptime;
#endif // __CPU_H__ #endif // __CPU_H__

203
gfx_1.cpp
View file

@ -4,35 +4,31 @@
#include "Adafruit_GFX.h" #include "Adafruit_GFX.h"
#include <Adafruit_ILI9341.h> #include <Adafruit_ILI9341.h>
bool gfx1_refresh = true; static uint8_t s_time_tab[6] = { '0', '0', ':', '0', '0', 0 };
static uint8_t s_time_tab[6] = {'0', '0', ':', '0', '0', 0};
static uint8_t s_localHum = 0, s_localTemp = 0, s_cpuTemp = 255; static uint8_t s_localHum = 0, s_localTemp = 0, s_cpuTemp = 255;
static int16_t s_cpu_usage = 255; static int16_t s_cpu_usage = 255;
static uint32_t s_ram_free = 255, s_ram_max = 255; static uint32_t s_ram_free = 255, s_ram_max = 255;
static String s_os = "Unknown", s_kernel = "Unknown", s_uptime = "Unknown";
// 5px size // 5px size
static void gfx_update_toolbar(); static void gfx_update_toolbar();
static void gfx_update_cpu(); static void gfx_update_cpu();
static void gfx_update_mem(); static void gfx_update_mem();
static void gfx_update_sys_info();
static void writeArray(const char *buf) static void writeArray(const char *buf) {
{ uint8_t c = 0;
uint8_t c= 0; while (buf[c] != 0)
while(buf[c] != 0)
tft.write(buf[c++]); tft.write(buf[c++]);
} }
void gfx1_udpate() void gfx1_udpate() {
{
// if(!gfx1_refresh)
// return ;
gfx1_refresh = false;
gfx_update_toolbar(); gfx_update_toolbar();
gfx_update_cpu(); gfx_update_cpu();
gfx_update_mem(); gfx_update_mem();
gfx_update_sys_info();
} }
#define LINE_Y_REL 29 #define LINE_Y_REL 29
@ -43,164 +39,189 @@ void gfx1_udpate()
char buf[20]; char buf[20];
void gfx1_layout() void gfx1_layout() {
{ uint8_t c = 0;
uint8_t c= 0;
tft.fillScreen(ILI9341_BLACK); tft.fillScreen(ILI9341_BLACK);
tft.drawLine(10, 18, 310, 18, ILI9341_YELLOW); tft.drawLine(10, 18, 310, 18, ILI9341_YELLOW);
tft.setTextColor(ILI9341_YELLOW, ILI9341_BLACK); tft.setTextColor(ILI9341_YELLOW, ILI9341_BLACK);
// Temp
tft.setCursor(35, 0); tft.setCursor(35, 0);
tft.setTextSize(1); tft.setTextSize(1);
tft.write('o'); tft.write('o');
tft.setTextSize(2); tft.setTextSize(2);
tft.setCursor(35+8, 2); tft.setCursor(35 + 8, 2);
tft.write('C'); tft.write('C');
//Humidity
// Humidity
tft.setCursor(300, 2); tft.setCursor(300, 2);
tft.write('%'); tft.write('%');
// CPU rect // CPU
tft.setTextSize(2); tft.setTextSize(2);
tft.drawRoundRect(5, 45, 150, 90, 10, ILI9341_DARKCYAN); tft.drawRoundRect(5, 25, 150, 90, 10, ILI9341_RED);
tft.drawLine(5, 45+LINE_Y_REL, 154, 45+LINE_Y_REL, ILI9341_DARKCYAN); tft.drawLine(5, 25 + LINE_Y_REL, 154, 25 + LINE_Y_REL, ILI9341_RED);
tft.setTextColor(ILI9341_DARKCYAN, ILI9341_BLACK); tft.setTextColor(ILI9341_RED, ILI9341_BLACK);
tft.setCursor(60, 45+TEXT_Y_REL); tft.setCursor(60, 25 + TEXT_Y_REL);
sprintf(buf, "CPU"); sprintf(buf, "CPU");
writeArray(buf); writeArray(buf);
tft.setCursor(15, 45+FIRST_TEXT_Y_REL); tft.setCursor(15, 25 + FIRST_TEXT_Y_REL);
sprintf(buf, "Usage:"); sprintf(buf, "Usage:");
writeArray(buf); writeArray(buf);
tft.setCursor(15, 45+FIRST_TEXT_Y_REL + TEXT_ESPACE_SHORT_Y); tft.setCursor(15, 25 + FIRST_TEXT_Y_REL + TEXT_ESPACE_SHORT_Y);
sprintf(buf, "Temp:"); sprintf(buf, "Temp:");
writeArray(buf); writeArray(buf);
tft.setCursor(15, 45+FIRST_TEXT_Y_REL + TEXT_ESPACE_SHORT_Y *2); tft.setCursor(15, 25 + FIRST_TEXT_Y_REL + TEXT_ESPACE_SHORT_Y * 2);
// memory // memory
tft.drawRoundRect(165, 45, 150, 90, 10, ILI9341_GREEN); tft.drawRoundRect(165, 25, 150, 90, 10, ILI9341_GREEN);
tft.drawLine(165, 45+LINE_Y_REL, 314, 45+LINE_Y_REL, ILI9341_GREEN); tft.drawLine(165, 25 + LINE_Y_REL, 314, 25 + LINE_Y_REL, ILI9341_GREEN);
tft.setTextColor(ILI9341_GREEN, ILI9341_BLACK); tft.setTextColor(ILI9341_GREEN, ILI9341_BLACK);
tft.setCursor(205, 45+TEXT_Y_REL); tft.setCursor(205, 25 + TEXT_Y_REL);
sprintf(buf, "MEMORY"); sprintf(buf, "MEMORY");
writeArray(buf); writeArray(buf);
tft.setCursor(175, 45+FIRST_TEXT_Y_REL); tft.setCursor(175, 25 + FIRST_TEXT_Y_REL);
sprintf(buf, "Max:"); sprintf(buf, "Max:");
writeArray(buf); writeArray(buf);
tft.setCursor(175, 45+FIRST_TEXT_Y_REL + TEXT_ESPACE_SHORT_Y); tft.setCursor(175, 25 + FIRST_TEXT_Y_REL + TEXT_ESPACE_SHORT_Y);
sprintf(buf, "Free:"); sprintf(buf, "Free:");
writeArray(buf); writeArray(buf);
gfx1_refresh = true; // sysinfo
tft.setTextSize(2);
tft.drawRoundRect(5, 125, 310, 110, 10, ILI9341_CYAN);
tft.drawLine(5, 125 + LINE_Y_REL, 314, 125 + LINE_Y_REL, ILI9341_CYAN);
tft.setTextColor(ILI9341_CYAN, ILI9341_BLACK);
tft.setCursor(55, 125 + TEXT_Y_REL);
sprintf(buf, "System Information");
writeArray(buf);
tft.setCursor(15, 125 + FIRST_TEXT_Y_REL);
sprintf(buf, "OS:");
writeArray(buf);
tft.setCursor(15, 125 + FIRST_TEXT_Y_REL + TEXT_ESPACE_SHORT_Y);
sprintf(buf, "Kernel:");
writeArray(buf);
tft.setCursor(15, 125 + FIRST_TEXT_Y_REL + TEXT_ESPACE_SHORT_Y * 2);
sprintf(buf, "Uptime:");
writeArray(buf);
gfx1_udpate(); gfx1_udpate();
} }
void get_formated_space(int32_t valueMb) void get_formated_space(int32_t valueMb) {
{
int8_t unity = 0; int8_t unity = 0;
if(valueMb > 999) if (valueMb > 999) {
{
valueMb = valueMb / 1024; valueMb = valueMb / 1024;
unity = 1; // GB unity = 1; // GB
} }
if(valueMb > 9999) if (valueMb > 9999) {
{
valueMb = valueMb / 1024; valueMb = valueMb / 1024;
unity = 2; // TB unity = 2; // TB
} }
if(unity == 0) if (unity == 0)
sprintf(buf, "%4d MB", valueMb); sprintf(buf, "%4d MB", valueMb);
else if(unity == 1) else if (unity == 1)
sprintf(buf, "%4d GB", valueMb); sprintf(buf, "%4d GB", valueMb);
else else
sprintf(buf, "%4d TB", valueMb); sprintf(buf, "%4d TB", valueMb);
} }
static void gfx_update_mem() static void gfx_update_mem() {
{ tft.setTextColor(ILI9341_GREEN, ILI9341_BLACK);
tft.setTextColor(ILI9341_GREEN, ILI9341_BLACK); if (s_ram_max != ramMax) {
if(s_ram_max != ramMax) tft.setCursor(175 + 50, 25 + FIRST_TEXT_Y_REL);
{
tft.setCursor(175 + 50, 45+FIRST_TEXT_Y_REL);
get_formated_space(ramMax); get_formated_space(ramMax);
writeArray(buf); writeArray(buf);
s_ram_free = ramMax; s_ram_max = ramMax;
} }
if(s_ram_free != ramFree) if (s_ram_free != ramFree) {
{ tft.setCursor(175 + 50, 25 + FIRST_TEXT_Y_REL + TEXT_ESPACE_SHORT_Y);
tft.setCursor(175 + 50, 45+FIRST_TEXT_Y_REL + TEXT_ESPACE_SHORT_Y);
get_formated_space(ramFree); get_formated_space(ramFree);
writeArray(buf); writeArray(buf);
s_ram_free = ramFree; s_ram_free = ramFree;
} }
} }
//s_cpu_usage = 0; static void gfx_update_cpu() {
static void gfx_update_cpu() tft.setTextColor(ILI9341_RED, ILI9341_BLACK);
{ if (cpuUsageGlobal != s_cpu_usage) {
tft.setTextColor(ILI9341_DARKCYAN, ILI9341_BLACK); tft.setCursor(15 + 75, 25 + FIRST_TEXT_Y_REL);
if(cpuUsageGlobal != s_cpu_usage)
{
tft.setCursor(15+75, 45+FIRST_TEXT_Y_REL);
sprintf(buf, "%3d %%", cpuUsageGlobal); sprintf(buf, "%3d %%", cpuUsageGlobal);
writeArray(buf); writeArray(buf);
s_cpu_usage = cpuUsageGlobal; s_cpu_usage = cpuUsageGlobal;
} }
if(s_cpuTemp != cpuTempGlobal) if (s_cpuTemp != cpuTempGlobal) {
{ tft.setCursor(15 + 75, 25 + FIRST_TEXT_Y_REL + TEXT_ESPACE_SHORT_Y);
tft.setCursor(15 + 75, 45+FIRST_TEXT_Y_REL + TEXT_ESPACE_SHORT_Y);
sprintf(buf, "%3d ", cpuTempGlobal); sprintf(buf, "%3d ", cpuTempGlobal);
writeArray(buf); writeArray(buf);
tft.setCursor(15 + 115, 45+FIRST_TEXT_Y_REL + TEXT_ESPACE_SHORT_Y - 2); tft.setCursor(15 + 115, 25 + FIRST_TEXT_Y_REL + TEXT_ESPACE_SHORT_Y - 2);
tft.setTextSize(1); tft.setTextSize(1);
tft.write('o'); tft.write('o');
tft.setTextSize(2); tft.setTextSize(2);
tft.setCursor(15 + 115 +8, 45+FIRST_TEXT_Y_REL + TEXT_ESPACE_SHORT_Y); tft.setCursor(15 + 115 + 8, 25 + FIRST_TEXT_Y_REL + TEXT_ESPACE_SHORT_Y);
tft.write('C'); tft.write('C');
s_cpuTemp = cpuTempGlobal; s_cpuTemp = cpuTempGlobal;
} }
} }
static void gfx_update_toolbar() static void gfx_update_sys_info() {
{ tft.setTextColor(ILI9341_CYAN, ILI9341_BLACK);
uint8_t c= 0;
tft.setCursor(15 + 50, 125 + FIRST_TEXT_Y_REL);
sprintf(buf, "%s", OS);
writeArray(buf);
s_os = OS;
tft.setCursor(15 + 95, 125 + FIRST_TEXT_Y_REL + TEXT_ESPACE_SHORT_Y);
sprintf(buf, "%s ", KernelVer);
writeArray(buf);
tft.setCursor(15 + 115, 125 + FIRST_TEXT_Y_REL + TEXT_ESPACE_SHORT_Y - 2);
s_kernel = KernelVer;
tft.setCursor(15 + 95, 125 + FIRST_TEXT_Y_REL + TEXT_ESPACE_SHORT_Y * 2);
sprintf(buf, "%s ", Uptime);
writeArray(buf);
tft.setCursor(15 + 115, 125 + FIRST_TEXT_Y_REL + TEXT_ESPACE_SHORT_Y * 2 - 2);
s_uptime = Uptime;
}
static void gfx_update_toolbar() {
uint8_t c = 0;
char buf[5]; char buf[5];
tft.setTextColor(ILI9341_YELLOW, ILI9341_BLACK); tft.setTextColor(ILI9341_YELLOW, ILI9341_BLACK);
//time
if(s_time_tab[4] != time_tab[4] || s_time_tab[3] != time_tab[3] if (s_time_tab[4] != time_tab[4] || s_time_tab[3] != time_tab[3]
|| s_time_tab[1] != time_tab[1] || s_time_tab[0] != time_tab[0]) || s_time_tab[1] != time_tab[1] || s_time_tab[0] != time_tab[0]) {
{ tft.setTextSize(2);
tft.setTextSize(2); tft.setCursor(135, 2);
tft.setCursor(135, 2);
while (c < 5) {
while(c < 5) uint8_t car = time_tab[c];
{ s_time_tab[c] = car;
uint8_t car = time_tab[c]; tft.write(car);
s_time_tab[c] = car; c++;
tft.write(car); }
c++;
} }
}
//temp //temp
if(s_localTemp != localTemp) if (s_localTemp != localTemp) {
{
tft.setCursor(10, 2); tft.setCursor(10, 2);
if(localTemp != 255) if (localTemp != 255)
sprintf(buf, "%2d", localTemp); sprintf(buf, "%2d", localTemp);
else else
sprintf(buf, "--"); sprintf(buf, "--");
writeArray(buf); writeArray(buf);
s_localTemp = localTemp; s_localTemp = localTemp;
} }
// humidity // humidity
if(s_localHum != localHum) if (s_localHum != localHum) {
{
tft.setCursor(275, 2); tft.setCursor(275, 2);
if(localHum != 255) if (localHum != 255)
sprintf(buf, "%2d", localHum); sprintf(buf, "%2d", localHum);
else else
sprintf(buf, "--"); sprintf(buf, "--");

View file

@ -8,7 +8,4 @@ extern Adafruit_ILI9341 tft;
extern void gfx1_udpate(); extern void gfx1_udpate();
extern void gfx1_layout(); extern void gfx1_layout();
extern bool gfx1_refresh;
#endif #endif

View file

@ -6,17 +6,17 @@
#include "datetimeHandler.h" #include "datetimeHandler.h"
#include "gfx_1.h" #include "gfx_1.h"
#define TFT_DC D4 #define TFT_DC D4
#define TFT_CS D2 #define TFT_CS D2
#define TFT_RESET D3 #define TFT_RESET D3
#define DHTPIN D8 #define DHTPIN D8
#define DHTTYPE DHT22 #define DHTTYPE DHT22
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC); Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);
DHT dht(DHTPIN, DHTTYPE); DHT dht(DHTPIN, DHTTYPE);
static uint32_t tempTime = 0; static uint32_t tempTime = 0;
static uint32_t rtcTime = 0; static uint32_t rtcTime = 0;
static uint32_t displayTime = 0; static uint32_t displayTime = 0;
void setup() { void setup() {
@ -26,76 +26,73 @@ void setup() {
} }
void update(String command) { void update(String command) {
int delimiterIndex = command.indexOf('='); if (!isnan(dht.readTemperature())) {
// Serial.println(command); localHum = dht.readHumidity();
if (delimiterIndex != -1) { localTemp = dht.readTemperature() - 4;
String key = command.substring(0, delimiterIndex); }
String value = command.substring(delimiterIndex + 1);
Serial.print(key);
// Check the key and assign the corresponding value String keys[] = { "CpuTemp", "CpuUsage", "RamMax", "RamFree", "Time", "OS", "Kernel", "Uptime" };
if (key.equals("CpuTemp")) { String values[] = { "", "", "", "", "", "", "", "" };
setCpuTemp(value);
Serial.print("Received CPU temperature: "); for (int i = 0; i < std::size(keys); i++) {
Serial.println(value);
// gfx1_udpate(); int index = command.indexOf(keys[i]);
} else if (key.equals("CpuUsage")) {
setCpuUsage(value); if (index != -1) {
Serial.print("Received CPU usage: "); String value = command.substring(index + keys[i].length() + 1, command.indexOf(",", index + keys[i].length() + 1));
Serial.println(value); values[i] = value;
// gfx1_udpate();
} else if (key.equals("RamFree")) {
setRamFree(value);
Serial.print("Received Ram free: ");
Serial.println(value);
// gfx1_udpate();
} else if (key.equals("RamMax")) {
setRamMax(value);
Serial.print("Received Ram max: ");
Serial.println(value);
// gfx1_udpate();
} else if (key.equals("Time")) {
setTime(value);
Serial.print("Received Time: ");
Serial.println(value);
// gfx1_udpate();
}
} }
gfx1_refresh = true; }
gfx1_udpate();
for (int i = 0; i < std::size(values); i++) {
Serial.print(keys[i]);
Serial.print(" = ");
Serial.println(values[i]);
switch (i) {
case 0:
if (values[i] != "")
setCpuTemp(values[i]);
break;
case 1:
if (values[i] != "")
setCpuUsage(values[i]);
break;
case 2:
if (values[i] != "")
setRamMax(values[i]);
break;
case 3:
if (values[i] != "")
setRamFree(values[i]);
break;
case 4:
if (values[i] != "")
setTime(values[i]);
break;
case 5:
if (values[i] != "")
OS = values[i];
break;
case 6:
if (values[i] != "")
KernelVer = values[i];
break;
case 7:
if (values[i] != "")
Uptime = values[i];
break;
}
}
gfx1_udpate();
} }
void loop() { void loop() {
Serial.println("Enter data:");
// while (Serial.available() == 0) {}
String command = Serial.readString(); String command = Serial.readString();
command.trim(); command.trim();
Serial.println(command);
if(!isnan(dht.readTemperature()))
{
localHum = dht.readHumidity();
localTemp = dht.readTemperature() - 4;
Serial.println(localTemp);
gfx1_refresh = true;
gfx1_udpate();
}
// else
// {
// localHum = 255;
// localTemp = 255;
// }
update(command); update(command);
// delay(1000);
// if ( currentTime > displayTime ) {
// displayTime = currentTime + 100000;
// }
} }
void initHardware() void initHardware() {
{
pinMode(TFT_RESET, OUTPUT); pinMode(TFT_RESET, OUTPUT);
digitalWrite(TFT_RESET, LOW); digitalWrite(TFT_RESET, LOW);
delay(1000); delay(1000);
@ -104,5 +101,4 @@ void initHardware()
tft.begin(); tft.begin();
tft.setRotation(3); tft.setRotation(3);
dht.begin(); dht.begin();
// delay(3000);
} }

View file

@ -5,12 +5,10 @@ from datetime import datetime
from datetime import timedelta from datetime import timedelta
import psutil import psutil
import serial import serial
from gettext import c2py
from time import sleep from time import sleep
import sensors import sensors
import subprocess import subprocess
import math import math
import pyowm
import os import os
CPU_TEMP_PATH = '/sys/devices/pci0000:00/0000:00:18.3/hwmon/hwmon2/temp1_input' CPU_TEMP_PATH = '/sys/devices/pci0000:00/0000:00:18.3/hwmon/hwmon2/temp1_input'
@ -27,37 +25,36 @@ def send_command(command):
sleep(0.1) sleep(0.1)
def set_time(date_time): def set_time(date_time):
request = '\nTime=%s\r\n' % date_time.strftime('%H:%M:%S') curr_time=date_time.strftime('%H:%M:%S')
send_command(request) return curr_time
def set_max(): def set_max():
ram_max = int(psutil.virtual_memory().total / (1024.*1024.)) ram_max = int(psutil.virtual_memory().total / (1024.*1024.))
request = 'RamMax=%d\r\n' % ram_max # request = 'RamMax=%d\r\n' % ram_max
send_command(request) # send_command(request)
return ram_max
def set_free(): def set_free():
ram_free = int(psutil.virtual_memory().free / (1024.*1024.)) ram_free = int(psutil.virtual_memory().free / (1024.*1024.))
request = 'RamFree=%d\r\n' % ram_free # request = 'RamFree=%d\r\n' % ram_free
send_command(request) # send_command(request)
return ram_free
def set_system_info(): def set_OS():
with open('/etc/os-release', 'r') as f: with open('/etc/os-release', 'r') as f:
for line in f: for line in f:
if line.startswith('NAME='): if line.startswith('NAME='):
OSName = line.split('"')[1] OSName = line.split('"')[1]
break break
request = 'OS=%s\r\n' % OSName return OSName
send_command(request)
sleep(1)
def set_kernel_version():
with open('/proc/version', 'r') as f: with open('/proc/version', 'r') as f:
for line in f: for line in f:
Kernel = line.split(' ')[2].split('-')[0] Kernel = line.split(' ')[2].split('-')[0]
break break
request = 'Kernel=%s\r\n' % Kernel return Kernel
send_command(request)
sleep(1)
def set_uptime(): def set_uptime():
uptime_seconds = psutil.boot_time() uptime_seconds = psutil.boot_time()
@ -65,35 +62,20 @@ def set_uptime():
uptime_hours = int(uptime.total_seconds() // 3600) uptime_hours = int(uptime.total_seconds() // 3600)
uptime_minutes = int((uptime.total_seconds() % 3600) // 60) uptime_minutes = int((uptime.total_seconds() % 3600) // 60)
uptime = f"{uptime_hours:02d}:{uptime_minutes:02d}" uptime = f"{uptime_hours:02d}:{uptime_minutes:02d}"
request = 'Uptime=%s\r\n' % uptime return uptime
send_command(request)
def start(tty_serial): def start():
set_system_info()
while 1: while 1:
set_uptime()
sleep(1)
cpu_temp = int(subprocess.check_output(['cat', CPU_TEMP_PATH]))/1000 cpu_temp = int(subprocess.check_output(['cat', CPU_TEMP_PATH]))/1000
requests = "\nCpuTemp="+str(math.trunc(cpu_temp))
send_command(requests)
sleep(1)
cpu_pct = psutil.cpu_percent(interval=None, percpu=False) cpu_pct = psutil.cpu_percent(interval=None, percpu=False)
cpu_global = int(cpu_pct) cpu_global = int(cpu_pct)
request = "\nCpuUsage=" + str(math.trunc(cpu_global)) request = "\nCpuTemp="+str(math.trunc(cpu_temp))+",CpuUsage="+str(math.trunc(cpu_global))+",RamMax="+str(set_max())+",RamFree="+str(set_free())+",Time="+str(set_time(datetime.now()))+",OS="+str(set_OS())+",Kernel="+str(set_kernel_version())+",Uptime="+str(set_uptime())
send_command(request) send_command(request)
sleep(1) sleep(2)
set_time(datetime.now())
sleep(1)
set_max()
sleep(1)
set_free()
sleep(1)
def main(): def main():
start('/dev/ttyUSB0') start()
if __name__ == "__main__": if __name__ == "__main__":
main() main()