아마존에서 제공하는 Alexa를 raspberry pi에 올려보자

https://github.com/ewenchou/alexa-client

위 URL을 따라가서 지시에 따라 alexa client를 사용해보도록 한다.


test_ask.py 파일은 영어로 된 wav파일을 요청하면 그에 맞는 alexa의 대답을 영어로된 wav파일로 반환해준다.

여기서 입력과 출력을 한글로 변경해보도록 하자.


먼저 한글 음성, 영어 음성을 각각 text로 변환시켜줄 STT와 텍스트를 음성으로 변환 시켜줄 TTS 그리고 번역이 필요하다.

각 부분에 대해 사용할 것은 다음과 같다.

STT : Google Cloud Speech API

TTS : Naver 음성합성 API

번역 : Naver 기계번역 API


Google Cloud Speech API

위 주소의 지시를 따라 debian에서 Google Cloud SDK 환경을 설치한다. 환경이 준비 되었다면 다음 URL을 따라서 Google Cloud Speech API를 사용하는 법에 대해 배워 보고, 제대로 작동되는지 예제를 다뤄보라.

https://cloud.google.com/speech/docs/getting-started


Naver API

TTS 설명 및 예시


Translation 설명 및 예시

https://developers.naver.com/docs/labs/translator/


이제 준비가 다 되었다. 한글로 말하면 한글로 대답해주는 나만의 korean Alexa를 python 코드로 구현해 보자.


korean Alexa

def transcribe_file_kor(speech_file):
    """Transcribe the given audio file."""
    
    speech_client = speech.Client()

    with io.open(speech_file, 'rb') as audio_file:
        content = audio_file.read()
        audio_sample = speech_client.sample(
            content=content,
            source_uri=None,
            encoding='LINEAR16',
            sample_rate_hertz=16000)

    alternatives = audio_sample.recognize('ko-KR')
    for alternative in alternatives:
		return alternative.transcript
		
def transcribe_file_eng(speech_file):
    """Transcribe the given audio file."""
    
    speech_client = speech.Client()

    with io.open(speech_file, 'rb') as audio_file:
        content = audio_file.read()
        audio_sample = speech_client.sample(
            content=content,
            source_uri=None,
            encoding='LINEAR16',
            sample_rate_hertz=16000)

    alternatives = audio_sample.recognize('en-US')
    for alternative in alternatives:
		return alternative.transcript

 이 코드는 Google Cloud Speech API를 사용하여 각각 한글로 된 음성파일을 한글 텍스트로, 영어로 된 음성파일을 영어 텍스트로 변환 시켜주는 코드이다. 



def translateKorToEng(korean_string):
	client_id = "YOUR_CLIENT_ID"
	client_secret = "YOUR_CLIENT_SECRET"
	encText = urllib.parse.quote(korean_string.encode("utf-8"))
	data = "source=ko&target=en&text=" + encText
	url = "https://openapi.naver.com/v1/language/translate"
	request = urllib.request.Request(url)
	request.add_header("X-Naver-Client-Id",client_id)
	request.add_header("X-Naver-Client-Secret",client_secret)
	response = urllib.request.urlopen(request, data=data.encode("utf-8"))
	rescode = response.getcode()
	if(rescode==200):
		response_body = json.loads(response.read().decode('utf-8'))
		translated_eng_str = response_body["message"]["result"]["translatedText"]
		return translated_eng_str
	else:
		print("Error Code:" + rescode)
		

def translateEngToKor(english_string):
	client_id = "YOUR_CLIENT_ID"
	client_secret = "YOUR_CLIENT_SECRET"
	encText = urllib.parse.quote(english_string.encode("utf-8"))
	data = "source=en&target=ko&text=" + encText
	url = "https://openapi.naver.com/v1/language/translate"
	request = urllib.request.Request(url)
	request.add_header("X-Naver-Client-Id",client_id)
	request.add_header("X-Naver-Client-Secret",client_secret)
	response = urllib.request.urlopen(request, data=data.encode("utf-8"))
	rescode = response.getcode()
	if(rescode==200):
		response_body = json.loads(response.read().decode('utf-8'))
		translated_kor_str = response_body["message"]["result"]["translatedText"]
		return translated_kor_str
	else:
		print("Error Code:" + rescode) 

 위 코드는 Naver 기계번역 API를 이용하여 한글을 영어로, 영어를 한글로 번역해주는 코드이다. client_id, client_secret 변수에는 자신이 할당 받은 id 와 secret을 적어 넣으면 된다.



