펜 사용하기

01. 스마트 북을 만들자

펜을 이용하여 책에 인쇄되어 있는 OID 코드를 읽어보자. 펜을 사용하기 위해서는 그림 1과 같이 먼저 스마트 로봇 론처의 환경 설정 > 주변기기에서 펜을 등록해야 한다. 각각의 펜은 제품 번호로 구분되는데, 펜의 제품 번호는 그림 1과 같이 등록할 때 표시된다(펜 종류 #1).

그림 1. 주변기기 등록

펜으로 OID 코드를 읽는 프로그램을 작성하시오.

RobotActivity 클래스를 상속한 액티비티를 만들고, onInitialized(Robot) 메소드와 onExecute() 메소드를 상속받아 새로 구현하자. 프로젝트에 스마트 로봇 라이브러리를 포함하는 것을 잊지 않기를 바란다.

 public class SampleActivity extends RobotActivity
 {
     @Override
     public void onCreate(Bundle savedInstanceState)
     {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.main);
     }

     @Override
     public void onInitialized(Robot robot)
     {
     }

     @Override
     public void onExecute()
     {
     }
 }

펜에는 OID 값을 읽는 디바이스로 EVENT_OID가 있다. OID 데이터는 -1부터 65535까지의 값을 가지는데, -1은 OID 코드를 읽지 못하였을 때 표시하는 값이다. 정상적으로 코드를 읽은 경우에는 0 이상의 값을 가진다.

알버트 로봇에서는 Robot 클래스의 findDeviceById(int deviceId) 메소드를 사용하여 필요한 디바이스의 객체를 얻었지만, 주변기기의 경우에는 Robot 클래스의 findDeviceById(int productId, int deviceId) 메소드를 사용하여야 한다. 디바이스 ID만으로는 어느 펜의 디바이스인지 구분할 수가 없기 때문에 productId에 제품 번호를 넣어주어야 한다. 여기서는 제품 번호가 1인 경우라고 가정하자.

 public class SampleActivity extends RobotActivity
 {
     private Device mOIDDevice;
 
     @Override
     public void onCreate(Bundle savedInstanceState)
     {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.main);
     }

     @Override
     public void onInitialized(Robot robot)
     {
         mOIDDevice = robot.findDeviceById(1, Pen.EVENT_OID); // 1번 펜의 OID 디바이스
     }

     @Override
     public void onExecute()
     {
         int oid = -1;
         if(mOIDDevice.e())
             oid = mOIDDevice.read();
     }
 }

OID 디바이스는 이벤트 디바이스라는 것에 주의해야 한다. 이벤트가 발생하였을 때만 데이터가 갱신되기 때문에 데이터를 읽기 전에 반드시 Device 클래스의 e() 메소드를 사용하여 이벤트가 발생하였는지 확인해야 한다.

펜에는 작고 앙증맞은 버튼이 있다. 똑같은 OID 코드에 대해서도 버튼 상태에 따라 다른 동작을 하도록 만들 수 있다. 버튼 상태에 대한 디바이스는 EVENT_BUTTON이다. 이벤트 디바이스이며, 버튼을 눌렀을 때는 1, 누르지 않았을 때는 0의 값을 가진다.

OID 코드와 함께 버튼의 상태도 읽어보도록 하자.

 public class SampleActivity extends RobotActivity
 {
     private Device mOIDDevice;
     private Device mButtonDevice;
 
     @Override
     public void onCreate(Bundle savedInstanceState)
     {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.main);
     }

     @Override
     public void onInitialized(Robot robot)
     {
         mOIDDevice = robot.findDeviceById(1, Pen.EVENT_OID);
         mButtonDevice = robot.findDeviceById(1, Pen.EVENT_BUTTON); // 1번 펜의 버튼 디바이스
     }

     @Override
     public void onExecute()
     {
         int oid = -1;
         int button = 0;
         if(mOIDDevice.e())
             oid = mOIDDevice.read();
         if(mButtonDevice.e())
             button = mButtonDevice.read();
     }
 }

이번에는 onDeviceDataChanged 메소드를 사용하여 구현해 보자.

 public class SampleActivity extends RobotActivity
 {
     @Override
     public void onCreate(Bundle savedInstanceState)
     {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.main);
     }

     @Override
     public void onDeviceDataChanged(Device device, Object values, long timestamp)
     {
         int oid = -1;
         int button = 0;
         if(device.getProductId() == 1)
         {
             switch(device.getId())
             {
             case Pen.EVENT_OID:
                 oid = ((int[])values)[0];
                 break;
             case Pen.EVENT_BUTTON:
                 button = ((int[])values)[0];
                 break;
             }
         }
     }
 }

Device 클래스의 getProductId() 메소드를 사용하여 제품 번호가 1인 경우인지 확인하였는데, 어느 펜을 사용해도 상관이 없다면 이 조건문은 없어도 된다.

02. 멀리 가면 안되요

펜은 지그비 무선 통신으로 로봇에 데이터를 전달한다. 와이파이 존에서 멀어지면 통신이 안되듯이 펜도 로봇에서 멀어지면 데이터를 전달하지 못한다.

지그비 신호 세기를 알아내는 프로그램을 작성하시오.

펜에는 지그비 신호 세기에 해당하는 디바이스로 SENSOR_SIGNAL이 있다. 신호 세기는 0부터 255까지의 값을 가지는데 펜이 로봇 가까이 있으면 신호 세기가 커져서 값이 증가하고, 멀어지면 신호 세기가 작아져서 값이 감소하게 된다.

 public class SampleActivity extends RobotActivity
 {
     private Device mSignalDevice;
 
     @Override
     public void onCreate(Bundle savedInstanceState)
     {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.main);
     }

     @Override
     public void onInitialized(Robot robot)
     {
         mSignalDevice = robot.findDeviceById(1, Pen.SENSOR_SIGNAL);
     }

     @Override
     public void onExecute()
     {
         int signal = mSignalDevice.read();
     }
 }

이번에는 onDeviceDataChanged 메소드를 사용하여 구현해 보자.

 public class SampleActivity extends RobotActivity
 {
     @Override
     public void onCreate(Bundle savedInstanceState)
     {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.main);
     }

     @Override
     public void onDeviceDataChanged(Device device, Object values, long timestamp)
     {
         int signal;
         switch(device.getId())
         {
         case Pen.SENSOR_SIGNAL:
             signal = ((int[])values)[0];
             break;
         }
     }
 }

03. 배고파요

펜에 내장된 배터리의 상태를 알려 주는 센서 디바이스는 SENSOR_BATTERY이다. 0부터 100까지의 값을 가지며 배터리의 잔량을 %로 나타낸다.

 public class SampleActivity extends RobotActivity
 {
     private Device mBatteryDevice;
 
     @Override
     public void onCreate(Bundle savedInstanceState)
     {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.main);
     }

     @Override
     public void onInitialized(Robot robot)
     {
         mBatteryDevice = robot.findDeviceById(1, Pen.SENSOR_BATTERY);
     }

     @Override
     public void onExecute()
     {
         int battery = mBatteryDevice.read();
     }
 }

onDeviceDataChanged 메소드를 사용하여 구현하면 다음과 같다.

 public class SampleActivity extends RobotActivity
 {
     @Override
     public void onCreate(Bundle savedInstanceState)
     {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.main);
     }

     @Override
     public void onDeviceDataChanged(Device device, Object values, long timestamp)
     {
         int battery;
         switch(device.getId())
         {
         case Pen.SENSOR_BATTERY:
             battery = ((int[])values)[0];
             break;
         }
     }
 }