2019년 4월 22일 월요일

직구한 LG TV 로컬변경 PC없이 자동으로 하기.

예전에 직구한 LG TV 로컬변경을 이전 블로그에서 포스팅 한적이 있습니다. (이전 블로그 글 링크)
지인이 이번에 또 LG TV를 직구 했는데 로컬 변경을 물어 보는데... 문제는 컴맹입니다...
그래서 컴맹도 쉽게 로컬 변경을 할수 있게 Arduino 를 사용해서 만들어 봤습니다.
서비스 단자에 이어폰 짹을 꼽고 USB 를 꼽아서 전원을 넣어주면 로컬 변경이 됩니다.
구지 사이즈가 클 필요가 없어서 Arduino Pro Mini에 Max3232 칩을 사용 했습니다.
USB 전원을 연결하면 비쥬얼 적인 효과를 위해서 LED가 깜빡이고 로컬 변경 코멘드를 전송 합니다.

그냥 단순하게 한가지 동작만 한다면 점퍼를 쓸필요가 없어서 저항 쓸 필요도 없이 아주 간단한 구성이 될텐데 괜히 범용성 생각하다가 보드가 지저분해 졌네요~
보드 뒷면인데 따로 회로 구성을 할 필요도 없이 간단 하지만 그래도 또 TV 제작 년도 별로 커멘드가 다르고, 다시 US 로컬 변경을 할 필요가 있어서 년도 선택 3개 한국,미국 선택 2개 해서..점퍼를 5개 구성해 줬습니다.
Arduino 소스 코드는 아래와 같습니다.
처음 부팅시 점퍼를 검사해서 년도모드 1~3을 검색하고 점퍼가 안 꼽혀 있으면 모드 3 입니다.
그리고 로컬 모드 KR,US를 검사해서 설정 합니다..점퍼가 안꼽혀 있으면 모드 0으로 KR로 로컬 변경을 한후 약 10초후 다시 US로 로컬 변경을 합니다. 즉 처음 보드에 전원을 넣고 KR 로 로컬 변경을 한후 보드를 빼면 KR 로컬이고... 10초 더 기다렸다가 US 로컬 변경까지 한후 보드를 빼면 US 로컬 변경이 되겠습니다.
#include <SoftwareSerial.h>

const int PinModeYear1 =  9;
const int PinModeYear2 =  8;
const int PinModeYear3 =  7;
const int PinModeKR =  2;
const int PinModeUS =  3;

String strSetName , strSetKR, strSetUS, strSetAdd;
int nModeYear = 3;
int nModeLocal = 0;

SoftwareSerial mySerial(10, 11); // RX, TX
void setup() {
  
  pinMode(LED_BUILTIN, OUTPUT);
  pinMode (PinModeYear1, INPUT);
  pinMode (PinModeYear2, INPUT);
  pinMode (PinModeYear3, INPUT);
  pinMode (PinModeKR, INPUT);
  pinMode (PinModeUS, INPUT);

  mySerial.begin(9600);
  Serial.begin(9600);


  if (digitalRead(PinModeYear1) == HIGH) nModeYear = 1;
  if (digitalRead(PinModeYear2) == HIGH) nModeYear = 2;
  if (digitalRead(PinModeYear3) == HIGH) nModeYear = 3;
  
  if (digitalRead(PinModeKR) == HIGH) nModeLocal = 1;
  if (digitalRead(PinModeUS) == HIGH) nModeLocal = 2;

  if (nModeYear == 1) { 
    //2014년 LB5900~6000
    //2015년 55LF6000
    strSetName = "2014~2015";
    strSetKR = "AN 00 01 4B 4F 52";
    strSetUS = "AN 00 02 55 53 41";
    strSetAdd = "AF 00 81 E0";
  }
  
  if (nModeYear == 2) {
    //2015년 65UF9500 ,65UF8500 
    //한국코드 - 18077
    strSetName = "2015~";
    strSetKR = "AU 00 46 9D 01 4B 4F 52";
    strSetUS = "AU 00 57 0A 02 55 53 41";
  }
  
  if (nModeYear == 3) {
    //2016년 이후
    //한국코드 - 18048  
    strSetName = "2016~";
    strSetKR = "AU 00 46 80 01 4B 4F 52";
    strSetUS = "AU 00 57 0A 02 55 53 41";
  }

  delay(500);
  Serial.println("===========================");
  Serial.println("LG TV Local Changer   v1.0");
  Serial.println("");
  Serial.println("2017/07/27");
  Serial.println("By CodeH (haesup@gmail.com)");
  Serial.println("===========================");
  Serial.println("JP9 : Year 2014   JP2 : KR");
  Serial.println("JP8 : Year 2015   JP3 : US");
  Serial.println("JP7 : Year 2016");
  Serial.println("---------------------------");
  if (nModeYear == 1) Serial.println("2014 TV");
  if (nModeYear == 2) Serial.println("2015 TV");
  if (nModeYear == 3) Serial.println("2016 TV");
  if (nModeLocal == 0) Serial.println("Local to KR.... After 10Sec... Local to US....");
  if (nModeLocal == 1) Serial.println("Local to KR....");
  if (nModeLocal == 2) Serial.println("Local to US....");
  Serial.println("");
  delay(500);
}