def koreanTextToSpeech(korean_string):
	client_id = "YOUR_CLIENT_ID"
	client_secret = "YOUR_CLIENT_SECRET"
	encText = urllib.parse.quote(korean_string.encode("utf-8"))
	data = "speaker=mijin&speed=0&text=" + encText;
	url = "https://openapi.naver.com/v1/voice/tts.bin"
	request = urllib.request.Request(url)
	request.add_header("X-Naver-Client-Id",client_id)
	request.add_header("X-Naver-Client-Secret",client_secret)
	response = urllib.request.urlopen(request, data=data.encode('utf-8'))
	rescode = response.getcode()
	if(rescode==200):
		print("TTS mp3")
		response_body = response.read()
		with open('response_audio_file_path.mp3', 'wb') as f:
			f.write(response_body)
	else:
		print("Error Code:" + rescode)

 위 코드는 한국어 TTS코드로 Naver 음성합성 API를 이용하여 한글 텍스트 파일을 요청하면 한국어 음성파일을 반환하는 코드이다. 마찬가지로 자신의 client_id 와 client_secret을 넣어주면 된다. "output_audio_file_path.mp3" 에는 음성파일을 반환받기 원하는 경로와 파일명을 정해주면 된다.



def askToAlexa():
    alexa = AlexaClient()
    input = 'your_request_audio_path.wav'
    save_to = 'your_response_audio_path.mp3'
    alexa.ask(input, save_to=save_to)
    print "Response from Alexa saved to {}".format(save_to) 

 마지막으로 영어 음성파일을 Alexa에게 전달하고 그에 대한 답변을 음성파일로 받는 함수이다.  input과 save_to에 각각 자신의 요청파일과 반환받기 원하는 파일의 경로와 파일명을 넣으면 된다. 


이제 조각 들을 모두 모았으니 하나로 합쳐보자!


# -*- coding: utf-8 -*-
import io
import sys
import os
import json
from six.moves import urllib
from alexa_client import AlexaClient
from google.cloud import speech

def transcribe_file_kor(speech_file):
    """Transcribe the given audio file."""
    
    speech_client = speech.Client()

    with io.open(speech_file, 'rb') as audio_file:
        content = audio_file.read()
        audio_sample = speech_client.sample(
            content=content,
            source_uri=None,
            encoding='LINEAR16',
            sample_rate_hertz=16000)

    alternatives = audio_sample.recognize('ko-KR')
    for alternative in alternatives:
		return alternative.transcript
		
def transcribe_file_eng(speech_file):
    """Transcribe the given audio file."""
    
    speech_client = speech.Client()

    with io.open(speech_file, 'rb') as audio_file:
        content = audio_file.read()
        audio_sample = speech_client.sample(
            content=content,
            source_uri=None,
            encoding='LINEAR16',
            sample_rate_hertz=16000)

    alternatives = audio_sample.recognize('en-US')
    for alternative in alternatives:
		return alternative.transcript
		
		
def translateKorToEng(korean_string):
	client_id = "YOUR_CLIENT_ID"
	client_secret = "YOUR_CLIENT_SECRET"
	encText = urllib.parse.quote(korean_string.encode("utf-8"))
	data = "source=ko&target=en&text=" + encText
	url = "https://openapi.naver.com/v1/language/translate"
	request = urllib.request.Request(url)
	request.add_header("X-Naver-Client-Id",client_id)
	request.add_header("X-Naver-Client-Secret",client_secret)
	response = urllib.request.urlopen(request, data=data.encode("utf-8"))
	rescode = response.getcode()
	if(rescode==200):
		response_body = json.loads(response.read().decode('utf-8'))
		translated_eng_str = response_body["message"]["result"]["translatedText"]
		return translated_eng_str
	else:
		print("Error Code:" + rescode)
		

