{"action":"created","comment":{"url":"https://api.github.com/repos/openhab/openhab/pulls/comments/46449878","id":46449878,"diff_hunk":"@@ -0,0 +1,367 @@\n+/**\n+ * Copyright (c) 2010-2015, openHAB.org and others.\n+ *\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.smarthomatic.internal;\n+\n+import java.io.IOException;\n+import java.io.InputStream;\n+import java.net.URL;\n+import java.util.Dictionary;\n+import java.util.Enumeration;\n+import java.util.StringTokenizer;\n+import java.util.regex.Matcher;\n+import java.util.regex.Pattern;\n+\n+import javax.xml.bind.JAXBContext;\n+import javax.xml.bind.JAXBException;\n+import javax.xml.bind.Unmarshaller;\n+\n+import org.apache.commons.lang.StringUtils;\n+import org.openhab.binding.smarthomatic.SmarthomaticBindingProvider;\n+import org.openhab.binding.smarthomatic.internal.SHCMessage.SHCData;\n+import org.openhab.binding.smarthomatic.internal.SHCMessage.SHCHeader;\n+import org.openhab.binding.smarthomatic.internal.packetData.Packet;\n+import org.openhab.core.binding.AbstractActiveBinding;\n+import org.openhab.core.items.Item;\n+import org.openhab.core.library.types.DecimalType;\n+import org.openhab.core.transform.TransformationException;\n+import org.openhab.core.transform.TransformationHelper;\n+import org.openhab.core.transform.TransformationService;\n+import org.openhab.core.types.Command;\n+import org.openhab.core.types.State;\n+import org.openhab.core.types.Type;\n+import org.osgi.framework.Bundle;\n+import org.osgi.service.cm.ConfigurationException;\n+import org.osgi.service.cm.ManagedService;\n+import org.slf4j.Logger;\n+import org.slf4j.LoggerFactory;\n+\n+/**\n+ * Implement this class if you are going create an actively polling service like\n+ * querying a Website/Device.\n+ * \n+ * @author arohde\n+ * @author mcjobo\n+ * @since 1.8.0\n+ */\n+public class SmarthomaticBinding extends AbstractActiveBinding<SmarthomaticBindingProvider>\n+\t\timplements ManagedService, SerialEventWorker {\n+\n+\tprivate static final Logger logger = LoggerFactory.getLogger(SmarthomaticBinding.class);\n+\t/**\n+\t * RegEx to extract a parse a function String <code>'(.*?)\\((.*)\\)'</code>\n+\t */\n+\tprivate static final Pattern EXTRACT_FUNCTION_PATTERN = Pattern.compile(\"(.*?)\\\\((.*)\\\\)\");\n+\tprivate BaseStation baseStation;\n+\tprivate String serialPortname;\n+\tprivate int serialBaudrate;\n+\tprivate Packet packet;\n+\n+\t/**\n+\t * the refresh interval which is used to poll values from the Smarthomatic\n+\t * server (optional, defaults to 60000ms)\n+\t * \n+\t * @since 1.8.0\n+\t */\n+\tprivate long refreshInterval = 60000;\n+\n+\tpublic SmarthomaticBinding() {\n+\t}\n+\n+\t/**\n+\t * activate binding\n+\t * \n+\t * @since 1.8.0\n+\t */\n+\tpublic void activate() {\n+\t\t// log activate of binding\n+\t\tif (baseStation != null) {\n+\t\t\tlogger.info(\"Smarthomatic Binding activated. BaseStation=\" + baseStation.toString());\n+\t\t}\n+\n+\t\tBundle bundle = SmarthomaticActivator.getContext().getBundle();\n+\t\tURL fileURL = bundle.getEntry(\"xml/packet_layout.xml\");\n+\t\tPacket packet = null;\n+\t\ttry {\n+\t\t\tInputStream inputStream = fileURL.openConnection().getInputStream();\n+\t\t\tJAXBContext jaxbContext = JAXBContext.newInstance(Packet.class);\n+\n+\t\t\tUnmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();\n+\t\t\tpacket = (Packet) jaxbUnmarshaller.unmarshal(inputStream);\n+\t\t} catch (IOException e1) {\n+\t\t\te1.printStackTrace();\n+\t\t} catch (JAXBException e) {\n+\t\t\te.printStackTrace();\n+\t\t}\n+\t\tthis.packet = packet;\n+\t}\n+\n+\t/**\n+\t * deactivate binding\n+\t * \n+\t * @since 1.8.0\n+\t */\n+\tpublic void deactivate() {\n+\t\t// deallocate resources here that are no longer needed and\n+\t\t// should be reset when activating this binding again\n+\t}\n+\n+\t/**\n+\t * @{inheritDoc\n+\t * \n+\t * @since 1.8.0\n+\t */\n+\t@Override\n+\tprotected long getRefreshInterval() {\n+\t\treturn refreshInterval;\n+\t}\n+\n+\t/**\n+\t * @{inheritDoc\n+\t * \n+\t * @since 1.8.0\n+\t */\n+\t@Override\n+\tprotected String getName() {\n+\t\treturn \"Smarthomatic Refresh Service\";\n+\t}\n+\n+\t/**\n+\t * @{inheritDoc\n+\t * \n+\t * @since 1.8.0\n+\t */\n+\t@Override\n+\tprotected void execute() {\n+\t\t// the frequently executed code (polling) goes here ...\n+\t\t// logger.debug(\"execute() method is called!\");\n+\t}\n+\n+\t/**\n+\t * @{inheritDoc\n+\t * \n+\t * @since 1.8.0\n+\t */\n+\t@Override\n+\tprotected void internalReceiveCommand(String itemName, Command command) {\n+\t\t// the code being executed when a command was sent on the openHAB\n+\t\t// event bus goes here. This method is only called if one of the\n+\t\t// BindingProviders provide a binding for the given 'itemName'.\n+\n+\t\tfor (SmarthomaticBindingProvider provider : this.providers) {\n+\t\t\tif (provider.providesBindingFor(itemName)) {\n+\t\t\t\tif (baseStation != null) {\n+\t\t\t\t\tbaseStation.sendCommand(provider.getDeviceId(itemName), provider.getMessageGroupId(itemName),\n+\t\t\t\t\t\t\tprovider.getMessageId(itemName), 0, command);\n+\t\t\t\t\t// provider.getType(itemName),\n+\t\t\t\t\t// provider.getToggleTime(itemName), command);\n+\t\t\t\t}\n+\t\t\t}\n+\t\t}\n+\n+\t\tlogger.debug(\"internalReceiveCommand() is called! {},{}\", new String[] { itemName, command.toString() });\n+\t}\n+\n+\t/**\n+\t * @{inheritDoc\n+\t * \n+\t * @since 1.8.0\n+\t */\n+\t@Override\n+\tprotected void internalReceiveUpdate(String itemName, State newState) {\n+\t\t// the code being executed when a state was sent on the openHAB\n+\t\t// event bus goes here. This method is only called if one of the\n+\t\t// BindingProviders provide a binding for the given 'itemName'.\n+\t\tlogger.debug(\"internalReceiveUpdate() is called!{},{}\", new String[] { itemName, newState.toString() });\n+\n+\t}\n+\n+\t/**\n+\t * @{inheritDoc\n+\t * \n+\t * @since 1.8.0\n+\t */\n+\t@Override\n+\tpublic void updated(Dictionary<String, ?> config) throws ConfigurationException {\n+\t\tif (config != null) {\n+\n+\t\t\t// to override the default refresh interval one has to add a\n+\t\t\t// parameter to openhab.cfg like\n+\t\t\t// <bindingName>:refresh=<intervalInMs>\n+\t\t\tString refreshIntervalString = (String) config.get(\"refresh\");\n+\t\t\tif (StringUtils.isNotBlank(refreshIntervalString)) {\n+\t\t\t\trefreshInterval = Long.parseLong(refreshIntervalString);\n+\t\t\t}\n+\n+\t\t\tboolean changed = false;\n+\n+\t\t\tif (serialPortname != (String) config.get(\"serialPort\")) {\n+\t\t\t\tserialPortname = (String) config.get(\"serialPort\");\n+\t\t\t\tchanged = true;\n+\t\t\t}\n+\t\t\tString dummy = (String) config.get(\"baud\");\n+\t\t\ttry {\n+\t\t\t\tif (serialBaudrate != Integer.parseInt(dummy)) {\n+\t\t\t\t\tserialBaudrate = Integer.parseInt(dummy);\n+\t\t\t\t\tchanged = true;\n+\t\t\t\t}\n+\t\t\t} catch (NumberFormatException e) {\n+\t\t\t\tlogger.info(\"reading exception\");\n+\t\t\t}\n+\n+\t\t\tif (changed | (baseStation == null)) {\n+\t\t\t\tif (baseStation != null)\n+\t\t\t\t\tbaseStation.closeSerialPort();\n+\n+\t\t\t\tbaseStation = new BaseStation(serialPortname, serialBaudrate, this);\n+\t\t\t\tlogger.debug(\"Smarthomatic Binding:update creates new basestation\");\n+\t\t\t}\n+\n+\t\t\tEnumeration<String> keys = config.keys();\n+\t\t\tfor (int i = 0; i < config.size(); i++) {\n+\t\t\t\tString key = keys.nextElement();\n+\t\t\t\tStringTokenizer tokens = new StringTokenizer(key, \":\");\n+\n+\t\t\t\tif (tokens.nextToken().equals(\"device\")) {\n+\t\t\t\t\tif (tokens.hasMoreElements()) {\n+\t\t\t\t\t\tdummy = tokens.nextToken();\n+\t\t\t\t\t\tint deviceID = Integer.parseInt(dummy);\n+\t\t\t\t\t\tString name = (String) config.get(key);\n+\t\t\t\t\t\tSmarthomaticGenericBindingProvider.addDevice(name, deviceID);\n+\t\t\t\t\t\tlogger.debug(\"Smarthomatic device {} can be indexed by name {}\", new String[] { dummy, name });\n+\t\t\t\t\t}\n+\t\t\t\t}\n+\t\t\t\tlogger.debug(\"KEY:\" + key);\n+\t\t\t}\n+\n+\t\t\tsetProperlyConfigured(true);\n+\t\t}\n+\t}\n+\n+\tprivate String processTransformation(String transformation, String response) {\n+\t\tString transformedResponse = response;\n+\t\tif (transformation == null) {\n+\t\t\treturn transformedResponse;\n+\t\t}\n+\t\ttry {\n+\t\t\tString[] parts = splitTransformationConfig(transformation);\n+\t\t\tString transformationType = parts[0];\n+\t\t\tString transformationFunction = parts[1];\n+\n+\t\t\tTransformationService transformationService = TransformationHelper\n+\t\t\t\t\t.getTransformationService(SmarthomaticActivator.getContext(), transformationType);\n+\t\t\tif (transformationService != null) {\n+\t\t\t\ttransformedResponse = transformationService.transform(transformationFunction, response);\n+\t\t\t} else {\n+\t\t\t\ttransformedResponse = response;\n+\t\t\t\tlogger.warn(\"couldn't transform response because transformationService of type '{}' is unavailable\",\n+\t\t\t\t\t\ttransformationType);\n+\t\t\t}\n+\t\t} catch (TransformationException te) {\n+\t\t\tlogger.error(\"transformation throws exception [transformation=\" + transformation + \", response=\" + response\n+\t\t\t\t\t+ \"]\", te);\n+\n+\t\t\t// in case of an error we return the response without any\n+\t\t\t// transformation\n+\t\t\ttransformedResponse = response;\n+\t\t}\n+\n+\t\tlogger.debug(\"transformed response is '{}'\", transformedResponse);\n+\n+\t\treturn transformedResponse;\n+\t}\n+\n+\t/**\n+\t * Splits a transformation configuration string into its two parts - the\n+\t * transformation type and the function/pattern to apply.\n+\t * \n+\t * @since 1.8.0\n+\t * @param transformation\n+\t *            the string to split\n+\t * @return a string array with exactly two entries for the type and the\n+\t *         function\n+\t */\n+\tprotected String[] splitTransformationConfig(String transformation) {\n+\t\tMatcher matcher = EXTRACT_FUNCTION_PATTERN.matcher(transformation);\n+\n+\t\tif (!matcher.matches()) {\n+\t\t\tthrow new IllegalArgumentException(\"given transformation function '\" + transformation\n+\t\t\t\t\t+ \"' does not follow the expected pattern '<function>(<pattern>)'\");\n+\t\t}\n+\t\tmatcher.reset();\n+\n+\t\tmatcher.find();\n+\t\tString type = matcher.group(1);\n+\t\tString pattern = matcher.group(2);\n+\n+\t\treturn new String[] { type, pattern };\n+\t}\n+\n+\t@Override\n+\tpublic void eventOccured(String message) {\n+\t\tStringTokenizer strTok = new StringTokenizer(message, \"\\n\");\n+\t\tString data = null;\n+\n+\t\t// check incoming data\n+\t\tint i = 0;\n+\t\twhile (strTok.hasMoreTokens()) {\n+\t\t\tString s = strTok.nextToken();\n+\t\t\tif (s.contains(SHCMessage.DATA_FLAG)) {\n+\t\t\t\tdata = s;\n+\t\t\t\tlogger.debug(\"<BaseStation data>[\" + (i) + \"]: \" + data);\n+\t\t\t}\n+\t\t}\n+\t\tif (data != null) {\n+\t\t\tSHCMessage shcMessage = new SHCMessage(data, packet);\n+\t\t\tSHCHeader shcHeader = shcMessage.getHeader();\n+\n+\t\t\tlogger.debug(\"BaseStation SenderID: \" + shcHeader.getSenderID() + \" MsgType: \" + shcHeader.getMessageType()","path":"bundles/binding/org.openhab.binding.smarthomatic/src/main/java/org/openhab/binding/smarthomatic/internal/SmarthomaticBinding.java","position":323,"original_position":323,"commit_id":"fceed3e70b61a587cfad812d794d6f7e4740dfcf","original_commit_id":"fceed3e70b61a587cfad812d794d6f7e4740dfcf","user":{"login":"hakan42","id":352641,"avatar_url":"https://avatars.githubusercontent.com/u/352641?v=3","gravatar_id":"","url":"https://api.github.com/users/hakan42","html_url":"https://github.com/hakan42","followers_url":"https://api.github.com/users/hakan42/followers","following_url":"https://api.github.com/users/hakan42/following{/other_user}","gists_url":"https://api.github.com/users/hakan42/gists{/gist_id}","starred_url":"https://api.github.com/users/hakan42/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/hakan42/subscriptions","organizations_url":"https://api.github.com/users/hakan42/orgs","repos_url":"https://api.github.com/users/hakan42/repos","events_url":"https://api.github.com/users/hakan42/events{/privacy}","received_events_url":"https://api.github.com/users/hakan42/received_events","type":"User","site_admin":false},"body":"Please use slf4j parametrization instead of string concatenation","created_at":"2015-12-02T18:01:43Z","updated_at":"2015-12-02T18:01:43Z","html_url":"https://github.com/openhab/openhab/pull/2992#discussion_r46449878","pull_request_url":"https://api.github.com/repos/openhab/openhab/pulls/2992","_links":{"self":{"href":"https://api.github.com/repos/openhab/openhab/pulls/comments/46449878"},"html":{"href":"https://github.com/openhab/openhab/pull/2992#discussion_r46449878"},"pull_request":{"href":"https://api.github.com/repos/openhab/openhab/pulls/2992"}}},"pull_request":{"url":"https://api.github.com/repos/openhab/openhab/pulls/2992","id":41368546,"html_url":"https://github.com/openhab/openhab/pull/2992","diff_url":"https://github.com/openhab/openhab/pull/2992.diff","patch_url":"https://github.com/openhab/openhab/pull/2992.patch","issue_url":"https://api.github.com/repos/openhab/openhab/issues/2992","number":2992,"state":"open","locked":false,"title":"Smarthomatic binding for openhab","user":{"login":"mcjobo","id":9785955,"avatar_url":"https://avatars.githubusercontent.com/u/9785955?v=3","gravatar_id":"","url":"https://api.github.com/users/mcjobo","html_url":"https://github.com/mcjobo","followers_url":"https://api.github.com/users/mcjobo/followers","following_url":"https://api.github.com/users/mcjobo/following{/other_user}","gists_url":"https://api.github.com/users/mcjobo/gists{/gist_id}","starred_url":"https://api.github.com/users/mcjobo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mcjobo/subscriptions","organizations_url":"https://api.github.com/users/mcjobo/orgs","repos_url":"https://api.github.com/users/mcjobo/repos","events_url":"https://api.github.com/users/mcjobo/events{/privacy}","received_events_url":"https://api.github.com/users/mcjobo/received_events","type":"User","site_admin":false},"body":"we've created a openhab binding for smarthomatic (see https://www.smarthomatic.org/basics/communication_protocol.html). I've also tested the binding with openhab2. Do I have to do anything else?","created_at":"2015-07-31T18:42:39Z","updated_at":"2015-12-02T18:01:43Z","closed_at":null,"merged_at":null,"merge_commit_sha":"05a944b2e89be02437be484143aea1dbbd219d7a","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/openhab/openhab/pulls/2992/commits","review_comments_url":"https://api.github.com/repos/openhab/openhab/pulls/2992/comments","review_comment_url":"https://api.github.com/repos/openhab/openhab/pulls/comments{/number}","comments_url":"https://api.github.com/repos/openhab/openhab/issues/2992/comments","statuses_url":"https://api.github.com/repos/openhab/openhab/statuses/fceed3e70b61a587cfad812d794d6f7e4740dfcf","head":{"label":"mcjobo:master","ref":"master","sha":"fceed3e70b61a587cfad812d794d6f7e4740dfcf","user":{"login":"mcjobo","id":9785955,"avatar_url":"https://avatars.githubusercontent.com/u/9785955?v=3","gravatar_id":"","url":"https://api.github.com/users/mcjobo","html_url":"https://github.com/mcjobo","followers_url":"https://api.github.com/users/mcjobo/followers","following_url":"https://api.github.com/users/mcjobo/following{/other_user}","gists_url":"https://api.github.com/users/mcjobo/gists{/gist_id}","starred_url":"https://api.github.com/users/mcjobo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mcjobo/subscriptions","organizations_url":"https://api.github.com/users/mcjobo/orgs","repos_url":"https://api.github.com/users/mcjobo/repos","events_url":"https://api.github.com/users/mcjobo/events{/privacy}","received_events_url":"https://api.github.com/users/mcjobo/received_events","type":"User","site_admin":false},"repo":{"id":26721040,"name":"openhab","full_name":"mcjobo/openhab","owner":{"login":"mcjobo","id":9785955,"avatar_url":"https://avatars.githubusercontent.com/u/9785955?v=3","gravatar_id":"","url":"https://api.github.com/users/mcjobo","html_url":"https://github.com/mcjobo","followers_url":"https://api.github.com/users/mcjobo/followers","following_url":"https://api.github.com/users/mcjobo/following{/other_user}","gists_url":"https://api.github.com/users/mcjobo/gists{/gist_id}","starred_url":"https://api.github.com/users/mcjobo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mcjobo/subscriptions","organizations_url":"https://api.github.com/users/mcjobo/orgs","repos_url":"https://api.github.com/users/mcjobo/repos","events_url":"https://api.github.com/users/mcjobo/events{/privacy}","received_events_url":"https://api.github.com/users/mcjobo/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/mcjobo/openhab","description":"Source code of the open Home Automation Bus (openHAB)","fork":true,"url":"https://api.github.com/repos/mcjobo/openhab","forks_url":"https://api.github.com/repos/mcjobo/openhab/forks","keys_url":"https://api.github.com/repos/mcjobo/openhab/keys{/key_id}","collaborators_url":"https://api.github.com/repos/mcjobo/openhab/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/mcjobo/openhab/teams","hooks_url":"https://api.github.com/repos/mcjobo/openhab/hooks","issue_events_url":"https://api.github.com/repos/mcjobo/openhab/issues/events{/number}","events_url":"https://api.github.com/repos/mcjobo/openhab/events","assignees_url":"https://api.github.com/repos/mcjobo/openhab/assignees{/user}","branches_url":"https://api.github.com/repos/mcjobo/openhab/branches{/branch}","tags_url":"https://api.github.com/repos/mcjobo/openhab/tags","blobs_url":"https://api.github.com/repos/mcjobo/openhab/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/mcjobo/openhab/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/mcjobo/openhab/git/refs{/sha}","trees_url":"https://api.github.com/repos/mcjobo/openhab/git/trees{/sha}","statuses_url":"https://api.github.com/repos/mcjobo/openhab/statuses/{sha}","languages_url":"https://api.github.com/repos/mcjobo/openhab/languages","stargazers_url":"https://api.github.com/repos/mcjobo/openhab/stargazers","contributors_url":"https://api.github.com/repos/mcjobo/openhab/contributors","subscribers_url":"https://api.github.com/repos/mcjobo/openhab/subscribers","subscription_url":"https://api.github.com/repos/mcjobo/openhab/subscription","commits_url":"https://api.github.com/repos/mcjobo/openhab/commits{/sha}","git_commits_url":"https://api.github.com/repos/mcjobo/openhab/git/commits{/sha}","comments_url":"https://api.github.com/repos/mcjobo/openhab/comments{/number}","issue_comment_url":"https://api.github.com/repos/mcjobo/openhab/issues/comments{/number}","contents_url":"https://api.github.com/repos/mcjobo/openhab/contents/{+path}","compare_url":"https://api.github.com/repos/mcjobo/openhab/compare/{base}...{head}","merges_url":"https://api.github.com/repos/mcjobo/openhab/merges","archive_url":"https://api.github.com/repos/mcjobo/openhab/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/mcjobo/openhab/downloads","issues_url":"https://api.github.com/repos/mcjobo/openhab/issues{/number}","pulls_url":"https://api.github.com/repos/mcjobo/openhab/pulls{/number}","milestones_url":"https://api.github.com/repos/mcjobo/openhab/milestones{/number}","notifications_url":"https://api.github.com/repos/mcjobo/openhab/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/mcjobo/openhab/labels{/name}","releases_url":"https://api.github.com/repos/mcjobo/openhab/releases{/id}","created_at":"2014-11-16T17:02:49Z","updated_at":"2015-03-30T11:02:37Z","pushed_at":"2015-09-23T20:09:53Z","git_url":"git://github.com/mcjobo/openhab.git","ssh_url":"git@github.com:mcjobo/openhab.git","clone_url":"https://github.com/mcjobo/openhab.git","svn_url":"https://github.com/mcjobo/openhab","homepage":null,"size":169092,"stargazers_count":1,"watchers_count":1,"language":"Java","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":2,"mirror_url":null,"open_issues_count":1,"forks":2,"open_issues":1,"watchers":1,"default_branch":"master"}},"base":{"label":"openhab:master","ref":"master","sha":"a629c17159a599b60e75be12918186122fd12625","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":12983151,"name":"openhab","full_name":"openhab/openhab","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/openhab","description":"Source code of the open Home Automation Bus (openHAB)","fork":false,"url":"https://api.github.com/repos/openhab/openhab","forks_url":"https://api.github.com/repos/openhab/openhab/forks","keys_url":"https://api.github.com/repos/openhab/openhab/keys{/key_id}","collaborators_url":"https://api.github.com/repos/openhab/openhab/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/openhab/openhab/teams","hooks_url":"https://api.github.com/repos/openhab/openhab/hooks","issue_events_url":"https://api.github.com/repos/openhab/openhab/issues/events{/number}","events_url":"https://api.github.com/repos/openhab/openhab/events","assignees_url":"https://api.github.com/repos/openhab/openhab/assignees{/user}","branches_url":"https://api.github.com/repos/openhab/openhab/branches{/branch}","tags_url":"https://api.github.com/repos/openhab/openhab/tags","blobs_url":"https://api.github.com/repos/openhab/openhab/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/openhab/openhab/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/openhab/openhab/git/refs{/sha}","trees_url":"https://api.github.com/repos/openhab/openhab/git/trees{/sha}","statuses_url":"https://api.github.com/repos/openhab/openhab/statuses/{sha}","languages_url":"https://api.github.com/repos/openhab/openhab/languages","stargazers_url":"https://api.github.com/repos/openhab/openhab/stargazers","contributors_url":"https://api.github.com/repos/openhab/openhab/contributors","subscribers_url":"https://api.github.com/repos/openhab/openhab/subscribers","subscription_url":"https://api.github.com/repos/openhab/openhab/subscription","commits_url":"https://api.github.com/repos/openhab/openhab/commits{/sha}","git_commits_url":"https://api.github.com/repos/openhab/openhab/git/commits{/sha}","comments_url":"https://api.github.com/repos/openhab/openhab/comments{/number}","issue_comment_url":"https://api.github.com/repos/openhab/openhab/issues/comments{/number}","contents_url":"https://api.github.com/repos/openhab/openhab/contents/{+path}","compare_url":"https://api.github.com/repos/openhab/openhab/compare/{base}...{head}","merges_url":"https://api.github.com/repos/openhab/openhab/merges","archive_url":"https://api.github.com/repos/openhab/openhab/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/openhab/openhab/downloads","issues_url":"https://api.github.com/repos/openhab/openhab/issues{/number}","pulls_url":"https://api.github.com/repos/openhab/openhab/pulls{/number}","milestones_url":"https://api.github.com/repos/openhab/openhab/milestones{/number}","notifications_url":"https://api.github.com/repos/openhab/openhab/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/openhab/openhab/labels{/name}","releases_url":"https://api.github.com/repos/openhab/openhab/releases{/id}","created_at":"2013-09-20T20:28:43Z","updated_at":"2015-12-02T16:09:11Z","pushed_at":"2015-12-02T17:50:18Z","git_url":"git://github.com/openhab/openhab.git","ssh_url":"git@github.com:openhab/openhab.git","clone_url":"https://github.com/openhab/openhab.git","svn_url":"https://github.com/openhab/openhab","homepage":null,"size":244413,"stargazers_count":1884,"watchers_count":1884,"language":"Java","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":1064,"mirror_url":null,"open_issues_count":438,"forks":1064,"open_issues":438,"watchers":1884,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/openhab/openhab/pulls/2992"},"html":{"href":"https://github.com/openhab/openhab/pull/2992"},"issue":{"href":"https://api.github.com/repos/openhab/openhab/issues/2992"},"comments":{"href":"https://api.github.com/repos/openhab/openhab/issues/2992/comments"},"review_comments":{"href":"https://api.github.com/repos/openhab/openhab/pulls/2992/comments"},"review_comment":{"href":"https://api.github.com/repos/openhab/openhab/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/openhab/openhab/pulls/2992/commits"},"statuses":{"href":"https://api.github.com/repos/openhab/openhab/statuses/fceed3e70b61a587cfad812d794d6f7e4740dfcf"}}}}