"기술"에 해당하는 글들
페이지:«1234567...19»

Sony Bravia TV의 웹 EPG 만들기 (두번째)
XMLHttpRequest로 SOAP 메시지 보내기

2013-04-28   //   alexken작성   //   기술  //  No Comments

이전글에 이어서,

이전 방식(Ruby + Server)의 단점은 집에 웹서버를 운영해야 한다는 점이다.
NAS도 어엿한 웹서버이므로 크게 문제될 것은 없지만, 그냥 단말기에서 동작하도록, 즉 HTML측에서 동작하도록 javascript를 이용해 XMLHttpRequest로 soap메시지를 전달하도록 전부 재 작성하였다.

단순 웹페이지라, 브라우저만 있는 기기라면, 스마트폰/태블릿/PC 어디서나, iOS/Android/WP7.5/Windows/MacOSX 무관하게 동작할 것이나, 현재 하늘이 핸드폰인 Lumia 710(WP7.5)의 IE에서만 동작하지 않았고, 나머지 기기에서는 완벽 동작한다.
사용하기 정말 편하며, 만들어 놓고 아주 뿌듯해 하고 있다.

그럼 본문

ircc Command 목록을 조회하는 코드는 다음과 같다.
중요한 점은 “X-CERS-DEVICE-ID”라는 헤더에 TV에 페어링을 통해 등록된 Mac주소를 함께 전송해야 한다. 없으면 403을 반환한다.

var tv_ip = 'XXX.XXX.XXX.XXX';
var client_mac_addr = 'XX-XX-XX-XX-XX-XX';

function getRemoteCommandList(){
  var xhr = new XMLHttpRequest();
  xhr.open('GET', 'http://' + tv_ip + '/cers/api/getRemoteCommandList',true);
  xhr.setRequestHeader("X-CERS-DEVICE-ID", 'MediaRemote:' + client_mac_addr);
  xhr.onreadystatechange=function() {
    if(xhr.status == 200){
      if (xhr.readyState==4) {
        alert(xhr.responseText);
      }
    }else{
      alert(xhr.status);
    }
  }
  xhr.send(null);
}

getRemoteCommandList를 호출하면 TV는 아래와 같은 xml 형태로 리모콘 값에 해당하는 값의 Base64로 인코딩된 값을 반환한다.
전체 커맨드 목록은 이 글 맨 아래에 정리하였다.

< ?xml version="1.0"?>
<remotecommandlist>
 <command name="Confirm" type="ircc" value="AAAAAQAAAAEAAABlAw==" />
 <command name="Up" type="ircc" value="AAAAAQAAAAEAAAB0Aw==" />
 <command name="Down" type="ircc" value="AAAAAQAAAAEAAAB1Aw==" />
  ...
 <command name="OneTouchRecStop" type="ircc" value="AAAAAgAAABoAAABjAw==" />
 <command name="MuteOn" type="url" value="http://_:80/cers/command/MuteOn"/>
 <command name="MuteOff" type="url" value="http://_:80/cers/command/MuteOff"/>    
</remotecommandlist>

마지막 줄에 type이 “ircc”가 아닌 “url”인 MuteOn과 MuteOff가 있는데, 이 url 유형의 command는 soap으로 보내지 않고, 해당 url에 GET만 수행해도 동작하며, 요청 기기의 MAC주소도 확인하지 않는다.
즉 코딩할 필요 없이 웹브라우저에서 해당주소를 입력하고 Enter만 쳐도 동작한다는 얘기다.
특이점은 command는 MuteOn과 MuteOff가 있지만 MuteOff는 동작하지 않고, MuteOn만 토글 형태로 동작한다.
물리적인 리모콘 버튼에서도 [조용히] 하나만 있기 때문에 일맥상통한다.

[조용히]/[조용히 해제]에 해당하는 코드는 아래와 같다.
getRemoteCommandList함수와의 차이점은 커스텀 헤더인 “X-CERS-DEVICE-ID”는 필요치 않다.

function muteOnOff(){          
  var xhr = new XMLHttpRequest();
  xhr.open('GET', 'http://' + tv_ip + '/cers/command/MuteOn',false);
  xhr.send(null);
}