def translateEngToKor(english_string):
	client_id = "YOUR_CLIENT_ID"
	client_secret = "YOUR_CLIENT_SECRET"
	encText = urllib.parse.quote(english_string.encode("utf-8"))
	data = "source=en&target=ko&text=" + encText
	url = "https://openapi.naver.com/v1/language/translate"
	request = urllib.request.Request(url)
	request.add_header("X-Naver-Client-Id",client_id)
	request.add_header("X-Naver-Client-Secret",client_secret)
	response = urllib.request.urlopen(request, data=data.encode("utf-8"))
	rescode = response.getcode()
	if(rescode==200):
		response_body = json.loads(response.read().decode('utf-8'))
		translated_kor_str = response_body["message"]["result"]["translatedText"]
		return translated_kor_str
	else:
		print("Error Code:" + rescode)
	
	
	
def koreanTextToSpeech(korean_string):
	client_id = "YOUR_CLIENT_ID"
	client_secret = "YOUR_CLIENT_SECRET"
	encText = urllib.parse.quote(korean_string.encode("utf-8"))
	data = "speaker=mijin&speed=0&text=" + encText;
	url = "https://openapi.naver.com/v1/voice/tts.bin"
	request = urllib.request.Request(url)
	request.add_header("X-Naver-Client-Id",client_id)
	request.add_header("X-Naver-Client-Secret",client_secret)
	response = urllib.request.urlopen(request, data=data.encode('utf-8'))
	rescode = response.getcode()
	if(rescode==200):
		print("TTS mp3")
		response_body = response.read()
		with open('korean_alexa.mp3', 'wb') as f:
			f.write(response_body)
	else:
		print("Error Code:" + rescode)
	
	
"""This test will send a pre-generated audio file in the `tests` directory
to AVS, and saves it as `/tmp/test1.mp3`."""
def askToAlexa():
    alexa = AlexaClient()
    input = 'after_srate_conv.wav'  #'{}/1.wav'.format(TESTS_PATH)
    save_to = 'response_alexa.mp3'
    alexa.ask(input, save_to=save_to)
    print "Response from Alexa saved to {}".format(save_to)


if __name__ == '__main__':

	# 환경 변수 설정
	os.system("export GOOGLE_APPLICATION_CREDENTIALS=\"Your_Google_Service_Account_Key_Path.json\"")
	
	# 인코딩 설정
	reload(sys)
	sys.setdefaultencoding('utf-8')
	
	# 녹음
	os.system("arecord -D plughw:1,0 -f S16_LE -c1 -r16000 -d 3 input.wav")
	print("recording complete!")
	
	# STT 한글
	input_kor_str = transcribe_file_kor('input.wav')
	print(input_kor_str)
	
	# 한글을 영어로 번역
	input_eng_str = translateKorToEng(unicode(input_kor_str))
	print(input_eng_str)
	
	# 영어 TTS
	os.system("espeak -w before_srate_conv.wav \""+input_eng_str+"\"")
	os.system("sox before_srate_conv.wav -r 16000 after_srate_conv.wav")
	print("TTS and srate convert completed")
	
        # alexa
	askToAlexa()
	
	# 영어음성 STT
	os.system("sox response_alexa.mp3 -r 16000 response_alexa_converted.wav")
	output_eng_str = transcribe_file_eng('response_alexa_converted.wav')
	print(output_eng_str)
	
	# 영어문장을 한글로 번역
	output_kor_str = translateEngToKor(output_eng_str).encode("utf-8")
	print(output_kor_str)
	
	# 한글 TTS
	koreanTextToSpeech(unicode(output_kor_str))
	
	# 한글 음성 출력
	os.system("mpg321 korean_alexa.mp3") 

자 이제 한글로 얘기하면 한글로 대답해주는 코드가 완성되었다. 미국 대통령이 누군지 물어보자.








PiFaceCAD를 이용해 음악 플레이어를 만들어보자

기능 ( 버튼과 리모콘을 이용해 구현)

  • 현재 시간 표시
  • Next, Play or Stop, Prev 곡 선택
  • 현재 곡 제목 표시 (화면을 넘어갈 시 왼쪽으로 흐르게 한다.)
  • 볼륨 조절, 음소거 가능

준비물

  • Raspberry PI
  • PiFace CAD
  • IR 리모콘 또는 IR센서가 내장된 스마트폰(IR 리모콘 어플을 받을 것)
  • 스피커 혹은 이어폰

1. PiFace CAD 를 사용하기 위한 SW 설치

SPI Enable on Pi
$ sudo raspi-config
<Advanced Options> - <SPI> - <Yes>
$ sudo reboot
install PiFace CAD Python package

$ sudo apt-get update $ sudo apt-get upgrade $ sudo apt-get install python-pifacecad


