| | |
| | | <groupId>cn.stylefeng</groupId> |
| | | <artifactId>guns-sys</artifactId> |
| | | <version>1.0.0</version> |
| | | <exclusions> |
| | | <exclusion> |
| | | <artifactId>guava</artifactId> |
| | | <groupId>com.google.guava</groupId> |
| | | </exclusion> |
| | | </exclusions> |
| | | </dependency> |
| | | |
| | | <!-- å·¥ä½æµ --> |
| | |
| | | <dependency> |
| | | <groupId>org.eclipse.milo</groupId> |
| | | <artifactId>sdk-client</artifactId> |
| | | <version>0.2.4</version> |
| | | <version>0.3.6</version> |
| | | </dependency> |
| | | |
| | | <!--Server SDKä¾èµ--> |
| | | <dependency> |
| | | <groupId>org.eclipse.milo</groupId> |
| | | <artifactId>sdk-server</artifactId> |
| | | <version>0.2.4</version> |
| | | <version>0.3.6</version> |
| | | </dependency> |
| | | |
| | | <!-- Stackä¾èµ--> |
| | | <dependency> |
| | | <groupId>org.eclipse.milo</groupId> |
| | | <artifactId>stack-client</artifactId> |
| | | <version>0.2.4</version> |
| | | <version>0.3.6</version> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>org.eclipse.milo</groupId> |
| | | <artifactId>stack-server</artifactId> |
| | | <version>0.2.4</version> |
| | | <version>0.3.6</version> |
| | | </dependency> |
| | | |
| | | <!--Milo客æ·ç«¯çä¾èµ--> |
| | | <dependency> |
| | | <groupId>org.eclipse.milo</groupId> |
| | | <artifactId>sdk-client</artifactId> |
| | | <version>0.2.4</version> |
| | | <artifactId>stack-client</artifactId> |
| | | <version>0.3.6</version> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | |
| | | <groupId>org.apache.hadoop</groupId> |
| | | <artifactId>hadoop-client</artifactId> |
| | | <version>3.1.3</version> |
| | | <exclusions> |
| | | <exclusion> |
| | | <artifactId>guava</artifactId> |
| | | <groupId>com.google.guava</groupId> |
| | | </exclusion> |
| | | </exclusions> |
| | | </dependency> |
| | | |
| | | <dependency> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.stylefeng.guns.opcua.cert; |
| | | |
| | | import java.io.InputStream; |
| | | import java.io.OutputStream; |
| | | import java.nio.file.Files; |
| | | import java.nio.file.Path; |
| | | import java.security.Key; |
| | | import java.security.KeyPair; |
| | | import java.security.KeyStore; |
| | | import java.security.PrivateKey; |
| | | import java.security.PublicKey; |
| | | import java.security.cert.X509Certificate; |
| | | import java.util.regex.Pattern; |
| | | |
| | | import org.eclipse.milo.opcua.sdk.server.util.HostnameUtil; |
| | | import org.eclipse.milo.opcua.stack.core.util.SelfSignedCertificateBuilder; |
| | | import org.eclipse.milo.opcua.stack.core.util.SelfSignedCertificateGenerator; |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | | import org.springframework.stereotype.Component; |
| | | |
| | | /** |
| | | * @ClassName: KeyStoreLoader |
| | | * @Description: KeyStoreLoader |
| | | * @author yyt |
| | | * @date 2023å¹´10æ13æ¥ |
| | | */ |
| | | @Component |
| | | public class KeyStoreLoader { |
| | | |
| | | private static final Pattern IP_ADDR_PATTERN = Pattern |
| | | .compile("^(([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.){3}([01]?\\d\\d?|2[0-4]\\d|25[0-5])$"); |
| | | |
| | | // è¯ä¹¦å«å |
| | | private static final String CLIENT_ALIAS = "jlclient-ai"; |
| | | // è·åç§é¥çå¯ç |
| | | private static final char[] PASSWORD = "yyt@8888888888".toCharArray(); |
| | | |
| | | private final Logger logger = LoggerFactory.getLogger(getClass()); |
| | | |
| | | // è¯ä¹¦å¯¹è±¡ |
| | | private X509Certificate clientCertificate; |
| | | // å¯é¥å¯¹å¯¹è±¡ |
| | | private KeyPair clientKeyPair; |
| | | |
| | | /** |
| | | * @MethodName: load |
| | | * @Description: load |
| | | * @param baseDir |
| | | * @return |
| | | * @throws Exception |
| | | * @CreateTime 2023å¹´10æ13æ¥ |
| | | */ |
| | | public KeyStoreLoader load(Path baseDir) throws Exception { |
| | | // å建ä¸ä¸ªä½¿ç¨`PKCS12`å å¯æ åçKeyStoreãKeyStoreå¨åé¢å°ä½ä¸ºè¯»ååçæè¯ä¹¦ç对象ã |
| | | KeyStore keyStore = KeyStore.getInstance("PKCS12"); |
| | | |
| | | // PKCS12çå å¯æ åçæ件åç¼æ¯.pfxï¼å
¶ä¸å
å«äºå
¬é¥åç§é¥ã |
| | | // èå
¶ä»å¦.derççæ ¼å¼åªå
å«å
¬é¥ï¼ç§é¥å¨å¦å¤çæ件ä¸ã |
| | | Path serverKeyStore = baseDir.resolve("OPCUA-client.pfx"); |
| | | |
| | | logger.info("Loading KeyStore at {}", serverKeyStore); |
| | | |
| | | // å¦ææ件ä¸åå¨åå建.pfxè¯ä¹¦æ件ã |
| | | if (!Files.exists(serverKeyStore)) { |
| | | keyStore.load(null, PASSWORD); |
| | | |
| | | // ç¨2048ä½çRASç®æ³ã`SelfSignedCertificateGenerator`为Miloåºç对象ã |
| | | KeyPair keyPair = SelfSignedCertificateGenerator.generateRsaKeyPair(2048); |
| | | |
| | | // `SelfSignedCertificateBuilder`ä¹æ¯Miloåºç对象ï¼ç¨æ¥çæè¯ä¹¦ã |
| | | // ä¸é´æ设置çè¯ä¹¦å±æ§å¯ä»¥èªè¡ä¿®æ¹ã |
| | | SelfSignedCertificateBuilder builder = new SelfSignedCertificateBuilder(keyPair) |
| | | .setCommonName("UaClient@Jellyleo") |
| | | .setOrganization("JL") |
| | | .setOrganizationalUnit("per") |
| | | .setLocalityName("jl") |
| | | .setStateName("JiangSu") |
| | | .setCountryCode("CN") |
| | | .setApplicationUri("urn:Yyt_PC:UnifiedAutomation:UaExpert") |
| | | .addDnsName("Yyt_PC") |
| | | .addIpAddress("127.0.0.1"); |
| | | |
| | | // Get as many hostnames and IP addresses as we can listed in the certificate. |
| | | for (String hostname : HostnameUtil.getHostnames("0.0.0.0")) { |
| | | if (IP_ADDR_PATTERN.matcher(hostname).matches()) { |
| | | builder.addIpAddress(hostname); |
| | | } else { |
| | | builder.addDnsName(hostname); |
| | | } |
| | | } |
| | | // å建è¯ä¹¦ |
| | | X509Certificate certificate = builder.build(); |
| | | |
| | | // 设置对åºç§é¥çå«åï¼å¯ç ï¼è¯ä¹¦é¾ |
| | | keyStore.setKeyEntry(CLIENT_ALIAS, keyPair.getPrivate(), PASSWORD, new X509Certificate[] { certificate }); |
| | | try (OutputStream out = Files.newOutputStream(serverKeyStore)) { |
| | | // ä¿åè¯ä¹¦å°è¾åºæµ |
| | | keyStore.store(out, PASSWORD); |
| | | } |
| | | } else { |
| | | try (InputStream in = Files.newInputStream(serverKeyStore)) { |
| | | // å¦ææ件åå¨å读å |
| | | keyStore.load(in, PASSWORD); |
| | | } |
| | | } |
| | | |
| | | // ç¨å¯ç è·å对åºå«åçç§é¥ã |
| | | Key serverPrivateKey = keyStore.getKey(CLIENT_ALIAS, PASSWORD); |
| | | if (serverPrivateKey instanceof PrivateKey) { |
| | | // è·å对åºå«åçè¯ä¹¦å¯¹è±¡ã |
| | | clientCertificate = (X509Certificate) keyStore.getCertificate(CLIENT_ALIAS); |
| | | // è·åå
¬é¥ |
| | | PublicKey serverPublicKey = clientCertificate.getPublicKey(); |
| | | // å建Keypair对象ã |
| | | clientKeyPair = new KeyPair(serverPublicKey, (PrivateKey) serverPrivateKey); |
| | | } |
| | | |
| | | return this; |
| | | } |
| | | |
| | | // è¿åè¯ä¹¦ |
| | | public X509Certificate getClientCertificate() { |
| | | return clientCertificate; |
| | | } |
| | | |
| | | // è¿åå¯é¥å¯¹ |
| | | public KeyPair getClientKeyPair() { |
| | | return clientKeyPair; |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.stylefeng.guns.opcua.cert; |
| | | |
| | | import lombok.extern.slf4j.Slf4j; |
| | | |
| | | @Slf4j |
| | | public class MethodName { |
| | | public void a(String name){ |
| | | log.info("str={}", name); |
| | | } |
| | | public void b(String name,String value){ |
| | | log.info("item={}, value={},{}", name, value,"BBBBBB"); |
| | | } |
| | | public void c(String name,String value){ |
| | | log.info("item={}, value={},{}", name, value,"CCCCCC"); |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.stylefeng.guns.opcua.client; |
| | | |
| | | import com.google.common.collect.ImmutableList; |
| | | import cn.stylefeng.guns.opcua.entity.NodeEntity; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.eclipse.milo.opcua.sdk.client.OpcUaClient; |
| | | import org.eclipse.milo.opcua.sdk.client.api.nodes.VariableNode; |
| | | import org.eclipse.milo.opcua.sdk.client.api.subscriptions.UaSubscription; |
| | | import org.eclipse.milo.opcua.stack.core.AttributeId; |
| | | import org.eclipse.milo.opcua.stack.core.BuiltinDataType; |
| | | import org.eclipse.milo.opcua.stack.core.types.builtin.DataValue; |
| | | import org.eclipse.milo.opcua.stack.core.types.builtin.NodeId; |
| | | import org.eclipse.milo.opcua.stack.core.types.builtin.StatusCode; |
| | | import org.eclipse.milo.opcua.stack.core.types.builtin.Variant; |
| | | import org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.Unsigned; |
| | | import org.eclipse.milo.opcua.stack.core.types.enumerated.MonitoringMode; |
| | | import org.eclipse.milo.opcua.stack.core.types.enumerated.TimestampsToReturn; |
| | | import org.eclipse.milo.opcua.stack.core.types.structured.MonitoredItemCreateRequest; |
| | | import org.eclipse.milo.opcua.stack.core.types.structured.MonitoringParameters; |
| | | import org.eclipse.milo.opcua.stack.core.types.structured.ReadValueId; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.util.CollectionUtils; |
| | | |
| | | import java.lang.reflect.InvocationTargetException; |
| | | import java.lang.reflect.Method; |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * @ClassName: ClientHandler |
| | | * @Description: 客æ·ç«¯å¤ç |
| | | * @author Jellyleo |
| | | * @date 2019å¹´12æ12æ¥ |
| | | */ |
| | | @Slf4j |
| | | @Service |
| | | public class ClientHandler { |
| | | |
| | | // 客æ·ç«¯å®ä¾ |
| | | private OpcUaClient client = null; |
| | | |
| | | @Autowired |
| | | private ClientRunner clientRunner; |
| | | |
| | | /** |
| | | * |
| | | * @MethodName: connect |
| | | * @Description: connect |
| | | * @throws Exception |
| | | * @CreateTime 2019å¹´12æ18æ¥ ä¸å10:41:09 |
| | | */ |
| | | public String connect() throws Exception { |
| | | |
| | | if (client != null) { |
| | | return "客æ·ç«¯å·²å建"; |
| | | } |
| | | |
| | | client = clientRunner.run(); |
| | | |
| | | if (client == null) { |
| | | return "客æ·ç«¯é
ç½®å®ä¾å失败"; |
| | | } |
| | | |
| | | // å建è¿æ¥ |
| | | client.connect().get(); |
| | | return "å建è¿æ¥æå"; |
| | | } |
| | | |
| | | /** |
| | | * @MethodName: disconnect |
| | | * @Description: æå¼è¿æ¥ |
| | | * @return |
| | | * @throws Exception |
| | | * @CreateTime 2019å¹´12æ18æ¥ ä¸å10:45:21 |
| | | */ |
| | | public String disconnect() throws Exception { |
| | | |
| | | if (client == null) { |
| | | return "è¿æ¥å·²æå¼"; |
| | | } |
| | | |
| | | // æå¼è¿æ¥ |
| | | clientRunner.getFuture().complete(client); |
| | | client = null; |
| | | return "æå¼è¿æ¥æå"; |
| | | } |
| | | |
| | | /** |
| | | * @MethodName: subscribe |
| | | * @Description: 订é
èç¹åé |
| | | * @throws Exception |
| | | * @CreateTime 2019å¹´12æ18æ¥ ä¸å10:38:11 |
| | | */ |
| | | public String subscribe(List<NodeEntity> nodes) throws Exception { |
| | | |
| | | if (client == null) { |
| | | return "æ¾ä¸å°å®¢æ·ç«¯ï¼æä½å¤±è´¥"; |
| | | } |
| | | |
| | | // List<Node> ns = client.getAddressSpace().browse(new NodeId(2, "模æééä¸.模æ设å¤ä¸")).get(); |
| | | |
| | | // æ¥è¯¢è®¢é
对象ï¼æ²¡æåå建 |
| | | UaSubscription subscription = null; |
| | | ImmutableList<UaSubscription> subscriptionList = client.getSubscriptionManager().getSubscriptions(); |
| | | if (CollectionUtils.isEmpty(subscriptionList)) { |
| | | subscription = client.getSubscriptionManager().createSubscription(1000.0).get(); |
| | | } else { |
| | | subscription = subscriptionList.get(0); |
| | | } |
| | | |
| | | // çæ§é¡¹è¯·æ±å表 |
| | | List<MonitoredItemCreateRequest> requests = new ArrayList<>(); |
| | | |
| | | if (!CollectionUtils.isEmpty(nodes)) { |
| | | for (NodeEntity node : nodes) { |
| | | // å建çæ§çåæ° |
| | | MonitoringParameters parameters = new MonitoringParameters(subscription.nextClientHandle(), 1000.0, // sampling |
| | | // interval |
| | | null, // filter, null means use default |
| | | Unsigned.uint(10), // queue size |
| | | true // discard oldest |
| | | ); |
| | | // å建订é
çåéï¼ å建çæ§é¡¹è¯· æ± |
| | | MonitoredItemCreateRequest request = new MonitoredItemCreateRequest( |
| | | new ReadValueId(new NodeId(node.getIndex(), node.getIdentifier()), AttributeId.Value.uid(), |
| | | null, null), |
| | | MonitoringMode.Reporting, parameters); |
| | | requests.add(request); |
| | | } |
| | | } |
| | | |
| | | // å建çæ§é¡¹ï¼å¹¶ä¸æ³¨ååéå¼æ¹åæ¶åçåè°å½æ° |
| | | subscription.createMonitoredItems(TimestampsToReturn.Both, requests, (item, id) -> { |
| | | item.setValueConsumer((i, v) -> { |
| | | handle(i.getReadValueId().getNodeId(), v.getValue()); |
| | | }); |
| | | }).get(); |
| | | |
| | | return "订é
æå"; |
| | | } |
| | | |
| | | /** |
| | | * * @MethodName: write |
| | | * @Description: åè°å½æ° |
| | | * @CreateTime 2023å¹´10æ13æ¥ |
| | | */ |
| | | |
| | | public void handle(NodeId id, Variant value){ |
| | | String className = "cn.stylefeng.guns.opcua.cert.MethodName"; |
| | | String methodName = "a"; |
| | | String str1 = id.getIdentifier().toString()+":"+value.getValue().toString(); |
| | | try { |
| | | Class<?> clazz = Class.forName(className); |
| | | Method method = clazz.getMethod(methodName, String.class); |
| | | |
| | | method.invoke(clazz.newInstance(), str1); |
| | | } catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException | InstantiationException | |
| | | InvocationTargetException e) { |
| | | e.printStackTrace(); |
| | | } |
| | | //if(id.getIdentifier().toString().equals("my.device.x1")){ |
| | | // log.info("item={}, value={},{}", id.getIdentifier().toString(), value,"è¿åä¸ä¸ªSNå·"); |
| | | //} |
| | | } |
| | | |
| | | /** |
| | | * @MethodName: write |
| | | * @Description: åèç¹éåå
¥ |
| | | * @param node |
| | | * @throws Exception |
| | | * @CreateTime 2019å¹´12æ18æ¥ ä¸å9:51:40 |
| | | */ |
| | | public String write(NodeEntity node) throws Exception { |
| | | |
| | | if (client == null) { |
| | | return "æ¾ä¸å°å®¢æ·ç«¯ï¼æä½å¤±è´¥"; |
| | | } |
| | | |
| | | NodeId nodeId = new NodeId(node.getIndex(), node.getIdentifier()); |
| | | Variant value = null; |
| | | switch (node.getType()) { |
| | | case "int": |
| | | value = new Variant(Integer.parseInt(node.getValue().toString())); |
| | | break; |
| | | case "boolean": |
| | | value = new Variant(Boolean.parseBoolean(node.getValue().toString())); |
| | | break; |
| | | } |
| | | DataValue dataValue = new DataValue(value, null, null); |
| | | |
| | | StatusCode statusCode = client.writeValue(nodeId, dataValue).get(); |
| | | |
| | | return "èç¹ã" + node.getIdentifier() + "ãåå
¥ç¶æï¼" + statusCode.isGood(); |
| | | } |
| | | |
| | | /** |
| | | * @MethodName: read |
| | | * @Description: 读å |
| | | * @param node |
| | | * @return |
| | | * @throws Exception |
| | | * @CreateTime 2019å¹´12æ19æ¥ ä¸å2:40:34 |
| | | */ |
| | | public String read(NodeEntity node) throws Exception { |
| | | |
| | | if (client == null) { |
| | | return "æ¾ä¸å°å®¢æ·ç«¯ï¼æä½å¤±è´¥"; |
| | | } |
| | | |
| | | NodeId nodeId = new NodeId(node.getIndex(), node.getIdentifier()); |
| | | VariableNode vnode = client.getAddressSpace().createVariableNode(nodeId); |
| | | DataValue value = vnode.readValue().get(); |
| | | log.info("Value={}", value); |
| | | |
| | | Variant variant = value.getValue(); |
| | | log.info("Variant={}", variant.getValue()); |
| | | |
| | | log.info("BackingClass={}", BuiltinDataType.getBackingClass(variant.getDataType().get())); |
| | | |
| | | return "èç¹ã" + node.getIdentifier() + "ãï¼" + variant.getValue(); |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.stylefeng.guns.opcua.client; |
| | | |
| | | import java.nio.file.Files; |
| | | import java.nio.file.Path; |
| | | import java.nio.file.Paths; |
| | | import java.util.List; |
| | | import java.util.concurrent.CompletableFuture; |
| | | import java.util.concurrent.ExecutionException; |
| | | import java.util.function.Predicate; |
| | | |
| | | import org.eclipse.milo.opcua.sdk.client.OpcUaClient; |
| | | import org.eclipse.milo.opcua.sdk.client.api.config.OpcUaClientConfig; |
| | | import org.eclipse.milo.opcua.sdk.client.api.identity.AnonymousProvider; |
| | | import org.eclipse.milo.opcua.sdk.client.api.identity.UsernameProvider; |
| | | import org.eclipse.milo.opcua.stack.client.DiscoveryClient; |
| | | import org.eclipse.milo.opcua.stack.core.Stack; |
| | | import org.eclipse.milo.opcua.stack.core.security.SecurityPolicy; |
| | | import org.eclipse.milo.opcua.stack.core.types.builtin.LocalizedText; |
| | | |
| | | import cn.stylefeng.guns.opcua.cert.KeyStoreLoader; |
| | | import cn.stylefeng.guns.opcua.config.Properties; |
| | | |
| | | import lombok.extern.slf4j.Slf4j; |
| | | |
| | | import org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.Unsigned; |
| | | import org.eclipse.milo.opcua.stack.core.types.structured.EndpointDescription; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Component; |
| | | |
| | | /** |
| | | * @ClassName: ClientRunner |
| | | * @Description: 客æ·ç«¯å¯å¨ç±» |
| | | * @author yyt |
| | | * @date 2023å¹´10æ13æ¥ |
| | | */ |
| | | @Slf4j |
| | | @Component |
| | | public class ClientRunner { |
| | | |
| | | private final CompletableFuture<OpcUaClient> future = new CompletableFuture<>(); |
| | | |
| | | @Autowired |
| | | private Properties properties; |
| | | |
| | | @Autowired |
| | | private KeyStoreLoader keyStoreLoader; |
| | | |
| | | /** |
| | | * @MethodName: run |
| | | * @Description: å¯å¨ |
| | | * @return |
| | | * @throws Exception |
| | | * @CreateTime 2023å¹´10æ13æ¥ |
| | | */ |
| | | public OpcUaClient run() throws Exception { |
| | | |
| | | OpcUaClient client = createClient(); |
| | | |
| | | future.whenCompleteAsync((c, ex) -> { |
| | | if (ex != null) { |
| | | log.error("Error running example: {}", ex.getMessage(), ex); |
| | | } |
| | | |
| | | try { |
| | | c.disconnect().get(); |
| | | Stack.releaseSharedResources(); |
| | | } catch (InterruptedException | ExecutionException e) { |
| | | log.error("Error disconnecting:", e.getMessage(), e); |
| | | } |
| | | }); |
| | | |
| | | return client; |
| | | } |
| | | |
| | | /** |
| | | * @MethodName: createClient |
| | | * @Description: å建客æ·ç«¯ |
| | | * @return |
| | | * @throws Exception |
| | | * @CreateTime 2023å¹´10æ13æ¥ |
| | | */ |
| | | private OpcUaClient createClient() throws Exception { |
| | | |
| | | Path securityTempDir = Paths.get(properties.getCertPath(), "security"); |
| | | Files.createDirectories(securityTempDir); |
| | | if (!Files.exists(securityTempDir)) { |
| | | log.error("unable to create security dir: " + securityTempDir); |
| | | return null; |
| | | } |
| | | |
| | | KeyStoreLoader loader = keyStoreLoader.load(securityTempDir); |
| | | |
| | | // æç´¢OPCèç¹ |
| | | List<EndpointDescription> endpoints = null; |
| | | try { |
| | | //è·åå®å
¨çç¥ |
| | | endpoints = DiscoveryClient.getEndpoints(properties.getEndpointUrl()).get(); |
| | | } catch (Throwable e) { |
| | | // try the explicit discovery endpoint as well |
| | | String discoveryUrl = properties.getEndpointUrl(); |
| | | |
| | | if (!discoveryUrl.endsWith("/")) { |
| | | discoveryUrl += "/"; |
| | | } |
| | | discoveryUrl += "discovery"; |
| | | |
| | | log.info("Trying explicit discovery URL: {}", discoveryUrl); |
| | | endpoints = DiscoveryClient.getEndpoints(discoveryUrl).get(); |
| | | } |
| | | |
| | | EndpointDescription endpoint = endpoints.stream() |
| | | .filter(e -> e.getSecurityPolicyUri().equals(SecurityPolicy.None.getUri())).filter(endpointFilter()) |
| | | .findFirst().orElseThrow(() -> new Exception("no desired endpoints returned")); |
| | | |
| | | OpcUaClientConfig config = OpcUaClientConfig.builder() |
| | | // opc uaèªå®ä¹çå称 |
| | | .setApplicationName(LocalizedText.english("plc")) |
| | | // å°å |
| | | .setApplicationUri("opc.tcp://127.0.0.1:49320") |
| | | .setCertificate(loader.getClientCertificate()).setKeyPair(loader.getClientKeyPair()) |
| | | // å®å
¨çç¥çé
ç½® |
| | | //.setEndpoint(endpoint).setIdentityProvider(new UsernameProvider("OPCUA", "yyt@8888888888")) |
| | | .setEndpoint(endpoint) |
| | | // å¿åéªè¯ |
| | | .setIdentityProvider(new AnonymousProvider()) |
| | | //çå¾
æ¶é´ |
| | | .setRequestTimeout(Unsigned.uint(5000)).build(); |
| | | |
| | | return OpcUaClient.create(config); |
| | | |
| | | } |
| | | |
| | | /** |
| | | * @MethodName: endpointFilter |
| | | * @Description: endpointFilter |
| | | * @return |
| | | * @CreateTime 2023å¹´10æ13æ¥ |
| | | */ |
| | | private Predicate<EndpointDescription> endpointFilter() { |
| | | return e -> true; |
| | | } |
| | | |
| | | /** |
| | | * @return the future |
| | | */ |
| | | public CompletableFuture<OpcUaClient> getFuture() { |
| | | return future; |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /** |
| | | * Created by Jellyleo on 2019å¹´12æ19æ¥ |
| | | * Copyright © 2019 jellyleo.com |
| | | * All rights reserved. |
| | | */ |
| | | package cn.stylefeng.guns.opcua.config; |
| | | |
| | | import org.springframework.beans.factory.annotation.Value; |
| | | import org.springframework.context.annotation.Configuration; |
| | | import org.springframework.context.annotation.PropertySource; |
| | | |
| | | import lombok.Getter; |
| | | |
| | | /** |
| | | * @ClassName: Properties |
| | | * @Description: OpcUaåæ° |
| | | * @author yyt |
| | | * @date 2023å¹´10æ13æ¥ |
| | | */ |
| | | @Getter |
| | | @Configuration |
| | | @PropertySource("classpath:opcua.properties") |
| | | public class Properties { |
| | | @Value("${opcua.server.endpoint.url}") |
| | | private String endpointUrl; |
| | | @Value("${opcua.server.idp.username}") |
| | | private String idpUsername; |
| | | @Value("${opcua.server.idp.password}") |
| | | private String idpPassword; |
| | | @Value("${opcua.client.app.name}") |
| | | private String appName; |
| | | @Value("${opcua.client.app.uri}") |
| | | private String appUri; |
| | | @Value("${opcua.client.cert.path}") |
| | | private String certPath; |
| | | @Value("${opcua.client.cert.file}") |
| | | private String certFile; |
| | | @Value("${opcua.client.cert.alias}") |
| | | private String certAlias; |
| | | @Value("${opcua.client.cert.common.name}") |
| | | private String commonName; |
| | | @Value("${opcua.client.cert.organization}") |
| | | private String organization; |
| | | @Value("${opcua.client.cert.organization.unit}") |
| | | private String orgUnit; |
| | | @Value("${opcua.client.cert.locality.name}") |
| | | private String localityName; |
| | | @Value("${opcua.client.cert.state.name}") |
| | | private String stateName; |
| | | @Value("${opcua.client.cert.country.code}") |
| | | private String countryCode; |
| | | @Value("${opcua.client.cert.dns.name}") |
| | | private String dnsName; |
| | | @Value("${opcua.client.cert.ip.address}") |
| | | private String ipAddress; |
| | | @Value("${opcua.client.cert.keystore.password}") |
| | | private String keyPassword; |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.stylefeng.guns.opcua.controller; |
| | | |
| | | import java.util.List; |
| | | import java.util.stream.Collectors; |
| | | import java.util.stream.Stream; |
| | | |
| | | import javax.servlet.http.HttpServletRequest; |
| | | |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Controller; |
| | | import org.springframework.web.bind.annotation.RequestMapping; |
| | | import org.springframework.web.bind.annotation.ResponseBody; |
| | | import cn.stylefeng.guns.opcua.client.ClientHandler; |
| | | import cn.stylefeng.guns.opcua.entity.NodeEntity; |
| | | |
| | | //import com.google.common.collect.Lists; |
| | | |
| | | /** |
| | | * @ClassName: OpcUaController |
| | | * @Description: OpcUaæ§å¶å¨ |
| | | * @author yyt |
| | | * @date 2023å¹´10æ13æ¥ |
| | | */ |
| | | @Controller |
| | | public class CommonController { |
| | | |
| | | @Autowired |
| | | private ClientHandler clientHandler; |
| | | |
| | | /** |
| | | * @MethodName: connect |
| | | * @Description: opcuaè¿æ¥å¹¶è®¢é
åé |
| | | * @param request |
| | | * @param response |
| | | * @return |
| | | * @CreateTime 2023å¹´10æ13æ¥ |
| | | */ |
| | | @RequestMapping("/connect") |
| | | @ResponseBody |
| | | public String connect() { |
| | | |
| | | try { |
| | | return clientHandler.connect(); |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | return "fail"; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * @MethodName: disconnect |
| | | * @Description: disconnect |
| | | * @return |
| | | * @CreateTime 2023å¹´10æ13æ¥ |
| | | */ |
| | | @RequestMapping("/disconnect") |
| | | @ResponseBody |
| | | public String disconnect() { |
| | | |
| | | try { |
| | | return clientHandler.disconnect(); |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | return "fail"; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * @MethodName: subscribe |
| | | * @Description: subscribe |
| | | * @return |
| | | * @CreateTime 2023å¹´10æ13æ¥ |
| | | */ |
| | | @RequestMapping("/subscribe") |
| | | @ResponseBody |
| | | public String subscribe(HttpServletRequest request) { |
| | | |
| | | try { |
| | | List<NodeEntity> nodes = Stream.of(request.getParameter("id").split(",")) |
| | | .map(id -> NodeEntity.builder().index(2).identifier(id).build()).collect(Collectors.toList()); |
| | | |
| | | return clientHandler.subscribe(nodes); |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | return "fail"; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * @MethodName: write |
| | | * @Description: èç¹åå
¥ |
| | | * @param request |
| | | * @return |
| | | * @CreateTime 2023å¹´10æ13æ¥ |
| | | */ |
| | | @RequestMapping("/write") |
| | | @ResponseBody |
| | | public String write(HttpServletRequest request) { |
| | | |
| | | NodeEntity node = NodeEntity.builder().index(2).identifier(request.getParameter("id")) |
| | | .value(request.getParameter("value")).type(request.getParameter("type")).build(); |
| | | |
| | | try { |
| | | return clientHandler.write(node); |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | return "fail"; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * @MethodName: read |
| | | * @Description: read |
| | | * @param request |
| | | * @return |
| | | * @CreateTime 2023å¹´10æ13æ¥ |
| | | */ |
| | | @RequestMapping("/read") |
| | | @ResponseBody |
| | | public String read(HttpServletRequest request) { |
| | | |
| | | NodeEntity node = NodeEntity.builder().index(2).identifier(request.getParameter("id")).build(); |
| | | |
| | | try { |
| | | return clientHandler.read(node); |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | return "fail"; |
| | | } |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.stylefeng.guns.opcua.controller; |
| | | |
| | | import cn.stylefeng.guns.base.pojo.page.LayuiPageInfo; |
| | | import cn.stylefeng.guns.opcua.entity.OpcuaConf; |
| | | import cn.stylefeng.guns.opcua.model.params.OpcuaConfParam; |
| | | import cn.stylefeng.guns.opcua.service.OpcuaConfService; |
| | | import cn.stylefeng.roses.core.base.controller.BaseController; |
| | | import cn.stylefeng.roses.kernel.model.response.ResponseData; |
| | | import cn.stylefeng.roses.core.mutidatasource.annotion.DataSource; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Controller; |
| | | import org.springframework.web.bind.annotation.RequestMapping; |
| | | import org.springframework.web.bind.annotation.ResponseBody; |
| | | |
| | | |
| | | |
| | | /** |
| | | * æ§å¶å¨ |
| | | * |
| | | * @author yyt |
| | | * @Date 2023-10-17 09:29:17 |
| | | */ |
| | | @Controller |
| | | @RequestMapping("/opcuaConf") |
| | | public class OpcuaConfController extends BaseController { |
| | | |
| | | private String PREFIX = "/modular/bs/opcuaConf"; |
| | | |
| | | @Autowired |
| | | private OpcuaConfService opcuaConfService; |
| | | |
| | | /** |
| | | * 跳转å°ä¸»é¡µé¢ |
| | | * |
| | | * @author yyt |
| | | * @Date 2023-10-17 |
| | | */ |
| | | @RequestMapping("") |
| | | public String index() { |
| | | |
| | | return PREFIX + "/opcuaConf.html"; |
| | | } |
| | | |
| | | /** |
| | | * æ°å¢é¡µé¢ |
| | | * |
| | | * @author yyt |
| | | * @Date 2023-10-17 |
| | | */ |
| | | @RequestMapping("/add") |
| | | public String add() { |
| | | return PREFIX + "/opcuaConf_add.html"; |
| | | } |
| | | |
| | | /** |
| | | * ç¼è¾é¡µé¢ |
| | | * |
| | | * @author yyt |
| | | * @Date 2023-10-17 |
| | | */ |
| | | @RequestMapping("/edit") |
| | | public String edit() { |
| | | return PREFIX + "/opcuaConf_edit.html"; |
| | | } |
| | | |
| | | /** |
| | | * æ°å¢æ¥å£ |
| | | * |
| | | * @author yyt |
| | | * @Date 2023-10-17 |
| | | */ |
| | | @RequestMapping("/addItem") |
| | | @ResponseBody |
| | | @DataSource(name = "self") |
| | | public ResponseData addItem(OpcuaConfParam opcuaConfParam) { |
| | | this.opcuaConfService.add(opcuaConfParam); |
| | | return ResponseData.success(); |
| | | } |
| | | |
| | | /** |
| | | * ç¼è¾æ¥å£ |
| | | * |
| | | * @author yyt |
| | | * @Date 2023-10-17 |
| | | */ |
| | | @RequestMapping("/editItem") |
| | | @ResponseBody |
| | | @DataSource(name = "self") |
| | | public ResponseData editItem(OpcuaConfParam opcuaConfParam) { |
| | | this.opcuaConfService.update(opcuaConfParam); |
| | | return ResponseData.success(); |
| | | } |
| | | |
| | | /** |
| | | * å é¤æ¥å£ |
| | | * |
| | | * @author yyt |
| | | * @Date 2023-10-17 |
| | | */ |
| | | @RequestMapping("/delete") |
| | | @ResponseBody |
| | | @DataSource(name = "self") |
| | | public ResponseData delete(OpcuaConfParam opcuaConfParam) { |
| | | this.opcuaConfService.delete(opcuaConfParam); |
| | | return ResponseData.success(); |
| | | } |
| | | |
| | | /** |
| | | * æ¥ç详æ
æ¥å£ |
| | | * |
| | | * @author yyt |
| | | * @Date 2023-10-17 |
| | | */ |
| | | @RequestMapping("/detail") |
| | | @ResponseBody |
| | | @DataSource(name = "self") |
| | | public ResponseData detail(OpcuaConfParam opcuaConfParam) { |
| | | OpcuaConf detail = this.opcuaConfService.getById(opcuaConfParam.getId()); |
| | | return ResponseData.success(detail); |
| | | } |
| | | |
| | | /** |
| | | * æ¥è¯¢å表 |
| | | * |
| | | * @author yyt |
| | | * @Date 2023-10-17 |
| | | */ |
| | | @ResponseBody |
| | | @RequestMapping("/list") |
| | | @DataSource(name = "self") |
| | | public LayuiPageInfo list(OpcuaConfParam opcuaConfParam) { |
| | | return this.opcuaConfService.findPageBySpec(opcuaConfParam); |
| | | } |
| | | |
| | | } |
| | | |
| | | |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.stylefeng.guns.opcua.entity; |
| | | |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.Builder; |
| | | import lombok.Data; |
| | | import lombok.NoArgsConstructor; |
| | | |
| | | @Data |
| | | @Builder(toBuilder = true) |
| | | @AllArgsConstructor |
| | | @NoArgsConstructor |
| | | public class NodeEntity { |
| | | |
| | | private Integer index; |
| | | private String identifier; |
| | | private Object value; |
| | | private String type; |
| | | private Integer clientHandle; |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.stylefeng.guns.opcua.entity; |
| | | |
| | | import com.baomidou.mybatisplus.annotation.TableName; |
| | | import com.baomidou.mybatisplus.annotation.IdType; |
| | | import com.baomidou.mybatisplus.annotation.TableId; |
| | | import com.baomidou.mybatisplus.annotation.TableField; |
| | | import java.io.Serializable; |
| | | |
| | | /** |
| | | * <p> |
| | | * |
| | | * </p> |
| | | * |
| | | * @author yyt |
| | | * @since 2023-10-17 |
| | | */ |
| | | @TableName("sys_opcua_conf") |
| | | public class OpcuaConf implements Serializable { |
| | | private static final long serialVersionUID=1L; |
| | | |
| | | /** |
| | | * ID |
| | | */ |
| | | @TableId(value = "id", type = IdType.ID_WORKER) |
| | | private Long id; |
| | | |
| | | /** |
| | | * æå±æ¨¡å |
| | | */ |
| | | @TableField("module") |
| | | private String module; |
| | | |
| | | /** |
| | | * èç¹ |
| | | */ |
| | | @TableField("node") |
| | | private String node; |
| | | |
| | | /** |
| | | * é¿åº¦ |
| | | */ |
| | | @TableField("length") |
| | | private Integer length; |
| | | |
| | | /** |
| | | * ç±»å |
| | | */ |
| | | @TableField("sys_types") |
| | | private String sys_types; |
| | | |
| | | /** |
| | | * åè½è¯´æ |
| | | */ |
| | | @TableField("functionality") |
| | | private String functionality; |
| | | |
| | | /** |
| | | * æ¯å¦è®¢é
|
| | | */ |
| | | @TableField("subscribe") |
| | | private Integer subscribe; |
| | | |
| | | /** |
| | | * 订é
ååºæ¨¡å |
| | | */ |
| | | @TableField("r_module") |
| | | private String rModule; |
| | | |
| | | /** |
| | | * 订é
ååºå½æ° |
| | | */ |
| | | @TableField("r_function") |
| | | private String rFunction; |
| | | |
| | | /** |
| | | * å¤æ³¨ |
| | | */ |
| | | @TableField("remarks") |
| | | private String remarks; |
| | | |
| | | |
| | | public Long getId() { |
| | | return id; |
| | | } |
| | | |
| | | public void setId(Long id) { |
| | | this.id = id; |
| | | } |
| | | |
| | | public String getModule() { |
| | | return module; |
| | | } |
| | | |
| | | public void setModule(String module) { |
| | | this.module = module; |
| | | } |
| | | |
| | | public String getNode() { |
| | | return node; |
| | | } |
| | | |
| | | public void setNode(String node) { |
| | | this.node = node; |
| | | } |
| | | |
| | | public Integer getLength() { |
| | | return length; |
| | | } |
| | | |
| | | public void setLength(Integer length) { |
| | | this.length = length; |
| | | } |
| | | |
| | | public String getSys_types() { |
| | | return sys_types; |
| | | } |
| | | |
| | | public void setSys_types(String sys_types) { |
| | | this.sys_types = sys_types; |
| | | } |
| | | |
| | | public String getFunctionality() { |
| | | return functionality; |
| | | } |
| | | |
| | | public void setFunctionality(String functionality) { |
| | | this.functionality = functionality; |
| | | } |
| | | |
| | | public Integer getSubscribe() { |
| | | return subscribe; |
| | | } |
| | | |
| | | public void setSubscribe(Integer subscribe) { |
| | | this.subscribe = subscribe; |
| | | } |
| | | |
| | | public String getrModule() { |
| | | return rModule; |
| | | } |
| | | |
| | | public void setrModule(String rModule) { |
| | | this.rModule = rModule; |
| | | } |
| | | |
| | | public String getrFunction() { |
| | | return rFunction; |
| | | } |
| | | |
| | | public void setrFunction(String rFunction) { |
| | | this.rFunction = rFunction; |
| | | } |
| | | |
| | | public String getRemarks() { |
| | | return remarks; |
| | | } |
| | | |
| | | public void setRemarks(String remarks) { |
| | | this.remarks = remarks; |
| | | } |
| | | |
| | | @Override |
| | | public String toString() { |
| | | return "OpcuaConf{" + |
| | | "id=" + id + |
| | | ", module=" + module + |
| | | ", node=" + node + |
| | | ", length=" + length + |
| | | ", sys_types=" + sys_types + ", " + "functionality=" + functionality + |
| | | ", subscribe=" + subscribe + |
| | | ", rModule=" + rModule + |
| | | ", rFunction=" + rFunction + |
| | | ", remarks=" + remarks + |
| | | "}"; |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.stylefeng.guns.opcua.mapper; |
| | | |
| | | import cn.stylefeng.guns.opcua.entity.OpcuaConf; |
| | | import cn.stylefeng.guns.opcua.model.params.OpcuaConfParam; |
| | | import cn.stylefeng.guns.opcua.model.result.OpcuaConfResult; |
| | | import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import org.apache.ibatis.annotations.Param; |
| | | |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * <p> |
| | | * Mapper æ¥å£ |
| | | * </p> |
| | | * |
| | | * @author yyt |
| | | * @since 2023-10-17 |
| | | */ |
| | | public interface OpcuaConfMapper extends BaseMapper<OpcuaConf> { |
| | | |
| | | /** |
| | | * è·åå表 |
| | | * |
| | | * @author yyt |
| | | * @Date 2023-10-17 |
| | | */ |
| | | List<OpcuaConfResult> customList(@Param("paramCondition") OpcuaConfParam paramCondition); |
| | | |
| | | /** |
| | | * è·åmapå表 |
| | | * |
| | | * @author yyt |
| | | * @Date 2023-10-17 |
| | | */ |
| | | List<Map<String, Object>> customMapList(@Param("paramCondition") OpcuaConfParam paramCondition); |
| | | |
| | | /** |
| | | * è·åå页å®ä½å表 |
| | | * |
| | | * @author yyt |
| | | * @Date 2023-10-17 |
| | | */ |
| | | Page<OpcuaConfResult> customPageList(@Param("page") Page page, @Param("paramCondition") OpcuaConfParam paramCondition); |
| | | |
| | | /** |
| | | * è·åå页mapå表 |
| | | * |
| | | * @author yyt |
| | | * @Date 2023-10-17 |
| | | */ |
| | | Page<Map<String, Object>> customPageMapList(@Param("page") Page page, @Param("paramCondition") OpcuaConfParam paramCondition); |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> |
| | | <mapper namespace="cn.stylefeng.guns.opcua.mapper.OpcuaConfMapper"> |
| | | |
| | | <!-- éç¨æ¥è¯¢æ å°ç»æ --> |
| | | <resultMap id="BaseResultMap" type="cn.stylefeng.guns.opcua.entity.OpcuaConf"> |
| | | <id column="id" property="id" /> |
| | | <result column="module" property="module" /> |
| | | <result column="node" property="node" /> |
| | | <result column="length" property="length" /> |
| | | <result column="sys_types" property="sys_types" /> |
| | | <result column="functionality" property="functionality" /> |
| | | <result column="subscribe" property="subscribe" /> |
| | | <result column="r_module" property="rModule" /> |
| | | <result column="r_function" property="rFunction" /> |
| | | <result column="remarks" property="remarks" /> |
| | | </resultMap> |
| | | |
| | | <!-- éç¨æ¥è¯¢ç»æå --> |
| | | <sql id="Base_Column_List"> |
| | | id AS "id", module AS "module", node AS "node", length AS "length",sys_types AS "sys_types",functionality AS "functionality", subscribe AS "subscribe", r_module AS "rModule", r_function AS "rFunction", remarks AS "remarks" |
| | | </sql> |
| | | |
| | | |
| | | <select id="customList" resultType="cn.stylefeng.guns.opcua.model.result.OpcuaConfResult" parameterType="cn.stylefeng.guns.opcua.model.params.OpcuaConfParam"> |
| | | select |
| | | <include refid="Base_Column_List"/> |
| | | from sys_opcua_conf where 1 = 1 |
| | | </select> |
| | | |
| | | <select id="customMapList" resultType="map" parameterType="cn.stylefeng.guns.opcua.model.params.OpcuaConfParam"> |
| | | select |
| | | <include refid="Base_Column_List"/> |
| | | from sys_opcua_conf where 1 = 1 |
| | | </select> |
| | | |
| | | <select id="customPageList" resultType="cn.stylefeng.guns.opcua.model.result.OpcuaConfResult" parameterType="cn.stylefeng.guns.opcua.model.params.OpcuaConfParam"> |
| | | select |
| | | <include refid="Base_Column_List"/> |
| | | from sys_opcua_conf where 1 = 1 |
| | | </select> |
| | | |
| | | <select id="customPageMapList" resultType="map" parameterType="cn.stylefeng.guns.opcua.model.params.OpcuaConfParam"> |
| | | select |
| | | <include refid="Base_Column_List"/> |
| | | from sys_opcua_conf where 1 = 1 |
| | | </select> |
| | | |
| | | </mapper> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.stylefeng.guns.opcua.model.params; |
| | | |
| | | import lombok.Data; |
| | | import cn.stylefeng.roses.kernel.model.validator.BaseValidatingParam; |
| | | import java.util.Date; |
| | | import java.io.Serializable; |
| | | import java.math.BigDecimal; |
| | | |
| | | /** |
| | | * <p> |
| | | * |
| | | * </p> |
| | | * |
| | | * @author yyt |
| | | * @since 2023-10-17 |
| | | */ |
| | | @Data |
| | | public class OpcuaConfParam implements Serializable, BaseValidatingParam { |
| | | |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | |
| | | /** |
| | | * ID |
| | | */ |
| | | private Long id; |
| | | |
| | | /** |
| | | * æå±æ¨¡å |
| | | */ |
| | | private String module; |
| | | |
| | | /** |
| | | * èç¹ |
| | | */ |
| | | private String node; |
| | | |
| | | /** |
| | | * é¿åº¦ |
| | | */ |
| | | private Integer length; |
| | | |
| | | /** |
| | | * ç±»å |
| | | */ |
| | | private String sys_types; |
| | | |
| | | /** |
| | | * åè½è¯´æ |
| | | */ |
| | | private String functionality; |
| | | |
| | | /** |
| | | * æ¯å¦è®¢é
|
| | | */ |
| | | private Integer subscribe; |
| | | |
| | | /** |
| | | * 订é
ååºæ¨¡å |
| | | */ |
| | | private String rModule; |
| | | |
| | | /** |
| | | * 订é
ååºå½æ° |
| | | */ |
| | | private String rFunction; |
| | | |
| | | /** |
| | | * å¤æ³¨ |
| | | */ |
| | | private String remarks; |
| | | |
| | | @Override |
| | | public String checkParam() { |
| | | return null; |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.stylefeng.guns.opcua.model.result; |
| | | |
| | | import lombok.Data; |
| | | import java.util.Date; |
| | | import java.io.Serializable; |
| | | import java.math.BigDecimal; |
| | | |
| | | /** |
| | | * <p> |
| | | * |
| | | * </p> |
| | | * |
| | | * @author yyt |
| | | * @since 2023-10-17 |
| | | */ |
| | | @Data |
| | | public class OpcuaConfResult implements Serializable { |
| | | |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | |
| | | /** |
| | | * ID |
| | | */ |
| | | private Long id; |
| | | |
| | | /** |
| | | * æå±æ¨¡å |
| | | */ |
| | | private String module; |
| | | |
| | | /** |
| | | * èç¹ |
| | | */ |
| | | private String node; |
| | | |
| | | /** |
| | | * é¿åº¦ |
| | | */ |
| | | private Integer length; |
| | | |
| | | /** |
| | | * ç±»å |
| | | */ |
| | | private String sys_types; |
| | | |
| | | /** |
| | | * åè½è¯´æ |
| | | */ |
| | | private String functionality; |
| | | |
| | | /** |
| | | * æ¯å¦è®¢é
|
| | | */ |
| | | private Integer subscribe; |
| | | |
| | | /** |
| | | * 订é
ååºæ¨¡å |
| | | */ |
| | | private String rModule; |
| | | |
| | | /** |
| | | * 订é
ååºå½æ° |
| | | */ |
| | | private String rFunction; |
| | | |
| | | /** |
| | | * å¤æ³¨ |
| | | */ |
| | | private String remarks; |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.stylefeng.guns.opcua.service; |
| | | |
| | | import cn.stylefeng.guns.base.pojo.page.LayuiPageInfo; |
| | | import cn.stylefeng.guns.opcua.entity.OpcuaConf; |
| | | import cn.stylefeng.guns.opcua.model.params.OpcuaConfParam; |
| | | import cn.stylefeng.guns.opcua.model.result.OpcuaConfResult; |
| | | import com.baomidou.mybatisplus.extension.service.IService; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * <p> |
| | | * æå¡ç±» |
| | | * </p> |
| | | * |
| | | * @author yyt |
| | | * @since 2023-10-17 |
| | | */ |
| | | public interface OpcuaConfService extends IService<OpcuaConf> { |
| | | |
| | | /** |
| | | * æ°å¢ |
| | | * |
| | | * @author yyt |
| | | * @Date 2023-10-17 |
| | | */ |
| | | void add(OpcuaConfParam param); |
| | | |
| | | /** |
| | | * å é¤ |
| | | * |
| | | * @author yyt |
| | | * @Date 2023-10-17 |
| | | */ |
| | | void delete(OpcuaConfParam param); |
| | | |
| | | /** |
| | | * æ´æ° |
| | | * |
| | | * @author yyt |
| | | * @Date 2023-10-17 |
| | | */ |
| | | void update(OpcuaConfParam param); |
| | | |
| | | /** |
| | | * æ¥è¯¢åæ¡æ°æ®ï¼Specificationæ¨¡å¼ |
| | | * |
| | | * @author yyt |
| | | * @Date 2023-10-17 |
| | | */ |
| | | OpcuaConfResult findBySpec(OpcuaConfParam param); |
| | | |
| | | /** |
| | | * æ¥è¯¢å表ï¼Specificationæ¨¡å¼ |
| | | * |
| | | * @author yyt |
| | | * @Date 2023-10-17 |
| | | */ |
| | | List<OpcuaConfResult> findListBySpec(OpcuaConfParam param); |
| | | |
| | | /** |
| | | * æ¥è¯¢å页æ°æ®ï¼Specificationæ¨¡å¼ |
| | | * |
| | | * @author yyt |
| | | * @Date 2023-10-17 |
| | | */ |
| | | LayuiPageInfo findPageBySpec(OpcuaConfParam param); |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.stylefeng.guns.opcua.service.impl; |
| | | |
| | | import cn.stylefeng.guns.base.pojo.page.LayuiPageFactory; |
| | | import cn.stylefeng.guns.base.pojo.page.LayuiPageInfo; |
| | | import cn.stylefeng.guns.opcua.entity.OpcuaConf; |
| | | import cn.stylefeng.guns.opcua.mapper.OpcuaConfMapper; |
| | | import cn.stylefeng.guns.opcua.model.params.OpcuaConfParam; |
| | | import cn.stylefeng.guns.opcua.model.result.OpcuaConfResult; |
| | | import cn.stylefeng.guns.opcua.service.OpcuaConfService; |
| | | import cn.stylefeng.roses.core.util.ToolUtil; |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | import java.io.Serializable; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * <p> |
| | | * æå¡å®ç°ç±» |
| | | * </p> |
| | | * |
| | | * @author yyt |
| | | * @since 2023-10-17 |
| | | */ |
| | | @Service |
| | | public class OpcuaConfServiceImpl extends ServiceImpl<OpcuaConfMapper, OpcuaConf> implements OpcuaConfService { |
| | | |
| | | @Override |
| | | public void add(OpcuaConfParam param){ |
| | | OpcuaConf entity = getEntity(param); |
| | | this.save(entity); |
| | | } |
| | | |
| | | @Override |
| | | public void delete(OpcuaConfParam param){ |
| | | this.removeById(getKey(param)); |
| | | } |
| | | |
| | | @Override |
| | | public void update(OpcuaConfParam param){ |
| | | OpcuaConf oldEntity = getOldEntity(param); |
| | | OpcuaConf newEntity = getEntity(param); |
| | | ToolUtil.copyProperties(newEntity, oldEntity); |
| | | this.updateById(newEntity); |
| | | } |
| | | |
| | | @Override |
| | | public OpcuaConfResult findBySpec(OpcuaConfParam param){ |
| | | return null; |
| | | } |
| | | |
| | | @Override |
| | | public List<OpcuaConfResult> findListBySpec(OpcuaConfParam param){ |
| | | return null; |
| | | } |
| | | |
| | | @Override |
| | | public LayuiPageInfo findPageBySpec(OpcuaConfParam param){ |
| | | Page pageContext = getPageContext(); |
| | | IPage page = this.baseMapper.customPageList(pageContext, param); |
| | | return LayuiPageFactory.createPageInfo(page); |
| | | } |
| | | |
| | | private Serializable getKey(OpcuaConfParam param){ |
| | | return param.getId(); |
| | | } |
| | | |
| | | private Page getPageContext() { |
| | | return LayuiPageFactory.defaultPage(); |
| | | } |
| | | |
| | | private OpcuaConf getOldEntity(OpcuaConfParam param) { |
| | | return this.getById(getKey(param)); |
| | | } |
| | | |
| | | private OpcuaConf getEntity(OpcuaConfParam param) { |
| | | OpcuaConf entity = new OpcuaConf(); |
| | | ToolUtil.copyProperties(param, entity); |
| | | return entity; |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | #opcua????? |
| | | opcua.server.endpoint.url=opc.tcp://127.0.0.1:49320 |
| | | opcua.server.idp.username=administrator |
| | | opcua.server.idp.password=yyt@8888888888 |
| | | #opcua????? |
| | | opcua.client.app.name=plc |
| | | opcua.client.app.uri=urn:Yyt_PC:UnifiedAutomation:UaExpert |
| | | opcua.client.cert.path=C:/Users/30672/Desktop |
| | | opcua.client.cert.file=Yyt_PC-client.pfx |
| | | opcua.client.cert.alias=jlclient-ai |
| | | opcua.client.cert.common.name=UaClient@Jellyleo |
| | | opcua.client.cert.organization=JL |
| | | opcua.client.cert.organization.unit=per |
| | | opcua.client.cert.locality.name=jl |
| | | opcua.client.cert.state.name=JiangSu |
| | | opcua.client.cert.country.code=CN |
| | | opcua.client.cert.dns.name=Jellyleo |
| | | opcua.client.cert.ip.address=administrator |
| | | opcua.client.cert.keystore.password=yyt@8888888888 |
¶Ô±ÈÐÂÎļþ |
| | |
| | | #opcuaæå¡ç«¯è®¾ç½® |
| | | opcua: |
| | | server: |
| | | endpoint: |
| | | url: opc.tcp://127.0.0.1:49320 |
| | | idp: |
| | | username: administrator |
| | | password: yyt@8888888888 |
| | | #opcua客æ·ç«¯è®¾ç½® |
| | | client: |
| | | app: |
| | | name: plc |
| | | uri: urn:Yyt_PC:UnifiedAutomation:UaExpert |
| | | cert: |
| | | path: C:/Users/30672/Desktop |
| | | file: Yyt_PC-client.pfx |
| | | alias: jlclient-ai |
| | | common: |
| | | name: UaClient@Jellyleo |
| | | #opcua.client.cert.organization=JL |
| | | #opcua.client.cert.organization.unit=per |
| | | #opcua.client.cert.locality.name=jl |
| | | #opcua.client.cert.state.name=JiangSu |
| | | #opcua.client.cert.country.code=CN |
| | | #opcua.client.cert.dns.name=Jellyleo |
| | | #opcua.client.cert.ip.address=administrator |
| | | #opcua.client.cert.keystore.password=yyt@8888888888 |
¶Ô±ÈÐÂÎļþ |
| | |
| | | layui.use(['table', 'admin', 'ax', 'func'], function () { |
| | | var $ = layui.$; |
| | | var table = layui.table; |
| | | var $ax = layui.ax; |
| | | var admin = layui.admin; |
| | | var func = layui.func; |
| | | |
| | | /** |
| | | * 管ç |
| | | */ |
| | | var OpcuaConf = { |
| | | tableId: "opcuaConfTable" |
| | | }; |
| | | |
| | | /** |
| | | * åå§åè¡¨æ ¼çå |
| | | */ |
| | | OpcuaConf.initColumn = function () { |
| | | return [[ |
| | | {type: 'checkbox'}, |
| | | {field: 'id', hide: true, title: 'ID'}, |
| | | {field: 'module', sort: true, title: 'æå±æ¨¡å'}, |
| | | {field: 'node', sort: true, title: 'èç¹'}, |
| | | {field: 'length', sort: true, title: 'é¿åº¦'}, |
| | | {field: 'types', sort: true, title: 'ç±»å'}, |
| | | {field: 'functionality', sort: true, title: 'åè½è¯´æ'}, |
| | | {field: 'subscribe', sort: true, title: 'æ¯å¦è®¢é
'}, |
| | | {field: 'rModule', sort: true, title: '订é
ååºæ¨¡å'}, |
| | | {field: 'rFunction', sort: true, title: '订é
ååºå½æ°'}, |
| | | {field: 'remarks', sort: true, title: 'å¤æ³¨'}, |
| | | {fixed: 'right',width: 125, minWidth: 125, align: 'center', toolbar: '#tableBar', title: 'æä½'} |
| | | ]]; |
| | | }; |
| | | |
| | | /** |
| | | * ç¹å»æ¥è¯¢æé® |
| | | */ |
| | | OpcuaConf.search = function () { |
| | | var queryData = {}; |
| | | |
| | | |
| | | table.reload(OpcuaConf.tableId, { |
| | | where: queryData, page: {curr: 1} |
| | | }); |
| | | }; |
| | | |
| | | /** |
| | | * 跳转å°æ·»å é¡µé¢ |
| | | */ |
| | | OpcuaConf.jumpAddPage = function () { |
| | | window.location.href = Feng.ctxPath + '/opcuaConf/add' |
| | | }; |
| | | |
| | | /** |
| | | * 跳转å°ç¼è¾é¡µé¢ |
| | | * |
| | | * @param data ç¹å»æé®æ¶åçè¡æ°æ® |
| | | */ |
| | | OpcuaConf.jumpEditPage = function (data) { |
| | | window.location.href = Feng.ctxPath + '/opcuaConf/edit?id=' + data.id |
| | | }; |
| | | |
| | | /** |
| | | * 导åºexcelæé® |
| | | */ |
| | | OpcuaConf.exportExcel = function () { |
| | | var checkRows = table.checkStatus(OpcuaConf.tableId); |
| | | if (checkRows.data.length === 0) { |
| | | Feng.error("请éæ©è¦å¯¼åºçæ°æ®"); |
| | | } else { |
| | | table.exportFile(tableResult.config.id, checkRows.data, 'xls'); |
| | | } |
| | | }; |
| | | |
| | | /** |
| | | * ç¹å»å é¤ |
| | | * |
| | | * @param data ç¹å»æé®æ¶åçè¡æ°æ® |
| | | */ |
| | | OpcuaConf.onDeleteItem = function (data) { |
| | | var operation = function () { |
| | | var ajax = new $ax(Feng.ctxPath + "/opcuaConf/delete", function (data) { |
| | | Feng.success("å é¤æå!"); |
| | | table.reload(OpcuaConf.tableId); |
| | | }, function (data) { |
| | | Feng.error("å é¤å¤±è´¥!" + data.responseJSON.message + "!"); |
| | | }); |
| | | ajax.set("id", data.id); |
| | | ajax.start(); |
| | | }; |
| | | Feng.confirm("æ¯å¦å é¤?", operation); |
| | | }; |
| | | |
| | | // 渲æè¡¨æ ¼ |
| | | var tableResult = table.render({ |
| | | elem: '#' + OpcuaConf.tableId, |
| | | url: Feng.ctxPath + '/opcuaConf/list', |
| | | page: true, |
| | | height: "full-158", |
| | | cellMinWidth: 100, |
| | | cols: OpcuaConf.initColumn() |
| | | }); |
| | | |
| | | // æç´¢æé®ç¹å»äºä»¶ |
| | | $('#btnSearch').click(function () { |
| | | OpcuaConf.search(); |
| | | }); |
| | | |
| | | // æ·»å æé®ç¹å»äºä»¶ |
| | | $('#btnAdd').click(function () { |
| | | |
| | | OpcuaConf.jumpAddPage(); |
| | | |
| | | }); |
| | | |
| | | // 导åºexcel |
| | | $('#btnExp').click(function () { |
| | | OpcuaConf.exportExcel(); |
| | | }); |
| | | |
| | | // å·¥å
·æ¡ç¹å»äºä»¶ |
| | | table.on('tool(' + OpcuaConf.tableId + ')', function (obj) { |
| | | var data = obj.data; |
| | | var layEvent = obj.event; |
| | | |
| | | if (layEvent === 'edit') { |
| | | OpcuaConf.jumpEditPage(data); |
| | | } else if (layEvent === 'delete') { |
| | | OpcuaConf.onDeleteItem(data); |
| | | } |
| | | }); |
| | | }); |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /** |
| | | * æ·»å æè
ä¿®æ¹é¡µé¢ |
| | | */ |
| | | var OpcuaConfInfoDlg = { |
| | | data: { |
| | | id: "", |
| | | module: "", |
| | | node: "", |
| | | length: "", |
| | | types: "", |
| | | functionality: "", |
| | | subscribe: "", |
| | | rModule: "", |
| | | rFunction: "", |
| | | remarks: "" |
| | | } |
| | | }; |
| | | |
| | | layui.use(['form', 'admin', 'ax','laydate','upload','formSelects'], function () { |
| | | var $ = layui.jquery; |
| | | var $ax = layui.ax; |
| | | var form = layui.form; |
| | | var admin = layui.admin; |
| | | |
| | | //表åæ交äºä»¶ |
| | | form.on('submit(btnSubmit)', function (data) { |
| | | var ajax = new $ax(Feng.ctxPath + "/opcuaConf/addItem", function (data) { |
| | | Feng.success("æ·»å æåï¼"); |
| | | window.location.href = Feng.ctxPath + '/opcuaConf' |
| | | }, function (data) { |
| | | Feng.error("æ·»å 失败ï¼" + data.responseJSON.message) |
| | | }); |
| | | ajax.set(data.field); |
| | | ajax.start(); |
| | | |
| | | return false; |
| | | }); |
| | | |
| | | $('#cancel').click(function(){ |
| | | window.location.href = Feng.ctxPath + '/opcuaConf' |
| | | }); |
| | | |
| | | }); |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /** |
| | | * 详æ
对è¯æ¡ |
| | | */ |
| | | var OpcuaConfInfoDlg = { |
| | | data: { |
| | | id: "", |
| | | module: "", |
| | | node: "", |
| | | length: "", |
| | | types: "", |
| | | functionality: "", |
| | | subscribe: "", |
| | | rModule: "", |
| | | rFunction: "", |
| | | remarks: "" |
| | | } |
| | | }; |
| | | |
| | | layui.use(['form', 'admin', 'ax','laydate','upload','formSelects'], function () { |
| | | var $ = layui.jquery; |
| | | var $ax = layui.ax; |
| | | var form = layui.form; |
| | | var admin = layui.admin; |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | //è·å详æ
ä¿¡æ¯ï¼å¡«å
表å |
| | | var ajax = new $ax(Feng.ctxPath + "/opcuaConf/detail?id=" + Feng.getUrlParam("id")); |
| | | var result = ajax.start(); |
| | | form.val('opcuaConfForm', result.data); |
| | | |
| | | //表åæ交äºä»¶ |
| | | form.on('submit(btnSubmit)', function (data) { |
| | | var ajax = new $ax(Feng.ctxPath + "/opcuaConf/editItem", function (data) { |
| | | Feng.success("æ´æ°æåï¼"); |
| | | window.location.href = Feng.ctxPath + '/opcuaConf' |
| | | }, function (data) { |
| | | Feng.error("æ´æ°å¤±è´¥ï¼" + data.responseJSON.message) |
| | | }); |
| | | ajax.set(data.field); |
| | | ajax.start(); |
| | | |
| | | return false; |
| | | }); |
| | | |
| | | $('#cancel').click(function(){ |
| | | window.location.href = Feng.ctxPath + '/opcuaConf' |
| | | }); |
| | | }); |
¶Ô±ÈÐÂÎļþ |
| | |
| | | @layout("/common/_container.html",{js:["/assets/modular/bs/opcuaConf/opcuaConf.js"]}){ |
| | | |
| | | <div class="layui-body-header"> |
| | | <span class="layui-body-header-title">管ç</span> |
| | | </div> |
| | | |
| | | <div class="layui-fluid"> |
| | | <div class="layui-row layui-col-space15"> |
| | | <div class="layui-col-sm12 layui-col-md12 layui-col-lg12"> |
| | | <div class="layui-card"> |
| | | <div class="layui-card-body"> |
| | | <div class="layui-form toolbar"> |
| | | <div class="layui-form-item"> |
| | | <div class="layui-inline"> |
| | | <button id="btnSearch" class="layui-btn icon-btn"><i class="layui-icon"></i>æç´¢</button> |
| | | <button id="btnAdd" class="layui-btn icon-btn"><i class="layui-icon"></i>æ·»å </button> |
| | | <button id="btnExp" class="layui-btn icon-btn"><i class="layui-icon"></i>导åº</button> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <table class="layui-table" id="opcuaConfTable" lay-filter="opcuaConfTable"></table> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <script type="text/html" id="tableBar"> |
| | | <a class="layui-btn layui-btn-primary layui-btn-xs" lay-event="edit">ä¿®æ¹</a> |
| | | <a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="delete">å é¤</a> |
| | | </script> |
| | | @} |
¶Ô±ÈÐÂÎļþ |
| | |
| | | @layout("/common/_form.html",{js:["/assets/modular/bs/opcuaConf/opcuaConf_add.js"],css:["/assets/expand/module/formSelects/formSelects-v4.css"]}){ |
| | | |
| | | <form class="layui-form" id="opcuaConfForm" lay-filter="opcuaConfForm"> |
| | | <div class="layui-fluid" style="padding-bottom: 75px;"> |
| | | <div class="layui-card"> |
| | | <div class="layui-card-header">åºæ¬ä¿¡æ¯</div> |
| | | <div class="layui-card-body"> |
| | | <div class="layui-form-item layui-row"> |
| | | <input name="id" type="hidden"/> |
| | | |
| | | <div class="layui-inline layui-col-md12"> |
| | | <label class="layui-form-label">æå±æ¨¡å<span style="color: red;">*</span></label> |
| | | <div class="layui-input-block"> |
| | | <input id="module" name="module" placeholder="请è¾å
¥æå±æ¨¡å" type="text" class="layui-input" lay-verify="required" required/> |
| | | </div> |
| | | </div> |
| | | <div class="layui-inline layui-col-md12"> |
| | | <label class="layui-form-label">èç¹<span style="color: red;">*</span></label> |
| | | <div class="layui-input-block"> |
| | | <input id="node" name="node" placeholder="请è¾å
¥èç¹" type="text" class="layui-input" lay-verify="required" required/> |
| | | </div> |
| | | </div> |
| | | <div class="layui-inline layui-col-md12"> |
| | | <label class="layui-form-label">é¿åº¦<span style="color: red;">*</span></label> |
| | | <div class="layui-input-block"> |
| | | <input id="length" name="length" placeholder="请è¾å
¥é¿åº¦" type="text" class="layui-input" lay-verify="required" required/> |
| | | </div> |
| | | </div> |
| | | <div class="layui-inline layui-col-md12"> |
| | | <label class="layui-form-label">ç±»å<span style="color: red;">*</span></label> |
| | | <div class="layui-input-block"> |
| | | <input id=" |
| | | |
| | | |
| | | |
| | | types" name=" |
| | | |
| | | |
| | | |
| | | types" placeholder="请è¾å
¥ç±»å" type="text" class="layui-input" lay-verify="required" required/> |
| | | </div> |
| | | </div> |
| | | <div class="layui-inline layui-col-md12"> |
| | | <label class="layui-form-label">åè½è¯´æ<span style="color: red;">*</span></label> |
| | | <div class="layui-input-block"> |
| | | <input id=" |
| | | functionality" name=" |
| | | functionality" placeholder="请è¾å
¥åè½è¯´æ" type="text" class="layui-input" lay-verify="required" required/> |
| | | </div> |
| | | </div> |
| | | <div class="layui-inline layui-col-md12"> |
| | | <label class="layui-form-label">æ¯å¦è®¢é
<span style="color: red;">*</span></label> |
| | | <div class="layui-input-block"> |
| | | <input id="subscribe" name="subscribe" placeholder="请è¾å
¥æ¯å¦è®¢é
" type="text" class="layui-input" lay-verify="required" required/> |
| | | </div> |
| | | </div> |
| | | <div class="layui-inline layui-col-md12"> |
| | | <label class="layui-form-label">订é
ååºæ¨¡å<span style="color: red;">*</span></label> |
| | | <div class="layui-input-block"> |
| | | <input id="rModule" name="rModule" placeholder="请è¾å
¥è®¢é
ååºæ¨¡å" type="text" class="layui-input" lay-verify="required" required/> |
| | | </div> |
| | | </div> |
| | | <div class="layui-inline layui-col-md12"> |
| | | <label class="layui-form-label">订é
ååºå½æ°<span style="color: red;">*</span></label> |
| | | <div class="layui-input-block"> |
| | | <input id="rFunction" name="rFunction" placeholder="请è¾å
¥è®¢é
ååºå½æ°" type="text" class="layui-input" lay-verify="required" required/> |
| | | </div> |
| | | </div> |
| | | <div class="layui-inline layui-col-md12"> |
| | | <label class="layui-form-label">å¤æ³¨<span style="color: red;">*</span></label> |
| | | <div class="layui-input-block"> |
| | | <input id="remarks" name="remarks" placeholder="请è¾å
¥å¤æ³¨" type="text" class="layui-input" lay-verify="required" required/> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="form-group-bottom text-center"> |
| | | <button class="layui-btn" lay-filter="btnSubmit" lay-submit> æ交 </button> |
| | | <button type="reset" class="layui-btn layui-btn-primary" id="cancel"> åæ¶ </button> |
| | | </div> |
| | | |
| | | </form> |
| | | |
| | | @} |
¶Ô±ÈÐÂÎļþ |
| | |
| | | @layout("/common/_form.html",{js:["/assets/modular/bs/opcuaConf/opcuaConf_edit.js"]}){ |
| | | |
| | | <form class="layui-form" id="opcuaConfForm" lay-filter="opcuaConfForm"> |
| | | <div class="layui-fluid" style="padding-bottom: 75px;"> |
| | | <div class="layui-card"> |
| | | <div class="layui-card-header">åºæ¬ä¿¡æ¯</div> |
| | | <div class="layui-card-body"> |
| | | <div class="layui-form-item layui-row"> |
| | | <input name="id" type="hidden"/> |
| | | |
| | | <div class="layui-inline layui-col-md12"> |
| | | <label class="layui-form-label">æå±æ¨¡å<span style="color: red;">*</span></label> |
| | | <div class="layui-input-block"> |
| | | <input id="module" name="module" placeholder="请è¾å
¥æå±æ¨¡å" type="text" class="layui-input" lay-verify="required" required/> |
| | | </div> |
| | | </div> |
| | | <div class="layui-inline layui-col-md12"> |
| | | <label class="layui-form-label">èç¹<span style="color: red;">*</span></label> |
| | | <div class="layui-input-block"> |
| | | <input id="node" name="node" placeholder="请è¾å
¥èç¹" type="text" class="layui-input" lay-verify="required" required/> |
| | | </div> |
| | | </div> |
| | | <div class="layui-inline layui-col-md12"> |
| | | <label class="layui-form-label">é¿åº¦<span style="color: red;">*</span></label> |
| | | <div class="layui-input-block"> |
| | | <input id="length" name="length" placeholder="请è¾å
¥é¿åº¦" type="text" class="layui-input" lay-verify="required" required/> |
| | | </div> |
| | | </div> |
| | | <div class="layui-inline layui-col-md12"> |
| | | <label class="layui-form-label">ç±»å<span style="color: red;">*</span></label> |
| | | <div class="layui-input-block"> |
| | | <input id=" |
| | | |
| | | |
| | | |
| | | types" name=" |
| | | |
| | | |
| | | |
| | | types" placeholder="请è¾å
¥ç±»å" type="text" class="layui-input" lay-verify="required" required/> |
| | | </div> |
| | | </div> |
| | | <div class="layui-inline layui-col-md12"> |
| | | <label class="layui-form-label">åè½è¯´æ<span style="color: red;">*</span></label> |
| | | <div class="layui-input-block"> |
| | | <input id=" |
| | | functionality" name=" |
| | | functionality" placeholder="请è¾å
¥åè½è¯´æ" type="text" class="layui-input" lay-verify="required" required/> |
| | | </div> |
| | | </div> |
| | | <div class="layui-inline layui-col-md12"> |
| | | <label class="layui-form-label">æ¯å¦è®¢é
<span style="color: red;">*</span></label> |
| | | <div class="layui-input-block"> |
| | | <input id="subscribe" name="subscribe" placeholder="请è¾å
¥æ¯å¦è®¢é
" type="text" class="layui-input" lay-verify="required" required/> |
| | | </div> |
| | | </div> |
| | | <div class="layui-inline layui-col-md12"> |
| | | <label class="layui-form-label">订é
ååºæ¨¡å<span style="color: red;">*</span></label> |
| | | <div class="layui-input-block"> |
| | | <input id="rModule" name="rModule" placeholder="请è¾å
¥è®¢é
ååºæ¨¡å" type="text" class="layui-input" lay-verify="required" required/> |
| | | </div> |
| | | </div> |
| | | <div class="layui-inline layui-col-md12"> |
| | | <label class="layui-form-label">订é
ååºå½æ°<span style="color: red;">*</span></label> |
| | | <div class="layui-input-block"> |
| | | <input id="rFunction" name="rFunction" placeholder="请è¾å
¥è®¢é
ååºå½æ°" type="text" class="layui-input" lay-verify="required" required/> |
| | | </div> |
| | | </div> |
| | | <div class="layui-inline layui-col-md12"> |
| | | <label class="layui-form-label">å¤æ³¨<span style="color: red;">*</span></label> |
| | | <div class="layui-input-block"> |
| | | <input id="remarks" name="remarks" placeholder="请è¾å
¥å¤æ³¨" type="text" class="layui-input" lay-verify="required" required/> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="form-group-bottom text-center"> |
| | | <button class="layui-btn" lay-filter="btnSubmit" lay-submit> æ交 </button> |
| | | <button type="reset" class="layui-btn layui-btn-primary" id="cancel"> åæ¶ </button> |
| | | </div> |
| | | |
| | | </form> |
| | | |
| | | @} |