August 17, 2018

디바이스마트 미디어:

[38호]Personal Black Box 소형 단말 개인 보안 장치

2016 ictmain

 

2016 ICT 융합 프로젝트 공모전 참가상

Personal Black Box 소형 단말 개인 보안 장치

글 | 건국대학교 김호중, 박현근

 

심사평

JK전자 차량용 블랙박스에서 착안해서 개인용으로 사용하도록 만들겠다는 생각은 창의성이 있어 보인다. 하지만 구현된 작품을 실제 사용하기에는 기구물의 완성도가 낮고, 특히 센서들과 카메라 데이터의 데이터 수집을 위한 소프트웨어 구현이 해외의 특정 업체에서 제공하는 라이브러리를 그대로 사용하고 있어서 소프트웨어 구현을 위한 노력이 부족한것 같다.

뉴티씨 매우 좋은 아이디어이지만 보고서 내용이 많이 빈약하고 설명이 부족하여, 기술성도 높은 좋은 작품임에도 불구하고 그에 비해서 높은 점수를 받지는 못했다. 하지만, 좀 더 표현하는 데에도 신경을 써서 문서화도 잘하고, 창의적인 내용과 실용적인 내용을 부각하여, 자세히 기술한다면 좋은 작품이 될 것이라고 확신한다.

칩센 내용상 스마트폰의 기능이 그대로 반영되어 있고 유사 APP도 있는 상황으로 좋은 평가를 받기는 힘들다. 어떤 경우를 위험한 상황으로 판단할지에 대한 부분도 없어 아쉽다.

위드로봇 라즈베리파이 보드에 여러 센서를 부착하여 개인용 블랙박스를 제작하는 아이디어가 좋다. 아쉬운 점은 보고서 상에서는 각각의 센서값들이 어떻게 잘 저장되었으며, 어떻게 활용할 수 있는지에 대한 내용이 빠져있다는 점이 어떻게 만들었는지 상세하게 설명하는 것만큼이나 이렇게 만들어진 작품이 어떻게 동작했으며, 잘 된 부분과 잘 안된 부분을 나눠 잘 안된 부분은 어떻게 추후 개선해 보겠다라는 내용이 보고서에 들어가면 더 좋을 것 같다.

작품 개요
새롭게 떠오르고 있는 새로운 플랫폼(Platform)
21세기 2015년이후 현재, 세계 IT산업은 빠르게 발전하다 못해 현재 포화상태이고, 각 국의 IT기업들은 소리없는 전쟁을 치르고 있다. 우리는 지금까지 다양한 플랫폼(Platform)의 변화를 겪어왔다.
고전적인 PC에서부터, 휴대성이 강조된 랩탑과 노트북, 통신기능이 탑재된 휴대폰, 강력한 컴퓨팅 파워까지 포함된 스마트폰. 이제는, 더욱 더 나아가 시계와 안경까지 플랫폼은 계속해서 변화중이다. 이러한 변화들을 통해 우리는 이제, 언제 어디서든지 인터넷에 접근할 수 있게 되었고, 모바일과 새로운 플랫폼에서는 다양한 센서(Sensor)를 통해 이전 플랫폼에서는 볼 수 없었던 다양하고 새로운, 신기한 어플리케이션이 제작되었다. 이는 가히 플랫폼이 가져온 혁명이라고 말할 수 있다.

오픈소스 소프트웨어에서 오픈소스 하드웨어로
이러한 IOT 시대로의 변화의 중점에 있다는 것을 더욱 체감하게 해주는 것이 바로 오픈소스 하드웨어(Open Source Hardware Project)이다. 최근의 소프트웨어는 오픈소스 소프트웨어로 개발되는 것이 추세였다. 이런 장점을 그대로 가져와 IOT 시대에 서는 하드웨어에 오픈소스 개념을 적용하였다. 오픈소스의 장점은 많지만 그 중에서도 사용자의 입맛에 맞게 소스를 재구성 할 수 있다는 점이 가장 매력적인 부분이다. 하드웨어라고 달라진 점은 없다. 하드웨어의 모든 소스, 회로도, 아키텍처가 공개되어 있고, 이를 사용하는 사용자는 필요한 부분, 수정할 부분을 고쳐 사용하면 된다.