2. IR Remote 설정하기

LIRC : Linux Infrared Remote Control

LIRC를 설치하고 재부팅
$ wget https://raw.github.com/piface/pifacecad/master/bin/setup_pifacecad_lirc.sh
$ chmod +x setup_pifacecad_lirc.sh
$ sudo ./setup_pifacecad_lirc.sh
$ sudo apt-get install lirc
$ sudo modprobe lirc_rpi gpio_in_pin=23
$ sudo reboot


3. Configuring LIRC

먼저 어떤 키를 입력할 수 있는 지 확인한다.
$ irrecord --list-namespace

위와 같이 설정 가능한 command들의 list가 나오게 된다.



$ sudo rm /etc/lirc/lircd.conf

$ sudo irrecord -f -d /dev/lirc0 /etc/lirc/lircd.conf

위의 코드를 실행해 자신만의 configuration 을 만들자

실행하면 아래와 같은 창이 나오게 된다. 잘 따라 가보자

그리고 재부팅을 하고나서 잘 등록이 되었는지 확인해보자.

$ sudo reboot
$ irw

위의 명령어를 실행하고 리모콘의 버튼을 눌러 제대로 입력을 받는지 확인한다. 입력이 제대로 되면 다음과 같이 자신이 등록한 키가 버튼을 누를 때마다 나오게된다.


버튼과 그 버튼의 이름이 잘 나오는 것을 확인할 수 있다.



이제 각 버튼에 대한 configuration을 하자.

$ nano ~/.lircrc

begin prog = myprogram button = KEY_OK config = 1 end begin prog = myprogram button = KEY_MENU config = 2 end

~/.lircrc 내용을 위와 같이 수정한다. 내가 아까 입력한 button의 이름을 button에 넣고 config에는 해당 button에 대한 반환값을 자신 임의대로 넣어주자.


$ python >>> import lirc >>> sockid = lirc.init("myprogram") >>> lirc.nextcode() # press KEY_OK on remote after this ['1'] >>> lirc.nextcode() # press KEY_MENU on remote after this ['2']

위 코드를  실행하면 해당 버튼을 눌렀을 때에 설정한 값이 잘 나오는지 확인할 수 있다.


나는 리모콘의 버튼과 config를 아래와 같이 설정하였다.


리모콘 버튼 설정


begin prog = myprogram button = KEY_VOLUMEUP config = 7 end begin prog = myprogram button = KEY_VOLUMEDOWN config = 6 end begin prog = myprogram button = KEY_CHANNELUP config = 3 end begin prog = myprogram button = KEY_CHANNELDOWN config = 1 end begin prog = myprogram button = KEY_MUTE config = 5 end begin prog = myprogram button = KEY_MENU config = 4 end begin prog = myprogram button = KEY_OK config = 2 end

Configuration


4. 음악 플레이어 준비하기

나는 여기서 pygame의 mixer를 사용했기 때문에 pygame이 없다면 설치해 주자.
$ sudo apt-get install mercurial
$ sudo pip install hg+http://bitbucket.org/pygame/pygame


5. 본격적으로 음악 플레이어 만들기

from pygame import mixer # Load the required library
import pifacecad
import time
import datetime
import threading


pin = -1		# PiFaceCAD button
remote = -1		# IR remote control button
volume = 50		# current volume
play = True		# current playing status (playing : True, pause: False)
mute = False	# current mute status
curSong = 0		# current song number
stridx = 0		# current printed song string index

song = ['We Don\'t Talk Anymore.mp3','Closer.mp3','Shape Of You.mp3','Starving.mp3','The Ocean.mp3'\
		,'Happy.mp3','Daft Punk.mp3', 'Chandelier.mp3','The Greatest.mp3', 'Lean On.mp3']

# init LCD
cad = pifacecad.PiFaceCAD()
cad.lcd.backlight_on()
cad.lcd.blink_off()
cad.lcd.cursor_off()

# bitmap
bmp_note = pifacecad.LCDBitmap([2,3,2,2,14,30,12,0])
bmp_play = pifacecad.LCDBitmap([0,8,12,14,12,8,0,0])
bmp_pause = pifacecad.LCDBitmap([0,27,27,27,27,27,0,0])
bmp_clock = pifacecad.LCDBitmap([0,14,21,23,17,14,0,0])
bmp_vol1 = pifacecad.LCDBitmap([1,3,15,15,15,3,1,0])
bmp_vol2 = pifacecad.LCDBitmap([8,16,0,24,0,16,8,0])

