{"action":"created","comment":{"url":"https://api.github.com/repos/kaaproject/kaa/pulls/comments/69116603","id":69116603,"diff_hunk":"@@ -4,4 +4,805 @@ title: Notifications\n permalink: /:path/\n sort_idx: 70\n ---\n-Purpose of notifications. Schemas and versioning. Topics, visibility (EP groups related), TTL, and subscriptions (mandatory and optional).\n+{% assign root_url = page.url | split: '/'%}\n+{% capture root_url  %} /{{root_url[1]}}/{{root_url[2]}}/{% endcapture %}\n+\n+* TOC\n+{:toc}\n+\n+\n+The Kaa Notification subsystem enables delivery of messages from the Kaa cluster to endpoints (EP). Unlike configuration data that represents the desired EP state, notifications can be thought of as calls for a dynamic EP action. \n+For example, a notification may cause a client application to display a message on the UI (a user notification).\n+\n+This guide will familiarize you with the basic concepts of Kaa notifications and programming of the Kaa notification subsystem. It is assumed that you have already set up either a [Kaa Sandbox](http://www.kaaproject.org/download-kaa) or a [full-blown Kaa cluster]({{root_url}}Administration-guide/System-installation/Cluster-setup/) and that you have created at least one [tenant]({{root_url}}Administration-guide/Tenants-and-applications-management/#TODO) and one [application]({{root_url}}Administration-guide/Tenants-and-applications-management/#managing-applications) in Kaa. \n+We also recommend that you review [collecting endpoint profiles guide]({{root_url}}Programming-guide/Key-platform-features/Data-collection) and [endpoint groups]({{root_url}}Programming-guide/Key-platform-features/Endpoint-groups) before you proceed with this guide.\n+\n+### Basic architecture\n+\n+The following diagram illustrates basic entities and data flows in scope of the notification management:\n+\n+* Notifications are generated based on the [notification schema](#notification-schema) created by the developer for the application \n+* The user or admin sends a notification via [REST API]({{root_url}}Programming-guide/Server-REST-APIs/#TODO) call or using Administration UI (see [Sending notifications](#sending-notifications)). \n+\n+![](images/basic_architecture_notification.png)\n+\n+### Configuring Kaa\n+This section provides guidance on how to configure notifications in Kaa.\n+\n+#### Notification schema\n+\n+The Kaa notifications functionality allows transferring any data to endpoints. The structure of the data that is carried by notifications is defined by the notification schema configured on the Kaa server and built into Kaa endpoints. The notification schema is defined similarly to the endpoint profile schema. \n+In addition to the user-defined schema and its version, notifications are characterized by their type that can be either system or user. System notifications are processed by the prepackaged endpoint functions, while user notifications are handed over to the client code via the endpoint API.\n+\n+Since the data structure requirements may evolve throughout the Kaa-based system lifetime, the Kaa server can be configured to simultaneously handle notification schemas of multiple versions. \n+In this case, a notification will have multiple schema versions associated with it, as well as multiple sets of notification data so that each schema version is covered. To deliver such a notification to an endpoint, the server chooses the schema version supported by the endpoint.\n+\n+The default notification schema installed for Kaa applications is empty. For the purpose of this guide, we will use a simple notification schema shown in the following code block.\n+\n+```json\n+{ \n+    \"type\":\"record\",\n+    \"name\":\"ExampleNotification\",\n+    \"namespace\":\"org.kaaproject.kaa.schema.sample.notification\",\n+    \"fields\":[ \n+        { \n+            \"name\":\"message\",\n+            \"type\":\"string\"\n+        }\n+    ]\n+}\n+```\n+\n+You can configure your own notification schema via [REST API]({{root_url}}Programming-guide/Server-REST-APIs/#TODO) call or use Administration UI as shown below. \n+\n+\n+The list of notification schemas created by a tenant developer for the application is shown in the **Notification schemas** window.\n+\n+![Add Notification Schema 1](images/add_notification_schema_1.png)\n+\n+As a tenant developer, you can create new notification schemas for the application as follows:\n+\n+1. In the **Notification schemas** window for the application, click **Add schema**.\n+2. In the **Add notification schema** window, create a notification schema either by using the [schema form](#schema-form) or by uploading a schema in the [Avro](http://avro.apache.org/docs/current/spec.html) format from a file.\n+\n+![Add Notification Schema 2](images/add_notification_schema_2.png)\n+3. Click **Add** to save the schema.\n+\n+If you want to review the added Avro schema, open the corresponding **Notification schema** window by clicking the schema in the **Notification schemas** window.\n+\n+![Add Notification Schema 3](images/add_notification_schema_3.png)\n+\n+#### Notification topics\n+\n+Notifications in Kaa are organized into topics. Each topic may be associated with one or more endpoint groups. To subscribe to a specific notification, endpoints must belong to one or more endpoint groups that are associated with the corresponding notification topic.\n+\n+Also, it is possible to make some of the topics configured within the application accessible only to some selected endpoint groups. For this purpose, each topic created in Kaa can be assigned to one or more endpoint groups (global by default). \n+In order for an endpoint to receive notifications associated with the topic, the endpoint must belong to at least one group that supports this topic.\n+\n+Topics can be mandatory or optional. Mandatory topic notifications are delivered in an enforced manner. Optional topics require subscription. It is responsibility of the client code to add notification listeners and subscribe to optional topics.\n+\n+You can manage notification topics via [REST API]({{root_url}}Programming-guide/Server-REST-APIs/#TODO) call or using Administration UI as shown below.\n+\n+To add a new notification topic to the application, do the following:\n+\n+1. Open the **Notification topics** window by clicking **Notification topics** under the application menu on the navigation panel and then click **Add notification topic**.\n+\n+    ![Add Notification Topic 1](images/add_notification_topic_1.png)\n+    \n+2. Fill in all necessary fields and then click **Add**.\n+\n+    ![Add Notification Topic 2](images/add_notification_topic_2.png)\n+\n+    The newly created topic will appear in the **Notification topics** window.\n+\n+    ![Add Notification Topic 3](images/add_notification_topic_3.png)\n+    \n+    \n+> **NOTE:** Once created, a notification topic does not impact any endpoints. To deliver notifications to some endpoint, at first you need to assign the topic to an endpoint group containing \n+this endpoint via [REST API]({{root_url}}Programming-guide/Server-REST-APIs/#TODO) or using [Administration UI](#add-notification-topic-to-endpoint-group).\n+\n+\n+#### Add notification topic to endpoint group\n+\n+To add a notification topic to the endpoint group, do the following:\n+\n+1. In the **Endpoint group** window, click **Add notification topic**.\n+2. In the **Add topic to endpoint group** dialog, select the topic(s) and click **Add**.\n+Now all the endpoints belonging to the current group will be subscribed to notifications on these topics.\n+\n+![Add topic to endpoint group](images/add_topic_to_endpoint_group.png)\n+\n+Assuming that you have created custom endpoint groups from the [Using endpoint groups guide]({{root_url}}Programming-guide/Key-platform-features/Endpoint-groups/#custom-endpoint-groups), it would be logical to create and assign the following topics:\n+\n+<table>\n+    <tr>\n+        <th rowspan=\"2\">Topic id</th>\n+        <th colspan=\"5\"><center>Endpoint Group Name</center></th>\n+    </tr>\n+    <tr>\n+        <th>All</th>\n+        <th>Android Froyo endpoints</th>\n+        <th>Android endpoints</th>\n+        <th>iOS 8 endpoints</th>\n+        <th>3.0 RC1 QA group endpoints</th>\n+    </tr>\n+    <tr>\n+        <td>Android notifications</td>     \n+        <td>false</td> \n+        <td>true</td>   \n+        <td>true</td>    \n+        <td>false</td>\n+        <td>false</td>      \n+    </tr>\n+    <tr>\n+        <td>iOS 8 notifications</td>      \n+        <td>false</td>                 \n+        <td>false</td>                   \n+        <td>false</td>                    \n+        <td>true</td>            \n+        <td>false</td>                      \n+    </tr>\n+    <tr>\n+        <td>All devices notifications</td> \n+        <td>true</td>                 \n+        <td>false</td>                  \n+        <td>false</td>                    \n+        <td>false</td>           \n+        <td>false</td>                     \n+    </tr>\n+</table>\n+\n+#### Sending notifications\n+To send a notification, you can issue the [REST API]({{root_url}}Programming-guide/Server-REST-APIs/#TODO) request or Administration UI as described below.\n+\n+Do the following steps to send a notification:\n+\n+1. In the **Notification topics**, click the mail icon next to the appropriate notification topic.\n+2. In the **Send notification** window, create a notification either by using the **Notification body** [record form](#record-form) or by uploading the data in the JSON format from a file.\n+\n+> **NOTE:** The contents of the file should match the corresponding notification schema. And if **Endpoint KeyHash** field is empty will be sent a broadcast notification.\n+\n+![Send Notification](images/send_notification.png)\n+3. Click **Send** to send the notification.\n+\n+The file with the following contents will match the default sandbox notification schema.\n+\n+```\n+{\"message\": \"Hello from Kaa!\"}\n+```\n+\n+#### Notification pipelines\n+\n+Notification pipelines manage individual notifications within a topic. A notification remains queued in the pipeline until its time-to-live (TTL) expires, after which the notification is dropped. The notification pipeline type specifies the scope of notifications delivery. \n+It can be either multicast (targeted to an unbounded number of endpoints) or unicast (targeted to a single specific endpoint).\n+    \n+**Multicast pipelines** \n+<br/>\n+Whenever a notification is sent to a topic, it gets added to the corresponding pipeline with a unique sequential index per pipeline. Endpoints independently maintain their position in every pipeline by remembering the last sequential index per pipeline that they received.\n+    \n+**Unicast pipelines** \n+<br/>\n+Whenever a notification is sent to a topic, it gets added to the corresponding pipeline with a unique ID. Endpoints independently maintain their pipeline by reporting all received notification IDs. The server removes the notification from the pipeline once it receives a receipt confirmation from the endpoint. \n+Sending a unicast notification requires specifying the endpoint and topic IDs. The endpoint must be subscribed to the specified topic, otherwise an error will be returned.\n+\n+### Using Notifications SDK API\n+This section provides code samples which illustrate practical usage of notifications in Kaa.\n+\n+#### Get available topics\n+To get a list of available topics, do the following:\n+\n+\n+<ul class=\"nav nav-tabs\">\n+  <li class=\"active\"><a data-toggle=\"tab\" href=\"#Java-9\">Java</a></li>\n+  <li><a data-toggle=\"tab\" href=\"#C_plus_plus-9\">C++</a></li>\n+  <li><a data-toggle=\"tab\" href=\"#C-9\">C</a></li>\n+  <li><a data-toggle=\"tab\" href=\"#Objective-C-9\">Objective-C</a></li>\n+</ul>\n+\n+<div class=\"tab-content\">\n+<div id=\"Java-9\" class=\"tab-pane fade in active\" markdown=\"1\" >\n+\n+```java\n+import org.kaaproject.kaa.client.KaaClient;\n+import org.kaaproject.kaa.client.DesktopKaaPlatformContext;\n+import org.kaaproject.kaa.common.endpoint.gen.Topic;\n+...\n+    KaaClient kaaClient = Kaa.newClient(new DesktopKaaPlatformContext())\n+    // Start Kaa client\n+    kaaClient.start()\n+...\n+ \n+    List<Topic> topics = kaaClient.getTopics();\n+ \n+    for (Topic topic : topics) {\n+        System.out.printf(\"Id: %s, name: %s, type: %s\"\n+                , topic.getId(), topic.getName(), topic.getSubscriptionType());\n+    }\n+```\n+\n+</div><div id=\"C_plus_plus-9\" class=\"tab-pane fade\" markdown=\"1\" >\n+\n+```c++\n+#include <iostream>\n+ \n+#include <kaa/Kaa.hpp>\n+#include <kaa/logging/LoggingUtils.hpp>\n+ \n+using namespace kaa;\n+ \n+...\n+// Create an endpoint instance\n+auto kaaClient = Kaa::newClient();\n+// Start an endpoint\n+kaaClient->start();\n+ \n+// Get available topics\n+const auto& topics = kaaClient->getTopics();\n+for (const auto& topic : topics) {\n+    std::cout << \"Id: \" << topic.id << \", name: \" << topic.name\n+              << \", type: \" << LoggingUtils::TopicSubscriptionTypeToString(topic.subscriptionType) << std::endl;\n+}\n+```\n+\n+</div><div id=\"C-9\" class=\"tab-pane fade\" markdown=\"1\" >\n+\n+```c\n+#include <kaa/platform/kaa_client.h>\n+#include <kaa/kaa_notification_manager.h>\n+ \n+kaa_client_t *kaa_client = /* ... */;\n+ \n+void on_topic_list_uploaded(void *context, kaa_list_t *topics)\n+{\n+    kaa_list_node_t *it = kaa_list_begin(topics);\n+    while (it) {\n+         kaa_topic_t *topic = (kaa_topic_t *) kaa_list_get_data(it);\n+         printf(\"Id: %lu, name: %s, type: %s\\n\", topic->id, topic->name, (topic->subscription_type == OPTIONAL_SUBSCRIPTION)? \"OPTIONAL\":\"MANDATORY\");  \n+         it = kaa_list_next(it);\n+    }\n+}\n+ \n+kaa_list_t *topics_list = NULL;\n+kaa_error_t error_core = kaa_get_topics(kaa_client_get_context(kaa_client)->notification_manager, &topics_list);\n+on_topic_list_uploaded(NULL, topics_list);\n+```\n+\n+</div><div id=\"Objective-C-9\" class=\"tab-pane fade\" markdown=\"1\" >\n+\n+```objective-c\n+#import <Kaa/Kaa.h>\n+...\n+    id<KaaClient> kaaClient = [Kaa client]\n+...\n+    // Start Kaa client\n+    [kaaClient start]\n+...\n+ \n+    NSArray *topics = [kaaClient getTopics];\n+ \n+    for (Topic *topic in topics) {\n+        NSLog(@\"%lld %@ %u\", topic.id, topic.name, topic.subscriptionType);\n+    }\n+```\n+\n+</div></div>\n+\n+#### Subscribe to optional topics\n+To receive notifications on some optional topic, at first subscribe to that topic as shown in the following code block:\n+<ul class=\"nav nav-tabs\">\n+  <li class=\"active\"><a data-toggle=\"tab\" href=\"#Java-14\">Java</a></li>\n+  <li><a data-toggle=\"tab\" href=\"#C_plus_plus-14\">C++</a></li>\n+  <li><a data-toggle=\"tab\" href=\"#C-14\">C</a></li>\n+  <li><a data-toggle=\"tab\" href=\"#Objective-C-14\">Objective-C</a></li>\n+</ul>\n+\n+<div class=\"tab-content\">\n+<div id=\"Java-14\" class=\"tab-pane fade in active\" markdown=\"1\" >\n+\n+```java\n+import org.kaaproject.kaa.client.KaaClient;\n+...\n+// Add notification listener(s) (optional)\n+...\n+// Subscribe\n+kaaClient.subscribeToTopic(\"Android notifications\", true);\n+...\n+// Unsubscribe. All added listeners will be removed automatically\n+kaaClient.unsubscribeFromTopic(\"Android notifications\", true);\n+```\n+\n+</div><div id=\"C_plus_plus-14\" class=\"tab-pane fade\" markdown=\"1\" >\n+\n+```c++\n+#include <kaa/Kaa.hpp>\n+ \n+using namespace kaa;\n+ \n+...\n+ \n+// Add notification listener(s) (optional)\n+ \n+// Subscribe\n+kaaClient->subscribeToTopic(\"Android notifications\");\n+ \n+// Unsubscribe\n+kaaClient->unsubscribeFromTopic(\"Android notifications\");\n+```\n+\n+</div><div id=\"C-14\" class=\"tab-pane fade\" markdown=\"1\" >\n+\n+```c\n+#include <kaa/kaa_notification_manager.h>\n+#include <kaa/platform/ext_notification_receiver.h>\n+// Assume we have some optional topic\n+uint64_t topic_id = 12345;\n+ \n+// Subcribe\n+kaa_error_t error_code = kaa_subscribe_to_topic(kaa_client_get_context(kaa_client)->notification_manager, &topic_id, true);\n+ \n+// Unsubscribe. All added listeners will be removed automatically\n+error_code = kaa_unsubscribe_from_topic(kaa_client_get_context(kaa_client)->notification_manager, &topic_id, true);\n+```\n+\n+</div><div id=\"Objective-C-14\" class=\"tab-pane fade\" markdown=\"1\" >\n+\n+```objective-c\n+#import <Kaa/Kaa.h>\n+...\n+// Add notification listener(s) (optional)\n+ \n+// Subscribe\n+[kaaClient subscribeToTopicWithId:@\"iOS notifications\" forceSync:YES];\n+...\n+// Unsubscribe. All added listeners will be removed automatically\n+[kaaClient unsubscribeFromTopicWithId:@\"iOS notifications\" forceSync:YES];\n+```\n+\n+</div></div>\n+\n+You can work with a list of optional topics in a similar way as with a list of available topics.\n+\n+<ul class=\"nav nav-tabs\">\n+  <li class=\"active\"><a data-toggle=\"tab\" href=\"#Java-15\">Java</a></li>\n+  <li><a data-toggle=\"tab\" href=\"#C_plus_plus-15\">C++</a></li>\n+  <li><a data-toggle=\"tab\" href=\"#C-15\">C</a></li>\n+  <li><a data-toggle=\"tab\" href=\"#Objective-C-15\">Objective-C</a></li>\n+</ul>\n+\n+<div class=\"tab-content\">\n+<div id=\"Java-15\" class=\"tab-pane fade in active\" markdown=\"1\" >\n+\n+```java\n+// Add notification listener(s) (optional)\n+...\n+// Subscribe\n+kaaClient.subscribeToTopics(Arrays.asList(\"iOS 8 notifications\", \"another_optional_topic_id\"), true);\n+...\n+// Unsubscribe\n+kaaClient.unsubscribeFromTopics(Arrays.asList(\"iOS 8 notifications\", \"another_optional_topic_id\"), true);\n+```\n+\n+</div><div id=\"C_plus_plus-15\" class=\"tab-pane fade\" markdown=\"1\" >\n+\n+```c++\n+#include <kaa/Kaa.hpp>\n+...\n+// Add notification listener(s) (optional)\n+ \n+// Subscribe\n+kaaClient->subscribeToTopics({\"iOS 8 notifications\", \"another_optional_topic_id\"});\n+ \n+// Unsubscribe\n+kaaClient->unsubscribeFromTopics({\"iOS 8 notifications\", \"another_optional_topic_id\"});\n+```\n+\n+</div><div id=\"C-15\" class=\"tab-pane fade\" markdown=\"1\" >\n+\n+```c\n+#include <kaa/kaa_notification_manager.h>\n+#include <kaa/platform/ext_notification_receiver.h>\n+ \n+// Assume we have some optional topics\n+uint64_t topic_ids[] = { 12345, 6789 };\n+ \n+// Subscribe\n+kaa_error_t error_code = kaa_subscribe_to_topics(kaa_client_get_context(kaa_client)->notification_manager, topic_ids, sizeof(topic_ids) / sizeof(uint64_t), true);\n+ \n+// Unsubscribe\n+error_code = kaa_unsubscribe_from_topics(kaa_client_get_context(kaa_client)->notification_manager, topic_ids, topics_count, true);\n+```\n+\n+</div><div id=\"Objective-C-15\" class=\"tab-pane fade\" markdown=\"1\" >\n+\n+```objective-c\n+// Add notification listener(s) (optional)\n+...\n+// Subscribe\n+[kaaClient subscribeToTopicsWithIDs:@[@\"iOS 8 notifications\", @\"another_optional_topic_id\"] forceSync:YES];\n+...\n+// Unsubscribe\n+[kaaClient unsubscribeFromTopicsWithIDs:@[@\"iOS 8 notifications\", @\"another_optional_topic_id\"] forceSync:YES];\n+```\n+\n+</div></div>\n+\n+\n+#### Subscribe to updates on available topics\n+To receive updates for the available topics list, add at least one listener as shown in the following code block (the number of listeners is not limited):\n+\n+<ul class=\"nav nav-tabs\">\n+  <li class=\"active\"><a data-toggle=\"tab\" href=\"#Java-10\">Java</a></li>\n+  <li><a data-toggle=\"tab\" href=\"#C_plus_plus-10\">C++</a></li>\n+  <li><a data-toggle=\"tab\" href=\"#C-10\">C</a></li>\n+  <li><a data-toggle=\"tab\" href=\"#Objective-C-10\">Objective-C</a></li>\n+</ul>\n+\n+<div class=\"tab-content\">\n+<div id=\"Java-10\" class=\"tab-pane fade in active\" markdown=\"1\" >\n+\n+```java\n+import org.kaaproject.kaa.client.KaaClient;\n+import org.kaaproject.kaa.client.KaaDesktop;\n+import org.kaaproject.kaa.client.notification.NotificationManager;\n+import org.kaaproject.kaa.client.notification.NotificationTopicListListener;\n+import org.kaaproject.kaa.common.endpoint.gen.Topic;\n+...\n+// Add listener\n+kaaClient.addTopicListListener(new NotificationTopicListListener() {\n+    @Override\n+    public void onListUpdated(List<Topic> topics) {\n+        for (Topic topic : topics) {\n+            System.out.printf(\"Id: %s, name: %s, type: %s\",\n+            topic.getId(), topic.getName(), topic.getSubscriptionType());\n+    }\n+}});\n+...\n+// Remove listener\n+kaaClient.removeTopicListListener(someOtherTopicUpdateListener);\n+```\n+\n+</div><div id=\"C_plus_plus-10\" class=\"tab-pane fade\" markdown=\"1\" >\n+\n+```c++\n+#include <iostream>\n+#include <memory>\n+ \n+#include <kaa/Kaa.hpp>\n+#include <kaa/logging/LoggingUtils.hpp>\n+#include <kaa/notification/INotificationTopicListListener.hpp>\n+ \n+using namespace kaa;\n+class NotificationTopicListListener : public INotificationTopicListListener {\n+public:\n+    virtual void onListUpdated(const Topics& topics)\n+    {\n+        for (const auto& topic : topics) {\n+            std::cout << \"Id: \" << topic.id << \", name: \" << topic.name\n+              << \", type: \" << LoggingUtils::TopicSubscriptionTypeToString(topic.subscriptionType) << std::endl;\n+        }\n+    }\n+};\n+...\n+// Create a listener which receives the list of available topics.\n+std::unique_ptr<NotificationTopicListListener> topicListListener(new NotificationTopicListListener());\n+ \n+// Add a listener\n+kaaClient->addTopicListListener(*topicListListener);\n+// Remove a listener\n+kaaClient->removeTopicListListener(*topicListListener);\n+```\n+\n+</div><div id=\"C-10\" class=\"tab-pane fade\" markdown=\"1\" >\n+\n+```c\n+#include <kaa/kaa_notification_manager.h>\n+#include <kaa/platform/ext_notification_receiver.h>\n+kaa_topic_listener_t topic_listener = { &on_topic_list_uploaded, NULL };\n+uint32_t topic_listener_id = 0;\n+ \n+// Add listener\n+kaa_error_t error_code = kaa_add_topic_list_listener(kaa_client_get_context(kaa_client)->notification_manager, &topic_listener, &topic_listener_id);\n+ \n+// Remove listener\n+error_code = kaa_remove_topic_list_listener(kaa_client_get_context(kaa_client)->notification_manager, &topic_listener_id);\n+```\n+\n+</div><div id=\"Objective-C-10\" class=\"tab-pane fade\" markdown=\"1\" >\n+\n+```objective-c","path":"doc/Programming-guide/Key-platform-features/Notifications/index.md","position":510,"original_position":510,"commit_id":"73a8cd95a111b3ecf4635509bf2eb27366c70ece","original_commit_id":"73a8cd95a111b3ecf4635509bf2eb27366c70ece","user":{"login":"balldir","id":1971989,"avatar_url":"https://avatars.githubusercontent.com/u/1971989?v=3","gravatar_id":"","url":"https://api.github.com/users/balldir","html_url":"https://github.com/balldir","followers_url":"https://api.github.com/users/balldir/followers","following_url":"https://api.github.com/users/balldir/following{/other_user}","gists_url":"https://api.github.com/users/balldir/gists{/gist_id}","starred_url":"https://api.github.com/users/balldir/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/balldir/subscriptions","organizations_url":"https://api.github.com/users/balldir/orgs","repos_url":"https://api.github.com/users/balldir/repos","events_url":"https://api.github.com/users/balldir/events{/privacy}","received_events_url":"https://api.github.com/users/balldir/received_events","type":"User","site_admin":false},"body":"Proper tip is objc , not objective-c","created_at":"2016-06-30T11:35:51Z","updated_at":"2016-06-30T11:35:51Z","html_url":"https://github.com/kaaproject/kaa/pull/764#discussion_r69116603","pull_request_url":"https://api.github.com/repos/kaaproject/kaa/pulls/764","_links":{"self":{"href":"https://api.github.com/repos/kaaproject/kaa/pulls/comments/69116603"},"html":{"href":"https://github.com/kaaproject/kaa/pull/764#discussion_r69116603"},"pull_request":{"href":"https://api.github.com/repos/kaaproject/kaa/pulls/764"}}},"pull_request":{"url":"https://api.github.com/repos/kaaproject/kaa/pulls/764","id":74060936,"html_url":"https://github.com/kaaproject/kaa/pull/764","diff_url":"https://github.com/kaaproject/kaa/pull/764.diff","patch_url":"https://github.com/kaaproject/kaa/pull/764.patch","issue_url":"https://api.github.com/repos/kaaproject/kaa/issues/764","number":764,"state":"open","locked":false,"title":"KAA-1167 Add a page on notifications","user":{"login":"Kirill380","id":6154009,"avatar_url":"https://avatars.githubusercontent.com/u/6154009?v=3","gravatar_id":"","url":"https://api.github.com/users/Kirill380","html_url":"https://github.com/Kirill380","followers_url":"https://api.github.com/users/Kirill380/followers","following_url":"https://api.github.com/users/Kirill380/following{/other_user}","gists_url":"https://api.github.com/users/Kirill380/gists{/gist_id}","starred_url":"https://api.github.com/users/Kirill380/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Kirill380/subscriptions","organizations_url":"https://api.github.com/users/Kirill380/orgs","repos_url":"https://api.github.com/users/Kirill380/repos","events_url":"https://api.github.com/users/Kirill380/events{/privacy}","received_events_url":"https://api.github.com/users/Kirill380/received_events","type":"User","site_admin":false},"body":"","created_at":"2016-06-16T10:59:46Z","updated_at":"2016-06-30T11:35:51Z","closed_at":null,"merged_at":null,"merge_commit_sha":"756769892657cc9ac48b0edc98bd3490704bc560","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/kaaproject/kaa/pulls/764/commits","review_comments_url":"https://api.github.com/repos/kaaproject/kaa/pulls/764/comments","review_comment_url":"https://api.github.com/repos/kaaproject/kaa/pulls/comments{/number}","comments_url":"https://api.github.com/repos/kaaproject/kaa/issues/764/comments","statuses_url":"https://api.github.com/repos/kaaproject/kaa/statuses/73a8cd95a111b3ecf4635509bf2eb27366c70ece","head":{"label":"Kirill380:feature/KAA-1167","ref":"feature/KAA-1167","sha":"73a8cd95a111b3ecf4635509bf2eb27366c70ece","user":{"login":"Kirill380","id":6154009,"avatar_url":"https://avatars.githubusercontent.com/u/6154009?v=3","gravatar_id":"","url":"https://api.github.com/users/Kirill380","html_url":"https://github.com/Kirill380","followers_url":"https://api.github.com/users/Kirill380/followers","following_url":"https://api.github.com/users/Kirill380/following{/other_user}","gists_url":"https://api.github.com/users/Kirill380/gists{/gist_id}","starred_url":"https://api.github.com/users/Kirill380/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Kirill380/subscriptions","organizations_url":"https://api.github.com/users/Kirill380/orgs","repos_url":"https://api.github.com/users/Kirill380/repos","events_url":"https://api.github.com/users/Kirill380/events{/privacy}","received_events_url":"https://api.github.com/users/Kirill380/received_events","type":"User","site_admin":false},"repo":{"id":58935242,"name":"kaa","full_name":"Kirill380/kaa","owner":{"login":"Kirill380","id":6154009,"avatar_url":"https://avatars.githubusercontent.com/u/6154009?v=3","gravatar_id":"","url":"https://api.github.com/users/Kirill380","html_url":"https://github.com/Kirill380","followers_url":"https://api.github.com/users/Kirill380/followers","following_url":"https://api.github.com/users/Kirill380/following{/other_user}","gists_url":"https://api.github.com/users/Kirill380/gists{/gist_id}","starred_url":"https://api.github.com/users/Kirill380/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Kirill380/subscriptions","organizations_url":"https://api.github.com/users/Kirill380/orgs","repos_url":"https://api.github.com/users/Kirill380/repos","events_url":"https://api.github.com/users/Kirill380/events{/privacy}","received_events_url":"https://api.github.com/users/Kirill380/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/Kirill380/kaa","description":"Kaa open-source middleware platform for building, managing, and integrating connected products with the Internet of Everything.","fork":true,"url":"https://api.github.com/repos/Kirill380/kaa","forks_url":"https://api.github.com/repos/Kirill380/kaa/forks","keys_url":"https://api.github.com/repos/Kirill380/kaa/keys{/key_id}","collaborators_url":"https://api.github.com/repos/Kirill380/kaa/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/Kirill380/kaa/teams","hooks_url":"https://api.github.com/repos/Kirill380/kaa/hooks","issue_events_url":"https://api.github.com/repos/Kirill380/kaa/issues/events{/number}","events_url":"https://api.github.com/repos/Kirill380/kaa/events","assignees_url":"https://api.github.com/repos/Kirill380/kaa/assignees{/user}","branches_url":"https://api.github.com/repos/Kirill380/kaa/branches{/branch}","tags_url":"https://api.github.com/repos/Kirill380/kaa/tags","blobs_url":"https://api.github.com/repos/Kirill380/kaa/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/Kirill380/kaa/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/Kirill380/kaa/git/refs{/sha}","trees_url":"https://api.github.com/repos/Kirill380/kaa/git/trees{/sha}","statuses_url":"https://api.github.com/repos/Kirill380/kaa/statuses/{sha}","languages_url":"https://api.github.com/repos/Kirill380/kaa/languages","stargazers_url":"https://api.github.com/repos/Kirill380/kaa/stargazers","contributors_url":"https://api.github.com/repos/Kirill380/kaa/contributors","subscribers_url":"https://api.github.com/repos/Kirill380/kaa/subscribers","subscription_url":"https://api.github.com/repos/Kirill380/kaa/subscription","commits_url":"https://api.github.com/repos/Kirill380/kaa/commits{/sha}","git_commits_url":"https://api.github.com/repos/Kirill380/kaa/git/commits{/sha}","comments_url":"https://api.github.com/repos/Kirill380/kaa/comments{/number}","issue_comment_url":"https://api.github.com/repos/Kirill380/kaa/issues/comments{/number}","contents_url":"https://api.github.com/repos/Kirill380/kaa/contents/{+path}","compare_url":"https://api.github.com/repos/Kirill380/kaa/compare/{base}...{head}","merges_url":"https://api.github.com/repos/Kirill380/kaa/merges","archive_url":"https://api.github.com/repos/Kirill380/kaa/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/Kirill380/kaa/downloads","issues_url":"https://api.github.com/repos/Kirill380/kaa/issues{/number}","pulls_url":"https://api.github.com/repos/Kirill380/kaa/pulls{/number}","milestones_url":"https://api.github.com/repos/Kirill380/kaa/milestones{/number}","notifications_url":"https://api.github.com/repos/Kirill380/kaa/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/Kirill380/kaa/labels{/name}","releases_url":"https://api.github.com/repos/Kirill380/kaa/releases{/id}","deployments_url":"https://api.github.com/repos/Kirill380/kaa/deployments","created_at":"2016-05-16T13:39:17Z","updated_at":"2016-05-16T13:39:27Z","pushed_at":"2016-06-30T11:31:34Z","git_url":"git://github.com/Kirill380/kaa.git","ssh_url":"git@github.com:Kirill380/kaa.git","clone_url":"https://github.com/Kirill380/kaa.git","svn_url":"https://github.com/Kirill380/kaa","homepage":"http://www.kaaproject.org","size":132151,"stargazers_count":0,"watchers_count":0,"language":"Java","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"kaaproject:develop","ref":"develop","sha":"11bc99383148ff9809eb9654eb610d3eea23019d","user":{"login":"kaaproject","id":6984613,"avatar_url":"https://avatars.githubusercontent.com/u/6984613?v=3","gravatar_id":"","url":"https://api.github.com/users/kaaproject","html_url":"https://github.com/kaaproject","followers_url":"https://api.github.com/users/kaaproject/followers","following_url":"https://api.github.com/users/kaaproject/following{/other_user}","gists_url":"https://api.github.com/users/kaaproject/gists{/gist_id}","starred_url":"https://api.github.com/users/kaaproject/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kaaproject/subscriptions","organizations_url":"https://api.github.com/users/kaaproject/orgs","repos_url":"https://api.github.com/users/kaaproject/repos","events_url":"https://api.github.com/users/kaaproject/events{/privacy}","received_events_url":"https://api.github.com/users/kaaproject/received_events","type":"Organization","site_admin":false},"repo":{"id":17839346,"name":"kaa","full_name":"kaaproject/kaa","owner":{"login":"kaaproject","id":6984613,"avatar_url":"https://avatars.githubusercontent.com/u/6984613?v=3","gravatar_id":"","url":"https://api.github.com/users/kaaproject","html_url":"https://github.com/kaaproject","followers_url":"https://api.github.com/users/kaaproject/followers","following_url":"https://api.github.com/users/kaaproject/following{/other_user}","gists_url":"https://api.github.com/users/kaaproject/gists{/gist_id}","starred_url":"https://api.github.com/users/kaaproject/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kaaproject/subscriptions","organizations_url":"https://api.github.com/users/kaaproject/orgs","repos_url":"https://api.github.com/users/kaaproject/repos","events_url":"https://api.github.com/users/kaaproject/events{/privacy}","received_events_url":"https://api.github.com/users/kaaproject/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/kaaproject/kaa","description":"Kaa open-source middleware platform for building, managing, and integrating connected products with the Internet of Everything.","fork":false,"url":"https://api.github.com/repos/kaaproject/kaa","forks_url":"https://api.github.com/repos/kaaproject/kaa/forks","keys_url":"https://api.github.com/repos/kaaproject/kaa/keys{/key_id}","collaborators_url":"https://api.github.com/repos/kaaproject/kaa/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/kaaproject/kaa/teams","hooks_url":"https://api.github.com/repos/kaaproject/kaa/hooks","issue_events_url":"https://api.github.com/repos/kaaproject/kaa/issues/events{/number}","events_url":"https://api.github.com/repos/kaaproject/kaa/events","assignees_url":"https://api.github.com/repos/kaaproject/kaa/assignees{/user}","branches_url":"https://api.github.com/repos/kaaproject/kaa/branches{/branch}","tags_url":"https://api.github.com/repos/kaaproject/kaa/tags","blobs_url":"https://api.github.com/repos/kaaproject/kaa/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/kaaproject/kaa/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/kaaproject/kaa/git/refs{/sha}","trees_url":"https://api.github.com/repos/kaaproject/kaa/git/trees{/sha}","statuses_url":"https://api.github.com/repos/kaaproject/kaa/statuses/{sha}","languages_url":"https://api.github.com/repos/kaaproject/kaa/languages","stargazers_url":"https://api.github.com/repos/kaaproject/kaa/stargazers","contributors_url":"https://api.github.com/repos/kaaproject/kaa/contributors","subscribers_url":"https://api.github.com/repos/kaaproject/kaa/subscribers","subscription_url":"https://api.github.com/repos/kaaproject/kaa/subscription","commits_url":"https://api.github.com/repos/kaaproject/kaa/commits{/sha}","git_commits_url":"https://api.github.com/repos/kaaproject/kaa/git/commits{/sha}","comments_url":"https://api.github.com/repos/kaaproject/kaa/comments{/number}","issue_comment_url":"https://api.github.com/repos/kaaproject/kaa/issues/comments{/number}","contents_url":"https://api.github.com/repos/kaaproject/kaa/contents/{+path}","compare_url":"https://api.github.com/repos/kaaproject/kaa/compare/{base}...{head}","merges_url":"https://api.github.com/repos/kaaproject/kaa/merges","archive_url":"https://api.github.com/repos/kaaproject/kaa/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/kaaproject/kaa/downloads","issues_url":"https://api.github.com/repos/kaaproject/kaa/issues{/number}","pulls_url":"https://api.github.com/repos/kaaproject/kaa/pulls{/number}","milestones_url":"https://api.github.com/repos/kaaproject/kaa/milestones{/number}","notifications_url":"https://api.github.com/repos/kaaproject/kaa/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/kaaproject/kaa/labels{/name}","releases_url":"https://api.github.com/repos/kaaproject/kaa/releases{/id}","deployments_url":"https://api.github.com/repos/kaaproject/kaa/deployments","created_at":"2014-03-17T18:48:31Z","updated_at":"2016-06-30T11:09:45Z","pushed_at":"2016-06-30T10:38:31Z","git_url":"git://github.com/kaaproject/kaa.git","ssh_url":"git@github.com:kaaproject/kaa.git","clone_url":"https://github.com/kaaproject/kaa.git","svn_url":"https://github.com/kaaproject/kaa","homepage":"http://www.kaaproject.org","size":145255,"stargazers_count":311,"watchers_count":311,"language":"Java","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":true,"forks_count":120,"mirror_url":null,"open_issues_count":24,"forks":120,"open_issues":24,"watchers":311,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/kaaproject/kaa/pulls/764"},"html":{"href":"https://github.com/kaaproject/kaa/pull/764"},"issue":{"href":"https://api.github.com/repos/kaaproject/kaa/issues/764"},"comments":{"href":"https://api.github.com/repos/kaaproject/kaa/issues/764/comments"},"review_comments":{"href":"https://api.github.com/repos/kaaproject/kaa/pulls/764/comments"},"review_comment":{"href":"https://api.github.com/repos/kaaproject/kaa/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/kaaproject/kaa/pulls/764/commits"},"statuses":{"href":"https://api.github.com/repos/kaaproject/kaa/statuses/73a8cd95a111b3ecf4635509bf2eb27366c70ece"}}}}
{"actor":{"display_login":"balldir"}}