[NFC] NFCTag listener and isConnected
authorMarcin Kaminski <marcin.ka@samsung.com>
Mon, 22 Dec 2014 07:53:00 +0000 (08:53 +0100)
committerMarcin Kaminski <marcin.ka@samsung.com>
Sat, 27 Dec 2014 17:30:09 +0000 (18:30 +0100)
NFCTag listener setting and unsetting added
with listener implementation.
Full implementation of NFTag::isConnected attribute

Change-Id: I122ec4978288f7f230a70624f6361710c7aad53e
Signed-off-by: Marcin Kaminski <marcin.ka@samsung.com>
src/nfc/nfc_adapter.cc
src/nfc/nfc_adapter.h
src/nfc/nfc_api.js
src/nfc/nfc_instance.cc

index 7cb4ec415e29d0eb435f194a3e1cb09a9fcde2c3..4b2f2591076cdbf996c8ccb36e32d4d86525c317 100644 (file)
@@ -61,6 +61,9 @@ NFCAdapter::~NFCAdapter() {
     if (m_is_ndef_listener_set) {
         nfc_p2p_unset_data_received_cb(m_peer_handle);
     }
+    if (m_is_tag_listener_set) {
+        nfc_manager_unset_tag_discovered_cb();
+    }
 }
 
 static picojson::value createEventError(double callbackId, PlatformException ex) {
@@ -646,17 +649,115 @@ bool NFCAdapter::IsTagConnected(int tag_id) {
 
     LoggerD("Entered");
 
-    if(tag_id != m_latest_tag_id) {
+    if(tag_id != m_latest_tag_id || NULL == m_last_tag_handle) {
         // internaly stored tag id changed -> new tag has been already connected
-        LoggerD("NFCTag () not connected. Latest tag id: %d",
-                tag_id, m_latest_tag_id);
+        // internaly stored tag handle NULL -> tag has been disconnected
+        LoggerD("NFCTag () not connected (id differs or invalid handle)");
+        return false;
+    }
+
+    nfc_tag_h handle = NULL;
+    int result = nfc_manager_get_connected_tag(&handle);
+    if(NFC_ERROR_NONE != result) {
+        LOGE("Failed to get connected tag: %s",
+            NFCUtil::getNFCErrorMessage(result).c_str());
+        // exception is thrown here to return undefined in JS layer
+        // instead of false
+        NFCUtil::throwNFCException(result, "Failed to get connected tag");
+    }
+
+    if(m_last_tag_handle != handle) {
+        LoggerD("Last known handle and current handle differs");
         return false;
     }
 
-    // TODO: implement checking if stored handle is still connected
-    LoggerW("This function is only a stub!");
     return true;
 }
 
+
+int NFCAdapter::GetNextTagId() {
+
+    LoggerD("Entered");
+    return ++m_latest_tag_id;
+}
+
+
+static void tagEventCallback(nfc_discovered_type_e type, nfc_tag_h tag, void *data)
+{
+    LoggerD("Entered");
+
+    picojson::value event = picojson::value(picojson::object());
+    picojson::object& obj = event.get<picojson::object>();
+    obj.insert(make_pair("listenerId", "TagListener"));
+
+    NFCAdapter* adapter = NFCAdapter::GetInstance();
+    // Tag detected event
+    if (NFC_DISCOVERED_TYPE_ATTACHED == type) {
+        nfc_tag_type_e tag_type;
+
+        int result;
+        result = nfc_tag_get_type(tag, &tag_type);
+        if(NFC_ERROR_NONE != result) {
+            LoggerE("setTagListener failed %d",result);
+            return;
+        }
+        // Fetch new id and set detected tag handle in NFCAdapter
+        int generated_id = adapter->GetNextTagId();
+        adapter->SetTagHandle(tag);
+
+        obj.insert(make_pair("action", "onattach"));
+        obj.insert(make_pair("id", static_cast<double>(generated_id)));
+        obj.insert(make_pair("type", NFCUtil::toStringNFCTag(tag_type)));
+
+        NFCInstance::getInstance().PostMessage(event.serialize().c_str());
+    }
+    // Tag disconnected event
+    else if (NFC_DISCOVERED_TYPE_DETACHED == type) {
+        // Set stored tag handle to NULL
+        adapter->SetTagHandle(NULL);
+
+        obj.insert(make_pair("action", "ondetach"));
+        NFCInstance::getInstance().PostMessage(event.serialize().c_str());
+    }
+    // ERROR - should never happen
+    else {
+        LoggerE("Invalid NFC discovered type: %d (%x)", type, type);
+    }
+
+}
+
+void NFCAdapter::SetTagListener(){
+
+    LoggerD("Entered");
+
+    if(!m_is_tag_listener_set) {
+        nfc_manager_set_tag_filter(NFC_TAG_FILTER_ALL_ENABLE);
+        int result = nfc_manager_set_tag_discovered_cb (tagEventCallback, NULL);
+        if (NFC_ERROR_NONE != result) {
+            LoggerE("Failed to register tag listener: %d", result);
+            NFCUtil::throwNFCException(result, "Failed to register tag listene");
+        }
+        m_is_tag_listener_set = true;
+    }
+}
+
+void NFCAdapter::UnsetTagListener(){
+
+    LoggerD("Entered");
+
+    if(m_is_tag_listener_set) {
+        nfc_manager_unset_tag_discovered_cb();
+        m_is_tag_listener_set = false;
+    }
+}
+
+void NFCAdapter::SetTagHandle(nfc_tag_h tag) {
+
+    LoggerD("Entered");
+
+    m_last_tag_handle = tag;
+}
+
+
 }// nfc
 }// extension