cad.lcd.store_custom_bitmap(0, bmp_note)
cad.lcd.store_custom_bitmap(1, bmp_play)
cad.lcd.store_custom_bitmap(2, bmp_pause)
cad.lcd.store_custom_bitmap(3, bmp_clock)
cad.lcd.store_custom_bitmap(4, bmp_vol1)
cad.lcd.store_custom_bitmap(5, bmp_vol2)

 코드의 첫 부분에는 라이브러리의 import와 사용할 전역변수 선언, 노래 리스트 저장, LCD 초기화, LCD에 출력할 bitmap을 저장하였다.



def showTime():			# print current hour and minute
	now = datetime.datetime.now()
	nowTime = now.strftime('%H:%M')
	cad.lcd.set_cursor(10,1)
	cad.lcd.write_custom_bitmap(3)
	cad.lcd.write(nowTime)
	cad.lcd.set_cursor(0,0)

showTime()은 현재 시간과 분을 LCD 오른쪽 아래에 출력 하는 함수이다. 주기적으로 출력하여 시간을 바꾸어 출력해준다.



def updateVolume():		# print current volume without bitmap
	global volume
	cad.lcd.set_cursor(2,1)
	if mute:
		cad.lcd.write('mute')
	else:
		cad.lcd.write(str(volume).rjust(4))
	cad.lcd.set_cursor(0,0)
	
def writeVolume():		# print current volume
	global volume
	global mute
	cad.lcd.set_cursor(0,1)
	cad.lcd.write_custom_bitmap(4)
	cad.lcd.write_custom_bitmap(5)
	updateVolume()

updateVolume() 은 현재 볼륨 상태(0~100)를 LCD왼쪽 아래에 출력한다.  음소거 중 일 경우에는 'mute' 문자열을 출력한다.

writeVolume()은 스피커 모양 비트맵을 함께 출력한다.




def writeBottomLine():	#print LCD bottom line
	global play
	showTime()
	writeVolume()
	cad.lcd.set_cursor(7,1)
	if play:
		cad.lcd.write_custom_bitmap(1)
	else:
		cad.lcd.write_custom_bitmap(2)
	cad.lcd.set_cursor(0,0)

 writeBottomLine()은 말그대로 LCD의 아랫줄을 출력하는 함수이다. showTime() 함수와 writeVolume() 함수를 통해 시간과 볼륨을 출력하고, 현재 재생상태를 읽어서 재생 중이라면 재생모양 비트맵을, 일시정지중이라면 일시정지 비트맵을 출력한다.




def writeTopLine():		#print LCD top line and rotate when length > 16
	global curSong
	global stridx
	
	cad.lcd.set_cursor(0,0)
	str = song[curSong]
	if len(str)>16:
		str_rotate = (str+'    '+str)[stridx:stridx+15]
		stridx += 1
		if stridx == len(str)+4:
			stridx = 0
		cad.lcd.write(str_rotate)
	else :
		cad.lcd.write(str)

 writeTopLine()은 LCD의 윗줄을 출력하는 함수이다. 윗줄에는 노래 제목이 들어가게 되는데, LCD 최대 길이인 16글자를 넘어 갈 경우가 있을 수도 있다. 이 함수는 글자가 16자 이상이라면 한번 실행할 때마다 한 칸씩 흐르게 되어있다. 따라서 main함수에서 writeTopLine()함수를 1초에 한번씩 실행하게 하여 글자가 16자 이상이라면 흐르게 하도록 하자. 





def update_pin_text(event):
	 global pin
	 pin = event.pin_num

def print_ir_code(event):
	 global remote
	 remote = int(event.ir_code)
	 
listener = pifacecad.SwitchEventListener(chip=cad)
for i in range(8):
	listener.register(i, pifacecad.IODIR_FALLING_EDGE, update_pin_text)
listener.activate()

remote_listener = pifacecad.IREventListener(prog='myprogram')
for i in range(8):
	remote_listener.register(str(i), print_ir_code)