자신을 좀 더 안전하게 돌봐줄 악세서리, Personal Black Box
블랙박스(Black Box)는, 현재까지는 자동차의 사고에 있어서 사고 현장을 촬영하여 사고 해결에 도움을 주는 그런 장치로 인식되고 있다. 사람의 경우는 어떠한가. 사람이 다니는 길에는 곳곳에 CCTV가 배치되어 있건만 CCTV의 사각지대로 인하여 제대로 촬영되지 않는 문제가 발생하기도 하며, 실종사건 발생시 추적하기가 매우 어려워진다. 그렇다면, 블랙박스를 사람에게도 가지고 다니게하면 어떨까?하고 생각하였다. 이 작품의 목적은 새로운 플랫폼을 통하여 사람의 범죄나 사고를 예방하고 후처리를 빠르게 해결할 수 있도록 도와주는, 누구나 보다 안전해지는 악세서리를 만드는 것이다.

작품설명
센서 데이터 수집/조회

38 ict 소형단말 (1)

카메라 사진 촬영/조회

38 ict 소형단말 (2)
전체 시스템 구성

38 ict 소형단말 (3)

데이터 흐름도(Data Flow Diagram)

38 ict 소형단말 (4)

개발 환경
MotherBoard

38 ict 소형단말 (1)

NetWork

38 ict 소형단말 (2)

Sensors

38 ict 소형단말 (3)

GPS – Adafruit GPS breakout board
Accelerometer – Adafruit Flora LSM303
Light – Adafuit Flora TSL2561
etc – Resistor, Switch, Wire…

Operation System and Programming Language

38 ict 소형단말 (4)
OS : Raspbian (Debian)
Language : Python, Java, HTML5

단계별 제작 과정
라즈비안 운영체제 설치 및 환경설정

라즈비안 운영체제 다운로드
https://www.raspberrypi.org/downloads/raspbian/

Win32DiskImager 다운로드
http://sourceforge.net/projects/win32diskimager/

Win32DiskImager로 다운받은 라즈비안 운영체제 이미지 파일을 SD Card에 설치하도록 한다.

38 ict 소형단말 (7)

SSH접근이 가능하도록 설정해주고 W ifi 모듈을 장착한뒤, 무선랜 설정으로 들어가 현재 사용할 AP를 연결 및 저장하도록 한다.

38 ict 소형단말 (6)

라즈베리파이 카메라 모듈 테스팅 및 모션인식 설정

카메라 모듈을 보드에 장착한다.

38 ict 소형단말 (7)

카메라 사용을 위해 다음을 터미널에서 입력한다.
‘sudo apt-get update’와 ‘sudo apt-get upgrade’를 입력한다. 그 후 ‘sudo raspi-config’를 입력해 설정창으로 들어간다. 설정창에서 카메라 사용여부를 ‘Enable’ 로 변경한다. 이후 리부팅한다.

38 ict 소형단말 (8)

라즈베리파이 모션 패키지를 설치하기 위해 터미널 창에서 순서로 진행하도록 한다.
‘sudo apt-get install -y motion’
‘sudo rm /usr/bin/motion’
‘mkdir tmp’
‘cd tmp’
‘wget http://rasplay.iptime.org/data/source/motion-mmal/motion’
‘wget http://rasplay.iptime.org/data/source/motion-mmal/motion-mmalcam.conf’
‘sudo chmod 700 motion’
‘sudo mv ~/tmp/motion /usr/bin/’
‘sudo mv ~/tmp/motion-mmalcam.conf /etc/motion/’

GPS 모듈 설정
GPS 모듈을 사용하기 위하여 OS설정을 변경한다. 터미널 창에서 다음을 입력한다.
‘sudo vi /boot/cmdline.txt’ 파일 안의 다음의 내용을
‘dwc_otg.lpm_enable=0 console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=dedline rootwait’
다음과 같이 바꾼다.
‘dwc_otg.lpm_enable=0 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline rootwait’

/etc/inittab 파일을 수정하기 위해 터미널에 다음과 같이 입력 후 수정한다.
‘sudo vi /etc/inittab’ 파일 안의 다음의 내용을
‘#Spawn a getty on Raspberry Pi serial line T0:23:respawn:/sbin/getty -L ttyAMA0 115200 vt100’
다음과 같이 바꾼다.
‘#Spawn a getty on Raspberry Pi serial line #T0:23:respawn:/sbin/getty -L ttyAMA0 115200 vt100’

GPS 관련 Daemon을 설치한다.
‘sudo apt-get install gaps psd-clients python-gps’

센서 사용을 위한 I2C 데이터 버스 설정
사용 금지된 i2c blacklist를 해제하여야 한다. 터미널에 다음을 입력한다.
‘sudo vi /etc/modprobe.d/raspi-blacklist.conf’
파일 안에 내용 중 ‘blacklist i2c-bcm2708’이란 내용을 ‘#’으로 주석 처리해준다.

