Trend(차트) 객체와 히스토리 Popup Trend(팝업 차트) 사용방법


본 강좌에서는 Trend(이하 차트)객체의 속성 및 사용방법에 대하여 설명합니다. 주의사항은 사용방법에 대해 설명하면서 알려드리고 본문 마지막에 표로 정리해 놓겠습니다.

enuSpace 학생용 버젼 다운로드 http://enuspace.tistory.com/entry/enuSpace-for-Mars-2017


Lesson6 project sample: lesson6.zip


enuspace for mars에서 차트의 사용법은 크게 3가지가 있습니다. 본 튜토리얼에서는 3가지와 팝업 차트까지 설명하도록 하겠습니다. 

1. 정적 데이터를 이용한 차트 객체 표현

2. 동적 데이터를 이용한 차트 객체 표현

3. 차트 객체를 Logic객체로 만들어서 사용하기

enuspace for mars에서 차트는 기본적으로 실시간 차트입니다. 이를 라인 차트로 변경하려면 몇가지 설정을 해줘야 합니다.

설정법은 정적 차트 설명 하는 부분에서 알려드리도록 하겠습니다.


우선 차트를 그리기 위한 프로젝트를 하나 생성합니다.

프로젝트 생성은 프로젝트 만들기 튜토리얼을 참조하시길 바랍니다.

프로젝트 생성이 완료 되었다면 Project Explorer에서 Picture폴더에 trend라는 svg파일을 하나 생성합니다.


그리고 리본메뉴에서 차트(Home->Chart)를 선택하고 에디트화면에 생성합니다.


위 화면이 차트를 처음 생성했을 때 나타나는 화면입니다.

여기까지 하셨으면 차트를 사용하기 위한 기본작업이 완료되었습니다.

차트와 차트의 컴포넌트 속성은 다음과 같습니다.


1. 정적으로 차트 사용하기

정적 차트(라인 차트)로 사용하기 위해서 몇가지 속성을 변경해야 합니다. 우선 위에서 생성한 차트를 선택하고 오른쪽에 속성창을 살펴봅니다.

클릭하시면 원본크기로 볼 수 있습니다.

위의 속성창에서 아래 세가지 속성을 변경해줍니다.

trend-flow = off

xview-max = 300

auto-scale = off

속성을 변경 했다면 아래와 같은 그림이 나옵니다.

이제 마우스로 차트를 선택 합니다. 선택하면 상단에 리본메뉴가 아래와 같이 바뀌어 있는것을 볼 수 있습니다. 

리본메뉴에 대해 잠깐 설명 하자면 Add Chart Element는 차트안에 있는 컴포넌트들(범례, 제목, 그래프, x축, y축)의 visible 속성을 뜻합니다.
Drawing 카테고리에 있는 메뉴들은 모두 차트 배경에 관한 속성입니다. 
Add Data항목은 차트의 series를 설정 하는 곳으로 series를 추가, 삭제, 속성 변경 등을 할 수 있습니다.

우리는 series를 추가해야 하니  Add Data를 선택 합니다.

Add Data항목을 선택 했을 때 나오는 창입니다.

위 창에서 Add 버튼을 클릭하여 series를 하나 추가합니다. 그리고 추가된 series를 선택하여 오른쪽에 series에 대한 속성을 띄웁니다.

series에 관한 속성은 다음과 같습니다.


정적 데이터의 데이터 포맷은 x,y x,y 입니다. 예) 50,300 100,250 150,400 200,150 250,500

위의 예를 series2의 data속성에 넣으면 다음과 같은 화면이 나옵니다.

현재 정적 차트에서 사용할 수 있는 타입은 line(선)과 scatter(점) 차트입니다. 그리고 두가지 타입은 하나의 차트에 나타낼 수 있습니다.

2. 동적 차트 사용하기

동적 차트를 사용하기 위해서 우선 값이 변하는 지역변수를 만들어 보겠습니다.

Project Explorer에서 picture폴더에 파일을 하나 더 생성합니다.

생성된 picture파일 화면에서 배경을 클릭하시고 오른쪽 속성창을 확인합니다. 속성창의 윗 부분에 4개의 아이콘이 있는 것을 확인할 수 있습니다. 이 중에서 V모양의 아이콘을 클릭합니다.

그러면 아래와 같은 창이 나옵니다.

여기서 picture파일의 지역변수를 생성할 수 있습니다. 생성 방법은 다음과 같습니다.

1) New라고 표시된 속성에서 드롭다운 메뉴의 <Add Variable>항목을 선택한다.

2) 변수 생성창에서 변수의 타입(필수), 이름(필수), 시작 값(필수), 설명(선택)을 입력하고 Accept버튼을 클릭합니다.


생성 완료된 화면

변수가 생성 되었다면 변수 값을 속성창의 4개 아이콘중 번개 모양의 아이콘을 선택하여 아래와 같은 창을 띄웁니다.

 위의 창에서 Script Type의 type속성을 text/javascript로 변경하고, ontaskview항목을 추가해줍니다.

스크립트 편집 창이 뜨면 다음과 같이 입력합니다.

(생성했던 변수이름) = Math.floor(Math.random() * 500);

입력을 완료하고 Compile 버튼이나 Accept버튼을 클릭하여 스크립트를 등록 하여 줍니다.

여기까지 완료하셨으면 값이 변화 하는지 확인해봅니다.

이제 picture화면에 차트를 새로 생성합니다. 차트가 생성되면 상단 리본메뉴의 Add Data항목을 열어 줍니다.

series1의 속성에서 variable 속성에 위에서 생성한 변수의 이름을 넣어 줍니다. (※주의 : 변수의 이름이 틀리면 값이 들어오지 않거나 원하는 변수의 값이 들어오지 않을 수 있습니다.)

여기까지 완료하면 상단 리본메뉴에서 Home->Run을 클릭하여 스크립트를 실행하여 줍니다. 차트의 그래프가 그려지는지 확인합니다.

그래프가 너무 촘촘히 나온다면 차트의 duration값을 60 또는 120으로 설정하시면 됩니다.

3. 차트 객체를 Logic객체로 만들어서 사용하기

Logic 파일 생성과 Logic객체 이용방법은 LOGIC 프로그래밍, HMI라이브러리 인터페이스 방법에서 확인 하시기 바랍니다.

우선 Project Explorer에서 Logic라이브러리 파일을 생성하고, Logic Node를 생성합니다.

시작과정을 모두 완료한 상태

먼저 리본메뉴의 Home->Connection Pin을 생성합니다. Pin의 속성을 다음과 같이 설정합니다.

name = input
var-type = double

설정이 완료되면 차트를 생성하여 속성을 변경해 줍니다.

title-visible = hidden
legend-visible = hidden
xaxis-visible = hidden
yaxis-visible = hidden
fill-opacity = 0
duration = 30
auto-scale = off

위와 같이 모두 변경 하였다면 차트의 크기를 줄여줍니다(줄이지 않으셔도 무방합니다.). 대략 밑의 그림 정도로 줄여 주시면 됩니다.

이제 차트를 선택클릭하고 리본메뉴의 Add Data항목을 클릭하여 series속성변경 창을 열고 속성을 다음과같이 변경합니다.

variable = pin의 이름(name속성)

위 과정을 모두 완료 한뒤 라이브러리를 저장해 줍니다.

2번에서 만들었던 picture를 열어줍니다.

여기에 방금 만든 Logic차트를 생성하여 줍니다.

생성이 완료되면 Logic차트에 ID값을 입력하여 줍니다. 입력이 완료 되면 배경을 클릭하고 스크립트를 편집합니다.

위 과정이 모두 완료 되면 리본 메뉴의 Run을 눌러 동작하는지 확인합니다.


■ 팝업 차트 사용하기

팝업 차트를 사용하기 위해서는 두가지 방법이 있습니다.

1. DB에 등록된 변수를 이용하여 팝업 차트로 보기

2. 현재 생성되어 있는 Logic객체의 데이터를 이용하여 팝업차트 이용하기

3. Logic객체의 데이터를 모아서 팝업차트 만들기

주의 할 점은 2번 방법의 경우 Logic객체에 Pin객체나 지역변수가 생성되어 있어야 합니다.

3번 방법은 여러개의 데이터를 한데 묶어서 볼 수 있다는 장점이 있습니다.


1. DB에 등록된 변수를 이용하기

우선 DB에 변수를 등록 해야합니다. 위에서 우리가 만들어놓은 지역변수를 등록하여 팝업차트를 만들어 봅시다.

먼저 리본메뉴의 Data/Communcation탭으로 이동합니다. 그리고 DB Show라는 버튼을 클릭합니다.