remote_listener.activate() 


  listener는 PiFace CAD 의 버튼에 대한 인터럽트이고, remote_listener는 IR리모콘에 대한 인터럽트이다. listener는 PiFace CAD버튼이 눌렸을 때 update_pin_text함수를 실행 시키고, remote_listener는 리모콘이 눌렀을 때 print_ir_code 함수를 실행하게 된다. event.pin_num는 누른 버튼의 번호이고, event.ir_code는 리모콘 버튼에 대응하는 config 값이다. 내가 사용할 버튼들을 listener의 register에 등록하고 그에 대한 콜백함수(update_pin_text, print_ir_code)도 입력한다. 콜백함수에서는 버튼에 대한 값을 전역 변수에 저장하도록 하였다. pin과 remote의 값을 통해 음악플레이어를 조종할 것이다.


음악들은 pygame의 mixer를 통해 재생하고, 조종한다.

mixer.music 에는 여러 함수가 있지만, 여기서 사용할 함수들만 소개하겠다.

pygame.mixer.music.load : 파일을 불러온다.

pygame.mixer.music.play : 불러온 파일을 재생한다.

pygame.mixer.music.get_volume : 현재 볼륨을 반환한다.

pygame.mixer.music.set_volume : 해당 값으로 볼륨을 설정한다.

pygame.mixer.music.get_busy : 불러온 파일 스트림이 진행중인지 확인한다.

pygame.mixer.music.pause : 음악을 일시 정지 한다

pygame.mixer.music.unpause : 음악의 일시정지를 푼다.


인터럽트를 통해 pin과 remote에 어떠한 값이 들어왔을 때 그에 대응하는 mixer.music의 함수를 실행시키는 방식으로 구현해보자.



def musicMainfunc():
	global pin
	global remote
	global volume
	global play
	global mute
	global curSong
	global stridx
	
	curSong = 0
	pin = -1
	remote = -1
	
	mixer.init()
	mixer.music.set_volume(float(volume)/100)
	while True:
		if curSong == len(song):
			curSong = 0
		cad.lcd.clear()
		cad.lcd.blink_off()
		cad.lcd.cursor_off()
		mixer.music.load(song[curSong])
		mixer.music.play()
		writeTopLine()
		count_t = time.time()
		while mixer.music.get_busy() == True:
			writeBottomLine()
			if time.time()-count_t > 1:	# writeTopLine every 1 second
				writeTopLine()
				count_t = time.time()
			# song control
			if pin == 1 or remote == 1:	# prev song
				curSong-=2
				if curSong==-2:
					curSong=len(song)-2
				pin = -1
				remote = -1
				stridx = 0
				break;
			elif pin == 3 or remote == 3:	# next song
				pin = -1
				remote = -1
				stridx = 0
				break;
				
			elif pin == 2 or remote == 2:	# play and pause
				if play:
					mixer.music.pause()
					play = False
				else:
					mixer.music.unpause()
					play = True
				pin = -1
				remote = -1
					
			# volume control
			elif pin == 6 or remote == 6:	# volume down
				while True:
					volume -= 3
					if volume < 0:
						volume = 0
					mixer.music.set_volume(float(volume)/100)
					updateVolume();
					sleep(0.2)
					if not cad.switches[6].value:
						break
				pin = -1
				remote = -1
			elif pin == 7 or remote == 7:	# volume up
				while True:
					volume += 3
					if volume > 100:
						volume = 100
					mixer.music.set_volume(float(volume)/100)
					updateVolume();
					sleep(0.2)
					if not cad.switches[7].value:
						break
				pin = -1
				remote = -1
			elif pin == 5 or remote == 5:	# mute
				if mute:
					mixer.music.set_volume(float(volume)/100)
					mute = False
				else:
					mixer.music.set_volume(0)
					mute = True
				pin = -1
				remote = -1
			elif pin == 4 or remote == 4:	# quit
				pin = -1
				remote = -1
				mixer.quit()
				return
		curSong+=1

 위에서 부터 pin과 remote 값이 1이 되면 이전 곡을 튼다. 3이 되면 다음곡을 틀고, 2가 되면 일시 정지 및 재생을 한다. 6과 7은 볼륨을 낮추고 올리며, 5는 음소거를 하고 해제한다. 마지막으로 4는 mixer를 종료한다.

정리하여 PiFace CAD 버튼과 리모콘 버튼의 역할은 다음과 같다.

1. 이전 곡                         <-  KEY_CHANNELDOWN

2. 재생 및 일시정지            <-  KEY_OK

3. 다음 곡                        <-  KEY_CHANNELUP

