package org.deviceconnect.android.deviceplugin.alljoyn; import android.support.annotation.NonNull; import android.util.Log; import org.alljoyn.about.AboutKeys; import org.alljoyn.bus.BusException; import org.alljoyn.bus.Variant; import org.alljoyn.services.common.BusObjectDescription; import java.util.Date; import java.util.Map; /** * AllJoynServiceEntitiy represents an AllJoyn service. * An AllJoynServiceEntity object is created from AllJoyn About announcement. * * @author NTT DOCOMO, INC. * @see <a href="https://allseenalliance.org/developers/learn/core/about-announcement/interface"> * https://allseenalliance.org/developers/learn/core/about-announcement/interface</a> */ public class AllJoynServiceEntity { /** * Human-friendly service name. */ public String serviceName; @NonNull public String busName; public short port; public Map<String, Variant> aboutData; // Flattened data from aboutData public String appId; public String defaultLanguage; public String deviceName; public String deviceId; public String appName; public String manufacturer; public String modelNumber; public String[] supportedLanguages; public String description; public String dateOfManufacture; public String softwareVersion; public String ajSoftwareVersion; public String hardwareVersion; public String supportUrl; @NonNull public BusObjectDescription[] proxyObjects; // public String objPath; public Date lastAlive; public AllJoynServiceEntity(@NonNull String busName, short port, Map<String, Variant> aboutData, @NonNull BusObjectDescription[] proxyObjects) { this.busName = busName; this.port = port; this.aboutData = aboutData; this.proxyObjects = proxyObjects; this.lastAlive = new Date(); flattenAboutData(); determineServiceName(); } /** * Flatten <code>aboutData</code> to member fields. */ private void flattenAboutData() { if (aboutData == null || aboutData.size() == 0) { return; } for (String key : aboutData.keySet()) { Variant val = aboutData.get(key); try { switch (key) { case AboutKeys.ABOUT_APP_ID: byte[] tmp = val.getObject(byte[].class); appId = toHexString(tmp); break; case AboutKeys.ABOUT_DEFAULT_LANGUAGE: // If default language is not specified, set it to English. try { defaultLanguage = val.getObject(String.class); } catch (Exception ignore) { defaultLanguage = "en"; } if (defaultLanguage == null || defaultLanguage.length() == 0) { defaultLanguage = "en"; } break; case AboutKeys.ABOUT_DEVICE_NAME: deviceName = val.getObject(String.class); break; case AboutKeys.ABOUT_DEVICE_ID: deviceId = val.getObject(String.class); break; case AboutKeys.ABOUT_APP_NAME: appName = val.getObject(String.class); break; case AboutKeys.ABOUT_MANUFACTURER: manufacturer = val.getObject(String.class); break; case AboutKeys.ABOUT_MODEL_NUMBER: modelNumber = val.getObject(String.class); break; case AboutKeys.ABOUT_SUPPORTED_LANGUAGES: supportedLanguages = val.getObject(String[].class); break; case AboutKeys.ABOUT_DESCRIPTION: description = val.getObject(String.class); break; case AboutKeys.ABOUT_DATE_OF_MANUFACTURE: dateOfManufacture = val.getObject(String.class); break; case AboutKeys.ABOUT_SOFTWARE_VERSION: softwareVersion = val.getObject(String.class); break; case AboutKeys.ABOUT_AJ_SOFTWARE_VERSION: ajSoftwareVersion = val.getObject(String.class); break; case AboutKeys.ABOUT_HARDWARE_VERSION: hardwareVersion = val.getObject(String.class); break; case AboutKeys.ABOUT_SUPPORT_URL: supportUrl = val.getObject(String.class); break; } } catch (Exception e) { if (BuildConfig.DEBUG) { Log.w(getClass().getSimpleName(), "Failed to parse \"" + key + "\": " + e.getLocalizedMessage()); } } } } private static String toHexString(byte[] bytes) { final char[] hexArray = "0123456789abcdef".toCharArray(); char[] hexChars = new char[bytes.length * 2]; for (int j = 0; j < bytes.length; ++j) { int v = bytes[j] & 0xFF; hexChars[j * 2] = hexArray[v >>> 4]; hexChars[j * 2 + 1] = hexArray[v & 0x0F]; } return new String(hexChars); } /** * Determine a DeviceConnect service name. */ private void determineServiceName() { if (aboutData.containsKey(AboutKeys.ABOUT_DEVICE_NAME)) { try { Variant val = aboutData.get(AboutKeys.ABOUT_DEVICE_NAME); serviceName = val.getObject(String.class); } catch (BusException e) { if (BuildConfig.DEBUG) { Log.w(getClass().getSimpleName(), "Failed to parse about announcement."); } serviceName = "Alljoyn service (" + busName.hashCode() + ")"; } } else { serviceName = "Alljoyn service (" + busName.hashCode() + ")"; } } }