DB TABLE 다이얼로그가 나타나면 상단의 DB그림에 G가 써져있는 버튼을 클릭합니다. 그 뒤 나타나는 창의 내용은
"해당 버튼을 누르고 계속 진행하면 기존에 생성되어 있던 데이터들이 모두 지워집니다. 그리고 글로벌 변수와 로직 객체의 변수들을 데이터 베이스에 재생성합니다. 계속하시겠습니까?" 라는 내용입니다.


여러분은 처음 생성하는 것일테니 아마도 전부 비어있을 겁니다. 그러므로 걱정하지 마시고 예를 눌러주시면 됩니다.

지금까지 제대로 따라오셨다면 아래와 같은 화면이 나타납니다. DB TABLE창을 닫지 않고, 리본메뉴에서 Run버튼을 눌러 변수의 값을 변화 시켜 줍니다.

DB TABLE창에서 팝업차트에서 보고 싶은 변수를 오른쪽 클릭하거나 'Ctrl+클릭' 또는 'Shift+클릭' 또는 '드래그'로 다중선택 하여 오른쪽위의 버튼을 클릭합니다.

생성된 팝업 차트를 확인합니다.


2. 현재 생성되어 있는 Logic객체의 데이터를 이용하여 팝업차트 이용하기

다시 picture 화면으로 돌아가서 Logic차트를 더블 클릭합니다.


아래와 같은 창이 나타나면 


팝업 차트로 보고싶은 변수를 마우스 오른클릭하여 팝업 차트를 실행합니다.

3. Logic객체의 데이터를 모아서 팝업차트 만들기

데이터를 한데 모아 사용하기 위해서 테이블 기능을 이용합니다. 리본메뉴의 Presentation->New Table버튼을 클릭합니다.

위와 같은 창이 나오면 Logic차트를 더블 클릭하여 아래와 같은 창을 다시 엽니다.

Table 창과 Logic변수 창이 모두 띄워져 있으면 Logic변수 창의 변수를 마우스 오른쪽 클릭하여 Add Monitor Paramiter를 선택합니다.

그리고 Table 창에 해당 변수가 추가되었는지 확인합니다.
※변수는 하나의 객체에서 여러 개를 추가할 수 있고, 다른 Logic객체에서도 추가할 수 있습니다.

여기서 팝업 차트를 띄우기 위해서 변수의 왼쪽에 체크박스를 체크 해줍니다.
※선택해야할 변수가 여러개라면 모두 체크해줍니다.

이후 Show Trend 버튼을 클릭합니다. (그리고 Run상태가 아닐경우 Run버튼을 클릭해줍니다.)

팝업 차트가 정상적으로 돌아가는지 확인합니다.


Web 연동 및 사용방법


본 강좌에서는 enuSpace를 이용하여 웹 브라우져에 화면 디스플레이 및 데이터 인터페이스를 구성하는 방법에 대하여 설명합니다.

enuSpace for mars 다운로드 : http://enuspace.tistory.com/entry/enuSpace-for-Mars-2017


enuSpace는 javascript와 lua script를 제공합니다. 웹 브라우져에서 동적인 현시를 위해서 javascript로 제작합니다.

enuSpace의 내부 구조와 웹 브라우져 랜더러간의 인터페이스 구조는 아래그림과 같습니다.



enuSpace에서 task scheduler는 lua 스크립트로 구현된 ontask()함수를 설정된 주기에 맞추어 호출되어 연산을 수행합니다. 또한, 뷰어가 드로잉시에 호출되는 ontaskview()함수는 루아스크립트와 자바스크립트 모두 이용할 수 있습니다. 웹 브라우져에서 랜더러의 함수 호출시에는 자바스크립트로 적용된 ontaskview()함수만 적용됩니다. 


웹 브라우져는 첫 기동시 서버측에 그래픽 리소스 svg 파일을 요청하며 관련 데이터를 연동합니다. 웹 브라우져는 내부 랜더러에서 서버 사이드에서 가져온 데이터와 ontaskview()함수를 호출하여 자신의 화면을 갱신합니다. 특정값을 제어하기 위해서 SetTagValue() 함수를 호출하여 서버사이드의 값을 제어합니다.  


enuSpace introduce의 설명


enuSpace for mars의 최신 버젼을 다운로드 하시면, 샘플 프로젝트 introduce를 오픈합니다. 


리본메뉴 Data/Communication->Web Browser 버튼을 클릭하여 브라우져를 실행합니다.  

웹 브라우져 창에 사용자 로그인창이 나타나고, 사용자 리스트에 추가된 로그인 정보를 이용하여 로그인을 수행합니다. 



여기에서 살펴볼 내용은 서버 사이드의 로직 변수, 전역변수 그리고 데이터베이스 tag 변수들에 대한 내용과 연동되는 부분과 enuSpace와 웹 랜더러간의 독립된 표현에 대한 부분이다. 

enuSpace 편집기에서 태양주의를 돌고 있는 별을 하나 선택하여 ontaskview() 함수를 확인하여 보면 다음과 같이 구현되어 있다. 



function _ontaskview()

{

rotate = rotate - 0.3;

if (rotate<0)

rotate = 360;

fill = GetValueColor( rotate/5 );

}

선택한 path객체(star)는 자신의 회전값을 0.3씩 줄이는 코드이며 0이하로 떨어진경우에는 초기값 360도로 설정하는 코드이다. 본 코드의 내용으로는 enuSpace의 서버와 웹 브라우져간의 동일한 현시를 수행하는 코드의 처리방식이 아니다.

만약 객체의 서버사이드의 회전값과 동일한 디스플레이를 수행하고자 하는 경우에는 다음과 같이 코드를 수정하여 보자.


main.svg를 선택하고 최상단에 전역변수를 하나 설정한다. 변수명은 g_rotate_star으로 하고 double 형으로 생성한다. 




생성된 g_rotate_star변수의 값을 갱신하는 코드를 추가하여야 한다. 이미 Main features 글자 객체 왼쪽에 원객체가 추가 되어 있다. 원 객체를 선택하고 Properties 윈도우의 Event 속성을 보면 Script Type에 text/lua 설정되어 있으며, ontask()함수를 수정한다. 



다음과 같이 추가 코드를 작성한다.

     g_rotate_star = g_rotate_star - 0.3 

if (g_rotate_star<0) then 

g_rotate_star = 360 

end


다음으로 그래픽 path 객체(star)의 ontaskview()함수를 다음과 같이 수정하자.

수정 전)

function _ontaskview()

{

rotate = rotate - 0.3;

if (rotate<0)

rotate = 360;

fill = GetValueColor( rotate/5 );

}

수정 후)

function _ontaskview()

{

rotate = g_rotate_star;

fill = GetValueColor( rotate/5 );

}


수정후 전역변수의 값을 이용하여 회전값을 적용하도록 구성하였다. 


enuSpace의 기동화면 모습과 웹 브라우져에서의 랜더링 출력 위치가 동일한 위치에서 출력되고 있음을 확인할 수 있다. 위 예제는 전역변수를 이용한 인터페이스 방법에 대하여 설명한 내용이다. 전역변수, 로직객체의 pin 변수, 데이터베이스의 tag변수는 동일한 형태로 연계하여 웹 브라우져에 동일한 디스플레이가 가능합니다.  


데이터베이스 TAG 인터페이스


데이터베이스 TAG를 이용하여 인터페이스를 위하여 데이터베이스 TAG 변수 하나를 추가합니다.  

TYPE : double

TAGID : @Presentation.rotate

VARIABLE : rotate


전역변수값을 디스플레이 위한 Text 객체를 추가하고 ontaskview()함수에 디스플레이 코드를 추가합니다.

function _ontaskview()

{

//TODO Add your javascript code here

textContent = GetTagValue("@Presentation.rotate").toString();

}


사각형 객체 2개를 추가하고, 각각 데이터베이스 TAG의 값을 변경하는 코드를 추가합니다.

function _onmousedown()

{

//TODO Add your javascript code here

SetTagValue("@Presentation.rotate", 90);

}


function _onmousedown()

{

//TODO Add your javascript code here

SetTagValue("@Presentation.rotate", 45);

}



enuSpace의 RunTime에서 사각형 객체를 클릭하여 Tag값이 변경됨을 확인할 수 있으며, 클라이언트 웹 브라우져에서 사각형 객체를 클릭하여 tag값이 변경되어 디스플레이 됨을 확인할 수 있습니다.




전역변수 및 로직객체 PIN 변수의 인터페이스


enuSpace에서는 전역변수와 로직객체의 PIN 변수의 인터페이스를 위하여 SetValue(), GetValue() 함수를 제공합니다.