i2c 디바이스를 활성화시키기 위해 터미널에 다음을 입력한다.
‘sudo vi /etc/modules’
파일의 내용중 가장 마지막 줄에 ‘i2c-dev’를 입력한뒤 저장한다.

i2c 관련 응용툴을 설치하기 위해 터미널에 다음을 입력한다.
‘sudo apt-get install i2c-tools libi2c-dev python-smbus’

i2c에 관해 유저 등록을 해주기 위해 다음을 입력한다.
‘sudo adduser pi i2c’

각종 센서 GPIO에 연결

38 ict 소형단말 (9) 38 ict 소형단말 (10)
각종 코드를 다운 및 설정
Adafruit 센서의 예제 소스코드를 토대로 소스코드를 작성할 것 이므로 GitHub에서 예제 소스코드를 다운 받는다.
터미널 창에서 다음을 입력한다.
‘git clone https://github.com/adafruit/Adafruit-Raspberry-Pi-Python-Code.git’
Adafruit에서 제공하는 센서들의 Python으로 작성된 예제 소스코드들이 전부 포함되어 있다.

센서들을 자동 실행할 쉘 스크립트 파일을 만든다.
라즈베리파이의 홈폴더에 ‘Motion.sh’라는 쉘 스크립트 파일을 만든다. 이 스크립트 파일은 모션캡쳐기능을 자동 실행하는 스크립트이다. 라즈베리파이의 홈폴더에 ‘Start.sh’라는 쉘 스크립트 파일을 만든다. 이 스크립트 파일은 클라우드, 센서를 작동시키는 스크립트이다.

스크립트 파일 자동 실행 등록을 해준다.
터미널 창에 다음을 입력한다. ‘sudo vim /etc/rc.local’

#!/bin/sh-e
#
#rc.local
#
#This script is executed at the end of each multiuser runlevel.
#Make sure that the script will “exit o” on success or any other
#value on error.
#
#In order to enable or disable this script just change the execution
#bits.
#
#By default this script does nothing.
#Print the IP address
_IP=$(hostname-I)||true
if{“$_IP”}; them
printf “My IP address is %sn””$_IP”
fi
#ADD line:
exit o

fi와 exit0사이에 명령어를 입력해준다.

‘/home/pi/Start.sh/’

재부팅하여 정상 동작하는지 확인한다.

First Model

38 ict 소형단말 (11)

라즈베리파이에서 불필요한 파츠를 제거한 모습.

38 ict 소형단말 (12)

38 ict 소형단말 (13)

RJ-45잭, 오디오잭, 영상잭을 제거했다. 또한 GPIO의 핀들을 전부 제거, USB 호스트에서 2단 잭을 제거하고, 1단 잭으로 변경했다.

38 ict 소형단말 (14)

작품의 초기 모델 Wifi모듈, 카메라, 센서들. 단, GPS센서의 경우 중요도가 낮 아서 일단 실험(자세 측정)에는 필요가 없고, 실험특성상 건물 내부에서만 진행되기에 장착하지 않음.

38 ict 소형단말 (15)

작품의 뒷모습. 실제로 착용을 하고(목걸이형식) 실험을 해야하기 때문에, 배터리를 장착하여 전원 코드에서 독립되도록 진행
목걸이 부위에서 사람의 뒷목에 닿는 부분, 이 곳에는 가속도 센서를 장착하여 현재 착용자의 몸이 앞/뒤/양옆 으로 기울었는지를 판단한다.

소스코드

[Motion.sh의 전문]

sudo modprobe bcm2835-v4l2
uv4l –driver raspicam –auto-video_nr –nopreview
LD_PRELOAD=/usr/lib/uv4l/uv4lext/armv6l/libuv4lext.so
motion -c ./ motion.conf

[Start.sh의 전문]

python /home/pi/Adafruit-Raspberry-Pi-Python-Code/Adafruit_LSM303/ Adafruit_LSM303.py &
python /home/pi/Adafruit-Raspberry-Pi-Python-Code/Adafruit_LSM303/ TSL2561.py &
java -jar FTP.jar &

[LM303.py의 전문]

from Adafruit_I2C import Adafruit_I2C
import math
import time
import RPi.GPIO as GPIO
import commands
import datetime
originX = 1000
originY = 1000
originZ = 1000