index f5d742f2de6683fa46f620c60e70830a4cff75c1..f6c62b3be4b05ec3ab4e1a2fcb20b7eb3696eeee 100644 (file)
@@ -54,6 +54,10 @@ public:
 
 // NFCTag related methods
     bool IsTagConnected(int tag_id);
+    void SetTagListener();
+    void UnsetTagListener();
+    int GetNextTagId();
+    void SetTagHandle(nfc_tag_h tag);
 
     static NFCAdapter* GetInstance();
 private:
@@ -61,6 +65,7 @@ private:
     virtual ~NFCAdapter();
 
     nfc_tag_h m_last_tag_handle;
+    bool m_is_tag_listener_set;
     int m_latest_tag_id;
     bool m_is_listener_set;
     bool m_is_transaction_ese_listener_set;
index 8e9ffcc841550c407645d679f32c038d5ed3b423..c8f7edaf47002d113328c0ee61e84ac2fc215b90 100644 (file)
@@ -51,6 +51,7 @@ var CARD_EMULATION_MODE_LISTENER = 'CardEmulationModeChanged';
 var ACTIVE_SECURE_ELEMENT_LISTENER = 'ActiveSecureElementChanged';
 var TRANSACTION_EVENT_ESE_LISTENER = 'TransactionEventListener_ESE';
 var TRANSACTION_EVENT_UICC_LISTENER = 'TransactionEventListener_UICC';
+var TAG_LISTENER = 'TagListener';
 var cardEmulationModeListener = new ListenerManager(native_, CARD_EMULATION_MODE_LISTENER);
 var activeSecureElementChangeListener = new ListenerManager(native_, ACTIVE_SECURE_ELEMENT_LISTENER);
 var transactionEventListenerEse = new ListenerManager(native_, TRANSACTION_EVENT_ESE_LISTENER);
