Wzyyy98 3 vuotta sitten
vanhempi
commit
241bf1b5ed

+ 9 - 115
src/pages/device/Instance/Detail/Opcua/index.tsx

@@ -1,5 +1,5 @@
 import { FormItem, ArrayTable, Editable, Select, NumberPicker } from '@formily/antd';
-import { createForm, Field, onFieldReact, FormPath, onFieldChange } from '@formily/core';
+import { createForm, Field, onFieldReact, FormPath } from '@formily/core';
 import { FormProvider, createSchemaField } from '@formily/react';
 import { Badge, Card, Empty, Input, Tooltip } from 'antd';
 import { action } from '@formily/reactive';
@@ -7,7 +7,7 @@ import type { Response } from '@/utils/typings';
 import './index.less';
 import { useDomFullHeight } from '@/hooks';
 import PermissionButton from '@/components/PermissionButton';
-import { service } from '@/pages/link/Channel/Modbus';
+import { service } from '@/pages/link/Channel/Opcua';
 import { useEffect, useState } from 'react';
 import { DisconnectOutlined, QuestionCircleOutlined } from '@ant-design/icons';
 import { onlyMessage } from '@/utils/util';
@@ -19,23 +19,14 @@ interface Props {
 export default (props: Props) => {
   const { data } = props;
   const { minHeight } = useDomFullHeight('.modbus');
-  const { permission } = PermissionButton.usePermission('link/Channel/Modbus');
+  const { permission } = PermissionButton.usePermission('link/Channel/Opcua');
   const [properties, setProperties] = useState<any>([]);
   const [filterList, setFilterList] = useState<any>([]);
   const [masterList, setMasterList] = useState<any>([]);
-  const [typeList, setTypeList] = useState<any>([]);
   const [reload, setReload] = useState<string>('');
   const [empty, setEmpty] = useState<boolean>(false);
 
   //数据类型长度
-  const lengthMap = new Map();
-  lengthMap.set('int8', 1);
-  lengthMap.set('int16', 2);
-  lengthMap.set('int32', 4);
-  lengthMap.set('int64', 8);
-  lengthMap.set('ieee754_float', 4);
-  lengthMap.set('ieee754_double', 8);
-  lengthMap.set('hex', 1);
 
   const Render = (propsText: any) => {
     const text = properties.find((item: any) => item.metadataId === propsText.value);
@@ -84,7 +75,7 @@ export default (props: Props) => {
 
   //异步数据源
   const getMaster = () =>
-    service.queryMaster({
+    service.noPagingOpcua({
       paging: false,
       sorts: [
         {
@@ -112,70 +103,19 @@ export default (props: Props) => {
       ],
       terms: [
         {
-          column: 'masterId',
+          column: 'opcUaId',
           value: collectorId,
         },
       ],
     });
   };
 
-  const getQuantity = async (field: any) => {
-    const path = FormPath.transform(
-      field.path,
-      /\d+/,
-      (index) => `array.${parseInt(index)}.collectorId`,
-    );
-    const path1 = FormPath.transform(
-      field.path,
-      /\d+/,
-      (index) => `array.${parseInt(index)}.pointId`,
-    );
-    const collectorId = field.query(path).get('value');
-    const pointId = field.query(path1).get('value');
-    if (collectorId && pointId) {
-      return service.getPoint({
-        paging: false,
-        sorts: [
-          {
-            name: 'createTime',
-            order: 'desc',
-          },
-        ],
-        terms: [
-          {
-            column: 'masterId',
-            value: collectorId,
-          },
-          {
-            column: 'id',
-            value: pointId,
-          },
-        ],
-      });
-    } else {
-      return [];
-    }
-  };
-  const useAsync = (api: any) => (field: Field) => {
-    field.loading = true;
-    api(field).then(
-      action.bound!((resp: Response<any>) => {
-        const value = resp.result?.[0].parameter.quantity || '';
-        field.dataSource = [...new Array(value * 2).keys()].map((item: any) => ({
-          label: item,
-          value: item,
-        }));
-        field.loading = false;
-      }),
-    );
-  };
-
   const useAsyncDataSource = (api: any) => (field: Field) => {
     field.loading = true;
     api(field).then(
       action.bound!((resp: Response<any>) => {
         field.dataSource = resp.result?.map((item: any) => ({
-          label: `${item.name}(${item.unitId}/${item.address}/${item.function.text})`,
+          label: `${item.name}(${item.opcPointId}/${item.dataMode?.text})`,
           value: item.id,
         }));
         field.loading = false;
@@ -193,7 +133,7 @@ export default (props: Props) => {
 
   useEffect(() => {
     service
-      .queryMaster({
+      .noPagingOpcua({
         paging: false,
         sorts: [
           {
@@ -211,18 +151,8 @@ export default (props: Props) => {
           setMasterList(list);
         }
       });
-    service.dataType().then((res) => {
-      if (res.status === 200) {
-        const items = res.result.map((item: any) => ({
-          label: item.name,
-          value: item.id,
-        }));
-        setTypeList(items);
-      }
-    });
   }, []);
   useEffect(() => {
-    console.log(typeList);
     const metadata = JSON.parse(data.metadata).properties?.map((item: any) => ({
       metadataId: item.id,
       metadataName: `${item.name}(${item.id})`,
@@ -282,11 +212,6 @@ export default (props: Props) => {
           /\d+/,
           (index) => `array.${parseInt(index)}.pointId`,
         );
-        const path1 = FormPath.transform(
-          field.path,
-          /\d+/,
-          (index) => `array.${parseInt(index)}.codec`,
-        );
         f.setFieldState(path, (state) => {
           if (value) {
             state.required = true;
@@ -296,34 +221,6 @@ export default (props: Props) => {
             form.validate();
           }
         });
-        f.setFieldState(path1, (state) => {
-          if (value) {
-            state.required = true;
-            form.validate();
-          } else {
-            state.required = false;
-            form.validate();
-          }
-        });
-      });
-      onFieldChange('array.*.codec', (field: any) => {
-        const value = (field as Field).value;
-        const path = FormPath.transform(
-          field.path,
-          /\d+/,
-          (index) => `array.${parseInt(index)}.codecConfiguration.readIndex`,
-        );
-        if ((field as Field).modified) {
-          const readIndex = field.query(path).get('value');
-          const dataLength = field.query(path).get('dataSource')?.length - 1;
-          const length = lengthMap.get(value) + readIndex;
-          console.log(length, dataLength);
-          if (length > dataLength) {
-            field.selfErrors = '数据类型对应的长度和起始位置加起来不能超过数据长度';
-          } else {
-            field.selfErrors = '';
-          }
-        }
       });
     },
   });
@@ -384,7 +281,7 @@ export default (props: Props) => {
                 title: (
                   <>
                     点位名称
-                    <Tooltip title="名称(从站ID/地址/功能码)">
+                    <Tooltip title="名称(点位ID/数据模式)">
                       <QuestionCircleOutlined />
                     </Tooltip>
                   </>
@@ -487,10 +384,7 @@ export default (props: Props) => {
           </div>
           <div className="edit-table">
             <FormProvider form={form}>
-              <SchemaField
-                schema={schema}
-                scope={{ useAsyncDataSource, getName, getMaster, getQuantity, useAsync }}
-              />
+              <SchemaField schema={schema} scope={{ useAsyncDataSource, getName, getMaster }} />
             </FormProvider>
           </div>
         </>

+ 22 - 6
src/pages/link/Channel/Opcua/index.tsx

@@ -21,10 +21,11 @@ import { PageContainer } from '@ant-design/pro-layout';
 import Service from './service';
 import SaveChannel from './saveChannel';
 import SavePoint from './savePoint';
-// import Import from './import';
 import { onlyMessage } from '@/utils/util';
 import Export from './Export';
 import Import from './import';
+import useSendWebsocketMessage from '@/hooks/websocket/useSendWebsocketMessage';
+import { map } from 'rxjs/operators';
 
 export const service = new Service('opc/client');
 
@@ -39,13 +40,15 @@ const NewOpc = () => {
   const [visiblePoint, setVisiblePoint] = useState<boolean>(false);
   const [current, setCurrent] = useState<any>({});
   const [pointDetail, setPointDetail] = useState<any>({});
-  // const [importVisible, setImportVisible] = useState<boolean>(false);
   const [opcList, setOpcList] = useState<any>([]);
   const [filterList, setFilterList] = useState([]);
   const opcId = useRef<string>('');
   const [pointList, setPointList] = useState<any>([]);
   const [exportVisible, setExportVisible] = useState<boolean>(false);
   const [importVisible, setImportVisible] = useState<boolean>(false);
+  const [subscribeTopic] = useSendWebsocketMessage();
+  const wsRef = useRef<any>();
+  const [currentData, setCurrentData] = useState<any>({});
 
   const collectMap = new Map();
   collectMap.set('good', 'success');
@@ -101,7 +104,7 @@ const NewOpc = () => {
     {
       title: '当前数据',
       search: false,
-      render: (record: any) => <>{record.parameter?.quantity}</>,
+      render: (record: any) => <>{currentData[record?.id] || ''}</>,
     },
     {
       title: '采集状态',
@@ -299,6 +302,22 @@ const NewOpc = () => {
     });
   };
 
+  useEffect(() => {
+    if (pointList && activeKey) {
+      const id = `collector-data-modbus`;
+      const topic = `/collector/MODBUS_TCP/${activeKey}/data`;
+      wsRef.current = subscribeTopic?.(id, topic, {
+        pointId: pointList.map((item: any) => item.id),
+      })
+        ?.pipe(map((res: any) => res.payload))
+        .subscribe((payload: any) => {
+          const { value } = payload;
+          current[value.property] = value.formatValue;
+          setCurrentData({ ...current });
+        });
+    }
+    return () => wsRef.current && wsRef.current?.unsubscribe();
+  }, [pointList]);
   const masterMemo = useMemo(
     () => (
       <Export
@@ -319,9 +338,6 @@ const NewOpc = () => {
   useEffect(() => {
     getOpc();
   }, []);
-  useEffect(() => {
-    console.log(pointList);
-  }, []);
 
   return (
     <PageContainer>

+ 23 - 30
src/pages/link/Channel/Opcua/service.ts

@@ -31,31 +31,7 @@ class Service extends BaseService<OpaUa> {
       method: 'GET',
       params,
     });
-  getDevice = (params?: any) =>
-    request(`/${SystemConst.API_BASE}/device-instance/_query`, {
-      method: 'POST',
-      data: params,
-    });
-  //绑定设备
-  bind = (params: any) =>
-    request(`/${SystemConst.API_BASE}/opc/device-bind/batch/_create`, {
-      method: 'POST',
-      data: params,
-    });
-  getBindList = (params: any) =>
-    request(`/${SystemConst.API_BASE}/opc/device-bind/device-details/_query/no-paging`, {
-      method: 'GET',
-      params,
-    });
-  unbind = (params: any, opcUaId: string) =>
-    request(`${SystemConst.API_BASE}/opc/device-bind/batch/${opcUaId}/_delete`, {
-      method: 'POST',
-      data: params,
-    });
-  deviceDetail = (id: any) =>
-    request(`${SystemConst.API_BASE}/device-instance/${id}/detail`, {
-      method: 'GET',
-    });
+
   addPoint = (params: any) =>
     request(`${SystemConst.API_BASE}/opc/point`, {
       method: 'POST',
@@ -66,6 +42,11 @@ class Service extends BaseService<OpaUa> {
       method: 'POST',
       data: params,
     });
+  getPoint = (params: any) =>
+    request(`${SystemConst.API_BASE}/opc/point/_query/no-paging`, {
+      method: 'POST',
+      data: params,
+    });
   editPoint = (id: string, params: any) =>
     request(`/${SystemConst.API_BASE}/opc/point/${id}`, {
       method: 'PUT',
@@ -80,11 +61,6 @@ class Service extends BaseService<OpaUa> {
       method: 'POST',
       data,
     });
-  stopPoint = (bindDeviceId: string, data: any) =>
-    request(`/${SystemConst.API_BASE}/opc/device-bind/points/${bindDeviceId}/_stop`, {
-      method: 'POST',
-      data,
-    });
   noPagingOpcua = (data: any) =>
     request(`/${SystemConst.API_BASE}/opc/client/_query/no-paging`, {
       method: 'POST',
@@ -95,6 +71,23 @@ class Service extends BaseService<OpaUa> {
       method: 'POST',
       data,
     });
+  removeDevicePoint = (deviceId: string, data: any) =>
+    request(`/${SystemConst.API_BASE}/things/collector/device/${deviceId}/_delete`, {
+      method: 'POST',
+      data,
+    });
+  //查询设备点位映射配置
+  getDevicePoint = (deviceId: string, param?: string) =>
+    request(`/${SystemConst.API_BASE}/things/collector/device/${deviceId}/_query`, {
+      method: 'GET',
+      param,
+    });
+  //保存设备绑定点位映射配置
+  saveDevicePoint = (deviceId: string, data: any) =>
+    request(`/${SystemConst.API_BASE}/things/collector/device/${deviceId}/OPC_UA`, {
+      method: 'PATCH',
+      data,
+    });
 }
 
 export default Service;