class Adafruit_LSM303(Adafruit_I2C):
LSM303_ADDRESS_ACCEL = (0×32 >> 1) # 0011001x # Default Type
LSM303_REGISTER_ACCEL_CTRL_REG1_A = 0×20 # 00000111 rw LSM303_REGISTER_ACCEL_CTRL_REG4_A = 0×23 # 00000000 rw LSM303_REGISTER_ACCEL_OUT_X_L_A = 0×28

def __init__(self, busnum=-1, debug=False, hires=False):
self.accel = Adafruit_I2C(self.LSM303_ADDRESS_ACCEL, busnum, debug)
self.accel.write8(self.LSM303_REGISTER_ACCEL_CTRL_REG1_A, 0×27)
if hires:
self.accel.write8(self.LSM303_REGISTER_ACCEL_CTRL_REG4_A,
0b00001000)
else:
self.accel.write8(self.LSM303_REGISTER_ACCEL_CTRL_REG4_A, 0) def accel12(self, list, idx):
n = list[idx] | (list[idx+1] << 8) # Low, high bytes
if n > 32767: n -= 65536 # 2’s complement signed
return n >> 4 # 12-bit resolution

def read(self):
list = self.accel.readList(
self.LSM303_REGISTER_ACCEL_OUT_X_L_A | 0×80, 6)
xyz = [self.accel12(list,0),
self.accel12(list,2),
self.accel12(list,4)] x = xyz[0] y = xyz[1] z = xyz[2] angles = [x,y,z] if x != 0 : angles[0] = math.atan( x / math.sqrt( math.pow(y,2) + math.pow(z,2) ) )
else :
angles[0] = 0
if y != 0 :
angles[1] = math.atan( y / math.sqrt( math.pow(x,2) + math.pow(z,2) ) )
else :
angles[1] = 0
if z != 0 :
angles[2] = math.atan( math.sqrt( math.pow(x,2) + math.pow(y,2) )/z )
else :
angles[2] = 0
angles[0] *= 180
angles[0] /= 3.141592
angles[1] *= 180
angles[1] /= 3.141592
angles[2] *= 180
angles[2] /= 3.141592
angles[0] = int(angles[0])
angles[1] = int(angles[1])
angles[2] = int(angles[2])
global originX
global originY
global originZ
if(originX != 1000 or originY != 1000 or originZ != 1000):
#if(angles[0] >= originX+10 or angles[0] <= originX-10) or (angles[1] >= originY+10 or angles[1] <= originY-10) or (angles[2] >= originZ+10 or angles[2] <= originZ-10):
if(angles[1] >= originY+10 or angles[1] <= originY-10):
print “alarm”
output = commands.getstatusoutput(“aplay /home/pi/PipeWarp.wav”)
GPIO.setmode(GPIO.BCM)
GPIO.setup(23 , GPIO.IN)
if GPIO.input(23)==0:
print “Button pressed!”
time.sleep(1)
print “Press the button (CTRL-C to exit)”
originX = angles[0] originY = angles[1] originZ = angles[2] print (“setup”, originX, originY, originZ)
return angles
if __name__ == ‘__main__’:
from time import sleep
s = datetime.datetime.now()
lsm = Adafruit_LSM303()
count = 1
time_count =1
print ‘[(Accelerometer X, Y, Z)]’
while True:
an = lsm.read()
print an
if(time_count < 30) :
f = open(“/home/pi/accelData”+str(count)+”.txt”, “a”)
f.write(str(lsm.read())+”\n”)
if(time_count > 30) :
count += 1
time_count = 1

sleep(1)
time_count += 1

 

[TSL2561.py의 전문]

