Browse Source

feat(device): status-property

Lind 4 years atrás
parent
commit
9ae17853a6

+ 2 - 2
src/app.tsx

@@ -130,7 +130,7 @@ export const request: RequestConfig = {
       history.push('/user/login');
       return;
     }
-    if (response.status === 400) {
+    if (response.status === 400 || response.status === 500) {
       response.text().then((resp: string) => {
         if (resp) {
           notification.error({
@@ -154,7 +154,7 @@ export const request: RequestConfig = {
         message: '网络异常',
       });
     }
-    throw error;
+    return response;
   },
   requestInterceptors: [requestInterceptor],
 };

+ 0 - 1
src/hooks/websocket/useSendWebsocketMessage.ts

@@ -60,7 +60,6 @@ export const useSendWebsocketMessage = () => {
     topic: string,
     parameter: Record<string, any>,
   ): Observable<any> => {
-    console.log(parameter, 'par');
     return new Observable((subscriber) => {
       if (!subscribeList[id]) {
         subscribeList[id] = [];

+ 97 - 20
src/pages/device/Instance/Detail/Running/Property.tsx

@@ -1,38 +1,115 @@
-import { SyncOutlined } from '@ant-design/icons';
-import { message } from 'antd';
+import { EditOutlined, SyncOutlined } from '@ant-design/icons';
+import { Divider, message, Spin } from 'antd';
 import ProCard from '@ant-design/pro-card';
-import type { PropertyMetadata } from '@/pages/device/Product/typings';
+import type { ObserverMetadata, PropertyMetadata } from '@/pages/device/Product/typings';
 import { Line } from '@ant-design/charts';
+import { useCallback, useEffect, useRef, useState } from 'react';
+import { service } from '@/pages/device/Instance';
+import { useParams } from 'umi';
 
 interface Props {
-  data: Partial<PropertyMetadata>;
+  data: Partial<PropertyMetadata> & ObserverMetadata;
 }
 
+type Payload = {
+  timeString: string;
+  timestamp: number;
+  value: number;
+  formatValue: string;
+  property: string;
+} & Record<string, unknown>;
 const Property = (props: Props) => {
   const { data } = props;
+  const [list, setList] = useState<Record<string, unknown>[]>([]);
+  const cacheList = useRef<Record<string, unknown>[]>(list);
+  const [title, setTitle] = useState<string>('');
+
+  const params = useParams<{ id: string }>();
+  const type = data.valueType?.type;
+  const value = list[list.length - 1];
+
+  useEffect(() => {
+    data.subscribe((payload: any) => {
+      if (payload instanceof Array) {
+        setTitle(`:${payload[payload?.length - 1].formatValue}`);
+        cacheList.current = payload;
+        setList(payload);
+      } else if (payload instanceof Object) {
+        const temp: Payload = {
+          timeString: payload.timeString,
+          timestamp: payload.timestamp,
+          ...payload.value,
+        };
+        // title
+        const newValue = temp?.formatValue;
+        setTitle(`:${newValue}`);
+        // list
+        const cache = cacheList.current;
+        cache.shift();
+        cache.push(temp);
+        setList(cache);
+      }
+    });
+  }, [data]);
+
+  const chart = useCallback(() => {
+    switch (type) {
+      case 'int':
+      case 'float':
+      case 'double':
+      case 'long':
+      case 'enum':
+        return (
+          <Line
+            height={60}
+            xField="timeString"
+            yField="value"
+            xAxis={false}
+            yAxis={false}
+            data={list}
+          />
+        );
+      case 'object':
+        return <div>{JSON.stringify(value.formatValue) || '/'}</div>;
+      default:
+        return null;
+    }
+  }, [list, type]);
+
+  const [loading, setLoading] = useState<boolean>(false);
+  const refreshProperty = async () => {
+    setLoading(true);
+    if (!data.id) return;
+    const resp = await service.getProperty(params.id, data.id);
+    setLoading(false);
+    if (resp.status === 200) {
+      message.success('操作成功');
+    }
+  };
   return (
     <ProCard
-      title={data.name}
-      extra={<SyncOutlined onClick={() => message.success('刷新')} />}
+      title={`${data?.name} ${title}`}
+      extra={
+        <>
+          <EditOutlined
+            onClick={async () => {
+              message.success('设置属性');
+            }}
+          />
+          <Divider type="vertical" />
+          <SyncOutlined onClick={refreshProperty} />
+          <Divider type="vertical" />
+          <EditOutlined onClick={refreshProperty} />
+        </>
+      }
       layout="center"
       bordered
       headerBordered
       colSpan={{ xs: 12, sm: 8, md: 6, lg: 6, xl: 6 }}
     >
-      <Line
-        height={60}
-        xField="key"
-        yField="value"
-        xAxis={false}
-        yAxis={false}
-        data={[
-          { key: 1, value: 12 },
-          { key: 2, value: 22 },
-          { key: 3, value: 32 },
-          { key: 4, value: 22 },
-          { key: 5, value: 12 },
-        ]}
-      />
+      <Spin spinning={loading} style={{ height: 60 }}>
+        {chart()}
+      </Spin>
     </ProCard>
   );
 };

+ 31 - 15
src/pages/device/Instance/Detail/Running/index.tsx

@@ -1,6 +1,10 @@
 import { InstanceModel, service } from '@/pages/device/Instance';
 import { Badge, Card, Col, Row } from 'antd';
-import type { DeviceMetadata } from '@/pages/device/Product/typings';
+import type {
+  DeviceMetadata,
+  ObserverMetadata,
+  PropertyMetadata,
+} from '@/pages/device/Product/typings';
 import { useIntl } from '@@/plugin-locale/localeExports';
 import { useCallback, useEffect, useState } from 'react';
 import Property from '@/pages/device/Instance/Detail/Running/Property';
@@ -16,6 +20,7 @@ const ColResponsiveProps = {
   xl: 6,
   style: { marginBottom: 24 },
 };
+
 const Running = () => {
   const intl = useIntl();
   const metadata = JSON.parse(InstanceModel.detail.metadata as string) as DeviceMetadata;
@@ -35,7 +40,8 @@ const Running = () => {
     };
     return item;
   };
-
+  metadata.events = metadata.events.map(addObserver);
+  metadata.properties = metadata.properties.map(addObserver);
   const [propertiesList, setPropertiesList] = useState<string[]>([]);
   // const eventWS = {
   //   id: `instance-info-event-${device.id}-${device.productId}`,
@@ -50,15 +56,23 @@ const Running = () => {
     topic: `/dashboard/device/${device.productId}/properties/realTime`,
   };
 
-  const getProperty = () => {
+  /**
+   * 获取ws下发属性数据
+   */
+  const subscribeProperty = () => {
     subscribeTopic!(propertyWs.id, propertyWs.topic, {
       deviceId: device.id,
       properties: propertiesList,
       history: 0,
     })
-      ?.pipe(map((res) => res.result))
-      .subscribe((resp: any) => {
-        console.log(resp, 'resp');
+      ?.pipe(map((res) => res.payload))
+      .subscribe((payload: any) => {
+        const property = metadata.properties.find(
+          (i) => i.id === payload.value.property,
+        ) as PropertyMetadata & ObserverMetadata;
+        if (property) {
+          property.next(payload);
+        }
       });
   };
 
@@ -77,25 +91,27 @@ const Running = () => {
       },
     ];
 
-    service.propertyRealTime(params).subscribe((data) => {
-      const index = metadata.properties.findIndex((i) => i.id === data.property);
-      if (index > -1) {
-        metadata.properties[index].list = data.list as any;
-      }
+    service.propertyRealTime(params).subscribe({
+      next: (data) => {
+        const index = metadata.properties.findIndex((i) => i.id === data.property);
+        if (index > -1) {
+          const property = metadata.properties[index] as PropertyMetadata & ObserverMetadata;
+          property.list = data.list as Record<string, unknown>[];
+          property.next(data.list);
+        }
+      },
     });
   };
   useEffect(() => {
-    getProperty();
+    subscribeProperty();
     getDashboard();
   }, []);
-  metadata.events = metadata.events.map(addObserver);
-  metadata.properties = metadata.properties.map(addObserver);
 
   const renderCard = useCallback(() => {
     return [
       ...metadata.properties.map((item) => (
         <Col {...ColResponsiveProps} key={item.id}>
-          <Property data={item} />
+          <Property data={item as Partial<PropertyMetadata> & ObserverMetadata} />
         </Col>
       )),
       ...metadata.events.map((item) => (

+ 5 - 0
src/pages/device/Instance/service.ts

@@ -38,6 +38,11 @@ class Service extends BaseService<DeviceInstance> {
         // toArray()
       ),
     );
+
+  public getProperty = (id: string, type: string) =>
+    request(`/${SystemConst.API_BASE}/device/standard/${id}/property/${type}`, {
+      method: 'GET',
+    });
 }
 
 export default Service;

+ 7 - 7
src/pages/device/Product/typings.d.ts

@@ -96,13 +96,7 @@ type PropertyMetadata = {
   expands: Record<string, any>;
   description?: string;
   // 运行状态处需要数据
-  list?: {
-    timeString: string;
-    timestamp: number;
-    formatValue: string;
-    property: string;
-    value: number;
-  } & Record<string, unknown>;
+  list?: Record<string, unknown>[];
 };
 type TagMetadata = {
   id: string;
@@ -166,3 +160,9 @@ type UnitType = {
   type: string;
   value: string;
 };
+
+type ObserverMetadata = {
+  type: unknown[];
+  subscribe: (data: any) => void;
+  next: (data: any) => void;
+};