2015년 1월 정보분과 겨울 심화탐구 - javamath.com · 2015-01-05 · (1) 먼저 pc...

60
2015년 1월 정보분과 겨울 심화탐구 목표: 라즈베리 파이와 아두이노 등을 이용하여 거북명령 프로그램 (스크래치, snap 등) 을 통해 원격으로 조정할 수 있는 거북 로봇을 만드는 배경을 탐구한다. 다음 사이트에서 필요한 지식을 얻는다. 라즈베리 한글 자료 : http://www.rasplay.org/?page_id=6911 http://opensource.kofac.re.kr/index.do snap 거북로봇 : https://github.com/MrYsLab 의 xi

Upload: others

Post on 24-Jun-2020

0 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: 2015년 1월 정보분과 겨울 심화탐구 - javamath.com · 2015-01-05 · (1) 먼저 PC 윈도우에 node.js 를 설치하고 아두이노 조작활동을 한다 (2) 다음,

2015년 1월 정보분과 겨울 심화탐구 목표: 라즈베리 파이와 아두이노 등을 이용하여 거북명령 프로그램 (스크래치, snap 등) 을 통해 원격으로 조정할 수 있는 거북 로봇을 만드는 배경을 탐구한다. 다음 사이트에서 필요한 지식을 얻는다.

라즈베리 한글 자료 : http://www.rasplay.org/?page_id=6911 http://opensource.kofac.re.kr/index.do

snap 거북로봇 : https://github.com/MrYsLab 의 xi

Page 2: 2015년 1월 정보분과 겨울 심화탐구 - javamath.com · 2015-01-05 · (1) 먼저 PC 윈도우에 node.js 를 설치하고 아두이노 조작활동을 한다 (2) 다음,

https://github.com/MrYsLab/xi

http://blog.derivatived.com/posts/Control-Your-Robot-With-Node.js-Raspberry-PI-and-Arduino/

=== 거북로봇을 Node.js 프로그래밍으로 Raspberry PI and Arduino 으로 조종 ===

(1) 먼저 PC 윈도우에 node.js 를 설치하고 아두이노 조작활동을 한다(2) 다음, 라즈베리파이에 node.js를 설치하고, 아두이노 거북로봇을 조작한다(3) 결국, 스마트폰으로 거북로봇에 접근하여 사물인터넷 환경을 만든다.

Page 3: 2015년 1월 정보분과 겨울 심화탐구 - javamath.com · 2015-01-05 · (1) 먼저 PC 윈도우에 node.js 를 설치하고 아두이노 조작활동을 한다 (2) 다음,

http://www.youtube.com/watch?v=8s2--hfsJDY#t=1181 (노드 아두이노 불켜기)

1. node.js, with npm (Node Packaged Modules)wget http://node-arm.herokuapp.com/node_latest_armhf.debsudo dpkg -i node_latest_armhf.deb

2. Install node modules:npm install socket.io express johnny-fivesocket.io - communication between browser and node serverjohnny-five - Arduino controlexpress - web page formatting

3. Install "StandardFirmata" on the ArduinoIn the Arduino IDE: File > Examples > Firmata > StandardFirmata

Node ServerTo start with, we need to set up a Node.js server to facilitate communication between the web browser and Arduino. We're also going to use Express.js as a supporting web framework.

First step is to create a new server.js file and type in preliminary code for a node server.

// Initialize express and servervar express = require('express')var app = express() , server = require('http').createServer(app);

// Access server through port 80server.listen(80);

// Set '/public' as the static folder. Any files there will be directly sent to the viewerapp.use(express.static(__dirname + '/public'));

// Set index.html as the base fileapp.get('/', function (req, res) {

Page 4: 2015년 1월 정보분과 겨울 심화탐구 - javamath.com · 2015-01-05 · (1) 먼저 PC 윈도우에 node.js 를 설치하고 아두이노 조작활동을 한다 (2) 다음,

res.sendfile(__dirname + '/index.html');});

Then, create a index.html in the same folder and put in some basic HTML code. Start up the node server with node server.js and visit the address using a web browser. You should see the contents of index.html.

In some cases, only administrators can run code that uses low ports (ie: 80). So sudo node server.js might be necessary instead.

============== Socket.io

Socket.io is a way to provide real time cross-browser communication. We'll use this to forward user actions in the browser to the Arduino. In the same server.js, add code for some basic socket.io functionality:

// Link socket.io to the previously created servervar io = require('socket.io').listen(server);

// When someone has connected to me...io.sockets.on('connection', function (socket) { // Send out a message (only to the one who connected) socket.emit('robot connected', { data: 'Connected' });

// When I've received 'robot command' message from this connection... socket.on('robot command', function (data) { console.log(data); });});Now, when server.js is running, someone can use a socket.io client to connect and send data in real-time.

========== Web Browserindex.html needs to be set up to act as a socket.io client so a web browser can be used to send commands to the node server.

<!--Add two buttons a user can click-->

Page 5: 2015년 1월 정보분과 겨울 심화탐구 - javamath.com · 2015-01-05 · (1) 먼저 PC 윈도우에 node.js 를 설치하고 아두이노 조작활동을 한다 (2) 다음,

<button type="button" id="turn-left">Turn Left</button><button type="button" id="turn-right">Turn Right</button>

