{"action":"created","comment":{"url":"https://api.github.com/repos/openhab/openhab2-addons/pulls/comments/71499278","id":71499278,"diff_hunk":"@@ -0,0 +1,401 @@\n+/**\n+ * Copyright (c) 2014 openHAB UG (haftungsbeschraenkt) and others.\n+ * All rights reserved. This program and the accompanying materials\n+ * are made available under the terms of the Eclipse Public License v1.0\n+ * which accompanies this distribution, and is available at\n+ * http://www.eclipse.org/legal/epl-v10.html\n+ */\n+package org.openhab.binding.feed.test\n+\n+import static org.apache.commons.httpclient.HttpStatus.*\n+import static org.hamcrest.CoreMatchers.*\n+import static org.junit.Assert.*\n+import static org.junit.matchers.JUnitMatchers.*\n+\n+import javax.servlet.ServletException\n+import javax.servlet.ServletOutputStream\n+import javax.servlet.http.HttpServlet\n+import javax.servlet.http.HttpServletRequest\n+import javax.servlet.http.HttpServletResponse\n+\n+import org.apache.commons.httpclient.HttpStatus\n+import org.custommonkey.xmlunit.*\n+import org.eclipse.smarthome.config.core.Configuration\n+import org.eclipse.smarthome.core.items.ItemRegistry\n+import org.eclipse.smarthome.core.items.StateChangeListener\n+import org.eclipse.smarthome.core.library.items.StringItem\n+import org.eclipse.smarthome.core.library.types.StringType\n+import org.eclipse.smarthome.core.thing.Channel\n+import org.eclipse.smarthome.core.thing.ChannelUID\n+import org.eclipse.smarthome.core.thing.ManagedThingProvider\n+import org.eclipse.smarthome.core.thing.Thing\n+import org.eclipse.smarthome.core.thing.ThingProvider\n+import org.eclipse.smarthome.core.thing.ThingRegistry\n+import org.eclipse.smarthome.core.thing.ThingStatus\n+import org.eclipse.smarthome.core.thing.ThingStatusDetail\n+import org.eclipse.smarthome.core.thing.ThingUID\n+import org.eclipse.smarthome.core.thing.binding.ThingHandler\n+import org.eclipse.smarthome.core.thing.binding.builder.ThingBuilder\n+import org.eclipse.smarthome.core.thing.link.ItemChannelLink\n+import org.eclipse.smarthome.core.thing.link.ManagedItemChannelLinkProvider\n+import org.eclipse.smarthome.core.types.RefreshType\n+import org.eclipse.smarthome.test.OSGiTest\n+import org.eclipse.smarthome.test.storage.VolatileStorageService\n+import org.junit.After\n+import org.junit.Before\n+import org.junit.Test\n+import org.junit.experimental.categories.Category\n+import org.openhab.binding.feed.FeedBindingConstants\n+import org.openhab.binding.feed.handler.FeedHandler\n+import org.osgi.service.http.HttpService\n+/**\n+ * Tests for {@link FeedHandler}\n+ *\n+ * @author Svilen Valkanov\n+ */\n+\n+public class FeedHandlerTest extends OSGiTest {\n+\n+    //Servlet URL configuration\n+    def MOCK_SERVLET_PROTOCOL = 'http'\n+    def MOCK_SERVLET_HOSTNAME = 'localhost'\n+    def MOCK_SERVLET_PORT = 9090\n+    def MOCK_SERVLET_PATH = '/test/feed';\n+\n+    //Files used for the test as input. They are located in /src/test/resources directory\n+    /**\n+     * The default mock content in the test is RSS 2.0 format, as this is the most popular format\n+     */\n+    def DEFAULT_MOCK_CONTENT = 'rss_2.0.xml'\n+\n+    /**\n+     * One new entry is added to {@link #DEFAULT_MOCK_CONTENT}\n+     */\n+    def MOCK_CONTENT_CHANGED = 'rss_2.0_changed.xml'\n+\n+    def ITEM_NAME = 'testItem'\n+    def THING_NAME = 'testFeedThing'\n+\n+\n+    int DEFAULT_MAX_WAIT_TIME = 6000\n+\n+    /**\n+     * Default auto refresh interval for the test is 1 Minute.\n+     */\n+    int DEFAULT_TEST_AUTOREFRESH_TIME = 1\n+\n+    /**\n+     * It is updated from mocked {@link StateChangeListener#stateUpdated() }\n+     */\n+    def currentItemState = null\n+\n+    //Required services for the test\n+    private ManagedThingProvider managedThingProvider\n+    private VolatileStorageService volatileStorageService\n+    private ThingRegistry thingRegistry\n+\n+    private FeedServiceMock servlet\n+    private Thing feedThing;\n+    private FeedHandler feedHandler = null;\n+    private ChannelUID channelUID = null\n+\n+    /**\n+     * This class is used as a mock for HTTP web server, serving XML feed content.\n+     */\n+    class FeedServiceMock extends HttpServlet {\n+        def feedContent;\n+        def httpStatus;\n+\n+        public FeedServiceMock(def feedContentFile) {\n+            super()\n+            setFeedContent(feedContentFile)\n+            //By default the servlet returns HTTP Status code 200 OK\n+            this.httpStatus = HttpStatus.SC_OK\n+        }\n+\n+        @Override\n+        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{\n+            ServletOutputStream outputStream = response.getOutputStream()\n+            outputStream.println(feedContent)\n+            //Recommended RSS MIME type - http://www.rssboard.org/rss-mime-type-application.txt\n+            //Atom MIME type is  - application/atom+xml\n+            //Other MIME types - text/plan, text/xml, text/html are tested and accepted as well\n+            response.setContentType(\"application/rss+xml\")\n+            response.setStatus(httpStatus)\n+        }\n+\n+        public void setFeedContent(String feedContentFile) {\n+            def path = \"input/${feedContentFile}\"\n+            feedContent = getClass().getClassLoader().getResourceAsStream(path).getText();\n+        }\n+\n+    }\n+\n+    private void registerFeedTestServlet (){\n+        HttpService httpService = getService(HttpService)\n+        assertThat httpService,is(notNullValue())\n+        servlet = new FeedServiceMock(DEFAULT_MOCK_CONTENT);\n+        httpService.registerServlet(MOCK_SERVLET_PATH, servlet, null, null)\n+    }\n+\n+    private void unregisterFeedTestServlet(){\n+        HttpService httpService = getService(HttpService)\n+        assertThat httpService,is(notNullValue())\n+        httpService.unregister(MOCK_SERVLET_PATH)\n+        servlet=null\n+    }\n+\n+    @Before\n+    public void setUp() {\n+        volatileStorageService = new VolatileStorageService()\n+        registerService(volatileStorageService)\n+\n+        managedThingProvider = getService(ThingProvider, ManagedThingProvider)\n+        assertThat managedThingProvider, is(notNullValue())\n+\n+        thingRegistry = getService(ThingRegistry)\n+        assertThat thingRegistry, is(notNullValue())\n+\n+        registerFeedTestServlet();\n+    }\n+\n+    private String generateURLString(String protocol,String hostname,int port,String path) {\n+        def String mockServletURL = \"$protocol://$hostname:$port$path\";\n+        return mockServletURL\n+    }\n+\n+    private void initializeDefaultFeedHandler (){\n+        def mockServletURL = generateURLString(MOCK_SERVLET_PROTOCOL,MOCK_SERVLET_HOSTNAME,MOCK_SERVLET_PORT,MOCK_SERVLET_PATH)\n+        //one minute update time is used for the tests\n+        def defaultTestRefreshInterval = new BigDecimal(DEFAULT_TEST_AUTOREFRESH_TIME)\n+        initializeFeedHandler(mockServletURL,defaultTestRefreshInterval)\n+    }\n+\n+    private void initializeFeedHandler (String URL) {\n+        initializeFeedHandler(URL,null)\n+    }\n+\n+    private void initializeFeedHandler(String URL,BigDecimal refreshTime) {\n+        //set up configuration\n+        Configuration configuration = new Configuration()\n+        configuration.put((FeedBindingConstants.URL), URL)\n+        configuration.put((FeedBindingConstants.REFRESH_TIME),refreshTime)\n+\n+        //create Feed Thing\n+        ThingUID feedUID = new ThingUID(FeedBindingConstants.FEED_THING_TYPE_UID,THING_NAME)\n+        channelUID = new ChannelUID(feedUID,FeedBindingConstants.CHANNEL_LATEST_ENTRY)\n+        Channel channel = new Channel(channelUID,\"String\")\n+        feedThing = ThingBuilder.create(FeedBindingConstants.FEED_THING_TYPE_UID, feedUID).withConfiguration(configuration).withChannel(channel).build()\n+\n+        managedThingProvider.add(feedThing)\n+\n+        //wait for FeedHandler to be registered\n+        waitForAssert({\n+            feedHandler = getService(ThingHandler, FeedHandler)\n+            assertThat \"FeedHandler is not registered\",feedHandler, is(notNullValue())\n+        },  DEFAULT_MAX_WAIT_TIME)\n+\n+        //This will ensure that the configuration is read before the channelLinked() method in FeedHandler is called !\n+        waitForAssert({\n+            feedThing.getStatus() == ThingStatus.ONLINE;\n+        })\n+        initializeItem(channelUID)\n+    }\n+\n+    private void initializeItem (ChannelUID channelUID){\n+        //Create new item\n+        def ItemRegistry itemRegistry = getService(ItemRegistry)\n+        assertThat itemRegistry, is(notNullValue())\n+\n+        StringItem newItem = new StringItem(ITEM_NAME)\n+\n+        // Add item state change listener\n+        def updateListener = [\n+            stateUpdated: { item, state ->\n+                currentItemState = state\n+            },\n+            stateChanged: { item, oldState, state ->\n+            }\n+        ] as StateChangeListener\n+\n+        newItem.addStateChangeListener(updateListener)\n+        itemRegistry.add(newItem)\n+\n+        //Add item channel link\n+        def ManagedItemChannelLinkProvider itemChannelLinkProvider = getService(ManagedItemChannelLinkProvider)\n+        assertThat itemChannelLinkProvider,is(notNullValue())\n+        itemChannelLinkProvider.add(new ItemChannelLink(ITEM_NAME,channelUID))\n+    }\n+\n+    private void testIfItemStateIsUpdated (boolean commandReceived, boolean contentChanged) {\n+        initializeDefaultFeedHandler()\n+\n+        waitForAssert({\n+            assertThat \"Feed Thing can not be initialized\",feedThing.getStatus(),is(equalTo(ThingStatus.ONLINE))\n+            assertThat \"Item's state is not updated on initialize\", currentItemState, is(notNullValue())\n+        },  DEFAULT_MAX_WAIT_TIME)\n+\n+        assertThat currentItemState,is(StringType)\n+        String firstItemState = currentItemState;\n+\n+        if(contentChanged) {\n+            //The content on the mocked server should be changed\n+            servlet.setFeedContent(MOCK_CONTENT_CHANGED)\n+        }\n+\n+        if(commandReceived){\n+            feedThing.handler.handleCommand(channelUID,RefreshType.REFRESH)\n+        } else {\n+            //The auto refresh task will handle the update after the default wait time\n+            sleep(DEFAULT_TEST_AUTOREFRESH_TIME*60*1000)\n+        }\n+\n+        waitForAssert({\n+            assertThat \"Error occured while trying to connect to server. Content is not dowloaded!\",\n+                    feedThing.getStatus(),is(equalTo(ThingStatus.ONLINE))\n+        }, DEFAULT_MAX_WAIT_TIME)\n+\n+        waitForAssert({\n+            if(contentChanged) {\n+                assertThat \"Content is not updated!\",currentItemState,not(equalTo(firstItemState))\n+            } else {\n+                assertThat currentItemState,is(equalTo(firstItemState))\n+            }\n+        },DEFAULT_MAX_WAIT_TIME)\n+    }\n+\n+    @Test\n+    public void 'assert that invalid configuration falls back to default values'() {\n+        def String mockServletURL = generateURLString(MOCK_SERVLET_PROTOCOL,MOCK_SERVLET_HOSTNAME,MOCK_SERVLET_PORT,MOCK_SERVLET_PATH)\n+        def defaultTestRefreshInterval = new BigDecimal(-10)\n+        initializeFeedHandler(mockServletURL,defaultTestRefreshInterval)\n+    }\n+\n+    @Test\n+    public void 'assert that item\\'s state is updated on refresh command if content changed' () {\n+        boolean commandRecevied = true;\n+        boolean contentChanged = true;\n+        testIfItemStateIsUpdated(commandRecevied,contentChanged);\n+    }\n+\n+    @Test\n+    public void 'assert that item\\'s state is not updated on refresh command if content is not changed' () {\n+        boolean commandRecevied = true;\n+        boolean contentChanged = false;\n+        testIfItemStateIsUpdated(commandRecevied,contentChanged);\n+    }\n+\n+    @Category(SlowTests.class)\n+    @Test\n+    public void 'assert that item\\'s state is not updated on auto refresh if content is not changed' () {\n+        boolean commandRecevied = false;\n+        boolean contentChanged = false;\n+        testIfItemStateIsUpdated(commandRecevied,contentChanged);\n+    }\n+\n+    @Category(SlowTests.class)\n+    @Test\n+    public void 'assert that item\\'s state is updated on auto refresh if content changed' () {\n+        boolean commandRecevied = false;","path":"addons/binding/org.openhab.binding.feed.test/src/test/groovy/org/openhab/binding/feed/test/FeedHandlerTest.groovy","position":299,"original_position":299,"commit_id":"d0a3ac295cd217bbae5ecfef752ab912b44be2f1","original_commit_id":"d0a3ac295cd217bbae5ecfef752ab912b44be2f1","user":{"login":"kaikreuzer","id":3244965,"avatar_url":"https://avatars.githubusercontent.com/u/3244965?v=3","gravatar_id":"","url":"https://api.github.com/users/kaikreuzer","html_url":"https://github.com/kaikreuzer","followers_url":"https://api.github.com/users/kaikreuzer/followers","following_url":"https://api.github.com/users/kaikreuzer/following{/other_user}","gists_url":"https://api.github.com/users/kaikreuzer/gists{/gist_id}","starred_url":"https://api.github.com/users/kaikreuzer/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kaikreuzer/subscriptions","organizations_url":"https://api.github.com/users/kaikreuzer/orgs","repos_url":"https://api.github.com/users/kaikreuzer/repos","events_url":"https://api.github.com/users/kaikreuzer/events{/privacy}","received_events_url":"https://api.github.com/users/kaikreuzer/received_events","type":"User","site_admin":false},"body":"dito","created_at":"2016-07-20T10:16:07Z","updated_at":"2016-07-20T10:16:07Z","html_url":"https://github.com/openhab/openhab2-addons/pull/762#discussion_r71499278","pull_request_url":"https://api.github.com/repos/openhab/openhab2-addons/pulls/762","_links":{"self":{"href":"https://api.github.com/repos/openhab/openhab2-addons/pulls/comments/71499278"},"html":{"href":"https://github.com/openhab/openhab2-addons/pull/762#discussion_r71499278"},"pull_request":{"href":"https://api.github.com/repos/openhab/openhab2-addons/pulls/762"}}},"pull_request":{"url":"https://api.github.com/repos/openhab/openhab2-addons/pulls/762","id":64177955,"html_url":"https://github.com/openhab/openhab2-addons/pull/762","diff_url":"https://github.com/openhab/openhab2-addons/pull/762.diff","patch_url":"https://github.com/openhab/openhab2-addons/pull/762.patch","issue_url":"https://api.github.com/repos/openhab/openhab2-addons/issues/762","number":762,"state":"open","locked":false,"title":"#724 Feed binding","user":{"login":"svilenvul","id":7120104,"avatar_url":"https://avatars.githubusercontent.com/u/7120104?v=3","gravatar_id":"","url":"https://api.github.com/users/svilenvul","html_url":"https://github.com/svilenvul","followers_url":"https://api.github.com/users/svilenvul/followers","following_url":"https://api.github.com/users/svilenvul/following{/other_user}","gists_url":"https://api.github.com/users/svilenvul/gists{/gist_id}","starred_url":"https://api.github.com/users/svilenvul/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/svilenvul/subscriptions","organizations_url":"https://api.github.com/users/svilenvul/orgs","repos_url":"https://api.github.com/users/svilenvul/repos","events_url":"https://api.github.com/users/svilenvul/events{/privacy}","received_events_url":"https://api.github.com/users/svilenvul/received_events","type":"User","site_admin":false},"body":"Pull request to #724","created_at":"2016-03-25T16:12:35Z","updated_at":"2016-07-20T10:16:07Z","closed_at":null,"merged_at":null,"merge_commit_sha":"8e96b9e4e757a9ccc7d62769538cebe1dbb09d3c","assignee":{"login":"kaikreuzer","id":3244965,"avatar_url":"https://avatars.githubusercontent.com/u/3244965?v=3","gravatar_id":"","url":"https://api.github.com/users/kaikreuzer","html_url":"https://github.com/kaikreuzer","followers_url":"https://api.github.com/users/kaikreuzer/followers","following_url":"https://api.github.com/users/kaikreuzer/following{/other_user}","gists_url":"https://api.github.com/users/kaikreuzer/gists{/gist_id}","starred_url":"https://api.github.com/users/kaikreuzer/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kaikreuzer/subscriptions","organizations_url":"https://api.github.com/users/kaikreuzer/orgs","repos_url":"https://api.github.com/users/kaikreuzer/repos","events_url":"https://api.github.com/users/kaikreuzer/events{/privacy}","received_events_url":"https://api.github.com/users/kaikreuzer/received_events","type":"User","site_admin":false},"assignees":[{"login":"kaikreuzer","id":3244965,"avatar_url":"https://avatars.githubusercontent.com/u/3244965?v=3","gravatar_id":"","url":"https://api.github.com/users/kaikreuzer","html_url":"https://github.com/kaikreuzer","followers_url":"https://api.github.com/users/kaikreuzer/followers","following_url":"https://api.github.com/users/kaikreuzer/following{/other_user}","gists_url":"https://api.github.com/users/kaikreuzer/gists{/gist_id}","starred_url":"https://api.github.com/users/kaikreuzer/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kaikreuzer/subscriptions","organizations_url":"https://api.github.com/users/kaikreuzer/orgs","repos_url":"https://api.github.com/users/kaikreuzer/repos","events_url":"https://api.github.com/users/kaikreuzer/events{/privacy}","received_events_url":"https://api.github.com/users/kaikreuzer/received_events","type":"User","site_admin":false}],"milestone":null,"commits_url":"https://api.github.com/repos/openhab/openhab2-addons/pulls/762/commits","review_comments_url":"https://api.github.com/repos/openhab/openhab2-addons/pulls/762/comments","review_comment_url":"https://api.github.com/repos/openhab/openhab2-addons/pulls/comments{/number}","comments_url":"https://api.github.com/repos/openhab/openhab2-addons/issues/762/comments","statuses_url":"https://api.github.com/repos/openhab/openhab2-addons/statuses/d0a3ac295cd217bbae5ecfef752ab912b44be2f1","head":{"label":"svilenvul:724-feed-binding","ref":"724-feed-binding","sha":"d0a3ac295cd217bbae5ecfef752ab912b44be2f1","user":{"login":"svilenvul","id":7120104,"avatar_url":"https://avatars.githubusercontent.com/u/7120104?v=3","gravatar_id":"","url":"https://api.github.com/users/svilenvul","html_url":"https://github.com/svilenvul","followers_url":"https://api.github.com/users/svilenvul/followers","following_url":"https://api.github.com/users/svilenvul/following{/other_user}","gists_url":"https://api.github.com/users/svilenvul/gists{/gist_id}","starred_url":"https://api.github.com/users/svilenvul/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/svilenvul/subscriptions","organizations_url":"https://api.github.com/users/svilenvul/orgs","repos_url":"https://api.github.com/users/svilenvul/repos","events_url":"https://api.github.com/users/svilenvul/events{/privacy}","received_events_url":"https://api.github.com/users/svilenvul/received_events","type":"User","site_admin":false},"repo":{"id":54727006,"name":"openhab2-addons","full_name":"svilenvul/openhab2-addons","owner":{"login":"svilenvul","id":7120104,"avatar_url":"https://avatars.githubusercontent.com/u/7120104?v=3","gravatar_id":"","url":"https://api.github.com/users/svilenvul","html_url":"https://github.com/svilenvul","followers_url":"https://api.github.com/users/svilenvul/followers","following_url":"https://api.github.com/users/svilenvul/following{/other_user}","gists_url":"https://api.github.com/users/svilenvul/gists{/gist_id}","starred_url":"https://api.github.com/users/svilenvul/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/svilenvul/subscriptions","organizations_url":"https://api.github.com/users/svilenvul/orgs","repos_url":"https://api.github.com/users/svilenvul/repos","events_url":"https://api.github.com/users/svilenvul/events{/privacy}","received_events_url":"https://api.github.com/users/svilenvul/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/svilenvul/openhab2-addons","description":"The next-generation open Home Automation Bus (openHAB)","fork":true,"url":"https://api.github.com/repos/svilenvul/openhab2-addons","forks_url":"https://api.github.com/repos/svilenvul/openhab2-addons/forks","keys_url":"https://api.github.com/repos/svilenvul/openhab2-addons/keys{/key_id}","collaborators_url":"https://api.github.com/repos/svilenvul/openhab2-addons/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/svilenvul/openhab2-addons/teams","hooks_url":"https://api.github.com/repos/svilenvul/openhab2-addons/hooks","issue_events_url":"https://api.github.com/repos/svilenvul/openhab2-addons/issues/events{/number}","events_url":"https://api.github.com/repos/svilenvul/openhab2-addons/events","assignees_url":"https://api.github.com/repos/svilenvul/openhab2-addons/assignees{/user}","branches_url":"https://api.github.com/repos/svilenvul/openhab2-addons/branches{/branch}","tags_url":"https://api.github.com/repos/svilenvul/openhab2-addons/tags","blobs_url":"https://api.github.com/repos/svilenvul/openhab2-addons/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/svilenvul/openhab2-addons/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/svilenvul/openhab2-addons/git/refs{/sha}","trees_url":"https://api.github.com/repos/svilenvul/openhab2-addons/git/trees{/sha}","statuses_url":"https://api.github.com/repos/svilenvul/openhab2-addons/statuses/{sha}","languages_url":"https://api.github.com/repos/svilenvul/openhab2-addons/languages","stargazers_url":"https://api.github.com/repos/svilenvul/openhab2-addons/stargazers","contributors_url":"https://api.github.com/repos/svilenvul/openhab2-addons/contributors","subscribers_url":"https://api.github.com/repos/svilenvul/openhab2-addons/subscribers","subscription_url":"https://api.github.com/repos/svilenvul/openhab2-addons/subscription","commits_url":"https://api.github.com/repos/svilenvul/openhab2-addons/commits{/sha}","git_commits_url":"https://api.github.com/repos/svilenvul/openhab2-addons/git/commits{/sha}","comments_url":"https://api.github.com/repos/svilenvul/openhab2-addons/comments{/number}","issue_comment_url":"https://api.github.com/repos/svilenvul/openhab2-addons/issues/comments{/number}","contents_url":"https://api.github.com/repos/svilenvul/openhab2-addons/contents/{+path}","compare_url":"https://api.github.com/repos/svilenvul/openhab2-addons/compare/{base}...{head}","merges_url":"https://api.github.com/repos/svilenvul/openhab2-addons/merges","archive_url":"https://api.github.com/repos/svilenvul/openhab2-addons/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/svilenvul/openhab2-addons/downloads","issues_url":"https://api.github.com/repos/svilenvul/openhab2-addons/issues{/number}","pulls_url":"https://api.github.com/repos/svilenvul/openhab2-addons/pulls{/number}","milestones_url":"https://api.github.com/repos/svilenvul/openhab2-addons/milestones{/number}","notifications_url":"https://api.github.com/repos/svilenvul/openhab2-addons/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/svilenvul/openhab2-addons/labels{/name}","releases_url":"https://api.github.com/repos/svilenvul/openhab2-addons/releases{/id}","deployments_url":"https://api.github.com/repos/svilenvul/openhab2-addons/deployments","created_at":"2016-03-25T15:16:00Z","updated_at":"2016-03-25T15:16:04Z","pushed_at":"2016-06-28T12:10:35Z","git_url":"git://github.com/svilenvul/openhab2-addons.git","ssh_url":"git@github.com:svilenvul/openhab2-addons.git","clone_url":"https://github.com/svilenvul/openhab2-addons.git","svn_url":"https://github.com/svilenvul/openhab2-addons","homepage":null,"size":45999,"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":"openhab:master","ref":"master","sha":"b24ad9c4837d4f9c9392c42d3eb44c5d313a09b8","user":{"login":"openhab","id":1007353,"avatar_url":"https://avatars.githubusercontent.com/u/1007353?v=3","gravatar_id":"","url":"https://api.github.com/users/openhab","html_url":"https://github.com/openhab","followers_url":"https://api.github.com/users/openhab/followers","following_url":"https://api.github.com/users/openhab/following{/other_user}","gists_url":"https://api.github.com/users/openhab/gists{/gist_id}","starred_url":"https://api.github.com/users/openhab/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/openhab/subscriptions","organizations_url":"https://api.github.com/users/openhab/orgs","repos_url":"https://api.github.com/users/openhab/repos","events_url":"https://api.github.com/users/openhab/events{/privacy}","received_events_url":"https://api.github.com/users/openhab/received_events","type":"Organization","site_admin":false},"repo":{"id":19753195,"name":"openhab2-addons","full_name":"openhab/openhab2-addons","owner":{"login":"openhab","id":1007353,"avatar_url":"https://avatars.githubusercontent.com/u/1007353?v=3","gravatar_id":"","url":"https://api.github.com/users/openhab","html_url":"https://github.com/openhab","followers_url":"https://api.github.com/users/openhab/followers","following_url":"https://api.github.com/users/openhab/following{/other_user}","gists_url":"https://api.github.com/users/openhab/gists{/gist_id}","starred_url":"https://api.github.com/users/openhab/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/openhab/subscriptions","organizations_url":"https://api.github.com/users/openhab/orgs","repos_url":"https://api.github.com/users/openhab/repos","events_url":"https://api.github.com/users/openhab/events{/privacy}","received_events_url":"https://api.github.com/users/openhab/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/openhab/openhab2-addons","description":"The next-generation open Home Automation Bus (openHAB)","fork":false,"url":"https://api.github.com/repos/openhab/openhab2-addons","forks_url":"https://api.github.com/repos/openhab/openhab2-addons/forks","keys_url":"https://api.github.com/repos/openhab/openhab2-addons/keys{/key_id}","collaborators_url":"https://api.github.com/repos/openhab/openhab2-addons/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/openhab/openhab2-addons/teams","hooks_url":"https://api.github.com/repos/openhab/openhab2-addons/hooks","issue_events_url":"https://api.github.com/repos/openhab/openhab2-addons/issues/events{/number}","events_url":"https://api.github.com/repos/openhab/openhab2-addons/events","assignees_url":"https://api.github.com/repos/openhab/openhab2-addons/assignees{/user}","branches_url":"https://api.github.com/repos/openhab/openhab2-addons/branches{/branch}","tags_url":"https://api.github.com/repos/openhab/openhab2-addons/tags","blobs_url":"https://api.github.com/repos/openhab/openhab2-addons/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/openhab/openhab2-addons/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/openhab/openhab2-addons/git/refs{/sha}","trees_url":"https://api.github.com/repos/openhab/openhab2-addons/git/trees{/sha}","statuses_url":"https://api.github.com/repos/openhab/openhab2-addons/statuses/{sha}","languages_url":"https://api.github.com/repos/openhab/openhab2-addons/languages","stargazers_url":"https://api.github.com/repos/openhab/openhab2-addons/stargazers","contributors_url":"https://api.github.com/repos/openhab/openhab2-addons/contributors","subscribers_url":"https://api.github.com/repos/openhab/openhab2-addons/subscribers","subscription_url":"https://api.github.com/repos/openhab/openhab2-addons/subscription","commits_url":"https://api.github.com/repos/openhab/openhab2-addons/commits{/sha}","git_commits_url":"https://api.github.com/repos/openhab/openhab2-addons/git/commits{/sha}","comments_url":"https://api.github.com/repos/openhab/openhab2-addons/comments{/number}","issue_comment_url":"https://api.github.com/repos/openhab/openhab2-addons/issues/comments{/number}","contents_url":"https://api.github.com/repos/openhab/openhab2-addons/contents/{+path}","compare_url":"https://api.github.com/repos/openhab/openhab2-addons/compare/{base}...{head}","merges_url":"https://api.github.com/repos/openhab/openhab2-addons/merges","archive_url":"https://api.github.com/repos/openhab/openhab2-addons/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/openhab/openhab2-addons/downloads","issues_url":"https://api.github.com/repos/openhab/openhab2-addons/issues{/number}","pulls_url":"https://api.github.com/repos/openhab/openhab2-addons/pulls{/number}","milestones_url":"https://api.github.com/repos/openhab/openhab2-addons/milestones{/number}","notifications_url":"https://api.github.com/repos/openhab/openhab2-addons/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/openhab/openhab2-addons/labels{/name}","releases_url":"https://api.github.com/repos/openhab/openhab2-addons/releases{/id}","deployments_url":"https://api.github.com/repos/openhab/openhab2-addons/deployments","created_at":"2014-05-13T19:41:58Z","updated_at":"2016-07-13T18:25:50Z","pushed_at":"2016-07-19T21:41:05Z","git_url":"git://github.com/openhab/openhab2-addons.git","ssh_url":"git@github.com:openhab/openhab2-addons.git","clone_url":"https://github.com/openhab/openhab2-addons.git","svn_url":"https://github.com/openhab/openhab2-addons","homepage":null,"size":175912,"stargazers_count":393,"watchers_count":393,"language":"Java","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":593,"mirror_url":null,"open_issues_count":116,"forks":593,"open_issues":116,"watchers":393,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/openhab/openhab2-addons/pulls/762"},"html":{"href":"https://github.com/openhab/openhab2-addons/pull/762"},"issue":{"href":"https://api.github.com/repos/openhab/openhab2-addons/issues/762"},"comments":{"href":"https://api.github.com/repos/openhab/openhab2-addons/issues/762/comments"},"review_comments":{"href":"https://api.github.com/repos/openhab/openhab2-addons/pulls/762/comments"},"review_comment":{"href":"https://api.github.com/repos/openhab/openhab2-addons/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/openhab/openhab2-addons/pulls/762/commits"},"statuses":{"href":"https://api.github.com/repos/openhab/openhab2-addons/statuses/d0a3ac295cd217bbae5ecfef752ab912b44be2f1"}}}}
{"actor":{"display_login":"kaikreuzer"}}