void loop() {

  if (nModeLocal == 1 || nModeLocal == 0) {
    digitalWrite(LED_BUILTIN, HIGH);
    delay(1000);
    digitalWrite(LED_BUILTIN, LOW);    
    delay(2000);
    Blink_CountDown(30);
    Serial.print("Set Local to Kor : ");
    Serial.println(strSetName);  
    Serial.print("Command : ");
    Serial.println(strSetKR);  
    mySerial.println(strSetKR);
    delay(2000);
    digitalWrite(LED_BUILTIN, HIGH);
    delay(1000);
    digitalWrite(LED_BUILTIN, LOW);   
    delay(500); 
    
    delay(5000);
  }
  
  
  
  if (nModeLocal == 2 || nModeLocal == 0) {
    digitalWrite(LED_BUILTIN, HIGH);
    delay(1000);
    digitalWrite(LED_BUILTIN, LOW);    
    delay(500);
    digitalWrite(LED_BUILTIN, HIGH);
    delay(1000);
    digitalWrite(LED_BUILTIN, LOW);    
    delay(2000);
    Blink_CountDown(40);
    Serial.print("Set Local to US : ");
    Serial.println(strSetName);  
    Serial.print("Command : ");
    Serial.println(strSetUS);  
    mySerial.println(strSetUS);
    delay(2000);
    digitalWrite(LED_BUILTIN, HIGH);
    delay(1000);
    digitalWrite(LED_BUILTIN, LOW);    
    delay(500);
    digitalWrite(LED_BUILTIN, HIGH);
    delay(1000);
    digitalWrite(LED_BUILTIN, LOW);    
    delay(500);
    
    delay(5000);
  }
  
  Serial.println("Work Finish!!!!!");
  while (1) delay (100);
}

void Blink_CountDown(int in) 
{
  int i;  
  for (int j = in ; j >= 0 ; --j) {
    i = j;
    if (i < 5) i = 5;
    if (i > 30) i = 30;
    digitalWrite(LED_BUILTIN, HIGH);
    delay(i * 10);
    digitalWrite(LED_BUILTIN, LOW);
    delay(i * 10);    
    Serial.print(".");
  }
  Serial.println("");
}
PC에 연결해서 점퍼 연결에 따라 커맨드가 정상적으로 전송 되는것을 확인 했고 이제 TV에 바로 연결 할수 있도록 이어폰 짹으로 변경 했습니다.
서비스 단자에 RX,TX가 항상 헷갈려서.... RX,TX 바꺼서 꼽을수 있게 짹 타입으로 하다보니 좀 지저분 하네요....확인해 보고 잘되는 핀 찾아서 그냥 납땜해 버려야 겠습니다.
서비스 단자에 4.5파이 이어폰 케이블 꼽고 USB 전원 넣고... 끝...
LED가 비쥬얼 적인 효과로 깜빡이긴 하는게...좀 기다려야 하네요...
그거 시름 그냥 딜레이 빼면 5초안에 가능 하겠군요~
[video width="720" height="404" mp4="http://codeh.kr/wp-content/uploads/2017/07/KakaoTalk_Video_20170728_1529_19_013.mp4"][/video]
설정 - 일반에서 국가 선택에 미국 밖에 없는데...
로컬 변경을 하면...이렇게 한국을 선택 할수 있습니다.
채널 검색에서도 한국 방송 잘~ 잡힙니다~
사실 서비스포트 프로토콜만 안다면...
따로 점퍼 스위치 안쓰고.... 보드에서 TV로 쿼리 날리고 답변온 티비 모델명을 가지고
거기에 맞는 커멘드를 날려주면 완전 자동으로 가능 하겠지만...자료를 구할데가 없으니 그냥 단방향으로 커멘드만 날리는 것만 가능 하겠군요..