위에서 작성한 getRemoteCommandList()를 통해서 얻은 ircc code를 가지고 직접 리모콘 키를 누르는 것과 동일한 효과를 내는 함수는 다음과 같다. sendIrccCommand에 ircc 코드를 보낼때 마다 리모콘 키 하나를 누르는 행위와 일치한다.

function sendIrccCommand(ircc){
  var body =
    '< ?xml version="1.0"?>'+
    '<s:envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" '+
    ' s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">'+
    '  <s:body>'+
    '    <u:x_sendircc xmlns:u="urn:schemas-sony-com:service:IRCC:1">'+
    '      <ircccode>' + ircc + '</ircccode>'+
    '    </u:x_sendircc>'+
    '  </s:body>'+
    '</s:envelope>';
  var xhr = new XMLHttpRequest();
  xhr.open('POST', 'http://' + tv_ip + '/IRCC',false);
  xhr.setRequestHeader('X-CERS-DEVICE-ID', 'MediaRemote:' + client_mac_addr);
  xhr.setRequestHeader('SOAPAction',     
                        '"urn:schemas-sony-com:service:IRCC:1#X_SendIRCC"');
  xhr.setRequestHeader('Content-Type', 'text/xml; charset=utf-8');
  xhr.send(body);
}

하지만 SBS를 튜닝하기 위해서는 디지털인 경우에 ‘6’, ‘.’, ‘1’과 같이 연속으로 3개의 키를 입력해야 한다.
sendIrccCommand를 좀더 추상화한 setChannel은 아래와 같고, 입력은 ‘6.1’, ‘10.1’ 과 같은 키 시퀀스에 해당하는 문자열을 입력으로 받는다.

function setChannel(ch){

  var num = [
            "AAAAAQAAAAEAAAAJAw==", //0
            "AAAAAQAAAAEAAAAAAw==", //1
            "AAAAAQAAAAEAAAABAw==", //2
            "AAAAAQAAAAEAAAACAw==", //3
            "AAAAAQAAAAEAAAADAw==", //4
            "AAAAAQAAAAEAAAAEAw==", //5
            "AAAAAQAAAAEAAAAFAw==", //6
            "AAAAAQAAAAEAAAAGAw==", //7
            "AAAAAQAAAAEAAAAHAw==", //8
            "AAAAAQAAAAEAAAAIAw=="  //9
  ];
  var dot = "AAAAAgAAAJcAAAAdAw=="  //.

  var c = ch.split("");
  for( var i in c ){
    switch(c[i]){
      case '.' :
        sendIrccCommand( dot );
        break;
      default:
        sendIrccCommand( num[ch[i]] );
        break;
    }
  }
}

더 보기 >>

Sony Bravia TV의 웹 EPG 만들기 (첫번째)
Ruby+Server 버전

2013-04-27   //   alexken작성   //   기술  //  3 Comments

집에 TV는 2년전 구입한 nx720이라는 Sony사 제품이다.
스마트폰에서 제어할 수 있도록 Media Remote라는 앱을 iOS용과 Android용으로 제공하고 있다.

그런데 Android용으로 TV SideView라는 새로운 앱을 제공하기 시작했다.
Media Remote가 리모콘의 단순 대체라면, TV SideView는 음성 컨트롤, EPG를 통한 채널 선택, 저장된 미디어 재생(PVR 모델의 경우)와 같은 새로운 UX를 제공하고, 이중에서 EPG를 통한 채널선택은 TV 사용에 있어 가장 자연스런 UX인거 같다.

그런데, 국가가 [일본/미국]인 경우에는 EPG를 보여주고 해당 채널을 선택할 수 있는 반면, 국가를 [한국]으로 설정해면 EPG 기능이 비활성화 되는 것에 광분하여 자체적으로 만들게 되었다.

조사해본 결과

