enuSpace for mars(2017)에서 확장용 web 모듈 사용하기


enuSpace for mars(2017)버젼부터 확장용 web 모듈을 추가하여 개발할 수 있는 기능을 제공합니다. 본 내용은 개발자에게 web 모듈 확장 프로젝트 사용 방법에 대하여 설명합니다.

확장 웹모듈 인터페이스 구조도

동작 방법 : enuSpace가 설치된 동일한 디렉토리에 제공되는 샘플용 프로젝트(WebExtension.sln)를 컴파일하여 WebExtension.dll 생성, enuSpace의 실행 프로그램 위치에 복사하여 붙여넣기를 수행합니다. 

enuSpace 프로그램을 실행하고 기존의 프로젝트를 로드하거나 신규 프로젝트를 생성후 웹 서버 시작 버튼을 클릭하면 enuSpace프로그램에서 확장 WebExtension.dll 파일을 로드합니다.  

사용 방법 : 기본 제공되는 RASTful API 이외의 함수에 대해서는 WebExtension.dll의 Requst함수에 의하여 처리되므로, 개발자가 클라이언트에서 전달된 데이터의 데이터를 전달받아 요청된 명령에 따른 처리를 수행하면 됩니다. 

아래 기본 샘플은 사용자가 웹서버를 통하여 전달받은 데이터를 확장 모듈에서 ECHO 데이터를 반환하는 샘플이다. 

void GetParamValue(CString strInput, CString *strAttr, CString *strParam)

{

int ipos = strInput.Find('=');

if (ipos > 0)

{

CString strElement;

*strAttr = strInput.Left(ipos);

*strParam = strInput.Right(strInput.GetLength() - ipos - 1);

}

}

char* WCToMB(CString str)

{

char * temp = new char[_tcslen(str) * 2 + 1];

WideCharToMultiByte(CP_ACP, 0, str, (int)_tcslen(str) + 1, temp, (int)_tcslen(str) * 2 + 1, 0, 0);

return temp;

}

extern "C" __declspec(dllexport) void Request(WebSocketObject* pSocketObject, wchar_t* funtionname, wchar_t* contents)

{

// SAMPLE CODE

CString strParam = contents;

CString Seperator = _T("&");

int charpos = 0;

CString token;

token = strParam.Tokenize(Seperator, charpos);


// 개별 입력 속성및 값을 취득하는 SAMPLE

while (token != L"")

{

token.Trim();

CString attribute; // attribute값 취득

CString value; // value값 취득

GetParamValue(token, &attribute, &value);

token = strParam.Tokenize(Seperator, charpos);

}


// 반환값 코드.

CString strResult;

strResult.Format(L"RESULT:%s, %s" ,funtionname, contents);

char* pstr = WCToMB(strResult.GetBuffer(0));


pSocketObject->response.sendlen = strlen(pstr);

pSocketObject->response.pSendBuffer = pstr;

pSocketObject->response.connent_type = L"application/json; charset=UTF-8";

return;

클라이언트 웹 브라우져에서 주소줄에 다음과 같이 입력하였을 경우, http://127.0.0.1:8080/myfunction?dfdf=444&dfefe=999

아래 그림과 같은 결과를 획득할 수 있다. 

주) 반환값을 전달할 때 char*의 메모리 값을 동적으로 생성하였으며, 별도의 메모리 해제를 수행하지 말아야 한다. enuSpace 웹 서버모듈에서 처리가 완료되면, 메모리를 자동으로 해제를 수행하기 때문이다. 


SVG와 JavaScript를 이용한 다이나믹 심볼 제작 (온도 Gauge)


라이브러리 생성

엔유스페이스를 실행하고 Project Explorer에서 Library하위에서 Logic선택후 Add New logic Library를 선택합니다. 라이브러리 파일이름을 입력후 Create를 수행하면, 새로운 로직파일이 생성됩니다.

생성된 파일을 선택후 팝업메뉴를 이용하여 Add Node를 통하여 새로운 심볼을 생성합니다. 생성된 심볼을 디자인합니다. 디자인 객체를 이용하여 아래 그림과 같이 디자인을 수행합니다. 

각각의 객체의 속성에 id를 위 그림과 같이 설정합니다. 핀객체에 대해서는 name의 속성값을 설정합니다. 핀객체는 로직블럭과 로직블럭간의 연결선을 이용하여 연결이 가능합니다. 연결선을 이용하여 핀객체 연결시 데이터 전송 역할을 수행합니다.


심볼의 자체에 이벤트 함수를 등록합니다. _ontask()함수에 아래의 코드를 추가합니다. 입력핀의 객체 변수값을 출력핀의 객체 변수값으로 할당하는 코드입니다.

function _ontask()

--TODO Add your lua script code here

output = input

end

심볼에 입력데이터의 min, max를 정의하는 변수를 추가합니다. 

float min = 0

float max = 100

