Browse Source

support OPCUA and LWIP

pull/123/head
wlyu 8 months ago
parent
commit
c20c9c20d2
  1. 10
      APP_Framework/Applications/control_app/Makefile
  2. 3
      APP_Framework/Applications/control_app/lwip_demo/Makefile
  3. 159
      APP_Framework/Applications/control_app/lwip_demo/lwip_ping_demo.c
  4. 418
      APP_Framework/Applications/control_app/lwip_demo/ping.c
  5. 19
      APP_Framework/Applications/control_app/lwip_demo/ping.h
  6. 3
      APP_Framework/Applications/control_app/opcua_demo/Makefile
  7. 246
      APP_Framework/Applications/control_app/opcua_demo/opcua_demo.c
  8. 6
      APP_Framework/Framework/control/Kconfig
  9. 2
      APP_Framework/Framework/control/Makefile
  10. 4
      APP_Framework/Framework/control/plc/Makefile
  11. 5
      APP_Framework/Framework/control/plc/interoperability/Kconfig
  12. 9
      APP_Framework/Framework/control/plc/interoperability/Makefile
  13. 30
      APP_Framework/Framework/control/plc/interoperability/interoperability.c
  14. 0
      APP_Framework/Framework/control/plc/interoperability/opcua/Kconfig
  15. 3
      APP_Framework/Framework/control/plc/interoperability/opcua/Makefile
  16. 71784
      APP_Framework/Framework/control/plc/interoperability/opcua/open62541.c
  17. 31298
      APP_Framework/Framework/control/plc/interoperability/opcua/open62541.h
  18. 342
      APP_Framework/Framework/control/plc/interoperability/opcua/ua_client.c
  19. 201
      APP_Framework/Framework/control/plc/interoperability/opcua/ua_data.c
  20. 38
      APP_Framework/Framework/control/plc/interoperability/opcua/ua_server.c
  21. 30
      APP_Framework/Framework/control/plc/interoperability/opcua/ua_test.c
  22. 4
      APP_Framework/Framework/control/plc/shared/Kconfig
  23. 4
      APP_Framework/Framework/control/plc/shared/Makefile
  24. 57
      APP_Framework/Framework/control/plc/shared/plc.c
  25. 124
      APP_Framework/Framework/control/plc/shared/plc.h
  26. 5
      APP_Framework/Framework/control/shared/Makefile
  27. 11
      APP_Framework/Framework/control/shared/control.c
  28. 510
      Ubiquitous/XiUOS/board/ok1052-c/board.c
  29. 281
      Ubiquitous/XiUOS/board/ok1052-c/board.h
  30. 12
      Ubiquitous/XiUOS/board/ok1052-c/link.lds
  31. 243
      Ubiquitous/XiUOS/board/ok1052-c/pin_mux.c
  32. 5
      Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/Kconfig
  33. 2
      Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/MIMXRT1052/drivers/Makefile
  34. 623
      Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/MIMXRT1052/drivers/fsl_cache.c
  35. 488
      Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/MIMXRT1052/drivers/fsl_cache.h
  36. 20
      Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/MIMXRT1052/drivers/fsl_clock.c
  37. 577
      Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/MIMXRT1052/drivers/fsl_clock.h
  38. 20
      Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/MIMXRT1052/drivers/fsl_common.c
  39. 36
      Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/MIMXRT1052/drivers/fsl_common.h
  40. 1123
      Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/MIMXRT1052/drivers/fsl_debug_console.c
  41. 213
      Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/MIMXRT1052/drivers/fsl_debug_console.h
  42. 158
      Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/MIMXRT1052/drivers/fsl_debug_console_conf.h
  43. 3517
      Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/MIMXRT1052/drivers/fsl_enet.c
  44. 1629
      Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/MIMXRT1052/drivers/fsl_enet.h
  45. 171
      Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/MIMXRT1052/drivers/fsl_gpio.c
  46. 20
      Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/MIMXRT1052/drivers/fsl_iomuxc.h
  47. 20
      Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/MIMXRT1052/drivers/fsl_lpuart.c
  48. 21
      Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/MIMXRT1052/drivers/fsl_lpuart.h
  49. 336
      Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/MIMXRT1052/drivers/fsl_phy.c
  50. 221
      Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/MIMXRT1052/drivers/fsl_phy.h
  51. 1
      Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/MIMXRT1052/system_MIMXRT1052.c
  52. 4
      Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/Makefile
  53. 1
      Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/ethernet/Kconfig
  54. 3
      Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/ethernet/Makefile
  55. 324
      Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/ethernet/enet_ethernetif.c
  56. 202
      Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/ethernet/enet_ethernetif.h
  57. 646
      Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/ethernet/enet_ethernetif_kinetis.c
  58. 972
      Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/ethernet/enet_ethernetif_lpc.c
  59. 94
      Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/ethernet/enet_ethernetif_priv.h
  60. 75
      Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/include/connect_ethernet.h
  61. 5
      Ubiquitous/XiUOS/path_app.mk
  62. 10
      Ubiquitous/XiUOS/path_kernel.mk

10
APP_Framework/Applications/control_app/Makefile

@ -0,0 +1,10 @@
SRC_DIR :=
ifeq ($(CONFIG_RESOURCES_LWIP),y)
SRC_DIR += lwip_demo
endif
ifeq ($(CONFIG_USING_CONTROL_PLC_OPCUA), y)
SRC_DIR += opcua_demo
endif
include $(KERNEL_ROOT)/compiler.mk

3
APP_Framework/Applications/control_app/lwip_demo/Makefile

@ -0,0 +1,3 @@
SRC_FILES := ping.c lwip_ping_demo.c
include $(KERNEL_ROOT)/compiler.mk

159
APP_Framework/Applications/control_app/lwip_demo/lwip_ping_demo.c