Sony TV의 경우 IRCC라는 웹서비스를 제공한다.
리모콘 키의 IR 신호에 해당하는 ircc 코드를 HTTP 프로토콜로 SOAP 메시지로 전달하면 리모콘 키를 누른 것과 동일하게 동작한다.
IRCC의 경우에 범용적으로 표준화된 것은 아니고, Sony가 개발한 Sony의 Bravia 브랜드를 사용하는 TV, Blue-lay, PVR 기기에서만 활용되는, 그다지 범용적인 기술 표준은 아니었다.

적당히 EPG 정보를 대충 가져와 그냥 html로 알아서 아래와 같이 변환 후 화면을 터치하면, 해당 프로그램의 채널로 TV가 튜닝하도록 하였다.

ircc command를 soap으로 전송하는 가장 손쉬운 방법은 ruby cers_remote 라이브러리를 이용하면 되고, 웹 서버측 php에서 ruby를 통해 TV로 soap 메시지를 보내게 된다.

ircc가 동작 제한 조건으로

  • ircc의 soap 메시지 header에 TV에 기 등록된 기기의 MAC주소를 보낼 것
  • ircc 전송측과 TV가 동일 네트워크에 있을 것

이 중 MAC 주소는 기존에 Media Remote를 설치해서 TV와 패어링된 스마트폰/태블릿의 MAC 주소여야 하고,송신측이 TV와 동일 네트워크에 있어야 하려면, 웹버서를 집내에서 운영해야 한다.

#!/usr/bin/env ruby

require "cers_device"
tv_ip = "XXX.XXX.XXX.XXX"
paired_device_mac = "XX-XX-XX-XX-XX-XX"

command =
"1"=>"AAAAAQAAAAEAAAAAAw==",
"2"=>"AAAAAQAAAAEAAAABAw==",
"3"=>"AAAAAQAAAAEAAAACAw==",
"4"=>"AAAAAQAAAAEAAAADAw==",
"5"=>"AAAAAQAAAAEAAAAEAw==",
"6"=>"AAAAAQAAAAEAAAAFAw==",
"7"=>"AAAAAQAAAAEAAAAGAw==",
"8"=>"AAAAAQAAAAEAAAAHAw==",
"9"=>"AAAAAQAAAAEAAAAIAw==",
"0"=>"AAAAAQAAAAEAAAAJAw==",
"."=>"AAAAAgAAAJcAAAAdAw=="
}

device = CersDevice.new(tv_ip,paired_device_mac)

if __FILE__ == $0
  ARGV[0].split(//).each{|x|
    device.send_ircc(command[x])
    sleep 1
  }
end

위 파일을 setch 라고 저장하였다면 터미널에서

$setch 11.1

로 채널전환 가능하며, 이를 서버측에서 불러주면됨

HTML5:getUserMedia를 이용한 초간단 웹캠 뷰어를 Nexus7에서

2013-03-12   //   alexken작성   //   기술  //  3 Comments

1년전에 HTML5:getUserMedia를 이용한 초간단 웹캠 뷰어란 글을 쓴적이 있다.
그런데 모처럼 들어가 보니 동작을 하지 않는다.
이유는

  navigator.webkitGetUserMedia("video", success);
  ==>   navigator.webkitGetUserMedia({video:true}, success);

webkitGetUserMedia 첫번째 인자가, 문자열 “video” 가 아니라, JSON 객체 {video:ture}로 넘기도록 좀더 표준에 가까워 졌다.
하지만, webkitGetUserMedia와 webkitURL처럼 webkit prefix는 여전히 붙여줘야 함.

아래와 같이 코드를 수정해서 다시 동작하도록 해놓음.

< !DOCTYPE html>
<html>
  <body>
    <video id="myvideo"  autoplay></video>
    <script type="text/javascript">
      var video = document.getElementById('myvideo');
     
      if(navigator.webkitGetUserMedia){
        navigator.webkitGetUserMedia({video:true}, success, fail);
      }else{ 
        navigator.getUserMedia({video:true}, success, fail);
      }
   
      function success(stream){
        if(window.webkitURL){
          video.src = window.webkitURL.createObjectURL(stream);
        }else{
          video.src = window.URL.createObjectURL(stream);
        }
      }

      function fail(err){
        console.log("The following error occured: " + err);
      }
    </script>
  </body>
</html>

더 보기 >>

