add fixed ADS

This commit is contained in:
2025-12-21 18:32:02 +09:00
parent 74d7e3b960
commit 5eb3b21aa3

147
App.tsx
View File

@@ -17,6 +17,15 @@ const App: React.FC = () => {
const [errorMsg, setErrorMsg] = useState<string | null>(null);
// Polling Logic
useEffect(() => {
try {
// @ts-ignore
(window.adsbygoogle = window.adsbygoogle || []).push({});
} catch (e) {
console.error("AdSense error", e);
}
}, []);
useEffect(() => {
let isMounted = true;
let timeoutId: number;
@@ -32,9 +41,9 @@ const App: React.FC = () => {
if (isMounted) setBasicInfo(parsedBasic);
// Delay 500ms
await new Promise(r => setTimeout(r, 500));
await new Promise(r => setTimeout(r, 500));
if (!isMounted) return;
// 2. Get Cell Info
const cellData = await serialService.sendCommand(CMD_CELL_INFO);
const parsedCells = JBDProtocol.parseCellInfo(cellData);
@@ -103,7 +112,7 @@ const App: React.FC = () => {
try {
const newCharge = type === 'charge' ? !currentState : basicInfo.mosfetStatus.charge;
const newDischarge = type === 'discharge' ? !currentState : basicInfo.mosfetStatus.discharge;
await serialService.toggleMosfet(newCharge, newDischarge);
} catch (e: any) {
alert("MOSFET 제어 실패: " + e.message);
@@ -123,7 +132,7 @@ const App: React.FC = () => {
return (
<div className="flex h-screen w-full bg-gray-950 text-gray-100 overflow-hidden">
{/* Sidebar */}
<div className="w-20 lg:w-64 flex-shrink-0 bg-gray-900 border-r border-gray-800 flex flex-col z-20">
<div className="p-6 flex items-center justify-center lg:justify-start">
@@ -136,32 +145,46 @@ const App: React.FC = () => {
<nav className="flex-1 px-4 space-y-2 mt-4">
<button
onClick={() => setActiveTab('dashboard')}
className={`w-full flex items-center p-3 rounded-xl transition-all ${
activeTab === 'dashboard'
? 'bg-blue-600 text-white shadow-lg shadow-blue-900/20'
: 'text-gray-400 hover:bg-gray-800 hover:text-gray-200'
}`}
className={`w-full flex items-center p-3 rounded-xl transition-all ${activeTab === 'dashboard'
? 'bg-blue-600 text-white shadow-lg shadow-blue-900/20'
: 'text-gray-400 hover:bg-gray-800 hover:text-gray-200'
}`}
>
<LayoutDashboard size={20} />
<span className="ml-3 hidden lg:block font-medium"></span>
</button>
<button
onClick={() => setActiveTab('settings')}
className={`w-full flex items-center p-3 rounded-xl transition-all ${
activeTab === 'settings'
? 'bg-blue-600 text-white shadow-lg shadow-blue-900/20'
: 'text-gray-400 hover:bg-gray-800 hover:text-gray-200'
}`}
className={`w-full flex items-center p-3 rounded-xl transition-all ${activeTab === 'settings'
? 'bg-blue-600 text-white shadow-lg shadow-blue-900/20'
: 'text-gray-400 hover:bg-gray-800 hover:text-gray-200'
}`}
>
<SettingsIcon size={20} />
<span className="ml-3 hidden lg:block font-medium"> (EEPROM)</span>
</button>
</nav>
{/* AdSense Unit */}
<div className="px-4 pb-2">
<div className="text-[10px] text-gray-600 text-center mb-1">Sponsored</div>
<ins className="adsbygoogle"
style={{ display: "block" }}
data-ad-client="ca-pub-4444852135420953"
data-ad-slot="7799405796"
data-ad-format="auto"
data-full-width-responsive="true"></ins>
<script>
(adsbygoogle = window.adsbygoogle || []).push({ });
</script>
</div>
<div className="p-4 border-t border-gray-800">
<div className="flex flex-col gap-2">
{connectionState === ConnectionState.CONNECTED ? (
<button
<button
onClick={handleDisconnect}
className="w-full py-3 px-4 bg-red-900/30 text-red-400 border border-red-900/50 rounded-xl hover:bg-red-900/50 transition-colors flex items-center justify-center font-semibold"
>
@@ -169,12 +192,12 @@ const App: React.FC = () => {
<span className="hidden lg:inline"> </span>
</button>
) : (
<button
<button
onClick={handleConnect}
disabled={connectionState === ConnectionState.CONNECTING}
className="w-full py-3 px-4 bg-green-600 text-white rounded-xl hover:bg-green-500 transition-colors flex items-center justify-center font-semibold shadow-lg shadow-green-900/20"
>
{connectionState === ConnectionState.CONNECTING ? <RefreshCw className="animate-spin" size={18}/> : <Usb size={18} className="mr-2" />}
{connectionState === ConnectionState.CONNECTING ? <RefreshCw className="animate-spin" size={18} /> : <Usb size={18} className="mr-2" />}
<span className="hidden lg:inline">BMS </span>
</button>
)}
@@ -190,58 +213,58 @@ const App: React.FC = () => {
{activeTab === 'dashboard' ? '개요 (Overview)' : '설정 (Configuration)'}
</h1>
<div className="flex items-center gap-4">
{connectionState === ConnectionState.CONNECTED && (
<div className="flex items-center text-xs font-mono text-green-400 bg-green-900/20 px-3 py-1 rounded-full border border-green-900/50">
<div className="w-2 h-2 rounded-full bg-green-500 mr-2 animate-pulse"></div>
CONNECTED
</div>
)}
{connectionState === ConnectionState.DISCONNECTED && (
<div className="flex items-center text-xs font-mono text-gray-500 bg-gray-800 px-3 py-1 rounded-full">
<div className="w-2 h-2 rounded-full bg-gray-500 mr-2"></div>
OFFLINE
</div>
)}
{connectionState === ConnectionState.CONNECTED && (
<div className="flex items-center text-xs font-mono text-green-400 bg-green-900/20 px-3 py-1 rounded-full border border-green-900/50">
<div className="w-2 h-2 rounded-full bg-green-500 mr-2 animate-pulse"></div>
CONNECTED
</div>
)}
{connectionState === ConnectionState.DISCONNECTED && (
<div className="flex items-center text-xs font-mono text-gray-500 bg-gray-800 px-3 py-1 rounded-full">
<div className="w-2 h-2 rounded-full bg-gray-500 mr-2"></div>
OFFLINE
</div>
)}
</div>
</header>
{/* Content Body with Right Sidebar */}
<div className="flex-1 flex overflow-hidden">
{/* Main View */}
<main className="flex-1 overflow-hidden bg-gray-950 relative">
{errorMsg && (
<div className="bg-red-900/80 text-white px-6 py-2 flex items-center justify-center text-sm font-medium backdrop-blur absolute top-0 left-0 right-0 z-30 animate-in slide-in-from-top-2">
<AlertCircle size={16} className="mr-2" />
{errorMsg}
</div>
)}
{/* Main View */}
<main className="flex-1 overflow-hidden bg-gray-950 relative">
{errorMsg && (
<div className="bg-red-900/80 text-white px-6 py-2 flex items-center justify-center text-sm font-medium backdrop-blur absolute top-0 left-0 right-0 z-30 animate-in slide-in-from-top-2">
<AlertCircle size={16} className="mr-2" />
{errorMsg}
</div>
)}
{renderContent()}
{/* Empty State Overlay */}
{connectionState !== ConnectionState.CONNECTED && (
<div className="absolute inset-0 bg-gray-950/80 backdrop-blur-sm z-10 flex flex-col items-center justify-center p-6 text-center">
<div className="w-16 h-16 bg-gray-800 rounded-2xl flex items-center justify-center mb-6 shadow-xl border border-gray-700">
<Usb size={32} className="text-gray-500"/>
</div>
<h2 className="text-2xl font-bold text-white mb-2"> </h2>
<p className="text-gray-400 max-w-md mb-8">
JBD BMS를 UART-to-USB .
</p>
<button
onClick={handleConnect}
className="py-3 px-8 bg-blue-600 hover:bg-blue-500 text-white font-semibold rounded-xl transition-all shadow-lg shadow-blue-900/30 flex items-center"
>
<Usb size={18} className="mr-2"/>
</button>
</div>
)}
</main>
{renderContent()}
{/* Right Terminal Panel */}
<aside className="w-80 lg:w-96 border-l border-gray-800 bg-gray-950 flex flex-col flex-shrink-0 z-20">
<Terminal />
</aside>
{/* Empty State Overlay */}
{connectionState !== ConnectionState.CONNECTED && (
<div className="absolute inset-0 bg-gray-950/80 backdrop-blur-sm z-10 flex flex-col items-center justify-center p-6 text-center">
<div className="w-16 h-16 bg-gray-800 rounded-2xl flex items-center justify-center mb-6 shadow-xl border border-gray-700">
<Usb size={32} className="text-gray-500" />
</div>
<h2 className="text-2xl font-bold text-white mb-2"> </h2>
<p className="text-gray-400 max-w-md mb-8">
JBD BMS를 UART-to-USB .
</p>
<button
onClick={handleConnect}
className="py-3 px-8 bg-blue-600 hover:bg-blue-500 text-white font-semibold rounded-xl transition-all shadow-lg shadow-blue-900/30 flex items-center"
>
<Usb size={18} className="mr-2" />
</button>
</div>
)}
</main>
{/* Right Terminal Panel */}
<aside className="w-80 lg:w-96 border-l border-gray-800 bg-gray-950 flex flex-col flex-shrink-0 z-20">
<Terminal />
</aside>
</div>
</div>
</div>