@@ -264,6 +265,49 @@ NFCAdapter.prototype.setPowered = function() {
 
 NFCAdapter.prototype.setTagListener  = function() {
 
+    var args = validator_.validateArgs(arguments, [
+        {
+            name: 'listener',
+            type: types_.LISTENER,
+            values: ['onattach', 'ondetach']
+        },
+        {
+            name : 'tagType',
+            type : types_.STRING,
+            optional : true,
+            nullable : true
+        }
+    ]);
+
+    // TODO: NFCTag type value validation needed here
+
+    // Listener object creation
+    var listenerCallback = function(message) {
+        var tagObject = undefined;
+
+        if('onattach' === message.action) {
+            tagObject = new NFCTag(message.id);
+
+            if(!types_.isNullOrUndefined(args.tagType)) {
+                // If filter set for listener then check tag type
+                if(tagObject.type !== args.tagType) {
+                    return;
+                }
+            }
+        }
+        args.listener[message.action](tagObject);
+    }
+
+    // Register (acivate) core listener if not done yet
+    if(!native_.isListenerSet(TAG_LISTENER)) {
+        var result = native_.callSync('NFCAdapter_setTagListener');
+        if (native_.isFailure(result)) {
+            throw new tizen.WebAPIException(0, result.error.message, result.error.name);
+        }
+    }
+
+    native_.addListener(TAG_LISTENER, listenerCallback);
+    return;
 };
 
 NFCAdapter.prototype.setPeerListener = function() {
@@ -296,6 +340,14 @@ NFCAdapter.prototype.setPeerListener = function() {
 
 NFCAdapter.prototype.unsetTagListener = function() {
 
+    native_.removeListener(TAG_LISTENER);
+
+    var result = native_.callSync('NFCAdapter_unsetTagListener');
+    if (native_.isFailure(result)) {
+        throw new tizen.WebAPIException(0, result.error.message, result.error.name);
+    }
+
+    return;
 };
 
 NFCAdapter.prototype.unsetPeerListener = function() {
index d729b44fae13111a9312a07f1445dea46fc06c11..576d64affce7cdd4fe6baa8898e4bcd87456c99b 100644 (file)
@@ -38,7 +38,6 @@ NFCInstance::NFCInstance() {
     REGISTER_SYNC("NFCAdapter_activeSecureElementGetter", ActiveSecureElementGetter);
     REGISTER_SYNC("NFCAdapter_setPeerListener", SetPeerListener);
     REGISTER_SYNC("NFCAdapter_setTagListener", SetTagListener);
-    REGISTER_SYNC("NFCAdapter_setPeerListener", SetPeerListener);
     REGISTER_SYNC("NFCAdapter_PeerIsConnectedGetter", PeerIsConnectedGetter);
     REGISTER_SYNC("NFCAdapter_unsetTagListener", UnsetTagListener);
     REGISTER_SYNC("NFCAdapter_unsetPeerListener", UnsetPeerListener);
@@ -212,6 +211,13 @@ void NFCInstance::ActiveSecureElementGetter(
 void NFCInstance::SetTagListener(
         const picojson::value& args, picojson::object& out) {
 
+    try {
+        NFCAdapter::GetInstance()->SetTagListener();
+        ReportSuccess(out);
+    }
+    catch(const common::PlatformException& ex) {
+        ReportError(ex, out);
+    }
 }
 
 void NFCInstance::PeerIsConnectedGetter(
@@ -242,6 +248,8 @@ void NFCInstance::SetPeerListener(
 void NFCInstance::UnsetTagListener(
         const picojson::value& args, picojson::object& out) {
 
+    NFCAdapter::GetInstance()->UnsetTagListener();
+    ReportSuccess(out);
 }
 
 void NFCInstance::UnsetPeerListener(
@@ -448,10 +456,26 @@ void NFCInstance::TagTypeGetter(
     int tag_id = (int)args.get("id").get<double>();
     LoggerD("Tag id: %d", tag_id);
 
-    // TODO: implement this stub
-    LoggerW("Stub function used!");
-    std::string tag_type = NFCUtil::toStringNFCTag(NFC_UNKNOWN_TARGET);
-    ReportSuccess(picojson::value(tag_type), out);
+    try {
+        // Function below throws exception if core API call fails
+        if (!NFCAdapter::GetInstance()->IsTagConnected(tag_id)) {
+            LoggerE("Tag with id %d is not connected anymore", tag_id);
+            // If tag is not connected then attribute's value
+            // should be undefined
+            ReportError(out);
+            return;
+        }
+
+        // TODO: implement this stub
+        LoggerW("Stub function used!");
+        std::string tag_type = NFCUtil::toStringNFCTag(NFC_UNKNOWN_TARGET);
+
+        ReportSuccess(picojson::value(tag_type), out);
+    }
+    catch(const PlatformException& ex) {
+        LoggerE("Failed to check tag connection");
+        ReportError(ex, out);
+    }
 }
 
 void NFCInstance::TagIsSupportedNDEFGetter(
@@ -462,10 +486,27 @@ void NFCInstance::TagIsSupportedNDEFGetter(
     int tag_id = (int)args.get("id").get<double>();
     LoggerD("Tag id: %d", tag_id);
 
-    // TODO: implement this stub
-    LoggerW("Stub function used!");
-    bool is_supported = true;
-    ReportSuccess(picojson::value(is_supported), out);
+    try {
+        // Function below throws exception if core API call fails
+        if (!NFCAdapter::GetInstance()->IsTagConnected(tag_id)) {
+            LoggerE("Tag with id %d is not connected anymore", tag_id);
+            // If tag is not connected then attribute's value
+            // should be undefined
+            ReportError(out);
+            return;
+        }
+
+        // TODO: implement this stub
+        LoggerW("Stub function used!");
+        bool is_supported = true;
+
+        ReportSuccess(picojson::value(is_supported), out);
+    }
+    catch(const PlatformException& ex) {
+        LoggerE("Failed to check tag connection");
+        ReportError(ex, out);
+    }
+
 }
 
 void NFCInstance::TagNDEFSizeGetter(
@@ -476,10 +517,27 @@ void NFCInstance::TagNDEFSizeGetter(
     int tag_id = (int)args.get("id").get<double>();
     LoggerD("Tag id: %d", tag_id);
 
-    // TODO: implement this stub
-    LoggerW("Stub function used!");
-    int ndef_size = 1234;
-    ReportSuccess(picojson::value((double)ndef_size), out);
+    try {
+        // Function below throws exception if core API call fails
+        if (!NFCAdapter::GetInstance()->IsTagConnected(tag_id)) {
+            LoggerE("Tag with id %d is not connected anymore", tag_id);
+            // If tag is not connected then attribute's value
+            // should be undefined
+            ReportError(out);
+            return;
+        }
+
+        // TODO: implement this stub
+        LoggerW("Stub function used!");
+        int ndef_size = 1234;
+
+        ReportSuccess(picojson::value((double)ndef_size), out);
+    }
+    catch(const PlatformException& ex) {
+        LoggerE("Failed to check tag connection");
+        ReportError(ex, out);
+    }
+
 }
 
 void NFCInstance::TagPropertiesGetter(
@@ -489,10 +547,24 @@ void NFCInstance::TagPropertiesGetter(
 
     int tag_id = (int)args.get("id").get<double>();
     LoggerD("Tag id: %d", tag_id);
-
-    // TODO: implement this stub
-    LoggerW("Stub function used!");
-    ReportSuccess(out);
+    try {
+        // Function below throws exception if core API call fails
+        if (!NFCAdapter::GetInstance()->IsTagConnected(tag_id)) {
+            LoggerE("Tag with id %d is not connected anymore", tag_id);
+            // If tag is not connected then attribute's value
+            // should be undefined
+            ReportError(out);
+            return;
+        }
+
+        // TODO: implement this stub
+        LoggerW("Stub function used!");
+        ReportSuccess(out);
+    }
+    catch(const PlatformException& ex) {
+        LoggerE("Failed to check tag connection");
+        ReportError(ex, out);
+    }
 }
 
 void NFCInstance::TagIsConnectedGetter(