블랙베리에서 올리는 포스트

2013-01-04   //   alexken작성   //   기술  //  No Comments

어제부터 가지고 놀기 시작한 다소 철지난 블랙베리 9900에서 올리는 포스팅이다.

목표는 사진 올리고 글작성 모두를 다른 기기 도움없이 여기서 끝내는 것 임.

다행히 WordPress 전용앱이 있었고, 스크린 캡쳐는 CaptureIt에서 할 수 있었다.

뽐뿌의 계기는 블랙베리를 블루투스 키보드로 활용할 수 있어서이고, 안드로이드 기기는 잘 붙고, iOS기기에는 현재까지 안붙음.

9900에서는 이게 좀 짱인게,
한번 붙으면
터치스크린은 멀티터치 지원되는 트랙패드처럼 동작하고, 바로 아래 빨콩으로 마우스처럼 동작하고, 오른쪽 볼륨 버튼은 원격 기기의 물리 버튼 처럼 동작하고, 마지막으로 말이 필요없는 블랙베리 키보드를 블투 키보드로 활용할 수 있다.
농담 아니라 RIM에서 블투 키보드 하나 출시해 주면 좋겠다.

키보드 최고이고,전체적으로 간결하고 깔끔해서 좋긴한데 오래 쓸거 같지는 않음.
필요한 앱도 앱월드에선 찾아지지 않고, 오래된 버전의 OTA를 찾아서 설치해야하고, 지원은 끊긴지 오래고, 시들어 가는 생태계에서 굳이 불편함을 감래하고 싶지는 않다.
블랙베리

블랙베리

iPad의 iBooks에 사전 추가하기

2012-07-24   //   alexken작성   //   기술  //  3 Comments

지난글 “MacOSX용 대한민국 우편번호 사전 만들기“에서 재미삼아 만들어본 사전을 iPad의 iBooks에서 띄우고 싶어서, 순정주의자인 내가 이것 땜에 iPad를 탈옥했다.

MacOSX처럼 /Library/Dictionaries에 복사만 하면 될 줄 알았는데, 복사해도 아무런 반응이 없음.

그래서 포기하고 있었는데, iBooks Dictionaries In Other Languages?에서 방법을 찾음.

MacOSX와 다르게 iOS에서는 앱별로 사전을 등록해 줘야함.

iBooks.app에 있는 BKDictionaryManager_LanguageToOrder.plist 파일에 위와 같이
사전마다 고유한 Bundle identifer값을 등록해주면, iBooks에서 사용자 사전이 활성화 됨.
일본어의 경우 고퀄의 사전이 기본 3개나 탑재되어 있음. 부러븐 것들.
한국어 사전도 넣어달란 얘긴 안할테니, 애플은 사용자가 사전을 JB없이도 추가할 수 있는 방법을 제공하라~~(방법 존재)

iPad에서 내가만든 사전을 띄운건 자랑
이것 땜에 jailbreak한건 안 자랑

MacOSX용 대한민국 우편번호 사전 만들기

2012-07-17   //   alexken작성   //   기술  //  2 Comments

binWord/blog Leopardの「辞書」アプリで郵便番号辞書を使う란 MacOS용 시스템 사전을 응용한 일본 우편번호 사전 만들기 포스트를 보고 한국어 버전으로 만들어 보았음.

우정사업본부에서도 우편번호 데이터를 얻을 수 있지만,
인터넷에서 아래와 같이 정리된 데이터를 이용하였음.(2012년5월, 51,989항목)

135-806 서울  강남구 개포1동    경남아파트                      1
135-807 서울  강남구 개포1동    우성3차아파트    (1∼6동)         2
135-806 서울  강남구 개포1동    우성9차아파트    (901∼902동)     3
135-770 서울  강남구 개포1동    주공아파트       (1∼16동)        4

아래와 같이 작성한 ruby 코드로 데이터를 사전용 xml 포맷으로 변환하고, XCode에 있는 사전 도구를 이용해서 make 한방 때리면 사전이 튀어 나옴.

#!/usr/bin/env ruby