SetValue 함수의 사용 예)

function _onmousedown()

{

//TODO Add your javascript code here

SetValue("ID_ARD.A0", 99);

}


GetValue 함수의 사용 예)

function _ontaskview()

{

//TODO Add your javascript code here

textContent = GetValue("ID_ARD.A0").toString();

}


* GetValue의 함수는 클라이언트 웹에서 특정 이벤트에 의해서 서버의 값을 가져와 처리하는 경우에 사용하며, 일반적으로 다음과 같이 코드를 사용하기를 권고합니다. (빠른 응답 속도)

textContent = GetValue("ID_ARD.A0").toString();  => textContent = ID_ARD.A0.toString();


* SetValue의 함수 또한 클라이언트 웹에서 특정 이벤트에 의하여 서버의 값을 설정하는 경우에 사용하며, 일반적으로 다음과 같이 코드를 사용하기를 권고합니다. (빠른 응답 속도)

SetValue("ID_ARD.A0", 99); => ID_ARD.A0 = 99;


본 강좌에서는 웹 브라우져와 연동시에 사용하는 함수에 대하여 알아보았습니다. 


-이엔유 주식회사-

IoT Platform 사용방법


본 강좌에서는 enuSpace for mars를 이용하여 IoT 디바이스의 센서값을 취득 및 데이터 로직을 구성하는 방법에 대하여 설명합니다.

enuSpace 학생용 버젼 다운로드 : http://enuspace.tistory.com/entry/enuSpace-for-Mars-2017


준비물

Raspberry PI, Arduino, sensor


프로그램 설치


1. Raspberry PI Installation (software)


enuSpace for mars와 연동하기 위하여 Raspberry PI에 windows 10 iot core 운영체제를 설치후 다운로드 링크에서 응용 프로그램을 설치합니다.


windows 10 iot core 설치 

설치 가이드 : https://developer.microsoft.com/ko-kr/windows/iot/GetStarted

마이크로소프트사에서 제공하는 설치 가이드를 기반으로 단계별로 설치 절차를 진행합니다.

윈도우 Edge 또는 웹브라우져를 이용하여 Window 10 iot core가 설치된 Raspberry PI에 접속을 수행합니다.



Windows 10 IoT Core의 기본 App의 IoTCoreDefaultApp 실행 화면입니다.



아래 그림과 같이 Raspberry PI와 Arduino 디바이스간에 USB Serial을 통하여 연결을 수행하고 아두이노에 센서 2종을 연결한 화면입니다.



Windows 10 IoT Core가 설치된 Raspberry PI에 아래 링크의 응용프로그램을 설치합니다. 


download link : http://enuspace.tistory.com/entry/enuSpace-for-Mars-2017

Windows 10 Core App : enuSpace_IoT (enuSpace_IoT_1.0.3.0_x86_x64_arm.appxbundle)



설정해상도는 1920 *1080으로 설정하여야 정상적인 디스플레이가 가능합니다.



App package 에서 다운로드한 파일을 선택합니다.




Go 버튼을 클릭하여 설치를 수행합니다.



설치를 완료 합니다.


Arduino Installation (software) 


아두이노 디바이스에 아두이노 IDE에서 제공하는 StandardFirmata 프로그램을 설치합니다. 

아두이노 IDE : https://www.arduino.cc/en/Main/Software

라즈베리 파이(Raspberry PI)와 아두이노(Arduino)간에는 StandardFirmata를 이용하여 통신을 수행합니다.


프로그램 기동


Raspberry PI와 Arduino에 프로그램을 설치 마무를 하였다면, 서버 프로그램을 기동합니다. enuSpace 프로그램을 기동하여 새로운 프로젝트를 생성합니다. 

enuSpace의 웹서버를 기동합니다. 웹 서버를 기동하기 전에 리본메뉴 Data/Communication->System Configuration 버튼을 클릭하여 웹서버 사용 유무 및 ip와 포트를 설정합니다.


리본메뉴 Data/Communication->Web Server의 Start 버튼을 클릭하여 서버를 기동합니다. 




서버 사이드 준비사항은 여기까지 입니다. 

라즈베리 파이 응용프로그램을 기동하여 enuSpace 프로그램에 디바이스 등록과정을 통하여 센서의 데이터 및 입출력 핀 제어를 수행합니다.


Raspberry PI -> enuSpace iot 응용프로그램 기동 


라즈베리 파이에 설치한 enuSpace iot 응용프로그램을 실행합니다. 상단의 Server URL의 정보를 enuSpace서버의 ip주소와 포트 정보를 입력합니다.


enuSpace 서버사이드에 본 디바이스를 접속하고자 하는 경우 서버 사이드에 사용자 등록되어 로그인을 수행하여야 합니다. 신규 프로젝트를 생성시에는 사용자 등록 버튼을 클릭하여 사용자 등록을 수행합니다. 


로그인 페이지는 자동 로그인 체크박스, 로그인 버튼, 아이디 찾기/비밀번호 찾기, 사용자 등록 버튼으로 구성, 자동 로그인 체크를 수행후 로그인을 실행하면, 다음 프로그램 재 기동시에는 자동 로그인이 수행됩니다. 

로그인 페이지에서 사용자 등록버튼을 클릭하면, 아래 그림과 같이 사용자 등록을 수행하는 페이지로 전환되면, 사용자 등록 버튼을 클릭을 수행하면, 설정된 서버 주소(enuSpace 서버 사이드)에 사용자 등록 요청을 수행합니다.



정상적으로 사용자 등록과 로그인 페이지가 완료되면, 디바이스 등록 페이지가 나타납니다.



디바이스의 타입은 현재 연결된 아두이노의 타입을 설정합니다. 디바이스 키는 통합 저작 도구 IOT 서버에 등록될 디바이스 키 정보이며, 라즈베리 파이의 시스템 이름을 활용합니다.

신규 디바이스를 등록하는 경우에는 관련 디바이스의 정보와 변수 정보를 enuSpace에 등록하는 과정입니다. 디바이스 등록 버튼을 클릭합니다.



아두이노와 연결된 시리얼 포트 리스트에서 아두이노와 연계된 시리얼 포트를 선택후 연결 버튼을 클릭하여 연결 수행합니다. 연결이 정상적으로 수행이 되면, 아두이노의 센서 데이터값이 현시되며, enuSpace에 등록된 서버에 전송을 수행하여 서버 사이드에서 데이터베이스화 되어 저장됩니다. enuSpace 서버 응용 프로그램에서 리본메뉴 Device List와 DB Show 버튼을 클릭하여 등록된 내용을 확인할 수 있습니다.


enuSpace 서버 사이드에서 프로그램 설치시 사용된 라이브러리를 불러와 화면 작도를 수행합니다. 아두이노 디바이스 심볼 객체의 속성 interface 설정값을 true로 설정하고, interface-id 항목에 #+디바이스 이름을 입력합니다. 이 작업은 디바이스와 디바이스의 tag db의 값이 그래픽적인 라이브러리에 인터페이스 됨을 의미합니다.


사용자 정의 device 심볼을 구성하고자 하는 경우에는 아래와 같은 절차를 따라서 생성합니다.

Project Explorer 하위 Libarary의 Logic에 라이브러리 파일을 생성하고, 디바이스 라이브러리 노드 이름을 입력하고 노드를 생성합니다. 로직의 핀을 추가하고 추가된 핀의 name 속성값을 device의 variable이름으로 설정합니다. 



다음 강좌에서는 클라이언트 웹 브라우져에서 랜더링을 위한 enuSpace 서버 사이드에서의 화면 구현 및 javascript 코드 구현 방법에 대하여 알아보겠습니다. 

-이엔유 주식회사-

enuSpace 시뮬레이션 기능 및 Data Visualization 사용방법


본 강좌에서는 enuSpace for mars를 이용하여 시뮬레이션을 수행하는 방법에 대하여 설명합니다. 

enuSpace 학생용 버젼 다운로드 : http://enuspace.tistory.com/entry/enuSpace-for-Mars-2017


enuSpace for mars에서 시뮬레이션 또는 task를 개발함에 있어 2가지 형태의 모델로 구성될 수 있습니다. enuSpace for mars의 ontask함수를 활용한 방법과 외부의 task의 모듈을 연동하는 방법입니다.


Lesson5 sample : lesson5.zip


1. 로직 라이브러리를 이용한 flowbased programming 방법.

2. 외부 모델을 이용한 연동 방법.


동영상 미리보기


New Project


새로운 프로젝트를 생성하기 위해서 Home->New->New Project메뉴를 이용하여 새로운 프로젝트를 생성합니다.