그리고 새로운 커맨드가 있다면 커맨드 공유 해 주시면 소스 코드에 반영 하겠습니다~

[PHP] 현재 사용중인 통신사(ISP)에 맞게 M3U 파일 보여주기.

IPTV를 보기 위해 M3U를 만들었습니다.
회사는 KT, 집은 SK, 본가는 LG 를 씁니다.
그리고 개인 서버에 M3U를 올려 놓고 집이나 휴대폰이나 회사에서 M3U를 가지고 MP3를 볼수 있는 프로그램에 M3U 경로를 지정해 주고 쓰고 있었는데, 통신사 마다 주소를 다르게 쳐주는게 은근 귀찮아서 만들어 봤습니다.
현재 IP를 가지고 통신사 ISP를 추적한후 통신사에 맞는 M3U파일을 보여 줍니다.
그리고 현재 사용중인 ASUS 공유기 RT-AC88U 에 경우 UDP 프록시 기능이 있어서 이 기능을 사용하면 버퍼링이 좀더 원활해 집니다.
<?php
/**
 * ================================
 * 2017/07/20
 * By CodeH
 * haesup@gmail.com
 * http://codeh.kr
 * ================================
 *
 * IP로 통신사 ISP 를 판단해서 각 통신사에 맞는 m3u 파일을 출력해준다.
 *
 *
 * ---------------------
 * 주소창에 인수로 옵션을 지정
 * ---------------------
 * 옵션명 : r=[숫자or아이피주소]
 * ?r=192.168.0.1 과 같이 값을 넣으면 Asus 라우터에 맞게 M3U 파일 앞에 라우터 UDP 프록시 주소를 넣어준다.
 * 0,1,2 를 넣으면 192.168.?.1 로 지정된다.
 *
 * 옵션명 : isp=[isp이름]
 * isp를 강제로 지정 한다. local / sk / lg / kt
 *
 * 옵션명 : p=port
 * 라우터에 Proxy 포트를 지정.. 기본 4000
 *
 * 옵션명 : d=1
 * 디버그 모드
 * ---------------------
 */

if ($_GET[d] == 1) {
    $DebugMode = true;
}
if ($_GET[r] <> "") {
    $RouterProxyIP = $_GET[r];
    //라우터 옵션에 IP 주소 다 쳐주는거 번거로우니 일반적으로 많이 쓰는 IP 대역 0,1,2 을 넣으면 자동으로 IP 대역을 만들어 준다.
    if ($RouterProxyIP == 0) $RouterProxyIP = "192.168.0.1";
    if ($RouterProxyIP == 1) $RouterProxyIP = "192.168.1.1";
    if ($RouterProxyIP == 2) $RouterProxyIP = "192.168.2.1";
    if ($DebugMode) echo ("RouterProxyIP ON / in Router Address : " . $RouterProxyIP . "<BR>");
}

// 포트값을 넣어주면 해당 포트를 사용하고... 안넣어주면 기본 포트인 4000번을 사용 한다.
if ($_GET[p] <> "") {
    $RouterProxyPort = $_GET[p];
}
else {
    $RouterProxyPort = "4000";
}