puts < <XML_HEAD
<?xml version="1.0" encoding="UTF-8"?>
<d:dictionary xmlns="http://www.w3.org/1999/xhtml"
              xmlns:d="http://www.apple.com/DTDs/DictionaryService-1.0.rng">
XML_HEAD

class File
  def File.open_and_process(*args)
    f = File.open(*args)
    yield f
    f.close
  end
end

File.open_and_process(ARGV[0],'r') do |file|
  while line = file.gets
    line.gsub(/\s+/,' ').scan(/^(\S+)\s+(.*)\s+(\d+)\s+$/).each{|zip,index,id|
      puts "<d:entry d:title='#{index}' id='#{id}' from=''>"
      index.split(' ').each{ |x|
        puts "\t<d:index d:value='#{x}'></d:index>"
      }
      puts "<section><b>#{zip}</b> #{index}</section>"
      puts "</d:entry>"
    }
  end
end

puts < <XML_TAIL
</d:dictionary>
XML_TAIL
</d:dictionary>

원래 txt 데이터는 3MB
MacOSX 사전용 xml로 변환하면 5MB
사전으로 컴파일하면 28MB
Zip으로 압축해서 5.7MB

7월19일 추가사항

배포를 하려해도 호스팅비용이 부담되어 어찌할까 하다가,
요번 참에 github 가입하고, 소스채 올림.

소스: https://github.com/alexken/korzipcode
컴파일된 사전: https://github.com/alexken/korzipcode/downloads

설치방법?
zip 파일을 다운받아 압축을 풀면 ‘한국 우편번호.dictionary’가 나오고 이것을 ~/Library/Dictionaries에 복사하면 끝.
(~/Library/Dictionaries을 파인더로 가기 힘들다면 Terminal.app에서 cd ~/Library/Dictionaries 하고 open . 으로 열 수 있음.)

앨런 튜링 탄생 100년

2012-06-23   //   alexken작성   //   기술  //  No Comments

alan turing google doodle

앨런 튜링 탄생 100년 되는 날.
오늘의 구글 두들, 이건 기념으로 남기지 않을 수가 없구나…

올해가 가기전에 레고 NXT로 튜링 머신을 만들기로 나하고 약속했는데, 만만치가 안구먼.

iOS6 베타 버전 설치 인증샷

2012-06-12   //   alexken작성   //   기술  //  1 Comment

지난번 쓴 일본어 시리와 울프람 알파의 인공지능와 관련, 한국어 시리의 결과가 궁금했는데, 역시 의미파악은 실패. 영어 시리의 경우 시리가 의미파악에 실패해도, 울프람알파라는 든든한 백업요원이 있어, 지난번 “세상에서 제일 좋은 핸드폰” 이란 질문을 울프람알파가 받아 재미있는 결과가 나왔는데, 울프람알파는 한국어를 모른다는 서글픈 현실…

그리고 이건 경기도 굴욕 사진(이런거야 정식때면 다 해결되겠지만, “주변에 중국집을 알려줘”와 같은 위치기반 의미있는 정보 제공은 한동안 힘들어 보임)

그리고 TOMTOM의 한국 지도는 정말 설렁했음.

처음으로 Google Adsense 수표 받아봄.

2012-06-04   //   alexken작성   //   기술  //  1 Comment

처음으로 구글로 부터 $100짜리 Adsense 수표를 받았다.

자랑같아 보이지만 사실 좀 챙피한 얘기이다.
2006년 6월 Adsense에 가입했으니, 6년 만에 받은 것이고, 그만큼 한산하고 인기없는 블로그란 얘기다.
물론 한동안 Adsense를 내려놓은 적도 있고, 올해 1월에 조건을 충족하여 $100 수표를 우편으로 보냈다가 내가 받아보지 못해 Western Union Quick Cash로 변경후 재발행 한 것이긴 하지만, 다 변명이고, 수익률로 따지자면 $108 / (12개월*6년) = 월 $1.5 = 월 1700원 정도의 수입이 발생했다고 할 수 있다.

내가 사용하는 호스팅이 월 500원 이니까, 호스팅 기간 연장을 하거나, 도메인 기간 연장에 사용해야겠다.

페이지:«1234567...19»