Simulation Time Setup


새로운 프로젝트 생성을 완료하였다면, 리본메뉴 Data/Communication->System Configuration메뉴를 선택하여 System Configuration 대화창의 속성을 설정합니다. 시뮬레이션용으로 설정하기 위해서는 Time의 속성중 Simulation Time을 설정합니다. Simulation Time을 설정하게 되면 enuSpace에서 기동되는 시작시간의 정보는 0초부터 동작을 수행합니다. 

System Time옵션에서 Simulation Time옵션으로 변경 수행시 프로젝트에 기존에 누적된 히스토리 데이터베이스가 모두 제거되어 초기화 됩니다. 프로젝트 로드시에도 기존의 히스토리 데이터베이스를 초기화 합니다.

참고로 System Time의 설정은 현재시간(UTC)을 기준으로 모든 데이터가 생성되고  히스토레 데이터에 누적됩니다.  



Simulation Scheduling


enuSpace for mars의 task()함수를 사용하는 경우에는 flowbased programming을 통하여 동작을 수행합니다. 내부 task()함수는 스케쥴링 속성값에 따라서 주기적인 연산을 호출하도록 구성되어 있습니다. 속성 설정하기 위해서 Project Explorer창 Task하위 logic_svg 아이템을 선택합니다. logic_svg 속성창 중 Cycle (Hz) 속성은 1초에 1, 2, 3, 4, 6, 8, 12, 24회 호출 주기에 대한 설정입니다. Task In/Out의 속성은 선택한 Task에 대하여 연산을 수행할 것인지, 제외할것인지를 설정합니다. 



시뮬레이션 모델을 제작하다보면 task()함수에서 delta T값을 이용하는 경우가 있습니다. 전역변수 dt값을 이용하여 코드를 구현합니다.


function _ontask()

--TODO Add your lua script code here

local deltaT = dt

--bla bla ~~

end


외부 모델 연계 API

시뮬레이션 모델 개발시 기존의 코드를 재활용하거나 외부의 모델과의 인터페이스가 필요한 경우가 있습니다. enuSpace는 외부 모델과 연동하기 위한 인터페이스 모듈을 제공합니다. 외부 모델과 연계시 dynamic link library(dll)을 이용합니다.

외부 연동 인터페이스 모듈의 dll의 주요 함수는 아래와 같습니다.


extern "C" __declspec(dllexport) bool OnInit();

extern "C" __declspec(dllexport) bool OnLoad();

extern "C" __declspec(dllexport) bool OnUnload();

extern "C" __declspec(dllexport) bool OnTask();


각 함수는 아래와 같은 조건에서 호출됩니다.

OnInit() : 첫 기동시 호출되는 초기화 함수

OnLoad() : dll 로드수행시 호출되는 함수

OnUnload() : dll 언로드 수행시 호출되는 함수

OnTask() : 스케쥴링 주기에 따라서 호출되는 함수


OnTask()함수 구현부에는 시뮬레이션을 수행하고자 하는 알고리즘을 추가합니다. 작성된 코드와 enuSpace와 연동하기 위해서 인터페이스용 콜백함수 4개를 제공합니다. 


extern "C" __declspec(dllexport) void SetCallBack_SetValue(void fcbSetValue(wchar_t*, double));

extern "C" __declspec(dllexport) void SetCallBack_GetValue(DBDataStruct* fcbGetValue(wchar_t*));

extern "C" __declspec(dllexport) void SetCallBack_SetArrayValue(void fcbSetArrayValue(wchar_t*, void*, int, int));

extern "C" __declspec(dllexport) void SetCallBack_GetArrayValue(DBDataStruct* fcbGetArrayValue(wchar_t*));


특정 데이터베이스의 Tag값을 읽고 쓰기 위한 함수 포인터입니다. 본 함수는 dll로드 수행시 함수의 포인터로 전달됩니다. 전달된 함수 포인터 이용하여 값을 읽거나 쓰기를 수행합니다. 


구현부를 보시면 아래와 같습니다.


void (*g_fcbSetValue)(wchar_t*, double) = NULL;

DBDataStruct* (*g_fcbGetValue)(wchar_t*) = NULL;

void(*g_fcbSetArrayValue)(wchar_t*, void*, int, int) = NULL;

DBDataStruct* (*g_fcbGetArrayValue)(wchar_t*) = NULL;


extern "C" __declspec(dllexport) void SetCallBack_SetValue(void fcbSetValue(wchar_t*, double)) g_fcbSetValue = fcbSetValue; }

extern "C" __declspec(dllexport) void SetCallBack_GetValue(DBDataStruct* fcbGetValue(wchar_t*)) g_fcbGetValue = fcbGetValue; }

extern "C" __declspec(dllexport) void SetCallBack_SetArrayValue(void fcbSetArrayValue(wchar_t*, void*, int, int)) g_fcbSetArrayValue = fcbSetArrayValue; }

extern "C" __declspec(dllexport) void SetCallBack_GetArrayValue(DBDataStruct* fcbGetArrayValue(wchar_t*)) g_fcbGetArrayValue = fcbGetArrayValue; }


위 코드는 기 제공되는 코드의 예시입니다. 


CMap<CString, LPCWSTR, DBDataStruct*, DBDataStruct*> g_DBMapList;

void SetArrayValue(CString strVariable, void* pSrc, int iType, int iSize)

{

if (g_fcbSetArrayValue)

g_fcbSetArrayValue(strVariable.GetBuffer(0), pSrc, iType, iSize);

}

DBDataStruct* GetArrayValue(CString strVariable)

{

if (g_fcbGetArrayValue)

return g_fcbGetArrayValue(strVariable.GetBuffer(0));

return NULL;

}

void SetValue(CString strVariable, double fValue)

{

double fReturn = 0;

DBDataStruct* pData = NULL;

g_DBMapList.Lookup(strVariable, pData);

if (g_fcbSetValue && pData == NULL)

{

pData = g_fcbGetValue(strVariable.GetBuffer(0));

g_DBMapList.SetAt(strVariable, pData);

}

if (pData && pData->pValue)

{

switch (pData->itype)

{

case DEF_INT:

*(int*)pData->pValue = (int)fValue;

break;

case DEF_FLOAT:

*(float*)pData->pValue = (float)fValue;

break;

case DEF_DOUBLE:

*(double*)pData->pValue = fValue;

break;

case DEF_BOOL:

if (fValue == 1)

*(bool*)pData->pValue = true;

else

*(bool*)pData->pValue = false;

break;

case DEF_WCHAR:

break;

default:

break;

}

}

}

double GetValue(CString strVariable)

{

double fReturn = 0;

DBDataStruct* pData = NULL;

g_DBMapList.Lookup(strVariable, pData);

if (g_fcbGetValue && pData == NULL)

{

pData = g_fcbGetValue(strVariable.GetBuffer(0));

if (pData)

g_DBMapList.SetAt(strVariable, pData);

}

if (pData && pData->pValue)

{

switch (pData->itype)

{

case DEF_INT:

fReturn = *(int*)pData->pValue;

break;

case DEF_FLOAT:

fReturn = *(float*)pData->pValue;

break;

case DEF_DOUBLE:

fReturn = *(double*)pData->pValue;

break;

case DEF_BOOL:

if (*(bool*)pData->pValue == TRUE)

fReturn = 1;

else

fReturn = 0;

break;

default:

break;

}

}

return fReturn;

}


실제 인터페이스는 값을 읽기 쓰기위한 코드와 모델 연산로직 코드를 추가함으로서 외부 모델을 연계할 수 있습니다. 


모델 예)

모델의 실행 코드와 인터페이스 코드 예시


double display[16][16];

float initValue = 1.0f;


extern "C" __declspec(dllexport) bool OnTask()

{

initValue = initValue + 0.1;

for (int x = 0; x < 16; x++)

{

for (int y = 0; y < 16; y++)

{

display[x][y] = 1.0 + sin(double((x * 16) + (y * 16)) / 3.141592 / 5 + initValue);

}

}

SetArrayValue(L"@CORE.display[0][0]", display, DEF_DOUBLE, 16 * 16);

return true;

}


sin파를 생성하여 데이터 인터페이스를 수행하는 코드를 작성하였습니다. 위와 같이 코드를 추가하고 컴파일을 수행하여 CoreTask.dll을 생성합니다. 모델 생성이 완료하였다면 데이터베이스와 연동하기 위한 tag id를 enuSpace 프로젝트에 추가를 수행합니다. SetArrayValue()함수는 배열 정보를 enuSpace에서 추가한 tag의(@CORE.display[0][0]) 값에 연산 결과를 전달하는 과정입니다. 