@ -0,0 +1,159 @@
/*
* Copyright (c) 2016, Freescale Semiconductor, Inc.
* Copyright 2016-2019 NXP
* All rights reserved.
*
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/*
* Copyright (c) 2021 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file lwip_ping_demo.c
* @brief Demo for ping function
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021.12.15
*/
/*******************************************************************************
* Includes
******************************************************************************/
#if LWIP_IPV4 && LWIP_RAW
#include "ping.h"
#include "lwip/opt.h"
#include "lwip/timeouts.h"
#include "lwip/init.h"
#include "netif/ethernet.h"
#include "board.h"
#include "pin_mux.h"
#include "clock_config.h"
#include "fsl_gpio.h"
#include "fsl_iomuxc.h"
#include <transform.h>
#include <sys_arch.h>
#include "connect_ethernet.h"
/*******************************************************************************
* Definitions
******************************************************************************/
/* IP address configuration. */
#define TEST_IP_ADDR0 192
#define TEST_IP_ADDR1 168
#define TEST_IP_ADDR2 250
#define TEST_IP_ADDR3 253
/* Netmask configuration. */
#define TEST_NET_MASK0 255
#define TEST_NET_MASK1 255
#define TEST_NET_MASK2 255
#define TEST_NET_MASK3 0
/* Gateway address configuration. */
#define TEST_GW_ADDR0 192
#define TEST_GW_ADDR1 168
#define TEST_GW_ADDR2 250
#define TEST_GW_ADDR3 252
/* MAC address configuration. */
#define TEST_MAC_ADDR {0x02, 0x12, 0x13, 0x10, 0x15, 0x11}
/* Address of PHY interface. */
#define TEST_PHY_ADDR 0x02U
/* System clock name. */
#define TEST_CLOCK_NAME kCLOCK_CoreSysClk
/*******************************************************************************
* Prototypes
******************************************************************************/
/*******************************************************************************
* Variables
******************************************************************************/
/*******************************************************************************
* Code
******************************************************************************/
/*!
* @brief Main function.
*/
int lwip_ping_test(void)
{
struct netif fsl_netif0;
#if defined(FSL_FEATURE_SOC_LPC_ENET_COUNT) && (FSL_FEATURE_SOC_LPC_ENET_COUNT > 0)
mem_range_t non_dma_memory[] = NON_DMA_MEMORY_ARRAY;
#endif /* FSL_FEATURE_SOC_LPC_ENET_COUNT */
ip4_addr_t fsl_netif0_ipaddr, fsl_netif0_netmask, fsl_netif0_gw;
ethernetif_config_t fsl_enet_config0 = {
.phyAddress = TEST_PHY_ADDR,
.clockName = TEST_CLOCK_NAME,
.macAddress = TEST_MAC_ADDR,
#if defined(FSL_FEATURE_SOC_LPC_ENET_COUNT) && (FSL_FEATURE_SOC_LPC_ENET_COUNT > 0)
.non_dma_memory = non_dma_memory,
#endif /* FSL_FEATURE_SOC_LPC_ENET_COUNT */
};
lw_print("lw: [%s] start ...\n", __func__);
ETH_BSP_Config();
IP4_ADDR(&fsl_netif0_ipaddr, TEST_IP_ADDR0, TEST_IP_ADDR1, TEST_IP_ADDR2, TEST_IP_ADDR3);
IP4_ADDR(&fsl_netif0_netmask, TEST_NET_MASK0, TEST_NET_MASK1, TEST_NET_MASK2, TEST_NET_MASK3);
IP4_ADDR(&fsl_netif0_gw, TEST_GW_ADDR0, TEST_GW_ADDR1, TEST_GW_ADDR2, TEST_GW_ADDR3);
lwip_init();
netif_add(&fsl_netif0, &fsl_netif0_ipaddr, &fsl_netif0_netmask, &fsl_netif0_gw, &fsl_enet_config0,
ethernetif0_init,
ethernet_input);
netif_set_default(&fsl_netif0);
netif_set_up(&fsl_netif0);
ping_init(&fsl_netif0_gw);
lw_print("\r\n************************************************\r\n");
lw_print(" PING example\r\n");
lw_print("************************************************\r\n");
lw_print(" IPv4 Address : %u.%u.%u.%u\r\n", ((u8_t *)&fsl_netif0_ipaddr)[0], ((u8_t *)&fsl_netif0_ipaddr)[1],
((u8_t *)&fsl_netif0_ipaddr)[2], ((u8_t *)&fsl_netif0_ipaddr)[3]);
lw_print(" IPv4 Subnet mask : %u.%u.%u.%u\r\n", ((u8_t *)&fsl_netif0_netmask)[0], ((u8_t *)&fsl_netif0_netmask)[1],
((u8_t *)&fsl_netif0_netmask)[2], ((u8_t *)&fsl_netif0_netmask)[3]);
lw_print(" IPv4 Gateway : %u.%u.%u.%u\r\n", ((u8_t *)&fsl_netif0_gw)[0], ((u8_t *)&fsl_netif0_gw)[1],
((u8_t *)&fsl_netif0_gw)[2], ((u8_t *)&fsl_netif0_gw)[3]);
lw_print("************************************************\r\n");
while (1)
{
/* Poll the driver, get any outstanding frames */
ethernetif_input(&fsl_netif0);
sys_check_timeouts(); /* Handle all system timeouts for all core protocols */
}
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(0),
LwPingTest, lwip_ping_test, lwip_ping_test);
#endif

418
APP_Framework/Applications/control_app/lwip_demo/ping.c

