From 95b786a05789e6f51c8fba573467c327504e7ef2 Mon Sep 17 00:00:00 2001 From: Patrick Fink Date: Fri, 4 Dec 2020 07:47:21 +0100 Subject: [PATCH 01/37] [flicbutton] Initial contribution FlicButton Binding Signed-off-by: Patrick Fink --- .../org.openhab.binding.flicbutton/.gitignore | 1 + .../.travis.yml | 9 + .../org.openhab.binding.flicbutton/LICENSE | 277 ++++++++ bundles/org.openhab.binding.flicbutton/NOTICE | 21 + .../org.openhab.binding.flicbutton/README.md | 118 ++++ .../org.openhab.binding.flicbutton/pom.xml | 38 ++ .../src/3rdparty/LICENSE | 121 ++++ .../javaclient/BatteryStatusListener.java | 45 ++ .../io/flic/fliclib/javaclient/Bdaddr.java | 68 ++ .../javaclient/ButtonConnectionChannel.java | 188 ++++++ .../fliclib/javaclient/ButtonScanner.java | 28 + .../flic/fliclib/javaclient/FlicClient.java | 630 ++++++++++++++++++ .../fliclib/javaclient/GeneralCallbacks.java | 28 + .../GetButtonInfoResponseCallback.java | 18 + .../javaclient/GetInfoResponseCallback.java | 19 + .../io/flic/fliclib/javaclient/Packets.java | 455 +++++++++++++ .../flic/fliclib/javaclient/ScanWizard.java | 64 ++ .../flic/fliclib/javaclient/StreamUtils.java | 81 +++ .../io/flic/fliclib/javaclient/TimerTask.java | 14 + .../fliclib/javaclient/enums/BdAddrType.java | 9 + .../enums/BluetoothControllerState.java | 10 + .../fliclib/javaclient/enums/ClickType.java | 13 + .../javaclient/enums/ConnectionStatus.java | 10 + .../enums/CreateConnectionChannelError.java | 9 + .../javaclient/enums/DisconnectReason.java | 11 + .../fliclib/javaclient/enums/LatencyMode.java | 10 + .../javaclient/enums/RemovedReason.java | 22 + .../javaclient/enums/ScanWizardResult.java | 13 + .../src/main/feature/feature.xml | 10 + .../FlicButtonBindingConstants.java | 51 ++ .../flicbutton/handler/ChildThingHandler.java | 74 ++ .../FlicButtonBatteryLevelListener.java | 42 ++ .../handler/FlicButtonEventListener.java | 86 +++ .../flicbutton/handler/FlicButtonHandler.java | 179 +++++ .../FlicDaemonBridgeConfiguration.java | 63 ++ .../handler/FlicDaemonBridgeHandler.java | 153 +++++ .../internal/FlicButtonHandlerFactory.java | 106 +++ .../discovery/FlicButtonDiscoveryService.java | 42 ++ .../FlicSimpleclientDiscoveryServiceImpl.java | 137 ++++ .../internal/util/FlicButtonUtils.java | 54 ++ .../main/resources/OH-INF/binding/binding.xml | 10 + .../resources/OH-INF/thing/thing-types.xml | 37 + .../tools/checkstyle.properties | 7 + bundles/pom.xml | 1 + 44 files changed, 3382 insertions(+) create mode 100644 bundles/org.openhab.binding.flicbutton/.gitignore create mode 100644 bundles/org.openhab.binding.flicbutton/.travis.yml create mode 100644 bundles/org.openhab.binding.flicbutton/LICENSE create mode 100644 bundles/org.openhab.binding.flicbutton/NOTICE create mode 100644 bundles/org.openhab.binding.flicbutton/README.md create mode 100644 bundles/org.openhab.binding.flicbutton/pom.xml create mode 100644 bundles/org.openhab.binding.flicbutton/src/3rdparty/LICENSE create mode 100644 bundles/org.openhab.binding.flicbutton/src/3rdparty/java/io/flic/fliclib/javaclient/BatteryStatusListener.java create mode 100644 bundles/org.openhab.binding.flicbutton/src/3rdparty/java/io/flic/fliclib/javaclient/Bdaddr.java create mode 100644 bundles/org.openhab.binding.flicbutton/src/3rdparty/java/io/flic/fliclib/javaclient/ButtonConnectionChannel.java create mode 100644 bundles/org.openhab.binding.flicbutton/src/3rdparty/java/io/flic/fliclib/javaclient/ButtonScanner.java create mode 100644 bundles/org.openhab.binding.flicbutton/src/3rdparty/java/io/flic/fliclib/javaclient/FlicClient.java create mode 100644 bundles/org.openhab.binding.flicbutton/src/3rdparty/java/io/flic/fliclib/javaclient/GeneralCallbacks.java create mode 100644 bundles/org.openhab.binding.flicbutton/src/3rdparty/java/io/flic/fliclib/javaclient/GetButtonInfoResponseCallback.java create mode 100644 bundles/org.openhab.binding.flicbutton/src/3rdparty/java/io/flic/fliclib/javaclient/GetInfoResponseCallback.java create mode 100644 bundles/org.openhab.binding.flicbutton/src/3rdparty/java/io/flic/fliclib/javaclient/Packets.java create mode 100644 bundles/org.openhab.binding.flicbutton/src/3rdparty/java/io/flic/fliclib/javaclient/ScanWizard.java create mode 100644 bundles/org.openhab.binding.flicbutton/src/3rdparty/java/io/flic/fliclib/javaclient/StreamUtils.java create mode 100644 bundles/org.openhab.binding.flicbutton/src/3rdparty/java/io/flic/fliclib/javaclient/TimerTask.java create mode 100644 bundles/org.openhab.binding.flicbutton/src/3rdparty/java/io/flic/fliclib/javaclient/enums/BdAddrType.java create mode 100644 bundles/org.openhab.binding.flicbutton/src/3rdparty/java/io/flic/fliclib/javaclient/enums/BluetoothControllerState.java create mode 100644 bundles/org.openhab.binding.flicbutton/src/3rdparty/java/io/flic/fliclib/javaclient/enums/ClickType.java create mode 100644 bundles/org.openhab.binding.flicbutton/src/3rdparty/java/io/flic/fliclib/javaclient/enums/ConnectionStatus.java create mode 100644 bundles/org.openhab.binding.flicbutton/src/3rdparty/java/io/flic/fliclib/javaclient/enums/CreateConnectionChannelError.java create mode 100644 bundles/org.openhab.binding.flicbutton/src/3rdparty/java/io/flic/fliclib/javaclient/enums/DisconnectReason.java create mode 100644 bundles/org.openhab.binding.flicbutton/src/3rdparty/java/io/flic/fliclib/javaclient/enums/LatencyMode.java create mode 100644 bundles/org.openhab.binding.flicbutton/src/3rdparty/java/io/flic/fliclib/javaclient/enums/RemovedReason.java create mode 100644 bundles/org.openhab.binding.flicbutton/src/3rdparty/java/io/flic/fliclib/javaclient/enums/ScanWizardResult.java create mode 100644 bundles/org.openhab.binding.flicbutton/src/main/feature/feature.xml create mode 100644 bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/FlicButtonBindingConstants.java create mode 100644 bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/ChildThingHandler.java create mode 100644 bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicButtonBatteryLevelListener.java create mode 100644 bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicButtonEventListener.java create mode 100644 bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicButtonHandler.java create mode 100644 bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicDaemonBridgeConfiguration.java create mode 100644 bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicDaemonBridgeHandler.java create mode 100644 bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/FlicButtonHandlerFactory.java create mode 100644 bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/discovery/FlicButtonDiscoveryService.java create mode 100644 bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/discovery/FlicSimpleclientDiscoveryServiceImpl.java create mode 100644 bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/util/FlicButtonUtils.java create mode 100644 bundles/org.openhab.binding.flicbutton/src/main/resources/OH-INF/binding/binding.xml create mode 100644 bundles/org.openhab.binding.flicbutton/src/main/resources/OH-INF/thing/thing-types.xml create mode 100644 bundles/org.openhab.binding.flicbutton/tools/checkstyle.properties diff --git a/bundles/org.openhab.binding.flicbutton/.gitignore b/bundles/org.openhab.binding.flicbutton/.gitignore new file mode 100644 index 0000000000000..ea8c4bf7f35f6 --- /dev/null +++ b/bundles/org.openhab.binding.flicbutton/.gitignore @@ -0,0 +1 @@ +/target diff --git a/bundles/org.openhab.binding.flicbutton/.travis.yml b/bundles/org.openhab.binding.flicbutton/.travis.yml new file mode 100644 index 0000000000000..1526a73c35dea --- /dev/null +++ b/bundles/org.openhab.binding.flicbutton/.travis.yml @@ -0,0 +1,9 @@ +language: java +jdk: openjdk11 +before_install: + - wget /~https://github.com/openhab/openhab-addons/archive/2.5.x.tar.gz + - tar xzf 2.5.x.tar.gz + - mkdir openhab-addons-2.5.x/bundles/org.openhab.binding.flicbutton + - shopt -s extglob dotglob + - mv !(openhab-addons-2.5.x) openhab-addons-2.5.x/bundles/org.openhab.binding.flicbutton + - cd openhab-addons-2.5.x/bundles/org.openhab.binding.flicbutton diff --git a/bundles/org.openhab.binding.flicbutton/LICENSE b/bundles/org.openhab.binding.flicbutton/LICENSE new file mode 100644 index 0000000000000..e55f34467e251 --- /dev/null +++ b/bundles/org.openhab.binding.flicbutton/LICENSE @@ -0,0 +1,277 @@ +Eclipse Public License - v 2.0 + + THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE + PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION + OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. + +1. DEFINITIONS + +"Contribution" means: + + a) in the case of the initial Contributor, the initial content + Distributed under this Agreement, and + + b) in the case of each subsequent Contributor: + i) changes to the Program, and + ii) additions to the Program; + where such changes and/or additions to the Program originate from + and are Distributed by that particular Contributor. A Contribution + "originates" from a Contributor if it was added to the Program by + such Contributor itself or anyone acting on such Contributor's behalf. + Contributions do not include changes or additions to the Program that + are not Modified Works. + +"Contributor" means any person or entity that Distributes the Program. + +"Licensed Patents" mean patent claims licensable by a Contributor which +are necessarily infringed by the use or sale of its Contribution alone +or when combined with the Program. + +"Program" means the Contributions Distributed in accordance with this +Agreement. + +"Recipient" means anyone who receives the Program under this Agreement +or any Secondary License (as applicable), including Contributors. + +"Derivative Works" shall mean any work, whether in Source Code or other +form, that is based on (or derived from) the Program and for which the +editorial revisions, annotations, elaborations, or other modifications +represent, as a whole, an original work of authorship. + +"Modified Works" shall mean any work in Source Code or other form that +results from an addition to, deletion from, or modification of the +contents of the Program, including, for purposes of clarity any new file +in Source Code form that contains any contents of the Program. Modified +Works shall not include works that contain only declarations, +interfaces, types, classes, structures, or files of the Program solely +in each case in order to link to, bind by name, or subclass the Program +or Modified Works thereof. + +"Distribute" means the acts of a) distributing or b) making available +in any manner that enables the transfer of a copy. + +"Source Code" means the form of a Program preferred for making +modifications, including but not limited to software source code, +documentation source, and configuration files. + +"Secondary License" means either the GNU General Public License, +Version 2.0, or any later versions of that license, including any +exceptions or additional permissions as identified by the initial +Contributor. + +2. GRANT OF RIGHTS + + a) Subject to the terms of this Agreement, each Contributor hereby + grants Recipient a non-exclusive, worldwide, royalty-free copyright + license to reproduce, prepare Derivative Works of, publicly display, + publicly perform, Distribute and sublicense the Contribution of such + Contributor, if any, and such Derivative Works. + + b) Subject to the terms of this Agreement, each Contributor hereby + grants Recipient a non-exclusive, worldwide, royalty-free patent + license under Licensed Patents to make, use, sell, offer to sell, + import and otherwise transfer the Contribution of such Contributor, + if any, in Source Code or other form. This patent license shall + apply to the combination of the Contribution and the Program if, at + the time the Contribution is added by the Contributor, such addition + of the Contribution causes such combination to be covered by the + Licensed Patents. The patent license shall not apply to any other + combinations which include the Contribution. No hardware per se is + licensed hereunder. + + c) Recipient understands that although each Contributor grants the + licenses to its Contributions set forth herein, no assurances are + provided by any Contributor that the Program does not infringe the + patent or other intellectual property rights of any other entity. + Each Contributor disclaims any liability to Recipient for claims + brought by any other entity based on infringement of intellectual + property rights or otherwise. As a condition to exercising the + rights and licenses granted hereunder, each Recipient hereby + assumes sole responsibility to secure any other intellectual + property rights needed, if any. For example, if a third party + patent license is required to allow Recipient to Distribute the + Program, it is Recipient's responsibility to acquire that license + before distributing the Program. + + d) Each Contributor represents that to its knowledge it has + sufficient copyright rights in its Contribution, if any, to grant + the copyright license set forth in this Agreement. + + e) Notwithstanding the terms of any Secondary License, no + Contributor makes additional grants to any Recipient (other than + those set forth in this Agreement) as a result of such Recipient's + receipt of the Program under the terms of a Secondary License + (if permitted under the terms of Section 3). + +3. REQUIREMENTS + +3.1 If a Contributor Distributes the Program in any form, then: + + a) the Program must also be made available as Source Code, in + accordance with section 3.2, and the Contributor must accompany + the Program with a statement that the Source Code for the Program + is available under this Agreement, and informs Recipients how to + obtain it in a reasonable manner on or through a medium customarily + used for software exchange; and + + b) the Contributor may Distribute the Program under a license + different than this Agreement, provided that such license: + i) effectively disclaims on behalf of all other Contributors all + warranties and conditions, express and implied, including + warranties or conditions of title and non-infringement, and + implied warranties or conditions of merchantability and fitness + for a particular purpose; + + ii) effectively excludes on behalf of all other Contributors all + liability for damages, including direct, indirect, special, + incidental and consequential damages, such as lost profits; + + iii) does not attempt to limit or alter the recipients' rights + in the Source Code under section 3.2; and + + iv) requires any subsequent distribution of the Program by any + party to be under a license that satisfies the requirements + of this section 3. + +3.2 When the Program is Distributed as Source Code: + + a) it must be made available under this Agreement, or if the + Program (i) is combined with other material in a separate file or + files made available under a Secondary License, and (ii) the initial + Contributor attached to the Source Code the notice described in + Exhibit A of this Agreement, then the Program may be made available + under the terms of such Secondary Licenses, and + + b) a copy of this Agreement must be included with each copy of + the Program. + +3.3 Contributors may not remove or alter any copyright, patent, +trademark, attribution notices, disclaimers of warranty, or limitations +of liability ("notices") contained within the Program from any copy of +the Program which they Distribute, provided that Contributors may add +their own appropriate notices. + +4. COMMERCIAL DISTRIBUTION + +Commercial distributors of software may accept certain responsibilities +with respect to end users, business partners and the like. While this +license is intended to facilitate the commercial use of the Program, +the Contributor who includes the Program in a commercial product +offering should do so in a manner which does not create potential +liability for other Contributors. Therefore, if a Contributor includes +the Program in a commercial product offering, such Contributor +("Commercial Contributor") hereby agrees to defend and indemnify every +other Contributor ("Indemnified Contributor") against any losses, +damages and costs (collectively "Losses") arising from claims, lawsuits +and other legal actions brought by a third party against the Indemnified +Contributor to the extent caused by the acts or omissions of such +Commercial Contributor in connection with its distribution of the Program +in a commercial product offering. The obligations in this section do not +apply to any claims or Losses relating to any actual or alleged +intellectual property infringement. In order to qualify, an Indemnified +Contributor must: a) promptly notify the Commercial Contributor in +writing of such claim, and b) allow the Commercial Contributor to control, +and cooperate with the Commercial Contributor in, the defense and any +related settlement negotiations. The Indemnified Contributor may +participate in any such claim at its own expense. + +For example, a Contributor might include the Program in a commercial +product offering, Product X. That Contributor is then a Commercial +Contributor. If that Commercial Contributor then makes performance +claims, or offers warranties related to Product X, those performance +claims and warranties are such Commercial Contributor's responsibility +alone. Under this section, the Commercial Contributor would have to +defend claims against the other Contributors related to those performance +claims and warranties, and if a court requires any other Contributor to +pay any damages as a result, the Commercial Contributor must pay +those damages. + +5. NO WARRANTY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT +PERMITTED BY APPLICABLE LAW, THE PROGRAM IS PROVIDED ON AN "AS IS" +BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR +IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF +TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR +PURPOSE. Each Recipient is solely responsible for determining the +appropriateness of using and distributing the Program and assumes all +risks associated with its exercise of rights under this Agreement, +including but not limited to the risks and costs of program errors, +compliance with applicable laws, damage to or loss of data, programs +or equipment, and unavailability or interruption of operations. + +6. DISCLAIMER OF LIABILITY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT +PERMITTED BY APPLICABLE LAW, NEITHER RECIPIENT NOR ANY CONTRIBUTORS +SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST +PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE +EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + +7. GENERAL + +If any provision of this Agreement is invalid or unenforceable under +applicable law, it shall not affect the validity or enforceability of +the remainder of the terms of this Agreement, and without further +action by the parties hereto, such provision shall be reformed to the +minimum extent necessary to make such provision valid and enforceable. + +If Recipient institutes patent litigation against any entity +(including a cross-claim or counterclaim in a lawsuit) alleging that the +Program itself (excluding combinations of the Program with other software +or hardware) infringes such Recipient's patent(s), then such Recipient's +rights granted under Section 2(b) shall terminate as of the date such +litigation is filed. + +All Recipient's rights under this Agreement shall terminate if it +fails to comply with any of the material terms or conditions of this +Agreement and does not cure such failure in a reasonable period of +time after becoming aware of such noncompliance. If all Recipient's +rights under this Agreement terminate, Recipient agrees to cease use +and distribution of the Program as soon as reasonably practicable. +However, Recipient's obligations under this Agreement and any licenses +granted by Recipient relating to the Program shall continue and survive. + +Everyone is permitted to copy and distribute copies of this Agreement, +but in order to avoid inconsistency the Agreement is copyrighted and +may only be modified in the following manner. The Agreement Steward +reserves the right to publish new versions (including revisions) of +this Agreement from time to time. No one other than the Agreement +Steward has the right to modify this Agreement. The Eclipse Foundation +is the initial Agreement Steward. The Eclipse Foundation may assign the +responsibility to serve as the Agreement Steward to a suitable separate +entity. Each new version of the Agreement will be given a distinguishing +version number. The Program (including Contributions) may always be +Distributed subject to the version of the Agreement under which it was +received. In addition, after a new version of the Agreement is published, +Contributor may elect to Distribute the Program (including its +Contributions) under the new version. + +Except as expressly stated in Sections 2(a) and 2(b) above, Recipient +receives no rights or licenses to the intellectual property of any +Contributor under this Agreement, whether expressly, by implication, +estoppel or otherwise. All rights in the Program not expressly granted +under this Agreement are reserved. Nothing in this Agreement is intended +to be enforceable by any entity that is not a Contributor or Recipient. +No third-party beneficiary rights are created under this Agreement. + +Exhibit A - Form of Secondary Licenses Notice + +"This Source Code may also be made available under the following +Secondary Licenses when the conditions for such availability set forth +in the Eclipse Public License, v. 2.0 are satisfied: {name license(s), +version(s), and exceptions or additional permissions here}." + + Simply including a copy of this Agreement, including this Exhibit A + is not sufficient to license the Source Code under Secondary Licenses. + + If it is not possible or desirable to put the notice in a particular + file, then You may include the notice in a location (such as a LICENSE + file in a relevant directory) where a recipient would be likely to + look for such a notice. + + You may add additional accurate notices of copyright ownership. \ No newline at end of file diff --git a/bundles/org.openhab.binding.flicbutton/NOTICE b/bundles/org.openhab.binding.flicbutton/NOTICE new file mode 100644 index 0000000000000..9a3e712ee40c9 --- /dev/null +++ b/bundles/org.openhab.binding.flicbutton/NOTICE @@ -0,0 +1,21 @@ +This content is produced and maintained by Patrick Fink. + +* Project home: https://www.openhab.org + +== Declared Project Licenses + +This program and the accompanying materials are made available under the terms +of the Eclipse Public License 2.0 which is available at +https://www.eclipse.org/legal/epl-2.0/. + +== Source Code + +/~https://github.com/openhab/openhab-addons + +== Third-party Content + +fliclib-javaclient (files under src/3rdparty) + +* License: CC0 1.0 +* Project: /~https://github.com/50ButtonsEach/fliclib-linux-hci +* Source: /~https://github.com/50ButtonsEach/fliclib-linux-hci/tree/master/clientlib/java/lib/src/main/java/io/flic/fliclib/javaclient diff --git a/bundles/org.openhab.binding.flicbutton/README.md b/bundles/org.openhab.binding.flicbutton/README.md new file mode 100644 index 0000000000000..e111e3d455d59 --- /dev/null +++ b/bundles/org.openhab.binding.flicbutton/README.md @@ -0,0 +1,118 @@ +# openHAB Flic Button Binding + +openHAB binding for using [Flic Buttons](https://flic.io/) +with a [fliclib-linux-hci](/~https://github.com/50ButtonsEach/fliclib-linux-hci) bridge. + +Currently, although Flic Buttons are BLE devices, this binding only supports fliclib-linux-hci (flicd) +as a bridge. The openHAB Bluetooth Bindings are not supported. Flicd requires a seperate Bluetooth adapter to work, so +if you use this binding together with e.g. the [Bluez Binding](https://www.openhab.org/addons/bindings/bluetooth.bluez/), +two physical Bluetooth adapters are required (one for Bluez and one for flicd). Be aware that flicd requires an initial +internet connection for the verification of the buttons. After buttons are initially added to flicd, internet connection +is not required anymore. + +## Supported Things + +| Thing Type ID | Description | +| --------------- | ------------------------- | +| flicd-bridge | The bridge representing a running instance of [fliclib-linux-hci (flicd)](/~https://github.com/50ButtonsEach/fliclib-linux-hci) on the server. | +| button | The Flic button (supports Flic 1 buttons as well as Flic 2 buttons) | + +## Discovery + +* There is no automatic discovery for flicd-bridge available. +* After flicd-bridge is (manually) configured, buttons will be automatically discovered via background discovery as soon + as they're addded with [simpleclient](/~https://github.com/50ButtonsEach/fliclib-linux-hci) . If they're already + attached to the flicd-bridge before configuring this binding, they can be discovered by triggering an active scan. + +## Thing Configuration + +### flicd-bridge + +Example for textual configuration: + +``` +Bridge flicbutton:flicd-bridge:mybridge +``` + +The default host is localhost:5551 (this should be sufficient if flicd is running with default settings on the same +server as openHAB). If your flicd service is running somewhere else, specify it like this: + +``` +Bridge flicbutton:flicd-bridge:mybridge [ hostname="", port=""] +``` + +If flicd is running on a remote host, please do not forget to start it with the parameter `-s `, otherwise it won't be accessible for openHAB (more details on [fliclib-linux-hci](/~https://github.com/50ButtonsEach/fliclib-linux-hci)). + +### button + +There are no configuration parameters for buttons available and normally no textual configuration is necessary as buttons are autodiscovered as soon as the bridge is configured. If you want to use textual configuration anyway, you can do it like this: + +``` +Bridge flicbutton:flicd-bridge:mybridge [ hostname="", port=""] { + Thing button "" + Thing button "" + ... +} +``` + +You can lookup the MAC addresses of your buttons within the inbox of Paper UI. You're free to choose any label you like for your button. + +## Channels + +| Channel ID | Channel Type | Item Type | Description | +| ------------------------- | ------------------------ | --------------------------| ------------------------------ | +| rawbutton | [System Trigger Channel](https://www.openhab.org/docs/developer/bindings/thing-xml.html#system-trigger-channel-types) `system.rawbutton` | Depends on the [Trigger Profile](https://www.openhab.org/docs/configuration/items.html#profiles) used | Raw Button channel that triggers `PRESSED` and `RELEASED` events, allows to use openHAB profiles or own implementations via rules to detect e.g. double clicks, long presses etc. | +| button | [System Trigger Channel](https://www.openhab.org/docs/developer/bindings/thing-xml.html#system-trigger-channel-types) `system.button` | Depends on the [Trigger Profile](https://www.openhab.org/docs/configuration/items.html#profiles) used | Button channel that is using Flic's implementation for detecting long, short or double clicks. Triggers `SHORT_PRESSED`,`DOUBLE_PRESSED` and `LONG_PRESSED` events. | +| battery-level | [System State Channel](https://www.openhab.org/docs/developer/bindings/thing-xml.html#system-state-channel-types) `system.battery-level` | Number | Represents the battery level as a percentage (0-100%). + + +## Example + +### Initial setup + +1. Setup and run flicd as described in [fliclib-linux-hci](/~https://github.com/50ButtonsEach/fliclib-linux-hci). Please consider that you need a seperate Bluetooth adapter. Shared usage with other Bluetooth services (e.g. Bluez) is not possible. +1. Connect your buttons to flicd using the simpleclient as described in [fliclib-linux-hci](/~https://github.com/50ButtonsEach/fliclib-linux-hci). Flicd has to run in background the whole time, simpleclient can be killed after you successfully tested the button connection. +1. Add a flicd-bridge via PaperUI or Textual Configuration. Please consider that flicd does only accept connections from localhost by default, to enable remote connections from openHAB you have to use the `--server-addr` parameter as described in [fliclib-linux-hci](/~https://github.com/50ButtonsEach/fliclib-linux-hci). +1. When the bridge is online, buttons newly added via simpleclient will automatically get discovered via background Discovery. To discover buttons that were set up before the Binding setup, please run an active scan. + +### Configuration Example using Profiles + +[Profiles](https://www.openhab.org/docs/configuration/items.html#profiles) are the recommended way to use this binding. + +demo.things: + +``` +Bridge bluetooth:bluegiga:bluegiga0 "Bluegiga Adapter" [ port="/dev/ttyBLUEGIGA", discovery=false ] { + Thing ptm215b rocker_livingroom "Rocker Living Room" [ address = "E2:15:00:00:53:F9" ] + Thing ptm215b rocker_kitchen "Rocker Kitchen" [ address = "E2:15:00:00:53:98" ] +} +``` + +demo.items: + +``` +Dimmer Light_LivingRoom { channel="milight:rgbLed:milight2:4:ledbrightness", channel="bluetooth:ptm215b:bluegiga0:rocker_livingroom:rocker1" [profile="rawbutton-to-on-off"], channel="bluetooth:ptm215b:bluegiga0:rocker_kitchen:rocker1" [profile="rawbutton-to-on-off"] } // We have a combined kitchen / livingroom, so we control the living room lights with switches from the living room and from the kitchen +Switch Light_Kitchen { channel="hue:group:1:kitchen-bulbs:switch", channel="bluetooth:ptm215b:bluegiga0:rocker_kitchen:rocker2" [profile="rawbutton-to-on-off"] } +``` + +### Configuration Example using Rules + +It's also possible to setup [Rules](https://www.openhab.org/docs/configuration/rules-dsl.html). +The following rules help to initially test your setup as they'll trigger log messages on incoming events. + ``` + rule "Button rule using the button channel" + + when + Channel "flicbutton:button:1:80-e4-da-71-12-34:button" triggered SHORT_PRESSED + then + logInfo("Flic", "Flic 'short pressed' triggered") + end + + rule "Button rule directly using the rawbutton channel" + + when + Channel "flicbutton:button:1:80-e4-da-71-12-34:rawbutton" triggered + then + logInfo("Flic", "Flic pressed: " + receivedEvent.event) + end + ``` diff --git a/bundles/org.openhab.binding.flicbutton/pom.xml b/bundles/org.openhab.binding.flicbutton/pom.xml new file mode 100644 index 0000000000000..6c898106b4d91 --- /dev/null +++ b/bundles/org.openhab.binding.flicbutton/pom.xml @@ -0,0 +1,38 @@ + + + + 4.0.0 + + + org.openhab.addons.bundles + org.openhab.addons.reactor.bundles + 3.0.0-SNAPSHOT + + + org.openhab.binding.flicbutton + + openHAB Add-ons :: Bundles :: FlicButton Binding + + + + + org.codehaus.mojo + build-helper-maven-plugin + + + + add-source + + generate-sources + + + src/3rdparty + + + + + + + + diff --git a/bundles/org.openhab.binding.flicbutton/src/3rdparty/LICENSE b/bundles/org.openhab.binding.flicbutton/src/3rdparty/LICENSE new file mode 100644 index 0000000000000..1625c17936079 --- /dev/null +++ b/bundles/org.openhab.binding.flicbutton/src/3rdparty/LICENSE @@ -0,0 +1,121 @@ +Creative Commons Legal Code + +CC0 1.0 Universal + + CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE + LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN + ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS + INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES + REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS + PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM + THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED + HEREUNDER. + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator +and subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for +the purpose of contributing to a commons of creative, cultural and +scientific works ("Commons") that the public can reliably and without fear +of later claims of infringement build upon, modify, incorporate in other +works, reuse and redistribute as freely as possible in any form whatsoever +and for any purposes, including without limitation commercial purposes. +These owners may contribute to the Commons to promote the ideal of a free +culture and the further production of creative, cultural and scientific +works, or to gain reputation or greater distribution for their Work in +part through the use and efforts of others. + +For these and/or other purposes and motivations, and without any +expectation of additional consideration or compensation, the person +associating CC0 with a Work (the "Affirmer"), to the extent that he or she +is an owner of Copyright and Related Rights in the Work, voluntarily +elects to apply CC0 to the Work and publicly distribute the Work under its +terms, with knowledge of his or her Copyright and Related Rights in the +Work and the meaning and intended legal effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not +limited to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, + communicate, and translate a Work; + ii. moral rights retained by the original author(s) and/or performer(s); +iii. publicity and privacy rights pertaining to a person's image or + likeness depicted in a Work; + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + v. rights protecting the extraction, dissemination, use and reuse of data + in a Work; + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation + thereof, including any amended or successor version of such + directive); and +vii. other similar, equivalent or corresponding rights throughout the + world based on applicable law or treaty, and any national + implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention +of, applicable law, Affirmer hereby overtly, fully, permanently, +irrevocably and unconditionally waives, abandons, and surrenders all of +Affirmer's Copyright and Related Rights and associated claims and causes +of action, whether now known or unknown (including existing as well as +future claims and causes of action), in the Work (i) in all territories +worldwide, (ii) for the maximum duration provided by applicable law or +treaty (including future time extensions), (iii) in any current or future +medium and for any number of copies, and (iv) for any purpose whatsoever, +including without limitation commercial, advertising or promotional +purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each +member of the public at large and to the detriment of Affirmer's heirs and +successors, fully intending that such Waiver shall not be subject to +revocation, rescission, cancellation, termination, or any other legal or +equitable action to disrupt the quiet enjoyment of the Work by the public +as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason +be judged legally invalid or ineffective under applicable law, then the +Waiver shall be preserved to the maximum extent permitted taking into +account Affirmer's express Statement of Purpose. In addition, to the +extent the Waiver is so judged Affirmer hereby grants to each affected +person a royalty-free, non transferable, non sublicensable, non exclusive, +irrevocable and unconditional license to exercise Affirmer's Copyright and +Related Rights in the Work (i) in all territories worldwide, (ii) for the +maximum duration provided by applicable law or treaty (including future +time extensions), (iii) in any current or future medium and for any number +of copies, and (iv) for any purpose whatsoever, including without +limitation commercial, advertising or promotional purposes (the +"License"). The License shall be deemed effective as of the date CC0 was +applied by Affirmer to the Work. Should any part of the License for any +reason be judged legally invalid or ineffective under applicable law, such +partial invalidity or ineffectiveness shall not invalidate the remainder +of the License, and in such case Affirmer hereby affirms that he or she +will not (i) exercise any of his or her remaining Copyright and Related +Rights in the Work or (ii) assert any associated claims and causes of +action with respect to the Work, in either case contrary to Affirmer's +express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + b. Affirmer offers the Work as-is and makes no representations or + warranties of any kind concerning the Work, express, implied, + statutory or otherwise, including without limitation warranties of + title, merchantability, fitness for a particular purpose, non + infringement, or the absence of latent or other defects, accuracy, or + the present or absence of errors, whether or not discoverable, all to + the greatest extent permissible under applicable law. + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without + limitation any person's Copyright and Related Rights in the Work. + Further, Affirmer disclaims responsibility for obtaining any necessary + consents, permissions or other rights required for any use of the + Work. + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to + this CC0 or use of the Work. \ No newline at end of file diff --git a/bundles/org.openhab.binding.flicbutton/src/3rdparty/java/io/flic/fliclib/javaclient/BatteryStatusListener.java b/bundles/org.openhab.binding.flicbutton/src/3rdparty/java/io/flic/fliclib/javaclient/BatteryStatusListener.java new file mode 100644 index 0000000000000..bb562f191500b --- /dev/null +++ b/bundles/org.openhab.binding.flicbutton/src/3rdparty/java/io/flic/fliclib/javaclient/BatteryStatusListener.java @@ -0,0 +1,45 @@ +package io.flic.fliclib.javaclient; + +import java.io.IOException; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * Battery status listener. + * + * Add this listener to a {@link FlicClient} by executing {@link FlicClient#addBatteryStatusListener(BatteryStatusListener)}. + */ +public class BatteryStatusListener { + private static AtomicInteger nextId = new AtomicInteger(); + int listenerId = nextId.getAndIncrement(); + + private Bdaddr bdaddr; + Callbacks callbacks; + + public BatteryStatusListener(Bdaddr bdaddr, Callbacks callbacks) { + if (bdaddr == null) { + throw new IllegalArgumentException("bdaddr is null"); + } + if (callbacks == null) { + throw new IllegalArgumentException("callbacks is null"); + } + this.bdaddr = bdaddr; + this.callbacks = callbacks; + } + + public Bdaddr getBdaddr() { + return bdaddr; + } + + public abstract static class Callbacks { + /** + * This will be called when the battery status has been updated. + * It will also be called immediately after the battery status listener has been created. + * If the button stays connected, this method will be called approximately every three hours. + * + * @param bdaddr Bluetooth device address + * @param batteryPercentage A number between 0 and 100 for the battery level. Will be -1 if unknown. + * @param timestamp Standard UNIX timestamp, in seconds, for the event. + */ + public abstract void onBatteryStatus(Bdaddr bdaddr, int batteryPercentage, long timestamp) throws IOException; + } +} \ No newline at end of file diff --git a/bundles/org.openhab.binding.flicbutton/src/3rdparty/java/io/flic/fliclib/javaclient/Bdaddr.java b/bundles/org.openhab.binding.flicbutton/src/3rdparty/java/io/flic/fliclib/javaclient/Bdaddr.java new file mode 100644 index 0000000000000..16a7b3989d3ff --- /dev/null +++ b/bundles/org.openhab.binding.flicbutton/src/3rdparty/java/io/flic/fliclib/javaclient/Bdaddr.java @@ -0,0 +1,68 @@ +package io.flic.fliclib.javaclient; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Arrays; + +/** + * Bluetooth address. + */ +public class Bdaddr { + private byte[] bytes; + + /** + * Creates a Bdaddr given the bluetooth address in string format. + * + * @param addr address of the format xx:xx:xx:xx:xx:xx + */ + public Bdaddr(String addr) { + bytes = new byte[6]; + bytes[5] = (byte)Integer.parseInt(addr.substring(0, 2), 16); + bytes[4] = (byte)Integer.parseInt(addr.substring(3, 5), 16); + bytes[3] = (byte)Integer.parseInt(addr.substring(6, 8), 16); + bytes[2] = (byte)Integer.parseInt(addr.substring(9, 11), 16); + bytes[1] = (byte)Integer.parseInt(addr.substring(12, 14), 16); + bytes[0] = (byte)Integer.parseInt(addr.substring(15, 17), 16); + } + + Bdaddr(InputStream stream) throws IOException { + bytes = new byte[6]; + for (int i = 0; i < 6; i++) { + bytes[i] = (byte)stream.read(); + } + } + + byte[] getBytes() { + return bytes.clone(); + } + + /** + * Create a string representing the bluetooth address. + * + * @return A string of the bdaddr + */ + @Override + public String toString() { + return String.format("%02x:%02x:%02x:%02x:%02x:%02x", bytes[5], bytes[4], bytes[3], bytes[2], bytes[1], bytes[0]); + } + + @Override + public int hashCode() { + return (bytes[0] & 0xff) ^ ((bytes[1] & 0xff) << 8) ^ ((bytes[2] & 0xff) << 16) ^ ((bytes[3] & 0xff) << 24) ^ (bytes[4] & 0xff) ^ ((bytes[5] & 0xff) << 8); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (!(obj instanceof Bdaddr)) { + return false; + } + Bdaddr other = (Bdaddr)obj; + return Arrays.equals(bytes, other.bytes); + } +} diff --git a/bundles/org.openhab.binding.flicbutton/src/3rdparty/java/io/flic/fliclib/javaclient/ButtonConnectionChannel.java b/bundles/org.openhab.binding.flicbutton/src/3rdparty/java/io/flic/fliclib/javaclient/ButtonConnectionChannel.java new file mode 100644 index 0000000000000..a006aea8b2eea --- /dev/null +++ b/bundles/org.openhab.binding.flicbutton/src/3rdparty/java/io/flic/fliclib/javaclient/ButtonConnectionChannel.java @@ -0,0 +1,188 @@ +package io.flic.fliclib.javaclient; + +import java.io.IOException; +import java.util.concurrent.atomic.AtomicInteger; + +import io.flic.fliclib.javaclient.enums.*; + +/** + * Button connection channel. + * + * Add this button connection channel to a {@link FlicClient} by executing {@link FlicClient#addConnectionChannel(ButtonConnectionChannel)}. + * You may only have this connection channel added to one {@link FlicClient} at a time. + */ +public class ButtonConnectionChannel { + private static AtomicInteger nextId = new AtomicInteger(); + int connId = nextId.getAndIncrement(); + + FlicClient client; + + private Bdaddr bdaddr; + private LatencyMode latencyMode; + private short autoDisconnectTime; + Callbacks callbacks; + + final Object lock = new Object(); + + /** + * Create a connection channel using the specified parameters. + * + * Add this button connection channel to a {@link FlicClient} by executing {@link FlicClient#addConnectionChannel(ButtonConnectionChannel)}. + * + * @param bdaddr + * @param latencyMode + * @param autoDisconnectTime Number of seconds (0 - 511) until disconnect if no button event happens. 512 disables this feature. + * @param callbacks + */ + public ButtonConnectionChannel(Bdaddr bdaddr, LatencyMode latencyMode, short autoDisconnectTime, Callbacks callbacks) { + if (bdaddr == null) { + throw new IllegalArgumentException("bdaddr is null"); + } + if (latencyMode == null) { + throw new IllegalArgumentException("latencyMode is null"); + } + if (callbacks == null) { + throw new IllegalArgumentException("callbacks is null"); + } + this.bdaddr = bdaddr; + this.latencyMode = latencyMode; + this.autoDisconnectTime = autoDisconnectTime; + this.callbacks = callbacks; + } + + /** + * Create a connection channel using the specified parameters. + * + * Add this button connection channel to a {@link FlicClient} by executing {@link FlicClient#addConnectionChannel(ButtonConnectionChannel)}. + * + * @param bdaddr + * @param callbacks + */ + public ButtonConnectionChannel(Bdaddr bdaddr, Callbacks callbacks) { + this(bdaddr, LatencyMode.NormalLatency, (short)0x1ff, callbacks); + } + + /** + * Get the {@link FlicClient} for this {@link ButtonConnectionChannel}. + * + * @return + */ + public FlicClient getFlicClient() { + return client; + } + + public Bdaddr getBdaddr() { + return bdaddr; + } + + public LatencyMode getLatencyMode() { + return latencyMode; + } + + public short getAutoDisconnectTime() { + return autoDisconnectTime; + } + + /** + * Applies new latency mode parameter. + * + * @param latencyMode + */ + public void setLatencyMode(LatencyMode latencyMode) throws IOException { + if (latencyMode == null) { + throw new IllegalArgumentException("latencyMode is null"); + } + synchronized (lock) { + this.latencyMode = latencyMode; + + FlicClient cl = client; + if (cl != null) { + CmdChangeModeParameters pkt = new CmdChangeModeParameters(); + pkt.connId = connId; + pkt.latencyMode = latencyMode; + pkt.autoDisconnectTime = autoDisconnectTime; + cl.sendPacket(pkt); + } + } + } + + /** + * Applies new auto disconnect time parameter. + * + * @param autoDisconnectTime Number of seconds (0 - 511) until disconnect if no button event happens. 512 disables this feature. + */ + public void setAutoDisconnectTime(short autoDisconnectTime) throws IOException { + if (latencyMode == null) { + throw new IllegalArgumentException("latencyMode is null"); + } + synchronized (lock) { + this.autoDisconnectTime = autoDisconnectTime; + + FlicClient cl = client; + if (cl != null) { + CmdChangeModeParameters pkt = new CmdChangeModeParameters(); + pkt.connId = connId; + pkt.latencyMode = latencyMode; + pkt.autoDisconnectTime = autoDisconnectTime; + cl.sendPacket(pkt); + } + } + } + + /** + * User callbacks for incoming events. + * + * See the protocol specification for further details. + */ + public abstract static class Callbacks { + + /** + * Called when the server has received the create connection channel command. + * + * If createConnectionChannelError is {@link CreateConnectionChannelError#NoError}, other events will arrive until {@link #onRemoved} is received. + * There will be no {@link #onRemoved} if an error occurred. + * + * @param channel + * @param createConnectionChannelError + * @param connectionStatus + * @throws IOException + */ + public void onCreateConnectionChannelResponse(ButtonConnectionChannel channel, CreateConnectionChannelError createConnectionChannelError, ConnectionStatus connectionStatus) throws IOException { + } + + /** + * Called when the connection channel has been removed. + * + * Check the removedReason to find out why. From this point, the connection channel can be re-added again if you wish. + * + * @param channel + * @param removedReason + * @throws IOException + */ + public void onRemoved(ButtonConnectionChannel channel, RemovedReason removedReason) throws IOException { + } + + /** + * Called when the connection status changes. + * + * @param channel + * @param connectionStatus + * @param disconnectReason Only valid if connectionStatus is {@link ConnectionStatus#Disconnected} + * @throws IOException + */ + public void onConnectionStatusChanged(ButtonConnectionChannel channel, ConnectionStatus connectionStatus, DisconnectReason disconnectReason) throws IOException { + } + + public void onButtonUpOrDown(ButtonConnectionChannel channel, ClickType clickType, boolean wasQueued, int timeDiff) throws IOException { + } + + public void onButtonClickOrHold(ButtonConnectionChannel channel, ClickType clickType, boolean wasQueued, int timeDiff) throws IOException { + } + + public void onButtonSingleOrDoubleClick(ButtonConnectionChannel channel, ClickType clickType, boolean wasQueued, int timeDiff) throws IOException { + } + + public void onButtonSingleOrDoubleClickOrHold(ButtonConnectionChannel channel, ClickType clickType, boolean wasQueued, int timeDiff) throws IOException { + } + } +} diff --git a/bundles/org.openhab.binding.flicbutton/src/3rdparty/java/io/flic/fliclib/javaclient/ButtonScanner.java b/bundles/org.openhab.binding.flicbutton/src/3rdparty/java/io/flic/fliclib/javaclient/ButtonScanner.java new file mode 100644 index 0000000000000..41ca1487e8cf9 --- /dev/null +++ b/bundles/org.openhab.binding.flicbutton/src/3rdparty/java/io/flic/fliclib/javaclient/ButtonScanner.java @@ -0,0 +1,28 @@ +package io.flic.fliclib.javaclient; + +import java.io.IOException; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * Button scanner class. + * + * Inherit this class and override the {@link #onAdvertisementPacket(Bdaddr, String, int, boolean, boolean)} method. + * Then add this button scanner to a {@link FlicClient} using {@link FlicClient#addScanner(ButtonScanner)} to start it. + */ +public abstract class ButtonScanner { + private static AtomicInteger nextId = new AtomicInteger(); + int scanId = nextId.getAndIncrement(); + + /** + * This will be called for every received advertisement packet from a Flic button. + * + * @param bdaddr Bluetooth address + * @param name Advertising name + * @param rssi RSSI value in dBm + * @param isPrivate The button is private and won't accept new connections from non-bonded clients + * @param alreadyVerified The server has already verified this button, which means you can connect to it even if it's private + * @param alreadyConnectedToThisDevice The button is already connected to this device + * @param alreadyConnectedToOtherDevice The button is already connected to another device + */ + public abstract void onAdvertisementPacket(Bdaddr bdaddr, String name, int rssi, boolean isPrivate, boolean alreadyVerified, boolean alreadyConnectedToThisDevice, boolean alreadyConnectedToOtherDevice) throws IOException; +} diff --git a/bundles/org.openhab.binding.flicbutton/src/3rdparty/java/io/flic/fliclib/javaclient/FlicClient.java b/bundles/org.openhab.binding.flicbutton/src/3rdparty/java/io/flic/fliclib/javaclient/FlicClient.java new file mode 100644 index 0000000000000..ca12329170e31 --- /dev/null +++ b/bundles/org.openhab.binding.flicbutton/src/3rdparty/java/io/flic/fliclib/javaclient/FlicClient.java @@ -0,0 +1,630 @@ +package io.flic.fliclib.javaclient; + +import io.flic.fliclib.javaclient.enums.CreateConnectionChannelError; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.Socket; +import java.net.SocketTimeoutException; +import java.net.UnknownHostException; +import java.util.ArrayDeque; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.ConcurrentSkipListMap; + +/** + * Implements a FlicClient over a TCP Socket. + * + * When this class is constructed, a socket connection is established. + * + * You may then send commands to the server and set timers. + * + * Once you are ready with the initialization you must call the {@link #handleEvents()} method which is a main loop that never exits, unless the socket is closed. + * + * For a more detailed description of all commands, events and enums, check the protocol specification. + */ +public class FlicClient { + private Socket socket; + private InputStream socketInputStream; + private OutputStream socketOutputStream; + + private ConcurrentHashMap scanners = new ConcurrentHashMap<>(); + private ConcurrentHashMap connectionChannels = new ConcurrentHashMap<>(); + private ConcurrentHashMap scanWizards = new ConcurrentHashMap<>(); + private ConcurrentHashMap batteryStatusListeners = new ConcurrentHashMap<>(); + private ConcurrentLinkedQueue getInfoResponseCallbackQueue = new ConcurrentLinkedQueue<>(); + private ArrayDeque getButtonInfoResponseCallbackQueue = new ArrayDeque<>(); + + private volatile GeneralCallbacks generalCallbacks = new GeneralCallbacks(); + + private ConcurrentSkipListMap timers = new ConcurrentSkipListMap<>(); + + private Thread handleEventsThread; + + /** + * Create a FlicClient and connect to the specified hostName and TCP port + * + * @param hostName + * @param port + * @throws UnknownHostException + * @throws IOException + */ + public FlicClient(String hostName, int port) throws UnknownHostException, IOException { + socket = new Socket(hostName, port); + socket.setKeepAlive(true); + socketInputStream = socket.getInputStream(); + socketOutputStream = socket.getOutputStream(); + } + + /** + * Create a FlicClient and connect to the specified hostName using the default TCP port + * + * @param hostName + * @throws UnknownHostException + * @throws IOException + */ + public FlicClient(String hostName) throws UnknownHostException, IOException { + this(hostName, 5551); + } + + /** + * Close the socket. + * + * From this point any use of this FlicClient is illegal. + * The {@link #handleEvents()} will return as soon as the closing is done. + * + * @throws IOException + */ + public void close() throws IOException { + runOnHandleEventsThread(new TimerTask() { + @Override + public void run() throws IOException { + socket.close(); + } + }); + } + + /** + * Set general callbacks to be called upon receiving some specific events. + * + * @param callbacks + */ + public void setGeneralCallbacks(GeneralCallbacks callbacks) { + if (callbacks == null) { + callbacks = new GeneralCallbacks(); + } + generalCallbacks = callbacks; + } + + /** + * Get info about the current state of the server. + * + * The server will send back its information directly and the callback will be called once the response arrives. + * + * @param callback + * @throws IOException + */ + public void getInfo(GetInfoResponseCallback callback) throws IOException { + if (callback == null) { + throw new IllegalArgumentException("callback is null"); + } + getInfoResponseCallbackQueue.add(callback); + + CmdGetInfo pkt = new CmdGetInfo(); + sendPacket(pkt); + } + + /** + * Get button info for a verified button. + * + * The server will send back its information directly and the callback will be called once the response arrives. + * Responses will arrive in the same order as requested. + * + * If the button isn't verified, the data sent to callback will be null. + * + * @param bdaddr The bluetooth address. + * @param callback Callback for the response. + * @throws IOException + */ + public void getButtonInfo(final Bdaddr bdaddr, final GetButtonInfoResponseCallback callback) throws IOException { + if (callback == null) { + throw new IllegalArgumentException("callback is null"); + } + // Run on events thread to ensure ordering if multiple requests are issued at the same time + runOnHandleEventsThread(new TimerTask() { + @Override + public void run() throws IOException { + getButtonInfoResponseCallbackQueue.add(callback); + + CmdGetButtonInfo pkt = new CmdGetButtonInfo(); + pkt.bdaddr = bdaddr; + sendPacket(pkt); + } + }); + } + + /** + * Add a scanner. + * + * The scan will start directly once the scanner is added. + * + * @param buttonScanner + * @throws IOException + */ + public void addScanner(ButtonScanner buttonScanner) throws IOException { + if (buttonScanner == null) { + throw new IllegalArgumentException("buttonScanner is null"); + } + if (scanners.putIfAbsent(buttonScanner.scanId, buttonScanner) != null) { + throw new IllegalArgumentException("Button scanner already added"); + } + + CmdCreateScanner pkt = new CmdCreateScanner(); + pkt.scanId = buttonScanner.scanId; + sendPacket(pkt); + } + + /** + * Remove a scanner. + * + * @param buttonScanner The same scanner that was used in {@link #addScanner(ButtonScanner)} + * @throws IOException + */ + public void removeScanner(ButtonScanner buttonScanner) throws IOException { + if (buttonScanner == null) { + throw new IllegalArgumentException("buttonScanner is null"); + } + if (scanners.remove(buttonScanner.scanId) == null) { + throw new IllegalArgumentException("Button scanner was never added"); + } + + CmdRemoveScanner pkt = new CmdRemoveScanner(); + pkt.scanId = buttonScanner.scanId; + sendPacket(pkt); + } + + /** + * Add a scan wizard. + * + * The scan wizard will start directly once the scan wizard is added. + * + * @param scanWizard + * @throws IOException + */ + public void addScanWizard(ScanWizard scanWizard) throws IOException { + if (scanWizard == null) { + throw new IllegalArgumentException("scanWizard is null"); + } + if (scanWizards.putIfAbsent(scanWizard.scanWizardId, scanWizard) != null) { + throw new IllegalArgumentException("Scan wizard already added"); + } + + CmdCreateScanWizard pkt = new CmdCreateScanWizard(); + pkt.scanWizardId = scanWizard.scanWizardId; + sendPacket(pkt); + } + + /** + * Cancel a scan wizard. + * + * This will cancel an ongoing scan wizard. + * + * If cancelled due to this request, the result of the scan wizard will be WizardCancelledByUser. + * + * @param scanWizard The same scan wizard that was used in {@link #addScanWizard(ScanWizard)} + * @throws IOException + */ + public void cancelScanWizard(ScanWizard scanWizard) throws IOException { + if (scanWizard == null) { + throw new IllegalArgumentException("scanWizard is null"); + } + + CmdCancelScanWizard pkt = new CmdCancelScanWizard(); + pkt.scanWizardId = scanWizard.scanWizardId; + sendPacket(pkt); + } + + /** + * Adds a connection channel to a specific Flic button. + * + * This will start listening for a specific Flic button's connection and button events. + * Make sure the Flic is either in public mode (by holding it down for 7 seconds) or already verified before calling this method. + * + * The {@link ButtonConnectionChannel.Callbacks#onCreateConnectionChannelResponse} + * method will be called after this command has been received by the server. + * + * You may have as many connection channels as you wish for a specific Flic Button. + * + * @param channel + * @throws IOException + */ + public void addConnectionChannel(ButtonConnectionChannel channel) throws IOException { + if (channel == null) { + throw new IllegalArgumentException("channel is null"); + } + if (connectionChannels.putIfAbsent(channel.connId, channel) != null) { + throw new IllegalArgumentException("Connection channel already added"); + } + + synchronized (channel.lock) { + channel.client = this; + + CmdCreateConnectionChannel pkt = new CmdCreateConnectionChannel(); + pkt.connId = channel.connId; + pkt.bdaddr = channel.getBdaddr(); + pkt.latencyMode = channel.getLatencyMode(); + pkt.autoDisconnectTime = channel.getAutoDisconnectTime(); + sendPacket(pkt); + } + } + + /** + * Remove a connection channel. + * + * This will stop listening for new events for a specific connection channel that has previously been added. + * Note: The effect of this command will take place at the time the {@link ButtonConnectionChannel.Callbacks#onRemoved} event arrives. + * + * @param channel + * @throws IOException + */ + public void removeConnectionChannel(ButtonConnectionChannel channel) throws IOException { + if (channel == null) { + throw new IllegalArgumentException("channel is null"); + } + + CmdRemoveConnectionChannel pkt = new CmdRemoveConnectionChannel(); + pkt.connId = channel.connId; + sendPacket(pkt); + } + + /** + * Force disconnection or cancel pending connection of a specific Flic button. + * + * This removes all connection channels for all clients connected to the server for this specific Flic button. + * + * @param bdaddr + * @throws IOException + */ + public void forceDisconnect(Bdaddr bdaddr) throws IOException { + if (bdaddr == null) { + throw new IllegalArgumentException("bdaddr is null"); + } + + CmdForceDisconnect pkt = new CmdForceDisconnect(); + pkt.bdaddr = bdaddr; + sendPacket(pkt); + } + + /** + * Delete a button. + * + * @param bdaddr + * @throws IOException + */ + public void deleteButton(Bdaddr bdaddr) throws IOException { + if (bdaddr == null) { + throw new IllegalArgumentException("bdaddr is null"); + } + + CmdDeleteButton pkt = new CmdDeleteButton(); + pkt.bdaddr = bdaddr; + sendPacket(pkt); + } + + /** + * Add a battery status listener. + * + * @param listener + * @throws IOException + */ + public void addBatteryStatusListener(BatteryStatusListener listener) throws IOException { + if (listener == null) { + throw new IllegalArgumentException("listener is null"); + } + if (batteryStatusListeners.putIfAbsent(listener.listenerId, listener) != null) { + throw new IllegalArgumentException("Battery status listener already added"); + } + + CmdCreateBatteryStatusListener pkt = new CmdCreateBatteryStatusListener(); + pkt.listenerId = listener.listenerId; + pkt.bdaddr = listener.getBdaddr(); + sendPacket(pkt); + } + + /** + * Remove a battery status listener + * + * @param listener + * @throws IOException + */ + public void removeBatteryStatusListener(BatteryStatusListener listener) throws IOException { + if (listener == null) { + throw new IllegalArgumentException("buttonScanner is null"); + } + if (batteryStatusListeners.remove(listener.listenerId) == null) { + throw new IllegalArgumentException("Battery status listener was never added"); + } + + CmdRemoveBatteryStatusListener pkt = new CmdRemoveBatteryStatusListener(); + pkt.listenerId = listener.listenerId; + sendPacket(pkt); + } + + void sendPacket(CommandPacket packet) throws IOException { + byte[] bytes = packet.construct(); + synchronized (socketOutputStream) { + socketOutputStream.write(bytes); + } + } + + /** + * Set a timer. + * + * This timer task will run after the specified timeoutMillis on the thread that handles the events. + * + * @param timeoutMillis + * @param timerTask + * @throws IOException + */ + public void setTimer(int timeoutMillis, TimerTask timerTask) throws IOException { + long pointInTime = System.nanoTime() + timeoutMillis * 1000000L; + while (timers.putIfAbsent(pointInTime, timerTask) != null) { + pointInTime++; + } + if (handleEventsThread != Thread.currentThread()) { + CmdPing pkt = new CmdPing(); + pkt.pingId = 0; + sendPacket(pkt); + } + } + + /** + * Run a task on the thread that handles the events. + * + * @param task + * @throws IOException + */ + public void runOnHandleEventsThread(TimerTask task) throws IOException { + if (handleEventsThread == Thread.currentThread()) { + task.run(); + } else { + setTimer(0, task); + } + } + + /** + * Start the main loop for this client. + * + * This method will not return until the socket has been closed. + * Once it has returned, any use of this FlicClient is illegal. + * + * @throws IOException + */ + public void handleEvents() throws IOException { + handleEventsThread = Thread.currentThread(); + while (true) { + Map.Entry firstTimer = timers.firstEntry(); + long timeout = 0; + if (firstTimer != null) { + timeout = firstTimer.getKey() - System.nanoTime(); + if (timeout <= 0) { + timers.remove(firstTimer.getKey(), firstTimer.getValue()); + firstTimer.getValue().run(); + continue; + } + } + + if (socket.isClosed()) { + break; + } + + int len0; + socket.setSoTimeout((int)(timeout / 1000000)); + try { + len0 = socketInputStream.read(); + } catch (SocketTimeoutException e) { + continue; + } + int len1 = socketInputStream.read(); + int len = len0 | (len1 << 8); + if ((len >> 16) == -1) { + break; + } + if (len == 0) { + continue; + } + byte[] pkt = new byte[len]; + + int pos = 0; + while (pos < len) { + int nbytes = socketInputStream.read(pkt, pos, len - pos); + if (nbytes == -1) { + break; + } + pos += nbytes; + } + if (len == 1) { + continue; + } + dispatchPacket(pkt); + } + socket.close(); + } + + private void dispatchPacket(byte[] packet) throws IOException { + int opcode = packet[0]; + switch (opcode) { + case EventPacket.EVT_ADVERTISEMENT_PACKET_OPCODE: { + EvtAdvertisementPacket pkt = new EvtAdvertisementPacket(); + pkt.parse(packet); + ButtonScanner scanner = scanners.get(pkt.scanId); + if (scanner != null) { + scanner.onAdvertisementPacket(pkt.addr, pkt.name, pkt.rssi, pkt.isPrivate, pkt.alreadyVerified, pkt.alreadyConnectedToThisDevice, pkt.alreadyConnectedToOtherDevice); + } + break; + } + case EventPacket.EVT_CREATE_CONNECTION_CHANNEL_RESPONSE_OPCODE: { + EvtCreateConnectionChannelResponse pkt = new EvtCreateConnectionChannelResponse(); + pkt.parse(packet); + ButtonConnectionChannel channel = connectionChannels.get(pkt.connId); + if (channel != null) { + if (pkt.connectionChannelError != CreateConnectionChannelError.NoError) { + connectionChannels.remove(channel.connId); + } + channel.callbacks.onCreateConnectionChannelResponse(channel, pkt.connectionChannelError, pkt.connectionStatus); + } + break; + } + case EventPacket.EVT_CONNECTION_STATUS_CHANGED_OPCODE: { + EvtConnectionStatusChanged pkt = new EvtConnectionStatusChanged(); + pkt.parse(packet); + ButtonConnectionChannel channel = connectionChannels.get(pkt.connId); + if (channel != null) { + channel.callbacks.onConnectionStatusChanged(channel, pkt.connectionStatus, pkt.disconnectReason); + } + break; + } + case EventPacket.EVT_CONNECTION_CHANNEL_REMOVED_OPCODE: { + EvtConnectionChannelRemoved pkt = new EvtConnectionChannelRemoved(); + pkt.parse(packet); + ButtonConnectionChannel channel = connectionChannels.get(pkt.connId); + if (channel != null) { + connectionChannels.remove(channel.connId); + channel.callbacks.onRemoved(channel, pkt.removedReason); + } + break; + } + case EventPacket.EVT_BUTTON_UP_OR_DOWN_OPCODE: + case EventPacket.EVT_BUTTON_CLICK_OR_HOLD_OPCODE: + case EventPacket.EVT_BUTTON_SINGLE_OR_DOUBLE_CLICK_OPCODE: + case EventPacket.EVT_BUTTON_SINGLE_OR_DOUBLE_CLICK_OR_HOLD_OPCODE: { + EvtButtonEvent pkt = new EvtButtonEvent(); + pkt.parse(packet); + ButtonConnectionChannel channel = connectionChannels.get(pkt.connId); + if (channel != null) { + if (opcode == EventPacket.EVT_BUTTON_UP_OR_DOWN_OPCODE) { + channel.callbacks.onButtonUpOrDown(channel, pkt.clickType, pkt.wasQueued, pkt.timeDiff); + } else if (opcode == EventPacket.EVT_BUTTON_CLICK_OR_HOLD_OPCODE) { + channel.callbacks.onButtonClickOrHold(channel, pkt.clickType, pkt.wasQueued, pkt.timeDiff); + } else if (opcode == EventPacket.EVT_BUTTON_SINGLE_OR_DOUBLE_CLICK_OPCODE) { + channel.callbacks.onButtonSingleOrDoubleClick(channel, pkt.clickType, pkt.wasQueued, pkt.timeDiff); + } else if (opcode == EventPacket.EVT_BUTTON_SINGLE_OR_DOUBLE_CLICK_OR_HOLD_OPCODE) { + channel.callbacks.onButtonSingleOrDoubleClickOrHold(channel, pkt.clickType, pkt.wasQueued, pkt.timeDiff); + } + } + break; + } + case EventPacket.EVT_NEW_VERIFIED_BUTTON_OPCODE: { + EvtNewVerifiedButton pkt = new EvtNewVerifiedButton(); + pkt.parse(packet); + GeneralCallbacks gc = generalCallbacks; + if (gc != null) { + gc.onNewVerifiedButton(pkt.bdaddr); + } + break; + } + case EventPacket.EVT_GET_INFO_RESPONSE_OPCODE: { + EvtGetInfoResponse pkt = new EvtGetInfoResponse(); + pkt.parse(packet); + getInfoResponseCallbackQueue.remove().onGetInfoResponse(pkt.bluetoothControllerState, pkt.myBdAddr, pkt.myBdAddrType, pkt.maxPendingConnections, pkt.maxConcurrentlyConnectedButtons, pkt.currentPendingConnections, pkt.currentlyNoSpaceForNewConnections, pkt.bdAddrOfVerifiedButtons); + break; + } + case EventPacket.EVT_NO_SPACE_FOR_NEW_CONNECTION_OPCODE: { + EvtNoSpaceForNewConnection pkt = new EvtNoSpaceForNewConnection(); + pkt.parse(packet); + GeneralCallbacks gc = generalCallbacks; + if (gc != null) { + gc.onNoSpaceForNewConnection(pkt.maxConcurrentlyConnectedButtons); + } + break; + } + case EventPacket.EVT_GOT_SPACE_FOR_NEW_CONNECTION_OPCODE: { + EvtGotSpaceForNewConnection pkt = new EvtGotSpaceForNewConnection(); + pkt.parse(packet); + GeneralCallbacks gc = generalCallbacks; + if (gc != null) { + gc.onGotSpaceForNewConnection(pkt.maxConcurrentlyConnectedButtons); + } + break; + } + case EventPacket.EVT_BLUETOOTH_CONTROLLER_STATE_CHANGE_OPCODE: { + EvtBluetoothControllerStateChange pkt = new EvtBluetoothControllerStateChange(); + pkt.parse(packet); + GeneralCallbacks gc = generalCallbacks; + if (gc != null) { + gc.onBluetoothControllerStateChange(pkt.state); + } + break; + } + case EventPacket.EVT_GET_BUTTON_INFO_RESPONSE_OPCODE: { + EvtGetButtonInfoResponse pkt = new EvtGetButtonInfoResponse(); + pkt.parse(packet); + getButtonInfoResponseCallbackQueue.remove().onGetButtonInfoResponse(pkt.bdaddr, pkt.uuid, pkt.color, pkt.serialNumber); + break; + } + case EventPacket.EVT_SCAN_WIZARD_FOUND_PRIVATE_BUTTON_OPCODE: { + EvtScanWizardFoundPrivateButton pkt = new EvtScanWizardFoundPrivateButton(); + pkt.parse(packet); + ScanWizard wizard = scanWizards.get(pkt.scanWizardId); + if (wizard != null) { + wizard.onFoundPrivateButton(); + } + break; + } + case EventPacket.EVT_SCAN_WIZARD_FOUND_PUBLIC_BUTTON_OPCODE: { + EvtScanWizardFoundPublicButton pkt = new EvtScanWizardFoundPublicButton(); + pkt.parse(packet); + ScanWizard wizard = scanWizards.get(pkt.scanWizardId); + if (wizard != null) { + wizard.bdaddr = pkt.addr; + wizard.name = pkt.name; + wizard.onFoundPublicButton(wizard.bdaddr, wizard.name); + } + break; + } + case EventPacket.EVT_SCAN_WIZARD_BUTTON_CONNECTED_OPCODE: { + EvtScanWizardButtonConnected pkt = new EvtScanWizardButtonConnected(); + pkt.parse(packet); + ScanWizard wizard = scanWizards.get(pkt.scanWizardId); + if (wizard != null) { + wizard.onButtonConnected(wizard.bdaddr, wizard.name); + } + break; + } + case EventPacket.EVT_SCAN_WIZARD_COMPLETED_OPCODE: { + EvtScanWizardCompleted pkt = new EvtScanWizardCompleted(); + pkt.parse(packet); + ScanWizard wizard = scanWizards.get(pkt.scanWizardId); + scanWizards.remove(pkt.scanWizardId); + if (wizard != null) { + Bdaddr bdaddr = wizard.bdaddr; + String name = wizard.name; + wizard.bdaddr = null; + wizard.name = null; + wizard.onCompleted(pkt.result, bdaddr, name); + } + break; + } + case EventPacket.EVT_BUTTON_DELETED_OPCODE: { + EvtButtonDeleted pkt = new EvtButtonDeleted(); + pkt.parse(packet); + GeneralCallbacks gc = generalCallbacks; + if (gc != null) { + gc.onButtonDeleted(pkt.bdaddr, pkt.deletedByThisClient); + } + break; + } + case EventPacket.EVT_BATTERY_STATUS_OPCODE: { + EvtBatteryStatus pkt = new EvtBatteryStatus(); + pkt.parse(packet); + BatteryStatusListener listener = batteryStatusListeners.get(pkt.listenerId); + if (listener != null) { + listener.callbacks.onBatteryStatus(listener.getBdaddr(), pkt.batteryPercentage, pkt.timestamp); + } + break; + } + } + } +} diff --git a/bundles/org.openhab.binding.flicbutton/src/3rdparty/java/io/flic/fliclib/javaclient/GeneralCallbacks.java b/bundles/org.openhab.binding.flicbutton/src/3rdparty/java/io/flic/fliclib/javaclient/GeneralCallbacks.java new file mode 100644 index 0000000000000..77399d7aa382b --- /dev/null +++ b/bundles/org.openhab.binding.flicbutton/src/3rdparty/java/io/flic/fliclib/javaclient/GeneralCallbacks.java @@ -0,0 +1,28 @@ +package io.flic.fliclib.javaclient; + +import io.flic.fliclib.javaclient.enums.BluetoothControllerState; + +import java.io.IOException; + +/** + * GeneralCallbacks. + * + * See the protocol specification for further details. + */ +public class GeneralCallbacks { + public void onNewVerifiedButton(Bdaddr bdaddr) throws IOException { + + } + public void onNoSpaceForNewConnection(int maxConcurrentlyConnectedButtons) throws IOException { + + } + public void onGotSpaceForNewConnection(int maxConcurrentlyConnectedButtons) throws IOException { + + } + public void onBluetoothControllerStateChange(BluetoothControllerState state) throws IOException { + + } + public void onButtonDeleted(Bdaddr bdaddr, boolean deletedByThisClient) throws IOException { + + } +} diff --git a/bundles/org.openhab.binding.flicbutton/src/3rdparty/java/io/flic/fliclib/javaclient/GetButtonInfoResponseCallback.java b/bundles/org.openhab.binding.flicbutton/src/3rdparty/java/io/flic/fliclib/javaclient/GetButtonInfoResponseCallback.java new file mode 100644 index 0000000000000..740f8dd0b4204 --- /dev/null +++ b/bundles/org.openhab.binding.flicbutton/src/3rdparty/java/io/flic/fliclib/javaclient/GetButtonInfoResponseCallback.java @@ -0,0 +1,18 @@ +package io.flic.fliclib.javaclient; + +/** + * GetButtonInfoResponseCallback. + * + * Used in {@link FlicClient#getButtonInfo(Bdaddr, GetButtonInfoResponseCallback)}. + */ +public abstract class GetButtonInfoResponseCallback { + /** + * Called upon response. + * + * @param bdaddr Bluetooth address + * @param uuid Uuid of button, might be null if unknown + * @param color Color of button, might be null if unknown + * @param serialNumber Serial number of the button, will be null if the button is not found + */ + public abstract void onGetButtonInfoResponse(Bdaddr bdaddr, String uuid, String color, String serialNumber); +} diff --git a/bundles/org.openhab.binding.flicbutton/src/3rdparty/java/io/flic/fliclib/javaclient/GetInfoResponseCallback.java b/bundles/org.openhab.binding.flicbutton/src/3rdparty/java/io/flic/fliclib/javaclient/GetInfoResponseCallback.java new file mode 100644 index 0000000000000..642a356658346 --- /dev/null +++ b/bundles/org.openhab.binding.flicbutton/src/3rdparty/java/io/flic/fliclib/javaclient/GetInfoResponseCallback.java @@ -0,0 +1,19 @@ +package io.flic.fliclib.javaclient; + +import io.flic.fliclib.javaclient.enums.BdAddrType; +import io.flic.fliclib.javaclient.enums.BluetoothControllerState; + +import java.io.IOException; + +/** + * GetInfoResponseCallback. + * + * Used in {@link FlicClient#getInfo(GetInfoResponseCallback)}. + */ +public abstract class GetInfoResponseCallback { + public abstract void onGetInfoResponse(BluetoothControllerState bluetoothControllerState, Bdaddr myBdAddr, + BdAddrType myBdAddrType, int maxPendingConnections, + int maxConcurrentlyConnectedButtons, int currentPendingConnections, + boolean currentlyNoSpaceForNewConnection, + Bdaddr[] verifiedButtons) throws IOException; +} diff --git a/bundles/org.openhab.binding.flicbutton/src/3rdparty/java/io/flic/fliclib/javaclient/Packets.java b/bundles/org.openhab.binding.flicbutton/src/3rdparty/java/io/flic/fliclib/javaclient/Packets.java new file mode 100644 index 0000000000000..7cdcf011c9d5d --- /dev/null +++ b/bundles/org.openhab.binding.flicbutton/src/3rdparty/java/io/flic/fliclib/javaclient/Packets.java @@ -0,0 +1,455 @@ +package io.flic.fliclib.javaclient; + +import java.io.*; +import java.nio.charset.StandardCharsets; + +import io.flic.fliclib.javaclient.enums.*; + +/** + * Flic Protocol Packets + */ + +abstract class CommandPacket { + protected int opcode; + + public final byte[] construct() { + ByteArrayOutputStream stream = new ByteArrayOutputStream(); + try { + write(stream); + } catch (IOException e) { + } + byte[] res = new byte[3 + stream.size()]; + res[0] = (byte)(1 + stream.size()); + res[1] = (byte)((1 + stream.size()) >> 8); + res[2] = (byte)opcode; + System.arraycopy(stream.toByteArray(), 0, res, 3, stream.size()); + return res; + } + + abstract protected void write(OutputStream stream) throws IOException; +} + +class CmdGetInfo extends CommandPacket { + @Override + protected void write(OutputStream stream) { + opcode = 0; + } +} + +class CmdCreateScanner extends CommandPacket { + public int scanId; + + @Override + protected void write(OutputStream stream) throws IOException { + opcode = 1; + StreamUtils.writeInt32(stream, scanId); + } +} + +class CmdRemoveScanner extends CommandPacket { + public int scanId; + + @Override + protected void write(OutputStream stream) throws IOException { + opcode = 2; + StreamUtils.writeInt32(stream, scanId); + } +} + +class CmdCreateConnectionChannel extends CommandPacket { + public int connId; + public Bdaddr bdaddr; + public LatencyMode latencyMode; + public short autoDisconnectTime; + + @Override + protected void write(OutputStream stream) throws IOException { + opcode = 3; + StreamUtils.writeInt32(stream, connId); + StreamUtils.writeBdaddr(stream, bdaddr); + StreamUtils.writeEnum(stream, latencyMode); + StreamUtils.writeInt16(stream, autoDisconnectTime); + } +} + +class CmdRemoveConnectionChannel extends CommandPacket { + public int connId; + + @Override + protected void write(OutputStream stream) throws IOException { + opcode = 4; + StreamUtils.writeInt32(stream, connId); + } +} + +class CmdForceDisconnect extends CommandPacket { + public Bdaddr bdaddr; + + @Override + protected void write(OutputStream stream) throws IOException { + opcode = 5; + StreamUtils.writeBdaddr(stream, bdaddr); + } +} + +class CmdChangeModeParameters extends CommandPacket { + public int connId; + public LatencyMode latencyMode; + public short autoDisconnectTime; + + @Override + protected void write(OutputStream stream) throws IOException { + opcode = 6; + StreamUtils.writeInt32(stream, connId); + StreamUtils.writeEnum(stream, latencyMode); + StreamUtils.writeInt16(stream, autoDisconnectTime); + } +} + +class CmdPing extends CommandPacket { + public int pingId; + + @Override + protected void write(OutputStream stream) throws IOException { + opcode = 7; + StreamUtils.writeInt32(stream, pingId); + } +} + +class CmdGetButtonInfo extends CommandPacket { + public Bdaddr bdaddr; + + @Override + protected void write(OutputStream stream) throws IOException { + opcode = 8; + StreamUtils.writeBdaddr(stream, bdaddr); + } +} + +class CmdCreateScanWizard extends CommandPacket { + public int scanWizardId; + + @Override + protected void write(OutputStream stream) throws IOException { + opcode = 9; + StreamUtils.writeInt32(stream, scanWizardId); + } +} + +class CmdCancelScanWizard extends CommandPacket { + public int scanWizardId; + + @Override + protected void write(OutputStream stream) throws IOException { + opcode = 10; + StreamUtils.writeInt32(stream, scanWizardId); + } +} + +class CmdDeleteButton extends CommandPacket { + public Bdaddr bdaddr; + + @Override + protected void write(OutputStream stream) throws IOException { + opcode = 11; + StreamUtils.writeBdaddr(stream, bdaddr); + } +} + +class CmdCreateBatteryStatusListener extends CommandPacket { + public int listenerId; + public Bdaddr bdaddr; + + @Override + protected void write(OutputStream stream) throws IOException { + opcode = 12; + StreamUtils.writeInt32(stream, listenerId); + StreamUtils.writeBdaddr(stream, bdaddr); + } +} + +class CmdRemoveBatteryStatusListener extends CommandPacket { + public int listenerId; + + @Override + protected void write(OutputStream stream) throws IOException { + opcode = 13; + StreamUtils.writeInt32(stream, listenerId); + } +} + +abstract class EventPacket { + public static final int EVT_ADVERTISEMENT_PACKET_OPCODE = 0; + public static final int EVT_CREATE_CONNECTION_CHANNEL_RESPONSE_OPCODE = 1; + public static final int EVT_CONNECTION_STATUS_CHANGED_OPCODE = 2; + public static final int EVT_CONNECTION_CHANNEL_REMOVED_OPCODE = 3; + public static final int EVT_BUTTON_UP_OR_DOWN_OPCODE = 4; + public static final int EVT_BUTTON_CLICK_OR_HOLD_OPCODE = 5; + public static final int EVT_BUTTON_SINGLE_OR_DOUBLE_CLICK_OPCODE = 6; + public static final int EVT_BUTTON_SINGLE_OR_DOUBLE_CLICK_OR_HOLD_OPCODE = 7; + public static final int EVT_NEW_VERIFIED_BUTTON_OPCODE = 8; + public static final int EVT_GET_INFO_RESPONSE_OPCODE = 9; + public static final int EVT_NO_SPACE_FOR_NEW_CONNECTION_OPCODE = 10; + public static final int EVT_GOT_SPACE_FOR_NEW_CONNECTION_OPCODE = 11; + public static final int EVT_BLUETOOTH_CONTROLLER_STATE_CHANGE_OPCODE = 12; + public static final int EVT_PING_RESPONSE_OPCODE = 13; + public static final int EVT_GET_BUTTON_INFO_RESPONSE_OPCODE = 14; + public static final int EVT_SCAN_WIZARD_FOUND_PRIVATE_BUTTON_OPCODE = 15; + public static final int EVT_SCAN_WIZARD_FOUND_PUBLIC_BUTTON_OPCODE = 16; + public static final int EVT_SCAN_WIZARD_BUTTON_CONNECTED_OPCODE = 17; + public static final int EVT_SCAN_WIZARD_COMPLETED_OPCODE = 18; + public static final int EVT_BUTTON_DELETED_OPCODE = 19; + public static final int EVT_BATTERY_STATUS_OPCODE = 20; + + public void parse(byte[] arr) { + InputStream stream = new ByteArrayInputStream(arr); + try { + stream.skip(1); + parseInternal(stream); + } catch(IOException e) { + } + } + + abstract protected void parseInternal(InputStream stream) throws IOException; +} + +class EvtAdvertisementPacket extends EventPacket { + public int scanId; + public Bdaddr addr; + public String name; + public int rssi; + public boolean isPrivate; + public boolean alreadyVerified; + public boolean alreadyConnectedToThisDevice; + public boolean alreadyConnectedToOtherDevice; + + @Override + protected void parseInternal(InputStream stream) throws IOException { + scanId = StreamUtils.getInt32(stream); + addr = StreamUtils.getBdaddr(stream); + name = StreamUtils.getString(stream, 16); + rssi = StreamUtils.getInt8(stream); + isPrivate = StreamUtils.getBoolean(stream); + alreadyVerified = StreamUtils.getBoolean(stream); + alreadyConnectedToThisDevice = StreamUtils.getBoolean(stream); + alreadyConnectedToOtherDevice = StreamUtils.getBoolean(stream); + } +} + +class EvtCreateConnectionChannelResponse extends EventPacket { + public int connId; + public CreateConnectionChannelError connectionChannelError; + public ConnectionStatus connectionStatus; + + @Override + protected void parseInternal(InputStream stream) throws IOException { + connId = StreamUtils.getInt32(stream); + connectionChannelError = CreateConnectionChannelError.values()[StreamUtils.getUInt8(stream)]; + connectionStatus = ConnectionStatus.values()[StreamUtils.getUInt8(stream)]; + } +} + +class EvtConnectionStatusChanged extends EventPacket { + public int connId; + public ConnectionStatus connectionStatus; + public DisconnectReason disconnectReason; + + @Override + protected void parseInternal(InputStream stream) throws IOException { + connId = StreamUtils.getInt32(stream); + connectionStatus = ConnectionStatus.values()[StreamUtils.getUInt8(stream)]; + disconnectReason = DisconnectReason.values()[StreamUtils.getUInt8(stream)]; + } +} + +class EvtConnectionChannelRemoved extends EventPacket { + public int connId; + public RemovedReason removedReason; + + @Override + protected void parseInternal(InputStream stream) throws IOException { + connId = StreamUtils.getInt32(stream); + removedReason = RemovedReason.values()[StreamUtils.getUInt8(stream)]; + } +} + +class EvtButtonEvent extends EventPacket { + public int connId; + public ClickType clickType; + public boolean wasQueued; + public int timeDiff; + + @Override + protected void parseInternal(InputStream stream) throws IOException { + connId = StreamUtils.getInt32(stream); + clickType = ClickType.values()[StreamUtils.getUInt8(stream)]; + wasQueued = StreamUtils.getBoolean(stream); + timeDiff = StreamUtils.getInt32(stream); + } +} + +class EvtNewVerifiedButton extends EventPacket { + public Bdaddr bdaddr; + + @Override + protected void parseInternal(InputStream stream) throws IOException { + bdaddr = StreamUtils.getBdaddr(stream); + } +} + +class EvtGetInfoResponse extends EventPacket { + public BluetoothControllerState bluetoothControllerState; + public Bdaddr myBdAddr; + public BdAddrType myBdAddrType; + public int maxPendingConnections; + public int maxConcurrentlyConnectedButtons; + public int currentPendingConnections; + public boolean currentlyNoSpaceForNewConnections; + public Bdaddr[] bdAddrOfVerifiedButtons; + + @Override + protected void parseInternal(InputStream stream) throws IOException { + bluetoothControllerState = BluetoothControllerState.values()[StreamUtils.getUInt8(stream)]; + myBdAddr = StreamUtils.getBdaddr(stream); + myBdAddrType = BdAddrType.values()[StreamUtils.getUInt8(stream)]; + maxPendingConnections = StreamUtils.getUInt8(stream); + maxConcurrentlyConnectedButtons = StreamUtils.getInt16(stream); + currentPendingConnections = StreamUtils.getUInt8(stream); + currentlyNoSpaceForNewConnections = StreamUtils.getBoolean(stream); + int nbVerifiedButtons = StreamUtils.getUInt16(stream); + bdAddrOfVerifiedButtons = new Bdaddr[nbVerifiedButtons]; + for (int i = 0; i < nbVerifiedButtons; i++) { + bdAddrOfVerifiedButtons[i] = StreamUtils.getBdaddr(stream); + } + } +} + +class EvtNoSpaceForNewConnection extends EventPacket { + public int maxConcurrentlyConnectedButtons; + + @Override + protected void parseInternal(InputStream stream) throws IOException { + maxConcurrentlyConnectedButtons = StreamUtils.getUInt8(stream); + } +} + +class EvtGotSpaceForNewConnection extends EventPacket { + public int maxConcurrentlyConnectedButtons; + + @Override + protected void parseInternal(InputStream stream) throws IOException { + maxConcurrentlyConnectedButtons = StreamUtils.getUInt8(stream); + } +} + +class EvtBluetoothControllerStateChange extends EventPacket { + public BluetoothControllerState state; + + @Override + protected void parseInternal(InputStream stream) throws IOException { + state = BluetoothControllerState.values()[StreamUtils.getUInt8(stream)]; + } +} + +class EvtGetButtonInfoResponse extends EventPacket { + public Bdaddr bdaddr; + public String uuid; + public String color; + public String serialNumber; + + @Override + protected void parseInternal(InputStream stream) throws IOException { + bdaddr = StreamUtils.getBdaddr(stream); + byte[] uuidBytes = StreamUtils.getByteArr(stream, 16); + StringBuilder sb = new StringBuilder(32); + for (int i = 0; i < 16; i++) { + sb.append(String.format("%02x", uuidBytes[i])); + } + uuid = sb.toString(); + if (uuid.equals("00000000000000000000000000000000")) { + uuid = null; + } + color = StreamUtils.getString(stream, 16); + if (color.isEmpty()) { + color = null; + } + serialNumber = StreamUtils.getString(stream, 16); + if (serialNumber.isEmpty()) { + serialNumber = null; + } + } +} + +class EvtScanWizardFoundPrivateButton extends EventPacket { + public int scanWizardId; + + @Override + protected void parseInternal(InputStream stream) throws IOException { + scanWizardId = StreamUtils.getInt32(stream); + } +} + +class EvtScanWizardFoundPublicButton extends EventPacket { + public int scanWizardId; + public Bdaddr addr; + public String name; + + @Override + protected void parseInternal(InputStream stream) throws IOException { + scanWizardId = StreamUtils.getInt32(stream); + addr = StreamUtils.getBdaddr(stream); + int nameLen = StreamUtils.getUInt8(stream); + byte[] bytes = new byte[nameLen]; + for (int i = 0; i < nameLen; i++) { + bytes[i] = (byte)stream.read(); + } + for (int i = nameLen; i < 16; i++) { + stream.skip(1); + } + name = new String(bytes, StandardCharsets.UTF_8); + } +} + +class EvtScanWizardButtonConnected extends EventPacket { + public int scanWizardId; + + @Override + protected void parseInternal(InputStream stream) throws IOException { + scanWizardId = StreamUtils.getInt32(stream); + } +} + +class EvtScanWizardCompleted extends EventPacket { + public int scanWizardId; + public ScanWizardResult result; + + @Override + protected void parseInternal(InputStream stream) throws IOException { + scanWizardId = StreamUtils.getInt32(stream); + result = ScanWizardResult.values()[StreamUtils.getUInt8(stream)]; + } +} + +class EvtButtonDeleted extends EventPacket { + public Bdaddr bdaddr; + public boolean deletedByThisClient; + + @Override + protected void parseInternal(InputStream stream) throws IOException { + bdaddr = StreamUtils.getBdaddr(stream); + deletedByThisClient = StreamUtils.getBoolean(stream); + } +} + +class EvtBatteryStatus extends EventPacket { + public int listenerId; + public int batteryPercentage; + public long timestamp; + + @Override + protected void parseInternal(InputStream stream) throws IOException { + listenerId = StreamUtils.getInt32(stream); + batteryPercentage = StreamUtils.getInt8(stream); + timestamp = StreamUtils.getInt64(stream); + } +} diff --git a/bundles/org.openhab.binding.flicbutton/src/3rdparty/java/io/flic/fliclib/javaclient/ScanWizard.java b/bundles/org.openhab.binding.flicbutton/src/3rdparty/java/io/flic/fliclib/javaclient/ScanWizard.java new file mode 100644 index 0000000000000..3e573f6bbe18d --- /dev/null +++ b/bundles/org.openhab.binding.flicbutton/src/3rdparty/java/io/flic/fliclib/javaclient/ScanWizard.java @@ -0,0 +1,64 @@ +package io.flic.fliclib.javaclient; + +import java.io.IOException; +import java.util.concurrent.atomic.AtomicInteger; + +import io.flic.fliclib.javaclient.enums.ScanWizardResult; + +/** + * Scan wizard class. + * + * This class will scan for a new button and pair it automatically. + * There are internal timeouts that make sure operations don't take too long time. + * + * Inherit this class and override the methods. + * Then add this scan wizard to a {@link FlicClient} using {@link FlicClient#addScanWizard(ScanWizard)} to start it. + * You can cancel by calling {@link FlicClient#cancelScanWizard(ScanWizard)}. + */ +public abstract class ScanWizard { + private static AtomicInteger nextId = new AtomicInteger(); + int scanWizardId = nextId.getAndIncrement(); + Bdaddr bdaddr; + String name; + + /** + * This will be called once if a private button is found. + * + * Tell the user to hold down the button for 7 seconds in order to make it public. + * + */ + public abstract void onFoundPrivateButton() throws IOException; + + /** + * This will be called once a public button is found. + * + * Now a connection attempt will be made to the device in order to pair and verify it. + * + * @param bdaddr Bluetooth Device Address + * @param name Advertising name + */ + public abstract void onFoundPublicButton(Bdaddr bdaddr, String name) throws IOException; + + /** + * This will be called once the bluetooth connection has been established. + * + * Now a pair attempt will be made. + * + * @param bdaddr Bluetooth Device Address + * @param name Advertising name + */ + public abstract void onButtonConnected(Bdaddr bdaddr, String name) throws IOException; + + /** + * Scan wizard completed. + * + * If the result is success, you can now create a connection channel to the button. + * + * The ScanWizard is now detached from the FlicClient and can now be recycled. + * + * @param result Result of the scan wizard + * @param bdaddr Bluetooth Device Address or null, depending on if {@link #onFoundPublicButton} has been called or not + * @param name Advertising name or null, depending on if {@link #onFoundPublicButton} has been called or not + */ + public abstract void onCompleted(ScanWizardResult result, Bdaddr bdaddr, String name) throws IOException; +} diff --git a/bundles/org.openhab.binding.flicbutton/src/3rdparty/java/io/flic/fliclib/javaclient/StreamUtils.java b/bundles/org.openhab.binding.flicbutton/src/3rdparty/java/io/flic/fliclib/javaclient/StreamUtils.java new file mode 100644 index 0000000000000..0db0ededd8e73 --- /dev/null +++ b/bundles/org.openhab.binding.flicbutton/src/3rdparty/java/io/flic/fliclib/javaclient/StreamUtils.java @@ -0,0 +1,81 @@ +package io.flic.fliclib.javaclient; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.charset.StandardCharsets; + +class StreamUtils { + public static boolean getBoolean(InputStream stream) throws IOException { + return stream.read() != 0; + } + public static int getUInt8(InputStream stream) throws IOException { + return stream.read(); + } + + public static int getInt8(InputStream stream) throws IOException { + return (byte)stream.read(); + } + + public static int getUInt16(InputStream stream) throws IOException { + return stream.read() | (stream.read() << 8); + } + + public static int getInt16(InputStream stream) throws IOException { + return (short)getUInt16(stream); + } + + public static int getInt32(InputStream stream) throws IOException { + return stream.read() | (stream.read() << 8) | (stream.read() << 16) | (stream.read() << 24); + } + + public static long getInt64(InputStream stream) throws IOException { + return (getInt32(stream) & 0xffffffffL) | ((long)getInt32(stream) << 32); + } + + public static Bdaddr getBdaddr(InputStream stream) throws IOException { + return new Bdaddr(stream); + } + + public static byte[] getByteArr(InputStream stream, int len) throws IOException { + byte[] arr = new byte[len]; + for (int i = 0; i < len; i++) { + arr[i] = (byte)stream.read(); + } + return arr; + } + + public static String getString(InputStream stream, int maxlen) throws IOException { + int len = getInt8(stream); + byte[] arr = new byte[len]; + for (int i = 0; i < len; i++) { + arr[i] = (byte)stream.read(); + } + for (int i = len; i < maxlen; i++) { + stream.skip(1); + } + return new String(arr, StandardCharsets.UTF_8); + } + + public static void writeEnum(OutputStream stream, Enum enumValue) throws IOException { + stream.write(enumValue.ordinal()); + } + + public static void writeInt8(OutputStream stream, int v) throws IOException { + stream.write(v); + } + + public static void writeInt16(OutputStream stream, int v) throws IOException { + stream.write(v & 0xff); + stream.write(v >> 8); + } + + public static void writeInt32(OutputStream stream, int v) throws IOException { + writeInt16(stream, v); + writeInt16(stream, v >> 16); + } + + public static void writeBdaddr(OutputStream stream, Bdaddr addr) throws IOException { + stream.write(addr.getBytes()); + } +} diff --git a/bundles/org.openhab.binding.flicbutton/src/3rdparty/java/io/flic/fliclib/javaclient/TimerTask.java b/bundles/org.openhab.binding.flicbutton/src/3rdparty/java/io/flic/fliclib/javaclient/TimerTask.java new file mode 100644 index 0000000000000..8ed0919d2edf6 --- /dev/null +++ b/bundles/org.openhab.binding.flicbutton/src/3rdparty/java/io/flic/fliclib/javaclient/TimerTask.java @@ -0,0 +1,14 @@ +package io.flic.fliclib.javaclient; + +import java.io.IOException; + +/** + * TimerTask. + * + * Use this interface instead of {@link Runnable} to avoid having to deal with IOExceptions. + * Invocations of the run method on this interface from the {@link FlicClient} will propagate IOExceptions to the caller of {@link FlicClient#handleEvents()}. + * + */ +public interface TimerTask { + void run() throws IOException; +} diff --git a/bundles/org.openhab.binding.flicbutton/src/3rdparty/java/io/flic/fliclib/javaclient/enums/BdAddrType.java b/bundles/org.openhab.binding.flicbutton/src/3rdparty/java/io/flic/fliclib/javaclient/enums/BdAddrType.java new file mode 100644 index 0000000000000..650e719ce8104 --- /dev/null +++ b/bundles/org.openhab.binding.flicbutton/src/3rdparty/java/io/flic/fliclib/javaclient/enums/BdAddrType.java @@ -0,0 +1,9 @@ +package io.flic.fliclib.javaclient.enums; + +/** + * Created by Emil on 2016-05-03. + */ +public enum BdAddrType { + PublicBdAddrType, + RandomBdAddrType +} diff --git a/bundles/org.openhab.binding.flicbutton/src/3rdparty/java/io/flic/fliclib/javaclient/enums/BluetoothControllerState.java b/bundles/org.openhab.binding.flicbutton/src/3rdparty/java/io/flic/fliclib/javaclient/enums/BluetoothControllerState.java new file mode 100644 index 0000000000000..24ee268192204 --- /dev/null +++ b/bundles/org.openhab.binding.flicbutton/src/3rdparty/java/io/flic/fliclib/javaclient/enums/BluetoothControllerState.java @@ -0,0 +1,10 @@ +package io.flic.fliclib.javaclient.enums; + +/** + * Created by Emil on 2016-05-03. + */ +public enum BluetoothControllerState { + Detached, + Resetting, + Attached +} diff --git a/bundles/org.openhab.binding.flicbutton/src/3rdparty/java/io/flic/fliclib/javaclient/enums/ClickType.java b/bundles/org.openhab.binding.flicbutton/src/3rdparty/java/io/flic/fliclib/javaclient/enums/ClickType.java new file mode 100644 index 0000000000000..d1a767b705b79 --- /dev/null +++ b/bundles/org.openhab.binding.flicbutton/src/3rdparty/java/io/flic/fliclib/javaclient/enums/ClickType.java @@ -0,0 +1,13 @@ +package io.flic.fliclib.javaclient.enums; + +/** + * Created by Emil on 2016-05-03. + */ +public enum ClickType { + ButtonDown, + ButtonUp, + ButtonClick, + ButtonSingleClick, + ButtonDoubleClick, + ButtonHold +} diff --git a/bundles/org.openhab.binding.flicbutton/src/3rdparty/java/io/flic/fliclib/javaclient/enums/ConnectionStatus.java b/bundles/org.openhab.binding.flicbutton/src/3rdparty/java/io/flic/fliclib/javaclient/enums/ConnectionStatus.java new file mode 100644 index 0000000000000..ad0673ad5fc26 --- /dev/null +++ b/bundles/org.openhab.binding.flicbutton/src/3rdparty/java/io/flic/fliclib/javaclient/enums/ConnectionStatus.java @@ -0,0 +1,10 @@ +package io.flic.fliclib.javaclient.enums; + +/** + * Created by Emil on 2016-05-03. + */ +public enum ConnectionStatus { + Disconnected, + Connected, + Ready +} diff --git a/bundles/org.openhab.binding.flicbutton/src/3rdparty/java/io/flic/fliclib/javaclient/enums/CreateConnectionChannelError.java b/bundles/org.openhab.binding.flicbutton/src/3rdparty/java/io/flic/fliclib/javaclient/enums/CreateConnectionChannelError.java new file mode 100644 index 0000000000000..aa78274ecd547 --- /dev/null +++ b/bundles/org.openhab.binding.flicbutton/src/3rdparty/java/io/flic/fliclib/javaclient/enums/CreateConnectionChannelError.java @@ -0,0 +1,9 @@ +package io.flic.fliclib.javaclient.enums; + +/** + * Created by Emil on 2016-05-03. + */ +public enum CreateConnectionChannelError { + NoError, + MaxPendingConnectionsReached +} diff --git a/bundles/org.openhab.binding.flicbutton/src/3rdparty/java/io/flic/fliclib/javaclient/enums/DisconnectReason.java b/bundles/org.openhab.binding.flicbutton/src/3rdparty/java/io/flic/fliclib/javaclient/enums/DisconnectReason.java new file mode 100644 index 0000000000000..a875a725ca68b --- /dev/null +++ b/bundles/org.openhab.binding.flicbutton/src/3rdparty/java/io/flic/fliclib/javaclient/enums/DisconnectReason.java @@ -0,0 +1,11 @@ +package io.flic.fliclib.javaclient.enums; + +/** + * Created by Emil on 2016-05-03. + */ +public enum DisconnectReason { + Unspecified, + ConnectionEstablishmentFailed, + TimedOut, + BondingKeysMismatch +} diff --git a/bundles/org.openhab.binding.flicbutton/src/3rdparty/java/io/flic/fliclib/javaclient/enums/LatencyMode.java b/bundles/org.openhab.binding.flicbutton/src/3rdparty/java/io/flic/fliclib/javaclient/enums/LatencyMode.java new file mode 100644 index 0000000000000..135693f5d2983 --- /dev/null +++ b/bundles/org.openhab.binding.flicbutton/src/3rdparty/java/io/flic/fliclib/javaclient/enums/LatencyMode.java @@ -0,0 +1,10 @@ +package io.flic.fliclib.javaclient.enums; + +/** + * Created by Emil on 2016-05-03. + */ +public enum LatencyMode { + NormalLatency, + LowLatency, + HighLatency +} diff --git a/bundles/org.openhab.binding.flicbutton/src/3rdparty/java/io/flic/fliclib/javaclient/enums/RemovedReason.java b/bundles/org.openhab.binding.flicbutton/src/3rdparty/java/io/flic/fliclib/javaclient/enums/RemovedReason.java new file mode 100644 index 0000000000000..48bc410f6bb68 --- /dev/null +++ b/bundles/org.openhab.binding.flicbutton/src/3rdparty/java/io/flic/fliclib/javaclient/enums/RemovedReason.java @@ -0,0 +1,22 @@ +package io.flic.fliclib.javaclient.enums; + +/** + * Created by Emil on 2016-05-03. + */ +public enum RemovedReason { + RemovedByThisClient, + ForceDisconnectedByThisClient, + ForceDisconnectedByOtherClient, + + ButtonIsPrivate, + VerifyTimeout, + InternetBackendError, + InvalidData, + + CouldntLoadDevice, + + DeletedByThisClient, + DeletedByOtherClient, + ButtonBelongsToOtherPartner, + DeletedFromButton +} diff --git a/bundles/org.openhab.binding.flicbutton/src/3rdparty/java/io/flic/fliclib/javaclient/enums/ScanWizardResult.java b/bundles/org.openhab.binding.flicbutton/src/3rdparty/java/io/flic/fliclib/javaclient/enums/ScanWizardResult.java new file mode 100644 index 0000000000000..e31582a98a182 --- /dev/null +++ b/bundles/org.openhab.binding.flicbutton/src/3rdparty/java/io/flic/fliclib/javaclient/enums/ScanWizardResult.java @@ -0,0 +1,13 @@ +package io.flic.fliclib.javaclient.enums; + +public enum ScanWizardResult { + WizardSuccess, + WizardCancelledByUser, + WizardFailedTimeout, + WizardButtonIsPrivate, + WizardBluetoothUnavailable, + WizardInternetBackendError, + WizardInvalidData, + WizardButtonBelongsToOtherPartner, + WizardButtonAlreadyConnectedToOtherDevice +} diff --git a/bundles/org.openhab.binding.flicbutton/src/main/feature/feature.xml b/bundles/org.openhab.binding.flicbutton/src/main/feature/feature.xml new file mode 100644 index 0000000000000..3608646164aac --- /dev/null +++ b/bundles/org.openhab.binding.flicbutton/src/main/feature/feature.xml @@ -0,0 +1,10 @@ + + + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + + + openhab-runtime-base + mvn:com.google.guava/guava/21.0 + mvn:org.openhab.addons.bundles/org.openhab.binding.flicbutton/${project.version} + + diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/FlicButtonBindingConstants.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/FlicButtonBindingConstants.java new file mode 100644 index 0000000000000..77da2b9a4933a --- /dev/null +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/FlicButtonBindingConstants.java @@ -0,0 +1,51 @@ +/** + * Copyright (c) 2016 - 2020 Patrick Fink + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the Eclipse + * Public License, v. 2.0 are satisfied: GNU General Public License, version 3 + * with the GNU Classpath Exception 2.0 which is + * available at https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-3.0 WITH Classpath-exception-2.0 + */ +package org.openhab.binding.flicbutton; + +import java.util.Collections; +import java.util.Set; + +import org.openhab.core.thing.ThingTypeUID; + +/** + * The {@link FlicButtonBinding} class defines common constants, which are + * used across the whole binding. + * + * @author Patrick Fink - Initial contribution + */ +public class FlicButtonBindingConstants { + + public static final String BINDING_ID = "flicbutton"; + + // List of all Thing Type UIDs + public final static ThingTypeUID BRIDGE_THING_TYPE = new ThingTypeUID(BINDING_ID, "flicd-bridge"); + public final static ThingTypeUID FLICBUTTON_THING_TYPE = new ThingTypeUID(BINDING_ID, "button"); + + public final static Set BRIDGE_THING_TYPES_UIDS = Collections.singleton(BRIDGE_THING_TYPE); + public static final Set SUPPORTED_THING_TYPES_UIDS = Collections.singleton(FLICBUTTON_THING_TYPE); + + // List of all configuration options + public static final String CONFIG_HOST_NAME = "hostname"; + public static final String CONFIG_PORT = "port"; + + // List of all Channel ids + public final static String CHANNEL_ID_RAWBUTTON_EVENTS = "rawbutton"; + public final static String CHANNEL_ID_BUTTON_EVENTS = "button"; + public final static String CHANNEL_ID_BATTERY_LEVEL = "battery-level"; + + // Other stuff + public final static int BUTTON_OFFLINE_GRACE_PERIOD_SECONDS = 60; +} diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/ChildThingHandler.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/ChildThingHandler.java new file mode 100644 index 0000000000000..183193a73b9c9 --- /dev/null +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/ChildThingHandler.java @@ -0,0 +1,74 @@ +/** + * Copyright (c) 2016 - 2020 Patrick Fink + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the Eclipse + * Public License, v. 2.0 are satisfied: GNU General Public License, version 3 + * with the GNU Classpath Exception 2.0 which is + * available at https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-3.0 WITH Classpath-exception-2.0 + */ + +package org.openhab.binding.flicbutton.handler; + +import java.util.Collection; +import java.util.Collections; + +import org.openhab.core.thing.Thing; +import org.openhab.core.thing.ThingStatus; +import org.openhab.core.thing.ThingStatusDetail; +import org.openhab.core.thing.binding.BaseThingHandler; +import org.openhab.core.thing.binding.BridgeHandler; + +/** + * @author Patrick Fink + * @param The bridge type this child handler depends on + */ +public abstract class ChildThingHandler extends BaseThingHandler { + private static final Collection defaultToleratedBridgeStatuses = Collections + .singleton(ThingStatus.ONLINE); + protected boolean bridgeValid = false; + protected BridgeHandlerType bridgeHandler; + + public ChildThingHandler(Thing thing) { + super(thing); + } + + public void initialize() { + setStatusBasedOnBridge(); + if (bridgeValid) { + linkBridge(); + } + } + + protected void linkBridge() { + try { + BridgeHandler bridgeHandlerUncasted = getBridge().getHandler(); + bridgeHandler = (BridgeHandlerType) bridgeHandlerUncasted; + } catch (ClassCastException e) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "Bridge Type is invalid."); + } + } + + protected void setStatusBasedOnBridge() { + setStatusBasedOnBridge(defaultToleratedBridgeStatuses); + } + + protected void setStatusBasedOnBridge(Collection toleratedBridgeStatuses) { + if (getBridge() != null) { + if (toleratedBridgeStatuses.contains(getBridge().getStatus())) { + bridgeValid = true; + } else { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE, + "Bridge in unsupported status: " + getBridge().getStatus()); + } + } else { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_UNINITIALIZED, "Bridge missing."); + } + } +} diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicButtonBatteryLevelListener.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicButtonBatteryLevelListener.java new file mode 100644 index 0000000000000..145129d51f15a --- /dev/null +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicButtonBatteryLevelListener.java @@ -0,0 +1,42 @@ +/** + * Copyright (c) 2016 - 2020 Patrick Fink + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the Eclipse + * Public License, v. 2.0 are satisfied: GNU General Public License, version 3 + * with the GNU Classpath Exception 2.0 which is + * available at https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-3.0 WITH Classpath-exception-2.0 + */ +package org.openhab.binding.flicbutton.handler; + +import java.io.IOException; + +import org.eclipse.jdt.annotation.NonNull; + +import io.flic.fliclib.javaclient.BatteryStatusListener; +import io.flic.fliclib.javaclient.Bdaddr; + +/** + * + * @author Patrick Fink + * + */ +public class FlicButtonBatteryLevelListener extends BatteryStatusListener.Callbacks { + + private final FlicButtonHandler thingHandler; + + FlicButtonBatteryLevelListener(@NonNull FlicButtonHandler thingHandler) { + this.thingHandler = thingHandler; + } + + @Override + public void onBatteryStatus(Bdaddr bdaddr, int i, long l) throws IOException { + thingHandler.updateBatteryChannel(i); + } +} diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicButtonEventListener.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicButtonEventListener.java new file mode 100644 index 0000000000000..d6a2a29b1375c --- /dev/null +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicButtonEventListener.java @@ -0,0 +1,86 @@ +/** + * Copyright (c) 2016 - 2020 Patrick Fink + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the Eclipse + * Public License, v. 2.0 are satisfied: GNU General Public License, version 3 + * with the GNU Classpath Exception 2.0 which is + * available at https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-3.0 WITH Classpath-exception-2.0 + */ +package org.openhab.binding.flicbutton.handler; + +import java.io.IOException; + +import org.eclipse.jdt.annotation.NonNull; +import org.openhab.binding.flicbutton.internal.util.FlicButtonUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import io.flic.fliclib.javaclient.ButtonConnectionChannel; +import io.flic.fliclib.javaclient.enums.*; + +/** + * + * @author Patrick Fink + * + */ +public class FlicButtonEventListener extends ButtonConnectionChannel.Callbacks { + private final Logger logger = LoggerFactory.getLogger(FlicButtonEventListener.class); + + private final FlicButtonHandler thingHandler; + + FlicButtonEventListener(@NonNull FlicButtonHandler thingHandler) { + this.thingHandler = thingHandler; + } + + @Override + public synchronized void onCreateConnectionChannelResponse(ButtonConnectionChannel channel, + CreateConnectionChannelError createConnectionChannelError, ConnectionStatus connectionStatus) { + logger.debug("Create response {}: {}, {}", channel.getBdaddr(), createConnectionChannelError, connectionStatus); + // Handling does not differ from Status change, so redirect + thingHandler.initializeStatus(connectionStatus); + notify(); + } + + @Override + public void onRemoved(ButtonConnectionChannel channel, RemovedReason removedReason) { + thingHandler.flicButtonRemoved(); + logger.debug("Button {} removed. ThingStatus updated to OFFLINE. Reason: {}", channel.getBdaddr(), + removedReason); + } + + @Override + public void onConnectionStatusChanged(ButtonConnectionChannel channel, ConnectionStatus connectionStatus, + DisconnectReason disconnectReason) { + logger.debug("New status for {}: {}", channel.getBdaddr(), + connectionStatus + (connectionStatus == ConnectionStatus.Disconnected ? ", " + disconnectReason : "")); + + thingHandler.connectionStatusChanged(connectionStatus, disconnectReason); + } + + @Override + public void onButtonUpOrDown(ButtonConnectionChannel channel, ClickType clickType, boolean wasQueued, int timeDiff) + throws IOException { + + logger.debug("{} {}", channel.getBdaddr(), clickType.name()); + + String commonTriggerEvent = FlicButtonUtils.flicOpenhabTriggerEventMap.get(clickType.name()); + + if (commonTriggerEvent != null) { + thingHandler.fireTriggerEvent(commonTriggerEvent); + } + } + + @Override + public void onButtonSingleOrDoubleClickOrHold(ButtonConnectionChannel channel, ClickType clickType, + boolean wasQueued, int timeDiff) throws IOException { + // Handling does not differ from up/down events, so redirect + onButtonUpOrDown(channel, clickType, wasQueued, timeDiff); + } +} diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicButtonHandler.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicButtonHandler.java new file mode 100644 index 0000000000000..afe466ff6a188 --- /dev/null +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicButtonHandler.java @@ -0,0 +1,179 @@ +/** + * Copyright (c) 2016 - 2020 Patrick Fink + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the Eclipse + * Public License, v. 2.0 are satisfied: GNU General Public License, version 3 + * with the GNU Classpath Exception 2.0 which is + * available at https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-3.0 WITH Classpath-exception-2.0 + */ +package org.openhab.binding.flicbutton.handler; + +import static org.openhab.binding.flicbutton.FlicButtonBindingConstants.*; + +import java.io.IOException; +import java.util.Objects; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; + +import org.openhab.binding.flicbutton.internal.util.FlicButtonUtils; +import org.openhab.core.library.types.DecimalType; +import org.openhab.core.thing.*; +import org.openhab.core.types.Command; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import io.flic.fliclib.javaclient.BatteryStatusListener; +import io.flic.fliclib.javaclient.Bdaddr; +import io.flic.fliclib.javaclient.ButtonConnectionChannel; +import io.flic.fliclib.javaclient.enums.ConnectionStatus; +import io.flic.fliclib.javaclient.enums.DisconnectReason; + +/** + * The {@link FlicButtonHandler} is responsible for handling commands, which are + * sent to one of the channels. + * + * @author Patrick Fink - Initial contribution + */ +public class FlicButtonHandler extends ChildThingHandler { + + private Logger logger = LoggerFactory.getLogger(FlicButtonHandler.class); + private ScheduledFuture delayedDisconnectTask; + private DisconnectReason latestDisconnectReason; + private ButtonConnectionChannel eventConnection; + BatteryStatusListener batteryConnection; + + public FlicButtonHandler(Thing thing) { + super(thing); + } + + public Bdaddr getBdaddr() { + return FlicButtonUtils.getBdAddrFromThingUID(getThing().getUID()); + } + + @Override + public void handleCommand(ChannelUID channelUID, Command command) { + // Pure sensor -> no commands have to be handled + } + + @Override + public void initialize() { + super.initialize(); + if (bridgeValid) { + initializeThing(); + } + } + + public void initializeThing() { + try { + FlicButtonBatteryLevelListener batteryListener = new FlicButtonBatteryLevelListener(this); + BatteryStatusListener batteryConnection = new BatteryStatusListener(getBdaddr(), batteryListener); + bridgeHandler.getFlicClient().addBatteryStatusListener(batteryConnection); + this.batteryConnection = batteryConnection; + + FlicButtonEventListener eventListener = new FlicButtonEventListener(this); + synchronized (eventListener) { + ButtonConnectionChannel eventConnection = new ButtonConnectionChannel(getBdaddr(), eventListener); + bridgeHandler.getFlicClient().addConnectionChannel(eventConnection); + this.eventConnection = eventConnection; + eventListener.wait(5000); + // Listener calls initializeStatus() before notifying so that ThingStatus is set at this point + } + } catch (IOException | InterruptedException e) { + logger.info("Connection setup for Flic Button {} failed.", this.getThing(), e); + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "Connection setup failed"); + } + } + + @Override + public void dispose() { + cancelDelayedDisconnectTask(); + + try { + if (eventConnection != null) { + bridgeHandler.getFlicClient().removeConnectionChannel(eventConnection); + } + if (batteryConnection != null) { + bridgeHandler.getFlicClient().removeBatteryStatusListener(this.batteryConnection); + } + } catch (IOException e) { + logger.error("Error occured while removing button channel", e); + } + + super.dispose(); + } + + void initializeStatus(ConnectionStatus connectionStatus) { + if (connectionStatus == ConnectionStatus.Disconnected) { + setOffline(); + } else { + setOnline(); + } + } + + void connectionStatusChanged(ConnectionStatus connectionStatus, DisconnectReason disconnectReason) { + latestDisconnectReason = disconnectReason; + if (connectionStatus == ConnectionStatus.Disconnected) { + // Status change to offline have to be scheduled to improve stability, see issue #2 + scheduleStatusChangeToOffline(); + } else { + setOnline(); + } + } + + private void scheduleStatusChangeToOffline() { + if (delayedDisconnectTask == null) { + delayedDisconnectTask = scheduler.schedule(() -> setOffline(), BUTTON_OFFLINE_GRACE_PERIOD_SECONDS, + TimeUnit.SECONDS); + } + } + + protected void setOnline() { + updateStatus(ThingStatus.ONLINE, ThingStatusDetail.NONE, "Button connected."); + } + + protected void setOffline() { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR, + "Disconnect Reason: " + Objects.toString(latestDisconnectReason)); + } + + // Cleanup delayedDisconnect on status change to online + @Override + protected void updateStatus(ThingStatus status, ThingStatusDetail statusDetail, String description) { + if (status == ThingStatus.ONLINE) { + cancelDelayedDisconnectTask(); + } + super.updateStatus(status, statusDetail, description); + } + + private void cancelDelayedDisconnectTask() { + if (delayedDisconnectTask != null) { + delayedDisconnectTask.cancel(false); + delayedDisconnectTask = null; + } + } + + void updateBatteryChannel(int percent) { + DecimalType batteryLevel = new DecimalType(percent); + updateState(CHANNEL_ID_BATTERY_LEVEL, batteryLevel); + } + + void flicButtonRemoved() { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.NONE, + "Button was removed/detached from flicd (e.g. by simpleclient)."); + } + + void fireTriggerEvent(String event) { + String channelID = event == CommonTriggerEvents.PRESSED || event == CommonTriggerEvents.RELEASED + ? CHANNEL_ID_RAWBUTTON_EVENTS + : CHANNEL_ID_BUTTON_EVENTS; + updateStatus(ThingStatus.ONLINE); + triggerChannel(channelID, event); + } +} diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicDaemonBridgeConfiguration.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicDaemonBridgeConfiguration.java new file mode 100644 index 0000000000000..f01ea71e36def --- /dev/null +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicDaemonBridgeConfiguration.java @@ -0,0 +1,63 @@ +/** + * Copyright (c) 2016 - 2020 Patrick Fink + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the Eclipse + * Public License, v. 2.0 are satisfied: GNU General Public License, version 3 + * with the GNU Classpath Exception 2.0 which is + * available at https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-3.0 WITH Classpath-exception-2.0 + */ +package org.openhab.binding.flicbutton.handler; + +import java.net.InetAddress; +import java.net.UnknownHostException; + +/** + * + * @author Patrick Fink + * + */ +public class FlicDaemonBridgeConfiguration { + + private final InetAddress hostname; + private final int port; + + FlicDaemonBridgeConfiguration(InetAddress hostname, int port) { + this.hostname = hostname; + this.port = port; + } + + FlicDaemonBridgeConfiguration(Object rawHostname, Object rawPort) + throws UnknownHostException, IllegalArgumentException { + if (rawHostname == null || rawPort == null) { + throw new IllegalArgumentException("Hostname and port must not be null"); + } + this.hostname = parseBridgeHostname(rawHostname); + this.port = parseBridgePort(rawPort); + } + + private InetAddress parseBridgeHostname(Object rawHostname) throws UnknownHostException { + String host_config = ((rawHostname instanceof String) ? (String) rawHostname + : (rawHostname instanceof InetAddress) ? ((InetAddress) rawHostname).getHostAddress() : null); + + return InetAddress.getByName(host_config); + } + + private int parseBridgePort(Object rawPort) { + return Integer.parseInt(rawPort.toString()); + } + + public InetAddress getHostname() { + return hostname; + } + + public int getPort() { + return port; + } +} diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicDaemonBridgeHandler.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicDaemonBridgeHandler.java new file mode 100644 index 0000000000000..ae127ae7351ce --- /dev/null +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicDaemonBridgeHandler.java @@ -0,0 +1,153 @@ +/** + * Copyright (c) 2016 - 2020 Patrick Fink + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the Eclipse + * Public License, v. 2.0 are satisfied: GNU General Public License, version 3 + * with the GNU Classpath Exception 2.0 which is + * available at https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-3.0 WITH Classpath-exception-2.0 + */ +package org.openhab.binding.flicbutton.handler; + +import java.io.IOException; +import java.net.UnknownHostException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; + +import org.openhab.binding.flicbutton.FlicButtonBindingConstants; +import org.openhab.binding.flicbutton.internal.discovery.FlicButtonDiscoveryService; +import org.openhab.core.thing.Bridge; +import org.openhab.core.thing.ChannelUID; +import org.openhab.core.thing.ThingStatus; +import org.openhab.core.thing.ThingStatusDetail; +import org.openhab.core.thing.binding.BaseBridgeHandler; +import org.openhab.core.types.Command; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import io.flic.fliclib.javaclient.FlicClient; + +/** + * The {@link FlicDaemonBridgeHandler} handles a running instance of the fliclib-linux-hci server (flicd). + * + * @author Patrick Fink - Initial contribution + */ +public class FlicDaemonBridgeHandler extends BaseBridgeHandler { + private static final Logger logger = LoggerFactory.getLogger(FlicDaemonBridgeHandler.class); + private static final long REINITIALIZE_DELAY_SECONDS = 10; + // Config parameters + private FlicDaemonBridgeConfiguration cfg; + // Services + private FlicButtonDiscoveryService buttonDiscoveryService; + private Future flicClientFuture; + // For disposal + private Collection> startedTasks = new ArrayList<>(2); + private FlicClient flicClient; + + public FlicDaemonBridgeHandler(Bridge bridge, FlicButtonDiscoveryService buttonDiscoveryService) { + super(bridge); + this.buttonDiscoveryService = buttonDiscoveryService; + } + + public FlicClient getFlicClient() { + return flicClient; + } + + @Override + public void initialize() { + logger.debug("Initialize Fliclib bridge"); + + try { + initConfigParameters(); + startFlicdClientAsync(); + activateButtonDiscoveryService(); + initThingStatus(); + } catch (UnknownHostException ignored) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "Hostname wrong or unknown!"); + } catch (IllegalArgumentException e) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, + "Configuration (hostname, port) is invalid and cannot be parsed."); + } catch (IOException e) { + logger.warn("Error occured while connecting to flicd", e); + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "Error connecting to flicd!"); + } + } + + private void initConfigParameters() throws UnknownHostException { + Object hostConfigRaw = thing.getConfiguration().get(FlicButtonBindingConstants.CONFIG_HOST_NAME); + Object portConfigRaw = thing.getConfiguration().get(FlicButtonBindingConstants.CONFIG_PORT); + cfg = new FlicDaemonBridgeConfiguration(hostConfigRaw, portConfigRaw); + } + + private void activateButtonDiscoveryService() { + buttonDiscoveryService.activate(flicClient); + } + + private void startFlicdClientAsync() throws IOException { + flicClient = new FlicClient(cfg.getHostname().getHostAddress(), cfg.getPort()); + Runnable flicClientService = () -> { + try { + flicClient.handleEvents(); + logger.info("Listening to flicd unexpectedly ended"); + } catch (Exception e) { + logger.info("Error occured while listening to flicd", e); + } finally { + onClientFailure(); + } + }; + + flicClientFuture = scheduler.submit(flicClientService); + startedTasks.add(flicClientFuture); + } + + private void onClientFailure() { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, + "flicd client terminated, probably flicd is not reachable."); + dispose(); + scheduleReinitialize(); + } + + private void initThingStatus() { + if (!flicClientFuture.isDone()) { + updateStatus(ThingStatus.ONLINE); + } else { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, + "flicd client could not be started, probably flicd is not reachable."); + } + } + + @Override + public void dispose() { + super.dispose(); + for (Future startedTask : startedTasks) { + if (!startedTask.isDone()) { + startedTask.cancel(true); + } + } + startedTasks = new ArrayList<>(2); + buttonDiscoveryService.deactivate(); + } + + private void scheduleReinitialize() { + startedTasks.add(scheduler.schedule(new Runnable() { + @Override + public void run() { + initialize(); + } + }, REINITIALIZE_DELAY_SECONDS, TimeUnit.SECONDS)); + } + + @Override + public void handleCommand(ChannelUID channelUID, Command command) { + // No commands to the fliclib-linux-hci are supported. + // So there is nothing to handle in the bridge handler + } +} diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/FlicButtonHandlerFactory.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/FlicButtonHandlerFactory.java new file mode 100644 index 0000000000000..bfecf09c307dd --- /dev/null +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/FlicButtonHandlerFactory.java @@ -0,0 +1,106 @@ +/** + * Copyright (c) 2016 - 2020 Patrick Fink + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the Eclipse + * Public License, v. 2.0 are satisfied: GNU General Public License, version 3 + * with the GNU Classpath Exception 2.0 which is + * available at https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-3.0 WITH Classpath-exception-2.0 + */ +package org.openhab.binding.flicbutton.internal; + +import java.util.HashMap; +import java.util.Hashtable; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.eclipse.jdt.annotation.Nullable; +import org.openhab.binding.flicbutton.FlicButtonBindingConstants; +import org.openhab.binding.flicbutton.handler.FlicButtonHandler; +import org.openhab.binding.flicbutton.handler.FlicDaemonBridgeHandler; +import org.openhab.binding.flicbutton.internal.discovery.FlicButtonDiscoveryService; +import org.openhab.binding.flicbutton.internal.discovery.FlicSimpleclientDiscoveryServiceImpl; +import org.openhab.core.config.discovery.DiscoveryService; +import org.openhab.core.thing.Bridge; +import org.openhab.core.thing.Thing; +import org.openhab.core.thing.ThingTypeUID; +import org.openhab.core.thing.ThingUID; +import org.openhab.core.thing.binding.BaseThingHandlerFactory; +import org.openhab.core.thing.binding.ThingHandler; +import org.openhab.core.thing.binding.ThingHandlerFactory; +import org.osgi.framework.ServiceRegistration; +import org.osgi.service.component.annotations.Component; + +/** + * The {@link FlicButtonHandlerFactory} is responsible for creating things and thing + * handlers. + * + * @author Patrick Fink - Initial contribution + */ +@Component(service = ThingHandlerFactory.class, configurationPid = "binding.flicbutton") +public class FlicButtonHandlerFactory extends BaseThingHandlerFactory { + + private final static Set SUPPORTED_THING_TYPES_UIDS = Stream + .concat(FlicButtonBindingConstants.BRIDGE_THING_TYPES_UIDS.stream(), + FlicButtonBindingConstants.SUPPORTED_THING_TYPES_UIDS.stream()) + .collect(Collectors.toSet()); + private final Map> discoveryServiceRegs = new HashMap<>(); + + @Override + public boolean supportsThingType(ThingTypeUID thingTypeUID) { + return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID); + } + + @Override + protected ThingHandler createHandler(Thing thing) { + + ThingTypeUID thingTypeUID = thing.getThingTypeUID(); + + if (thingTypeUID.equals(FlicButtonBindingConstants.FLICBUTTON_THING_TYPE)) { + return new FlicButtonHandler(thing); + } else if (thingTypeUID.equals(FlicButtonBindingConstants.BRIDGE_THING_TYPE)) { + FlicButtonDiscoveryService discoveryService = new FlicSimpleclientDiscoveryServiceImpl(thing.getUID()); + FlicDaemonBridgeHandler bridgeHandler = new FlicDaemonBridgeHandler((Bridge) thing, discoveryService); + registerDiscoveryService(discoveryService, thing.getUID()); + + return bridgeHandler; + } + + return null; + } + + @Override + protected synchronized void removeHandler(ThingHandler thingHandler) { + if (thingHandler instanceof FlicDaemonBridgeHandler) { + unregisterDiscoveryService(thingHandler.getThing().getUID()); + } + super.removeHandler(thingHandler); + } + + private synchronized void registerDiscoveryService(FlicButtonDiscoveryService discoveryService, + ThingUID bridgeUID) { + this.discoveryServiceRegs.put(bridgeUID, getBundleContext().registerService(DiscoveryService.class.getName(), + discoveryService, new Hashtable())); + } + + private synchronized void unregisterDiscoveryService(ThingUID bridgeUID) { + ServiceRegistration serviceReg = this.discoveryServiceRegs.get(bridgeUID); + if (serviceReg != null) { + FlicButtonDiscoveryService service = (FlicButtonDiscoveryService) getBundleContext() + .getService(serviceReg.getReference()); + if (service != null) { + service.deactivate(); + } + serviceReg.unregister(); + discoveryServiceRegs.remove(bridgeUID); + } + } +} diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/discovery/FlicButtonDiscoveryService.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/discovery/FlicButtonDiscoveryService.java new file mode 100644 index 0000000000000..ce5efa6c79d01 --- /dev/null +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/discovery/FlicButtonDiscoveryService.java @@ -0,0 +1,42 @@ +/** + * Copyright (c) 2016 - 2020 Patrick Fink + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the Eclipse + * Public License, v. 2.0 are satisfied: GNU General Public License, version 3 + * with the GNU Classpath Exception 2.0 which is + * available at https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-3.0 WITH Classpath-exception-2.0 + */ +package org.openhab.binding.flicbutton.internal.discovery; + +import org.eclipse.jdt.annotation.NonNull; +import org.openhab.core.config.discovery.DiscoveryService; +import org.openhab.core.thing.ThingUID; + +import io.flic.fliclib.javaclient.Bdaddr; +import io.flic.fliclib.javaclient.FlicClient; + +/** + * + * @author Patrick Fink + * + */ +public interface FlicButtonDiscoveryService extends DiscoveryService { + + /** + * + * @param bdaddr Bluetooth address of the discovered Flic button + * @return UID that was created by the discovery service + */ + public ThingUID flicButtonDiscovered(Bdaddr bdaddr); + + public void activate(@NonNull FlicClient client); + + public void deactivate(); +} diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/discovery/FlicSimpleclientDiscoveryServiceImpl.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/discovery/FlicSimpleclientDiscoveryServiceImpl.java new file mode 100644 index 0000000000000..422baba3bb712 --- /dev/null +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/discovery/FlicSimpleclientDiscoveryServiceImpl.java @@ -0,0 +1,137 @@ +/** + * Copyright (c) 2016 - 2020 Patrick Fink + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the Eclipse + * Public License, v. 2.0 are satisfied: GNU General Public License, version 3 + * with the GNU Classpath Exception 2.0 which is + * available at https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-3.0 WITH Classpath-exception-2.0 + */ +package org.openhab.binding.flicbutton.internal.discovery; + +import java.io.IOException; + +import org.eclipse.jdt.annotation.NonNull; +import org.openhab.binding.flicbutton.FlicButtonBindingConstants; +import org.openhab.binding.flicbutton.internal.FlicButtonHandlerFactory; +import org.openhab.binding.flicbutton.internal.util.FlicButtonUtils; +import org.openhab.core.config.discovery.AbstractDiscoveryService; +import org.openhab.core.config.discovery.DiscoveryResult; +import org.openhab.core.config.discovery.DiscoveryResultBuilder; +import org.openhab.core.thing.ThingUID; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import io.flic.fliclib.javaclient.Bdaddr; +import io.flic.fliclib.javaclient.FlicClient; +import io.flic.fliclib.javaclient.GeneralCallbacks; +import io.flic.fliclib.javaclient.GetInfoResponseCallback; +import io.flic.fliclib.javaclient.enums.BdAddrType; +import io.flic.fliclib.javaclient.enums.BluetoothControllerState; + +/** + * For each configured flicd service, there is a {@link FlicSimpleclientDiscoveryServiceImpl} which will be initialized + * by + * {@link FlicButtonHandlerFactory}. + * + * It can scan for Flic Buttons already that are already added to fliclib-linux-hci ("verified" buttons), * + * but it does not support adding and verify new buttons on it's own. + * New buttons have to be added (verified) e.g. via simpleclient by Shortcut Labs. + * Background discovery listens for new buttons that are getting verified. + * + * @author Patrick Fink - Initial contribution + */ +public class FlicSimpleclientDiscoveryServiceImpl extends AbstractDiscoveryService + implements FlicButtonDiscoveryService { + private final Logger logger = LoggerFactory.getLogger(FlicSimpleclientDiscoveryServiceImpl.class); + + private boolean activated = false; + private ThingUID bridgeUID; + private FlicClient flicClient; + + public FlicSimpleclientDiscoveryServiceImpl(@NonNull ThingUID bridgeUID) { + super(FlicButtonBindingConstants.SUPPORTED_THING_TYPES_UIDS, 2, true); + this.bridgeUID = bridgeUID; + } + + @Override + public void activate(@NonNull FlicClient flicClient) { + this.flicClient = flicClient; + activated = true; + super.activate(null); + } + + @Override + public void deactivate() { + activated = false; + super.deactivate(); + } + + @Override + protected void startScan() { + try { + if (activated) { + discoverVerifiedButtons(); + } + + } catch (IOException e) { + logger.warn("Error occured during button discovery", e); + if (this.scanListener != null) { + scanListener.onErrorOccurred(e); + } + } + } + + protected void discoverVerifiedButtons() throws IOException { + // Register FlicButtonEventListener to all already existing Flic buttons + flicClient.getInfo(new GetInfoResponseCallback() { + @Override + public void onGetInfoResponse(BluetoothControllerState bluetoothControllerState, Bdaddr myBdAddr, + BdAddrType myBdAddrType, int maxPendingConnections, int maxConcurrentlyConnectedButtons, + int currentPendingConnections, boolean currentlyNoSpaceForNewConnection, Bdaddr[] verifiedButtons) + throws IOException { + + for (final Bdaddr bdaddr : verifiedButtons) { + flicButtonDiscovered(bdaddr); + } + } + }); + } + + @Override + protected void startBackgroundDiscovery() { + super.startBackgroundDiscovery(); + flicClient.setGeneralCallbacks(new GeneralCallbacks() { + @Override + public void onNewVerifiedButton(Bdaddr bdaddr) throws IOException { + logger.info("A new Flic button was added by an external flicd client: {}", bdaddr); + flicButtonDiscovered(bdaddr); + } + }); + } + + @Override + protected void stopBackgroundDiscovery() { + super.stopBackgroundDiscovery(); + if (flicClient != null) { + flicClient.setGeneralCallbacks(null); + } + } + + @Override + public ThingUID flicButtonDiscovered(Bdaddr bdaddr) { + logger.info("Flic Button {} discovered!", bdaddr); + ThingUID flicButtonUID = FlicButtonUtils.getThingUIDFromBdAddr(bdaddr, bridgeUID); + + DiscoveryResult discoveryResult = DiscoveryResultBuilder.create(flicButtonUID).withBridge(bridgeUID) + .withLabel("Flic Button " + bdaddr.toString().replace(":", "")).build(); + this.thingDiscovered(discoveryResult); + return flicButtonUID; + } +} diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/util/FlicButtonUtils.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/util/FlicButtonUtils.java new file mode 100644 index 0000000000000..753ecf67d66eb --- /dev/null +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/util/FlicButtonUtils.java @@ -0,0 +1,54 @@ +/** + * Copyright (c) 2016 - 2020 Patrick Fink + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the Eclipse + * Public License, v. 2.0 are satisfied: GNU General Public License, version 3 + * with the GNU Classpath Exception 2.0 which is + * available at https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-3.0 WITH Classpath-exception-2.0 + */ +package org.openhab.binding.flicbutton.internal.util; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import org.openhab.binding.flicbutton.FlicButtonBindingConstants; +import org.openhab.core.thing.CommonTriggerEvents; +import org.openhab.core.thing.ThingUID; + +import io.flic.fliclib.javaclient.Bdaddr; + +/** + * + * @author Patrick Fink + * + */ +public class FlicButtonUtils { + public static final Map flicOpenhabTriggerEventMap = Collections + .unmodifiableMap(new HashMap() { + { + put("ButtonSingleClick", CommonTriggerEvents.SHORT_PRESSED); + put("ButtonDoubleClick", CommonTriggerEvents.DOUBLE_PRESSED); + put("ButtonHold", CommonTriggerEvents.LONG_PRESSED); + put("ButtonDown", CommonTriggerEvents.PRESSED); + put("ButtonUp", CommonTriggerEvents.RELEASED); + } + }); + + public static ThingUID getThingUIDFromBdAddr(Bdaddr bdaddr, ThingUID bridgeUID) { + String thingID = bdaddr.toString().replace(":", "-"); + return new ThingUID(FlicButtonBindingConstants.FLICBUTTON_THING_TYPE, bridgeUID, thingID); + } + + public static Bdaddr getBdAddrFromThingUID(ThingUID thingUID) { + String bdaddrRaw = thingUID.getId().replace("-", ":"); + return new Bdaddr(bdaddrRaw); + } +} diff --git a/bundles/org.openhab.binding.flicbutton/src/main/resources/OH-INF/binding/binding.xml b/bundles/org.openhab.binding.flicbutton/src/main/resources/OH-INF/binding/binding.xml new file mode 100644 index 0000000000000..bd9fe6fdf043a --- /dev/null +++ b/bundles/org.openhab.binding.flicbutton/src/main/resources/OH-INF/binding/binding.xml @@ -0,0 +1,10 @@ + + + + FlicButton Binding + This is the binding for FlicButton. + Patrick Fink + + diff --git a/bundles/org.openhab.binding.flicbutton/src/main/resources/OH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.flicbutton/src/main/resources/OH-INF/thing/thing-types.xml new file mode 100644 index 0000000000000..2f4efbac2e0d3 --- /dev/null +++ b/bundles/org.openhab.binding.flicbutton/src/main/resources/OH-INF/thing/thing-types.xml @@ -0,0 +1,37 @@ + + + + + + This bridge represents a running instance of the fliclib-linux-hci server (flicd). + + + + + IP or Host name of the Flic daemon (flicd). Defaults to localhost. + localhost + + + + Port where flicd is running. Defaults to 5551. + 5551 + + + + + + + + + + The thing(-type) representing a Flic Button + + + + + + + diff --git a/bundles/org.openhab.binding.flicbutton/tools/checkstyle.properties b/bundles/org.openhab.binding.flicbutton/tools/checkstyle.properties new file mode 100644 index 0000000000000..24f082c8f618a --- /dev/null +++ b/bundles/org.openhab.binding.flicbutton/tools/checkstyle.properties @@ -0,0 +1,7 @@ +checkstyle.forbiddenPackageUsageCheck.forbiddenPackages= +checkstyle.forbiddenPackageUsageCheck.exceptions= +checkstyle.headerCheck.content=^/\\*\\*$\\n^ \\* Copyright \\(c\\) {0} - {1} Patrick Fink$\\n^ \\*$\\n^ \\* This program and the accompanying materials are made available under the$\\n^ \\* terms of the Eclipse Public License 2\\.0 which is available at$\\n^ \\* http://www.eclipse.org/legal/epl\\-2\\.0.$ +checkstyle.headerCheck.values=2016,2020 +checkstyle.requiredFilesCheck.extensions=xml,md +checkstyle.requiredFilesCheck.files=pom.xml +checkstyle.pomXmlCheck.checkPomVersion=false \ No newline at end of file diff --git a/bundles/pom.xml b/bundles/pom.xml index fa3dde1666c27..8df6998301b1f 100644 --- a/bundles/pom.xml +++ b/bundles/pom.xml @@ -100,6 +100,7 @@ org.openhab.binding.exec org.openhab.binding.feed org.openhab.binding.feican + org.openhab.binding.flicbutton org.openhab.binding.fmiweather org.openhab.binding.folding org.openhab.binding.foobot From b3b4e91c0fcede1d7c700391727f0a4e6a9f78e9 Mon Sep 17 00:00:00 2001 From: Patrick Fink Date: Fri, 4 Dec 2020 22:06:26 +0100 Subject: [PATCH 02/37] [flicbutton] Add config parameter address for FlicButton thing Signed-off-by: Patrick Fink --- .../FlicButtonBindingConstants.java | 1 + .../flicbutton/handler/FlicButtonHandler.java | 28 +++++++++---------- .../FlicSimpleclientDiscoveryServiceImpl.java | 5 +++- .../resources/OH-INF/thing/thing-types.xml | 6 ++++ 4 files changed, 25 insertions(+), 15 deletions(-) diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/FlicButtonBindingConstants.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/FlicButtonBindingConstants.java index 77da2b9a4933a..7245d07630cdd 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/FlicButtonBindingConstants.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/FlicButtonBindingConstants.java @@ -40,6 +40,7 @@ public class FlicButtonBindingConstants { // List of all configuration options public static final String CONFIG_HOST_NAME = "hostname"; public static final String CONFIG_PORT = "port"; + public static final String CONFIG_ADDRESS = "address"; // List of all Channel ids public final static String CHANNEL_ID_RAWBUTTON_EVENTS = "rawbutton"; diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicButtonHandler.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicButtonHandler.java index afe466ff6a188..7a21ac03763ef 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicButtonHandler.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicButtonHandler.java @@ -15,25 +15,23 @@ */ package org.openhab.binding.flicbutton.handler; -import static org.openhab.binding.flicbutton.FlicButtonBindingConstants.*; - -import java.io.IOException; -import java.util.Objects; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.TimeUnit; - -import org.openhab.binding.flicbutton.internal.util.FlicButtonUtils; +import io.flic.fliclib.javaclient.BatteryStatusListener; +import io.flic.fliclib.javaclient.Bdaddr; +import io.flic.fliclib.javaclient.ButtonConnectionChannel; +import io.flic.fliclib.javaclient.enums.ConnectionStatus; +import io.flic.fliclib.javaclient.enums.DisconnectReason; import org.openhab.core.library.types.DecimalType; import org.openhab.core.thing.*; import org.openhab.core.types.Command; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import io.flic.fliclib.javaclient.BatteryStatusListener; -import io.flic.fliclib.javaclient.Bdaddr; -import io.flic.fliclib.javaclient.ButtonConnectionChannel; -import io.flic.fliclib.javaclient.enums.ConnectionStatus; -import io.flic.fliclib.javaclient.enums.DisconnectReason; +import java.io.IOException; +import java.util.Objects; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; + +import static org.openhab.binding.flicbutton.FlicButtonBindingConstants.*; /** * The {@link FlicButtonHandler} is responsible for handling commands, which are @@ -47,6 +45,7 @@ public class FlicButtonHandler extends ChildThingHandler delayedDisconnectTask; private DisconnectReason latestDisconnectReason; private ButtonConnectionChannel eventConnection; + private Bdaddr bdaddr; BatteryStatusListener batteryConnection; public FlicButtonHandler(Thing thing) { @@ -54,7 +53,7 @@ public FlicButtonHandler(Thing thing) { } public Bdaddr getBdaddr() { - return FlicButtonUtils.getBdAddrFromThingUID(getThing().getUID()); + return bdaddr; } @Override @@ -65,6 +64,7 @@ public void handleCommand(ChannelUID channelUID, Command command) { @Override public void initialize() { super.initialize(); + bdaddr = new Bdaddr((String) this.getThing().getConfiguration().get(CONFIG_ADDRESS)); if (bridgeValid) { initializeThing(); } diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/discovery/FlicSimpleclientDiscoveryServiceImpl.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/discovery/FlicSimpleclientDiscoveryServiceImpl.java index 422baba3bb712..f51f5c15c300d 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/discovery/FlicSimpleclientDiscoveryServiceImpl.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/discovery/FlicSimpleclientDiscoveryServiceImpl.java @@ -130,7 +130,10 @@ public ThingUID flicButtonDiscovered(Bdaddr bdaddr) { ThingUID flicButtonUID = FlicButtonUtils.getThingUIDFromBdAddr(bdaddr, bridgeUID); DiscoveryResult discoveryResult = DiscoveryResultBuilder.create(flicButtonUID).withBridge(bridgeUID) - .withLabel("Flic Button " + bdaddr.toString().replace(":", "")).build(); + .withLabel("Flic Button " + bdaddr.toString().replace(":", "")) + .withProperty(FlicButtonBindingConstants.CONFIG_ADDRESS, bdaddr.toString()) + .withRepresentationProperty(FlicButtonBindingConstants.CONFIG_ADDRESS) + .build(); this.thingDiscovered(discoveryResult); return flicButtonUID; } diff --git a/bundles/org.openhab.binding.flicbutton/src/main/resources/OH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.flicbutton/src/main/resources/OH-INF/thing/thing-types.xml index 2f4efbac2e0d3..29005bcd66e65 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/resources/OH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.flicbutton/src/main/resources/OH-INF/thing/thing-types.xml @@ -28,6 +28,12 @@ The thing(-type) representing a Flic Button + + + + Bluetooth address in XX:XX:XX:XX:XX:XX format + + From 329ac592fa94972ffaf1f575bc8603a2288fed4f Mon Sep 17 00:00:00 2001 From: Patrick Fink Date: Fri, 4 Dec 2020 22:09:08 +0100 Subject: [PATCH 03/37] [flicbutton] Run spotless Signed-off-by: Patrick Fink --- .../flicbutton/handler/FlicButtonHandler.java | 23 ++++++++++--------- .../FlicSimpleclientDiscoveryServiceImpl.java | 3 +-- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicButtonHandler.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicButtonHandler.java index 7a21ac03763ef..8f1d92ff5b388 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicButtonHandler.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicButtonHandler.java @@ -15,23 +15,24 @@ */ package org.openhab.binding.flicbutton.handler; -import io.flic.fliclib.javaclient.BatteryStatusListener; -import io.flic.fliclib.javaclient.Bdaddr; -import io.flic.fliclib.javaclient.ButtonConnectionChannel; -import io.flic.fliclib.javaclient.enums.ConnectionStatus; -import io.flic.fliclib.javaclient.enums.DisconnectReason; -import org.openhab.core.library.types.DecimalType; -import org.openhab.core.thing.*; -import org.openhab.core.types.Command; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import static org.openhab.binding.flicbutton.FlicButtonBindingConstants.*; import java.io.IOException; import java.util.Objects; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; -import static org.openhab.binding.flicbutton.FlicButtonBindingConstants.*; +import org.openhab.core.library.types.DecimalType; +import org.openhab.core.thing.*; +import org.openhab.core.types.Command; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import io.flic.fliclib.javaclient.BatteryStatusListener; +import io.flic.fliclib.javaclient.Bdaddr; +import io.flic.fliclib.javaclient.ButtonConnectionChannel; +import io.flic.fliclib.javaclient.enums.ConnectionStatus; +import io.flic.fliclib.javaclient.enums.DisconnectReason; /** * The {@link FlicButtonHandler} is responsible for handling commands, which are diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/discovery/FlicSimpleclientDiscoveryServiceImpl.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/discovery/FlicSimpleclientDiscoveryServiceImpl.java index f51f5c15c300d..4348675b23332 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/discovery/FlicSimpleclientDiscoveryServiceImpl.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/discovery/FlicSimpleclientDiscoveryServiceImpl.java @@ -132,8 +132,7 @@ public ThingUID flicButtonDiscovered(Bdaddr bdaddr) { DiscoveryResult discoveryResult = DiscoveryResultBuilder.create(flicButtonUID).withBridge(bridgeUID) .withLabel("Flic Button " + bdaddr.toString().replace(":", "")) .withProperty(FlicButtonBindingConstants.CONFIG_ADDRESS, bdaddr.toString()) - .withRepresentationProperty(FlicButtonBindingConstants.CONFIG_ADDRESS) - .build(); + .withRepresentationProperty(FlicButtonBindingConstants.CONFIG_ADDRESS).build(); this.thingDiscovered(discoveryResult); return flicButtonUID; } From 0e3c17d9c62fb86c4f9fae79d19c927e4eeb7902 Mon Sep 17 00:00:00 2001 From: Patrick Fink Date: Fri, 4 Dec 2020 22:51:02 +0100 Subject: [PATCH 04/37] [flicbutton] Code cleanup & docs improvement Signed-off-by: Patrick Fink --- CODEOWNERS | 1 + .../org.openhab.binding.flicbutton/.gitignore | 1 - .../.travis.yml | 9 - .../org.openhab.binding.flicbutton/LICENSE | 277 ------------------ .../org.openhab.binding.flicbutton/README.md | 25 +- .../FlicButtonBindingConstants.java | 15 +- .../flicbutton/handler/ChildThingHandler.java | 17 +- .../FlicButtonBatteryLevelListener.java | 15 +- .../handler/FlicButtonEventListener.java | 15 +- .../flicbutton/handler/FlicButtonHandler.java | 15 +- .../FlicDaemonBridgeConfiguration.java | 20 +- .../handler/FlicDaemonBridgeHandler.java | 15 +- .../internal/FlicButtonHandlerFactory.java | 15 +- .../discovery/FlicButtonDiscoveryService.java | 17 +- .../FlicSimpleclientDiscoveryServiceImpl.java | 15 +- .../internal/util/FlicButtonUtils.java | 19 +- .../resources/OH-INF/thing/thing-types.xml | 10 +- .../tools/checkstyle.properties | 7 - 18 files changed, 95 insertions(+), 413 deletions(-) delete mode 100644 bundles/org.openhab.binding.flicbutton/.gitignore delete mode 100644 bundles/org.openhab.binding.flicbutton/.travis.yml delete mode 100644 bundles/org.openhab.binding.flicbutton/LICENSE delete mode 100644 bundles/org.openhab.binding.flicbutton/tools/checkstyle.properties diff --git a/CODEOWNERS b/CODEOWNERS index c6329d68d026b..925861ee6a1d7 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -68,6 +68,7 @@ /bundles/org.openhab.binding.exec/ @kgoderis /bundles/org.openhab.binding.feed/ @svilenvul /bundles/org.openhab.binding.feican/ @Hilbrand +/bundles/org.openhab.binding.flicbutton/ @pfink /bundles/org.openhab.binding.fmiweather/ @ssalonen /bundles/org.openhab.binding.folding/ @fa2k /bundles/org.openhab.binding.foobot/ @airboxlab @Hilbrand diff --git a/bundles/org.openhab.binding.flicbutton/.gitignore b/bundles/org.openhab.binding.flicbutton/.gitignore deleted file mode 100644 index ea8c4bf7f35f6..0000000000000 --- a/bundles/org.openhab.binding.flicbutton/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/target diff --git a/bundles/org.openhab.binding.flicbutton/.travis.yml b/bundles/org.openhab.binding.flicbutton/.travis.yml deleted file mode 100644 index 1526a73c35dea..0000000000000 --- a/bundles/org.openhab.binding.flicbutton/.travis.yml +++ /dev/null @@ -1,9 +0,0 @@ -language: java -jdk: openjdk11 -before_install: - - wget /~https://github.com/openhab/openhab-addons/archive/2.5.x.tar.gz - - tar xzf 2.5.x.tar.gz - - mkdir openhab-addons-2.5.x/bundles/org.openhab.binding.flicbutton - - shopt -s extglob dotglob - - mv !(openhab-addons-2.5.x) openhab-addons-2.5.x/bundles/org.openhab.binding.flicbutton - - cd openhab-addons-2.5.x/bundles/org.openhab.binding.flicbutton diff --git a/bundles/org.openhab.binding.flicbutton/LICENSE b/bundles/org.openhab.binding.flicbutton/LICENSE deleted file mode 100644 index e55f34467e251..0000000000000 --- a/bundles/org.openhab.binding.flicbutton/LICENSE +++ /dev/null @@ -1,277 +0,0 @@ -Eclipse Public License - v 2.0 - - THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE - PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION - OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. - -1. DEFINITIONS - -"Contribution" means: - - a) in the case of the initial Contributor, the initial content - Distributed under this Agreement, and - - b) in the case of each subsequent Contributor: - i) changes to the Program, and - ii) additions to the Program; - where such changes and/or additions to the Program originate from - and are Distributed by that particular Contributor. A Contribution - "originates" from a Contributor if it was added to the Program by - such Contributor itself or anyone acting on such Contributor's behalf. - Contributions do not include changes or additions to the Program that - are not Modified Works. - -"Contributor" means any person or entity that Distributes the Program. - -"Licensed Patents" mean patent claims licensable by a Contributor which -are necessarily infringed by the use or sale of its Contribution alone -or when combined with the Program. - -"Program" means the Contributions Distributed in accordance with this -Agreement. - -"Recipient" means anyone who receives the Program under this Agreement -or any Secondary License (as applicable), including Contributors. - -"Derivative Works" shall mean any work, whether in Source Code or other -form, that is based on (or derived from) the Program and for which the -editorial revisions, annotations, elaborations, or other modifications -represent, as a whole, an original work of authorship. - -"Modified Works" shall mean any work in Source Code or other form that -results from an addition to, deletion from, or modification of the -contents of the Program, including, for purposes of clarity any new file -in Source Code form that contains any contents of the Program. Modified -Works shall not include works that contain only declarations, -interfaces, types, classes, structures, or files of the Program solely -in each case in order to link to, bind by name, or subclass the Program -or Modified Works thereof. - -"Distribute" means the acts of a) distributing or b) making available -in any manner that enables the transfer of a copy. - -"Source Code" means the form of a Program preferred for making -modifications, including but not limited to software source code, -documentation source, and configuration files. - -"Secondary License" means either the GNU General Public License, -Version 2.0, or any later versions of that license, including any -exceptions or additional permissions as identified by the initial -Contributor. - -2. GRANT OF RIGHTS - - a) Subject to the terms of this Agreement, each Contributor hereby - grants Recipient a non-exclusive, worldwide, royalty-free copyright - license to reproduce, prepare Derivative Works of, publicly display, - publicly perform, Distribute and sublicense the Contribution of such - Contributor, if any, and such Derivative Works. - - b) Subject to the terms of this Agreement, each Contributor hereby - grants Recipient a non-exclusive, worldwide, royalty-free patent - license under Licensed Patents to make, use, sell, offer to sell, - import and otherwise transfer the Contribution of such Contributor, - if any, in Source Code or other form. This patent license shall - apply to the combination of the Contribution and the Program if, at - the time the Contribution is added by the Contributor, such addition - of the Contribution causes such combination to be covered by the - Licensed Patents. The patent license shall not apply to any other - combinations which include the Contribution. No hardware per se is - licensed hereunder. - - c) Recipient understands that although each Contributor grants the - licenses to its Contributions set forth herein, no assurances are - provided by any Contributor that the Program does not infringe the - patent or other intellectual property rights of any other entity. - Each Contributor disclaims any liability to Recipient for claims - brought by any other entity based on infringement of intellectual - property rights or otherwise. As a condition to exercising the - rights and licenses granted hereunder, each Recipient hereby - assumes sole responsibility to secure any other intellectual - property rights needed, if any. For example, if a third party - patent license is required to allow Recipient to Distribute the - Program, it is Recipient's responsibility to acquire that license - before distributing the Program. - - d) Each Contributor represents that to its knowledge it has - sufficient copyright rights in its Contribution, if any, to grant - the copyright license set forth in this Agreement. - - e) Notwithstanding the terms of any Secondary License, no - Contributor makes additional grants to any Recipient (other than - those set forth in this Agreement) as a result of such Recipient's - receipt of the Program under the terms of a Secondary License - (if permitted under the terms of Section 3). - -3. REQUIREMENTS - -3.1 If a Contributor Distributes the Program in any form, then: - - a) the Program must also be made available as Source Code, in - accordance with section 3.2, and the Contributor must accompany - the Program with a statement that the Source Code for the Program - is available under this Agreement, and informs Recipients how to - obtain it in a reasonable manner on or through a medium customarily - used for software exchange; and - - b) the Contributor may Distribute the Program under a license - different than this Agreement, provided that such license: - i) effectively disclaims on behalf of all other Contributors all - warranties and conditions, express and implied, including - warranties or conditions of title and non-infringement, and - implied warranties or conditions of merchantability and fitness - for a particular purpose; - - ii) effectively excludes on behalf of all other Contributors all - liability for damages, including direct, indirect, special, - incidental and consequential damages, such as lost profits; - - iii) does not attempt to limit or alter the recipients' rights - in the Source Code under section 3.2; and - - iv) requires any subsequent distribution of the Program by any - party to be under a license that satisfies the requirements - of this section 3. - -3.2 When the Program is Distributed as Source Code: - - a) it must be made available under this Agreement, or if the - Program (i) is combined with other material in a separate file or - files made available under a Secondary License, and (ii) the initial - Contributor attached to the Source Code the notice described in - Exhibit A of this Agreement, then the Program may be made available - under the terms of such Secondary Licenses, and - - b) a copy of this Agreement must be included with each copy of - the Program. - -3.3 Contributors may not remove or alter any copyright, patent, -trademark, attribution notices, disclaimers of warranty, or limitations -of liability ("notices") contained within the Program from any copy of -the Program which they Distribute, provided that Contributors may add -their own appropriate notices. - -4. COMMERCIAL DISTRIBUTION - -Commercial distributors of software may accept certain responsibilities -with respect to end users, business partners and the like. While this -license is intended to facilitate the commercial use of the Program, -the Contributor who includes the Program in a commercial product -offering should do so in a manner which does not create potential -liability for other Contributors. Therefore, if a Contributor includes -the Program in a commercial product offering, such Contributor -("Commercial Contributor") hereby agrees to defend and indemnify every -other Contributor ("Indemnified Contributor") against any losses, -damages and costs (collectively "Losses") arising from claims, lawsuits -and other legal actions brought by a third party against the Indemnified -Contributor to the extent caused by the acts or omissions of such -Commercial Contributor in connection with its distribution of the Program -in a commercial product offering. The obligations in this section do not -apply to any claims or Losses relating to any actual or alleged -intellectual property infringement. In order to qualify, an Indemnified -Contributor must: a) promptly notify the Commercial Contributor in -writing of such claim, and b) allow the Commercial Contributor to control, -and cooperate with the Commercial Contributor in, the defense and any -related settlement negotiations. The Indemnified Contributor may -participate in any such claim at its own expense. - -For example, a Contributor might include the Program in a commercial -product offering, Product X. That Contributor is then a Commercial -Contributor. If that Commercial Contributor then makes performance -claims, or offers warranties related to Product X, those performance -claims and warranties are such Commercial Contributor's responsibility -alone. Under this section, the Commercial Contributor would have to -defend claims against the other Contributors related to those performance -claims and warranties, and if a court requires any other Contributor to -pay any damages as a result, the Commercial Contributor must pay -those damages. - -5. NO WARRANTY - -EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT -PERMITTED BY APPLICABLE LAW, THE PROGRAM IS PROVIDED ON AN "AS IS" -BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR -IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF -TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR -PURPOSE. Each Recipient is solely responsible for determining the -appropriateness of using and distributing the Program and assumes all -risks associated with its exercise of rights under this Agreement, -including but not limited to the risks and costs of program errors, -compliance with applicable laws, damage to or loss of data, programs -or equipment, and unavailability or interruption of operations. - -6. DISCLAIMER OF LIABILITY - -EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT -PERMITTED BY APPLICABLE LAW, NEITHER RECIPIENT NOR ANY CONTRIBUTORS -SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST -PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE -EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - -7. GENERAL - -If any provision of this Agreement is invalid or unenforceable under -applicable law, it shall not affect the validity or enforceability of -the remainder of the terms of this Agreement, and without further -action by the parties hereto, such provision shall be reformed to the -minimum extent necessary to make such provision valid and enforceable. - -If Recipient institutes patent litigation against any entity -(including a cross-claim or counterclaim in a lawsuit) alleging that the -Program itself (excluding combinations of the Program with other software -or hardware) infringes such Recipient's patent(s), then such Recipient's -rights granted under Section 2(b) shall terminate as of the date such -litigation is filed. - -All Recipient's rights under this Agreement shall terminate if it -fails to comply with any of the material terms or conditions of this -Agreement and does not cure such failure in a reasonable period of -time after becoming aware of such noncompliance. If all Recipient's -rights under this Agreement terminate, Recipient agrees to cease use -and distribution of the Program as soon as reasonably practicable. -However, Recipient's obligations under this Agreement and any licenses -granted by Recipient relating to the Program shall continue and survive. - -Everyone is permitted to copy and distribute copies of this Agreement, -but in order to avoid inconsistency the Agreement is copyrighted and -may only be modified in the following manner. The Agreement Steward -reserves the right to publish new versions (including revisions) of -this Agreement from time to time. No one other than the Agreement -Steward has the right to modify this Agreement. The Eclipse Foundation -is the initial Agreement Steward. The Eclipse Foundation may assign the -responsibility to serve as the Agreement Steward to a suitable separate -entity. Each new version of the Agreement will be given a distinguishing -version number. The Program (including Contributions) may always be -Distributed subject to the version of the Agreement under which it was -received. In addition, after a new version of the Agreement is published, -Contributor may elect to Distribute the Program (including its -Contributions) under the new version. - -Except as expressly stated in Sections 2(a) and 2(b) above, Recipient -receives no rights or licenses to the intellectual property of any -Contributor under this Agreement, whether expressly, by implication, -estoppel or otherwise. All rights in the Program not expressly granted -under this Agreement are reserved. Nothing in this Agreement is intended -to be enforceable by any entity that is not a Contributor or Recipient. -No third-party beneficiary rights are created under this Agreement. - -Exhibit A - Form of Secondary Licenses Notice - -"This Source Code may also be made available under the following -Secondary Licenses when the conditions for such availability set forth -in the Eclipse Public License, v. 2.0 are satisfied: {name license(s), -version(s), and exceptions or additional permissions here}." - - Simply including a copy of this Agreement, including this Exhibit A - is not sufficient to license the Source Code under Secondary Licenses. - - If it is not possible or desirable to put the notice in a particular - file, then You may include the notice in a location (such as a LICENSE - file in a relevant directory) where a recipient would be likely to - look for such a notice. - - You may add additional accurate notices of copyright ownership. \ No newline at end of file diff --git a/bundles/org.openhab.binding.flicbutton/README.md b/bundles/org.openhab.binding.flicbutton/README.md index e111e3d455d59..07a60d56bf04d 100644 --- a/bundles/org.openhab.binding.flicbutton/README.md +++ b/bundles/org.openhab.binding.flicbutton/README.md @@ -20,6 +20,7 @@ is not required anymore. ## Discovery * There is no automatic discovery for flicd-bridge available. + * After flicd-bridge is (manually) configured, buttons will be automatically discovered via background discovery as soon as they're addded with [simpleclient](/~https://github.com/50ButtonsEach/fliclib-linux-hci) . If they're already attached to the flicd-bridge before configuring this binding, they can be discovered by triggering an active scan. @@ -45,17 +46,17 @@ If flicd is running on a remote host, please do not forget to start it with the ### button -There are no configuration parameters for buttons available and normally no textual configuration is necessary as buttons are autodiscovered as soon as the bridge is configured. If you want to use textual configuration anyway, you can do it like this: +For the button, the only config parameter is the MAC address. Normally, no textual configuration is necessary as buttons are autodiscovered as soon as the bridge is configured. If you want to use textual configuration anyway, you can do it like this: ``` Bridge flicbutton:flicd-bridge:mybridge [ hostname="", port=""] { - Thing button "" - Thing button "" + Thing button myflic1 "" [address = ] + Thing button myflic2 "" [address = ] ... } ``` -You can lookup the MAC addresses of your buttons within the inbox of Paper UI. You're free to choose any label you like for your button. +You can lookup the MAC addresses of your buttons within the inbox of the UI. You're free to choose any label you like for your button. ## Channels @@ -72,7 +73,7 @@ You can lookup the MAC addresses of your buttons within the inbox of Paper UI. Y 1. Setup and run flicd as described in [fliclib-linux-hci](/~https://github.com/50ButtonsEach/fliclib-linux-hci). Please consider that you need a seperate Bluetooth adapter. Shared usage with other Bluetooth services (e.g. Bluez) is not possible. 1. Connect your buttons to flicd using the simpleclient as described in [fliclib-linux-hci](/~https://github.com/50ButtonsEach/fliclib-linux-hci). Flicd has to run in background the whole time, simpleclient can be killed after you successfully tested the button connection. -1. Add a flicd-bridge via PaperUI or Textual Configuration. Please consider that flicd does only accept connections from localhost by default, to enable remote connections from openHAB you have to use the `--server-addr` parameter as described in [fliclib-linux-hci](/~https://github.com/50ButtonsEach/fliclib-linux-hci). +1. Add a flicd-bridge via UI or Textual Configuration. Please consider that flicd does only accept connections from localhost by default, to enable remote connections from openHAB you have to use the `--server-addr` parameter as described in [fliclib-linux-hci](/~https://github.com/50ButtonsEach/fliclib-linux-hci). 1. When the bridge is online, buttons newly added via simpleclient will automatically get discovered via background Discovery. To discover buttons that were set up before the Binding setup, please run an active scan. ### Configuration Example using Profiles @@ -82,17 +83,17 @@ You can lookup the MAC addresses of your buttons within the inbox of Paper UI. Y demo.things: ``` -Bridge bluetooth:bluegiga:bluegiga0 "Bluegiga Adapter" [ port="/dev/ttyBLUEGIGA", discovery=false ] { - Thing ptm215b rocker_livingroom "Rocker Living Room" [ address = "E2:15:00:00:53:F9" ] - Thing ptm215b rocker_kitchen "Rocker Kitchen" [ address = "E2:15:00:00:53:98" ] +Bridge flicbutton:flicd-bridge:local-flicd { + Thing button flic_livingroom "Yellow Button Living Room" [address = "60:13:B3:02:18:BD"] + Thing button flic_kitchen "Black Button Kitchen" [address = "B5:7E:59:78:86:9F"] } ``` demo.items: ``` -Dimmer Light_LivingRoom { channel="milight:rgbLed:milight2:4:ledbrightness", channel="bluetooth:ptm215b:bluegiga0:rocker_livingroom:rocker1" [profile="rawbutton-to-on-off"], channel="bluetooth:ptm215b:bluegiga0:rocker_kitchen:rocker1" [profile="rawbutton-to-on-off"] } // We have a combined kitchen / livingroom, so we control the living room lights with switches from the living room and from the kitchen -Switch Light_Kitchen { channel="hue:group:1:kitchen-bulbs:switch", channel="bluetooth:ptm215b:bluegiga0:rocker_kitchen:rocker2" [profile="rawbutton-to-on-off"] } +Dimmer Light_LivingRoom { channel="milight:rgbLed:milight2:4:ledbrightness", channel="flicbutton:button:local-flicd:flic_livingroom:rawbutton" [profile="rawbutton-toggle-switch"], channel="flicbutton:button:local-flicd:flic_kitchen:rawbutton" [profile="rawbutton-toggle-switch"] } // We have a combined kitchen / livingroom, so we control the living room lights with switches from the living room and from the kitchen +Switch Light_Kitchen { channel="hue:group:1:kitchen-bulbs:switch", channel="flicbutton:button:local-flicd:flic_kitchen:rawbutton" [profile="rawbutton-toggle-switch"] } ``` ### Configuration Example using Rules @@ -103,7 +104,7 @@ The following rules help to initially test your setup as they'll trigger log mes rule "Button rule using the button channel" when - Channel "flicbutton:button:1:80-e4-da-71-12-34:button" triggered SHORT_PRESSED + Channel "flicbutton:button:local-flicd:flic_livingroom:button" triggered SHORT_PRESSED then logInfo("Flic", "Flic 'short pressed' triggered") end @@ -111,7 +112,7 @@ The following rules help to initially test your setup as they'll trigger log mes rule "Button rule directly using the rawbutton channel" when - Channel "flicbutton:button:1:80-e4-da-71-12-34:rawbutton" triggered + Channel "flicbutton:button:local-flicd:flic_livingroom:rawbutton" triggered then logInfo("Flic", "Flic pressed: " + receivedEvent.event) end diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/FlicButtonBindingConstants.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/FlicButtonBindingConstants.java index 7245d07630cdd..c1d45b5559f28 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/FlicButtonBindingConstants.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/FlicButtonBindingConstants.java @@ -1,17 +1,14 @@ /** - * Copyright (c) 2016 - 2020 Patrick Fink + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the Eclipse - * Public License, v. 2.0 are satisfied: GNU General Public License, version 3 - * with the GNU Classpath Exception 2.0 which is - * available at https://www.gnu.org/software/classpath/license.html. + * http://www.eclipse.org/legal/epl-2.0 * - * SPDX-License-Identifier: EPL-2.0 OR GPL-3.0 WITH Classpath-exception-2.0 + * SPDX-License-Identifier: EPL-2.0 */ package org.openhab.binding.flicbutton; diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/ChildThingHandler.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/ChildThingHandler.java index 183193a73b9c9..69e737be6c49b 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/ChildThingHandler.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/ChildThingHandler.java @@ -1,17 +1,14 @@ /** - * Copyright (c) 2016 - 2020 Patrick Fink + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the Eclipse - * Public License, v. 2.0 are satisfied: GNU General Public License, version 3 - * with the GNU Classpath Exception 2.0 which is - * available at https://www.gnu.org/software/classpath/license.html. + * http://www.eclipse.org/legal/epl-2.0 * - * SPDX-License-Identifier: EPL-2.0 OR GPL-3.0 WITH Classpath-exception-2.0 + * SPDX-License-Identifier: EPL-2.0 */ package org.openhab.binding.flicbutton.handler; @@ -26,7 +23,7 @@ import org.openhab.core.thing.binding.BridgeHandler; /** - * @author Patrick Fink + * @author Patrick Fink - Initial contribution * @param The bridge type this child handler depends on */ public abstract class ChildThingHandler extends BaseThingHandler { diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicButtonBatteryLevelListener.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicButtonBatteryLevelListener.java index 145129d51f15a..b123ca356f49b 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicButtonBatteryLevelListener.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicButtonBatteryLevelListener.java @@ -1,17 +1,14 @@ /** - * Copyright (c) 2016 - 2020 Patrick Fink + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the Eclipse - * Public License, v. 2.0 are satisfied: GNU General Public License, version 3 - * with the GNU Classpath Exception 2.0 which is - * available at https://www.gnu.org/software/classpath/license.html. + * http://www.eclipse.org/legal/epl-2.0 * - * SPDX-License-Identifier: EPL-2.0 OR GPL-3.0 WITH Classpath-exception-2.0 + * SPDX-License-Identifier: EPL-2.0 */ package org.openhab.binding.flicbutton.handler; diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicButtonEventListener.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicButtonEventListener.java index d6a2a29b1375c..12cd08eb76284 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicButtonEventListener.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicButtonEventListener.java @@ -1,17 +1,14 @@ /** - * Copyright (c) 2016 - 2020 Patrick Fink + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the Eclipse - * Public License, v. 2.0 are satisfied: GNU General Public License, version 3 - * with the GNU Classpath Exception 2.0 which is - * available at https://www.gnu.org/software/classpath/license.html. + * http://www.eclipse.org/legal/epl-2.0 * - * SPDX-License-Identifier: EPL-2.0 OR GPL-3.0 WITH Classpath-exception-2.0 + * SPDX-License-Identifier: EPL-2.0 */ package org.openhab.binding.flicbutton.handler; diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicButtonHandler.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicButtonHandler.java index 8f1d92ff5b388..e999aeaa683dc 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicButtonHandler.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicButtonHandler.java @@ -1,17 +1,14 @@ /** - * Copyright (c) 2016 - 2020 Patrick Fink + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the Eclipse - * Public License, v. 2.0 are satisfied: GNU General Public License, version 3 - * with the GNU Classpath Exception 2.0 which is - * available at https://www.gnu.org/software/classpath/license.html. + * http://www.eclipse.org/legal/epl-2.0 * - * SPDX-License-Identifier: EPL-2.0 OR GPL-3.0 WITH Classpath-exception-2.0 + * SPDX-License-Identifier: EPL-2.0 */ package org.openhab.binding.flicbutton.handler; diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicDaemonBridgeConfiguration.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicDaemonBridgeConfiguration.java index f01ea71e36def..4b3187aef7994 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicDaemonBridgeConfiguration.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicDaemonBridgeConfiguration.java @@ -1,28 +1,28 @@ /** - * Copyright (c) 2016 - 2020 Patrick Fink + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the Eclipse - * Public License, v. 2.0 are satisfied: GNU General Public License, version 3 - * with the GNU Classpath Exception 2.0 which is - * available at https://www.gnu.org/software/classpath/license.html. + * http://www.eclipse.org/legal/epl-2.0 * - * SPDX-License-Identifier: EPL-2.0 OR GPL-3.0 WITH Classpath-exception-2.0 + * SPDX-License-Identifier: EPL-2.0 */ package org.openhab.binding.flicbutton.handler; import java.net.InetAddress; import java.net.UnknownHostException; +import org.eclipse.jdt.annotation.NonNullByDefault; + /** * - * @author Patrick Fink + * @author Patrick Fink - Initial contribution * */ +@NonNullByDefault public class FlicDaemonBridgeConfiguration { private final InetAddress hostname; diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicDaemonBridgeHandler.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicDaemonBridgeHandler.java index ae127ae7351ce..1f08cb45b96fc 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicDaemonBridgeHandler.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicDaemonBridgeHandler.java @@ -1,17 +1,14 @@ /** - * Copyright (c) 2016 - 2020 Patrick Fink + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the Eclipse - * Public License, v. 2.0 are satisfied: GNU General Public License, version 3 - * with the GNU Classpath Exception 2.0 which is - * available at https://www.gnu.org/software/classpath/license.html. + * http://www.eclipse.org/legal/epl-2.0 * - * SPDX-License-Identifier: EPL-2.0 OR GPL-3.0 WITH Classpath-exception-2.0 + * SPDX-License-Identifier: EPL-2.0 */ package org.openhab.binding.flicbutton.handler; diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/FlicButtonHandlerFactory.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/FlicButtonHandlerFactory.java index bfecf09c307dd..11901a4eb04b8 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/FlicButtonHandlerFactory.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/FlicButtonHandlerFactory.java @@ -1,17 +1,14 @@ /** - * Copyright (c) 2016 - 2020 Patrick Fink + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the Eclipse - * Public License, v. 2.0 are satisfied: GNU General Public License, version 3 - * with the GNU Classpath Exception 2.0 which is - * available at https://www.gnu.org/software/classpath/license.html. + * http://www.eclipse.org/legal/epl-2.0 * - * SPDX-License-Identifier: EPL-2.0 OR GPL-3.0 WITH Classpath-exception-2.0 + * SPDX-License-Identifier: EPL-2.0 */ package org.openhab.binding.flicbutton.internal; diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/discovery/FlicButtonDiscoveryService.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/discovery/FlicButtonDiscoveryService.java index ce5efa6c79d01..d76efbae668ea 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/discovery/FlicButtonDiscoveryService.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/discovery/FlicButtonDiscoveryService.java @@ -1,21 +1,19 @@ /** - * Copyright (c) 2016 - 2020 Patrick Fink + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the Eclipse - * Public License, v. 2.0 are satisfied: GNU General Public License, version 3 - * with the GNU Classpath Exception 2.0 which is - * available at https://www.gnu.org/software/classpath/license.html. + * http://www.eclipse.org/legal/epl-2.0 * - * SPDX-License-Identifier: EPL-2.0 OR GPL-3.0 WITH Classpath-exception-2.0 + * SPDX-License-Identifier: EPL-2.0 */ package org.openhab.binding.flicbutton.internal.discovery; import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.NonNullByDefault; import org.openhab.core.config.discovery.DiscoveryService; import org.openhab.core.thing.ThingUID; @@ -27,6 +25,7 @@ * @author Patrick Fink * */ +@NonNullByDefault public interface FlicButtonDiscoveryService extends DiscoveryService { /** diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/discovery/FlicSimpleclientDiscoveryServiceImpl.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/discovery/FlicSimpleclientDiscoveryServiceImpl.java index 4348675b23332..4385ee4ecb0ed 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/discovery/FlicSimpleclientDiscoveryServiceImpl.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/discovery/FlicSimpleclientDiscoveryServiceImpl.java @@ -1,17 +1,14 @@ /** - * Copyright (c) 2016 - 2020 Patrick Fink + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the Eclipse - * Public License, v. 2.0 are satisfied: GNU General Public License, version 3 - * with the GNU Classpath Exception 2.0 which is - * available at https://www.gnu.org/software/classpath/license.html. + * http://www.eclipse.org/legal/epl-2.0 * - * SPDX-License-Identifier: EPL-2.0 OR GPL-3.0 WITH Classpath-exception-2.0 + * SPDX-License-Identifier: EPL-2.0 */ package org.openhab.binding.flicbutton.internal.discovery; diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/util/FlicButtonUtils.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/util/FlicButtonUtils.java index 753ecf67d66eb..69c6aea428f51 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/util/FlicButtonUtils.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/util/FlicButtonUtils.java @@ -1,17 +1,14 @@ /** - * Copyright (c) 2016 - 2020 Patrick Fink + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the Eclipse - * Public License, v. 2.0 are satisfied: GNU General Public License, version 3 - * with the GNU Classpath Exception 2.0 which is - * available at https://www.gnu.org/software/classpath/license.html. + * http://www.eclipse.org/legal/epl-2.0 * - * SPDX-License-Identifier: EPL-2.0 OR GPL-3.0 WITH Classpath-exception-2.0 + * SPDX-License-Identifier: EPL-2.0 */ package org.openhab.binding.flicbutton.internal.util; @@ -19,6 +16,7 @@ import java.util.HashMap; import java.util.Map; +import org.eclipse.jdt.annotation.NonNullByDefault; import org.openhab.binding.flicbutton.FlicButtonBindingConstants; import org.openhab.core.thing.CommonTriggerEvents; import org.openhab.core.thing.ThingUID; @@ -27,9 +25,10 @@ /** * - * @author Patrick Fink + * @author Patrick Fink - Initial contribution * */ +@NonNullByDefault public class FlicButtonUtils { public static final Map flicOpenhabTriggerEventMap = Collections .unmodifiableMap(new HashMap() { diff --git a/bundles/org.openhab.binding.flicbutton/src/main/resources/OH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.flicbutton/src/main/resources/OH-INF/thing/thing-types.xml index 29005bcd66e65..cdd2e898ec90a 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/resources/OH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.flicbutton/src/main/resources/OH-INF/thing/thing-types.xml @@ -28,16 +28,16 @@ The thing(-type) representing a Flic Button + + + + + Bluetooth address in XX:XX:XX:XX:XX:XX format - - - - - diff --git a/bundles/org.openhab.binding.flicbutton/tools/checkstyle.properties b/bundles/org.openhab.binding.flicbutton/tools/checkstyle.properties deleted file mode 100644 index 24f082c8f618a..0000000000000 --- a/bundles/org.openhab.binding.flicbutton/tools/checkstyle.properties +++ /dev/null @@ -1,7 +0,0 @@ -checkstyle.forbiddenPackageUsageCheck.forbiddenPackages= -checkstyle.forbiddenPackageUsageCheck.exceptions= -checkstyle.headerCheck.content=^/\\*\\*$\\n^ \\* Copyright \\(c\\) {0} - {1} Patrick Fink$\\n^ \\*$\\n^ \\* This program and the accompanying materials are made available under the$\\n^ \\* terms of the Eclipse Public License 2\\.0 which is available at$\\n^ \\* http://www.eclipse.org/legal/epl\\-2\\.0.$ -checkstyle.headerCheck.values=2016,2020 -checkstyle.requiredFilesCheck.extensions=xml,md -checkstyle.requiredFilesCheck.files=pom.xml -checkstyle.pomXmlCheck.checkPomVersion=false \ No newline at end of file From 42b2180527096825fc596bda097f402840bed7c2 Mon Sep 17 00:00:00 2001 From: Patrick Fink Date: Tue, 15 Dec 2020 03:26:44 +0100 Subject: [PATCH 05/37] Apply suggestions from code review Co-authored-by: Fabian Wolter --- bundles/org.openhab.binding.flicbutton/README.md | 2 +- .../binding/flicbutton/handler/ChildThingHandler.java | 1 + .../binding/flicbutton/handler/FlicButtonHandler.java | 2 +- .../flicbutton/handler/FlicDaemonBridgeHandler.java | 8 +------- .../src/main/resources/OH-INF/thing/thing-types.xml | 2 +- 5 files changed, 5 insertions(+), 10 deletions(-) diff --git a/bundles/org.openhab.binding.flicbutton/README.md b/bundles/org.openhab.binding.flicbutton/README.md index 07a60d56bf04d..ac605cda30098 100644 --- a/bundles/org.openhab.binding.flicbutton/README.md +++ b/bundles/org.openhab.binding.flicbutton/README.md @@ -22,7 +22,7 @@ is not required anymore. * There is no automatic discovery for flicd-bridge available. * After flicd-bridge is (manually) configured, buttons will be automatically discovered via background discovery as soon - as they're addded with [simpleclient](/~https://github.com/50ButtonsEach/fliclib-linux-hci) . If they're already + as they're addded with [simpleclient](/~https://github.com/50ButtonsEach/fliclib-linux-hci). If they're already attached to the flicd-bridge before configuring this binding, they can be discovered by triggering an active scan. ## Thing Configuration diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/ChildThingHandler.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/ChildThingHandler.java index 69e737be6c49b..6add12e15161b 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/ChildThingHandler.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/ChildThingHandler.java @@ -36,6 +36,7 @@ public ChildThingHandler(Thing thing) { super(thing); } + @Override public void initialize() { setStatusBasedOnBridge(); if (bridgeValid) { diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicButtonHandler.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicButtonHandler.java index e999aeaa683dc..b4c1a7d1d53fe 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicButtonHandler.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicButtonHandler.java @@ -127,7 +127,7 @@ void connectionStatusChanged(ConnectionStatus connectionStatus, DisconnectReason private void scheduleStatusChangeToOffline() { if (delayedDisconnectTask == null) { - delayedDisconnectTask = scheduler.schedule(() -> setOffline(), BUTTON_OFFLINE_GRACE_PERIOD_SECONDS, + delayedDisconnectTask = scheduler.schedule(this::setOffline, BUTTON_OFFLINE_GRACE_PERIOD_SECONDS, TimeUnit.SECONDS); } } diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicDaemonBridgeHandler.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicDaemonBridgeHandler.java index 1f08cb45b96fc..89bff5a0091c2 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicDaemonBridgeHandler.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicDaemonBridgeHandler.java @@ -125,7 +125,6 @@ private void initThingStatus() { public void dispose() { super.dispose(); for (Future startedTask : startedTasks) { - if (!startedTask.isDone()) { startedTask.cancel(true); } } @@ -134,12 +133,7 @@ public void dispose() { } private void scheduleReinitialize() { - startedTasks.add(scheduler.schedule(new Runnable() { - @Override - public void run() { - initialize(); - } - }, REINITIALIZE_DELAY_SECONDS, TimeUnit.SECONDS)); + startedTasks.add(scheduler.schedule(this::initialize, REINITIALIZE_DELAY_SECONDS, TimeUnit.SECONDS)); } @Override diff --git a/bundles/org.openhab.binding.flicbutton/src/main/resources/OH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.flicbutton/src/main/resources/OH-INF/thing/thing-types.xml index cdd2e898ec90a..46f95a9888414 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/resources/OH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.flicbutton/src/main/resources/OH-INF/thing/thing-types.xml @@ -11,7 +11,7 @@ - IP or Host name of the Flic daemon (flicd). Defaults to localhost. + IP or Host name of the Flic daemon (flicd). localhost From 02cb32022c08af6b25aee5d50d60d574a37d33e5 Mon Sep 17 00:00:00 2001 From: Patrick Fink Date: Mon, 1 Mar 2021 04:30:26 +0100 Subject: [PATCH 06/37] [flicbutton] Update LICENSE Signed-off-by: Patrick Fink --- .../openhab/binding/flicbutton/FlicButtonBindingConstants.java | 2 +- .../openhab/binding/flicbutton/handler/ChildThingHandler.java | 2 +- .../flicbutton/handler/FlicButtonBatteryLevelListener.java | 2 +- .../binding/flicbutton/handler/FlicButtonEventListener.java | 2 +- .../openhab/binding/flicbutton/handler/FlicButtonHandler.java | 2 +- .../flicbutton/handler/FlicDaemonBridgeConfiguration.java | 2 +- .../binding/flicbutton/handler/FlicDaemonBridgeHandler.java | 2 +- .../binding/flicbutton/internal/FlicButtonHandlerFactory.java | 2 +- .../internal/discovery/FlicButtonDiscoveryService.java | 2 +- .../discovery/FlicSimpleclientDiscoveryServiceImpl.java | 2 +- .../binding/flicbutton/internal/util/FlicButtonUtils.java | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/FlicButtonBindingConstants.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/FlicButtonBindingConstants.java index c1d45b5559f28..27eb430ee96c2 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/FlicButtonBindingConstants.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/FlicButtonBindingConstants.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2020 Contributors to the openHAB project + * Copyright (c) 2010-2021 Contributors to the openHAB project * * See the NOTICE file(s) distributed with this work for additional * information. diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/ChildThingHandler.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/ChildThingHandler.java index 6add12e15161b..725e46cde70d1 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/ChildThingHandler.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/ChildThingHandler.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2020 Contributors to the openHAB project + * Copyright (c) 2010-2021 Contributors to the openHAB project * * See the NOTICE file(s) distributed with this work for additional * information. diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicButtonBatteryLevelListener.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicButtonBatteryLevelListener.java index b123ca356f49b..704d13b0ef2dd 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicButtonBatteryLevelListener.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicButtonBatteryLevelListener.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2020 Contributors to the openHAB project + * Copyright (c) 2010-2021 Contributors to the openHAB project * * See the NOTICE file(s) distributed with this work for additional * information. diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicButtonEventListener.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicButtonEventListener.java index 12cd08eb76284..495bae472fb23 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicButtonEventListener.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicButtonEventListener.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2020 Contributors to the openHAB project + * Copyright (c) 2010-2021 Contributors to the openHAB project * * See the NOTICE file(s) distributed with this work for additional * information. diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicButtonHandler.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicButtonHandler.java index b4c1a7d1d53fe..457efbec3535a 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicButtonHandler.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicButtonHandler.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2020 Contributors to the openHAB project + * Copyright (c) 2010-2021 Contributors to the openHAB project * * See the NOTICE file(s) distributed with this work for additional * information. diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicDaemonBridgeConfiguration.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicDaemonBridgeConfiguration.java index 4b3187aef7994..525132f0d8616 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicDaemonBridgeConfiguration.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicDaemonBridgeConfiguration.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2020 Contributors to the openHAB project + * Copyright (c) 2010-2021 Contributors to the openHAB project * * See the NOTICE file(s) distributed with this work for additional * information. diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicDaemonBridgeHandler.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicDaemonBridgeHandler.java index 89bff5a0091c2..39f7c0df6a5a4 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicDaemonBridgeHandler.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicDaemonBridgeHandler.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2020 Contributors to the openHAB project + * Copyright (c) 2010-2021 Contributors to the openHAB project * * See the NOTICE file(s) distributed with this work for additional * information. diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/FlicButtonHandlerFactory.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/FlicButtonHandlerFactory.java index 11901a4eb04b8..30c1fc430b6b3 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/FlicButtonHandlerFactory.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/FlicButtonHandlerFactory.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2020 Contributors to the openHAB project + * Copyright (c) 2010-2021 Contributors to the openHAB project * * See the NOTICE file(s) distributed with this work for additional * information. diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/discovery/FlicButtonDiscoveryService.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/discovery/FlicButtonDiscoveryService.java index d76efbae668ea..ccf3e4257cb66 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/discovery/FlicButtonDiscoveryService.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/discovery/FlicButtonDiscoveryService.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2020 Contributors to the openHAB project + * Copyright (c) 2010-2021 Contributors to the openHAB project * * See the NOTICE file(s) distributed with this work for additional * information. diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/discovery/FlicSimpleclientDiscoveryServiceImpl.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/discovery/FlicSimpleclientDiscoveryServiceImpl.java index 4385ee4ecb0ed..e06796f0db898 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/discovery/FlicSimpleclientDiscoveryServiceImpl.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/discovery/FlicSimpleclientDiscoveryServiceImpl.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2020 Contributors to the openHAB project + * Copyright (c) 2010-2021 Contributors to the openHAB project * * See the NOTICE file(s) distributed with this work for additional * information. diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/util/FlicButtonUtils.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/util/FlicButtonUtils.java index 69c6aea428f51..7b1e6a1cfdec4 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/util/FlicButtonUtils.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/util/FlicButtonUtils.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2020 Contributors to the openHAB project + * Copyright (c) 2010-2021 Contributors to the openHAB project * * See the NOTICE file(s) distributed with this work for additional * information. From aeab4eb461b64273c12af7441110e33ae71d2d8c Mon Sep 17 00:00:00 2001 From: Patrick Fink Date: Mon, 1 Mar 2021 05:19:26 +0100 Subject: [PATCH 07/37] [flicbutton] Apply suggestions from code review (2) & update to 3.1-SNAPSHOT Signed-off-by: Patrick Fink --- .../org.openhab.binding.flicbutton/README.md | 40 +++++++++---------- .../org.openhab.binding.flicbutton/pom.xml | 2 +- .../flicbutton/handler/FlicButtonHandler.java | 2 +- .../handler/FlicDaemonBridgeHandler.java | 15 +++---- .../main/resources/OH-INF/binding/binding.xml | 3 +- .../resources/OH-INF/thing/thing-types.xml | 1 + 6 files changed, 30 insertions(+), 33 deletions(-) diff --git a/bundles/org.openhab.binding.flicbutton/README.md b/bundles/org.openhab.binding.flicbutton/README.md index ac605cda30098..50ef94aec8aea 100644 --- a/bundles/org.openhab.binding.flicbutton/README.md +++ b/bundles/org.openhab.binding.flicbutton/README.md @@ -39,7 +39,7 @@ The default host is localhost:5551 (this should be sufficient if flicd is runnin server as openHAB). If your flicd service is running somewhere else, specify it like this: ``` -Bridge flicbutton:flicd-bridge:mybridge [ hostname="", port=""] +Bridge flicbutton:flicd-bridge:mybridge [ hostname="", port=] ``` If flicd is running on a remote host, please do not forget to start it with the parameter `-s `, otherwise it won't be accessible for openHAB (more details on [fliclib-linux-hci](/~https://github.com/50ButtonsEach/fliclib-linux-hci)). @@ -50,8 +50,8 @@ For the button, the only config parameter is the MAC address. Normally, no textu ``` Bridge flicbutton:flicd-bridge:mybridge [ hostname="", port=""] { - Thing button myflic1 "" [address = ] - Thing button myflic2 "" [address = ] + Thing button myflic1 "" [address =""] + Thing button myflic2 "" [address =""] ... } ``` @@ -100,20 +100,20 @@ Switch Light_Kitchen { channel="hue:group:1:kitchen-bulbs:switch", channel="f It's also possible to setup [Rules](https://www.openhab.org/docs/configuration/rules-dsl.html). The following rules help to initially test your setup as they'll trigger log messages on incoming events. - ``` - rule "Button rule using the button channel" - - when - Channel "flicbutton:button:local-flicd:flic_livingroom:button" triggered SHORT_PRESSED - then - logInfo("Flic", "Flic 'short pressed' triggered") - end - - rule "Button rule directly using the rawbutton channel" - - when - Channel "flicbutton:button:local-flicd:flic_livingroom:rawbutton" triggered - then - logInfo("Flic", "Flic pressed: " + receivedEvent.event) - end - ``` +``` +rule "Button rule using the button channel" + +when + Channel "flicbutton:button:local-flicd:flic_livingroom:button" triggered SHORT_PRESSED +then + logInfo("Flic", "Flic 'short pressed' triggered") +end + +rule "Button rule directly using the rawbutton channel" + +when + Channel "flicbutton:button:local-flicd:flic_livingroom:rawbutton" triggered +then + logInfo("Flic", "Flic pressed: " + receivedEvent.event) +end +``` diff --git a/bundles/org.openhab.binding.flicbutton/pom.xml b/bundles/org.openhab.binding.flicbutton/pom.xml index 6c898106b4d91..93219a4a77d3a 100644 --- a/bundles/org.openhab.binding.flicbutton/pom.xml +++ b/bundles/org.openhab.binding.flicbutton/pom.xml @@ -7,7 +7,7 @@ org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 3.0.0-SNAPSHOT + 3.1.0-SNAPSHOT org.openhab.binding.flicbutton diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicButtonHandler.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicButtonHandler.java index 457efbec3535a..12c91e554efcb 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicButtonHandler.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicButtonHandler.java @@ -101,7 +101,7 @@ public void dispose() { bridgeHandler.getFlicClient().removeBatteryStatusListener(this.batteryConnection); } } catch (IOException e) { - logger.error("Error occured while removing button channel", e); + logger.warn("Button channel could not be properly removed", e); } super.dispose(); diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicDaemonBridgeHandler.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicDaemonBridgeHandler.java index 39f7c0df6a5a4..857830e86ff35 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicDaemonBridgeHandler.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicDaemonBridgeHandler.java @@ -60,8 +60,6 @@ public FlicClient getFlicClient() { @Override public void initialize() { - logger.debug("Initialize Fliclib bridge"); - try { initConfigParameters(); startFlicdClientAsync(); @@ -73,8 +71,8 @@ public void initialize() { updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "Configuration (hostname, port) is invalid and cannot be parsed."); } catch (IOException e) { - logger.warn("Error occured while connecting to flicd", e); - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "Error connecting to flicd!"); + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, + "Error connecting to flicd!\n" + e); } } @@ -93,9 +91,9 @@ private void startFlicdClientAsync() throws IOException { Runnable flicClientService = () -> { try { flicClient.handleEvents(); - logger.info("Listening to flicd unexpectedly ended"); - } catch (Exception e) { - logger.info("Error occured while listening to flicd", e); + logger.warn("Listening to flicd unexpectedly ended"); + } catch (IOException e) { + logger.debug("Error occured while listening to flicd", e); } finally { onClientFailure(); } @@ -125,8 +123,7 @@ private void initThingStatus() { public void dispose() { super.dispose(); for (Future startedTask : startedTasks) { - startedTask.cancel(true); - } + startedTask.cancel(true); } startedTasks = new ArrayList<>(2); buttonDiscoveryService.deactivate(); diff --git a/bundles/org.openhab.binding.flicbutton/src/main/resources/OH-INF/binding/binding.xml b/bundles/org.openhab.binding.flicbutton/src/main/resources/OH-INF/binding/binding.xml index bd9fe6fdf043a..8055604ca2001 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/resources/OH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.flicbutton/src/main/resources/OH-INF/binding/binding.xml @@ -4,7 +4,6 @@ xsi:schemaLocation="https://openhab.org/schemas/binding/v1.0.0 https://openhab.org/schemas/binding-1.0.0.xsd"> FlicButton Binding - This is the binding for FlicButton. - Patrick Fink + This is the binding for Flic buttons by Shortcut Labs. diff --git a/bundles/org.openhab.binding.flicbutton/src/main/resources/OH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.flicbutton/src/main/resources/OH-INF/thing/thing-types.xml index 46f95a9888414..3eb811fdb94af 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/resources/OH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.flicbutton/src/main/resources/OH-INF/thing/thing-types.xml @@ -10,6 +10,7 @@ + network-address IP or Host name of the Flic daemon (flicd). localhost From 94fa83e30675f9040909339fb868701270f855f8 Mon Sep 17 00:00:00 2001 From: Patrick Fink Date: Mon, 1 Mar 2021 06:21:11 +0100 Subject: [PATCH 08/37] [flicbutton] Apply suggestions from code review (3) & fix offline status Signed-off-by: Patrick Fink --- .../flicbutton/handler/FlicButtonHandler.java | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicButtonHandler.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicButtonHandler.java index 12c91e554efcb..49fc7f00698ef 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicButtonHandler.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicButtonHandler.java @@ -81,11 +81,14 @@ public void initializeThing() { bridgeHandler.getFlicClient().addConnectionChannel(eventConnection); this.eventConnection = eventConnection; eventListener.wait(5000); - // Listener calls initializeStatus() before notifying so that ThingStatus is set at this point + // Listener calls initializeStatus() before notifying so that ThingStatus is should be set at this point + if (this.getThing().getStatus().equals(ThingStatus.INITIALIZING)) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, + "Got no response by eventListener"); + } } } catch (IOException | InterruptedException e) { - logger.info("Connection setup for Flic Button {} failed.", this.getThing(), e); - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "Connection setup failed"); + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "Connection setup failed. " + e); } } @@ -118,7 +121,8 @@ void initializeStatus(ConnectionStatus connectionStatus) { void connectionStatusChanged(ConnectionStatus connectionStatus, DisconnectReason disconnectReason) { latestDisconnectReason = disconnectReason; if (connectionStatus == ConnectionStatus.Disconnected) { - // Status change to offline have to be scheduled to improve stability, see issue #2 + // Status change to offline have to be scheduled to improve stability, + // see /~https://github.com/pfink/openhab2-flicbutton/issues/2 scheduleStatusChangeToOffline(); } else { setOnline(); @@ -137,7 +141,7 @@ protected void setOnline() { } protected void setOffline() { - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR, + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.NONE, "Disconnect Reason: " + Objects.toString(latestDisconnectReason)); } From 6f183795aff7093f40e40dde70fe463d8ff075d6 Mon Sep 17 00:00:00 2001 From: Patrick Fink Date: Tue, 2 Mar 2021 23:19:35 +0100 Subject: [PATCH 09/37] [flicbutton] Fix 3rd party source for proper IDE integration Signed-off-by: Patrick Fink --- bundles/org.openhab.binding.flicbutton/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundles/org.openhab.binding.flicbutton/pom.xml b/bundles/org.openhab.binding.flicbutton/pom.xml index 93219a4a77d3a..d36ac4cdbed9c 100644 --- a/bundles/org.openhab.binding.flicbutton/pom.xml +++ b/bundles/org.openhab.binding.flicbutton/pom.xml @@ -27,7 +27,7 @@ generate-sources - src/3rdparty + src/3rdparty/java From a95559a114c1682c14248e2db388ddf0ea90618c Mon Sep 17 00:00:00 2001 From: Patrick Fink Date: Tue, 2 Mar 2021 23:34:22 +0100 Subject: [PATCH 10/37] [flicbutton] Simplify config parsing Signed-off-by: Patrick Fink --- .../FlicDaemonBridgeConfiguration.java | 33 ++++--------------- .../handler/FlicDaemonBridgeHandler.java | 8 ++--- 2 files changed, 10 insertions(+), 31 deletions(-) diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicDaemonBridgeConfiguration.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicDaemonBridgeConfiguration.java index 525132f0d8616..e557c6417bcf9 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicDaemonBridgeConfiguration.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicDaemonBridgeConfiguration.java @@ -25,36 +25,17 @@ @NonNullByDefault public class FlicDaemonBridgeConfiguration { - private final InetAddress hostname; - private final int port; + private String hostname; + private int port; - FlicDaemonBridgeConfiguration(InetAddress hostname, int port) { - this.hostname = hostname; - this.port = port; - } - - FlicDaemonBridgeConfiguration(Object rawHostname, Object rawPort) - throws UnknownHostException, IllegalArgumentException { - if (rawHostname == null || rawPort == null) { - throw new IllegalArgumentException("Hostname and port must not be null"); - } - this.hostname = parseBridgeHostname(rawHostname); - this.port = parseBridgePort(rawPort); - } - - private InetAddress parseBridgeHostname(Object rawHostname) throws UnknownHostException { - String host_config = ((rawHostname instanceof String) ? (String) rawHostname - : (rawHostname instanceof InetAddress) ? ((InetAddress) rawHostname).getHostAddress() : null); - - return InetAddress.getByName(host_config); - } + private InetAddress host; - private int parseBridgePort(Object rawPort) { - return Integer.parseInt(rawPort.toString()); + public void initAndValidate() throws UnknownHostException { + host = InetAddress.getByName(hostname); } - public InetAddress getHostname() { - return hostname; + public InetAddress getHost() { + return host; } public int getPort() { diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicDaemonBridgeHandler.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicDaemonBridgeHandler.java index 857830e86ff35..48f96d086fee9 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicDaemonBridgeHandler.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicDaemonBridgeHandler.java @@ -19,7 +19,6 @@ import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; -import org.openhab.binding.flicbutton.FlicButtonBindingConstants; import org.openhab.binding.flicbutton.internal.discovery.FlicButtonDiscoveryService; import org.openhab.core.thing.Bridge; import org.openhab.core.thing.ChannelUID; @@ -77,9 +76,8 @@ public void initialize() { } private void initConfigParameters() throws UnknownHostException { - Object hostConfigRaw = thing.getConfiguration().get(FlicButtonBindingConstants.CONFIG_HOST_NAME); - Object portConfigRaw = thing.getConfiguration().get(FlicButtonBindingConstants.CONFIG_PORT); - cfg = new FlicDaemonBridgeConfiguration(hostConfigRaw, portConfigRaw); + cfg = getConfigAs(FlicDaemonBridgeConfiguration.class); + cfg.initAndValidate(); } private void activateButtonDiscoveryService() { @@ -87,7 +85,7 @@ private void activateButtonDiscoveryService() { } private void startFlicdClientAsync() throws IOException { - flicClient = new FlicClient(cfg.getHostname().getHostAddress(), cfg.getPort()); + flicClient = new FlicClient(cfg.getHost().getHostAddress(), cfg.getPort()); Runnable flicClientService = () -> { try { flicClient.handleEvents(); From 6b787ed4003a40a9ab08b72eed5008b15b8c7453 Mon Sep 17 00:00:00 2001 From: Patrick Fink Date: Tue, 2 Mar 2021 23:40:39 +0100 Subject: [PATCH 11/37] [flicbutton] Move everything to internal package Signed-off-by: Patrick Fink --- .../{ => internal}/FlicButtonBindingConstants.java | 2 +- .../flicbutton/internal/FlicButtonHandlerFactory.java | 5 ++--- .../discovery/FlicSimpleclientDiscoveryServiceImpl.java | 2 +- .../flicbutton/{ => internal}/handler/ChildThingHandler.java | 2 +- .../handler/FlicButtonBatteryLevelListener.java | 2 +- .../{ => internal}/handler/FlicButtonEventListener.java | 2 +- .../flicbutton/{ => internal}/handler/FlicButtonHandler.java | 4 ++-- .../handler/FlicDaemonBridgeConfiguration.java | 5 +---- .../{ => internal}/handler/FlicDaemonBridgeHandler.java | 2 +- .../binding/flicbutton/internal/util/FlicButtonUtils.java | 2 +- 10 files changed, 12 insertions(+), 16 deletions(-) rename bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/{ => internal}/FlicButtonBindingConstants.java (97%) rename bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/{ => internal}/handler/ChildThingHandler.java (97%) rename bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/{ => internal}/handler/FlicButtonBatteryLevelListener.java (94%) rename bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/{ => internal}/handler/FlicButtonEventListener.java (98%) rename bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/{ => internal}/handler/FlicButtonHandler.java (97%) rename bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/{ => internal}/handler/FlicDaemonBridgeConfiguration.java (88%) rename bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/{ => internal}/handler/FlicDaemonBridgeHandler.java (98%) diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/FlicButtonBindingConstants.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/FlicButtonBindingConstants.java similarity index 97% rename from bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/FlicButtonBindingConstants.java rename to bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/FlicButtonBindingConstants.java index 27eb430ee96c2..3e96c9d967601 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/FlicButtonBindingConstants.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/FlicButtonBindingConstants.java @@ -10,7 +10,7 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.openhab.binding.flicbutton; +package org.openhab.binding.flicbutton.internal; import java.util.Collections; import java.util.Set; diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/FlicButtonHandlerFactory.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/FlicButtonHandlerFactory.java index 30c1fc430b6b3..83589999a76f8 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/FlicButtonHandlerFactory.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/FlicButtonHandlerFactory.java @@ -20,11 +20,10 @@ import java.util.stream.Stream; import org.eclipse.jdt.annotation.Nullable; -import org.openhab.binding.flicbutton.FlicButtonBindingConstants; -import org.openhab.binding.flicbutton.handler.FlicButtonHandler; -import org.openhab.binding.flicbutton.handler.FlicDaemonBridgeHandler; import org.openhab.binding.flicbutton.internal.discovery.FlicButtonDiscoveryService; import org.openhab.binding.flicbutton.internal.discovery.FlicSimpleclientDiscoveryServiceImpl; +import org.openhab.binding.flicbutton.internal.handler.FlicButtonHandler; +import org.openhab.binding.flicbutton.internal.handler.FlicDaemonBridgeHandler; import org.openhab.core.config.discovery.DiscoveryService; import org.openhab.core.thing.Bridge; import org.openhab.core.thing.Thing; diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/discovery/FlicSimpleclientDiscoveryServiceImpl.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/discovery/FlicSimpleclientDiscoveryServiceImpl.java index e06796f0db898..cb7513f04c1f4 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/discovery/FlicSimpleclientDiscoveryServiceImpl.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/discovery/FlicSimpleclientDiscoveryServiceImpl.java @@ -15,7 +15,7 @@ import java.io.IOException; import org.eclipse.jdt.annotation.NonNull; -import org.openhab.binding.flicbutton.FlicButtonBindingConstants; +import org.openhab.binding.flicbutton.internal.FlicButtonBindingConstants; import org.openhab.binding.flicbutton.internal.FlicButtonHandlerFactory; import org.openhab.binding.flicbutton.internal.util.FlicButtonUtils; import org.openhab.core.config.discovery.AbstractDiscoveryService; diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/ChildThingHandler.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/ChildThingHandler.java similarity index 97% rename from bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/ChildThingHandler.java rename to bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/ChildThingHandler.java index 725e46cde70d1..7440d5380e995 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/ChildThingHandler.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/ChildThingHandler.java @@ -11,7 +11,7 @@ * SPDX-License-Identifier: EPL-2.0 */ -package org.openhab.binding.flicbutton.handler; +package org.openhab.binding.flicbutton.internal.handler; import java.util.Collection; import java.util.Collections; diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicButtonBatteryLevelListener.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonBatteryLevelListener.java similarity index 94% rename from bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicButtonBatteryLevelListener.java rename to bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonBatteryLevelListener.java index 704d13b0ef2dd..b8112a1800874 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicButtonBatteryLevelListener.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonBatteryLevelListener.java @@ -10,7 +10,7 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.openhab.binding.flicbutton.handler; +package org.openhab.binding.flicbutton.internal.handler; import java.io.IOException; diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicButtonEventListener.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonEventListener.java similarity index 98% rename from bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicButtonEventListener.java rename to bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonEventListener.java index 495bae472fb23..477f12dcd7e45 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicButtonEventListener.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonEventListener.java @@ -10,7 +10,7 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.openhab.binding.flicbutton.handler; +package org.openhab.binding.flicbutton.internal.handler; import java.io.IOException; diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicButtonHandler.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonHandler.java similarity index 97% rename from bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicButtonHandler.java rename to bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonHandler.java index 49fc7f00698ef..f58141e958a27 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicButtonHandler.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonHandler.java @@ -10,9 +10,9 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.openhab.binding.flicbutton.handler; +package org.openhab.binding.flicbutton.internal.handler; -import static org.openhab.binding.flicbutton.FlicButtonBindingConstants.*; +import static org.openhab.binding.flicbutton.internal.FlicButtonBindingConstants.*; import java.io.IOException; import java.util.Objects; diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicDaemonBridgeConfiguration.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicDaemonBridgeConfiguration.java similarity index 88% rename from bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicDaemonBridgeConfiguration.java rename to bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicDaemonBridgeConfiguration.java index e557c6417bcf9..d91ea56cf1dec 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicDaemonBridgeConfiguration.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicDaemonBridgeConfiguration.java @@ -10,19 +10,16 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.openhab.binding.flicbutton.handler; +package org.openhab.binding.flicbutton.internal.handler; import java.net.InetAddress; import java.net.UnknownHostException; -import org.eclipse.jdt.annotation.NonNullByDefault; - /** * * @author Patrick Fink - Initial contribution * */ -@NonNullByDefault public class FlicDaemonBridgeConfiguration { private String hostname; diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicDaemonBridgeHandler.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicDaemonBridgeHandler.java similarity index 98% rename from bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicDaemonBridgeHandler.java rename to bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicDaemonBridgeHandler.java index 48f96d086fee9..9cce497db66f8 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/handler/FlicDaemonBridgeHandler.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicDaemonBridgeHandler.java @@ -10,7 +10,7 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.openhab.binding.flicbutton.handler; +package org.openhab.binding.flicbutton.internal.handler; import java.io.IOException; import java.net.UnknownHostException; diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/util/FlicButtonUtils.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/util/FlicButtonUtils.java index 7b1e6a1cfdec4..2f995ce7e35e4 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/util/FlicButtonUtils.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/util/FlicButtonUtils.java @@ -17,7 +17,7 @@ import java.util.Map; import org.eclipse.jdt.annotation.NonNullByDefault; -import org.openhab.binding.flicbutton.FlicButtonBindingConstants; +import org.openhab.binding.flicbutton.internal.FlicButtonBindingConstants; import org.openhab.core.thing.CommonTriggerEvents; import org.openhab.core.thing.ThingUID; From b5ff19f546a56a00cd03120beccc79d305b9eff8 Mon Sep 17 00:00:00 2001 From: Patrick Fink Date: Wed, 3 Mar 2021 01:13:40 +0100 Subject: [PATCH 12/37] [flicbutton] Remove hyphens from port parameter docs example Signed-off-by: Patrick Fink --- bundles/org.openhab.binding.flicbutton/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundles/org.openhab.binding.flicbutton/README.md b/bundles/org.openhab.binding.flicbutton/README.md index 50ef94aec8aea..5185a07edc037 100644 --- a/bundles/org.openhab.binding.flicbutton/README.md +++ b/bundles/org.openhab.binding.flicbutton/README.md @@ -49,7 +49,7 @@ If flicd is running on a remote host, please do not forget to start it with the For the button, the only config parameter is the MAC address. Normally, no textual configuration is necessary as buttons are autodiscovered as soon as the bridge is configured. If you want to use textual configuration anyway, you can do it like this: ``` -Bridge flicbutton:flicd-bridge:mybridge [ hostname="", port=""] { +Bridge flicbutton:flicd-bridge:mybridge [ hostname="", port=] { Thing button myflic1 "" [address =""] Thing button myflic2 "" [address =""] ... From d88ed491ac1a175797c4562f0586039ef0df2742 Mon Sep 17 00:00:00 2001 From: Patrick Fink Date: Sat, 6 Mar 2021 18:10:02 +0100 Subject: [PATCH 13/37] [flicbutton] Change maintainer to openHAB project Signed-off-by: Patrick Fink --- bundles/org.openhab.binding.flicbutton/NOTICE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundles/org.openhab.binding.flicbutton/NOTICE b/bundles/org.openhab.binding.flicbutton/NOTICE index 9a3e712ee40c9..ca1e0d671e175 100644 --- a/bundles/org.openhab.binding.flicbutton/NOTICE +++ b/bundles/org.openhab.binding.flicbutton/NOTICE @@ -1,4 +1,4 @@ -This content is produced and maintained by Patrick Fink. +This content is produced and maintained by the openHAB project. * Project home: https://www.openhab.org From 78054f177e362eacad909b1e0c3854019572d5db Mon Sep 17 00:00:00 2001 From: Patrick Fink Date: Sat, 2 Oct 2021 01:00:51 +0200 Subject: [PATCH 14/37] Apply docs suggestions + update to 3.2.0-SNAPSHOT Signed-off-by: Patrick Fink Co-authored-by: Matthew Skinner --- .../org.openhab.binding.flicbutton/README.md | 29 +++++++++---------- .../org.openhab.binding.flicbutton/pom.xml | 2 +- 2 files changed, 15 insertions(+), 16 deletions(-) diff --git a/bundles/org.openhab.binding.flicbutton/README.md b/bundles/org.openhab.binding.flicbutton/README.md index 5185a07edc037..ae1a309ae8f7a 100644 --- a/bundles/org.openhab.binding.flicbutton/README.md +++ b/bundles/org.openhab.binding.flicbutton/README.md @@ -3,12 +3,11 @@ openHAB binding for using [Flic Buttons](https://flic.io/) with a [fliclib-linux-hci](/~https://github.com/50ButtonsEach/fliclib-linux-hci) bridge. -Currently, although Flic Buttons are BLE devices, this binding only supports fliclib-linux-hci (flicd) -as a bridge. The openHAB Bluetooth Bindings are not supported. Flicd requires a seperate Bluetooth adapter to work, so -if you use this binding together with e.g. the [Bluez Binding](https://www.openhab.org/addons/bindings/bluetooth.bluez/), -two physical Bluetooth adapters are required (one for Bluez and one for flicd). Be aware that flicd requires an initial -internet connection for the verification of the buttons. After buttons are initially added to flicd, internet connection -is not required anymore. +Currently, although Flic Buttons are BLE devices, this binding only supports fliclib-linux-hci (flicd) as a bridge. +The openHAB Bluetooth Bindings are not supported. +Flicd requires a seperate Bluetooth adapter to work, so if you use this binding together with e.g. the [Bluez Binding](https://www.openhab.org/addons/bindings/bluetooth.bluez/), two physical Bluetooth adapters are required (one for Bluez and one for flicd). +Be aware that flicd requires an initial internet connection for the verification of the buttons. +After buttons are initially added to flicd, an internet connection is not required anymore. ## Supported Things @@ -21,9 +20,8 @@ is not required anymore. * There is no automatic discovery for flicd-bridge available. -* After flicd-bridge is (manually) configured, buttons will be automatically discovered via background discovery as soon - as they're addded with [simpleclient](/~https://github.com/50ButtonsEach/fliclib-linux-hci). If they're already - attached to the flicd-bridge before configuring this binding, they can be discovered by triggering an active scan. +* After flicd-bridge is (manually) configured, buttons will be automatically discovered via background discovery as soon as they're added with [simpleclient](/~https://github.com/50ButtonsEach/fliclib-linux-hci). +If they're already attached to the flicd-bridge before configuring this binding, they can be discovered by triggering an active scan. ## Thing Configuration @@ -35,8 +33,8 @@ Example for textual configuration: Bridge flicbutton:flicd-bridge:mybridge ``` -The default host is localhost:5551 (this should be sufficient if flicd is running with default settings on the same -server as openHAB). If your flicd service is running somewhere else, specify it like this: +The default host is localhost:5551 (this should be sufficient if flicd is running with default settings on the same server as openHAB). +If your flicd service is running somewhere else, specify it like this: ``` Bridge flicbutton:flicd-bridge:mybridge [ hostname="", port=] @@ -46,7 +44,9 @@ If flicd is running on a remote host, please do not forget to start it with the ### button -For the button, the only config parameter is the MAC address. Normally, no textual configuration is necessary as buttons are autodiscovered as soon as the bridge is configured. If you want to use textual configuration anyway, you can do it like this: +For the button, the only config parameter is the MAC address. +Normally, no textual configuration is necessary as buttons are auto discovered as soon as the bridge is configured. +If you want to use textual configuration anyway, you can do it like this: ``` Bridge flicbutton:flicd-bridge:mybridge [ hostname="", port=] { @@ -56,7 +56,8 @@ Bridge flicbutton:flicd-bridge:mybridge [ hostname="", port= org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 3.1.0-SNAPSHOT + 3.2.0-SNAPSHOT org.openhab.binding.flicbutton From dc2de234c66afcda210bcb36b5a7bc0cd94cc43f Mon Sep 17 00:00:00 2001 From: Patrick Fink Date: Mon, 4 Oct 2021 02:13:07 +0200 Subject: [PATCH 15/37] [flicbutton] Fix bridge offline & reconnect handling Signed-off-by: Patrick Fink --- .../flicbutton/internal/handler/ChildThingHandler.java | 10 +++++++++- .../flicbutton/internal/handler/FlicButtonHandler.java | 8 ++++++++ .../internal/handler/FlicDaemonBridgeHandler.java | 4 +++- 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/ChildThingHandler.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/ChildThingHandler.java index 7440d5380e995..bba6431ec46e6 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/ChildThingHandler.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/ChildThingHandler.java @@ -19,6 +19,7 @@ import org.openhab.core.thing.Thing; import org.openhab.core.thing.ThingStatus; import org.openhab.core.thing.ThingStatusDetail; +import org.openhab.core.thing.ThingStatusInfo; import org.openhab.core.thing.binding.BaseThingHandler; import org.openhab.core.thing.binding.BridgeHandler; @@ -39,7 +40,7 @@ public ChildThingHandler(Thing thing) { @Override public void initialize() { setStatusBasedOnBridge(); - if (bridgeValid) { + if (getBridge() != null) { linkBridge(); } } @@ -57,15 +58,22 @@ protected void setStatusBasedOnBridge() { setStatusBasedOnBridge(defaultToleratedBridgeStatuses); } + @Override + public void bridgeStatusChanged(ThingStatusInfo bridgeStatusInfo) { + this.setStatusBasedOnBridge(); + } + protected void setStatusBasedOnBridge(Collection toleratedBridgeStatuses) { if (getBridge() != null) { if (toleratedBridgeStatuses.contains(getBridge().getStatus())) { bridgeValid = true; } else { + bridgeValid = false; updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE, "Bridge in unsupported status: " + getBridge().getStatus()); } } else { + bridgeValid = false; updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_UNINITIALIZED, "Bridge missing."); } } diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonHandler.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonHandler.java index f58141e958a27..70629585916fb 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonHandler.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonHandler.java @@ -68,6 +68,14 @@ public void initialize() { } } + @Override + public void bridgeStatusChanged(ThingStatusInfo bridgeStatusInfo) { + super.bridgeStatusChanged(bridgeStatusInfo); + if (getThing().getStatusInfo().getStatusDetail() == ThingStatusDetail.BRIDGE_OFFLINE && bridgeValid) { + initializeThing(); + } + } + public void initializeThing() { try { FlicButtonBatteryLevelListener batteryListener = new FlicButtonBatteryLevelListener(this); diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicDaemonBridgeHandler.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicDaemonBridgeHandler.java index 9cce497db66f8..dc925199b0128 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicDaemonBridgeHandler.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicDaemonBridgeHandler.java @@ -72,6 +72,8 @@ public void initialize() { } catch (IOException e) { updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "Error connecting to flicd!\n" + e); + dispose(); + scheduleReinitialize(); } } @@ -103,7 +105,7 @@ private void startFlicdClientAsync() throws IOException { private void onClientFailure() { updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, - "flicd client terminated, probably flicd is not reachable."); + "flicd client terminated, probably flicd is not reachable anymore."); dispose(); scheduleReinitialize(); } From c14a72cd155befd690106e15b876300cbf6e1fe2 Mon Sep 17 00:00:00 2001 From: Patrick Fink Date: Mon, 4 Oct 2021 02:17:43 +0200 Subject: [PATCH 16/37] [flicbutton] Close open socket on dispose Signed-off-by: Patrick Fink --- .../internal/handler/FlicDaemonBridgeHandler.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicDaemonBridgeHandler.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicDaemonBridgeHandler.java index dc925199b0128..b1ca90fdc6bff 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicDaemonBridgeHandler.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicDaemonBridgeHandler.java @@ -127,6 +127,14 @@ public void dispose() { } startedTasks = new ArrayList<>(2); buttonDiscoveryService.deactivate(); + if(flicClient != null) { + try { + flicClient.close(); + flicClient = null; + } catch (IOException e) { + logger.debug("Error closing connection to flicd: ", e.getMessage()); + } + } } private void scheduleReinitialize() { From 506f5bbc605122c98a6fcc031e922a9068d37b5e Mon Sep 17 00:00:00 2001 From: Patrick Fink Date: Mon, 4 Oct 2021 02:20:00 +0200 Subject: [PATCH 17/37] [flicbutton] Improve exception error message in ThingStatus Signed-off-by: Patrick Fink --- .../flicbutton/internal/handler/FlicDaemonBridgeHandler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicDaemonBridgeHandler.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicDaemonBridgeHandler.java index b1ca90fdc6bff..5276e26dc48bc 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicDaemonBridgeHandler.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicDaemonBridgeHandler.java @@ -71,7 +71,7 @@ public void initialize() { "Configuration (hostname, port) is invalid and cannot be parsed."); } catch (IOException e) { updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, - "Error connecting to flicd!\n" + e); + "Error connecting to flicd: " + e.getMessage()); dispose(); scheduleReinitialize(); } From 3526e736091e1ceec1953015090d5cb49dbb5eb4 Mon Sep 17 00:00:00 2001 From: Patrick Fink Date: Mon, 4 Oct 2021 02:20:39 +0200 Subject: [PATCH 18/37] [flicbutton] Fix README title Signed-off-by: Patrick Fink --- bundles/org.openhab.binding.flicbutton/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundles/org.openhab.binding.flicbutton/README.md b/bundles/org.openhab.binding.flicbutton/README.md index ae1a309ae8f7a..ca5a8f414c7cc 100644 --- a/bundles/org.openhab.binding.flicbutton/README.md +++ b/bundles/org.openhab.binding.flicbutton/README.md @@ -1,4 +1,4 @@ -# openHAB Flic Button Binding +# Flic Button Binding openHAB binding for using [Flic Buttons](https://flic.io/) with a [fliclib-linux-hci](/~https://github.com/50ButtonsEach/fliclib-linux-hci) bridge. From 35e8628f250917c8f53d7dff045d7a9c87e51818 Mon Sep 17 00:00:00 2001 From: Patrick Fink Date: Mon, 4 Oct 2021 02:26:16 +0200 Subject: [PATCH 19/37] [flicbutton] Improve exception error message in ThingStatus Signed-off-by: Patrick Fink --- .../binding/flicbutton/internal/handler/FlicButtonHandler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonHandler.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonHandler.java index 70629585916fb..dcb06e906e37d 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonHandler.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonHandler.java @@ -96,7 +96,7 @@ public void initializeThing() { } } } catch (IOException | InterruptedException e) { - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "Connection setup failed. " + e); + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "Connection setup failed: " + e.getMessage()); } } From f91a6dc9baa16ea42cb0fed5b078993033093d81 Mon Sep 17 00:00:00 2001 From: Patrick Fink Date: Mon, 4 Oct 2021 02:47:59 +0200 Subject: [PATCH 20/37] [flicbutton] Style fixes Signed-off-by: Patrick Fink --- .../org.openhab.binding.flicbutton/README.md | 28 +++++++++++++------ .../internal/handler/FlicButtonHandler.java | 3 +- .../handler/FlicDaemonBridgeHandler.java | 4 +-- 3 files changed, 24 insertions(+), 11 deletions(-) diff --git a/bundles/org.openhab.binding.flicbutton/README.md b/bundles/org.openhab.binding.flicbutton/README.md index ca5a8f414c7cc..19b0b57de5aab 100644 --- a/bundles/org.openhab.binding.flicbutton/README.md +++ b/bundles/org.openhab.binding.flicbutton/README.md @@ -5,7 +5,9 @@ with a [fliclib-linux-hci](/~https://github.com/50ButtonsEach/fliclib-linux-hci) b Currently, although Flic Buttons are BLE devices, this binding only supports fliclib-linux-hci (flicd) as a bridge. The openHAB Bluetooth Bindings are not supported. -Flicd requires a seperate Bluetooth adapter to work, so if you use this binding together with e.g. the [Bluez Binding](https://www.openhab.org/addons/bindings/bluetooth.bluez/), two physical Bluetooth adapters are required (one for Bluez and one for flicd). +Flicd requires a seperate Bluetooth adapter to work, so if you use this binding together with e.g. the +[Bluez Binding](https://www.openhab.org/addons/bindings/bluetooth.bluez/), +two physical Bluetooth adapters are required (one for Bluez and one for flicd). Be aware that flicd requires an initial internet connection for the verification of the buttons. After buttons are initially added to flicd, an internet connection is not required anymore. @@ -19,9 +21,11 @@ After buttons are initially added to flicd, an internet connection is not requir ## Discovery * There is no automatic discovery for flicd-bridge available. - -* After flicd-bridge is (manually) configured, buttons will be automatically discovered via background discovery as soon as they're added with [simpleclient](/~https://github.com/50ButtonsEach/fliclib-linux-hci). -If they're already attached to the flicd-bridge before configuring this binding, they can be discovered by triggering an active scan. +* After flicd-bridge is (manually) configured, buttons will be automatically discovered via background discovery as soon + as they're added with [simpleclient](/~https://github.com/50ButtonsEach/fliclib-linux-hci). + +If they're already attached to the flicd-bridge before configuring this binding, they can be discovered by triggering an +active scan. ## Thing Configuration @@ -70,10 +74,17 @@ You're free to choose any label you like for your button. ### Initial setup -1. Setup and run flicd as described in [fliclib-linux-hci](/~https://github.com/50ButtonsEach/fliclib-linux-hci). Please consider that you need a seperate Bluetooth adapter. Shared usage with other Bluetooth services (e.g. Bluez) is not possible. -1. Connect your buttons to flicd using the simpleclient as described in [fliclib-linux-hci](/~https://github.com/50ButtonsEach/fliclib-linux-hci). Flicd has to run in background the whole time, simpleclient can be killed after you successfully tested the button connection. -1. Add a flicd-bridge via UI or Textual Configuration. Please consider that flicd does only accept connections from localhost by default, to enable remote connections from openHAB you have to use the `--server-addr` parameter as described in [fliclib-linux-hci](/~https://github.com/50ButtonsEach/fliclib-linux-hci). -1. When the bridge is online, buttons newly added via simpleclient will automatically get discovered via background Discovery. To discover buttons that were set up before the Binding setup, please run an active scan. +1. Setup and run flicd as described in [fliclib-linux-hci](/~https://github.com/50ButtonsEach/fliclib-linux-hci). + Please consider that you need a seperate Bluetooth adapter. Shared usage with other Bluetooth services (e.g. Bluez) + is not possible. +1. Connect your buttons to flicd using the simpleclient as described in + [fliclib-linux-hci](/~https://github.com/50ButtonsEach/fliclib-linux-hci). Flicd has to run in background the whole + time, simpleclient can be killed after you successfully tested the button connection. +1. Add a flicd-bridge via UI or Textual Configuration. Please consider that flicd does only accept connections from + localhost by default, to enable remote connections from openHAB you have to use the `--server-addr` parameter as + described in [fliclib-linux-hci](/~https://github.com/50ButtonsEach/fliclib-linux-hci). +1. When the bridge is online, buttons newly added via simpleclient will automatically get discovered via background + discovery. To discover buttons that were set up before the Binding setup, please run an active scan. ### Configuration Example using Profiles @@ -99,6 +110,7 @@ Switch Light_Kitchen { channel="hue:group:1:kitchen-bulbs:switch", channel="f It's also possible to setup [Rules](https://www.openhab.org/docs/configuration/rules-dsl.html). The following rules help to initially test your setup as they'll trigger log messages on incoming events. + ``` rule "Button rule using the button channel" diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonHandler.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonHandler.java index dcb06e906e37d..71896b67b9330 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonHandler.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonHandler.java @@ -96,7 +96,8 @@ public void initializeThing() { } } } catch (IOException | InterruptedException e) { - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "Connection setup failed: " + e.getMessage()); + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, + "Connection setup failed: {}" + e.getMessage()); } } diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicDaemonBridgeHandler.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicDaemonBridgeHandler.java index 5276e26dc48bc..507e12187b3fc 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicDaemonBridgeHandler.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicDaemonBridgeHandler.java @@ -127,12 +127,12 @@ public void dispose() { } startedTasks = new ArrayList<>(2); buttonDiscoveryService.deactivate(); - if(flicClient != null) { + if (flicClient != null) { try { flicClient.close(); flicClient = null; } catch (IOException e) { - logger.debug("Error closing connection to flicd: ", e.getMessage()); + logger.debug("Error closing connection to flicd: {}", e.getMessage()); } } } From d4217714670abaec56f6813de269daaeb8799b20 Mon Sep 17 00:00:00 2001 From: Patrick Fink Date: Mon, 4 Oct 2021 03:17:12 +0200 Subject: [PATCH 21/37] [flicbutton] Use trace log level for button clicks & status changes Signed-off-by: Patrick Fink --- .../flicbutton/internal/handler/FlicButtonEventListener.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonEventListener.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonEventListener.java index 477f12dcd7e45..e194eadf1e3a4 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonEventListener.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonEventListener.java @@ -55,7 +55,7 @@ public void onRemoved(ButtonConnectionChannel channel, RemovedReason removedReas @Override public void onConnectionStatusChanged(ButtonConnectionChannel channel, ConnectionStatus connectionStatus, DisconnectReason disconnectReason) { - logger.debug("New status for {}: {}", channel.getBdaddr(), + logger.trace("New status for {}: {}", channel.getBdaddr(), connectionStatus + (connectionStatus == ConnectionStatus.Disconnected ? ", " + disconnectReason : "")); thingHandler.connectionStatusChanged(connectionStatus, disconnectReason); @@ -65,7 +65,7 @@ public void onConnectionStatusChanged(ButtonConnectionChannel channel, Connectio public void onButtonUpOrDown(ButtonConnectionChannel channel, ClickType clickType, boolean wasQueued, int timeDiff) throws IOException { - logger.debug("{} {}", channel.getBdaddr(), clickType.name()); + logger.trace("{} {}", channel.getBdaddr(), clickType.name()); String commonTriggerEvent = FlicButtonUtils.flicOpenhabTriggerEventMap.get(clickType.name()); From be18b74f596fbd79dcc7d2c27958386201437b70 Mon Sep 17 00:00:00 2001 From: Patrick Fink Date: Mon, 4 Oct 2021 13:48:15 +0200 Subject: [PATCH 22/37] Apply doc improvements from code review Signed-off-by: Patrick Fink Co-authored-by: Matthew Skinner --- bundles/org.openhab.binding.flicbutton/README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/bundles/org.openhab.binding.flicbutton/README.md b/bundles/org.openhab.binding.flicbutton/README.md index 19b0b57de5aab..87e81dfdf2d6d 100644 --- a/bundles/org.openhab.binding.flicbutton/README.md +++ b/bundles/org.openhab.binding.flicbutton/README.md @@ -75,16 +75,16 @@ You're free to choose any label you like for your button. ### Initial setup 1. Setup and run flicd as described in [fliclib-linux-hci](/~https://github.com/50ButtonsEach/fliclib-linux-hci). - Please consider that you need a seperate Bluetooth adapter. Shared usage with other Bluetooth services (e.g. Bluez) + Please consider that you need a separate Bluetooth adapter. Shared usage with other Bluetooth services (e.g. Bluez) is not possible. 1. Connect your buttons to flicd using the simpleclient as described in [fliclib-linux-hci](/~https://github.com/50ButtonsEach/fliclib-linux-hci). Flicd has to run in background the whole - time, simpleclient can be killed after you successfully tested the button connection. -1. Add a flicd-bridge via UI or Textual Configuration. Please consider that flicd does only accept connections from + time, simpleclient can be killed after you successfully test the button connects. +1. Add a flicd-bridge via the UI or textual configuration. Please consider that flicd only accepts connections from localhost by default, to enable remote connections from openHAB you have to use the `--server-addr` parameter as described in [fliclib-linux-hci](/~https://github.com/50ButtonsEach/fliclib-linux-hci). 1. When the bridge is online, buttons newly added via simpleclient will automatically get discovered via background - discovery. To discover buttons that were set up before the Binding setup, please run an active scan. + discovery. To discover buttons that were set up before the binding was setup, please run an active scan. ### Configuration Example using Profiles From 72cb03a96f5b899739bac725fe81b4d11789d2d9 Mon Sep 17 00:00:00 2001 From: Patrick Fink Date: Sun, 24 Oct 2021 18:15:16 +0200 Subject: [PATCH 23/37] [flicbutton] Add binding to bom/openhab-addons Signed-off-by: Patrick Fink --- bom/openhab-addons/pom.xml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/bom/openhab-addons/pom.xml b/bom/openhab-addons/pom.xml index c86eafdcd7a81..745f6b66a5804 100644 --- a/bom/openhab-addons/pom.xml +++ b/bom/openhab-addons/pom.xml @@ -416,6 +416,11 @@ org.openhab.binding.feican ${project.version} + + org.openhab.addons.bundles + org.openhab.binding.flicbutton + ${project.version} + org.openhab.addons.bundles org.openhab.binding.fmiweather From 38f76dac8a50cadb4fba28515cea357fca2d757e Mon Sep 17 00:00:00 2001 From: Patrick Fink Date: Sun, 24 Oct 2021 18:16:42 +0200 Subject: [PATCH 24/37] [flicbutton] Cleanup / remove guava leftover Signed-off-by: Patrick Fink --- .../org.openhab.binding.flicbutton/src/main/feature/feature.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/bundles/org.openhab.binding.flicbutton/src/main/feature/feature.xml b/bundles/org.openhab.binding.flicbutton/src/main/feature/feature.xml index 3608646164aac..45d90679a3968 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.flicbutton/src/main/feature/feature.xml @@ -4,7 +4,6 @@ openhab-runtime-base - mvn:com.google.guava/guava/21.0 mvn:org.openhab.addons.bundles/org.openhab.binding.flicbutton/${project.version} From 2711a7fb9a52013d159b91b3718e5d2c86a3f6e7 Mon Sep 17 00:00:00 2001 From: Patrick Fink Date: Sun, 24 Oct 2021 18:32:24 +0200 Subject: [PATCH 25/37] [flicbutton] Remove online status description Signed-off-by: Patrick Fink --- .../binding/flicbutton/internal/handler/FlicButtonHandler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonHandler.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonHandler.java index 71896b67b9330..2b4fcae83f950 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonHandler.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonHandler.java @@ -146,7 +146,7 @@ private void scheduleStatusChangeToOffline() { } protected void setOnline() { - updateStatus(ThingStatus.ONLINE, ThingStatusDetail.NONE, "Button connected."); + updateStatus(ThingStatus.ONLINE, ThingStatusDetail.NONE); } protected void setOffline() { From 678ecee1755f4ab8f5d07734ad4e40bd0d1a13ab Mon Sep 17 00:00:00 2001 From: Patrick Fink Date: Sun, 24 Oct 2021 18:50:48 +0200 Subject: [PATCH 26/37] [flicbutton] Improve flicd hostname label Signed-off-by: Patrick Fink Co-authored-by: Fabian Wolter --- .../src/main/resources/OH-INF/thing/thing-types.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundles/org.openhab.binding.flicbutton/src/main/resources/OH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.flicbutton/src/main/resources/OH-INF/thing/thing-types.xml index 3eb811fdb94af..25d3784d67bbe 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/resources/OH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.flicbutton/src/main/resources/OH-INF/thing/thing-types.xml @@ -11,7 +11,7 @@ network-address - + IP or Host name of the Flic daemon (flicd). localhost From 14ec92da7e563d6699f19d6356611c95c895d0f6 Mon Sep 17 00:00:00 2001 From: Patrick Fink Date: Sun, 24 Oct 2021 18:52:38 +0200 Subject: [PATCH 27/37] [flicbutton] Do not catch IllegalArgumentException anymore as its not neeed Signed-off-by: Patrick Fink --- .../flicbutton/internal/handler/FlicDaemonBridgeHandler.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicDaemonBridgeHandler.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicDaemonBridgeHandler.java index 507e12187b3fc..829c6170fb995 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicDaemonBridgeHandler.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicDaemonBridgeHandler.java @@ -66,9 +66,6 @@ public void initialize() { initThingStatus(); } catch (UnknownHostException ignored) { updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "Hostname wrong or unknown!"); - } catch (IllegalArgumentException e) { - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, - "Configuration (hostname, port) is invalid and cannot be parsed."); } catch (IOException e) { updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "Error connecting to flicd: " + e.getMessage()); From a048560f2e3c718858554a9d254965c206cf6f7c Mon Sep 17 00:00:00 2001 From: Patrick Fink Date: Sun, 24 Oct 2021 18:55:56 +0200 Subject: [PATCH 28/37] [flicbutton] Use debug log level instead of info Signed-off-by: Patrick Fink --- .../discovery/FlicSimpleclientDiscoveryServiceImpl.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/discovery/FlicSimpleclientDiscoveryServiceImpl.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/discovery/FlicSimpleclientDiscoveryServiceImpl.java index cb7513f04c1f4..51ed803920aae 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/discovery/FlicSimpleclientDiscoveryServiceImpl.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/discovery/FlicSimpleclientDiscoveryServiceImpl.java @@ -107,7 +107,7 @@ protected void startBackgroundDiscovery() { flicClient.setGeneralCallbacks(new GeneralCallbacks() { @Override public void onNewVerifiedButton(Bdaddr bdaddr) throws IOException { - logger.info("A new Flic button was added by an external flicd client: {}", bdaddr); + logger.debug("A new Flic button was added by an external flicd client: {}", bdaddr); flicButtonDiscovered(bdaddr); } }); @@ -123,7 +123,7 @@ protected void stopBackgroundDiscovery() { @Override public ThingUID flicButtonDiscovered(Bdaddr bdaddr) { - logger.info("Flic Button {} discovered!", bdaddr); + logger.debug("Flic Button {} discovered!", bdaddr); ThingUID flicButtonUID = FlicButtonUtils.getThingUIDFromBdAddr(bdaddr, bridgeUID); DiscoveryResult discoveryResult = DiscoveryResultBuilder.create(flicButtonUID).withBridge(bridgeUID) From 97d0cdc686ae00cdb98858c98b7492a2565c99d1 Mon Sep 17 00:00:00 2001 From: Patrick Fink Date: Sun, 13 Feb 2022 23:11:27 +0100 Subject: [PATCH 29/37] [flicbutton] Update version and license Signed-off-by: Patrick Fink --- bundles/org.openhab.binding.flicbutton/pom.xml | 2 +- .../binding/flicbutton/internal/FlicButtonBindingConstants.java | 2 +- .../binding/flicbutton/internal/FlicButtonHandlerFactory.java | 2 +- .../internal/discovery/FlicButtonDiscoveryService.java | 2 +- .../discovery/FlicSimpleclientDiscoveryServiceImpl.java | 2 +- .../binding/flicbutton/internal/handler/ChildThingHandler.java | 2 +- .../internal/handler/FlicButtonBatteryLevelListener.java | 2 +- .../flicbutton/internal/handler/FlicButtonEventListener.java | 2 +- .../binding/flicbutton/internal/handler/FlicButtonHandler.java | 2 +- .../internal/handler/FlicDaemonBridgeConfiguration.java | 2 +- .../flicbutton/internal/handler/FlicDaemonBridgeHandler.java | 2 +- .../binding/flicbutton/internal/util/FlicButtonUtils.java | 2 +- 12 files changed, 12 insertions(+), 12 deletions(-) diff --git a/bundles/org.openhab.binding.flicbutton/pom.xml b/bundles/org.openhab.binding.flicbutton/pom.xml index 8bbed09269236..9163b246e9d4b 100644 --- a/bundles/org.openhab.binding.flicbutton/pom.xml +++ b/bundles/org.openhab.binding.flicbutton/pom.xml @@ -7,7 +7,7 @@ org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 3.2.0-SNAPSHOT + 3.3.0-SNAPSHOT org.openhab.binding.flicbutton diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/FlicButtonBindingConstants.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/FlicButtonBindingConstants.java index 3e96c9d967601..9f1d5092caf73 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/FlicButtonBindingConstants.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/FlicButtonBindingConstants.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2021 Contributors to the openHAB project + * Copyright (c) 2010-2022 Contributors to the openHAB project * * See the NOTICE file(s) distributed with this work for additional * information. diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/FlicButtonHandlerFactory.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/FlicButtonHandlerFactory.java index 83589999a76f8..9848f9d6c4509 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/FlicButtonHandlerFactory.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/FlicButtonHandlerFactory.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2021 Contributors to the openHAB project + * Copyright (c) 2010-2022 Contributors to the openHAB project * * See the NOTICE file(s) distributed with this work for additional * information. diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/discovery/FlicButtonDiscoveryService.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/discovery/FlicButtonDiscoveryService.java index ccf3e4257cb66..3c1fb1e5f5132 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/discovery/FlicButtonDiscoveryService.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/discovery/FlicButtonDiscoveryService.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2021 Contributors to the openHAB project + * Copyright (c) 2010-2022 Contributors to the openHAB project * * See the NOTICE file(s) distributed with this work for additional * information. diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/discovery/FlicSimpleclientDiscoveryServiceImpl.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/discovery/FlicSimpleclientDiscoveryServiceImpl.java index 51ed803920aae..e0e6d3b25689b 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/discovery/FlicSimpleclientDiscoveryServiceImpl.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/discovery/FlicSimpleclientDiscoveryServiceImpl.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2021 Contributors to the openHAB project + * Copyright (c) 2010-2022 Contributors to the openHAB project * * See the NOTICE file(s) distributed with this work for additional * information. diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/ChildThingHandler.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/ChildThingHandler.java index bba6431ec46e6..d405fae830456 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/ChildThingHandler.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/ChildThingHandler.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2021 Contributors to the openHAB project + * Copyright (c) 2010-2022 Contributors to the openHAB project * * See the NOTICE file(s) distributed with this work for additional * information. diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonBatteryLevelListener.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonBatteryLevelListener.java index b8112a1800874..cd0c8529ad792 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonBatteryLevelListener.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonBatteryLevelListener.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2021 Contributors to the openHAB project + * Copyright (c) 2010-2022 Contributors to the openHAB project * * See the NOTICE file(s) distributed with this work for additional * information. diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonEventListener.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonEventListener.java index e194eadf1e3a4..b5f8c321b3e30 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonEventListener.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonEventListener.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2021 Contributors to the openHAB project + * Copyright (c) 2010-2022 Contributors to the openHAB project * * See the NOTICE file(s) distributed with this work for additional * information. diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonHandler.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonHandler.java index 2b4fcae83f950..05ab6927a5972 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonHandler.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonHandler.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2021 Contributors to the openHAB project + * Copyright (c) 2010-2022 Contributors to the openHAB project * * See the NOTICE file(s) distributed with this work for additional * information. diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicDaemonBridgeConfiguration.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicDaemonBridgeConfiguration.java index d91ea56cf1dec..75fbf2ad525e9 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicDaemonBridgeConfiguration.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicDaemonBridgeConfiguration.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2021 Contributors to the openHAB project + * Copyright (c) 2010-2022 Contributors to the openHAB project * * See the NOTICE file(s) distributed with this work for additional * information. diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicDaemonBridgeHandler.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicDaemonBridgeHandler.java index 829c6170fb995..8e064d325afef 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicDaemonBridgeHandler.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicDaemonBridgeHandler.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2021 Contributors to the openHAB project + * Copyright (c) 2010-2022 Contributors to the openHAB project * * See the NOTICE file(s) distributed with this work for additional * information. diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/util/FlicButtonUtils.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/util/FlicButtonUtils.java index 2f995ce7e35e4..c10f654b8790f 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/util/FlicButtonUtils.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/util/FlicButtonUtils.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2021 Contributors to the openHAB project + * Copyright (c) 2010-2022 Contributors to the openHAB project * * See the NOTICE file(s) distributed with this work for additional * information. From a968d1609c9b133b6dee1d8185d11761dc151838 Mon Sep 17 00:00:00 2001 From: Patrick Fink Date: Mon, 14 Feb 2022 01:07:57 +0100 Subject: [PATCH 30/37] [flicbutton] Fix SAT warnings, e.g. add null handling annotations Signed-off-by: Patrick Fink --- .../internal/FlicButtonBindingConstants.java | 16 ++++++----- .../internal/FlicButtonHandlerFactory.java | 5 +++- .../discovery/FlicButtonDiscoveryService.java | 5 ++-- .../FlicSimpleclientDiscoveryServiceImpl.java | 28 +++++++++++-------- .../internal/handler/ChildThingHandler.java | 5 +++- .../FlicButtonBatteryLevelListener.java | 10 ++++--- .../handler/FlicButtonEventListener.java | 2 +- .../internal/handler/FlicButtonHandler.java | 19 ++++++++----- .../FlicDaemonBridgeConfiguration.java | 8 +++++- .../handler/FlicDaemonBridgeHandler.java | 16 +++++++---- 10 files changed, 72 insertions(+), 42 deletions(-) diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/FlicButtonBindingConstants.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/FlicButtonBindingConstants.java index 9f1d5092caf73..fdafbd2b13c3f 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/FlicButtonBindingConstants.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/FlicButtonBindingConstants.java @@ -15,6 +15,7 @@ import java.util.Collections; import java.util.Set; +import org.eclipse.jdt.annotation.NonNullByDefault; import org.openhab.core.thing.ThingTypeUID; /** @@ -23,15 +24,16 @@ * * @author Patrick Fink - Initial contribution */ +@NonNullByDefault public class FlicButtonBindingConstants { public static final String BINDING_ID = "flicbutton"; // List of all Thing Type UIDs - public final static ThingTypeUID BRIDGE_THING_TYPE = new ThingTypeUID(BINDING_ID, "flicd-bridge"); - public final static ThingTypeUID FLICBUTTON_THING_TYPE = new ThingTypeUID(BINDING_ID, "button"); + public static final ThingTypeUID BRIDGE_THING_TYPE = new ThingTypeUID(BINDING_ID, "flicd-bridge"); + public static final ThingTypeUID FLICBUTTON_THING_TYPE = new ThingTypeUID(BINDING_ID, "button"); - public final static Set BRIDGE_THING_TYPES_UIDS = Collections.singleton(BRIDGE_THING_TYPE); + public static final Set BRIDGE_THING_TYPES_UIDS = Collections.singleton(BRIDGE_THING_TYPE); public static final Set SUPPORTED_THING_TYPES_UIDS = Collections.singleton(FLICBUTTON_THING_TYPE); // List of all configuration options @@ -40,10 +42,10 @@ public class FlicButtonBindingConstants { public static final String CONFIG_ADDRESS = "address"; // List of all Channel ids - public final static String CHANNEL_ID_RAWBUTTON_EVENTS = "rawbutton"; - public final static String CHANNEL_ID_BUTTON_EVENTS = "button"; - public final static String CHANNEL_ID_BATTERY_LEVEL = "battery-level"; + public static final String CHANNEL_ID_RAWBUTTON_EVENTS = "rawbutton"; + public static final String CHANNEL_ID_BUTTON_EVENTS = "button"; + public static final String CHANNEL_ID_BATTERY_LEVEL = "battery-level"; // Other stuff - public final static int BUTTON_OFFLINE_GRACE_PERIOD_SECONDS = 60; + public static final int BUTTON_OFFLINE_GRACE_PERIOD_SECONDS = 60; } diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/FlicButtonHandlerFactory.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/FlicButtonHandlerFactory.java index 9848f9d6c4509..5f5b7ac73e6b9 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/FlicButtonHandlerFactory.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/FlicButtonHandlerFactory.java @@ -19,6 +19,7 @@ import java.util.stream.Collectors; import java.util.stream.Stream; +import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.flicbutton.internal.discovery.FlicButtonDiscoveryService; import org.openhab.binding.flicbutton.internal.discovery.FlicSimpleclientDiscoveryServiceImpl; @@ -42,9 +43,10 @@ * @author Patrick Fink - Initial contribution */ @Component(service = ThingHandlerFactory.class, configurationPid = "binding.flicbutton") +@NonNullByDefault public class FlicButtonHandlerFactory extends BaseThingHandlerFactory { - private final static Set SUPPORTED_THING_TYPES_UIDS = Stream + private static final Set SUPPORTED_THING_TYPES_UIDS = Stream .concat(FlicButtonBindingConstants.BRIDGE_THING_TYPES_UIDS.stream(), FlicButtonBindingConstants.SUPPORTED_THING_TYPES_UIDS.stream()) .collect(Collectors.toSet()); @@ -56,6 +58,7 @@ public boolean supportsThingType(ThingTypeUID thingTypeUID) { } @Override + @Nullable protected ThingHandler createHandler(Thing thing) { ThingTypeUID thingTypeUID = thing.getThingTypeUID(); diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/discovery/FlicButtonDiscoveryService.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/discovery/FlicButtonDiscoveryService.java index 3c1fb1e5f5132..313b0776d1b7a 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/discovery/FlicButtonDiscoveryService.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/discovery/FlicButtonDiscoveryService.java @@ -12,7 +12,6 @@ */ package org.openhab.binding.flicbutton.internal.discovery; -import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.NonNullByDefault; import org.openhab.core.config.discovery.DiscoveryService; import org.openhab.core.thing.ThingUID; @@ -22,7 +21,7 @@ /** * - * @author Patrick Fink + * @author Patrick Fink Initial contribution * */ @NonNullByDefault @@ -35,7 +34,7 @@ public interface FlicButtonDiscoveryService extends DiscoveryService { */ public ThingUID flicButtonDiscovered(Bdaddr bdaddr); - public void activate(@NonNull FlicClient client); + public void activate(FlicClient client); public void deactivate(); } diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/discovery/FlicSimpleclientDiscoveryServiceImpl.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/discovery/FlicSimpleclientDiscoveryServiceImpl.java index e0e6d3b25689b..f849a53373fc8 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/discovery/FlicSimpleclientDiscoveryServiceImpl.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/discovery/FlicSimpleclientDiscoveryServiceImpl.java @@ -15,8 +15,9 @@ import java.io.IOException; import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.flicbutton.internal.FlicButtonBindingConstants; -import org.openhab.binding.flicbutton.internal.FlicButtonHandlerFactory; import org.openhab.binding.flicbutton.internal.util.FlicButtonUtils; import org.openhab.core.config.discovery.AbstractDiscoveryService; import org.openhab.core.config.discovery.DiscoveryResult; @@ -44,13 +45,14 @@ * * @author Patrick Fink - Initial contribution */ +@NonNullByDefault public class FlicSimpleclientDiscoveryServiceImpl extends AbstractDiscoveryService implements FlicButtonDiscoveryService { private final Logger logger = LoggerFactory.getLogger(FlicSimpleclientDiscoveryServiceImpl.class); private boolean activated = false; private ThingUID bridgeUID; - private FlicClient flicClient; + private @Nullable FlicClient flicClient; public FlicSimpleclientDiscoveryServiceImpl(@NonNull ThingUID bridgeUID) { super(FlicButtonBindingConstants.SUPPORTED_THING_TYPES_UIDS, 2, true); @@ -89,13 +91,15 @@ protected void discoverVerifiedButtons() throws IOException { // Register FlicButtonEventListener to all already existing Flic buttons flicClient.getInfo(new GetInfoResponseCallback() { @Override - public void onGetInfoResponse(BluetoothControllerState bluetoothControllerState, Bdaddr myBdAddr, - BdAddrType myBdAddrType, int maxPendingConnections, int maxConcurrentlyConnectedButtons, - int currentPendingConnections, boolean currentlyNoSpaceForNewConnection, Bdaddr[] verifiedButtons) - throws IOException { - - for (final Bdaddr bdaddr : verifiedButtons) { - flicButtonDiscovered(bdaddr); + public void onGetInfoResponse(@Nullable BluetoothControllerState bluetoothControllerState, + @Nullable Bdaddr myBdAddr, @Nullable BdAddrType myBdAddrType, int maxPendingConnections, + int maxConcurrentlyConnectedButtons, int currentPendingConnections, + boolean currentlyNoSpaceForNewConnection, Bdaddr @Nullable [] verifiedButtons) throws IOException { + + for (final @Nullable Bdaddr bdaddr : verifiedButtons) { + if (bdaddr != null) { + flicButtonDiscovered((@NonNull Bdaddr) bdaddr); + } } } }); @@ -106,9 +110,11 @@ protected void startBackgroundDiscovery() { super.startBackgroundDiscovery(); flicClient.setGeneralCallbacks(new GeneralCallbacks() { @Override - public void onNewVerifiedButton(Bdaddr bdaddr) throws IOException { + public void onNewVerifiedButton(@Nullable Bdaddr bdaddr) throws IOException { logger.debug("A new Flic button was added by an external flicd client: {}", bdaddr); - flicButtonDiscovered(bdaddr); + if (bdaddr != null) { + flicButtonDiscovered((@NonNull Bdaddr) bdaddr); + } } }); } diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/ChildThingHandler.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/ChildThingHandler.java index d405fae830456..d0f5d1b391881 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/ChildThingHandler.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/ChildThingHandler.java @@ -16,6 +16,8 @@ import java.util.Collection; import java.util.Collections; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.openhab.core.thing.Thing; import org.openhab.core.thing.ThingStatus; import org.openhab.core.thing.ThingStatusDetail; @@ -27,11 +29,12 @@ * @author Patrick Fink - Initial contribution * @param The bridge type this child handler depends on */ +@NonNullByDefault public abstract class ChildThingHandler extends BaseThingHandler { private static final Collection defaultToleratedBridgeStatuses = Collections .singleton(ThingStatus.ONLINE); protected boolean bridgeValid = false; - protected BridgeHandlerType bridgeHandler; + protected @Nullable BridgeHandlerType bridgeHandler; public ChildThingHandler(Thing thing) { super(thing); diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonBatteryLevelListener.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonBatteryLevelListener.java index cd0c8529ad792..af18f0e6e4639 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonBatteryLevelListener.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonBatteryLevelListener.java @@ -14,26 +14,28 @@ import java.io.IOException; -import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import io.flic.fliclib.javaclient.BatteryStatusListener; import io.flic.fliclib.javaclient.Bdaddr; /** * - * @author Patrick Fink + * @author Patrick Fink Initial contribution * */ +@NonNullByDefault public class FlicButtonBatteryLevelListener extends BatteryStatusListener.Callbacks { private final FlicButtonHandler thingHandler; - FlicButtonBatteryLevelListener(@NonNull FlicButtonHandler thingHandler) { + FlicButtonBatteryLevelListener(FlicButtonHandler thingHandler) { this.thingHandler = thingHandler; } @Override - public void onBatteryStatus(Bdaddr bdaddr, int i, long l) throws IOException { + public void onBatteryStatus(@Nullable Bdaddr bdaddr, int i, long l) throws IOException { thingHandler.updateBatteryChannel(i); } } diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonEventListener.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonEventListener.java index b5f8c321b3e30..86caf5016e5d1 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonEventListener.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonEventListener.java @@ -24,7 +24,7 @@ /** * - * @author Patrick Fink + * @author Patrick Fink Initial contribution * */ public class FlicButtonEventListener extends ButtonConnectionChannel.Callbacks { diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonHandler.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonHandler.java index 05ab6927a5972..416825b29e55d 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonHandler.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonHandler.java @@ -19,6 +19,8 @@ import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.openhab.core.library.types.DecimalType; import org.openhab.core.thing.*; import org.openhab.core.types.Command; @@ -37,20 +39,23 @@ * * @author Patrick Fink - Initial contribution */ +@NonNullByDefault public class FlicButtonHandler extends ChildThingHandler { private Logger logger = LoggerFactory.getLogger(FlicButtonHandler.class); - private ScheduledFuture delayedDisconnectTask; - private DisconnectReason latestDisconnectReason; - private ButtonConnectionChannel eventConnection; - private Bdaddr bdaddr; + private @Nullable ScheduledFuture delayedDisconnectTask; + @Nullable + DisconnectReason latestDisconnectReason; + private @Nullable ButtonConnectionChannel eventConnection; + private @Nullable Bdaddr bdaddr; + @Nullable BatteryStatusListener batteryConnection; public FlicButtonHandler(Thing thing) { super(thing); } - public Bdaddr getBdaddr() { + public @Nullable Bdaddr getBdaddr() { return bdaddr; } @@ -156,7 +161,7 @@ protected void setOffline() { // Cleanup delayedDisconnect on status change to online @Override - protected void updateStatus(ThingStatus status, ThingStatusDetail statusDetail, String description) { + protected void updateStatus(ThingStatus status, ThingStatusDetail statusDetail, @Nullable String description) { if (status == ThingStatus.ONLINE) { cancelDelayedDisconnectTask(); } @@ -181,7 +186,7 @@ void flicButtonRemoved() { } void fireTriggerEvent(String event) { - String channelID = event == CommonTriggerEvents.PRESSED || event == CommonTriggerEvents.RELEASED + String channelID = event.equals(CommonTriggerEvents.PRESSED) || event.equals(CommonTriggerEvents.RELEASED) ? CHANNEL_ID_RAWBUTTON_EVENTS : CHANNEL_ID_BUTTON_EVENTS; updateStatus(ThingStatus.ONLINE); diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicDaemonBridgeConfiguration.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicDaemonBridgeConfiguration.java index 75fbf2ad525e9..7ae94e98c0a02 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicDaemonBridgeConfiguration.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicDaemonBridgeConfiguration.java @@ -15,23 +15,29 @@ import java.net.InetAddress; import java.net.UnknownHostException; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; + /** * * @author Patrick Fink - Initial contribution * */ +@NonNullByDefault public class FlicDaemonBridgeConfiguration { + @Nullable private String hostname; private int port; + @Nullable private InetAddress host; public void initAndValidate() throws UnknownHostException { host = InetAddress.getByName(hostname); } - public InetAddress getHost() { + public @Nullable InetAddress getHost() { return host; } diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicDaemonBridgeHandler.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicDaemonBridgeHandler.java index 8e064d325afef..501b1e8036aa0 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicDaemonBridgeHandler.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicDaemonBridgeHandler.java @@ -19,6 +19,9 @@ import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.flicbutton.internal.discovery.FlicButtonDiscoveryService; import org.openhab.core.thing.Bridge; import org.openhab.core.thing.ChannelUID; @@ -36,24 +39,25 @@ * * @author Patrick Fink - Initial contribution */ +@NonNullByDefault public class FlicDaemonBridgeHandler extends BaseBridgeHandler { private static final Logger logger = LoggerFactory.getLogger(FlicDaemonBridgeHandler.class); private static final long REINITIALIZE_DELAY_SECONDS = 10; // Config parameters - private FlicDaemonBridgeConfiguration cfg; + private @Nullable FlicDaemonBridgeConfiguration cfg; // Services private FlicButtonDiscoveryService buttonDiscoveryService; - private Future flicClientFuture; + private @Nullable Future flicClientFuture; // For disposal - private Collection> startedTasks = new ArrayList<>(2); - private FlicClient flicClient; + private Collection<@Nullable Future> startedTasks = new ArrayList<>(2); + private @Nullable FlicClient flicClient; public FlicDaemonBridgeHandler(Bridge bridge, FlicButtonDiscoveryService buttonDiscoveryService) { super(bridge); this.buttonDiscoveryService = buttonDiscoveryService; } - public FlicClient getFlicClient() { + public @Nullable FlicClient getFlicClient() { return flicClient; } @@ -80,7 +84,7 @@ private void initConfigParameters() throws UnknownHostException { } private void activateButtonDiscoveryService() { - buttonDiscoveryService.activate(flicClient); + buttonDiscoveryService.activate((@NonNull FlicClient) flicClient); } private void startFlicdClientAsync() throws IOException { From 6a3d7c933451a2ca881f1a83d42be07c0b7bec5b Mon Sep 17 00:00:00 2001 From: Patrick Fink Date: Mon, 14 Feb 2022 01:56:58 +0100 Subject: [PATCH 31/37] [flicbutton] Fix SAT warnings (2) Signed-off-by: Patrick Fink --- .../internal/FlicButtonHandlerFactory.java | 1 - .../discovery/FlicButtonDiscoveryService.java | 2 +- .../FlicSimpleclientDiscoveryServiceImpl.java | 6 +- .../internal/handler/ChildThingHandler.java | 4 +- .../FlicButtonBatteryLevelListener.java | 2 +- .../handler/FlicButtonEventListener.java | 61 +++++++++++-------- .../internal/handler/FlicButtonHandler.java | 9 ++- .../handler/FlicDaemonBridgeHandler.java | 8 ++- .../internal/util/FlicButtonUtils.java | 2 +- 9 files changed, 57 insertions(+), 38 deletions(-) diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/FlicButtonHandlerFactory.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/FlicButtonHandlerFactory.java index 5f5b7ac73e6b9..5e44ab7fcc0a0 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/FlicButtonHandlerFactory.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/FlicButtonHandlerFactory.java @@ -60,7 +60,6 @@ public boolean supportsThingType(ThingTypeUID thingTypeUID) { @Override @Nullable protected ThingHandler createHandler(Thing thing) { - ThingTypeUID thingTypeUID = thing.getThingTypeUID(); if (thingTypeUID.equals(FlicButtonBindingConstants.FLICBUTTON_THING_TYPE)) { diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/discovery/FlicButtonDiscoveryService.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/discovery/FlicButtonDiscoveryService.java index 313b0776d1b7a..11040e3dfd459 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/discovery/FlicButtonDiscoveryService.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/discovery/FlicButtonDiscoveryService.java @@ -21,7 +21,7 @@ /** * - * @author Patrick Fink Initial contribution + * @author Patrick Fink - Initial contribution * */ @NonNullByDefault diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/discovery/FlicSimpleclientDiscoveryServiceImpl.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/discovery/FlicSimpleclientDiscoveryServiceImpl.java index f849a53373fc8..3d25bd3dda4db 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/discovery/FlicSimpleclientDiscoveryServiceImpl.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/discovery/FlicSimpleclientDiscoveryServiceImpl.java @@ -54,13 +54,13 @@ public class FlicSimpleclientDiscoveryServiceImpl extends AbstractDiscoveryServi private ThingUID bridgeUID; private @Nullable FlicClient flicClient; - public FlicSimpleclientDiscoveryServiceImpl(@NonNull ThingUID bridgeUID) { + public FlicSimpleclientDiscoveryServiceImpl(ThingUID bridgeUID) { super(FlicButtonBindingConstants.SUPPORTED_THING_TYPES_UIDS, 2, true); this.bridgeUID = bridgeUID; } @Override - public void activate(@NonNull FlicClient flicClient) { + public void activate(FlicClient flicClient) { this.flicClient = flicClient; activated = true; super.activate(null); @@ -78,7 +78,6 @@ protected void startScan() { if (activated) { discoverVerifiedButtons(); } - } catch (IOException e) { logger.warn("Error occured during button discovery", e); if (this.scanListener != null) { @@ -95,7 +94,6 @@ public void onGetInfoResponse(@Nullable BluetoothControllerState bluetoothContro @Nullable Bdaddr myBdAddr, @Nullable BdAddrType myBdAddrType, int maxPendingConnections, int maxConcurrentlyConnectedButtons, int currentPendingConnections, boolean currentlyNoSpaceForNewConnection, Bdaddr @Nullable [] verifiedButtons) throws IOException { - for (final @Nullable Bdaddr bdaddr : verifiedButtons) { if (bdaddr != null) { flicButtonDiscovered((@NonNull Bdaddr) bdaddr); diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/ChildThingHandler.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/ChildThingHandler.java index d0f5d1b391881..4834ae894d07a 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/ChildThingHandler.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/ChildThingHandler.java @@ -31,7 +31,7 @@ */ @NonNullByDefault public abstract class ChildThingHandler extends BaseThingHandler { - private static final Collection defaultToleratedBridgeStatuses = Collections + private static final Collection DEFAULT_TOLERATED_BRIDGE_STATUSES = Collections .singleton(ThingStatus.ONLINE); protected boolean bridgeValid = false; protected @Nullable BridgeHandlerType bridgeHandler; @@ -58,7 +58,7 @@ protected void linkBridge() { } protected void setStatusBasedOnBridge() { - setStatusBasedOnBridge(defaultToleratedBridgeStatuses); + setStatusBasedOnBridge(DEFAULT_TOLERATED_BRIDGE_STATUSES); } @Override diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonBatteryLevelListener.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonBatteryLevelListener.java index af18f0e6e4639..3e27214ff9d92 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonBatteryLevelListener.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonBatteryLevelListener.java @@ -22,7 +22,7 @@ /** * - * @author Patrick Fink Initial contribution + * @author Patrick Fink - Initial contribution * */ @NonNullByDefault diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonEventListener.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonEventListener.java index 86caf5016e5d1..554a2a2170a17 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonEventListener.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonEventListener.java @@ -15,69 +15,82 @@ import java.io.IOException; import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.flicbutton.internal.util.FlicButtonUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import io.flic.fliclib.javaclient.ButtonConnectionChannel; -import io.flic.fliclib.javaclient.enums.*; +import io.flic.fliclib.javaclient.enums.ClickType; +import io.flic.fliclib.javaclient.enums.ConnectionStatus; +import io.flic.fliclib.javaclient.enums.CreateConnectionChannelError; +import io.flic.fliclib.javaclient.enums.DisconnectReason; +import io.flic.fliclib.javaclient.enums.RemovedReason; /** * - * @author Patrick Fink Initial contribution + * @author Patrick Fink - Initial contribution * */ +@NonNullByDefault public class FlicButtonEventListener extends ButtonConnectionChannel.Callbacks { private final Logger logger = LoggerFactory.getLogger(FlicButtonEventListener.class); private final FlicButtonHandler thingHandler; - FlicButtonEventListener(@NonNull FlicButtonHandler thingHandler) { + FlicButtonEventListener(FlicButtonHandler thingHandler) { this.thingHandler = thingHandler; } @Override - public synchronized void onCreateConnectionChannelResponse(ButtonConnectionChannel channel, - CreateConnectionChannelError createConnectionChannelError, ConnectionStatus connectionStatus) { + public synchronized void onCreateConnectionChannelResponse(@Nullable ButtonConnectionChannel channel, + @Nullable CreateConnectionChannelError createConnectionChannelError, + @Nullable ConnectionStatus connectionStatus) { logger.debug("Create response {}: {}, {}", channel.getBdaddr(), createConnectionChannelError, connectionStatus); // Handling does not differ from Status change, so redirect - thingHandler.initializeStatus(connectionStatus); - notify(); + if (connectionStatus != null) { + thingHandler.initializeStatus((@NonNull ConnectionStatus) connectionStatus); + notify(); + } } @Override - public void onRemoved(ButtonConnectionChannel channel, RemovedReason removedReason) { + public void onRemoved(@Nullable ButtonConnectionChannel channel, @Nullable RemovedReason removedReason) { thingHandler.flicButtonRemoved(); logger.debug("Button {} removed. ThingStatus updated to OFFLINE. Reason: {}", channel.getBdaddr(), removedReason); } @Override - public void onConnectionStatusChanged(ButtonConnectionChannel channel, ConnectionStatus connectionStatus, - DisconnectReason disconnectReason) { + public void onConnectionStatusChanged(@Nullable ButtonConnectionChannel channel, + @Nullable ConnectionStatus connectionStatus, @Nullable DisconnectReason disconnectReason) { logger.trace("New status for {}: {}", channel.getBdaddr(), connectionStatus + (connectionStatus == ConnectionStatus.Disconnected ? ", " + disconnectReason : "")); - - thingHandler.connectionStatusChanged(connectionStatus, disconnectReason); + if (connectionStatus != null) { + thingHandler.connectionStatusChanged((@NonNull ConnectionStatus) connectionStatus, disconnectReason); + } } @Override - public void onButtonUpOrDown(ButtonConnectionChannel channel, ClickType clickType, boolean wasQueued, int timeDiff) - throws IOException { - - logger.trace("{} {}", channel.getBdaddr(), clickType.name()); - - String commonTriggerEvent = FlicButtonUtils.flicOpenhabTriggerEventMap.get(clickType.name()); - - if (commonTriggerEvent != null) { - thingHandler.fireTriggerEvent(commonTriggerEvent); + public void onButtonUpOrDown(@Nullable ButtonConnectionChannel channel, @Nullable ClickType clickType, + boolean wasQueued, int timeDiff) throws IOException { + if (channel != null && clickType != null) { + logger.trace("{} {}", channel.getBdaddr(), clickType.name()); + String commonTriggerEvent = FlicButtonUtils.FLIC_OPENHAB_TRIGGER_EVENT_MAP.get(clickType.name()); + if (commonTriggerEvent != null) { + thingHandler.fireTriggerEvent(commonTriggerEvent); + } } } @Override - public void onButtonSingleOrDoubleClickOrHold(ButtonConnectionChannel channel, ClickType clickType, - boolean wasQueued, int timeDiff) throws IOException { + public void onButtonSingleOrDoubleClickOrHold(@Nullable ButtonConnectionChannel channel, + @Nullable ClickType clickType, boolean wasQueued, int timeDiff) throws IOException { // Handling does not differ from up/down events, so redirect - onButtonUpOrDown(channel, clickType, wasQueued, timeDiff); + if (channel != null && clickType != null) { + onButtonUpOrDown((@NonNull ButtonConnectionChannel) channel, (@NonNull ClickType) clickType, wasQueued, + timeDiff); + } } } diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonHandler.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonHandler.java index 416825b29e55d..b96a0c5b250c0 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonHandler.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonHandler.java @@ -22,7 +22,12 @@ import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.openhab.core.library.types.DecimalType; -import org.openhab.core.thing.*; +import org.openhab.core.thing.ChannelUID; +import org.openhab.core.thing.CommonTriggerEvents; +import org.openhab.core.thing.Thing; +import org.openhab.core.thing.ThingStatus; +import org.openhab.core.thing.ThingStatusDetail; +import org.openhab.core.thing.ThingStatusInfo; import org.openhab.core.types.Command; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -132,7 +137,7 @@ void initializeStatus(ConnectionStatus connectionStatus) { } } - void connectionStatusChanged(ConnectionStatus connectionStatus, DisconnectReason disconnectReason) { + void connectionStatusChanged(ConnectionStatus connectionStatus, @Nullable DisconnectReason disconnectReason) { latestDisconnectReason = disconnectReason; if (connectionStatus == ConnectionStatus.Disconnected) { // Status change to offline have to be scheduled to improve stability, diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicDaemonBridgeHandler.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicDaemonBridgeHandler.java index 501b1e8036aa0..14b57ae5187be 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicDaemonBridgeHandler.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicDaemonBridgeHandler.java @@ -41,7 +41,7 @@ */ @NonNullByDefault public class FlicDaemonBridgeHandler extends BaseBridgeHandler { - private static final Logger logger = LoggerFactory.getLogger(FlicDaemonBridgeHandler.class); + private final Logger logger = LoggerFactory.getLogger(FlicDaemonBridgeHandler.class); private static final long REINITIALIZE_DELAY_SECONDS = 10; // Config parameters private @Nullable FlicDaemonBridgeConfiguration cfg; @@ -84,7 +84,11 @@ private void initConfigParameters() throws UnknownHostException { } private void activateButtonDiscoveryService() { - buttonDiscoveryService.activate((@NonNull FlicClient) flicClient); + if (flicClient != null) { + buttonDiscoveryService.activate((@NonNull FlicClient) flicClient); + } else { + throw new IllegalStateException("flicClient not properly initialized"); + } } private void startFlicdClientAsync() throws IOException { diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/util/FlicButtonUtils.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/util/FlicButtonUtils.java index c10f654b8790f..a5c219f580985 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/util/FlicButtonUtils.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/util/FlicButtonUtils.java @@ -30,7 +30,7 @@ */ @NonNullByDefault public class FlicButtonUtils { - public static final Map flicOpenhabTriggerEventMap = Collections + public static final Map FLIC_OPENHAB_TRIGGER_EVENT_MAP = Collections .unmodifiableMap(new HashMap() { { put("ButtonSingleClick", CommonTriggerEvents.SHORT_PRESSED); From df55fb1531ef2bfd411f5cee7895f6c98a9e224e Mon Sep 17 00:00:00 2001 From: Patrick Fink Date: Mon, 14 Feb 2022 22:12:59 +0100 Subject: [PATCH 32/37] [flicbutton] Concurrency refactoring & fixes Signed-off-by: Patrick Fink --- .../flic/fliclib/javaclient/FlicClient.java | 2 +- .../handler/FlicButtonEventListener.java | 8 ++- .../internal/handler/FlicButtonHandler.java | 61 +++++++++++-------- .../FlicDaemonBridgeConfiguration.java | 11 +--- .../handler/FlicDaemonBridgeHandler.java | 34 +++++------ 5 files changed, 63 insertions(+), 53 deletions(-) diff --git a/bundles/org.openhab.binding.flicbutton/src/3rdparty/java/io/flic/fliclib/javaclient/FlicClient.java b/bundles/org.openhab.binding.flicbutton/src/3rdparty/java/io/flic/fliclib/javaclient/FlicClient.java index ca12329170e31..07f0544bbf4e0 100644 --- a/bundles/org.openhab.binding.flicbutton/src/3rdparty/java/io/flic/fliclib/javaclient/FlicClient.java +++ b/bundles/org.openhab.binding.flicbutton/src/3rdparty/java/io/flic/fliclib/javaclient/FlicClient.java @@ -404,7 +404,7 @@ public void runOnHandleEventsThread(TimerTask task) throws IOException { */ public void handleEvents() throws IOException { handleEventsThread = Thread.currentThread(); - while (true) { + while (!Thread.currentThread().isInterrupted()) { Map.Entry firstTimer = timers.firstEntry(); long timeout = 0; if (firstTimer != null) { diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonEventListener.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonEventListener.java index 554a2a2170a17..8a61edaea6e16 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonEventListener.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonEventListener.java @@ -13,6 +13,7 @@ package org.openhab.binding.flicbutton.internal.handler; import java.io.IOException; +import java.util.concurrent.Semaphore; import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.NonNullByDefault; @@ -38,11 +39,16 @@ public class FlicButtonEventListener extends ButtonConnectionChannel.Callbacks { private final Logger logger = LoggerFactory.getLogger(FlicButtonEventListener.class); private final FlicButtonHandler thingHandler; + private final Semaphore channelResponseSemaphore = new Semaphore(0); FlicButtonEventListener(FlicButtonHandler thingHandler) { this.thingHandler = thingHandler; } + public Semaphore getChannelResponseSemaphore() { + return channelResponseSemaphore; + } + @Override public synchronized void onCreateConnectionChannelResponse(@Nullable ButtonConnectionChannel channel, @Nullable CreateConnectionChannelError createConnectionChannelError, @@ -51,7 +57,7 @@ public synchronized void onCreateConnectionChannelResponse(@Nullable ButtonConne // Handling does not differ from Status change, so redirect if (connectionStatus != null) { thingHandler.initializeStatus((@NonNull ConnectionStatus) connectionStatus); - notify(); + channelResponseSemaphore.release(); } } diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonHandler.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonHandler.java index b96a0c5b250c0..d388b3f03974b 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonHandler.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonHandler.java @@ -16,6 +16,7 @@ import java.io.IOException; import java.util.Objects; +import java.util.concurrent.Future; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; @@ -49,12 +50,11 @@ public class FlicButtonHandler extends ChildThingHandler delayedDisconnectTask; - @Nullable - DisconnectReason latestDisconnectReason; + private @Nullable Future initializationTask; + private @Nullable DisconnectReason latestDisconnectReason; private @Nullable ButtonConnectionChannel eventConnection; private @Nullable Bdaddr bdaddr; - @Nullable - BatteryStatusListener batteryConnection; + private @Nullable BatteryStatusListener batteryConnection; public FlicButtonHandler(Thing thing) { super(thing); @@ -74,7 +74,7 @@ public void initialize() { super.initialize(); bdaddr = new Bdaddr((String) this.getThing().getConfiguration().get(CONFIG_ADDRESS)); if (bridgeValid) { - initializeThing(); + initializationTask = scheduler.submit(this::initializeThing); } } @@ -82,28 +82,19 @@ public void initialize() { public void bridgeStatusChanged(ThingStatusInfo bridgeStatusInfo) { super.bridgeStatusChanged(bridgeStatusInfo); if (getThing().getStatusInfo().getStatusDetail() == ThingStatusDetail.BRIDGE_OFFLINE && bridgeValid) { - initializeThing(); + dispose(); + initializationTask = scheduler.submit(this::initializeThing); } } - public void initializeThing() { + private void initializeThing() { try { - FlicButtonBatteryLevelListener batteryListener = new FlicButtonBatteryLevelListener(this); - BatteryStatusListener batteryConnection = new BatteryStatusListener(getBdaddr(), batteryListener); - bridgeHandler.getFlicClient().addBatteryStatusListener(batteryConnection); - this.batteryConnection = batteryConnection; - - FlicButtonEventListener eventListener = new FlicButtonEventListener(this); - synchronized (eventListener) { - ButtonConnectionChannel eventConnection = new ButtonConnectionChannel(getBdaddr(), eventListener); - bridgeHandler.getFlicClient().addConnectionChannel(eventConnection); - this.eventConnection = eventConnection; - eventListener.wait(5000); - // Listener calls initializeStatus() before notifying so that ThingStatus is should be set at this point - if (this.getThing().getStatus().equals(ThingStatus.INITIALIZING)) { - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, - "Got no response by eventListener"); - } + initializeBatteryListener(); + initializeEventListener(); + // EventListener calls initializeStatus() before releasing so that ThingStatus should be set at this point + if (this.getThing().getStatus().equals(ThingStatus.INITIALIZING)) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, + "Got no response by eventListener"); } } catch (IOException | InterruptedException e) { updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, @@ -111,10 +102,25 @@ public void initializeThing() { } } + private void initializeBatteryListener() throws IOException { + FlicButtonBatteryLevelListener batteryListener = new FlicButtonBatteryLevelListener(this); + BatteryStatusListener batteryConnection = new BatteryStatusListener(getBdaddr(), batteryListener); + bridgeHandler.getFlicClient().addBatteryStatusListener(batteryConnection); + this.batteryConnection = batteryConnection; + } + + public void initializeEventListener() throws IOException, InterruptedException { + FlicButtonEventListener eventListener = new FlicButtonEventListener(this); + ButtonConnectionChannel eventConnection = new ButtonConnectionChannel(getBdaddr(), eventListener); + bridgeHandler.getFlicClient().addConnectionChannel(eventConnection); + this.eventConnection = eventConnection; + eventListener.getChannelResponseSemaphore().tryAcquire(5, TimeUnit.SECONDS); + } + @Override public void dispose() { cancelDelayedDisconnectTask(); - + cancelInitializationTask(); try { if (eventConnection != null) { bridgeHandler.getFlicClient().removeConnectionChannel(eventConnection); @@ -173,6 +179,13 @@ protected void updateStatus(ThingStatus status, ThingStatusDetail statusDetail, super.updateStatus(status, statusDetail, description); } + private void cancelInitializationTask() { + if (initializationTask != null) { + initializationTask.cancel(false); + initializationTask = null; + } + } + private void cancelDelayedDisconnectTask() { if (delayedDisconnectTask != null) { delayedDisconnectTask.cancel(false); diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicDaemonBridgeConfiguration.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicDaemonBridgeConfiguration.java index 7ae94e98c0a02..441ce21a31ffe 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicDaemonBridgeConfiguration.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicDaemonBridgeConfiguration.java @@ -30,15 +30,8 @@ public class FlicDaemonBridgeConfiguration { private String hostname; private int port; - @Nullable - private InetAddress host; - - public void initAndValidate() throws UnknownHostException { - host = InetAddress.getByName(hostname); - } - - public @Nullable InetAddress getHost() { - return host; + public @Nullable InetAddress getHost() throws UnknownHostException { + return InetAddress.getByName(hostname); } public int getPort() { diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicDaemonBridgeHandler.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicDaemonBridgeHandler.java index 14b57ae5187be..cba4319de0e45 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicDaemonBridgeHandler.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicDaemonBridgeHandler.java @@ -49,7 +49,7 @@ public class FlicDaemonBridgeHandler extends BaseBridgeHandler { private FlicButtonDiscoveryService buttonDiscoveryService; private @Nullable Future flicClientFuture; // For disposal - private Collection<@Nullable Future> startedTasks = new ArrayList<>(2); + private Collection<@Nullable Future> startedTasks = new ArrayList<>(3); private @Nullable FlicClient flicClient; public FlicDaemonBridgeHandler(Bridge bridge, FlicButtonDiscoveryService buttonDiscoveryService) { @@ -63,6 +63,10 @@ public FlicDaemonBridgeHandler(Bridge bridge, FlicButtonDiscoveryService buttonD @Override public void initialize() { + startedTasks.add(scheduler.submit(this::initializeThing)); + } + + public void initializeThing() { try { initConfigParameters(); startFlicdClientAsync(); @@ -78,9 +82,8 @@ public void initialize() { } } - private void initConfigParameters() throws UnknownHostException { + private void initConfigParameters() { cfg = getConfigAs(FlicDaemonBridgeConfiguration.class); - cfg.initAndValidate(); } private void activateButtonDiscoveryService() { @@ -96,16 +99,21 @@ private void startFlicdClientAsync() throws IOException { Runnable flicClientService = () -> { try { flicClient.handleEvents(); - logger.warn("Listening to flicd unexpectedly ended"); + flicClient.close(); + logger.debug("Listening to flicd ended"); } catch (IOException e) { logger.debug("Error occured while listening to flicd", e); } finally { - onClientFailure(); + if (Thread.currentThread().isInterrupted()) { + onClientFailure(); + } } }; - flicClientFuture = scheduler.submit(flicClientService); - startedTasks.add(flicClientFuture); + if (!Thread.currentThread().isInterrupted()) { + flicClientFuture = scheduler.submit(flicClientService); + startedTasks.add(flicClientFuture); + } } private void onClientFailure() { @@ -127,19 +135,9 @@ private void initThingStatus() { @Override public void dispose() { super.dispose(); - for (Future startedTask : startedTasks) { - startedTask.cancel(true); - } + startedTasks.forEach(task -> task.cancel(true)); startedTasks = new ArrayList<>(2); buttonDiscoveryService.deactivate(); - if (flicClient != null) { - try { - flicClient.close(); - flicClient = null; - } catch (IOException e) { - logger.debug("Error closing connection to flicd: {}", e.getMessage()); - } - } } private void scheduleReinitialize() { From b9a0574ef4f0c293e510bc2be2592d68ee9488b3 Mon Sep 17 00:00:00 2001 From: Patrick Fink Date: Mon, 14 Feb 2022 22:49:09 +0100 Subject: [PATCH 33/37] [flicbutton] Cancel initialization task also when already running Signed-off-by: Patrick Fink --- .../binding/flicbutton/internal/handler/FlicButtonHandler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonHandler.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonHandler.java index d388b3f03974b..bc5b2d54243fb 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonHandler.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonHandler.java @@ -181,7 +181,7 @@ protected void updateStatus(ThingStatus status, ThingStatusDetail statusDetail, private void cancelInitializationTask() { if (initializationTask != null) { - initializationTask.cancel(false); + initializationTask.cancel(true); initializationTask = null; } } From 43c42629f6fd4babe3adeedce002e8746869d309 Mon Sep 17 00:00:00 2001 From: Patrick Fink Date: Sun, 20 Feb 2022 21:26:05 +0100 Subject: [PATCH 34/37] [flicbutton] Add javadoc and move FLIC_OPENHAB_EVENT_TRIGGER_MAP constant to constants class Signed-off-by: Patrick Fink --- .../internal/FlicButtonBindingConstants.java | 16 +++++++++++++++- .../discovery/FlicButtonDiscoveryService.java | 1 + .../FlicSimpleclientDiscoveryServiceImpl.java | 1 - .../internal/handler/ChildThingHandler.java | 3 +++ .../handler/FlicButtonBatteryLevelListener.java | 2 ++ .../handler/FlicButtonEventListener.java | 6 ++++-- .../internal/handler/FlicButtonHandler.java | 4 ++-- .../handler/FlicDaemonBridgeConfiguration.java | 1 + .../internal/util/FlicButtonUtils.java | 17 +---------------- .../main/resources/OH-INF/thing/thing-types.xml | 6 +++--- 10 files changed, 32 insertions(+), 25 deletions(-) diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/FlicButtonBindingConstants.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/FlicButtonBindingConstants.java index fdafbd2b13c3f..0aa1773aff3b8 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/FlicButtonBindingConstants.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/FlicButtonBindingConstants.java @@ -13,13 +13,16 @@ package org.openhab.binding.flicbutton.internal; import java.util.Collections; +import java.util.HashMap; +import java.util.Map; import java.util.Set; import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.core.thing.CommonTriggerEvents; import org.openhab.core.thing.ThingTypeUID; /** - * The {@link FlicButtonBinding} class defines common constants, which are + * The {@link FlicButtonBindingConstants} class defines common constants, which are * used across the whole binding. * * @author Patrick Fink - Initial contribution @@ -48,4 +51,15 @@ public class FlicButtonBindingConstants { // Other stuff public static final int BUTTON_OFFLINE_GRACE_PERIOD_SECONDS = 60; + + public static final Map FLIC_OPENHAB_TRIGGER_EVENT_MAP = Collections + .unmodifiableMap(new HashMap() { + { + put("ButtonSingleClick", CommonTriggerEvents.SHORT_PRESSED); + put("ButtonDoubleClick", CommonTriggerEvents.DOUBLE_PRESSED); + put("ButtonHold", CommonTriggerEvents.LONG_PRESSED); + put("ButtonDown", CommonTriggerEvents.PRESSED); + put("ButtonUp", CommonTriggerEvents.RELEASED); + } + }); } diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/discovery/FlicButtonDiscoveryService.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/discovery/FlicButtonDiscoveryService.java index 11040e3dfd459..917beb9570843 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/discovery/FlicButtonDiscoveryService.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/discovery/FlicButtonDiscoveryService.java @@ -20,6 +20,7 @@ import io.flic.fliclib.javaclient.FlicClient; /** + * A {@link DiscoveryService} for Flic buttons. * * @author Patrick Fink - Initial contribution * diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/discovery/FlicSimpleclientDiscoveryServiceImpl.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/discovery/FlicSimpleclientDiscoveryServiceImpl.java index 3d25bd3dda4db..fedab907a1260 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/discovery/FlicSimpleclientDiscoveryServiceImpl.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/discovery/FlicSimpleclientDiscoveryServiceImpl.java @@ -87,7 +87,6 @@ protected void startScan() { } protected void discoverVerifiedButtons() throws IOException { - // Register FlicButtonEventListener to all already existing Flic buttons flicClient.getInfo(new GetInfoResponseCallback() { @Override public void onGetInfoResponse(@Nullable BluetoothControllerState bluetoothControllerState, diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/ChildThingHandler.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/ChildThingHandler.java index 4834ae894d07a..58793d295d0d3 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/ChildThingHandler.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/ChildThingHandler.java @@ -26,6 +26,9 @@ import org.openhab.core.thing.binding.BridgeHandler; /** + * The {@link ChildThingHandler} class is an abstract class for handlers that are dependent from a parent + * {@link BridgeHandler}. + * * @author Patrick Fink - Initial contribution * @param The bridge type this child handler depends on */ diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonBatteryLevelListener.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonBatteryLevelListener.java index 3e27214ff9d92..43bdda8dd6817 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonBatteryLevelListener.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonBatteryLevelListener.java @@ -21,6 +21,8 @@ import io.flic.fliclib.javaclient.Bdaddr; /** + * Each {@link FlicButtonBatteryLevelListener} object listens to the battery status of a specific Flic button + * and calls updates the {@link FlicButtonHandler} accordingly. * * @author Patrick Fink - Initial contribution * diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonEventListener.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonEventListener.java index 8a61edaea6e16..77c2d0780ae53 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonEventListener.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonEventListener.java @@ -18,7 +18,7 @@ import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; -import org.openhab.binding.flicbutton.internal.util.FlicButtonUtils; +import org.openhab.binding.flicbutton.internal.FlicButtonBindingConstants; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -30,6 +30,8 @@ import io.flic.fliclib.javaclient.enums.RemovedReason; /** + * Each {@link FlicButtonEventListener} object listens to events of a specific Flic button and calls the + * associated {@link FlicButtonHandler} back accordingly. * * @author Patrick Fink - Initial contribution * @@ -83,7 +85,7 @@ public void onButtonUpOrDown(@Nullable ButtonConnectionChannel channel, @Nullabl boolean wasQueued, int timeDiff) throws IOException { if (channel != null && clickType != null) { logger.trace("{} {}", channel.getBdaddr(), clickType.name()); - String commonTriggerEvent = FlicButtonUtils.FLIC_OPENHAB_TRIGGER_EVENT_MAP.get(clickType.name()); + String commonTriggerEvent = FlicButtonBindingConstants.FLIC_OPENHAB_TRIGGER_EVENT_MAP.get(clickType.name()); if (commonTriggerEvent != null) { thingHandler.fireTriggerEvent(commonTriggerEvent); } diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonHandler.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonHandler.java index bc5b2d54243fb..70bf51e23cd8c 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonHandler.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonHandler.java @@ -40,8 +40,8 @@ import io.flic.fliclib.javaclient.enums.DisconnectReason; /** - * The {@link FlicButtonHandler} is responsible for handling commands, which are - * sent to one of the channels. + * The {@link FlicButtonHandler} is responsible for initializing the online status of Flic Buttons + * and trigger channel events when they're used. * * @author Patrick Fink - Initial contribution */ diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicDaemonBridgeConfiguration.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicDaemonBridgeConfiguration.java index 441ce21a31ffe..1f176b2bac5a8 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicDaemonBridgeConfiguration.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicDaemonBridgeConfiguration.java @@ -19,6 +19,7 @@ import org.eclipse.jdt.annotation.Nullable; /** + * The configuration of a flicd bridge handled by {@link FlicDaemonBridgeHandler}. * * @author Patrick Fink - Initial contribution * diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/util/FlicButtonUtils.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/util/FlicButtonUtils.java index a5c219f580985..3f59ce45b4615 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/util/FlicButtonUtils.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/util/FlicButtonUtils.java @@ -12,35 +12,20 @@ */ package org.openhab.binding.flicbutton.internal.util; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - import org.eclipse.jdt.annotation.NonNullByDefault; import org.openhab.binding.flicbutton.internal.FlicButtonBindingConstants; -import org.openhab.core.thing.CommonTriggerEvents; import org.openhab.core.thing.ThingUID; import io.flic.fliclib.javaclient.Bdaddr; /** + * The {@link FlicButtonUtils} class defines static utility methods that are used within the binding. * * @author Patrick Fink - Initial contribution * */ @NonNullByDefault public class FlicButtonUtils { - public static final Map FLIC_OPENHAB_TRIGGER_EVENT_MAP = Collections - .unmodifiableMap(new HashMap() { - { - put("ButtonSingleClick", CommonTriggerEvents.SHORT_PRESSED); - put("ButtonDoubleClick", CommonTriggerEvents.DOUBLE_PRESSED); - put("ButtonHold", CommonTriggerEvents.LONG_PRESSED); - put("ButtonDown", CommonTriggerEvents.PRESSED); - put("ButtonUp", CommonTriggerEvents.RELEASED); - } - }); - public static ThingUID getThingUIDFromBdAddr(Bdaddr bdaddr, ThingUID bridgeUID) { String thingID = bdaddr.toString().replace(":", "-"); return new ThingUID(FlicButtonBindingConstants.FLICBUTTON_THING_TYPE, bridgeUID, thingID); diff --git a/bundles/org.openhab.binding.flicbutton/src/main/resources/OH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.flicbutton/src/main/resources/OH-INF/thing/thing-types.xml index 25d3784d67bbe..f7a679f28450d 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/resources/OH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.flicbutton/src/main/resources/OH-INF/thing/thing-types.xml @@ -11,12 +11,12 @@ network-address - + IP or Host name of the Flic daemon (flicd). localhost - - + + Port where flicd is running. Defaults to 5551. 5551 From d2fd2cfd0b432ec241056fc5bda8bcf2478a157d Mon Sep 17 00:00:00 2001 From: Patrick Fink Date: Sun, 20 Feb 2022 21:29:23 +0100 Subject: [PATCH 35/37] [flicbutton] Use ThingStatusDetail.OFFLINE.GONE when Flic button was removed from bridge Signed-off-by: Patrick Fink --- .../binding/flicbutton/internal/handler/FlicButtonHandler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonHandler.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonHandler.java index 70bf51e23cd8c..ffda46abbb5cb 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonHandler.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/handler/FlicButtonHandler.java @@ -199,7 +199,7 @@ void updateBatteryChannel(int percent) { } void flicButtonRemoved() { - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.NONE, + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.GONE, "Button was removed/detached from flicd (e.g. by simpleclient)."); } From c39a7a616a420ad56d30e2820656796bb6f2c738 Mon Sep 17 00:00:00 2001 From: Patrick Fink Date: Sun, 20 Feb 2022 21:35:39 +0100 Subject: [PATCH 36/37] [flicbutton] Fix FlicSimpleclientDiscoveryServiceImpl javadoc Signed-off-by: Patrick Fink --- .../discovery/FlicSimpleclientDiscoveryServiceImpl.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/discovery/FlicSimpleclientDiscoveryServiceImpl.java b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/discovery/FlicSimpleclientDiscoveryServiceImpl.java index fedab907a1260..3caa071093be2 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/discovery/FlicSimpleclientDiscoveryServiceImpl.java +++ b/bundles/org.openhab.binding.flicbutton/src/main/java/org/openhab/binding/flicbutton/internal/discovery/FlicSimpleclientDiscoveryServiceImpl.java @@ -35,8 +35,7 @@ /** * For each configured flicd service, there is a {@link FlicSimpleclientDiscoveryServiceImpl} which will be initialized - * by - * {@link FlicButtonHandlerFactory}. + * by {@link org.openhab.binding.flicbutton.internal.FlicButtonHandlerFactory}. * * It can scan for Flic Buttons already that are already added to fliclib-linux-hci ("verified" buttons), * * but it does not support adding and verify new buttons on it's own. From b6e1e7bd1ef659495eb59964e2885e9eec066332 Mon Sep 17 00:00:00 2001 From: Patrick Fink Date: Sun, 20 Feb 2022 21:37:09 +0100 Subject: [PATCH 37/37] [flicbutton] Fix required definition of thing types Signed-off-by: Patrick Fink --- .../src/main/resources/OH-INF/thing/thing-types.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bundles/org.openhab.binding.flicbutton/src/main/resources/OH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.flicbutton/src/main/resources/OH-INF/thing/thing-types.xml index f7a679f28450d..e5c79c2ce9008 100644 --- a/bundles/org.openhab.binding.flicbutton/src/main/resources/OH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.flicbutton/src/main/resources/OH-INF/thing/thing-types.xml @@ -9,7 +9,7 @@ This bridge represents a running instance of the fliclib-linux-hci server (flicd). - + network-address IP or Host name of the Flic daemon (flicd). @@ -35,7 +35,7 @@ - + Bluetooth address in XX:XX:XX:XX:XX:XX format