/* * Copyright (C) 2013-2014 Sony Computer Science Laboratories, Inc. All Rights Reserved. * Copyright (C) 2014 Sony Corporation. All Rights Reserved. */ package com.sonycsl.Kadecot.device; import android.content.Context; import android.util.Log; import com.sonycsl.Kadecot.call.CannotProcessRequestException; import com.sonycsl.Kadecot.call.ErrorResponse; import com.sonycsl.Kadecot.call.Notification; import com.sonycsl.Kadecot.call.Response; import com.sonycsl.Kadecot.core.KadecotCoreApplication; import com.sonycsl.Kadecot.log.Logger; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import java.util.ArrayList; import java.util.HashMap; import java.util.List; /** * Deviceを管理するクラス */ public class DeviceManager { private static final String TAG = DeviceManager.class.getSimpleName(); private static DeviceManager sInstance = null; private final Context mContext; private final HashMap<String, DeviceProtocol> mDeviceProtocols; private boolean mStarted = false; private DeviceDatabase mDeviceDatabase; private Logger mLogger; private static final String KEY_DEVICE = "device"; private static final String KEY_NICKNAME = "nickname"; private static final String KEY_PROTOCOL = "protocol"; private static final String KEY_DEVICE_NAME = "deviceName"; private static final String KEY_ACTIVE = "active"; private static final String KEY_PARENT = "parent"; private static final String KEY_DEVICE_TYPE = "deviceType"; private static final String KEY_CURRENT_NAME = "currentName"; private static final String KEY_NEW_NAME = "newName"; private static final String KEY_TARGET_NAME = "targetName"; private static final String KEY_SUCCESS = "success"; private static final String KEY_PROPERTY_NAME = "propertyName"; private static final String KEY_PROPERTY_VALUE = "propertyValue"; private static final String KEY_PROPERTY = "property"; private KadecotCoreApplication mApp; private DeviceManager(Context context) { mApp = (KadecotCoreApplication) context.getApplicationContext(); mContext = mApp; mDeviceProtocols = new HashMap<String, DeviceProtocol>(); } public static synchronized DeviceManager getInstance(Context context) { if (sInstance == null) { sInstance = new DeviceManager(context); } return sInstance; } public synchronized void start() { mStarted = true; for (DeviceProtocol protocol : mDeviceProtocols.values()) { protocol.start(); } refreshDeviceList(0); } public synchronized void stop() { for (DeviceProtocol protocol : mDeviceProtocols.values()) { protocol.stop(); } getLogger().unwatchAll(); Notification.informAllOnUpdateList(mContext); mStarted = false; } public boolean isStarted() { return mStarted; } public void refreshDeviceList(int permissionLevel) { if (isStarted() == false) { return; } // Notification.informAllEmptyOnUpdateList(mContext); Notification.informAllInactiveDeviceList(mContext); for (DeviceProtocol protocol : mDeviceProtocols.values()) { protocol.refreshDeviceList(); } // Notification.informAllOnUpdateList(mContext); } public synchronized void deleteAllDeviceData() { boolean started = mStarted; stop(); for (DeviceProtocol protocol : mDeviceProtocols.values()) { protocol.deleteAllDeviceData(); } getDeviceDatabase().deleteAllDeviceData(); if (started) { start(); } } /** * clientPermission が 0 なら 全ての操作を許可 1 なら 一部の操作の許可 protocolPermission が 0 なら * 一部のClientのみ許可 1 なら 全部のClientを許可 clientPermission : {0,1} * protocolPermission : {0,1} * * @param clientPermissionLevel * @param protocolPermissionLevel * @return */ public static boolean isAllowedPermission(int clientPermissionLevel, int protocolPermissionLevel) { return (clientPermissionLevel <= protocolPermissionLevel); } public JSONObject getDeviceList(int permissionLevel) { if (isStarted() == false) { return new JSONObject(); } final JSONObject deviceList = new JSONObject(); JSONArray list = new JSONArray(); List<DeviceData> dataList = getDeviceDatabase().getDeviceDataList(); for (DeviceData data : dataList) { JSONObject device = getDeviceInfo(data, permissionLevel); if (device != null) { list.put(device); } } try { deviceList.put(KEY_DEVICE, list); } catch (JSONException e) { // Never happens. Log.e(TAG, "JSON exception occurs at getDeviceList"); } return deviceList; } public JSONObject getDeviceInfo(long deviceId, int permissionLevel) { DeviceData data = getDeviceDatabase().getDeviceData(deviceId); if (data != null) { return getDeviceInfo(data, permissionLevel); } else { return null; } } public JSONObject getDeviceInfo(DeviceData data, int permissionLevel) { JSONObject device = new JSONObject(); try { device.put(KEY_NICKNAME, data.nickname); device.put(KEY_PROTOCOL, data.protocolName); DeviceProtocol protocol = mDeviceProtocols.get(data.protocolName); DeviceInfo info = null; if (protocol != null) { if (!(isAllowedPermission(permissionLevel, protocol.getAllowedPermissionLevel()))) { return null; } info = protocol.getDeviceInfo(data.deviceId, "ja"); } if (protocol != null && info != null) { device.put(KEY_ACTIVE, info.active); device.put(KEY_DEVICE_NAME, info.deviceName); device.put(KEY_DEVICE_TYPE, info.deviceType); device.put(KEY_PARENT, info.parent); return device; } else { // device.put("active", null); return null; } } catch (JSONException e) { return null; } } public void registerDeviceProtocol(DeviceProtocol protocol) { mDeviceProtocols.put(protocol.getProtocolName(), protocol); } public Response set(String nickname, ArrayList<DeviceProperty> propertyList, int permissionLevel) { if (isStarted() == false) { return new ErrorResponse(ErrorResponse.INTERNAL_ERROR_CODE, "Cannot access device"); } DeviceData data = getDeviceDatabase().getDeviceData(nickname); if (data == null) { return new ErrorResponse(ErrorResponse.INVALID_PARAMS_CODE, "nickname not found"); } DeviceProtocol protocol = mDeviceProtocols.get(data.protocolName); if (isAllowedPermission(permissionLevel, protocol.getAllowedPermissionLevel())) { try { List<DeviceProperty> list = protocol.set(data.deviceId, propertyList); DeviceInfo info = protocol.getDeviceInfo(data.deviceId, "jp"); for (DeviceProperty p : list) { completeAccessDeviceProperty(data, info, Logger.ACCESS_TYPE_SET, p); } return toAccessResponse(nickname, list); } catch (AccessException e) { // TODO Auto-generated catch block e.printStackTrace(); return e.getErrorResponse(); } } else { return new ErrorResponse(ErrorResponse.INVALID_PARAMS_CODE, "permission denied"); } } public Response get(String nickname, ArrayList<DeviceProperty> propertyList, int permissionLevel) { if (isStarted() == false) { return new ErrorResponse(ErrorResponse.INTERNAL_ERROR_CODE, "Cannot access device"); } DeviceData data = getDeviceDatabase().getDeviceData(nickname); if (data == null) { return new ErrorResponse(ErrorResponse.INVALID_PARAMS_CODE, "nickname not found"); } DeviceProtocol protocol = mDeviceProtocols.get(data.protocolName); if (isAllowedPermission(permissionLevel, protocol.getAllowedPermissionLevel())) { try { List<DeviceProperty> list = protocol.get(data.deviceId, propertyList); // log DeviceInfo info = protocol.getDeviceInfo(data.deviceId, "jp"); for (DeviceProperty p : list) { completeAccessDeviceProperty(data, info, Logger.ACCESS_TYPE_GET, p); } return toAccessResponse(nickname, list); } catch (AccessException e) { // TODO Auto-generated catch block e.printStackTrace(); return e.getErrorResponse(); } } else { return new ErrorResponse(ErrorResponse.INVALID_PARAMS_CODE, "permission denied"); } } private Response toAccessResponse(String nickname, List<DeviceProperty> list) { JSONObject result = new JSONObject(); try { result.put("nickname", nickname); JSONArray array = new JSONArray(); for (DeviceProperty p : list) { JSONObject prop = new JSONObject(); prop.put("name", p.name); prop.put("value", p.value); prop.put("success", p.success); prop.put("message", p.message); array.put(prop); } result.put("property", array); } catch (JSONException e) { // TODO Auto-generated catch block e.printStackTrace(); } return new Response(result); } public synchronized Response deleteDeviceData(JSONObject params) { if (isStarted() == false) { return new ErrorResponse(ErrorResponse.INTERNAL_ERROR_CODE, "Cannot access device"); } if (params == null || params.length() < 1) { return new ErrorResponse(ErrorResponse.INVALID_PARAMS_CODE); } String nickname = null; try { nickname = params.getString(KEY_TARGET_NAME); } catch (JSONException e) { e.printStackTrace(); return new ErrorResponse(ErrorResponse.INVALID_PARAMS_CODE); } DeviceData data = getDeviceDatabase().getDeviceData(nickname); if (data == null) { return new ErrorResponse(ErrorResponse.INVALID_PARAMS_CODE, "nickname not found"); } return deleteDeviceData(data); } public synchronized Response deleteDeviceData(DeviceData data) { DeviceProtocol protocol = mDeviceProtocols.get(data.protocolName); CannotProcessRequestException cpre = null; try { protocol.deleteDeviceData(data.deviceId); } catch (CannotProcessRequestException e) { cpre = e; } boolean b = getDeviceDatabase().deleteDeviceData(data.deviceId); if (b) { Notification.informAllOnDeviceDeleted(data.nickname, protocol .getAllowedPermissionLevel()); } if (cpre != null) { // error return cpre.getErrorResponse(); } else { return new Response(new JSONObject()); } } public synchronized Response deleteInactiveDevices(int permissionLevel) { if (isStarted() == false) { return new ErrorResponse(ErrorResponse.INTERNAL_ERROR_CODE, "Cannot access device"); } List<DeviceData> dataList = getDeviceDatabase().getDeviceDataList(); for (DeviceData data : dataList) { DeviceInfo info = null; DeviceProtocol protocol = mDeviceProtocols.get(data.protocolName); if (protocol != null) { info = protocol.getDeviceInfo(data.deviceId, "jp"); if (info != null && !info.active) { protocol.deleteDeviceData(data.deviceId); getDeviceDatabase().deleteDeviceData(data.deviceId); } } } Notification.informAllOnUpdateList(mContext); return new Response(new JSONObject()); } public synchronized Response changeNickname(JSONObject params) { if (isStarted() == false) { return new ErrorResponse(ErrorResponse.INTERNAL_ERROR_CODE, "Cannot access device"); } if (params == null || params.length() < 2) { return new ErrorResponse(ErrorResponse.INVALID_PARAMS_CODE); } String oldNickname = null; String newNickname = null; try { oldNickname = params.getString(KEY_CURRENT_NAME); newNickname = params.getString(KEY_NEW_NAME); } catch (JSONException e) { e.printStackTrace(); return new ErrorResponse(ErrorResponse.INVALID_PARAMS_CODE); } DeviceData data = getDeviceDatabase().getDeviceData(oldNickname); if (data == null) { return new ErrorResponse(ErrorResponse.INVALID_PARAMS_CODE, "nickname not found"); } boolean result = getDeviceDatabase().update(oldNickname, newNickname); if (!result) { return new ErrorResponse(ErrorResponse.INVALID_PARAMS_CODE, "New nickname exists."); } DeviceProtocol protocol = mDeviceProtocols.get(data.protocolName); Notification.informAllOnNicknameChanged(oldNickname, newNickname, protocol .getAllowedPermissionLevel()); return new Response(new JSONObject()); } public void onPropertyChanged(DeviceData data, List<DeviceProperty> list) { JSONObject obj = new JSONObject(); if (data == null) { return; } try { obj.put(KEY_NICKNAME, data.nickname); JSONArray array = new JSONArray(); for (DeviceProperty p : list) { JSONObject prop = new JSONObject(); prop.put(KEY_PROPERTY_NAME, p.name); prop.put(KEY_PROPERTY_VALUE, p.value); prop.put(KEY_SUCCESS, p.success); array.put(prop); } obj.put(KEY_PROPERTY, array); Notification.informAllOnPropertyChanged(obj, 1); } catch (JSONException e) { // TODO Auto-generated catch block e.printStackTrace(); } // log DeviceProtocol protocol = mDeviceProtocols.get(data.protocolName); DeviceInfo info = protocol.getDeviceInfo(data.deviceId, "jp"); for (DeviceProperty p : list) { completeAccessDeviceProperty(data, info, Logger.ACCESS_TYPE_GET, p); } } private DeviceDatabase getDeviceDatabase() { if (mDeviceDatabase == null) { mDeviceDatabase = DeviceDatabase.getInstance(mContext); } return mDeviceDatabase; } private Logger getLogger() { if (mLogger == null) { mLogger = Logger.getInstance(mContext); } return mLogger; } private void completeAccessDeviceProperty(final DeviceData data, DeviceInfo info, String accessType, DeviceProperty property) { getLogger().insertLog(data, info, accessType, property); mApp.getModifiableObject().onControlProperty(data, info, accessType, property); } }