diff --git a/RowClient/mobile/src/main/AndroidManifest.xml b/RowClient/mobile/src/main/AndroidManifest.xml index 90de996..f4aa1ce 100644 --- a/RowClient/mobile/src/main/AndroidManifest.xml +++ b/RowClient/mobile/src/main/AndroidManifest.xml @@ -15,6 +15,7 @@ + diff --git a/RowClient/wear/src/main/java/com/gdgssu/rowclient/ControlSendingThread.java b/RowClient/wear/src/main/java/com/gdgssu/rowclient/ControlSendingThread.java new file mode 100644 index 0000000..9d213c2 --- /dev/null +++ b/RowClient/wear/src/main/java/com/gdgssu/rowclient/ControlSendingThread.java @@ -0,0 +1,17 @@ +package com.gdgssu.rowclient; + +import android.content.Context; + +public class ControlSendingThread implements Runnable { + + private Context mContext; + + public ControlSendingThread(Context mContext) { + this.mContext = mContext; + } + + @Override + public void run() { + + } +} diff --git a/RowClient/wear/src/main/java/com/gdgssu/rowclient/MainActivity.java b/RowClient/wear/src/main/java/com/gdgssu/rowclient/MainActivity.java index 5ec78cb..660ef0c 100644 --- a/RowClient/wear/src/main/java/com/gdgssu/rowclient/MainActivity.java +++ b/RowClient/wear/src/main/java/com/gdgssu/rowclient/MainActivity.java @@ -20,5 +20,7 @@ public void onLayoutInflated(WatchViewStub stub) { mTextView = (TextView) stub.findViewById(R.id.text); } }); + + new Thread(new ControlSendingThread(getApplicationContext())).start(); } } diff --git a/RowClient/wear/src/main/java/com/gdgssu/rowclient/RowClientReceiver.java b/RowClient/wear/src/main/java/com/gdgssu/rowclient/RowClientReceiver.java new file mode 100644 index 0000000..35b804a --- /dev/null +++ b/RowClient/wear/src/main/java/com/gdgssu/rowclient/RowClientReceiver.java @@ -0,0 +1,19 @@ +package com.gdgssu.rowclient; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.net.wifi.WifiManager; + +public class RowClientReceiver extends BroadcastReceiver { + @Override + public void onReceive(Context context, Intent intent) { + String action = intent.getAction(); + + if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) { + + } else { + throw new UnsupportedOperationException("Not yet implemented"); + } + } +} diff --git a/RowClient/wear/src/main/java/com/gdgssu/rowclient/StateSyncThread.java b/RowClient/wear/src/main/java/com/gdgssu/rowclient/StateSyncThread.java new file mode 100644 index 0000000..0f71fb3 --- /dev/null +++ b/RowClient/wear/src/main/java/com/gdgssu/rowclient/StateSyncThread.java @@ -0,0 +1,37 @@ +package com.gdgssu.rowclient; + +import android.content.Context; + +public class StateSyncThread extends Thread { + + /** + * IRSender 애플리케이션과 소켓으로 연결하여 현재 가정에서 컨트롤할 디바이스의 종류를 받아와야한다 + * 만약 30초동안 찾지 못한다면 본 Thread는 종료된다 + */ + + private int foundDeviceSecond = 0; + private Context mContext; + + public StateSyncThread(Context mContext) { + this.mContext = mContext; + } + + @Override + public void run() { + while(true){ + try { + + //Todo : 소켓을 IRSender측으로 보내는 로직 작성 + + Thread.sleep(1000); + foundDeviceSecond++; + } catch (InterruptedException e) { + e.printStackTrace(); + } + + if (foundDeviceSecond==30){ + break; + } + } + } +} diff --git a/RowIRSender/app/build.gradle b/RowIRSender/app/build.gradle index 7eef6e4..36f39d1 100644 --- a/RowIRSender/app/build.gradle +++ b/RowIRSender/app/build.gradle @@ -2,7 +2,7 @@ apply plugin: 'com.android.application' android { compileSdkVersion 23 - buildToolsVersion "23.0.1" + buildToolsVersion "23.0.2" defaultConfig { applicationId "com.gdgssu.rowirsender" @@ -24,4 +24,5 @@ dependencies { testCompile 'junit:junit:4.12' compile 'com.android.support:appcompat-v7:23.1.0' compile files('libs/qremote.jar') + compile 'com.google.code.gson:gson:2.3' } diff --git a/RowIRSender/app/src/main/AndroidManifest.xml b/RowIRSender/app/src/main/AndroidManifest.xml index b76acc9..3127034 100644 --- a/RowIRSender/app/src/main/AndroidManifest.xml +++ b/RowIRSender/app/src/main/AndroidManifest.xml @@ -2,13 +2,29 @@ + + + + + - + + + + + + + + + diff --git a/RowIRSender/app/src/main/java/com/gdgssu/rowirsender/DeviceControlInfo.java b/RowIRSender/app/src/main/java/com/gdgssu/rowirsender/DeviceControlInfo.java new file mode 100644 index 0000000..2937eff --- /dev/null +++ b/RowIRSender/app/src/main/java/com/gdgssu/rowirsender/DeviceControlInfo.java @@ -0,0 +1,70 @@ +package com.gdgssu.rowirsender; + +import android.util.Log; + +import com.lge.hardware.IRBlaster.Device; +import com.lge.hardware.IRBlaster.IRFunction; + +import java.util.List; + +public class DeviceControlInfo { + + /** + * 웨어러블로부터 전송받은 데이터를 파싱하며, 일시적으로 인스턴스를 통해 저장하여 활용하는 모델 클래스입니다 + */ + private final static String TAG = DeviceControlInfo.class.getSimpleName(); + + public int deviceId; + public String functionName; + public String deviceName; + + public int getDeviceId() { + return deviceId; + } + + public void setDeviceId(int deviceId) { + this.deviceId = deviceId; + } + + public String getFunctionName() { + return functionName; + } + + public void setFunctionName(String functionName) { + this.functionName = functionName; + } + + public String getDeviceName() { + return deviceName; + } + + public void setDeviceName(String deviceName) { + this.deviceName = deviceName; + } + + /** + * String 형태의 funcLabel을 int형태의 Keycode로 변환합니다 + * @param deviceList + * @param funcLabel + * @return function id + */ + public int getFunctionKeyCode(List deviceList, String funcLabel) { + + if (deviceList.size() == 0) { + Log.e(TAG, "A device is not selected."); + return -1; + } + for (Device device : deviceList){ + for (IRFunction function : device.KeyFunctions) { + if (function.Name.equalsIgnoreCase(funcLabel)) { + return function.Id; + } + } + } + Log.e(TAG, "[" + funcLabel + "] search function failed"); + + return -1; + } + + // An example to use IR function labels.[E] +} diff --git a/RowIRSender/app/src/main/java/com/gdgssu/rowirsender/DeviceInfoParser.java b/RowIRSender/app/src/main/java/com/gdgssu/rowirsender/DeviceInfoParser.java new file mode 100644 index 0000000..ae67088 --- /dev/null +++ b/RowIRSender/app/src/main/java/com/gdgssu/rowirsender/DeviceInfoParser.java @@ -0,0 +1,18 @@ +package com.gdgssu.rowirsender; + +import com.google.gson.Gson; + +public class DeviceInfoParser { + + /** + * 소켓을 통해서 전송된 json형태의 데이터를 파싱하는 클래스입니다 + * @param jsonData + * @return DeviceControlInfo + */ + + public static DeviceControlInfo parsedInfo(String jsonData){ + + Gson gson = new Gson(); + return gson.fromJson(jsonData, DeviceControlInfo.class); + } +} diff --git a/RowIRSender/app/src/main/java/com/gdgssu/rowirsender/DevicePreferenceHelper.java b/RowIRSender/app/src/main/java/com/gdgssu/rowirsender/DevicePreferenceHelper.java new file mode 100644 index 0000000..231007b --- /dev/null +++ b/RowIRSender/app/src/main/java/com/gdgssu/rowirsender/DevicePreferenceHelper.java @@ -0,0 +1,54 @@ +package com.gdgssu.rowirsender; + +import android.app.Activity; +import android.content.Context; +import android.content.SharedPreferences; + +import com.google.gson.Gson; +import com.lge.hardware.IRBlaster.Device; + +import java.util.Arrays; +import java.util.List; + +/** + * 유저가 컨트롤할 Device(AIRCON, TV, STB, DVD 등)을 저장하고 저장된 내용을 가져오는 PrefenceHelper 클래스 + * mIR.getDevices()를 이용해 애플리케이션을 완전히 종료하고 다시 실행해도 디바이스 목록을 가져올수있다면 이 클래스는 효용성이 없습니다 + */ + +public class DevicePreferenceHelper { + private final static String PREF_NAME = "com.gdgssu.rowirsender.devicepref"; + public final static String PREF_DEVICE_STORE = "PREF_DEVICE_STORE"; + + private Context mContext; + + public DevicePreferenceHelper(Context mContext) { + this.mContext = mContext; + } + + public void setDevicePref(String key, List deviceList){ + SharedPreferences pref = mContext.getSharedPreferences(PREF_NAME, Activity.MODE_PRIVATE); + SharedPreferences.Editor editor = pref.edit(); + + Gson gson = new Gson(); + String devicesJsonData = gson.toJson(deviceList); + + editor.putString(key, devicesJsonData); + editor.apply(); + } + + public List getDevicePref(String key){ + List deviceList; + SharedPreferences pref = mContext.getSharedPreferences(PREF_NAME, Activity.MODE_PRIVATE); + + if (pref.contains(PREF_DEVICE_STORE)){ + String devicesJsonData = pref.getString(key, null); + Gson gson = new Gson(); + Device[] deviceArray = gson.fromJson(devicesJsonData, Device[].class); + deviceList = Arrays.asList(deviceArray); + }else{ + return null; + } + + return deviceList; + } +} diff --git a/RowIRSender/app/src/main/java/com/gdgssu/rowirsender/MainActivity.java b/RowIRSender/app/src/main/java/com/gdgssu/rowirsender/MainActivity.java deleted file mode 100644 index 243c2ef..0000000 --- a/RowIRSender/app/src/main/java/com/gdgssu/rowirsender/MainActivity.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.gdgssu.rowirsender; - -import android.support.v7.app.AppCompatActivity; -import android.os.Bundle; - -public class MainActivity extends AppCompatActivity { - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_main); - } -} diff --git a/RowIRSender/app/src/main/java/com/gdgssu/rowirsender/RowIRReceiver.java b/RowIRSender/app/src/main/java/com/gdgssu/rowirsender/RowIRReceiver.java new file mode 100644 index 0000000..42cdecf --- /dev/null +++ b/RowIRSender/app/src/main/java/com/gdgssu/rowirsender/RowIRReceiver.java @@ -0,0 +1,24 @@ +package com.gdgssu.rowirsender; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; + +public class RowIRReceiver extends BroadcastReceiver { + + /** + * 스마트폰이 부팅되자마자 RowIRService를 구동하게끔하는 기능을 담당하는 Receiver입니다 + * @param context + * @param intent + */ + + @Override + public void onReceive(Context context, Intent intent) { + + if (intent.getAction().equals("gdgssu.com.rowirsender.getaction")){ + context.startService(new Intent(context, RowIRService.class)); + }else{ + throw new UnsupportedOperationException("Not yet implemented"); + } + } +} diff --git a/RowIRSender/app/src/main/java/com/gdgssu/rowirsender/RowIRService.java b/RowIRSender/app/src/main/java/com/gdgssu/rowirsender/RowIRService.java new file mode 100644 index 0000000..d1b75ad --- /dev/null +++ b/RowIRSender/app/src/main/java/com/gdgssu/rowirsender/RowIRService.java @@ -0,0 +1,97 @@ +package com.gdgssu.rowirsender; + +import android.app.Service; +import android.content.Intent; +import android.os.IBinder; +import android.support.annotation.Nullable; +import android.util.Log; + +import com.lge.hardware.IRBlaster.Device; +import com.lge.hardware.IRBlaster.IRAction; +import com.lge.hardware.IRBlaster.IRBlaster; +import com.lge.hardware.IRBlaster.IRBlasterCallback; +import com.lge.hardware.IRBlaster.ResultCode; + +import java.util.Arrays; +import java.util.List; + +public class RowIRService extends Service implements SocketReceiveListener { + + /** + * 이 애플리케이션에서 웨어러블의 명령을 기다리는 Thread를 생성하고, + * 그 명령을 IR 송신을 이용하여 수행하는 중심적인 역할을 담당합니다. + */ + + private final static String TAG = RowIRService.class.getSimpleName(); + + private IRBlaster mIR; + private DevicePreferenceHelper prefHelper; + + private boolean mIR_ready = false; + private List deviceList = null; + + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + Log.i(TAG, "onStartCommand"); + + initInstance(); + + if (mIR != null) { + deviceList = Arrays.asList(mIR.getDevices()); +// deviceList = prefHelper.getDevicePref(DevicePreferenceHelper.PREF_DEVICE_STORE); + new SocketReceiverThread().start(); + } + + return super.onStartCommand(intent, flags, startId); + } + + private void initInstance() { + if (IRBlaster.isSdkSupported(getApplicationContext())) { + mIR = IRBlaster.getIRBlaster(getApplicationContext(), mIrBlasterReadyCallback); + prefHelper = new DevicePreferenceHelper(getApplicationContext()); + } else { + Log.e(TAG, "No IR Blaster in this device"); + } + } + + @Nullable + @Override + public IBinder onBind(Intent intent) { + return null; + } + + @Override + public void onReceive(String message) { + //Todo : 소켓을 통해 메시지가 전달되었을 때 처리할 로직 작성 + DeviceControlInfo deviceControlInfo = DeviceInfoParser.parsedInfo(message); + + int controlFunctionCode = deviceControlInfo.getFunctionKeyCode(deviceList, deviceControlInfo.getFunctionName()); + + if (controlFunctionCode != -1) { + mIR.sendIR(new IRAction(deviceControlInfo.getDeviceId(), controlFunctionCode, 0)); + } + } + + private IRBlasterCallback mIrBlasterReadyCallback = new IRBlasterCallback() { + @Override + public void IRBlasterReady() { + Log.d(TAG, "IRBlaster is ready"); + mIR_ready = true; + } + + @Override + public void learnIRCompleted(int i) { + + } + + @Override + public void newDeviceId(int i) { + + } + + @Override + public void failure(int i) { + Log.e(TAG, "Error: " + ResultCode.getString(i)); + } + }; +} diff --git a/RowIRSender/app/src/main/java/com/gdgssu/rowirsender/SettingActivity.java b/RowIRSender/app/src/main/java/com/gdgssu/rowirsender/SettingActivity.java new file mode 100644 index 0000000..14aacca --- /dev/null +++ b/RowIRSender/app/src/main/java/com/gdgssu/rowirsender/SettingActivity.java @@ -0,0 +1,59 @@ +package com.gdgssu.rowirsender; + +import android.support.v7.app.AppCompatActivity; +import android.os.Bundle; +import android.util.Log; +import android.view.View; +import android.widget.Button; + +import com.lge.hardware.IRBlaster.IRBlaster; +import com.lge.hardware.IRBlaster.IRBlasterCallback; + +public class SettingActivity extends AppCompatActivity { + + private IRBlaster mIR; + private IRBlasterCallback mIrBlasterReadyCallBack = new IRBlasterCallback() { + @Override + public void IRBlasterReady() { + + } + + @Override + public void learnIRCompleted(int i) { + + } + + @Override + public void newDeviceId(int i) { + + } + + @Override + public void failure(int i) { + + } + }; + + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_setting); + + if (IRBlaster.isSdkSupported(getApplicationContext())) { + mIR = IRBlaster.getIRBlaster(getApplicationContext(), mIrBlasterReadyCallBack); + } else { + Log.e("TAG", "sdk not supported IR"); + } + + Button addDeviceButton = (Button) findViewById(R.id.add_device); + + addDeviceButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + // 디바이스를 추가하는 Activity로 Intent를 발생시키는 SDK 함수 + int result = mIR.addDevice(); + } + }); + } +} diff --git a/RowIRSender/app/src/main/java/com/gdgssu/rowirsender/SocketReceiveListener.java b/RowIRSender/app/src/main/java/com/gdgssu/rowirsender/SocketReceiveListener.java new file mode 100644 index 0000000..7f26494 --- /dev/null +++ b/RowIRSender/app/src/main/java/com/gdgssu/rowirsender/SocketReceiveListener.java @@ -0,0 +1,11 @@ +package com.gdgssu.rowirsender; + +public interface SocketReceiveListener { + + /** + * SocketReceiverThread에서 RowIRService로 JsonText 데이터를 전달하는 기능을 수행하는 인터페이스입니다 + * @param message + */ + + void onReceive(String message); +} diff --git a/RowIRSender/app/src/main/java/com/gdgssu/rowirsender/SocketReceiverThread.java b/RowIRSender/app/src/main/java/com/gdgssu/rowirsender/SocketReceiverThread.java new file mode 100644 index 0000000..4e963d8 --- /dev/null +++ b/RowIRSender/app/src/main/java/com/gdgssu/rowirsender/SocketReceiverThread.java @@ -0,0 +1,41 @@ +package com.gdgssu.rowirsender; + +import android.util.Log; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.ServerSocket; +import java.net.Socket; + +public class SocketReceiverThread extends Thread { + + /** + * 웨어러블측에서 보내오는 소켓 통신 데이터를 listen하고있는 Thread입니다. + * 본 Thread는 RowIRSender의 핵심적인 역할을 담당하는 RowIRService 클래스를 통해 작동되기 시작합니다. + * 현재 포트번호는 임의로 5000번을 잡아놓았습니다. + *

+ * service.onReceive()를 통해 RowIRService로 JsonText 데이터를 전달합니다. + */ + + private final static String TAG = SocketReceiverThread.class.getSimpleName(); + private RowIRService service = new RowIRService(); + + @Override + public void run() { + while (true) { + try{ + ServerSocket serverSocket = new ServerSocket(5000); + + Socket socket = serverSocket.accept(); + BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream())); + String deliverMessage; + deliverMessage=reader.readLine(); + service.onReceive(deliverMessage); + + }catch (IOException e){ + Log.d(TAG, e.getMessage()); + } + } + } +} diff --git a/RowIRSender/app/src/main/res/layout/activity_main.xml b/RowIRSender/app/src/main/res/layout/activity_setting.xml similarity index 58% rename from RowIRSender/app/src/main/res/layout/activity_main.xml rename to RowIRSender/app/src/main/res/layout/activity_setting.xml index 4f1a402..80062ea 100644 --- a/RowIRSender/app/src/main/res/layout/activity_main.xml +++ b/RowIRSender/app/src/main/res/layout/activity_setting.xml @@ -4,8 +4,13 @@ android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" - android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity"> + android:paddingBottom="@dimen/activity_vertical_margin" + tools:context="com.gdgssu.rowirsender.SettingActivity"> + +