4. 종료                            <-  KEY_MENU

5. 음소거 및 해제               <-  KEY_MUTE

6. 볼륨 낮추기                   <-  KEY_VOLUMEUP

7. 볼륨 올리기                   <-  KEY_VOLUMEDOWN



이제 위의 코드들을 합치고 musicMainfunc()을 실행시키면 PiFaceCAD를 이용해 음악플레이어를 확인할 수 있다. 아래의 데모영상을 보고 잘 구현되었는지 확인해보자.







Open API와 python을 연동해보자

먼저 API로는 OpenWeatherMap API를 사용하도록 합니다 

http://openweathermap.org/api


먼저 위 링크를 타고 가면 아래와 같은 페이지가 나오는데,

위 페이지에서 API key 를 클릭합니다.







회원가입을 해야 API key를 받을 수 있기 때문에 회원가입을 하고,



회원가입 후 다시 API key를 받으면,




위와 같이 자신의 키를 받을 수 있습니다. 키를 사용하기까지 키를 받고 나서 10~60분 정도 걸린다고 하니, 안된다고 화내지말고 기다립니다. 다시 API 탭으로 돌아가서 API를 선택합니다.






현재 날씨를 사용할 것이기 때문에 Current weather data의 API doc을 클릭해서 사용법을 알아봅니다.







API 문서에 여러 요청방법들이 있지만, city name을 이용해 요청하는 방법만을 알아보겠습니다.

API call 에 보면

api.openweathermap.org/data/2.5/weather?q={city name}



이라 설명이 나와있고 사실 이 뒤에 자신의 키를 더 입력해야 합니다. 또한 섭씨로 온도를 받기 위해 units=Metric 라는 요청을 추가합니다.

api.openweathermap.org/data/2.5/weather?units=Metric&q={city name}&APPID={your API key}


위 코드에서  {city name}  대신 Seoul을 입력하고 {your API key} 대신 자신의 API키를 넣어서 크롬 주소창에 입력하고 이동해보면, 아래와 같은 JSON 형식의 답변이 오게 됩니다.

{"coord":{"lon":126.98,"lat":37.57},"weather":[{"id":721,"main":"Haze","description":"haze","icon":"50n"},{"id":701,"main":"Mist","description":"mist","icon":"50n"}],"base":"stations","main":{"temp":7.9,"pressure":1020,"humidity":45,"temp_min":4,"temp_max":10},"visibility":10000,"wind":{"speed":2.1,"deg":220},"clouds":{"all":80},"dt":1490435400,"sys":{"type":1,"id":8514,"message":0.008,"country":"KR","sunrise":1490390873,"sunset":1490435317},"id":1835848,"name":"Seoul","cod":200}



Python 에서 API 요청하고 답변받기



python에서 API를 요청하고 답을 받으려면  httplib2 라이브러리가 필요하기 때문에, 콘솔창을 킨 후 다음 명령어를 입력합니다.

$ python -m pip install httplib2


라이브러리를 설치 했으니 lPython 콘솔에 다음과 같은 코드를 입력합니다.

import httplib2
import json

url = 'http://api.openweathermap.org/data/2.5/weather?units=Metric&q='
city = 'Seoul'
mykey = '&APPID=5e19e0a4433cbb1b0a6e5f0e5b784af2'

h = httplib2.Http()
myrequest = url+city+mykey
response, content = h.request(myrequest, 'GET')
result = json.loads(content.decode('utf-8'))


다시 lPython 콘솔에 result를 입력하면 다음과 같은 출력이 나옵니다.

{'base': 'stations',
 'clouds': {'all': 75},
 'cod': 200,
 'coord': {'lat': 37.57, 'lon': 126.98},
 'dt': 1490433600,
 'id': 1835848,
 'main': {'humidity': 65,
  'pressure': 1018,
  'temp': 281.16,
  'temp_max': 283.15,
  'temp_min': 277.15},
 'name': 'Seoul',
 'sys': {'country': 'KR',
  'id': 8519,
  'message': 0.0154,
  'sunrise': 1490390875,
  'sunset': 1490435315,
  'type': 1},
 'visibility': 9000,
 'weather': [{'description': 'haze', 'icon': '50d', 'id': 721, 'main': 'Haze'},
  {'description': 'mist', 'icon': '50d', 'id': 701, 'main': 'Mist'}],
 'wind': {'deg': 320, 'speed': 1.5}}