SetArrayValue() 함수의 파라미터 정보를 보면 변수명, 원본 데이터의 메모리 주소, 복사하고자하는 데이터 타입, 사이즈값입니다. 만약 단일 변수에 추가하고자 하는 경우에는 SetValue()함수를 이용합니다. 경우에 따라서 위의 예시에서 제공하는 SetValue()함수 등은 확장 및 변경하여 구현할 수 있습니다.


enuSpace for mars 데이터베이스 TAG 추가


enuSpace의 리본메뉴 Data/Communication->DB Show 버튼을 클릭합니다. 다음과 같이 DB Table의 정보가 나타나고 DB+ 버튼을 클릭하여 모델간의 인터페이스를 위한 TAG 변수를 추가합니다. 추가되는 최종 TAG ID는 @문자가 앞에 추가됩니다. @문자는 데이터베이스 TAG 변수와 전역변수와의 구분자로도 활용됩니다. 데이터베이스 TAG ID를 이용하여 스크립트에서 활용합니다.



정상적으로 데이터베이스 TAG가 추가완료 후 앞에서 제작한 외부 TASK(CoreTask.dll)를 enuSpace 프로젝트에 추가합니다. Project Explorer의 Task항목을 선택하고 팝업메뉴 Add Task를 선택하여 Task Module의 콤보박스에 CoreTask.dll을 선택합니다. 프로젝트 디렉토리 lesson5//Task//CoreTask에 앞에서 생성한 CoreTask.dll 파일이 존재하는 경우 자동으로 콤보박스에서 선택이 가능하도록 제공이 됩니다. 



디렉토리의 구조 및 외부 TASK의 위치는 아래 그림과 같습니다.



TASK가 정상 등록이 되었다면, TASK를 기동하기 위해서 리본메뉴 Home->Script Operation의 Run 버튼을 클릭합니다. 연산이 정상적으로 처리되고 있는지를 확인하기 위해서 리본메뉴의 리본메뉴의 Data/Communication->DB Show메뉴를 선택하여 데이터베이스의 실시간 값을 확인합니다. 



아래 그림과 같이 차트 버튼을 클릭하여 팝업 Trend를 이용하여 데이터값을 확인할 수 있습니다. 차트사용 방법은 별도의 강좌에서 설명하도록 하겠습니다. 



3D data visualization


앞에서 제작한 배열변수의 값을 3차원 디스플레이에 디스플레이 하기 위해서 픽쳐파일 core_display.x3d 파일을 추가합니다. 추가된 x3d 파일을 선택후 Terrain객체를 추가합니다. Terrain 객체의 속성중 subdivision_x, subdivision_y의 값을 데이터베이스 TAG의 배열정보 16, 16으로 설정합니다. subdivision의 값을 설정함에 따라 내부의 double형 데이터 변수 data[16][16]가 생성됩니다.



추가된 Terrain 객체에 javascript 또는 lua script를 이용하여 데이터베이스 tag의 값을 그래픽 객체의 디스플레이 객체에 전달하여 실시간 데이터를 디스플레이 하기 위해서 아래 예시 코드와 같이 memcpy() 함수를 이용합니다. memcpy() 함수를 이용하지 않고 개별적인 인터페이스는 

data[0][0] = @CORE.display[0][0];

data[0][1] = @CORE.display[0][1]; ... 와 같이 코드를 작성할 수 있습니다.


* memcpy함수 사용시 변수의 타입과 변수 사이즈 입력에 주의하여야 한다. 잘못된 인자의 사용으로 인한 메모리 릭 또는 비정상 종료가 발생할 수 있습니다.    


ex) lua script

function _ontaskview()

--TODO Add your lua script code here

memcpy(&data[0][0],&@CORE.display[0][0],16*16)

end

ex) javascript

function _ontaskview()

{

//TODO Add your javascript code here

memcpy(&data[0][0],&@CORE.display[0][0],16*16);

}



2D data visualization


앞 강좌에서 기초객체의 속성값을 이용하여 2D 그래픽에 가시화하는 방법에 소개하였습니다. 간략히 살펴보면 추가된 객체를 선택하고 ontaskview의 함수를 추가합니다. enuSpace는 javascript와 lua script를 지원하며 각각의 예시는 아래와 같습니다.


function _ontaskview()

{

//TODO Add your javascript code here

textContent = @CORE.display[0][0];

}

function _ontaskview()

--TODO Add your lua script code here

text = string.format("%f", @CORE.display[0][0])

end


데이터베이스의 tag 값을 가져오기 위해서는 데이터베이스 tag id를 이용합니다. 데이터베이스 변수는 첫문자에 @문자를 포함합니다. 



데이터베이스의 값을 가져와 Text 객체의 값으로 할당하는 예시 화면.

사각형의 객체를 가져와 연산 결과를 높이값으로 표현하기 위해서 아래와 같이 코드를 추가합니다.


function _ontaskview()

{

//TODO Add your javascript code here

height = @CORE.display[0][15]*50;

}



시뮬레이션 상태값 저장 및 복원 (Snap, Reset) 기능


enuSpace 시뮬레이션 기능은 현재 설정된 상태값을 저장하고 저장된 상태값에 대한 복원 기능을 제공합니다. 상단의 리본메뉴 Home->Condition의 Snap 버튼과 Reset 버튼을 이용합니다. 


다음 강좌에서는 Trend 객체와 히스토리 팝업 Trend의 기능 및 사용방법에 알아보겠습니다.

-이엔유 주식회사- 

enuSpace를 이용한 LOGIC 라이브러리 생성 및 적용 방법


본 강좌에서는 로직 라이브러리 생성 방법과 생성된 로직을 이용하여 프로그래밍 방법에 대하여 설명합니다.

강좌샘플 : lesson3.zip


동영상 미리보기



New Project

새로운 프로젝트를 생성하기 위해서 Home->New->New Project메뉴를 선택합니다.


New Project (popup window)윈도우가 나타나면, 솔루션 이름과 솔루션을 저장할 디렉토리를 설정후 OK 버튼을 클릭합니다.


New Logic library

Project Explorer->Library->Logic 아이템을 선택후 마우스 오른쪽 버튼을 클릭하여 팝업메뉴를 호출합니다. 팝업메뉴 Add New Hmi Library를 선택하여 라이브러리 이름을 입력합니다.

두개의 입력을 받아서 더하기 연산을 수행하는 ADD 로직 라이브러를 생성하기 위해서, Project Explorer에 추가된 logic_library.svg 파일을 선택, 팝업메뉴 Add Symbol을 선택하여 심볼의 이름을 ADD로 입력하고 New 버튼을 클릭합니다.


추가된 ADD 라이브러리를 선택하고 디자인을 수행합니다. 간단하게 사각형 객체와 Path 객체를 추가후

Ribbon Menu->Home->Connection Pin을 선택후 Graphic 윈도우에 마우스를 클릭하여 Connection Pin 객체를 생성합니다. 두개의 입력과 하나의 출력 핀을 생성하여 배치를 수행합니다.

배치를 모두 마치고나면, 각 핀의 이름을 설정합니다. 설정된 입력핀은 스크립트에서 사용되는 변수명으로 사용됩니다.

입력 핀과 출력 핀의 색상을 바꾸어 직관적 이해가 가능하도록 구성합니다.

위와 같이 입출력핀 구성을 마무리 하였다면, 라이브러리에 로직용 스크립트를 추가합니다. 라이브러리의 멤버함수 ontask() 함수를 추가합니다.

function _ontask()

--TODO Add your lua script code here

output = input1 + input2

end

이로써 더하기 연산을 수행하는 ADD 로직 라이브러리가 완성되었습니다. 추가적인 디자인과 현재값을 현시하는 라벨을 추가하거나 다양한 표현을 추가적으로 구성할 수 있습니다. 


Using Logic Library in picture

앞에서 제작한 로직 라이브러리를 이용하여 로직화면을 구성하도록 하겠습니다.

Project Explorer의 Picture를 선택후 오른쪽 버튼을 클릭하여 New Picture file 다이얼로그를 호출합니다. filename을 sample을 일력하여 새로운 픽쳐파일을 생성합니다.

Logic 라이브러리 창을 클릭후 앞에서 생성한 라이브러리를 선택후 Drag & Drop으로 객체를 생성합니다.

로직을 연산을 수행하기 위해서 Ribbon Menu->Home->Script operation의 Run 버튼을 클릭하여 기동을 수행합니다. 

추가된 객체를 마우스를 이용하여 더블 클릭하면, 로직의 입출력 테이블이 나타납니다. 테이블의 값 부분을 더블 클릭하여 입력값을 수정합니다.

