Browse Source

[Improve][Modularization][Module_PowerSharing]
2022.08.12 / Chihhao Hsu

Actions:
1.Fixed some issues with allocating current
2.Added a monitoring mode to instantly watch the status of the current distribution and real-time output (use command #/root/Module_PowerSharing -watch)

Files:
1.Module_PowerSharing.c

Version: V0.02
Update: 20220812

8408 2 years ago
parent
commit
47506bf860
1 changed files with 420 additions and 126 deletions
  1. 420 126
      EVSE/Modularization/Module_PowerSharing.c

+ 420 - 126
EVSE/Modularization/Module_PowerSharing.c

@@ -6,41 +6,61 @@
  */
 #include "Module_PowerSharing.h"
 
+
 //-----------------------------------------------------------------------------
-//#define MODPS_FW_VER_TYPE_FORMAL	//V0.XX
-#define MODPS_FW_VER_TYPE_TEST		//T0.XX
+#define MODPS_FW_VER_TYPE_FORMAL	//V0.XX
+//#define MODPS_FW_VER_TYPE_TEST		//T0.XX
+
+//#define MODPS_FW_VER_NUM	(1)    //V/T0.01
+//#define MODPS_FW_DATE		("20220730")
 
-#define MODPS_FW_VER_NUM	(1)    //V/T0.01
-#define MODPS_FW_DATE		("20220730")
+#define MODPS_FW_VER_NUM	(2)    //V/T0.02
+#define MODPS_FW_DATE		("20220812")
 
 //-----------------------------------------------------------------------------
 #if (MODPS_FW_VER_NUM >= 1)
 #define MODIFY_MODPS_BALANCE_CHECK_LOOP
 #define FUNC_MODPS_APPEND_LOG
 #endif
+//-----------------------------------------------------------------------------
+#if (MODPS_FW_VER_NUM >= 2)
+#define MODIFY_MODPS_LET_ON_HAND_ALL_USED
+#define MODIFY_MODPS_REDUCE_DEBUG_LOG
+#define FUNC_MODPS_WATCH_MODE
+#endif
 
 //-----------------------------------------------------------------------------
 
-char Version_And_Date[2][10] = { 0 };
+#define HTK_USE_XPRINT
+#define HTK_BUILD_IN_LINUX
 
-void Init_FW_Info(void)
-{
-#ifdef MODPS_FW_VER_TYPE_FORMAL
-    sprintf(Version_And_Date[0], "V%4.2f", MODPS_FW_VER_NUM * 0.01);
+#ifdef HTK_BUILD_IN_LINUX
+#define HTK_PREPROCESSOR_STRING_FILE	(strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__)
+#else
+#define HTK_PREPROCESSOR_STRING_FILE	(strrchr(__FILE__, '\\') ? strrchr(__FILE__, '\\') + 1 : __FILE__)
 #endif
 
-#ifdef MODPS_FW_VER_TYPE_TEST
-    sprintf(Version_And_Date[0], "T%4.2f", MODPS_FW_VER_NUM * 0.01);
+
+#ifdef HTK_USE_XPRINT
+#define XP(FMT, ARGS...) (printf(FMT, ##ARGS))
+//#define XPH(FMT, ARGS...) (printf("[%s:%d:%s] "FMT, __FILE__, __LINE__, __FUNCTION__, ##ARGS))
+#define XPH(FMT, ARGS...) (printf("[%s:%d:%s] "FMT, HTK_PREPROCESSOR_STRING_FILE, __LINE__, __FUNCTION__, ##ARGS))
+#else
+#define XP(FMT, ARGS...)
 #endif
 
-    sprintf(Version_And_Date[1], "%s", MODPS_FW_DATE);
-}
+//-----------------------------------------------------------------------------
+
+char Version_And_Date[2][10] = { 0 };
+
+//-----------------------------------------------------------------------------
 
 struct SysConfigAndInfo		*ShmSysConfigAndInfo;
 struct StatusCodeData 		*ShmStatusCodeData;
 struct OCPP16Data			*ShmOCPP16Data;
 struct OCPP20Data			*ShmOCPP20Data;
 struct POWER_SHARING		*ShmPowerSharing;
+
 ParsingRatedCur modelnameInfo 	= {0};
 uint8_t gunType[4] 				= {0};
 uint8_t gunTotalNumber			= 0;
@@ -731,6 +751,20 @@ int conn_update_status(int socketFd, Connector_Info *connectorInfo, uint8_t conn
 				   (ShmPowerSharing->Connection_Info[idx].connectorInfo[gun_index].availableSharingCurrent != connectorInfo[gun_index].availableSharingCurrent) ||
 				   (ShmPowerSharing->Connection_Info[idx].connectorInfo[gun_index].presentOutputCurrent != connectorInfo[gun_index].presentOutputCurrent))
 				{
+#ifdef MODIFY_MODPS_REDUCE_DEBUG_LOG
+					const char* GUN_TYPE[] = { "AC", "AC3", "DC" };
+					char GunType[8] = { 0 };
+					char s[64] = { 0 };
+
+					Connector_Info* pGun = &connectorInfo[gun_index];
+					strcpy(GunType, pGun->connectorType >= 0 && pGun->connectorType <= 2 ? GUN_TYPE[pGun->connectorType] : "-");
+					sprintf(s, "C%d, G%d, %s, %d, %d, %d", idx, gun_index, GunType,
+						pGun->isGunConnected ? 1 : 0,
+						pGun->presentOutputCurrent,
+						pGun->availableSharingCurrent);
+					DEBUG_INFO("%s\n", s);
+
+#else //MODIFY_MODPS_REDUCE_DEBUG_LOG
 					switch(connectorInfo[gun_index].connectorType)
 					{
 						case CONNECTOR_TYPE_AC:
@@ -748,6 +782,7 @@ int conn_update_status(int socketFd, Connector_Info *connectorInfo, uint8_t conn
 					DEBUG_INFO("Conn-%d gun_%d available current: %d\n", idx, gun_index, connectorInfo[gun_index].availableSharingCurrent);
 					DEBUG_INFO("Conn-%d gun_%d preset output current: %d\n", idx, gun_index, connectorInfo[gun_index].presentOutputCurrent);
 					DEBUG_INFO("==================================\n");
+#endif //MODIFY_MODPS_REDUCE_DEBUG_LOG
 				}
 
 				ShmPowerSharing->Connection_Info[idx].connectorInfo[gun_index].connectorType = connectorInfo[gun_index].connectorType;
@@ -762,6 +797,44 @@ int conn_update_status(int socketFd, Connector_Info *connectorInfo, uint8_t conn
 	return result;
 }
 
+
+#ifdef MODIFY_MODPS_LET_ON_HAND_ALL_USED
+int conn_getOnHandCurrent(BOOL bUpdateChargingProfileLimit)
+{
+	static uint16_t ChargingProfileLimit = 0;
+
+	if (bUpdateChargingProfileLimit || ChargingProfileLimit == 0)
+	{
+		ChargingProfileLimit = checkChargingProfileLimit();
+	}
+
+	int result = 0;
+	for(uint8_t idx=0;idx<CONNECTION_LIMIT;idx++)
+	{
+		if(ShmPowerSharing->Connection_Info[idx].isSocketConnected)
+		{
+			for(uint8_t gun_index=0;gun_index<ShmPowerSharing->Connection_Info[idx].connectorCount;gun_index++)
+			{
+				//if (ShmPowerSharing->Connection_Info[idx].connectorInfo[gun_index].isGunConnected)
+				{
+					result += (ShmPowerSharing->Connection_Info[idx].connectorInfo[gun_index].connectorType == CONNECTOR_TYPE_AC_THREE?
+							ShmPowerSharing->Connection_Info[idx].connectorInfo[gun_index].availableSharingCurrent*3:
+							ShmPowerSharing->Connection_Info[idx].connectorInfo[gun_index].availableSharingCurrent);
+				}
+			}
+		}
+	}
+	result = ChargingProfileLimit - result;
+
+	if(ShmPowerSharing->onHandCurrent != result)
+	{
+		DEBUG_INFO("Total available current: %d\n", result);
+		ShmPowerSharing->onHandCurrent = result;
+	}
+
+	return result;
+}
+#else //MODIFY_MODPS_LET_ON_HAND_ALL_USED
 int conn_getOnHandCurrent(void)
 {
 	int result = 0;
@@ -787,6 +860,7 @@ int conn_getOnHandCurrent(void)
 
 	return result;
 }
+#endif //MODIFY_MODPS_LET_ON_HAND_ALL_USED
 
 void create_cmd_getStatus(struct Message *out)
 {
@@ -1286,26 +1360,27 @@ Connector_Info* GetIsetMaxGun(void)
 	uint16_t Imin = 0;
 	uint16_t IsetMax = 6;
 	Connector_Info* pGunIsetMax = NULL;
+	uint16_t RealIset = 0;
 
 	for (uint8_t i = 0; i < CONNECTION_LIMIT; i++)
 	{
 		pDev = &ShmPowerSharing->Connection_Info[i];
-		if (!pDev->isSocketConnected)
-		{
-			continue;
-		}
-		for (uint8_t j = 0; j < pDev->connectorCount; j++)
+		if (pDev->isSocketConnected)
 		{
-			pGun = &pDev->connectorInfo[j];
-			if (pGun->isGunConnected)
+			for (uint8_t j = 0; j < pDev->connectorCount; j++)
 			{
-				pIset = &pGun->availableSharingCurrent;
-				pIout = &pGun->presentOutputCurrent;
-				Imin = pGun->connectorType==CONNECTOR_TYPE_DC ? SHARE_MIN_DC : SHARE_MIN_AC;
-				if (*pIset > Imin && *pIout > Imin && *pIset > IsetMax)
+				pGun = &pDev->connectorInfo[j];
+				if (pGun->isGunConnected)
 				{
-					IsetMax = *pIset;
-					pGunIsetMax = pGun;
+					pIset = &pGun->availableSharingCurrent;
+					pIout = &pGun->presentOutputCurrent;
+					Imin = pGun->connectorType == CONNECTOR_TYPE_DC ? SHARE_MIN_DC : SHARE_MIN_AC;
+					RealIset = (pGun->connectorType == CONNECTOR_TYPE_AC_THREE ? *pIset * 3 : *pIset);
+					if (*pIset > Imin && *pIout > Imin && RealIset > IsetMax)
+					{
+						IsetMax = RealIset;
+						pGunIsetMax = pGun;
+					}
 				}
 			}
 		}
@@ -1328,26 +1403,27 @@ Connector_Info* GetIsetMinGun(void)
 	uint16_t Imin = 0;
 	uint16_t IsetMin = 1000;
 	Connector_Info* pGunIsetMin = NULL;
+	uint16_t RealIset = 0;
 
 	for (uint8_t i = 0; i < CONNECTION_LIMIT; i++)
 	{
 		pDev = &ShmPowerSharing->Connection_Info[i];
-		if (!pDev->isSocketConnected)
-		{
-			continue;
-		}
-		for (uint8_t j = 0; j < pDev->connectorCount; j++)
+		if (pDev->isSocketConnected)
 		{
-			pGun = &pDev->connectorInfo[j];
-			if (pGun->isGunConnected)
+			for (uint8_t j = 0; j < pDev->connectorCount; j++)
 			{
-				pIset = &pGun->availableSharingCurrent;
-				pIout = &pGun->presentOutputCurrent;
-				Imin = pGun->connectorType==CONNECTOR_TYPE_DC ? SHARE_MIN_DC : SHARE_MIN_AC;
-				if (*pIset >= Imin && *pIout >= Imin && *pIset < IsetMin)
+				pGun = &pDev->connectorInfo[j];
+				if (pGun->isGunConnected)
 				{
-					IsetMin = *pIset;
-					pGunIsetMin = pGun;
+					pIset = &pGun->availableSharingCurrent;
+					pIout = &pGun->presentOutputCurrent;
+					Imin = pGun->connectorType == CONNECTOR_TYPE_DC ? SHARE_MIN_DC : SHARE_MIN_AC;
+					RealIset = (pGun->connectorType == CONNECTOR_TYPE_AC_THREE ? *pIset * 3 : *pIset);
+					if (*pIset > Imin && *pIout > Imin && RealIset < IsetMin)
+					{
+						IsetMin = RealIset;
+						pGunIsetMin = pGun;
+					}
 				}
 			}
 		}
@@ -1361,6 +1437,31 @@ Connector_Info* GetIsetMinGun(void)
 	return pGunIsetMin;
 }
 
+typedef struct _GunInfoEx
+{
+	BOOL m_bIncreasing: 1;
+	BOOL m_bDecreasing: 1;
+	//uint16_t m_IoutMax;
+} GunInfoEx, *PGunInfoEx;
+
+#define CONNECTOR_LIMIT (4) 	//struct CONNECTION_INFO: connectorInfo[4]
+GunInfoEx g_GunInfoEx[CONNECTION_LIMIT][CONNECTOR_LIMIT];
+
+void ResetGunInfoEx(void)
+{
+	PGunInfoEx p = NULL;
+	for (uint8_t i = 0; i < CONNECTION_LIMIT; i++)
+	{
+		for (uint8_t j = 0; j < CONNECTOR_LIMIT; j++)
+		{
+			p = &g_GunInfoEx[i][j];
+			p->m_bIncreasing = FALSE;
+			p->m_bDecreasing = FALSE;
+		}
+	}
+
+	//DEBUG_INFO("#ResetGunInfoEx\n");
+}
 int balance_check_loop(void)
 {
 	DEBUG_INFO("==========[ balance_check_loop begin ]==========\n");
@@ -1368,7 +1469,7 @@ int balance_check_loop(void)
 	{
 		// Get connection info
 		conn_getConectedQuantity();
-		conn_getOnHandCurrent();
+		conn_getOnHandCurrent(TRUE);
 		conn_getConectedConnector();
 
 		// Check conn heart beat
@@ -1411,129 +1512,184 @@ int balance_check_loop(void)
 				DEBUG_INFO("Detect gun connected re-allocate available current to each connection.\n");
 				ShmPowerSharing->isDetectNewConnected = NO;
 			}
-		}
-
-		struct CONNECTION_INFO* pDev = NULL;
-		Connector_Info* pGun = NULL;
-		uint16_t* pIset = NULL;
-		uint16_t* pIout = NULL;
-		uint16_t Imin = 0;
 
-		for(uint8_t idx = 0; idx < CONNECTION_LIMIT; idx++)
+			ResetGunInfoEx();
+		}
+		else
 		{
-			pDev = &ShmPowerSharing->Connection_Info[idx];
-			for(uint8_t gun_index = 0; gun_index < pDev->connectorCount; gun_index++)
+			struct CONNECTION_INFO* pDev = NULL;
+			Connector_Info* pGun = NULL;
+			uint16_t* pIset = NULL;
+			uint16_t* pIout = NULL;
+			uint16_t Imin = 0;
+			PGunInfoEx pGunInfoEx = NULL;
+
+			for(uint8_t idx = 0; idx < CONNECTION_LIMIT; idx++)
 			{
-				pGun = &pDev->connectorInfo[gun_index];
-				pIset = &pGun->availableSharingCurrent;
-				pIout = &pGun->presentOutputCurrent;
-				Imin = (pGun->connectorType == CONNECTOR_TYPE_DC ? SHARE_MIN_DC : SHARE_MIN_AC);
-
-				if(pDev->isSocketConnected && pGun->isGunConnected)
+				pDev = &ShmPowerSharing->Connection_Info[idx];
+				for(uint8_t gun_index = 0; gun_index < pDev->connectorCount; gun_index++)
 				{
-					if((getDiffSecNow(pGun->tmrCheckCapacity) >= INTERVAL_SPEC_CHECK_CAPACITY))
+					pGun = &pDev->connectorInfo[gun_index];
+					pIset = &pGun->availableSharingCurrent;
+					uint16_t PreIset = pGun->availableSharingCurrent;
+					pIout = &pGun->presentOutputCurrent;
+					Imin = (pGun->connectorType == CONNECTOR_TYPE_DC ? SHARE_MIN_DC : SHARE_MIN_AC);
+					pGunInfoEx = &g_GunInfoEx[idx][gun_index];
+
+					if(pDev->isSocketConnected && pGun->isGunConnected)
 					{
-						int16_t Idiff = *pIset - *pIout;
-						if(Idiff > 3)
-						{
-							int32_t IsetAdd = - (Idiff >> 1);
-							uint16_t IsetNext = *pIset + IsetAdd;
-							if(IsetNext >= Imin)
-								*pIset = IsetNext;
-							else
-								*pIset = Imin;
-						}
-						else if((abs(Idiff) <= 1) && (ShmPowerSharing->onHandCurrent > 0))
+						if((getDiffSecNow(pGun->tmrCheckCapacity) >= INTERVAL_SPEC_CHECK_CAPACITY))
 						{
-							int AvgCurr = ShmPowerSharing->onHandCurrent /
-								(ShmPowerSharing->connectedConnectorQty == 0 ? 1 : ShmPowerSharing->connectedConnectorQty);
-							*pIset += (pGun->connectorType == CONNECTOR_TYPE_AC_THREE ? AvgCurr / 3 : AvgCurr);
-						}
-						else
-						{
-						}
-
-						Connector_Info* pGunIsetMax = GetIsetMaxGun();
-						Connector_Info* pGunIsetMin = GetIsetMinGun();
-						if (pGun == pGunIsetMax && pGunIsetMax == pGunIsetMin)
-						{
-							if (pGun->connectorType == CONNECTOR_TYPE_AC_THREE)
+							int16_t Idiff = *pIset - *pIout;
+							if(Idiff > 3)
+							{
+								int32_t IsetAdd = - (Idiff >> 1);
+								uint16_t IsetNext = *pIset + IsetAdd;
+								if(IsetNext >= Imin)
+									*pIset = IsetNext;
+								else
+									*pIset = Imin;
+
+								pGunInfoEx->m_bIncreasing = FALSE;
+								pGunInfoEx->m_bDecreasing = TRUE;
+							}
+							else if((abs(Idiff) <= 1) && (ShmPowerSharing->onHandCurrent > 0))
 							{
-								if (ShmPowerSharing->onHandCurrent >= 3)
+
+								int AvgCurr = ShmPowerSharing->onHandCurrent /
+									(ShmPowerSharing->connectedConnectorQty == 0 ? 1 : ShmPowerSharing->connectedConnectorQty);
+
+#ifdef MODIFY_MODPS_LET_ON_HAND_ALL_USED
+								if (pGun->connectorType == CONNECTOR_TYPE_AC_THREE)
+								{
+									int32_t IsetAdd = AvgCurr / 3;
+									if (IsetAdd >= 1)
+									{
+										*pIset += IsetAdd;
+									}
+									else if (ShmPowerSharing->onHandCurrent >= 3)
+									{
+										*pIset += 1;
+									}
+								}
+								else
 								{
-									*pIset += 1;
-									conn_getOnHandCurrent();
+									if (ShmPowerSharing->onHandCurrent <= 2)
+									{
+										*pIset += 1;
+									}
+									else
+									{
+										*pIset += AvgCurr;
+									}
 								}
+								pGunInfoEx->m_bIncreasing = TRUE;
+								pGunInfoEx->m_bDecreasing = FALSE;
+#else
+								*pIset += (pGun->connectorType == CONNECTOR_TYPE_AC_THREE ? AvgCurr / 3 : AvgCurr);
+#endif
 							}
 							else
 							{
-								for (uint8_t i = 1; i <= 1; i++)
+								pGunInfoEx->m_bIncreasing = FALSE;
+								pGunInfoEx->m_bDecreasing = FALSE;
+							}
+
+							//-----------------------------------------------------------------------------
+							if (*pIset != PreIset)
+							{
+								PreIset = *pIset;
+								conn_getOnHandCurrent(FALSE);
+							}
+
+							Connector_Info* pGunIsetMax = GetIsetMaxGun();
+							Connector_Info* pGunIsetMin = GetIsetMinGun();
+
+//							uint16_t RealIsetMax = pGunIsetMax->connectorType == CONNECTOR_TYPE_AC_THREE ? pGunIsetMax->availableSharingCurrent * 3 : pGunIsetMax->availableSharingCurrent;
+//							uint16_t RealIsetMin = pGunIsetMin->connectorType == CONNECTOR_TYPE_AC_THREE ? pGunIsetMin->availableSharingCurrent * 3 : pGunIsetMin->availableSharingCurrent;
+//							BOOL bBalance = abs(RealIsetMax - RealIsetMin) <= 3;
+
+							if (pGun == pGunIsetMax && pGunIsetMax == pGunIsetMin)
+							{
+								if (pGun->connectorType == CONNECTOR_TYPE_AC_THREE)
 								{
-									if (ShmPowerSharing->onHandCurrent > 0)
+									if (ShmPowerSharing->onHandCurrent >= 3)
 									{
 										*pIset += 1;
-										conn_getOnHandCurrent();
 									}
-									else
+								}
+								else
+								{
+									if (ShmPowerSharing->onHandCurrent >= 1)
 									{
-										break;
+										*pIset += 1;
 									}
 								}
 							}
-						}
-						else if (pGun == pGunIsetMin)
-						{
-							if (pGun->connectorType == CONNECTOR_TYPE_AC_THREE)
+							else if (pGun == pGunIsetMin)
 							{
-								if (ShmPowerSharing->onHandCurrent >= 3)
+								if (pGunInfoEx->m_bDecreasing == TRUE)
+								{
+
+								}
+								else
 								{
-									*pIset += 1;
-									conn_getOnHandCurrent();
+									if (pGun->connectorType == CONNECTOR_TYPE_AC_THREE)
+									{
+										if (ShmPowerSharing->onHandCurrent >= 3)
+										{
+											*pIset += 1;
+										}
+									}
+									else
+									{
+										if (ShmPowerSharing->onHandCurrent >= 1)
+										{
+											*pIset += 1;
+										}
+									}
 								}
+
 							}
-							else
+							else if (pGun == pGunIsetMax)
 							{
-								for (uint8_t i = 1; i <= 1; i++)
+								if (pGunInfoEx->m_bIncreasing == TRUE)
+								{
+
+								}
+								else
 								{
-									if (ShmPowerSharing->onHandCurrent > 0)
+									if (pGun->connectorType == CONNECTOR_TYPE_AC_THREE)
 									{
-										*pIset += 1;
-										conn_getOnHandCurrent();
+										*pIset -= 1;
 									}
 									else
 									{
-										break;
+										*pIset -= 1;
 									}
 								}
+
 							}
+							refreshStartTimer(&ShmPowerSharing->Connection_Info[idx].connectorInfo[gun_index].tmrCheckCapacity);
 						}
-						else if (pGun == pGunIsetMax)
+					}
+					else
+					{
+						if(*pIset != 0)
 						{
-							if (pGun->connectorType == CONNECTOR_TYPE_AC_THREE)
-							{
-								*pIset -= 1;
-								conn_getOnHandCurrent();
-							}
-							else
-							{
-								*pIset -= 1;
-								conn_getOnHandCurrent();
-							}
+							DEBUG_INFO("Dupfd-%d on conn-%d available current reset to 0A\n", ShmPowerSharing->Connection_Info[idx].socketFd, idx);
 						}
-						refreshStartTimer(&ShmPowerSharing->Connection_Info[idx].connectorInfo[gun_index].tmrCheckCapacity);
+						*pIset = 0;
 					}
-				}
-				else
-				{
-					if(*pIset != 0)
+
+					if (*pIset != PreIset)
 					{
-						DEBUG_INFO("Dupfd-%d on conn-%d available current reset to 0A\n", ShmPowerSharing->Connection_Info[idx].socketFd, idx);
+						PreIset = *pIset;
+						conn_getOnHandCurrent(FALSE);
 					}
-					*pIset = 0;
 				}
 			}
 		}
-
 		usleep(100000);
 	}
 
@@ -1637,13 +1793,156 @@ int balance_check_loop(void)
 }
 #endif //MODIFY_MODPS_BALANCE_CHECK_LOOP
 
+#ifdef FUNC_MODPS_WATCH_MODE
+
+void SetCursorPos(int XPos, int YPos)
+{
+    printf("\033[%d;%dH", YPos + 1, XPos + 1);
+}
+
+int WatchMode(void)
+{
+	int MeterSMId;
+
+	if ((MeterSMId = shmget(ShmPowerShargingKey, sizeof(struct POWER_SHARING), 0777)) < 0)
+	{
+		XP("shmget ShmPowerShargingKey NG\n");
+		return FAIL;
+	}
+	else if ((ShmPowerSharing = shmat(MeterSMId, NULL, 0)) == (void *) -1)
+	{
+		XP("shmat ShmPowerShargingKey NG\n");
+		return FAIL;
+	}
+
+	//---------------------------------------
+	struct CONNECTION_INFO* pDev = NULL;
+	Connector_Info* pGun = NULL;
+	int result = 0;
+	int Iset = 0;
+
+    struct winsize CurConsoleSize, PreConsoleSize;
+    ioctl(STDOUT_FILENO, TIOCGWINSZ, &CurConsoleSize);
+    //same with command: #stty size
+	int CurRowCountOutp = 0;
+	int PreRowCountOutp = 0;
+	system("reset");
+	const char* sbar = "================================\n";
+	//---------------------------------------
+
+	while (1)
+	{
+		ioctl(STDOUT_FILENO, TIOCGWINSZ, &CurConsoleSize);
+		if (CurConsoleSize.ws_col != PreConsoleSize.ws_col ||
+			CurConsoleSize.ws_row != PreConsoleSize.ws_row ||
+			CurRowCountOutp != PreRowCountOutp
+		)
+		{
+			memcpy(&PreConsoleSize, &CurConsoleSize, sizeof(CurConsoleSize));
+			PreRowCountOutp = CurRowCountOutp;
+			system("reset");
+		}
+
+		CurRowCountOutp = 0;
+
+		SetCursorPos(0, 0);
+		XP("%s", sbar);
+		XP("ConsoleSize: %d x %d\n", CurConsoleSize.ws_col, CurConsoleSize.ws_row);
+		XP("Version: %s\n", Version_And_Date[0]);
+		XP("Update: %s\n", Version_And_Date[1]);
+	    XP("Build: %s %s\n", __DATE__, __TIME__);
+	    XP("%s", sbar);
+
+	    result = 0;
+		for(uint8_t idx = 0; idx < CONNECTION_LIMIT; idx++)
+		{
+			pDev = &ShmPowerSharing->Connection_Info[idx];
+			if(pDev->isSocketConnected)
+			{
+				for(uint8_t gun_index = 0; gun_index < pDev->connectorCount; gun_index++)
+				{
+					pGun = &pDev->connectorInfo[gun_index];
+
+					Iset = pGun->availableSharingCurrent;
+
+					if (pGun->connectorType == CONNECTOR_TYPE_AC_THREE)
+					{
+						XP("[C:%2d][G:%2d]: %3d / %3d (x3=%3d) (%d)\n", idx, gun_index,
+								pGun->presentOutputCurrent,
+								Iset,
+								Iset * 3,
+								pGun->connectorType
+								);
+						result += (Iset * 3);
+					}
+					else
+					{
+						XP("[C:%2d][G:%2d]: %3d / %3d (%d)\n", idx, gun_index,
+								pGun->presentOutputCurrent,
+								Iset,
+								pGun->connectorType
+								);
+						result += Iset;
+					}
+					CurRowCountOutp++;
+				}
+			}
+		}
+		XP("Sum of Iset = %-4d\n", result);
+		XP("TotalLimitCurr = %-4d\n", ShmPowerSharing->onHandCurrent + result);
+		XP("OnHandCurr = %-4d\n", ShmPowerSharing->onHandCurrent);
+		XP("Connection = %-2d\n", ShmPowerSharing->connectedConnectionQty);
+		XP("Connector = %-2d\n", ShmPowerSharing->connectedConnectorQty);
+		XP("%s", sbar);
+
+		usleep(500000);
+	}
+}
+#endif //FUNC_MODPS_WATCH_MODE
+
+
+//-----------------------------------------------------------------------------
+
+void Init_FW_Info(void)
+{
+#ifdef MODPS_FW_VER_TYPE_FORMAL
+    sprintf(Version_And_Date[0], "V%4.2f", MODPS_FW_VER_NUM * 0.01);
+#endif
+
+#ifdef MODPS_FW_VER_TYPE_TEST
+    sprintf(Version_And_Date[0], "T%4.2f", MODPS_FW_VER_NUM * 0.01);
+#endif
+
+    sprintf(Version_And_Date[1], "%s", MODPS_FW_DATE);
+}
+
+//-----------------------------------------------------------------------------
+
 //==========================================
 // Main process
 //==========================================
+#ifdef FUNC_MODPS_WATCH_MODE
+int main(int argc, char *argv[])
+#else
 int main(void)
+#endif
 {
 	signal(SIGCHLD,SIG_IGN);
 
+	Init_FW_Info();
+
+#ifdef FUNC_MODPS_WATCH_MODE
+	if (argc == 2 && strcmp(argv[1], "-watch") == 0)
+	{
+		return WatchMode();
+	}
+#endif
+
+    DEBUG_INFO("\n\n");
+    DEBUG_INFO("Version: %s\n", Version_And_Date[0]);
+    DEBUG_INFO("Update: %s\n", Version_And_Date[1]);
+    DEBUG_INFO("Build: %s %s\n", __DATE__, __TIME__);
+
 	// Initial share memory
 	if(InitShareMemory() == FAIL)
 	{
@@ -1657,11 +1956,6 @@ int main(void)
 		return 0;
 	}
 
-	Init_FW_Info();
-	DEBUG_INFO("\n\n");
-	DEBUG_INFO("Latest Firmware Version : [ %s ]\n", Version_And_Date[0]);
-	DEBUG_INFO("Latest Upgrade Date : [ %s ]\n", Version_And_Date[1]);
-
 	// Enable server if rotary switch not slave mode
 	if(ShmSysConfigAndInfo->SysConfig.isEnableLocalPowerSharing == 1)
 	{