<!--Using JQuery for button events--><script src="js/jquery.min.js"></script><!--Socket.io library--><script src="/socket.io/socket.io.js"></script><script> $(document).ready(function() { // Connect to the node.js server. Change the IP address to the actual node server location. var socket = io.connect('http://localhost'); // When I've received 'robot connected' message from the socket.io server... socket.on('robot connected', function (data) { console.log(data); // Send out a message to the server socket.emit('robot command', { command: 'nothing' }); });

// When the html buttons are clicked... $('#turn-left').click(function() { socket.emit('robot command', { command: turn-left }); }); $('#turn-right').click(function() { socket.emit('robot command', { command: turn-right }); }); });</script>

Socket.io automatically generates the Javascript file required by the web browser, so you don't need to place this in the public folder. In our project on github, we use Bootstrap and JQuery to boost the functionality of our web page. The Javascript libraries are placed in a public -> js folder.

========= Johnny-five

Setting Up Firmata

Page 6: 2015년 1월 정보분과 겨울 심화탐구 - javamath.com · 2015-01-05 · (1) 먼저 PC 윈도우에 node.js 를 설치하고 아두이노 조작활동을 한다 (2) 다음,

Before you can start programming your NodeBots, you will need to load Firmata onto your Arduino-compatible microcontroller:

• Download Arduino IDE• Connect your Arduino-compatible microcontroller via USB• Launch Arduino IDE and open the Firmata sketch via the menu: File

>Examples >Firmata >StandardFirmata• Select your Arduino board type (e.g. Arduino Uno) via Tools >Board• Select the port for your board via Tools >Serial Port >(the comm port of

your Arduino)• Upload the program by selecting File >Upload

If you are having trouble uploading, a full trouble shooting guide can be found here: http://ardx.org/TRBL

Running a Johnny-Five programThe Johnny-Five module has already been installed when you installed this guide, so any code examples you create within the node-ardx directory will run. If you are creating code in a different location, you will need to install the Johnny-Five module, e.g:

npm install johnny-fiveRun code examples from the terminal e.g.node code/CIRC01-code-led-a-strobe.js

Johnny-five is an Arduino framework for easier robot control. We'll use the library to translate received socket.io commands into Arduino commands. Remember to install "StandardFirmata" on the Arduino, so it can properly interpret Johnny-five from node.js. In server.js:

var five = require("johnny-five") , board, servo;

// Global storage for Arduino Servosvar arduinoServos = {};

// Initialize connection to Arduino (will crash if none is attached)board = new five.Board();

// When the connection is ready...board.on("ready", function() {

Page 7: 2015년 1월 정보분과 겨울 심화탐구 - javamath.com · 2015-01-05 · (1) 먼저 PC 윈도우에 node.js 를 설치하고 아두이노 조작활동을 한다 (2) 다음,

// Add a steering servo arduinoServos = { steering: new five.Servo({pin: 9, // Send signal through Arduino Pin #9range: [0, 180], // Servo value ranges: 0-180 (Check motors for actual range)type: "standard", // Default "standard". "continuous" for cont. rotation servosstartAt: 90, // if you would like the servo to immediately move to degreecenter: false // If true moves servo to center of range instead of starAt }) }; steering = arduinoServos.steering;

// Inject the `servo` hardware into context; allows direct command line access board.repl.inject({ s: arduinoServos });});

//... In the section: socket.on('robot command', function (data)...// Update Arduino motor values if the received command is a 'turn-left' or 'turn-right'var command = data.command;if (command == 'turn-left') { arduinoServos.steering.to(20);

board.repl.inject({ s: arduinoServos });}else if (command == 'turn-right') { arduinoServos.steering.to(160);

board.repl.inject({ s: arduinoServos });}

//...

Page 8: 2015년 1월 정보분과 겨울 심화탐구 - javamath.com · 2015-01-05 · (1) 먼저 PC 윈도우에 node.js 를 설치하고 아두이노 조작활동을 한다 (2) 다음,

Node.js 설치하고 개발환경 설정하기다운로드 하기 http://www.nodejs.org페이지에서 install 버튼을 누르면 OS에 맞는 인스톨러를 다운로드 해준다.

다음으로 installer를 실행한다.

이제 node 명령을 하면 노드가 실행된다.

우리가 흔히 웹서버를 띄운다고 하면 Apache 와 같은 웹서버 프로그램이 필요합니다. 하지만 node.js 에서는 모듈을 통해서 간단하게 웹서버를 띄울 수 있습니다. 먼저, node.js 실행을 하는 기본 확장자는 js입니다. 코드 작성도 일반 텍스트 기반에서 작성을 하고 확장자만 js 로 만들어 주면 됩니다. 편의상 윈도우에서 작업을 하도록 하겠습니다.

Page 9: 2015년 1월 정보분과 겨울 심화탐구 - javamath.com · 2015-01-05 · (1) 먼저 PC 윈도우에 node.js 를 설치하고 아두이노 조작활동을 한다 (2) 다음,

 

 설치를 끝냈으면 이제 노트패드를 불러 간단한 웹서버를 만드는 코딩을 해보자

var http = require('http');http.createServer(function(request, response) {response.writeHead(200);response.write("Hello, this is dog.");response.end();}).listen(3000);console.log('Listening on port 3000...');

이 코드를 app.js로 저장한다. 다음으로 다음과 같이 해당 파일을 실행한다.

이제 웹브라우져로 확인해보면 다음과 같이 메세지가 출력되는 것을 확인할 수 있다.

Page 10: 2015년 1월 정보분과 겨울 심화탐구 - javamath.com · 2015-01-05 · (1) 먼저 PC 윈도우에 node.js 를 설치하고 아두이노 조작활동을 한다 (2) 다음,

js 파일 만들기 :  우선 C 드라이브에 nodejs 라는 폴더를 만들었습니다. 그리고 텍스트 파일을 하나 만든 다음에 main.js 라고 이름을 만들어줍니다. 그 다음 메모장을 통해서 홈페이지에 있던 샘플 내용을 그대로 복사해서 붙여 넣어 줍니다. var http = require('http');http.createServer(function (req, res) {  res.writeHead(200, {'Content-Type': 'text/plain'});  res.end('Hello World\n');}).listen(1337, '127.0.0.1');console.log('Server running at http://127.0.0.1:1337/'); 위의 내용을 간략하게 설명을 한다면... var http = require('http'); node.js 의 장점 중에 하나가 javascript를 사용하면서 다양한 기능들이 있는 모듈을 사용할 수 있습니다. 기본적으로 제공되는 http 모듈을 사용해 간단하게 웹서버를 띄울 수 있습니다. http.createServer(function (req, res) {  res.writeHead(200, {'Content-Type': 'text/plain'});  res.end('Hello World\n');}) http 모듈을 사용해서 서버를 생성합니다. 샘플에서는 res.end 에는 화면에 나타할 내용을 표시해줍니다.  

listen(1337, '127.0.0.1');

createServer 명령 뒤에 붙는 것으로 앞에는 포트 번호, 뒤에는 주소를 적어주면 됩니다.

console.log('Server running at http://127.0.0.1:1337/');

마지막으로 console.log 는 말 그대로 로그를 보여줍니다.C에서 print 문이나 Java에서 System.out 처럼 사용하면 됩니다.

Page 11: 2015년 1월 정보분과 겨울 심화탐구 - javamath.com · 2015-01-05 · (1) 먼저 PC 윈도우에 node.js 를 설치하고 아두이노 조작활동을 한다 (2) 다음,

 실행 : 실행은 콘솔 창에서 이뤄집니다. 윈도우의 경우 시작 - 실행 - cmd를 통해서 명령 프로프트 창을 띄워줍니다.  아래 그림과 같이 main.js 파일을 작성한 위치로 이동해 줍니다. 

 실행은 별 다른 명령 없이, node 다음에 실행할 파일명을 붙여주면 됩니다. node main.js :: 실행을 하면 Server running... 메시지를 볼 수 있습니다. 

   

Page 12: 2015년 1월 정보분과 겨울 심화탐구 - javamath.com · 2015-01-05 · (1) 먼저 PC 윈도우에 node.js 를 설치하고 아두이노 조작활동을 한다 (2) 다음,

우선 “web_server.js”라는 파일을 만들고 아래의 코드를 작성 후 저장하자.

var http = require("http");var server = http.createServer(function(request, response) { response.writeHead(200, {"Content-Type": "text/html"}); response.write("<!DOCTYPE \"html\">"); response.write("<html>"); response.write("<head>"); response.write("<title>Hello World Page</title>"); response.write("</head>"); response.write("<body>"); response.write("Hello World!"); response.write("</body>"); response.write("</html>"); response.end();});server.listen(80);console.log("Server is listening");

이 서버를 구동시키려면 아래의 명령어를 실행해라. 정상적으로 실행이 된다면 “Server is listening”이라는 메시지를 보게될 것이다. 예제의 서버가 HTTP의 표준 포트인 80번 포트에 바인딩하고 있다는 것에 주목하자. 이 포트가 시스템에서 이미 사용중이거나 제한되어 있다면 에러가 발생할 것이다.$ node web_server.js

다음은 웹 브라우저를 사용해서 서버에 연결해 볼 차례이다. 원하는 브라우저를 실행하고 다음 링크 중 하나를 직접 연결한다. 네트워크 측면에서 localhost(및 로컬호스트의 IP인 127.0.0.1)는 현재 사용중인 시스템을 가르킨다. 브라우저가 “Hello World!”라고 보여주면 정상인 것이다.http://localhosthttp://127.0.0.1

Page 13: 2015년 1월 정보분과 겨울 심화탐구 - javamath.com · 2015-01-05 · (1) 먼저 PC 윈도우에 node.js 를 설치하고 아두이노 조작활동을 한다 (2) 다음,

 Module모듈은 개념은, 다른 파일에서 모듈을 불러다 쓸 수 있는 일종의 라이브러리 개념이다. java의 import되는 다른 클래스나 C에서 #include 되는 라이브러리의 개념을 생각하면 된다. 모듈은 파일 단위로 구현되는데, export를 이용하여, 외부에 노출된다. 마치 java class의 public method 와 같은 개념으로 생각하면 된다. 해당 파일에 있는 함수라도 exports를 하지 않으면, 외부에서 호출할 수 없다. (일종의 java class의 private과 같은 개념). Hello.js 파일에 hello라는 함수가 있고, 이를 다른 파일에서 불러쓰고 싶다면, Hello.js 파일에서 다음과 같이 정의한 후

var hello = function(){...}exports = hello;

이 hello 함수를 사용하고자 하는 파일 (예를 들어 app.js에서) require 를 이용해서 모듈을 불러오고, 호출해서 사용한다.

var hello = require('./Hello');hello();

require에는 사용하고자 하는 모듈의 파일명을 “.js” 확장자를 제외하고 서술한다. 모듈에서 exports 될 수 있는 것은 함수와 자바스크립트 객체가 된다. 위의 예는 함수 형태를 이용하여 모듈을 사용하는 경우인데, 만약에 객체형으로 export 하고 싶다면 export하는 파일에서는

exports.hello = function(){...}

로 export하고 불러 사용하는 쪽에서는

var h = require('./Hello');h.hello();

형태로 호출한다.

Module의 경로앞의 예에서는 “./Hello”로 Hello.js에서 .js를 제거하고 서술하였으며, 앞에 “./”를 이용하여 경로를 서술하였다. 파일의 경로를 아래와 같이 서술할 수 있는데,

varhello = require('Hello'); 이 경우 node.js는 현재 실행 디렉토리를 먼저 찾고 없으면, 애플리케이션 디렉토리의 하위디렉토리인 /node_modules/ 라는 디렉토리를 찾는다.

Page 14: 2015년 1월 정보분과 겨울 심화탐구 - javamath.com · 2015-01-05 · (1) 먼저 PC 윈도우에 node.js 를 설치하고 아두이노 조작활동을 한다 (2) 다음,

이 디렉토리는 node의 모듈을 저장하는 디렉토리이다. 만약에 이 디렉토리에서 찾지 못하면, 하위 디렉토리의 /node_modules/ 디렉토리를 찾게 된다. 예를 들어서 애플리케이션 디렉토리가 /home/terry/myapp 인 경우, /home/terry/myapp/node_modules를 먼저 찾고 없으면 다음과 같은 순서로 찾게 된다.

� /home/terry/node_modules

� /home/node_modules

� /node_modules

 

 

Module의 종류Native Module과 javascript 모듈node.js는 엔진은 C++로 짜야져 있고, 그 위에서 동작하는 애플리케이션은 javascript로 구현된다. 그래서 모듈도 두 가지 타입을 가지고 있다. C++/C로 된 모듈을 Native 모듈이라고 하고, Javascript로 된 모듈을 javascript 모듈이라고 한다. Javascript 모듈의 경우, 설치시에 파일이 복사되는 수준에서 설치가 되지만, native module의 경우에는 컴파일을 하면서 설치를 한다. (마치 Linux의 make install 처럼). 그래서 반드시 C/C++ 컴파일러가 설치되어 있어야 한다. Linux에서는 GCC, Windows에서는 Visual Studio Expess(무료)등을 설치하면 된다.

Global Module과 Local Module다음으로 Global Module과 Local Module이라는 개념을 가지고 있는데, Global Module은 시스템내에 설치된 모든 node.js 프로그램들이 참조할 수 있는 전역 모듈이다. 윈도우즈의 경우 디폴트로 ${user_home}/AppData/Roaming/npm/node_module 디렉토리에 설치된다.또는 환경 변수 NODE_PATH에 그 경로를 다음과 같이 지정할 수 있다.NODE_PATH=C:\Users\terry\AppData\Roaming\npm\node_moduleLocal Module의 경우 application 디렉토리의 /node_module 디렉토리에 설치되며, 해당 애플리케이션만 그 모듈을 참조할 수 있다.

기본 모듈과 확장 모듈node의 모듈에도 node 설치시에 기본적으로 설치되는 모듈과, 추가로 설치해야 하는 확장 모듈이 있다. 기본 모듈은 http 프로토콜 핸들링이나, file system, event, cluster,TLS/SSL와 같은 암호화 등의 모듈이 있고, 확장 설치로는 웹 개발 프레임웍인 express등이 있다. 기본/확장 모듈에 대해서는 https://github.com/joyent/node/wiki/modules를 참고 바란다.

NPMnpm은 node package manager의 약자로, 앞서 설며한 모듈들에 대한 설치 및 의존성을 관리해 주는 도구이다. 마치 Linux의 rpm이나 Python의 pip 처럼 설치를 하면, repository에

Page 15: 2015년 1월 정보분과 겨울 심화탐구 - javamath.com · 2015-01-05 · (1) 먼저 PC 윈도우에 node.js 를 설치하고 아두이노 조작활동을 한다 (2) 다음,

서 해당 모듈을 읽어다가 설치를 해주며, java의 maven처럼 package.json 이라는 파일에 (pom.xml과 비슷한 역할을 함) module간의 dependency (의존성)에 따라서 의존성이 있는 모듈을 같이 설치한다. node.js 가 JavaScript로 개발이 가능하기 때문에 새로운 언어를 배워야할 부담이 적습니다. 하지만, 우리가 흔히 알고 있는 JavaScript로 모든 것을 개발할 수 있을까? 라고 물어보면 답은 No! 위와 같이 JavaScript 만으로 해결하지 못하는 문제들을 지원하는 모듈로 통해서 해결할 수 있다면, 조금 더 쉽게 프로그래밍이 가능할 것입니다. node.js 에서는 위와 같이 JavaScript 만으로 구현하기 힘든 부분을 모듈로서 해결할 수 있습니다. 

  npm 란? Node Packaged Modules 의 약자가 npm입니다. 말 그대로 Node.js에서 사용되는 모듈을 패키지로 모아놓은 곳이예요. 내가 사용하고자 하는 필요한 패키지를 찾아서 다운로드 받으면 사용할 수 있도록 되어 있습니다. node.js 초기 버전에서는 별로로 설치해줘야 했지만, 지금은 node.js 가 설치되면서 자동으로 npm 이 설치가 됩니다. 지금은 node.js 와 같이 설치되므로 npm -v 명령으로 확인하면 됩니다. 

 예전에 명령으로 설치하던 npm 버전은 1.0 이었는데, 최근엔 1.1 로 업데이트 되면서 아키텍쳐가 많이 바뀌었다고 합니다. 혹시 예전 버전을 쓰시는 분 있으면 지금 node.js 버전과 맞지 않아서 에러가 발생할 수도 있습니다. 홈페이지 주소 : https://npmjs.org 

Page 16: 2015년 1월 정보분과 겨울 심화탐구 - javamath.com · 2015-01-05 · (1) 먼저 PC 윈도우에 node.js 를 설치하고 아두이노 조작활동을 한다 (2) 다음,

 === npm 명령어 === 윈도우에서 npm help라고 입력하면 npm 관련 명령어를 볼 수 있습니다. 

 위의 명령을 참고해서 'npm help 명령어'를 입력하면 사용법을 볼 수 있습니다. 예) npm -h install 

 주로 사용되는 명령은 아래와 같습니다. npm install 패키지명 : 패키지 파일을 찾아서 설치를 합니다. npm list installed : 현재 설치되어 있는 패키지를 보여줍니다. npm update 패키지명 : 설치된 패키지를 최신버전으로 업데이트 합니다.

Page 17: 2015년 1월 정보분과 겨울 심화탐구 - javamath.com · 2015-01-05 · (1) 먼저 PC 윈도우에 node.js 를 설치하고 아두이노 조작활동을 한다 (2) 다음,

npm 이 어떤 것이고 사용 방법에 대해서 알아봤습니다. 주요한 명령을 설명하면.

� Ÿ   npm list {module} {-g} : 이 명령은 현재 디렉토리 아래에 설치되어 있는

확장 모듈을 리스트 해준다. {module}을 정해주면, 해당 모듈에 대한 리스트를

출력해주고, {-g} 옵션을 추가하면 global에 설치된 모듈 리스트들을 출력.

� Ÿ   npm install {-g} : npm 레파지토리 (maven 레파지토리 처럼 외부에 설치되

어 있음)로부터, 모듈을 읽어서 로컬에 설치한다. –g 옵션을 적용할 경우 전역

모듈로 설치한다.

� Ÿ   npm update {module} {-g} : 설치된 모듈을 최신 버전으로 업데이트 한다.

� Ÿ   npm remove {module} {-g} : 설치된 모듈을 삭제한다.

� Ÿ   npm info {module} : 해당 모듈의 의존성, 모듈명등 상세 정보를 출력한다.

� Ÿ   npm init : 이 명령어를 수행하면 interactive prompt 모드를 통해서

 package.json 파일을 만들기 위한 사용자로부터 받아서, package.json 파일을

생성해준다.

package.json 파일package.json은 maven의 pom.xml과 같은 역할을 한다. 모듈에 대한 정보 (버전,제작자,모듈명 등) 기술을 하면서, 모듈에 대한 의존성, repository 경로등을 정의한다.

