November 22, 2024

디바이스마트 미디어:

[66호] 원하는 색상으로 제어가 가능한 아두이노 IoT 스마트 무드등 키트 -

2021-06-25

★2021 ICT 융합 프로젝트 공모전 결과 발표! -

2021-05-12

디바이스마트 국내 온라인 유통사 유일 벨로다인 라이다 공급! -

2021-02-16

★총 상금 500만원 /2021 ICT 융합 프로젝트 공모전★ -

2021-01-18

디바이스마트 온라인 매거진 전자책(PDF)이 무료! -

2020-09-29

[61호]음성으로 제어하는 간접등 만들기 -

2020-08-26

디바이스마트 자체제작 코딩키트 ‘코딩 도담도담’ 출시 -

2020-08-10

GGM AC모터 대량등록! -

2020-07-10

[60호]초소형 레이더 MDR, 어떻게 제어하고 활용하나 -

2020-06-30

[60호]NANO 33 IoT보드를 활용한 블루투스 수평계 만들기 -

2020-06-30

라즈베리파이3가 드디어 출시!!! (Now Raspberry Pi 3 is Coming!!) -

2016-02-29

MoonWalker Actuator 판매개시!! -

2015-08-27

디바이스마트 레이저가공, 밀링, 선반, 라우터 등 커스텀서비스 견적요청 방법 설명동영상 입니다. -

2015-06-09

디바이스마트와 인텔®이 함께하는 IoT 경진대회! -

2015-05-19

드디어 adafruit도 디바이스마트에서 쉽고 저렴하게 !! -

2015-03-25

[29호] Intel Edison Review -

2015-03-10

Pololu 공식 Distributor 디바이스마트, Pololu 상품 판매 개시!! -

2015-03-09

[칩센]블루투스 전 제품 10%가격할인!! -

2015-02-02

[Arduino]Uno(R3) 구입시 37종 센서키트 할인이벤트!! -

2015-02-02

[M.A.I]Ahram_ISP_V1.5 60개 한정수량 할인이벤트!! -

2015-02-02

[54호]원버튼 핸드폰 찾기

54 ict 원버튼 (1)

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

원버튼 핸드폰 찾기

글 | 서경대학교 이승규

1. 심사평
칩센 간단한 아이디어지만, 생활에서의 불편함을 잘 캐치하였으며, 어떤 방향으로 해결할지에 대한 아이디어도 좋습니다. 다만 실제 구현한 동영상이나, 제품 이미지가 없으며, 보고서도 다른 사람에 비해서는 조금 부족한듯 한 것이 아쉽습니다.
뉴티씨 재미있는 내용의 작품으로 구성하였으며, 최근에 핫할 수 있는 아이템으로 재미있게 구성되었습니다. 다만, 핸드폰에서 반대쪽을 찾는 부분도 구현하고, 데이터의 보안성도 고려하였으면 더 좋은 작품이 되었을 것 같습니다. 작품의 동작 인터페이스 부분에서 일반인들도 알아볼 수 있도록 고려하여, 그래픽을 좀 넣고 하였으면 좋았을 것 같습니다. 모든 작품은 동작 자체도 중요하지만, 디자인도 절반이 중요하다는 생각을 하면 다음에는 좀 더 좋은 작품으로 만날 수 있을 것 같습니다. 훌륭한 프로그래머로 성장하시길 바랍니다.
위드로봇 매일 사용하는 핸드폰에 관한 아이디어는 실용적입니다. 하지만 별도의 서버가 필요없는 앱만으로 구현하는 것이 더 나았을 것 같습니다.