@ -0,0 +1,418 @@
/**
* @file
* Ping sender module
*
*/
/*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
*/
/**
* This is an example of a "ping" sender (with raw API and socket API).
* It can be used as a start point to maintain opened a network connection, or
* like a network "watchdog" for your device.
*
*/
#include "lwip/opt.h"
//tst by wly
#include "ip.h"
#if LWIP_RAW /* don't build if not configured for use in lwipopts.h */
#include "ping.h"
#include "lwip/mem.h"
#include "lwip/raw.h"
#include "lwip/icmp.h"
#include "lwip/netif.h"
#include "lwip/sys.h"
#include "lwip/timeouts.h"
#include "lwip/inet_chksum.h"
#include "lwip/prot/ip4.h"
#if PING_USE_SOCKETS
#include "lwip/sockets.h"
#include "lwip/inet.h"
#include <string.h>
#endif /* PING_USE_SOCKETS */
/**
* PING_DEBUG: Enable debugging for PING.
*/
#ifndef PING_DEBUG
#define PING_DEBUG LWIP_DBG_ON
#endif
/** ping receive timeout - in milliseconds */
#ifndef PING_RCV_TIMEO
#define PING_RCV_TIMEO 1000
#endif
/** ping delay - in milliseconds */
#ifndef PING_DELAY
#define PING_DELAY 3000
#endif
/** ping identifier - must fit on a u16_t */
#ifndef PING_ID
#define PING_ID 0xAFAF
#endif
/** ping additional data size to include in the packet */
#ifndef PING_DATA_SIZE
#define PING_DATA_SIZE 32
#endif
/** ping result action - no default action */
#ifndef PING_RESULT
#define PING_RESULT(ping_ok)
#endif
/* ping variables */
static const ip_addr_t* ping_target;
static u16_t ping_seq_num;
#ifdef LWIP_DEBUG
static u32_t ping_time;
#endif /* LWIP_DEBUG */
#if !PING_USE_SOCKETS
static struct raw_pcb *ping_pcb;
#endif /* PING_USE_SOCKETS */
/** Prepare a echo ICMP request */
static void
ping_prepare_echo( struct icmp_echo_hdr *iecho, u16_t len)
{
size_t i;
size_t data_len = len - sizeof(struct icmp_echo_hdr);
ICMPH_TYPE_SET(iecho, ICMP_ECHO);
ICMPH_CODE_SET(iecho, 0);
iecho->chksum = 0;
iecho->id = PING_ID;
iecho->seqno = lwip_htons(++ping_seq_num);
/* fill the additional data buffer with some data */
for(i = 0; i < data_len; i++) {
((char*)iecho)[sizeof(struct icmp_echo_hdr) + i] = (char)i;
}
iecho->chksum = inet_chksum(iecho, len);
}
#if PING_USE_SOCKETS
/* Ping using the socket ip */
static err_t
ping_send(int s, const ip_addr_t *addr)
{
int err;
struct icmp_echo_hdr *iecho;
struct sockaddr_storage to;
size_t ping_size = sizeof(struct icmp_echo_hdr) + PING_DATA_SIZE;
LWIP_ASSERT("ping_size is too big", ping_size <= 0xffff);
#if LWIP_IPV6
if(IP_IS_V6(addr) && !ip6_addr_isipv4mappedipv6(ip_2_ip6(addr))) {
/* todo: support ICMP6 echo */
return ERR_VAL;
}
#endif /* LWIP_IPV6 */
iecho = (struct icmp_echo_hdr *)mem_malloc((mem_size_t)ping_size);
if (!iecho) {
return ERR_MEM;
}
ping_prepare_echo(iecho, (u16_t)ping_size);
#if LWIP_IPV4
if(IP_IS_V4(addr)) {
struct sockaddr_in *to4 = (struct sockaddr_in*)&to;
to4->sin_len = sizeof(to4);
to4->sin_family = AF_INET;
inet_addr_from_ip4addr(&to4->sin_addr, ip_2_ip4(addr));
}
#endif /* LWIP_IPV4 */
#if LWIP_IPV6
if(IP_IS_V6(addr)) {
struct sockaddr_in6 *to6 = (struct sockaddr_in6*)&to;
to6->sin6_len = sizeof(to6);
to6->sin6_family = AF_INET6;
inet6_addr_from_ip6addr(&to6->sin6_addr, ip_2_ip6(addr));
}
#endif /* LWIP_IPV6 */
err = lwip_sendto(s, iecho, ping_size, 0, (struct sockaddr*)&to, sizeof(to));
mem_free(iecho);
return (err ? ERR_OK : ERR_VAL);
}
static void
ping_recv(int s)
{
char buf[64];
int len;
struct sockaddr_storage from;
int fromlen = sizeof(from);
// lw_print("lw: [%s] recv %d\n",__func__, fromlen);
while((len = lwip_recvfrom(s, buf, sizeof(buf), 0, (struct sockaddr*)&from, (socklen_t*)&fromlen)) > 0) {
if (len >= (int)(sizeof(struct ip_hdr)+sizeof(struct icmp_echo_hdr))) {
ip_addr_t fromaddr;
memset(&fromaddr, 0, sizeof(fromaddr));
#if LWIP_IPV4
if(from.ss_family == AF_INET) {
struct sockaddr_in *from4 = (struct sockaddr_in*)&from;
inet_addr_to_ip4addr(ip_2_ip4(&fromaddr), &from4->sin_addr);
IP_SET_TYPE_VAL(fromaddr, IPADDR_TYPE_V4);
}
#endif /* LWIP_IPV4 */
#if LWIP_IPV6
if(from.ss_family == AF_INET6) {
struct sockaddr_in6 *from6 = (struct sockaddr_in6*)&from;
inet6_addr_to_ip6addr(ip_2_ip6(&fromaddr), &from6->sin6_addr);
IP_SET_TYPE_VAL(fromaddr, IPADDR_TYPE_V6);
}
#endif /* LWIP_IPV6 */
LWIP_DEBUGF( PING_DEBUG, ("ping: recv "));
ip_addr_debug_print_val(PING_DEBUG, fromaddr);
LWIP_DEBUGF( PING_DEBUG, (" %"U32_F" ms\n", (sys_now() - ping_time)));
/* todo: support ICMP6 echo */
#if LWIP_IPV4
if (IP_IS_V4_VAL(fromaddr)) {
struct ip_hdr *iphdr;
struct icmp_echo_hdr *iecho;
iphdr = (struct ip_hdr *)buf;
iecho = (struct icmp_echo_hdr *)(buf + (IPH_HL(iphdr) * 4));
if ((iecho->id == PING_ID) && (iecho->seqno == lwip_htons(ping_seq_num))) {
/* do some ping result processing */
PING_RESULT((ICMPH_TYPE(iecho) == ICMP_ER));
return;
} else {
LWIP_DEBUGF( PING_DEBUG, ("ping: drop\n"));
}
}
#endif /* LWIP_IPV4 */
}
fromlen = sizeof(from);
}
if (len == 0) {
LWIP_DEBUGF( PING_DEBUG, ("ping: recv - %"U32_F" ms - timeout\n", (sys_now()-ping_time)));
}
/* do some ping result processing */
PING_RESULT(0);
}
static void
ping_thread(void *arg)
{
int s;
int ret;
#if LWIP_SO_SNDRCVTIMEO_NONSTANDARD
int timeout = PING_RCV_TIMEO;
#else
struct timeval timeout;
timeout.tv_sec = PING_RCV_TIMEO/1000;
timeout.tv_usec = (PING_RCV_TIMEO%1000)*1000;
#endif
LWIP_UNUSED_ARG(arg);
lw_print("lw: [%s] start...\n", __func__);
#if LWIP_IPV6
if(IP_IS_V4(ping_target) || ip6_addr_isipv4mappedipv6(ip_2_ip6(ping_target))) {
s = lwip_socket(AF_INET6, SOCK_RAW, IP_PROTO_ICMP);
} else {
s = lwip_socket(AF_INET6, SOCK_RAW, IP6_NEXTH_ICMP6);
}
#else
s = lwip_socket(AF_INET, SOCK_RAW, IP_PROTO_ICMP);
#endif
if (s < 0) {
lw_print("lw: [%s] ping failed %d!\n", __func__, s);
return;
}
lw_print("lw: [%s] ping start!\n", __func__);
ret = lwip_setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
LWIP_ASSERT("setting receive timeout failed", ret == 0);
LWIP_UNUSED_ARG(ret);
while (1) {
if (ping_send(s, ping_target) == ERR_OK) {
LWIP_DEBUGF( PING_DEBUG, ("ping: send "));
ip_addr_debug_print(PING_DEBUG, ping_target);
LWIP_DEBUGF( PING_DEBUG, ("\n"));
#ifdef LWIP_DEBUG
ping_time = sys_now();
#endif /* LWIP_DEBUG */
ping_recv(s);
} else {
LWIP_DEBUGF( PING_DEBUG, ("ping: send "));
ip_addr_debug_print(PING_DEBUG, ping_target);
LWIP_DEBUGF( PING_DEBUG, (" - error\n"));
}
sys_msleep(PING_DELAY);
}
}
#else /* PING_USE_SOCKETS */
/* Ping using the raw ip */
static u8_t
ping_recv(void *arg, struct raw_pcb *pcb, struct pbuf *p, const ip_addr_t *addr)
{
struct icmp_echo_hdr *iecho;
LWIP_UNUSED_ARG(arg);
LWIP_UNUSED_ARG(pcb);
LWIP_UNUSED_ARG(addr);
LWIP_ASSERT("p != NULL", p != NULL);
if ((p->tot_len >= (PBUF_IP_HLEN + sizeof(struct icmp_echo_hdr))) &&
pbuf_remove_header(p, PBUF_IP_HLEN) == 0) {
iecho = (struct icmp_echo_hdr *)p->payload;
if ((iecho->id == PING_ID) && (iecho->seqno == lwip_htons(ping_seq_num))) {
LWIP_DEBUGF( PING_DEBUG, ("ping: recv "));
ip_addr_debug_print(PING_DEBUG, addr);
LWIP_DEBUGF( PING_DEBUG, (" %"U32_F" ms\n", (sys_now()-ping_time)));
/* do some ping result processing */
PING_RESULT(1);
pbuf_free(p);
return 1; /* eat the packet */
}
/* not eaten, restore original packet */
/* Changed to the "_force" version because of LPC zerocopy pbufs */
pbuf_add_header_force(p, PBUF_IP_HLEN);
}
return 0; /* don't eat the packet */
}
static void
ping_send(struct raw_pcb *raw, const ip_addr_t *addr)
{
struct pbuf *p;
struct icmp_echo_hdr *iecho;
size_t ping_size = sizeof(struct icmp_echo_hdr) + PING_DATA_SIZE;
LWIP_DEBUGF( PING_DEBUG, ("ping: send "));
ip_addr_debug_print(PING_DEBUG, addr);
LWIP_DEBUGF( PING_DEBUG, ("\n"));
LWIP_ASSERT("ping_size <= 0xffff", ping_size <= 0xffff);
p = pbuf_alloc(PBUF_IP, (u16_t)ping_size, PBUF_RAM);
if (!p) {
lw_trace();
return;
}
if ((p->len == p->tot_len) && (p->next == NULL)) {
iecho = (struct icmp_echo_hdr *)p->payload;
ping_prepare_echo(iecho, (u16_t)ping_size);
raw_sendto(raw, p, addr);
#ifdef LWIP_DEBUG
ping_time = sys_now();
#endif /* LWIP_DEBUG */
}
pbuf_free(p);
// lw_print("lw: [%s] send %d\n", __func__, ping_size);
}
static void
ping_timeout(void *arg)
{
struct raw_pcb *pcb = (struct raw_pcb*)arg;
LWIP_ASSERT("ping_timeout: no pcb given!", pcb != NULL);
ping_send(pcb, ping_target);
sys_timeout(PING_DELAY, ping_timeout, pcb);
}
static void
ping_raw_init(void)
{
ping_pcb = raw_new(IP_PROTO_ICMP);
LWIP_ASSERT("ping_pcb != NULL", ping_pcb != NULL);
//tst by wly
lw_print("lw: [%s] pcb %p\n", __func__, ping_pcb);
raw_recv(ping_pcb, ping_recv, NULL);
raw_bind(ping_pcb, IP_ADDR_ANY);
sys_timeout(PING_DELAY, ping_timeout, ping_pcb);
}
void
ping_send_now(void)
{
LWIP_ASSERT("ping_pcb != NULL", ping_pcb != NULL);
ping_send(ping_pcb, ping_target);
}
#endif /* PING_USE_SOCKETS */
#define PING_THREAD_STACKSIZE 4096
#define PING_THREAD_PRIO 0
void
ping_init(const ip_addr_t* ping_addr)
{
sys_thread_t th;
ping_target = ping_addr;
#if PING_USE_SOCKETS
th = sys_thread_new("ping_thread", ping_thread, NULL, PING_THREAD_STACKSIZE, PING_THREAD_PRIO);
lw_print("lw: [%s] sys %d addr %#x\n", __func__, th, (*ping_addr).addr);
#else /* PING_USE_SOCKETS */
ping_raw_init();
#endif /* PING_USE_SOCKETS */
}
#endif /* LWIP_RAW */