if ($_GET[isp] <> "") {
    $ISP  = $_GET[isp];
    if ($DebugMode) echo ("in isp  : " . $ISP . "<BR>");
}


    $IP = $_SERVER['REMOTE_ADDR'];
    //$IP = "164.124.101.2";  //LG DNS
    //$IP = "203.248.252.2";  //LG DNS
    //$IP = "210.220.163.82";  //SK DNS
    //$IP = "219.250.36.130";  //SK DNS
    //$IP = "168.126.63.1";  //KT DNS
    //$IP = "168.126.63.2";  //KT DNS

if ($DebugMode) echo ("Client IP : " . $IP . "<BR>");


//-----------------------------------------------------------------------------
//Local 인지 검사.

if ($ISP == "") {
    $IP_Parts = explode(".", $IP);
    $IP_Head = $IP_Parts[0] . "." . $IP_Parts[1];
    if ($DebugMode) echo ("IP Head : " . $IP_Head . " == (192.168)<BR>");
    if ($IP_Head == "192.168") {
        $ISP = "Local";
    }

    $IP_Head = $IP_Parts[0] . "." . $IP_Parts[1] . "." . $IP_Parts[2] . ".0" ; 
}
//-----------------------------------------------------------------------------

if ($ISP == "") {
    $foundISP = "";
    $foundFile = false;


    $fp = fopen("./ip.txt", 'r');
    if($fp) {
        while(!feof($fp)) {
            $readstr = fgets($fp,1024);
            $readval = explode(",", $readstr);                        
            $IP_Parts = explode(".", $readval[0]);

            $IP_Head_File = $IP_Parts[0] . "." . $IP_Parts[1] . "." . $IP_Parts[2] . ".0" ; 

            //if ( $readval[0] == $IP ) {
            if ( $IP_Head == $IP_Head_File ) {
                $foundFile = true;
                $foundISP = $readval[1];
                $ISP = $foundISP;
                if ($DebugMode) echo ($ISP . "<BR>");
            }
        }
    }
    else {
        if ($DebugMode) echo ("[no file]");
    }

    if ($foundISP == "") {
        if ($DebugMode) echo ("[no found ip from file]");
    }
    else {
        if ($DebugMode) echo ($foundISP);
    }

    if ($DebugMode) echo ("[end]");
    fclose($fp);
}
//-----------------------------------------------------------------------------

if ($foundISP == "" && $ISP == "") {
    $User_Agent = 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:33.0) Gecko/20100101 Firefox/33.0';
    $Accept = 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8';
    $Accept_Language = 'en-US,en;q=0.5';
    $Referer = 'http://whatismyipaddress.com/';
    $Connection = 'keep-alive';

    $HTML = file_get_contents("http://whatismyipaddress.com/ip/$IP", false, stream_context_create(array('http' => array('method' => 'GET', 'header' => "User-Agent: $User_Agent\r\nAccept: $Accept\r\nAccept-Language: $Accept_Language\r\nReferer: $Referer\r\nConnection: $Connection\r\n\r\n"))));

    preg_match_all('/<th>(.*?)<\/th><td>(.*?)<\/td>/s', $HTML, $Matches, PREG_SET_ORDER);

    $ASN = $Matches[3][2];
    $ISP = $Matches[4][2];
    $City = $Matches[11][2];
    $State = $Matches[10][2];
    $ZIP = $Matches[15][2];
    $Country = $Matches[9][2];

    if ($DebugMode) echo $ISP . "<BR>";
    if ($DebugMode) echo $ASN . "<BR>";
}


//-----------------------------------------------------------------------------
//echo ("ISP: " . $ISP . "<BR>");
$ISP = preg_replace('/\r\n|\r|\n/','',$ISP);    //개행문자 제거