2. 작품 개요
현대사회를 살아가는데 핸드폰은 가장 중요한 수단이며 모든 사람들이 사용을 한다. 하지만 남에게 피해를 주기 싫어하며 핸드폰 벨소리가 시끄럽기 때문에 무음으로 해놓고 많은 시간을 보낸다. 그러는 도중에 집에 오거나 실내로 들어오면 핸드폰을 던져놓고 다른 일을 하기 바쁘며 주변에 던져진 옷이나 물건들로 인해 휴대폰이 금방 사라지며 어디다가 뒀는지 금새 잊어버리기 바쁘다.
그럴 때 짜증 날뿐더러 많은 시간을 소비하게 돼서 시간이 아깝다. 이런 경우를 해결하기 위해 핸드폰을 원격으로 벨 소리를 바꿔줄 수 없을까 하는 생각에서 이 작품을 만들게 되었으며 한걸음 더 나아가 쉽게 해결하기 위해서 라즈베리파이를 이용해서 버튼을 한번 클릭하는 것만으로 핸드폰에 소리를 내야겠다고 생각했다.

3. 작품 설명
3.1. 주요 동작 및 특징
라즈베리파이에 GPIO핀을 이용한 버튼을 누르면 핸드폰이 무음에서 벨소리로 바뀌면서 알림음을 울리게 된다.

3.2. 전체 시스템 구성
가장 중요하다고 볼 수 있는 메인 소켓서버를 pc에서 구성한다. 단 pc에 있는 서버는 꺼지지 않는다고 가정을 하며 라즈베리파이에서는 파이썬을 이용해서 소켓으로 버튼이 눌러질때만 메시지를 메인서버로 전송한다.
그 다음 안드로이드 어플은 라즈베리에서 보낸 ‘Hi’ 메시지를 받을수 있도록 구성을 한 뒤 메시지를 받으면 무음에서 벨소리로 바뀌며 알림음을 한 번 낼 수 있도록 구성했다.

3.3. 개발환경
메인 서버와 라즈베리파이는 파이썬으로 개발했으며 어플은 자바(안드로이드 스튜디오)로 개발했다.

3.4. 단계별 제작과정
먼저 메인 서버를 파이썬으로 구성해서 제작하였다. 그 다음 자바를 이용해서 어플을 개발 하였다. 어플은 항상 서버를 유지하고 UI환경에서 벗어나더라도 동작하게 서비스로 만들었다.
라즈베리파이에서 파이썬을 이용하여 소켓으로 메시지를 전송하였다.

3.5. 소스코드
1. 메인 서버 파이썬 코드:

Server.py

from socket import *
from threading import *
from select import *
cli_list =[] cli_id = [] class Connect(Thread):
def __init__(self):
Thread.__init__(self)
sevip = ’192.168.0.13′
sevport = 6000
sevaddr = (sevip,sevport)
self.mysocket = socket(AF_INET,SOCK_STREAM)
self.mysocket.bind(sevaddr)
self.mysocket.listen(10)

def run(self):
while True:
clisock, addr = self.mysocket.accept()
cli_list.append(clisock)
cli_id.append(clisock.fileno())
print(“{}->{}가접속”.format(clisock,clisock.fileno()))
receive = Receive(clisock)
send = Send(clisock)
receive.start()
send.start()
class Send(Thread):
def __init__(self,clisock):
Thread.__init__(self)
self.clisock = clisock
def run(self):
while True:
data = input()
for i in cli_list:
i.sendall(bytes(data,’UTF-8′))
class Receive(Thread):
def __init__(self,clisock):
Thread.__init__(self)
self.clisock = clisock
def run(self):
while True:
try:
data =self.clisock.recv(1024)

for i in cli_list:
i.send(data)

except ConnectionError:
print(“{}와 연결 끊김”.format(self.clisock.fileno()))
break
if data == None:
print(“{}응답없음”.format(self.clisock.fileno()))
break

try:
print(self.clisock.fileno(),” : “,data.decode(‘UTF-8′))
except UnicodeDecodeError:
pass
cli_id.remove(self.clisock.fileno())
cli_list.remove(self.clisock)
self.clisock.close()
print(‘클라이언트 정상종료 ——’)

a = Connect()
a.start()