입력값에 따라서 변경되는 것을 확인할 수 있습니다. 

아래 그림과 같이 로직 객체를 추가하여 Ribbon menu의 Home->Transfer 메뉴를 이용하여 객체간에 연결을 수행합니다.

테이블의 입력값을 조정하여 로직을 연산결과를 확인할 수 있습니다.

팝업 테이블의 변수리스트를 다중 선택하여 팝업 TREND로 데이터를 확인할 수 있습니다. 

Trend의 활용법은 별도의 강좌에서 설명하도록 하겠습니다.


다음 강좌에서는 logic객체의 변수값을 hmi객체에 값을 적용하는 응용에 대하여 알아보도록 하겠습니다.

-이엔유 주식회사-


enuSpace를 이용한 HMI 라이브러리 생성 및 적용 방법 (2/2)


본 강좌에서는 다이나틱 데이터 디스플레이를 HMI Panel 라이브러리 제작하는 과정을 포함하고 있습니다.

enuSpace를 이용한 HMI 라이브러리 생성 및 적용 방법(1/2)


강좌샘플 : lesson2.zip


enuSpace를 이용한 HMI 라이브러리 생성 및 적용 방법(1/2)절에 이어서 심볼의 사이즈 조정인자와 심볼의 색상, 라벨의 색상값을 설정할 수 있는 인터페이스를 추가합니다.


Project Explorer에서 LABEL_VALUE를 선택후 Properties창에서 Variable Window를 선택합니다. 다음과 같이 4개의 변수를 추가합니다.

double m_width;                // 라이브러리 폭 조정인자

double m_height;               // 라이브러리 높이 조정인자

wchar m_backcolor;            // 라이브러리 패널 색상 조정인자

wchar m_labelcolor;            // 라이브러리 라벨 색상 조정인자


라이브러리에 추가된 멤버변수는 onload() 함수를 통하여 연계를 수행합니다. onload() 함수는 객체가 초기에 로드시 호출되며, 멤버변수의 속성을 변경 수행시 호출되는 함수입니다.

추가된  코드 내용을 보면 아래와 같습니다.

function _onload()

{

//TODO Add your javascript code here

ID_PANEL.width = ID_PANEL.translate_x + m_width;

ID_PANEL.height = ID_PANEL.translate_y + m_height;

ID_PANEL.fill = m_backcolor;

ID_LABEL.stroke = m_labelcolor;

ID_LABEL.translate_x = ID_PANEL.width/2;

ID_LABEL.translate_y = ID_PANEL.height - ID_PANEL.height/5;

}

ID_PANEL의 폭값은 ID_PANEL의 위치 이동값과 사용자가 업데이트한 또는 초기화된 값의 합으로 설정되며, 높이 또한 동일한 연산을 통하여 ID_PANEL의 사이즈롤 조정합니다. 

또한, 패널의 내부 색상값은 멤버변수 m_backcolor값과 라벨의 폰트 색상은 m_labelcolor의 값을 이용하여 연계됩니다. 

패널의 사이즈 조정시 라벨의 위치값도 조정을 해주어야 합니다. 라벨의 속성중 text_anchor의 값은 middle로 설정되어 있기 때문에 폭의 중간값으로 설정하고 높이는 패널 높이의 4/5위치에 배치시켰다.


코드를 Compile 버튼을 클릭후 이전장에서 추가한 Project Explorer의 Picture의 sample.svg 파일을 오픈한다. 오픈을 수행하면 이전에 생성된 객체의 속성을 유지하고 있기 때문에 재로딩을 수행한다. 단축키 F5 버튼을 누르면 픽쳐페이지를 재로딩을 수행합니다. 수정한 라이브러리의 속성이 나타납니다.


sample.svg 픽쳐에 여러개의 LABEL_VALUE객체를 추가하여 각 객체의 멤버변수의 값을 조정하여 테스트를 합니다. 색상값을 입력할 경우 rgb(20,20,20) 형태로 입력합니다.

라이브러리의 속성값 변경에 따른 디스플레이


LABEL_VALUE 라이브러리에 패널의 외곽선 색상, 폰트의 사이즈에 대한 인터페이스도 추가하여 완성도 높은  라이브러리를 작성해 보세요.


다음 강좌에서는 로직 라이브러리 생성 및 적용방법에 대하여 알아보도록 하겠습니다.

-이엔유 주식회사-

enuSpace를 이용한 HMI 라이브러리 생성 및 적용 방법 (1/2)


본 강좌에서는 다이나믹 데이터 디스플레이를 HMI Panel 라이브러리 제작하는 과정을 포함하고 있습니다.


동영상 미리보기



New Project

새로운 프로젝트를 생성하기 위해서 Home->New->New Project 선택를 선택합니다.


New Project (Popup Window) 윈도우가 나타납니다. 솔루션 이름과 솔루션을 저장할 디렉토리를 설정후 OK 버튼을 클릭합니다.


New Hmi library

Project Explorer->Library->Hmi 아이템을 선택후 마우스 오른쪽 버튼을 클릭하여 팝업메뉴를 호출한다. 팝업메뉴 Add New Hmi Library를 선택하여 라이브러리의 이름을 입력합니다.


Project Explorer에 추가된 hmi_library.svg 파일을 선택후 마우스 오른쪽 버튼을 클릭하여 팝업메뉴를 호출한다. 팝업메뉴 Add Symbol을 선택하여 심볼의 이름을 LABEL_VALUE입력하고 New 버튼을 클릭합니다. 


Project Explorer에서 앞에서 추가한 라이브러리를 선택하면 라이브러리 편집 Picture Window가 나타납니다.


다이나믹 디스플레이를 위한 패널 제작을 위하여 그래픽 편집도구를 이용하여 다음과 같이 구성합니다. 사각형 객체와 문자객체를 추가합니다.


문자객체에 데이터를 디스플레이할 경우, 항상 사각형의 중앙정렬이 되도록 문자객체를 선택하고 Properties Window의 속성 text-anchor의 값을 middle로 설정합니다.  

참고사이트 : https://www.w3.org/TR/SVG/text.html#TextAnchorProperty


라이브러리를 OOP(Object Oriented Programming)기반으로 제작하기 위해서 멤버변수를 추가합니다. 디스플레이할 값과 연동하기 위한 변수를 추가합니다. Project Explorer->lesson2->Library->Hmi->hmi_library.svg->LABEL_VALUE를 선택하거나, 빈 공간을 선택합니다. 선택후 Properties 에서 변수를 추가합니다.  


데이터 연동시 두가지 방법으로 추가가 가능합니다. 라이브러리의 멤버함수 ontaskview()에 추가하는 방법과 TEXT 객체의 멤버함수 ontaskview()함수에 추가하는 방법입니다.


라이브러리의 멤버함수에 ontaskview()함수에 추가하는 스크립트 코드는 아래와 같습니다.

function _ontaskview()

{

//TODO Add your javascript code here

ID_LABEL.textContent = m_value.toString();

}

TEXT객체에 고유한 ID이름을 설정하고 고유한 ID값을 이용하여 텍스트의 값을 멤버변수 m_value의 값을 문자열로 치환하는 방법입니다.


TEXT객체의 ontaskview()함수에 추가하는 스크립트 코드는 아래와 같습니다.

function _ontaskview()

{

//TODO Add your javascript code here

textContent = m_value.toString();

}

TEXT객체 자체에 추가하는 스크립트 코드는 자신의 ID값을 적용할 필요없이 textContent 속성값을 호출하면 됩니다.


본 강좌에서는 라이브러리의 ontaskview() 함수를 이용하여 구현합니다. 

이로써 값을 디스플레이하는 다이나믹 패널이 제작 완료되었습니다.


Using HMI Library in picture

앞에서 제작한 다이나믹 라이브러리를 이용하여 픽쳐를 구현해보도록 하겠습니다.

Project Explorer의 Picture를 선택후 오른쪽 버튼을 클릭하여 팝업메뉴를 호출합니다. sample로 입력후 Create 버튼을 클릭하여 새로운 픽쳐 페이지를 생성합니다.


HMI 라이브러리 창을 클릭후 앞에서 생성한 라이브러리를 선택 후 Drag & Drop으로 객체를 생성합니다.

생성된 객체를 선택한후 속성창의 Variable Window에서 앞에서 추가한 멤버변수가 나타나고 값을 할당하기 위한 Set Attribute항목이 나타납니다. #m_value의 값으로 입력할 수 있는 타입은  2가지입니다. 

1. 상수값을 입력합니다.

2. 인터페이스 되고자 하는 변수를 입력합니다.