if ($ISP == "local" || $ISP == "" || $ISP == "Local") {
    if ($DebugMode)  echo "Local KT";
    //if (!$DebugMode) echo include("../h/kt_router.m3u");
    if ($RouterProxyIP == "" ) $RouterProxyIP = "192.168.0.1";  //서버가 있는곳은 KT에 라우터 Proxy를 항상 쓰니 따로 라우터 옵션을 안줘도 그냥 라우터 Proxy 값을 적용해준다.
    if (!$DebugMode) Show_M3U("../h/kt.m3u", $RouterProxyIP, $RouterProxyPort);
}
elseif ($ISP == "kt" || $ISP == "Korea Telecom" || $ASN == 4766) {
    if ($DebugMode)  echo "KT";
    //if (!$DebugMode) echo include("../h/kt.m3u");
    if (!$DebugMode) Show_M3U("../h/kt.m3u", $RouterProxyIP, $RouterProxyPort);
}
elseif ($ISP == "sk" || $ISP == "SK Broadband" || $ISP == "SK Telecom" || $ASN == 9318 || $ASN == 9644) {
    if ($DebugMode)  echo "SK";
    //if (!$DebugMode) echo include("../h/sk.m3u");
    if (!$DebugMode) Show_M3U("../h/sk.m3u", $RouterProxyIP, $RouterProxyPort);
}
elseif ($ISP == "lg" || $ISP == "LG DACOM Corporation" || $ASN == 3786 || $ISP == "Lg Powercomm" || $ASN == 17858) {
    if ($DebugMode)  echo "LG";
    //if (!$DebugMode) echo include("../h/lg.m3u");
    if (!$DebugMode) Show_M3U("../h/lg.m3u", $RouterProxyIP, $RouterProxyPort);
}
else {
    echo "unknown isp!";   
    echo ("ISP: " . $ISP . "<BR>");
    $ISP = "";
}

?>


<?php 
/*
<body>
    <table align="center">
        <tr><td>IP :</td><td><?php echo $IP;?></td></tr>
        <tr><td>ASN :</td><td><?php echo $ASN;?></td></tr>
        <tr><td>ISP :</td><td><?php echo $ISP;?></td></tr>
        <tr><td>City :</td><td><?php echo $City;?></td></tr>
        <tr><td>State :</td><td><?php echo $State;?></td></tr>
        <tr><td>Zipcode :</td><td><?php echo $ZIP;?></td></tr>
        <tr><td>Country :</td><td><?php echo $Country;?></td></tr>
    </table>
</body>
*/


if ( $foundISP == "" && $ISP <> "Local" && $_GET[isp] == "") {
    if ($DebugMode) echo ("<BR>" . "[W]");
    $fp = fopen("./ip.txt", 'ab');
    //fwrite($fp, $IP . "," . $ISP . "\r\n");
    fwrite($fp, $IP_Head . "," . $ISP . "\r\n");    
    fclose($fp);
}

function Show_M3U($filename, $RouterProxyIP, $RouterProxyPort){
    //echo include($filename);
    $fp = fopen( $filename , 'r');

    if($fp) {
        while(!feof($fp)) {
            $readstr = fgets($fp,1024);
            //str_replace("rtp://", "http://192.168.0.1:4000/rtp/", $readstr) ;
            $changeStr = $readstr;
            if ($RouterProxyIP <> "") {
                $changeStr = str_replace("rtp://", "http://" . $RouterProxyIP . ":" . $RouterProxyPort . "/rtp/", $changeStr) ;    
                $changeStr = str_replace("udp://", "http://" . $RouterProxyIP . ":" . $RouterProxyPort . "/udp/", $changeStr) ;    
            }

            echo $changeStr;
        }
        fclose($fp);
    }
}

?>
그리고 부수적으로 IP를 가지고 ISP를 검색 할때 조금 시간이 걸려서 그냥 TXT 파일에 이전 IP를 저장 하는 기능을 추가 했습니다. DB 까지는 구지 사용할 필요가 없을거 같고..이 자료 퍼가실때 DB 설정 까지 하시긴 번거로우실테니 그냥 TXT 파일을 사용 했습니다.

별거 아닌 코드지만 그래도 처음부터 만들긴 시간이 걸리니 그냥 참고 하시기 바랍니다.

2.안드로이드 TV 박스(Android TV Box) 내장 메모리에 LibreElec 설치하기.

이제 안드로이드 TV 박스(Android TV Box) 내장 메모리에 LibreElec 를 설치해서 microSD 카드를 빼도 LibreElec가 돌아가도록 LibreElec 전용 머신을 만들어 보려고 합니다.
putty를 이용해서 앞에서 확인했던 IP 주소로 접속합니다.
접속시 SSH 키 관련 경고 창이 나오면 그냥 Y를 누르면 됩니다.
ID : root
Password : libreelec
로그인을 합니다.