위의 소스코드를 실행하고 나면 소켓에 연결을 기다리는 대기창이 뜬다.

2. 안드로이드 클라이언트 소스:

MyService.java

package com.example.tmdrb.cc;

/**
* Created by tmdrb on 2018-02-28.
*/

import android.annotation.TargetApi;
import android.app.Service;
import android.content.Intent;
import android.media.AudioManager;
import android.media.Ringtone;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Handler;
import android.os.IBinder;
import android.renderscript.ScriptGroup;
import android.support.annotation.NonNull;
import android.util.Log;
import android.widget.TextView;
import android.widget.Toast;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.Socket;
import java.net.SocketException;

import android.app.NotificationManager;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.media.AudioManager;
import android.media.Ringtone;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Vibrator;
import android.support.annotation.Nullable;
import android.util.Log;
import android.widget.TextView;
import android.widget.Toast;
import com.example.tmdrb.cc.MainActivity;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.net.SocketException;
import java.security.Provider;

public class MyService extends Service {
Vibrator vibrator;
Handler handler;
Socket socket;
StringBuffer buffer;
InputStream inputStream;
Ringtone ringtone;
AudioManager manager;
TextView textView;
Uri uri;
@Nullable
@Override

public IBinder onBind(Intent intent) {
return null;
}
public void onCreate(){
super.onCreate();
}
public int onStartCommand(Intent intent,int flags, int startId){
Start();

return super.onStartCommand(intent,flags,startId);
}

private void change(){

try{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
manager = (AudioManager) getSystemService(AUDIO_SERVICE);

}
manager.setRingerMode(2);
int max = manager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
manager.setStreamVolume(AudioManager.STREAM_RING,max,0);
}
catch (Exception e){
Log.d(“tag”,”error”);}
Log.d(“tag”,”changed”);

uri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
ringtone = RingtoneManager.getRingtone(getApplicationContext(),uri);
ringtone.play();
Log.d(“tag”,”Ring”);
}
void Start(){
Connect con = new Connect();
con.start();

}
class Receive extends Thread{
Vibrator vibrator;
Message message;
byte [] bi;
String result;
int len;
public void run(){
super.run();
while(true) {

try {
buffer = new StringBuffer();
inputStream = socket.getInputStream();
bi = new byte[1024];
while((len = inputStream.read(bi)) != -1){
buffer.append(new String(bi,0,len));
result = buffer.toString();
break;

}
Log.d(“tag”,result);
if(inputStream != null) {
Change c = new Change();
c.start();
}

}catch(SocketException e){
try {
socket.close();
Log.d(“tag”,”disconnect”);
break;
} catch (IOException e1) {
e1.printStackTrace();
}
}
catch (IOException e) {
e.printStackTrace();
}
}
}
}
class Change extends Thread{

@Override
public void run() {
super.run();
change();
}
private void change() {
manager = (AudioManager) getSystemService(AUDIO_SERVICE);
manager.setRingerMode(2);
int max = manager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
manager.setStreamVolume(AudioManager.STREAM_RING,max,0);
uri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
ringtone = RingtoneManager.getRingtone(getApplicationContext(),uri);
for(int i =0;i<10;i++){
ringtone.play();
}}
}
class Connect extends Thread {
Receive receive = new Receive();
public void run() {
while (true){
try {

Log.d(“tag”,”아직 대기중”);
socket = new Socket(“192.168.0.13″,6000);
Log.d(“tag”,”연결 성공”);
receive.start();
if(socket !=null)
break;

} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
MainActivity.java
package com.example.tmdrb.cc;

import android.content.Context;
import android.content.Intent;
import android.os.StrictMode;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

Intent intent;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
intent = new Intent(getApplicationContext(),MyService.class);
startService(intent);
}
}
activity_main.xml

<?xml version=”1.0″ encoding=”utf-8″?>
<android.support.constraint.ConstraintLayout xmlns:android=”http://schemas.android.com/apk/res/android”
xmlns:app=”http://schemas.android.com/apk/res-auto”
xmlns:tools=”http://schemas.android.com/tools”
android:layout_width=”match_parent”
android:layout_height=”match_parent”
tools:context=”com.example.tmdrb.cc.MainActivity”>

<TextView
android:layout_width=”wrap_content”
android:layout_height=”wrap_content”
android:text=”Hello World!”
app:layout_constraintBottom_toBottomOf=”parent”
app:layout_constraintLeft_toLeftOf=”parent”
app:layout_constraintRight_toRightOf=”parent”
app:layout_constraintTop_toTopOf=”parent” />

</android.support.constraint.ConstraintLayout>

AndroidManifest.xml
<?xml version=”1.0″ encoding=”utf-8″?>
<manifest xmlns:android=”http://schemas.android.com/apk/res/android”
package=”com.example.tmdrb.cc”>

<uses-permission android:name=”android.permission.INTERNET”></uses-permission>
<uses-permission android:name=”android.permission.VIBRATE”></uses-permission>
<uses-permission android:name=”android.permission.ACCESS_NOTIFICATION_POLICY”></uses-permission>
<uses-permission android:name=”android.permission.RECEIVE_BOOT_COMPLETED”></uses-permission>
<application
android:allowBackup=”true”
android:icon=”@mipmap/ic_launcher”
android:label=”@string/app_name”
android:roundIcon=”@mipmap/ic_launcher_round”
android:supportsRtl=”true”
android:theme=”@style/AppTheme”>
<activity android:name=”.MainActivity”>
<intent-filter>
<action android:name=”android.intent.action.MAIN” />

<category android:name=”android.intent.category.LAUNCHER” />
</intent-filter>
</activity>
<receiver
android:name=”.Boot”
android:enabled=”true”
android:exported=”false”
android:label=”BOOT”>
<intent-filter >
<action android:name=”android.intent.action.BOOT_COMPLETED”/>
</intent-filter>
</receiver>
<service android:name=”.MyService”></service>
</application>
</manifest>



안드로이드 소스코드를 실행하면 클라이언트가 접속했다는 정보를 출력해주는 창이 뜬다.

3. 라즈베리파이 클라이언트 소스

raspberrypi network.py

from threading import *
from socket import *
import time
import RPi.GPIO as GPIO

GPIO.setmode(GPIO.BCM)
GPIO.setup(6,GPIO.IN,pull_up_down = GPIO.PUD_UP)
socket = socket(AF_INET,SOCK_STREAM)

class Send(Thread):
def __init__(self,socket):
Thread.__init__(self)
self.socket = socket
def run(self):
while True:
GPIO.setup(6,GPIO.IN,pull_up_down = GPIO.PUD_UP)
if GPIO.input(6) == 0:
self.socket.send(‘hi’)
time.sleep(2)

class Connect(Thread):
def __init__(self,socket):
Thread.__init__(self)
self.socket = socket
def run(self):
while True:
try:
self.socket.connect((’192.168.0.13′,6000))
send = Send(self.socket)
send.start()
except:
pass
c = Connect(socket)
c.start()



위의 소스코드를 실행하면 클라이언트로 접속했다는 정보를 출력을 해준다.

54 ict 원버튼 (2)

메인 PC 서버에는 안드로이드 클라이언트와 라즈베리파이의 클라이언트가 존재하게 된다. 이제 라즈베리 파이에서 버튼을 누르면 ‘Hi’라는 메시지가 메인 PC서버로 전송 된다.
그리고 메인 PC 서버는 다시 안드로이드로 ‘Hi’라는 메시지를 보내주게 된다. 이로써 안드로이드에서 ‘Hi’라는 메시지를 전달받음과 동시에 무음에서 벨소리로 전환되며 메시지를 받은 개수 만큼 알림음을 최대 볼륨으로 울려준다.
라즈베리파이 회로도:

54 ict 원버튼 (3)

Leave A Comment

*