result는 dictionary 형식으로 저장되어 있으므로, 우리가 원하는 정보만을 빼서 사용하겠습니다.

result 에서 "main"키의 값인 dictionary에서 습도('humidity'), 기온('temp'), 최고기온('temp_max'), 최저기온('temp_min')을 사용하고, 'weather'키에서 날씨('main')을 사용하겠습니다.



서울시의 날씨, 기온, 습도를 나타내는 코드를 다음과 같이 짜보았습니다.

# -*- coding: utf-8 -*-
"""
Created on Sat Mar 25 18:22:28 2017

@author: newkyu
"""

import httplib2
import json

url = 'http://api.openweathermap.org/data/2.5/weather?units=Metric&q='
city = 'Seoul'
mykey = '&APPID=5e19e0a4433cbb1b0a6e5f0e5b784af2'

h = httplib2.Http()
myrequest = url+city+mykey
response, content = h.request(myrequest, 'GET')
result = json.loads(content.decode('utf-8'))

humidity = result['main']['humidity']
temp = result['main']['temp']
temp_max = result['main']['temp_max']
temp_min = result['main']['temp_min']
weather = result['weather'][0]['main']

print('Seoul\'s weather is',weather)
print('Current temperature : ', temp,'°C')
print('Max     temperature : ', temp_max,'°C')
print('Min     temperature : ', temp_min,'°C')
print('Current humidity    : ', humidity,'%')


출력 결과는 아래와 같이 나오게 됩니다.



여태까지 한 것을 통해 서울, 도쿄, 런던, 뉴욕, 파리, 시드니, 나이로비의 현재 날씨와 온도를

보여주는 코드를 짜보았습니다.

# -*- coding: utf-8 -*-
"""
Created on Sat Mar 25 18:22:28 2017

@author: newkyu
"""

import httplib2
import json

url = 'http://api.openweathermap.org/data/2.5/weather?units=Metric&q='
cities = ['Seoul','Tokyo','London','Newyork','Paris','Sydney','Nairobi']
mykey = '&APPID=5e19e0a4433cbb1b0a6e5f0e5b784af2'

h = httplib2.Http()
for city in cities:
    myrequest = url+city+mykey
    response, content = h.request(myrequest, 'GET')
    result = json.loads(content.decode('utf-8'))
    
    humidity = result['main']['humidity']
    temp = result['main']['temp']
    temp_max = result['main']['temp_max']
    temp_min = result['main']['temp_min']
    weather = result['weather'][0]['main']
    
    print(city,'\'s weather is ',weather,sep='')
    print('Current temperature : ', temp,'°C')
    print('Max     temperature : ', temp_max,'°C')
    print('Min     temperature : ', temp_min,'°C')
    print('Current humidity    : ', humidity,'%\n\n')

출력결과

Seoul's weather is Haze
Current temperature :  6.87 °C
Max     temperature :  9 °C
Min     temperature :  4 °C
Current humidity    :  70 %


Tokyo's weather is Clouds
Current temperature :  6.92 °C
Max     temperature :  9 °C
Min     temperature :  5 °C
Current humidity    :  57 %


London's weather is Clear
Current temperature :  11 °C
Max     temperature :  12 °C
Min     temperature :  10 °C
Current humidity    :  50 %


Newyork's weather is Rain
Current temperature :  7.93 °C
Max     temperature :  13 °C
Min     temperature :  3 °C
Current humidity    :  61 %


Paris's weather is Clear
Current temperature :  12.5 °C
Max     temperature :  13 °C
Min     temperature :  12 °C
Current humidity    :  50 %


Sydney's weather is Clear
Current temperature :  23 °C
Max     temperature :  23 °C
Min     temperature :  23 °C
Current humidity    :  73 %


Nairobi's weather is Clouds
Current temperature :  28.45 °C
Max     temperature :  29 °C
Min     temperature :  28 °C
Current humidity    :  32 %


잘 나오는 것을 확인할 수 있습니다. 이제 API에 요청하고 답변받고, python과 연동하는 방법도 알았으니, 다른 API를 통해 자신이 만들고 싶은 프로그램을 만들 수 있을 겁니다. 아래 링크로 가보면 여러 Open API 들이 많으므로 사용해보시기 바랍니다.


https://www.data.go.kr/

+ Recent posts