의존성 관리아래 코드는 샘플 package.json 파일로, app이라는 모듈 0.0.1 버전에 대해서 서술하였으며, 이 모듈을 사용하기 위해서는 express 모듈 3.x버전과 redis 모듈 (버전에 상관없이 최신)을 필요로 한다. 또한 모듈은 git://xxx URL로부터 읽어서 설치하도록 되어 있다.{

  "name": "app",

  "version": "0.0.1",

  "dependencies": {

    "express": "3.x",

    "redis": "*"

}

“repository”: {“type”:”git”,”url”,”git://xxxx”}

}

npm을 이용한 스크립트와 테스트 수행npm은 make나 maven 처럼 custom command를 지정하여 명령어를 수행하도록 할 수 있다. 예를 들어 node server를 start하거나, test를 수행하거나 또는 빌드(?)패키징을 하도록 설정이 가능하다. “scripts”라는 엘리먼트를 사용하면 되는데, 아래 예제는 npm start를 하면 app.js 애플리케이션으로 node.js를 실행하고, npm test를 하면, mocha 테스트 프레임웍을 수행하여,테스트를 수행하도록 하는 스크립트이다.:중략"redis": "*"

}

“scripts”: {“start”:”node app.js”,

             “test”:”mocha”}

}

Page 18: 2015년 1월 정보분과 겨울 심화탐구 - javamath.com · 2015-01-05 · (1) 먼저 PC 윈도우에 node.js 를 설치하고 아두이노 조작활동을 한다 (2) 다음,

참고Npm 메뉴얼을 보면, “config’ 엘리먼트를 정의해놓고, 여기에 환경 변수를 설정할 수 있다. 즉 db 접속 정보나, http listen 포트와 같이 환경에 따라서 변경이 되는 부분은 코드 상에 직접 넣지 않고, package.json 안에 설정해서, 이 파일만 변경을 하면 되도록 한다. 이를 통해서 개발,테스트 환경에 대해서package.json만 다르게 운영하거나, 운영 환경으로 배포시 간략하게 package.json만 변경하도록 한다. 예를 들어서 package.json에{ “config”:{“dbport”:”3306’,”dbuser”:”terry”}, ..} 라고 정해 놓으면코드내에서 http.createServer(...).listen(process.env.npm_package_config_dbport); 라고 하면, package.json에서 지정한 환경 변수를 가져다 쓸 수 있다고 한다. 사용하는 방법이 별도의 config 파일을 만들고 예를 들어 config.json으로 만들고 파일내에{ “dbport”:”3306”,

“dbuser”:”terry”}라고 해놓고var config = require(“./config.json”); 으로 부르면 바로 json 객체로 나온다.다음으로 값을 참고하려면console.log(config.dbport);console.log(config.dbuser);식으로 사용하면 된다.  버전 SemanticsModule의 버전Semantics를 살펴보자. 보통 3자리로 구성되는데 1.2.3일 경우

� 1: major version� 2: minor version� 3:patch level

이다.package.json에서 dependency에 대한 버전을 정의할 수 있는데, "dependencies" : {   "mymodule" : "1.8.1}는 1.8.1 버전에 대한 의존성을"dependencies" : {   "mymodule" : "~1" }이 의미는 : >= 1.0.0 <2.0.0"dependencies" : {   "mymodule" : "~1.8” }이 의미는 :> =1.8 <2.0.0 까지을 정하는 것인데, 설명은 했지만, node.js의 경우 한참 개발되고 있는 신생 에코 시스템이기 때문에 모듈 버전간의 변화가 심할 수 있기 때문에 되도록이면 range 방식은 사용하지 않는 것이 바람직하다.

Page 19: 2015년 1월 정보분과 겨울 심화탐구 - javamath.com · 2015-01-05 · (1) 먼저 PC 윈도우에 node.js 를 설치하고 아두이노 조작활동을 한다 (2) 다음,

회사 같은 곳에서 HTTP proxy를 사용하는 경우 해결 방법npm install 인스톨시 회사 내부 네트워크에서 사용할 경우, 회사에서 proxy를 사용하면, npm install시 proxy 를 타지 않아서 설치가 npm 설치가 제대로 동작하지 않는 경우가 있다. 이런 문제를 해결 하려면,npm 환경 변수 세팅에 http proxy 서버를 지정해주면 되는데, 지정 방법은 다음과 같다.

� npm config set proxy http://proxy.company.com:8080� npm config set https-proxy http://proxy.company.com:8080

========== node.js 에서 express 사용하기 =========== 이번에도 npm을 통해서 node.js에서 자주 사용하는 패키지 모듈을 설치해보고 사용해보는 예제를 테스트 해볼까 합니다. 웹프레임워크를 담당하는 express를 설치해보도록 합니다. 

 1. express 란? 기본적으로 node.js에서 웹 브라우저를 띄운다면 http를 통해서 웹 화면을 구성했습니다.하지만, 사용할 수 있는 기능이 단순하다보니 전문적인 웹 환경을 구성하기엔 부족한 부분이 많이 있습니다. http 예제 코드를 보면 js 파일 내에 화면을 직접 구현해야 합니다. 그렇다면 기존에 이미 만들어진 html 기반의 화면을 통채로 불러올 순 없을까요? node.js를 사용하는 서버 프로그램 따로 UI를 담당하는 웹 화면을 구성해서 따로 작업하는게 효율성을 따져봐도 좋을 거 같습니다. 이렇게 MVC 모델로 구성을 하게 되는데 이런 것을 직접 구현하기 보다는 만들어진 모듈이 있다면 편할 겁니다. node.js 에서는 이러한 웹프레임워크로 express를 많이 사용하는 편입니다.  2. express 설치 먼저 express 홈페이지에 접속하면 기본적인 설명과 샘플을 볼 수 있습니다. 홈페이지 : http://expressjs.com/ 아래 그림은 첫 페이지 화면입니다. 

Page 20: 2015년 1월 정보분과 겨울 심화탐구 - javamath.com · 2015-01-05 · (1) 먼저 PC 윈도우에 node.js 를 설치하고 아두이노 조작활동을 한다 (2) 다음,

 여기서 중요한 건 작게 보이는 3.0.0입니다. node.js 가 아직 개발 중인 단계로 모듈들 또한 자주 업데이트가 됩니다. 그래서 express를 자료를 검색해서 예제를 해보다보면 안되는 경우가 많이 있습니다. express가 3.0.0 으로 업데이트 되면서 과거 버전과 사용법이 약간 달라져서 인터넷에서 검색된 결과대로 해도 안될 수 있습니다. 이 문서 또한 나중에 express 가 버전업 되면 사용법이 달라질 수 있습니다. 우선 설치를 하려면 npm을 사용하면 됩니다. 지난번과 같이 윈도우 환경에서 작업을 했으며, C 드라이브에 nodejs 라는 폴더를 만든 후에 작업을 진행하였습니다.  아래와 같이 명령을 입력합니다. c:\nodejs> npm install express 아래 그림과 같이 npm 패키지를 관리하는 곳에서 express 정보를 가지고 파일을 다운로드 하게 됩니다. 

  3. 테스트 프로그램 작성 node.js에서 html 코드를 직접 작성하지 않고, 미리 만들어진 html 의 정보를 그대로 가져와서 출력해보도록 하겠습니다. html 파일의 이름은 express.html입니다. 테스트를 위해서 express.js 파일을 만들었습니다. 

Page 21: 2015년 1월 정보분과 겨울 심화탐구 - javamath.com · 2015-01-05 · (1) 먼저 PC 윈도우에 node.js 를 설치하고 아두이노 조작활동을 한다 (2) 다음,

var express     = require('express'),    app         = express();

app.get('/', function(req, res) {    res.sendfile(__dirname + '/express.html');});    app.listen(3000); 위와 같이 express.js 파일을 만든 후, 실행을 해보도록 합니다. c:\nodejs>node express.js 그 다음 웹 브라우저를 통해서 http://localhost:3000 으로 접속합니다.js 파일에 내용을 입력하지 않고 html파일을 읽어드려서 화면에 출력하였습니다. 

  =============  node.js 에서 express 사용하기 – 2번째 ==================== 지난번에는 웹프레임워크를 담당하는 express를 설치해보고 간단하게 적용해보았습니다.이번에는 기존에 만들어진 웹구조를 통채로 express 와 연결해보도록 하겠습니다. 기존에 만들어진 웹 구조는 그 자체로도 동작하지만, 새롭게 node.js 와 연동해서 변경을 해주려면 귀찮을 일이 될겁니다. 하지만, express에서 옵션을 추가하면 기존 웹 이미지를 그대로 node.js 위에서 사용가능합니다. 

Page 22: 2015년 1월 정보분과 겨울 심화탐구 - javamath.com · 2015-01-05 · (1) 먼저 PC 윈도우에 node.js 를 설치하고 아두이노 조작활동을 한다 (2) 다음,

1. express 옵션 지난번에 테스트를 위해서 만든 express.js 파일이 있습니다.express.html 파일을 읽어오도록 하는거였습니다. var express     = require('express'),    app         = express();

app.get('/', function(req, res) {    res.sendfile(__dirname + '/express.html');});    app.listen(3000); 이번에는 소스를 수정해서 현재 폴더내에 html 폴더 안에 있는 웹파일을 읽어오도록 하겠습니다. 예제로 쓴 파일은 jquery를 사용해서 메뉴를 만드는 항목입니다. index.html 파일이 있고, assets 안에 이미지와 각각 스타일 요소들이 있습니다. index.html 파일을 클릭해서 실행해도 화면을 보는데 문제는 없습니다. 원래 소스에서 아래와 같이 추가해주도록 합니다. __dirname 은 현재 폴더를 나타내는 node.js 요소입니다. 아래와 같이 express 관련된 옵션을 추가해줍니다. var express     = require('express'),    app         = express(),    index_dir   = __dirname + '/';

app.listen(3000);

app.set('views', index_dir);app.set('view options', { layout: false });app.use(express.static(index_dir));app.use(express.bodyParser());app.use(express.methodOverride());app.use(app.router);app.use(express.errorHandler());app.use(express.favicon()); views 는 화면에 표시할 경로를 가르킵니다. bodyParser() html에서 POST 요청 처리를 할 때 사용됩니다. methodOverride()는 request를 확인하고 bodyParser 의 요청을 받아서 채워주고 put 명령을 사용할 수 있게 합니다. errorHandler()는 예외 및 에러 처리를 합니다. router 는 express에서 불러온 어플리케이션의 라우팅을 마운트하는데 사용됩니다.

Page 23: 2015년 1월 정보분과 겨울 심화탐구 - javamath.com · 2015-01-05 · (1) 먼저 PC 윈도우에 node.js 를 설치하고 아두이노 조작활동을 한다 (2) 다음,

 2. express 실행 수정을 했으면 명령 프롬프트 창을 열고 아래와 같이 실행을 해줍니다. c:\nodejs>node express 그 다음 웹 브라우저를 통해서 localhost 의 지정된 포트 3000번으로 접속하도록 합니다. 그러면 아래와 같이 node.js 위에 기존에 만들어진 html 기반의 파일들이 동작하는 것을 확인할 수 있습니다. 

npm을 통해서 node.js에서 사용할 수 있는 패키지 모듈을 설치해보고 사용해보는 예제를 테스트 해볼까 합니다. 웹 소켓 통신에 주로 쓰이는 socket.io 의 샘플을 다뤄볼까합니다.

1. socket.io 란? 지금까지 웹 브라우저 통신을 한다고 하면 불편한 점이 많았습니다.http 프로토콜을 가지고 데이터를 주고 받거나 php에서 url을 넘겨서 데이터를 교환하고자 했는데 구현할 때 불편함을 많이 느꼈습니다. 이번에 html5 가 등장하면서 실시간 웹 소켓 통신인 Websocket을 내놓았지만, 표준화 되기까지 아직 부족한 부분이 많습니다. 현재 다양한 브라우저에서 지원을 하고 기술적으로 발달하고 있지만, 시범적으로 써볼 단계일뿐 널리 사용되고 편하게 사용되고 있지 않습니다. websocket이 아직 개발중인 단계라면 socket.io 는 node.js에서 바로 사용할 수 있는 기술입니다. 엄밀히 말하면 socket.io가 아직 표준 기술은 아니지만, javascript를 사용하면 node.js에서 외부의 다른 통신요소를 거치지 않고 실시간 웹을 구현할 수 있는 기술이라서 유용하게 쓰일 수 있습니다. node.js 에서 소켓 통신을 지원하는 모듈이 더 있지만, 가장 안정적이고 편하게 사용할 수 있는게 socket.io 입니다.  2. socket.io 설치 npm을 가지고 원하는 모듈을 설치할 수 있습니다. socket.io 홈페이지에 접속하면 기본적인 설명과 샘플을 볼 수 있습니다. 홈페이지 : http://socket.io 첫 페이지 화면입니다.