다음으로 ID_GAGUE객체를 선택하고 이벤트함수 _ontaskview()함수를 추가합니다. 이때 추가할 스크립트는 JavaScript를 이용하여 추가합니다. JavaScript를 이용하는 경우에는 웹 현시에 있어 동일한 스크립트가 동작되어 수행됩니다.

function _ontaskview()

{

//TODO Add your javascript code here

var datagap = max-min;


var data = output;

if (data < min)

data = min;

else if (data >max)

data = max;


var h = (43 * (data-min)) / (max - min);

ID_GAUGE.height = h;


ID_LABEL_VALUE.textContent = output.toString();

ID_LABEL_MIN.textContent = min.toString();

ID_LABEL_MAX.textContent = max.toString();

}

위 코드를 간단하게 보면, 출력 데이터의 값이 심볼변수를 설정한 min, max의 범위안에서 처리가 되도록 조건을 걸어줍니다. 다음으로 ID_GAUGE의 초기 Height값 43을 기준으로 출력 데이터의 실제 게이지의 높이값을 계산하여, ID_GAUGE객체의 높이값으로 치환합니다.

ID_LABEL_VALUE, ID_LABEL_MIN, ID_LABEL_MAX의 값 현시를 위한 코드를 추가합니다. 이와같은 방법으로 SVG 그래픽 과 JavaScript 코드를 이용하여 다양한 그래픽 심볼 라이브러리를 생성할 수 있습니다. 


화면 드로잉

생성된 라이브러리를 이용하여 픽쳐페이지에 적용합니다. Project Explorer에서 Picture를 선택후 Add New Picture Item 메뉴를 선택하여 픽쳐페이지를 생성합니다.

생성된 픽쳐페이지에 생성한 라이브러리를 마우스를 이용하여 드래그 & 드랍으로 객체를 생성합니다. 선택객체를 더블클릭하여 Value Table의 입력값을 조정하여 정상적으로 라이브러리가 생성되었는지 확인합니다.

입력값을 50으로 설정시 게이지바의 위치가 50의 위치하였음을 확인할 수 있습니다.

리본 메뉴의 Data/Communication에서 웹서버 기동 메뉴를 클릭하여, 웹서버를 기동한 후 웹브라우져를 통하여 제작한 픽쳐페이지가 정상적으로 현시되는지 확인합니다. 


다양한 형태의 게이지를 생성하여, 아래 그림과 같이 적용 및 활용할 수 있습니다.

enuSpace for Mars(2017)은 HMI/SCADA/DCS/IoT분야에 강력한 기능을 활용하여 적용할 수 있습니다. 


본 기술개발의 일부는 중소기업청의 창업기술개발사업의 일환으로 수행된 결과입니다.


enuSpace for Mars(2017) - 주요기능 소개 (ENU Co.ltd)


추가되는 기능


1. IoT 디바이스를 로직 심볼 형태로 제공합니다.

2. 웹 서버기능이 엔유스페이스 프로그램에서 자체 지원합니다.

3. IoT 디바이스 심볼과 로직 블럭을 이용하여 연산 및 제어처리가 가능합니다. 

4. 웹 브라우져를 통하여 로직 처리 결과 확인이 가능합니다. 


상세기능.

IoT 디바이스를 심볼로 구성하여 그래픽적인 연산처리를 수행한후 실시간 디바이스의 센서값을 웹을 통하여 현시 및 제어를 수행할 수 있습니다. 

enuSpace for Mars의 데이터 인터페이스 구성도

enuSpace for Mars는 

Raspberry PI 전용 Windows 10 IoT Core기반의 전용 응용프로그램,

Arduino의 StandardFirmata 프로그램을 설치하여 연계를 수행합니다.

디바이스 등록과정을 거친후 서버에서 모든 제어 및 모니터링을 수행합니다.

● Raspberry PI 응용프로그램을 이용한 디바이스 등록 방법

사용자 로그인 및 웹서버 주소 설정 과정

디바이스 등록 과정

디바이스 등록후 StandardFirmata를 이용한 Arduino 시리얼 통신 연결 

디바이스 심볼 객체를 이용하여 디바이스 모니터링 및 제어기 만들기.

※ 디바이스 심볼은 기 제공되는 심볼을 이용하거나, 사용자가 직접 심볼을 제작하여 등록후 사용이 가능합니다. 


● 디바이스 심볼 만들기 방법

ProjectExplorer에서 Library하위 Logic에서 신규 라이브러리 파일을 생성하고, Add Node 메뉴를 이용하여 신규 라이브러리를 생성합니다.

생성된 신규 라이브러리에 관련 이미지 또는 기본 드로잉 객체를 이용하여 심볼을 디자인 합니다. 디자인된 심볼에 외부의 데이터 인터페이스를 위한 PIN객체를 추가하고, PIN객체의 속성 name을 디바이스의 A0, A1, A2, A3, A4, A5, D0, ~, D13까지 생성합니다. 

본 단계는 사용자가 직접 제어를 위한 방법이며, 본 프로그램에서 제공되는 라이브러리를 이용하는 경우에는 별도의 작업이 필요치 않습니다.  