19
APP_Framework/Applications/control_app/lwip_demo/ping.h

@ -0,0 +1,19 @@
#ifndef LWIP_PING_H
#define LWIP_PING_H
#include "lwip/ip_addr.h"
/**
* PING_USE_SOCKETS: Set to 1 to use sockets, otherwise the raw api is used
*/
#ifndef PING_USE_SOCKETS
#define PING_USE_SOCKETS 0//LWIP_SOCKET
#endif
void ping_init(const ip_addr_t* ping_addr);
#if !PING_USE_SOCKETS
void ping_send_now(void);
#endif /* !PING_USE_SOCKETS */
#endif /* LWIP_PING_H */

3
APP_Framework/Applications/control_app/opcua_demo/Makefile

@ -0,0 +1,3 @@
SRC_FILES :=opcua_demo.c
include $(KERNEL_ROOT)/compiler.mk

246
APP_Framework/Applications/control_app/opcua_demo/opcua_demo.c

@ -0,0 +1,246 @@
/*
* Copyright (c) 2021 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file ua_demo.c
* @brief Demo for OpcUa function
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021.11.11
*/
#include <list.h>
#include <transform.h>
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <sys/types.h>
#include <lwip/altcp.h>
#include <fsl_gpio.h>
#include <fsl_iomuxc.h>
#include "netif/ethernet.h"
#include "enet_ethernetif.h"
#include "connect_ethernet.h"
typedef unsigned int nfds_t;
#include "../../../../APP_Framework/Framework/control/plc/interoperability/opcua/open62541.h"
#define ua_print printf
#define ua_trace() printf("ua: [%s] %d pass!\n", __func__, __LINE__)
#define TCP_LOCAL_PORT 4840
/* IP address configuration. */
#define configIP_ADDR0 192
#define configIP_ADDR1 168
#define configIP_ADDR2 250
#define configIP_ADDR3 253
/* Netmask configuration. */
#define configNET_MASK0 255
#define configNET_MASK1 255
#define configNET_MASK2 255
#define configNET_MASK3 0
/* Gateway address configuration. */
#define configGW_ADDR0 192
#define configGW_ADDR1 168
#define configGW_ADDR2 250
#define configGW_ADDR3 252
/* MAC address configuration. */
#define configMAC_ADDR { 0x02, 0x12, 0x13, 0x10, 0x15, 0x11}
/* ENET PHY address. */
#define BOARD_ENET0_PHY_ADDRESS (0x02U) /* Phy address of enet port 0. */
/* Address of PHY interface. */
#define EXAMPLE_PHY_ADDRESS BOARD_ENET0_PHY_ADDRESS
/* System clock name. */
#define EXAMPLE_CLOCK_NAME kCLOCK_CoreSysClk
//#define sourceClock CLOCK_GetFreq(kCLOCK_CoreSysClk)
const char *test_uri = "opc.tcp://192.168.250.5:4840";
const char *test_cb_str = "tcp client connected\r\n";
void ua_ip_init(void)
{
struct netif fsl_netif0;
#if defined(FSL_FEATURE_SOC_LPC_ENET_COUNT) && (FSL_FEATURE_SOC_LPC_ENET_COUNT > 0)
mem_range_t non_dma_memory[] = NON_DMA_MEMORY_ARRAY;
#endif /* FSL_FEATURE_SOC_LPC_ENET_COUNT */
ip4_addr_t fsl_netif0_ipaddr, fsl_netif0_netmask, fsl_netif0_gw;
ethernetif_config_t fsl_enet_config0 = {
.phyAddress = EXAMPLE_PHY_ADDRESS,
.clockName = EXAMPLE_CLOCK_NAME,
.macAddress = configMAC_ADDR,
#if defined(FSL_FEATURE_SOC_LPC_ENET_COUNT) && (FSL_FEATURE_SOC_LPC_ENET_COUNT > 0)
.non_dma_memory = non_dma_memory,
#endif /* FSL_FEATURE_SOC_LPC_ENET_COUNT */
};
gpio_pin_config_t gpio_config = {kGPIO_DigitalOutput, 0, kGPIO_NoIntmode};
ua_print("lw: [%s] start ...\n", __func__);
IP4_ADDR(&fsl_netif0_ipaddr, configIP_ADDR0, configIP_ADDR1, configIP_ADDR2, configIP_ADDR3);
IP4_ADDR(&fsl_netif0_netmask, configNET_MASK0, configNET_MASK1, configNET_MASK2, configNET_MASK3);
IP4_ADDR(&fsl_netif0_gw, configGW_ADDR0, configGW_ADDR1, configGW_ADDR2, configGW_ADDR3);
lwip_init();
netif_add(&fsl_netif0, &fsl_netif0_ipaddr, &fsl_netif0_netmask, &fsl_netif0_gw, &fsl_enet_config0, ethernetif0_init,
ethernet_input);
netif_set_default(&fsl_netif0);
netif_set_up(&fsl_netif0);
// ping_init(&fsl_netif0_gw);
ua_print("\r\n************************************************\r\n");
ua_print(" PING example\r\n");
ua_print("************************************************\r\n");
ua_print(" IPv4 Address : %u.%u.%u.%u\r\n", ((u8_t *)&fsl_netif0_ipaddr)[0], ((u8_t *)&fsl_netif0_ipaddr)[1],
((u8_t *)&fsl_netif0_ipaddr)[2], ((u8_t *)&fsl_netif0_ipaddr)[3]);
ua_print(" IPv4 Subnet mask : %u.%u.%u.%u\r\n", ((u8_t *)&fsl_netif0_netmask)[0], ((u8_t *)&fsl_netif0_netmask)[1],
((u8_t *)&fsl_netif0_netmask)[2], ((u8_t *)&fsl_netif0_netmask)[3]);
ua_print(" IPv4 Gateway : %u.%u.%u.%u\r\n", ((u8_t *)&fsl_netif0_gw)[0], ((u8_t *)&fsl_netif0_gw)[1],
((u8_t *)&fsl_netif0_gw)[2], ((u8_t *)&fsl_netif0_gw)[3]);
ua_print("************************************************\r\n");
}
// tcp client callback
static err_t TcpClientCallback(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)
{
uint32_t i;
if (p != NULL)
{
struct pbuf *ptmp = p;
ua_print("get msg from %d:%d:%d:%d port:%d:\r\n",
*((uint8_t *)&tpcb->remote_ip.addr),
*((uint8_t *)&tpcb->remote_ip.addr + 1),
*((uint8_t *)&tpcb->remote_ip.addr + 2),
*((uint8_t *)&tpcb->remote_ip.addr + 3),
tpcb->remote_port);
while (ptmp != NULL)
{
for (i = 0; i < p->len; i++)
{
ua_print("%c", *((char *)p->payload + i));
}
ptmp = p->next;
}
ua_print("\r\n");
tcp_recved(tpcb, p->tot_len);
pbuf_free(p);
}
else if (err == ERR_OK)
{
ua_print("tcp: tcp client closed\r\n");
tcp_recved(tpcb, p->tot_len);
return tcp_close(tpcb);
}
return ERR_OK;
}
// connect callback function
static err_t TcpClientConnected(void *arg, struct tcp_pcb *tpcb, err_t err)
{
ua_print(test_cb_str);
tcp_write(tpcb, test_cb_str, strlen(test_cb_str), 0);
tcp_recv(tpcb, TcpClientCallback);
return ERR_OK;
}
void ua_set_ip(void *param)
{
struct tcp_pcb *tpcb = NULL;
err_t err;
ua_print("ua: [%s] start test\n", __func__);
ua_ip_init();
tpcb = tcp_new();
if (tpcb == NULL)
{
ua_print("ua: [%s] tcp pcb null\n", __func__);
return;
}
ua_print("ua: [%s] tcp bind port %d\n", __func__, TCP_LOCAL_PORT);
/* bind local port and ip addresss*/
err = tcp_bind(tpcb, IP_ADDR_ANY, TCP_LOCAL_PORT);
if (err != ERR_OK)
{
memp_free(MEMP_TCP_PCB, tpcb);
ua_print("ua: [%s] can not bind pcb\n", __func__);
return;
}
ua_print("ua: [%s] start tcp...\n", __func__);
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(0),
UaSetIp, ua_set_ip, ua_set_ip);
void TestUaConnect(int argc, char *argv[])
{
UA_StatusCode retval;
char ua_msg[128];
int len;
if (argc >= 1)
{
memset(ua_msg, 0, 128);
strncpy(ua_msg, argv[1], (len = strlen(argv[1])));
ua_print("ua: [%s] start\n", __func__);
}
ua_set_ip(NULL);
UA_Client *client = UA_Client_new();
if (client == NULL)
{
ua_print("ua: [%s] tcp client null\n", __func__);
return;
}
UA_ClientConfig *config = UA_Client_getConfig(client);
UA_ClientConfig_setDefault(config);
retval = UA_Client_connect(client, test_uri);
if (retval != UA_STATUSCODE_GOOD)
{
ua_print("ua: [%s] ret %x\n", __func__, retval);
UA_Client_delete(client);
return;
}
ua_print("ua: [%s] start Ua Test!\n", __func__);
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(0),
UaConnect, TestUaConnect, TestUaConnect);