installtointernal
터미널 창에 installtointernal 라고 쳐주면 설치가 시작 됩니다.
확인 차원에서 YES를 입력해 줍니다.
백업을 하고.. (따로 무엇을 할 필요는 없고 자동으로 진행 됩니다.)
시스템 파일을 복사 하고.. (따로 무엇을 할 필요는 없고 자동으로 진행 됩니다.)
데이타 파티션을 포멧하고.. (따로 무엇을 할 필요는 없고 자동으로 진행 됩니다.)
부팅할때 설정했던 값을 내부 파티션으로 복사할것인지 물어 봅니다. Y 를 눌러 줍니다.
Kodi를 정지 시키고 자동으로 리부팅이 됩니다.

이제 MicroSD카드를 빼도 기본적으로 LibreElec가 실행이 되는 LibreElec 전용 머신이 되었습니다.

아무래도 중소기업에 만든 펌을 쓰면 안드로이드 위에 올라가 있고 아무래도 LibreElec 보단 버그 픽스도 한계가 있고 한데..이제 빠릿 빠릿한 성능을 느낄수 있을겁니다.

1.안드로이드 TV 박스(Android TV Box)에서 LibreElec 사용 하기

1.안드로이드 TV 박스(Android TV Box)에 LibreElec 돌리기.
아래 링크로 접속을 합니다.
http://kszaq.libreelec.tv/s905/
버젼이 여러가지 있는데 이글을 쓰는 시점에는 8.0.2e 가 최신 버젼이니 해당 버젼으로 들어갑니다.
LibreELEC-S905.arm-8.0-8.0.2e.img.gz 를 클릭해서 다운 받습니다.
그리고 다시 초기 페이지로 가서 device_trees 로 들어 갑니다.
필자에 경우 CPU가 S905 이므로 S905로 들어갑니다. 다른 CPU를 사용 중이라면 해당 CPU이름을 클릭 합니다.
자신의 안드로이드TV박스에 맞는 하드웨어의 파일을 다운로드 해야합니다.
스펙은 제품 제작사에 제품 설명을 참고 하면 됩니다.
우선 TV006에 스펙을 보면..
2기가 램에 기가비트에 일반적인Wifi를 사용했네요.
gxbb_p200_2G_1Gbit.dtb 이 파일을 받으면 될것 같습니다.

그리고 U4X+S 에 스펙을 보면..
1기가 램에 5G Wifi를 사용 했네요.. Lan은 스펙에는 없지만 기가 비트라고 광고를 했으니..
gxbb_p200_1G_1Gbit_RealtekWiFi.dtb 이 파일을 받으면 될것 같습니다.

이제 https://libreelec.tv/downloads/ 에 접속을 해서
LibreELEC USB-SD Creator 을 다운 받아서 실행 합니다.
Select_File을 눌러서 처음 다운 받은 IMG 파일을 합니다.
MicroSD카드의 경로를 골라주고 Write를 누르면 작업이 시작 됩니다.


혹시 에러가 뜨면 아래 링크로 가서 파티션을 지우고 다시 시도해 보시기 바랍니다.
http://codeh.kr/blog/341
용량이 크지 않으니 1분 내외면 작업이 완료 됩니다.

이제 탐색기에서 SD카드를 보면 LIBREELEC 라는 볼륨 이름으로 파티션이 만들어졌습니다.
여기에 위에서 device_trees 에서 다운 받은 파일들을 복사합니다.
어떤 파일을 받아야 되는지 알아서 하나만 받았다면 하나만 복사 하면 됩니다.
하지만 어떤 파일인지 잘 모를경우 여러 파일을 복사해서 하나씩 적용해 봐야 합니다.
원래 있던 dtb파일에 F2키를 눌러서 파일 이름을 dtb_org 와 같이 다름 이름으로 변경해 줍니다.

그리고 적용 하고자 하는 파일에 커서를 대고 Ctrl+C를 눌러서 복사하고..