IoT 디바이스 라이브러리 생성 방법

라벨의 객체에 실시간 디바이스 센서값 표현하기 위해서는 신규 text 객체를 추가합니다. 추가된 객체에 javascript 함수를 추가합니다. javascript는 웹 모니터링시에 동일한 형태로 브라우져에서 현시됩니다.

텍스트 객체에 스크립트를 추가하는 방법

위 그림과 같이 ontaskview() 함수를 추가하고, textContent = A0.toString(); 코드를 추가함으로서 A0의 변수값을 text의 라벨값으로 현시하기 위한 코드를 추가합니다.

위와 같이 사용자가 다양한 형태의 게이지, 컴포넌트 등을 구성하여 라이브러리를 구성할 수 있습니다.


● 디바이스 심볼활용 방법 (픽쳐 드로잉)

ProjectExplorer에서 Picture의 하위에 Add New Picture Item 버튼을 클릭하여 새로운 픽쳐페이지를 생성합니다. 생성된 페이지에 Logic 객체와 HMI 객체를 이용하여 화면 드로잉을 수행합니다. 

IoT 디바이스 심볼 객체를 이용한 드로잉 방법

등록된 디바이스에 대하여 IoT 디바이스 심볼 객체에 대한 속성 설정을 통한 화면 연계를 수행합니다.

디바이스 심볼을 선택하고, interface 속성값을 true 설정, interface-id의 속성값을 디바이스 키값을 입력합니다. 인터페이스 설정이 완료되면 디바이스의 정보가 심볼객체를 통하여 데이터가 현시됩니다.


모든 화면 구성 및 그래픽적인 로직화면 구성이 완료되었다면 저장을 수행합니다.


● enuSpace for Mars의 웹 서버연동

위 작업이 마무리 되었으면, 엔유스페이스 프로그램이 실행된 컴퓨터의 서버주소를 브라우져를 실행하여 주소를 입력합니다.

서버의 정보가 클라이언트에 실시간 데이터가 모니터링됨을 확인 할 수 있습니다.

enuSpace for Mars(2017) 실행 화면

크롬 브라우져에서 enuSpace에 접속한 화면


본 기술개발의 일부는 중소기업청의 창업기술개발사업의 일환으로 수행된 결과입니다.

Windows 10 IoT Core, Raspberry PI, Arduino and enuSpace Platform


IoT 통합 플랫폼 연계 작업 내역 (enuSpace for mars - ver 2.0)

Raspberry PI에 윈도우즈 10 IoT Core를 설치하고 Arduino의 센서 Analog 신호를 시리얼 통신으로 입력 받아 enuSpace Platform에 http 통신을 이용하여 데이터를 받아서 처리하는 일련의 작업과정을 설명합니다.

아래 동영상은 enuSpace 통합 플랫폼 웹서버와 라즈베리 파이에 Windows 10 IoT Core App간의 연동 내용을 포함하고 있습니다.


Step1. Windows 10 iot core 설치

https://developer.microsoft.com/ko-kr/windows/iot/GetStarted

위 링크의 내용을 기반으로 단계별로 설치 절차를 진행합니다.  

Dashboad를 다운 받아 프로그램을 설치합니다.

이미지를 다운 받아서 Flash Memory에 이미지를 저장합니다.

Flash Memory를 라으베리 파이에 삽입하고 전원을 연결하면 모든 설치가 완료됩니다.

설치가 끝난후 개발자 모드 설정을 수행합니다.


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

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


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

라즈베리 파일에 Windows 10 IoT Core 를 설치, 아두이노를 연결 및 센서 2종 음향 및 플래어 센서 연결을 마무리 하였다면 아두이노 프로그램밍을 수행합니다.


Step 2. 아두이노 프로그래밍

Arduino를 USB로 연결하고 Arduino IDE에서 예제 AnalogOutSerial을 참조하여 코드를 수정하여 컴파일 및 배포를 수행합니다.


const int analogInPin1 = A0;  

const int analogInPin2 = A1; 

int sensorValue = 0;       

int sensorValue2 = 0;       

String Buffer ;

void setup() {

  Serial.begin(250000);

}

 

void loop() {

  // read the analog in value:

  sensorValue = analogRead(analogInPin1);

sensorValue2 = analogRead(analogInPin2);

 

  // print the results to the serial monitor:

  Buffer = "";

  Buffer += sensorValue;

  Buffer += ":";

  Buffer += sensorValue2;

Serial.println(Buffer);

}