6
APP_Framework/Framework/control/Kconfig

@ -1,4 +1,8 @@
menuconfig SUPPORT_CONTROL_FRAMEWORK
bool "support control framework"
default n
select TRANSFORM_LAYER_ATTRIUBUTE
select TRANSFORM_LAYER_ATTRIUBUTE
if SUPPORT_CONTROL_FRAMEWORK
source "$APP_DIR/Framework/control/plc/interoperability/Kconfig"
endif

2
APP_Framework/Framework/control/Makefile

@ -1,3 +1,3 @@
SRC_DIR :=
SRC_DIR := shared plc
include $(KERNEL_ROOT)/compiler.mk

4
APP_Framework/Framework/control/plc/Makefile

@ -0,0 +1,4 @@
SRC_DIR := shared interoperability
include $(KERNEL_ROOT)/compiler.mk

5
APP_Framework/Framework/control/plc/interoperability/Kconfig

@ -0,0 +1,5 @@
menuconfig USING_CONTROL_PLC_OPCUA
bool "PLC support OPCUA"
default y

9
APP_Framework/Framework/control/plc/interoperability/Makefile

@ -0,0 +1,9 @@
SRC_DIR :=
ifeq ($(CONFIG_USING_CONTROL_PLC_OPCUA), y)
SRC_DIR += opcua
endif
SRC_FILES += interoperability.c
include $(KERNEL_ROOT)/compiler.mk

30
APP_Framework/Framework/control/plc/interoperability/interoperability.c