Page 24: 2015년 1월 정보분과 겨울 심화탐구 - javamath.com · 2015-01-05 · (1) 먼저 PC 윈도우에 node.js 를 설치하고 아두이노 조작활동을 한다 (2) 다음,

 

  우선 설치를 하려면 npm을 사용하면 됩니다. 편의상 윈도우 환경에서 작업을 했으며, C 드라이브에 nodejs 라는 폴더를 만든 후에 작업을 진행하였습니다.  아래와 같이 npm 명령을 입력합니다. c:\nodejs>npm install socket.io 아래와 같이 npm 패키지를 관리하는 곳에서 socket.io의 정보를 받아 다운로드 하게 됩니다. 

 

 설치가 완료되면 node_modules 이라는 폴더가 생기고 그 안에 설치한 패키지가 생깁니다.

Page 25: 2015년 1월 정보분과 겨울 심화탐구 - javamath.com · 2015-01-05 · (1) 먼저 PC 윈도우에 node.js 를 설치하고 아두이노 조작활동을 한다 (2) 다음,

 3. 서버 프로그램 작성 패키지를 설치하였으니, 서버 프로그램을 작성해볼 차례입니다. socket.io 홈페이지에 가면 HOW To USE 에 가면 아래와 같이 샘플 예제를 보여줍니다. 

 그대로 해보도록 합니다. 서버 프로그램은 node.js를 통해서 실행할 것이므로 파일의 확장자는 js 로 만들어 줍니다. C 드라이브 nodejs 폴더 아래  app.js 라는 파일을 만들어서 아래 내용을 입력해줍니다. var app = require('http').createServer(handler)  , io = require('socket.io').listen(app)  , fs = require('fs')

app.listen(80);

function handler (req, res) {    fs.readFile(__dirname + '/index.html',    function (err, data) {        if (err) {            res.writeHead(500);            return res.end('Error loading index.html');        }

        res.writeHead(200);        res.end(data);    });}

Page 26: 2015년 1월 정보분과 겨울 심화탐구 - javamath.com · 2015-01-05 · (1) 먼저 PC 윈도우에 node.js 를 설치하고 아두이노 조작활동을 한다 (2) 다음,