#!/usr/bin/python
import sys
import time from Adafruit_I2C
import Adafruit_I2C
import os class TSL2561:
i2c = None
def __init__(self, address=0×39, debug=0, pause=0.8):
self.i2c = Adafruit_I2C(address)
self.address = address
self.pause = pause
self.debug = debug
self.gain = 0 # no gain preselected
self.i2c.write8(0×80, 0×03) # enable the device
def setGain(self,gain=1):
“”” Set the gain “””
if (gain != self.gain):
if (gain==1):
self.i2c.write8(0×81, 0×02) # set gain = 1X and timing = 402 mSec
if (self.debug):
print “Setting low gain”
else:
self.i2c.write8(0×81, 0×12) # set gain = 16X and timing = 402 mSec
if (self.debug):
print “Setting high gain”
self.gain=gain; # safe gain for calculation
time.sleep(self.pause) # pause for integration (self.pause must be bigger than integration time)
def readWord(self, reg):
“””Reads a word from the I2C device”””
try:
wordval = self.i2c.readU16(reg)
newval = self.i2c.reverseByteOrder(wordval)
if (self.debug):
print(“I2C: Device 0x%02X returned 0x%04X from reg 0x%02X” % (self.address, wordval & 0xFFFF, reg))
return newval
except IOError:
print(“Error accessing 0x%02X: Check your I2C address” % self.address)
return -1
def readFull(self, reg=0x8C):
“””Reads visible+IR diode from the I2C device”””
return self.readWord(reg);
def readIR(self, reg=0x8E):
“””Reads IR only diode from the I2C device”””
return self.readWord(reg);
def readLux(self, gain = 0):
“””Grabs a lux reading either with autoranging (gain=0) or with a specified gain (1, 16)”””
if (gain == 1 or gain == 16):
self.setGain(gain) # low/highGain
ambient = self.readFull()
IR = self.readIR()
elif (gain==0): # auto gain
self.setGain(16) # first try highGain
ambient = self.readFull()
if (ambient < 65535):
IR = self.readIR()
if (ambient >= 65535 or IR >= 65535): # value(s) exeed(s) datarange
self.setGain(1) # set lowGain
ambient = self.readFull()
IR = self.readIR()
if (self.gain==1):
ambient *= 16 # scale 1x to 16x
IR *= 16 # scale 1x to 16x
ratio = (IR / float(ambient)) # changed to make it run under python 2
if (self.debug):
print “IR Result”, IR
print “Ambient Result”, ambient
if ((ratio >= 0) & (ratio <= 0.52)):
lux = (0.0315 * ambient) – (0.0593 * ambient * (ratio**1.4))
elif (ratio <= 0.65):
lux = (0.0229 * ambient) – (0.0291 * IR)
elif (ratio <= 0.80):
lux = (0.0157 * ambient) – (0.018 * IR)
elif (ratio <= 1.3):
lux = (0.00338 * ambient) – (0.0026 * IR)
elif (ratio > 1.3):
lux = 0
return lux
if __name__ == “__main__”:
count = 1
time_count = 1
while True:
tsl=TSL2561()
print tsl.readLux(1)
f = open(“/home/pi/lightData”+str(count)+”.txt”,”a”)
if(time_count < 30) :
f.write(str(tsl.readLux(1))+”\n”)
if(time_count > 30) :
count += 1
time_count = 1
time.sleep(1)
time_count += 1

[FTP.java의 전문]

import org.apache.commons.net.ftp.*;
import java.io.*;
public class FTP {
FTPClient client = new FTPClient();
Thread th;
Thread th2;
Thread th3;
public FTP() throws IOException{
th3 = new Thread(execMnM);
try{
client.connect(“server address”);
boolean login = client.login(“Login ID”,”Password”);
if(login){
System.out.println(“Login Success.”);
try{
client.changeWorkingDirectory(“Working Directory”);
System.out.println(client.printWorkingDirectory());
}catch(Exception se){
se.printStackTrace();
}
th3.start();
}else{
System.out.println(“Login fail…”);
}
while(true){
FileInputStream fis;
File file = new File(“./”);
String[] a = file.list();
client.setFileTransferMode(1);
for(int i = 0; i < a.length; i++){
if(a[i].contains(“.txt”)){
Thread.sleep(500);
if(new File(“./”+a[i]).length() > 620){
fis = new FileInputStream(a[i]);
client.setFileType(FTPClient.BINARY_FILE_TYPE);
boolean isuploaded = client.storeFile(a[i], fis);
System.out.println(a[i]+”’s upload complete? : “+isuploaded);
File up = new File(a[i]);
up.delete();
}
}
if(a[i].contains(“.jpg”)){
Thread.sleep(500);
fis = new FileInputStream(a[i]);
client.setFileType(FTPClient.BINARY_FILE_TYPE);
boolean isuploaded = client.storeFile(a[i], fis);
System.out.println(a[i]+”’s upload complete? : “+isuploaded);
File up = new File(a[i]);
up.delete();
}
}
}
}catch(Exception e){
e.printStackTrace();
}finally{
try{
client.disconnect();
}catch(Exception e){
e.printStackTrace();
}
}
} Runnable execMnM = new Runnable(){
public void run(){
try{ Runtime.getRuntime().exec(“./Motion.sh”); }catch(Exception e){}
while(true){
try{ Runtime.getRuntime().exec(“./Mic.sh”); }catch(Exception e){}
}
}
};
public static void main(String[] ar)throws IOException{
new FTP();
}
}

 

 

Leave A Comment

*