@ -0,0 +1,30 @@
/*
* Copyright (c) 2021 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
void ctrl_interop_init(void)
{
}
void ctrl_interop_connect(void)
{
}
void ctrl_interop_enable(void)
{
}
void ctrl_interop_disable(void)
{
}

0
APP_Framework/Framework/control/plc/interoperability/opcua/Kconfig

3
APP_Framework/Framework/control/plc/interoperability/opcua/Makefile

@ -0,0 +1,3 @@
SRC_FILES := ua_data.c open62541.c ua_client.c ua_server.c
include $(KERNEL_ROOT)/compiler.mk

71784
APP_Framework/Framework/control/plc/interoperability/opcua/open62541.c

File diff suppressed because it is too large

31298
APP_Framework/Framework/control/plc/interoperability/opcua/open62541.h

File diff suppressed because it is too large

342
APP_Framework/Framework/control/plc/interoperability/opcua/ua_client.c

@ -0,0 +1,342 @@
/*
* Copyright (c) 2021 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#include "open62541.h"
#include <stdlib.h>
#define OPC_SERVER "opc.tcp://192.168.250.5:4840"
#define ua_print printf
#ifdef UA_ENABLE_SUBSCRIPTIONS
static void handler_TheAnswerChanged(UA_Client *client, UA_UInt32 subId, void *subContext,
UA_UInt32 monId, void *monContext, UA_DataValue *value)
{
ua_print("The Answer has changed!\n");
}
#endif
static UA_StatusCode nodeIter(UA_NodeId childId, UA_Boolean isInverse, UA_NodeId referenceTypeId, void *handle)
{
if(isInverse)
{
return UA_STATUSCODE_GOOD;
}
UA_NodeId *parent = (UA_NodeId *)handle;
ua_print("%d, %d --- %d ---> NodeId %d, %d\n",
parent->namespaceIndex, parent->identifier.numeric,
referenceTypeId.identifier.numeric, childId.namespaceIndex,
childId.identifier.numeric);
return UA_STATUSCODE_GOOD;
}
int ua_get_points(UA_Client *client)
{
/* Listing endpoints */
UA_EndpointDescription* endpointArray = NULL;
size_t endpointArraySize = 0;
UA_StatusCode retval = UA_Client_getEndpoints(client, OPC_SERVER,
&endpointArraySize, &endpointArray);
if(retval != UA_STATUSCODE_GOOD)
{
UA_Array_delete(endpointArray, endpointArraySize, &UA_TYPES[UA_TYPES_ENDPOINTDESCRIPTION]);
return EXIT_FAILURE;
}
ua_print("%i endpoints found\n", (int)endpointArraySize);
for(size_t i=0;i<endpointArraySize;i++)
{
ua_print("URL of endpoint %i is %.*s\n", (int)i,
(int)endpointArray[i].endpointUrl.length,
endpointArray[i].endpointUrl.data);
}
UA_Array_delete(endpointArray,endpointArraySize, &UA_TYPES[UA_TYPES_ENDPOINTDESCRIPTION]);
return EXIT_SUCCESS;
}
void ua_browser_objects(UA_Client *client)
{
/* Browse some objects */
ua_print("Browsing nodes in objects folder:\n");
UA_BrowseRequest bReq;
UA_BrowseRequest_init(&bReq);
bReq.requestedMaxReferencesPerNode = 0;
bReq.nodesToBrowse = UA_BrowseDescription_new();
bReq.nodesToBrowseSize = 1;
bReq.nodesToBrowse[0].nodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER); /* browse objects folder */
bReq.nodesToBrowse[0].resultMask = UA_BROWSERESULTMASK_ALL; /* return everything */
UA_BrowseResponse bResp = UA_Client_Service_browse(client, bReq);
ua_print("%-9s %-16s %-16s %-16s\n", "NAMESPACE", "NODEID", "BROWSE NAME", "DISPLAY NAME");
for(size_t i = 0; i < bResp.resultsSize; ++i) {
for(size_t j = 0; j < bResp.results[i].referencesSize; ++j) {
UA_ReferenceDescription *ref = &(bResp.results[i].references[j]);
if(ref->nodeId.nodeId.identifierType == UA_NODEIDTYPE_NUMERIC) {
ua_print("%-9d %-16d %-16.*s %-16.*s\n", ref->nodeId.nodeId.namespaceIndex,
ref->nodeId.nodeId.identifier.numeric, (int)ref->browseName.name.length,
ref->browseName.name.data, (int)ref->displayName.text.length,
ref->displayName.text.data);
} else if(ref->nodeId.nodeId.identifierType == UA_NODEIDTYPE_STRING) {
ua_print("%-9d %-16.*s %-16.*s %-16.*s\n", ref->nodeId.nodeId.namespaceIndex,
(int)ref->nodeId.nodeId.identifier.string.length,
ref->nodeId.nodeId.identifier.string.data,
(int)ref->browseName.name.length, ref->browseName.name.data,
(int)ref->displayName.text.length, ref->displayName.text.data);
}
/* TODO: distinguish further types */
}
}
UA_BrowseRequest_clear(&bReq);
UA_BrowseResponse_clear(&bResp);
}
void ua_browser_nodes(UA_Client *client)
{
/* Same thing, this time using the node iterator... */
UA_NodeId *parent = UA_NodeId_new();
*parent = UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER);
UA_Client_forEachChildNodeCall(client, UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),
nodeIter, (void *) parent);
UA_NodeId_delete(parent);
}
UA_UInt32 ua_start_sub(UA_Client *client)
{
/* Create a subscription */
UA_CreateSubscriptionRequest request = UA_CreateSubscriptionRequest_default();
UA_CreateSubscriptionResponse response = UA_Client_Subscriptions_create(client, request,
NULL, NULL, NULL);
UA_UInt32 subId = response.subscriptionId;
if(response.responseHeader.serviceResult == UA_STATUSCODE_GOOD)
ua_print("Create subscription succeeded, id %u\n", subId);
UA_MonitoredItemCreateRequest monRequest =
UA_MonitoredItemCreateRequest_default(UA_NODEID_STRING(1, "the.answer"));
UA_MonitoredItemCreateResult monResponse =
UA_Client_MonitoredItems_createDataChange(client, response.subscriptionId,
UA_TIMESTAMPSTORETURN_BOTH,
monRequest, NULL, handler_TheAnswerChanged, NULL);
if(monResponse.statusCode == UA_STATUSCODE_GOOD)
ua_print("Monitoring 'the.answer', id %u\n", monResponse.monitoredItemId);
/* The first publish request should return the initial value of the variable */
UA_Client_run_iterate(client, 1000);
return subId;
}
void ua_read_attr(UA_Client *client)
{
/* Read attribute */
UA_Int32 value = 0;
ua_print("\nReading the value of node (1, \"the.answer\"):\n");
UA_Variant *val = UA_Variant_new();
UA_StatusCode retval = UA_Client_readValueAttribute(client, UA_NODEID_STRING(1, "the.answer"), val);
if(retval == UA_STATUSCODE_GOOD && UA_Variant_isScalar(val) &&
val->type == &UA_TYPES[UA_TYPES_INT32]) {
value = *(UA_Int32*)val->data;
ua_print("the value is: %i\n", value);
}
UA_Variant_delete(val);
/* Write node attribute */
value++;
ua_print("\nWriting a value of node (1, \"the.answer\"):\n");
UA_WriteRequest wReq;
UA_WriteRequest_init(&wReq);
wReq.nodesToWrite = UA_WriteValue_new();
wReq.nodesToWriteSize = 1;
wReq.nodesToWrite[0].nodeId = UA_NODEID_STRING_ALLOC(1, "the.answer");
wReq.nodesToWrite[0].attributeId = UA_ATTRIBUTEID_VALUE;
wReq.nodesToWrite[0].value.hasValue = true;
wReq.nodesToWrite[0].value.value.type = &UA_TYPES[UA_TYPES_INT32];
wReq.nodesToWrite[0].value.value.storageType = UA_VARIANT_DATA_NODELETE; /* do not free the integer on deletion */
wReq.nodesToWrite[0].value.value.data = &value;
UA_WriteResponse wResp = UA_Client_Service_write(client, wReq);
if(wResp.responseHeader.serviceResult == UA_STATUSCODE_GOOD)
ua_print("the new value is: %i\n", value);
UA_WriteRequest_clear(&wReq);
UA_WriteResponse_clear(&wResp);
/* Write node attribute (using the highlevel API) */
value++;
UA_Variant *myVariant = UA_Variant_new();
UA_Variant_setScalarCopy(myVariant, &value, &UA_TYPES[UA_TYPES_INT32]);
UA_Client_writeValueAttribute(client, UA_NODEID_STRING(1, "the.answer"), myVariant);
UA_Variant_delete(myVariant);
}
void ua_call_remote(UA_Client *client)
{
/* Call a remote method */
UA_Variant input;
UA_String argString = UA_STRING("Hello Server");
UA_Variant_init(&input);
UA_Variant_setScalarCopy(&input, &argString, &UA_TYPES[UA_TYPES_STRING]);
size_t outputSize;
UA_Variant *output;
UA_StatusCode retval = UA_Client_call(client, UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),
UA_NODEID_NUMERIC(1, 62541), 1, &input, &outputSize, &output);
if(retval == UA_STATUSCODE_GOOD) {
ua_print("Method call was successful, and %lu returned values available.\n",
(unsigned long)outputSize);
UA_Array_delete(output, outputSize, &UA_TYPES[UA_TYPES_VARIANT]);
} else {
ua_print("Method call was unsuccessful, and %x returned values available.\n", retval);
}
UA_Variant_clear(&input);
}
void ua_add_nodes(UA_Client *client)
{
/* Add new nodes*/
/* New ReferenceType */
UA_NodeId ref_id;
UA_ReferenceTypeAttributes ref_attr = UA_ReferenceTypeAttributes_default;
ref_attr.displayName = UA_LOCALIZEDTEXT("en-US", "NewReference");
ref_attr.description = UA_LOCALIZEDTEXT("en-US", "References something that might or might not exist");
ref_attr.inverseName = UA_LOCALIZEDTEXT("en-US", "IsNewlyReferencedBy");
UA_StatusCode retval = UA_Client_addReferenceTypeNode(client,
UA_NODEID_NUMERIC(1, 12133),
UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES),
UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE),
UA_QUALIFIEDNAME(1, "NewReference"),
ref_attr, &ref_id);
if(retval == UA_STATUSCODE_GOOD )
ua_print("Created 'NewReference' with numeric NodeID %u\n", ref_id.identifier.numeric);
/* New ObjectType */
UA_NodeId objt_id;
UA_ObjectTypeAttributes objt_attr = UA_ObjectTypeAttributes_default;
objt_attr.displayName = UA_LOCALIZEDTEXT("en-US", "TheNewObjectType");
objt_attr.description = UA_LOCALIZEDTEXT("en-US", "Put innovative description here");
retval = UA_Client_addObjectTypeNode(client,
UA_NODEID_NUMERIC(1, 12134),
UA_NODEID_NUMERIC(0, UA_NS0ID_BASEOBJECTTYPE),
UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE),
UA_QUALIFIEDNAME(1, "NewObjectType"),
objt_attr, &objt_id);
if(retval == UA_STATUSCODE_GOOD)
ua_print("Created 'NewObjectType' with numeric NodeID %u\n", objt_id.identifier.numeric);
/* New Object */
UA_NodeId obj_id;
UA_ObjectAttributes obj_attr = UA_ObjectAttributes_default;
obj_attr.displayName = UA_LOCALIZEDTEXT("en-US", "TheNewGreatNode");
obj_attr.description = UA_LOCALIZEDTEXT("de-DE", "Hier koennte Ihre Webung stehen!");
retval = UA_Client_addObjectNode(client,
UA_NODEID_NUMERIC(1, 0),
UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),
UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES),
UA_QUALIFIEDNAME(1, "TheGreatNode"),
UA_NODEID_NUMERIC(1, 12134),
obj_attr, &obj_id);
if(retval == UA_STATUSCODE_GOOD )
ua_print("Created 'NewObject' with numeric NodeID %u\n", obj_id.identifier.numeric);
/* New Integer Variable */
UA_NodeId var_id;
UA_VariableAttributes var_attr = UA_VariableAttributes_default;
var_attr.displayName = UA_LOCALIZEDTEXT("en-US", "TheNewVariableNode");
var_attr.description =
UA_LOCALIZEDTEXT("en-US", "This integer is just amazing - it has digits and everything.");
UA_Int32 int_value = 1234;
/* This does not copy the value */
UA_Variant_setScalar(&var_attr.value, &int_value, &UA_TYPES[UA_TYPES_INT32]);
var_attr.dataType = UA_TYPES[UA_TYPES_INT32].typeId;
retval = UA_Client_addVariableNode(client,
UA_NODEID_NUMERIC(1, 0), // Assign new/random NodeID
UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),
UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES),
UA_QUALIFIEDNAME(0, "VariableNode"),
UA_NODEID_NULL, // no variable type
var_attr, &var_id);
if(retval == UA_STATUSCODE_GOOD )
ua_print("Created 'NewVariable' with numeric NodeID %u\n", var_id.identifier.numeric);
}
int ua_run_test(UA_Client *client)
{
UA_StatusCode retval;
/* Listing endpoints */
retval = ua_get_points(client);
if(retval != UA_STATUSCODE_GOOD) {
UA_Client_delete(client);
return EXIT_FAILURE;
}
/* Connect to a server */
/* anonymous connect would be: retval = UA_Client_connect(client, "opc.tcp://localhost:4840"); */
retval = UA_Client_connect(client, OPC_SERVER);
if(retval != UA_STATUSCODE_GOOD) {
UA_Client_delete(client);
return EXIT_FAILURE;
}
ua_browser_objects(client);
/* Same thing, this time using the node iterator... */
ua_browser_nodes(client);
#ifdef UA_ENABLE_SUBSCRIPTIONS
UA_Int32 subId = ua_start_sub(client);
#endif
ua_read_attr(client);
#ifdef UA_ENABLE_SUBSCRIPTIONS
/* Take another look at the.answer */
UA_Client_run_iterate(client, 100);
/* Delete the subscription */
if(UA_Client_Subscriptions_deleteSingle(client, subId) == UA_STATUSCODE_GOOD)
ua_print("Subscription removed\n");
#endif
#ifdef UA_ENABLE_METHODCALLS
ua_call_remote(client);
#endif
#ifdef UA_ENABLE_NODEMANAGEMENT
ua_add_nodes(client);
#endif
return EXIT_SUCCESS;
}
void ua_read_time(UA_Client *client)
{
/* Read the value attribute of the node. UA_Client_readValueAttribute is a
* wrapper for the raw read service available as UA_Client_Service_read. */
UA_Variant value; /* Variants can hold scalar values and arrays of any type */
UA_Variant_init(&value);
/* NodeId of the variable holding the current time */
const UA_NodeId nodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_CURRENTTIME);
UA_StatusCode retval = UA_Client_readValueAttribute(client, nodeId, &value);
if(retval == UA_STATUSCODE_GOOD && UA_Variant_hasScalarType(&value, &UA_TYPES[UA_TYPES_DATETIME]))
{
UA_DateTime raw_date = *(UA_DateTime *) value.data;
UA_DateTimeStruct dts = UA_DateTime_toStruct(raw_date);
UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "date is: %u-%u-%u %u:%u:%u.%03u\n",
dts.day, dts.month, dts.year, dts.hour, dts.min, dts.sec, dts.milliSec);
}
/* Clean up */
UA_Variant_clear(&value);
}