Ctrl+V를 눌러서 붙여 넣기를 하면 복사본으로 파일을 생성 됩니다.
복사본으로 만들어진 파일에 F2 키를 눌러서 이름을 dtb.img 로 입력 합니다.
경고 창이 뜨는데 Y를 눌러서 변경 하면 됩니다.

이제 만들어진 microSD 카드를 안드로이드TV박스에 꼽고 전원을 켭니다.
부팅이 안되고 멈쳐 있거나 계속 리부팅이 된다면 다른 dtb 파일로 다시 시도해 봅니다.



HDMI CEC 에 대해서 간단히 설명.

HDMI 는 아실테고..HDMI CEC 라는 규격이 있습니다.
쉽게 설명하면 HDMI로 리모콘 조작 신호를 보낸다고 이해하는게 간단할것 입니다.
일반적으로 TV에 셋탑이나 기타 플래이어를 연결해서 사용을 하는데..리모콘을 여러개 주렁 주렁 쓰는게 여간 번거로운게 아니라서 기본적인 동작을 TV 리모콘으로 제어를 하면 HDMI 케이블을 통해서 TV와 연결된 기기로 신호를 보내줘서 조작이 가능하게 하는것 입니다.
국내에서 많이 사용하는 TV는 아무래도 LG와 삼성전자 가 있겠죠.
우선 LG는 심플 링크라는 이름으로 부르고 다름과 같이 설명 합니다.
심플링크란 다양한 멀티미디어 기기들을 심플링크 메뉴를 통해 TV 리모컨만으로 편리하게 제어, 감상할 수 있는 기능입니다.
 로고가 있는 기기에 대해서만 동작됩니다. 외부기기의 심플링크 로고를 확인하세요. 
심플링크를 이용하려면 고속 HDMI 케이블(CEC(Consumer Electronics Control) 기능이 추가된 케이블)을 사용해야 합니다. 고속 HDMI 케이블은 기기 간의 정보 교환을 위한 13번 핀이 연결되어 있습니다.
그리고 삼성전자는 Anynet+ 이라고 부르고 다름과 같이 설명을 합니다.
애니넷+는 다른말로 HDMI CEC 라고도 합니다. HDMI 케이블로 연결된 기기를 제어할 수 있는 것을 말하며, 해당 기능을 이용하기 위해서는 애니넷+ 기능이 탑제된 제품들만 사용이 가능합니다.
HDMI의 CEC 전용 라인으로 통신을 하게 되는데 젠더 사용 시에는 동작이 안 됩니다.
뭐 결국 HDMI CEC 입니다.
그리고 아쉽게도 저가형 TV로 나오는 대우루컴즈 제품에 경우 HDMI CEC 를 지원 하지 않는다고 합니다. 흔히 말하는 대기업 제품이 아닌 제품에 경우 HDMI CEC 지원 여부를 미리 체크하시기 바랍니다.
집에 삼성 모니터 중에 TV 기능이 부가적으로 붙은 모니터가 있어서 설정에 일반으로 들어가니 Anynet+ 을 켜고 끄는 모드가 있습니다. HDMI CEC 가 지원되는 장비를 연결하니 HDMI 아이콘에 Anynet+ 가 표시 되고 방향키및 숫자키등을 지원해 주네요.
[video width="720" height="404" mp4="http://codeh.kr/wp-content/uploads/2017/07/KakaoTalk_Video_20170711_1228_10_280.mp4"][/video]

연결할 장비 둘다 CEC를 지원 해야 하고...그리고 또 필요한게 HDMI 케이블 인데..
따로 신경 쓸 필요 없이 HDMI Specification 1.0 에서 이미 CEC에 대한 규약이 들어간 상태 입니다.
이론 적으로는 15개의 장비를 연결할 수 있다고 합니다.
그리고 HDMI 1.3 에 CEC 관련 명령어 코멘드가 약간 업데이트 되었습니다.

이론적으로는 HDMI 1.0 케이블도 가능 하며.. HDMI 1.3 이상의 케이블을 쓰면 별 문제가 없을겁니다.하지만 이름 없는 중국산 HDMI 케에블은 왠지...13번 핀까지 연결 안한것들도 있을 수 있으니 연결이 잘 안되면 티비를 구매할때 들어 있는 케이블이나 조금 괜찮은 케이블로 시도해 보시기 바랍니다.