어떠한값도 입력하지 않았을 경우에는 초기값을 유지합니다.


테스트를 위해서 Ribbon Menu->Script Operation의 Run 버튼을 클릭하여 스크립트를 기동합니다. 0으로 디스플레이 되는것을 확인할 수 있습니다. 50을 입력합니다. 아래 그림과 같이 50으로 변경되어 디스플레이 됨을 확인할 수 있습니다.

Set Attribute에 변수를 할당하기 위한 변수가 없기 때문에 sample.svg에 멤버변수를 추가하여 연동을 합니다. Project Explorer의 Picture하위 sample.svg를 선택하거나 Picture Window의 배경을 선택합니다. 속성창에서 Variable Window에서 픽쳐 변수를 생성합니다.

변수가 생성이 되었다면, 픽쳐의 멤버함수 ontask()함수에 lua 스크립트를 이용하여 추가합니다. enuSpace의 lua 스크립트를 사용하는 경우는 특정 모델에 해당하는 연산을 수행하고자 할 경우에는 ontask()함수를 사용합니다. ontask()함수는 lua 스크립트에서만 추가가능합니다.

다음과 같이 루아 스크립트를 추가합니다.

function _ontask()

--TODO Add your lua script code here

m_double = m_double + 1

if (m_double > 100) then

m_double = 0

end

end

Ribbon Menu의 Home->Script Operation의 Run 버튼을 클릭하면, Task의 logic_svg의 속성 Cycle(Hz)값에 따라 연산을 수행합니다. 간단하게 0에서 100까지 증가하는 연산을 구성하였다면, 앞에서 생성한 HMI 객체를 선택하고 Variable Window의 SetAttribute의 #m_value의 값에 #m_double을 입력합니다.


Picture에 추가한 멤버변수를 HMI 라이브러리의 변수를 연결을 수행하였습니다. 연결시 외부 데이터의 인터페이스를 수행하는 경우에는 변수명 앞에 #을 입력하여야 합니다. #의 의미는 데이터의 인터페이스를 의미합니다.

Home->Runtime 버튼을 클릭하여, 실제 동작화면을 통하여 변수값 변경 및 색상값 변경에 대한 결과를 확인할 수 있습니다.


패널의 색상 및 사이즈를 조정하시고자 하는 경우가 발생할 경우에 별도의 라이브러리를 만들지 않고 라이브러리의 기능을 확장하여 사용할 수 있습니다.

다음 강좌에서는 HMI 라이브러리의 확장 사용방법에 대하여 알아보도록 하겠습니다.

enuSpace를 이용한 HMI 라이브러리 생성 및 적용 방법(2/2)

- 이엔유 주식회사- 



엔유스페이스 소개 자료 V1.0 (pdf) 파일 다운

enuSpace 팜플렛.pdf








엔유스페이스 HMI/SCADA/IOT/APPLICATION 솔루션 소개



About enuSpace ?


엔유스페이스는 HMI/SCADA/DCS/IOT분야에서 활용되는 다기능 통합 개발자 솔루션입니다. 그래픽 편집 및 런타임 뷰어 기능을 포함하고 있으며, 동적 데이터 가시화 도구를 제공합니다. 객체 지향 프로그래밍(Object Oriented Programming:OOP) 개념을 도입한 사용자 정의 라이브러리를 생성하여 그래픽 컴포넌트로 적용 가능합니다.

엔유스페이스는 동적 디스플레이와 시뮬레이션 도구가 통합되어 로직 및 알고리즘 라이브러리 블럭을 이용하여 데이터 연결선만으로 플로우베이스 프로그래밍(Flowbased Programming)이 가능합니다. 연산결과는 동적 디스플레이 객체를 통하여 표현합니다.

엔유스페이스는 소프트웨어 개발자 도구(Software Development Kit :SDK)를 제공하며, SDK 그래픽 기능을 활용하여 빠르고 수려한 윈도우 그래픽 프로그램을 개발할 수 있습니다


HMI/LOGIC Total Solution Overview


Design symbol and drawing pictures for simulation and monitoring

Advanced GUI Programming (Flowbased Programming)

Extended file format(Scalable Vector Graphics + Lua Script Language)

Versatile software tool to develop and display dynamic graphical user interfaces

Graphic Component (Easy to development User Application Program)

Making Dynamic Symbols & Logic Symbols


Graphics Designer

엔유스페이스 편집기는 직관적 사용이 가능한 사용자 편의 편집 기능을 제공합니다. 모든 객체의 속성은 동적표현을 위한 인자로 활용될 수 있습니다.

스크립트 언어를 이용하여 모든 인자에 대한 속성 변경을 수행함으로서 유연한 인터페이스가 가능합니다. 편집과정 중에 실제 런타임 뷰어를 통한 실행 결과값을 확인 및 디버깅할 수 있습니다.


Flowbased Programming


엔유스페이스는 사용자가 로직 컴포넌트를 제작하여 시뮬레이션 알고리즘을 개발 및 적용할 수 있습니다. 적용범위는 단순로직에서 부터 복잡한 수식까지 적용 가능합니다.

Connect to your data using enuSpace APIs

응용 프로그램 개발 수행시 엔유스페이스 API를 이용하여 데이터 인터페이스를 수행할 수 있습니다. 뿐만 아니라, 각 개별 객체를 API를 이용하여 생성, 수정, 제거를 수행할 수 있습니다. 각 객체에 스크립트 함수등을 동적으로 추가 등록할 수 있는 API를 제공합니다.


Application Areas


엔유스페이스는 교육 및 연구용 시뮬레이션, 산업용 모니터링 및 제어분야 등 전범위 적용이 가능합니다. 발전소, 항공, 전기 생산, 분산 제어 시스템 분야에 있어 광범위하게 사용가능한 솔루션 입니다.

 



enuSpace SDK를 이용한 그래픽 편집기 제작 


상세코드를 확인하실려면 샘플 프로젝트를 다운 받아주세요.

샘플 다운

GUIEditor#1.zip

제1강


enuSpace HMI/SCADA 솔루션은 개발자에게 그래픽 응용프로그램을 쉽고 빠르게 제작할 수 있는 SDK를 제공합니다. 본 제1강에서는 enuSpace SDK를 이용하여 나만의 저작기 생성방법을 소개 합니다.

우선, 나만의 그래픽 편집기를 제작하기 위해서 Visual Studio 2012를 이용하여 새로운 프로젝트를 생성합니다.





간단한 예시용 프로젝트 이므로, 단일 문서에 CView 기반의 SDI 프로젝트로 생성합니다.


생성된 프로젝트에 enuSpace를 이용하기 위해 SDK의 라이브러리와 해더 파일을 추가합니다.

 

MFC 프로젝트의 stdafx.h 파일에 라이브러리와 해더파일을 추가합니다.


stdafx.h

// ~~
#include "header\enuLibrary.h"
#include "header\SvgDefine.h"

#pragma comment (lib, "lib\\enuSpaceLib.lib")
// ~~

MFC의 프로젝트 속성을 조금더 수행하면, 출력 디렉토리에 Bin의 디렉토리로 변경, 대상이름은 Debug와 Release에 구분하여 GUIEditor_R, GUIEditor_D로 구분하여 생성하도록 옵션을 수정합니다.



여기까지 프로젝트 설정을 마무리하고 컴파일하여 빌드된 프로그램을 실행하면, 빈 프로젝트가 실행됩니다. 여기에 enuSpace SDK 프로젝트를 생성하고, View를 생성하여 보겠습니다.


해더에 멤버변수 3개를 추가하도록 합니다.