201
APP_Framework/Framework/control/plc/interoperability/opcua/ua_data.c

@ -0,0 +1,201 @@
#include "open62541.h"
/* Opc.Ua - ns=0;i=7617 */
const UA_Byte variablenode_ns_0_i_7617_variant_DataContents_byteArray[177218] = {60, 111, 112, 99, 58, 84, 121, 112, 101, 68, 105, 99, 116, 105, 111, 110, 97, 114, 121, 13, 10, 32, 32, 120, 109, 108, 110, 115, 58, 111, 112, 99, 61, 34, 104, 116, 116, 112, 58, 47, 47, 111, 112, 99, 102, 111, 117, 110, 100, 97, 116, 105, 111, 110, 46, 111, 114, 103, 47, 66, 105, 110, 97, 114, 121, 83, 99, 104, 101, 109, 97, 47, 34, 13, 10, 32, 32, 120, 109, 108, 110, 115, 58, 120, 115, 105, 61, 34, 104, 116, 116, 112, 58, 47, 47, 119, 119, 119, 46, 119, 51, 46, 111, 114, 103, 47, 50, 48, 48, 49, 47, 88, 77, 76, 83, 99, 104, 101, 109, 97, 45, 105, 110, 115, 116, 97, 110, 99, 101, 34, 13, 10, 32, 32, 120, 109, 108, 110, 115, 58, 117, 97, 61, 34, 104, 116, 116, 112, 58, 47, 47, 111, 112, 99, 102, 111, 117, 110, 100, 97, 116, 105, 111, 110, 46, 111, 114, 103, 47, 85, 65, 47, 34, 13, 10, 32, 32, 120, 109, 108, 110, 115, 58, 116, 110, 115, 61, 34, 104, 116, 116, 112, 58, 47, 47, 111, 112, 99, 102, 111, 117, 110, 100, 97, 116, 105, 111, 110, 46, 111, 114, 103, 47, 85, 65, 47, 34, 13, 10, 32, 32, 68, 101, 102, 97, 117, 108, 116, 66, 121, 116, 101, 79, 114, 100, 101, 114, 61, 34, 76, 105, 116, 116, 108, 101, 69, 110, 100, 105, 97, 110, 34, 13, 10, 32, 32, 84, 97, 114, 103, 101, 116, 78, 97, 109, 101, 115, 112, 97, 99, 101, 61, 34, 104, 116, 116, 112, 58, 47, 47, 111, 112, 99, 102, 111, 117, 110, 100, 97, 116, 105, 111, 110, 46, 111, 114, 103, 47, 85, 65, 47, 34, 13, 10, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 73, 109, 112, 111, 114, 116, 32, 78, 97, 109, 101, 115, 112, 97, 99, 101, 61, 34, 104, 116, 116, 112, 58, 47, 47, 111, 112, 99, 102, 111, 117, 110, 100, 97, 116, 105, 111, 110, 46, 111, 114, 103, 47, 66, 105, 110, 97, 114, 121, 83, 99, 104, 101, 109, 97, 47, 34, 32, 47, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 88, 109, 108, 69, 108, 101, 109, 101, 110, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 68, 111, 99, 117, 109, 101, 110, 116, 97, 116, 105, 111, 110, 62, 65, 110, 32, 88, 77, 76, 32, 101, 108, 101, 109, 101, 110, 116, 32, 101, 110, 99, 111, 100, 101, 100, 32, 97, 115, 32, 97, 32, 85, 84, 70, 45, 56, 32, 115, 116, 114, 105, 110, 103, 46, 60, 47, 111, 112, 99, 58, 68, 111, 99, 117, 109, 101, 110, 116, 97, 116, 105, 111, 110, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 76, 101, 110, 103, 116, 104, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 86, 97, 108, 117, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 67, 104, 97, 114, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 76, 101, 110, 103, 116, 104, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 73, 100, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 54, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 68, 111, 99, 117, 109, 101, 110, 116, 97, 116, 105, 111, 110, 62, 84, 104, 101, 32, 112, 111, 115, 115, 105, 98, 108, 101, 32, 101, 110, 99, 111, 100, 105, 110, 103, 115, 32, 102, 111, 114, 32, 97, 32, 78, 111, 100, 101, 73, 100, 32, 118, 97, 108, 117, 101, 46, 60, 47, 111, 112, 99, 58, 68, 111, 99, 117, 109, 101, 110, 116, 97, 116, 105, 111, 110, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 84, 119, 111, 66, 121, 116, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117,
101, 32, 78, 97, 109, 101, 61, 34, 70, 111, 117, 114, 66, 121, 116, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 78, 117, 109, 101, 114, 105, 99, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 83, 116, 114, 105, 110, 103, 34, 32, 86, 97, 108, 117, 101, 61, 34, 51, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 71, 117, 105, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103, 34, 32, 86, 97, 108, 117, 101, 61, 34, 53, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 84, 119, 111, 66, 121, 116, 101, 78, 111, 100, 101, 73, 100, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 100, 101, 110, 116, 105, 102, 105, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 70, 111, 117, 114, 66, 121, 116, 101, 78, 111, 100, 101, 73, 100, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 97, 109, 101, 115, 112, 97, 99, 101, 73, 110, 100, 101, 120, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 100, 101, 110, 116, 105, 102, 105, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 49, 54, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 78, 117, 109, 101, 114, 105, 99, 78, 111, 100, 101, 73, 100, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 97, 109, 101, 115, 112, 97, 99, 101, 73, 110, 100, 101, 120, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 49, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 100, 101, 110, 116, 105, 102, 105, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 83, 116, 114, 105, 110, 103, 78, 111, 100, 101, 73, 100, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 97, 109, 101, 115, 112, 97, 99, 101, 73, 110, 100, 101, 120, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 49, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34
, 73, 100, 101, 110, 116, 105, 102, 105, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 67, 104, 97, 114, 65, 114, 114, 97, 121, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 71, 117, 105, 100, 78, 111, 100, 101, 73, 100, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 97, 109, 101, 115, 112, 97, 99, 101, 73, 110, 100, 101, 120, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 49, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 100, 101, 110, 116, 105, 102, 105, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 71, 117, 105, 100, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103, 78, 111, 100, 101, 73, 100, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 97, 109, 101, 115, 112, 97, 99, 101, 73, 110, 100, 101, 120, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 49, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 100, 101, 110, 116, 105, 102, 105, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 73, 100, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 68, 111, 99, 117, 109, 101, 110, 116, 97, 116, 105, 111, 110, 62, 65, 110, 32, 105, 100, 101, 110, 116, 105, 102, 105, 101, 114, 32, 102, 111, 114, 32, 97, 32, 110, 111, 100, 101, 32, 105, 110, 32, 97, 32, 85, 65, 32, 115, 101, 114, 118, 101, 114, 32, 97, 100, 100, 114, 101, 115, 115, 32, 115, 112, 97, 99, 101, 46, 60, 47, 111, 112, 99, 58, 68, 111, 99, 117, 109, 101, 110, 116, 97, 116, 105, 111, 110, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 73, 100, 84, 121, 112, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 101, 114, 118, 101, 100, 49, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 105, 116, 34, 32, 76, 101, 110, 103, 116, 104, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 119, 111, 66, 121, 116, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 84, 119, 111, 66, 121, 116, 101, 78, 111, 100, 101, 73, 100, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 100, 101, 73, 100, 84, 121, 112, 101, 34, 32, 83, 119, 105, 116, 99, 104, 86, 97, 108, 117, 101, 61, 34, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 70, 111, 117, 114, 66, 121, 116, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 70, 111, 117, 114, 66, 121, 116, 101, 78, 111, 100, 101, 73, 100, 34, 32, 83, 119, 105, 116, 99,