io.sockets.on('connection', function (socket) {    socket.emit('news', { hello: 'world' });    socket.on('my other event', function (data) {        console.log(data);    });}); node.js에서 모듈을 사용할 때는 require를 통해서 사용하고자 하는 모듈명을 적어줍니다. 실제 모듈 위치는 node_modules 아래 socket.io 이지만, node_modules는 node.js에서 자동으로 관리하기 때문에 적어주지 않고 모듈명만 적어주도록 합니다. 기본적인 웹서버를 기동하기 위해서 http를 사용해서 서버를 생성해줍니다. var app = require('http').createServer  아래 부분은 socket.io 의 가장 기본적인 함수입니다.socket.io를 활성화 하고 외부의 클라이언트에서 접속, 즉 connection을 하면 명령을 수행한다는 뜻입니다. 접속을 하게 되면 무조건 저 함수를 거치게 된다고 보면 됩니다. io.sockets.on('connection', function (socket) {}  socket.emit 는 접속한 대상에게 데이터를 전송하는 부분입니다.위의 내용에 따르면 서버에 접속한 클라이언트에게 바로 'news' 라는 내용을 전송합니다. socket.emit  아래는 데이터 부분인데, node.js 에서는 기본적으로 json 방식으로 데이터를 보냅니다. 'news', { hello: 'world' }  on 은 명령 또는 데이터를 받기 위해 대기를 하고 있는 것입니다. 예제에 따라 서버에서는 대기를 하고 있다가 클라이언트에서 'my other event' 라는 데이터를 받게 되면 함수 내용을 수행하게 됩니다. socket.on

 4. 클라이언트 프로그램 작성 서버 프로그램을 작성했으니, 클라이언트 프로그램을 작성할 차례입니다. 클라이언트 화면에 보여질 부분, 즉 웹 브라우저에 나타날 부분이라서 html 파일을 만들어줍니다.  index.html

Page 27: 2015년 1월 정보분과 겨울 심화탐구 - javamath.com · 2015-01-05 · (1) 먼저 PC 윈도우에 node.js 를 설치하고 아두이노 조작활동을 한다 (2) 다음,

이라는 파일을 만들어서 아래 내용을 입력하였습니다. <script src="/socket.io/socket.io.js"></script><script>    var socket = io.connect('http://localhost');    socket.on('news', function (data) {        console.log(data);        socket.emit('my other event', { my: 'data' });    });</script>  5. 프로그램 테스트 프로그램 테스트는 먼저 서버 프로그램을 실행해줍니다. node app.js 라고 명령합니다. 서버는 현재 대기중이기 때문에 동작을 보려면 웹 브라우저에 접속을 합니다. html5를 가장 많이 지원하는 크롬 브라우저로 웹 브라우저를 띄우고 http://localhost 로 접속을 합니다. 접속을 하면 대기하고 있던 서버에서는 'news' 데이터를 웹 브라우저에 보냅니다. 그러면 웹 브라우저에서는 'news' 라는 데이터를 받고 그에 해당하는 함수를 실행합니다. 먼저 받은 데이터를 console.log 메시지를 사용하여 출력합니다. 

 그 다음 socket.emit을 통해서 서버로 'my other event', { my: 'data' } 데이터를 보내면 'my other event'가 데이터를 받아서 { my: 'data' } 데이터를 출력합니다. 

Page 28: 2015년 1월 정보분과 겨울 심화탐구 - javamath.com · 2015-01-05 · (1) 먼저 PC 윈도우에 node.js 를 설치하고 아두이노 조작활동을 한다 (2) 다음,

void setup() {   Serial.begin(9600); // initialize the digital pin as an output. // Pin 13 has an LED connected on most Arduino boards: pinMode(13, OUTPUT); }  

void loop() {   digitalWrite(13, HIGH); // set the LED on delay(1000); // wait for a second digitalWrite(13, LOW); // set the LED off delay(1000); // wait for a second }

var isOn = false; setInterval( function(){     if( !isOn ) { // OFF면         setLED(1);     } else { // ON이면         setLED(0);     }     isOn = !isOn; }, 1000 );  function setLED(flag) {     // 뭔가 데이터를 장치로 보내는 코드가 있을꺼임

========== Node.js 로 LED 불 키기 =============

하드웨어가 준비가 되었다면, Arduino IDE와 nodeJS를 설치합니다. 설치에 대한 가이드는 패스하고, 바로 실습으로 들어가보도록 하겠습니다. 먼저 Arduino로 LED를 깜빡거리는 소스를 살펴볼텐데요, Arduino IDE를 설치하신 후, Example >1. Basis >Blink 를 선택하시면 아래와 같은 소스를 볼 수 있습니다.

위 코드는 Arduino에서 디지털 13번 핀에 전류를 1초 간격으로 줬다가 안줬다가 하는 형태로 LED를 깜빡거리게 하고 있습니다. 이걸 nodeJS에서 하려면 어떻게 할까요? Arduino와 nodeJS간에는 어떠한 연관성도 없습니다. 사실, 이 작업은 nodeJS가 아닌 ruby로도 할 수 있고, Flash의 ActionScript로도 할 수 있죠. nodeJS와 Arduino 간에 연결 방법은 여러가지가 있습니다만, 단순히 Arduino 보드를 구매 분이라면.. USB 케이블 밖에 없겠죠?다시 말해, nodeJS에서 USB Serial 통신으로 Arduino에 메시지를 보내고, Arduino에서는 보낸 메시지에 따라 LED를 켰다 껐다 하면 되겠죠. 이제 Arduino를 제어하는 주체가 nodeJS 쪽이 되야하기 때문에, 아래와 같이 JS 코드가 작성 될 것입니다.

Page 29: 2015년 1월 정보분과 겨울 심화탐구 - javamath.com · 2015-01-05 · (1) 먼저 PC 윈도우에 node.js 를 설치하고 아두이노 조작활동을 한다 (2) 다음,

}

1234567891011121314151617181920212223

void setup() {  Serial.begin(9600); // initialize the digital pin as an output. // Pin 13 has an LED connected on most Arduino boards: pinMode(13, OUTPUT); Serial.println(“hello”);}  void loop() {  int incomingValue = 0;           // nodeJS에서 보낸값   if( Serial.available() >0 ) {  // 뭔가 입력값이 있다면     incomingValue = Serial.read();   }    if( incomingValue == 49 ) {     // 값이 '1' 이면     digitalWrite(13, HIGH);        // LED를 켠다.   }    if( incomingValue == 48 ) {     // 값이 '0' 이면     digitalWrite(13, LOW);         // LED를 끈다.   } }

이제 setLED만 완성하면 되겠네요! 가만, Arduino쪽에서도 기존의 Blink 코드를 바꿔줘야할 것인데… 일단, nodeJS에서 setLED에 1과 0을 줬기 때문에 Arduino쪽에서도 마찬가지로 ‘1’을 보내면 LED가 ON, ‘0’을 보내면 LED가 OFF라고 합시다. 여기서 ‘1’ 또는 ‘0’이 되는건 이유는 없고, 단순히 데이터 교환을 위한 약속이라고 보시면 됩니다. 뭔가 프로토콜이 정해진것 같으니.. Arduino쪽 loop() 함수 코드를 다음과 같이 수정합니다.

자, 이젠 nodeJS쪽에서만 잘 보내면 되겠네요 :D 근데, 어떻게 보낼까요? OS에서는 Device File이라는게 있는데요, 간단히 말해 장치가 가상의 파일과 1:1로 연결되어 입/출력을 주거니 받거니 한다는 것입니다. 예를 들어, 마우스를 움직이면 화면에 커서가 움직이는것 처럼, 마우스와 OS간에 뭔가 서로 통신을 하는거죠. Arduino도 장치이기 때문에 컴퓨터와 나름 입/출력을 할 수 있는 뭔가가 있을껍니다. nodeJS쪽에서 Arduino에 연결하기 위해서는… 일단 Arduino가 연결된 장치를 찾아야겠죠? 앞에서 설치한 Arduino IDE를 실행해 보면 메뉴에 Tools >Serial Port 쪽에서 사용 가능한 Serial 장치를 확인할 수 있습니다. 이 하나를 nodeJS에서 사용하면 되겠습니다.

그럼… nodeJS에서 장치로 어떻게 연결할까요? 앞에서 장치가 ‘가상의 파일’로 연결되어 있다고 했으니, nodeJS File System API를 사용하면 될 것 같네요. 여기서는 Arduino가

Page 30: 2015년 1월 정보분과 겨울 심화탐구 - javamath.com · 2015-01-05 · (1) 먼저 PC 윈도우에 node.js 를 설치하고 아두이노 조작활동을 한다 (2) 다음,

123456

var fs = require('fs');   // Appending 모드('a')로 /dev/tty-usbserial1 장치를 Open fs.open('/dev/tty-usbserial1', 'a', 666, function( e, fd ) {      // 장치가 정상적으로 열리면 값을 보내야겠죠? } );

12345678

var fs = require('fs');  // Appending 모드('a')로 /dev/tty-usbserial1 장치를 Open fs.open('/dev/tty-usbserial1', 'a', 666, function( e, fd ) {      fs.write( fd, '1', null, null, null, function() {          // 장치에 '1'이 잘 보내졌을 경우     } } );

1234567891011

var fs = require('fs');  // Appending 모드('a')로 /dev/tty-usbserial1 장치를 Open fs.open('/dev/tty-usbserial1', 'a', 666, function( e, fd ) {      fs.write( fd, '1', null, null, null, function() {          // 장치에 '1'이 잘 보내졌을 경우, 연결을 닫는다.         fs.close(fd, function() {              // 연결 종료.         } );     } } );

/dev/tty-usbserial1 에 연결되어 있다고 가정합시다. 일단 장치를 열어야겠죠?

그렇다면 값은 어떻게 보낼까요? 파일을 읽고 쓰는것 처럼, 장치에 뭔가를 보내려면 파일에 기록을 하는 형태가 되면 될 것 같습니다. 여기서는 fs.write를 사용해보도록 하겠습니다. fs.write API는 아래와 같습니다. fs.write(fd, buffer, offset, length, position, [callback])일단 fd는 fs.open이 성공적으로 이뤄지면 받을 수 있겠죠?buffer에 장치에 실어보낼 값을 넣어주면 되겠네요. 나머지는 마지막 callback을 제외하고 크게 문제가 안되니 null로 처리해 봅시다.

일단 장치에 연결을 잘 했고, ‘1’을 보냈다면 LED가 켜지겠죠?혹시 안켜진다면.. Arduino IDE가 해당 장치를 사용하고 있을 수 있습니다. 닫고, 다시 실행해보세요. (그것도 아니라면.. 음.. =_=;;) LED가 잘 켜졌으니, 장치에 더 이상 보낼 값이 없겠죠? 해당 연결을 닫아줘야겠습니다. 이때는 fs.close()를 사용해 현 시점에서 연결을 종료시켜줍니다.

Page 31: 2015년 1월 정보분과 겨울 심화탐구 - javamath.com · 2015-01-05 · (1) 먼저 PC 윈도우에 node.js 를 설치하고 아두이노 조작활동을 한다 (2) 다음,

1234567891011121314

function setLED(flag) {      var fs = require('fs');        // Appending 모드로 /dev/tty-usbserial1 장치를 Open     fs.open('/dev/tty-usbserial1', 'a', 666, function( e, fd ) {         // flag가 0이 아니면 '1'을 보내고,         //        0이면 '0'을 보낸다.         fs.write( fd, flag ? '1': '0', null, null, null, function(){              fs.close(fd, function(){                  console.log('Sending ', flag);             });         });     }); }

var isOn = false; setInterval(function(){     if( !isOn ) { // OFF면         setLED(1);     } else{       // ON이면         setLED(0);     }     isOn = !isOn; }, 1000);  function setLED(flag) {     var fs = require('fs');      // Appending 모드로 /dev/tty-usbserial1 장치를 Open     fs.open('/dev/tty-usbserial1', 'a', 666, function( e, fd ) {         // flag가 0이 아니면 '1'을 보내고,         //        0이면 '0'을 보낸다.         fs.write( fd, flag ? '1': '0', null, null, null, function(){             fs.close(fd, function(){                 console.log('Sending ', flag);             });         });     }); }

여기까지 잘 따라했다면, 위에서 만든 코드를 가지고 setLED 함수를 만들어봅시다.setLED에 1을 주면 ‘1’이 전송되고, 0을 주면 ‘0’이 전송되게 하면 되겠죠?

여기까지 완성한 후, 실행을 시키면 LED가 깜빡이는 것을 볼 수 있을겁니다.

Page 32: 2015년 1월 정보분과 겨울 심화탐구 - javamath.com · 2015-01-05 · (1) 먼저 PC 윈도우에 node.js 를 설치하고 아두이노 조작활동을 한다 (2) 다음,

=========== 설치된 Node.js 의 작동 테스트 ============

일반 컴퓨터 또는 노트북을 이용 해 모니터,키보드,마우스,어댑터가 없는 상태에서 라즈베리파이와 랜케이블 하나로만 라즈베리파이를 제어 하실 수 있는 방법에 대해 공개를 해 볼까 합니다. 우선 시스템 구성도는 그림 1) 과 같습니다. 

 그림 1)* 라즈베리파이의 전원 역시 데스크탑 또는 노트북 USB Port를 이용하시어 전력공급이 가능합니다.

일단 말하자면, 다소 복잡하고 어렵다. IPv4 고정아이피, 자동으로 재설정 등등;;이번 세팅을 위해선 사전에 반드시 모니터와 마우스 키보드가 라즈베리에 붙어야한다

밑에는 연결하기 전의 모습. 오른쪽에 아무것도 뜨지 않는다.

1. 밑에 사진 보면 라즈베리랑 UTP선을 연결하니까 떳다. 

Page 33: 2015년 1월 정보분과 겨울 심화탐구 - javamath.com · 2015-01-05 · (1) 먼저 PC 윈도우에 node.js 를 설치하고 아두이노 조작활동을 한다 (2) 다음,

2. 데스크 탑 또는 노트북 IP 정보확인

● [참고] 데스크탑 컴퓨터에 라즈베리를 연결해 인터넷을 하려고 한다. 전산실 컴퓨터의 로컬 영역 연결의 아이피 주소를, 아래 화면의 오른쪽 무선 인터넷 연결을 마우스 오른쪽으로 속성을 선택하고, 로컬 영역 연결로 공유 (sharing)하고 TCP/IP에서 고정 아이피로 로컬 엉역 연결 아이피 주소로 주고, 인터넷 공유를 선택해 쓸 수 있다. 로컬 영역 연결 아이피(예를 들어, 192.168.137.1) 를 무선 네트워크 연결의 Gateway IP로 하고, 아이피 마지막 숫자가 다르도록 (예를 들어, 192.168.137.10) wireless 네트워크 아이피를 만들어 준다.

● /boot 디렉토리의 cmdline.txt에서 마지막에 ip:192.168.137.10::192.168.137.1 더한다) === Raspberry Pi Cookbook for Python Programmers 책의 내용 참고 ===

그림 1-2)

그림 1-2) 에서 ”자세히”를 클릭하여 네트워크 연결 세부정보에서 IPv4 주소를 저장해 둔다.

Page 34: 2015년 1월 정보분과 겨울 심화탐구 - javamath.com · 2015-01-05 · (1) 먼저 PC 윈도우에 node.js 를 설치하고 아두이노 조작활동을 한다 (2) 다음,

3. 이제 라즈베리를 모니터랑 키보드에 연결해서, root 경로에 있는 cmdline.txt.를 만져준다. 그런데 문제가 있음. read only라서 권한을 변경해줘야 함! sudo chmod 777 cmdline.txt

그리고 나서 끝에 add : ip=내아이피 를 써준다(참고로 입력하는게 진짜 이상하고 어려웠다).

4. 문제가 생겼다. 라즈베리를 껏다 켜거나 설정이 바뀔 때마다 2번의 IPv4 주소가 계속 바뀐다. 이러면 txt에 아이피를 계속 바꿔줘야 되는데 그러면 못쓴다...도움을 받아, 라즈베리에 ip를 고정시키고 노트북도 ip를 고정으로 쓰기로 했다.먼저 라즈베리를 아래와 같이

-1.  vi/etc/network/interfaces 에 간다.(tab 치면 자동완성)-2. 가서 ip주소를 원하는대로 바꾼다(1.1.1.1도 된다). 나는 일관성을 위해...-3. service networking restart 입력 -> 초기화-4. ifconfig로 확인 (윈도우에서나 ipconfig)

--위 사진처럼 ip와 마스크등이 나타난다. 넷 마스크도 2번 사진처럼 설정함.

Page 35: 2015년 1월 정보분과 겨울 심화탐구 - javamath.com · 2015-01-05 · (1) 먼저 PC 윈도우에 node.js 를 설치하고 아두이노 조작활동을 한다 (2) 다음,

5. 이제는 노트북도 이에 맞게 설정해준다. 169.254.90.42가 라즈베리였으니까 나는 그냥 169.254.90.43으로 바꿨다.

-1. 여기로 가서 IPv4 빨간줄 더블클릭

-2. 위처럼 세팅(이것도 그냥 쳐도 되지만 그냥그냥...)이렇게 확인버튼을 누르고 나서 실행-cmd-에서 핑을 날려보자.

라즈베리로 핑을 날렸더니 응답이 온다!! 연결이 되었다는 뜻.

Page 36: 2015년 1월 정보분과 겨울 심화탐구 - javamath.com · 2015-01-05 · (1) 먼저 PC 윈도우에 node.js 를 설치하고 아두이노 조작활동을 한다 (2) 다음,

6. putty에서 이제 해당 아이피를 설정해주고 저장~(포트 번호는 22번이 기본이다 이것 또한 바꿀 수 있다)

direct라고 이름을 지었다.

연결 성공! 완벽하다.

7. 이제 조심해야 할 점!IP를 수동으로 할당했으므로 이대로 랜선을 뽑고 인터넷을 하면 접속이 안된다(DHCP ip 주소 자동할당?) 따라서 반드시

Page 37: 2015년 1월 정보분과 겨울 심화탐구 - javamath.com · 2015-01-05 · (1) 먼저 PC 윈도우에 node.js 를 설치하고 아두이노 조작활동을 한다 (2) 다음,

자동으로 IP 주소 받기를 설정하고 꺼야한다!

=============================================================================

완료화면. ifconfig, ip route 확인.

라즈베리파이 : 유선랜(eth0) 설정Raspbian을 설치하시면 처음은 유동IP 설정법으로 되어 있습니다.변경을 위해선 두 가지(interfaces, resolv.conf) 파일을 변경 해 주어야 합니다.우선 interfaces 파일의 수정을 위해 저장되어 있는 위치를 먼저 찾아보겠습니다.

위에서 보듯 interfaces 파일은 세 곳에 위치해 있습니다. 우린 /etc/network/interfaces 만 수정하면 됩니다. 자 그럼 이제 나에게 맞는 고정IP로 변경을 해 보겠습니다.

Page 38: 2015년 1월 정보분과 겨울 심화탐구 - javamath.com · 2015-01-05 · (1) 먼저 PC 윈도우에 node.js 를 설치하고 아두이노 조작활동을 한다 (2) 다음,

sudo nano /etc/network/interfaces

# 고정 IP 설정하기 #iface lo inet loopback#iface eth0 inet dhcp 위 항목을 주석처리 후, 아래 내용을 추가 수정합니다.auto eth0iface eth0 inet staticaddress [ip주소]network [ip주소에 마지막을 0으로]netmask [서브넷마스크]gateway [기본 게이트웨이]broadcast [기본DNS서버] 수정 저장 후, 변경된 설정이 적용되도록 네트웍을 재시작합니다./etc/init.d/networking restart 현재는 내부와의 통신은 정상적으로 이루어 지도록 설정이 되어 있지만외부 인터넷이 가능하도록 /etc/resolv.conf 파일을 열어 DNS값을 추가수정합니다.sudo nano /etc/resolv.conf

이제 모든 설정이 완료 되었습니다.

Page 39: 2015년 1월 정보분과 겨울 심화탐구 - javamath.com · 2015-01-05 · (1) 먼저 PC 윈도우에 node.js 를 설치하고 아두이노 조작활동을 한다 (2) 다음,

X-window 나 wget 명령어를 사용하여 테스트 해보시기 바랍니다.

=======================================================

쉽게 생각해서 텍스트 기반으로 원격지에 접속하기 위해서는 SSH가 필수이다.

2. hostname 설정 및 SSH 서버 설치

라즈베리 파이를 설치하면 ssh 서버는 기본 옵션이 enable이라서 기본적으로 설치됩니다

만.. 혹시라도 설치하지 않도록 하신 분들은 라즈베리 옵션을 띄우셔서 옵션을 바꾸시면 됩

니다. 라즈베리 환경 설정 방법은 터미널에서 "raspi-config" 를 실행하시면 됩니다. 실행 화면에서  hostname과 ssh 사용을 위해 "8 Advanced Options"를 선택 하세요.

2.1. hostname 설정

호스트명 설정은 필수는 아니지만 라즈베리 파이를 사용하는 사용자가 2명 이상인 경우에는 별도의 호스트명을 설정해 두는것도 나쁘지는 않습니다."A2 Hostname"을 선택 합니다.

기본 호스트명은 "raspberrypi"로 설정되어 있습니다.

Page 40: 2015년 1월 정보분과 겨울 심화탐구 - javamath.com · 2015-01-05 · (1) 먼저 PC 윈도우에 node.js 를 설치하고 아두이노 조작활동을 한다 (2) 다음,

본인이 원하는 호스트명으로 변경 후 "OK" 버튼을 선택하면 끝입니다.^^;;제 경우 라즈베리 파이가 여러 개 있기 때문에 "dev4unetpi1"로 설정 했습니다.호스트명은 나중에 라즈베리 파이에 할당 된 IP대신 사용이 가능 하기 때문에각자 다른 사람들이 사용 할 것 같지 않은 이름으로 짧게 설정하시면 됩니다.(아무래도 IP주소 보다는 영문으로 된 이름이 사용하기는 더 편하겠지요^^)

2.2. ssh 설정

SSH 서버 설치를 위해 "A4 SSH"를 선택 합니다.원격에서 작업하기 위해서는 필수 작업이기 때문에 반드시 설치 하시기 바랍니다.

Page 41: 2015년 1월 정보분과 겨울 심화탐구 - javamath.com · 2015-01-05 · (1) 먼저 PC 윈도우에 node.js 를 설치하고 아두이노 조작활동을 한다 (2) 다음,

단순히 "<Enable>"를 선택하시면 됩니다.

위 처럼 "SSH server enabled" 라는 메시지가 나오면 설치된 것입니다.^^

참 쉽죠잉~

3. SSH 클라이언트(putty)

ssh 서버가 설치되었으면 ssh 서버에 접속 할 수 있는 클라이언트 프로그램이 필요한데..

리눅스의 경우 기본적으로 설치되어 있기 때문에 ssh 커맨드를 이용해서 접속 해도 됩니다

만... 윈도우즈의 경우에는 telnet은 지원해도 아쉽게도 ssh는 아직 지원하지 않습니다.

윈도우즈에서 많이 사용되는 무료 ssh 클라이언트 프로그램으로는 putty가 있습니다.

간단히 네이버에서 "putty" 라고 검색하면 쉽게 찾을 수 있습니다.

http://www.chiark.greenend.org.uk/~sgtatham/putty

PuTTY 사이트에 방문 하셨으면 "Download"를 클릭 합니다.

Putty가 기능이 많다보니 종류도 많은데 그 중 첫번째인 "PuTTY"를 다운로드 받습니다.

다운받은 putty.exe 파일을 실행 합니다.

Page 42: 2015년 1월 정보분과 겨울 심화탐구 - javamath.com · 2015-01-05 · (1) 먼저 PC 윈도우에 node.js 를 설치하고 아두이노 조작활동을 한다 (2) 다음,

Putty를 실행하면 위와 같은 화면이 나오는데...Host Name 부분에 접속 할 라즈베리 파이의 IP주소나 hostname을 적어 줍니다.참고로, 라즈베리 파이의 IP주소는 라즈베리 파이의 터미널 창에서 "ifconfig" 라고 입력하면 eth0 나 wlan0에서 확인 가능합니다.Saved Sessions에 본인이 원하는 이름을 입력 후 "Save" 버튼을 클릭 해 주세요.그래야 다음에 접속 할 때 매번 입력하지 않고 편합니다.^^

Open 버튼을 클릭하면 Host Name에 입력된 IP로 접속을 시도합니다.

만약, 해당 서버에 처음 접속하는 경우에는 위와 같은 화면이 나옵니다. SSH는 서두에 말씀드린것 처럼 보안 관련 기능이 있기 때문에 위와 같은 인증키에 대한 내용이 나옵니다. 그냥 무조건 "예~"를 선택하시면 됩니다.^^

Page 43: 2015년 1월 정보분과 겨울 심화탐구 - javamath.com · 2015-01-05 · (1) 먼저 PC 윈도우에 node.js 를 설치하고 아두이노 조작활동을 한다 (2) 다음,

인증과정을 거치면 라즈베리 파이 서버에 접속하기 위한 아이디와 비번을 물어 봅니다.

접속이 가능한 아이디와 비번을 입력하시면 됩니다. 별도의 계정을 만들지 않았으면 계정은 pi 가 기본이고, 비번은 raspberry입니다.

아이디와 비밀번호가 제대로 입력되었으면 위 처럼 라즈베리 파이에 정상적으로 로그인이

될 것입니다. 이제 모니터가 없어도 원격에서 편안하게 라즈베리 파이를 이용하시면 됩니다.^^

라즈베리파이에서 에디터를 열고 다음과 같이 코드를 입력한다

pi@raspberrypi ~ $ sudo vi hello.js

var http = require(‘http’);

http.createServer(  function (req, res) {    res.writeHead(200, {‘Content-Type’: ‘text/plain’});    res.end(‘Hello World\n’);  }).listen(8081);

console.log(‘Server running at http://localhost:8081/’);

Page 44: 2015년 1월 정보분과 겨울 심화탐구 - javamath.com · 2015-01-05 · (1) 먼저 PC 윈도우에 node.js 를 설치하고 아두이노 조작활동을 한다 (2) 다음,

그후 

pi@raspberrypi ~ $ sudo node hello.js를 실행하여 웹 서버를 가동한다.

다른 컴퓨터에서 웹브라우저를 열고 주소창에 다음과 같이 접속 URL을 입력한다http://192.168.40.10:8081/사용된 IP 주소는 라즈베리파이에 현재 할당된 IP 주소이다

Node.js 의 작동을 테스트한 결과화면

[참고] 라즈베리 동영상 강의와 강의자료 http://opensource.kofac.re.kr/edu/curriculum_list.do

위의 동영상 강의에서 아두이노 연결하고 제어하기를 실습한다.다음 주소에 라즈베리로 아두이노 조정하는 21분 동영상 강의와 자료가 있다

http://opensource.kofac.re.kr/edu/detail_view.do?aIdx=78 http://ponyfoo.com/articles/teach-yourself-nodejs-in-10-steps

Teach Yourself Node.JS in 10 Steps

IDE로 스케치를 작성한 후, Arduino를 PC에 연결하고 작성한 스케치를 전송하면 됩니다.(아두이노에서는 프로그램을 스케치라고 부릅니다.) 아래 두 함수를 적절히 작성하면 됩니다.

void setup() { // 설정 코드를 넣는 위치입니다. 딱 한 번만 실행되요.}

void loop() { // 동작 코드를 넣는 위치 입니다. 무한반복됩니다.

Page 45: 2015년 1월 정보분과 겨울 심화탐구 - javamath.com · 2015-01-05 · (1) 먼저 PC 윈도우에 node.js 를 설치하고 아두이노 조작활동을 한다 (2) 다음,

}

나도 LED 켜고 싶어요 ======== LED를 켜기 =========

LED를 위와 같이 연결하고 아래 스케치를 IDE 통해서 업로드를 하면 LED가 깜빡일껍니다./* Blink: Turns on an LED on for one second, then off for one second, */// Pin 13 has an LED connected on most Arduino boards.// give it a name:int led = 13;// the setup routine runs once when you press reset:void setup() { // initialize the digital pin as an output. pinMode(led, OUTPUT); }// the loop routine runs over and over again forever:void loop() { digitalWrite(led, HIGH); // turn the LED on (HIGH is the voltage level) delay(1000); // wait for a second digitalWrite(led, LOW); // turn the LED off by making the voltage LOW delay(1000); // wait for a second}

위 스케치를 간단히 설명하면,•setup() ◦13번 핀을 출력용으로 사용할 꺼야.•loop() ◦13번 핀에 전류를 줄꺼야. 그럼 켜지겠지?◦1초 쉬자.◦13번 핀에 전류를 안줄꺼야. 그럼 꺼지겠지?◦1초 쉬자.

실행하면 1초 주기로 계속 LED가 깜빡 거릴껍니다.위 자료는 http://arduino.cc/en/Tutorial/Blink 입니다.이제 웹을 통해 LED 켜도록 하죠. 일단 Arduino가 웹이든 어디든 누군가에게로 부터 명령을 받을 수 있게 수정해야합니다. Arduino에게 “1” 이라 외치면 LED가 켜지고, “0”이라고 외치면 LED가 꺼질 수 있도록 말이죠.

Page 46: 2015년 1월 정보분과 겨울 심화탐구 - javamath.com · 2015-01-05 · (1) 먼저 PC 윈도우에 node.js 를 설치하고 아두이노 조작활동을 한다 (2) 다음,

/* Turns on an LED on for 1 second, then off for 1 second, repeatedly. */// Pin 13 has an LED connected on most Arduino boards.// give it a name:int led = 13;// the setup routine runs once when you press reset:void setup() { // initialize the digital pin as an output. pinMode(led, OUTPUT); }// the loop routine runs over and over again forever:void loop() {int incomingValue = 0; // 보낸값을 저장하기 위한 변수 선언 if ( Serial.available() > 0 ) { // 뭔가 입력값이 있다면 incomingValue = Serial.read(); } if ( incomingValue == 49 ) { // 값이 '1' 이면 digitalWrite(13, HIGH); // LED를 켠다. }

if ( incomingValue == 48 ) { // 값이 '0' 이면 digitalWrite(13, LOW); // LED를 끈다. }}

일단 이렇게 작성하고 Arduino에 업로드를 합니다. 그리고 웹에서 Arduino를 키기 위해서는, 아두이노가 웹서버에 연결이 되어야 할 것 같네요. 그 이유는, 웹페이지에서 누군가 LED 켜기 버튼을 눌렀을 때, 그 값을 웹서버가 받아서 아두이노에 전달해줘야하기 때문이죠.

그럼 웹서버는 Arduino와 어떻게 통신할까요? Arduino IDE에서 프로그램을 업로드 할 때와 같은 방식의 통신을 해야할 것 같은데요. Arduino는 USB Serial Modem으로 연결이 되어 있어서 웹서버에서 Arduino에 값을 보내려면 Modem 통신 라이브러리를 사용해야합니다.(뭔가 어려워지네요…)

=== 아래 부분은 라즈베리파이에서 node-serialport 설치 후 할 수 있습니다 ===NodeJS 쪽에는 Serial 통신용 모듈인 node-serialport 라는게 있습니다. 이 모듈을

Page 47: 2015년 1월 정보분과 겨울 심화탐구 - javamath.com · 2015-01-05 · (1) 먼저 PC 윈도우에 node.js 를 설치하고 아두이노 조작활동을 한다 (2) 다음,

사용한다면 아래와 같은 모양으로 Arduino에 “1”/”0”을 보낼 수 있겠네요.

var SerialPort = require("serialport").SerialPortvar serialPort = new SerialPort("/dev/tty-usbserial1", { baudrate: 9600}, false);

serialPort.open(function () { console.log('접속되었구요'); serialPort.on('data', function(data) { // Arduino에서 뭔가 데이터를 보내주면 출력할꺼에요. console.log('data received: ' + data); });

serialPort.write("1", function(err, results) { // LED가 무작정 켜질꺼에요.}

Arduino가 아닌 NodeJS로 LED를 켜는걸 해봤으니… NodeJS로 웹서버를 띄운다면 웹에서 LED 켜는게 가능해지겠죠?

Express 라는 NodeJS 모듈을 이용해 간단히 켜볼까요?일단 간단히 앱을 하나 만들어봅시다.

$ sudo npm install -g express$ express -e simpleApp ; cd simpleApp && npm install

여기서는 Arduino와 연결을 위해 SerialPort 모듈을 사용합니다. 모듈 설치 해야겠죠?

$ npm install serialport

우선, app.js를 수정해서 LED가 Toggle 되는 간단한 프로젝트를 만들어봅시다.// app.js/** Module dependencies. */

var express = require('express');

Page 48: 2015년 1월 정보분과 겨울 심화탐구 - javamath.com · 2015-01-05 · (1) 먼저 PC 윈도우에 node.js 를 설치하고 아두이노 조작활동을 한다 (2) 다음,

var routes = require('./routes');var user = require('./routes/user');var http = require('http');var path = require('path');

var app = express();

// all environmentsapp.set('port', process.env.PORT || 3000);app.set('views', __dirname + '/views');app.set('view engine', 'ejs');app.use(express.favicon());app.use(express.logger('dev'));app.use(express.bodyParser());app.use(express.methodOverride());app.use(express.static(path.join(__dirname, 'public')));

// development onlyif ('development' == app.get('env')) { app.use(express.errorHandler());}

//// 이 값에 따라 LED 켜지는게 결정된다.//var ledStatus = false;

app.get('/', function(req, res) { res.render('index', { title: 'Express' });});

//// POST 액션을 받으면 LED가 Toggle 되도록 한다.//app.post('/', function(req, res) { ledStatus = ledStatus ? false : true; res.render('index', { title: 'Express' });

Page 49: 2015년 1월 정보분과 겨울 심화탐구 - javamath.com · 2015-01-05 · (1) 먼저 PC 윈도우에 node.js 를 설치하고 아두이노 조작활동을 한다 (2) 다음,

});

http.createServer(app).listen(app.get('port'), function(){ console.log('Express server listening on port ' + app.get('port'));});

//// Serial Port를 사용하는 예제//

var SerialPort = require("serialport").SerialPort

// Arduino가 /dev/tty-usbserial1 에 연결되었다고 가정합니다.var serialPort = new SerialPort("/dev/tty-usbserial1", { baudrate: 9600}, false);

serialPort.open(function () { console.log('접속되었구요'); serialPort.on('data', function(data) { // Arduino 쪽에서 뭔가 출력했다면 // 여길 통해서 데이터를 볼 수 있습니다. console.log('data received: ' + data); }); setInterval(function(){ serialPort.write(ledStatus ? "1" : "0", function(err, results) { // LED가 ON/OFF 될꺼에요 }); }, 100);});

이제 views/index.ejs 에 버튼을 하나 넣고, 버튼을 누르면 POST Action이 가게끔 수정합니다.<!-- views/index.ejs -->

<!DOCTYPE html><html>

Page 50: 2015년 1월 정보분과 겨울 심화탐구 - javamath.com · 2015-01-05 · (1) 먼저 PC 윈도우에 node.js 를 설치하고 아두이노 조작활동을 한다 (2) 다음,

<head> <title><%= title %></title> <link rel='stylesheet' href='/stylesheets/style.css' /> </head> <body> <h1><%= title %></h1> <p>Welcome to <%= title %></p>

<!-- 간단히 버튼으로 POST를 보내도록 한다. --> <form action="/" method="post"> <button type="submit">눌러봐</button> </form> </body></html>

이제 node app.js로 웹서버를 구동 시키고 http://localhost:3000 로 접속해서 버튼을 눌러봅시다.버튼이 정상적으로 켜진다면 웹에서 LED를 켜신거구요, 안켜지시는 분은 다시 한번 Arduino 보드에 스케치를 업로드 하셨는지 확인 하시거나 Arduino를 다시 연결해보세요. 여기까지 간단하게 급조한 예제를 살펴봤습니다.

페이지 갱신되는 예제가 허접 보인다구요? 그렇다면 socket.io 쪽을 살펴보시면 도움이 될 것 같아요. 매번 스케치를 업로드 해야하나요? 스크립트 처럼 쓸 수 없을까요?

Firmata라는게 있습니다. 요걸 사용하시면 매번 업로드 하지 않고도 Arduino를 자유롭게 제어할 수 있습니다. Firmata? 뭐죠?Firmata는 아두이노 같은 마이크로 컨트롤러와 PC가 서로 통신하기 위해 고안된 범용 프로토콜입니다. 어떻게 쓰는건가요?

일단, Arduino에 최초 StandardFirmata 라는 스케치를 업로드 합니다. 그 후에, Arduino와 통신을 하기 위해서는 Firmata 프로토콜에 맞도록 메시지만 보내주시면 됩니다.

만약, NodeJS를 사용해서 Arduino와 통신하고 싶다면 NodeJS으로 제작된 Firmata 모듈을 사용해 Arduino를 제어할 수 있습니다.

NodeJS 예로 들까요? NodeJS 쪽 Firmata 모듈 중 Johnny-Five라는 Firmata

Page 51: 2015년 1월 정보분과 겨울 심화탐구 - javamath.com · 2015-01-05 · (1) 먼저 PC 윈도우에 node.js 를 설치하고 아두이노 조작활동을 한다 (2) 다음,

based Arduino Framework이 있습니다.

var five = require("johnny-five"), // or "./lib/johnny-five" when running from the source board = new five.Board();

board.on("ready", function() {

// Create an Led on pin 13 and strobe it on/off // Optionally set the speed; defaults to 100ms (new five.Led(13)).strobe(); });

위 모듈을 사용해 이전에 만들었던 app.js를 바꿔볼까요?// app.js

/** Module dependencies. */

var express = require('express');var routes = require('./routes');var user = require('./routes/user');var http = require('http');var path = require('path');

var app = express();

// all environmentsapp.set('port', process.env.PORT || 3000);app.set('views', __dirname + '/views');app.set('view engine', 'ejs');app.use(express.favicon());app.use(express.logger('dev'));app.use(express.bodyParser());app.use(express.methodOverride());app.use(express.static(path.join(__dirname, 'public')));

// development only

Page 52: 2015년 1월 정보분과 겨울 심화탐구 - javamath.com · 2015-01-05 · (1) 먼저 PC 윈도우에 node.js 를 설치하고 아두이노 조작활동을 한다 (2) 다음,

if ('development' == app.get('env')) { app.use(express.errorHandler());}

//// 이 값에 따라 LED 켜지는게 결정된다.//var ledStatus = false;

app.get('/', function(req, res) { res.render('index', { title: 'Express' });});

//// POST 액션을 받으면 LED가 Toggle 되도록 한다.//app.post('/', function(req, res) { ledStatus = ledStatus ? false : true; res.render('index', { title: 'Express' });});

http.createServer(app).listen(app.get('port'), function(){ console.log('Express server listening on port ' + app.get('port'));});

//// Johnny-five 모듈로 보드에 접속해 LED를 제어한다.// var five = require('johnny-five') , board = new five.Board();

board.on("ready", function() { // // 13번 PIN을 OUTPUT으로 // this.pinMode(13, 1);

Page 53: 2015년 1월 정보분과 겨울 심화탐구 - javamath.com · 2015-01-05 · (1) 먼저 PC 윈도우에 node.js 를 설치하고 아두이노 조작활동을 한다 (2) 다음,

// // 0.1s마다 돌면서 ledStatus 값에 따라 LED를 ON/OFF 한다. // this.loop(100, function() { // this.digitalWrite( 13, ledStatus ? 1 : 0 ); });});

Page 54: 2015년 1월 정보분과 겨울 심화탐구 - javamath.com · 2015-01-05 · (1) 먼저 PC 윈도우에 node.js 를 설치하고 아두이노 조작활동을 한다 (2) 다음,

============== Firmata 대신에 duino를 사용할 수 있다 ================

라즈베리에서 nodeJS 명령으로 아두이노 컨트롤

아두이노에 duino 코드 업로드하기duino를 사용하기 위해서는 아두이노에 duino 프로토콜을 해석할 수 있는 프로그램을 설치해야 한다. 아두이노 프로그램(github.com/ecto/duino/blob/master/src/du.ino)을 다운로드해 아두이노 IDE로 업로드한다. 일단 du.ino가 아두이노 보드에 올라가면 아두이노 IDE가 필요 없게 된다. 이제 Node.js를 이용해 프로그래밍하는 일만 남았다. du.ino를 업로드할 때 아두이노 IDE에서 보드와 시리얼포트를 설정한다. 그리고 du.ino를 스케치 프로그램으로 업로드한다. 업로드가 완료되면 Node.js로 아두이노를 제어할 준비가 모두 끝난 것이다.

샘플 소스와 의존 라이브러리여기서 사용할 샘플 코드를 github에 올려두었다. 링크(github.com/jinniahn/duino_sample)를 이용해 소스를 다운로드하고 npm install 명령으로 의존모듈들을 설치해야 한다. duino 모듈은 github에 있는 최신 소스를 사용하고 있다. 또 의존 라이브러리로 ‘SerialPort’ 모듈이 있는데, 이 모듈을 컴파일해야 하므로 윈도우의 경우에는 설치가 쉽지 않다. 여기서는 리눅스를 이용하도록 하겠다. 꼭 윈도우에서 사용하고자 하는 경우에는 SerialPort 모듈의 설치 문서(github.com/voodootikigod/node-serialport#to-install)를 참고하기 바란다. 리눅스나 맥에서 작업하고 있다면 NPM(Node Packaged Module)을 이용해 설치할 수 있다.

<리스트 1> NPM을 이용한 SerialPort 모듈 설치$&gt; cd $duino_sample_path $&gt; npm install위의 $duino_sample_path는 github에서 받은 소스의 경로로 변경해야 한다.

var arduino =require('duino'), board =new arduino.Board({ device:'USB0'});

var led =new arduino.Led({ board: board, pin:13});

led.blink();

라즈베리파이와 아두이노 연결 시 /dev/ttyUSB0를 통해 serial 통신하게 되어 device attribute에 USB0라고 입력. MS Windows / MAC 계열에서는 아래 파일로

Page 55: 2015년 1월 정보분과 겨울 심화탐구 - javamath.com · 2015-01-05 · (1) 먼저 PC 윈도우에 node.js 를 설치하고 아두이노 조작활동을 한다 (2) 다음,

node_modules/duino/lib/board.js를 대체한 뒤 device 명으로 시리얼 포트가 연결된 COM포트 명 입력 ex) COM4

[예제 1] 버튼을 눌러 LED에 불 켜기이제 예제를 다뤄볼 것이다. 첫 번째는 LED와 버튼을 이용하는 예제다. 간단하지만 디지털 I/O를 다뤄 볼 수 있는 대표적인 예제다. 아두이노는 대부분 외부의 입력을 센서를 통해 입력받아 어떤 결과를 LCD나 부저와 같은 방식으로 출력한다. 예제에서는 단색 LED로 외부에 정보를 표시하는 방법을 살펴볼 것이다. 우선 회로도부터 살펴보자(<그림 7> 참조).

<그림 7> 버튼과 LED의 연결 회로도

회로도를 보면, 아두이노의 2개의 핀을 사용한 것을 확인할 수 있다. 버튼과 연결되는 디지털 핀 2(D2)와 LED에 연결될 디지털 핀 8이 사용된다. 회로도를 간단히 하기 위해서 5V와 GND는 아두이노와 연결하지 않았다. 하지만 실제 부품을 연결할 때는 모두 아두이노 보드의 전원핀을 이용해야 한다. 간략하게 설명을 하면 <그림 8>과 같다.

<그림 8> 회로 기호 설명

<그림 8>은 앞으로의 예제에서 사용할 부품들을 회로 기호로 표시한 것이다. 아두이노 보드는 사각형으로 보드를 표현하고 있다. 보드에 연결되는 핀 중 사용할 핀을 기호로 표시한다. 보드에는 많은 핀들이 존재하지만 회로도에서 모두 표시할 필요는 없다. 사용할 핀만 표시하면 된다. 저항은 지그재그 선으로 이뤄진 기호를 사용하고 있다. 저항값은 저항 기호 옆에 적는다. 빛 감지 센서와 LED는 빛이 들어가고 나가는 방향에 따라 화살표가 다른 것이 특징이다. 스위치는 버튼을 누르면 연결되고 떼면 연결이 끊어진다. 마지막으로 전원이다. 본 예제의 회로도에서는 전원을 아두이노 보드와 연결하지 않았지만 실제로 회로를 구성할때는 반드시 보드의 전원을 사용해야 한다. 이 예제를 실행하기 위해서는 1개의 버튼과 1개의 LED, 그리고 10K 옴의 저항이 필요하다. 부품들을 회로도에 따라서 잘 연결하자. LED의 경우 극성이 정해져 있다. 다리가 긴 쪽이 +극이고 짧은 쪽이 -극이다.

Page 56: 2015년 1월 정보분과 겨울 심화탐구 - javamath.com · 2015-01-05 · (1) 먼저 PC 윈도우에 node.js 를 설치하고 아두이노 조작활동을 한다 (2) 다음,

<리스트 2> 버튼이 누르면 LED에 불이 들어옴(button_led.js)

var arduino = require('duino')

var board = new arduino.Board({ // &lt;=== 1 debug: true, // if mac, use below // device: ‘usb’

// linux serial dev : /dev/ttyACM0 device: 'ttyACM0' // &lt;=== 2 });

var led = new arduino.Led({ //&lt;=== 3 board: board, pin: 13 });

var button = new arduino.Button({ //&lt;=== 4 board: board, pin: 2 });

button.on('up', function(){ //&lt;=== 5 led.off(); });

button.on('down', function(){ //&lt;=== 6 led.on(); });

<리스트 2>의 코드를 보자. 이 코드의 목적은 버튼을 누르고 있으면 LED에 불이 들어오고 아니면 꺼지도록 하는 것이다. 이를 위해서 버튼과 LED를 제어할 필요가 있다. duino에는 각각의 클래스를 제공하고 있다. 소스 코드에서 1번은 아두이노와의 연결과 데이터 교환을 담당하는 board다. 여기에 시리얼포트의 이름이 들어간다. 리눅스를 사용하고 있다면 ttyACM0을 사용하고 맥이라면 usb를 입력한다. board 객체는 버튼이나 LED를 다루기 위해 반드시 필요한 값으로 객체 생성 시에 사용된다. 3, 4번에 led와 button 객체를 생성하면서 board를 사용한 것을 기억하자. 그리고 추가적으로 핀 번호도 지정해 각 부품이 어떤 핀에 연결될 것인지 지정한다. 회로도에서 지정한 것처럼 디지털 핀 2와 버튼을 연결하고 디지털 핀 13에 LED를 연결했다. 소스 코드에도 이 정보를 반영했다.

Page 57: 2015년 1월 정보분과 겨울 심화탐구 - javamath.com · 2015-01-05 · (1) 먼저 PC 윈도우에 node.js 를 설치하고 아두이노 조작활동을 한다 (2) 다음,

버튼을 누르면 button 객체에 ‘down’ 이벤트가 발생한다. on 메소드를 사용해 해당 이벤트에 핸들러를 등록해 둔다(<리스트 2>의 6). 핸들러에서는 led.on() 명령으로 LED에 전원이 공급된다. 아두이노의 코드들 대부분은 이처럼 이벤트에 의해 동작한다. Node.js는 event emitter가 있어 센서의 이벤트에 따른 동작을 쉽게 구현할 수 있다.

[예제 2] 주변의 밝기 알아보기또 다른 예제를 보도록 하자. 앞에서 버튼을 사용해서 디지털 신호를 받았다면 이번에는 아날로그 값을 읽어보도록 할 것이다. 우리 주변의 정보들은 대부분 아날로그 값이다. 온도, 습도, 기압, 조도과 같은 정보들은 디지털 값들처럼 0, 1의 값으로 정확히 표현되지 않는다.

<그림 9> 조도 센서를 연결한 회로도

아날로그 값들은 특정 시점에 샘플링을 통해서만 디지털 값으로 변환한다. 이는 ADC(Analog-to-Digital Converter)에 의해 샘플링된다. 아두이노의 아날로그 입력 핀들에는 이 ADC가 연결돼 있다. 이번에는 외부의 밝기를 알아보는 예제를 통해 아날로그 값을 어떤 식으로 읽어 오는지 확인해 본다. 이 예제를 응용하면 아날로그 값으로 입력 받는 온도 센서, 습도 센서를 이용할 수 있다.

이번 예제는 조도 센서를 A0 핀에 연결하게 된다. 이때 조도 센서와 GND 사이에 10K 옴을 사용하고 있다. 이는 버튼을 이용할 때처럼 조도 센서의 저항값이 너무 작을 경우 회로에 많은 전류가 흐르는 것을 방지하기 위해서 사용된다. 이러한 역할을 하는 저항을 ‘풀다운 저항’이라고 한다. 아날로그 센서를 사용할 때 많이 사용되는 구성이다. 그리고 디지털 핀 13에 LED를 연결하도록 한다. 이 예제의 목적은 조도 값에 따라 LED가 켜지거나 꺼지도록 하는 것이다.

<리스트 3> 예제를 위한 소스 코드var arduino = require('duino') var board = new arduino.Board({ // &lt;=== 1 debug: true, // if mac, use below // device: 'usb'

Page 58: 2015년 1월 정보분과 겨울 심화탐구 - javamath.com · 2015-01-05 · (1) 먼저 PC 윈도우에 node.js 를 설치하고 아두이노 조작활동을 한다 (2) 다음,

// linux serial dev : /dev/ttyACM0 device: 'ttyACM0' // &lt;=== 2 });

// setup light sensor // get data every 1sec // PIN : A0 var light_sensor = new arduino.Sensor({ //&lt;=== 3 board: board, pin: 'A0', throttle: 1000 });

var led = new Arduino.Led({ // &lt;===4 board: board, pin: 13 });

light_sensor.on('read', function(err,data){ // &lt;===5 console.log('val = ' + data); if( data &gt; 200 ) { //&lt;===6 led.off(); } else { led.on(); } });

<리스트 3>은 앞에서 살펴봤던 버튼 예제와 크게 다르지 않다. 먼저 아두이노 보드와의 연결을 담당하는 board 객체를 생성한다. 아날로그 핀에 연결된 조도 센서는 sensor 객체를 이용하게 되는데, 이때 pin 값은 ‘A0’으로 한다. 보드의 아날로그 핀인 A0 핀을 의미한다. throttle은 sensor 값을 읽는 주기를 나타낸 것으로, 1000ms로 한다. 1초마다 센서 값을 읽는다는 뜻이다. 기본값은 10ms이다. sensor 객체의 값이 주기적으로 읽혀지면 “read” 이벤트가 발생한다. 5번은 센서가 읽혔을 때 호출되는 이벤트 핸들러다. 핸들러에 들어오는 값으로 로직을 처리한다. 여기서는 조도 입력 값이 200이 넘으면 LED를 끄고 그 이하이면 LED 켜도록 돼 있다. 즉, 주변이 밝으면 조명을 끄고 어두우면 조명을 켠다. 아두이노의 아날로그 핀 값은 0~1023의 값으로 변환돼 입력된다. 조도의 경우 이 값이 높을수록 주변이 밝음을 의미한다. LED 대신 형광등을 연결할 수 있다면 방이 어두워지면 자동으로 불이 켜지는 장치를 만들 수도 있겟다.

Page 59: 2015년 1월 정보분과 겨울 심화탐구 - javamath.com · 2015-01-05 · (1) 먼저 PC 윈도우에 node.js 를 설치하고 아두이노 조작활동을 한다 (2) 다음,

duino의 다른 클래스들예제를 통해 duino 라이브러리의 Board, Sensor, Led, Button을 살펴봤다. 이것들 외에도 다양한 클래스가 라이브러리로 제공된다. 모터를 제어할 수 있는 Servo 클래스나 초음파로 거리를 구하는 Ping 클래스, 동작감지 센서를 통해 주변 사람의 움직임을 감지하는 Pir 클래스 등이 그것들이다.

이들 각각의 클래스들은 그에 해당하는 센서 혹은 액츄에이터들을 제어할 수 있다. 간단한 예제들은 여기에 있는 API를 사용해 개발이 가능하다. 하지만 아두이노 보드가 다른 보드와 통신해야 한다면 시리얼통신이나 SPI 혹은 I2C 방식으로 연결하게 되는데, duino는 아직 이런 통신 부분에 대한 것을 제공하고 있지 않다. 만약 이런 부분이 필요하다면 duino를 수정해야 한다. 하지만 프로토콜 자체가 단순하므로 원하는 기능을 구현하는 것이 그리 어렵지는 않다. 다만 수정할 때는 duino의 Node.js 코드와 아두이노 코드를 모두 수정해야 함을 기억하자.

시리얼 연결 방식의 문제와 해결 방법duino는 시리얼을 통해 핀 모드 설정, 디지털 핀 제어, 아날로그 입출력 등 아두이노가 다룰 수 있는 저수준의 API를 Node.js에서 그대로 사용할 수 있도록 제공한다. 이 API를 사용하는 Node.js는 아두이노를 세밀하게 다룰 수 있다. LED나 Servo 모터 하나하나를 모두 다룰 수 있는 것이다. 하지만 정밀도가 요구되는 상황에서는 적용하기 어렵다. 이는 Node.js 때문이라기보다 OS의 특성에 기인한다. Node.js가 실행되는 리눅스와 같은 OS는 실시간 OS가 아니기 때문에 어떤 명령을 수행하는 데 얼마 동안의 시간이 소요되는지 확신할 수 없다. 이 때문에 Node.js로는 정확한 제어가 어렵다. 이 문제를 해결하는 방법은 두 가지다.

첫째는 아두이노가 실행할 명령을 한 번에 주고 실행시키는 방식이다. Node.js가 세부적인 API까지 사용할 수 있다는 것은 분명 장점이다. 아두이노의 코드가 커지는 것을 방지할 수 있을 뿐 아니라 아두이노의 코드를 업데이트하는 것보다는 Node.js의 코드를 변경하는 것이 더 쉽기 때문이다. 그렇다면 Node.js로 저수준 API를 사용하면서 실시간성을 보장할 방법은 없을까? 현재 방식의 문제는 명령마다 매번 통신해서 명령을 전달하고 실행하는 것이다. 이때 통신 회선의 속도와 Node.js가 실행되는 OS로 인해 명령의 실행 시점이 정확하지 않다. 그렇다면 실행해야 하는 명령을 하나의 단위로 묶어 전달한 뒤 실행시키는 방법을 생각해 볼 수 있다. 이 방식을 사용하면 기존처럼 저수준 API를 그대로 사용할 수 있고 수정해야 하는 코드 역시 많지 않게 된다. 단지 트랜잭션 명령을 시작하고 종료하는 코드만 있으면 된다.

둘째는 실시간성이 필요한 코드를 미리 아두이노에 개발해 놓는 방식이다. 단순하게 생각하면 명령이 너무 세부적이라는 것이 문제가 된다. 예를 들어 LED를 제어하기 위해 핀 번호를 설정하면 불이 켜지는 명령을 따로 하는 것이다. 이를 하나의 명령으로 만들면 문제가 해결된다. 대신 아두이노에서 처리해야 하는 코드가 만들어지고 Node.js는 아두이노에 이 핸들러를 실행시키는 명령을 보낸다. 명령이 많아져 아두이노의 코드가 커지는 것만 아니라면 이 방법 역시 훌륭한 해결법이다.

이 두 가지 방법의 차이는 결국 메인 로직을 어디에 둘 것인가이다. Node.js의 장점을 충분히 살리고자 한다면 첫 번째 방법이 더 적합하지 않을까 생각한다.

Page 60: 2015년 1월 정보분과 겨울 심화탐구 - javamath.com · 2015-01-05 · (1) 먼저 PC 윈도우에 node.js 를 설치하고 아두이노 조작활동을 한다 (2) 다음,

정리하며Node.js의 장점은 기능의 확정성에 있다. NPM을 통해 수만 개의 모듈에 제공되고 있다. 또 Node.js 자체는 기본 기능에 매우 충실하다. 기본적인 file I/O 기능, 바이너리 데이터를 위한 Buffer 클래스 등 최소한의 기능을 제공하면서 시스템의 안정성에 더 무게를 뒀다. 이 외에도 고급 기능들은 모두 NPM으로 관리되는 모듈이 제공된다. 앞서 살펴봤던 duino도 이 모듈 중의 하나이다.

이번 시간에는 아두이노를 Node.js에서 어떻게 다루는지, 또 어떤 방식으로 제어하는지 살펴봤다. Node.js의 진정한 가치는 인터넷 연결에서 발휘된다. 다음 시간에는 아두이노의 기능을 웹서비스로서 외부에 제공하는 기능을 구현해 볼 것이다.

 [참고자료]1. duino (github.com/ecto/duino) 2. firmata (firmata.org/wiki/Main_Page) 3. Node.js (nodejs.org) 4. 샘플 소스 (github.com/jinniahn/duino_sample)