Step 3. 라즈베리 파이(Raspberry PI)에 WinRT 응용프로그램을 개발(WinRT C#) 절차

Microsoft Visual Studio 2015 다운로드 사이트

https://developer.microsoft.com/ko-kr/windows/downloads

Microsoft Visual Studio 2015를 이용하여 IoT C# 프로젝트를 생성합니다.


아래 사이트에 가시면 시리얼 통신에 적합한 샘플을 구할수 있습니다.

https://developer.microsoft.com/en-us/windows/iot/samples/serialuart

위 사이트에서 샘플을 다운 받아서 간단하게 C#용으로 시리얼 통신을 수행합니다.

시리얼 통신으로 부터 전달받은 데이터를 차트에 표현하도록 하겠습니다. 

차트를 드로잉하기 위해서 nuget에 있는 https://www.nuget.org/packages/WinRTXamlToolkit.Controls.DataVisualization.UWP/

Toolkit을 이용하는 방법이 있습니다.  

Window 10 iot core 용으로 다운 받을 경우 UWP 버젼으로 다운 받아야 한다. 정상적으로 받았을 경우 xaml 파일과 cs 소스 코드를 이용하여 개발을 수행합니다. 

        <WinRT_Charting:Chart x:Name="LineChart1" Title="My Chart">

            <WinRT_Charting:LineSeries Title="T1"

                        ItemsSource="{Binding Items}"

                        IndependentValueBinding="{Binding Name}"

                        DependentValueBinding="{Binding Value}"

                        IsSelectionEnabled="True"/>

            <WinRT_Charting:LineSeries Title="T2"

                        ItemsSource="{Binding Items}"

                        IndependentValueBinding="{Binding Name}"

                        DependentValueBinding="{Binding Value}"

                        IsSelectionEnabled="True"/>

        </WinRT_Charting:Chart>


private void updateChart_Click(object sender, RoutedEventArgs e)

        {

            try

            {

                List<NameValueItem> newitems1 = new List<NameValueItem>();

                List<NameValueItem> newitems2 = new List<NameValueItem>();

 

                int num = items1.Count / 250;

                int con = 0;

                int value1 = 0;

                int value2 = 0;

                string name;

                for (var i = 0; i < items1.Count; i++)

                {

                     name = Convert.ToString(newitems1.Count);

                     newitems1.Add(new NameValueItem { Name = name, Value = items1[i].Value });

                     newitems2.Add(new NameValueItem { Name = name, Value = items2[i].Value });


                }

                ((LineSeries)this.LineChart1.Series[0]).ItemsSource = newitems1;

                ((LineSeries)this.LineChart1.Series[1]).ItemsSource = newitems2;

 

                newitems1 = null;

                newitems2 = null;

            }

            catch (Exception ex)

            {

                status.Text = ex.Message;

            }

        } 

센서값을 차트로 표현결과, 라즈베리 파이에서 그래픽 리소스를 많이 잡아먹는 WinRTXamlToolkit.Controls.DataVisualization를 이용할 경우에는 많은 양의 데이터를 표현은 어렵다는것을 확인하였습니다. 약 1000개의 데이터를 현시할 경우, 약 30초정도 소요됩니다. 아래 그림은 1000개의 데이터를 차트에 표현하여 보았습니다. 

실시간으로 데이터 표현이 어렵기 때문에, 데이터를 취득하는 버튼과 데이터 취득 종료버튼을 별도로 이용하여 데이터를 분석하는 모듈로 구성하였습니다. 

만약 실시간으로 차트를 표현하고자 한다면, Canvas를 이용하여 직접 Drawing을 수행하면 빠른 현시가 가능합니다. 


Canvas객체를 이용하 WinRT C# Chart 드로잉

private void DrawChart(Canvas canGraph, List<NameValueItem>[] pList, double axisx_min, double axisx_max, double data_min, double data_max)

        {

            canGraph.Children.Clear();


            double[] RectWall;

            RectWall = new double[4];

            RectWall[0] = 0;                // left 

            RectWall[1] = 0;                // top

            RectWall[2] = canGraph.ActualWidth;   // right

            RectWall[3] = canGraph.ActualHeight;  // bottom


            double[] RectGap;

            RectGap = new double[4];

            RectGap[0] = 30;    // left 

            RectGap[1] = 20;    // top

            RectGap[2] = 20;    // right

            RectGap[3] = 20;    // bottom


            double[] RectChart;

            RectChart = new double[4];

            RectChart[0] = RectWall[0] + RectGap[0]; // left 

            RectChart[1] = RectWall[1] + RectGap[1]; // top

            RectChart[2] = RectWall[2] - RectGap[2]; // right

            RectChart[3] = RectWall[3] - RectGap[3]; // bottom


            double fChartWidth = RectChart[2] - RectChart[0];

            double fChartHeight = RectChart[3] - RectChart[1];


            int xGridNum = 5;

            int yGridNum = 10;

            double fGridGapX = fChartWidth / xGridNum;

            double fGridGapY = fChartHeight / yGridNum;


            // 차트 그리기.

            Rectangle pChartRect = new Rectangle();

            pChartRect.StrokeThickness = 1;

            pChartRect.Fill = new SolidColorBrush(Colors.Black);

            pChartRect.Stroke = new SolidColorBrush(Colors.Yellow);

            pChartRect.Width = fChartWidth;

            pChartRect.Height = fChartHeight;

            Canvas.SetLeft(pChartRect, RectChart[0]);

            Canvas.SetTop(pChartRect, RectChart[1]);

            canGraph.Children.Add(pChartRect);


            // x축 그리기.

            int iCount = 0;

            GeometryGroup xaxis_geom = new GeometryGroup();

            for (double x = 0; x <= fChartWidth; x += fGridGapX)

            {

                LineGeometry xtick = new LineGeometry();

                xtick.StartPoint = new Point(x + RectChart[0], RectChart[3] + 5);

                xtick.EndPoint = new Point(x + RectChart[0], RectChart[1]);

                xaxis_geom.Children.Add(xtick);


                TextBlock xlabel = new TextBlock();

                int ivalue = (int)axisx_min + (int)(axisx_max - axisx_min) / xGridNum * iCount;

                xlabel.Text = ivalue.ToString();

                xlabel.FontSize = 10;

                Canvas.SetLeft(xlabel, x + RectChart[0]);

                Canvas.SetTop(xlabel, RectChart[3] + 5);

                canGraph.Children.Add(xlabel);

                iCount = iCount + 1;

            }


            Path xaxis_path = new Path();

            xaxis_path.StrokeThickness = 1;

            xaxis_path.Stroke = new SolidColorBrush(Colors.Green);

            xaxis_path.Data = xaxis_geom;

            canGraph.Children.Add(xaxis_path);


            // y축 그리기.

            iCount = 0;

            GeometryGroup yxaxis_geom = new GeometryGroup();

            for (double y = 0; y <= fChartHeight; y += fGridGapY)

            {

                LineGeometry ytick = new LineGeometry();

                ytick.StartPoint = new Point(RectChart[0] - 5, RectChart[3] - y);

                ytick.EndPoint = new Point(RectChart[2], RectChart[3] - y);

                yxaxis_geom.Children.Add(ytick);


                TextBlock ylabel = new TextBlock();

                int ivalue = (int)data_min + (int)(data_max - data_min) / yGridNum * iCount;

                ylabel.Text = ivalue.ToString();

                ylabel.FontSize = 10;

                Canvas.SetLeft(ylabel, RectChart[0] - 20);

                Canvas.SetTop(ylabel, RectChart[3] - y - ylabel.FontSize);

                canGraph.Children.Add(ylabel);

                iCount = iCount + 1;

            }


            Path yaxis_path = new Path();

            yaxis_path.StrokeThickness = 1;

            yaxis_path.Stroke = new SolidColorBrush(Colors.Green);

            yaxis_path.Data = yxaxis_geom;

            canGraph.Children.Add(yaxis_path);


            // data 그리기.

            double x1 = 0;

            double y1 = 0;

            double x2 = 0;

            double y2 = 0;

            

            int idim = 0;

            idim = pList.Length;

            if (idim > 0)

            {

                for (int i = 0; i < idim; i++)

                {

                    GeometryGroup data_geom = new GeometryGroup();


                    List<NameValueItem> newitems = pList[i];

                    double xstep = fChartWidth / newitems.Count;


                    for (int j = 0; j < newitems.Count-1; j++)

                    {

                        LineGeometry vline = new LineGeometry();


                        x1 = RectChart[0] + xstep * j;

                        y1 = RectChart[3] - fChartHeight * ((newitems[j].Value- data_min) / (data_max - data_min));

                        if (y1 < RectChart[1])

                            y1 = RectChart[1];

                        if (y1 > RectChart[3])

                            y1 = RectChart[3];

                        x2 = RectChart[0] + xstep * (j+1);

                        y2 = RectChart[3] - fChartHeight * ((newitems[j+1].Value - data_min) / (data_max - data_min));

                        if (y2 < RectChart[1])

                            y2 = RectChart[1];

                        if (y2 > RectChart[3])

                            y2 = RectChart[3];

                        vline.StartPoint = new Point(x1, y1);

                        vline.EndPoint = new Point(x2, y2);

                        data_geom.Children.Add(vline);

                    }


                    Path value_path = new Path();

                    value_path.StrokeThickness = 1;

                    if (i == 0)  

                        value_path.Stroke = new SolidColorBrush(Colors.Red);

                    else if (i == 1)

                        value_path.Stroke = new SolidColorBrush(Colors.Green);

                    else if (i == 2)

                        value_path.Stroke = new SolidColorBrush(Colors.Blue);

                    else

                        value_path.Stroke = new SolidColorBrush(Colors.Yellow);

                    value_path.Data = data_geom;

                    canGraph.Children.Add(value_path);

                }

            }

        }

위와 같이 직접 Canvas에 직접 차트를 그릴경우에는 약 3000개의 데이터를 현시하는데 있어 2~3초정도 소요됨을 확인하였습니다. 

차트를 이용하여 대용량을 현시하고자 할 경우에는 Canvas에 직접 그리는 것을 권고합니다.

Canvas를 이용하여 WinRT용 C# 차트 응용프로그램 실행 화면.


Step 4. enuSpace 서버(웹 서버)에 데이터를 연동

enuSpace for mars 버젼은 다기능 통합 소프트웨어 플랫폼입니다. enuSpace(엔유스페이스) 웹서버와 데이터를 연동하도록 하겠습니다. 웹서버에 연동시 라즈베리 파이에서 1초에 약 2700샘플링 데이터를 취득합니다. 이때 모든 데이터를 서버에 연동하는 것은 서버에 큰 부담을 안겨줄수 있습니다. 이에 1초에 2회의 대표값 데이터를 전송하도록 구성 하였습니다.

라즈베리 파이에서 Windows 10 IoT Core App에 웹 통신을 이용한 디바이스 등록, 변수 등록 페이지를 추가하여 센서값을 연결하기 용이하도록 구성하여 보았습니다. 

알람 설정과 서버에 전송 설정을 수행하는 UI도 함께 구성하였습니다. 


Windows 10 IoT Core용 WinRT C# 을 이용한 웹 통신 처리 코드는 아래와 같이 사용할 수 있습니다. 

enuSpace 서버(웹 서버)에 데이터를 전송하는 샘플 코드입니다. 

WinRT C# http request POST 전송 처리.

        public async void SendSensorData(int iVal1, int iVal2)

        {

            if (m_bSendValue)

            {

                String url = "http://169.254.60.226:8080/setvalue_package";

                var text = "{\"" + "@" + m_DeviceID + ".A0" + "\":\"" + iVal1.ToString() + "\",\"" + "@" + m_DeviceID + ".A1" + "\":\"" + iVal2.ToString() + "\"}";

                var strParam = "tagid_list=" + text;

                String response = await getResponse(url, strParam);

                status.Text = response;

            }

        } 


        private async Task<String> getResponse(String url, string data)

        {

            try

            {

                WebRequest request = WebRequest.Create(url);


                request.ContentType = "application/json";

                byte[] byteArray = System.Text.Encoding.UTF8.GetBytes(data);

                request.ContentType = "application/x-www-form-urlencoded";

                request.Method = "POST";


                using (var requestStream = await request.GetRequestStreamAsync())

                {

                    System.IO.StreamWriter writer = new System.IO.StreamWriter(requestStream);

                    writer.Write(data);

                    writer.Flush();


                    using (WebResponse response = await request.GetResponseAsync())

                    {

                        using (System.IO.Stream responseStream = response.GetResponseStream())

                        {

                            System.IO.StreamReader reader = new System.IO.StreamReader(responseStream);

                            String answer = reader.ReadToEnd();

                            return answer;

                        }

                    }

                }

            }

            catch (Exception ex)

            {

                status.Text = ex.Message;

                return "";

            }

        }

웹 서버에 POST 명령으로 데이터를 전송하기 위해서 WebRequest를 이용한다. 그리고 비동기식 처리를 통하여 데이터 취득에 영향을 최소화 합니다.


Step 5. enuSpace 통합 플랫폼을 이용하여 데이터 현시를 위한 픽쳐 화면을 구성합니다. 

enuSpace 통합 플랫폼에서 제공하는 웹 서버를 구동하고, 라즈베리 파이의 응용프로그램을 통하여 디바이스 추가 및 변수 추가를 수행합니다.

라즈베리 파이의 응용 프로그램에서 추가한 디바이스와 변수 정보를 DB 관리자를 통하여 확인하실수 있습니다.

라즈베리 파이의 응용 프로그램으로부터 주기적으로 데이터 들어오는 확인합니다. 정상적으로 데이터가 전달되는 값을 확인하였다면, 픽쳐를 생성하고 아날로그 Value와 알람 Value값을 차트를 추가하여 현시합니다.

차트는 시리즈 2개를 추가하고, 각각의 DB Tag 정보를 연결을 수행하면 아래 그림과 같이 센서 아날로그 신호 값을 실시간 데이터로 확인 할 수 있습니다.

아래 그림은 라즈베리파이에서 전송한 센서 데이터가 enuSpace 서버에서 현시되는 결과의 모습입니다.


추가 팁 

Windows IoT Core Remote Server 사용 Tip.

라즈베리 파이 응용 프로그램을 리모트 컨트롤을 수행하기 위해서 아래 그림의 링크를 따라서, 어플을 설치후 라즈베리 파이의 IP주소를 입력하여 실행을 수행하면, 리모트 컨트롤이 가능합니다.


enuSpace for Mars를 이용한 2D, 3D Data Visualization 작업


실행 결과 동영상


샘플 Task 생성 및 등록.

* enuSpace for Mars는 뛰어난 Timing Scheduling 기능을 제공합니다. C++, Fortran 을 이용하여 생성한 dll을 정확한 타이밍 스케쥴러를 통하여 Task 연산이 가능하도록 적용하였습니다.

* 연산된 결과는 메모리 기반의 데이터베이스와 연계되어 빠른 인터페이스가 가능하도록 적용하였습니다. 

* 생성된 모델을 스케쥴링 타임 설정값을 지정합니다.


DB 등록.

간단하게 작성된 모델 변수를 DB에 등록합니다.

샘플 모델을 0~1사이의 값으로 값을 생성하여 타이밍 스케쥴러에 따라서 연산을 수행합니다.


화면 픽쳐 객체 생성.

페이지 로딩시 2D 객체를 루아 스크립트를 이용하여 동적으로 생성합니다. 생성된 객체에 데이터 바인딩을 수행할 스크립트도 같이 등록하여 줍니다.

function _onload()

local tx = 300

local ty = 200

local i = 1

local j = 1

local k = 1

local id_text

for i=1,24,1 do 

for j=1,15,1 do

id_text = string.format("ID_%d_1_%d_H", j,i)

CreateRect(id_text, 0, 0, 15, 15, 20*j+tx, 20*i+ty)

end

end


local strScript

for i=1,24,1 do 

for j=1,15,1 do

id_text = string.format("ID_%d_1_%d_H", j, i)

strScript = string.format("function _ontaskview()\nfill=GetValueColor(@CORE.flux_%d_1_%d)\nend", j, i)

RegisterLuaScriptById(id_text, "_ontaskview", strScript)

end

end

local tx = 800

local ty = 300


local k = 2

for i=1,15,1 do 

for j = 1,15,1 do

id_text = string.format("ID_%d_%d_%d", i, j, k)

CreateRect(id_text, 0, 0, 15, 15, i*20+tx, j*20+ty)

end

end

for i=1,15,1 do 

for j = 1,15,1 do

id_text = string.format("ID_%d_%d_%d", i, j, k)

strScript = string.format("function _ontaskview()\nfill=GetValueColor(@CORE.flux_%d_%d_%d)\nend", i, j, k)

RegisterLuaScriptById(id_text, "_ontaskview", strScript)

end

end

end 


페이지 로딩시 3D 객체를 루아 스크립트를 이용하여 동적으로 생성합니다. 생성된 객체에 데이터 바인딩을 수행할 스크립트도 같이 등록하여 줍니다.

function _onload()

local tx = 75

local ty = 75

local tz = 150

local i = 1

local j = 1

local k = 1

local id_text

for i=1,15,1 do 

for j = 1,15,1 do

for k = 1,24,1 do

id_text = string.format("ID_%d_%d_%d", i, j, k)

Create3DBox(id_text, 7, i*10-tx,j*10-ty,tz-k*10)

end

end

end

local strScript

for i=1,15,1 do 

for j = 1,15,1 do

for k = 1,24,1 do

id_text = string.format("ID_%d_%d_%d", i, j, k)

strScript = string.format("function _ontaskview()\ndiffuseColor=GetValueColor(@CORE.flux_%d_%d_%d)\nend", i, j, k)

RegisterLuaScriptById(id_text, "_ontaskview", strScript)

end

end

end

end


function GetValueColor(fValue)


fValue = fValue * 50

local color


if fValue<0 then

color = string.format("rgb(0,0,0)")

elseif fValue>0 and fValue <=5 then

color = string.format("rgb(15,75,165)")

elseif fValue>5 and fValue <=10 then

color = string.format("rgb(30,110,200)")

elseif fValue>10 and fValue <=15 then

color = string.format("rgb(60,160,240)")

elseif fValue>15 and fValue <=20 then

color = string.format("rgb(80,180,250)")

elseif fValue>20 and fValue <=25 then

color = string.format("rgb(130,210,255)")

elseif fValue>25 and fValue <=30 then

color = string.format("rgb(160,240,255)")

elseif fValue>30 and fValue <=35 then

color = string.format("rgb(200,250,255)")

elseif fValue>35 and fValue <=40 then

color = string.format("rgb(230,255,255)")

elseif fValue>40 and fValue <=45 then

color = string.format("rgb(255,250,220)")

elseif fValue>45 and fValue <=50 then

color = string.format("rgb(255,232,120)")

elseif fValue>50 and fValue <=55 then

color = string.format("rgb(255,192,60)")

elseif fValue>55 and fValue <=60 then

color = string.format("rgb(255,160,0)")

elseif fValue>60 and fValue <=65 then

color = string.format("rgb(255,96,0)")

elseif fValue>65 and fValue <=70 then

color = string.format("rgb(255,50,0)")

elseif fValue>70 and fValue <=75 then

color = string.format("rgb(225,20,0)")

elseif fValue>75 and fValue <=80 then

color = string.format("rgb(192,0,0)")

elseif fValue > 80 then

color = string.format("rgb(150,0,0)")

end

return color

end







엔유스페이스 소개 자료 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

enuSpace professional 2016 기준

void ShellExecute method (enuSpace in lua script)


enuSpace in lua function


void ShellExecute(

[in] string Operation,

[in] string File,

[in] string Parameters,

[in] string Directory,

};


Parameters

Operation[in]

Type:string

The set of available verbs depends on the particular file or folder. Generally, the actions available from an object's shortcut menu are available verbs. The following verbs are commonly used:


edit

Launches an editor and opens the document for editing. If File is not a document file, the function will fail.


explore

Explores a folder specified by File.


find

Initiates a search beginning in the directory specified by Directory.


open

Opens the item specified by the File parameter. The item can be a file or folder.


print

Prints the file specified by File. If File is not a document file, the function fails.


File[in]

Type:string

A pointer to a null-terminated string that specifies the file or object on which to execute the specified verb. To specify a Shell namespace object, pass the fully qualified parse name. Note that not all verbs are supported on all objects. For example, not all document types support the "print" verb. If a relative path is used for the Directory parameter do not use a relative path for File.


Parameters[in]

Type:string

If File specifies an executable file, this parameter is a pointer to a null-terminated string that specifies the parameters to be passed to the application. The format of this string is determined by the verb that is to be invoked. If File specifies a document file, Parameters should be NULL.


Directory[in]

Type:string

A pointer to a null-terminated string that specifies the default (working) directory for the action. If this value is NULL, the current working directory is used. If a relative path is provided at File, do not use a relative path for Directory.



Return value

Type : void


Remarks

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



Examples


enuSpace script editor


function onmousedown()

ShellExecute("open", "http://enuspace.tistory.com", "", "")

end



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

enuSpace :: PlaySound()  (0) 2016.01.15

enuSpace professional 2016 기준

enuSpace 편집기 스크립트 사용자 함수 호출 (lua script)


스크립트 내에서의 다른 함수 실행 


같은 객체 내의 함수 실행


각 객체는 다른 여러 개의 함수를 포함할 수 있으며 예시로 사용된 것처럼 직접 함수 이름을 호출할 수 있다.

다음 그림에서 GetColor함수는 같은 사각형 객체 내에 있으며 onmousedown함수에서 사용된 예이다.





이웃 객체 내의 함수 실행


각 객체에 함수는 이웃하는 다른 객체의 함수를 호출할 수 있다.

다음 그림에서 GetColor함수는 같은 사각형 객체 내에 있으며 onmousedown함수에서 사용된 예이다.



다음 그림은 "빨강"이라는 텍스트 객체에 SetFontSize함수를 이용하여 fonts-size를 바꾸는 함수를 만들고 이웃한 객체인 사각형 객체의 마우스다운 이벤트 함수를 이용하여 실행하는 함수 예시이다. 사각형 객체는 마우스를 클릭하여 index 값을 바꾸고 인덱스 값에 따라 이웃한 객체인 ID_TestRed 객체의 font-size를 바꾼다.




Lua Script 함수 실행


각 객체는 자식객체의 함수, 상위객체의 함수 페이지 함수, 전역 함수, 인터페이스 함수, 루아스크립트 함수 등을 실행할 수 있는데 실행되는 순서는 다음과 같다.

- 같은 객체 내의 함수

- 자식 객체의 함수

- 이웃 객체의 함수

- 상위 객체의 함수

- 페이지 함수

- 전역함수

- 인터페이스 함수

- .루아스크립트 함수

우선 순위는 같은 객체 내의 함수가 가장 높고 루아스크립트 함수가 가장 낮다. 자식 객체의 함수를 실행하기 위해서는 자식객체 id.함수 이름으로 실행해야 하며 자식객체에서 찾지 못하면 이웃 객체에서 찾는데 이웃객체에도 없으면 차례로 우선순위가 높은 순으로 찾는다. 따라서 우선 순위가 낮은 함수를 사용하려면 같은 이름의 함수는 우선 순위가 낮은 함수를 찾을 때까지 존재하지 않아야 한다. mean 함수는 테이블을 인수로 받아 테이블 내의 모든 값을 더해서 테이블의 필드 개수로 나누어 평균값을 구한 후 그 값을 반환한다. 다음 그림은 mean 전역함수를 선언한 예시이다.




다음 그림은 전역함수 mean 함수를 이용해서 onmousedown에 의해 바뀌는 index 값을 각 테이블의 필드 값에 더하고 테이블의 평균값을 구하는 전역함수 mean을 이용해서 평균값을 구해서 텍스트 객체(ID_TextRed)의 text 에 문자열을 할당하는 onmousedown함수 예제와 그 실행된 상태를 표시하는 예시이다.





다른 함수를 실행함으로써 바뀐 값을 그 후에 사용하는 방법


다른 함수를 실행함으로써 전역 변수나 다른 기타의 변수가 바뀐 상태의 것을 현재의 스크립트 함수에서 다시 사용하고자 할 때 값을 다시 가져오는 GetValue(변수이름) 을 사용하여야 하며 그냥 사용할 시는 변경된 값이 적용되지 않는다.

다음 그림은 스크립트 내에서 index의 값을 사용하는 예시를 보여준다. IncreaseIndex함수는 index값을 1씩 증가시키므로 IncreaseIndex함수가 실행된 후에는 index 값이 1이 증가되어 있으나 스크립트 내에서는 아직 이전 값을 가지고 있다. 변경된 값을 가져오기 위해서 GetValue(index)를 사용하여 현재의 값을 가지고 와서 사용한다.










+ Recent posts