라즈베리 파이(Raspberry Pi) LibreELEC(XBMC) 미디어 플레이어로...

라즈베리 파이(Raspberry Pi) 활용 방법 첫번째로 미디어 플레이어를 만들어 보려고 합니다.
기능으로는 NAS에 저장된 동영상 파일을 끌어다가 플래이 해주고, M3U로 만들어 놓은 IPTV 스트리밍 주소를 바로 바로 재생 하려고 합니다. 쉽게 말해서 셋탑박스 기능이 되겠습니다.
사실 집에 SK BTV 셋탑박스가 있긴 하지만 대기 전력 차단 차원에서 전원 코드를 뺐다 꼈다 하는데 이놈이...부팅을 하려면 1분 이상 걸리고...반응속도 느리고...광고가 많고...티비 잘 보고 있는데 지맘데로 업데이트 5분 넘게 하냐고 비티 보여 주지도 않고....여러모로 불편 합니다.
우선 라즈베리 파이(Raspberry Pi) 에 하드웨어에는 영상 및 음성을 출력해 줄수 있는 기능이 이미 모두 갖추어져 있기 때문에 소프트웨어적인 설정만 해주면 됩니다.
LibreELEC를 설치 하려고 합니다. 예전에 OpenElec 였는데 개발팀 들이 넘어 왔다고 한거 같은데...
Open에 개방되었다 보다 Libre에 자유롭다는 뜻이 좀더 좋은거 같습니다.
예전에 OpenOffice 나올때 SUN 으로 넘어가고 처음 개발팀 출발 취지와 맞지 않았는지 핵심 개발 인력이 나와서 LibreOffice 를 만들었는데 관계가 있나 모르겠군요..
LibreELEC 이든 OpenElec 간에.. 그 기본엔 KODI 라는 미디어 플레이어가 있습니다.
KODI는 XBMC 에서 이름이 바뀐것 이고요.
XBMC는 예전에 MS 에서 처음 내놓은 XBOX 라는 게임기에서 돌아가는 서드파티 미디어 플레이어 였습니다. 필자가 20대때 호주에서 어학연수를 하던 시절에 mod칩 붙인 XBOX 한국에서 공수 받아서 한국 드라마 많이도 봤었던때가 생각니 새록새록 나는군요.

간단하게 정리하면 KODI는 미디어 플레이어 이고,
LibreELEC는 KODI 에 최적화 해서 OS를 셋팅하고 거기에 KODI를 넣어 놓은 OS라고 보시면 됩니다.
아무래도 라즈베리 파이(Raspberry Pi)가 CPU 성능이 그렇게 높은건 아니니 전용으로 쓰면 여러모로 장점이 있습니다.

https://libreelec.tv/downloads/

우선 SD 카드를 만들어 주는 프로그램을 다운 받습니다.

OpenElec 이나 다른 배포판을 설치 할때에는 Win32Disk Imager 을 사용해야 했는데 여러모로 편해졌네요.
라즈베리 파이(Raspberry Pi) 보드를 골라주고 배포판의 버젼 골라주고 Download를 누르면 바로 다운로드가 됩니다.
아니면 홈페이지에서 바로 이미지 파일을 다운로드 할수도 있습니다.
홈페이지에서 바로 받는것 보단 좀 느린감이 있습니다.
이미지 파일의 용량이 130메가 이고 SD를 만들면 512메가의 파티션을 만들어 줍니다.
1기가 이상 SD카드 아무거나 사용 해도 됩니다.
SD 카드 위치를 골라주고 Write를 누르면 SD 카드를 만들어 줍니다.
시간은 1분 정도 밖에 안걸리는 것 같네요.
이제 SD카드를 라즈베리 파이(Raspberry Pi) 에 HDMI 모니터, 마우스, 키보드등을 연결하고, MicroUSB 를 연결하고 전원을 넣어주면 라즈베리 파이(Raspberry Pi)에 LibreELEC 이 부팅이 됩니다.

기타 설정은 다음 편에서 다루기로 하겠습니다.