class CGUIEditorView : public CView
{
// ~~
private:
	HPROJECT m_pProject;
	HVIEW    m_pENUView;
	HSVG     m_pSvgHandle;


m_pProject는 enuSpace 의 프로젝트 핸들입니다. 

m_pENUView는 enuSpace의 뷰의 핸들입니다. 뷰핸들을 이용하여 그래픽 객체를 제어할 경우에 사용되는 멤버 변수입니다.

m_pSvgHandle은 enuSpace의 SVG 파일 핸들입니다.



각 핸들을 추가한후, 뷰의 OnInitialUpdate() MFC 가상함수를 추가합니다. 추가된 함수에 아래코드를 추가하여 빌드를 수행합니다. 


void CGUIEditorView::OnInitialUpdate()
{
	CView::OnInitialUpdate();

	// Create Project
	m_pProject = enuCreateProject();


	// Project Open
	wchar_t szPath[MAX_PATH];
	GetModuleFileName(NULL, szPath, MAX_PATH);
	wchar_t drive[MAX_PATH];    // Drive
	wchar_t dir[MAX_PATH];      // Directory
	wchar_t fname[MAX_PATH];    // Filename
	wchar_t ext[MAX_PATH];      // Ext
	_wsplitpath_s(szPath, drive, dir, fname, ext);

	CString strProjectName;
	strProjectName.Format(L"%s%sGUI\\GUI.enup", drive, dir);
	enuLoadProjectFile(strProjectName.GetBuffer(0));

	// ENU View Create
	m_pENUView = enuCreateView(this->m_hWnd);

	// ENU View Size Set.
	RECT rect;
	GetClientRect(&rect);
	enuSetWindowPos(m_pENUView, rect.left, rect.top, rect.right, rect.bottom);

	// ENU View Window Color Set.
	enuSetWindowColor(m_pENUView, 200,200,200);

	// ENU View ID Set.
	enuSetViewID(m_pENUView, L"KoreaAIP");

	// New Page Create.
	CString strPicture = L"picture\\KoreaAIP.svg";
	m_pSvgHandle = enuNewSvgPageFile(strPicture.GetBuffer(0));

	// ENU View Attach Set Page
	enuSetSvgPageView(m_pENUView, strPicture.GetBuffer(0));

	// Page Canvas Color Set.
	enuSetCanvasColor(m_pENUView,  100,100,100);
}

위 코드의 내용을 간략히 살펴보면, 새로운 프로젝트를 생성하는 API 함수 enuCreateProject(), 프로젝트를 로드 수행하는 enuLoadProjectFile() 함수 여기 샘플에서는 기본 프로젝트를 생성하여 로드한 결과입니다. enuSpace의 뷰를 생성하는 enuCreateView()함수와 윈도우의 위치지정을 위한 enuSetWinwosPos() 함수, 윈도우의 색상을 지정하는 enuSetWindowColor()함수, 윈도우의 ID를 지정하는 enuSetViewID()함수, 그리고 새로운 그래픽 페이지를 생성하는 enuNewSvgPageFile()함수입니다.

그리고 생성된 뷰에 새로운 그래픽 페이지를 연결을 수행하여 화면상에 보여지도록 하는 enuSetSvgPageView()를 호출하였습니다. 
만약 여러개의 그래픽 페이지를 생성하였고, 상황에 맞게 뷰에 보여지도록 설정하는 함수가 enuSetSvgPageView()함수입니다. 

처음 생성하였을 경우, 기본적으로 그래픽 편집모드로 생성됩니다. 운영 모드로 변경하고자 하는 경우에는 enuSetScriptOperationMode(true)를 수행함으로서 운영모드로 변경할 수 있습니다.
 


여기까지 진행이 되었다면, 다음으로 객체를 생성하기 위한 인터페이스를 열어주어야 합니다. 이때 enuSetCallBackSelectToolBar()함수를 이용하여 툴바의 객체 선택정보가 변경되었을 경우, 응용프로그램에게 전달 받고자하는 콜백함수를 설정을 추가합니다. 


그리고 Ribbon 메뉴에 각 기초객체를 생성하기 위해 MainFrm.cpp에 CreateRibbonBar()를 생성합니다.

BOOL CMainFrame::CreateRibbonBar()
{
	if (!m_wndRibbonBar.Create(this))
	{
		return -1;      // fail to create
	}

	m_PanelImages.SetImageSize(CSize(16, 16));
	if (!m_PanelImages.Load(IDB_PANEL_IMAGE))
	{
		TRACE0("Failed to load panel images\n");
		return -1;
	}

	CMFCRibbonCategory* pCategory = m_wndRibbonBar.AddCategory(_T("Home\nh"), IDB_FILESMALL, IDB_FILELARGE);

	CMFCRibbonPanel* pPanelDraw = pCategory->AddPanel(_T("Object"), m_PanelImages.ExtractIcon(1));

	pPanelDraw->Add(new CMFCRibbonButton(ID_SEL_POINTER, _T("Select\ns"), 0));
	pPanelDraw->Add(new CMFCRibbonButton(ID_SEL_LINE, _T("Line\nl"), 0));
	pPanelDraw->Add(new CMFCRibbonButton(ID_SEL_POLYLINE, _T("Polyline\nl"), 0));
	pPanelDraw->Add(new CMFCRibbonButton(ID_SEL_POLYGON, _T("Polygon\ny"), 0));
	pPanelDraw->Add(new CMFCRibbonButton(ID_SEL_CIRCLE, _T("Circle\ne"), 0));
	pPanelDraw->Add(new CMFCRibbonButton(ID_SEL_ELLIPSE, _T("Ellipse\ne"), 0));
	pPanelDraw->Add(new CMFCRibbonButton(ID_SEL_RECT, _T("Rectangle\nr"), 0));
	pPanelDraw->Add(new CMFCRibbonButton(ID_SEL_TEXT, _T("Text\nn"), 0));
	pPanelDraw->Add(new CMFCRibbonButton(ID_SEL_IMAGE, _T("Image\nn"), 0));
	pPanelDraw->Add(new CMFCRibbonButton(ID_SEL_EDITBOX, _T("Edit Box\n"), 0));
	pPanelDraw->Add(new CMFCRibbonButton(ID_SEL_CHART, _T("Chart\n"), 0));

	// Add quick access toolbar commands:
	CMFCRibbonQuickAccessToolBarDefaultState qatState;

	m_wndRibbonBar.SetQuickAccessDefaultState(qatState);

	// Add elements to the right side of tabs:
	CMFCRibbonButton* pVisualStyleButton = new CMFCRibbonButton((UINT) -1, _T("Style\ns"));

	pVisualStyleButton->SetMenu(IDR_THEME_MENU, FALSE , TRUE );

	pVisualStyleButton->SetToolTipText(_T("Modify Visual Style"));
	pVisualStyleButton->SetDescription(_T("Choose one of the following looks:\r\nMS Office 2003 or MS Office 2007"));
	m_wndRibbonBar.AddToTabs(pVisualStyleButton);

	m_wndRibbonBar.AddToTabs(new CMFCRibbonButton(ID_APP_ABOUT, _T(""), m_PanelImages.ExtractIcon(0)));

	return TRUE;
}

생성된 리본바에 기초객체 버튼에 기능을 인터페이스 해주기 위하여 enuSetSelectToolBar(int iSel)함수에 생성하고자하는 객체의 타입을 전달합니다. 이미지의 객체를 생성하는 인터페이스 함수는 enuCreateImage()함수를 이용합니다. 자세한 코드는 샘플 프로젝트의 GUIEditorView.cpp 에 있습니다.


CGUIEditorView* g_GUIEditor = NULL;
void SelectToolBarCallBack(int iSel)
{
	if (g_GUIEditor)
		g_GUIEditor->SetSelectToolBar(iSel, false);
}

void CGUIEditorView::SetSelectToolBar(int iSel, bool bFlag)
{
	m_iSelToolbar = iSel;
	if (!bFlag)
		return;
	enuSetSelectToolBar(iSel);
}

void CGUIEditorView::OnInitialUpdate()
{
	CView::OnInitialUpdate();

	g_GUIEditor = this;

	// Create Project
	m_pProject = enuCreateProject();

	// Editor Toolbar status callback function set.
	enuSetCallBackSelectToolBar(SelectToolBarCallBack);
                                     .
                                     .
                                     .
                                     .
}




메뉴 연결 수행만으로 그래픽의 기초객체를 추가, 제거, 편집할 수 있는 응용 프로그램이 개발되었습니다. 

마우스 휠을 이용한 스케일 조정, 회전, 사이즈 조정이 가능합니다. 



enuSpace SDK를 이용하면 그래픽 저작기 뿐만 아니라 그래픽 컴포넌트로서 디테일하게 제어하지 못한 그래픽 제어 기능을 제공합니다. 

다음 강좌 제2강에서는 생성된 객체의 속성을 연결하기 위한 속성바 생성 및 속성변경시 객체의 속성 변경 이벤트에 대하여 설명 드리도록 하겠습니다. 







enuSpace professional 2016 기준

void PlaySound method (enuSpace in lua script)


enuSpace in lua lua function


void PlaySound(

[in] string Filename

};


Parameters

Filename[in]

Type:string

wav 파일 이름을 사용


Return value

Type : bool


Remarks

루아 스크립트에서 본 함수를 사용하는 경우, windos api PlaySound 함수 호출 수행



Examples


enuSpace script editor


function onmousedown()

PlaySound("Alarm02.wav")

end

'enuSpace for lua API' 카테고리의 다른 글

enuSpace :: ShellExecute()  (0) 2016.01.15

+ Recent posts