Explorar o código

Added Sunshine status

Penta hai 2 semanas
pai
achega
8ac711ccd7

+ 8 - 0
charts/openshift-console-plugin/values.yaml

@@ -9,6 +9,14 @@ plugin:
           name: mpd-radio-dashboard
           namespace: ampache
           port: 9443
+    - alias: game-status
+      authorization: None
+      endpoint:
+        type: Service
+        service:
+          name: sunshine-game-status
+          namespace: desktop
+          port: 9444
   name: ""
   description: ""
   image: ""

+ 5 - 0
src/components/DashboardPage.tsx

@@ -21,6 +21,7 @@ import type { FC } from 'react';
 import { useState } from 'react';
 
 import NowPlayingCard from './NowPlayingCard';
+import GamingCard from './GamingCard';
 
 const TUNED_NAMESPACE = 'openshift-cluster-node-tuning-operator';
 const TUNED_NAME = 'custom-tuned-profile';
@@ -184,6 +185,10 @@ const DashboardPage: FC = () => {
       <PageSection>
         <NowPlayingCard />
       </PageSection>
+      
+      <PageSection>
+        <GamingCard />
+      </PageSection>
     </>
   );
 };

+ 152 - 0
src/components/GamingCard.tsx

@@ -0,0 +1,152 @@
+import { consoleFetchJSON } from '@openshift-console/dynamic-plugin-sdk';
+
+import {
+  Alert,
+  Card,
+  CardBody,
+  CardTitle,
+  Spinner,
+} from '@patternfly/react-core';
+
+import type { FC } from 'react';
+import { useEffect, useState } from 'react';
+
+interface GameStatus {
+  game: {
+    running: boolean;
+    appid: number | null;
+    name: string | null;
+    processes: number;
+    cpuPercent: number;
+    memoryMiB: number;
+  };
+
+  sunshine: {
+    sessionActive: boolean;
+    sessions: number;
+  };
+
+  updatedAt: string | null;
+}
+
+const STATUS_URL =
+  '/api/proxy/plugin/homelab-dashboard/game-status/api/status';
+
+const REFRESH_INTERVAL_MS = 5_000;
+const REQUEST_TIMEOUT_MS = 1_000;
+
+const GamingCard: FC = () => {
+  const [status, setStatus] = useState<GameStatus>();
+  const [fetchError, setFetchError] = useState(false);
+
+  useEffect(() => {
+    let stopped = false;
+    let timer: number | undefined;
+
+    const poll = async () => {
+      try {
+        const result = (await consoleFetchJSON(
+          STATUS_URL,
+          'GET',
+          {},
+          REQUEST_TIMEOUT_MS,
+        )) as GameStatus;
+
+        if (!stopped) {
+          setStatus(result);
+          setFetchError(false);
+        }
+      } catch {
+        if (!stopped) {
+          setFetchError(true);
+        }
+      } finally {
+        if (!stopped) {
+          timer = window.setTimeout(
+            poll,
+            REFRESH_INTERVAL_MS,
+          );
+        }
+      }
+    };
+
+    void poll();
+
+    return () => {
+      stopped = true;
+
+      if (timer !== undefined) {
+        window.clearTimeout(timer);
+      }
+    };
+  }, []);
+
+  return (
+    <Card>
+      <CardTitle>Gaming</CardTitle>
+
+      <CardBody>
+        {!status && !fetchError ? (
+          <Spinner size="md" />
+        ) : (
+          <>
+            {fetchError && (
+              <Alert
+                isInline
+                variant="warning"
+                title="Gaming status unavailable"
+              >
+                The Sunshine status service did not respond
+                within one second.
+              </Alert>
+            )}
+
+            {status && (
+              <>
+                <p>
+                  Current game:{' '}
+                  <strong>
+                    {status.game.running
+                      ? status.game.name ?? 'Unknown game'
+                      : 'None'}
+                  </strong>
+                </p>
+
+                {status.game.running && (
+                  <>
+                    <p>
+                      CPU:{' '}
+                      <strong>
+                        {status.game.cpuPercent.toFixed(1)}%
+                      </strong>
+                    </p>
+
+                    <p>
+                      RAM:{' '}
+                      <strong>
+                        {status.game.memoryMiB.toFixed(1)} MiB
+                      </strong>
+                    </p>
+                  </>
+                )}
+
+                <p>
+                  Sunshine session:{' '}
+                  <strong>
+                    {status.sunshine.sessionActive
+                      ? status.sunshine.sessions > 1
+                        ? `Yes (${status.sunshine.sessions})`
+                        : 'Yes'
+                      : 'No'}
+                  </strong>
+                </p>
+              </>
+            )}
+          </>
+        )}
+      </CardBody>
+    </Card>
+  );
+};
+
+export default GamingCard;